Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Mon, 29 Aug 2011 18:52:20 +0000 (14:52 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 29 Aug 2011 18:52:20 +0000 (14:52 -0400)
3322 files changed:
CREDITS
Documentation/ABI/testing/pstore
Documentation/ABI/testing/sysfs-class-net-mesh
Documentation/ABI/testing/sysfs-platform-ideapad-laptop
Documentation/CodingStyle
Documentation/DocBook/.gitignore
Documentation/DocBook/Makefile
Documentation/DocBook/dvb/dvbproperty.xml [deleted file]
Documentation/DocBook/dvb/dvbstb.png [deleted file]
Documentation/DocBook/dvb/frontend.h.xml [deleted file]
Documentation/DocBook/media-entities.tmpl [deleted file]
Documentation/DocBook/media-indices.tmpl [deleted file]
Documentation/DocBook/media/Makefile [new file with mode: 0644]
Documentation/DocBook/media/bayer.png.b64 [new file with mode: 0644]
Documentation/DocBook/media/crop.gif.b64 [new file with mode: 0644]
Documentation/DocBook/media/dvb/.gitignore [moved from Documentation/DocBook/dvb/.gitignore with 100% similarity]
Documentation/DocBook/media/dvb/audio.xml [moved from Documentation/DocBook/dvb/audio.xml with 79% similarity]
Documentation/DocBook/media/dvb/ca.xml [moved from Documentation/DocBook/dvb/ca.xml with 67% similarity]
Documentation/DocBook/media/dvb/demux.xml [moved from Documentation/DocBook/dvb/demux.xml with 84% similarity]
Documentation/DocBook/media/dvb/dvbapi.xml [moved from Documentation/DocBook/dvb/dvbapi.xml with 85% similarity]
Documentation/DocBook/media/dvb/dvbproperty.xml [new file with mode: 0644]
Documentation/DocBook/media/dvb/dvbstb.pdf [moved from Documentation/DocBook/dvb/dvbstb.pdf with 100% similarity]
Documentation/DocBook/media/dvb/examples.xml [moved from Documentation/DocBook/dvb/examples.xml with 100% similarity]
Documentation/DocBook/media/dvb/frontend.xml [moved from Documentation/DocBook/dvb/frontend.xml with 75% similarity]
Documentation/DocBook/media/dvb/intro.xml [moved from Documentation/DocBook/dvb/intro.xml with 92% similarity]
Documentation/DocBook/media/dvb/kdapi.xml [moved from Documentation/DocBook/dvb/kdapi.xml with 100% similarity]
Documentation/DocBook/media/dvb/net.xml [moved from Documentation/DocBook/dvb/net.xml with 57% similarity]
Documentation/DocBook/media/dvb/video.xml [moved from Documentation/DocBook/dvb/video.xml with 81% similarity]
Documentation/DocBook/media/dvbstb.png.b64 [new file with mode: 0644]
Documentation/DocBook/media/fieldseq_bt.gif.b64 [new file with mode: 0644]
Documentation/DocBook/media/fieldseq_tb.gif.b64 [new file with mode: 0644]
Documentation/DocBook/media/nv12mt.gif.b64 [new file with mode: 0644]
Documentation/DocBook/media/nv12mt_example.gif.b64 [new file with mode: 0644]
Documentation/DocBook/media/pipeline.png.b64 [new file with mode: 0644]
Documentation/DocBook/media/v4l/.gitignore [moved from Documentation/DocBook/v4l/.gitignore with 100% similarity]
Documentation/DocBook/media/v4l/biblio.xml [moved from Documentation/DocBook/v4l/biblio.xml with 100% similarity]
Documentation/DocBook/media/v4l/capture.c.xml [moved from Documentation/DocBook/v4l/capture.c.xml with 100% similarity]
Documentation/DocBook/media/v4l/common.xml [moved from Documentation/DocBook/v4l/common.xml with 99% similarity]
Documentation/DocBook/media/v4l/compat.xml [moved from Documentation/DocBook/v4l/compat.xml with 99% similarity]
Documentation/DocBook/media/v4l/controls.xml [moved from Documentation/DocBook/v4l/controls.xml with 62% similarity]
Documentation/DocBook/media/v4l/crop.pdf [moved from Documentation/DocBook/v4l/crop.pdf with 100% similarity]
Documentation/DocBook/media/v4l/dev-capture.xml [moved from Documentation/DocBook/v4l/dev-capture.xml with 100% similarity]
Documentation/DocBook/media/v4l/dev-codec.xml [moved from Documentation/DocBook/v4l/dev-codec.xml with 100% similarity]
Documentation/DocBook/media/v4l/dev-effect.xml [moved from Documentation/DocBook/v4l/dev-effect.xml with 100% similarity]
Documentation/DocBook/media/v4l/dev-event.xml [new file with mode: 0644]
Documentation/DocBook/media/v4l/dev-osd.xml [moved from Documentation/DocBook/v4l/dev-osd.xml with 100% similarity]
Documentation/DocBook/media/v4l/dev-output.xml [moved from Documentation/DocBook/v4l/dev-output.xml with 100% similarity]
Documentation/DocBook/media/v4l/dev-overlay.xml [moved from Documentation/DocBook/v4l/dev-overlay.xml with 100% similarity]
Documentation/DocBook/media/v4l/dev-radio.xml [moved from Documentation/DocBook/v4l/dev-radio.xml with 100% similarity]
Documentation/DocBook/media/v4l/dev-raw-vbi.xml [moved from Documentation/DocBook/v4l/dev-raw-vbi.xml with 100% similarity]
Documentation/DocBook/media/v4l/dev-rds.xml [moved from Documentation/DocBook/v4l/dev-rds.xml with 100% similarity]
Documentation/DocBook/media/v4l/dev-sliced-vbi.xml [moved from Documentation/DocBook/v4l/dev-sliced-vbi.xml with 100% similarity]
Documentation/DocBook/media/v4l/dev-subdev.xml [moved from Documentation/DocBook/v4l/dev-subdev.xml with 100% similarity]
Documentation/DocBook/media/v4l/dev-teletext.xml [moved from Documentation/DocBook/v4l/dev-teletext.xml with 100% similarity]
Documentation/DocBook/media/v4l/driver.xml [moved from Documentation/DocBook/v4l/driver.xml with 100% similarity]
Documentation/DocBook/media/v4l/fdl-appendix.xml [moved from Documentation/DocBook/v4l/fdl-appendix.xml with 100% similarity]
Documentation/DocBook/media/v4l/fieldseq_bt.pdf [moved from Documentation/DocBook/v4l/fieldseq_bt.pdf with 100% similarity]
Documentation/DocBook/media/v4l/fieldseq_tb.pdf [moved from Documentation/DocBook/v4l/fieldseq_tb.pdf with 100% similarity]
Documentation/DocBook/media/v4l/func-close.xml [moved from Documentation/DocBook/v4l/func-close.xml with 100% similarity]
Documentation/DocBook/media/v4l/func-ioctl.xml [new file with mode: 0644]
Documentation/DocBook/media/v4l/func-mmap.xml [moved from Documentation/DocBook/v4l/func-mmap.xml with 100% similarity]
Documentation/DocBook/media/v4l/func-munmap.xml [moved from Documentation/DocBook/v4l/func-munmap.xml with 100% similarity]
Documentation/DocBook/media/v4l/func-open.xml [moved from Documentation/DocBook/v4l/func-open.xml with 100% similarity]
Documentation/DocBook/media/v4l/func-poll.xml [moved from Documentation/DocBook/v4l/func-poll.xml with 100% similarity]
Documentation/DocBook/media/v4l/func-read.xml [moved from Documentation/DocBook/v4l/func-read.xml with 100% similarity]
Documentation/DocBook/media/v4l/func-select.xml [moved from Documentation/DocBook/v4l/func-select.xml with 100% similarity]
Documentation/DocBook/media/v4l/func-write.xml [moved from Documentation/DocBook/v4l/func-write.xml with 100% similarity]
Documentation/DocBook/media/v4l/gen-errors.xml [new file with mode: 0644]
Documentation/DocBook/media/v4l/io.xml [moved from Documentation/DocBook/v4l/io.xml with 100% similarity]
Documentation/DocBook/media/v4l/keytable.c.xml [moved from Documentation/DocBook/v4l/keytable.c.xml with 100% similarity]
Documentation/DocBook/media/v4l/libv4l.xml [moved from Documentation/DocBook/v4l/libv4l.xml with 100% similarity]
Documentation/DocBook/media/v4l/lirc_device_interface.xml [moved from Documentation/DocBook/v4l/lirc_device_interface.xml with 99% similarity]
Documentation/DocBook/media/v4l/media-controller.xml [moved from Documentation/DocBook/v4l/media-controller.xml with 100% similarity]
Documentation/DocBook/media/v4l/media-func-close.xml [moved from Documentation/DocBook/v4l/media-func-close.xml with 100% similarity]
Documentation/DocBook/media/v4l/media-func-ioctl.xml [moved from Documentation/DocBook/v4l/media-func-ioctl.xml with 59% similarity]
Documentation/DocBook/media/v4l/media-func-open.xml [moved from Documentation/DocBook/v4l/media-func-open.xml with 100% similarity]
Documentation/DocBook/media/v4l/media-ioc-device-info.xml [moved from Documentation/DocBook/v4l/media-ioc-device-info.xml with 97% similarity]
Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml [moved from Documentation/DocBook/v4l/media-ioc-enum-entities.xml with 100% similarity]
Documentation/DocBook/media/v4l/media-ioc-enum-links.xml [moved from Documentation/DocBook/v4l/media-ioc-enum-links.xml with 98% similarity]
Documentation/DocBook/media/v4l/media-ioc-setup-link.xml [moved from Documentation/DocBook/v4l/media-ioc-setup-link.xml with 87% similarity]
Documentation/DocBook/media/v4l/pipeline.pdf [moved from Documentation/DocBook/v4l/pipeline.pdf with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-grey.xml [moved from Documentation/DocBook/v4l/pixfmt-grey.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-m420.xml [moved from Documentation/DocBook/v4l/pixfmt-m420.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-nv12.xml [moved from Documentation/DocBook/v4l/pixfmt-nv12.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-nv12m.xml [moved from Documentation/DocBook/v4l/pixfmt-nv12m.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-nv12mt.xml [moved from Documentation/DocBook/v4l/pixfmt-nv12mt.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-nv16.xml [moved from Documentation/DocBook/v4l/pixfmt-nv16.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml [moved from Documentation/DocBook/v4l/pixfmt-packed-rgb.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-packed-yuv.xml [moved from Documentation/DocBook/v4l/pixfmt-packed-yuv.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-sbggr16.xml [moved from Documentation/DocBook/v4l/pixfmt-sbggr16.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-sbggr8.xml [moved from Documentation/DocBook/v4l/pixfmt-sbggr8.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-sgbrg8.xml [moved from Documentation/DocBook/v4l/pixfmt-sgbrg8.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-sgrbg8.xml [moved from Documentation/DocBook/v4l/pixfmt-sgrbg8.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-srggb10.xml [moved from Documentation/DocBook/v4l/pixfmt-srggb10.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-srggb12.xml [moved from Documentation/DocBook/v4l/pixfmt-srggb12.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-srggb8.xml [moved from Documentation/DocBook/v4l/pixfmt-srggb8.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-uyvy.xml [moved from Documentation/DocBook/v4l/pixfmt-uyvy.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-vyuy.xml [moved from Documentation/DocBook/v4l/pixfmt-vyuy.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-y10.xml [moved from Documentation/DocBook/v4l/pixfmt-y10.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-y10b.xml [moved from Documentation/DocBook/v4l/pixfmt-y10b.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-y12.xml [moved from Documentation/DocBook/v4l/pixfmt-y12.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-y16.xml [moved from Documentation/DocBook/v4l/pixfmt-y16.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-y41p.xml [moved from Documentation/DocBook/v4l/pixfmt-y41p.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-yuv410.xml [moved from Documentation/DocBook/v4l/pixfmt-yuv410.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-yuv411p.xml [moved from Documentation/DocBook/v4l/pixfmt-yuv411p.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-yuv420.xml [moved from Documentation/DocBook/v4l/pixfmt-yuv420.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml [moved from Documentation/DocBook/v4l/pixfmt-yuv420m.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-yuv422p.xml [moved from Documentation/DocBook/v4l/pixfmt-yuv422p.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-yuyv.xml [moved from Documentation/DocBook/v4l/pixfmt-yuyv.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt-yvyu.xml [moved from Documentation/DocBook/v4l/pixfmt-yvyu.xml with 100% similarity]
Documentation/DocBook/media/v4l/pixfmt.xml [moved from Documentation/DocBook/v4l/pixfmt.xml with 94% similarity]
Documentation/DocBook/media/v4l/planar-apis.xml [moved from Documentation/DocBook/v4l/planar-apis.xml with 100% similarity]
Documentation/DocBook/media/v4l/remote_controllers.xml [moved from Documentation/DocBook/v4l/remote_controllers.xml with 100% similarity]
Documentation/DocBook/media/v4l/subdev-formats.xml [moved from Documentation/DocBook/v4l/subdev-formats.xml with 99% similarity]
Documentation/DocBook/media/v4l/v4l2.xml [moved from Documentation/DocBook/v4l/v4l2.xml with 97% similarity]
Documentation/DocBook/media/v4l/v4l2grab.c.xml [moved from Documentation/DocBook/v4l/v4l2grab.c.xml with 100% similarity]
Documentation/DocBook/media/v4l/vbi_525.pdf [moved from Documentation/DocBook/v4l/vbi_525.pdf with 100% similarity]
Documentation/DocBook/media/v4l/vbi_625.pdf [moved from Documentation/DocBook/v4l/vbi_625.pdf with 100% similarity]
Documentation/DocBook/media/v4l/vbi_hsync.pdf [moved from Documentation/DocBook/v4l/vbi_hsync.pdf with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-cropcap.xml [moved from Documentation/DocBook/v4l/vidioc-cropcap.xml with 95% similarity]
Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml [moved from Documentation/DocBook/v4l/vidioc-dbg-g-chip-ident.xml with 97% similarity]
Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml [moved from Documentation/DocBook/v4l/vidioc-dbg-g-register.xml with 94% similarity]
Documentation/DocBook/media/v4l/vidioc-dqevent.xml [moved from Documentation/DocBook/v4l/vidioc-dqevent.xml with 84% similarity]
Documentation/DocBook/media/v4l/vidioc-encoder-cmd.xml [moved from Documentation/DocBook/v4l/vidioc-encoder-cmd.xml with 96% similarity]
Documentation/DocBook/media/v4l/vidioc-enum-dv-presets.xml [moved from Documentation/DocBook/v4l/vidioc-enum-dv-presets.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-enum-fmt.xml [moved from Documentation/DocBook/v4l/vidioc-enum-fmt.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-enum-frameintervals.xml [moved from Documentation/DocBook/v4l/vidioc-enum-frameintervals.xml with 97% similarity]
Documentation/DocBook/media/v4l/vidioc-enum-framesizes.xml [moved from Documentation/DocBook/v4l/vidioc-enum-framesizes.xml with 97% similarity]
Documentation/DocBook/media/v4l/vidioc-enumaudio.xml [moved from Documentation/DocBook/v4l/vidioc-enumaudio.xml with 89% similarity]
Documentation/DocBook/media/v4l/vidioc-enumaudioout.xml [moved from Documentation/DocBook/v4l/vidioc-enumaudioout.xml with 90% similarity]
Documentation/DocBook/media/v4l/vidioc-enuminput.xml [moved from Documentation/DocBook/v4l/vidioc-enuminput.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-enumoutput.xml [moved from Documentation/DocBook/v4l/vidioc-enumoutput.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-enumstd.xml [moved from Documentation/DocBook/v4l/vidioc-enumstd.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-g-audio.xml [moved from Documentation/DocBook/v4l/vidioc-g-audio.xml with 93% similarity]
Documentation/DocBook/media/v4l/vidioc-g-audioout.xml [moved from Documentation/DocBook/v4l/vidioc-g-audioout.xml with 92% similarity]
Documentation/DocBook/media/v4l/vidioc-g-crop.xml [moved from Documentation/DocBook/v4l/vidioc-g-crop.xml with 93% similarity]
Documentation/DocBook/media/v4l/vidioc-g-ctrl.xml [moved from Documentation/DocBook/v4l/vidioc-g-ctrl.xml with 94% similarity]
Documentation/DocBook/media/v4l/vidioc-g-dv-preset.xml [moved from Documentation/DocBook/v4l/vidioc-g-dv-preset.xml with 96% similarity]
Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml [moved from Documentation/DocBook/v4l/vidioc-g-dv-timings.xml with 98% similarity]
Documentation/DocBook/media/v4l/vidioc-g-enc-index.xml [moved from Documentation/DocBook/v4l/vidioc-g-enc-index.xml with 95% similarity]
Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml [moved from Documentation/DocBook/v4l/vidioc-g-ext-ctrls.xml with 95% similarity]
Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml [moved from Documentation/DocBook/v4l/vidioc-g-fbuf.xml with 97% similarity]
Documentation/DocBook/media/v4l/vidioc-g-fmt.xml [moved from Documentation/DocBook/v4l/vidioc-g-fmt.xml with 93% similarity]
Documentation/DocBook/media/v4l/vidioc-g-frequency.xml [moved from Documentation/DocBook/v4l/vidioc-g-frequency.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-g-input.xml [moved from Documentation/DocBook/v4l/vidioc-g-input.xml with 85% similarity]
Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml [moved from Documentation/DocBook/v4l/vidioc-g-jpegcomp.xml with 93% similarity]
Documentation/DocBook/media/v4l/vidioc-g-modulator.xml [moved from Documentation/DocBook/v4l/vidioc-g-modulator.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-g-output.xml [moved from Documentation/DocBook/v4l/vidioc-g-output.xml with 87% similarity]
Documentation/DocBook/media/v4l/vidioc-g-parm.xml [moved from Documentation/DocBook/v4l/vidioc-g-parm.xml with 97% similarity]
Documentation/DocBook/media/v4l/vidioc-g-priority.xml [moved from Documentation/DocBook/v4l/vidioc-g-priority.xml with 97% similarity]
Documentation/DocBook/media/v4l/vidioc-g-sliced-vbi-cap.xml [moved from Documentation/DocBook/v4l/vidioc-g-sliced-vbi-cap.xml with 97% similarity]
Documentation/DocBook/media/v4l/vidioc-g-std.xml [moved from Documentation/DocBook/v4l/vidioc-g-std.xml with 90% similarity]
Documentation/DocBook/media/v4l/vidioc-g-tuner.xml [moved from Documentation/DocBook/v4l/vidioc-g-tuner.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-log-status.xml [moved from Documentation/DocBook/v4l/vidioc-log-status.xml with 80% similarity]
Documentation/DocBook/media/v4l/vidioc-overlay.xml [moved from Documentation/DocBook/v4l/vidioc-overlay.xml with 90% similarity]
Documentation/DocBook/media/v4l/vidioc-qbuf.xml [moved from Documentation/DocBook/v4l/vidioc-qbuf.xml with 95% similarity]
Documentation/DocBook/media/v4l/vidioc-query-dv-preset.xml [moved from Documentation/DocBook/v4l/vidioc-query-dv-preset.xml with 79% similarity]
Documentation/DocBook/media/v4l/vidioc-querybuf.xml [moved from Documentation/DocBook/v4l/vidioc-querybuf.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-querycap.xml [moved from Documentation/DocBook/v4l/vidioc-querycap.xml with 93% similarity]
Documentation/DocBook/media/v4l/vidioc-queryctrl.xml [moved from Documentation/DocBook/v4l/vidioc-queryctrl.xml with 97% similarity]
Documentation/DocBook/media/v4l/vidioc-querystd.xml [moved from Documentation/DocBook/v4l/vidioc-querystd.xml with 78% similarity]
Documentation/DocBook/media/v4l/vidioc-reqbufs.xml [moved from Documentation/DocBook/v4l/vidioc-reqbufs.xml with 92% similarity]
Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml [moved from Documentation/DocBook/v4l/vidioc-s-hw-freq-seek.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-streamon.xml [moved from Documentation/DocBook/v4l/vidioc-streamon.xml with 92% similarity]
Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml [moved from Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml [moved from Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml [moved from Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-subdev-g-crop.xml [moved from Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml [moved from Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml with 99% similarity]
Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml [moved from Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml with 100% similarity]
Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml [new file with mode: 0644]
Documentation/DocBook/media/vbi_525.gif.b64 [new file with mode: 0644]
Documentation/DocBook/media/vbi_625.gif.b64 [new file with mode: 0644]
Documentation/DocBook/media/vbi_hsync.gif.b64 [new file with mode: 0644]
Documentation/DocBook/media_api.tmpl [moved from Documentation/DocBook/media.tmpl with 89% similarity]
Documentation/DocBook/v4l/bayer.pdf [deleted file]
Documentation/DocBook/v4l/bayer.png [deleted file]
Documentation/DocBook/v4l/crop.gif [deleted file]
Documentation/DocBook/v4l/dev-event.xml [deleted file]
Documentation/DocBook/v4l/fieldseq_bt.gif [deleted file]
Documentation/DocBook/v4l/fieldseq_tb.gif [deleted file]
Documentation/DocBook/v4l/func-ioctl.xml [deleted file]
Documentation/DocBook/v4l/nv12mt.gif [deleted file]
Documentation/DocBook/v4l/nv12mt_example.gif [deleted file]
Documentation/DocBook/v4l/pipeline.png [deleted file]
Documentation/DocBook/v4l/vbi_525.gif [deleted file]
Documentation/DocBook/v4l/vbi_625.gif [deleted file]
Documentation/DocBook/v4l/vbi_hsync.gif [deleted file]
Documentation/DocBook/v4l/videodev2.h.xml [deleted file]
Documentation/DocBook/v4l/vidioc-subscribe-event.xml [deleted file]
Documentation/acpi/apei/einj.txt
Documentation/device-mapper/dm-crypt.txt
Documentation/device-mapper/dm-flakey.txt
Documentation/device-mapper/dm-raid.txt
Documentation/devicetree/bindings/arm/arm-boards [new file with mode: 0644]
Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio_keys.txt
Documentation/devicetree/bindings/i2c/arm-versatile.txt [new file with mode: 0644]
Documentation/devicetree/bindings/input/fsl-mma8450.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/arm-versatile.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
Documentation/devicetree/bindings/net/fsl-fec.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/smsc-lan91c111.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/smsc911x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/samsung-wdt.txt [new file with mode: 0644]
Documentation/dmaengine.txt
Documentation/dvb/get_dvb_firmware [changed mode: 0644->0755]
Documentation/fault-injection/fault-injection.txt
Documentation/feature-removal-schedule.txt
Documentation/frv/booting.txt
Documentation/hwmon/adm1275
Documentation/hwmon/coretemp
Documentation/hwmon/lm25066 [new file with mode: 0644]
Documentation/hwmon/lm90
Documentation/hwmon/lm95245 [new file with mode: 0644]
Documentation/hwmon/max16064
Documentation/hwmon/max1668 [new file with mode: 0644]
Documentation/hwmon/max34440
Documentation/hwmon/max8688
Documentation/hwmon/ntc_thermistor [new file with mode: 0644]
Documentation/hwmon/pmbus
Documentation/hwmon/sysfs-interface
Documentation/ioctl/ioctl-number.txt
Documentation/kernel-parameters.txt
Documentation/m68k/kernel-options.txt
Documentation/media-framework.txt
Documentation/networking/00-INDEX
Documentation/networking/bonding.txt
Documentation/networking/netdevices.txt
Documentation/networking/scaling.txt [new file with mode: 0644]
Documentation/power/runtime_pm.txt
Documentation/scsi/ChangeLog.megaraid_sas
Documentation/video4linux/API.html
Documentation/video4linux/CARDLIST.cx23885
Documentation/video4linux/CARDLIST.cx88
Documentation/video4linux/CARDLIST.em28xx
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/CARDLIST.tuner
Documentation/video4linux/CARDLIST.usbvision
Documentation/video4linux/README.davinci-vpbe [new file with mode: 0644]
Documentation/video4linux/v4l2-controls.txt
Documentation/video4linux/v4l2-framework.txt
Documentation/watchdog/00-INDEX
Documentation/watchdog/watchdog-kernel-api.txt [new file with mode: 0644]
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/Kconfig
arch/alpha/kernel/sys_alcor.c
arch/alpha/kernel/sys_cabriolet.c
arch/alpha/kernel/sys_dp264.c
arch/alpha/kernel/sys_eb64p.c
arch/alpha/kernel/sys_eiger.c
arch/alpha/kernel/sys_marvel.c
arch/alpha/kernel/sys_miata.c
arch/alpha/kernel/sys_mikasa.c
arch/alpha/kernel/sys_nautilus.c
arch/alpha/kernel/sys_noritake.c
arch/alpha/kernel/sys_rawhide.c
arch/alpha/kernel/sys_ruffian.c
arch/alpha/kernel/sys_rx164.c
arch/alpha/kernel/sys_sable.c
arch/alpha/kernel/sys_sio.c
arch/alpha/kernel/sys_sx164.c
arch/alpha/kernel/sys_takara.c
arch/alpha/kernel/sys_titan.c
arch/alpha/kernel/sys_wildfire.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/Makefile
arch/arm/boot/dts/skeleton.dtsi [new file with mode: 0644]
arch/arm/boot/dts/tegra-harmony.dts [new file with mode: 0644]
arch/arm/boot/dts/tegra-seaboard.dts [new file with mode: 0644]
arch/arm/boot/dts/tegra20.dtsi [new file with mode: 0644]
arch/arm/boot/dts/versatile-ab.dts [new file with mode: 0644]
arch/arm/boot/dts/versatile-pb.dts [new file with mode: 0644]
arch/arm/common/it8152.c
arch/arm/include/asm/hardware/it8152.h
arch/arm/include/asm/mach/arch.h
arch/arm/include/asm/mach/pci.h
arch/arm/include/asm/prom.h
arch/arm/kernel/armksyms.c
arch/arm/kernel/bios32.c
arch/arm/kernel/devtree.c
arch/arm/kernel/iwmmxt.S
arch/arm/kernel/module.c
arch/arm/kernel/process.c
arch/arm/lib/Makefile
arch/arm/lib/sha1.S [deleted file]
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91cap9.c
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/board-1arm.c
arch/arm/mach-at91/board-afeb-9260v1.c
arch/arm/mach-at91/board-cam60.c
arch/arm/mach-at91/board-cap9adk.c
arch/arm/mach-at91/board-carmeva.c
arch/arm/mach-at91/board-cpu9krea.c
arch/arm/mach-at91/board-cpuat91.c
arch/arm/mach-at91/board-csb337.c
arch/arm/mach-at91/board-csb637.c
arch/arm/mach-at91/board-eb9200.c
arch/arm/mach-at91/board-ecbat91.c
arch/arm/mach-at91/board-eco920.c
arch/arm/mach-at91/board-flexibity.c
arch/arm/mach-at91/board-foxg20.c
arch/arm/mach-at91/board-gsia18s.c
arch/arm/mach-at91/board-kafa.c
arch/arm/mach-at91/board-kb9202.c
arch/arm/mach-at91/board-neocore926.c
arch/arm/mach-at91/board-pcontrol-g20.c
arch/arm/mach-at91/board-picotux200.c
arch/arm/mach-at91/board-qil-a9260.c
arch/arm/mach-at91/board-rm9200dk.c
arch/arm/mach-at91/board-rm9200ek.c
arch/arm/mach-at91/board-sam9-l9260.c
arch/arm/mach-at91/board-sam9260ek.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/board-sam9m10g45ek.c
arch/arm/mach-at91/board-sam9rlek.c
arch/arm/mach-at91/board-snapper9260.c
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-at91/board-usb-a9260.c
arch/arm/mach-at91/board-usb-a9263.c
arch/arm/mach-at91/board-yl-9200.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/include/mach/at91_dbgu.h
arch/arm/mach-at91/include/mach/at91cap9.h
arch/arm/mach-at91/include/mach/at91rm9200.h
arch/arm/mach-at91/include/mach/at91sam9260.h
arch/arm/mach-at91/include/mach/at91sam9261.h
arch/arm/mach-at91/include/mach/at91sam9263.h
arch/arm/mach-at91/include/mach/at91sam9g45.h
arch/arm/mach-at91/include/mach/at91sam9rl.h
arch/arm/mach-at91/include/mach/cpu.h
arch/arm/mach-at91/include/mach/debug-macro.S
arch/arm/mach-at91/include/mach/hardware.h
arch/arm/mach-at91/include/mach/io.h
arch/arm/mach-at91/setup.c [new file with mode: 0644]
arch/arm/mach-at91/soc.h [new file with mode: 0644]
arch/arm/mach-cns3xxx/pcie.c
arch/arm/mach-dove/pcie.c
arch/arm/mach-footbridge/cats-pci.c
arch/arm/mach-footbridge/ebsa285-pci.c
arch/arm/mach-footbridge/netwinder-pci.c
arch/arm/mach-footbridge/personal-pci.c
arch/arm/mach-imx/clock-imx1.c
arch/arm/mach-imx/clock-imx21.c
arch/arm/mach-imx/clock-imx25.c
arch/arm/mach-imx/clock-imx27.c
arch/arm/mach-imx/clock-imx31.c
arch/arm/mach-imx/clock-imx35.c
arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
arch/arm/mach-imx/mach-imx27_visstrim_m10.c
arch/arm/mach-imx/mach-mx25_3ds.c
arch/arm/mach-imx/mach-mx31ads.c
arch/arm/mach-imx/mach-mx31lilly.c
arch/arm/mach-imx/mach-pcm043.c
arch/arm/mach-imx/mm-imx25.c
arch/arm/mach-imx/mm-imx31.c
arch/arm/mach-imx/mm-imx35.c
arch/arm/mach-integrator/pci.c
arch/arm/mach-iop13xx/iq81340mc.c
arch/arm/mach-iop13xx/pci.c
arch/arm/mach-iop32x/em7210.c
arch/arm/mach-iop32x/glantank.c
arch/arm/mach-iop32x/iq31244.c
arch/arm/mach-iop32x/iq80321.c
arch/arm/mach-iop32x/n2100.c
arch/arm/mach-iop33x/iq80331.c
arch/arm/mach-iop33x/iq80332.c
arch/arm/mach-ixp2000/enp2611.c
arch/arm/mach-ixp2000/ixdp2400.c
arch/arm/mach-ixp2000/ixdp2800.c
arch/arm/mach-ixp2000/ixdp2x01.c
arch/arm/mach-ixp23xx/ixdp2351.c
arch/arm/mach-ixp23xx/roadrunner.c
arch/arm/mach-ixp4xx/avila-pci.c
arch/arm/mach-ixp4xx/coyote-pci.c
arch/arm/mach-ixp4xx/dsmg600-pci.c
arch/arm/mach-ixp4xx/fsg-pci.c
arch/arm/mach-ixp4xx/gateway7001-pci.c
arch/arm/mach-ixp4xx/goramo_mlr.c
arch/arm/mach-ixp4xx/gtwx5715-pci.c
arch/arm/mach-ixp4xx/ixdp425-pci.c
arch/arm/mach-ixp4xx/ixdpg425-pci.c
arch/arm/mach-ixp4xx/nas100d-pci.c
arch/arm/mach-ixp4xx/nslu2-pci.c
arch/arm/mach-ixp4xx/vulcan-pci.c
arch/arm/mach-ixp4xx/wg302v2-pci.c
arch/arm/mach-kirkwood/pcie.c
arch/arm/mach-ks8695/board-dsm320.c
arch/arm/mach-ks8695/board-micrel.c
arch/arm/mach-ks8695/include/mach/devices.h
arch/arm/mach-mmp/gplugd.c
arch/arm/mach-mmp/include/mach/mfp-gplugd.h [deleted file]
arch/arm/mach-mmp/include/mach/mfp-pxa168.h
arch/arm/mach-mmp/time.c
arch/arm/mach-msm/Kconfig
arch/arm/mach-msm/Makefile
arch/arm/mach-msm/gpio.c [deleted file]
arch/arm/mach-msm/gpio_hw.h [deleted file]
arch/arm/mach-msm/gpiomux.h
arch/arm/mach-msm/include/mach/msm_gpiomux.h [new file with mode: 0644]
arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
arch/arm/mach-msm/include/mach/msm_iomap.h
arch/arm/mach-msm/io.c
arch/arm/mach-mv78xx0/pcie.c
arch/arm/mach-mx5/board-cpuimx51.c
arch/arm/mach-mx5/board-mx51_babbage.c
arch/arm/mach-mx5/board-mx51_efikamx.c
arch/arm/mach-mx5/board-mx51_efikasb.c
arch/arm/mach-mx5/board-mx53_loco.c
arch/arm/mach-mx5/clock-mx51-mx53.c
arch/arm/mach-mx5/mm.c
arch/arm/mach-mx5/mx51_efika.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-am3517crane.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/cminst44xx.h
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/smartreflex.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-orion5x/common.h
arch/arm/mach-orion5x/db88f5281-setup.c
arch/arm/mach-orion5x/dns323-setup.c
arch/arm/mach-orion5x/kurobox_pro-setup.c
arch/arm/mach-orion5x/mss2-setup.c
arch/arm/mach-orion5x/pci.c
arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
arch/arm/mach-orion5x/rd88f5182-setup.c
arch/arm/mach-orion5x/terastation_pro2-setup.c
arch/arm/mach-orion5x/ts209-setup.c
arch/arm/mach-orion5x/ts409-setup.c
arch/arm/mach-orion5x/wnr854t-setup.c
arch/arm/mach-orion5x/wrt350n-v2-setup.c
arch/arm/mach-pxa/cm-x2xx-pci.c
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-sa1100/pci-nanoengine.c
arch/arm/mach-shark/pci.c
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/clock-sh7367.c
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/clock-sh7377.c
arch/arm/mach-shmobile/clock-sh73a0.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/Makefile.boot
arch/arm/mach-tegra/board-dt.c [new file with mode: 0644]
arch/arm/mach-tegra/pcie.c
arch/arm/mach-versatile/Kconfig
arch/arm/mach-versatile/Makefile
arch/arm/mach-versatile/core.c
arch/arm/mach-versatile/core.h
arch/arm/mach-versatile/pci.c
arch/arm/mach-versatile/versatile_dt.c [new file with mode: 0644]
arch/arm/mach-zynq/Makefile
arch/arm/mach-zynq/board_dt.c [deleted file]
arch/arm/mm/alignment.c
arch/arm/mm/init.c
arch/arm/mm/proc-arm946.S
arch/arm/plat-mxc/devices/platform-fec.c
arch/arm/plat-mxc/devices/platform-imx-dma.c
arch/arm/plat-mxc/devices/platform-imx-uart.c
arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
arch/arm/plat-mxc/include/mach/debug-macro.S
arch/arm/plat-mxc/include/mach/devices-common.h
arch/arm/plat-mxc/include/mach/dma.h
arch/arm/plat-mxc/include/mach/esdhc.h
arch/arm/plat-mxc/include/mach/iomux-mx53.h
arch/arm/plat-mxc/include/mach/sdma.h
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/include/plat/dma.h
arch/arm/plat-omap/include/plat/irqs.h
arch/arm/plat-omap/include/plat/serial.h
arch/arm/plat-omap/iovmm.c
arch/arm/tools/mach-types
arch/avr32/Kconfig
arch/cris/arch-v10/drivers/sync_serial.c
arch/cris/arch-v10/kernel/irq.c
arch/cris/include/asm/thread_info.h
arch/frv/Kconfig
arch/frv/mm/pgalloc.c
arch/ia64/Kconfig
arch/ia64/hp/sim/simeth.c
arch/ia64/include/asm/gpio.h [new file with mode: 0644]
arch/ia64/kernel/efi.c
arch/m68k/Kconfig
arch/m68k/Kconfig.mmu
arch/m68k/amiga/chipram.c
arch/m68k/atari/stram.c
arch/m68k/include/asm/atari_stram.h
arch/m68k/include/asm/atarihw.h
arch/m68k/kernel/setup_mm.c
arch/m68k/math-emu/fp_log.c
arch/m68k/math-emu/multi_arith.h
arch/m68k/mm/init_mm.c
arch/parisc/Kconfig
arch/parisc/include/asm/atomic.h
arch/parisc/include/asm/futex.h
arch/parisc/include/asm/unistd.h
arch/parisc/kernel/syscall_table.S
arch/powerpc/Kconfig
arch/powerpc/boot/dts/p1010rdb.dts
arch/powerpc/boot/dts/p1010si.dtsi
arch/powerpc/configs/40x/acadia_defconfig
arch/powerpc/configs/40x/ep405_defconfig
arch/powerpc/configs/40x/hcu4_defconfig
arch/powerpc/configs/40x/kilauea_defconfig
arch/powerpc/configs/40x/makalu_defconfig
arch/powerpc/configs/40x/walnut_defconfig
arch/powerpc/configs/44x/arches_defconfig
arch/powerpc/configs/44x/bamboo_defconfig
arch/powerpc/configs/44x/bluestone_defconfig
arch/powerpc/configs/44x/canyonlands_defconfig
arch/powerpc/configs/44x/ebony_defconfig
arch/powerpc/configs/44x/eiger_defconfig
arch/powerpc/configs/44x/icon_defconfig
arch/powerpc/configs/44x/katmai_defconfig
arch/powerpc/configs/44x/redwood_defconfig
arch/powerpc/configs/44x/sam440ep_defconfig
arch/powerpc/configs/44x/sequoia_defconfig
arch/powerpc/configs/44x/taishan_defconfig
arch/powerpc/configs/44x/warp_defconfig
arch/powerpc/configs/ppc40x_defconfig
arch/powerpc/configs/ppc44x_defconfig
arch/powerpc/include/asm/jump_label.h
arch/powerpc/include/asm/kdump.h
arch/powerpc/include/asm/reg.h
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/iomap.c
arch/powerpc/kernel/machine_kexec.c
arch/powerpc/kernel/perf_callchain.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/platforms/40x/Kconfig
arch/powerpc/platforms/44x/Kconfig
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/cell/Kconfig
arch/powerpc/platforms/pseries/dtl.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/io_event_irq.c
arch/powerpc/platforms/pseries/kexec.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/plpar_wrappers.h
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/ppc4xx_pci.c
arch/s390/Kconfig
arch/s390/include/asm/ipl.h
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/qdio.h
arch/s390/include/asm/system.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/base.S
arch/s390/kernel/compat_signal.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/ipl.c
arch/s390/kernel/reipl64.S
arch/s390/kernel/setup.c
arch/s390/kernel/signal.c
arch/s390/kernel/smp.c
arch/s390/mm/maccess.c
arch/s390/mm/pgtable.c
arch/sh/Kconfig
arch/sh/Makefile
arch/sh/boards/board-apsh4a3a.c
arch/sh/boards/board-apsh4ad0a.c
arch/sh/boards/board-sh7785lcr.c
arch/sh/boards/board-urquell.c
arch/sh/boards/mach-ap325rxa/setup.c
arch/sh/boards/mach-highlander/setup.c
arch/sh/boards/mach-sdk7786/setup.c
arch/sh/drivers/pci/fixups-cayman.c
arch/sh/drivers/pci/fixups-dreamcast.c
arch/sh/drivers/pci/fixups-landisk.c
arch/sh/drivers/pci/fixups-r7780rp.c
arch/sh/drivers/pci/fixups-rts7751r2d.c
arch/sh/drivers/pci/fixups-sdk7780.c
arch/sh/drivers/pci/fixups-se7751.c
arch/sh/drivers/pci/fixups-sh03.c
arch/sh/drivers/pci/fixups-snapgear.c
arch/sh/drivers/pci/fixups-titan.c
arch/sh/drivers/pci/pcie-sh7786.c
arch/sh/include/asm/pci.h
arch/sh/include/cpu-sh3/cpu/serial.h [new file with mode: 0644]
arch/sh/include/cpu-sh4a/cpu/serial.h [new file with mode: 0644]
arch/sh/kernel/cpu/clock-cpg.c
arch/sh/kernel/cpu/sh3/Makefile
arch/sh/kernel/cpu/sh3/serial-sh770x.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/serial-sh7710.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/serial-sh7720.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/setup-sh7705.c
arch/sh/kernel/cpu/sh3/setup-sh770x.c
arch/sh/kernel/cpu/sh3/setup-sh7720.c
arch/sh/kernel/cpu/sh4/clock-sh4-202.c
arch/sh/kernel/cpu/sh4/setup-sh7750.c
arch/sh/kernel/cpu/sh4/setup-sh7760.c
arch/sh/kernel/cpu/sh4a/Makefile
arch/sh/kernel/cpu/sh4a/clock-sh7343.c
arch/sh/kernel/cpu/sh4a/clock-sh7366.c
arch/sh/kernel/cpu/sh4a/clock-sh7722.c
arch/sh/kernel/cpu/sh4a/clock-sh7723.c
arch/sh/kernel/cpu/sh4a/clock-sh7724.c
arch/sh/kernel/cpu/sh4a/clock-sh7757.c
arch/sh/kernel/cpu/sh4a/clock-sh7763.c
arch/sh/kernel/cpu/sh4a/clock-sh7780.c
arch/sh/kernel/cpu/sh4a/clock-sh7785.c
arch/sh/kernel/cpu/sh4a/clock-sh7786.c
arch/sh/kernel/cpu/sh4a/clock-shx3.c
arch/sh/kernel/cpu/sh4a/serial-sh7722.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/setup-sh7366.c
arch/sh/kernel/cpu/sh4a/setup-sh7722.c
arch/sh/kernel/cpu/sh4a/setup-sh7723.c
arch/sh/kernel/cpu/sh4a/setup-sh7724.c
arch/sh/kernel/cpu/sh4a/setup-sh7763.c
arch/sh/kernel/cpu/sh4a/setup-sh7780.c
arch/sh/kernel/cpu/sh4a/setup-sh7785.c
arch/sh/kernel/cpu/sh4a/setup-sh7786.c
arch/sh/kernel/idle.c
arch/sparc/Kconfig
arch/sparc/include/asm/Kbuild
arch/sparc/include/asm/bitops_64.h
arch/sparc/include/asm/div64.h [deleted file]
arch/sparc/include/asm/elf_64.h
arch/sparc/include/asm/hypervisor.h
arch/sparc/include/asm/irq_regs.h [deleted file]
arch/sparc/include/asm/leon_pci.h
arch/sparc/include/asm/local.h [deleted file]
arch/sparc/include/asm/local64.h [deleted file]
arch/sparc/include/asm/spitfire.h
arch/sparc/include/asm/tsb.h
arch/sparc/include/asm/xor_64.h
arch/sparc/kernel/cpu.c
arch/sparc/kernel/cpumap.c
arch/sparc/kernel/ds.c
arch/sparc/kernel/entry.h
arch/sparc/kernel/head_64.S
arch/sparc/kernel/hvapi.c
arch/sparc/kernel/hvcalls.S
arch/sparc/kernel/ioport.c
arch/sparc/kernel/kernel.h
arch/sparc/kernel/ktlb.S
arch/sparc/kernel/leon_pci_grpci2.c
arch/sparc/kernel/mdesc.c
arch/sparc/kernel/pcr.c
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/sparc_ksyms_64.c
arch/sparc/kernel/sstate.c
arch/sparc/kernel/unaligned_64.c
arch/sparc/kernel/vmlinux.lds.S
arch/sparc/lib/Makefile
arch/sparc/lib/NG2page.S [deleted file]
arch/sparc/lib/NGpage.S
arch/sparc/lib/atomic32.c
arch/sparc/lib/ffs.S [new file with mode: 0644]
arch/sparc/lib/hweight.S [new file with mode: 0644]
arch/sparc/mm/init_64.c
arch/tile/Kconfig
arch/tile/include/asm/Kbuild
arch/tile/include/asm/bug.h [deleted file]
arch/tile/include/asm/bugs.h [deleted file]
arch/tile/include/asm/cputime.h [deleted file]
arch/tile/include/asm/device.h [deleted file]
arch/tile/include/asm/div64.h [deleted file]
arch/tile/include/asm/emergency-restart.h [deleted file]
arch/tile/include/asm/errno.h [deleted file]
arch/tile/include/asm/fb.h [deleted file]
arch/tile/include/asm/fcntl.h [deleted file]
arch/tile/include/asm/fixmap.h
arch/tile/include/asm/ioctl.h [deleted file]
arch/tile/include/asm/ioctls.h [deleted file]
arch/tile/include/asm/ipc.h [deleted file]
arch/tile/include/asm/ipcbuf.h [deleted file]
arch/tile/include/asm/irq_regs.h [deleted file]
arch/tile/include/asm/kdebug.h [deleted file]
arch/tile/include/asm/local.h [deleted file]
arch/tile/include/asm/module.h [deleted file]
arch/tile/include/asm/msgbuf.h [deleted file]
arch/tile/include/asm/mutex.h [deleted file]
arch/tile/include/asm/param.h [deleted file]
arch/tile/include/asm/parport.h [deleted file]
arch/tile/include/asm/poll.h [deleted file]
arch/tile/include/asm/posix_types.h [deleted file]
arch/tile/include/asm/resource.h [deleted file]
arch/tile/include/asm/scatterlist.h [deleted file]
arch/tile/include/asm/sembuf.h [deleted file]
arch/tile/include/asm/serial.h [deleted file]
arch/tile/include/asm/shmbuf.h [deleted file]
arch/tile/include/asm/shmparam.h [deleted file]
arch/tile/include/asm/socket.h [deleted file]
arch/tile/include/asm/sockios.h [deleted file]
arch/tile/include/asm/statfs.h [deleted file]
arch/tile/include/asm/termbits.h [deleted file]
arch/tile/include/asm/termios.h [deleted file]
arch/tile/include/asm/types.h [deleted file]
arch/tile/include/asm/ucontext.h [deleted file]
arch/tile/include/asm/xor.h [deleted file]
arch/tile/include/hv/drv_srom_intf.h [new file with mode: 0644]
arch/tile/kernel/pci.c
arch/tile/kernel/time.c
arch/tile/mm/init.c
arch/um/drivers/net_kern.c
arch/unicore32/kernel/pci.c
arch/x86/Kconfig
arch/x86/include/asm/desc.h
arch/x86/include/asm/io.h
arch/x86/include/asm/irq_vectors.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/ptrace.h
arch/x86/include/asm/traps.h
arch/x86/include/asm/unistd_64.h
arch/x86/include/asm/vsyscall.h
arch/x86/kernel/Makefile
arch/x86/kernel/acpi/cstate.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/paravirt.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/step.c
arch/x86/kernel/traps.c
arch/x86/kernel/vmlinux.lds.S
arch/x86/kernel/vsyscall_64.c
arch/x86/kernel/vsyscall_emu_64.S
arch/x86/kernel/vsyscall_trace.h [new file with mode: 0644]
arch/x86/mm/fault.c
arch/x86/pci/acpi.c
arch/x86/pci/ce4100.c
arch/x86/pci/common.c
arch/x86/pci/direct.c
arch/x86/pci/numaq_32.c
arch/x86/pci/olpc.c
arch/x86/pci/pcbios.c
arch/x86/pci/visws.c
arch/x86/platform/mrst/Makefile
arch/x86/platform/mrst/pmu.c [new file with mode: 0644]
arch/x86/platform/mrst/pmu.h [new file with mode: 0644]
arch/x86/vdso/vdso.S
arch/x86/xen/Makefile
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/setup.c
arch/x86/xen/trace.c
arch/xtensa/platforms/iss/network.c
block/blk-core.c
block/blk-timeout.c
crypto/md5.c
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acpredef.h
drivers/acpi/acpica/nspredef.c
drivers/acpi/acpica/nsrepair2.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/apei/Kconfig
drivers/acpi/apei/apei-base.c
drivers/acpi/apei/apei-internal.h
drivers/acpi/apei/einj.c
drivers/acpi/apei/erst-dbg.c
drivers/acpi/apei/erst.c
drivers/acpi/apei/ghes.c
drivers/acpi/apei/hest.c
drivers/acpi/battery.c
drivers/acpi/bus.c
drivers/acpi/dock.c
drivers/acpi/ec_sys.c
drivers/acpi/fan.c
drivers/acpi/osl.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_root.c
drivers/acpi/processor_thermal.c
drivers/acpi/sbs.c
drivers/acpi/sleep.c
drivers/acpi/sysfs.c
drivers/acpi/thermal.c
drivers/acpi/video.c
drivers/ata/libata-acpi.c
drivers/atm/eni.c
drivers/base/devtmpfs.c
drivers/base/power/domain.c
drivers/base/power/runtime.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/hw_random/n2-drv.c
drivers/char/hw_random/n2rng.h
drivers/char/ramoops.c
drivers/char/random.c
drivers/char/tile-srom.c [new file with mode: 0644]
drivers/char/tpm/tpm_tis.c
drivers/connector/cn_proc.c
drivers/cpuidle/cpuidle.c
drivers/cpuidle/cpuidle.h
drivers/cpuidle/driver.c
drivers/cpuidle/governor.c
drivers/crypto/n2_core.c
drivers/dma/TODO
drivers/dma/amba-pl08x.c
drivers/dma/at_hdmac.c
drivers/dma/coh901318.c
drivers/dma/dmaengine.c
drivers/dma/ep93xx_dma.c
drivers/dma/imx-sdma.c
drivers/dma/intel_mid_dma.c
drivers/dma/ioat/dma_v3.c
drivers/dma/ioat/pci.c
drivers/dma/ipu/ipu_idmac.c
drivers/dma/mv_xor.c
drivers/dma/mxs-dma.c
drivers/dma/pch_dma.c
drivers/dma/pl330.c
drivers/dma/shdma.c
drivers/dma/shdma.h
drivers/dma/ste_dma40.c
drivers/dma/ste_dma40_ll.h
drivers/eisa/pci_eisa.c
drivers/firmware/efivars.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-ab8500.c
drivers/gpio/gpio-msm-v1.c [new file with mode: 0644]
drivers/gpio/gpio-msm-v2.c [moved from arch/arm/mach-msm/gpio-v2.c with 99% similarity]
drivers/gpio/gpio-tps65912.c [new file with mode: 0644]
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/radeon/Makefile
drivers/gpu/drm/radeon/atom.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/coretemp.c
drivers/hwmon/lm90.c
drivers/hwmon/lm95241.c
drivers/hwmon/lm95245.c [new file with mode: 0644]
drivers/hwmon/max1668.c [new file with mode: 0644]
drivers/hwmon/ntc_thermistor.c [new file with mode: 0644]
drivers/hwmon/pmbus/Kconfig [new file with mode: 0644]
drivers/hwmon/pmbus/Makefile [new file with mode: 0644]
drivers/hwmon/pmbus/adm1275.c [moved from drivers/hwmon/adm1275.c with 67% similarity]
drivers/hwmon/pmbus/lm25066.c [new file with mode: 0644]
drivers/hwmon/pmbus/max16064.c [moved from drivers/hwmon/max16064.c with 66% similarity]
drivers/hwmon/pmbus/max34440.c [moved from drivers/hwmon/max34440.c with 76% similarity]
drivers/hwmon/pmbus/max8688.c [moved from drivers/hwmon/max8688.c with 72% similarity]
drivers/hwmon/pmbus/pmbus.c [moved from drivers/hwmon/pmbus.c with 89% similarity]
drivers/hwmon/pmbus/pmbus.h [moved from drivers/hwmon/pmbus.h with 79% similarity]
drivers/hwmon/pmbus/pmbus_core.c [moved from drivers/hwmon/pmbus_core.c with 84% similarity]
drivers/hwmon/pmbus/ucd9000.c [moved from drivers/hwmon/ucd9000.c with 100% similarity]
drivers/hwmon/pmbus/ucd9200.c [moved from drivers/hwmon/ucd9200.c with 100% similarity]
drivers/ide/cy82c693.c
drivers/ide/ide_platform.c
drivers/infiniband/hw/amso1100/c2.c
drivers/infiniband/hw/cxgb3/Makefile
drivers/infiniband/hw/cxgb4/Makefile
drivers/infiniband/hw/mlx4/Kconfig
drivers/infiniband/hw/nes/nes_nic.c
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/lm8323.c
drivers/input/keyboard/tegra-kbc.c
drivers/input/misc/kxtj9.c
drivers/input/misc/mma8450.c
drivers/input/mouse/hgpk.c
drivers/input/serio/xilinx_ps2.c
drivers/input/touchscreen/ad7879.c
drivers/md/Kconfig
drivers/md/dm-crypt.c
drivers/md/dm-flakey.c
drivers/md/dm-io.c
drivers/md/dm-ioctl.c
drivers/md/dm-kcopyd.c
drivers/md/dm-log-userspace-base.c
drivers/md/dm-log.c
drivers/md/dm-mpath.c
drivers/md/dm-raid.c
drivers/md/dm-snap-persistent.c
drivers/md/dm-snap.c
drivers/md/dm-table.c
drivers/md/dm.c
drivers/md/dm.h
drivers/media/Kconfig
drivers/media/common/tuners/Kconfig
drivers/media/common/tuners/Makefile
drivers/media/common/tuners/tuner-types.c
drivers/media/common/tuners/xc4000.c [new file with mode: 0644]
drivers/media/common/tuners/xc4000.h [new file with mode: 0644]
drivers/media/dvb/Kconfig
drivers/media/dvb/Makefile
drivers/media/dvb/bt8xx/dvb-bt8xx.c
drivers/media/dvb/ddbridge/Kconfig [new file with mode: 0644]
drivers/media/dvb/ddbridge/Makefile [new file with mode: 0644]
drivers/media/dvb/ddbridge/ddbridge-core.c [new file with mode: 0644]
drivers/media/dvb/ddbridge/ddbridge-regs.h [new file with mode: 0644]
drivers/media/dvb/ddbridge/ddbridge.h [new file with mode: 0644]
drivers/media/dvb/dvb-core/Makefile
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/dvb/dvb-core/dvb_net.h
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/af9015.c
drivers/media/dvb/dvb-usb/af9015.h
drivers/media/dvb/dvb-usb/anysee.c
drivers/media/dvb/dvb-usb/anysee.h
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dvb-usb.h
drivers/media/dvb/dvb-usb/gp8psk.h
drivers/media/dvb/dvb-usb/technisat-usb2.c
drivers/media/dvb/dvb-usb/vp7045.h
drivers/media/dvb/firewire/firedtv-avc.c
drivers/media/dvb/firewire/firedtv-ci.c
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/au8522_decoder.c
drivers/media/dvb/frontends/cx24113.c
drivers/media/dvb/frontends/cx24116.c
drivers/media/dvb/frontends/cxd2820r.h
drivers/media/dvb/frontends/cxd2820r_core.c
drivers/media/dvb/frontends/cxd2820r_priv.h
drivers/media/dvb/frontends/dib7000p.c
drivers/media/dvb/frontends/drxd_hard.c
drivers/media/dvb/frontends/drxk.h [new file with mode: 0644]
drivers/media/dvb/frontends/drxk_hard.c [new file with mode: 0644]
drivers/media/dvb/frontends/drxk_hard.h [new file with mode: 0644]
drivers/media/dvb/frontends/drxk_map.h [new file with mode: 0644]
drivers/media/dvb/frontends/itd1000.c
drivers/media/dvb/frontends/nxt6000.c
drivers/media/dvb/frontends/s5h1420.c
drivers/media/dvb/frontends/tda18271c2dd.c [new file with mode: 0644]
drivers/media/dvb/frontends/tda18271c2dd.h [new file with mode: 0644]
drivers/media/dvb/frontends/tda18271c2dd_maps.h [new file with mode: 0644]
drivers/media/dvb/ngene/Kconfig
drivers/media/dvb/ngene/ngene-cards.c
drivers/media/dvb/ngene/ngene-core.c
drivers/media/dvb/ngene/ngene-dvb.c
drivers/media/dvb/ngene/ngene.h
drivers/media/dvb/siano/smscoreapi.c
drivers/media/dvb/siano/smscoreapi.h
drivers/media/radio/dsbr100.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-mr800.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-tea5764.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-timb.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-wl1273.c
drivers/media/radio/radio-zoltrix.c
drivers/media/radio/si470x/radio-si470x-i2c.c
drivers/media/radio/si470x/radio-si470x-usb.c
drivers/media/radio/si470x/radio-si470x.h
drivers/media/radio/wl128x/fmdrv.h
drivers/media/radio/wl128x/fmdrv_v4l2.c
drivers/media/rc/Kconfig
drivers/media/rc/Makefile
drivers/media/rc/ene_ir.c
drivers/media/rc/ene_ir.h
drivers/media/rc/ir-lirc-codec.c
drivers/media/rc/ir-mce_kbd-decoder.c [new file with mode: 0644]
drivers/media/rc/ir-raw.c
drivers/media/rc/ite-cir.c
drivers/media/rc/keymaps/rc-rc6-mce.c
drivers/media/rc/mceusb.c
drivers/media/rc/nuvoton-cir.c
drivers/media/rc/rc-core-priv.h
drivers/media/rc/rc-loopback.c
drivers/media/rc/rc-main.c
drivers/media/rc/redrat3.c
drivers/media/rc/winbond-cir.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/adp1653.c [new file with mode: 0644]
drivers/media/video/arv.c
drivers/media/video/atmel-isi.c [new file with mode: 0644]
drivers/media/video/au0828/au0828-core.c
drivers/media/video/au0828/au0828-video.c
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttvp.h
drivers/media/video/bw-qcam.c
drivers/media/video/c-qcam.c
drivers/media/video/cafe_ccic-regs.h [deleted file]
drivers/media/video/cafe_ccic.c [deleted file]
drivers/media/video/cpia2/cpia2.h
drivers/media/video/cpia2/cpia2_v4l.c
drivers/media/video/cx18/cx18-alsa-main.c
drivers/media/video/cx18/cx18-driver.h
drivers/media/video/cx18/cx18-ioctl.c
drivers/media/video/cx18/cx18-version.h
drivers/media/video/cx231xx/cx231xx-avcore.c
drivers/media/video/cx231xx/cx231xx-cards.c
drivers/media/video/cx231xx/cx231xx-core.c
drivers/media/video/cx231xx/cx231xx-video.c
drivers/media/video/cx231xx/cx231xx.h
drivers/media/video/cx23885/altera-ci.c
drivers/media/video/cx23885/cx23885-417.c
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-core.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-input.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx23885/cx23885.h
drivers/media/video/cx88/cx88-alsa.c
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-core.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-input.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/davinci/Kconfig
drivers/media/video/davinci/Makefile
drivers/media/video/davinci/vpbe.c [new file with mode: 0644]
drivers/media/video/davinci/vpbe_display.c [new file with mode: 0644]
drivers/media/video/davinci/vpbe_osd.c [new file with mode: 0644]
drivers/media/video/davinci/vpbe_osd_regs.h [new file with mode: 0644]
drivers/media/video/davinci/vpbe_venc.c [new file with mode: 0644]
drivers/media/video/davinci/vpbe_venc_regs.h [new file with mode: 0644]
drivers/media/video/davinci/vpif_capture.c
drivers/media/video/davinci/vpif_capture.h
drivers/media/video/davinci/vpif_display.c
drivers/media/video/davinci/vpif_display.h
drivers/media/video/em28xx/Kconfig
drivers/media/video/em28xx/Makefile
drivers/media/video/em28xx/em28xx-audio.c
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/em28xx/em28xx-dvb.c
drivers/media/video/em28xx/em28xx-i2c.c
drivers/media/video/em28xx/em28xx-input.c
drivers/media/video/em28xx/em28xx-reg.h
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/em28xx/em28xx.h
drivers/media/video/et61x251/et61x251.h
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/fsl-viu.c
drivers/media/video/gspca/Kconfig
drivers/media/video/gspca/Makefile
drivers/media/video/gspca/gl860/gl860.h
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/ov519.c
drivers/media/video/gspca/se401.c [new file with mode: 0644]
drivers/media/video/gspca/se401.h [new file with mode: 0644]
drivers/media/video/gspca/sunplus.c
drivers/media/video/gspca/t613.c
drivers/media/video/hdpvr/hdpvr-core.c
drivers/media/video/hdpvr/hdpvr-video.c
drivers/media/video/hdpvr/hdpvr.h
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-version.h
drivers/media/video/m5mols/m5mols_capture.c
drivers/media/video/m5mols/m5mols_core.c
drivers/media/video/marvell-ccic/Kconfig [new file with mode: 0644]
drivers/media/video/marvell-ccic/Makefile [new file with mode: 0644]
drivers/media/video/marvell-ccic/cafe-driver.c [new file with mode: 0644]
drivers/media/video/marvell-ccic/mcam-core.c [new file with mode: 0644]
drivers/media/video/marvell-ccic/mcam-core.h [new file with mode: 0644]
drivers/media/video/marvell-ccic/mmp-driver.c [new file with mode: 0644]
drivers/media/video/mem2mem_testdev.c
drivers/media/video/mt9m001.c
drivers/media/video/mt9m111.c
drivers/media/video/mt9t031.c
drivers/media/video/mt9t112.c
drivers/media/video/mt9v011.c
drivers/media/video/mt9v022.c
drivers/media/video/mt9v032.c
drivers/media/video/mx1_camera.c
drivers/media/video/mx2_camera.c
drivers/media/video/mx3_camera.c
drivers/media/video/omap/Kconfig
drivers/media/video/omap/Makefile
drivers/media/video/omap/omap_vout.c
drivers/media/video/omap/omap_vout_vrfb.c [new file with mode: 0644]
drivers/media/video/omap/omap_vout_vrfb.h [new file with mode: 0644]
drivers/media/video/omap/omap_voutdef.h
drivers/media/video/omap/omap_voutlib.c
drivers/media/video/omap/omap_voutlib.h
drivers/media/video/omap1_camera.c
drivers/media/video/omap24xxcam.c
drivers/media/video/omap3isp/isp.c
drivers/media/video/omap3isp/isp.h
drivers/media/video/omap3isp/ispccdc.c
drivers/media/video/omap3isp/ispccp2.c
drivers/media/video/omap3isp/ispccp2.h
drivers/media/video/omap3isp/ispstat.c
drivers/media/video/omap3isp/ispvideo.c
drivers/media/video/omap3isp/ispvideo.h
drivers/media/video/ov2640.c
drivers/media/video/ov5642.c [new file with mode: 0644]
drivers/media/video/ov7670.c
drivers/media/video/ov772x.c
drivers/media/video/ov9640.c
drivers/media/video/ov9740.c
drivers/media/video/pms.c
drivers/media/video/pvrusb2/pvrusb2-main.c
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/pwc/Kconfig
drivers/media/video/pwc/pwc-ctrl.c
drivers/media/video/pwc/pwc-dec1.c
drivers/media/video/pwc/pwc-dec1.h
drivers/media/video/pwc/pwc-dec23.c
drivers/media/video/pwc/pwc-dec23.h
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-ioctl.h [deleted file]
drivers/media/video/pwc/pwc-kiara.c
drivers/media/video/pwc/pwc-misc.c
drivers/media/video/pwc/pwc-uncompress.c
drivers/media/video/pwc/pwc-uncompress.h [deleted file]
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pwc/pwc.h
drivers/media/video/pxa_camera.c
drivers/media/video/rj54n1cb0c.c
drivers/media/video/s2255drv.c
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/s5p-mfc/Makefile [new file with mode: 0644]
drivers/media/video/s5p-mfc/regs-mfc.h [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc.c [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_cmd.c [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_cmd.h [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_common.h [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_debug.h [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_dec.c [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_dec.h [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_enc.c [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_enc.h [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_intr.c [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_intr.h [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_opr.c [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_opr.h [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_pm.c [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_pm.h [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_shm.c [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc_shm.h [new file with mode: 0644]
drivers/media/video/s5p-tv/Kconfig [new file with mode: 0644]
drivers/media/video/s5p-tv/Makefile [new file with mode: 0644]
drivers/media/video/s5p-tv/hdmi_drv.c [new file with mode: 0644]
drivers/media/video/s5p-tv/hdmiphy_drv.c [new file with mode: 0644]
drivers/media/video/s5p-tv/mixer.h [new file with mode: 0644]
drivers/media/video/s5p-tv/mixer_drv.c [new file with mode: 0644]
drivers/media/video/s5p-tv/mixer_grp_layer.c [new file with mode: 0644]
drivers/media/video/s5p-tv/mixer_reg.c [new file with mode: 0644]
drivers/media/video/s5p-tv/mixer_video.c [new file with mode: 0644]
drivers/media/video/s5p-tv/mixer_vp_layer.c [new file with mode: 0644]
drivers/media/video/s5p-tv/regs-hdmi.h [new file with mode: 0644]
drivers/media/video/s5p-tv/regs-mixer.h [new file with mode: 0644]
drivers/media/video/s5p-tv/regs-sdo.h [new file with mode: 0644]
drivers/media/video/s5p-tv/regs-vp.h [new file with mode: 0644]
drivers/media/video/s5p-tv/sdo_drv.c [new file with mode: 0644]
drivers/media/video/saa7115.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-video.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/saa7164/saa7164-encoder.c
drivers/media/video/saa7164/saa7164-vbi.c
drivers/media/video/saa7164/saa7164.h
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/sh_mobile_csi2.c
drivers/media/video/sh_vou.c
drivers/media/video/sn9c102/sn9c102.h
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/soc_camera.c
drivers/media/video/soc_camera_platform.c
drivers/media/video/sr030pc30.c
drivers/media/video/tda7432.c
drivers/media/video/timblogiw.c
drivers/media/video/tlg2300/pd-common.h
drivers/media/video/tlg2300/pd-main.c
drivers/media/video/tlg2300/pd-radio.c
drivers/media/video/tuner-core.c
drivers/media/video/tw9910.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_driver.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/uvc/uvcvideo.h
drivers/media/video/v4l2-common.c
drivers/media/video/v4l2-compat-ioctl32.c
drivers/media/video/v4l2-ctrls.c
drivers/media/video/v4l2-device.c
drivers/media/video/v4l2-event.c
drivers/media/video/v4l2-fh.c
drivers/media/video/v4l2-ioctl.c
drivers/media/video/v4l2-subdev.c
drivers/media/video/videobuf-dma-sg.c
drivers/media/video/videobuf2-dma-sg.c
drivers/media/video/videobuf2-memops.c
drivers/media/video/vino.c
drivers/media/video/vivi.c
drivers/media/video/w9966.c
drivers/media/video/zoran/zoran.h
drivers/media/video/zoran/zoran_card.c
drivers/media/video/zoran/zoran_driver.c
drivers/media/video/zr364xx.c
drivers/message/fusion/mptscsih.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/aat2870-core.c [new file with mode: 0644]
drivers/mfd/ab3550-core.c
drivers/mfd/ab8500-core.c
drivers/mfd/ab8500-debugfs.c
drivers/mfd/jz4740-adc.c
drivers/mfd/lpc_sch.c
drivers/mfd/max8997-irq.c
drivers/mfd/max8998.c
drivers/mfd/omap-usb-host.c
drivers/mfd/stmpe.c
drivers/mfd/stmpe.h
drivers/mfd/timberdale.c
drivers/mfd/tps65910.c
drivers/mfd/tps65911-comparator.c
drivers/mfd/tps65912-core.c [new file with mode: 0644]
drivers/mfd/tps65912-i2c.c [new file with mode: 0644]
drivers/mfd/tps65912-irq.c [new file with mode: 0644]
drivers/mfd/tps65912-spi.c [new file with mode: 0644]
drivers/mfd/twl-core.c
drivers/mfd/twl4030-madc.c
drivers/mfd/twl6030-pwm.c
drivers/mfd/wm831x-auxadc.c [new file with mode: 0644]
drivers/mfd/wm831x-core.c
drivers/mfd/wm831x-irq.c
drivers/mfd/wm8350-irq.c
drivers/mfd/wm8994-core.c
drivers/mfd/wm8994-irq.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-pltfm.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/appletalk/cops.c
drivers/net/appletalk/ltpc.c
drivers/net/arcnet/Kconfig
drivers/net/arcnet/Makefile
drivers/net/arcnet/com20020.c
drivers/net/arcnet/com20020_cs.c [moved from drivers/net/pcmcia/com20020_cs.c with 100% similarity]
drivers/net/arm/Kconfig [deleted file]
drivers/net/arm/Makefile [deleted file]
drivers/net/benet/Kconfig [deleted file]
drivers/net/bna/bfi_ctreg.h [deleted file]
drivers/net/bna/bfi_ll.h [deleted file]
drivers/net/bna/bna_ctrl.c [deleted file]
drivers/net/bna/bna_hw.h [deleted file]
drivers/net/bna/bna_txrx.c [deleted file]
drivers/net/bonding/bond_main.c
drivers/net/bonding/bonding.h
drivers/net/caif/caif_hsi.c
drivers/net/caif/caif_spi.c
drivers/net/can/flexcan.c
drivers/net/can/mscan/mscan.c
drivers/net/can/sja1000/plx_pci.c
drivers/net/can/slcan.c
drivers/net/cris/eth_v10.c
drivers/net/dummy.c
drivers/net/ethernet/3com/3c501.c [moved from drivers/net/3c501.c with 99% similarity]
drivers/net/ethernet/3com/3c501.h [moved from drivers/net/3c501.h with 100% similarity]
drivers/net/ethernet/3com/3c509.c [moved from drivers/net/3c509.c with 99% similarity]
drivers/net/ethernet/3com/3c515.c [moved from drivers/net/3c515.c with 99% similarity]
drivers/net/ethernet/3com/3c574_cs.c [moved from drivers/net/pcmcia/3c574_cs.c with 99% similarity]
drivers/net/ethernet/3com/3c589_cs.c [moved from drivers/net/pcmcia/3c589_cs.c with 99% similarity]
drivers/net/ethernet/3com/3c59x.c [moved from drivers/net/3c59x.c with 99% similarity]
drivers/net/ethernet/3com/Kconfig [new file with mode: 0644]
drivers/net/ethernet/3com/Makefile [new file with mode: 0644]
drivers/net/ethernet/3com/typhoon.c [moved from drivers/net/typhoon.c with 99% similarity]
drivers/net/ethernet/3com/typhoon.h [moved from drivers/net/typhoon.h with 100% similarity]
drivers/net/ethernet/8390/3c503.c [moved from drivers/net/3c503.c with 99% similarity]
drivers/net/ethernet/8390/3c503.h [moved from drivers/net/3c503.h with 100% similarity]
drivers/net/ethernet/8390/8390.c [moved from drivers/net/8390.c with 97% similarity]
drivers/net/ethernet/8390/8390.h [moved from drivers/net/8390.h with 100% similarity]
drivers/net/ethernet/8390/8390p.c [moved from drivers/net/8390p.c with 97% similarity]
drivers/net/ethernet/8390/Kconfig [new file with mode: 0644]
drivers/net/ethernet/8390/Makefile [new file with mode: 0644]
drivers/net/ethernet/8390/ac3200.c [moved from drivers/net/ac3200.c with 99% similarity]
drivers/net/ethernet/8390/apne.c [moved from drivers/net/apne.c with 100% similarity]
drivers/net/ethernet/8390/ax88796.c [moved from drivers/net/ax88796.c with 99% similarity]
drivers/net/ethernet/8390/axnet_cs.c [moved from drivers/net/pcmcia/axnet_cs.c with 99% similarity]
drivers/net/ethernet/8390/e2100.c [moved from drivers/net/e2100.c with 99% similarity]
drivers/net/ethernet/8390/es3210.c [moved from drivers/net/es3210.c with 100% similarity]
drivers/net/ethernet/8390/etherh.c [moved from drivers/net/arm/etherh.c with 99% similarity]
drivers/net/ethernet/8390/hp-plus.c [moved from drivers/net/hp-plus.c with 99% similarity]
drivers/net/ethernet/8390/hp.c [moved from drivers/net/hp.c with 100% similarity]
drivers/net/ethernet/8390/hydra.c [moved from drivers/net/hydra.c with 99% similarity]
drivers/net/ethernet/8390/lib8390.c [moved from drivers/net/lib8390.c with 100% similarity]
drivers/net/ethernet/8390/lne390.c [moved from drivers/net/lne390.c with 100% similarity]
drivers/net/ethernet/8390/mac8390.c [moved from drivers/net/mac8390.c with 99% similarity]
drivers/net/ethernet/8390/ne-h8300.c [moved from drivers/net/ne-h8300.c with 99% similarity]
drivers/net/ethernet/8390/ne.c [moved from drivers/net/ne.c with 100% similarity]
drivers/net/ethernet/8390/ne2.c [moved from drivers/net/ne2.c with 100% similarity]
drivers/net/ethernet/8390/ne2k-pci.c [moved from drivers/net/ne2k-pci.c with 99% similarity]
drivers/net/ethernet/8390/ne3210.c [moved from drivers/net/ne3210.c with 100% similarity]
drivers/net/ethernet/8390/pcnet_cs.c [moved from drivers/net/pcmcia/pcnet_cs.c with 99% similarity]
drivers/net/ethernet/8390/smc-mca.c [moved from drivers/net/smc-mca.c with 99% similarity]
drivers/net/ethernet/8390/smc-ultra.c [moved from drivers/net/smc-ultra.c with 99% similarity]
drivers/net/ethernet/8390/smc-ultra32.c [moved from drivers/net/smc-ultra32.c with 99% similarity]
drivers/net/ethernet/8390/stnic.c [moved from drivers/net/stnic.c with 100% similarity]
drivers/net/ethernet/8390/wd.c [moved from drivers/net/wd.c with 99% similarity]
drivers/net/ethernet/8390/zorro8390.c [moved from drivers/net/zorro8390.c with 99% similarity]
drivers/net/ethernet/Kconfig [new file with mode: 0644]
drivers/net/ethernet/Makefile [new file with mode: 0644]
drivers/net/ethernet/adaptec/Kconfig [new file with mode: 0644]
drivers/net/ethernet/adaptec/Makefile [new file with mode: 0644]
drivers/net/ethernet/adaptec/starfire.c [moved from drivers/net/starfire.c with 99% similarity]
drivers/net/ethernet/adi/Kconfig [new file with mode: 0644]
drivers/net/ethernet/adi/Makefile [new file with mode: 0644]
drivers/net/ethernet/adi/bfin_mac.c [moved from drivers/net/bfin_mac.c with 99% similarity]
drivers/net/ethernet/adi/bfin_mac.h [moved from drivers/net/bfin_mac.h with 100% similarity]
drivers/net/ethernet/aeroflex/Kconfig [new file with mode: 0644]
drivers/net/ethernet/aeroflex/Makefile [new file with mode: 0644]
drivers/net/ethernet/aeroflex/greth.c [moved from drivers/net/greth.c with 99% similarity]
drivers/net/ethernet/aeroflex/greth.h [moved from drivers/net/greth.h with 100% similarity]
drivers/net/ethernet/alteon/Kconfig [new file with mode: 0644]
drivers/net/ethernet/alteon/Makefile [new file with mode: 0644]
drivers/net/ethernet/alteon/acenic.c [moved from drivers/net/acenic.c with 99% similarity]
drivers/net/ethernet/alteon/acenic.h [moved from drivers/net/acenic.h with 100% similarity]
drivers/net/ethernet/amd/7990.c [moved from drivers/net/7990.c with 100% similarity]
drivers/net/ethernet/amd/7990.h [moved from drivers/net/7990.h with 100% similarity]
drivers/net/ethernet/amd/Kconfig [new file with mode: 0644]
drivers/net/ethernet/amd/Makefile [new file with mode: 0644]
drivers/net/ethernet/amd/a2065.c [moved from drivers/net/a2065.c with 99% similarity]
drivers/net/ethernet/amd/a2065.h [moved from drivers/net/a2065.h with 100% similarity]
drivers/net/ethernet/amd/am79c961a.c [moved from drivers/net/arm/am79c961a.c with 99% similarity]
drivers/net/ethernet/amd/am79c961a.h [moved from drivers/net/arm/am79c961a.h with 100% similarity]
drivers/net/ethernet/amd/amd8111e.c [moved from drivers/net/amd8111e.c with 99% similarity]
drivers/net/ethernet/amd/amd8111e.h [moved from drivers/net/amd8111e.h with 100% similarity]
drivers/net/ethernet/amd/ariadne.c [moved from drivers/net/ariadne.c with 99% similarity]
drivers/net/ethernet/amd/ariadne.h [moved from drivers/net/ariadne.h with 100% similarity]
drivers/net/ethernet/amd/atarilance.c [moved from drivers/net/atarilance.c with 99% similarity]
drivers/net/ethernet/amd/au1000_eth.c [moved from drivers/net/au1000_eth.c with 99% similarity]
drivers/net/ethernet/amd/au1000_eth.h [moved from drivers/net/au1000_eth.h with 100% similarity]
drivers/net/ethernet/amd/declance.c [moved from drivers/net/declance.c with 99% similarity]
drivers/net/ethernet/amd/depca.c [moved from drivers/net/depca.c with 99% similarity]
drivers/net/ethernet/amd/depca.h [moved from drivers/net/depca.h with 100% similarity]
drivers/net/ethernet/amd/hplance.c [moved from drivers/net/hplance.c with 99% similarity]
drivers/net/ethernet/amd/hplance.h [moved from drivers/net/hplance.h with 100% similarity]
drivers/net/ethernet/amd/lance.c [moved from drivers/net/lance.c with 99% similarity]
drivers/net/ethernet/amd/mvme147.c [moved from drivers/net/mvme147.c with 99% similarity]
drivers/net/ethernet/amd/ni65.c [moved from drivers/net/ni65.c with 99% similarity]
drivers/net/ethernet/amd/ni65.h [moved from drivers/net/ni65.h with 100% similarity]
drivers/net/ethernet/amd/nmclan_cs.c [moved from drivers/net/pcmcia/nmclan_cs.c with 99% similarity]
drivers/net/ethernet/amd/pcnet32.c [moved from drivers/net/pcnet32.c with 99% similarity]
drivers/net/ethernet/amd/sun3lance.c [moved from drivers/net/sun3lance.c with 99% similarity]
drivers/net/ethernet/amd/sunlance.c [moved from drivers/net/sunlance.c with 99% similarity]
drivers/net/ethernet/apple/Kconfig [new file with mode: 0644]
drivers/net/ethernet/apple/Makefile [new file with mode: 0644]
drivers/net/ethernet/apple/bmac.c [moved from drivers/net/bmac.c with 99% similarity]
drivers/net/ethernet/apple/bmac.h [moved from drivers/net/bmac.h with 100% similarity]
drivers/net/ethernet/apple/cs89x0.c [moved from drivers/net/cs89x0.c with 99% similarity]
drivers/net/ethernet/apple/cs89x0.h [moved from drivers/net/cs89x0.h with 100% similarity]
drivers/net/ethernet/apple/mac89x0.c [moved from drivers/net/mac89x0.c with 99% similarity]
drivers/net/ethernet/apple/mace.c [moved from drivers/net/mace.c with 99% similarity]
drivers/net/ethernet/apple/mace.h [moved from drivers/net/mace.h with 100% similarity]
drivers/net/ethernet/apple/macmace.c [moved from drivers/net/macmace.c with 99% similarity]
drivers/net/ethernet/atheros/Kconfig [new file with mode: 0644]
drivers/net/ethernet/atheros/Makefile [new file with mode: 0644]
drivers/net/ethernet/atheros/atl1c/Makefile [moved from drivers/net/atl1c/Makefile with 100% similarity]
drivers/net/ethernet/atheros/atl1c/atl1c.h [moved from drivers/net/atl1c/atl1c.h with 100% similarity]
drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c [moved from drivers/net/atl1c/atl1c_ethtool.c with 100% similarity]
drivers/net/ethernet/atheros/atl1c/atl1c_hw.c [moved from drivers/net/atl1c/atl1c_hw.c with 100% similarity]
drivers/net/ethernet/atheros/atl1c/atl1c_hw.h [moved from drivers/net/atl1c/atl1c_hw.h with 100% similarity]
drivers/net/ethernet/atheros/atl1c/atl1c_main.c [moved from drivers/net/atl1c/atl1c_main.c with 99% similarity]
drivers/net/ethernet/atheros/atl1e/Makefile [moved from drivers/net/atl1e/Makefile with 100% similarity]
drivers/net/ethernet/atheros/atl1e/atl1e.h [moved from drivers/net/atl1e/atl1e.h with 100% similarity]
drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c [moved from drivers/net/atl1e/atl1e_ethtool.c with 100% similarity]
drivers/net/ethernet/atheros/atl1e/atl1e_hw.c [moved from drivers/net/atl1e/atl1e_hw.c with 100% similarity]
drivers/net/ethernet/atheros/atl1e/atl1e_hw.h [moved from drivers/net/atl1e/atl1e_hw.h with 100% similarity]
drivers/net/ethernet/atheros/atl1e/atl1e_main.c [moved from drivers/net/atl1e/atl1e_main.c with 99% similarity]
drivers/net/ethernet/atheros/atl1e/atl1e_param.c [moved from drivers/net/atl1e/atl1e_param.c with 100% similarity]
drivers/net/ethernet/atheros/atlx/Makefile [moved from drivers/net/atlx/Makefile with 100% similarity]
drivers/net/ethernet/atheros/atlx/atl1.c [moved from drivers/net/atlx/atl1.c with 99% similarity]
drivers/net/ethernet/atheros/atlx/atl1.h [moved from drivers/net/atlx/atl1.h with 100% similarity]
drivers/net/ethernet/atheros/atlx/atl2.c [moved from drivers/net/atlx/atl2.c with 99% similarity]
drivers/net/ethernet/atheros/atlx/atl2.h [moved from drivers/net/atlx/atl2.h with 100% similarity]
drivers/net/ethernet/atheros/atlx/atlx.c [moved from drivers/net/atlx/atlx.c with 100% similarity]
drivers/net/ethernet/atheros/atlx/atlx.h [moved from drivers/net/atlx/atlx.h with 100% similarity]
drivers/net/ethernet/broadcom/Kconfig [new file with mode: 0644]
drivers/net/ethernet/broadcom/Makefile [new file with mode: 0644]
drivers/net/ethernet/broadcom/b44.c [moved from drivers/net/b44.c with 99% similarity]
drivers/net/ethernet/broadcom/b44.h [moved from drivers/net/b44.h with 100% similarity]
drivers/net/ethernet/broadcom/bcm63xx_enet.c [moved from drivers/net/bcm63xx_enet.c with 99% similarity]
drivers/net/ethernet/broadcom/bcm63xx_enet.h [moved from drivers/net/bcm63xx_enet.h with 100% similarity]
drivers/net/ethernet/broadcom/bnx2.c [moved from drivers/net/bnx2.c with 99% similarity]
drivers/net/ethernet/broadcom/bnx2.h [moved from drivers/net/bnx2.h with 100% similarity]
drivers/net/ethernet/broadcom/bnx2_fw.h [moved from drivers/net/bnx2_fw.h with 100% similarity]
drivers/net/ethernet/broadcom/bnx2x/Makefile [moved from drivers/net/bnx2x/Makefile with 100% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h [moved from drivers/net/bnx2x/bnx2x.h with 98% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c [moved from drivers/net/bnx2x/bnx2x_cmn.c with 97% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h [moved from drivers/net/bnx2x/bnx2x_cmn.h with 99% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c [moved from drivers/net/bnx2x/bnx2x_dcb.c with 99% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h [moved from drivers/net/bnx2x/bnx2x_dcb.h with 100% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h [moved from drivers/net/bnx2x/bnx2x_dump.h with 100% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c [moved from drivers/net/bnx2x/bnx2x_ethtool.c with 99% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h [moved from drivers/net/bnx2x/bnx2x_fw_defs.h with 100% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h [moved from drivers/net/bnx2x/bnx2x_fw_file_hdr.h with 100% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h [moved from drivers/net/bnx2x/bnx2x_hsi.h with 99% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h [moved from drivers/net/bnx2x/bnx2x_init.h with 100% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h [moved from drivers/net/bnx2x/bnx2x_init_ops.h with 100% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c [moved from drivers/net/bnx2x/bnx2x_link.c with 97% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h [moved from drivers/net/bnx2x/bnx2x_link.h with 99% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c [moved from drivers/net/bnx2x/bnx2x_main.c with 99% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h [moved from drivers/net/bnx2x/bnx2x_reg.h with 99% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c [moved from drivers/net/bnx2x/bnx2x_sp.c with 98% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h [moved from drivers/net/bnx2x/bnx2x_sp.h with 100% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c [moved from drivers/net/bnx2x/bnx2x_stats.c with 98% similarity]
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h [moved from drivers/net/bnx2x/bnx2x_stats.h with 100% similarity]
drivers/net/ethernet/broadcom/cnic.c [moved from drivers/net/cnic.c with 99% similarity]
drivers/net/ethernet/broadcom/cnic.h [moved from drivers/net/cnic.h with 99% similarity]
drivers/net/ethernet/broadcom/cnic_defs.h [moved from drivers/net/cnic_defs.h with 99% similarity]
drivers/net/ethernet/broadcom/cnic_if.h [moved from drivers/net/cnic_if.h with 100% similarity]
drivers/net/ethernet/broadcom/sb1250-mac.c [moved from drivers/net/sb1250-mac.c with 99% similarity]
drivers/net/ethernet/broadcom/tg3.c [moved from drivers/net/tg3.c with 98% similarity]
drivers/net/ethernet/broadcom/tg3.h [moved from drivers/net/tg3.h with 99% similarity]
drivers/net/ethernet/brocade/Kconfig [new file with mode: 0644]
drivers/net/ethernet/brocade/Makefile [new file with mode: 0644]
drivers/net/ethernet/brocade/bna/Kconfig [new file with mode: 0644]
drivers/net/ethernet/brocade/bna/Makefile [moved from drivers/net/bna/Makefile with 52% similarity]
drivers/net/ethernet/brocade/bna/bfa_cee.c [moved from drivers/net/bna/bfa_cee.c with 98% similarity]
drivers/net/ethernet/brocade/bna/bfa_cee.h [moved from drivers/net/bna/bfa_cee.h with 100% similarity]
drivers/net/ethernet/brocade/bna/bfa_cs.h [moved from drivers/net/bna/bfa_cs.h with 100% similarity]
drivers/net/ethernet/brocade/bna/bfa_defs.h [moved from drivers/net/bna/bfa_defs.h with 92% similarity]
drivers/net/ethernet/brocade/bna/bfa_defs_cna.h [moved from drivers/net/bna/bfa_defs_cna.h with 100% similarity]
drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h [moved from drivers/net/bna/bfa_defs_mfg_comm.h with 89% similarity]
drivers/net/ethernet/brocade/bna/bfa_defs_status.h [moved from drivers/net/bna/bfa_defs_status.h with 100% similarity]
drivers/net/ethernet/brocade/bna/bfa_ioc.c [moved from drivers/net/bna/bfa_ioc.c with 87% similarity]
drivers/net/ethernet/brocade/bna/bfa_ioc.h [moved from drivers/net/bna/bfa_ioc.h with 88% similarity]
drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c [moved from drivers/net/bna/bfa_ioc_ct.c with 76% similarity]
drivers/net/ethernet/brocade/bna/bfa_msgq.c [new file with mode: 0644]
drivers/net/ethernet/brocade/bna/bfa_msgq.h [new file with mode: 0644]
drivers/net/ethernet/brocade/bna/bfi.h [moved from drivers/net/bna/bfi.h with 70% similarity]
drivers/net/ethernet/brocade/bna/bfi_cna.h [moved from drivers/net/bna/bfi_cna.h with 100% similarity]
drivers/net/ethernet/brocade/bna/bfi_enet.h [new file with mode: 0644]
drivers/net/ethernet/brocade/bna/bfi_reg.h [new file with mode: 0644]
drivers/net/ethernet/brocade/bna/bna.h [moved from drivers/net/bna/bna.h with 67% similarity]
drivers/net/ethernet/brocade/bna/bna_enet.c [new file with mode: 0644]
drivers/net/ethernet/brocade/bna/bna_hw_defs.h [new file with mode: 0644]
drivers/net/ethernet/brocade/bna/bna_tx_rx.c [new file with mode: 0644]
drivers/net/ethernet/brocade/bna/bna_types.h [moved from drivers/net/bna/bna_types.h with 58% similarity]
drivers/net/ethernet/brocade/bna/bnad.c [moved from drivers/net/bna/bnad.c with 85% similarity]
drivers/net/ethernet/brocade/bna/bnad.h [moved from drivers/net/bna/bnad.h with 89% similarity]
drivers/net/ethernet/brocade/bna/bnad_ethtool.c [moved from drivers/net/bna/bnad_ethtool.c with 67% similarity]
drivers/net/ethernet/brocade/bna/cna.h [moved from drivers/net/bna/cna.h with 68% similarity]
drivers/net/ethernet/brocade/bna/cna_fwimg.c [moved from drivers/net/bna/cna_fwimg.c with 100% similarity]
drivers/net/ethernet/cadence/Kconfig [new file with mode: 0644]
drivers/net/ethernet/cadence/Makefile [new file with mode: 0644]
drivers/net/ethernet/cadence/at91_ether.c [moved from drivers/net/arm/at91_ether.c with 99% similarity]
drivers/net/ethernet/cadence/at91_ether.h [moved from drivers/net/arm/at91_ether.h with 100% similarity]
drivers/net/ethernet/cadence/macb.c [moved from drivers/net/macb.c with 99% similarity]
drivers/net/ethernet/cadence/macb.h [moved from drivers/net/macb.h with 100% similarity]
drivers/net/ethernet/chelsio/Kconfig [new file with mode: 0644]
drivers/net/ethernet/chelsio/Makefile [new file with mode: 0644]
drivers/net/ethernet/chelsio/cxgb/Makefile [moved from drivers/net/chelsio/Makefile with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/common.h [moved from drivers/net/chelsio/common.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/cphy.h [moved from drivers/net/chelsio/cphy.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/cpl5_cmd.h [moved from drivers/net/chelsio/cpl5_cmd.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/cxgb2.c [moved from drivers/net/chelsio/cxgb2.c with 99% similarity]
drivers/net/ethernet/chelsio/cxgb/elmer0.h [moved from drivers/net/chelsio/elmer0.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/espi.c [moved from drivers/net/chelsio/espi.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/espi.h [moved from drivers/net/chelsio/espi.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/fpga_defs.h [moved from drivers/net/chelsio/fpga_defs.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/gmac.h [moved from drivers/net/chelsio/gmac.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/mv88e1xxx.c [moved from drivers/net/chelsio/mv88e1xxx.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/mv88e1xxx.h [moved from drivers/net/chelsio/mv88e1xxx.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/mv88x201x.c [moved from drivers/net/chelsio/mv88x201x.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/my3126.c [moved from drivers/net/chelsio/my3126.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/pm3393.c [moved from drivers/net/chelsio/pm3393.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/regs.h [moved from drivers/net/chelsio/regs.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/sge.c [moved from drivers/net/chelsio/sge.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/sge.h [moved from drivers/net/chelsio/sge.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/subr.c [moved from drivers/net/chelsio/subr.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/suni1x10gexp_regs.h [moved from drivers/net/chelsio/suni1x10gexp_regs.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/tp.c [moved from drivers/net/chelsio/tp.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/tp.h [moved from drivers/net/chelsio/tp.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/vsc7326.c [moved from drivers/net/chelsio/vsc7326.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb/vsc7326_reg.h [moved from drivers/net/chelsio/vsc7326_reg.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/Makefile [moved from drivers/net/cxgb3/Makefile with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/adapter.h [moved from drivers/net/cxgb3/adapter.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/ael1002.c [moved from drivers/net/cxgb3/ael1002.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/aq100x.c [moved from drivers/net/cxgb3/aq100x.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/common.h [moved from drivers/net/cxgb3/common.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/cxgb3_ctl_defs.h [moved from drivers/net/cxgb3/cxgb3_ctl_defs.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/cxgb3_defs.h [moved from drivers/net/cxgb3/cxgb3_defs.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/cxgb3_ioctl.h [moved from drivers/net/cxgb3/cxgb3_ioctl.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c [moved from drivers/net/cxgb3/cxgb3_main.c with 99% similarity]
drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c [moved from drivers/net/cxgb3/cxgb3_offload.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.h [moved from drivers/net/cxgb3/cxgb3_offload.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/firmware_exports.h [moved from drivers/net/cxgb3/firmware_exports.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/l2t.c [moved from drivers/net/cxgb3/l2t.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/l2t.h [moved from drivers/net/cxgb3/l2t.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/mc5.c [moved from drivers/net/cxgb3/mc5.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/regs.h [moved from drivers/net/cxgb3/regs.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/sge.c [moved from drivers/net/cxgb3/sge.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/sge_defs.h [moved from drivers/net/cxgb3/sge_defs.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/t3_cpl.h [moved from drivers/net/cxgb3/t3_cpl.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/t3_hw.c [moved from drivers/net/cxgb3/t3_hw.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/t3cdev.h [moved from drivers/net/cxgb3/t3cdev.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/version.h [moved from drivers/net/cxgb3/version.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/vsc8211.c [moved from drivers/net/cxgb3/vsc8211.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb3/xgmac.c [moved from drivers/net/cxgb3/xgmac.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4/Makefile [moved from drivers/net/cxgb4/Makefile with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h [moved from drivers/net/cxgb4/cxgb4.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c [moved from drivers/net/cxgb4/cxgb4_main.c with 99% similarity]
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h [moved from drivers/net/cxgb4/cxgb4_uld.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4/l2t.c [moved from drivers/net/cxgb4/l2t.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4/l2t.h [moved from drivers/net/cxgb4/l2t.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4/sge.c [moved from drivers/net/cxgb4/sge.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c [moved from drivers/net/cxgb4/t4_hw.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4/t4_hw.h [moved from drivers/net/cxgb4/t4_hw.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4/t4_msg.h [moved from drivers/net/cxgb4/t4_msg.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h [moved from drivers/net/cxgb4/t4_regs.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h [moved from drivers/net/cxgb4/t4fw_api.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4vf/Makefile [moved from drivers/net/cxgb4vf/Makefile with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4vf/adapter.h [moved from drivers/net/cxgb4vf/adapter.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c [moved from drivers/net/cxgb4vf/cxgb4vf_main.c with 99% similarity]
drivers/net/ethernet/chelsio/cxgb4vf/sge.c [moved from drivers/net/cxgb4vf/sge.c with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h [moved from drivers/net/cxgb4vf/t4vf_common.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_defs.h [moved from drivers/net/cxgb4vf/t4vf_defs.h with 100% similarity]
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c [moved from drivers/net/cxgb4vf/t4vf_hw.c with 100% similarity]
drivers/net/ethernet/cirrus/Kconfig [new file with mode: 0644]
drivers/net/ethernet/cirrus/Makefile [new file with mode: 0644]
drivers/net/ethernet/cirrus/ep93xx_eth.c [moved from drivers/net/arm/ep93xx_eth.c with 100% similarity]
drivers/net/ethernet/cisco/Kconfig [new file with mode: 0644]
drivers/net/ethernet/cisco/Makefile [new file with mode: 0644]
drivers/net/ethernet/cisco/enic/Kconfig [new file with mode: 0644]
drivers/net/ethernet/cisco/enic/Makefile [moved from drivers/net/enic/Makefile with 100% similarity]
drivers/net/ethernet/cisco/enic/cq_desc.h [moved from drivers/net/enic/cq_desc.h with 100% similarity]
drivers/net/ethernet/cisco/enic/cq_enet_desc.h [moved from drivers/net/enic/cq_enet_desc.h with 100% similarity]
drivers/net/ethernet/cisco/enic/enic.h [moved from drivers/net/enic/enic.h with 100% similarity]
drivers/net/ethernet/cisco/enic/enic_dev.c [moved from drivers/net/enic/enic_dev.c with 100% similarity]
drivers/net/ethernet/cisco/enic/enic_dev.h [moved from drivers/net/enic/enic_dev.h with 100% similarity]
drivers/net/ethernet/cisco/enic/enic_main.c [moved from drivers/net/enic/enic_main.c with 99% similarity]
drivers/net/ethernet/cisco/enic/enic_pp.c [moved from drivers/net/enic/enic_pp.c with 100% similarity]
drivers/net/ethernet/cisco/enic/enic_pp.h [moved from drivers/net/enic/enic_pp.h with 100% similarity]
drivers/net/ethernet/cisco/enic/enic_res.c [moved from drivers/net/enic/enic_res.c with 100% similarity]
drivers/net/ethernet/cisco/enic/enic_res.h [moved from drivers/net/enic/enic_res.h with 100% similarity]
drivers/net/ethernet/cisco/enic/rq_enet_desc.h [moved from drivers/net/enic/rq_enet_desc.h with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_cq.c [moved from drivers/net/enic/vnic_cq.c with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_cq.h [moved from drivers/net/enic/vnic_cq.h with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_dev.c [moved from drivers/net/enic/vnic_dev.c with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_dev.h [moved from drivers/net/enic/vnic_dev.h with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_devcmd.h [moved from drivers/net/enic/vnic_devcmd.h with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_enet.h [moved from drivers/net/enic/vnic_enet.h with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_intr.c [moved from drivers/net/enic/vnic_intr.c with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_intr.h [moved from drivers/net/enic/vnic_intr.h with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_nic.h [moved from drivers/net/enic/vnic_nic.h with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_resource.h [moved from drivers/net/enic/vnic_resource.h with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_rq.c [moved from drivers/net/enic/vnic_rq.c with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_rq.h [moved from drivers/net/enic/vnic_rq.h with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_rss.h [moved from drivers/net/enic/vnic_rss.h with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_stats.h [moved from drivers/net/enic/vnic_stats.h with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_vic.c [moved from drivers/net/enic/vnic_vic.c with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_vic.h [moved from drivers/net/enic/vnic_vic.h with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_wq.c [moved from drivers/net/enic/vnic_wq.c with 100% similarity]
drivers/net/ethernet/cisco/enic/vnic_wq.h [moved from drivers/net/enic/vnic_wq.h with 100% similarity]
drivers/net/ethernet/cisco/enic/wq_enet_desc.h [moved from drivers/net/enic/wq_enet_desc.h with 100% similarity]
drivers/net/ethernet/davicom/Kconfig [new file with mode: 0644]
drivers/net/ethernet/davicom/Makefile [new file with mode: 0644]
drivers/net/ethernet/davicom/dm9000.c [moved from drivers/net/dm9000.c with 99% similarity]
drivers/net/ethernet/davicom/dm9000.h [moved from drivers/net/dm9000.h with 100% similarity]
drivers/net/ethernet/dec/Kconfig [new file with mode: 0644]
drivers/net/ethernet/dec/Makefile [new file with mode: 0644]
drivers/net/ethernet/dec/ewrk3.c [moved from drivers/net/ewrk3.c with 99% similarity]
drivers/net/ethernet/dec/ewrk3.h [moved from drivers/net/ewrk3.h with 100% similarity]
drivers/net/ethernet/dec/tulip/21142.c [moved from drivers/net/tulip/21142.c with 100% similarity]
drivers/net/ethernet/dec/tulip/Kconfig [moved from drivers/net/tulip/Kconfig with 96% similarity]
drivers/net/ethernet/dec/tulip/Makefile [moved from drivers/net/tulip/Makefile with 100% similarity]
drivers/net/ethernet/dec/tulip/de2104x.c [moved from drivers/net/tulip/de2104x.c with 99% similarity]
drivers/net/ethernet/dec/tulip/de4x5.c [moved from drivers/net/tulip/de4x5.c with 99% similarity]
drivers/net/ethernet/dec/tulip/de4x5.h [moved from drivers/net/tulip/de4x5.h with 100% similarity]
drivers/net/ethernet/dec/tulip/dmfe.c [moved from drivers/net/tulip/dmfe.c with 99% similarity]
drivers/net/ethernet/dec/tulip/eeprom.c [moved from drivers/net/tulip/eeprom.c with 100% similarity]
drivers/net/ethernet/dec/tulip/interrupt.c [moved from drivers/net/tulip/interrupt.c with 100% similarity]
drivers/net/ethernet/dec/tulip/media.c [moved from drivers/net/tulip/media.c with 100% similarity]
drivers/net/ethernet/dec/tulip/pnic.c [moved from drivers/net/tulip/pnic.c with 100% similarity]
drivers/net/ethernet/dec/tulip/pnic2.c [moved from drivers/net/tulip/pnic2.c with 100% similarity]
drivers/net/ethernet/dec/tulip/timer.c [moved from drivers/net/tulip/timer.c with 100% similarity]
drivers/net/ethernet/dec/tulip/tulip.h [moved from drivers/net/tulip/tulip.h with 100% similarity]
drivers/net/ethernet/dec/tulip/tulip_core.c [moved from drivers/net/tulip/tulip_core.c with 99% similarity]
drivers/net/ethernet/dec/tulip/uli526x.c [moved from drivers/net/tulip/uli526x.c with 99% similarity]
drivers/net/ethernet/dec/tulip/winbond-840.c [moved from drivers/net/tulip/winbond-840.c with 99% similarity]
drivers/net/ethernet/dec/tulip/xircom_cb.c [moved from drivers/net/tulip/xircom_cb.c with 100% similarity]
drivers/net/ethernet/dlink/Kconfig [new file with mode: 0644]
drivers/net/ethernet/dlink/Makefile [new file with mode: 0644]
drivers/net/ethernet/dlink/de600.c [moved from drivers/net/de600.c with 100% similarity]
drivers/net/ethernet/dlink/de600.h [moved from drivers/net/de600.h with 100% similarity]
drivers/net/ethernet/dlink/de620.c [moved from drivers/net/de620.c with 99% similarity]
drivers/net/ethernet/dlink/de620.h [moved from drivers/net/de620.h with 100% similarity]
drivers/net/ethernet/dlink/dl2k.c [moved from drivers/net/dl2k.c with 95% similarity]
drivers/net/ethernet/dlink/dl2k.h [moved from drivers/net/dl2k.h with 81% similarity]
drivers/net/ethernet/dlink/sundance.c [moved from drivers/net/sundance.c with 99% similarity]
drivers/net/ethernet/dnet.c [moved from drivers/net/dnet.c with 100% similarity]
drivers/net/ethernet/dnet.h [moved from drivers/net/dnet.h with 100% similarity]
drivers/net/ethernet/emulex/Kconfig [new file with mode: 0644]
drivers/net/ethernet/emulex/Makefile [new file with mode: 0644]
drivers/net/ethernet/emulex/benet/Kconfig [new file with mode: 0644]
drivers/net/ethernet/emulex/benet/Makefile [moved from drivers/net/benet/Makefile with 100% similarity]
drivers/net/ethernet/emulex/benet/be.h [moved from drivers/net/benet/be.h with 84% similarity]
drivers/net/ethernet/emulex/benet/be_cmds.c [moved from drivers/net/benet/be_cmds.c with 94% similarity]
drivers/net/ethernet/emulex/benet/be_cmds.h [moved from drivers/net/benet/be_cmds.h with 95% similarity]
drivers/net/ethernet/emulex/benet/be_ethtool.c [moved from drivers/net/benet/be_ethtool.c with 85% similarity]
drivers/net/ethernet/emulex/benet/be_hw.h [moved from drivers/net/benet/be_hw.h with 94% similarity]
drivers/net/ethernet/emulex/benet/be_main.c [moved from drivers/net/benet/be_main.c with 90% similarity]
drivers/net/ethernet/ethoc.c [moved from drivers/net/ethoc.c with 99% similarity]
drivers/net/ethernet/faraday/Kconfig [new file with mode: 0644]
drivers/net/ethernet/faraday/Makefile [new file with mode: 0644]
drivers/net/ethernet/faraday/ftgmac100.c [moved from drivers/net/ftgmac100.c with 100% similarity]
drivers/net/ethernet/faraday/ftgmac100.h [moved from drivers/net/ftgmac100.h with 100% similarity]
drivers/net/ethernet/faraday/ftmac100.c [moved from drivers/net/ftmac100.c with 100% similarity]
drivers/net/ethernet/faraday/ftmac100.h [moved from drivers/net/ftmac100.h with 100% similarity]
drivers/net/ethernet/fealnx.c [moved from drivers/net/fealnx.c with 99% similarity]
drivers/net/ethernet/freescale/Kconfig [new file with mode: 0644]
drivers/net/ethernet/freescale/Makefile [new file with mode: 0644]
drivers/net/ethernet/freescale/fec.c [moved from drivers/net/fec.c with 93% similarity]
drivers/net/ethernet/freescale/fec.h [moved from drivers/net/fec.h with 100% similarity]
drivers/net/ethernet/freescale/fec_mpc52xx.c [moved from drivers/net/fec_mpc52xx.c with 99% similarity]
drivers/net/ethernet/freescale/fec_mpc52xx.h [moved from drivers/net/fec_mpc52xx.h with 100% similarity]
drivers/net/ethernet/freescale/fec_mpc52xx_phy.c [moved from drivers/net/fec_mpc52xx_phy.c with 100% similarity]
drivers/net/ethernet/freescale/fs_enet/Kconfig [moved from drivers/net/fs_enet/Kconfig with 91% similarity]
drivers/net/ethernet/freescale/fs_enet/Makefile [moved from drivers/net/fs_enet/Makefile with 100% similarity]
drivers/net/ethernet/freescale/fs_enet/fec.h [moved from drivers/net/fs_enet/fec.h with 100% similarity]
drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c [moved from drivers/net/fs_enet/fs_enet-main.c with 99% similarity]
drivers/net/ethernet/freescale/fs_enet/fs_enet.h [moved from drivers/net/fs_enet/fs_enet.h with 100% similarity]
drivers/net/ethernet/freescale/fs_enet/mac-fcc.c [moved from drivers/net/fs_enet/mac-fcc.c with 100% similarity]
drivers/net/ethernet/freescale/fs_enet/mac-fec.c [moved from drivers/net/fs_enet/mac-fec.c with 100% similarity]
drivers/net/ethernet/freescale/fs_enet/mac-scc.c [moved from drivers/net/fs_enet/mac-scc.c with 100% similarity]
drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c [moved from drivers/net/fs_enet/mii-bitbang.c with 100% similarity]
drivers/net/ethernet/freescale/fs_enet/mii-fec.c [moved from drivers/net/fs_enet/mii-fec.c with 100% similarity]
drivers/net/ethernet/freescale/fsl_pq_mdio.c [moved from drivers/net/fsl_pq_mdio.c with 100% similarity]
drivers/net/ethernet/freescale/fsl_pq_mdio.h [moved from drivers/net/fsl_pq_mdio.h with 100% similarity]
drivers/net/ethernet/freescale/gianfar.c [moved from drivers/net/gianfar.c with 99% similarity]
drivers/net/ethernet/freescale/gianfar.h [moved from drivers/net/gianfar.h with 100% similarity]
drivers/net/ethernet/freescale/gianfar_ethtool.c [moved from drivers/net/gianfar_ethtool.c with 99% similarity]
drivers/net/ethernet/freescale/gianfar_ptp.c [moved from drivers/net/gianfar_ptp.c with 98% similarity]
drivers/net/ethernet/freescale/gianfar_sysfs.c [moved from drivers/net/gianfar_sysfs.c with 100% similarity]
drivers/net/ethernet/freescale/ucc_geth.c [moved from drivers/net/ucc_geth.c with 99% similarity]
drivers/net/ethernet/freescale/ucc_geth.h [moved from drivers/net/ucc_geth.h with 100% similarity]
drivers/net/ethernet/freescale/ucc_geth_ethtool.c [moved from drivers/net/ucc_geth_ethtool.c with 100% similarity]
drivers/net/ethernet/fujitsu/Kconfig [new file with mode: 0644]
drivers/net/ethernet/fujitsu/Makefile [new file with mode: 0644]
drivers/net/ethernet/fujitsu/at1700.c [moved from drivers/net/at1700.c with 99% similarity]
drivers/net/ethernet/fujitsu/eth16i.c [moved from drivers/net/eth16i.c with 99% similarity]
drivers/net/ethernet/fujitsu/fmvj18x_cs.c [moved from drivers/net/pcmcia/fmvj18x_cs.c with 99% similarity]
drivers/net/ethernet/hp/Kconfig [new file with mode: 0644]
drivers/net/ethernet/hp/Makefile [new file with mode: 0644]
drivers/net/ethernet/hp/hp100.c [moved from drivers/net/hp100.c with 99% similarity]
drivers/net/ethernet/hp/hp100.h [moved from drivers/net/hp100.h with 100% similarity]
drivers/net/ethernet/i825xx/3c505.c [moved from drivers/net/3c505.c with 99% similarity]
drivers/net/ethernet/i825xx/3c505.h [moved from drivers/net/3c505.h with 100% similarity]
drivers/net/ethernet/i825xx/3c507.c [moved from drivers/net/3c507.c with 100% similarity]
drivers/net/ethernet/i825xx/3c523.c [moved from drivers/net/3c523.c with 99% similarity]
drivers/net/ethernet/i825xx/3c523.h [moved from drivers/net/3c523.h with 100% similarity]
drivers/net/ethernet/i825xx/3c527.c [moved from drivers/net/3c527.c with 99% similarity]
drivers/net/ethernet/i825xx/3c527.h [moved from drivers/net/3c527.h with 100% similarity]
drivers/net/ethernet/i825xx/82596.c [moved from drivers/net/82596.c with 99% similarity]
drivers/net/ethernet/i825xx/Kconfig [new file with mode: 0644]
drivers/net/ethernet/i825xx/Makefile [new file with mode: 0644]
drivers/net/ethernet/i825xx/eepro.c [moved from drivers/net/eepro.c with 99% similarity]
drivers/net/ethernet/i825xx/eexpress.c [moved from drivers/net/eexpress.c with 99% similarity]
drivers/net/ethernet/i825xx/eexpress.h [moved from drivers/net/eexpress.h with 100% similarity]
drivers/net/ethernet/i825xx/ether1.c [moved from drivers/net/arm/ether1.c with 99% similarity]
drivers/net/ethernet/i825xx/ether1.h [moved from drivers/net/arm/ether1.h with 100% similarity]
drivers/net/ethernet/i825xx/lasi_82596.c [moved from drivers/net/lasi_82596.c with 100% similarity]
drivers/net/ethernet/i825xx/lib82596.c [moved from drivers/net/lib82596.c with 99% similarity]
drivers/net/ethernet/i825xx/lp486e.c [moved from drivers/net/lp486e.c with 99% similarity]
drivers/net/ethernet/i825xx/ni52.c [moved from drivers/net/ni52.c with 99% similarity]
drivers/net/ethernet/i825xx/ni52.h [moved from drivers/net/ni52.h with 100% similarity]
drivers/net/ethernet/i825xx/sni_82596.c [moved from drivers/net/sni_82596.c with 100% similarity]
drivers/net/ethernet/i825xx/sun3_82586.c [moved from drivers/net/sun3_82586.c with 99% similarity]
drivers/net/ethernet/i825xx/sun3_82586.h [moved from drivers/net/sun3_82586.h with 100% similarity]
drivers/net/ethernet/i825xx/znet.c [moved from drivers/net/znet.c with 99% similarity]
drivers/net/ethernet/ibm/Kconfig [new file with mode: 0644]
drivers/net/ethernet/ibm/Makefile [new file with mode: 0644]
drivers/net/ethernet/ibm/ehea/Makefile [moved from drivers/net/ehea/Makefile with 100% similarity]
drivers/net/ethernet/ibm/ehea/ehea.h [moved from drivers/net/ehea/ehea.h with 100% similarity]
drivers/net/ethernet/ibm/ehea/ehea_ethtool.c [moved from drivers/net/ehea/ehea_ethtool.c with 100% similarity]
drivers/net/ethernet/ibm/ehea/ehea_hw.h [moved from drivers/net/ehea/ehea_hw.h with 100% similarity]
drivers/net/ethernet/ibm/ehea/ehea_main.c [moved from drivers/net/ehea/ehea_main.c with 99% similarity]
drivers/net/ethernet/ibm/ehea/ehea_phyp.c [moved from drivers/net/ehea/ehea_phyp.c with 100% similarity]
drivers/net/ethernet/ibm/ehea/ehea_phyp.h [moved from drivers/net/ehea/ehea_phyp.h with 100% similarity]
drivers/net/ethernet/ibm/ehea/ehea_qmr.c [moved from drivers/net/ehea/ehea_qmr.c with 100% similarity]
drivers/net/ethernet/ibm/ehea/ehea_qmr.h [moved from drivers/net/ehea/ehea_qmr.h with 100% similarity]
drivers/net/ethernet/ibm/emac/Kconfig [moved from drivers/net/ibm_newemac/Kconfig with 63% similarity]
drivers/net/ethernet/ibm/emac/Makefile [new file with mode: 0644]
drivers/net/ethernet/ibm/emac/core.c [moved from drivers/net/ibm_newemac/core.c with 98% similarity]
drivers/net/ethernet/ibm/emac/core.h [moved from drivers/net/ibm_newemac/core.h with 97% similarity]
drivers/net/ethernet/ibm/emac/debug.c [moved from drivers/net/ibm_newemac/debug.c with 100% similarity]
drivers/net/ethernet/ibm/emac/debug.h [moved from drivers/net/ibm_newemac/debug.h with 98% similarity]
drivers/net/ethernet/ibm/emac/emac.h [moved from drivers/net/ibm_newemac/emac.h with 95% similarity]
drivers/net/ethernet/ibm/emac/mal.c [moved from drivers/net/ibm_newemac/mal.c with 99% similarity]
drivers/net/ethernet/ibm/emac/mal.h [moved from drivers/net/ibm_newemac/mal.h with 99% similarity]
drivers/net/ethernet/ibm/emac/phy.c [moved from drivers/net/ibm_newemac/phy.c with 98% similarity]
drivers/net/ethernet/ibm/emac/phy.h [moved from drivers/net/ibm_newemac/phy.h with 100% similarity]
drivers/net/ethernet/ibm/emac/rgmii.c [moved from drivers/net/ibm_newemac/rgmii.c with 100% similarity]
drivers/net/ethernet/ibm/emac/rgmii.h [moved from drivers/net/ibm_newemac/rgmii.h with 96% similarity]
drivers/net/ethernet/ibm/emac/tah.c [moved from drivers/net/ibm_newemac/tah.c with 100% similarity]
drivers/net/ethernet/ibm/emac/tah.h [moved from drivers/net/ibm_newemac/tah.h with 97% similarity]
drivers/net/ethernet/ibm/emac/zmii.c [moved from drivers/net/ibm_newemac/zmii.c with 100% similarity]
drivers/net/ethernet/ibm/emac/zmii.h [moved from drivers/net/ibm_newemac/zmii.h with 96% similarity]
drivers/net/ethernet/ibm/ibmveth.c [moved from drivers/net/ibmveth.c with 99% similarity]
drivers/net/ethernet/ibm/ibmveth.h [moved from drivers/net/ibmveth.h with 100% similarity]
drivers/net/ethernet/ibm/iseries_veth.c [moved from drivers/net/iseries_veth.c with 99% similarity]
drivers/net/ethernet/icplus/Kconfig [new file with mode: 0644]
drivers/net/ethernet/icplus/Makefile [new file with mode: 0644]
drivers/net/ethernet/icplus/ipg.c [moved from drivers/net/ipg.c with 92% similarity]
drivers/net/ethernet/icplus/ipg.h [moved from drivers/net/ipg.h with 100% similarity]
drivers/net/ethernet/intel/Kconfig [new file with mode: 0644]
drivers/net/ethernet/intel/Makefile [new file with mode: 0644]
drivers/net/ethernet/intel/e100.c [moved from drivers/net/e100.c with 99% similarity]
drivers/net/ethernet/intel/e1000/Makefile [moved from drivers/net/e1000/Makefile with 100% similarity]
drivers/net/ethernet/intel/e1000/e1000.h [moved from drivers/net/e1000/e1000.h with 99% similarity]
drivers/net/ethernet/intel/e1000/e1000_ethtool.c [moved from drivers/net/e1000/e1000_ethtool.c with 99% similarity]
drivers/net/ethernet/intel/e1000/e1000_hw.c [moved from drivers/net/e1000/e1000_hw.c with 99% similarity]
drivers/net/ethernet/intel/e1000/e1000_hw.h [moved from drivers/net/e1000/e1000_hw.h with 100% similarity]
drivers/net/ethernet/intel/e1000/e1000_main.c [moved from drivers/net/e1000/e1000_main.c with 99% similarity]
drivers/net/ethernet/intel/e1000/e1000_osdep.h [moved from drivers/net/e1000/e1000_osdep.h with 100% similarity]
drivers/net/ethernet/intel/e1000/e1000_param.c [moved from drivers/net/e1000/e1000_param.c with 100% similarity]
drivers/net/ethernet/intel/e1000e/80003es2lan.c [moved from drivers/net/e1000e/es2lan.c with 99% similarity]
drivers/net/ethernet/intel/e1000e/82571.c [moved from drivers/net/e1000e/82571.c with 99% similarity]
drivers/net/ethernet/intel/e1000e/Makefile [moved from drivers/net/e1000e/Makefile with 96% similarity]
drivers/net/ethernet/intel/e1000e/defines.h [moved from drivers/net/e1000e/defines.h with 100% similarity]
drivers/net/ethernet/intel/e1000e/e1000.h [moved from drivers/net/e1000e/e1000.h with 98% similarity]
drivers/net/ethernet/intel/e1000e/ethtool.c [moved from drivers/net/e1000e/ethtool.c with 96% similarity]
drivers/net/ethernet/intel/e1000e/hw.h [moved from drivers/net/e1000e/hw.h with 100% similarity]
drivers/net/ethernet/intel/e1000e/ich8lan.c [moved from drivers/net/e1000e/ich8lan.c with 98% similarity]
drivers/net/ethernet/intel/e1000e/lib.c [moved from drivers/net/e1000e/lib.c with 99% similarity]
drivers/net/ethernet/intel/e1000e/netdev.c [moved from drivers/net/e1000e/netdev.c with 95% similarity]
drivers/net/ethernet/intel/e1000e/param.c [moved from drivers/net/e1000e/param.c with 100% similarity]
drivers/net/ethernet/intel/e1000e/phy.c [moved from drivers/net/e1000e/phy.c with 99% similarity]
drivers/net/ethernet/intel/igb/Makefile [moved from drivers/net/igb/Makefile with 100% similarity]
drivers/net/ethernet/intel/igb/e1000_82575.c [moved from drivers/net/igb/e1000_82575.c with 100% similarity]
drivers/net/ethernet/intel/igb/e1000_82575.h [moved from drivers/net/igb/e1000_82575.h with 100% similarity]
drivers/net/ethernet/intel/igb/e1000_defines.h [moved from drivers/net/igb/e1000_defines.h with 100% similarity]
drivers/net/ethernet/intel/igb/e1000_hw.h [moved from drivers/net/igb/e1000_hw.h with 100% similarity]
drivers/net/ethernet/intel/igb/e1000_mac.c [moved from drivers/net/igb/e1000_mac.c with 100% similarity]
drivers/net/ethernet/intel/igb/e1000_mac.h [moved from drivers/net/igb/e1000_mac.h with 100% similarity]
drivers/net/ethernet/intel/igb/e1000_mbx.c [moved from drivers/net/igb/e1000_mbx.c with 100% similarity]
drivers/net/ethernet/intel/igb/e1000_mbx.h [moved from drivers/net/igb/e1000_mbx.h with 100% similarity]
drivers/net/ethernet/intel/igb/e1000_nvm.c [moved from drivers/net/igb/e1000_nvm.c with 99% similarity]
drivers/net/ethernet/intel/igb/e1000_nvm.h [moved from drivers/net/igb/e1000_nvm.h with 100% similarity]
drivers/net/ethernet/intel/igb/e1000_phy.c [moved from drivers/net/igb/e1000_phy.c with 100% similarity]
drivers/net/ethernet/intel/igb/e1000_phy.h [moved from drivers/net/igb/e1000_phy.h with 100% similarity]
drivers/net/ethernet/intel/igb/e1000_regs.h [moved from drivers/net/igb/e1000_regs.h with 100% similarity]
drivers/net/ethernet/intel/igb/igb.h [moved from drivers/net/igb/igb.h with 100% similarity]
drivers/net/ethernet/intel/igb/igb_ethtool.c [moved from drivers/net/igb/igb_ethtool.c with 99% similarity]
drivers/net/ethernet/intel/igb/igb_main.c [moved from drivers/net/igb/igb_main.c with 99% similarity]
drivers/net/ethernet/intel/igbvf/Makefile [moved from drivers/net/igbvf/Makefile with 100% similarity]
drivers/net/ethernet/intel/igbvf/defines.h [moved from drivers/net/igbvf/defines.h with 100% similarity]
drivers/net/ethernet/intel/igbvf/ethtool.c [moved from drivers/net/igbvf/ethtool.c with 100% similarity]
drivers/net/ethernet/intel/igbvf/igbvf.h [moved from drivers/net/igbvf/igbvf.h with 100% similarity]
drivers/net/ethernet/intel/igbvf/mbx.c [moved from drivers/net/igbvf/mbx.c with 100% similarity]
drivers/net/ethernet/intel/igbvf/mbx.h [moved from drivers/net/igbvf/mbx.h with 100% similarity]
drivers/net/ethernet/intel/igbvf/netdev.c [moved from drivers/net/igbvf/netdev.c with 99% similarity]
drivers/net/ethernet/intel/igbvf/regs.h [moved from drivers/net/igbvf/regs.h with 100% similarity]
drivers/net/ethernet/intel/igbvf/vf.c [moved from drivers/net/igbvf/vf.c with 100% similarity]
drivers/net/ethernet/intel/igbvf/vf.h [moved from drivers/net/igbvf/vf.h with 100% similarity]
drivers/net/ethernet/intel/ixgb/Makefile [moved from drivers/net/ixgb/Makefile with 100% similarity]
drivers/net/ethernet/intel/ixgb/ixgb.h [moved from drivers/net/ixgb/ixgb.h with 100% similarity]
drivers/net/ethernet/intel/ixgb/ixgb_ee.c [moved from drivers/net/ixgb/ixgb_ee.c with 98% similarity]
drivers/net/ethernet/intel/ixgb/ixgb_ee.h [moved from drivers/net/ixgb/ixgb_ee.h with 100% similarity]
drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c [moved from drivers/net/ixgb/ixgb_ethtool.c with 100% similarity]
drivers/net/ethernet/intel/ixgb/ixgb_hw.c [moved from drivers/net/ixgb/ixgb_hw.c with 99% similarity]
drivers/net/ethernet/intel/ixgb/ixgb_hw.h [moved from drivers/net/ixgb/ixgb_hw.h with 100% similarity]
drivers/net/ethernet/intel/ixgb/ixgb_ids.h [moved from drivers/net/ixgb/ixgb_ids.h with 100% similarity]
drivers/net/ethernet/intel/ixgb/ixgb_main.c [moved from drivers/net/ixgb/ixgb_main.c with 99% similarity]
drivers/net/ethernet/intel/ixgb/ixgb_osdep.h [moved from drivers/net/ixgb/ixgb_osdep.h with 100% similarity]
drivers/net/ethernet/intel/ixgb/ixgb_param.c [moved from drivers/net/ixgb/ixgb_param.c with 100% similarity]
drivers/net/ethernet/intel/ixgbe/Makefile [moved from drivers/net/ixgbe/Makefile with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe.h [moved from drivers/net/ixgbe/ixgbe.h with 96% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c [moved from drivers/net/ixgbe/ixgbe_82598.c with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c [moved from drivers/net/ixgbe/ixgbe_82599.c with 96% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c [moved from drivers/net/ixgbe/ixgbe_common.c with 99% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h [moved from drivers/net/ixgbe/ixgbe_common.h with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c [moved from drivers/net/ixgbe/ixgbe_dcb.c with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h [moved from drivers/net/ixgbe/ixgbe_dcb.h with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c [moved from drivers/net/ixgbe/ixgbe_dcb_82598.c with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h [moved from drivers/net/ixgbe/ixgbe_dcb_82598.h with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c [moved from drivers/net/ixgbe/ixgbe_dcb_82599.c with 99% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h [moved from drivers/net/ixgbe/ixgbe_dcb_82599.h with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c [moved from drivers/net/ixgbe/ixgbe_dcb_nl.c with 95% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c [moved from drivers/net/ixgbe/ixgbe_ethtool.c with 99% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c [moved from drivers/net/ixgbe/ixgbe_fcoe.c with 99% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h [moved from drivers/net/ixgbe/ixgbe_fcoe.h with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c [moved from drivers/net/ixgbe/ixgbe_main.c with 94% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c [moved from drivers/net/ixgbe/ixgbe_mbx.c with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h [moved from drivers/net/ixgbe/ixgbe_mbx.h with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c [moved from drivers/net/ixgbe/ixgbe_phy.c with 99% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h [moved from drivers/net/ixgbe/ixgbe_phy.h with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c [moved from drivers/net/ixgbe/ixgbe_sriov.c with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h [moved from drivers/net/ixgbe/ixgbe_sriov.h with 100% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h [moved from drivers/net/ixgbe/ixgbe_type.h with 99% similarity]
drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c [moved from drivers/net/ixgbe/ixgbe_x540.c with 99% similarity]
drivers/net/ethernet/intel/ixgbevf/Makefile [moved from drivers/net/ixgbevf/Makefile with 100% similarity]
drivers/net/ethernet/intel/ixgbevf/defines.h [moved from drivers/net/ixgbevf/defines.h with 100% similarity]
drivers/net/ethernet/intel/ixgbevf/ethtool.c [moved from drivers/net/ixgbevf/ethtool.c with 94% similarity]
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h [moved from drivers/net/ixgbevf/ixgbevf.h with 98% similarity]
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c [moved from drivers/net/ixgbevf/ixgbevf_main.c with 98% similarity]
drivers/net/ethernet/intel/ixgbevf/mbx.c [moved from drivers/net/ixgbevf/mbx.c with 100% similarity]
drivers/net/ethernet/intel/ixgbevf/mbx.h [moved from drivers/net/ixgbevf/mbx.h with 100% similarity]
drivers/net/ethernet/intel/ixgbevf/regs.h [moved from drivers/net/ixgbevf/regs.h with 100% similarity]
drivers/net/ethernet/intel/ixgbevf/vf.c [moved from drivers/net/ixgbevf/vf.c with 100% similarity]
drivers/net/ethernet/intel/ixgbevf/vf.h [moved from drivers/net/ixgbevf/vf.h with 100% similarity]
drivers/net/ethernet/jme.c [moved from drivers/net/jme.c with 99% similarity]
drivers/net/ethernet/jme.h [moved from drivers/net/jme.h with 100% similarity]
drivers/net/ethernet/korina.c [moved from drivers/net/korina.c with 99% similarity]
drivers/net/ethernet/lantiq_etop.c [moved from drivers/net/lantiq_etop.c with 99% similarity]
drivers/net/ethernet/marvell/Kconfig [new file with mode: 0644]
drivers/net/ethernet/marvell/Makefile [new file with mode: 0644]
drivers/net/ethernet/marvell/mv643xx_eth.c [moved from drivers/net/mv643xx_eth.c with 99% similarity]
drivers/net/ethernet/marvell/pxa168_eth.c [moved from drivers/net/pxa168_eth.c with 100% similarity]
drivers/net/ethernet/marvell/skge.c [moved from drivers/net/skge.c with 99% similarity]
drivers/net/ethernet/marvell/skge.h [moved from drivers/net/skge.h with 100% similarity]
drivers/net/ethernet/marvell/sky2.c [moved from drivers/net/sky2.c with 99% similarity]
drivers/net/ethernet/marvell/sky2.h [moved from drivers/net/sky2.h with 100% similarity]
drivers/net/ethernet/mellanox/Kconfig [new file with mode: 0644]
drivers/net/ethernet/mellanox/Makefile [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlx4/Kconfig [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlx4/Makefile [moved from drivers/net/mlx4/Makefile with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/alloc.c [moved from drivers/net/mlx4/alloc.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/catas.c [moved from drivers/net/mlx4/catas.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/cmd.c [moved from drivers/net/mlx4/cmd.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/cq.c [moved from drivers/net/mlx4/cq.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/en_cq.c [moved from drivers/net/mlx4/en_cq.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c [moved from drivers/net/mlx4/en_ethtool.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/en_main.c [moved from drivers/net/mlx4/en_main.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/en_netdev.c [moved from drivers/net/mlx4/en_netdev.c with 99% similarity]
drivers/net/ethernet/mellanox/mlx4/en_port.c [moved from drivers/net/mlx4/en_port.c with 99% similarity]
drivers/net/ethernet/mellanox/mlx4/en_port.h [moved from drivers/net/mlx4/en_port.h with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/en_resources.c [moved from drivers/net/mlx4/en_resources.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/en_rx.c [moved from drivers/net/mlx4/en_rx.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/en_selftest.c [moved from drivers/net/mlx4/en_selftest.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/en_tx.c [moved from drivers/net/mlx4/en_tx.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/eq.c [moved from drivers/net/mlx4/eq.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/fw.c [moved from drivers/net/mlx4/fw.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/fw.h [moved from drivers/net/mlx4/fw.h with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/icm.c [moved from drivers/net/mlx4/icm.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/icm.h [moved from drivers/net/mlx4/icm.h with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/intf.c [moved from drivers/net/mlx4/intf.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/main.c [moved from drivers/net/mlx4/main.c with 99% similarity]
drivers/net/ethernet/mellanox/mlx4/mcg.c [moved from drivers/net/mlx4/mcg.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/mlx4.h [moved from drivers/net/mlx4/mlx4.h with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h [moved from drivers/net/mlx4/mlx4_en.h with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/mr.c [moved from drivers/net/mlx4/mr.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/pd.c [moved from drivers/net/mlx4/pd.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/port.c [moved from drivers/net/mlx4/port.c with 98% similarity]
drivers/net/ethernet/mellanox/mlx4/profile.c [moved from drivers/net/mlx4/profile.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/qp.c [moved from drivers/net/mlx4/qp.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/reset.c [moved from drivers/net/mlx4/reset.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/sense.c [moved from drivers/net/mlx4/sense.c with 100% similarity]
drivers/net/ethernet/mellanox/mlx4/srq.c [moved from drivers/net/mlx4/srq.c with 100% similarity]
drivers/net/ethernet/micrel/Kconfig [new file with mode: 0644]
drivers/net/ethernet/micrel/Makefile [new file with mode: 0644]
drivers/net/ethernet/micrel/ks8695net.c [moved from drivers/net/arm/ks8695net.c with 99% similarity]
drivers/net/ethernet/micrel/ks8695net.h [moved from drivers/net/arm/ks8695net.h with 100% similarity]
drivers/net/ethernet/micrel/ks8842.c [moved from drivers/net/ks8842.c with 100% similarity]
drivers/net/ethernet/micrel/ks8851.c [moved from drivers/net/ks8851.c with 100% similarity]
drivers/net/ethernet/micrel/ks8851.h [moved from drivers/net/ks8851.h with 100% similarity]
drivers/net/ethernet/micrel/ks8851_mll.c [moved from drivers/net/ks8851_mll.c with 100% similarity]
drivers/net/ethernet/micrel/ksz884x.c [moved from drivers/net/ksz884x.c with 100% similarity]
drivers/net/ethernet/microchip/Kconfig [new file with mode: 0644]
drivers/net/ethernet/microchip/Makefile [new file with mode: 0644]
drivers/net/ethernet/microchip/enc28j60.c [moved from drivers/net/enc28j60.c with 99% similarity]
drivers/net/ethernet/microchip/enc28j60_hw.h [moved from drivers/net/enc28j60_hw.h with 100% similarity]
drivers/net/ethernet/mipsnet.c [moved from drivers/net/mipsnet.c with 99% similarity]
drivers/net/ethernet/myricom/Kconfig [new file with mode: 0644]
drivers/net/ethernet/myricom/Makefile [new file with mode: 0644]
drivers/net/ethernet/myricom/myri10ge/Makefile [moved from drivers/net/myri10ge/Makefile with 100% similarity]
drivers/net/ethernet/myricom/myri10ge/myri10ge.c [moved from drivers/net/myri10ge/myri10ge.c with 99% similarity]
drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp.h [moved from drivers/net/myri10ge/myri10ge_mcp.h with 100% similarity]
drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h [moved from drivers/net/myri10ge/myri10ge_mcp_gen_header.h with 100% similarity]
drivers/net/ethernet/natsemi/Kconfig [new file with mode: 0644]
drivers/net/ethernet/natsemi/Makefile [new file with mode: 0644]
drivers/net/ethernet/natsemi/ibmlana.c [moved from drivers/net/ibmlana.c with 99% similarity]
drivers/net/ethernet/natsemi/ibmlana.h [moved from drivers/net/ibmlana.h with 100% similarity]
drivers/net/ethernet/natsemi/jazzsonic.c [moved from drivers/net/jazzsonic.c with 99% similarity]
drivers/net/ethernet/natsemi/macsonic.c [moved from drivers/net/macsonic.c with 99% similarity]
drivers/net/ethernet/natsemi/natsemi.c [moved from drivers/net/natsemi.c with 99% similarity]
drivers/net/ethernet/natsemi/ns83820.c [moved from drivers/net/ns83820.c with 99% similarity]
drivers/net/ethernet/natsemi/sonic.c [moved from drivers/net/sonic.c with 100% similarity]
drivers/net/ethernet/natsemi/sonic.h [moved from drivers/net/sonic.h with 100% similarity]
drivers/net/ethernet/natsemi/xtsonic.c [moved from drivers/net/xtsonic.c with 99% similarity]
drivers/net/ethernet/neterion/Kconfig [new file with mode: 0644]
drivers/net/ethernet/neterion/Makefile [new file with mode: 0644]
drivers/net/ethernet/neterion/s2io-regs.h [moved from drivers/net/s2io-regs.h with 100% similarity]
drivers/net/ethernet/neterion/s2io.c [moved from drivers/net/s2io.c with 99% similarity]
drivers/net/ethernet/neterion/s2io.h [moved from drivers/net/s2io.h with 100% similarity]
drivers/net/ethernet/neterion/vxge/Makefile [moved from drivers/net/vxge/Makefile with 100% similarity]
drivers/net/ethernet/neterion/vxge/vxge-config.c [moved from drivers/net/vxge/vxge-config.c with 100% similarity]
drivers/net/ethernet/neterion/vxge/vxge-config.h [moved from drivers/net/vxge/vxge-config.h with 100% similarity]
drivers/net/ethernet/neterion/vxge/vxge-ethtool.c [moved from drivers/net/vxge/vxge-ethtool.c with 100% similarity]
drivers/net/ethernet/neterion/vxge/vxge-ethtool.h [moved from drivers/net/vxge/vxge-ethtool.h with 100% similarity]
drivers/net/ethernet/neterion/vxge/vxge-main.c [moved from drivers/net/vxge/vxge-main.c with 99% similarity]
drivers/net/ethernet/neterion/vxge/vxge-main.h [moved from drivers/net/vxge/vxge-main.h with 100% similarity]
drivers/net/ethernet/neterion/vxge/vxge-reg.h [moved from drivers/net/vxge/vxge-reg.h with 100% similarity]
drivers/net/ethernet/neterion/vxge/vxge-traffic.c [moved from drivers/net/vxge/vxge-traffic.c with 100% similarity]
drivers/net/ethernet/neterion/vxge/vxge-traffic.h [moved from drivers/net/vxge/vxge-traffic.h with 100% similarity]
drivers/net/ethernet/neterion/vxge/vxge-version.h [moved from drivers/net/vxge/vxge-version.h with 100% similarity]
drivers/net/ethernet/netx-eth.c [moved from drivers/net/netx-eth.c with 99% similarity]
drivers/net/ethernet/nuvoton/Kconfig [new file with mode: 0644]
drivers/net/ethernet/nuvoton/Makefile [new file with mode: 0644]
drivers/net/ethernet/nuvoton/w90p910_ether.c [moved from drivers/net/arm/w90p910_ether.c with 99% similarity]
drivers/net/ethernet/nvidia/Kconfig [new file with mode: 0644]
drivers/net/ethernet/nvidia/Makefile [new file with mode: 0644]
drivers/net/ethernet/nvidia/forcedeth.c [moved from drivers/net/forcedeth.c with 99% similarity]
drivers/net/ethernet/octeon/Kconfig [moved from drivers/net/octeon/Kconfig with 85% similarity]
drivers/net/ethernet/octeon/Makefile [new file with mode: 0644]
drivers/net/ethernet/octeon/octeon_mgmt.c [moved from drivers/net/octeon/octeon_mgmt.c with 99% similarity]
drivers/net/ethernet/oki-semi/Kconfig [new file with mode: 0644]
drivers/net/ethernet/oki-semi/Makefile [new file with mode: 0644]
drivers/net/ethernet/oki-semi/pch_gbe/Kconfig [new file with mode: 0644]
drivers/net/ethernet/oki-semi/pch_gbe/Makefile [moved from drivers/net/pch_gbe/Makefile with 100% similarity]
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h [moved from drivers/net/pch_gbe/pch_gbe.h with 100% similarity]
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c [moved from drivers/net/pch_gbe/pch_gbe_api.c with 100% similarity]
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h [moved from drivers/net/pch_gbe/pch_gbe_api.h with 100% similarity]
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c [moved from drivers/net/pch_gbe/pch_gbe_ethtool.c with 100% similarity]
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c [moved from drivers/net/pch_gbe/pch_gbe_main.c with 99% similarity]
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c [moved from drivers/net/pch_gbe/pch_gbe_param.c with 100% similarity]
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c [moved from drivers/net/pch_gbe/pch_gbe_phy.c with 100% similarity]
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h [moved from drivers/net/pch_gbe/pch_gbe_phy.h with 100% similarity]
drivers/net/ethernet/packetengines/Kconfig [new file with mode: 0644]
drivers/net/ethernet/packetengines/Makefile [new file with mode: 0644]
drivers/net/ethernet/packetengines/hamachi.c [moved from drivers/net/hamachi.c with 99% similarity]
drivers/net/ethernet/packetengines/yellowfin.c [moved from drivers/net/yellowfin.c with 99% similarity]
drivers/net/ethernet/pasemi/Kconfig [new file with mode: 0644]
drivers/net/ethernet/pasemi/Makefile [new file with mode: 0644]
drivers/net/ethernet/pasemi/pasemi_mac.c [moved from drivers/net/pasemi_mac.c with 99% similarity]
drivers/net/ethernet/pasemi/pasemi_mac.h [moved from drivers/net/pasemi_mac.h with 100% similarity]
drivers/net/ethernet/pasemi/pasemi_mac_ethtool.c [moved from drivers/net/pasemi_mac_ethtool.c with 100% similarity]
drivers/net/ethernet/qlogic/Kconfig [new file with mode: 0644]
drivers/net/ethernet/qlogic/Makefile [new file with mode: 0644]
drivers/net/ethernet/qlogic/netxen/Makefile [moved from drivers/net/netxen/Makefile with 100% similarity]
drivers/net/ethernet/qlogic/netxen/netxen_nic.h [moved from drivers/net/netxen/netxen_nic.h with 99% similarity]
drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c [moved from drivers/net/netxen/netxen_nic_ctx.c with 100% similarity]
drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c [moved from drivers/net/netxen/netxen_nic_ethtool.c with 100% similarity]
drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h [moved from drivers/net/netxen/netxen_nic_hdr.h with 100% similarity]
drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c [moved from drivers/net/netxen/netxen_nic_hw.c with 100% similarity]
drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.h [moved from drivers/net/netxen/netxen_nic_hw.h with 100% similarity]
drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c [moved from drivers/net/netxen/netxen_nic_init.c with 99% similarity]
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c [moved from drivers/net/netxen/netxen_nic_main.c with 96% similarity]
drivers/net/ethernet/qlogic/qla3xxx.c [moved from drivers/net/qla3xxx.c with 99% similarity]
drivers/net/ethernet/qlogic/qla3xxx.h [moved from drivers/net/qla3xxx.h with 100% similarity]
drivers/net/ethernet/qlogic/qlcnic/Makefile [moved from drivers/net/qlcnic/Makefile with 100% similarity]
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h [moved from drivers/net/qlcnic/qlcnic.h with 99% similarity]
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c [moved from drivers/net/qlcnic/qlcnic_ctx.c with 100% similarity]
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c [moved from drivers/net/qlcnic/qlcnic_ethtool.c with 98% similarity]
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h [moved from drivers/net/qlcnic/qlcnic_hdr.h with 100% similarity]
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c [moved from drivers/net/qlcnic/qlcnic_hw.c with 99% similarity]
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c [moved from drivers/net/qlcnic/qlcnic_init.c with 99% similarity]
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c [moved from drivers/net/qlcnic/qlcnic_main.c with 98% similarity]
drivers/net/ethernet/qlogic/qlge/Makefile [moved from drivers/net/qlge/Makefile with 100% similarity]
drivers/net/ethernet/qlogic/qlge/qlge.h [moved from drivers/net/qlge/qlge.h with 100% similarity]
drivers/net/ethernet/qlogic/qlge/qlge_dbg.c [moved from drivers/net/qlge/qlge_dbg.c with 100% similarity]
drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c [moved from drivers/net/qlge/qlge_ethtool.c with 100% similarity]
drivers/net/ethernet/qlogic/qlge/qlge_main.c [moved from drivers/net/qlge/qlge_main.c with 99% similarity]
drivers/net/ethernet/qlogic/qlge/qlge_mpi.c [moved from drivers/net/qlge/qlge_mpi.c with 100% similarity]
drivers/net/ethernet/racal/Kconfig [new file with mode: 0644]
drivers/net/ethernet/racal/Makefile [new file with mode: 0644]
drivers/net/ethernet/racal/ni5010.c [moved from drivers/net/ni5010.c with 99% similarity]
drivers/net/ethernet/racal/ni5010.h [moved from drivers/net/ni5010.h with 100% similarity]
drivers/net/ethernet/rdc/Kconfig [new file with mode: 0644]
drivers/net/ethernet/rdc/Makefile [new file with mode: 0644]
drivers/net/ethernet/rdc/r6040.c [moved from drivers/net/r6040.c with 99% similarity]
drivers/net/ethernet/realtek/8139cp.c [moved from drivers/net/8139cp.c with 99% similarity]
drivers/net/ethernet/realtek/8139too.c [moved from drivers/net/8139too.c with 99% similarity]
drivers/net/ethernet/realtek/Kconfig [new file with mode: 0644]
drivers/net/ethernet/realtek/Makefile [new file with mode: 0644]
drivers/net/ethernet/realtek/atp.c [moved from drivers/net/atp.c with 99% similarity]
drivers/net/ethernet/realtek/atp.h [moved from drivers/net/atp.h with 100% similarity]
drivers/net/ethernet/realtek/r8169.c [moved from drivers/net/r8169.c with 99% similarity]
drivers/net/ethernet/realtek/sc92031.c [moved from drivers/net/sc92031.c with 99% similarity]
drivers/net/ethernet/renesas/Kconfig [new file with mode: 0644]
drivers/net/ethernet/renesas/Makefile [new file with mode: 0644]
drivers/net/ethernet/renesas/sh_eth.c [moved from drivers/net/sh_eth.c with 99% similarity]
drivers/net/ethernet/renesas/sh_eth.h [moved from drivers/net/sh_eth.h with 100% similarity]
drivers/net/ethernet/s6gmac.c [moved from drivers/net/s6gmac.c with 100% similarity]
drivers/net/ethernet/seeq/Kconfig [new file with mode: 0644]
drivers/net/ethernet/seeq/Makefile [new file with mode: 0644]
drivers/net/ethernet/seeq/ether3.c [moved from drivers/net/arm/ether3.c with 99% similarity]
drivers/net/ethernet/seeq/ether3.h [moved from drivers/net/arm/ether3.h with 100% similarity]
drivers/net/ethernet/seeq/seeq8005.c [moved from drivers/net/seeq8005.c with 99% similarity]
drivers/net/ethernet/seeq/seeq8005.h [moved from drivers/net/seeq8005.h with 100% similarity]
drivers/net/ethernet/seeq/sgiseeq.c [moved from drivers/net/sgiseeq.c with 99% similarity]
drivers/net/ethernet/seeq/sgiseeq.h [moved from drivers/net/sgiseeq.h with 100% similarity]
drivers/net/ethernet/sfc/Kconfig [moved from drivers/net/sfc/Kconfig with 96% similarity]
drivers/net/ethernet/sfc/Makefile [moved from drivers/net/sfc/Makefile with 100% similarity]
drivers/net/ethernet/sfc/bitfield.h [moved from drivers/net/sfc/bitfield.h with 100% similarity]
drivers/net/ethernet/sfc/efx.c [moved from drivers/net/sfc/efx.c with 99% similarity]
drivers/net/ethernet/sfc/efx.h [moved from drivers/net/sfc/efx.h with 100% similarity]
drivers/net/ethernet/sfc/enum.h [moved from drivers/net/sfc/enum.h with 100% similarity]
drivers/net/ethernet/sfc/ethtool.c [moved from drivers/net/sfc/ethtool.c with 100% similarity]
drivers/net/ethernet/sfc/falcon.c [moved from drivers/net/sfc/falcon.c with 100% similarity]
drivers/net/ethernet/sfc/falcon_boards.c [moved from drivers/net/sfc/falcon_boards.c with 100% similarity]
drivers/net/ethernet/sfc/falcon_xmac.c [moved from drivers/net/sfc/falcon_xmac.c with 100% similarity]
drivers/net/ethernet/sfc/filter.c [moved from drivers/net/sfc/filter.c with 100% similarity]
drivers/net/ethernet/sfc/filter.h [moved from drivers/net/sfc/filter.h with 100% similarity]
drivers/net/ethernet/sfc/io.h [moved from drivers/net/sfc/io.h with 100% similarity]
drivers/net/ethernet/sfc/mac.h [moved from drivers/net/sfc/mac.h with 100% similarity]
drivers/net/ethernet/sfc/mcdi.c [moved from drivers/net/sfc/mcdi.c with 100% similarity]
drivers/net/ethernet/sfc/mcdi.h [moved from drivers/net/sfc/mcdi.h with 100% similarity]
drivers/net/ethernet/sfc/mcdi_mac.c [moved from drivers/net/sfc/mcdi_mac.c with 100% similarity]
drivers/net/ethernet/sfc/mcdi_pcol.h [moved from drivers/net/sfc/mcdi_pcol.h with 100% similarity]
drivers/net/ethernet/sfc/mcdi_phy.c [moved from drivers/net/sfc/mcdi_phy.c with 100% similarity]
drivers/net/ethernet/sfc/mdio_10g.c [moved from drivers/net/sfc/mdio_10g.c with 100% similarity]
drivers/net/ethernet/sfc/mdio_10g.h [moved from drivers/net/sfc/mdio_10g.h with 100% similarity]
drivers/net/ethernet/sfc/mtd.c [moved from drivers/net/sfc/mtd.c with 100% similarity]
drivers/net/ethernet/sfc/net_driver.h [moved from drivers/net/sfc/net_driver.h with 100% similarity]
drivers/net/ethernet/sfc/nic.c [moved from drivers/net/sfc/nic.c with 100% similarity]
drivers/net/ethernet/sfc/nic.h [moved from drivers/net/sfc/nic.h with 100% similarity]
drivers/net/ethernet/sfc/phy.h [moved from drivers/net/sfc/phy.h with 100% similarity]
drivers/net/ethernet/sfc/qt202x_phy.c [moved from drivers/net/sfc/qt202x_phy.c with 100% similarity]
drivers/net/ethernet/sfc/regs.h [moved from drivers/net/sfc/regs.h with 100% similarity]
drivers/net/ethernet/sfc/rx.c [moved from drivers/net/sfc/rx.c with 100% similarity]
drivers/net/ethernet/sfc/selftest.c [moved from drivers/net/sfc/selftest.c with 100% similarity]
drivers/net/ethernet/sfc/selftest.h [moved from drivers/net/sfc/selftest.h with 100% similarity]
drivers/net/ethernet/sfc/siena.c [moved from drivers/net/sfc/siena.c with 100% similarity]
drivers/net/ethernet/sfc/spi.h [moved from drivers/net/sfc/spi.h with 100% similarity]
drivers/net/ethernet/sfc/tenxpress.c [moved from drivers/net/sfc/tenxpress.c with 100% similarity]
drivers/net/ethernet/sfc/tx.c [moved from drivers/net/sfc/tx.c with 100% similarity]
drivers/net/ethernet/sfc/txc43128_phy.c [moved from drivers/net/sfc/txc43128_phy.c with 100% similarity]
drivers/net/ethernet/sfc/workarounds.h [moved from drivers/net/sfc/workarounds.h with 100% similarity]
drivers/net/ethernet/sgi/Kconfig [new file with mode: 0644]
drivers/net/ethernet/sgi/Makefile [new file with mode: 0644]
drivers/net/ethernet/sgi/ioc3-eth.c [moved from drivers/net/ioc3-eth.c with 99% similarity]
drivers/net/ethernet/sgi/meth.c [moved from drivers/net/meth.c with 100% similarity]
drivers/net/ethernet/sgi/meth.h [moved from drivers/net/meth.h with 100% similarity]
drivers/net/ethernet/sis/Kconfig [new file with mode: 0644]
drivers/net/ethernet/sis/Makefile [new file with mode: 0644]
drivers/net/ethernet/sis/sis190.c [moved from drivers/net/sis190.c with 99% similarity]
drivers/net/ethernet/sis/sis900.c [moved from drivers/net/sis900.c with 99% similarity]
drivers/net/ethernet/sis/sis900.h [moved from drivers/net/sis900.h with 100% similarity]
drivers/net/ethernet/smsc/Kconfig [new file with mode: 0644]
drivers/net/ethernet/smsc/Makefile [new file with mode: 0644]
drivers/net/ethernet/smsc/epic100.c [moved from drivers/net/epic100.c with 99% similarity]
drivers/net/ethernet/smsc/smc911x.c [moved from drivers/net/smc911x.c with 99% similarity]
drivers/net/ethernet/smsc/smc911x.h [moved from drivers/net/smc911x.h with 100% similarity]
drivers/net/ethernet/smsc/smc9194.c [moved from drivers/net/smc9194.c with 99% similarity]
drivers/net/ethernet/smsc/smc9194.h [moved from drivers/net/smc9194.h with 100% similarity]
drivers/net/ethernet/smsc/smc91c92_cs.c [moved from drivers/net/pcmcia/smc91c92_cs.c with 99% similarity]
drivers/net/ethernet/smsc/smc91x.c [moved from drivers/net/smc91x.c with 99% similarity]
drivers/net/ethernet/smsc/smc91x.h [moved from drivers/net/smc91x.h with 100% similarity]
drivers/net/ethernet/smsc/smsc911x.c [moved from drivers/net/smsc911x.c with 97% similarity]
drivers/net/ethernet/smsc/smsc911x.h [moved from drivers/net/smsc911x.h with 100% similarity]
drivers/net/ethernet/smsc/smsc9420.c [moved from drivers/net/smsc9420.c with 99% similarity]
drivers/net/ethernet/smsc/smsc9420.h [moved from drivers/net/smsc9420.h with 100% similarity]
drivers/net/ethernet/stmicro/Kconfig [new file with mode: 0644]
drivers/net/ethernet/stmicro/Makefile [new file with mode: 0644]
drivers/net/ethernet/stmicro/stmmac/Kconfig [moved from drivers/net/stmmac/Kconfig with 93% similarity]
drivers/net/ethernet/stmicro/stmmac/Makefile [moved from drivers/net/stmmac/Makefile with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/common.h [moved from drivers/net/stmmac/common.h with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/descs.h [moved from drivers/net/stmmac/descs.h with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/dwmac100.h [moved from drivers/net/stmmac/dwmac100.h with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h [moved from drivers/net/stmmac/dwmac1000.h with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c [moved from drivers/net/stmmac/dwmac1000_core.c with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c [moved from drivers/net/stmmac/dwmac1000_dma.c with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c [moved from drivers/net/stmmac/dwmac100_core.c with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c [moved from drivers/net/stmmac/dwmac100_dma.c with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h [moved from drivers/net/stmmac/dwmac_dma.h with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c [moved from drivers/net/stmmac/dwmac_lib.c with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/enh_desc.c [moved from drivers/net/stmmac/enh_desc.c with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/norm_desc.c [moved from drivers/net/stmmac/norm_desc.c with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/stmmac.h [moved from drivers/net/stmmac/stmmac.h with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c [moved from drivers/net/stmmac/stmmac_ethtool.c with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c [moved from drivers/net/stmmac/stmmac_main.c with 99% similarity]
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c [moved from drivers/net/stmmac/stmmac_mdio.c with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c [moved from drivers/net/stmmac/stmmac_timer.c with 100% similarity]
drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h [moved from drivers/net/stmmac/stmmac_timer.h with 100% similarity]
drivers/net/ethernet/sun/Kconfig [new file with mode: 0644]
drivers/net/ethernet/sun/Makefile [new file with mode: 0644]
drivers/net/ethernet/sun/cassini.c [moved from drivers/net/cassini.c with 99% similarity]
drivers/net/ethernet/sun/cassini.h [moved from drivers/net/cassini.h with 100% similarity]
drivers/net/ethernet/sun/niu.c [moved from drivers/net/niu.c with 99% similarity]
drivers/net/ethernet/sun/niu.h [moved from drivers/net/niu.h with 100% similarity]
drivers/net/ethernet/sun/sunbmac.c [moved from drivers/net/sunbmac.c with 97% similarity]
drivers/net/ethernet/sun/sunbmac.h [moved from drivers/net/sunbmac.h with 95% similarity]
drivers/net/ethernet/sun/sungem.c [moved from drivers/net/sungem.c with 99% similarity]
drivers/net/ethernet/sun/sungem.h [moved from drivers/net/sungem.h with 100% similarity]
drivers/net/ethernet/sun/sunhme.c [moved from drivers/net/sunhme.c with 99% similarity]
drivers/net/ethernet/sun/sunhme.h [moved from drivers/net/sunhme.h with 100% similarity]
drivers/net/ethernet/sun/sunqe.c [moved from drivers/net/sunqe.c with 99% similarity]
drivers/net/ethernet/sun/sunqe.h [moved from drivers/net/sunqe.h with 100% similarity]
drivers/net/ethernet/sun/sunvnet.c [moved from drivers/net/sunvnet.c with 99% similarity]
drivers/net/ethernet/sun/sunvnet.h [moved from drivers/net/sunvnet.h with 100% similarity]
drivers/net/ethernet/tehuti/Kconfig [new file with mode: 0644]
drivers/net/ethernet/tehuti/Makefile [new file with mode: 0644]
drivers/net/ethernet/tehuti/tehuti.c [moved from drivers/net/tehuti.c with 99% similarity]
drivers/net/ethernet/tehuti/tehuti.h [moved from drivers/net/tehuti.h with 100% similarity]
drivers/net/ethernet/ti/Kconfig [new file with mode: 0644]
drivers/net/ethernet/ti/Makefile [new file with mode: 0644]
drivers/net/ethernet/ti/cpmac.c [moved from drivers/net/cpmac.c with 99% similarity]
drivers/net/ethernet/ti/davinci_cpdma.c [moved from drivers/net/davinci_cpdma.c with 100% similarity]
drivers/net/ethernet/ti/davinci_cpdma.h [moved from drivers/net/davinci_cpdma.h with 100% similarity]
drivers/net/ethernet/ti/davinci_emac.c [moved from drivers/net/davinci_emac.c with 99% similarity]
drivers/net/ethernet/ti/davinci_mdio.c [moved from drivers/net/davinci_mdio.c with 100% similarity]
drivers/net/ethernet/ti/tlan.c [moved from drivers/net/tlan.c with 99% similarity]
drivers/net/ethernet/ti/tlan.h [moved from drivers/net/tlan.h with 100% similarity]
drivers/net/ethernet/tile/Kconfig [new file with mode: 0644]
drivers/net/ethernet/tile/Makefile [moved from drivers/net/tile/Makefile with 100% similarity]
drivers/net/ethernet/tile/tilepro.c [moved from drivers/net/tile/tilepro.c with 100% similarity]
drivers/net/ethernet/toshiba/Kconfig [new file with mode: 0644]
drivers/net/ethernet/toshiba/Makefile [new file with mode: 0644]
drivers/net/ethernet/toshiba/ps3_gelic_net.c [moved from drivers/net/ps3_gelic_net.c with 99% similarity]
drivers/net/ethernet/toshiba/ps3_gelic_net.h [moved from drivers/net/ps3_gelic_net.h with 100% similarity]
drivers/net/ethernet/toshiba/ps3_gelic_wireless.c [moved from drivers/net/ps3_gelic_wireless.c with 99% similarity]
drivers/net/ethernet/toshiba/ps3_gelic_wireless.h [moved from drivers/net/ps3_gelic_wireless.h with 100% similarity]
drivers/net/ethernet/toshiba/spider_net.c [moved from drivers/net/spider_net.c with 99% similarity]
drivers/net/ethernet/toshiba/spider_net.h [moved from drivers/net/spider_net.h with 99% similarity]
drivers/net/ethernet/toshiba/spider_net_ethtool.c [moved from drivers/net/spider_net_ethtool.c with 100% similarity]
drivers/net/ethernet/toshiba/tc35815.c [moved from drivers/net/tc35815.c with 99% similarity]
drivers/net/ethernet/tundra/Kconfig [new file with mode: 0644]
drivers/net/ethernet/tundra/Makefile [new file with mode: 0644]
drivers/net/ethernet/tundra/tsi108_eth.c [moved from drivers/net/tsi108_eth.c with 99% similarity]
drivers/net/ethernet/tundra/tsi108_eth.h [moved from drivers/net/tsi108_eth.h with 100% similarity]
drivers/net/ethernet/via/Kconfig [new file with mode: 0644]
drivers/net/ethernet/via/Makefile [new file with mode: 0644]
drivers/net/ethernet/via/via-rhine.c [moved from drivers/net/via-rhine.c with 99% similarity]
drivers/net/ethernet/via/via-velocity.c [moved from drivers/net/via-velocity.c with 97% similarity]
drivers/net/ethernet/via/via-velocity.h [moved from drivers/net/via-velocity.h with 100% similarity]
drivers/net/ethernet/xilinx/Kconfig [new file with mode: 0644]
drivers/net/ethernet/xilinx/Makefile [new file with mode: 0644]
drivers/net/ethernet/xilinx/ll_temac.h [moved from drivers/net/ll_temac.h with 100% similarity]
drivers/net/ethernet/xilinx/ll_temac_main.c [moved from drivers/net/ll_temac_main.c with 99% similarity]
drivers/net/ethernet/xilinx/ll_temac_mdio.c [moved from drivers/net/ll_temac_mdio.c with 100% similarity]
drivers/net/ethernet/xilinx/xilinx_emaclite.c [moved from drivers/net/xilinx_emaclite.c with 100% similarity]
drivers/net/ethernet/xircom/Kconfig [new file with mode: 0644]
drivers/net/ethernet/xircom/Makefile [new file with mode: 0644]
drivers/net/ethernet/xircom/xirc2ps_cs.c [moved from drivers/net/pcmcia/xirc2ps_cs.c with 99% similarity]
drivers/net/ethernet/xscale/Kconfig [new file with mode: 0644]
drivers/net/ethernet/xscale/Makefile [new file with mode: 0644]
drivers/net/ethernet/xscale/ixp2000/Kconfig [moved from drivers/net/ixp2000/Kconfig with 94% similarity]
drivers/net/ethernet/xscale/ixp2000/Makefile [moved from drivers/net/ixp2000/Makefile with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/caleb.c [moved from drivers/net/ixp2000/caleb.c with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/caleb.h [moved from drivers/net/ixp2000/caleb.h with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/enp2611.c [moved from drivers/net/ixp2000/enp2611.c with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.c [moved from drivers/net/ixp2000/ixp2400-msf.c with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.h [moved from drivers/net/ixp2000/ixp2400-msf.h with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.uc [moved from drivers/net/ixp2000/ixp2400_rx.uc with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.ucode [moved from drivers/net/ixp2000/ixp2400_rx.ucode with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.uc [moved from drivers/net/ixp2000/ixp2400_tx.uc with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.ucode [moved from drivers/net/ixp2000/ixp2400_tx.ucode with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/ixpdev.c [moved from drivers/net/ixp2000/ixpdev.c with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/ixpdev.h [moved from drivers/net/ixp2000/ixpdev.h with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/ixpdev_priv.h [moved from drivers/net/ixp2000/ixpdev_priv.h with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/pm3386.c [moved from drivers/net/ixp2000/pm3386.c with 100% similarity]
drivers/net/ethernet/xscale/ixp2000/pm3386.h [moved from drivers/net/ixp2000/pm3386.h with 100% similarity]
drivers/net/ethernet/xscale/ixp4xx_eth.c [moved from drivers/net/arm/ixp4xx_eth.c with 99% similarity]
drivers/net/fddi/Kconfig [new file with mode: 0644]
drivers/net/fddi/Makefile [new file with mode: 0644]
drivers/net/fddi/defxx.c [moved from drivers/net/defxx.c with 99% similarity]
drivers/net/fddi/defxx.h [moved from drivers/net/defxx.h with 100% similarity]
drivers/net/fddi/skfp/Makefile [moved from drivers/net/skfp/Makefile with 100% similarity]
drivers/net/fddi/skfp/cfm.c [moved from drivers/net/skfp/cfm.c with 100% similarity]
drivers/net/fddi/skfp/drvfbi.c [moved from drivers/net/skfp/drvfbi.c with 100% similarity]
drivers/net/fddi/skfp/ecm.c [moved from drivers/net/skfp/ecm.c with 100% similarity]
drivers/net/fddi/skfp/ess.c [moved from drivers/net/skfp/ess.c with 100% similarity]
drivers/net/fddi/skfp/fplustm.c [moved from drivers/net/skfp/fplustm.c with 100% similarity]
drivers/net/fddi/skfp/h/cmtdef.h [moved from drivers/net/skfp/h/cmtdef.h with 99% similarity]
drivers/net/fddi/skfp/h/fddi.h [moved from drivers/net/skfp/h/fddi.h with 100% similarity]
drivers/net/fddi/skfp/h/fddimib.h [moved from drivers/net/skfp/h/fddimib.h with 100% similarity]
drivers/net/fddi/skfp/h/fplustm.h [moved from drivers/net/skfp/h/fplustm.h with 100% similarity]
drivers/net/fddi/skfp/h/hwmtm.h [moved from drivers/net/skfp/h/hwmtm.h with 99% similarity]
drivers/net/fddi/skfp/h/mbuf.h [moved from drivers/net/skfp/h/mbuf.h with 100% similarity]
drivers/net/fddi/skfp/h/osdef1st.h [moved from drivers/net/skfp/h/osdef1st.h with 100% similarity]
drivers/net/fddi/skfp/h/sba.h [moved from drivers/net/skfp/h/sba.h with 98% similarity]
drivers/net/fddi/skfp/h/sba_def.h [moved from drivers/net/skfp/h/sba_def.h with 100% similarity]
drivers/net/fddi/skfp/h/skfbi.h [moved from drivers/net/skfp/h/skfbi.h with 100% similarity]
drivers/net/fddi/skfp/h/skfbiinc.h [moved from drivers/net/skfp/h/skfbiinc.h with 99% similarity]
drivers/net/fddi/skfp/h/smc.h [moved from drivers/net/skfp/h/smc.h with 98% similarity]
drivers/net/fddi/skfp/h/smt.h [moved from drivers/net/skfp/h/smt.h with 100% similarity]
drivers/net/fddi/skfp/h/smt_p.h [moved from drivers/net/skfp/h/smt_p.h with 100% similarity]
drivers/net/fddi/skfp/h/smtstate.h [moved from drivers/net/skfp/h/smtstate.h with 100% similarity]
drivers/net/fddi/skfp/h/supern_2.h [moved from drivers/net/skfp/h/supern_2.h with 100% similarity]
drivers/net/fddi/skfp/h/targethw.h [moved from drivers/net/skfp/h/targethw.h with 98% similarity]
drivers/net/fddi/skfp/h/targetos.h [moved from drivers/net/skfp/h/targetos.h with 99% similarity]
drivers/net/fddi/skfp/h/types.h [moved from drivers/net/skfp/h/types.h with 100% similarity]
drivers/net/fddi/skfp/hwmtm.c [moved from drivers/net/skfp/hwmtm.c with 100% similarity]
drivers/net/fddi/skfp/hwt.c [moved from drivers/net/skfp/hwt.c with 100% similarity]
drivers/net/fddi/skfp/pcmplc.c [moved from drivers/net/skfp/pcmplc.c with 100% similarity]
drivers/net/fddi/skfp/pmf.c [moved from drivers/net/skfp/pmf.c with 100% similarity]
drivers/net/fddi/skfp/queue.c [moved from drivers/net/skfp/queue.c with 100% similarity]
drivers/net/fddi/skfp/rmt.c [moved from drivers/net/skfp/rmt.c with 100% similarity]
drivers/net/fddi/skfp/skfddi.c [moved from drivers/net/skfp/skfddi.c with 99% similarity]
drivers/net/fddi/skfp/smt.c [moved from drivers/net/skfp/smt.c with 100% similarity]
drivers/net/fddi/skfp/smtdef.c [moved from drivers/net/skfp/smtdef.c with 100% similarity]
drivers/net/fddi/skfp/smtinit.c [moved from drivers/net/skfp/smtinit.c with 100% similarity]
drivers/net/fddi/skfp/smttimer.c [moved from drivers/net/skfp/smttimer.c with 100% similarity]
drivers/net/fddi/skfp/srf.c [moved from drivers/net/skfp/srf.c with 100% similarity]
drivers/net/hippi/Kconfig [new file with mode: 0644]
drivers/net/hippi/Makefile [new file with mode: 0644]
drivers/net/hippi/rrunner.c [moved from drivers/net/rrunner.c with 100% similarity]
drivers/net/hippi/rrunner.h [moved from drivers/net/rrunner.h with 100% similarity]
drivers/net/ibm_newemac/Makefile [deleted file]
drivers/net/irda/sh_irda.c
drivers/net/irda/sh_sir.c
drivers/net/irda/smsc-ircc2.c
drivers/net/macvlan.c
drivers/net/octeon/Makefile [deleted file]
drivers/net/pci-skeleton.c [deleted file]
drivers/net/pcmcia/Kconfig [deleted file]
drivers/net/pcmcia/Makefile [deleted file]
drivers/net/phy/Kconfig
drivers/net/phy/dp83640.c
drivers/net/plip/Kconfig [new file with mode: 0644]
drivers/net/plip/Makefile [new file with mode: 0644]
drivers/net/plip/plip.c [moved from drivers/net/plip.c with 100% similarity]
drivers/net/ppp/Kconfig [new file with mode: 0644]
drivers/net/ppp/Makefile [new file with mode: 0644]
drivers/net/ppp/bsd_comp.c [moved from drivers/net/bsd_comp.c with 100% similarity]
drivers/net/ppp/ppp_async.c [moved from drivers/net/ppp_async.c with 100% similarity]
drivers/net/ppp/ppp_deflate.c [moved from drivers/net/ppp_deflate.c with 100% similarity]
drivers/net/ppp/ppp_generic.c [moved from drivers/net/ppp_generic.c with 100% similarity]
drivers/net/ppp/ppp_mppe.c [moved from drivers/net/ppp_mppe.c with 100% similarity]
drivers/net/ppp/ppp_mppe.h [moved from drivers/net/ppp_mppe.h with 100% similarity]
drivers/net/ppp/ppp_synctty.c [moved from drivers/net/ppp_synctty.c with 100% similarity]
drivers/net/ppp/pppoe.c [moved from drivers/net/pppoe.c with 100% similarity]
drivers/net/ppp/pppox.c [moved from drivers/net/pppox.c with 100% similarity]
drivers/net/ppp/pptp.c [moved from drivers/net/pptp.c with 100% similarity]
drivers/net/slip/Kconfig [new file with mode: 0644]
drivers/net/slip/Makefile [new file with mode: 0644]
drivers/net/slip/slhc.c [moved from drivers/net/slhc.c with 100% similarity]
drivers/net/slip/slip.c [moved from drivers/net/slip.c with 98% similarity]
drivers/net/slip/slip.h [moved from drivers/net/slip.h with 94% similarity]
drivers/net/sungem_phy.c
drivers/net/tokenring/3c359.c
drivers/net/tokenring/Kconfig
drivers/net/tokenring/Makefile
drivers/net/tokenring/ibmtr.c
drivers/net/tokenring/ibmtr_cs.c [moved from drivers/net/pcmcia/ibmtr_cs.c with 99% similarity]
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/olympic.c
drivers/net/tokenring/smctr.c
drivers/net/tokenring/tms380tr.c
drivers/net/tun.c
drivers/net/usb/asix.c
drivers/net/usb/catc.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/dm9601.c
drivers/net/usb/int51x1.c
drivers/net/usb/kaweth.c
drivers/net/usb/lg-vl600.c
drivers/net/usb/mcs7830.c
drivers/net/usb/pegasus.c
drivers/net/usb/rtl8150.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/smsc95xx.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/wan/hdlc_ppp.c
drivers/net/wan/sbni.c
drivers/net/wireless/airo.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/b43/dma.c
drivers/net/wireless/hostap/hostap_main.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/libertas/main.c
drivers/net/wireless/libertas/mesh.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/orinoco/main.c
drivers/net/wireless/orinoco/orinoco_usb.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/rndis_wlan.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
drivers/net/wireless/wl1251/acx.c
drivers/net/wireless/wl1251/cmd.c
drivers/net/wireless/zd1201.c
drivers/of/address.c
drivers/of/base.c
drivers/of/gpio.c
drivers/of/of_net.c
drivers/pci/hotplug/acpi_pcihp.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/pci.c
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/aer/aerdrv_errprint.c
drivers/pci/probe.c
drivers/pci/setup-bus.c
drivers/pci/setup-irq.c
drivers/pci/setup-res.c
drivers/pcmcia/pxa2xx_balloon3.c
drivers/pcmcia/pxa2xx_cm_x255.c
drivers/pcmcia/pxa2xx_cm_x270.c
drivers/pcmcia/pxa2xx_colibri.c
drivers/pcmcia/pxa2xx_mainstone.c
drivers/pcmcia/pxa2xx_palmld.c
drivers/pcmcia/pxa2xx_palmtc.c
drivers/pcmcia/pxa2xx_palmtx.c
drivers/pcmcia/pxa2xx_stargate2.c
drivers/pcmcia/pxa2xx_viper.c
drivers/pcmcia/soc_common.c
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/acerhdf.c
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/asus-wmi.h
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/dell-wmi.c
drivers/platform/x86/eeepc-wmi.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel_ips.c
drivers/platform/x86/intel_menlow.c
drivers/platform/x86/intel_mid_thermal.c
drivers/platform/x86/intel_rar_register.c
drivers/platform/x86/intel_scu_ipc.c
drivers/platform/x86/msi-laptop.c
drivers/platform/x86/msi-wmi.c
drivers/platform/x86/samsung-laptop.c
drivers/platform/x86/samsung-q10.c [new file with mode: 0644]
drivers/platform/x86/thinkpad_acpi.c
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/apm_power.c
drivers/power/bq20z75.c
drivers/power/gpio-charger.c
drivers/power/max17042_battery.c
drivers/power/max8903_charger.c
drivers/power/max8997_charger.c [new file with mode: 0644]
drivers/power/max8998_charger.c [new file with mode: 0644]
drivers/power/s3c_adc_battery.c
drivers/power/twl4030_charger.c
drivers/power/wm831x_backup.c
drivers/power/wm831x_power.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/aat2870-regulator.c [new file with mode: 0644]
drivers/regulator/core.c
drivers/regulator/dummy.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/tps65912-regulator.c [new file with mode: 0644]
drivers/regulator/twl-regulator.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8994-regulator.c
drivers/rtc/rtc-omap.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_proc.c
drivers/s390/char/sclp_async.c
drivers/s390/cio/qdio.h
drivers/s390/cio/qdio_debug.c
drivers/s390/cio/qdio_main.c
drivers/s390/cio/qdio_setup.c
drivers/s390/cio/qdio_thinint.c
drivers/s390/net/lcs.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3.h
drivers/s390/net/qeth_l3_main.c
drivers/s390/net/qeth_l3_sys.c
drivers/scsi/bfa/bfa.h
drivers/scsi/bfa/bfa_core.c
drivers/scsi/bfa/bfa_defs.h
drivers/scsi/bfa/bfa_defs_svc.h
drivers/scsi/bfa/bfa_fc.h
drivers/scsi/bfa/bfa_fcpim.c
drivers/scsi/bfa/bfa_fcpim.h
drivers/scsi/bfa/bfa_fcs.c
drivers/scsi/bfa/bfa_fcs.h
drivers/scsi/bfa/bfa_fcs_fcpim.c
drivers/scsi/bfa/bfa_fcs_lport.c
drivers/scsi/bfa/bfa_fcs_rport.c
drivers/scsi/bfa/bfa_hw_cb.c
drivers/scsi/bfa/bfa_hw_ct.c
drivers/scsi/bfa/bfa_ioc.c
drivers/scsi/bfa/bfa_ioc.h
drivers/scsi/bfa/bfa_modules.h
drivers/scsi/bfa/bfa_svc.c
drivers/scsi/bfa/bfa_svc.h
drivers/scsi/bfa/bfad.c
drivers/scsi/bfa/bfad_bsg.c
drivers/scsi/bfa/bfad_bsg.h
drivers/scsi/bfa/bfad_drv.h
drivers/scsi/bfa/bfad_im.c
drivers/scsi/bfa/bfad_im.h
drivers/scsi/bfa/bfi.h
drivers/scsi/bnx2fc/Kconfig
drivers/scsi/bnx2fc/bnx2fc.h
drivers/scsi/bnx2fc/bnx2fc_debug.h
drivers/scsi/bnx2fc/bnx2fc_els.c
drivers/scsi/bnx2fc/bnx2fc_fcoe.c
drivers/scsi/bnx2fc/bnx2fc_hwi.c
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/bnx2fc/bnx2fc_tgt.c
drivers/scsi/bnx2i/Kconfig
drivers/scsi/bnx2i/bnx2i.h
drivers/scsi/cxgbi/cxgb3i/Kbuild
drivers/scsi/cxgbi/cxgb3i/Kconfig
drivers/scsi/cxgbi/cxgb4i/Kbuild
drivers/scsi/cxgbi/cxgb4i/Kconfig
drivers/scsi/device_handler/scsi_dh_rdac.c
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fcoe/fcoe_transport.c
drivers/scsi/hpsa.c
drivers/scsi/hpsa.h
drivers/scsi/ipr.c
drivers/scsi/libfc/fc_exch.c
drivers/scsi/libfc/fc_fcp.c
drivers/scsi/libfc/fc_lport.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_bsg.c
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_debugfs.c
drivers/scsi/lpfc/lpfc_debugfs.h
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw.h
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_mbox.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fp.c
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/mvsas/Kconfig
drivers/scsi/mvsas/mv_64xx.c
drivers/scsi/mvsas/mv_94xx.c
drivers/scsi/mvsas/mv_94xx.h
drivers/scsi/mvsas/mv_chips.h
drivers/scsi/mvsas/mv_defs.h
drivers/scsi/mvsas/mv_init.c
drivers/scsi/mvsas/mv_sas.c
drivers/scsi/mvsas/mv_sas.h
drivers/scsi/pmcraid.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_dbg.h
drivers/scsi/qla2xxx/qla_dfs.c
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_inline.h
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_nx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_transport_spi.c
drivers/sh/clk/core.c
drivers/spi/spi-pl022.c
drivers/staging/brcm80211/brcmfmac/dhd_linux.c
drivers/staging/cxd2099/Kconfig
drivers/staging/cxd2099/cxd2099.c
drivers/staging/cxd2099/cxd2099.h
drivers/staging/dt3155v4l/dt3155v4l.c
drivers/staging/et131x/et131x_netdev.c
drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
drivers/staging/gma500/gem_glue.c
drivers/staging/gma500/gem_glue.h
drivers/staging/hv/blkvsc_drv.c
drivers/staging/hv/netvsc_drv.c
drivers/staging/iio/accel/adis16203_core.c
drivers/staging/iio/accel/adis16204_core.c
drivers/staging/iio/accel/adis16209_core.c
drivers/staging/iio/accel/adis16240_core.c
drivers/staging/iio/gyro/adis16260_core.c
drivers/staging/nvec/TODO
drivers/staging/octeon/ethernet.c
drivers/staging/rtl8187se/r8180_core.c
drivers/staging/rtl8192e/r8192E_core.c
drivers/staging/rtl8192u/r8192U_core.c
drivers/staging/rtl8192u/r819xU_firmware.c
drivers/staging/rts_pstor/rtsx.c
drivers/staging/rts_pstor/rtsx.h
drivers/staging/slicoss/slicoss.c
drivers/staging/solo6x10/core.c
drivers/staging/solo6x10/enc.c
drivers/staging/solo6x10/g723.c
drivers/staging/solo6x10/p2m.c
drivers/staging/solo6x10/solo6x10.h
drivers/staging/speakup/devsynth.c
drivers/staging/tm6000/tm6000-alsa.c
drivers/staging/vt6655/device_main.c
drivers/staging/vt6656/main_usb.c
drivers/staging/wlags49_h2/wl_netdev.c
drivers/staging/wlan-ng/p80211netdev.c
drivers/staging/zcache/Makefile
drivers/staging/zcache/zcache-main.c [moved from drivers/staging/zcache/zcache.c with 99% similarity]
drivers/target/iscsi/Kconfig
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_nego.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tcm_fc.h
drivers/target/tcm_fc/tfc_cmd.c
drivers/target/tcm_fc/tfc_io.c
drivers/thermal/Kconfig
drivers/thermal/thermal_sys.c
drivers/tty/serial/Kconfig
drivers/tty/serial/imx.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/sh-sci.h
drivers/usb/class/usbtmc.c
drivers/usb/core/config.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/f_hid.c
drivers/usb/gadget/fusb300_udc.c
drivers/usb/gadget/net2272.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/gadget/uvc_v4l2.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-mxc.c
drivers/usb/host/ehci-omap.c
drivers/usb/host/isp1760-hcd.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci.c
drivers/usb/musb/Kconfig
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/tusb6010_omap.c
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/storage/unusual_devs.h
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/aat2870_bl.c [new file with mode: 0644]
drivers/video/omap2/displays/panel-taal.c
drivers/video/omap2/dss/Kconfig
drivers/video/omap2/dss/core.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/display.c
drivers/video/omap2/dss/dpi.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/dss.h
drivers/video/omap2/dss/dss_features.c
drivers/video/omap2/dss/dss_features.h
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/dss/manager.c
drivers/video/omap2/dss/overlay.c
drivers/video/omap2/dss/rfbi.c
drivers/video/omap2/dss/sdi.c
drivers/video/omap2/dss/venc.c
drivers/video/omap2/omapfb/omapfb-ioctl.c
drivers/video/omap2/omapfb/omapfb-main.c
drivers/video/omap2/omapfb/omapfb-sysfs.c
drivers/video/omap2/omapfb/omapfb.h
drivers/video/savage/savagefb.h
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/at91sam9_wdt.c
drivers/watchdog/at91sam9_wdt.h [moved from arch/arm/mach-at91/include/mach/at91_wdt.h with 96% similarity]
drivers/watchdog/dw_wdt.c [new file with mode: 0644]
drivers/watchdog/hpwdt.c
drivers/watchdog/iTCO_wdt.c
drivers/watchdog/imx2_wdt.c
drivers/watchdog/it8712f_wdt.c
drivers/watchdog/it87_wdt.c
drivers/watchdog/mpcore_wdt.c
drivers/watchdog/mtx-1_wdt.c
drivers/watchdog/nv_tco.c
drivers/watchdog/of_xilinx_wdt.c [new file with mode: 0644]
drivers/watchdog/pc87413_wdt.c
drivers/watchdog/s3c2410_wdt.c
drivers/watchdog/sch311x_wdt.c
drivers/watchdog/shwdt.c
drivers/watchdog/sp805_wdt.c
drivers/watchdog/watchdog_core.c [new file with mode: 0644]
drivers/watchdog/watchdog_dev.c [new file with mode: 0644]
drivers/watchdog/watchdog_dev.h [new file with mode: 0644]
drivers/xen/Kconfig
drivers/xen/grant-table.c
drivers/xen/xen-pciback/xenbus.c
drivers/xen/xen-selfballoon.c
fs/9p/acl.c
fs/9p/acl.h
fs/9p/vfs_inode_dotl.c
fs/Kconfig
fs/autofs4/autofs_i.h
fs/autofs4/waitq.c
fs/block_dev.c
fs/btrfs/Makefile
fs/btrfs/acl.c
fs/btrfs/compression.c
fs/btrfs/ctree.h
fs/btrfs/dir-item.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/extent_map.c
fs/btrfs/file-item.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ref-cache.c [deleted file]
fs/btrfs/ref-cache.h [deleted file]
fs/btrfs/root-tree.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dns_resolve.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/misc.c
fs/cifs/transport.c
fs/compat_ioctl.c
fs/dcache.c
fs/ecryptfs/Kconfig
fs/ecryptfs/inode.c
fs/ecryptfs/keystore.c
fs/ecryptfs/main.c
fs/ecryptfs/read_write.c
fs/exec.c
fs/exofs/Kbuild
fs/exofs/Kconfig
fs/exofs/exofs.h
fs/exofs/inode.c
fs/exofs/ore.c [moved from fs/exofs/ios.c with 61% similarity]
fs/exofs/pnfs.h [deleted file]
fs/exofs/super.c
fs/ext2/acl.c
fs/ext2/acl.h
fs/ext3/acl.c
fs/ext3/namei.c
fs/ext4/Makefile
fs/ext4/acl.c
fs/ext4/balloc.c
fs/ext4/block_validity.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/fsync.c
fs/ext4/ialloc.c
fs/ext4/indirect.c [new file with mode: 0644]
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/mballoc.c
fs/ext4/mballoc.h
fs/ext4/namei.c
fs/ext4/page-io.c
fs/ext4/resize.c
fs/ext4/super.c
fs/ext4/truncate.h [new file with mode: 0644]
fs/fs-writeback.c
fs/generic_acl.c
fs/gfs2/acl.c
fs/hppfs/hppfs.c
fs/inode.c
fs/jbd2/checkpoint.c
fs/jbd2/journal.c
fs/jffs2/acl.c
fs/jffs2/acl.h
fs/jffs2/fs.c
fs/jffs2/os-linux.h
fs/jfs/acl.c
fs/jfs/xattr.c
fs/namei.c
fs/nfs/Kconfig
fs/nfs/Makefile
fs/nfs/blocklayout/Makefile [new file with mode: 0644]
fs/nfs/blocklayout/blocklayout.c [new file with mode: 0644]
fs/nfs/blocklayout/blocklayout.h [new file with mode: 0644]
fs/nfs/blocklayout/blocklayoutdev.c [new file with mode: 0644]
fs/nfs/blocklayout/blocklayoutdm.c [new file with mode: 0644]
fs/nfs/blocklayout/extents.c [new file with mode: 0644]
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/nfs3acl.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/ocfs2/acl.c
fs/posix_acl.c
fs/proc/base.c
fs/pstore/inode.c
fs/pstore/internal.h
fs/pstore/platform.c
fs/reiserfs/xattr_acl.c
fs/stack.c
fs/stat.c
fs/xfs/linux-2.6/xfs_acl.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_buf.h
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/quota/xfs_dquot.c
fs/xfs/quota/xfs_qm.c
fs/xfs/xfs_acl.h
fs/xfs/xfs_ag.h
fs/xfs/xfs_alloc.c
fs/xfs/xfs_attr.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_btree.c
fs/xfs/xfs_btree.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_dinode.h
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_rtalloc.h
fs/xfs/xfs_rw.c
fs/xfs/xfs_sb.h
fs/xfs/xfs_trans_ail.c
fs/xfs/xfs_trans_buf.c
fs/xfs/xfs_vnodeops.c
include/acpi/acpi_drivers.h
include/acpi/acpixf.h
include/acpi/apei.h
include/acpi/processor.h
include/drm/drm_crtc.h
include/drm/i915_drm.h
include/linux/acpi.h
include/linux/aer.h
include/linux/amba/pl08x.h
include/linux/atalk.h
include/linux/ax25.h
include/linux/bitmap.h
include/linux/caif/caif_socket.h
include/linux/can.h
include/linux/can/bcm.h
include/linux/cpuidle.h
include/linux/cred.h
include/linux/cryptohash.h
include/linux/dcache.h
include/linux/device-mapper.h
include/linux/dm-ioctl.h
include/linux/dm-kcopyd.h
include/linux/dvb/audio.h
include/linux/efi.h
include/linux/ethtool.h
include/linux/fault-inject.h
include/linux/fs.h
include/linux/genalloc.h
include/linux/gfp.h
include/linux/idr.h
include/linux/if.h
include/linux/if_ether.h
include/linux/if_packet.h
include/linux/if_pppol2tp.h
include/linux/if_pppox.h
include/linux/in.h
include/linux/input.h
include/linux/ioport.h
include/linux/ipx.h
include/linux/irda.h
include/linux/irq.h
include/linux/irqdomain.h [new file with mode: 0644]
include/linux/jbd2.h
include/linux/kconfig.h [new file with mode: 0644]
include/linux/l2tp.h
include/linux/llc.h
include/linux/llist.h [new file with mode: 0644]
include/linux/memcontrol.h
include/linux/mfd/aat2870.h [new file with mode: 0644]
include/linux/mfd/ab8500.h
include/linux/mfd/max8997.h
include/linux/mfd/max8998.h
include/linux/mfd/stmpe.h
include/linux/mfd/tps65910.h
include/linux/mfd/tps65912.h [new file with mode: 0644]
include/linux/mfd/wm831x/core.h
include/linux/mfd/wm831x/pdata.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/netdevice.h
include/linux/netfilter/xt_connlimit.h
include/linux/netfilter/xt_conntrack.h
include/linux/netfilter/xt_iprange.h
include/linux/netfilter_arp/arp_tables.h
include/linux/netfilter_decnet.h
include/linux/netfilter_ipv4.h
include/linux/netfilter_ipv4/ip_tables.h
include/linux/netfilter_ipv6.h
include/linux/netfilter_ipv6/ip6_tables.h
include/linux/netlink.h
include/linux/netrom.h
include/linux/nfs.h
include/linux/nfs4.h
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_xdr.h
include/linux/of.h
include/linux/of_gpio.h
include/linux/of_irq.h
include/linux/of_net.h
include/linux/page-flags.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/phonet.h
include/linux/phy.h
include/linux/platform_data/ntc_thermistor.h [new file with mode: 0644]
include/linux/posix_acl.h
include/linux/power/bq20z75.h
include/linux/power/max17042_battery.h
include/linux/pstore.h
include/linux/radix-tree.h
include/linux/random.h
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/rose.h
include/linux/sched.h
include/linux/serial_sci.h
include/linux/sh_clk.h
include/linux/sh_dma.h
include/linux/shm.h
include/linux/shmem_fs.h
include/linux/skbuff.h
include/linux/slub_def.h
include/linux/socket.h
include/linux/sungem_phy.h [moved from drivers/net/sungem_phy.h with 98% similarity]
include/linux/swapops.h
include/linux/tcp.h
include/linux/thermal.h
include/linux/tipc_config.h
include/linux/un.h
include/linux/videodev2.h
include/linux/watchdog.h
include/linux/x25.h
include/media/adp1653.h [new file with mode: 0644]
include/media/atmel-isi.h [new file with mode: 0644]
include/media/davinci/vpbe.h [new file with mode: 0644]
include/media/davinci/vpbe_display.h [new file with mode: 0644]
include/media/davinci/vpbe_osd.h [new file with mode: 0644]
include/media/davinci/vpbe_types.h [new file with mode: 0644]
include/media/davinci/vpbe_venc.h [new file with mode: 0644]
include/media/mmp-camera.h [new file with mode: 0644]
include/media/ov7670.h [moved from drivers/media/video/ov7670.h with 100% similarity]
include/media/rc-core.h
include/media/rc-map.h
include/media/sh_mobile_ceu.h
include/media/sh_mobile_csi2.h
include/media/soc_camera.h
include/media/soc_camera_platform.h
include/media/timb_radio.h
include/media/tuner.h
include/media/v4l2-chip-ident.h
include/media/v4l2-ctrls.h
include/media/v4l2-event.h
include/media/v4l2-fh.h
include/media/v4l2-mediabus.h
include/media/v4l2-subdev.h
include/net/addrconf.h
include/net/cipso_ipv4.h
include/net/dst.h
include/net/if_inet6.h
include/net/inet_sock.h
include/net/iucv/af_iucv.h
include/net/iucv/iucv.h
include/net/netlabel.h
include/net/scm.h
include/net/sctp/structs.h
include/net/secure_seq.h [new file with mode: 0644]
include/net/sock.h
include/scsi/fc_frame.h
include/scsi/osd_ore.h [new file with mode: 0644]
include/sound/tea575x-tuner.h
include/sound/wm8996.h [moved from include/sound/wm8915.h with 63% similarity]
include/trace/events/ext4.h
include/trace/events/jbd2.h
include/trace/events/xen.h
include/video/omapdss.h
init/main.c
ipc/shm.c
kernel/Makefile
kernel/compat.c
kernel/cred.c
kernel/debug/gdbstub.c
kernel/debug/kdb/kdb_bt.c
kernel/debug/kdb/kdb_cmds
kernel/debug/kdb/kdb_debugger.c
kernel/debug/kdb/kdb_io.c
kernel/debug/kdb/kdb_main.c
kernel/debug/kdb/kdb_private.h
kernel/fork.c
kernel/futex.c
kernel/irq/Kconfig
kernel/irq/Makefile
kernel/irq/irqdomain.c [new file with mode: 0644]
kernel/kmod.c
kernel/lockdep.c
kernel/printk.c
kernel/resource.c
kernel/sys.c
kernel/taskstats.c
kernel/trace/Kconfig
lib/Kconfig
lib/Makefile
lib/bitmap.c
lib/fault-inject.c
lib/genalloc.c
lib/idr.c
lib/llist.c [new file with mode: 0644]
lib/md5.c [new file with mode: 0644]
lib/radix-tree.c
lib/sha1.c
mm/failslab.c
mm/filemap.c
mm/memcontrol.c
mm/memory-failure.c
mm/mincore.c
mm/oom_kill.c
mm/page_alloc.c
mm/shmem.c
mm/slab.c
mm/slub.c
mm/swapfile.c
mm/truncate.c
net/802/garp.c
net/802/stp.c
net/8021q/vlan.c
net/8021q/vlan_core.c
net/8021q/vlan_dev.c
net/atm/br2684.c
net/atm/lec.c
net/batman-adv/aggregation.h
net/batman-adv/bat_sysfs.c
net/batman-adv/bitarray.c
net/batman-adv/gateway_client.c
net/batman-adv/hard-interface.c
net/batman-adv/hard-interface.h
net/batman-adv/hash.h
net/batman-adv/main.c
net/batman-adv/main.h
net/batman-adv/originator.c
net/batman-adv/packet.h
net/batman-adv/routing.c
net/batman-adv/send.c
net/batman-adv/soft-interface.c
net/batman-adv/translation-table.c
net/batman-adv/translation-table.h
net/batman-adv/types.h
net/batman-adv/unicast.c
net/batman-adv/unicast.h
net/batman-adv/vis.c
net/bluetooth/bnep/netdev.c
net/bridge/br_device.c
net/bridge/br_if.c
net/bridge/br_notify.c
net/bridge/netfilter/ebtable_broute.c
net/bridge/netfilter/ebtables.c
net/caif/cfcnfg.c
net/caif/cfctrl.c
net/caif/cfdbgl.c
net/caif/cfdgml.c
net/caif/cffrml.c
net/caif/cfmuxl.c
net/caif/cfrfml.c
net/caif/cfserl.c
net/caif/cfsrvl.c
net/caif/cfutill.c
net/caif/cfveil.c
net/caif/cfvidl.c
net/can/af_can.c
net/core/Makefile
net/core/datagram.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/dst.c
net/core/fib_rules.c
net/core/filter.c
net/core/kmap_skb.h
net/core/neighbour.c
net/core/net-sysfs.c
net/core/netpoll.c
net/core/pktgen.c
net/core/rtnetlink.c
net/core/scm.c
net/core/secure_seq.c [new file with mode: 0644]
net/core/skbuff.c
net/core/sock.c
net/core/user_dma.c
net/dccp/ccids/ccid2.c
net/dccp/ccids/ccid2.h
net/dccp/dccp.h
net/dccp/feat.c
net/dccp/feat.h
net/dccp/ipv4.c
net/dccp/ipv6.c
net/dccp/proto.c
net/decnet/dn_dev.c
net/dsa/slave.c
net/ieee802154/6lowpan.c [new file with mode: 0644]
net/ieee802154/6lowpan.h [new file with mode: 0644]
net/ieee802154/Kconfig
net/ieee802154/Makefile
net/ipv4/devinet.c
net/ipv4/fib_trie.c
net/ipv4/gre.c
net/ipv4/igmp.c
net/ipv4/inet_hashtables.c
net/ipv4/inet_lro.c
net/ipv4/inetpeer.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ipip.c
net/ipv4/ipmr.c
net/ipv4/netfilter.c
net/ipv4/netfilter/nf_nat_amanda.c
net/ipv4/netfilter/nf_nat_core.c
net/ipv4/netfilter/nf_nat_ftp.c
net/ipv4/netfilter/nf_nat_h323.c
net/ipv4/netfilter/nf_nat_irc.c
net/ipv4/netfilter/nf_nat_pptp.c
net/ipv4/netfilter/nf_nat_proto_common.c
net/ipv4/netfilter/nf_nat_sip.c
net/ipv4/netfilter/nf_nat_snmp_basic.c
net/ipv4/netfilter/nf_nat_standalone.c
net/ipv4/netfilter/nf_nat_tftp.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/syncookies.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/datagram.c
net/ipv6/exthdrs.c
net/ipv6/icmp.c
net/ipv6/inet6_connection_sock.c
net/ipv6/inet6_hashtables.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ipv6_sockglue.c
net/ipv6/ndisc.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/syncookies.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/irda/irlan/irlan_eth.c
net/iucv/Kconfig
net/iucv/af_iucv.c
net/iucv/iucv.c
net/mac80211/agg-rx.c
net/mac80211/cfg.c
net/mac80211/ibss.c
net/mac80211/iface.c
net/mac80211/mesh_pathtbl.c
net/mac80211/sta_info.c
net/netfilter/core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_ecache.c
net/netfilter/nf_conntrack_extend.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_log.c
net/netfilter/nf_queue.c
net/netfilter/nfnetlink.c
net/netlabel/Makefile
net/netlabel/netlabel_addrlist.c
net/netlabel/netlabel_addrlist.h
net/netlabel/netlabel_cipso_v4.c
net/netlabel/netlabel_cipso_v4.h
net/netlabel/netlabel_domainhash.c
net/netlabel/netlabel_domainhash.h
net/netlabel/netlabel_kapi.c
net/netlabel/netlabel_mgmt.c
net/netlabel/netlabel_mgmt.h
net/netlabel/netlabel_unlabeled.c
net/netlabel/netlabel_unlabeled.h
net/netlabel/netlabel_user.c
net/netlabel/netlabel_user.h
net/netlink/af_netlink.c
net/packet/af_packet.c
net/phonet/af_phonet.c
net/phonet/pn_dev.c
net/phonet/socket.c
net/sched/act_mirred.c
net/sched/sch_prio.c
net/sched/sch_sfb.c
net/sched/sch_sfq.c
net/sctp/associola.c
net/sctp/outqueue.c
net/sctp/sm_make_chunk.c
net/sctp/sm_statefuns.c
net/socket.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/xprt.c
net/unix/af_unix.c
net/xfrm/xfrm_algo.c
net/xfrm/xfrm_ipcomp.c
net/xfrm/xfrm_user.c
scripts/kconfig/Makefile
scripts/kconfig/conf.c
scripts/kconfig/confdata.c
scripts/kconfig/expr.c
scripts/kconfig/expr.h
scripts/kconfig/gconf.c
scripts/kconfig/kconfig_load.c [deleted file]
scripts/kconfig/kxgettext.c
scripts/kconfig/lkc.h
scripts/kconfig/lkc_proto.h
scripts/kconfig/mconf.c
scripts/kconfig/menu.c
scripts/kconfig/nconf.c
scripts/kconfig/qconf.cc
scripts/kconfig/qconf.h
scripts/kconfig/symbol.c
scripts/kconfig/util.c
scripts/kconfig/zconf.l
scripts/kconfig/zconf.lex.c_shipped
scripts/kconfig/zconf.tab.c_shipped
scripts/kconfig/zconf.y
security/selinux/hooks.c
security/selinux/include/netif.h
security/selinux/include/netlabel.h
security/selinux/include/netnode.h
security/selinux/include/netport.h
security/selinux/netif.c
security/selinux/netlabel.c
security/selinux/netnode.c
security/selinux/netport.c
security/selinux/selinuxfs.c
security/selinux/ss/ebitmap.c
security/selinux/ss/mls.c
security/selinux/ss/mls.h
security/selinux/ss/policydb.c
security/selinux/ss/services.c
security/smack/smack_lsm.c
security/tomoyo/common.c
sound/core/pcm_compat.c
sound/core/rtctimer.c
sound/core/timer.c
sound/i2c/other/tea575x-tuner.c
sound/oss/pas2_pcm.c
sound/oss/pss.c
sound/pci/Kconfig
sound/pci/asihpi/hpicmn.c
sound/pci/asihpi/hpidspcd.c
sound/pci/asihpi/hpioctl.c
sound/pci/hda/alc269_quirks.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c
sound/pci/rme9652/hdspm.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/wm8915.c [deleted file]
sound/soc/codecs/wm8915.h [deleted file]
sound/soc/codecs/wm8996.c [new file with mode: 0644]
sound/soc/codecs/wm8996.h [new file with mode: 0644]
sound/soc/codecs/wm_hubs.c
sound/soc/samsung/Kconfig
sound/soc/samsung/speyside.c
sound/soc/txx9/txx9aclc.c
sound/usb/caiaq/input.c
sound/usb/endpoint.c
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/quirks-table.h
sound/usb/quirks.c
tools/perf/Makefile
tools/perf/builtin-lock.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/util/config.c
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/header.c
tools/perf/util/probe-event.c
tools/perf/util/python.c
tools/perf/util/setup.py
tools/perf/util/symbol.c
tools/power/cpupower/.gitignore [new file with mode: 0644]
tools/power/cpupower/Makefile [new file with mode: 0644]
tools/power/cpupower/README [new file with mode: 0644]
tools/power/cpupower/ToDo [new file with mode: 0644]
tools/power/cpupower/bench/Makefile [new file with mode: 0644]
tools/power/cpupower/bench/README-BENCH [new file with mode: 0644]
tools/power/cpupower/bench/benchmark.c [new file with mode: 0644]
tools/power/cpupower/bench/benchmark.h [new file with mode: 0644]
tools/power/cpupower/bench/config.h [new file with mode: 0644]
tools/power/cpupower/bench/cpufreq-bench_plot.sh [new file with mode: 0644]
tools/power/cpupower/bench/cpufreq-bench_script.sh [new file with mode: 0644]
tools/power/cpupower/bench/example.cfg [new file with mode: 0644]
tools/power/cpupower/bench/main.c [new file with mode: 0644]
tools/power/cpupower/bench/parse.c [new file with mode: 0644]
tools/power/cpupower/bench/parse.h [new file with mode: 0644]
tools/power/cpupower/bench/system.c [new file with mode: 0644]
tools/power/cpupower/bench/system.h [new file with mode: 0644]
tools/power/cpupower/debug/i386/Makefile [new file with mode: 0644]
tools/power/cpupower/debug/i386/centrino-decode.c [new file with mode: 0644]
tools/power/cpupower/debug/i386/dump_psb.c [new file with mode: 0644]
tools/power/cpupower/debug/i386/intel_gsic.c [new file with mode: 0644]
tools/power/cpupower/debug/i386/powernow-k8-decode.c [new file with mode: 0644]
tools/power/cpupower/debug/kernel/Makefile [new file with mode: 0644]
tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c [new file with mode: 0644]
tools/power/cpupower/debug/x86_64/Makefile [new file with mode: 0644]
tools/power/cpupower/debug/x86_64/centrino-decode.c [new symlink]
tools/power/cpupower/debug/x86_64/powernow-k8-decode.c [new symlink]
tools/power/cpupower/lib/cpufreq.c [new file with mode: 0644]
tools/power/cpupower/lib/cpufreq.h [new file with mode: 0644]
tools/power/cpupower/lib/sysfs.c [new file with mode: 0644]
tools/power/cpupower/lib/sysfs.h [new file with mode: 0644]
tools/power/cpupower/man/cpupower-frequency-info.1 [new file with mode: 0644]
tools/power/cpupower/man/cpupower-frequency-set.1 [new file with mode: 0644]
tools/power/cpupower/man/cpupower-info.1 [new file with mode: 0644]
tools/power/cpupower/man/cpupower-monitor.1 [new file with mode: 0644]
tools/power/cpupower/man/cpupower-set.1 [new file with mode: 0644]
tools/power/cpupower/man/cpupower.1 [new file with mode: 0644]
tools/power/cpupower/po/cs.po [new file with mode: 0644]
tools/power/cpupower/po/de.po [new file with mode: 0644]
tools/power/cpupower/po/fr.po [new file with mode: 0644]
tools/power/cpupower/po/it.po [new file with mode: 0644]
tools/power/cpupower/po/pt.po [new file with mode: 0644]
tools/power/cpupower/utils/builtin.h [new file with mode: 0644]
tools/power/cpupower/utils/cpufreq-info.c [new file with mode: 0644]
tools/power/cpupower/utils/cpufreq-set.c [new file with mode: 0644]
tools/power/cpupower/utils/cpuidle-info.c [new file with mode: 0644]
tools/power/cpupower/utils/cpupower-info.c [new file with mode: 0644]
tools/power/cpupower/utils/cpupower-set.c [new file with mode: 0644]
tools/power/cpupower/utils/cpupower.c [new file with mode: 0644]
tools/power/cpupower/utils/helpers/amd.c [new file with mode: 0644]
tools/power/cpupower/utils/helpers/bitmask.c [new file with mode: 0644]
tools/power/cpupower/utils/helpers/bitmask.h [new file with mode: 0644]
tools/power/cpupower/utils/helpers/cpuid.c [new file with mode: 0644]
tools/power/cpupower/utils/helpers/helpers.h [new file with mode: 0644]
tools/power/cpupower/utils/helpers/misc.c [new file with mode: 0644]
tools/power/cpupower/utils/helpers/msr.c [new file with mode: 0644]
tools/power/cpupower/utils/helpers/pci.c [new file with mode: 0644]
tools/power/cpupower/utils/helpers/sysfs.c [new file with mode: 0644]
tools/power/cpupower/utils/helpers/sysfs.h [new file with mode: 0644]
tools/power/cpupower/utils/helpers/topology.c [new file with mode: 0644]
tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c [new file with mode: 0644]
tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c [new file with mode: 0644]
tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c [new file with mode: 0644]
tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h [new file with mode: 0644]
tools/power/cpupower/utils/idle_monitor/idle_monitors.def [new file with mode: 0644]
tools/power/cpupower/utils/idle_monitor/idle_monitors.h [new file with mode: 0644]
tools/power/cpupower/utils/idle_monitor/mperf_monitor.c [new file with mode: 0644]
tools/power/cpupower/utils/idle_monitor/nhm_idle.c [new file with mode: 0644]
tools/power/cpupower/utils/idle_monitor/snb_idle.c [new file with mode: 0644]
tools/power/cpupower/utils/version-gen.sh [new file with mode: 0755]
tools/power/x86/turbostat/turbostat.c
tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
tools/slub/slabinfo.c

diff --git a/CREDITS b/CREDITS
index 1deb331..07e32a8 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -504,7 +504,7 @@ N: Dominik Brodowski
 E: linux@brodo.de
 W: http://www.brodo.de/
 P: 1024D/725B37C6  190F 3E77 9C89 3B6D BECD  46EE 67C3 0308 725B 37C6
-D: parts of CPUFreq code, ACPI bugfixes
+D: parts of CPUFreq code, ACPI bugfixes, PCMCIA rewrite, cpufrequtils
 S: Tuebingen, Germany
 
 N: Andries Brouwer
@@ -857,6 +857,10 @@ S: One Dell Way
 S: Round Rock, TX  78682
 S: USA
 
+N: Mattia Dongili
+E: malattia@gmail.com
+D: cpufrequtils (precursor to cpupowerutils)
+
 N: Ben Dooks
 E: ben-linux@fluff.org
 E: ben@simtec.co.uk
@@ -1883,6 +1887,11 @@ S: Kruislaan 419
 S: 1098 VA Amsterdam 
 S: The Netherlands
 
+N: Goran Koruga
+E: korugag@siol.net
+D: cpufrequtils (precursor to cpupowerutils)
+S: Slovenia
+
 N: Jiri Kosina
 E: jikos@jikos.cz
 E: jkosina@suse.cz
@@ -2916,6 +2925,12 @@ S: Schlossbergring 9
 S: 79098 Freiburg
 S: Germany
 
+N: Thomas Renninger
+E: trenn@suse.de
+D: cpupowerutils
+S: SUSE Linux GmbH
+S: Germany
+
 N: Joerg Reuter
 E: jreuter@yaina.de
 W: http://yaina.de/jreuter/
index ddf451e..ff1df4e 100644 (file)
@@ -39,3 +39,9 @@ Description:  Generic interface to platform dependent persistent storage.
                multiple) files based on the record size of the underlying
                persistent storage until at least this amount is reached.
                Default is 10 Kbytes.
+
+               Pstore only supports one backend at a time. If multiple
+               backends are available, the preferred backend may be
+               set by passing the pstore.backend= argument to the kernel at
+               boot time.
+
index 748fe17..b020014 100644 (file)
@@ -22,6 +22,14 @@ Description:
                 mesh will be fragmented or silently discarded if the
                 packet size exceeds the outgoing interface MTU.
 
+What:          /sys/class/net/<mesh_iface>/mesh/ap_isolation
+Date:          May 2011
+Contact:       Antonio Quartulli <ordex@autistici.org>
+Description:
+               Indicates whether the data traffic going from a
+               wireless client to another wireless client will be
+               silently dropped.
+
 What:           /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
 Date:           October 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
index 807fca2..ff53183 100644 (file)
@@ -4,3 +4,20 @@ KernelVersion: 2.6.37
 Contact:       "Ike Panhc <ike.pan@canonical.com>"
 Description:
                Control the power of camera module. 1 means on, 0 means off.
+
+What:          /sys/devices/platform/ideapad/cfg
+Date:          Jun 2011
+KernelVersion: 3.1
+Contact:       "Ike Panhc <ike.pan@canonical.com>"
+Description:
+               Ideapad capability bits.
+               Bit 8-10: 1 - Intel graphic only
+                         2 - ATI graphic only
+                         3 - Nvidia graphic only
+                         4 - Intel and ATI graphic
+                         5 - Intel and Nvidia graphic
+               Bit 16: Bluetooth exist (1 for exist)
+               Bit 17: 3G exist (1 for exist)
+               Bit 18: Wifi exist (1 for exist)
+               Bit 19: Camera exist (1 for exist)
+
index fa6e25b..c940239 100644 (file)
@@ -80,22 +80,13 @@ available tools.
 The limit on the length of lines is 80 columns and this is a strongly
 preferred limit.
 
-Statements longer than 80 columns will be broken into sensible chunks.
-Descendants are always substantially shorter than the parent and are placed
-substantially to the right. The same applies to function headers with a long
-argument list. Long strings are as well broken into shorter strings. The
-only exception to this is where exceeding 80 columns significantly increases
-readability and does not hide information.
-
-void fun(int a, int b, int c)
-{
-       if (condition)
-               printk(KERN_WARNING "Warning this is a long printk with "
-                                               "3 parameters a: %u b: %u "
-                                               "c: %u \n", a, b, c);
-       else
-               next_statement;
-}
+Statements longer than 80 columns will be broken into sensible chunks, unless
+exceeding 80 columns significantly increases readability and does not hide
+information. Descendants are always substantially shorter than the parent and
+are placed substantially to the right. The same applies to function headers
+with a long argument list. However, never break user-visible strings such as
+printk messages, because that breaks the ability to grep for them.
+
 
                Chapter 3: Placing Braces and Spaces
 
index 679034c..720f245 100644 (file)
@@ -8,4 +8,7 @@
 *.dvi
 *.log
 *.out
-media/
+*.png
+*.gif
+media-indices.tmpl
+media-entities.tmpl
index 3cebfa0..66725a3 100644 (file)
@@ -14,7 +14,9 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
            genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
            80211.xml debugobjects.xml sh.xml regulator.xml \
            alsa-driver-api.xml writing-an-alsa-driver.xml \
-           tracepoint.xml media.xml drm.xml
+           tracepoint.xml drm.xml media_api.xml
+
+include $(srctree)/Documentation/DocBook/media/Makefile
 
 ###
 # The build process is as follows (targets):
@@ -32,7 +34,7 @@ PS_METHOD     = $(prefer-db2x)
 
 ###
 # The targets that may be used.
-PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs xmldoclinks
+PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs
 
 BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
 xmldocs: $(BOOKS)
@@ -45,27 +47,14 @@ PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
 pdfdocs: $(PDF)
 
 HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
-htmldocs: $(HTML) xmldoclinks
+htmldocs: $(HTML)
        $(call build_main_index)
        $(call build_images)
+       $(call install_media_images)
 
 MAN := $(patsubst %.xml, %.9, $(BOOKS))
 mandocs: $(MAN)
 
-build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \
-              cp $(srctree)/Documentation/DocBook/dvb/*.png \
-                 $(srctree)/Documentation/DocBook/v4l/*.gif \
-                 $(objtree)/Documentation/DocBook/media/
-
-xmldoclinks:
-ifneq ($(objtree),$(srctree))
-       for dep in dvb media-entities.tmpl media-indices.tmpl v4l; do \
-               rm -f $(objtree)/Documentation/DocBook/$$dep \
-               && ln -s $(srctree)/Documentation/DocBook/$$dep $(objtree)/Documentation/DocBook/ \
-               || exit; \
-       done
-endif
-
 installmandocs: mandocs
        mkdir -p /usr/local/man/man9/
        install Documentation/DocBook/man/*.9.gz /usr/local/man/man9/
@@ -97,11 +86,11 @@ define rule_docproc
         ) > $(dir $@).$(notdir $@).cmd
 endef
 
-%.xml: %.tmpl xmldoclinks FORCE
+%.xml: %.tmpl FORCE
        $(call if_changed_rule,docproc)
 
 ###
-#Read in all saved dependency files 
+#Read in all saved dependency files
 cmd_files := $(wildcard $(foreach f,$(BOOKS),$(dir $(f)).$(notdir $(f)).cmd))
 
 ifneq ($(cmd_files),)
@@ -150,7 +139,7 @@ quiet_cmd_db2pdf = PDF     $@
 
 index = index.html
 main_idx = Documentation/DocBook/$(index)
-build_main_index = rm -rf $(main_idx) && \
+build_main_index = rm -rf $(main_idx); \
                   echo '<h1>Linux Kernel HTML Documentation</h1>' >> $(main_idx) && \
                   echo '<h2>Kernel Version: $(KERNELVERSION)</h2>' >> $(main_idx) && \
                   cat $(HTML) >> $(main_idx)
@@ -242,7 +231,7 @@ clean-files := $(DOCBOOKS) \
 
 clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
 
-cleandocs:
+cleandocs: cleanmediadocs
        $(Q)rm -f $(call objectify, $(clean-files))
        $(Q)rm -rf $(call objectify, $(clean-dirs))
 
diff --git a/Documentation/DocBook/dvb/dvbproperty.xml b/Documentation/DocBook/dvb/dvbproperty.xml
deleted file mode 100644 (file)
index b5365f6..0000000
+++ /dev/null
@@ -1,590 +0,0 @@
-<section id="FE_GET_SET_PROPERTY">
-<title>FE_GET_PROPERTY/FE_SET_PROPERTY</title>
-
-<programlisting>
-/* Reserved fields should be set to 0 */
-struct dtv_property {
-       __u32 cmd;
-       union {
-               __u32 data;
-               struct {
-                       __u8 data[32];
-                       __u32 len;
-                       __u32 reserved1[3];
-                       void *reserved2;
-               } buffer;
-       } u;
-       int result;
-} __attribute__ ((packed));
-
-/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */
-#define DTV_IOCTL_MAX_MSGS 64
-
-struct dtv_properties {
-       __u32 num;
-       struct dtv_property *props;
-};
-</programlisting>
-
-<section id="FE_GET_PROPERTY">
-<title>FE_GET_PROPERTY</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call returns one or more frontend properties. This call only
- requires read-only access to the device.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(int fd, int request = <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>,
- dtv_properties &#x22C6;props);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry align="char">
-<para>int fd</para>
-</entry><entry
- align="char">
-<para>File descriptor returned by a previous call to open().</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int num</para>
-</entry><entry
- align="char">
-<para>Equals <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link> for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct dtv_property *props</para>
-</entry><entry
- align="char">
-<para>Points to the location where the front-end property commands are stored.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>ERRORS</para>
-<informaltable><tgroup cols="2"><tbody><row>
-  <entry align="char"><para>EINVAL</para></entry>
-  <entry align="char"><para>Invalid parameter(s) received or number of parameters out of the range.</para></entry>
- </row><row>
-  <entry align="char"><para>ENOMEM</para></entry>
-  <entry align="char"><para>Out of memory.</para></entry>
- </row><row>
-  <entry align="char"><para>EFAULT</para></entry>
-  <entry align="char"><para>Failure while copying data from/to userspace.</para></entry>
- </row><row>
-  <entry align="char"><para>EOPNOTSUPP</para></entry>
-  <entry align="char"><para>Property type not supported.</para></entry>
- </row></tbody></tgroup></informaltable>
-</section>
-
-<section id="FE_SET_PROPERTY">
-<title>FE_SET_PROPERTY</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call sets one or more frontend properties. This call only
- requires read-only access to the device.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(int fd, int request = <link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>,
- dtv_properties &#x22C6;props);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry align="char">
-<para>int fd</para>
-</entry><entry
- align="char">
-<para>File descriptor returned by a previous call to open().</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int num</para>
-</entry><entry
- align="char">
-<para>Equals <link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link> for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct dtv_property *props</para>
-</entry><entry
- align="char">
-<para>Points to the location where the front-end property commands are stored.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row>
-  <entry align="char"><para>EINVAL</para></entry>
-  <entry align="char"><para>Invalid parameter(s) received or number of parameters out of the range.</para></entry>
- </row><row>
-  <entry align="char"><para>ENOMEM</para></entry>
-  <entry align="char"><para>Out of memory.</para></entry>
- </row><row>
-  <entry align="char"><para>EFAULT</para></entry>
-  <entry align="char"><para>Failure while copying data from/to userspace.</para></entry>
- </row><row>
-  <entry align="char"><para>EOPNOTSUPP</para></entry>
-  <entry align="char"><para>Property type not supported.</para></entry>
- </row></tbody></tgroup></informaltable>
-</section>
-
-<section>
-       <title>Property types</title>
-<para>
-On <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>/<link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>,
-the actual action is determined by the dtv_property cmd/data pairs. With one single ioctl, is possible to
-get/set up to 64 properties. The actual meaning of each property is described on the next sections.
-</para>
-
-<para>The available frontend property types are:</para>
-<programlisting>
-#define DTV_UNDEFINED          0
-#define DTV_TUNE               1
-#define DTV_CLEAR              2
-#define DTV_FREQUENCY          3
-#define DTV_MODULATION         4
-#define DTV_BANDWIDTH_HZ       5
-#define DTV_INVERSION          6
-#define DTV_DISEQC_MASTER      7
-#define DTV_SYMBOL_RATE                8
-#define DTV_INNER_FEC          9
-#define DTV_VOLTAGE            10
-#define DTV_TONE               11
-#define DTV_PILOT              12
-#define DTV_ROLLOFF            13
-#define DTV_DISEQC_SLAVE_REPLY 14
-#define DTV_FE_CAPABILITY_COUNT        15
-#define DTV_FE_CAPABILITY      16
-#define DTV_DELIVERY_SYSTEM    17
-#define DTV_ISDBT_PARTIAL_RECEPTION    18
-#define DTV_ISDBT_SOUND_BROADCASTING   19
-#define DTV_ISDBT_SB_SUBCHANNEL_ID     20
-#define DTV_ISDBT_SB_SEGMENT_IDX       21
-#define DTV_ISDBT_SB_SEGMENT_COUNT     22
-#define DTV_ISDBT_LAYERA_FEC                   23
-#define DTV_ISDBT_LAYERA_MODULATION            24
-#define DTV_ISDBT_LAYERA_SEGMENT_COUNT         25
-#define DTV_ISDBT_LAYERA_TIME_INTERLEAVING     26
-#define DTV_ISDBT_LAYERB_FEC                   27
-#define DTV_ISDBT_LAYERB_MODULATION            28
-#define DTV_ISDBT_LAYERB_SEGMENT_COUNT         29
-#define DTV_ISDBT_LAYERB_TIME_INTERLEAVING     30
-#define DTV_ISDBT_LAYERC_FEC                   31
-#define DTV_ISDBT_LAYERC_MODULATION            32
-#define DTV_ISDBT_LAYERC_SEGMENT_COUNT         33
-#define DTV_ISDBT_LAYERC_TIME_INTERLEAVING     34
-#define DTV_API_VERSION                35
-#define DTV_CODE_RATE_HP       36
-#define DTV_CODE_RATE_LP       37
-#define DTV_GUARD_INTERVAL     38
-#define DTV_TRANSMISSION_MODE  39
-#define DTV_HIERARCHY          40
-#define DTV_ISDBT_LAYER_ENABLED        41
-#define DTV_ISDBS_TS_ID                42
-</programlisting>
-</section>
-
-<section id="fe_property_common">
-       <title>Parameters that are common to all Digital TV standards</title>
-       <section id="DTV_FREQUENCY">
-               <title><constant>DTV_FREQUENCY</constant></title>
-
-               <para>Central frequency of the channel, in HZ.</para>
-
-               <para>Notes:</para>
-               <para>1)For ISDB-T, the channels are usually transmitted with an offset of 143kHz.
-                       E.g. a valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of
-                       the channel which is 6MHz.</para>
-
-               <para>2)As in ISDB-Tsb the channel consists of only one or three segments the
-                       frequency step is 429kHz, 3*429 respectively. As for ISDB-T the
-                       central frequency of the channel is expected.</para>
-       </section>
-
-       <section id="DTV_BANDWIDTH_HZ">
-               <title><constant>DTV_BANDWIDTH_HZ</constant></title>
-
-               <para>Bandwidth for the channel, in HZ.</para>
-
-               <para>Possible values:
-                       <constant>1712000</constant>,
-                       <constant>5000000</constant>,
-                       <constant>6000000</constant>,
-                       <constant>7000000</constant>,
-                       <constant>8000000</constant>,
-                       <constant>10000000</constant>.
-               </para>
-
-               <para>Notes:</para>
-
-               <para>1) For ISDB-T it should be always 6000000Hz (6MHz)</para>
-               <para>2) For ISDB-Tsb it can vary depending on the number of connected segments</para>
-               <para>3) Bandwidth doesn't apply for DVB-C transmissions, as the bandwidth
-                        for DVB-C depends on the symbol rate</para>
-               <para>4) Bandwidth in ISDB-T is fixed (6MHz) or can be easily derived from
-                       other parameters (DTV_ISDBT_SB_SEGMENT_IDX,
-                       DTV_ISDBT_SB_SEGMENT_COUNT).</para>
-               <para>5) DVB-T supports 6, 7 and 8MHz.</para>
-               <para>6) In addition, DVB-T2 supports 1.172, 5 and 10MHz.</para>
-       </section>
-
-       <section id="DTV_DELIVERY_SYSTEM">
-               <title><constant>DTV_DELIVERY_SYSTEM</constant></title>
-
-               <para>Specifies the type of Delivery system</para>
-
-               <para>Possible values: </para>
-<programlisting>
-typedef enum fe_delivery_system {
-       SYS_UNDEFINED,
-       SYS_DVBC_ANNEX_AC,
-       SYS_DVBC_ANNEX_B,
-       SYS_DVBT,
-       SYS_DSS,
-       SYS_DVBS,
-       SYS_DVBS2,
-       SYS_DVBH,
-       SYS_ISDBT,
-       SYS_ISDBS,
-       SYS_ISDBC,
-       SYS_ATSC,
-       SYS_ATSCMH,
-       SYS_DMBTH,
-       SYS_CMMB,
-       SYS_DAB,
-       SYS_DVBT2,
-} fe_delivery_system_t;
-</programlisting>
-
-       </section>
-
-       <section id="DTV_TRANSMISSION_MODE">
-               <title><constant>DTV_TRANSMISSION_MODE</constant></title>
-
-               <para>Specifies the number of carriers used by the standard</para>
-
-               <para>Possible values are:</para>
-<programlisting>
-typedef enum fe_transmit_mode {
-       TRANSMISSION_MODE_2K,
-       TRANSMISSION_MODE_8K,
-       TRANSMISSION_MODE_AUTO,
-       TRANSMISSION_MODE_4K,
-       TRANSMISSION_MODE_1K,
-       TRANSMISSION_MODE_16K,
-       TRANSMISSION_MODE_32K,
-} fe_transmit_mode_t;
-</programlisting>
-
-               <para>Notes:</para>
-               <para>1) ISDB-T supports three carrier/symbol-size: 8K, 4K, 2K. It is called
-                       'mode' in the standard: Mode 1 is 2K, mode 2 is 4K, mode 3 is 8K</para>
-
-               <para>2) If <constant>DTV_TRANSMISSION_MODE</constant> is set the <constant>TRANSMISSION_MODE_AUTO</constant> the
-                       hardware will try to find the correct FFT-size (if capable) and will
-                       use TMCC to fill in the missing parameters.</para>
-               <para>3) DVB-T specifies 2K and 8K as valid sizes.</para>
-               <para>4) DVB-T2 specifies 1K, 2K, 4K, 8K, 16K and 32K.</para>
-       </section>
-
-       <section id="DTV_GUARD_INTERVAL">
-               <title><constant>DTV_GUARD_INTERVAL</constant></title>
-
-               <para>Possible values are:</para>
-<programlisting>
-typedef enum fe_guard_interval {
-       GUARD_INTERVAL_1_32,
-       GUARD_INTERVAL_1_16,
-       GUARD_INTERVAL_1_8,
-       GUARD_INTERVAL_1_4,
-       GUARD_INTERVAL_AUTO,
-       GUARD_INTERVAL_1_128,
-       GUARD_INTERVAL_19_128,
-       GUARD_INTERVAL_19_256,
-} fe_guard_interval_t;
-</programlisting>
-
-               <para>Notes:</para>
-               <para>1) If <constant>DTV_GUARD_INTERVAL</constant> is set the <constant>GUARD_INTERVAL_AUTO</constant> the hardware will
-                       try to find the correct guard interval (if capable) and will use TMCC to fill
-                       in the missing parameters.</para>
-               <para>2) Intervals 1/128, 19/128 and 19/256 are used only for DVB-T2 at present</para>
-       </section>
-</section>
-
-<section id="isdbt">
-       <title>ISDB-T frontend</title>
-       <para>This section describes shortly what are the possible parameters in the Linux
-               DVB-API called "S2API" and now DVB API 5 in order to tune an ISDB-T/ISDB-Tsb
-               demodulator:</para>
-
-       <para>This ISDB-T/ISDB-Tsb API extension should reflect all information
-               needed to tune any ISDB-T/ISDB-Tsb hardware. Of course it is possible
-               that some very sophisticated devices won't need certain parameters to
-               tune.</para>
-
-       <para>The information given here should help application writers to know how
-               to handle ISDB-T and ISDB-Tsb hardware using the Linux DVB-API.</para>
-
-       <para>The details given here about ISDB-T and ISDB-Tsb are just enough to
-               basically show the dependencies between the needed parameter values,
-               but surely some information is left out. For more detailed information
-               see the following documents:</para>
-
-       <para>ARIB STD-B31 - "Transmission System for Digital Terrestrial
-               Television Broadcasting" and</para>
-       <para>ARIB TR-B14 - "Operational Guidelines for Digital Terrestrial
-               Television Broadcasting".</para>
-
-       <para>In order to read this document one has to have some knowledge the
-               channel structure in ISDB-T and ISDB-Tsb. I.e. it has to be known to
-               the reader that an ISDB-T channel consists of 13 segments, that it can
-               have up to 3 layer sharing those segments, and things like that.</para>
-
-       <para>Parameters used by ISDB-T and ISDB-Tsb.</para>
-
-       <section id="isdbt-new-parms">
-               <title>ISDB-T only parameters</title>
-
-               <section id="isdbt-part-rec">
-                       <title><constant>DTV_ISDBT_PARTIAL_RECEPTION</constant></title>
-
-                       <para><constant>If DTV_ISDBT_SOUND_BROADCASTING</constant> is '0' this bit-field represents whether
-                               the channel is in partial reception mode or not.</para>
-
-                       <para>If '1' <constant>DTV_ISDBT_LAYERA_*</constant> values are assigned to the center segment and
-                               <constant>DTV_ISDBT_LAYERA_SEGMENT_COUNT</constant> has to be '1'.</para>
-
-                       <para>If in addition <constant>DTV_ISDBT_SOUND_BROADCASTING</constant> is '1'
-                               <constant>DTV_ISDBT_PARTIAL_RECEPTION</constant> represents whether this ISDB-Tsb channel
-                               is consisting of one segment and layer or three segments and two layers.</para>
-
-                       <para>Possible values: 0, 1, -1 (AUTO)</para>
-               </section>
-
-               <section id="isdbt-sound-bcast">
-                       <title><constant>DTV_ISDBT_SOUND_BROADCASTING</constant></title>
-
-                       <para>This field represents whether the other DTV_ISDBT_*-parameters are
-                               referring to an ISDB-T and an ISDB-Tsb channel. (See also
-                               <constant>DTV_ISDBT_PARTIAL_RECEPTION</constant>).</para>
-
-                       <para>Possible values: 0, 1, -1 (AUTO)</para>
-               </section>
-
-               <section id="isdbt-sb-ch-id">
-                       <title><constant>DTV_ISDBT_SB_SUBCHANNEL_ID</constant></title>
-
-                       <para>This field only applies if <constant>DTV_ISDBT_SOUND_BROADCASTING</constant> is '1'.</para>
-
-                       <para>(Note of the author: This might not be the correct description of the
-                               <constant>SUBCHANNEL-ID</constant> in all details, but it is my understanding of the technical
-                               background needed to program a device)</para>
-
-                       <para>An ISDB-Tsb channel (1 or 3 segments) can be broadcasted alone or in a
-                               set of connected ISDB-Tsb channels. In this set of channels every
-                               channel can be received independently. The number of connected
-                               ISDB-Tsb segment can vary, e.g. depending on the frequency spectrum
-                               bandwidth available.</para>
-
-                       <para>Example: Assume 8 ISDB-Tsb connected segments are broadcasted. The
-                               broadcaster has several possibilities to put those channels in the
-                               air: Assuming a normal 13-segment ISDB-T spectrum he can align the 8
-                               segments from position 1-8 to 5-13 or anything in between.</para>
-
-                       <para>The underlying layer of segments are subchannels: each segment is
-                               consisting of several subchannels with a predefined IDs. A sub-channel
-                               is used to help the demodulator to synchronize on the channel.</para>
-
-                       <para>An ISDB-T channel is always centered over all sub-channels. As for
-                               the example above, in ISDB-Tsb it is no longer as simple as that.</para>
-
-                       <para><constant>The DTV_ISDBT_SB_SUBCHANNEL_ID</constant> parameter is used to give the
-                               sub-channel ID of the segment to be demodulated.</para>
-
-                       <para>Possible values: 0 .. 41, -1 (AUTO)</para>
-               </section>
-
-               <section id="isdbt-sb-seg-idx">
-
-                       <title><constant>DTV_ISDBT_SB_SEGMENT_IDX</constant></title>
-
-                       <para>This field only applies if <constant>DTV_ISDBT_SOUND_BROADCASTING</constant> is '1'.</para>
-
-                       <para><constant>DTV_ISDBT_SB_SEGMENT_IDX</constant> gives the index of the segment to be
-                               demodulated for an ISDB-Tsb channel where several of them are
-                               transmitted in the connected manner.</para>
-
-                       <para>Possible values: 0 .. <constant>DTV_ISDBT_SB_SEGMENT_COUNT</constant> - 1</para>
-
-                       <para>Note: This value cannot be determined by an automatic channel search.</para>
-               </section>
-
-               <section id="isdbt-sb-seg-cnt">
-                       <title><constant>DTV_ISDBT_SB_SEGMENT_COUNT</constant></title>
-
-                       <para>This field only applies if <constant>DTV_ISDBT_SOUND_BROADCASTING</constant> is '1'.</para>
-
-                       <para><constant>DTV_ISDBT_SB_SEGMENT_COUNT</constant> gives the total count of connected ISDB-Tsb
-                               channels.</para>
-
-                       <para>Possible values: 1 .. 13</para>
-
-                       <para>Note: This value cannot be determined by an automatic channel search.</para>
-               </section>
-
-               <section id="isdb-hierq-layers">
-                       <title>Hierarchical layers</title>
-
-                       <para>ISDB-T channels can be coded hierarchically. As opposed to DVB-T in
-                               ISDB-T hierarchical layers can be decoded simultaneously. For that
-                               reason a ISDB-T demodulator has 3 viterbi and 3 reed-solomon-decoders.</para>
-
-                       <para>ISDB-T has 3 hierarchical layers which each can use a part of the
-                               available segments. The total number of segments over all layers has
-                               to 13 in ISDB-T.</para>
-
-                       <section id="isdbt-layer-ena">
-                               <title><constant>DTV_ISDBT_LAYER_ENABLED</constant></title>
-
-                               <para>Hierarchical reception in ISDB-T is achieved by enabling or disabling
-                                       layers in the decoding process. Setting all bits of
-                                       <constant>DTV_ISDBT_LAYER_ENABLED</constant> to '1' forces all layers (if applicable) to be
-                                       demodulated. This is the default.</para>
-
-                               <para>If the channel is in the partial reception mode
-                                       (<constant>DTV_ISDBT_PARTIAL_RECEPTION</constant> = 1) the central segment can be decoded
-                                       independently of the other 12 segments. In that mode layer A has to
-                                       have a <constant>SEGMENT_COUNT</constant> of 1.</para>
-
-                               <para>In ISDB-Tsb only layer A is used, it can be 1 or 3 in ISDB-Tsb
-                                       according to <constant>DTV_ISDBT_PARTIAL_RECEPTION</constant>. <constant>SEGMENT_COUNT</constant> must be filled
-                                       accordingly.</para>
-
-                               <para>Possible values: 0x1, 0x2, 0x4 (|-able)</para>
-
-                               <para><constant>DTV_ISDBT_LAYER_ENABLED[0:0]</constant> - layer A</para>
-                               <para><constant>DTV_ISDBT_LAYER_ENABLED[1:1]</constant> - layer B</para>
-                               <para><constant>DTV_ISDBT_LAYER_ENABLED[2:2]</constant> - layer C</para>
-                               <para><constant>DTV_ISDBT_LAYER_ENABLED[31:3]</constant> unused</para>
-                       </section>
-
-                       <section id="isdbt-layer-fec">
-                               <title><constant>DTV_ISDBT_LAYER*_FEC</constant></title>
-
-                               <para>Possible values: <constant>FEC_AUTO</constant>, <constant>FEC_1_2</constant>, <constant>FEC_2_3</constant>, <constant>FEC_3_4</constant>, <constant>FEC_5_6</constant>, <constant>FEC_7_8</constant></para>
-                       </section>
-
-                       <section id="isdbt-layer-mod">
-                               <title><constant>DTV_ISDBT_LAYER*_MODULATION</constant></title>
-
-                               <para>Possible values: <constant>QAM_AUTO</constant>, QP<constant>SK, QAM_16</constant>, <constant>QAM_64</constant>, <constant>DQPSK</constant></para>
-
-                               <para>Note: If layer C is <constant>DQPSK</constant> layer B has to be <constant>DQPSK</constant>. If layer B is <constant>DQPSK</constant>
-                                       and <constant>DTV_ISDBT_PARTIAL_RECEPTION</constant>=0 layer has to be <constant>DQPSK</constant>.</para>
-                       </section>
-
-                       <section id="isdbt-layer-seg-cnt">
-                               <title><constant>DTV_ISDBT_LAYER*_SEGMENT_COUNT</constant></title>
-
-                               <para>Possible values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -1 (AUTO)</para>
-
-                               <para>Note: Truth table for <constant>DTV_ISDBT_SOUND_BROADCASTING</constant> and
-                                       <constant>DTV_ISDBT_PARTIAL_RECEPTION</constant> and <constant>LAYER</constant>*_SEGMENT_COUNT</para>
-
-                               <informaltable id="isdbt-layer_seg-cnt-table">
-                                       <tgroup cols="6">
-
-                                               <tbody>
-                                                       <row>
-                                                               <entry>PR</entry>
-                                                               <entry>SB</entry>
-                                                               <entry>Layer A width</entry>
-                                                               <entry>Layer B width</entry>
-                                                               <entry>Layer C width</entry>
-                                                               <entry>total width</entry>
-                                                       </row>
-
-                                                       <row>
-                                                               <entry>0</entry>
-                                                               <entry>0</entry>
-                                                               <entry>1 .. 13</entry>
-                                                               <entry>1 .. 13</entry>
-                                                               <entry>1 .. 13</entry>
-                                                               <entry>13</entry>
-                                                       </row>
-
-                                                       <row>
-                                                               <entry>1</entry>
-                                                               <entry>0</entry>
-                                                               <entry>1</entry>
-                                                               <entry>1 .. 13</entry>
-                                                               <entry>1 .. 13</entry>
-                                                               <entry>13</entry>
-                                                       </row>
-
-                                                       <row>
-                                                               <entry>0</entry>
-                                                               <entry>1</entry>
-                                                               <entry>1</entry>
-                                                               <entry>0</entry>
-                                                               <entry>0</entry>
-                                                               <entry>1</entry>
-                                                       </row>
-
-                                                       <row>
-                                                               <entry>1</entry>
-                                                               <entry>1</entry>
-                                                               <entry>1</entry>
-                                                               <entry>2</entry>
-                                                               <entry>0</entry>
-                                                               <entry>13</entry>
-                                                       </row>
-                                               </tbody>
-
-                                       </tgroup>
-                               </informaltable>
-
-                       </section>
-
-                       <section id="isdbt_layer_t_interl">
-                               <title><constant>DTV_ISDBT_LAYER*_TIME_INTERLEAVING</constant></title>
-
-                               <para>Possible values: 0, 1, 2, 3, -1 (AUTO)</para>
-
-                               <para>Note: The real inter-leaver depth-names depend on the mode (fft-size); the values
-                                       here are referring to what can be found in the TMCC-structure -
-                                       independent of the mode.</para>
-                       </section>
-               </section>
-       </section>
-       <section id="dvbt2-params">
-               <title>DVB-T2 parameters</title>
-               
-               <para>This section covers parameters that apply only to the DVB-T2 delivery method. DVB-T2
-                       support is currently in the early stages development so expect this section to grow
-                       and become more detailed with time.</para>
-
-               <section id="dvbt2-plp-id">
-                       <title><constant>DTV_DVBT2_PLP_ID</constant></title>
-
-                       <para>DVB-T2 supports Physical Layer Pipes (PLP) to allow transmission of
-                               many data types via a single multiplex. The API will soon support this
-                               at which point this section will be expanded.</para>
-               </section>
-       </section>
-</section>
-</section>
diff --git a/Documentation/DocBook/dvb/dvbstb.png b/Documentation/DocBook/dvb/dvbstb.png
deleted file mode 100644 (file)
index 9b8f372..0000000
Binary files a/Documentation/DocBook/dvb/dvbstb.png and /dev/null differ
diff --git a/Documentation/DocBook/dvb/frontend.h.xml b/Documentation/DocBook/dvb/frontend.h.xml
deleted file mode 100644 (file)
index d792f78..0000000
+++ /dev/null
@@ -1,428 +0,0 @@
-<programlisting>
-/*
- * frontend.h
- *
- * Copyright (C) 2000 Marcus Metzler &lt;marcus@convergence.de&gt;
- *                  Ralph  Metzler &lt;ralph@convergence.de&gt;
- *                  Holger Waechtler &lt;holger@convergence.de&gt;
- *                  Andre Draszik &lt;ad@convergence.de&gt;
- *                  for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser 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 _DVBFRONTEND_H_
-#define _DVBFRONTEND_H_
-
-#include &lt;linux/types.h&gt;
-
-typedef enum fe_type {
-        FE_QPSK,
-        FE_QAM,
-        FE_OFDM,
-        FE_ATSC
-} fe_type_t;
-
-
-typedef enum fe_caps {
-        FE_IS_STUPID                    = 0,
-        FE_CAN_INVERSION_AUTO           = 0x1,
-        FE_CAN_FEC_1_2                  = 0x2,
-        FE_CAN_FEC_2_3                  = 0x4,
-        FE_CAN_FEC_3_4                  = 0x8,
-        FE_CAN_FEC_4_5                  = 0x10,
-        FE_CAN_FEC_5_6                  = 0x20,
-        FE_CAN_FEC_6_7                  = 0x40,
-        FE_CAN_FEC_7_8                  = 0x80,
-        FE_CAN_FEC_8_9                  = 0x100,
-        FE_CAN_FEC_AUTO                 = 0x200,
-        FE_CAN_QPSK                     = 0x400,
-        FE_CAN_QAM_16                   = 0x800,
-        FE_CAN_QAM_32                   = 0x1000,
-        FE_CAN_QAM_64                   = 0x2000,
-        FE_CAN_QAM_128                  = 0x4000,
-        FE_CAN_QAM_256                  = 0x8000,
-        FE_CAN_QAM_AUTO                 = 0x10000,
-        FE_CAN_TRANSMISSION_MODE_AUTO   = 0x20000,
-        FE_CAN_BANDWIDTH_AUTO           = 0x40000,
-        FE_CAN_GUARD_INTERVAL_AUTO      = 0x80000,
-        FE_CAN_HIERARCHY_AUTO           = 0x100000,
-        FE_CAN_8VSB                     = 0x200000,
-        FE_CAN_16VSB                    = 0x400000,
-        FE_HAS_EXTENDED_CAPS            = 0x800000,   /* We need more bitspace for newer APIs, indicate this. */
-        FE_CAN_TURBO_FEC                = 0x8000000,  /* frontend supports "turbo fec modulation" */
-        FE_CAN_2G_MODULATION            = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */
-        FE_NEEDS_BENDING                = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */
-        FE_CAN_RECOVER                  = 0x40000000, /* frontend can recover from a cable unplug automatically */
-        FE_CAN_MUTE_TS                  = 0x80000000  /* frontend can stop spurious TS data output */
-} fe_caps_t;
-
-
-struct dvb_frontend_info {
-        char       name[128];
-        fe_type_t  type;
-        __u32      frequency_min;
-        __u32      frequency_max;
-        __u32      frequency_stepsize;
-        __u32      frequency_tolerance;
-        __u32      symbol_rate_min;
-        __u32      symbol_rate_max;
-        __u32      symbol_rate_tolerance;       /* ppm */
-        __u32      notifier_delay;              /* DEPRECATED */
-        fe_caps_t  caps;
-};
-
-
-/**
- *  Check out the DiSEqC bus spec available on http://www.eutelsat.org/ for
- *  the meaning of this struct...
- */
-struct dvb_diseqc_master_cmd {
-        __u8 msg [6];   /*  { framing, address, command, data [3] } */
-        __u8 msg_len;   /*  valid values are 3...6  */
-};
-
-
-struct dvb_diseqc_slave_reply {
-        __u8 msg [4];   /*  { framing, data [3] } */
-        __u8 msg_len;   /*  valid values are 0...4, 0 means no msg  */
-        int  timeout;   /*  return from ioctl after timeout ms with */
-};                      /*  errorcode when no message was received  */
-
-
-typedef enum fe_sec_voltage {
-        SEC_VOLTAGE_13,
-        SEC_VOLTAGE_18,
-        SEC_VOLTAGE_OFF
-} fe_sec_voltage_t;
-
-
-typedef enum fe_sec_tone_mode {
-        SEC_TONE_ON,
-        SEC_TONE_OFF
-} fe_sec_tone_mode_t;
-
-
-typedef enum fe_sec_mini_cmd {
-        SEC_MINI_A,
-        SEC_MINI_B
-} fe_sec_mini_cmd_t;
-
-
-typedef enum fe_status {
-        FE_HAS_SIGNAL   = 0x01,   /* found something above the noise level */
-        FE_HAS_CARRIER  = 0x02,   /* found a DVB signal  */
-        FE_HAS_VITERBI  = 0x04,   /* FEC is stable  */
-        FE_HAS_SYNC     = 0x08,   /* found sync bytes  */
-        FE_HAS_LOCK     = 0x10,   /* everything's working... */
-        FE_TIMEDOUT     = 0x20,   /* no lock within the last ~2 seconds */
-        FE_REINIT       = 0x40    /* frontend was reinitialized,  */
-} fe_status_t;                    /* application is recommended to reset */
-                                  /* DiSEqC, tone and parameters */
-
-typedef enum fe_spectral_inversion {
-        INVERSION_OFF,
-        INVERSION_ON,
-        INVERSION_AUTO
-} fe_spectral_inversion_t;
-
-
-typedef enum fe_code_rate {
-        FEC_NONE = 0,
-        FEC_1_2,
-        FEC_2_3,
-        FEC_3_4,
-        FEC_4_5,
-        FEC_5_6,
-        FEC_6_7,
-        FEC_7_8,
-        FEC_8_9,
-        FEC_AUTO,
-        FEC_3_5,
-        FEC_9_10,
-} fe_code_rate_t;
-
-
-typedef enum fe_modulation {
-        QPSK,
-        QAM_16,
-        QAM_32,
-        QAM_64,
-        QAM_128,
-        QAM_256,
-        QAM_AUTO,
-        VSB_8,
-        VSB_16,
-        PSK_8,
-        APSK_16,
-        APSK_32,
-        DQPSK,
-} fe_modulation_t;
-
-typedef enum fe_transmit_mode {
-        TRANSMISSION_MODE_2K,
-        TRANSMISSION_MODE_8K,
-        TRANSMISSION_MODE_AUTO,
-        TRANSMISSION_MODE_4K,
-        TRANSMISSION_MODE_1K,
-        TRANSMISSION_MODE_16K,
-        TRANSMISSION_MODE_32K,
-} fe_transmit_mode_t;
-
-typedef enum fe_bandwidth {
-        BANDWIDTH_8_MHZ,
-        BANDWIDTH_7_MHZ,
-        BANDWIDTH_6_MHZ,
-        BANDWIDTH_AUTO,
-        BANDWIDTH_5_MHZ,
-        BANDWIDTH_10_MHZ,
-        BANDWIDTH_1_712_MHZ,
-} fe_bandwidth_t;
-
-
-typedef enum fe_guard_interval {
-        GUARD_INTERVAL_1_32,
-        GUARD_INTERVAL_1_16,
-        GUARD_INTERVAL_1_8,
-        GUARD_INTERVAL_1_4,
-        GUARD_INTERVAL_AUTO,
-        GUARD_INTERVAL_1_128,
-        GUARD_INTERVAL_19_128,
-        GUARD_INTERVAL_19_256,
-} fe_guard_interval_t;
-
-
-typedef enum fe_hierarchy {
-        HIERARCHY_NONE,
-        HIERARCHY_1,
-        HIERARCHY_2,
-        HIERARCHY_4,
-        HIERARCHY_AUTO
-} fe_hierarchy_t;
-
-
-struct dvb_qpsk_parameters {
-        __u32           symbol_rate;  /* symbol rate in Symbols per second */
-        fe_code_rate_t  fec_inner;    /* forward error correction (see above) */
-};
-
-struct dvb_qam_parameters {
-        __u32           symbol_rate; /* symbol rate in Symbols per second */
-        fe_code_rate_t  fec_inner;   /* forward error correction (see above) */
-        fe_modulation_t modulation;  /* modulation type (see above) */
-};
-
-struct dvb_vsb_parameters {
-        fe_modulation_t modulation;  /* modulation type (see above) */
-};
-
-struct dvb_ofdm_parameters {
-        fe_bandwidth_t      bandwidth;
-        fe_code_rate_t      code_rate_HP;  /* high priority stream code rate */
-        fe_code_rate_t      code_rate_LP;  /* low priority stream code rate */
-        fe_modulation_t     constellation; /* modulation type (see above) */
-        fe_transmit_mode_t  transmission_mode;
-        fe_guard_interval_t guard_interval;
-        fe_hierarchy_t      hierarchy_information;
-};
-
-
-struct dvb_frontend_parameters {
-        __u32 frequency;     /* (absolute) frequency in Hz for QAM/OFDM/ATSC */
-                             /* intermediate frequency in kHz for QPSK */
-        fe_spectral_inversion_t inversion;
-        union {
-                struct dvb_qpsk_parameters qpsk;
-                struct dvb_qam_parameters  qam;
-                struct dvb_ofdm_parameters ofdm;
-                struct dvb_vsb_parameters vsb;
-        } u;
-};
-
-
-struct dvb_frontend_event {
-        fe_status_t status;
-        struct dvb_frontend_parameters parameters;
-};
-
-/* S2API Commands */
-#define DTV_UNDEFINED           0
-#define DTV_TUNE                1
-#define DTV_CLEAR               2
-#define DTV_FREQUENCY           3
-#define DTV_MODULATION          4
-#define DTV_BANDWIDTH_HZ        5
-#define DTV_INVERSION           6
-#define DTV_DISEQC_MASTER       7
-#define DTV_SYMBOL_RATE         8
-#define DTV_INNER_FEC           9
-#define DTV_VOLTAGE             10
-#define DTV_TONE                11
-#define DTV_PILOT               12
-#define DTV_ROLLOFF             13
-#define DTV_DISEQC_SLAVE_REPLY  14
-
-/* Basic enumeration set for querying unlimited capabilities */
-#define DTV_FE_CAPABILITY_COUNT 15
-#define DTV_FE_CAPABILITY       16
-#define DTV_DELIVERY_SYSTEM     17
-
-/* ISDB-T and ISDB-Tsb */
-#define DTV_ISDBT_PARTIAL_RECEPTION     18
-#define DTV_ISDBT_SOUND_BROADCASTING    19
-
-#define DTV_ISDBT_SB_SUBCHANNEL_ID      20
-#define DTV_ISDBT_SB_SEGMENT_IDX        21
-#define DTV_ISDBT_SB_SEGMENT_COUNT      22
-
-#define DTV_ISDBT_LAYERA_FEC                    23
-#define DTV_ISDBT_LAYERA_MODULATION             24
-#define DTV_ISDBT_LAYERA_SEGMENT_COUNT          25
-#define DTV_ISDBT_LAYERA_TIME_INTERLEAVING      26
-
-#define DTV_ISDBT_LAYERB_FEC                    27
-#define DTV_ISDBT_LAYERB_MODULATION             28
-#define DTV_ISDBT_LAYERB_SEGMENT_COUNT          29
-#define DTV_ISDBT_LAYERB_TIME_INTERLEAVING      30
-
-#define DTV_ISDBT_LAYERC_FEC                    31
-#define DTV_ISDBT_LAYERC_MODULATION             32
-#define DTV_ISDBT_LAYERC_SEGMENT_COUNT          33
-#define DTV_ISDBT_LAYERC_TIME_INTERLEAVING      34
-
-#define DTV_API_VERSION         35
-
-#define DTV_CODE_RATE_HP        36
-#define DTV_CODE_RATE_LP        37
-#define DTV_GUARD_INTERVAL      38
-#define DTV_TRANSMISSION_MODE   39
-#define DTV_HIERARCHY           40
-
-#define DTV_ISDBT_LAYER_ENABLED 41
-
-#define DTV_ISDBS_TS_ID         42
-
-#define DTV_DVBT2_PLP_ID       43
-
-#define DTV_MAX_COMMAND                         DTV_DVBT2_PLP_ID
-
-typedef enum fe_pilot {
-        PILOT_ON,
-        PILOT_OFF,
-        PILOT_AUTO,
-} fe_pilot_t;
-
-typedef enum fe_rolloff {
-        ROLLOFF_35, /* Implied value in DVB-S, default for DVB-S2 */
-        ROLLOFF_20,
-        ROLLOFF_25,
-        ROLLOFF_AUTO,
-} fe_rolloff_t;
-
-typedef enum fe_delivery_system {
-        SYS_UNDEFINED,
-        SYS_DVBC_ANNEX_AC,
-        SYS_DVBC_ANNEX_B,
-        SYS_DVBT,
-        SYS_DSS,
-        SYS_DVBS,
-        SYS_DVBS2,
-        SYS_DVBH,
-        SYS_ISDBT,
-        SYS_ISDBS,
-        SYS_ISDBC,
-        SYS_ATSC,
-        SYS_ATSCMH,
-        SYS_DMBTH,
-        SYS_CMMB,
-        SYS_DAB,
-        SYS_DVBT2,
-} fe_delivery_system_t;
-
-struct dtv_cmds_h {
-        char    *name;          /* A display name for debugging purposes */
-
-        __u32   cmd;            /* A unique ID */
-
-        /* Flags */
-        __u32   set:1;          /* Either a set or get property */
-        __u32   buffer:1;       /* Does this property use the buffer? */
-        __u32   reserved:30;    /* Align */
-};
-
-struct dtv_property {
-        __u32 cmd;
-        __u32 reserved[3];
-        union {
-                __u32 data;
-                struct {
-                        __u8 data[32];
-                        __u32 len;
-                        __u32 reserved1[3];
-                        void *reserved2;
-                } buffer;
-        } u;
-        int result;
-} __attribute__ ((packed));
-
-/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */
-#define DTV_IOCTL_MAX_MSGS 64
-
-struct dtv_properties {
-        __u32 num;
-        struct dtv_property *props;
-};
-
-#define <link linkend="FE_GET_PROPERTY">FE_SET_PROPERTY</link>            _IOW('o', 82, struct dtv_properties)
-#define <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>            _IOR('o', 83, struct dtv_properties)
-
-
-/**
- * When set, this flag will disable any zigzagging or other "normal" tuning
- * behaviour. Additionally, there will be no automatic monitoring of the lock
- * status, and hence no frontend events will be generated. If a frontend device
- * is closed, this flag will be automatically turned off when the device is
- * reopened read-write.
- */
-#define FE_TUNE_MODE_ONESHOT 0x01
-
-
-#define <link linkend="FE_GET_INFO">FE_GET_INFO</link>                _IOR('o', 61, struct dvb_frontend_info)
-
-#define <link linkend="FE_DISEQC_RESET_OVERLOAD">FE_DISEQC_RESET_OVERLOAD</link>   _IO('o', 62)
-#define <link linkend="FE_DISEQC_SEND_MASTER_CMD">FE_DISEQC_SEND_MASTER_CMD</link>  _IOW('o', 63, struct dvb_diseqc_master_cmd)
-#define <link linkend="FE_DISEQC_RECV_SLAVE_REPLY">FE_DISEQC_RECV_SLAVE_REPLY</link> _IOR('o', 64, struct dvb_diseqc_slave_reply)
-#define <link linkend="FE_DISEQC_SEND_BURST">FE_DISEQC_SEND_BURST</link>       _IO('o', 65)  /* fe_sec_mini_cmd_t */
-
-#define <link linkend="FE_SET_TONE">FE_SET_TONE</link>                _IO('o', 66)  /* fe_sec_tone_mode_t */
-#define <link linkend="FE_SET_VOLTAGE">FE_SET_VOLTAGE</link>             _IO('o', 67)  /* fe_sec_voltage_t */
-#define <link linkend="FE_ENABLE_HIGH_LNB_VOLTAGE">FE_ENABLE_HIGH_LNB_VOLTAGE</link> _IO('o', 68)  /* int */
-
-#define <link linkend="FE_READ_STATUS">FE_READ_STATUS</link>             _IOR('o', 69, fe_status_t)
-#define <link linkend="FE_READ_BER">FE_READ_BER</link>                _IOR('o', 70, __u32)
-#define <link linkend="FE_READ_SIGNAL_STRENGTH">FE_READ_SIGNAL_STRENGTH</link>    _IOR('o', 71, __u16)
-#define <link linkend="FE_READ_SNR">FE_READ_SNR</link>                _IOR('o', 72, __u16)
-#define <link linkend="FE_READ_UNCORRECTED_BLOCKS">FE_READ_UNCORRECTED_BLOCKS</link> _IOR('o', 73, __u32)
-
-#define <link linkend="FE_SET_FRONTEND">FE_SET_FRONTEND</link>            _IOW('o', 76, struct dvb_frontend_parameters)
-#define <link linkend="FE_GET_FRONTEND">FE_GET_FRONTEND</link>            _IOR('o', 77, struct dvb_frontend_parameters)
-#define <link linkend="FE_SET_FRONTEND_TUNE_MODE">FE_SET_FRONTEND_TUNE_MODE</link>  _IO('o', 81) /* unsigned int */
-#define <link linkend="FE_GET_EVENT">FE_GET_EVENT</link>               _IOR('o', 78, struct dvb_frontend_event)
-
-#define <link linkend="FE_DISHNETWORK_SEND_LEGACY_CMD">FE_DISHNETWORK_SEND_LEGACY_CMD</link> _IO('o', 80) /* unsigned int */
-
-#endif /*_DVBFRONTEND_H_*/
-</programlisting>
diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
deleted file mode 100644 (file)
index e5fe094..0000000
+++ /dev/null
@@ -1,464 +0,0 @@
-<!-- Generated file! Do not edit. -->
-
-<!-- Functions -->
-<!ENTITY func-close "<link linkend='func-close'><function>close()</function></link>">
-<!ENTITY func-ioctl "<link linkend='func-ioctl'><function>ioctl()</function></link>">
-<!ENTITY func-mmap "<link linkend='func-mmap'><function>mmap()</function></link>">
-<!ENTITY func-munmap "<link linkend='func-munmap'><function>munmap()</function></link>">
-<!ENTITY func-open "<link linkend='func-open'><function>open()</function></link>">
-<!ENTITY func-poll "<link linkend='func-poll'><function>poll()</function></link>">
-<!ENTITY func-read "<link linkend='func-read'><function>read()</function></link>">
-<!ENTITY func-select "<link linkend='func-select'><function>select()</function></link>">
-<!ENTITY func-write "<link linkend='func-write'><function>write()</function></link>">
-
-<!ENTITY media-func-close "<link linkend='media-func-close'><function>close()</function></link>">
-<!ENTITY media-func-ioctl "<link linkend='media-func-ioctl'><function>ioctl()</function></link>">
-<!ENTITY media-func-open "<link linkend='media-func-open'><function>open()</function></link>">
-
-<!-- Ioctls -->
-<!ENTITY VIDIOC-CROPCAP "<link linkend='vidioc-cropcap'><constant>VIDIOC_CROPCAP</constant></link>">
-<!ENTITY VIDIOC-DBG-G-CHIP-IDENT "<link linkend='vidioc-dbg-g-chip-ident'><constant>VIDIOC_DBG_G_CHIP_IDENT</constant></link>">
-<!ENTITY VIDIOC-DBG-G-REGISTER "<link linkend='vidioc-dbg-g-register'><constant>VIDIOC_DBG_G_REGISTER</constant></link>">
-<!ENTITY VIDIOC-DBG-S-REGISTER "<link linkend='vidioc-dbg-g-register'><constant>VIDIOC_DBG_S_REGISTER</constant></link>">
-<!ENTITY VIDIOC-DQBUF "<link linkend='vidioc-qbuf'><constant>VIDIOC_DQBUF</constant></link>">
-<!ENTITY VIDIOC-DQEVENT "<link linkend='vidioc-dqevent'><constant>VIDIOC_DQEVENT</constant></link>">
-<!ENTITY VIDIOC-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_ENCODER_CMD</constant></link>">
-<!ENTITY VIDIOC-ENUMAUDIO "<link linkend='vidioc-enumaudio'><constant>VIDIOC_ENUMAUDIO</constant></link>">
-<!ENTITY VIDIOC-ENUMAUDOUT "<link linkend='vidioc-enumaudioout'><constant>VIDIOC_ENUMAUDOUT</constant></link>">
-<!ENTITY VIDIOC-ENUMINPUT "<link linkend='vidioc-enuminput'><constant>VIDIOC_ENUMINPUT</constant></link>">
-<!ENTITY VIDIOC-ENUMOUTPUT "<link linkend='vidioc-enumoutput'><constant>VIDIOC_ENUMOUTPUT</constant></link>">
-<!ENTITY VIDIOC-ENUMSTD "<link linkend='vidioc-enumstd'><constant>VIDIOC_ENUMSTD</constant></link>">
-<!ENTITY VIDIOC-ENUM-DV-PRESETS "<link linkend='vidioc-enum-dv-presets'><constant>VIDIOC_ENUM_DV_PRESETS</constant></link>">
-<!ENTITY VIDIOC-ENUM-FMT "<link linkend='vidioc-enum-fmt'><constant>VIDIOC_ENUM_FMT</constant></link>">
-<!ENTITY VIDIOC-ENUM-FRAMEINTERVALS "<link linkend='vidioc-enum-frameintervals'><constant>VIDIOC_ENUM_FRAMEINTERVALS</constant></link>">
-<!ENTITY VIDIOC-ENUM-FRAMESIZES "<link linkend='vidioc-enum-framesizes'><constant>VIDIOC_ENUM_FRAMESIZES</constant></link>">
-<!ENTITY VIDIOC-G-AUDIO "<link linkend='vidioc-g-audio'><constant>VIDIOC_G_AUDIO</constant></link>">
-<!ENTITY VIDIOC-G-AUDOUT "<link linkend='vidioc-g-audioout'><constant>VIDIOC_G_AUDOUT</constant></link>">
-<!ENTITY VIDIOC-G-CROP "<link linkend='vidioc-g-crop'><constant>VIDIOC_G_CROP</constant></link>">
-<!ENTITY VIDIOC-G-CTRL "<link linkend='vidioc-g-ctrl'><constant>VIDIOC_G_CTRL</constant></link>">
-<!ENTITY VIDIOC-G-DV-PRESET "<link linkend='vidioc-g-dv-preset'><constant>VIDIOC_G_DV_PRESET</constant></link>">
-<!ENTITY VIDIOC-G-DV-TIMINGS "<link linkend='vidioc-g-dv-timings'><constant>VIDIOC_G_DV_TIMINGS</constant></link>">
-<!ENTITY VIDIOC-G-ENC-INDEX "<link linkend='vidioc-g-enc-index'><constant>VIDIOC_G_ENC_INDEX</constant></link>">
-<!ENTITY VIDIOC-G-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_G_EXT_CTRLS</constant></link>">
-<!ENTITY VIDIOC-G-FBUF "<link linkend='vidioc-g-fbuf'><constant>VIDIOC_G_FBUF</constant></link>">
-<!ENTITY VIDIOC-G-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_G_FMT</constant></link>">
-<!ENTITY VIDIOC-G-FREQUENCY "<link linkend='vidioc-g-frequency'><constant>VIDIOC_G_FREQUENCY</constant></link>">
-<!ENTITY VIDIOC-G-INPUT "<link linkend='vidioc-g-input'><constant>VIDIOC_G_INPUT</constant></link>">
-<!ENTITY VIDIOC-G-JPEGCOMP "<link linkend='vidioc-g-jpegcomp'><constant>VIDIOC_G_JPEGCOMP</constant></link>">
-<!ENTITY VIDIOC-G-MPEGCOMP "<link linkend=''><constant>VIDIOC_G_MPEGCOMP</constant></link>">
-<!ENTITY VIDIOC-G-MODULATOR "<link linkend='vidioc-g-modulator'><constant>VIDIOC_G_MODULATOR</constant></link>">
-<!ENTITY VIDIOC-G-OUTPUT "<link linkend='vidioc-g-output'><constant>VIDIOC_G_OUTPUT</constant></link>">
-<!ENTITY VIDIOC-G-PARM "<link linkend='vidioc-g-parm'><constant>VIDIOC_G_PARM</constant></link>">
-<!ENTITY VIDIOC-G-PRIORITY "<link linkend='vidioc-g-priority'><constant>VIDIOC_G_PRIORITY</constant></link>">
-<!ENTITY VIDIOC-G-SLICED-VBI-CAP "<link linkend='vidioc-g-sliced-vbi-cap'><constant>VIDIOC_G_SLICED_VBI_CAP</constant></link>">
-<!ENTITY VIDIOC-G-STD "<link linkend='vidioc-g-std'><constant>VIDIOC_G_STD</constant></link>">
-<!ENTITY VIDIOC-G-TUNER "<link linkend='vidioc-g-tuner'><constant>VIDIOC_G_TUNER</constant></link>">
-<!ENTITY VIDIOC-LOG-STATUS "<link linkend='vidioc-log-status'><constant>VIDIOC_LOG_STATUS</constant></link>">
-<!ENTITY VIDIOC-OVERLAY "<link linkend='vidioc-overlay'><constant>VIDIOC_OVERLAY</constant></link>">
-<!ENTITY VIDIOC-QBUF "<link linkend='vidioc-qbuf'><constant>VIDIOC_QBUF</constant></link>">
-<!ENTITY VIDIOC-QUERYBUF "<link linkend='vidioc-querybuf'><constant>VIDIOC_QUERYBUF</constant></link>">
-<!ENTITY VIDIOC-QUERYCAP "<link linkend='vidioc-querycap'><constant>VIDIOC_QUERYCAP</constant></link>">
-<!ENTITY VIDIOC-QUERYCTRL "<link linkend='vidioc-queryctrl'><constant>VIDIOC_QUERYCTRL</constant></link>">
-<!ENTITY VIDIOC-QUERYMENU "<link linkend='vidioc-queryctrl'><constant>VIDIOC_QUERYMENU</constant></link>">
-<!ENTITY VIDIOC-QUERYSTD "<link linkend='vidioc-querystd'><constant>VIDIOC_QUERYSTD</constant></link>">
-<!ENTITY VIDIOC-QUERY-DV-PRESET "<link linkend='vidioc-query-dv-preset'><constant>VIDIOC_QUERY_DV_PRESET</constant></link>">
-<!ENTITY VIDIOC-REQBUFS "<link linkend='vidioc-reqbufs'><constant>VIDIOC_REQBUFS</constant></link>">
-<!ENTITY VIDIOC-STREAMOFF "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMOFF</constant></link>">
-<!ENTITY VIDIOC-STREAMON "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMON</constant></link>">
-<!ENTITY VIDIOC-SUBSCRIBE-EVENT "<link linkend='vidioc-subscribe-event'><constant>VIDIOC_SUBSCRIBE_EVENT</constant></link>">
-<!ENTITY VIDIOC-S-AUDIO "<link linkend='vidioc-g-audio'><constant>VIDIOC_S_AUDIO</constant></link>">
-<!ENTITY VIDIOC-S-AUDOUT "<link linkend='vidioc-g-audioout'><constant>VIDIOC_S_AUDOUT</constant></link>">
-<!ENTITY VIDIOC-S-CROP "<link linkend='vidioc-g-crop'><constant>VIDIOC_S_CROP</constant></link>">
-<!ENTITY VIDIOC-S-CTRL "<link linkend='vidioc-g-ctrl'><constant>VIDIOC_S_CTRL</constant></link>">
-<!ENTITY VIDIOC-S-DV-PRESET "<link linkend='vidioc-g-dv-preset'><constant>VIDIOC_S_DV_PRESET</constant></link>">
-<!ENTITY VIDIOC-S-DV-TIMINGS "<link linkend='vidioc-g-dv-timings'><constant>VIDIOC_S_DV_TIMINGS</constant></link>">
-<!ENTITY VIDIOC-S-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_S_EXT_CTRLS</constant></link>">
-<!ENTITY VIDIOC-S-FBUF "<link linkend='vidioc-g-fbuf'><constant>VIDIOC_S_FBUF</constant></link>">
-<!ENTITY VIDIOC-S-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_S_FMT</constant></link>">
-<!ENTITY VIDIOC-S-FREQUENCY "<link linkend='vidioc-g-frequency'><constant>VIDIOC_S_FREQUENCY</constant></link>">
-<!ENTITY VIDIOC-S-HW-FREQ-SEEK "<link linkend='vidioc-s-hw-freq-seek'><constant>VIDIOC_S_HW_FREQ_SEEK</constant></link>">
-<!ENTITY VIDIOC-S-INPUT "<link linkend='vidioc-g-input'><constant>VIDIOC_S_INPUT</constant></link>">
-<!ENTITY VIDIOC-S-JPEGCOMP "<link linkend='vidioc-g-jpegcomp'><constant>VIDIOC_S_JPEGCOMP</constant></link>">
-<!ENTITY VIDIOC-S-MPEGCOMP "<link linkend=''><constant>VIDIOC_S_MPEGCOMP</constant></link>">
-<!ENTITY VIDIOC-S-MODULATOR "<link linkend='vidioc-g-modulator'><constant>VIDIOC_S_MODULATOR</constant></link>">
-<!ENTITY VIDIOC-S-OUTPUT "<link linkend='vidioc-g-output'><constant>VIDIOC_S_OUTPUT</constant></link>">
-<!ENTITY VIDIOC-S-PARM "<link linkend='vidioc-g-parm'><constant>VIDIOC_S_PARM</constant></link>">
-<!ENTITY VIDIOC-S-PRIORITY "<link linkend='vidioc-g-priority'><constant>VIDIOC_S_PRIORITY</constant></link>">
-<!ENTITY VIDIOC-S-STD "<link linkend='vidioc-g-std'><constant>VIDIOC_S_STD</constant></link>">
-<!ENTITY VIDIOC-S-TUNER "<link linkend='vidioc-g-tuner'><constant>VIDIOC_S_TUNER</constant></link>">
-<!ENTITY VIDIOC-SUBDEV-ENUM-FRAME-SIZE "<link linkend='vidioc-subdev-enum-frame-size'><constant>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</constant></link>">
-<!ENTITY VIDIOC-SUBDEV-ENUM-MBUS-CODE "<link linkend='vidioc-subdev-enum-mbus-code'><constant>VIDIOC_SUBDEV_ENUM_MBUS_CODE</constant></link>">
-<!ENTITY VIDIOC-SUBDEV-G-CROP "<link linkend='vidioc-subdev-g-crop'><constant>VIDIOC_SUBDEV_G_CROP</constant></link>">
-<!ENTITY VIDIOC-SUBDEV-G-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_G_FMT</constant></link>">
-<!ENTITY VIDIOC-SUBDEV-G-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant></link>">
-<!ENTITY VIDIOC-SUBDEV-S-CROP "<link linkend='vidioc-subdev-g-crop'><constant>VIDIOC_SUBDEV_S_CROP</constant></link>">
-<!ENTITY VIDIOC-SUBDEV-S-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_S_FMT</constant></link>">
-<!ENTITY VIDIOC-SUBDEV-S-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant></link>">
-<!ENTITY VIDIOC-TRY-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_TRY_ENCODER_CMD</constant></link>">
-<!ENTITY VIDIOC-TRY-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_TRY_EXT_CTRLS</constant></link>">
-<!ENTITY VIDIOC-TRY-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_TRY_FMT</constant></link>">
-<!ENTITY VIDIOC-UNSUBSCRIBE-EVENT "<link linkend='vidioc-subscribe-event'><constant>VIDIOC_UNSUBSCRIBE_EVENT</constant></link>">
-
-<!ENTITY MEDIA-IOC-DEVICE-INFO "<link linkend='media-ioc-device-info'><constant>MEDIA_IOC_DEVICE_INFO</constant></link>">
-<!ENTITY MEDIA-IOC-ENUM-ENTITIES "<link linkend='media-ioc-enum-entities'><constant>MEDIA_IOC_ENUM_ENTITIES</constant></link>">
-<!ENTITY MEDIA-IOC-ENUM-LINKS "<link linkend='media-ioc-enum-links'><constant>MEDIA_IOC_ENUM_LINKS</constant></link>">
-<!ENTITY MEDIA-IOC-SETUP-LINK "<link linkend='media-ioc-setup-link'><constant>MEDIA_IOC_SETUP_LINK</constant></link>">
-
-<!-- Types -->
-<!ENTITY v4l2-std-id "<link linkend='v4l2-std-id'>v4l2_std_id</link>">
-
-<!-- Enums -->
-<!ENTITY v4l2-buf-type "enum&nbsp;<link linkend='v4l2-buf-type'>v4l2_buf_type</link>">
-<!ENTITY v4l2-colorspace "enum&nbsp;<link linkend='v4l2-colorspace'>v4l2_colorspace</link>">
-<!ENTITY v4l2-ctrl-type "enum&nbsp;<link linkend='v4l2-ctrl-type'>v4l2_ctrl_type</link>">
-<!ENTITY v4l2-exposure-auto-type "enum&nbsp;<link linkend='v4l2-exposure-auto-type'>v4l2_exposure_auto_type</link>">
-<!ENTITY v4l2-field "enum&nbsp;<link linkend='v4l2-field'>v4l2_field</link>">
-<!ENTITY v4l2-frmivaltypes "enum&nbsp;<link linkend='v4l2-frmivaltypes'>v4l2_frmivaltypes</link>">
-<!ENTITY v4l2-frmsizetypes "enum&nbsp;<link linkend='v4l2-frmsizetypes'>v4l2_frmsizetypes</link>">
-<!ENTITY v4l2-mbus-pixelcode "enum&nbsp;<link linkend='v4l2-mbus-pixelcode'>v4l2_mbus_pixelcode</link>">
-<!ENTITY v4l2-memory "enum&nbsp;<link linkend='v4l2-memory'>v4l2_memory</link>">
-<!ENTITY v4l2-mpeg-audio-ac3-bitrate "enum&nbsp;<link linkend='v4l2-mpeg-audio-ac3-bitrate'>v4l2_mpeg_audio_ac3_bitrate</link>">
-<!ENTITY v4l2-mpeg-audio-crc "enum&nbsp;<link linkend='v4l2-mpeg-audio-crc'>v4l2_mpeg_audio_crc</link>">
-<!ENTITY v4l2-mpeg-audio-emphasis "enum&nbsp;<link linkend='v4l2-mpeg-audio-emphasis'>v4l2_mpeg_audio_emphasis</link>">
-<!ENTITY v4l2-mpeg-audio-encoding "enum&nbsp;<link linkend='v4l2-mpeg-audio-encoding'>v4l2_mpeg_audio_encoding</link>">
-<!ENTITY v4l2-mpeg-audio-l1-bitrate "enum&nbsp;<link linkend='v4l2-mpeg-audio-l1-bitrate'>v4l2_mpeg_audio_l1_bitrate</link>">
-<!ENTITY v4l2-mpeg-audio-l2-bitrate "enum&nbsp;<link linkend='v4l2-mpeg-audio-l2-bitrate'>v4l2_mpeg_audio_l2_bitrate</link>">
-<!ENTITY v4l2-mpeg-audio-l3-bitrate "enum&nbsp;<link linkend='v4l2-mpeg-audio-l3-bitrate'>v4l2_mpeg_audio_l3_bitrate</link>">
-<!ENTITY v4l2-mpeg-audio-mode "enum&nbsp;<link linkend='v4l2-mpeg-audio-mode'>v4l2_mpeg_audio_mode</link>">
-<!ENTITY v4l2-mpeg-audio-mode-extension "enum&nbsp;<link linkend='v4l2-mpeg-audio-mode-extension'>v4l2_mpeg_audio_mode_extension</link>">
-<!ENTITY v4l2-mpeg-audio-sampling-freq "enum&nbsp;<link linkend='v4l2-mpeg-audio-sampling-freq'>v4l2_mpeg_audio_sampling_freq</link>">
-<!ENTITY chroma-spatial-filter-type "enum&nbsp;<link linkend='chroma-spatial-filter-type'>v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type</link>">
-<!ENTITY luma-spatial-filter-type "enum&nbsp;<link linkend='luma-spatial-filter-type'>v4l2_mpeg_cx2341x_video_luma_spatial_filter_type</link>">
-<!ENTITY v4l2-mpeg-cx2341x-video-median-filter-type "enum&nbsp;<link linkend='v4l2-mpeg-cx2341x-video-median-filter-type'>v4l2_mpeg_cx2341x_video_median_filter_type</link>">
-<!ENTITY v4l2-mpeg-cx2341x-video-spatial-filter-mode "enum&nbsp;<link linkend='v4l2-mpeg-cx2341x-video-spatial-filter-mode'>v4l2_mpeg_cx2341x_video_spatial_filter_mode</link>">
-<!ENTITY v4l2-mpeg-cx2341x-video-temporal-filter-mode "enum&nbsp;<link linkend='v4l2-mpeg-cx2341x-video-temporal-filter-mode'>v4l2_mpeg_cx2341x_video_temporal_filter_mode</link>">
-<!ENTITY v4l2-mpeg-stream-type "enum&nbsp;<link linkend='v4l2-mpeg-stream-type'>v4l2_mpeg_stream_type</link>">
-<!ENTITY v4l2-mpeg-stream-vbi-fmt "enum&nbsp;<link linkend='v4l2-mpeg-stream-vbi-fmt'>v4l2_mpeg_stream_vbi_fmt</link>">
-<!ENTITY v4l2-mpeg-video-aspect "enum&nbsp;<link linkend='v4l2-mpeg-video-aspect'>v4l2_mpeg_video_aspect</link>">
-<!ENTITY v4l2-mpeg-video-bitrate-mode "enum&nbsp;<link linkend='v4l2-mpeg-video-bitrate-mode'>v4l2_mpeg_video_bitrate_mode</link>">
-<!ENTITY v4l2-mpeg-video-encoding "enum&nbsp;<link linkend='v4l2-mpeg-video-encoding'>v4l2_mpeg_video_encoding</link>">
-<!ENTITY v4l2-power-line-frequency "enum&nbsp;<link linkend='v4l2-power-line-frequency'>v4l2_power_line_frequency</link>">
-<!ENTITY v4l2-priority "enum&nbsp;<link linkend='v4l2-priority'>v4l2_priority</link>">
-<!ENTITY v4l2-subdev-format-whence "enum&nbsp;<link linkend='v4l2-subdev-format-whence'>v4l2_subdev_format_whence</link>">
-<!ENTITY v4l2-tuner-type "enum&nbsp;<link linkend='v4l2-tuner-type'>v4l2_tuner_type</link>">
-<!ENTITY v4l2-preemphasis "enum&nbsp;<link linkend='v4l2-preemphasis'>v4l2_preemphasis</link>">
-
-<!-- Structures -->
-<!ENTITY v4l2-audio "struct&nbsp;<link linkend='v4l2-audio'>v4l2_audio</link>">
-<!ENTITY v4l2-audioout "struct&nbsp;<link linkend='v4l2-audioout'>v4l2_audioout</link>">
-<!ENTITY v4l2-bt-timings "struct&nbsp;<link linkend='v4l2-bt-timings'>v4l2_bt_timings</link>">
-<!ENTITY v4l2-buffer "struct&nbsp;<link linkend='v4l2-buffer'>v4l2_buffer</link>">
-<!ENTITY v4l2-plane "struct&nbsp;<link linkend='v4l2-plane'>v4l2_plane</link>">
-<!ENTITY v4l2-capability "struct&nbsp;<link linkend='v4l2-capability'>v4l2_capability</link>">
-<!ENTITY v4l2-captureparm "struct&nbsp;<link linkend='v4l2-captureparm'>v4l2_captureparm</link>">
-<!ENTITY v4l2-clip "struct&nbsp;<link linkend='v4l2-clip'>v4l2_clip</link>">
-<!ENTITY v4l2-control "struct&nbsp;<link linkend='v4l2-control'>v4l2_control</link>">
-<!ENTITY v4l2-crop "struct&nbsp;<link linkend='v4l2-crop'>v4l2_crop</link>">
-<!ENTITY v4l2-cropcap "struct&nbsp;<link linkend='v4l2-cropcap'>v4l2_cropcap</link>">
-<!ENTITY v4l2-dbg-chip-ident "struct&nbsp;<link linkend='v4l2-dbg-chip-ident'>v4l2_dbg_chip_ident</link>">
-<!ENTITY v4l2-dbg-match "struct&nbsp;<link linkend='v4l2-dbg-match'>v4l2_dbg_match</link>">
-<!ENTITY v4l2-dbg-register "struct&nbsp;<link linkend='v4l2-dbg-register'>v4l2_dbg_register</link>">
-<!ENTITY v4l2-dv-enum-preset "struct&nbsp;<link linkend='v4l2-dv-enum-preset'>v4l2_dv_enum_preset</link>">
-<!ENTITY v4l2-dv-preset "struct&nbsp;<link linkend='v4l2-dv-preset'>v4l2_dv_preset</link>">
-<!ENTITY v4l2-dv-timings "struct&nbsp;<link linkend='v4l2-dv-timings'>v4l2_dv_timings</link>">
-<!ENTITY v4l2-enc-idx "struct&nbsp;<link linkend='v4l2-enc-idx'>v4l2_enc_idx</link>">
-<!ENTITY v4l2-enc-idx-entry "struct&nbsp;<link linkend='v4l2-enc-idx-entry'>v4l2_enc_idx_entry</link>">
-<!ENTITY v4l2-encoder-cmd "struct&nbsp;<link linkend='v4l2-encoder-cmd'>v4l2_encoder_cmd</link>">
-<!ENTITY v4l2-event "struct&nbsp;<link linkend='v4l2-event'>v4l2_event</link>">
-<!ENTITY v4l2-event-subscription "struct&nbsp;<link linkend='v4l2-event-subscription'>v4l2_event_subscription</link>">
-<!ENTITY v4l2-event-vsync "struct&nbsp;<link linkend='v4l2-event-vsync'>v4l2_event_vsync</link>">
-<!ENTITY v4l2-ext-control "struct&nbsp;<link linkend='v4l2-ext-control'>v4l2_ext_control</link>">
-<!ENTITY v4l2-ext-controls "struct&nbsp;<link linkend='v4l2-ext-controls'>v4l2_ext_controls</link>">
-<!ENTITY v4l2-fmtdesc "struct&nbsp;<link linkend='v4l2-fmtdesc'>v4l2_fmtdesc</link>">
-<!ENTITY v4l2-format "struct&nbsp;<link linkend='v4l2-format'>v4l2_format</link>">
-<!ENTITY v4l2-fract "struct&nbsp;<link linkend='v4l2-fract'>v4l2_fract</link>">
-<!ENTITY v4l2-framebuffer "struct&nbsp;<link linkend='v4l2-framebuffer'>v4l2_framebuffer</link>">
-<!ENTITY v4l2-frequency "struct&nbsp;<link linkend='v4l2-frequency'>v4l2_frequency</link>">
-<!ENTITY v4l2-frmival-stepwise "struct&nbsp;<link linkend='v4l2-frmival-stepwise'>v4l2_frmival_stepwise</link>">
-<!ENTITY v4l2-frmivalenum "struct&nbsp;<link linkend='v4l2-frmivalenum'>v4l2_frmivalenum</link>">
-<!ENTITY v4l2-frmsize-discrete "struct&nbsp;<link linkend='v4l2-frmsize-discrete'>v4l2_frmsize_discrete</link>">
-<!ENTITY v4l2-frmsize-stepwise "struct&nbsp;<link linkend='v4l2-frmsize-stepwise'>v4l2_frmsize_stepwise</link>">
-<!ENTITY v4l2-frmsizeenum "struct&nbsp;<link linkend='v4l2-frmsizeenum'>v4l2_frmsizeenum</link>">
-<!ENTITY v4l2-hw-freq-seek "struct&nbsp;<link linkend='v4l2-hw-freq-seek'>v4l2_hw_freq_seek</link>">
-<!ENTITY v4l2-input "struct&nbsp;<link linkend='v4l2-input'>v4l2_input</link>">
-<!ENTITY v4l2-jpegcompression "struct&nbsp;<link linkend='v4l2-jpegcompression'>v4l2_jpegcompression</link>">
-<!ENTITY v4l2-mbus-framefmt "struct&nbsp;<link linkend='v4l2-mbus-framefmt'>v4l2_mbus_framefmt</link>">
-<!ENTITY v4l2-modulator "struct&nbsp;<link linkend='v4l2-modulator'>v4l2_modulator</link>">
-<!ENTITY v4l2-mpeg-vbi-fmt-ivtv "struct&nbsp;<link linkend='v4l2-mpeg-vbi-fmt-ivtv'>v4l2_mpeg_vbi_fmt_ivtv</link>">
-<!ENTITY v4l2-output "struct&nbsp;<link linkend='v4l2-output'>v4l2_output</link>">
-<!ENTITY v4l2-outputparm "struct&nbsp;<link linkend='v4l2-outputparm'>v4l2_outputparm</link>">
-<!ENTITY v4l2-pix-format "struct&nbsp;<link linkend='v4l2-pix-format'>v4l2_pix_format</link>">
-<!ENTITY v4l2-pix-format-mplane "struct&nbsp;<link linkend='v4l2-pix-format-mplane'>v4l2_pix_format_mplane</link>">
-<!ENTITY v4l2-plane-pix-format "struct&nbsp;<link linkend='v4l2-plane-pix-format'>v4l2_plane_pix_format</link>">
-<!ENTITY v4l2-queryctrl "struct&nbsp;<link linkend='v4l2-queryctrl'>v4l2_queryctrl</link>">
-<!ENTITY v4l2-querymenu "struct&nbsp;<link linkend='v4l2-querymenu'>v4l2_querymenu</link>">
-<!ENTITY v4l2-rect "struct&nbsp;<link linkend='v4l2-rect'>v4l2_rect</link>">
-<!ENTITY v4l2-requestbuffers "struct&nbsp;<link linkend='v4l2-requestbuffers'>v4l2_requestbuffers</link>">
-<!ENTITY v4l2-sliced-vbi-cap "struct&nbsp;<link linkend='v4l2-sliced-vbi-cap'>v4l2_sliced_vbi_cap</link>">
-<!ENTITY v4l2-sliced-vbi-data "struct&nbsp;<link linkend='v4l2-sliced-vbi-data'>v4l2_sliced_vbi_data</link>">
-<!ENTITY v4l2-sliced-vbi-format "struct&nbsp;<link linkend='v4l2-sliced-vbi-format'>v4l2_sliced_vbi_format</link>">
-<!ENTITY v4l2-subdev-frame-interval "struct&nbsp;<link linkend='v4l2-subdev-frame-interval'>v4l2_subdev_frame_interval</link>">
-<!ENTITY v4l2-subdev-frame-interval-enum "struct&nbsp;<link linkend='v4l2-subdev-frame-interval-enum'>v4l2_subdev_frame_interval_enum</link>">
-<!ENTITY v4l2-subdev-frame-size-enum "struct&nbsp;<link linkend='v4l2-subdev-frame-size-enum'>v4l2_subdev_frame_size_enum</link>">
-<!ENTITY v4l2-subdev-crop "struct&nbsp;<link linkend='v4l2-subdev-crop'>v4l2_subdev_crop</link>">
-<!ENTITY v4l2-subdev-format "struct&nbsp;<link linkend='v4l2-subdev-format'>v4l2_subdev_format</link>">
-<!ENTITY v4l2-subdev-mbus-code-enum "struct&nbsp;<link linkend='v4l2-subdev-mbus-code-enum'>v4l2_subdev_mbus_code_enum</link>">
-<!ENTITY v4l2-standard "struct&nbsp;<link linkend='v4l2-standard'>v4l2_standard</link>">
-<!ENTITY v4l2-streamparm "struct&nbsp;<link linkend='v4l2-streamparm'>v4l2_streamparm</link>">
-<!ENTITY v4l2-timecode "struct&nbsp;<link linkend='v4l2-timecode'>v4l2_timecode</link>">
-<!ENTITY v4l2-tuner "struct&nbsp;<link linkend='v4l2-tuner'>v4l2_tuner</link>">
-<!ENTITY v4l2-vbi-format "struct&nbsp;<link linkend='v4l2-vbi-format'>v4l2_vbi_format</link>">
-<!ENTITY v4l2-window "struct&nbsp;<link linkend='v4l2-window'>v4l2_window</link>">
-
-<!ENTITY media-device-info "struct&nbsp;<link linkend='media-device-info'>media_device_info</link>">
-<!ENTITY media-entity-desc "struct&nbsp;<link linkend='media-entity-desc'>media_entity_desc</link>">
-<!ENTITY media-links-enum "struct&nbsp;<link linkend='media-links-enum'>media_links_enum</link>">
-<!ENTITY media-pad-desc "struct&nbsp;<link linkend='media-pad-desc'>media_pad_desc</link>">
-<!ENTITY media-link-desc "struct&nbsp;<link linkend='media-link-desc'>media_link_desc</link>">
-
-<!-- Error Codes -->
-<!ENTITY EACCES "<errorcode>EACCES</errorcode> error code">
-<!ENTITY EAGAIN "<errorcode>EAGAIN</errorcode> error code">
-<!ENTITY EBADF "<errorcode>EBADF</errorcode> error code">
-<!ENTITY EBUSY "<errorcode>EBUSY</errorcode> error code">
-<!ENTITY EFAULT "<errorcode>EFAULT</errorcode> error code">
-<!ENTITY EIO "<errorcode>EIO</errorcode> error code">
-<!ENTITY EINTR "<errorcode>EINTR</errorcode> error code">
-<!ENTITY EINVAL "<errorcode>EINVAL</errorcode> error code">
-<!ENTITY ENFILE "<errorcode>ENFILE</errorcode> error code">
-<!ENTITY ENOMEM "<errorcode>ENOMEM</errorcode> error code">
-<!ENTITY ENOSPC "<errorcode>ENOSPC</errorcode> error code">
-<!ENTITY ENOTTY "<errorcode>ENOTTY</errorcode> error code">
-<!ENTITY ENXIO "<errorcode>ENXIO</errorcode> error code">
-<!ENTITY EMFILE "<errorcode>EMFILE</errorcode> error code">
-<!ENTITY EPERM "<errorcode>EPERM</errorcode> error code">
-<!ENTITY EPIPE "<errorcode>EPIPE</errorcode> error code">
-<!ENTITY ERANGE "<errorcode>ERANGE</errorcode> error code">
-
-<!-- Subsections -->
-<!ENTITY sub-biblio SYSTEM "v4l/biblio.xml">
-<!ENTITY sub-common SYSTEM "v4l/common.xml">
-<!ENTITY sub-planar-apis SYSTEM "v4l/planar-apis.xml">
-<!ENTITY sub-compat SYSTEM "v4l/compat.xml">
-<!ENTITY sub-controls SYSTEM "v4l/controls.xml">
-<!ENTITY sub-dev-capture SYSTEM "v4l/dev-capture.xml">
-<!ENTITY sub-dev-codec SYSTEM "v4l/dev-codec.xml">
-<!ENTITY sub-dev-event SYSTEM "v4l/dev-event.xml">
-<!ENTITY sub-dev-effect SYSTEM "v4l/dev-effect.xml">
-<!ENTITY sub-dev-osd SYSTEM "v4l/dev-osd.xml">
-<!ENTITY sub-dev-output SYSTEM "v4l/dev-output.xml">
-<!ENTITY sub-dev-overlay SYSTEM "v4l/dev-overlay.xml">
-<!ENTITY sub-dev-radio SYSTEM "v4l/dev-radio.xml">
-<!ENTITY sub-dev-raw-vbi SYSTEM "v4l/dev-raw-vbi.xml">
-<!ENTITY sub-dev-rds SYSTEM "v4l/dev-rds.xml">
-<!ENTITY sub-dev-sliced-vbi SYSTEM "v4l/dev-sliced-vbi.xml">
-<!ENTITY sub-dev-subdev SYSTEM "v4l/dev-subdev.xml">
-<!ENTITY sub-dev-teletext SYSTEM "v4l/dev-teletext.xml">
-<!ENTITY sub-driver SYSTEM "v4l/driver.xml">
-<!ENTITY sub-libv4l SYSTEM "v4l/libv4l.xml">
-<!ENTITY sub-lirc_device_interface SYSTEM "v4l/lirc_device_interface.xml">
-<!ENTITY sub-remote_controllers SYSTEM "v4l/remote_controllers.xml">
-<!ENTITY sub-fdl-appendix SYSTEM "v4l/fdl-appendix.xml">
-<!ENTITY sub-close SYSTEM "v4l/func-close.xml">
-<!ENTITY sub-ioctl SYSTEM "v4l/func-ioctl.xml">
-<!ENTITY sub-mmap SYSTEM "v4l/func-mmap.xml">
-<!ENTITY sub-munmap SYSTEM "v4l/func-munmap.xml">
-<!ENTITY sub-open SYSTEM "v4l/func-open.xml">
-<!ENTITY sub-poll SYSTEM "v4l/func-poll.xml">
-<!ENTITY sub-read SYSTEM "v4l/func-read.xml">
-<!ENTITY sub-select SYSTEM "v4l/func-select.xml">
-<!ENTITY sub-write SYSTEM "v4l/func-write.xml">
-<!ENTITY sub-io SYSTEM "v4l/io.xml">
-<!ENTITY sub-grey SYSTEM "v4l/pixfmt-grey.xml">
-<!ENTITY sub-m420 SYSTEM "v4l/pixfmt-m420.xml">
-<!ENTITY sub-nv12 SYSTEM "v4l/pixfmt-nv12.xml">
-<!ENTITY sub-nv12m SYSTEM "v4l/pixfmt-nv12m.xml">
-<!ENTITY sub-nv12mt SYSTEM "v4l/pixfmt-nv12mt.xml">
-<!ENTITY sub-nv16 SYSTEM "v4l/pixfmt-nv16.xml">
-<!ENTITY sub-packed-rgb SYSTEM "v4l/pixfmt-packed-rgb.xml">
-<!ENTITY sub-packed-yuv SYSTEM "v4l/pixfmt-packed-yuv.xml">
-<!ENTITY sub-sbggr16 SYSTEM "v4l/pixfmt-sbggr16.xml">
-<!ENTITY sub-sbggr8 SYSTEM "v4l/pixfmt-sbggr8.xml">
-<!ENTITY sub-sgbrg8 SYSTEM "v4l/pixfmt-sgbrg8.xml">
-<!ENTITY sub-sgrbg8 SYSTEM "v4l/pixfmt-sgrbg8.xml">
-<!ENTITY sub-uyvy SYSTEM "v4l/pixfmt-uyvy.xml">
-<!ENTITY sub-vyuy SYSTEM "v4l/pixfmt-vyuy.xml">
-<!ENTITY sub-y16 SYSTEM "v4l/pixfmt-y16.xml">
-<!ENTITY sub-y41p SYSTEM "v4l/pixfmt-y41p.xml">
-<!ENTITY sub-yuv410 SYSTEM "v4l/pixfmt-yuv410.xml">
-<!ENTITY sub-yuv411p SYSTEM "v4l/pixfmt-yuv411p.xml">
-<!ENTITY sub-yuv420 SYSTEM "v4l/pixfmt-yuv420.xml">
-<!ENTITY sub-yuv420m SYSTEM "v4l/pixfmt-yuv420m.xml">
-<!ENTITY sub-yuv422p SYSTEM "v4l/pixfmt-yuv422p.xml">
-<!ENTITY sub-yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
-<!ENTITY sub-yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
-<!ENTITY sub-srggb10 SYSTEM "v4l/pixfmt-srggb10.xml">
-<!ENTITY sub-srggb12 SYSTEM "v4l/pixfmt-srggb12.xml">
-<!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
-<!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml">
-<!ENTITY sub-y12 SYSTEM "v4l/pixfmt-y12.xml">
-<!ENTITY sub-y10b SYSTEM "v4l/pixfmt-y10b.xml">
-<!ENTITY sub-pixfmt SYSTEM "v4l/pixfmt.xml">
-<!ENTITY sub-cropcap SYSTEM "v4l/vidioc-cropcap.xml">
-<!ENTITY sub-dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
-<!ENTITY sub-encoder-cmd SYSTEM "v4l/vidioc-encoder-cmd.xml">
-<!ENTITY sub-enum-fmt SYSTEM "v4l/vidioc-enum-fmt.xml">
-<!ENTITY sub-enum-frameintervals SYSTEM "v4l/vidioc-enum-frameintervals.xml">
-<!ENTITY sub-enum-framesizes SYSTEM "v4l/vidioc-enum-framesizes.xml">
-<!ENTITY sub-enumaudio SYSTEM "v4l/vidioc-enumaudio.xml">
-<!ENTITY sub-enumaudioout SYSTEM "v4l/vidioc-enumaudioout.xml">
-<!ENTITY sub-enuminput SYSTEM "v4l/vidioc-enuminput.xml">
-<!ENTITY sub-enumoutput SYSTEM "v4l/vidioc-enumoutput.xml">
-<!ENTITY sub-enum-dv-presets SYSTEM "v4l/vidioc-enum-dv-presets.xml">
-<!ENTITY sub-g-dv-preset SYSTEM "v4l/vidioc-g-dv-preset.xml">
-<!ENTITY sub-query-dv-preset SYSTEM "v4l/vidioc-query-dv-preset.xml">
-<!ENTITY sub-g-dv-timings SYSTEM "v4l/vidioc-g-dv-timings.xml">
-<!ENTITY sub-enumstd SYSTEM "v4l/vidioc-enumstd.xml">
-<!ENTITY sub-g-audio SYSTEM "v4l/vidioc-g-audio.xml">
-<!ENTITY sub-g-audioout SYSTEM "v4l/vidioc-g-audioout.xml">
-<!ENTITY sub-dbg-g-chip-ident SYSTEM "v4l/vidioc-dbg-g-chip-ident.xml">
-<!ENTITY sub-g-crop SYSTEM "v4l/vidioc-g-crop.xml">
-<!ENTITY sub-g-ctrl SYSTEM "v4l/vidioc-g-ctrl.xml">
-<!ENTITY sub-g-enc-index SYSTEM "v4l/vidioc-g-enc-index.xml">
-<!ENTITY sub-g-ext-ctrls SYSTEM "v4l/vidioc-g-ext-ctrls.xml">
-<!ENTITY sub-g-fbuf SYSTEM "v4l/vidioc-g-fbuf.xml">
-<!ENTITY sub-g-fmt SYSTEM "v4l/vidioc-g-fmt.xml">
-<!ENTITY sub-g-frequency SYSTEM "v4l/vidioc-g-frequency.xml">
-<!ENTITY sub-g-input SYSTEM "v4l/vidioc-g-input.xml">
-<!ENTITY sub-g-jpegcomp SYSTEM "v4l/vidioc-g-jpegcomp.xml">
-<!ENTITY sub-g-modulator SYSTEM "v4l/vidioc-g-modulator.xml">
-<!ENTITY sub-g-output SYSTEM "v4l/vidioc-g-output.xml">
-<!ENTITY sub-g-parm SYSTEM "v4l/vidioc-g-parm.xml">
-<!ENTITY sub-g-priority SYSTEM "v4l/vidioc-g-priority.xml">
-<!ENTITY sub-g-sliced-vbi-cap SYSTEM "v4l/vidioc-g-sliced-vbi-cap.xml">
-<!ENTITY sub-g-std SYSTEM "v4l/vidioc-g-std.xml">
-<!ENTITY sub-g-tuner SYSTEM "v4l/vidioc-g-tuner.xml">
-<!ENTITY sub-log-status SYSTEM "v4l/vidioc-log-status.xml">
-<!ENTITY sub-overlay SYSTEM "v4l/vidioc-overlay.xml">
-<!ENTITY sub-qbuf SYSTEM "v4l/vidioc-qbuf.xml">
-<!ENTITY sub-querybuf SYSTEM "v4l/vidioc-querybuf.xml">
-<!ENTITY sub-querycap SYSTEM "v4l/vidioc-querycap.xml">
-<!ENTITY sub-queryctrl SYSTEM "v4l/vidioc-queryctrl.xml">
-<!ENTITY sub-querystd SYSTEM "v4l/vidioc-querystd.xml">
-<!ENTITY sub-reqbufs SYSTEM "v4l/vidioc-reqbufs.xml">
-<!ENTITY sub-s-hw-freq-seek SYSTEM "v4l/vidioc-s-hw-freq-seek.xml">
-<!ENTITY sub-streamon SYSTEM "v4l/vidioc-streamon.xml">
-<!ENTITY sub-subdev-enum-frame-interval SYSTEM "v4l/vidioc-subdev-enum-frame-interval.xml">
-<!ENTITY sub-subdev-enum-frame-size SYSTEM "v4l/vidioc-subdev-enum-frame-size.xml">
-<!ENTITY sub-subdev-enum-mbus-code SYSTEM "v4l/vidioc-subdev-enum-mbus-code.xml">
-<!ENTITY sub-subdev-formats SYSTEM "v4l/subdev-formats.xml">
-<!ENTITY sub-subdev-g-crop SYSTEM "v4l/vidioc-subdev-g-crop.xml">
-<!ENTITY sub-subdev-g-fmt SYSTEM "v4l/vidioc-subdev-g-fmt.xml">
-<!ENTITY sub-subdev-g-frame-interval SYSTEM "v4l/vidioc-subdev-g-frame-interval.xml">
-<!ENTITY sub-capture-c SYSTEM "v4l/capture.c.xml">
-<!ENTITY sub-keytable-c SYSTEM "v4l/keytable.c.xml">
-<!ENTITY sub-v4l2grab-c SYSTEM "v4l/v4l2grab.c.xml">
-<!ENTITY sub-videodev2-h SYSTEM "v4l/videodev2.h.xml">
-<!ENTITY sub-v4l2 SYSTEM "v4l/v4l2.xml">
-<!ENTITY sub-dqevent SYSTEM "v4l/vidioc-dqevent.xml">
-<!ENTITY sub-subscribe-event SYSTEM "v4l/vidioc-subscribe-event.xml">
-<!ENTITY sub-intro SYSTEM "dvb/intro.xml">
-<!ENTITY sub-frontend SYSTEM "dvb/frontend.xml">
-<!ENTITY sub-dvbproperty SYSTEM "dvb/dvbproperty.xml">
-<!ENTITY sub-demux SYSTEM "dvb/demux.xml">
-<!ENTITY sub-video SYSTEM "dvb/video.xml">
-<!ENTITY sub-audio SYSTEM "dvb/audio.xml">
-<!ENTITY sub-ca SYSTEM "dvb/ca.xml">
-<!ENTITY sub-net SYSTEM "dvb/net.xml">
-<!ENTITY sub-kdapi SYSTEM "dvb/kdapi.xml">
-<!ENTITY sub-examples SYSTEM "dvb/examples.xml">
-<!ENTITY sub-frontend-h SYSTEM "dvb/frontend.h.xml">
-<!ENTITY sub-dvbapi SYSTEM "dvb/dvbapi.xml">
-<!ENTITY sub-media SYSTEM "media.xml">
-<!ENTITY sub-media-entities SYSTEM "media-entities.tmpl">
-<!ENTITY sub-media-indices SYSTEM "media-indices.tmpl">
-
-<!ENTITY sub-media-controller SYSTEM "v4l/media-controller.xml">
-<!ENTITY sub-media-func-open SYSTEM "v4l/media-func-open.xml">
-<!ENTITY sub-media-func-close SYSTEM "v4l/media-func-close.xml">
-<!ENTITY sub-media-func-ioctl SYSTEM "v4l/media-func-ioctl.xml">
-<!ENTITY sub-media-ioc-device-info SYSTEM "v4l/media-ioc-device-info.xml">
-<!ENTITY sub-media-ioc-enum-entities SYSTEM "v4l/media-ioc-enum-entities.xml">
-<!ENTITY sub-media-ioc-enum-links SYSTEM "v4l/media-ioc-enum-links.xml">
-<!ENTITY sub-media-ioc-setup-link SYSTEM "v4l/media-ioc-setup-link.xml">
-
-<!-- Function Reference -->
-<!ENTITY close SYSTEM "v4l/func-close.xml">
-<!ENTITY ioctl SYSTEM "v4l/func-ioctl.xml">
-<!ENTITY mmap SYSTEM "v4l/func-mmap.xml">
-<!ENTITY munmap SYSTEM "v4l/func-munmap.xml">
-<!ENTITY open SYSTEM "v4l/func-open.xml">
-<!ENTITY poll SYSTEM "v4l/func-poll.xml">
-<!ENTITY read SYSTEM "v4l/func-read.xml">
-<!ENTITY select SYSTEM "v4l/func-select.xml">
-<!ENTITY write SYSTEM "v4l/func-write.xml">
-<!ENTITY grey SYSTEM "v4l/pixfmt-grey.xml">
-<!ENTITY nv12 SYSTEM "v4l/pixfmt-nv12.xml">
-<!ENTITY nv12m SYSTEM "v4l/pixfmt-nv12m.xml">
-<!ENTITY nv16 SYSTEM "v4l/pixfmt-nv16.xml">
-<!ENTITY packed-rgb SYSTEM "v4l/pixfmt-packed-rgb.xml">
-<!ENTITY packed-yuv SYSTEM "v4l/pixfmt-packed-yuv.xml">
-<!ENTITY sbggr16 SYSTEM "v4l/pixfmt-sbggr16.xml">
-<!ENTITY sbggr8 SYSTEM "v4l/pixfmt-sbggr8.xml">
-<!ENTITY sgbrg8 SYSTEM "v4l/pixfmt-sgbrg8.xml">
-<!ENTITY sgrbg8 SYSTEM "v4l/pixfmt-sgrbg8.xml">
-<!ENTITY uyvy SYSTEM "v4l/pixfmt-uyvy.xml">
-<!ENTITY vyuy SYSTEM "v4l/pixfmt-vyuy.xml">
-<!ENTITY y16 SYSTEM "v4l/pixfmt-y16.xml">
-<!ENTITY y41p SYSTEM "v4l/pixfmt-y41p.xml">
-<!ENTITY yuv410 SYSTEM "v4l/pixfmt-yuv410.xml">
-<!ENTITY yuv411p SYSTEM "v4l/pixfmt-yuv411p.xml">
-<!ENTITY yuv420 SYSTEM "v4l/pixfmt-yuv420.xml">
-<!ENTITY yuv420m SYSTEM "v4l/pixfmt-yuv420m.xml">
-<!ENTITY yuv422p SYSTEM "v4l/pixfmt-yuv422p.xml">
-<!ENTITY yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
-<!ENTITY yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
-<!ENTITY srggb10 SYSTEM "v4l/pixfmt-srggb10.xml">
-<!ENTITY srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
-<!ENTITY y10 SYSTEM "v4l/pixfmt-y10.xml">
-<!ENTITY cropcap SYSTEM "v4l/vidioc-cropcap.xml">
-<!ENTITY dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
-<!ENTITY encoder-cmd SYSTEM "v4l/vidioc-encoder-cmd.xml">
-<!ENTITY enum-fmt SYSTEM "v4l/vidioc-enum-fmt.xml">
-<!ENTITY enum-frameintervals SYSTEM "v4l/vidioc-enum-frameintervals.xml">
-<!ENTITY enum-framesizes SYSTEM "v4l/vidioc-enum-framesizes.xml">
-<!ENTITY enumaudio SYSTEM "v4l/vidioc-enumaudio.xml">
-<!ENTITY enumaudioout SYSTEM "v4l/vidioc-enumaudioout.xml">
-<!ENTITY enuminput SYSTEM "v4l/vidioc-enuminput.xml">
-<!ENTITY enumoutput SYSTEM "v4l/vidioc-enumoutput.xml">
-<!ENTITY enum-dv-presets SYSTEM "v4l/vidioc-enum-dv-presets.xml">
-<!ENTITY g-dv-preset SYSTEM "v4l/vidioc-g-dv-preset.xml">
-<!ENTITY query-dv-preset SYSTEM "v4l/vidioc-query-dv-preset.xml">
-<!ENTITY g-dv-timings SYSTEM "v4l/vidioc-g-dv-timings.xml">
-<!ENTITY enumstd SYSTEM "v4l/vidioc-enumstd.xml">
-<!ENTITY g-audio SYSTEM "v4l/vidioc-g-audio.xml">
-<!ENTITY g-audioout SYSTEM "v4l/vidioc-g-audioout.xml">
-<!ENTITY dbg-g-chip-ident SYSTEM "v4l/vidioc-dbg-g-chip-ident.xml">
-<!ENTITY g-crop SYSTEM "v4l/vidioc-g-crop.xml">
-<!ENTITY g-ctrl SYSTEM "v4l/vidioc-g-ctrl.xml">
-<!ENTITY g-enc-index SYSTEM "v4l/vidioc-g-enc-index.xml">
-<!ENTITY g-ext-ctrls SYSTEM "v4l/vidioc-g-ext-ctrls.xml">
-<!ENTITY g-fbuf SYSTEM "v4l/vidioc-g-fbuf.xml">
-<!ENTITY g-fmt SYSTEM "v4l/vidioc-g-fmt.xml">
-<!ENTITY g-frequency SYSTEM "v4l/vidioc-g-frequency.xml">
-<!ENTITY g-input SYSTEM "v4l/vidioc-g-input.xml">
-<!ENTITY g-jpegcomp SYSTEM "v4l/vidioc-g-jpegcomp.xml">
-<!ENTITY g-modulator SYSTEM "v4l/vidioc-g-modulator.xml">
-<!ENTITY g-output SYSTEM "v4l/vidioc-g-output.xml">
-<!ENTITY g-parm SYSTEM "v4l/vidioc-g-parm.xml">
-<!ENTITY g-priority SYSTEM "v4l/vidioc-g-priority.xml">
-<!ENTITY g-sliced-vbi-cap SYSTEM "v4l/vidioc-g-sliced-vbi-cap.xml">
-<!ENTITY g-std SYSTEM "v4l/vidioc-g-std.xml">
-<!ENTITY g-tuner SYSTEM "v4l/vidioc-g-tuner.xml">
-<!ENTITY log-status SYSTEM "v4l/vidioc-log-status.xml">
-<!ENTITY overlay SYSTEM "v4l/vidioc-overlay.xml">
-<!ENTITY qbuf SYSTEM "v4l/vidioc-qbuf.xml">
-<!ENTITY querybuf SYSTEM "v4l/vidioc-querybuf.xml">
-<!ENTITY querycap SYSTEM "v4l/vidioc-querycap.xml">
-<!ENTITY queryctrl SYSTEM "v4l/vidioc-queryctrl.xml">
-<!ENTITY querystd SYSTEM "v4l/vidioc-querystd.xml">
-<!ENTITY reqbufs SYSTEM "v4l/vidioc-reqbufs.xml">
-<!ENTITY s-hw-freq-seek SYSTEM "v4l/vidioc-s-hw-freq-seek.xml">
-<!ENTITY streamon SYSTEM "v4l/vidioc-streamon.xml">
-<!ENTITY dqevent SYSTEM "v4l/vidioc-dqevent.xml">
-<!ENTITY subscribe_event SYSTEM "v4l/vidioc-subscribe-event.xml">
diff --git a/Documentation/DocBook/media-indices.tmpl b/Documentation/DocBook/media-indices.tmpl
deleted file mode 100644 (file)
index 78d6031..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-<!-- Generated file! Do not edit. -->
-
-<index><title>List of Types</title>
-<indexentry><primaryie><link linkend='v4l2-std-id'>v4l2_std_id</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-buf-type'>v4l2_buf_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-colorspace'>v4l2_colorspace</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-ctrl-type'>v4l2_ctrl_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-exposure-auto-type'>v4l2_exposure_auto_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-field'>v4l2_field</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-frmivaltypes'>v4l2_frmivaltypes</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-frmsizetypes'>v4l2_frmsizetypes</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-memory'>v4l2_memory</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-ac3-bitrate'>v4l2_mpeg_audio_ac3_bitrate</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-crc'>v4l2_mpeg_audio_crc</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-emphasis'>v4l2_mpeg_audio_emphasis</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-encoding'>v4l2_mpeg_audio_encoding</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-l1-bitrate'>v4l2_mpeg_audio_l1_bitrate</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-l2-bitrate'>v4l2_mpeg_audio_l2_bitrate</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-l3-bitrate'>v4l2_mpeg_audio_l3_bitrate</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-mode'>v4l2_mpeg_audio_mode</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-mode-extension'>v4l2_mpeg_audio_mode_extension</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-sampling-freq'>v4l2_mpeg_audio_sampling_freq</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='chroma-spatial-filter-type'>v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='luma-spatial-filter-type'>v4l2_mpeg_cx2341x_video_luma_spatial_filter_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-cx2341x-video-median-filter-type'>v4l2_mpeg_cx2341x_video_median_filter_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-cx2341x-video-spatial-filter-mode'>v4l2_mpeg_cx2341x_video_spatial_filter_mode</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-cx2341x-video-temporal-filter-mode'>v4l2_mpeg_cx2341x_video_temporal_filter_mode</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-stream-type'>v4l2_mpeg_stream_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-stream-vbi-fmt'>v4l2_mpeg_stream_vbi_fmt</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-video-aspect'>v4l2_mpeg_video_aspect</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-video-bitrate-mode'>v4l2_mpeg_video_bitrate_mode</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-video-encoding'>v4l2_mpeg_video_encoding</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-power-line-frequency'>v4l2_power_line_frequency</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-priority'>v4l2_priority</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-tuner-type'>v4l2_tuner_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-preemphasis'>v4l2_preemphasis</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-audio'>v4l2_audio</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-audioout'>v4l2_audioout</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-bt-timings'>v4l2_bt_timings</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-buffer'>v4l2_buffer</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-capability'>v4l2_capability</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-captureparm'>v4l2_captureparm</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-clip'>v4l2_clip</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-control'>v4l2_control</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-crop'>v4l2_crop</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-cropcap'>v4l2_cropcap</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dbg-chip-ident'>v4l2_dbg_chip_ident</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dbg-match'>v4l2_dbg_match</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dbg-register'>v4l2_dbg_register</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dv-enum-preset'>v4l2_dv_enum_preset</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dv-preset'>v4l2_dv_preset</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dv-timings'>v4l2_dv_timings</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-enc-idx'>v4l2_enc_idx</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-enc-idx-entry'>v4l2_enc_idx_entry</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-encoder-cmd'>v4l2_encoder_cmd</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-ext-control'>v4l2_ext_control</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-ext-controls'>v4l2_ext_controls</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-fmtdesc'>v4l2_fmtdesc</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-format'>v4l2_format</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-fract'>v4l2_fract</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-framebuffer'>v4l2_framebuffer</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-frequency'>v4l2_frequency</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-frmival-stepwise'>v4l2_frmival_stepwise</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-frmivalenum'>v4l2_frmivalenum</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-frmsize-discrete'>v4l2_frmsize_discrete</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-frmsize-stepwise'>v4l2_frmsize_stepwise</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-frmsizeenum'>v4l2_frmsizeenum</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-hw-freq-seek'>v4l2_hw_freq_seek</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-input'>v4l2_input</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-jpegcompression'>v4l2_jpegcompression</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-modulator'>v4l2_modulator</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-mpeg-vbi-fmt-ivtv'>v4l2_mpeg_vbi_fmt_ivtv</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-output'>v4l2_output</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-outputparm'>v4l2_outputparm</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-pix-format'>v4l2_pix_format</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-queryctrl'>v4l2_queryctrl</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-querymenu'>v4l2_querymenu</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-rect'>v4l2_rect</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-requestbuffers'>v4l2_requestbuffers</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-sliced-vbi-cap'>v4l2_sliced_vbi_cap</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-sliced-vbi-data'>v4l2_sliced_vbi_data</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-sliced-vbi-format'>v4l2_sliced_vbi_format</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-standard'>v4l2_standard</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-streamparm'>v4l2_streamparm</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-timecode'>v4l2_timecode</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-tuner'>v4l2_tuner</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-vbi-format'>v4l2_vbi_format</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-window'>v4l2_window</link></primaryie></indexentry>
-</index>
diff --git a/Documentation/DocBook/media/Makefile b/Documentation/DocBook/media/Makefile
new file mode 100644 (file)
index 0000000..6628b4b
--- /dev/null
@@ -0,0 +1,386 @@
+###
+# Media build rules - Auto-generates media contents/indexes and *.h xml's
+#
+
+SHELL=/bin/bash
+
+MEDIA_OBJ_DIR=$(objtree)/Documentation/DocBook/
+MEDIA_SRC_DIR=$(srctree)/Documentation/DocBook/media
+
+MEDIA_TEMP =  media-entities.tmpl \
+             media-indices.tmpl \
+             videodev2.h.xml \
+             v4l2.xml \
+             audio.h.xml \
+             ca.h.xml \
+             dmx.h.xml \
+             frontend.h.xml \
+             net.h.xml \
+             video.h.xml \
+
+IMGFILES := $(patsubst %.b64,%, $(notdir $(shell ls $(MEDIA_SRC_DIR)/*.b64)))
+OBJIMGFILES := $(addprefix $(MEDIA_OBJ_DIR)/, $(IMGFILES))
+GENFILES := $(addprefix $(MEDIA_OBJ_DIR)/, $(MEDIA_TEMP))
+
+PHONY += cleanmediadocs
+
+cleanmediadocs:
+       -@rm `find $(MEDIA_OBJ_DIR) -type l` $(GENFILES) $(OBJIMGFILES) 2>/dev/null
+
+$(obj)/media_api.xml: $(GENFILES) FORCE
+
+#$(MEDIA_OBJ_DIR)/media_api.html: $(MEDIA_OBJ_DIR)/media_api.xml
+#$(MEDIA_OBJ_DIR)/media_api.pdf: $(MEDIA_OBJ_DIR)/media_api.xml
+#$(MEDIA_OBJ_DIR)/media_api.ps: $(MEDIA_OBJ_DIR)/media_api.xml
+
+V4L_SGMLS = \
+       $(shell ls $(MEDIA_SRC_DIR)/v4l/*.xml|perl -ne 'print "$$1 " if (m,.*/(.*)\n,)') \
+       capture.c.xml \
+       keytable.c.xml \
+       v4l2grab.c.xml
+
+DVB_SGMLS = \
+       $(shell ls $(MEDIA_SRC_DIR)/dvb/*.xml|perl -ne 'print "$$1 " if (m,.*/(.*)\n,)')
+
+MEDIA_SGMLS =  $(addprefix ./,$(V4L_SGMLS)) $(addprefix ./,$(DVB_SGMLS)) $(addprefix ./,$(MEDIA_TEMP))
+
+FUNCS = \
+       close \
+       ioctl \
+       mmap \
+       munmap \
+       open \
+       poll \
+       read \
+       select \
+       write \
+
+IOCTLS = \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/videodev2.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/audio.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/ca.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/dmx.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/frontend.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([A-Z][^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/net.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/video.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/media.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/v4l2-subdev.h) \
+       VIDIOC_SUBDEV_G_FRAME_INTERVAL \
+       VIDIOC_SUBDEV_S_FRAME_INTERVAL \
+       VIDIOC_SUBDEV_ENUM_MBUS_CODE \
+       VIDIOC_SUBDEV_ENUM_FRAME_SIZE \
+       VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \
+
+TYPES = \
+       $(shell perl -ne 'print "$$1 " if /^typedef\s+[^\s]+\s+([^\s]+)\;/' $(srctree)/include/linux/videodev2.h) \
+       $(shell perl -ne 'print "$$1 " if /^}\s+([a-z0-9_]+_t)/' $(srctree)/include/linux/dvb/frontend.h)
+
+ENUMS = \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/videodev2.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/audio.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/ca.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/dmx.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/frontend.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/net.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/video.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/media.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-mediabus.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-subdev.h)
+
+STRUCTS = \
+       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/videodev2.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s\{]+)\s*/)' $(srctree)/include/linux/dvb/audio.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/ca.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/dmx.h) \
+       $(shell perl -ne 'print "$$1 " if (!/dtv\_cmds\_h/ && /^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/frontend.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([A-Z][^\s]+)\s+/)' $(srctree)/include/linux/dvb/net.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/video.h) \
+       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/media.h) \
+       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-subdev.h) \
+       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-mediabus.h)
+
+ERRORS = \
+       E2BIG \
+       EACCES \
+       EAGAIN \
+       EBADF \
+       EBADFD \
+       EBADR \
+       EBADRQC \
+       EBUSY \
+       ECHILD \
+       ECONNRESET \
+       EDEADLK \
+       EDOM \
+       EEXIST \
+       EFAULT \
+       EFBIG \
+       EILSEQ \
+       EINIT \
+       EINPROGRESS \
+       EINTR \
+       EINVAL \
+       EIO \
+       EMFILE \
+       ENFILE \
+       ENOBUFS \
+       ENODATA \
+       ENODEV \
+       ENOENT \
+       ENOIOCTLCMD \
+       ENOMEM \
+       ENOSPC \
+       ENOSR \
+       ENOSYS \
+       ENOTSUP \
+       ENOTSUPP \
+       ENOTTY \
+       ENXIO \
+       EOPNOTSUPP \
+       EOVERFLOW \
+       EPERM \
+       EPIPE \
+       EPROTO \
+       ERANGE \
+       EREMOTE \
+       EREMOTEIO \
+       ERESTART \
+       ERESTARTSYS \
+       ESHUTDOWN \
+       ESPIPE \
+       ETIME \
+       ETIMEDOUT \
+       EUSERS \
+       EWOULDBLOCK \
+       EXDEV \
+
+ESCAPE = \
+       -e "s/&/\\&amp;/g" \
+       -e "s/</\\&lt;/g" \
+       -e "s/>/\\&gt;/g"
+
+FILENAME = \
+       -e s,"^[^\/]*/",, \
+       -e s/"\\.xml"// \
+       -e s/"\\.tmpl"// \
+       -e s/\\\./-/g \
+       -e s/"^func-"// \
+       -e s/"^pixfmt-"// \
+       -e s/"^vidioc-"//
+
+# Generate references to these structs in videodev2.h.xml.
+DOCUMENTED = \
+       -e "s/\(enum *\)v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1<link linkend=\"\2\">v4l2_mpeg_cx2341x_video_\2<\/link>/g" \
+       -e "s/\(\(enum\|struct\) *\)\(v4l2_[a-zA-Z0-9_]*\)/\1<link linkend=\"\3\">\3<\/link>/g" \
+       -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\) /<link linkend=\"\1\">\1<\/link> /g" \
+       -e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" \
+       -e "s/v4l2\-mpeg\-vbi\-ITV0/v4l2-mpeg-vbi-itv0-1/g"
+
+DVB_DOCUMENTED = \
+       -e "s/\(linkend\=\"\)FE_SET_PROPERTY/\1FE_GET_PROPERTY/g" \
+       -e "s,\(struct\s\+\)\([a-z0-9_]\+\)\(\s\+{\),\1\<link linkend=\"\2\">\2\<\/link\>\3,g" \
+       -e "s,\(}\s\+\)\([a-z0-9_]\+_t\+\),\1\<link linkend=\"\2\">\2\<\/link\>,g" \
+       -e "s,\(define\s\+\)\(DTV_[A-Z0-9_]\+\)\(\s\+[0-9]\+\),\1\<link linkend=\"\2\">\2\<\/link\>\3,g" \
+       -e "s,<link\s\+linkend=\".*\">\(DTV_IOCTL_MAX_MSGS\|dtv_cmds_h\|__.*_old\)<\/link>,\1,g" \
+       -e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" \
+       -e "s,\(audio-mixer\|audio-karaoke\|audio-status\|ca-slot-info\|ca-descr-info\|ca-caps\|ca-msg\|ca-descr\|ca-pid\|dmx-filter\|dmx-caps\|video-system\|video-highlight\|video-spu\|video-spu-palette\|video-navi-pack\)-t,\1,g" \
+       -e "s,DTV-ISDBT-LAYER[A-C],DTV-ISDBT-LAYER,g" \
+       -e "s,\(define\s\+\)\([A-Z0-9_]\+\)\(\s\+_IO\),\1\<link linkend=\"\2\">\2\<\/link\>\3,g" \
+       -e "s,<link\s\+linkend=\".*\">\(__.*_OLD\)<\/link>,\1,g" \
+
+#
+# Media targets and dependencies
+#
+
+install_media_images = \
+       $(Q)cp $(OBJIMGFILES) $(MEDIA_OBJ_DIR)/media_api
+
+$(MEDIA_OBJ_DIR)/%: $(MEDIA_SRC_DIR)/%.b64
+       $(Q)base64 -d $< >$@
+
+$(MEDIA_OBJ_DIR)/v4l2.xml: $(OBJIMGFILES)
+       @$($(quiet)gen_xml)
+       @(ln -sf $(MEDIA_SRC_DIR)/v4l/*xml $(MEDIA_OBJ_DIR)/)
+       @(ln -sf $(MEDIA_SRC_DIR)/dvb/*xml $(MEDIA_OBJ_DIR)/)
+
+$(MEDIA_OBJ_DIR)/videodev2.h.xml: $(srctree)/include/linux/videodev2.h $(MEDIA_OBJ_DIR)/v4l2.xml
+       @$($(quiet)gen_xml)
+       @(                                      \
+       echo "<programlisting>") > $@
+       @(                                      \
+       expand --tabs=8 < $< |                  \
+         sed $(ESCAPE) $(DOCUMENTED) |         \
+         sed 's/i\.e\./&ie;/') >> $@
+       @(                                      \
+       echo "</programlisting>") >> $@
+
+$(MEDIA_OBJ_DIR)/audio.h.xml: $(srctree)/include/linux/dvb/audio.h $(MEDIA_OBJ_DIR)/v4l2.xml
+       @$($(quiet)gen_xml)
+       @(                                      \
+       echo "<programlisting>") > $@
+       @(                                      \
+       expand --tabs=8 < $< |                  \
+         sed $(ESCAPE) $(DVB_DOCUMENTED) |     \
+         sed 's/i\.e\./&ie;/') >> $@
+       @(                                      \
+       echo "</programlisting>") >> $@
+
+$(MEDIA_OBJ_DIR)/ca.h.xml: $(srctree)/include/linux/dvb/ca.h $(MEDIA_OBJ_DIR)/v4l2.xml
+       @$($(quiet)gen_xml)
+       @(                                      \
+       echo "<programlisting>") > $@
+       @(                                      \
+       expand --tabs=8 < $< |                  \
+         sed $(ESCAPE) $(DVB_DOCUMENTED) |     \
+         sed 's/i\.e\./&ie;/') >> $@
+       @(                                      \
+       echo "</programlisting>") >> $@
+
+$(MEDIA_OBJ_DIR)/dmx.h.xml: $(srctree)/include/linux/dvb/dmx.h $(MEDIA_OBJ_DIR)/v4l2.xml
+       @$($(quiet)gen_xml)
+       @(                                      \
+       echo "<programlisting>") > $@
+       @(                                      \
+       expand --tabs=8 < $< |                  \
+         sed $(ESCAPE) $(DVB_DOCUMENTED) |     \
+         sed 's/i\.e\./&ie;/') >> $@
+       @(                                      \
+       echo "</programlisting>") >> $@
+
+$(MEDIA_OBJ_DIR)/frontend.h.xml: $(srctree)/include/linux/dvb/frontend.h $(MEDIA_OBJ_DIR)/v4l2.xml
+       @$($(quiet)gen_xml)
+       @(                                      \
+       echo "<programlisting>") > $@
+       @(                                      \
+       expand --tabs=8 < $< |                  \
+         sed $(ESCAPE) $(DVB_DOCUMENTED) |     \
+         sed 's/i\.e\./&ie;/') >> $@
+       @(                                      \
+       echo "</programlisting>") >> $@
+
+$(MEDIA_OBJ_DIR)/net.h.xml: $(srctree)/include/linux/dvb/net.h $(MEDIA_OBJ_DIR)/v4l2.xml
+       @$($(quiet)gen_xml)
+       @(                                      \
+       echo "<programlisting>") > $@
+       @(                                      \
+       expand --tabs=8 < $< |                  \
+         sed $(ESCAPE) $(DVB_DOCUMENTED) |     \
+         sed 's/i\.e\./&ie;/') >> $@
+       @(                                      \
+       echo "</programlisting>") >> $@
+
+$(MEDIA_OBJ_DIR)/video.h.xml: $(srctree)/include/linux/dvb/video.h $(MEDIA_OBJ_DIR)/v4l2.xml
+       @$($(quiet)gen_xml)
+       @(                                      \
+       echo "<programlisting>") > $@
+       @(                                      \
+       expand --tabs=8 < $< |                  \
+         sed $(ESCAPE) $(DVB_DOCUMENTED) |     \
+         sed 's/i\.e\./&ie;/') >> $@
+       @(                                      \
+       echo "</programlisting>") >> $@
+
+$(MEDIA_OBJ_DIR)/media-entities.tmpl: $(MEDIA_OBJ_DIR)/v4l2.xml
+       @$($(quiet)gen_xml)
+       @(                                                              \
+       echo "<!-- Generated file! Do not edit. -->") >$@
+       @(                                                              \
+       echo -e "\n<!-- Functions -->") >>$@
+       @(                                                              \
+       for ident in $(FUNCS) ; do                                      \
+         entity=`echo $$ident | tr _ -` ;                              \
+         echo "<!ENTITY func-$$entity \"<link"                         \
+           "linkend='func-$$entity'><function>$$ident()</function></link>\">" \
+         >>$@ ;                                                        \
+       done)
+       @(                                                              \
+       echo -e "\n<!-- Ioctls -->") >>$@
+       @(                                                              \
+       for ident in $(IOCTLS) ; do                                     \
+         entity=`echo $$ident | tr _ -` ;                              \
+         id=`grep "<refname>$$ident" $(MEDIA_OBJ_DIR)/vidioc-*.xml | sed -r s,"^.*/(.*).xml.*","\1",` ; \
+         echo "<!ENTITY $$entity \"<link"                              \
+           "linkend='$$id'><constant>$$ident</constant></link>\">"     \
+         >>$@ ;                                                        \
+       done)
+       @(                                                              \
+       echo -e "\n<!-- Types -->") >>$@
+       @(                                                              \
+       for ident in $(TYPES) ; do                                      \
+         entity=`echo $$ident | tr _ -` ;                              \
+         echo "<!ENTITY $$entity \"<link"                              \
+           "linkend='$$entity'>$$ident</link>\">" >>$@ ;               \
+       done)
+       @(                                                              \
+       echo -e "\n<!-- Enums -->") >>$@
+       @(                                                              \
+       for ident in $(ENUMS) ; do                                      \
+         entity=`echo $$ident | sed -e "s/v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1/" | tr _ -` ; \
+         echo "<!ENTITY $$entity \"enum&nbsp;<link"                    \
+           "linkend='$$entity'>$$ident</link>\">" >>$@ ;               \
+       done)
+       @(                                                              \
+       echo -e "\n<!-- Structures -->") >>$@
+       @(                                                              \
+       for ident in $(STRUCTS) ; do                                    \
+         entity=`echo $$ident | tr _ - | sed s/v4l2-mpeg-vbi-ITV0/v4l2-mpeg-vbi-itv0-1/g` ; \
+         echo "<!ENTITY $$entity \"struct&nbsp;<link"                  \
+           "linkend='$$entity'>$$ident</link>\">" >>$@ ;               \
+       done)
+       @(                                                              \
+       echo -e "\n<!-- Error Codes -->") >>$@
+       @(                                                              \
+       for ident in $(ERRORS) ; do                                     \
+         echo "<!ENTITY $$ident \"<errorcode>$$ident</errorcode>"      \
+           "error code\">" >>$@ ;                                      \
+       done)
+       @(                                                              \
+       echo -e "\n<!-- Subsections -->") >>$@
+       @(                                                              \
+       for file in $(MEDIA_SGMLS) ; do                                 \
+         entity=`echo "$$file" | sed $(FILENAME) -e s/"^([^-]*)"/sub\1/` ; \
+         if ! echo "$$file" |                                          \
+           grep -q -E -e '^(func|vidioc|pixfmt)-' ; then               \
+           echo "<!ENTITY sub-$$entity SYSTEM \"$$file\">" >>$@ ;      \
+         fi ;                                                          \
+       done)
+       @(                                                              \
+       echo -e "\n<!-- Function Reference -->") >>$@
+       @(                                                              \
+       for file in $(MEDIA_SGMLS) ; do                                 \
+         if echo "$$file" |                                            \
+           grep -q -E -e '(func|vidioc|pixfmt)-' ; then                \
+           entity=`echo "$$file" |sed $(FILENAME)` ;                   \
+           echo "<!ENTITY $$entity SYSTEM \"$$file\">" >>$@ ;  \
+         fi ;                                                          \
+       done)
+
+# Jade can auto-generate a list-of-tables, which includes all structs,
+# but we only want data types, all types, and sorted please.
+$(MEDIA_OBJ_DIR)/media-indices.tmpl: $(MEDIA_OBJ_DIR)/v4l2.xml
+       @$($(quiet)gen_xml)
+       @(                                                              \
+       echo "<!-- Generated file! Do not edit. -->") >$@
+       @(                                                              \
+       echo -e "\n<index><title>List of Types</title>") >>$@
+       @(                                                              \
+       for ident in $(TYPES) ; do                                      \
+         id=`echo $$ident | tr _ -` ;                                  \
+         echo "<indexentry><primaryie><link"                           \
+           "linkend='$$id'>$$ident</link></primaryie></indexentry>" >>$@ ; \
+       done)
+       @(                                                              \
+       for ident in $(ENUMS) ; do                                      \
+         id=`echo $$ident | sed -e "s/v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1/" | tr _ -`; \
+         echo "<indexentry><primaryie>enum&nbsp;<link"                 \
+           "linkend='$$id'>$$ident</link></primaryie></indexentry>" >>$@ ; \
+       done)
+       @(                                                              \
+       for ident in $(STRUCTS) ; do                                    \
+         id=`echo $$ident | tr _ - | sed s/v4l2-mpeg-vbi-ITV0/v4l2-mpeg-vbi-itv0-1/g` ; \
+         echo "<indexentry><primaryie>struct&nbsp;<link"               \
+           "linkend='$$id'>$$ident</link></primaryie></indexentry>" >>$@ ; \
+       done)
+       @(                                                              \
+       echo "</index>") >>$@
+
diff --git a/Documentation/DocBook/media/bayer.png.b64 b/Documentation/DocBook/media/bayer.png.b64
new file mode 100644 (file)
index 0000000..ccdf2bc
--- /dev/null
@@ -0,0 +1,171 @@
+iVBORw0KGgoAAAANSUhEUgAAAlgAAACqCAMAAABGfcHVAAAAAXNSR0IArs4c6QAAAwBQTFRFAAIA
+CAICAAQVEQEBAgsAJgECAAogAwsTAQopHQYBNAEAAAxNARQAERIQAhoDABwAABZEHRQKGRYKQw0F
+ACMBACUAERwpHR4cVRAFBR5rZhADACR2JiIhBDAGAiWGgQ4AcxQABDYACSeQMSYlJykmESxYlQ4A
+PSYZIS05OSsJHS5JOC8kAEMDUC8SADXLNDUzADbEAEsAADX/2RABCFIAAD/qxB0AAD//BFgAK0Vp
+WT4r3hwA3RsTRERAAEf/5CIA2iYCCUv+WUgz7iIAOk5g3CgVSU5SiD8uB2sABm8AE1X/U1RQOFyL
+4jkfIlz/RV98M1j+G2H/fVk23jtD4T0pXl9ieFtGcV894UIiYWJfAIwA50gOV2p+4kssO2j+dGZx
+bG1qVmj/OHH/aHJzfnBX5lQ7B50AZnahdXd0AKUG5V1ARnz/6mErCqgAAKsAent46GBIW4GhAK0A
+AK8B42FtALIOin9/ALUAiIOBALkAVIf/6WxWg4eBi4SKJrEAmoVtdY2geoP/rYVXhoyOqYVuJbUh
+IrgWX5D/jo6J7nszP7gAsI9S63xnN70zZqO/fZzCOb4+cZr+64dy8otYnJ6b7ImDRcM56IqcWMEo
+oJb/N8ZoTMRL7Y9/QchcsaOTo6eohaj/7ZqKXspXj6v9xal+oK+7d7vTUM+Afco5r7CumLTVStKV
+bs9ukbb/9qx/9q9l8queoLv/e9R66beG7rDImNRhi9aDwsPAs8bWzcK2cd67jtqP5MWUodyB8b+1
+tMr/z8L/j9+kbOXWnN2ZstD7yc7Rzs7Ly9xb183UwdD/+si/qeOmvuKIx9fj4tPCtuWiqOrL+tS2
+y9v++NPK2dvZt+m0ueq80+Wo3OeSwuy/yezG+d7f/eS/z/DS3uf/6Ono4PC71O39xPb02vPZ/+nR
++Ori6e399+vt+PGz+ur65fL55/Xb4vbh7ffX/PPY8vP9+vLy6Pf36fjr/PfM8vjr//f+/vn48P36
+9vv+/vzf+fv4/fvu//z7+v7//P/7/v/8//QpxAAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAFY8AABWW
+AQ2TT8cAAAAHdElNRQfaCRQXGSltwbPRAAAgAElEQVR42u2dDXwU1bXAZwEJtEaNH1nbh68fpoWK
+iE1ao2Bgo9RqIrEg+BIFmqLYLOlMcHHlU6DiQmrJM2jKo0QIBHgUjD5ETcQIlKq0gKDmA+UjiRAT
+BCOBkGzC5re/++6987Ezszszdzc7s9jfPa2wO+zMPefc/5575t67Z5hB/0Ek/W668xckcmVmQZ5S
+CvLmgshl4QCiZu+8ntCOgWlzVfrl5ZZFrl6T/VYSv9x5K3Pj9wnkh9fFFxQE6VcVqXY+8PjgH5K0
++/0bBxDaYcsN0i+vLlTbzH9kjEknkEF3zptjLPPmXL2VwGC/nxysm+YRyc+/S2bHNYUgmtJkf5RI
+vScH3HEvifz05mhqB8G68d6xJO3ecSWhHXYfYdvM99LHGEv6mEF3zmFJ5Gr49e9qVUh7O/wP/w/9
+gf4EXnKwbpjNGQs779bvktlxzULg7TCQzvDAItBvzqMD7hjrMJaxPx0Cv3OdBvqFBRZJs46xCCwi
+O+xNwNfSclom6F2L4j1A/UsG1hgI1jyWUzLEKf/gX0CwevIzsvSlJoyh8IY5LmPhEFhEhsCI9b7L
+oy/uI2GBRaDfPATWaGO596dDADhioJ+7PKyI5SBoF4NFZAcEa6ZjvL7MOg9MAWtPxv4aHdlfM315
+TMHy7Gg4pifN5cUxBMsPisub9dRrqHc1xBCsC7vHH6jVlQOO3eGBhccc9B+rGIWkP/ALBNYEA3uX
+xxasooMGbVaWxhSs0kr9Njs8zbEE60C2UbOTTAOrR6/ZHjB/ZWzBet+gzR0xBmuHfpttsQbLIEP2
+ZpsGVrsBWMspWBQsGrEoWFEAK1UUDbBkQEkJu+Ko+WDxDRmApWmH+WCF0u/bCFYIMyIHK30CL1kZ
+Y1J17wo51snhW1/4d9BdoZlgcZx7mcezzM1yemBp22E2WBzL66fsExVYjmxBxsNed1gHVra8XX2w
+WBc2A/4dDbCSp4v/2PrGb1L1hkKnZ8sRNFH39cel6K1lQyFbvLcZXf3YrmWsNlg6dpgMFltc3dAN
+j3+zazWrCVbKBun8ltcfS3FYBpb0D721L+uCxXoqxO5VfEMiBmsa6BL/+UxWqhZYMFytPSVd5yMU
+qKxJ3jlub7f4D5f+xmqDpW2HuWCxr0r69b7N6oAV6JsTj6VYBpaciP9L0QaLVXQv13ewUqeBdjyS
+ZM0/Cf6uBRbkak03uLSraBHnWfsJAJ/LEi2TIxZs7bPyZS6XZwu0XEaWCiwdO0wFi3sXgC/K4QDi
+qfhEoV8QWNtT8FLK+L90gddHWwjWjNGw1dG/mgW7/jFNsFjYvd/sKnK73Kh7P4oSWHw3JOcDkJGq
+BVbxBfD5IidKqpzOV/3gb05rwGJfRXEAfYM41nMKfMXpgaVhh5lgsVsAeJvj9YOMXVrE6YAlvHwa
+XJSFLJPBOg8m8W2lpLwFQ5YjNFgc6t45OFCx0OVgNRu1iIVEByznu+ArIUixnPMfKGRZARaCSRpf
+ENx/4wwiVgg7TASLc52CA4f4BiobCFmaYDlSusBUC8GaGgC6VgssFnavS3QtC7uXiyJYMP09o5m8
+O2GfOsW8il1TudoisF4FX8hGvy3lc1yGYAXZYSZYa+RBitvy9hyXIVij744RWP+jDRb8ygaCFLdm
+x7KoJO/tyWj2Jz3/JPhjssY8lnNL91cvsNL8KOtk1fNY5iTv3D/AP2UJMaubvGvZYSJY8Jv+T04+
+8eAyBCsFdvBXVg6F2UK7k85oDoUs7N5FsiwjSsk7v5cKkqHsD3nEcm4BnznxHINTENaaCVJpcBGn
+zXQilpYdZoL1iThSB+kXBNbu8VOhzFhwAICXrUzeF2RPnTpp6qy/nAG9YzWSd5gpfqZhRl/AkpjY
+P0HrrtBZDQ468ZuKHVgqXdYk793Ag4zkllXyDZfq5FhadpgJVjMoxZ3g3sHrV84ZzmMB8LpjdCym
+G3r/oDXdwFaD97EZHG9FxQ53VHKsadOh5K8/q51jYbDwC/FSiywFixX7/Sirk2Np2GEmWA2gHOvn
+Efe3aCfvXiTA27J9lpVLOl7cLvyH2g2PaU6QSmCx4mXcXDTASkaSmpxxEvw1VXsofBLPt79/9AgU
+2DJr5VDIFh2rh9IM6vXA0rDDgqGQW4b1awAN+neFvzoDvpTPjlqVvD8Nw+ToFG2wxKGQO3gUmnEk
+GmAlS/M/Y5KXg5pkLbD45F3IsdhgsExO3vHS5JMV2mDp2GFJ8o71KzYCK+VhSJYjxXKw4A0DeF0P
+LDF5xxOVXLQiltg384PAktaanxSmG+D9AkrtEFhWLEKzr4Jv+FsUNOizO/QjloYd5k439C6SVIID
+doPRPNbTXeA96yPW6JS3AFCkWMrpBg/qXmmYcEcbLO2IxTrfBRdfcAqYOZ1WDYVozvGf0s2vkxAs
+6yIWGqs/l9ZsnWtBsxFYKHa8bOEitDiPBQfhc49prhWyqHuliWhX1HIsvI1JL8eCMJ0CF1ezeBxk
+iz+xLMdCSyYfzRZugbd0gCO6OVZoO0xd0lnTDT57QdiktqYDtBnOvMPYcc7CRWhpghSmWW9qgoVW
+EC6u5uMGh7s3KmBNQzJ9+UnQpTnzzjmLTwHwRUVxcemWBnjnusuqRWi0ctX5cXlR8dq9HQB8s1pv
+SUfDDlMjFkxPQO/H5auKy/e2of0XhmuFKQ93gTctHwpHO1ColA+GqkVovntXFQndG5WZd0m6fqe9
+bYZzej6RPvjZ6qAJUtP2vLNrpP0c53bNYXVm3rXsMHnbzFrJL727XtCbIA0srYA/pVg33SAu6dx9
+BpyQ3Teot80oujc6E6TtWBpr1mfobPRDUrzlSEfH10d3FcEbBws3+rnX7m3o6Pjm43K9jX46dpi8
+0Y9zFe891tHZ/HHFMo5zEawV/uo4+HKsVWCdli1C+2F2p7nRj+OK+O7dUeRio7vnPdVoazIr3/Ru
+4dZkce2bI9vznmr51mRh2wd72e95T9HdmhzKDEt+paP4MQX9+Rf9lU60wKI//6JgUbAoWJczWMRF
+QehQSMEyJWJNM7B3eYwj1re8KEhnjMGaZNSsaUVB0tcrZaPqbVaMyxiVVlcqRP22KLZljEqLlApV
+q97uiG0ZowOOVzboyitmlTECK6fly2V6fr7qfXtMwTpaVKyUUtX74uYYggVAs1o9lX5F1SCGYDWB
+l2bMVMos5dsZL4HwwTIQFwYrmmICWNEUM8CKnpgDFpmEAVZQM263+shsl1ZxWz/6H/oD/ukPC6x5
+s42L6s4mrEFqClgkRX8hWPeONRYzwBpN0i4Ci8iOkGB5Q7xjbP2CZGDwoX62K29Qy/U33RB8bEDS
+SLUkpfUlYjE3EMmVIewIJTZ7sH4FfQHrqhuuV8tNQUduuJrpTyQ228hg/UoiByuXsN3+A64OtiPE
+kauYEP0bslw4c9MD9xPIA9d/5wc/JJH+uWUlaunL6Di3P1GzPxhMaMfV920N0q8qcvVO27/34/80
+lh9/b8D9D5DIz+3B7ivZFzlYv73+AaKG7x9AaEd8YbB+IUdH5hdkddR/9H2iOuX3XrE1ujnW3O+Q
+tXsdqR3PRnko/GUGQXX5jNsYjki9B5JIWvWSg3UrmVtY5jYSO9J/SV7n/efzOJKsDYI1mkSugOGp
+7ai+HAsLrLEE2afj3uvI7JhzEwTrgJGEA9ZtRPXlbx/wJMlNCA/WfgNpB/4wwCJyy5PM7UQ56u0w
+x2o7YtC/bSaB1eZx6xcqd9XHFKyXpLpnGuLYQBwTog+WF7wmlo3TkIzp7SB2YJ027F63p80csOoX
+dXR3aksHKC2PKVjZG8BpPQEvzYgpWPkrhd1koaWnJqMmhmCdqXd3dOpJd4e73hywjngM7C2viClY
+M7YbtPnKrFiDpSutWY0xBcuoe4HHNLC6KVgmgtUYa7AM8ncfBYuCRcGiYH3rwRJ+UKYLVookVoLl
+0Gw3FFgh7TAZrNRkQVKNwVKXCLIIrNBuUYKlZUZfwOJYd3FpeemqZawOWI4VCwSZ6bAyYk0V2501
+VVnzIBgsDTvMBSt1+vL5WPKVtZNCgMW6iqB6pcs41lKwtNyiACt1gmjGNHWZ/IjBYj17+T0jX+9a
+xGqCNT5wlZbXrQMrJUBEb+0f5D9NDwJLyw5zwUreLx4/80Z6qg5YrGvLMeykznplPXiTwZLc8o3K
+LQqwkqX9cl5VdbGIwWLXXIDGNjc0dwBwSfFLRWXEAoB/NN3xLgBetw6sDeC00C5UT/5LXjVYmnaY
+DNYe0IoeydgIe75GBywO/SC0t62hARXpV5S7NhcsdouWW9RgdfFm+EGXskx+hGCxW/yoTjnHch6o
+wsUXdMDi053Rk94CQFFewmSwtgsp1oIz4M2xmmBp22E6WCtxapK+shv8MVUTLM8p0LurCFVRXauq
+B28qWKj2hcwti3TAqklORRlWvrpMfoRgeU6Cz4VfvqLyDB+x2mA5UCV62OV3v6V8xoHpYOHC+6ic
+9CUZ0CqwtO0wHaz1yWPSUfb7GngjWQss9l0UL4QSVKgevEVgofrtvFtw9Y1drA5YqenIjuT5UqGx
+voCFCnzPFltzvgo+l1XADwZL6Oy/SHUIrAFLfH0azNACS8cOK8DCr1aCPVpgscXdgSjFek71yoqH
+mAkWrt+u4ZbgiKWuYNcXsIrlNe9dntJlLpcxWG8pC+JYBdbDivroSrB07LAALFw9acwH2kMh7ODP
+ZflN6arZ1kQsPbeEAAvbsTIaQyG79pQ8HXEpCnyHzrFSUHGJP8Ugx4Ij8InHNHIsPTtMB2vjmIyM
+jKzpe5QdohwK/6GsB29R8q7rliCwxmRBM6at7z7zm2iABb7RLPCtBmsFlld2A/CplXeFtQtwuxvO
+AHmxFDVY2naYDpbU+2O0wTolPPmBcwbVgzcVLB23aEw3gK7fJfd9uoEtB8f4Osw7ULnc+vpjHlYL
+rIDjP1UW/jUZrIC8PFoTLB07LAML7E/XBMsnlBUv4tU7uoO1BKwK0S2VQrsezhAs0Pi71KiB5XaK
+v6srZnXnsbygd/tMVWFnk8FqOYAnsb58KVt75l3PDvNzrFS0E3nCym7FWKgEqxsUadSrNxUsyS1t
+wW4JcVcIBT2VrysKEWut/yIfossr0SMJOsEqVjfHelo9O2pRjvUW+FJZ9Fc9FGrbYdFdYWry/G4g
+G0XUQyFOojkPUq/iiKxIr7lDodotRazBXWFqctZJ8NfkKCTvwnQsXw65Qw8sNI/FFwxPsRYs9BzH
+46D3MZ2IpWOHVdMNY1JrwHwNsHTq1ZsJFgfd8oLCLYZgwZfrFfNxkc5jfSKfS2QNwBIKhv/J4oiF
+XkxCFTS1F6F17LAMrGRtsFhUDz6g7A6LwFK5hbMQLG4NWl/gxJKMHXo5Ft+vdx9XFQy3BCx+ENZe
+hNaxwyqwUtNPakcszyk0A87x6jmrZWXFzQULAh1wC8z0VhmClZr6RjTAQlN34O1l+HET7jUNQIa0
+BlgpDwNFOWmrJkhhqOzVWYTWtsOatcLk5DGvgTOy/Q2qJZ21F8AXq92ouoq7aK8ffMxatFao7ZZg
+sPj9WMv9QHFbGCFYnAs23ftxZcWOgx3oOezGM+9BT8+waOYdDoafai9Ca9thOlh7lq+Esr4GKJJe
+1SI03nzxBVSvGpW9/uwFa5Z0VG659LbOPFYjNmPlHgD+nhyV/VicVEi996NlrM5+LLG3YQ9flG+6
+Mxms3YFnGsufIBm0H0vLDqv2YwGwUXc/VvFe8XNflLo4y/ZjabpFcx5rf3qUdpCyruLqg0cOVpe7
+We2Nfo7aA9Ja4YLa2plWgbXi+EvSIvT22t1jdXaQathhMljra/BPlfe8sVK5jSloBynLeir2HqlH
+5eBZ6/ZjSW6pVLtFCVa+YMaejdNTo73nnTXY8x76tfl73h2ybfcke97Z2Ox5Tybd887FZs87S7bn
+PWjTu9m/0nE4ZC8dlu15d2i1e9n8SkeonfFt/5VOuoYd9Odf9OdffQKL/q6QgkXBomBRsPoKlo+C
+9e8MllGzZoFV7+4EPm3pBqWxBSt7A/DqyWVQxqirpwv+H/6BRfybF9AY4zJGHt3u9YFOs8BqVlfi
+KlIXXjsYU7BWOCYpC61NUr6f5NhArJ4ZYK1Pn6astKZ6mzWtNYZgnf7aYyjNPFizSeowQ7DGkgiq
+QdpWf0QhR5Vv64+CcMAiaheBRWZHqFKRu1UCog7WbQOcROWucanID5RSs3+PUlrDKhVJ5BYnQ2iH
+vQl8repetdTj/ZXMreyTBML+6EbHHSRyRYmv6fQZlYDI5ZnvELU7+joyO5w3PXO+6YJKuiNXr8l+
++5hfGkv67cyjThI3329vamrqVYu61TCK2/6IzC2PwohFYAeMWB8Gd29IdZgBVwbJVVcFHxtgG0wk
+tiH2IBnZB7BKCNu9NpQdwYeuZOKD1IvP7QNYSf0GBsmg4EP9mBC6XB3iWLB69viIn3ngA8+GajeU
+MKR2BOtnD13nPbNuH4HUjcwl+ty+pMLgz9X1BayRZPpl9sGOPujXNKSs7kNjqSuzV5HoV1eYFOJo
+U+Rg5RK6pcreBztCTgIwhF/XtKVkn0siqfPeRe6bQsLHWuROJrRjIYimNNnJqKyznyf63NakaGrn
+Azk5ZJ/sIraDpM67VwCrcf1GXVnfDjtkLgANldX6gsAqA2C//vXWv0acJPBgvW/QbmUbADkQrI0b
+CewoAJ1GZlSHAxYcB+r1L1gJ7773oWfQbDd4HNsBASwD7SobwgLLf3yDgWzn7TDqXtGOAxsM7fBi
+sHqmTcifriP5WfkYrA6P+nlsKnFVYLBqMqZN15X0jWFFrGqXfrPFniIfAmtlhq4Zgh3PglJ3qbEd
+YYBVb6Sfqx53yAbHzBm64qiFYPlAhUtfvyJPWzhgeWdkz9JtdqZjA7TjX4bdy9txoXb8jBmGdmCw
+2rMMJtzemIDBanYbGFRZjMHak2VgbziP7oVgVRg98PSYuwOBZTRjzdvxLPAYPmG1OCywqosMPlRU
+jcFascDgc9m7MVhGj+7tcDeEA9bp8bUGH1uwAoH1tbuDxI4LB7KBsR08WBP2AP6Rb/5QAjtkGg+W
+0SNj0bOUk/hnQoe8EN9GTwRg6Q/sxzydAlh+YzuejfIzoavA+0ZgreLBemmBfgrgJQQrnGdCQ7DO
+Zx8wSIh4sNoMA+EqASyyZ0IjsPYbfNPDBSuKT7EnilgSWAR2ULAoWBQsChYFi4JFwaJgfVvBajcA
+azkFi4JFIxYFi4JFwaJgUbAoWBQsChZN3ilYNGJRsChYFCwKVphg5RCCVUAG1pCS6A6Fc0eSgNUB
+cu4jBKsgumDFE4IVTwZWmT3KYGWC00RgxROCFU8MViEZWLklZGDlVEU3YpXlkkWswgIysKAdUQUr
+s44IrLpMMrCqMkFUwVo4lzBiZf7raxKw6jK7ScECRGChaxGBBSWqYEEhAgsKCVjQDm80wUJCAhYS
+ErCQRA8sLERg4e5tI7Jjd1TBQjuiiMDygegOhfCCZGD1kEUsnzeqEQvZSwSWjxAsX5TB8hGC5SME
+yxdtsC77iOUnAwsKjViXU8QKC6xoRiwKFgWLRiwKFgWLgkXBomBRsChYFCwKFgWL3hVSsChYNGJR
+sChYFCwKFgWLgkXBomBhsGoIwTIoR1IpgmWg4PIwk/dygw80IMUgWOsJwTKsNhNlsIolsPRlkgBW
+pf7HOsIFy6jazIoVRN0r2LHbsNrMJBGsjNcaa3SkcT1fl6jBVd/coCNtFXz5nz0ZNcrrqa7emB8m
+WMVtDbrtHnR1oC9e/nxdMyQ7PJUG16soDku/ao+uWxqaPTwpK2Ycr9WV8TxYxeW6+jUfcTWEo97p
+8dv12z0+cwXfvUeI7Ng9vraWwA4IFliZkaWQaRMUbydk8KHAV+7WL+8t1G9vn66+nvJtFnEBfGGk
+W2RQVhwXSvNDoLN0RbSj0uUhsoNUDOvaCxGmdrxKpirfOma04M/VG+jnLveFpd8Kh7Kd7Gy1IgeI
+ulewo2WG6nrjs0PZwaCa4Y2tja2tjY3wL/g3fo3+j9/gF9LorpQO1Xt+jPaDdnxuo3AJ8bKyNkjr
+lIuxv81AhM81tirsaNWyo43wepHqp37fKeQyLcdb9OT4eSEHazO4XpjqAf1moVZ8uz4jt3TyZpw3
+uh62gyFSzQ8uf/H/m9jxbyIMdQEVChYVChYVChYVKhQsKhQsKhQsKlQoWFQoWFQoWCD0g0V8fvUL
+2SdDbKDwmqqu1xtQQd1SqCNBp/WYrKDkpR5/kEt9BKf5zFscUDTfE/zSq+llXwTdq4hYWwvmIlla
+8o786M6SwmeXbj6ruOjhrYVzl5YdEo41FSycK5z5odnfhJadJagZ6XG7hULLSBm0ZFNXoDgiSi86
+benmdtO/qYGGsGuqeJfOXbi0rJVfUtonOHnp5h6VlxeqvRxlrsokXTa3KjpzHWq6Sd408vKzopel
+M5eWHIpsKExjBIkfd1LEc93wBHxo2JRuiebD9wyxoWOJ4w7hz9QxktinmNp3LYtvxi3HD1si+EFs
+2JY4hf9yyHXhu9ILehcPF0/zmxey4IV7BXfFDVvSjRvKlanzIj5SKB0Y9g7Q8rIpYKUxoZremZYg
+eOuk6JqAlzerzhTACBesTGZkDpTJsKlbeANbHoH43Dc5J3M4w9wiXvP5BCYOHUuzMQO3ocel1jHx
+OVgyYf89ZOJ37vBQ6JP7YDsJjO0hXsN4JlNs+SkcIhi7qAsDj3Sh074cJZ3G3GVaz6H9C7Ahu+Cu
+u86iYwVMkqBOAtNvG3JNCX9kMjww6JD8tEzey2dN857QvTk5sH8HviN00xM2Ji5tMvZfIj7mlbyc
+hrzs589ME8Eg9Z8KrBL+xbqh/V7EcX0iE7fkEPrWt6yTrvmcjZnyYQ+Ol6OYQTU4YsVLEaV/3Aem
+9dyXI5jEzdjxdYttzO9xOLIzTfwQ9Hx/rEsVIz7bvOURW2KNeNqSJv60BHiaecPgKNjQId4PCcyD
+PFjis5EPj7Jh1kqYTOHACPgRv+RlIHj5Qb95YJWIugy1Pci/eo6JEzpz3XAhdEB3DdvcJHr5KcWZ
+6wbzYIQNlvjA9CeY3yKbN6GQJMh7gxkcGE8k2J4Sj50bxUzhwRLzu97/Mq/n4LWlqAnxjsOv7cw+
+4V+HM1sxWElisnnpZ7YXkRXPMbdIucEm4bToC24oUcpON/W3HVKABb66FkeoEiYNKojo2cQMA7yX
+A6dBL79jHliFUjPMNThlec8WJ4FyYiizJNjLiScVSCIwIgfLDxZiPHqHMjI+JyIdusAjzDi/6Enw
+pu2hs3Kw/HJPRrvjDg+OCzj93IjEDySwvH6o2HDbZgVYXYI9h69gtgXgHJG4zaxtWS3XMbJrTxy4
+TeUO/jvAg4XzdeYWrNJ1zIuB9GFi3IsWgNXL2M6jUW8UzFykf3+OeQpqj73slcYI6OUAWH6QRxo3
+QkescyP6ob54b8A1rYF/PXcIJiz+iz/jUwW+oUsfnvdaFrH+zPwk0AG9hw95gWwohN91/EWTR6x7
+bEuE0wLSiawwR95kftKtcpccrBPX9jskHwrBRD4rhNHjrPo08yPWoPNYpUEBiADsTOyuu4CkQm8n
+9LIsYn05ot8HEYGVu68KyrpRcLSDt3+/tj0l3HBCEW6Ot18x7JR0DM+6+GU5Vi/MsfaY1XG/Zv4X
+KNThc6wSrPPihMRtQJFj9T5iG/gBPu2/g08zI3VXNCT0TagcKw0rvPUe20N4UgJ62a/2sgU5Fmpz
+Q/9xFwKdqeVldGYeD8bQuCWE92YqsEQZ181rsjTohHXMfUGXhmAVYMk19a5wKBNiGiU+XtSZn26o
+YobMRark5eK7Qi867R1ggfjguLI56GgBM5JXJwfeSgt3haLGiYcwj6G8bBJYabwu8IZ0IJ4oeoZ5
+POj7EexlnwqMSMCyJyEZYkP5G5q+4BH3jeQlTYjkXlxCPAkfS6rDYEkTHQ+1muYaO1OHo03VEL7l
+PB6sJEFnfGsMwZJ0ieMjwRCmisdfUDgH+MzpuJH47gGAJqGhTHisIDB3lMinEBAsXuEEG8zZ/TIv
+JwW8bBJY4pyfeLeQJ8bTNEFlH/DFq7xcgM+UgxF5jtWybiiDponE75JPpAb75T4erCTh4D4MVi6U
+oTbhZtskuVn4LolzoJkibcJEBx6Jqhg7VCUnIT5xyVnxtHeEWMZLmllgpQkRS5wvTsJgjczLzc0c
+HD9MnPUXcyzv4XuYRMXXV+ZlsyIWdE1mf2bcZiHuSBFLRA7mqwlBXg4Moi3rbmYe8kcOFkzuEq75
+AA23S7AGvq1QqgqZIfD17sHj+ByrCh3cahfAQkc+HYxaNW+x60Zh9G/C6uSIYO0Tb/ZtP+mRcqxN
+trglqtSMPy3XLLACORbvLogUBiuXny5KFO9MA3eFJ0b0ezHotELIo6k5Vu9E5hYxY39ezLFwZ5bF
+I7DUXs5RpP0QjJo+gNUDhjNl6DZHfldYh8E68bNB2xTD077AXeGmBHT3ahpZf2YelC2eFirAQvdT
+TL/zgbvC51CGhXVR3hVuNQss3JDM9io5WLA3+21TgyVMCilvJveZCVYh8si5UWjePYBJICXGEes5
+6OUumZdz5Gm/X5gtjBSsLhif4fmXZPNYfvAhAgvNYz0kW65UgAWet9leNAsrPzjcP64m8G6pGqxe
+xtYjm26YaBO6Ep4mZu9ePygzD6xzV0jzWLChrXKwwLkRaNxTgCVOcp2TzbMhL5sLFpozGMrccoEP
+sqOYpwJN92CwdvZPVHhZAVaXlEhGOBQKcUk+lQzvB6/FlPfv91RgkeVaOVj+XvhlOGkWWTiIB67+
+hHoofNP23XYZWOew+/zq0xabB5Ziih+6Sw4WzhOE5F1U4NJE2+9BsJeHmD6Ptckm8iRfWgGH8awp
+dNddSi+LYHl5MPZHApYAZssjDB58YSOJwlrhzidsaAUCyNYKfXWLb7bZ6gJgecGJwba7zNs+EFjF
+atl5j42ZrJggPTwUeyswQWjMGXEAAAJqSURBVPpef366gV8rPCuddp9pYPGLkry7HrEx4+RgoTUo
+YbohU5zzs/FBLMjLfpPBgtFcXISeKK4Vnt+3OMEWh159qvTy44oJ0ntIJxxUYKUVoNu7nOEMjs5e
+YXcDOmJjmHHC1/F5G9rdkItWv6EKfsXM+3MMs80srsR1d3hnAxWMm9LKg5WTh3TOTGDUM++PMGgM
+9PrA4VH8adiKKa3m6Ye2UUjuwhMvAbBganNLK45YSdjJuXg/hh97+Z4QXjYTLDgY3iXQ/QQT6Mxx
+7wS8PFn08ln+fhI7OedmJo5wUjD0fixmmLRss244nhey2ccJW3jwfqwEfr/OyCU9wv21CNalEcwg
+8wZDaacQY59yiE/NmcBWITznt5Wxi2DBACJsQhH3Y/GnmSi968SGkLu8aD9WjrSM0h9veAjsx7Lz
+82z8Nq74wGlmgZXGzBW/AZsYKbkS92PF4xiBs4qWxUPkXvaFBCMcsEpy87Aod1ruLJlbwG/HlO0w
+hMcKln4oZDdNuXmBT+dONm8XKcqYdhbCljdLq2sFvMoFS/mOBHU5c6UAsi53ssiR+jTzBDaUt7Ss
+SbwJzSmTdH8+93GYX1TlCE4uUygDvZyn9nKUwSrJqZLePZO7tNsrtHUYdTDuTG9IL/tkYBAvORnu
+eff6Zb0qSo/OcADM3Pfu1VHWq3fAr2djlNlXudQXdCTYjV4L6uCodfEG97RwSL7nXa2zPwKwqFCJ
+mlCwqFCwqFCwqFCwqFChYFGhYFGhYFGhQsGiQsGiQsGiQoWCRYWCRYWCRYUKBYsKBYsKBYsKFQoW
+FQoWFQoWFSoULCqXq/w/gbudjI6bMwYAAAAASUVORK5CYII=
diff --git a/Documentation/DocBook/media/crop.gif.b64 b/Documentation/DocBook/media/crop.gif.b64
new file mode 100644 (file)
index 0000000..11d936a
--- /dev/null
@@ -0,0 +1,105 @@
+R0lGODlhuQJGAeMAAAAAAH9/fwCvAP8AANEA0dEAAK8Ar////wCOAAAA0QAA////////////////
+/////ywAAAAAuQJGAQAE/vDISau9OOvNu/9gKI5kaZ5oqq5s675wLM90bd94ru987//AoHBILBqP
+yKRyyWw6n9CodEqtWq/YrHbL7Xq/4LB4TC6bz+i0es1uu9/wuHxOr9vv+Lx+z+/7/4CBgoOEhYaH
+iImKi4yNjo+QkZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6gQC9vr/A
+wcLDxMXGx8jJysvMzc7P0NHS09TV1tfYxbth2d3e3+DRAePk5ebn6Onl4ezt7u3q8fLqANtg7/j5
++s/z/f4B+wIKHAjsn8F09ex5IciwobuDEM1Bi0ixosWLGDNqrJhQIZdk/htDihxJsiTJiSZTqlzJ
+MmNHj1q+tRznsKbNmzhzDoz3EiYWmTN7+vQJgOfQmN5mAjzKtCg9pj+TBoU61ClCqlaAthSKVZdV
+dFy7NtHKMqxYW1/PmT2bhOzKtWxlpZUYF4pblXDrvpq7Tq+Tu+UGCB5MuLDhw4gTK17MuLHjx5Aj
+S55MubLly5gza95MmVxev0EAkxsg8jNoVXNJ0zy9RPQ41RtNsz6V2vPstlLTwdYo+zap2qt9G3Ed
+YLdL4bGAL0VOhLhxjL2Zf1IeXboM56Wtt6KuPXRudM8vVu+eiTt5H9hDjj9vyfyIXrTW80gfO4OC
++/jz69/Pv7///wAG/ijggAQWaOCBCCao4IIMNujggRe4J4IwBxBg4YUYZqjhhhx26OGHIIYo4ogk
+loihMBbi1k084VlklgLsWQKjBRJqgIwEBJRyY4UqZsNidhjMGOMkQlLgnjERwkdBjuVpk2QFTB5B
+H2/2DUlJkRNYhWQKUTKyJQpdFjHlcUFaSaQxo9nGQph/fCkDm0OMCV2VZh7iZpbnwCYfBnDKcecO
+fXq3ojotckRnnXr8SQGWEtQIphuKEhEoEHKKdygHCUiQ6QEJdDrEphWA2oGo3UXaAaMHOHrCpFmY
+2gSr6H2XJ5AXoHqBp5xyuimpPfCa6we+6uWqCaiqagKsTAxrBbLz/slqTqEUvWgBqLviSqqvnXpq
+rbbZTpDtt9ziSsG3unKraabkltutWMq+UOyswa3A7A/tfjGvDpW6eKm3v+a667i38vvvuQLzW7Cm
+AJ878L/W9ouuR/Xi8O6zasorRMRo3JtDvoaWOe2v4IIc7LUIE4zwtd1Sm7C6KZ8MLsmzYBzExIFV
+rILGJsgcB843cBztvgqHWnKwup5s8rroVivwwEc3DHLR/jKcis5K0JxmvDezQLUePNvgc0TSBix0
+1OuG6nS56nob7ssqp132wuIi7cnWU1j9ms1chkD3IF3X8DVEYe9AtNi37M2F3cXh/WgFhjPSNw1/
+HxS4CS97MPjH/ts5uQfieqbQuCWPzxC5QZPncPnYoXz+BueKY+Bm6J3AHsPo/5TOmup5sB5vxLJv
+0vsLtPtjO1W4D0Kz6r9nknwLwfczvFeam6IAmndjnfcsy2vtbM3qAT2KkhkULwj4SRITIbzLWYx9
+j9j82L3HvyljivzeG1tC9qCzf4379cEPigACCAYAB0jAAhrwgAhMoAIXyMAGOvCBEIygAVMVDBLo
+Ln1ZWx8SmjeP521CAEYiXypAGML1XHBPF8BfJVToue1drX+1GgUJZTHDFJywBSycRA5PwEF5eFAT
+NYRFEE9wwzXRYoc5c2H1YGgBW32QFkMk1vkoZr3FyQKJJeih/lH894kotsKLFpwi9zB4vSvqzxr8
+oxIXPQHGVbRRBEVUnxk3qMTEvS+GonjjBBCwxwMg4I+d0CMI4pjBOUqpjtACm/c4IUhASuCPfPQj
+I1lAyDLGAosk0OJT1hhIC0RSkpDsoyg9GUpAhtKPp6QAJD9pB0F+oJJWvOQZq5FGMuExFFHkYyR1
+OUpWqrKPvHykJIXZyzy40gOwXNURZ0mNWs6Jk5P0JChXKUxHXsCXwQTlKIe5h2OeSowvRKEFMOkI
+ck4IkbRqogyvaU1uZpOd1URlNXepSnriwZscSOaxlknHQekmnRVwIhAxgM09rtKXBrXnKalJzFTe
+AZ8b0Of9/vh5SH+CB6CLWicPEAoIiGpAoiQwp+OYOQ1nWgqaT0TBQTl6TUN4tH7oEyeUKDocdN5R
+nXnsAUv98FJO2i+kNBWTTZkYUI3SkJLgXKJMlxTU5gxVjbf8HxSRSqOY4rCpcXqqLXGKy6muAKQj
+EOkixPoBTV4FpQOdRU+jiicqkjGWsCCrB8wKlkWm9KhfTaod36pMDVbUR4TC6AQEmom1spGqjLOq
+Ef1aU4uiD6pclapaEWskxcpRlv0E7D9vWtScTjavVXXrUicgV0SUlgN0VYtd04pXFYBVBKc1RGxt
+pNVnsvWwn3WtXju3WEM2VrMX5WxGPdtaG+62dftkrFAd/utWyHa2q7k1bmjHOFocYfVitT3pbTsZ
+XRS8NgSzJUR4XZddfaG1sF7V7XTDeVXlOpW5Y3TucKFbXO8et4p99e1ygfvYrT5XsvUl4n35mlz9
+vpe/zfXvfAEcC8P+t63Uba+BswrfF8p3sEZtMGUhzN7eYvav7QuscDFMXA2DNrGilfCHfxvizRJ1
+wV1Mr3RRHGEPx5Wk0jCpebcbzQBLcb1KVfGNM9vi4L6YxPQ1sXpp3OHLDhnE+xPxkSVAWEw4uMcz
+rmyKbfyK8ZYPwfFVMJIZLMQNN8qyhVzxfovcX9tGNsbdFTCQ91pdHrmXwmC2sJipnOEyn1jLNXZy
+l3Es/g4pX5jPJfbzkgHd5DQ/mcVRdvGhD1DlS1z5rlnmcJC57Aov06i8HeMxphWd6TNvWdCdJjRK
+JL1nSvf5FZdGNJM3jepWeJpxoP7Zea0sY/vOmbe1ZsWtS5jnJU660paINXr/rGk6C3nQRI60kY/9
+alco+7sgGLYftN2oXCty15butZxn7WxO21rV/DB0q5FdCWXzmtmmDrSjoQ1lNKrbzQ/GrY9LgO0P
+cJsP/04tXcCdbHH/mNzAnneqo21vVuMbxvpWcqlThWZLPnrN0m6zdt8ccVL7GuHIneidsVthY6+7
+2l80M8VPrfBzM5yW9954vrm77zD+OuRAHbmgir1X/monGtYq/2lYr7tzNif44WOGc81H0G8P/HsP
+Afc24Fa77KXDccB1fjrX0O0MHYea4zSX+McZTeuWC5vrzfC6rkXNWrGPm+zlDvYqol7ynp/859YO
+esXhSm9IN3zad0+yx9/e7IRbvO8Y/7vGdwx2LA/+4HA3PN8XXm+YO1zmEA/74/mN9WdT3u+WBzzS
+ZU1moMN75fI+/OcTH/rFf33mjjf9oguP86HrnFJSlxzV3231EDS9A1rPA915nsipE7zdBuf8zfFb
+YDUf2OhhHr2r8Z7y0wsdtkTHfd2Lr/vjU8Ld4bb+3vPrfDxDX8/SZ/f3k29zkDNf5BMmOfEFS3ql
+/rsd8rR/f87jX/SMHx3zSddxsjdx1wde2UcvuUc6uxd+vTdInWduZ/dyzRRzjAd7ozaAY5d/BAZ/
+5Sd/52dy6YdyrHBtDyh3qjB8H2h3IUh9I6h3LKd6Lld5E3h5FZh5sZd34veCkxeDoDeDogeA9SeA
+ODh78dZoMBiBMlhSFPh6NniBQ0iA49d8F/d8/hd9QDh9goeBhFeEZXeEc4d2zKB238Z2VXd/yud+
+G7h/Hdh/ivd/NRiAmqeF+MeFcWd2XyiBSkiDTAiHN1h9RIh6RriDSNiDefiDbxiEcfiEGUiHkkd+
+U2h+VYh+V6h+kyBBlniJmJiJmriJluiCqSeI/neYhDm2hGvXeJzgCzEjQkxXgnZ4gmC4DGJofGS4
+CcAAC7XYfpFXe9h3ewi4ffSHhfGjiqvwC2eYi/pne/ynffM3YoiYOqhoi894dcuXhsi4hsqYgtyn
+gN5XHt1mi93oe6zoha6Ih6Ooh6VogTpSZ+3RG7/HAcGHBygYiSA4idCYisgUjqA4jqJYaOY4hqY4
+NepYCcI4cwWYbQcYK77IjMBYj3KxFu24Ae94B/HYhlZ4iAuZHAFJCQP5kBoQkXYwka3nhnvYjAyJ
+kWBXkP52kD0gcH2xjQBpj3CIkk6nks2SkFN2kWiRkZOgJByZAR5ZByDpg653jk1YCwM5jADQ/pN8
+QpM7wJIhR4l7oZOSoIoyCXxMiS8JWDsLaJRS+QgwQj5V6Y5XuTFZKTxbmZOvICRKEpYQOZY44JTv
+B5Xx0ZWKgCW+EIUc+IgeKI8qSI9YcZSiUCxp0YhSiHhUSJGSaJFyWTh0WQjv0guB6IiGCYmIOY+K
+GReA2QnHUxSEmZeTuZeV2ZeXWReZqQl2A5nHuIvJ2IvLeJOLuQ2leQmcA5lZ55Y9U5bOc5ZHEZtX
+cl+8mZK8iJCt6XO305h6cEK/KZbBuZK42UG6STzGeQdFlJw+aZte05w+9Jx/GZ10QEjUOU7W6TfY
+uUWzKCzcGQew9J2kFZ6QM56bVJ5+oZ6E/qBP6vmTdBCUhTiU/oiOtyGfgQBS1Gmfc4Cf5WiII4mT
+0uGffvBavymgckCg/GigRMmH1qGgm4OP5GWVy1mTwxl4Q2KheNB0memgO/OKyhCL3QefzAGiddCO
+R0micAChqyah+1mU58GicsCRwgijbyCj6daPsviPMYKjq4OhZdUTPOoGPtp1pFijFGomRMoGSvmN
+draawomNv/iaCXqeh2Ok51Sl1siaWKqQWlqhXJoFU4pr7Ck67nlWKgqlZ2oFaQolUZo/5Bih+hmk
+/IkoIfQHc8pUFKSXbBiSFXmgZcoedQoGf7qeWRKngrCkadekemqjfPokx+mlakilqQCp/mEoqSkq
+pJWaoSGKqdXYp5tqoiDhqdr4pqFqqi1KqqppqabAqbCoqlrpkq3aqK86jbW5AYlqWqiKDCi6qqCa
+q7Q1B4tqXR3wq4VAqydqq2aJq8bqqm6QrGCKWo4KlMF6DMN6q6w6rbIqpbBqgHqTrQ+6rdQDpJ+6
+p+C6rObqA9baNcy6behaDN0ard/arqKaBvGaRJzgrKmqrsTKrvo6V++aA/3KQwebBgArrNCam9Ja
+sPtKBgmLAvMqkfVKDPcKsfkqscdKseNqkCtwsfeZscOwsc4ZsR4bPgsbAxU7si0bBg3LrQ+bsh27
+sr4asy3wstojCTObrjQ6qU+Ks/7q/gU8yzw6uwU/a681m50qS7Q52wVH6wIkuwZLq7FNS57FCrVZ
+lLTFqIG92p4jdaczmqfrSqlcq7BoGrLAeZ2KcLUnm7XvubVpW7RVMLVsCqxk+6NBe7ZDW7cqULUu
+y7Yz2ZRe+wRwKwwo67Q3C7jlWjeEq6HNIl4mq7hy66Z067gWe7gwpYOSiZWPWrnBsLhaS7CaG7ic
+e5J4manMCQiJO7qXW1dPe7pfygR4O7l98LoFEbuqNbu0W7tJcLutC3Wiu7sC662Z+7swG7yRq5w1
+tXV7y6THi6/Jq7zLawTCi3vwWLy/QLpza7rWS7U6m73e8ZHce5e8O3CNG76bOwTk/otdJRu9kTq9
+HFu97Iu0M9O8bfkEgvsq54ua9Guz9nu/+Auv+tuRUtC/SqC73Zu+Lbm+BIy6PfC+h6Sk/8sXiWmo
+EQy/OkDBdMQGDIy+Acy4A7zBwHOeHowbahDCANy3A4u2JnybN5DCSqDAQcDCGGyZGhzDTlUDNNwa
+qQuB18iX2Yi84MvDbisDP5wsQSyOV0rEWYrEFQwDSzwWTVyYlEmoGTyhJCnFCOguB1yd3HDFpXqY
+WqzDXIygXly+nhiZWNwFNmwDOOy9mHvEa0yWOfiJn/sFcTwDc+zAT3nHQAyFnvvG90DGzkuIBWq2
+L/y3gqy9cwiIXZiPfIzIYryP/mUrkml8qI8snl/LiLpIrmrQx0IsplBMpp38F+NRxUhBBX88wqUL
+w6nMxq8Uxkv5BqS8x4MqlJrspF08y897j7zqeWuQy6ybxbxcqJsMzFEQm6xcyU7wyi5sxLLMzFkV
+UbacQnZgzG2ryHjay0L7y9b8wT61umXsJ6krzYxMzY48zlNMkOYcq9t8uOoMzn4rzu6swpnHlgi8
+B9x8y5jMt+tMvXaczz2MiPx8yf4cs/WszL6sxgatyjiZ0ADdB//MqAEtvdNM0NUc0eSMhmHbJu/a
+0Fv80Jzs0T8wPT1B0do8CNxM0mhs0ih9BTMCPiwNnoWQyzAtmjs801RQJPBx/tMzZSdcutNFzNHt
+7NNHwCgtPMm6zAvcadRRrNSQ+2lf0ZnHnNPGKdWoTNVSMDGoidXnTNQ0wNWu6dVfDU69INbyvAgX
+a9bEidZOgDioGdKOwKxw7aFybbvHFY2tmAiJmtcruNdNgJyl7NbVJdh+Sdh8Pcw4yiwGMAGRbQCU
+jQGRnQKXvQWPfcF0LLsQzNg+XIIgiiyVLQGUfdmZTQGpbQKr3cpPbcqhedT1W9CgjbDhqKBsktmT
+XdoHkNqtXdqnLdm7fdqVTdy7PcaGPMSxPdW1zbzD/GnHPNmm3duSXd0XIN3TTd3ajdoVwN1iIJ+K
+PZrNjQQS9Z1wIt3GPd28/m0B2L3d2e3dxJ3dY2DenA3IcTnezg3SUdvNwu3b1d3aqt3b8P3e6m3d
+AH7IIpvR87vRs93R+D3D48qbfbLaup3e7G3avD3g1G3c7W0GEl7fsPy9Dv7gof3c7prIolCa4d3T
+JO6+kQuYssPhgL0WK77MLU4ED7mWQ40KOg6oCt6pIV7HI37jg2vi50Q+SVoGxIjR3pzJDh3OEE3k
+tm3kR94RSa7k0VjjMi3l+Uvl5fqMV04GFaTlUH7SXL6FklyH/hrmZ+ALZH7PUX7mJa7fa2Iidn7n
+eJ7ner7nJgLiDC7AtC3neezG9wuXG2jmgr6KXh7Bhv5DiT4D1qqvja6d/o/+h0K9spPuu5UujXTO
+w5n+2ZsOjotOwJ9ewqGOi2ArxaUe6Keu6J0ew6s+5K3u6sZIjdYb60k962h+6R6L6/is64uY5myt
+vL4e58Ae7LwuscWO6Me+XclesMve7EqczUQb7dJOxdSOs9Z+7S4Q6e267dzexk5N6m3q2aYe7uVc
+yIVe7r0L6ugek/FM7OyuvudurAUgAfd+AAWw7z+Q7yfg79806utuk3F9uvyu7/qe7wCvAwtPAg3/
+UdmO6fP+wPVuJf5+7/uu8BXw8BmP8QrP7x0/AR0/8gl/8CKf8fhu8hpf8h4P8iHfuXpM7gAw8wBQ
+8zZ/8zif8zrf2e1e/vEWj/AIv/L4fgEXD/QXX/RFL/JAv/RLr/JDb/Qpr/QmD/ECz746f/VYj/U8
+T++sjigYz/Jfn/AYsPBC7/Rkj/JJ//Ri//Qr//FKz/JU/+omnPV0X/dbT/FdXyco//ZCbwEHH/Z/
+//drb/Z9H/htz/Ypr/Fp7+zx/rt1//hXf/eB7LhkP/Qk7/eCn/hwr/kjf/lBv/d7v/mKj/ahn+4x
+P/CQn/o5zNM2jtIPnwGvvwPeDq6qX/uSf99I3PkeEPtE7+JVH761r/q3f+g+zft+7/tyv8HBn/rD
+7+jvLurJz+jL//jNT+nPb/qEbvXTb/f2fegP8v3gH/7iP/7kX/7m/n/+6D/707r93K8bnPH+8B//
+8j//9F//9n//+E//oez47J/1SmHJEHDkpNVenPXm3X8wFEeyNM8RCFa2BVA4lme6tm8g13e+9/lW
+UDgkFgOvW1K5ZDadT6hSVURGrVdsdvnjdntGcHhY1ZbNZ3Ra3ZkSyWt4XF7z1rtivNi+5/f9f8BA
+wUHCQsNDxETFHaO3uUfISDa7vErLS8xMzU3OTr1Az1DRUdJS0yBHSdXVyL3TV9hY2dmjRdtb3NxB
+2iNW3985XeFh4mLjY+Rk5WUeYOdn6Gjpaepq62vsbO1t7m7vb/Bw8XHycvNz9HT1dfZ293f4ePl5
++nr7e/x8/X3+G37/f4ABBQ4kWNDgQYQJFS5k2NDhQ4gRJdKLAAA7
similarity index 79%
rename from Documentation/DocBook/dvb/audio.xml
rename to Documentation/DocBook/media/dvb/audio.xml
index eeb96b8..d643862 100644 (file)
@@ -14,17 +14,17 @@ the omission of the audio and video device.
 audio device.
 </para>
 
-<section id="audio_stream_source_t">
+<section id="audio-stream-source-t">
 <title>audio_stream_source_t</title>
 <para>The audio stream source is set through the AUDIO_SELECT_SOURCE call and can take
 the following values, depending on whether we are replaying from an internal (demux) or
 external (user write) source.
 </para>
 <programlisting>
- typedef enum {
-        AUDIO_SOURCE_DEMUX,
-        AUDIO_SOURCE_MEMORY
- } audio_stream_source_t;
+typedef enum {
+       AUDIO_SOURCE_DEMUX,
+       AUDIO_SOURCE_MEMORY
+} audio_stream_source_t;
 </programlisting>
 <para>AUDIO_SOURCE_DEMUX selects the demultiplexer (fed either by the frontend or the
 DVR device) as the source of the video stream. If AUDIO_SOURCE_MEMORY
@@ -33,61 +33,64 @@ call.
 </para>
 
 </section>
-<section id="audio_play_state_t">
+<section id="audio-play-state-t">
 <title>audio_play_state_t</title>
 <para>The following values can be returned by the AUDIO_GET_STATUS call representing the
 state of audio playback.
 </para>
 <programlisting>
- typedef enum {
-        AUDIO_STOPPED,
-        AUDIO_PLAYING,
-        AUDIO_PAUSED
- } audio_play_state_t;
+typedef enum {
+       AUDIO_STOPPED,
+       AUDIO_PLAYING,
+       AUDIO_PAUSED
+} audio_play_state_t;
 </programlisting>
 
 </section>
-<section id="audio_channel_select_t">
+<section id="audio-channel-select-t">
 <title>audio_channel_select_t</title>
 <para>The audio channel selected via AUDIO_CHANNEL_SELECT is determined by the
 following values.
 </para>
 <programlisting>
- typedef enum {
-        AUDIO_STEREO,
-        AUDIO_MONO_LEFT,
-        AUDIO_MONO_RIGHT,
- } audio_channel_select_t;
+typedef enum {
+       AUDIO_STEREO,
+       AUDIO_MONO_LEFT,
+       AUDIO_MONO_RIGHT,
+       AUDIO_MONO,
+       AUDIO_STEREO_SWAPPED
+} audio_channel_select_t;
 </programlisting>
 
 </section>
-<section id="struct_audio_status">
+<section id="audio-status">
 <title>struct audio_status</title>
 <para>The AUDIO_GET_STATUS call returns the following structure informing about various
 states of the playback operation.
 </para>
 <programlisting>
- typedef struct audio_status {
-        boolean AV_sync_state;
-        boolean mute_state;
-        audio_play_state_t play_state;
-        audio_stream_source_t stream_source;
-        audio_channel_select_t channel_select;
-        boolean bypass_mode;
- } audio_status_t;
+typedef struct audio_status {
+       boolean AV_sync_state;
+       boolean mute_state;
+       audio_play_state_t play_state;
+       audio_stream_source_t stream_source;
+       audio_channel_select_t channel_select;
+       boolean bypass_mode;
+       audio_mixer_t mixer_state;
+} audio_status_t;
 </programlisting>
 
 </section>
-<section id="struct_audio_mixer">
+<section id="audio-mixer">
 <title>struct audio_mixer</title>
 <para>The following structure is used by the AUDIO_SET_MIXER call to set the audio
 volume.
 </para>
 <programlisting>
- typedef struct audio_mixer {
-        unsigned int volume_left;
-        unsigned int volume_right;
- } audio_mixer_t;
+typedef struct audio_mixer {
+       unsigned int volume_left;
+       unsigned int volume_right;
+} audio_mixer_t;
 </programlisting>
 
 </section>
@@ -109,17 +112,17 @@ bits set according to the hardwares capabilities.
 </programlisting>
 
 </section>
-<section id="struct_audio_karaoke">
+<section id="audio-karaoke">
 <title>struct audio_karaoke</title>
 <para>The ioctl AUDIO_SET_KARAOKE uses the following format:
 </para>
 <programlisting>
- typedef
- struct audio_karaoke{
-        int vocal1;
-        int vocal2;
-        int melody;
- } audio_karaoke_t;
+typedef
+struct audio_karaoke {
+       int vocal1;
+       int vocal2;
+       int melody;
+} audio_karaoke_t;
 </programlisting>
 <para>If Vocal1 or Vocal2 are non-zero, they get mixed into left and right t at 70% each. If both,
 Vocal1 and Vocal2 are non-zero, Vocal1 gets mixed into the left channel and Vocal2 into the
@@ -128,7 +131,7 @@ and right.
 </para>
 
 </section>
-<section id="audio_attributes">
+<section id="audio-attributes-t">
 <title>audio attributes</title>
 <para>The following attributes can be set by a call to AUDIO_SET_ATTRIBUTES:
 </para>
@@ -217,21 +220,13 @@ and right.
 <para>(blocking mode is the default)</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>ENODEV</para>
 </entry><entry
  align="char">
 <para>Device driver not loaded/available.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
 </entry>
  </row><row><entry
  align="char">
@@ -276,8 +271,7 @@ and right.
 <para>File descriptor returned by a previous call to open().</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>EBADF</para>
@@ -332,8 +326,7 @@ and right.
 <para>Size of buf.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>EPERM</para>
@@ -358,7 +351,7 @@ and right.
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="AUDIO_STOP"
 role="subsection"><title>AUDIO_STOP</title>
 <para>DESCRIPTION
 </para>
@@ -391,25 +384,9 @@ role="subsection"><title>AUDIO_STOP</title>
 <para>Equals AUDIO_STOP for this command.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_PLAY"
 role="subsection"><title>AUDIO_PLAY</title>
 <para>DESCRIPTION
 </para>
@@ -443,25 +420,9 @@ role="subsection"><title>AUDIO_PLAY</title>
 <para>Equals AUDIO_PLAY for this command.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_PAUSE"
 role="subsection"><title>AUDIO_PAUSE</title>
 <para>DESCRIPTION
 </para>
@@ -503,25 +464,49 @@ role="subsection"><title>AUDIO_PAUSE</title>
 <para>Equals AUDIO_PAUSE for this command.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
+&return-value-dvb;
+
+</section><section id="AUDIO_CONTINUE"
+role="subsection"><title>AUDIO_CONTINUE</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl restarts the decoding and playing process previously paused
+with AUDIO_PAUSE command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>It only works if the stream were previously stopped with AUDIO_PAUSE</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request = AUDIO_CONTINUE);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
 </para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
+<para>int fd</para>
 </entry><entry
  align="char">
-<para>fd is not a valid open file descriptor.</para>
+<para>File descriptor returned by a previous call to open().</para>
 </entry>
  </row><row><entry
  align="char">
-<para>EINTERNAL</para>
+<para>int request</para>
 </entry><entry
  align="char">
-<para>Internal error.</para>
+<para>Equals AUDIO_CONTINUE for this command.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_SELECT_SOURCE"
 role="subsection"><title>AUDIO_SELECT_SOURCE</title>
 <para>DESCRIPTION
 </para>
@@ -567,32 +552,9 @@ role="subsection"><title>AUDIO_SELECT_SOURCE</title>
  stream.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Illegal input parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_SET_MUTE"
 role="subsection"><title>AUDIO_SET_MUTE</title>
 <para>DESCRIPTION
 </para>
@@ -646,32 +608,9 @@ role="subsection"><title>AUDIO_SET_MUTE</title>
 <para>FALSE Audio Un-mute</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Illegal input parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_SET_AV_SYNC"
 role="subsection"><title>AUDIO_SET_AV_SYNC</title>
 <para>DESCRIPTION
 </para>
@@ -725,32 +664,9 @@ role="subsection"><title>AUDIO_SET_AV_SYNC</title>
 <para>FALSE AV-sync OFF</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Illegal input parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_SET_BYPASS_MODE"
 role="subsection"><title>AUDIO_SET_BYPASS_MODE</title>
 <para>DESCRIPTION
 </para>
@@ -808,32 +724,9 @@ role="subsection"><title>AUDIO_SET_BYPASS_MODE</title>
 <para>FALSE Bypass is enabled</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Illegal input parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_CHANNEL_SELECT"
 role="subsection"><title>AUDIO_CHANNEL_SELECT</title>
 <para>DESCRIPTION
 </para>
@@ -877,32 +770,9 @@ role="subsection"><title>AUDIO_CHANNEL_SELECT</title>
  stereo).</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Illegal input parameter ch.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_GET_STATUS"
 role="subsection"><title>AUDIO_GET_STATUS</title>
 <para>DESCRIPTION
 </para>
@@ -945,32 +815,9 @@ role="subsection"><title>AUDIO_GET_STATUS</title>
 <para>Returns the current state of Audio Device.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>status points to invalid address.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_GET_CAPABILITIES"
 role="subsection"><title>AUDIO_GET_CAPABILITIES</title>
 <para>DESCRIPTION
 </para>
@@ -1013,32 +860,9 @@ role="subsection"><title>AUDIO_GET_CAPABILITIES</title>
 <para>Returns a bit array of supported sound formats.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>cap points to an invalid address.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_CLEAR_BUFFER"
 role="subsection"><title>AUDIO_CLEAR_BUFFER</title>
 <para>DESCRIPTION
 </para>
@@ -1072,25 +896,9 @@ role="subsection"><title>AUDIO_CLEAR_BUFFER</title>
 <para>Equals AUDIO_CLEAR_BUFFER for this command.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_SET_ID"
 role="subsection"><title>AUDIO_SET_ID</title>
 <para>DESCRIPTION
 </para>
@@ -1136,32 +944,9 @@ role="subsection"><title>AUDIO_SET_ID</title>
 <para>audio sub-stream id</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Invalid sub-stream id.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_SET_MIXER"
 role="subsection"><title>AUDIO_SET_MIXER</title>
 <para>DESCRIPTION
 </para>
@@ -1202,32 +987,9 @@ role="subsection"><title>AUDIO_SET_MIXER</title>
 <para>mixer settings.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>mix points to an invalid address.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="AUDIO_SET_STREAMTYPE"
 role="subsection"><title>AUDIO_SET_STREAMTYPE</title>
 <para>DESCRIPTION
 </para>
@@ -1270,17 +1032,9 @@ role="subsection"><title>AUDIO_SET_STREAMTYPE</title>
 <para>stream type</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
@@ -1288,7 +1042,7 @@ role="subsection"><title>AUDIO_SET_STREAMTYPE</title>
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="AUDIO_SET_EXT_ID"
 role="subsection"><title>AUDIO_SET_EXT_ID</title>
 <para>DESCRIPTION
 </para>
@@ -1330,17 +1084,9 @@ role="subsection"><title>AUDIO_SET_EXT_ID</title>
 <para>audio sub_stream_id</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
@@ -1348,7 +1094,7 @@ role="subsection"><title>AUDIO_SET_EXT_ID</title>
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="AUDIO_SET_ATTRIBUTES"
 role="subsection"><title>AUDIO_SET_ATTRIBUTES</title>
 <para>DESCRIPTION
 </para>
@@ -1391,17 +1137,9 @@ role="subsection"><title>AUDIO_SET_ATTRIBUTES</title>
 <para>audio attributes according to section ??</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
@@ -1409,7 +1147,7 @@ role="subsection"><title>AUDIO_SET_ATTRIBUTES</title>
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="AUDIO_SET_KARAOKE"
 role="subsection"><title>AUDIO_SET_KARAOKE</title>
 <para>DESCRIPTION
 </para>
@@ -1422,7 +1160,7 @@ role="subsection"><title>AUDIO_SET_KARAOKE</title>
 </para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
-<para>int ioctl(fd, int request = AUDIO_SET_STREAMTYPE,
+<para>int ioctl(fd, int request = AUDIO_SET_KARAOKE,
  audio_karaoke_t &#x22C6;karaoke);</para>
 </entry>
  </row></tbody></tgroup></informaltable>
@@ -1440,7 +1178,7 @@ role="subsection"><title>AUDIO_SET_KARAOKE</title>
 <para>int request</para>
 </entry><entry
  align="char">
-<para>Equals AUDIO_SET_STREAMTYPE for this
+<para>Equals AUDIO_SET_KARAOKE for this
  command.</para>
 </entry>
  </row><row><entry
@@ -1452,17 +1190,9 @@ role="subsection"><title>AUDIO_SET_KARAOKE</title>
 <para>karaoke settings according to section ??.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
similarity index 67%
rename from Documentation/DocBook/dvb/ca.xml
rename to Documentation/DocBook/media/dvb/ca.xml
index b1f1d2f..5c4adb4 100644 (file)
@@ -8,75 +8,85 @@ including <emphasis role="tt">linux/dvb/ca.h</emphasis> in your application.
 <title>CA Data Types</title>
 
 
-<section id="ca_slot_info_t">
+<section id="ca-slot-info">
 <title>ca_slot_info_t</title>
  <programlisting>
- /&#x22C6; slot interface types and info &#x22C6;/
+typedef struct ca_slot_info {
+       int num;               /&#x22C6; slot number &#x22C6;/
 
- typedef struct ca_slot_info_s {
-        int num;               /&#x22C6; slot number &#x22C6;/
+       int type;              /&#x22C6; CA interface this slot supports &#x22C6;/
+#define CA_CI            1     /&#x22C6; CI high level interface &#x22C6;/
+#define CA_CI_LINK       2     /&#x22C6; CI link layer level interface &#x22C6;/
+#define CA_CI_PHYS       4     /&#x22C6; CI physical layer level interface &#x22C6;/
+#define CA_DESCR         8     /&#x22C6; built-in descrambler &#x22C6;/
+#define CA_SC          128     /&#x22C6; simple smart card interface &#x22C6;/
 
-        int type;           /&#x22C6; CA interface this slot supports &#x22C6;/
- #define CA_CI            1  /&#x22C6; CI high level interface &#x22C6;/
- #define CA_CI_LINK       2  /&#x22C6; CI link layer level interface &#x22C6;/
- #define CA_CI_PHYS       4  /&#x22C6; CI physical layer level interface &#x22C6;/
- #define CA_SC          128  /&#x22C6; simple smart card interface &#x22C6;/
-
-        unsigned int flags;
- #define CA_CI_MODULE_PRESENT 1 /&#x22C6; module (or card) inserted &#x22C6;/
- #define CA_CI_MODULE_READY   2
- } ca_slot_info_t;
+       unsigned int flags;
+#define CA_CI_MODULE_PRESENT 1 /&#x22C6; module (or card) inserted &#x22C6;/
+#define CA_CI_MODULE_READY   2
+} ca_slot_info_t;
 </programlisting>
 
 </section>
-<section id="ca_descr_info_t">
+<section id="ca-descr-info">
 <title>ca_descr_info_t</title>
- <programlisting>
- typedef struct ca_descr_info_s {
-        unsigned int num;  /&#x22C6; number of available descramblers (keys) &#x22C6;/
-        unsigned int type; /&#x22C6; type of supported scrambling system &#x22C6;/
- #define CA_ECD           1
- #define CA_NDS           2
- #define CA_DSS           4
- } ca_descr_info_t;
+<programlisting>
+typedef struct ca_descr_info {
+       unsigned int num;  /&#x22C6; number of available descramblers (keys) &#x22C6;/
+       unsigned int type; /&#x22C6; type of supported scrambling system &#x22C6;/
+#define CA_ECD           1
+#define CA_NDS           2
+#define CA_DSS           4
+} ca_descr_info_t;
 </programlisting>
 
 </section>
-<section id="ca_cap_t">
-<title>ca_cap_t</title>
- <programlisting>
- typedef struct ca_cap_s {
-        unsigned int slot_num;  /&#x22C6; total number of CA card and module slots &#x22C6;/
-        unsigned int slot_type; /&#x22C6; OR of all supported types &#x22C6;/
-        unsigned int descr_num; /&#x22C6; total number of descrambler slots (keys) &#x22C6;/
-        unsigned int descr_type;/&#x22C6; OR of all supported types &#x22C6;/
+<section id="ca-caps">
+<title>ca_caps_t</title>
+<programlisting>
+typedef struct ca_caps {
+       unsigned int slot_num;  /&#x22C6; total number of CA card and module slots &#x22C6;/
+       unsigned int slot_type; /&#x22C6; OR of all supported types &#x22C6;/
+       unsigned int descr_num; /&#x22C6; total number of descrambler slots (keys) &#x22C6;/
+       unsigned int descr_type;/&#x22C6; OR of all supported types &#x22C6;/
  } ca_cap_t;
 </programlisting>
 
 </section>
-<section id="ca_msg_t">
+<section id="ca-msg">
 <title>ca_msg_t</title>
- <programlisting>
- /&#x22C6; a message to/from a CI-CAM &#x22C6;/
- typedef struct ca_msg_s {
-        unsigned int index;
-        unsigned int type;
-        unsigned int length;
-        unsigned char msg[256];
- } ca_msg_t;
+<programlisting>
+/&#x22C6; a message to/from a CI-CAM &#x22C6;/
+typedef struct ca_msg {
+       unsigned int index;
+       unsigned int type;
+       unsigned int length;
+       unsigned char msg[256];
+} ca_msg_t;
 </programlisting>
 
 </section>
-<section id="ca_descr_t">
+<section id="ca-descr">
 <title>ca_descr_t</title>
- <programlisting>
- typedef struct ca_descr_s {
-        unsigned int index;
-        unsigned int parity;
-        unsigned char cw[8];
- } ca_descr_t;
+<programlisting>
+typedef struct ca_descr {
+       unsigned int index;
+       unsigned int parity;
+       unsigned char cw[8];
+} ca_descr_t;
 </programlisting>
- </section></section>
+</section>
+
+<section id="ca-pid">
+<title>ca-pid</title>
+<programlisting>
+typedef struct ca_pid {
+       unsigned int pid;
+       int index;              /&#x22C6; -1 == disable&#x22C6;/
+} ca_pid_t;
+</programlisting>
+</section></section>
+
 <section id="ca_function_calls">
 <title>CA Function Calls</title>
 
@@ -148,8 +158,7 @@ including <emphasis role="tt">linux/dvb/ca.h</emphasis> in your application.
 <para>(blocking mode is the default)</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>ENODEV</para>
@@ -207,8 +216,7 @@ including <emphasis role="tt">linux/dvb/ca.h</emphasis> in your application.
 <para>File descriptor returned by a previous call to open().</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>EBADF</para>
similarity index 84%
rename from Documentation/DocBook/dvb/demux.xml
rename to Documentation/DocBook/media/dvb/demux.xml
index 1b8c4e9..37c1790 100644 (file)
@@ -7,15 +7,19 @@ accessed by including <emphasis role="tt">linux/dvb/dmx.h</emphasis> in your app
 <section id="dmx_types">
 <title>Demux Data Types</title>
 
-<section id="dmx_output_t">
+<section id="dmx-output-t">
 <title>dmx_output_t</title>
- <programlisting>
- typedef enum
- {
-        DMX_OUT_DECODER,
-        DMX_OUT_TAP,
-        DMX_OUT_TS_TAP
- } dmx_output_t;
+<programlisting>
+typedef enum
+{
+       DMX_OUT_DECODER, /&#x22C6; Streaming directly to decoder. &#x22C6;/
+       DMX_OUT_TAP,     /&#x22C6; Output going to a memory buffer &#x22C6;/
+                        /&#x22C6; (to be retrieved via the read command).&#x22C6;/
+       DMX_OUT_TS_TAP,  /&#x22C6; Output multiplexed into a new TS  &#x22C6;/
+                        /&#x22C6; (to be retrieved by reading from the &#x22C6;/
+                        /&#x22C6; logical DVR device).                 &#x22C6;/
+       DMX_OUT_TSDEMUX_TAP /&#x22C6; Like TS_TAP but retrieved from the DMX device &#x22C6;/
+} dmx_output_t;
 </programlisting>
 <para><emphasis role="tt">DMX_OUT_TAP</emphasis> delivers the stream output to the demux device on which the ioctl is
 called.
@@ -26,96 +30,95 @@ specified.
 </para>
 </section>
 
-<section id="dmx_input_t">
+<section id="dmx-input-t">
 <title>dmx_input_t</title>
- <programlisting>
- typedef enum
- {
-        DMX_IN_FRONTEND,
-        DMX_IN_DVR
- } dmx_input_t;
+<programlisting>
+typedef enum
+{
+       DMX_IN_FRONTEND, /&#x22C6; Input from a front-end device.  &#x22C6;/
+       DMX_IN_DVR       /&#x22C6; Input from the logical DVR device.  &#x22C6;/
+} dmx_input_t;
 </programlisting>
 </section>
 
-<section id="dmx_pes_type_t">
+<section id="dmx-pes-type-t">
 <title>dmx_pes_type_t</title>
- <programlisting>
- typedef enum
- {
-        DMX_PES_AUDIO,
-        DMX_PES_VIDEO,
-        DMX_PES_TELETEXT,
-        DMX_PES_SUBTITLE,
-        DMX_PES_PCR,
-        DMX_PES_OTHER
- } dmx_pes_type_t;
-</programlisting>
-</section>
+<programlisting>
+typedef enum
+{
+       DMX_PES_AUDIO0,
+       DMX_PES_VIDEO0,
+       DMX_PES_TELETEXT0,
+       DMX_PES_SUBTITLE0,
+       DMX_PES_PCR0,
 
-<section id="dmx_event_t">
-<title>dmx_event_t</title>
- <programlisting>
- typedef enum
- {
-        DMX_SCRAMBLING_EV,
-        DMX_FRONTEND_EV
- } dmx_event_t;
-</programlisting>
-</section>
+       DMX_PES_AUDIO1,
+       DMX_PES_VIDEO1,
+       DMX_PES_TELETEXT1,
+       DMX_PES_SUBTITLE1,
+       DMX_PES_PCR1,
 
-<section id="dmx_scrambling_status_t">
-<title>dmx_scrambling_status_t</title>
- <programlisting>
- typedef enum
- {
-        DMX_SCRAMBLING_OFF,
-        DMX_SCRAMBLING_ON
- } dmx_scrambling_status_t;
+       DMX_PES_AUDIO2,
+       DMX_PES_VIDEO2,
+       DMX_PES_TELETEXT2,
+       DMX_PES_SUBTITLE2,
+       DMX_PES_PCR2,
+
+       DMX_PES_AUDIO3,
+       DMX_PES_VIDEO3,
+       DMX_PES_TELETEXT3,
+       DMX_PES_SUBTITLE3,
+       DMX_PES_PCR3,
+
+       DMX_PES_OTHER
+} dmx_pes_type_t;
 </programlisting>
 </section>
 
-<section id="dmx_filter">
+<section id="dmx-filter">
 <title>struct dmx_filter</title>
  <programlisting>
  typedef struct dmx_filter
- {
-        uint8_t         filter[DMX_FILTER_SIZE];
-        uint8_t         mask[DMX_FILTER_SIZE];
- } dmx_filter_t;
+{
+       __u8  filter[DMX_FILTER_SIZE];
+       __u8  mask[DMX_FILTER_SIZE];
+       __u8  mode[DMX_FILTER_SIZE];
+} dmx_filter_t;
 </programlisting>
 </section>
 
-<section id="dmx_sct_filter_params">
+<section id="dmx-sct-filter-params">
 <title>struct dmx_sct_filter_params</title>
- <programlisting>
- struct dmx_sct_filter_params
- {
-        uint16_t            pid;
-        dmx_filter_t        filter;
-        uint32_t            timeout;
-        uint32_t            flags;
- #define DMX_CHECK_CRC       1
- #define DMX_ONESHOT         2
- #define DMX_IMMEDIATE_START 4
- };
+<programlisting>
+struct dmx_sct_filter_params
+{
+       __u16          pid;
+       dmx_filter_t   filter;
+       __u32          timeout;
+       __u32          flags;
+#define DMX_CHECK_CRC       1
+#define DMX_ONESHOT         2
+#define DMX_IMMEDIATE_START 4
+#define DMX_KERNEL_CLIENT   0x8000
+};
 </programlisting>
 </section>
 
-<section id="dmx_pes_filter_params">
+<section id="dmx-pes-filter-params">
 <title>struct dmx_pes_filter_params</title>
- <programlisting>
- struct dmx_pes_filter_params
- {
-        uint16_t            pid;
-        dmx_input_t         input;
-        dmx_output_t        output;
-        dmx_pes_type_t      pes_type;
-        uint32_t            flags;
- };
+<programlisting>
+struct dmx_pes_filter_params
+{
+       __u16          pid;
+       dmx_input_t    input;
+       dmx_output_t   output;
+       dmx_pes_type_t pes_type;
+       __u32          flags;
+};
 </programlisting>
 </section>
 
-<section id="dmx_event">
+<section id="dmx-event">
 <title>struct dmx_event</title>
  <programlisting>
  struct dmx_event
@@ -130,19 +133,44 @@ specified.
 </programlisting>
 </section>
 
-<section id="dmx_stc">
+<section id="dmx-stc">
 <title>struct dmx_stc</title>
- <programlisting>
- struct dmx_stc {
-        unsigned int num;       /&#x22C6; input : which STC? 0..N &#x22C6;/
-        unsigned int base;      /&#x22C6; output: divisor for stc to get 90 kHz clock &#x22C6;/
-        uint64_t stc;           /&#x22C6; output: stc in 'base'&#x22C6;90 kHz units &#x22C6;/
- };
+<programlisting>
+struct dmx_stc {
+       unsigned int num;       /&#x22C6; input : which STC? 0..N &#x22C6;/
+       unsigned int base;      /&#x22C6; output: divisor for stc to get 90 kHz clock &#x22C6;/
+       __u64 stc;              /&#x22C6; output: stc in 'base'&#x22C6;90 kHz units &#x22C6;/
+};
 </programlisting>
- </section>
+</section>
 
+<section id="dmx-caps">
+<title>struct dmx_caps</title>
+<programlisting>
+ typedef struct dmx_caps {
+       __u32 caps;
+       int num_decoders;
+} dmx_caps_t;
+</programlisting>
+</section>
+
+<section id="dmx-source-t">
+<title>enum dmx_source_t</title>
+<programlisting>
+typedef enum {
+       DMX_SOURCE_FRONT0 = 0,
+       DMX_SOURCE_FRONT1,
+       DMX_SOURCE_FRONT2,
+       DMX_SOURCE_FRONT3,
+       DMX_SOURCE_DVR0   = 16,
+       DMX_SOURCE_DVR1,
+       DMX_SOURCE_DVR2,
+       DMX_SOURCE_DVR3
+} dmx_source_t;
+</programlisting>
 </section>
 
+</section>
 <section id="dmx_fcalls">
 <title>Demux Function Calls</title>
 
@@ -211,8 +239,7 @@ specified.
 <para>(blocking mode is the default)</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>ENODEV</para>
@@ -271,8 +298,7 @@ specified.
 <para>File descriptor returned by a previous call to open().</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>EBADF</para>
@@ -353,8 +379,7 @@ specified.
 <para>Size of buf.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>EWOULDBLOCK</para>
@@ -457,8 +482,7 @@ specified.
 <para>Size of buf.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>EWOULDBLOCK</para>
@@ -491,7 +515,7 @@ specified.
  </row></tbody></tgroup></informaltable>
 </section>
 
-<section id="dmx_start">
+<section id="DMX_START">
 <title>DMX_START</title>
 <para>DESCRIPTION
 </para>
@@ -525,17 +549,9 @@ specified.
 <para>Equals DMX_START for this command.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
@@ -556,7 +572,7 @@ specified.
  </row></tbody></tgroup></informaltable>
 </section>
 
-<section id="dmx_stop">
+<section id="DMX_STOP">
 <title>DMX_STOP</title>
 <para>DESCRIPTION
 </para>
@@ -591,19 +607,10 @@ specified.
 <para>Equals DMX_STOP for this command.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid file descriptor.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
-<section id="dmx_set_filter">
+<section id="DMX_SET_FILTER">
 <title>DMX_SET_FILTER</title>
 <para>DESCRIPTION
 </para>
@@ -654,26 +661,10 @@ specified.
 <para>Pointer to structure containing filter parameters.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Invalid argument.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
-<section id="dmx_set_pes_filter">
+<section id="DMX_SET_PES_FILTER">
 <title>DMX_SET_PES_FILTER</title>
 <para>DESCRIPTION
 </para>
@@ -727,24 +718,9 @@ specified.
 <para>Pointer to structure containing filter parameters.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Invalid argument.</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EBUSY</para>
 </entry><entry
  align="char">
@@ -756,7 +732,7 @@ specified.
  </row></tbody></tgroup></informaltable>
 </section>
 
-<section id="dms_set_buffer_size">
+<section id="DMX_SET_BUFFER_SIZE">
 <title>DMX_SET_BUFFER_SIZE</title>
 <para>DESCRIPTION
 </para>
@@ -799,27 +775,10 @@ specified.
 <para>Size of circular buffer.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ENOMEM</para>
-</entry><entry
- align="char">
-<para>The driver was not able to allocate a buffer of the
- requested size.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
-<section id="dmx_get_event">
+<section id="DMX_GET_EVENT">
 <title>DMX_GET_EVENT</title>
 <para>DESCRIPTION
 </para>
@@ -872,24 +831,9 @@ specified.
 <para>Pointer to the location where the event is to be stored.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>ev points to an invalid address.</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EWOULDBLOCK</para>
 </entry><entry
  align="char">
@@ -899,7 +843,7 @@ specified.
  </row></tbody></tgroup></informaltable>
 </section>
 
-<section id="dmx_get_stc">
+<section id="DMX_GET_STC">
 <title>DMX_GET_STC</title>
 <para>DESCRIPTION
 </para>
@@ -946,24 +890,9 @@ specified.
 <para>Pointer to the location where the stc is to be stored.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>stc points to an invalid address.</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
similarity index 85%
rename from Documentation/DocBook/dvb/dvbapi.xml
rename to Documentation/DocBook/media/dvb/dvbapi.xml
index 9fad86c..2ab6ddc 100644 (file)
@@ -114,8 +114,28 @@ Added ISDB-T test originally written by Patrick Boettcher
     &sub-examples;
   </chapter>
 <!-- END OF CHAPTERS -->
+  <appendix id="audio_h">
+    <title>DVB Audio Header File</title>
+    &sub-audio-h;
+  </appendix>
+  <appendix id="ca_h">
+    <title>DVB Conditional Access Header File</title>
+    &sub-ca-h;
+  </appendix>
+  <appendix id="dmx_h">
+    <title>DVB Demux Header File</title>
+    &sub-dmx-h;
+  </appendix>
   <appendix id="frontend_h">
     <title>DVB Frontend Header File</title>
     &sub-frontend-h;
   </appendix>
+  <appendix id="net_h">
+    <title>DVB Network Header File</title>
+    &sub-net-h;
+  </appendix>
+  <appendix id="video_h">
+    <title>DVB Video Header File</title>
+    &sub-video-h;
+  </appendix>
 
diff --git a/Documentation/DocBook/media/dvb/dvbproperty.xml b/Documentation/DocBook/media/dvb/dvbproperty.xml
new file mode 100644 (file)
index 0000000..207e1a5
--- /dev/null
@@ -0,0 +1,859 @@
+<section id="FE_GET_SET_PROPERTY">
+<title><constant>FE_GET_PROPERTY/FE_SET_PROPERTY</constant></title>
+<para>This section describes the DVB version 5 extention of the DVB-API, also
+called "S2API", as this API were added to provide support for DVB-S2. It was
+designed to be able to replace the old frontend API. Yet, the DISEQC and
+the capability ioctls weren't implemented yet via the new way.</para>
+<para>The typical usage for the <constant>FE_GET_PROPERTY/FE_SET_PROPERTY</constant>
+API is to replace the ioctl's were the <link linkend="dvb-frontend-parameters">
+struct <constant>dvb_frontend_parameters</constant></link> were used.</para>
+<section id="dtv-property">
+<title>DTV property type</title>
+<programlisting>
+/* Reserved fields should be set to 0 */
+struct dtv_property {
+       __u32 cmd;
+       union {
+               __u32 data;
+               struct {
+                       __u8 data[32];
+                       __u32 len;
+                       __u32 reserved1[3];
+                       void *reserved2;
+               } buffer;
+       } u;
+       int result;
+} __attribute__ ((packed));
+
+/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */
+#define DTV_IOCTL_MAX_MSGS 64
+</programlisting>
+</section>
+<section id="dtv-properties">
+<title>DTV properties type</title>
+<programlisting>
+struct dtv_properties {
+       __u32 num;
+       struct dtv_property *props;
+};
+</programlisting>
+</section>
+
+<section id="FE_GET_PROPERTY">
+<title>FE_GET_PROPERTY</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call returns one or more frontend properties. This call only
+ requires read-only access to the device.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request = <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>,
+ dtv_properties &#x22C6;props);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int num</para>
+</entry><entry
+ align="char">
+<para>Equals <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link> for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct dtv_property *props</para>
+</entry><entry
+ align="char">
+<para>Points to the location where the front-end property commands are stored.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+<informaltable><tgroup cols="2"><tbody><row>
+  <entry align="char"><para>EOPNOTSUPP</para></entry>
+  <entry align="char"><para>Property type not supported.</para></entry>
+ </row></tbody></tgroup></informaltable>
+</section>
+
+<section id="FE_SET_PROPERTY">
+<title>FE_SET_PROPERTY</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call sets one or more frontend properties. This call only
+ requires read-only access to the device.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request = <link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>,
+ dtv_properties &#x22C6;props);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int num</para>
+</entry><entry
+ align="char">
+<para>Equals <link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link> for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct dtv_property *props</para>
+</entry><entry
+ align="char">
+<para>Points to the location where the front-end property commands are stored.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+<informaltable><tgroup cols="2"><tbody><row>
+  <entry align="char"><para>EOPNOTSUPP</para></entry>
+  <entry align="char"><para>Property type not supported.</para></entry>
+ </row></tbody></tgroup></informaltable>
+</section>
+
+<section>
+       <title>Property types</title>
+<para>
+On <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>/<link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>,
+the actual action is determined by the dtv_property cmd/data pairs. With one single ioctl, is possible to
+get/set up to 64 properties. The actual meaning of each property is described on the next sections.
+</para>
+
+<para>The available frontend property types are shown on the next section.</para>
+</section>
+
+<section id="fe_property_parameters">
+       <title>Digital TV property parameters</title>
+       <section id="DTV-UNDEFINED">
+       <title><constant>DTV_UNDEFINED</constant></title>
+       <para>Used internally. A GET/SET operation for it won't change or return anything.</para>
+       </section>
+       <section id="DTV-TUNE">
+       <title><constant>DTV_TUNE</constant></title>
+       <para>Interpret the cache of data, build either a traditional frontend tunerequest so we can pass validation in the <constant>FE_SET_FRONTEND</constant> ioctl.</para>
+       </section>
+       <section id="DTV-CLEAR">
+       <title><constant>DTV_CLEAR</constant></title>
+       <para>Reset a cache of data specific to the frontend here. This does not effect hardware.</para>
+       </section>
+       <section id="DTV-FREQUENCY">
+               <title><constant>DTV_FREQUENCY</constant></title>
+
+               <para>Central frequency of the channel, in HZ.</para>
+
+               <para>Notes:</para>
+               <para>1)For ISDB-T, the channels are usually transmitted with an offset of 143kHz.
+                       E.g. a valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of
+                       the channel which is 6MHz.</para>
+
+               <para>2)As in ISDB-Tsb the channel consists of only one or three segments the
+                       frequency step is 429kHz, 3*429 respectively. As for ISDB-T the
+                       central frequency of the channel is expected.</para>
+       </section>
+       <section id="DTV-MODULATION">
+       <title><constant>DTV_MODULATION</constant></title>
+<para>Specifies the frontend modulation type for cable and satellite types. The modulation can be one of the types bellow:</para>
+<programlisting>
+ typedef enum fe_modulation {
+       QPSK,
+       QAM_16,
+       QAM_32,
+       QAM_64,
+       QAM_128,
+       QAM_256,
+       QAM_AUTO,
+       VSB_8,
+       VSB_16,
+       PSK_8,
+       APSK_16,
+       APSK_32,
+       DQPSK,
+ } fe_modulation_t;
+</programlisting>
+       </section>
+       <section id="DTV-BANDWIDTH-HZ">
+               <title><constant>DTV_BANDWIDTH_HZ</constant></title>
+
+               <para>Bandwidth for the channel, in HZ.</para>
+
+               <para>Possible values:
+                       <constant>1712000</constant>,
+                       <constant>5000000</constant>,
+                       <constant>6000000</constant>,
+                       <constant>7000000</constant>,
+                       <constant>8000000</constant>,
+                       <constant>10000000</constant>.
+               </para>
+
+               <para>Notes:</para>
+
+               <para>1) For ISDB-T it should be always 6000000Hz (6MHz)</para>
+               <para>2) For ISDB-Tsb it can vary depending on the number of connected segments</para>
+               <para>3) Bandwidth doesn't apply for DVB-C transmissions, as the bandwidth
+                        for DVB-C depends on the symbol rate</para>
+               <para>4) Bandwidth in ISDB-T is fixed (6MHz) or can be easily derived from
+                       other parameters (DTV_ISDBT_SB_SEGMENT_IDX,
+                       DTV_ISDBT_SB_SEGMENT_COUNT).</para>
+               <para>5) DVB-T supports 6, 7 and 8MHz.</para>
+               <para>6) In addition, DVB-T2 supports 1.172, 5 and 10MHz.</para>
+       </section>
+       <section id="DTV-INVERSION">
+       <title><constant>DTV_INVERSION</constant></title>
+       <para>The Inversion field can take one of these values:
+       </para>
+       <programlisting>
+       typedef enum fe_spectral_inversion {
+               INVERSION_OFF,
+               INVERSION_ON,
+               INVERSION_AUTO
+       } fe_spectral_inversion_t;
+       </programlisting>
+       <para>It indicates if spectral inversion should be presumed or not. In the automatic setting
+       (<constant>INVERSION_AUTO</constant>) the hardware will try to figure out the correct setting by
+       itself.
+       </para>
+       </section>
+       <section id="DTV-DISEQC-MASTER">
+       <title><constant>DTV_DISEQC_MASTER</constant></title>
+       <para>Currently not implemented.</para>
+       </section>
+       <section id="DTV-SYMBOL-RATE">
+       <title><constant>DTV_SYMBOL_RATE</constant></title>
+       <para>Digital TV symbol rate, in bauds (symbols/second). Used on cable standards.</para>
+       </section>
+       <section id="DTV-INNER-FEC">
+       <title><constant>DTV_INNER_FEC</constant></title>
+       <para>Used cable/satellite transmissions. The acceptable values are:
+       </para>
+       <programlisting>
+typedef enum fe_code_rate {
+       FEC_NONE = 0,
+       FEC_1_2,
+       FEC_2_3,
+       FEC_3_4,
+       FEC_4_5,
+       FEC_5_6,
+       FEC_6_7,
+       FEC_7_8,
+       FEC_8_9,
+       FEC_AUTO,
+       FEC_3_5,
+       FEC_9_10,
+} fe_code_rate_t;
+       </programlisting>
+       <para>which correspond to error correction rates of 1/2, 2/3, etc.,
+       no error correction or auto detection.</para>
+       </section>
+       <section id="DTV-VOLTAGE">
+       <title><constant>DTV_VOLTAGE</constant></title>
+       <para>The voltage is usually used with non-DiSEqC capable LNBs to switch
+       the polarzation (horizontal/vertical). When using DiSEqC epuipment this
+       voltage has to be switched consistently to the DiSEqC commands as
+       described in the DiSEqC spec.</para>
+       <programlisting>
+               typedef enum fe_sec_voltage {
+               SEC_VOLTAGE_13,
+               SEC_VOLTAGE_18
+               } fe_sec_voltage_t;
+       </programlisting>
+       </section>
+       <section id="DTV-TONE">
+       <title><constant>DTV_TONE</constant></title>
+       <para>Currently not used.</para>
+       </section>
+       <section id="DTV-PILOT">
+       <title><constant>DTV_PILOT</constant></title>
+       <para>Sets DVB-S2 pilot</para>
+       <section id="fe-pilot-t">
+               <title>fe_pilot type</title>
+               <programlisting>
+typedef enum fe_pilot {
+       PILOT_ON,
+       PILOT_OFF,
+       PILOT_AUTO,
+} fe_pilot_t;
+               </programlisting>
+               </section>
+       </section>
+       <section id="DTV-ROLLOFF">
+       <title><constant>DTV_ROLLOFF</constant></title>
+               <para>Sets DVB-S2 rolloff</para>
+
+       <section id="fe-rolloff-t">
+               <title>fe_rolloff type</title>
+               <programlisting>
+typedef enum fe_rolloff {
+       ROLLOFF_35, /* Implied value in DVB-S, default for DVB-S2 */
+       ROLLOFF_20,
+       ROLLOFF_25,
+       ROLLOFF_AUTO,
+} fe_rolloff_t;
+               </programlisting>
+               </section>
+       </section>
+       <section id="DTV-DISEQC-SLAVE-REPLY">
+       <title><constant>DTV_DISEQC_SLAVE_REPLY</constant></title>
+       <para>Currently not implemented.</para>
+       </section>
+       <section id="DTV-FE-CAPABILITY-COUNT">
+       <title><constant>DTV_FE_CAPABILITY_COUNT</constant></title>
+       <para>Currently not implemented.</para>
+       </section>
+       <section id="DTV-FE-CAPABILITY">
+       <title><constant>DTV_FE_CAPABILITY</constant></title>
+       <para>Currently not implemented.</para>
+       </section>
+       <section id="DTV-DELIVERY-SYSTEM">
+               <title><constant>DTV_DELIVERY_SYSTEM</constant></title>
+               <para>Specifies the type of Delivery system</para>
+               <section id="fe-delivery-system-t">
+               <title>fe_delivery_system type</title>
+               <para>Possible values: </para>
+<programlisting>
+typedef enum fe_delivery_system {
+       SYS_UNDEFINED,
+       SYS_DVBC_ANNEX_AC,
+       SYS_DVBC_ANNEX_B,
+       SYS_DVBT,
+       SYS_DSS,
+       SYS_DVBS,
+       SYS_DVBS2,
+       SYS_DVBH,
+       SYS_ISDBT,
+       SYS_ISDBS,
+       SYS_ISDBC,
+       SYS_ATSC,
+       SYS_ATSCMH,
+       SYS_DMBTH,
+       SYS_CMMB,
+       SYS_DAB,
+       SYS_DVBT2,
+} fe_delivery_system_t;
+</programlisting>
+               </section>
+       </section>
+       <section id="DTV-ISDBT-PARTIAL-RECEPTION">
+               <title><constant>DTV_ISDBT_PARTIAL_RECEPTION</constant></title>
+
+               <para>If <constant>DTV_ISDBT_SOUND_BROADCASTING</constant> is '0' this bit-field represents whether
+                       the channel is in partial reception mode or not.</para>
+
+               <para>If '1' <constant>DTV_ISDBT_LAYERA_*</constant> values are assigned to the center segment and
+                       <constant>DTV_ISDBT_LAYERA_SEGMENT_COUNT</constant> has to be '1'.</para>
+
+               <para>If in addition <constant>DTV_ISDBT_SOUND_BROADCASTING</constant> is '1'
+                       <constant>DTV_ISDBT_PARTIAL_RECEPTION</constant> represents whether this ISDB-Tsb channel
+                       is consisting of one segment and layer or three segments and two layers.</para>
+
+               <para>Possible values: 0, 1, -1 (AUTO)</para>
+       </section>
+       <section id="DTV-ISDBT-SOUND-BROADCASTING">
+               <title><constant>DTV_ISDBT_SOUND_BROADCASTING</constant></title>
+
+               <para>This field represents whether the other DTV_ISDBT_*-parameters are
+                       referring to an ISDB-T and an ISDB-Tsb channel. (See also
+                       <constant>DTV_ISDBT_PARTIAL_RECEPTION</constant>).</para>
+
+               <para>Possible values: 0, 1, -1 (AUTO)</para>
+       </section>
+       <section id="DTV-ISDBT-SB-SUBCHANNEL-ID">
+               <title><constant>DTV_ISDBT_SB_SUBCHANNEL_ID</constant></title>
+
+               <para>This field only applies if <constant>DTV_ISDBT_SOUND_BROADCASTING</constant> is '1'.</para>
+
+               <para>(Note of the author: This might not be the correct description of the
+                       <constant>SUBCHANNEL-ID</constant> in all details, but it is my understanding of the technical
+                       background needed to program a device)</para>
+
+               <para>An ISDB-Tsb channel (1 or 3 segments) can be broadcasted alone or in a
+                       set of connected ISDB-Tsb channels. In this set of channels every
+                       channel can be received independently. The number of connected
+                       ISDB-Tsb segment can vary, e.g. depending on the frequency spectrum
+                       bandwidth available.</para>
+
+               <para>Example: Assume 8 ISDB-Tsb connected segments are broadcasted. The
+                       broadcaster has several possibilities to put those channels in the
+                       air: Assuming a normal 13-segment ISDB-T spectrum he can align the 8
+                       segments from position 1-8 to 5-13 or anything in between.</para>
+
+               <para>The underlying layer of segments are subchannels: each segment is
+                       consisting of several subchannels with a predefined IDs. A sub-channel
+                       is used to help the demodulator to synchronize on the channel.</para>
+
+               <para>An ISDB-T channel is always centered over all sub-channels. As for
+                       the example above, in ISDB-Tsb it is no longer as simple as that.</para>
+
+               <para><constant>The DTV_ISDBT_SB_SUBCHANNEL_ID</constant> parameter is used to give the
+                       sub-channel ID of the segment to be demodulated.</para>
+
+               <para>Possible values: 0 .. 41, -1 (AUTO)</para>
+       </section>
+       <section id="DTV-ISDBT-SB-SEGMENT-IDX">
+               <title><constant>DTV_ISDBT_SB_SEGMENT_IDX</constant></title>
+               <para>This field only applies if <constant>DTV_ISDBT_SOUND_BROADCASTING</constant> is '1'.</para>
+               <para><constant>DTV_ISDBT_SB_SEGMENT_IDX</constant> gives the index of the segment to be
+                       demodulated for an ISDB-Tsb channel where several of them are
+                       transmitted in the connected manner.</para>
+               <para>Possible values: 0 .. <constant>DTV_ISDBT_SB_SEGMENT_COUNT</constant> - 1</para>
+               <para>Note: This value cannot be determined by an automatic channel search.</para>
+       </section>
+       <section id="DTV-ISDBT-SB-SEGMENT-COUNT">
+               <title><constant>DTV_ISDBT_SB_SEGMENT_COUNT</constant></title>
+               <para>This field only applies if <constant>DTV_ISDBT_SOUND_BROADCASTING</constant> is '1'.</para>
+               <para><constant>DTV_ISDBT_SB_SEGMENT_COUNT</constant> gives the total count of connected ISDB-Tsb
+                       channels.</para>
+               <para>Possible values: 1 .. 13</para>
+               <para>Note: This value cannot be determined by an automatic channel search.</para>
+       </section>
+       <section id="isdb-hierq-layers">
+               <title><constant>DTV-ISDBT-LAYER*</constant> parameters</title>
+               <para>ISDB-T channels can be coded hierarchically. As opposed to DVB-T in
+                       ISDB-T hierarchical layers can be decoded simultaneously. For that
+                       reason a ISDB-T demodulator has 3 viterbi and 3 reed-solomon-decoders.</para>
+               <para>ISDB-T has 3 hierarchical layers which each can use a part of the
+                       available segments. The total number of segments over all layers has
+                       to 13 in ISDB-T.</para>
+               <para>There are 3 parameter sets, for Layers A, B and C.</para>
+               <section id="DTV-ISDBT-LAYER-ENABLED">
+                       <title><constant>DTV_ISDBT_LAYER_ENABLED</constant></title>
+                       <para>Hierarchical reception in ISDB-T is achieved by enabling or disabling
+                               layers in the decoding process. Setting all bits of
+                               <constant>DTV_ISDBT_LAYER_ENABLED</constant> to '1' forces all layers (if applicable) to be
+                               demodulated. This is the default.</para>
+                       <para>If the channel is in the partial reception mode
+                               (<constant>DTV_ISDBT_PARTIAL_RECEPTION</constant> = 1) the central segment can be decoded
+                               independently of the other 12 segments. In that mode layer A has to
+                               have a <constant>SEGMENT_COUNT</constant> of 1.</para>
+                       <para>In ISDB-Tsb only layer A is used, it can be 1 or 3 in ISDB-Tsb
+                               according to <constant>DTV_ISDBT_PARTIAL_RECEPTION</constant>. <constant>SEGMENT_COUNT</constant> must be filled
+                               accordingly.</para>
+                       <para>Possible values: 0x1, 0x2, 0x4 (|-able)</para>
+                       <para><constant>DTV_ISDBT_LAYER_ENABLED[0:0]</constant> - layer A</para>
+                       <para><constant>DTV_ISDBT_LAYER_ENABLED[1:1]</constant> - layer B</para>
+                       <para><constant>DTV_ISDBT_LAYER_ENABLED[2:2]</constant> - layer C</para>
+                       <para><constant>DTV_ISDBT_LAYER_ENABLED[31:3]</constant> unused</para>
+               </section>
+               <section id="DTV-ISDBT-LAYER-FEC">
+                       <title><constant>DTV_ISDBT_LAYER*_FEC</constant></title>
+                       <para>Possible values: <constant>FEC_AUTO</constant>, <constant>FEC_1_2</constant>, <constant>FEC_2_3</constant>, <constant>FEC_3_4</constant>, <constant>FEC_5_6</constant>, <constant>FEC_7_8</constant></para>
+               </section>
+               <section id="DTV-ISDBT-LAYER-MODULATION">
+                       <title><constant>DTV_ISDBT_LAYER*_MODULATION</constant></title>
+                       <para>Possible values: <constant>QAM_AUTO</constant>, QP<constant>SK, QAM_16</constant>, <constant>QAM_64</constant>, <constant>DQPSK</constant></para>
+                       <para>Note: If layer C is <constant>DQPSK</constant> layer B has to be <constant>DQPSK</constant>. If layer B is <constant>DQPSK</constant>
+                               and <constant>DTV_ISDBT_PARTIAL_RECEPTION</constant>=0 layer has to be <constant>DQPSK</constant>.</para>
+               </section>
+               <section id="DTV-ISDBT-LAYER-SEGMENT-COUNT">
+                       <title><constant>DTV_ISDBT_LAYER*_SEGMENT_COUNT</constant></title>
+                       <para>Possible values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -1 (AUTO)</para>
+                       <para>Note: Truth table for <constant>DTV_ISDBT_SOUND_BROADCASTING</constant> and
+                               <constant>DTV_ISDBT_PARTIAL_RECEPTION</constant> and <constant>LAYER</constant>*_SEGMENT_COUNT</para>
+                       <informaltable id="isdbt-layer_seg-cnt-table">
+                               <tgroup cols="6">
+                                       <tbody>
+                                               <row>
+                                                       <entry>PR</entry>
+                                                       <entry>SB</entry>
+                                                       <entry>Layer A width</entry>
+                                                       <entry>Layer B width</entry>
+                                                       <entry>Layer C width</entry>
+                                                       <entry>total width</entry>
+                                               </row>
+                                               <row>
+                                                       <entry>0</entry>
+                                                       <entry>0</entry>
+                                                       <entry>1 .. 13</entry>
+                                                       <entry>1 .. 13</entry>
+                                                       <entry>1 .. 13</entry>
+                                                       <entry>13</entry>
+                                               </row>
+                                               <row>
+                                                       <entry>1</entry>
+                                                       <entry>0</entry>
+                                                       <entry>1</entry>
+                                                       <entry>1 .. 13</entry>
+                                                       <entry>1 .. 13</entry>
+                                                       <entry>13</entry>
+                                               </row>
+                                               <row>
+                                                       <entry>0</entry>
+                                                       <entry>1</entry>
+                                                       <entry>1</entry>
+                                                       <entry>0</entry>
+                                                       <entry>0</entry>
+                                                       <entry>1</entry>
+                                               </row>
+                                               <row>
+                                                       <entry>1</entry>
+                                                       <entry>1</entry>
+                                                       <entry>1</entry>
+                                                       <entry>2</entry>
+                                                       <entry>0</entry>
+                                                       <entry>13</entry>
+                                               </row>
+                                       </tbody>
+                               </tgroup>
+                       </informaltable>
+               </section>
+               <section id="DTV-ISDBT-LAYER-TIME-INTERLEAVING">
+                       <title><constant>DTV_ISDBT_LAYER*_TIME_INTERLEAVING</constant></title>
+                       <para>Possible values: 0, 1, 2, 3, -1 (AUTO)</para>
+                       <para>Note: The real inter-leaver depth-names depend on the mode (fft-size); the values
+                               here are referring to what can be found in the TMCC-structure -
+                               independent of the mode.</para>
+               </section>
+       </section>
+       <section id="DTV-API-VERSION">
+       <title><constant>DTV_API_VERSION</constant></title>
+       <para>Returns the major/minor version of the DVB API</para>
+       </section>
+       <section id="DTV-CODE-RATE-HP">
+       <title><constant>DTV_CODE_RATE_HP</constant></title>
+       <para>Used on terrestrial transmissions. The acceptable values are:
+       </para>
+       <programlisting>
+typedef enum fe_code_rate {
+       FEC_NONE = 0,
+       FEC_1_2,
+       FEC_2_3,
+       FEC_3_4,
+       FEC_4_5,
+       FEC_5_6,
+       FEC_6_7,
+       FEC_7_8,
+       FEC_8_9,
+       FEC_AUTO,
+       FEC_3_5,
+       FEC_9_10,
+} fe_code_rate_t;
+       </programlisting>
+       </section>
+       <section id="DTV-CODE-RATE-LP">
+       <title><constant>DTV_CODE_RATE_LP</constant></title>
+       <para>Used on terrestrial transmissions. The acceptable values are:
+       </para>
+       <programlisting>
+typedef enum fe_code_rate {
+       FEC_NONE = 0,
+       FEC_1_2,
+       FEC_2_3,
+       FEC_3_4,
+       FEC_4_5,
+       FEC_5_6,
+       FEC_6_7,
+       FEC_7_8,
+       FEC_8_9,
+       FEC_AUTO,
+       FEC_3_5,
+       FEC_9_10,
+} fe_code_rate_t;
+       </programlisting>
+       </section>
+       <section id="DTV-GUARD-INTERVAL">
+               <title><constant>DTV_GUARD_INTERVAL</constant></title>
+
+               <para>Possible values are:</para>
+<programlisting>
+typedef enum fe_guard_interval {
+       GUARD_INTERVAL_1_32,
+       GUARD_INTERVAL_1_16,
+       GUARD_INTERVAL_1_8,
+       GUARD_INTERVAL_1_4,
+       GUARD_INTERVAL_AUTO,
+       GUARD_INTERVAL_1_128,
+       GUARD_INTERVAL_19_128,
+       GUARD_INTERVAL_19_256,
+} fe_guard_interval_t;
+</programlisting>
+
+               <para>Notes:</para>
+               <para>1) If <constant>DTV_GUARD_INTERVAL</constant> is set the <constant>GUARD_INTERVAL_AUTO</constant> the hardware will
+                       try to find the correct guard interval (if capable) and will use TMCC to fill
+                       in the missing parameters.</para>
+               <para>2) Intervals 1/128, 19/128 and 19/256 are used only for DVB-T2 at present</para>
+       </section>
+       <section id="DTV-TRANSMISSION-MODE">
+               <title><constant>DTV_TRANSMISSION_MODE</constant></title>
+
+               <para>Specifies the number of carriers used by the standard</para>
+
+               <para>Possible values are:</para>
+<programlisting>
+typedef enum fe_transmit_mode {
+       TRANSMISSION_MODE_2K,
+       TRANSMISSION_MODE_8K,
+       TRANSMISSION_MODE_AUTO,
+       TRANSMISSION_MODE_4K,
+       TRANSMISSION_MODE_1K,
+       TRANSMISSION_MODE_16K,
+       TRANSMISSION_MODE_32K,
+} fe_transmit_mode_t;
+</programlisting>
+               <para>Notes:</para>
+               <para>1) ISDB-T supports three carrier/symbol-size: 8K, 4K, 2K. It is called
+                       'mode' in the standard: Mode 1 is 2K, mode 2 is 4K, mode 3 is 8K</para>
+
+               <para>2) If <constant>DTV_TRANSMISSION_MODE</constant> is set the <constant>TRANSMISSION_MODE_AUTO</constant> the
+                       hardware will try to find the correct FFT-size (if capable) and will
+                       use TMCC to fill in the missing parameters.</para>
+               <para>3) DVB-T specifies 2K and 8K as valid sizes.</para>
+               <para>4) DVB-T2 specifies 1K, 2K, 4K, 8K, 16K and 32K.</para>
+       </section>
+       <section id="DTV-HIERARCHY">
+       <title><constant>DTV_HIERARCHY</constant></title>
+       <para>Frontend hierarchy</para>
+       <programlisting>
+typedef enum fe_hierarchy {
+        HIERARCHY_NONE,
+        HIERARCHY_1,
+        HIERARCHY_2,
+        HIERARCHY_4,
+        HIERARCHY_AUTO
+ } fe_hierarchy_t;
+       </programlisting>
+       </section>
+       <section id="DTV-ISDBS-TS-ID">
+       <title><constant>DTV_ISDBS_TS_ID</constant></title>
+       <para>Currently unused.</para>
+       </section>
+       <section id="DTV-DVBT2-PLP-ID">
+               <title><constant>DTV_DVBT2_PLP_ID</constant></title>
+               <para>DVB-T2 supports Physical Layer Pipes (PLP) to allow transmission of
+                       many data types via a single multiplex. The API will soon support this
+                       at which point this section will be expanded.</para>
+       </section>
+</section>
+       <section id="frontend-property-terrestrial-systems">
+       <title>Properties used on terrestrial delivery systems</title>
+               <section id="dvbt-params">
+                       <title>DVB-T delivery system</title>
+                       <para>The following parameters are valid for DVB-T:</para>
+                       <itemizedlist mark='opencircle'>
+                               <listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-BANDWIDTH-HZ"><constant>DTV_BANDWIDTH_HZ</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-CODE-RATE-HP"><constant>DTV_CODE_RATE_HP</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-CODE-RATE-LP"><constant>DTV_CODE_RATE_LP</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-GUARD-INTERVAL"><constant>DTV_GUARD_INTERVAL</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-TRANSMISSION-MODE"><constant>DTV_TRANSMISSION_MODE</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-HIERARCHY"><constant>DTV_HIERARCHY</constant></link></para></listitem>
+                       </itemizedlist>
+               </section>
+               <section id="dvbt2-params">
+                       <title>DVB-T2 delivery system</title>
+                       <para>DVB-T2 support is currently in the early stages
+                       of development, so expect that this section maygrow and become
+                       more detailed with time.</para>
+               <para>The following parameters are valid for DVB-T2:</para>
+               <itemizedlist mark='opencircle'>
+                       <listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-BANDWIDTH-HZ"><constant>DTV_BANDWIDTH_HZ</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-CODE-RATE-HP"><constant>DTV_CODE_RATE_HP</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-CODE-RATE-LP"><constant>DTV_CODE_RATE_LP</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-GUARD-INTERVAL"><constant>DTV_GUARD_INTERVAL</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-TRANSMISSION-MODE"><constant>DTV_TRANSMISSION_MODE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-HIERARCHY"><constant>DTV_HIERARCHY</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-DVBT2-PLP-ID"><constant>DTV_DVBT2_PLP_ID</constant></link></para></listitem>
+               </itemizedlist>
+               </section>
+               <section id="isdbt">
+               <title>ISDB-T delivery system</title>
+               <para>This ISDB-T/ISDB-Tsb API extension should reflect all information
+                       needed to tune any ISDB-T/ISDB-Tsb hardware. Of course it is possible
+                       that some very sophisticated devices won't need certain parameters to
+                       tune.</para>
+               <para>The information given here should help application writers to know how
+                       to handle ISDB-T and ISDB-Tsb hardware using the Linux DVB-API.</para>
+               <para>The details given here about ISDB-T and ISDB-Tsb are just enough to
+                       basically show the dependencies between the needed parameter values,
+                       but surely some information is left out. For more detailed information
+                       see the following documents:</para>
+               <para>ARIB STD-B31 - "Transmission System for Digital Terrestrial
+                       Television Broadcasting" and</para>
+               <para>ARIB TR-B14 - "Operational Guidelines for Digital Terrestrial
+                       Television Broadcasting".</para>
+               <para>In order to understand the ISDB specific parameters,
+                       one has to have some knowledge the channel structure in
+                       ISDB-T and ISDB-Tsb. I.e. it has to be known to
+                       the reader that an ISDB-T channel consists of 13 segments,
+                       that it can have up to 3 layer sharing those segments,
+                       and things like that.</para>
+               <para>The following parameters are valid for ISDB-T:</para>
+               <itemizedlist mark='opencircle'>
+                       <listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-BANDWIDTH-HZ"><constant>DTV_BANDWIDTH_HZ</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-CODE-RATE-HP"><constant>DTV_CODE_RATE_HP</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-CODE-RATE-LP"><constant>DTV_CODE_RATE_LP</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-GUARD-INTERVAL"><constant>DTV_GUARD_INTERVAL</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-TRANSMISSION-MODE"><constant>DTV_TRANSMISSION_MODE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-HIERARCHY"><constant>DTV_HIERARCHY</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-ENABLED"><constant>DTV_ISDBT_LAYER_ENABLED</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-PARTIAL-RECEPTION"><constant>DTV_ISDBT_PARTIAL_RECEPTION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-SOUND-BROADCASTING"><constant>DTV_ISDBT_SOUND_BROADCASTING</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-SB-SUBCHANNEL-ID"><constant>DTV_ISDBT_SB_SUBCHANNEL_ID</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-SB-SEGMENT-IDX"><constant>DTV_ISDBT_SB_SEGMENT_IDX</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-SB-SEGMENT-COUNT"><constant>DTV_ISDBT_SB_SEGMENT_COUNT</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-FEC"><constant>DTV_ISDBT_LAYERA_FEC</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-MODULATION"><constant>DTV_ISDBT_LAYERA_MODULATION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-SEGMENT-COUNT"><constant>DTV_ISDBT_LAYERA_SEGMENT_COUNT</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-TIME-INTERLEAVING"><constant>DTV_ISDBT_LAYERA_TIME_INTERLEAVING</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-FEC"><constant>DTV_ISDBT_LAYERB_FEC</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-MODULATION"><constant>DTV_ISDBT_LAYERB_MODULATION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-SEGMENT-COUNT"><constant>DTV_ISDBT_LAYERB_SEGMENT_COUNT</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-TIME-INTERLEAVING"><constant>DTV_ISDBT_LAYERB_TIME_INTERLEAVING</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-FEC"><constant>DTV_ISDBT_LAYERC_FEC</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-MODULATION"><constant>DTV_ISDBT_LAYERC_MODULATION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-SEGMENT-COUNT"><constant>DTV_ISDBT_LAYERC_SEGMENT_COUNT</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBT-LAYER-TIME-INTERLEAVING"><constant>DTV_ISDBT_LAYERC_TIME_INTERLEAVING</constant></link></para></listitem>
+               </itemizedlist>
+               </section>
+               <section id="atsc-params">
+                       <title>ATSC delivery system</title>
+                       <para>The following parameters are valid for ATSC:</para>
+                       <itemizedlist mark='opencircle'>
+                               <listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-BANDWIDTH-HZ"><constant>DTV_BANDWIDTH_HZ</constant></link></para></listitem>
+                       </itemizedlist>
+               </section>
+       </section>
+       <section id="frontend-property-cable-systems">
+       <title>Properties used on cable delivery systems</title>
+       <section id="dvbc-params">
+               <title>DVB-C delivery system</title>
+               <para>The DVB-C Annex-A/C is the widely used cable standard. Transmission uses QAM modulation.</para>
+               <para>The following parameters are valid for DVB-C Annex A/C:</para>
+               <itemizedlist mark='opencircle'>
+                       <listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
+               </itemizedlist>
+       </section>
+       <section id="dvbc-annex-b-params">
+               <title>DVB-C Annex B delivery system</title>
+               <para>The DVB-C Annex-B is only used on a few Countries like the United States.</para>
+               <para>The following parameters are valid for DVB-C Annex B:</para>
+               <itemizedlist mark='opencircle'>
+                       <listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
+               </itemizedlist>
+       </section>
+       </section>
+       <section id="frontend-property-satellital-systems">
+       <title>Properties used on satellital delivery systems</title>
+       <section id="dvbs-params">
+               <title>DVB-S delivery system</title>
+               <para>The following parameters are valid for DVB-S:</para>
+               <itemizedlist mark='opencircle'>
+                       <listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
+               </itemizedlist>
+               <para>Future implementations might add those two missing parameters:</para>
+               <itemizedlist mark='opencircle'>
+                       <listitem><para><link linkend="DTV-DISEQC-MASTER"><constant>DTV_DISEQC_MASTER</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-DISEQC-SLAVE-REPLY"><constant>DTV_DISEQC_SLAVE_REPLY</constant></link></para></listitem>
+               </itemizedlist>
+       </section>
+       <section id="dvbs2-params">
+               <title>DVB-S2 delivery system</title>
+               <para>The following parameters are valid for DVB-S2:</para>
+               <itemizedlist mark='opencircle'>
+                       <listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-VOLTAGE"><constant>DTV_VOLTAGE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-TONE"><constant>DTV_TONE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-PILOT"><constant>DTV_PILOT</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ROLLOFF"><constant>DTV_ROLLOFF</constant></link></para></listitem>
+               </itemizedlist>
+               <para>Future implementations might add those two missing parameters:</para>
+               <itemizedlist mark='opencircle'>
+                       <listitem><para><link linkend="DTV-DISEQC-MASTER"><constant>DTV_DISEQC_MASTER</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-DISEQC-SLAVE-REPLY"><constant>DTV_DISEQC_SLAVE_REPLY</constant></link></para></listitem>
+               </itemizedlist>
+       </section>
+       <section id="isdbs-params">
+               <title>ISDB-S delivery system</title>
+               <para>The following parameters are valid for ISDB-S:</para>
+               <itemizedlist mark='opencircle'>
+                       <listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-VOLTAGE"><constant>DTV_VOLTAGE</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-ISDBS-TS-ID"><constant>DTV_ISDBS_TS_ID</constant></link></para></listitem>
+               </itemizedlist>
+       </section>
+       </section>
+</section>
similarity index 75%
rename from Documentation/DocBook/dvb/frontend.xml
rename to Documentation/DocBook/media/dvb/frontend.xml
index 60c6976..61407ea 100644 (file)
@@ -20,22 +20,52 @@ cards, in which case there exists no frontend device.</para>
 <section id="frontend_types">
 <title>Frontend Data Types</title>
 
-<section id="frontend_type">
-<title>frontend type</title>
-
-<para>For historical reasons frontend types are named after the type of modulation used in
-transmission.</para>
-<programlisting>
-       typedef enum fe_type {
-       FE_QPSK,   /&#x22C6; DVB-S &#x22C6;/
-       FE_QAM,    /&#x22C6; DVB-C &#x22C6;/
-       FE_OFDM    /&#x22C6; DVB-T &#x22C6;/
-       } fe_type_t;
-</programlisting>
-
+<section id="fe-type-t">
+<title>Frontend type</title>
+
+<para>For historical reasons, frontend types are named by the type of modulation used in
+transmission. The fontend types are given by fe_type_t type, defined as:</para>
+
+<table pgwide="1" frame="none" id="fe-type">
+<title>Frontend types</title>
+<tgroup cols="3">
+   &cs-def;
+   <thead>
+     <row>
+       <entry>fe_type</entry>
+       <entry>Description</entry>
+       <entry><link linkend="DTV-DELIVERY-SYSTEM">DTV_DELIVERY_SYSTEM</link> equivalent type</entry>
+     </row>
+  </thead>
+  <tbody valign="top">
+  <row>
+     <entry id="FE_QPSK"><constant>FE_QPSK</constant></entry>
+     <entry>For DVB-S standard</entry>
+     <entry><constant>SYS_DVBS</constant></entry>
+  </row>
+  <row>
+     <entry id="FE_QAM"><constant>FE_QAM</constant></entry>
+     <entry>For DVB-C annex A/C standard</entry>
+     <entry><constant>SYS_DVBC_ANNEX_AC</constant></entry>
+  </row>
+  <row>
+     <entry id="FE_OFDM"><constant>FE_OFDM</constant></entry>
+     <entry>For DVB-T standard</entry>
+     <entry><constant>SYS_DVBT</constant></entry>
+  </row>
+  <row>
+     <entry id="FE_ATSC"><constant>FE_ATSC</constant></entry>
+     <entry>For ATSC standard (terrestrial) or for DVB-C Annex B (cable) used in US.</entry>
+     <entry><constant>SYS_ATSC</constant> (terrestrial) or <constant>SYS_DVBC_ANNEX_B</constant> (cable)</entry>
+  </row>
+</tbody></tgroup></table>
+
+<para>Newer formats like DVB-S2, ISDB-T, ISDB-S and DVB-T2 are not described at the above, as they're
+supported via the new <link linkend="FE_GET_SET_PROPERTY">FE_GET_PROPERTY/FE_GET_SET_PROPERTY</link> ioctl's, using the <link linkend="DTV-DELIVERY-SYSTEM">DTV_DELIVERY_SYSTEM</link> parameter.
+</para>
 </section>
 
-<section id="frontend_caps">
+<section id="fe-caps-t">
 <title>frontend capabilities</title>
 
 <para>Capabilities describe what a frontend can do. Some capabilities can only be supported for
@@ -76,7 +106,7 @@ a specific frontend type.</para>
 </programlisting>
 </section>
 
-<section id="frontend_info">
+<section id="dvb-frontend-info">
 <title>frontend information</title>
 
 <para>Information about the frontend ca be queried with
@@ -99,7 +129,7 @@ a specific frontend type.</para>
 </programlisting>
 </section>
 
-<section id="frontend_diseqc">
+<section id="dvb-diseqc-master-cmd">
 <title>diseqc master command</title>
 
 <para>A message sent from the frontend to DiSEqC capable equipment.</para>
@@ -110,7 +140,7 @@ a specific frontend type.</para>
        };
 </programlisting>
 </section>
-<section role="subsection">
+<section role="subsection" id="dvb-diseqc-slave-reply">
 <title>diseqc slave reply</title>
 
 <para>A reply to the frontend from DiSEqC 2.0 capable equipment.</para>
@@ -123,7 +153,7 @@ a specific frontend type.</para>
 </programlisting>
 </section>
 
-<section id="frontend_diseqc_slave_reply">
+<section id="fe-sec-voltage-t">
 <title>diseqc slave reply</title>
 <para>The voltage is usually used with non-DiSEqC capable LNBs to switch the polarzation
 (horizontal/vertical). When using DiSEqC epuipment this voltage has to be switched
@@ -136,7 +166,7 @@ consistently to the DiSEqC commands as described in the DiSEqC spec.</para>
 </programlisting>
 </section>
 
-<section id="frontend_sec_tone">
+<section id="fe-sec-tone-mode-t">
 <title>SEC continuous tone</title>
 
 <para>The continuous 22KHz tone is usually used with non-DiSEqC capable LNBs to switch the
@@ -151,7 +181,7 @@ spec.</para>
 </programlisting>
 </section>
 
-<section id="frontend_sec_burst">
+<section id="fe-sec-mini-cmd-t">
 <title>SEC tone burst</title>
 
 <para>The 22KHz tone burst is usually used with non-DiSEqC capable switches to select
@@ -168,7 +198,7 @@ spec.</para>
 <para></para>
 </section>
 
-<section id="frontend_status">
+<section id="fe-status-t">
 <title>frontend status</title>
 <para>Several functions of the frontend device use the fe_status data type defined
 by</para>
@@ -188,31 +218,54 @@ by</para>
 
 </section>
 
-<section id="frontend_params">
+<section id="dvb-frontend-parameters">
 <title>frontend parameters</title>
 <para>The kind of parameters passed to the frontend device for tuning depend on
-the kind of hardware you are using. All kinds of parameters are combined as an
-union in the FrontendParameters structure:</para>
+the kind of hardware you are using.</para>
+<para>The struct <constant>dvb_frontend_parameters</constant> uses an
+union with specific per-system parameters. However, as newer delivery systems
+required more data, the structure size weren't enough to fit, and just
+extending its size would break the existing applications. So, those parameters
+were replaced by the usage of <link linkend="FE_GET_SET_PROPERTY">
+<constant>FE_GET_PROPERTY/FE_SET_PROPERTY</constant></link> ioctl's. The
+new API is flexible enough to add new parameters to existing delivery systems,
+and to add newer delivery systems.</para>
+<para>So, newer applications should use <link linkend="FE_GET_SET_PROPERTY">
+<constant>FE_GET_PROPERTY/FE_SET_PROPERTY</constant></link> instead, in
+order to be able to support the newer System Delivery like  DVB-S2, DVB-T2,
+DVB-C2, ISDB, etc.</para>
+<para>All kinds of parameters are combined as an union in the FrontendParameters structure:</para>
 <programlisting>
- struct dvb_frontend_parameters {
-        uint32_t frequency;       /&#x22C6; (absolute) frequency in Hz for QAM/OFDM &#x22C6;/
-                                  /&#x22C6; intermediate frequency in kHz for QPSK &#x22C6;/
-        fe_spectral_inversion_t inversion;
-        union {
-                struct dvb_qpsk_parameters qpsk;
-                struct dvb_qam_parameters  qam;
-                struct dvb_ofdm_parameters ofdm;
-        } u;
- };
+struct dvb_frontend_parameters {
+       uint32_t frequency;     /&#x22C6; (absolute) frequency in Hz for QAM/OFDM &#x22C6;/
+                               /&#x22C6; intermediate frequency in kHz for QPSK &#x22C6;/
+       fe_spectral_inversion_t inversion;
+       union {
+               struct dvb_qpsk_parameters qpsk;
+               struct dvb_qam_parameters  qam;
+               struct dvb_ofdm_parameters ofdm;
+               struct dvb_vsb_parameters  vsb;
+       } u;
+};
 </programlisting>
-<para>For satellite QPSK frontends you have to use the <constant>QPSKParameters</constant> member defined by</para>
+<para>In the case of QPSK frontends the <constant>frequency</constant> field specifies the intermediate
+frequency, i.e. the offset which is effectively added to the local oscillator frequency (LOF) of
+the LNB. The intermediate frequency has to be specified in units of kHz. For QAM and
+OFDM frontends the <constant>frequency</constant> specifies the absolute frequency and is given in Hz.
+</para>
+<section id="dvb-qpsk-parameters">
+<title>QPSK parameters</title>
+<para>For satellite QPSK frontends you have to use the <constant>dvb_qpsk_parameters</constant> structure:</para>
 <programlisting>
  struct dvb_qpsk_parameters {
         uint32_t        symbol_rate;  /&#x22C6; symbol rate in Symbols per second &#x22C6;/
         fe_code_rate_t  fec_inner;    /&#x22C6; forward error correction (see above) &#x22C6;/
  };
 </programlisting>
-<para>for cable QAM frontend you use the <constant>QAMParameters</constant> structure</para>
+</section>
+<section id="dvb-qam-parameters">
+<title>QAM parameters</title>
+<para>for cable QAM frontend you use the <constant>dvb_qam_parameters</constant> structure:</para>
 <programlisting>
  struct dvb_qam_parameters {
         uint32_t         symbol_rate; /&#x22C6; symbol rate in Symbols per second &#x22C6;/
@@ -220,8 +273,19 @@ union in the FrontendParameters structure:</para>
         fe_modulation_t  modulation;  /&#x22C6; modulation type (see above) &#x22C6;/
  };
 </programlisting>
-<para>DVB-T frontends are supported by the <constant>OFDMParamters</constant> structure
-</para>
+</section>
+<section id="dvb-vsb-parameters">
+<title>VSB parameters</title>
+<para>ATSC frontends are supported by the <constant>dvb_vsb_parameters</constant> structure:</para>
+<programlisting>
+struct dvb_vsb_parameters {
+       fe_modulation_t modulation;     /&#x22C6; modulation type (see above) &#x22C6;/
+};
+</programlisting>
+</section>
+<section id="dvb-ofdm-parameters">
+<title>OFDM parameters</title>
+<para>DVB-T frontends are supported by the <constant>dvb_ofdm_parameters</constant> structure:</para>
 <programlisting>
  struct dvb_ofdm_parameters {
         fe_bandwidth_t      bandwidth;
@@ -233,86 +297,124 @@ union in the FrontendParameters structure:</para>
         fe_hierarchy_t      hierarchy_information;
  };
 </programlisting>
-<para>In the case of QPSK frontends the <constant>Frequency</constant> field specifies the intermediate
-frequency, i.e. the offset which is effectively added to the local oscillator frequency (LOF) of
-the LNB. The intermediate frequency has to be specified in units of kHz. For QAM and
-OFDM frontends the Frequency specifies the absolute frequency and is given in
-Hz.
-</para>
+</section>
+<section id="fe-spectral-inversion-t">
+<title>frontend spectral inversion</title>
 <para>The Inversion field can take one of these values:
 </para>
 <programlisting>
- typedef enum fe_spectral_inversion {
-        INVERSION_OFF,
-        INVERSION_ON,
-        INVERSION_AUTO
- } fe_spectral_inversion_t;
+typedef enum fe_spectral_inversion {
+       INVERSION_OFF,
+       INVERSION_ON,
+       INVERSION_AUTO
+} fe_spectral_inversion_t;
 </programlisting>
 <para>It indicates if spectral inversion should be presumed or not. In the automatic setting
 (<constant>INVERSION_AUTO</constant>) the hardware will try to figure out the correct setting by
 itself.
 </para>
-<para>The possible values for the <constant>FEC_inner</constant> field are
+</section>
+<section id="fe-code-rate-t">
+<title>frontend code rate</title>
+<para>The possible values for the <constant>fec_inner</constant> field used on
+<link refend="dvb-qpsk-parameters"><constant>struct dvb_qpsk_parameters</constant></link> and
+<link refend="dvb-qam-parameters"><constant>struct dvb_qam_parameters</constant></link> are:
 </para>
 <programlisting>
- typedef enum fe_code_rate {
-        FEC_NONE = 0,
-        FEC_1_2,
-        FEC_2_3,
-        FEC_3_4,
-        FEC_4_5,
-        FEC_5_6,
-        FEC_6_7,
-        FEC_7_8,
-        FEC_8_9,
-        FEC_AUTO
- } fe_code_rate_t;
+typedef enum fe_code_rate {
+       FEC_NONE = 0,
+       FEC_1_2,
+       FEC_2_3,
+       FEC_3_4,
+       FEC_4_5,
+       FEC_5_6,
+       FEC_6_7,
+       FEC_7_8,
+       FEC_8_9,
+       FEC_AUTO,
+       FEC_3_5,
+       FEC_9_10,
+} fe_code_rate_t;
 </programlisting>
 <para>which correspond to error correction rates of 1/2, 2/3, etc., no error correction or auto
 detection.
 </para>
-<para>For cable and terrestrial frontends (QAM and OFDM) one also has to specify the quadrature
-modulation mode which can be one of the following:
+</section>
+<section id="fe-modulation-t">
+<title>frontend modulation type for QAM, OFDM and VSB</title>
+<para>For cable and terrestrial frontends, e. g. for
+<link refend="dvb-qam-parameters"><constant>struct dvb_qpsk_parameters</constant></link>,
+<link refend="dvb-ofdm-parameters"><constant>struct dvb_qam_parameters</constant></link> and
+<link refend="dvb-vsb-parameters"><constant>struct dvb_qam_parameters</constant></link>,
+it needs to specify the quadrature modulation mode which can be one of the following:
 </para>
 <programlisting>
  typedef enum fe_modulation {
- QPSK,
-        QAM_16,
-        QAM_32,
-        QAM_64,
-        QAM_128,
-        QAM_256,
-        QAM_AUTO
+       QPSK,
+       QAM_16,
+       QAM_32,
+       QAM_64,
+       QAM_128,
+       QAM_256,
+       QAM_AUTO,
+       VSB_8,
+       VSB_16,
+       PSK_8,
+       APSK_16,
+       APSK_32,
+       DQPSK,
  } fe_modulation_t;
 </programlisting>
+</section>
 <para>Finally, there are several more parameters for OFDM:
 </para>
+<section id="fe-transmit-mode-t">
+<title>Number of carriers per channel</title>
 <programlisting>
- typedef enum fe_transmit_mode {
-        TRANSMISSION_MODE_2K,
-        TRANSMISSION_MODE_8K,
-        TRANSMISSION_MODE_AUTO
+typedef enum fe_transmit_mode {
+       TRANSMISSION_MODE_2K,
+       TRANSMISSION_MODE_8K,
+       TRANSMISSION_MODE_AUTO,
+       TRANSMISSION_MODE_4K,
+       TRANSMISSION_MODE_1K,
+       TRANSMISSION_MODE_16K,
+       TRANSMISSION_MODE_32K,
  } fe_transmit_mode_t;
 </programlisting>
- <programlisting>
- typedef enum fe_bandwidth {
-        BANDWIDTH_8_MHZ,
-        BANDWIDTH_7_MHZ,
-        BANDWIDTH_6_MHZ,
-        BANDWIDTH_AUTO
- } fe_bandwidth_t;
+</section>
+<section id="fe-bandwidth-t">
+<title>frontend bandwidth</title>
+<programlisting>
+typedef enum fe_bandwidth {
+       BANDWIDTH_8_MHZ,
+       BANDWIDTH_7_MHZ,
+       BANDWIDTH_6_MHZ,
+       BANDWIDTH_AUTO,
+       BANDWIDTH_5_MHZ,
+       BANDWIDTH_10_MHZ,
+       BANDWIDTH_1_712_MHZ,
+} fe_bandwidth_t;
 </programlisting>
- <programlisting>
- typedef enum fe_guard_interval {
-        GUARD_INTERVAL_1_32,
-        GUARD_INTERVAL_1_16,
-        GUARD_INTERVAL_1_8,
-        GUARD_INTERVAL_1_4,
-        GUARD_INTERVAL_AUTO
- } fe_guard_interval_t;
+</section>
+<section id="fe-guard-interval-t">
+<title>frontend guard inverval</title>
+<programlisting>
+typedef enum fe_guard_interval {
+       GUARD_INTERVAL_1_32,
+       GUARD_INTERVAL_1_16,
+       GUARD_INTERVAL_1_8,
+       GUARD_INTERVAL_1_4,
+       GUARD_INTERVAL_AUTO,
+       GUARD_INTERVAL_1_128,
+       GUARD_INTERVAL_19_128,
+       GUARD_INTERVAL_19_256,
+} fe_guard_interval_t;
 </programlisting>
- <programlisting>
- typedef enum fe_hierarchy {
+</section>
+<section id="fe-hierarchy-t">
+<title>frontend hierarchy</title>
+<programlisting>
+typedef enum fe_hierarchy {
         HIERARCHY_NONE,
         HIERARCHY_1,
         HIERARCHY_2,
@@ -320,10 +422,11 @@ modulation mode which can be one of the following:
         HIERARCHY_AUTO
  } fe_hierarchy_t;
 </programlisting>
+</section>
 
 </section>
 
-<section id="frontend_events">
+<section id="dvb-frontend-event">
 <title>frontend events</title>
  <programlisting>
  struct dvb_frontend_event {
@@ -412,8 +515,7 @@ modulation mode which can be one of the following:
 <para>(blocking mode is the default)</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>ENODEV</para>
@@ -473,8 +575,7 @@ modulation mode which can be one of the following:
 <para>File descriptor returned by a previous call to open().</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>EBADF</para>
@@ -530,8 +631,7 @@ modulation mode which can be one of the following:
  to be stored.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>EBADF</para>
@@ -592,38 +692,8 @@ modulation mode which can be one of the following:
 <para>The bit error rate is stored into *ber.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>ber points to invalid address.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ENOSIGNAL</para>
-</entry><entry
- align="char">
-<para>There is no signal, thus no meaningful bit error rate. Also
- returned if the front-end is not turned on.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ENOSYS</para>
-</entry><entry
- align="char">
-<para>Function not available for this device.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+
+&return-value-dvb;
 </section>
 
 <section id="FE_READ_SNR">
@@ -670,38 +740,7 @@ modulation mode which can be one of the following:
 </entry>
  </row></tbody></tgroup></informaltable>
 
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>snr points to invalid address.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ENOSIGNAL</para>
-</entry><entry
- align="char">
-<para>There is no signal, thus no meaningful signal strength
- value. Also returned if front-end is not turned on.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ENOSYS</para>
-</entry><entry
- align="char">
-<para>Function not available for this device.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
 <section id="FE_READ_SIGNAL_STRENGTH">
@@ -748,38 +787,8 @@ modulation mode which can be one of the following:
 <para>The signal strength value is stored into *strength.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>status points to invalid address.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ENOSIGNAL</para>
-</entry><entry
- align="char">
-<para>There is no signal, thus no meaningful signal strength
- value. Also returned if front-end is not turned on.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ENOSYS</para>
-</entry><entry
- align="char">
-<para>Function not available for this device.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+
+&return-value-dvb;
 </section>
 
 <section id="FE_READ_UNCORRECTED_BLOCKS">
@@ -833,30 +842,8 @@ modulation mode which can be one of the following:
  so far.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>ublocks points to invalid address.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ENOSYS</para>
-</entry><entry
- align="char">
-<para>Function not available for this device.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+
+&return-value-dvb;
 </section>
 
 <section id="FE_SET_FRONTEND">
@@ -909,24 +896,10 @@ modulation mode which can be one of the following:
 <para>Points to parameters for tuning operation.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>p points to invalid address.</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
@@ -982,25 +955,9 @@ modulation mode which can be one of the following:
 </entry>
  </row></tbody></tgroup></informaltable>
 
-<para>ERRORS
-</para>
-
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>p points to invalid address.</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
@@ -1084,24 +1041,9 @@ modulation mode which can be one of the following:
 </entry>
  </row></tbody></tgroup></informaltable>
 
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>ev points to invalid address.</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EWOULDBLOCK</para>
 </entry><entry
  align="char">
@@ -1111,11 +1053,6 @@ modulation mode which can be one of the following:
  </row><row><entry
  align="char">
 <para>EOVERFLOW</para>
-</entry><entry
- align="char">
-</entry>
- </row><row><entry
- align="char">
 </entry><entry
  align="char">
 <para>Overflow in event queue - one or more events were lost.</para>
@@ -1170,23 +1107,7 @@ modulation mode which can be one of the following:
  to be stored.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>info points to invalid address.</para>
-</entry>
-</row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
 <section id="FE_DISEQC_RESET_OVERLOAD">
@@ -1229,30 +1150,7 @@ modulation mode which can be one of the following:
 </entry>
  </row></tbody></tgroup></informaltable>
 
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EPERM</para>
-</entry><entry
- align="char">
-<para>Permission denied (needs read/write access).</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error in the device driver.</para>
-</entry>
-</row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
 <section id="FE_DISEQC_SEND_MASTER_CMD">
@@ -1302,45 +1200,7 @@ modulation mode which can be one of the following:
 </entry>
  </row></tbody></tgroup></informaltable>
 
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>Seq points to an invalid address.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>The data structure referred to by seq is invalid in some
- way.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EPERM</para>
-</entry><entry
- align="char">
-<para>Permission denied (needs read/write access).</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error in the device driver.</para>
-</entry>
-</row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
 <section id="FE_DISEQC_RECV_SLAVE_REPLY">
@@ -1390,45 +1250,7 @@ modulation mode which can be one of the following:
 <para>Pointer to the command to be received.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>Seq points to an invalid address.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>The data structure referred to by seq is invalid in some
- way.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EPERM</para>
-</entry><entry
- align="char">
-<para>Permission denied (needs read/write access).</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error in the device driver.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
 <section id="FE_DISEQC_SEND_BURST">
@@ -1476,45 +1298,7 @@ modulation mode which can be one of the following:
 </entry>
  </row></tbody></tgroup></informaltable>
 
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>Seq points to an invalid address.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>The data structure referred to by seq is invalid in some
- way.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EPERM</para>
-</entry><entry
- align="char">
-<para>Permission denied (needs read/write access).</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error in the device driver.</para>
-</entry>
-</row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
 <section id="FE_SET_TONE">
@@ -1560,44 +1344,7 @@ modulation mode which can be one of the following:
 <para>The requested tone generation mode (on/off).</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>ENODEV</para>
-</entry><entry
- align="char">
-<para>Device driver not loaded/available.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EBUSY</para>
-</entry><entry
- align="char">
-<para>Device or resource busy.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Invalid argument.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EPERM</para>
-</entry><entry
- align="char">
-<para>File not opened with read permissions.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error in the device driver.</para>
-</entry>
-</row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
 <section id="FE_SET_VOLTAGE">
@@ -1645,44 +1392,7 @@ modulation mode which can be one of the following:
 </entry>
  </row></tbody></tgroup></informaltable>
 
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>ENODEV</para>
-</entry><entry
- align="char">
-<para>Device driver not loaded/available.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EBUSY</para>
-</entry><entry
- align="char">
-<para>Device or resource busy.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Invalid argument.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EPERM</para>
-</entry><entry
- align="char">
-<para>File not opened with read permissions.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error in the device driver.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
 <section id="FE_ENABLE_HIGH_LNB_VOLTAGE">
@@ -1731,44 +1441,7 @@ modulation mode which can be one of the following:
 </entry>
  </row></tbody></tgroup></informaltable>
 
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>ENODEV</para>
-</entry><entry
- align="char">
-<para>Device driver not loaded/available.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EBUSY</para>
-</entry><entry
- align="char">
-<para>Device or resource busy.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Invalid argument.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EPERM</para>
-</entry><entry
- align="char">
-<para>File not opened with read permissions.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error in the device driver.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
 <section id="FE_SET_FRONTEND_TUNE_MODE">
@@ -1800,11 +1473,7 @@ FE_TUNE_MODE_ONESHOT When set, this flag will disable any zigzagging or other "n
 </entry>
  </row></tbody></tgroup></informaltable>
 
-<para>ERRORS</para>
-<informaltable><tgroup cols="2"><tbody><row>
-<entry align="char"><para>EINVAL</para></entry>
-<entry align="char"><para>Invalid argument.</para></entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
 <section id="FE_DISHNETWORK_SEND_LEGACY_CMD">
@@ -1838,12 +1507,7 @@ sends the specified raw cmd to the dish via DISEqC.
 </entry>
  </row></tbody></tgroup></informaltable>
 
-<para>ERRORS</para>
-<informaltable><tgroup cols="1"><tbody><row>
-<entry align="char">
-       <para>There are no errors in use for this call</para>
-</entry>
-</row></tbody></tgroup></informaltable>
+&return-value-dvb;
 </section>
 
 </section>
similarity index 92%
rename from Documentation/DocBook/dvb/intro.xml
rename to Documentation/DocBook/media/dvb/intro.xml
index 0dc83f6..c75dc7c 100644 (file)
@@ -154,6 +154,10 @@ are called:</para>
 </listitem>
  <listitem>
 
+<para><emphasis role="tt">/dev/dvb/adapterN/dvrM</emphasis>,</para>
+</listitem>
+ <listitem>
+
 <para><emphasis role="tt">/dev/dvb/adapterN/caM</emphasis>,</para></listitem></itemizedlist>
 
 <para>where N enumerates the DVB PCI cards in a system starting
@@ -175,10 +179,27 @@ the devices are described in the following chapters.</para>
 The DVB API include files should be included in application sources with
 a partial path like:</para>
 
-
+<programlisting>
+       #include &#x003C;linux/dvb/audio.h&#x003E;
+</programlisting>
+<programlisting>
+       #include &#x003C;linux/dvb/ca.h&#x003E;
+</programlisting>
+<programlisting>
+       #include &#x003C;linux/dvb/dmx.h&#x003E;
+</programlisting>
 <programlisting>
        #include &#x003C;linux/dvb/frontend.h&#x003E;
 </programlisting>
+<programlisting>
+       #include &#x003C;linux/dvb/net.h&#x003E;
+</programlisting>
+<programlisting>
+       #include &#x003C;linux/dvb/osd.h&#x003E;
+</programlisting>
+<programlisting>
+       #include &#x003C;linux/dvb/video.h&#x003E;
+</programlisting>
 
 <para>To enable applications to support different API version, an
 additional include file <emphasis
similarity index 57%
rename from Documentation/DocBook/dvb/net.xml
rename to Documentation/DocBook/media/dvb/net.xml
index 94e388d..67d37e5 100644 (file)
@@ -7,6 +7,23 @@ application.
 </para>
 <section id="dvb_net_types">
 <title>DVB Net Data Types</title>
+
+<section id="dvb-net-if">
+<title>struct dvb_net_if</title>
+<programlisting>
+struct dvb_net_if {
+       __u16 pid;
+       __u16 if_num;
+       __u8  feedtype;
+#define DVB_NET_FEEDTYPE_MPE 0 /&#x22C6; multi protocol encapsulation &#x22C6;/
+#define DVB_NET_FEEDTYPE_ULE 1 /&#x22C6; ultra lightweight encapsulation &#x22C6;/
+};
+</programlisting>
+</section>
+
+</section>
+<section id="net_fcalls">
+<title>DVB net Function Calls</title>
 <para>To be written&#x2026;
 </para>
 </section>
similarity index 81%
rename from Documentation/DocBook/dvb/video.xml
rename to Documentation/DocBook/media/dvb/video.xml
index 7bb287e..25fb823 100644 (file)
@@ -18,15 +18,16 @@ supported on some MPEG decoders made for DVD playback.
 <section id="video_types">
 <title>Video Data Types</title>
 
-<section id="video_format_t">
+<section id="video-format-t">
 <title>video_format_t</title>
 <para>The <emphasis role="tt">video_format_t</emphasis> data type defined by
 </para>
 <programlisting>
- typedef enum {
-        VIDEO_FORMAT_4_3,
-        VIDEO_FORMAT_16_9
- } video_format_t;
+typedef enum {
+       VIDEO_FORMAT_4_3,     /&#x22C6; Select 4:3 format &#x22C6;/
+       VIDEO_FORMAT_16_9,    /&#x22C6; Select 16:9 format. &#x22C6;/
+       VIDEO_FORMAT_221_1    /&#x22C6; 2.21:1 &#x22C6;/
+} video_format_t;
 </programlisting>
 <para>is used in the VIDEO_SET_FORMAT function (??) to tell the driver which aspect ratio
 the output hardware (e.g. TV) has. It is also used in the data structures video_status
@@ -36,34 +37,36 @@ stream.
 </para>
 </section>
 
-<section id="video_display_format_t">
-<title>video_display_format_t</title>
+<section id="video-displayformat-t">
+<title>video_displayformat_t</title>
 <para>In case the display format of the video stream and of the display hardware differ the
 application has to specify how to handle the cropping of the picture. This can be done using
 the VIDEO_SET_DISPLAY_FORMAT call (??) which accepts
 </para>
 <programlisting>
- typedef enum {
-        VIDEO_PAN_SCAN,
-        VIDEO_LETTER_BOX,
-        VIDEO_CENTER_CUT_OUT
- } video_display_format_t;
+typedef enum {
+       VIDEO_PAN_SCAN,       /&#x22C6; use pan and scan format &#x22C6;/
+       VIDEO_LETTER_BOX,     /&#x22C6; use letterbox format &#x22C6;/
+       VIDEO_CENTER_CUT_OUT  /&#x22C6; use center cut out format &#x22C6;/
+} video_displayformat_t;
 </programlisting>
 <para>as argument.
 </para>
 </section>
 
-<section id="video_stream_source">
+<section id="video-stream-source-t">
 <title>video stream source</title>
 <para>The video stream source is set through the VIDEO_SELECT_SOURCE call and can take
 the following values, depending on whether we are replaying from an internal (demuxer) or
 external (user write) source.
 </para>
 <programlisting>
- typedef enum {
-        VIDEO_SOURCE_DEMUX,
-        VIDEO_SOURCE_MEMORY
- } video_stream_source_t;
+typedef enum {
+       VIDEO_SOURCE_DEMUX, /&#x22C6; Select the demux as the main source &#x22C6;/
+       VIDEO_SOURCE_MEMORY /&#x22C6; If this source is selected, the stream
+                              comes from the user through the write
+                              system call &#x22C6;/
+} video_stream_source_t;
 </programlisting>
 <para>VIDEO_SOURCE_DEMUX selects the demultiplexer (fed either by the frontend or the
 DVR device) as the source of the video stream. If VIDEO_SOURCE_MEMORY
@@ -72,49 +75,98 @@ call.
 </para>
 </section>
 
-<section id="video_play_state">
+<section id="video-play-state-t">
 <title>video play state</title>
 <para>The following values can be returned by the VIDEO_GET_STATUS call representing the
 state of video playback.
 </para>
 <programlisting>
- typedef enum {
-        VIDEO_STOPPED,
-        VIDEO_PLAYING,
-        VIDEO_FREEZED
- } video_play_state_t;
+typedef enum {
+       VIDEO_STOPPED, /&#x22C6; Video is stopped &#x22C6;/
+       VIDEO_PLAYING, /&#x22C6; Video is currently playing &#x22C6;/
+       VIDEO_FREEZED  /&#x22C6; Video is freezed &#x22C6;/
+} video_play_state_t;
 </programlisting>
 </section>
 
-<section id="video_event">
+<section id="video-command">
+<para>The structure must be zeroed before use by the application
+This ensures it can be extended safely in the future.</para>
+<title>struct video-command</title>
+<programlisting>
+struct video_command {
+       __u32 cmd;
+       __u32 flags;
+       union {
+               struct {
+                       __u64 pts;
+               } stop;
+
+               struct {
+                       /&#x22C6; 0 or 1000 specifies normal speed,
+                          1 specifies forward single stepping,
+                          -1 specifies backward single stepping,
+                          &gt;>1: playback at speed/1000 of the normal speed,
+                          &lt;-1: reverse playback at (-speed/1000) of the normal speed. &#x22C6;/
+                       __s32 speed;
+                       __u32 format;
+               } play;
+
+               struct {
+                       __u32 data[16];
+               } raw;
+       };
+};
+</programlisting>
+</section>
+
+<section id="video-size-t">
+<title>struct video_size-t</title>
+<programlisting>
+typedef struct {
+       int w;
+       int h;
+       video_format_t aspect_ratio;
+} video_size_t;
+</programlisting>
+</section>
+
+
+<section id="video-event">
 <title>struct video_event</title>
 <para>The following is the structure of a video event as it is returned by the VIDEO_GET_EVENT
 call.
 </para>
 <programlisting>
- struct video_event {
-        int32_t type;
-        time_t timestamp;
-        union {
-                video_format_t video_format;
-        } u;
- };
+struct video_event {
+       __s32 type;
+#define VIDEO_EVENT_SIZE_CHANGED       1
+#define VIDEO_EVENT_FRAME_RATE_CHANGED 2
+#define VIDEO_EVENT_DECODER_STOPPED    3
+#define VIDEO_EVENT_VSYNC              4
+       __kernel_time_t timestamp;
+       union {
+               video_size_t size;
+               unsigned int frame_rate;        /&#x22C6; in frames per 1000sec &#x22C6;/
+               unsigned char vsync_field;      /&#x22C6; unknown/odd/even/progressive &#x22C6;/
+       } u;
+};
 </programlisting>
 </section>
 
-<section id="video_status">
+<section id="video-status">
 <title>struct video_status</title>
 <para>The VIDEO_GET_STATUS call returns the following structure informing about various
 states of the playback operation.
 </para>
 <programlisting>
- struct video_status {
-        boolean video_blank;
-        video_play_state_t play_state;
-        video_stream_source_t stream_source;
-        video_format_t video_format;
-        video_displayformat_t display_format;
- };
+struct video_status {
+       int                   video_blank;   /&#x22C6; blank video on freeze? &#x22C6;/
+       video_play_state_t    play_state;    /&#x22C6; current state of playback &#x22C6;/
+       video_stream_source_t stream_source; /&#x22C6; current source (demux/memory) &#x22C6;/
+       video_format_t        video_format;  /&#x22C6; current aspect ratio of stream &#x22C6;/
+       video_displayformat_t display_format;/&#x22C6; selected cropping mode &#x22C6;/
+};
 </programlisting>
 <para>If video_blank is set video will be blanked out if the channel is changed or if playback is
 stopped. Otherwise, the last picture will be displayed. play_state indicates if the video is
@@ -127,17 +179,17 @@ device.
 </para>
 </section>
 
-<section id="video_still_picture">
+<section id="video-still-picture">
 <title>struct video_still_picture</title>
 <para>An I-frame displayed via the VIDEO_STILLPICTURE call is passed on within the
 following structure.
 </para>
 <programlisting>
- /&#x22C6; pointer to and size of a single iframe in memory &#x22C6;/
- struct video_still_picture {
-        char &#x22C6;iFrame;
-        int32_t size;
- };
+/&#x22C6; pointer to and size of a single iframe in memory &#x22C6;/
+struct video_still_picture {
+       char &#x22C6;iFrame;        /&#x22C6; pointer to a single iframe in memory &#x22C6;/
+       int32_t size;
+};
 </programlisting>
 </section>
 
@@ -164,26 +216,26 @@ bits set according to the hardwares capabilities.
 </programlisting>
 </section>
 
-<section id="video_system">
+<section id="video-system">
 <title>video system</title>
 <para>A call to VIDEO_SET_SYSTEM sets the desired video system for TV output. The
 following system types can be set:
 </para>
 <programlisting>
- typedef enum {
-         VIDEO_SYSTEM_PAL,
-         VIDEO_SYSTEM_NTSC,
-         VIDEO_SYSTEM_PALN,
-         VIDEO_SYSTEM_PALNc,
-         VIDEO_SYSTEM_PALM,
-         VIDEO_SYSTEM_NTSC60,
-         VIDEO_SYSTEM_PAL60,
-         VIDEO_SYSTEM_PALM60
- } video_system_t;
+typedef enum {
+        VIDEO_SYSTEM_PAL,
+        VIDEO_SYSTEM_NTSC,
+        VIDEO_SYSTEM_PALN,
+        VIDEO_SYSTEM_PALNc,
+        VIDEO_SYSTEM_PALM,
+        VIDEO_SYSTEM_NTSC60,
+        VIDEO_SYSTEM_PAL60,
+        VIDEO_SYSTEM_PALM60
+} video_system_t;
 </programlisting>
 </section>
 
-<section id="video_highlight">
+<section id="video-highlight">
 <title>struct video_highlight</title>
 <para>Calling the ioctl VIDEO_SET_HIGHLIGHTS posts the SPU highlight information. The
 call expects the following format for that information:
@@ -210,7 +262,7 @@ call expects the following format for that information:
 </programlisting>
 
 </section>
-<section id="video_spu">
+<section id="video-spu">
 <title>video SPU</title>
 <para>Calling VIDEO_SET_SPU deactivates or activates SPU decoding, according to the
 following format:
@@ -224,7 +276,7 @@ following format:
 </programlisting>
 
 </section>
-<section id="video_spu_palette">
+<section id="video-spu-palette">
 <title>video SPU palette</title>
 <para>The following structure is used to set the SPU palette by calling VIDEO_SPU_PALETTE:
 </para>
@@ -237,7 +289,7 @@ following format:
 </programlisting>
 
 </section>
-<section id="video_navi_pack">
+<section id="video-navi-pack">
 <title>video NAVI pack</title>
 <para>In order to get the navigational data the following structure has to be passed to the ioctl
 VIDEO_GET_NAVI:
@@ -252,7 +304,7 @@ VIDEO_GET_NAVI:
 </section>
 
 
-<section id="video_attributes">
+<section id="video-attributes-t">
 <title>video attributes</title>
 <para>The following attributes can be set by a call to VIDEO_SET_ATTRIBUTES:
 </para>
@@ -347,8 +399,7 @@ VIDEO_GET_NAVI:
 <para>(blocking mode is the default)</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>ENODEV</para>
@@ -406,8 +457,7 @@ VIDEO_GET_NAVI:
 <para>File descriptor returned by a previous call to open().</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>EBADF</para>
@@ -462,8 +512,7 @@ VIDEO_GET_NAVI:
 <para>Size of buf.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+<para>RETURN VALUE</para>
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
 <para>EPERM</para>
@@ -488,7 +537,7 @@ VIDEO_GET_NAVI:
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="VIDEO_STOP"
 role="subsection"><title>VIDEO_STOP</title>
 <para>DESCRIPTION
 </para>
@@ -543,26 +592,9 @@ role="subsection"><title>VIDEO_STOP</title>
 <para>FALSE: Show last decoded frame.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error, possibly in the communication with the
- DVB subsystem.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_PLAY"
 role="subsection"><title>VIDEO_PLAY</title>
 <para>DESCRIPTION
 </para>
@@ -596,26 +628,9 @@ role="subsection"><title>VIDEO_PLAY</title>
 <para>Equals VIDEO_PLAY for this command.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error, possibly in the communication with the
- DVB subsystem.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_FREEZE"
 role="subsection"><title>VIDEO_FREEZE</title>
 <para>DESCRIPTION
 </para>
@@ -653,26 +668,9 @@ role="subsection"><title>VIDEO_FREEZE</title>
 <para>Equals VIDEO_FREEZE for this command.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error, possibly in the communication with the
- DVB subsystem.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_CONTINUE"
 role="subsection"><title>VIDEO_CONTINUE</title>
 <para>DESCRIPTION
 </para>
@@ -706,26 +704,9 @@ role="subsection"><title>VIDEO_CONTINUE</title>
 <para>Equals VIDEO_CONTINUE for this command.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error, possibly in the communication with the
- DVB subsystem.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_SELECT_SOURCE"
 role="subsection"><title>VIDEO_SELECT_SOURCE</title>
 <para>DESCRIPTION
 </para>
@@ -769,26 +750,9 @@ role="subsection"><title>VIDEO_SELECT_SOURCE</title>
 <para>Indicates which source shall be used for the Video stream.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error, possibly in the communication with the
- DVB subsystem.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_SET_BLANK"
 role="subsection"><title>VIDEO_SET_BLANK</title>
 <para>DESCRIPTION
 </para>
@@ -835,33 +799,9 @@ role="subsection"><title>VIDEO_SET_BLANK</title>
 <para>FALSE: Show last decoded frame.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error, possibly in the communication with the
- DVB subsystem.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Illegal input parameter</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_GET_STATUS"
 role="subsection"><title>VIDEO_GET_STATUS</title>
 <para>DESCRIPTION
 </para>
@@ -903,33 +843,9 @@ role="subsection"><title>VIDEO_GET_STATUS</title>
 <para>Returns the current status of the Video Device.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error, possibly in the communication with the
- DVB subsystem.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>status points to invalid address</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_GET_EVENT"
 role="subsection"><title>VIDEO_GET_EVENT</title>
 <para>DESCRIPTION
 </para>
@@ -980,24 +896,9 @@ role="subsection"><title>VIDEO_GET_EVENT</title>
  stored.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>ev points to invalid address</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EWOULDBLOCK</para>
 </entry><entry
  align="char">
@@ -1007,18 +908,13 @@ role="subsection"><title>VIDEO_GET_EVENT</title>
  </row><row><entry
  align="char">
 <para>EOVERFLOW</para>
-</entry><entry
- align="char">
-</entry>
- </row><row><entry
- align="char">
 </entry><entry
  align="char">
 <para>Overflow in event queue - one or more events were lost.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="VIDEO_SET_DISPLAY_FORMAT"
 role="subsection"><title>VIDEO_SET_DISPLAY_FORMAT</title>
 <para>DESCRIPTION
 </para>
@@ -1063,32 +959,9 @@ role="subsection"><title>VIDEO_SET_DISPLAY_FORMAT</title>
 <para>Selects the video format to be used.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Illegal parameter format.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_STILLPICTURE"
 role="subsection"><title>VIDEO_STILLPICTURE</title>
 <para>DESCRIPTION
 </para>
@@ -1133,32 +1006,9 @@ role="subsection"><title>VIDEO_STILLPICTURE</title>
 <para>Pointer to a location where an I-frame and size is stored.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>sp points to an invalid iframe.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_FAST_FORWARD"
 role="subsection"><title>VIDEO_FAST_FORWARD</title>
 <para>DESCRIPTION
 </para>
@@ -1200,39 +1050,17 @@ role="subsection"><title>VIDEO_FAST_FORWARD</title>
 <para>The number of frames to skip.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EPERM</para>
 </entry><entry
  align="char">
 <para>Mode VIDEO_SOURCE_MEMORY not selected.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Illegal parameter format.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="VIDEO_SLOWMOTION"
 role="subsection"><title>VIDEO_SLOWMOTION</title>
 <para>DESCRIPTION
 </para>
@@ -1274,39 +1102,17 @@ role="subsection"><title>VIDEO_SLOWMOTION</title>
 <para>The number of times to repeat each frame.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EPERM</para>
 </entry><entry
  align="char">
 <para>Mode VIDEO_SOURCE_MEMORY not selected.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Illegal parameter format.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="VIDEO_GET_CAPABILITIES"
 role="subsection"><title>VIDEO_GET_CAPABILITIES</title>
 <para>DESCRIPTION
 </para>
@@ -1350,25 +1156,9 @@ role="subsection"><title>VIDEO_GET_CAPABILITIES</title>
  information.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>cap points to an invalid iframe.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_SET_ID"
 role="subsection"><title>VIDEO_SET_ID</title>
 <para>DESCRIPTION
 </para>
@@ -1410,24 +1200,9 @@ role="subsection"><title>VIDEO_SET_ID</title>
 <para>video sub-stream id</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINTERNAL</para>
-</entry><entry
- align="char">
-<para>Internal error.</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
@@ -1435,7 +1210,7 @@ role="subsection"><title>VIDEO_SET_ID</title>
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="VIDEO_CLEAR_BUFFER"
 role="subsection"><title>VIDEO_CLEAR_BUFFER</title>
 <para>DESCRIPTION
 </para>
@@ -1468,18 +1243,9 @@ role="subsection"><title>VIDEO_CLEAR_BUFFER</title>
 <para>Equals VIDEO_CLEAR_BUFFER for this command.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_SET_STREAMTYPE"
 role="subsection"><title>VIDEO_SET_STREAMTYPE</title>
 <para>DESCRIPTION
 </para>
@@ -1522,25 +1288,9 @@ role="subsection"><title>VIDEO_SET_STREAMTYPE</title>
 <para>stream type</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>type is not a valid or supported stream type.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_SET_FORMAT"
 role="subsection"><title>VIDEO_SET_FORMAT</title>
 <para>DESCRIPTION
 </para>
@@ -1583,17 +1333,9 @@ role="subsection"><title>VIDEO_SET_FORMAT</title>
 <para>video format of TV as defined in section ??.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
@@ -1601,7 +1343,7 @@ role="subsection"><title>VIDEO_SET_FORMAT</title>
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="VIDEO_SET_SYSTEM"
 role="subsection"><title>VIDEO_SET_SYSTEM</title>
 <para>DESCRIPTION
 </para>
@@ -1645,17 +1387,9 @@ role="subsection"><title>VIDEO_SET_SYSTEM</title>
 <para>video system of TV output.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
@@ -1663,7 +1397,7 @@ role="subsection"><title>VIDEO_SET_SYSTEM</title>
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="VIDEO_SET_HIGHLIGHT"
 role="subsection"><title>VIDEO_SET_HIGHLIGHT</title>
 <para>DESCRIPTION
 </para>
@@ -1705,25 +1439,9 @@ role="subsection"><title>VIDEO_SET_HIGHLIGHT</title>
 <para>SPU Highlight information according to section ??.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>input is not a valid highlight setting.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
+&return-value-dvb;
 
-</section><section
+</section><section id="VIDEO_SET_SPU"
 role="subsection"><title>VIDEO_SET_SPU</title>
 <para>DESCRIPTION
 </para>
@@ -1766,17 +1484,9 @@ role="subsection"><title>VIDEO_SET_SPU</title>
  to section ??.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
@@ -1785,7 +1495,7 @@ role="subsection"><title>VIDEO_SET_SPU</title>
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="VIDEO_SET_SPU_PALETTE"
 role="subsection"><title>VIDEO_SET_SPU_PALETTE</title>
 <para>DESCRIPTION
 </para>
@@ -1827,17 +1537,9 @@ role="subsection"><title>VIDEO_SET_SPU_PALETTE</title>
 <para>SPU palette according to section ??.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
@@ -1845,7 +1547,7 @@ role="subsection"><title>VIDEO_SET_SPU_PALETTE</title>
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="VIDEO_GET_NAVI"
 role="subsection"><title>VIDEO_GET_NAVI</title>
 <para>DESCRIPTION
 </para>
@@ -1889,17 +1591,9 @@ role="subsection"><title>VIDEO_GET_NAVI</title>
  ??.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EFAULT</para>
 </entry><entry
  align="char">
@@ -1907,7 +1601,7 @@ role="subsection"><title>VIDEO_GET_NAVI</title>
 </entry>
  </row></tbody></tgroup></informaltable>
 
-</section><section
+</section><section id="VIDEO_SET_ATTRIBUTES"
 role="subsection"><title>VIDEO_SET_ATTRIBUTES</title>
 <para>DESCRIPTION
 </para>
@@ -1951,17 +1645,9 @@ role="subsection"><title>VIDEO_SET_ATTRIBUTES</title>
 <para>video attributes according to section ??.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
-<para>ERRORS
-</para>
+&return-value-dvb;
 <informaltable><tgroup cols="2"><tbody><row><entry
  align="char">
-<para>EBADF</para>
-</entry><entry
- align="char">
-<para>fd is not a valid open file descriptor</para>
-</entry>
- </row><row><entry
- align="char">
 <para>EINVAL</para>
 </entry><entry
  align="char">
diff --git a/Documentation/DocBook/media/dvbstb.png.b64 b/Documentation/DocBook/media/dvbstb.png.b64
new file mode 100644 (file)
index 0000000..e8b52fd
--- /dev/null
@@ -0,0 +1,398 @@
+iVBORw0KGgoAAAANSUhEUgAAAzMAAAGaCAYAAAA7Jx25AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBI
+WXMAAA3XAAANiQFmEOuiAAAgAElEQVR42uzdd1RU18I28GdgKFZUBE0saFA0KoqFFkEhKhbAQmxJ
+bIkNNEpMEUwsMZarJMZrw4KxRExQczUqil0jRBA1GAjGQqLYC4TemdnfH76cj3HodYDntxaLmTll
+zuw57Zmz9z4yIYQAkYZzcnJCSkoKGjZsyMIgIiIiquPS09PRoEEDyBhmqCaQyWRo06YN3nvvPRYG
+ERERUR137Ngx/Pnnn5CzKKgmMDAwwKpVqxhmiIiIiAj29vZ4//33ocWiICIiIiKimohhhoiIiIiI
+GGaIiIiIiIgYZoiIiIiIiBhmiIiIiIiIYYaIiIiIiIhhhoiIiIiIiGGGiIiIiIgYZoiIiIiIiBhm
+iIiIiIiIGGaIiIiIiIgYZoiIiIiIiGGGiIiIiIiIYYaIiIiIiIhhhoiIiIiIGGaIiIiIiIgYZoiI
+iIiIiBhmiIiIiIiIYYaIiIiIiIhhhoiIiIiIqFLIWQRElSMsLAy2trZo1KgR5HJualTxEhIS8P33
+3+PDDz+sM5+5bdu2ePDgAZo2bcoVgCplm3J0dMS5c+fqzGf++uuvsWTJEm5TVClSU1ORk5ODBw8e
+oHXr1gwzRDVJbm4uAGDRokUwMDBggVCFmzlzJrKysurUZ3727BksLCzg4eHBFYAq3IIFC5CQkFCn
+PnNGRgYAYNWqVVwBqMJFRUVh48aNUCqVlfYeDDNElWzGjBkMM1QpNm7cWOc+c8uWLTFjxgzMmDGD
+KwBVuLt37yIkJKTOfW5nZ2duU1SpYaYysc0MERERERHVSAwzRERERETEMENERERERMQwQ0RERERE
+xDBDREREREQMM0RERERERAwzREREREREDDNERERERMQwQ0RERERExDBDRERERETEMENERERERMQw
+Q0REREREDDNEREREREQMM0RERERERAwzRERERETEMENERERERMQwQ0RERERExDBDREREREQMM0RE
+RERERAwzREREREREDDNEREREREQMM0RERERExDBDRERERETEMENERERERMQwQ0REREREDDNERERE
+REQMM0RERERERAwzRERERETEMENERERERMQwQ0REREREVGnkLAKimunBgwdISkoq8/SGhoZ47bXX
+WJCV6NmzZwgMDMS5c+ewd+9eFgiVSVZWFkJCQnD16lU8evQICoUChoaG6NChA2xsbNCxY0fIZDI8
+efIEp06dwuTJk0s876CgIJiYmKBLly4saKq2Y5Wuri6aNm0KQ0NDaGnxd3ZimCGqE/78808EBgbi
+p59+QkJCgsowLS0tyGQy6blSqYQQQmWcjz/+GGvXrmVBVoKtW7di+/btuHbtGoQQMDQ0ZKFQqf37
+77/w8fHBtm3bkJCQgCZNmsDS0hLGxsZ48OABtm/fjidPnsDU1BR2dnYICwtDz549SxxmlEol5s6d
+CxsbG+zZs4cFTpV2rDpx4gQOHDiAJ0+eqAzT09ODUqlETk4OAEBfXx/dunWDvb093Nzc0LdvX5Vj
+GVFBGH+JaqihQ4di06ZNOHr0qMrrly5dgkKhQG5urvSnVCqRlZWF27dvY8mSJQCA7OxsFmIlmTFj
+Bs6ePctfu6nMTp48iTfffBOrV6+Gnp4e9uzZg+fPn+PUqVPw9/fHkSNH8PDhQxw9ehRCCOzevRu3
+bt1CWlpaqd4jJiYG+/btw+PHj1noVGnHqnXr1uHcuXMqr+/fvx8ZGRnIzs5GSkoKIiIi8M0330BH
+Rwdr166Fvb09evXqhdOnT7MQiWGGqDazsrJSeV5Y1TFdXV107NgRX331FSZPniz9ElbTnDp1SuOX
+USaToXHjxujevTtXUCq1H3/8EcOGDcPz58/RtWtXREREYMKECdDR0VE9gGtpwcXFBdeuXYONjQ0A
+ID09vcTvs2HDBgBATk4OfH19WfBUqTp16gS5/P9XCDI3N5euujRs2BAWFhb46KOP8Ntvv+HIkSNo
+3rw5rl+/DicnJ3z66adQKpUsRGKYIaqNdHR0Sl3HeNy4cTXyysyBAwdq1EkX635TaV29ehVTpkyB
+UqlEw4YNcfToUbRs2bLIaZo0aYIjR47AyMioxFdm7ty5g6CgIGhrawMAtmzZgoyMDH4BVGlkMhl0
+dXVLNJ6rqyvCwsLQqlUrAMB3332Hjz/+mIVIDDNEtfkgURqOjo5YunRpjfqMd+7cwfTp0/llU62l
+VCoxY8YM6arp/Pnz0b59+xJNa2RkBC8vrxJfmfH19YWVlRUmTJgAAIiPj2cnFaRRxypTU1McOnRI
+CtwbNmzA4cOHWYjEMENUl+Xm5iIhIQH6+vowMTEpcJz8HQUIIdQ6DijoBKy0CppnUfN59uwZnJ2d
+S9V7mxCiVMtW2mWqiPckyu/EiROIiIgAAGhra8Pd3b1U00+aNAlZWVnFjpeamoqdO3di9uzZmD17
+tvT6f//732K3d6KqZGlpiRkzZkjPvby8it3HlmY/XNh+v6jtoCTHRU1RlmNSac8BGGaIqEpduXIF
+CxYsUHs9MTERfn5+sLa2xrVr15CSkoJJkyZBX18fbdq0QWRkpMrOLTAwEMOHD4epqSnat2+Pxo0b
+o3///vDz8yu0LU5ubi7Onz8PDw8PmJubS+87d+5cGBoaQi6Xw8LCQq2x5+XLl2Fra4s7d+4AAEJD
+Q+Hi4gIXFxfMnz9fZdzs7Gz4+vrC2toa+vr60NHRQdeuXeHj41PgSV5Zl+lVx44dw8CBA/Haa6+h
+Q4cO6NmzJw4cOFBn17OgoCC1XouoeD/++KP02NbWFkZGRqWa3sjICDt37ix2PH9/f8jlcowdOxaW
+lpawtrYGAERHR+Ps2bP8IjRQaGgooqKi6mTYnDNnjvT41q1buHTpkto4pdn3CyFw7do1eHt7o127
+dkhMTIQQAv7+/rCwsIBcLkfTpk3x8ccfS9Wxc3NzsXnzZvTu3Ru6urqoX78+3n33XbWeRPfv34/x
+48dLx6jFixdLw5KSkjB37lwMHz5cGp6/hkRsbCzmz58vDcv7++KLL5Cbm4vDhw9j7Nix0utz587F
+s2fPylUWZTkH0NTURqTxDAwMxN69e2vUMgcHBwsAIjExsdLfS1tbWwAQAMTdu3cLHW/hwoVi5syZ
+0vMrV66IESNGCF1dXWn63377TfTv31/o6+tLry1YsEAIIUR6eroYPXq00NPTE7t37xY5OTlCCCFu
+374t+vbtKwCIHj16iNjYWJX3PXXqlHBycpLm16JFCxEdHS06duwoHB0dhYuLi6hfv74AIHR0dMQf
+f/whTfvXX3+J06dPC2NjYwFA2NraitOnT4vTp0+L8PBwabynT5+KPn36iOnTp4vIyEjx6NEjcejQ
+IdGiRQsBQPTt21ekpaVVyDLlUSgUYvbs2UIul4stW7aI7OxsIYQQ0dHRwsLCQjRq1EgAEIaGhpXy
+vZubmwtfX1+NW/fzyrRdu3Zi5syZIiAgQDx58qRC5t22bVuN/MwVoVWrVlLZeXp6Vsp7KJVK0bVr
+V+Hl5SW95u/vL72vs7NznT7WeHt7Czs7O41brmnTpgkAwsDAQIwYMUKsX79eREZGCqVSWSGfuaq+
+9wYNGkjr2l9//VXi6dq3by9Nt3jxYpVhpdn3X7p0SYwePVrI5XKV5Rg8eLCwsrIS7u7u4u2335aG
+ff755+LJkyfirbfeEo6OjmLWrFli1KhRQktLSwAQrq6uast67949af6DBw9WGx4dHS0ds18td6VS
+KZYtWya9f+/evVWGr1y5Uujq6oqAgIACv/vSHgdLew5QFpGRkQKA2nlBRQgMDBQGBgaCYYYYZmpZ
+mDl48KAIDQ2V/i5duiTOnj0rvv76a6Grq6sSZtLS0kR2drZ0oAQgnJycxKFDh0RqaqqYOHGiaNKk
+iTh9+rRQKpVi7NixAkCBJ5MpKSmic+fOAoDo1KmTSElJURtn6NChAoDQ19cXlpaWIiIiQhr2xx9/
+SJ9jypQpatOamJgIAGLEiBFqw7Kzs0WfPn3EqFGj1Hbw+/fvlz6bt7d3hS7TokWLBACxZs0atWGP
+Hz+WDtx1Lcw0a9ZMKnMdHR3pwF4R4aa2hpnk5GSpzApbpyrC2bNnhUwmU/nRIzMzU/qxAIC4efMm
+w4yG8fDwkE6gtbS0hJ6eXoWFm5oQZkaOHClNN3r06HLv+xcsWCANs7GxUflhTKlUSu/XoEEDYWlp
+KS5cuKAy/erVq6XpY2Ji1JbX1NS00DCT/3hWULkrlUoxZMgQ6bvOK6f09HTRsWNH8d133xU4z7KU
+RWnOARhmiBhmqizMFPeXP8zk+eGHH6ThX331VYHvcezYMQFANG3aVGRlZRU4zpEjR6T5fPHFF2rD
+P/roI2n4s2fP1Ib369dPCkOlCTNbt24VAMS5c+fUhmVmZkq/MDVt2lS6mlTeZbpx44bQ1tYWhoaG
+hZbH8OHD62SYMTIyKnT9K2+4qa1h5p9//lEpp61bt1bK+4waNarAX5PzgjkAMWvWLIYZDQwz+a8m
+5P8rb7ipCWFmxowZ0nSOjo7l3vdv375dml9YWJjatPv27ZOGb9q0SW34zZs3peG7du1SG96pU6ci
+w0xe2Cms3O/fvy9d2XdychJKpVJMmzZNODg4CIVCUeA05TkOluQcQJPDjJw1UYlql5s3b6o07hdC
+IC0tDZcuXcKHH35Y4DT5718xZMiQAsfJ6xLZysqq0O41hw0bBmNjYzx//hxbt27F0qVLVe4rkNcr
+DQAYGxurTZ/XDWd8fHypPrOfnx8AIDw8HNHR0WrDmzVrhsePHyMhIQE3btxQuf9LWZdp3bp1UCgU
+GDhwYKHl0ahRI66Qr8jfpurevXvYsWMHvv/+e+Tm5qJdu3YYPHgwHB0d0b9//2K7JK7NFApFhc8z
+NjYWhw8fxvHjx9WGzZw5EytXroRCocCuXbuwfPlyNG3alCtsDZB3U+S8dhlHjx7FiRMnkJWVBQMD
+Azg4OGDAgAFwcHBAt27dSt37pSbIv8z5j1dl3ffn3+83aNCg0P1+3jxe1aJFC+nxw4cPK/zztmnT
+Bt988w3c3d1x6tQpTJo0CYcPH0ZUVFShXf6X5zhYknMATcYwQ1TL6OnpQV9fX+W1evXqYfjw4Viw
+YIHUkL4w+Xfy+Q+WFy5cAAA0b968yGn79++PAwcOID4+HtHR0ejRo0eJlz1vJy1K0cg1OTkZ165d
+g7a2dqGNzseMGaP2HuVZJiGE1EVo586dq/Uk5v79+7h27ZpGrYO5ubllDjfff/89tm/fDoVCIYWb
+3r17w9XVtVaHm1eDQ1xcXIW/x5YtW/DGG29g0KBBBZ68ubm54cCBA0hPT8f27dvx+eef18l9aFpa
+msZtUy9evChzuDly5AiCgoKQnZ2Nxo0bw9HREf369YO9vT369OlTI76Tf//9V3r8+uuvV/q+v6Dj
+oMrJc74f6Srr/kzTp0/Hvn37cP78efj7+2Pjxo2F9kJakWVR3GdnmCGqQ4QG9jrz9ttv4+7du6We
+Lj4+XroZX3Enqp06dZIeP3z4sFRhpizu3r0rdT+5Zs2aKtkRv3jxAk+fPgVQvVdfsrOzsWrVKqxa
+tarWbDf516979+5h69atUkifOnVqpVyx0ARNmjSRrmoCQExMTIXOPyMjA35+flAoFCq/yL66nefZ
+sGED5s2bp3LSVlfcuHGjxpzkl/RYlNcrV3JyMg4fPiz9GOPo6CiFA01269Yt6XHv3r2rbd9flbS0
+tODn5wdzc3NkZGTg1KlTmDVrVoFX1mp7WTDMEFWDFy9eYPny5Rq3XD179sTGjRtLPV3+E8i8k/jC
+GBoaSo+rYoeaF7KEELh//36JbzJYHvl/Nc/MzKy271NPTw/ffvttodUHq4uZmVmZryzo6ekhKysL
+enp6sLS0hJOTE/r37w8bGxvo6uoiMDCw1u437OzscPDgQQAvu+KtSAEBAUhNTYWPj0+Rv8quWLEC
+T58+xYMHD3Do0CGVX3Prip49exZYFa86ffbZZ/jhhx9KddUzj46ODpRKJZRKJTp06IChQ4fCwcEB
+ffv2hbGxMRYsWIDExESNPp5GRUVJz11cXKpt31/V0tLSpOPvkSNHsG/fPowfP14jjoMMM0S12Llz
+5zBgwABMnTq11nym5s2bQ0dHBzk5OYiOjoYQotB61/lv0PXGG29U+rLVr19fehwSElIlO3E9PT3p
+8d9//11t34tMJkP9+vU1rm1Daerk6+vrIzMzUyW8ODo6Ftk2q7YaO3asFGbu3LmDqKgo6f5H5SGE
+wIYNGzBmzBjMnTu3yHHj4+Px1VdfAXh5E826GGby7jOiSfLvc4qjq6sLhUIBpVKJjh07YsiQIXBw
+cIC9vX2R1YQ11c6dO6WaDi4uLmjXrl217furUlZWFiZMmIClS5di48aNePToEebMmYMBAwao3YOq
+tpdFcXjTTKIKolQqsXz5cgwYMAAAMHz48Fp1cM+7sV5cXBxu3LhR6Lh59XVbtWqFjh07VvqymZqa
+SifPfn5+RVbvS01NxcyZM8v9nq1bt5YaTF64cIF3TS+FvPZcenp6sLOzwxdffIHg4GAkJycjODgY
+ixYtgp2dXZ0LMgDg5uamchLy3XffVch8L168iIiICEyfPr3YcWfOnCmt25cuXUJ4eDhXWg2nq6sL
+bW1tyGQymJmZwd3dHQcOHMCLFy9w69YtrFu3DqNGjaqRQebx48dSNVpdXV2sXr26Wvf9FaUkx4yF
+CxeicePGmD9/PjZv3iwdfz09PTXiOMgwQ1TLvHjxAoMGDcKSJUsAvLxjcUE9oFTWTjH/1ZDKOrH+
+4IMPpMcBAQGFjpd38uPu7l7qXnOKWva8eeXV/c7TqFEjKWgFBwdjz549BU6fm5uLKVOmwMnJqdzL
+pKenh/79+wN4WVc5KCioyGnrWtjJq/Lwanixt7dneCmCjo4ONm3aJD3ftWsXTp8+XeLpExMT4erq
+qnZX8NWrV8PMzAz29vbFzqNly5YYPXq09Hzt2rXcwWsApVIpVTcqaXjJX+W3Jp3E50lISMDIkSOR
+kJAAANi0aRO6dOlSZfv+8sirYp2enl5gGaSkpBQ5/a+//oqNGzfCz88PWlpacHV1xbvvvgsA+Omn
+n3D06NEqPQ4yzBDVcufPn0fXrl1x8eJFKJVKaGlp4bPPPquy909PT1c5QJSlZ5X8YaiwOtmTJk2C
+paUlAGDz5s0F1rG+ffs2goODYWZmhnnz5qkNL67xdl7PVgUd8PKqfdy+fVsanp2djcePH6v8UjVt
+2jSsX79e6s0HeFllx8XFBdnZ2XBzc6uQZcr/+Tw8PNS650xMTERISAiAl41uU1NT68w2kXcAfzW8
+XLx4keGlGEOHDsWaNWuk525ubiVqJxQaGgpLS0v069dPpdvYK1euICgoCGPGjCnxjwvvvfee9PjA
+gQPVWpWS/v8JsBCixoWXV/e1+dsYFhZshBA4deoU+vTpgytXrkBXVxfbtm3DtGnT1MYt674//zGv
+LMfE4n5AzLvCevnyZdy+fVulDFasWCHtIwu6DUFycjImT56MBQsW4M0335ReX7dunfQdu7u7qx2D
+y3McLMk5AMMMUS2kVCrx9ddfY+DAgYiPj0dubi7kcjnGjx+Ptm3bVtlynDx5UuV5YVcJipK/u+bf
+f/+9wHHkcjkOHTqETp06IT4+HhMmTFD5BT4hIQETJ05EmzZtEBgYWGDf/flPivJ6bcp/QPjzzz8B
+vOxONDk5WWW4ra2tNI/58+fj4MGDeOedd/Dvv/9i3LhxGDdunBQ+PD090bx5c/To0QOmpqYwMzND
+UlIS/P391U7oyrpMw4YNg4eHBwDg/v376NWrF1asWIHAwEBs27YNjo6OMDAwkA4O3bt3r3WX9gtz
+7do1ZGVlMbyU0SeffIJ9+/ahWbNmSE1NhaurK9zc3HDy5EmVX3pTU1MRFBSEd955By4uLli2bJlK
+d8qZmZmYNWuWtP2WVF6bhLyTr3nz5hV78keVa968eYiLi6tR4eVV58+fV1mP9u3bh5iYGPz999/4
+/fffcfjwYSxatAg9evTA4MGDce/ePbi5ueH69euFVpEs674/f2+BBQWK2NhY6XFB1aofPHggPX78
++LHa8LyaDNnZ2bCzs4OXlxe8vb1hbm4OIQQcHBwAAGFhYXj//fdx7Ngx6bxi2rRpUCqV8PLyUpmn
+kZGRVPvj8ePHmDJlikrwKM9xsCTnAJqe9ok0noGBgdi7d6/GLM+TJ0+Eg4OD2h2ZZTKZiIyMFEII
+ERwcLACIxMTESlkGPz8/MWjQoALvCm1nZyc+/fTTYudx5swZ4erqKrS0tKRp9fT0xKRJk8T27dsL
+nCYpKUnMmzdPNGrUSLz++utixowZ4sMPPxQmJibC3d1dxMXFqU0TGhoqxo8fr7KMXbp0EV9++aUQ
+QoiTJ08KJycnleE9e/YU27Ztk+YRGxsrWrduLQ1//fXXxfnz56XhOTk5YsmSJdJdk/P+DAwMxMKF
+C0VGRkaFL5NCoRDffPONaNq0qcp4JiYm4ty5c+L9998XhoaGwsPDQwQHBxd65+ayMjc3F76+vnVq
+X9C2bds685nj4uLEkiVLRNu2bVX2MYaGhqJZs2YCgGjTpo1YtGiR2na3f/9+0blzZ2k6uVwuRo0a
+JY4fP17o+/31119i8uTJol27dmr7lN69e4tffvml1pe5t7e3sLOzq1PblLe3d6F3oq+oY5WTk5PQ
+1dVVW6/y/zVu3Fh06dJFjB07VmzatEk8fPiwRPMvzb7/119/FbNmzRJ6enoq+2tvb28RGxsr/v77
+bzFv3jzRvHlzabiurq7w8PAQFy5cEBkZGeLzzz8X7du3V9m23N3dRWBgoPQ+SqVSLF26VOX43KxZ
+M+n44ezsLNq3by+8vb1FaGioyM3NFcHBweLtt98WAISRkZHw8fFR+Zznzp0TDg4OKp/R1tZWZZsu
+7XGwLOcApRUZGSkAiNjY2ApftwIDA4WBgYGQCbZcpRqgSZMm8PX1Van+UJ2/Lo0ZMwYpKSkq7Tfk
+cjkcHR1x6tQpAC97FLG3t0diYqL0C31tkpWVhT/++ANxcXFo2rQpevToodKjSmVIS0tDWFiY1PNV
+QT38ZGRk4Pr160hISICRkRG6d+9eqp6AyloW169fR1xcHIyNjdGzZ0/I5XLExMTAxMRE5e7KFal7
+9+7w8PCQrhDVBSYmJvD29q5Tn1kIgdu3b+PPP/9EXFwclEoljI2N0bVrV3Tq1KlG3tFdUy1YsAAh
+ISEIDg6uU585Kiqqxnd7Xh37/uK8ePEC169fR7169dCnTx+pDeE///yDdu3alfomzjWxLKKiotC9
+e3fExsZWeK2VY8eO4f3332fXzEQlpVAosGzZMixbtky6HPzq8C+++KLOlIeenh6srKyq9D0bNGgg
+9RZXmHr16klV0qqyLPIaX+bXoUMHbjhUbjKZDJ06dVK5IS0RVf++vzhGRkYYNGiQ2uuVfdsCTSyL
+ysQwQ1QCT58+xZgxYxAWFlZg3XEtLS1YWFhI9WCJiIiIqPKxAwCiYpw5cwbdunVDeHh4kb18LFy4
+kIVFRERExDBDVP0UCgUWL14MJycnJCQkqN3fJI9MJoOJiQlGjBjBQiMiIiKqQqxmRlSAR48eYfz4
+8QgLC5P69y+MtrY2vvjii0pryEdEREREDDNEJXLq1CkMHjwYurq6Jbp5lIGBASZNmsSCIyIiIqpi
+/CmZKB8hBPbv3w8AhVYry09XVxdeXl68ISARERERwwxR9ZLJZNi+fTvWr18PLS2tYquO6ejoYMaM
+GSw4IiIiIoYZIs0wZ84cnDlzBo0aNSr0hoe6urr46KOPauUNMYmIiIgYZohqMEdHR4SGhkJbW7vA
+O2wrlUp4enqyoIiIiIgYZog0z6pVq9CsWTO4uLhAW1tbel1XVxeTJ0/Ga6+9xkIiIiIiYpgh0izr
+1q1DQEAA/ve//+Hw4cNYvnw5tLS0IJPJkJ2dDS8vLxYSEREREcMMkWa5cOECPvvsM/j6+sLGxgYy
+mQze3t4IDAyEEAI2Njbo2LEjC4qIiIioGvE+M0SvuH//PsaOHYtp06Zh6tSpKsOGDh2KW7duISsr
+iwVFRERExDBDpDnS09Ph5uYGMzMzrFu3rsBxzMzMWFBEREREDDNEmsXDwwNPnz7F1atXeSNMIiIi
+IoYZopohr8H/r7/+ipYtW7JAiIiIiBhmiDRfXoP/LVu2wMbGhgVCREREVAOwNzOq84pq8E9ERERE
+DDNEGqkkDf6JiIiISDOxmhnVaWzwT0RERFQLwsz333+P77//Hg0aNGCpUIVTKBTIycnB//73Pxgb
+G2vEMrHBPxEREVEtCTMxMTEIDQ2Fl5cXS4UqXFRUFM6fP4/MzEyNWB42+CciIiKqRWEGAJydnbFq
+1SqWClVKmDl+/LhGLAsb/BMRERHVDuwAgOoUNvgnIiIiqj3YAQDVKWzwT0RERMQwQ1TjsME/ERER
+EcMMUY3DBv9EREREtQ/bzFCtxwb/RERERAwzRDUOG/wTERER1V6sZka1Ghv8ExERETHMENU4bPBP
+RERExDBDVOOwwT8RERFR7cc2M1TrsME/EREREcMMUY3DBv9EREREdQermVGtwgb/RERERAwzRDWO
+pjb4X716NQwMDPgFUYWLioqqc5/54cOHWL16NZKTk7kCUKXsr83Nzevc5z527BhWr17NFaAYycnJ
+uH//Ptq1a4eGDRuyQDTkOMUwQ7WCJjb4b9iwIUxMTHDixAloabFGJ1W8Nm3awMjIqE59ZkdHR9y/
+fx8HDhzgCkAVrl27dujZs2ed+sytWrVCmzZtuE29QqlUIi0tTeUvJycHMpkM+vr66NKlCwupBLKz
+s2FqalqptWUYZqjG09QG/xYWFrh37x6/IKIKdObMGRYCUQX66KOP8NFHH9XpMlAoFIiOjkZ4eDgu
+X76My5cv48aNGxBCoHPnznBycoKVlRVsbGwQFRWFhQsX4urVq1x5NATDDNVobPBPREREpfHo0SMp
+tFy+fBnXrhOJlUQAACAASURBVF1DamoqWrZsCWtra4wfPx42Njbo06cPGjdurDLtjRs3WIAMM0QV
+hw3+iYiIqDCpqam4evUqwsPDERYWhvDwcDx69Aj169dH7969YWVlhdmzZ8Pa2hpt27ZlgTHMEFUd
+TW3wT0RERFWvuOpi1tbWWLhwIWxsbNCtWzfI5TwNZpghqiaa2OCfiIiIqk55qosRwwxRtdHUBv9E
+RERUOVhdjBhmqFZgg38iIqLajdXFiGGGai02+CciIqpdWF2MGGaoTjhx4gT27dvHBv9EREQ1FKuL
+EcMM1Um5ubn48ccfsXXrVjb4JyIiqgFYXYwYZojwssF/eno63n77bTb4JyIi0lCsLkYMM0SvyGvw
+r6WlhUmTJrFAiIiINACrixHDDFEJeHh44NmzZ2jQoAEvPxMREVUDVhcjhhmiMli3bh0CAgLw66+/
+YsiQISwQIiKiKlCS6mLW1tawtLRkdTFimCEqyIULF/DZZ59hy5YtbPBPRERUSVhdjBhmiCrY/fv3
+MXbsWEybNo0N/omIiCoIq4sRw0wVCAoKgomJCbp06cJvpw7Ka/BvZmaGdevWsUCIiIjKiNXFiGGm
+iimVSsydOxc2NjbYs2cPv506KK/B/5UrV6Crq8sCISIiKgFWFyOGGQ1w8uRJxMTEIDY2FqtXr8br
+r7/Ob6gOyd/gv2XLliwQIiKiAigUCty4cUPlqgurixHDjAbYsGEDACAnJwe+vr5Yvnx5lb7/qVOn
+4OTkxLWiGrDBPxERUcFYXYyoBoSZO3fuICgoCNra2lAoFNiyZQu+/PJL1KtXr0re/8CBA9i7dy/D
+TDVgg38iIqKXWF2MqIaGGV9fX1hZWeHNN9/E7t27ER8fj71792LatGlVEqSmT58OBwcHrhFVjA3+
+iYiormJ1Mc329OlThISEYPTo0UWOFxMTg3/++Yc/iNflMJOamoqdO3di/fr1UpgBgP/+97+YOnUq
+ZDJZieclhFAbX6lUQktLq8Dxnz17BmdnZyQlJZVqmYUQEEIUOt/yLFNFTfvqfACUqiyrAhv8ExFR
+XcHqYjXLzZs3MW7cOMTFxaFp06aFjrdnzx4cPXqUYaaaaGnCQvj7+0Mul2Ps2LGwtLSEtbU1ACA6
+Ohpnz54tdvrc3FycP38eHh4eMDc3BwAkJiZi7ty5MDQ0hFwuh4WFBU6fPq0y3eXLl2Fra4s7d+4A
+AEJDQ+Hi4gIXFxfMnz9f7X2ys7Ph6+sLa2tr6OvrQ0dHB127doWPjw+ysrIqZJnKO21+V69excSJ
+E2Fvb4/Bgwejbdu26N27N3bs2CGFm+qU1+D/wIEDbPBPRES1SmpqKi5cuAAfHx+4ubmhdevWaN26
+NSZOnIjQ0FD06dMHO3bsQGxsLJ48eYJffvkFX3zxBQYMGMAgoyFsbGygq6uLkJCQIse7cOECHB0d
+WWDVRfwfb29v4ezsLKqaUqkUXbt2FV5eXtJr/v7+AoAAUOwynTp1Sjg5OUnjt2jRQkRHR4uOHTsK
+R0dH4eLiIurXry8ACB0dHfHHH39I0/7111/i9OnTwtjYWAAQtra24vTp0+L06dMiPDxc5X2ePn0q
++vTpI6ZPny4iIyPFo0ePxKFDh0SLFi0EANG3b1+RlpZW7mUqz7T5bdq0SchkMuHp6SkUCoUQQoi0
+tDRhZ2cnAIgVK1ZU6fccGRkpAIjY2FghhBDnz58XcrlcbN++vUTTGxgYiL179woiIiJNk5ubKyIj
+I4Wfn5+YNm2aMDc3F9ra2kJLS0t06dJFfPDBB2Lz5s0iIiJC5OTksMBqkH79+olPPvlEer53717R
+tm1b6Xl6errQ09MTR44cYWFVscDAQGFgYCCqPcycPXtWyGQycffuXem1zMxMKWAAEDdv3ix2PkOH
+DhUAhL6+vrC0tBQRERHSsD/++ENoa2sLAGLKlClq05qYmAgAYsSIEQXOOzs7W/Tp00eMGjVKKJVK
+lWH79++XltPb27vClqk80z548EAafurUKZVhAQEBAoBo1KiRyMrKqpYwExsbK4yMjIS7u3uJp2eY
+ISIiTfHw4UPxv//9T8yfP1/0799fNGzYUAAQLVu2FCNGjBArVqwQZ86cEUlJSSysGm7x4sWiZ8+e
+hYaZ8+fPC21tbZGQkMDCqqYwU+3VzDZu3AgXFxe0a9dOek1PTw8zZ86Unq9fv77Y+ZiamgIAMjMz
+ERgYCAsLC2lY9+7d0bdvX6kqWWnt3LkTV69exZw5c9TanAwfPhz6+voAgK1btyI3N7dClqk8096+
+fRsKhQIAEBcXpzLM2NgYAJCSkoK7d+9W+fedkZHBBv9ERMTqYlQjODo64o8//kBCQkKBw8+fP4/u
+3bujSZMmLKxqUq0dAMTGxuLw4cM4fvy42rCZM2di5cqVUCgU2LVrF5YvX15k4yttbW21E/b8WrVq
+BQCIj48v9XL6+fkBAMLDwxEdHa02vFmzZnj8+DESEhJw48YNdO/evdzLVJ5p+/Xrh08//RRZWVkY
+OXKkyrD8Yay0nR5UhC+//JIN/omISCOxdzF6lY2NDXR0dBASEgJXV1e14WwvU8fDzJYtW/DGG29g
+0KBBBZ6su7m54cCBA0hPT8f27dvx+eefl/m98nr/EqVs+J6cnIxr165BW1sbT548KXCcMWPGqL1P
+ZS5TcdPK5XJ8++23Kq+lp6cjICAAO3bskF5TKpVV/p0fOXIEFy9eZIN/IiKqduxdjIqjr68Pa2tr
+XLhwQS3MZGRk4PLly/jss89YUHUxzGRkZMDPzw8KhUK6kvGq/FcdNmzYgHnz5lX5ryB3796FEAJK
+pRJr1qxRuWJSE9y7dw/r16/HrVu3MHXqVCxZsqRauw5csWIFbGxsuOUREVGV4s0oqawcHBxw9OhR
+tdcvX76M3Nxc2Nvbs5DqYpgJCAhAamoqfHx8iryasWLFCjx9+hQPHjzAoUOHVK6CVIW0tDQAL6+A
+3L9/H+3bt68RX2xaWhoWLFgAf39/+Pr6Ys2aNZDJZLhw4UK1Ltft27dx//59HiiIiKjSsLoYVSRH
+R0csX74ciYmJKq+zvUwdDjNCCGzYsAFjxozB3Llzixw3Pj4eX331FYCXN9Gs6jBTv3596XFISEiN
+CDNJSUlwdHREREQEgoKCMGTIEI1Ztl69esHExASTJk2Cn58f280QEVG5sboYVaa8djPBwcEqr7O9
+jGaolt7MLl68iIiICEyfPr3YcWfOnAkdHR0AwKVLlxAeHl6ly2pqaio1mvfz8yuyfUtqaqpKL2zV
+ZeXKlYiIiICJiYlGBRkAcHZ2BgD88MMPePPNN3HixAluhUREVGLsXYyqWv52M3ny2ss4ODiwgOpi
+mFm9ejXMzMxKVMewZcuWGD16tPR87dq1ZXrPokJIXljJzs5WG9aoUSNYW1sDAIKDg7Fnz54C55Gb
+m4spU6aUqj1KWRr+l2TavN7h9PT01Ibl5ORU+0oXFRUF4GV7JGdnZ4wcORL//PMPt0YiIlKhUCgQ
+FRWF7du3Y/r06VKVngEDBmD37t1o0qQJFi5ciIiICCQlJeHixYv49ttvMWbMGFZnpgrl4OCA8+fP
+S8/DwsLYXqauhpkrV64gKCgIY8aMUbtnS2Hee+896fGBAwfw999/F7jDK0reSXxBISCvy+fbt29L
+w7Ozs/H48WMAgKenpzTutGnTsH79emRlZUmv3blzBy4uLsjOzoabm1uFLFN5ps3rpezOnTv4888/
+pdczMzOxe/dulV8VyhuqyqJbt2745JNPYGBgAF1dXcTExKBbt2746quvpGUiIiLNdP36ddy5c6dS
+5v3o0SMcPHgQXl5ecHBwQJMmTdC9e3csWrQIL168wPjx43Hy5EkkJCQgOjoaO3bsgLu7OywsLNju
+hSpV3v1m0tPTAbysYtajRw+2l6lrYSYzMxOzZs0CgFLtdPLfUFOhUGDevHlq3QrnDzjPnz9XGSaE
+kE7qk5KSkJycrDLc1tZWmsf8+fNx8OBBvPPOO/j3338BAOPGjcO4ceOkEOHp6YnmzZujR48eMDU1
+hZmZGZKSkuDv768S0MqzTOWZNu/qkBACgwYNwsKFCzF79mz06NEDXbt2lcZbtWoVlixZgh9++KHK
+V7wlS5ZAX18fPXr0wN27dzFr1ixs3rwZXbp0waFDh7hlEhFpmN9//x0jR45Er169EBAQUO75sboY
+1SR57WZu3rwphRlWMdMQ4v94e3sLZ2dnUVn2798vOnfuLAAIAEIul4tRo0aJ48ePFzrNX3/9JSZP
+nizatWsnTZf317t3b/HLL7+I0NBQMX78eJVhXbp0EV9++aUQQoiTJ08KJycnleE9e/YU27Ztk94n
+NjZWtG7dWhr++uuvi/Pnz6ssS05OjliyZIlo1KiRyrwMDAzEwoULRUZGhjRueZapIj5PUlKScHBw
+UBnH2dlZxMTECIVCIczNzaXXR40aJdLT00Vli4yMFABEbGys9NquXbuEvr6+mDx5sqhfv744dOiQ
+mDt3rpDL5WLIkCHi1q1b0rgGBgZi7969goiIqtaVK1eEq6urkMlkwsnJSYSEhJR6Hrm5uSIyMlL4
++fmJadOmCXNzc6GtrS20tLREly5dxAcffCA2b94sIiIiRE5ODgudNFK/fv3EsGHDRJs2bYSenp44
+cuQIC6UaBQYGCgMDAyET/1fHaMGCBYiKikJgYGCdDHVpaWkICwuDnp4eLC0tC2xvArysmnX9+nUk
+JCTAyMgI3bt3L3Tcag6piIyMxJMnT/Dmm2/CxMREGpaSkoLQ0FA0b94cPXv2LHF1v/KIiopC9+7d
+ERsbK9VjFkLA3t4eTZo0QYcOHeDn54fDhw+jRYsWmDNnDkJDQ/HJJ5/gyy+/ROvWreHr66tS5ZCI
+iCpPeHg4vv76axw7dgxDhgzB4sWLpZoMxSmudzErKyv2LkY1zpIlS+Dv74/U1FTEx8cjLi6O1cyq
+0bFjx/D++++DFUz/T4MGDTBgwIBix6tXr16Jd+bVSSaToUePHujRo4fasEaNGlXrjTPzL+PGjRvR
+p08f/PLLLwCAESNG4PDhwzh//jwCAgLw6aefwt/fXyM6LiAiqgvCwsLw9ddfIygoCMOGDUNYWJjU
+EU5BeDNKqivy7jfToEEDtpfRIAwzVK0sLCwwY8YMzJs3D5GRkSqB5t1334Wrqyu+/vprfPPNN1i+
+fLlaux8iIqoYv/32G77++mucPn0azs7OCA8Ph6Wlpco4vBkl1WXW1taQy+VISUlhexmGGaL/b9my
+Zfj555/x7bffSl1v5wWagQMHwsfHB1u2bIFcLoeFhQXmzJmDxYsX8xcRIqIKEBwcjKVLl+LcuXNw
+dXXFlStX0Lt3bwBFVxezsrLizSipTqlXrx7Mzc1x7do1hhmGGaL/z9DQECtXroSnpycmT55cYKDR
+0tKCt7c39PX1MW/ePAQEBGD9+vUq9yAiIqKS+/XXX7F06VJcuHABI0eOREhICLKzs3H27FmsWLGC
+1cWICtC8eXMA4P1lGGaIVH344YfYunUrPv30Uxw4cEAt0ORxc3PD0KFDsXLlSrXuuYmIqHjnz5/H
+0qVLERwcjF69emHUqFG4c+cO+vXrx+piRMXw9vbGixcvWDuEYYZIlZaWFjZs2IC+ffvi1KlTcHJy
+Ugk0+Xtcq1evHpYtW8ZCIyIqhb1792LChAkAAG1tbSiVSsTGxsLIyAgjR47E2rVrWV2MqBjW1tYY
+PHgwC4JhhkidjY0NPvzwQ3h6eiIyMhI6OjpSoFm/fr10o9Ca4s8//8TEiRPRrFkzaGlp8QumCvf8
++XMsX74crq6udeYzv/POO3j48CFPuEshOTkZMTEx0o2ggZcN+QHgxYsXCAoKQlBQEJYtWwaZTCZd
+hcn7r6Ojo/JcLpdDJpNBW1sbLVq0gKGhYa0pq3///RdvvfUWNmzYUGfWj++//x7r16+HsbExN5YS
+ysrKwqBBg1gQJZCdnY309HQcO3as0tYxhhnSKCtXroSZmRnWrVuHzz77DDKZDGvXrsWWLVuwZs0a
+vP322xg4cGCN+CyJiYm4fv063N3dYWBgwC+XKtzq1avx8OHDOvWZDx48iMaNG8PDw4MrQCk4OjpK
+ISYnJ0f6r1QqkZ2drfZfCIGsrCzpf94JHABkZmZK/9u3b4+OHTvWqm0qOzu7Tq0bMTExiIyMhJeX
+FzcUqnBRUVG4ePGitN9gmKFaz8jICEuXLsWXX36Jd999F61atYJMJoO+vj5sbW1VOgWoKVatWsUw
+Q5Xi+PHjde4zt23bFt7e3gwzVClkMhlCQkLq3Od2dnbGqlWruAJQpYSZyj5Wse4LaZzZs2ejQ4cO
+mD9/vsrrEyZMwPTp0zFixAicOXOGBUVERERUxzHMkMbR1tbG+vXrERAQgODgYOn1vCpnDDRERERE
+BLCaGWkoe3t7zJw5E8+ePVN5PS/QAKiRVc6IiIiIiGGG6gBfX98CX2egISIiIiKGGaqxGGiIiIiI
+iGGGGGiIiIiIiGGGiIGGiIiIiBhmiBhoiIiIiIhhhhhoiIiIiIhhhoiBhoiIiIgYZogYaIiIiIiI
+YYaIgYaIiIiIYYaIgYaIiIiIGGaIGGiIiIiIiGGGiIGGiIiIiBhmiIGGiIiIiBhmiBhoiIiIiIhh
+hoiBhoiIiIgYZogYaIiIiIgYZogYaIiIiIiIYYaIgYaIiIiIGGaIGGiIiIiIGGaIGGiIiIiIiGGG
+iIGGiIiIiBhmiBhoiIiIiIhhhoiBhoiIiIhhhoiBhoiIiIiqNcxcuHABZ86cYalQhYuKimKgISIi
+IqLKCzNpaWkYNGgQS4XqPAYaIiIiohoUZv7zn//gP//5D0uEiIGGiIiIqGaFGSJioCmMEALh4eE4
+ceIEnj17BmNjY1haWuLtt99GvXr1kJiYiJ9//hnTpk2Tpnnw4AGSkpLK/J6GhoZ47bXXih0vKysL
+ISEhuHr1Kh49egSFQgFDQ0N06NABNjY26NixI2QyGZ48eYJTp05h8uTJXLGpWgUFBcHExARdunTR
+mGV69uwZAgMDce7cOezdu1dl2L179+Dh4QEDAwNs3boVBgYG/BKpytbLFy9eFDq8adOmaNWqVYHH
+rOjo6AKnad++PRo0aFBh63ZR2w4xzBAx0GiAFy9eYNKkSThx4gSaN28OW1tb3L9/H76+vsjKyoKL
+iwsePnwIuVyuEmb+/PNPBAYG4qeffkJCQoLKPLW0tCCTyaTnSqUSQgiVcT7++GOp3Avy77//wsfH
+B9u2bUNCQgKaNGkCS0tLGBsb48GDB9i+fTuePHkCU1NT2NnZISwsDD179mSYoWqlVCoxd+5c2NjY
+YM+ePdW+PFu3bsX27dtx7do1CCFgaGioNs6aNWtw4sQJAICtrS08PT35RVKV+Oeff+Dn54ddu3ap
+HCM6deqE8ePHo1+/foWGmaCgIPz22284fPgwAMDAwACzZs3CRx99JIWZ8qzbJdl2qIoIohrAwMBA
+7N27t1qXQalUCk9PT1G/fn1x+vTpYscPDg4WAERiYmKNLfeMjAxhYWEhAIjJkyeLjIwMaVh2drbY
+vHmzqFevngAgOnfuXOA8QkJCBADpLyQkpMDxsrKyxO3bt8WSJUsEADFr1qxCl+vEiRPC2NhYABAt
+W7YUe/bsEdnZ2SrjKBQKcfToUfHGG29I7+3q6lqrtgtzc3Ph6+tbp/YFbdu2rdGf+fjx4wKA0NHR
+EY8ePar25VEqlSIpKUl07dpVABCGhoZq42zbtk0AEDKZTJw9e7ZWr1/e3t7Czs6uTm1T3t7ewtnZ
+WaOX0cfHR+U48tNPP5V42i5duggA4sSJExW6bpdk2yEhIiMjBQARGxtb4fMODAwUBgYGQotxjqh0
+V2imT5+OESNG1Ime/7Zt24br16+jSZMm2Lx5M/T19aVhOjo6cHd3x5kzZ1CvXj08evSowHlYWVmp
+PC/oVzQA0NXVRceOHfHVV19h8uTJyMnJKXC8H3/8EcOGDcPz58/RtWtXREREYMKECdDR0VG7+uPi
+4oJr167BxsYGAJCens4VmarVhg0bAAA5OTnw9fXViP1a48aN0b1790LHmT59Oi5fvoyoqCi8/fbb
+/BKpys2bNw9vvvmm9DwkJKSkP9gjLi4OdnZ2GDx4cIWu2yXZdqhqMMwQMdAU6siRIwAAU1NT1KtX
+r8Bx3nrrLXzzzTdISUlBSkqK2nAdHR1oaZVuVzNu3DhkZ2ervX716lVMmTIFSqUSDRs2xNGjR9Gy
+Zcsi59WkSRMcOXIERkZGSEtL40pM1ebOnTsICgqCtrY2AGDLli3IyMjQjJOBYrZRKysrdO3alV8i
+VQu5XI7FixdLz/39/Uu0Pw8PD8fz58/x0UcfVdq6XdrjGzHMEDHQVKHHjx9LJ2FFXdWYPn06WrRo
+IY1fUJmVhqOjI5YuXarymlKpxIwZM6QrNvPnz0f79u1LND8jIyN4eXnxygxVK19fX1hZWWHChAkA
+gPj4eDYYJiqh0aNHw8TEBACQlJSEHTt2FDvN999/j+bNm2PkyJEsQIYZIqqLgaZJkyYAgOTkZCxY
+sKDQ8XR1dTFp0iT8+++/5X7PFy9eQF9fXzpo5Tlx4gQiIiIAANra2nB3dy/VfCdNmoSsrCyuvFQt
+UlNTsXPnTsyePRuzZ8+WXv/vf/+r1vlFVRBCQKlUlmm6kirL/IkKI5fL8fHHH0vP165dC4VCUej4
+KSkp+PHHHzF58mTo6elV2Lpd1m2nPNNyW2KYIWKgKaP8N9Fdv349Pv744wKrfwGAj48PbG1ty/V+
+SqWy0J7ifvzxR+mxra0tjIyMSjVvIyMj7Ny5kysuVQt/f3/I5XKMHTsWlpaWsLa2BgBER0fj7Nmz
+RU67f/9+jB8/Hi4uLnBxcVGpbpOUlIS5c+di+PDh0vBXr2rmd+zYMQwcOBCvvfYaOnTogJ49e+LA
+gQNFvn9KSgp++OEHDB48GOvWrSvyRC0wMBDDhw+Hqakp2rdvj8aNG6N///7w8/MrtB0cUUlNnTpV
+6j757t27Uk9lhR0z0tLSMH369HKv22XddgAgOzsbvr6+sLa2hr6+PnR0dNC1a1f4+PgU+gMbt6XS
+p0Qi9mZWCb2c1YbezOLi4sRrr72m0ouMhYWFCA8PL9V8tLW1penv3r1b6HghISHCxMSkwGGtWrWS
+5uHp6cmNgr2Z1RhKpVJ07dpVeHl5Sa/5+/tL63NJepK6d++ekMvlAoAYPHiw2vDo6GhpOytofgqF
+QsyePVvI5XKxZcsWqfe/6OhoYWFhIRo1aqTWI1N0dLQYO3as0NfXl5b1m2++KXD50tPTxejRo4We
+np7YvXu3yMnJEUIIcfv2bdG3b18BQPTo0aNSejRib2a1vzez/D7//HNpfezbt2+h21zPnj1Fv379
+ChxemnW7LNtOnqdPn4o+ffqI6dOni8jISPHo0SNx6NAh0aJFC2n509LSauW2VJW9mTHMEMNMJQWa
+2hBmhBDi999/F82bN1cJNADExIkTxcOHD0sdZg4ePChCQ0NV/n799VexZcsW0a5duwLDTHJyssp7
+r1mzhhsFw0yNcfbsWSGTyVSCfGZmptS9OABx8+bNYudjampaaJgRQggTE5NCw8yiRYsK3XYeP34s
+GjRooHZClpqaKjIzM8Xu3buLPOFTKpVi7NixAkCB301KSoro3LmzACA6deokUlJSGGYYZsrswYMH
+UrAHIMLCwtTGuXLligAg/P39C5xHSdftsm47Qry8fUGfPn3EqFGjhFKpVBm2f/9+6X29vb1r5bZU
+lWGG1cyIWOWsSD179sS1a9fUuq3cs2cPOnfujG3btpWqHr2bmxtsbW1V/vr37w93d3fcu3evwGni
+4uJUnjds2JArHdUYGzduhIuLC9q1aye9pqenh5kzZ6pU4yyOXC4v0/C//voLK1euhKGhYYG9Or32
+2msYMGCA2usNGjSAnp4e7O3ti3zfoKAg7N+/H02bNsXUqVPVhjds2BA+Pj4AgFu3buE///kPVwoq
+s9atW2PcuHHS8++++05tnK1bt6Jp06Z45513CpxHSdftsm47ALBz505cvXoVc+bMUesEZ/jw4dKt
+DrZu3Yrc3FxuS+XAMENUSYHm6tWrteaztW3bFmfOnMG+ffvwxhtvSK+npqZi5syZRd4X5lU3b95E
+RkaG9Jeeno6kpCRcvXoVffv2LdE8imr0SaRJYmNjcfjwYZVG/3lmzpwpddO8a9cuJCQkVMoyrFu3
+DgqFAgMHDoSurm6B4zRq1KjQ6V+9h9Or8u6XY2VlVej8hw0bBmNjY7WTN6Ky+OSTT6THP//8M2Jj
+Y6XnycnJ+OmnnzBx4kSVe6OVZd0uz7bj5+cH4GX30Bs3blT58/PzQ7NmzQAACQkJuHHjBrclhhki
+zQs0RfX+VVM/29ixY3Hjxg0sXbpU5VfgPXv2YPLkySW6QqOnpwd9fX3pr169emjcuDF69+6NzZs3
+FzhN06ZNVZ6/eqWGSFNt2bIFb7zxhkpnGnlatWoFNzc3AC9v6Lp9+/YKf38hhNRIunPnzhU+f6VS
+iQsXLgAAmjdvXuh42tra6N+/P4CXXVJHR0dz5aAy69WrFxwcHKR1MP+VzZI0/K/sbSc5ORnXrl2D
+trY2njx5gpiYGLW/MWPGwNPTE56entDS0uK2VA5ybhJElRNoHj9+XKKeTmoaPT09LF68GEOGDMGI
+ESPw9OlTAMBPP/2EUaNGYcyYMWWed7du3dCqVSu115s0aQJjY2M8f/4cABATE8MVjTReRkYG/Pz8
+oFAoCr1LeHx8vPR4w4YNmDdvXrHVyUrjxYsX0jZa1NWXsoqPj5duXljcL8SdOnWSHj98+BA9evTg
+SkJl9umnn0on/35+fliyZAkaNWqErVu3wtbWFt26dau2befu3btSN8xr1qyRrsAW937clhhmiDQq
+0MyZM6dGh5nU1FQ0aNCg0BteWllZITg4GLa2ttKVEl9f33KFGZlMht9++63AYXZ2djh48CAAIDQ0
+lCsZDE9QJwAAGAdJREFUabyAgACkpqbCx8enyLuEr1ixAk+fPsWDBw9w6NChcm1Dr8p/FTMzM7PC
+P2P+Kp95J36FMTQ0lB6X5OSOqCjDhg1Dp06dcOvWLaSkpGD79u2wt7fH9evXK6Qb/vJsO3mhRAiB
++/fvl+gGz9yWGGaINDLQ1GTu7u6YNWsW3nrrrULH6dChA3x8fPDhhx8CAP74448KXYaHDx/CyMgI
+enp6GDt2rBRm7ty5g6ioKJibm3NFI40khMCGDRswZswYzJ07t8hx4+Pj8dVXXwF4eRPNigwz+W8W
++Pfff1f452zevDl0dHSQk5OD6OhoCCEK3fflv/Ff/rZ3RGWhpaWFTz75ROpIY926dYiMjETjxo0r
+ZBsqz7ZTv3596XFISEiJwgy3pXKsC9wciKiwoLJ8+fJix8t/o8yS3GW5pJKSkmBpaSldbndzc1M5
+IBTUgw2Rprh48SIiIiJKVG9/5syZUkPkS5cuITw8vMwB6lWtW7eW5n3hwoVS9TxYEnK5XLoBaFxc
+nNSQuSBPnjwB8LKtUMeOHbmSULlNnDhRal9y//597N69GxMmTECDBg3KPe/ybDumpqZSEPHz8yty
+2ryOdLgtMcwQUSWEmaCgoCLvsAy8bBeQx8bGpsQnWcVZtGgROnfuLB2UdHR0sGnTJmn4rl27cPr0
+6RLPLzExEa6urnj27Bm/XKp0q1evhpmZWbFdvwJAy5YtMXr0aOn52rVrCxwvrzpJenp6gdtYSkqK
+2ut6enpSY+G7d+8iKCioyG20oG21uO33gw8+kB4HBAQUOl5eSHN3d6/xV65JM9SrVw+zZs1Sea00
+Df+LWrfLs+00atRICibBwcHYs2dPgdPm5uZiypQpcHJy4rbEMENElRFm8nauRf1ClL9dUP7uMvNk
+ZmaqXBIv7sQor3rOhg0b1HqAGjp0KNasWSM9d3NzQ2BgYLGfJTQ0FJaWlujXrx9atGjBL5cq1ZUr
+VxAUFIQxY8aU+ETjvffeU9mmCqrWkndl8vLly7h9+7b0ukKhwIoVK6SQk79TAQCYN2+e9NjDwwMP
+Hz5UC/ohISEAXvbClJqaqjI8f7frBTVMnjRpEiwtLQEAmzdvRmJioto4t2/fRnBwMMzMzFSWh6i8
+Zs2aJdUK6NOnDywsLEo8bXHrdnm2HU9PT+nxtGnTsH79emRlZUmv3blzBy4uLsjOzpZ6NeS2xDBD
+RJUQZhISEmBnZ4effvpJpYGiUqnEjh07pBt4LV++vMBfoV8NGzt27EBYWBhiYmJw79493L17Fzdv
+3sTFixexadMm2NvbS20MBg4cqDa/Tz75BPv27UOzZs2QmpoKV1dXuLm54eTJkyq/WKempiIoKAjv
+vPMOXFxcsGzZMnz++ef8YqlSZWZmSr8Ul6ZXsvw31FQoFJg3b57KjwB5PywAQHZ2Nuzs7ODl5QVv
+b2+Ym5tDCCF1VRsWFob3338fx44dA/CyobSHhweAl1VxevXqhRUrViAwMBDbtm2Do6MjDAwMpBO6
+7t27q9zQM/+PGbdu3VJbdrlcjkOHDqFTp06Ij4/HhAkTpAbQefuQiRMnok2bNggMDKyQKkBEeVq0
+aIGJEycCAGbMmFGqaYtbt8uz7YwbN066uWdOTg48PT3RvHlz9OjRA6ampjAzM0NSUhL8/f2lHz24
+LZWRIKoBDAwMxN69e2vUMgcHBwsAIjExsUaWuVKpFAYGBmLJkiXCy8tLmJmZiRYtWoghQ4YIV1dX
+0bZtWwFAmJqaip9//lltej8/PzFgwAChra0tAJT6z8DAQOTm5ha6fHFxcWLJkiXScgAQMplMGBoa
+imbNmgkAok2bNmLRokUiLi6uVm4X5ubmwtfXt07tC9q2bauxn3n//v2ic+fO0vool8vFqFGjxPHj
+xwud5q+//hKTJ08W7dq1U9sGevfuLX755ReVbXLp0qVCLpdL4zRr1kxs27ZNCCGEs7OzaN++vfD2
+9hahoaEq249CoRDffPONaNq0qcp7mJiYiHPnzon33/9/7d1/dNV1/cDxF9vdxgZzTn4VET/q2DIC
+A9EgEaxOBxI9kOmRUA6dOqEQET+UMDrQOXKC6mQHS4qAlHM8mgdPHTMMzBN4GHFU1CUJyVkonFJ+
+jDMYsrGN7dMfftnXxa8pG9y7PR5/7W73fnbv+3Mv7LnPfX12e9KtW7dk2rRpyebNm5OGhoZk06ZN
+yYwZM5Lu3bs3e41NnDgxeeyxx055LEeOHElmz56dFBYWJr17906mTp2afOMb30j69euX3HXXXRnx
+Opw/f34ycuTIDvWamj9/fjJu3LiMfgw7duxICgsLk6qqqhZd//08tz/Ia+ek+vr6ZNGiRUlhYeEp
+/7/94Ac/SGpqak57/9rDa+mkV199NYmIZM+ePa2+7T/96U9JUVFR0ilp7WlAaAOXXnppLF++vNlb
+MdJdaWlpXHfddXH48OGm39xkmqeffjpuuOGGk7/4iF27dkVZWVkcOnQo8vPzY9CgQTF06NCznnb2
+AvxCJnbt2hX/+Mc/oqKiIhobG6Nnz54xcODAKCkpadfvJx48eHBMmzat6TeHHUG/fv1i/vz5Heox
+/6+DBw9GWVlZ5Ofnx7Bhw5r+yvnu3bujf//+Z3091tbWRllZWVRUVETPnj1jyJAhkUqlory8PPr1
+63fOv4jeErW1tfH3v/89Kioqori4OK688spmZ3dKZ/fee2+UlpbG5s2bO8zz6d57743t27e36C27
+6ezll1+OoUOHttn2z+e1U1NTE2VlZVFZWRk9evSIwYMHt+iEOZn8Wjpp+/btMXjw4NizZ0/07du3
+Vbe9bt26uP32252aGTizkyET8e6ppktKSpr9sa50kK73C9pKjx49Tpkni2jZKVrz8vKaBpPf6+Tb
+SltDXl5eXHPNNXYUF1Rbhsz5vnby8/ObnfnTa6l1mZkBAADEDAAAgJgBAAAQMwAAgJgBAAAQMwAA
+AGIGAAAQMwAAAGIGAABAzAAAAIgZAABAzAAAAIgZAAAAMQMAAIgZAAAAMQMAACBmAAAAMQMAACBm
+AAAAxAwAAICYAQAAxAwAAICYAQAAEDMAAICYAQAAEDMAAABiBgAAEDMAAABiBgAAQMwAAACIGQAA
+QMwAAACIGQAAADEDAACIGQAAgDSTsgTQttauXRtFRUUWgla3ffv2DveYKyoqYu3atdG9e/cO85gb
+Ghri+PHj0aVLF096/163iXXr1sXatWs9AVqguro68vPzo1OnThYjTf6fEjPQVi+u1Lsvr9mzZ0dO
+To4FoU3k5eV1qMdbVFQUGzdujLKysg7zmOvq6qK6ujry8vKic+fOfohqQ5WVlTF69OgO9Zjz8/Mj
+IuLOO+/0BDiH2traqKmpiYKCgsjNzbUgLXDkyJGIiMjKars3g4kZaCPDhw+PJEksBLSit956q8M9
+5rq6uli1alUsXbo0qqqqYubMmTFr1qwoLi72hOC8LVy4MBYuXGghzmL9+vUxd+7c2Lt3b9x3330x
+Z86cpgjk4jMzAwBpLDc3N6ZPnx7l5eXxox/9KB566KEYMGBALFq0KCorKy0QtJHy8vIYP358jBs3
+LoYPHx67du2KBQsWCBkxAwCIGkhPhw8fjrvvvjsGDhwYVVVVsW3btli9enV8+MMftjhiBgAQNZB+
+Tpw4EcuXL4/LL7881q5dG2vWrImNGzfGkCFDLI6YAQBEDaSn9evXx5VXXhnf+973YtasWfHPf/4z
+Jk6caGHEDAAgaiA9mYsRMwCAqIGMYi5GzAAAogYyirkYMQMAiBrIOOZixAwAIGogo5iLETMAQDuN
+moULF4oa2iVzMWIGAGjnUfPwww+LGtoVczFiBgAQNZBxzMWIGQBA1IgaMkp5eXlMmDDBXIyYAQBE
+jaghM7x3LubIkSPmYsQMACBqRA3pzVwMYgYAEDVkHHMxiBkAQNSQUczFIGYAAFFDRjEXg5gBAFo9
+apYsWSJqaDPmYhAzAECbRc20adNEDW3CXAwt1SlJksQykPZP1E6dYvDgwTFp0iSLAZCGGhoa4sUX
+X4yNGzdGbW1tXHvttTFy5EjzDLwvhw4dinXr1sXOnTvjqquuijFjxkRhYaGF4RTr1q2LzZs3ixky
+wzXXXBNVVVXRtWtXiwGQxpIkiYqKiti3b180NDREz549o1evXpGdnW1xOGsMv/3223HgwIHo2rVr
+9OnTJwoKCiwMZ1RdXR1du3YVMwBA66urq4vVq1fHkiVLoqqqKmbOnBmzZ8+O4uJii0OTEydOxG9+
+85tYtGhRFBQUxI9//GNvJ+N9ETMAgKjhglu/fn3MnTs39u7dG/Pnz485c+Z4WyJiBgAQNaSv8vLy
+uPvuu+Opp56Kr3/967F48WKnWeYDczYzAKDNOfsZ/l4MbcGRGQDggnOkpuMwF4OYAQBEDRnHXAxi
+BgAQNWQUczFcKGZmAICLzkxN+2AuhgvNkRkAIO04UpNZzMUgZgAARE3GMReDmAEAEDUZxVwM6cDM
+DACQ9szUpA9zMaQTR2YAgIzjSM2FZy4GMQMAIGoyjrkYxAwAgKjJKOZiSHdmZgCAjGempnWZiyFT
+ODIDALQ7jtR8MP87F7N06dL42te+ZmEQMwAAoiZ9mYtBzAAAiJqMYi6GTGZmBgBo98zUnMpcDO2B
+IzMAQIfTHo/UvPnmm/Hmm2/G9ddff9brmYtBzAAAdPCoOXbsWDz77LMxfvz4i/44du3aFSUlJU2P
+KScn57TXMxdDe+NtZgBAh3U+bz/75S9/GRMmTIilS5de1Mewc+fOuPbaayM7OzuysrLigQceOOU6
+5eXlMWHChBg3blwMHz48du3aFQsWLBAyZDxHZgAA/k9Lj9QcO3YsPvrRj0ZlZWVkZ2fHlClTYsWK
+FZFKpS7o/S0rK4svfOELcfTo0Thx4kRERHTp0iXeeOON6NGjRxw+fDgWL14cv/jFL+Jzn/tc3H//
+/TFkyBA7GjEDANBRo+anP/1pLFiwIOrr6yMiIicnJ0aOHBl/+MMfoqio6ILcx5deeik+//nPR3V1
+dTQ0NDR9Pjc3NyZNmhRXX321uRjEDACAqPn/qLnzzjtj0KBBp7wNLTc3NwYMGBDPPPNM9O3bt03v
+15YtW2LMmDFx/PjxZiHzXgUFBfH973/fXAxiBgBA1LwbNQcPHoz6+vrTRkROTk5ccsklsWHDhrjq
+qqva5L5s2rQpvvzlL0ddXV00Njae9jpZWVkxZMiQ2LZtm52HmAEAIKKysjL69OkT1dXVZ7xOdnZ2
+pFKpePzxx1v9TGcbNmyI8ePHR319/RlD5r1B87vf/S5uvfVWO452y9nMAABaaNWqVU1zMmfS0NAQ
+dXV1cfPNN8eyZcta7Xs/9dRTceONN571iMx7JUkS3/3ud+P48eN2HGIGAKAjO3bsWCxZsuScMXMy
+JBobG2POnDnx7W9/+4xzLS31xBNPxM033xwnTpyIlr6pJkmSePvtty/6qaNBzAAAXGTLli2Lo0eP
+vq/bNDY2xsqVK+Omm26Kd9555wN930ceeSRuu+229xVEeXl50alTp4iIeO2118JUAe2VmRkAgHOo
+qamJgoKCiHj3rGV1dXXv6/a5ubnxiU98IjZs2BC9e/du8e1Wr14dU6dObdF8TCqVirq6uhgwYEBM
+mDAhxo4dG6NGjYrOnTvbgYgZAICObN++fbF169bYunVrPPfcc1FWVhZ1dXWRl5fXooH8nJycKC4u
+jmeffTYGDRp0zu/34IMPxne+850zHlXJy8uLurq6yM3NjS9+8Ytx0003xdixY6N///52FmIGAIAz
+q6+vj5dffjmef/75+Nvf/habNm2K/fv3RyqViuzs7KitrT3lNllZWZGXlxe///3vY+zYsWfc9s9+
+9rOYN29es0By9AXEDABAm/nPf/4TL7zwQmzZsiU2bdoUr776atTX10fnzp2jtra22VGWX/3qV3HX
+XXedso377rsvFi5cGBHvnua5sbHR0RcQMwAAF1ZdXV288sorsXXr1ti8eXOUlpbGgQMHmr7+pS99
+KdavXx9ZWe+ek2natGnx61//OiIi+vfvH1/5ylccfQExAwBcKPv27Ys//vGPFuIMDh8+HP/617/i
+6aefjoaGhujbt2/ccccdsX79+vj3v/8dH/rQh2L06NHRrVs3i3UWI0eOjE996lMWQsyIGQCg9ZSW
+lsZ1110XvXr1ii5duliQczj5N2mysrKaTqfM2e3evTuWL18e06ZNsxgdXMoSAABt4fXXX4+ioiIL
+QasbPHiwRSAi/NFMAABAzAAAAIgZAAAAMQMAAIgZAAAAMQMAACBmAAAAMQMAACBmAAAAxAwAAICY
+AQAAxAwAAICYAQAAEDMAAICYAQAAEDMAAABiBgAAEDMAAABiBgAAQMwAAACIGQAAQMwAAACIGQAA
+ADEDAACIGQAAADEDAAAgZgAAADEDAAAgZgAAAMQMAACAmAEAANqBlCUAADh/VVVVsXfv3vP7wSyV
+ik9+8pOxf//+OHjw4BmvV1xcHB/5yEdO+XySJPHaa6+d9jYDBgyILl262FGIGQAAmvvLX/4St9xy
+y3lto2fPnrF///7YvXt3rFy5Mh5++OFIkqTp6yUlJTFx4sQYNWrUGWPmz3/+c2zZsiWefPLJiIgo
+KiqK6dOnx4wZM8QMYgYAgFPV1NRERETv3r1jwYIF8dnPfjYuu+yySKVSUVpaGpMmTYqIiI997GPx
+3HPPRZIkcfz48XjrrbfiySefjGXLljVtY8SIETFixIi44oorYt68eU3f44c//GFMnDjxjPchKysr
+7rnnnrjnnnti4MCBsWPHjnj88cdjzJgxdhBiBgCA06uuro6cnJz461//GiUlJc2+1qNHj6aPc3Jy
+ok+fPk2XL7/88hg9enRceumlsXjx4ma3mz17djz00EOxc+fOiIgoLS09a8yclCRJVFRUxMiRI4UM
+7ZoTAAAAtIKampoYP378KSHTUjNmzIjGxsZoaGho+lwqlYqFCxc2XX7kkUfi2LFj59zWCy+8EAcO
+HIgZM2bYMYgZAADOHTPjxo37wLe/7LLLYtiwYXH8+PFmn7/llluiX79+ERFx5MiR+O1vf3vOba1e
+vTq6d+8eEyZMsGMQMwAAnN28efNiypQp57WNLVu2REFBQbPPpVKpmDVrVtPln//8582O3vyvo0eP
+xqOPPhpTpkyJvLw8OwYxAwDAOX6oysqKTp06ndc2srOzT7uNb37zm1FUVBQREW+88UbTmcpO59FH
+H41jx47Ft771LTsFMQMAwMVVWFgYU6dObbp8//33n/Z6SZLEihUrYtSoUR94dgfEDAAArWrmzJmR
+Sr17ItotW7bE888/f8p1XnrppXjllVeahQ+IGQAALqo+ffrEbbfd1nT5dEdnVqxYEcXFxfHVr37V
+giFmAABIH3PmzGn6+Iknnog9e/Y0Xa6qqorHHnssJk+eHJ07d7ZYiBkAANLH0KFD4/rrr4+IiMbG
+xnjggQeavmbwHzEDAEBamzt3btPHK1eujKqqqqbB/xEjRsSnP/1pi4SYAQAg/dxwww1NZyo7evRo
+rFq1KrZt2xZlZWUG/xEzAACk8Q9vWVnNZmeWLVsWDz74YFxyySVx6623WiDEDAAA6Wvy5MnRvXv3
+iIjYu3dvrFmzJu64447o0qWLxUHMAADQehobG1t1e/n5+TF9+vRmnzP4j5gBAKDVvfPOO00f19TU
+tMo2p0+fHnl5eRERMWzYsPjMZz5joREzAAC0rmeeeabp471798aOHTvOe5u9evWKyZMnR0QY/EfM
+AADQeg4dOhRTpkyJIUOGxIoVK5p97eqrr44bb7wxfvKTn5zX95gzZ04UFhbGxIkTLTgdUsoSAAC0
+vm7dusWaNWva9HtcccUVsWnTpigsLLTgdEiOzAAAZLChQ4daBMQMAACAmAEAABAzAAAAYgYAABAz
+AAAAYgYAAEDMAAAAYgYAAEDMAAAAiBkAAEDMAAAAiBkAAAAxAwAAIGYAAAAxAwAAIGYAAADEDAAA
+IGYAAADEDAAAgJgBAADEjCUAAADEDAAAgJgBAAAQMwAAgJgBAAAQMwAAAGIGAAAQMwAAAGIGAABA
+zAAAAIgZAABAzAAAAIgZAAAAMQMAAIgZAACA9JCyBABAW+jVq1cUFBRYCFpdZWWlRSAiIjolSZJY
+BgCgtVRUVMTGjRstBG1q6NCh8fGPf9xCiBkxAwAAZB4zMwAAQEZKvb79xaYLJYOutiIAAEBGcGQG
+AADISP8FpxZnWS0U37cAAAAASUVORK5CYII=
diff --git a/Documentation/DocBook/media/fieldseq_bt.gif.b64 b/Documentation/DocBook/media/fieldseq_bt.gif.b64
new file mode 100644 (file)
index 0000000..b5b557b
--- /dev/null
@@ -0,0 +1,447 @@
+R0lGODlhcwKfAucAAAAAAElJDK+vr0gSElYMDC8kDV5bEBcHOwYGSEQODmEaGgoKOBkTVC0tVyAg
+aDcJC6Ojoys8DAAYGqSkxV9fFFtdEJmZmUA4EF0wMAAAcAoTHTZHJ0gYGAcMTwcSO29ISFUHB2AV
+FXd3YAcHMRUVQiIAGg4HT3t7eywOJ3d3dwcHSEEgABMuDnd3OGpkSQAAYlZGBzEEBGJlDCstCxwc
+WQcHSzkRGWBtYC0AACA3ABAKNhAQTTMwDA0VQD4AAEYVFVVVVSQMJQULOB8fQScnYBgYRD5VPmZm
+DEZRB2ZiDAoKSgAAVAwQOH5+lBwcS+7u7hoaST4+X3d3WACPADMzMyBRIDgAAGBgc0JCEHEAAEwN
+DRkwDAoKOR8kPZR7eyA1IABpABgNQBA9EABVAAsLRww/DAwMPgBNAENDCgc9B8zMzAUFQQBDAD4M
+DAwOKgAAcQA5AEtLFYqKAA0NTC8HBxEREQgfCAArAAApACIqMkkGBhoqKnwAAAsGQ6qqqkoKCg4O
+MlkcHAoZJCcrW6SkpFQAAAAAOBAOSwAVGh0ROgMPHWZmB00QEGUAAFQaGjEyC2w4OLe3n4qKioiI
+iBAVMC4uXhkZUGIAAHJYWHd3AAAAPhAQUQUGL0BAIGggIBgAGkIVFV9fEAwcJR8KJA8MU9EAAAcH
+VRoaYWhoaDcAALu7AGZmZnAAAGRkZGQVFVhqWD4KCgwOUzMzDAAAmgklBzEHBzExClhYWBMTPAYJ
+Qy8fCFpaB///////ACISRExUDUQrDAwMVhISSEYYGHd3IDhcOERERElJAAkPNTsHF1hYckgGBj05
+CFYAADg4OCAVO0hCDDAwMLu7ilpaDR8qCDg+EBxGHN3d3REGNjo9CDQ8DBwYRGZmHFMAABQ+FBE+
+ESIiIhs+BxU0FWVeBw04DYqKsxAsEB8hQAwuDAc2BwwqDAoqCgcIL1dMDQAA0Q0iDQwiDAckBxAQ
+EDwAAAAAU0JCDAkJPru7u5oAADg4bAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAALwALAAAAABzAp8C
+AAj+AHkJHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuX
+MGPKnEmzps2bOHPq3Mkz5z0AQIMCSNHyZ0WjE5GqNAZAqcGmT+8VZMoL6k6rEp0KfEJl489VBcEB
+GGjBwk8LBJsyFQqU15MUdQDUWfVk4JNVccER5ZXCT8+/gAN/xFp0LEWtDxEfRKo44s8n1/YeJCyQ
+8GO+1xhSbvwxRWaklBEiXoVW4886BNW0FQjkyem6laUKdLqKSuZrQIxtpbLqc51JbsHBFkw8pYUT
+w4uHDK2SM0PnCqHPNiz9uWGFoS1fb7h5u0nQshf+ar2G2isAKn4FpqByHQivn8YkY3WK9RoANXx1
+kwUncBVw5QCSdAsA8jiDXIAeEQYXAMbgp0YKKQAFYVxEPbjgXm/FBURmD1pQxz1qsDfUdAVlCMCG
+vFg4lhpMgbOKYX6IBY5fHX642FBx0cULbnKlUFdQkgS1IxA91mWMBWJRYQF7dZQ2HVBIsdhjbG4R
+WUeE4f3UFlQN6hUiUK1puV1Q93Sp24LglNYlAGmmKGJrvBxJ4YWxiUkmLzGymZ6ULnqXAlgC5Tmj
+QRE2qd+NkwDKCziTwAjcT6rhV1WW28013D11UfHfVrItieCnHw0YVIEHgnoRVutllgJ/X+F54hP+
+fjT1FWR68WXbXV3dU4cxmBoDnGpSaZUqru/NJRUVrV3DXrHBAnCNrrwmN9Cs17jIC2+QUUEUY4Zh
+qyxR52X2IlFwFWSUUU/8tmObXBrzxBNEhveeYVCd5wd5RD1Ra3eVzajGPeCoSq8x4qJ2ZXDghvlq
+rFJBBR6z82aGbLbe+TqbjT9lNtCq4npHUMblqQEOUr3Nmx+VJJIVl7aSToqQan/ZydbMNNds8804
+56zzzjzXbGpFWA0q0IdKWSWrswIhyUuTAtn3L9IE2ddsQUzveF/GKUJtwVirSAZECliLpnUdqmns
+ockml500agCkx625YxnlqUCT6NaU2lbL+zD+AKXNpTHK09Lr5MaCk+h3WrIZ3fDULnc90Nd4b12Q
+VY6zJtmiTnoc+LV+QYiUfuiyS6lB96wHAKDMAa5TZBC27vrrsMcu++y012777bjDHg3N4Dgj7c8P
+YTXzPUUnTvx1Rgl/PFlUgBMv2gMp/zaJawUFtuabT6fUudTFjfxYVk2/uVERCmX38tHrTe/iTa8C
+Th1A4MevyykCsStV9Bt1jfvwy288lQ5bX5zYcr3spU8g1ZMQ4gbCH7HxIlGLetp7/sOYOjxhPthz
+FX40VRDPqA54IISIqAhkoN+F0CFBkxf0FBe2s1XNaVG6D5W08sKrGcY+ZuPa5aB3I7OBI3L+qHkb
+EPPXPbiZzAKHSh8Om6YdAKowQ/TLnlUOhrbwbQeKinNiFaVSuYEskReSI4iNeNFFg1StKgnRH9lY
+NZYUSEopX8NgWpIDlVURJFawSd0J92iQW5DKhHzkTnhS9UALFq9Op6MVuW5VG7RF6oFt46GtrkEs
+pRgjWcvSVbCIhrwdUqtW3tLWvOqClFCCSzbiIxG61PUtlxnDXfBqosusAgQ42TGSHwPAj2TDSqbs
+kkS1rMst/zdLxjkMYza6JMWmshdNQqx0fAkYGanjyW6J0iiHUkq65DiQV2aGWMFB0T1EmbVAmjMh
+lDwnRRS0MvwcclI/WZCOTAQnpSwoPgD+mIRW6EnK6zyBKYZKmozQYk/vqIiKPEKoWNRAHtQkdC9W
+TNn4DPMlKkIllldyYy61mKK1UAE/AI3aQq2CJDbBhW2oXJFH/YeyekmlodeSYUnb5BaAIrEgk3CP
+QNlUmgi55UVNMoxPNwpJd95HMk5p1Ojsghe5lGwrTa1V0nSqzqpadSXVmckOr7rHdAEyNbDRVU+A
+MDiumvWsHclqTO6xKbSeMAVlPcgqWgMvReWkWm7Nq14tota9+vUjb2FILF/FE7P89bCITaxiF8vY
+xjr2sZCNrGQnS9nKWvaymM2sZjfL2c569rOgDa1oR1uSfxHvtKhNrWpXy9rWuva1sI3+7WkBaVrZ
+2va2uM0tbNOo29769re7FQ1wh0vc3/K2uMhNbnAN4hrlOve5p21ZQvIxi+pa97rYza52t8vd7nr3
+u+CtbgZUOBBP4OO86E2vetfL3va6973wja98z1uIhHBDFfjNr373y9/++ve/AA6wgAeMX24kxBpg
+SLCCF8zgBjv4wRCOsIQnTOEEWyMhSwivhjfM4Q6DlwaiYcV8R0ziEptYvp5gSD7cweIWu/jFMI6x
+jGdM4xrb+MYsngV5BeKJUvj4x0AOspCHTOQiG/nISE6yjy+REGL04slQjrKUp0zlKlv5yljOspaf
+TIyEVGEKYA6zmMdM5jKb+cxoTrP+mtcM5iok5AU4jrOc50znGztANPhQsp73zOc+JznFC1lxnQdN
+6ELTWMcI6bGfF83oRhuZyQhx8pYnTelKWzrLXUbIl9nM6U57+tNqdjNC4GzoUpt60HdeTJ4dzepW
+LxrQChH0qWdN60PvmBeKdrWud/3oJl/618AONpYzfZBNg/rYyE72mUV9EFLX+tnQdkeqSbdqXlv7
+2qWAdULOYYZue/vb4A63uMdN7nKb+9zo7jYXIIAQDhDg3fCOt7znTe962/ve+M63vt9di4TI4ggA
+D7jAB07wghv84AhPuMIXDnBZJOQd6Ii4xCdO8Ypb/OIYz7jGN87xiL8jIexIt8j+R07ykqPbDQiB
+wB/2zfKWu/zl+uaAiqNNc1oj+iC5xrbOWw3pg0ha2EAP+qWJbRBjK/voSP80sw3i7Jo7ndDTNle1
+d051RmsbIbJ+utbnfHOD5LzqYN9zzw3yc6Gb/exWJnpBjJ70trvdzEsvSNO3TncbR/1jUw+73pF8
+9YNkve6Al3HXC/L1vRt+yGMvSNnRznjGq50gbH+75N8ed4LMPfCYb/Hdp5X3w3v+x303yN8zn/nB
+E6Twn/d84gmy+Ma7PuiPH0jkJ0/7o1d+IJcnfeA3P5vOp/7woS/IEOZA/OIb//jIT77yl8/85jv/
++cUnBEJ+oIXqW//62M++9rf+z/3ue//74K8+LBKChWmY//zoT7/618/+9rv//fCPv/mxkBBzkOP+
++M+//vfP//77//8AGIACeH/mkBD2AH0ImIAKuIDPxwQIQQjhF4ESOIEUGH4/MHO6p3umV16/14Gr
+NxCt93oi+GuxJxCzV3soCGq3JxC5l4F0x3vv4XsdqHfBRxCj54J0t4E8NoOp94ECEYIjGISTVoK8
+cIIpeIRstoK80II4+HQweA8yyINVV4MDcYNN+HQ6iGtSqHq+JoReWGlEaIRIOIbL9mZXuHt4toXA
+h4FnmIO3hnpquHM+yAtA+IV2OGVhSIZ6mIRm2IYvmIZxSIMMAQUvUIiGeIj+iJiIiriIjNiIjviI
+kFiIS8BuB5EA83CJmJiJmriJnNiJnviJoBiKoniJOJAQ2ZAJqJiKqriKrNiKrviKsBiLsjiLqJgN
+CREPbJCLuriLvNiLvviLwBiMwjiMxJiL8ZAQhhCJyriMzNiMkDgCKZcKoziN1FiN1iiKCcCGfoiF
+bxiIejeHdXiH4tgLebiH5liGo7aNW/eEUeiNvEaFAmGF6lhrWQiH7shr4DiO+oiHXnaO/khmSsiE
+8zhr7HiPU6iNAwlt9WiQVJeP+/iQ5NiP/ziRUxCQCVlzBcmQOgePvEAEHvaRIBmS3pUBAoAQrsAH
+KJmSKrmSLNmSLvmSMBn+kzI5kyjZDAkRCgSWkzq5kzw5YKGQEGJQYUI5lERZlBQmBhgmkkq5lCC5
+CQghAI1Ak1I5lVRZlTPpCgzRAG+wlVzZlV75lWAZlmI5lmRZlma5lfRQkgehACfWlm75lvBVXwgR
+B3JQl3Z5l3iZl3q5l3zZl375l4BZl3GQEOJwBoZ5mIiZmIq5mIzZmI75mJAZmYYpDgmhCWd5mZiZ
+mZppliTwlCIGl6AZmm2pAAh5kTbXjRqJbQ4JkfpYjhTpjxZpmtCWkalpbRwpj7JZaAtZm9a2mqwp
+jq75muYYm7lJa7TJm7p2m8VJj6iJnLrmm79ph8EpnHpInMtpasfpnKz+xpFOUAPe+Z3gGZ7iOZ7k
+WZ7meZ7omZ7eqQKUaBADAALwGZ/yOZ/0WZ/2eZ/4mZ/6uZ/wGQMJgQa7EKACOqAEWqAGeqAImqAK
+uqAMGqBokBDrkA4SOqEUWqEWeqEYmqEauqEc2qESug4JsQbqOaIkWqImmp4LkHJ6wJ8s2qIu+qL7
+OQCleZ2EtpvayXNdGJ13OJ3UOYbWSaOFlp03anUzCqR0ZqND2mjQqaNCyKM9eoQ/aqR1JqRJ2mfK
+KaW62ZxVumhLyqQj6KRPioJRiqVyRqVbqmdXSqZ1hqRnymdd6qWvB6ZhSntjqqZ2BohtaqUM0Z0n
+2qd++qfmyZ4I8Z7+MFqohnqo+OmfCAGgDdqojvqokLqgD4oQEeqhlnqpmJqpHAqiCCGigPqpoNqn
+KXoQELCiiHqqqFqoMhpodrqmWpqnevamcNp4cjqnklenrUpjZgqrRpamuYpjbMqrSCars4p2tWqr
+boervxpjuyqsQ+ary1pjweqsRUasxWp2x4qsSaes0epizUqtQMaRWrmZ5Fqu5jqWaYkQbCma7Nqu
+cZkQdBmY8jqv9FqvfzmYCFGYkrmv/Nqv/gqZlIkQlnmuBFuw5NqZByEAn+muDNuw+ECaC+GRTDmx
+FDuSamkQJ2mVGruxHAuTNokQONmTIjuyJAtgP4kQQWmUKruyLBv+YUiJEBlWsTI7s9XllAkblR2b
+szqrsVjJqt1qY9MKrkJmrdcKexKprWLahz+rq3gqtEUGrUsLY0HrtD9GtEUrbNmKtMrGrUv7rU4L
+tVHrYlNLtaVgtVcLbFmrtcjGtT/rtULLkVHgAHI7t3Rbt3Z7t3ibt3q7t3zbt3JLA7eGAZ4wuIRb
+uIZ7uIibuIq7uIzbuI47uKCQEJ1ADJRbuZZ7uZibuZq7uZzbuZ77uZTbCQnxBVVQuqZ7uqibuqq7
+uqzbuq77urBbul+QELjgt7Z7u7ibu317DqIRCI/7u8AbvMLruBhAWsZ7vMibvMq7vMzbvM77vNAb
+vdI7vdRbvdb+e73Ym73au73c273e+73gG77iO77kW77me77om77qy1VnBEblsRXNlEGawRa6ARr0
+K0nzEhRCcxDlwxZScRdxYSnRIxRwsr4GfMAPkQJUxQtAYFdDhRhqQCSEhRCh8TBGdMHumx5ptB3k
+gSK4UQcaYxXKssAIXMImPBCqARsXpMF+EBcSxUB0wRVJNDnkZcFEdcPRJB7bcUkFUUuAEysnHMRB
+TFMt7EVpUkRTEVYZVMEChMEGZDV/cyN2IUOpoUtRBMRCnMUHrMD9IRm+kkqE0kCTUcNNjMMvHEVS
+fMYcNcJa3Mbqm8JLIylcDMZ2ARe3VhVskTIzsy0eoxV6BD3+ilEv5vNVblzI3qskMXIx/aTGhUQw
+2EHGH4S/TvFFDrQVVIzCVvzHhrzJ3ptTldO/ZIIYq3LHB3TBTEw622FH0bHDJOzDaMzJsAy+9vFD
+qHzGFyRdCXHKryzJ1+EhGlzJTQM/t2E/IUzKsXzM19s8aSwzvDIzuQzJeJzHzJy/QLG/G1wiTXU4
+kYzM3NzN3vzN4BzO4jzOZpUCr3TOr4TLH4FE6PxKcUXO8BzP8jzP9FzP9nzP+JzP+rzP/NzP/vzP
+AP1YuTPQBF3QBn3QUexXrHPQDN3QDk3QCb1XpfPQFF3RFg0hjtUzGr3RHN3RPGPMZiUzHj3SJF3S
+NwPSXAX+yia90ixN0hm9VXr1Eyh9VTKdWDWNWEOF0/K7VyOCWDd9WD/9V0HtVzl9WEWtWD0N1Joc
+0kvNVUO9V0dN1DutV0ntBZhw1Vid1Vq91Vzd1V791WAd1mKN1YEz01b10zfwCmq91mzd1m791nAd
+13I913Rd12p9A2WdWDl9DWPd137914A91l5AOC/NgWRLZD331DGNFWKotlub1zrNeYdNZLAW1YiV
+1PZItond1DTN2I5Np5Bt1MjTjlRb2VOdV5g92YgX2kLt2Z99q6wt1ZKt2kFm2oW9g7QNZJtt1lX1
+04392ioY21A92rkdroTdWEnNCKm63Mytn8sg3IsdHur+oKnUXd3WvaHqAN15ldOE0Nze/d3yyQjH
+zVipXdxLpt1u5dvATXnojVY5DYXm7WO2jdySkdlUu9s27drrva3tfVbvTdpfO96LVd7mjd8+rd/7
+bXv9Xc7EHd/zTd71Hd9lu+BOjeAJnmzMptjb3eDm/eADLhmECt4inqqKOi+8rU4/XanXveIsrqmc
+auJ6fR2lOuI0fqqryhen7VYEXtwGrtTh8dsXvmYZztlW9d8S7uFIHeHx3eOt/eNBruDaE+Oz3eEC
+nuSGXeAU3tlO/uQYnuVFzuHFjeSJldTr6rBmLppyCeMHHh76+q9u/uZw3pgBq+aiPRAKe+Z4DpoQ
+i+P+t80LjpAFgB7ogj7ohF7ohn7oiJ7oir7ogO4DXt7bWOENLTvplL6y3vDo6pTTAtANjN7pnv7p
+oL7ojlDlY67kWB7lay57XN7lqF7nvXfkpH7Zps7jmH5O6r3qxzbkJ35ORu7gsX5YO57bTO5Xt47r
+Slfr5tTrVK4eOY5WST0MbRDt0j7t1F7t1n7t2J7t2r7t3B7tdIDsgfTT8FAG5F7u5n7u6J7u6r7u
+7N7u7v7u5A4P4M5HOQ0BD9Dt+J7v+r7v3D4Mv/5XwU7bwy7RFm7sfNjqf6XsYf7vfhXwqj3w0a3q
+Bu9pui7lr+7rzN7n9u20EJ9XxT7xB0/nCQ/muS3+5rJ+5bSO8MRe8CCPZhUf2Re/7HxO3wNBfRV4
+8zif8903fipP8OFhfwMY9EI/9EQfgAXY83rF3Tq/9Eyf8xeY8TSP26cu8iu/5S0v5PO+Rwpf8gzP
+07Mu7Fl/Qh9/9S4f9iG09bRt8sD+9QJv9iA09mQPd24PPGiv2moP8Gz/8HP/M3Af9wC596ZS95N9
+9w0vGe4Gc4if+Ip/b/2G9B6PFRDXcZI/+ZRf+Rv3cY7vVvW+covf+Z6P+DIH9RCO8mCf+WjV934v
+Zi/v6jEI66L/4aTf9qZ/Vqif+m0G+KAi+IdN+F4f+3o/+0xt9bb/98Cf0iSf9l1P1ZIRAnne/G3+
+meYant5Y8Q1jUP3Wf/3Yn/3av/3c3/3e//3gX/3fgPufoukL6/zoL18hkPyoLRl/HurwH//yj+iO
+XvxaPhCSXun6v/8Sdun2/+UAwUuggG5ZDB5EmFDhQoYNHT6EGNGgI4G8UgComFHjRo4dPX4EGVLk
+yIwAUlT0VErlSpYtXb6EGVPmTJo1VV6qeA/APZI9ff4E2lMnT4FVphxFmlTpUqZNnT6FGlXq0So5
+dwbFmlUryYs58dkEG1bs2JqeKnbdmlbt2oomUZKFG1fuTJwCh7LFm3fk3aJT/f4FHFhqVbtX9R5G
+nBEtr3tf5z6GDNeswMWJLSd2KzBlZM6d6Vr+JXpZtFq+vIwKRp1a9VPCjA2Php11cWPPtW2vnGwR
+Y2zeWzPzwuBJ+HDixY0fR55c+XLmzYWDAt1butDXX6pcx55d+3bu3b1/Bx9e/PUv0aefBzk7kHP2
+7d2/b47h7G709UH+tp/fdWj99kv3r+8/AM+rbEAC6TMwP/wS7E1ABmNz8MHRIpTwsgIrHO1CDGNb
+cEPLKPRQLxBDxGtEEtfS8MS8UlTxMABWuSdGGWeksUYbb8QxRx135DHHSV5rUUQAJumxSCOPRDLJ
+GH/kL0i8LlIySimnNHIVBJ1EDAAtt+SySy+/BDNMMccks0wzm8SSNDPXZLNNN9/0Es00t7r+CE47
+78TTzTkTo7JPP/+U8Yk92XoCUEMPRVLQQdW6BlFHH8VxUUknpbRSSy/FNFNNN+W0U08/BTVUUUcl
+tVRTT0U1VVVXZbVVV1+FNVZZZ6W1VltvxTVXXXfltdfD6rAgIwvqyOiJk1zDyktjkOVFWWYz0mlL
+cPz4qEsqQrtmlToAACcFQaPt8pYvj7WACi2pCFYgbjWyUk5f34V31xSAyAiIVRTbTaeN1ABCSyAU
+5QjIwtRFU1+NDOZlWGo7MuwJbQW9po5VruFFDSqo0EjgZvlbhYqF/aDi3mYBUCOjbd2NN2WVY1UD
+AEWfAGBhXvzYdmCNwFnliSeoWJbhgnf+0xhhqxQDx6PXYObJGHoreqLbktB8zQJwAOblCWCbpeLY
+mc1FeWWvv0YVnHRprugasfO9khdjFBU6458J3qjtZ3m5BgCKAw7Nap1J1mgSjNuCOjQqJtkoBYyH
+LFqgVZgEu3HHUZ1Xca2NIRLtj1JIHO+4gX774Cs1hrvqVaiVW2iNXwsao53AKZmXOuru+nHZZ6+0
+ZUHraD1yg+UWyNg6UPbSZi9PKv1zd50t/umNUH97pxROAnlj2qen/lJ0/Uj8njq+tXyjSeow5m6f
+Nw8d2rSFrlt8tyv6UQ2YW2f/7/IBr2hw7w+/R42iF5e+ev//T9Mk7HWsOnEpRmnDXOz++me++dmM
+gWfJ3PL4cxWlFctp9FufQIZFNasF6yqse90CAThCEmKobqwj39yqxreQpK6BKnyWwowWmu8JJGIT
+q9jFMqi8inTsYyGDm+H+BroSFtGI9qFCBIfmGi4ZA1xbmmEKv8TELS3ridOqFpeoAL9sbatbVBNh
+A8t1LsLBrWVlJOIR1bhGNrbRjW+EYxzlOMdQpcAYd8SjMeCHGAvkEY/pomMgBTlIQhbSkIdEZCIV
+uUhGNtKRj4RkJCU5SUpW0pKXxGR98rRJTnZyS1pD1RM9OUpSnmlVoixlKlXJJVgBwBjPg2UsZTlL
+WtbSlrfEZS51mcsOlUonq9hlMIX+OUxiFvN57Trli4y5TGY2M5jGSJuqelmqaY7KRKC65qey6SkW
+naqao/pmqLbZqXFyqpyb6qapwhmqdWozjaI6p6bimal0UlNryshHPvW5T37205//BGhABTpQguoT
+fu30VGlc0AKGNtShD4VoRCU6UYpW1KIXZagLzJOq0lSioB8FaUhFStAozKeVWsuHO1S6Upa21KUv
+hWlMZTpTmtZUpbMIDULJ+Rpi9MKnPwVqUIU6VKIW1ahHRWpSfUqMjYbyNS+waVSlOlWq1tQBJn3V
+b1JaVa521asyxWlbQHmq0vRUqWdFa1rVilSmFkaB7gwNVL86V7py9aqUiWaqtFr+V772laZhVddY
+TVXWtRbWsIc9alv3k8y4+tWxj13pXXVz0opsFbKXrStgmyVYX/IUsZ8FrWEVO09MlUaumEWtVyVb
+T1L9BgovgG1sZTtb2tbWtrfFbW51u1vYLgECYmVsRWxxDOIW17jHRW5ylbtc5jbXuc8lri2aStbX
+GIK318VudrW72xFg1VV7TW14q6pZnZrTs6FFb3oTO93BPlW875XqavOKKvDC175gzSlnSUVY9fbX
+v0tlb2cbe18Cv1S+lBWIZQu8YHeQV7/WPO9/JRza0b5TnO5lMIMPnFWtEWEWHwZxiEU8YhKX2MQn
+RnGKVfzhDAgAuKoqTShUMWP+GtfYxjfGcY51vGMe99jHMw5FgPf7miWs2MhHRnKSVbwJ77bqNw14
+Q5SlPGUqV9nKV8ZylrW8ZS5HmR4uDmxwBRIHOZTZzGdGc5rVvGY2t9nNb4ZzmeMgZAiHRhNdxnOe
+9bxnLpOgyayqb4YJ7GAx88KsE0b0YSv81oRiWNAE3vB3UfroAhMaxhFOdKbTuuhCn5bS8I20kyf9
+aftamqOY1nSq2UpneDqa1OINNaC15oQa1NrWt8Z1rnW9a1732te/BnatVfDbMF86NGjYRbKVvWxm
+N9vZz4Z2tKU9bWonGw2svnBo1hBsbnfb298G9gL+vKpAvzq1pnZqaA6tanb+F5XTxq6Ip82N2liT
+e9TzPnd+C73udvcbqO8+9YDxTe9xS/PeA78suqmrbn83/N/YxqarEf7Yehu8shPHrMLby3CHOxzg
+6Y43xi9bcb3OGtwnR3nKfT3sFwe8IsiudsxlPnOaT/vabi30tlW+c56fXNx4RTAvFCzyvmpcwBXh
+d8fZ/fGFh5zojiU5fQ/+9MzqG94CSbrSU830jTud6nyNujen/vWvGn3IHNd6u7l+dIHIm+yqLXjJ
+KwJlPtfd7nfP8pdbDvIxx9nvfwd84OE8Z5xfnRd3xnviFV93PwOdwxXxsJIlP3nKn7jFe2+6QGT8
+Y8533vOf73GQC+9ygRT+ufKnR73kmex4SV/87XQ1e52RnvZ+r/3sXn893Fkvatfn3quxbzXaab91
+iMMV976vatjVOXbkSxX42Z798FVte9m3vfldVb49KzKEYHTf+98Hf/jFP37yl9/850d/95VA7M0W
+WhZHgH/85T9/+tff/vfHf/71v3/4y6L4jQ6NEUi/ASTAAjRA9HODuJO63ru+qXq+iBM+6Us06gu+
+42tAm8q+1mK+C5ypBzQ+rJNA4hs9vuMFt+PAmcpAcNrAE4QpDwTA6AvBCfy/nRI4FqSpFBSVcrPB
+mHJBGoTBGJwwCoQ+69vBG1RAsdu+OVDCJWTCJnTCJ4TCKJTCKaTCKlz+QkLAvK4TCCyYhi70wi8E
+wzAUwzEkwzI0wzNEwy7Eghk0r9CwByuEwziUwzmsQiY4wuVjwCJsQasjPUMDQhkcwcwrQT1EwTvU
+vgQjRPzKQrbzwz8MQjbcFNNKxJjCQXZawUTswTb8QUfsLyGEQAucRJWqRFDRwVBsMD4kwazjRAqD
+RHmSOFN0h1H8lN9oAmWwxVvExVzUxV3kxV70xV8ExmC8RfEpr0h8DRGQgmRUxmVkxmZ0xmeExmiU
+xmmkxmQUgVbMlNIQxm3kxm70RmG8AkPUQFkrNBI0x1NhLRUkR8M7Ry1MlXTMwQdTR3YUxHYsFXhk
+J3Dwo33kx370x3/+BMiAFMiB5MdidEWeIciEVMiFZEiC5JpkQsiGlMiJpEiBBIf5OpWK1MiN5Mg/
+WhU16MiQFMmF3KNTAcmRRMmU7MdMYsmWdMmXhMmYlMmZpMmatMmbxMmc1Mmd5Mme9MmfBMqgFMqh
+JMrzuJqKGJZiORbeGQnkAZousaLz4RIsAomWWZr5QSWTQCXisZaFcaUHEoh+OShncZaiNEv0iJyK
+sBd8caCK4Bd/ASMeeiAX8hykrAOZ6Yg6ARgieg3eEZoU2J6RKaNngZkOARILO8vEFA3b6Z2YqQia
+6Z6MwBmd4ZkoqsswgqG/VKKNAJajxMzy8UvjaRZjCMxnmQRwOE3+CZJLxWTN3hAbgSAbGzqbthSI
+taHN1RSezgFLurEbj/ADl1mFq+TL0AjNjKGYnaCCpUGYrKmbkjxMRmvN6ESRpQGmiqCc3cFIzLHM
+udTNJcIgjgjOmXGZFwLNaPpLNMofxzSY5uSFrNmhz5TO+MwLxsQdyqAX7OwI3wGeLhGeLuHKFPpO
+zlyYOkDP8SmMLuEJUTrKqwDMQtkNvxGIGlrN4ZHPCsWL68mewMRP7wEf9VHNy6TL3UyfjvhNLSLP
+BSrOHkocwwgZgzEXLsHL57TQGc0LAapO3UBQuUmgFuqcEPVOi9jMHhIZ8TzO4yFO80QQgzGMlumK
+ERUIIApQxKT+0SkdiRMqSWZpm/cRCbr0UQeSIY6wGrwkUPjsSyTlzvnACMPJCAmdHyml0jf9iCTi
+COxsIlTaziWaIlGKSmnBS41IyozomJFhpe9EpajMiLqhFiAxF15AzUN1zDYNHjiV1Eml1Eq11Ev1
+HzvaxyvNiz7aR0DC1FAV1VEl1VI11VNF1VRV1VVl1VZ1VQNxpliV1Vl9Hme4BVrF1VzdJVRwBlTQ
+1V8FVlniVV8N1mLV1WE11mSl1VtwBmV11llVl1WS1mml1mq11mvF1mzV1m3l1m711m8Nk2KTJmdY
+FUkAAEko13NNV3RVFWfASFFBC4PUFAAgV1UxV3ZNlXtd11X+cVdWiVd5zMF6zVd1tVeCHVh8RZV+
+XZV/dUtIcdg+2UuBVYOHpdgoqQh9tYuK1dgjuViD3diP7ZGOxVeQJdkcqQiFrZqSVVkagR+GTbDU
+g9mYTbEMyCmB9QR8wNmc1dmd5dme9dmfBdqgFdqhxdlCENmK4AbQU9qlZVoe44ajFQhrAIOppdqq
+tdqrxdqs1dqt5dqu9dqptQao5QXTk9myNdtZoIGTpY97YAWiddu3hdu4HdrccFmhg8WWIi+bvY29
+7Yy64AWMbcRV7ESxPY3VMNzDFYzWAFwTDEXJQlna4NvInQu6BZpLJMS8fQvJ1Vyy8FvAVUXBRSzF
+AtzCRdz+0jVdp1Bcg2XcSXTctXWMzYVdm6BccR06WMRczYjd3KWJzjXYzwVd0SLc0xXe4UWK1MXX
+1U3E1vUK3WVemJjd9hOIczCD6aXe6rXe68Xe7NXe7eXe7vXe6eUC9qPXiuAAAjDf80Xf9FXf9WXf
+9nXf94Xf+DXfWhDb9+O/+8Xf/NVf/fM/gQDcd0CHABbgASbgAjbgA0bgBFbgBWbgAH4HsWWH75Xg
+CabgCvbeBBQIlIWAP5DfDvbgDwbh+OUArCrFULxdXtiM5lXhmxBb3/3dtRJdgyVd4qVhwzVeUGxc
+tV3eFV7h5y3hSTzhFOZh5uVdfHXhF9604K3hJV6NGyb+wrsVRR22i9cdYt31YcvVwyCu4uYt4k1E
+YkVTYiYW48Bw4kGE4ijOYNfdYua94jy03ZrN3DWO3S4GwS8GrRjG1xke4z2GijJGXkJU3imW49xt
+Y4EYAjpE5ERWZCrEQnUR2B/QgkiW5Emm5Eq25EvG5EzW5E3m5EiGBbHlwjQU5VEm5VI+wzX0X4M1
+B3Jg5VZ25VeG5ViW5Vmm5Vq25VtmZXMQ2zdc5F72ZUS2wzSuCELo5GI25mNG5k7+ARLG4iLU4kGG
+XToOXDsG41TOYz7G5qjw4zNGY154XCqG5sgtZLvl5mcOZ8mV5iOm5lWz5orQ42yGZ6oQ2z/Ww0Bm
+DHD+PufbGOfaNUVzzue9Ted1Dt0wjueCnoJt5mZ7htx/3tt95uZTbAu9ZWiAbmGBrua/lWGD1miE
+PmOFxueJ5oxx5r4DJOmSNunyW7+IrohhaIOWdumXhumYlumZpumatumbxumWpoP63d+e9umfzr/+
+xWh8hYcyMOqjRuqkVuqlZuqmduqnhuqoNmp4EFsBPOmrxmqSxmBvpg8IeICcBuuwFuuxxulhYGY3
+7mc4xl2Qto2AtujCwmN31miD5mgo9mi2tg2HLme1RmG8rg23fmu1iuu+mOt4ruu7vWu/7gy9PmN/
+VuzHAOzARqvBNo3CNux5fujEfmzIGOfIO9vPTr3+y3PkinAFPjDt00bt1Fbt1Wbt1nbt14bt2Dbt
+ZhDbzWva28Zt0BO9oa4IMfja3wbu4BZurxUDsSVb0EbuyVs9rq4IAWgE2Ybu6Jbu6Y5tVzhrgaC7
+xdPu7c47MGsWgVUAuRXv8SbvoDXadu47wVPv9WbvNiM83hYIcTiD+abv+rbv+8bv/Nbv/ebv/vbv
++RYHsUU87ibwAn+DxmPugWjb8mbwBhdvBbhucm5svhbizZaLyJZspaLsd7ZsJj5sWNRsC5cLxoZi
+xxZxzq3oDJ9sgu7wMf5wUwzxEycLEr9bE5fxsMBwFV8v9K7sFufjF89hYRbkG5eMCKe1nkPyJF/+
+OfEV2AEAgSeH8iiX8imn8iq38ivH8izX8iePAbGFuZoD8zAXc2i7OfjmhXVIhzRX8zVn8zZ38zeH
+8ziX8zmn8zRfB7HVOSXX8z2vgZ9LcF6AAD3Y8kEn9EI3dC0fgAjnZxOmcCKHixzXcXdjcR9fYiBn
+XSm+Z0efcUV/aBvX9M/gcXWO9F7YcErfY0tPXkxf6E+XXU7fa5Vea1a3CUgfdaEqdVMXY1QHZFX/
+aFl3XlefcFjva1+vCVqv9YfjcQ7H9dPV9XrmdWIviwgvAj6ndiVv5O+uCEY49G3n9m7H8mUQ23oY
+83En9zCvB7FVhzpX93Vn93anc3XA82qX953+83OUJQRvx/d873ZGAPYSb3RoB3UzF/VIv/Vlr+Fm
+L8IYB3iXoPE3FvYKX/iWMPZjB7BkN/hKx+yEfvaI/3XH+2FM/HeOd4mJp/iCv/jhRfgdVHiRL4Vx
+zm4Dh3nF07vRFojwdvCbx3nzFlsya++e93n1fm/Ale//JvqiN/qj7+8A5/EBj/mmtzsER1kBWPCc
+p/qqxwcI9/gOS+6tlzzRxnaBKG3qFvuxJ3vXpm0et+3cVvu117HdBlzfHu64l/u539ri5vHj5vq8
+T7HljvrnLvu/B3yxt+6sR2tGf3iWH/kUp3iiMvmTZ/aM7+iNR3zc6PcaD/nJLwWSP/bGd/z+0k15
+G1x5kW/4tD58zGfhUF98Sbf4zhfez2fB0Of4ca6E7aL92rf93FoCvg6ES+D93vf93wf+4Bf+4Sf+
+4jf+4+d9KwDlTGD+5nf+54f+6Jf+6af+6rf+62d+VDZzFmCD7vf+7wf/8Bf/8Sf/8jf/80f/7mcB
+sbWu23f/96d9XFD1QkD++rf/+8f/4w+ECNcrgUUVwAUIXgIHEixo8CDChAoXMmx4UBIASQ4nUqxo
+8aJAiBIxcuzo0aEzAB9HkiyZQiQvAClKsmxpEYAzlzJnItRI8+ZNmzh3ttTJ8+fHkECHejwpUCXR
+pBdhKm3q0KfTqA8jSq1qEKrVqkKzcjX+mnLVvbBix5Ita/Ys2rRq17JVCyBa27hy59KtG7YVgFZ2
+9/LtGxevXr+CBwsGTPgw4rnRACRu7BjtKpQAJlOubPky5syaN3Pu7Pkz6NCiR5Mubfo06tSqV7Nu
+7fo17NiyZ78W+Pg27rCSIOTufViAJAG+h/sFLpw48rrGkzOXC0FS8+hxuVKvbv069uzat3Pv7v07
++PDix5Mvb/48+vTq17Nv7/49/Pjy59Ovb/8+/vz69/Pv7/8/gAEKOCCBBRp4IIIJKrgggw06+CCE
+EUo4IYUVWnghhhlq2N0TFvBizEIgJmSMMSlQoUaIaohI0IofbvgijDGilwKIIF5DhTH+JxbUokE1
+NsTjQC0CKSORRRqp1CQe+rHSkj5a4Acv1/BYIonXuPjhNeCkoOU1JuqYQgoe8rJll7xYQAUVHoLo
+B47gCDTkkXHKOadH1wDByyrXPOFji0vueA8v96xyJZ+8qHHnjR+iGKSLVDzBCzh78uLoE3XQeSmm
+mVrkIxBW+mgoECvtyKiIhVpQolFTYqnllvd8Cqemscp66SSrqEliHacGusqjPQIq6KSGFqrGSh1e
+SeqVkzT6RKWzOvssndcA0OubLq6CY4kFgUnio9eC6aKIXkJZarUgnknFSmvieOex0Lr7Lrzxyjsv
+vQx1CSaYVta7L7/9+vsvwAELPDD+wQUbfDDCCSu8MMMNO/wwxBFLPHF1VOhrgbK8GNuuQiSSqOaH
+HqfLIonoHlRHyYt6uZKKxqBM5ctK4kjFuIMKtAqsCIUpkJ0DiZkzySSOzMvLxqhYUNHUBukyiSiu
+/GbJYlL0hJs3L2os0AQVjWKNIrfrsckGvazjmGiudCrT28ZcdtjG2Ixn1tqK2bNAPzvkcbZde/x1
+yaIS1PLLvLCZI5Qh57jo1FXjuWjhcQu0tYhFgzxQ0ifnKOrgNJuJK5VMG822qG4PhHNFFtedsZnV
+/ugxyHh/CvXlBqGNMpMzFz424hdNknGnAtGoepQz5w58uaMyerPUx0u6s5l+Czn+0D1APPoEEK4q
+Do7jAx0qUJK2odSil8kTTyiLxgN70IrMWzB0sBYBsSgVA/3e4o2H9ziqqsfjKf6Vy4u5vv6Opb50
+XS97AtkeL7o3JnINBAho4p+q8gc8WyFERNGbXvWuRLeKvE8g8TPU9whyD+Hd73gSvNL5jBe/C2os
+g8RL3/8IOBDsVWR3AundAoFXP7KVr3wnXBEF0Wcb6bUQUCLa4EUSRTWBNAl4T4oSkCJoPB2yq4dP
+YN+xnnczfUUJZ6uAkh9IV5FITcpK1GPgzTxYQhP2UH9wWtHzVvTBigAwjEycH0GeKKU1Fq+Nx0Ki
+6q74tQDC0YdfFJwYKUJG0xH+C43EEojiAgiuKf6xisbL00CuMagjWnIidbSZGMGHIkAOkmNa5Jjq
+QIRJnr3tlHE8ZBgNGDyNVa2RToTSHik5ST+uiJSqW2UXNdhJi1jMT5JC40D8tKO9gYt1pRwf0XBl
+xDa6cplqGBRYZDkmCzzhgyk4GioltcymXaloppSkG30YtYssMQVQOiYqBec3ygmtXM48JSpfVodp
+prOf5bomnlxlkTB184biBBIp8cY1w+WNlxUcn97AMTyHtBNKk/ADMpM5z8fVM3IeW6g/tZYjcOQy
+pIUkFUCzScxrKFN6GZVnj5ipt4YS8qHnxJ1HdrcKFPUOmYfaKETPqb+ECqT+oNXUHzA1CaL4xU+b
+h8JYoIbWoiumQGlBfSbw3lhTbRrkfR/sKcd+KkQfUrKXwxSRUampVmQxNZ4LeaqyUsDPqa6CV3zc
+ZU15NsxfclGTbqWIV1tIPhGuAqil/CE6r3SopLZyrcVrqzZ16rS5/i1UY0WWQ/VqU8b+1SJ2+qDH
+cnUsQVlVkq974eggyKgB5jVQRKSeQFNQ2M4mhAq9m91pO3jZVPoRhW+bImu5WhAL1BV2uWoRaW2K
+2dYGUa2sRa3vYugi2WJxIra1Eo1cxr49cVGXp31mc8332gwKN4/FBZzRWgRA5Q42rym0YvXGCyjo
+brNuI6MubQ/yWd/hin3+yd0tXukb3h6yELb5BexGPUqia9XTuwxNF+vAZljJ+c5smWWi7VwkLU/p
+bo6qK5oAzOngaDYNbyup3G6fdmCG1KFwpBIZg7PlYBOTOL19s9zHKhw2+oKuWhtecUEm4eFyeuwE
+2CPRXWc60+zGTrmZa9xIWtxDEx9Zxpml8NZQjLSPCi7Dre2xhgHAYfclmKMLxhZQI4g3hqKtyZd9
+MjQpJuc5y+he+OouR/AFpvmqZ3344t9F/AwmQGfFzvn6iKFTgOfz6FmuIxE0865zj0aPJNGLNk+j
++dyRTNO5057+NKhDLepRk7rUpj41qlOt6lWzutWufjWsY91q0frMUgP+EWSgULIUy4DoHpLhda4N
+4mvKgMPFB/F1rpPHmGFbZiWX6bVlNJcSTWvN1rdeRR0AUIeqHuUy3aYMDvkIhN9KK3d+YwxGmE2Z
+YKfE29MuiLqLrRBkpwS5IsEMiDDz7cnIm91dBcDwXDUZ3ap7Mr+qTL8REm1AneQy1JZ1VFJgyXET
+xCv0ruzASzsQdMNbMg+/OPR0bQEpIwTZvq4DtTh+FE2rPOQVR/m7DeKHybi4m71Tg21XfhCOPwHb
+pX1kMq2dwEh6JebXzjYPha1rlxudIC3398iN3fFuow7kLX+6zn0Hc5DfejLzVAMAlHXFrS+d6WYi
++c7n23OYew/i1gH+e6+eAAAX+yHbbS8IOHjVTVhhnd59L7u/xxTJqfvayldn+cfLjm6s82LcFPdd
+JMFuJca33MoDmQS10b7je9g966Mznc9LDni/P7zpgd9SQvzusl5ZHfFpd/rBDzIJcMyeRfNMU+DN
+LviEqFzufOa6260CDjHVPZPDRwnwjcF6wG888Z7X/d15JmbR5xrsizo87JVekOljXe5+GPlAqIA6
+2zyK8pq2wOBRWVyNAbyotNf10x39fBGO3uOvpz9Bfnxsj+c88Ng3yNWhCPBNiqK1H/vljhpYyQCC
+nP4BIJ9VCrUMYPBFHLvM1ptgHvIxn/ykX/Npn+nlXu4xXrAh2+/+NN3/4Z/8ZAzWgZ/3zV8HOiAK
+ZtJvMZGtnYn8yBX8lZ73XBoIkt79QZ8Ikh7YQUnrZR8M+o7NAF+5EWD0TZ0HvuAR9pyxSeAENgXc
+EY3K3Am9SeDY6WC7VcbdXcZKAB/XBaFIIBvVeMgJfiFljKFl0BrWWVbjsYsIPtvzcd1FnQyUAEHG
+jJC/ieDIjV/HVUbsseFkiMjTlaEO+mAKoFwRbhywGSJSgKCQcY+tSWDBZeD26aAdQl8VSkWa+EHV
+cN6jbCHzTQLK8KAL+qATxmCUTN/+sRspruHfEcQqVM3TyZ1lPIr4DRegmF8eDd5ejQmvTF+lFOIH
+3gM4gIMX9qD+/R2h7jWgE3IcFYDF0q0hFFrA9AEfFVgGLhmgbXjIAi6dNBphAoEjFX5iUkzCuIlK
+wxEi8LUKQ9RiMtZfxXFg211cqNCi8zHd06Ff13kI6nUdlABjkMwT9SCEGuTKB2Wis1Eb5wliLE5j
+6SXi0g3kRHIc2BWdCVak63FdA1bjm8yTZY3jPfKe6zWhOkaFtEiUB3Kd3E3UD/pjP8Zg1KXeGepa
+pfDjE7Lb01keENyJzVnJjXyQQa6d0lgAoUEK7T3h0/UiQ5DhM25iK94k9Rldw5njB3Zk7pkIQaCi
+90zCo6CiAjLfxVnlD4KlJ65kU1ABB5piZRhDJqKkB+pbwUH+G7FJHeEt3STQorcx4NxJIgSAo5lM
+i8Zgm7bZlSQuXmWEm0ElxEks2sV5m8NdJQpixi9aRq7l5bxN5aRcI8tVZstpyWa2YVNmUmAGSjcC
+AMGJYWkCQMLtXGUkXTqypW3eJm7mpm7uZp65DjnhRJvhzVJSSHA6E060jOsYFnsUZ47xpnM+J3RG
+p3ROJ3VWp3VeJ3Zmp3Zu54D4pnd+J3iGp3iOJ3mWp3nKpH8gp3muJ3u2p3uyJ3r2B3O+J33Wp32S
+p4LA5n3uJ3/yZzc24374Grb0J4EWqHn+Z4GchIEuKIOCJzhooIBM4oD4GoDqB4UWyIUSCEcKyIYW
+iIQKSIb+TqgI9keIciiE9keHEsiHBkiJsuiI8keLAkiK/seMRqjfeAEm5KiO7iiP9qiP/iiQBqmQ
+DimR6mjIVWh+hOgNvAKTNqmTPimURqmUTimVVqmVXimT3sCRJqiuXUORfimYhqmYFqkXyM+JAoiE
+ekIprCmbtqmbvimcxqmczimd1qmdruklbCmBhGgVTIGf/imgBqqgDiqhFqqhHiqiJqqfVoGeDkjR
+3QM+3KmkTiqlVqqdeoKZ5qffqKmldqqnfuqc5qn3ICl+8KminiqqpqqqJiqjjiqXQk+kgqqszmqn
+YqrvnOl/pCmt7iqv1qmo5hqp3oepriqxFquxGmqrAuv+q9pGrPaqsz5rKdjqmOCqf+gqtF7rrv5q
+jP7HsB6rt37rqibrtvrHozYrtp6rp0prjQaIhNpAMrwrvMarvM4rvdarvd4rvuarvr7rAzQqiKrc
+FoSDwA4swRaswR4swiaswi4swzaswG6BvwZI0RHCvlasxV4sxu6rDWRqgkioA7gDyIasyI4syZas
+yZ4syqasyq4syL5AxAJIiBJDL8wszdaszd4szuaszu4sz/asz84sMbwsjeraPcwCyx4t0iat0q6s
+A3Asgnjs0kat1E5tyrqsq+6pysnsz24t13at1/Zs0F6toxKt0VKt2Z5t1DbtrWrqQHws2r4t3Fat
+0Pr+R8x+rd3eLd7ybNgqq4aSbdz+LeCGrNpOK9sKhNsGLuKirdXyrYjymdbmLeRG7tfu7biiqN8m
+LuZS7eCuK5r6DQqUAOiGruiOLumWrumeLuqmruquLuh+wtySqMrRAhvMLu3Wru3eLu7mru7uLu/2
+ru/OLi28Ln8UHQSwrvEeL/ImL+uigNMeiLWiK/RWqra+aICqXJ+CK/Zm76GKK/XqR7lGL/hOqrpS
+a388b/ier5xOb7DaR7dqr/u+L/eub318L/rWL5yOb+HyAqfaL//iqfBWL59d7/sOcPbG77IGirn2
+b/3ib8d6rvI+MARHcOq6rtj+K59RQw5ksAZvMAf+d7AHfzAIh7AIjzAJZzA1/K/36lrxSjALtzAE
+M+/aNnDbZi4NR+3iVi6MZq3k7jAPgy0K58ejlm0NDzHLbi758gfUErESy20Fu6jj9jAURzHNUm73
+AvHlLjEWk6wR5+/hZrEXu8MNV3Gp6rAUl/EOU7H80kcQfzEbb7EMGy4bf3EYp/F81K0Z33HeovEB
+F20ce7EbP63fhIEJDDIhF7IhHzIiJ7IiLzIjN7IjD3If/PAY81nAOqwlXzImZzLDQmwTy6iuEcIj
+h7IojzIpP3IYNK+BmK8Co6/6Yqj1EjAsg6sB9y2srjL/MjAgD8T+2vL5tjLWBnAsB7OxzvLY1jL+
+L6MvLjvvph4zK0uysL6yMEdzqhKziRozM4NvMqfyMl8z+Ppy4w6EAEuzOG+vM9sH/XIz9Gazh/rN
+NpCCO78zPMezPM8zPdezPd8zPuezO7NDOddHiD6CDAS0QA80QRe0QR80Qie0Qi80Qwf0I/SzGqsw
+GegzRVe0RV90Pm8DKq/zDPcxFs+xKz8xHo/05EL0fKyxRy/xHytzR6c0EYP0Lw/E45I0TfusHtOy
+bQixS9fwSmtzS+80DcP0NwvETNe0UefsTRdzTgP1EPc0RwvEKcyCVE81VVe1VV81Vme1Vm81V3e1
+VC+BSctHiFKAKpS1WZ81Wqe1Wq81W7e1W7/+NVyXNQWEdXwUnQBkgFfntV7vNV939SlstIr6jSNk
+AWEXtmEfNmIntmIvNmM3tmM/NmH7AF3DR4iKwxlcNmZntmZvNmd3tmd/NmiHtmhftjhM9nvYdTdA
+tmqvNmu39mM7AmAPiCqj87V6swWD8zjnNrKatnucM21jqzoHti7/NrrathPjtm4nd6BSs8QSbQIT
+t7MGt2xvM3RDq3HDLDQrt3Yztydbc3VHd2zb6ECgQBCUt3mfN3qnt3qvN3u3t3u/N3yXNwUz7m0L
+xAxEAH7nt37vN3/3t3//N4AHuIAPOH7PAG+3B/GOQnwvOIM3uIPDNwwT7hvzQhczdeIKdX3+80JR
+HzWHT/GBswdKWzjmOrVww7GIYy6GHzdRdziL12xSV/NSn3jikvh0/7SM/22KY7dItziLv3hzQ49O
+33jc0rh4m7iQ4/iHr4cd83iH+3h3x/iRD3l4s6vfPEMYXDmWZ7mWbzmXd7mXfzmYh7mYX7kOJLl6
+hGg1/IKarzmbt7mbvzmcx7mczzmd17maV4OZp8fEjjmf97mf//mYP8OUd+5wf/ezXje3Zrd2Jzd3
+D613G/quSneR6y+kOyui062iL3puNzq5Onel96qkU3mhfzqtXjrsArOmM3qez4inkzqthjqhC8Qu
+u/qnmnoOo3qqb/qqM1qr0zqownqusjP+Rg87sRf7PfNzJyc6nwF0Qze7sz87tC/0Qyd7pw8EBEy0
+sWe7tg+7RsdwLht5lL9tjiu7TDN5j+86pl1xuKMtkYs6uK+72Y47pu+4uRu1kzs6lMO72bZ7rFO4
+visuupfHktd7Td97tef7v0stvwf7QER1Xz88xEe8VoM1tZ/6QFRAXGe8xm88x8N1BQQ8edg1Xks8
+yZf8w/+1t7O0QAy2a7e8y788Y0t2xd/6QFj2aN88zue8zod2ac/8fqA2zAe90Ls8bKe8T8u6r8uq
+rQMwcuf6OHO65T560lcqsFcrdU+9pS69hWa60wsz1A9vr2M91Q86wyO92Gc9yI9H+3b+vdenvXj4
+9tlLatWXr9/4wgHcPd7nvd7vPd/3vd//PeAHvuDfPTa4fXiEaDYggeIvPuM3vuM/PuRHvuRPPuVX
+vuJng+GDB/EOPud3vud//uD7AtlbvY0n/NLKu8WvOMHbe+Z/R4ibftqOPt2XPuwjLerTvOqvPk0b
+fNQjfO0j7cKT/rv//tHePtPnvu6PNO+DPZAT/9IG/+wPv/OrrPFvPb0n/x0v/8+r+/Qzrewjsd8k
+AuiPP/mXP+AXvs9b/0Bog+W3v/u/P/xXvja0vndMrPnfP/6XfyJ8/37Mdtz7KkDwEngPwD2BBxEm
+VLiQYUOHDyFGfEjQoMAqUzBm1Lj+kWNHjx9BhhQ5EmOVgxQlplS5kmVLgSkAnMRXimZNmzdx5tS5
+k2dPnz9pejoI02VRo0ddAkhx0BNQp0+hRv156WRBpFexYkVpkWRXr1/BjjQ50GpWs2dVEh04U2pb
+t295Cn0ZE21duxCVMoW7l69bqmQr3hVsdyuvi2ERJ1YMciyvwoMhZ1XrmG1fy5fjDqUbmfPZvAId
+ZRE9mnRp06dRp1a9mnVr0T6qBu48u2VhcWdw59a9m3dv37+BBxc+HLe42LSRs5wsoJtr58+hR2/t
+SHNy6y0/8zo1i3t379/Bhxc/nnx58+e5Lzl+nX3DwhVUxZc/n359+/fx59e/n3/+/Arr2wsQoeUy
+QM/AAxFM8LxTqhPQQYWyc8CdCSms0MILMcxQww057NDDCV8A8MH2CiOmlxNRTFHFFVls0cUXYYxR
+xhOJEXHE6ya7Z5YPeezRxx89dKDBGx+MEMgjkUySwxABI5LEsngxccYpqazSyhhrbNJJHDfTUckv
+wURSyLm2dNDIMNFMc0kby+ysxCvhjFNOGLN0DMo2Z8txRzX57HPCMXmZDE/rsjvkhUMRTVTRRRlt
+1NFHIY1U0kMNYXPQwQrLJpNNOe3U009BDVXUUUkt1dRNs7H00rsmg2CJSWGNVdZZJT1kyFVpy64p
+zHjtlaa/7JQNV8EKO2yxY5H+Dauxx4ZltcvKfI2WL7kC3axZznSVVtu9gGX2WrSKTVbccUVa9s5v
+0coR2m3ZfYpaQdEVLNt26XWq23PjzSpccvnttyRV8z1K3XoJ9uldawOua96CGcbpXmETRmpffylO
+1lyIIzZq4IY5rungjO3K7pkwSC7Z5JNRTlnllVlu2eWXSdYBYJBXKqyaX3DOWeedee7Z55+BDlro
+oXGuZmaaU5qMEJiZbtrpp2F+5lakrzrTz6vDZDJYqo96c86vwYazTm+5TqvLPbFOO0lA4S27KKvV
+jttHrcl2OyKvw85b7xfHxtfuiPSUW/Ae2Ub4b5bgHlzxDOn2+3CH8N5b8sn++8b48YYCX1xzDAu/
+PKmlBJJw89EpbNxyzxWKfPLVw64cdcDPJl32zl9XKbsmlMld9915793334EPXvjhidf96NoLE0GK
+5Zlv3vnnoY9e+umpr9765UU4/vXJrine++/BD7/4Jqau/aHszF+o7vS3Zl99x9lv230y53cI/frb
+x19L/fPXX/75/6e/+9VvfekroPkOWLsAxs9w/OMFAMBhDAlOkIIVtOAFMZhBDW6Qgx3UIBXgZ0AA
+UMGDJTThCVGYQgmC8HTpg4kKYRhDGZoQHA3k3wxxmEMdTlANDuSFGnYYRCGisIcOtMAQkZjEDPqQ
+iU104hOhGEUpTpGKVbT+4hWxmEUtbpGLXfTiF8EYRjGOkYxlNOMZ0ZhGNa6RjW104xvhGEc5zpGO
+dbTjHfGYRz3ukY999OMfARlIQQ6SkIU05CERyQsgrAIh1wBAEV9ykBBCDgCVtKSdBGJJTWZSWASx
+JDj8QMlMGgMhBHmgJitJSlRWMpOaBCVZGAKERybkHsaoJBCK6ElNGkSXEAwlQ2Cyynv08pUKUQMj
+z9fChFhlkispyBOM8YRETvMufqgDQiYBjgFt5lxPWEUdRgjJ1BnOlA/E2LnKyQsL1OGX72vlJKqC
+kDv5DUopqIM004mQJ1QSdAJRAwDg+QR74rOB6VxnOxmSz3TCRJoJMYb+OIF5jZRYJQUSzYpVLIBM
+am7ULOw8CBX6eQ9wSlJYq6CCRL/Z0HGu1JwLQae1UqDNhNIFAMa4JyxJKs9zysYq+TxINrOJEGP0
+kxdUsAAmWfoSmbrHWvk8lxqWelFlJsUgT6iDRTma1aOsApn7LOITwDEJbgorBYFxnE+RSs9OWsuR
+WKUlTe9BBSDglJM6dSlPe4jWolZ0lrzwKkLUIFG95rOtooynJN0aKNAZwwI1NCoI63BUq6gBsqCj
+LD/rapUnyDKypFRDCuz5GW9WchXSHG0dYFKRVcBTq611iTUFYgEqDKWsY2VqYg9bSrje9a3LtFw5
+C/LPUDqVpzsdCjL+0erIHoKUrr1Nal2ZqlvaKsQYrB0hSvNiz5ailhfXqINBqvtDZhrEKsYAwhOe
+AELH1IGRfpilMUq7WUbG9BqjrcgkSOla/a7Eo0BgbVyR2tKFrJO179tlWlGZ35f6dqZ1HShx5Zng
+VmoSdGidxGx5MYlrBvitqGyugBtcFVQe1a4P/GU5TWkV9uK2u+M1Z2ExSZCGFsSRDf0nLyIrEEdW
+RK/79fFCUlBaAEjUqry0LS3BAY4WohW4xpXuQWDM0rJQYRUQzimEAmOBIXNYICDUZCiVW8qjDpat
+W45ubr254SuXBcUxsco1VgGOOuBSnVQAhyzJm+d0OjLABeklK6H+xGYb/pjQ/owshv+cF3TWocBn
+frJanavUM5fln4Kap5Pr6tMoU1kgQ0UIEJZC5gFF1Z255XJZBA3LOwm0Dv8soouDa2ZTppPGhgMH
+iXc8EDUXmtcISXKj6XouKgA7xI/GNF0POunABLPE0GVwTn2aAgwLRMNkmYQ0NSzYgm4m2Yalqzfn
+KlTr8pguKTYIdwMFDldnGAChdLF50ateWoM3vqsgJX3t+5L89prf1cItrT0szGIfdpXM9DAxESpl
+2aj3yhM+8J3AEWpUxrTRjjyxl+lsp4lrvJLF9DbHb6nSlyAz1Zi0ih8w3sPQDhWgLoYmBFcRk3n7
+VZYAOO9clJL+giL6t98997lDrkHqutyjoSJFilVF/nOl/7zKg4k4zTVaFNAuneorOaIFSSwYIFqQ
+qFy7egWz3pJrdB0tQCRt0lsS9aqvne1td/vb4R53uc+d7nW3+93xnne9F1KJffd72PG3db8PXogQ
+rZ/gCZ94HEIRgop3PAwHOD+CkPDxlS8hC304ectvnoM1ZDzZ6xd59yXwdaRHnek9t8DQg35+omcf
+6i8H+8fJ/nCqbz3r3ed6EU619M3sPe9RZ/vc91MSrzD+8ZGffOUvn/nNd/7zoR/942NV9wiEEiaw
+n33tb5/73ff+98EffvGPX/vaOz2UpJ9+9a+f/dK/QfkcmJ3+YlSM/scCg1lxv3u9dKxj1KL93wqD
+DepvABGjMYSPfeSPABXQK+5PkvLP+gJjV/ivYfzP984vMARwATUwJAxw0PAnATcwBDuiATPpAZEH
+SiRwAgumAoHPcwJQBGFQIzrw8w5i/mIwBknwgUzw9/ZPBVfQ/FwQSjLwBkVwBp8oO7qgB5RwCZmw
+CZ3wCaEwCqVwCqmwCpeQEBww86DkAtqhC73wC8EwDMVwDMmwDM3wDNGwCy8ACGMPSpDBCuEwDuVw
+DquQEuCPf7IjH2SHdGYB/7QwMKSEdQTxa1zHgQrjBfZwdGjHifIwETenD7PQEKEkEAexEq+kEPnn
+EB1Rcxb+sYkacRMVBxJL8A8PghIt8RRnBBP1RxNBcXA6kYk+sRXlRhR1kBQFwhRRMRddRBXxhxVl
+MW5e0YeyIw9EoRiN8RiRMRmVcRmZsRmd8RmhsRgFAQIiMROhpACAIRu1cRu5sRu98RvBMRzFcRzJ
+MRsLgA1nD0o0IBrZsR3d8R2hUQPuUID6yQaJMARzsPpOMAJ9kGFY0BZ5YQjvUQONkBHrcSDx0Q8l
+kR/7kWD+cSEPQiARkgAL0hMPciIXMB938AJ7sCHb5SGtEQMxcgErEhb7aQOIIyVVciVZcjjgQACq
+cRWhBBSkoyZt8iZXAxTQ8XAK4w5a8ieBMiiDwzjoxyD+D6ISFCQplXIpyyMDYHIUIVIgKKA/qLIq
+rfIq+YMCdhIAoWQJmPIrwVIpGWAeP7Cf9PAX44YW9ZEHb1EX3ZJvttJufBEtsSYY488s6VJt1HIj
+gxAQ3/IvV4QXCQhKEDEv65IsV+8gztIw/WQvARIXAdMtBVPyCJMxr8Yu8bCfuqADOLMzPfMzQTM0
+RXM0SbM0TfM0OTMXqBEqQ/IgeGAcYDM2ZXM2abM2bfM2cTM3dXM3YZMH4tJtCoMTUHM4ibM4jfM0
+3QAxb68GR1IBNRIgU9AjtwUkZVIkm3MAS1IYL/I66e85o5IXolM6pYU6e1EIubP+svMumfM8K8Y7
+W1P+IMJTPH2FPAfTOtnTX9IzM9fzPvvFPauzI+UzWuiTMu2TP8klP+nxIIbgOBm0QR3UNLGQNf9T
+IKCBNy30QjE0Q3cTGn6zbAojFx40REW0QZlAOYdPMS2zMRXyPaMkMl10MkevMlOUTzAzQQViMWcU
+TRzzOyHTRVERRl9PRnMUTWq0LFF0SHV0RSe0RX30L4FU/wSiMJEUTIo0MW90SsNkR1m0R5u0Ep8U
+Ag9CSrF0bUwUAftpDyQgTdV0Tdm0Td30TeE0TuV0Tuk0TRFhNWvxO3VhBfi0T/30TwE1UAV1UAm1
+UA31UPlUFzqUawpDEer0USE1UiWVTuWxKC1yPw3+dFz8szwZMkDHc1Gp5gUz9UDLNH1AcFTFZVPr
+E0A9lVcGNEYLFFWPBUGNVCDsUVbtT0k5lVVb9TJeNUhjFVcTg1atlBfQdFKRNVmVNU7vNCZ3VSD2
+FFGldVqptVoNVVH3Z0kddVm5tVuRtVKrhQavdEyVREuXlEu7VBC/dB/DlFyVpEqXc1zd9UjM9VmZ
+NF1zcV3ZkhfEdF59BF5PVF791UfqdVXbEl/zFVSRZi4HlkcA1kyPtGF7pGAJtBQRNmGz1V77VWI7
+5GFNtZ8WdERFdmQh1FkNlhcqVENVdmVZFjc5NGNPFkRJdmZpljNL1FJNElOFNTFUtWLhs1cFVGH+
+aUZUd1YxiDVeeeFWizYsehZWeRVop0VoQYZol1ZZStV8TrVqwaJpgfVpoRYufhVKA1JrC/Bqaydr
+ybYruFZs4/NrwVZqM4Zq05YkjjZgeeEcYiFv9XZv+bZv/fZvATdwBXdwCTdvyQBP15IjBYIHkqBx
+HfdxITdyJXdyKbdyLfdyMbdxfRNmfZYX2KFwQTd0RXd0CTc5cVY7I5ZjPYRinfZgL9YS9VVx+VV1
+HdZsXycWaZdDWLdrXfd1BzF2+7Jdc7djbRd1cHd4M2R3xRZdfTdvgLcNA2NjkddCPBZr+wkpwzJ7
+tbcpnzJPWXQqsTJ8xXd880MrObd1ecErt3f+fdmXO8bydNVTIFBSKOm3fn/yJU22c2kSJ/m3f2tS
+J8+Xd3nBJ+23gA14KIvXc9B2bkVibcH0Z93WV+E2YuSWgTkwgS9ngS34IxyYXSE4gvsibB94bDdY
+LDD4cTS4hDmig/e1bUFYKkTYg0lYhRnjhA9nGOExh3V4h51xGvMXfbGxHIV4iIm4iMfxHANYbNeR
+h5m4iXMYXA/wY1N3ei9EeUeYeZsXbJ43HaOXijWkes8WL70YQ6xYhrE4i+dki3lSSMe4QsD4dsW4
+jSukjPf1jNE4TtSYK7tYjt3Yhv/meOWYjmXXju/4Eic4YRhWjt/YeDWTDh35kSGZCiPUe5f+lAvT
+8JIxOZM1+QzXMIlH+A0jOZRF2ZHtEH7101ZpOCRYWHZd+IWhIob3VSJTeSPqFmJReZY9YpWD94Nd
++S1gWXZlGZf/xZRtNGmFeQR19WRbuZeB4pd3eYaPOSNqWYpvOZozQpeh12uZuZkPOWAq+Jin2XoP
+Am9Jt5zN+ZwD93B/WIAZN3Pd+Z3hOZ4vd3P7x14/F53xOZ/L2XTD9QjjmI/dQZCfmZALuUryWC7Z
+mI8XWYH/mY8FOpt7t6Cdt5vzJZHbeKEzuKEDOZk7l6AlOhUpOl4seowxGoX7aRDaN6W11ynXWWwN
+gHxhOqbF1wBCGl0KQ31VOqeXcgf82G7+smN+DziohfoM8FdC7XV//TeplVo1ALieT5aAhzqq7Zco
++9koq9mapwCbuVibt9lgavpbvlmYwzmMdTaatXqNO7Wro8KZIRqarXms4bisj/ms9Zir1Xon2Hqr
+BSKYxbqn3QYJPSCwBXuwCbuwDfuwETuxFXuxGVuwEZcv25oZYGCyKbuyLfuyMTuzNXuzObuzPXuy
+meGrr6UwhKCxTfu0UTu1GRsQ/LpsALmNH1qv7/WjW0e0m2Wkvbikb1ijYZuj0dejaZtObHtYcJuK
+dfuPeXuMYxutLTa4a9uTZVh6Sbq1uea1ldu3BRi4nbtFDho4E1qRqZtqskMZ8qG8zfv+vNE7vdV7
+vdm7vd37veHbvCEpcZ/ZBVrgvvE7v/V7v/m7v/37vwE8wAX8vl1guHGlMCohvhV8wRm8weE7CsIb
+aeiboQFySS0cf6JYnFH3Oy/8ZP3HA4v1lFm0wzv3wxkvgjgvxTFowtOR8lT8xVfIAoPQxWFcxT3v
+iWo8xyUI8A5Px3Pc8OYH8Xw8xfeuyI38yJE8yZV8yZm8yZ38yaE8yqV8yqm8yq38yrE8y7V8y7m8
+y738y8E8zMV8zMm8zM38zNEcInLsINZJnyoMxO1HwoBLzsnJlRIuIVgNANhrxlYJyr4JglIA7UTM
+koDgGhKNxdP8y1Mg3ARikbbpw37+qOZujiHwpcmeC9k8iiFMSqKuAQgUDGO8axUkirKmLamugYSa
+LdFVHbAAoKH2qZ2sqdxsLb5QndIhxtIjzdRiqiGgJMz8xrz0KawGzr1SfdWN/dYEArZ07NZknbqK
+btAqfbdyvbmiLCH2/CSkCV/+CptK/cmSfd9AzNiNfdEFYhX6qbrazCF23dYV7tJPzXLWaYR0ruFM
+DdLpauxETsbFHcz/SZpa7SXmKt0XgtVOp88RjMK47N0hR9oAgOTo3N3JYsSKfd8T3aj8QKZEiqDs
+XcOMgcXoHaei/bmqvSHcq4e0va9+Sui+7ZsmnuLRfBIWCXSCaZfQKqamKuTDHdL+82ndXSrf82wh
+gL3T7uHpSq259N3lu9yR1I2lfGrbk6ndpz3Aug3oO96vTMrZGmnF2O2mih7cWh7pzdzOSu3PjCHR
+eP3WaarPyR7kPG7g/1zrTwmVKgLOwKmmkN3ACN3nwX7v9UcNiI3vAT/wBf+OUuCCgPwsvo6CeLwo
+MGjwHf/xIT/yJX/yKb/yLf/yMT/zNZ8zQKvzPf/zQT/0RX/0Sb/0Tf/0Ub+ifGjsUr/1Xf/1YR/2
+Pf71Yr/2bf/2YZ/xCm73eb/3ff/3gT/4hV/utXD4jf/4kT/5g78FL2fmlf/5oT/6f19cR9xeSdx9
+Mrz54dxur1+Au9+Ftn97wp/+mqvfw60fw8c/9dKfrAViAsrh/eE//uV//um//u3//vE///Uf/g18
+VQojEgBCmsCBBAsaPIgwocKFDBsKjMQr4j0A9yJavIgxo8aNHDt6/AjSYwoAFp+UO4kypcqVLFu6
+fAkzpkyUEyyODIkzp86dPDUCSGHRwayhRIsaPYo0qdKlTJs6HbrE4sSKPatavRpyqkVuqrp6/Qo2
+rNixZMuaPYu2KzepFLG6ffv2psQMT+vavYvXqQObJOH6/Vv1Z1B3hAsbPow4seLFjBs7fkz4BVuq
+gCtbzqg1IrFenDt7/gw6tOjRpEubPs2Z2OTLrFnL5XVvFuTZtGvbfrw34uv+1rwtC47o4Lbw4cQb
+S5bYtrdyt5l5bUYNPbr06aZVI6e8PDvP17GLe/8+PDev3drL8/zNKzj49eyNrzYPH2Tz59Tr278/
+2jrs5PH7b+QuW3sCDkiYeOT5h2BG6O1gSoMOPghhhBJOSGGFFl6IYYMIvJdgh83Vs0uIIo5IYokm
+nohiiiquyGKI9XDYIYKvEZJhjTbeiGOGO/AVY48WoacegUKCd9x+2PkI33z4Lcmkffo1hyR8AA5J
+pXcG9hVlgkBWyaVwRUKZpXZKNklmmaU9yV+Y2k3ZZZuzXakmglu6Sad718VZ3phm7slnL2geiSdv
+bNZJKGJwBgrfnIUuGhn+jIi2pmefkjL556PKDcpooYdamh16wuQIaqiiWsiJo5xW1pwsi6zKaquu
+vgprrLLOSmuttq4qi6mn/vUaBAiMCmywoQrD467KKZopoV+maexfkU4KbX2VNlsZpsnSuSm1lyF7
+rZvLAqotVs9GSy5004YLl7Xddpktun9xuy6X37oL17jl3kvaufRepW68VLa7r1vonZJXwQYfzFRU
+dwZ8VXNxyAFxxBJPTHHFFl+MccYabwxxHLoynNNrAtCFcMkmF3xKsSALDFRElrwBc8wyz0xzzTbf
+jHPOOu8MsyYfrywffxSkRXTRRh+NFgU/Ay0SlgLQw3PUUk9N9c6WqMz+dGAtp+evt0tnvZG9+I79
+mb5gg9Rv1wQCfDZO8KpN4LxtZ8UffWTfXfbXc6vcHdxVsr23R2/73Z7cgXckNt5jm314RmkTvh7g
+jfu0dRFmXI555ppvznnnnn8OeuiiX86O3oE390gAqq/Oeuuuvw577LLPTnvtqj9i+t69cjF6777/
+DrzoRWA9eUeDQ05k7nMnrvi9jBevG5Z9Iz+g5ND/uHWQ1BeufNvMN0/u89A/vj1x1l/Py/HlD2c4
++gs7B37z4hdP/vq3nX+9+vbb1r7738c/qflNrn77ow3+oIceEsxhgQxsoAMfCMEISnCCFKygBRdo
+j+6drTlYmIYHPwj+whCKcIQkLKEJT4jCFHoQCxoE24wuCMMYynCGFyQB8dx3Ef0VcDb9Q9//ANgn
+ATaOgDvEzQ1xGBEdFtExPbzeD4G4JyEejohLZMwBi6fEKi6midB7IhTLJMXAUVGLibni5LJIRsRw
+sXhe/GKTwqg76QUojbUxY+PQA4Vg6HGPfOyjH/8IyEAKcpCELKQeR9DCrKXqCIxspCMfCclISnKS
+lKykJS/JyFy9D4e9UoIhPwnKUIqykFA4IhLRSMfCrHFybXTjkuA4tzGmskCmxCEqZ7nKxrXSlfeB
+ZdtkOUs7Hu6Wqczl4XbJS2klkmnATKUwAzewk0lzmk1RmJGQ+L7+h3Fsm9zspjc15rFNuk9kJKOm
+Oc85i5RFD5sK2trLqgbPeMoTZz4Tpw+FhrR86nOfZlGaPa8nMqjNc6AEhefV1snOHGZvlrQx5unq
+lszwLRNozaTjM/dGTDo6dG/IjKh0fHm2iqbxonPLaBo3ujyIejSAE12ZSMlI0rahJxEmqKlNb4rT
+nOp0pzztqU9/CtSaluqfXeQPC8KB1KQqdalMbapTnwrVqEp1qkhlQUtB1qs+BHWrXO2qV4GaiFq6
+Dz2eKIVZz4rWtKp1rWxtq1vfCte4mvUSV2VYc6owhbzqda987atf/wrYwAp2sITNaxXqGjDu4EOu
+jG2sYx8bV0/+iBV9ZIWsZS+L2bfSlahs5A9eCwva0Ip2tIM9LGcHKL3FZna1rLWsZBGa0CRurayt
+ra1tNYvYfd2VtLztrW8Fa9prYlOxty2ucc/62vFgKbaVPa5za7tZ4SJxt7+trnV5G1wwoY+4z+1u
+ZpN7IGyihxEgKK95z4ve9Kp3vextr3vfC9/yLiO39GqOOtKB3/zqd7/87a9//wvgAAt4wPhVB33d
+NaP4KnjBDG5wfBkx2fzN1rsUtmx0tetEz153wxwu7YHRxd0Ki1iu4F1uQps74hS79cLMuidlPtvh
+GMt4CtltMUBTq+Ics7XEscWeRWir4yDP9cPhou6Mj3zdGoP+a3w4FrKQedzj9E3YyUFm8ZI7+2Ik
+a7m6SmZniKmsYij3GD0JmIeZz4zmNKt5zWxus5vfDOc4mxkHRNZWc+yAhzzrec987rOf/wzoQAt6
+0ITOsx3qTK1epULOjG60ox8d5wREGIFTBrOKrcxOI29506Lt8nCbbOkUi5m5lQ61iDGNTU1zetUe
+Pu0QQW3qCo/6xKWOtXdRPV0Ns3rXwEV0s75s6+7Omp1khrSxj43sN9PZ1cfkTzzYAO1oS3va1K62
+ta+N7Wxre9vQjoevjaXoZIt73MeWNGxJ/eNgVxjXOFQ1r9+tV08jEdjqPu6wxVvrehuX3f7TNbz/
+bdhv74r+3vq+7b1Pme+C25bfLrYIjAEOb3lzEtYKN/iksZjwirOW4RnOMsT/LfFxUlzjrT24LbdG
+XgerfOUsb+98mf1QyqAjDTSvuc1vjvOc63znPO+5z39Oc3QI/FQJbrnRj75yCJ+b1ukm+W05XlSP
+f/zdId/uyJ3+3YufMeNYt/DQOeXuqXO66jeWimq7zlqTj5XraHcs1LHscLFT/euWInjbH6t2yrL9
+7nJ9Oyv9LfdVk53JZud71pdO7K1xgACMb7zjHw/5yEt+8pSvvOUvz/ha0P1RzXkHOj4P+tCLfvSk
+L73pT4/61Kv+8+/YPKJ69QfMy372tK/95Tmg9Tvu3fD+uIU5RwEf+E0Pnn5X5z2Jcz/M3RufrX7X
+JfCDr+Xho7bwy8c78qGp/OqntfnNljr0tyz9V1Nf+4zNu4QtogB8qH/97G+/+98P//jLf/70r7/6
+C+H6QDXHG2Dov///D4ABKIADSIAFaIAHiID95w35hyciwwr2B4ERKIETWH8KcH0YtTWOkAUbyIEd
+6IEfCIIhKIIjSIIlaIIb6AMMGCfNIQ5n4IIvCIMxKIMzSIM1aIM3iIM56ILioIJqIjLdcIJBKIRD
+SIQm6AgXWFLZR35D5nsp5X3fh2ThN0XFt4RrZX6U1nRVCFfcF3NxB4Xg14NhYndamFZXiHFZSIZt
+xYX+v/eEXyhjUihGVJiGZmWGW2cRw9AGeaiHe8iHfeiHfwiIgSiIg0iIeUgHYZglzQEPZcCIjeiI
+jwiJkSiJk0iJlWiJl8iI8ICIUdIrD1CInwiKoSiKhDgMSChTSriEa+iEXuiGRwaHcTR+c2iFpng2
+KCaLaqWK3vN8rchhrxhLcjiHdah7aHiLaJWLG7SLvJhkm4gkYyiLwph8xFiMTChd7ZaMyshlzOgj
+zhiMtAg26PEBkCCO40iO5WiO54iO6aiO68iO7SiOGKCNPdIcRlAM9WiP94iP+aiP+8iP/eiP/wiQ
+9WgE8Rgjr6EG7oiQCamQC+mOH+CNWYMe1nhlfzeTkc5XkVOYUOGFcJlmY1HHkRcZhxlpYon3kSWZ
+ah1JfCIZZeljDCngki8JkzEpkzNJkzVpkzeJkzlpk6uAkn+3CjoJlEEplENJlC7JkyAZR0WplEvJ
+lEFpDCMpXgAglVNJlVVplVeJlVmplVvJlV3ZlUiZUl4plmNJlmVpllUJlr90lmvJlm1plisJl3Ep
+l3O5NwEBADs=
diff --git a/Documentation/DocBook/media/fieldseq_tb.gif.b64 b/Documentation/DocBook/media/fieldseq_tb.gif.b64
new file mode 100644 (file)
index 0000000..7b4c176
--- /dev/null
@@ -0,0 +1,445 @@
+R0lGODlhdQKaAucAAAAAAElJDK+vr1YMDBUVZC8kDQAAVkYQEBcHOwYGSCEJHSAgaKOjoys8DDMz
+CgAYGp+fn19fFJmZmQoKO10wMA0VIAAAcDsICCsMDAcMT1MMD2ZmAAcSO29ISFUHByIAGoiIAA4H
+T0pKDJaFhXd3d0EgABoaVGYyAC4AKXd3ODs7BwAAN1MAKQAAYlZGB2JlDBwcWWBtYCA3ABAQTQAA
+ZQ0VQD4AAFVVVUhjSCQMJQAAfBMHMkQgIEtLSzAyDD5VPmZmDEZRB2FhEWZiDFo2ETkdCwAAVEUt
+Gu7u7js7Ozc3N3d3WACPADU1NTMzMyBRIDgAAEJCEHEAAEwNDZeXAABpAEQFBSMjIxgNQDooCBA9
+EEhIbwBVAAw/DAwMPgBNAENDCgc9B8zMzABDAD4MDAwOKjwKCkQWKUscHAAAcUtLFRMTEwohCoqK
+AA0NTBEREQgfCBUqIgApADIAAA4ULzg+DEEfH3wAAAcHSaqqqlkcHDgMDKSkpFQAABUVRjEwCGZm
+B00QEDAwXSUMJGUAAJaWlhQUUnx8jVQaGgcGLggSGy8GBmw4OGNAL4qKioiIiGIAAEsHB3JYWHd3
+AAAAPlctLYQyAGggIBgAGkIVFQwcJRgYSA8MU9EAAAcHVQAALRoaYbu7AEY1H2ZmZlxdEHAAAD82
+DlhqWExGHgwOUzMzDAAAmgA5KTEHB2ZmPlpaB///////ACISRExUDTJPJUQrDAwMVhISSEhISHd3
+IC4xCjhcOA4ORERERBkVXElJAG5gYFhYcnt1ZkgGBlYAAAUFMTg4ODo3BTJrAFESEmZmMF5jBwoG
+Q1paDUkKChxGHN3d3RwYRGZmHCgoKFMAACYmJi4YLhQ+FCIiIhU0FT0AKR4eHmVeBw04DRAsEAwu
+DAc2BwoqCgAAPFdMDQAA0WAqKgwiDEgZGRkQRAckBxsTPDEwDBAQEDwAAEJGDAAAU0FBQEJCDLu7
+u2IYGJoAABgYRjg4bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAALAALAAAAAB1ApoC
+AAj+AGEJHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuX
+MGOelAegpk0AJFrSrLhTpYQ3AHoeDFpQqMCfQQHIXEh0olGBYkZtpGkTW56B0EYBfTMKCUEJEqja
+7DpQDIAbBJsOJHF1qdu3cOOqVKtTKcWnEOnmlQALWk6Eep8C4Ou3YWC7JUlAg9VUL0K8vcRMRUwC
+gFdoXBdD6+WE4A0kQqE5kSqwsuWBepFg8yq3tevXsPPKg4n3YW2HjnHPZrp7oODehoHDui2ysfDH
+iKFi42iU6A20A5G84SsQrdE8iKdPR3181KPY4MP+NySBC4L4lHRJAI0MSwwJ0++B5nSvHqdAJPVv
+LHb/U54YJzX99RR+QOnX3ntKidELANiMYlce2DB4FX9vHMdYTfIQeNZ+8dlHkFg9QSihQEQpyKCD
+H9q0E4X+AfhGTir6ZhMskWGTU33Y8EWffFC5OB+CONX3V1BixVgfe7DgWFlB7621nmRMAjBdLwk1
+Bw0SAEBZ1mKw5PHddQ9aNgp0jB0nQWfnpanmDTVNU56aI6lFghOLkbAcTVJh9xl28uCJBDQ2Jkkn
+EqN0Js8bvWTYy3dmzfbUnFcWOhxXsznxmWhKHeooANAcmihrBhEFKaGGAtAVoH9xN1ymFa66GFH+
+lv4JYEFE7eRphi/21ephJDqRR6fY1MlqnlnCkitmfZra5VlI8Fnms89CmuRy6jkKVEGLlkbntEwG
+CwuKyK2VE3HfLhaapQKNuSxrjpkF50Sg9SnvvPTWa++9+Oar77789lsvPDcBsE0Tqb67kVpWDVSh
+UMbRxKUEy23XV5YOFwRNrckZS93FYlRs1sNKjZLqDSRUnBBREnNsMsS0bvrtyDD6x+lRGWPsqkCZ
+pSVcT4MZtCRN7M6Ws0AM70bU0UbPljDO8uQ4kAQ177a0scA5TWKVAQ8mVJECUbnqTZ/h3NYb30Hb
+ssEQFZn12my37fbbcMct99xxo62RWlknq2r+mVsrhbfeRzmBDZsu68xdT33TGHDJGYc629+JG77T
+gjfFHLmqtiKWFTZv3CAZr9CKcQOiC66q6uadd4yYcc+ynrdav5EYMHAIYx2dVljunGnZtWF3E5q5
+5Wb3QfH6a/zxyCev/LwAB3xFEoUMnxHCuu9N5Myw/KSxQCrbZRaUNhOUMsV2XQzyy0U1fvb4qj/8
+xtk7iey4+TTDn2njBJpNtF1N5Wp60QQhEABb97ikwQIbwrFa9qImEAQmRGKMsZ2MaESmdCmFBFCq
+zShIs6xXWUh40gthStgEAHZYSksitIictvWIN4BmdUnzE6oEFalSQaVYjwDAVR41KEkJpRf+l5qV
+piYFuOEUjESzGZUPTfWnQEmOVdYqIAVlxcDMKewvdtKf6aBFtr4s6IWq8p+dBog0xrRFVCx0YbWG
+EyFslU1aLfRKyaa1GHDNMUW3QwtmDOSXa3ltiwF8Q1tw9p12qS+FiCxJoTyXyOkBpz5OkAwZk1Uf
+smgobEI5UmUeMaD8eEUoSFjQlI4SIadlsnEAEsMlP4kToJDliaRkEHWIEkopSeCPSPwfYvIAoLNI
+JpUEwcz7mgIxBqmnQjDsUi89N8lniRIWwIQklKSJyyRxUJokygmhbMm/I6otbH3RijFp5J4JFkR7
+BJFU3rJXwUa6UySgemddxHPEhZBLnij+AVRDVEm097XmBtTBp0AHOrx7ukUeZXOIQQk6klFYqCBj
+QgISbsBBuOiToRjNaHgWCieOarQjhVnIRGsCzriE5aMoTalKV8rSlrr0pTCNqUxnStOa2vSmOM2p
+TnfK05769KdADapQh0rUohr1qEhNqlKXipARSOKpUI2qVKdK1apa9apYzapWocolgxwiGGANq1jH
+StaymvWsaE2rWtca1oTE4BRwjatc50rXutr1rnjNq173CtcYJEQYSwisYAdL2MIa9rCITaxiF8vY
+wAojIVuNrGQnS9mtAgMh0GCrZjfL2c6y9RAOYUQnRkva0pr2tKhNrWpXy9rWuna09Hj+6ALIQdva
+2va2uM2tbnfL29769re0bUFCnsCE4hr3uMhNrnKXy9zmOve50C3uExKSi1hY97rYza52t8vd7nr3
+u+ANr3VzkRBIvPa86E2vel17icesArjwja985/vbBYR2vfjNr35ZG1uEzJa+AA6wgHkrXIQQN7oI
+TrCCF/zc6SKkuuKNsIQnTGHwkhch5t2vhjeM3/YeRB7vHbCIRwxg+zZEtBxOsYr5K1sSu/jFvi3w
+QQ7M4Brb+MbMdfBBIFzhHvv4x9298EEyvOIiG7kTHjYIiGHM5CbX1sQMQfGRp8zh/h7kv07OMoll
+bBAa4/jLYF6wjg3CYyCb+cwUFrL+QYhM5TbnN8lFCbGW5yxgKC/EDlPIs573zOc++/nPgA60oAdN
+aD3zASF+cIOiF83oRjv60ZCOtKQnTelKK9oLCfFGNzbN6U57+tOgDrWoR03qUpt6095ISBSawepW
+u/rVsI61rGdN61rb+tasjkJCzFDoXvv618Am9B4QwgdLG/vYyE62pf1wXzc7e71WNgiW6Uxt+XK5
+IF4Os7a3vdwxF6TMaA63uLmr5oKw+dnobi2cPyTnaru7vs1Ot7xXG+2CTPvd+NbttQmSbW77m9ve
+Jgi4x03wcZebIOeet8JJu27ftDvfELetnRUi5YVbvBP1Jsi9Ix7xfQ+k3/8O+Zf+Az6QgRf85GY+
++EASfnF5N5xoD+c4xCeekIq3fN4ZH8jGZY5vjwsE5CIPOoNJLhCTo/zoFVa5QFh+82e/fDgx5/m7
+aY4QHgzg6ljPuta3zvWue/3rYA+72K/uDAYgpB5eSLva1872trv97XCPu9znTve0JyIh5uiC3vfO
+9777/e+AD7zgB0/4wuvdHAlRBRAWz/jGO/7xkI+85CdP+cpbfvGqSEgrxs75znv+82LHAEIYMIG6
+m/70qE893esR76bLO+cC2bnUq+1zWABd6LiPLtFhYXSk+168SocF013f5qcvefYzbz3xnw17WMge
++XOu/e1zT/0cU/f32E9zeZf+73L3Qj/fVD+Izbnf5uY///tOln7116/762f//eEN/vDJX2TjRx39
+WQ6/QcpBj/77//8AGIACOIAEWIAGeIAI2H+lIAAIYQJp8IAQGIESOIEUWIEWeIEYmIEa+ICUkBDZ
+8AUgGIIiOIIkWIImeIIomIIquIIgmA0JoQZtEIMyOIM0WIM2eIM4mIM6uIM8GINqkBB9kIBCOIRE
+WIQImAwIIQDvsIFM2IRO+IQaaAIOUQlSUIVWeIVYmIVauIVc2IVe+IVgWIXUwIAHAQqrcIZomIZq
+uIZs2IZu+IZwGIdyeIZGkBDXUAV4mId6uId82Id++IeAGIiCOIh4eA0JEQH+oZCIiriIjNiIjviI
+kBiJkjiJlJiIEZAQNhCGmriJnNiJYJgJSWgBcziKpFiKpiiHoKB89Ddl5od/7qZ+7BeL1vdg8FeL
+3iV/q+hs9ueK1aZ/BTF+uVhkrciLdAaLsniMx7V7vWeL8IeLwUhlu0iMc+aLBAGMz5hiwyiNWWaM
+yIiMysiM4IhdzniNRhaN2uhk1DgQaBAJ7NiO7viO8BiP8jiP9FiP9niP7DgMZncQt+AJ/viPABmQ
+AjmQBFmQBnmQCJmQ/lgMCREO4PCQEBmREjmRFFmRFnmRGJmRGvmQ4ZAQYPAKIBmSIjmSJFmSJnmS
+KJmSKrmSIAkGCWEF+Bj+kzI5kzR5j8N2EAyQAAq5kzzZkz6ZkLegiuRYZS12juk3XN2YlN8YjuE4
+jkOpYuZolDCWjgJhjU+pX9kolS/GjUkZi0vJlMzolFe5YVGplSRGlbBglWMJbUVpli7GlV25fl8J
+lrUolmupX2XplgOGlmp5l+iVlXo5YHAZl9Q3l3T5fnbpl+uVl4FZYg6RCTUZmZI5mfZ4aAcxAz+Z
+mZq5mQeZAAnxDWEQmqI5mqRZmqZ5mqiZmqq5mqwZmt+QECIACLI5m7RZm7Z5m7iZm7q5m7zZm7Ip
+AglxAZQ5nMQpmTdpEHzAmcq5nJs5A0KpmOkFmI0JYINJmLhnmIeJfYn+CZ3oxZjTKV98yZ1Y2Zbf
+SZ1IaZ3sh53Z6XvbKZ7s5X3lGWDh6Z5s6V/xGWDViZ4ip57reXTtSZ+r5Z336VvzCaB/SZ4DCl/5
+qZ//xp/9eXL/aaCoJaAJultoeQ6QkKEauqEc2qEe+qEgGqIiOqIkmqF9sI8GwQvisKIs2qIu+qIw
+GqMyOqM0WqM2uqKfkBDpMAY82qM++qNAGqRCOqREWqRGeqQ8mg4JoQKT0KRO+qRQGqVSOqVUWqVW
+eqVY2qQqkBBQUKJe+qVgGqYk2gqjtwI3eqZomqZqaqO88JwSmlrSWaG9taAMCnDu96C/F6FvWloU
+Kqe4VaB7ymL26af+wEWndaptDoqnBrd9gapu8EmoBOqmjUpacQqpuGWohwpmiaqo4aanjdqnlkoO
+FyqmpFqqpiqiJ4oQKrqmrNqqrjqjOYoQcCAHtFqrtnqruJqrurqrvNqrvvqrtAoHCfEHv1Csxnqs
+yJqsyrqszNqszvqs0Fqsf8Clp1qt1lqqZIqTZvqq3NqtrNqmJzapgnploTqn55mpQbepnHpmnhqo
+oGqpgCqup1Wp5Rpc54quIaeu6wpk7bqn7wqp8SqvpUWv9Yqp+Gpj+rqvPtavb/qvhBqwAgtbCFqv
+tmWwBzt0d6qwBMewEuqwfoqWHXAJIjuyJFuyJnuyKJuyKruyLNv+siOLQgRhDwswszRbszZ7szib
+szq7szzbsz47szCQELTwBERbtEZ7tEibtEq7tEzbtE77tERLCwmhDLlQtVZ7tVibtVq7tVzbtV77
+tWBbtcqQEHrgsmZ7tmibti1LAQghBj/7tnAbt3L7s/bAVHZ7t3ibt3q7t3zbt377t4AbuII7uIRb
+uIZ7uIibuIq7uIzbuI77uJAbuZI7uZRbuZb7UhCUPf50HwJySIYRMFTCM6ALSDJSFYPkM2szG4Sy
+Fa90ITZRUpcbu7KLESRQQRRFEEtCulBBQrB7NumTS78bvJp7uh+WHHukGaPDJU0hGu00u877vPt0
+GrCAJYOUB9f+orsH1BVI4ATVZDjB6xh4YRRZpBBGAUQF8RzAuyzQu77sqxBWY71YkSN2ARmsQRzg
+yz/HEb7Giz3hch/FQhBm4RVqgR3tW8AGnCTQIT9dw0nz67ncAhj5i79K1jixI0HYS0Dcgy4HvMHP
+G8DGMk3W0cAIIUAnEzD7IzuVg70V3L8XfDQ30QvxxMEybLlOIAEQ0k+sdMIG0UK90FVDEcHpa054
+hBX8W7zR8b9lcRogNMNMLLmPQFFYlDd4MUYMcb9BrMNDXBrLQb7JYb6eAR1L3MRi3LgXgw0wu0UD
+gsQKYcVapMKI8RPEO8HB1DnI+wbK+1BjnMeMKzhG/DU2kSj+WXMyQOy6N+HHNRG6NzE1Fnwf4jQ0
+bazHkBzJkjzJlFzJlnzJNEUCvbDJnIwkInFLnbzJAYXJpFzKpnzKqJzKqrzKrNzKrvzKsBzLsjzL
+tFzLtnzLGhHKurzLvNzLvvzLwBzMwuzLo8xSCjLMyJzMyrzMy3zGKnXMzBzN0jzNyXxTDELN2JzN
+2uwhLkUT3KvN4BzOyAwgePxR3izO6JzOvNxGNsXNLuXOLEUT5axR8gxT9fxSuVtT8MxS+6xS99zN
+YZxR/9xS+UxT/axSB41SAx3PAY1RC71SBT1T3CwMjFDRFn3RGJ3RGr3RHN3RHv3RIG3RXZXQ5qwW
+OLALKJ3+0iq90izd0i790jAd0zI90yiNAzIyzwKtFiG90zzd0z4d0h2wFg7cUtzcl5MabSRNz2ox
+fRd7Yzr20P6sFvMnrkkW0TJV1BGLWkhdT1HdG0zd1DX21A3NUP881ZNa1UPNz6li1I261fa81GDt
+b2KN0w4t1Vl9WmhtzWt916bl1i/1z18d1wo212/dG2b9qUKt1+pYnIzd2Paoj6jB1Sn1z2zQmpZ9
+2Zid2azJBjdd2AMBk44d2qLNjsdp1TGF1XxNqb2R1Dnt1YK9bYT913ad2qOV1+2817SNcast2QoN
+168dZrEN0Iad20iW2Lc9EGwdqH4t3B/328Dd2bI93Ln+bdv6nCpU6InYnd3a3YVjGNmeLRAfyILi
+Pd7kXd4q6IL7Q9dkrRaZuN3u/d7YDYqlkdYrxc38Z4T4nd/6XYAL6N3RPRBaQIgCPuAEXuCDqAXQ
+zdwCEYT73eAOjt9ION+KXZXEvdwtBdjOrakJfuGzTdvUbdC4TdsWztCuneE4FtwcLt0ebtzVjdwV
+vtvfbXsmfuIbTuIrR9wfLtGpgqHX2uM+jqooytp13RuzCqxGfuRInuS+KqzpHeNd+uNQHuUZmq1J
+Qt8IHeKpPeIrheEzjrA1vuUdnto5ftVYztda3tXN3eVh/eVovnQ4zuIg7uK5feaT7dtqLmZsXucq
+Lub+cK7jci7iMP7fP3fnGNvkgi58by7hxy0QeBZsjv7okC5olskYvF3SvaFpp5bpmr7pnF5qqWbo
+Cg4LvBbppF7qjl7aVp5SqA3o/h3qgU3oyIXiNu7m093nZP7nWR7org7rg53nvb3nfD3mp13md03n
+v57mvN5+oJ7iN17rit7iFD7nus7sg57syr4q6k1QZZ3oVT7hsMADZBDu4j7u5F7u5n7u6J7u6r7u
+7B7uZhDkla7UvZF3hlfv9n7v+E54iLfssw4Li9DuAB/wAj/w7C56zx7n0c7q2RTjr27tsg7mwH7X
+wg5Tq57rrU7tMm7t0PXwbY7ozt7ti56WL37x/d7+8MnO8Xre7Ct+8H4uENcN3zAf89xNhpQe4+Ft
+3jif8zp/guiN7THe3jIf9EIvBfIN8tAOC/f94Eq/9PxN80K+3r1xhwY+9VRf9YBoiPwO8QPB4Ezf
+9V5PDxFu9Agv8tJO8lpf7RrvXCh/7LS+8mLf8mSv8DV/6CbP62tv6SrP5yx/6wlv8QtP92nfYL6O
+922v92/P998Oeoq/+IwPdmVn9h1vDt8w+ZRf+ZZ/+Zif+Zq/+Zzf+Z4/+fvu84e+eY1f+qav+AZ/
++MOO62Y+7SUf+Go/+PKe98Fu66vf960P+SmP9rCvXHc/+4Vf+3t/+3Hv93O/673fbbLf2rQv8bb+
+T/HEntXGTvgZn/zJ9fvMH/zOP/zQPxCS8NPgH/7i/9Fa8vTarhY/QNPqv/7s3/4z/QPLP+QDQQHj
+X//2L/7P/1LmT1D7L1BQvfsAAUvgQIIFDR5EmFDhQoYNEcoDIM/hRIoVLV4USAIARo4dPXYEQOLj
+SJIlQ5ZEmbIiRIkqXb48yBLmzJkyad5MqRHnTpgnef4EKRLo0JURiR51aBPp0odGmT4tqBPqVIQA
+epHAmlXrVq5dvX4FG1bs2LA+qT6FOIrsWrZt3b7FOsrpWaZp4d7Fm3dtr410/QIAHFjwYMKFDR9G
+nFjxYsZC/SKFyFjyZMqVLQ9u+fho5MudPX/+pqxZ9GjSpU2fRp1a9WrWrV2/hh1b9mzatW3fxp1b
+927evX3/Bh5c+HDixY0fR55c+XLmzZ0/hx5d+nTq1a1fx55d+3buFN9IICjhDUEkQiFyJNwL1nlY
+6df3JcgZALY8Cgc7yQxt1Jv5JJC8J+yGwoSSwAnAnABPoPkKkiuz7h6EMEKKSLiBoBtGIUgq9ggS
+Q0AAbvivKgcFYm+ugTY8ET7x6hNRICT2+w+aN0aBBhYxnHCiIBMVdHAUJ1jMwwkM2wNADIL4G1FC
+JZdUUgwAQkQCABZhyYM/EuEbCJtRkEDCCfVaLKjEJFG8MkNsEporSol6qXAgJLBxrL0k55L+AJsQ
+XfyuPSccC3JHJv8EVDtsEqxyIGgG7YtMWHoJUdGB/BTTIEVRhAaAGg9K8w0uiyzokRwfnTMzJx4x
+iIQcAXjkTIFGecTPQF+FFToKV3Wsl0fYc3QgElTFdMy+IMWyTIJcldPFUeqbFEs/5wJWTmyMhOWN
+SpOMtVprj3PyvzegnRXXYN0k4Q1qFRxMWMJESlbHcd1LF1SDmPVVTqyoPHXca+/FtzcE81BVHk3f
+E7bTN3q5FMz4fo03TCwrLVjdgVoVI0poH/6Ux3dFJbXTesU4k9Vi8wU55N0euVAojTBTdFd73VXY
+4pZfzojXi4dds00X4aR5ZoHEuxMWJPL+NOpZaT8WuWijY6v0WUkTDVbihpolOsWlB1oRzcweGQ8W
+GWm0EUeHv171R4GCHNIoUz8l9mi11x7NCZmlBjCwXuQDzOqpiSyXbvXko88+wZyYWD/+4Ow5apep
+NhCAUd11MuO02YY8csknp7xyyy/HPPNYSeilc897mRgmCT73PEHNT0c9ddVXZ71111+HPXbZZ6e9
+dttvxz133XeHXB7ffwc+eOGHJ754449HPnnlC08OCeWfhz566acXnnnkoKE+e+23n7460L4HP/zA
+ViaObvHPR38x8oc7OX333y/M+1G4p7/++ltdXziIbrW/f/+hx59zNPI/AhaweHLxXpz+lKOU5TBw
+gY8jjlSaI0HpmKWBEByOA5OjQeRQcDkehI4FH5i/4HDwOCY0DgiTo0LnmEUQC4BhDGU4QxrW0IY3
+xGEOdbhDGNYgRSQEjlJQkQsiFtGIR0RiEpW4RCY20YlPJCIqfihA+MgDBjzEYha1uMUdCkJX33qO
+WRZADjKW0YxnRGMa1bhGNrbRjW8kYwum2Byl5CIWd8RjHvW4Rz720Y9/BGQgBXnHXMyRORKUxyrg
+uEhGNtKRb1zAFxM4kDE+0pKXxCQb5XglIP6mjoMEZShFOUpBFpKTVDyRIjO5SlZaMpIZAWMLHVPJ
+VtbSlpo05AUzY0dS9tKXv/yjKd/+00nfIFKVt0RmMsnxSliwsDlmMUEapDlNalbTmtfEZja1uU1u
+dlOalMjlCAeihjaU05znRGc61blOdrbTne+EZznVEM4VwkcA7/BmPvW5T3520wSSpI5ZQLEKghbU
+oAdFaEIVulCGNtShDyWoEeiJHKVEIBQXxWhGNbpRjnbUox8FaUhFetEITPQ4EhSABSC6Upa21KUP
+BQVApyNGZdbUlpscpnM+CUye9rSXwkRhcYxpU6KukpnOZA5Ni7rUR+I0qOWbCy99OlWqBtOkKazi
+MZm6VUjKtIKz5GpY3ehUDOovqlVFa1rxCNSyBmeoYoVrGo8ay2c65haewGte9br+V7721a9/BWxg
+BTtYvBbjqsVRChhesVjGNtaxj4VsZCU7WcpW1rKLBcNhIwgfBiSAsJ8FbWhFO9hbeDU6So1rauOo
+2QyeVa2vnSpbidmbt6o2tXOdpEBoaVu4knW2vNkpbIX7S9mikkRa5W1YcRtQsCa3t6w16y6HO92f
+QtetWXUuXJc70+Zml6u+1alrqTveQRZ3gtj1Lle3+9WBzGC074VvfAObAOsGcS4iAER+9btf/vbX
+v/8FcIAFPGAC51cE9f2NBPkgXwY3OL4zMG0Iu5vepYKXjuIlb4b9aN5DopfCS13vaSf8YZtamDnB
+1XCK9cjhD3qYxDYNsYQp+eL+oppYlwORqop1HAsWK6e2NFZmjMM4YiDf0sbiFEiOd5ziHtczlUWu
+qZBlORBeiMPKV8ZylrW8ZS532ctfBnOYrfwJBPtGKSqYRJrVvGY2t9nNb4ZznOU8ZzqnWQVlpi1n
+VyBmPvfZz38OMy8iPOQZQzmZR94ghpes4SZ30MWGrqWU61poSN8Uz8BV9KLJ2+iTPrrSRh30lHX7
+aUuf8sLS1TSTL72bH5M6k5JOqmOqDGha19rWXiazqU88lz/8wte/BnawhT1sYhfb2MdGdrJ9/YdV
+60aCDNjzraU9bVoLGpa5hcVuXY1JRFM006meLqex+uRtg/razKV0uS/Z7RP+fhvcwhW3UD2t7kbC
+ejmopXdTm50bFL873PvGTavzzUh7KwffA2cku43Tb3/DG+C3ETjCu3pu7rbXwRfHuGDpq+sbCyQe
+lwV5yEU+csvG4+G2UXDGVb5yvUKY4uwdtcQbqXDEurvhaY33Zskt80UWPDkH53kbaQ5VVN98uDln
+37yDrkafIwfoS1fj0FtbdKPDFunCiTjU0dj04zxd62eUenRxXPWjn7w2Wf96GbluHLNswhZvh3vc
+5T53utfd7nfHe971/nbDchzJsFAFEAQ/eMIX3vCHR3ziFb94xjde8KowO22ejYe9V97yl8e83jcR
+6knHPO1Rj/xsGE72ql7+/bo7//zWOR/rdKfejGEvoc1J31PTAwftn197cbyeetjbl+qzL33oZXP7
+tOeeOGJ8afKVv/yGStTvic6MNEY6fepX3/oilYbwY4NIlTLf+99PvvGHYxYxGND89tM+bJRyfvZz
+L/2vkaDz2j9/6U0MqfdWIPTD+9vdPDXpz7k/g8s/b+M/3fA/sTsvAKQr1ju1/XPABDSumYKfCZzA
+AuQ3CsRA97HAgMvADhSf6tCLEBTBEcyKhlEOaCDBFFRBtzDBDVrBF4TBr+CdGaTBGrTBG8TBHNTB
+HeTBHvTBHwTCIBTCISTCIjTCI0TCJFTCJeSOPKGarHER81jAhWCXXxn+jL35Fr6ZkoRwEpuJGvMJ
+CfNBl/tgEas4GAvhFHK5QryRGyZ0Q9OYlYG4kAxhGoPoEMAAEbt5Gag5w515gy08iJO5E2KZC0dB
+kXD5D8DIGIBxEcDIPxNpqzeUxKfIlkackiqpw4LQEi7xEj3sQz6Em5hZiO9wQsNhGUaEGYuxin9B
+xVRJFZ05nEmURc0YlLGBwkORgEwkCEYJGFiEG1DsRYZJiDx4klGwGULMDEMMFkuREydokw3Zk0oJ
+naiJxFm0xp+IQ7UYCFvxFoXYFU/8xYTpw1M0CGOkkieJxZzpxVBsJseRBydBlr6QRljYE7AxxWvE
+R6SoxG3JiArpxoP+KA9xQZNyYcRzQUV2vEeB+EOFdEeDMR+JoBsnNBtNYQ9PEQissUeDzMeNHIp9
+6Zd/+UeBIRj7SBhgPEhhPAhi/Jt0PEVlJIhRUBWnEBL2SJzA2EJI3ECO1EmOIBltbCbC8J1vURmG
+gBqTPMS3eckhOccaQUaE7MVIsZGQ2AiUpEelpMac3MmspIikmUZGJBOnIcqSFMdQrBqAXMiBeANS
+acp1fEqE+aKNMBWCwEhyrEattEuOcJuYYBrBmBvCAEdz8Uu9iZv5AMTwgMKwYcO6ackqJIhKqQ8T
+MRBYwIZF1BopoUu/vMvM1MzN5MzO9Ewe5BzSAZ2bGB3RNJ3PRM3+1FTN1WTN1nTN14TN2JTN2aTN
+2jwd0cTN3NTN3eTN3vTN3/zNNZgG4CTO4jTO4yROJVgDJUDO5nTO5wRO5WRO6KTO6qRO6bTO7NTO
+4pyGNdjO7wRP3hwWbAjP8jRPAGAH81TP7awGAKiG9YTP6mzP94zP+mzO+bTP/DROdrAK/fTP38QG
+ZRlApzMG53AEAHAEA0VQBU3Q5jCGKdS5RxnQrivQ5jjQBmWOC2VQ53hQBRyWCWW7Cs3QBbVQEh1R
+DF2ODo3A9nCMEZCEF4XRGJXRGaXRGrXRG8XRHNVRGC0YABDRQwiGIBXSISXSIjXSI0XSJFXSJWVS
+IR0IDRWIGDj+hSml0iq10ivF0izV0i3l0i710imNgSc1UWFYgjI10zNF0zRV0zVl0zZ10zeF0zIV
+BjHF0B210zvF0zzdUWAYCBXVmiYF1EAV1EFt0kPwKrNghE5Q1EVl1EZ11EeF1EiV1Eml1EpVVHrI
+DB9tPddbLYGAUlh4AiYQ1VEl1VI11VNF1VRV1VVl1VYV1Seg07EDPpyLVYGABEvF1VzV1V2t1Evo
+U6VLvfVCVF4l1mI11knF1EcRUW3jVHLAqU8NVVeV1mml1mplVVj1VBNVsln1KWH61Fs91nAVV2L1
+VYHw00Rq1jMSVsdI1HF113dF1kxd1nR9vVoFVWvF13zV11X+xVZY+NRt5Vae8lYTBVd4NdiD7YRy
+hYVzRa5mXdeBaFeEldhxTVYFmVd67VR/NdFo3deO9Vhr7dd/Ddjgy1YMLdiJRdliVViGxVgyeliB
+sIMpkNmZpdmatdmbxdmc1dmd5dmenVk+UNaB8AM3INqiNdqjRdqkVdqlZdqmddqnJVovsFdv6Iaq
+tdqrxdqs1dqt5dqu9dqvBduq9QZ7jYJmMNuzRdu0Vdu1Zdu2ddu3hdu4NdsosFcz8Nm7xdu81due
+3YNfHQg+gNrAFdzBJVyo9YNDZdeUVVxirdj2uFiMfdaN/djJpdxrtVeAHVlfGliTXdzOzdWVBVbc
+Q1yI9dz+0qXUxtVUz6PXyMVQjq3c14XdkNXWzI0tez1Z08VdRgVd1EvXl4WFiM3d4O0E1H3c1bVX
+14Xd5P1Y2cVQzKXdUdrcgbhd4TXd3T2ull2m0RUI4KVe0yXeTeVU1h0I5FXe8s1X5pXV5wWm6LXV
+7g1e612PhuVU3+WBAbDf+8Xf/NXf/eXf/vXf/wXgALZfZ2CAoBWIevCCBFbgBWbgBnbgB4bgCJbg
+CabgBE4EezWHLtDgDebgDvbgDwbhEBbhESbhEtZgc7DXwHO8FWbhFnZhxoO8kh2IVhDgGrbhG8bh
+AMYAvxUIBpiACgbiIBbiIabgetDe33Xf3P1e1U1X8RX+CPI13yieVvRNMvUVWNtNYtyFX3RtWd/l
+3ixW3CXONux14nuV4jOmViqGBee14vLCYjD23C2WX9fzYjj2XDFm1vA9XjTmY1dVYzZu40BiX1iY
+XjuWWDnGXt8tB3pg5EZ25EeG5EiW5Emm5Eq25Etm5FIQAAOGhWjqp08G5VDWJnCSYYHIhi9A5VRW
+5VVm5VZ25VeG5ViW5VlG5WywV3KKp1zW5V3m5Xeap1KGhT7A5GEm5mI25ktOBh6GhXsS5WZ2ZlD+
+p5czi0qQgmq25mvG5mzW5m3m5m725m8G52qmhk222IEYKPBD53RuPnu9hipw53eG53iW53mm53q2
+53v+xud8dudrsFeLur5/BuiA/qiSAmYbCOeDRuiEVmhwzgRlTil1huiILqiYkubENeQwllfwdb0y
+huI+9uhR/eNA1tw3vmiUReQuPuIvLmmDxWMy3uOPhulSDWmRJqVBLuSVfteTxtg6xmmJbemW5eiY
+FupXvVyarmmS7mmD1Wl6pV8ycOqnhuqoluqppuqqtuqrxuqsdmozKOByFgi3y7ywFuuxvru+01gM
+NYdvUOu1Zuu2duu3huu4luu5puu6VmsUBuZ1CIC95uu+9uu/BuzAFuzBJuzCNuy9Xgd7XQStZuzG
+duzHzuodNlfOojyytuzLDuvNq2jSTeqD/WnIfen+oYbpmTbqULLpzj7Ype7dlEZtls5oJm7WoBbt
+0S7q0jZtpG5tcVVth2Xt3HbXzzZeYO7o2Y5i0rbtUsJt3zbW3Z7f3lbucAXuJg5t4uZj4z5uQDrt
+5w5X5qbjI86ESADv8Bbv8Sbv8jbv80bv9Fbv9Q5voPVqWHAvlpPvi9u4sx6IbwiD/Nbv/ebv/vbv
+/wbwABfwASfw/P4Ge8WvAlPwBWfwBh+wAwPmC2DvCafwCrfw9e7byf7b+ebwBnO5n/xQztZuY43u
+2J5u6j5j677uDUvuEddV7g5W53ZxXi1xPRZuFO9jFV9xPsruGedVGBfdzd5eH2fc1x5joD5xHDf+
+Xx3f8RVrcSKnVCAvPhmHckut8Y1OciVXXiZv8rV68iqPVCn/Ot89B0gw8zNH8zRX8zVn8zZ38zeH
+8zg38z7oaselMmrD8zwHs1yzb4FIhzEA9EAX9EEn9EI39ENH9ERX9EUH9HSwVzSrs0iX9Emn9Dm7
+M2CGAjnX9E3n9E6P81ZQZmjT81En9SuzNhCXUBEH80q9ct7Lci2P3dru8j7q8VWPcmXm4p2mcluP
+1Fb/PNmG9SWX9Vnfo1rn9TDH9TmOcSFH4mOPV07OYyy/8WAXdmAG5CY3dmd3VDHXOkU+5m8H93Cv
+ZE3mZALQgXNH93RX93Vn93Z393eH93iX93P+NwB71QIuwPd81/d95/d+9/d/B/iAF/iBx3ctsFch
+oIKEV/iFZ/iGd/iHh/iIl/iJp/iEFwJ7FWZx1/iN//Zk1nCBEAAamPeRJ/mSN3l5J4AjpuaFZvmW
+d/luHmdOPmeJpnnwc74+h4V21ued5/me93l85mdg9meBJvqivz6CxnmDfvmlZ3qWb+iPX+buq/mp
+Xz6KRnUFsWhth1RfTztgp/bk5fJZz3atX1RuhzqeJntH5fqv8/qvf92w7/KxT3uzXzq0T3tGXXut
+a3u3p1y4x/Yv13q6Dzrf7YBLMPzDR/zEV/zFZ/zGd/zHh/zIP/yJSV1YsAcuwvzM1/wcggH+e6WF
+JwD90Bf90Sf90jf900f91Ff91Qd9WrBXZYCi2Jf92af9J1IGe9UDydf93ef93o98ClBmMdj84Sd+
+zbeHI04qEV2OT11+E21+FFUOP+2wEG8h5VcO5r9+589+6E8O6W8x6n8m608O7B9/7S9/7kcO7/cx
+ZbmKGHT/F+yP95f/EewBAOiB+cd/vaj/+8///n+L/QcIEgIHEixo8CDChAoXMmyoEBsAhxInUqxo
+cWAvALA2wgLg8SPIkCJHkixp8iTKlCpXsmzp8iXMmDJn0qxp8ybOnDp38uzpUyfHoEKHEi1q9CjS
+pEqXMm3q9CnUqFKnUq1q9SrWrFq3cu3+6vUr2LBix5Ita/Ys2rRq17Jt6/Yt3Lhy59Kta/cu3rx6
+9/Lt6/cv4MCCBxMubPgw4sSKFzNu7Pgx5MiSJ1OubPky5syaN3Pu7Pkz6NCiR5Mubfo06tSqV7Nu
+7fo17NiyyyKRAKsXUtxGe/Ui4URMbjG6gw6/Pfs48uSbSeDGDc1Jr99Ciw9trpQ6x+LYlXPv7t3v
+I9t5SMAab11CHljQqPfmDc34bWjYSMyH5lu6QNuw6NuHJcGJE7bhlgd02Gy03XcJKrigWtDcAMso
+0CBhXXHjTScPLPKMAh+FsIjx4HO3AZedcU4gAQs2E8JiIhJvMPgijDGWZd0N71nn4Q3+5E1Hom4d
+StAbCRqxF9989MlzI4IyKrkkk009MoqAvL3xY4ajnFgdhhqu6GGHYpBXG3w8wvdIiUi02CSaaapZ
+FDQAXHmgcaNA15tQAvF2opwCGafbfen1CCdu/zlB3oDQPRjmmokquiijjTr6aFn2EfQepJVaeimm
+mWq6KaedevopqKGKOiqppZp6KqqpqspWHhtu5ARH+iU51Bu83Vgrb8AVh2svb2bXC67A3aejrQFC
+5QSlEpAJC5izTmergLfZSihxvA1KFK7S7QcgecIByxtzuIoHnRN+ugqhs0ORoJ+DscJ53bTw8Spc
+tdHpGJS3uG407IHWjtgUEgZuNMr+iOkhitS8Pca7q62+clTrtfty65+UQH7bi2383nbuKOnWye6h
+/r2blK0Y71kyosXey1G+vJVHrsHF/stUqxzBulHMTPEqL7SI8urwRhDrSGB06f34LXMXCzvxxhx1
+TJXAYrgqj0aI3qffjiQerN1GWhI13LobSUDtq1A9smyN+9640XPRzTwyoFmPDGV1G6kYtn/3ct31
+DSciccORAqPoMb6Hhtd11cXdACDWWmu999yNE8cR3mPD1+5TN4x4sxiJByUPuW+nDPfoVX5d9n76
+WQ432KoTKjg2hLNsuH7Mwb24sXLHPbnjdJ+eYd/MAn55yE1F7WrncIPudt2P667+m9dZwypP8H9j
+yDrlrt8Gu+xFjZJe2H//6TTqz5MOOYLDcT3czU6FGDDOtheHnnrYDTmk45jzjgTZI0MeIUeg0bHv
+ledpTknRit4jvpF5aSOCc9y7IBcm/cltfWwrHlMsVzN0wY0EwKEg9rbGu4NFMISlG10vCNiq7jnw
+RMjykO3C1EAUNU9MI5wgBrUGQLZtSDcgXAoB8WbA4nhQPTncG/789zvc7FA950Lf5FKYnhVSpWYm
+2g+9SKgiWvEmWrDY2QnTB8HmWEtyTEGWhVS0tqBY6FkuO1kXT0hCXL0BQ1B0HHt6ITUIHekp60LC
+zTw4vqD8sGS6Cpqt5ChG7Nn+ChuiUwr8SJCeR+RhkGxcGSLppLA43lEoEMOGjUbYyT3tcRR9dMof
+b9Y3S16wOomEoyZvuMj78caRULHiiSjJyvhx0WS6mVcYsRUdUCZxlM0p5SmnAsoHyYNsxeEfCYBW
+uiSGaZEorMrZCAaLtK0RR5g8nwjzd0S7wcqYTqOUE3EDq3I+5UPKypAzg4KEUViphiUcYwBzqEQb
+TkVzsPobh4SioW9O03yke9eHgonHKG6JnU5xJ5lIYEe4zbOeutuTQY1YFN00UYAkfMoyhRfQz42C
+oEjM6HZ086GOPlGUDF3nR51CT9scrVaI0txueEdN6J1LbpXrn1QcdDNbTan+OBqSpgh36jQzqi91
+YtPbCKnnN8DhhgQljSlSnJC2mq5tQui8qCX/Z8aR/RSrGaQnl76Vxafm1Hmy7FpPtQbQspqwrFW9
+KgtflbakvaF/Xt3ojpQ6sLHCR6rCmyhVZprWWq01b229Jz5N1zzrVW94ddXeXYEalc75apO9eAQY
+DQrMnf0MsJRjWl6JkqPATktO4LInLAkFLZUJM47bipgJX1Y047QplE95RPvexSv6vPKGPMtVyZJm
+r8fellhWeYPBIjit2L3WoMn9oq3EUNpe6lFiuJWjxpwDAN86BbhZ45UEqGs/1iYyubQ1rW7LddB2
+ukmn0FLvN/eGXuy6bLv+nsxufKMLXtSqZ7xmXRWCE5ymsQ2EsE5pJkHsIqmBfDUqExZIhQnD4PxY
+ZcN4o8uFSZDhp4R4xIIpyPWogmK7QHggVmmxnhQs4xnTuMY2vjGOc6zjHfO4xz7+MZCDLOQhE7nI
+Rj4yp6YUFAm4iCP8Q5xURIIbqm1Eyhmq2udAgg0BD4XKVGscAORBNZGQx8pj/oh8O5JiTzbZyaN4
+AwD6eqWRVBkkafvdRm7Q0zbN7F5hjsqZP3LlOoekymu+8ke2fBQqd8SoGhkJbujcES0bjNFDuQEA
+3nYkj+AU0SDJEqWNEiSRiDnUSMYLCYqn56AECcpC+RCnkarmLlftzwL+xTJHLM1kLmf5ym94k60N
+HZRg5xrXJPj1rIeSB49EF5BpE4NWhT0UW88T2a9eWR7aDItHPLDV0nYznLVFFEsX+9vDPrSuoWsU
+RntkWYPmCLGJDe8UH/tE5HayR1bWOTLxD9n3drV/1L1oXFs6SLI+tVs4azcARDfbVfs3NqwEyCTJ
++90V/ze56bNujVCNTuaO96HfPe9kC0XPq97XAzv3noqT/DbffMShBb6ie8kDziMPipze82akYrzW
+IW+5yPfzwFtXGVhXIjfIiZL0f28bG9wmzsqMxfSMD53Wvb45wuuCDf1kO4BbfziuD3T0sJ/b6kAP
+OsALbGIvZzrTH1/+88XDbuCKI4HhTLaZu7t2IpYTO72whZCr6j6igD0Cy/KWKNaJrni+oxvXvS0K
+u0F3KKTD/efxBg7TB8Xnhc9MDO+ZuuMNvPGrV9nEWXdLqgemN5iD/SgaL0rczZ322bN80FSOYdIT
+n3YSLKvid6+7wWrPeNLzUNlN/g/lJGr4nyNu7WSPvNIbL5TaR75z6aF82adN76mRffMRYzraac/8
+tBecoKd/i8LfMKLUMxr8/R6/SFxN5vDfm/oc10jAbJN7Qn+EPIGOs35U3Gpt06EIX0joBrHdGyVh
+S3rcwLKAjsjVHpPl3a19msUdoOzVH/NBX71hH7xh4KSBhI78m3n+bVuTgd//tV72QR7BiYSDnR9b
+BEgeCEzN2ZsKCgVo9YLpnR30KR7xPd643V/X/Nr+8SCujYLAyFvdhYQLUaAEYMjwxcrQ6dN+WImB
+tQio6V6GYAM2jB/9+Vz0+aDasaC0OYEp4VoRYp0EGNi/OUFIpMfm5ZptgB4hiR4ZlpvdvBkM0sUj
+6JmOjNqn/ZuRJEXsGaHZodzoWVqOFGEhyt+h+d3CZcwDAd/ZtZzH2Q0VahfyeVr/AV3NUWAQml0U
+4iEi3qGtdY63vV0Yjty9AeGKuMolbpP/kV3Qvd7okWL47WFbtIktKd69CZ5SFGIjkuKuJSKWtQgj
+hhy59WB2rMz+DTyIs73Hc9xMFFabr0iAg3EhKFqavDkBKIbi4lme9ImNzIkivXnEClbi0oWdbwQF
+aCHOI+TSG3weLaYbr4mhpc0TFeriWjhB1b3b//VCChqFMMZfQHKiohmjOzKiQYZeeogEA7hdrNRX
+tcWZRY0EFNpZhQVPUQRJhnFjoZHaHV4dRoagoAVaQprimrlhOpYksc0HJ0aE09VhpbkhAHRaCs5i
+ot0jPoYER/IjUAalUA4lURYlYCiXIYXF0ZSMyXTHUpbMC16FtzCl+SHGU/aMUWalVm4lV3alV34l
+WIalWI4lWZalWZ4lWqalcvwEW/qEF2JGCralXNLEW14GIM7+JV7ORGoAAJBchF/+JWA2xCjUnmZQ
+TUkFJmImJmIOZl1aRpAoJmRGZkVkxF5WZWZQTWNWBmaKxmaGRiqCxmeWRkRwJmFeZmnC5WnaJS1y
+RmiSxmiGRmeCRmx+xmx6Rmt2xm2KxmvCQgcwgm/+JnAGp3AOJ3EWp3EeJ3Imp29SQLFlJmXE5g/s
+gnROJ3VWp3VeJ3Zmp3ZuJ3d2p3T+QHOKRiqKgXKWp3meJ3oqZwdQzmqGxm5eQifEp3zOJ33Wp33e
+J37mp37uJ3/GJySEJ2wG2xMwAYEWqIEeKIImqIIuKIM2qIM+KIE+AYCCJpbJAz30J4ZmqIZuKH9e
+AntWJkf+wCeHjiiJlmh+/ifiOOdkxOaAQqiLviiMxqiDSmiKimeFXqiJ5qiOjqiH7kt7gsZ77qiQ
+Dul+ouiVqahksKiMLimTNmmD0uiR2miu4SiRVqmVdkKP7sePfkaQXqmXCqmR1mZnKKmTlqmZLimU
+iilr3uiXtmmOZmluuue9WMMg1Kmd3ime5qme7imf9qmf/img1qkCTChtBpsPvACiJqqiLiqjNqqj
+PiqkRqqkTiqi+gCh2iaWMYACBCqndqqnfiqgWsOHosZuLgA5nCqqpqqqriqrtqqrviqsxqqsnmoL
+XOqYBlsuxIKu7iqv9qqv/iqwBquwDiuxFquu5oKtrmn+rq3CrDarsz4rtMrqAozqaZRqtF4rtmYr
+rNZqjQZoiuWqsYaruI4ruRIrsnYrhS6rtq4ru2LrtPooiG6EqbYrvdbrtibrZsQmuJYrv/arvwbr
+uUapZ1Yos9qrwR7sqb6rlsYrLPjCKjwsxEasxE4sxVasxV4sxmasxj6sEeBrYQYbKYSCyI4syZas
+yZ4syqasyq4sy7asyJKCx2ZGKgqABWyszd4szuasxvoCtZrGbiKCFASt0A4t0Rat0R4t0iat0i4t
+0watDcQsaqZYNnwB1Vat1V4t1mat1m4t13at134t1WYD1KomRwgANTQt2qat2q4t0yJCz4rmvYio
+m87+7YaGaWpaBpmeqd7uLYOm6d1WRipaKN0ObobC6ZZ6RpcSruKe6NjirYDyLeRGboH6LZJGRuBS
+6eJmLn0aLsPKreZ+bifYbeVCRt5KrumaKeVKaddgLuhmLueS6r3IAgLMLu3Wru3eLu7mru7uLu/2
+ru/O7gQ0rmYGWx0EgfEeL/Imr/IuL/M2r/M+L/RGr/HWgfBSRioywO9mr/ZuL/f+riy8rWvey7wi
+LPm2K7cKrGzi6r+uL/v2a8Cq6XIQbPnO77oqbJwCqfjSr/5e6/nC78d+a/sGsACba/VORuAW7P4m
+8Kza7+F2hrUqMATfK7oWKgAPsAVf8LEWsGQccAT+d3CrMjDDjq8HjzA59O/fPqf6YrAKB/D7nrAB
+yy8JkzAIwy5HyG733jAO5/DuBu8Ee0ZsFq/0BrEQDzERQy/19jBuZqoOLzET5/D3wisNb4Tntu7i
+ii5ppliLnq4WN2nqDuyUUvHnvm61xi0Ya64VeytHZPEWrzGMdnG6rm4Zuy74jkbixvHgnnH6YjEb
+7/GLuvFnXK4dK64Y++y9AC3bHjIiJ3LSPi0Sc0ZsTi3YRrIkTzIle63YNnL8lu3ZKjInd/Ihuy0U
+jzFHOKzOlrIpn/LFdiwm/y9HhKzLvjIsx7IssyzMrrLMYhnNorIu77Ip82woEzJHiHAMR7AJj+7+
+Y+jrCifz+rawMTsGBw+zB8+wKMsrNHtwMV8xR+yrMm/zuDKz6mYIAlezAkszMFOzOEPwNaPxRmgz
+N7czAdsyZjzzOScwOcMtR0QDJ+SzPu8zP/ezP/8zQAe0QA80QedzImhwZMTmoVIqQze0Qz+0pFoq
+PJPtRjAALxQ0Rme0Rm80QUfDHOsmGQfyHSM06T4uH5/0k5L0YwCySNPtINuzFLc03eIxBacxSt+0
+gvoxpn6xTLvpS4dviPa0m9K0D5s0Th91hKq0M7OpUH/pT9NxSDf1lRL1reoxUiO1TicxT0u1lT41
+SHOEOmCBWI81WZe1WZ81Wqe1Wq81W7e1WO/+gFI3xg/PAl3XtV3fNV7ntV7vNV/3tV//NV0fMfr+
+MZbxgVsfNmIntmK7tTp8tJwG8zwrcDrncTa7s2W/82DvdNeEc2TPbz0DtTl3Nv1Odk2v82WfNrB6
+sxdvtmjr72dDNWS39vySdlFXMGrfdgZPtGPCsGyT72t/dWj39sHSdlVXNm7jtmq/MTgLt287Nv5y
+hDXkgHRPN3VXt3VfN3Znt3ZvN3d3t3RjQlwzRmzqQgOUt3mfN3qnt3qvN3u3t3u/N3yXty6E92Jc
+r3ffN37nt357t6j+MkzDwhRzNZjSt2KU7lWjdFYrKxwLeJV69WPHNIMTKVU7slEfOIITeGL+sHSE
+C6mDPzeEb/iOTni+VriF83GCZ/KCg7iOdjiXFrInvziMLy0jZ3ZxbwQkVzKO57iOb+0l07iCw4LZ
+xriQD7nQgvLCRjEsgAIvLzmTZ6wq+/iIp1gEzDKVV7mVr2wEYDhizGzNNrmXf/nDgoJzt3hsM7fB
+EjeF2/Zxn3ZyE7a6mrnB/vaDw4Iwwzm7onmUG/eas7mWH4Y823m7yrmH0zmg1yues7Jp7zmf6zbg
+8nah1++YI+694DNHV7qlX3pAHzSjo3CKLTREfzqoh/qjSjSUa8b1XjSmp7qqV7pH+zdoA7iKh3if
+G4aBlzgbn7ipM3WsmyiLS3pQ77qJijj+osOCGtv6rc96YWg4sPNopDtwVC87hwq7aVq1se8xrt/y
+VkP7hva6s/+6ttctshNGrVf76V57POv6txdus3PGbqJDCLw7vMe7vM87vde7vd87vue7vr87M4T7
+YMSmOyyDwA88wRe8wR88wie8wi88wze8wLuDv59YYe87xVe8xV/8vqPDum/GAz/6uh76tOu5ortz
+m2v2cns8pLs6bAc3yvNvxAcGMo+8ZZe8VrN2y2eroJM5y9/8s4J81Iq8zG8zzf+4PHA2zztrzvv6
+zh/9rPr8ZcR80HPz0KP4yTP9syZ9t2/EIHwA13e913892Ie92I892Ze92Z8914P3pq/+aLDJgNu/
+PdzHvdzPPd3Xvd3fPd7nPdy//FFmKtr/PeAHvuCj/SBsvGbUcbr3p7T//EYUO7mXO9//hbInfoca
+fmYgPuXr5+I/PYk/vumaO0VnCOtmfn5yO7s/O+kz7tonaed7fuSC/m5ne+rjp+lz/L2cAQvkvu7v
+Pu/3vu//PvAHv/APP/HnPgpEvl8APDIsP/M3v/M/P/RHv/RPP/VXv/UvP8SvvuXisjYUv/d/P/iH
+P/GfgeVjxm4qOZin/5I/uf+G/EZM+ZXHv/xTeZZrP2Rwufrnvy6LucoDN6FbPUCQEziQYEGBLWAl
+lAdAXkKHDyFGlDiRYkWLFzFaXNj+MGGuWB9BhhQ5kmRJkydRplT5MZfDjRlhxpQ5k2ZCEgBcrjK4
+k2dPnz+BBhU6cIHDmzWRJlWaFAAJhwuGRpU6lSpPhAoZLtW6devLjivBhhU7VmVLrBy5plUL86hC
+nVXhxpVrsKhNnGvx5s3Y9Olcv3+nXoXlVW/hvIQ9klW8mPFJs4OzGpastu3gt4AxZ95ZF1blyZ/X
+8k2ILkRp06dRp1a9mnVr169hl2bmMjJo2zUJu1u2m3dv37+BBxc+nHhx47vd0UZ7mznbu7D4xJY+
+nXr12OiMPm++faZoWJc6hRc/nnx58+fRp1e/nn14SMq5x69I+AkT+/fx59e/n3/+f///AQzQvifg
+k89AiCqTh572GGzQwQfZuyS7AymkyDvwIMxQww3Te++sCimkT8ARSSzRxAAJ/BBEAxNckMMXYcxQ
+QrtWrBGWC2PMUcf1PIRsORuZE/HEIYks0r8UfQSSuxZ3bNJJ8WbsTDsl5cPxyStz7JEwKm0T0sgv
+wTwRyS25/IxJLNHkMErPytzOO3Wsi1POOV1LpMA2PyNMl+P47NPPP43T5U48JauMAWboTFRROdWZ
+kFA3nUoIKs0opVQwMh89rLbEGuvUU7IewzTTtRK8rNJT/eKMzVEn825SVGGN69LaWMULsU9xzTWl
+UGmtlbLn5DE11mGjUnVKXwv+c5XYZaOa9Udku9pU12mpBYnXZ6FdqlRmuQXK2Gwlc3WVcckt19xz
+0U1X3XXZbdfdcY0YFNylCJMmlHvxzVffffnt199/AQ5Y4HulkXfepBK04N2FGW7YYXe/PTgv78SQ
+x+KLMc5Y44057tjjj0EO+WKDJaaJMJFRTlnllVEmuWSZKkOC5ZlprhlkMRx9OS3vdDa5155jEhVo
+jIQe2qJVjcYI6aRl4pnpi4p+OqKopX6I6qppxPqipbWuyOmuIboaa7GrJltqrsGWMm2YAGjb7bfh
+jlvuuemu2+678c4b27UXytvvvwEPXHC49077psERT1zxwNfOiITHIY9c8sn+Ka/c8ssxz1zzzaFp
+PCJoNg9d9NFJL33yzj232vTVWW+99NRhj1322Wmv3fbbcc9d9915793334EPXvjhiS/e+OORT175
+5Zlv3vnnoY9e+umpr97667HvXQwAUE9olBseygP1hZCK26ms+n7bKfIhgvuG7iVCHwAJHmLocMLT
+d7uh/AHoBecbsbU98D0ECaN4AwCwEakbwa0XCXEf/ML2QP61TYFGgeDUjkUR8rEvWrB4X/ZAmDQn
+POIhb6BfQrbHEQ46JA9OaNsokGChZ8lPIit0IEcK+IYYTkR+OnRIbVZoQ6w4BAk3aCAAJXK4HcIC
+CU4YRefk8QYSIjEikcn+4RIj6BBoOOGIN5zIFi8COpiQT4xc2WAXQ5jGkj3CCSwEwBJ7ERkbQkOK
+sNgiGts3w/1lUIi06kUF8wiZP/4QLUHko3bY9zNYmNCERkGjBLDhxSouZ5A11E4etKPIzgCSXhns
+ZEKw8T81jhJc0OCeTQbYmUfIcUpi6KIQCTlJyFhSlg6BpAwhs73/ARGRh7RaJKkYvjd+zyEjJCBH
+FEmrW9KShWjUJDYaIobHUZAEB1zfXaqJwP9lExv02+BdHoENBOahgf4TZzcTkodz5gGFccTGKO4y
+Ck6Skp6jMiYssMFOWIghkqysCAmAGT89zhKDtRwiD/fYmSPy0mq+TEj+AZH5LGJicoeaTOZyYElQ
+O5IAi4pEwikXMgpYYPIGSMCkxXCSQlg8ooHywEbnjvLNlb50pW27US86Z8DBvGGPnXNCSbcITjzW
+k6iEYuM+31DMhvhTIjkUZRXfttA9Ek6jsaQNLsmHBHQylDZww8rbQinJEuqzjsFsH9wiRauMTvCE
+Ym3oQanIEPJt7xFYnJBM0ZkQF97ohOSTp0NuQILtoU4Cd8loURELpI+CTqSdGSBTEfSGJ3ptoLDs
+43KWKVCCRvGjhewlM5l4g8b2CpNvayMs7mlBs1o1IZnN4kN1ytq3ajQycr0LOQHgBHaK4QZv6EUc
+Z0m+2sCTiuSLo/r+OMi+wyaWuSC6QTj1edy3VTUhN3DCUxEqS8sey4/z9CIHA8tVuM7WJlKFyCga
+O9JTAlSYMbzoQypZ0KvKdr4crC1KIYJJMbwhUjIlX15hAVx//vUhpiSsYT3ZXAUfCJJJraUN8+DD
+i/yMhvKtHw4NaNcLaxQJB/QseUFMAvMS8Q36TEgdtfpBeTghrdiyYoYnwsECpnK1P8SZfSNKvnBC
+kXt1hEYcZYYT8gG0c6vEiT+juD+eBhioe13pUBccZfl8NL0bhoz67uc2XAZygi1F6wLd9kGsameV
+H+6q+qoaxc7FTQIOdsgoTptDBCpQbg58m5gteeeO7k23tM0xTgr+2DZ0QnLOb+CpkLEpThYfWYV3
+IXRekRBHEx5xFFOU8qUxbbRHeJcrYuhem5fyhgtmmtSlRlYTDUNkO7JYKRKosqlhjaffznrWkxEx
+rX+L3ZfhutZJecSouYKEbPJXwzArdqyRnWxlL5vZzXb2s6EdbWlPm9rVtva1sZ1tbfOa29329rfB
+HW5xj5vcbYWdK8mdbnWvm93s1nXj0N1uec+b3urWHQLrnW997/trjVsIF/cdcIGn24WFA9u/B55w
+hXdbnPfmdNr6zTdNps1sT6s409AGu4ivbeMHn7jHDd61iyct46nrONhOrrWRG23lQ2s50EruOe+M
+QBI1t/nNcZ7+c53vnOc99/nPgW7z7qV8bLWJwSmQnnSlL53pTXf606EedalPHekxcBnFaxN0rW+d
+610POjBydjvvMCJNZc8QPdBC9LLVpj5hcvvb/zOmj4u8NpAw+90btKYEx27sePf7etD+w4fTHS1t
+h/vhEc8EuYdc5XX/++PPo3eHO4TskLe8eALvwME3vvCJ9/zbFz87wtj98peXfO76XnrLZ/5Gmy96
+5z8feyOFXnajV73lT48774jCBb33/e+BH3zhD5/4xTf+8ZHvez4IXvS1oQMHoB996U+f+tW3/vWx
+n33tbx/6dLg6yB0ChuSPn/zlNz/yTRF223knBdVyf65CkXb+168dLa/q1v0LwpmX94wwk3j//zvl
+MWKucdgPAA1QMeKP+WqvNuwP/xxQ/+aO8xzC/w6wAsFCAPdO4xSo/SywA1EiATWv+erPAUlQICCQ
+8V5vAj1wBUsCAycvITiQBWXwI0Cw9USwL0rwAb+P8FRwBmfQBVFPgUShFoiwCI3wCJEwCZVwCZmw
+CZ3wCYuQARQwdgijAjThCrEwC7VwC7mwC73wC8EwDMXwCitgByUwIbIACtVwDdmwDZ+wANSvdlLv
+9v6O9dROarxE9vSwRGiPCh2PDv8u98ROgSoPEPHODucPD9luDxmRRPoQdmzPEPFOENePECXxEOXv
+BhPC8Br+sRP74xFTJxIvsewoUQ4VqBKkIBVVcRVZsRVd8RVhMRZlcRZpMRWpQQCmEBJrIxu+oBd9
+8ReBMRiFcRiJsRiN8RiRsRezwQxTMCFsoBahMRqlcRppMRPikHa8QxkGZhu5sRu9UWBAABdDcAHR
+whAe5hzRMR3ZxRCYkf4cYgO+MR7lcR4BJgKucXYK0AdlsAbv0OIYMAd1UEX8EC0oUB9XEAh1bwMN
+kgX5MRH9cQQB8v5OUBNhoSAX0gIRchAdIgYvsgIbkiIbMCKJZSLJsQc7sgIzshIdAhWGoCVd8iVh
+MiZlciZpsiZt8iZxsiVfQQrHcSAdogxSISiFciiJsij+jfIokTIplXIpmTIoy6AdFREtjiEnqbIq
+rfIqcXId7lF25nAU0QQRKZITPXEs8QMUPUcUvRJLShEbLTEtvzITS3ITyXIuyxIqH9IhSM8tr2Qt
+8bEt9fJJwDIuYUEs6dITzdLf/vAvnYQvudIvFXNHAtMn5bIw5/IwJQ4t8vIxdYQx+U4Ix+EzQTM0
+RXM0SbM0TfM0UTM1VRM0l68ndREt6KAGZHM2abM2bfM2cTM3dXM3ebM3ZdP7BPI1w281ibM4jfM4
+VTP9siYhN/IkLfAjBTMkRTJWSFIyK9I5UXIrO7M5sdMAodM6pXM6UaU6hTMhLLI73S8lTZE70fP9
+vrP+PGEhPMWzUsgzFGvjPNtzWtSTLdkzP6nlPe0TIudzWOrzLO/TP9NTOzXQIY6gBBz0QSE0QiV0
+Qim0Qi30QjE0Qx+UJ21QMBXhAUA0REV0REm0RE30RFE0RVV0RUFUEeySaQijCDR0Rmm0Rm00Q+Fw
+OTUyIQpRM3MkMuGTMCmTES0T6zDTR3eEMxeUR5FUR4A0QB1CSIdUD4sU/BIiM5tUTRTU5BwzSzfk
+SQ0U9qa0E6uUB6/US2FESbnUIRrBEtz0TeE0TuV0Tum0Tu30TvE0T930BMSxQ60zDlghUAV1UAm1
+UA31UBE1URV1URk1UOPgRZOGME5ATym1Ui31UvP+lAi2VOYUSBvp8VNBNR7DMRehNCHMUR1RNVXP
+kR2Ds1RhAR5DNVZltR43lQAVEkH/Ey7Bc0BHElJZ7kBxVT9rleNuNVjhT1fhUz55FTMKFDEJ0lh1
+ZT/7sj+htVMANExxcFnH01ddDlir1VOktTFXkhvItVzN9VzRNV3VdV3ZtV3d9V3JdRw4tB9htDbK
+IAPwNV/1dV/5tV/99V8BNmAFdmDx9SlbFVsT4hjgdWEZtmEd9l3/YFghrkvRFELA1FmjdEwNk1uB
+Bi0rFkLUlFMp72O/FFldVUo11vPK9AxhAUtJNu8kFuUo9mXb42IvM2NTlkg5lv8Sk2ZhVkdVkkn+
+fdZBbNZIcTZnqXRndcZjh3Y9QtZWx/VhpXZqqZZd5ZVUERYW7pVgubZrvfZrBdZgk0QwFbZqzfZs
+pTZigXY9YfBbP+VaMVZStBVWmvVmzdNtwTVmuyYf8ZYx4NZu43Nut/Vg4/Y6+5YxwnU72/ZwF+Nv
+jVZuBZc+lfZl+o9xFyNxlxQWPHVWObdzQ2FUXdNVT1VVSbd014VVx9Y6YdVzWTdU7XFt+TMh2hRT
+abd2bddO+RRrCxdQG7V3ffd3gXdRH5VwAXdSb/d4kZd2NRV2p1Vom7ZmTTZrURZp4W5lm7Fln5dB
+npZYRzZ72aNorXQwqTdpifdxsdd7nVZvtab+K9H3PMDXTMV3fGPPet3xTNs3PbZ3Yh1iCN2wf/33
+f5twXh2yXtHCCsfwgBE4gRU4DMuwfMM3DQE4giW4f3NUbYKQWi0XLBw3fJU1cuOibs0XPzO4LNQX
+a/h2hDU4egu3gz24KkA4fEUYhR2jhKvmhGU4JTYYflm4hafiheE3hm+YJDB3TRc3iHFYhQF3h3m4
+WCa3ZCrXiHeFhqVm95Cziq34ilOzNf0UPmPTN734i8E4jHkTOFMXPsEAi9E4ja1YOS2YOZ33fs3j
+fVl2euUXTOg3KvESjtEjf2W2e/W4POT4eum4jmeviSWGaf+4E/h4b2f2jwO5fuOXkBHvju/+0n4T
+eTwWeX0bWY8fGY8nU5IPj5IJOI8vGZOl+Gm8gyWxcpVZuZVrcid1F3CBsilpuZZt+ZaXUmz3b2lr
+Yypd+ZeBeZW1knnFtYih2CRymGWVeImFwodZFoiPmSVOmWlsOJpFIpmvd5mZ2VsM+WCe2JqFeJqT
+pprBmQaR2Hy1eZt9wpmvF5qjeYhFNiE2t3XpWR5Bd4tF13T1eZ/JBXV3mXJrY3XreaC78XXbeEdh
+ARWpcaEZuqFj8RZj2Xx5MRkpuqIt+qKPcRkdGH6f0aE9+qMX2hqJWXFhoUdLuZMrOZJBGfS6eV4Q
++Y8z2YQ3GY5RepQ/eaXdTpQjtWdLOab+a3im77emd1pMcTpMdPpXj7SUoUScjWb3JvipofoJBZgi
+DXiBrfqqsdoLG7iMXRWCo/qrwboWKngAudeYyxkksBmS01mdeYKdIdmdjxmeodaszzoW0tqTA5et
+5cKt8RquoViuyxoWOLKu7fqcOViv97qlweWbCTsWAFt/6fqs7zql1xqxCYKvU9qvjfix+zghliAF
+QDu0RXu0Sbu0Tfu0UTu1VXu1Q1uU6HWoHcIeZHu2abu2bfu2cTu3dXu3ebu3aVuxs4UwlIG1ibu4
+jfu4V9sVmHpoXnucBxi2BRM+YYesIbuYrVO6XXW6M5CIrRu7s9a7G4e6Ue6PXKe8zdv+vJu7W+Xp
+vNm7vUUHnlBw7dbbvem7vicHuFBvcfR7v/mbgpqvvwE8wAEnvhVRwA38wOdG2xR8wRm8wR38wSE8
+wiV8wim8wi38wjE8wzV8wzm8wz38w0E8xEV8xEm8xE38xFE8xVV8xVm8xV38xWE8sRrJltyMifpr
+uy2EgQgqbrwMg9wmnypC2A5IsioqbrTIgObs2MAsqvgHz2L8yZmDBGhMtB6iLYSIt9qmpLZstn5G
+iDiozUwsIuCsc6DBiNxKiySrc8TACU6LsuZr1aAMyuW8MLZnhz7KxCIMwSLinZCgieK8xhLpWbxc
+O9gruxLClHBGkXqBxrTK0gy9qjD+ac4l/TPyKsK0qJv0HCJ6YYcOq8vvwtMtzI5OSSKI3CXc61k+
+CruOys3Hi5wm/dULQ8q9R4F64RGUa+8KXbNeC9Rfi75oPLcEy9cH3SLEC3SUHNaRHSnqfJG2CXxu
+fSKEvHCMfMe/bNitLMZIwIVGS8etfcvZKtnBnSucQALUSSF86Nkj4hF8C9jOfMcF/VhWyMAwQr9q
+LNUhIpyI3cyYKLbCvd+R4hFEK1KyrG3wC0GgacLevd27vTMCqor2rMaYzCF6waUGT7yoy98xPiNM
+Kaxey4bsHeHli9fJC8wp4rc6p4BOS5HoaLJWScK8/TlmLONlPiacoOHri4EmaMv+56vO+MfLfjzM
+I0LO0tzOqMqOkLx/AOzRm/zYZ77pdUcMHN3ppX7qqR7Cbw3X3k0tJIDbzE0puq3qwT7sxX7syb7s
+zf7s0T7t1X7t2f7B7fvt4R5y2B1sQCfu7Z6+517k7n7v2fveEPzv/57A/RHwCV/ABR/jCj/x+/sF
+rzu7Hd9zxBvxGR+8AZfyDQfHsSbyNZkiLT98tZt2NF+mHaJibKb0TZ9mgBtaTub0Wb/1Qyb1kSVm
+XH/2aR9jRCn0f9ohLoEeeL/3ff/3gT/4hX/4ib/4jf/4eb8PYN9XCOMZquD5oT/6pX/6qb/6rf/6
+sT/7tf/5n2H5ayVBSgH5xX/+/Mm//I/fp6dYgTBEqTtBSyJQkIuapTdaa86E/dEfldWf/d3D+1kl
+D+O/kAECFix5AOQJPIgwocKFDBs6fAgx4kMSAA7Ko9cpo8aNHDt6/AgypMiRJDNeOkhRosqVLFu6
+bAiAxMFLJWvavImTJCSLBV/6/AlUJUGDAp8wOYo0qdKlTJs6fQo1qtSjT3gSDYo1a9CUAi/m/Ao2
+rMiTArlqPYv2Z8yDBzy4fQs3rty5dOvavYs3r9tFVtP6/ctw6MFw4AobPow4seLFjBs7fgy5cLi+
+gCsDNstgmN7NnDt7znsAZUXLpEmvFUhTrOrVX3d27Vk6NlbBRafavo07t9T+qq+vyv7t0qxX1sSL
+jxUNPDnW07BSG38OvZPrgbCVW4dIG5ZR3dy7e3/Km7rv6+QVCscYPT1xsrDMln/vkLlz9fTBTs8O
+H3727d/7+9cdHn75lXdefQZ+xZ57Ay4Ii3wHPmjTfdUxeN1+/12IYVQBTkihcgVCCOJxZY3W4YDM
+BfJZiiqueNcwlJWoXHbfhEFjjTbeiGOOOu7IY48+/kjjNy/CCJxZfLCIZJIrBoIckfA5GGKUHkk4
+npOlWZhhllpSNaSVpX0oZZgmNenldVCKGSaVZcqG5ZZu/rdhlWv+BSaaUSZI4pzAnWlniGrqaVmb
+bw7aXZyAWlZnnxDieej+njIJNA89kk5KaaWWXopppppuymmnkvbRZaNnZZfNF6aeimqqqq7Kaquu
+vgprrKZmE6qoWZklQCme7sprr752Og+ZtlrG3Dx3HItsssouy2yzzj4LbbTSHktMrcMClZ0WVWzL
+bbfefgtuuOKOS2655m6rhbXX+oQrIdO+C2+88kob7IjrEvtoc4pG+ee9s1XHH6EC42aov1gluq+B
+jBrsF58JG9gvwz4JOnDFGqorsUQIP6zewhlr5TDH6kX8MUsUW4wyUwWX3NLGIkPnMctAMXdAOzbf
+jHPOOu/Mc88+/wx00DbPgbHMgVUHhxxKL810004/DXXUUk9NddVKw1H+tNHmkcgAFEJ/DXbYYgcd
+mr1aq5XvfC+nR/LZDp2cctxc9ua2xiQOt3bHwta9Ush5G9c23wrBLXfKKwvOkMt/sxYz4hH5vThr
+gTtOd22FX87E4ZQjpHjkYjW+OUxpew7d5JQTjvnAmofe3t3okV4c6KwrdKKStt+Ol4uVz747YZH9
+Dnzwwj822e68G4l78srDxaTZvDMEOez2Zc036qkTunronUuPk+zPCxQ99ziZ7rj117+Z/ebbi1+T
+99+Hz35N5CNu/vlbpk/5+vGP5P7z8O8/kvkJrn72yxL+HKc/AIKkf7xjzjkGAMEISnCCFKygBS+I
+wQxqcIMQbAX16pb+HXN0YYQkLKEJT4jCFKpwhSxsoQtHaI4Pug0zzuCgDW+Iwxxu8Bx7+95B/qdA
+kAiwegArIMoOiLgEBrEjDJwdEJfYkSGCsIhGrBgSBadEKGqkiax7ohY1IkW3EbCKcJLh2bL4RS6G
+rli/aqMb37gpUBlvdqSSlR3viMc8xopWc2QdrnQFx0AKso31ap0PF8IcREhhkYxspCMfCclISnKS
+lKykJRdpAzNqLTvXOJcnPwnKUJrrGpo0Gq6occlUqnKVrLQkInp4SC9+UTqllNkYydifK/INjVpU
+4+Zk+cUwnu2WuPSOLuvGSyj6knLA1KIwN0nFYqKvlixL5hKX6Tj+B2pgm9zspje/Cc5winOc5Cyn
+ObfpwT6GLju6aIA73wnPeMpznvSspz3vic98ulMX1CwZDc8J0IAKdKDm5KHzDvnDfC2AHAxtqEMf
+CtGISnSiFK2oRS/K0Bb082PZyUUsPgrSkIp0pCQtqUlPitKUqvSjudhoxoSzCozKdKY0relFFwBL
+HzJnoTbtqU9/SlGNqnNzHV2pUY+K1KSqtKVDzd/dYgrUqEq1pzg9KEIbpNCpanWrFhWqeHxYVKWK
+daxkPSlTv/o9mHJ1rWxtaFUNedWEHoSnba3rVL0qINaFtax87atSz5pX7T3VroSN6lsVhFDm+MEN
+jG2sYx8L2cj+SnaylK2sZS/LWC+4VGLZiUIzPgva0Ip2tKQtrWlPi9rUqvazUdgsw4yE2djKdra0
+xawfcvq+rBZ2tzbFK4f0Wh2P+nW4xEUpYH8rWItAlbfMxehh83TVnTZ3ul11rcH2Wtzsave4clLf
+YKkL3og+N65yFQhdw4tecvi2u6cLrnbfm13u+lCt6U3veMmL1bnWN73rBat74Qvgvso3rd/dL3jv
+S17m8EIcDG6wgx8M4QhLeMIUrrCFL8zgT1jXX9lRwSQ+DOIQi3jEJC6xiU+M4hSr+MMq2PC9MLMC
+DMt4xjSu8YV5gVv/6dbA1O3v97Ab4CAndcDPoy+Pp4vguEr+98jT9fHzgCzkKC/VxesyMpN5m+To
+7vjKu3Uy76As5TCXlMjHKzCXC5vlxOaLADpos5vfDOc4y3nOdK6zne+M5zYbgMrXyo4QqADoQAt6
+0IQutKEPjehEK3rRgBYCn4eFKxrkedKUrrSl8UyAHDcwX6BYhac/DepQi3rUpC61qU+N6lR72giP
+tlV2IhCKWMt61rSuta1vjetc63rXvI51BFotKlxZQNXELraxj51qUGjaiVs+s129TMf/innaYwZ2
+o6zs7LqmOZbNzjZboQ3cqwiX2uQOKZlnh21vr3XbOu22urcK7nVKu9zlPrcfzfxurrI7twe5hSf+
+DfCAC3z+4AQvuMEPjvCEK/zfxbD2obIDhldIfOIUr7jFL47xjGt84xzvuMTB4HBAYSYBCy+5yU+O
+coXfYtlddHe+pRpvos6b3tS2d3K7styXb3XfOtavzrka8/aKm+b0trl3lftzfbN8jS5Pek+DXr6Z
+Ez3MRncq0p0+VZ5v2udYjyrU6Sf1qUe56gjEd9epuvRf5svfKW+7299+8IY3NepXcQAg7o73vOt9
+73zvu9//DvjAC/7uDgi5nkYO98Qr3u0rt6qauX52n359gGEXe5DJnkSzR56mWmc25Ddf08kTceiW
+FzPmsah50Ds37cxsuuorKvopkr70Uj79LlP/+op2vuX+B+k0sn8P/OCbmtVzB/tV1NCG5Ct/+cxv
+vvOfD/3oS3/61E++Ggw/J2ELf/vcB76yHc/tg7D50uQvv/nrvOfiU/4qQui1+98P//jz2tHqv/1B
+BCDp8+t//+TPNPjb/Xm5d1GxJ0aVR3vvZXvIhHsCKFG7x3QByIBBhX1rAmYHiIATWCbpFoET5YBq
+B4EbGFEEOEwGaIHFlYAztIAg6Fasl035Ug9eAIMxKIMzSIM1aIM3iIM5qIM7CIOJgIFekh3rEABD
+SIRFaIRHiIRJqIRLyIRN6IRDuA4/aCWYMQE8aIVXiIVZuIP1wIKIs2QqKIH1J3sHMW4lCGAneEYp
+CIb+Hdh6HwiGDSWC0DR7ZghfaKg1GviGK/h//GZeeThRcWg0FUiHw2WHpqSGKsiGLeiGeQiItkSC
+g8hXhSgzeOiHieiF+bIF9qCJm8iJneiJnwiKoSiKo0iKpaiJgiCFTpIdrpACreiKrwiLsSiLs0iL
+tWiLt4iLregKqUgkZiEGpgiMwSiMw2iKW9CFgsMcX4ZcMsdedDdf0IVu0Bh+P7aMQudfzZh5h4RY
+0/hk1eiM1IiNqKeN0qhTvUAC54iO6aiO68iO7eiO7wiP8SiP7zgK3gh2ozCP+aiP+8iP/XiO9RiO
+t+ePA0mQBamPvUCO7wMAC8mQDemQDwmRESmRE0kokRVpkRYZkFN0kRvJkR3pkR/pkBmJgiBJkiVp
+kh6JXympkivJkm4TEAA7
diff --git a/Documentation/DocBook/media/nv12mt.gif.b64 b/Documentation/DocBook/media/nv12mt.gif.b64
new file mode 100644 (file)
index 0000000..083a7c8
--- /dev/null
@@ -0,0 +1,37 @@
+R0lGODlhFgFnAMZnAAAAAAYCAgAASAwFBQAAdEgAACQODkgASCoQEEgAdHQAADATEjUVFHQASDsX
+F3QAdE0eHVMhIABISABInEhIAIM0Mok2NI84Nk9PT5o9O5xIAHRInFlZWaxEQbhJRgB0v75LSLhQ
+TbRTUcBRTrBXVatcWsJWVKdfXW9vb6VhX0h0v8RcWZhpaJJubpBwb8ZiX8ZiYI5zc4t1dYd4eMhn
+Zb90AIN8fH9/f8pracpta8ttasxzcM51dM52dM53dc94dkic39F+fNOEgpmZmdWJh9ePjdiTkt+c
+SNuamd2gnt6lo3S//5y/nOCqqeKwr+S1tOa7uv+/dOjBwOrGxuzKye3KyuzMy5zf/7/fnO/S0fHX
+1//fnPPd3fTe3vXj4vfo6Pnu7r////v09N////35+f//v///3///////////////////////////
+/////////////////////////////////////////////////////////////////////////yH+
+FE5WMTJNVCBtZW1vcnkgbGF5b3V0ACwAAAAAFgFnAAAH/oBngoOEhYaHiImKi4yNjo+QkZKTlJWW
+l5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/AwcLDxMXGmkM3ysvMzc7P
+0NHS0CjT1tfY19XZ3N3Y297h4sxDlQDj6OLn6ezZ6+3w0u/x9M0A5r/3vvq9/Lz+kQDqEpiLIC6D
+txAyUliLIS2HsyDKkniIIiyLrzC60tiKoyCPq0CqEpmKJCqQJk+lNLWyVEtSKPPJ3Ddz0stRN0Xl
+DLUTVEyaQPvVlNTzU1FPRzsl5fRTaNB/QwNGHTi1IL6nu5Zu0qqpKVSsVME+4pqJLCazl9Ba8oqp
+jAIA/gTCIOXkVsAVo52OAABgV6kmMxr2Cgbil9LLGh/OIJ6r6QgBLAfuMm48YYzPT1siF7a5qUyD
+u1HibtaUWfLoS55NT+a0+DSklqXPxK5EJkuhm7NdV8pMYW9i3YJsT8q99Wqm2MQn/cihZRBuzasv
+RenrdgnwM8uFQzpSOfrrTcihW5KyogiYM89VF9cUWq7i3+sRTVlB5Lyj6ngNd/58pn0mMUmY4ER6
++R2nGWCEMbUIGQE2QUYj3Fnm3VibIPgeJ178kEFz4Imn4F8aEJbcWY18EcQLViziVoITOvLSFgXA
+5R4iVvxg44045oijByAU0QMIQAYppJAwPHhIFILx/qUeieDFCIB1igjBg45U4nhBlVSaAEIQYiTi
+2IzXLbTKF1mUaeaZaJr5RAc5aKeIFStw0RErVehARZp4mrlAnmlCscILU8yp3y5iILECBI7AKaeg
+q3DxQ5cuMgLgCg5uZBwuTpiAhBgQKZqRK45CKqYiftZ30aW1WEFDEF58xIinn4L6aCMIabHDDhye
+OqgtYgSRonOLwBqrrKImglAQUjyEalg0xjlRLKEuotayFIoliLC6whKtsVVFai222Wo7KyLT7kpU
+VeCGK26xhJTLmblZGZKuuutW1C2tUc1Lb7233TuqU9c6m9At2wJrLb68JEEGP/rG4u4iBaPnr7S8
+/ohhgsRnNOxwLgU/LJVh9YR8Qwsl3HCOCyHIIDI986yMjgwkzKBMyy63g1LN8JzAgskoq4wzOzT/
+3E0MIIiQggM2CG0ztbW88MUZDAgc7y5aFlHBCDsk4ebA8NryxQsZd7DoV7oIQcQKBpyhRRM/jOCE
+VV3X8kQRcKYtCBnsNsQLFHSLPQjecL+bi9lxApCFEjuM0ASzuXwNtdSMf5yLlkQEAcIOSmzN9S5O
+A6Dxs3HPogUIOSBhRQATy1LEE/d8vq+3t5BhhH0YA6zLFELo47qlocNChhC/unowLRYzDLnevbvy
+e/DC265LEqgPsntITCsPvCEef4fV9CVVz8ry/vYOjzwh3KvkvSrgh+985AGPDbrgvl9PbuoRNev+
+6wjHzzz29L8v7/G8g18r0sct8SkrEeXTyfkigaS9sIgRBCwge/bSlzBNAjAV/BACAXgIGAmmOxo8
+lybK8AC5TGdJh4igBAuhOUaUYQOWqQEIMVGb2jVGAh6iRA0N9iYOFmJE8RFhJ/CzIPn9qxDZoYR/
+NLEcBNClAUzIISWWw6FO+XAQQOzKAocjxUKoUBEImY+pIAEY+GhCCh0wT2OAkEVJkMc8EtGYB/cC
+pRBKjjVmTKER85fCBhlpEQ2c4SYGEKC3XWILCQhDGyUBIBNE4BG7O0IGtZg8SkRIEV+k2CJM/oSi
+R0gShWs5Q4aYY4kaiKiLlvDCBUjZCNcRMYh3zMSXFuEDHGAJS1e65Y20xKVGvPJNurTSjUbQox8N
+6ZhAosEf3ZIkADxQXsHU0QWI6SNkIrNIKlJAHSkpwEvIUEKK6AKfxrmncZbJT4BSxBZUIIgTlsic
+ZyrnE1bQJkws8gxkgieaIEDPFkaiBlCapR21dxwn7UWQTErEpCqlCMBQEJRrKdQKnkAaVFKiUB2g
+aEEPCk5YEpRshygV7VwRAU3lbRaZQsIA+qc+kBLCVriKhaos0CpcqIpVNpxaNwNXCGTJoldWyJ5C
+fcVDl35Up0blKVJjyT6lNvUgW/TfUp+6jzkhJhWqBqxfJQ+4Pqd6FXZXrepUv8rHsWK1q2e1qlnF
+SlVbsKWt4wurW6O6saxKFa5gZCn+5mrXiijNZn8FWmDTEbTBuqMSHDDsODCgWHEwtrHeeCxkucGB
+Y1j2spjNrGY3y9nOevazoA2taEdL2tKa9rSoTa1qV8va1rr2tbCNrWxnS9va2va2uM3tLQIBADs=
diff --git a/Documentation/DocBook/media/nv12mt_example.gif.b64 b/Documentation/DocBook/media/nv12mt_example.gif.b64
new file mode 100644 (file)
index 0000000..a512078
--- /dev/null
@@ -0,0 +1,121 @@
+R0lGODlhoAHkAOe1AAAAAAAASAAAdEgAAEgASEgAdBgYGHQAABoaGnQASHQAdC0eHigoKEIlJEYm
+JS4uLlssKzY2NgBISFIyMQBInEBAQEhBQUhIAFBBQVhCQkhISF5DQ2NDQmdDQ3NEQ05OToNGRHhJ
+SJxIAItHRY9HRXRInJdIRlpaWppLSaJJRqpJR7BIRa5KR2NfX7JKR2BgYGxdXWleXmZfX31ZWXJc
+XHpaWQB0v29dXLZKSHhbWolXVpVUU5JVU55SUJhUUqdQTrpLSK9OTKRRT6FSULRNS7hMSrVNSr5L
+SL9MSr1OS7xQTsBRTrtTUL5WU7lYVsJWVEh0v7deW4pqab5dW8RcWbdgXrZjYcZgXnd3d8ZiX8Zi
+YL9lY7RoZshnZb90ALJubLFwb8prabBzccpta79wbsttaqx6ecxzcKt8e4aGhr93dc10cs51dM52
+dImJib97ec53dc94dqiEhKeHhkic39F+fKeKiaWPj9OEgqSSkb6PjtWJh5qamqGamqCcnNePjZ+f
+n9iTkr6amtiUktmVk9+cSL6enduamb+jo92gnr+pqd6lo7Ozs7+wsHS//7W1tZy/nOCqqbm5ub+4
+uOKwr+S1tL+/v9+/dOa7uv+/dOjBwOrGxuzKye3KyuzMy5zf/7/fnO/S0d/fnPHX1+Dg4P/fnPPd
+3fTe3vXj4vfo6L//v+/v7/nu7r///9//v/v09N//39////35+f//v///3///////////////////
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////yH+EUNyZWF0ZWQgd2l0aCBH
+SU1QACwAAAAAoAHkAAAI/gBrCRxIsKDBgwgTKlzIsKHDhxAjSpxIsaLFixgzatzIsaPHjyBDihxJ
+sqTJkyhTqlzJsqXLlzBjypxJs6bNmzhz6tzJs6fPn0CDCh1KtKjRo0iTKl3KtKnTp1CjSp1KtapV
+h6QkWdrKtavXr2DDih0rlpFWsmjTqkVrdq3bt27bwp1L16vcunjn3s3LNy2jVRU/MKhAuLDhw4gT
+K17MeDGCwY0jS54c+THly5gvW87MufPhzZ5DcwYturRkBGkqvgAEdPVP169Z+4Q9W3ZP2hJx89St
+k3dv27uBB4+tWvhO3ziRJzeeU/lN5zWhK5ROk7pM69eZL2+t/Xl3hthj/oZ/OZ789+jn0ROnWN5l
+e5bv4aefGX9l/ZTx7+Ofn537+tr/5cZffwAGeNyA4iFoXnH+FejgcAb+xmCEzSm44IMQ3mbhQPqh
+1KFJH4K4oXwNajghhhJSuJ2K3p1oIoopvgjjihOFWJKNI+GY44j28dgji+D5qJKOIRFZpJAeIpkk
+kAvZOMsBAAjQykdOHhDAJ1QqSVAhAABwpUcf0iJCl2TS0ZGNmZDpSJYcpekllmfyaKMXNtRCZ0av
+jEJQiIUIAAoBcMbJUSEUxHJkQa+wglEpgGKUJ4da1vLkmn1OiZEsoUC6USkDrJmJlIKyF+ksCWD5
+qaUWydJFHagIhCOj/oFyFCKpsYIp3CZPRCKLRXdeumqrs5Zay6kaxTGGniESS2uoNUYKay3PZhQJ
+FYnI8mqjtm5KwAVd1pltQangkYUnFEUrLbUtRGqnAKocsOZGmlDxRwyRZvLlpMwKqC2W5mLEyh5U
+zKAutNjme5G9WOJr8ECerJqKRIQautG/RsjRkRcAFNrRK4kUYQZHGHt5wbsb5edso/1mFEoQVrS6
+L5saEWunt7J+N221DyncUQ5OsJrRk2Z6AWpHN1RxbEc6a2TyRsvKjJAncUQt9dRUT/3DEUgcofXW
+XHc9CEMpK30ylmKaaRAebFSt9to/VLG21F0cQYUmDkXMENRvs13F/hFLXNH131wvgpCy7t6dt9pt
+L3HEH20ADrgWuyrktNguXlT2zAulEsrmnHfueec6KNEFuQt5QoUpYBdc80aXh11LJ2Vw8vnss+dg
+B+2cH3IEHg8zBHRDmuNOew5mPDE6RggTXOtBwQvveQ5oUDFGpnefvtCTNJcsp7qcRomqRq8Q4nFD
+pqMuOZlvLmxR9wCQbJApcbzSbEKoGEt9Q5V+9IoPSlCyEZddch/4dsCESjikfAl5UrdgNj+eUOIJ
+h5BBehB4oZTAT34R8c0rDvEEA8bkgTvog09AKELyWa8lS9NJw3wGHQpW0ILxy6BxHngIDL5khagw
+EkdwSB0XkkhU/jpBxRhIVwvn+NA9A4PIBSGiG0z4LCZCJJ0OwVcHKU7whEis3IEScsQstmSJDpmi
++ipUOix6sYEz6uIZWQLGIDFJPVw04xplWCKCqHGOK2njdJJ4KBbd8UdAjNAfUchHiegRIWJcnYoG
+OaTt1bEWjPwhTA5pkERq75ECieR+tBgjSMqRPoWcCCX3FMpvoUiTmwykg1AJSJmM0lWlHCONMvnJ
+BHHyJtWCDStb6coYHsSSlPsJD/xgx1raUpU6ecUTisiaXfKylzYk5Rtn8ooi2MaZS0JmTjaBB2Zi
+s5E3McUaeifNGd1kE0OQzTdPEp8TYKEv8ByLGvRgCQ1IoQmK/oinPr+igXfuE56IOMIU3iCISWyl
+n/9M6EH9qdB9qiEE7zQEPhsKTw3woSIagIxpNqoYFmCgAg5YQQY4StLEGECjJTUNDo5AAhMAIQUg
+aABKU1rSk9L0pixYAAM44IKR3pSjBkiNNm+SiixA0gh3mCZL8AAw1I0iEj9Igv9ktJOivmAOxoQj
+GnNSiT+YjgaykUU0W4QTTHj1hC/ww1jJ2JOu1oAJ5quFWNm6VZww9XQvsMMizrCESGwRJ0X1JOqA
+mRHCXoSpSK1FKPbaV7rqaydPOMIe6nCEKCzifp20SRYeVj7DXsSzFYlsD6xwhDNc9q91tckojjCG
+Q3giXUpl/skfPPjVWCpyJ6sdww7mELkMPRYnsgiEomAZ25Vwk2GJNedMgqso0N6yIc51iCzwQERm
+FlclyiTIW+OKWuBSl7jKbZJtKTLd6lo3vDDBmauwyl3H2qS8mkJvQqK7EPgWhL6/1dA6s3kT+4KX
+qnSsiX/LCeAt7ldE3jUvfgOc2pcMmMC+hdCBSbJghDz4vAV+SIUJcuH4ZpiuExbJhgvS4RFD15Ey
+6bCHI9zdEIPExAJRMYzF+9yUqHjF3Y2wi00ZkxvPeI81PsmNcZzZHAvWJiYe8o/ni+KYlekhQyay
+QBIlETd9CXzIGpiYrkyRR1WSOc5kX8YkdkmMPInLChxa/n2/C2SEYPZ6VgrUmZcX5Db/TAFTSh5D
+oizlWuBKVzkrgaG8oLGMqKoONxhYISSgOokc2mV93qXrgmmRPv0pUHfqlUL4rBz7McTS2AI1nYeq
+YT4mzcJsPnFCwjWuKqtZWkYQQ2/NnABINHoiN+utclg56cJqKVpNe7VB+Izhg2yCCnsYrkL61ev8
+MpgjzZZrqlWtkBWSkyFiyp5GYsAFKmxCI4WgQ7Qd8i9v//cgqBSzAH2tkWg9q9fELvZBZJGIXM3a
+IMy+dZ2Z/BFNo9q8bmRIrhfipkLXLBS/ukgpCtCKcT8E4axqYVYRUgguU1rh2Hq3vqUNcH4zJBV1
+aDVC/vI96gaHMYl2UwgcwnA4xLmt5XGI29zwZ/GnwVxqbYsa1hwHOMEZxAtmmjTebj41vhGB53/z
+uUNOjZEPuRtlG1850eOQ85tHtg5rVR5BHH7yfUMkfws5hfOGd7uxh0J3vGsI0w3SPLPbLhQPPB5F
+FIg+s4HL7J+Lew1MXbjbYhxOwf4eQcSO98293eyYoEIWvn0QkpfZ5BQhNJl5jJD6TW8hpYCCQPRc
+sj4Q4glTzQjXGRI+0MubV+8C++P/LpDL+fuz6eEYFQA9ctWNPuCQl4iYxyzLWmywgw0RU5dqnpHQ
+1RDaG48IDTEYIvYZfPUUcdPw+TUA70HfIIlPdkKk/v8m7hM/9zRm0fJh0jAh5AEnOISwkYs8kFGc
+4Qx6Oib4tVoQJ0LaJVFcchS/fN0XFqQOdANKXkcgHzZL6+de7Nd1/UdImISACUhW81cd43VxLOaA
+FgiBznaAGFiBBqiBSNZkBfiBDdiBDyiCpHaBJihfBBiC9PdsHLiBHtiCMSiBAyh/LwiDKJiCNxh+
+KmiDO0iDCyhJGViCMkiEQNiDMJFCSOh/MyiAQfhMTDSBFGiER/iDVdiECOFOFPVPCLWF8dSFXlhR
+DBWGeQGGZFiGY3iGdGFRGDVTP7VRNvWGJBWHcghUbliHnkGHeFgaeriHeShUEeiELFiEJJiDVxiF
+/iOIg4YoiIPIiC6IhT4IiUkohey2hOoniUxIhStohZuIiE8ITp+YSpbIgCdYiIpoijrIiZFYaomY
+ipiIR5q4igo4ikKoipPYioRIbbQIhbF4i6HIX0O4iJ3Yi5kojLKoi404jMboi7sIioGojKcYjbko
+jYfIir/ITpTYdNloEUvmccn4S9vIjeFYitToiK9Iis94jK5IjLC4jMWIjLb4juUIjfOojjxoEXM2
+ENJnd9r4M3Gmj9M3hRORj5unJtc3kP9YkOlTiQfzZJICJcImjhmxjwJBkAwZjF/nJ9gyC3g2LN+X
+jhSnkYAnaHbyfDUYkpdWkYWjerCHEaImEJzi/ikRCZIHwZF59iWZpm0SeRE26ZGf8JICOYusVxBr
+R5O1tzyTc5IJAWzCkpRKeZSbByrL0o9M4y6BF5Rz13e3d4+PWC63tpXeOJQDkW1YGRHmIjTtsm5P
+2XjYkjxF2ZUVASsaV3Jw6ZVwApZhWZdmeWuvBxFedm7rUzAFN3k7uSiqgzEmWZhTpmwQcZbDNzJd
+Fn+nxyt1MpcVgSl9Fnk0g5eIBIKBWSspNxGPBphxeWsVR5fWaJiAdwBBM5N19Wf3ljrL85b1lXB8
+ojGWWRHGkmX/Y3CcCY5riW+qw5IUkWtOd2u0mZpDSThqmVqs1nFLeWtOCRE3A1sZAXZXaRHx/jIv
+WsKSv8l/5NiYBSN5GlFuAtNuGad5PnmRn7l5X/Kdl5hJDuMQKYM9/rIHFZMR5Nl6IhA0OjkRHDM+
+GLGfAwGf8SmU0Yc+V7J7iSkRK9MyDUkmVyJ8C0mVFuF9WAJA7XOQAzFw26egn0B3/0kRPPNE5VJ9
+ZFIo3eOaE1E0RxOXKNolFHAJIMqenqgSQzd1V5M1SMc1X4OOJoE2U0c1Vfc2MheAG5GjN9c2fOM3
+Pbo1SocRStpyibM4jfOkRwA5vIigJ9F2hRc6cldtE0dh2Qg7slN4nXN4uIN215YRXup2xROmKPGm
+zgM90vNmTzOmfWSUKxE+AlpG7eWMJ/FK/lxJEJaHp33KP6G3E69AQB5UPYGKjcGJEjQkQZDKjChB
+qHk5ZRz0qC9BQiP0BCF0QHoqYp5pE+kncZEqqJnqS8opEONHfr/SjXY0q/OxY8FJq7Wwf6RZTKvK
+qq2adXlpfzLBq7rqe1XUqwWBq7k6jqXIrC35Ra6Ke/Eoj0eGqXq5jtdKjyWhqQdaj+oIrc3agOIa
+rS7hrcoKrtjqq+b4qkZWruZ6rtPamdcoqehWqvbKp7UIr/Eqr8KamdpKgvwannZGVQOrmC+hqcf6
+rTB4sPq6sATmsJPqEYQKsem6gRKLkdSqE7mkTvhai5M0rwA7jTYxTOyqrgxLTcvkGhk7/rEfMUoW
+O5k4UU3X9LHA+hBaqIZ0IQhkUE9YIFH5pLNwYYZCKxaKsAWNwE9pWLRrQbRMqxaCgAL+BLRPmxZs
+SBEZ5YehQQIeUAEGMAE9pbV5eIdiqxgbcAQqMAIdYAGE0Ydlexlu+7aTQQIQMBg85VNyKxlB5bIl
+sVm1sF3NOBKR9Qd4sARnkAg54KwaWxNZAAOA0LLjWlVG5QnJ9Y0qcVdOBVVSFbhdmgVXZbNAmq0x
+0VW1FWP/yq0uYVYUlFanW4034VZwNRBzhYqFahOYm1eM5Vfs2LlHFrMWi1hJtVh8pbsoO7IxEVmT
+VVmnVa0o4bedpbiiKxOiRVqmhaiu/guPqsVarmWdlqsSs0VLYFWvI5FbuxWbtFuw7yVcxtuuM3Fc
+mVS5zGtj6uu7p7pc00a/ybRMAwG43asS9oW/BMsSDwbAOaFeRcRe/YsS/kXAiyvA03axJIsekBvA
+DlxdDBy9NvbAEHy9LTLBDVzB9wW9N/rBCqzBG8y+K+LBI2y/AHfBK+xgJnzCqHuEKsylMFFiIuyu
+OgzCm+qOL1TDG3vDMezCO+y/Mby+M+yIQIy+MAydMlu8MjwSnJbDNoyAS0yvKXbETxywQYyQFrdl
+qElsyEFlS5eQYtagD/EoHWKRtQBAH5kQfxmfrJSPFOqQ/ZqgXWI2FLlnWvzE1nsQ/ntsZahZxF0c
+EUApEIuWfBxXxbD5aSIJk4oMEYeWaC75yIiMxnuWcAeqSYdcoJFcxRDRkwgjym8cY338xJ52PR05
+yiRJoAj7wnY5EKRiayUXb0/8nA3xdINMnbFmvrq3kcJiER76xOnGlyNKwmXsPrQpxt9xbNqndn0X
+lYJHwcApegUTbpNmy1sMSfO5bBkXo80pEdxmbkPJKNwCAMfMEOXGeEZUqiljoFGcy7aXfPEGHfRm
+b7I5liKQzrAMynt5lwznOtq8zQIxzMK5PKfpaxB3f78MJ24ZzROx0Kqaz1uCyRjsEK/Xl7J7yusL
+ciKXEL0ymGVZuxMRLUCndQYh/nVDWqSHc6RQSZQQbUc6+nI7h6VHEKWQ7NBDo2lTenNGZ9M3jXmq
+k5z9PBGh2caYrNJL+nIwd3XCetRtXMqETNIN/ZDoAwD8KBCEh6ahoKbOw6YvTRBFSae483Zx58QU
+/SyXIxBk7Tx692vDadEXvRAsSZwFsdV459XCk3iLF5LTTNTYO9UP8c6fLNiH6s1w4gWpx6JM5Hmm
+15610DqFjRCl5z/HKWes6XcV4cqubKMGIXu093O+qZ6c98qCzRAY6sm77M+/56kGgaHOR5gVYXyt
+S3A1yj7hzBCxqh+pbdembZYxmjGiENxy7c+1kH2MWRAMCgtjUqF3fNooHKsu/lF+53cT6YfE9piL
+7gd/SVzNM0KsMJF/VFwQvJqyHBywAHjeTLy7IMveW3q+KFzI8N3d2R3fXBzBPezDoXuO7a3f/R3Y
+/v3eUCzg963e+T3f9W3fBq7gDI7FnJuvCfzfA36zxo3f9L2uAU7gC+7dEa7hG47hGS6KyJzgJF7i
+1mrhJm7eH37iK96OCA7iAP7iLN7gKe7iBX7gEy7i8evhNA7j8p3jwLjjFC7jNr4QOVu1buG0SD4W
+Sr7kYtHkTq60Ua4WUD7lXHG1E5G1eZsZcbvljNHlXr4YYB7miDHmZH4YZn7mbQuII+7jKF7jEn7j
+F67iPT7jc77f7j3kPy7n/nAe5y1e5H8ez24e6H5e53Y+6DjO54hu6Hge4kFe1EAO4UKu4/zN4xw+
+6Y+e55Su6Zle4YSu54p+6Ive5zFL0Ize6JEu6e5d6kTs6KrO6a/u6adu6X0O6m8u6nR+54U+67b+
+6Zsu67pO66M+7MQO6Il+68bO679O5Ki+58je7KGe7MHe6w5+E3F8rF62ZHGM3dglmab+Etk+3s5+
+7A2xx5EtAlK9aZrcIRR5xrINZbY6kXbsxqstu5rM7R+ax3Wcx6K57koSyAaZKvGOPA4pyCO93hFB
+ynCSyPWOEMaJJAoPzwVNBSbLk6v8JVAdEcOsHwq/dZN9EA9vZhcfoivJ/tgOMS0Vj48jH5PDYvLA
+Dp4agS+z/PEJYZ7qMikSLxCs0ANMwHj+6AhTaRHrLOhw5j4aDRE2zxGTkp0XsfM9X5WOoCzB/Nwv
+n8/YTPMK8aAM/ZnqpjR2cO9cvy0LZBESzT0FA89a/zJoGdPc+PUm+pkPndvQfekXcScL13D61tNU
+WtNYitM/p20JbRB6/zY516RA7fcCcSdxzzBDKjU/bdOI//cVLduDnzdX0zeHrxCahpjvnkkr7TaG
+D/kI0SshEwCQaaFtrhB2c9Ku09bCA6Zo/RBQvXauXzt2cNYXYTcyo2m1Tztv3ZtkRvtcvTmwf50a
+8ztCM81szdW2g/uV/maSgD3u1V5pUgkldeco4vMx1xmR0b8QMvAFj039lqLW/VkRlf3tjvw9GQ+g
+2Q9uQ8OcGvH94V8Rdj2dqY/vo5+YBlqpSkKgio3IACGgVS2CBQ0eRFiQUhEwrxI+hOiFQqyCtETQ
+qVWKwCeIHWtRenLIYa0XgDyeJCiRYsFZBzCi9AjykAyTMDuqLJgpAEeNHG1CXNjw50OcB1vaGAqx
+ZNKCS5kaLDUAwFQAEwn2fErQU5c6qEjWzJpRKlUKosZaDbu1zg2wWaNSrRrrLQBHTNV6bdr26dyp
+EwsJDFvr7tfAYuH6pVo3sFq2hflWdXVgKtLCBJ0yvVxZs0FUYzzl/t0cmrNnwqIrd/58MLPpwKhB
+sw7tejVszbNt2qZdGHfurLt5P/X9e2hw4T+JF0d5/KFy5B6ZN1+uF3rS59NVS7d+G3v2k9UNeude
+Orz28cO3l08Inrt66+zZtz+P/rp8mO+h278fn75l/R3xN/+vuAAF7I++AYU7kDf3CjSQQfQSVNDB
+8iDMjULYFtyvOwnHs/DCDcPrkLUQRcMwQ/8+XA/FFE1USsXsRgytRBbTc3E6GGOsMb8Zo9sRIRl7
+fA1I/oT8LkcAjTySyCGBQxK5G2trkkAlxSPyycp+FNJK3aJEkMsIp6QSSCzF9LLCMs2cUsst03RR
+zcDc7O1M2uBksRJMOjFz8QQsLOGzTz//BDRQQQcldFAN9iw0UUUXTfRQRh+F9FFHI6W00j8ntTRT
+SjHVtFNFNeAjKzciqKBUU09FNVVVV2W1VVYfINVVWWelVVZYa8U1V1xv1bVXX1Hl9Vdhew12WGNn
+feARMJdltllnn4U2WmmnpbZaa6/FNlttt+W2W2+/BTdcccclt1xzz0U3XXXXZbddd9+FN15556W3
+XnvvxTdfffflt19//+03IAA7
diff --git a/Documentation/DocBook/media/pipeline.png.b64 b/Documentation/DocBook/media/pipeline.png.b64
new file mode 100644 (file)
index 0000000..97d9ac0
--- /dev/null
@@ -0,0 +1,213 @@
+iVBORw0KGgoAAAANSUhEUgAAAlgAAAEcCAMAAAAsmToJAAAAAXNSR0IArs4c6QAAAwBQTFRFAAEA
+EAEBAwUBCgMBCAUKAgkMHQIDCwYXFQYDBgkVDwgFCAsHChASJwkDFA4NEg4TDhANHgwHDg8aExAG
+DBEjBBUZERMQCBNRDxU0ExcZFRgVFRcgCRkzHBcUDRdCNRELIxYTAx4mLBUMEBwcEhsiDxwhExsu
+Dh8XJRkQByAtDCMUHx4bACk0DSsiGScsFCRcJSUiGSZCDiwqGCg1LyQbIycpVhsPDy0wNyQVECxA
+PSIfCS84ADJCEStWRiIULSwpADdHCDkgEy1/BjorEjhADDhXCzZvITNPUysQDzs8MjIvCj04BT1O
+PDEoQjEhMDU3LzY9KTdFTTMYNzk2GD6PAEpfEUVjBExFCEpPB1ArK0FjKEVZYTscdDYXG0d5SkA5
+FEiJQUNAOURPAFhCA1RpP0ZJVEMvYUAyBFtRWkYnDlR+QEleAF1jkTojHlV1AGB4PlN5YU87cUws
+SVRXAGaBWVJKUlRRRVZlAG1PWFNSBGt5AmqVAG+NAHNpK17BWl9ifFs9KWmnSGZ0YGFfp1IuCnWj
+AHuKbWBXoVNAdGBPDniWAHujTWmLk14rAH+ch19XX2aRX2t8AIeLiWgvAIeeAIaqa21rOnehdW1m
+AImspWJYj2tLW3C0AIyvWXaNAo6xb3Z5dXZzent4WIKiQojAen+CkX1pcoSWcYDOoH9fp4E+Y4ur
+hoWCXIvGb4mut3xpqYNYnYdUO5rDyXxdjY6LYJqk0IRGb5azXZnMjJGUgJWqpJB8l5aUyJN4kKK1
+rZ6IYqzge6Xho6GdnaWpgqy6yZ9zvaR0hqzMk6rN5Jxxw6mF26lbq7C2pLTGwrCbs7Owvb+8zcGc
+8rp42L2xsMbY3L+jtMfsz8W2nM/yx8jH0MfA7MWU78h/3crIyNTo4NLD6dK1z9bc1dbT3NXOv9vr
+/OKSwur8++Gw4uTh0ef78uPU+OPL3Ojz++bGyfH36evo/+3b6vT88vPw/feu1/v+//bb//nK/PnW
+5f/+//ro+fv49/7///37//71//3//v/8sZeTnQAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAFY4AABWO
+AUTUBDsAAAAHdElNRQfaCRQPAiJBEFMLAAAgAElEQVR42u2dD3wU5bX300nWws50shA4lyTGikRE
+Qy0aUChKvJZqTQGBFNurVo0FWq2VqhAq0hc0t1rAxtLLpu61cUl6gWtNe3vb7Z9IKm+Xqn2tkFih
+GmwFA9Xwpw1s/UOyCc97zvPM7L/sbjabXTLZPL/PhzA7O7M7s893zjnPmec5k8WkpNKgLPkTSEmw
+pCRYVlSjp5n/3+3xGGsONHt2vx1t04PNTbtP8aUujxAuHvN6XjHe721pbmqLsp/H021+crP5wce8
+Ta8Evi+wKMHKHKkwjf/vA+D/77SrAKDeeTRiO3/vcnzDoTzXgy/+CEKMbVdw5dh9tMGubAfuuMjf
+E7HnfgAf/X9yJn6Aupqv206fNfYdXHr/Aloc944EK7PBWg9QurVxlQ3s70Vs+FmAdQ0LAP6By1cA
+KCT2AsBqXKme7mEfajBr25MaTIjkSjPA0mHsVnz/G8jgzyBna4MGH/UzdgHYt9ZrMNovwcpksN4E
+eJpeHbLB5PDtelT4L/wP4Fr+95NirQa34d85cB1jX3eAsGVhiPRuR644WPjOafxgHXw9uD8axL/k
+3+gj3P4vLgJ0SrAyGaxzoFCsfpObJh8aJVMtzUSMA3JZTw/Ab8RKYcD+Rvu2ehsJJIBu9llFwdW3
+0l8N1B0CrDlgpz1K4OfIkRqgT4cOjNkkWBkLFiM4ejT4nXjVrcH/wb9G4BUUwOcZ+xCgtkh74Ci9
+9Iu1Jig/BjhDhmzCGUTzccaKNx9lAqwSUAVY17Kvw7U7S2wLn6fXRXCzn90P2dIVZhxYIlxSiCE0
+W+8F1l+GYDU0hG99P9/gVxiEKxiGvYPMoCMjT2a8fxyRQkQw9HpJg3EBGAmsr4PDz8Eaxz4F+UBf
++DjtMZ0WJ/9ZBu8ZDlZwfX7fjTG0x9ibPTF93D52UEdELgD9LXYw19zteA7onMwLAHuI74SB9QGG
+b372DKAvLQF4xN/7FPlR/17gjD3H/BKszHWFYRbr6siEA7sL4Jbga4zG2Yd2sCuqaoC1H63YS3wJ
+nSW3RyFgsQ0coQLsNn4KdD/3gtcauG0HOCItVgYH78EYq4fHWOFaDLA6tMNHe3St0m0L3+Ixln+/
+BqP3ib0xGue2LRQstmu+vXjz13mMZYRbubhoFw7yXyRYmdwrHMN7hR/fgVGSdrovVzvEUpuXYPhn
+wG9+wJcOaTDZ3GcOpU/fiACLmb3CP5o0ncemCcamQY4EK+PzWD3zYayNYvcwYUj0UiCldTf+9yXQ
+2RNlKl+6Aw2YLRCtU/D+uBZgxQDr9iIkrauIeo067OOu8Cfs38Fxgi9+XoKVyWCx+wBKG5t1tDfU
+9ME81hlybtki3U59w9XNuOVL/r+IJbu/58yXwOgGdPd0aXAuwXU384eAdT7YtzXqPPO+HuybPRdA
+9hnW5YDR2zz41ntnJFiZDBbbbnfQvUI7OBaF5bF+ZdwehALCj+4n2n9qLDkK/8zxMdSNjlA/3UP4
+vRFqsf4+xhG4V8h3G0sB+/4ptJjzB5luyDDV1otUVXd9vbGmpXFr09td96mXha5kT9Yb4psfbKxv
+EgMdDjZuE2MTzPfru/9eX/8HsabWeMcY3eBtaHrL+LiDjVt3B75v224/k2CNFL3+D/kbSLCkJFhS
+EiwpKQmWlARLSoIlJSXBkpJgSUmwpKQkWFISLCkJlpSUBEtKgiUlwZKSkmBJSbCkJFhSUhIsKQmW
+leRP28f50/H5EizLSlHEDC9jCuGxJ6crtoU7TkVjxJxkuGu+XVvNp9t0bS9SFu4Ra1+/PTt/c+R+
+uFLbfMJYtNvMbRk7nq34JFiZrPB5hYdsoKqqA9Sjfbm61ZhkOAdwG1D3IVd2WhJFGp4CB+6Xw8Iq
+kD6j0QbZR3D3F/he8CPjHT1s3r0EK8PB6rHBLARmby7kRm538i4QYP2Jag4dmwkOKkU69gjbqcEb
+rOddgD1sL8DDofu8D/C4/9gCyPHTrNVZp3oXixpZjCCVYI0gsHy8Tihjf1Rt+Le7pSWw2U4bjBZg
+faUEkRJ1QETZte8ShefDT3CxtukV1tXSQm6yBXf+d7Nc0T9o2/d4SUjCyf8iTJZgjTCwng2+FVKG
+janqMn9o3UgDLOKmy1g83NrKQ6zzwc493+/YFFFKpoAqIuk03/5dmoCP1g/00xKsjAerpIWLYzMK
+oDTw9ACfqgY2w7A8rCDpHEETzZb+kPgCeIpqAz7HOD0PI2yXMfYpUcS2gGosLwf7bq8G1zNuwn7D
+JFgZD1ZAFBWdTxVBcjZHezJFKFhPAfyQwLqDu0LOGCysmi8qHS0G+Dg6wR4qJHKCVy4ajWtn0lec
+SzvfDzczCVbmg1VQxWVgs2E6oaY/HgcsP3FVKvB6pGUDCLCu53aMB+eE0E9E3y9ntxet4Gh6a/QD
+q3Qi62UYyyRYIyzdwPt/O2/Xg+X4+oJF1bNhEV/k1YgWCVdIXvGfIupCS6Xz9/8+xQGQOwddoXh8
+ABqv/8JNf9/a2goQ0jWQYGU2WH7W0cbJ6dL6lLYNsVi3AnzNWHfwyXV7WDCOZyI4p7ptRvW/XdVb
+T8/B4P1TZtnRccFCWqoEa6RYrCvUfHPt5JhgfTeQ5uxobz1DVd7HElH0rIq/cb5wAx3yCLTDbf4z
+It1gxPElMAE7mCQqFS/BGilgIRiXdeDyTkoWsO7W1ihgvYkheCuJPz7nBDumUTbrV5D3NvOdT2VI
+j2O8hRudxz/8YT97EXL9fnSFz/nZq4FnpbA+z7yQYGVyjLXcAXb+MIFFEXmsIFi5gU6kv0tFs6OK
+eGsBf1iF9g9yhLnMz0vh+u/npd3VN/j7/EEBpWcCYMngPaOlqCWhSatd84tUteDGHZF5LAKLv+xR
+TeGLQ/N1dcZm8faGEjV/4VF0hCoHaaaqnOIrtYXivuP2MlBnBOvEq6oESyq+QobC9ER7vydyq5Eq
+CZaUBEtKgiUlwZJKnyqmlXRLsKRSrhJlBI5KlmClX+USLKl0qFKCJZUO1UqwpNKhZkVtl2BJpVzt
+qtIswZJKvRSlUoIllQ6wFAmWVOqlKkq3BEsq5apWyzokWFIpV4eiVEiwpNISZHVLsKRSrlpFaZBg
+SaVeoCidEiyplKthZGYcJFhpV4FSPgIHZUmw0q8KtFkdEiypVKsbwVIafBIsqVSrhNCq7ZBgSaU8
+gie2ytq6JVhSqVWVSlZLbeiUYEmlVp4ChexWebsESyq16qzgZmtahwRLKg1mSylvlGBJpVotQLGW
+T4IllXKrpYyAjKkEaygEmU+WBGtINE3J9AmHEqwhIwskWFKpV4mi1EuwpFIvJbMHAEqwhkrNme0M
++4Dl6+w4++rs7EnT+Q3R6SRysxm7hu3D5HQGC1Z3x7Kc8RNnX2XIds1VadXU8ebS7Ik2W+pHlfja
+Z+RMnBg4CVt6z+YqW+CHmzrRNr6x39PpUJQBPQjF10anY37HNek+nYkXm42Dp6N5O5MHy9eQs8Lt
+CqpufOirNGjtNaGv3POyWlOJVWeVbW3YCUysS+/pTHWGnc5VOYf7OcKCgSSzOm8cXxN6Au7x6T0b
+15IVoSy4LtYOJwlWs80Z/slnGSxaYUuZ1equ7XP0Zxcs1NJ+TqdNUaoSPZ2qyKM/u2DxCz/flwRY
+3fkrIz/57IPlqrumKjVcdUReJUMBlqtuam3co0y4sENn39M562DRV3oHDFZ7Tl+IhgAsl6smPxWD
+LFuiQXT2wXK5NtrinU5VGbQlcjreiX0/eQjAQhtcNUCwWi+OwtCQgOVy2gbPlWdetK8bCrBc7nh3
+broVpTyB09m6xGURsFxrywcE1oGov/nQgOVyOgadIVrisgxYSFb3IH1h41KXZcBybawcAFi+0VEJ
+GiKwXM6iwXHVNs9lIbCQrNiHWpFA9r09+q80RGC5VtYmDlZBdICGCizX2nWDSjPE+sWHCCyXszrm
+sbYqiqe/89FclgLLNa8lUbDqV7qsBZZr9mACeJvbYmC55nbEuWFY0s/pFNVYDCy3LUGwfBe7rAaW
+syR5rg6sdFkNLFdsZ+io6KesQ3uM5h06sFw1tYmB9aDTcmC5ViQ9Rao7x2U9sNYeiHW40/ob76e7
+LAeW62JfQmDFMlhDCZZzWrJgHV5pQbBim6zGfu7qdC+1IFg1iUwyyvKstCBYrquSBSvfZUWwlsS6
+xtv7id5vrLEgWHUTEwGr3G1FsNY2JTmgYbwlwaqrjToEprMdu4UFFQWxx89oLguC5Zp3IAGwprqs
+CFZNeXJgdaywJFiurOiDkwOKZdGWWBKstZ4EwFpiSbBcSSZJm93WBCvaLcP2ELBi5bnWWhIs94PD
+F6z85MCqqrMmWBdGM0mOAFexplU0bLQmWAn4k6yl1gRrYnJgLbMoWHN90buEhmL1DGstCtalIw6s
+iuEEFus3xFpnUbAulGBZGqwyg6uY4zkkWBKsZMDqNMDySLAkWKkEixcHiTdxVYIlwUoKrGYBVrcE
+S4KVUrBE+B77xqgES4KVHFj00ArFK8GSYKUYLF/cEEuCJcFKEiwevndLsCRYqQbLqyhx5r1IsCRY
+SYKF4XurBEuClXqwKuONTZZgSbCSBYvFe/yqBEuClTRYtRIsCVY6wGISLAmWBEuCJcGSYEmwMhGs
+JRIslFM3phzrOsQ54keHCViz9VFiI11fGe901kiLlW6wwOBJh/zYW10EwwUs0A2wIA5Yn4AVEixL
+gAUZBRa+KcE662A5UeZ7xrITN3I6hydYEafD/yewnBKsswqW8xOA0jfRms/RItxM9oo0HMF6lB95
+qVO4c+PM5vKVKyRYaQeLWyYOVo0uIIK7Xa5vGosPDTew6GwEWF8Vp6MjTuKK4WRJsM4SWKYQrEkA
+ZKwuIYwESxcu2TS8YqyAVrrcAJNx3RaACUZc9f1S8oEyxjrbYNUA3GEE658nyAqXOodd8B4C1hf0
+vG/Tyq/i/25yiStl8D40MVbIi0K60Emzhm+vcK7xoo5e3CA84b0SrKEBy2m8GId/vxgIroY3WFt4
+wPXo5fxs7pVgnX2wTFdYQ66Qa+MlwxgsdIWbTFco3l5TALl11gJr49xJ+Zfem+nphgIRvF9EXUWA
+q3HxWwZYzmEIVmjwjl1BKrl1OYyzFliXGB3Xh1IOVs0NULppoGD54oK1ZlL+TcmBZYby+sO8a8g1
+ziUyWYmCNQlqBgpWd1ywHr08/xpnUnksI91AOQZ3gVii1RTI5z2UIFg3wNI0gvUFgM9sqrkHD6wu
+xWBR5kindhwQWNOUKl9MsP7VyB0klXkX6Z6QBOksc22CYH0ZBg4WKNXdMcH6ajBlO/AEKcdpFh3f
+lot0I8Ry8UB+ZWJg3aOnE6y6POCPqXlUh9tSDNZFUOz8NBS6BwoWKoytIFiI6t14oNclBlYqFAoW
+IZgEWKgwtoJgoXn5TE0BfDIxsFKhULC+gDSmEyxdXLimq9ENr1in67xTXhxYC6V1Bueom/iuOl5y
+t8UC69FR8DDyqn87CbDC2AqC9W90OP8Gk4YELPScyYIVxlYQrG9SBP5lXXcOAVho9wrTChZ6F714
+ZRhXSNbdBJzQVdyaBVzHp43VpS6xSaQDDYK1ln6xLaH2ZUBgBdkKgnURXEgxd27dkIB1t2sQYAXZ
+CoJ1Azm37+uwaUjA+ow7ra6Qmp74mOcMmq8vQK4bF9H5110CY92uFaDjXl+dh32PFWi9hdm6jbbW
+H6qJ6QrX8r1CDeLEhgQU0hIGW0GwdAKrJhTmszuCNBys2fUJnI4adjrEVhCsKwks/BU3DokrdKUZ
+LIxkddMerRFm+fuj4A4836uIIKIDadJu4ZcVgja5Tti5c4m90jgxlgnW7CAFSjKq6gMWWAOsS5M6
+neogWJcSWO7MBQvbiiei5xFBhm5Caua6XIaxKuC92eJNLmMtIiiM2uwEwJo1OLCmtVvVYiUFVmXn
+yLFYwiNehE5vBeUHuOaGgeW6h/dt9W8PEKw+MVZ3vwqNsYgq68RYfcCa60vgdCCcKtbHFQ5RjJV2
+sJaCkWnCBfeaYA8lHCye7dRhXogrnFwXoCxGr1AfVK/QoCpar7DYZRGwBhS8V3b27RXqQ9Yr7B+s
+jsGB9X262y9uDlxWh/ZlFrbUo6VLnSFg1WFHG/faMgrj9jV83GUgeI8Hlisv+TxWkKrwPBbEymPp
+ISOv+tOWgn43ASMZmTKwKjti5rH08/rJY9WJzO7Fse8uzU00uz0QsMpaB515N8YifttMUgHkhoIV
+SEKQC7oE9JB0Q1ywRJbiNtfAwZrW3h098/7pWJl33XTi/YPljH/bmSs/pWBVdsTIvFOO0ribHBus
+uov4uYWl6Psm5VMPVr3SOLgYy8CmeFPwRbEz3BWKtYWbAglS/SZX/2Ald69wWjhVCd4r1EOzpmkD
+S9cHDJajsiPuvUK4qr97hV8QRIVb6tSApccDq7Vv+biBBu/OkPkewQkf5n9ha8OWnVHmtwx6dEN3
+UqMbQsCqyZ90zyTRFf3ipPzZnGy0clvmTip9iC+izSO79uiVBcaYjnxw3TPpwltMdC9cEgusCAd0
+dkY3mPcIL9dzuSOnkxK3mddcWZA/9aEgWFvmFly4xEDm0UmznP3dhA7/7gv7lo9THN0jfTxWKFim
+uzScfDF/W7y42ozGzFvSfMyMGZ/R3gVmZGAZsG7g8z8CSUdxeDRmRozug3NNsIzzXcvBmgR5mwYJ
+VjkFh+0SrFCw9E/y4VaFaylDV8xpKtxIMR+a2Ro+k/DLGDg715iDSOGmGgzfruW4Xc9XWwesOqLl
+QmO83Fd1KN1Y8zli7Vu6fq9z4yQaJcPBwrdmbdp4ER9IQxHZeXWDBKuWdzuaRzpYgU4hgkPjBWqM
+7u73aaSMDvS83G9yjJwGTNfxZbrhLpb58CyA8wSb1gHLmEEIGh6p8xJ+fM4r521y1XzxXpcxNpnA
+cn6Cj17EUP9eAuu8/mOs/sBqNe58jHSwzE5hjRhz5TSGXrnoRxYjsraEgeUU/bxP0p9NZorB2MlS
+YGEwdZHRwXZHDrZaczkYYLmN+YRz4bw6BOvewYNlPiGvRLpC0xWGdf4IKmMudBhYhgpNyAywnBYE
+ixz4F3XI+3ZY3Qa6HUJpCAOsQCpvVF3MAcoDA8t8Ql7gaQgSrOgWKxwspyFzPoVVLdaauWvNVPZa
+d8g0588BxlhiXrRpscwzShFYtYG7Bi0SrABYGGNNDomx+oJ1XUjeMwSsqy0GlrsAxvKFbyFYGGNN
+EIHUBMMrfisQY10iDt1IfaYCrNbgXc5aCZYJFvX7Jm+iXmGhKxKsux+l0fPXO7d8EfKvDgPrX83O
+oqXSDYUr+QCUUS7R9auhwArByuWnhwwFe4Wue4KT7gcNFgu5f14uwTLBMge7FrrCweKBvlGhxZyo
+E7RSYvVtVoqxPgGBCTmBPNb15tLkAozTRR7LeCt3U8rAKguC1T5SwQreJKwxK0TiVT5J55lpfJvW
+GbUjt1yuz+aZd9BmG+8Gt3GtmaSXbnLpVgret+B55M9+SBzKlhsgV9xOoCNd6/qEPoGqSNaJt/RL
+HxKZ95SAVRvuCeVM6NRpZBe3NYMsn5xiL8FKJVgs1A9KsCRYKQMLg6xpXkWpl2BJsFIKVi09H09R
+CiRYEqyUgtVBw2YqFaVj2IJVKcFyWfXJFM2K4hmuYHWoEizLguUz0qPDEawyRYJlWbBoGkL38ASr
+Q1HaJFiWBavBvAs97MAqD/ZoJVjWA6tNUaqHJVgdNONLgmXdx8opijoswaJR+yDBsi5YZsJhmIHV
+wW8bSLCsC5bHmFMxzMCqCBv+KsGyHljtxpSK4QWWMFhh04wkWNYCywyyhhdYFUbZDAmWdcEygqxh
+BVZnn0lGEizLgYVBlne4gWUYLEWVYFkXrHaRyRpOYHUGRlVLsKwLFgZZZRYGa3x0722oNdZJLbMo
+WLMzC6wZ/VQtI7CWWBOs/HgGyxyw31cPuq0J1vjkwGq0KFjl8Q66mo9PzppnTbCmxzNYsW/qtFnU
+YuUkN26xc601waqPd9Beng/Kml1nRbBqlvWtsuapClTYj3lTp3OpNcGakRxY7BpLgrXCy/qN3rNi
+O4+hBGtljKExtXjQVY7Y0Xu3zZpgtSQJlm5JsK7qZPGj9woEy7vUimCNj8GN6BF2x45YKtxWBGui
+L0mwqjZaECx3fvyDBsoHZbHxddYDa2NF9ENuDYx8jTkOcK4FwaorYMlqqgXBWtEc/5gr6erPYo0r
+rAfW1JhGVunv2tfc1gNrbmfSYE2rsRxYbls/x1xL3cIsxmLxM3RgbVwW02CV9NuRutJyYLnLWfKa
+aDmwlnr7OeRmuqmDYLXMsxpYWuwIq/9rv95pNbBs3YMAq3ajxcByl/V3yHj9NxBYrHqltcC6qj2G
+7y5XKhJoCsVtLbDmtrPBSK+xFFju/i8Tnm/I4jOqaqwE1opt0Y+3Je6g5JC5bTluK4G1opENTjZL
+gTW1td8D7qZ8AweL5TutA9bKZTGvg3gTv0J7hqPd1gFrRfUguWL+8RYC65rdifgMDIUFWKxko1XA
+WrouNleJtlFnVG84JGDNa2CDls9mFbDcF7+SyAFTIivLzMQtsQRYdeO9MQNCpXIATbHWEmC5x7ey
+FMinbbQEWHVKYuFiuaIEwGItORYAa60tRpqqakBcoZr6HvzZB2tFTgdLjWonuoccLPe8GxPs3lYq
+SndW8LJYN945pGDVrc2KYa7aoCDOUJkY7vDGqe4hBcu9IquNpUydkyJGC5xtsNxLshLu3aIZ6MwK
+Pfgm29SN7qDG/9ydVm28JuTFivHj26JfEB0l2B1UBu5TOmpzZteEfMPE9J6Ne6or5MXS8eMPs5Sq
+Y5ntGudZPJ0lK4LLdUtslw4gaVKtKB1ZEUd/eOvCS01pl6ZZ+ebC3GVN7TFSn94CGidTltxd3I7D
+62688mydTsjnL/O2d7LUq+PAA5eetdaZdKG5dOMDLe0DyvHSPZ0sZmV5y8IrpkoNC9VbGqz2anSB
+NLSvoE021fBSg6K0WROs1uoCY6xoWUOHbCgJVirUVlUgLBWG7M2SquEoC8ZYLWXGuPYSpT4t8a/U
+WVCUXuHQqkpV+FOrobHdJ5tnWIPVaSGwqvjseaVaQjXchS3pswxYbdwH1sugKgNUEXqvcIjlAap7
+JW1VRqjEOmB5MFwvl1hliGiqujXAokExHtkgmQNWpTXA6lQKlGbZHpmijsCYdwsEe9WyPTJGLYrS
+aAmwOhKcJSE1PNRIjz2xAlhV5YpXNkfmqIrK21oALF/ch5hIDTuBqN1ghS6hjLAySD5RxmjoD6Q2
+8LhXqUyQl2J3K4BVEO/hOFLDTtV8YvHQg9WtqOWyNTJIojje0IPV2W8xNanhpLYy/pSmoQfLfFyU
+VMZ4whargFUrmyPTPKEFwGqjMl1SGdQnrLYGWL7WVpltyByVG7NAs+RPIZVa/yNuo0iwpFKpShG6
+JwCWP4FPC27TM9AD6Ym+m182UUp0tn9HNFhGTftIsDyqkQZXVPEknu3zdVWbsbnvIR+7vUjVFu4j
+Jj7MUkm054YiNX/ZUbFnma6WrO6740Gb+IpD+MkzdoiVG0rU/DtPibWAn3B6xCNRFmwIUbniNfy9
+HTOWnYqGz1Pmxo9NdzhmPE1LO8t0rWQ1geXfH/JDB/puqiGyLxum68Ze2BB2beGJnqSP2jRYfcEC
+83yA+mpd04FmOQAUHo3Y8KAOqmID/Q90zhqQVNY7Exy4tUYb36/hnhpcH/ndvVOAPyH1VTtk4/tf
+o1XT+WcVcupwUaPFkR4Emw3hAA7WBgf+MPjL5L7Ul6tDYGy8gFoL4BvM/4wDf13gv/5+vuj4Qdg+
+KhhCDhabezF2K7afTbRfMmpWppkDVfoBaw7kPO9jPXtzYHLEht+FcSeYbw5chsu7wNbWimIvQu4R
+5ltM53PcBt/zs72a43fh++2fAhysro/Aom6210bv/xhmdLL9NvWHjH0JinFRgx9KsMLAegbgEew8
+Hz4f7H3syU4wwPp/GjzP2FOQd5RdADf72c+0vLcYmwn3+tkL2qi3Qvdp5VoOE/zsTQ2ew720vD/j
+Vnl7mG8B3JZkBz+kMFB8sF7TdHGBYFP/lEKzqsDQ9NunP0BZC8jhkF0mVl4BtPLvNvt77ECFfhoN
+cRasY69WVf2ZsWMPVG1lbL4KYzlYf9X0dxgxtYx15ehv0Lm+3clYNizjX75MghUG1vlGY6O9vxr/
+q68KFs6cDo5csfH2+dl+P+tVoY3RP8b//tNGdCFev2QfPFBFrbihqlLEXm/qo470sGa+F277CrsL
+rsPVv9Wy30s21RAYABUfrP+A85iJzE18ZUSS/H9hHP49Bx7Y+WATIyyqxb7/bYTk7+fA91jvR8je
+fRZGY3ygaM+3cbBahUNshQlo3EazXdVbT9DrL0EpWjObtFjhYP0JHCeE2/sOjMKlSgiOCFFK9wVf
+4m/+Tw3eRouFru9Nsli/EJgsh2sZ+wrkveV/hlsoxmF7OriXDfagg/olo0U0XkmoUVEcLDZYjuoq
+VLWDwPo4PBIgaAKdQ8SQvJOj4BbGPrBxb134FvsYt1hdWfC4scHPwP4Gt3dPvyhsXpvfQOqvoNP5
+vgpj0XgVLnAAOOgsj+fAwqrpUCxjLHBU8YYAAus7kG108Dg2vC6xqbfDOUN6sk+xF2z6sgd53PSE
+2HUVNWDXGDj3Q53bPGGZToXu9Q4bA1TGvZeM18DVGlYhry9YATWQBdpqrBc+L0IY2tuPoMO0QfHu
+XWSW/gPGYn/uZQ0M/l6wwSLGY8J8HS41D4CDhTHYN/hFo7EDALk7WpaDg8h7ir46SoQ68sAKCFur
+IkiOg8CKzB6FgLUe4EcijgcYi+A8KN6rogb0v4DRP2QbUdocvqHQUxpZL7sgKimwOsLnhvYFS21t
+QbUqkWCN7vNRJ6eA/izFbIep8uwhjNNP5kBh1e06YGBF9vUZJI5fEyfRpuW+EwYWGjO0TWXAwdJ/
+YnrB+0Hb0XKfpv9UgmU0BJbt7hUAAAvPSURBVAfr9gTB6mH3YVfQTxfs2N0tMyHnRBhYgrdfi23f
+tI06Yu613gGz/ATW7mTBosA9dJRK/BjrioAr/HEg2gro2BSw/zokjZAFm9mhMQ5wzLoCAys8WrwK
+ik+ZfUhhukLAIuwge7M2Dl2h6udeMZcds+m/YRTbTZZghcZYQVf4N97TiwFWD4ZScIuf+of2oxyj
+O4KukDfgnzQ0WGKn++BfTK7uEnsZrrCLwq2BclUWMayuv+D9XAqH9jGMnh6J5KoIcvaF5dyA0qgH
+WtrYKP13wrpeb/wax5AhnvEKBYsda209cQBmoVfkYB1AsA6I9w6AJsEKBetvGFmh/3qeneERVEyL
+tRx0Ho+vMs2UzQze74LPi3hdJKy4J/ylsTty9XjIqn/mDDh471SVaeGPkowP1n4bueHP2m/ZzoPw
+sPhqCow10J9TcgsPmvTfdXqf9NNSDv7FaP0b5hUxEwp1yPf7Q8HyNnq4Kfsa682B33CjeC6F9PQ9
+f8SQXoIVmm6YQhmdX6jFe3X4AYsJ1nrIEx2+JwR+y9FMYdeKTNwF8HsRwY4FnduDDwJ9P1z5U9OI
+kVn7Hy17gLeC2qgGY/cAwMIj1Vef6L0PIz5+U6eq2hsSIy6sRlVRj1HfwY4tQPd1yIbo49LX0Bzl
+QC69X+2hcEr/DfYMbw6zWN+F/CNsly33HT++n7+H4U/2DdaVQ51LXFwowQoD600NFu5hL4MOY6nR
+G6qrooCFG43lv3n7u7nwtVNsu07x1AIoPYHNRR7wXR1uRotAeR/yliLqfTPX2KsNwy7HDnZwSqBT
+n3DCXVGmRVSC7wcsdp8GqupA+5m/2R+ax3rfZnRZcPNetK+qCqOPUOxNS6V+sj+GqsgRLqLrwnCG
+Aiw/kqerDpVHaYtpEQr93EbS92knJFjht3RetuMPw2/E3HkkIr8QeLnA/M3bKIClrSkWOa7TIv+h
+MZo/RVc/XeL/CdmnTUcYuLuznpobxp0a0KFWRnvQUVbfJJcBliJuQr/+WJGiPdAyBfLeCM1jeRVT
+9GpXmZK/mTqxPTunKzOa6Jo6x3y/qmuMMprWzFFs7xn5DhFi3We33WkEorumK8U7uP099mQRLp4a
+6VyxacGGEMmhY9vLsm0Ln7/LQb6wPHzKXIV4+RHzN8de+sFVevaM53lO9dgG3XYnub/1ikJ5nKcU
+Bd3ig+ZHBPYib7R3fnb+5u6B3IRudSjRxgAnPGxm552Jf5c/ua3kWJlE9PpMS111vHJslEc8yIF+
+UoNQgwLoBqOVYpRgSSWtRipIDC1R35NgSSWn7lpR5zpG5VgJllQyaq0UPbOYTw+RYEkNWG314sE0
+1XHm7UmwpAYkX3MlUkUpBk/c8ukSLKmE1d5YaT7ur7q/h0hKsKT6V2erp7qiIJATr27t/0m+Eiyp
+aGrxNjd7GmurqyrLSxziOX9Clc2JPUdZgiUVTaBECFeU17Yk/nBuCZZUNBWEMFVQUe1paRvgY0kl
+WFJRXSEfFt3W3pHsY24lWFJpkQRLSoIlJcGSkmBJSUmwpCRYUhIsKak0g9Vab0zwqq3nQ057vQ1b
+m96OuuvL9XySoZ+1NG7b7RcTO7z1TebErdcbt/WtAHAwuPJg49am4LQA39Z62RgRqq8X2UmP0SYH
+Guu3RS+q8O5WsQW2RQNuwtuCWiV2U9TWG2o3WlDs5e/11jeeSAdYEfMKt9tpTqFaGuW7juXwSYb+
+Y9NVAIe2B49rfx5ubeNzvHuX22i/8FqiYmXhW+Yi2AKVMReb8+6lAnKAGEgnSs3sn0KzCtXRf4iy
+5QLRav69OpWDKj7Rw96fSa0yms95vs/GV4btEVIq0r+3iO91BFvwNWpB5fG0g/WyBouamh+zw8V9
+djw5EzhYvRdA/jbPdBj9Hk1MLW3aYHM820OgFDY9aaPqWSFaD7lbPTMh30+Tox2rmxeICfWMV0KU
+YMUF630dxm1tbiwC+9tnIjdcr4lWw20ubmoEGOdH1OybPUU0PxV/dftWXDw3bHaduAuoQd4+KpqF
+exXBuNO0iC2oOX6fbrCuAF71+GUtL6KSKNuZBwKs12xU1eGkDb7HvstrxPyWivy9puHJsf+dsSh0
+n+M2eBZJ/Bh87wz7GE2O7rIZ5R0O2SRY/YD1HbATGb1TqDJfmF6badYg/Y5qP2HU8RtFk+vf1ahg
+5Bh4iTO3L5qlQ+P0Pzaaa/+uLW8PewJoavEGXmQvrWBlGzVmmprbOOWBQpFesD+icrA6W71i82qE
+ZR1dNlRR9Me8tB93f3OU0afRrimj/X8FlVzji8TUOXyDLF40mfk+kvusBCs+WBVGISNvM9XkDJ0J
+rUDpjaLV2luahZtrYzq0MlGN9C/aqKN+ciE/YF15Ctqt9/lf0lNU25YdNveiGqQPMdbzF9uod9IM
+1q2Qu/lEyBkEAuzdq98KK0iKJucniOE6sdkP0dT98LEi28I96PePU6mAn4H+UmjZUVxRfITt0kQN
+m8Xw+AEJVhSwOoNg/QrgzmAEHlq7YeHz4aUcXgC0WAvgslOiEsh/CiKpGhYV9HuWikKKNv1wlB60
+Yi9Q1eSP8zJGH+bk/SENYBlDvHipyIPZ6KJmrDNOyNPcGuamg2D1ziS/fgUPqdArbkbzS1Xewf4c
+vy7053gditc0HlL9GHLxstgAdkXTnhMBVilrk2BFActsCsJmOjaFtszoSHubPaFbhoJ1vIjs0MkF
+oCowDsF5DLJp9SpeknEBZG/XzKJF60OK6Z2cQnvpyVf0GxhY7OAC6rw5tOei7BoEqxej8F9TKObY
+wU4uB/SK2aA/z3z3UUjPus7BjyhGJ9h7Dsw4wfbmIEPYl8TvUeFOvx+tXf5pCVa/YPVu4D05ZXWU
+EhchYCFXo45QTw93duAl7g+UiqSm/ruOH2E4wt4xwcJ9yNWofURUiwBrd7rTDeiBPbdnO0B9Lg5Y
+vpmgPm3UKcSzKcLTGWUaLyqrvV8Dx0uUJTmETClU8IhgW3SKvf4R3OzkmFw8pXYJVnxXSL+z97E8
+ozRRTLAO6ZCNsfoHOmz2U52xl9BiKUGLRUXW7EdEzvG3WraZDTpWJKp+ptVihYPFj2Hv+dH6CSZY
+vinC5VFfcboyY88V8N/oFY2C7xR1vaoB/Jp/0LFVDu2BV7QJ9PiAf/A4fhzaKsgm4wVKhWQpTh5L
+6PBiyDsRGyzkitfvNAKr5RhYhcRYIq+jG2DdBXeYNOZBDjdeIsb6IMk674mDdWDVFNE92AW2mGCh
+FdVCe7JdOXazV9ibRVVuu8ag+R0d7Ge8CnMpjqezfR00AstQpWQpNliPlf1cOLB4VZOP6/QgGhao
+wb0Kctifgr1CwxUaddXGmHYJvee4I0aamnqFf7LZ09wrxL7encYXxrZYiyHXeKbPX8vz3qFIazLF
+6WOPUoVu9Q1ebnKHqPf+lRL6Owc7kGixqMb4rTCZdXhI9eBo9kqWYoM1nUprM+pOx7FYRfBR4Sd/
+oelHeMD/eQLo14E8lgjeeWb9bwG7NF2Un2QskMc6L915rPsBCmsbn5wOKsVIEU8F52Cd2asZ4X41
+FRDN3/aY3f4Sz7xrW58cBbPQQFEW9Ble1f5F0Fc3zOePnVhMi7drjh8ZaWQZvPcD1ssOyFm3rWG5
+g9d5jKjoJ8A6Qw9fEBX9eqfg1g0XYBx/hjLv6xpE5v1n1CP8iqhua1RTZmeeMffyknOZsW2VI/2Z
+994N2fxeofZ8RB4raLG+ZDoyDKr2Z9P9Px5v9S7HqEmddYr6HsXcNo0+KlbaZ5GB66EbWJD9tPlh
+Eqz+YqxdOvUKHaJXGL0G6cxgDdJj/F5hDm+39XRfgyruoyO8mSfvP3oq8CgU8iDB24YH6bah8jRL
+PVhtnkax0OjhSavelmZPc1vYKlONnhb+1xC96PV6dpsjFl5vbqL9Xvd46Kazr8lDHY4DYiXpIG4b
+NOroECVJkRe5R/QKvUabHPB6ml45FbbKkPHSbApPB/+pPa8YHu5gcxMfvOD1eGj31zweDNNagi1t
+iM9GbfE0p2V0g5QUk2BJSbCkJFhSUoPW/wfr5tj8wgE+HwAAAABJRU5ErkJggg==
similarity index 99%
rename from Documentation/DocBook/v4l/common.xml
rename to Documentation/DocBook/media/v4l/common.xml
index 9028721..a86f7a0 100644 (file)
@@ -236,7 +236,15 @@ important parts of the API.</para>
     <para>The &VIDIOC-QUERYCAP; ioctl is available to check if the kernel
 device is compatible with this specification, and to query the <link
 linkend="devices">functions</link> and <link linkend="io">I/O
-methods</link> supported by the device. Other features can be queried
+methods</link> supported by the device.</para>
+
+    <para>Starting with kernel version 3.1, VIDIOC-QUERYCAP will return the
+V4L2 API version used by the driver, with generally matches the Kernel version.
+There's no need of using &VIDIOC-QUERYCAP; to check if an specific ioctl is
+supported, the V4L2 core now returns ENOIOCTLCMD if a driver doesn't provide
+support for an ioctl.</para>
+
+    <para>Other features can be queried
 by calling the respective ioctl, for example &VIDIOC-ENUMINPUT;
 to learn about the number, types and names of video connectors on the
 device. Although abstraction is a major objective of this API, the
similarity index 99%
rename from Documentation/DocBook/v4l/compat.xml
rename to Documentation/DocBook/media/v4l/compat.xml
index 9f7cd4f..ce1004a 100644 (file)
@@ -10,12 +10,10 @@ driver writers to port or update their code.</para>
     <para>The Video For Linux API was first introduced in Linux 2.1 to
 unify and replace various TV and radio device related interfaces,
 developed independently by driver writers in prior years. Starting
-with Linux 2.5 the much improved V4L2 API replaces the V4L API,
-although existing drivers will continue to support V4L applications in
-the future, either directly or through the V4L2 compatibility layer in
-the <filename>videodev</filename> kernel module translating ioctls on
-the fly. For a transition period not all drivers will support the V4L2
-API.</para>
+with Linux 2.5 the much improved V4L2 API replaces the V4L API.
+The support for the old V4L calls were removed from Kernel, but the
+library <xref linkend="libv4l" /> supports the conversion of a V4L
+API system call into a V4L2 one.</para>
 
     <section>
       <title>Opening and Closing Devices</title>
@@ -84,12 +82,7 @@ not compatible with V4L or V4L2.</para> </footnote>,
 device file. V4L2 drivers <emphasis>may</emphasis> support multiple
 opens, see <xref linkend="open" /> for details and consequences.</para>
 
-      <para>V4L drivers respond to V4L2 ioctls with an &EINVAL;. The
-compatibility layer in the V4L2 <filename>videodev</filename> module
-can translate V4L ioctl requests to their V4L2 counterpart, however a
-V4L2 driver usually needs more preparation to become fully V4L
-compatible. This is covered in more detail in <xref
-         linkend="driver" />.</para>
+      <para>V4L drivers respond to V4L2 ioctls with an &EINVAL;.</para>
     </section>
 
     <section>
@@ -2367,6 +2360,16 @@ that used it. It was originally scheduled for removal in 2.6.35.
         </listitem>
       </orderedlist>
     </section>
+    <section>
+      <title>V4L2 in Linux 3.1</title>
+      <orderedlist>
+        <listitem>
+         <para>VIDIOC_QUERYCAP now returns a per-subsystem version instead of a per-driver one.</para>
+         <para>Standardize an error code for invalid ioctl.</para>
+          <para>Added V4L2_CTRL_TYPE_BITMASK.</para>
+        </listitem>
+      </orderedlist>
+    </section>
 
     <section id="other">
       <title>Relation of V4L2 to other Linux multimedia APIs</title>
@@ -2472,6 +2475,9 @@ ioctls.</para>
         <listitem>
          <para>&VIDIOC-DBG-G-CHIP-IDENT; ioctl.</para>
         </listitem>
+        <listitem>
+         <para>Flash API. <xref linkend="flash-controls" /></para>
+        </listitem>
       </itemizedlist>
     </section>
 
similarity index 62%
rename from Documentation/DocBook/v4l/controls.xml
rename to Documentation/DocBook/media/v4l/controls.xml
index a920ee8..8516401 100644 (file)
@@ -51,6 +51,10 @@ readability until any ioctl (querying the properties) is
 called.</para>
       </footnote></para>
 
+    <para>
+      All controls use machine endianness.
+    </para>
+
     <table pgwide="1" frame="none" id="control-id">
       <title>Control IDs</title>
       <tgroup cols="3">
@@ -323,6 +327,22 @@ minimum value disables backlight compensation.</entry>
            <entry></entry>
            <entry>End of the predefined control IDs (currently
 <constant>V4L2_CID_ILLUMINATORS_2</constant> + 1).</entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_CID_MIN_BUFFERS_FOR_CAPTURE</constant></entry>
+           <entry>integer</entry>
+           <entry>This is a read-only control that can be read by the application
+and used as a hint to determine the number of CAPTURE buffers to pass to REQBUFS.
+The value is the minimum number of CAPTURE buffers that is necessary for hardware
+to work.</entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_CID_MIN_BUFFERS_FOR_OUTPUT</constant></entry>
+           <entry>integer</entry>
+           <entry>This is a read-only control that can be read by the application
+and used as a hint to determine the number of OUTPUT buffers to pass to REQBUFS.
+The value is the minimum number of OUTPUT buffers that is necessary for hardware
+to work.</entry>
          </row>
          <row>
            <entry><constant>V4L2_CID_PRIVATE_BASE</constant></entry>
@@ -545,6 +565,10 @@ may not be supported (<constant>VIDIOC_QUERYMENU</constant> will
 return an error). A good example is the list of supported MPEG audio
 bitrates. Some drivers only support one or two bitrates, others
 support a wider range.</para>
+
+      <para>
+       All controls use machine endianness.
+      </para>
     </section>
 
     <section>
@@ -670,7 +694,8 @@ caption of a Tab page in a GUI, for example.</entry>
              </row><row><entry spanname="descr">The MPEG-1, -2 or -4
 output stream type. One cannot assume anything here. Each hardware
 MPEG encoder tends to support different subsets of the available MPEG
-stream types. The currently defined stream types are:</entry>
+stream types. This control is specific to multiplexed MPEG streams.
+The currently defined stream types are:</entry>
              </row>
              <row>
                <entrytbl spanname="descr" cols="2">
@@ -800,6 +825,7 @@ frequency. Possible values are:</entry>
                <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_ENCODING</constant>&nbsp;</entry>
                <entry>enum&nbsp;v4l2_mpeg_audio_encoding</entry>
              </row><row><entry spanname="descr">MPEG Audio encoding.
+This control is specific to multiplexed MPEG streams.
 Possible values are:</entry>
              </row>
              <row>
@@ -1250,7 +1276,8 @@ and reproducible audio bitstream. 0 = unmuted, 1 = muted.</entry>
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_ENCODING</constant>&nbsp;</entry>
                <entry>enum&nbsp;v4l2_mpeg_video_encoding</entry>
              </row><row><entry spanname="descr">MPEG Video encoding
-method. Possible values are:</entry>
+method. This control is specific to multiplexed MPEG streams.
+Possible values are:</entry>
              </row>
              <row>
                <entrytbl spanname="descr" cols="2">
@@ -1406,225 +1433,1178 @@ of the video. The supplied 32-bit integer is interpreted as follows (bit
                  </tbody>
                </entrytbl>
              </row>
-           </tbody>
-         </tgroup>
-       </table>
-      </section>
 
-      <section>
-       <title>CX2341x MPEG Controls</title>
 
-       <para>The following MPEG class controls deal with MPEG
-encoding settings that are specific to the Conexant CX23415 and
-CX23416 MPEG encoding chips.</para>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">If enabled the decoder expects to receive a single slice per buffer, otherwise
+the decoder expects a single frame in per buffer. Applicable to the decoder, all codecs.
+</entry>
+             </row>
 
-       <table pgwide="1" frame="none" id="cx2341x-control-id">
-         <title>CX2341x Control IDs</title>
-         <tgroup cols="4">
-           <colspec colname="c1" colwidth="1*" />
-           <colspec colname="c2" colwidth="6*" />
-           <colspec colname="c3" colwidth="2*" />
-           <colspec colname="c4" colwidth="6*" />
-           <spanspec namest="c1" nameend="c2" spanname="id" />
-           <spanspec namest="c2" nameend="c4" spanname="descr" />
-           <thead>
+             <row><entry></entry></row>
              <row>
-               <entry spanname="id" align="left">ID</entry>
-               <entry align="left">Type</entry>
-             </row><row><entry spanname="descr" align="left">Description</entry>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE</constant>&nbsp;</entry>
+               <entry>boolean</entry>
              </row>
-           </thead>
-           <tbody valign="top">
+             <row><entry spanname="descr">Enable writing sample aspect ratio in the Video Usability Information.
+Applicable to the H264 encoder.</entry>
+             </row>
+
              <row><entry></entry></row>
-             <row id="v4l2-mpeg-cx2341x-video-spatial-filter-mode">
-               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_cx2341x_video_spatial_filter_mode</entry>
-             </row><row><entry spanname="descr">Sets the Spatial
-Filter mode (default <constant>MANUAL</constant>). Possible values
-are:</entry>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_vui_sar_idc</entry>
+             </row>
+             <row><entry spanname="descr">VUI sample aspect ratio indicator for H.264 encoding. The value
+is defined in the table E-1 in the standard. Applicable to the H264 encoder.</entry>
              </row>
              <row>
                <entrytbl spanname="descr" cols="2">
                  <tbody valign="top">
-                   <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL</constant>&nbsp;</entry>
-                     <entry>Choose the filter manually</entry>
-                   </row>
-                   <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO</constant>&nbsp;</entry>
-                     <entry>Choose the filter automatically</entry>
-                   </row>
+
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED</constant>&nbsp;</entry>
+                         <entry>Unspecified</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1</constant>&nbsp;</entry>
+                         <entry>1x1</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_12x11</constant>&nbsp;</entry>
+                         <entry>12x11</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_10x11</constant>&nbsp;</entry>
+                         <entry>10x11</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_16x11</constant>&nbsp;</entry>
+                         <entry>16x11</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_40x33</constant>&nbsp;</entry>
+                         <entry>40x33</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_24x11</constant>&nbsp;</entry>
+                         <entry>24x11</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_20x11</constant>&nbsp;</entry>
+                         <entry>20x11</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_32x11</constant>&nbsp;</entry>
+                         <entry>32x11</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_80x33</constant>&nbsp;</entry>
+                         <entry>80x33</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_18x11</constant>&nbsp;</entry>
+                         <entry>18x11</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_15x11</constant>&nbsp;</entry>
+                         <entry>15x11</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_64x33</constant>&nbsp;</entry>
+                         <entry>64x33</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_160x99</constant>&nbsp;</entry>
+                         <entry>160x99</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_4x3</constant>&nbsp;</entry>
+                         <entry>4x3</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_3x2</constant>&nbsp;</entry>
+                         <entry>3x2</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1</constant>&nbsp;</entry>
+                         <entry>2x1</entry>
+                       </row>
+                       <row>
+                         <entry><constant>V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED</constant>&nbsp;</entry>
+                         <entry>Extended SAR</entry>
+                       </row>
                  </tbody>
                </entrytbl>
              </row>
+
              <row><entry></entry></row>
              <row>
-               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER</constant>&nbsp;</entry>
-               <entry>integer&nbsp;(0-15)</entry>
-             </row><row><entry spanname="descr">The setting for the
-Spatial Filter. 0 = off, 15 = maximum. (Default is 0.)</entry>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH</constant>&nbsp;</entry>
+               <entry>integer</entry>
              </row>
+             <row><entry spanname="descr">Extended sample aspect ratio width for H.264 VUI encoding.
+Applicable to the H264 encoder.</entry>
+             </row>
+
              <row><entry></entry></row>
-             <row id="luma-spatial-filter-type">
-               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_cx2341x_video_luma_spatial_filter_type</entry>
-             </row><row><entry spanname="descr">Select the algorithm
-to use for the Luma Spatial Filter (default
-<constant>1D_HOR</constant>). Possible values:</entry>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Extended sample aspect ratio height for H.264 VUI encoding.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_LEVEL</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_level</entry>
+             </row>
+             <row><entry spanname="descr">The level information for the H264 video elementary stream.
+Applicable to the H264 encoder.
+Possible values are:</entry>
              </row>
              <row>
                <entrytbl spanname="descr" cols="2">
                  <tbody valign="top">
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF</constant>&nbsp;</entry>
-                     <entry>No filter</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_1_0</constant>&nbsp;</entry>
+                     <entry>Level 1.0</entry>
                    </row>
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR</constant>&nbsp;</entry>
-                     <entry>One-dimensional horizontal</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_1B</constant>&nbsp;</entry>
+                     <entry>Level 1B</entry>
                    </row>
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT</constant>&nbsp;</entry>
-                     <entry>One-dimensional vertical</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_1_1</constant>&nbsp;</entry>
+                     <entry>Level 1.1</entry>
                    </row>
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE</constant>&nbsp;</entry>
-                     <entry>Two-dimensional separable</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_1_2</constant>&nbsp;</entry>
+                     <entry>Level 1.2</entry>
                    </row>
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE</constant>&nbsp;</entry>
-                     <entry>Two-dimensional symmetrical
-non-separable</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_1_3</constant>&nbsp;</entry>
+                     <entry>Level 1.3</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_2_0</constant>&nbsp;</entry>
+                     <entry>Level 2.0</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_2_1</constant>&nbsp;</entry>
+                     <entry>Level 2.1</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_2_2</constant>&nbsp;</entry>
+                     <entry>Level 2.2</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_3_0</constant>&nbsp;</entry>
+                     <entry>Level 3.0</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_3_1</constant>&nbsp;</entry>
+                     <entry>Level 3.1</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_3_2</constant>&nbsp;</entry>
+                     <entry>Level 3.2</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_4_0</constant>&nbsp;</entry>
+                     <entry>Level 4.0</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_4_1</constant>&nbsp;</entry>
+                     <entry>Level 4.1</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_4_2</constant>&nbsp;</entry>
+                     <entry>Level 4.2</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_5_0</constant>&nbsp;</entry>
+                     <entry>Level 5.0</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_5_1</constant>&nbsp;</entry>
+                     <entry>Level 5.1</entry>
                    </row>
                  </tbody>
                </entrytbl>
              </row>
+
              <row><entry></entry></row>
-             <row id="chroma-spatial-filter-type">
-               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type</entry>
-             </row><row><entry spanname="descr">Select the algorithm
-for the Chroma Spatial Filter (default <constant>1D_HOR</constant>).
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_mpeg4_level</entry>
+             </row>
+             <row><entry spanname="descr">The level information for the MPEG4 elementary stream.
+Applicable to the MPEG4 encoder.
 Possible values are:</entry>
              </row>
              <row>
                <entrytbl spanname="descr" cols="2">
                  <tbody valign="top">
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF</constant>&nbsp;</entry>
-                     <entry>No filter</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_LEVEL_0</constant>&nbsp;</entry>
+                     <entry>Level 0</entry>
                    </row>
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR</constant>&nbsp;</entry>
-                     <entry>One-dimensional horizontal</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_LEVEL_0B</constant>&nbsp;</entry>
+                     <entry>Level 0b</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_LEVEL_1</constant>&nbsp;</entry>
+                     <entry>Level 1</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_LEVEL_2</constant>&nbsp;</entry>
+                     <entry>Level 2</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_LEVEL_3</constant>&nbsp;</entry>
+                     <entry>Level 3</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_LEVEL_3B</constant>&nbsp;</entry>
+                     <entry>Level 3b</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_LEVEL_4</constant>&nbsp;</entry>
+                     <entry>Level 4</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_LEVEL_5</constant>&nbsp;</entry>
+                     <entry>Level 5</entry>
                    </row>
                  </tbody>
                </entrytbl>
              </row>
+
              <row><entry></entry></row>
-             <row id="v4l2-mpeg-cx2341x-video-temporal-filter-mode">
-               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_cx2341x_video_temporal_filter_mode</entry>
-             </row><row><entry spanname="descr">Sets the Temporal
-Filter mode (default <constant>MANUAL</constant>). Possible values
-are:</entry>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_PROFILE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_h264_profile</entry>
+             </row>
+             <row><entry spanname="descr">The profile information for H264.
+Applicable to the H264 encoder.
+Possible values are:</entry>
              </row>
              <row>
                <entrytbl spanname="descr" cols="2">
                  <tbody valign="top">
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL</constant>&nbsp;</entry>
-                     <entry>Choose the filter manually</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE</constant>&nbsp;</entry>
+                     <entry>Baseline profile</entry>
                    </row>
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO</constant>&nbsp;</entry>
-                     <entry>Choose the filter automatically</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE</constant>&nbsp;</entry>
+                     <entry>Constrained Baseline profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_MAIN</constant>&nbsp;</entry>
+                     <entry>Main profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED</constant>&nbsp;</entry>
+                     <entry>Extended profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_HIGH</constant>&nbsp;</entry>
+                     <entry>High profile</entry>
                    </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10</constant>&nbsp;</entry>
+                     <entry>High 10 profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422</constant>&nbsp;</entry>
+                     <entry>High 422 profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE</constant>&nbsp;</entry>
+                     <entry>High 444 Predictive profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA</constant>&nbsp;</entry>
+                     <entry>High 10 Intra profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA</constant>&nbsp;</entry>
+                     <entry>High 422 Intra profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA</constant>&nbsp;</entry>
+                     <entry>High 444 Intra profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA</constant>&nbsp;</entry>
+                     <entry>CAVLC 444 Intra profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE</constant>&nbsp;</entry>
+                     <entry>Scalable Baseline profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH</constant>&nbsp;</entry>
+                     <entry>Scalable High profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA</constant>&nbsp;</entry>
+                     <entry>Scalable High Intra profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH</constant>&nbsp;</entry>
+                     <entry>Stereo High profile</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH</constant>&nbsp;</entry>
+                     <entry>Multiview High profile</entry>
+                   </row>
+
                  </tbody>
                </entrytbl>
              </row>
+
              <row><entry></entry></row>
              <row>
-               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER</constant>&nbsp;</entry>
-               <entry>integer&nbsp;(0-31)</entry>
-             </row><row><entry spanname="descr">The setting for the
-Temporal Filter. 0 = off, 31 = maximum. (Default is 8 for full-scale
-capturing and 0 for scaled capturing.)</entry>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_mpeg4_profile</entry>
              </row>
-             <row><entry></entry></row>
-             <row id="v4l2-mpeg-cx2341x-video-median-filter-type">
-               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_cx2341x_video_median_filter_type</entry>
-             </row><row><entry spanname="descr">Median Filter Type
-(default <constant>OFF</constant>). Possible values are:</entry>
+             <row><entry spanname="descr">The profile information for MPEG4.
+Applicable to the MPEG4 encoder.
+Possible values are:</entry>
              </row>
              <row>
                <entrytbl spanname="descr" cols="2">
                  <tbody valign="top">
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF</constant>&nbsp;</entry>
-                     <entry>No filter</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_PROFILE_SIMPLE</constant>&nbsp;</entry>
+                     <entry>Simple profile</entry>
                    </row>
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR</constant>&nbsp;</entry>
-                     <entry>Horizontal filter</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_PROFILE_ADVANCED_SIMPLE</constant>&nbsp;</entry>
+                     <entry>Advanced Simple profile</entry>
                    </row>
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT</constant>&nbsp;</entry>
-                     <entry>Vertical filter</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_PROFILE_CORE</constant>&nbsp;</entry>
+                     <entry>Core profile</entry>
                    </row>
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT</constant>&nbsp;</entry>
-                     <entry>Horizontal and vertical filter</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_PROFILE_SIMPLE_SCALABLE</constant>&nbsp;</entry>
+                     <entry>Simple Scalable profile</entry>
                    </row>
                    <row>
-                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG</constant>&nbsp;</entry>
-                     <entry>Diagonal filter</entry>
+                     <entry><constant>V4L2_MPEG_VIDEO_PROFILE_ADVANCED_CODING_EFFICIENCY</constant>&nbsp;</entry>
+                     <entry></entry>
                    </row>
                  </tbody>
                </entrytbl>
              </row>
+
              <row><entry></entry></row>
              <row>
-               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM</constant>&nbsp;</entry>
-               <entry>integer&nbsp;(0-255)</entry>
-             </row><row><entry spanname="descr">Threshold above which
-the luminance median filter is enabled (default 0)</entry>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MAX_REF_PIC</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">The maximum number of reference pictures used for encoding.
+Applicable to the encoder.
+</entry>
              </row>
+
              <row><entry></entry></row>
              <row>
-               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP</constant>&nbsp;</entry>
-               <entry>integer&nbsp;(0-255)</entry>
-             </row><row><entry spanname="descr">Threshold below which
-the luminance median filter is enabled (default 255)</entry>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_multi_slice_mode</entry>
+             </row>
+             <row><entry spanname="descr">Determines how the encoder should handle division of frame into slices.
+Applicable to the encoder.
+Possible values are:</entry>
              </row>
-             <row><entry></entry></row>
              <row>
-               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM</constant>&nbsp;</entry>
-               <entry>integer&nbsp;(0-255)</entry>
-             </row><row><entry spanname="descr">Threshold above which
-the chroma median filter is enabled (default 0)</entry>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE</constant>&nbsp;</entry>
+                     <entry>Single slice per frame.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB</constant>&nbsp;</entry>
+                     <entry>Multiple slices with set maximum number of macroblocks per slice.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES</constant>&nbsp;</entry>
+                     <entry>Multiple slice with set maximum size in bytes per slice.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
              </row>
+
              <row><entry></entry></row>
              <row>
-               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP</constant>&nbsp;</entry>
-               <entry>integer&nbsp;(0-255)</entry>
-             </row><row><entry spanname="descr">Threshold below which
-the chroma median filter is enabled (default 255)</entry>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB</constant>&nbsp;</entry>
+               <entry>integer</entry>
              </row>
+             <row><entry spanname="descr">The maximum number of macroblocks in a slice. Used when
+<constant>V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE</constant> is set to <constant>V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB</constant>.
+Applicable to the encoder.</entry>
+             </row>
+
              <row><entry></entry></row>
              <row>
-               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS</constant>&nbsp;</entry>
-               <entry>boolean</entry>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES</constant>&nbsp;</entry>
+               <entry>integer</entry>
              </row>
-             <row><entry spanname="descr">The CX2341X MPEG encoder
-can insert one empty MPEG-2 PES packet into the stream between every
-four video frames. The packet size is 2048 bytes, including the
-packet_start_code_prefix and stream_id fields. The stream_id is 0xBF
-(private stream 2). The payload consists of 0x00 bytes, to be filled
-in by the application. 0 = do not insert, 1 = insert packets.</entry>
+             <row><entry spanname="descr">The maximum size of a slice in bytes. Used when
+<constant>V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE</constant> is set to <constant>V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES</constant>.
+Applicable to the encoder.</entry>
              </row>
-           </tbody>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_h264_loop_filter_mode</entry>
+             </row>
+             <row><entry spanname="descr">Loop filter mode for H264 encoder.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED</constant>&nbsp;</entry>
+                     <entry>Loop filter is enabled.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED</constant>&nbsp;</entry>
+                     <entry>Loop filter is disabled.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY</constant>&nbsp;</entry>
+                     <entry>Loop filter is disabled at the slice boundary.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Loop filter alpha coefficient, defined in the H264 standard.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Loop filter beta coefficient, defined in the H264 standard.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_h264_symbol_mode</entry>
+             </row>
+             <row><entry spanname="descr">Entropy coding mode for H264 - CABAC/CAVALC.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC</constant>&nbsp;</entry>
+                     <entry>Use CAVLC entropy coding.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC</constant>&nbsp;</entry>
+                     <entry>Use CABAC entropy coding.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Enable 8X8 transform for H264. Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Cyclic intra macroblock refresh. This is the number of continuous macroblocks
+refreshed every frame. Each frame a succesive set of macroblocks is refreshed until the cycle completes and starts from the
+top of the frame. Applicable to H264, H263 and MPEG4 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Frame level rate control enable.
+If this control is disabled then the quantization parameter for each frame type is constant and set with appropriate controls
+(e.g. <constant>V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP</constant>).
+If frame rate control is enabled then quantization parameter is adjusted to meet the chosen bitrate. Minimum and maximum value
+for the quantization parameter can be set with appropriate controls (e.g. <constant>V4L2_CID_MPEG_VIDEO_H263_MIN_QP</constant>).
+Applicable to encoders.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Macroblock level rate control enable.
+Applicable to the MPEG4 and H264 encoders.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_QPEL</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Quarter pixel motion estimation for MPEG4. Applicable to the MPEG4 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Quantization parameter for an I frame for H263. Valid range: from 1 to 31.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H263_MIN_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Minimum quantization parameter for H263. Valid range: from 1 to 31.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H263_MAX_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Maximum quantization parameter for H263. Valid range: from 1 to 31.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Quantization parameter for an P frame for H263. Valid range: from 1 to 31.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Quantization parameter for an B frame for H263. Valid range: from 1 to 31.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Quantization parameter for an I frame for H264. Valid range: from 0 to 51.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_MIN_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Minimum quantization parameter for H264. Valid range: from 0 to 51.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_MAX_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Maximum quantization parameter for H264. Valid range: from 0 to 51.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Quantization parameter for an P frame for H264. Valid range: from 0 to 51.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Quantization parameter for an B frame for H264. Valid range: from 0 to 51.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Quantization parameter for an I frame for MPEG4. Valid range: from 1 to 31.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Minimum quantization parameter for MPEG4. Valid range: from 1 to 31.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Maximum quantization parameter for MPEG4. Valid range: from 1 to 31.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Quantization parameter for an P frame for MPEG4. Valid range: from 1 to 31.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Quantization parameter for an B frame for MPEG4. Valid range: from 1 to 31.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VBV_SIZE</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">The Video Buffer Verifier size in kilobytes, it is used as a limitation of frame skip.
+The VBV is defined in the standard as a mean to verify that the produced stream will be succesfully decoded.
+The standard describes it as "Part of a hypothetical decoder that is conceptually connected to the
+output of the encoder. Its purpose is to provide a constraint on the variability of the data rate that an
+encoder or editing process may produce.".
+Applicable to the MPEG1, MPEG2, MPEG4 encoders.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">The Coded Picture Buffer size in kilobytes, it is used as a limitation of frame skip.
+The CPB is defined in the H264 standard as a mean to verify that the produced stream will be succesfully decoded.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_I_PERIOD</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Period between I-frames in the open GOP for H264. In case of an open GOP
+this is the period between two I-frames. The period between IDR (Instantaneous Decoding Refresh) frames is taken from the GOP_SIZE control.
+An IDR frame, which stands for Instantaneous Decoding Refresh is an I-frame after which no prior frames are
+referenced. This means that a stream can be restarted from an IDR frame without the need to store or decode any
+previous frames. Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_HEADER_MODE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_header_mode</entry>
+             </row>
+             <row><entry spanname="descr">Determines whether the header is returned as the first buffer or is
+it returned together with the first frame. Applicable to encoders.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE</constant>&nbsp;</entry>
+                     <entry>The stream header is returned separately in the first buffer.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME</constant>&nbsp;</entry>
+                     <entry>The stream header is returned together with the first encoded frame.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row><row><entry spanname="descr">Enabled the deblocking post processing filter for MPEG4 decoder.
+Applicable to the MPEG4 decoder.</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_VOP_TIME_RES</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">vop_time_increment_resolution value for MPEG4. Applicable to the MPEG4 encoder.</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_VOP_TIME_INC</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">vop_time_increment value for MPEG4. Applicable to the MPEG4 encoder.</entry>
+             </row>
+
+           </tbody>
+         </tgroup>
+       </table>
+      </section>
+
+      <section>
+       <title>MFC 5.1 MPEG Controls</title>
+
+       <para>The following MPEG class controls deal with MPEG
+decoding and encoding settings that are specific to the Multi Format Codec 5.1 device present
+in the S5P family of SoCs by Samsung.
+</para>
+
+       <table pgwide="1" frame="none" id="mfc51-control-id">
+         <title>MFC 5.1 Control IDs</title>
+         <tgroup cols="4">
+           <colspec colname="c1" colwidth="1*" />
+           <colspec colname="c2" colwidth="6*" />
+           <colspec colname="c3" colwidth="2*" />
+           <colspec colname="c4" colwidth="6*" />
+           <spanspec namest="c1" nameend="c2" spanname="id" />
+           <spanspec namest="c2" nameend="c4" spanname="descr" />
+           <thead>
+             <row>
+               <entry spanname="id" align="left">ID</entry>
+               <entry align="left">Type</entry>
+             </row><row><entry spanname="descr" align="left">Description</entry>
+             </row>
+           </thead>
+           <tbody valign="top">
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">If the display delay is enabled then the decoder has to return a
+CAPTURE buffer after processing a certain number of OUTPUT buffers. If this number is low, then it may result in
+buffers not being dequeued in display order. In addition hardware may still use those buffers as reference, thus
+application should not write to those buffers. This feature can be used for example for generating thumbnails of videos.
+Applicable to the H264 decoder.
+             </entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">Display delay value for H264 decoder.
+The decoder is forced to return a decoded frame after the set 'display delay' number of frames. If this number is
+low it may result in frames returned out of dispaly order, in addition the hardware may still be using the returned buffer
+as a reference picture for subsequent frames.
+</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">The number of reference pictures used for encoding a P picture.
+Applicable to the H264 encoder.</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_PADDING</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row><row><entry spanname="descr">Padding enable in the encoder - use a color instead of repeating border pixels.
+Applicable to encoders.</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">Padding color in the encoder. Applicable to encoders. The supplied 32-bit integer is interpreted as follows (bit
+0 = least significant bit):</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry>Bit 0:7</entry>
+                     <entry>V chrominance information</entry>
+                   </row>
+                   <row>
+                     <entry>Bit 8:15</entry>
+                     <entry>U chrominance information</entry>
+                   </row>
+                   <row>
+                     <entry>Bit 16:23</entry>
+                     <entry>Y luminance information</entry>
+                   </row>
+                   <row>
+                     <entry>Bit 24:31</entry>
+                     <entry>Must be zero.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">Reaction coefficient for MFC rate control. Applicable to encoders.
+<para>Note 1: Valid only when the frame level RC is enabled.</para>
+<para>Note 2: For tight CBR, this field must be small (ex. 2 ~ 10).
+For VBR, this field must be large (ex. 100 ~ 1000).</para>
+<para>Note 3: It is not recommended to use the greater number than FRAME_RATE * (10^9 / BIT_RATE).</para>
+</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row><row><entry spanname="descr">Adaptive rate control for dark region.
+Valid only when H.264 and macroblock level RC is enabled (<constant>V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE</constant>).
+Applicable to the H264 encoder.</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row><row><entry spanname="descr">Adaptive rate control for smooth region.
+Valid only when H.264 and macroblock level RC is enabled (<constant>V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE</constant>).
+Applicable to the H264 encoder.</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row><row><entry spanname="descr">Adaptive rate control for static region.
+Valid only when H.264 and macroblock level RC is enabled (<constant>V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE</constant>).
+Applicable to the H264 encoder.</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row><row><entry spanname="descr">Adaptive rate control for activity region.
+Valid only when H.264 and macroblock level RC is enabled (<constant>V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE</constant>).
+Applicable to the H264 encoder.</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_mfc51_frame_skip_mode</entry>
+             </row>
+             <row><entry spanname="descr">
+Indicates in what conditions the encoder should skip frames. If encoding a frame would cause the encoded stream to be larger then
+a chosen data limit then the frame will be skipped.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_MFC51_FRAME_SKIP_MODE_DISABLED</constant>&nbsp;</entry>
+                     <entry>Frame skip mode is disabled.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_MFC51_FRAME_SKIP_MODE_LEVEL_LIMIT</constant>&nbsp;</entry>
+                     <entry>Frame skip mode enabled and buffer limit is set by the chosen level and is defined by the standard.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_MFC51_FRAME_SKIP_MODE_BUF_LIMIT</constant>&nbsp;</entry>
+                     <entry>Frame skip mode enabled and buffer limit is set by the VBV (MPEG1/2/4) or CPB (H264) buffer size control.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">Enable rate-control with fixed target bit.
+If this setting is enabled, then the rate control logic of the encoder will calculate the average bitrate
+for a GOP and keep it below or equal the set bitrate target. Otherwise the rate control logic calculates the
+overall average bitrate for the stream and keeps it below or equal to the set bitrate. In the first case
+the average bitrate for the whole stream will be smaller then the set bitrate. This is caused because the
+average is calculated for smaller number of frames, on the other hand enabling this setting will ensure that
+the stream will meet tight bandwidth contraints. Applicable to encoders.
+</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_mfc51_force_frame_type</entry>
+             </row>
+             <row><entry spanname="descr">Force a frame type for the next queued buffer. Applicable to encoders.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_MFC51_FORCE_FRAME_TYPE_DISABLED</constant>&nbsp;</entry>
+                     <entry>Forcing a specific frame type disabled.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_MFC51_FORCE_FRAME_TYPE_I_FRAME</constant>&nbsp;</entry>
+                     <entry>Force an I-frame.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_MFC51_FORCE_FRAME_TYPE_NOT_CODED</constant>&nbsp;</entry>
+                     <entry>Force a non-coded frame.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+           </tbody>
+         </tgroup>
+       </table>
+      </section>
+
+      <section>
+       <title>CX2341x MPEG Controls</title>
+
+       <para>The following MPEG class controls deal with MPEG
+encoding settings that are specific to the Conexant CX23415 and
+CX23416 MPEG encoding chips.</para>
+
+       <table pgwide="1" frame="none" id="cx2341x-control-id">
+         <title>CX2341x Control IDs</title>
+         <tgroup cols="4">
+           <colspec colname="c1" colwidth="1*" />
+           <colspec colname="c2" colwidth="6*" />
+           <colspec colname="c3" colwidth="2*" />
+           <colspec colname="c4" colwidth="6*" />
+           <spanspec namest="c1" nameend="c2" spanname="id" />
+           <spanspec namest="c2" nameend="c4" spanname="descr" />
+           <thead>
+             <row>
+               <entry spanname="id" align="left">ID</entry>
+               <entry align="left">Type</entry>
+             </row><row><entry spanname="descr" align="left">Description</entry>
+             </row>
+           </thead>
+           <tbody valign="top">
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-cx2341x-video-spatial-filter-mode">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_cx2341x_video_spatial_filter_mode</entry>
+             </row><row><entry spanname="descr">Sets the Spatial
+Filter mode (default <constant>MANUAL</constant>). Possible values
+are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL</constant>&nbsp;</entry>
+                     <entry>Choose the filter manually</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO</constant>&nbsp;</entry>
+                     <entry>Choose the filter automatically</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER</constant>&nbsp;</entry>
+               <entry>integer&nbsp;(0-15)</entry>
+             </row><row><entry spanname="descr">The setting for the
+Spatial Filter. 0 = off, 15 = maximum. (Default is 0.)</entry>
+             </row>
+             <row><entry></entry></row>
+             <row id="luma-spatial-filter-type">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_cx2341x_video_luma_spatial_filter_type</entry>
+             </row><row><entry spanname="descr">Select the algorithm
+to use for the Luma Spatial Filter (default
+<constant>1D_HOR</constant>). Possible values:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF</constant>&nbsp;</entry>
+                     <entry>No filter</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR</constant>&nbsp;</entry>
+                     <entry>One-dimensional horizontal</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT</constant>&nbsp;</entry>
+                     <entry>One-dimensional vertical</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE</constant>&nbsp;</entry>
+                     <entry>Two-dimensional separable</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE</constant>&nbsp;</entry>
+                     <entry>Two-dimensional symmetrical
+non-separable</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+             <row><entry></entry></row>
+             <row id="chroma-spatial-filter-type">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type</entry>
+             </row><row><entry spanname="descr">Select the algorithm
+for the Chroma Spatial Filter (default <constant>1D_HOR</constant>).
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF</constant>&nbsp;</entry>
+                     <entry>No filter</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR</constant>&nbsp;</entry>
+                     <entry>One-dimensional horizontal</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-cx2341x-video-temporal-filter-mode">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_cx2341x_video_temporal_filter_mode</entry>
+             </row><row><entry spanname="descr">Sets the Temporal
+Filter mode (default <constant>MANUAL</constant>). Possible values
+are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL</constant>&nbsp;</entry>
+                     <entry>Choose the filter manually</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO</constant>&nbsp;</entry>
+                     <entry>Choose the filter automatically</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER</constant>&nbsp;</entry>
+               <entry>integer&nbsp;(0-31)</entry>
+             </row><row><entry spanname="descr">The setting for the
+Temporal Filter. 0 = off, 31 = maximum. (Default is 8 for full-scale
+capturing and 0 for scaled capturing.)</entry>
+             </row>
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-cx2341x-video-median-filter-type">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_cx2341x_video_median_filter_type</entry>
+             </row><row><entry spanname="descr">Median Filter Type
+(default <constant>OFF</constant>). Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF</constant>&nbsp;</entry>
+                     <entry>No filter</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR</constant>&nbsp;</entry>
+                     <entry>Horizontal filter</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT</constant>&nbsp;</entry>
+                     <entry>Vertical filter</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT</constant>&nbsp;</entry>
+                     <entry>Horizontal and vertical filter</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG</constant>&nbsp;</entry>
+                     <entry>Diagonal filter</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM</constant>&nbsp;</entry>
+               <entry>integer&nbsp;(0-255)</entry>
+             </row><row><entry spanname="descr">Threshold above which
+the luminance median filter is enabled (default 0)</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP</constant>&nbsp;</entry>
+               <entry>integer&nbsp;(0-255)</entry>
+             </row><row><entry spanname="descr">Threshold below which
+the luminance median filter is enabled (default 255)</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM</constant>&nbsp;</entry>
+               <entry>integer&nbsp;(0-255)</entry>
+             </row><row><entry spanname="descr">Threshold above which
+the chroma median filter is enabled (default 0)</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP</constant>&nbsp;</entry>
+               <entry>integer&nbsp;(0-255)</entry>
+             </row><row><entry spanname="descr">Threshold below which
+the chroma median filter is enabled (default 255)</entry>
+             </row>
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">The CX2341X MPEG encoder
+can insert one empty MPEG-2 PES packet into the stream between every
+four video frames. The packet size is 2048 bytes, including the
+packet_start_code_prefix and stream_id fields. The stream_id is 0xBF
+(private stream 2). The payload consists of 0x00 bytes, to be filled
+in by the application. 0 = do not insert, 1 = insert packets.</entry>
+             </row>
+           </tbody>
          </tgroup>
        </table>
       </section>
@@ -2092,6 +3072,289 @@ manually or automatically if set to zero. Unit, range and step are driver-specif
 <para>For more details about RDS specification, refer to
 <xref linkend="en50067" /> document, from CENELEC.</para>
     </section>
+
+    <section id="flash-controls">
+      <title>Flash Control Reference</title>
+
+      <note>
+       <title>Experimental</title>
+
+       <para>This is an <link linkend="experimental">experimental</link>
+interface and may change in the future.</para>
+      </note>
+
+      <para>
+       The V4L2 flash controls are intended to provide generic access
+       to flash controller devices. Flash controller devices are
+       typically used in digital cameras.
+      </para>
+
+      <para>
+       The interface can support both LED and xenon flash devices. As
+       of writing this, there is no xenon flash driver using this
+       interface.
+      </para>
+
+      <section id="flash-controls-use-cases">
+       <title>Supported use cases</title>
+
+       <section>
+         <title>Unsynchronised LED flash (software strobe)</title>
+
+         <para>
+           Unsynchronised LED flash is controlled directly by the
+           host as the sensor. The flash must be enabled by the host
+           before the exposure of the image starts and disabled once
+           it ends. The host is fully responsible for the timing of
+           the flash.
+         </para>
+
+         <para>Example of such device: Nokia N900.</para>
+       </section>
+
+       <section>
+         <title>Synchronised LED flash (hardware strobe)</title>
+
+         <para>
+           The synchronised LED flash is pre-programmed by the host
+           (power and timeout) but controlled by the sensor through a
+           strobe signal from the sensor to the flash.
+         </para>
+
+         <para>
+           The sensor controls the flash duration and timing. This
+           information typically must be made available to the
+           sensor.
+         </para>
+
+       </section>
+
+       <section>
+         <title>LED flash as torch</title>
+
+         <para>
+           LED flash may be used as torch in conjunction with another
+           use case involving camera or individually.
+         </para>
+
+       </section>
+
+      </section>
+
+      <table pgwide="1" frame="none" id="flash-control-id">
+      <title>Flash Control IDs</title>
+
+      <tgroup cols="4">
+       <colspec colname="c1" colwidth="1*" />
+       <colspec colname="c2" colwidth="6*" />
+       <colspec colname="c3" colwidth="2*" />
+       <colspec colname="c4" colwidth="6*" />
+       <spanspec namest="c1" nameend="c2" spanname="id" />
+       <spanspec namest="c2" nameend="c4" spanname="descr" />
+       <thead>
+         <row>
+           <entry spanname="id" align="left">ID</entry>
+           <entry align="left">Type</entry>
+         </row><row rowsep="1"><entry spanname="descr" align="left">Description</entry>
+         </row>
+       </thead>
+       <tbody valign="top">
+         <row><entry></entry></row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_CLASS</constant></entry>
+           <entry>class</entry>
+         </row>
+         <row>
+           <entry spanname="descr">The FLASH class descriptor.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_LED_MODE</constant></entry>
+           <entry>menu</entry>
+         </row>
+         <row id="v4l2-flash-led-mode">
+           <entry spanname="descr">Defines the mode of the flash LED,
+           the high-power white LED attached to the flash controller.
+           Setting this control may not be possible in presence of
+           some faults. See V4L2_CID_FLASH_FAULT.</entry>
+         </row>
+         <row>
+           <entrytbl spanname="descr" cols="2">
+             <tbody valign="top">
+               <row>
+                 <entry><constant>V4L2_FLASH_LED_MODE_NONE</constant></entry>
+                 <entry>Off.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_LED_MODE_FLASH</constant></entry>
+                 <entry>Flash mode.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_LED_MODE_TORCH</constant></entry>
+                 <entry>Torch mode. See V4L2_CID_FLASH_TORCH_INTENSITY.</entry>
+               </row>
+             </tbody>
+           </entrytbl>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_SOURCE</constant></entry>
+           <entry>menu</entry>
+         </row>
+         <row id="v4l2-flash-strobe-source"><entry
+         spanname="descr">Defines the source of the flash LED
+         strobe.</entry>
+         </row>
+         <row>
+           <entrytbl spanname="descr" cols="2">
+             <tbody valign="top">
+               <row>
+                 <entry><constant>V4L2_FLASH_STROBE_SOURCE_SOFTWARE</constant></entry>
+                 <entry>The flash strobe is triggered by using
+                 the V4L2_CID_FLASH_STROBE control.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_STROBE_SOURCE_EXTERNAL</constant></entry>
+                 <entry>The flash strobe is triggered by an
+                 external source. Typically this is a sensor,
+                 which makes it possible to synchronises the
+                 flash strobe start to exposure start.</entry>
+               </row>
+             </tbody>
+           </entrytbl>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE</constant></entry>
+           <entry>button</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Strobe flash. Valid when
+           V4L2_CID_FLASH_LED_MODE is set to
+           V4L2_FLASH_LED_MODE_FLASH and V4L2_CID_FLASH_STROBE_SOURCE
+           is set to V4L2_FLASH_STROBE_SOURCE_SOFTWARE. Setting this
+           control may not be possible in presence of some faults.
+           See V4L2_CID_FLASH_FAULT.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_STOP</constant></entry>
+           <entry>button</entry>
+         </row>
+         <row><entry spanname="descr">Stop flash strobe immediately.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_STATUS</constant></entry>
+           <entry>boolean</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Strobe status: whether the flash
+           is strobing at the moment or not. This is a read-only
+           control.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_TIMEOUT</constant></entry>
+           <entry>integer</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Hardware timeout for flash. The
+           flash strobe is stopped after this period of time has
+           passed from the start of the strobe.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_INTENSITY</constant></entry>
+           <entry>integer</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Intensity of the flash strobe when
+           the flash LED is in flash mode
+           (V4L2_FLASH_LED_MODE_FLASH). The unit should be milliamps
+           (mA) if possible.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_TORCH_INTENSITY</constant></entry>
+           <entry>integer</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Intensity of the flash LED in
+           torch mode (V4L2_FLASH_LED_MODE_TORCH). The unit should be
+           milliamps (mA) if possible. Setting this control may not
+           be possible in presence of some faults. See
+           V4L2_CID_FLASH_FAULT.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_INDICATOR_INTENSITY</constant></entry>
+           <entry>integer</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Intensity of the indicator LED.
+           The indicator LED may be fully independent of the flash
+           LED. The unit should be microamps (uA) if possible.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_FAULT</constant></entry>
+           <entry>bitmask</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Faults related to the flash. The
+           faults tell about specific problems in the flash chip
+           itself or the LEDs attached to it. Faults may prevent
+           further use of some of the flash controls. In particular,
+           V4L2_CID_FLASH_LED_MODE is set to V4L2_FLASH_LED_MODE_NONE
+           if the fault affects the flash LED. Exactly which faults
+           have such an effect is chip dependent. Reading the faults
+           resets the control and returns the chip to a usable state
+           if possible.</entry>
+         </row>
+         <row>
+           <entrytbl spanname="descr" cols="2">
+             <tbody valign="top">
+               <row>
+                 <entry><constant>V4L2_FLASH_FAULT_OVER_VOLTAGE</constant></entry>
+                 <entry>Flash controller voltage to the flash LED
+                 has exceeded the limit specific to the flash
+                 controller.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_FAULT_TIMEOUT</constant></entry>
+                 <entry>The flash strobe was still on when
+                 the timeout set by the user ---
+                 V4L2_CID_FLASH_TIMEOUT control --- has expired.
+                 Not all flash controllers may set this in all
+                 such conditions.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_FAULT_OVER_TEMPERATURE</constant></entry>
+                 <entry>The flash controller has overheated.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_FAULT_SHORT_CIRCUIT</constant></entry>
+                 <entry>The short circuit protection of the flash
+                 controller has been triggered.</entry>
+               </row>
+             </tbody>
+           </entrytbl>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_CHARGE</constant></entry>
+           <entry>boolean</entry>
+         </row>
+         <row><entry spanname="descr">Enable or disable charging of the xenon
+         flash capacitor.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_READY</constant></entry>
+           <entry>boolean</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Is the flash ready to strobe?
+           Xenon flashes require their capacitors charged before
+           strobing. LED flashes often require a cooldown period
+           after strobe during which another strobe will not be
+           possible. This is a read-only control.</entry>
+         </row>
+         <row><entry></entry></row>
+       </tbody>
+      </tgroup>
+      </table>
+
+    </section>
 </section>
 
   <!--
diff --git a/Documentation/DocBook/media/v4l/dev-event.xml b/Documentation/DocBook/media/v4l/dev-event.xml
new file mode 100644 (file)
index 0000000..f14ae3f
--- /dev/null
@@ -0,0 +1,51 @@
+  <title>Event Interface</title>
+
+  <para>The V4L2 event interface provides a means for a user to get
+  immediately notified on certain conditions taking place on a device.
+  This might include start of frame or loss of signal events, for
+  example. Changes in the value or state of a V4L2 control can also be
+  reported through events.
+  </para>
+
+  <para>To receive events, the events the user is interested in first must
+  be subscribed using the &VIDIOC-SUBSCRIBE-EVENT; ioctl. Once an event is
+  subscribed, the events of subscribed types are dequeueable using the
+  &VIDIOC-DQEVENT; ioctl. Events may be unsubscribed using
+  VIDIOC_UNSUBSCRIBE_EVENT ioctl. The special event type V4L2_EVENT_ALL may
+  be used to unsubscribe all the events the driver supports.</para>
+
+  <para>The event subscriptions and event queues are specific to file
+  handles. Subscribing an event on one file handle does not affect
+  other file handles.</para>
+
+  <para>The information on dequeueable events is obtained by using select or
+  poll system calls on video devices. The V4L2 events use POLLPRI events on
+  poll system call and exceptions on select system call.</para>
+
+  <para>Starting with kernel 3.1 certain guarantees can be given with
+  regards to events:<orderedlist>
+       <listitem>
+         <para>Each subscribed event has its own internal dedicated event queue.
+This means that flooding of one event type will not interfere with other
+event types.</para>
+       </listitem>
+       <listitem>
+         <para>If the internal event queue for a particular subscribed event
+becomes full, then the oldest event in that queue will be dropped.</para>
+       </listitem>
+       <listitem>
+         <para>Where applicable, certain event types can ensure that the payload
+of the oldest event that is about to be dropped will be merged with the payload
+of the next oldest event. Thus ensuring that no information is lost, but only an
+intermediate step leading up to that information. See the documentation for the
+event you want to subscribe to whether this is applicable for that event or not.</para>
+       </listitem>
+      </orderedlist></para>
+
+  <!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "v4l2.sgml"
+indent-tabs-mode: nil
+End:
+  -->
diff --git a/Documentation/DocBook/media/v4l/func-ioctl.xml b/Documentation/DocBook/media/v4l/func-ioctl.xml
new file mode 100644 (file)
index 0000000..2de64be
--- /dev/null
@@ -0,0 +1,79 @@
+<refentry id="func-ioctl">
+  <refmeta>
+    <refentrytitle>V4L2 ioctl()</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>v4l2-ioctl</refname>
+    <refpurpose>Program a V4L2 device</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;sys/ioctl.h&gt;</funcsynopsisinfo>
+      <funcprototype>
+       <funcdef>int <function>ioctl</function></funcdef>
+       <paramdef>int <parameter>fd</parameter></paramdef>
+       <paramdef>int <parameter>request</parameter></paramdef>
+       <paramdef>void *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+       <term><parameter>fd</parameter></term>
+       <listitem>
+         <para>&fd;</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>request</parameter></term>
+       <listitem>
+         <para>V4L2 ioctl request code as defined in the <filename>videodev2.h</filename> header file, for example
+VIDIOC_QUERYCAP.</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>argp</parameter></term>
+       <listitem>
+         <para>Pointer to a function parameter, usually a structure.</para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>The <function>ioctl()</function> function is used to program
+V4L2 devices. The argument <parameter>fd</parameter> must be an open
+file descriptor. An ioctl <parameter>request</parameter> has encoded
+in it whether the argument is an input, output or read/write
+parameter, and the size of the argument <parameter>argp</parameter> in
+bytes. Macros and defines specifying V4L2 ioctl requests are located
+in the <filename>videodev2.h</filename> header file.
+Applications should use their own copy, not include the version in the
+kernel sources on the system they compile on. All V4L2 ioctl requests,
+their respective function and parameters are specified in <xref
+       linkend="user-func" />.</para>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+    <para>When an ioctl that takes an output or read/write parameter fails,
+    the parameter remains unmodified.</para>
+  </refsect1>
+</refentry>
+
+<!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "v4l2.sgml"
+indent-tabs-mode: nil
+End:
+-->
diff --git a/Documentation/DocBook/media/v4l/gen-errors.xml b/Documentation/DocBook/media/v4l/gen-errors.xml
new file mode 100644 (file)
index 0000000..5bbf3ce
--- /dev/null
@@ -0,0 +1,78 @@
+<title>Generic Error Codes</title>
+
+<table frame="none" pgwide="1" id="gen-errors">
+  <title>Generic error codes</title>
+  <tgroup cols="2">
+    &cs-str;
+    <tbody valign="top">
+       <!-- Keep it ordered alphabetically -->
+      <row>
+       <entry>EBADF</entry>
+       <entry>The file descriptor is not a valid.</entry>
+      </row>
+      <row>
+       <entry>EBUSY</entry>
+       <entry>The ioctl can't be handled because the device is busy. This is
+              typically return while device is streaming, and an ioctl tried to
+              change something that would affect the stream, or would require the
+              usage of a hardware resource that was already allocated. The ioctl
+              must not be retried without performing another action to fix the
+              problem first (typically: stop the stream before retrying).</entry>
+      </row>
+      <row>
+       <entry>EFAULT</entry>
+       <entry>There was a failure while copying data from/to userspace,
+              probably caused by an invalid pointer reference.</entry>
+      </row>
+      <row>
+       <entry>EINVAL</entry>
+       <entry>One or more of the ioctl parameters are invalid or out of the
+              allowed range. This is a widely used error code. See the individual
+              ioctl requests for specific causes.</entry>
+      </row>
+      <row>
+        <entry>ENODEV</entry>
+       <entry>Device not found or was removed.</entry>
+      </row>
+      <row>
+       <entry>ENOMEM</entry>
+       <entry>There's not enough memory to handle the desired operation.</entry>
+      </row>
+      <row>
+       <entry>ENOTTY</entry>
+       <entry>The ioctl is not supported by the driver, actually meaning that
+              the required functionality is not available, or the file
+              descriptor is not for a media device.</entry>
+      </row>
+      <row>
+       <entry>ENOSPC</entry>
+       <entry>On USB devices, the stream ioctl's can return this error, meaning
+              that this request would overcommit the usb bandwidth reserved
+              for periodic transfers (up to 80% of the USB bandwidth).</entry>
+      </row>
+      <row>
+       <entry>ENOSYS or EOPNOTSUPP</entry>
+       <entry>Function not available for this device (dvb API only. Will likely
+              be replaced anytime soon by ENOTTY).</entry>
+      </row>
+      <row>
+       <entry>EPERM</entry>
+       <entry>Permission denied. Can be returned if the device needs write
+               permission, or some special capabilities is needed
+               (e. g. root)</entry>
+      </row>
+      <row>
+       <entry>EWOULDBLOCK</entry>
+       <entry>Operation would block. Used when the ioctl would need to wait
+              for an event, but the device was opened in non-blocking mode.</entry>
+      </row>
+    </tbody>
+  </tgroup>
+</table>
+
+<para>Note 1: ioctls may return other error codes. Since errors may have side
+effects such as a driver reset, applications should abort on unexpected errors.
+</para>
+
+<para>Note 2: Request-specific error codes are listed in the individual
+requests descriptions.</para>
@@ -246,6 +246,8 @@ on working with the default settings initially.</para>
     </listitem>
   </varlistentry>
 </variablelist>
-
+<section id="lirc_dev_errors">
+  &return-value;
+</section>
 </section>
 </section>
   </refsect1>
 
   <refsect1>
-    <title>Return Value</title>
+    &return-value;
 
-    <para><function>ioctl()</function> returns <returnvalue>0</returnvalue> on
-    success. On failure, <returnvalue>-1</returnvalue> is returned, and the
-    <varname>errno</varname> variable is set appropriately. Generic error codes
-    are listed below, and request-specific error codes are listed in the
+    <para>Request-specific error codes are listed in the
     individual requests descriptions.</para>
     <para>When an ioctl that takes an output or read/write parameter fails,
     the parameter remains unmodified.</para>
-
-    <variablelist>
-      <varlistentry>
-       <term><errorcode>EBADF</errorcode></term>
-       <listitem>
-         <para><parameter>fd</parameter> is not a valid open file descriptor.
-         </para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>EFAULT</errorcode></term>
-       <listitem>
-         <para><parameter>argp</parameter> references an inaccessible memory
-         area.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>EINVAL</errorcode></term>
-       <listitem>
-         <para>The <parameter>request</parameter> or the data pointed to by
-         <parameter>argp</parameter> is not valid. This is a very common error
-         code, see the individual ioctl requests listed in
-         <xref linkend="media-user-func" /> for actual causes.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>ENOMEM</errorcode></term>
-       <listitem>
-         <para>Insufficient kernel memory was available to complete the
-         request.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>ENOTTY</errorcode></term>
-       <listitem>
-         <para><parameter>fd</parameter> is  not  associated  with  a character
-         special device.</para>
-       </listitem>
-      </varlistentry>
-    </variablelist>
   </refsect1>
 </refentry>
   </refsect1>
 
   <refsect1>
-    <title>Return value</title>
-    <para>This function doesn't return specific error codes.</para>
+    &return-value;
   </refsect1>
 </refentry>
     </table>
 
     <table pgwide="1" frame="none" id="media-link-desc">
-      <title>struct <structname>media_links_desc</structname></title>
+      <title>struct <structname>media_link_desc</structname></title>
       <tgroup cols="3">
         &cs-str;
        <tbody valign="top">
     &return-value;
 
     <variablelist>
-      <varlistentry>
-       <term><errorcode>EBUSY</errorcode></term>
-       <listitem>
-         <para>The link properties can't be changed because the link is
-         currently busy. This can be caused, for instance, by an active media
-         stream (audio or video) on the link. The ioctl shouldn't be retried if
-         no other action is performed before to fix the problem.</para>
-       </listitem>
-      </varlistentry>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
similarity index 94%
rename from Documentation/DocBook/v4l/pixfmt.xml
rename to Documentation/DocBook/media/v4l/pixfmt.xml
index deb6602..2ff6b77 100644 (file)
@@ -121,7 +121,7 @@ set this field to zero.</entry>
     an array of <structname>v4l2_plane_pix_format</structname> structures,
     describing all planes of that format.</para>
   <table pgwide="1" frame="none" id="v4l2-plane-pix-format">
-    <title>struct <structname>vl42_plane_pix_format</structname></title>
+    <title>struct <structname>v4l2_plane_pix_format</structname></title>
     <tgroup cols="3">
       &cs-str;
       <tbody valign="top">
@@ -741,10 +741,55 @@ information.</para>
          <row id="V4L2-PIX-FMT-MPEG">
            <entry><constant>V4L2_PIX_FMT_MPEG</constant></entry>
            <entry>'MPEG'</entry>
-           <entry>MPEG stream. The actual format is determined by
+           <entry>MPEG multiplexed stream. The actual format is determined by
 extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
 <xref linkend="mpeg-control-id" />.</entry>
          </row>
+         <row id="V4L2-PIX-FMT-H264">
+               <entry><constant>V4L2_PIX_FMT_H264</constant></entry>
+               <entry>'H264'</entry>
+               <entry>H264 video elementary stream with start codes.</entry>
+         </row>
+         <row id="V4L2-PIX-FMT-H264-NO-SC">
+               <entry><constant>V4L2_PIX_FMT_H264_NO_SC</constant></entry>
+               <entry>'AVC1'</entry>
+               <entry>H264 video elementary stream without start codes.</entry>
+         </row>
+         <row id="V4L2-PIX-FMT-H263">
+               <entry><constant>V4L2_PIX_FMT_H263</constant></entry>
+               <entry>'H263'</entry>
+               <entry>H263 video elementary stream.</entry>
+         </row>
+         <row id="V4L2-PIX-FMT-MPEG1">
+               <entry><constant>V4L2_PIX_FMT_MPEG1</constant></entry>
+               <entry>'MPG1'</entry>
+               <entry>MPEG1 video elementary stream.</entry>
+         </row>
+         <row id="V4L2-PIX-FMT-MPEG2">
+               <entry><constant>V4L2_PIX_FMT_MPEG2</constant></entry>
+               <entry>'MPG2'</entry>
+               <entry>MPEG2 video elementary stream.</entry>
+         </row>
+         <row id="V4L2-PIX-FMT-MPEG4">
+               <entry><constant>V4L2_PIX_FMT_MPEG4</constant></entry>
+               <entry>'MPG4'</entry>
+               <entry>MPEG4 video elementary stream.</entry>
+         </row>
+         <row id="V4L2-PIX-FMT-XVID">
+               <entry><constant>V4L2_PIX_FMT_XVID</constant></entry>
+               <entry>'XVID'</entry>
+               <entry>Xvid video elementary stream.</entry>
+         </row>
+         <row id="V4L2-PIX-FMT-VC1-ANNEX-G">
+               <entry><constant>V4L2_PIX_FMT_VC1_ANNEX_G</constant></entry>
+               <entry>'VC1G'</entry>
+               <entry>VC1, SMPTE 421M Annex G compliant stream.</entry>
+         </row>
+         <row id="V4L2-PIX-FMT-VC1-ANNEX-L">
+               <entry><constant>V4L2_PIX_FMT_VC1_ANNEX_L</constant></entry>
+               <entry>'VC1L'</entry>
+               <entry>VC1, SMPTE 421M Annex L compliant stream.</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
@@ -804,6 +849,12 @@ kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm
            <entry>'CPIA'</entry>
            <entry>YUV format used by the gspca cpia1 driver.</entry>
          </row>
+         <row id="V4L2-PIX-FMT-JPGL">
+           <entry><constant>V4L2_PIX_FMT_JPGL</constant></entry>
+           <entry>'JPGL'</entry>
+           <entry>JPEG-Light format (Pegasus Lossless JPEG)
+                       used in Divio webcams NW 80x.</entry>
+         </row>
          <row id="V4L2-PIX-FMT-SPCA501">
            <entry><constant>V4L2_PIX_FMT_SPCA501</constant></entry>
            <entry>'S501'</entry>
@@ -854,6 +905,11 @@ kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm
            <entry>'PJPG'</entry>
            <entry>Pixart 73xx JPEG format used by the gspca driver.</entry>
          </row>
+         <row id="V4L2-PIX-FMT-SE401">
+           <entry><constant>V4L2_PIX_FMT_SE401</constant></entry>
+           <entry>'S401'</entry>
+           <entry>Compressed RGB format used by the gspca se401 driver</entry>
+         </row>
          <row id="V4L2-PIX-FMT-SQ905C">
            <entry><constant>V4L2_PIX_FMT_SQ905C</constant></entry>
            <entry>'905C'</entry>
       <figure id="bayer-patterns">
        <title>Bayer Patterns</title>
        <mediaobject>
-         <imageobject>
-           <imagedata fileref="bayer.pdf" format="PS" />
-         </imageobject>
          <imageobject>
            <imagedata fileref="bayer.png" format="PNG" />
          </imageobject>
 
       <para>Those data formats consist of an ordered sequence of 8-bit bytes
        obtained from JPEG compression process. Additionally to the
-       <constant>_JPEG</constant> prefix the format code is made of
+       <constant>_JPEG</constant> postfix the format code is made of
        the following information.
        <itemizedlist>
          <listitem><para>The number of bus samples per entropy encoded byte.</para></listitem>
similarity index 97%
rename from Documentation/DocBook/v4l/v4l2.xml
rename to Documentation/DocBook/media/v4l/v4l2.xml
index a7fd76d..0d05e87 100644 (file)
@@ -87,7 +87,7 @@ Remote Controller chapter.</contrib>
       </author>
 
       <author>
-       <firstname>Pawel</firstname>
+       <firstname>Pawel</firstname>
        <surname>Osciak</surname>
        <contrib>Designed and documented the multi-planar API.</contrib>
        <affiliation>
@@ -127,6 +127,15 @@ structs, ioctls) must be noted in more detail in the history chapter
 (compat.xml), along with the possible impact on existing drivers and
 applications. -->
 
+      <revision>
+       <revnumber>3.1</revnumber>
+       <date>2011-06-27</date>
+       <authorinitials>mcc, po, hv</authorinitials>
+       <revremark>Documented that VIDIOC_QUERYCAP now returns a per-subsystem version instead of a per-driver one.
+                  Standardize an error code for invalid ioctl.
+                  Added V4L2_CTRL_TYPE_BITMASK.</revremark>
+      </revision>
+
       <revision>
        <revnumber>2.6.39</revnumber>
        <date>2011-03-01</date>
@@ -401,7 +410,7 @@ and discussions on the V4L mailing list.</revremark>
 </partinfo>
 
 <title>Video for Linux Two API Specification</title>
- <subtitle>Revision 2.6.39</subtitle>
+ <subtitle>Revision 3.1</subtitle>
 
   <chapter id="common">
     &sub-common;
@@ -156,19 +156,10 @@ on 22 Oct 2002 subject "Re:[V4L][patches!] Re:v4l2/kernel-2.5" -->
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
          <para>The &v4l2-cropcap; <structfield>type</structfield> is
-invalid or the ioctl is not supported. This is not permitted for
-video capture, output and overlay devices, which must support
-<constant>VIDIOC_CROPCAP</constant>.</para>
+invalid. This is not permitted for video capture, output and overlay devices,
+which must support <constant>VIDIOC_CROPCAP</constant>.</para>
        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -258,18 +258,9 @@ could not identify it.</entry>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
-         <para>The driver does not support this ioctl, or the
-<structfield>match_type</structfield> is invalid.</para>
+         <para>The <structfield>match_type</structfield> is invalid.</para>
        </listitem>
       </varlistentry>
      </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -246,15 +246,6 @@ register.</entry>
     &return-value;
 
     <variablelist>
-      <varlistentry>
-       <term><errorcode>EINVAL</errorcode></term>
-       <listitem>
-         <para>The driver does not support this ioctl, or the kernel
-was not compiled with the <constant>CONFIG_VIDEO_ADV_DEBUG</constant>
-option, or the <structfield>match_type</structfield> is invalid, or the
-selected chip or register does not exist.</para>
-       </listitem>
-      </varlistentry>
       <varlistentry>
        <term><errorcode>EPERM</errorcode></term>
        <listitem>
@@ -265,11 +256,3 @@ to execute these ioctls.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
            <entry>Event data for event V4L2_EVENT_VSYNC.
             </entry>
          </row>
+         <row>
+           <entry></entry>
+           <entry>&v4l2-event-ctrl;</entry>
+            <entry><structfield>ctrl</structfield></entry>
+           <entry>Event data for event V4L2_EVENT_CTRL.
+            </entry>
+         </row>
          <row>
            <entry></entry>
            <entry>__u8</entry>
             <entry></entry>
            <entry>Event timestamp.</entry>
          </row>
+         <row>
+           <entry>u32</entry>
+           <entry><structfield>id</structfield></entry>
+            <entry></entry>
+           <entry>The ID associated with the event source. If the event does not
+               have an associated ID (this depends on the event type), then this
+               is 0.</entry>
+         </row>
          <row>
            <entry>__u32</entry>
-           <entry><structfield>reserved</structfield>[9]</entry>
+           <entry><structfield>reserved</structfield>[8]</entry>
             <entry></entry>
            <entry>Reserved for future extensions. Drivers must set
            the array to zero.</entry>
     </table>
 
   </refsect1>
+  <refsect1>
+    &return-value;
+  </refsect1>
 </refentry>
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -180,8 +180,7 @@ Pictures</wordasword>, rather than immediately.</entry>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
-         <para>The driver does not support this ioctl, or the
-<structfield>cmd</structfield> field is invalid.</para>
+         <para>The <structfield>cmd</structfield> field is invalid.</para>
        </listitem>
       </varlistentry>
       <varlistentry>
@@ -194,11 +193,3 @@ the encoder was not running.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -254,17 +254,6 @@ enumerated.</entry>
 
   <refsect1>
     &return-value;
-
-    <para>See the description section above for a list of return
-values that <varname>errno</varname> can have.</para>
   </refsect1>
 
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -267,16 +267,5 @@ application should zero out all members except for the
 
   <refsect1>
     &return-value;
-
-    <para>See the description section above for a list of return
-values that <varname>errno</varname> can have.</para>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -68,19 +68,9 @@ until the driver returns <errorcode>EINVAL</errorcode>.</para>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
-         <para>The number of the audio input is out of bounds, or
-there are no audio inputs at all and this ioctl is not
-supported.</para>
+         <para>The number of the audio input is out of bounds.</para>
        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -71,19 +71,9 @@ signal to a sound card are not audio outputs in this sense.</para>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
-         <para>The number of the audio output is out of bounds, or
-there are no audio outputs at all and this ioctl is not
-supported.</para>
+         <para>The number of the audio output is out of bounds.</para>
        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -164,25 +164,9 @@ tuner.</entry>
        <listitem>
          <para>No audio inputs combine with the current video input,
 or the number of the selected audio input is out of bounds or it does
-not combine, or there are no audio inputs at all and the ioctl is not
-supported.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>EBUSY</errorcode></term>
-       <listitem>
-         <para>I/O is in progress, the input cannot be
-switched.</para>
+not combine.</para>
        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -130,25 +130,9 @@ applications must set the array to zero.</entry>
        <listitem>
          <para>No audio outputs combine with the current video
 output, or the number of the selected audio output is out of bounds or
-it does not combine, or there are no audio outputs at all and the
-ioctl is not supported.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>EBUSY</errorcode></term>
-       <listitem>
-         <para>I/O is in progress, the output cannot be
-switched.</para>
+it does not combine.</para>
        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -122,22 +122,5 @@ for &v4l2-cropcap; <structfield>bounds</structfield> is used.</entry>
 
   <refsect1>
     &return-value;
-
-    <variablelist>
-      <varlistentry>
-       <term><errorcode>EINVAL</errorcode></term>
-       <listitem>
-         <para>Cropping is not supported.</para>
-       </listitem>
-      </varlistentry>
-    </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -117,6 +117,13 @@ because another applications took over control of the device function
 this control belongs to.</para>
        </listitem>
       </varlistentry>
+      <varlistentry>
+       <term><errorcode>EACCES</errorcode></term>
+       <listitem>
+         <para>Attempt to set a read-only control or to get a
+         write-only control.</para>
+       </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
@@ -97,14 +97,8 @@ If the preset is not supported, it returns an &EINVAL; </para>
        </tbody>
       </tgroup>
     </table>
-
+  </refsect1>
+  <refsect1>
+    &return-value;
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -212,12 +212,7 @@ bit 0 (V4L2_DV_VSYNC_POS_POL) is for vertical sync polarity and bit 1 (V4L2_DV_H
       </tgroup>
     </table>
   </refsect1>
+  <refsect1>
+    &return-value;
+  </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -192,22 +192,5 @@ this mask to obtain the picture coding type.</entry>
 
   <refsect1>
     &return-value;
-
-    <variablelist>
-      <varlistentry>
-       <term><errorcode>EINVAL</errorcode></term>
-       <listitem>
-         <para>The driver does not support this ioctl.</para>
-       </listitem>
-      </varlistentry>
-    </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -250,6 +250,13 @@ These controls are described in <xref
 These controls are described in <xref
                linkend="fm-tx-controls" />.</entry>
          </row>
+         <row>
+           <entry><constant>V4L2_CTRL_CLASS_FLASH</constant></entry>
+           <entry>0x9c0000</entry>
+           <entry>The class containing flash device controls.
+These controls are described in <xref
+               linkend="flash-controls" />.</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
@@ -294,6 +301,13 @@ The field <structfield>size</structfield> is set to a value that is enough
 to store the payload and this error code is returned.</para>
        </listitem>
       </varlistentry>
+      <varlistentry>
+       <term><errorcode>EACCES</errorcode></term>
+       <listitem>
+         <para>Attempt to try or set a read-only control or to get a
+         write-only control.</para>
+       </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
@@ -445,29 +445,12 @@ by a privileged user to negotiate the parameters for a destructive
 overlay.</para>
        </listitem>
       </varlistentry>
-      <varlistentry>
-       <term><errorcode>EBUSY</errorcode></term>
-       <listitem>
-         <para>The framebuffer parameters cannot be changed at this
-time because overlay is already enabled, or capturing is enabled
-and the hardware cannot capture and overlay simultaneously.</para>
-       </listitem>
-      </varlistentry>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
-         <para>The ioctl is not supported or the
-<constant>VIDIOC_S_FBUF</constant> parameters are unsuitable.</para>
+         <para>The <constant>VIDIOC_S_FBUF</constant> parameters are unsuitable.</para>
        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -183,30 +183,14 @@ capture and output devices.</entry>
     &return-value;
 
     <variablelist>
-      <varlistentry>
-       <term><errorcode>EBUSY</errorcode></term>
-       <listitem>
-         <para>The data format cannot be changed at this
-time, for example because I/O is already in progress.</para>
-       </listitem>
-      </varlistentry>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
          <para>The &v4l2-format; <structfield>type</structfield>
-field is invalid, the requested buffer type not supported, or
-<constant>VIDIOC_TRY_FMT</constant> was called and is not
-supported with this buffer type.</para>
+field is invalid, the requested buffer type not supported, or the
+format is not supported with this buffer type.</para>
        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -75,26 +75,9 @@ querying or negotiating any other parameters.</para>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
-         <para>The number of the video input is out of bounds, or
-there are no video inputs at all and this ioctl is not
-supported.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>EBUSY</errorcode></term>
-       <listitem>
-         <para>I/O is in progress, the input cannot be
-switched.</para>
+         <para>The number of the video input is out of bounds.</para>
        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -159,22 +159,5 @@ to add them.</para>
 
   <refsect1>
     &return-value;
-
-    <variablelist>
-      <varlistentry>
-       <term><errorcode>EINVAL</errorcode></term>
-       <listitem>
-         <para>This ioctl is not supported.</para>
-       </listitem>
-      </varlistentry>
-    </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -76,25 +76,9 @@ negotiating any other parameters.</para>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
          <para>The number of the video output is out of bounds, or
-there are no video outputs at all and this ioctl is not
-supported.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>EBUSY</errorcode></term>
-       <listitem>
-         <para>I/O is in progress, the output cannot be
-switched.</para>
+there are no video outputs at all.</para>
        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -311,22 +311,5 @@ excessive motion blur. </para>
 
   <refsect1>
     &return-value;
-
-    <variablelist>
-      <varlistentry>
-       <term><errorcode>EINVAL</errorcode></term>
-       <listitem>
-         <para>This ioctl is not supported.</para>
-       </listitem>
-      </varlistentry>
-    </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -120,8 +120,7 @@ recording.</entry>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
-         <para>The requested priority value is invalid, or the
-driver does not support access priorities.</para>
+         <para>The requested priority value is invalid.</para>
        </listitem>
       </varlistentry>
       <varlistentry>
@@ -246,19 +246,10 @@ line systems.</entry>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
-         <para>The device does not support sliced VBI capturing or
-output, or the value in the <structfield>type</structfield> field is
+         <para>The value in the <structfield>type</structfield> field is
 wrong.</para>
        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -82,14 +82,7 @@ standards.</para>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
-         <para>This ioctl is not supported, or the
-<constant>VIDIOC_S_STD</constant> parameter was unsuitable.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>EBUSY</errorcode></term>
-       <listitem>
-         <para>The device is busy and therefore can not change the standard</para>
+         <para>The <constant>VIDIOC_S_STD</constant> parameter was unsuitable.</para>
        </listitem>
       </varlistentry>
     </variablelist>
@@ -37,22 +37,5 @@ was introduced in Linux 2.6.15.</para>
 
   <refsect1>
     &return-value;
-
-    <variablelist>
-      <varlistentry>
-       <term><errorcode>EINVAL</errorcode></term>
-       <listitem>
-         <para>The driver does not support this ioctl.</para>
-       </listitem>
-      </varlistentry>
-    </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
-         <para>Video overlay is not supported, or the
-parameters have not been set up. See <xref
+         <para>The overlay parameters have not been set up. See <xref
 linkend="overlay" /> for the necessary steps.</para>
        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
similarity index 95%
rename from Documentation/DocBook/v4l/vidioc-qbuf.xml
rename to Documentation/DocBook/media/v4l/vidioc-qbuf.xml
index f2b11f8..9caa49a 100644 (file)
@@ -158,15 +158,6 @@ or no buffers have been allocated yet, or the
 <structfield>userptr</structfield> or
 <structfield>length</structfield> are invalid.</para>
        </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>ENOMEM</errorcode></term>
-       <listitem>
-         <para>Not enough physical or virtual memory was available to
-enqueue a user pointer buffer.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
        <term><errorcode>EIO</errorcode></term>
        <listitem>
          <para><constant>VIDIOC_DQBUF</constant> failed due to an
@@ -184,11 +175,3 @@ continue streaming.
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -61,27 +61,5 @@ returned.</para>
 
   <refsect1>
     &return-value;
-    <variablelist>
-      <varlistentry>
-       <term><errorcode>EINVAL</errorcode></term>
-       <listitem>
-         <para>This ioctl is not supported.</para>
-       </listitem>
-    </varlistentry>
-      <varlistentry>
-       <term><errorcode>EBUSY</errorcode></term>
-       <listitem>
-         <para>The device is busy and therefore can not sense the preset</para>
-       </listitem>
-      </varlistentry>
-    </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -67,9 +67,8 @@ driver is not compatible with this specification the ioctl returns an
            <entry><para>Name of the driver, a unique NUL-terminated
 ASCII string. For example: "bttv". Driver specific applications can
 use this information to verify the driver identity. It is also useful
-to work around known bugs, or to identify drivers in error reports.
-The driver version is stored in the <structfield>version</structfield>
-field.</para><para>Storing strings in fixed sized arrays is bad
+to work around known bugs, or to identify drivers in error reports.</para>
+<para>Storing strings in fixed sized arrays is bad
 practice but unavoidable here. Drivers and applications should take
 precautions to never read or write beyond the end of the array and to
 make sure the strings are properly NUL-terminated.</para></entry>
@@ -100,9 +99,13 @@ empty string (<structfield>bus_info</structfield>[0] = 0).<!-- XXX pci_dev->slot
          <row>
            <entry>__u32</entry>
            <entry><structfield>version</structfield></entry>
-           <entry><para>Version number of the driver. Together with
-the <structfield>driver</structfield> field this identifies a
-particular driver. The version number is formatted using the
+           <entry><para>Version number of the driver.</para>
+<para>Starting on kernel 3.1, the version reported is provided per
+V4L2 subsystem, following the same Kernel numberation scheme. However, it
+should not always return the same version as the kernel, if, for example,
+an stable or distribution-modified kernel uses the V4L2 stack from a
+newer kernel.</para>
+<para>The version number is formatted using the
 <constant>KERNEL_VERSION()</constant> macro:</para></entry>
          </row>
          <row>
@@ -280,24 +283,5 @@ linkend="mmap">streaming</link> I/O method.</entry>
 
   <refsect1>
     &return-value;
-
-    <variablelist>
-      <varlistentry>
-       <term><errorcode>EINVAL</errorcode></term>
-       <listitem>
-         <para>The device is not compatible with this
-specification.</para>
-       </listitem>
-      </varlistentry>
-    </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
-
@@ -156,7 +156,8 @@ signed value.</entry>
            <entry>Maximum value, inclusive. This field gives an upper
 bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
 highest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant>
-controls.
+controls. For <constant>V4L2_CTRL_TYPE_BITMASK</constant> controls it is the
+set of usable bits.
 For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the maximum value
 gives the maximum length of the string. This length <emphasis>does not include the terminating
 zero</emphasis>. It may not be valid for any other type of control, including
@@ -289,6 +290,15 @@ values which are actually different on the hardware.</entry>
            <entry>The control has a menu of N choices. The names of
 the menu items can be enumerated with the
 <constant>VIDIOC_QUERYMENU</constant> ioctl.</entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_CTRL_TYPE_BITMASK</constant></entry>
+           <entry>0</entry>
+           <entry>n/a</entry>
+           <entry>any</entry>
+           <entry>A bitmask field. The maximum value is the set of bits that can
+be used, all other bits are to be 0. The maximum value is interpreted as a __u32,
+allowing the use of bit 31 in the bitmask.</entry>
          </row>
          <row>
            <entry><constant>V4L2_CTRL_TYPE_BUTTON</constant></entry>
@@ -62,28 +62,5 @@ current video input or output.</para>
 
   <refsect1>
     &return-value;
-
-    <variablelist>
-      <varlistentry>
-       <term><errorcode>EINVAL</errorcode></term>
-       <listitem>
-         <para>This ioctl is not supported.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>EBUSY</errorcode></term>
-       <listitem>
-         <para>The device is busy and therefore can not detect the standard</para>
-       </listitem>
-      </varlistentry>
-    </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -121,14 +121,6 @@ higher. This array should be zeroed by applications.</entry>
     &return-value;
 
     <variablelist>
-      <varlistentry>
-       <term><errorcode>EBUSY</errorcode></term>
-       <listitem>
-         <para>The driver supports multiple opens and I/O is already
-in progress, or reallocation of buffers was attempted although one or
-more are still mapped.</para>
-       </listitem>
-      </varlistentry>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
@@ -140,11 +132,3 @@ supported.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
@@ -88,9 +88,9 @@ synchronize with other events.</para>
       <varlistentry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
-         <para>Streaming I/O is not supported, the buffer
-<structfield>type</structfield> is not supported, or no buffers have
-been allocated (memory mapping) or enqueued (output) yet.</para>
+         <para>The buffer<structfield>type</structfield> is not supported,
+         or no buffers have been allocated (memory mapping) or enqueued
+         (output) yet.</para>
        </listitem>
       </varlistentry>
       <varlistentry>
@@ -105,11 +105,3 @@ been allocated (memory mapping) or enqueued (output) yet.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
       </varlistentry>
     </variablelist>
   </refsect1>
+  <refsect1>
+    &return-value;
+  </refsect1>
 </refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml b/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
new file mode 100644 (file)
index 0000000..69c0d8a
--- /dev/null
@@ -0,0 +1,297 @@
+<refentry id="vidioc-subscribe-event">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</refname>
+    <refpurpose>Subscribe or unsubscribe event</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+       <funcdef>int <function>ioctl</function></funcdef>
+       <paramdef>int <parameter>fd</parameter></paramdef>
+       <paramdef>int <parameter>request</parameter></paramdef>
+       <paramdef>struct v4l2_event_subscription
+*<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+       <term><parameter>fd</parameter></term>
+       <listitem>
+         <para>&fd;</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>request</parameter></term>
+       <listitem>
+         <para>VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>argp</parameter></term>
+       <listitem>
+         <para></para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>Subscribe or unsubscribe V4L2 event. Subscribed events are
+    dequeued by using the &VIDIOC-DQEVENT; ioctl.</para>
+
+    <table frame="none" pgwide="1" id="v4l2-event-subscription">
+      <title>struct <structname>v4l2_event_subscription</structname></title>
+      <tgroup cols="3">
+       &cs-str;
+       <tbody valign="top">
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>type</structfield></entry>
+           <entry>Type of the event.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>id</structfield></entry>
+           <entry>ID of the event source. If there is no ID associated with
+               the event source, then set this to 0. Whether or not an event
+               needs an ID depends on the event type.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>flags</structfield></entry>
+           <entry>Event flags, see <xref linkend="event-flags" />.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>reserved</structfield>[5]</entry>
+           <entry>Reserved for future extensions. Drivers and applications
+           must set the array to zero.</entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="event-type">
+      <title>Event Types</title>
+      <tgroup cols="3">
+       &cs-def;
+       <tbody valign="top">
+         <row>
+           <entry><constant>V4L2_EVENT_ALL</constant></entry>
+           <entry>0</entry>
+           <entry>All events. V4L2_EVENT_ALL is valid only for
+           VIDIOC_UNSUBSCRIBE_EVENT for unsubscribing all events at once.
+           </entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_VSYNC</constant></entry>
+           <entry>1</entry>
+           <entry>This event is triggered on the vertical sync.
+           This event has a &v4l2-event-vsync; associated with it.
+           </entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_EOS</constant></entry>
+           <entry>2</entry>
+           <entry>This event is triggered when the end of a stream is reached.
+           This is typically used with MPEG decoders to report to the application
+           when the last of the MPEG stream has been decoded.
+           </entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_CTRL</constant></entry>
+           <entry>3</entry>
+           <entry><para>This event requires that the <structfield>id</structfield>
+               matches the control ID from which you want to receive events.
+               This event is triggered if the control's value changes, if a
+               button control is pressed or if the control's flags change.
+               This event has a &v4l2-event-ctrl; associated with it. This struct
+               contains much of the same information as &v4l2-queryctrl; and
+               &v4l2-control;.</para>
+
+               <para>If the event is generated due to a call to &VIDIOC-S-CTRL; or
+               &VIDIOC-S-EXT-CTRLS;, then the event will <emphasis>not</emphasis> be sent to
+               the file handle that called the ioctl function. This prevents
+               nasty feedback loops. If you <emphasis>do</emphasis> want to get the
+               event, then set the <constant>V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK</constant>
+               flag.
+               </para>
+
+               <para>This event type will ensure that no information is lost when
+               more events are raised than there is room internally. In that
+               case the &v4l2-event-ctrl; of the second-oldest event is kept,
+               but the <structfield>changes</structfield> field of the
+               second-oldest event is ORed with the <structfield>changes</structfield>
+               field of the oldest event.</para>
+           </entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
+           <entry>0x08000000</entry>
+           <entry>Base event number for driver-private events.</entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+
+    <table pgwide="1" frame="none" id="event-flags">
+      <title>Event Flags</title>
+      <tgroup cols="3">
+       &cs-def;
+       <tbody valign="top">
+         <row>
+           <entry><constant>V4L2_EVENT_SUB_FL_SEND_INITIAL</constant></entry>
+           <entry>0x0001</entry>
+           <entry>When this event is subscribed an initial event will be sent
+               containing the current status. This only makes sense for events
+               that are triggered by a status change such as <constant>V4L2_EVENT_CTRL</constant>.
+               Other events will ignore this flag.</entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK</constant></entry>
+           <entry>0x0002</entry>
+           <entry><para>If set, then events directly caused by an ioctl will also be sent to
+               the filehandle that called that ioctl. For example, changing a control using
+               &VIDIOC-S-CTRL; will cause a V4L2_EVENT_CTRL to be sent back to that same
+               filehandle. Normally such events are suppressed to prevent feedback loops
+               where an application changes a control to a one value and then another, and
+               then receives an event telling it that that control has changed to the first
+               value.</para>
+
+               <para>Since it can't tell whether that event was caused by another application
+               or by the &VIDIOC-S-CTRL; call it is hard to decide whether to set the
+               control to the value in the event, or ignore it.</para>
+
+               <para>Think carefully when you set this flag so you won't get into situations
+               like that.</para>
+           </entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="v4l2-event-vsync">
+      <title>struct <structname>v4l2_event_vsync</structname></title>
+      <tgroup cols="3">
+       &cs-str;
+       <tbody valign="top">
+         <row>
+           <entry>__u8</entry>
+           <entry><structfield>field</structfield></entry>
+           <entry>The upcoming field. See &v4l2-field;.</entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="v4l2-event-ctrl">
+      <title>struct <structname>v4l2_event_ctrl</structname></title>
+      <tgroup cols="4">
+       &cs-str;
+       <tbody valign="top">
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>changes</structfield></entry>
+           <entry></entry>
+           <entry>A bitmask that tells what has changed. See <xref linkend="changes-flags" />.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>type</structfield></entry>
+           <entry></entry>
+           <entry>The type of the control. See &v4l2-ctrl-type;.</entry>
+         </row>
+         <row>
+           <entry>union (anonymous)</entry>
+           <entry></entry>
+           <entry></entry>
+           <entry></entry>
+         </row>
+         <row>
+           <entry></entry>
+           <entry>__s32</entry>
+           <entry><structfield>value</structfield></entry>
+           <entry>The 32-bit value of the control for 32-bit control types.
+               This is 0 for string controls since the value of a string
+               cannot be passed using &VIDIOC-DQEVENT;.</entry>
+         </row>
+         <row>
+           <entry></entry>
+           <entry>__s64</entry>
+           <entry><structfield>value64</structfield></entry>
+           <entry>The 64-bit value of the control for 64-bit control types.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>flags</structfield></entry>
+           <entry></entry>
+           <entry>The control flags. See <xref linkend="control-flags" />.</entry>
+         </row>
+         <row>
+           <entry>__s32</entry>
+           <entry><structfield>minimum</structfield></entry>
+           <entry></entry>
+           <entry>The minimum value of the control. See &v4l2-queryctrl;.</entry>
+         </row>
+         <row>
+           <entry>__s32</entry>
+           <entry><structfield>maximum</structfield></entry>
+           <entry></entry>
+           <entry>The maximum value of the control. See &v4l2-queryctrl;.</entry>
+         </row>
+         <row>
+           <entry>__s32</entry>
+           <entry><structfield>step</structfield></entry>
+           <entry></entry>
+           <entry>The step value of the control. See &v4l2-queryctrl;.</entry>
+         </row>
+         <row>
+           <entry>__s32</entry>
+           <entry><structfield>default_value</structfield></entry>
+           <entry></entry>
+           <entry>The default value value of the control. See &v4l2-queryctrl;.</entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+
+    <table pgwide="1" frame="none" id="changes-flags">
+      <title>Changes</title>
+      <tgroup cols="3">
+       &cs-def;
+       <tbody valign="top">
+         <row>
+           <entry><constant>V4L2_EVENT_CTRL_CH_VALUE</constant></entry>
+           <entry>0x0001</entry>
+           <entry>This control event was triggered because the value of the control
+               changed. Special case: if a button control is pressed, then this
+               event is sent as well, even though there is not explicit value
+               associated with a button control.</entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_CTRL_CH_FLAGS</constant></entry>
+           <entry>0x0002</entry>
+           <entry>This control event was triggered because the control flags
+               changed.</entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+  <refsect1>
+    &return-value;
+  </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/vbi_525.gif.b64 b/Documentation/DocBook/media/vbi_525.gif.b64
new file mode 100644 (file)
index 0000000..d5dcf06
--- /dev/null
@@ -0,0 +1,84 @@
+R0lGODlhKgPIAIAAAAAAAP///yH5BAEAAAEALAAAAAAqA8gAAAL+jI+py+0Po5y02ouz3rz7D4bi
+SJbmiabqWgJs475LLCt0fdy4oeN9/QPuEEFZkXVcJZXDXNP5pC0TgGrMSrRMidhA1/uNbB9j2CZ8
+Kc+qHDXDTT2jK3BuPau13vFpdmc/p6Uh5SeYoXMHyFNomEeYiNEVKCFFx8Wz2Eh56YWp2bfnGXk1
+OEhaKnem2rYa6vp3KIqaBhULmsk4Ufc1KTbq4rfbhxkcOQx22limZ4P8STYH3PsGu8pqe439aw36
+eji9qT1rGCpraf5MkQynyJeuG0c73imvLYzuUAwF/P6WTK8vHDdj2Qia8hYL4bF2o/CpmydOXa6I
+uqQNPFepny/+d+cM0qsH8qNGCI8M3gvG7KG8iSJJVoNIp1w5h/C+gSPjgWE9hR0Lqmzp0RFPjLV+
+hoRki2XNPJyCVmy2U6KnHm6WnboRcOPFkS59xqQpEKZRpkDHfi1rdqlXgTMVKVVL7h/cnmi1rtxq
+t27Yn1n5xrySUi81iYAlvR2MN23Fm/nkyHzp9G9iSof3Ps1pE3PmyV2dhaSL1Jiee3/ZjI5Mkhlj
+xDPXGnkClgns1pxV0K6d4rbYF7pRv44CW7Dtojt6f/YxO7hxrrmVJ3/eZDnd4tCjVw+OPbv27dy7
+e/8OPrz48eTLmz+PPr369ezbu38PP778+fTr27+PP7/+/fz++/v/D2CAAg5IYIEGHohgggouSNFv
+1l2HHIRCACehgw9eOIR0001I4YVq8MJIVZItUpJiG564GG75VJaXb5aVthtljwnV1mauyXijVqtB
+FVRoK7Foxi0kNphaYdhYNRUxQMZDWZKd9IXTQTmmFluUDQln5TcqBrnlYEOhaGJXNZrUpR24sLPN
+kC6uaBGWMywERpWISeUZacIE5iZH8OApJ3FrtvhnY5AdR1iZVOw4p1BTZhljlGNG1aijfgIKl4+f
+kNZjoIL2ySOacX4kYlyyfDgooWBSWmikOH15mU5ksfqiqUVqNsySXN7FqZ5jWdoTr7sSqaOtTH6Y
+EajMNZX+kbC53qopDDMuymhprgLbGaTUbgrtm8smCqOqQRYbZrV58vijtzZgNW2TTHZEag7rHFuU
+Pp4aSq6sc9EJa7jinpVuq/Ruy+xSj9KibL0YyRXrXr7WlC+242qrDMJsEYYSVvAiUzGJwg7c7BqI
+GjyiuQ5f7PG/7j57VqkpqryyyJ0WDDBxC29ymr3+YFEzyRpLE5qG91qYYYVAR4hh0B0WTbTRR1Mn
+NBKTDs0h0lErTTXTSyddNdZabw311ET7nLDTTct2tddmn82bc2V3zbbYazMId9xyz0133XbfjXfe
+eu/Nd99+/w144IIPTnjhhh+OeOKKczcR2CYvDnnkkgf+XoTF2eUCs9uTb85554MrVUjmJGDuuMue
+n4566gKyxM+T2L37cNqqz0577QG2/ikpVxEie7LflW578MIPL1vroVdifOy3outkscD/THz00k+v
+ne46ApQT70o2ZWz1RT5Pffji2w4YWcqLkrzvMhNT/Wjuvy/6+PLPL/w/854vr+t58gP+vufySb8A
+CnB8phEBmo7nhDHwz3vQGKADH0jAT4UgVGZQILjeBsEManB6GqKgP+h0vtFtcIQk5KAJpqAa/znL
+Xc4CXv9KCMP2fMyA8fvDDCdYwzbg7IQbwZ0IqeHCGArRbj4UwgvxgDJSHXEfIUQVEpuIqiLycIhU
+jJv+FNO2RCeJQ4kPuuIHUMi+Kb4piFUso4K8yIQsYm8cIlKj9VrQQyiqUH9mrOPm0DgcN8YsXoLQ
+Ix1HAMY/ArKCdiyk5PDYHD+6qo1dlOPItIXIG0XSkJT02yR5qEg2EqyRHYyjzyrnyEqK8oyhTEgj
+7bFJo13SI2EwzCdDhDP4yXKWtKxYLWWJsVu+L5e6rFkv4bezX9pSmDd0XzdgZkwa7SJnFDMNMX35
+TFdGM5jE5GU1o4kn1WDzmXbg2TaFaSZrgvNks+ymOL9Jy3DesGUiSd5wmEhGt5SiHUipp+naCZL7
+6ZOV+WyixMJhT1MKlJ+CFCP2nmexf9plCZZbJWT+3Cm7MJIxSfGcp0WTglGC9CtL+9RERz3aT3pm
+FFeiuShBHcqNN75ToqjkaBhXqr8XJnSPIC0oHP2JU5FqdKQ2g5jyLNerfgo1qDolKTlMmsqTlrJa
+Km1OAmOGCKa+1KkstRBEUdDQpUpqoEk1KlF2ei2fftQoYyVrSFERUK9aQp4tRakmbXrTqtbUpXD9
+oVw1d9UTZLWiXO0jWnn61Y7xca5mJWxhifpXsKr1IWxV6kQPitc1GnZOTcVqFhRq0Lxmdqp6palb
+L5vYxQL0nkA9rGnVgql9FvWoiu2qX9uqVWxVtrNP/em6lsdZ2t6VbE9ap1B9y9qS9jWwwS2uzvD+
+OdmFDjWoIF0tcZ+7VqTWFLjMpS5Ri6krsaoJpt6M2hFLK7bGuha6DAPsqSi7XNSmV73NDa1xVSLe
+1xLUqlaLbViWCF7vJu27ns2pe8k72rCSq6z3XW+B22ve8rZWvuM9LW/xm13LPo2q9mUufScU3+gm
+OMCiDRtukytVEIcYsRuO44I1LNz5RrTCytXvfo/G3wnTNsOM/S98S+zED1vYwS0WsWxxGkLMbjXF
+DWbvhV185CS/GMm9ky6KOywmHM/xxz7WMY97bFbn3vjENR7ulSVM05QumcljXnGMabwnGysYylO2
+spG/TOUqo1fLa35vl4ksZ7uyeMRmrq8akav+5OI5+c5sFlRaezpgA/P5zXDGLZ05bOc0e5nRD/Zz
+mfscHWYiQdNKAK6n4wfAxSTi09wk5zipqctunvqct1T1L8P5i1GLLtTsdMRBrBvrHNoE18fEL6dH
+CexgC3vYxC62sY+N7GQre9nMbraznw3taEt72tSutrWvje1sa3vb3O62t78N7nCLe9zkLre5z43u
+dKt73exut7vfDe94y3ve9K63ve9t7SBkNdH47re/9Qq6CAP63wQvuGZ2mYneFoPWBm+4w8VUWiMB
+5IIPr7jFX2a/YCZ8zxfvuLnf1VB5QcnjJDd4YTKucN3xuuQsb7nLXw7zmMt85jSvuc1vjvP+nOt8
+5zzvuc9/DvSgC33oRC+60Y+O9KQrfelMb7rTnw71qEt96lSvutWvjvWsa33rXO+6178O9rCLfexk
+L7vZz472scG0vllD24rZzrW28bbtcl873N2uObUfqkQzJFaJPAO9Fm53W34/mcbO+7/t9j1ksfzY
+MiUO+DaXDPCLT9VpKr8yZnpQDM50JcmkyTOdNT5Enx8mxhAPaxApq/CULxjFV9S8kT9yhWts0zL4
+JVnX44uigl1481Cf8KsI3Kf+Er6biMXS18/+gy2JJfBzFw/Mc35U0NcXJxAh+4A1ENC69xdoER38
+34Mf+sZvF/5OP3yQ+QKAt8+14Z9/2dH+H3dnh4d/Als5f1MzMcdsCoj5SfwwqXVb/Mca6qd9WBaA
+R/J+1qddDHeAUZZy85c+mOcp/ndc5QMqGyMawrd5ACVx/8dYKrcsFQg7DAhEu6NAG7g9q3cU3RN4
+zBJV9jdwsXM/GQiCRuZWNWh7Msh3QmaAhoYSIyhja1ALbQJ/obM+L0iExvJry8d8LpiAuPdSN7h9
+3VOD3kdHW1AVsOOAxEclTySEIIQOHViF7XSFZQgUVFiGj8CCYpiGR+g8Axgt24c8Q9gpvTJbHjZg
+IjguFJQVZChbH2h/2rODJjgqxieDGTiFevgyFKWGAYOBj8gtVPF564IpLRKJgziAgAj+ieFniNxX
+fUo4LPcXhn2YEqMnif+TMYNHgKoWeTTYTGoifZzXeAsoivpXJ2f4PaHHik7oMZ1ni4yIi8fDib+I
+gen3g6pohE34gMa4cbO4ixJkh8m4d0HYi5Lniq1XjMqojcqgd2AmNXVnd3g3juRIYXT3dnGXjuZ4
+jl/zjboVjuvIjvB4d/NoUOiYd+qYj/Z4j+6IQXNXj/IojuAYkAK5j/yoZwV5kAa5kA2Zdg8JkREp
+kRNJkRVpkT73ZxwnjASpjwCJkIP0jv3Yke34kSAZjww5kPQ4kiSZkipZkhOkNifpkOWIkjQ5kzZJ
+NqyXi9uYeIrXho8TZtTlCjnEMfn+Z07jN3n3hIuC1ZNKeY2JiD6Zs0gC5iWzliav+Inv51vKx3wo
+WIrTV3uh2IqC9zjZN5ZL2DBgSZW+iI2GBpTT2IwmtpajqJSGIY232JRbuQ1myZZoKZZZmTt8ySV3
+ggapWEHRAJjU2JaL6YVMKYepMpe/GJlH6ZTI2Jdu6ZRcuZGQBJePqTCTmYRG2XyO6Q52Ui5QuJn7
+sA4amC2XOYeJCWukWVugeX2y+ZeiGZSO0ZrncpdGWYKwOZq2mV94SXwzEyymCULIo4u0h5rt95ZD
+uZuuyS2xSJuNeZZ3WJlhBmRQBAhCGVrLmRfGCXF1yTyg2ThkQlZ5eJ3lWYipOZ3+UKmd/uSDrwmf
+ciSY76kuacmY+Hk9lWmEwumJ8BmDSBl9/zKgpEmI6CkjGcOM/MmN3QicnRmX0OBpuvmW3GlD4jkr
+QEmUFuqfHXokUjkPGtoYDSqd+meiE+qMehmf0ZmQComTHtmScSWTMWqjHPmSMPmPMhpRGemjMYmP
+N4mjM0qjMHqjLkmkL5qjIPCjLXqhLqqkSWqSQXqkSFqTLHmlVpqlIrmkF+mlXwqmYSqmY7puiEim
+Zzogj4GEaMqmAIIQmtmmcTofbyqhcqp0GSlD1gCndvpvuqYldSU3dOqkfJpun/VFt1md5sFQjOKn
+hFpu+dObKVMXUnSMx5AfDBX+agfqqH0qQQtkCrMZf81gqBvnmemBTZtacuCyp98yFbyAD/NJSLiD
+p4dKoSuHqu62qJHqlpTYJ5AgcvKBqbfqclroUOUZBynoFP/pHrMqrI8KL2CErB1YQPHBrM06bjwJ
+lxsDJCkkqgD3WNZ6Ro16lT5gq0JCnBPGrfs5SerJcaOKm+BaH+4KC5kkZoR2nTTBrixToKCESTwK
+r2mqkatySi1lr/uJr7nFpJ6kooMWpf8KsHpErwQraed6sIAKLez6SQHrsHAjr6wQsSpGMzzIqp0U
+ZfwKR9W6sfzRsarwsXnWrYDJryurohjbWSibsvohs5MmaBI7se45qQhLq5L+YrIiZLM3ix85i2e/
+oRMHJLJesmfoArVPyWqldnivNrW1hGqvhk5Xi7VcW05ei0u9JrbKNLbS8nioyE1bC7bAtLYIt7Xo
+BLfmBLdWW7Vz20vq9E2mFrZ1u2qihrcdRHq19Vj5CoaFVqIMC2kAdq/U57KWqGh0hWBJu2WG67Q6
+y11AO6WEq6O71WjIhbRSBaubG1OVZrH7R7lAhLhyGWmLO4MHtmOUhoDqhWaJO7mru34YorlBC1mV
+Frr8RmWf61K9q7uaRaO5K1m26xKzq7qKa7CM+7qu27nadVaWC4GnCxXKS2HG+1CYm7nHG717FVnC
+Syuje7mlq0XIK7DUO2T+6Luwvhu97gu7iya7qVu97Fu5khtZ5ju+2ru94uu8v6ux1Oe/BUG8ema8
+A+y9T8Zg9suZCGqZjtu4pfm4wUu/68u8FqzAFwa8H7bBjgZVyAi+vDuo8xvAIVy/F5y++Eu7dZaI
+wym/sQvDL6xc2IvBLFy7C6zBJfxECPV9BIZe+ru/CZy96DfEWHm/DDxGFYyZ1luqcfa+EPy8MQy6
+SsyqXLbCPeti5fq74gq62JWtSMTFwavFUgyPFShlKVxkV7y8ienCkPvEEhzBEkzDS4zEBaq+ZXxp
++RtopEs1MQYwCIzAQJzEZ1zFBPq/8evGiOzEWUbFR4zChZzG5bvHkoz+aWRmyZRsw5mMxRl8w51M
+sYcMvYrsZqFMwiq8xpp8yptcyavMynw8yXrcyqksy7d7x5D8yA46ymScyzKcyKUcySfsyWpMy5Z2
+yZjsyrGMzOBoxlYcsrXsyMHMum28yKSsyz8cub9cw8Kczc1MzK+szHl8zMX8zXVcuNh8uIT8zJ/c
+utUsvVHMyxTszA3MxOWMw8mMx+BcxOIczsY8y9s8zOZsy9DcvOv8zrvcy+zcgI0sz+RsugBdvPic
+z/Z8zxmSoqNT0aq4a1JiI92Q0bm2aqeqt3cb0qk20q1W0iYttbR4ax3N0RsNBBdNQ114QjCNQzLd
+AjRttDmt0zvN0z1u7dM/DdRBLdRDTdRFbdRHjdRJrdRLzdRN7dRPDdVRLdVTTdVVbdVXjdVfVBkx
++APSnNU5bZaaCsVfPdQnR8TkJwlnTdZAnSwXJIidutZBHbhrqpqnuKpx/a9c3RdvndZ43dO+pCSY
+E9gqF8bNWgAAOw==
diff --git a/Documentation/DocBook/media/vbi_625.gif.b64 b/Documentation/DocBook/media/vbi_625.gif.b64
new file mode 100644 (file)
index 0000000..831f49a
--- /dev/null
@@ -0,0 +1,90 @@
+R0lGODlhKgPIAIAAAAAAAP///yH5BAEAAAEALAAAAAAqA8gAAAL+jI+py+0Po5y02ouz3rz7D4bi
+SJbmiabqWgJs475LLCt0fdy4oeN9/QPuEEFZkXVcJZXDXNP5pC0TgGrOCqVMidhAVdqVbLmx73Wc
+FXfNabGFzfbG3Rz0bDO/2G1hzJ7o8ceT56dB+Gb4JciD16fnh3VI97bmOCE4tyhVUSbHKOlg1xnp
+6aWFKDfaecrqQlrK2vqK2bjImPFaiLuKuxvY+2HLq1tniHcLzFmWy6mnitxMeWs5iaZo0xZhTahj
+rdzXHa3m6Eod+h1+LW7MXpx83P7962y+ju4O//5oGr8PHUvs36VjoCBsujTsxp5t0MIB1MZLYb07
+CBt+QlWRHz/+Zto62NLYD+Ouj7Q+ZlMj0J80kCr1iaSHT6WmeAXPAXOVzNs0hw8fHAwzkeLATz9E
+xVo2qCa2o7AA9Wz5cmXIgFAhKu2Yb2q1rFSrDmUZFeUgrQaLdhWriFZKGKt6LNTSlopXthevrIUB
+d9rSp6FGcbnLwCRYe2ELo+VK+CxEwF9XkoypeCtZn05dTiqlNupMxnyWxXkL17OVtHz7loMTdO+4
+pGsMsz0dKbVcyK7LXsWbyKSweTA95qatDHho4T7TqqsdWN1toaFbExNMHMkTzimgR2cSZfpgI9qt
+T8aePbz4IQebeLcsZDz56ecjv2g/9z37+fTNd6+vPb/+/fz++/v/D2CAAg5IYIEGHohgggouyGCD
+Dj4IYYQSTkhhhRZeiGGGGm7IYYcefghiiCKOSGKJJp6IYooqrsjidyrAh9yL+K2nng/31WgjjtzN
+mKOO8lFHxhlJxRjkkEY2tloWy51k2mxAVoaQQkImRiRuIyEmD5ZIomeVYMLIZhMkS6rWm4vJecZl
+cWBsRomUz+Vlymg4bWflYnGWo5FOGZ02FphPYmbkmHQmRxRSgzJXpntl/UlmcIca5ItvilJJx2OS
+TkrZo5k6CgemfBDFKJPF7ZRTIZsMgxUip4qKKFN5UropSKD54xasW9p6a65VBiYmb/dc2qZuwMaH
+laXvZEb+FbKPCKpkm68KutBoTshZWpN6MRqtm6H+8ZmTulabqplhXikuNtBhgqqnM6SLa7jE2nZd
+rGzK5CeUqMxJq6l2YavvTn6yGVG7zGn77aZgvOvuruvGexnCndXLq5YCC2Vsmg2LUzGcTSm8r7fg
+0pUKxMgwdOdY/O4JaMkFf/pqyiv/Jau9CY/asqatOlwnzuM6JvHMOsPsZaQZ/3zzV0NfdnS4HL3c
+KsBZpnIk01NCHbXP1o4MsSjgyAzp0xsddzHRHqOz2289d83wmb46e/aibauZNhXGMWuz3KjNG6Vz
++fooHY/p8Q0ejYDL6PeO9hX+4+DVsRr4DjByPMLjE5v+ILnUJ1Qe9t+Cb855j4d/jrnVfSuOQuii
+N+5555qrbjjrrTt+Y4uyz0577bbfjnvuuu/Oe+++/w588MIPT3zxxh+PfPLKL8+87rWGYLqI0TdP
+ffWwM249oXKDgC/y02cPfvgkkPJ97t137075HKovfvvuQ1KXh9zKJ6V37A7P/vv6739Oa0BFnoRK
+QG9+2PlJMLDnu/zxb4EMxJPJ/DLA/sXvF0EogsgG5hQDkupeCOydAhkIwvcdAYJeqYdfymOMCvLK
+Swe7yKqgkLU4dZB3AaRbCG8YwhrOEGazUaHJNuKboqjQaRBMSDrqBkOu4W9uTAQbDp8IRSV2jFtm
+2Y7+thwIDyzi64VIBKIMvQip+/Gwit5Tkw2jiMbsGcVRPfyhBTdGq7gY6ovoG1UL6ximJSwtVLjT
+YRr/mMZZFctJRZSgLswiR73gMWcsqw0Jx0a8DwJyksAj4CCjRr7T2aSCiQTiIiMGsvg8UorBkyQl
+T7k7S3aNXQJEm2lWxcl9bRGFnWFM2TAIyuOZEpUpOqNHLhgMX9ahXqq02xZTQrCdRQyWdpolq+Yk
+uTdqMoG8BOEnZSSsHYLRRmukFAnFGKOA2ayVsBjhNkUgTVcab5fVNNE1F5fNk33wnY2y2iOBWbQ2
+8rFj9axLNBmZy3W2c4H0vFwXcTmUeXaxmBmUlf3+LkmSdJprn5kb50AvWruCUu6g3gKNQrtZmns+
+dJUU/WE/6bjRgAIUoyx1J0e599I0eNQ+INXVPaEH0ZTeAZzE2QI7WwrU7Hw0KzNdT00rOkqckjSm
+9jynUvMJyaBKVX5MDSJN9jHUj+UzqTCdGtWcOECJyAmf8CqSbWDTxLSiVa1MZA1b5+bWt5ImZHI1
+Dj2YZddgiSyvel1rXc3w17bSNbCiIWxhDUsGwyoWbNdYrGITO1jCJjatRXIsYs/gV7betbJkhZtM
+ndqChkaPJ6fYTdk2g9pyQUmVrJVJQDS6Qnak9pBX1RxXxyfa2o4LmoG7LW6nVdJjgfa3imzc/Ez+
+K9ubKNdiuWytSJz7XKbCliKzxapuE+fJ3k5wHVOoX3AB4tvIAYKnxEUp4Yp7Xj5Od6LLtS5tmYtQ
+8Lo2uq5Fbns5+N7Xei68T82ufl3J2/Tyt78Bxm6BS5fb9HJ0vXI57X2jcUv50pe7842uffOLX/f+
+t3UDPmAS59Xd8X63MR32sD9tO1zxfti4y0phcjEMYdV+dsISpnB9XfzgVuS4xgberk79S+Pdphid
+CRbwkEML3KpKmMH6OC6OYaxjKGtVNdDlMYn1e2ENZ3jLQdbuFxe34grL68hdRa+RyaviQo02g51F
+kpN74WApV0rGFumy0sQs3yxzOcpatjOY/eX+Zbols06wCXSbrwzWPyt5w9hdsHQfHVM0L5POMfPz
+mC09Zj3HWM6XZPToFo3nT7Nv0F7e3KhJ+WNHa5rPe04opUkN4FDf+cZwfnGfWY3pH59am2UGda51
+PZ5dj7glb+4Xp5d66yl3VNax/nVzHx3nZM9ZuCiutrV7vN9gZ3t1xW7xjqct7YoK2dlUZnasV+3q
+Y2cqwsL2tY2vLerrDfu68ea2t40dbmS32nIzfreVkYblJ+d73d8GOLxLzeFtHzzhC1e0qgW+705H
+fJrlJveyLb5sdIN74gSnNsM/DvJ6N1zk2H5dt1Vla45v8tWofjbG+01hjUt80wO/dMgRXvL+nOsc
+CHM1Qs/fw9fhkEtMmrBhovMW2Mn+Vel1Zbpcnf50r7KN6CMpOj6DjoSfZ/3o1dG6Erz+da5Pdexk
+L7vZz472tKt97Wxvu9vfDve4y33udK+73e+O97zrfe9877vf/w74wAt+8IQvvOEPj/jEK37xjG+8
+4x8P+chLfvKUr7zlL4/5zGt+85zvvOfx7sNrXfzzpC89gyQB6zqbfvWsL9Bh7xgyNbd+9rT3zxwr
+3aly1n73vAcdMw7rxt4Lf/iE4+LX2rJH4it/+bLNvSI7JXbmS3/61K++9a+P/exrf/vc7773vw/+
+8It//OQvv/nPj/70q3/97G+/+98P//j+y3/+9K+//e+P//zrf//877///w+AASiAA0iABWiAB4iA
+CaiAC8iADeiADwiBtoc4n+Y6FChvFYg6qaOBG/g6HNiBq3OBE7gua1I1FCd1JKhsXkVa4jaCPRRD
+XoOCKUg1MMeCtVQZ0RdVZQVD/+I1dzImWsMT0AKDUmeCR3I3HHOELXdSahMoP/g0n/GCUdKETvgn
+5MMnJ3MYX4VFRQgoUChIboMmybdSIHOFYqhSfQFoJlWDQGOEYjMLs2A5b7iC6kQzaCJ6ayhLX6VN
+JONAgHVUdSiHu2KFPoaHD5QykrZDsYEq3VQSUzQ5qzUyMniDOTiGNoeFGPE8/DZjQjj+XzhIiXfm
+ibymegeFLBqkiZFYM4XoMXqjiqNHiskSikqIKIX2iDA3K9mSJ9QiiZmAiq3YhrIIjCoYjOrFilQo
+dGamibzoMlxoViozBrhIg8yojDOYjM6hi9XoXZcohf/whVaBWYi4LZXQh7WYhNsiil9Gi6eIe4lY
+KsP4Um6yV+04jKVIV7U4ilVIVKkYKzXGUAZHS3QoGbEniRv0j/tYWpmojqT1h+5yTANZaY5Whc8g
+Q8QEJ/AIjlrTi+aIMkn0M7lgKAupPQTTjWiIexfpDBZhhp+4PQ/Zj2TYUNpYh81CkRsJezKYSUt4
+hi6piDBJkuOYkji5ks5nSUA4JZz+uI1KMpPHyBIjeTVqBpKvcYNRmCTRCJBNmYtPaZV22Ip5cHv8
+xpVEWJVQiZRMKZakYZRS+HNkyYRaqJYtaIRS6Y0zGI/zRmlEJoIKFoIeaIF6mYEg6Jcf+JeNlpd/
+Y0qFGTsY2JeCGZiKCZiNuZeO+ZiMCZnnZZikg2CWaVCYiWSaWV6I6XB8mZiRKZmiGYGlaZqniZqp
+qZqryZqt2WuDOZl4uZikKZux+ZmzGZq5WZu2mZmc2ZueeZm+aZfC2V+wyZupZpy0eZu4uZzHuZlE
+OYUK85UlaJA6uJTSuTXU6IvTeJbwpUw9CDluKTZAWZ3N8TZiWZdulZ7UaY9s6Z3+NqidDjmNmFiR
+ntAtKRiI9qknh+GFgoh842iTqvCR7QmWDmmI79mT6hJKCgpVBkpm5RmewQWODRqSP5mTMWmhFLow
+XyOPzdBCC/VfBVmJBqOS5BlfIPomJeqOGvqd40mX71gL53km8RQscdOi6siRCHqiOMqNDGouwCSi
+TUKCSXmUYLSfRzmHYYmeD3mK98meI+qLKgqhUbqWBEqIDpqhUOqS63mOXfqkPJp6SgpgF+RgTnNv
+6Uil8MiOKcpr9AhHzNgsUjpiSZMRXGqidzqCV7c2ERqkVLqicroXdEozb5qQZNSeikimiSiROEGk
+YMhm+FifPTo5v7dPGNkyWTr+pzJ6oQ6ahy76p16KqSy6oYLqp6DqpTB6qqU4oeeIkBjzhDv5iNMZ
+n1NapUlKq/DplOT4P1+6qTwqXbEoqp7lqakao5qKqz66klwqTFQkWJAzV0Z3V31KosT5msmpm7up
+nMH5OcCprdaKrdn6m9yqU5W5reK6meUKms05mteqruwart7aru46rncZr99qr/farelar/mqr+/K
+nPvqr//qmgNLsAVrsAeLsAl7O8ansNP3U9ZjKaHasID0sNxTsc3Dbi86sfxzaPzRsZOUse62sR9y
+Ho8BI+RUp1KhhlMVshc7sgMSG8N0pUGZi8HET2KRYUxGSS37sh60jMuCZgD+Sqgn6U+xtLLTJqIS
+5bInEkD7+LE9qyASQShBCBX3g0j66KHFZbRDS3CkhkfQtLQu9UqGKrJQmyD+s1O1MpciRrYn9opm
+xkrPMkO0VEVqe7QNdFlm2yIFpoxusap1ezO8lTWdFJVu25U3qjKpeDBhWyI1BKx6CyJJJWltyahW
+dCrRgowf9kKH26s3qXrSAkV+BLm086EvKaYNirIZpyqlK2Lsxbmiij5xG7qjKzwh9oxA8k8eCmtf
+m10+pTFXyrgkEry0GyDd5Q2ykbtmtE1DtFN2YUGY2ranyjzDq3ePi05PO3U+IEzF6rsV8byg25mT
+BpJS+0aryqnTe33mC1P+WUVv+iYE6otUMzss4utNpuu6yGlN6auxWWtUMbFGWZW8S6Gza1hiXHJg
+w4lD1Jt38EtBNOW/NMdN+ysqBYwwFDwXB1ycxCsgDGxV/du+7ssdHAyhFtwuJFy/Ioy4GuyxEjwQ
+7OtpMxfCLEwnJvwyNGxTD6qjKkwjLvy++QjBPVy2UmTD0zTETYXCWqrD9MHDMexxuMbEAdxGAZwJ
+sNoCQOGH2MtZjhVZSWdZr7d0W9x00cqseAV2Z7VXz2pZYNx0XRxXSafGXRzGUwjHbwVZcxzHscfG
+39hEWWzHalXH2/saYsWrxYqSMnxxA6xyhoRviTxpyMqkV/Zy9+iPEMf+v+q2cqaGw8BSxEsGaZyR
+jWsWZmdmyM92xLOGyD9cyfdWc7iBN5Dsb678b6ZMyaWVcqjcY6XcbKfMySAGiqO8iUFMaJncaxh8
+rpucboucyoxMXTksybP2ygZnYzIXRrXsxLfsy3Wmy5A8wGH6Wbh8admMaNesusCMS+AMw7RcawUH
+wgm5otzscs8sy+mMzNW8cSjmzeNmzrkcaUr4yYFGzhh0z738z4c80PaLcvK8yo08nu68o84cy/qM
+0Adtyay8rcRcXsY8yW56buKsptPTzwkX0C6Xzx03zy1MzcccngxdcfDcbNE8yyatziSdbSFdzgX9
+yxqdaRxdZIpm0b/+iaY+PcgeJs2UEW3KjKeQGMmPDM2cHNHJbMv1DNKAbMpYLNKJ2kH1I9W5TNWk
+nNWwTHJ9M9SKnNDL7Mgq7YpevdTa/NJuUNRPjXNvbWQKt3NwPdc8nSNhjRdtTc9wqtQOjdZ+PclN
+jc4TrdBy/dV0bdcjp62SZNYEdtdr3RF6jdKH2s6VLYqN/cuCDdOETdYX2G6f7dmGfdg3F9c7gtex
+FdOXvNCWrV6sDZF3KNGqbNT6FNqKDWyiXdqkXdeL/diazdYnDdXsfNmuXWVq7duRDdznPNqJrdvM
+vdu8XdG4DWan3bypTdFlTdzmNm4ufdzTbN2FbdvFLN3OvdzkHd7RF93bJf3b393ZKZ3dSY3Z2AzZ
+3s3ZAhzd551mNv3Ozw3U5lHGpfPfl3NGA351Rmfgj6XHd7xYUKdZCR51rGE2vVJ1E04eAU45Fl7F
+1htMGv5LHN7hXZ3EIS7iI07iJW7iJ47iKa7iK87iLe7iLw7jMS7jM07jNW7jN47jOa7jO87jPe7j
+Pw7kQV68E+EQhqrAQs6aZmirzYzkQC4aAmmIygHlTS7kP0G3gRJ8VB7kAGCRbQB8uqflTu6Ci4jl
+ehjmPs7laf58XB7Fau6DR56aBQAAOw==
diff --git a/Documentation/DocBook/media/vbi_hsync.gif.b64 b/Documentation/DocBook/media/vbi_hsync.gif.b64
new file mode 100644 (file)
index 0000000..cdafabe
--- /dev/null
@@ -0,0 +1,43 @@
+R0lGODlhBwHJAOcAAAAAAAEBAQICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQoKCgsLCwwMDA0NDQ4O
+Dg8PDxAQEBERERISEhMTExQUFBUVFRYWFhcXFxgYGBkZGRoaGhsbGxwcHB0dHR4eHh8fHyAgICEh
+ISIiIiMjIyQkJCUlJSYmJicnJygoKCkpKSoqKisrKywsLC0tLS4uLi8vLzAwMDExMTIyMjMzMzQ0
+NDU1NTY2Njc3Nzg4ODk5OTo6Ojs7Ozw8PD09PT4+Pj8/P0BAQEFBQUJCQkNDQ0REREVFRUZGRkdH
+R0hISElJSUpKSktLS0xMTE1NTU5OTk9PT1BQUFFRUVJSUlNTU1RUVFVVVVZWVldXV1hYWFlZWVpa
+WltbW1xcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2RkZGVlZWZmZmdnZ2hoaGlpaWpqamtra2xsbG1t
+bW5ubm9vb3BwcHFxcXJycnNzc3R0dHV1dXZ2dnd3d3h4eHl5eXp6ent7e3x8fH19fX5+fn9/f4CA
+gIGBgYKCgoODg4SEhIWFhYaGhoeHh4iIiImJiYqKiouLi4yMjI2NjY6Ojo+Pj5CQkJGRkZKSkpOT
+k5SUlJWVlZaWlpeXl5iYmJmZmZqampubm5ycnJ2dnZ6enp+fn6CgoKGhoaKioqOjo6SkpKWlpaam
+pqenp6ioqKmpqaqqqqurq6ysrK2tra6urq+vr7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5
+ubq6uru7u7y8vL29vb6+vr+/v8DAwMHBwcLCwsPDw8TExMXFxcbGxsfHx8jIyMnJycrKysvLy8zM
+zM3Nzc7Ozs/Pz9DQ0NHR0dLS0tPT09TU1NXV1dbW1tfX19jY2NnZ2dra2tvb29zc3N3d3d7e3t/f
+3+Dg4OHh4eLi4uPj4+Tk5OXl5ebm5ufn5+jo6Onp6erq6uvr6+zs7O3t7e7u7u/v7/Dw8PHx8fLy
+8vPz8/T09PX19fb29vf39/j4+Pn5+fr6+vv7+/z8/P39/f7+/v///ywAAAAABwHJAAAI/gD/CRxI
+sKDBgwgTKlzIsKHDhxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjypxJs6bN
+mzhz6tzJs6fPn0CDCh1KtKjRo0iTKl3KtKnTp1CjSp1KtarVqyQBYN1aVSvXr1C9gh2rVOxCsV4B
+mE2b0GxDt2TjtnWo9l9du2rrar2bl+BavQL3ApZLeC5du3j77g2MF/FAtIv1AoZb+Gfey5gza97M
+ua/ByJ4XI8b8+PHl0ZkrE6XsuCDr1xD5ip7d2m9pv6IZqxYK+zPC3g/T0mabGLdk4YEH7wYK3PZB
+yqyXSw/++3l139OzS4R+Hbtr7eCp/nv/bp18+PMKuZcfj7792fXm47ufz/52fd308zu/X3u/fv3N
++Sfgf/MFaJ98BLpnIH4IJojegv0d6GB7EEI4oXYVdnfhgxoOyOCG4WXIH4jTidggiSV2KOGHKGa3
+oIUtqvaiijEuNyN8NUp344g5EqYef9H1KNePJwYpJFlEehjhkT7iuCKLTMZl4olRgjWlklV+deWT
+WWpJ45JgdrnVllCKOeaXMJrZFZpfqmkVmWG6SRWcRsoZFZl12hkWmzxemCdXeAr555lOgjnof4de
+tSOVG0KWaFl3GVponH52ZumlmGaq6aaY0pjmhJppmRqQbTaKm6gewgnio2uSOumq/jpO+qmDrE5F
+p6AtSZZeSrf2WOtEoZEmm2C/Astnn6CapKtjbClWZki95lhsbLcRtxmlHkVb47TBWcuYcGvxeiyj
+fp7kGbOJEZscStrGyK1T7bb4blPxojgvU4Hiulu+vto4Lpck3rvUoljCuq+npZp6cKGz0uovwwmX
+u3CRESc7sZINJyhwWbJW7PDFXGZM4MZI1WsvyCF7rDHKZYqMKMuSvmqwS5yOypHJAcP0K8k4z5xr
+RTz/C7DPLO2crdDPEr2S0R31rDDNQB/dMbISQ01R0FOT+/TPV0vtqtZVc21s0wjLLONFJG8XNdkQ
+y5z2UNy+TW3XbN8Ho9xBxa3z/to3lz0i3nljBPhbfG+UZMoqG5db2+KJ9O7gDDHd99dUstpscsgR
+x6CzqC0O0uN70z05xVlHdNpwgvUHGWrFef5RppGHPjawNddue3nB5nYufsKmu/vrhL/3kuRqq1Tr
+6pd/G+6HymGLdvC7Dl+46cYD7aywoSleXGOtj5RnnZALP3vx7Bb2J/iyk6++subTZanz2ZJ2te2R
+st8+9NaFHx/x1Jff5GFz0Z9/+Dc3c9EnSK4ryfLG1z89GaY6AjwQARvnQLfBr24XpFrizGSk+tlv
+aOJbXwULxj3/gTB6DBwhCD2oQLBtkIR66mAEVTe9AqqQhCzMigvNhsIbrnCG/m6ZIAB9+MPqwfCB
+IryhDI14QiQ2kIiUyqH3dqhBHtoJfSZs4gu16CYsGpCKYDyinLz4QS5W8YwcjF0WkxbCJxKRjC0M
+oxnlmCU46tA19BPiCO04xZjM8IBq/GL63hjIMloNitiS4uv+aMUxRk5/ihQXIhMJSUaiUUzgq6RM
+LEmhR5qLk2LsoieVBco5YnKUCiwlG2OIyqyoMoNpPIsm/TjJRMKya698JYZiB7kELq2W6OvlLT8H
+TF62MJfM+R3+lnnIAB5zk8zBHOZks7/BqEuXwXwmLS1DzestDnmNud5MsqlDZPKGWMkzT+9CBc33
+5PGd8IynPOfJwkilLp37/gniN8dZyDgOcienCadudnc6anavnT30p/SKokvH9fOO/+RmqxIK0YUi
+EosBNVz2tnnRR9KzUxyFYjAzqpHehZSQbdxYEBEqUhcVM0WTbGhNZBor+7xNj8SMaT7TJc1Tgcug
+Bf2LNZnlKODp1KYCbR64ujcZ0OBxe5FR3jAfqsSdNiujucMnPnl3uaxiraNI3ep3hro8161uNLbB
+G00fNk3abG+aAiXqcKqlGG8Oy6hgLang+HnUjERyiBFV4VpZitKa5rWEgKJjldgpKs5d9KOQjeym
+XkrSMdnzpYatpWY3y1l6NXGB3RlsZ9eDzp7ydKmnW1dAlTnaQ94zruEkS2tUnfra1iIUdRvlHueu
+iS7N2daic1VncEEz3N/6MbVyNU1TV0tUdL3VuF6aKnQhJdrpWve62M2udrfL3e5697vgDa94x0ve
+8lIkIAA7
similarity index 89%
rename from Documentation/DocBook/media.tmpl
rename to Documentation/DocBook/media_api.tmpl
index 88f2cc6..4e8e898 100644 (file)
@@ -8,7 +8,8 @@
 <!ENTITY ie                     "i.&nbsp;e.">
 <!ENTITY fd                     "File descriptor returned by <link linkend='func-open'><function>open()</function></link>.">
 <!ENTITY i2c                    "I<superscript>2</superscript>C">
-<!ENTITY return-value          "<title>Return Value</title><para>On success <returnvalue>0</returnvalue> is returned, on error <returnvalue>-1</returnvalue> and the <varname>errno</varname> variable is set appropriately:</para>">
+<!ENTITY return-value          "<title>Return Value</title><para>On success <returnvalue>0</returnvalue> is returned, on error <returnvalue>-1</returnvalue> and the <varname>errno</varname> variable is set appropriately. The generic error codes are described at the <link linkend='gen-errors'>Generic Error Codes</link> chapter.</para>">
+<!ENTITY return-value-dvb      "<para>RETURN VALUE</para><para>On success <returnvalue>0</returnvalue> is returned, on error <returnvalue>-1</returnvalue> and the <varname>errno</varname> variable is set appropriately. The generic error codes are described at the <link linkend='gen-errors'>Generic Error Codes</link> chapter.</para>">
 <!ENTITY manvol                 "<manvolnum>2</manvolnum>">
 
 <!-- Table templates: structs, structs w/union, defines. -->
@@ -110,6 +111,11 @@ Foundation. A copy of the license is included in the chapter entitled
 &sub-media-controller;
 </part>
 
+<chapter id="gen_errors">
+&sub-gen-errors;
+</chapter>
+
+
 &sub-fdl-appendix;
 
 </book>
diff --git a/Documentation/DocBook/v4l/bayer.pdf b/Documentation/DocBook/v4l/bayer.pdf
deleted file mode 100644 (file)
index 905e60e..0000000
Binary files a/Documentation/DocBook/v4l/bayer.pdf and /dev/null differ
diff --git a/Documentation/DocBook/v4l/bayer.png b/Documentation/DocBook/v4l/bayer.png
deleted file mode 100644 (file)
index 9b15fb2..0000000
Binary files a/Documentation/DocBook/v4l/bayer.png and /dev/null differ
diff --git a/Documentation/DocBook/v4l/crop.gif b/Documentation/DocBook/v4l/crop.gif
deleted file mode 100644 (file)
index 3b9e7d8..0000000
Binary files a/Documentation/DocBook/v4l/crop.gif and /dev/null differ
diff --git a/Documentation/DocBook/v4l/dev-event.xml b/Documentation/DocBook/v4l/dev-event.xml
deleted file mode 100644 (file)
index be5a98f..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-  <title>Event Interface</title>
-
-  <para>The V4L2 event interface provides means for user to get
-  immediately notified on certain conditions taking place on a device.
-  This might include start of frame or loss of signal events, for
-  example.
-  </para>
-
-  <para>To receive events, the events the user is interested in first must
-  be subscribed using the &VIDIOC-SUBSCRIBE-EVENT; ioctl. Once an event is
-  subscribed, the events of subscribed types are dequeueable using the
-  &VIDIOC-DQEVENT; ioctl. Events may be unsubscribed using
-  VIDIOC_UNSUBSCRIBE_EVENT ioctl. The special event type V4L2_EVENT_ALL may
-  be used to unsubscribe all the events the driver supports.</para>
-
-  <para>The event subscriptions and event queues are specific to file
-  handles. Subscribing an event on one file handle does not affect
-  other file handles.
-  </para>
-
-  <para>The information on dequeueable events is obtained by using select or
-  poll system calls on video devices. The V4L2 events use POLLPRI events on
-  poll system call and exceptions on select system call.  </para>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
diff --git a/Documentation/DocBook/v4l/fieldseq_bt.gif b/Documentation/DocBook/v4l/fieldseq_bt.gif
deleted file mode 100644 (file)
index 60e8569..0000000
Binary files a/Documentation/DocBook/v4l/fieldseq_bt.gif and /dev/null differ
diff --git a/Documentation/DocBook/v4l/fieldseq_tb.gif b/Documentation/DocBook/v4l/fieldseq_tb.gif
deleted file mode 100644 (file)
index 718492f..0000000
Binary files a/Documentation/DocBook/v4l/fieldseq_tb.gif and /dev/null differ
diff --git a/Documentation/DocBook/v4l/func-ioctl.xml b/Documentation/DocBook/v4l/func-ioctl.xml
deleted file mode 100644 (file)
index b60fd37..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-<refentry id="func-ioctl">
-  <refmeta>
-    <refentrytitle>V4L2 ioctl()</refentrytitle>
-    &manvol;
-  </refmeta>
-
-  <refnamediv>
-    <refname>v4l2-ioctl</refname>
-    <refpurpose>Program a V4L2 device</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <funcsynopsis>
-      <funcsynopsisinfo>#include &lt;sys/ioctl.h&gt;</funcsynopsisinfo>
-      <funcprototype>
-       <funcdef>int <function>ioctl</function></funcdef>
-       <paramdef>int <parameter>fd</parameter></paramdef>
-       <paramdef>int <parameter>request</parameter></paramdef>
-       <paramdef>void *<parameter>argp</parameter></paramdef>
-      </funcprototype>
-    </funcsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>Arguments</title>
-
-    <variablelist>
-      <varlistentry>
-       <term><parameter>fd</parameter></term>
-       <listitem>
-         <para>&fd;</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><parameter>request</parameter></term>
-       <listitem>
-         <para>V4L2 ioctl request code as defined in the <filename>videodev2.h</filename> header file, for example
-VIDIOC_QUERYCAP.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><parameter>argp</parameter></term>
-       <listitem>
-         <para>Pointer to a function parameter, usually a structure.</para>
-       </listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-
-  <refsect1>
-    <title>Description</title>
-
-    <para>The <function>ioctl()</function> function is used to program
-V4L2 devices. The argument <parameter>fd</parameter> must be an open
-file descriptor. An ioctl <parameter>request</parameter> has encoded
-in it whether the argument is an input, output or read/write
-parameter, and the size of the argument <parameter>argp</parameter> in
-bytes. Macros and defines specifying V4L2 ioctl requests are located
-in the <filename>videodev2.h</filename> header file.
-Applications should use their own copy, not include the version in the
-kernel sources on the system they compile on. All V4L2 ioctl requests,
-their respective function and parameters are specified in <xref
-       linkend="user-func" />.</para>
-  </refsect1>
-
-  <refsect1>
-    <title>Return Value</title>
-
-    <para>On success the <function>ioctl()</function> function returns
-<returnvalue>0</returnvalue> and does not reset the
-<varname>errno</varname> variable. On failure
-<returnvalue>-1</returnvalue> is returned, when the ioctl takes an
-output or read/write parameter it remains unmodified, and the
-<varname>errno</varname> variable is set appropriately. See below for
-possible error codes. Generic errors like <errorcode>EBADF</errorcode>
-or <errorcode>EFAULT</errorcode> are not listed in the sections
-discussing individual ioctl requests.</para>
-    <para>Note ioctls may return undefined error codes. Since errors
-may have side effects such as a driver reset applications should
-abort on unexpected errors.</para>
-
-    <variablelist>
-      <varlistentry>
-       <term><errorcode>EBADF</errorcode></term>
-       <listitem>
-         <para><parameter>fd</parameter> is not a valid open file
-descriptor.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>EBUSY</errorcode></term>
-       <listitem>
-         <para>The property cannot be changed right now. Typically
-this error code is returned when I/O is in progress or the driver
-supports multiple opens and another process locked the property.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>EFAULT</errorcode></term>
-       <listitem>
-         <para><parameter>argp</parameter> references an inaccessible
-memory area.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>ENOTTY</errorcode></term>
-       <listitem>
-         <para><parameter>fd</parameter> is  not  associated  with  a
-character special device.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>EINVAL</errorcode></term>
-       <listitem>
-         <para>The <parameter>request</parameter> or the data pointed
-to by <parameter>argp</parameter> is not valid. This is a very common
-error code, see the individual ioctl requests listed in <xref
-             linkend="user-func" /> for actual causes.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>ENOMEM</errorcode></term>
-       <listitem>
-         <para>Not enough physical or virtual memory was available to
-complete the request.</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><errorcode>ERANGE</errorcode></term>
-       <listitem>
-         <para>The application attempted to set a control with the
-&VIDIOC-S-CTRL; ioctl to a value which is out of bounds.</para>
-       </listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-</refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
diff --git a/Documentation/DocBook/v4l/nv12mt.gif b/Documentation/DocBook/v4l/nv12mt.gif
deleted file mode 100644 (file)
index ef2d4cf..0000000
Binary files a/Documentation/DocBook/v4l/nv12mt.gif and /dev/null differ
diff --git a/Documentation/DocBook/v4l/nv12mt_example.gif b/Documentation/DocBook/v4l/nv12mt_example.gif
deleted file mode 100644 (file)
index df81d68..0000000
Binary files a/Documentation/DocBook/v4l/nv12mt_example.gif and /dev/null differ
diff --git a/Documentation/DocBook/v4l/pipeline.png b/Documentation/DocBook/v4l/pipeline.png
deleted file mode 100644 (file)
index f19b86c..0000000
Binary files a/Documentation/DocBook/v4l/pipeline.png and /dev/null differ
diff --git a/Documentation/DocBook/v4l/vbi_525.gif b/Documentation/DocBook/v4l/vbi_525.gif
deleted file mode 100644 (file)
index 5580b69..0000000
Binary files a/Documentation/DocBook/v4l/vbi_525.gif and /dev/null differ
diff --git a/Documentation/DocBook/v4l/vbi_625.gif b/Documentation/DocBook/v4l/vbi_625.gif
deleted file mode 100644 (file)
index 34e3251..0000000
Binary files a/Documentation/DocBook/v4l/vbi_625.gif and /dev/null differ
diff --git a/Documentation/DocBook/v4l/vbi_hsync.gif b/Documentation/DocBook/v4l/vbi_hsync.gif
deleted file mode 100644 (file)
index b02434d..0000000
Binary files a/Documentation/DocBook/v4l/vbi_hsync.gif and /dev/null differ
diff --git a/Documentation/DocBook/v4l/videodev2.h.xml b/Documentation/DocBook/v4l/videodev2.h.xml
deleted file mode 100644 (file)
index c50536a..0000000
+++ /dev/null
@@ -1,1946 +0,0 @@
-<programlisting>
-/*
- *  Video for Linux Two header file
- *
- *  Copyright (C) 1999-2007 the contributors
- *
- *  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.
- *
- *  Alternatively you can redistribute this file under the terms of the
- *  BSD license as stated below:
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in
- *     the documentation and/or other materials provided with the
- *     distribution.
- *  3. The names of its contributors may not be used to endorse or promote
- *     products derived from this software without specific prior written
- *     permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- *  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *      Header file for v4l or V4L2 drivers and applications
- * with public API.
- * All kernel-specific stuff were moved to media/v4l2-dev.h, so
- * no #if __KERNEL tests are allowed here
- *
- *      See http://linuxtv.org for more info
- *
- *      Author: Bill Dirks &lt;bill@thedirks.org&gt;
- *              Justin Schoeman
- *              Hans Verkuil &lt;hverkuil@xs4all.nl&gt;
- *              et al.
- */
-#ifndef __LINUX_VIDEODEV2_H
-#define __LINUX_VIDEODEV2_H
-
-#ifdef __KERNEL__
-#include &lt;linux/time.h&gt;     /* need struct timeval */
-#else
-#include &lt;sys/time.h&gt;
-#endif
-#include &lt;linux/compiler.h&gt;
-#include &lt;linux/ioctl.h&gt;
-#include &lt;linux/types.h&gt;
-
-/*
- * Common stuff for both V4L1 and V4L2
- * Moved from videodev.h
- */
-#define VIDEO_MAX_FRAME               32
-#define VIDEO_MAX_PLANES               8
-
-#ifndef __KERNEL__
-
-/* These defines are V4L1 specific and should not be used with the V4L2 API!
-   They will be removed from this header in the future. */
-
-#define VID_TYPE_CAPTURE        1       /* Can capture */
-#define VID_TYPE_TUNER          2       /* Can tune */
-#define VID_TYPE_TELETEXT       4       /* Does teletext */
-#define VID_TYPE_OVERLAY        8       /* Overlay onto frame buffer */
-#define VID_TYPE_CHROMAKEY      16      /* Overlay by chromakey */
-#define VID_TYPE_CLIPPING       32      /* Can clip */
-#define VID_TYPE_FRAMERAM       64      /* Uses the frame buffer memory */
-#define VID_TYPE_SCALES         128     /* Scalable */
-#define VID_TYPE_MONOCHROME     256     /* Monochrome only */
-#define VID_TYPE_SUBCAPTURE     512     /* Can capture subareas of the image */
-#define VID_TYPE_MPEG_DECODER   1024    /* Can decode MPEG streams */
-#define VID_TYPE_MPEG_ENCODER   2048    /* Can encode MPEG streams */
-#define VID_TYPE_MJPEG_DECODER  4096    /* Can decode MJPEG streams */
-#define VID_TYPE_MJPEG_ENCODER  8192    /* Can encode MJPEG streams */
-#endif
-
-/*
- *      M I S C E L L A N E O U S
- */
-
-/*  Four-character-code (FOURCC) */
-#define v4l2_fourcc(a, b, c, d)\
-        ((__u32)(a) | ((__u32)(b) &lt;&lt; 8) | ((__u32)(c) &lt;&lt; 16) | ((__u32)(d) &lt;&lt; 24))
-
-/*
- *      E N U M S
- */
-enum <link linkend="v4l2-field">v4l2_field</link> {
-        V4L2_FIELD_ANY           = 0, /* driver can choose from none,
-                                         top, bottom, interlaced
-                                         depending on whatever it thinks
-                                         is approximate ... */
-        V4L2_FIELD_NONE          = 1, /* this device has no fields ... */
-        V4L2_FIELD_TOP           = 2, /* top field only */
-        V4L2_FIELD_BOTTOM        = 3, /* bottom field only */
-        V4L2_FIELD_INTERLACED    = 4, /* both fields interlaced */
-        V4L2_FIELD_SEQ_TB        = 5, /* both fields sequential into one
-                                         buffer, top-bottom order */
-        V4L2_FIELD_SEQ_BT        = 6, /* same as above + bottom-top order */
-        V4L2_FIELD_ALTERNATE     = 7, /* both fields alternating into
-                                         separate buffers */
-        V4L2_FIELD_INTERLACED_TB = 8, /* both fields interlaced, top field
-                                         first and the top field is
-                                         transmitted first */
-        V4L2_FIELD_INTERLACED_BT = 9, /* both fields interlaced, top field
-                                         first and the bottom field is
-                                         transmitted first */
-};
-#define V4L2_FIELD_HAS_TOP(field)       \
-        ((field) == V4L2_FIELD_TOP      ||\
-         (field) == V4L2_FIELD_INTERLACED ||\
-         (field) == V4L2_FIELD_INTERLACED_TB ||\
-         (field) == V4L2_FIELD_INTERLACED_BT ||\
-         (field) == V4L2_FIELD_SEQ_TB   ||\
-         (field) == V4L2_FIELD_SEQ_BT)
-#define V4L2_FIELD_HAS_BOTTOM(field)    \
-        ((field) == V4L2_FIELD_BOTTOM   ||\
-         (field) == V4L2_FIELD_INTERLACED ||\
-         (field) == V4L2_FIELD_INTERLACED_TB ||\
-         (field) == V4L2_FIELD_INTERLACED_BT ||\
-         (field) == V4L2_FIELD_SEQ_TB   ||\
-         (field) == V4L2_FIELD_SEQ_BT)
-#define V4L2_FIELD_HAS_BOTH(field)      \
-        ((field) == V4L2_FIELD_INTERLACED ||\
-         (field) == V4L2_FIELD_INTERLACED_TB ||\
-         (field) == V4L2_FIELD_INTERLACED_BT ||\
-         (field) == V4L2_FIELD_SEQ_TB ||\
-         (field) == V4L2_FIELD_SEQ_BT)
-
-enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> {
-        V4L2_BUF_TYPE_VIDEO_CAPTURE        = 1,
-        V4L2_BUF_TYPE_VIDEO_OUTPUT         = 2,
-        V4L2_BUF_TYPE_VIDEO_OVERLAY        = 3,
-        V4L2_BUF_TYPE_VBI_CAPTURE          = 4,
-        V4L2_BUF_TYPE_VBI_OUTPUT           = 5,
-        V4L2_BUF_TYPE_SLICED_VBI_CAPTURE   = 6,
-        V4L2_BUF_TYPE_SLICED_VBI_OUTPUT    = 7,
-#if 1
-        /* Experimental */
-        V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,
-#endif
-        V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
-        V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE  = 10,
-        V4L2_BUF_TYPE_PRIVATE              = 0x80,
-};
-
-#define V4L2_TYPE_IS_MULTIPLANAR(type)                  \
-        ((type) == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE   \
-         || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-
-#define V4L2_TYPE_IS_OUTPUT(type)                               \
-        ((type) == V4L2_BUF_TYPE_VIDEO_OUTPUT                   \
-         || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE         \
-         || (type) == V4L2_BUF_TYPE_VIDEO_OVERLAY               \
-         || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY        \
-         || (type) == V4L2_BUF_TYPE_VBI_OUTPUT                  \
-         || (type) == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
-
-enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link> {
-        V4L2_TUNER_RADIO             = 1,
-        V4L2_TUNER_ANALOG_TV         = 2,
-        V4L2_TUNER_DIGITAL_TV        = 3,
-};
-
-enum <link linkend="v4l2-memory">v4l2_memory</link> {
-        V4L2_MEMORY_MMAP             = 1,
-        V4L2_MEMORY_USERPTR          = 2,
-        V4L2_MEMORY_OVERLAY          = 3,
-};
-
-/* see also http://vektor.theorem.ca/graphics/ycbcr/ */
-enum <link linkend="v4l2-colorspace">v4l2_colorspace</link> {
-        /* ITU-R 601 -- broadcast NTSC/PAL */
-        V4L2_COLORSPACE_SMPTE170M     = 1,
-
-        /* 1125-Line (US) HDTV */
-        V4L2_COLORSPACE_SMPTE240M     = 2,
-
-        /* HD and modern captures. */
-        V4L2_COLORSPACE_REC709        = 3,
-
-        /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */
-        V4L2_COLORSPACE_BT878         = 4,
-
-        /* These should be useful.  Assume 601 extents. */
-        V4L2_COLORSPACE_470_SYSTEM_M  = 5,
-        V4L2_COLORSPACE_470_SYSTEM_BG = 6,
-
-        /* I know there will be cameras that send this.  So, this is
-         * unspecified chromaticities and full 0-255 on each of the
-         * Y'CbCr components
-         */
-        V4L2_COLORSPACE_JPEG          = 7,
-
-        /* For RGB colourspaces, this is probably a good start. */
-        V4L2_COLORSPACE_SRGB          = 8,
-};
-
-enum <link linkend="v4l2-priority">v4l2_priority</link> {
-        V4L2_PRIORITY_UNSET       = 0,  /* not initialized */
-        V4L2_PRIORITY_BACKGROUND  = 1,
-        V4L2_PRIORITY_INTERACTIVE = 2,
-        V4L2_PRIORITY_RECORD      = 3,
-        V4L2_PRIORITY_DEFAULT     = V4L2_PRIORITY_INTERACTIVE,
-};
-
-struct <link linkend="v4l2-rect">v4l2_rect</link> {
-        __s32   left;
-        __s32   top;
-        __s32   width;
-        __s32   height;
-};
-
-struct <link linkend="v4l2-fract">v4l2_fract</link> {
-        __u32   numerator;
-        __u32   denominator;
-};
-
-/*
- *      D R I V E R   C A P A B I L I T I E S
- */
-struct <link linkend="v4l2-capability">v4l2_capability</link> {
-        __u8    driver[16];     /* i.e.ie; "bttv" */
-        __u8    card[32];       /* i.e.ie; "Hauppauge WinTV" */
-        __u8    bus_info[32];   /* "PCI:" + pci_name(pci_dev) */
-        __u32   version;        /* should use KERNEL_VERSION() */
-        __u32   capabilities;   /* Device capabilities */
-        __u32   reserved[4];
-};
-
-/* Values for 'capabilities' field */
-#define V4L2_CAP_VIDEO_CAPTURE          0x00000001  /* Is a video capture device */
-#define V4L2_CAP_VIDEO_OUTPUT           0x00000002  /* Is a video output device */
-#define V4L2_CAP_VIDEO_OVERLAY          0x00000004  /* Can do video overlay */
-#define V4L2_CAP_VBI_CAPTURE            0x00000010  /* Is a raw VBI capture device */
-#define V4L2_CAP_VBI_OUTPUT             0x00000020  /* Is a raw VBI output device */
-#define V4L2_CAP_SLICED_VBI_CAPTURE     0x00000040  /* Is a sliced VBI capture device */
-#define V4L2_CAP_SLICED_VBI_OUTPUT      0x00000080  /* Is a sliced VBI output device */
-#define V4L2_CAP_RDS_CAPTURE            0x00000100  /* RDS data capture */
-#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY   0x00000200  /* Can do video output overlay */
-#define V4L2_CAP_HW_FREQ_SEEK           0x00000400  /* Can do hardware frequency seek  */
-#define V4L2_CAP_RDS_OUTPUT             0x00000800  /* Is an RDS encoder */
-
-/* Is a video capture device that supports multiplanar formats */
-#define V4L2_CAP_VIDEO_CAPTURE_MPLANE   0x00001000
-/* Is a video output device that supports multiplanar formats */
-#define V4L2_CAP_VIDEO_OUTPUT_MPLANE    0x00002000
-
-#define V4L2_CAP_TUNER                  0x00010000  /* has a tuner */
-#define V4L2_CAP_AUDIO                  0x00020000  /* has audio support */
-#define V4L2_CAP_RADIO                  0x00040000  /* is a radio device */
-#define V4L2_CAP_MODULATOR              0x00080000  /* has a modulator */
-
-#define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
-#define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
-#define V4L2_CAP_STREAMING              0x04000000  /* streaming I/O ioctls */
-
-/*
- *      V I D E O   I M A G E   F O R M A T
- */
-struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
-        __u32                   width;
-        __u32                   height;
-        __u32                   pixelformat;
-        enum <link linkend="v4l2-field">v4l2_field</link>         field;
-        __u32                   bytesperline;   /* for padding, zero if unused */
-        __u32                   sizeimage;
-        enum <link linkend="v4l2-colorspace">v4l2_colorspace</link>    colorspace;
-        __u32                   priv;           /* private data, depends on pixelformat */
-};
-
-/*      Pixel format         FOURCC                          depth  Description  */
-
-/* RGB formats */
-#define <link linkend="V4L2-PIX-FMT-RGB332">V4L2_PIX_FMT_RGB332</link>  v4l2_fourcc('R', 'G', 'B', '1') /*  8  RGB-3-3-2     */
-#define <link linkend="V4L2-PIX-FMT-RGB444">V4L2_PIX_FMT_RGB444</link>  v4l2_fourcc('R', '4', '4', '4') /* 16  xxxxrrrr ggggbbbb */
-#define <link linkend="V4L2-PIX-FMT-RGB555">V4L2_PIX_FMT_RGB555</link>  v4l2_fourcc('R', 'G', 'B', 'O') /* 16  RGB-5-5-5     */
-#define <link linkend="V4L2-PIX-FMT-RGB565">V4L2_PIX_FMT_RGB565</link>  v4l2_fourcc('R', 'G', 'B', 'P') /* 16  RGB-5-6-5     */
-#define <link linkend="V4L2-PIX-FMT-RGB555X">V4L2_PIX_FMT_RGB555X</link> v4l2_fourcc('R', 'G', 'B', 'Q') /* 16  RGB-5-5-5 BE  */
-#define <link linkend="V4L2-PIX-FMT-RGB565X">V4L2_PIX_FMT_RGB565X</link> v4l2_fourcc('R', 'G', 'B', 'R') /* 16  RGB-5-6-5 BE  */
-#define <link linkend="V4L2-PIX-FMT-BGR666">V4L2_PIX_FMT_BGR666</link>  v4l2_fourcc('B', 'G', 'R', 'H') /* 18  BGR-6-6-6     */
-#define <link linkend="V4L2-PIX-FMT-BGR24">V4L2_PIX_FMT_BGR24</link>   v4l2_fourcc('B', 'G', 'R', '3') /* 24  BGR-8-8-8     */
-#define <link linkend="V4L2-PIX-FMT-RGB24">V4L2_PIX_FMT_RGB24</link>   v4l2_fourcc('R', 'G', 'B', '3') /* 24  RGB-8-8-8     */
-#define <link linkend="V4L2-PIX-FMT-BGR32">V4L2_PIX_FMT_BGR32</link>   v4l2_fourcc('B', 'G', 'R', '4') /* 32  BGR-8-8-8-8   */
-#define <link linkend="V4L2-PIX-FMT-RGB32">V4L2_PIX_FMT_RGB32</link>   v4l2_fourcc('R', 'G', 'B', '4') /* 32  RGB-8-8-8-8   */
-
-/* Grey formats */
-#define <link linkend="V4L2-PIX-FMT-GREY">V4L2_PIX_FMT_GREY</link>    v4l2_fourcc('G', 'R', 'E', 'Y') /*  8  Greyscale     */
-#define <link linkend="V4L2-PIX-FMT-Y4">V4L2_PIX_FMT_Y4</link>      v4l2_fourcc('Y', '0', '4', ' ') /*  4  Greyscale     */
-#define <link linkend="V4L2-PIX-FMT-Y6">V4L2_PIX_FMT_Y6</link>      v4l2_fourcc('Y', '0', '6', ' ') /*  6  Greyscale     */
-#define <link linkend="V4L2-PIX-FMT-Y10">V4L2_PIX_FMT_Y10</link>     v4l2_fourcc('Y', '1', '0', ' ') /* 10  Greyscale     */
-#define <link linkend="V4L2-PIX-FMT-Y16">V4L2_PIX_FMT_Y16</link>     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
-
-/* Grey bit-packed formats */
-#define <link linkend="V4L2-PIX-FMT-Y10BPACK">V4L2_PIX_FMT_Y10BPACK</link>    v4l2_fourcc('Y', '1', '0', 'B') /* 10  Greyscale bit-packed */
-
-/* Palette formats */
-#define <link linkend="V4L2-PIX-FMT-PAL8">V4L2_PIX_FMT_PAL8</link>    v4l2_fourcc('P', 'A', 'L', '8') /*  8  8-bit palette */
-
-/* Luminance+Chrominance formats */
-#define <link linkend="V4L2-PIX-FMT-YVU410">V4L2_PIX_FMT_YVU410</link>  v4l2_fourcc('Y', 'V', 'U', '9') /*  9  YVU 4:1:0     */
-#define <link linkend="V4L2-PIX-FMT-YVU420">V4L2_PIX_FMT_YVU420</link>  v4l2_fourcc('Y', 'V', '1', '2') /* 12  YVU 4:2:0     */
-#define <link linkend="V4L2-PIX-FMT-YUYV">V4L2_PIX_FMT_YUYV</link>    v4l2_fourcc('Y', 'U', 'Y', 'V') /* 16  YUV 4:2:2     */
-#define <link linkend="V4L2-PIX-FMT-YYUV">V4L2_PIX_FMT_YYUV</link>    v4l2_fourcc('Y', 'Y', 'U', 'V') /* 16  YUV 4:2:2     */
-#define <link linkend="V4L2-PIX-FMT-YVYU">V4L2_PIX_FMT_YVYU</link>    v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */
-#define <link linkend="V4L2-PIX-FMT-UYVY">V4L2_PIX_FMT_UYVY</link>    v4l2_fourcc('U', 'Y', 'V', 'Y') /* 16  YUV 4:2:2     */
-#define <link linkend="V4L2-PIX-FMT-VYUY">V4L2_PIX_FMT_VYUY</link>    v4l2_fourcc('V', 'Y', 'U', 'Y') /* 16  YUV 4:2:2     */
-#define <link linkend="V4L2-PIX-FMT-YUV422P">V4L2_PIX_FMT_YUV422P</link> v4l2_fourcc('4', '2', '2', 'P') /* 16  YVU422 planar */
-#define <link linkend="V4L2-PIX-FMT-YUV411P">V4L2_PIX_FMT_YUV411P</link> v4l2_fourcc('4', '1', '1', 'P') /* 16  YVU411 planar */
-#define <link linkend="V4L2-PIX-FMT-Y41P">V4L2_PIX_FMT_Y41P</link>    v4l2_fourcc('Y', '4', '1', 'P') /* 12  YUV 4:1:1     */
-#define <link linkend="V4L2-PIX-FMT-YUV444">V4L2_PIX_FMT_YUV444</link>  v4l2_fourcc('Y', '4', '4', '4') /* 16  xxxxyyyy uuuuvvvv */
-#define <link linkend="V4L2-PIX-FMT-YUV555">V4L2_PIX_FMT_YUV555</link>  v4l2_fourcc('Y', 'U', 'V', 'O') /* 16  YUV-5-5-5     */
-#define <link linkend="V4L2-PIX-FMT-YUV565">V4L2_PIX_FMT_YUV565</link>  v4l2_fourcc('Y', 'U', 'V', 'P') /* 16  YUV-5-6-5     */
-#define <link linkend="V4L2-PIX-FMT-YUV32">V4L2_PIX_FMT_YUV32</link>   v4l2_fourcc('Y', 'U', 'V', '4') /* 32  YUV-8-8-8-8   */
-#define <link linkend="V4L2-PIX-FMT-YUV410">V4L2_PIX_FMT_YUV410</link>  v4l2_fourcc('Y', 'U', 'V', '9') /*  9  YUV 4:1:0     */
-#define <link linkend="V4L2-PIX-FMT-YUV420">V4L2_PIX_FMT_YUV420</link>  v4l2_fourcc('Y', 'U', '1', '2') /* 12  YUV 4:2:0     */
-#define <link linkend="V4L2-PIX-FMT-HI240">V4L2_PIX_FMT_HI240</link>   v4l2_fourcc('H', 'I', '2', '4') /*  8  8-bit color   */
-#define <link linkend="V4L2-PIX-FMT-HM12">V4L2_PIX_FMT_HM12</link>    v4l2_fourcc('H', 'M', '1', '2') /*  8  YUV 4:2:0 16x16 macroblocks */
-#define <link linkend="V4L2-PIX-FMT-M420">V4L2_PIX_FMT_M420</link>    v4l2_fourcc('M', '4', '2', '0') /* 12  YUV 4:2:0 2 lines y, 1 line uv interleaved */
-
-/* two planes -- one Y, one Cr + Cb interleaved  */
-#define <link linkend="V4L2-PIX-FMT-NV12">V4L2_PIX_FMT_NV12</link>    v4l2_fourcc('N', 'V', '1', '2') /* 12  Y/CbCr 4:2:0  */
-#define <link linkend="V4L2-PIX-FMT-NV21">V4L2_PIX_FMT_NV21</link>    v4l2_fourcc('N', 'V', '2', '1') /* 12  Y/CrCb 4:2:0  */
-#define <link linkend="V4L2-PIX-FMT-NV16">V4L2_PIX_FMT_NV16</link>    v4l2_fourcc('N', 'V', '1', '6') /* 16  Y/CbCr 4:2:2  */
-#define <link linkend="V4L2-PIX-FMT-NV61">V4L2_PIX_FMT_NV61</link>    v4l2_fourcc('N', 'V', '6', '1') /* 16  Y/CrCb 4:2:2  */
-
-/* two non contiguous planes - one Y, one Cr + Cb interleaved  */
-#define <link linkend="V4L2-PIX-FMT-NV12M">V4L2_PIX_FMT_NV12M</link>   v4l2_fourcc('N', 'M', '1', '2') /* 12  Y/CbCr 4:2:0  */
-#define <link linkend="V4L2-PIX-FMT-NV12MT">V4L2_PIX_FMT_NV12MT</link>  v4l2_fourcc('T', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 64x32 macroblocks */
-
-/* three non contiguous planes - Y, Cb, Cr */
-#define <link linkend="V4L2-PIX-FMT-YUV420M">V4L2_PIX_FMT_YUV420M</link> v4l2_fourcc('Y', 'M', '1', '2') /* 12  YUV420 planar */
-
-/* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
-#define <link linkend="V4L2-PIX-FMT-SBGGR8">V4L2_PIX_FMT_SBGGR8</link>  v4l2_fourcc('B', 'A', '8', '1') /*  8  BGBG.. GRGR.. */
-#define <link linkend="V4L2-PIX-FMT-SGBRG8">V4L2_PIX_FMT_SGBRG8</link>  v4l2_fourcc('G', 'B', 'R', 'G') /*  8  GBGB.. RGRG.. */
-#define <link linkend="V4L2-PIX-FMT-SGRBG8">V4L2_PIX_FMT_SGRBG8</link>  v4l2_fourcc('G', 'R', 'B', 'G') /*  8  GRGR.. BGBG.. */
-#define <link linkend="V4L2-PIX-FMT-SRGGB8">V4L2_PIX_FMT_SRGGB8</link>  v4l2_fourcc('R', 'G', 'G', 'B') /*  8  RGRG.. GBGB.. */
-#define <link linkend="V4L2-PIX-FMT-SBGGR10">V4L2_PIX_FMT_SBGGR10</link> v4l2_fourcc('B', 'G', '1', '0') /* 10  BGBG.. GRGR.. */
-#define <link linkend="V4L2-PIX-FMT-SGBRG10">V4L2_PIX_FMT_SGBRG10</link> v4l2_fourcc('G', 'B', '1', '0') /* 10  GBGB.. RGRG.. */
-#define <link linkend="V4L2-PIX-FMT-SGRBG10">V4L2_PIX_FMT_SGRBG10</link> v4l2_fourcc('B', 'A', '1', '0') /* 10  GRGR.. BGBG.. */
-#define <link linkend="V4L2-PIX-FMT-SRGGB10">V4L2_PIX_FMT_SRGGB10</link> v4l2_fourcc('R', 'G', '1', '0') /* 10  RGRG.. GBGB.. */
-        /* 10bit raw bayer DPCM compressed to 8 bits */
-#define <link linkend="V4L2-PIX-FMT-SGRBG10DPCM8">V4L2_PIX_FMT_SGRBG10DPCM8</link> v4l2_fourcc('B', 'D', '1', '0')
-        /*
-         * 10bit raw bayer, expanded to 16 bits
-         * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb...
-         */
-#define <link linkend="V4L2-PIX-FMT-SBGGR16">V4L2_PIX_FMT_SBGGR16</link> v4l2_fourcc('B', 'Y', 'R', '2') /* 16  BGBG.. GRGR.. */
-
-/* compressed formats */
-#define <link linkend="V4L2-PIX-FMT-MJPEG">V4L2_PIX_FMT_MJPEG</link>    v4l2_fourcc('M', 'J', 'P', 'G') /* Motion-JPEG   */
-#define <link linkend="V4L2-PIX-FMT-JPEG">V4L2_PIX_FMT_JPEG</link>     v4l2_fourcc('J', 'P', 'E', 'G') /* JFIF JPEG     */
-#define <link linkend="V4L2-PIX-FMT-DV">V4L2_PIX_FMT_DV</link>       v4l2_fourcc('d', 'v', 's', 'd') /* 1394          */
-#define <link linkend="V4L2-PIX-FMT-MPEG">V4L2_PIX_FMT_MPEG</link>     v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4    */
-
-/*  Vendor-specific formats   */
-#define <link linkend="V4L2-PIX-FMT-CPIA1">V4L2_PIX_FMT_CPIA1</link>    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
-#define <link linkend="V4L2-PIX-FMT-WNVA">V4L2_PIX_FMT_WNVA</link>     v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */
-#define <link linkend="V4L2-PIX-FMT-SN9C10X">V4L2_PIX_FMT_SN9C10X</link>  v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */
-#define <link linkend="V4L2-PIX-FMT-SN9C20X-I420">V4L2_PIX_FMT_SN9C20X_I420</link> v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */
-#define <link linkend="V4L2-PIX-FMT-PWC1">V4L2_PIX_FMT_PWC1</link>     v4l2_fourcc('P', 'W', 'C', '1') /* pwc older webcam */
-#define <link linkend="V4L2-PIX-FMT-PWC2">V4L2_PIX_FMT_PWC2</link>     v4l2_fourcc('P', 'W', 'C', '2') /* pwc newer webcam */
-#define <link linkend="V4L2-PIX-FMT-ET61X251">V4L2_PIX_FMT_ET61X251</link> v4l2_fourcc('E', '6', '2', '5') /* ET61X251 compression */
-#define <link linkend="V4L2-PIX-FMT-SPCA501">V4L2_PIX_FMT_SPCA501</link>  v4l2_fourcc('S', '5', '0', '1') /* YUYV per line */
-#define <link linkend="V4L2-PIX-FMT-SPCA505">V4L2_PIX_FMT_SPCA505</link>  v4l2_fourcc('S', '5', '0', '5') /* YYUV per line */
-#define <link linkend="V4L2-PIX-FMT-SPCA508">V4L2_PIX_FMT_SPCA508</link>  v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */
-#define <link linkend="V4L2-PIX-FMT-SPCA561">V4L2_PIX_FMT_SPCA561</link>  v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
-#define <link linkend="V4L2-PIX-FMT-PAC207">V4L2_PIX_FMT_PAC207</link>   v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
-#define <link linkend="V4L2-PIX-FMT-MR97310A">V4L2_PIX_FMT_MR97310A</link> v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
-#define <link linkend="V4L2-PIX-FMT-SN9C2028">V4L2_PIX_FMT_SN9C2028</link> v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */
-#define <link linkend="V4L2-PIX-FMT-SQ905C">V4L2_PIX_FMT_SQ905C</link>   v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
-#define <link linkend="V4L2-PIX-FMT-PJPG">V4L2_PIX_FMT_PJPG</link>     v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
-#define <link linkend="V4L2-PIX-FMT-OV511">V4L2_PIX_FMT_OV511</link>    v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */
-#define <link linkend="V4L2-PIX-FMT-OV518">V4L2_PIX_FMT_OV518</link>    v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */
-#define <link linkend="V4L2-PIX-FMT-STV0680">V4L2_PIX_FMT_STV0680</link>  v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */
-#define <link linkend="V4L2-PIX-FMT-TM6000">V4L2_PIX_FMT_TM6000</link>   v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */
-#define <link linkend="V4L2-PIX-FMT-CIT-YYVYUY">V4L2_PIX_FMT_CIT_YYVYUY</link> v4l2_fourcc('C', 'I', 'T', 'V') /* one line of Y then 1 line of VYUY */
-#define <link linkend="V4L2-PIX-FMT-KONICA420">V4L2_PIX_FMT_KONICA420</link>  v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
-
-/*
- *      F O R M A T   E N U M E R A T I O N
- */
-struct <link linkend="v4l2-fmtdesc">v4l2_fmtdesc</link> {
-        __u32               index;             /* Format number      */
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link>  type;              /* buffer type        */
-        __u32               flags;
-        __u8                description[32];   /* Description string */
-        __u32               pixelformat;       /* Format fourcc      */
-        __u32               reserved[4];
-};
-
-#define V4L2_FMT_FLAG_COMPRESSED 0x0001
-#define V4L2_FMT_FLAG_EMULATED   0x0002
-
-#if 1
-        /* Experimental Frame Size and frame rate enumeration */
-/*
- *      F R A M E   S I Z E   E N U M E R A T I O N
- */
-enum <link linkend="v4l2-frmsizetypes">v4l2_frmsizetypes</link> {
-        V4L2_FRMSIZE_TYPE_DISCRETE      = 1,
-        V4L2_FRMSIZE_TYPE_CONTINUOUS    = 2,
-        V4L2_FRMSIZE_TYPE_STEPWISE      = 3,
-};
-
-struct <link linkend="v4l2-frmsize-discrete">v4l2_frmsize_discrete</link> {
-        __u32                   width;          /* Frame width [pixel] */
-        __u32                   height;         /* Frame height [pixel] */
-};
-
-struct <link linkend="v4l2-frmsize-stepwise">v4l2_frmsize_stepwise</link> {
-        __u32                   min_width;      /* Minimum frame width [pixel] */
-        __u32                   max_width;      /* Maximum frame width [pixel] */
-        __u32                   step_width;     /* Frame width step size [pixel] */
-        __u32                   min_height;     /* Minimum frame height [pixel] */
-        __u32                   max_height;     /* Maximum frame height [pixel] */
-        __u32                   step_height;    /* Frame height step size [pixel] */
-};
-
-struct <link linkend="v4l2-frmsizeenum">v4l2_frmsizeenum</link> {
-        __u32                   index;          /* Frame size number */
-        __u32                   pixel_format;   /* Pixel format */
-        __u32                   type;           /* Frame size type the device supports. */
-
-        union {                                 /* Frame size */
-                struct <link linkend="v4l2-frmsize-discrete">v4l2_frmsize_discrete</link>    discrete;
-                struct <link linkend="v4l2-frmsize-stepwise">v4l2_frmsize_stepwise</link>    stepwise;
-        };
-
-        __u32   reserved[2];                    /* Reserved space for future use */
-};
-
-/*
- *      F R A M E   R A T E   E N U M E R A T I O N
- */
-enum <link linkend="v4l2-frmivaltypes">v4l2_frmivaltypes</link> {
-        V4L2_FRMIVAL_TYPE_DISCRETE      = 1,
-        V4L2_FRMIVAL_TYPE_CONTINUOUS    = 2,
-        V4L2_FRMIVAL_TYPE_STEPWISE      = 3,
-};
-
-struct <link linkend="v4l2-frmival-stepwise">v4l2_frmival_stepwise</link> {
-        struct <link linkend="v4l2-fract">v4l2_fract</link>       min;            /* Minimum frame interval [s] */
-        struct <link linkend="v4l2-fract">v4l2_fract</link>       max;            /* Maximum frame interval [s] */
-        struct <link linkend="v4l2-fract">v4l2_fract</link>       step;           /* Frame interval step size [s] */
-};
-
-struct <link linkend="v4l2-frmivalenum">v4l2_frmivalenum</link> {
-        __u32                   index;          /* Frame format index */
-        __u32                   pixel_format;   /* Pixel format */
-        __u32                   width;          /* Frame width */
-        __u32                   height;         /* Frame height */
-        __u32                   type;           /* Frame interval type the device supports. */
-
-        union {                                 /* Frame interval */
-                struct <link linkend="v4l2-fract">v4l2_fract</link>               discrete;
-                struct <link linkend="v4l2-frmival-stepwise">v4l2_frmival_stepwise</link>    stepwise;
-        };
-
-        __u32   reserved[2];                    /* Reserved space for future use */
-};
-#endif
-
-/*
- *      T I M E C O D E
- */
-struct <link linkend="v4l2-timecode">v4l2_timecode</link> {
-        __u32   type;
-        __u32   flags;
-        __u8    frames;
-        __u8    seconds;
-        __u8    minutes;
-        __u8    hours;
-        __u8    userbits[4];
-};
-
-/*  Type  */
-#define V4L2_TC_TYPE_24FPS              1
-#define V4L2_TC_TYPE_25FPS              2
-#define V4L2_TC_TYPE_30FPS              3
-#define V4L2_TC_TYPE_50FPS              4
-#define V4L2_TC_TYPE_60FPS              5
-
-/*  Flags  */
-#define V4L2_TC_FLAG_DROPFRAME          0x0001 /* "drop-frame" mode */
-#define V4L2_TC_FLAG_COLORFRAME         0x0002
-#define V4L2_TC_USERBITS_field          0x000C
-#define V4L2_TC_USERBITS_USERDEFINED    0x0000
-#define V4L2_TC_USERBITS_8BITCHARS      0x0008
-/* The above is based on SMPTE timecodes */
-
-struct <link linkend="v4l2-jpegcompression">v4l2_jpegcompression</link> {
-        int quality;
-
-        int  APPn;              /* Number of APP segment to be written,
-                                 * must be 0..15 */
-        int  APP_len;           /* Length of data in JPEG APPn segment */
-        char APP_data[60];      /* Data in the JPEG APPn segment. */
-
-        int  COM_len;           /* Length of data in JPEG COM segment */
-        char COM_data[60];      /* Data in JPEG COM segment */
-
-        __u32 jpeg_markers;     /* Which markers should go into the JPEG
-                                 * output. Unless you exactly know what
-                                 * you do, leave them untouched.
-                                 * Inluding less markers will make the
-                                 * resulting code smaller, but there will
-                                 * be fewer applications which can read it.
-                                 * The presence of the APP and COM marker
-                                 * is influenced by APP_len and COM_len
-                                 * ONLY, not by this property! */
-
-#define V4L2_JPEG_MARKER_DHT (1&lt;&lt;3)    /* Define Huffman Tables */
-#define V4L2_JPEG_MARKER_DQT (1&lt;&lt;4)    /* Define Quantization Tables */
-#define V4L2_JPEG_MARKER_DRI (1&lt;&lt;5)    /* Define Restart Interval */
-#define V4L2_JPEG_MARKER_COM (1&lt;&lt;6)    /* Comment segment */
-#define V4L2_JPEG_MARKER_APP (1&lt;&lt;7)    /* App segment, driver will
-                                        * allways use APP0 */
-};
-
-/*
- *      M E M O R Y - M A P P I N G   B U F F E R S
- */
-struct <link linkend="v4l2-requestbuffers">v4l2_requestbuffers</link> {
-        __u32                   count;
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link>      type;
-        enum <link linkend="v4l2-memory">v4l2_memory</link>        memory;
-        __u32                   reserved[2];
-};
-
-/**
- * struct <link linkend="v4l2-plane">v4l2_plane</link> - plane info for multi-planar buffers
- * @bytesused:          number of bytes occupied by data in the plane (payload)
- * @length:             size of this plane (NOT the payload) in bytes
- * @mem_offset:         when memory in the associated struct <link linkend="v4l2-buffer">v4l2_buffer</link> is
- *                      V4L2_MEMORY_MMAP, equals the offset from the start of
- *                      the device memory for this plane (or is a "cookie" that
- *                      should be passed to mmap() called on the video node)
- * @userptr:            when memory is V4L2_MEMORY_USERPTR, a userspace pointer
- *                      pointing to this plane
- * @data_offset:        offset in the plane to the start of data; usually 0,
- *                      unless there is a header in front of the data
- *
- * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer
- * with two planes can have one plane for Y, and another for interleaved CbCr
- * components. Each plane can reside in a separate memory buffer, or even in
- * a completely separate memory node (e.g. in embedded devices).
- */
-struct <link linkend="v4l2-plane">v4l2_plane</link> {
-        __u32                   bytesused;
-        __u32                   length;
-        union {
-                __u32           mem_offset;
-                unsigned long   userptr;
-        } m;
-        __u32                   data_offset;
-        __u32                   reserved[11];
-};
-
-/**
- * struct <link linkend="v4l2-buffer">v4l2_buffer</link> - video buffer info
- * @index:      id number of the buffer
- * @type:       buffer type (type == *_MPLANE for multiplanar buffers)
- * @bytesused:  number of bytes occupied by data in the buffer (payload);
- *              unused (set to 0) for multiplanar buffers
- * @flags:      buffer informational flags
- * @field:      field order of the image in the buffer
- * @timestamp:  frame timestamp
- * @timecode:   frame timecode
- * @sequence:   sequence count of this frame
- * @memory:     the method, in which the actual video data is passed
- * @offset:     for non-multiplanar buffers with memory == V4L2_MEMORY_MMAP;
- *              offset from the start of the device memory for this plane,
- *              (or a "cookie" that should be passed to mmap() as offset)
- * @userptr:    for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR;
- *              a userspace pointer pointing to this buffer
- * @planes:     for multiplanar buffers; userspace pointer to the array of plane
- *              info structs for this buffer
- * @length:     size in bytes of the buffer (NOT its payload) for single-plane
- *              buffers (when type != *_MPLANE); number of elements in the
- *              planes array for multi-plane buffers
- * @input:      input number from which the video data has has been captured
- *
- * Contains data exchanged by application and driver using one of the Streaming
- * I/O methods.
- */
-struct <link linkend="v4l2-buffer">v4l2_buffer</link> {
-        __u32                   index;
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link>      type;
-        __u32                   bytesused;
-        __u32                   flags;
-        enum <link linkend="v4l2-field">v4l2_field</link>         field;
-        struct timeval          timestamp;
-        struct <link linkend="v4l2-timecode">v4l2_timecode</link>    timecode;
-        __u32                   sequence;
-
-        /* memory location */
-        enum <link linkend="v4l2-memory">v4l2_memory</link>        memory;
-        union {
-                __u32           offset;
-                unsigned long   userptr;
-                struct <link linkend="v4l2-plane">v4l2_plane</link> *planes;
-        } m;
-        __u32                   length;
-        __u32                   input;
-        __u32                   reserved;
-};
-
-/*  Flags for 'flags' field */
-#define V4L2_BUF_FLAG_MAPPED    0x0001  /* Buffer is mapped (flag) */
-#define V4L2_BUF_FLAG_QUEUED    0x0002  /* Buffer is queued for processing */
-#define V4L2_BUF_FLAG_DONE      0x0004  /* Buffer is ready */
-#define V4L2_BUF_FLAG_KEYFRAME  0x0008  /* Image is a keyframe (I-frame) */
-#define V4L2_BUF_FLAG_PFRAME    0x0010  /* Image is a P-frame */
-#define V4L2_BUF_FLAG_BFRAME    0x0020  /* Image is a B-frame */
-/* Buffer is ready, but the data contained within is corrupted. */
-#define V4L2_BUF_FLAG_ERROR     0x0040
-#define V4L2_BUF_FLAG_TIMECODE  0x0100  /* timecode field is valid */
-#define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
-
-/*
- *      O V E R L A Y   P R E V I E W
- */
-struct <link linkend="v4l2-framebuffer">v4l2_framebuffer</link> {
-        __u32                   capability;
-        __u32                   flags;
-/* FIXME: in theory we should pass something like PCI device + memory
- * region + offset instead of some physical address */
-        void                    *base;
-        struct <link linkend="v4l2-pix-format">v4l2_pix_format</link>  fmt;
-};
-/*  Flags for the 'capability' field. Read only */
-#define V4L2_FBUF_CAP_EXTERNOVERLAY     0x0001
-#define V4L2_FBUF_CAP_CHROMAKEY         0x0002
-#define V4L2_FBUF_CAP_LIST_CLIPPING     0x0004
-#define V4L2_FBUF_CAP_BITMAP_CLIPPING   0x0008
-#define V4L2_FBUF_CAP_LOCAL_ALPHA       0x0010
-#define V4L2_FBUF_CAP_GLOBAL_ALPHA      0x0020
-#define V4L2_FBUF_CAP_LOCAL_INV_ALPHA   0x0040
-#define V4L2_FBUF_CAP_SRC_CHROMAKEY     0x0080
-/*  Flags for the 'flags' field. */
-#define V4L2_FBUF_FLAG_PRIMARY          0x0001
-#define V4L2_FBUF_FLAG_OVERLAY          0x0002
-#define V4L2_FBUF_FLAG_CHROMAKEY        0x0004
-#define V4L2_FBUF_FLAG_LOCAL_ALPHA      0x0008
-#define V4L2_FBUF_FLAG_GLOBAL_ALPHA     0x0010
-#define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA  0x0020
-#define V4L2_FBUF_FLAG_SRC_CHROMAKEY    0x0040
-
-struct <link linkend="v4l2-clip">v4l2_clip</link> {
-        struct <link linkend="v4l2-rect">v4l2_rect</link>        c;
-        struct <link linkend="v4l2-clip">v4l2_clip</link>        __user *next;
-};
-
-struct <link linkend="v4l2-window">v4l2_window</link> {
-        struct <link linkend="v4l2-rect">v4l2_rect</link>        w;
-        enum <link linkend="v4l2-field">v4l2_field</link>         field;
-        __u32                   chromakey;
-        struct <link linkend="v4l2-clip">v4l2_clip</link>        __user *clips;
-        __u32                   clipcount;
-        void                    __user *bitmap;
-        __u8                    global_alpha;
-};
-
-/*
- *      C A P T U R E   P A R A M E T E R S
- */
-struct <link linkend="v4l2-captureparm">v4l2_captureparm</link> {
-        __u32              capability;    /*  Supported modes */
-        __u32              capturemode;   /*  Current mode */
-        struct <link linkend="v4l2-fract">v4l2_fract</link>  timeperframe;  /*  Time per frame in .1us units */
-        __u32              extendedmode;  /*  Driver-specific extensions */
-        __u32              readbuffers;   /*  # of buffers for read */
-        __u32              reserved[4];
-};
-
-/*  Flags for 'capability' and 'capturemode' fields */
-#define V4L2_MODE_HIGHQUALITY   0x0001  /*  High quality imaging mode */
-#define V4L2_CAP_TIMEPERFRAME   0x1000  /*  timeperframe field is supported */
-
-struct <link linkend="v4l2-outputparm">v4l2_outputparm</link> {
-        __u32              capability;   /*  Supported modes */
-        __u32              outputmode;   /*  Current mode */
-        struct <link linkend="v4l2-fract">v4l2_fract</link>  timeperframe; /*  Time per frame in seconds */
-        __u32              extendedmode; /*  Driver-specific extensions */
-        __u32              writebuffers; /*  # of buffers for write */
-        __u32              reserved[4];
-};
-
-/*
- *      I N P U T   I M A G E   C R O P P I N G
- */
-struct <link linkend="v4l2-cropcap">v4l2_cropcap</link> {
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link>      type;
-        struct <link linkend="v4l2-rect">v4l2_rect</link>        bounds;
-        struct <link linkend="v4l2-rect">v4l2_rect</link>        defrect;
-        struct <link linkend="v4l2-fract">v4l2_fract</link>       pixelaspect;
-};
-
-struct <link linkend="v4l2-crop">v4l2_crop</link> {
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link>      type;
-        struct <link linkend="v4l2-rect">v4l2_rect</link>        c;
-};
-
-/*
- *      A N A L O G   V I D E O   S T A N D A R D
- */
-
-typedef __u64 v4l2_std_id;
-
-/* one bit for each */
-#define V4L2_STD_PAL_B          ((v4l2_std_id)0x00000001)
-#define V4L2_STD_PAL_B1         ((v4l2_std_id)0x00000002)
-#define V4L2_STD_PAL_G          ((v4l2_std_id)0x00000004)
-#define V4L2_STD_PAL_H          ((v4l2_std_id)0x00000008)
-#define V4L2_STD_PAL_I          ((v4l2_std_id)0x00000010)
-#define V4L2_STD_PAL_D          ((v4l2_std_id)0x00000020)
-#define V4L2_STD_PAL_D1         ((v4l2_std_id)0x00000040)
-#define V4L2_STD_PAL_K          ((v4l2_std_id)0x00000080)
-
-#define V4L2_STD_PAL_M          ((v4l2_std_id)0x00000100)
-#define V4L2_STD_PAL_N          ((v4l2_std_id)0x00000200)
-#define V4L2_STD_PAL_Nc         ((v4l2_std_id)0x00000400)
-#define V4L2_STD_PAL_60         ((v4l2_std_id)0x00000800)
-
-#define V4L2_STD_NTSC_M         ((v4l2_std_id)0x00001000)
-#define V4L2_STD_NTSC_M_JP      ((v4l2_std_id)0x00002000)
-#define V4L2_STD_NTSC_443       ((v4l2_std_id)0x00004000)
-#define V4L2_STD_NTSC_M_KR      ((v4l2_std_id)0x00008000)
-
-#define V4L2_STD_SECAM_B        ((v4l2_std_id)0x00010000)
-#define V4L2_STD_SECAM_D        ((v4l2_std_id)0x00020000)
-#define V4L2_STD_SECAM_G        ((v4l2_std_id)0x00040000)
-#define V4L2_STD_SECAM_H        ((v4l2_std_id)0x00080000)
-#define V4L2_STD_SECAM_K        ((v4l2_std_id)0x00100000)
-#define V4L2_STD_SECAM_K1       ((v4l2_std_id)0x00200000)
-#define V4L2_STD_SECAM_L        ((v4l2_std_id)0x00400000)
-#define V4L2_STD_SECAM_LC       ((v4l2_std_id)0x00800000)
-
-/* ATSC/HDTV */
-#define V4L2_STD_ATSC_8_VSB     ((v4l2_std_id)0x01000000)
-#define V4L2_STD_ATSC_16_VSB    ((v4l2_std_id)0x02000000)
-
-/* FIXME:
-   Although std_id is 64 bits, there is an issue on PPC32 architecture that
-   makes switch(__u64) to break. So, there's a hack on v4l2-common.c rounding
-   this value to 32 bits.
-   As, currently, the max value is for V4L2_STD_ATSC_16_VSB (30 bits wide),
-   it should work fine. However, if needed to add more than two standards,
-   v4l2-common.c should be fixed.
- */
-
-/* some merged standards */
-#define V4L2_STD_MN     (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC)
-#define V4L2_STD_B      (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B)
-#define V4L2_STD_GH     (V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H)
-#define V4L2_STD_DK     (V4L2_STD_PAL_DK|V4L2_STD_SECAM_DK)
-
-/* some common needed stuff */
-#define V4L2_STD_PAL_BG         (V4L2_STD_PAL_B         |\
-                                 V4L2_STD_PAL_B1        |\
-                                 V4L2_STD_PAL_G)
-#define V4L2_STD_PAL_DK         (V4L2_STD_PAL_D         |\
-                                 V4L2_STD_PAL_D1        |\
-                                 V4L2_STD_PAL_K)
-#define V4L2_STD_PAL            (V4L2_STD_PAL_BG        |\
-                                 V4L2_STD_PAL_DK        |\
-                                 V4L2_STD_PAL_H         |\
-                                 V4L2_STD_PAL_I)
-#define V4L2_STD_NTSC           (V4L2_STD_NTSC_M        |\
-                                 V4L2_STD_NTSC_M_JP     |\
-                                 V4L2_STD_NTSC_M_KR)
-#define V4L2_STD_SECAM_DK       (V4L2_STD_SECAM_D       |\
-                                 V4L2_STD_SECAM_K       |\
-                                 V4L2_STD_SECAM_K1)
-#define V4L2_STD_SECAM          (V4L2_STD_SECAM_B       |\
-                                 V4L2_STD_SECAM_G       |\
-                                 V4L2_STD_SECAM_H       |\
-                                 V4L2_STD_SECAM_DK      |\
-                                 V4L2_STD_SECAM_L       |\
-                                 V4L2_STD_SECAM_LC)
-
-#define V4L2_STD_525_60         (V4L2_STD_PAL_M         |\
-                                 V4L2_STD_PAL_60        |\
-                                 V4L2_STD_NTSC          |\
-                                 V4L2_STD_NTSC_443)
-#define V4L2_STD_625_50         (V4L2_STD_PAL           |\
-                                 V4L2_STD_PAL_N         |\
-                                 V4L2_STD_PAL_Nc        |\
-                                 V4L2_STD_SECAM)
-#define V4L2_STD_ATSC           (V4L2_STD_ATSC_8_VSB    |\
-                                 V4L2_STD_ATSC_16_VSB)
-
-#define V4L2_STD_UNKNOWN        0
-#define V4L2_STD_ALL            (V4L2_STD_525_60        |\
-                                 V4L2_STD_625_50)
-
-struct <link linkend="v4l2-standard">v4l2_standard</link> {
-        __u32                index;
-        v4l2_std_id          id;
-        __u8                 name[24];
-        struct <link linkend="v4l2-fract">v4l2_fract</link>    frameperiod; /* Frames, not fields */
-        __u32                framelines;
-        __u32                reserved[4];
-};
-
-/*
- *      V I D E O       T I M I N G S   D V     P R E S E T
- */
-struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link> {
-        __u32   preset;
-        __u32   reserved[4];
-};
-
-/*
- *      D V     P R E S E T S   E N U M E R A T I O N
- */
-struct <link linkend="v4l2-dv-enum-preset">v4l2_dv_enum_preset</link> {
-        __u32   index;
-        __u32   preset;
-        __u8    name[32]; /* Name of the preset timing */
-        __u32   width;
-        __u32   height;
-        __u32   reserved[4];
-};
-
-/*
- *      D V     P R E S E T     V A L U E S
- */
-#define         V4L2_DV_INVALID         0
-#define         V4L2_DV_480P59_94       1 /* BT.1362 */
-#define         V4L2_DV_576P50          2 /* BT.1362 */
-#define         V4L2_DV_720P24          3 /* SMPTE 296M */
-#define         V4L2_DV_720P25          4 /* SMPTE 296M */
-#define         V4L2_DV_720P30          5 /* SMPTE 296M */
-#define         V4L2_DV_720P50          6 /* SMPTE 296M */
-#define         V4L2_DV_720P59_94       7 /* SMPTE 274M */
-#define         V4L2_DV_720P60          8 /* SMPTE 274M/296M */
-#define         V4L2_DV_1080I29_97      9 /* BT.1120/ SMPTE 274M */
-#define         V4L2_DV_1080I30         10 /* BT.1120/ SMPTE 274M */
-#define         V4L2_DV_1080I25         11 /* BT.1120 */
-#define         V4L2_DV_1080I50         12 /* SMPTE 296M */
-#define         V4L2_DV_1080I60         13 /* SMPTE 296M */
-#define         V4L2_DV_1080P24         14 /* SMPTE 296M */
-#define         V4L2_DV_1080P25         15 /* SMPTE 296M */
-#define         V4L2_DV_1080P30         16 /* SMPTE 296M */
-#define         V4L2_DV_1080P50         17 /* BT.1120 */
-#define         V4L2_DV_1080P60         18 /* BT.1120 */
-
-/*
- *      D V     B T     T I M I N G S
- */
-
-/* BT.656/BT.1120 timing data */
-struct <link linkend="v4l2-bt-timings">v4l2_bt_timings</link> {
-        __u32   width;          /* width in pixels */
-        __u32   height;         /* height in lines */
-        __u32   interlaced;     /* Interlaced or progressive */
-        __u32   polarities;     /* Positive or negative polarity */
-        __u64   pixelclock;     /* Pixel clock in HZ. Ex. 74.25MHz-&gt;74250000 */
-        __u32   hfrontporch;    /* Horizpontal front porch in pixels */
-        __u32   hsync;          /* Horizontal Sync length in pixels */
-        __u32   hbackporch;     /* Horizontal back porch in pixels */
-        __u32   vfrontporch;    /* Vertical front porch in pixels */
-        __u32   vsync;          /* Vertical Sync length in lines */
-        __u32   vbackporch;     /* Vertical back porch in lines */
-        __u32   il_vfrontporch; /* Vertical front porch for bottom field of
-                                 * interlaced field formats
-                                 */
-        __u32   il_vsync;       /* Vertical sync length for bottom field of
-                                 * interlaced field formats
-                                 */
-        __u32   il_vbackporch;  /* Vertical back porch for bottom field of
-                                 * interlaced field formats
-                                 */
-        __u32   reserved[16];
-} __attribute__ ((packed));
-
-/* Interlaced or progressive format */
-#define V4L2_DV_PROGRESSIVE     0
-#define V4L2_DV_INTERLACED      1
-
-/* Polarities. If bit is not set, it is assumed to be negative polarity */
-#define V4L2_DV_VSYNC_POS_POL   0x00000001
-#define V4L2_DV_HSYNC_POS_POL   0x00000002
-
-
-/* DV timings */
-struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link> {
-        __u32 type;
-        union {
-                struct <link linkend="v4l2-bt-timings">v4l2_bt_timings</link>  bt;
-                __u32   reserved[32];
-        };
-} __attribute__ ((packed));
-
-/* Values for the type field */
-#define V4L2_DV_BT_656_1120     0       /* BT.656/1120 timing type */
-
-/*
- *      V I D E O   I N P U T S
- */
-struct <link linkend="v4l2-input">v4l2_input</link> {
-        __u32        index;             /*  Which input */
-        __u8         name[32];          /*  Label */
-        __u32        type;              /*  Type of input */
-        __u32        audioset;          /*  Associated audios (bitfield) */
-        __u32        tuner;             /*  Associated tuner */
-        v4l2_std_id  std;
-        __u32        status;
-        __u32        capabilities;
-        __u32        reserved[3];
-};
-
-/*  Values for the 'type' field */
-#define V4L2_INPUT_TYPE_TUNER           1
-#define V4L2_INPUT_TYPE_CAMERA          2
-
-/* field 'status' - general */
-#define V4L2_IN_ST_NO_POWER    0x00000001  /* Attached device is off */
-#define V4L2_IN_ST_NO_SIGNAL   0x00000002
-#define V4L2_IN_ST_NO_COLOR    0x00000004
-
-/* field 'status' - sensor orientation */
-/* If sensor is mounted upside down set both bits */
-#define V4L2_IN_ST_HFLIP       0x00000010 /* Frames are flipped horizontally */
-#define V4L2_IN_ST_VFLIP       0x00000020 /* Frames are flipped vertically */
-
-/* field 'status' - analog */
-#define V4L2_IN_ST_NO_H_LOCK   0x00000100  /* No horizontal sync lock */
-#define V4L2_IN_ST_COLOR_KILL  0x00000200  /* Color killer is active */
-
-/* field 'status' - digital */
-#define V4L2_IN_ST_NO_SYNC     0x00010000  /* No synchronization lock */
-#define V4L2_IN_ST_NO_EQU      0x00020000  /* No equalizer lock */
-#define V4L2_IN_ST_NO_CARRIER  0x00040000  /* Carrier recovery failed */
-
-/* field 'status' - VCR and set-top box */
-#define V4L2_IN_ST_MACROVISION 0x01000000  /* Macrovision detected */
-#define V4L2_IN_ST_NO_ACCESS   0x02000000  /* Conditional access denied */
-#define V4L2_IN_ST_VTR         0x04000000  /* VTR time constant */
-
-/* capabilities flags */
-#define V4L2_IN_CAP_PRESETS             0x00000001 /* Supports S_DV_PRESET */
-#define V4L2_IN_CAP_CUSTOM_TIMINGS      0x00000002 /* Supports S_DV_TIMINGS */
-#define V4L2_IN_CAP_STD                 0x00000004 /* Supports S_STD */
-
-/*
- *      V I D E O   O U T P U T S
- */
-struct <link linkend="v4l2-output">v4l2_output</link> {
-        __u32        index;             /*  Which output */
-        __u8         name[32];          /*  Label */
-        __u32        type;              /*  Type of output */
-        __u32        audioset;          /*  Associated audios (bitfield) */
-        __u32        modulator;         /*  Associated modulator */
-        v4l2_std_id  std;
-        __u32        capabilities;
-        __u32        reserved[3];
-};
-/*  Values for the 'type' field */
-#define V4L2_OUTPUT_TYPE_MODULATOR              1
-#define V4L2_OUTPUT_TYPE_ANALOG                 2
-#define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY       3
-
-/* capabilities flags */
-#define V4L2_OUT_CAP_PRESETS            0x00000001 /* Supports S_DV_PRESET */
-#define V4L2_OUT_CAP_CUSTOM_TIMINGS     0x00000002 /* Supports S_DV_TIMINGS */
-#define V4L2_OUT_CAP_STD                0x00000004 /* Supports S_STD */
-
-/*
- *      C O N T R O L S
- */
-struct <link linkend="v4l2-control">v4l2_control</link> {
-        __u32                id;
-        __s32                value;
-};
-
-struct <link linkend="v4l2-ext-control">v4l2_ext_control</link> {
-        __u32 id;
-        __u32 size;
-        __u32 reserved2[1];
-        union {
-                __s32 value;
-                __s64 value64;
-                char *string;
-        };
-} __attribute__ ((packed));
-
-struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link> {
-        __u32 ctrl_class;
-        __u32 count;
-        __u32 error_idx;
-        __u32 reserved[2];
-        struct <link linkend="v4l2-ext-control">v4l2_ext_control</link> *controls;
-};
-
-/*  Values for ctrl_class field */
-#define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */
-#define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */
-#define V4L2_CTRL_CLASS_CAMERA 0x009a0000       /* Camera class controls */
-#define V4L2_CTRL_CLASS_FM_TX 0x009b0000        /* FM Modulator control class */
-
-#define V4L2_CTRL_ID_MASK         (0x0fffffff)
-#define V4L2_CTRL_ID2CLASS(id)    ((id) &amp; 0x0fff0000UL)
-#define V4L2_CTRL_DRIVER_PRIV(id) (((id) &amp; 0xffff) &gt;= 0x1000)
-
-enum <link linkend="v4l2-ctrl-type">v4l2_ctrl_type</link> {
-        V4L2_CTRL_TYPE_INTEGER       = 1,
-        V4L2_CTRL_TYPE_BOOLEAN       = 2,
-        V4L2_CTRL_TYPE_MENU          = 3,
-        V4L2_CTRL_TYPE_BUTTON        = 4,
-        V4L2_CTRL_TYPE_INTEGER64     = 5,
-        V4L2_CTRL_TYPE_CTRL_CLASS    = 6,
-        V4L2_CTRL_TYPE_STRING        = 7,
-};
-
-/*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
-struct <link linkend="v4l2-queryctrl">v4l2_queryctrl</link> {
-        __u32                id;
-        enum <link linkend="v4l2-ctrl-type">v4l2_ctrl_type</link>  type;
-        __u8                 name[32];  /* Whatever */
-        __s32                minimum;   /* Note signedness */
-        __s32                maximum;
-        __s32                step;
-        __s32                default_value;
-        __u32                flags;
-        __u32                reserved[2];
-};
-
-/*  Used in the VIDIOC_QUERYMENU ioctl for querying menu items */
-struct <link linkend="v4l2-querymenu">v4l2_querymenu</link> {
-        __u32           id;
-        __u32           index;
-        __u8            name[32];       /* Whatever */
-        __u32           reserved;
-};
-
-/*  Control flags  */
-#define V4L2_CTRL_FLAG_DISABLED         0x0001
-#define V4L2_CTRL_FLAG_GRABBED          0x0002
-#define V4L2_CTRL_FLAG_READ_ONLY        0x0004
-#define V4L2_CTRL_FLAG_UPDATE           0x0008
-#define V4L2_CTRL_FLAG_INACTIVE         0x0010
-#define V4L2_CTRL_FLAG_SLIDER           0x0020
-#define V4L2_CTRL_FLAG_WRITE_ONLY       0x0040
-
-/*  Query flag, to be ORed with the control ID */
-#define V4L2_CTRL_FLAG_NEXT_CTRL        0x80000000
-
-/*  User-class control IDs defined by V4L2 */
-#define V4L2_CID_BASE                   (V4L2_CTRL_CLASS_USER | 0x900)
-#define V4L2_CID_USER_BASE              V4L2_CID_BASE
-/*  IDs reserved for driver specific controls */
-#define V4L2_CID_PRIVATE_BASE           0x08000000
-
-#define V4L2_CID_USER_CLASS             (V4L2_CTRL_CLASS_USER | 1)
-#define V4L2_CID_BRIGHTNESS             (V4L2_CID_BASE+0)
-#define V4L2_CID_CONTRAST               (V4L2_CID_BASE+1)
-#define V4L2_CID_SATURATION             (V4L2_CID_BASE+2)
-#define V4L2_CID_HUE                    (V4L2_CID_BASE+3)
-#define V4L2_CID_AUDIO_VOLUME           (V4L2_CID_BASE+5)
-#define V4L2_CID_AUDIO_BALANCE          (V4L2_CID_BASE+6)
-#define V4L2_CID_AUDIO_BASS             (V4L2_CID_BASE+7)
-#define V4L2_CID_AUDIO_TREBLE           (V4L2_CID_BASE+8)
-#define V4L2_CID_AUDIO_MUTE             (V4L2_CID_BASE+9)
-#define V4L2_CID_AUDIO_LOUDNESS         (V4L2_CID_BASE+10)
-#define V4L2_CID_BLACK_LEVEL            (V4L2_CID_BASE+11) /* Deprecated */
-#define V4L2_CID_AUTO_WHITE_BALANCE     (V4L2_CID_BASE+12)
-#define V4L2_CID_DO_WHITE_BALANCE       (V4L2_CID_BASE+13)
-#define V4L2_CID_RED_BALANCE            (V4L2_CID_BASE+14)
-#define V4L2_CID_BLUE_BALANCE           (V4L2_CID_BASE+15)
-#define V4L2_CID_GAMMA                  (V4L2_CID_BASE+16)
-#define V4L2_CID_WHITENESS              (V4L2_CID_GAMMA) /* Deprecated */
-#define V4L2_CID_EXPOSURE               (V4L2_CID_BASE+17)
-#define V4L2_CID_AUTOGAIN               (V4L2_CID_BASE+18)
-#define V4L2_CID_GAIN                   (V4L2_CID_BASE+19)
-#define V4L2_CID_HFLIP                  (V4L2_CID_BASE+20)
-#define V4L2_CID_VFLIP                  (V4L2_CID_BASE+21)
-
-/* Deprecated; use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */
-#define V4L2_CID_HCENTER                (V4L2_CID_BASE+22)
-#define V4L2_CID_VCENTER                (V4L2_CID_BASE+23)
-
-#define V4L2_CID_POWER_LINE_FREQUENCY   (V4L2_CID_BASE+24)
-enum <link linkend="v4l2-power-line-frequency">v4l2_power_line_frequency</link> {
-        V4L2_CID_POWER_LINE_FREQUENCY_DISABLED  = 0,
-        V4L2_CID_POWER_LINE_FREQUENCY_50HZ      = 1,
-        V4L2_CID_POWER_LINE_FREQUENCY_60HZ      = 2,
-};
-#define V4L2_CID_HUE_AUTO                       (V4L2_CID_BASE+25)
-#define V4L2_CID_WHITE_BALANCE_TEMPERATURE      (V4L2_CID_BASE+26)
-#define V4L2_CID_SHARPNESS                      (V4L2_CID_BASE+27)
-#define V4L2_CID_BACKLIGHT_COMPENSATION         (V4L2_CID_BASE+28)
-#define V4L2_CID_CHROMA_AGC                     (V4L2_CID_BASE+29)
-#define V4L2_CID_COLOR_KILLER                   (V4L2_CID_BASE+30)
-#define V4L2_CID_COLORFX                        (V4L2_CID_BASE+31)
-enum <link linkend="v4l2-colorfx">v4l2_colorfx</link> {
-        V4L2_COLORFX_NONE       = 0,
-        V4L2_COLORFX_BW         = 1,
-        V4L2_COLORFX_SEPIA      = 2,
-        V4L2_COLORFX_NEGATIVE = 3,
-        V4L2_COLORFX_EMBOSS = 4,
-        V4L2_COLORFX_SKETCH = 5,
-        V4L2_COLORFX_SKY_BLUE = 6,
-        V4L2_COLORFX_GRASS_GREEN = 7,
-        V4L2_COLORFX_SKIN_WHITEN = 8,
-        V4L2_COLORFX_VIVID = 9,
-};
-#define V4L2_CID_AUTOBRIGHTNESS                 (V4L2_CID_BASE+32)
-#define V4L2_CID_BAND_STOP_FILTER               (V4L2_CID_BASE+33)
-
-#define V4L2_CID_ROTATE                         (V4L2_CID_BASE+34)
-#define V4L2_CID_BG_COLOR                       (V4L2_CID_BASE+35)
-
-#define V4L2_CID_CHROMA_GAIN                    (V4L2_CID_BASE+36)
-
-#define V4L2_CID_ILLUMINATORS_1                 (V4L2_CID_BASE+37)
-#define V4L2_CID_ILLUMINATORS_2                 (V4L2_CID_BASE+38)
-
-/* last CID + 1 */
-#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+39)
-
-/*  MPEG-class control IDs defined by V4L2 */
-#define V4L2_CID_MPEG_BASE                      (V4L2_CTRL_CLASS_MPEG | 0x900)
-#define V4L2_CID_MPEG_CLASS                     (V4L2_CTRL_CLASS_MPEG | 1)
-
-/*  MPEG streams */
-#define V4L2_CID_MPEG_STREAM_TYPE               (V4L2_CID_MPEG_BASE+0)
-enum <link linkend="v4l2-mpeg-stream-type">v4l2_mpeg_stream_type</link> {
-        V4L2_MPEG_STREAM_TYPE_MPEG2_PS   = 0, /* MPEG-2 program stream */
-        V4L2_MPEG_STREAM_TYPE_MPEG2_TS   = 1, /* MPEG-2 transport stream */
-        V4L2_MPEG_STREAM_TYPE_MPEG1_SS   = 2, /* MPEG-1 system stream */
-        V4L2_MPEG_STREAM_TYPE_MPEG2_DVD  = 3, /* MPEG-2 DVD-compatible stream */
-        V4L2_MPEG_STREAM_TYPE_MPEG1_VCD  = 4, /* MPEG-1 VCD-compatible stream */
-        V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */
-};
-#define V4L2_CID_MPEG_STREAM_PID_PMT            (V4L2_CID_MPEG_BASE+1)
-#define V4L2_CID_MPEG_STREAM_PID_AUDIO          (V4L2_CID_MPEG_BASE+2)
-#define V4L2_CID_MPEG_STREAM_PID_VIDEO          (V4L2_CID_MPEG_BASE+3)
-#define V4L2_CID_MPEG_STREAM_PID_PCR            (V4L2_CID_MPEG_BASE+4)
-#define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO       (V4L2_CID_MPEG_BASE+5)
-#define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO       (V4L2_CID_MPEG_BASE+6)
-#define V4L2_CID_MPEG_STREAM_VBI_FMT            (V4L2_CID_MPEG_BASE+7)
-enum <link linkend="v4l2-mpeg-stream-vbi-fmt">v4l2_mpeg_stream_vbi_fmt</link> {
-        V4L2_MPEG_STREAM_VBI_FMT_NONE = 0,  /* No VBI in the MPEG stream */
-        V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1,  /* VBI in private packets, IVTV format */
-};
-
-/*  MPEG audio */
-#define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ       (V4L2_CID_MPEG_BASE+100)
-enum <link linkend="v4l2-mpeg-audio-sampling-freq">v4l2_mpeg_audio_sampling_freq</link> {
-        V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0,
-        V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1,
-        V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2,
-};
-#define V4L2_CID_MPEG_AUDIO_ENCODING            (V4L2_CID_MPEG_BASE+101)
-enum <link linkend="v4l2-mpeg-audio-encoding">v4l2_mpeg_audio_encoding</link> {
-        V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0,
-        V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1,
-        V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2,
-        V4L2_MPEG_AUDIO_ENCODING_AAC     = 3,
-        V4L2_MPEG_AUDIO_ENCODING_AC3     = 4,
-};
-#define V4L2_CID_MPEG_AUDIO_L1_BITRATE          (V4L2_CID_MPEG_BASE+102)
-enum <link linkend="v4l2-mpeg-audio-l1-bitrate">v4l2_mpeg_audio_l1_bitrate</link> {
-        V4L2_MPEG_AUDIO_L1_BITRATE_32K  = 0,
-        V4L2_MPEG_AUDIO_L1_BITRATE_64K  = 1,
-        V4L2_MPEG_AUDIO_L1_BITRATE_96K  = 2,
-        V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3,
-        V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4,
-        V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5,
-        V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6,
-        V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7,
-        V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8,
-        V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9,
-        V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10,
-        V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11,
-        V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12,
-        V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13,
-};
-#define V4L2_CID_MPEG_AUDIO_L2_BITRATE          (V4L2_CID_MPEG_BASE+103)
-enum <link linkend="v4l2-mpeg-audio-l2-bitrate">v4l2_mpeg_audio_l2_bitrate</link> {
-        V4L2_MPEG_AUDIO_L2_BITRATE_32K  = 0,
-        V4L2_MPEG_AUDIO_L2_BITRATE_48K  = 1,
-        V4L2_MPEG_AUDIO_L2_BITRATE_56K  = 2,
-        V4L2_MPEG_AUDIO_L2_BITRATE_64K  = 3,
-        V4L2_MPEG_AUDIO_L2_BITRATE_80K  = 4,
-        V4L2_MPEG_AUDIO_L2_BITRATE_96K  = 5,
-        V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6,
-        V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7,
-        V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8,
-        V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9,
-        V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10,
-        V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11,
-        V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12,
-        V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13,
-};
-#define V4L2_CID_MPEG_AUDIO_L3_BITRATE          (V4L2_CID_MPEG_BASE+104)
-enum <link linkend="v4l2-mpeg-audio-l3-bitrate">v4l2_mpeg_audio_l3_bitrate</link> {
-        V4L2_MPEG_AUDIO_L3_BITRATE_32K  = 0,
-        V4L2_MPEG_AUDIO_L3_BITRATE_40K  = 1,
-        V4L2_MPEG_AUDIO_L3_BITRATE_48K  = 2,
-        V4L2_MPEG_AUDIO_L3_BITRATE_56K  = 3,
-        V4L2_MPEG_AUDIO_L3_BITRATE_64K  = 4,
-        V4L2_MPEG_AUDIO_L3_BITRATE_80K  = 5,
-        V4L2_MPEG_AUDIO_L3_BITRATE_96K  = 6,
-        V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7,
-        V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8,
-        V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9,
-        V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10,
-        V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11,
-        V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12,
-        V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13,
-};
-#define V4L2_CID_MPEG_AUDIO_MODE                (V4L2_CID_MPEG_BASE+105)
-enum <link linkend="v4l2-mpeg-audio-mode">v4l2_mpeg_audio_mode</link> {
-        V4L2_MPEG_AUDIO_MODE_STEREO       = 0,
-        V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1,
-        V4L2_MPEG_AUDIO_MODE_DUAL         = 2,
-        V4L2_MPEG_AUDIO_MODE_MONO         = 3,
-};
-#define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION      (V4L2_CID_MPEG_BASE+106)
-enum <link linkend="v4l2-mpeg-audio-mode-extension">v4l2_mpeg_audio_mode_extension</link> {
-        V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4  = 0,
-        V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8  = 1,
-        V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2,
-        V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3,
-};
-#define V4L2_CID_MPEG_AUDIO_EMPHASIS            (V4L2_CID_MPEG_BASE+107)
-enum <link linkend="v4l2-mpeg-audio-emphasis">v4l2_mpeg_audio_emphasis</link> {
-        V4L2_MPEG_AUDIO_EMPHASIS_NONE         = 0,
-        V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1,
-        V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17    = 2,
-};
-#define V4L2_CID_MPEG_AUDIO_CRC                 (V4L2_CID_MPEG_BASE+108)
-enum <link linkend="v4l2-mpeg-audio-crc">v4l2_mpeg_audio_crc</link> {
-        V4L2_MPEG_AUDIO_CRC_NONE  = 0,
-        V4L2_MPEG_AUDIO_CRC_CRC16 = 1,
-};
-#define V4L2_CID_MPEG_AUDIO_MUTE                (V4L2_CID_MPEG_BASE+109)
-#define V4L2_CID_MPEG_AUDIO_AAC_BITRATE         (V4L2_CID_MPEG_BASE+110)
-#define V4L2_CID_MPEG_AUDIO_AC3_BITRATE         (V4L2_CID_MPEG_BASE+111)
-enum <link linkend="v4l2-mpeg-audio-ac3-bitrate">v4l2_mpeg_audio_ac3_bitrate</link> {
-        V4L2_MPEG_AUDIO_AC3_BITRATE_32K  = 0,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_40K  = 1,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_48K  = 2,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_56K  = 3,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_64K  = 4,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_80K  = 5,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_96K  = 6,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18,
-};
-
-/*  MPEG video */
-#define V4L2_CID_MPEG_VIDEO_ENCODING            (V4L2_CID_MPEG_BASE+200)
-enum <link linkend="v4l2-mpeg-video-encoding">v4l2_mpeg_video_encoding</link> {
-        V4L2_MPEG_VIDEO_ENCODING_MPEG_1     = 0,
-        V4L2_MPEG_VIDEO_ENCODING_MPEG_2     = 1,
-        V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2,
-};
-#define V4L2_CID_MPEG_VIDEO_ASPECT              (V4L2_CID_MPEG_BASE+201)
-enum <link linkend="v4l2-mpeg-video-aspect">v4l2_mpeg_video_aspect</link> {
-        V4L2_MPEG_VIDEO_ASPECT_1x1     = 0,
-        V4L2_MPEG_VIDEO_ASPECT_4x3     = 1,
-        V4L2_MPEG_VIDEO_ASPECT_16x9    = 2,
-        V4L2_MPEG_VIDEO_ASPECT_221x100 = 3,
-};
-#define V4L2_CID_MPEG_VIDEO_B_FRAMES            (V4L2_CID_MPEG_BASE+202)
-#define V4L2_CID_MPEG_VIDEO_GOP_SIZE            (V4L2_CID_MPEG_BASE+203)
-#define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE         (V4L2_CID_MPEG_BASE+204)
-#define V4L2_CID_MPEG_VIDEO_PULLDOWN            (V4L2_CID_MPEG_BASE+205)
-#define V4L2_CID_MPEG_VIDEO_BITRATE_MODE        (V4L2_CID_MPEG_BASE+206)
-enum <link linkend="v4l2-mpeg-video-bitrate-mode">v4l2_mpeg_video_bitrate_mode</link> {
-        V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0,
-        V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1,
-};
-#define V4L2_CID_MPEG_VIDEO_BITRATE             (V4L2_CID_MPEG_BASE+207)
-#define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK        (V4L2_CID_MPEG_BASE+208)
-#define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_MPEG_BASE+209)
-#define V4L2_CID_MPEG_VIDEO_MUTE                (V4L2_CID_MPEG_BASE+210)
-#define V4L2_CID_MPEG_VIDEO_MUTE_YUV            (V4L2_CID_MPEG_BASE+211)
-
-/*  MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */
-#define V4L2_CID_MPEG_CX2341X_BASE                              (V4L2_CTRL_CLASS_MPEG | 0x1000)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE         (V4L2_CID_MPEG_CX2341X_BASE+0)
-enum <link linkend="v4l2-mpeg-cx2341x-video-spatial-filter-mode">v4l2_mpeg_cx2341x_video_spatial_filter_mode</link> {
-        V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0,
-        V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO   = 1,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER              (V4L2_CID_MPEG_CX2341X_BASE+1)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE    (V4L2_CID_MPEG_CX2341X_BASE+2)
-enum <link linkend="luma-spatial-filter-type">v4l2_mpeg_cx2341x_video_luma_spatial_filter_type</link> {
-        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF                  = 0,
-        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR               = 1,
-        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT              = 2,
-        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE      = 3,
-        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE  (V4L2_CID_MPEG_CX2341X_BASE+3)
-enum <link linkend="chroma-spatial-filter-type">v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type</link> {
-        V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF    = 0,
-        V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE        (V4L2_CID_MPEG_CX2341X_BASE+4)
-enum <link linkend="v4l2-mpeg-cx2341x-video-temporal-filter-mode">v4l2_mpeg_cx2341x_video_temporal_filter_mode</link> {
-        V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0,
-        V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO   = 1,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER             (V4L2_CID_MPEG_CX2341X_BASE+5)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE          (V4L2_CID_MPEG_CX2341X_BASE+6)
-enum <link linkend="v4l2-mpeg-cx2341x-video-median-filter-type">v4l2_mpeg_cx2341x_video_median_filter_type</link> {
-        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF      = 0,
-        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR      = 1,
-        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT     = 2,
-        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3,
-        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG     = 4,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM   (V4L2_CID_MPEG_CX2341X_BASE+7)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP      (V4L2_CID_MPEG_CX2341X_BASE+8)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+9)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP    (V4L2_CID_MPEG_CX2341X_BASE+10)
-#define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS         (V4L2_CID_MPEG_CX2341X_BASE+11)
-
-/*  Camera class control IDs */
-#define V4L2_CID_CAMERA_CLASS_BASE      (V4L2_CTRL_CLASS_CAMERA | 0x900)
-#define V4L2_CID_CAMERA_CLASS           (V4L2_CTRL_CLASS_CAMERA | 1)
-
-#define V4L2_CID_EXPOSURE_AUTO                  (V4L2_CID_CAMERA_CLASS_BASE+1)
-enum  <link linkend="v4l2-exposure-auto-type">v4l2_exposure_auto_type</link> {
-        V4L2_EXPOSURE_AUTO = 0,
-        V4L2_EXPOSURE_MANUAL = 1,
-        V4L2_EXPOSURE_SHUTTER_PRIORITY = 2,
-        V4L2_EXPOSURE_APERTURE_PRIORITY = 3
-};
-#define V4L2_CID_EXPOSURE_ABSOLUTE              (V4L2_CID_CAMERA_CLASS_BASE+2)
-#define V4L2_CID_EXPOSURE_AUTO_PRIORITY         (V4L2_CID_CAMERA_CLASS_BASE+3)
-
-#define V4L2_CID_PAN_RELATIVE                   (V4L2_CID_CAMERA_CLASS_BASE+4)
-#define V4L2_CID_TILT_RELATIVE                  (V4L2_CID_CAMERA_CLASS_BASE+5)
-#define V4L2_CID_PAN_RESET                      (V4L2_CID_CAMERA_CLASS_BASE+6)
-#define V4L2_CID_TILT_RESET                     (V4L2_CID_CAMERA_CLASS_BASE+7)
-
-#define V4L2_CID_PAN_ABSOLUTE                   (V4L2_CID_CAMERA_CLASS_BASE+8)
-#define V4L2_CID_TILT_ABSOLUTE                  (V4L2_CID_CAMERA_CLASS_BASE+9)
-
-#define V4L2_CID_FOCUS_ABSOLUTE                 (V4L2_CID_CAMERA_CLASS_BASE+10)
-#define V4L2_CID_FOCUS_RELATIVE                 (V4L2_CID_CAMERA_CLASS_BASE+11)
-#define V4L2_CID_FOCUS_AUTO                     (V4L2_CID_CAMERA_CLASS_BASE+12)
-
-#define V4L2_CID_ZOOM_ABSOLUTE                  (V4L2_CID_CAMERA_CLASS_BASE+13)
-#define V4L2_CID_ZOOM_RELATIVE                  (V4L2_CID_CAMERA_CLASS_BASE+14)
-#define V4L2_CID_ZOOM_CONTINUOUS                (V4L2_CID_CAMERA_CLASS_BASE+15)
-
-#define V4L2_CID_PRIVACY                        (V4L2_CID_CAMERA_CLASS_BASE+16)
-
-#define V4L2_CID_IRIS_ABSOLUTE                  (V4L2_CID_CAMERA_CLASS_BASE+17)
-#define V4L2_CID_IRIS_RELATIVE                  (V4L2_CID_CAMERA_CLASS_BASE+18)
-
-/* FM Modulator class control IDs */
-#define V4L2_CID_FM_TX_CLASS_BASE               (V4L2_CTRL_CLASS_FM_TX | 0x900)
-#define V4L2_CID_FM_TX_CLASS                    (V4L2_CTRL_CLASS_FM_TX | 1)
-
-#define V4L2_CID_RDS_TX_DEVIATION               (V4L2_CID_FM_TX_CLASS_BASE + 1)
-#define V4L2_CID_RDS_TX_PI                      (V4L2_CID_FM_TX_CLASS_BASE + 2)
-#define V4L2_CID_RDS_TX_PTY                     (V4L2_CID_FM_TX_CLASS_BASE + 3)
-#define V4L2_CID_RDS_TX_PS_NAME                 (V4L2_CID_FM_TX_CLASS_BASE + 5)
-#define V4L2_CID_RDS_TX_RADIO_TEXT              (V4L2_CID_FM_TX_CLASS_BASE + 6)
-
-#define V4L2_CID_AUDIO_LIMITER_ENABLED          (V4L2_CID_FM_TX_CLASS_BASE + 64)
-#define V4L2_CID_AUDIO_LIMITER_RELEASE_TIME     (V4L2_CID_FM_TX_CLASS_BASE + 65)
-#define V4L2_CID_AUDIO_LIMITER_DEVIATION        (V4L2_CID_FM_TX_CLASS_BASE + 66)
-
-#define V4L2_CID_AUDIO_COMPRESSION_ENABLED      (V4L2_CID_FM_TX_CLASS_BASE + 80)
-#define V4L2_CID_AUDIO_COMPRESSION_GAIN         (V4L2_CID_FM_TX_CLASS_BASE + 81)
-#define V4L2_CID_AUDIO_COMPRESSION_THRESHOLD    (V4L2_CID_FM_TX_CLASS_BASE + 82)
-#define V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME  (V4L2_CID_FM_TX_CLASS_BASE + 83)
-#define V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME (V4L2_CID_FM_TX_CLASS_BASE + 84)
-
-#define V4L2_CID_PILOT_TONE_ENABLED             (V4L2_CID_FM_TX_CLASS_BASE + 96)
-#define V4L2_CID_PILOT_TONE_DEVIATION           (V4L2_CID_FM_TX_CLASS_BASE + 97)
-#define V4L2_CID_PILOT_TONE_FREQUENCY           (V4L2_CID_FM_TX_CLASS_BASE + 98)
-
-#define V4L2_CID_TUNE_PREEMPHASIS               (V4L2_CID_FM_TX_CLASS_BASE + 112)
-enum <link linkend="v4l2-preemphasis">v4l2_preemphasis</link> {
-        V4L2_PREEMPHASIS_DISABLED       = 0,
-        V4L2_PREEMPHASIS_50_uS          = 1,
-        V4L2_PREEMPHASIS_75_uS          = 2,
-};
-#define V4L2_CID_TUNE_POWER_LEVEL               (V4L2_CID_FM_TX_CLASS_BASE + 113)
-#define V4L2_CID_TUNE_ANTENNA_CAPACITOR         (V4L2_CID_FM_TX_CLASS_BASE + 114)
-
-/*
- *      T U N I N G
- */
-struct <link linkend="v4l2-tuner">v4l2_tuner</link> {
-        __u32                   index;
-        __u8                    name[32];
-        enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link>    type;
-        __u32                   capability;
-        __u32                   rangelow;
-        __u32                   rangehigh;
-        __u32                   rxsubchans;
-        __u32                   audmode;
-        __s32                   signal;
-        __s32                   afc;
-        __u32                   reserved[4];
-};
-
-struct <link linkend="v4l2-modulator">v4l2_modulator</link> {
-        __u32                   index;
-        __u8                    name[32];
-        __u32                   capability;
-        __u32                   rangelow;
-        __u32                   rangehigh;
-        __u32                   txsubchans;
-        __u32                   reserved[4];
-};
-
-/*  Flags for the 'capability' field */
-#define V4L2_TUNER_CAP_LOW              0x0001
-#define V4L2_TUNER_CAP_NORM             0x0002
-#define V4L2_TUNER_CAP_STEREO           0x0010
-#define V4L2_TUNER_CAP_LANG2            0x0020
-#define V4L2_TUNER_CAP_SAP              0x0020
-#define V4L2_TUNER_CAP_LANG1            0x0040
-#define V4L2_TUNER_CAP_RDS              0x0080
-#define V4L2_TUNER_CAP_RDS_BLOCK_IO     0x0100
-#define V4L2_TUNER_CAP_RDS_CONTROLS     0x0200
-
-/*  Flags for the 'rxsubchans' field */
-#define V4L2_TUNER_SUB_MONO             0x0001
-#define V4L2_TUNER_SUB_STEREO           0x0002
-#define V4L2_TUNER_SUB_LANG2            0x0004
-#define V4L2_TUNER_SUB_SAP              0x0004
-#define V4L2_TUNER_SUB_LANG1            0x0008
-#define V4L2_TUNER_SUB_RDS              0x0010
-
-/*  Values for the 'audmode' field */
-#define V4L2_TUNER_MODE_MONO            0x0000
-#define V4L2_TUNER_MODE_STEREO          0x0001
-#define V4L2_TUNER_MODE_LANG2           0x0002
-#define V4L2_TUNER_MODE_SAP             0x0002
-#define V4L2_TUNER_MODE_LANG1           0x0003
-#define V4L2_TUNER_MODE_LANG1_LANG2     0x0004
-
-struct <link linkend="v4l2-frequency">v4l2_frequency</link> {
-        __u32                 tuner;
-        enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link>  type;
-        __u32                 frequency;
-        __u32                 reserved[8];
-};
-
-struct <link linkend="v4l2-hw-freq-seek">v4l2_hw_freq_seek</link> {
-        __u32                 tuner;
-        enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link>  type;
-        __u32                 seek_upward;
-        __u32                 wrap_around;
-        __u32                 spacing;
-        __u32                 reserved[7];
-};
-
-/*
- *      R D S
- */
-
-struct <link linkend="v4l2-rds-data">v4l2_rds_data</link> {
-        __u8    lsb;
-        __u8    msb;
-        __u8    block;
-} __attribute__ ((packed));
-
-#define V4L2_RDS_BLOCK_MSK       0x7
-#define V4L2_RDS_BLOCK_A         0
-#define V4L2_RDS_BLOCK_B         1
-#define V4L2_RDS_BLOCK_C         2
-#define V4L2_RDS_BLOCK_D         3
-#define V4L2_RDS_BLOCK_C_ALT     4
-#define V4L2_RDS_BLOCK_INVALID   7
-
-#define V4L2_RDS_BLOCK_CORRECTED 0x40
-#define V4L2_RDS_BLOCK_ERROR     0x80
-
-/*
- *      A U D I O
- */
-struct <link linkend="v4l2-audio">v4l2_audio</link> {
-        __u32   index;
-        __u8    name[32];
-        __u32   capability;
-        __u32   mode;
-        __u32   reserved[2];
-};
-
-/*  Flags for the 'capability' field */
-#define V4L2_AUDCAP_STEREO              0x00001
-#define V4L2_AUDCAP_AVL                 0x00002
-
-/*  Flags for the 'mode' field */
-#define V4L2_AUDMODE_AVL                0x00001
-
-struct <link linkend="v4l2-audioout">v4l2_audioout</link> {
-        __u32   index;
-        __u8    name[32];
-        __u32   capability;
-        __u32   mode;
-        __u32   reserved[2];
-};
-
-/*
- *      M P E G   S E R V I C E S
- *
- *      NOTE: EXPERIMENTAL API
- */
-#if 1
-#define V4L2_ENC_IDX_FRAME_I    (0)
-#define V4L2_ENC_IDX_FRAME_P    (1)
-#define V4L2_ENC_IDX_FRAME_B    (2)
-#define V4L2_ENC_IDX_FRAME_MASK (0xf)
-
-struct <link linkend="v4l2-enc-idx-entry">v4l2_enc_idx_entry</link> {
-        __u64 offset;
-        __u64 pts;
-        __u32 length;
-        __u32 flags;
-        __u32 reserved[2];
-};
-
-#define V4L2_ENC_IDX_ENTRIES (64)
-struct <link linkend="v4l2-enc-idx">v4l2_enc_idx</link> {
-        __u32 entries;
-        __u32 entries_cap;
-        __u32 reserved[4];
-        struct <link linkend="v4l2-enc-idx-entry">v4l2_enc_idx_entry</link> entry[V4L2_ENC_IDX_ENTRIES];
-};
-
-
-#define V4L2_ENC_CMD_START      (0)
-#define V4L2_ENC_CMD_STOP       (1)
-#define V4L2_ENC_CMD_PAUSE      (2)
-#define V4L2_ENC_CMD_RESUME     (3)
-
-/* Flags for V4L2_ENC_CMD_STOP */
-#define V4L2_ENC_CMD_STOP_AT_GOP_END    (1 &lt;&lt; 0)
-
-struct <link linkend="v4l2-encoder-cmd">v4l2_encoder_cmd</link> {
-        __u32 cmd;
-        __u32 flags;
-        union {
-                struct {
-                        __u32 data[8];
-                } raw;
-        };
-};
-
-#endif
-
-
-/*
- *      D A T A   S E R V I C E S   ( V B I )
- *
- *      Data services API by Michael Schimek
- */
-
-/* Raw VBI */
-struct <link linkend="v4l2-vbi-format">v4l2_vbi_format</link> {
-        __u32   sampling_rate;          /* in 1 Hz */
-        __u32   offset;
-        __u32   samples_per_line;
-        __u32   sample_format;          /* V4L2_PIX_FMT_* */
-        __s32   start[2];
-        __u32   count[2];
-        __u32   flags;                  /* V4L2_VBI_* */
-        __u32   reserved[2];            /* must be zero */
-};
-
-/*  VBI flags  */
-#define V4L2_VBI_UNSYNC         (1 &lt;&lt; 0)
-#define V4L2_VBI_INTERLACED     (1 &lt;&lt; 1)
-
-/* Sliced VBI
- *
- *    This implements is a proposal V4L2 API to allow SLICED VBI
- * required for some hardware encoders. It should change without
- * notice in the definitive implementation.
- */
-
-struct <link linkend="v4l2-sliced-vbi-format">v4l2_sliced_vbi_format</link> {
-        __u16   service_set;
-        /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
-           service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
-                                 (equals frame lines 313-336 for 625 line video
-                                  standards, 263-286 for 525 line standards) */
-        __u16   service_lines[2][24];
-        __u32   io_size;
-        __u32   reserved[2];            /* must be zero */
-};
-
-/* Teletext World System Teletext
-   (WST), defined on ITU-R BT.653-2 */
-#define V4L2_SLICED_TELETEXT_B          (0x0001)
-/* Video Program System, defined on ETS 300 231*/
-#define V4L2_SLICED_VPS                 (0x0400)
-/* Closed Caption, defined on EIA-608 */
-#define V4L2_SLICED_CAPTION_525         (0x1000)
-/* Wide Screen System, defined on ITU-R BT1119.1 */
-#define V4L2_SLICED_WSS_625             (0x4000)
-
-#define V4L2_SLICED_VBI_525             (V4L2_SLICED_CAPTION_525)
-#define V4L2_SLICED_VBI_625             (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625)
-
-struct <link linkend="v4l2-sliced-vbi-cap">v4l2_sliced_vbi_cap</link> {
-        __u16   service_set;
-        /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
-           service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
-                                 (equals frame lines 313-336 for 625 line video
-                                  standards, 263-286 for 525 line standards) */
-        __u16   service_lines[2][24];
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> type;
-        __u32   reserved[3];    /* must be 0 */
-};
-
-struct <link linkend="v4l2-sliced-vbi-data">v4l2_sliced_vbi_data</link> {
-        __u32   id;
-        __u32   field;          /* 0: first field, 1: second field */
-        __u32   line;           /* 1-23 */
-        __u32   reserved;       /* must be 0 */
-        __u8    data[48];
-};
-
-/*
- * Sliced VBI data inserted into MPEG Streams
- */
-
-/*
- * V4L2_MPEG_STREAM_VBI_FMT_IVTV:
- *
- * Structure of payload contained in an MPEG 2 Private Stream 1 PES Packet in an
- * MPEG-2 Program Pack that contains V4L2_MPEG_STREAM_VBI_FMT_IVTV Sliced VBI
- * data
- *
- * Note, the MPEG-2 Program Pack and Private Stream 1 PES packet header
- * definitions are not included here.  See the MPEG-2 specifications for details
- * on these headers.
- */
-
-/* Line type IDs */
-#define V4L2_MPEG_VBI_IVTV_TELETEXT_B     (1)
-#define V4L2_MPEG_VBI_IVTV_CAPTION_525    (4)
-#define V4L2_MPEG_VBI_IVTV_WSS_625        (5)
-#define V4L2_MPEG_VBI_IVTV_VPS            (7)
-
-struct <link linkend="v4l2-mpeg-vbi-itv0-line">v4l2_mpeg_vbi_itv0_line</link> {
-        __u8 id;        /* One of V4L2_MPEG_VBI_IVTV_* above */
-        __u8 data[42];  /* Sliced VBI data for the line */
-} __attribute__ ((packed));
-
-struct <link linkend="v4l2-mpeg-vbi-itv0">v4l2_mpeg_vbi_itv0</link> {
-        __le32 linemask[2]; /* Bitmasks of VBI service lines present */
-        struct <link linkend="v4l2-mpeg-vbi-itv0-line">v4l2_mpeg_vbi_itv0_line</link> line[35];
-} __attribute__ ((packed));
-
-struct <link linkend="v4l2-mpeg-vbi-itv0-1">v4l2_mpeg_vbi_ITV0</link> {
-        struct <link linkend="v4l2-mpeg-vbi-itv0-line">v4l2_mpeg_vbi_itv0_line</link> line[36];
-} __attribute__ ((packed));
-
-#define V4L2_MPEG_VBI_IVTV_MAGIC0       "itv0"
-#define V4L2_MPEG_VBI_IVTV_MAGIC1       "ITV0"
-
-struct <link linkend="v4l2-mpeg-vbi-fmt-ivtv">v4l2_mpeg_vbi_fmt_ivtv</link> {
-        __u8 magic[4];
-        union {
-                struct <link linkend="v4l2-mpeg-vbi-itv0">v4l2_mpeg_vbi_itv0</link> itv0;
-                struct <link linkend="v4l2-mpeg-vbi-itv0-1">v4l2_mpeg_vbi_ITV0</link> ITV0;
-        };
-} __attribute__ ((packed));
-
-/*
- *      A G G R E G A T E   S T R U C T U R E S
- */
-
-/**
- * struct <link linkend="v4l2-plane-pix-format">v4l2_plane_pix_format</link> - additional, per-plane format definition
- * @sizeimage:          maximum size in bytes required for data, for which
- *                      this plane will be used
- * @bytesperline:       distance in bytes between the leftmost pixels in two
- *                      adjacent lines
- */
-struct <link linkend="v4l2-plane-pix-format">v4l2_plane_pix_format</link> {
-        __u32           sizeimage;
-        __u16           bytesperline;
-        __u16           reserved[7];
-} __attribute__ ((packed));
-
-/**
- * struct <link linkend="v4l2-pix-format-mplane">v4l2_pix_format_mplane</link> - multiplanar format definition
- * @width:              image width in pixels
- * @height:             image height in pixels
- * @pixelformat:        little endian four character code (fourcc)
- * @field:              field order (for interlaced video)
- * @colorspace:         supplemental to pixelformat
- * @plane_fmt:          per-plane information
- * @num_planes:         number of planes for this format
- */
-struct <link linkend="v4l2-pix-format-mplane">v4l2_pix_format_mplane</link> {
-        __u32                           width;
-        __u32                           height;
-        __u32                           pixelformat;
-        enum <link linkend="v4l2-field">v4l2_field</link>                 field;
-        enum <link linkend="v4l2-colorspace">v4l2_colorspace</link>            colorspace;
-
-        struct <link linkend="v4l2-plane-pix-format">v4l2_plane_pix_format</link>    plane_fmt[VIDEO_MAX_PLANES];
-        __u8                            num_planes;
-        __u8                            reserved[11];
-} __attribute__ ((packed));
-
-/**
- * struct <link linkend="v4l2-format">v4l2_format</link> - stream data format
- * @type:       type of the data stream
- * @pix:        definition of an image format
- * @pix_mp:     definition of a multiplanar image format
- * @win:        definition of an overlaid image
- * @vbi:        raw VBI capture or output parameters
- * @sliced:     sliced VBI capture or output parameters
- * @raw_data:   placeholder for future extensions and custom formats
- */
-struct <link linkend="v4l2-format">v4l2_format</link> {
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> type;
-        union {
-                struct <link linkend="v4l2-pix-format">v4l2_pix_format</link>          pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
-                struct <link linkend="v4l2-pix-format-mplane">v4l2_pix_format_mplane</link>   pix_mp;  /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
-                struct <link linkend="v4l2-window">v4l2_window</link>              win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
-                struct <link linkend="v4l2-vbi-format">v4l2_vbi_format</link>          vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
-                struct <link linkend="v4l2-sliced-vbi-format">v4l2_sliced_vbi_format</link>   sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
-                __u8    raw_data[200];                   /* user-defined */
-        } fmt;
-};
-
-/*      Stream type-dependent parameters
- */
-struct <link linkend="v4l2-streamparm">v4l2_streamparm</link> {
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> type;
-        union {
-                struct <link linkend="v4l2-captureparm">v4l2_captureparm</link> capture;
-                struct <link linkend="v4l2-outputparm">v4l2_outputparm</link>  output;
-                __u8    raw_data[200];  /* user-defined */
-        } parm;
-};
-
-/*
- *      E V E N T S
- */
-
-#define V4L2_EVENT_ALL                          0
-#define V4L2_EVENT_VSYNC                        1
-#define V4L2_EVENT_EOS                          2
-#define V4L2_EVENT_PRIVATE_START                0x08000000
-
-/* Payload for V4L2_EVENT_VSYNC */
-struct <link linkend="v4l2-event-vsync">v4l2_event_vsync</link> {
-        /* Can be V4L2_FIELD_ANY, _NONE, _TOP or _BOTTOM */
-        __u8 field;
-} __attribute__ ((packed));
-
-struct <link linkend="v4l2-event">v4l2_event</link> {
-        __u32                           type;
-        union {
-                struct <link linkend="v4l2-event-vsync">v4l2_event_vsync</link> vsync;
-                __u8                    data[64];
-        } u;
-        __u32                           pending;
-        __u32                           sequence;
-        struct timespec                 timestamp;
-        __u32                           reserved[9];
-};
-
-struct <link linkend="v4l2-event-subscription">v4l2_event_subscription</link> {
-        __u32                           type;
-        __u32                           reserved[7];
-};
-
-/*
- *      A D V A N C E D   D E B U G G I N G
- *
- *      NOTE: EXPERIMENTAL API, NEVER RELY ON THIS IN APPLICATIONS!
- *      FOR DEBUGGING, TESTING AND INTERNAL USE ONLY!
- */
-
-/* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */
-
-#define V4L2_CHIP_MATCH_HOST       0  /* Match against chip ID on host (0 for the host) */
-#define V4L2_CHIP_MATCH_I2C_DRIVER 1  /* Match against I2C driver name */
-#define V4L2_CHIP_MATCH_I2C_ADDR   2  /* Match against I2C 7-bit address */
-#define V4L2_CHIP_MATCH_AC97       3  /* Match against anciliary AC97 chip */
-
-struct <link linkend="v4l2-dbg-match">v4l2_dbg_match</link> {
-        __u32 type; /* Match type */
-        union {     /* Match this chip, meaning determined by type */
-                __u32 addr;
-                char name[32];
-        };
-} __attribute__ ((packed));
-
-struct <link linkend="v4l2-dbg-register">v4l2_dbg_register</link> {
-        struct <link linkend="v4l2-dbg-match">v4l2_dbg_match</link> match;
-        __u32 size;     /* register size in bytes */
-        __u64 reg;
-        __u64 val;
-} __attribute__ ((packed));
-
-/* VIDIOC_DBG_G_CHIP_IDENT */
-struct <link linkend="v4l2-dbg-chip-ident">v4l2_dbg_chip_ident</link> {
-        struct <link linkend="v4l2-dbg-match">v4l2_dbg_match</link> match;
-        __u32 ident;       /* chip identifier as specified in &lt;media/v4l2-chip-ident.h&gt; */
-        __u32 revision;    /* chip revision, chip specific */
-} __attribute__ ((packed));
-
-/*
- *      I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
- *
- */
-#define VIDIOC_QUERYCAP          _IOR('V',  0, struct <link linkend="v4l2-capability">v4l2_capability</link>)
-#define VIDIOC_RESERVED           _IO('V',  1)
-#define VIDIOC_ENUM_FMT         _IOWR('V',  2, struct <link linkend="v4l2-fmtdesc">v4l2_fmtdesc</link>)
-#define VIDIOC_G_FMT            _IOWR('V',  4, struct <link linkend="v4l2-format">v4l2_format</link>)
-#define VIDIOC_S_FMT            _IOWR('V',  5, struct <link linkend="v4l2-format">v4l2_format</link>)
-#define VIDIOC_REQBUFS          _IOWR('V',  8, struct <link linkend="v4l2-requestbuffers">v4l2_requestbuffers</link>)
-#define VIDIOC_QUERYBUF         _IOWR('V',  9, struct <link linkend="v4l2-buffer">v4l2_buffer</link>)
-#define VIDIOC_G_FBUF            _IOR('V', 10, struct <link linkend="v4l2-framebuffer">v4l2_framebuffer</link>)
-#define VIDIOC_S_FBUF            _IOW('V', 11, struct <link linkend="v4l2-framebuffer">v4l2_framebuffer</link>)
-#define VIDIOC_OVERLAY           _IOW('V', 14, int)
-#define VIDIOC_QBUF             _IOWR('V', 15, struct <link linkend="v4l2-buffer">v4l2_buffer</link>)
-#define VIDIOC_DQBUF            _IOWR('V', 17, struct <link linkend="v4l2-buffer">v4l2_buffer</link>)
-#define VIDIOC_STREAMON          _IOW('V', 18, int)
-#define VIDIOC_STREAMOFF         _IOW('V', 19, int)
-#define VIDIOC_G_PARM           _IOWR('V', 21, struct <link linkend="v4l2-streamparm">v4l2_streamparm</link>)
-#define VIDIOC_S_PARM           _IOWR('V', 22, struct <link linkend="v4l2-streamparm">v4l2_streamparm</link>)
-#define VIDIOC_G_STD             _IOR('V', 23, v4l2_std_id)
-#define VIDIOC_S_STD             _IOW('V', 24, v4l2_std_id)
-#define VIDIOC_ENUMSTD          _IOWR('V', 25, struct <link linkend="v4l2-standard">v4l2_standard</link>)
-#define VIDIOC_ENUMINPUT        _IOWR('V', 26, struct <link linkend="v4l2-input">v4l2_input</link>)
-#define VIDIOC_G_CTRL           _IOWR('V', 27, struct <link linkend="v4l2-control">v4l2_control</link>)
-#define VIDIOC_S_CTRL           _IOWR('V', 28, struct <link linkend="v4l2-control">v4l2_control</link>)
-#define VIDIOC_G_TUNER          _IOWR('V', 29, struct <link linkend="v4l2-tuner">v4l2_tuner</link>)
-#define VIDIOC_S_TUNER           _IOW('V', 30, struct <link linkend="v4l2-tuner">v4l2_tuner</link>)
-#define VIDIOC_G_AUDIO           _IOR('V', 33, struct <link linkend="v4l2-audio">v4l2_audio</link>)
-#define VIDIOC_S_AUDIO           _IOW('V', 34, struct <link linkend="v4l2-audio">v4l2_audio</link>)
-#define VIDIOC_QUERYCTRL        _IOWR('V', 36, struct <link linkend="v4l2-queryctrl">v4l2_queryctrl</link>)
-#define VIDIOC_QUERYMENU        _IOWR('V', 37, struct <link linkend="v4l2-querymenu">v4l2_querymenu</link>)
-#define VIDIOC_G_INPUT           _IOR('V', 38, int)
-#define VIDIOC_S_INPUT          _IOWR('V', 39, int)
-#define VIDIOC_G_OUTPUT          _IOR('V', 46, int)
-#define VIDIOC_S_OUTPUT         _IOWR('V', 47, int)
-#define VIDIOC_ENUMOUTPUT       _IOWR('V', 48, struct <link linkend="v4l2-output">v4l2_output</link>)
-#define VIDIOC_G_AUDOUT          _IOR('V', 49, struct <link linkend="v4l2-audioout">v4l2_audioout</link>)
-#define VIDIOC_S_AUDOUT          _IOW('V', 50, struct <link linkend="v4l2-audioout">v4l2_audioout</link>)
-#define VIDIOC_G_MODULATOR      _IOWR('V', 54, struct <link linkend="v4l2-modulator">v4l2_modulator</link>)
-#define VIDIOC_S_MODULATOR       _IOW('V', 55, struct <link linkend="v4l2-modulator">v4l2_modulator</link>)
-#define VIDIOC_G_FREQUENCY      _IOWR('V', 56, struct <link linkend="v4l2-frequency">v4l2_frequency</link>)
-#define VIDIOC_S_FREQUENCY       _IOW('V', 57, struct <link linkend="v4l2-frequency">v4l2_frequency</link>)
-#define VIDIOC_CROPCAP          _IOWR('V', 58, struct <link linkend="v4l2-cropcap">v4l2_cropcap</link>)
-#define VIDIOC_G_CROP           _IOWR('V', 59, struct <link linkend="v4l2-crop">v4l2_crop</link>)
-#define VIDIOC_S_CROP            _IOW('V', 60, struct <link linkend="v4l2-crop">v4l2_crop</link>)
-#define VIDIOC_G_JPEGCOMP        _IOR('V', 61, struct <link linkend="v4l2-jpegcompression">v4l2_jpegcompression</link>)
-#define VIDIOC_S_JPEGCOMP        _IOW('V', 62, struct <link linkend="v4l2-jpegcompression">v4l2_jpegcompression</link>)
-#define VIDIOC_QUERYSTD          _IOR('V', 63, v4l2_std_id)
-#define VIDIOC_TRY_FMT          _IOWR('V', 64, struct <link linkend="v4l2-format">v4l2_format</link>)
-#define VIDIOC_ENUMAUDIO        _IOWR('V', 65, struct <link linkend="v4l2-audio">v4l2_audio</link>)
-#define VIDIOC_ENUMAUDOUT       _IOWR('V', 66, struct <link linkend="v4l2-audioout">v4l2_audioout</link>)
-#define VIDIOC_G_PRIORITY        _IOR('V', 67, enum <link linkend="v4l2-priority">v4l2_priority</link>)
-#define VIDIOC_S_PRIORITY        _IOW('V', 68, enum <link linkend="v4l2-priority">v4l2_priority</link>)
-#define VIDIOC_G_SLICED_VBI_CAP _IOWR('V', 69, struct <link linkend="v4l2-sliced-vbi-cap">v4l2_sliced_vbi_cap</link>)
-#define VIDIOC_LOG_STATUS         _IO('V', 70)
-#define VIDIOC_G_EXT_CTRLS      _IOWR('V', 71, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
-#define VIDIOC_S_EXT_CTRLS      _IOWR('V', 72, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
-#define VIDIOC_TRY_EXT_CTRLS    _IOWR('V', 73, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
-#if 1
-#define VIDIOC_ENUM_FRAMESIZES  _IOWR('V', 74, struct <link linkend="v4l2-frmsizeenum">v4l2_frmsizeenum</link>)
-#define VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct <link linkend="v4l2-frmivalenum">v4l2_frmivalenum</link>)
-#define VIDIOC_G_ENC_INDEX       _IOR('V', 76, struct <link linkend="v4l2-enc-idx">v4l2_enc_idx</link>)
-#define VIDIOC_ENCODER_CMD      _IOWR('V', 77, struct <link linkend="v4l2-encoder-cmd">v4l2_encoder_cmd</link>)
-#define VIDIOC_TRY_ENCODER_CMD  _IOWR('V', 78, struct <link linkend="v4l2-encoder-cmd">v4l2_encoder_cmd</link>)
-#endif
-
-#if 1
-/* Experimental, meant for debugging, testing and internal use.
-   Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined.
-   You must be root to use these ioctls. Never use these in applications! */
-#define VIDIOC_DBG_S_REGISTER    _IOW('V', 79, struct <link linkend="v4l2-dbg-register">v4l2_dbg_register</link>)
-#define VIDIOC_DBG_G_REGISTER   _IOWR('V', 80, struct <link linkend="v4l2-dbg-register">v4l2_dbg_register</link>)
-
-/* Experimental, meant for debugging, testing and internal use.
-   Never use this ioctl in applications! */
-#define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct <link linkend="v4l2-dbg-chip-ident">v4l2_dbg_chip_ident</link>)
-#endif
-
-#define VIDIOC_S_HW_FREQ_SEEK    _IOW('V', 82, struct <link linkend="v4l2-hw-freq-seek">v4l2_hw_freq_seek</link>)
-#define VIDIOC_ENUM_DV_PRESETS  _IOWR('V', 83, struct <link linkend="v4l2-dv-enum-preset">v4l2_dv_enum_preset</link>)
-#define VIDIOC_S_DV_PRESET      _IOWR('V', 84, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
-#define VIDIOC_G_DV_PRESET      _IOWR('V', 85, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
-#define VIDIOC_QUERY_DV_PRESET  _IOR('V',  86, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
-#define VIDIOC_S_DV_TIMINGS     _IOWR('V', 87, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
-#define VIDIOC_G_DV_TIMINGS     _IOWR('V', 88, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
-#define VIDIOC_DQEVENT           _IOR('V', 89, struct <link linkend="v4l2-event">v4l2_event</link>)
-#define VIDIOC_SUBSCRIBE_EVENT   _IOW('V', 90, struct <link linkend="v4l2-event-subscription">v4l2_event_subscription</link>)
-#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct <link linkend="v4l2-event-subscription">v4l2_event_subscription</link>)
-
-/* Reminder: when adding new ioctls please add support for them to
-   drivers/media/video/v4l2-compat-ioctl32.c as well! */
-
-#define BASE_VIDIOC_PRIVATE     192             /* 192-255 are private */
-
-#endif /* __LINUX_VIDEODEV2_H */
-</programlisting>
diff --git a/Documentation/DocBook/v4l/vidioc-subscribe-event.xml b/Documentation/DocBook/v4l/vidioc-subscribe-event.xml
deleted file mode 100644 (file)
index 8b50179..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-<refentry id="vidioc-subscribe-event">
-  <refmeta>
-    <refentrytitle>ioctl VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</refentrytitle>
-    &manvol;
-  </refmeta>
-
-  <refnamediv>
-    <refname>VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</refname>
-    <refpurpose>Subscribe or unsubscribe event</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <funcsynopsis>
-      <funcprototype>
-       <funcdef>int <function>ioctl</function></funcdef>
-       <paramdef>int <parameter>fd</parameter></paramdef>
-       <paramdef>int <parameter>request</parameter></paramdef>
-       <paramdef>struct v4l2_event_subscription
-*<parameter>argp</parameter></paramdef>
-      </funcprototype>
-    </funcsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>Arguments</title>
-
-    <variablelist>
-      <varlistentry>
-       <term><parameter>fd</parameter></term>
-       <listitem>
-         <para>&fd;</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><parameter>request</parameter></term>
-       <listitem>
-         <para>VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</para>
-       </listitem>
-      </varlistentry>
-      <varlistentry>
-       <term><parameter>argp</parameter></term>
-       <listitem>
-         <para></para>
-       </listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-
-  <refsect1>
-    <title>Description</title>
-
-    <para>Subscribe or unsubscribe V4L2 event. Subscribed events are
-    dequeued by using the &VIDIOC-DQEVENT; ioctl.</para>
-
-    <table frame="none" pgwide="1" id="v4l2-event-subscription">
-      <title>struct <structname>v4l2_event_subscription</structname></title>
-      <tgroup cols="3">
-       &cs-str;
-       <tbody valign="top">
-         <row>
-           <entry>__u32</entry>
-           <entry><structfield>type</structfield></entry>
-           <entry>Type of the event.</entry>
-         </row>
-         <row>
-           <entry>__u32</entry>
-           <entry><structfield>reserved</structfield>[7]</entry>
-           <entry>Reserved for future extensions. Drivers and applications
-           must set the array to zero.</entry>
-         </row>
-       </tbody>
-      </tgroup>
-    </table>
-
-    <table frame="none" pgwide="1" id="event-type">
-      <title>Event Types</title>
-      <tgroup cols="3">
-       &cs-def;
-       <tbody valign="top">
-         <row>
-           <entry><constant>V4L2_EVENT_ALL</constant></entry>
-           <entry>0</entry>
-           <entry>All events. V4L2_EVENT_ALL is valid only for
-           VIDIOC_UNSUBSCRIBE_EVENT for unsubscribing all events at once.
-           </entry>
-         </row>
-         <row>
-           <entry><constant>V4L2_EVENT_VSYNC</constant></entry>
-           <entry>1</entry>
-           <entry>This event is triggered on the vertical sync.
-           This event has &v4l2-event-vsync; associated with it.
-           </entry>
-         </row>
-         <row>
-           <entry><constant>V4L2_EVENT_EOS</constant></entry>
-           <entry>2</entry>
-           <entry>This event is triggered when the end of a stream is reached.
-           This is typically used with MPEG decoders to report to the application
-           when the last of the MPEG stream has been decoded.
-           </entry>
-         </row>
-         <row>
-           <entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
-           <entry>0x08000000</entry>
-           <entry>Base event number for driver-private events.</entry>
-         </row>
-       </tbody>
-      </tgroup>
-    </table>
-
-    <table frame="none" pgwide="1" id="v4l2-event-vsync">
-      <title>struct <structname>v4l2_event_vsync</structname></title>
-      <tgroup cols="3">
-       &cs-str;
-       <tbody valign="top">
-         <row>
-           <entry>__u8</entry>
-           <entry><structfield>field</structfield></entry>
-           <entry>The upcoming field. See &v4l2-field;.</entry>
-         </row>
-       </tbody>
-      </tgroup>
-    </table>
-
-  </refsect1>
-</refentry>
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index dfab718..5cc699b 100644 (file)
@@ -48,12 +48,19 @@ directory apei/einj. The following files are provided.
 - param1
   This file is used to set the first error parameter value. Effect of
   parameter depends on error_type specified. For memory error, this is
-  physical memory address.
+  physical memory address.  Only available if param_extension module
+  parameter is specified.
 
 - param2
   This file is used to set the second error parameter value. Effect of
   parameter depends on error_type specified. For memory error, this is
-  physical memory address mask.
+  physical memory address mask.  Only available if param_extension
+  module parameter is specified.
+
+Injecting parameter support is a BIOS version specific extension, that
+is, it only works on some BIOS version.  If you want to use it, please
+make sure your BIOS version has the proper support and specify
+"param_extension=y" in module parameter.
 
 For more information about EINJ, please refer to ACPI specification
 version 4.0, section 17.5.
index 6b5c42d..2c656ae 100644 (file)
@@ -4,7 +4,8 @@ dm-crypt
 Device-Mapper's "crypt" target provides transparent encryption of block devices
 using the kernel crypto API.
 
-Parameters: <cipher> <key> <iv_offset> <device path> <offset>
+Parameters: <cipher> <key> <iv_offset> <device path> \
+             <offset> [<#opt_params> <opt_params>]
 
 <cipher>
     Encryption cipher and an optional IV generation mode.
@@ -37,6 +38,24 @@ Parameters: <cipher> <key> <iv_offset> <device path> <offset>
 <offset>
     Starting sector within the device where the encrypted data begins.
 
+<#opt_params>
+    Number of optional parameters. If there are no optional parameters,
+    the optional paramaters section can be skipped or #opt_params can be zero.
+    Otherwise #opt_params is the number of following arguments.
+
+    Example of optional parameters section:
+        1 allow_discards
+
+allow_discards
+    Block discard requests (a.k.a. TRIM) are passed through the crypt device.
+    The default is to ignore discard requests.
+
+    WARNING: Assess the specific security risks carefully before enabling this
+    option.  For example, allowing discards on encrypted devices may lead to
+    the leak of information about the ciphertext device (filesystem type,
+    used space etc.) if the discarded blocks can be located easily on the
+    device later.
+
 Example scripts
 ===============
 LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
index c8efdfd..6ff5c23 100644 (file)
@@ -1,17 +1,53 @@
 dm-flakey
 =========
 
-This target is the same as the linear target except that it returns I/O
-errors periodically.  It's been found useful in simulating failing
-devices for testing purposes.
+This target is the same as the linear target except that it exhibits
+unreliable behaviour periodically.  It's been found useful in simulating
+failing devices for testing purposes.
 
 Starting from the time the table is loaded, the device is available for
-<up interval> seconds, then returns errors for <down interval> seconds,
-and then this cycle repeats.
+<up interval> seconds, then exhibits unreliable behaviour for <down
+interval> seconds, and then this cycle repeats.
 
-Parameters: <dev path> <offset> <up interval> <down interval>
+Also, consider using this in combination with the dm-delay target too,
+which can delay reads and writes and/or send them to different
+underlying devices.
+
+Table parameters
+----------------
+  <dev path> <offset> <up interval> <down interval> \
+    [<num_features> [<feature arguments>]]
+
+Mandatory parameters:
     <dev path>: Full pathname to the underlying block-device, or a
                 "major:minor" device-number.
     <offset>: Starting sector within the device.
     <up interval>: Number of seconds device is available.
     <down interval>: Number of seconds device returns errors.
+
+Optional feature parameters:
+  If no feature parameters are present, during the periods of
+  unreliability, all I/O returns errors.
+
+  drop_writes:
+       All write I/O is silently ignored.
+       Read I/O is handled correctly.
+
+  corrupt_bio_byte <Nth_byte> <direction> <value> <flags>:
+       During <down interval>, replace <Nth_byte> of the data of
+       each matching bio with <value>.
+
+    <Nth_byte>: The offset of the byte to replace.
+               Counting starts at 1, to replace the first byte.
+    <direction>: Either 'r' to corrupt reads or 'w' to corrupt writes.
+                'w' is incompatible with drop_writes.
+    <value>: The value (from 0-255) to write.
+    <flags>: Perform the replacement only if bio->bi_rw has all the
+            selected flags set.
+
+Examples:
+  corrupt_bio_byte 32 r 1 0
+       - replaces the 32nd byte of READ bios with the value 1
+
+  corrupt_bio_byte 224 w 0 32
+       - replaces the 224th byte of REQ_META (=32) bios with the value 0
index 33b6b70..2a8c113 100644 (file)
-Device-mapper RAID (dm-raid) is a bridge from DM to MD.  It
-provides a way to use device-mapper interfaces to access the MD RAID
-drivers.
+dm-raid
+-------
 
-As with all device-mapper targets, the nominal public interfaces are the
-constructor (CTR) tables and the status outputs (both STATUSTYPE_INFO
-and STATUSTYPE_TABLE).  The CTR table looks like the following:
+The device-mapper RAID (dm-raid) target provides a bridge from DM to MD.
+It allows the MD RAID drivers to be accessed using a device-mapper
+interface.
 
-1: <s> <l> raid \
-2:      <raid_type> <#raid_params> <raid_params> \
-3:      <#raid_devs> <meta_dev1> <dev1> .. <meta_devN> <devN>
-
-Line 1 contains the standard first three arguments to any device-mapper
-target - the start, length, and target type fields.  The target type in
-this case is "raid".
-
-Line 2 contains the arguments that define the particular raid
-type/personality/level, the required arguments for that raid type, and
-any optional arguments.  Possible raid types include: raid4, raid5_la,
-raid5_ls, raid5_rs, raid6_zr, raid6_nr, and raid6_nc.  (raid1 is
-planned for the future.)  The list of required and optional parameters
-is the same for all the current raid types.  The required parameters are
-positional, while the optional parameters are given as key/value pairs.
-The possible parameters are as follows:
- <chunk_size>           Chunk size in sectors.
- [[no]sync]             Force/Prevent RAID initialization
- [rebuild <idx>]        Rebuild the drive indicated by the index
- [daemon_sleep <ms>]    Time between bitmap daemon work to clear bits
- [min_recovery_rate <kB/sec/disk>]      Throttle RAID initialization
- [max_recovery_rate <kB/sec/disk>]      Throttle RAID initialization
- [max_write_behind <sectors>]           See '-write-behind=' (man mdadm)
- [stripe_cache <sectors>]               Stripe cache size for higher RAIDs
-
-Line 3 contains the list of devices that compose the array in
-metadata/data device pairs.  If the metadata is stored separately, a '-'
-is given for the metadata device position.  If a drive has failed or is
-missing at creation time, a '-' can be given for both the metadata and
-data drives for a given position.
-
-NB. Currently all metadata devices must be specified as '-'.
-
-Examples:
-# RAID4 - 4 data drives, 1 parity
+The target is named "raid" and it accepts the following parameters:
+
+  <raid_type> <#raid_params> <raid_params> \
+    <#raid_devs> <metadata_dev0> <dev0> [.. <metadata_devN> <devN>]
+
+<raid_type>:
+  raid1                RAID1 mirroring
+  raid4                RAID4 dedicated parity disk
+  raid5_la     RAID5 left asymmetric
+               - rotating parity 0 with data continuation
+  raid5_ra     RAID5 right asymmetric
+               - rotating parity N with data continuation
+  raid5_ls     RAID5 left symmetric
+               - rotating parity 0 with data restart
+  raid5_rs     RAID5 right symmetric
+               - rotating parity N with data restart
+  raid6_zr     RAID6 zero restart
+               - rotating parity zero (left-to-right) with data restart
+  raid6_nr     RAID6 N restart
+               - rotating parity N (right-to-left) with data restart
+  raid6_nc     RAID6 N continue
+               - rotating parity N (right-to-left) with data continuation
+
+  Refererence: Chapter 4 of
+  http://www.snia.org/sites/default/files/SNIA_DDF_Technical_Position_v2.0.pdf
+
+<#raid_params>: The number of parameters that follow.
+
+<raid_params> consists of
+    Mandatory parameters:
+        <chunk_size>: Chunk size in sectors.  This parameter is often known as
+                     "stripe size".  It is the only mandatory parameter and
+                     is placed first.
+
+    followed by optional parameters (in any order):
+       [sync|nosync]   Force or prevent RAID initialization.
+
+       [rebuild <idx>] Rebuild drive number idx (first drive is 0).
+
+       [daemon_sleep <ms>]
+               Interval between runs of the bitmap daemon that
+               clear bits.  A longer interval means less bitmap I/O but
+               resyncing after a failure is likely to take longer.
+
+       [min_recovery_rate <kB/sec/disk>]  Throttle RAID initialization
+       [max_recovery_rate <kB/sec/disk>]  Throttle RAID initialization
+       [write_mostly <idx>]               Drive index is write-mostly
+       [max_write_behind <sectors>]       See '-write-behind=' (man mdadm)
+       [stripe_cache <sectors>]           Stripe cache size (higher RAIDs only)
+       [region_size <sectors>]
+               The region_size multiplied by the number of regions is the
+               logical size of the array.  The bitmap records the device
+               synchronisation state for each region.
+
+<#raid_devs>: The number of devices composing the array.
+       Each device consists of two entries.  The first is the device
+       containing the metadata (if any); the second is the one containing the
+       data.
+
+       If a drive has failed or is missing at creation time, a '-' can be
+       given for both the metadata and data drives for a given position.
+
+
+Example tables
+--------------
+# RAID4 - 4 data drives, 1 parity (no metadata devices)
 # No metadata devices specified to hold superblock/bitmap info
 # Chunk size of 1MiB
 # (Lines separated for easy reading)
+
 0 1960893648 raid \
         raid4 1 2048 \
         5 - 8:17 - 8:33 - 8:49 - 8:65 - 8:81
 
-# RAID4 - 4 data drives, 1 parity (no metadata devices)
+# RAID4 - 4 data drives, 1 parity (with metadata devices)
 # Chunk size of 1MiB, force RAID initialization,
 #       min recovery rate at 20 kiB/sec/disk
+
 0 1960893648 raid \
-        raid4 4 2048 min_recovery_rate 20 sync\
-        5 - 8:17 - 8:33 - 8:49 - 8:65 - 8:81
+        raid4 4 2048 sync min_recovery_rate 20 \
+        5 8:17 8:18 8:33 8:34 8:49 8:50 8:65 8:66 8:81 8:82
 
-Performing a 'dmsetup table' should display the CTR table used to
-construct the mapping (with possible reordering of optional
-parameters).
+'dmsetup table' displays the table used to construct the mapping.
+The optional parameters are always printed in the order listed
+above with "sync" or "nosync" always output ahead of the other
+arguments, regardless of the order used when originally loading the table.
+Arguments that can be repeated are ordered by value.
 
-Performing a 'dmsetup status' will yield information on the state and
-health of the array.  The output is as follows:
+'dmsetup status' yields information on the state and health of the
+array.
+The output is as follows:
 1: <s> <l> raid \
 2:      <raid_type> <#devices> <1 health char for each dev> <resync_ratio>
 
-Line 1 is standard DM output.  Line 2 is best shown by example:
+Line 1 is the standard output produced by device-mapper.
+Line 2 is produced by the raid target, and best explained by example:
         0 1960893648 raid raid4 5 AAAAA 2/490221568
 Here we can see the RAID type is raid4, there are 5 devices - all of
 which are 'A'live, and the array is 2/490221568 complete with recovery.
+Faulty or missing devices are marked 'D'.  Devices that are out-of-sync
+are marked 'a'.
diff --git a/Documentation/devicetree/bindings/arm/arm-boards b/Documentation/devicetree/bindings/arm/arm-boards
new file mode 100644 (file)
index 0000000..91f2614
--- /dev/null
@@ -0,0 +1,20 @@
+ARM Versatile Application and Platform Baseboards
+-------------------------------------------------
+ARM's development hardware platform with connectors for customizable
+core tiles.  The hardware configuration of the Versatile boards is
+highly customizable.
+
+Required properties (in root node):
+       compatible = "arm,versatile-ab";  /* Application baseboard */
+       compatible = "arm,versatile-pb";  /* Platform baseboard */
+
+Interrupt controllers:
+- VIC required properties:
+       compatible = "arm,versatile-vic";
+       interrupt-controller;
+       #interrupt-cells = <1>;
+
+- SIC required properties:
+       compatible = "arm,versatile-sic";
+       interrupt-controller;
+       #interrupt-cells = <1>;
diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
new file mode 100644 (file)
index 0000000..d1e3f44
--- /dev/null
@@ -0,0 +1,17 @@
+* Freescale Smart Direct Memory Access (SDMA) Controller for i.MX
+
+Required properties:
+- compatible : Should be "fsl,<chip>-sdma"
+- reg : Should contain SDMA registers location and length
+- interrupts : Should contain SDMA interrupt
+- fsl,sdma-ram-script-name : Should contain the full path of SDMA RAM
+  scripts firmware
+
+Examples:
+
+sdma@83fb0000 {
+       compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
+       reg = <0x83fb0000 0x4000>;
+       interrupts = <6>;
+       fsl,sdma-ram-script-name = "sdma-imx51.bin";
+};
index 7190c99..5c2c021 100644 (file)
@@ -10,7 +10,7 @@ Optional properties:
 Each button (key) is represented as a sub-node of "gpio-keys":
 Subnode properties:
 
-       - gpios: OF devcie-tree gpio specificatin.
+       - gpios: OF device-tree gpio specification.
        - label: Descriptive name of the key.
        - linux,code: Keycode to emit.
 
diff --git a/Documentation/devicetree/bindings/i2c/arm-versatile.txt b/Documentation/devicetree/bindings/i2c/arm-versatile.txt
new file mode 100644 (file)
index 0000000..361d31c
--- /dev/null
@@ -0,0 +1,10 @@
+i2c Controller on ARM Versatile platform:
+
+Required properties:
+- compatible : Must be "arm,versatile-i2c";
+- reg
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties:
+- Child nodes conforming to i2c bus binding
diff --git a/Documentation/devicetree/bindings/input/fsl-mma8450.txt b/Documentation/devicetree/bindings/input/fsl-mma8450.txt
new file mode 100644 (file)
index 0000000..a00c94c
--- /dev/null
@@ -0,0 +1,11 @@
+* Freescale MMA8450 3-Axis Accelerometer
+
+Required properties:
+- compatible : "fsl,mma8450".
+
+Example:
+
+accelerometer: mma8450@1c {
+       compatible = "fsl,mma8450";
+       reg = <0x1c>;
+};
diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
new file mode 100644 (file)
index 0000000..ab22fe6
--- /dev/null
@@ -0,0 +1,34 @@
+* Freescale Enhanced Secure Digital Host Controller (eSDHC) for i.MX
+
+The Enhanced Secure Digital Host Controller on Freescale i.MX family
+provides an interface for MMC, SD, and SDIO types of memory cards.
+
+Required properties:
+- compatible : Should be "fsl,<chip>-esdhc"
+- reg : Should contain eSDHC registers location and length
+- interrupts : Should contain eSDHC interrupt
+
+Optional properties:
+- fsl,card-wired : Indicate the card is wired to host permanently
+- fsl,cd-internal : Indicate to use controller internal card detection
+- fsl,wp-internal : Indicate to use controller internal write protection
+- cd-gpios : Specify GPIOs for card detection
+- wp-gpios : Specify GPIOs for write protection
+
+Examples:
+
+esdhc@70004000 {
+       compatible = "fsl,imx51-esdhc";
+       reg = <0x70004000 0x4000>;
+       interrupts = <1>;
+       fsl,cd-internal;
+       fsl,wp-internal;
+};
+
+esdhc@70008000 {
+       compatible = "fsl,imx51-esdhc";
+       reg = <0x70008000 0x4000>;
+       interrupts = <2>;
+       cd-gpios = <&gpio0 6 0>; /* GPIO1_6 */
+       wp-gpios = <&gpio0 5 0>; /* GPIO1_5 */
+};
diff --git a/Documentation/devicetree/bindings/mtd/arm-versatile.txt b/Documentation/devicetree/bindings/mtd/arm-versatile.txt
new file mode 100644 (file)
index 0000000..476845d
--- /dev/null
@@ -0,0 +1,8 @@
+Flash device on ARM Versatile board
+
+Required properties:
+- compatible : must be "arm,versatile-flash";
+- bank-width : width in bytes of flash interface.
+
+Optional properties:
+- Subnode partition map from mtd flash binding
index 1a729f0..1ad80d5 100644 (file)
@@ -1,61 +1,24 @@
-CAN Device Tree Bindings
-------------------------
-2011 Freescale Semiconductor, Inc.
+Flexcan CAN contoller on Freescale's ARM and PowerPC system-on-a-chip (SOC).
 
-fsl,flexcan-v1.0 nodes
------------------------
-In addition to the required compatible-, reg- and interrupt-properties, you can
-also specify which clock source shall be used for the controller.
+Required properties:
 
-CPI Clock- Can Protocol Interface Clock
-       This CLK_SRC bit of CTRL(control register) selects the clock source to
-       the CAN Protocol Interface(CPI) to be either the peripheral clock
-       (driven by the PLL) or the crystal oscillator clock. The selected clock
-       is the one fed to the prescaler to generate the Serial Clock (Sclock).
-       The PRESDIV field of CTRL(control register) controls a prescaler that
-       generates the Serial Clock (Sclock), whose period defines the
-       time quantum used to compose the CAN waveform.
+- compatible : Should be "fsl,<processor>-flexcan"
 
-Can Engine Clock Source
-       There are two sources for CAN clock
-       - Platform Clock  It represents the bus clock
-       - Oscillator Clock
+  An implementation should also claim any of the following compatibles
+  that it is fully backwards compatible with:
 
-       Peripheral Clock (PLL)
-       --------------
-                    |
-                   ---------                 -------------
-                   |       |CPI Clock        | Prescaler |       Sclock
-                   |       |---------------->| (1.. 256) |------------>
-                   ---------                 -------------
-                     |  |
-       --------------  ---------------------CLK_SRC
-       Oscillator Clock
+  - fsl,p1010-flexcan
 
-- fsl,flexcan-clock-source : CAN Engine Clock Source.This property selects
-                            the peripheral clock. PLL clock is fed to the
-                            prescaler to generate the Serial Clock (Sclock).
-                            Valid values are "oscillator" and "platform"
-                            "oscillator": CAN engine clock source is oscillator clock.
-                            "platform" The CAN engine clock source is the bus clock
-                            (platform clock).
+- reg : Offset and length of the register set for this device
+- interrupts : Interrupt tuple for this device
+- clock-frequency : The oscillator frequency driving the flexcan device
 
-- fsl,flexcan-clock-divider : for the reference and system clock, an additional
-                             clock divider can be specified.
-- clock-frequency: frequency required to calculate the bitrate for FlexCAN.
+Example:
 
-Note:
-       - v1.0 of flexcan-v1.0 represent the IP block version for P1010 SOC.
-       - P1010 does not have oscillator as the Clock Source.So the default
-         Clock Source is platform clock.
-Examples:
-
-       can0@1c000 {
-               compatible = "fsl,flexcan-v1.0";
+       can@1c000 {
+               compatible = "fsl,p1010-flexcan";
                reg = <0x1c000 0x1000>;
                interrupts = <48 0x2>;
                interrupt-parent = <&mpic>;
-               fsl,flexcan-clock-source = "platform";
-               fsl,flexcan-clock-divider = <2>;
-               clock-frequency = <fixed by u-boot>;
+               clock-frequency = <200000000>; // filled in by bootloader
        };
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
new file mode 100644 (file)
index 0000000..de43951
--- /dev/null
@@ -0,0 +1,24 @@
+* Freescale Fast Ethernet Controller (FEC)
+
+Required properties:
+- compatible : Should be "fsl,<soc>-fec"
+- reg : Address and length of the register set for the device
+- interrupts : Should contain fec interrupt
+- phy-mode : String, operation mode of the PHY interface.
+  Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
+  "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii".
+- phy-reset-gpios : Should specify the gpio for phy reset
+
+Optional properties:
+- local-mac-address : 6 bytes, mac address
+
+Example:
+
+fec@83fec000 {
+       compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+       reg = <0x83fec000 0x4000>;
+       interrupts = <87>;
+       phy-mode = "mii";
+       phy-reset-gpios = <&gpio1 14 0>; /* GPIO2_14 */
+       local-mac-address = [00 04 9F 01 1B B9];
+};
diff --git a/Documentation/devicetree/bindings/net/smsc-lan91c111.txt b/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
new file mode 100644 (file)
index 0000000..953049b
--- /dev/null
@@ -0,0 +1,10 @@
+SMSC LAN91c111 Ethernet mac
+
+Required properties:
+- compatible = "smsc,lan91c111";
+- reg : physical address and size of registers
+- interrupts : interrupt connection
+
+Optional properties:
+- phy-device : phandle to Ethernet phy
+- local-mac-address : Ethernet mac address to use
diff --git a/Documentation/devicetree/bindings/net/smsc911x.txt b/Documentation/devicetree/bindings/net/smsc911x.txt
new file mode 100644 (file)
index 0000000..adb5b57
--- /dev/null
@@ -0,0 +1,38 @@
+* Smart Mixed-Signal Connectivity (SMSC) LAN911x/912x Controller
+
+Required properties:
+- compatible : Should be "smsc,lan<model>", "smsc,lan9115"
+- reg : Address and length of the io space for SMSC LAN
+- interrupts : Should contain SMSC LAN interrupt line
+- interrupt-parent : Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- phy-mode : String, operation mode of the PHY interface.
+  Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
+  "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii".
+
+Optional properties:
+- reg-shift : Specify the quantity to shift the register offsets by
+- reg-io-width : Specify the size (in bytes) of the IO accesses that
+  should be performed on the device.  Valid value for SMSC LAN is
+  2 or 4.  If it's omitted or invalid, the size would be 2.
+- smsc,irq-active-high : Indicates the IRQ polarity is active-high
+- smsc,irq-push-pull : Indicates the IRQ type is push-pull
+- smsc,force-internal-phy : Forces SMSC LAN controller to use
+  internal PHY
+- smsc,force-external-phy : Forces SMSC LAN controller to use
+  external PHY
+- smsc,save-mac-address : Indicates that mac address needs to be saved
+  before resetting the controller
+- local-mac-address : 6 bytes, mac address
+
+Examples:
+
+lan9220@f4000000 {
+       compatible = "smsc,lan9220", "smsc,lan9115";
+       reg = <0xf4000000 0x2000000>;
+       phy-mode = "mii";
+       interrupt-parent = <&gpio1>;
+       interrupts = <31>;
+       reg-io-width = <4>;
+       smsc,irq-push-pull;
+};
diff --git a/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt b/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt
new file mode 100644 (file)
index 0000000..a9c0406
--- /dev/null
@@ -0,0 +1,19 @@
+* Freescale i.MX Universal Asynchronous Receiver/Transmitter (UART)
+
+Required properties:
+- compatible : Should be "fsl,<soc>-uart"
+- reg : Address and length of the register set for the device
+- interrupts : Should contain uart interrupt
+
+Optional properties:
+- fsl,uart-has-rtscts : Indicate the uart has rts and cts
+- fsl,irda-mode : Indicate the uart supports irda mode
+
+Example:
+
+uart@73fbc000 {
+       compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+       reg = <0x73fbc000 0x4000>;
+       interrupts = <31>;
+       fsl,uart-has-rtscts;
+};
diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt b/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt
new file mode 100644 (file)
index 0000000..2144af1
--- /dev/null
@@ -0,0 +1,14 @@
+* Freescale i.MX Watchdog Timer (WDT) Controller
+
+Required properties:
+- compatible : Should be "fsl,<soc>-wdt"
+- reg : Should contain WDT registers location and length
+- interrupts : Should contain WDT interrupt
+
+Examples:
+
+wdt@73f98000 {
+       compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+       reg = <0x73f98000 0x4000>;
+       interrupts = <58>;
+};
diff --git a/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt b/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt
new file mode 100644 (file)
index 0000000..79ead82
--- /dev/null
@@ -0,0 +1,11 @@
+* Samsung's Watchdog Timer Controller
+
+The Samsung's Watchdog controller is used for resuming system operation
+after a preset amount of time during which the WDT reset event has not
+occured.
+
+Required properties:
+- compatible : should be "samsung,s3c2410-wdt"
+- reg : base physical address of the controller and length of memory mapped
+       region.
+- interrupts : interrupt number to the cpu.
index 5a0cb1e..94b7e0f 100644 (file)
@@ -10,87 +10,181 @@ NOTE: For DMA Engine usage in async_tx please see:
 Below is a guide to device driver writers on how to use the Slave-DMA API of the
 DMA Engine. This is applicable only for slave DMA usage only.
 
-The slave DMA usage consists of following steps
+The slave DMA usage consists of following steps:
 1. Allocate a DMA slave channel
 2. Set slave and controller specific parameters
 3. Get a descriptor for transaction
-4. Submit the transaction and wait for callback notification
+4. Submit the transaction
+5. Issue pending requests and wait for callback notification
 
 1. Allocate a DMA slave channel
-Channel allocation is slightly different in the slave DMA context, client
-drivers typically need a channel from a particular DMA controller only and even
-in some cases a specific channel is desired. To request a channel
-dma_request_channel() API is used.
-
-Interface:
-struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
-               dma_filter_fn filter_fn,
-               void *filter_param);
-where dma_filter_fn is defined as:
-typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
-
-When the optional 'filter_fn' parameter is set to NULL dma_request_channel
-simply returns the first channel that satisfies the capability mask.  Otherwise,
-when the mask parameter is insufficient for specifying the necessary channel,
-the filter_fn routine can be used to disposition the available channels in the
-system. The filter_fn routine is called once for each free channel in the
-system.  Upon seeing a suitable channel filter_fn returns DMA_ACK which flags
-that channel to be the return value from dma_request_channel.  A channel
-allocated via this interface is exclusive to the caller, until
-dma_release_channel() is called.
+
+   Channel allocation is slightly different in the slave DMA context,
+   client drivers typically need a channel from a particular DMA
+   controller only and even in some cases a specific channel is desired.
+   To request a channel dma_request_channel() API is used.
+
+   Interface:
+       struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
+                       dma_filter_fn filter_fn,
+                       void *filter_param);
+   where dma_filter_fn is defined as:
+       typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
+
+   The 'filter_fn' parameter is optional, but highly recommended for
+   slave and cyclic channels as they typically need to obtain a specific
+   DMA channel.
+
+   When the optional 'filter_fn' parameter is NULL, dma_request_channel()
+   simply returns the first channel that satisfies the capability mask.
+
+   Otherwise, the 'filter_fn' routine will be called once for each free
+   channel which has a capability in 'mask'.  'filter_fn' is expected to
+   return 'true' when the desired DMA channel is found.
+
+   A channel allocated via this interface is exclusive to the caller,
+   until dma_release_channel() is called.
 
 2. Set slave and controller specific parameters
-Next step is always to pass some specific information to the DMA driver. Most of
-the generic information which a slave DMA can use is in struct dma_slave_config.
-It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA
-burst lengths etc. If some DMA controllers have more parameters to be sent then
-they should try to embed struct dma_slave_config in their controller specific
-structure. That gives flexibility to client to pass more parameters, if
-required.
-
-Interface:
-int dmaengine_slave_config(struct dma_chan *chan,
-                                         struct dma_slave_config *config)
+
+   Next step is always to pass some specific information to the DMA
+   driver.  Most of the generic information which a slave DMA can use
+   is in struct dma_slave_config.  This allows the clients to specify
+   DMA direction, DMA addresses, bus widths, DMA burst lengths etc
+   for the peripheral.
+
+   If some DMA controllers have more parameters to be sent then they
+   should try to embed struct dma_slave_config in their controller
+   specific structure. That gives flexibility to client to pass more
+   parameters, if required.
+
+   Interface:
+       int dmaengine_slave_config(struct dma_chan *chan,
+                                 struct dma_slave_config *config)
+
+   Please see the dma_slave_config structure definition in dmaengine.h
+   for a detailed explaination of the struct members.  Please note
+   that the 'direction' member will be going away as it duplicates the
+   direction given in the prepare call.
 
 3. Get a descriptor for transaction
-For slave usage the various modes of slave transfers supported by the
-DMA-engine are:
-slave_sg       - DMA a list of scatter gather buffers from/to a peripheral
-dma_cyclic     - Perform a cyclic DMA operation from/to a peripheral till the
+
+   For slave usage the various modes of slave transfers supported by the
+   DMA-engine are:
+
+   slave_sg    - DMA a list of scatter gather buffers from/to a peripheral
+   dma_cyclic  - Perform a cyclic DMA operation from/to a peripheral till the
                  operation is explicitly stopped.
-The non NULL return of this transfer API represents a "descriptor" for the given
-transaction.
-
-Interface:
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
-               struct dma_chan *chan,
-               struct scatterlist *dst_sg, unsigned int dst_nents,
-               struct scatterlist *src_sg, unsigned int src_nents,
+
+   A non-NULL return of this transfer API represents a "descriptor" for
+   the given transaction.
+
+   Interface:
+       struct dma_async_tx_descriptor *(*chan->device->device_prep_slave_sg)(
+               struct dma_chan *chan, struct scatterlist *sgl,
+               unsigned int sg_len, enum dma_data_direction direction,
                unsigned long flags);
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
+
+       struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
                struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
                size_t period_len, enum dma_data_direction direction);
 
-4. Submit the transaction and wait for callback notification
-To schedule the transaction to be scheduled by dma device, the "descriptor"
-returned in above (3) needs to be submitted.
-To tell the dma driver that a transaction is ready to be serviced, the
-descriptor->submit() callback needs to be invoked. This chains the descriptor to
-the pending queue.
-The transactions in the pending queue can be activated by calling the
-issue_pending API. If channel is idle then the first transaction in queue is
-started and subsequent ones queued up.
-On completion of the DMA operation the next in queue is submitted and a tasklet
-triggered. The tasklet would then call the client driver completion callback
-routine for notification, if set.
-Interface:
-void dma_async_issue_pending(struct dma_chan *chan);
-
-==============================================================================
-
-Additional usage notes for dma driver writers
-1/ Although DMA engine specifies that completion callback routines cannot submit
-any new operations, but typically for slave DMA subsequent transaction may not
-be available for submit prior to callback routine being called. This requirement
-is not a requirement for DMA-slave devices. But they should take care to drop
-the spin-lock they might be holding before calling the callback routine
+   The peripheral driver is expected to have mapped the scatterlist for
+   the DMA operation prior to calling device_prep_slave_sg, and must
+   keep the scatterlist mapped until the DMA operation has completed.
+   The scatterlist must be mapped using the DMA struct device.  So,
+   normal setup should look like this:
+
+       nr_sg = dma_map_sg(chan->device->dev, sgl, sg_len);
+       if (nr_sg == 0)
+               /* error */
+
+       desc = chan->device->device_prep_slave_sg(chan, sgl, nr_sg,
+                       direction, flags);
+
+   Once a descriptor has been obtained, the callback information can be
+   added and the descriptor must then be submitted.  Some DMA engine
+   drivers may hold a spinlock between a successful preparation and
+   submission so it is important that these two operations are closely
+   paired.
+
+   Note:
+       Although the async_tx API specifies that completion callback
+       routines cannot submit any new operations, this is not the
+       case for slave/cyclic DMA.
+
+       For slave DMA, the subsequent transaction may not be available
+       for submission prior to callback function being invoked, so
+       slave DMA callbacks are permitted to prepare and submit a new
+       transaction.
+
+       For cyclic DMA, a callback function may wish to terminate the
+       DMA via dmaengine_terminate_all().
+
+       Therefore, it is important that DMA engine drivers drop any
+       locks before calling the callback function which may cause a
+       deadlock.
+
+       Note that callbacks will always be invoked from the DMA
+       engines tasklet, never from interrupt context.
+
+4. Submit the transaction
+
+   Once the descriptor has been prepared and the callback information
+   added, it must be placed on the DMA engine drivers pending queue.
+
+   Interface:
+       dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
+
+   This returns a cookie can be used to check the progress of DMA engine
+   activity via other DMA engine calls not covered in this document.
+
+   dmaengine_submit() will not start the DMA operation, it merely adds
+   it to the pending queue.  For this, see step 5, dma_async_issue_pending.
+
+5. Issue pending DMA requests and wait for callback notification
+
+   The transactions in the pending queue can be activated by calling the
+   issue_pending API. If channel is idle then the first transaction in
+   queue is started and subsequent ones queued up.
+
+   On completion of each DMA operation, the next in queue is started and
+   a tasklet triggered. The tasklet will then call the client driver
+   completion callback routine for notification, if set.
+
+   Interface:
+       void dma_async_issue_pending(struct dma_chan *chan);
+
+Further APIs:
+
+1. int dmaengine_terminate_all(struct dma_chan *chan)
+
+   This causes all activity for the DMA channel to be stopped, and may
+   discard data in the DMA FIFO which hasn't been fully transferred.
+   No callback functions will be called for any incomplete transfers.
+
+2. int dmaengine_pause(struct dma_chan *chan)
+
+   This pauses activity on the DMA channel without data loss.
+
+3. int dmaengine_resume(struct dma_chan *chan)
+
+   Resume a previously paused DMA channel.  It is invalid to resume a
+   channel which is not currently paused.
+
+4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
+        dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
+
+   This can be used to check the status of the channel.  Please see
+   the documentation in include/linux/dmaengine.h for a more complete
+   description of this API.
+
+   This can be used in conjunction with dma_async_is_complete() and
+   the cookie returned from 'descriptor->submit()' to check for
+   completion of a specific DMA transaction.
+
+   Note:
+       Not all DMA engine drivers can return reliable information for
+       a running DMA channel.  It is recommended that DMA engine users
+       pause or stop (via dmaengine_terminate_all) the channel before
+       using this API.
old mode 100644 (file)
new mode 100755 (executable)
index 3348d31..c466f58
@@ -27,7 +27,7 @@ use IO::Handle;
                "or51211", "or51132_qam", "or51132_vsb", "bluebird",
                "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718",
                "af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
-               "lme2510c_s7395_old");
+               "lme2510c_s7395_old", "drxk", "drxk_terratec_h5");
 
 # Check args
 syntax() if (scalar(@ARGV) != 1);
@@ -634,6 +634,37 @@ sub lme2510c_s7395_old {
     $outfile;
 }
 
+sub drxk {
+    my $url = "http://l4m-daten.de/files/";
+    my $zipfile = "DDTuner.zip";
+    my $hash = "f5a37b9a20a3534997997c0b1382a3e5";
+    my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
+    my $drvfile = "DDTuner.sys";
+    my $fwfile = "drxk_a3.mc";
+
+    checkstandard();
+
+    wgetfile($zipfile, $url . $zipfile);
+    verify($zipfile, $hash);
+    unzip($zipfile, $tmpdir);
+    extract("$tmpdir/$drvfile", 0x14dd8, 15634, "$fwfile");
+
+    "$fwfile"
+}
+
+sub drxk_terratec_h5 {
+    my $url = "http://www.linuxtv.org/downloads/firmware/";
+    my $hash = "19000dada8e2741162ccc50cc91fa7f1";
+    my $fwfile = "dvb-usb-terratec-h5-drxk.fw";
+
+    checkstandard();
+
+    wgetfile($fwfile, $url . $fwfile);
+    verify($fwfile, $hash);
+
+    "$fwfile"
+}
+
 # ---------------------------------------------------------------
 # Utilities
 
index 7be15e4..82a5d25 100644 (file)
@@ -143,8 +143,7 @@ o provide a way to configure fault attributes
   failslab, fail_page_alloc, and fail_make_request use this way.
   Helper functions:
 
-       init_fault_attr_dentries(entries, attr, name);
-       void cleanup_fault_attr_dentries(entries);
+       fault_create_debugfs_attr(name, parent, attr);
 
 - module parameters
 
index dfd6a9f..c4a6e14 100644 (file)
@@ -296,15 +296,6 @@ Who:       Ravikiran Thirumalai <kiran@scalex86.org>
 
 ---------------------------
 
-What:  CONFIG_THERMAL_HWMON
-When:  January 2009
-Why:   This option was introduced just to allow older lm-sensors userspace
-       to keep working over the upgrade to 2.6.26. At the scheduled time of
-       removal fixed lm-sensors (2.x or 3.x) should be readily available.
-Who:   Rene Herman <rene.herman@gmail.com>
-
----------------------------
-
 What:  Code that is now under CONFIG_WIRELESS_EXT_SYSFS
        (in net/core/net-sysfs.c)
 When:  After the only user (hal) has seen a release with the patches
@@ -527,6 +518,41 @@ Who:       Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 
 ----------------------------
 
+What:  Support for driver specific ioctls in the pwc driver (everything
+       defined in media/pwc-ioctl.h)
+When:  3.3
+Why:   This stems from the v4l1 era, with v4l2 everything can be done with
+       standardized v4l2 API calls
+Who:   Hans de Goede <hdegoede@redhat.com>
+
+----------------------------
+
+What:  Driver specific sysfs API in the pwc driver
+When:  3.3
+Why:   Setting pan/tilt should be done with v4l2 controls, like with other
+       cams. The button is available as a standard input device
+Who:   Hans de Goede <hdegoede@redhat.com>
+
+----------------------------
+
+What:  Driver specific use of pixfmt.priv in the pwc driver
+When:  3.3
+Why:   The .priv field never was intended for this, setting a framerate is
+       support using the standardized S_PARM ioctl
+Who:   Hans de Goede <hdegoede@redhat.com>
+
+----------------------------
+
+What:  Software emulation of arbritary resolutions in the pwc driver
+When:  3.3
+Why:   The pwc driver claims to support any resolution between 160x120
+       and 640x480, but emulates this by simply drawing a black border
+       around the image. Userspace can draw its own black border if it
+       really wants one.
+Who:   Hans de Goede <hdegoede@redhat.com>
+
+----------------------------
+
 What:  For VIDIOC_S_FREQUENCY the type field must match the device node's type.
        If not, return -EINVAL.
 When:  3.2
@@ -555,3 +581,14 @@ Why:       This driver has been superseded by g_mass_storage.
 Who:   Alan Stern <stern@rowland.harvard.edu>
 
 ----------------------------
+
+What:   threeg and interface sysfs files in /sys/devices/platform/acer-wmi
+When:   2012
+Why:    In 3.0, we can now autodetect internal 3G device and already have
+       the threeg rfkill device. So, we plan to remove threeg sysfs support
+       for it's no longer necessary.
+
+       We also plan to remove interface sysfs file that exposed which ACPI-WMI
+       interface that was used by acer-wmi driver. It will replaced by
+       information log when acer-wmi initial.
+Who:    Lee, Chun-Yi <jlee@novell.com>
index ace200b..37c4d84 100644 (file)
@@ -106,13 +106,20 @@ separated by spaces:
       To use the first on-chip serial port at baud rate 115200, no parity, 8
       bits, and no flow control.
 
-  (*) root=/dev/<xxxx>
+  (*) root=<xxxx>
 
-      This specifies the device upon which the root filesystem resides. For
-      example:
+      This specifies the device upon which the root filesystem resides. It
+      may be specified by major and minor number, device path, or even
+      partition uuid, if supported.  For example:
 
        /dev/nfs        NFS root filesystem
        /dev/mtdblock3  Fourth RedBoot partition on the System Flash
+       PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF/PARTNROFF=1
+               first partition after the partition with the given UUID
+       253:0           Device with major 253 and minor 0
+
+      Authoritative information can be found in
+      "Documentation/kernel-parameters.txt".
 
   (*) rw
 
index 6a3a647..097b3cc 100644 (file)
@@ -43,8 +43,8 @@ Documentation/hwmon/pmbus for details.
 Sysfs entries
 -------------
 
-The following attributes are supported. Limits are read-write; all other
-attributes are read-only.
+The following attributes are supported. Limits are read-write, history reset
+attributes are write-only, all other attributes are read-only.
 
 in1_label              "vin1" or "vout1" depending on chip variant and
                        configuration.
@@ -53,8 +53,12 @@ in1_min                      Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
 in1_max                        Maximum voltage. From VOUT_OV_WARN_LIMIT register.
 in1_min_alarm          Voltage low alarm. From VOLTAGE_UV_WARNING status.
 in1_max_alarm          Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in1_highest            Historical maximum voltage.
+in1_reset_history      Write any value to reset history.
 
 curr1_label            "iout1"
 curr1_input            Measured current. From READ_IOUT register.
 curr1_max              Maximum current. From IOUT_OC_WARN_LIMIT register.
 curr1_max_alarm                Current high alarm. From IOUT_OC_WARN_LIMIT register.
+curr1_highest          Historical maximum current.
+curr1_reset_history    Write any value to reset history.
index f85e913..fa8776a 100644 (file)
@@ -35,6 +35,13 @@ the Out-Of-Spec bit. Following table summarizes the exported sysfs files:
 All Sysfs entries are named with their core_id (represented here by 'X').
 tempX_input     - Core temperature (in millidegrees Celsius).
 tempX_max       - All cooling devices should be turned on (on Core2).
+                  Initialized with IA32_THERM_INTERRUPT. When the CPU
+                  temperature reaches this temperature, an interrupt is
+                  generated and tempX_max_alarm is set.
+tempX_max_hyst   - If the CPU temperature falls below than temperature,
+                  an interrupt is generated and tempX_max_alarm is reset.
+tempX_max_alarm  - Set if the temperature reaches or exceeds tempX_max.
+                  Reset if the temperature drops to or below tempX_max_hyst.
 tempX_crit      - Maximum junction temperature (in millidegrees Celsius).
 tempX_crit_alarm - Set when Out-of-spec bit is set, never clears.
                   Correct CPU operation is no longer guaranteed.
diff --git a/Documentation/hwmon/lm25066 b/Documentation/hwmon/lm25066
new file mode 100644 (file)
index 0000000..a21db81
--- /dev/null
@@ -0,0 +1,90 @@
+Kernel driver max8688
+=====================
+
+Supported chips:
+  * National Semiconductor LM25066
+    Prefix: 'lm25066'
+    Addresses scanned: -
+    Datasheets:
+       http://www.national.com/pf/LM/LM25066.html
+       http://www.national.com/pf/LM/LM25066A.html
+  * National Semiconductor LM5064
+    Prefix: 'lm5064'
+    Addresses scanned: -
+    Datasheet:
+       http://www.national.com/pf/LM/LM5064.html
+  * National Semiconductor LM5066
+    Prefix: 'lm5066'
+    Addresses scanned: -
+    Datasheet:
+       http://www.national.com/pf/LM/LM5066.html
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for National Semiconductor LM25066,
+LM5064, and LM5064 Power Management, Monitoring, Control, and Protection ICs.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in1_label              "vin"
+in1_input              Measured input voltage.
+in1_average            Average measured input voltage.
+in1_min                        Minimum input voltage.
+in1_max                        Maximum input voltage.
+in1_min_alarm          Input voltage low alarm.
+in1_max_alarm          Input voltage high alarm.
+
+in2_label              "vout1"
+in2_input              Measured output voltage.
+in2_average            Average measured output voltage.
+in2_min                        Minimum output voltage.
+in2_min_alarm          Output voltage low alarm.
+
+in3_label              "vout2"
+in3_input              Measured voltage on vaux pin
+
+curr1_label            "iin"
+curr1_input            Measured input current.
+curr1_average          Average measured input current.
+curr1_max              Maximum input current.
+curr1_max_alarm                Input current high alarm.
+
+power1_label           "pin"
+power1_input           Measured input power.
+power1_average         Average measured input power.
+power1_max             Maximum input power limit.
+power1_alarm           Input power alarm
+power1_input_highest   Historical maximum power.
+power1_reset_history   Write any value to reset maximum power history.
+
+temp1_input            Measured temperature.
+temp1_max              Maximum temperature.
+temp1_crit             Critical high temperature.
+temp1_max_alarm                Chip temperature high alarm.
+temp1_crit_alarm       Chip temperature critical high alarm.
index f3efd18..9cd14cf 100644 (file)
@@ -113,7 +113,11 @@ Supported chips:
     Prefix: 'w83l771'
     Addresses scanned: I2C 0x4c
     Datasheet: Not publicly available, can be requested from Nuvoton
-
+  * Philips/NXP SA56004X
+    Prefix: 'sa56004'
+    Addresses scanned: I2C 0x48 through 0x4F
+    Datasheet: Publicly available at NXP website
+               http://ics.nxp.com/products/interface/datasheet/sa56004x.pdf
 
 Author: Jean Delvare <khali@linux-fr.org>
 
@@ -193,6 +197,9 @@ W83L771AWG/ASG
   * The AWG and ASG variants only differ in package format.
   * Diode ideality factor configuration (remote sensor) at 0xE3
 
+SA56004X:
+  * Better local resolution
+
 All temperature values are given in degrees Celsius. Resolution
 is 1.0 degree for the local temperature, 0.125 degree for the remote
 temperature, except for the MAX6657, MAX6658 and MAX6659 which have a
diff --git a/Documentation/hwmon/lm95245 b/Documentation/hwmon/lm95245
new file mode 100644 (file)
index 0000000..cbd8aea
--- /dev/null
@@ -0,0 +1,33 @@
+Kernel driver lm95245
+==================
+
+Supported chips:
+  * National Semiconductor LM95245
+    Addresses scanned: I2C 0x18, 0x19, 0x29, 0x4c, 0x4d
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/mpf/LM/LM95245.html
+
+
+Author: Alexander Stein <alexander.stein@systec-electronic.com>
+
+Description
+-----------
+
+The LM95245 is an 11-bit digital temperature sensor with a 2-wire System
+Management Bus (SMBus) interface and TruTherm technology that can monitor
+the temperature of a remote diode as well as its own temperature.
+The LM95245 can be used to very accurately monitor the temperature of
+external devices such as microprocessors.
+
+All temperature values are given in millidegrees Celsius. Local temperature
+is given within a range of -127 to +127.875 degrees. Remote temperatures are
+given within a range of -127 to +255 degrees. Resolution depends on
+temperature input and range.
+
+Each sensor has its own critical limit, but the hysteresis is common to all
+two channels.
+
+The lm95245 driver can change its update interval to a fixed set of values.
+It will round up to the next selectable interval. See the datasheet for exact
+values. Reading sensor values more often will do no harm, but will return
+'old' values.
index 4172899..f6e8bcb 100644 (file)
@@ -50,6 +50,8 @@ in[1-4]_min_alarm     Voltage low alarm. From VOLTAGE_UV_WARNING status.
 in[1-4]_max_alarm      Voltage high alarm. From VOLTAGE_OV_WARNING status.
 in[1-4]_lcrit_alarm    Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
 in[1-4]_crit_alarm     Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
+in[1-4]_highest                Historical maximum voltage.
+in[1-4]_reset_history  Write any value to reset history.
 
 temp1_input            Measured temperature. From READ_TEMPERATURE_1 register.
 temp1_max              Maximum temperature. From OT_WARN_LIMIT register.
@@ -60,3 +62,5 @@ temp1_max_alarm               Chip temperature high alarm. Set by comparing
 temp1_crit_alarm       Chip temperature critical high alarm. Set by comparing
                        READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT
                        status is set.
+temp1_highest          Historical maximum temperature.
+temp1_reset_history    Write any value to reset history.
diff --git a/Documentation/hwmon/max1668 b/Documentation/hwmon/max1668
new file mode 100644 (file)
index 0000000..0616ed9
--- /dev/null
@@ -0,0 +1,60 @@
+Kernel driver max1668
+=====================
+
+Supported chips:
+  * Maxim MAX1668, MAX1805 and MAX1989
+    Prefix: 'max1668'
+    Addresses scanned: I2C 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX1668-MAX1989.pdf
+
+Author:
+    David George <david.george@ska.ac.za>
+
+Description
+-----------
+
+This driver implements support for the Maxim MAX1668, MAX1805 and MAX1989
+chips.
+
+The three devices are very similar, but the MAX1805 has a reduced feature
+set; only two remote temperature inputs vs the four avaible on the other
+two ICs.
+
+The driver is able to distinguish between the devices and creates sysfs
+entries as follows:
+
+MAX1805, MAX1668 and MAX1989:
+
+temp1_input     ro local (ambient) temperature
+temp1_max       rw local temperature maximum threshold for alarm
+temp1_max_alarm ro local temperature maximum threshold alarm
+temp1_min       rw local temperature minimum threshold for alarm
+temp1_min_alarm ro local temperature minimum threshold alarm
+temp2_input     ro remote temperature 1
+temp2_max       rw remote temperature 1 maximum threshold for alarm
+temp2_max_alarm ro remote temperature 1 maximum threshold alarm
+temp2_min       rw remote temperature 1 minimum threshold for alarm
+temp2_min_alarm ro remote temperature 1 minimum threshold alarm
+temp3_input     ro remote temperature 2
+temp3_max       rw remote temperature 2 maximum threshold for alarm
+temp3_max_alarm ro remote temperature 2 maximum threshold alarm
+temp3_min       rw remote temperature 2 minimum threshold for alarm
+temp3_min_alarm ro remote temperature 2 minimum threshold alarm
+
+MAX1668 and MAX1989 only:
+temp4_input     ro remote temperature 3
+temp4_max       rw remote temperature 3 maximum threshold for alarm
+temp4_max_alarm ro remote temperature 3 maximum threshold alarm
+temp4_min       rw remote temperature 3 minimum threshold for alarm
+temp4_min_alarm ro remote temperature 3 minimum threshold alarm
+temp5_input     ro remote temperature 4
+temp5_max       rw remote temperature 4 maximum threshold for alarm
+temp5_max_alarm ro remote temperature 4 maximum threshold alarm
+temp5_min       rw remote temperature 4 minimum threshold for alarm
+temp5_min_alarm ro remote temperature 4 minimum threshold alarm
+
+Module Parameters
+-----------------
+
+* read_only: int
+  Set to non-zero if you wish to prevent write access to alarm thresholds.
index 6c525dd..8ab5153 100644 (file)
@@ -56,6 +56,8 @@ in[1-6]_min_alarm     Voltage low alarm. From VOLTAGE_UV_WARNING status.
 in[1-6]_max_alarm      Voltage high alarm. From VOLTAGE_OV_WARNING status.
 in[1-6]_lcrit_alarm    Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
 in[1-6]_crit_alarm     Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
+in[1-6]_highest                Historical maximum voltage.
+in[1-6]_reset_history  Write any value to reset history.
 
 curr[1-6]_label                "iout[1-6]".
 curr[1-6]_input                Measured current. From READ_IOUT register.
@@ -63,6 +65,8 @@ curr[1-6]_max         Maximum current. From IOUT_OC_WARN_LIMIT register.
 curr[1-6]_crit         Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
 curr[1-6]_max_alarm    Current high alarm. From IOUT_OC_WARNING status.
 curr[1-6]_crit_alarm   Current critical high alarm. From IOUT_OC_FAULT status.
+curr[1-6]_highest      Historical maximum current.
+curr[1-6]_reset_history        Write any value to reset history.
 
                        in6 and curr6 attributes only exist for MAX34440.
 
@@ -75,5 +79,7 @@ temp[1-8]_max         Maximum temperature. From OT_WARN_LIMIT register.
 temp[1-8]_crit         Critical high temperature. From OT_FAULT_LIMIT register.
 temp[1-8]_max_alarm    Temperature high alarm.
 temp[1-8]_crit_alarm   Temperature critical high alarm.
+temp[1-8]_highest      Historical maximum temperature.
+temp[1-8]_reset_history        Write any value to reset history.
 
                        temp7 and temp8 attributes only exist for MAX34440.
index 0ddd3a4..71ed10a 100644 (file)
@@ -50,6 +50,8 @@ in1_min_alarm         Voltage low alarm. From VOLTAGE_UV_WARNING status.
 in1_max_alarm          Voltage high alarm. From VOLTAGE_OV_WARNING status.
 in1_lcrit_alarm                Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
 in1_crit_alarm         Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
+in1_highest            Historical maximum voltage.
+in1_reset_history      Write any value to reset history.
 
 curr1_label            "iout1"
 curr1_input            Measured current. From READ_IOUT register.
@@ -57,6 +59,8 @@ curr1_max             Maximum current. From IOUT_OC_WARN_LIMIT register.
 curr1_crit             Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
 curr1_max_alarm                Current high alarm. From IOUT_OC_WARN_LIMIT register.
 curr1_crit_alarm       Current critical high alarm. From IOUT_OC_FAULT status.
+curr1_highest          Historical maximum current.
+curr1_reset_history    Write any value to reset history.
 
 temp1_input            Measured temperature. From READ_TEMPERATURE_1 register.
 temp1_max              Maximum temperature. From OT_WARN_LIMIT register.
@@ -67,3 +71,5 @@ temp1_max_alarm               Chip temperature high alarm. Set by comparing
 temp1_crit_alarm       Chip temperature critical high alarm. Set by comparing
                        READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT
                        status is set.
+temp1_highest          Historical maximum temperature.
+temp1_reset_history    Write any value to reset history.
diff --git a/Documentation/hwmon/ntc_thermistor b/Documentation/hwmon/ntc_thermistor
new file mode 100644 (file)
index 0000000..3bfda94
--- /dev/null
@@ -0,0 +1,93 @@
+Kernel driver ntc_thermistor
+=================
+
+Supported thermistors:
+* Murata NTC Thermistors NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, NCP15WL333
+  Prefixes: 'ncp15wb473', 'ncp18wb473', 'ncp21wb473', 'ncp03wb473', 'ncp15wl333'
+  Datasheet: Publicly available at Murata
+
+Other NTC thermistors can be supported simply by adding compensation
+tables; e.g., NCP15WL333 support is added by the table ncpXXwl333.
+
+Authors:
+       MyungJoo Ham <myungjoo.ham@samsung.com>
+
+Description
+-----------
+
+The NTC thermistor is a simple thermistor that requires users to provide the
+resistance and lookup the corresponding compensation table to get the
+temperature input.
+
+The NTC driver provides lookup tables with a linear approximation function
+and four circuit models with an option not to use any of the four models.
+
+The four circuit models provided are:
+
+       $: resister, [TH]: the thermistor
+
+ 1. connect = NTC_CONNECTED_POSITIVE, pullup_ohm > 0
+
+   [pullup_uV]
+       |    |
+      [TH]  $ (pullup_ohm)
+       |    |
+       +----+-----------------------[read_uV]
+       |
+       $ (pulldown_ohm)
+       |
+      --- (ground)
+
+ 2. connect = NTC_CONNECTED_POSITIVE, pullup_ohm = 0 (not-connected)
+
+   [pullup_uV]
+       |
+      [TH]
+       |
+       +----------------------------[read_uV]
+       |
+       $ (pulldown_ohm)
+       |
+      --- (ground)
+
+ 3. connect = NTC_CONNECTED_GROUND, pulldown_ohm > 0
+
+   [pullup_uV]
+       |
+       $ (pullup_ohm)
+       |
+       +----+-----------------------[read_uV]
+       |    |
+      [TH]  $ (pulldown_ohm)
+       |    |
+      -------- (ground)
+
+ 4. connect = NTC_CONNECTED_GROUND, pulldown_ohm = 0 (not-connected)
+
+   [pullup_uV]
+       |
+       $ (pullup_ohm)
+       |
+       +----------------------------[read_uV]
+       |
+      [TH]
+       |
+      --- (ground)
+
+When one of the four circuit models is used, read_uV, pullup_uV, pullup_ohm,
+pulldown_ohm, and connect should be provided. When none of the four models
+are suitable or the user can get the resistance directly, the user should
+provide read_ohm and _not_ provide the others.
+
+Sysfs Interface
+---------------
+name           the mandatory global attribute, the thermistor name.
+
+temp1_type     always 4 (thermistor)
+               RO
+
+temp1_input    measure the temperature and provide the measured value.
+               (reading this file initiates the reading procedure.)
+               RO
+
+Note that each NTC thermistor has only _one_ thermistor; thus, only temp1 exists.
index 5e462fc..c36c1c1 100644 (file)
@@ -13,6 +13,13 @@ Supported chips:
     Prefix: 'ltc2978'
     Addresses scanned: -
     Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
+  * ON Semiconductor ADP4000, NCP4200, NCP4208
+    Prefixes: 'adp4000', 'ncp4200', 'ncp4208'
+    Addresses scanned: -
+    Datasheets:
+       http://www.onsemi.com/pub_link/Collateral/ADP4000-D.PDF
+       http://www.onsemi.com/pub_link/Collateral/NCP4200-D.PDF
+       http://www.onsemi.com/pub_link/Collateral/JUNE%202009-%20REV.%200.PDF
   * Generic PMBus devices
     Prefix: 'pmbus'
     Addresses scanned: -
index 8f63c24..a4aa8f6 100644 (file)
@@ -139,6 +139,29 @@ in[0-*]_input      Voltage input value.
                thumb: drivers should report the voltage values at the
                "pins" of the chip.
 
+in[0-*]_average
+               Average voltage
+               Unit: millivolt
+               RO
+
+in[0-*]_lowest
+               Historical minimum voltage
+               Unit: millivolt
+               RO
+
+in[0-*]_highest
+               Historical maximum voltage
+               Unit: millivolt
+               RO
+
+in[0-*]_reset_history
+               Reset inX_lowest and inX_highest
+               WO
+
+in_reset_history
+               Reset inX_lowest and inX_highest for all sensors
+               WO
+
 in[0-*]_label  Suggested voltage channel label.
                Text string
                Should only be created if the driver has hints about what
@@ -407,6 +430,29 @@ curr[1-*]_input    Current input value
                Unit: milliampere
                RO
 
+curr[1-*]_average
+               Average current use
+               Unit: milliampere
+               RO
+
+curr[1-*]_lowest
+               Historical minimum current
+               Unit: milliampere
+               RO
+
+curr[1-*]_highest
+               Historical maximum current
+               Unit: milliampere
+               RO
+
+curr[1-*]_reset_history
+               Reset currX_lowest and currX_highest
+               WO
+
+curr_reset_history
+               Reset currX_lowest and currX_highest for all sensors
+               WO
+
 Also see the Alarms section for status flags associated with currents.
 
 *********
index 72ba8d5..845a191 100644 (file)
@@ -292,6 +292,7 @@ Code  Seq#(hex)     Include File            Comments
                                        <mailto:buk@buks.ipn.de>
 0xA0   all     linux/sdp/sdp.h         Industrial Device Project
                                        <mailto:kenji@bitgate.com>
+0xA2   00-0F   arch/tile/include/asm/hardwall.h
 0xA3   80-8F   Port ACL                in development:
                                        <mailto:tlewis@mindspring.com>
 0xA3   90-9F   linux/dtlk.h
index 4ca9389..78926aa 100644 (file)
@@ -163,6 +163,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
                        See also Documentation/power/pm.txt, pci=noacpi
 
+       acpi_rsdp=      [ACPI,EFI,KEXEC]
+                       Pass the RSDP address to the kernel, mostly used
+                       on machines running EFI runtime service to boot the
+                       second kernel for kdump.
+
        acpi_apic_instance=     [ACPI, IOAPIC]
                        Format: <int>
                        2: use 2nd APIC table, if available
@@ -546,6 +551,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        /proc/<pid>/coredump_filter.
                        See also Documentation/filesystems/proc.txt.
 
+       cpuidle.off=1   [CPU_IDLE]
+                       disable the cpuidle sub-system
+
        cpcihp_generic= [HW,PCI] Generic port I/O CompactPCI driver
                        Format:
                        <first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
@@ -2153,6 +2161,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        [HW,MOUSE] Controls Logitech smartscroll autorepeat.
                        0 = disabled, 1 = enabled (default).
 
+       pstore.backend= Specify the name of the pstore backend to use
+
        pt.             [PARIDE]
                        See Documentation/blockdev/paride.txt.
 
@@ -2238,6 +2248,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        ro              [KNL] Mount root device read-only on boot
 
        root=           [KNL] Root filesystem
+                       See name_to_dev_t comment in init/do_mounts.c.
 
        rootdelay=      [KNL] Delay (in seconds) to pause before attempting to
                        mount the root filesystem
@@ -2669,6 +2680,27 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        vmpoff=         [KNL,S390] Perform z/VM CP command after power off.
                        Format: <command>
 
+       vsyscall=       [X86-64]
+                       Controls the behavior of vsyscalls (i.e. calls to
+                       fixed addresses of 0xffffffffff600x00 from legacy
+                       code).  Most statically-linked binaries and older
+                       versions of glibc use these calls.  Because these
+                       functions are at fixed addresses, they make nice
+                       targets for exploits that can control RIP.
+
+                       emulate     [default] Vsyscalls turn into traps and are
+                                   emulated reasonably safely.
+
+                       native      Vsyscalls are native syscall instructions.
+                                   This is a little bit faster than trapping
+                                   and makes a few dynamic recompilers work
+                                   better than they would in emulation mode.
+                                   It also makes exploits much easier to write.
+
+                       none        Vsyscalls don't work at all.  This makes
+                                   them quite hard to use for exploits but
+                                   might break your system.
+
        vt.cur_default= [VT] Default cursor shape.
                        Format: 0xCCBBAA, where AA, BB, and CC are the same as
                        the parameters of the <Esc>[?A;B;Cc escape sequence;
index c93bed6..97d45f2 100644 (file)
@@ -129,6 +129,20 @@ decimal 11 is the major of SCSI CD-ROMs, and the minor 0 stands for
 the first of these. You can find out all valid major numbers by
 looking into include/linux/major.h.
 
+In addition to major and minor numbers, if the device containing your
+root partition uses a partition table format with unique partition
+identifiers, then you may use them.  For instance,
+"root=PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF".  It is also
+possible to reference another partition on the same device using a
+known partition UUID as the starting point.  For example,
+if partition 5 of the device has the UUID of
+00112233-4455-6677-8899-AABBCCDDEEFF then partition 3 may be found as
+follows:
+  PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF/PARTNROFF=-2
+
+Authoritative information can be found in
+"Documentation/kernel-parameters.txt".
+
 
 2.2) ro, rw
 -----------
index 76a2087..669b5fb 100644 (file)
@@ -310,7 +310,7 @@ is non-immutable. The operation must either configure the hardware or store
 the configuration information to be applied later.
 
 Link configuration must not have any side effect on other links. If an enabled
-link at a sink pad prevents another link at the same pad from being disabled,
+link at a sink pad prevents another link at the same pad from being enabled,
 the link_setup operation must return -EBUSY and can't implicitly disable the
 first enabled link.
 
index 4edd78d..bbce121 100644 (file)
@@ -1,13 +1,21 @@
 00-INDEX
        - this file
+3c359.txt
+       - information on the 3Com TokenLink Velocity XL (3c5359) driver.
 3c505.txt
        - information on the 3Com EtherLink Plus (3c505) driver.
+3c509.txt
+       - information on the 3Com Etherlink III Series Ethernet cards.
 6pack.txt
        - info on the 6pack protocol, an alternative to KISS for AX.25
 DLINK.txt
        - info on the D-Link DE-600/DE-620 parallel port pocket adapters
 PLIP.txt
        - PLIP: The Parallel Line Internet Protocol device driver
+README.ipw2100
+       - README for the Intel PRO/Wireless 2100 driver.
+README.ipw2200
+       - README for the Intel PRO/Wireless 2915ABG and 2200BG driver.
 README.sb1000
        - info on General Instrument/NextLevel SURFboard1000 cable modem.
 alias.txt
@@ -20,8 +28,12 @@ atm.txt
        - info on where to get ATM programs and support for Linux.
 ax25.txt
        - info on using AX.25 and NET/ROM code for Linux
+batman-adv.txt
+       - B.A.T.M.A.N routing protocol on top of layer 2 Ethernet Frames.
 baycom.txt
        - info on the driver for Baycom style amateur radio modems
+bonding.txt
+       - Linux Ethernet Bonding Driver HOWTO: link aggregation in Linux.
 bridge.txt
        - where to get user space programs for ethernet bridging with Linux.
 can.txt
@@ -34,32 +46,60 @@ cxacru.txt
        - Conexant AccessRunner USB ADSL Modem
 cxacru-cf.py
        - Conexant AccessRunner USB ADSL Modem configuration file parser
+cxgb.txt
+       - Release Notes for the Chelsio N210 Linux device driver.
+dccp.txt
+       - the Datagram Congestion Control Protocol (DCCP) (RFC 4340..42).
 de4x5.txt
        - the Digital EtherWORKS DE4?? and DE5?? PCI Ethernet driver
 decnet.txt
        - info on using the DECnet networking layer in Linux.
 depca.txt
        - the Digital DEPCA/EtherWORKS DE1?? and DE2?? LANCE Ethernet driver
+dl2k.txt
+       - README for D-Link DL2000-based Gigabit Ethernet Adapters (dl2k.ko).
+dm9000.txt
+       - README for the Simtec DM9000 Network driver.
 dmfe.txt
        - info on the Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver.
+dns_resolver.txt
+       - The DNS resolver module allows kernel servies to make DNS queries.
+driver.txt
+       - Softnet driver issues.
 e100.txt
        - info on Intel's EtherExpress PRO/100 line of 10/100 boards
 e1000.txt
        - info on Intel's E1000 line of gigabit ethernet boards
+e1000e.txt
+       - README for the Intel Gigabit Ethernet Driver (e1000e).
 eql.txt
        - serial IP load balancing
 ewrk3.txt
        - the Digital EtherWORKS 3 DE203/4/5 Ethernet driver
+fib_trie.txt
+       - Level Compressed Trie (LC-trie) notes: a structure for routing.
 filter.txt
        - Linux Socket Filtering
 fore200e.txt
        - FORE Systems PCA-200E/SBA-200E ATM NIC driver info.
 framerelay.txt
        - info on using Frame Relay/Data Link Connection Identifier (DLCI).
+gen_stats.txt
+       - Generic networking statistics for netlink users.
+generic_hdlc.txt
+       - The generic High Level Data Link Control (HDLC) layer.
 generic_netlink.txt
        - info on Generic Netlink
+gianfar.txt
+       - Gianfar Ethernet Driver.
 ieee802154.txt
        - Linux IEEE 802.15.4 implementation, API and drivers
+ifenslave.c
+       - Configure network interfaces for parallel routing (bonding).
+igb.txt
+       - README for the Intel Gigabit Ethernet Driver (igb).
+igbvf.txt
+       - README for the Intel Gigabit Ethernet Driver (igbvf).
 ip-sysctl.txt
        - /proc/sys/net/ipv4/* variables
 ip_dynaddr.txt
@@ -68,41 +108,117 @@ ipddp.txt
        - AppleTalk-IP Decapsulation and AppleTalk-IP Encapsulation
 iphase.txt
        - Interphase PCI ATM (i)Chip IA Linux driver info.
+ipv6.txt
+       - Options to the ipv6 kernel module.
+ipvs-sysctl.txt
+       - Per-inode explanation of the /proc/sys/net/ipv4/vs interface.
 irda.txt
        - where to get IrDA (infrared) utilities and info for Linux.
+ixgb.txt
+       - README for the Intel 10 Gigabit Ethernet Driver (ixgb).
+ixgbe.txt
+       - README for the Intel 10 Gigabit Ethernet Driver (ixgbe).
+ixgbevf.txt
+       - README for the Intel Virtual Function (VF) Driver (ixgbevf).
+l2tp.txt
+       - User guide to the L2TP tunnel protocol.
 lapb-module.txt
        - programming information of the LAPB module.
 ltpc.txt
        - the Apple or Farallon LocalTalk PC card driver
+mac80211-injection.txt
+       - HOWTO use packet injection with mac80211
 multicast.txt
        - Behaviour of cards under Multicast
+multiqueue.txt
+       - HOWTO for multiqueue network device support.
+netconsole.txt
+       - The network console module netconsole.ko: configuration and notes.
+netdev-features.txt
+       - Network interface features API description.
 netdevices.txt
        - info on network device driver functions exported to the kernel.
+netif-msg.txt
+       - Design of the network interface message level setting (NETIF_MSG_*).
+nfc.txt
+       - The Linux Near Field Communication (NFS) subsystem.
 olympic.txt
        - IBM PCI Pit/Pit-Phy/Olympic Token Ring driver info.
+operstates.txt
+       - Overview of network interface operational states.
+packet_mmap.txt
+       - User guide to memory mapped packet socket rings (PACKET_[RT]X_RING).
+phonet.txt
+       - The Phonet packet protocol used in Nokia cellular modems.
+phy.txt
+       - The PHY abstraction layer.
+pktgen.txt
+       - User guide to the kernel packet generator (pktgen.ko).
 policy-routing.txt
        - IP policy-based routing
+ppp_generic.txt
+       - Information about the generic PPP driver.
+proc_net_tcp.txt
+       - Per inode overview of the /proc/net/tcp and /proc/net/tcp6 interfaces.
+radiotap-headers.txt
+       - Background on radiotap headers.
 ray_cs.txt
        - Raylink Wireless LAN card driver info.
+rds.txt
+       - Background on the reliable, ordered datagram delivery method RDS.
+regulatory.txt
+       - Overview of the Linux wireless regulatory infrastructure.
+rxrpc.txt
+       - Guide to the RxRPC protocol.
+s2io.txt
+       - Release notes for Neterion Xframe I/II 10GbE driver.
+scaling.txt
+       - Explanation of network scaling techniques: RSS, RPS, RFS, aRFS, XPS.
+sctp.txt
+       - Notes on the Linux kernel implementation of the SCTP protocol.
+secid.txt
+       - Explanation of the secid member in flow structures.
 skfp.txt
        - SysKonnect FDDI (SK-5xxx, Compaq Netelligent) driver info.
 smc9.txt
        - the driver for SMC's 9000 series of Ethernet cards
 smctr.txt
        - SMC TokenCard TokenRing Linux driver info.
+spider-net.txt
+       - README for the Spidernet Driver (as found in PS3 / Cell BE).
+stmmac.txt
+       - README for the STMicro Synopsys Ethernet driver.
+tc-actions-env-rules.txt
+       - rules for traffic control (tc) actions.
+timestamping.txt
+       - overview of network packet timestamping variants.
 tcp.txt
        - short blurb on how TCP output takes place.
+tcp-thin.txt
+       - kernel tuning options for low rate 'thin' TCP streams.
 tlan.txt
        - ThunderLAN (Compaq Netelligent 10/100, Olicom OC-2xxx) driver info.
 tms380tr.txt
        - SysKonnect Token Ring ISA/PCI adapter driver info.
+tproxy.txt
+       - Transparent proxy support user guide.
 tuntap.txt
        - TUN/TAP device driver, allowing user space Rx/Tx of packets.
+udplite.txt
+       - UDP-Lite protocol (RFC 3828) introduction.
 vortex.txt
        - info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards.
+vxge.txt
+       - README for the Neterion X3100 PCIe Server Adapter.
 x25.txt
        - general info on X.25 development.
 x25-iface.txt
        - description of the X.25 Packet Layer to LAPB device interface.
+xfrm_proc.txt
+       - description of the statistics package for XFRM.
+xfrm_sync.txt
+       - sync patches for XFRM enable migration of an SA between hosts.
+xfrm_sysctl.txt
+       - description of the XFRM configuration options.
 z8530drv.txt
        - info about Linux driver for Z8530 based HDLC cards for AX.25
index 675612f..91df678 100644 (file)
@@ -238,6 +238,18 @@ ad_select
 
        This option was added in bonding version 3.4.0.
 
+all_slaves_active
+
+       Specifies that duplicate frames (received on inactive ports) should be
+       dropped (0) or delivered (1).
+
+       Normally, bonding will drop duplicate frames (received on inactive
+       ports), which is desirable for most users. But there are some times
+       it is nice to allow duplicate frames to be delivered.
+
+       The default value is 0 (drop duplicate frames received on inactive
+       ports).
+
 arp_interval
 
        Specifies the ARP link monitoring frequency in milliseconds.
@@ -433,6 +445,23 @@ miimon
        determined.  See the High Availability section for additional
        information.  The default value is 0.
 
+min_links
+
+       Specifies the minimum number of links that must be active before
+       asserting carrier. It is similar to the Cisco EtherChannel min-links
+       feature. This allows setting the minimum number of member ports that
+       must be up (link-up state) before marking the bond device as up
+       (carrier on). This is useful for situations where higher level services
+       such as clustering want to ensure a minimum number of low bandwidth
+       links are active before switchover. This option only affect 802.3ad
+       mode.
+
+       The default value is 0. This will cause carrier to be asserted (for
+       802.3ad mode) whenever there is an active aggregator, regardless of the
+       number of available links in that aggregator. Note that, because an
+       aggregator cannot be active without at least one available link,
+       setting this option to 0 or to 1 has the exact same effect.
+
 mode
 
        Specifies one of the bonding policies. The default is
@@ -599,7 +628,7 @@ num_unsol_na
        affect only the active-backup mode.  These options were added for
        bonding versions 3.3.0 and 3.4.0 respectively.
 
-       From Linux 2.6.40 and bonding version 3.7.1, these notifications
+       From Linux 3.0 and bonding version 3.7.1, these notifications
        are generated by the ipv4 and ipv6 code and the numbers of
        repetitions cannot be set independently.
 
index 87b3d15..8935834 100644 (file)
@@ -73,7 +73,7 @@ dev->hard_start_xmit:
        has to lock by itself when needed. It is recommended to use a try lock
        for this and return NETDEV_TX_LOCKED when the spin lock fails.
        The locking there should also properly protect against 
-       set_multicast_list. Note that the use of NETIF_F_LLTX is deprecated.
+       set_rx_mode. Note that the use of NETIF_F_LLTX is deprecated.
        Don't use it for new drivers.
 
        Context: Process with BHs disabled or BH (timer),
@@ -92,7 +92,7 @@ dev->tx_timeout:
        Context: BHs disabled
        Notes: netif_queue_stopped() is guaranteed true
 
-dev->set_multicast_list:
+dev->set_rx_mode:
        Synchronization: netif_tx_lock spinlock.
        Context: BHs disabled
 
diff --git a/Documentation/networking/scaling.txt b/Documentation/networking/scaling.txt
new file mode 100644 (file)
index 0000000..58fd741
--- /dev/null
@@ -0,0 +1,378 @@
+Scaling in the Linux Networking Stack
+
+
+Introduction
+============
+
+This document describes a set of complementary techniques in the Linux
+networking stack to increase parallelism and improve performance for
+multi-processor systems.
+
+The following technologies are described:
+
+  RSS: Receive Side Scaling
+  RPS: Receive Packet Steering
+  RFS: Receive Flow Steering
+  Accelerated Receive Flow Steering
+  XPS: Transmit Packet Steering
+
+
+RSS: Receive Side Scaling
+=========================
+
+Contemporary NICs support multiple receive and transmit descriptor queues
+(multi-queue). On reception, a NIC can send different packets to different
+queues to distribute processing among CPUs. The NIC distributes packets by
+applying a filter to each packet that assigns it to one of a small number
+of logical flows. Packets for each flow are steered to a separate receive
+queue, which in turn can be processed by separate CPUs. This mechanism is
+generally known as “Receive-side Scaling” (RSS). The goal of RSS and
+the other scaling techniques to increase performance uniformly.
+Multi-queue distribution can also be used for traffic prioritization, but
+that is not the focus of these techniques.
+
+The filter used in RSS is typically a hash function over the network
+and/or transport layer headers-- for example, a 4-tuple hash over
+IP addresses and TCP ports of a packet. The most common hardware
+implementation of RSS uses a 128-entry indirection table where each entry
+stores a queue number. The receive queue for a packet is determined
+by masking out the low order seven bits of the computed hash for the
+packet (usually a Toeplitz hash), taking this number as a key into the
+indirection table and reading the corresponding value.
+
+Some advanced NICs allow steering packets to queues based on
+programmable filters. For example, webserver bound TCP port 80 packets
+can be directed to their own receive queue. Such “n-tuple” filters can
+be configured from ethtool (--config-ntuple).
+
+==== RSS Configuration
+
+The driver for a multi-queue capable NIC typically provides a kernel
+module parameter for specifying the number of hardware queues to
+configure. In the bnx2x driver, for instance, this parameter is called
+num_queues. A typical RSS configuration would be to have one receive queue
+for each CPU if the device supports enough queues, or otherwise at least
+one for each memory domain, where a memory domain is a set of CPUs that
+share a particular memory level (L1, L2, NUMA node, etc.).
+
+The indirection table of an RSS device, which resolves a queue by masked
+hash, is usually programmed by the driver at initialization. The
+default mapping is to distribute the queues evenly in the table, but the
+indirection table can be retrieved and modified at runtime using ethtool
+commands (--show-rxfh-indir and --set-rxfh-indir). Modifying the
+indirection table could be done to give different queues different
+relative weights.
+
+== RSS IRQ Configuration
+
+Each receive queue has a separate IRQ associated with it. The NIC triggers
+this to notify a CPU when new packets arrive on the given queue. The
+signaling path for PCIe devices uses message signaled interrupts (MSI-X),
+that can route each interrupt to a particular CPU. The active mapping
+of queues to IRQs can be determined from /proc/interrupts. By default,
+an IRQ may be handled on any CPU. Because a non-negligible part of packet
+processing takes place in receive interrupt handling, it is advantageous
+to spread receive interrupts between CPUs. To manually adjust the IRQ
+affinity of each interrupt see Documentation/IRQ-affinity. Some systems
+will be running irqbalance, a daemon that dynamically optimizes IRQ
+assignments and as a result may override any manual settings.
+
+== Suggested Configuration
+
+RSS should be enabled when latency is a concern or whenever receive
+interrupt processing forms a bottleneck. Spreading load between CPUs
+decreases queue length. For low latency networking, the optimal setting
+is to allocate as many queues as there are CPUs in the system (or the
+NIC maximum, if lower). The most efficient high-rate configuration
+is likely the one with the smallest number of receive queues where no
+receive queue overflows due to a saturated CPU, because in default
+mode with interrupt coalescing enabled, the aggregate number of
+interrupts (and thus work) grows with each additional queue.
+
+Per-cpu load can be observed using the mpstat utility, but note that on
+processors with hyperthreading (HT), each hyperthread is represented as
+a separate CPU. For interrupt handling, HT has shown no benefit in
+initial tests, so limit the number of queues to the number of CPU cores
+in the system.
+
+
+RPS: Receive Packet Steering
+============================
+
+Receive Packet Steering (RPS) is logically a software implementation of
+RSS. Being in software, it is necessarily called later in the datapath.
+Whereas RSS selects the queue and hence CPU that will run the hardware
+interrupt handler, RPS selects the CPU to perform protocol processing
+above the interrupt handler. This is accomplished by placing the packet
+on the desired CPU’s backlog queue and waking up the CPU for processing.
+RPS has some advantages over RSS: 1) it can be used with any NIC,
+2) software filters can easily be added to hash over new protocols,
+3) it does not increase hardware device interrupt rate (although it does
+introduce inter-processor interrupts (IPIs)).
+
+RPS is called during bottom half of the receive interrupt handler, when
+a driver sends a packet up the network stack with netif_rx() or
+netif_receive_skb(). These call the get_rps_cpu() function, which
+selects the queue that should process a packet.
+
+The first step in determining the target CPU for RPS is to calculate a
+flow hash over the packet’s addresses or ports (2-tuple or 4-tuple hash
+depending on the protocol). This serves as a consistent hash of the
+associated flow of the packet. The hash is either provided by hardware
+or will be computed in the stack. Capable hardware can pass the hash in
+the receive descriptor for the packet; this would usually be the same
+hash used for RSS (e.g. computed Toeplitz hash). The hash is saved in
+skb->rx_hash and can be used elsewhere in the stack as a hash of the
+packet’s flow.
+
+Each receive hardware queue has an associated list of CPUs to which
+RPS may enqueue packets for processing. For each received packet,
+an index into the list is computed from the flow hash modulo the size
+of the list. The indexed CPU is the target for processing the packet,
+and the packet is queued to the tail of that CPU’s backlog queue. At
+the end of the bottom half routine, IPIs are sent to any CPUs for which
+packets have been queued to their backlog queue. The IPI wakes backlog
+processing on the remote CPU, and any queued packets are then processed
+up the networking stack.
+
+==== RPS Configuration
+
+RPS requires a kernel compiled with the CONFIG_RPS kconfig symbol (on
+by default for SMP). Even when compiled in, RPS remains disabled until
+explicitly configured. The list of CPUs to which RPS may forward traffic
+can be configured for each receive queue using a sysfs file entry:
+
+ /sys/class/net/<dev>/queues/rx-<n>/rps_cpus
+
+This file implements a bitmap of CPUs. RPS is disabled when it is zero
+(the default), in which case packets are processed on the interrupting
+CPU. Documentation/IRQ-affinity.txt explains how CPUs are assigned to
+the bitmap.
+
+== Suggested Configuration
+
+For a single queue device, a typical RPS configuration would be to set
+the rps_cpus to the CPUs in the same memory domain of the interrupting
+CPU. If NUMA locality is not an issue, this could also be all CPUs in
+the system. At high interrupt rate, it might be wise to exclude the
+interrupting CPU from the map since that already performs much work.
+
+For a multi-queue system, if RSS is configured so that a hardware
+receive queue is mapped to each CPU, then RPS is probably redundant
+and unnecessary. If there are fewer hardware queues than CPUs, then
+RPS might be beneficial if the rps_cpus for each queue are the ones that
+share the same memory domain as the interrupting CPU for that queue.
+
+
+RFS: Receive Flow Steering
+==========================
+
+While RPS steers packets solely based on hash, and thus generally
+provides good load distribution, it does not take into account
+application locality. This is accomplished by Receive Flow Steering
+(RFS). The goal of RFS is to increase datacache hitrate by steering
+kernel processing of packets to the CPU where the application thread
+consuming the packet is running. RFS relies on the same RPS mechanisms
+to enqueue packets onto the backlog of another CPU and to wake up that
+CPU.
+
+In RFS, packets are not forwarded directly by the value of their hash,
+but the hash is used as index into a flow lookup table. This table maps
+flows to the CPUs where those flows are being processed. The flow hash
+(see RPS section above) is used to calculate the index into this table.
+The CPU recorded in each entry is the one which last processed the flow.
+If an entry does not hold a valid CPU, then packets mapped to that entry
+are steered using plain RPS. Multiple table entries may point to the
+same CPU. Indeed, with many flows and few CPUs, it is very likely that
+a single application thread handles flows with many different flow hashes.
+
+rps_sock_table is a global flow table that contains the *desired* CPU for
+flows: the CPU that is currently processing the flow in userspace. Each
+table value is a CPU index that is updated during calls to recvmsg and
+sendmsg (specifically, inet_recvmsg(), inet_sendmsg(), inet_sendpage()
+and tcp_splice_read()).
+
+When the scheduler moves a thread to a new CPU while it has outstanding
+receive packets on the old CPU, packets may arrive out of order. To
+avoid this, RFS uses a second flow table to track outstanding packets
+for each flow: rps_dev_flow_table is a table specific to each hardware
+receive queue of each device. Each table value stores a CPU index and a
+counter. The CPU index represents the *current* CPU onto which packets
+for this flow are enqueued for further kernel processing. Ideally, kernel
+and userspace processing occur on the same CPU, and hence the CPU index
+in both tables is identical. This is likely false if the scheduler has
+recently migrated a userspace thread while the kernel still has packets
+enqueued for kernel processing on the old CPU.
+
+The counter in rps_dev_flow_table values records the length of the current
+CPU's backlog when a packet in this flow was last enqueued. Each backlog
+queue has a head counter that is incremented on dequeue. A tail counter
+is computed as head counter + queue length. In other words, the counter
+in rps_dev_flow_table[i] records the last element in flow i that has
+been enqueued onto the currently designated CPU for flow i (of course,
+entry i is actually selected by hash and multiple flows may hash to the
+same entry i).
+
+And now the trick for avoiding out of order packets: when selecting the
+CPU for packet processing (from get_rps_cpu()) the rps_sock_flow table
+and the rps_dev_flow table of the queue that the packet was received on
+are compared. If the desired CPU for the flow (found in the
+rps_sock_flow table) matches the current CPU (found in the rps_dev_flow
+table), the packet is enqueued onto that CPU’s backlog. If they differ,
+the current CPU is updated to match the desired CPU if one of the
+following is true:
+
+- The current CPU's queue head counter >= the recorded tail counter
+  value in rps_dev_flow[i]
+- The current CPU is unset (equal to NR_CPUS)
+- The current CPU is offline
+
+After this check, the packet is sent to the (possibly updated) current
+CPU. These rules aim to ensure that a flow only moves to a new CPU when
+there are no packets outstanding on the old CPU, as the outstanding
+packets could arrive later than those about to be processed on the new
+CPU.
+
+==== RFS Configuration
+
+RFS is only available if the kconfig symbol CONFIG_RFS is enabled (on
+by default for SMP). The functionality remains disabled until explicitly
+configured. The number of entries in the global flow table is set through:
+
+ /proc/sys/net/core/rps_sock_flow_entries
+
+The number of entries in the per-queue flow table are set through:
+
+ /sys/class/net/<dev>/queues/tx-<n>/rps_flow_cnt
+
+== Suggested Configuration
+
+Both of these need to be set before RFS is enabled for a receive queue.
+Values for both are rounded up to the nearest power of two. The
+suggested flow count depends on the expected number of active connections
+at any given time, which may be significantly less than the number of open
+connections. We have found that a value of 32768 for rps_sock_flow_entries
+works fairly well on a moderately loaded server.
+
+For a single queue device, the rps_flow_cnt value for the single queue
+would normally be configured to the same value as rps_sock_flow_entries.
+For a multi-queue device, the rps_flow_cnt for each queue might be
+configured as rps_sock_flow_entries / N, where N is the number of
+queues. So for instance, if rps_flow_entries is set to 32768 and there
+are 16 configured receive queues, rps_flow_cnt for each queue might be
+configured as 2048.
+
+
+Accelerated RFS
+===============
+
+Accelerated RFS is to RFS what RSS is to RPS: a hardware-accelerated load
+balancing mechanism that uses soft state to steer flows based on where
+the application thread consuming the packets of each flow is running.
+Accelerated RFS should perform better than RFS since packets are sent
+directly to a CPU local to the thread consuming the data. The target CPU
+will either be the same CPU where the application runs, or at least a CPU
+which is local to the application thread’s CPU in the cache hierarchy.
+
+To enable accelerated RFS, the networking stack calls the
+ndo_rx_flow_steer driver function to communicate the desired hardware
+queue for packets matching a particular flow. The network stack
+automatically calls this function every time a flow entry in
+rps_dev_flow_table is updated. The driver in turn uses a device specific
+method to program the NIC to steer the packets.
+
+The hardware queue for a flow is derived from the CPU recorded in
+rps_dev_flow_table. The stack consults a CPU to hardware queue map which
+is maintained by the NIC driver. This is an auto-generated reverse map of
+the IRQ affinity table shown by /proc/interrupts. Drivers can use
+functions in the cpu_rmap (“CPU affinity reverse map”) kernel library
+to populate the map. For each CPU, the corresponding queue in the map is
+set to be one whose processing CPU is closest in cache locality.
+
+==== Accelerated RFS Configuration
+
+Accelerated RFS is only available if the kernel is compiled with
+CONFIG_RFS_ACCEL and support is provided by the NIC device and driver.
+It also requires that ntuple filtering is enabled via ethtool. The map
+of CPU to queues is automatically deduced from the IRQ affinities
+configured for each receive queue by the driver, so no additional
+configuration should be necessary.
+
+== Suggested Configuration
+
+This technique should be enabled whenever one wants to use RFS and the
+NIC supports hardware acceleration.
+
+XPS: Transmit Packet Steering
+=============================
+
+Transmit Packet Steering is a mechanism for intelligently selecting
+which transmit queue to use when transmitting a packet on a multi-queue
+device. To accomplish this, a mapping from CPU to hardware queue(s) is
+recorded. The goal of this mapping is usually to assign queues
+exclusively to a subset of CPUs, where the transmit completions for
+these queues are processed on a CPU within this set. This choice
+provides two benefits. First, contention on the device queue lock is
+significantly reduced since fewer CPUs contend for the same queue
+(contention can be eliminated completely if each CPU has its own
+transmit queue). Secondly, cache miss rate on transmit completion is
+reduced, in particular for data cache lines that hold the sk_buff
+structures.
+
+XPS is configured per transmit queue by setting a bitmap of CPUs that
+may use that queue to transmit. The reverse mapping, from CPUs to
+transmit queues, is computed and maintained for each network device.
+When transmitting the first packet in a flow, the function
+get_xps_queue() is called to select a queue. This function uses the ID
+of the running CPU as a key into the CPU-to-queue lookup table. If the
+ID matches a single queue, that is used for transmission. If multiple
+queues match, one is selected by using the flow hash to compute an index
+into the set.
+
+The queue chosen for transmitting a particular flow is saved in the
+corresponding socket structure for the flow (e.g. a TCP connection).
+This transmit queue is used for subsequent packets sent on the flow to
+prevent out of order (ooo) packets. The choice also amortizes the cost
+of calling get_xps_queues() over all packets in the flow. To avoid
+ooo packets, the queue for a flow can subsequently only be changed if
+skb->ooo_okay is set for a packet in the flow. This flag indicates that
+there are no outstanding packets in the flow, so the transmit queue can
+change without the risk of generating out of order packets. The
+transport layer is responsible for setting ooo_okay appropriately. TCP,
+for instance, sets the flag when all data for a connection has been
+acknowledged.
+
+==== XPS Configuration
+
+XPS is only available if the kconfig symbol CONFIG_XPS is enabled (on by
+default for SMP). The functionality remains disabled until explicitly
+configured. To enable XPS, the bitmap of CPUs that may use a transmit
+queue is configured using the sysfs file entry:
+
+/sys/class/net/<dev>/queues/tx-<n>/xps_cpus
+
+== Suggested Configuration
+
+For a network device with a single transmission queue, XPS configuration
+has no effect, since there is no choice in this case. In a multi-queue
+system, XPS is preferably configured so that each CPU maps onto one queue.
+If there are as many queues as there are CPUs in the system, then each
+queue can also map onto one CPU, resulting in exclusive pairings that
+experience no contention. If there are fewer queues than CPUs, then the
+best CPUs to share a given queue are probably those that share the cache
+with the CPU that processes transmit completions for that queue
+(transmit interrupts).
+
+
+Further Information
+===================
+RPS and RFS were introduced in kernel 2.6.35. XPS was incorporated into
+2.6.38. Original patches were submitted by Tom Herbert
+(therbert@google.com)
+
+Accelerated RFS was introduced in 2.6.35. Original patches were
+submitted by Ben Hutchings (bhutchings@solarflare.com)
+
+Authors:
+Tom Herbert (therbert@google.com)
+Willem de Bruijn (willemb@google.com)
index 14dd3c6..4ce5450 100644 (file)
@@ -54,11 +54,10 @@ referred to as subsystem-level callbacks in what follows.
 By default, the callbacks are always invoked in process context with interrupts
 enabled.  However, subsystems can use the pm_runtime_irq_safe() helper function
 to tell the PM core that a device's ->runtime_suspend() and ->runtime_resume()
-callbacks should be invoked in atomic context with interrupts disabled
-(->runtime_idle() is still invoked the default way).  This implies that these
-callback routines must not block or sleep, but it also means that the
-synchronous helper functions listed at the end of Section 4 can be used within
-an interrupt handler or in an atomic context.
+callbacks should be invoked in atomic context with interrupts disabled.
+This implies that these callback routines must not block or sleep, but it also
+means that the synchronous helper functions listed at the end of Section 4 can
+be used within an interrupt handler or in an atomic context.
 
 The subsystem-level suspend callback is _entirely_ _responsible_ for handling
 the suspend of the device as appropriate, which may, but need not include
@@ -483,6 +482,7 @@ pm_runtime_suspend()
 pm_runtime_autosuspend()
 pm_runtime_resume()
 pm_runtime_get_sync()
+pm_runtime_put_sync()
 pm_runtime_put_sync_suspend()
 
 5. Runtime PM Initialization, Device Probing and Removal
index 9ed1d9d..1b6e27d 100644 (file)
@@ -1,3 +1,11 @@
+Release Date    : Tue. Jul 26, 2011 17:00:00 PST 2010 -
+                       (emaild-id:megaraidlinux@lsi.com)
+                       Adam Radford
+Current Version : 00.00.05.40-rc1
+Old Version     : 00.00.05.38-rc1
+    1. Fix FastPath I/O to work with degraded RAID 1.
+    2. Add .change_queue_depth support.
+-------------------------------------------------------------------------------
 Release Date    : Wed. May 11, 2011 17:00:00 PST 2010 -
                        (emaild-id:megaraidlinux@lsi.com)
                        Adam Radford
index d72fd2a..256f8ef 100644 (file)
@@ -9,7 +9,7 @@
   <table border="0">
    <tr>
     <td>
-     <a href="http://www.linuxtv.org/downloads/video4linux/API/V4L1_API.html">V4L original API</a>
+     <a href="http://linuxtv.org/downloads/legacy/video4linux/API/V4L1_API.html">V4L original API</a>
     </td>
     <td>
      Obsoleted by V4L2 API
index 87c4634..8910449 100644 (file)
@@ -27,3 +27,5 @@
  26 -> Hauppauge WinTV-HVR1290                             [0070:8551]
  27 -> Mygica X8558 PRO DMB-TH                             [14f1:8578]
  28 -> LEADTEK WinFast PxTV1200                            [107d:6f22]
+ 29 -> GoTView X5 3D Hybrid                                [5654:2390]
+ 30 -> NetUP Dual DVB-T/C-CI RF                            [1b55:e2e4]
index 42517d9..d9c0f11 100644 (file)
@@ -84,3 +84,4 @@
  83 -> Prof 7301 DVB-S/S2                                  [b034:3034]
  84 -> Samsung SMT 7020 DVB-S                              [18ac:dc00,18ac:dccd]
  85 -> Twinhan VP-1027 DVB-S                               [1822:0023]
+ 86 -> TeVii S464 DVB-S/S2                                 [d464:9022]
index 9aae449..4a7b3df 100644 (file)
@@ -74,3 +74,5 @@
  74 -> Actionmaster/LinXcel/Digitus VC211A      (em2800)
  75 -> Dikom DK300                              (em2882)
  76 -> KWorld PlusTV 340U or UB435-Q (ATSC)     (em2870)        [1b80:a340]
+ 77 -> EM2874 Leadership ISDBT                  (em2874)
+ 78 -> PCTV nanoStick T2 290e                   (em28174)
index 6b4c72d..7efae9b 100644 (file)
 181 -> TechoTrend TT-budget T-3000              [13c2:2804]
 182 -> Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid  [17de:b136]
 183 -> Compro VideoMate Vista M1F               [185b:c900]
+184 -> Encore ENLTV-FM 3                        [1a7f:2108]
+185 -> MagicPro ProHDTV Pro2 DMB-TH/Hybrid      [17de:d136]
+186 -> Beholder BeholdTV 501                    [5ace:5010]
+187 -> Beholder BeholdTV 503 FM                 [5ace:5030]
index e67c1db..6323b7a 100644 (file)
@@ -78,8 +78,10 @@ tuner=77 - TCL tuner MF02GIP-5N-E
 tuner=78 - Philips FMD1216MEX MK3 Hybrid Tuner
 tuner=79 - Philips PAL/SECAM multi (FM1216 MK5)
 tuner=80 - Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough
+tuner=81 - Xceive 4000 tuner
 tuner=81 - Partsnic (Daewoo) PTI-5NF05
 tuner=82 - Philips CU1216L
 tuner=83 - NXP TDA18271
 tuner=84 - Sony BTF-Pxn01Z
 tuner=85 - Philips FQ1236 MK5
+tuner=86 - Tena TNF5337 MFD
index 0b72d3f..6fd1af3 100644 (file)
@@ -63,3 +63,5 @@
  62 -> Pinnacle PCTV Bungee USB (PAL) FM                        [2304:0419]
  63 -> Hauppauge WinTv-USB                                      [2400:4200]
  64 -> Pinnacle Studio PCTV USB (NTSC) FM V3                    [2304:0113]
+ 65 -> Nogatech USB MicroCam NTSC (NV3000N)                     [0573:3000]
+ 66 -> Nogatech USB MicroCam PAL (NV3001P)                      [0573:3001]
diff --git a/Documentation/video4linux/README.davinci-vpbe b/Documentation/video4linux/README.davinci-vpbe
new file mode 100644 (file)
index 0000000..7a460b0
--- /dev/null
@@ -0,0 +1,93 @@
+
+                VPBE V4L2 driver design
+ ======================================================================
+
+ File partitioning
+ -----------------
+ V4L2 display device driver
+         drivers/media/video/davinci/vpbe_display.c
+         drivers/media/video/davinci/vpbe_display.h
+
+ VPBE display controller
+         drivers/media/video/davinci/vpbe.c
+         drivers/media/video/davinci/vpbe.h
+
+ VPBE venc sub device driver
+         drivers/media/video/davinci/vpbe_venc.c
+         drivers/media/video/davinci/vpbe_venc.h
+         drivers/media/video/davinci/vpbe_venc_regs.h
+
+ VPBE osd driver
+         drivers/media/video/davinci/vpbe_osd.c
+         drivers/media/video/davinci/vpbe_osd.h
+         drivers/media/video/davinci/vpbe_osd_regs.h
+
+ Functional partitioning
+ -----------------------
+
+ Consists of the following (in the same order as the list under file
+ partitioning):-
+
+ 1. V4L2 display driver
+    Implements creation of video2 and video3 device nodes and
+    provides v4l2 device interface to manage VID0 and VID1 layers.
+
+ 2. Display controller
+    Loads up VENC, OSD and external encoders such as ths8200. It provides
+    a set of API calls to V4L2 drivers to set the output/standards
+    in the VENC or external sub devices. It also provides
+    a device object to access the services from OSD subdevice
+    using sub device ops. The connection of external encoders to VENC LCD
+    controller port is done at init time based on default output and standard
+    selection or at run time when application change the output through
+    V4L2 IOCTLs.
+
+    When connected to an external encoder, vpbe controller is also responsible
+    for setting up the interface between VENC and external encoders based on
+    board specific settings (specified in board-xxx-evm.c). This allows
+    interfacing external encoders such as ths8200. The setup_if_config()
+    is implemented for this as well as configure_venc() (part of the next patch)
+    API to set timings in VENC for a specific display resolution. As of this
+    patch series, the interconnection and enabling and setting of the external
+    encoders is not present, and would be a part of the next patch series.
+
+ 3. VENC subdevice module
+    Responsible for setting outputs provided through internal DACs and also
+    setting timings at LCD controller port when external encoders are connected
+    at the port or LCD panel timings required. When external encoder/LCD panel
+    is connected, the timings for a specific standard/preset is retrieved from
+    the board specific table and the values are used to set the timings in
+    venc using non-standard timing mode.
+
+    Support LCD Panel displays using the VENC. For example to support a Logic
+    PD display, it requires setting up the LCD controller port with a set of
+    timings for the resolution supported and setting the dot clock. So we could
+    add the available outputs as a board specific entry (i.e add the "LogicPD"
+    output name to board-xxx-evm.c). A table of timings for various LCDs
+    supported can be maintained in the board specific setup file to support
+    various LCD displays.As of this patch a basic driver is present, and this
+    support for external encoders and displays forms a part of the next
+    patch series.
+
+ 4. OSD module
+    OSD module implements all OSD layer management and hardware specific
+    features. The VPBE module interacts with the OSD for enabling and
+    disabling appropriate features of the OSD.
+
+ Current status:-
+
+ A fully functional working version of the V4L2 driver is available. This
+ driver has been tested with NTSC and PAL standards and buffer streaming.
+
+ Following are TBDs.
+
+ vpbe display controller
+    - Add support for external encoders.
+    - add support for selecting external encoder as default at probe time.
+
+ vpbe venc sub device
+    - add timings for supporting ths8200
+    - add support for LogicPD LCD.
+
+ FB drivers
+    - Add support for fbdev drivers.- Ready and part of subsequent patches.
index 881e7f4..9346fc8 100644 (file)
@@ -277,16 +277,13 @@ implement g_volatile_ctrl like this:
        {
                switch (ctrl->id) {
                case V4L2_CID_BRIGHTNESS:
-                       ctrl->cur.val = read_reg(0x123);
+                       ctrl->val = read_reg(0x123);
                        break;
                }
        }
 
-The 'new value' union is not used in g_volatile_ctrl. In general controls
-that need to implement g_volatile_ctrl are read-only controls.
-
-Note that if one or more controls in a control cluster are marked as volatile,
-then all the controls in the cluster are seen as volatile.
+Note that you use the 'new value' union as well in g_volatile_ctrl. In general
+controls that need to implement g_volatile_ctrl are read-only controls.
 
 To mark a control as volatile you have to set the is_volatile flag:
 
@@ -453,6 +450,25 @@ In the example above the following are equivalent for the VOLUME case:
        ctrl == ctrl->cluster[AUDIO_CL_VOLUME] == state->audio_cluster[AUDIO_CL_VOLUME]
        ctrl->cluster[AUDIO_CL_MUTE] == state->audio_cluster[AUDIO_CL_MUTE]
 
+In practice using cluster arrays like this becomes very tiresome. So instead
+the following equivalent method is used:
+
+       struct {
+               /* audio cluster */
+               struct v4l2_ctrl *volume;
+               struct v4l2_ctrl *mute;
+       };
+
+The anonymous struct is used to clearly 'cluster' these two control pointers,
+but it serves no other purpose. The effect is the same as creating an
+array with two control pointers. So you can just do:
+
+       state->volume = v4l2_ctrl_new_std(&state->ctrl_handler, ...);
+       state->mute = v4l2_ctrl_new_std(&state->ctrl_handler, ...);
+       v4l2_ctrl_cluster(2, &state->volume);
+
+And in foo_s_ctrl you can use these pointers directly: state->mute->val.
+
 Note that controls in a cluster may be NULL. For example, if for some
 reason mute was never added (because the hardware doesn't support that
 particular feature), then mute will be NULL. So in that case we have a
@@ -475,6 +491,43 @@ controls, then the 'is_new' flag would be 1 for both controls.
 The 'is_new' flag is always 1 when called from v4l2_ctrl_handler_setup().
 
 
+Handling autogain/gain-type Controls with Auto Clusters
+=======================================================
+
+A common type of control cluster is one that handles 'auto-foo/foo'-type
+controls. Typical examples are autogain/gain, autoexposure/exposure,
+autowhitebalance/red balance/blue balance. In all cases you have one controls
+that determines whether another control is handled automatically by the hardware,
+or whether it is under manual control from the user.
+
+If the cluster is in automatic mode, then the manual controls should be
+marked inactive. When the volatile controls are read the g_volatile_ctrl
+operation should return the value that the hardware's automatic mode set up
+automatically.
+
+If the cluster is put in manual mode, then the manual controls should become
+active again and the is_volatile flag should be ignored (so g_volatile_ctrl is
+no longer called while in manual mode).
+
+Finally the V4L2_CTRL_FLAG_UPDATE should be set for the auto control since
+changing that control affects the control flags of the manual controls.
+
+In order to simplify this a special variation of v4l2_ctrl_cluster was
+introduced:
+
+void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
+                       u8 manual_val, bool set_volatile);
+
+The first two arguments are identical to v4l2_ctrl_cluster. The third argument
+tells the framework which value switches the cluster into manual mode. The
+last argument will optionally set the is_volatile flag for the non-auto controls.
+
+The first control of the cluster is assumed to be the 'auto' control.
+
+Using this function will ensure that you don't need to handle all the complex
+flag and volatile handling.
+
+
 VIDIOC_LOG_STATUS Support
 =========================
 
@@ -636,9 +689,7 @@ button controls are write-only controls.
 -EINVAL as the spec says.
 
 5) The spec does not mention what should happen when you try to set/get a
-control class controls. ivtv currently returns -EINVAL (indicating that the
-control ID does not exist) while the framework will return -EACCES, which
-makes more sense.
+control class controls. The framework will return -EACCES.
 
 
 Proposals for Extensions
index cf21f7a..f8dcabf 100644 (file)
@@ -817,11 +817,7 @@ int my_open(struct file *file)
 
        ...
 
-       ret = v4l2_fh_init(&my_fh->fh, vfd);
-       if (ret) {
-               kfree(my_fh);
-               return ret;
-       }
+       v4l2_fh_init(&my_fh->fh, vfd);
 
        ...
 
@@ -844,7 +840,7 @@ int my_release(struct file *file)
 
 Below is a short description of the v4l2_fh functions used:
 
-int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
+void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
 
   Initialise the file handle. This *MUST* be performed in the driver's
   v4l2_file_operations->open() handler.
@@ -901,14 +897,38 @@ V4L2 events
 The V4L2 events provide a generic way to pass events to user space.
 The driver must use v4l2_fh to be able to support V4L2 events.
 
-Useful functions:
+Events are defined by a type and an optional ID. The ID may refer to a V4L2
+object such as a control ID. If unused, then the ID is 0.
+
+When the user subscribes to an event the driver will allocate a number of
+kevent structs for that event. So every (type, ID) event tuple will have
+its own set of kevent structs. This guarantees that if a driver is generating
+lots of events of one type in a short time, then that will not overwrite
+events of another type.
+
+But if you get more events of one type than the number of kevents that were
+reserved, then the oldest event will be dropped and the new one added.
+
+Furthermore, the internal struct v4l2_subscribed_event has merge() and
+replace() callbacks which drivers can set. These callbacks are called when
+a new event is raised and there is no more room. The replace() callback
+allows you to replace the payload of the old event with that of the new event,
+merging any relevant data from the old payload into the new payload that
+replaces it. It is called when this event type has only one kevent struct
+allocated. The merge() callback allows you to merge the oldest event payload
+into that of the second-oldest event payload. It is called when there are two
+or more kevent structs allocated.
 
-- v4l2_event_alloc()
+This way no status information is lost, just the intermediate steps leading
+up to that state.
 
-  To use events, the driver must allocate events for the file handle. By
-  calling the function more than once, the driver may assure that at least n
-  events in total have been allocated. The function may not be called in
-  atomic context.
+A good example of these replace/merge callbacks is in v4l2-event.c:
+ctrls_replace() and ctrls_merge() callbacks for the control event.
+
+Note: these callbacks can be called from interrupt context, so they must be
+fast.
+
+Useful functions:
 
 - v4l2_event_queue()
 
@@ -920,7 +940,9 @@ Useful functions:
 
   The video_device->ioctl_ops->vidioc_subscribe_event must check the driver
   is able to produce events with specified event id. Then it calls
-  v4l2_event_subscribe() to subscribe the event.
+  v4l2_event_subscribe() to subscribe the event. The last argument is the
+  size of the event queue for this event. If it is 0, then the framework
+  will fill in a default value (this depends on the event type).
 
 - v4l2_event_unsubscribe()
 
@@ -935,14 +957,8 @@ Useful functions:
 
   Returns the number of pending events. Useful when implementing poll.
 
-Drivers do not initialise events directly. The events are initialised
-through v4l2_fh_init() if video_device->ioctl_ops->vidioc_subscribe_event is
-non-NULL. This *MUST* be performed in the driver's
-v4l2_file_operations->open() handler.
-
 Events are delivered to user space through the poll system call. The driver
-can use v4l2_fh->events->wait wait_queue_head_t as the argument for
-poll_wait().
+can use v4l2_fh->wait (a wait_queue_head_t) as the argument for poll_wait().
 
 There are standard and private events. New standard events must use the
 smallest available event type. The drivers must allocate their events from
@@ -952,5 +968,4 @@ The first event type in the class is reserved for future use, so the first
 available event type is 'class base + 1'.
 
 An example on how the V4L2 events may be used can be found in the OMAP
-3 ISP driver available at <URL:http://gitorious.org/omap3camera> as of
-writing this.
+3 ISP driver (drivers/media/video/omap3isp).
index ee99451..fc51128 100644 (file)
@@ -8,6 +8,8 @@ src/
        - directory holding watchdog related example programs.
 watchdog-api.txt
        - description of the Linux Watchdog driver API.
+watchdog-kernel-api.txt
+       - description of the Linux WatchDog Timer Driver Core kernel API.
 watchdog-parameters.txt
        - information on driver parameters (for drivers other than
          the ones that have driver-specific files here)
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
new file mode 100644 (file)
index 0000000..4f7c894
--- /dev/null
@@ -0,0 +1,162 @@
+The Linux WatchDog Timer Driver Core kernel API.
+===============================================
+Last reviewed: 22-Jul-2011
+
+Wim Van Sebroeck <wim@iguana.be>
+
+Introduction
+------------
+This document does not describe what a WatchDog Timer (WDT) Driver or Device is.
+It also does not describe the API which can be used by user space to communicate
+with a WatchDog Timer. If you want to know this then please read the following
+file: Documentation/watchdog/watchdog-api.txt .
+
+So what does this document describe? It describes the API that can be used by
+WatchDog Timer Drivers that want to use the WatchDog Timer Driver Core
+Framework. This framework provides all interfacing towards user space so that
+the same code does not have to be reproduced each time. This also means that
+a watchdog timer driver then only needs to provide the different routines
+(operations) that control the watchdog timer (WDT).
+
+The API
+-------
+Each watchdog timer driver that wants to use the WatchDog Timer Driver Core
+must #include <linux/watchdog.h> (you would have to do this anyway when
+writing a watchdog device driver). This include file contains following
+register/unregister routines:
+
+extern int watchdog_register_device(struct watchdog_device *);
+extern void watchdog_unregister_device(struct watchdog_device *);
+
+The watchdog_register_device routine registers a watchdog timer device.
+The parameter of this routine is a pointer to a watchdog_device structure.
+This routine returns zero on success and a negative errno code for failure.
+
+The watchdog_unregister_device routine deregisters a registered watchdog timer
+device. The parameter of this routine is the pointer to the registered
+watchdog_device structure.
+
+The watchdog device structure looks like this:
+
+struct watchdog_device {
+       const struct watchdog_info *info;
+       const struct watchdog_ops *ops;
+       unsigned int bootstatus;
+       unsigned int timeout;
+       unsigned int min_timeout;
+       unsigned int max_timeout;
+       void *driver_data;
+       unsigned long status;
+};
+
+It contains following fields:
+* info: a pointer to a watchdog_info structure. This structure gives some
+  additional information about the watchdog timer itself. (Like it's unique name)
+* ops: a pointer to the list of watchdog operations that the watchdog supports.
+* timeout: the watchdog timer's timeout value (in seconds).
+* min_timeout: the watchdog timer's minimum timeout value (in seconds).
+* max_timeout: the watchdog timer's maximum timeout value (in seconds).
+* bootstatus: status of the device after booting (reported with watchdog
+  WDIOF_* status bits).
+* driver_data: a pointer to the drivers private data of a watchdog device.
+  This data should only be accessed via the watchdog_set_drvadata and
+  watchdog_get_drvdata routines.
+* status: this field contains a number of status bits that give extra
+  information about the status of the device (Like: is the watchdog timer
+  running/active, is the nowayout bit set, is the device opened via
+  the /dev/watchdog interface or not, ...).
+
+The list of watchdog operations is defined as:
+
+struct watchdog_ops {
+       struct module *owner;
+       /* mandatory operations */
+       int (*start)(struct watchdog_device *);
+       int (*stop)(struct watchdog_device *);
+       /* optional operations */
+       int (*ping)(struct watchdog_device *);
+       unsigned int (*status)(struct watchdog_device *);
+       int (*set_timeout)(struct watchdog_device *, unsigned int);
+       long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
+};
+
+It is important that you first define the module owner of the watchdog timer
+driver's operations. This module owner will be used to lock the module when
+the watchdog is active. (This to avoid a system crash when you unload the
+module and /dev/watchdog is still open).
+Some operations are mandatory and some are optional. The mandatory operations
+are:
+* start: this is a pointer to the routine that starts the watchdog timer
+  device.
+  The routine needs a pointer to the watchdog timer device structure as a
+  parameter. It returns zero on success or a negative errno code for failure.
+* stop: with this routine the watchdog timer device is being stopped.
+  The routine needs a pointer to the watchdog timer device structure as a
+  parameter. It returns zero on success or a negative errno code for failure.
+  Some watchdog timer hardware can only be started and not be stopped. The
+  driver supporting this hardware needs to make sure that a start and stop
+  routine is being provided. This can be done by using a timer in the driver
+  that regularly sends a keepalive ping to the watchdog timer hardware.
+
+Not all watchdog timer hardware supports the same functionality. That's why
+all other routines/operations are optional. They only need to be provided if
+they are supported. These optional routines/operations are:
+* ping: this is the routine that sends a keepalive ping to the watchdog timer
+  hardware.
+  The routine needs a pointer to the watchdog timer device structure as a
+  parameter. It returns zero on success or a negative errno code for failure.
+  Most hardware that does not support this as a separate function uses the
+  start function to restart the watchdog timer hardware. And that's also what
+  the watchdog timer driver core does: to send a keepalive ping to the watchdog
+  timer hardware it will either use the ping operation (when available) or the
+  start operation (when the ping operation is not available).
+  (Note: the WDIOC_KEEPALIVE ioctl call will only be active when the
+  WDIOF_KEEPALIVEPING bit has been set in the option field on the watchdog's
+  info structure).
+* status: this routine checks the status of the watchdog timer device. The
+  status of the device is reported with watchdog WDIOF_* status flags/bits.
+* set_timeout: this routine checks and changes the timeout of the watchdog
+  timer device. It returns 0 on success, -EINVAL for "parameter out of range"
+  and -EIO for "could not write value to the watchdog". On success the timeout
+  value of the watchdog_device will be changed to the value that was just used
+  to re-program the watchdog timer device.
+  (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the
+  watchdog's info structure).
+* ioctl: if this routine is present then it will be called first before we do
+  our own internal ioctl call handling. This routine should return -ENOIOCTLCMD
+  if a command is not supported. The parameters that are passed to the ioctl
+  call are: watchdog_device, cmd and arg.
+
+The status bits should (preferably) be set with the set_bit and clear_bit alike
+bit-operations. The status bits that are defined are:
+* WDOG_ACTIVE: this status bit indicates whether or not a watchdog timer device
+  is active or not. When the watchdog is active after booting, then you should
+  set this status bit (Note: when you register the watchdog timer device with
+  this bit set, then opening /dev/watchdog will skip the start operation)
+* WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device
+  was opened via /dev/watchdog.
+  (This bit should only be used by the WatchDog Timer Driver Core).
+* WDOG_ALLOW_RELEASE: this bit stores whether or not the magic close character
+  has been sent (so that we can support the magic close feature).
+  (This bit should only be used by the WatchDog Timer Driver Core).
+* WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog.
+  If this bit is set then the watchdog timer will not be able to stop.
+
+Note: The WatchDog Timer Driver Core supports the magic close feature and
+the nowayout feature. To use the magic close feature you must set the
+WDIOF_MAGICCLOSE bit in the options field of the watchdog's info structure.
+The nowayout feature will overrule the magic close feature.
+
+To get or set driver specific data the following two helper functions should be
+used:
+
+static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
+static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
+
+The watchdog_set_drvdata function allows you to add driver specific data. The
+arguments of this function are the watchdog device where you want to add the
+driver specific data to and a pointer to the data itself.
+
+The watchdog_get_drvdata function allows you to retrieve driver specific data.
+The argument of this function is the watchdog device where you want to retrieve
+data from. The function retruns the pointer to the driver specific data.
index c66c093..579713e 100644 (file)
@@ -117,20 +117,20 @@ Maintainers List (try to look for most precise areas first)
 M:     Philip Blundell <philb@gnu.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/3c505*
+F:     drivers/net/ethernet/i825xx/3c505*
 
 3C59X NETWORK DRIVER
 M:     Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     Documentation/networking/vortex.txt
-F:     drivers/net/3c59x.c
+F:     drivers/net/ethernet/3com/3c59x.c
 
 3CR990 NETWORK DRIVER
 M:     David Dillow <dave@thedillows.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/typhoon*
+F:     drivers/net/ethernet/3com/typhoon*
 
 3WARE SAS/SATA-RAID SCSI DRIVERS (3W-XXXX, 3W-9XXX, 3W-SAS)
 M:     Adam Radford <linuxraid@lsi.com>
@@ -156,7 +156,7 @@ M:  Realtek linux nic maintainers <nic_swsd@realtek.com>
 M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/r8169.c
+F:     drivers/net/ethernet/realtek/r8169.c
 
 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
 M:     Greg Kroah-Hartman <gregkh@suse.de>
@@ -170,8 +170,7 @@ F:  include/linux/serial_8250.h
 8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
 L:     netdev@vger.kernel.org
 S:     Orphan / Obsolete
-F:     drivers/net/*8390*
-F:     drivers/net/ax88796.c
+F:     drivers/net/ethernet/8390/
 
 9P FILE SYSTEM
 M:     Eric Van Hensbergen <ericvh@gmail.com>
@@ -214,7 +213,7 @@ ACENIC DRIVER
 M:     Jes Sorensen <jes@trained-monkey.org>
 L:     linux-acenic@sunsite.dk
 S:     Maintained
-F:     drivers/net/acenic*
+F:     drivers/net/ethernet/alteon/acenic*
 
 ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER
 M:     Peter Feuerer <peter@piie.net>
@@ -746,7 +745,7 @@ L:  linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.arm.linux.org.uk/
 S:     Maintained
 F:     arch/arm/mach-ebsa110/
-F:     drivers/net/arm/am79c961a.*
+F:     drivers/net/ethernet/amd/am79c961a.*
 
 ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6)
 M:     Daniel Ribeiro <drwyrm@gmail.com>
@@ -1015,7 +1014,8 @@ F:        arch/arm/include/asm/hardware/ioc.h
 F:     arch/arm/include/asm/hardware/iomd.h
 F:     arch/arm/include/asm/hardware/memc.h
 F:     arch/arm/mach-rpc/
-F:     drivers/net/arm/ether*
+F:     drivers/net/ethernet/i825xx/ether1*
+F:     drivers/net/ethernet/seeq/ether3*
 F:     drivers/scsi/arm/
 
 ARM/SHARK MACHINE SUPPORT
@@ -1127,7 +1127,7 @@ F:        arch/arm/mach-nuc93x/
 F:     drivers/input/keyboard/w90p910_keypad.c
 F:     drivers/input/touchscreen/w90p910_ts.c
 F:     drivers/watchdog/nuc900_wdt.c
-F:     drivers/net/arm/w90p910_ether.c
+F:     drivers/net/ethernet/nuvoton/w90p910_ether.c
 F:     drivers/mtd/nand/nuc900_nand.c
 F:     drivers/rtc/rtc-nuc900.c
 F:     drivers/spi/spi_nuc900.c
@@ -1283,7 +1283,7 @@ L:        netdev@vger.kernel.org
 W:     http://sourceforge.net/projects/atl1
 W:     http://atl1.sourceforge.net
 S:     Maintained
-F:     drivers/net/atlx/
+F:     drivers/net/ethernet/atheros/
 
 ATM
 M:     Chas Williams <chas@cmf.nrl.navy.mil>
@@ -1323,7 +1323,7 @@ F:        include/video/atmel_lcdc.h
 ATMEL MACB ETHERNET DRIVER
 M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 S:     Supported
-F:     drivers/net/macb.*
+F:     drivers/net/ethernet/cadence/
 
 ATMEL SPI DRIVER
 M:     Nicolas Ferre <nicolas.ferre@atmel.com>
@@ -1446,7 +1446,7 @@ BLACKFIN EMAC DRIVER
 L:     uclinux-dist-devel@blackfin.uclinux.org
 W:     http://blackfin.uclinux.org
 S:     Supported
-F:     drivers/net/bfin_mac.*
+F:     drivers/net/ethernet/adi/
 
 BLACKFIN RTC DRIVER
 M:     Mike Frysinger <vapier.adi@gmail.com>
@@ -1527,27 +1527,27 @@ BROADCOM B44 10/100 ETHERNET DRIVER
 M:     Gary Zambrano <zambrano@broadcom.com>
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     drivers/net/b44.*
+F:     drivers/net/ethernet/broadcom/b44.*
 
 BROADCOM BNX2 GIGABIT ETHERNET DRIVER
 M:     Michael Chan <mchan@broadcom.com>
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     drivers/net/bnx2.*
-F:     drivers/net/bnx2_*
+F:     drivers/net/ethernet/broadcom/bnx2.*
+F:     drivers/net/ethernet/broadcom/bnx2_*
 
 BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
 M:     Eilon Greenstein <eilong@broadcom.com>
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     drivers/net/bnx2x/
+F:     drivers/net/ethernet/broadcom/bnx2x/
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
 M:     Matt Carlson <mcarlson@broadcom.com>
 M:     Michael Chan <mchan@broadcom.com>
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     drivers/net/tg3.*
+F:     drivers/net/ethernet/broadcom/tg3.*
 
 BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
 M:     Brett Rudley <brudley@broadcom.com>
@@ -1577,7 +1577,7 @@ M:        Rasesh Mody <rmody@brocade.com>
 M:     Debashis Dutt <ddutt@brocade.com>
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     drivers/net/bna/
+F:     drivers/net/ethernet/brocade/bna/
 
 BSG (block layer generic sg v4 driver)
 M:     FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
@@ -1762,13 +1762,13 @@ M:      Vasanthy Kolluri <vkolluri@cisco.com>
 M:     Roopa Prabhu <roprabhu@cisco.com>
 M:     David Wang <dwang2@cisco.com>
 S:     Supported
-F:     drivers/net/enic/
+F:     drivers/net/ethernet/cisco/enic/
 
 CIRRUS LOGIC EP93XX ETHERNET DRIVER
 M:     Hartley Sweeten <hsweeten@visionengravers.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/arm/ep93xx_eth.c
+F:     drivers/net/ethernet/cirrus/ep93xx_eth.c
 
 CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER
 M:     Lennert Buytenhek <kernel@wantstofly.org>
@@ -1908,7 +1908,7 @@ CPMAC ETHERNET DRIVER
 M:     Florian Fainelli <florian@openwrt.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/cpmac.c
+F:     drivers/net/ethernet/ti/cpmac.c
 
 CPU FREQUENCY DRIVERS
 M:     Dave Jones <davej@redhat.com>
@@ -1925,6 +1925,12 @@ S:       Maintained
 F:     arch/x86/kernel/cpuid.c
 F:     arch/x86/kernel/msr.c
 
+CPU POWER MONITORING SUBSYSTEM
+M:     Dominik Brodowski <linux@dominikbrodowski.net>
+M:     Thomas Renninger <trenn@suse.de>
+S:     Maintained
+F:     tools/power/cpupower
+
 CPUSETS
 M:     Paul Menage <menage@google.com>
 W:     http://www.bullopensource.org/cpuset/
@@ -1989,7 +1995,7 @@ M:        Divy Le Ray <divy@chelsio.com>
 L:     netdev@vger.kernel.org
 W:     http://www.chelsio.com
 S:     Supported
-F:     drivers/net/cxgb3/
+F:     drivers/net/ethernet/chelsio/cxgb3/
 
 CXGB3 IWARP RNIC DRIVER (IW_CXGB3)
 M:     Steve Wise <swise@chelsio.com>
@@ -2003,7 +2009,7 @@ M:        Dimitris Michailidis <dm@chelsio.com>
 L:     netdev@vger.kernel.org
 W:     http://www.chelsio.com
 S:     Supported
-F:     drivers/net/cxgb4/
+F:     drivers/net/ethernet/chelsio/cxgb4/
 
 CXGB4 IWARP RNIC DRIVER (IW_CXGB4)
 M:     Steve Wise <swise@chelsio.com>
@@ -2017,14 +2023,14 @@ M:      Casey Leedom <leedom@chelsio.com>
 L:     netdev@vger.kernel.org
 W:     http://www.chelsio.com
 S:     Supported
-F:     drivers/net/cxgb4vf/
+F:     drivers/net/ethernet/chelsio/cxgb4vf/
 
 STMMAC ETHERNET DRIVER
 M:     Giuseppe Cavallaro <peppe.cavallaro@st.com>
 L:     netdev@vger.kernel.org
 W:     http://www.stlinux.com
 S:     Supported
-F:     drivers/net/stmmac/
+F:     drivers/net/ethernet/stmicro/stmmac/
 
 CYBERPRO FB DRIVER
 M:     Russell King <linux@arm.linux.org.uk>
@@ -2068,7 +2074,7 @@ DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
 L:     netdev@vger.kernel.org
 S:     Orphan
 F:     Documentation/networking/dmfe.txt
-F:     drivers/net/tulip/dmfe.c
+F:     drivers/net/ethernet/tulip/dmfe.c
 
 DC390/AM53C974 SCSI driver
 M:     Kurt Garloff <garloff@suse.de>
@@ -2107,7 +2113,7 @@ F:        net/decnet/
 DEFXX FDDI NETWORK DRIVER
 M:     "Maciej W. Rozycki" <macro@linux-mips.org>
 S:     Maintained
-F:     drivers/net/defxx.*
+F:     drivers/net/fddi/defxx.*
 
 DELL LAPTOP DRIVER
 M:     Matthew Garrett <mjg59@srcf.ucam.org>
@@ -2460,7 +2466,7 @@ EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER
 M:     Breno Leitao <leitao@linux.vnet.ibm.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/ehea/
+F:     drivers/net/ethernet/ibm/ehea/
 
 EMBEDDED LINUX
 M:     Paul Gortmaker <paul.gortmaker@windriver.com>
@@ -2505,7 +2511,7 @@ ETHEREXPRESS-16 NETWORK DRIVER
 M:     Philip Blundell <philb@gnu.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/eexpress.*
+F:     drivers/net/ethernet/i825xx/eexpress.*
 
 ETHERNET BRIDGE
 M:     Stephen Hemminger <shemminger@linux-foundation.org>
@@ -2519,7 +2525,7 @@ F:        net/bridge/
 ETHERTEAM 16I DRIVER
 M:     Mika Kuoppala <miku@iki.fi>
 S:     Maintained
-F:     drivers/net/eth16i.c
+F:     drivers/net/ethernet/fujitsu/eth16i.c
 
 EXT2 FILE SYSTEM
 M:     Jan Kara <jack@suse.cz>
@@ -2637,9 +2643,8 @@ S:        Maintained
 F:     arch/x86/math-emu/
 
 FRAME RELAY DLCI/FRAD (Sangoma drivers too)
-M:     Mike McLagan <mike.mclagan@linux.org>
 L:     netdev@vger.kernel.org
-S:     Maintained
+S:     Orphan
 F:     drivers/net/wan/dlci.c
 F:     drivers/net/wan/sdla.c
 
@@ -2684,7 +2689,7 @@ M:        Vitaly Bordug <vbordug@ru.mvista.com>
 L:     linuxppc-dev@lists.ozlabs.org
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/fs_enet/
+F:     drivers/net/ethernet/freescale/fs_enet/
 F:     include/linux/fs_enet_pd.h
 
 FREESCALE QUICC ENGINE LIBRARY
@@ -2706,7 +2711,7 @@ M:        Li Yang <leoli@freescale.com>
 L:     netdev@vger.kernel.org
 L:     linuxppc-dev@lists.ozlabs.org
 S:     Maintained
-F:     drivers/net/ucc_geth*
+F:     drivers/net/ethernet/freescale/ucc_geth*
 
 FREESCALE QUICC ENGINE UCC UART DRIVER
 M:     Timur Tabi <timur@freescale.com>
@@ -3044,6 +3049,7 @@ S:        Maintained
 F:     include/linux/hippidevice.h
 F:     include/linux/if_hippi.h
 F:     net/802/hippi.c
+F:     drivers/net/hippi/
 
 HOST AP DRIVER
 M:     Jouni Malinen <j@w1.fi>
@@ -3061,7 +3067,7 @@ F:        drivers/platform/x86/tc1100-wmi.c
 HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
 M:     Jaroslav Kysela <perex@perex.cz>
 S:     Maintained
-F:     drivers/net/hp100.*
+F:     drivers/net/ethernet/hp/hp100.*
 
 HPET:  High Precision Event Timers driver
 M:     Clemens Ladisch <clemens@ladisch.de>
@@ -3159,7 +3165,7 @@ IBM Power Virtual Ethernet Device Driver
 M:     Santiago Leon <santil@linux.vnet.ibm.com>
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     drivers/net/ibmveth.*
+F:     drivers/net/ethernet/ibm/ibmveth.*
 
 IBM ServeRAID RAID DRIVER
 P:     Jack Hammer
@@ -3315,7 +3321,7 @@ F:        arch/arm/mach-ixp4xx/include/mach/qmgr.h
 F:     arch/arm/mach-ixp4xx/include/mach/npe.h
 F:     arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
 F:     arch/arm/mach-ixp4xx/ixp4xx_npe.c
-F:     drivers/net/arm/ixp4xx_eth.c
+F:     drivers/net/ethernet/xscale/ixp4xx_eth.c
 F:     drivers/net/wan/ixp4xx_hss.c
 
 INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
@@ -3327,7 +3333,7 @@ INTEL IXP2000 ETHERNET DRIVER
 M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/ixp2000/
+F:     drivers/net/ethernet/xscale/ixp2000/
 
 INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf)
 M:     Jeff Kirsher <jeffrey.t.kirsher@intel.com>
@@ -3336,13 +3342,13 @@ M:      Bruce Allan <bruce.w.allan@intel.com>
 M:     Carolyn Wyborny <carolyn.wyborny@intel.com>
 M:     Don Skidmore <donald.c.skidmore@intel.com>
 M:     Greg Rose <gregory.v.rose@intel.com>
-M:     PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
+M:     Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
 M:     Alex Duyck <alexander.h.duyck@intel.com>
 M:     John Ronciak <john.ronciak@intel.com>
 L:     e1000-devel@lists.sourceforge.net
 W:     http://e1000.sourceforge.net/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-2.6.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next-2.6.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next.git
 S:     Supported
 F:     Documentation/networking/e100.txt
 F:     Documentation/networking/e1000.txt
@@ -3352,14 +3358,13 @@ F:      Documentation/networking/igbvf.txt
 F:     Documentation/networking/ixgb.txt
 F:     Documentation/networking/ixgbe.txt
 F:     Documentation/networking/ixgbevf.txt
-F:     drivers/net/e100.c
-F:     drivers/net/e1000/
-F:     drivers/net/e1000e/
-F:     drivers/net/igb/
-F:     drivers/net/igbvf/
-F:     drivers/net/ixgb/
-F:     drivers/net/ixgbe/
-F:     drivers/net/ixgbevf/
+F:     drivers/net/ethernet/intel/
+
+INTEL MRST PMU DRIVER
+M:     Len Brown <len.brown@intel.com>
+L:     linux-pm@lists.linux-foundation.org
+S:     Supported
+F:     arch/x86/platform/mrst/pmu.*
 
 INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
 L:     linux-wireless@vger.kernel.org
@@ -3421,7 +3426,7 @@ IOC3 ETHERNET DRIVER
 M:     Ralf Baechle <ralf@linux-mips.org>
 L:     linux-mips@linux-mips.org
 S:     Maintained
-F:     drivers/net/ioc3-eth.c
+F:     drivers/net/ethernet/sgi/ioc3-eth.c
 
 IOC3 SERIAL DRIVER
 M:     Pat Gefre <pfg@sgi.com>
@@ -3439,7 +3444,7 @@ M:        Francois Romieu <romieu@fr.zoreil.com>
 M:     Sorbica Shieh <sorbica@icplus.com.tw>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/ipg.*
+F:     drivers/net/ethernet/icplus/ipg.*
 
 IPATH DRIVER
 M:     Mike Marciniszyn <infinipath@qlogic.com>
@@ -3587,7 +3592,7 @@ JME NETWORK DRIVER
 M:     Guo-Fu Tseng <cooldavid@cooldavid.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/jme.*
+F:     drivers/net/ethernet/jme.*
 
 JOURNALLING FLASH FILE SYSTEM V2 (JFFS2)
 M:     David Woodhouse <dwmw2@infradead.org>
@@ -3894,9 +3899,9 @@ F:        arch/powerpc/platforms/powermac/
 F:     drivers/macintosh/
 
 LINUX FOR POWERPC EMBEDDED MPC5XXX
-M:     Grant Likely <grant.likely@secretlab.ca>
+M:     Anatolij Gustschin <agust@denx.de>
 L:     linuxppc-dev@lists.ozlabs.org
-T:     git git://git.secretlab.ca/git/linux-2.6.git
+T:     git git://git.denx.de/linux-2.6-agust.git
 S:     Maintained
 F:     arch/powerpc/platforms/512x/
 F:     arch/powerpc/platforms/52xx/
@@ -4118,7 +4123,7 @@ MARVELL MV643XX ETHERNET DRIVER
 M:     Lennert Buytenhek <buytenh@wantstofly.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/mv643xx_eth.*
+F:     drivers/net/ethernet/marvell/mv643xx_eth.*
 F:     include/linux/mv643xx.h
 
 MARVELL MWIFIEX WIRELESS DRIVER
@@ -4150,6 +4155,13 @@ S:       Orphan
 F:     drivers/video/matrox/matroxfb_*
 F:     include/linux/matroxfb.h
 
+MAX1668 TEMPERATURE SENSOR DRIVER
+M:     "David George" <david.george@ska.ac.za>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/max1668
+F:     drivers/hwmon/max1668.c
+
 MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
 M:     "Hans J. Koch" <hjk@hansjkoch.de>
 L:     lm-sensors@lm-sensors.org
@@ -4325,12 +4337,12 @@ M:      Andrew Gallatin <gallatin@myri.com>
 L:     netdev@vger.kernel.org
 W:     http://www.myri.com/scs/download-Myri10GE.html
 S:     Supported
-F:     drivers/net/myri10ge/
+F:     drivers/net/ethernet/myricom/myri10ge/
 
 NATSEMI ETHERNET DRIVER (DP8381x)
 M:     Tim Hockin <thockin@hockin.org>
 S:     Maintained
-F:     drivers/net/natsemi.c
+F:     drivers/net/ethernet/natsemi/natsemi.c
 
 NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER
 M:     Daniel Mack <zonque@gmail.com>
@@ -4370,9 +4382,8 @@ W:        http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous
 W:     http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous
 S:     Supported
 F:     Documentation/networking/s2io.txt
-F:     drivers/net/s2io*
 F:     Documentation/networking/vxge.txt
-F:     drivers/net/vxge/
+F:     drivers/net/ethernet/neterion/
 
 NETFILTER/IPTABLES/IPCHAINS
 P:     Rusty Russell
@@ -4396,10 +4407,10 @@ F:      net/*/netfilter/
 F:     net/netfilter/
 
 NETLABEL
-M:     Paul Moore <paul.moore@hp.com>
+M:     Paul Moore <paul@paul-moore.com>
 W:     http://netlabel.sf.net
 L:     netdev@vger.kernel.org
-S:     Supported
+S:     Maintained
 F:     Documentation/netlabel/
 F:     include/net/netlabel.h
 F:     net/netlabel/
@@ -4444,7 +4455,6 @@ F:        include/linux/netdevice.h
 NETWORKING [IPv4/IPv6]
 M:     "David S. Miller" <davem@davemloft.net>
 M:     Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
-M:     "Pekka Savola (ipv6)" <pekkas@netcore.fi>
 M:     James Morris <jmorris@namei.org>
 M:     Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
 M:     Patrick McHardy <kaber@trash.net>
@@ -4457,7 +4467,7 @@ F:        include/net/ip*
 F:     arch/x86/net/*
 
 NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK)
-M:     Paul Moore <paul.moore@hp.com>
+M:     Paul Moore <paul@paul-moore.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 
@@ -4486,11 +4496,12 @@ F:      include/linux/if_*
 F:     include/linux/*device.h
 
 NETXEN (1/10) GbE SUPPORT
-M:     Amit Kumar Salecha <amit.salecha@qlogic.com>
+M:     Sony Chacko <sony.chacko@qlogic.com>
+M:     Rajesh Borundia <rajesh.borundia@qlogic.com>
 L:     netdev@vger.kernel.org
 W:     http://www.qlogic.com
 S:     Supported
-F:     drivers/net/netxen/
+F:     drivers/net/ethernet/qlogic/netxen/
 
 NFC SUBSYSTEM
 M:     Lauro Ramos Venancio <lauro.venancio@openbossa.org>
@@ -4522,7 +4533,7 @@ M:        Jan-Pascal van Best <janpascal@vanbest.org>
 M:     Andreas Mohr <andi@lisas.de>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/ni5010.*
+F:     drivers/net/ethernet/racal/ni5010.*
 
 NILFS2 FILESYSTEM
 M:     KONISHI Ryusuke <konishi.ryusuke@lab.ntt.co.jp>
@@ -4720,6 +4731,7 @@ S:        Maintained
 F:     drivers/of
 F:     include/linux/of*.h
 K:     of_get_property
+K:     of_match_table
 
 OPENRISC ARCHITECTURE
 M:     Jonas Bonn <jonas@southpole.se>
@@ -4787,7 +4799,7 @@ PA SEMI ETHERNET DRIVER
 M:     Olof Johansson <olof@lixom.net>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/pasemi_mac.*
+F:     drivers/net/ethernet/pasemi/*
 
 PA SEMI SMBUS DRIVER
 M:     Olof Johansson <olof@lixom.net>
@@ -4934,7 +4946,7 @@ PCNET32 NETWORK DRIVER
 M:     Don Fry <pcnet32@frontier.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/pcnet32.c
+F:     drivers/net/ethernet/amd/pcnet32.c
 
 PCRYPT PARALLEL CRYPTO ENGINE
 M:     Steffen Klassert <steffen.klassert@secunet.com>
@@ -5010,6 +5022,17 @@ F:       drivers/i2c/busses/i2c-puv3.c
 F:     drivers/video/fb-puv3.c
 F:     drivers/rtc/rtc-puv3.c
 
+PMBUS HARDWARE MONITORING DRIVERS
+M:     Guenter Roeck <guenter.roeck@ericsson.com>
+L:     lm-sensors@lm-sensors.org
+W:     http://www.lm-sensors.org/
+W:     http://www.roeck-us.net/linux/drivers/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
+S:     Maintained
+F:     Documentation/hwmon/pmbus
+F:     drivers/hwmon/pmbus/
+F:     include/linux/i2c/pmbus.h
+
 PMC SIERRA MaxRAID DRIVER
 M:     Anil Ravindranath <anil_ravindranath@pmc-sierra.com>
 L:     linux-scsi@vger.kernel.org
@@ -5055,7 +5078,7 @@ PPP PROTOCOL DRIVERS AND COMPRESSORS
 M:     Paul Mackerras <paulus@samba.org>
 L:     linux-ppp@vger.kernel.org
 S:     Maintained
-F:     drivers/net/ppp_*
+F:     drivers/net/ppp/ppp_*
 
 PPP OVER ATM (RFC 2364)
 M:     Mitchell Blank Jr <mitch@sfgoth.com>
@@ -5066,8 +5089,8 @@ F:        include/linux/atmppp.h
 PPP OVER ETHERNET
 M:     Michal Ostrowski <mostrows@earthlink.net>
 S:     Maintained
-F:     drivers/net/pppoe.c
-F:     drivers/net/pppox.c
+F:     drivers/net/ppp/pppoe.c
+F:     drivers/net/ppp/pppox.c
 
 PPP OVER L2TP
 M:     James Chapman <jchapman@katalix.com>
@@ -5088,7 +5111,7 @@ PPTP DRIVER
 M:     Dmitry Kozlov <xeb@mail.ru>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/pptp.c
+F:     drivers/net/ppp/pptp.c
 W:     http://sourceforge.net/projects/accel-pptp
 
 PREEMPTIBLE KERNEL
@@ -5117,7 +5140,7 @@ M:        Geoff Levand <geoff@infradead.org>
 L:     netdev@vger.kernel.org
 L:     cbe-oss-dev@lists.ozlabs.org
 S:     Maintained
-F:     drivers/net/ps3_gelic_net.*
+F:     drivers/net/ethernet/toshiba/ps3_gelic_net.*
 
 PS3 PLATFORM SUPPORT
 M:     Geoff Levand <geoff@infradead.org>
@@ -5235,23 +5258,24 @@ M:      linux-driver@qlogic.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     Documentation/networking/LICENSE.qla3xxx
-F:     drivers/net/qla3xxx.*
+F:     drivers/net/ethernet/qlogic/qla3xxx.*
 
 QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
-M:     Amit Kumar Salecha <amit.salecha@qlogic.com>
 M:     Anirban Chakraborty <anirban.chakraborty@qlogic.com>
+M:     Sony Chacko <sony.chacko@qlogic.com>
 M:     linux-driver@qlogic.com
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     drivers/net/qlcnic/
+F:     drivers/net/ethernet/qlogic/qlcnic/
 
 QLOGIC QLGE 10Gb ETHERNET DRIVER
+M:     Anirban Chakraborty <anirban.chakraborty@qlogic.com>
 M:     Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
 M:     Ron Mercer <ron.mercer@qlogic.com>
 M:     linux-driver@qlogic.com
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     drivers/net/qlge/
+F:     drivers/net/ethernet/qlogic/qlge/
 
 QNX4 FILESYSTEM
 M:     Anders Larsen <al@alarsen.net>
@@ -5333,7 +5357,7 @@ RDC R6040 FAST ETHERNET DRIVER
 M:     Florian Fainelli <florian@openwrt.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/r6040.c
+F:     drivers/net/ethernet/rdc/r6040.c
 
 RDS - RELIABLE DATAGRAM SOCKETS
 M:     Andy Grover <andy.grover@oracle.com>
@@ -5736,7 +5760,7 @@ M:        Ajit Khaparde <ajit.khaparde@emulex.com>
 L:     netdev@vger.kernel.org
 W:     http://www.emulex.com
 S:     Supported
-F:     drivers/net/benet/
+F:     drivers/net/ethernet/emulex/benet/
 
 SFC NETWORK DRIVER
 M:     Solarflare linux maintainers <linux-net-drivers@solarflare.com>
@@ -5744,7 +5768,7 @@ M:        Steve Hodgson <shodgson@solarflare.com>
 M:     Ben Hutchings <bhutchings@solarflare.com>
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     drivers/net/sfc/
+F:     drivers/net/ethernet/sfc/
 
 SGI GRU DRIVER
 M:     Jack Steiner <steiner@sgi.com>
@@ -5810,14 +5834,14 @@ SIS 190 ETHERNET DRIVER
 M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/sis190.c
+F:     drivers/net/ethernet/sis/sis190.c
 
 SIS 900/7016 FAST ETHERNET DRIVER
 M:     Daniele Venzano <venza@brownhat.org>
 W:     http://www.brownhat.org/sis900.html
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/sis900.*
+F:     drivers/net/ethernet/sis/sis900.*
 
 SIS 96X I2C/SMBUS DRIVER
 M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
@@ -5844,8 +5868,7 @@ SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
 M:     Stephen Hemminger <shemminger@linux-foundation.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/skge.*
-F:     drivers/net/sky2.*
+F:     drivers/net/ethernet/marvell/sk*
 
 SLAB ALLOCATOR
 M:     Christoph Lameter <cl@linux-foundation.org>
@@ -5859,7 +5882,7 @@ F:        mm/sl?b.c
 SMC91x ETHERNET DRIVER
 M:     Nicolas Pitre <nico@fluxnic.net>
 S:     Odd Fixes
-F:     drivers/net/smc91x.*
+F:     drivers/net/ethernet/smsc/smc91x.*
 
 SMM665 HARDWARE MONITOR DRIVER
 M:     Guenter Roeck <linux@roeck-us.net>
@@ -5894,13 +5917,13 @@ M:      Steve Glendinning <steve.glendinning@smsc.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     include/linux/smsc911x.h
-F:     drivers/net/smsc911x.*
+F:     drivers/net/ethernet/smsc/smsc911x.*
 
 SMSC9420 PCI ETHERNET DRIVER
 M:     Steve Glendinning <steve.glendinning@smsc.com>
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     drivers/net/smsc9420.*
+F:     drivers/net/ethernet/smsc/smsc9420.*
 
 SN-IA64 (Itanium) SUB-PLATFORM
 M:     Jes Sorensen <jes@sgi.com>
@@ -5934,7 +5957,7 @@ SONIC NETWORK DRIVER
 M:     Thomas Bogendoerfer <tsbogend@alpha.franken.de>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/sonic.*
+F:     drivers/net/ethernet/natsemi/sonic.*
 
 SONICS SILICON BACKPLANE DRIVER (SSB)
 M:     Michael Buesch <m@bues.ch>
@@ -6075,7 +6098,7 @@ M:        Jens Osterkamp <jens@de.ibm.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     Documentation/networking/spider_net.txt
-F:     drivers/net/spider_net*
+F:     drivers/net/ethernet/toshiba/spider_net*
 
 SPU FILE SYSTEM
 M:     Jeremy Kerr <jk@ozlabs.org>
@@ -6253,7 +6276,7 @@ F:        drivers/staging/xgifb/
 STARFIRE/DURALAN NETWORK DRIVER
 M:     Ion Badulescu <ionut@badula.org>
 S:     Odd Fixes
-F:     drivers/net/starfire*
+F:     drivers/net/ethernet/adaptec/starfire*
 
 SUN3/3X
 M:     Sam Creasey <sammy@sammy.net>
@@ -6262,6 +6285,7 @@ S:        Maintained
 F:     arch/m68k/kernel/*sun3*
 F:     arch/m68k/sun3*/
 F:     arch/m68k/include/asm/sun3*
+F:     drivers/net/ethernet/i825xx/sun3*
 
 SUPERH
 M:     Paul Mundt <lethal@linux-sh.org>
@@ -6305,6 +6329,7 @@ F:        include/linux/sysv_fs.h
 TARGET SUBSYSTEM
 M:     Nicholas A. Bellinger <nab@linux-iscsi.org>
 L:     linux-scsi@vger.kernel.org
+L:     target-devel@vger.kernel.org
 L:     http://groups.google.com/group/linux-iscsi-target-dev
 W:     http://www.linux-iscsi.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/nab/lio-core-2.6.git master
@@ -6349,7 +6374,7 @@ M:        Alexander Indenbaum <baum@tehutinetworks.net>
 M:     Andy Gospodarek <andy@greyhouse.net>
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     drivers/net/tehuti*
+F:     drivers/net/ethernet/tehuti/*
 
 Telecom Clock Driver for MCPL0010
 M:     Mark Gross <mark.gross@intel.com>
@@ -6400,7 +6425,7 @@ W:        http://www.tilera.com/scm/
 S:     Supported
 F:     arch/tile/
 F:     drivers/tty/hvc/hvc_tile.c
-F:     drivers/net/tile/
+F:     drivers/net/ethernet/tile/
 F:     drivers/edac/tile_edac.c
 
 TLAN NETWORK DRIVER
@@ -6409,7 +6434,7 @@ L:        tlan-devel@lists.sourceforge.net (subscribers-only)
 W:     http://sourceforge.net/projects/tlan/
 S:     Maintained
 F:     Documentation/networking/tlan.txt
-F:     drivers/net/tlan.*
+F:     drivers/net/ethernet/ti/tlan.*
 
 TOMOYO SECURITY MODULE
 M:     Kentaro Takeda <takedakn@nttdata.co.jp>
@@ -6503,7 +6528,7 @@ TULIP NETWORK DRIVERS
 M:     Grant Grundler <grundler@parisc-linux.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/tulip/
+F:     drivers/net/ethernet/tulip/
 
 TUN/TAP driver
 M:     Maxim Krasnyansky <maxk@qualcomm.com>
@@ -6549,7 +6574,7 @@ W:        http://uclinux-h8.sourceforge.jp/
 S:     Supported
 F:     arch/h8300/
 F:     drivers/ide/ide-h8300.c
-F:     drivers/net/ne-h8300.c
+F:     drivers/net/ethernet/8390/ne-h8300.c
 
 UDF FILESYSTEM
 M:     Jan Kara <jack@suse.cz>
@@ -6977,7 +7002,7 @@ F:        include/linux/vhost.h
 VIA RHINE NETWORK DRIVER
 M:     Roger Luethi <rl@hellgate.ch>
 S:     Maintained
-F:     drivers/net/via-rhine.c
+F:     drivers/net/ethernet/via/via-rhine.c
 
 VIAPRO SMBUS DRIVER
 M:     Jean Delvare <khali@linux-fr.org>
@@ -7005,7 +7030,7 @@ VIA VELOCITY NETWORK DRIVER
 M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/via-velocity.*
+F:     drivers/net/ethernet/via/via-velocity.*
 
 VLAN (802.1Q)
 M:     Patrick McHardy <kaber@trash.net>
@@ -7338,7 +7363,7 @@ THE REST
 M:     Linus Torvalds <torvalds@linux-foundation.org>
 L:     linux-kernel@vger.kernel.org
 Q:     http://patchwork.kernel.org/project/LKML/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
 S:     Buried alive in reporters
 F:     *
 F:     */
index d018956..b4ca4e1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
-PATCHLEVEL = 0
+PATCHLEVEL = 1
 SUBLEVEL = 0
-EXTRAVERSION =
+EXTRAVERSION = -rc1
 NAME = Sneaky Weasel
 
 # *DOCUMENTATION*
@@ -360,7 +360,7 @@ CFLAGS_GCOV = -fprofile-arcs -ftest-coverage
 LINUXINCLUDE    := -I$(srctree)/arch/$(hdr-arch)/include \
                    -Iarch/$(hdr-arch)/include/generated -Iinclude \
                    $(if $(KBUILD_SRC), -I$(srctree)/include) \
-                   -include include/generated/autoconf.h
+                   -include $(srctree)/include/linux/kconfig.h
 
 KBUILD_CPPFLAGS := -D__KERNEL__
 
index 26b0e23..4b0669c 100644 (file)
@@ -178,4 +178,7 @@ config HAVE_ARCH_MUTEX_CPU_RELAX
 config HAVE_RCU_TABLE_FREE
        bool
 
+config ARCH_HAVE_NMI_SAFE_CMPXCHG
+       bool
+
 source "kernel/gcov/Kconfig"
index ca2da8d..60cde53 100644 (file)
@@ -14,6 +14,7 @@ config ALPHA
        select AUTO_IRQ_AFFINITY if SMP
        select GENERIC_IRQ_SHOW
        select ARCH_WANT_OPTIONAL_GPIOLIB
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG
        help
          The Alpha is a 64-bit general-purpose processor designed and
          marketed by the Digital Equipment Corporation of blessed memory,
index 0e14399..8606d77 100644 (file)
@@ -183,7 +183,7 @@ alcor_init_irq(void)
  */
 
 static int __init
-alcor_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+alcor_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[7][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
index c8c112d..1029619 100644 (file)
@@ -175,7 +175,7 @@ pc164_init_irq(void)
  */
 
 static inline int __init
-eb66p_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+eb66p_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[5][5] __initdata = {
                /*INT  INTA  INTB  INTC   INTD */
@@ -205,7 +205,7 @@ eb66p_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
  */
 
 static inline int __init
-cabriolet_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+cabriolet_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[5][5] __initdata = {
                /*INT   INTA  INTB  INTC   INTD */
@@ -289,7 +289,7 @@ cia_cab_init_pci(void)
  */
 
 static inline int __init
-alphapc164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+alphapc164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[7][5] __initdata = {
                /*INT   INTA  INTB   INTC   INTD */
index f885682..bb7f0c7 100644 (file)
@@ -382,7 +382,7 @@ isa_irq_fixup(struct pci_dev *dev, int irq)
 }
 
 static int __init
-dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+dp264_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[6][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
@@ -404,7 +404,7 @@ dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 }
 
 static int __init
-monet_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+monet_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[13][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
@@ -466,7 +466,7 @@ monet_swizzle(struct pci_dev *dev, u8 *pinp)
 }
 
 static int __init
-webbrick_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+webbrick_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[13][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
@@ -488,7 +488,7 @@ webbrick_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 }
 
 static int __init
-clipper_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+clipper_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[7][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
index a7a23b4..3c6c13c 100644 (file)
@@ -169,7 +169,7 @@ eb64p_init_irq(void)
  */
 
 static int __init
-eb64p_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+eb64p_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[5][5] __initdata = {
                /*INT  INTA  INTB  INTC   INTD */
index a60cd5b..35f480d 100644 (file)
@@ -144,7 +144,7 @@ eiger_init_irq(void)
 }
 
 static int __init
-eiger_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+eiger_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        u8 irq_orig;
 
index 388b99d..95cfc83 100644 (file)
@@ -318,7 +318,7 @@ marvel_init_irq(void)
 }
 
 static int 
-marvel_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+marvel_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        struct pci_controller *hose = dev->sysdata;
        struct io7_port *io7_port = hose->sysdata;
index 61ccd95..258da68 100644 (file)
@@ -151,7 +151,7 @@ miata_init_irq(void)
  */
 
 static int __init
-miata_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+miata_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
         static char irq_tab[18][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
index 0e6e469..c0fd728 100644 (file)
@@ -146,7 +146,7 @@ mikasa_init_irq(void)
  */
 
 static int __init
-mikasa_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+mikasa_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[8][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
index 99c0f46..4112200 100644 (file)
@@ -65,7 +65,7 @@ nautilus_init_irq(void)
 }
 
 static int __init
-nautilus_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+nautilus_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        /* Preserve the IRQ set up by the console.  */
 
index a00ac70..2172528 100644 (file)
@@ -194,7 +194,7 @@ noritake_init_irq(void)
  */
 
 static int __init
-noritake_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+noritake_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[15][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
index 7f52161..a125d6b 100644 (file)
@@ -223,7 +223,7 @@ rawhide_init_irq(void)
  */
 
 static int __init
-rawhide_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+rawhide_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[5][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
index f33648e..2581cbe 100644 (file)
@@ -119,7 +119,7 @@ ruffian_kill_arch (int mode)
  */
 
 static int __init
-ruffian_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+ruffian_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
         static char irq_tab[11][5] __initdata = {
              /*INT  INTA INTB INTC INTD */
index 216d94d..b172b27 100644 (file)
@@ -144,7 +144,7 @@ rx164_init_irq(void)
  */
 
 static int __init
-rx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+rx164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 #if 0
        static char irq_tab_pass1[6][5] __initdata = {
index da714e4..98d1dbf 100644 (file)
@@ -194,7 +194,7 @@ sable_init_irq(void)
  */
 
 static int __init
-sable_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+sable_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[9][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
@@ -376,7 +376,7 @@ lynx_init_irq(void)
  */
 
 static int __init
-lynx_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+lynx_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[19][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
index 85b4aea..47bec1e 100644 (file)
@@ -146,7 +146,7 @@ sio_fixup_irq_levels(unsigned int level_bits)
 }
 
 static inline int __init
-noname_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+noname_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        /*
         * The Noname board has 5 PCI slots with each of the 4
@@ -185,7 +185,7 @@ noname_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 }
 
 static inline int __init
-p2k_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+p2k_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[][5] __initdata = {
                /*INT A   B   C   D */
index 41d4ad4..73e1c31 100644 (file)
@@ -95,7 +95,7 @@ sx164_init_irq(void)
  */
 
 static int __init
-sx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+sx164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[5][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
index a31f8cd..2ae99ad 100644 (file)
@@ -157,7 +157,7 @@ takara_init_irq(void)
  */
 
 static int __init
-takara_map_irq_srm(struct pci_dev *dev, u8 slot, u8 pin)
+takara_map_irq_srm(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[15][5] __initdata = {
                { 16+3, 16+3, 16+3, 16+3, 16+3},   /* slot  6 == device 3 */
@@ -188,7 +188,7 @@ takara_map_irq_srm(struct pci_dev *dev, u8 slot, u8 pin)
 }
 
 static int __init
-takara_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+takara_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[15][5] __initdata = {
                { 16+3, 16+3, 16+3, 16+3, 16+3},   /* slot  6 == device 3 */
index 6994407..f47b30a 100644 (file)
@@ -305,7 +305,7 @@ titan_late_init(void)
 }
 
 static int __devinit
-titan_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+titan_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        u8 intline;
        int irq;
index d92cdc7..17c85a6 100644 (file)
@@ -290,7 +290,7 @@ wildfire_device_interrupt(unsigned long vector)
  */
 
 static int __init
-wildfire_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+wildfire_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static char irq_tab[8][5] __initdata = {
                /*INT    INTA   INTB   INTC   INTD */
index 09ebf0b..5ebc5d9 100644 (file)
@@ -195,8 +195,7 @@ config VECTORS_BASE
          The base address of exception vectors.
 
 config ARM_PATCH_PHYS_VIRT
-       bool "Patch physical to virtual translations at runtime (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       bool "Patch physical to virtual translations at runtime"
        depends on !XIP_KERNEL && MMU
        depends on !ARCH_REALVIEW || !SPARSEMEM
        help
@@ -1716,6 +1715,7 @@ config USE_OF
        bool "Flattened Device Tree support"
        select OF
        select OF_EARLY_FLATTREE
+       select IRQ_DOMAIN
        help
          Include support for flattened device tree machine descriptions.
 
index 3a4a04b..70c424e 100644 (file)
@@ -282,6 +282,12 @@ zImage Image xipImage bootpImage uImage: vmlinux
 zinstall uinstall install: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
+%.dtb:
+       $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
+dtbs:
+       $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
@@ -298,6 +304,7 @@ define archhelp
   echo  '  uImage        - U-Boot wrapped zImage'
   echo  '  bootpImage    - Combined zImage and initial RAM disk' 
   echo  '                  (supply initrd image via make variable INITRD=<path>)'
+  echo  '  dtbs          - Build device tree blobs for enabled boards'
   echo  '  install       - Install uncompressed kernel'
   echo  '  zinstall      - Install compressed kernel'
   echo  '  uinstall      - Install U-Boot wrapped compressed kernel'
index 9128fdd..a1edfd5 100644 (file)
@@ -59,6 +59,12 @@ $(obj)/zImage:       $(obj)/compressed/vmlinux FORCE
 
 endif
 
+# Rule to build device tree blobs
+$(obj)/%.dtb: $(src)/dts/%.dts
+       $(call cmd,dtc)
+
+$(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y))
+
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
                   -C none -a $(LOADADDR) -e $(STARTADDR) \
diff --git a/arch/arm/boot/dts/skeleton.dtsi b/arch/arm/boot/dts/skeleton.dtsi
new file mode 100644 (file)
index 0000000..b41d241
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Skeleton device tree; the bare minimum needed to boot; just include and
+ * add a compatible value.  The bootloader will typically populate the memory
+ * node.
+ */
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       chosen { };
+       aliases { };
+       memory { device_type = "memory"; reg = <0 0>; };
+};
diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts
new file mode 100644 (file)
index 0000000..4c05334
--- /dev/null
@@ -0,0 +1,70 @@
+/dts-v1/;
+
+/memreserve/ 0x1c000000 0x04000000;
+/include/ "tegra20.dtsi"
+
+/ {
+       model = "NVIDIA Tegra2 Harmony evaluation board";
+       compatible = "nvidia,harmony", "nvidia,tegra20";
+
+       chosen {
+               bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk0p2 rw rootwait";
+       };
+
+       memory@0 {
+               reg = < 0x00000000 0x40000000 >;
+       };
+
+       i2c@7000c000 {
+               clock-frequency = <400000>;
+
+               codec: wm8903@1a {
+                       compatible = "wlf,wm8903";
+                       reg = <0x1a>;
+                       interrupts = < 347 >;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       /* 0x8000 = Not configured */
+                       gpio-cfg = < 0x8000 0x8000 0 0x8000 0x8000 >;
+               };
+       };
+
+       i2c@7000c400 {
+               clock-frequency = <400000>;
+       };
+
+       i2c@7000c500 {
+               clock-frequency = <400000>;
+       };
+
+       i2c@7000d000 {
+               clock-frequency = <400000>;
+       };
+
+       sound {
+               compatible = "nvidia,harmony-sound", "nvidia,tegra-wm8903";
+
+               spkr-en-gpios = <&codec 2 0>;
+               hp-det-gpios = <&gpio 178 0>;
+               int-mic-en-gpios = <&gpio 184 0>;
+               ext-mic-en-gpios = <&gpio 185 0>;
+       };
+
+       serial@70006300 {
+               clock-frequency = < 216000000 >;
+       };
+
+       sdhci@c8000200 {
+               gpios = <&gpio 69 0>, /* cd, gpio PI5 */
+                       <&gpio 57 0>, /* wp, gpio PH1 */
+                       <&gpio 155 0>; /* power, gpio PT3 */
+       };
+
+       sdhci@c8000600 {
+               gpios = <&gpio 58 0>, /* cd, gpio PH2 */
+                       <&gpio 59 0>, /* wp, gpio PH3 */
+                       <&gpio 70 0>; /* power, gpio PI6 */
+       };
+};
diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts
new file mode 100644 (file)
index 0000000..1940cae
--- /dev/null
@@ -0,0 +1,28 @@
+/dts-v1/;
+
+/memreserve/ 0x1c000000 0x04000000;
+/include/ "tegra20.dtsi"
+
+/ {
+       model = "NVIDIA Seaboard";
+       compatible = "nvidia,seaboard", "nvidia,tegra20";
+
+       chosen {
+               bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk1p3 rw rootwait";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = < 0x00000000 0x40000000 >;
+       };
+
+       serial@70006300 {
+               clock-frequency = < 216000000 >;
+       };
+
+       sdhci@c8000400 {
+               gpios = <&gpio 69 0>, /* cd, gpio PI5 */
+                       <&gpio 57 0>, /* wp, gpio PH1 */
+                       <&gpio 70 0>; /* power, gpio PI6 */
+       };
+};
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
new file mode 100644 (file)
index 0000000..5727595
--- /dev/null
@@ -0,0 +1,139 @@
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "nvidia,tegra20";
+       interrupt-parent = <&intc>;
+
+       intc: interrupt-controller@50041000 {
+               compatible = "nvidia,tegra20-gic";
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               reg = < 0x50041000 0x1000 >,
+                     < 0x50040100 0x0100 >;
+       };
+
+       i2c@7000c000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra20-i2c";
+               reg = <0x7000C000 0x100>;
+               interrupts = < 70 >;
+       };
+
+       i2c@7000c400 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra20-i2c";
+               reg = <0x7000C400 0x100>;
+               interrupts = < 116 >;
+       };
+
+       i2c@7000c500 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra20-i2c";
+               reg = <0x7000C500 0x100>;
+               interrupts = < 124 >;
+       };
+
+       i2c@7000d000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra20-i2c";
+               reg = <0x7000D000 0x200>;
+               interrupts = < 85 >;
+       };
+
+       i2s@70002800 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra20-i2s";
+               reg = <0x70002800 0x200>;
+               interrupts = < 45 >;
+               dma-channel = < 2 >;
+       };
+
+       i2s@70002a00 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra20-i2s";
+               reg = <0x70002a00 0x200>;
+               interrupts = < 35 >;
+               dma-channel = < 1 >;
+       };
+
+       das@70000c00 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra20-das";
+               reg = <0x70000c00 0x80>;
+       };
+
+       gpio: gpio@6000d000 {
+               compatible = "nvidia,tegra20-gpio";
+               reg = < 0x6000d000 0x1000 >;
+               interrupts = < 64 65 66 67 87 119 121 >;
+               #gpio-cells = <2>;
+               gpio-controller;
+       };
+
+       serial@70006000 {
+               compatible = "nvidia,tegra20-uart";
+               reg = <0x70006000 0x40>;
+               reg-shift = <2>;
+               interrupts = < 68 >;
+       };
+
+       serial@70006040 {
+               compatible = "nvidia,tegra20-uart";
+               reg = <0x70006040 0x40>;
+               reg-shift = <2>;
+               interrupts = < 69 >;
+       };
+
+       serial@70006200 {
+               compatible = "nvidia,tegra20-uart";
+               reg = <0x70006200 0x100>;
+               reg-shift = <2>;
+               interrupts = < 78 >;
+       };
+
+       serial@70006300 {
+               compatible = "nvidia,tegra20-uart";
+               reg = <0x70006300 0x100>;
+               reg-shift = <2>;
+               interrupts = < 122 >;
+       };
+
+       serial@70006400 {
+               compatible = "nvidia,tegra20-uart";
+               reg = <0x70006400 0x100>;
+               reg-shift = <2>;
+               interrupts = < 123 >;
+       };
+
+       sdhci@c8000000 {
+               compatible = "nvidia,tegra20-sdhci";
+               reg = <0xc8000000 0x200>;
+               interrupts = < 46 >;
+       };
+
+       sdhci@c8000200 {
+               compatible = "nvidia,tegra20-sdhci";
+               reg = <0xc8000200 0x200>;
+               interrupts = < 47 >;
+       };
+
+       sdhci@c8000400 {
+               compatible = "nvidia,tegra20-sdhci";
+               reg = <0xc8000400 0x200>;
+               interrupts = < 51 >;
+       };
+
+       sdhci@c8000600 {
+               compatible = "nvidia,tegra20-sdhci";
+               reg = <0xc8000600 0x200>;
+               interrupts = < 63 >;
+       };
+};
+
diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts
new file mode 100644 (file)
index 0000000..0b32925
--- /dev/null
@@ -0,0 +1,192 @@
+/dts-v1/;
+/include/ "skeleton.dtsi"
+
+/ {
+       model = "ARM Versatile AB";
+       compatible = "arm,versatile-ab";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&vic>;
+
+       aliases {
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               i2c0 = &i2c0;
+       };
+
+       memory {
+               reg = <0x0 0x08000000>;
+       };
+
+       flash@34000000 {
+               compatible = "arm,versatile-flash";
+               reg = <0x34000000 0x4000000>;
+               bank-width = <4>;
+       };
+
+       i2c0: i2c@10002000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "arm,versatile-i2c";
+               reg = <0x10002000 0x1000>;
+
+               rtc@68 {
+                       compatible = "dallas,ds1338";
+                       reg = <0x68>;
+               };
+       };
+
+       net@10010000 {
+               compatible = "smsc,lan91c111";
+               reg = <0x10010000 0x10000>;
+               interrupts = <25>;
+       };
+
+       lcd@10008000 {
+               compatible = "arm,versatile-lcd";
+               reg = <0x10008000 0x1000>;
+       };
+
+       amba {
+               compatible = "arm,amba-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               vic: intc@10140000 {
+                       compatible = "arm,versatile-vic";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+                       reg = <0x10140000 0x1000>;
+               };
+
+               sic: intc@10003000 {
+                       compatible = "arm,versatile-sic";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+                       reg = <0x10003000 0x1000>;
+                       interrupt-parent = <&vic>;
+                       interrupts = <31>; /* Cascaded to vic */
+               };
+
+               dma@10130000 {
+                       compatible = "arm,pl081", "arm,primecell";
+                       reg = <0x10130000 0x1000>;
+                       interrupts = <17>;
+               };
+
+               uart0: uart@101f1000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x101f1000 0x1000>;
+                       interrupts = <12>;
+               };
+
+               uart1: uart@101f2000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x101f2000 0x1000>;
+                       interrupts = <13>;
+               };
+
+               uart2: uart@101f3000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x101f3000 0x1000>;
+                       interrupts = <14>;
+               };
+
+               smc@10100000 {
+                       compatible = "arm,primecell";
+                       reg = <0x10100000 0x1000>;
+               };
+
+               mpmc@10110000 {
+                       compatible = "arm,primecell";
+                       reg = <0x10110000 0x1000>;
+               };
+
+               display@10120000 {
+                       compatible = "arm,pl110", "arm,primecell";
+                       reg = <0x10120000 0x1000>;
+                       interrupts = <16>;
+               };
+
+               sctl@101e0000 {
+                       compatible = "arm,primecell";
+                       reg = <0x101e0000 0x1000>;
+               };
+
+               watchdog@101e1000 {
+                       compatible = "arm,primecell";
+                       reg = <0x101e1000 0x1000>;
+                       interrupts = <0>;
+               };
+
+               gpio0: gpio@101e4000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x101e4000 0x1000>;
+                       gpio-controller;
+                       interrupts = <6>;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio1: gpio@101e5000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x101e5000 0x1000>;
+                       interrupts = <7>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               rtc@101e8000 {
+                       compatible = "arm,pl030", "arm,primecell";
+                       reg = <0x101e8000 0x1000>;
+                       interrupts = <10>;
+               };
+
+               sci@101f0000 {
+                       compatible = "arm,primecell";
+                       reg = <0x101f0000 0x1000>;
+                       interrupts = <15>;
+               };
+
+               ssp@101f4000 {
+                       compatible = "arm,pl022", "arm,primecell";
+                       reg = <0x101f4000 0x1000>;
+                       interrupts = <11>;
+               };
+
+               fpga {
+                       compatible = "arm,versatile-fpga", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x10000000 0x10000>;
+
+                       aaci@4000 {
+                               compatible = "arm,primecell";
+                               reg = <0x4000 0x1000>;
+                               interrupts = <24>;
+                       };
+                       mmc@5000 {
+                               compatible = "arm,primecell";
+                               reg = < 0x5000 0x1000>;
+                               interrupts = <22>;
+                       };
+                       kmi@6000 {
+                               compatible = "arm,pl050", "arm,primecell";
+                               reg = <0x6000 0x1000>;
+                               interrupt-parent = <&sic>;
+                               interrupts = <3>;
+                       };
+                       kmi@7000 {
+                               compatible = "arm,pl050", "arm,primecell";
+                               reg = <0x7000 0x1000>;
+                               interrupt-parent = <&sic>;
+                               interrupts = <4>;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts
new file mode 100644 (file)
index 0000000..8a614e3
--- /dev/null
@@ -0,0 +1,48 @@
+/include/ "versatile-ab.dts"
+
+/ {
+       model = "ARM Versatile PB";
+       compatible = "arm,versatile-pb";
+
+       amba {
+               gpio2: gpio@101e6000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x101e6000 0x1000>;
+                       interrupts = <8>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio3: gpio@101e7000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x101e7000 0x1000>;
+                       interrupts = <9>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               fpga {
+                       uart@9000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x9000 0x1000>;
+                               interrupt-parent = <&sic>;
+                               interrupts = <6>;
+                       };
+                       sci@a000 {
+                               compatible = "arm,primecell";
+                               reg = <0xa000 0x1000>;
+                               interrupt-parent = <&sic>;
+                               interrupts = <5>;
+                       };
+                       mmc@b000 {
+                               compatible = "arm,primecell";
+                               reg = <0xb000 0x1000>;
+                               interrupts = <23>;
+                       };
+               };
+       };
+};
index 14ad62e..a7934ba 100644 (file)
@@ -144,7 +144,7 @@ void it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
 }
 
 /* mapping for on-chip devices */
-int __init it8152_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init it8152_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        if ((dev->vendor == PCI_VENDOR_ID_ITE) &&
            (dev->device == PCI_DEVICE_ID_ITE_8152)) {
index b2f95c7..b3fea38 100644 (file)
@@ -105,7 +105,7 @@ struct pci_sys_data;
 
 extern void it8152_irq_demux(unsigned int irq, struct irq_desc *desc);
 extern void it8152_init_irq(void);
-extern int it8152_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
+extern int it8152_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
 extern int it8152_pci_setup(int nr, struct pci_sys_data *sys);
 extern struct pci_bus *it8152_pci_scan_bus(int nr, struct pci_sys_data *sys);
 
index 3281fb4..217aa19 100644 (file)
@@ -74,4 +74,11 @@ static const struct machine_desc __mach_desc_##_type \
 #define MACHINE_END                            \
 };
 
+#define DT_MACHINE_START(_name, _namestr)              \
+static const struct machine_desc __mach_desc_##_name   \
+ __used                                                        \
+ __attribute__((__section__(".arch.info.init"))) = {   \
+       .nr             = ~0,                           \
+       .name           = _namestr,
+
 #endif
index 16330bd..186efd4 100644 (file)
@@ -25,7 +25,7 @@ struct hw_pci {
        void            (*preinit)(void);
        void            (*postinit)(void);
        u8              (*swizzle)(struct pci_dev *dev, u8 *pin);
-       int             (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
+       int             (*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
 };
 
 /*
@@ -44,7 +44,7 @@ struct pci_sys_data {
                                        /* Bridge swizzling                     */
        u8              (*swizzle)(struct pci_dev *, u8 *);
                                        /* IRQ mapping                          */
-       int             (*map_irq)(struct pci_dev *, u8, u8);
+       int             (*map_irq)(const struct pci_dev *, u8, u8);
        struct hw_pci   *hw;
        void            *private_data;  /* platform controller private data     */
 };
index 11b8708..6f65ca8 100644 (file)
 #include <asm/setup.h>
 #include <asm/irq.h>
 
-static inline void irq_dispose_mapping(unsigned int virq)
-{
-       return;
-}
-
 extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
 extern void arm_dt_memblock_reserve(void);
 
index acca35a..aeef960 100644 (file)
@@ -112,9 +112,6 @@ EXPORT_SYMBOL(__put_user_4);
 EXPORT_SYMBOL(__put_user_8);
 #endif
 
-       /* crypto hash */
-EXPORT_SYMBOL(sha_transform);
-
        /* gcc lib functions */
 EXPORT_SYMBOL(__ashldi3);
 EXPORT_SYMBOL(__ashrdi3);
index e4ee050..d6df359 100644 (file)
@@ -476,7 +476,7 @@ static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 *pin)
 /*
  * Map a slot/pin to an IRQ.
  */
-static int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        struct pci_sys_data *sys = dev->sysdata;
        int irq = -1;
index 0cdd7b4..1a33e9d 100644 (file)
@@ -132,17 +132,3 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
 
        return mdesc_best;
 }
-
-/**
- * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
- *
- * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
- * mapped 1:1 onto Linux irq numbers.  Cascaded irq controllers are not
- * supported.
- */
-unsigned int irq_create_of_mapping(struct device_node *controller,
-                                  const u32 *intspec, unsigned int intsize)
-{
-       return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
index 7fa3bb0..a087838 100644 (file)
@@ -195,10 +195,10 @@ ENTRY(iwmmxt_task_disable)
 
        @ enable access to CP0 and CP1
        XSC(mrc p15, 0, r4, c15, c1, 0)
-       XSC(orr r4, r4, #0xf)
+       XSC(orr r4, r4, #0x3)
        XSC(mcr p15, 0, r4, c15, c1, 0)
        PJ4(mrc p15, 0, r4, c1, c0, 2)
-       PJ4(orr r4, r4, #0x3)
+       PJ4(orr r4, r4, #0xf)
        PJ4(mcr p15, 0, r4, c1, c0, 2)
 
        mov     r0, #0                          @ nothing to load
@@ -313,7 +313,7 @@ ENTRY(iwmmxt_task_switch)
        teq     r2, r3                          @ next task owns it?
        movne   pc, lr                          @ no: leave Concan disabled
 
-1:     @ flip Conan access
+1:     @ flip Concan access
        XSC(eor r1, r1, #0x3)
        XSC(mcr p15, 0, r1, c15, c1, 0)
        PJ4(eor r1, r1, #0xf)
index 05b3776..cc2020c 100644 (file)
@@ -323,7 +323,11 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
 #endif
        s = find_mod_section(hdr, sechdrs, ".alt.smp.init");
        if (s && !is_smp())
+#ifdef CONFIG_SMP_ON_UP
                fixup_smp((void *)s->sh_addr, s->sh_size);
+#else
+               return -EINVAL;
+#endif
        return 0;
 }
 
index 5e1e541..1a347f4 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/uaccess.h>
 #include <linux/random.h>
 #include <linux/hw_breakpoint.h>
+#include <linux/cpuidle.h>
 
 #include <asm/cacheflush.h>
 #include <asm/leds.h>
@@ -196,7 +197,8 @@ void cpu_idle(void)
                                cpu_relax();
                        } else {
                                stop_critical_timings();
-                               pm_idle();
+                               if (cpuidle_idle_call())
+                                       pm_idle();
                                start_critical_timings();
                                /*
                                 * This will eventually be removed - pm_idle
index 59ff42d..cf73a7f 100644 (file)
@@ -12,7 +12,7 @@ lib-y         := backtrace.o changebit.o csumipv6.o csumpartial.o   \
                   strchr.o strrchr.o                                 \
                   testchangebit.o testclearbit.o testsetbit.o        \
                   ashldi3.o ashrdi3.o lshrdi3.o muldi3.o             \
-                  ucmpdi2.o lib1funcs.o div64.o sha1.o               \
+                  ucmpdi2.o lib1funcs.o div64.o                      \
                   io-readsb.o io-writesb.o io-readsl.o io-writesl.o
 
 mmu-y  := clear_user.o copy_page.o getuser.o putuser.o
diff --git a/arch/arm/lib/sha1.S b/arch/arm/lib/sha1.S
deleted file mode 100644 (file)
index eb0edb8..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- *  linux/arch/arm/lib/sha1.S
- *
- *  SHA transform optimized for ARM
- *
- *  Copyright: (C) 2005 by Nicolas Pitre <nico@fluxnic.net>
- *  Created:   September 17, 2005
- *
- *  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 reference implementation for this code is linux/lib/sha1.c
- */
-
-#include <linux/linkage.h>
-
-       .text
-
-
-/*
- * void sha_transform(__u32 *digest, const char *in, __u32 *W)
- *
- * Note: the "in" ptr may be unaligned.
- */
-
-ENTRY(sha_transform)
-
-       stmfd   sp!, {r4 - r8, lr}
-
-       @ for (i = 0; i < 16; i++)
-       @         W[i] = be32_to_cpu(in[i]);
-
-#ifdef __ARMEB__
-       mov     r4, r0
-       mov     r0, r2
-       mov     r2, #64
-       bl      memcpy
-       mov     r2, r0
-       mov     r0, r4
-#else
-       mov     r3, r2
-       mov     lr, #16
-1:     ldrb    r4, [r1], #1
-       ldrb    r5, [r1], #1
-       ldrb    r6, [r1], #1
-       ldrb    r7, [r1], #1
-       subs    lr, lr, #1
-       orr     r5, r5, r4, lsl #8
-       orr     r6, r6, r5, lsl #8
-       orr     r7, r7, r6, lsl #8
-       str     r7, [r3], #4
-       bne     1b
-#endif
-
-       @ for (i = 0; i < 64; i++)
-       @         W[i+16] = ror(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 31);
-
-       sub     r3, r2, #4
-       mov     lr, #64
-2:     ldr     r4, [r3, #4]!
-       subs    lr, lr, #1
-       ldr     r5, [r3, #8]
-       ldr     r6, [r3, #32]
-       ldr     r7, [r3, #52]
-       eor     r4, r4, r5
-       eor     r4, r4, r6
-       eor     r4, r4, r7
-       mov     r4, r4, ror #31
-       str     r4, [r3, #64]
-       bne     2b
-
-       /*
-        * The SHA functions are:
-        *
-        * f1(B,C,D) = (D ^ (B & (C ^ D)))
-        * f2(B,C,D) = (B ^ C ^ D)
-        * f3(B,C,D) = ((B & C) | (D & (B | C)))
-        *
-        * Then the sub-blocks are processed as follows:
-        *
-        * A' = ror(A, 27) + f(B,C,D) + E + K + *W++
-        * B' = A
-        * C' = ror(B, 2)
-        * D' = C
-        * E' = D
-        *
-        * We therefore unroll each loop 5 times to avoid register shuffling.
-        * Also the ror for C (and also D and E which are successivelyderived
-        * from it) is applied in place to cut on an additional mov insn for
-        * each round.
-        */
-
-       .macro  sha_f1, A, B, C, D, E
-       ldr     r3, [r2], #4
-       eor     ip, \C, \D
-       add     \E, r1, \E, ror #2
-       and     ip, \B, ip, ror #2
-       add     \E, \E, \A, ror #27
-       eor     ip, ip, \D, ror #2
-       add     \E, \E, r3
-       add     \E, \E, ip
-       .endm
-
-       .macro  sha_f2, A, B, C, D, E
-       ldr     r3, [r2], #4
-       add     \E, r1, \E, ror #2
-       eor     ip, \B, \C, ror #2
-       add     \E, \E, \A, ror #27
-       eor     ip, ip, \D, ror #2
-       add     \E, \E, r3
-       add     \E, \E, ip
-       .endm
-
-       .macro  sha_f3, A, B, C, D, E
-       ldr     r3, [r2], #4
-       add     \E, r1, \E, ror #2
-       orr     ip, \B, \C, ror #2
-       add     \E, \E, \A, ror #27
-       and     ip, ip, \D, ror #2
-       add     \E, \E, r3
-       and     r3, \B, \C, ror #2
-       orr     ip, ip, r3
-       add     \E, \E, ip
-       .endm
-
-       ldmia   r0, {r4 - r8}
-
-       mov     lr, #4
-       ldr     r1, .L_sha_K + 0
-
-       /* adjust initial values */
-       mov     r6, r6, ror #30
-       mov     r7, r7, ror #30
-       mov     r8, r8, ror #30
-
-3:     subs    lr, lr, #1
-       sha_f1  r4, r5, r6, r7, r8
-       sha_f1  r8, r4, r5, r6, r7
-       sha_f1  r7, r8, r4, r5, r6
-       sha_f1  r6, r7, r8, r4, r5
-       sha_f1  r5, r6, r7, r8, r4
-       bne     3b
-
-       ldr     r1, .L_sha_K + 4
-       mov     lr, #4
-
-4:     subs    lr, lr, #1
-       sha_f2  r4, r5, r6, r7, r8
-       sha_f2  r8, r4, r5, r6, r7
-       sha_f2  r7, r8, r4, r5, r6
-       sha_f2  r6, r7, r8, r4, r5
-       sha_f2  r5, r6, r7, r8, r4
-       bne     4b
-
-       ldr     r1, .L_sha_K + 8
-       mov     lr, #4
-
-5:     subs    lr, lr, #1
-       sha_f3  r4, r5, r6, r7, r8
-       sha_f3  r8, r4, r5, r6, r7
-       sha_f3  r7, r8, r4, r5, r6
-       sha_f3  r6, r7, r8, r4, r5
-       sha_f3  r5, r6, r7, r8, r4
-       bne     5b
-
-       ldr     r1, .L_sha_K + 12
-       mov     lr, #4
-
-6:     subs    lr, lr, #1
-       sha_f2  r4, r5, r6, r7, r8
-       sha_f2  r8, r4, r5, r6, r7
-       sha_f2  r7, r8, r4, r5, r6
-       sha_f2  r6, r7, r8, r4, r5
-       sha_f2  r5, r6, r7, r8, r4
-       bne     6b
-
-       ldmia   r0, {r1, r2, r3, ip, lr}
-       add     r4, r1, r4
-       add     r5, r2, r5
-       add     r6, r3, r6, ror #2
-       add     r7, ip, r7, ror #2
-       add     r8, lr, r8, ror #2
-       stmia   r0, {r4 - r8}
-
-       ldmfd   sp!, {r4 - r8, pc}
-
-ENDPROC(sha_transform)
-
-       .align  2
-.L_sha_K:
-       .word   0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6
-
-
-/*
- * void sha_init(__u32 *buf)
- */
-
-       .align  2
-.L_sha_initial_digest:
-       .word   0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
-
-ENTRY(sha_init)
-
-       str     lr, [sp, #-4]!
-       adr     r1, .L_sha_initial_digest
-       ldmia   r1, {r1, r2, r3, ip, lr}
-       stmia   r0, {r1, r2, r3, ip, lr}
-       ldr     pc, [sp], #4
-
-ENDPROC(sha_init)
index 9696623..bf57e8b 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-obj-y          := irq.o gpio.o
+obj-y          := irq.o gpio.o setup.o
 obj-m          :=
 obj-n          :=
 obj-           :=
index f1013d0..bfc6844 100644 (file)
 #include <mach/at91_rstc.h>
 #include <mach/at91_shdwc.h>
 
+#include "soc.h"
 #include "generic.h"
 #include "clock.h"
 
-static struct map_desc at91cap9_io_desc[] __initdata = {
-       {
-               .virtual        = AT91_VA_BASE_SYS,
-               .pfn            = __phys_to_pfn(AT91_BASE_SYS),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_IO_VIRT_BASE - AT91CAP9_SRAM_SIZE,
-               .pfn            = __phys_to_pfn(AT91CAP9_SRAM_BASE),
-               .length         = AT91CAP9_SRAM_SIZE,
-               .type           = MT_DEVICE,
-       },
-};
-
 /* --------------------------------------------------------------------
  *  Clocks
  * -------------------------------------------------------------------- */
@@ -339,24 +326,17 @@ static void at91cap9_poweroff(void)
  *  AT91CAP9 processor initialization
  * -------------------------------------------------------------------- */
 
-void __init at91cap9_map_io(void)
+static void __init at91cap9_map_io(void)
 {
-       /* Map peripherals */
-       iotable_init(at91cap9_io_desc, ARRAY_SIZE(at91cap9_io_desc));
+       at91_init_sram(0, AT91CAP9_SRAM_BASE, AT91CAP9_SRAM_SIZE);
 }
 
-void __init at91cap9_initialize(unsigned long main_clock)
+static void __init at91cap9_initialize(void)
 {
        at91_arch_reset = at91cap9_reset;
        pm_power_off = at91cap9_poweroff;
        at91_extern_irq = (1 << AT91CAP9_ID_IRQ0) | (1 << AT91CAP9_ID_IRQ1);
 
-       /* Init clock subsystem */
-       at91_clock_init(main_clock);
-
-       /* Register the processor-specific clocks */
-       at91cap9_register_clocks();
-
        /* Register GPIO subsystem */
        at91_gpio_init(at91cap9_gpio, 4);
 
@@ -409,14 +389,9 @@ static unsigned int at91cap9_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0,      /* Advanced Interrupt Controller (IRQ1) */
 };
 
-void __init at91cap9_init_interrupts(unsigned int priority[NR_AIC_IRQS])
-{
-       if (!priority)
-               priority = at91cap9_default_irq_priority;
-
-       /* Initialize the AIC interrupt controller */
-       at91_aic_init(priority);
-
-       /* Enable GPIO interrupts */
-       at91_gpio_irq_setup();
-}
+struct at91_init_soc __initdata at91cap9_soc = {
+       .map_io = at91cap9_map_io,
+       .default_irq_priority = at91cap9_default_irq_priority,
+       .register_clocks = at91cap9_register_clocks,
+       .init = at91cap9_initialize,
+};
index 83a1a3f..f73302d 100644 (file)
 #include <mach/at91_st.h>
 #include <mach/cpu.h>
 
+#include "soc.h"
 #include "generic.h"
 #include "clock.h"
 
 static struct map_desc at91rm9200_io_desc[] __initdata = {
        {
-               .virtual        = AT91_VA_BASE_SYS,
-               .pfn            = __phys_to_pfn(AT91_BASE_SYS),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       }, {
                .virtual        = AT91_VA_BASE_EMAC,
                .pfn            = __phys_to_pfn(AT91RM9200_BASE_EMAC),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE,
-               .pfn            = __phys_to_pfn(AT91RM9200_SRAM_BASE),
-               .length         = AT91RM9200_SRAM_SIZE,
-               .type           = MT_DEVICE,
        },
 };
 
@@ -304,24 +295,17 @@ static void at91rm9200_reset(void)
        at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
 }
 
-int rm9200_type;
-EXPORT_SYMBOL(rm9200_type);
-
-void __init at91rm9200_set_type(int type)
-{
-       rm9200_type = type;
-}
-
 /* --------------------------------------------------------------------
  *  AT91RM9200 processor initialization
  * -------------------------------------------------------------------- */
-void __init at91rm9200_map_io(void)
+static void __init at91rm9200_map_io(void)
 {
        /* Map peripherals */
+       at91_init_sram(0, AT91RM9200_SRAM_BASE, AT91RM9200_SRAM_SIZE);
        iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
 }
 
-void __init at91rm9200_initialize(unsigned long main_clock)
+static void __init at91rm9200_initialize(void)
 {
        at91_arch_reset = at91rm9200_reset;
        at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1)
@@ -329,12 +313,6 @@ void __init at91rm9200_initialize(unsigned long main_clock)
                        | (1 << AT91RM9200_ID_IRQ4) | (1 << AT91RM9200_ID_IRQ5)
                        | (1 << AT91RM9200_ID_IRQ6);
 
-       /* Init clock subsystem */
-       at91_clock_init(main_clock);
-
-       /* Register the processor-specific clocks */
-       at91rm9200_register_clocks();
-
        /* Initialize GPIO subsystem */
        at91_gpio_init(at91rm9200_gpio,
                cpu_is_at91rm9200_bga() ? AT91RM9200_BGA : AT91RM9200_PQFP);
@@ -383,14 +361,9 @@ static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0       /* Advanced Interrupt Controller (IRQ6) */
 };
 
-void __init at91rm9200_init_interrupts(unsigned int priority[NR_AIC_IRQS])
-{
-       if (!priority)
-               priority = at91rm9200_default_irq_priority;
-
-       /* Initialize the AIC interrupt controller */
-       at91_aic_init(priority);
-
-       /* Enable GPIO interrupts */
-       at91_gpio_irq_setup();
-}
+struct at91_init_soc __initdata at91rm9200_soc = {
+       .map_io = at91rm9200_map_io,
+       .default_irq_priority = at91rm9200_default_irq_priority,
+       .register_clocks = at91rm9200_register_clocks,
+       .init = at91rm9200_initialize,
+};
index 7d606b0..cb397be 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/cpu.h>
+#include <mach/at91_dbgu.h>
 #include <mach/at91sam9260.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_rstc.h>
 #include <mach/at91_shdwc.h>
 
+#include "soc.h"
 #include "generic.h"
 #include "clock.h"
 
-static struct map_desc at91sam9260_io_desc[] __initdata = {
-       {
-               .virtual        = AT91_VA_BASE_SYS,
-               .pfn            = __phys_to_pfn(AT91_BASE_SYS),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }
-};
-
-static struct map_desc at91sam9260_sram_desc[] __initdata = {
-       {
-               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE,
-               .pfn            = __phys_to_pfn(AT91SAM9260_SRAM0_BASE),
-               .length         = AT91SAM9260_SRAM0_SIZE,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE - AT91SAM9260_SRAM1_SIZE,
-               .pfn            = __phys_to_pfn(AT91SAM9260_SRAM1_BASE),
-               .length         = AT91SAM9260_SRAM1_SIZE,
-               .type           = MT_DEVICE,
-       }
-};
-
-static struct map_desc at91sam9g20_sram_desc[] __initdata = {
-       {
-               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9G20_SRAM0_SIZE,
-               .pfn            = __phys_to_pfn(AT91SAM9G20_SRAM0_BASE),
-               .length         = AT91SAM9G20_SRAM0_SIZE,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9G20_SRAM0_SIZE - AT91SAM9G20_SRAM1_SIZE,
-               .pfn            = __phys_to_pfn(AT91SAM9G20_SRAM1_BASE),
-               .length         = AT91SAM9G20_SRAM1_SIZE,
-               .type           = MT_DEVICE,
-       }
-};
-
-static struct map_desc at91sam9xe_sram_desc[] __initdata = {
-       {
-               .pfn            = __phys_to_pfn(AT91SAM9XE_SRAM_BASE),
-               .type           = MT_DEVICE,
-       }
-};
-
 /* --------------------------------------------------------------------
  *  Clocks
  * -------------------------------------------------------------------- */
@@ -330,11 +288,9 @@ static void at91sam9260_poweroff(void)
 
 static void __init at91sam9xe_map_io(void)
 {
-       unsigned long cidr, sram_size;
-
-       cidr = at91_sys_read(AT91_DBGU_CIDR);
+       unsigned long sram_size;
 
-       switch (cidr & AT91_CIDR_SRAMSIZ) {
+       switch (at91_soc_initdata.cidr & AT91_CIDR_SRAMSIZ) {
                case AT91_CIDR_SRAMSIZ_32K:
                        sram_size = 2 * SZ_16K;
                        break;
@@ -343,38 +299,29 @@ static void __init at91sam9xe_map_io(void)
                        sram_size = SZ_16K;
        }
 
-       at91sam9xe_sram_desc->virtual = AT91_IO_VIRT_BASE - sram_size;
-       at91sam9xe_sram_desc->length = sram_size;
-
-       iotable_init(at91sam9xe_sram_desc, ARRAY_SIZE(at91sam9xe_sram_desc));
+       at91_init_sram(0, AT91SAM9XE_SRAM_BASE, sram_size);
 }
 
-void __init at91sam9260_map_io(void)
+static void __init at91sam9260_map_io(void)
 {
-       /* Map peripherals */
-       iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc));
-
-       if (cpu_is_at91sam9xe())
+       if (cpu_is_at91sam9xe()) {
                at91sam9xe_map_io();
-       else if (cpu_is_at91sam9g20())
-               iotable_init(at91sam9g20_sram_desc, ARRAY_SIZE(at91sam9g20_sram_desc));
-       else
-               iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
+       } else if (cpu_is_at91sam9g20()) {
+               at91_init_sram(0, AT91SAM9G20_SRAM0_BASE, AT91SAM9G20_SRAM0_SIZE);
+               at91_init_sram(1, AT91SAM9G20_SRAM1_BASE, AT91SAM9G20_SRAM1_SIZE);
+       } else {
+               at91_init_sram(0, AT91SAM9260_SRAM0_BASE, AT91SAM9260_SRAM0_SIZE);
+               at91_init_sram(1, AT91SAM9260_SRAM1_BASE, AT91SAM9260_SRAM1_SIZE);
+       }
 }
 
-void __init at91sam9260_initialize(unsigned long main_clock)
+static void __init at91sam9260_initialize(void)
 {
        at91_arch_reset = at91sam9_alt_reset;
        pm_power_off = at91sam9260_poweroff;
        at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
                        | (1 << AT91SAM9260_ID_IRQ2);
 
-       /* Init clock subsystem */
-       at91_clock_init(main_clock);
-
-       /* Register the processor-specific clocks */
-       at91sam9260_register_clocks();
-
        /* Register GPIO subsystem */
        at91_gpio_init(at91sam9260_gpio, 3);
 }
@@ -421,14 +368,9 @@ static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0,      /* Advanced Interrupt Controller */
 };
 
-void __init at91sam9260_init_interrupts(unsigned int priority[NR_AIC_IRQS])
-{
-       if (!priority)
-               priority = at91sam9260_default_irq_priority;
-
-       /* Initialize the AIC interrupt controller */
-       at91_aic_init(priority);
-
-       /* Enable GPIO interrupts */
-       at91_gpio_irq_setup();
-}
+struct at91_init_soc __initdata at91sam9260_soc = {
+       .map_io = at91sam9260_map_io,
+       .default_irq_priority = at91sam9260_default_irq_priority,
+       .register_clocks = at91sam9260_register_clocks,
+       .init = at91sam9260_initialize,
+};
index c148316..d522b47 100644 (file)
 #include <mach/at91_rstc.h>
 #include <mach/at91_shdwc.h>
 
+#include "soc.h"
 #include "generic.h"
 #include "clock.h"
 
-static struct map_desc at91sam9261_io_desc[] __initdata = {
-       {
-               .virtual        = AT91_VA_BASE_SYS,
-               .pfn            = __phys_to_pfn(AT91_BASE_SYS),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       },
-};
-
-static struct map_desc at91sam9261_sram_desc[] __initdata = {
-       {
-               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9261_SRAM_SIZE,
-               .pfn            = __phys_to_pfn(AT91SAM9261_SRAM_BASE),
-               .length         = AT91SAM9261_SRAM_SIZE,
-               .type           = MT_DEVICE,
-       },
-};
-
-static struct map_desc at91sam9g10_sram_desc[] __initdata = {
-       {
-               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9G10_SRAM_SIZE,
-               .pfn            = __phys_to_pfn(AT91SAM9G10_SRAM_BASE),
-               .length         = AT91SAM9G10_SRAM_SIZE,
-               .type           = MT_DEVICE,
-       },
-};
-
 /* --------------------------------------------------------------------
  *  Clocks
  * -------------------------------------------------------------------- */
@@ -302,30 +276,21 @@ static void at91sam9261_poweroff(void)
  *  AT91SAM9261 processor initialization
  * -------------------------------------------------------------------- */
 
-void __init at91sam9261_map_io(void)
+static void __init at91sam9261_map_io(void)
 {
-       /* Map peripherals */
-       iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc));
-
        if (cpu_is_at91sam9g10())
-               iotable_init(at91sam9g10_sram_desc, ARRAY_SIZE(at91sam9g10_sram_desc));
+               at91_init_sram(0, AT91SAM9G10_SRAM_BASE, AT91SAM9G10_SRAM_SIZE);
        else
-               iotable_init(at91sam9261_sram_desc, ARRAY_SIZE(at91sam9261_sram_desc));
+               at91_init_sram(0, AT91SAM9261_SRAM_BASE, AT91SAM9261_SRAM_SIZE);
 }
 
-void __init at91sam9261_initialize(unsigned long main_clock)
+static void __init at91sam9261_initialize(void)
 {
        at91_arch_reset = at91sam9_alt_reset;
        pm_power_off = at91sam9261_poweroff;
        at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)
                        | (1 << AT91SAM9261_ID_IRQ2);
 
-       /* Init clock subsystem */
-       at91_clock_init(main_clock);
-
-       /* Register the processor-specific clocks */
-       at91sam9261_register_clocks();
-
        /* Register GPIO subsystem */
        at91_gpio_init(at91sam9261_gpio, 3);
 }
@@ -372,14 +337,9 @@ static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0,      /* Advanced Interrupt Controller */
 };
 
-void __init at91sam9261_init_interrupts(unsigned int priority[NR_AIC_IRQS])
-{
-       if (!priority)
-               priority = at91sam9261_default_irq_priority;
-
-       /* Initialize the AIC interrupt controller */
-       at91_aic_init(priority);
-
-       /* Enable GPIO interrupts */
-       at91_gpio_irq_setup();
-}
+struct at91_init_soc __initdata at91sam9261_soc = {
+       .map_io = at91sam9261_map_io,
+       .default_irq_priority = at91sam9261_default_irq_priority,
+       .register_clocks = at91sam9261_register_clocks,
+       .init = at91sam9261_initialize,
+};
index dc28477..044f3c9 100644 (file)
 #include <mach/at91_rstc.h>
 #include <mach/at91_shdwc.h>
 
+#include "soc.h"
 #include "generic.h"
 #include "clock.h"
 
-static struct map_desc at91sam9263_io_desc[] __initdata = {
-       {
-               .virtual        = AT91_VA_BASE_SYS,
-               .pfn            = __phys_to_pfn(AT91_BASE_SYS),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE,
-               .pfn            = __phys_to_pfn(AT91SAM9263_SRAM0_BASE),
-               .length         = AT91SAM9263_SRAM0_SIZE,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE - AT91SAM9263_SRAM1_SIZE,
-               .pfn            = __phys_to_pfn(AT91SAM9263_SRAM1_BASE),
-               .length         = AT91SAM9263_SRAM1_SIZE,
-               .type           = MT_DEVICE,
-       },
-};
-
 /* --------------------------------------------------------------------
  *  Clocks
  * -------------------------------------------------------------------- */
@@ -313,24 +295,18 @@ static void at91sam9263_poweroff(void)
  *  AT91SAM9263 processor initialization
  * -------------------------------------------------------------------- */
 
-void __init at91sam9263_map_io(void)
+static void __init at91sam9263_map_io(void)
 {
-       /* Map peripherals */
-       iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
+       at91_init_sram(0, AT91SAM9263_SRAM0_BASE, AT91SAM9263_SRAM0_SIZE);
+       at91_init_sram(1, AT91SAM9263_SRAM1_BASE, AT91SAM9263_SRAM1_SIZE);
 }
 
-void __init at91sam9263_initialize(unsigned long main_clock)
+static void __init at91sam9263_initialize(void)
 {
        at91_arch_reset = at91sam9_alt_reset;
        pm_power_off = at91sam9263_poweroff;
        at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
 
-       /* Init clock subsystem */
-       at91_clock_init(main_clock);
-
-       /* Register the processor-specific clocks */
-       at91sam9263_register_clocks();
-
        /* Register GPIO subsystem */
        at91_gpio_init(at91sam9263_gpio, 5);
 }
@@ -377,14 +353,9 @@ static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0,      /* Advanced Interrupt Controller (IRQ1) */
 };
 
-void __init at91sam9263_init_interrupts(unsigned int priority[NR_AIC_IRQS])
-{
-       if (!priority)
-               priority = at91sam9263_default_irq_priority;
-
-       /* Initialize the AIC interrupt controller */
-       at91_aic_init(priority);
-
-       /* Enable GPIO interrupts */
-       at91_gpio_irq_setup();
-}
+struct at91_init_soc __initdata at91sam9263_soc = {
+       .map_io = at91sam9263_map_io,
+       .default_irq_priority = at91sam9263_default_irq_priority,
+       .register_clocks = at91sam9263_register_clocks,
+       .init = at91sam9263_initialize,
+};
index 11e2141..e04c5fb 100644 (file)
 #include <mach/at91_shdwc.h>
 #include <mach/cpu.h>
 
+#include "soc.h"
 #include "generic.h"
 #include "clock.h"
 
-static struct map_desc at91sam9g45_io_desc[] __initdata = {
-       {
-               .virtual        = AT91_VA_BASE_SYS,
-               .pfn            = __phys_to_pfn(AT91_BASE_SYS),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9G45_SRAM_SIZE,
-               .pfn            = __phys_to_pfn(AT91SAM9G45_SRAM_BASE),
-               .length         = AT91SAM9G45_SRAM_SIZE,
-               .type           = MT_DEVICE,
-       }
-};
-
 /* --------------------------------------------------------------------
  *  Clocks
  * -------------------------------------------------------------------- */
@@ -329,24 +316,17 @@ static void at91sam9g45_poweroff(void)
  *  AT91SAM9G45 processor initialization
  * -------------------------------------------------------------------- */
 
-void __init at91sam9g45_map_io(void)
+static void __init at91sam9g45_map_io(void)
 {
-       /* Map peripherals */
-       iotable_init(at91sam9g45_io_desc, ARRAY_SIZE(at91sam9g45_io_desc));
+       at91_init_sram(0, AT91SAM9G45_SRAM_BASE, AT91SAM9G45_SRAM_SIZE);
 }
 
-void __init at91sam9g45_initialize(unsigned long main_clock)
+static void __init at91sam9g45_initialize(void)
 {
        at91_arch_reset = at91sam9g45_reset;
        pm_power_off = at91sam9g45_poweroff;
        at91_extern_irq = (1 << AT91SAM9G45_ID_IRQ0);
 
-       /* Init clock subsystem */
-       at91_clock_init(main_clock);
-
-       /* Register the processor-specific clocks */
-       at91sam9g45_register_clocks();
-
        /* Register GPIO subsystem */
        at91_gpio_init(at91sam9g45_gpio, 5);
 }
@@ -393,14 +373,9 @@ static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0,      /* Advanced Interrupt Controller (IRQ0) */
 };
 
-void __init at91sam9g45_init_interrupts(unsigned int priority[NR_AIC_IRQS])
-{
-       if (!priority)
-               priority = at91sam9g45_default_irq_priority;
-
-       /* Initialize the AIC interrupt controller */
-       at91_aic_init(priority);
-
-       /* Enable GPIO interrupts */
-       at91_gpio_irq_setup();
-}
+struct at91_init_soc __initdata at91sam9g45_soc = {
+       .map_io = at91sam9g45_map_io,
+       .default_irq_priority = at91sam9g45_default_irq_priority,
+       .register_clocks = at91sam9g45_register_clocks,
+       .init = at91sam9g45_initialize,
+};
index 29dff18..a238105 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/cpu.h>
+#include <mach/at91_dbgu.h>
 #include <mach/at91sam9rl.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_rstc.h>
 #include <mach/at91_shdwc.h>
 
+#include "soc.h"
 #include "generic.h"
 #include "clock.h"
 
-static struct map_desc at91sam9rl_io_desc[] __initdata = {
-       {
-               .virtual        = AT91_VA_BASE_SYS,
-               .pfn            = __phys_to_pfn(AT91_BASE_SYS),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       },
-};
-
-static struct map_desc at91sam9rl_sram_desc[] __initdata = {
-       {
-               .pfn            = __phys_to_pfn(AT91SAM9RL_SRAM_BASE),
-               .type           = MT_DEVICE,
-       }
-};
-
 /* --------------------------------------------------------------------
  *  Clocks
  * -------------------------------------------------------------------- */
@@ -287,16 +273,11 @@ static void at91sam9rl_poweroff(void)
  *  AT91SAM9RL processor initialization
  * -------------------------------------------------------------------- */
 
-void __init at91sam9rl_map_io(void)
+static void __init at91sam9rl_map_io(void)
 {
-       unsigned long cidr, sram_size;
-
-       /* Map peripherals */
-       iotable_init(at91sam9rl_io_desc, ARRAY_SIZE(at91sam9rl_io_desc));
-
-       cidr = at91_sys_read(AT91_DBGU_CIDR);
+       unsigned long sram_size;
 
-       switch (cidr & AT91_CIDR_SRAMSIZ) {
+       switch (at91_soc_initdata.cidr & AT91_CIDR_SRAMSIZ) {
                case AT91_CIDR_SRAMSIZ_32K:
                        sram_size = 2 * SZ_16K;
                        break;
@@ -305,25 +286,16 @@ void __init at91sam9rl_map_io(void)
                        sram_size = SZ_16K;
        }
 
-       at91sam9rl_sram_desc->virtual = AT91_IO_VIRT_BASE - sram_size;
-       at91sam9rl_sram_desc->length = sram_size;
-
        /* Map SRAM */
-       iotable_init(at91sam9rl_sram_desc, ARRAY_SIZE(at91sam9rl_sram_desc));
+       at91_init_sram(0, AT91SAM9RL_SRAM_BASE, sram_size);
 }
 
-void __init at91sam9rl_initialize(unsigned long main_clock)
+static void __init at91sam9rl_initialize(void)
 {
        at91_arch_reset = at91sam9_alt_reset;
        pm_power_off = at91sam9rl_poweroff;
        at91_extern_irq = (1 << AT91SAM9RL_ID_IRQ0);
 
-       /* Init clock subsystem */
-       at91_clock_init(main_clock);
-
-       /* Register the processor-specific clocks */
-       at91sam9rl_register_clocks();
-
        /* Register GPIO subsystem */
        at91_gpio_init(at91sam9rl_gpio, 4);
 }
@@ -370,14 +342,9 @@ static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0,      /* Advanced Interrupt Controller */
 };
 
-void __init at91sam9rl_init_interrupts(unsigned int priority[NR_AIC_IRQS])
-{
-       if (!priority)
-               priority = at91sam9rl_default_irq_priority;
-
-       /* Initialize the AIC interrupt controller */
-       at91_aic_init(priority);
-
-       /* Enable GPIO interrupts */
-       at91_gpio_irq_setup();
-}
+struct at91_init_soc __initdata at91sam9rl_soc = {
+       .map_io = at91sam9rl_map_io,
+       .default_irq_priority = at91sam9rl_default_irq_priority,
+       .register_clocks = at91sam9rl_register_clocks,
+       .init = at91sam9rl_initialize,
+};
index ab1d463..5aa5885 100644 (file)
@@ -46,7 +46,7 @@ static void __init onearm_init_early(void)
        at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
 
        /* Initialize processor: 18.432 MHz crystal */
-       at91rm9200_initialize(18432000);
+       at91_initialize(18432000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -63,11 +63,6 @@ static void __init onearm_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init onearm_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata onearm_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
@@ -97,8 +92,8 @@ static void __init onearm_board_init(void)
 MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = onearm_init_early,
-       .init_irq       = onearm_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = onearm_board_init,
 MACHINE_END
index a4924de..b0c796d 100644 (file)
@@ -51,7 +51,7 @@
 static void __init afeb9260_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
+       at91_initialize(18432000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -70,12 +70,6 @@ static void __init afeb9260_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init afeb9260_init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
-
 /*
  * USB Host port
  */
@@ -219,9 +213,9 @@ static void __init afeb9260_board_init(void)
 MACHINE_START(AFEB9260, "Custom afeb9260 board")
        /* Maintainer: Sergey Lapin <slapin@ossfans.org> */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = afeb9260_init_early,
-       .init_irq       = afeb9260_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = afeb9260_board_init,
 MACHINE_END
 
index 148fccb..d1abd58 100644 (file)
@@ -48,7 +48,7 @@
 static void __init cam60_init_early(void)
 {
        /* Initialize processor: 10 MHz crystal */
-       at91sam9260_initialize(10000000);
+       at91_initialize(10000000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -57,12 +57,6 @@ static void __init cam60_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init cam60_init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
-
 /*
  * USB Host
  */
@@ -199,8 +193,8 @@ static void __init cam60_board_init(void)
 MACHINE_START(CAM60, "KwikByte CAM60")
        /* Maintainer: KwikByte */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = cam60_init_early,
-       .init_irq       = cam60_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = cam60_board_init,
 MACHINE_END
index cdb65d4..679b0b7 100644 (file)
@@ -53,7 +53,7 @@
 static void __init cap9adk_init_early(void)
 {
        /* Initialize processor: 12 MHz crystal */
-       at91cap9_initialize(12000000);
+       at91_initialize(12000000);
 
        /* Setup the LEDs: USER1 and USER2 LED for cpu/timer... */
        at91_init_leds(AT91_PIN_PA10, AT91_PIN_PA11);
@@ -65,12 +65,6 @@ static void __init cap9adk_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init cap9adk_init_irq(void)
-{
-       at91cap9_init_interrupts(NULL);
-}
-
-
 /*
  * USB Host port
  */
@@ -397,8 +391,8 @@ static void __init cap9adk_board_init(void)
 MACHINE_START(AT91CAP9ADK, "Atmel AT91CAP9A-DK")
        /* Maintainer: Stelian Pop <stelian.pop@leadtechdesign.com> */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91cap9_map_io,
+       .map_io         = at91_map_io,
        .init_early     = cap9adk_init_early,
-       .init_irq       = cap9adk_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = cap9adk_board_init,
 MACHINE_END
index f36b186..c578c5d 100644 (file)
@@ -43,7 +43,7 @@
 static void __init carmeva_init_early(void)
 {
        /* Initialize processor: 20.000 MHz crystal */
-       at91rm9200_initialize(20000000);
+       at91_initialize(20000000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -57,11 +57,6 @@ static void __init carmeva_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init carmeva_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata carmeva_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
@@ -163,8 +158,8 @@ static void __init carmeva_board_init(void)
 MACHINE_START(CARMEVA, "Carmeva")
        /* Maintainer: Conitec Datasystems */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = carmeva_init_early,
-       .init_irq       = carmeva_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = carmeva_board_init,
 MACHINE_END
index 9805110..f4da8a1 100644 (file)
@@ -50,7 +50,7 @@
 static void __init cpu9krea_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
+       at91_initialize(18432000);
 
        /* DGBU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -81,11 +81,6 @@ static void __init cpu9krea_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init cpu9krea_init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
 /*
  * USB Host port
  */
@@ -376,8 +371,8 @@ MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
 #endif
        /* Maintainer: Eric Benard - EUKREA Electromatique */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = cpu9krea_init_early,
-       .init_irq       = cpu9krea_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = cpu9krea_board_init,
 MACHINE_END
index 6daabe3..2d919f5 100644 (file)
@@ -57,7 +57,7 @@ static void __init cpuat91_init_early(void)
        at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
 
        /* Initialize processor: 18.432 MHz crystal */
-       at91rm9200_initialize(18432000);
+       at91_initialize(18432000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -82,11 +82,6 @@ static void __init cpuat91_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init cpuat91_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata cpuat91_eth_data = {
        .is_rmii        = 1,
 };
@@ -180,8 +175,8 @@ static void __init cpuat91_board_init(void)
 MACHINE_START(CPUAT91, "Eukrea")
        /* Maintainer: Eric Benard - EUKREA Electromatique */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = cpuat91_init_early,
-       .init_irq       = cpuat91_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = cpuat91_board_init,
 MACHINE_END
index d98bcec..17654d5 100644 (file)
@@ -46,7 +46,7 @@
 static void __init csb337_init_early(void)
 {
        /* Initialize processor: 3.6864 MHz crystal */
-       at91rm9200_initialize(3686400);
+       at91_initialize(3686400);
 
        /* Setup the LEDs */
        at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
@@ -58,11 +58,6 @@ static void __init csb337_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init csb337_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata csb337_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC2,
        .is_rmii        = 0,
@@ -258,8 +253,8 @@ static void __init csb337_board_init(void)
 MACHINE_START(CSB337, "Cogent CSB337")
        /* Maintainer: Bill Gatliff */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = csb337_init_early,
-       .init_irq       = csb337_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = csb337_board_init,
 MACHINE_END
index 019aab4..72b5567 100644 (file)
@@ -43,7 +43,7 @@
 static void __init csb637_init_early(void)
 {
        /* Initialize processor: 3.6864 MHz crystal */
-       at91rm9200_initialize(3686400);
+       at91_initialize(3686400);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -52,11 +52,6 @@ static void __init csb637_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init csb637_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata csb637_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC0,
        .is_rmii        = 0,
@@ -139,8 +134,8 @@ static void __init csb637_board_init(void)
 MACHINE_START(CSB637, "Cogent CSB637")
        /* Maintainer: Bill Gatliff */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = csb637_init_early,
-       .init_irq       = csb637_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = csb637_board_init,
 MACHINE_END
index e948453..01170a2 100644 (file)
@@ -43,7 +43,7 @@
 static void __init eb9200_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91rm9200_initialize(18432000);
+       at91_initialize(18432000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -60,11 +60,6 @@ static void __init eb9200_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init eb9200_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata eb9200_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
@@ -121,8 +116,8 @@ static void __init eb9200_board_init(void)
 
 MACHINE_START(ATEB9200, "Embest ATEB9200")
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = eb9200_init_early,
-       .init_irq       = eb9200_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = eb9200_board_init,
 MACHINE_END
index a6f57fa..7c0313c 100644 (file)
@@ -49,7 +49,7 @@ static void __init ecb_at91init_early(void)
        at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
 
        /* Initialize processor: 18.432 MHz crystal */
-       at91rm9200_initialize(18432000);
+       at91_initialize(18432000);
 
        /* Setup the LEDs */
        at91_init_leds(AT91_PIN_PC7, AT91_PIN_PC7);
@@ -64,11 +64,6 @@ static void __init ecb_at91init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init ecb_at91init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata ecb_at91eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 0,
@@ -173,8 +168,8 @@ static void __init ecb_at91board_init(void)
 MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
        /* Maintainer: emQbit.com */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ecb_at91init_early,
-       .init_irq       = ecb_at91init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ecb_at91board_init,
 MACHINE_END
index bfc0062..8252c72 100644 (file)
@@ -35,7 +35,7 @@ static void __init eco920_init_early(void)
        /* Set cpu type: PQFP */
        at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
 
-       at91rm9200_initialize(18432000);
+       at91_initialize(18432000);
 
        /* Setup the LEDs */
        at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
@@ -47,11 +47,6 @@ static void __init eco920_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init eco920_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata eco920_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC2,
        .is_rmii        = 1,
@@ -135,8 +130,8 @@ static void __init eco920_board_init(void)
 MACHINE_START(ECO920, "eco920")
        /* Maintainer: Sascha Hauer */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = eco920_init_early,
-       .init_irq       = eco920_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = eco920_board_init,
 MACHINE_END
index 466c063..4c3f65d 100644 (file)
@@ -40,7 +40,7 @@
 static void __init flexibity_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
+       at91_initialize(18432000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -49,11 +49,6 @@ static void __init flexibity_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init flexibity_init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
 /* USB Host port */
 static struct at91_usbh_data __initdata flexibity_usbh_data = {
        .ports          = 2,
@@ -155,8 +150,8 @@ static void __init flexibity_board_init(void)
 MACHINE_START(FLEXIBITY, "Flexibity Connect")
        /* Maintainer: Maxim Osipov */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = flexibity_init_early,
-       .init_irq       = flexibity_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = flexibity_board_init,
 MACHINE_END
index e2d1dc9..f27d1a7 100644 (file)
@@ -60,7 +60,7 @@
 static void __init foxg20_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
+       at91_initialize(18432000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -101,12 +101,6 @@ static void __init foxg20_init_early(void)
 
 }
 
-static void __init foxg20_init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
-
 /*
  * USB Host port
  */
@@ -267,8 +261,8 @@ static void __init foxg20_board_init(void)
 MACHINE_START(ACMENETUSFOXG20, "Acme Systems srl FOX Board G20")
        /* Maintainer: Sergio Tanzilli */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = foxg20_init_early,
-       .init_irq       = foxg20_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = foxg20_board_init,
 MACHINE_END
index 1d4f36b..2e95949 100644 (file)
@@ -75,11 +75,6 @@ static void __init gsia18s_init_early(void)
        at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
 }
 
-static void __init init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
 /*
  * Two USB Host ports
  */
@@ -577,8 +572,8 @@ static void __init gsia18s_board_init(void)
 
 MACHINE_START(GSIA18S, "GS_IA18_S")
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = gsia18s_init_early,
-       .init_irq       = init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = gsia18s_board_init,
 MACHINE_END
index 9b003ff..4a17089 100644 (file)
@@ -46,7 +46,7 @@ static void __init kafa_init_early(void)
        at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
 
        /* Initialize processor: 18.432 MHz crystal */
-       at91rm9200_initialize(18432000);
+       at91_initialize(18432000);
 
        /* Set up the LEDs */
        at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
@@ -61,11 +61,6 @@ static void __init kafa_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init kafa_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata kafa_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 0,
@@ -99,8 +94,8 @@ static void __init kafa_board_init(void)
 MACHINE_START(KAFA, "Sperry-Sun KAFA")
        /* Maintainer: Sergei Sharonov */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = kafa_init_early,
-       .init_irq       = kafa_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = kafa_board_init,
 MACHINE_END
index a813a74..9dc8d49 100644 (file)
@@ -48,7 +48,7 @@ static void __init kb9202_init_early(void)
        at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
 
        /* Initialize processor: 10 MHz crystal */
-       at91rm9200_initialize(10000000);
+       at91_initialize(10000000);
 
        /* Set up the LEDs */
        at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
@@ -69,11 +69,6 @@ static void __init kb9202_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init kb9202_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata kb9202_eth_data = {
        .phy_irq_pin    = AT91_PIN_PB29,
        .is_rmii        = 0,
@@ -140,8 +135,8 @@ static void __init kb9202_board_init(void)
 MACHINE_START(KB9200, "KB920x")
        /* Maintainer: KwikByte, Inc. */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = kb9202_init_early,
-       .init_irq       = kb9202_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = kb9202_board_init,
 MACHINE_END
index 961e805..9bc6ab3 100644 (file)
@@ -54,7 +54,7 @@
 static void __init neocore926_init_early(void)
 {
        /* Initialize processor: 20 MHz crystal */
-       at91sam9263_initialize(20000000);
+       at91_initialize(20000000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -66,12 +66,6 @@ static void __init neocore926_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init neocore926_init_irq(void)
-{
-       at91sam9263_init_interrupts(NULL);
-}
-
-
 /*
  * USB Host port
  */
@@ -388,8 +382,8 @@ static void __init neocore926_board_init(void)
 MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926")
        /* Maintainer: ADENEO */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9263_map_io,
+       .map_io         = at91_map_io,
        .init_early     = neocore926_init_early,
-       .init_irq       = neocore926_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = neocore926_board_init,
 MACHINE_END
index 21a21af..49e3f69 100644 (file)
@@ -53,13 +53,6 @@ static void __init pcontrol_g20_init_early(void)
        at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
 }
 
-
-static void __init init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
-
 static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
        .ncs_read_setup         = 16,
        .nrd_setup              = 18,
@@ -223,8 +216,8 @@ static void __init pcontrol_g20_board_init(void)
 MACHINE_START(PCONTROL_G20, "PControl G20")
        /* Maintainer: pgsellmann@portner-elektronik.at */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = pcontrol_g20_init_early,
-       .init_irq       = init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = pcontrol_g20_board_init,
 MACHINE_END
index 756cc2a..b7b8390 100644 (file)
@@ -46,7 +46,7 @@
 static void __init picotux200_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91rm9200_initialize(18432000);
+       at91_initialize(18432000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -60,11 +60,6 @@ static void __init picotux200_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init picotux200_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata picotux200_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
@@ -124,8 +119,8 @@ static void __init picotux200_board_init(void)
 MACHINE_START(PICOTUX2XX, "picotux 200")
        /* Maintainer: Kleinhenz Elektronik GmbH */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = picotux200_init_early,
-       .init_irq       = picotux200_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = picotux200_board_init,
 MACHINE_END
index d1a6001..81f9110 100644 (file)
@@ -51,7 +51,7 @@
 static void __init ek_init_early(void)
 {
        /* Initialize processor: 12.000 MHz crystal */
-       at91sam9260_initialize(12000000);
+       at91_initialize(12000000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -72,12 +72,6 @@ static void __init ek_init_early(void)
 
 }
 
-static void __init ek_init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
-
 /*
  * USB Host port
  */
@@ -269,8 +263,8 @@ static void __init ek_board_init(void)
 MACHINE_START(QIL_A9260, "CALAO QIL_A9260")
        /* Maintainer: calao-systems */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ek_init_early,
-       .init_irq       = ek_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
 MACHINE_END
index aef9627..6f08faa 100644 (file)
@@ -48,7 +48,7 @@
 static void __init dk_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91rm9200_initialize(18432000);
+       at91_initialize(18432000);
 
        /* Setup the LEDs */
        at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
@@ -65,11 +65,6 @@ static void __init dk_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init dk_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata dk_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
@@ -228,8 +223,8 @@ static void __init dk_board_init(void)
 MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
        /* Maintainer: SAN People/Atmel */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = dk_init_early,
-       .init_irq       = dk_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = dk_board_init,
 MACHINE_END
index 015a021..85bcccd 100644 (file)
@@ -48,7 +48,7 @@
 static void __init ek_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91rm9200_initialize(18432000);
+       at91_initialize(18432000);
 
        /* Setup the LEDs */
        at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
@@ -65,11 +65,6 @@ static void __init ek_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init ek_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
 static struct at91_eth_data __initdata ek_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
@@ -194,8 +189,8 @@ static void __init ek_board_init(void)
 MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
        /* Maintainer: SAN People/Atmel */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ek_init_early,
-       .init_irq       = ek_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
 MACHINE_END
index aaf1bf0..4d3a02f 100644 (file)
@@ -47,7 +47,7 @@
 static void __init ek_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
+       at91_initialize(18432000);
 
        /* Setup the LEDs */
        at91_init_leds(AT91_PIN_PA9, AT91_PIN_PA6);
@@ -67,12 +67,6 @@ static void __init ek_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init ek_init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
-
 /*
  * USB Host port
  */
@@ -213,8 +207,8 @@ static void __init ek_board_init(void)
 MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
        /* Maintainer: Olimex */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ek_init_early,
-       .init_irq       = ek_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
 MACHINE_END
index 5c24074..8a50c3e 100644 (file)
@@ -53,7 +53,7 @@
 static void __init ek_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
+       at91_initialize(18432000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -70,12 +70,6 @@ static void __init ek_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init ek_init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
-
 /*
  * USB Host port
  */
@@ -354,8 +348,8 @@ static void __init ek_board_init(void)
 MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ek_init_early,
-       .init_irq       = ek_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
 MACHINE_END
index b60c22b..5096a0e 100644 (file)
@@ -57,7 +57,7 @@
 static void __init ek_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91sam9261_initialize(18432000);
+       at91_initialize(18432000);
 
        /* Setup the LEDs */
        at91_init_leds(AT91_PIN_PA13, AT91_PIN_PA14);
@@ -69,12 +69,6 @@ static void __init ek_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init ek_init_irq(void)
-{
-       at91sam9261_init_interrupts(NULL);
-}
-
-
 /*
  * DM9000 ethernet device
  */
@@ -621,8 +615,8 @@ MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
 #endif
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9261_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ek_init_early,
-       .init_irq       = ek_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
 MACHINE_END
index 9bbdc92..ea8f185 100644 (file)
@@ -56,7 +56,7 @@
 static void __init ek_init_early(void)
 {
        /* Initialize processor: 16.367 MHz crystal */
-       at91sam9263_initialize(16367660);
+       at91_initialize(16367660);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -68,12 +68,6 @@ static void __init ek_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init ek_init_irq(void)
-{
-       at91sam9263_init_interrupts(NULL);
-}
-
-
 /*
  * USB Host port
  */
@@ -452,8 +446,8 @@ static void __init ek_board_init(void)
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9263_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ek_init_early,
-       .init_irq       = ek_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
 MACHINE_END
index 1325a50..817f59d 100644 (file)
@@ -64,7 +64,7 @@ static int inline ek_have_2mmc(void)
 static void __init ek_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
+       at91_initialize(18432000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -81,12 +81,6 @@ static void __init ek_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init ek_init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
-
 /*
  * USB Host port
  */
@@ -404,17 +398,17 @@ static void __init ek_board_init(void)
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ek_init_early,
-       .init_irq       = ek_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
 MACHINE_END
 
 MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ek_init_early,
-       .init_irq       = ek_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
 MACHINE_END
index 33eaa13..ad234cc 100644 (file)
@@ -50,7 +50,7 @@
 static void __init ek_init_early(void)
 {
        /* Initialize processor: 12.000 MHz crystal */
-       at91sam9g45_initialize(12000000);
+       at91_initialize(12000000);
 
        /* DGBU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -63,12 +63,6 @@ static void __init ek_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init ek_init_irq(void)
-{
-       at91sam9g45_init_interrupts(NULL);
-}
-
-
 /*
  * USB HS Host port (common to OHCI & EHCI)
  */
@@ -422,8 +416,8 @@ static void __init ek_board_init(void)
 MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9g45_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ek_init_early,
-       .init_irq       = ek_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
 MACHINE_END
index effb399..4f14b54 100644 (file)
@@ -41,7 +41,7 @@
 static void __init ek_init_early(void)
 {
        /* Initialize processor: 12.000 MHz crystal */
-       at91sam9rl_initialize(12000000);
+       at91_initialize(12000000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -53,12 +53,6 @@ static void __init ek_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init ek_init_irq(void)
-{
-       at91sam9rl_init_interrupts(NULL);
-}
-
-
 /*
  * USB HS Device port
  */
@@ -330,8 +324,8 @@ static void __init ek_board_init(void)
 MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9rl_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ek_init_early,
-       .init_irq       = ek_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
 MACHINE_END
index 6010ce1..c73d25e 100644 (file)
@@ -42,7 +42,7 @@
 
 static void __init snapper9260_init_early(void)
 {
-       at91sam9260_initialize(18432000);
+       at91_initialize(18432000);
 
        /* Debug on ttyS0 */
        at91_register_uart(0, 0, 0);
@@ -55,11 +55,6 @@ static void __init snapper9260_init_early(void)
        at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
 }
 
-static void __init snapper9260_init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
 static struct at91_usbh_data __initdata snapper9260_usbh_data = {
        .ports          = 2,
 };
@@ -179,9 +174,9 @@ static void __init snapper9260_board_init(void)
 
 MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = snapper9260_init_early,
-       .init_irq       = snapper9260_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = snapper9260_board_init,
 MACHINE_END
 
index 5e5c856..936e5fd 100644 (file)
@@ -35,7 +35,7 @@
 void __init stamp9g20_init_early(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
+       at91_initialize(18432000);
 
        /* DGBU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -76,12 +76,6 @@ static void __init portuxg20_init_early(void)
        at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
 }
 
-static void __init init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
-
 /*
  * NAND flash
  */
@@ -299,17 +293,17 @@ static void __init stamp9g20evb_board_init(void)
 MACHINE_START(PORTUXG20, "taskit PortuxG20")
        /* Maintainer: taskit GmbH */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = portuxg20_init_early,
-       .init_irq       = init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = portuxg20_board_init,
 MACHINE_END
 
 MACHINE_START(STAMP9G20, "taskit Stamp9G20")
        /* Maintainer: taskit GmbH */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = stamp9g20evb_init_early,
-       .init_irq       = init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = stamp9g20evb_board_init,
 MACHINE_END
index 0e784e6..8c4c1a0 100644 (file)
@@ -51,7 +51,7 @@
 static void __init ek_init_early(void)
 {
        /* Initialize processor: 12.000 MHz crystal */
-       at91sam9260_initialize(12000000);
+       at91_initialize(12000000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -60,12 +60,6 @@ static void __init ek_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init ek_init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
-
 /*
  * USB Host port
  */
@@ -229,8 +223,8 @@ static void __init ek_board_init(void)
 MACHINE_START(USB_A9260, "CALAO USB_A9260")
        /* Maintainer: calao-systems */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9260_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ek_init_early,
-       .init_irq       = ek_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
 MACHINE_END
index cf626dd..25e7937 100644 (file)
@@ -50,7 +50,7 @@
 static void __init ek_init_early(void)
 {
        /* Initialize processor: 12.00 MHz crystal */
-       at91sam9263_initialize(12000000);
+       at91_initialize(12000000);
 
        /* DBGU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
@@ -59,12 +59,6 @@ static void __init ek_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init ek_init_irq(void)
-{
-       at91sam9263_init_interrupts(NULL);
-}
-
-
 /*
  * USB Host port
  */
@@ -245,8 +239,8 @@ static void __init ek_board_init(void)
 MACHINE_START(USB_A9263, "CALAO USB_A9263")
        /* Maintainer: calao-systems */
        .timer          = &at91sam926x_timer,
-       .map_io         = at91sam9263_map_io,
+       .map_io         = at91_map_io,
        .init_early     = ek_init_early,
-       .init_irq       = ek_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
 MACHINE_END
index c208cc3..95edcbd 100644 (file)
@@ -56,7 +56,7 @@ static void __init yl9200_init_early(void)
        at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
 
        /* Initialize processor: 18.432 MHz crystal */
-       at91rm9200_initialize(18432000);
+       at91_initialize(18432000);
 
        /* Setup the LEDs D2=PB17 (timer), D3=PB16 (cpu) */
        at91_init_leds(AT91_PIN_PB16, AT91_PIN_PB17);
@@ -79,12 +79,6 @@ static void __init yl9200_init_early(void)
        at91_set_serial_console(0);
 }
 
-static void __init yl9200_init_irq(void)
-{
-       at91rm9200_init_interrupts(NULL);
-}
-
-
 /*
  * LEDs
  */
@@ -599,8 +593,8 @@ static void __init yl9200_board_init(void)
 MACHINE_START(YL9200, "uCdragon YL-9200")
        /* Maintainer: S.Birtles */
        .timer          = &at91rm9200_timer,
-       .map_io         = at91rm9200_map_io,
+       .map_io         = at91_map_io,
        .init_early     = yl9200_init_early,
-       .init_irq       = yl9200_init_irq,
+       .init_irq       = at91_init_irq_default,
        .init_machine   = yl9200_board_init,
 MACHINE_END
index 8ff3418..938b34f 100644 (file)
 #include <linux/clkdev.h>
 
  /* Map io */
-extern void __init at91rm9200_map_io(void);
-extern void __init at91sam9260_map_io(void);
-extern void __init at91sam9261_map_io(void);
-extern void __init at91sam9263_map_io(void);
-extern void __init at91sam9rl_map_io(void);
-extern void __init at91sam9g45_map_io(void);
-extern void __init at91x40_map_io(void);
-extern void __init at91cap9_map_io(void);
+extern void __init at91_map_io(void);
+extern void __init at91_init_sram(int bank, unsigned long base,
+                                 unsigned int length);
 
  /* Processors */
 extern void __init at91rm9200_set_type(int type);
-extern void __init at91rm9200_initialize(unsigned long main_clock);
-extern void __init at91sam9260_initialize(unsigned long main_clock);
-extern void __init at91sam9261_initialize(unsigned long main_clock);
-extern void __init at91sam9263_initialize(unsigned long main_clock);
-extern void __init at91sam9rl_initialize(unsigned long main_clock);
-extern void __init at91sam9g45_initialize(unsigned long main_clock);
+extern void __init at91_initialize(unsigned long main_clock);
 extern void __init at91x40_initialize(unsigned long main_clock);
-extern void __init at91cap9_initialize(unsigned long main_clock);
 
  /* Interrupts */
-extern void __init at91rm9200_init_interrupts(unsigned int priority[]);
-extern void __init at91sam9260_init_interrupts(unsigned int priority[]);
-extern void __init at91sam9261_init_interrupts(unsigned int priority[]);
-extern void __init at91sam9263_init_interrupts(unsigned int priority[]);
-extern void __init at91sam9rl_init_interrupts(unsigned int priority[]);
-extern void __init at91sam9g45_init_interrupts(unsigned int priority[]);
+extern void __init at91_init_irq_default(void);
+extern void __init at91_init_interrupts(unsigned int priority[]);
 extern void __init at91x40_init_interrupts(unsigned int priority[]);
-extern void __init at91cap9_init_interrupts(unsigned int priority[]);
 extern void __init at91_aic_init(unsigned int priority[]);
 
  /* Timer */
@@ -49,7 +33,6 @@ extern struct sys_timer at91sam926x_timer;
 extern struct sys_timer at91x40_timer;
 
  /* Clocks */
-extern int __init at91_clock_init(unsigned long main_clock);
 /*
  * function to specify the clock of the default console. As we do not
  * use the device/driver bus, the dev_name is not intialize. So we need
@@ -62,6 +45,11 @@ extern void __init at91sam9263_set_console_clock(int id);
 extern void __init at91sam9rl_set_console_clock(int id);
 extern void __init at91sam9g45_set_console_clock(int id);
 extern void __init at91cap9_set_console_clock(int id);
+#ifdef CONFIG_AT91_PMC_UNIT
+extern int __init at91_clock_init(unsigned long main_clock);
+#else
+static int inline at91_clock_init(unsigned long main_clock) { return 0; }
+#endif
 struct device;
 
  /* Power Management */
index 6dcaa77..dbfe455 100644 (file)
 #ifndef AT91_DBGU_H
 #define AT91_DBGU_H
 
+#define dbgu_readl(dbgu, field) \
+       __raw_readl(AT91_VA_BASE_SYS + dbgu + AT91_DBGU_ ## field)
+
 #ifdef AT91_DBGU
-#define AT91_DBGU_CR           (AT91_DBGU + 0x00)      /* Control Register */
-#define AT91_DBGU_MR           (AT91_DBGU + 0x04)      /* Mode Register */
-#define AT91_DBGU_IER          (AT91_DBGU + 0x08)      /* Interrupt Enable Register */
+#define AT91_DBGU_CR           (0x00)  /* Control Register */
+#define AT91_DBGU_MR           (0x04)  /* Mode Register */
+#define AT91_DBGU_IER          (0x08)  /* Interrupt Enable Register */
 #define                AT91_DBGU_TXRDY         (1 << 1)                /* Transmitter Ready */
 #define                AT91_DBGU_TXEMPTY       (1 << 9)                /* Transmitter Empty */
-#define AT91_DBGU_IDR          (AT91_DBGU + 0x0c)      /* Interrupt Disable Register */
-#define AT91_DBGU_IMR          (AT91_DBGU + 0x10)      /* Interrupt Mask Register */
-#define AT91_DBGU_SR           (AT91_DBGU + 0x14)      /* Status Register */
-#define AT91_DBGU_RHR          (AT91_DBGU + 0x18)      /* Receiver Holding Register */
-#define AT91_DBGU_THR          (AT91_DBGU + 0x1c)      /* Transmitter Holding Register */
-#define AT91_DBGU_BRGR         (AT91_DBGU + 0x20)      /* Baud Rate Generator Register */
+#define AT91_DBGU_IDR          (0x0c)  /* Interrupt Disable Register */
+#define AT91_DBGU_IMR          (0x10)  /* Interrupt Mask Register */
+#define AT91_DBGU_SR           (0x14)  /* Status Register */
+#define AT91_DBGU_RHR          (0x18)  /* Receiver Holding Register */
+#define AT91_DBGU_THR          (0x1c)  /* Transmitter Holding Register */
+#define AT91_DBGU_BRGR         (0x20)  /* Baud Rate Generator Register */
 
-#define AT91_DBGU_CIDR         (AT91_DBGU + 0x40)      /* Chip ID Register */
-#define AT91_DBGU_EXID         (AT91_DBGU + 0x44)      /* Chip ID Extension Register */
-#define AT91_DBGU_FNR          (AT91_DBGU + 0x48)      /* Force NTRST Register [SAM9 only] */
+#define AT91_DBGU_CIDR         (0x40)  /* Chip ID Register */
+#define AT91_DBGU_EXID         (0x44)  /* Chip ID Extension Register */
+#define AT91_DBGU_FNR          (0x48)  /* Force NTRST Register [SAM9 only] */
 #define                AT91_DBGU_FNTRST        (1 << 0)                /* Force NTRST */
 
 #endif /* AT91_DBGU */
index 6659938..c5df1e8 100644 (file)
@@ -75,7 +75,6 @@
 #define AT91CAP9_BASE_EMAC             0xfffbc000
 #define AT91CAP9_BASE_ADC              0xfffc0000
 #define AT91CAP9_BASE_ISI              0xfffc4000
-#define AT91_BASE_SYS                  0xffffe200
 
 /*
  * System Peripherals (offset from AT91_BASE_SYS)
index 99e0f8d..e4037b5 100644 (file)
@@ -74,7 +74,6 @@
 #define AT91RM9200_BASE_SSC1   0xfffd4000
 #define AT91RM9200_BASE_SSC2   0xfffd8000
 #define AT91RM9200_BASE_SPI    0xfffe0000
-#define AT91_BASE_SYS          0xfffff000
 
 
 /*
index 8b6bf83..9a79116 100644 (file)
@@ -76,7 +76,6 @@
 #define AT91SAM9260_BASE_TC4           0xfffdc040
 #define AT91SAM9260_BASE_TC5           0xfffdc080
 #define AT91SAM9260_BASE_ADC           0xfffe0000
-#define AT91_BASE_SYS                  0xffffe800
 
 /*
  * System Peripherals (offset from AT91_BASE_SYS)
index eafbdda..ce59620 100644 (file)
@@ -60,7 +60,6 @@
 #define AT91SAM9261_BASE_SSC2          0xfffc4000
 #define AT91SAM9261_BASE_SPI0          0xfffc8000
 #define AT91SAM9261_BASE_SPI1          0xfffcc000
-#define AT91_BASE_SYS                  0xffffea00
 
 
 /*
index e2d3482..f1b9296 100644 (file)
@@ -70,7 +70,6 @@
 #define AT91SAM9263_BASE_EMAC          0xfffbc000
 #define AT91SAM9263_BASE_ISI           0xfffc4000
 #define AT91SAM9263_BASE_2DGE          0xfffc8000
-#define AT91_BASE_SYS                  0xffffe000
 
 /*
  * System Peripherals (offset from AT91_BASE_SYS)
index 659304a..2c611b9 100644 (file)
@@ -82,7 +82,6 @@
 #define AT91SAM9G45_BASE_TC3           0xfffd4000
 #define AT91SAM9G45_BASE_TC4           0xfffd4040
 #define AT91SAM9G45_BASE_TC5           0xfffd4080
-#define AT91_BASE_SYS                  0xffffe200
 
 /*
  * System Peripherals (offset from AT91_BASE_SYS)
index 41dbbe6..1aabacd 100644 (file)
@@ -64,7 +64,6 @@
 #define AT91SAM9RL_BASE_TSC    0xfffd0000
 #define AT91SAM9RL_BASE_UDPHS  0xfffd4000
 #define AT91SAM9RL_BASE_AC97C  0xfffd8000
-#define AT91_BASE_SYS          0xffffc000
 
 
 /*
index df966c2..f6ce936 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * arch/arm/mach-at91/include/mach/cpu.h
  *
- *  Copyright (C) 2006 SAN People
+ * Copyright (C) 2006 SAN People
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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
  *
  */
 
-#ifndef __ASM_ARCH_CPU_H
-#define __ASM_ARCH_CPU_H
-
-#include <mach/hardware.h>
-#include <mach/at91_dbgu.h>
-
+#ifndef __MACH_CPU_H__
+#define __MACH_CPU_H__
 
 #define ARCH_ID_AT91RM9200     0x09290780
 #define ARCH_ID_AT91SAM9260    0x019803a0
 #define ARCH_ID_AT91M40807     0x14080745
 #define ARCH_ID_AT91R40008     0x44000840
 
-static inline unsigned long at91_cpu_identify(void)
-{
-       return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION);
-}
-
-static inline unsigned long at91_cpu_fully_identify(void)
-{
-       return at91_sys_read(AT91_DBGU_CIDR);
-}
-
 #define ARCH_EXID_AT91SAM9M11  0x00000001
 #define ARCH_EXID_AT91SAM9M10  0x00000002
 #define ARCH_EXID_AT91SAM9G46  0x00000003
@@ -60,40 +47,80 @@ static inline unsigned long at91_cpu_fully_identify(void)
 #define ARCH_EXID_AT91SAM9G25  0x00000003
 #define ARCH_EXID_AT91SAM9X25  0x00000004
 
-static inline unsigned long at91_exid_identify(void)
-{
-       return at91_sys_read(AT91_DBGU_EXID);
-}
-
-
 #define ARCH_FAMILY_AT91X92    0x09200000
 #define ARCH_FAMILY_AT91SAM9   0x01900000
 #define ARCH_FAMILY_AT91SAM9XE 0x02900000
 
-static inline unsigned long at91_arch_identify(void)
-{
-       return (at91_sys_read(AT91_DBGU_CIDR) & AT91_CIDR_ARCH);
-}
-
-#ifdef CONFIG_ARCH_AT91CAP9
-#include <mach/at91_pmc.h>
-
+/* PMC revision */
 #define ARCH_REVISION_CAP9_B   0x399
 #define ARCH_REVISION_CAP9_C   0x601
 
-static inline unsigned long at91cap9_rev_identify(void)
+/* RM9200 type */
+#define ARCH_REVISON_9200_BGA  (0 << 0)
+#define ARCH_REVISON_9200_PQFP (1 << 0)
+
+enum at91_soc_type {
+       /* 920T */
+       AT91_SOC_RM9200,
+
+       /* CAP */
+       AT91_SOC_CAP9,
+
+       /* SAM92xx */
+       AT91_SOC_SAM9260, AT91_SOC_SAM9261, AT91_SOC_SAM9263,
+
+       /* SAM9Gxx */
+       AT91_SOC_SAM9G10, AT91_SOC_SAM9G20, AT91_SOC_SAM9G45,
+
+       /* SAM9RL */
+       AT91_SOC_SAM9RL,
+
+       /* SAM9X5 */
+       AT91_SOC_SAM9X5,
+
+       /* Unknown type */
+       AT91_SOC_NONE
+};
+
+enum at91_soc_subtype {
+       /* RM9200 */
+       AT91_SOC_RM9200_BGA, AT91_SOC_RM9200_PQFP,
+
+       /* CAP9 */
+       AT91_SOC_CAP9_REV_B, AT91_SOC_CAP9_REV_C,
+
+       /* SAM9260 */
+       AT91_SOC_SAM9XE,
+
+       /* SAM9G45 */
+       AT91_SOC_SAM9G45ES, AT91_SOC_SAM9M10, AT91_SOC_SAM9G46, AT91_SOC_SAM9M11,
+
+       /* SAM9X5 */
+       AT91_SOC_SAM9G15, AT91_SOC_SAM9G35, AT91_SOC_SAM9X35,
+       AT91_SOC_SAM9G25, AT91_SOC_SAM9X25,
+
+       /* Unknown subtype */
+       AT91_SOC_SUBTYPE_NONE
+};
+
+struct at91_socinfo {
+       unsigned int type, subtype;
+       unsigned int cidr, exid;
+};
+
+extern struct at91_socinfo at91_soc_initdata;
+const char *at91_get_soc_type(struct at91_socinfo *c);
+const char *at91_get_soc_subtype(struct at91_socinfo *c);
+
+static inline int at91_soc_is_detected(void)
 {
-       return (at91_sys_read(AT91_PMC_VER));
+       return at91_soc_initdata.type != AT91_SOC_NONE;
 }
-#endif
 
 #ifdef CONFIG_ARCH_AT91RM9200
-extern int rm9200_type;
-#define ARCH_REVISON_9200_BGA  (0 << 0)
-#define ARCH_REVISON_9200_PQFP (1 << 0)
-#define cpu_is_at91rm9200()    (at91_cpu_identify() == ARCH_ID_AT91RM9200)
-#define cpu_is_at91rm9200_bga()        (!cpu_is_at91rm9200_pqfp())
-#define cpu_is_at91rm9200_pqfp() (cpu_is_at91rm9200() && rm9200_type & ARCH_REVISON_9200_PQFP)
+#define cpu_is_at91rm9200()    (at91_soc_initdata.type == AT91_SOC_RM9200)
+#define cpu_is_at91rm9200_bga()        (at91_soc_initdata.subtype == AT91_SOC_RM9200_BGA)
+#define cpu_is_at91rm9200_pqfp() (at91_soc_initdata.subtype == AT91_SOC_RM9200_PQFP)
 #else
 #define cpu_is_at91rm9200()    (0)
 #define cpu_is_at91rm9200_bga()        (0)
@@ -101,52 +128,49 @@ extern int rm9200_type;
 #endif
 
 #ifdef CONFIG_ARCH_AT91SAM9260
-#define cpu_is_at91sam9xe()    (at91_arch_identify() == ARCH_FAMILY_AT91SAM9XE)
-#define cpu_is_at91sam9260()   ((at91_cpu_identify() == ARCH_ID_AT91SAM9260) || cpu_is_at91sam9xe())
+#define cpu_is_at91sam9xe()    (at91_soc_initdata.subtype == AT91_SOC_SAM9XE)
+#define cpu_is_at91sam9260()   (at91_soc_initdata.type == AT91_SOC_SAM9260)
 #else
 #define cpu_is_at91sam9xe()    (0)
 #define cpu_is_at91sam9260()   (0)
 #endif
 
 #ifdef CONFIG_ARCH_AT91SAM9G20
-#define cpu_is_at91sam9g20()   (at91_cpu_identify() == ARCH_ID_AT91SAM9G20)
+#define cpu_is_at91sam9g20()   (at91_soc_initdata.type == AT91_SOC_SAM9G20)
 #else
 #define cpu_is_at91sam9g20()   (0)
 #endif
 
 #ifdef CONFIG_ARCH_AT91SAM9261
-#define cpu_is_at91sam9261()   (at91_cpu_identify() == ARCH_ID_AT91SAM9261)
+#define cpu_is_at91sam9261()   (at91_soc_initdata.type == AT91_SOC_SAM9261)
 #else
 #define cpu_is_at91sam9261()   (0)
 #endif
 
 #ifdef CONFIG_ARCH_AT91SAM9G10
-#define cpu_is_at91sam9g10()   ((at91_cpu_identify() & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10)
+#define cpu_is_at91sam9g10()   (at91_soc_initdata.type == AT91_SOC_SAM9G10)
 #else
 #define cpu_is_at91sam9g10()   (0)
 #endif
 
 #ifdef CONFIG_ARCH_AT91SAM9263
-#define cpu_is_at91sam9263()   (at91_cpu_identify() == ARCH_ID_AT91SAM9263)
+#define cpu_is_at91sam9263()   (at91_soc_initdata.type == AT91_SOC_SAM9263)
 #else
 #define cpu_is_at91sam9263()   (0)
 #endif
 
 #ifdef CONFIG_ARCH_AT91SAM9RL
-#define cpu_is_at91sam9rl()    (at91_cpu_identify() == ARCH_ID_AT91SAM9RL64)
+#define cpu_is_at91sam9rl()    (at91_soc_initdata.type == AT91_SOC_SAM9RL)
 #else
 #define cpu_is_at91sam9rl()    (0)
 #endif
 
 #ifdef CONFIG_ARCH_AT91SAM9G45
-#define cpu_is_at91sam9g45()   (at91_cpu_identify() == ARCH_ID_AT91SAM9G45)
-#define cpu_is_at91sam9g45es() (at91_cpu_fully_identify() == ARCH_ID_AT91SAM9G45ES)
-#define cpu_is_at91sam9m10()    (cpu_is_at91sam9g45() && \
-                                (at91_exid_identify() == ARCH_EXID_AT91SAM9M10))
-#define cpu_is_at91sam9m46()    (cpu_is_at91sam9g45() && \
-                                (at91_exid_identify() == ARCH_EXID_AT91SAM9G46))
-#define cpu_is_at91sam9m11()    (cpu_is_at91sam9g45() && \
-                                (at91_exid_identify() == ARCH_EXID_AT91SAM9M11))
+#define cpu_is_at91sam9g45()   (at91_soc_initdata.type == AT91_SOC_SAM9G45)
+#define cpu_is_at91sam9g45es() (at91_soc_initdata.subtype == AT91_SOC_SAM9G45ES)
+#define cpu_is_at91sam9m10()   (at91_soc_initdata.subtype == AT91_SOC_SAM9M10)
+#define cpu_is_at91sam9g46()   (at91_soc_initdata.subtype == AT91_SOC_SAM9G46)
+#define cpu_is_at91sam9m11()   (at91_soc_initdata.subtype == AT91_SOC_SAM9M11)
 #else
 #define cpu_is_at91sam9g45()   (0)
 #define cpu_is_at91sam9g45es() (0)
@@ -156,17 +180,12 @@ extern int rm9200_type;
 #endif
 
 #ifdef CONFIG_ARCH_AT91SAM9X5
-#define cpu_is_at91sam9x5()    (at91_cpu_identify() == ARCH_ID_AT91SAM9X5)
-#define cpu_is_at91sam9g15()   (cpu_is_at91sam9x5() && \
-                               (at91_exid_identify() == ARCH_EXID_AT91SAM9G15))
-#define cpu_is_at91sam9g35()   (cpu_is_at91sam9x5() && \
-                               (at91_exid_identify() == ARCH_EXID_AT91SAM9G35))
-#define cpu_is_at91sam9x35()   (cpu_is_at91sam9x5() && \
-                               (at91_exid_identify() == ARCH_EXID_AT91SAM9X35))
-#define cpu_is_at91sam9g25()   (cpu_is_at91sam9x5() && \
-                               (at91_exid_identify() == ARCH_EXID_AT91SAM9G25))
-#define cpu_is_at91sam9x25()   (cpu_is_at91sam9x5() && \
-                               (at91_exid_identify() == ARCH_EXID_AT91SAM9X25))
+#define cpu_is_at91sam9x5()    (at91_soc_initdata.type == AT91_SOC_SAM9X5)
+#define cpu_is_at91sam9g15()   (at91_soc_initdata.subtype == AT91_SOC_SAM9G15)
+#define cpu_is_at91sam9g35()   (at91_soc_initdata.subtype == AT91_SOC_SAM9G35)
+#define cpu_is_at91sam9x35()   (at91_soc_initdata.subtype == AT91_SOC_SAM9X35)
+#define cpu_is_at91sam9g25()   (at91_soc_initdata.subtype == AT91_SOC_SAM9G25)
+#define cpu_is_at91sam9x25()   (at91_soc_initdata.subtype == AT91_SOC_SAM9X25)
 #else
 #define cpu_is_at91sam9x5()    (0)
 #define cpu_is_at91sam9g15()   (0)
@@ -177,9 +196,9 @@ extern int rm9200_type;
 #endif
 
 #ifdef CONFIG_ARCH_AT91CAP9
-#define cpu_is_at91cap9()      (at91_cpu_identify() == ARCH_ID_AT91CAP9)
-#define cpu_is_at91cap9_revB() (at91cap9_rev_identify() == ARCH_REVISION_CAP9_B)
-#define cpu_is_at91cap9_revC() (at91cap9_rev_identify() == ARCH_REVISION_CAP9_C)
+#define cpu_is_at91cap9()      (at91_soc_initdata.type == AT91_SOC_CAP9)
+#define cpu_is_at91cap9_revB() (at91_soc_initdata.subtype == AT91_SOC_CAP9_REV_B)
+#define cpu_is_at91cap9_revC() (at91_soc_initdata.subtype == AT91_SOC_CAP9_REV_C)
 #else
 #define cpu_is_at91cap9()      (0)
 #define cpu_is_at91cap9_revB() (0)
@@ -192,4 +211,4 @@ extern int rm9200_type;
  */
 #define cpu_is_at32ap7000()    (0)
 
-#endif
+#endif /* __MACH_CPU_H__ */
index 0f959fa..bc1e0b2 100644 (file)
 #include <mach/at91_dbgu.h>
 
        .macro  addruart, rp, rv
-       ldr     \rp, =(AT91_BASE_SYS + AT91_DBGU)               @ System peripherals (phys address)
-       ldr     \rv, =(AT91_VA_BASE_SYS + AT91_DBGU)            @ System peripherals (virt address)
+       ldr     \rp, =(AT91_BASE_SYS + AT91_DBGU)       @ System peripherals (phys address)
+       ldr     \rv, =(AT91_VA_BASE_SYS + AT91_DBGU)    @ System peripherals (virt address)
        .endm
 
        .macro  senduart,rd,rx
-       strb    \rd, [\rx, #(AT91_DBGU_THR - AT91_DBGU)]        @ Write to Transmitter Holding Register
+       strb    \rd, [\rx, #(AT91_DBGU_THR)]            @ Write to Transmitter Holding Register
        .endm
 
        .macro  waituart,rd,rx
-1001:  ldr     \rd, [\rx, #(AT91_DBGU_SR - AT91_DBGU)]         @ Read Status Register
-       tst     \rd, #AT91_DBGU_TXRDY                           @ DBGU_TXRDY = 1 when ready to transmit
+1001:  ldr     \rd, [\rx, #(AT91_DBGU_SR)]             @ Read Status Register
+       tst     \rd, #AT91_DBGU_TXRDY                   @ DBGU_TXRDY = 1 when ready to transmit
        beq     1001b
        .endm
 
        .macro  busyuart,rd,rx
-1001:  ldr     \rd, [\rx, #(AT91_DBGU_SR - AT91_DBGU)]         @ Read Status Register
-       tst     \rd, #AT91_DBGU_TXEMPTY                         @ DBGU_TXEMPTY = 1 when transmission complete
+1001:  ldr     \rd, [\rx, #(AT91_DBGU_SR)]             @ Read Status Register
+       tst     \rd, #AT91_DBGU_TXEMPTY                 @ DBGU_TXEMPTY = 1 when transmission complete
        beq     1001b
        .endm
 
index 1008b9f..483478d 100644 (file)
 #error "Unsupported AT91 processor"
 #endif
 
+#if !defined(CONFIG_ARCH_AT91X40)
+/*
+ * On all at91 except rm9200 and x40 have the System Controller starts
+ * at address 0xffffc000 and has a size of 16KiB.
+ *
+ * On rm9200 it's start at 0xfffe4000 of 111KiB with non reserved data starting
+ * at 0xfffff000
+ *
+ * Removes the individual definitions of AT91_BASE_SYS and
+ * replaces them with a common version at base 0xfffffc000 and size 16KiB
+ * and map the same memory space
+ */
+#define AT91_BASE_SYS  0xffffc000
+#endif
 
 /*
  * Peripheral identifiers/interrupts.
index 0b0cccc..4298e78 100644 (file)
 #ifndef __ASM_ARCH_IO_H
 #define __ASM_ARCH_IO_H
 
+#include <mach/hardware.h>
+
 #define IO_SPACE_LIMIT         0xFFFFFFFF
 
 #define __io(a)                __typesafe_io(a)
 #define __mem_pci(a)   (a)
 
-
 #ifndef __ASSEMBLY__
 
+#ifndef CONFIG_ARCH_AT91X40
+#define __arch_ioremap at91_ioremap
+#define __arch_iounmap at91_iounmap
+#endif
+
+void __iomem *at91_ioremap(unsigned long phys, size_t size, unsigned int type);
+void at91_iounmap(volatile void __iomem *addr);
+
 static inline unsigned int at91_sys_read(unsigned int reg_offset)
 {
        void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS;
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
new file mode 100644 (file)
index 0000000..aa64294
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2007 Atmel Corporation.
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Under GPLv2
+ */
+
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/cpu.h>
+#include <mach/at91_dbgu.h>
+#include <mach/at91_pmc.h>
+
+#include "soc.h"
+#include "generic.h"
+
+struct at91_init_soc __initdata at91_boot_soc;
+
+struct at91_socinfo at91_soc_initdata;
+EXPORT_SYMBOL(at91_soc_initdata);
+
+void __init at91rm9200_set_type(int type)
+{
+       if (type == ARCH_REVISON_9200_PQFP)
+               at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
+       else
+               at91_soc_initdata.subtype = AT91_SOC_RM9200_PQFP;
+}
+
+void __init at91_init_irq_default(void)
+{
+       at91_init_interrupts(at91_boot_soc.default_irq_priority);
+}
+
+void __init at91_init_interrupts(unsigned int *priority)
+{
+       /* Initialize the AIC interrupt controller */
+       at91_aic_init(priority);
+
+       /* Enable GPIO interrupts */
+       at91_gpio_irq_setup();
+}
+
+static struct map_desc sram_desc[2] __initdata;
+
+void __init at91_init_sram(int bank, unsigned long base, unsigned int length)
+{
+       struct map_desc *desc = &sram_desc[bank];
+
+       desc->virtual = AT91_IO_VIRT_BASE - length;
+       if (bank > 0)
+               desc->virtual -= sram_desc[bank - 1].length;
+
+       desc->pfn = __phys_to_pfn(base);
+       desc->length = length;
+       desc->type = MT_DEVICE;
+
+       pr_info("AT91: sram at 0x%lx of 0x%x mapped at 0x%lx\n",
+               base, length, desc->virtual);
+
+       iotable_init(desc, 1);
+}
+
+static struct map_desc at91_io_desc __initdata = {
+       .virtual        = AT91_VA_BASE_SYS,
+       .pfn            = __phys_to_pfn(AT91_BASE_SYS),
+       .length         = SZ_16K,
+       .type           = MT_DEVICE,
+};
+
+void __iomem *at91_ioremap(unsigned long p, size_t size, unsigned int type)
+{
+       if (p >= AT91_BASE_SYS && p <= (AT91_BASE_SYS + SZ_16K - 1))
+               return (void __iomem *)AT91_IO_P2V(p);
+
+       return __arm_ioremap_caller(p, size, type, __builtin_return_address(0));
+}
+EXPORT_SYMBOL(at91_ioremap);
+
+void at91_iounmap(volatile void __iomem *addr)
+{
+       unsigned long virt = (unsigned long)addr;
+
+       if (virt >= VMALLOC_START && virt < VMALLOC_END)
+               __iounmap(addr);
+}
+EXPORT_SYMBOL(at91_iounmap);
+
+#define AT91_DBGU0     0xfffff200
+#define AT91_DBGU1     0xffffee00
+
+static void __init soc_detect(u32 dbgu_base)
+{
+       u32 cidr, socid;
+
+       cidr = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_CIDR);
+       socid = cidr & ~AT91_CIDR_VERSION;
+
+       switch (socid) {
+       case ARCH_ID_AT91CAP9: {
+#ifdef CONFIG_AT91_PMC_UNIT
+               u32 pmc_ver = at91_sys_read(AT91_PMC_VER);
+
+               if (pmc_ver == ARCH_REVISION_CAP9_B)
+                       at91_soc_initdata.subtype = AT91_SOC_CAP9_REV_B;
+               else if (pmc_ver == ARCH_REVISION_CAP9_C)
+                       at91_soc_initdata.subtype = AT91_SOC_CAP9_REV_C;
+#endif
+               at91_soc_initdata.type = AT91_SOC_CAP9;
+               at91_boot_soc = at91cap9_soc;
+               break;
+       }
+
+       case ARCH_ID_AT91RM9200:
+               at91_soc_initdata.type = AT91_SOC_RM9200;
+               at91_boot_soc = at91rm9200_soc;
+               break;
+
+       case ARCH_ID_AT91SAM9260:
+               at91_soc_initdata.type = AT91_SOC_SAM9260;
+               at91_boot_soc = at91sam9260_soc;
+               break;
+
+       case ARCH_ID_AT91SAM9261:
+               at91_soc_initdata.type = AT91_SOC_SAM9261;
+               at91_boot_soc = at91sam9261_soc;
+               break;
+
+       case ARCH_ID_AT91SAM9263:
+               at91_soc_initdata.type = AT91_SOC_SAM9263;
+               at91_boot_soc = at91sam9263_soc;
+               break;
+
+       case ARCH_ID_AT91SAM9G20:
+               at91_soc_initdata.type = AT91_SOC_SAM9G20;
+               at91_boot_soc = at91sam9260_soc;
+               break;
+
+       case ARCH_ID_AT91SAM9G45:
+               at91_soc_initdata.type = AT91_SOC_SAM9G45;
+               if (cidr == ARCH_ID_AT91SAM9G45ES)
+                       at91_soc_initdata.subtype = AT91_SOC_SAM9G45ES;
+               at91_boot_soc = at91sam9g45_soc;
+               break;
+
+       case ARCH_ID_AT91SAM9RL64:
+               at91_soc_initdata.type = AT91_SOC_SAM9RL;
+               at91_boot_soc = at91sam9rl_soc;
+               break;
+
+       case ARCH_ID_AT91SAM9X5:
+               at91_soc_initdata.type = AT91_SOC_SAM9X5;
+               at91_boot_soc = at91sam9x5_soc;
+               break;
+       }
+
+       /* at91sam9g10 */
+       if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
+               at91_soc_initdata.type = AT91_SOC_SAM9G10;
+               at91_boot_soc = at91sam9261_soc;
+       }
+       /* at91sam9xe */
+       else if ((cidr & AT91_CIDR_ARCH) == ARCH_FAMILY_AT91SAM9XE) {
+               at91_soc_initdata.type = AT91_SOC_SAM9260;
+               at91_soc_initdata.subtype = AT91_SOC_SAM9XE;
+               at91_boot_soc = at91sam9260_soc;
+       }
+
+       if (!at91_soc_is_detected())
+               return;
+
+       at91_soc_initdata.cidr = cidr;
+
+       /* sub version of soc */
+       at91_soc_initdata.exid = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_EXID);
+
+       if (at91_soc_initdata.type == AT91_SOC_SAM9G45) {
+               switch (at91_soc_initdata.exid) {
+               case ARCH_EXID_AT91SAM9M10:
+                       at91_soc_initdata.subtype = AT91_SOC_SAM9M10;
+                       break;
+               case ARCH_EXID_AT91SAM9G46:
+                       at91_soc_initdata.subtype = AT91_SOC_SAM9G46;
+                       break;
+               case ARCH_EXID_AT91SAM9M11:
+                       at91_soc_initdata.subtype = AT91_SOC_SAM9M11;
+                       break;
+               }
+       }
+
+       if (at91_soc_initdata.type == AT91_SOC_SAM9X5) {
+               switch (at91_soc_initdata.exid) {
+               case ARCH_EXID_AT91SAM9G15:
+                       at91_soc_initdata.subtype = AT91_SOC_SAM9G15;
+                       break;
+               case ARCH_EXID_AT91SAM9G35:
+                       at91_soc_initdata.subtype = AT91_SOC_SAM9G35;
+                       break;
+               case ARCH_EXID_AT91SAM9X35:
+                       at91_soc_initdata.subtype = AT91_SOC_SAM9X35;
+                       break;
+               case ARCH_EXID_AT91SAM9G25:
+                       at91_soc_initdata.subtype = AT91_SOC_SAM9G25;
+                       break;
+               case ARCH_EXID_AT91SAM9X25:
+                       at91_soc_initdata.subtype = AT91_SOC_SAM9X25;
+                       break;
+               }
+       }
+}
+
+static const char *soc_name[] = {
+       [AT91_SOC_RM9200]       = "at91rm9200",
+       [AT91_SOC_CAP9]         = "at91cap9",
+       [AT91_SOC_SAM9260]      = "at91sam9260",
+       [AT91_SOC_SAM9261]      = "at91sam9261",
+       [AT91_SOC_SAM9263]      = "at91sam9263",
+       [AT91_SOC_SAM9G10]      = "at91sam9g10",
+       [AT91_SOC_SAM9G20]      = "at91sam9g20",
+       [AT91_SOC_SAM9G45]      = "at91sam9g45",
+       [AT91_SOC_SAM9RL]       = "at91sam9rl",
+       [AT91_SOC_SAM9X5]       = "at91sam9x5",
+       [AT91_SOC_NONE]         = "Unknown"
+};
+
+const char *at91_get_soc_type(struct at91_socinfo *c)
+{
+       return soc_name[c->type];
+}
+EXPORT_SYMBOL(at91_get_soc_type);
+
+static const char *soc_subtype_name[] = {
+       [AT91_SOC_RM9200_BGA]   = "at91rm9200 BGA",
+       [AT91_SOC_RM9200_PQFP]  = "at91rm9200 PQFP",
+       [AT91_SOC_CAP9_REV_B]   = "at91cap9 revB",
+       [AT91_SOC_CAP9_REV_C]   = "at91cap9 revC",
+       [AT91_SOC_SAM9XE]       = "at91sam9xe",
+       [AT91_SOC_SAM9G45ES]    = "at91sam9g45es",
+       [AT91_SOC_SAM9M10]      = "at91sam9m10",
+       [AT91_SOC_SAM9G46]      = "at91sam9g46",
+       [AT91_SOC_SAM9M11]      = "at91sam9m11",
+       [AT91_SOC_SAM9G15]      = "at91sam9g15",
+       [AT91_SOC_SAM9G35]      = "at91sam9g35",
+       [AT91_SOC_SAM9X35]      = "at91sam9x35",
+       [AT91_SOC_SAM9G25]      = "at91sam9g25",
+       [AT91_SOC_SAM9X25]      = "at91sam9x25",
+       [AT91_SOC_SUBTYPE_NONE] = "Unknown"
+};
+
+const char *at91_get_soc_subtype(struct at91_socinfo *c)
+{
+       return soc_subtype_name[c->subtype];
+}
+EXPORT_SYMBOL(at91_get_soc_subtype);
+
+void __init at91_map_io(void)
+{
+       /* Map peripherals */
+       iotable_init(&at91_io_desc, 1);
+
+       at91_soc_initdata.type = AT91_SOC_NONE;
+       at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE;
+
+       soc_detect(AT91_DBGU0);
+       if (!at91_soc_is_detected())
+               soc_detect(AT91_DBGU1);
+
+       if (!at91_soc_is_detected())
+               panic("AT91: Impossible to detect the SOC type");
+
+       pr_info("AT91: Detected soc type: %s\n",
+               at91_get_soc_type(&at91_soc_initdata));
+       pr_info("AT91: Detected soc subtype: %s\n",
+               at91_get_soc_subtype(&at91_soc_initdata));
+
+       if (!at91_soc_is_enabled())
+               panic("AT91: Soc not enabled");
+
+       if (at91_boot_soc.map_io)
+               at91_boot_soc.map_io();
+}
+
+void __init at91_initialize(unsigned long main_clock)
+{
+       /* Init clock subsystem */
+       at91_clock_init(main_clock);
+
+       /* Register the processor-specific clocks */
+       at91_boot_soc.register_clocks();
+
+       at91_boot_soc.init();
+}
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
new file mode 100644 (file)
index 0000000..21ed881
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Under GPLv2
+ */
+
+struct at91_init_soc {
+       unsigned int *default_irq_priority;
+       void (*map_io)(void);
+       void (*register_clocks)(void);
+       void (*init)(void);
+};
+
+extern struct at91_init_soc at91_boot_soc;
+extern struct at91_init_soc at91cap9_soc;
+extern struct at91_init_soc at91rm9200_soc;
+extern struct at91_init_soc at91sam9260_soc;
+extern struct at91_init_soc at91sam9261_soc;
+extern struct at91_init_soc at91sam9263_soc;
+extern struct at91_init_soc at91sam9g45_soc;
+extern struct at91_init_soc at91sam9rl_soc;
+extern struct at91_init_soc at91sam9x5_soc;
+
+static inline int at91_soc_is_enabled(void)
+{
+       return at91_boot_soc.init != NULL;
+}
+
+#if !defined(CONFIG_ARCH_AT91CAP9)
+#define at91cap9_soc   at91_boot_soc
+#endif
+
+#if !defined(CONFIG_ARCH_AT91RM9200)
+#define at91rm9200_soc at91_boot_soc
+#endif
+
+#if !(defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20))
+#define at91sam9260_soc        at91_boot_soc
+#endif
+
+#if !(defined(CONFIG_ARCH_AT91SAM9261) || defined(CONFIG_ARCH_AT91SAM9G10))
+#define at91sam9261_soc        at91_boot_soc
+#endif
+
+#if !defined(CONFIG_ARCH_AT91SAM9263)
+#define at91sam9263_soc        at91_boot_soc
+#endif
+
+#if !defined(CONFIG_ARCH_AT91SAM9G45)
+#define at91sam9g45_soc        at91_boot_soc
+#endif
+
+#if !defined(CONFIG_ARCH_AT91SAM9RL)
+#define at91sam9rl_soc at91_boot_soc
+#endif
+
+#if !defined(CONFIG_ARCH_AT91SAM9X5)
+#define at91sam9x5_soc at91_boot_soc
+#endif
index a4ec080..06fd25d 100644 (file)
@@ -172,7 +172,7 @@ static struct pci_bus *cns3xxx_pci_scan_bus(int nr, struct pci_sys_data *sys)
        return pci_scan_bus(sys->busnr, &cns3xxx_pcie_ops, sys);
 }
 
-static int cns3xxx_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int cns3xxx_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        struct cns3xxx_pcie *cnspci = pdev_to_cnspci(dev);
        int irq = cnspci->irqs[slot];
index c2f1c47..aa2b3a0 100644 (file)
@@ -193,7 +193,7 @@ dove_pcie_scan_bus(int nr, struct pci_sys_data *sys)
        return bus;
 }
 
-static int __init dove_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init dove_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        struct pcie_port *pp = bus_to_port(dev->bus->number);
 
index ae3e1c8..32321f6 100644 (file)
@@ -16,7 +16,7 @@
 /* cats host-specific stuff */
 static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
 
-static int __init cats_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        if (dev->irq >= 255)
                return -1;      /* not a valid interrupt. */
index e5ab5bd..511c673 100644 (file)
@@ -15,7 +15,7 @@
 
 static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI };
 
-static int __init ebsa285_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init ebsa285_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
            dev->device == PCI_DEVICE_ID_CONTAQ_82C693)
index e263d6d..6218761 100644 (file)
@@ -17,7 +17,7 @@
  * We now use the slot ID instead of the device identifiers to select
  * which interrupt is routed where.
  */
-static int __init netwinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init netwinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        switch (slot) {
        case 0:  /* host bridge */
index d5fca95..aeb651d 100644 (file)
@@ -18,7 +18,8 @@ static int irqmap_personal_server[] __initdata = {
        IRQ_DOORBELLHOST, IRQ_DMA1, IRQ_DMA2, IRQ_PCI
 };
 
-static int __init personal_server_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init personal_server_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        unsigned char line;
 
index dcc4172..4aabeb2 100644 (file)
@@ -587,9 +587,9 @@ static struct clk_lookup lookups[] __initdata = {
        _REGISTER_CLOCK(NULL, "mma", mma_clk)
        _REGISTER_CLOCK("imx_udc.0", NULL, usbd_clk)
        _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-       _REGISTER_CLOCK("imx-uart.0", NULL, uart_clk)
-       _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk)
-       _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk)
+       _REGISTER_CLOCK("imx1-uart.0", NULL, uart_clk)
+       _REGISTER_CLOCK("imx1-uart.1", NULL, uart_clk)
+       _REGISTER_CLOCK("imx1-uart.2", NULL, uart_clk)
        _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
        _REGISTER_CLOCK("imx1-cspi.0", NULL, spi_clk)
        _REGISTER_CLOCK("imx1-cspi.1", NULL, spi_clk)
index bf30a8c..ee15d8c 100644 (file)
@@ -1162,10 +1162,10 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK(NULL, "perclk3", per_clk[2])
        _REGISTER_CLOCK(NULL, "perclk4", per_clk[3])
        _REGISTER_CLOCK(NULL, "clko", clko_clk)
-       _REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0])
-       _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[1])
-       _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[2])
-       _REGISTER_CLOCK("imx-uart.3", NULL, uart_clk[3])
+       _REGISTER_CLOCK("imx21-uart.0", NULL, uart_clk[0])
+       _REGISTER_CLOCK("imx21-uart.1", NULL, uart_clk[1])
+       _REGISTER_CLOCK("imx21-uart.2", NULL, uart_clk[2])
+       _REGISTER_CLOCK("imx21-uart.3", NULL, uart_clk[3])
        _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[0])
        _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[1])
        _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[2])
index af1c580..e63e235 100644 (file)
@@ -272,11 +272,12 @@ DEFINE_CLOCK(can2_clk,     1, CCM_CGCR1,  3, get_rate_ipg, NULL, NULL);
        },
 
 static struct clk_lookup lookups[] = {
-       _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-       _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-       _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
-       _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
-       _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
+       /* i.mx25 has the i.mx21 type uart */
+       _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+       _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+       _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+       _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
+       _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
        _REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk)
        _REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk)
        _REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
@@ -295,19 +296,20 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
        _REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk)
        _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk)
-       _REGISTER_CLOCK("fec.0", NULL, fec_clk)
+       _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
        _REGISTER_CLOCK("imxdi_rtc.0", NULL, dryice_clk)
        _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
        _REGISTER_CLOCK("imx2-wdt.0", NULL, wdt_clk)
        _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
        _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx25.0", NULL, esdhc1_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx25.1", NULL, esdhc2_clk)
        _REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
        _REGISTER_CLOCK(NULL, "audmux", audmux_clk)
        _REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
        _REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
-       _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+       /* i.mx25 has the i.mx35 type sdma */
+       _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
 };
 
 int __init mx25_clocks_init(void)
@@ -329,6 +331,9 @@ int __init mx25_clocks_init(void)
        __raw_writel(__raw_readl(CRM_BASE+0x64) | (1 << 7) | (1 << 0),
                        CRM_BASE + 0x64);
 
+       /* Clock source for gpt is ahb_div */
+       __raw_writel(__raw_readl(CRM_BASE+0x64) & ~(1 << 5), CRM_BASE + 0x64);
+
        mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
 
        return 0;
index 583f251..6912b82 100644 (file)
@@ -624,12 +624,13 @@ DEFINE_CLOCK1(csi_clk,     0, NULL,   0, parent, &csi_clk1, &per4_clk);
        },
 
 static struct clk_lookup lookups[] = {
-       _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-       _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-       _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
-       _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
-       _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
-       _REGISTER_CLOCK("imx-uart.5", NULL, uart6_clk)
+       /* i.mx27 has the i.mx21 type uart */
+       _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+       _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+       _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+       _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
+       _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
+       _REGISTER_CLOCK("imx21-uart.5", NULL, uart6_clk)
        _REGISTER_CLOCK(NULL, "gpt1", gpt1_clk)
        _REGISTER_CLOCK(NULL, "gpt2", gpt2_clk)
        _REGISTER_CLOCK(NULL, "gpt3", gpt3_clk)
@@ -662,7 +663,7 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK(NULL, "brom", brom_clk)
        _REGISTER_CLOCK(NULL, "emma", emma_clk)
        _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk)
-       _REGISTER_CLOCK("fec.0", NULL, fec_clk)
+       _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
        _REGISTER_CLOCK(NULL, "emi", emi_clk)
        _REGISTER_CLOCK(NULL, "sahara2", sahara2_clk)
        _REGISTER_CLOCK(NULL, "ata", ata_clk)
index 25f343f..d973770 100644 (file)
@@ -547,11 +547,12 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk1)
        _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk2)
        _REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk)
-       _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-       _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-       _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
-       _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
-       _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
+       /* i.mx31 has the i.mx21 type uart */
+       _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+       _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+       _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+       _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
+       _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
        _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
        _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
        _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk)
@@ -564,7 +565,7 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK(NULL, "ata", ata_clk)
        _REGISTER_CLOCK(NULL, "rtic", rtic_clk)
        _REGISTER_CLOCK(NULL, "rng", rng_clk)
-       _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk1)
+       _REGISTER_CLOCK("imx31-sdma", NULL, sdma_clk1)
        _REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2)
        _REGISTER_CLOCK(NULL, "mstick", mstick1_clk)
        _REGISTER_CLOCK(NULL, "mstick", mstick2_clk)
index 5a4cc1e..88b62a0 100644 (file)
@@ -458,10 +458,11 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("imx-epit.0", NULL, epit1_clk)
        _REGISTER_CLOCK("imx-epit.1", NULL, epit2_clk)
        _REGISTER_CLOCK(NULL, "esai", esai_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
-       _REGISTER_CLOCK("fec.0", NULL, fec_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx35.0", NULL, esdhc1_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx35.1", NULL, esdhc2_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx35.2", NULL, esdhc3_clk)
+       /* i.mx35 has the i.mx27 type fec */
+       _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
        _REGISTER_CLOCK(NULL, "gpio", gpio1_clk)
        _REGISTER_CLOCK(NULL, "gpio", gpio2_clk)
        _REGISTER_CLOCK(NULL, "gpio", gpio3_clk)
@@ -481,14 +482,15 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK(NULL, "rtc", rtc_clk)
        _REGISTER_CLOCK(NULL, "rtic", rtic_clk)
        _REGISTER_CLOCK(NULL, "scc", scc_clk)
-       _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+       _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
        _REGISTER_CLOCK(NULL, "spba", spba_clk)
        _REGISTER_CLOCK(NULL, "spdif", spdif_clk)
        _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
        _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
-       _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-       _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-       _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+       /* i.mx35 has the i.mx21 type uart */
+       _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+       _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+       _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
        _REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk)
        _REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk)
        _REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
index 01ebcb3..66e8726 100644 (file)
@@ -225,7 +225,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
 
 static struct esdhc_platform_data sd1_pdata = {
        .cd_gpio = GPIO_SD1CD,
-       .wp_gpio = -EINVAL,
+       .cd_type = ESDHC_CD_GPIO,
+       .wp_type = ESDHC_WP_NONE,
 };
 
 /*
index 558eb52..0f0af02 100644 (file)
@@ -236,7 +236,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
 
 static struct esdhc_platform_data sd1_pdata = {
        .cd_gpio = GPIO_SD1CD,
-       .wp_gpio = -EINVAL,
+       .cd_type = ESDHC_CD_GPIO,
+       .wp_type = ESDHC_WP_NONE,
 };
 
 /*
index 6707de0..6778f81 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/input.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
+#include <sound/tlv320aic32x4.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
@@ -196,6 +197,17 @@ static struct pca953x_platform_data visstrim_m10_pca9555_pdata = {
        .invert = 0,
 };
 
+static struct aic32x4_pdata visstrim_m10_aic32x4_pdata = {
+       .power_cfg = AIC32X4_PWR_MICBIAS_2075_LDOIN |
+                    AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE |
+                    AIC32X4_PWR_AIC32X4_LDO_ENABLE |
+                    AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36 |
+                    AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED,
+       .micpga_routing = AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K |
+                        AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K,
+       .swapdacs = false,
+};
+
 static struct i2c_board_info visstrim_m10_i2c_devices[] = {
        {
                I2C_BOARD_INFO("pca9555", 0x20),
@@ -203,6 +215,7 @@ static struct i2c_board_info visstrim_m10_i2c_devices[] = {
        },
        {
                I2C_BOARD_INFO("tlv320aic32x4", 0x18),
+               .platform_data = &visstrim_m10_aic32x4_pdata,
        }
 };
 
index 01534bb..7f66a91 100644 (file)
@@ -215,6 +215,8 @@ static const struct imxi2c_platform_data mx25_3ds_i2c0_data __initconst = {
 static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {
        .wp_gpio = SD1_GPIO_WP,
        .cd_gpio = SD1_GPIO_CD,
+       .wp_type = ESDHC_WP_GPIO,
+       .cd_type = ESDHC_CD_GPIO,
 };
 
 static void __init mx25pdk_init(void)
index 0ce4947..29ca890 100644 (file)
@@ -468,7 +468,7 @@ static struct i2c_board_info __initdata mx31ads_i2c1_devices[] = {
 #endif
 };
 
-static void mxc_init_i2c(void)
+static void __init mxc_init_i2c(void)
 {
        i2c_register_board_info(1, mx31ads_i2c1_devices,
                                ARRAY_SIZE(mx31ads_i2c1_devices));
@@ -486,7 +486,7 @@ static unsigned int ssi_pins[] = {
        MX31_PIN_STXD5__STXD5,
 };
 
-static void mxc_init_audio(void)
+static void __init mxc_init_audio(void)
 {
        imx31_add_imx_ssi(0, NULL);
        mxc_iomux_setup_multiple_pins(ssi_pins, ARRAY_SIZE(ssi_pins), "ssi");
index 750368d..126913a 100644 (file)
@@ -192,7 +192,7 @@ static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
        .portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
 };
 
-static void lilly1131_usb_init(void)
+static void __init lilly1131_usb_init(void)
 {
        imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
 
index 163cc31..660ec3e 100644 (file)
@@ -349,6 +349,8 @@ __setup("otg_mode=", pcm043_otg_mode);
 static struct esdhc_platform_data sd1_pdata = {
        .wp_gpio = SD1_GPIO_WP,
        .cd_gpio = SD1_GPIO_CD,
+       .wp_type = ESDHC_WP_GPIO,
+       .cd_type = ESDHC_CD_GPIO,
 };
 
 /*
index 8bf0291..cc4d152 100644 (file)
@@ -79,7 +79,6 @@ static struct sdma_script_start_addrs imx25_sdma_script __initdata = {
 };
 
 static struct sdma_platform_data imx25_sdma_pdata __initdata = {
-       .sdma_version = 2,
        .fw_name = "sdma-imx25.bin",
        .script_addrs = &imx25_sdma_script,
 };
@@ -92,5 +91,6 @@ void __init imx25_soc_init(void)
        mxc_register_gpio("imx31-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
        mxc_register_gpio("imx31-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
 
-       imx_add_imx_sdma(MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
+       /* i.mx25 has the i.mx35 type sdma */
+       imx_add_imx_sdma("imx35-sdma", MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
 }
index 61bff38..b7c55e7 100644 (file)
@@ -69,7 +69,6 @@ static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
 };
 
 static struct sdma_platform_data imx31_sdma_pdata __initdata = {
-       .sdma_version = 1,
        .fw_name = "sdma-imx31-to2.bin",
        .script_addrs = &imx31_to2_sdma_script,
 };
@@ -88,5 +87,5 @@ void __init imx31_soc_init(void)
                imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
        }
 
-       imx_add_imx_sdma(MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
+       imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
 }
index 98769ae..f49bac7 100644 (file)
@@ -86,7 +86,6 @@ static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
 };
 
 static struct sdma_platform_data imx35_sdma_pdata __initdata = {
-       .sdma_version = 2,
        .fw_name = "sdma-imx35-to2.bin",
        .script_addrs = &imx35_to2_sdma_script,
 };
@@ -106,5 +105,5 @@ void __init imx35_soc_init(void)
                imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
        }
 
-       imx_add_imx_sdma(MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
+       imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
 }
index 2fdb954..520b6bf 100644 (file)
@@ -95,7 +95,7 @@ static int irq_tab[4] __initdata = {
  * map the specified device/slot/pin to an IRQ.  This works out such
  * that slot 9 pin 1 is INT0, pin 2 is INT1, and slot 10 pin 1 is INT1.
  */
-static int __init integrator_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init integrator_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int intnr = ((slot - 9) + (pin - 1)) & 3;
 
index 9b5a63f..23dfaff 100644 (file)
@@ -30,7 +30,7 @@
 extern int init_atu; /* Flag to select which ATU(s) to initialize / disable */
 
 static int __init
-iq81340mc_pcix_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+iq81340mc_pcix_map_irq(const struct pci_dev *dev, u8 idsel, u8 pin)
 {
        switch (idsel) {
        case 1:
index 0690b1d..251c408 100644 (file)
@@ -388,7 +388,7 @@ static int iop13xx_atue_pci_status(int clear)
 }
 
 static int
-iop13xx_pcie_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+iop13xx_pcie_map_irq(const struct pci_dev *dev, u8 idsel, u8 pin)
 {
        WARN_ON(idsel != 0);
 
index 779f924..6cbffbf 100644 (file)
@@ -81,7 +81,7 @@ void __init em7210_map_io(void)
 #define INTD   IRQ_IOP32X_XINT3
 
 static int __init
-em7210_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+em7210_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static int pci_irq_table[][4] = {
                /*
index c6b6f9c..ceef5d4 100644 (file)
@@ -77,7 +77,7 @@ void __init glantank_map_io(void)
 #define INTD   IRQ_IOP32X_XINT3
 
 static int __init
-glantank_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+glantank_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static int pci_irq_table[][4] = {
                /*
index fde962c..3a62514 100644 (file)
@@ -103,7 +103,7 @@ void __init iq31244_map_io(void)
  * EP80219/IQ31244 PCI.
  */
 static int __init
-ep80219_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+ep80219_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
@@ -139,7 +139,7 @@ static struct hw_pci ep80219_pci __initdata = {
 };
 
 static int __init
-iq31244_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+iq31244_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index 3a95950..35b7e69 100644 (file)
@@ -71,7 +71,7 @@ void __init iq80321_map_io(void)
  * IQ80321 PCI.
  */
 static int __init
-iq80321_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+iq80321_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index 626aa37..1a374ea 100644 (file)
@@ -78,7 +78,7 @@ void __init n2100_map_io(void)
  * N2100 PCI.
  */
 static int __init
-n2100_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index c565f8d..637c027 100644 (file)
@@ -54,7 +54,7 @@ static struct sys_timer iq80331_timer = {
  * IQ80331 PCI.
  */
 static int __init
-iq80331_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+iq80331_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index 36a9efb..90a0436 100644 (file)
@@ -54,7 +54,7 @@ static struct sys_timer iq80332_timer = {
  * IQ80332 PCI.
  */
 static int __init
-iq80332_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+iq80332_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index 88663ab..62c60ad 100644 (file)
@@ -148,7 +148,8 @@ static struct pci_bus * __init enp2611_pci_scan_bus(int nr,
        return pci_scan_bus(sys->busnr, &enp2611_pci_ops, sys);
 }
 
-static int __init enp2611_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init enp2611_pci_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        int irq;
 
index dfffc1e..5bad1a8 100644 (file)
@@ -78,7 +78,8 @@ int ixdp2400_pci_setup(int nr, struct pci_sys_data *sys)
        return 1;
 }
 
-static int __init ixdp2400_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init ixdp2400_pci_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        if (ixdp2x00_master_npu()) {
 
index cd4c9bc..3d3cef8 100644 (file)
@@ -161,7 +161,8 @@ static int __init ixdp2800_pci_setup(int nr, struct pci_sys_data *sys)
        return 1;
 }
 
-static int __init ixdp2800_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init ixdp2800_pci_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        if (ixdp2x00_master_npu()) {
 
index 84835b2..be2a254 100644 (file)
@@ -252,7 +252,8 @@ void __init ixdp2x01_pci_preinit(void)
 
 #define DEVPIN(dev, pin) ((pin) | ((dev) << 3))
 
-static int __init ixdp2x01_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init ixdp2x01_pci_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        u8 bus = dev->bus->number;
        u32 devpin = DEVPIN(PCI_SLOT(dev->devfn), pin);
index 8dcba17..ec028e3 100644 (file)
@@ -168,7 +168,7 @@ void __init ixdp2351_init_irq(void)
  */
 #define DEVPIN(dev, pin) ((pin) | ((dev) << 3))
 
-static int __init ixdp2351_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init ixdp2351_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        u8 bus = dev->bus->number;
        u32 devpin = DEVPIN(PCI_SLOT(dev->devfn), pin);
index 8fe0c62..844551d 100644 (file)
@@ -56,7 +56,8 @@
 #define INTC_PIN       IXP23XX_GPIO_PIN_11
 #define INTD_PIN       IXP23XX_GPIO_PIN_12
 
-static int __init roadrunner_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+static int __init roadrunner_map_irq(const struct pci_dev *dev, u8 idsel,
+       u8 pin)
 {
        static int pci_card_slot_irq[] = {INTB, INTC, INTD, INTA};
        static int pmc_card_slot_irq[] = {INTA, INTB, INTC, INTD};
index 162043f..8fea0a3 100644 (file)
@@ -46,7 +46,7 @@ void __init avila_pci_preinit(void)
        ixp4xx_pci_preinit();
 }
 
-static int __init avila_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init avila_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static int pci_irq_table[IRQ_LINES] = {
                IXP4XX_GPIO_IRQ(INTA),
index 37fda7d..71f5c9c 100644 (file)
@@ -37,7 +37,7 @@ void __init coyote_pci_preinit(void)
        ixp4xx_pci_preinit();
 }
 
-static int __init coyote_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init coyote_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        if (slot == SLOT0_DEVID)
                return IXP4XX_GPIO_IRQ(SLOT0_INTA);
index c761201..0532510 100644 (file)
@@ -44,7 +44,7 @@ void __init dsmg600_pci_preinit(void)
        ixp4xx_pci_preinit();
 }
 
-static int __init dsmg600_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init dsmg600_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static int pci_irq_table[MAX_DEV][IRQ_LINES] = {
                { IXP4XX_GPIO_IRQ(INTE), -1, -1 },
index 44ccde9..d2ac803 100644 (file)
@@ -38,7 +38,7 @@ void __init fsg_pci_preinit(void)
        ixp4xx_pci_preinit();
 }
 
-static int __init fsg_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init fsg_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static int pci_irq_table[IRQ_LINES] = {
                IXP4XX_GPIO_IRQ(INTC),
index fc11241..76581fb 100644 (file)
@@ -35,7 +35,8 @@ void __init gateway7001_pci_preinit(void)
        ixp4xx_pci_preinit();
 }
 
-static int __init gateway7001_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init gateway7001_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        if (slot == 1)
                return IRQ_IXP4XX_GPIO11;
index 5f00ad2..7548d9a 100644 (file)
@@ -462,7 +462,7 @@ static void __init gmlr_pci_postinit(void)
        }
 }
 
-static int __init gmlr_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init gmlr_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        switch(slot) {
        case SLOT_ETHA: return IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHA);
index 38cc072..d68fc06 100644 (file)
@@ -49,7 +49,7 @@ void __init gtwx5715_pci_preinit(void)
 }
 
 
-static int __init gtwx5715_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init gtwx5715_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int rc = -1;
 
index 58f4004..fffd8c5 100644 (file)
@@ -43,7 +43,7 @@ void __init ixdp425_pci_preinit(void)
        ixp4xx_pci_preinit();
 }
 
-static int __init ixdp425_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init ixdp425_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static int pci_irq_table[IRQ_LINES] = {
                IXP4XX_GPIO_IRQ(INTA),
index e64f6d0..34efe75 100644 (file)
@@ -31,7 +31,7 @@ void __init ixdpg425_pci_preinit(void)
        ixp4xx_pci_preinit();
 }
 
-static int __init ixdpg425_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init ixdpg425_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        if (slot == 12 || slot == 13)
                return IRQ_IXP4XX_GPIO7;
index 428d120..5434ccf 100644 (file)
@@ -41,7 +41,7 @@ void __init nas100d_pci_preinit(void)
        ixp4xx_pci_preinit();
 }
 
-static int __init nas100d_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init nas100d_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static int pci_irq_table[MAX_DEV][IRQ_LINES] = {
                { IXP4XX_GPIO_IRQ(INTA), -1, -1 },
index 2e85f76..b571605 100644 (file)
@@ -38,7 +38,7 @@ void __init nslu2_pci_preinit(void)
        ixp4xx_pci_preinit();
 }
 
-static int __init nslu2_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init nslu2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        static int pci_irq_table[IRQ_LINES] = {
                IXP4XX_GPIO_IRQ(INTA),
index 03bdec5..0bc3f34 100644 (file)
@@ -43,7 +43,7 @@ void __init vulcan_pci_preinit(void)
        ixp4xx_pci_preinit();
 }
 
-static int __init vulcan_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init vulcan_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        if (slot == 1)
                return IXP4XX_GPIO_IRQ(INTA);
index 17f3cf5..f27dfcf 100644 (file)
@@ -35,7 +35,7 @@ void __init wg302v2_pci_preinit(void)
        ixp4xx_pci_preinit();
 }
 
-static int __init wg302v2_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init wg302v2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        if (slot == 1)
                return IRQ_IXP4XX_GPIO8;
index bfeb9c9..74b992d 100644 (file)
@@ -245,7 +245,8 @@ kirkwood_pcie_scan_bus(int nr, struct pci_sys_data *sys)
        return bus;
 }
 
-static int __init kirkwood_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init kirkwood_pcie_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        struct pcie_port *pp = bus_to_port(dev->bus);
 
index ada92b6..1338cb3 100644 (file)
@@ -34,7 +34,7 @@
 #include "generic.h"
 
 #ifdef CONFIG_PCI
-static int dsm320_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int dsm320_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        switch (slot) {
        case 0:
index c7ad09b..e2e3cba 100644 (file)
@@ -24,7 +24,7 @@
 #include "generic.h"
 
 #ifdef CONFIG_PCI
-static int micrel_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int micrel_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        return KS8695_IRQ_EXTERN0;
 }
index 2744fec..85a3c9a 100644 (file)
@@ -30,7 +30,7 @@ extern void __init ks8695_init_leds(u8 cpu_led, u8 timer_led);
 
 struct ks8695_pci_cfg {
        short mode;
-       int (*map_irq)(struct pci_dev *, u8, u8);
+       int (*map_irq)(const struct pci_dev *, u8, u8);
 };
 extern __init void ks8695_init_pci(struct ks8695_pci_cfg *);
 
index c070c24..98e25d9 100644 (file)
 #include <mach/gpio.h>
 #include <mach/pxa168.h>
 #include <mach/mfp-pxa168.h>
-#include <mach/mfp-gplugd.h>
 
 #include "common.h"
 
 static unsigned long gplugd_pin_config[] __initdata = {
        /* UART3 */
-       GPIO8_UART3_SOUT,
-       GPIO9_UART3_SIN,
-       GPI1O_UART3_CTS,
-       GPI11_UART3_RTS,
+       GPIO8_UART3_TXD,
+       GPIO9_UART3_RXD,
+       GPIO1O_UART3_CTS,
+       GPIO11_UART3_RTS,
+
+       /* USB OTG PEN */
+       GPIO18_GPIO,
 
        /* MMC2 */
        GPIO28_MMC2_CMD,
@@ -109,6 +111,12 @@ static unsigned long gplugd_pin_config[] __initdata = {
        GPIO105_CI2C_SDA,
        GPIO106_CI2C_SCL,
 
+       /* SPI NOR Flash on SSP2 */
+       GPIO107_SSP2_RXD,
+       GPIO108_SSP2_TXD,
+       GPIO110_GPIO,     /* SPI_CSn */
+       GPIO111_SSP2_CLK,
+
        /* Select JTAG */
        GPIO109_GPIO,
 
@@ -154,7 +162,7 @@ static void __init select_disp_freq(void)
                                "frequency\n");
        } else {
                gpio_direction_output(35, 1);
-               gpio_free(104);
+               gpio_free(35);
        }
 
        if (unlikely(gpio_request(85, "DISP_FREQ_SEL_2"))) {
@@ -162,7 +170,7 @@ static void __init select_disp_freq(void)
                                "frequency\n");
        } else {
                gpio_direction_output(85, 0);
-               gpio_free(104);
+               gpio_free(85);
        }
 }
 
diff --git a/arch/arm/mach-mmp/include/mach/mfp-gplugd.h b/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
deleted file mode 100644 (file)
index b8cf38d..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * linux/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
- *
- *   MFP definitions used in gplugD
- *
- * 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 __MACH_MFP_GPLUGD_H
-#define __MACH_MFP_GPLUGD_H
-
-#include <plat/mfp.h>
-#include <mach/mfp.h>
-
-/* UART3 */
-#define GPIO8_UART3_SOUT       MFP_CFG(GPIO8, AF2)
-#define GPIO9_UART3_SIN        MFP_CFG(GPIO9, AF2)
-#define GPI1O_UART3_CTS        MFP_CFG(GPIO10, AF2)
-#define GPI11_UART3_RTS        MFP_CFG(GPIO11, AF2)
-
-/* MMC2 */
-#define        GPIO28_MMC2_CMD         MFP_CFG_DRV(GPIO28, AF6, FAST)
-#define        GPIO29_MMC2_CLK         MFP_CFG_DRV(GPIO29, AF6, FAST)
-#define        GPIO30_MMC2_DAT0        MFP_CFG_DRV(GPIO30, AF6, FAST)
-#define        GPIO31_MMC2_DAT1        MFP_CFG_DRV(GPIO31, AF6, FAST)
-#define        GPIO32_MMC2_DAT2        MFP_CFG_DRV(GPIO32, AF6, FAST)
-#define        GPIO33_MMC2_DAT3        MFP_CFG_DRV(GPIO33, AF6, FAST)
-
-/* I2S */
-#undef GPIO114_I2S_FRM
-#undef GPIO115_I2S_BCLK
-
-#define GPIO114_I2S_FRM                MFP_CFG_DRV(GPIO114, AF1, FAST)
-#define GPIO115_I2S_BCLK        MFP_CFG_DRV(GPIO115, AF1, FAST)
-#define GPIO116_I2S_TXD         MFP_CFG_DRV(GPIO116, AF1, FAST)
-
-/* MMC4 */
-#define GPIO125_MMC4_DAT3       MFP_CFG_DRV(GPIO125, AF7, FAST)
-#define GPIO126_MMC4_DAT2       MFP_CFG_DRV(GPIO126, AF7, FAST)
-#define GPIO127_MMC4_DAT1       MFP_CFG_DRV(GPIO127, AF7, FAST)
-#define GPIO0_2_MMC4_DAT0       MFP_CFG_DRV(GPIO0_2, AF7, FAST)
-#define GPIO1_2_MMC4_CMD        MFP_CFG_DRV(GPIO1_2, AF7, FAST)
-#define GPIO2_2_MMC4_CLK        MFP_CFG_DRV(GPIO2_2, AF7, FAST)
-
-/* OTG GPIO */
-#define GPIO_USB_OTG_PEN        18
-#define GPIO_USB_OIDIR          20
-
-/* Other GPIOs are 35, 84, 85 */
-#endif /* __MACH_MFP_GPLUGD_H */
index 8c78232..92aaa3c 100644 (file)
 #define GPIO33_CF_nCD2         MFP_CFG(GPIO33, AF3)
 
 /* UART */
+#define GPIO8_UART3_TXD                MFP_CFG(GPIO8, AF2)
+#define GPIO9_UART3_RXD                MFP_CFG(GPIO9, AF2)
+#define GPIO1O_UART3_CTS       MFP_CFG(GPIO10, AF2)
+#define GPIO11_UART3_RTS       MFP_CFG(GPIO11, AF2)
 #define GPIO88_UART2_TXD       MFP_CFG(GPIO88, AF2)
 #define GPIO89_UART2_RXD       MFP_CFG(GPIO89, AF2)
 #define GPIO107_UART1_TXD      MFP_CFG_DRV(GPIO107, AF1, FAST)
 #define GPIO53_MMC1_CD         MFP_CFG(GPIO53, AF1)
 #define GPIO46_MMC1_WP         MFP_CFG(GPIO46, AF1)
 
+/* MMC2 */
+#define        GPIO28_MMC2_CMD         MFP_CFG_DRV(GPIO28, AF6, FAST)
+#define        GPIO29_MMC2_CLK         MFP_CFG_DRV(GPIO29, AF6, FAST)
+#define        GPIO30_MMC2_DAT0        MFP_CFG_DRV(GPIO30, AF6, FAST)
+#define        GPIO31_MMC2_DAT1        MFP_CFG_DRV(GPIO31, AF6, FAST)
+#define        GPIO32_MMC2_DAT2        MFP_CFG_DRV(GPIO32, AF6, FAST)
+#define        GPIO33_MMC2_DAT3        MFP_CFG_DRV(GPIO33, AF6, FAST)
+
+/* MMC4 */
+#define GPIO125_MMC4_DAT3       MFP_CFG_DRV(GPIO125, AF7, FAST)
+#define GPIO126_MMC4_DAT2       MFP_CFG_DRV(GPIO126, AF7, FAST)
+#define GPIO127_MMC4_DAT1       MFP_CFG_DRV(GPIO127, AF7, FAST)
+#define GPIO0_2_MMC4_DAT0       MFP_CFG_DRV(GPIO0_2, AF7, FAST)
+#define GPIO1_2_MMC4_CMD        MFP_CFG_DRV(GPIO1_2, AF7, FAST)
+#define GPIO2_2_MMC4_CLK        MFP_CFG_DRV(GPIO2_2, AF7, FAST)
+
 /* LCD */
 #define GPIO84_LCD_CS          MFP_CFG(GPIO84, AF1)
 #define GPIO60_LCD_DD0         MFP_CFG(GPIO60, AF1)
 #define GPIO106_CI2C_SCL       MFP_CFG(GPIO106, AF1)
 
 /* I2S */
-#define GPIO113_I2S_MCLK       MFP_CFG(GPIO113,AF6)
-#define GPIO114_I2S_FRM                MFP_CFG(GPIO114,AF1)
-#define GPIO115_I2S_BCLK       MFP_CFG(GPIO115,AF1)
-#define GPIO116_I2S_RXD                MFP_CFG(GPIO116,AF2)
-#define GPIO117_I2S_TXD                MFP_CFG(GPIO117,AF2)
+#define GPIO113_I2S_MCLK       MFP_CFG(GPIO113, AF6)
+#define GPIO114_I2S_FRM                MFP_CFG(GPIO114, AF1)
+#define GPIO115_I2S_BCLK       MFP_CFG(GPIO115, AF1)
+#define GPIO116_I2S_RXD                MFP_CFG(GPIO116, AF2)
+#define GPIO116_I2S_TXD         MFP_CFG(GPIO116, AF1)
+#define GPIO117_I2S_TXD                MFP_CFG(GPIO117, AF2)
 
 /* PWM */
 #define GPIO96_PWM3_OUT                MFP_CFG(GPIO96, AF1)
 #define GPIO101_MII_MDIO       MFP_CFG(GPIO101, AF5)
 #define GPIO103_RX_DV          MFP_CFG(GPIO103, AF5)
 
+/* SSP2 */
+#define GPIO107_SSP2_RXD       MFP_CFG(GPIO107, AF4)
+#define GPIO108_SSP2_TXD       MFP_CFG(GPIO108, AF4)
+#define GPIO111_SSP2_CLK       MFP_CFG(GPIO111, AF4)
+#define GPIO112_SSP2_FRM       MFP_CFG(GPIO112, AF4)
+
 #endif /* __ASM_MACH_MFP_PXA168_H */
index 99833b9..4e91ee6 100644 (file)
@@ -51,12 +51,12 @@ static inline uint32_t timer_read(void)
 {
        int delay = 100;
 
-       __raw_writel(1, TIMERS_VIRT_BASE + TMR_CVWR(0));
+       __raw_writel(1, TIMERS_VIRT_BASE + TMR_CVWR(1));
 
        while (delay--)
                cpu_relax();
 
-       return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(0));
+       return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(1));
 }
 
 unsigned long long notrace sched_clock(void)
@@ -75,28 +75,51 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
        struct clock_event_device *c = dev_id;
 
-       /* disable and clear pending interrupt status */
-       __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0));
-       __raw_writel(0x1, TIMERS_VIRT_BASE + TMR_ICR(0));
+       /*
+        * Clear pending interrupt status.
+        */
+       __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0));
+
+       /*
+        * Disable timer 0.
+        */
+       __raw_writel(0x02, TIMERS_VIRT_BASE + TMR_CER);
+
        c->event_handler(c);
+
        return IRQ_HANDLED;
 }
 
 static int timer_set_next_event(unsigned long delta,
                                struct clock_event_device *dev)
 {
-       unsigned long flags, next;
+       unsigned long flags;
 
        local_irq_save(flags);
 
-       /* clear pending interrupt status and enable */
+       /*
+        * Disable timer 0.
+        */
+       __raw_writel(0x02, TIMERS_VIRT_BASE + TMR_CER);
+
+       /*
+        * Clear and enable timer match 0 interrupt.
+        */
        __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0));
        __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_IER(0));
 
-       next = timer_read() + delta;
-       __raw_writel(next, TIMERS_VIRT_BASE + TMR_TN_MM(0, 0));
+       /*
+        * Setup new clockevent timer value.
+        */
+       __raw_writel(delta - 1, TIMERS_VIRT_BASE + TMR_TN_MM(0, 0));
+
+       /*
+        * Enable timer 0.
+        */
+       __raw_writel(0x03, TIMERS_VIRT_BASE + TMR_CER);
 
        local_irq_restore(flags);
+
        return 0;
 }
 
@@ -145,23 +168,26 @@ static struct clocksource cksrc = {
 static void __init timer_config(void)
 {
        uint32_t ccr = __raw_readl(TIMERS_VIRT_BASE + TMR_CCR);
-       uint32_t cer = __raw_readl(TIMERS_VIRT_BASE + TMR_CER);
-       uint32_t cmr = __raw_readl(TIMERS_VIRT_BASE + TMR_CMR);
 
-       __raw_writel(cer & ~0x1, TIMERS_VIRT_BASE + TMR_CER); /* disable */
+       __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_CER); /* disable */
 
-       ccr &= (cpu_is_mmp2()) ? TMR_CCR_CS_0(0) : TMR_CCR_CS_0(3);
+       ccr &= (cpu_is_mmp2()) ? (TMR_CCR_CS_0(0) | TMR_CCR_CS_1(0)) :
+               (TMR_CCR_CS_0(3) | TMR_CCR_CS_1(3));
        __raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR);
 
-       /* free-running mode */
-       __raw_writel(cmr | 0x01, TIMERS_VIRT_BASE + TMR_CMR);
+       /* set timer 0 to periodic mode, and timer 1 to free-running mode */
+       __raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CMR);
 
-       __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(0)); /* free-running */
+       __raw_writel(0x1, TIMERS_VIRT_BASE + TMR_PLCR(0)); /* periodic */
        __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(0));  /* clear status */
        __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0));
 
-       /* enable timer counter */
-       __raw_writel(cer | 0x01, TIMERS_VIRT_BASE + TMR_CER);
+       __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(1)); /* free-running */
+       __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(1));  /* clear status */
+       __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(1));
+
+       /* enable timer 1 counter */
+       __raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CER);
 }
 
 static struct irqaction timer_irq = {
index 888e925..ebde97f 100644 (file)
@@ -11,6 +11,7 @@ config ARCH_MSM7X00A
        select MSM_SMD
        select MSM_SMD_PKG3
        select CPU_V6
+       select GPIO_MSM_V1
        select MSM_PROC_COMM
        select HAS_MSM_DEBUG_UART_PHYS
 
@@ -22,6 +23,7 @@ config ARCH_MSM7X30
        select MSM_VIC
        select CPU_V7
        select MSM_GPIOMUX
+       select GPIO_MSM_V1
        select MSM_PROC_COMM
        select HAS_MSM_DEBUG_UART_PHYS
 
@@ -33,6 +35,7 @@ config ARCH_QSD8X50
        select MSM_VIC
        select CPU_V7
        select MSM_GPIOMUX
+       select GPIO_MSM_V1
        select MSM_PROC_COMM
        select HAS_MSM_DEBUG_UART_PHYS
 
@@ -44,6 +47,7 @@ config ARCH_MSM8X60
        select ARM_GIC
        select CPU_V7
        select MSM_V2_TLMM
+       select GPIO_MSM_V2
        select MSM_GPIOMUX
        select MSM_SCM if SMP
 
index b70658c..4285dfd 100644 (file)
@@ -29,11 +29,3 @@ obj-$(CONFIG_ARCH_MSM8960) += board-msm8960.o devices-msm8960.o
 obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o
-ifdef CONFIG_MSM_V2_TLMM
-ifndef CONFIG_ARCH_MSM8960
-# TODO: TLMM Mapping issues need to be resolved
-obj-y  += gpio-v2.o
-endif
-else
-obj-y  += gpio.o
-endif
diff --git a/arch/arm/mach-msm/gpio.c b/arch/arm/mach-msm/gpio.c
deleted file mode 100644 (file)
index 5ea273b..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/* linux/arch/arm/mach-msm/gpio.c
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#include <linux/bitops.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include "gpio_hw.h"
-#include "gpiomux.h"
-
-#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
-
-#define MSM_GPIO_BANK(bank, first, last)                               \
-       {                                                               \
-               .regs = {                                               \
-                       .out =         MSM_GPIO_OUT_##bank,             \
-                       .in =          MSM_GPIO_IN_##bank,              \
-                       .int_status =  MSM_GPIO_INT_STATUS_##bank,      \
-                       .int_clear =   MSM_GPIO_INT_CLEAR_##bank,       \
-                       .int_en =      MSM_GPIO_INT_EN_##bank,          \
-                       .int_edge =    MSM_GPIO_INT_EDGE_##bank,        \
-                       .int_pos =     MSM_GPIO_INT_POS_##bank,         \
-                       .oe =          MSM_GPIO_OE_##bank,              \
-               },                                                      \
-               .chip = {                                               \
-                       .base = (first),                                \
-                       .ngpio = (last) - (first) + 1,                  \
-                       .get = msm_gpio_get,                            \
-                       .set = msm_gpio_set,                            \
-                       .direction_input = msm_gpio_direction_input,    \
-                       .direction_output = msm_gpio_direction_output,  \
-                       .to_irq = msm_gpio_to_irq,                      \
-                       .request = msm_gpio_request,                    \
-                       .free = msm_gpio_free,                          \
-               }                                                       \
-       }
-
-#define MSM_GPIO_BROKEN_INT_CLEAR 1
-
-struct msm_gpio_regs {
-       void __iomem *out;
-       void __iomem *in;
-       void __iomem *int_status;
-       void __iomem *int_clear;
-       void __iomem *int_en;
-       void __iomem *int_edge;
-       void __iomem *int_pos;
-       void __iomem *oe;
-};
-
-struct msm_gpio_chip {
-       spinlock_t              lock;
-       struct gpio_chip        chip;
-       struct msm_gpio_regs    regs;
-#if MSM_GPIO_BROKEN_INT_CLEAR
-       unsigned                int_status_copy;
-#endif
-       unsigned int            both_edge_detect;
-       unsigned int            int_enable[2]; /* 0: awake, 1: sleep */
-};
-
-static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
-                         unsigned offset, unsigned on)
-{
-       unsigned mask = BIT(offset);
-       unsigned val;
-
-       val = readl(msm_chip->regs.out);
-       if (on)
-               writel(val | mask, msm_chip->regs.out);
-       else
-               writel(val & ~mask, msm_chip->regs.out);
-       return 0;
-}
-
-static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
-{
-       int loop_limit = 100;
-       unsigned pol, val, val2, intstat;
-       do {
-               val = readl(msm_chip->regs.in);
-               pol = readl(msm_chip->regs.int_pos);
-               pol = (pol & ~msm_chip->both_edge_detect) |
-                     (~val & msm_chip->both_edge_detect);
-               writel(pol, msm_chip->regs.int_pos);
-               intstat = readl(msm_chip->regs.int_status);
-               val2 = readl(msm_chip->regs.in);
-               if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
-                       return;
-       } while (loop_limit-- > 0);
-       printk(KERN_ERR "msm_gpio_update_both_edge_detect, "
-              "failed to reach stable state %x != %x\n", val, val2);
-}
-
-static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip,
-                                       unsigned offset)
-{
-       unsigned bit = BIT(offset);
-
-#if MSM_GPIO_BROKEN_INT_CLEAR
-       /* Save interrupts that already triggered before we loose them. */
-       /* Any interrupt that triggers between the read of int_status */
-       /* and the write to int_clear will still be lost though. */
-       msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
-       msm_chip->int_status_copy &= ~bit;
-#endif
-       writel(bit, msm_chip->regs.int_clear);
-       msm_gpio_update_both_edge_detect(msm_chip);
-       return 0;
-}
-
-static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct msm_gpio_chip *msm_chip;
-       unsigned long irq_flags;
-
-       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-       return 0;
-}
-
-static int
-msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct msm_gpio_chip *msm_chip;
-       unsigned long irq_flags;
-
-       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       msm_gpio_write(msm_chip, offset, value);
-       writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-       return 0;
-}
-
-static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct msm_gpio_chip *msm_chip;
-
-       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-       return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0;
-}
-
-static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct msm_gpio_chip *msm_chip;
-       unsigned long irq_flags;
-
-       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       msm_gpio_write(msm_chip, offset, value);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-}
-
-static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       return MSM_GPIO_TO_INT(chip->base + offset);
-}
-
-#ifdef CONFIG_MSM_GPIOMUX
-static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-       return msm_gpiomux_get(chip->base + offset);
-}
-
-static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-       msm_gpiomux_put(chip->base + offset);
-}
-#else
-#define msm_gpio_request NULL
-#define msm_gpio_free NULL
-#endif
-
-struct msm_gpio_chip msm_gpio_chips[] = {
-#if defined(CONFIG_ARCH_MSM7X00A)
-       MSM_GPIO_BANK(0,   0,  15),
-       MSM_GPIO_BANK(1,  16,  42),
-       MSM_GPIO_BANK(2,  43,  67),
-       MSM_GPIO_BANK(3,  68,  94),
-       MSM_GPIO_BANK(4,  95, 106),
-       MSM_GPIO_BANK(5, 107, 121),
-#elif defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X27)
-       MSM_GPIO_BANK(0,   0,  15),
-       MSM_GPIO_BANK(1,  16,  42),
-       MSM_GPIO_BANK(2,  43,  67),
-       MSM_GPIO_BANK(3,  68,  94),
-       MSM_GPIO_BANK(4,  95, 106),
-       MSM_GPIO_BANK(5, 107, 132),
-#elif defined(CONFIG_ARCH_MSM7X30)
-       MSM_GPIO_BANK(0,   0,  15),
-       MSM_GPIO_BANK(1,  16,  43),
-       MSM_GPIO_BANK(2,  44,  67),
-       MSM_GPIO_BANK(3,  68,  94),
-       MSM_GPIO_BANK(4,  95, 106),
-       MSM_GPIO_BANK(5, 107, 133),
-       MSM_GPIO_BANK(6, 134, 150),
-       MSM_GPIO_BANK(7, 151, 181),
-#elif defined(CONFIG_ARCH_QSD8X50)
-       MSM_GPIO_BANK(0,   0,  15),
-       MSM_GPIO_BANK(1,  16,  42),
-       MSM_GPIO_BANK(2,  43,  67),
-       MSM_GPIO_BANK(3,  68,  94),
-       MSM_GPIO_BANK(4,  95, 103),
-       MSM_GPIO_BANK(5, 104, 121),
-       MSM_GPIO_BANK(6, 122, 152),
-       MSM_GPIO_BANK(7, 153, 164),
-#endif
-};
-
-static void msm_gpio_irq_ack(struct irq_data *d)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       msm_gpio_clear_detect_status(msm_chip,
-                                    d->irq - gpio_to_irq(msm_chip->chip.base));
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-}
-
-static void msm_gpio_irq_mask(struct irq_data *d)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
-
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       /* level triggered interrupts are also latched */
-       if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
-               msm_gpio_clear_detect_status(msm_chip, offset);
-       msm_chip->int_enable[0] &= ~BIT(offset);
-       writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-}
-
-static void msm_gpio_irq_unmask(struct irq_data *d)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
-
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       /* level triggered interrupts are also latched */
-       if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
-               msm_gpio_clear_detect_status(msm_chip, offset);
-       msm_chip->int_enable[0] |= BIT(offset);
-       writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-}
-
-static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
-
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-
-       if (on)
-               msm_chip->int_enable[1] |= BIT(offset);
-       else
-               msm_chip->int_enable[1] &= ~BIT(offset);
-
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-       return 0;
-}
-
-static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
-       unsigned val, mask = BIT(offset);
-
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       val = readl(msm_chip->regs.int_edge);
-       if (flow_type & IRQ_TYPE_EDGE_BOTH) {
-               writel(val | mask, msm_chip->regs.int_edge);
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
-       } else {
-               writel(val & ~mask, msm_chip->regs.int_edge);
-               __irq_set_handler_locked(d->irq, handle_level_irq);
-       }
-       if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
-               msm_chip->both_edge_detect |= mask;
-               msm_gpio_update_both_edge_detect(msm_chip);
-       } else {
-               msm_chip->both_edge_detect &= ~mask;
-               val = readl(msm_chip->regs.int_pos);
-               if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
-                       writel(val | mask, msm_chip->regs.int_pos);
-               else
-                       writel(val & ~mask, msm_chip->regs.int_pos);
-       }
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-       return 0;
-}
-
-static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-       int i, j, mask;
-       unsigned val;
-
-       for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
-               struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
-               val = readl(msm_chip->regs.int_status);
-               val &= msm_chip->int_enable[0];
-               while (val) {
-                       mask = val & -val;
-                       j = fls(mask) - 1;
-                       /* printk("%s %08x %08x bit %d gpio %d irq %d\n",
-                               __func__, v, m, j, msm_chip->chip.start + j,
-                               FIRST_GPIO_IRQ + msm_chip->chip.start + j); */
-                       val &= ~mask;
-                       generic_handle_irq(FIRST_GPIO_IRQ +
-                                          msm_chip->chip.base + j);
-               }
-       }
-       desc->irq_data.chip->irq_ack(&desc->irq_data);
-}
-
-static struct irq_chip msm_gpio_irq_chip = {
-       .name          = "msmgpio",
-       .irq_ack       = msm_gpio_irq_ack,
-       .irq_mask      = msm_gpio_irq_mask,
-       .irq_unmask    = msm_gpio_irq_unmask,
-       .irq_set_wake  = msm_gpio_irq_set_wake,
-       .irq_set_type  = msm_gpio_irq_set_type,
-};
-
-static int __init msm_init_gpio(void)
-{
-       int i, j = 0;
-
-       for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
-               if (i - FIRST_GPIO_IRQ >=
-                       msm_gpio_chips[j].chip.base +
-                       msm_gpio_chips[j].chip.ngpio)
-                       j++;
-               irq_set_chip_data(i, &msm_gpio_chips[j]);
-               irq_set_chip_and_handler(i, &msm_gpio_irq_chip,
-                                        handle_edge_irq);
-               set_irq_flags(i, IRQF_VALID);
-       }
-
-       for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
-               spin_lock_init(&msm_gpio_chips[i].lock);
-               writel(0, msm_gpio_chips[i].regs.int_en);
-               gpiochip_add(&msm_gpio_chips[i].chip);
-       }
-
-       irq_set_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
-       irq_set_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
-       irq_set_irq_wake(INT_GPIO_GROUP1, 1);
-       irq_set_irq_wake(INT_GPIO_GROUP2, 2);
-       return 0;
-}
-
-postcore_initcall(msm_init_gpio);
diff --git a/arch/arm/mach-msm/gpio_hw.h b/arch/arm/mach-msm/gpio_hw.h
deleted file mode 100644 (file)
index 6b50660..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-/* arch/arm/mach-msm/gpio_hw.h
- *
- * Copyright (C) 2007 Google, Inc.
- * Author: Brian Swetland <swetland@google.com>
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#ifndef __ARCH_ARM_MACH_MSM_GPIO_HW_H
-#define __ARCH_ARM_MACH_MSM_GPIO_HW_H
-
-#include <mach/msm_iomap.h>
-
-/* see 80-VA736-2 Rev C pp 695-751
-**
-** These are actually the *shadow* gpio registers, since the
-** real ones (which allow full access) are only available to the
-** ARM9 side of the world.
-**
-** Since the _BASE need to be page-aligned when we're mapping them
-** to virtual addresses, adjust for the additional offset in these
-** macros.
-*/
-
-#if defined(CONFIG_ARCH_MSM7X30)
-#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + (off))
-#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off))
-#else
-#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + 0x800 + (off))
-#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off))
-#endif
-
-#if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_MSM7X25) ||\
-    defined(CONFIG_ARCH_MSM7X27)
-
-/* output value */
-#define MSM_GPIO_OUT_0         MSM_GPIO1_REG(0x00)  /* gpio  15-0  */
-#define MSM_GPIO_OUT_1         MSM_GPIO2_REG(0x00)  /* gpio  42-16 */
-#define MSM_GPIO_OUT_2         MSM_GPIO1_REG(0x04)  /* gpio  67-43 */
-#define MSM_GPIO_OUT_3         MSM_GPIO1_REG(0x08)  /* gpio  94-68 */
-#define MSM_GPIO_OUT_4         MSM_GPIO1_REG(0x0C)  /* gpio 106-95 */
-#define MSM_GPIO_OUT_5         MSM_GPIO1_REG(0x50)  /* gpio 107-121 */
-
-/* same pin map as above, output enable */
-#define MSM_GPIO_OE_0          MSM_GPIO1_REG(0x10)
-#define MSM_GPIO_OE_1          MSM_GPIO2_REG(0x08)
-#define MSM_GPIO_OE_2          MSM_GPIO1_REG(0x14)
-#define MSM_GPIO_OE_3          MSM_GPIO1_REG(0x18)
-#define MSM_GPIO_OE_4          MSM_GPIO1_REG(0x1C)
-#define MSM_GPIO_OE_5          MSM_GPIO1_REG(0x54)
-
-/* same pin map as above, input read */
-#define MSM_GPIO_IN_0          MSM_GPIO1_REG(0x34)
-#define MSM_GPIO_IN_1          MSM_GPIO2_REG(0x20)
-#define MSM_GPIO_IN_2          MSM_GPIO1_REG(0x38)
-#define MSM_GPIO_IN_3          MSM_GPIO1_REG(0x3C)
-#define MSM_GPIO_IN_4          MSM_GPIO1_REG(0x40)
-#define MSM_GPIO_IN_5          MSM_GPIO1_REG(0x44)
-
-/* same pin map as above, 1=edge 0=level interrup */
-#define MSM_GPIO_INT_EDGE_0    MSM_GPIO1_REG(0x60)
-#define MSM_GPIO_INT_EDGE_1    MSM_GPIO2_REG(0x50)
-#define MSM_GPIO_INT_EDGE_2    MSM_GPIO1_REG(0x64)
-#define MSM_GPIO_INT_EDGE_3    MSM_GPIO1_REG(0x68)
-#define MSM_GPIO_INT_EDGE_4    MSM_GPIO1_REG(0x6C)
-#define MSM_GPIO_INT_EDGE_5    MSM_GPIO1_REG(0xC0)
-
-/* same pin map as above, 1=positive 0=negative */
-#define MSM_GPIO_INT_POS_0     MSM_GPIO1_REG(0x70)
-#define MSM_GPIO_INT_POS_1     MSM_GPIO2_REG(0x58)
-#define MSM_GPIO_INT_POS_2     MSM_GPIO1_REG(0x74)
-#define MSM_GPIO_INT_POS_3     MSM_GPIO1_REG(0x78)
-#define MSM_GPIO_INT_POS_4     MSM_GPIO1_REG(0x7C)
-#define MSM_GPIO_INT_POS_5     MSM_GPIO1_REG(0xBC)
-
-/* same pin map as above, interrupt enable */
-#define MSM_GPIO_INT_EN_0      MSM_GPIO1_REG(0x80)
-#define MSM_GPIO_INT_EN_1      MSM_GPIO2_REG(0x60)
-#define MSM_GPIO_INT_EN_2      MSM_GPIO1_REG(0x84)
-#define MSM_GPIO_INT_EN_3      MSM_GPIO1_REG(0x88)
-#define MSM_GPIO_INT_EN_4      MSM_GPIO1_REG(0x8C)
-#define MSM_GPIO_INT_EN_5      MSM_GPIO1_REG(0xB8)
-
-/* same pin map as above, write 1 to clear interrupt */
-#define MSM_GPIO_INT_CLEAR_0   MSM_GPIO1_REG(0x90)
-#define MSM_GPIO_INT_CLEAR_1   MSM_GPIO2_REG(0x68)
-#define MSM_GPIO_INT_CLEAR_2   MSM_GPIO1_REG(0x94)
-#define MSM_GPIO_INT_CLEAR_3   MSM_GPIO1_REG(0x98)
-#define MSM_GPIO_INT_CLEAR_4   MSM_GPIO1_REG(0x9C)
-#define MSM_GPIO_INT_CLEAR_5   MSM_GPIO1_REG(0xB4)
-
-/* same pin map as above, 1=interrupt pending */
-#define MSM_GPIO_INT_STATUS_0  MSM_GPIO1_REG(0xA0)
-#define MSM_GPIO_INT_STATUS_1  MSM_GPIO2_REG(0x70)
-#define MSM_GPIO_INT_STATUS_2  MSM_GPIO1_REG(0xA4)
-#define MSM_GPIO_INT_STATUS_3  MSM_GPIO1_REG(0xA8)
-#define MSM_GPIO_INT_STATUS_4  MSM_GPIO1_REG(0xAC)
-#define MSM_GPIO_INT_STATUS_5  MSM_GPIO1_REG(0xB0)
-
-#endif
-
-#if defined(CONFIG_ARCH_QSD8X50)
-/* output value */
-#define MSM_GPIO_OUT_0         MSM_GPIO1_REG(0x00)  /* gpio  15-0   */
-#define MSM_GPIO_OUT_1         MSM_GPIO2_REG(0x00)  /* gpio  42-16  */
-#define MSM_GPIO_OUT_2         MSM_GPIO1_REG(0x04)  /* gpio  67-43  */
-#define MSM_GPIO_OUT_3         MSM_GPIO1_REG(0x08)  /* gpio  94-68  */
-#define MSM_GPIO_OUT_4         MSM_GPIO1_REG(0x0C)  /* gpio 103-95  */
-#define MSM_GPIO_OUT_5         MSM_GPIO1_REG(0x10)  /* gpio 121-104 */
-#define MSM_GPIO_OUT_6         MSM_GPIO1_REG(0x14)  /* gpio 152-122 */
-#define MSM_GPIO_OUT_7         MSM_GPIO1_REG(0x18)  /* gpio 164-153 */
-
-/* same pin map as above, output enable */
-#define MSM_GPIO_OE_0          MSM_GPIO1_REG(0x20)
-#define MSM_GPIO_OE_1          MSM_GPIO2_REG(0x08)
-#define MSM_GPIO_OE_2          MSM_GPIO1_REG(0x24)
-#define MSM_GPIO_OE_3          MSM_GPIO1_REG(0x28)
-#define MSM_GPIO_OE_4          MSM_GPIO1_REG(0x2C)
-#define MSM_GPIO_OE_5          MSM_GPIO1_REG(0x30)
-#define MSM_GPIO_OE_6          MSM_GPIO1_REG(0x34)
-#define MSM_GPIO_OE_7          MSM_GPIO1_REG(0x38)
-
-/* same pin map as above, input read */
-#define MSM_GPIO_IN_0          MSM_GPIO1_REG(0x50)
-#define MSM_GPIO_IN_1          MSM_GPIO2_REG(0x20)
-#define MSM_GPIO_IN_2          MSM_GPIO1_REG(0x54)
-#define MSM_GPIO_IN_3          MSM_GPIO1_REG(0x58)
-#define MSM_GPIO_IN_4          MSM_GPIO1_REG(0x5C)
-#define MSM_GPIO_IN_5          MSM_GPIO1_REG(0x60)
-#define MSM_GPIO_IN_6          MSM_GPIO1_REG(0x64)
-#define MSM_GPIO_IN_7          MSM_GPIO1_REG(0x68)
-
-/* same pin map as above, 1=edge 0=level interrup */
-#define MSM_GPIO_INT_EDGE_0    MSM_GPIO1_REG(0x70)
-#define MSM_GPIO_INT_EDGE_1    MSM_GPIO2_REG(0x50)
-#define MSM_GPIO_INT_EDGE_2    MSM_GPIO1_REG(0x74)
-#define MSM_GPIO_INT_EDGE_3    MSM_GPIO1_REG(0x78)
-#define MSM_GPIO_INT_EDGE_4    MSM_GPIO1_REG(0x7C)
-#define MSM_GPIO_INT_EDGE_5    MSM_GPIO1_REG(0x80)
-#define MSM_GPIO_INT_EDGE_6    MSM_GPIO1_REG(0x84)
-#define MSM_GPIO_INT_EDGE_7    MSM_GPIO1_REG(0x88)
-
-/* same pin map as above, 1=positive 0=negative */
-#define MSM_GPIO_INT_POS_0     MSM_GPIO1_REG(0x90)
-#define MSM_GPIO_INT_POS_1     MSM_GPIO2_REG(0x58)
-#define MSM_GPIO_INT_POS_2     MSM_GPIO1_REG(0x94)
-#define MSM_GPIO_INT_POS_3     MSM_GPIO1_REG(0x98)
-#define MSM_GPIO_INT_POS_4     MSM_GPIO1_REG(0x9C)
-#define MSM_GPIO_INT_POS_5     MSM_GPIO1_REG(0xA0)
-#define MSM_GPIO_INT_POS_6     MSM_GPIO1_REG(0xA4)
-#define MSM_GPIO_INT_POS_7     MSM_GPIO1_REG(0xA8)
-
-/* same pin map as above, interrupt enable */
-#define MSM_GPIO_INT_EN_0      MSM_GPIO1_REG(0xB0)
-#define MSM_GPIO_INT_EN_1      MSM_GPIO2_REG(0x60)
-#define MSM_GPIO_INT_EN_2      MSM_GPIO1_REG(0xB4)
-#define MSM_GPIO_INT_EN_3      MSM_GPIO1_REG(0xB8)
-#define MSM_GPIO_INT_EN_4      MSM_GPIO1_REG(0xBC)
-#define MSM_GPIO_INT_EN_5      MSM_GPIO1_REG(0xC0)
-#define MSM_GPIO_INT_EN_6      MSM_GPIO1_REG(0xC4)
-#define MSM_GPIO_INT_EN_7      MSM_GPIO1_REG(0xC8)
-
-/* same pin map as above, write 1 to clear interrupt */
-#define MSM_GPIO_INT_CLEAR_0   MSM_GPIO1_REG(0xD0)
-#define MSM_GPIO_INT_CLEAR_1   MSM_GPIO2_REG(0x68)
-#define MSM_GPIO_INT_CLEAR_2   MSM_GPIO1_REG(0xD4)
-#define MSM_GPIO_INT_CLEAR_3   MSM_GPIO1_REG(0xD8)
-#define MSM_GPIO_INT_CLEAR_4   MSM_GPIO1_REG(0xDC)
-#define MSM_GPIO_INT_CLEAR_5   MSM_GPIO1_REG(0xE0)
-#define MSM_GPIO_INT_CLEAR_6   MSM_GPIO1_REG(0xE4)
-#define MSM_GPIO_INT_CLEAR_7   MSM_GPIO1_REG(0xE8)
-
-/* same pin map as above, 1=interrupt pending */
-#define MSM_GPIO_INT_STATUS_0  MSM_GPIO1_REG(0xF0)
-#define MSM_GPIO_INT_STATUS_1  MSM_GPIO2_REG(0x70)
-#define MSM_GPIO_INT_STATUS_2  MSM_GPIO1_REG(0xF4)
-#define MSM_GPIO_INT_STATUS_3  MSM_GPIO1_REG(0xF8)
-#define MSM_GPIO_INT_STATUS_4  MSM_GPIO1_REG(0xFC)
-#define MSM_GPIO_INT_STATUS_5  MSM_GPIO1_REG(0x100)
-#define MSM_GPIO_INT_STATUS_6  MSM_GPIO1_REG(0x104)
-#define MSM_GPIO_INT_STATUS_7  MSM_GPIO1_REG(0x108)
-
-#endif
-
-#if defined(CONFIG_ARCH_MSM7X30)
-
-/* output value */
-#define MSM_GPIO_OUT_0         MSM_GPIO1_REG(0x00)   /* gpio  15-0   */
-#define MSM_GPIO_OUT_1         MSM_GPIO2_REG(0x00)   /* gpio  43-16  */
-#define MSM_GPIO_OUT_2         MSM_GPIO1_REG(0x04)   /* gpio  67-44  */
-#define MSM_GPIO_OUT_3         MSM_GPIO1_REG(0x08)   /* gpio  94-68  */
-#define MSM_GPIO_OUT_4         MSM_GPIO1_REG(0x0C)   /* gpio 106-95  */
-#define MSM_GPIO_OUT_5         MSM_GPIO1_REG(0x50)   /* gpio 133-107 */
-#define MSM_GPIO_OUT_6         MSM_GPIO1_REG(0xC4)   /* gpio 150-134 */
-#define MSM_GPIO_OUT_7         MSM_GPIO1_REG(0x214)  /* gpio 181-151 */
-
-/* same pin map as above, output enable */
-#define MSM_GPIO_OE_0          MSM_GPIO1_REG(0x10)
-#define MSM_GPIO_OE_1          MSM_GPIO2_REG(0x08)
-#define MSM_GPIO_OE_2          MSM_GPIO1_REG(0x14)
-#define MSM_GPIO_OE_3          MSM_GPIO1_REG(0x18)
-#define MSM_GPIO_OE_4          MSM_GPIO1_REG(0x1C)
-#define MSM_GPIO_OE_5          MSM_GPIO1_REG(0x54)
-#define MSM_GPIO_OE_6          MSM_GPIO1_REG(0xC8)
-#define MSM_GPIO_OE_7          MSM_GPIO1_REG(0x218)
-
-/* same pin map as above, input read */
-#define MSM_GPIO_IN_0          MSM_GPIO1_REG(0x34)
-#define MSM_GPIO_IN_1          MSM_GPIO2_REG(0x20)
-#define MSM_GPIO_IN_2          MSM_GPIO1_REG(0x38)
-#define MSM_GPIO_IN_3          MSM_GPIO1_REG(0x3C)
-#define MSM_GPIO_IN_4          MSM_GPIO1_REG(0x40)
-#define MSM_GPIO_IN_5          MSM_GPIO1_REG(0x44)
-#define MSM_GPIO_IN_6          MSM_GPIO1_REG(0xCC)
-#define MSM_GPIO_IN_7          MSM_GPIO1_REG(0x21C)
-
-/* same pin map as above, 1=edge 0=level interrup */
-#define MSM_GPIO_INT_EDGE_0    MSM_GPIO1_REG(0x60)
-#define MSM_GPIO_INT_EDGE_1    MSM_GPIO2_REG(0x50)
-#define MSM_GPIO_INT_EDGE_2    MSM_GPIO1_REG(0x64)
-#define MSM_GPIO_INT_EDGE_3    MSM_GPIO1_REG(0x68)
-#define MSM_GPIO_INT_EDGE_4    MSM_GPIO1_REG(0x6C)
-#define MSM_GPIO_INT_EDGE_5    MSM_GPIO1_REG(0xC0)
-#define MSM_GPIO_INT_EDGE_6    MSM_GPIO1_REG(0xD0)
-#define MSM_GPIO_INT_EDGE_7    MSM_GPIO1_REG(0x240)
-
-/* same pin map as above, 1=positive 0=negative */
-#define MSM_GPIO_INT_POS_0     MSM_GPIO1_REG(0x70)
-#define MSM_GPIO_INT_POS_1     MSM_GPIO2_REG(0x58)
-#define MSM_GPIO_INT_POS_2     MSM_GPIO1_REG(0x74)
-#define MSM_GPIO_INT_POS_3     MSM_GPIO1_REG(0x78)
-#define MSM_GPIO_INT_POS_4     MSM_GPIO1_REG(0x7C)
-#define MSM_GPIO_INT_POS_5     MSM_GPIO1_REG(0xBC)
-#define MSM_GPIO_INT_POS_6     MSM_GPIO1_REG(0xD4)
-#define MSM_GPIO_INT_POS_7     MSM_GPIO1_REG(0x228)
-
-/* same pin map as above, interrupt enable */
-#define MSM_GPIO_INT_EN_0      MSM_GPIO1_REG(0x80)
-#define MSM_GPIO_INT_EN_1      MSM_GPIO2_REG(0x60)
-#define MSM_GPIO_INT_EN_2      MSM_GPIO1_REG(0x84)
-#define MSM_GPIO_INT_EN_3      MSM_GPIO1_REG(0x88)
-#define MSM_GPIO_INT_EN_4      MSM_GPIO1_REG(0x8C)
-#define MSM_GPIO_INT_EN_5      MSM_GPIO1_REG(0xB8)
-#define MSM_GPIO_INT_EN_6      MSM_GPIO1_REG(0xD8)
-#define MSM_GPIO_INT_EN_7      MSM_GPIO1_REG(0x22C)
-
-/* same pin map as above, write 1 to clear interrupt */
-#define MSM_GPIO_INT_CLEAR_0   MSM_GPIO1_REG(0x90)
-#define MSM_GPIO_INT_CLEAR_1   MSM_GPIO2_REG(0x68)
-#define MSM_GPIO_INT_CLEAR_2   MSM_GPIO1_REG(0x94)
-#define MSM_GPIO_INT_CLEAR_3   MSM_GPIO1_REG(0x98)
-#define MSM_GPIO_INT_CLEAR_4   MSM_GPIO1_REG(0x9C)
-#define MSM_GPIO_INT_CLEAR_5   MSM_GPIO1_REG(0xB4)
-#define MSM_GPIO_INT_CLEAR_6   MSM_GPIO1_REG(0xDC)
-#define MSM_GPIO_INT_CLEAR_7   MSM_GPIO1_REG(0x230)
-
-/* same pin map as above, 1=interrupt pending */
-#define MSM_GPIO_INT_STATUS_0  MSM_GPIO1_REG(0xA0)
-#define MSM_GPIO_INT_STATUS_1  MSM_GPIO2_REG(0x70)
-#define MSM_GPIO_INT_STATUS_2  MSM_GPIO1_REG(0xA4)
-#define MSM_GPIO_INT_STATUS_3  MSM_GPIO1_REG(0xA8)
-#define MSM_GPIO_INT_STATUS_4  MSM_GPIO1_REG(0xAC)
-#define MSM_GPIO_INT_STATUS_5  MSM_GPIO1_REG(0xB0)
-#define MSM_GPIO_INT_STATUS_6  MSM_GPIO1_REG(0xE0)
-#define MSM_GPIO_INT_STATUS_7  MSM_GPIO1_REG(0x234)
-
-#endif
-
-#endif
index b178d9c..00459f6 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/bitops.h>
 #include <linux/errno.h>
+#include <mach/msm_gpiomux.h>
 
 #if defined(CONFIG_MSM_V2_TLMM)
 #include "gpiomux-v2.h"
@@ -71,12 +72,6 @@ enum {
  */
 extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS];
 
-/* Increment a gpio's reference count, possibly activating the line. */
-int __must_check msm_gpiomux_get(unsigned gpio);
-
-/* Decrement a gpio's reference count, possibly suspending the line. */
-int msm_gpiomux_put(unsigned gpio);
-
 /* Install a new configuration to the gpio line.  To avoid overwriting
  * a configuration, leave the VALID bit out.
  */
@@ -94,16 +89,6 @@ int msm_gpiomux_write(unsigned gpio,
  */
 void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val);
 #else
-static inline int __must_check msm_gpiomux_get(unsigned gpio)
-{
-       return -ENOSYS;
-}
-
-static inline int msm_gpiomux_put(unsigned gpio)
-{
-       return -ENOSYS;
-}
-
 static inline int msm_gpiomux_write(unsigned gpio,
                                    gpiomux_config_t active,
                                    gpiomux_config_t suspended)
diff --git a/arch/arm/mach-msm/include/mach/msm_gpiomux.h b/arch/arm/mach-msm/include/mach/msm_gpiomux.h
new file mode 100644 (file)
index 0000000..0c7d393
--- /dev/null
@@ -0,0 +1,38 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_MSM_GPIOMUX_H
+#define _LINUX_MSM_GPIOMUX_H
+
+#ifdef CONFIG_MSM_GPIOMUX
+
+/* Increment a gpio's reference count, possibly activating the line. */
+int __must_check msm_gpiomux_get(unsigned gpio);
+
+/* Decrement a gpio's reference count, possibly suspending the line. */
+int msm_gpiomux_put(unsigned gpio);
+
+#else
+
+static inline int __must_check msm_gpiomux_get(unsigned gpio)
+{
+       return -ENOSYS;
+}
+
+static inline int msm_gpiomux_put(unsigned gpio)
+{
+       return -ENOSYS;
+}
+
+#endif
+
+#endif /* _LINUX_MSM_GPIOMUX_H */
index 8f99d97..94fe9fe 100644 (file)
 #define MSM_DMOV_PHYS         0xA9700000
 #define MSM_DMOV_SIZE         SZ_4K
 
-#define MSM_GPIO1_BASE        IOMEM(0xE0003000)
-#define MSM_GPIO1_PHYS        0xA9200000
-#define MSM_GPIO1_SIZE        SZ_4K
+#define MSM7X00_GPIO1_PHYS        0xA9200000
+#define MSM7X00_GPIO1_SIZE        SZ_4K
 
-#define MSM_GPIO2_BASE        IOMEM(0xE0004000)
-#define MSM_GPIO2_PHYS        0xA9300000
-#define MSM_GPIO2_SIZE        SZ_4K
+#define MSM7X00_GPIO2_PHYS        0xA9300000
+#define MSM7X00_GPIO2_SIZE        SZ_4K
 
 #define MSM_CLK_CTL_BASE      IOMEM(0xE0005000)
 #define MSM_CLK_CTL_PHYS      0xA8600000
index 4d84be1..3769444 100644 (file)
 #define MSM_DMOV_PHYS         0xAC400000
 #define MSM_DMOV_SIZE         SZ_4K
 
-#define MSM_GPIO1_BASE        IOMEM(0xE0003000)
-#define MSM_GPIO1_PHYS        0xAC001000
-#define MSM_GPIO1_SIZE        SZ_4K
+#define MSM7X30_GPIO1_PHYS        0xAC001000
+#define MSM7X30_GPIO1_SIZE        SZ_4K
 
-#define MSM_GPIO2_BASE        IOMEM(0xE0004000)
-#define MSM_GPIO2_PHYS        0xAC101000
-#define MSM_GPIO2_SIZE        SZ_4K
+#define MSM7X30_GPIO2_PHYS        0xAC101000
+#define MSM7X30_GPIO2_SIZE        SZ_4K
 
 #define MSM_CLK_CTL_BASE      IOMEM(0xE0005000)
 #define MSM_CLK_CTL_PHYS      0xAB800000
index d414320..d67cd73 100644 (file)
 #define MSM_DMOV_PHYS         0xA9700000
 #define MSM_DMOV_SIZE         SZ_4K
 
-#define MSM_GPIO1_BASE        IOMEM(0xE0003000)
-#define MSM_GPIO1_PHYS        0xA9000000
-#define MSM_GPIO1_SIZE        SZ_4K
+#define QSD8X50_GPIO1_PHYS        0xA9000000
+#define QSD8X50_GPIO1_SIZE        SZ_4K
 
-#define MSM_GPIO2_BASE        IOMEM(0xE0004000)
-#define MSM_GPIO2_PHYS        0xA9100000
-#define MSM_GPIO2_SIZE        SZ_4K
+#define QSD8X50_GPIO2_PHYS        0xA9100000
+#define QSD8X50_GPIO2_SIZE        SZ_4K
 
 #define MSM_CLK_CTL_BASE      IOMEM(0xE0005000)
 #define MSM_CLK_CTL_PHYS      0xA8600000
index 2f494b6..4ded152 100644 (file)
@@ -61,5 +61,7 @@
 #define MSM_QGIC_CPU_BASE      IOMEM(0xF0001000)
 #define MSM_TMR_BASE           IOMEM(0xF0200000)
 #define MSM_TMR0_BASE          IOMEM(0xF0201000)
+#define MSM_GPIO1_BASE         IOMEM(0xE0003000)
+#define MSM_GPIO2_BASE         IOMEM(0xE0004000)
 
 #endif
index cec6ed1..140ddbb 100644 (file)
@@ -43,8 +43,8 @@ static struct map_desc msm_io_desc[] __initdata = {
        MSM_DEVICE(VIC),
        MSM_CHIP_DEVICE(CSR, MSM7X00),
        MSM_DEVICE(DMOV),
-       MSM_DEVICE(GPIO1),
-       MSM_DEVICE(GPIO2),
+       MSM_CHIP_DEVICE(GPIO1, MSM7X00),
+       MSM_CHIP_DEVICE(GPIO2, MSM7X00),
        MSM_DEVICE(CLK_CTL),
 #ifdef CONFIG_MSM_DEBUG_UART
        MSM_DEVICE(DEBUG_UART),
@@ -76,8 +76,8 @@ static struct map_desc qsd8x50_io_desc[] __initdata = {
        MSM_DEVICE(VIC),
        MSM_CHIP_DEVICE(CSR, QSD8X50),
        MSM_DEVICE(DMOV),
-       MSM_DEVICE(GPIO1),
-       MSM_DEVICE(GPIO2),
+       MSM_CHIP_DEVICE(GPIO1, QSD8X50),
+       MSM_CHIP_DEVICE(GPIO2, QSD8X50),
        MSM_DEVICE(CLK_CTL),
        MSM_DEVICE(SIRC),
        MSM_DEVICE(SCPLL),
@@ -135,8 +135,8 @@ static struct map_desc msm7x30_io_desc[] __initdata = {
        MSM_DEVICE(VIC),
        MSM_CHIP_DEVICE(CSR, MSM7X30),
        MSM_DEVICE(DMOV),
-       MSM_DEVICE(GPIO1),
-       MSM_DEVICE(GPIO2),
+       MSM_CHIP_DEVICE(GPIO1, MSM7X30),
+       MSM_CHIP_DEVICE(GPIO2, MSM7X30),
        MSM_DEVICE(CLK_CTL),
        MSM_DEVICE(CLK_CTL_SH2),
        MSM_DEVICE(AD5),
index d6336af..c51af1c 100644 (file)
@@ -260,7 +260,8 @@ mv78xx0_pcie_scan_bus(int nr, struct pci_sys_data *sys)
        return bus;
 }
 
-static int __init mv78xx0_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init mv78xx0_pcie_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        struct pcie_port *pp = bus_to_port(dev->bus->number);
 
index 7c893fa..68934ea 100644 (file)
@@ -81,7 +81,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
                .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
        }, {
                .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
-               .irq = irq_to_gpio(CPUIMX51_QUARTD_GPIO),
+               .irq = gpio_to_irq(CPUIMX51_QUARTD_GPIO),
                .irqflags = IRQF_TRIGGER_HIGH,
                .uartclk = CPUIMX51_QUART_XTAL,
                .regshift = CPUIMX51_QUART_REGSHIFT,
index 15c6000..11b0ff6 100644 (file)
@@ -41,8 +41,6 @@
 #define BABBAGE_POWER_KEY      IMX_GPIO_NR(2, 21)
 #define BABBAGE_ECSPI1_CS0     IMX_GPIO_NR(4, 24)
 #define BABBAGE_ECSPI1_CS1     IMX_GPIO_NR(4, 25)
-#define BABBAGE_SD1_CD         IMX_GPIO_NR(1, 0)
-#define BABBAGE_SD1_WP         IMX_GPIO_NR(1, 1)
 #define BABBAGE_SD2_CD         IMX_GPIO_NR(1, 6)
 #define BABBAGE_SD2_WP         IMX_GPIO_NR(1, 5)
 
@@ -146,8 +144,9 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
        MX51_PAD_SD1_DATA1__SD1_DATA1,
        MX51_PAD_SD1_DATA2__SD1_DATA2,
        MX51_PAD_SD1_DATA3__SD1_DATA3,
-       MX51_PAD_GPIO1_0__GPIO1_0,
-       MX51_PAD_GPIO1_1__GPIO1_1,
+       /* CD/WP from controller */
+       MX51_PAD_GPIO1_0__SD1_CD,
+       MX51_PAD_GPIO1_1__SD1_WP,
 
        /* SD 2 */
        MX51_PAD_SD2_CMD__SD2_CMD,
@@ -156,6 +155,7 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
        MX51_PAD_SD2_DATA1__SD2_DATA1,
        MX51_PAD_SD2_DATA2__SD2_DATA2,
        MX51_PAD_SD2_DATA3__SD2_DATA3,
+       /* CD/WP gpio */
        MX51_PAD_GPIO1_6__GPIO1_6,
        MX51_PAD_GPIO1_5__GPIO1_5,
 
@@ -340,13 +340,15 @@ static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
 };
 
 static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
-       .cd_gpio = BABBAGE_SD1_CD,
-       .wp_gpio = BABBAGE_SD1_WP,
+       .cd_type = ESDHC_CD_CONTROLLER,
+       .wp_type = ESDHC_WP_CONTROLLER,
 };
 
 static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
        .cd_gpio = BABBAGE_SD2_CD,
        .wp_gpio = BABBAGE_SD2_WP,
+       .cd_type = ESDHC_CD_GPIO,
+       .wp_type = ESDHC_WP_GPIO,
 };
 
 /*
@@ -367,7 +369,7 @@ static void __init mx51_babbage_init(void)
                                        ARRAY_SIZE(mx51babbage_pads));
 
        imx51_add_imx_uart(0, &uart_pdata);
-       imx51_add_imx_uart(1, &uart_pdata);
+       imx51_add_imx_uart(1, NULL);
        imx51_add_imx_uart(2, &uart_pdata);
 
        babbage_fec_reset();
index f70700d..551daf8 100644 (file)
@@ -108,9 +108,9 @@ static void __init mx51_efikamx_board_id(void)
        gpio_request(EFIKAMX_PCBID2, "pcbid2");
        gpio_direction_input(EFIKAMX_PCBID2);
 
-       id = gpio_get_value(EFIKAMX_PCBID0);
-       id |= gpio_get_value(EFIKAMX_PCBID1) << 1;
-       id |= gpio_get_value(EFIKAMX_PCBID2) << 2;
+       id = gpio_get_value(EFIKAMX_PCBID0) ? 1 : 0;
+       id |= (gpio_get_value(EFIKAMX_PCBID1) ? 1 : 0) << 1;
+       id |= (gpio_get_value(EFIKAMX_PCBID2) ? 1 : 0) << 2;
 
        switch (id) {
        case 7:
index 2e4d9d3..8a9bca2 100644 (file)
@@ -156,23 +156,24 @@ static struct gpio_keys_button mx51_efikasb_keys[] = {
        {
                .code = KEY_POWER,
                .gpio = EFIKASB_PWRKEY,
-               .type = EV_PWR,
+               .type = EV_KEY,
                .desc = "Power Button",
                .wakeup = 1,
-               .debounce_interval = 10, /* ms */
+               .active_low = 1,
        },
        {
                .code = SW_LID,
                .gpio = EFIKASB_LID,
                .type = EV_SW,
                .desc = "Lid Switch",
+               .active_low = 1,
        },
        {
-               /* SW_RFKILLALL vs KEY_RFKILL ? */
-               .code = SW_RFKILL_ALL,
+               .code = KEY_RFKILL,
                .gpio = EFIKASB_RFKILL,
-               .type = EV_SW,
+               .type = EV_KEY,
                .desc = "rfkill",
+               .active_low = 1,
        },
 };
 
@@ -224,8 +225,8 @@ static void __init mx51_efikasb_board_id(void)
        gpio_request(EFIKASB_PCBID1, "pcb id1");
        gpio_direction_input(EFIKASB_PCBID1);
 
-       id = gpio_get_value(EFIKASB_PCBID0);
-       id |= gpio_get_value(EFIKASB_PCBID1) << 1;
+       id = gpio_get_value(EFIKASB_PCBID0) ? 1 : 0;
+       id |= (gpio_get_value(EFIKASB_PCBID1) ? 1 : 0) << 1;
 
        switch (id) {
        default:
index 54be525..4e1d51d 100644 (file)
@@ -210,11 +210,15 @@ static const struct gpio_keys_platform_data loco_button_data __initconst = {
 
 static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
        .cd_gpio = LOCO_SD1_CD,
+       .cd_type = ESDHC_CD_GPIO,
+       .wp_type = ESDHC_WP_NONE,
 };
 
 static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
        .cd_gpio = LOCO_SD3_CD,
        .wp_gpio = LOCO_SD3_WP,
+       .cd_type = ESDHC_CD_GPIO,
+       .wp_type = ESDHC_WP_GPIO,
 };
 
 static inline void mx53_loco_fec_reset(void)
index 23cd809..f7bf996 100644 (file)
@@ -271,7 +271,11 @@ static int _clk_pll_enable(struct clk *clk)
        int i = 0;
 
        pllbase = _get_pll_base(clk);
-       reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN;
+       reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+       if (reg & MXC_PLL_DP_CTL_UPEN)
+               return 0;
+
+       reg |= MXC_PLL_DP_CTL_UPEN;
        __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
 
        /* Wait for lock */
@@ -1422,11 +1426,13 @@ DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
        },
 
 static struct clk_lookup mx51_lookups[] = {
-       _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-       _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-       _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+       /* i.mx51 has the i.mx21 type uart */
+       _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+       _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+       _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
        _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-       _REGISTER_CLOCK("fec.0", NULL, fec_clk)
+       /* i.mx51 has the i.mx27 type fec */
+       _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
        _REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
        _REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
        _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
@@ -1446,7 +1452,8 @@ static struct clk_lookup mx51_lookups[] = {
        _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
        _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
        _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
-       _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+       /* i.mx51 has the i.mx35 type sdma */
+       _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
        _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
        _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
        _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
@@ -1454,10 +1461,10 @@ static struct clk_lookup mx51_lookups[] = {
        _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
        /* i.mx51 has the i.mx35 type cspi */
        _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk)
        _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
        _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
        _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
@@ -1470,29 +1477,32 @@ static struct clk_lookup mx51_lookups[] = {
 };
 
 static struct clk_lookup mx53_lookups[] = {
-       _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-       _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-       _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
-       _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
-       _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
+       /* i.mx53 has the i.mx21 type uart */
+       _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+       _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+       _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+       _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
+       _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
        _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-       _REGISTER_CLOCK("fec.0", NULL, fec_clk)
+       /* i.mx53 has the i.mx25 type fec */
+       _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
        _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
        _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
        _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
        _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_mx53_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_mx53_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_mx53_clk)
        /* i.mx53 has the i.mx51 type ecspi */
        _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
        _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
        /* i.mx53 has the i.mx25 type cspi */
        _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk)
        _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
        _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
-       _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+       /* i.mx53 has the i.mx35 type sdma */
+       _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
        _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
        _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
        _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
index ef8aec9..baea6e5 100644 (file)
@@ -115,7 +115,6 @@ static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
 };
 
 static struct sdma_platform_data imx51_sdma_pdata __initdata = {
-       .sdma_version = 2,
        .fw_name = "sdma-imx51.bin",
        .script_addrs = &imx51_sdma_script,
 };
@@ -135,7 +134,6 @@ static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
 };
 
 static struct sdma_platform_data imx53_sdma_pdata __initdata = {
-       .sdma_version = 2,
        .fw_name = "sdma-imx53.bin",
        .script_addrs = &imx53_sdma_script,
 };
@@ -148,7 +146,8 @@ void __init imx51_soc_init(void)
        mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
        mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
 
-       imx_add_imx_sdma(MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
+       /* i.mx51 has the i.mx35 type sdma */
+       imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
 }
 
 void __init imx53_soc_init(void)
@@ -162,5 +161,6 @@ void __init imx53_soc_init(void)
        mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
        mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
 
-       imx_add_imx_sdma(MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
+       /* i.mx53 has the i.mx35 type sdma */
+       imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
 }
index 56739c2..c920945 100644 (file)
@@ -186,7 +186,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 
        mdelay(10);
 
-       return mx51_initialize_usb_hw(0, MXC_EHCI_ITC_NO_THRESHOLD);
+       return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
 static struct mxc_usbh_platform_data usbh1_config = {
@@ -260,8 +260,8 @@ static struct regulator_consumer_supply vvideo_consumers[] = {
 };
 
 static struct regulator_consumer_supply vsd_consumers[] = {
-       REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.0"),
-       REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"),
+       REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.0"),
+       REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.1"),
 };
 
 static struct regulator_consumer_supply pwgt1_consumer[] = {
index 4ae6257..57b66d5 100644 (file)
@@ -7,7 +7,6 @@ config ARCH_OMAP2PLUS_TYPICAL
        default y
        select AEABI
        select REGULATOR
-       select PM
        select PM_RUNTIME
        select VFP
        select NEON if ARCH_OMAP3 || ARCH_OMAP4
index 5f2b55f..933e935 100644 (file)
@@ -45,8 +45,6 @@ static struct omap_board_config_kernel am3517_crane_config[] __initdata = {
 static struct omap_board_mux board_mux[] __initdata = {
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux      NULL
 #endif
 
 static void __init am3517_crane_init_early(void)
index 32f5f89..3ae16b4 100644 (file)
@@ -491,23 +491,22 @@ static void __init beagle_opp_init(void)
 
        /* Custom OPP enabled for all xM versions */
        if (cpu_is_omap3630()) {
-               struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
-               struct omap_hwmod *dh = omap_hwmod_lookup("iva");
-               struct device *dev;
+               struct device *mpu_dev, *iva_dev;
 
-               if (!mh || !dh) {
+               mpu_dev = omap2_get_mpuss_device();
+               iva_dev = omap2_get_iva_device();
+
+               if (!mpu_dev || !iva_dev) {
                        pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
-                               __func__, mh, dh);
+                               __func__, mpu_dev, iva_dev);
                        return;
                }
                /* Enable MPU 1GHz and lower opps */
-               dev = &mh->od->pdev.dev;
-               r = opp_enable(dev, 800000000);
+               r = opp_enable(mpu_dev, 800000000);
                /* TODO: MPU 1GHz needs SR and ABB */
 
                /* Enable IVA 800MHz and lower opps */
-               dev = &dh->od->pdev.dev;
-               r |= opp_enable(dev, 660000000);
+               r |= opp_enable(iva_dev, 660000000);
                /* TODO: DSP 800MHz needs SR and ABB */
                if (r) {
                        pr_err("%s: failed to enable higher opp %d\n",
@@ -516,10 +515,8 @@ static void __init beagle_opp_init(void)
                         * Cleanup - disable the higher freqs - we dont care
                         * about the results
                         */
-                       dev = &mh->od->pdev.dev;
-                       opp_disable(dev, 800000000);
-                       dev = &dh->od->pdev.dev;
-                       opp_disable(dev, 660000000);
+                       opp_disable(mpu_dev, 800000000);
+                       opp_disable(iva_dev, 660000000);
                }
        }
        return;
index cc503aa..5a886cd 100644 (file)
@@ -418,6 +418,10 @@ static struct regulator_consumer_supply rx51_vmmc1_supply[] = {
        REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
 
+static struct regulator_consumer_supply rx51_vaux2_supply[] = {
+       REGULATOR_SUPPLY("vdds_csib", "omap3isp"),
+};
+
 static struct regulator_consumer_supply rx51_vaux3_supply[] = {
        REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
 };
@@ -479,6 +483,8 @@ static struct regulator_init_data rx51_vaux2 = {
                .valid_ops_mask         = REGULATOR_CHANGE_MODE
                                        | REGULATOR_CHANGE_STATUS,
        },
+       .num_consumer_supplies  = ARRAY_SIZE(rx51_vaux2_supply),
+       .consumer_supplies      = rx51_vaux2_supply,
 };
 
 /* VAUX3 - adds more power to VIO_18 rail */
index f2ea645..a018a73 100644 (file)
@@ -18,13 +18,36 @@ extern void omap4_cminst_clkdm_force_sleep(u8 part, s16 inst, u16 cdoffs);
 extern void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs);
 
 extern int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
-extern int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
+
+# ifdef CONFIG_ARCH_OMAP4
+extern int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs,
+                                        u16 clkctrl_offs);
 
 extern void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs,
                                       u16 clkctrl_offs);
 extern void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
                                        u16 clkctrl_offs);
 
+# else
+
+static inline int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs,
+                                       u16 clkctrl_offs)
+{
+       return 0;
+}
+
+static inline void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst,
+                               s16 cdoffs, u16 clkctrl_offs)
+{
+}
+
+static inline void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
+                                u16 clkctrl_offs)
+{
+}
+
+# endif
+
 /*
  * In an ideal world, we would not export these low-level functions,
  * but this will probably take some time to fix properly
index 543fcb8..a5b7a23 100644 (file)
@@ -25,6 +25,7 @@
 #include <video/omapdss.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
+#include <plat/omap-pm.h>
 
 static struct platform_device omap_display_device = {
        .name          = "omapdss",
@@ -42,20 +43,6 @@ static struct omap_device_pm_latency omap_dss_latency[] = {
        },
 };
 
-/* oh_core is used for getting opt-clocks */
-static struct omap_hwmod       *oh_core;
-
-static bool opt_clock_available(const char *clk_role)
-{
-       int i;
-
-       for (i = 0; i < oh_core->opt_clks_cnt; i++) {
-               if (!strcmp(oh_core->opt_clks[i].role, clk_role))
-                       return true;
-       }
-       return false;
-}
-
 struct omap_dss_hwmod_data {
        const char *oh_name;
        const char *dev_name;
@@ -109,16 +96,9 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
                oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);
        }
 
-       /* opt_clks are always associated with dss hwmod */
-       oh_core = omap_hwmod_lookup("dss_core");
-       if (!oh_core) {
-               pr_err("Could not look up dss_core.\n");
-               return -ENODEV;
-       }
-
        pdata.board_data = board_data;
-       pdata.board_data->get_last_off_on_transaction_id = NULL;
-       pdata.opt_clock_available = opt_clock_available;
+       pdata.board_data->get_context_loss_count =
+               omap_pm_get_dev_context_loss_count;
 
        for (i = 0; i < oh_count; i++) {
                oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name);
index c7fb22a..655e948 100644 (file)
@@ -821,11 +821,10 @@ static void __init omap_mux_set_cmdline_signals(void)
        if (!omap_mux_options)
                return;
 
-       options = kmalloc(strlen(omap_mux_options) + 1, GFP_KERNEL);
+       options = kstrdup(omap_mux_options, GFP_KERNEL);
        if (!options)
                return;
 
-       strcpy(options, omap_mux_options);
        next_opt = options;
 
        while ((token = strsep(&next_opt, ",")) != NULL) {
@@ -855,24 +854,19 @@ static int __init omap_mux_copy_names(struct omap_mux *src,
 
        for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
                if (src->muxnames[i]) {
-                       dst->muxnames[i] =
-                               kmalloc(strlen(src->muxnames[i]) + 1,
-                                       GFP_KERNEL);
+                       dst->muxnames[i] = kstrdup(src->muxnames[i],
+                                                  GFP_KERNEL);
                        if (!dst->muxnames[i])
                                goto free;
-                       strcpy(dst->muxnames[i], src->muxnames[i]);
                }
        }
 
 #ifdef CONFIG_DEBUG_FS
        for (i = 0; i < OMAP_MUX_NR_SIDES; i++) {
                if (src->balls[i]) {
-                       dst->balls[i] =
-                               kmalloc(strlen(src->balls[i]) + 1,
-                                       GFP_KERNEL);
+                       dst->balls[i] = kstrdup(src->balls[i], GFP_KERNEL);
                        if (!dst->balls[i])
                                goto free;
-                       strcpy(dst->balls[i], src->balls[i]);
                }
        }
 #endif
index 2ce2fb7..34c01a7 100644 (file)
@@ -621,7 +621,7 @@ void sr_disable(struct voltagedomain *voltdm)
                        sr_v2_disable(sr);
        }
 
-       pm_runtime_put_sync(&sr->pdev->dev);
+       pm_runtime_put_sync_suspend(&sr->pdev->dev);
 }
 
 /**
@@ -860,6 +860,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
        irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 
        pm_runtime_enable(&pdev->dev);
+       pm_runtime_irq_safe(&pdev->dev);
 
        sr_info->pdev = pdev;
        sr_info->srid = pdev->id;
index e964072..cf1de7d 100644 (file)
@@ -293,7 +293,8 @@ static void __init omap2_gp_clocksource_init(int gptimer_id,
        pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
                gptimer_id, clksrc.rate);
 
-       __omap_dm_timer_load_start(clksrc.io_base, OMAP_TIMER_CTRL_ST, 0, 1);
+       __omap_dm_timer_load_start(clksrc.io_base,
+                       OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
        init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);
 
        if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
index 2543342..daa056e 100644 (file)
@@ -48,14 +48,7 @@ void __init omap_pmic_init(int bus, u32 clkrate,
        omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
 }
 
-static struct twl4030_usb_data omap4_usb_pdata = {
-       .phy_init       = omap4430_phy_init,
-       .phy_exit       = omap4430_phy_exit,
-       .phy_power      = omap4430_phy_power,
-       .phy_set_clock  = omap4430_phy_set_clk,
-       .phy_suspend    = omap4430_phy_suspend,
-};
-
+#if defined(CONFIG_ARCH_OMAP3)
 static struct twl4030_usb_data omap3_usb_pdata = {
        .usb_mode       = T2_USB_MODE_ULPI,
 };
@@ -122,6 +115,45 @@ static struct regulator_init_data omap3_vpll2_idata = {
        .consumer_supplies              = omap3_vpll2_supplies,
 };
 
+void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
+                                 u32 pdata_flags, u32 regulators_flags)
+{
+       if (!pmic_data->irq_base)
+               pmic_data->irq_base = TWL4030_IRQ_BASE;
+       if (!pmic_data->irq_end)
+               pmic_data->irq_end = TWL4030_IRQ_END;
+
+       /* Common platform data configurations */
+       if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
+               pmic_data->usb = &omap3_usb_pdata;
+
+       if (pdata_flags & TWL_COMMON_PDATA_BCI && !pmic_data->bci)
+               pmic_data->bci = &omap3_bci_pdata;
+
+       if (pdata_flags & TWL_COMMON_PDATA_MADC && !pmic_data->madc)
+               pmic_data->madc = &omap3_madc_pdata;
+
+       if (pdata_flags & TWL_COMMON_PDATA_AUDIO && !pmic_data->audio)
+               pmic_data->audio = &omap3_audio_pdata;
+
+       /* Common regulator configurations */
+       if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
+               pmic_data->vdac = &omap3_vdac_idata;
+
+       if (regulators_flags & TWL_COMMON_REGULATOR_VPLL2 && !pmic_data->vpll2)
+               pmic_data->vpll2 = &omap3_vpll2_idata;
+}
+#endif /* CONFIG_ARCH_OMAP3 */
+
+#if defined(CONFIG_ARCH_OMAP4)
+static struct twl4030_usb_data omap4_usb_pdata = {
+       .phy_init       = omap4430_phy_init,
+       .phy_exit       = omap4430_phy_exit,
+       .phy_power      = omap4430_phy_power,
+       .phy_set_clock  = omap4430_phy_set_clk,
+       .phy_suspend    = omap4430_phy_suspend,
+};
+
 static struct regulator_init_data omap4_vdac_idata = {
        .constraints = {
                .min_uV                 = 1800000,
@@ -273,32 +305,4 @@ void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
            !pmic_data->clk32kg)
                pmic_data->clk32kg = &omap4_clk32kg_idata;
 }
-
-void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
-                                 u32 pdata_flags, u32 regulators_flags)
-{
-       if (!pmic_data->irq_base)
-               pmic_data->irq_base = TWL4030_IRQ_BASE;
-       if (!pmic_data->irq_end)
-               pmic_data->irq_end = TWL4030_IRQ_END;
-
-       /* Common platform data configurations */
-       if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
-               pmic_data->usb = &omap3_usb_pdata;
-
-       if (pdata_flags & TWL_COMMON_PDATA_BCI && !pmic_data->bci)
-               pmic_data->bci = &omap3_bci_pdata;
-
-       if (pdata_flags & TWL_COMMON_PDATA_MADC && !pmic_data->madc)
-               pmic_data->madc = &omap3_madc_pdata;
-
-       if (pdata_flags & TWL_COMMON_PDATA_AUDIO && !pmic_data->audio)
-               pmic_data->audio = &omap3_audio_pdata;
-
-       /* Common regulator configurations */
-       if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
-               pmic_data->vdac = &omap3_vdac_idata;
-
-       if (regulators_flags & TWL_COMMON_REGULATOR_VPLL2 && !pmic_data->vpll2)
-               pmic_data->vpll2 = &omap3_vpll2_idata;
-}
+#endif /* CONFIG_ARCH_OMAP4 */
index f2b2b35..3e5499d 100644 (file)
@@ -51,7 +51,7 @@ void orion5x_pci_disable(void);
 void orion5x_pci_set_cardbus_mode(void);
 int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
 struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
-int orion5x_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
+int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
 
 struct machine_desc;
 struct meminfo;
index f95d3cb..a3e3e9e 100644 (file)
@@ -237,7 +237,8 @@ void __init db88f5281_pci_preinit(void)
        }
 }
 
-static int __init db88f5281_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init db88f5281_pci_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        int irq;
 
index 855e0e7..a6eddae 100644 (file)
@@ -70,14 +70,14 @@ enum {
  * PCI setup
  */
 
-static int __init dns323_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init dns323_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
        /*
         * Check for devices with hard-wired IRQs.
         */
-       irq = orion5x_pci_map_irq(dev, slot, pin);
+       irq = orion5x_pci_map_irq(const dev, slot, pin);
        if (irq != -1)
                return irq;
 
index c0eb646..0038124 100644 (file)
@@ -119,7 +119,8 @@ static struct platform_device kurobox_pro_nor_flash = {
  * PCI
  ****************************************************************************/
 
-static int __init kurobox_pro_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init kurobox_pro_pci_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        int irq;
 
index 59263b7..ef3bb8e 100644 (file)
@@ -73,7 +73,7 @@ static struct platform_device mss2_nor_flash = {
 /****************************************************************************
  * PCI setup
  ****************************************************************************/
-static int __init mss2_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init mss2_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index f64965d..28b8760 100644 (file)
@@ -589,7 +589,7 @@ struct pci_bus __init *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys
        return bus;
 }
 
-int __init orion5x_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int bus = dev->bus->number;
 
index 9eec7c2..291d22b 100644 (file)
@@ -131,7 +131,7 @@ static void __init rd88f5181l_fxo_init(void)
 }
 
 static int __init
-rd88f5181l_fxo_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+rd88f5181l_fxo_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index 0cc90bb..3f02362 100644 (file)
@@ -140,7 +140,7 @@ static void __init rd88f5181l_ge_init(void)
 }
 
 static int __init
-rd88f5181l_ge_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+rd88f5181l_ge_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index 48da39b..27fd38e 100644 (file)
@@ -172,7 +172,8 @@ void __init rd88f5182_pci_preinit(void)
        }
 }
 
-static int __init rd88f5182_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init rd88f5182_pci_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        int irq;
 
index 29ce826..a34e4fa 100644 (file)
@@ -100,7 +100,7 @@ void __init tsp2_pci_preinit(void)
        }
 }
 
-static int __init tsp2_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init tsp2_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index 47162fd..c983161 100644 (file)
@@ -143,7 +143,8 @@ void __init qnap_ts209_pci_preinit(void)
        }
 }
 
-static int __init qnap_ts209_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init qnap_ts209_pci_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        int irq;
 
index 5aacc7a..cc33b22 100644 (file)
@@ -121,7 +121,8 @@ static struct platform_device qnap_ts409_nor_flash = {
  * PCI
  ****************************************************************************/
 
-static int __init qnap_ts409_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init qnap_ts409_pci_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        int irq;
 
index 444a1c7..2653595 100644 (file)
@@ -133,7 +133,8 @@ static void __init wnr854t_init(void)
        platform_device_register(&wnr854t_nor_flash);
 }
 
-static int __init wnr854t_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init wnr854t_pci_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        int irq;
 
index d1952be..251ef15 100644 (file)
@@ -221,7 +221,8 @@ static void __init wrt350n_v2_init(void)
        platform_device_register(&wrt350n_v2_button_device);
 }
 
-static int __init wrt350n_v2_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init wrt350n_v2_pci_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        int irq;
 
index 4eb7660..6bf479d 100644 (file)
@@ -77,7 +77,7 @@ void cmx2xx_pci_resume(void) {}
 #endif
 
 /* PCI IRQ mapping*/
-static int __init cmx2xx_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init cmx2xx_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index 9026249..af0c2fe 100644 (file)
@@ -65,7 +65,7 @@
 #include <plat/iic.h>
 #include <plat/pm.h>
 
-#include <sound/wm8915.h>
+#include <sound/wm8996.h>
 #include <sound/wm8962.h>
 #include <sound/wm9081.h>
 
@@ -614,7 +614,7 @@ static struct wm831x_pdata glenfarclas_pmic_pdata __initdata = {
        .disable_touch = true,
 };
 
-static struct wm8915_retune_mobile_config wm8915_retune[] = {
+static struct wm8996_retune_mobile_config wm8996_retune[] = {
        {
                .name = "Sub LPF",
                .rate = 48000,
@@ -635,12 +635,12 @@ static struct wm8915_retune_mobile_config wm8915_retune[] = {
        },
 };
 
-static struct wm8915_pdata wm8915_pdata __initdata = {
+static struct wm8996_pdata wm8996_pdata __initdata = {
        .ldo_ena = S3C64XX_GPN(7),
        .gpio_base = CODEC_GPIO_BASE,
        .micdet_def = 1,
-       .inl_mode = WM8915_DIFFERRENTIAL_1,
-       .inr_mode = WM8915_DIFFERRENTIAL_1,
+       .inl_mode = WM8996_DIFFERRENTIAL_1,
+       .inr_mode = WM8996_DIFFERRENTIAL_1,
 
        .irq_flags = IRQF_TRIGGER_RISING,
 
@@ -652,8 +652,8 @@ static struct wm8915_pdata wm8915_pdata __initdata = {
                0x020e, /* GPIO5 == CLKOUT */
        },
 
-       .retune_mobile_cfgs = wm8915_retune,
-       .num_retune_mobile_cfgs = ARRAY_SIZE(wm8915_retune),
+       .retune_mobile_cfgs = wm8996_retune,
+       .num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
 };
 
 static struct wm8962_pdata wm8962_pdata __initdata = {
@@ -679,8 +679,8 @@ static struct i2c_board_info i2c_devs1[] __initdata = {
          .platform_data = &glenfarclas_pmic_pdata },
 
        { I2C_BOARD_INFO("wm1250-ev1", 0x27) },
-       { I2C_BOARD_INFO("wm8915", 0x1a),
-         .platform_data = &wm8915_pdata,
+       { I2C_BOARD_INFO("wm8996", 0x1a),
+         .platform_data = &wm8996_pdata,
          .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
        },
        { I2C_BOARD_INFO("wm9081", 0x6c),
index 5fc074f..dd39fee 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/mach-types.h>
 
 #include <mach/nanoengine.h>
+#include <mach/hardware.h>
 
 static DEFINE_SPINLOCK(nano_lock);
 
@@ -122,7 +123,8 @@ static struct pci_ops pci_nano_ops = {
        .write  = nanoengine_write_config,
 };
 
-static int __init pci_nanoengine_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init pci_nanoengine_map_irq(const struct pci_dev *dev, u8 slot,
+       u8 pin)
 {
        return NANOENGINE_IRQ_GPIO_PCI;
 }
index 92d7227..7cb79a0 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
-static int __init shark_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init shark_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        if (dev->bus->number == 0)
                if (dev->devfn == 0)
index 837138e..9e0856b 100644 (file)
@@ -957,19 +957,16 @@ static struct resource csi2_resources[] = {
        },
 };
 
-static struct platform_device csi2_device = {
-       .name   = "sh-mobile-csi2",
-       .id     = 0,
+static struct sh_mobile_ceu_companion csi2 = {
+       .id             = 0,
        .num_resources  = ARRAY_SIZE(csi2_resources),
        .resource       = csi2_resources,
-       .dev    = {
-               .platform_data = &csi2_info,
-       },
+       .platform_data  = &csi2_info,
 };
 
 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
        .flags = SH_CEU_FLAG_USE_8BIT_BUS,
-       .csi2_dev = &csi2_device.dev,
+       .csi2 = &csi2,
 };
 
 static struct resource ceu_resources[] = {
@@ -1013,7 +1010,6 @@ static struct platform_device *ap4evb_devices[] __initdata = {
        &lcdc1_device,
        &lcdc_device,
        &hdmi_device,
-       &csi2_device,
        &ceu_device,
        &ap4evb_camera,
        &meram_device,
index 5b36b6c..d41c01f 100644 (file)
@@ -1192,8 +1192,8 @@ static struct platform_device sh_mmcif_device = {
 };
 
 
-static int mackerel_camera_add(struct soc_camera_link *icl, struct device *dev);
-static void mackerel_camera_del(struct soc_camera_link *icl);
+static int mackerel_camera_add(struct soc_camera_device *icd);
+static void mackerel_camera_del(struct soc_camera_device *icd);
 
 static int camera_set_capture(struct soc_camera_platform_info *info,
                              int enable)
@@ -1232,16 +1232,15 @@ static void mackerel_camera_release(struct device *dev)
        soc_camera_platform_release(&camera_device);
 }
 
-static int mackerel_camera_add(struct soc_camera_link *icl,
-                              struct device *dev)
+static int mackerel_camera_add(struct soc_camera_device *icd)
 {
-       return soc_camera_platform_add(icl, dev, &camera_device, &camera_link,
+       return soc_camera_platform_add(icd, &camera_device, &camera_link,
                                       mackerel_camera_release, 0);
 }
 
-static void mackerel_camera_del(struct soc_camera_link *icl)
+static void mackerel_camera_del(struct soc_camera_device *icd)
 {
-       soc_camera_platform_del(icl, camera_device, &camera_link);
+       soc_camera_platform_del(icd, camera_device, &camera_link);
 }
 
 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
index 6b186ae..5218c34 100644 (file)
@@ -259,9 +259,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [CMMSTP003] = MSTP(&r_clk, CMMSTPCR0, 3, 0), /* KEYSC */
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("r_clk", &r_clk),
index 91f5779..6b1619a 100644 (file)
@@ -561,10 +561,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
-#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("dv_clki_div2_clk", &sh7372_dv_clki_div2_clk),
index 9594246..8cee7b1 100644 (file)
@@ -267,9 +267,6 @@ static struct clk mstp_clks[] = {
        [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("r_clk", &r_clk),
index bcacb1e..6db2cca 100644 (file)
@@ -306,10 +306,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
-#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("r_clk", &r_clk),
index 5ec1846..d82ebab 100644 (file)
@@ -27,14 +27,14 @@ comment "Tegra board type"
 
 config MACH_HARMONY
        bool "Harmony board"
-       select MACH_HAS_SND_SOC_TEGRA_WM8903
+       select MACH_HAS_SND_SOC_TEGRA_WM8903 if SND_SOC
        help
          Support for nVidia Harmony development platform
 
 config MACH_KAEN
        bool "Kaen board"
        select MACH_SEABOARD
-       select MACH_HAS_SND_SOC_TEGRA_WM8903
+       select MACH_HAS_SND_SOC_TEGRA_WM8903 if SND_SOC
        help
          Support for the Kaen version of Seaboard
 
@@ -45,12 +45,18 @@ config MACH_PAZ00
 
 config MACH_SEABOARD
        bool "Seaboard board"
-       select MACH_HAS_SND_SOC_TEGRA_WM8903
+       select MACH_HAS_SND_SOC_TEGRA_WM8903 if SND_SOC
        help
          Support for nVidia Seaboard development platform. It will
         also be included for some of the derivative boards that
         have large similarities with the seaboard design.
 
+config MACH_TEGRA_DT
+       bool "Generic Tegra board (FDT support)"
+       select USE_OF
+       help
+         Support for generic nVidia Tegra boards using Flattened Device Tree
+
 config MACH_TRIMSLICE
        bool "TrimSlice board"
        select TEGRA_PCI
index ed58ef9..f11b910 100644 (file)
@@ -29,5 +29,8 @@ obj-${CONFIG_MACH_PAZ00}              += board-paz00-pinmux.o
 obj-${CONFIG_MACH_SEABOARD}             += board-seaboard.o
 obj-${CONFIG_MACH_SEABOARD}             += board-seaboard-pinmux.o
 
+obj-${CONFIG_MACH_TEGRA_DT}             += board-dt.o
+obj-${CONFIG_MACH_TEGRA_DT}             += board-harmony-pinmux.o
+
 obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice.o
 obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice-pinmux.o
index db52d61..428ad12 100644 (file)
@@ -1,3 +1,6 @@
 zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC)   := 0x00008000
 params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)        := 0x00000100
 initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)        := 0x00800000
+
+dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb
+dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb
diff --git a/arch/arm/mach-tegra/board-dt.c b/arch/arm/mach-tegra/board-dt.c
new file mode 100644 (file)
index 0000000..9f47e04
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * nVidia Tegra device tree board support
+ *
+ * Copyright (C) 2010 Secret Lab Technologies, Ltd.
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/pda_power.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/i2c-tegra.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/setup.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+
+#include "board.h"
+#include "board-harmony.h"
+#include "clock.h"
+#include "devices.h"
+
+void harmony_pinmux_init(void);
+void seaboard_pinmux_init(void);
+
+
+struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
+       OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC3_BASE, "sdhci-tegra.2", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC4_BASE, "sdhci-tegra.3", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C_BASE, "tegra-i2c.0", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C2_BASE, "tegra-i2c.1", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C3_BASE, "tegra-i2c.2", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_DVC_BASE, "tegra-i2c.3", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.0", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.1", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL),
+       {}
+};
+
+static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
+       /* name         parent          rate            enabled */
+       { "uartd",      "pll_p",        216000000,      true },
+       { NULL,         NULL,           0,              0},
+};
+
+static struct of_device_id tegra_dt_match_table[] __initdata = {
+       { .compatible = "simple-bus", },
+       {}
+};
+
+static struct of_device_id tegra_dt_gic_match[] __initdata = {
+       { .compatible = "nvidia,tegra20-gic", },
+       {}
+};
+
+static void __init tegra_dt_init(void)
+{
+       struct device_node *node;
+
+       node = of_find_matching_node_by_address(NULL, tegra_dt_gic_match,
+                                               TEGRA_ARM_INT_DIST_BASE);
+       if (node)
+               irq_domain_add_simple(node, INT_GIC_BASE);
+
+       tegra_clk_init_from_table(tegra_dt_clk_init_table);
+
+       if (of_machine_is_compatible("nvidia,harmony"))
+               harmony_pinmux_init();
+       else if (of_machine_is_compatible("nvidia,seaboard"))
+               seaboard_pinmux_init();
+
+       /*
+        * Finished with the static registrations now; fill in the missing
+        * devices
+        */
+       of_platform_populate(NULL, tegra_dt_match_table, tegra20_auxdata_lookup, NULL);
+}
+
+static const char * tegra_dt_board_compat[] = {
+       "nvidia,harmony",
+       "nvidia,seaboard",
+       NULL
+};
+
+DT_MACHINE_START(TEGRA_DT, "nVidia Tegra (Flattened Device Tree)")
+       .map_io         = tegra_map_common_io,
+       .init_early     = tegra_init_early,
+       .init_irq       = tegra_init_irq,
+       .timer          = &tegra_timer,
+       .init_machine   = tegra_dt_init,
+       .dt_compat      = tegra_dt_board_compat,
+MACHINE_END
index 031cd0a..f1f699d 100644 (file)
@@ -449,7 +449,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
        return 1;
 }
 
-static int tegra_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int tegra_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        return INT_PCIE_INTR;
 }
index 9cdec5a..c1f38f6 100644 (file)
@@ -17,4 +17,12 @@ config MACH_VERSATILE_AB
          Include support for the ARM(R) Versatile Application Baseboard
          for the ARM926EJ-S.
 
+config MACH_VERSATILE_DT
+       bool "Support Versatile platform from device tree"
+       select USE_OF
+       select CPU_ARM926T
+       help
+         Include support for the ARM(R) Versatile/PB platform,
+         using the device tree for discovery
+
 endmenu
index 97cf4d8..81fa3fe 100644 (file)
@@ -5,4 +5,5 @@
 obj-y                                  := core.o
 obj-$(CONFIG_ARCH_VERSATILE_PB)                += versatile_pb.o
 obj-$(CONFIG_MACH_VERSATILE_AB)                += versatile_ab.o
+obj-$(CONFIG_MACH_VERSATILE_DT)                += versatile_dt.o
 obj-$(CONFIG_PCI)                      += pci.o
index 0c99cf0..e340a54 100644 (file)
@@ -24,6 +24,9 @@
 #include <linux/platform_device.h>
 #include <linux/sysdev.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
 #include <linux/amba/pl061.h>
@@ -83,13 +86,26 @@ static struct fpga_irq_data sic_irq = {
 #define PIC_MASK       0
 #endif
 
+/* Lookup table for finding a DT node that represents the vic instance */
+static const struct of_device_id vic_of_match[] __initconst = {
+       { .compatible = "arm,versatile-vic", },
+       {}
+};
+
+static const struct of_device_id sic_of_match[] __initconst = {
+       { .compatible = "arm,versatile-sic", },
+       {}
+};
+
 void __init versatile_init_irq(void)
 {
        vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
+       irq_domain_generate_simple(vic_of_match, VERSATILE_VIC_BASE, IRQ_VIC_START);
 
        writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
 
        fpga_irq_init(IRQ_VICSOURCE31, ~PIC_MASK, &sic_irq);
+       irq_domain_generate_simple(sic_of_match, VERSATILE_SIC_BASE, IRQ_SIC_START);
 
        /*
         * Interrupts on secondary controller from 0 to 8 are routed to
@@ -646,6 +662,52 @@ static struct amba_device *amba_devs[] __initdata = {
        &kmi1_device,
 };
 
+#ifdef CONFIG_OF
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+struct of_dev_auxdata versatile_auxdata_lookup[] __initdata = {
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI0_BASE, "fpga:05", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_KMI0_BASE, "fpga:06", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_KMI1_BASE, "fpga:07", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART3_BASE, "fpga:09", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI1_BASE, "fpga:0b", NULL),
+
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_CLCD_BASE, "dev:20", &clcd_plat_data),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART0_BASE, "dev:f1", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART1_BASE, "dev:f2", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART2_BASE, "dev:f3", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_SSP_BASE, "dev:f4", NULL),
+
+#if 0
+       /*
+        * These entries are unnecessary because no clocks referencing
+        * them.  I've left them in for now as place holders in case
+        * any of them need to be added back, but they should be
+        * removed before actually committing this patch.  --gcl
+        */
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_AACI_BASE, "fpga:04", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCI1_BASE, "fpga:0a", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_SMC_BASE, "dev:00", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_MPMC_BASE, "dev:10", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_DMAC_BASE, "dev:30", NULL),
+
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCTL_BASE, "dev:e0", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_WATCHDOG_BASE, "dev:e1", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO0_BASE, "dev:e4", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO1_BASE, "dev:e5", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO2_BASE, "dev:e6", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO3_BASE, "dev:e7", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_RTC_BASE, "dev:e8", NULL),
+       OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCI_BASE, "dev:f0", NULL),
+#endif
+       {}
+};
+#endif
+
 #ifdef CONFIG_LEDS
 #define VA_LEDS_BASE (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET)
 
index fd6404e..e014227 100644 (file)
@@ -23,6 +23,7 @@
 #define __ASM_ARCH_VERSATILE_H
 
 #include <linux/amba/bus.h>
+#include <linux/of_platform.h>
 
 extern void __init versatile_init(void);
 extern void __init versatile_init_early(void);
@@ -30,6 +31,9 @@ extern void __init versatile_init_irq(void);
 extern void __init versatile_map_io(void);
 extern struct sys_timer versatile_timer;
 extern unsigned int mmc_status(struct device *dev);
+#ifdef CONFIG_OF
+extern struct of_dev_auxdata versatile_auxdata_lookup[];
+#endif
 
 #define AMBA_DEVICE(name,busid,base,plat)                      \
 static struct amba_device name##_device = {                    \
index 7848a17..c898deb 100644 (file)
@@ -328,7 +328,7 @@ void __init pci_versatile_preinit(void)
 /*
  * map the specified device/slot/pin to an IRQ.   Different backplanes may need to modify this.
  */
-static int __init versatile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init versatile_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
        int devslot = PCI_SLOT(dev->devfn);
diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c
new file mode 100644 (file)
index 0000000..54e037c
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Versatile board support using the device tree
+ *
+ *  Copyright (C) 2010 Secret Lab Technologies Ltd.
+ *  Copyright (C) 2009 Jeremy Kerr <jeremy.kerr@canonical.com>
+ *  Copyright (C) 2004 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * 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/init.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "core.h"
+
+static void __init versatile_dt_init(void)
+{
+       of_platform_populate(NULL, of_default_bus_match_table,
+                            versatile_auxdata_lookup, NULL);
+}
+
+static const char *versatile_dt_match[] __initconst = {
+       "arm,versatile-ab",
+       "arm,versatile-pb",
+       NULL,
+};
+
+DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)")
+       .map_io         = versatile_map_io,
+       .init_early     = versatile_init_early,
+       .init_irq       = versatile_init_irq,
+       .timer          = &versatile_timer,
+       .init_machine   = versatile_dt_init,
+       .dt_compat      = versatile_dt_match,
+MACHINE_END
index c550c67..397268c 100644 (file)
@@ -3,4 +3,4 @@
 #
 
 # Common support
-obj-y                          := common.o timer.o board_dt.o
+obj-y                          := common.o timer.o
diff --git a/arch/arm/mach-zynq/board_dt.c b/arch/arm/mach-zynq/board_dt.c
deleted file mode 100644 (file)
index e69de29..0000000
index be7c638..cfbcf8b 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 
+#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include "fault.h"
@@ -95,6 +96,33 @@ static const char *usermode_action[] = {
        "signal+warn"
 };
 
+/* Return true if and only if the ARMv6 unaligned access model is in use. */
+static bool cpu_is_v6_unaligned(void)
+{
+       return cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U);
+}
+
+static int safe_usermode(int new_usermode, bool warn)
+{
+       /*
+        * ARMv6 and later CPUs can perform unaligned accesses for
+        * most single load and store instructions up to word size.
+        * LDM, STM, LDRD and STRD still need to be handled.
+        *
+        * Ignoring the alignment fault is not an option on these
+        * CPUs since we spin re-faulting the instruction without
+        * making any progress.
+        */
+       if (cpu_is_v6_unaligned() && !(new_usermode & (UM_FIXUP | UM_SIGNAL))) {
+               new_usermode |= UM_FIXUP;
+
+               if (warn)
+                       printk(KERN_WARNING "alignment: ignoring faults is unsafe on this CPU.  Defaulting to fixup mode.\n");
+       }
+
+       return new_usermode;
+}
+
 static int alignment_proc_show(struct seq_file *m, void *v)
 {
        seq_printf(m, "User:\t\t%lu\n", ai_user);
@@ -125,7 +153,7 @@ static ssize_t alignment_proc_write(struct file *file, const char __user *buffer
                if (get_user(mode, buffer))
                        return -EFAULT;
                if (mode >= '0' && mode <= '5')
-                       ai_usermode = mode - '0';
+                       ai_usermode = safe_usermode(mode - '0', true);
        }
        return count;
 }
@@ -886,9 +914,16 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        if (ai_usermode & UM_FIXUP)
                goto fixup;
 
-       if (ai_usermode & UM_SIGNAL)
-               force_sig(SIGBUS, current);
-       else {
+       if (ai_usermode & UM_SIGNAL) {
+               siginfo_t si;
+
+               si.si_signo = SIGBUS;
+               si.si_errno = 0;
+               si.si_code = BUS_ADRALN;
+               si.si_addr = (void __user *)addr;
+
+               force_sig_info(si.si_signo, &si, current);
+       } else {
                /*
                 * We're about to disable the alignment trap and return to
                 * user space.  But if an interrupt occurs before actually
@@ -926,20 +961,11 @@ static int __init alignment_init(void)
                return -ENOMEM;
 #endif
 
-       /*
-        * ARMv6 and later CPUs can perform unaligned accesses for
-        * most single load and store instructions up to word size.
-        * LDM, STM, LDRD and STRD still need to be handled.
-        *
-        * Ignoring the alignment fault is not an option on these
-        * CPUs since we spin re-faulting the instruction without
-        * making any progress.
-        */
-       if (cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U)) {
+       if (cpu_is_v6_unaligned()) {
                cr_alignment &= ~CR_A;
                cr_no_alignment &= ~CR_A;
                set_cr(cr_alignment);
-               ai_usermode = UM_FIXUP;
+               ai_usermode = safe_usermode(ai_usermode, false);
        }
 
        hook_fault_code(1, do_alignment, SIGBUS, BUS_ADRALN,
index 2fee782..91bca35 100644 (file)
@@ -441,7 +441,7 @@ static inline int free_area(unsigned long pfn, unsigned long end, char *s)
 static inline void poison_init_mem(void *s, size_t count)
 {
        u32 *p = (u32 *)s;
-       while ((count = count - 4))
+       for (; count != 0; count -= 4)
                *p++ = 0xe7fddef0;
 }
 
index f8f7ea3..683af3a 100644 (file)
@@ -410,6 +410,7 @@ __arm946_proc_info:
        .long   0x41009460
        .long   0xff00fff0
        .long   0
+       .long   0
        b       __arm946_setup
        .long   cpu_arch_name
        .long   cpu_elf_name
@@ -418,6 +419,6 @@ __arm946_proc_info:
        .long   arm946_processor_functions
        .long   0
        .long   0
-       .long   arm940_cache_fns
+       .long   arm946_cache_fns
        .size   __arm946_proc_info, . - __arm946_proc_info
 
index 4fc6ffc..0bae44e 100644 (file)
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
 
-#define imx_fec_data_entry_single(soc)                                 \
+#define imx_fec_data_entry_single(soc, _devid)                         \
        {                                                               \
+               .devid = _devid,                                        \
                .iobase = soc ## _FEC_BASE_ADDR,                        \
                .irq = soc ## _INT_FEC,                                 \
        }
 
 #ifdef CONFIG_SOC_IMX25
 const struct imx_fec_data imx25_fec_data __initconst =
-       imx_fec_data_entry_single(MX25);
+       imx_fec_data_entry_single(MX25, "imx25-fec");
 #endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_fec_data imx27_fec_data __initconst =
-       imx_fec_data_entry_single(MX27);
+       imx_fec_data_entry_single(MX27, "imx27-fec");
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
 #ifdef CONFIG_SOC_IMX35
+/* i.mx35 has the i.mx27 type fec */
 const struct imx_fec_data imx35_fec_data __initconst =
-       imx_fec_data_entry_single(MX35);
+       imx_fec_data_entry_single(MX35, "imx27-fec");
 #endif
 
 #ifdef CONFIG_SOC_IMX50
+/* i.mx50 has the i.mx25 type fec */
 const struct imx_fec_data imx50_fec_data __initconst =
-       imx_fec_data_entry_single(MX50);
+       imx_fec_data_entry_single(MX50, "imx25-fec");
 #endif
 
 #ifdef CONFIG_SOC_IMX51
+/* i.mx51 has the i.mx27 type fec */
 const struct imx_fec_data imx51_fec_data __initconst =
-       imx_fec_data_entry_single(MX51);
+       imx_fec_data_entry_single(MX51, "imx27-fec");
 #endif
 
 #ifdef CONFIG_SOC_IMX53
+/* i.mx53 has the i.mx25 type fec */
 const struct imx_fec_data imx53_fec_data __initconst =
-       imx_fec_data_entry_single(MX53);
+       imx_fec_data_entry_single(MX53, "imx25-fec");
 #endif
 
 struct platform_device *__init imx_add_fec(
@@ -63,7 +68,7 @@ struct platform_device *__init imx_add_fec(
                },
        };
 
-       return imx_add_platform_device_dmamask("fec", 0,
+       return imx_add_platform_device_dmamask(data->devid, 0,
                        res, ARRAY_SIZE(res),
                        pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
index 2b0fdb2..7fa7e9c 100644 (file)
@@ -14,7 +14,7 @@ struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
                        "imx-dma", -1, NULL, 0, NULL, 0);
 }
 
-struct platform_device __init __maybe_unused *imx_add_imx_sdma(
+struct platform_device __init __maybe_unused *imx_add_imx_sdma(char *name,
        resource_size_t iobase, int irq, struct sdma_platform_data *pdata)
 {
        struct resource res[] = {
@@ -29,6 +29,6 @@ struct platform_device __init __maybe_unused *imx_add_imx_sdma(
                },
        };
 
-       return platform_device_register_resndata(&mxc_ahb_bus, "imx-sdma",
+       return platform_device_register_resndata(&mxc_ahb_bus, name,
                        -1, res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
index cfce8c9..2020d84 100644 (file)
@@ -152,7 +152,7 @@ struct platform_device *__init imx_add_imx_uart_3irq(
                },
        };
 
-       return imx_add_platform_device("imx-uart", data->id, res,
+       return imx_add_platform_device("imx1-uart", data->id, res,
                        ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
 
@@ -172,6 +172,7 @@ struct platform_device *__init imx_add_imx_uart_1irq(
                },
        };
 
-       return imx_add_platform_device("imx-uart", data->id, res, ARRAY_SIZE(res),
-                       pdata, sizeof(*pdata));
+       /* i.mx21 type uart runs on all i.mx except i.mx1 */
+       return imx_add_platform_device("imx21-uart", data->id,
+                       res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
index 6b2940b..5955f5d 100644 (file)
 #include <mach/devices-common.h>
 #include <mach/esdhc.h>
 
-#define imx_sdhci_esdhc_imx_data_entry_single(soc, _id, hwid) \
+#define imx_sdhci_esdhc_imx_data_entry_single(soc, _devid, _id, hwid) \
        {                                                               \
+               .devid = _devid,                                        \
                .id = _id,                                              \
                .iobase = soc ## _ESDHC ## hwid ## _BASE_ADDR,  \
                .irq = soc ## _INT_ESDHC ## hwid,                       \
        }
 
-#define imx_sdhci_esdhc_imx_data_entry(soc, id, hwid)  \
-       [id] = imx_sdhci_esdhc_imx_data_entry_single(soc, id, hwid)
+#define imx_sdhci_esdhc_imx_data_entry(soc, devid, id, hwid)   \
+       [id] = imx_sdhci_esdhc_imx_data_entry_single(soc, devid, id, hwid)
 
 #ifdef CONFIG_SOC_IMX25
 const struct imx_sdhci_esdhc_imx_data
 imx25_sdhci_esdhc_imx_data[] __initconst = {
 #define imx25_sdhci_esdhc_imx_data_entry(_id, _hwid)                   \
-       imx_sdhci_esdhc_imx_data_entry(MX25, _id, _hwid)
+       imx_sdhci_esdhc_imx_data_entry(MX25, "sdhci-esdhc-imx25", _id, _hwid)
        imx25_sdhci_esdhc_imx_data_entry(0, 1),
        imx25_sdhci_esdhc_imx_data_entry(1, 2),
 };
@@ -34,7 +35,7 @@ imx25_sdhci_esdhc_imx_data[] __initconst = {
 const struct imx_sdhci_esdhc_imx_data
 imx35_sdhci_esdhc_imx_data[] __initconst = {
 #define imx35_sdhci_esdhc_imx_data_entry(_id, _hwid)                   \
-       imx_sdhci_esdhc_imx_data_entry(MX35, _id, _hwid)
+       imx_sdhci_esdhc_imx_data_entry(MX35, "sdhci-esdhc-imx35", _id, _hwid)
        imx35_sdhci_esdhc_imx_data_entry(0, 1),
        imx35_sdhci_esdhc_imx_data_entry(1, 2),
        imx35_sdhci_esdhc_imx_data_entry(2, 3),
@@ -45,7 +46,7 @@ imx35_sdhci_esdhc_imx_data[] __initconst = {
 const struct imx_sdhci_esdhc_imx_data
 imx51_sdhci_esdhc_imx_data[] __initconst = {
 #define imx51_sdhci_esdhc_imx_data_entry(_id, _hwid)                   \
-       imx_sdhci_esdhc_imx_data_entry(MX51, _id, _hwid)
+       imx_sdhci_esdhc_imx_data_entry(MX51, "sdhci-esdhc-imx51", _id, _hwid)
        imx51_sdhci_esdhc_imx_data_entry(0, 1),
        imx51_sdhci_esdhc_imx_data_entry(1, 2),
        imx51_sdhci_esdhc_imx_data_entry(2, 3),
@@ -57,7 +58,7 @@ imx51_sdhci_esdhc_imx_data[] __initconst = {
 const struct imx_sdhci_esdhc_imx_data
 imx53_sdhci_esdhc_imx_data[] __initconst = {
 #define imx53_sdhci_esdhc_imx_data_entry(_id, _hwid)                   \
-       imx_sdhci_esdhc_imx_data_entry(MX53, _id, _hwid)
+       imx_sdhci_esdhc_imx_data_entry(MX53, "sdhci-esdhc-imx53", _id, _hwid)
        imx53_sdhci_esdhc_imx_data_entry(0, 1),
        imx53_sdhci_esdhc_imx_data_entry(1, 2),
        imx53_sdhci_esdhc_imx_data_entry(2, 3),
@@ -65,6 +66,11 @@ imx53_sdhci_esdhc_imx_data[] __initconst = {
 };
 #endif /* ifdef CONFIG_SOC_IMX53 */
 
+static const struct esdhc_platform_data default_esdhc_pdata __initconst = {
+       .wp_type = ESDHC_WP_NONE,
+       .cd_type = ESDHC_CD_NONE,
+};
+
 struct platform_device *__init imx_add_sdhci_esdhc_imx(
                const struct imx_sdhci_esdhc_imx_data *data,
                const struct esdhc_platform_data *pdata)
@@ -81,6 +87,13 @@ struct platform_device *__init imx_add_sdhci_esdhc_imx(
                },
        };
 
-       return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
+       /*
+        * If machine does not provide pdata, use the default one
+        * which means no WP/CD support
+        */
+       if (!pdata)
+               pdata = &default_esdhc_pdata;
+
+       return imx_add_platform_device(data->devid, data->id, res,
                        ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
index 91fc7cd..e4dde91 100644 (file)
 #define UART_PADDR     MX51_UART1_BASE_ADDR
 #endif
 
+/* iMX50/53 have same addresses, but not iMX51 */
+#if defined(CONFIG_SOC_IMX50) || defined(CONFIG_SOC_IMX53)
+#ifdef UART_PADDR
+#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
+#endif
+#define UART_PADDR     MX53_UART1_BASE_ADDR
+#endif
+
 #define UART_VADDR     IMX_IO_ADDRESS(UART_PADDR)
 
                .macro  addruart, rp, rv
index bf93820..524538a 100644 (file)
@@ -30,6 +30,7 @@ static inline struct platform_device *imx_add_platform_device(
 
 #include <linux/fec.h>
 struct imx_fec_data {
+       const char *devid;
        resource_size_t iobase;
        resource_size_t irq;
 };
@@ -276,6 +277,7 @@ struct platform_device *__init imx_add_mxc_w1(
 
 #include <mach/esdhc.h>
 struct imx_sdhci_esdhc_imx_data {
+       const char *devid;
        int id;
        resource_size_t iobase;
        resource_size_t irq;
@@ -297,5 +299,5 @@ struct platform_device *__init imx_add_spi_imx(
                const struct spi_imx_master *pdata);
 
 struct platform_device *imx_add_imx_dma(void);
-struct platform_device *imx_add_imx_sdma(
+struct platform_device *imx_add_imx_sdma(char *name,
        resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
index ef77515..233d0a5 100644 (file)
@@ -60,7 +60,8 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan)
 
 static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
 {
-       return !strcmp(dev_name(chan->device->dev), "imx-sdma") ||
+       return !strcmp(dev_name(chan->device->dev), "imx31-sdma") ||
+               !strcmp(dev_name(chan->device->dev), "imx35-sdma") ||
                !strcmp(dev_name(chan->device->dev), "imx-dma");
 }
 
index 86003f4..aaf9748 100644 (file)
 #ifndef __ASM_ARCH_IMX_ESDHC_H
 #define __ASM_ARCH_IMX_ESDHC_H
 
+enum wp_types {
+       ESDHC_WP_NONE,          /* no WP, neither controller nor gpio */
+       ESDHC_WP_CONTROLLER,    /* mmc controller internal WP */
+       ESDHC_WP_GPIO,          /* external gpio pin for WP */
+};
+
+enum cd_types {
+       ESDHC_CD_NONE,          /* no CD, neither controller nor gpio */
+       ESDHC_CD_CONTROLLER,    /* mmc controller internal CD */
+       ESDHC_CD_GPIO,          /* external gpio pin for CD */
+       ESDHC_CD_PERMANENT,     /* no CD, card permanently wired to host */
+};
+
 /**
- * struct esdhc_platform_data - optional platform data for esdhc on i.MX
+ * struct esdhc_platform_data - platform data for esdhc on i.MX
  *
- * strongly recommended for i.MX25/35, not needed for other variants
+ * ESDHC_WP(CD)_CONTROLLER type is not available on i.MX25/35.
  *
- * @wp_gpio:   gpio for write_protect (-EINVAL if unused)
- * @cd_gpio:   gpio for card_detect interrupt (-EINVAL if unused)
+ * @wp_gpio:   gpio for write_protect
+ * @cd_gpio:   gpio for card_detect interrupt
+ * @wp_type:   type of write_protect method (see wp_types enum above)
+ * @cd_type:   type of card_detect method (see cd_types enum above)
  */
 
 struct esdhc_platform_data {
        unsigned int wp_gpio;
        unsigned int cd_gpio;
+       enum wp_types wp_type;
+       enum cd_types cd_type;
 };
 #endif /* __ASM_ARCH_IMX_ESDHC_H */
index 9440b9e..5408fd1 100644 (file)
@@ -30,6 +30,9 @@
 #define MX53_SDHC_PAD_CTRL     (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
                                PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_HIGH | \
                                PAD_CTL_SRE_FAST)
+#define PAD_CTRL_I2C   (PAD_CTL_SRE_FAST | PAD_CTL_ODE | PAD_CTL_PKE | \
+                       PAD_CTL_PUE | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP \
+                       | PAD_CTL_HYS)
 
 #define _MX53_PAD_GPIO_19__KPP_COL_5           IOMUX_PAD(0x348, 0x20, 0, 0x840, 0, 0)
 #define _MX53_PAD_GPIO_19__GPIO4_5             IOMUX_PAD(0x348, 0x20, 1, 0x0, 0, 0)
 #define MX53_PAD_KEY_COL3__GPIO4_12            (_MX53_PAD_KEY_COL3__GPIO4_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL3__USBOH3_H2_DP                (_MX53_PAD_KEY_COL3__USBOH3_H2_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL3__SPDIF_IN1           (_MX53_PAD_KEY_COL3__SPDIF_IN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__I2C2_SCL            (_MX53_PAD_KEY_COL3__I2C2_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__I2C2_SCL            (_MX53_PAD_KEY_COL3__I2C2_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_KEY_COL3__ECSPI1_SS3          (_MX53_PAD_KEY_COL3__ECSPI1_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL3__FEC_CRS             (_MX53_PAD_KEY_COL3__FEC_CRS | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK            (_MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW3__GPIO4_13            (_MX53_PAD_KEY_ROW3__GPIO4_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW3__USBOH3_H2_DM                (_MX53_PAD_KEY_ROW3__USBOH3_H2_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK            (_MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__I2C2_SDA            (_MX53_PAD_KEY_ROW3__I2C2_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__I2C2_SDA            (_MX53_PAD_KEY_ROW3__I2C2_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_KEY_ROW3__OSC32K_32K_OUT              (_MX53_PAD_KEY_ROW3__OSC32K_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW3__CCM_PLL4_BYP                (_MX53_PAD_KEY_ROW3__CCM_PLL4_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0         (_MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT8__KPP_COL_7          (_MX53_PAD_CSI0_DAT8__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT8__ECSPI2_SCLK                (_MX53_PAD_CSI0_DAT8__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC            (_MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__I2C1_SDA           (_MX53_PAD_CSI0_DAT8__I2C1_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__I2C1_SDA           (_MX53_PAD_CSI0_DAT8__I2C1_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37           (_MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT8__TPIU_TRACE_5               (_MX53_PAD_CSI0_DAT8__TPIU_TRACE_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9               (_MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT9__KPP_ROW_7          (_MX53_PAD_CSI0_DAT9__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT9__ECSPI2_MOSI                (_MX53_PAD_CSI0_DAT9__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR           (_MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__I2C1_SCL           (_MX53_PAD_CSI0_DAT9__I2C1_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__I2C1_SCL           (_MX53_PAD_CSI0_DAT9__I2C1_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38           (_MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT9__TPIU_TRACE_6               (_MX53_PAD_CSI0_DAT9__TPIU_TRACE_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10             (_MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK              (_MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS             (_MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_EB2__ECSPI1_SS0           (_MX53_PAD_EIM_EB2__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__I2C2_SCL             (_MX53_PAD_EIM_EB2__I2C2_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__I2C2_SCL             (_MX53_PAD_EIM_EB2__I2C2_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_EIM_D16__EMI_WEIM_D_16                (_MX53_PAD_EIM_D16__EMI_WEIM_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D16__GPIO3_16             (_MX53_PAD_EIM_D16__GPIO3_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D16__IPU_DI0_PIN5         (_MX53_PAD_EIM_D16__IPU_DI0_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK           (_MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D16__ECSPI1_SCLK          (_MX53_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__I2C2_SDA             (_MX53_PAD_EIM_D16__I2C2_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__I2C2_SDA             (_MX53_PAD_EIM_D16__I2C2_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_EIM_D17__EMI_WEIM_D_17                (_MX53_PAD_EIM_D17__EMI_WEIM_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D17__GPIO3_17             (_MX53_PAD_EIM_D17__GPIO3_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D17__IPU_DI0_PIN6         (_MX53_PAD_EIM_D17__IPU_DI0_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN           (_MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D17__ECSPI1_MISO          (_MX53_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__I2C3_SCL             (_MX53_PAD_EIM_D17__I2C3_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__I2C3_SCL             (_MX53_PAD_EIM_D17__I2C3_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_EIM_D18__EMI_WEIM_D_18                (_MX53_PAD_EIM_D18__EMI_WEIM_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D18__GPIO3_18             (_MX53_PAD_EIM_D18__GPIO3_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D18__IPU_DI0_PIN7         (_MX53_PAD_EIM_D18__IPU_DI0_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO           (_MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D18__ECSPI1_MOSI          (_MX53_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__I2C3_SDA             (_MX53_PAD_EIM_D18__I2C3_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__I2C3_SDA             (_MX53_PAD_EIM_D18__I2C3_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_EIM_D18__IPU_DI1_D0_CS                (_MX53_PAD_EIM_D18__IPU_DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D19__EMI_WEIM_D_19                (_MX53_PAD_EIM_D19__EMI_WEIM_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D19__GPIO3_19             (_MX53_PAD_EIM_D19__GPIO3_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D21__IPU_DI0_PIN17                (_MX53_PAD_EIM_D21__IPU_DI0_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK           (_MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D21__CSPI_SCLK            (_MX53_PAD_EIM_D21__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__I2C1_SCL             (_MX53_PAD_EIM_D21__I2C1_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__I2C1_SCL             (_MX53_PAD_EIM_D21__I2C1_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_EIM_D21__USBOH3_USBOTG_OC             (_MX53_PAD_EIM_D21__USBOH3_USBOTG_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D22__EMI_WEIM_D_22                (_MX53_PAD_EIM_D22__EMI_WEIM_D_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D22__GPIO3_22             (_MX53_PAD_EIM_D22__GPIO3_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D28__UART2_CTS            (_MX53_PAD_EIM_D28__UART2_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO           (_MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D28__CSPI_MOSI            (_MX53_PAD_EIM_D28__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__I2C1_SDA             (_MX53_PAD_EIM_D28__I2C1_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__I2C1_SDA             (_MX53_PAD_EIM_D28__I2C1_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_EIM_D28__IPU_EXT_TRIG         (_MX53_PAD_EIM_D28__IPU_EXT_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D28__IPU_DI0_PIN13                (_MX53_PAD_EIM_D28__IPU_DI0_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D29__EMI_WEIM_D_29                (_MX53_PAD_EIM_D29__EMI_WEIM_D_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_9__SCC_FAIL_STATE                (_MX53_PAD_GPIO_9__SCC_FAIL_STATE | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_3__ESAI1_HCKR            (_MX53_PAD_GPIO_3__ESAI1_HCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_3__GPIO1_3               (_MX53_PAD_GPIO_3__GPIO1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__I2C3_SCL              (_MX53_PAD_GPIO_3__I2C3_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__I2C3_SCL              (_MX53_PAD_GPIO_3__I2C3_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_GPIO_3__DPLLIP1_TOG_EN                (_MX53_PAD_GPIO_3__DPLLIP1_TOG_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_3__CCM_CLKO2             (_MX53_PAD_GPIO_3__CCM_CLKO2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0            (_MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_3__MLB_MLBCLK            (_MX53_PAD_GPIO_3__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_6__ESAI1_SCKT            (_MX53_PAD_GPIO_6__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_6__GPIO1_6               (_MX53_PAD_GPIO_6__GPIO1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__I2C3_SDA              (_MX53_PAD_GPIO_6__I2C3_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__I2C3_SDA              (_MX53_PAD_GPIO_6__I2C3_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_GPIO_6__CCM_CCM_OUT_0         (_MX53_PAD_GPIO_6__CCM_CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_6__CSU_CSU_INT_DEB               (_MX53_PAD_GPIO_6__CSU_CSU_INT_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1            (_MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_5__CCM_CLKO              (_MX53_PAD_GPIO_5__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2           (_MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4            (_MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__I2C3_SCL              (_MX53_PAD_GPIO_5__I2C3_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__I2C3_SCL              (_MX53_PAD_GPIO_5__I2C3_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_GPIO_5__CCM_PLL1_BYP          (_MX53_PAD_GPIO_5__CCM_PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_7__ESAI1_TX4_RX1         (_MX53_PAD_GPIO_7__ESAI1_TX4_RX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_7__GPIO1_7               (_MX53_PAD_GPIO_7__GPIO1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT             (_MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1         (_MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_16__SPDIF_IN1            (_MX53_PAD_GPIO_16__SPDIF_IN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__I2C3_SDA             (_MX53_PAD_GPIO_16__I2C3_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__I2C3_SDA             (_MX53_PAD_GPIO_16__I2C3_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
 #define MX53_PAD_GPIO_16__SJC_DE_B             (_MX53_PAD_GPIO_16__SJC_DE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_17__ESAI1_TX0            (_MX53_PAD_GPIO_17__ESAI1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_17__GPIO7_12             (_MX53_PAD_GPIO_17__GPIO7_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
index f495c87..3a39428 100644 (file)
@@ -48,12 +48,10 @@ struct sdma_script_start_addrs {
 /**
  * struct sdma_platform_data - platform specific data for SDMA engine
  *
- * @sdma_version       The version of this SDMA engine
  * @fw_name            The firmware name
  * @script_addrs       SDMA scripts addresses in SDMA ROM
  */
 struct sdma_platform_data {
-       int sdma_version;
        char *fw_name;
        struct sdma_script_start_addrs *script_addrs;
 };
index 6e6735f..bb8f4a6 100644 (file)
@@ -13,6 +13,7 @@ config ARCH_OMAP1
        bool "TI OMAP1"
        select CLKDEV_LOOKUP
        select CLKSRC_MMIO
+       select GENERIC_IRQ_CHIP
        help
          "Systems based on omap7xx, omap15xx or omap16xx"
 
index d1c916f..dc562a5 100644 (file)
 
 #define OMAP36XX_DMA_UART4_TX          81      /* S_DMA_80 */
 #define OMAP36XX_DMA_UART4_RX          82      /* S_DMA_81 */
+
+/* Only for AM35xx */
+#define AM35XX_DMA_UART4_TX            54
+#define AM35XX_DMA_UART4_RX            55
+
 /*----------------------------------------------------------------------------*/
 
 #define OMAP1_DMA_TOUT_IRQ             (1 << 0)
index 926d25c..30e1071 100644 (file)
 #define INT_35XX_EMAC_C0_TX_PULSE_IRQ  69
 #define INT_35XX_EMAC_C0_MISC_PULSE_IRQ        70
 #define INT_35XX_USBOTG_IRQ            71
+#define INT_35XX_UART4                 84
 #define INT_35XX_CCDC_VD0_IRQ          88
 #define INT_35XX_CCDC_VD1_IRQ          92
 #define INT_35XX_CCDC_VD2_IRQ          93
index 2723f91..de3b10c 100644 (file)
@@ -56,6 +56,9 @@
 #define TI816X_UART2_BASE      0x48022000
 #define TI816X_UART3_BASE      0x48024000
 
+/* AM3505/3517 UART4 */
+#define AM35XX_UART4_BASE      0x4809E000      /* Only on AM3505/3517 */
+
 /* External port on Zoom2/3 */
 #define ZOOM_UART_BASE         0x10000000
 #define ZOOM_UART_VIRT         0xfa400000
index c60737c..79e7fed 100644 (file)
@@ -423,9 +423,6 @@ static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, u32 da,
 {
        unsigned int i;
        struct scatterlist *sg;
-       void *va;
-
-       va = phys_to_virt(pa);
 
        for_each_sg(sgt->sgl, sg, sgt->nents, i) {
                unsigned bytes;
index 3b3776d..fff68d0 100644 (file)
@@ -910,7 +910,7 @@ omapl138_case_a3    MACH_OMAPL138_CASE_A3   OMAPL138_CASE_A3        3280
 uemd                   MACH_UEMD               UEMD                    3281
 ccwmx51mut             MACH_CCWMX51MUT         CCWMX51MUT              3282
 rockhopper             MACH_ROCKHOPPER         ROCKHOPPER              3283
-nookcolor              MACH_NOOKCOLOR          NOOKCOLOR               3284
+encore                 MACH_ENCORE             ENCORE                  3284
 hkdkc100               MACH_HKDKC100           HKDKC100                3285
 ts42xx                 MACH_TS42XX             TS42XX                  3286
 aebl                   MACH_AEBL               AEBL                    3287
index e9d689b..197e96f 100644 (file)
@@ -10,6 +10,7 @@ config AVR32
        select GENERIC_IRQ_PROBE
        select HARDIRQS_SW_RESEND
        select GENERIC_IRQ_SHOW
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG
        help
          AVR32 is a high-performance 32-bit RISC microprocessor core,
          designed for cost-sensitive embedded applications, with particular
index 8502653..466af40 100644 (file)
@@ -158,7 +158,7 @@ static int sync_serial_open(struct inode *inode, struct file *file);
 static int sync_serial_release(struct inode *inode, struct file *file);
 static unsigned int sync_serial_poll(struct file *filp, poll_table *wait);
 
-static int sync_serial_ioctl(struct file *file,
+static long sync_serial_ioctl(struct file *file,
        unsigned int cmd, unsigned long arg);
 static ssize_t sync_serial_write(struct file *file, const char *buf,
        size_t count, loff_t *ppos);
@@ -625,11 +625,11 @@ static int sync_serial_open(struct inode *inode, struct file *file)
                        *R_IRQ_MASK1_SET = 1 << port->data_avail_bit;
                DEBUG(printk(KERN_DEBUG "sser%d rec started\n", dev));
        }
-       ret = 0;
+       err = 0;
        
 out:
        mutex_unlock(&sync_serial_mutex);
-       return ret;
+       return err;
 }
 
 static int sync_serial_release(struct inode *inode, struct file *file)
index 907cfb5..ba0e596 100644 (file)
@@ -20,6 +20,9 @@
 #define crisv10_mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
 #define crisv10_unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
 
+extern void kgdb_init(void);
+extern void breakpoint(void);
+
 /* don't use set_int_vector, it bypasses the linux interrupt handlers. it is
  * global just so that the kernel gdb can use it.
  */
index 29b74a1..332f19c 100644 (file)
@@ -11,8 +11,6 @@
 
 #ifdef __KERNEL__
 
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-
 #ifndef __ASSEMBLY__
 #include <asm/types.h>
 #include <asm/processor.h>
@@ -67,8 +65,10 @@ struct thread_info {
 
 #define init_thread_info       (init_thread_union.thread_info)
 
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 /* thread information allocation */
-#define alloc_thread_info(tsk, node) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define alloc_thread_info_node(tsk, node)      \
+       ((struct thread_info *) __get_free_pages(GFP_KERNEL, 1))
 #define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
 
 #endif /* !__ASSEMBLY__ */
index cb884e4..bad27a6 100644 (file)
@@ -7,6 +7,7 @@ config FRV
        select HAVE_PERF_EVENTS
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_IRQ_SHOW
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG
 
 config ZONE_DMA
        bool
index c42c83d..4fb63a3 100644 (file)
@@ -133,13 +133,7 @@ void pgd_dtor(void *pgd)
 
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       pgd_t *pgd;
-
-       pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
-       if (!pgd)
-               return pgd;
-
-       return pgd;
+       return quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
 }
 
 void pgd_free(struct mm_struct *mm, pgd_t *pgd)
index 137b277..1248547 100644 (file)
@@ -27,6 +27,8 @@ config IA64
        select GENERIC_PENDING_IRQ if SMP
        select IRQ_PER_CPU
        select GENERIC_IRQ_SHOW
+       select ARCH_WANT_OPTIONAL_GPIOLIB
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG
        default y
        help
          The Itanium Processor Family is Intel's 64-bit successor to
@@ -89,6 +91,9 @@ config GENERIC_TIME_VSYSCALL
 config HAVE_SETUP_PER_CPU_AREA
        def_bool y
 
+config GENERIC_GPIO
+       def_bool y
+
 config DMI
        bool
        default y
index 7e81966..47afcc6 100644 (file)
@@ -172,7 +172,7 @@ static const struct net_device_ops simeth_netdev_ops = {
        .ndo_stop               = simeth_close,
        .ndo_start_xmit         = simeth_tx,
        .ndo_get_stats          = simeth_get_stats,
-       .ndo_set_multicast_list = set_multicast_list, /* not yet used */
+       .ndo_set_rx_mode        = set_multicast_list, /* not yet used */
 
 };
 
diff --git a/arch/ia64/include/asm/gpio.h b/arch/ia64/include/asm/gpio.h
new file mode 100644 (file)
index 0000000..590a20d
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Generic GPIO API implementation for IA-64.
+ *
+ * A stright copy of that for PowerPC which was:
+ *
+ * Copyright (c) 2007-2008  MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.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.
+ */
+
+#ifndef _ASM_IA64_GPIO_H
+#define _ASM_IA64_GPIO_H
+
+#include <linux/errno.h>
+#include <asm-generic/gpio.h>
+
+#ifdef CONFIG_GPIOLIB
+
+/*
+ * We don't (yet) implement inlined/rapid versions for on-chip gpios.
+ * Just call gpiolib.
+ */
+static inline int gpio_get_value(unsigned int gpio)
+{
+       return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned int gpio, int value)
+{
+       __gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned int gpio)
+{
+       return __gpio_cansleep(gpio);
+}
+
+static inline int gpio_to_irq(unsigned int gpio)
+{
+       return __gpio_to_irq(gpio);
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+       return -EINVAL;
+}
+
+#endif /* CONFIG_GPIOLIB */
+
+#endif /* _ASM_IA64_GPIO_H */
index 6fc03af..c38d22e 100644 (file)
@@ -156,7 +156,7 @@ prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name,      \
 #define STUB_SET_VARIABLE(prefix, adjust_arg)                                 \
 static efi_status_t                                                           \
 prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor,                \
-                      unsigned long attr, unsigned long data_size,            \
+                      u32 attr, unsigned long data_size,                      \
                       void *data)                                             \
 {                                                                             \
        struct ia64_fpreg fr[6];                                               \
index 284cd37..9e8ee9d 100644 (file)
@@ -6,6 +6,7 @@ config M68K
        select GENERIC_ATOMIC64 if MMU
        select HAVE_GENERIC_HARDIRQS if !MMU
        select GENERIC_IRQ_SHOW if !MMU
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
 
 config RWSEM_GENERIC_SPINLOCK
        bool
index 16539b1..13e20bb 100644 (file)
@@ -372,12 +372,6 @@ config AMIGA_PCMCIA
          Include support in the kernel for pcmcia on Amiga 1200 and Amiga
          600. If you intend to use pcmcia cards say Y; otherwise say N.
 
-config STRAM_PROC
-       bool "ST-RAM statistics in /proc"
-       depends on ATARI
-       help
-         Say Y here to report ST-RAM usage statistics in /proc/stram.
-
 config HEARTBEAT
        bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
        default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
index dd0447d..99449fb 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/string.h>
 #include <linux/module.h>
 
+#include <asm/atomic.h>
 #include <asm/page.h>
 #include <asm/amigahw.h>
 
@@ -23,111 +24,100 @@ unsigned long amiga_chip_size;
 EXPORT_SYMBOL(amiga_chip_size);
 
 static struct resource chipram_res = {
-    .name = "Chip RAM", .start = CHIP_PHYSADDR
+       .name = "Chip RAM", .start = CHIP_PHYSADDR
 };
-static unsigned long chipavail;
+static atomic_t chipavail;
 
 
 void __init amiga_chip_init(void)
 {
-    if (!AMIGAHW_PRESENT(CHIP_RAM))
-       return;
+       if (!AMIGAHW_PRESENT(CHIP_RAM))
+               return;
 
-    chipram_res.end = amiga_chip_size-1;
-    request_resource(&iomem_resource, &chipram_res);
+       chipram_res.end = CHIP_PHYSADDR + amiga_chip_size - 1;
+       request_resource(&iomem_resource, &chipram_res);
 
-    chipavail = amiga_chip_size;
+       atomic_set(&chipavail, amiga_chip_size);
 }
 
 
 void *amiga_chip_alloc(unsigned long size, const char *name)
 {
-    struct resource *res;
+       struct resource *res;
+       void *p;
 
-    /* round up */
-    size = PAGE_ALIGN(size);
+       res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+       if (!res)
+               return NULL;
 
-#ifdef DEBUG
-    printk("amiga_chip_alloc: allocate %ld bytes\n", size);
-#endif
-    res = kzalloc(sizeof(struct resource), GFP_KERNEL);
-    if (!res)
-       return NULL;
-    res->name = name;
+       res->name = name;
+       p = amiga_chip_alloc_res(size, res);
+       if (!p) {
+               kfree(res);
+               return NULL;
+       }
 
-    if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) {
-       kfree(res);
-       return NULL;
-    }
-    chipavail -= size;
-#ifdef DEBUG
-    printk("amiga_chip_alloc: returning %lx\n", res->start);
-#endif
-    return (void *)ZTWO_VADDR(res->start);
+       return p;
 }
 EXPORT_SYMBOL(amiga_chip_alloc);
 
 
-    /*
-     *  Warning:
-     *  amiga_chip_alloc_res is meant only for drivers that need to allocate
-     *  Chip RAM before kmalloc() is functional. As a consequence, those
-      drivers must not free that Chip RAM afterwards.
-     */
+       /*
+        *  Warning:
+        *  amiga_chip_alloc_res is meant only for drivers that need to
+        *  allocate Chip RAM before kmalloc() is functional. As a consequence,
+        *  those drivers must not free that Chip RAM afterwards.
+        */
 
-void * __init amiga_chip_alloc_res(unsigned long size, struct resource *res)
+void *amiga_chip_alloc_res(unsigned long size, struct resource *res)
 {
-    unsigned long start;
-
-    /* round up */
-    size = PAGE_ALIGN(size);
-    /* dmesg into chipmem prefers memory at the safe end */
-    start = CHIP_PHYSADDR + chipavail - size;
-
-#ifdef DEBUG
-    printk("amiga_chip_alloc_res: allocate %ld bytes\n", size);
-#endif
-    if (allocate_resource(&chipram_res, res, size, start, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) {
-       printk("amiga_chip_alloc_res: first alloc failed!\n");
-       if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0)
-           return NULL;
-    }
-    chipavail -= size;
-#ifdef DEBUG
-    printk("amiga_chip_alloc_res: returning %lx\n", res->start);
-#endif
-    return (void *)ZTWO_VADDR(res->start);
+       int error;
+
+       /* round up */
+       size = PAGE_ALIGN(size);
+
+       pr_debug("amiga_chip_alloc_res: allocate %lu bytes\n", size);
+       error = allocate_resource(&chipram_res, res, size, 0, UINT_MAX,
+                                 PAGE_SIZE, NULL, NULL);
+       if (error < 0) {
+               pr_err("amiga_chip_alloc_res: allocate_resource() failed %d!\n",
+                      error);
+               return NULL;
+       }
+
+       atomic_sub(size, &chipavail);
+       pr_debug("amiga_chip_alloc_res: returning %pR\n", res);
+       return (void *)ZTWO_VADDR(res->start);
 }
 
 void amiga_chip_free(void *ptr)
 {
-    unsigned long start = ZTWO_PADDR(ptr);
-    struct resource **p, *res;
-    unsigned long size;
-
-    for (p = &chipram_res.child; (res = *p); p = &res->sibling) {
-       if (res->start != start)
-           continue;
-       *p = res->sibling;
-       size = res->end-start;
-#ifdef DEBUG
-       printk("amiga_chip_free: free %ld bytes at %p\n", size, ptr);
-#endif
-       chipavail += size;
+       unsigned long start = ZTWO_PADDR(ptr);
+       struct resource *res;
+       unsigned long size;
+
+       res = lookup_resource(&chipram_res, start);
+       if (!res) {
+               pr_err("amiga_chip_free: trying to free nonexistent region at "
+                      "%p\n", ptr);
+               return;
+       }
+
+       size = resource_size(res);
+       pr_debug("amiga_chip_free: free %lu bytes at %p\n", size, ptr);
+       atomic_add(size, &chipavail);
+       release_resource(res);
        kfree(res);
-       return;
-    }
-    printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr);
 }
 EXPORT_SYMBOL(amiga_chip_free);
 
 
 unsigned long amiga_chip_avail(void)
 {
-#ifdef DEBUG
-       printk("amiga_chip_avail : %ld bytes\n", chipavail);
-#endif
-       return chipavail;
+       unsigned long n = atomic_read(&chipavail);
+
+       pr_debug("amiga_chip_avail : %lu bytes\n", n);
+       return n;
 }
 EXPORT_SYMBOL(amiga_chip_avail);
 
index 6ec3b7f..0810c8d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/m68k/atari/stram.c: Functions for ST-RAM allocations
+ * Functions for ST-RAM allocations
  *
  * Copyright 1994-97 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
  *
 #include <asm/atari_stram.h>
 #include <asm/io.h>
 
-#undef DEBUG
-
-#ifdef DEBUG
-#define        DPRINTK(fmt,args...) printk( fmt, ##args )
-#else
-#define DPRINTK(fmt,args...)
-#endif
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_STRAM_PROC)
-/* abbrev for the && above... */
-#define DO_PROC
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#endif
 
 /*
- * ++roman:
- *
- * New version of ST-Ram buffer allocation. Instead of using the
- * 1 MB - 4 KB that remain when the ST-Ram chunk starts at $1000
- * (1 MB granularity!), such buffers are reserved like this:
- *
- *  - If the kernel resides in ST-Ram anyway, we can take the buffer
- *    from behind the current kernel data space the normal way
- *    (incrementing start_mem).
- *
- *  - If the kernel is in TT-Ram, stram_init() initializes start and
- *    end of the available region. Buffers are allocated from there
- *    and mem_init() later marks the such used pages as reserved.
- *    Since each TT-Ram chunk is at least 4 MB in size, I hope there
- *    won't be an overrun of the ST-Ram region by normal kernel data
- *    space.
- *
- * For that, ST-Ram may only be allocated while kernel initialization
- * is going on, or exactly: before mem_init() is called. There is also
- * no provision now for freeing ST-Ram buffers. It seems that isn't
- * really needed.
- *
+ * The ST-RAM allocator allocates memory from a pool of reserved ST-RAM of
+ * configurable size, set aside on ST-RAM init.
+ * As long as this pool is not exhausted, allocation of real ST-RAM can be
+ * guaranteed.
  */
 
-/* Start and end (virtual) of ST-RAM */
-static void *stram_start, *stram_end;
-
-/* set after memory_init() executed and allocations via start_mem aren't
- * possible anymore */
-static int mem_init_done;
-
 /* set if kernel is in ST-RAM */
 static int kernel_in_stram;
 
-typedef struct stram_block {
-       struct stram_block *next;
-       void *start;
-       unsigned long size;
-       unsigned flags;
-       const char *owner;
-} BLOCK;
-
-/* values for flags field */
-#define BLOCK_FREE     0x01    /* free structure in the BLOCKs pool */
-#define BLOCK_KMALLOCED        0x02    /* structure allocated by kmalloc() */
-#define BLOCK_GFP      0x08    /* block allocated with __get_dma_pages() */
+static struct resource stram_pool = {
+       .name = "ST-RAM Pool"
+};
 
-/* list of allocated blocks */
-static BLOCK *alloc_list;
+static unsigned long pool_size = 1024*1024;
 
-/* We can't always use kmalloc() to allocate BLOCK structures, since
- * stram_alloc() can be called rather early. So we need some pool of
- * statically allocated structures. 20 of them is more than enough, so in most
- * cases we never should need to call kmalloc(). */
-#define N_STATIC_BLOCKS        20
-static BLOCK static_blocks[N_STATIC_BLOCKS];
 
-/***************************** Prototypes *****************************/
+static int __init atari_stram_setup(char *arg)
+{
+       if (!MACH_IS_ATARI)
+               return 0;
 
-static BLOCK *add_region( void *addr, unsigned long size );
-static BLOCK *find_region( void *addr );
-static int remove_region( BLOCK *block );
+       pool_size = memparse(arg, NULL);
+       return 0;
+}
 
-/************************* End of Prototypes **************************/
+early_param("stram_pool", atari_stram_setup);
 
-\f
-/* ------------------------------------------------------------------------ */
-/*                                                        Public Interface                                                             */
-/* ------------------------------------------------------------------------ */
 
 /*
  * This init function is called very early by atari/config.c
@@ -123,25 +67,23 @@ static int remove_region( BLOCK *block );
 void __init atari_stram_init(void)
 {
        int i;
+       void *stram_start;
 
-       /* initialize static blocks */
-       for( i = 0; i < N_STATIC_BLOCKS; ++i )
-               static_blocks[i].flags = BLOCK_FREE;
-
-       /* determine whether kernel code resides in ST-RAM (then ST-RAM is the
-        * first memory block at virtual 0x0) */
+       /*
+        * determine whether kernel code resides in ST-RAM
+        * (then ST-RAM is the first memory block at virtual 0x0)
+        */
        stram_start = phys_to_virt(0);
        kernel_in_stram = (stram_start == 0);
 
-       for( i = 0; i < m68k_num_memory; ++i ) {
+       for (i = 0; i < m68k_num_memory; ++i) {
                if (m68k_memory[i].addr == 0) {
-                       /* skip first 2kB or page (supervisor-only!) */
-                       stram_end = stram_start + m68k_memory[i].size;
                        return;
                }
        }
+
        /* Should never come here! (There is always ST-Ram!) */
-       panic( "atari_stram_init: no ST-RAM found!" );
+       panic("atari_stram_init: no ST-RAM found!");
 }
 
 
@@ -151,226 +93,68 @@ void __init atari_stram_init(void)
  */
 void __init atari_stram_reserve_pages(void *start_mem)
 {
-       /* always reserve first page of ST-RAM, the first 2 kB are
-        * supervisor-only! */
+       /*
+        * always reserve first page of ST-RAM, the first 2 KiB are
+        * supervisor-only!
+        */
        if (!kernel_in_stram)
                reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
 
-}
+       stram_pool.start = (resource_size_t)alloc_bootmem_low_pages(pool_size);
+       stram_pool.end = stram_pool.start + pool_size - 1;
+       request_resource(&iomem_resource, &stram_pool);
 
-void atari_stram_mem_init_hook (void)
-{
-       mem_init_done = 1;
+       pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
+                pool_size, &stram_pool);
 }
 
 
-/*
- * This is main public interface: somehow allocate a ST-RAM block
- *
- *  - If we're before mem_init(), we have to make a static allocation. The
- *    region is taken in the kernel data area (if the kernel is in ST-RAM) or
- *    from the start of ST-RAM (if the kernel is in TT-RAM) and added to the
- *    rsvd_stram_* region. The ST-RAM is somewhere in the middle of kernel
- *    address space in the latter case.
- *
- *  - If mem_init() already has been called, try with __get_dma_pages().
- *    This has the disadvantage that it's very hard to get more than 1 page,
- *    and it is likely to fail :-(
- *
- */
-void *atari_stram_alloc(long size, const char *owner)
+void *atari_stram_alloc(unsigned long size, const char *owner)
 {
-       void *addr = NULL;
-       BLOCK *block;
-       int flags;
-
-       DPRINTK("atari_stram_alloc(size=%08lx,owner=%s)\n", size, owner);
-
-       if (!mem_init_done)
-               return alloc_bootmem_low(size);
-       else {
-               /* After mem_init(): can only resort to __get_dma_pages() */
-               addr = (void *)__get_dma_pages(GFP_KERNEL, get_order(size));
-               flags = BLOCK_GFP;
-               DPRINTK( "atari_stram_alloc: after mem_init, "
-                                "get_pages=%p\n", addr );
+       struct resource *res;
+       int error;
+
+       pr_debug("atari_stram_alloc: allocate %lu bytes\n", size);
+
+       /* round up */
+       size = PAGE_ALIGN(size);
+
+       res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+       if (!res)
+               return NULL;
+
+       res->name = owner;
+       error = allocate_resource(&stram_pool, res, size, 0, UINT_MAX,
+                                 PAGE_SIZE, NULL, NULL);
+       if (error < 0) {
+               pr_err("atari_stram_alloc: allocate_resource() failed %d!\n",
+                      error);
+               kfree(res);
+               return NULL;
        }
 
-       if (addr) {
-               if (!(block = add_region( addr, size ))) {
-                       /* out of memory for BLOCK structure :-( */
-                       DPRINTK( "atari_stram_alloc: out of mem for BLOCK -- "
-                                        "freeing again\n" );
-                       free_pages((unsigned long)addr, get_order(size));
-                       return( NULL );
-               }
-               block->owner = owner;
-               block->flags |= flags;
-       }
-       return( addr );
+       pr_debug("atari_stram_alloc: returning %pR\n", res);
+       return (void *)res->start;
 }
 EXPORT_SYMBOL(atari_stram_alloc);
 
-void atari_stram_free( void *addr )
 
+void atari_stram_free(void *addr)
 {
-       BLOCK *block;
-
-       DPRINTK( "atari_stram_free(addr=%p)\n", addr );
+       unsigned long start = (unsigned long)addr;
+       struct resource *res;
+       unsigned long size;
 
-       if (!(block = find_region( addr ))) {
-               printk( KERN_ERR "Attempt to free non-allocated ST-RAM block at %p "
-                               "from %p\n", addr, __builtin_return_address(0) );
+       res = lookup_resource(&stram_pool, start);
+       if (!res) {
+               pr_err("atari_stram_free: trying to free nonexistent region "
+                      "at %p\n", addr);
                return;
        }
-       DPRINTK( "atari_stram_free: found block (%p): size=%08lx, owner=%s, "
-                        "flags=%02x\n", block, block->size, block->owner, block->flags );
-
-       if (!(block->flags & BLOCK_GFP))
-               goto fail;
 
-       DPRINTK("atari_stram_free: is kmalloced, order_size=%d\n",
-               get_order(block->size));
-       free_pages((unsigned long)addr, get_order(block->size));
-       remove_region( block );
-       return;
-
-  fail:
-       printk( KERN_ERR "atari_stram_free: cannot free block at %p "
-                       "(called from %p)\n", addr, __builtin_return_address(0) );
+       size = resource_size(res);
+       pr_debug("atari_stram_free: free %lu bytes at %p\n", size, addr);
+       release_resource(res);
+       kfree(res);
 }
 EXPORT_SYMBOL(atari_stram_free);
-
-\f
-/* ------------------------------------------------------------------------ */
-/*                                                       Region Management                                                             */
-/* ------------------------------------------------------------------------ */
-
-
-/* insert a region into the alloced list (sorted) */
-static BLOCK *add_region( void *addr, unsigned long size )
-{
-       BLOCK **p, *n = NULL;
-       int i;
-
-       for( i = 0; i < N_STATIC_BLOCKS; ++i ) {
-               if (static_blocks[i].flags & BLOCK_FREE) {
-                       n = &static_blocks[i];
-                       n->flags = 0;
-                       break;
-               }
-       }
-       if (!n && mem_init_done) {
-               /* if statics block pool exhausted and we can call kmalloc() already
-                * (after mem_init()), try that */
-               n = kmalloc( sizeof(BLOCK), GFP_KERNEL );
-               if (n)
-                       n->flags = BLOCK_KMALLOCED;
-       }
-       if (!n) {
-               printk( KERN_ERR "Out of memory for ST-RAM descriptor blocks\n" );
-               return( NULL );
-       }
-       n->start = addr;
-       n->size  = size;
-
-       for( p = &alloc_list; *p; p = &((*p)->next) )
-               if ((*p)->start > addr) break;
-       n->next = *p;
-       *p = n;
-
-       return( n );
-}
-
-
-/* find a region (by start addr) in the alloced list */
-static BLOCK *find_region( void *addr )
-{
-       BLOCK *p;
-
-       for( p = alloc_list; p; p = p->next ) {
-               if (p->start == addr)
-                       return( p );
-               if (p->start > addr)
-                       break;
-       }
-       return( NULL );
-}
-
-
-/* remove a block from the alloced list */
-static int remove_region( BLOCK *block )
-{
-       BLOCK **p;
-
-       for( p = &alloc_list; *p; p = &((*p)->next) )
-               if (*p == block) break;
-       if (!*p)
-               return( 0 );
-
-       *p = block->next;
-       if (block->flags & BLOCK_KMALLOCED)
-               kfree( block );
-       else
-               block->flags |= BLOCK_FREE;
-       return( 1 );
-}
-
-
-\f
-/* ------------------------------------------------------------------------ */
-/*                                              /proc statistics file stuff                                            */
-/* ------------------------------------------------------------------------ */
-
-#ifdef DO_PROC
-
-#define        PRINT_PROC(fmt,args...) seq_printf( m, fmt, ##args )
-
-static int stram_proc_show(struct seq_file *m, void *v)
-{
-       BLOCK *p;
-
-       PRINT_PROC("Total ST-RAM:      %8u kB\n",
-                          (stram_end - stram_start) >> 10);
-       PRINT_PROC( "Allocated regions:\n" );
-       for( p = alloc_list; p; p = p->next ) {
-               PRINT_PROC("0x%08lx-0x%08lx: %s (",
-                          virt_to_phys(p->start),
-                          virt_to_phys(p->start+p->size-1),
-                          p->owner);
-               if (p->flags & BLOCK_GFP)
-                       PRINT_PROC( "page-alloced)\n" );
-               else
-                       PRINT_PROC( "??)\n" );
-       }
-
-       return 0;
-}
-
-static int stram_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, stram_proc_show, NULL);
-}
-
-static const struct file_operations stram_proc_fops = {
-       .open           = stram_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static int __init proc_stram_init(void)
-{
-       proc_create("stram", 0, NULL, &stram_proc_fops);
-       return 0;
-}
-module_init(proc_stram_init);
-#endif
-
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  tab-width: 4
- * End:
- */
index 7546d13..62e2759 100644 (file)
@@ -6,12 +6,11 @@
  */
 
 /* public interface */
-void *atari_stram_alloc(long size, const char *owner);
+void *atari_stram_alloc(unsigned long size, const char *owner);
 void atari_stram_free(void *);
 
 /* functions called internally by other parts of the kernel */
 void atari_stram_init(void);
 void atari_stram_reserve_pages(void *start_mem);
-void atari_stram_mem_init_hook (void);
 
 #endif /*_M68K_ATARI_STRAM_H */
index f51f709..0392b28 100644 (file)
@@ -399,8 +399,8 @@ struct CODEC
 #define CODEC_OVERFLOW_LEFT     2
   u_char unused2, unused3, unused4, unused5;
   u_char gpio_directions;
-#define GPIO_IN                 0
-#define GPIO_OUT                1
+#define CODEC_GPIO_IN           0
+#define CODEC_GPIO_OUT          1
   u_char unused6;
   u_char gpio_data;
 };
index 334d836..c3b4506 100644 (file)
@@ -216,7 +216,9 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
 
 void __init setup_arch(char **cmdline_p)
 {
+#ifndef CONFIG_SUN3
        int i;
+#endif
 
        /* The bootinfo is located right after the kernel bss */
        m68k_parse_bootinfo((const struct bi_record *)_end);
index 367ecee..3384a52 100644 (file)
@@ -105,9 +105,6 @@ fp_fetoxm1(struct fp_ext *dest, struct fp_ext *src)
 
        fp_monadic_check(dest, src);
 
-       if (IS_ZERO(dest))
-               return dest;
-
        return dest;
 }
 
index 4ad0ca9..4b5eb3d 100644 (file)
 #ifndef MULTI_ARITH_H
 #define MULTI_ARITH_H
 
-#if 0  /* old code... */
-
-/* Unsigned only, because we don't need signs to multiply and divide. */
-typedef unsigned int int128[4];
-
-/* Word order */
-enum {
-       MSW128,
-       NMSW128,
-       NLSW128,
-       LSW128
-};
-
-/* big-endian */
-#define LO_WORD(ll) (((unsigned int *) &ll)[1])
-#define HI_WORD(ll) (((unsigned int *) &ll)[0])
-
-/* Convenience functions to stuff various integer values into int128s */
-
-static inline void zero128(int128 a)
-{
-       a[LSW128] = a[NLSW128] = a[NMSW128] = a[MSW128] = 0;
-}
-
-/* Human-readable word order in the arguments */
-static inline void set128(unsigned int i3, unsigned int i2, unsigned int i1,
-                         unsigned int i0, int128 a)
-{
-       a[LSW128] = i0;
-       a[NLSW128] = i1;
-       a[NMSW128] = i2;
-       a[MSW128] = i3;
-}
-
-/* Convenience functions (for testing as well) */
-static inline void int64_to_128(unsigned long long src, int128 dest)
-{
-       dest[LSW128] = (unsigned int) src;
-       dest[NLSW128] = src >> 32;
-       dest[NMSW128] = dest[MSW128] = 0;
-}
-
-static inline void int128_to_64(const int128 src, unsigned long long *dest)
-{
-       *dest = src[LSW128] | (long long) src[NLSW128] << 32;
-}
-
-static inline void put_i128(const int128 a)
-{
-       printk("%08x %08x %08x %08x\n", a[MSW128], a[NMSW128],
-              a[NLSW128], a[LSW128]);
-}
-
-/* Internal shifters:
-
-   Note that these are only good for 0 < count < 32.
- */
-
-static inline void _lsl128(unsigned int count, int128 a)
-{
-       a[MSW128] = (a[MSW128] << count) | (a[NMSW128] >> (32 - count));
-       a[NMSW128] = (a[NMSW128] << count) | (a[NLSW128] >> (32 - count));
-       a[NLSW128] = (a[NLSW128] << count) | (a[LSW128] >> (32 - count));
-       a[LSW128] <<= count;
-}
-
-static inline void _lsr128(unsigned int count, int128 a)
-{
-       a[LSW128] = (a[LSW128] >> count) | (a[NLSW128] << (32 - count));
-       a[NLSW128] = (a[NLSW128] >> count) | (a[NMSW128] << (32 - count));
-       a[NMSW128] = (a[NMSW128] >> count) | (a[MSW128] << (32 - count));
-       a[MSW128] >>= count;
-}
-
-/* Should be faster, one would hope */
-
-static inline void lslone128(int128 a)
-{
-       asm volatile ("lsl.l #1,%0\n"
-                     "roxl.l #1,%1\n"
-                     "roxl.l #1,%2\n"
-                     "roxl.l #1,%3\n"
-                     :
-                     "=d" (a[LSW128]),
-                     "=d"(a[NLSW128]),
-                     "=d"(a[NMSW128]),
-                     "=d"(a[MSW128])
-                     :
-                     "0"(a[LSW128]),
-                     "1"(a[NLSW128]),
-                     "2"(a[NMSW128]),
-                     "3"(a[MSW128]));
-}
-
-static inline void lsrone128(int128 a)
-{
-       asm volatile ("lsr.l #1,%0\n"
-                     "roxr.l #1,%1\n"
-                     "roxr.l #1,%2\n"
-                     "roxr.l #1,%3\n"
-                     :
-                     "=d" (a[MSW128]),
-                     "=d"(a[NMSW128]),
-                     "=d"(a[NLSW128]),
-                     "=d"(a[LSW128])
-                     :
-                     "0"(a[MSW128]),
-                     "1"(a[NMSW128]),
-                     "2"(a[NLSW128]),
-                     "3"(a[LSW128]));
-}
-
-/* Generalized 128-bit shifters:
-
-   These bit-shift to a multiple of 32, then move whole longwords.  */
-
-static inline void lsl128(unsigned int count, int128 a)
-{
-       int wordcount, i;
-
-       if (count % 32)
-               _lsl128(count % 32, a);
-
-       if (0 == (wordcount = count / 32))
-               return;
-
-       /* argh, gak, endian-sensitive */
-       for (i = 0; i < 4 - wordcount; i++) {
-               a[i] = a[i + wordcount];
-       }
-       for (i = 3; i >= 4 - wordcount; --i) {
-               a[i] = 0;
-       }
-}
-
-static inline void lsr128(unsigned int count, int128 a)
-{
-       int wordcount, i;
-
-       if (count % 32)
-               _lsr128(count % 32, a);
-
-       if (0 == (wordcount = count / 32))
-               return;
-
-       for (i = 3; i >= wordcount; --i) {
-               a[i] = a[i - wordcount];
-       }
-       for (i = 0; i < wordcount; i++) {
-               a[i] = 0;
-       }
-}
-
-static inline int orl128(int a, int128 b)
-{
-       b[LSW128] |= a;
-}
-
-static inline int btsthi128(const int128 a)
-{
-       return a[MSW128] & 0x80000000;
-}
-
-/* test bits (numbered from 0 = LSB) up to and including "top" */
-static inline int bftestlo128(int top, const int128 a)
-{
-       int r = 0;
-
-       if (top > 31)
-               r |= a[LSW128];
-       if (top > 63)
-               r |= a[NLSW128];
-       if (top > 95)
-               r |= a[NMSW128];
-
-       r |= a[3 - (top / 32)] & ((1 << (top % 32 + 1)) - 1);
-
-       return (r != 0);
-}
-
-/* Aargh.  We need these because GCC is broken */
-/* FIXME: do them in assembly, for goodness' sake! */
-static inline void mask64(int pos, unsigned long long *mask)
-{
-       *mask = 0;
-
-       if (pos < 32) {
-               LO_WORD(*mask) = (1 << pos) - 1;
-               return;
-       }
-       LO_WORD(*mask) = -1;
-       HI_WORD(*mask) = (1 << (pos - 32)) - 1;
-}
-
-static inline void bset64(int pos, unsigned long long *dest)
-{
-       /* This conditional will be optimized away.  Thanks, GCC! */
-       if (pos < 32)
-               asm volatile ("bset %1,%0":"=m"
-                             (LO_WORD(*dest)):"id"(pos));
-       else
-               asm volatile ("bset %1,%0":"=m"
-                             (HI_WORD(*dest)):"id"(pos - 32));
-}
-
-static inline int btst64(int pos, unsigned long long dest)
-{
-       if (pos < 32)
-               return (0 != (LO_WORD(dest) & (1 << pos)));
-       else
-               return (0 != (HI_WORD(dest) & (1 << (pos - 32))));
-}
-
-static inline void lsl64(int count, unsigned long long *dest)
-{
-       if (count < 32) {
-               HI_WORD(*dest) = (HI_WORD(*dest) << count)
-                   | (LO_WORD(*dest) >> count);
-               LO_WORD(*dest) <<= count;
-               return;
-       }
-       count -= 32;
-       HI_WORD(*dest) = LO_WORD(*dest) << count;
-       LO_WORD(*dest) = 0;
-}
-
-static inline void lsr64(int count, unsigned long long *dest)
-{
-       if (count < 32) {
-               LO_WORD(*dest) = (LO_WORD(*dest) >> count)
-                   | (HI_WORD(*dest) << (32 - count));
-               HI_WORD(*dest) >>= count;
-               return;
-       }
-       count -= 32;
-       LO_WORD(*dest) = HI_WORD(*dest) >> count;
-       HI_WORD(*dest) = 0;
-}
-#endif
-
 static inline void fp_denormalize(struct fp_ext *reg, unsigned int cnt)
 {
        reg->exp += cnt;
@@ -481,117 +241,6 @@ static inline void fp_dividemant(union fp_mant128 *dest, struct fp_ext *src,
        }
 }
 
-#if 0
-static inline unsigned int fp_fls128(union fp_mant128 *src)
-{
-       unsigned long data;
-       unsigned int res, off;
-
-       if ((data = src->m32[0]))
-               off = 0;
-       else if ((data = src->m32[1]))
-               off = 32;
-       else if ((data = src->m32[2]))
-               off = 64;
-       else if ((data = src->m32[3]))
-               off = 96;
-       else
-               return 128;
-
-       asm ("bfffo %1{#0,#32},%0" : "=d" (res) : "dm" (data));
-       return res + off;
-}
-
-static inline void fp_shiftmant128(union fp_mant128 *src, int shift)
-{
-       unsigned long sticky;
-
-       switch (shift) {
-       case 0:
-               return;
-       case 1:
-               asm volatile ("lsl.l #1,%0"
-                       : "=d" (src->m32[3]) : "0" (src->m32[3]));
-               asm volatile ("roxl.l #1,%0"
-                       : "=d" (src->m32[2]) : "0" (src->m32[2]));
-               asm volatile ("roxl.l #1,%0"
-                       : "=d" (src->m32[1]) : "0" (src->m32[1]));
-               asm volatile ("roxl.l #1,%0"
-                       : "=d" (src->m32[0]) : "0" (src->m32[0]));
-               return;
-       case 2 ... 31:
-               src->m32[0] = (src->m32[0] << shift) | (src->m32[1] >> (32 - shift));
-               src->m32[1] = (src->m32[1] << shift) | (src->m32[2] >> (32 - shift));
-               src->m32[2] = (src->m32[2] << shift) | (src->m32[3] >> (32 - shift));
-               src->m32[3] = (src->m32[3] << shift);
-               return;
-       case 32 ... 63:
-               shift -= 32;
-               src->m32[0] = (src->m32[1] << shift) | (src->m32[2] >> (32 - shift));
-               src->m32[1] = (src->m32[2] << shift) | (src->m32[3] >> (32 - shift));
-               src->m32[2] = (src->m32[3] << shift);
-               src->m32[3] = 0;
-               return;
-       case 64 ... 95:
-               shift -= 64;
-               src->m32[0] = (src->m32[2] << shift) | (src->m32[3] >> (32 - shift));
-               src->m32[1] = (src->m32[3] << shift);
-               src->m32[2] = src->m32[3] = 0;
-               return;
-       case 96 ... 127:
-               shift -= 96;
-               src->m32[0] = (src->m32[3] << shift);
-               src->m32[1] = src->m32[2] = src->m32[3] = 0;
-               return;
-       case -31 ... -1:
-               shift = -shift;
-               sticky = 0;
-               if (src->m32[3] << (32 - shift))
-                       sticky = 1;
-               src->m32[3] = (src->m32[3] >> shift) | (src->m32[2] << (32 - shift)) | sticky;
-               src->m32[2] = (src->m32[2] >> shift) | (src->m32[1] << (32 - shift));
-               src->m32[1] = (src->m32[1] >> shift) | (src->m32[0] << (32 - shift));
-               src->m32[0] = (src->m32[0] >> shift);
-               return;
-       case -63 ... -32:
-               shift = -shift - 32;
-               sticky = 0;
-               if ((src->m32[2] << (32 - shift)) || src->m32[3])
-                       sticky = 1;
-               src->m32[3] = (src->m32[2] >> shift) | (src->m32[1] << (32 - shift)) | sticky;
-               src->m32[2] = (src->m32[1] >> shift) | (src->m32[0] << (32 - shift));
-               src->m32[1] = (src->m32[0] >> shift);
-               src->m32[0] = 0;
-               return;
-       case -95 ... -64:
-               shift = -shift - 64;
-               sticky = 0;
-               if ((src->m32[1] << (32 - shift)) || src->m32[2] || src->m32[3])
-                       sticky = 1;
-               src->m32[3] = (src->m32[1] >> shift) | (src->m32[0] << (32 - shift)) | sticky;
-               src->m32[2] = (src->m32[0] >> shift);
-               src->m32[1] = src->m32[0] = 0;
-               return;
-       case -127 ... -96:
-               shift = -shift - 96;
-               sticky = 0;
-               if ((src->m32[0] << (32 - shift)) || src->m32[1] || src->m32[2] || src->m32[3])
-                       sticky = 1;
-               src->m32[3] = (src->m32[0] >> shift) | sticky;
-               src->m32[2] = src->m32[1] = src->m32[0] = 0;
-               return;
-       }
-
-       if (shift < 0 && (src->m32[0] || src->m32[1] || src->m32[2] || src->m32[3]))
-               src->m32[3] = 1;
-       else
-               src->m32[3] = 0;
-       src->m32[2] = 0;
-       src->m32[1] = 0;
-       src->m32[0] = 0;
-}
-#endif
-
 static inline void fp_putmant128(struct fp_ext *dest, union fp_mant128 *src,
                                 int shift)
 {
@@ -637,183 +286,4 @@ static inline void fp_putmant128(struct fp_ext *dest, union fp_mant128 *src,
        }
 }
 
-#if 0 /* old code... */
-static inline int fls(unsigned int a)
-{
-       int r;
-
-       asm volatile ("bfffo %1{#0,#32},%0"
-                     : "=d" (r) : "md" (a));
-       return r;
-}
-
-/* fls = "find last set" (cf. ffs(3)) */
-static inline int fls128(const int128 a)
-{
-       if (a[MSW128])
-               return fls(a[MSW128]);
-       if (a[NMSW128])
-               return fls(a[NMSW128]) + 32;
-       /* XXX: it probably never gets beyond this point in actual
-          use, but that's indicative of a more general problem in the
-          algorithm (i.e. as per the actual 68881 implementation, we
-          really only need at most 67 bits of precision [plus
-          overflow]) so I'm not going to fix it. */
-       if (a[NLSW128])
-               return fls(a[NLSW128]) + 64;
-       if (a[LSW128])
-               return fls(a[LSW128]) + 96;
-       else
-               return -1;
-}
-
-static inline int zerop128(const int128 a)
-{
-       return !(a[LSW128] | a[NLSW128] | a[NMSW128] | a[MSW128]);
-}
-
-static inline int nonzerop128(const int128 a)
-{
-       return (a[LSW128] | a[NLSW128] | a[NMSW128] | a[MSW128]);
-}
-
-/* Addition and subtraction */
-/* Do these in "pure" assembly, because "extended" asm is unmanageable
-   here */
-static inline void add128(const int128 a, int128 b)
-{
-       /* rotating carry flags */
-       unsigned int carry[2];
-
-       carry[0] = a[LSW128] > (0xffffffff - b[LSW128]);
-       b[LSW128] += a[LSW128];
-
-       carry[1] = a[NLSW128] > (0xffffffff - b[NLSW128] - carry[0]);
-       b[NLSW128] = a[NLSW128] + b[NLSW128] + carry[0];
-
-       carry[0] = a[NMSW128] > (0xffffffff - b[NMSW128] - carry[1]);
-       b[NMSW128] = a[NMSW128] + b[NMSW128] + carry[1];
-
-       b[MSW128] = a[MSW128] + b[MSW128] + carry[0];
-}
-
-/* Note: assembler semantics: "b -= a" */
-static inline void sub128(const int128 a, int128 b)
-{
-       /* rotating borrow flags */
-       unsigned int borrow[2];
-
-       borrow[0] = b[LSW128] < a[LSW128];
-       b[LSW128] -= a[LSW128];
-
-       borrow[1] = b[NLSW128] < a[NLSW128] + borrow[0];
-       b[NLSW128] = b[NLSW128] - a[NLSW128] - borrow[0];
-
-       borrow[0] = b[NMSW128] < a[NMSW128] + borrow[1];
-       b[NMSW128] = b[NMSW128] - a[NMSW128] - borrow[1];
-
-       b[MSW128] = b[MSW128] - a[MSW128] - borrow[0];
-}
-
-/* Poor man's 64-bit expanding multiply */
-static inline void mul64(unsigned long long a, unsigned long long b, int128 c)
-{
-       unsigned long long acc;
-       int128 acc128;
-
-       zero128(acc128);
-       zero128(c);
-
-       /* first the low words */
-       if (LO_WORD(a) && LO_WORD(b)) {
-               acc = (long long) LO_WORD(a) * LO_WORD(b);
-               c[NLSW128] = HI_WORD(acc);
-               c[LSW128] = LO_WORD(acc);
-       }
-       /* Next the high words */
-       if (HI_WORD(a) && HI_WORD(b)) {
-               acc = (long long) HI_WORD(a) * HI_WORD(b);
-               c[MSW128] = HI_WORD(acc);
-               c[NMSW128] = LO_WORD(acc);
-       }
-       /* The middle words */
-       if (LO_WORD(a) && HI_WORD(b)) {
-               acc = (long long) LO_WORD(a) * HI_WORD(b);
-               acc128[NMSW128] = HI_WORD(acc);
-               acc128[NLSW128] = LO_WORD(acc);
-               add128(acc128, c);
-       }
-       /* The first and last words */
-       if (HI_WORD(a) && LO_WORD(b)) {
-               acc = (long long) HI_WORD(a) * LO_WORD(b);
-               acc128[NMSW128] = HI_WORD(acc);
-               acc128[NLSW128] = LO_WORD(acc);
-               add128(acc128, c);
-       }
-}
-
-/* Note: unsigned */
-static inline int cmp128(int128 a, int128 b)
-{
-       if (a[MSW128] < b[MSW128])
-               return -1;
-       if (a[MSW128] > b[MSW128])
-               return 1;
-       if (a[NMSW128] < b[NMSW128])
-               return -1;
-       if (a[NMSW128] > b[NMSW128])
-               return 1;
-       if (a[NLSW128] < b[NLSW128])
-               return -1;
-       if (a[NLSW128] > b[NLSW128])
-               return 1;
-
-       return (signed) a[LSW128] - b[LSW128];
-}
-
-inline void div128(int128 a, int128 b, int128 c)
-{
-       int128 mask;
-
-       /* Algorithm:
-
-          Shift the divisor until it's at least as big as the
-          dividend, keeping track of the position to which we've
-          shifted it, i.e. the power of 2 which we've multiplied it
-          by.
-
-          Then, for this power of 2 (the mask), and every one smaller
-          than it, subtract the mask from the dividend and add it to
-          the quotient until the dividend is smaller than the raised
-          divisor.  At this point, divide the dividend and the mask
-          by 2 (i.e. shift one place to the right).  Lather, rinse,
-          and repeat, until there are no more powers of 2 left. */
-
-       /* FIXME: needless to say, there's room for improvement here too. */
-
-       /* Shift up */
-       /* XXX: since it just has to be "at least as big", we can
-          probably eliminate this horribly wasteful loop.  I will
-          have to prove this first, though */
-       set128(0, 0, 0, 1, mask);
-       while (cmp128(b, a) < 0 && !btsthi128(b)) {
-               lslone128(b);
-               lslone128(mask);
-       }
-
-       /* Shift down */
-       zero128(c);
-       do {
-               if (cmp128(a, b) >= 0) {
-                       sub128(b, a);
-                       add128(mask, c);
-               }
-               lsrone128(mask);
-               lsrone128(b);
-       } while (nonzerop128(mask));
-
-       /* The remainder is in a... */
-}
-#endif
-
 #endif /* MULTI_ARITH_H */
index 9113c2f..bbe5254 100644 (file)
@@ -83,11 +83,6 @@ void __init mem_init(void)
        int initpages = 0;
        int i;
 
-#ifdef CONFIG_ATARI
-       if (MACH_IS_ATARI)
-               atari_stram_mem_init_hook();
-#endif
-
        /* this will put all memory onto the freelists */
        totalram_pages = num_physpages = 0;
        for_each_online_pgdat(pgdat) {
index 65adc86..e077b0b 100644 (file)
@@ -15,6 +15,7 @@ config PARISC
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_IRQ_PROBE
        select IRQ_PER_CPU
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG
 
        help
          The PA-RISC microprocessor is designed by Hewlett-Packard and used
index b1dc71f..4054b31 100644 (file)
@@ -258,10 +258,10 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 
 #define ATOMIC64_INIT(i) ((atomic64_t) { (i) })
 
-static __inline__ int
+static __inline__ s64
 __atomic64_add_return(s64 i, atomic64_t *v)
 {
-       int ret;
+       s64 ret;
        unsigned long flags;
        _atomic_spin_lock_irqsave(v, flags);
 
index 67a33cc..2388bdb 100644 (file)
@@ -5,11 +5,14 @@
 
 #include <linux/futex.h>
 #include <linux/uaccess.h>
+#include <asm/atomic.h>
 #include <asm/errno.h>
 
 static inline int
 futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
+       unsigned long int flags;
+       u32 val;
        int op = (encoded_op >> 28) & 7;
        int cmp = (encoded_op >> 24) & 15;
        int oparg = (encoded_op << 8) >> 20;
@@ -18,21 +21,58 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
                oparg = 1 << oparg;
 
-       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
+       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))
                return -EFAULT;
 
        pagefault_disable();
 
+       _atomic_spin_lock_irqsave(uaddr, flags);
+
        switch (op) {
        case FUTEX_OP_SET:
+               /* *(int *)UADDR2 = OPARG; */
+               ret = get_user(oldval, uaddr);
+               if (!ret)
+                       ret = put_user(oparg, uaddr);
+               break;
        case FUTEX_OP_ADD:
+               /* *(int *)UADDR2 += OPARG; */
+               ret = get_user(oldval, uaddr);
+               if (!ret) {
+                       val = oldval + oparg;
+                       ret = put_user(val, uaddr);
+               }
+               break;
        case FUTEX_OP_OR:
+               /* *(int *)UADDR2 |= OPARG; */
+               ret = get_user(oldval, uaddr);
+               if (!ret) {
+                       val = oldval | oparg;
+                       ret = put_user(val, uaddr);
+               }
+               break;
        case FUTEX_OP_ANDN:
+               /* *(int *)UADDR2 &= ~OPARG; */
+               ret = get_user(oldval, uaddr);
+               if (!ret) {
+                       val = oldval & ~oparg;
+                       ret = put_user(val, uaddr);
+               }
+               break;
        case FUTEX_OP_XOR:
+               /* *(int *)UADDR2 ^= OPARG; */
+               ret = get_user(oldval, uaddr);
+               if (!ret) {
+                       val = oldval ^ oparg;
+                       ret = put_user(val, uaddr);
+               }
+               break;
        default:
                ret = -ENOSYS;
        }
 
+       _atomic_spin_unlock_irqrestore(uaddr, flags);
+
        pagefault_enable();
 
        if (!ret) {
@@ -54,7 +94,9 @@ static inline int
 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                              u32 oldval, u32 newval)
 {
+       int ret;
        u32 val;
+       unsigned long flags;
 
        /* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
         * our gateway page, and causes no end of trouble...
@@ -65,12 +107,24 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
        if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
                return -EFAULT;
 
-       if (get_user(val, uaddr))
-               return -EFAULT;
-       if (val == oldval && put_user(newval, uaddr))
-               return -EFAULT;
+       /* HPPA has no cmpxchg in hardware and therefore the
+        * best we can do here is use an array of locks. The
+        * lock selected is based on a hash of the userspace
+        * address. This should scale to a couple of CPUs.
+        */
+
+       _atomic_spin_lock_irqsave(uaddr, flags);
+
+       ret = get_user(val, uaddr);
+
+       if (!ret && val == oldval)
+               ret = put_user(newval, uaddr);
+
        *uval = val;
-       return 0;
+
+       _atomic_spin_unlock_irqrestore(uaddr, flags);
+
+       return ret;
 }
 
 #endif /*__KERNEL__*/
index 3392de3..d61de64 100644 (file)
 #define __NR_open_by_handle_at (__NR_Linux + 326)
 #define __NR_syncfs            (__NR_Linux + 327)
 #define __NR_setns             (__NR_Linux + 328)
+#define __NR_sendmmsg          (__NR_Linux + 329)
 
-#define __NR_Linux_syscalls    (__NR_setns + 1)
+#define __NR_Linux_syscalls    (__NR_sendmmsg + 1)
 
 
 #define __IGNORE_select                /* newselect */
index 34a4f5a..e66366f 100644 (file)
        ENTRY_COMP(open_by_handle_at)
        ENTRY_SAME(syncfs)
        ENTRY_SAME(setns)
+       ENTRY_COMP(sendmmsg)
 
        /* Nothing yet */
 
index 374c475..47682b6 100644 (file)
@@ -136,6 +136,7 @@ config PPC
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_BPF_JIT if (PPC64 && NET)
        select HAVE_ARCH_JUMP_LABEL
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG
 
 config EARLY_PRINTK
        bool
@@ -655,6 +656,8 @@ config SBUS
 
 config FSL_SOC
        bool
+       select HAVE_CAN_FLEXCAN if NET && CAN
+       select PPC_CLOCK if CAN_FLEXCAN
 
 config FSL_PCI
        bool
index 6b33b73..d6c669c 100644 (file)
@@ -23,6 +23,8 @@
                ethernet2 = &enet2;
                pci0 = &pci0;
                pci1 = &pci1;
+               can0 = &can0;
+               can1 = &can1;
        };
 
        memory {
                        };
                };
 
-               can0@1c000 {
-                       fsl,flexcan-clock-source = "platform";
-               };
-
-               can1@1d000 {
-                       fsl,flexcan-clock-source = "platform";
-               };
-
                usb@22000 {
                        phy_type = "utmi";
                };
index 7f51104..cabe0a4 100644 (file)
                        interrupt-parent = <&mpic>;
                };
 
-               can0@1c000 {
-                       compatible = "fsl,flexcan-v1.0";
+               can0: can@1c000 {
+                       compatible = "fsl,p1010-flexcan";
                        reg = <0x1c000 0x1000>;
                        interrupts = <48 0x2>;
                        interrupt-parent = <&mpic>;
-                       fsl,flexcan-clock-divider = <2>;
                };
 
-               can1@1d000 {
-                       compatible = "fsl,flexcan-v1.0";
+               can1: can@1d000 {
+                       compatible = "fsl,p1010-flexcan";
                        reg = <0x1d000 0x1000>;
                        interrupts = <61 0x2>;
                        interrupt-parent = <&mpic>;
-                       fsl,flexcan-clock-divider = <2>;
                };
 
                L2: l2-cache-controller@20000 {
index 4182c77..ed3bab7 100644 (file)
@@ -44,12 +44,13 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
 CONFIG_MII=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
-CONFIG_IBM_NEW_EMAC_DEBUG=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
+CONFIG_IBM_EMAC_DEBUG=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
index 2dbb293..17582a3 100644 (file)
@@ -42,8 +42,9 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
index ebeb4ac..dba263c 100644 (file)
@@ -43,8 +43,9 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
index 532ea9d..f2d4be9 100644 (file)
@@ -51,10 +51,11 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
index 3c142ac..42b9793 100644 (file)
@@ -43,10 +43,11 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
index ff57d48..aa1a4ca 100644 (file)
@@ -40,8 +40,9 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
index 3ed16d5..329f9a3 100644 (file)
@@ -44,10 +44,11 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
index b1b7d2c..cef7d62 100644 (file)
@@ -32,8 +32,9 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
index 30a0a8e..20c8d26 100644 (file)
@@ -38,10 +38,11 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
index a46942a..d5be93e 100644 (file)
@@ -49,10 +49,11 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
index 07d77e5..f9269fc 100644 (file)
@@ -40,8 +40,9 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
index 2ce7e9a..9be0890 100644 (file)
@@ -55,10 +55,11 @@ CONFIG_FUSION=y
 CONFIG_FUSION_SAS=y
 CONFIG_I2O=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 CONFIG_E1000E=y
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
index 18730ff..82f7303 100644 (file)
@@ -56,8 +56,9 @@ CONFIG_FUSION_SAS=y
 CONFIG_FUSION_CTL=y
 CONFIG_FUSION_LOGGING=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_WLAN is not set
index 34c0914..109562c 100644 (file)
@@ -42,8 +42,9 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
index 01cc2b1..4880281 100644 (file)
@@ -53,11 +53,12 @@ CONFIG_FUSION=y
 CONFIG_FUSION_SAS=y
 CONFIG_I2O=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
-CONFIG_IBM_NEW_EMAC_DEBUG=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
+CONFIG_IBM_EMAC_DEBUG=y
 CONFIG_E1000E=y
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
index dfcffed..ca088cd 100644 (file)
@@ -44,8 +44,9 @@ CONFIG_ATA=y
 # CONFIG_SATA_PMP is not set
 CONFIG_SATA_SIL=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 CONFIG_INPUT_FF_MEMLESS=m
index 47e399f..b7a653b 100644 (file)
@@ -46,8 +46,9 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
index a6a002e..30de97f 100644 (file)
@@ -40,8 +40,9 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
index abf74dc..105bc56 100644 (file)
@@ -54,9 +54,10 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
 CONFIG_MII=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_EMAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
index bfd634b..7cb703b 100644 (file)
@@ -50,8 +50,9 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_XILINX_SYSACE=m
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 CONFIG_SERIO=m
 # CONFIG_SERIO_I8042 is not set
index 4713320..6cdf1c0 100644 (file)
@@ -63,8 +63,9 @@ CONFIG_BLK_DEV_SD=m
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_TUN=m
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 CONFIG_SERIO=m
 # CONFIG_SERIO_I8042 is not set
index 1f780b9..938986e 100644 (file)
@@ -22,7 +22,6 @@ static __always_inline bool arch_static_branch(struct jump_label_key *key)
        asm goto("1:\n\t"
                 "nop\n\t"
                 ".pushsection __jump_table,  \"aw\"\n\t"
-                ".align 4\n\t"
                 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
                 ".popsection \n\t"
                 : :  "i" (key) : : l_yes);
@@ -41,7 +40,6 @@ struct jump_entry {
        jump_label_t code;
        jump_label_t target;
        jump_label_t key;
-       jump_label_t pad;
 };
 
 #endif /* _ASM_POWERPC_JUMP_LABEL_H */
index 6857af5..bffd062 100644 (file)
@@ -3,17 +3,7 @@
 
 #include <asm/page.h>
 
-/*
- * If CONFIG_RELOCATABLE is enabled we can place the kdump kernel anywhere.
- * To keep enough space in the RMO for the first stage kernel on 64bit, we
- * place it at 64MB. If CONFIG_RELOCATABLE is not enabled we must place
- * the second stage at 32MB.
- */
-#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_PPC64)
-#define KDUMP_KERNELBASE       0x4000000
-#else
 #define KDUMP_KERNELBASE       0x2000000
-#endif
 
 /* How many bytes to reserve at zero for kdump. The reserve limit should
  * be greater or equal to the trampoline's end address.
index e8aaf6f..559da19 100644 (file)
 #define PV_970         0x0039
 #define PV_POWER5      0x003A
 #define PV_POWER5p     0x003B
-#define PV_POWER7      0x003F
 #define PV_970FX       0x003C
 #define PV_POWER6      0x003E
 #define PV_POWER7      0x003F
 #define mtmsrd(v)      __mtmsrd((v), 0)
 #define mtmsr(v)       mtmsrd(v)
 #else
-#define mtmsr(v)       asm volatile("mtmsr %0" : : "r" (v) : "memory")
+#define mtmsr(v)       asm volatile("mtmsr %0" : \
+                                    : "r" ((unsigned long)(v)) \
+                                    : "memory")
 #endif
 
 #define mfspr(rn)      ({unsigned long rval; \
                        asm volatile("mfspr %0," __stringify(rn) \
                                : "=r" (rval)); rval;})
-#define mtspr(rn, v)   asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v)\
+#define mtspr(rn, v)   asm volatile("mtspr " __stringify(rn) ",%0" : \
+                                    : "r" ((unsigned long)(v)) \
                                     : "memory")
 
 #ifdef __powerpc64__
index 9fb9332..fa44ff5 100644 (file)
@@ -2051,7 +2051,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
 
 static struct cpu_spec the_cpu_spec;
 
-static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s)
+static struct cpu_spec * __init setup_cpu_spec(unsigned long offset,
+                                              struct cpu_spec *s)
 {
        struct cpu_spec *t = &the_cpu_spec;
        struct cpu_spec old;
@@ -2114,6 +2115,8 @@ static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s)
                t->cpu_setup(offset, t);
        }
 #endif /* CONFIG_PPC64 || CONFIG_BOOKE */
+
+       return t;
 }
 
 struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
@@ -2124,10 +2127,8 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
        s = PTRRELOC(s);
 
        for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) {
-               if ((pvr & s->pvr_mask) == s->pvr_value) {
-                       setup_cpu_spec(offset, s);
-                       return s;
-               }
+               if ((pvr & s->pvr_mask) == s->pvr_value)
+                       return setup_cpu_spec(offset, s);
        }
 
        BUG();
index 1577434..b25f632 100644 (file)
@@ -117,6 +117,7 @@ void ioport_unmap(void __iomem *addr)
 EXPORT_SYMBOL(ioport_map);
 EXPORT_SYMBOL(ioport_unmap);
 
+#ifdef CONFIG_PCI
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
 {
        resource_size_t start = pci_resource_start(dev, bar);
@@ -146,3 +147,4 @@ void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
 
 EXPORT_SYMBOL(pci_iomap);
 EXPORT_SYMBOL(pci_iounmap);
+#endif /* CONFIG_PCI */
index 6658a15..9ce1672 100644 (file)
@@ -136,12 +136,16 @@ void __init reserve_crashkernel(void)
        crashk_res.start = KDUMP_KERNELBASE;
 #else
        if (!crashk_res.start) {
+#ifdef CONFIG_PPC64
                /*
-                * unspecified address, choose a region of specified size
-                * can overlap with initrd (ignoring corruption when retained)
-                * ppc64 requires kernel and some stacks to be in first segemnt
+                * On 64bit we split the RMO in half but cap it at half of
+                * a small SLB (128MB) since the crash kernel needs to place
+                * itself and some stacks to be in the first segment.
                 */
+               crashk_res.start = min(0x80000000ULL, (ppc64_rma_size / 2));
+#else
                crashk_res.start = KDUMP_KERNELBASE;
+#endif
        }
 
        crash_base = PAGE_ALIGN(crashk_res.start);
index d05ae42..564c1d8 100644 (file)
@@ -154,8 +154,12 @@ static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret)
            ((unsigned long)ptr & 7))
                return -EFAULT;
 
-       if (!__get_user_inatomic(*ret, ptr))
+       pagefault_disable();
+       if (!__get_user_inatomic(*ret, ptr)) {
+               pagefault_enable();
                return 0;
+       }
+       pagefault_enable();
 
        return read_user_stack_slow(ptr, ret, 8);
 }
@@ -166,8 +170,12 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)
            ((unsigned long)ptr & 3))
                return -EFAULT;
 
-       if (!__get_user_inatomic(*ret, ptr))
+       pagefault_disable();
+       if (!__get_user_inatomic(*ret, ptr)) {
+               pagefault_enable();
                return 0;
+       }
+       pagefault_enable();
 
        return read_user_stack_slow(ptr, ret, 4);
 }
@@ -294,11 +302,17 @@ static inline int current_is_64bit(void)
  */
 static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)
 {
+       int rc;
+
        if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) ||
            ((unsigned long)ptr & 3))
                return -EFAULT;
 
-       return __get_user_inatomic(*ret, ptr);
+       pagefault_disable();
+       rc = __get_user_inatomic(*ret, ptr);
+       pagefault_enable();
+
+       return rc;
 }
 
 static inline void perf_callchain_user_64(struct perf_callchain_entry *entry,
index c016033..a909f4e 100644 (file)
@@ -1020,7 +1020,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align)
        }
        if (addr == 0)
                return 0;
-       RELOC(alloc_bottom) = addr;
+       RELOC(alloc_bottom) = addr + size;
 
        prom_debug(" -> %x\n", addr);
        prom_debug("  alloc_bottom : %x\n", RELOC(alloc_bottom));
@@ -1830,11 +1830,13 @@ static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
                if (room > DEVTREE_CHUNK_SIZE)
                        room = DEVTREE_CHUNK_SIZE;
                if (room < PAGE_SIZE)
-                       prom_panic("No memory for flatten_device_tree (no room)");
+                       prom_panic("No memory for flatten_device_tree "
+                                  "(no room)\n");
                chunk = alloc_up(room, 0);
                if (chunk == 0)
-                       prom_panic("No memory for flatten_device_tree (claim failed)");
-               *mem_end = RELOC(alloc_top);
+                       prom_panic("No memory for flatten_device_tree "
+                                  "(claim failed)\n");
+               *mem_end = chunk + room;
        }
 
        ret = (void *)*mem_start;
@@ -2042,7 +2044,7 @@ static void __init flatten_device_tree(void)
 
        /*
         * Check how much room we have between alloc top & bottom (+/- a
-        * few pages), crop to 4Mb, as this is our "chuck" size
+        * few pages), crop to 1MB, as this is our "chunk" size
         */
        room = RELOC(alloc_top) - RELOC(alloc_bottom) - 0x4000;
        if (room > DEVTREE_CHUNK_SIZE)
@@ -2053,7 +2055,7 @@ static void __init flatten_device_tree(void)
        mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
        if (mem_start == 0)
                prom_panic("Can't allocate initial device-tree chunk\n");
-       mem_end = RELOC(alloc_top);
+       mem_end = mem_start + room;
 
        /* Get root of tree */
        root = call_prom("peer", 1, 1, (phandle)0);
index 6dd3358..de29501 100644 (file)
@@ -1251,7 +1251,7 @@ BEGIN_FTR_SECTION
        reg = 0
        .rept   32
        li      r6,reg*16+VCPU_VSRS
-       stxvd2x reg,r6,r3
+       STXVD2X(reg,r6,r3)
        reg = reg + 1
        .endr
 FTR_SECTION_ELSE
@@ -1313,7 +1313,7 @@ BEGIN_FTR_SECTION
        reg = 0
        .rept   32
        li      r7,reg*16+VCPU_VSRS
-       lxvd2x  reg,r7,r4
+       LXVD2X(reg,r7,r4)
        reg = reg + 1
        .endr
 FTR_SECTION_ELSE
index d733d7c..b5d8706 100644 (file)
@@ -130,21 +130,21 @@ config 405GP
        bool
        select IBM405_ERR77
        select IBM405_ERR51
-       select IBM_NEW_EMAC_ZMII
+       select IBM_EMAC_ZMII
 
 config 405EP
        bool
 
 config 405EX
        bool
-       select IBM_NEW_EMAC_EMAC4
-       select IBM_NEW_EMAC_RGMII
+       select IBM_EMAC_EMAC4
+       select IBM_EMAC_RGMII
 
 config 405EZ
        bool
-       select IBM_NEW_EMAC_NO_FLOW_CTRL
-       select IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
-       select IBM_NEW_EMAC_MAL_COMMON_ERR
+       select IBM_EMAC_NO_FLOW_CTRL
+       select IBM_EMAC_MAL_CLR_ICINTSTAT
+       select IBM_EMAC_MAL_COMMON_ERR
 
 config 405GPR
        bool
index e958b6f..762322c 100644 (file)
@@ -23,7 +23,7 @@ config BLUESTONE
        default n
        select PPC44x_SIMPLE
        select APM821xx
-       select IBM_NEW_EMAC_RGMII
+       select IBM_EMAC_RGMII
        help
          This option enables support for the APM APM821xx Evaluation board.
 
@@ -122,8 +122,8 @@ config CANYONLANDS
        select PPC4xx_PCI_EXPRESS
        select PCI_MSI
        select PPC4xx_MSI
-       select IBM_NEW_EMAC_RGMII
-       select IBM_NEW_EMAC_ZMII
+       select IBM_EMAC_RGMII
+       select IBM_EMAC_ZMII
        help
          This option enables support for the AMCC PPC460EX evaluation board.
 
@@ -135,8 +135,8 @@ config GLACIER
        select 460EX # Odd since it uses 460GT but the effects are the same
        select PCI
        select PPC4xx_PCI_EXPRESS
-       select IBM_NEW_EMAC_RGMII
-       select IBM_NEW_EMAC_ZMII
+       select IBM_EMAC_RGMII
+       select IBM_EMAC_ZMII
        help
          This option enables support for the AMCC PPC460GT evaluation board.
 
@@ -161,7 +161,7 @@ config EIGER
        select 460SX
        select PCI
        select PPC4xx_PCI_EXPRESS
-       select IBM_NEW_EMAC_RGMII
+       select IBM_EMAC_RGMII
        help
          This option enables support for the AMCC PPC460SX evaluation board.
 
@@ -260,59 +260,59 @@ config 440EP
        bool
        select PPC_FPU
        select IBM440EP_ERR42
-       select IBM_NEW_EMAC_ZMII
+       select IBM_EMAC_ZMII
        select USB_ARCH_HAS_OHCI
 
 config 440EPX
        bool
        select PPC_FPU
-       select IBM_NEW_EMAC_EMAC4
-       select IBM_NEW_EMAC_RGMII
-       select IBM_NEW_EMAC_ZMII
+       select IBM_EMAC_EMAC4
+       select IBM_EMAC_RGMII
+       select IBM_EMAC_ZMII
 
 config 440GRX
        bool
-       select IBM_NEW_EMAC_EMAC4
-       select IBM_NEW_EMAC_RGMII
-       select IBM_NEW_EMAC_ZMII
+       select IBM_EMAC_EMAC4
+       select IBM_EMAC_RGMII
+       select IBM_EMAC_ZMII
 
 config 440GP
        bool
-       select IBM_NEW_EMAC_ZMII
+       select IBM_EMAC_ZMII
 
 config 440GX
        bool
-       select IBM_NEW_EMAC_EMAC4
-       select IBM_NEW_EMAC_RGMII
-       select IBM_NEW_EMAC_ZMII #test only
-       select IBM_NEW_EMAC_TAH  #test only
+       select IBM_EMAC_EMAC4
+       select IBM_EMAC_RGMII
+       select IBM_EMAC_ZMII #test only
+       select IBM_EMAC_TAH  #test only
 
 config 440SP
        bool
 
 config 440SPe
        bool
-       select IBM_NEW_EMAC_EMAC4
+       select IBM_EMAC_EMAC4
 
 config 460EX
        bool
        select PPC_FPU
-       select IBM_NEW_EMAC_EMAC4
-       select IBM_NEW_EMAC_TAH
+       select IBM_EMAC_EMAC4
+       select IBM_EMAC_TAH
 
 config 460SX
        bool
        select PPC_FPU
-       select IBM_NEW_EMAC_EMAC4
-       select IBM_NEW_EMAC_RGMII
-       select IBM_NEW_EMAC_ZMII
-       select IBM_NEW_EMAC_TAH
+       select IBM_EMAC_EMAC4
+       select IBM_EMAC_RGMII
+       select IBM_EMAC_ZMII
+       select IBM_EMAC_TAH
 
 config APM821xx
        bool
        select PPC_FPU
-       select IBM_NEW_EMAC_EMAC4
-       select IBM_NEW_EMAC_TAH
+       select IBM_EMAC_EMAC4
+       select IBM_EMAC_TAH
 
 # 44x errata/workaround config symbols, selected by the CPU models above
 config IBM440EP_ERR42
index d0af7fb..b9ba861 100644 (file)
@@ -24,7 +24,7 @@ source "arch/powerpc/platforms/wsp/Kconfig"
 
 config KVM_GUEST
        bool "KVM Guest support"
-       default y
+       default n
        ---help---
          This option enables various optimizations for running under the KVM
          hypervisor. Overhead for the kernel when not running inside KVM should
index 67d5009..2e7ff0c 100644 (file)
@@ -17,10 +17,10 @@ config PPC_CELL_NATIVE
        select PPC_CELL_COMMON
        select MPIC
        select PPC_IO_WORKAROUNDS
-       select IBM_NEW_EMAC_EMAC4
-       select IBM_NEW_EMAC_RGMII
-       select IBM_NEW_EMAC_ZMII #test only
-       select IBM_NEW_EMAC_TAH  #test only
+       select IBM_EMAC_EMAC4
+       select IBM_EMAC_RGMII
+       select IBM_EMAC_ZMII #test only
+       select IBM_EMAC_TAH  #test only
        default n
 
 config PPC_IBM_CELL_BLADE
index e919007..0e86563 100644 (file)
@@ -181,7 +181,7 @@ static void dtl_stop(struct dtl *dtl)
 
        lppaca_of(dtl->cpu).dtl_enable_mask = 0x0;
 
-       unregister_dtl(hwcpu, __pa(dtl->buf));
+       unregister_dtl(hwcpu);
 }
 
 static u64 dtl_current_index(struct dtl *dtl)
index bc02885..83a3ca2 100644 (file)
@@ -135,7 +135,7 @@ static void pseries_mach_cpu_die(void)
                get_lppaca()->idle = 0;
 
                if (get_preferred_offline_state(cpu) == CPU_STATE_ONLINE) {
-                       unregister_slb_shadow(hwcpu, __pa(get_slb_shadow()));
+                       unregister_slb_shadow(hwcpu);
 
                        /*
                         * Call to start_secondary_resume() will not return.
@@ -150,7 +150,7 @@ static void pseries_mach_cpu_die(void)
        WARN_ON(get_preferred_offline_state(cpu) != CPU_STATE_OFFLINE);
 
        set_cpu_current_state(cpu, CPU_STATE_OFFLINE);
-       unregister_slb_shadow(hwcpu, __pa(get_slb_shadow()));
+       unregister_slb_shadow(hwcpu);
        rtas_stop_self();
 
        /* Should never get here... */
index c829e60..2c4dd1f 100644 (file)
@@ -212,17 +212,15 @@ static int __init ioei_init(void)
        struct device_node *np;
 
        ioei_check_exception_token = rtas_token("check-exception");
-       if (ioei_check_exception_token == RTAS_UNKNOWN_SERVICE) {
-               pr_warning("IO Event IRQ not supported on this system !\n");
+       if (ioei_check_exception_token == RTAS_UNKNOWN_SERVICE)
                return -ENODEV;
-       }
+
        np = of_find_node_by_path("/event-sources/ibm,io-events");
        if (np) {
                request_event_sources_irqs(np, ioei_interrupt, "IO_EVENT");
+               pr_info("IBM I/O event interrupts enabled\n");
                of_node_put(np);
        } else {
-               pr_err("io_event_irq: No ibm,io-events on system! "
-                      "IO Event interrupt disabled.\n");
                return -ENODEV;
        }
        return 0;
index 54cf3a4..7d94bdc 100644 (file)
@@ -25,20 +25,30 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
 {
        /* Don't risk a hypervisor call if we're crashing */
        if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
-               unsigned long addr;
+               int ret;
+               int cpu = smp_processor_id();
+               int hwcpu = hard_smp_processor_id();
 
-               addr = __pa(get_slb_shadow());
-               if (unregister_slb_shadow(hard_smp_processor_id(), addr))
-                       printk("SLB shadow buffer deregistration of "
-                              "cpu %u (hw_cpu_id %d) failed\n",
-                              smp_processor_id(),
-                              hard_smp_processor_id());
+               if (get_lppaca()->dtl_enable_mask) {
+                       ret = unregister_dtl(hwcpu);
+                       if (ret) {
+                               pr_err("WARNING: DTL deregistration for cpu "
+                                      "%d (hw %d) failed with %d\n",
+                                      cpu, hwcpu, ret);
+                       }
+               }
+
+               ret = unregister_slb_shadow(hwcpu);
+               if (ret) {
+                       pr_err("WARNING: SLB shadow buffer deregistration "
+                              "for cpu %d (hw %d) failed with %d\n",
+                              cpu, hwcpu, ret);
+               }
 
-               addr = __pa(get_lppaca());
-               if (unregister_vpa(hard_smp_processor_id(), addr)) {
-                       printk("VPA deregistration of cpu %u (hw_cpu_id %d) "
-                                       "failed\n", smp_processor_id(),
-                                       hard_smp_processor_id());
+               ret = unregister_vpa(hwcpu);
+               if (ret) {
+                       pr_err("WARNING: VPA deregistration for cpu %d "
+                              "(hw %d) failed with %d\n", cpu, hwcpu, ret);
                }
        }
 }
index f7205d3..c9a29da 100644 (file)
@@ -67,9 +67,8 @@ void vpa_init(int cpu)
        ret = register_vpa(hwcpu, addr);
 
        if (ret) {
-               printk(KERN_ERR "WARNING: vpa_init: VPA registration for "
-                               "cpu %d (hw %d) of area %lx returns %ld\n",
-                               cpu, hwcpu, addr, ret);
+               pr_err("WARNING: VPA registration for cpu %d (hw %d) of area "
+                      "%lx failed with %ld\n", cpu, hwcpu, addr, ret);
                return;
        }
        /*
@@ -80,10 +79,9 @@ void vpa_init(int cpu)
        if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
                ret = register_slb_shadow(hwcpu, addr);
                if (ret)
-                       printk(KERN_ERR
-                              "WARNING: vpa_init: SLB shadow buffer "
-                              "registration for cpu %d (hw %d) of area %lx "
-                              "returns %ld\n", cpu, hwcpu, addr, ret);
+                       pr_err("WARNING: SLB shadow buffer registration for "
+                              "cpu %d (hw %d) of area %lx failed with %ld\n",
+                              cpu, hwcpu, addr, ret);
        }
 
        /*
@@ -100,8 +98,9 @@ void vpa_init(int cpu)
                dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES;
                ret = register_dtl(hwcpu, __pa(dtl));
                if (ret)
-                       pr_warn("DTL registration failed for cpu %d (%ld)\n",
-                               cpu, ret);
+                       pr_err("WARNING: DTL registration of cpu %d (hw %d) "
+                              "failed with %ld\n", smp_processor_id(),
+                              hwcpu, ret);
                lppaca_of(cpu).dtl_enable_mask = 2;
        }
 }
@@ -204,7 +203,7 @@ static void pSeries_lpar_hptab_clear(void)
                unsigned long ptel;
        } ptes[4];
        long lpar_rc;
-       int i, j;
+       unsigned long i, j;
 
        /* Read in batches of 4,
         * invalidate only valid entries not in the VRMA
index 4bf2120..41c24c1 100644 (file)
@@ -53,9 +53,9 @@ static inline long vpa_call(unsigned long flags, unsigned long cpu,
        return plpar_hcall_norets(H_REGISTER_VPA, flags, cpu, vpa);
 }
 
-static inline long unregister_vpa(unsigned long cpu, unsigned long vpa)
+static inline long unregister_vpa(unsigned long cpu)
 {
-       return vpa_call(0x5, cpu, vpa);
+       return vpa_call(0x5, cpu, 0);
 }
 
 static inline long register_vpa(unsigned long cpu, unsigned long vpa)
@@ -63,9 +63,9 @@ static inline long register_vpa(unsigned long cpu, unsigned long vpa)
        return vpa_call(0x1, cpu, vpa);
 }
 
-static inline long unregister_slb_shadow(unsigned long cpu, unsigned long vpa)
+static inline long unregister_slb_shadow(unsigned long cpu)
 {
-       return vpa_call(0x7, cpu, vpa);
+       return vpa_call(0x7, cpu, 0);
 }
 
 static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa)
@@ -73,9 +73,9 @@ static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa)
        return vpa_call(0x3, cpu, vpa);
 }
 
-static inline long unregister_dtl(unsigned long cpu, unsigned long vpa)
+static inline long unregister_dtl(unsigned long cpu)
 {
-       return vpa_call(0x6, cpu, vpa);
+       return vpa_call(0x6, cpu, 0);
 }
 
 static inline long register_dtl(unsigned long cpu, unsigned long vpa)
index d00e529..0969fd9 100644 (file)
@@ -324,8 +324,9 @@ static int alloc_dispatch_logs(void)
        dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES;
        ret = register_dtl(hard_smp_processor_id(), __pa(dtl));
        if (ret)
-               pr_warn("DTL registration failed for boot cpu %d (%d)\n",
-                       smp_processor_id(), ret);
+               pr_err("WARNING: DTL registration of cpu %d (hw %d) failed "
+                      "with %d\n", smp_processor_id(),
+                      hard_smp_processor_id(), ret);
        get_paca()->lppaca_ptr->dtl_enable_mask = 2;
 
        return 0;
index a59ba96..dbfe96b 100644 (file)
@@ -655,8 +655,6 @@ struct ppc4xx_pciex_hwops
 
 static struct ppc4xx_pciex_hwops *ppc4xx_pciex_hwops;
 
-#ifdef CONFIG_44x
-
 static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port,
                                           unsigned int sdr_offset,
                                           unsigned int mask,
@@ -688,6 +686,7 @@ static int __init ppc4xx_pciex_port_reset_sdr(struct ppc4xx_pciex_port *port)
        return 0;
 }
 
+
 static void __init ppc4xx_pciex_check_link_sdr(struct ppc4xx_pciex_port *port)
 {
        printk(KERN_INFO "PCIE%d: Checking link...\n", port->index);
@@ -718,6 +717,8 @@ static void __init ppc4xx_pciex_check_link_sdr(struct ppc4xx_pciex_port *port)
                printk(KERN_INFO "PCIE%d: No device detected.\n", port->index);
 }
 
+#ifdef CONFIG_44x
+
 /* Check various reset bits of the 440SPe PCIe core */
 static int __init ppc440spe_pciex_check_reset(struct device_node *np)
 {
index c03fef7..ed5cb5a 100644 (file)
@@ -81,6 +81,7 @@ config S390
        select INIT_ALL_POSSIBLE
        select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_BZIP2
        select HAVE_KERNEL_LZMA
@@ -273,11 +274,11 @@ config MARCH_Z10
          on older machines.
 
 config MARCH_Z196
-       bool "IBM zEnterprise 196"
+       bool "IBM zEnterprise 114 and 196"
        help
-         Select this to enable optimizations for IBM zEnterprise 196
-         (2817 series). The kernel will be slightly faster but will not work
-         on older machines.
+         Select this to enable optimizations for IBM zEnterprise 114 and 196
+         (2818 and 2817 series). The kernel will be slightly faster but will
+         not work on older machines.
 
 endchoice
 
index 5e95d95..97cc440 100644 (file)
@@ -167,5 +167,6 @@ enum diag308_rc {
 };
 
 extern int diag308(unsigned long subcode, void *addr);
+extern void diag308_reset(void);
 
 #endif /* _ASM_S390_IPL_H */
index f26280d..e85c911 100644 (file)
@@ -18,6 +18,7 @@ void system_call(void);
 void pgm_check_handler(void);
 void mcck_int_handler(void);
 void io_int_handler(void);
+void psw_restart_int_handler(void);
 
 #ifdef CONFIG_32BIT
 
@@ -150,7 +151,10 @@ struct _lowcore {
         */
        __u32   ipib;                           /* 0x0e00 */
        __u32   ipib_checksum;                  /* 0x0e04 */
-       __u8    pad_0x0e08[0x0f00-0x0e08];      /* 0x0e08 */
+
+       /* 64 bit save area */
+       __u64   save_area_64;                   /* 0x0e08 */
+       __u8    pad_0x0e10[0x0f00-0x0e10];      /* 0x0e10 */
 
        /* Extended facility list */
        __u64   stfle_fac_list[32];             /* 0x0f00 */
@@ -286,7 +290,10 @@ struct _lowcore {
         */
        __u64   ipib;                           /* 0x0e00 */
        __u32   ipib_checksum;                  /* 0x0e08 */
-       __u8    pad_0x0e0c[0x0f00-0x0e0c];      /* 0x0e0c */
+
+       /* 64 bit save area */
+       __u64   save_area_64;                   /* 0x0e0c */
+       __u8    pad_0x0e14[0x0f00-0x0e14];      /* 0x0e14 */
 
        /* Extended facility list */
        __u64   stfle_fac_list[32];             /* 0x0f00 */
index 55dfcc8..a4b6229 100644 (file)
@@ -119,14 +119,12 @@ struct stack_frame {
  * Do necessary setup to start up a new thread.
  */
 #define start_thread(regs, new_psw, new_stackp) do {           \
-       set_fs(USER_DS);                                        \
        regs->psw.mask  = psw_user_bits;                        \
        regs->psw.addr  = new_psw | PSW_ADDR_AMODE;             \
        regs->gprs[15]  = new_stackp;                           \
 } while (0)
 
 #define start_thread31(regs, new_psw, new_stackp) do {         \
-       set_fs(USER_DS);                                        \
        regs->psw.mask  = psw_user32_bits;                      \
        regs->psw.addr  = new_psw | PSW_ADDR_AMODE;             \
        regs->gprs[15]  = new_stackp;                           \
index 15c9762..2199362 100644 (file)
@@ -122,6 +122,40 @@ struct slibe {
        u64 parms;
 };
 
+/**
+ * struct qaob - queue asynchronous operation block
+ * @res0: reserved parameters
+ * @res1: reserved parameter
+ * @res2: reserved parameter
+ * @res3: reserved parameter
+ * @aorc: asynchronous operation return code
+ * @flags: internal flags
+ * @cbtbs: control block type
+ * @sb_count: number of storage blocks
+ * @sba: storage block element addresses
+ * @dcount: size of storage block elements
+ * @user0: user defineable value
+ * @res4: reserved paramater
+ * @user1: user defineable value
+ * @user2: user defineable value
+ */
+struct qaob {
+       u64 res0[6];
+       u8 res1;
+       u8 res2;
+       u8 res3;
+       u8 aorc;
+       u8 flags;
+       u16 cbtbs;
+       u8 sb_count;
+       u64 sba[QDIO_MAX_ELEMENTS_PER_BUFFER];
+       u16 dcount[QDIO_MAX_ELEMENTS_PER_BUFFER];
+       u64 user0;
+       u64 res4[2];
+       u64 user1;
+       u64 user2;
+} __attribute__ ((packed, aligned(256)));
+
 /**
  * struct slib - storage list information block (SLIB)
  * @nsliba: next SLIB address (if any)
@@ -225,6 +259,41 @@ struct slsb {
 #define CHSC_AC2_DATA_DIV_AVAILABLE    0x0010
 #define CHSC_AC2_DATA_DIV_ENABLED      0x0002
 
+/**
+ * struct qdio_outbuf_state - SBAL related asynchronous operation information
+ *   (for communication with upper layer programs)
+ *   (only required for use with completion queues)
+ * @flags: flags indicating state of buffer
+ * @aob: pointer to QAOB used for the particular SBAL
+ * @user: pointer to upper layer program's state information related to SBAL
+ *        (stored in user1 data of QAOB)
+ */
+struct qdio_outbuf_state {
+       u8 flags;
+       struct qaob *aob;
+       void *user;
+};
+
+#define QDIO_OUTBUF_STATE_FLAG_NONE    0x00
+#define QDIO_OUTBUF_STATE_FLAG_PENDING 0x01
+
+#define CHSC_AC1_INITIATE_INPUTQ       0x80
+
+
+/* qdio adapter-characteristics-1 flag */
+#define AC1_SIGA_INPUT_NEEDED          0x40    /* process input queues */
+#define AC1_SIGA_OUTPUT_NEEDED         0x20    /* process output queues */
+#define AC1_SIGA_SYNC_NEEDED           0x10    /* ask hypervisor to sync */
+#define AC1_AUTOMATIC_SYNC_ON_THININT  0x08    /* set by hypervisor */
+#define AC1_AUTOMATIC_SYNC_ON_OUT_PCI  0x04    /* set by hypervisor */
+#define AC1_SC_QEBSM_AVAILABLE         0x02    /* available for subchannel */
+#define AC1_SC_QEBSM_ENABLED           0x01    /* enabled for subchannel */
+
+#define CHSC_AC2_DATA_DIV_AVAILABLE    0x0010
+#define CHSC_AC2_DATA_DIV_ENABLED      0x0002
+
+#define CHSC_AC3_FORMAT2_CQ_AVAILABLE  0x8000
+
 struct qdio_ssqd_desc {
        u8 flags;
        u8:8;
@@ -243,8 +312,7 @@ struct qdio_ssqd_desc {
        u64 sch_token;
        u8 mro;
        u8 mri;
-       u8:8;
-       u8 sbalic;
+       u16 qdioac3;
        u16:16;
        u8:8;
        u8 mmwc;
@@ -280,9 +348,11 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
  * @no_output_qs: number of output queues
  * @input_handler: handler to be called for input queues
  * @output_handler: handler to be called for output queues
+ * @queue_start_poll: polling handlers (one per input queue or NULL)
  * @int_parm: interruption parameter
  * @input_sbal_addr_array:  address of no_input_qs * 128 pointers
  * @output_sbal_addr_array: address of no_output_qs * 128 pointers
+ * @output_sbal_state_array: no_output_qs * 128 state info (for CQ or NULL)
  */
 struct qdio_initialize {
        struct ccw_device *cdev;
@@ -297,11 +367,12 @@ struct qdio_initialize {
        unsigned int no_output_qs;
        qdio_handler_t *input_handler;
        qdio_handler_t *output_handler;
-       void (*queue_start_poll) (struct ccw_device *, int, unsigned long);
+       void (**queue_start_poll) (struct ccw_device *, int, unsigned long);
        int scan_threshold;
        unsigned long int_parm;
        void **input_sbal_addr_array;
        void **output_sbal_addr_array;
+       struct qdio_outbuf_state *output_sbal_state_array;
 };
 
 #define QDIO_STATE_INACTIVE            0x00000002 /* after qdio_cleanup */
@@ -316,6 +387,7 @@ struct qdio_initialize {
 extern int qdio_allocate(struct qdio_initialize *);
 extern int qdio_establish(struct qdio_initialize *);
 extern int qdio_activate(struct ccw_device *);
+extern void qdio_release_aob(struct qaob *);
 extern int do_QDIO(struct ccw_device *, unsigned int, int, unsigned int,
                   unsigned int);
 extern int qdio_start_irq(struct ccw_device *, int);
index d382629..6582f69 100644 (file)
@@ -113,6 +113,7 @@ extern void pfault_fini(void);
 
 extern void cmma_init(void);
 extern int memcpy_real(void *, void *, size_t);
+extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
 
 #define finish_arch_switch(prev) do {                                       \
        set_fs(current->thread.mm_segment);                                  \
index 05d8f38..532fd43 100644 (file)
@@ -27,12 +27,9 @@ int main(void)
        BLANK();
        DEFINE(__TASK_pid, offsetof(struct task_struct, pid));
        BLANK();
-       DEFINE(__THREAD_per_cause,
-              offsetof(struct task_struct, thread.per_event.cause));
-       DEFINE(__THREAD_per_address,
-              offsetof(struct task_struct, thread.per_event.address));
-       DEFINE(__THREAD_per_paid,
-              offsetof(struct task_struct, thread.per_event.paid));
+       DEFINE(__THREAD_per_cause, offsetof(struct task_struct, thread.per_event.cause));
+       DEFINE(__THREAD_per_address, offsetof(struct task_struct, thread.per_event.address));
+       DEFINE(__THREAD_per_paid, offsetof(struct task_struct, thread.per_event.paid));
        BLANK();
        DEFINE(__TI_task, offsetof(struct thread_info, task));
        DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain));
@@ -142,6 +139,7 @@ int main(void)
        DEFINE(__LC_FPREGS_SAVE_AREA, offsetof(struct _lowcore, floating_pt_save_area));
        DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area));
        DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area));
+       DEFINE(__LC_SAVE_AREA_64, offsetof(struct _lowcore, save_area_64));
 #ifdef CONFIG_32BIT
        DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr));
 #else /* CONFIG_32BIT */
index 209938c..2554356 100644 (file)
@@ -76,6 +76,42 @@ s390_base_pgm_handler_fn:
        .quad   0
        .previous
 
+#
+# Calls diag 308 subcode 1 and continues execution
+#
+# The following conditions must be ensured before calling this function:
+# * Prefix register = 0
+# * Lowcore protection is disabled
+#
+ENTRY(diag308_reset)
+       larl    %r4,.Lctlregs           # Save control registers
+       stctg   %c0,%c15,0(%r4)
+       larl    %r4,.Lrestart_psw       # Setup restart PSW at absolute 0
+       lghi    %r3,0
+       lg      %r4,0(%r4)              # Save PSW
+       sturg   %r4,%r3                 # Use sturg, because of large pages
+       lghi    %r1,1
+       diag    %r1,%r1,0x308
+.Lrestart_part2:
+       lhi     %r0,0                   # Load r0 with zero
+       lhi     %r1,2                   # Use mode 2 = ESAME (dump)
+       sigp    %r1,%r0,0x12            # Switch to ESAME mode
+       sam64                           # Switch to 64 bit addressing mode
+       larl    %r4,.Lctlregs           # Restore control registers
+       lctlg   %c0,%c15,0(%r4)
+       br      %r14
+.align 16
+.Lrestart_psw:
+       .long   0x00080000,0x80000000 + .Lrestart_part2
+
+       .section .bss
+.align 8
+.Lctlregs:
+       .rept   16
+       .quad   0
+       .endr
+       .previous
+
 #else /* CONFIG_64BIT */
 
 ENTRY(s390_base_mcck_handler)
index eee9998..a9a285b 100644 (file)
@@ -380,20 +380,13 @@ asmlinkage long sys32_sigreturn(void)
                goto badframe;
        if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
                goto badframe;
-
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
+       set_current_blocked(&set);
        if (restore_sigregs32(regs, &frame->sregs))
                goto badframe;
        if (restore_sigregs_gprs_high(regs, frame->gprs_high))
                goto badframe;
-
        return regs->gprs[2];
-
 badframe:
        force_sig(SIGSEGV, current);
        return 0;
@@ -413,31 +406,22 @@ asmlinkage long sys32_rt_sigreturn(void)
                goto badframe;
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
-
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
+       set_current_blocked(&set);
        if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
                goto badframe;
        if (restore_sigregs_gprs_high(regs, frame->gprs_high))
                goto badframe;
-
        err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
        st.ss_sp = compat_ptr(ss_sp);
        err |= __get_user(st.ss_size, &frame->uc.uc_stack.ss_size);
        err |= __get_user(st.ss_flags, &frame->uc.uc_stack.ss_flags);
        if (err)
                goto badframe; 
-
        set_fs (KERNEL_DS);
        do_sigaltstack((stack_t __force __user *)&st, NULL, regs->gprs[15]);
        set_fs (old_fs);
-
        return regs->gprs[2];
-
 badframe:
        force_sig(SIGSEGV, current);
        return 0;
@@ -605,10 +589,10 @@ give_sigsegv:
  * OK, we're invoking a handler
  */    
 
-int
-handle_signal32(unsigned long sig, struct k_sigaction *ka,
-               siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+                   siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
 {
+       sigset_t blocked;
        int ret;
 
        /* Set up the stack frame */
@@ -616,15 +600,12 @@ handle_signal32(unsigned long sig, struct k_sigaction *ka,
                ret = setup_rt_frame32(sig, ka, info, oldset, regs);
        else
                ret = setup_frame32(sig, ka, oldset, regs);
-
-       if (ret == 0) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-               if (!(ka->sa.sa_flags & SA_NODEFER))
-                       sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
-       return ret;
+       if (ret)
+               return ret;
+       sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
+               sigaddset(&blocked, sig);
+       set_current_blocked(&blocked);
+       return 0;
 }
 
index 3eab7cf..02ec8fe 100644 (file)
@@ -849,6 +849,34 @@ restart_crash:
 restart_go:
 #endif
 
+#
+# PSW restart interrupt handler
+#
+ENTRY(psw_restart_int_handler)
+       st      %r15,__LC_SAVE_AREA_64(%r0)     # save r15
+       basr    %r15,0
+0:     l       %r15,.Lrestart_stack-0b(%r15)   # load restart stack
+       l       %r15,0(%r15)
+       ahi     %r15,-SP_SIZE                   # make room for pt_regs
+       stm     %r0,%r14,SP_R0(%r15)            # store gprs %r0-%r14 to stack
+       mvc     SP_R15(4,%r15),__LC_SAVE_AREA_64(%r0)# store saved %r15 to stack
+       mvc     SP_PSW(8,%r15),__LC_RST_OLD_PSW(%r0) # store restart old psw
+       xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # set backchain to 0
+       basr    %r14,0
+1:     l       %r14,.Ldo_restart-1b(%r14)
+       basr    %r14,%r14
+
+       basr    %r14,0                          # load disabled wait PSW if
+2:     lpsw    restart_psw_crash-2b(%r14)      # do_restart returns
+       .align 4
+.Ldo_restart:
+       .long   do_restart
+.Lrestart_stack:
+       .long   restart_stack
+       .align 8
+restart_psw_crash:
+       .long   0x000a0000,0x00000000 + restart_psw_crash
+
        .section .kprobes.text, "ax"
 
 #ifdef CONFIG_CHECK_STACK
index 7a0fd42..5f729d6 100644 (file)
@@ -865,6 +865,26 @@ restart_crash:
 restart_go:
 #endif
 
+#
+# PSW restart interrupt handler
+#
+ENTRY(psw_restart_int_handler)
+       stg     %r15,__LC_SAVE_AREA_64(%r0)     # save r15
+       larl    %r15,restart_stack              # load restart stack
+       lg      %r15,0(%r15)
+       aghi    %r15,-SP_SIZE                   # make room for pt_regs
+       stmg    %r0,%r14,SP_R0(%r15)            # store gprs %r0-%r14 to stack
+       mvc     SP_R15(8,%r15),__LC_SAVE_AREA_64(%r0)# store saved %r15 to stack
+       mvc     SP_PSW(16,%r15),__LC_RST_OLD_PSW(%r0)# store restart old psw
+       xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # set backchain to 0
+       brasl   %r14,do_restart
+
+       larl    %r14,restart_psw_crash          # load disabled wait PSW if
+       lpswe   0(%r14)                         # do_restart returns
+       .align 8
+restart_psw_crash:
+       .quad   0x0002000080000000,0x0000000000000000 + restart_psw_crash
+
        .section .kprobes.text, "ax"
 
 #ifdef CONFIG_CHECK_STACK
index a689070..04361d5 100644 (file)
  * - halt
  * - power off
  * - reipl
+ * - restart
  */
 #define ON_PANIC_STR           "on_panic"
 #define ON_HALT_STR            "on_halt"
 #define ON_POFF_STR            "on_poff"
 #define ON_REIPL_STR           "on_reboot"
+#define ON_RESTART_STR         "on_restart"
 
 struct shutdown_action;
 struct shutdown_trigger {
@@ -1544,17 +1546,20 @@ static char vmcmd_on_reboot[128];
 static char vmcmd_on_panic[128];
 static char vmcmd_on_halt[128];
 static char vmcmd_on_poff[128];
+static char vmcmd_on_restart[128];
 
 DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot);
 DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic);
 DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt);
 DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff);
+DEFINE_IPL_ATTR_STR_RW(vmcmd, on_restart, "%s\n", "%s\n", vmcmd_on_restart);
 
 static struct attribute *vmcmd_attrs[] = {
        &sys_vmcmd_on_reboot_attr.attr,
        &sys_vmcmd_on_panic_attr.attr,
        &sys_vmcmd_on_halt_attr.attr,
        &sys_vmcmd_on_poff_attr.attr,
+       &sys_vmcmd_on_restart_attr.attr,
        NULL,
 };
 
@@ -1576,6 +1581,8 @@ static void vmcmd_run(struct shutdown_trigger *trigger)
                cmd = vmcmd_on_halt;
        else if (strcmp(trigger->name, ON_POFF_STR) == 0)
                cmd = vmcmd_on_poff;
+       else if (strcmp(trigger->name, ON_RESTART_STR) == 0)
+               cmd = vmcmd_on_restart;
        else
                return;
 
@@ -1707,6 +1714,34 @@ static void do_panic(void)
        stop_run(&on_panic_trigger);
 }
 
+/* on restart */
+
+static struct shutdown_trigger on_restart_trigger = {ON_RESTART_STR,
+       &reipl_action};
+
+static ssize_t on_restart_show(struct kobject *kobj,
+                              struct kobj_attribute *attr, char *page)
+{
+       return sprintf(page, "%s\n", on_restart_trigger.action->name);
+}
+
+static ssize_t on_restart_store(struct kobject *kobj,
+                               struct kobj_attribute *attr,
+                               const char *buf, size_t len)
+{
+       return set_trigger(buf, &on_restart_trigger, len);
+}
+
+static struct kobj_attribute on_restart_attr =
+       __ATTR(on_restart, 0644, on_restart_show, on_restart_store);
+
+void do_restart(void)
+{
+       smp_send_stop();
+       on_restart_trigger.action->fn(&on_restart_trigger);
+       stop_run(&on_restart_trigger);
+}
+
 /* on halt */
 
 static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};
@@ -1783,7 +1818,9 @@ static void __init shutdown_triggers_init(void)
        if (sysfs_create_file(&shutdown_actions_kset->kobj,
                              &on_poff_attr.attr))
                goto fail;
-
+       if (sysfs_create_file(&shutdown_actions_kset->kobj,
+                             &on_restart_attr.attr))
+               goto fail;
        return;
 fail:
        panic("shutdown_triggers_init failed\n");
@@ -1959,6 +1996,12 @@ static void do_reset_calls(void)
 {
        struct reset_call *reset;
 
+#ifdef CONFIG_64BIT
+       if (diag308_set_works) {
+               diag308_reset();
+               return;
+       }
+#endif
        list_for_each_entry(reset, &rcall, list)
                reset->fn();
 }
index 78eb7cf..e690975 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp 2000,2009
+ *    Copyright IBM Corp 2000,2011
  *    Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>,
  *              Denis Joseph Barrow,
  */
@@ -7,6 +7,64 @@
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 
+#
+# store_status
+#
+# Prerequisites to run this function:
+# - Prefix register is set to zero
+# - Original prefix register is stored in "dump_prefix_page"
+# - Lowcore protection is off
+#
+ENTRY(store_status)
+       /* Save register one and load save area base */
+       stg     %r1,__LC_SAVE_AREA_64(%r0)
+       lghi    %r1,SAVE_AREA_BASE
+       /* General purpose registers */
+       stmg    %r0,%r15,__LC_GPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       lg      %r2,__LC_SAVE_AREA_64(%r0)
+       stg     %r2,__LC_GPREGS_SAVE_AREA-SAVE_AREA_BASE+8(%r1)
+       /* Control registers */
+       stctg   %c0,%c15,__LC_CREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       /* Access registers */
+       stam    %a0,%a15,__LC_AREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       /* Floating point registers */
+       std     %f0, 0x00 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f1, 0x08 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f2, 0x10 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f3, 0x18 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f4, 0x20 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f5, 0x28 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f6, 0x30 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f7, 0x38 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f8, 0x40 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f9, 0x48 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f10,0x50 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f11,0x58 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f12,0x60 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f13,0x68 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f14,0x70 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       std     %f15,0x78 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       /* Floating point control register */
+       stfpc   __LC_FP_CREG_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       /* CPU timer */
+       stpt    __LC_CPU_TIMER_SAVE_AREA-SAVE_AREA_BASE(%r1)
+       /* Saved prefix register */
+       larl    %r2,dump_prefix_page
+       mvc     __LC_PREFIX_SAVE_AREA-SAVE_AREA_BASE(4,%r1),0(%r2)
+       /* Clock comparator - seven bytes */
+       larl    %r2,.Lclkcmp
+       stckc   0(%r2)
+       mvc     __LC_CLOCK_COMP_SAVE_AREA-SAVE_AREA_BASE + 1(7,%r1),1(%r2)
+       /* Program status word */
+       epsw    %r2,%r3
+       st      %r2,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 0(%r1)
+       st      %r3,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 4(%r1)
+       larl    %r2,store_status
+       stg     %r2,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 8(%r1)
+       br      %r14
+.align 8
+.Lclkcmp:      .quad   0x0000000000000000
+
 #
 # do_reipl_asm
 # Parameter: r2 = schid of reipl device
 ENTRY(do_reipl_asm)
                basr    %r13,0
 .Lpg0:         lpswe   .Lnewpsw-.Lpg0(%r13)
-.Lpg1:         # do store status of all registers
-
-               stg     %r1,.Lregsave-.Lpg0(%r13)
-               lghi    %r1,0x1000
-               stmg    %r0,%r15,__LC_GPREGS_SAVE_AREA-0x1000(%r1)
-               lg      %r0,.Lregsave-.Lpg0(%r13)
-               stg     %r0,__LC_GPREGS_SAVE_AREA-0x1000+8(%r1)
-               stctg   %c0,%c15,__LC_CREGS_SAVE_AREA-0x1000(%r1)
-               stam    %a0,%a15,__LC_AREGS_SAVE_AREA-0x1000(%r1)
-               lg      %r10,.Ldump_pfx-.Lpg0(%r13)
-               mvc     __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),0(%r10)
-               stfpc   __LC_FP_CREG_SAVE_AREA-0x1000(%r1)
-               stckc   .Lclkcmp-.Lpg0(%r13)
-               mvc     __LC_CLOCK_COMP_SAVE_AREA-0x1000(7,%r1),.Lclkcmp-.Lpg0(%r13)
-               stpt    __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1)
-               stg     %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1)
+.Lpg1:         brasl   %r14,store_status
 
                lctlg   %c6,%c6,.Lall-.Lpg0(%r13)
                lgr     %r1,%r2
@@ -67,10 +110,7 @@ ENTRY(do_reipl_asm)
                st      %r14,.Ldispsw+12-.Lpg0(%r13)
                lpswe   .Ldispsw-.Lpg0(%r13)
                .align  8
-.Lclkcmp:      .quad   0x0000000000000000
 .Lall:         .quad   0x00000000ff000000
-.Ldump_pfx:    .quad   dump_prefix_page
-.Lregsave:     .quad   0x0000000000000000
                .align  16
 /*
  * These addresses have to be 31 bit otherwise
index 0c35dee..7b371c3 100644 (file)
@@ -346,7 +346,7 @@ setup_lowcore(void)
        lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
        lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
        lc->restart_psw.addr =
-               PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
+               PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
        if (user_mode != HOME_SPACE_MODE)
                lc->restart_psw.mask |= PSW_ASC_HOME;
        lc->external_new_psw.mask = psw_kernel_bits;
@@ -529,6 +529,27 @@ static void __init setup_memory_end(void)
                memory_end = memory_size;
 }
 
+void *restart_stack __attribute__((__section__(".data")));
+
+/*
+ * Setup new PSW and allocate stack for PSW restart interrupt
+ */
+static void __init setup_restart_psw(void)
+{
+       psw_t psw;
+
+       restart_stack = __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0);
+       restart_stack += ASYNC_SIZE;
+
+       /*
+        * Setup restart PSW for absolute zero lowcore. This is necesary
+        * if PSW restart is done on an offline CPU that has lowcore zero
+        */
+       psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+       psw.addr = PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
+       copy_to_absolute_zero(&S390_lowcore.restart_psw, &psw, sizeof(psw));
+}
+
 static void __init
 setup_memory(void)
 {
@@ -731,6 +752,7 @@ static void __init setup_hwcaps(void)
                strcpy(elf_platform, "z10");
                break;
        case 0x2817:
+       case 0x2818:
                strcpy(elf_platform, "z196");
                break;
        }
@@ -792,6 +814,7 @@ setup_arch(char **cmdline_p)
        setup_addressing_mode();
        setup_memory();
        setup_resources();
+       setup_restart_psw();
        setup_lowcore();
 
         cpu_init();
index abbb3c3..9a40e1c 100644 (file)
@@ -57,17 +57,15 @@ typedef struct
  */
 SYSCALL_DEFINE3(sigsuspend, int, history0, int, history1, old_sigset_t, mask)
 {
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
-       current->saved_sigmask = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       sigset_t blocked;
 
+       current->saved_sigmask = current->blocked;
+       mask &= _BLOCKABLE;
+       siginitset(&blocked, mask);
+       set_current_blocked(&blocked);
        set_current_state(TASK_INTERRUPTIBLE);
        schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-
+       set_restore_sigmask();
        return -ERESTARTNOHAND;
 }
 
@@ -172,18 +170,11 @@ SYSCALL_DEFINE0(sigreturn)
                goto badframe;
        if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
                goto badframe;
-
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
+       set_current_blocked(&set);
        if (restore_sigregs(regs, &frame->sregs))
                goto badframe;
-
        return regs->gprs[2];
-
 badframe:
        force_sig(SIGSEGV, current);
        return 0;
@@ -199,21 +190,14 @@ SYSCALL_DEFINE0(rt_sigreturn)
                goto badframe;
        if (__copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
-
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
+       set_current_blocked(&set);
        if (restore_sigregs(regs, &frame->uc.uc_mcontext))
                goto badframe;
-
        if (do_sigaltstack(&frame->uc.uc_stack, NULL,
                           regs->gprs[15]) == -EFAULT)
                goto badframe;
        return regs->gprs[2];
-
 badframe:
        force_sig(SIGSEGV, current);
        return 0;
@@ -385,14 +369,11 @@ give_sigsegv:
        return -EFAULT;
 }
 
-/*
- * OK, we're invoking a handler
- */    
-
-static int
-handle_signal(unsigned long sig, struct k_sigaction *ka,
-             siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+static int handle_signal(unsigned long sig, struct k_sigaction *ka,
+                        siginfo_t *info, sigset_t *oldset,
+                        struct pt_regs *regs)
 {
+       sigset_t blocked;
        int ret;
 
        /* Set up the stack frame */
@@ -400,17 +381,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
                ret = setup_rt_frame(sig, ka, info, oldset, regs);
        else
                ret = setup_frame(sig, ka, oldset, regs);
-
-       if (ret == 0) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-               if (!(ka->sa.sa_flags & SA_NODEFER))
-                       sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
-
-       return ret;
+       if (ret)
+               return ret;
+       sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
+               sigaddset(&blocked, sig);
+       set_current_blocked(&blocked);
+       return 0;
 }
 
 /*
index a6d85c0..6ab16ac 100644 (file)
@@ -452,23 +452,27 @@ out:
  */
 int __cpuinit start_secondary(void *cpuvoid)
 {
-       /* Setup the cpu */
        cpu_init();
        preempt_disable();
-       /* Enable TOD clock interrupts on the secondary cpu. */
        init_cpu_timer();
-       /* Enable cpu timer interrupts on the secondary cpu. */
        init_cpu_vtimer();
-       /* Enable pfault pseudo page faults on this cpu. */
        pfault_init();
 
-       /* call cpu notifiers */
        notify_cpu_starting(smp_processor_id());
-       /* Mark this cpu as online */
        ipi_call_lock();
        set_cpu_online(smp_processor_id(), true);
        ipi_call_unlock();
-       /* Switch on interrupts */
+       __ctl_clear_bit(0, 28); /* Disable lowcore protection */
+       S390_lowcore.restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+       S390_lowcore.restart_psw.addr =
+               PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
+       __ctl_set_bit(0, 28); /* Enable lowcore protection */
+       /*
+        * Wait until the cpu which brought this one up marked it
+        * active before enabling interrupts.
+        */
+       while (!cpumask_test_cpu(smp_processor_id(), cpu_active_mask))
+               cpu_relax();
        local_irq_enable();
        /* cpu_idle will call schedule for us */
        cpu_idle();
@@ -507,7 +511,11 @@ static int __cpuinit smp_alloc_lowcore(int cpu)
        memset((char *)lowcore + 512, 0, sizeof(*lowcore) - 512);
        lowcore->async_stack = async_stack + ASYNC_SIZE;
        lowcore->panic_stack = panic_stack + PAGE_SIZE;
-
+       lowcore->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+       lowcore->restart_psw.addr =
+               PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
+       if (user_mode != HOME_SPACE_MODE)
+               lowcore->restart_psw.mask |= PSW_ASC_HOME;
 #ifndef CONFIG_64BIT
        if (MACHINE_HAS_IEEE) {
                unsigned long save_area;
index 51e5cd9..5dbbaa6 100644 (file)
@@ -85,3 +85,19 @@ int memcpy_real(void *dest, void *src, size_t count)
        arch_local_irq_restore(flags);
        return rc;
 }
+
+/*
+ * Copy memory to absolute zero
+ */
+void copy_to_absolute_zero(void *dest, void *src, size_t count)
+{
+       unsigned long cr0;
+
+       BUG_ON((unsigned long) dest + count >= sizeof(struct _lowcore));
+       preempt_disable();
+       __ctl_store(cr0, 0, 0);
+       __ctl_clear_bit(0, 28); /* disable lowcore protection */
+       memcpy_real(dest + store_prefix(), src, count);
+       __ctl_load(cr0, 0, 0);
+       preempt_enable();
+}
index 2adb239..4d1f2bc 100644 (file)
@@ -528,6 +528,7 @@ static inline void page_table_free_pgste(unsigned long *table)
 static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
                                                    unsigned long vmaddr)
 {
+       return NULL;
 }
 
 static inline void page_table_free_pgste(unsigned long *table)
index 748ff19..ff9177c 100644 (file)
@@ -11,6 +11,7 @@ config SUPERH
        select HAVE_DMA_ATTRS
        select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG if (GUSA_RB || CPU_SH4A)
        select PERF_USE_VMALLOC
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_BZIP2
index e3d8170..99385d0 100644 (file)
@@ -173,6 +173,7 @@ core-$(CONFIG_HD6446X_SERIES)       += arch/sh/cchips/hd6446x/
 cpuincdir-$(CONFIG_CPU_SH2A)   += cpu-sh2a
 cpuincdir-$(CONFIG_CPU_SH2)    += cpu-sh2
 cpuincdir-$(CONFIG_CPU_SH3)    += cpu-sh3
+cpuincdir-$(CONFIG_CPU_SH4A)   += cpu-sh4a
 cpuincdir-$(CONFIG_CPU_SH4)    += cpu-sh4
 cpuincdir-$(CONFIG_CPU_SH5)    += cpu-sh5
 cpuincdir-y                    += cpu-common   # Must be last
index 8e2a270..2823619 100644 (file)
@@ -116,7 +116,7 @@ static int apsh4a3a_clk_init(void)
        int ret;
 
        clk = clk_get(NULL, "extal");
-       if (!clk || IS_ERR(clk))
+       if (IS_ERR(clk))
                return PTR_ERR(clk);
        ret = clk_set_rate(clk, 33333000);
        clk_put(clk);
index e2bd218..b4d6292 100644 (file)
@@ -94,7 +94,7 @@ static int apsh4ad0a_clk_init(void)
        int ret;
 
        clk = clk_get(NULL, "extal");
-       if (!clk || IS_ERR(clk))
+       if (IS_ERR(clk))
                return PTR_ERR(clk);
        ret = clk_set_rate(clk, 33333000);
        clk_put(clk);
index ee65ff0..d879848 100644 (file)
@@ -299,7 +299,7 @@ static int sh7785lcr_clk_init(void)
        int ret;
 
        clk = clk_get(NULL, "extal");
-       if (!clk || IS_ERR(clk))
+       if (IS_ERR(clk))
                return PTR_ERR(clk);
        ret = clk_set_rate(clk, 33333333);
        clk_put(clk);
index d81c609..24e3316 100644 (file)
@@ -190,7 +190,7 @@ static int urquell_clk_init(void)
                return -EINVAL;
 
        clk = clk_get(NULL, "extal");
-       if (!clk || IS_ERR(clk))
+       if (IS_ERR(clk))
                return PTR_ERR(clk);
        ret = clk_set_rate(clk, 33333333);
        clk_put(clk);
index 1dc924b..d362657 100644 (file)
@@ -332,8 +332,8 @@ static int camera_set_capture(struct soc_camera_platform_info *info,
        return ret;
 }
 
-static int ap325rxa_camera_add(struct soc_camera_link *icl, struct device *dev);
-static void ap325rxa_camera_del(struct soc_camera_link *icl);
+static int ap325rxa_camera_add(struct soc_camera_device *icd);
+static void ap325rxa_camera_del(struct soc_camera_device *icd);
 
 static struct soc_camera_platform_info camera_info = {
        .format_name = "UYVY",
@@ -366,24 +366,23 @@ static void ap325rxa_camera_release(struct device *dev)
        soc_camera_platform_release(&camera_device);
 }
 
-static int ap325rxa_camera_add(struct soc_camera_link *icl,
-                              struct device *dev)
+static int ap325rxa_camera_add(struct soc_camera_device *icd)
 {
-       int ret = soc_camera_platform_add(icl, dev, &camera_device, &camera_link,
+       int ret = soc_camera_platform_add(icd, &camera_device, &camera_link,
                                          ap325rxa_camera_release, 0);
        if (ret < 0)
                return ret;
 
        ret = camera_probe();
        if (ret < 0)
-               soc_camera_platform_del(icl, camera_device, &camera_link);
+               soc_camera_platform_del(icd, camera_device, &camera_link);
 
        return ret;
 }
 
-static void ap325rxa_camera_del(struct soc_camera_link *icl)
+static void ap325rxa_camera_del(struct soc_camera_device *icd)
 {
-       soc_camera_platform_del(icl, camera_device, &camera_link);
+       soc_camera_platform_del(icd, camera_device, &camera_link);
 }
 #endif /* CONFIG_I2C */
 
index 87618c9..74b8db1 100644 (file)
@@ -335,8 +335,6 @@ static struct clk *r7780rp_clocks[] = {
        &ivdr_clk,
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("ivdr_clk", &ivdr_clk),
index 1521aa7..486d1ac 100644 (file)
@@ -194,7 +194,7 @@ static int sdk7786_clk_init(void)
                return -EINVAL;
 
        clk = clk_get(NULL, "extal");
-       if (!clk || IS_ERR(clk))
+       if (IS_ERR(clk))
                return PTR_ERR(clk);
        ret = clk_set_rate(clk, 33333333);
        clk_put(clk);
index b68b61d..edc2fb7 100644 (file)
@@ -5,7 +5,7 @@
 #include <cpu/irq.h>
 #include "pci-sh5.h"
 
-int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int result = -1;
 
index 942ef4f..edeea89 100644 (file)
@@ -64,7 +64,7 @@ static void __init gapspci_fixup_resources(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
 
-int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        /*
         * The interrupt routing semantics here are quite trivial.
index 95c6e2d..ecb1d10 100644 (file)
@@ -19,7 +19,7 @@
 #define PCIMCR_MRSET_OFF       0xBFFFFFFF
 #define PCIMCR_RFSH_OFF                0xFFFFFFFB
 
-int pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
        /*
         * slot0: pin1-4 = irq5,6,7,8
index 08b2d86..f9370dc 100644 (file)
@@ -18,7 +18,7 @@ static char irq_tab[] __initdata = {
        65, 66, 67, 68,
 };
 
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
        return irq_tab[slot];
 }
index e248516..eaddb56 100644 (file)
@@ -31,7 +31,7 @@ static char lboxre2_irq_tab[] __initdata = {
        IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
 };
 
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
        if (mach_is_lboxre2())
                return lboxre2_irq_tab[slot];
index 0930f98..0b84725 100644 (file)
@@ -27,7 +27,7 @@ static char sdk7780_irq_tab[4][16] __initdata = {
        { 68, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
 };
 
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
        return sdk7780_irq_tab[pin-1][slot];
 }
index fd3e6b0..2ec146c 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/io.h>
 #include "pci-sh4.h"
 
-int __init pcibios_map_platform_irq(struct pci_dev *, u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(const struct pci_dev *, u8 slot, u8 pin)
 {
         switch (slot) {
         case 0: return 13;
index 2e8a18b..1615e59 100644 (file)
@@ -3,7 +3,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 
-int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index 5a39ecc..4a093c6 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/pci.h>
 #include "pci-sh4.h"
 
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
        int irq = -1;
 
index 3a79fa8..bd1addb 100644 (file)
@@ -27,7 +27,7 @@ static char titan_irq_tab[] __initdata = {
        TITAN_IRQ_USB,
 };
 
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
        int irq = titan_irq_tab[slot];
 
index 4418f90..4df27c4 100644 (file)
@@ -466,7 +466,7 @@ static int __init pcie_init(struct sh7786_pcie_port *port)
        return 0;
 }
 
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
         return 71;
 }
index f0efe97..cb21e23 100644 (file)
@@ -112,7 +112,7 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 #endif
 
 /* Board-specific fixup routines. */
-int pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
+int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin);
 
 extern void pcibios_resource_to_bus(struct pci_dev *dev,
        struct pci_bus_region *region, struct resource *res);
diff --git a/arch/sh/include/cpu-sh3/cpu/serial.h b/arch/sh/include/cpu-sh3/cpu/serial.h
new file mode 100644 (file)
index 0000000..7766329
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __CPU_SH3_SERIAL_H
+#define __CPU_SH3_SERIAL_H
+
+#include <linux/serial_sci.h>
+
+extern struct plat_sci_port_ops sh770x_sci_port_ops;
+extern struct plat_sci_port_ops sh7710_sci_port_ops;
+extern struct plat_sci_port_ops sh7720_sci_port_ops;
+
+#endif /* __CPU_SH3_SERIAL_H */
diff --git a/arch/sh/include/cpu-sh4a/cpu/serial.h b/arch/sh/include/cpu-sh4a/cpu/serial.h
new file mode 100644 (file)
index 0000000..ff1bc27
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __CPU_SH4A_SERIAL_H
+#define __CPU_SH4A_SERIAL_H
+
+/* arch/sh/kernel/cpu/sh4a/serial-sh7722.c */
+extern struct plat_sci_port_ops sh7722_sci_port_ops;
+
+#endif /* __CPU_SH4A_SERIAL_H */
index 8f63a26..f59b1f3 100644 (file)
@@ -35,8 +35,6 @@ static struct clk *onchip_clocks[] = {
        &cpu_clk,
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("master_clk", &master_clk),
index ecab274..6f13f33 100644 (file)
@@ -7,15 +7,15 @@ obj-y := ex.o probe.o entry.o setup-sh3.o
 obj-$(CONFIG_HIBERNATION)              += swsusp.o
 
 # CPU subtype setup
-obj-$(CONFIG_CPU_SUBTYPE_SH7705)       += setup-sh7705.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7706)       += setup-sh770x.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7707)       += setup-sh770x.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7708)       += setup-sh770x.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7709)       += setup-sh770x.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7710)       += setup-sh7710.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7712)       += setup-sh7710.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7720)       += setup-sh7720.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7721)       += setup-sh7720.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7705)       += setup-sh7705.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7706)       += setup-sh770x.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7707)       += setup-sh770x.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7708)       += setup-sh770x.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7709)       += setup-sh770x.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7710)       += setup-sh7710.o serial-sh7710.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7712)       += setup-sh7710.o serial-sh7710.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7720)       += setup-sh7720.o serial-sh7720.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7721)       += setup-sh7720.o serial-sh7720.o
 
 # Primary on-chip clocks (common)
 clock-$(CONFIG_CPU_SH3)                        := clock-sh3.o
diff --git a/arch/sh/kernel/cpu/sh3/serial-sh770x.c b/arch/sh/kernel/cpu/sh3/serial-sh770x.c
new file mode 100644 (file)
index 0000000..4f7242c
--- /dev/null
@@ -0,0 +1,33 @@
+#include <linux/serial_sci.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <cpu/serial.h>
+
+#define SCPCR 0xA4000116
+#define SCPDR 0xA4000136
+
+static void sh770x_sci_init_pins(struct uart_port *port, unsigned int cflag)
+{
+       unsigned short data;
+
+       /* We need to set SCPCR to enable RTS/CTS */
+       data = __raw_readw(SCPCR);
+       /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
+       __raw_writew(data & 0x0fcf, SCPCR);
+
+       if (!(cflag & CRTSCTS)) {
+               /* We need to set SCPCR to enable RTS/CTS */
+               data = __raw_readw(SCPCR);
+               /* Clear out SCP7MD1,0, SCP4MD1,0,
+                  Set SCP6MD1,0 = {01} (output)  */
+               __raw_writew((data & 0x0fcf) | 0x1000, SCPCR);
+
+               data = __raw_readb(SCPDR);
+               /* Set /RTS2 (bit6) = 0 */
+               __raw_writeb(data & 0xbf, SCPDR);
+       }
+}
+
+struct plat_sci_port_ops sh770x_sci_port_ops = {
+       .init_pins      = sh770x_sci_init_pins,
+};
diff --git a/arch/sh/kernel/cpu/sh3/serial-sh7710.c b/arch/sh/kernel/cpu/sh3/serial-sh7710.c
new file mode 100644 (file)
index 0000000..42190ef
--- /dev/null
@@ -0,0 +1,20 @@
+#include <linux/serial_sci.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <cpu/serial.h>
+
+#define PACR 0xa4050100
+#define PBCR 0xa4050102
+
+static void sh7710_sci_init_pins(struct uart_port *port, unsigned int cflag)
+{
+       if (port->mapbase == 0xA4400000) {
+               __raw_writew(__raw_readw(PACR) & 0xffc0, PACR);
+               __raw_writew(__raw_readw(PBCR) & 0x0fff, PBCR);
+       } else if (port->mapbase == 0xA4410000)
+               __raw_writew(__raw_readw(PBCR) & 0xf003, PBCR);
+}
+
+struct plat_sci_port_ops sh7710_sci_port_ops = {
+       .init_pins      = sh7710_sci_init_pins,
+};
diff --git a/arch/sh/kernel/cpu/sh3/serial-sh7720.c b/arch/sh/kernel/cpu/sh3/serial-sh7720.c
new file mode 100644 (file)
index 0000000..8832c52
--- /dev/null
@@ -0,0 +1,37 @@
+#include <linux/serial_sci.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <cpu/serial.h>
+#include <asm/gpio.h>
+
+static void sh7720_sci_init_pins(struct uart_port *port, unsigned int cflag)
+{
+       unsigned short data;
+
+       if (cflag & CRTSCTS) {
+               /* enable RTS/CTS */
+               if (port->mapbase == 0xa4430000) { /* SCIF0 */
+                       /* Clear PTCR bit 9-2; enable all scif pins but sck */
+                       data = __raw_readw(PORT_PTCR);
+                       __raw_writew((data & 0xfc03), PORT_PTCR);
+               } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
+                       /* Clear PVCR bit 9-2 */
+                       data = __raw_readw(PORT_PVCR);
+                       __raw_writew((data & 0xfc03), PORT_PVCR);
+               }
+       } else {
+               if (port->mapbase == 0xa4430000) { /* SCIF0 */
+                       /* Clear PTCR bit 5-2; enable only tx and rx  */
+                       data = __raw_readw(PORT_PTCR);
+                       __raw_writew((data & 0xffc3), PORT_PTCR);
+               } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
+                       /* Clear PVCR bit 5-2 */
+                       data = __raw_readw(PORT_PVCR);
+                       __raw_writew((data & 0xffc3), PORT_PVCR);
+               }
+       }
+}
+
+struct plat_sci_port_ops sh7720_sci_port_ops = {
+       .init_pins      = sh7720_sci_init_pins,
+};
index cd2e702..2309618 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
 #include <asm/rtc.h>
+#include <cpu/serial.h>
 
 enum {
        UNUSED = 0,
@@ -75,6 +76,8 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_4,
        .type           = PORT_SCIF,
        .irqs           = { 56, 56, 56 },
+       .ops            = &sh770x_sci_port_ops,
+       .regtype        = SCIx_SH7705_SCIF_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -92,6 +95,8 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_4,
        .type           = PORT_SCIF,
        .irqs           = { 52, 52, 52 },
+       .ops            = &sh770x_sci_port_ops,
+       .regtype        = SCIx_SH7705_SCIF_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
index 4551ad6..3f3d5fe 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
+#include <cpu/serial.h>
 
 enum {
        UNUSED = 0,
@@ -108,11 +109,14 @@ static struct platform_device rtc_device = {
 
 static struct plat_sci_port scif0_platform_data = {
        .mapbase        = 0xfffffe80,
+       .port_reg       = 0xa4000136,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_TE | SCSCR_RE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCI,
        .irqs           = { 23, 23, 23, 0 },
+       .ops            = &sh770x_sci_port_ops,
+       .regshift       = 1,
 };
 
 static struct platform_device scif0_device = {
@@ -132,6 +136,8 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 56, 56, 56, 56 },
+       .ops            = &sh770x_sci_port_ops,
+       .regtype        = SCIx_SH3_SCIF_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -146,11 +152,14 @@ static struct platform_device scif1_device = {
     defined(CONFIG_CPU_SUBTYPE_SH7709)
 static struct plat_sci_port scif2_platform_data = {
        .mapbase        = 0xa4000140,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_TE | SCSCR_RE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_IRDA,
        .irqs           = { 52, 52, 52, 52 },
+       .ops            = &sh770x_sci_port_ops,
+       .regshift       = 1,
 };
 
 static struct platform_device scif2_device = {
index 365b94a..9492034 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
 #include <asm/rtc.h>
+#include <cpu/serial.h>
 
 static struct resource rtc_resources[] = {
        [0] = {
@@ -55,6 +56,8 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_4,
        .type           = PORT_SCIF,
        .irqs           = { 80, 80, 80, 80 },
+       .ops            = &sh7720_sci_port_ops,
+       .regtype        = SCIx_SH7705_SCIF_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -72,6 +75,8 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_4,
        .type           = PORT_SCIF,
        .irqs           = { 81, 81, 81, 81 },
+       .ops            = &sh7720_sci_port_ops,
+       .regtype        = SCIx_SH7705_SCIF_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
index 3f6f8e9..f4e262a 100644 (file)
@@ -147,8 +147,6 @@ static struct clk *sh4202_onchip_clocks[] = {
        &sh4202_shoc_clk,
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("emi_clk", &sh4202_emi_clk),
index e53b4b3..98cc0c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SH7750/SH7751 Setup
+ * SH7091/SH7750/SH7750S/SH7750R/SH7751/SH7751R Setup
  *
  *  Copyright (C) 2006  Paul Mundt
  *  Copyright (C) 2006  Jamie Lenehan
@@ -38,11 +38,13 @@ static struct platform_device rtc_device = {
 
 static struct plat_sci_port sci_platform_data = {
        .mapbase        = 0xffe00000,
+       .port_reg       = 0xffe0001C,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_TE | SCSCR_RE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCI,
        .irqs           = { 23, 23, 23, 0 },
+       .regshift       = 2,
 };
 
 static struct platform_device sci_device = {
index 78bbf23..c0b4c77 100644 (file)
@@ -133,6 +133,7 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 52, 53, 55, 54 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -150,6 +151,7 @@ static struct plat_sci_port scif1_platform_data = {
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .irqs           = { 72, 73, 75, 74 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -167,6 +169,7 @@ static struct plat_sci_port scif2_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 76, 77, 79, 78 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -184,6 +187,7 @@ static struct plat_sci_port scif3_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCI,
        .irqs           = { 80, 81, 82, 0 },
+       .regshift       = 2,
 };
 
 static struct platform_device scif3_device = {
index cc122b1..c57fb28 100644 (file)
@@ -10,7 +10,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7780)      += setup-sh7780.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7785)       += setup-sh7785.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7786)       += setup-sh7786.o intc-shx3.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7343)       += setup-sh7343.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7722)       += setup-sh7722.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7722)       += setup-sh7722.o serial-sh7722.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7723)       += setup-sh7723.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7724)       += setup-sh7724.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7366)       += setup-sh7366.o
index 93c6460..70e45bd 100644 (file)
@@ -194,8 +194,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("rclk", &r_clk),
@@ -233,32 +231,17 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
        CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
        CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
-       {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP007],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP006],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP005],
-       }, {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.3",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP004],
-       },
+
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP007]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP006]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP005]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP004]),
+
        CLKDEV_CON_ID("sio0", &mstp_clks[MSTP003]),
        CLKDEV_CON_ID("siof0", &mstp_clks[MSTP002]),
        CLKDEV_CON_ID("siof1", &mstp_clks[MSTP001]),
-       CLKDEV_CON_ID("i2c0", &mstp_clks[MSTP109]),
-       CLKDEV_CON_ID("i2c1", &mstp_clks[MSTP108]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP109]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP108]),
        CLKDEV_CON_ID("tpu0", &mstp_clks[MSTP225]),
        CLKDEV_CON_ID("irda0", &mstp_clks[MSTP224]),
        CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP218]),
index 049dc06..3c31650 100644 (file)
@@ -192,8 +192,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("rclk", &r_clk),
@@ -231,25 +229,14 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
        CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
        CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
-       {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP007],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP006],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP005],
-       },
+
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP007]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP006]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP005]),
+
        CLKDEV_CON_ID("msiof0", &mstp_clks[MSTP002]),
        CLKDEV_CON_ID("sbr0", &mstp_clks[MSTP001]),
-       CLKDEV_CON_ID("i2c0", &mstp_clks[MSTP109]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP109]),
        CLKDEV_CON_ID("icb0", &mstp_clks[MSTP227]),
        CLKDEV_CON_ID("meram0", &mstp_clks[MSTP226]),
        CLKDEV_CON_ID("dacy1", &mstp_clks[MSTP224]),
index 9d23a36..c9a4808 100644 (file)
@@ -175,8 +175,6 @@ static struct clk mstp_clks[HWBLK_NR] = {
        SH_HWBLK_CLK(HWBLK_LCDC, &div4_clks[DIV4_P], 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("rclk", &r_clk),
@@ -201,42 +199,20 @@ static struct clk_lookup lookups[] = {
        /* MSTP clocks */
        CLKDEV_CON_ID("uram0", &mstp_clks[HWBLK_URAM]),
        CLKDEV_CON_ID("xymem0", &mstp_clks[HWBLK_XYMEM]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU],
-       }, {
-               /* TMU2 */
-               .dev_id         = "sh_tmu.2",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[HWBLK_TMU]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[HWBLK_TMU]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[HWBLK_TMU]),
+
        CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]),
        CLKDEV_CON_ID("rwdt0", &mstp_clks[HWBLK_RWDT]),
        CLKDEV_CON_ID("flctl0", &mstp_clks[HWBLK_FLCTL]),
-       {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF0],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF1],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF2],
-       },
-       CLKDEV_CON_ID("i2c0", &mstp_clks[HWBLK_IIC]),
+
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[HWBLK_SCIF0]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]),
+
+       CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC]),
        CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]),
        CLKDEV_CON_ID("sdhi0", &mstp_clks[HWBLK_SDHI]),
        CLKDEV_CON_ID("keysc0", &mstp_clks[HWBLK_KEYSC]),
index 55493cd..3cc3827 100644 (file)
@@ -200,8 +200,6 @@ static struct clk mstp_clks[] = {
        SH_HWBLK_CLK(HWBLK_LCDC, &div4_clks[DIV4_B], 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("rclk", &r_clk),
@@ -305,7 +303,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("msiof0", &mstp_clks[HWBLK_MSIOF0]),
        CLKDEV_CON_ID("msiof1", &mstp_clks[HWBLK_MSIOF1]),
        CLKDEV_CON_ID("meram0", &mstp_clks[HWBLK_MERAM]),
-       CLKDEV_CON_ID("i2c0", &mstp_clks[HWBLK_IIC]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC]),
        CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]),
        CLKDEV_CON_ID("atapi0", &mstp_clks[HWBLK_ATAPI]),
        CLKDEV_CON_ID("adc0", &mstp_clks[HWBLK_ADC]),
index d08fa95..8668f55 100644 (file)
@@ -252,8 +252,6 @@ static struct clk mstp_clks[HWBLK_NR] = {
        SH_HWBLK_CLK(HWBLK_LCDC, &div4_clks[DIV4_B], 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("rclk", &r_clk),
@@ -289,77 +287,31 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("sh0", &mstp_clks[HWBLK_SHYWAY]),
        CLKDEV_CON_ID("hudi0", &mstp_clks[HWBLK_HUDI]),
        CLKDEV_CON_ID("ubc0", &mstp_clks[HWBLK_UBC]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU0],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU0],
-       }, {
-               /* TMU2 */
-               .dev_id         = "sh_tmu.2",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU0],
-       }, {
-               /* TMU3 */
-               .dev_id         = "sh_tmu.3",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU1],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[HWBLK_TMU0]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[HWBLK_TMU0]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[HWBLK_TMU0]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.3", &mstp_clks[HWBLK_TMU1]),
+
        CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]),
        CLKDEV_CON_ID("rwdt0", &mstp_clks[HWBLK_RWDT]),
        CLKDEV_CON_ID("dmac1", &mstp_clks[HWBLK_DMAC1]),
-       {
-               /* TMU4 */
-               .dev_id         = "sh_tmu.4",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU1],
-       }, {
-               /* TMU5 */
-               .dev_id         = "sh_tmu.5",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU1],
-       }, {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF0],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF1],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF2],
-       }, {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.3",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF3],
-       }, {
-               /* SCIF4 */
-               .dev_id         = "sh-sci.4",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF4],
-       }, {
-               /* SCIF5 */
-               .dev_id         = "sh-sci.5",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF5],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.4", &mstp_clks[HWBLK_TMU1]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.5", &mstp_clks[HWBLK_TMU1]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[HWBLK_SCIF0]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[HWBLK_SCIF3]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[HWBLK_SCIF4]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[HWBLK_SCIF5]),
+
        CLKDEV_CON_ID("msiof0", &mstp_clks[HWBLK_MSIOF0]),
        CLKDEV_CON_ID("msiof1", &mstp_clks[HWBLK_MSIOF1]),
        CLKDEV_CON_ID("keysc0", &mstp_clks[HWBLK_KEYSC]),
        CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]),
-       CLKDEV_CON_ID("i2c0", &mstp_clks[HWBLK_IIC0]),
-       CLKDEV_CON_ID("i2c1", &mstp_clks[HWBLK_IIC1]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC0]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[HWBLK_IIC1]),
        CLKDEV_CON_ID("mmc0", &mstp_clks[HWBLK_MMC]),
        CLKDEV_CON_ID("eth0", &mstp_clks[HWBLK_ETHER]),
        CLKDEV_CON_ID("atapi0", &mstp_clks[HWBLK_ATAPI]),
index eedddad..3b097b0 100644 (file)
@@ -101,8 +101,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP220] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 20, 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("extal", &extal_clk),
@@ -116,33 +114,13 @@ static struct clk_lookup lookups[] = {
        /* MSTP32 clocks */
        CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]),
        CLKDEV_CON_ID("riic", &mstp_clks[MSTP000]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP113],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP114],
-       },
-       {
-               /* SCIF4 (But, ID is 2) */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP112],
-       }, {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP111],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP110],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP113]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP114]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP112]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP111]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP110]),
+
        CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
        CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]),
 };
index 599630f..2d4c7fd 100644 (file)
@@ -91,8 +91,6 @@ static struct clk *sh7763_onchip_clocks[] = {
        &sh7763_shyway_clk,
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("shyway_clk", &sh7763_shyway_clk),
index 8894926..3b53348 100644 (file)
@@ -97,8 +97,6 @@ static struct clk *sh7780_onchip_clocks[] = {
        &sh7780_shyway_clk,
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("shyway_clk", &sh7780_shyway_clk),
index 2d96024..e5b420c 100644 (file)
@@ -116,8 +116,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP100] = SH_CLK_MSTP32(NULL, MSTPCR1, 0, 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("extal", &extal_clk),
@@ -134,74 +132,27 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 
        /* MSTP32 clocks */
-       {
-               /* SCIF5 */
-               .dev_id         = "sh-sci.5",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP029],
-       }, {
-               /* SCIF4 */
-               .dev_id         = "sh-sci.4",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP028],
-       }, {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.3",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP027],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP026],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP025],
-       }, {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP024],
-       },
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP029]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP028]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]),
+
        CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]),
        CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]),
        CLKDEV_CON_ID("hac1_fck", &mstp_clks[MSTP017]),
        CLKDEV_CON_ID("hac0_fck", &mstp_clks[MSTP016]),
        CLKDEV_CON_ID("mmcif_fck", &mstp_clks[MSTP013]),
        CLKDEV_CON_ID("flctl_fck", &mstp_clks[MSTP012]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU2 */
-               .dev_id         = "sh_tmu.2",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU3 */
-               .dev_id         = "sh_tmu.3",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU4 */
-               .dev_id         = "sh_tmu.4",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU5 */
-               .dev_id         = "sh_tmu.5",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.3", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.4", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.5", &mstp_clks[MSTP009]),
+
        CLKDEV_CON_ID("siof_fck", &mstp_clks[MSTP003]),
        CLKDEV_CON_ID("hspi_fck", &mstp_clks[MSTP002]),
        CLKDEV_CON_ID("hudi_fck", &mstp_clks[MSTP119]),
index 42e403b..f6c0c3d 100644 (file)
@@ -125,8 +125,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP102] = SH_CLK_MSTP32(NULL, MSTPCR1, 2, 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("extal", &extal_clk),
@@ -141,37 +139,13 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 
        /* MSTP32 clocks */
-       {
-               /* SCIF5 */
-               .dev_id         = "sh-sci.5",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP029],
-       }, {
-               /* SCIF4 */
-               .dev_id         = "sh-sci.4",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP028],
-       }, {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.3",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP027],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP026],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP025],
-       }, {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP024],
-       },
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP029]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP028]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]),
+
        CLKDEV_CON_ID("ssi3_fck", &mstp_clks[MSTP023]),
        CLKDEV_CON_ID("ssi2_fck", &mstp_clks[MSTP022]),
        CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]),
@@ -180,67 +154,20 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("hac0_fck", &mstp_clks[MSTP016]),
        CLKDEV_CON_ID("i2c1_fck", &mstp_clks[MSTP015]),
        CLKDEV_CON_ID("i2c0_fck", &mstp_clks[MSTP014]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU2 */
-               .dev_id         = "sh_tmu.2",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU3 */
-               .dev_id         = "sh_tmu.3",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU4 */
-               .dev_id         = "sh_tmu.4",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU5 */
-               .dev_id         = "sh_tmu.5",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU6 */
-               .dev_id         = "sh_tmu.6",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP010],
-       }, {
-               /* TMU7 */
-               .dev_id         = "sh_tmu.7",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP010],
-       }, {
-               /* TMU8 */
-               .dev_id         = "sh_tmu.8",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP010],
-       }, {
-               /* TMU9 */
-               .dev_id         = "sh_tmu.9",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP011],
-       }, {
-               /* TMU10 */
-               .dev_id         = "sh_tmu.10",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP011],
-       }, {
-               /* TMU11 */
-               .dev_id         = "sh_tmu.11",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP011],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.3", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.4", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.5", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.6", &mstp_clks[MSTP010]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.7", &mstp_clks[MSTP010]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.8", &mstp_clks[MSTP010]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.9", &mstp_clks[MSTP011]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.10", &mstp_clks[MSTP011]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.11", &mstp_clks[MSTP011]),
+
        CLKDEV_CON_ID("sdif1_fck", &mstp_clks[MSTP005]),
        CLKDEV_CON_ID("sdif0_fck", &mstp_clks[MSTP004]),
        CLKDEV_CON_ID("hspi_fck", &mstp_clks[MSTP002]),
index 1afdb93..bf2d00b 100644 (file)
@@ -100,8 +100,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("extal", &extal_clk),
@@ -116,62 +114,23 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 
        /* MSTP32 clocks */
-       {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.3",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP027],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP026],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP025],
-       }, {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP024],
-       },
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]),
+
        CLKDEV_CON_ID("h8ex_fck", &mstp_clks[MSTP003]),
        CLKDEV_CON_ID("csm_fck", &mstp_clks[MSTP002]),
        CLKDEV_CON_ID("fe1_fck", &mstp_clks[MSTP001]),
        CLKDEV_CON_ID("fe0_fck", &mstp_clks[MSTP000]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU2 */
-               .dev_id         = "sh_tmu.2",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU3 */
-               .dev_id         = "sh_tmu.3",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU4 */
-               .dev_id         = "sh_tmu.4",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU5 */
-               .dev_id         = "sh_tmu.5",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.3", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.4", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.5", &mstp_clks[MSTP009]),
+
        CLKDEV_CON_ID("hudi_fck", &mstp_clks[MSTP119]),
        CLKDEV_CON_ID("dmac_11_6_fck", &mstp_clks[MSTP105]),
        CLKDEV_CON_ID("dmac_5_0_fck", &mstp_clks[MSTP104]),
diff --git a/arch/sh/kernel/cpu/sh4a/serial-sh7722.c b/arch/sh/kernel/cpu/sh4a/serial-sh7722.c
new file mode 100644 (file)
index 0000000..59bc3a7
--- /dev/null
@@ -0,0 +1,23 @@
+#include <linux/serial_sci.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#define PSCR 0xA405011E
+
+static void sh7722_sci_init_pins(struct uart_port *port, unsigned int cflag)
+{
+       unsigned short data;
+
+       if (port->mapbase == 0xffe00000) {
+               data = __raw_readw(PSCR);
+               data &= ~0x03cf;
+               if (!(cflag & CRTSCTS))
+                       data |= 0x0340;
+
+               __raw_writew(data, PSCR);
+       }
+}
+
+struct plat_sci_port_ops sh7722_sci_port_ops = {
+       .init_pins      = sh7722_sci_init_pins,
+};
index 82616af..8777386 100644 (file)
@@ -20,6 +20,7 @@
 
 static struct plat_sci_port scif0_platform_data = {
        .mapbase        = 0xffe00000,
+       .port_reg       = 0xa405013e,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
index 5813d80..278a0e5 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <cpu/dma-register.h>
 #include <cpu/sh7722.h>
+#include <cpu/serial.h>
 
 static const struct sh_dmae_slave_config sh7722_dmae_slaves[] = {
        {
@@ -185,6 +186,8 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 80, 80, 80, 80 },
+       .ops            = &sh7722_sci_port_ops,
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -202,6 +205,8 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 81, 81, 81, 81 },
+       .ops            = &sh7722_sci_port_ops,
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -219,6 +224,8 @@ static struct plat_sci_port scif2_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 82, 82, 82, 82 },
+       .ops            = &sh7722_sci_port_ops,
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
index 0723822..3c2810d 100644 (file)
 /* Serial */
 static struct plat_sci_port scif0_platform_data = {
        .mapbase        = 0xffe00000,
+       .port_reg       = 0xa4050160,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 80, 80, 80, 80 },
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -40,11 +42,13 @@ static struct platform_device scif0_device = {
 
 static struct plat_sci_port scif1_platform_data = {
        .mapbase        = 0xffe10000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 81, 81, 81, 81 },
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -57,11 +61,13 @@ static struct platform_device scif1_device = {
 
 static struct plat_sci_port scif2_platform_data = {
        .mapbase        = 0xffe20000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 82, 82, 82, 82 },
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -75,6 +81,7 @@ static struct platform_device scif2_device = {
 static struct plat_sci_port scif3_platform_data = {
        .mapbase        = 0xa4e30000,
        .flags          = UPF_BOOT_AUTOCONF,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_3,
        .type           = PORT_SCIFA,
@@ -91,6 +98,7 @@ static struct platform_device scif3_device = {
 
 static struct plat_sci_port scif4_platform_data = {
        .mapbase        = 0xa4e40000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_3,
@@ -108,6 +116,7 @@ static struct platform_device scif4_device = {
 
 static struct plat_sci_port scif5_platform_data = {
        .mapbase        = 0xa4e50000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_3,
index 134a397..a37dd72 100644 (file)
@@ -296,11 +296,13 @@ static struct platform_device dma1_device = {
 /* Serial */
 static struct plat_sci_port scif0_platform_data = {
        .mapbase        = 0xffe00000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 80, 80, 80, 80 },
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -313,11 +315,13 @@ static struct platform_device scif0_device = {
 
 static struct plat_sci_port scif1_platform_data = {
        .mapbase        = 0xffe10000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 81, 81, 81, 81 },
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -330,11 +334,13 @@ static struct platform_device scif1_device = {
 
 static struct plat_sci_port scif2_platform_data = {
        .mapbase        = 0xffe20000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 82, 82, 82, 82 },
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -347,6 +353,7 @@ static struct platform_device scif2_device = {
 
 static struct plat_sci_port scif3_platform_data = {
        .mapbase        = 0xa4e30000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_3,
@@ -364,6 +371,7 @@ static struct platform_device scif3_device = {
 
 static struct plat_sci_port scif4_platform_data = {
        .mapbase        = 0xa4e40000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_3,
@@ -381,6 +389,7 @@ static struct platform_device scif4_device = {
 
 static struct plat_sci_port scif5_platform_data = {
        .mapbase        = 0xa4e50000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_3,
index 593eca6..0011351 100644 (file)
@@ -23,6 +23,7 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 40, 40, 40, 40 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -40,6 +41,7 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 76, 76, 76, 76 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -57,6 +59,7 @@ static struct plat_sci_port scif2_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 104, 104, 104, 104 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
index 08add7f..3d4d207 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_timer.h>
-
 #include <cpu/dma-register.h>
 
 static struct plat_sci_port scif0_platform_data = {
@@ -24,6 +23,7 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 40, 40, 40, 40 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -41,6 +41,7 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 76, 76, 76, 76 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
index 18d8fc1..b29e634 100644 (file)
@@ -15,9 +15,7 @@
 #include <linux/mm.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_timer.h>
-
 #include <asm/mmzone.h>
-
 #include <cpu/dma-register.h>
 
 static struct plat_sci_port scif0_platform_data = {
@@ -27,6 +25,7 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 40, 40, 40, 40 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -44,6 +43,7 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 44, 44, 44, 44 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -61,6 +61,7 @@ static struct plat_sci_port scif2_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 60, 60, 60, 60 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -78,6 +79,7 @@ static struct plat_sci_port scif3_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 61, 61, 61, 61 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif3_device = {
@@ -95,6 +97,7 @@ static struct plat_sci_port scif4_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 62, 62, 62, 62 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif4_device = {
@@ -112,6 +115,7 @@ static struct plat_sci_port scif5_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 63, 63, 63, 63 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif5_device = {
index beba32b..dd5e709 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SH7786 Setup
  *
- * Copyright (C) 2009 - 2010  Renesas Solutions Corp.
+ * Copyright (C) 2009 - 2011  Renesas Solutions Corp.
  * Kuninori Morimoto <morimoto.kuninori@renesas.com>
  * Paul Mundt <paul.mundt@renesas.com>
  *
@@ -33,6 +33,7 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 40, 41, 43, 42 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -53,6 +54,7 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 44, 44, 44, 44 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -70,6 +72,7 @@ static struct plat_sci_port scif2_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 50, 50, 50, 50 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -87,6 +90,7 @@ static struct plat_sci_port scif3_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 51, 51, 51, 51 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif3_device = {
@@ -104,6 +108,7 @@ static struct plat_sci_port scif4_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 52, 52, 52, 52 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif4_device = {
@@ -121,6 +126,7 @@ static struct plat_sci_port scif5_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 53, 53, 53, 53 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif5_device = {
index 84db0d6..32114e0 100644 (file)
 #include <linux/thread_info.h>
 #include <linux/irqflags.h>
 #include <linux/smp.h>
+#include <linux/cpuidle.h>
 #include <asm/pgalloc.h>
 #include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/smp.h>
 
-void (*pm_idle)(void) = NULL;
+static void (*pm_idle)(void);
 
 static int hlt_counter;
 
@@ -100,7 +101,8 @@ void cpu_idle(void)
                        local_irq_disable();
                        /* Don't trace irqs off for idle */
                        stop_critical_timings();
-                       pm_idle();
+                       if (cpuidle_idle_call())
+                               pm_idle();
                        /*
                         * Sanity check to ensure that pm_idle() returns
                         * with IRQs enabled
index 1074ddd..42c67be 100644 (file)
@@ -54,6 +54,7 @@ config SPARC64
        select HAVE_PERF_EVENTS
        select PERF_USE_VMALLOC
        select IRQ_PREFLOW_FASTEOI
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG
 
 config ARCH_DEFCONFIG
        string
index 3c93f08..2c2e388 100644 (file)
@@ -16,3 +16,8 @@ header-y += traps.h
 header-y += uctx.h
 header-y += utrap.h
 header-y += watchdog.h
+
+generic-y += div64.h
+generic-y += local64.h
+generic-y += irq_regs.h
+generic-y += local.h
index 325e295..29011cc 100644 (file)
@@ -26,61 +26,28 @@ extern void change_bit(unsigned long nr, volatile unsigned long *addr);
 #define smp_mb__before_clear_bit()     barrier()
 #define smp_mb__after_clear_bit()      barrier()
 
-#include <asm-generic/bitops/ffz.h>
-#include <asm-generic/bitops/__ffs.h>
 #include <asm-generic/bitops/fls.h>
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 
 #ifdef __KERNEL__
 
+extern int ffs(int x);
+extern unsigned long __ffs(unsigned long);
+
+#include <asm-generic/bitops/ffz.h>
 #include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/ffs.h>
 
 /*
  * hweightN: returns the hamming weight (i.e. the number
  * of bits set) of a N-bit word
  */
 
-#ifdef ULTRA_HAS_POPULATION_COUNT
-
-static inline unsigned int __arch_hweight64(unsigned long w)
-{
-       unsigned int res;
-
-       __asm__ ("popc %1,%0" : "=r" (res) : "r" (w));
-       return res;
-}
-
-static inline unsigned int __arch_hweight32(unsigned int w)
-{
-       unsigned int res;
-
-       __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff));
-       return res;
-}
+extern unsigned long __arch_hweight64(__u64 w);
+extern unsigned int __arch_hweight32(unsigned int w);
+extern unsigned int __arch_hweight16(unsigned int w);
+extern unsigned int __arch_hweight8(unsigned int w);
 
-static inline unsigned int __arch_hweight16(unsigned int w)
-{
-       unsigned int res;
-
-       __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff));
-       return res;
-}
-
-static inline unsigned int __arch_hweight8(unsigned int w)
-{
-       unsigned int res;
-
-       __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff));
-       return res;
-}
-
-#else
-
-#include <asm-generic/bitops/arch_hweight.h>
-
-#endif
 #include <asm-generic/bitops/const_hweight.h>
 #include <asm-generic/bitops/lock.h>
 #endif /* __KERNEL__ */
diff --git a/arch/sparc/include/asm/div64.h b/arch/sparc/include/asm/div64.h
deleted file mode 100644 (file)
index 6cd978c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
index cfa9cd2..7df8b7f 100644 (file)
 #define R_SPARC_6              45
 
 /* Bits present in AT_HWCAP, primarily for Sparc32.  */
-
-#define HWCAP_SPARC_FLUSH       1    /* CPU supports flush instruction. */
-#define HWCAP_SPARC_STBAR       2
-#define HWCAP_SPARC_SWAP        4
-#define HWCAP_SPARC_MULDIV      8
-#define HWCAP_SPARC_V9         16
-#define HWCAP_SPARC_ULTRA3     32
-#define HWCAP_SPARC_BLKINIT    64
-#define HWCAP_SPARC_N2         128
+#define HWCAP_SPARC_FLUSH       0x00000001
+#define HWCAP_SPARC_STBAR       0x00000002
+#define HWCAP_SPARC_SWAP        0x00000004
+#define HWCAP_SPARC_MULDIV      0x00000008
+#define HWCAP_SPARC_V9         0x00000010
+#define HWCAP_SPARC_ULTRA3     0x00000020
+#define HWCAP_SPARC_BLKINIT    0x00000040
+#define HWCAP_SPARC_N2         0x00000080
+
+/* Solaris compatible AT_HWCAP bits. */
+#define AV_SPARC_MUL32         0x00000100 /* 32x32 multiply is efficient */
+#define AV_SPARC_DIV32         0x00000200 /* 32x32 divide is efficient */
+#define AV_SPARC_FSMULD                0x00000400 /* 'fsmuld' is efficient */
+#define AV_SPARC_V8PLUS                0x00000800 /* v9 insn available to 32bit */
+#define AV_SPARC_POPC          0x00001000 /* 'popc' is efficient */
+#define AV_SPARC_VIS           0x00002000 /* VIS insns available */
+#define AV_SPARC_VIS2          0x00004000 /* VIS2 insns available */
+#define AV_SPARC_ASI_BLK_INIT  0x00008000 /* block init ASIs available */
+#define AV_SPARC_FMAF          0x00010000 /* fused multiply-add */
+#define AV_SPARC_VIS3          0x00020000 /* VIS3 insns available */
+#define AV_SPARC_HPC           0x00040000 /* HPC insns available */
+#define AV_SPARC_RANDOM                0x00080000 /* 'random' insn available */
+#define AV_SPARC_TRANS         0x00100000 /* transaction insns available */
+#define AV_SPARC_FJFMAU                0x00200000 /* unfused multiply-add */
+#define AV_SPARC_IMA           0x00400000 /* integer multiply-add */
+#define AV_SPARC_ASI_CACHE_SPARING \
+                               0x00800000 /* cache sparing ASIs available */
 
 #define CORE_DUMP_USE_REGSET
 
@@ -162,31 +180,8 @@ typedef struct {
 #define ELF_ET_DYN_BASE                0x0000010000000000UL
 #define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL
 
-
-/* This yields a mask that user programs can use to figure out what
-   instruction set this cpu supports.  */
-
-/* On Ultra, we support all of the v8 capabilities. */
-static inline unsigned int sparc64_elf_hwcap(void)
-{
-       unsigned int cap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
-                           HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV |
-                           HWCAP_SPARC_V9);
-
-       if (tlb_type == cheetah || tlb_type == cheetah_plus)
-               cap |= HWCAP_SPARC_ULTRA3;
-       else if (tlb_type == hypervisor) {
-               if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
-                   sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
-                       cap |= HWCAP_SPARC_BLKINIT;
-               if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
-                       cap |= HWCAP_SPARC_N2;
-       }
-
-       return cap;
-}
-
-#define ELF_HWCAP      sparc64_elf_hwcap()
+extern unsigned long sparc64_elf_hwcap;
+#define ELF_HWCAP      sparc64_elf_hwcap
 
 /* This yields a string that ld.so will use to load implementation
    specific libraries for optimization.  This is more specific in
index 7568640..015a761 100644 (file)
@@ -2927,6 +2927,13 @@ extern unsigned long sun4v_ncs_request(unsigned long request,
 #define HV_FAST_FIRE_GET_PERFREG       0x120
 #define HV_FAST_FIRE_SET_PERFREG       0x121
 
+#define HV_FAST_REBOOT_DATA_SET                0x172
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_reboot_data_set(unsigned long ra,
+                                          unsigned long len);
+#endif
+
 /* Function numbers for HV_CORE_TRAP.  */
 #define HV_CORE_SET_VER                        0x00
 #define HV_CORE_PUTCHAR                        0x01
@@ -2940,16 +2947,23 @@ extern unsigned long sun4v_ncs_request(unsigned long request,
 #define HV_GRP_CORE                    0x0001
 #define HV_GRP_INTR                    0x0002
 #define HV_GRP_SOFT_STATE              0x0003
+#define HV_GRP_TM                      0x0080
 #define HV_GRP_PCI                     0x0100
 #define HV_GRP_LDOM                    0x0101
 #define HV_GRP_SVC_CHAN                        0x0102
 #define HV_GRP_NCS                     0x0103
 #define HV_GRP_RNG                     0x0104
+#define HV_GRP_PBOOT                   0x0105
+#define HV_GRP_TPM                     0x0107
+#define HV_GRP_SDIO                    0x0108
+#define HV_GRP_SDIO_ERR                        0x0109
+#define HV_GRP_REBOOT_DATA             0x0110
 #define HV_GRP_NIAG_PERF               0x0200
 #define HV_GRP_FIRE_PERF               0x0201
 #define HV_GRP_N2_CPU                  0x0202
 #define HV_GRP_NIU                     0x0204
 #define HV_GRP_VF_CPU                  0x0205
+#define HV_GRP_KT_CPU                  0x0209
 #define HV_GRP_DIAG                    0x0300
 
 #ifndef __ASSEMBLY__
diff --git a/arch/sparc/include/asm/irq_regs.h b/arch/sparc/include/asm/irq_regs.h
deleted file mode 100644 (file)
index 3dd9c0b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
index 42b4b31..f48527e 100644 (file)
@@ -12,7 +12,7 @@ struct leon_pci_info {
        struct pci_ops *ops;
        struct resource io_space;
        struct resource mem_space;
-       int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
+       int (*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
 };
 
 extern void leon_pci_init(struct platform_device *ofdev,
diff --git a/arch/sparc/include/asm/local.h b/arch/sparc/include/asm/local.h
deleted file mode 100644 (file)
index bc80815..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _SPARC_LOCAL_H
-#define _SPARC_LOCAL_H
-
-#include <asm-generic/local.h>
-
-#endif
diff --git a/arch/sparc/include/asm/local64.h b/arch/sparc/include/asm/local64.h
deleted file mode 100644 (file)
index 36c93b5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
index f0d0c40..55a17c6 100644 (file)
@@ -42,6 +42,7 @@
 #define SUN4V_CHIP_INVALID     0x00
 #define SUN4V_CHIP_NIAGARA1    0x01
 #define SUN4V_CHIP_NIAGARA2    0x02
+#define SUN4V_CHIP_NIAGARA3    0x03
 #define SUN4V_CHIP_UNKNOWN     0xff
 
 #ifndef __ASSEMBLY__
index 83c571d..1a8afd1 100644 (file)
@@ -133,29 +133,6 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
        sub     TSB, 0x8, TSB;   \
        TSB_STORE(TSB, TAG);
 
-#define KTSB_LOAD_QUAD(TSB, REG) \
-       ldda            [TSB] ASI_NUCLEUS_QUAD_LDD, REG;
-
-#define KTSB_STORE(ADDR, VAL) \
-       stxa            VAL, [ADDR] ASI_N;
-
-#define KTSB_LOCK_TAG(TSB, REG1, REG2) \
-99:    lduwa   [TSB] ASI_N, REG1;      \
-       sethi   %hi(TSB_TAG_LOCK_HIGH), REG2;\
-       andcc   REG1, REG2, %g0;        \
-       bne,pn  %icc, 99b;              \
-        nop;                           \
-       casa    [TSB] ASI_N, REG1, REG2;\
-       cmp     REG1, REG2;             \
-       bne,pn  %icc, 99b;              \
-        nop;                           \
-
-#define KTSB_WRITE(TSB, TTE, TAG) \
-       add     TSB, 0x8, TSB;   \
-       stxa    TTE, [TSB] ASI_N;     \
-       sub     TSB, 0x8, TSB;   \
-       stxa    TAG, [TSB] ASI_N;
-
        /* Do a kernel page table walk.  Leaves physical PTE pointer in
         * REG1.  Jumps to FAIL_LABEL on early page table walk termination.
         * VADDR will not be clobbered, but REG2 will.
@@ -239,6 +216,8 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
        (KERNEL_TSB_SIZE_BYTES / 16)
 #define KERNEL_TSB4M_NENTRIES  4096
 
+#define KTSB_PHYS_SHIFT                15
+
        /* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
         * on TSB hit.  REG1, REG2, REG3, and REG4 are used as temporaries
         * and the found TTE will be left in REG1.  REG3 and REG4 must
@@ -247,13 +226,22 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
         * VADDR and TAG will be preserved and not clobbered by this macro.
         */
 #define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
-       sethi           %hi(swapper_tsb), REG1; \
+661:   sethi           %hi(swapper_tsb), REG1;                 \
        or              REG1, %lo(swapper_tsb), REG1; \
+       .section        .swapper_tsb_phys_patch, "ax"; \
+       .word           661b; \
+       .previous; \
+661:   nop; \
+       .section        .tsb_ldquad_phys_patch, "ax"; \
+       .word           661b; \
+       sllx            REG1, KTSB_PHYS_SHIFT, REG1; \
+       sllx            REG1, KTSB_PHYS_SHIFT, REG1; \
+       .previous; \
        srlx            VADDR, PAGE_SHIFT, REG2; \
        and             REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
        sllx            REG2, 4, REG2; \
        add             REG1, REG2, REG2; \
-       KTSB_LOAD_QUAD(REG2, REG3); \
+       TSB_LOAD_QUAD(REG2, REG3); \
        cmp             REG3, TAG; \
        be,a,pt         %xcc, OK_LABEL; \
         mov            REG4, REG1;
@@ -263,12 +251,21 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
         * we can make use of that for the index computation.
         */
 #define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
-       sethi           %hi(swapper_4m_tsb), REG1; \
+661:   sethi           %hi(swapper_4m_tsb), REG1;           \
        or              REG1, %lo(swapper_4m_tsb), REG1; \
+       .section        .swapper_4m_tsb_phys_patch, "ax"; \
+       .word           661b; \
+       .previous; \
+661:   nop; \
+       .section        .tsb_ldquad_phys_patch, "ax"; \
+       .word           661b; \
+       sllx            REG1, KTSB_PHYS_SHIFT, REG1; \
+       sllx            REG1, KTSB_PHYS_SHIFT, REG1; \
+       .previous; \
        and             TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
        sllx            REG2, 4, REG2; \
        add             REG1, REG2, REG2; \
-       KTSB_LOAD_QUAD(REG2, REG3); \
+       TSB_LOAD_QUAD(REG2, REG3); \
        cmp             REG3, TAG; \
        be,a,pt         %xcc, OK_LABEL; \
         mov            REG4, REG1;
index bee4bf4..9ed6ff6 100644 (file)
@@ -65,6 +65,7 @@ static struct xor_block_template xor_block_niagara = {
 #define XOR_SELECT_TEMPLATE(FASTEST) \
        ((tlb_type == hypervisor && \
          (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \
-          sun4v_chip_type == SUN4V_CHIP_NIAGARA2)) ? \
+          sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || \
+          sun4v_chip_type == SUN4V_CHIP_NIAGARA3)) ? \
         &xor_block_niagara : \
         &xor_block_VIS)
index 138dbbc..9810fd8 100644 (file)
@@ -396,6 +396,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
                   , cpu_data(0).clock_tick
 #endif
                );
+       cpucap_info(m);
 #ifdef CONFIG_SMP
        smp_bogo(m);
 #endif
@@ -474,11 +475,18 @@ static void __init sun4v_cpu_probe(void)
                sparc_pmu_type = "niagara2";
                break;
 
+       case SUN4V_CHIP_NIAGARA3:
+               sparc_cpu_type = "UltraSparc T3 (Niagara3)";
+               sparc_fpu_type = "UltraSparc T3 integrated FPU";
+               sparc_pmu_type = "niagara3";
+               break;
+
        default:
                printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n",
                       prom_cpu_compatible);
                sparc_cpu_type = "Unknown SUN4V CPU";
                sparc_fpu_type = "Unknown SUN4V FPU";
+               sparc_pmu_type = "Unknown SUN4V PMU";
                break;
        }
 }
index d91fd78..4197e8d 100644 (file)
@@ -324,6 +324,7 @@ static int iterate_cpu(struct cpuinfo_tree *t, unsigned int root_index)
        switch (sun4v_chip_type) {
        case SUN4V_CHIP_NIAGARA1:
        case SUN4V_CHIP_NIAGARA2:
+       case SUN4V_CHIP_NIAGARA3:
                rover_inc_table = niagara_iterate_method;
                break;
        default:
index dd1342c..7429b47 100644 (file)
 #include <linux/reboot.h>
 #include <linux/cpu.h>
 
+#include <asm/hypervisor.h>
 #include <asm/ldc.h>
 #include <asm/vio.h>
 #include <asm/mdesc.h>
 #include <asm/head.h>
 #include <asm/irq.h>
 
+#include "kernel.h"
+
 #define DRV_MODULE_NAME                "ds"
 #define PFX DRV_MODULE_NAME    ": "
 #define DRV_MODULE_VERSION     "1.0"
@@ -828,18 +831,32 @@ void ldom_set_var(const char *var, const char *value)
        }
 }
 
+static char full_boot_str[256] __attribute__((aligned(32)));
+static int reboot_data_supported;
+
 void ldom_reboot(const char *boot_command)
 {
        /* Don't bother with any of this if the boot_command
         * is empty.
         */
        if (boot_command && strlen(boot_command)) {
-               char full_boot_str[256];
+               unsigned long len;
 
                strcpy(full_boot_str, "boot ");
                strcpy(full_boot_str + strlen("boot "), boot_command);
+               len = strlen(full_boot_str);
 
-               ldom_set_var("reboot-command", full_boot_str);
+               if (reboot_data_supported) {
+                       unsigned long ra = kimage_addr_to_ra(full_boot_str);
+                       unsigned long hv_ret;
+
+                       hv_ret = sun4v_reboot_data_set(ra, len);
+                       if (hv_ret != HV_EOK)
+                               pr_err("SUN4V: Unable to set reboot data "
+                                      "hv_ret=%lu\n", hv_ret);
+               } else {
+                       ldom_set_var("reboot-command", full_boot_str);
+               }
        }
        sun4v_mach_sir();
 }
@@ -1237,6 +1254,16 @@ static struct vio_driver ds_driver = {
 
 static int __init ds_init(void)
 {
+       unsigned long hv_ret, major, minor;
+
+       if (tlb_type == hypervisor) {
+               hv_ret = sun4v_get_version(HV_GRP_REBOOT_DATA, &major, &minor);
+               if (hv_ret == HV_EOK) {
+                       pr_info("SUN4V: Reboot data supported (maj=%lu,min=%lu).\n",
+                               major, minor);
+                       reboot_data_supported = 1;
+               }
+       }
        kthread_run(ds_thread, NULL, "kldomd");
 
        return vio_register_driver(&ds_driver);
index d1f1361..e27f8ea 100644 (file)
@@ -42,6 +42,20 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
 
 #else /* CONFIG_SPARC32 */
+struct popc_3insn_patch_entry {
+       unsigned int    addr;
+       unsigned int    insns[3];
+};
+extern struct popc_3insn_patch_entry __popc_3insn_patch,
+       __popc_3insn_patch_end;
+
+struct popc_6insn_patch_entry {
+       unsigned int    addr;
+       unsigned int    insns[6];
+};
+extern struct popc_6insn_patch_entry __popc_6insn_patch,
+       __popc_6insn_patch_end;
+
 extern void __init per_cpu_patch(void);
 extern void __init sun4v_patch(void);
 extern void __init boot_cpu_id_too_large(int cpu);
index aa594c7..0eac1b2 100644 (file)
@@ -132,6 +132,8 @@ prom_sun4v_name:
        .asciz  "sun4v"
 prom_niagara_prefix:
        .asciz  "SUNW,UltraSPARC-T"
+prom_sparc_prefix:
+       .asciz  "SPARC-T"
        .align  4
 prom_root_compatible:
        .skip   64
@@ -379,6 +381,22 @@ sun4v_chip_type:
        sethi   %hi(prom_niagara_prefix), %g7
        or      %g7, %lo(prom_niagara_prefix), %g7
        mov     17, %g3
+90:    ldub    [%g7], %g2
+       ldub    [%g1], %g4
+       cmp     %g2, %g4
+       bne,pn  %icc, 89f
+        add    %g7, 1, %g7
+       subcc   %g3, 1, %g3
+       bne,pt  %xcc, 90b
+        add    %g1, 1, %g1
+       ba,pt   %xcc, 91f
+        nop
+
+89:    sethi   %hi(prom_cpu_compatible), %g1
+       or      %g1, %lo(prom_cpu_compatible), %g1
+       sethi   %hi(prom_sparc_prefix), %g7
+       or      %g7, %lo(prom_sparc_prefix), %g7
+       mov     7, %g3
 90:    ldub    [%g7], %g2
        ldub    [%g1], %g4
        cmp     %g2, %g4
@@ -389,6 +407,15 @@ sun4v_chip_type:
         add    %g1, 1, %g1
 
        sethi   %hi(prom_cpu_compatible), %g1
+       or      %g1, %lo(prom_cpu_compatible), %g1
+       ldub    [%g1 + 7], %g2
+       cmp     %g2, '3'
+       be,pt   %xcc, 5f
+        mov    SUN4V_CHIP_NIAGARA3, %g4
+       ba,pt   %xcc, 4f
+        nop
+
+91:    sethi   %hi(prom_cpu_compatible), %g1
        or      %g1, %lo(prom_cpu_compatible), %g1
        ldub    [%g1 + 17], %g2
        cmp     %g2, '1'
@@ -397,6 +424,7 @@ sun4v_chip_type:
        cmp     %g2, '2'
        be,pt   %xcc, 5f
         mov    SUN4V_CHIP_NIAGARA2, %g4
+       
 4:
        mov     SUN4V_CHIP_UNKNOWN, %g4
 5:     sethi   %hi(sun4v_chip_type), %g2
@@ -514,6 +542,9 @@ niagara_tlb_fixup:
         cmp    %g1, SUN4V_CHIP_NIAGARA2
        be,pt   %xcc, niagara2_patch
         nop
+       cmp     %g1, SUN4V_CHIP_NIAGARA3
+       be,pt   %xcc, niagara2_patch
+        nop
 
        call    generic_patch_copyops
         nop
@@ -528,7 +559,7 @@ niagara2_patch:
         nop
        call    niagara_patch_bzero
         nop
-       call    niagara2_patch_pageops
+       call    niagara_patch_pageops
         nop
 
        ba,a,pt %xcc, 80f
index 7c60afb..c2d055d 100644 (file)
@@ -28,16 +28,23 @@ static struct api_info api_table[] = {
        { .group = HV_GRP_CORE,         .flags = FLAG_PRE_API   },
        { .group = HV_GRP_INTR,                                 },
        { .group = HV_GRP_SOFT_STATE,                           },
+       { .group = HV_GRP_TM,                                   },
        { .group = HV_GRP_PCI,          .flags = FLAG_PRE_API   },
        { .group = HV_GRP_LDOM,                                 },
        { .group = HV_GRP_SVC_CHAN,     .flags = FLAG_PRE_API   },
        { .group = HV_GRP_NCS,          .flags = FLAG_PRE_API   },
        { .group = HV_GRP_RNG,                                  },
+       { .group = HV_GRP_PBOOT,                                },
+       { .group = HV_GRP_TPM,                                  },
+       { .group = HV_GRP_SDIO,                                 },
+       { .group = HV_GRP_SDIO_ERR,                             },
+       { .group = HV_GRP_REBOOT_DATA,                          },
        { .group = HV_GRP_NIAG_PERF,    .flags = FLAG_PRE_API   },
        { .group = HV_GRP_FIRE_PERF,                            },
        { .group = HV_GRP_N2_CPU,                               },
        { .group = HV_GRP_NIU,                                  },
        { .group = HV_GRP_VF_CPU,                               },
+       { .group = HV_GRP_KT_CPU,                               },
        { .group = HV_GRP_DIAG,         .flags = FLAG_PRE_API   },
 };
 
index 8a5f35f..58d60de 100644 (file)
@@ -798,3 +798,10 @@ ENTRY(sun4v_niagara2_setperf)
        retl
         nop
 ENDPROC(sun4v_niagara2_setperf)
+
+ENTRY(sun4v_reboot_data_set)
+       mov     HV_FAST_REBOOT_DATA_SET, %o5
+       ta      HV_FAST_TRAP
+       retl
+        nop
+ENDPROC(sun4v_reboot_data_set)
index 6ffccd6..d0479e2 100644 (file)
@@ -65,9 +65,6 @@ static inline void dma_make_coherent(unsigned long pa, unsigned long len)
 }
 #endif
 
-static struct resource *_sparc_find_resource(struct resource *r,
-                                            unsigned long);
-
 static void __iomem *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz);
 static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys,
     unsigned long size, char *name);
@@ -143,7 +140,11 @@ void iounmap(volatile void __iomem *virtual)
        unsigned long vaddr = (unsigned long) virtual & PAGE_MASK;
        struct resource *res;
 
-       if ((res = _sparc_find_resource(&sparc_iomap, vaddr)) == NULL) {
+       /*
+        * XXX Too slow. Can have 8192 DVMA pages on sun4m in the worst case.
+        * This probably warrants some sort of hashing.
+       */
+       if ((res = lookup_resource(&sparc_iomap, vaddr)) == NULL) {
                printk("free_io/iounmap: cannot free %lx\n", vaddr);
                return;
        }
@@ -319,7 +320,7 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
        struct resource *res;
        struct page *pgv;
 
-       if ((res = _sparc_find_resource(&_sparc_dvma,
+       if ((res = lookup_resource(&_sparc_dvma,
            (unsigned long)p)) == NULL) {
                printk("sbus_free_consistent: cannot free %p\n", p);
                return;
@@ -492,7 +493,7 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
 {
        struct resource *res;
 
-       if ((res = _sparc_find_resource(&_sparc_dvma,
+       if ((res = lookup_resource(&_sparc_dvma,
            (unsigned long)p)) == NULL) {
                printk("pci_free_consistent: cannot free %p\n", p);
                return;
@@ -715,25 +716,6 @@ static const struct file_operations sparc_io_proc_fops = {
 };
 #endif /* CONFIG_PROC_FS */
 
-/*
- * This is a version of find_resource and it belongs to kernel/resource.c.
- * Until we have agreement with Linus and Martin, it lingers here.
- *
- * XXX Too slow. Can have 8192 DVMA pages on sun4m in the worst case.
- * This probably warrants some sort of hashing.
- */
-static struct resource *_sparc_find_resource(struct resource *root,
-                                            unsigned long hit)
-{
-       struct resource *tmp;
-
-       for (tmp = root->child; tmp != 0; tmp = tmp->sibling) {
-               if (tmp->start <= hit && tmp->end >= hit)
-                       return tmp;
-       }
-       return NULL;
-}
-
 static void register_proc_sparc_ioport(void)
 {
 #ifdef CONFIG_PROC_FS
index 6f6544c..fd6c36b 100644 (file)
@@ -4,12 +4,27 @@
 #include <linux/interrupt.h>
 
 #include <asm/traps.h>
+#include <asm/head.h>
+#include <asm/io.h>
 
 /* cpu.c */
 extern const char *sparc_pmu_type;
 extern unsigned int fsr_storage;
 extern int ncpus_probed;
 
+#ifdef CONFIG_SPARC64
+/* setup_64.c */
+struct seq_file;
+extern void cpucap_info(struct seq_file *);
+
+static inline unsigned long kimage_addr_to_ra(const char *p)
+{
+       unsigned long val = (unsigned long) p;
+
+       return kern_base + (val - KERNBASE);
+}
+#endif
+
 #ifdef CONFIG_SPARC32
 /* cpu.c */
 extern void cpu_probe(void);
index 1d36147..79f3103 100644 (file)
@@ -47,16 +47,16 @@ kvmap_itlb_tsb_miss:
 kvmap_itlb_vmalloc_addr:
        KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_itlb_longpath)
 
-       KTSB_LOCK_TAG(%g1, %g2, %g7)
+       TSB_LOCK_TAG(%g1, %g2, %g7)
 
        /* Load and check PTE.  */
        ldxa            [%g5] ASI_PHYS_USE_EC, %g5
        mov             1, %g7
        sllx            %g7, TSB_TAG_INVALID_BIT, %g7
        brgez,a,pn      %g5, kvmap_itlb_longpath
-        KTSB_STORE(%g1, %g7)
+        TSB_STORE(%g1, %g7)
 
-       KTSB_WRITE(%g1, %g5, %g6)
+       TSB_WRITE(%g1, %g5, %g6)
 
        /* fallthrough to TLB load */
 
@@ -102,9 +102,9 @@ kvmap_itlb_longpath:
 kvmap_itlb_obp:
        OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_itlb_longpath)
 
-       KTSB_LOCK_TAG(%g1, %g2, %g7)
+       TSB_LOCK_TAG(%g1, %g2, %g7)
 
-       KTSB_WRITE(%g1, %g5, %g6)
+       TSB_WRITE(%g1, %g5, %g6)
 
        ba,pt           %xcc, kvmap_itlb_load
         nop
@@ -112,17 +112,17 @@ kvmap_itlb_obp:
 kvmap_dtlb_obp:
        OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_dtlb_longpath)
 
-       KTSB_LOCK_TAG(%g1, %g2, %g7)
+       TSB_LOCK_TAG(%g1, %g2, %g7)
 
-       KTSB_WRITE(%g1, %g5, %g6)
+       TSB_WRITE(%g1, %g5, %g6)
 
        ba,pt           %xcc, kvmap_dtlb_load
         nop
 
        .align          32
 kvmap_dtlb_tsb4m_load:
-       KTSB_LOCK_TAG(%g1, %g2, %g7)
-       KTSB_WRITE(%g1, %g5, %g6)
+       TSB_LOCK_TAG(%g1, %g2, %g7)
+       TSB_WRITE(%g1, %g5, %g6)
        ba,pt           %xcc, kvmap_dtlb_load
         nop
 
@@ -222,16 +222,16 @@ kvmap_linear_patch:
 kvmap_dtlb_vmalloc_addr:
        KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath)
 
-       KTSB_LOCK_TAG(%g1, %g2, %g7)
+       TSB_LOCK_TAG(%g1, %g2, %g7)
 
        /* Load and check PTE.  */
        ldxa            [%g5] ASI_PHYS_USE_EC, %g5
        mov             1, %g7
        sllx            %g7, TSB_TAG_INVALID_BIT, %g7
        brgez,a,pn      %g5, kvmap_dtlb_longpath
-        KTSB_STORE(%g1, %g7)
+        TSB_STORE(%g1, %g7)
 
-       KTSB_WRITE(%g1, %g5, %g6)
+       TSB_WRITE(%g1, %g5, %g6)
 
        /* fallthrough to TLB load */
 
index 44dc093..fad1bd0 100644 (file)
@@ -215,7 +215,7 @@ struct grpci2_priv {
 DEFINE_SPINLOCK(grpci2_dev_lock);
 struct grpci2_priv *grpci2priv;
 
-int grpci2_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int grpci2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        struct grpci2_priv *priv = dev->bus->sysdata;
        int irq_group;
index 42f28c7..acaebb6 100644 (file)
@@ -508,6 +508,8 @@ const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
 }
 EXPORT_SYMBOL(mdesc_node_name);
 
+static u64 max_cpus = 64;
+
 static void __init report_platform_properties(void)
 {
        struct mdesc_handle *hp = mdesc_grab();
@@ -543,8 +545,10 @@ static void __init report_platform_properties(void)
        if (v)
                printk("PLATFORM: watchdog-max-timeout [%llu ms]\n", *v);
        v = mdesc_get_property(hp, pn, "max-cpus", NULL);
-       if (v)
-               printk("PLATFORM: max-cpus [%llu]\n", *v);
+       if (v) {
+               max_cpus = *v;
+               printk("PLATFORM: max-cpus [%llu]\n", max_cpus);
+       }
 
 #ifdef CONFIG_SMP
        {
@@ -715,7 +719,7 @@ static void __cpuinit set_proc_ids(struct mdesc_handle *hp)
 }
 
 static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
-                                        unsigned char def)
+                                        unsigned long def, unsigned long max)
 {
        u64 val;
 
@@ -726,6 +730,9 @@ static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
        if (!val || val >= 64)
                goto use_default;
 
+       if (val > max)
+               val = max;
+
        *mask = ((1U << val) * 64U) - 1U;
        return;
 
@@ -736,19 +743,28 @@ use_default:
 static void __cpuinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
                                     struct trap_per_cpu *tb)
 {
+       static int printed;
        const u64 *val;
 
        val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);
-       get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7);
+       get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7, ilog2(max_cpus * 2));
 
        val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);
-       get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7);
+       get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7, 8);
 
        val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);
-       get_one_mondo_bits(val, &tb->resum_qmask, 6);
+       get_one_mondo_bits(val, &tb->resum_qmask, 6, 7);
 
        val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);
-       get_one_mondo_bits(val, &tb->nonresum_qmask, 2);
+       get_one_mondo_bits(val, &tb->nonresum_qmask, 2, 2);
+       if (!printed++) {
+               pr_info("SUN4V: Mondo queue sizes "
+                       "[cpu(%u) dev(%u) r(%u) nr(%u)]\n",
+                       tb->cpu_mondo_qmask + 1,
+                       tb->dev_mondo_qmask + 1,
+                       tb->resum_qmask + 1,
+                       tb->nonresum_qmask + 1);
+       }
 }
 
 static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask)
index 8ac23e6..343b0f9 100644 (file)
@@ -80,8 +80,11 @@ static void n2_pcr_write(u64 val)
 {
        unsigned long ret;
 
-       ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
-       if (ret != HV_EOK)
+       if (val & PCR_N2_HTRACE) {
+               ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
+               if (ret != HV_EOK)
+                       write_pcr(val);
+       } else
                write_pcr(val);
 }
 
@@ -106,6 +109,10 @@ static int __init register_perf_hsvc(void)
                        perf_hsvc_group = HV_GRP_N2_CPU;
                        break;
 
+               case SUN4V_CHIP_NIAGARA3:
+                       perf_hsvc_group = HV_GRP_KT_CPU;
+                       break;
+
                default:
                        return -ENODEV;
                }
index 171e8d8..614da62 100644 (file)
@@ -1343,7 +1343,8 @@ static bool __init supported_pmu(void)
                sparc_pmu = &niagara1_pmu;
                return true;
        }
-       if (!strcmp(sparc_pmu_type, "niagara2")) {
+       if (!strcmp(sparc_pmu_type, "niagara2") ||
+           !strcmp(sparc_pmu_type, "niagara3")) {
                sparc_pmu = &niagara2_pmu;
                return true;
        }
index c4dd099..3e9daea 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/interrupt.h>
 #include <linux/cpu.h>
 #include <linux/initrd.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -46,6 +47,8 @@
 #include <asm/mmu.h>
 #include <asm/ns87303.h>
 #include <asm/btext.h>
+#include <asm/elf.h>
+#include <asm/mdesc.h>
 
 #ifdef CONFIG_IP_PNP
 #include <net/ipconfig.h>
@@ -269,6 +272,40 @@ void __init sun4v_patch(void)
        sun4v_hvapi_init();
 }
 
+static void __init popc_patch(void)
+{
+       struct popc_3insn_patch_entry *p3;
+       struct popc_6insn_patch_entry *p6;
+
+       p3 = &__popc_3insn_patch;
+       while (p3 < &__popc_3insn_patch_end) {
+               unsigned long i, addr = p3->addr;
+
+               for (i = 0; i < 3; i++) {
+                       *(unsigned int *) (addr +  (i * 4)) = p3->insns[i];
+                       wmb();
+                       __asm__ __volatile__("flush     %0"
+                                            : : "r" (addr +  (i * 4)));
+               }
+
+               p3++;
+       }
+
+       p6 = &__popc_6insn_patch;
+       while (p6 < &__popc_6insn_patch_end) {
+               unsigned long i, addr = p6->addr;
+
+               for (i = 0; i < 6; i++) {
+                       *(unsigned int *) (addr +  (i * 4)) = p6->insns[i];
+                       wmb();
+                       __asm__ __volatile__("flush     %0"
+                                            : : "r" (addr +  (i * 4)));
+               }
+
+               p6++;
+       }
+}
+
 #ifdef CONFIG_SMP
 void __init boot_cpu_id_too_large(int cpu)
 {
@@ -278,6 +315,154 @@ void __init boot_cpu_id_too_large(int cpu)
 }
 #endif
 
+/* On Ultra, we support all of the v8 capabilities. */
+unsigned long sparc64_elf_hwcap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
+                                  HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV |
+                                  HWCAP_SPARC_V9);
+EXPORT_SYMBOL(sparc64_elf_hwcap);
+
+static const char *hwcaps[] = {
+       "flush", "stbar", "swap", "muldiv", "v9",
+       "ultra3", "blkinit", "n2",
+
+       /* These strings are as they appear in the machine description
+        * 'hwcap-list' property for cpu nodes.
+        */
+       "mul32", "div32", "fsmuld", "v8plus", "popc", "vis", "vis2",
+       "ASIBlkInit", "fmaf", "vis3", "hpc", "random", "trans", "fjfmau",
+       "ima", "cspare",
+};
+
+void cpucap_info(struct seq_file *m)
+{
+       unsigned long caps = sparc64_elf_hwcap;
+       int i, printed = 0;
+
+       seq_puts(m, "cpucaps\t\t: ");
+       for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
+               unsigned long bit = 1UL << i;
+               if (caps & bit) {
+                       seq_printf(m, "%s%s",
+                                  printed ? "," : "", hwcaps[i]);
+                       printed++;
+               }
+       }
+       seq_putc(m, '\n');
+}
+
+static void __init report_hwcaps(unsigned long caps)
+{
+       int i, printed = 0;
+
+       printk(KERN_INFO "CPU CAPS: [");
+       for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
+               unsigned long bit = 1UL << i;
+               if (caps & bit) {
+                       printk(KERN_CONT "%s%s",
+                              printed ? "," : "", hwcaps[i]);
+                       if (++printed == 8) {
+                               printk(KERN_CONT "]\n");
+                               printk(KERN_INFO "CPU CAPS: [");
+                               printed = 0;
+                       }
+               }
+       }
+       printk(KERN_CONT "]\n");
+}
+
+static unsigned long __init mdesc_cpu_hwcap_list(void)
+{
+       struct mdesc_handle *hp;
+       unsigned long caps = 0;
+       const char *prop;
+       int len;
+       u64 pn;
+
+       hp = mdesc_grab();
+       if (!hp)
+               return 0;
+
+       pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "cpu");
+       if (pn == MDESC_NODE_NULL)
+               goto out;
+
+       prop = mdesc_get_property(hp, pn, "hwcap-list", &len);
+       if (!prop)
+               goto out;
+
+       while (len) {
+               int i, plen;
+
+               for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
+                       unsigned long bit = 1UL << i;
+
+                       if (!strcmp(prop, hwcaps[i])) {
+                               caps |= bit;
+                               break;
+                       }
+               }
+
+               plen = strlen(prop) + 1;
+               prop += plen;
+               len -= plen;
+       }
+
+out:
+       mdesc_release(hp);
+       return caps;
+}
+
+/* This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+static void __init init_sparc64_elf_hwcap(void)
+{
+       unsigned long cap = sparc64_elf_hwcap;
+       unsigned long mdesc_caps;
+
+       if (tlb_type == cheetah || tlb_type == cheetah_plus)
+               cap |= HWCAP_SPARC_ULTRA3;
+       else if (tlb_type == hypervisor) {
+               if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
+                   sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
+                   sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
+                       cap |= HWCAP_SPARC_BLKINIT;
+               if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
+                   sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
+                       cap |= HWCAP_SPARC_N2;
+       }
+
+       cap |= (AV_SPARC_MUL32 | AV_SPARC_DIV32 | AV_SPARC_V8PLUS);
+
+       mdesc_caps = mdesc_cpu_hwcap_list();
+       if (!mdesc_caps) {
+               if (tlb_type == spitfire)
+                       cap |= AV_SPARC_VIS;
+               if (tlb_type == cheetah || tlb_type == cheetah_plus)
+                       cap |= AV_SPARC_VIS | AV_SPARC_VIS2;
+               if (tlb_type == cheetah_plus)
+                       cap |= AV_SPARC_POPC;
+               if (tlb_type == hypervisor) {
+                       if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1)
+                               cap |= AV_SPARC_ASI_BLK_INIT;
+                       if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
+                           sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
+                               cap |= (AV_SPARC_VIS | AV_SPARC_VIS2 |
+                                       AV_SPARC_ASI_BLK_INIT |
+                                       AV_SPARC_POPC);
+                       if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
+                               cap |= (AV_SPARC_VIS3 | AV_SPARC_HPC |
+                                       AV_SPARC_FMAF);
+               }
+       }
+       sparc64_elf_hwcap = cap | mdesc_caps;
+
+       report_hwcaps(sparc64_elf_hwcap);
+
+       if (sparc64_elf_hwcap & AV_SPARC_POPC)
+               popc_patch();
+}
+
 void __init setup_arch(char **cmdline_p)
 {
        /* Initialize PROM console and command line. */
@@ -337,6 +522,7 @@ void __init setup_arch(char **cmdline_p)
        init_cur_cpu_trap(current_thread_info());
 
        paging_init();
+       init_sparc64_elf_hwcap();
 }
 
 extern int stop_a_enabled;
index 372ad59..83b47ab 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/bitops.h>
 
 #include <asm/system.h>
 #include <asm/cpudata.h>
@@ -38,5 +39,15 @@ EXPORT_SYMBOL(sun4v_niagara_setperf);
 EXPORT_SYMBOL(sun4v_niagara2_getperf);
 EXPORT_SYMBOL(sun4v_niagara2_setperf);
 
+/* from hweight.S */
+EXPORT_SYMBOL(__arch_hweight8);
+EXPORT_SYMBOL(__arch_hweight16);
+EXPORT_SYMBOL(__arch_hweight32);
+EXPORT_SYMBOL(__arch_hweight64);
+
+/* from ffs_ffz.S */
+EXPORT_SYMBOL(ffs);
+EXPORT_SYMBOL(__ffs);
+
 /* Exporting a symbol from /init/main.c */
 EXPORT_SYMBOL(saved_command_line);
index 8cdbe59..c59af54 100644 (file)
 #include <asm/head.h>
 #include <asm/io.h>
 
-static int hv_supports_soft_state;
-
-static unsigned long kimage_addr_to_ra(const char *p)
-{
-       unsigned long val = (unsigned long) p;
+#include "kernel.h"
 
-       return kern_base + (val - KERNBASE);
-}
+static int hv_supports_soft_state;
 
 static void do_set_sstate(unsigned long state, const char *msg)
 {
index 35cff16..76e4ac1 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/bitops.h>
 #include <linux/perf_event.h>
 #include <linux/ratelimit.h>
+#include <linux/bitops.h>
 #include <asm/fpumacro.h>
 
 enum direction {
@@ -373,16 +374,11 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
        }
 }
 
-static char popc_helper[] = {
-0, 1, 1, 2, 1, 2, 2, 3,
-1, 2, 2, 3, 2, 3, 3, 4, 
-};
-
 int handle_popc(u32 insn, struct pt_regs *regs)
 {
-       u64 value;
-       int ret, i, rd = ((insn >> 25) & 0x1f);
        int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
+       int ret, rd = ((insn >> 25) & 0x1f);
+       u64 value;
                                
        perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
        if (insn & 0x2000) {
@@ -392,10 +388,7 @@ int handle_popc(u32 insn, struct pt_regs *regs)
                maybe_flush_windows(0, insn & 0x1f, rd, from_kernel);
                value = fetch_reg(insn & 0x1f, regs);
        }
-       for (ret = 0, i = 0; i < 16; i++) {
-               ret += popc_helper[value & 0xf];
-               value >>= 4;
-       }
+       ret = hweight64(value);
        if (rd < 16) {
                if (rd)
                        regs->u_regs[rd] = ret;
index c022075..0e16056 100644 (file)
@@ -107,7 +107,26 @@ SECTIONS
                *(.sun4v_2insn_patch)
                __sun4v_2insn_patch_end = .;
        }
-
+       .swapper_tsb_phys_patch : {
+               __swapper_tsb_phys_patch = .;
+               *(.swapper_tsb_phys_patch)
+               __swapper_tsb_phys_patch_end = .;
+       }
+       .swapper_4m_tsb_phys_patch : {
+               __swapper_4m_tsb_phys_patch = .;
+               *(.swapper_4m_tsb_phys_patch)
+               __swapper_4m_tsb_phys_patch_end = .;
+       }
+       .popc_3insn_patch : {
+               __popc_3insn_patch = .;
+               *(.popc_3insn_patch)
+               __popc_3insn_patch_end = .;
+       }
+       .popc_6insn_patch : {
+               __popc_6insn_patch = .;
+               *(.popc_6insn_patch)
+               __popc_6insn_patch_end = .;
+       }
        PERCPU_SECTION(SMP_CACHE_BYTES)
 
        . = ALIGN(PAGE_SIZE);
index 7f01b8f..a3fc437 100644 (file)
@@ -31,13 +31,13 @@ lib-$(CONFIG_SPARC64) += NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o
 lib-$(CONFIG_SPARC64) += NGpatch.o NGpage.o NGbzero.o
 
 lib-$(CONFIG_SPARC64) += NG2memcpy.o NG2copy_from_user.o NG2copy_to_user.o
-lib-$(CONFIG_SPARC64) +=  NG2patch.o NG2page.o
+lib-$(CONFIG_SPARC64) +=  NG2patch.o
 
 lib-$(CONFIG_SPARC64) += GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o
 lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o
 
 lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o
-lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o
+lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o
 
 obj-y                 += iomap.o
 obj-$(CONFIG_SPARC32) += atomic32.o
diff --git a/arch/sparc/lib/NG2page.S b/arch/sparc/lib/NG2page.S
deleted file mode 100644 (file)
index 73b6b7c..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* NG2page.S: Niagara-2 optimized clear and copy page.
- *
- * Copyright (C) 2007 (davem@davemloft.net)
- */
-
-#include <asm/asi.h>
-#include <asm/page.h>
-#include <asm/visasm.h>
-
-       .text
-       .align  32
-
-       /* This is heavily simplified from the sun4u variants
-        * because Niagara-2 does not have any D-cache aliasing issues.
-        */
-NG2copy_user_page:     /* %o0=dest, %o1=src, %o2=vaddr */
-       prefetch        [%o1 + 0x00], #one_read
-       prefetch        [%o1 + 0x40], #one_read
-       VISEntryHalf
-       set             PAGE_SIZE, %g7
-       sub             %o0, %o1, %g3
-1:     stxa            %g0, [%o1 + %g3] ASI_BLK_INIT_QUAD_LDD_P
-       subcc           %g7, 64, %g7
-       ldda            [%o1] ASI_BLK_P, %f0
-       stda            %f0, [%o1 + %g3] ASI_BLK_P
-       add             %o1, 64, %o1
-       bne,pt          %xcc, 1b
-        prefetch       [%o1 + 0x40], #one_read
-       membar          #Sync
-       VISExitHalf
-       retl
-        nop
-
-#define BRANCH_ALWAYS  0x10680000
-#define NOP            0x01000000
-#define NG_DO_PATCH(OLD, NEW)  \
-       sethi   %hi(NEW), %g1; \
-       or      %g1, %lo(NEW), %g1; \
-       sethi   %hi(OLD), %g2; \
-       or      %g2, %lo(OLD), %g2; \
-       sub     %g1, %g2, %g1; \
-       sethi   %hi(BRANCH_ALWAYS), %g3; \
-       sll     %g1, 11, %g1; \
-       srl     %g1, 11 + 2, %g1; \
-       or      %g3, %lo(BRANCH_ALWAYS), %g3; \
-       or      %g3, %g1, %g3; \
-       stw     %g3, [%g2]; \
-       sethi   %hi(NOP), %g3; \
-       or      %g3, %lo(NOP), %g3; \
-       stw     %g3, [%g2 + 0x4]; \
-       flush   %g2;
-
-       .globl  niagara2_patch_pageops
-       .type   niagara2_patch_pageops,#function
-niagara2_patch_pageops:
-       NG_DO_PATCH(copy_user_page, NG2copy_user_page)
-       NG_DO_PATCH(_clear_page, NGclear_page)
-       NG_DO_PATCH(clear_user_page, NGclear_user_page)
-       retl
-        nop
-       .size   niagara2_patch_pageops,.-niagara2_patch_pageops
index 428920d..b9e790b 100644 (file)
         */
 
 NGcopy_user_page:      /* %o0=dest, %o1=src, %o2=vaddr */
-       prefetch        [%o1 + 0x00], #one_read
-       mov             8, %g1
-       mov             16, %g2
-       mov             24, %g3
+       save            %sp, -192, %sp
+       rd              %asi, %g3
+       wr              %g0, ASI_BLK_INIT_QUAD_LDD_P, %asi
        set             PAGE_SIZE, %g7
+       prefetch        [%i1 + 0x00], #one_read
+       prefetch        [%i1 + 0x40], #one_read
 
-1:     ldda            [%o1 + %g0] ASI_BLK_INIT_QUAD_LDD_P, %o2
-       ldda            [%o1 + %g2] ASI_BLK_INIT_QUAD_LDD_P, %o4
-       prefetch        [%o1 + 0x40], #one_read
-       add             %o1, 32, %o1
-       stxa            %o2, [%o0 + %g0] ASI_BLK_INIT_QUAD_LDD_P
-       stxa            %o3, [%o0 + %g1] ASI_BLK_INIT_QUAD_LDD_P
-       ldda            [%o1 + %g0] ASI_BLK_INIT_QUAD_LDD_P, %o2
-       stxa            %o4, [%o0 + %g2] ASI_BLK_INIT_QUAD_LDD_P
-       stxa            %o5, [%o0 + %g3] ASI_BLK_INIT_QUAD_LDD_P
-       ldda            [%o1 + %g2] ASI_BLK_INIT_QUAD_LDD_P, %o4
-       add             %o1, 32, %o1
-       add             %o0, 32, %o0
-       stxa            %o2, [%o0 + %g0] ASI_BLK_INIT_QUAD_LDD_P
-       stxa            %o3, [%o0 + %g1] ASI_BLK_INIT_QUAD_LDD_P
-       stxa            %o4, [%o0 + %g2] ASI_BLK_INIT_QUAD_LDD_P
-       stxa            %o5, [%o0 + %g3] ASI_BLK_INIT_QUAD_LDD_P
-       subcc           %g7, 64, %g7
+1:     prefetch        [%i1 + 0x80], #one_read
+       prefetch        [%i1 + 0xc0], #one_read
+       ldda            [%i1 + 0x00] %asi, %o2
+       ldda            [%i1 + 0x10] %asi, %o4
+       ldda            [%i1 + 0x20] %asi, %l2
+       ldda            [%i1 + 0x30] %asi, %l4
+       stxa            %o2, [%i0 + 0x00] %asi
+       stxa            %o3, [%i0 + 0x08] %asi
+       stxa            %o4, [%i0 + 0x10] %asi
+       stxa            %o5, [%i0 + 0x18] %asi
+       stxa            %l2, [%i0 + 0x20] %asi
+       stxa            %l3, [%i0 + 0x28] %asi
+       stxa            %l4, [%i0 + 0x30] %asi
+       stxa            %l5, [%i0 + 0x38] %asi
+       ldda            [%i1 + 0x40] %asi, %o2
+       ldda            [%i1 + 0x50] %asi, %o4
+       ldda            [%i1 + 0x60] %asi, %l2
+       ldda            [%i1 + 0x70] %asi, %l4
+       stxa            %o2, [%i0 + 0x40] %asi
+       stxa            %o3, [%i0 + 0x48] %asi
+       stxa            %o4, [%i0 + 0x50] %asi
+       stxa            %o5, [%i0 + 0x58] %asi
+       stxa            %l2, [%i0 + 0x60] %asi
+       stxa            %l3, [%i0 + 0x68] %asi
+       stxa            %l4, [%i0 + 0x70] %asi
+       stxa            %l5, [%i0 + 0x78] %asi
+       add             %i1, 128, %i1
+       subcc           %g7, 128, %g7
        bne,pt          %xcc, 1b
-        add            %o0, 32, %o0
+        add            %i0, 128, %i0
+       wr              %g3, 0x0, %asi
        membar          #Sync
-       retl
-        nop
+       ret
+        restore
 
-       .globl          NGclear_page, NGclear_user_page
+       .align          32
 NGclear_page:          /* %o0=dest */
 NGclear_user_page:     /* %o0=dest, %o1=vaddr */
-       mov             8, %g1
-       mov             16, %g2
-       mov             24, %g3
+       rd              %asi, %g3
+       wr              %g0, ASI_BLK_INIT_QUAD_LDD_P, %asi
        set             PAGE_SIZE, %g7
 
-1:     stxa            %g0, [%o0 + %g0] ASI_BLK_INIT_QUAD_LDD_P
-       stxa            %g0, [%o0 + %g1] ASI_BLK_INIT_QUAD_LDD_P
-       stxa            %g0, [%o0 + %g2] ASI_BLK_INIT_QUAD_LDD_P
-       stxa            %g0, [%o0 + %g3] ASI_BLK_INIT_QUAD_LDD_P
-       add             %o0, 32, %o0
-       stxa            %g0, [%o0 + %g0] ASI_BLK_INIT_QUAD_LDD_P
-       stxa            %g0, [%o0 + %g1] ASI_BLK_INIT_QUAD_LDD_P
-       stxa            %g0, [%o0 + %g2] ASI_BLK_INIT_QUAD_LDD_P
-       stxa            %g0, [%o0 + %g3] ASI_BLK_INIT_QUAD_LDD_P
-       subcc           %g7, 64, %g7
+1:     stxa            %g0, [%o0 + 0x00] %asi
+       stxa            %g0, [%o0 + 0x08] %asi
+       stxa            %g0, [%o0 + 0x10] %asi
+       stxa            %g0, [%o0 + 0x18] %asi
+       stxa            %g0, [%o0 + 0x20] %asi
+       stxa            %g0, [%o0 + 0x28] %asi
+       stxa            %g0, [%o0 + 0x30] %asi
+       stxa            %g0, [%o0 + 0x38] %asi
+       stxa            %g0, [%o0 + 0x40] %asi
+       stxa            %g0, [%o0 + 0x48] %asi
+       stxa            %g0, [%o0 + 0x50] %asi
+       stxa            %g0, [%o0 + 0x58] %asi
+       stxa            %g0, [%o0 + 0x60] %asi
+       stxa            %g0, [%o0 + 0x68] %asi
+       stxa            %g0, [%o0 + 0x70] %asi
+       stxa            %g0, [%o0 + 0x78] %asi
+       stxa            %g0, [%o0 + 0x80] %asi
+       stxa            %g0, [%o0 + 0x88] %asi
+       stxa            %g0, [%o0 + 0x90] %asi
+       stxa            %g0, [%o0 + 0x98] %asi
+       stxa            %g0, [%o0 + 0xa0] %asi
+       stxa            %g0, [%o0 + 0xa8] %asi
+       stxa            %g0, [%o0 + 0xb0] %asi
+       stxa            %g0, [%o0 + 0xb8] %asi
+       stxa            %g0, [%o0 + 0xc0] %asi
+       stxa            %g0, [%o0 + 0xc8] %asi
+       stxa            %g0, [%o0 + 0xd0] %asi
+       stxa            %g0, [%o0 + 0xd8] %asi
+       stxa            %g0, [%o0 + 0xe0] %asi
+       stxa            %g0, [%o0 + 0xe8] %asi
+       stxa            %g0, [%o0 + 0xf0] %asi
+       stxa            %g0, [%o0 + 0xf8] %asi
+       subcc           %g7, 256, %g7
        bne,pt          %xcc, 1b
-        add            %o0, 32, %o0
+        add            %o0, 256, %o0
+       wr              %g3, 0x0, %asi
        membar          #Sync
        retl
         nop
index 8600eb2..1d32b54 100644 (file)
@@ -65,7 +65,7 @@ int __atomic_add_unless(atomic_t *v, int a, int u)
        if (ret != u)
                v->counter += a;
        spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
-       return ret != u;
+       return ret;
 }
 EXPORT_SYMBOL(__atomic_add_unless);
 
diff --git a/arch/sparc/lib/ffs.S b/arch/sparc/lib/ffs.S
new file mode 100644 (file)
index 0000000..b39389f
--- /dev/null
@@ -0,0 +1,84 @@
+#include <linux/linkage.h>
+
+       .register       %g2,#scratch
+
+       .text
+       .align  32
+
+ENTRY(ffs)
+       brnz,pt %o0, 1f
+        mov    1, %o1
+       retl
+        clr    %o0
+       nop
+       nop
+ENTRY(__ffs)
+       sllx    %o0, 32, %g1            /* 1  */
+       srlx    %o0, 32, %g2
+
+       clr     %o1                     /* 2  */
+       movrz   %g1, %g2, %o0
+
+       movrz   %g1, 32, %o1            /* 3  */
+1:     clr     %o2
+
+       sllx    %o0, (64 - 16), %g1     /* 4  */
+       srlx    %o0, 16, %g2
+
+       movrz   %g1, %g2, %o0           /* 5  */
+       clr     %o3
+
+       movrz   %g1, 16, %o2            /* 6  */
+       clr     %o4
+
+       and     %o0, 0xff, %g1          /* 7  */
+       srlx    %o0, 8, %g2
+
+       movrz   %g1, %g2, %o0           /* 8  */
+       clr     %o5
+
+       movrz   %g1, 8, %o3             /* 9  */
+       add     %o2, %o1, %o2
+
+       and     %o0, 0xf, %g1           /* 10 */
+       srlx    %o0, 4, %g2
+
+       movrz   %g1, %g2, %o0           /* 11 */
+       add     %o2, %o3, %o2
+
+       movrz   %g1, 4, %o4             /* 12 */
+
+       and     %o0, 0x3, %g1           /* 13 */
+       srlx    %o0, 2, %g2
+
+       movrz   %g1, %g2, %o0           /* 14 */
+       add     %o2, %o4, %o2
+
+       movrz   %g1, 2, %o5             /* 15 */
+
+       and     %o0, 0x1, %g1           /* 16 */
+
+       add     %o2, %o5, %o2           /* 17 */
+       xor     %g1, 0x1, %g1
+
+       retl                            /* 18 */
+        add    %o2, %g1, %o0
+ENDPROC(ffs)
+ENDPROC(__ffs)
+
+       .section        .popc_6insn_patch, "ax"
+       .word           ffs
+       brz,pn  %o0, 98f
+        neg    %o0, %g1
+       xnor    %o0, %g1, %o1
+       popc    %o1, %o0
+98:    retl
+        nop
+       .word           __ffs
+       neg     %o0, %g1
+       xnor    %o0, %g1, %o1
+       popc    %o1, %o0
+       retl
+        sub    %o0, 1, %o0
+       nop
+       .previous
diff --git a/arch/sparc/lib/hweight.S b/arch/sparc/lib/hweight.S
new file mode 100644 (file)
index 0000000..95414e0
--- /dev/null
@@ -0,0 +1,51 @@
+#include <linux/linkage.h>
+
+       .text
+       .align  32
+ENTRY(__arch_hweight8)
+       ba,pt   %xcc, __sw_hweight8
+        nop
+       nop
+ENDPROC(__arch_hweight8)
+       .section        .popc_3insn_patch, "ax"
+       .word           __arch_hweight8
+       sllx            %o0, 64-8, %g1
+       retl
+        popc           %g1, %o0
+       .previous
+
+ENTRY(__arch_hweight16)
+       ba,pt   %xcc, __sw_hweight16
+        nop
+       nop
+ENDPROC(__arch_hweight16)
+       .section        .popc_3insn_patch, "ax"
+       .word           __arch_hweight16
+       sllx            %o0, 64-16, %g1
+       retl
+        popc           %g1, %o0
+       .previous
+
+ENTRY(__arch_hweight32)
+       ba,pt   %xcc, __sw_hweight32
+        nop
+       nop
+ENDPROC(__arch_hweight32)
+       .section        .popc_3insn_patch, "ax"
+       .word           __arch_hweight32
+       sllx            %o0, 64-32, %g1
+       retl
+        popc           %g1, %o0
+       .previous
+
+ENTRY(__arch_hweight64)
+       ba,pt   %xcc, __sw_hweight64
+        nop
+       nop
+ENDPROC(__arch_hweight64)
+       .section        .popc_3insn_patch, "ax"
+       .word           __arch_hweight64
+       retl
+        popc           %o0, %o0
+       nop
+       .previous
index 3fd8e18..581531d 100644 (file)
@@ -1597,6 +1597,44 @@ static void __init tsb_phys_patch(void)
 static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR];
 extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
 
+static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned long pa)
+{
+       pa >>= KTSB_PHYS_SHIFT;
+
+       while (start < end) {
+               unsigned int *ia = (unsigned int *)(unsigned long)*start;
+
+               ia[0] = (ia[0] & ~0x3fffff) | (pa >> 10);
+               __asm__ __volatile__("flush     %0" : : "r" (ia));
+
+               ia[1] = (ia[1] & ~0x3ff) | (pa & 0x3ff);
+               __asm__ __volatile__("flush     %0" : : "r" (ia + 1));
+
+               start++;
+       }
+}
+
+static void ktsb_phys_patch(void)
+{
+       extern unsigned int __swapper_tsb_phys_patch;
+       extern unsigned int __swapper_tsb_phys_patch_end;
+       unsigned long ktsb_pa;
+
+       ktsb_pa = kern_base + ((unsigned long)&swapper_tsb[0] - KERNBASE);
+       patch_one_ktsb_phys(&__swapper_tsb_phys_patch,
+                           &__swapper_tsb_phys_patch_end, ktsb_pa);
+#ifndef CONFIG_DEBUG_PAGEALLOC
+       {
+       extern unsigned int __swapper_4m_tsb_phys_patch;
+       extern unsigned int __swapper_4m_tsb_phys_patch_end;
+       ktsb_pa = (kern_base +
+                  ((unsigned long)&swapper_4m_tsb[0] - KERNBASE));
+       patch_one_ktsb_phys(&__swapper_4m_tsb_phys_patch,
+                           &__swapper_4m_tsb_phys_patch_end, ktsb_pa);
+       }
+#endif
+}
+
 static void __init sun4v_ktsb_init(void)
 {
        unsigned long ktsb_pa;
@@ -1716,8 +1754,10 @@ void __init paging_init(void)
                sun4u_pgprot_init();
 
        if (tlb_type == cheetah_plus ||
-           tlb_type == hypervisor)
+           tlb_type == hypervisor) {
                tsb_phys_patch();
+               ktsb_phys_patch();
+       }
 
        if (tlb_type == hypervisor) {
                sun4v_patch_tlb_handlers();
index 0249b8b..b30f71a 100644 (file)
@@ -12,6 +12,7 @@ config TILE
        select GENERIC_PENDING_IRQ if SMP
        select GENERIC_IRQ_SHOW
        select SYS_HYPERVISOR
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG if !M386
 
 # FIXME: investigate whether we need/want these options.
 #      select HAVE_IOREMAP_PROT
index 849ab2f..aec60dc 100644 (file)
@@ -2,3 +2,41 @@ include include/asm-generic/Kbuild.asm
 
 header-y += ucontext.h
 header-y += hardwall.h
+
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += cputime.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += fb.h
+generic-y += fcntl.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipc.h
+generic-y += ipcbuf.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += local.h
+generic-y += module.h
+generic-y += msgbuf.h
+generic-y += mutex.h
+generic-y += param.h
+generic-y += parport.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sembuf.h
+generic-y += serial.h
+generic-y += shmbuf.h
+generic-y += shmparam.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += statfs.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += types.h
+generic-y += ucontext.h
+generic-y += xor.h
diff --git a/arch/tile/include/asm/bug.h b/arch/tile/include/asm/bug.h
deleted file mode 100644 (file)
index b12fd89..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bug.h>
diff --git a/arch/tile/include/asm/bugs.h b/arch/tile/include/asm/bugs.h
deleted file mode 100644 (file)
index 61791e1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bugs.h>
diff --git a/arch/tile/include/asm/cputime.h b/arch/tile/include/asm/cputime.h
deleted file mode 100644 (file)
index 6d68ad7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/cputime.h>
diff --git a/arch/tile/include/asm/device.h b/arch/tile/include/asm/device.h
deleted file mode 100644 (file)
index f0a4c25..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/device.h>
diff --git a/arch/tile/include/asm/div64.h b/arch/tile/include/asm/div64.h
deleted file mode 100644 (file)
index 6cd978c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
diff --git a/arch/tile/include/asm/emergency-restart.h b/arch/tile/include/asm/emergency-restart.h
deleted file mode 100644 (file)
index 3711bd9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/emergency-restart.h>
diff --git a/arch/tile/include/asm/errno.h b/arch/tile/include/asm/errno.h
deleted file mode 100644 (file)
index 4c82b50..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/errno.h>
diff --git a/arch/tile/include/asm/fb.h b/arch/tile/include/asm/fb.h
deleted file mode 100644 (file)
index 3a4988e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/fb.h>
diff --git a/arch/tile/include/asm/fcntl.h b/arch/tile/include/asm/fcntl.h
deleted file mode 100644 (file)
index 46ab12d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/fcntl.h>
index 51537ff..c66f793 100644 (file)
@@ -75,12 +75,6 @@ extern void __set_fixmap(enum fixed_addresses idx,
 
 #define set_fixmap(idx, phys) \
                __set_fixmap(idx, phys, PAGE_KERNEL)
-/*
- * Some hardware wants to get fixmapped without caching.
- */
-#define set_fixmap_nocache(idx, phys) \
-               __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
-
 #define clear_fixmap(idx) \
                __set_fixmap(idx, 0, __pgprot(0))
 
diff --git a/arch/tile/include/asm/ioctl.h b/arch/tile/include/asm/ioctl.h
deleted file mode 100644 (file)
index b279fe0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/tile/include/asm/ioctls.h b/arch/tile/include/asm/ioctls.h
deleted file mode 100644 (file)
index ec34c76..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctls.h>
diff --git a/arch/tile/include/asm/ipc.h b/arch/tile/include/asm/ipc.h
deleted file mode 100644 (file)
index a46e3d9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/arch/tile/include/asm/ipcbuf.h b/arch/tile/include/asm/ipcbuf.h
deleted file mode 100644 (file)
index 84c7e51..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipcbuf.h>
diff --git a/arch/tile/include/asm/irq_regs.h b/arch/tile/include/asm/irq_regs.h
deleted file mode 100644 (file)
index 3dd9c0b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/tile/include/asm/kdebug.h b/arch/tile/include/asm/kdebug.h
deleted file mode 100644 (file)
index 6ece1b0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/tile/include/asm/local.h b/arch/tile/include/asm/local.h
deleted file mode 100644 (file)
index c11c530..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local.h>
diff --git a/arch/tile/include/asm/module.h b/arch/tile/include/asm/module.h
deleted file mode 100644 (file)
index 1e4b79f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/module.h>
diff --git a/arch/tile/include/asm/msgbuf.h b/arch/tile/include/asm/msgbuf.h
deleted file mode 100644 (file)
index 809134c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/msgbuf.h>
diff --git a/arch/tile/include/asm/mutex.h b/arch/tile/include/asm/mutex.h
deleted file mode 100644 (file)
index ff6101a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/tile/include/asm/param.h b/arch/tile/include/asm/param.h
deleted file mode 100644 (file)
index 965d454..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/param.h>
diff --git a/arch/tile/include/asm/parport.h b/arch/tile/include/asm/parport.h
deleted file mode 100644 (file)
index cf252af..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/parport.h>
diff --git a/arch/tile/include/asm/poll.h b/arch/tile/include/asm/poll.h
deleted file mode 100644 (file)
index c98509d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/poll.h>
diff --git a/arch/tile/include/asm/posix_types.h b/arch/tile/include/asm/posix_types.h
deleted file mode 100644 (file)
index 22cae62..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/posix_types.h>
diff --git a/arch/tile/include/asm/resource.h b/arch/tile/include/asm/resource.h
deleted file mode 100644 (file)
index 04bc4db..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/resource.h>
diff --git a/arch/tile/include/asm/scatterlist.h b/arch/tile/include/asm/scatterlist.h
deleted file mode 100644 (file)
index 35d786f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/scatterlist.h>
diff --git a/arch/tile/include/asm/sembuf.h b/arch/tile/include/asm/sembuf.h
deleted file mode 100644 (file)
index 7673b83..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/sembuf.h>
diff --git a/arch/tile/include/asm/serial.h b/arch/tile/include/asm/serial.h
deleted file mode 100644 (file)
index a0cb0ca..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/serial.h>
diff --git a/arch/tile/include/asm/shmbuf.h b/arch/tile/include/asm/shmbuf.h
deleted file mode 100644 (file)
index 83c05fc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/shmbuf.h>
diff --git a/arch/tile/include/asm/shmparam.h b/arch/tile/include/asm/shmparam.h
deleted file mode 100644 (file)
index 93f30de..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/shmparam.h>
diff --git a/arch/tile/include/asm/socket.h b/arch/tile/include/asm/socket.h
deleted file mode 100644 (file)
index 6b71384..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/socket.h>
diff --git a/arch/tile/include/asm/sockios.h b/arch/tile/include/asm/sockios.h
deleted file mode 100644 (file)
index def6d47..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/sockios.h>
diff --git a/arch/tile/include/asm/statfs.h b/arch/tile/include/asm/statfs.h
deleted file mode 100644 (file)
index 0b91fe1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/statfs.h>
diff --git a/arch/tile/include/asm/termbits.h b/arch/tile/include/asm/termbits.h
deleted file mode 100644 (file)
index 3935b10..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termbits.h>
diff --git a/arch/tile/include/asm/termios.h b/arch/tile/include/asm/termios.h
deleted file mode 100644 (file)
index 280d78a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termios.h>
diff --git a/arch/tile/include/asm/types.h b/arch/tile/include/asm/types.h
deleted file mode 100644 (file)
index b9e79bc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/types.h>
diff --git a/arch/tile/include/asm/ucontext.h b/arch/tile/include/asm/ucontext.h
deleted file mode 100644 (file)
index 9bc07b9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ucontext.h>
diff --git a/arch/tile/include/asm/xor.h b/arch/tile/include/asm/xor.h
deleted file mode 100644 (file)
index c82eb12..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/xor.h>
diff --git a/arch/tile/include/hv/drv_srom_intf.h b/arch/tile/include/hv/drv_srom_intf.h
new file mode 100644 (file)
index 0000000..6395faa
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 Tilera 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, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * @file drv_srom_intf.h
+ * Interface definitions for the SPI Flash ROM driver.
+ */
+
+#ifndef _SYS_HV_INCLUDE_DRV_SROM_INTF_H
+#define _SYS_HV_INCLUDE_DRV_SROM_INTF_H
+
+/** Read this offset to get the total device size. */
+#define SROM_TOTAL_SIZE_OFF   0xF0000000
+
+/** Read this offset to get the device sector size. */
+#define SROM_SECTOR_SIZE_OFF  0xF0000004
+
+/** Read this offset to get the device page size. */
+#define SROM_PAGE_SIZE_OFF    0xF0000008
+
+/** Write this offset to flush any pending writes. */
+#define SROM_FLUSH_OFF        0xF1000000
+
+/** Write this offset, plus the byte offset of the start of a sector, to
+ *  erase a sector.  Any write data is ignored, but there must be at least
+ *  one byte of write data.  Only applies when the driver is in MTD mode.
+ */
+#define SROM_ERASE_OFF        0xF2000000
+
+#endif /* _SYS_HV_INCLUDE_DRV_SROM_INTF_H */
index 6d4cb5d..2a8014c 100644 (file)
@@ -228,7 +228,7 @@ err_cont:
  * (pin - 1) converts from the PCI standard's [1:4] convention to
  * a normal [0:3] range.
  */
-static int tile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int tile_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        struct pci_controller *controller =
                (struct pci_controller *)dev->sysdata;
index c4be58c..f6f50f2 100644 (file)
@@ -78,7 +78,6 @@ static struct clocksource cycle_counter_cs = {
        .rating = 300,
        .read = clocksource_get_cycles,
        .mask = CLOCKSOURCE_MASK(64),
-       .shift = 22,   /* typical value, e.g. x86 tsc uses this */
        .flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -91,8 +90,6 @@ void __init setup_clock(void)
        cycles_per_sec = hv_sysconf(HV_SYSCONF_CPU_SPEED);
        sched_clock_mult =
                clocksource_hz2mult(cycles_per_sec, SCHED_CLOCK_SHIFT);
-       cycle_counter_cs.mult =
-               clocksource_hz2mult(cycles_per_sec, cycle_counter_cs.shift);
 }
 
 void __init calibrate_delay(void)
@@ -107,7 +104,7 @@ void __init calibrate_delay(void)
 void __init time_init(void)
 {
        /* Initialize and register the clock source. */
-       clocksource_register(&cycle_counter_cs);
+       clocksource_register_hz(&cycle_counter_cs, cycles_per_sec);
 
        /* Start up the tile-timer interrupt source on the boot cpu. */
        setup_tile_timer();
index 4e10c40..7309988 100644 (file)
@@ -836,8 +836,7 @@ void __init mem_init(void)
 #endif
 
 #ifdef CONFIG_FLATMEM
-       if (!mem_map)
-               BUG();
+       BUG_ON(!mem_map);
 #endif
 
 #ifdef CONFIG_HIGHMEM
index 22745b4..a492e59 100644 (file)
@@ -368,7 +368,7 @@ static const struct net_device_ops uml_netdev_ops = {
        .ndo_open               = uml_net_open,
        .ndo_stop               = uml_net_close,
        .ndo_start_xmit         = uml_net_start_xmit,
-       .ndo_set_multicast_list = uml_net_set_multicast_list,
+       .ndo_set_rx_mode        = uml_net_set_multicast_list,
        .ndo_tx_timeout         = uml_net_tx_timeout,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = uml_net_change_mtu,
index 100eab8..4892fbb 100644 (file)
@@ -102,7 +102,7 @@ void pci_puv3_preinit(void)
        writel(readl(PCIBRI_CMD) | PCIBRI_CMD_IO | PCIBRI_CMD_MEM, PCIBRI_CMD);
 }
 
-static int __init pci_puv3_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init pci_puv3_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        if (dev->bus->number == 0) {
 #ifdef CONFIG_ARCH_FPGA /* 4 pci slots */
index 153aa6f..6a47bb2 100644 (file)
@@ -72,6 +72,7 @@ config X86
        select USE_GENERIC_SMP_HELPERS if SMP
        select HAVE_BPF_JIT if (X86_64 && NET)
        select CLKEVT_I8253
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG
 
 config INSTRUCTION_DECODER
        def_bool (KPROBES || PERF_EVENTS)
@@ -1905,7 +1906,7 @@ config PCI_BIOS
 # x86-64 doesn't support PCI BIOS access from long mode so always go direct.
 config PCI_DIRECT
        def_bool y
-       depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY || PCI_GOOLPC))
+       depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY || PCI_GOOLPC || PCI_GOMMCONFIG))
 
 config PCI_MMCONFIG
        def_bool y
index 7b439d9..41935fa 100644 (file)
@@ -27,8 +27,8 @@ static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *in
 
        desc->base2             = (info->base_addr & 0xff000000) >> 24;
        /*
-        * Don't allow setting of the lm bit. It is useless anyway
-        * because 64bit system calls require __USER_CS:
+        * Don't allow setting of the lm bit. It would confuse
+        * user_64bit_mode and would get overridden by sysret anyway.
         */
        desc->l                 = 0;
 }
index d02804d..d8e8eef 100644 (file)
@@ -40,8 +40,6 @@
 #include <linux/compiler.h>
 #include <asm/page.h>
 
-#include <xen/xen.h>
-
 #define build_mmio_read(name, size, type, reg, barrier) \
 static inline type name(const volatile void __iomem *addr) \
 { type ret; asm volatile("mov" size " %1,%0":reg (ret) \
@@ -334,6 +332,7 @@ extern void fixup_early_ioremap(void);
 extern bool is_early_ioremap_ptep(pte_t *ptep);
 
 #ifdef CONFIG_XEN
+#include <xen/xen.h>
 struct bio_vec;
 
 extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
index f9a3209..7e50f06 100644 (file)
@@ -17,7 +17,6 @@
  *  Vectors   0 ...  31 : system traps and exceptions - hardcoded events
  *  Vectors  32 ... 127 : device interrupts
  *  Vector  128         : legacy int80 syscall interface
- *  Vector  204         : legacy x86_64 vsyscall emulation
  *  Vectors 129 ... INVALIDATE_TLB_VECTOR_START-1 except 204 : device interrupts
  *  Vectors INVALIDATE_TLB_VECTOR_START ... 255 : special interrupts
  *
@@ -51,9 +50,6 @@
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR                        0x80
 #endif
-#ifdef CONFIG_X86_64
-# define VSYSCALL_EMU_VECTOR           0xcc
-#endif
 
 /*
  * Vectors 0x30-0x3f are used for ISA interrupts.
index 2c76521..8e8b9a4 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <asm/desc_defs.h>
 #include <asm/kmap_types.h>
+#include <asm/pgtable_types.h>
 
 struct page;
 struct thread_struct;
@@ -63,6 +64,11 @@ struct paravirt_callee_save {
 struct pv_info {
        unsigned int kernel_rpl;
        int shared_kernel_pmd;
+
+#ifdef CONFIG_X86_64
+       u16 extra_user_64bit_cs;  /* __USER_CS if none */
+#endif
+
        int paravirt_enabled;
        const char *name;
 };
index 2193715..0d1171c 100644 (file)
@@ -751,8 +751,6 @@ static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
                     :: "a" (eax), "c" (ecx));
 }
 
-extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
-
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 extern void init_amd_e400_c1e_mask(void);
 
index 94e7618..3566454 100644 (file)
@@ -131,6 +131,9 @@ struct pt_regs {
 #ifdef __KERNEL__
 
 #include <linux/init.h>
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt_types.h>
+#endif
 
 struct cpuinfo_x86;
 struct task_struct;
@@ -187,6 +190,22 @@ static inline int v8086_mode(struct pt_regs *regs)
 #endif
 }
 
+#ifdef CONFIG_X86_64
+static inline bool user_64bit_mode(struct pt_regs *regs)
+{
+#ifndef CONFIG_PARAVIRT
+       /*
+        * On non-paravirt systems, this is the only long mode CPL 3
+        * selector.  We do not allow long mode selectors in the LDT.
+        */
+       return regs->cs == __USER_CS;
+#else
+       /* Headers are too twisted for this to go in paravirt.h. */
+       return regs->cs == __USER_CS || regs->cs == pv_info.extra_user_64bit_cs;
+#endif
+}
+#endif
+
 /*
  * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
  * when it traps.  The previous stack will be directly underneath the saved
index 2bae0a5..0012d09 100644 (file)
@@ -40,7 +40,6 @@ asmlinkage void alignment_check(void);
 asmlinkage void machine_check(void);
 #endif /* CONFIG_X86_MCE */
 asmlinkage void simd_coprocessor_error(void);
-asmlinkage void emulate_vsyscall(void);
 
 dotraplinkage void do_divide_error(struct pt_regs *, long);
 dotraplinkage void do_debug(struct pt_regs *, long);
@@ -67,7 +66,6 @@ dotraplinkage void do_alignment_check(struct pt_regs *, long);
 dotraplinkage void do_machine_check(struct pt_regs *, long);
 #endif
 dotraplinkage void do_simd_coprocessor_error(struct pt_regs *, long);
-dotraplinkage void do_emulate_vsyscall(struct pt_regs *, long);
 #ifdef CONFIG_X86_32
 dotraplinkage void do_iret_error(struct pt_regs *, long);
 #endif
index 705bf13..d92641c 100644 (file)
@@ -681,6 +681,8 @@ __SYSCALL(__NR_syncfs, sys_syncfs)
 __SYSCALL(__NR_sendmmsg, sys_sendmmsg)
 #define __NR_setns                             308
 __SYSCALL(__NR_setns, sys_setns)
+#define __NR_getcpu                            309
+__SYSCALL(__NR_getcpu, sys_getcpu)
 
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
index 6010707..eaea1d3 100644 (file)
@@ -27,6 +27,12 @@ extern struct timezone sys_tz;
 
 extern void map_vsyscall(void);
 
+/*
+ * Called on instruction fetch fault in vsyscall page.
+ * Returns true if handled.
+ */
+extern bool emulate_vsyscall(struct pt_regs *regs, unsigned long address);
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_X86_VSYSCALL_H */
index 0410557..82f2912 100644 (file)
@@ -17,19 +17,6 @@ CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
 endif
 
-#
-# vsyscalls (which work on the user stack) should have
-# no stack-protector checks:
-#
-nostackp := $(call cc-option, -fno-stack-protector)
-CFLAGS_vsyscall_64.o   := $(PROFILING) -g0 $(nostackp)
-CFLAGS_hpet.o          := $(nostackp)
-CFLAGS_paravirt.o      := $(nostackp)
-GCOV_PROFILE_vsyscall_64.o     := n
-GCOV_PROFILE_hpet.o            := n
-GCOV_PROFILE_tsc.o             := n
-GCOV_PROFILE_paravirt.o                := n
-
 obj-y                  := process_$(BITS).o signal.o entry_$(BITS).o
 obj-y                  += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
 obj-y                  += time.o ioport.o ldt.o dumpstack.o
index 5812404..f50e7fb 100644 (file)
@@ -149,6 +149,29 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
 }
 EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
 
+/*
+ * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
+ * which can obviate IPI to trigger checking of need_resched.
+ * We execute MONITOR against need_resched and enter optimized wait state
+ * through MWAIT. Whenever someone changes need_resched, we would be woken
+ * up from MWAIT (without an IPI).
+ *
+ * New with Core Duo processors, MWAIT can take some hints based on CPU
+ * capability.
+ */
+void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
+{
+       if (!need_resched()) {
+               if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
+                       clflush((void *)&current_thread_info()->flags);
+
+               __monitor((void *)&current_thread_info()->flags, 0, 0);
+               smp_mb();
+               if (!need_resched())
+                       __mwait(ax, cx);
+       }
+}
+
 void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
 {
        unsigned int cpu = smp_processor_id();
index 45fbb8f..f88af2c 100644 (file)
@@ -1590,6 +1590,7 @@ static __init int intel_pmu_init(void)
                break;
 
        case 42: /* SandyBridge */
+       case 45: /* SandyBridge, "Romely-EP" */
                memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
 
index e13329d..6419bb0 100644 (file)
@@ -1111,7 +1111,6 @@ zeroentry spurious_interrupt_bug do_spurious_interrupt_bug
 zeroentry coprocessor_error do_coprocessor_error
 errorentry alignment_check do_alignment_check
 zeroentry simd_coprocessor_error do_simd_coprocessor_error
-zeroentry emulate_vsyscall do_emulate_vsyscall
 
 
        /* Reload gs selector with exception handling */
index 613a793..d90272e 100644 (file)
@@ -307,6 +307,10 @@ struct pv_info pv_info = {
        .paravirt_enabled = 0,
        .kernel_rpl = 0,
        .shared_kernel_pmd = 1, /* Only used when CONFIG_X86_PAE is set */
+
+#ifdef CONFIG_X86_64
+       .extra_user_64bit_cs = __USER_CS,
+#endif
 };
 
 struct pv_init_ops pv_init_ops = {
index e1ba8cb..e7e3b01 100644 (file)
@@ -438,29 +438,6 @@ void cpu_idle_wait(void)
 }
 EXPORT_SYMBOL_GPL(cpu_idle_wait);
 
-/*
- * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
- * which can obviate IPI to trigger checking of need_resched.
- * We execute MONITOR against need_resched and enter optimized wait state
- * through MWAIT. Whenever someone changes need_resched, we would be woken
- * up from MWAIT (without an IPI).
- *
- * New with Core Duo processors, MWAIT can take some hints based on CPU
- * capability.
- */
-void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
-{
-       if (!need_resched()) {
-               if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
-                       clflush((void *)&current_thread_info()->flags);
-
-               __monitor((void *)&current_thread_info()->flags, 0, 0);
-               smp_mb();
-               if (!need_resched())
-                       __mwait(ax, cx);
-       }
-}
-
 /* Default MONITOR/MWAIT with no hints, used for default C1 state */
 static void mwait_idle(void)
 {
index a3d0dc5..7a3b651 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/kdebug.h>
+#include <linux/cpuidle.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -109,7 +110,8 @@ void cpu_idle(void)
                        local_irq_disable();
                        /* Don't trace irqs off for idle */
                        stop_critical_timings();
-                       pm_idle();
+                       if (cpuidle_idle_call())
+                               pm_idle();
                        start_critical_timings();
                }
                tick_nohz_restart_sched_tick();
index ca6f7ab..f693e44 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/ftrace.h>
+#include <linux/cpuidle.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -136,7 +137,8 @@ void cpu_idle(void)
                        enter_idle();
                        /* Don't trace irqs off for idle */
                        stop_critical_timings();
-                       pm_idle();
+                       if (cpuidle_idle_call())
+                               pm_idle();
                        start_critical_timings();
 
                        /* In many cases the interrupt that ended idle
index 7977f0c..c346d11 100644 (file)
@@ -74,7 +74,7 @@ static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
 
 #ifdef CONFIG_X86_64
                case 0x40 ... 0x4f:
-                       if (regs->cs != __USER_CS)
+                       if (!user_64bit_mode(regs))
                                /* 32-bit mode: register increment */
                                return 0;
                        /* 64-bit mode: REX prefix */
index 9682ec5..6913369 100644 (file)
@@ -872,12 +872,6 @@ void __init trap_init(void)
        set_bit(SYSCALL_VECTOR, used_vectors);
 #endif
 
-#ifdef CONFIG_X86_64
-       BUG_ON(test_bit(VSYSCALL_EMU_VECTOR, used_vectors));
-       set_system_intr_gate(VSYSCALL_EMU_VECTOR, &emulate_vsyscall);
-       set_bit(VSYSCALL_EMU_VECTOR, used_vectors);
-#endif
-
        /*
         * Should be a barrier for any external CPU state:
         */
index 4aa9c54..0f703f1 100644 (file)
@@ -71,7 +71,6 @@ PHDRS {
        text PT_LOAD FLAGS(5);          /* R_E */
        data PT_LOAD FLAGS(6);          /* RW_ */
 #ifdef CONFIG_X86_64
-       user PT_LOAD FLAGS(5);          /* R_E */
 #ifdef CONFIG_SMP
        percpu PT_LOAD FLAGS(6);        /* RW_ */
 #endif
@@ -154,44 +153,16 @@ SECTIONS
 
 #ifdef CONFIG_X86_64
 
-#define VSYSCALL_ADDR (-10*1024*1024)
-
-#define VLOAD_OFFSET (VSYSCALL_ADDR - __vsyscall_0 + LOAD_OFFSET)
-#define VLOAD(x) (ADDR(x) - VLOAD_OFFSET)
-
-#define VVIRT_OFFSET (VSYSCALL_ADDR - __vsyscall_0)
-#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
-
-       . = ALIGN(4096);
-       __vsyscall_0 = .;
-
-       . = VSYSCALL_ADDR;
-       .vsyscall : AT(VLOAD(.vsyscall)) {
-               *(.vsyscall_0)
-
-               . = 1024;
-               *(.vsyscall_1)
-
-               . = 2048;
-               *(.vsyscall_2)
-
-               . = 4096;  /* Pad the whole page. */
-       } :user =0xcc
-       . = ALIGN(__vsyscall_0 + PAGE_SIZE, PAGE_SIZE);
-
-#undef VSYSCALL_ADDR
-#undef VLOAD_OFFSET
-#undef VLOAD
-#undef VVIRT_OFFSET
-#undef VVIRT
-
+       . = ALIGN(PAGE_SIZE);
        __vvar_page = .;
 
        .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) {
+               /* work around gold bug 13023 */
+               __vvar_beginning_hack = .;
 
-             /* Place all vvars at the offsets in asm/vvar.h. */
-#define EMIT_VVAR(name, offset)                \
-               . = offset;             \
+               /* Place all vvars at the offsets in asm/vvar.h. */
+#define EMIT_VVAR(name, offset)                        \
+               . = __vvar_beginning_hack + offset;     \
                *(.vvar_ ## name)
 #define __VVAR_KERNEL_LDS
 #include <asm/vvar.h>
index dda7dff..18ae83d 100644 (file)
@@ -18,9 +18,6 @@
  *  use the vDSO.
  */
 
-/* Disable profiling for userspace code: */
-#define DISABLE_BRANCH_PROFILING
-
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <asm/vgtod.h>
 #include <asm/traps.h>
 
+#define CREATE_TRACE_POINTS
+#include "vsyscall_trace.h"
+
 DEFINE_VVAR(int, vgetcpu_mode);
 DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data) =
 {
        .lock = __SEQLOCK_UNLOCKED(__vsyscall_gtod_data.lock),
 };
 
+static enum { EMULATE, NATIVE, NONE } vsyscall_mode = EMULATE;
+
+static int __init vsyscall_setup(char *str)
+{
+       if (str) {
+               if (!strcmp("emulate", str))
+                       vsyscall_mode = EMULATE;
+               else if (!strcmp("native", str))
+                       vsyscall_mode = NATIVE;
+               else if (!strcmp("none", str))
+                       vsyscall_mode = NONE;
+               else
+                       return -EINVAL;
+
+               return 0;
+       }
+
+       return -EINVAL;
+}
+early_param("vsyscall", vsyscall_setup);
+
 void update_vsyscall_tz(void)
 {
        unsigned long flags;
@@ -100,7 +121,7 @@ static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
 
        printk("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
               level, tsk->comm, task_pid_nr(tsk),
-              message, regs->ip - 2, regs->cs,
+              message, regs->ip, regs->cs,
               regs->sp, regs->ax, regs->si, regs->di);
 }
 
@@ -118,46 +139,39 @@ static int addr_to_vsyscall_nr(unsigned long addr)
        return nr;
 }
 
-void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
+bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 {
        struct task_struct *tsk;
        unsigned long caller;
        int vsyscall_nr;
        long ret;
 
-       local_irq_enable();
-
        /*
-        * Real 64-bit user mode code has cs == __USER_CS.  Anything else
-        * is bogus.
+        * No point in checking CS -- the only way to get here is a user mode
+        * trap to a high address, which means that we're in 64-bit user code.
         */
-       if (regs->cs != __USER_CS) {
-               /*
-                * If we trapped from kernel mode, we might as well OOPS now
-                * instead of returning to some random address and OOPSing
-                * then.
-                */
-               BUG_ON(!user_mode(regs));
 
-               /* Compat mode and non-compat 32-bit CS should both segfault. */
-               warn_bad_vsyscall(KERN_WARNING, regs,
-                                 "illegal int 0xcc from 32-bit mode");
-               goto sigsegv;
+       WARN_ON_ONCE(address != regs->ip);
+
+       if (vsyscall_mode == NONE) {
+               warn_bad_vsyscall(KERN_INFO, regs,
+                                 "vsyscall attempted with vsyscall=none");
+               return false;
        }
 
-       /*
-        * x86-ism here: regs->ip points to the instruction after the int 0xcc,
-        * and int 0xcc is two bytes long.
-        */
-       vsyscall_nr = addr_to_vsyscall_nr(regs->ip - 2);
+       vsyscall_nr = addr_to_vsyscall_nr(address);
+
+       trace_emulate_vsyscall(vsyscall_nr);
+
        if (vsyscall_nr < 0) {
                warn_bad_vsyscall(KERN_WARNING, regs,
-                                 "illegal int 0xcc (exploit attempt?)");
+                                 "misaligned vsyscall (exploit attempt or buggy program) -- look up the vsyscall kernel parameter if you need a workaround");
                goto sigsegv;
        }
 
        if (get_user(caller, (unsigned long __user *)regs->sp) != 0) {
-               warn_bad_vsyscall(KERN_WARNING, regs, "int 0xcc with bad stack (exploit attempt?)");
+               warn_bad_vsyscall(KERN_WARNING, regs,
+                                 "vsyscall with bad stack (exploit attempt?)");
                goto sigsegv;
        }
 
@@ -202,13 +216,11 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
        regs->ip = caller;
        regs->sp += 8;
 
-       local_irq_disable();
-       return;
+       return true;
 
 sigsegv:
-       regs->ip -= 2;  /* The faulting instruction should be the int 0xcc. */
        force_sig(SIGSEGV, current);
-       local_irq_disable();
+       return true;
 }
 
 /*
@@ -256,15 +268,21 @@ cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)
 
 void __init map_vsyscall(void)
 {
-       extern char __vsyscall_0;
-       unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0);
+       extern char __vsyscall_page;
+       unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page);
        extern char __vvar_page;
        unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page);
 
-       /* Note that VSYSCALL_MAPPED_PAGES must agree with the code below. */
-       __set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL);
+       __set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_vsyscall,
+                    vsyscall_mode == NATIVE
+                    ? PAGE_KERNEL_VSYSCALL
+                    : PAGE_KERNEL_VVAR);
+       BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_FIRST_PAGE) !=
+                    (unsigned long)VSYSCALL_START);
+
        __set_fixmap(VVAR_PAGE, physaddr_vvar_page, PAGE_KERNEL_VVAR);
-       BUILD_BUG_ON((unsigned long)__fix_to_virt(VVAR_PAGE) != (unsigned long)VVAR_ADDRESS);
+       BUILD_BUG_ON((unsigned long)__fix_to_virt(VVAR_PAGE) !=
+                    (unsigned long)VVAR_ADDRESS);
 }
 
 static int __init vsyscall_init(void)
index ffa845e..c9596a9 100644 (file)
@@ -7,21 +7,31 @@
  */
 
 #include <linux/linkage.h>
+
 #include <asm/irq_vectors.h>
+#include <asm/page_types.h>
+#include <asm/unistd_64.h>
+
+__PAGE_ALIGNED_DATA
+       .globl __vsyscall_page
+       .balign PAGE_SIZE, 0xcc
+       .type __vsyscall_page, @object
+__vsyscall_page:
+
+       mov $__NR_gettimeofday, %rax
+       syscall
+       ret
 
-/* The unused parts of the page are filled with 0xcc by the linker script. */
+       .balign 1024, 0xcc
+       mov $__NR_time, %rax
+       syscall
+       ret
 
-.section .vsyscall_0, "a"
-ENTRY(vsyscall_0)
-       int $VSYSCALL_EMU_VECTOR
-END(vsyscall_0)
+       .balign 1024, 0xcc
+       mov $__NR_getcpu, %rax
+       syscall
+       ret
 
-.section .vsyscall_1, "a"
-ENTRY(vsyscall_1)
-       int $VSYSCALL_EMU_VECTOR
-END(vsyscall_1)
+       .balign 4096, 0xcc
 
-.section .vsyscall_2, "a"
-ENTRY(vsyscall_2)
-       int $VSYSCALL_EMU_VECTOR
-END(vsyscall_2)
+       .size __vsyscall_page, 4096
diff --git a/arch/x86/kernel/vsyscall_trace.h b/arch/x86/kernel/vsyscall_trace.h
new file mode 100644 (file)
index 0000000..a8b2ede
--- /dev/null
@@ -0,0 +1,29 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM vsyscall
+
+#if !defined(__VSYSCALL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __VSYSCALL_TRACE_H
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(emulate_vsyscall,
+
+           TP_PROTO(int nr),
+
+           TP_ARGS(nr),
+
+           TP_STRUCT__entry(__field(int, nr)),
+
+           TP_fast_assign(
+                          __entry->nr = nr;
+                          ),
+
+           TP_printk("nr = %d", __entry->nr)
+);
+
+#endif
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH ../../arch/x86/kernel
+#define TRACE_INCLUDE_FILE vsyscall_trace
+#include <trace/define_trace.h>
index 4d09df0..247aae3 100644 (file)
@@ -105,7 +105,7 @@ check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr,
                 * but for now it's good enough to assume that long
                 * mode only uses well known segments or kernel.
                 */
-               return (!user_mode(regs)) || (regs->cs == __USER_CS);
+               return (!user_mode(regs) || user_64bit_mode(regs));
 #endif
        case 0x60:
                /* 0x64 thru 0x67 are valid prefixes in all modes. */
@@ -720,6 +720,18 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
                if (is_errata100(regs, address))
                        return;
 
+#ifdef CONFIG_X86_64
+               /*
+                * Instruction fetch faults in the vsyscall page might need
+                * emulation.
+                */
+               if (unlikely((error_code & PF_INSTR) &&
+                            ((address & ~0xfff) == VSYSCALL_START))) {
+                       if (emulate_vsyscall(regs, address))
+                               return;
+               }
+#endif
+
                if (unlikely(show_unhandled_signals))
                        show_signal_msg(regs, error_code, address, tsk);
 
index 68c3c13..ae3cb23 100644 (file)
@@ -246,10 +246,9 @@ static void add_resources(struct pci_root_info *info)
 
                conflict = insert_resource_conflict(root, res);
                if (conflict)
-                       dev_err(&info->bridge->dev,
-                               "address space collision: host bridge window %pR "
-                               "conflicts with %s %pR\n",
-                               res, conflict->name, conflict);
+                       dev_info(&info->bridge->dev,
+                                "ignoring host bridge window %pR (conflicts with %s %pR)\n",
+                                res, conflict->name, conflict);
                else
                        pci_bus_add_resource(info->bus, res, 0);
        }
index 67858be..9917609 100644 (file)
@@ -257,6 +257,7 @@ static int ce4100_conf_read(unsigned int seg, unsigned int bus,
 {
        int i;
 
+       WARN_ON(seg);
        if (bus == 1) {
                for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
                        if (bus1_fixups[i].dev_func == devfn &&
@@ -282,6 +283,7 @@ static int ce4100_conf_write(unsigned int seg, unsigned int bus,
 {
        int i;
 
+       WARN_ON(seg);
        if (bus == 1) {
                for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
                        if (bus1_fixups[i].dev_func == devfn &&
index 5fe7502..92df322 100644 (file)
@@ -246,13 +246,6 @@ static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = {
                },
        },
 #endif         /* __i386__ */
-       {
-               .callback = find_sort_method,
-               .ident = "Dell System",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
-               },
-       },
        {
                .callback = set_bf_sort,
                .ident = "Dell PowerEdge 1950",
@@ -293,6 +286,13 @@ static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"),
                },
        },
+       {
+               .callback = find_sort_method,
+               .ident = "Dell System",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+               },
+       },
        {
                .callback = set_bf_sort,
                .ident = "HP ProLiant BL20p G3",
index e6fd847..4f2c704 100644 (file)
@@ -22,7 +22,7 @@ static int pci_conf1_read(unsigned int seg, unsigned int bus,
 {
        unsigned long flags;
 
-       if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
+       if (seg || (bus > 255) || (devfn > 255) || (reg > 4095)) {
                *value = -1;
                return -EINVAL;
        }
@@ -53,7 +53,7 @@ static int pci_conf1_write(unsigned int seg, unsigned int bus,
 {
        unsigned long flags;
 
-       if ((bus > 255) || (devfn > 255) || (reg > 4095))
+       if (seg || (bus > 255) || (devfn > 255) || (reg > 4095))
                return -EINVAL;
 
        raw_spin_lock_irqsave(&pci_config_lock, flags);
@@ -97,6 +97,7 @@ static int pci_conf2_read(unsigned int seg, unsigned int bus,
        unsigned long flags;
        int dev, fn;
 
+       WARN_ON(seg);
        if ((bus > 255) || (devfn > 255) || (reg > 255)) {
                *value = -1;
                return -EINVAL;
@@ -138,6 +139,7 @@ static int pci_conf2_write(unsigned int seg, unsigned int bus,
        unsigned long flags;
        int dev, fn;
 
+       WARN_ON(seg);
        if ((bus > 255) || (devfn > 255) || (reg > 255)) 
                return -EINVAL;
 
index 5c9e245..512a88c 100644 (file)
@@ -34,6 +34,7 @@ static int pci_conf1_mq_read(unsigned int seg, unsigned int bus,
        unsigned long flags;
        void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus));
 
+       WARN_ON(seg);
        if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
                return -EINVAL;
 
@@ -73,6 +74,7 @@ static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
        unsigned long flags;
        void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus));
 
+       WARN_ON(seg);
        if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) 
                return -EINVAL;
 
index 13700ec..5262603 100644 (file)
@@ -206,6 +206,8 @@ static int pci_olpc_read(unsigned int seg, unsigned int bus,
 {
        uint32_t *addr;
 
+       WARN_ON(seg);
+
        /* Use the hardware mechanism for non-simulated devices */
        if (!is_simulated(bus, devfn))
                return pci_direct_conf1.read(seg, bus, devfn, reg, len, value);
@@ -264,6 +266,8 @@ static int pci_olpc_read(unsigned int seg, unsigned int bus,
 static int pci_olpc_write(unsigned int seg, unsigned int bus,
                unsigned int devfn, int reg, int len, uint32_t value)
 {
+       WARN_ON(seg);
+
        /* Use the hardware mechanism for non-simulated devices */
        if (!is_simulated(bus, devfn))
                return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
index a5f7d0d..f685535 100644 (file)
@@ -181,6 +181,7 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
        unsigned long flags;
        unsigned long bx = (bus << 8) | devfn;
 
+       WARN_ON(seg);
        if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
                return -EINVAL;
 
@@ -247,6 +248,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,
        unsigned long flags;
        unsigned long bx = (bus << 8) | devfn;
 
+       WARN_ON(seg);
        if ((bus > 255) || (devfn > 255) || (reg > 255)) 
                return -EINVAL;
 
index 03008f7..6f2f8ee 100644 (file)
@@ -24,7 +24,7 @@ static void pci_visws_disable_irq(struct pci_dev *dev) { }
 
 unsigned int pci_bus0, pci_bus1;
 
-static int __init visws_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init visws_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq, bus = dev->bus->number;
 
index f61ccdd..1ea3877 100644 (file)
@@ -1,3 +1,4 @@
 obj-$(CONFIG_X86_MRST)         += mrst.o
 obj-$(CONFIG_X86_MRST)         += vrtc.o
 obj-$(CONFIG_EARLY_PRINTK_MRST)        += early_printk_mrst.o
+obj-$(CONFIG_X86_MRST)         += pmu.o
diff --git a/arch/x86/platform/mrst/pmu.c b/arch/x86/platform/mrst/pmu.c
new file mode 100644 (file)
index 0000000..9281da7
--- /dev/null
@@ -0,0 +1,817 @@
+/*
+ * mrst/pmu.c - driver for MRST Power Management Unit
+ *
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * 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/cpuidle.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/seq_file.h>
+#include <linux/sfi.h>
+#include <asm/intel_scu_ipc.h>
+#include "pmu.h"
+
+#define IPCMSG_FW_REVISION     0xF4
+
+struct mrst_device {
+       u16 pci_dev_num;        /* DEBUG only */
+       u16 lss;
+       u16 latest_request;
+       unsigned int pci_state_counts[PCI_D3cold + 1]; /* DEBUG only */
+};
+
+/*
+ * comlete list of MRST PCI devices
+ */
+static struct mrst_device mrst_devs[] = {
+/*  0 */ { 0x0800, LSS_SPI0 },         /* Moorestown SPI Ctrl 0 */
+/*  1 */ { 0x0801, LSS_SPI1 },         /* Moorestown SPI Ctrl 1 */
+/*  2 */ { 0x0802, LSS_I2C0 },         /* Moorestown I2C 0 */
+/*  3 */ { 0x0803, LSS_I2C1 },         /* Moorestown I2C 1 */
+/*  4 */ { 0x0804, LSS_I2C2 },         /* Moorestown I2C 2 */
+/*  5 */ { 0x0805, LSS_KBD },          /* Moorestown Keyboard Ctrl */
+/*  6 */ { 0x0806, LSS_USB_HC },       /* Moorestown USB Ctrl */
+/*  7 */ { 0x0807, LSS_SD_HC0 },       /* Moorestown SD Host Ctrl 0 */
+/*  8 */ { 0x0808, LSS_SD_HC1 },       /* Moorestown SD Host Ctrl 1 */
+/*  9 */ { 0x0809, LSS_NAND },         /* Moorestown NAND Ctrl */
+/* 10 */ { 0x080a, LSS_AUDIO },                /* Moorestown Audio Ctrl */
+/* 11 */ { 0x080b, LSS_IMAGING },      /* Moorestown ISP */
+/* 12 */ { 0x080c, LSS_SECURITY },     /* Moorestown Security Controller */
+/* 13 */ { 0x080d, LSS_DISPLAY },      /* Moorestown External Displays */
+/* 14 */ { 0x080e, 0 },                        /* Moorestown SCU IPC */
+/* 15 */ { 0x080f, LSS_GPIO },         /* Moorestown GPIO Controller */
+/* 16 */ { 0x0810, 0 },                        /* Moorestown Power Management Unit */
+/* 17 */ { 0x0811, LSS_USB_OTG },      /* Moorestown OTG Ctrl */
+/* 18 */ { 0x0812, LSS_SPI2 },         /* Moorestown SPI Ctrl 2 */
+/* 19 */ { 0x0813, 0 },                        /* Moorestown SC DMA */
+/* 20 */ { 0x0814, LSS_AUDIO_LPE },    /* Moorestown LPE DMA */
+/* 21 */ { 0x0815, LSS_AUDIO_SSP },    /* Moorestown SSP0 */
+
+/* 22 */ { 0x084F, LSS_SD_HC2 },       /* Moorestown SD Host Ctrl 2 */
+
+/* 23 */ { 0x4102, 0 },                        /* Lincroft */
+/* 24 */ { 0x4110, 0 },                        /* Lincroft */
+};
+
+/* n.b. We ignore PCI-id 0x815 in LSS9 b/c MeeGo has no driver for it */
+static u16 mrst_lss9_pci_ids[] = {0x080a, 0x0814, 0};
+static u16 mrst_lss10_pci_ids[] = {0x0800, 0x0801, 0x0802, 0x0803,
+                                       0x0804, 0x0805, 0x080f, 0};
+
+/* handle concurrent SMP invokations of pmu_pci_set_power_state() */
+static spinlock_t mrst_pmu_power_state_lock;
+
+static unsigned int wake_counters[MRST_NUM_LSS];       /* DEBUG only */
+static unsigned int pmu_irq_stats[INT_INVALID + 1];    /* DEBUG only */
+
+static int graphics_is_off;
+static int lss_s0i3_enabled;
+static bool mrst_pmu_s0i3_enable;
+
+/*  debug counters */
+static u32 pmu_wait_ready_calls;
+static u32 pmu_wait_ready_udelays;
+static u32 pmu_wait_ready_udelays_max;
+static u32 pmu_wait_done_calls;
+static u32 pmu_wait_done_udelays;
+static u32 pmu_wait_done_udelays_max;
+static u32 pmu_set_power_state_entry;
+static u32 pmu_set_power_state_send_cmd;
+
+static struct mrst_device *pci_id_2_mrst_dev(u16 pci_dev_num)
+{
+       int index = 0;
+
+       if ((pci_dev_num >= 0x0800) && (pci_dev_num <= 0x815))
+               index = pci_dev_num - 0x800;
+       else if (pci_dev_num == 0x084F)
+               index = 22;
+       else if (pci_dev_num == 0x4102)
+               index = 23;
+       else if (pci_dev_num == 0x4110)
+               index = 24;
+
+       if (pci_dev_num != mrst_devs[index].pci_dev_num) {
+               WARN_ONCE(1, FW_BUG "Unknown PCI device 0x%04X\n", pci_dev_num);
+               return 0;
+       }
+
+       return &mrst_devs[index];
+}
+
+/**
+ * mrst_pmu_validate_cstates
+ * @dev: cpuidle_device
+ *
+ * Certain states are not appropriate for governor to pick in some cases.
+ * This function will be called as cpuidle_device's prepare callback and
+ * thus tells governor to ignore such states when selecting the next state
+ * to enter.
+ */
+
+#define IDLE_STATE4_IS_C6      4
+#define IDLE_STATE5_IS_S0I3    5
+
+int mrst_pmu_invalid_cstates(void)
+{
+       int cpu = smp_processor_id();
+
+       /*
+        * Demote to C4 if the PMU is busy.
+        * Since LSS changes leave the busy bit clear...
+        * busy means either the PMU is waiting for an ACK-C6 that
+        * isn't coming due to an MWAIT that returned immediately;
+        * or we returned from S0i3 successfully, and the PMU
+        * is not done sending us interrupts.
+        */
+       if (pmu_read_busy_status())
+               return 1 << IDLE_STATE4_IS_C6 | 1 << IDLE_STATE5_IS_S0I3;
+
+       /*
+        * Disallow S0i3 if: PMU is not initialized, or CPU1 is active,
+        * or if device LSS is insufficient, or the GPU is active,
+        * or if it has been explicitly disabled.
+        */
+       if (!pmu_reg || !cpumask_equal(cpu_online_mask, cpumask_of(cpu)) ||
+           !lss_s0i3_enabled || !graphics_is_off || !mrst_pmu_s0i3_enable)
+               return 1 << IDLE_STATE5_IS_S0I3;
+       else
+               return 0;
+}
+
+/*
+ * pmu_update_wake_counters(): read PM_WKS, update wake_counters[]
+ * DEBUG only.
+ */
+static void pmu_update_wake_counters(void)
+{
+       int lss;
+       u32 wake_status;
+
+       wake_status = pmu_read_wks();
+
+       for (lss = 0; lss < MRST_NUM_LSS; ++lss) {
+               if (wake_status & (1 << lss))
+                       wake_counters[lss]++;
+       }
+}
+
+int mrst_pmu_s0i3_entry(void)
+{
+       int status;
+
+       /* Clear any possible error conditions */
+       pmu_write_ics(0x300);
+
+       /* set wake control to current D-states */
+       pmu_write_wssc(S0I3_SSS_TARGET);
+
+       status = mrst_s0i3_entry(PM_S0I3_COMMAND, &pmu_reg->pm_cmd);
+       pmu_update_wake_counters();
+       return status;
+}
+
+/* poll for maximum of 5ms for busy bit to clear */
+static int pmu_wait_ready(void)
+{
+       int udelays;
+
+       pmu_wait_ready_calls++;
+
+       for (udelays = 0; udelays < 500; ++udelays) {
+               if (udelays > pmu_wait_ready_udelays_max)
+                       pmu_wait_ready_udelays_max = udelays;
+
+               if (pmu_read_busy_status() == 0)
+                       return 0;
+
+               udelay(10);
+               pmu_wait_ready_udelays++;
+       }
+
+       /*
+        * if this fires, observe
+        * /sys/kernel/debug/mrst_pmu_wait_ready_calls
+        * /sys/kernel/debug/mrst_pmu_wait_ready_udelays
+        */
+       WARN_ONCE(1, "SCU not ready for 5ms");
+       return -EBUSY;
+}
+/* poll for maximum of 50ms us for busy bit to clear */
+static int pmu_wait_done(void)
+{
+       int udelays;
+
+       pmu_wait_done_calls++;
+
+       for (udelays = 0; udelays < 500; ++udelays) {
+               if (udelays > pmu_wait_done_udelays_max)
+                       pmu_wait_done_udelays_max = udelays;
+
+               if (pmu_read_busy_status() == 0)
+                       return 0;
+
+               udelay(100);
+               pmu_wait_done_udelays++;
+       }
+
+       /*
+        * if this fires, observe
+        * /sys/kernel/debug/mrst_pmu_wait_done_calls
+        * /sys/kernel/debug/mrst_pmu_wait_done_udelays
+        */
+       WARN_ONCE(1, "SCU not done for 50ms");
+       return -EBUSY;
+}
+
+u32 mrst_pmu_msi_is_disabled(void)
+{
+       return pmu_msi_is_disabled();
+}
+
+void mrst_pmu_enable_msi(void)
+{
+       pmu_msi_enable();
+}
+
+/**
+ * pmu_irq - pmu driver interrupt handler
+ * Context: interrupt context
+ */
+static irqreturn_t pmu_irq(int irq, void *dummy)
+{
+       union pmu_pm_ics pmu_ics;
+
+       pmu_ics.value = pmu_read_ics();
+
+       if (!pmu_ics.bits.pending)
+               return IRQ_NONE;
+
+       switch (pmu_ics.bits.cause) {
+       case INT_SPURIOUS:
+       case INT_CMD_DONE:
+       case INT_CMD_ERR:
+       case INT_WAKE_RX:
+       case INT_SS_ERROR:
+       case INT_S0IX_MISS:
+       case INT_NO_ACKC6:
+               pmu_irq_stats[pmu_ics.bits.cause]++;
+               break;
+       default:
+               pmu_irq_stats[INT_INVALID]++;
+       }
+
+       pmu_write_ics(pmu_ics.value); /* Clear pending interrupt */
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * Translate PCI power management to MRST LSS D-states
+ */
+static int pci_2_mrst_state(int lss, pci_power_t pci_state)
+{
+       switch (pci_state) {
+       case PCI_D0:
+               if (SSMSK(D0i1, lss) & D0I1_ACG_SSS_TARGET)
+                       return D0i1;
+               else
+                       return D0;
+       case PCI_D1:
+               return D0i1;
+       case PCI_D2:
+               return D0i2;
+       case PCI_D3hot:
+       case PCI_D3cold:
+               return D0i3;
+       default:
+               WARN(1, "pci_state %d\n", pci_state);
+               return 0;
+       }
+}
+
+static int pmu_issue_command(u32 pm_ssc)
+{
+       union pmu_pm_set_cfg_cmd_t command;
+
+       if (pmu_read_busy_status()) {
+               pr_debug("pmu is busy, Operation not permitted\n");
+               return -1;
+       }
+
+       /*
+        * enable interrupts in PMU so that interrupts are
+        * propagated when ioc bit for a particular set
+        * command is set
+        */
+
+       pmu_irq_enable();
+
+       /* Configure the sub systems for pmu2 */
+
+       pmu_write_ssc(pm_ssc);
+
+       /*
+        * Send the set config command for pmu its configured
+        * for mode CM_IMMEDIATE & hence with No Trigger
+        */
+
+       command.pmu2_params.d_param.cfg_mode = CM_IMMEDIATE;
+       command.pmu2_params.d_param.cfg_delay = 0;
+       command.pmu2_params.d_param.rsvd = 0;
+
+       /* construct the command to send SET_CFG to particular PMU */
+       command.pmu2_params.d_param.cmd = SET_CFG_CMD;
+       command.pmu2_params.d_param.ioc = 0;
+       command.pmu2_params.d_param.mode_id = 0;
+       command.pmu2_params.d_param.sys_state = SYS_STATE_S0I0;
+
+       /* write the value of PM_CMD into particular PMU */
+       pr_debug("pmu command being written %x\n",
+                       command.pmu_pm_set_cfg_cmd_value);
+
+       pmu_write_cmd(command.pmu_pm_set_cfg_cmd_value);
+
+       return 0;
+}
+
+static u16 pmu_min_lss_pci_req(u16 *ids, u16 pci_state)
+{
+       u16 existing_request;
+       int i;
+
+       for (i = 0; ids[i]; ++i) {
+               struct mrst_device *mrst_dev;
+
+               mrst_dev = pci_id_2_mrst_dev(ids[i]);
+               if (unlikely(!mrst_dev))
+                       continue;
+
+               existing_request = mrst_dev->latest_request;
+               if (existing_request < pci_state)
+                       pci_state = existing_request;
+       }
+       return pci_state;
+}
+
+/**
+ * pmu_pci_set_power_state - Callback function is used by all the PCI devices
+ *                     for a platform  specific device power on/shutdown.
+ */
+
+int pmu_pci_set_power_state(struct pci_dev *pdev, pci_power_t pci_state)
+{
+       u32 old_sss, new_sss;
+       int status = 0;
+       struct mrst_device *mrst_dev;
+
+       pmu_set_power_state_entry++;
+
+       BUG_ON(pdev->vendor != PCI_VENDOR_ID_INTEL);
+       BUG_ON(pci_state < PCI_D0 || pci_state > PCI_D3cold);
+
+       mrst_dev = pci_id_2_mrst_dev(pdev->device);
+       if (unlikely(!mrst_dev))
+               return -ENODEV;
+
+       mrst_dev->pci_state_counts[pci_state]++;        /* count invocations */
+
+       /* PMU driver calls self as part of PCI initialization, ignore */
+       if (pdev->device == PCI_DEV_ID_MRST_PMU)
+               return 0;
+
+       BUG_ON(!pmu_reg); /* SW bug if called before initialized */
+
+       spin_lock(&mrst_pmu_power_state_lock);
+
+       if (pdev->d3_delay) {
+               dev_dbg(&pdev->dev, "d3_delay %d, should be 0\n",
+                       pdev->d3_delay);
+               pdev->d3_delay = 0;
+       }
+       /*
+        * If Lincroft graphics, simply remember state
+        */
+       if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY
+               && !((pdev->class & PCI_SUB_CLASS_MASK) >> 8)) {
+               if (pci_state == PCI_D0)
+                       graphics_is_off = 0;
+               else
+                       graphics_is_off = 1;
+               goto ret;
+       }
+
+       if (!mrst_dev->lss)
+               goto ret;       /* device with no LSS */
+
+       if (mrst_dev->latest_request == pci_state)
+               goto ret;       /* no change */
+
+       mrst_dev->latest_request = pci_state;   /* record latest request */
+
+       /*
+        * LSS9 and LSS10 contain multiple PCI devices.
+        * Use the lowest numbered (highest power) state in the LSS
+        */
+       if (mrst_dev->lss == 9)
+               pci_state = pmu_min_lss_pci_req(mrst_lss9_pci_ids, pci_state);
+       else if (mrst_dev->lss == 10)
+               pci_state = pmu_min_lss_pci_req(mrst_lss10_pci_ids, pci_state);
+
+       status = pmu_wait_ready();
+       if (status)
+               goto ret;
+
+       old_sss = pmu_read_sss();
+       new_sss = old_sss & ~SSMSK(3, mrst_dev->lss);
+       new_sss |= SSMSK(pci_2_mrst_state(mrst_dev->lss, pci_state),
+                       mrst_dev->lss);
+
+       if (new_sss == old_sss)
+               goto ret;       /* nothing to do */
+
+       pmu_set_power_state_send_cmd++;
+
+       status = pmu_issue_command(new_sss);
+
+       if (unlikely(status != 0)) {
+               dev_err(&pdev->dev, "Failed to Issue a PM command\n");
+               goto ret;
+       }
+
+       if (pmu_wait_done())
+               goto ret;
+
+       lss_s0i3_enabled =
+       ((pmu_read_sss() & S0I3_SSS_TARGET) == S0I3_SSS_TARGET);
+ret:
+       spin_unlock(&mrst_pmu_power_state_lock);
+       return status;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static char *d0ix_names[] = {"D0", "D0i1", "D0i2", "D0i3"};
+
+static inline const char *d0ix_name(int state)
+{
+       return d0ix_names[(int) state];
+}
+
+static int debug_mrst_pmu_show(struct seq_file *s, void *unused)
+{
+       struct pci_dev *pdev = NULL;
+       u32 cur_pmsss;
+       int lss;
+
+       seq_printf(s, "0x%08X D0I1_ACG_SSS_TARGET\n", D0I1_ACG_SSS_TARGET);
+
+       cur_pmsss = pmu_read_sss();
+
+       seq_printf(s, "0x%08X S0I3_SSS_TARGET\n", S0I3_SSS_TARGET);
+
+       seq_printf(s, "0x%08X Current SSS ", cur_pmsss);
+       seq_printf(s, lss_s0i3_enabled ? "\n" : "[BLOCKS s0i3]\n");
+
+       if (cpumask_equal(cpu_online_mask, cpumask_of(0)))
+               seq_printf(s, "cpu0 is only cpu online\n");
+       else
+               seq_printf(s, "cpu0 is NOT only cpu online [BLOCKS S0i3]\n");
+
+       seq_printf(s, "GFX: %s\n", graphics_is_off ? "" : "[BLOCKS s0i3]");
+
+
+       for_each_pci_dev(pdev) {
+               int pos;
+               u16 pmcsr;
+               struct mrst_device *mrst_dev;
+               int i;
+
+               mrst_dev = pci_id_2_mrst_dev(pdev->device);
+
+               seq_printf(s, "%s %04x/%04X %-16.16s ",
+                       dev_name(&pdev->dev),
+                       pdev->vendor, pdev->device,
+                       dev_driver_string(&pdev->dev));
+
+               if (unlikely (!mrst_dev)) {
+                       seq_printf(s, " UNKNOWN\n");
+                       continue;
+               }
+
+               if (mrst_dev->lss)
+                       seq_printf(s, "LSS %2d %-4s ", mrst_dev->lss,
+                               d0ix_name(((cur_pmsss >>
+                                       (mrst_dev->lss * 2)) & 0x3)));
+               else
+                       seq_printf(s, "            ");
+
+               /* PCI PM config space setting */
+               pos = pci_find_capability(pdev, PCI_CAP_ID_PM);
+               if (pos != 0) {
+                       pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr);
+               seq_printf(s, "PCI-%-4s",
+                       pci_power_name(pmcsr & PCI_PM_CTRL_STATE_MASK));
+               } else {
+                       seq_printf(s, "        ");
+               }
+
+               seq_printf(s, " %s ", pci_power_name(mrst_dev->latest_request));
+               for (i = 0; i <= PCI_D3cold; ++i)
+                       seq_printf(s, "%d ", mrst_dev->pci_state_counts[i]);
+
+               if (mrst_dev->lss) {
+                       unsigned int lssmask;
+
+                       lssmask = SSMSK(D0i3, mrst_dev->lss);
+
+                       if ((lssmask & S0I3_SSS_TARGET) &&
+                               ((lssmask & cur_pmsss) !=
+                                       (lssmask & S0I3_SSS_TARGET)))
+                                               seq_printf(s , "[BLOCKS s0i3]");
+               }
+
+               seq_printf(s, "\n");
+       }
+       seq_printf(s, "Wake Counters:\n");
+       for (lss = 0; lss < MRST_NUM_LSS; ++lss)
+               seq_printf(s, "LSS%d %d\n", lss, wake_counters[lss]);
+
+       seq_printf(s, "Interrupt Counters:\n");
+       seq_printf(s,
+               "INT_SPURIOUS \t%8u\n" "INT_CMD_DONE \t%8u\n"
+               "INT_CMD_ERR  \t%8u\n" "INT_WAKE_RX  \t%8u\n"
+               "INT_SS_ERROR \t%8u\n" "INT_S0IX_MISS\t%8u\n"
+               "INT_NO_ACKC6 \t%8u\n" "INT_INVALID  \t%8u\n",
+               pmu_irq_stats[INT_SPURIOUS], pmu_irq_stats[INT_CMD_DONE],
+               pmu_irq_stats[INT_CMD_ERR], pmu_irq_stats[INT_WAKE_RX],
+               pmu_irq_stats[INT_SS_ERROR], pmu_irq_stats[INT_S0IX_MISS],
+               pmu_irq_stats[INT_NO_ACKC6], pmu_irq_stats[INT_INVALID]);
+
+       seq_printf(s, "mrst_pmu_wait_ready_calls          %8d\n",
+                       pmu_wait_ready_calls);
+       seq_printf(s, "mrst_pmu_wait_ready_udelays        %8d\n",
+                       pmu_wait_ready_udelays);
+       seq_printf(s, "mrst_pmu_wait_ready_udelays_max    %8d\n",
+                       pmu_wait_ready_udelays_max);
+       seq_printf(s, "mrst_pmu_wait_done_calls           %8d\n",
+                       pmu_wait_done_calls);
+       seq_printf(s, "mrst_pmu_wait_done_udelays         %8d\n",
+                       pmu_wait_done_udelays);
+       seq_printf(s, "mrst_pmu_wait_done_udelays_max     %8d\n",
+                       pmu_wait_done_udelays_max);
+       seq_printf(s, "mrst_pmu_set_power_state_entry     %8d\n",
+                       pmu_set_power_state_entry);
+       seq_printf(s, "mrst_pmu_set_power_state_send_cmd  %8d\n",
+                       pmu_set_power_state_send_cmd);
+       seq_printf(s, "SCU busy: %d\n", pmu_read_busy_status());
+
+       return 0;
+}
+
+static int debug_mrst_pmu_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, debug_mrst_pmu_show, NULL);
+}
+
+static const struct file_operations devices_state_operations = {
+       .open           = debug_mrst_pmu_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+#endif /* DEBUG_FS */
+
+/*
+ * Validate SCU PCI shim PCI vendor capability byte
+ * against LSS hard-coded in mrst_devs[] above.
+ * DEBUG only.
+ */
+static void pmu_scu_firmware_debug(void)
+{
+       struct pci_dev *pdev = NULL;
+
+       for_each_pci_dev(pdev) {
+               struct mrst_device *mrst_dev;
+               u8 pci_config_lss;
+               int pos;
+
+               mrst_dev = pci_id_2_mrst_dev(pdev->device);
+               if (unlikely(!mrst_dev)) {
+                       printk(KERN_ERR FW_BUG "pmu: Unknown "
+                               "PCI device 0x%04X\n", pdev->device);
+                       continue;
+               }
+
+               if (mrst_dev->lss == 0)
+                       continue;        /* no LSS in our table */
+
+               pos = pci_find_capability(pdev, PCI_CAP_ID_VNDR);
+               if (!pos != 0) {
+                       printk(KERN_ERR FW_BUG "pmu: 0x%04X "
+                               "missing PCI Vendor Capability\n",
+                               pdev->device);
+                       continue;
+               }
+               pci_read_config_byte(pdev, pos + 4, &pci_config_lss);
+               if (!(pci_config_lss & PCI_VENDOR_CAP_LOG_SS_MASK)) {
+                       printk(KERN_ERR FW_BUG "pmu: 0x%04X "
+                               "invalid PCI Vendor Capability 0x%x "
+                               " expected LSS 0x%X\n",
+                               pdev->device, pci_config_lss, mrst_dev->lss);
+                       continue;
+               }
+               pci_config_lss &= PCI_VENDOR_CAP_LOG_ID_MASK;
+
+               if (mrst_dev->lss == pci_config_lss)
+                       continue;
+
+               printk(KERN_ERR FW_BUG "pmu: 0x%04X LSS = %d, expected %d\n",
+                       pdev->device, pci_config_lss, mrst_dev->lss);
+       }
+}
+
+/**
+ * pmu_probe
+ */
+static int __devinit pmu_probe(struct pci_dev *pdev,
+                                  const struct pci_device_id *pci_id)
+{
+       int ret;
+       struct mrst_pmu_reg *pmu;
+
+       /* Init the device */
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "Unable to Enable PCI device\n");
+               return ret;
+       }
+
+       ret = pci_request_regions(pdev, MRST_PMU_DRV_NAME);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n");
+               goto out_err1;
+       }
+
+       /* Map the memory of PMU reg base */
+       pmu = pci_iomap(pdev, 0, 0);
+       if (!pmu) {
+               dev_err(&pdev->dev, "Unable to map the PMU address space\n");
+               ret = -ENOMEM;
+               goto out_err2;
+       }
+
+#ifdef CONFIG_DEBUG_FS
+       /* /sys/kernel/debug/mrst_pmu */
+       (void) debugfs_create_file("mrst_pmu", S_IFREG | S_IRUGO,
+                               NULL, NULL, &devices_state_operations);
+#endif
+       pmu_reg = pmu;  /* success */
+
+       if (request_irq(pdev->irq, pmu_irq, 0, MRST_PMU_DRV_NAME, NULL)) {
+               dev_err(&pdev->dev, "Registering isr has failed\n");
+               ret = -1;
+               goto out_err3;
+       }
+
+       pmu_scu_firmware_debug();
+
+       pmu_write_wkc(S0I3_WAKE_SOURCES);       /* Enable S0i3 wakeup sources */
+
+       pmu_wait_ready();
+
+       pmu_write_ssc(D0I1_ACG_SSS_TARGET);     /* Enable Auto-Clock_Gating */
+       pmu_write_cmd(0x201);
+
+       spin_lock_init(&mrst_pmu_power_state_lock);
+
+       /* Enable the hardware interrupt */
+       pmu_irq_enable();
+       return 0;
+
+out_err3:
+       free_irq(pdev->irq, NULL);
+       pci_iounmap(pdev, pmu_reg);
+       pmu_reg = NULL;
+out_err2:
+       pci_release_region(pdev, 0);
+out_err1:
+       pci_disable_device(pdev);
+       return ret;
+}
+
+static void __devexit pmu_remove(struct pci_dev *pdev)
+{
+       dev_err(&pdev->dev, "Mid PM pmu_remove called\n");
+
+       /* Freeing up the irq */
+       free_irq(pdev->irq, NULL);
+
+       pci_iounmap(pdev, pmu_reg);
+       pmu_reg = NULL;
+
+       /* disable the current PCI device */
+       pci_release_region(pdev, 0);
+       pci_disable_device(pdev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(pmu_pci_ids) = {
+       { PCI_VDEVICE(INTEL, PCI_DEV_ID_MRST_PMU), 0 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(pci, pmu_pci_ids);
+
+static struct pci_driver driver = {
+       .name = MRST_PMU_DRV_NAME,
+       .id_table = pmu_pci_ids,
+       .probe = pmu_probe,
+       .remove = __devexit_p(pmu_remove),
+};
+
+/**
+ * pmu_pci_register - register the PMU driver as PCI device
+ */
+static int __init pmu_pci_register(void)
+{
+       return pci_register_driver(&driver);
+}
+
+/* Register and probe via fs_initcall() to preceed device_initcall() */
+fs_initcall(pmu_pci_register);
+
+static void __exit mid_pci_cleanup(void)
+{
+       pci_unregister_driver(&driver);
+}
+
+static int ia_major;
+static int ia_minor;
+
+static int pmu_sfi_parse_oem(struct sfi_table_header *table)
+{
+       struct sfi_table_simple *sb;
+
+       sb = (struct sfi_table_simple *)table;
+       ia_major = (sb->pentry[1] >> 0) & 0xFFFF;
+       ia_minor = (sb->pentry[1] >> 16) & 0xFFFF;
+       printk(KERN_INFO "mrst_pmu: IA FW version v%x.%x\n",
+               ia_major, ia_minor);
+
+       return 0;
+}
+
+static int __init scu_fw_check(void)
+{
+       int ret;
+       u32 fw_version;
+
+       if (!pmu_reg)
+               return 0;       /* this driver didn't probe-out */
+
+       sfi_table_parse("OEMB", NULL, NULL, pmu_sfi_parse_oem);
+
+       if (ia_major < 0x6005 || ia_minor < 0x1525) {
+               WARN(1, "mrst_pmu: IA FW version too old\n");
+               return -1;
+       }
+
+       ret = intel_scu_ipc_command(IPCMSG_FW_REVISION, 0, NULL, 0,
+                                       &fw_version, 1);
+
+       if (ret) {
+               WARN(1, "mrst_pmu: IPC FW version? %d\n", ret);
+       } else {
+               int scu_major = (fw_version >> 8) & 0xFF;
+               int scu_minor = (fw_version >> 0) & 0xFF;
+
+               printk(KERN_INFO "mrst_pmu: firmware v%x\n", fw_version);
+
+               if ((scu_major >= 0xC0) && (scu_minor >= 0x49)) {
+                       printk(KERN_INFO "mrst_pmu: enabling S0i3\n");
+                       mrst_pmu_s0i3_enable = true;
+               } else {
+                       WARN(1, "mrst_pmu: S0i3 disabled, old firmware %X.%X",
+                                       scu_major, scu_minor);
+               }
+       }
+       return 0;
+}
+late_initcall(scu_fw_check);
+module_exit(mid_pci_cleanup);
diff --git a/arch/x86/platform/mrst/pmu.h b/arch/x86/platform/mrst/pmu.h
new file mode 100644 (file)
index 0000000..bfbfe64
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * mrst/pmu.h - private definitions for MRST Power Management Unit mrst/pmu.c
+ *
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * 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 _MRST_PMU_H_
+#define _MRST_PMU_H_
+
+#define PCI_DEV_ID_MRST_PMU            0x0810
+#define MRST_PMU_DRV_NAME              "mrst_pmu"
+#define        PCI_SUB_CLASS_MASK              0xFF00
+
+#define        PCI_VENDOR_CAP_LOG_ID_MASK      0x7F
+#define PCI_VENDOR_CAP_LOG_SS_MASK     0x80
+
+#define SUB_SYS_ALL_D0I1       0x01155555
+#define S0I3_WAKE_SOURCES      0x00001FFF
+
+#define PM_S0I3_COMMAND                                        \
+       ((0 << 31) |    /* Reserved */                  \
+       (0 << 30) |     /* Core must be idle */         \
+       (0xc2 << 22) |  /* ACK C6 trigger */            \
+       (3 << 19) |     /* Trigger on DMI message */    \
+       (3 << 16) |     /* Enter S0i3 */                \
+       (0 << 13) |     /* Numeric mode ID (sw) */      \
+       (3 << 9) |      /* Trigger mode */              \
+       (0 << 8) |      /* Do not interrupt */          \
+       (1 << 0))       /* Set configuration */
+
+#define        LSS_DMI         0
+#define        LSS_SD_HC0      1
+#define        LSS_SD_HC1      2
+#define        LSS_NAND        3
+#define        LSS_IMAGING     4
+#define        LSS_SECURITY    5
+#define        LSS_DISPLAY     6
+#define        LSS_USB_HC      7
+#define        LSS_USB_OTG     8
+#define        LSS_AUDIO       9
+#define        LSS_AUDIO_LPE   9
+#define        LSS_AUDIO_SSP   9
+#define        LSS_I2C0        10
+#define        LSS_I2C1        10
+#define        LSS_I2C2        10
+#define        LSS_KBD         10
+#define        LSS_SPI0        10
+#define        LSS_SPI1        10
+#define        LSS_SPI2        10
+#define        LSS_GPIO        10
+#define        LSS_SRAM        11      /* used by SCU, do not touch */
+#define        LSS_SD_HC2      12
+/* LSS hardware bits 15,14,13 are hardwired to 0, thus unusable */
+#define MRST_NUM_LSS   13
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+#define        SSMSK(mask, lss) ((mask) << ((lss) * 2))
+#define        D0      0
+#define        D0i1    1
+#define        D0i2    2
+#define        D0i3    3
+
+#define S0I3_SSS_TARGET        (               \
+       SSMSK(D0i1, LSS_DMI) |          \
+       SSMSK(D0i3, LSS_SD_HC0) |       \
+       SSMSK(D0i3, LSS_SD_HC1) |       \
+       SSMSK(D0i3, LSS_NAND) |         \
+       SSMSK(D0i3, LSS_SD_HC2) |       \
+       SSMSK(D0i3, LSS_IMAGING) |      \
+       SSMSK(D0i3, LSS_SECURITY) |     \
+       SSMSK(D0i3, LSS_DISPLAY) |      \
+       SSMSK(D0i3, LSS_USB_HC) |       \
+       SSMSK(D0i3, LSS_USB_OTG) |      \
+       SSMSK(D0i3, LSS_AUDIO) |        \
+       SSMSK(D0i1, LSS_I2C0))
+
+/*
+ * D0i1 on Langwell is Autonomous Clock Gating (ACG).
+ * Enable ACG on every LSS except camera and audio
+ */
+#define D0I1_ACG_SSS_TARGET     \
+       (SUB_SYS_ALL_D0I1 & ~SSMSK(D0i1, LSS_IMAGING) & ~SSMSK(D0i1, LSS_AUDIO))
+
+enum cm_mode {
+       CM_NOP,                 /* ignore the config mode value */
+       CM_IMMEDIATE,
+       CM_DELAY,
+       CM_TRIGGER,
+       CM_INVALID
+};
+
+enum sys_state {
+       SYS_STATE_S0I0,
+       SYS_STATE_S0I1,
+       SYS_STATE_S0I2,
+       SYS_STATE_S0I3,
+       SYS_STATE_S3,
+       SYS_STATE_S5
+};
+
+#define SET_CFG_CMD    1
+
+enum int_status {
+       INT_SPURIOUS = 0,
+       INT_CMD_DONE = 1,
+       INT_CMD_ERR = 2,
+       INT_WAKE_RX = 3,
+       INT_SS_ERROR = 4,
+       INT_S0IX_MISS = 5,
+       INT_NO_ACKC6 = 6,
+       INT_INVALID = 7,
+};
+
+/* PMU register interface */
+static struct mrst_pmu_reg {
+       u32 pm_sts;             /* 0x00 */
+       u32 pm_cmd;             /* 0x04 */
+       u32 pm_ics;             /* 0x08 */
+       u32 _resv1;             /* 0x0C */
+       u32 pm_wkc[2];          /* 0x10 */
+       u32 pm_wks[2];          /* 0x18 */
+       u32 pm_ssc[4];          /* 0x20 */
+       u32 pm_sss[4];          /* 0x30 */
+       u32 pm_wssc[4];         /* 0x40 */
+       u32 pm_c3c4;            /* 0x50 */
+       u32 pm_c5c6;            /* 0x54 */
+       u32 pm_msi_disable;     /* 0x58 */
+} *pmu_reg;
+
+static inline u32 pmu_read_sts(void) { return readl(&pmu_reg->pm_sts); }
+static inline u32 pmu_read_ics(void) { return readl(&pmu_reg->pm_ics); }
+static inline u32 pmu_read_wks(void) { return readl(&pmu_reg->pm_wks[0]); }
+static inline u32 pmu_read_sss(void) { return readl(&pmu_reg->pm_sss[0]); }
+
+static inline void pmu_write_cmd(u32 arg) { writel(arg, &pmu_reg->pm_cmd); }
+static inline void pmu_write_ics(u32 arg) { writel(arg, &pmu_reg->pm_ics); }
+static inline void pmu_write_wkc(u32 arg) { writel(arg, &pmu_reg->pm_wkc[0]); }
+static inline void pmu_write_ssc(u32 arg) { writel(arg, &pmu_reg->pm_ssc[0]); }
+static inline void pmu_write_wssc(u32 arg)
+                                       { writel(arg, &pmu_reg->pm_wssc[0]); }
+
+static inline void pmu_msi_enable(void) { writel(0, &pmu_reg->pm_msi_disable); }
+static inline u32 pmu_msi_is_disabled(void)
+                               { return readl(&pmu_reg->pm_msi_disable); }
+
+union pmu_pm_ics {
+       struct {
+               u32 cause:8;
+               u32 enable:1;
+               u32 pending:1;
+               u32 reserved:22;
+       } bits;
+       u32 value;
+};
+
+static inline void pmu_irq_enable(void)
+{
+       union pmu_pm_ics pmu_ics;
+
+       pmu_ics.value = pmu_read_ics();
+       pmu_ics.bits.enable = 1;
+       pmu_write_ics(pmu_ics.value);
+}
+
+union pmu_pm_status {
+       struct {
+               u32 pmu_rev:8;
+               u32 pmu_busy:1;
+               u32 mode_id:4;
+               u32 Reserved:19;
+       } pmu_status_parts;
+       u32 pmu_status_value;
+};
+
+static inline int pmu_read_busy_status(void)
+{
+       union pmu_pm_status result;
+
+       result.pmu_status_value = pmu_read_sts();
+
+       return result.pmu_status_parts.pmu_busy;
+}
+
+/* pmu set config parameters */
+struct cfg_delay_param_t {
+       u32 cmd:8;
+       u32 ioc:1;
+       u32 cfg_mode:4;
+       u32 mode_id:3;
+       u32 sys_state:3;
+       u32 cfg_delay:8;
+       u32 rsvd:5;
+};
+
+struct cfg_trig_param_t {
+       u32 cmd:8;
+       u32 ioc:1;
+       u32 cfg_mode:4;
+       u32 mode_id:3;
+       u32 sys_state:3;
+       u32 cfg_trig_type:3;
+       u32 cfg_trig_val:8;
+       u32 cmbi:1;
+       u32 rsvd1:1;
+};
+
+union pmu_pm_set_cfg_cmd_t {
+       union {
+               struct cfg_delay_param_t d_param;
+               struct cfg_trig_param_t t_param;
+       } pmu2_params;
+       u32 pmu_pm_set_cfg_cmd_value;
+};
+
+#ifdef FUTURE_PATCH
+extern int mrst_s0i3_entry(u32 regval, u32 *regaddr);
+#else
+static inline int mrst_s0i3_entry(u32 regval, u32 *regaddr) { return -1; }
+#endif
+#endif
index 1b979c1..01f5e3b 100644 (file)
@@ -9,6 +9,7 @@ __PAGE_ALIGNED_DATA
 vdso_start:
        .incbin "arch/x86/vdso/vdso.so"
 vdso_end:
+       .align PAGE_SIZE /* extra data here leaks to userspace. */
 
 .previous
 
index ccf73b2..3326204 100644 (file)
@@ -13,7 +13,9 @@ CFLAGS_mmu.o                  := $(nostackp)
 obj-y          := enlighten.o setup.o multicalls.o mmu.o irq.o \
                        time.o xen-asm.o xen-asm_$(BITS).o \
                        grant-table.o suspend.o platform-pci-unplug.o \
-                       p2m.o trace.o
+                       p2m.o
+
+obj-$(CONFIG_FTRACE) += trace.o
 
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
index 974a528..e2345af 100644 (file)
@@ -951,6 +951,10 @@ static const struct pv_info xen_info __initconst = {
        .paravirt_enabled = 1,
        .shared_kernel_pmd = 0,
 
+#ifdef CONFIG_X86_64
+       .extra_user_64bit_cs = FLAT_USER_CS64,
+#endif
+
        .name = "Xen",
 };
 
index f987bde..8cce339 100644 (file)
@@ -1916,6 +1916,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
 # endif
 #else
        case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE:
+       case VVAR_PAGE:
 #endif
        case FIX_TEXT_POKE0:
        case FIX_TEXT_POKE1:
@@ -1956,7 +1957,8 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
 #ifdef CONFIG_X86_64
        /* Replicate changes to map the vsyscall page into the user
           pagetable vsyscall mapping. */
-       if (idx >= VSYSCALL_LAST_PAGE && idx <= VSYSCALL_FIRST_PAGE) {
+       if ((idx >= VSYSCALL_LAST_PAGE && idx <= VSYSCALL_FIRST_PAGE) ||
+           idx == VVAR_PAGE) {
                unsigned long vaddr = __fix_to_virt(idx);
                set_pte_vaddr_pud(level3_user_vsyscall, vaddr, pte);
        }
index 60aeeb5..df118a8 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/pm.h>
 #include <linux/memblock.h>
+#include <linux/cpuidle.h>
 
 #include <asm/elf.h>
 #include <asm/vdso.h>
@@ -92,8 +93,6 @@ static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
        if (end <= start)
                return 0;
 
-       printk(KERN_INFO "xen_release_chunk: looking at area pfn %lx-%lx: ",
-              start, end);
        for(pfn = start; pfn < end; pfn++) {
                unsigned long mfn = pfn_to_mfn(pfn);
 
@@ -106,14 +105,14 @@ static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
 
                ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
                                           &reservation);
-               WARN(ret != 1, "Failed to release memory %lx-%lx err=%d\n",
-                    start, end, ret);
+               WARN(ret != 1, "Failed to release pfn %lx err=%d\n", pfn, ret);
                if (ret == 1) {
                        __set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
                        len++;
                }
        }
-       printk(KERN_CONT "%ld pages freed\n", len);
+       printk(KERN_INFO "Freeing  %lx-%lx pfn range: %lu pages freed\n",
+              start, end, len);
 
        return len;
 }
@@ -139,7 +138,7 @@ static unsigned long __init xen_return_unused_memory(unsigned long max_pfn,
        if (last_end < max_addr)
                released += xen_release_chunk(last_end, max_addr);
 
-       printk(KERN_INFO "released %ld pages of unused memory\n", released);
+       printk(KERN_INFO "released %lu pages of unused memory\n", released);
        return released;
 }
 
@@ -426,7 +425,7 @@ void __init xen_arch_setup(void)
 #ifdef CONFIG_X86_32
        boot_cpu_data.hlt_works_ok = 1;
 #endif
-       pm_idle = default_idle;
+       disable_cpuidle();
        boot_option_idle_override = IDLE_HALT;
 
        fiddle_vdso();
index 734beba..520022d 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/ftrace.h>
+#include <xen/interface/xen.h>
 
 #define N(x)   [__HYPERVISOR_##x] = "("#x")"
 static const char *xen_hypercall_names[] = {
index f717e20..7dde244 100644 (file)
@@ -633,7 +633,7 @@ static const struct net_device_ops iss_netdev_ops = {
        .ndo_set_mac_address    = iss_net_set_mac,
        //.ndo_do_ioctl         = iss_net_ioctl,
        .ndo_tx_timeout         = iss_net_tx_timeout,
-       .ndo_set_multicast_list = iss_net_set_multicast_list,
+       .ndo_set_rx_mode        = iss_net_set_multicast_list,
 };
 
 static int iss_net_configure(int index, char *init)
index b850bed..b627558 100644 (file)
@@ -1368,8 +1368,10 @@ static bool should_fail_request(struct hd_struct *part, unsigned int bytes)
 
 static int __init fail_make_request_debugfs(void)
 {
-       return init_fault_attr_dentries(&fail_make_request,
-                                       "fail_make_request");
+       struct dentry *dir = fault_create_debugfs_attr("fail_make_request",
+                                               NULL, &fail_make_request);
+
+       return IS_ERR(dir) ? PTR_ERR(dir) : 0;
 }
 
 late_initcall(fail_make_request_debugfs);
index 4f0c06c..7803548 100644 (file)
@@ -28,7 +28,10 @@ int blk_should_fake_timeout(struct request_queue *q)
 
 static int __init fail_io_timeout_debugfs(void)
 {
-       return init_fault_attr_dentries(&fail_io_timeout, "fail_io_timeout");
+       struct dentry *dir = fault_create_debugfs_attr("fail_io_timeout",
+                                               NULL, &fail_io_timeout);
+
+       return IS_ERR(dir) ? PTR_ERR(dir) : 0;
 }
 
 late_initcall(fail_io_timeout_debugfs);
index 30efc7d..7febeaa 100644 (file)
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/cryptohash.h>
 #include <asm/byteorder.h>
 
-#define F1(x, y, z)    (z ^ (x & (y ^ z)))
-#define F2(x, y, z)    F1(z, x, y)
-#define F3(x, y, z)    (x ^ y ^ z)
-#define F4(x, y, z)    (y ^ (x | ~z))
-
-#define MD5STEP(f, w, x, y, z, in, s) \
-       (w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
-
-static void md5_transform(u32 *hash, u32 const *in)
-{
-       u32 a, b, c, d;
-
-       a = hash[0];
-       b = hash[1];
-       c = hash[2];
-       d = hash[3];
-
-       MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
-       MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
-       MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
-       MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
-       MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
-       MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
-       MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
-       MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
-       MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
-       MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
-       MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
-       MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
-       MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
-       MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
-       MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
-       MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
-       MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
-       MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
-       MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
-       MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
-       MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
-       MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
-       MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
-       MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
-       MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
-       MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
-       MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
-       MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
-       MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
-       MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
-       MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
-       MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
-       MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
-       MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
-       MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
-       MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
-       MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
-       MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
-       MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
-       MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
-       MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
-       MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
-       MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
-       MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
-       MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
-       MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
-       MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
-       MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
-       MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
-       MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
-       MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
-       MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
-       MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
-       MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
-       MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
-       MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
-       MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
-       MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
-       MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
-       MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
-       MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
-       MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
-       MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
-       MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
-       hash[0] += a;
-       hash[1] += b;
-       hash[2] += c;
-       hash[3] += d;
-}
-
 /* XXX: this stuff can be optimized */
 static inline void le32_to_cpu_array(u32 *buf, unsigned int words)
 {
index 73863d8..76dc02f 100644 (file)
@@ -126,6 +126,12 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE);
  */
 u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE);
 
+/*
+ * Disable runtime checking and repair of values returned by control methods.
+ * Use only if the repair is causing a problem on a particular machine.
+ */
+u8 ACPI_INIT_GLOBAL(acpi_gbl_disable_auto_repair, FALSE);
+
 /* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */
 
 struct acpi_table_fadt acpi_gbl_FADT;
index c7f743c..5552125 100644 (file)
@@ -357,6 +357,7 @@ struct acpi_predefined_data {
        char *pathname;
        const union acpi_predefined_info *predefined;
        union acpi_operand_object *parent_package;
+       struct acpi_namespace_node *node;
        u32 flags;
        u8 node_flags;
 };
index 94e73c9..c445cca 100644 (file)
@@ -468,6 +468,7 @@ static const union acpi_predefined_info predefined_names[] =
        {{"_SWS", 0, ACPI_RTYPE_INTEGER}},
        {{"_TC1", 0, ACPI_RTYPE_INTEGER}},
        {{"_TC2", 0, ACPI_RTYPE_INTEGER}},
+       {{"_TDL", 0, ACPI_RTYPE_INTEGER}},
        {{"_TIP", 1, ACPI_RTYPE_INTEGER}},
        {{"_TIV", 1, ACPI_RTYPE_INTEGER}},
        {{"_TMP", 0, ACPI_RTYPE_INTEGER}},
index 9fb03fa..c845c80 100644 (file)
@@ -193,14 +193,20 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
        }
 
        /*
-        * 1) We have a return value, but if one wasn't expected, just exit, this is
-        * not a problem. For example, if the "Implicit Return" feature is
-        * enabled, methods will always return a value.
+        * Return value validation and possible repair.
         *
-        * 2) If the return value can be of any type, then we cannot perform any
-        * validation, exit.
+        * 1) Don't perform return value validation/repair if this feature
+        * has been disabled via a global option.
+        *
+        * 2) We have a return value, but if one wasn't expected, just exit,
+        * this is not a problem. For example, if the "Implicit Return"
+        * feature is enabled, methods will always return a value.
+        *
+        * 3) If the return value can be of any type, then we cannot perform
+        * any validation, just exit.
         */
-       if ((!predefined->info.expected_btypes) ||
+       if (acpi_gbl_disable_auto_repair ||
+           (!predefined->info.expected_btypes) ||
            (predefined->info.expected_btypes == ACPI_RTYPE_ALL)) {
                goto cleanup;
        }
@@ -212,6 +218,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
                goto cleanup;
        }
        data->predefined = predefined;
+       data->node = node;
        data->node_flags = node->flags;
        data->pathname = pathname;
 
index 973883b..024c4f2 100644 (file)
@@ -503,6 +503,21 @@ acpi_ns_repair_TSS(struct acpi_predefined_data *data,
 {
        union acpi_operand_object *return_object = *return_object_ptr;
        acpi_status status;
+       struct acpi_namespace_node *node;
+
+       /*
+        * We can only sort the _TSS return package if there is no _PSS in the
+        * same scope. This is because if _PSS is present, the ACPI specification
+        * dictates that the _TSS Power Dissipation field is to be ignored, and
+        * therefore some BIOSs leave garbage values in the _TSS Power field(s).
+        * In this case, it is best to just return the _TSS package as-is.
+        * (May, 2011)
+        */
+       status =
+           acpi_ns_get_node(data->node, "^_PSS", ACPI_NS_NO_UPSEARCH, &node);
+       if (ACPI_SUCCESS(status)) {
+               return (AE_OK);
+       }
 
        status = acpi_ns_check_sorted_list(data, return_object, 5, 1,
                                           ACPI_SORT_DESCENDING,
index 48db094..62365f6 100644 (file)
@@ -126,12 +126,29 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
        }
 
        /*
-        * Originally, we checked the table signature for "SSDT" or "PSDT" here.
-        * Next, we added support for OEMx tables, signature "OEM".
-        * Valid tables were encountered with a null signature, so we've just
-        * given up on validating the signature, since it seems to be a waste
-        * of code. The original code was removed (05/2008).
+        * Validate the incoming table signature.
+        *
+        * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
+        * 2) We added support for OEMx tables, signature "OEM".
+        * 3) Valid tables were encountered with a null signature, so we just
+        *    gave up on validating the signature, (05/2008).
+        * 4) We encountered non-AML tables such as the MADT, which caused
+        *    interpreter errors and kernel faults. So now, we once again allow
+        *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
         */
+       if ((table_desc->pointer->signature[0] != 0x00) &&
+           (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))
+           && (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) {
+               ACPI_ERROR((AE_INFO,
+                           "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx",
+                           acpi_ut_valid_acpi_name(*(u32 *)table_desc->
+                                                   pointer->
+                                                   signature) ? table_desc->
+                           pointer->signature : "????",
+                           *(u32 *)table_desc->pointer->signature));
+
+               return_ACPI_STATUS(AE_BAD_SIGNATURE);
+       }
 
        (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 
index f739a70..c34aa51 100644 (file)
@@ -10,9 +10,11 @@ config ACPI_APEI
          error injection.
 
 config ACPI_APEI_GHES
-       tristate "APEI Generic Hardware Error Source"
+       bool "APEI Generic Hardware Error Source"
        depends on ACPI_APEI && X86
        select ACPI_HED
+       select LLIST
+       select GENERIC_ALLOCATOR
        help
          Generic Hardware Error Source provides a way to report
          platform hardware errors (such as that from chipset). It
@@ -30,6 +32,13 @@ config ACPI_APEI_PCIEAER
          PCIe AER errors may be reported via APEI firmware first mode.
          Turn on this option to enable the corresponding support.
 
+config ACPI_APEI_MEMORY_FAILURE
+       bool "APEI memory error recovering support"
+       depends on ACPI_APEI && MEMORY_FAILURE
+       help
+         Memory errors may be reported via APEI firmware first mode.
+         Turn on this option to enable the memory recovering support.
+
 config ACPI_APEI_EINJ
        tristate "APEI Error INJection (EINJ)"
        depends on ACPI_APEI && DEBUG_FS
index 4a904a4..8041248 100644 (file)
@@ -157,9 +157,10 @@ EXPORT_SYMBOL_GPL(apei_exec_noop);
  * Interpret the specified action. Go through whole action table,
  * execute all instructions belong to the action.
  */
-int apei_exec_run(struct apei_exec_context *ctx, u8 action)
+int __apei_exec_run(struct apei_exec_context *ctx, u8 action,
+                   bool optional)
 {
-       int rc;
+       int rc = -ENOENT;
        u32 i, ip;
        struct acpi_whea_header *entry;
        apei_exec_ins_func_t run;
@@ -198,9 +199,9 @@ rewind:
                        goto rewind;
        }
 
-       return 0;
+       return !optional && rc < 0 ? rc : 0;
 }
-EXPORT_SYMBOL_GPL(apei_exec_run);
+EXPORT_SYMBOL_GPL(__apei_exec_run);
 
 typedef int (*apei_exec_entry_func_t)(struct apei_exec_context *ctx,
                                      struct acpi_whea_header *entry,
@@ -603,3 +604,29 @@ struct dentry *apei_get_debugfs_dir(void)
        return dapei;
 }
 EXPORT_SYMBOL_GPL(apei_get_debugfs_dir);
+
+int apei_osc_setup(void)
+{
+       static u8 whea_uuid_str[] = "ed855e0c-6c90-47bf-a62a-26de0fc5ad5c";
+       acpi_handle handle;
+       u32 capbuf[3];
+       struct acpi_osc_context context = {
+               .uuid_str       = whea_uuid_str,
+               .rev            = 1,
+               .cap.length     = sizeof(capbuf),
+               .cap.pointer    = capbuf,
+       };
+
+       capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
+       capbuf[OSC_SUPPORT_TYPE] = 0;
+       capbuf[OSC_CONTROL_TYPE] = 0;
+
+       if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))
+           || ACPI_FAILURE(acpi_run_osc(handle, &context)))
+               return -EIO;
+       else {
+               kfree(context.ret.pointer);
+               return 0;
+       }
+}
+EXPORT_SYMBOL_GPL(apei_osc_setup);
index ef0581f..f57050e 100644 (file)
@@ -50,7 +50,18 @@ static inline u64 apei_exec_ctx_get_output(struct apei_exec_context *ctx)
        return ctx->value;
 }
 
-int apei_exec_run(struct apei_exec_context *ctx, u8 action);
+int __apei_exec_run(struct apei_exec_context *ctx, u8 action, bool optional);
+
+static inline int apei_exec_run(struct apei_exec_context *ctx, u8 action)
+{
+       return __apei_exec_run(ctx, action, 0);
+}
+
+/* It is optional whether the firmware provides the action */
+static inline int apei_exec_run_optional(struct apei_exec_context *ctx, u8 action)
+{
+       return __apei_exec_run(ctx, action, 1);
+}
 
 /* Common instruction implementation */
 
@@ -113,4 +124,6 @@ void apei_estatus_print(const char *pfx,
                        const struct acpi_hest_generic_status *estatus);
 int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus);
 int apei_estatus_check(const struct acpi_hest_generic_status *estatus);
+
+int apei_osc_setup(void);
 #endif
index f74b2ea..589b96c 100644 (file)
@@ -46,7 +46,8 @@
  * Some BIOSes allow parameters to the SET_ERROR_TYPE entries in the
  * EINJ table through an unpublished extension. Use with caution as
  * most will ignore the parameter and make their own choice of address
- * for error injection.
+ * for error injection.  This extension is used only if
+ * param_extension module parameter is specified.
  */
 struct einj_parameter {
        u64 type;
@@ -65,6 +66,9 @@ struct einj_parameter {
        ((struct acpi_whea_header *)((char *)(tab) +                    \
                                    sizeof(struct acpi_table_einj)))
 
+static bool param_extension;
+module_param(param_extension, bool, 0);
+
 static struct acpi_table_einj *einj_tab;
 
 static struct apei_resources einj_resources;
@@ -285,7 +289,7 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
 
        einj_exec_ctx_init(&ctx);
 
-       rc = apei_exec_run(&ctx, ACPI_EINJ_BEGIN_OPERATION);
+       rc = apei_exec_run_optional(&ctx, ACPI_EINJ_BEGIN_OPERATION);
        if (rc)
                return rc;
        apei_exec_ctx_set_input(&ctx, type);
@@ -323,7 +327,7 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
        rc = __einj_error_trigger(trigger_paddr);
        if (rc)
                return rc;
-       rc = apei_exec_run(&ctx, ACPI_EINJ_END_OPERATION);
+       rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION);
 
        return rc;
 }
@@ -489,14 +493,6 @@ static int __init einj_init(void)
                                     einj_debug_dir, NULL, &error_type_fops);
        if (!fentry)
                goto err_cleanup;
-       fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR,
-                                   einj_debug_dir, &error_param1);
-       if (!fentry)
-               goto err_cleanup;
-       fentry = debugfs_create_x64("param2", S_IRUSR | S_IWUSR,
-                                   einj_debug_dir, &error_param2);
-       if (!fentry)
-               goto err_cleanup;
        fentry = debugfs_create_file("error_inject", S_IWUSR,
                                     einj_debug_dir, NULL, &error_inject_fops);
        if (!fentry)
@@ -513,12 +509,23 @@ static int __init einj_init(void)
        rc = apei_exec_pre_map_gars(&ctx);
        if (rc)
                goto err_release;
-       param_paddr = einj_get_parameter_address();
-       if (param_paddr) {
-               einj_param = ioremap(param_paddr, sizeof(*einj_param));
-               rc = -ENOMEM;
-               if (!einj_param)
-                       goto err_unmap;
+       if (param_extension) {
+               param_paddr = einj_get_parameter_address();
+               if (param_paddr) {
+                       einj_param = ioremap(param_paddr, sizeof(*einj_param));
+                       rc = -ENOMEM;
+                       if (!einj_param)
+                               goto err_unmap;
+                       fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR,
+                                                   einj_debug_dir, &error_param1);
+                       if (!fentry)
+                               goto err_unmap;
+                       fentry = debugfs_create_x64("param2", S_IRUSR | S_IWUSR,
+                                                   einj_debug_dir, &error_param2);
+                       if (!fentry)
+                               goto err_unmap;
+               } else
+                       pr_warn(EINJ_PFX "Parameter extension is not supported.\n");
        }
 
        pr_info(EINJ_PFX "Error INJection is initialized.\n");
@@ -526,6 +533,8 @@ static int __init einj_init(void)
        return 0;
 
 err_unmap:
+       if (einj_param)
+               iounmap(einj_param);
        apei_exec_post_unmap_gars(&ctx);
 err_release:
        apei_resources_release(&einj_resources);
index a4cfb64..903549d 100644 (file)
@@ -33,7 +33,7 @@
 
 #define ERST_DBG_PFX                   "ERST DBG: "
 
-#define ERST_DBG_RECORD_LEN_MAX                4096
+#define ERST_DBG_RECORD_LEN_MAX                0x4000
 
 static void *erst_dbg_buf;
 static unsigned int erst_dbg_buf_len;
@@ -213,6 +213,10 @@ static struct miscdevice erst_dbg_dev = {
 
 static __init int erst_dbg_init(void)
 {
+       if (erst_disable) {
+               pr_info(ERST_DBG_PFX "ERST support is disabled.\n");
+               return -ENODEV;
+       }
        return misc_register(&erst_dbg_dev);
 }
 
index e6cef8e..2ca59dc 100644 (file)
@@ -642,7 +642,7 @@ static int __erst_write_to_storage(u64 offset)
        int rc;
 
        erst_exec_ctx_init(&ctx);
-       rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_WRITE);
+       rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_WRITE);
        if (rc)
                return rc;
        apei_exec_ctx_set_input(&ctx, offset);
@@ -666,7 +666,7 @@ static int __erst_write_to_storage(u64 offset)
        if (rc)
                return rc;
        val = apei_exec_ctx_get_output(&ctx);
-       rc = apei_exec_run(&ctx, ACPI_ERST_END);
+       rc = apei_exec_run_optional(&ctx, ACPI_ERST_END);
        if (rc)
                return rc;
 
@@ -681,7 +681,7 @@ static int __erst_read_from_storage(u64 record_id, u64 offset)
        int rc;
 
        erst_exec_ctx_init(&ctx);
-       rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_READ);
+       rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_READ);
        if (rc)
                return rc;
        apei_exec_ctx_set_input(&ctx, offset);
@@ -709,7 +709,7 @@ static int __erst_read_from_storage(u64 record_id, u64 offset)
        if (rc)
                return rc;
        val = apei_exec_ctx_get_output(&ctx);
-       rc = apei_exec_run(&ctx, ACPI_ERST_END);
+       rc = apei_exec_run_optional(&ctx, ACPI_ERST_END);
        if (rc)
                return rc;
 
@@ -724,7 +724,7 @@ static int __erst_clear_from_storage(u64 record_id)
        int rc;
 
        erst_exec_ctx_init(&ctx);
-       rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_CLEAR);
+       rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_CLEAR);
        if (rc)
                return rc;
        apei_exec_ctx_set_input(&ctx, record_id);
@@ -748,7 +748,7 @@ static int __erst_clear_from_storage(u64 record_id)
        if (rc)
                return rc;
        val = apei_exec_ctx_get_output(&ctx);
-       rc = apei_exec_run(&ctx, ACPI_ERST_END);
+       rc = apei_exec_run_optional(&ctx, ACPI_ERST_END);
        if (rc)
                return rc;
 
@@ -932,8 +932,11 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
 static int erst_open_pstore(struct pstore_info *psi);
 static int erst_close_pstore(struct pstore_info *psi);
 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
-                      struct timespec *time);
-static u64 erst_writer(enum pstore_type_id type, size_t size);
+                          struct timespec *time, struct pstore_info *psi);
+static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+                      size_t size, struct pstore_info *psi);
+static int erst_clearer(enum pstore_type_id type, u64 id,
+                       struct pstore_info *psi);
 
 static struct pstore_info erst_info = {
        .owner          = THIS_MODULE,
@@ -942,7 +945,7 @@ static struct pstore_info erst_info = {
        .close          = erst_close_pstore,
        .read           = erst_reader,
        .write          = erst_writer,
-       .erase          = erst_clear
+       .erase          = erst_clearer
 };
 
 #define CPER_CREATOR_PSTORE                                            \
@@ -983,7 +986,7 @@ static int erst_close_pstore(struct pstore_info *psi)
 }
 
 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
-                      struct timespec *time)
+                          struct timespec *time, struct pstore_info *psi)
 {
        int rc;
        ssize_t len = 0;
@@ -1037,7 +1040,8 @@ out:
        return (rc < 0) ? rc : (len - sizeof(*rcd));
 }
 
-static u64 erst_writer(enum pstore_type_id type, size_t size)
+static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+                      size_t size, struct pstore_info *psi)
 {
        struct cper_pstore_record *rcd = (struct cper_pstore_record *)
                                        (erst_info.buf - sizeof(*rcd));
@@ -1080,6 +1084,12 @@ static u64 erst_writer(enum pstore_type_id type, size_t size)
        return rcd->hdr.record_id;
 }
 
+static int erst_clearer(enum pstore_type_id type, u64 id,
+                       struct pstore_info *psi)
+{
+       return erst_clear(id);
+}
+
 static int __init erst_init(void)
 {
        int rc = 0;
index f703b28..0784f99 100644 (file)
@@ -12,7 +12,7 @@
  * For more information about Generic Hardware Error Source, please
  * refer to ACPI Specification version 4.0, section 17.3.2.6
  *
- * Copyright 2010 Intel Corp.
+ * Copyright 2010,2011 Intel Corp.
  *   Author: Huang Ying <ying.huang@intel.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -42,6 +42,9 @@
 #include <linux/mutex.h>
 #include <linux/ratelimit.h>
 #include <linux/vmalloc.h>
+#include <linux/irq_work.h>
+#include <linux/llist.h>
+#include <linux/genalloc.h>
 #include <acpi/apei.h>
 #include <acpi/atomicio.h>
 #include <acpi/hed.h>
 #define GHES_PFX       "GHES: "
 
 #define GHES_ESTATUS_MAX_SIZE          65536
+#define GHES_ESOURCE_PREALLOC_MAX_SIZE 65536
+
+#define GHES_ESTATUS_POOL_MIN_ALLOC_ORDER 3
+
+/* This is just an estimation for memory pool allocation */
+#define GHES_ESTATUS_CACHE_AVG_SIZE    512
+
+#define GHES_ESTATUS_CACHES_SIZE       4
+
+#define GHES_ESTATUS_IN_CACHE_MAX_NSEC 10000000000ULL
+/* Prevent too many caches are allocated because of RCU */
+#define GHES_ESTATUS_CACHE_ALLOCED_MAX (GHES_ESTATUS_CACHES_SIZE * 3 / 2)
+
+#define GHES_ESTATUS_CACHE_LEN(estatus_len)                    \
+       (sizeof(struct ghes_estatus_cache) + (estatus_len))
+#define GHES_ESTATUS_FROM_CACHE(estatus_cache)                 \
+       ((struct acpi_hest_generic_status *)                    \
+        ((struct ghes_estatus_cache *)(estatus_cache) + 1))
+
+#define GHES_ESTATUS_NODE_LEN(estatus_len)                     \
+       (sizeof(struct ghes_estatus_node) + (estatus_len))
+#define GHES_ESTATUS_FROM_NODE(estatus_node)                           \
+       ((struct acpi_hest_generic_status *)                            \
+        ((struct ghes_estatus_node *)(estatus_node) + 1))
 
 /*
  * One struct ghes is created for each generic hardware error source.
@@ -77,6 +104,22 @@ struct ghes {
        };
 };
 
+struct ghes_estatus_node {
+       struct llist_node llnode;
+       struct acpi_hest_generic *generic;
+};
+
+struct ghes_estatus_cache {
+       u32 estatus_len;
+       atomic_t count;
+       struct acpi_hest_generic *generic;
+       unsigned long long time_in;
+       struct rcu_head rcu;
+};
+
+int ghes_disable;
+module_param_named(disable, ghes_disable, bool, 0);
+
 static int ghes_panic_timeout  __read_mostly = 30;
 
 /*
@@ -121,6 +164,22 @@ static struct vm_struct *ghes_ioremap_area;
 static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi);
 static DEFINE_SPINLOCK(ghes_ioremap_lock_irq);
 
+/*
+ * printk is not safe in NMI context.  So in NMI handler, we allocate
+ * required memory from lock-less memory allocator
+ * (ghes_estatus_pool), save estatus into it, put them into lock-less
+ * list (ghes_estatus_llist), then delay printk into IRQ context via
+ * irq_work (ghes_proc_irq_work).  ghes_estatus_size_request record
+ * required pool size by all NMI error source.
+ */
+static struct gen_pool *ghes_estatus_pool;
+static unsigned long ghes_estatus_pool_size_request;
+static struct llist_head ghes_estatus_llist;
+static struct irq_work ghes_proc_irq_work;
+
+struct ghes_estatus_cache *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE];
+static atomic_t ghes_estatus_cache_alloced;
+
 static int ghes_ioremap_init(void)
 {
        ghes_ioremap_area = __get_vm_area(PAGE_SIZE * GHES_IOREMAP_PAGES,
@@ -180,6 +239,55 @@ static void ghes_iounmap_irq(void __iomem *vaddr_ptr)
        __flush_tlb_one(vaddr);
 }
 
+static int ghes_estatus_pool_init(void)
+{
+       ghes_estatus_pool = gen_pool_create(GHES_ESTATUS_POOL_MIN_ALLOC_ORDER, -1);
+       if (!ghes_estatus_pool)
+               return -ENOMEM;
+       return 0;
+}
+
+static void ghes_estatus_pool_free_chunk_page(struct gen_pool *pool,
+                                             struct gen_pool_chunk *chunk,
+                                             void *data)
+{
+       free_page(chunk->start_addr);
+}
+
+static void ghes_estatus_pool_exit(void)
+{
+       gen_pool_for_each_chunk(ghes_estatus_pool,
+                               ghes_estatus_pool_free_chunk_page, NULL);
+       gen_pool_destroy(ghes_estatus_pool);
+}
+
+static int ghes_estatus_pool_expand(unsigned long len)
+{
+       unsigned long i, pages, size, addr;
+       int ret;
+
+       ghes_estatus_pool_size_request += PAGE_ALIGN(len);
+       size = gen_pool_size(ghes_estatus_pool);
+       if (size >= ghes_estatus_pool_size_request)
+               return 0;
+       pages = (ghes_estatus_pool_size_request - size) / PAGE_SIZE;
+       for (i = 0; i < pages; i++) {
+               addr = __get_free_page(GFP_KERNEL);
+               if (!addr)
+                       return -ENOMEM;
+               ret = gen_pool_add(ghes_estatus_pool, addr, PAGE_SIZE, -1);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static void ghes_estatus_pool_shrink(unsigned long len)
+{
+       ghes_estatus_pool_size_request -= PAGE_ALIGN(len);
+}
+
 static struct ghes *ghes_new(struct acpi_hest_generic *generic)
 {
        struct ghes *ghes;
@@ -341,43 +449,196 @@ static void ghes_clear_estatus(struct ghes *ghes)
        ghes->flags &= ~GHES_TO_CLEAR;
 }
 
-static void ghes_do_proc(struct ghes *ghes)
+static void ghes_do_proc(const struct acpi_hest_generic_status *estatus)
 {
-       int sev, processed = 0;
+       int sev, sec_sev;
        struct acpi_hest_generic_data *gdata;
 
-       sev = ghes_severity(ghes->estatus->error_severity);
-       apei_estatus_for_each_section(ghes->estatus, gdata) {
-#ifdef CONFIG_X86_MCE
+       sev = ghes_severity(estatus->error_severity);
+       apei_estatus_for_each_section(estatus, gdata) {
+               sec_sev = ghes_severity(gdata->error_severity);
                if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
                                 CPER_SEC_PLATFORM_MEM)) {
-                       apei_mce_report_mem_error(
-                               sev == GHES_SEV_CORRECTED,
-                               (struct cper_sec_mem_err *)(gdata+1));
-                       processed = 1;
-               }
+                       struct cper_sec_mem_err *mem_err;
+                       mem_err = (struct cper_sec_mem_err *)(gdata+1);
+#ifdef CONFIG_X86_MCE
+                       apei_mce_report_mem_error(sev == GHES_SEV_CORRECTED,
+                                                 mem_err);
 #endif
+#ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE
+                       if (sev == GHES_SEV_RECOVERABLE &&
+                           sec_sev == GHES_SEV_RECOVERABLE &&
+                           mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS) {
+                               unsigned long pfn;
+                               pfn = mem_err->physical_addr >> PAGE_SHIFT;
+                               memory_failure_queue(pfn, 0, 0);
+                       }
+#endif
+               }
        }
 }
 
-static void ghes_print_estatus(const char *pfx, struct ghes *ghes)
+static void __ghes_print_estatus(const char *pfx,
+                                const struct acpi_hest_generic *generic,
+                                const struct acpi_hest_generic_status *estatus)
 {
-       /* Not more than 2 messages every 5 seconds */
-       static DEFINE_RATELIMIT_STATE(ratelimit, 5*HZ, 2);
-
        if (pfx == NULL) {
-               if (ghes_severity(ghes->estatus->error_severity) <=
+               if (ghes_severity(estatus->error_severity) <=
                    GHES_SEV_CORRECTED)
                        pfx = KERN_WARNING HW_ERR;
                else
                        pfx = KERN_ERR HW_ERR;
        }
-       if (__ratelimit(&ratelimit)) {
-               printk(
-       "%s""Hardware error from APEI Generic Hardware Error Source: %d\n",
-       pfx, ghes->generic->header.source_id);
-               apei_estatus_print(pfx, ghes->estatus);
+       printk("%s""Hardware error from APEI Generic Hardware Error Source: %d\n",
+              pfx, generic->header.source_id);
+       apei_estatus_print(pfx, estatus);
+}
+
+static int ghes_print_estatus(const char *pfx,
+                             const struct acpi_hest_generic *generic,
+                             const struct acpi_hest_generic_status *estatus)
+{
+       /* Not more than 2 messages every 5 seconds */
+       static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2);
+       static DEFINE_RATELIMIT_STATE(ratelimit_uncorrected, 5*HZ, 2);
+       struct ratelimit_state *ratelimit;
+
+       if (ghes_severity(estatus->error_severity) <= GHES_SEV_CORRECTED)
+               ratelimit = &ratelimit_corrected;
+       else
+               ratelimit = &ratelimit_uncorrected;
+       if (__ratelimit(ratelimit)) {
+               __ghes_print_estatus(pfx, generic, estatus);
+               return 1;
        }
+       return 0;
+}
+
+/*
+ * GHES error status reporting throttle, to report more kinds of
+ * errors, instead of just most frequently occurred errors.
+ */
+static int ghes_estatus_cached(struct acpi_hest_generic_status *estatus)
+{
+       u32 len;
+       int i, cached = 0;
+       unsigned long long now;
+       struct ghes_estatus_cache *cache;
+       struct acpi_hest_generic_status *cache_estatus;
+
+       len = apei_estatus_len(estatus);
+       rcu_read_lock();
+       for (i = 0; i < GHES_ESTATUS_CACHES_SIZE; i++) {
+               cache = rcu_dereference(ghes_estatus_caches[i]);
+               if (cache == NULL)
+                       continue;
+               if (len != cache->estatus_len)
+                       continue;
+               cache_estatus = GHES_ESTATUS_FROM_CACHE(cache);
+               if (memcmp(estatus, cache_estatus, len))
+                       continue;
+               atomic_inc(&cache->count);
+               now = sched_clock();
+               if (now - cache->time_in < GHES_ESTATUS_IN_CACHE_MAX_NSEC)
+                       cached = 1;
+               break;
+       }
+       rcu_read_unlock();
+       return cached;
+}
+
+static struct ghes_estatus_cache *ghes_estatus_cache_alloc(
+       struct acpi_hest_generic *generic,
+       struct acpi_hest_generic_status *estatus)
+{
+       int alloced;
+       u32 len, cache_len;
+       struct ghes_estatus_cache *cache;
+       struct acpi_hest_generic_status *cache_estatus;
+
+       alloced = atomic_add_return(1, &ghes_estatus_cache_alloced);
+       if (alloced > GHES_ESTATUS_CACHE_ALLOCED_MAX) {
+               atomic_dec(&ghes_estatus_cache_alloced);
+               return NULL;
+       }
+       len = apei_estatus_len(estatus);
+       cache_len = GHES_ESTATUS_CACHE_LEN(len);
+       cache = (void *)gen_pool_alloc(ghes_estatus_pool, cache_len);
+       if (!cache) {
+               atomic_dec(&ghes_estatus_cache_alloced);
+               return NULL;
+       }
+       cache_estatus = GHES_ESTATUS_FROM_CACHE(cache);
+       memcpy(cache_estatus, estatus, len);
+       cache->estatus_len = len;
+       atomic_set(&cache->count, 0);
+       cache->generic = generic;
+       cache->time_in = sched_clock();
+       return cache;
+}
+
+static void ghes_estatus_cache_free(struct ghes_estatus_cache *cache)
+{
+       u32 len;
+
+       len = apei_estatus_len(GHES_ESTATUS_FROM_CACHE(cache));
+       len = GHES_ESTATUS_CACHE_LEN(len);
+       gen_pool_free(ghes_estatus_pool, (unsigned long)cache, len);
+       atomic_dec(&ghes_estatus_cache_alloced);
+}
+
+static void ghes_estatus_cache_rcu_free(struct rcu_head *head)
+{
+       struct ghes_estatus_cache *cache;
+
+       cache = container_of(head, struct ghes_estatus_cache, rcu);
+       ghes_estatus_cache_free(cache);
+}
+
+static void ghes_estatus_cache_add(
+       struct acpi_hest_generic *generic,
+       struct acpi_hest_generic_status *estatus)
+{
+       int i, slot = -1, count;
+       unsigned long long now, duration, period, max_period = 0;
+       struct ghes_estatus_cache *cache, *slot_cache = NULL, *new_cache;
+
+       new_cache = ghes_estatus_cache_alloc(generic, estatus);
+       if (new_cache == NULL)
+               return;
+       rcu_read_lock();
+       now = sched_clock();
+       for (i = 0; i < GHES_ESTATUS_CACHES_SIZE; i++) {
+               cache = rcu_dereference(ghes_estatus_caches[i]);
+               if (cache == NULL) {
+                       slot = i;
+                       slot_cache = NULL;
+                       break;
+               }
+               duration = now - cache->time_in;
+               if (duration >= GHES_ESTATUS_IN_CACHE_MAX_NSEC) {
+                       slot = i;
+                       slot_cache = cache;
+                       break;
+               }
+               count = atomic_read(&cache->count);
+               period = duration;
+               do_div(period, (count + 1));
+               if (period > max_period) {
+                       max_period = period;
+                       slot = i;
+                       slot_cache = cache;
+               }
+       }
+       /* new_cache must be put into array after its contents are written */
+       smp_wmb();
+       if (slot != -1 && cmpxchg(ghes_estatus_caches + slot,
+                                 slot_cache, new_cache) == slot_cache) {
+               if (slot_cache)
+                       call_rcu(&slot_cache->rcu, ghes_estatus_cache_rcu_free);
+       } else
+               ghes_estatus_cache_free(new_cache);
+       rcu_read_unlock();
 }
 
 static int ghes_proc(struct ghes *ghes)
@@ -387,9 +648,11 @@ static int ghes_proc(struct ghes *ghes)
        rc = ghes_read_estatus(ghes, 0);
        if (rc)
                goto out;
-       ghes_print_estatus(NULL, ghes);
-       ghes_do_proc(ghes);
-
+       if (!ghes_estatus_cached(ghes->estatus)) {
+               if (ghes_print_estatus(NULL, ghes->generic, ghes->estatus))
+                       ghes_estatus_cache_add(ghes->generic, ghes->estatus);
+       }
+       ghes_do_proc(ghes->estatus);
 out:
        ghes_clear_estatus(ghes);
        return 0;
@@ -447,6 +710,45 @@ static int ghes_notify_sci(struct notifier_block *this,
        return ret;
 }
 
+static void ghes_proc_in_irq(struct irq_work *irq_work)
+{
+       struct llist_node *llnode, *next, *tail = NULL;
+       struct ghes_estatus_node *estatus_node;
+       struct acpi_hest_generic *generic;
+       struct acpi_hest_generic_status *estatus;
+       u32 len, node_len;
+
+       /*
+        * Because the time order of estatus in list is reversed,
+        * revert it back to proper order.
+        */
+       llnode = llist_del_all(&ghes_estatus_llist);
+       while (llnode) {
+               next = llnode->next;
+               llnode->next = tail;
+               tail = llnode;
+               llnode = next;
+       }
+       llnode = tail;
+       while (llnode) {
+               next = llnode->next;
+               estatus_node = llist_entry(llnode, struct ghes_estatus_node,
+                                          llnode);
+               estatus = GHES_ESTATUS_FROM_NODE(estatus_node);
+               len = apei_estatus_len(estatus);
+               node_len = GHES_ESTATUS_NODE_LEN(len);
+               ghes_do_proc(estatus);
+               if (!ghes_estatus_cached(estatus)) {
+                       generic = estatus_node->generic;
+                       if (ghes_print_estatus(NULL, generic, estatus))
+                               ghes_estatus_cache_add(generic, estatus);
+               }
+               gen_pool_free(ghes_estatus_pool, (unsigned long)estatus_node,
+                             node_len);
+               llnode = next;
+       }
+}
+
 static int ghes_notify_nmi(struct notifier_block *this,
                                  unsigned long cmd, void *data)
 {
@@ -476,7 +778,8 @@ static int ghes_notify_nmi(struct notifier_block *this,
 
        if (sev_global >= GHES_SEV_PANIC) {
                oops_begin();
-               ghes_print_estatus(KERN_EMERG HW_ERR, ghes_global);
+               __ghes_print_estatus(KERN_EMERG HW_ERR, ghes_global->generic,
+                                    ghes_global->estatus);
                /* reboot to log the error! */
                if (panic_timeout == 0)
                        panic_timeout = ghes_panic_timeout;
@@ -484,12 +787,34 @@ static int ghes_notify_nmi(struct notifier_block *this,
        }
 
        list_for_each_entry_rcu(ghes, &ghes_nmi, list) {
+#ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
+               u32 len, node_len;
+               struct ghes_estatus_node *estatus_node;
+               struct acpi_hest_generic_status *estatus;
+#endif
                if (!(ghes->flags & GHES_TO_CLEAR))
                        continue;
-               /* Do not print estatus because printk is not NMI safe */
-               ghes_do_proc(ghes);
+#ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
+               if (ghes_estatus_cached(ghes->estatus))
+                       goto next;
+               /* Save estatus for further processing in IRQ context */
+               len = apei_estatus_len(ghes->estatus);
+               node_len = GHES_ESTATUS_NODE_LEN(len);
+               estatus_node = (void *)gen_pool_alloc(ghes_estatus_pool,
+                                                     node_len);
+               if (estatus_node) {
+                       estatus_node->generic = ghes->generic;
+                       estatus = GHES_ESTATUS_FROM_NODE(estatus_node);
+                       memcpy(estatus, ghes->estatus, len);
+                       llist_add(&estatus_node->llnode, &ghes_estatus_llist);
+               }
+next:
+#endif
                ghes_clear_estatus(ghes);
        }
+#ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
+       irq_work_queue(&ghes_proc_irq_work);
+#endif
 
 out:
        raw_spin_unlock(&ghes_nmi_lock);
@@ -504,10 +829,26 @@ static struct notifier_block ghes_notifier_nmi = {
        .notifier_call = ghes_notify_nmi,
 };
 
+static unsigned long ghes_esource_prealloc_size(
+       const struct acpi_hest_generic *generic)
+{
+       unsigned long block_length, prealloc_records, prealloc_size;
+
+       block_length = min_t(unsigned long, generic->error_block_length,
+                            GHES_ESTATUS_MAX_SIZE);
+       prealloc_records = max_t(unsigned long,
+                                generic->records_to_preallocate, 1);
+       prealloc_size = min_t(unsigned long, block_length * prealloc_records,
+                             GHES_ESOURCE_PREALLOC_MAX_SIZE);
+
+       return prealloc_size;
+}
+
 static int __devinit ghes_probe(struct platform_device *ghes_dev)
 {
        struct acpi_hest_generic *generic;
        struct ghes *ghes = NULL;
+       unsigned long len;
        int rc = -EINVAL;
 
        generic = *(struct acpi_hest_generic **)ghes_dev->dev.platform_data;
@@ -573,6 +914,8 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev)
                mutex_unlock(&ghes_list_mutex);
                break;
        case ACPI_HEST_NOTIFY_NMI:
+               len = ghes_esource_prealloc_size(generic);
+               ghes_estatus_pool_expand(len);
                mutex_lock(&ghes_list_mutex);
                if (list_empty(&ghes_nmi))
                        register_die_notifier(&ghes_notifier_nmi);
@@ -597,6 +940,7 @@ static int __devexit ghes_remove(struct platform_device *ghes_dev)
 {
        struct ghes *ghes;
        struct acpi_hest_generic *generic;
+       unsigned long len;
 
        ghes = platform_get_drvdata(ghes_dev);
        generic = ghes->generic;
@@ -627,6 +971,8 @@ static int __devexit ghes_remove(struct platform_device *ghes_dev)
                 * freed after NMI handler finishes.
                 */
                synchronize_rcu();
+               len = ghes_esource_prealloc_size(generic);
+               ghes_estatus_pool_shrink(len);
                break;
        default:
                BUG();
@@ -662,15 +1008,43 @@ static int __init ghes_init(void)
                return -EINVAL;
        }
 
+       if (ghes_disable) {
+               pr_info(GHES_PFX "GHES is not enabled!\n");
+               return -EINVAL;
+       }
+
+       init_irq_work(&ghes_proc_irq_work, ghes_proc_in_irq);
+
        rc = ghes_ioremap_init();
        if (rc)
                goto err;
 
-       rc = platform_driver_register(&ghes_platform_driver);
+       rc = ghes_estatus_pool_init();
        if (rc)
                goto err_ioremap_exit;
 
+       rc = ghes_estatus_pool_expand(GHES_ESTATUS_CACHE_AVG_SIZE *
+                                     GHES_ESTATUS_CACHE_ALLOCED_MAX);
+       if (rc)
+               goto err_pool_exit;
+
+       rc = platform_driver_register(&ghes_platform_driver);
+       if (rc)
+               goto err_pool_exit;
+
+       rc = apei_osc_setup();
+       if (rc == 0 && osc_sb_apei_support_acked)
+               pr_info(GHES_PFX "APEI firmware first mode is enabled by APEI bit and WHEA _OSC.\n");
+       else if (rc == 0 && !osc_sb_apei_support_acked)
+               pr_info(GHES_PFX "APEI firmware first mode is enabled by WHEA _OSC.\n");
+       else if (rc && osc_sb_apei_support_acked)
+               pr_info(GHES_PFX "APEI firmware first mode is enabled by APEI bit.\n");
+       else
+               pr_info(GHES_PFX "Failed to enable APEI firmware first mode.\n");
+
        return 0;
+err_pool_exit:
+       ghes_estatus_pool_exit();
 err_ioremap_exit:
        ghes_ioremap_exit();
 err:
@@ -680,6 +1054,7 @@ err:
 static void __exit ghes_exit(void)
 {
        platform_driver_unregister(&ghes_platform_driver);
+       ghes_estatus_pool_exit();
        ghes_ioremap_exit();
 }
 
index 181bc2f..05fee06 100644 (file)
@@ -231,16 +231,17 @@ void __init acpi_hest_init(void)
                goto err;
        }
 
-       rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count);
-       if (rc)
-               goto err;
-
-       rc = hest_ghes_dev_register(ghes_count);
-       if (!rc) {
-               pr_info(HEST_PFX "Table parsing has been initialized.\n");
-               return;
+       if (!ghes_disable) {
+               rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count);
+               if (rc)
+                       goto err;
+               rc = hest_ghes_dev_register(ghes_count);
+               if (rc)
+                       goto err;
        }
 
+       pr_info(HEST_PFX "Table parsing has been initialized.\n");
+       return;
 err:
        hest_disable = 1;
 }
index 2c66135..7711d94 100644 (file)
@@ -55,6 +55,9 @@
 #define ACPI_BATTERY_NOTIFY_INFO       0x81
 #define ACPI_BATTERY_NOTIFY_THRESHOLD   0x82
 
+/* Battery power unit: 0 means mW, 1 means mA */
+#define ACPI_BATTERY_POWER_UNIT_MA     1
+
 #define _COMPONENT             ACPI_BATTERY_COMPONENT
 
 ACPI_MODULE_NAME("battery");
@@ -91,16 +94,12 @@ MODULE_DEVICE_TABLE(acpi, battery_device_ids);
 enum {
        ACPI_BATTERY_ALARM_PRESENT,
        ACPI_BATTERY_XINFO_PRESENT,
-       /* For buggy DSDTs that report negative 16-bit values for either
-        * charging or discharging current and/or report 0 as 65536
-        * due to bad math.
-        */
-       ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
        ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
 };
 
 struct acpi_battery {
        struct mutex lock;
+       struct mutex sysfs_lock;
        struct power_supply bat;
        struct acpi_device *device;
        struct notifier_block pm_nb;
@@ -301,7 +300,8 @@ static enum power_supply_property energy_battery_props[] = {
 #ifdef CONFIG_ACPI_PROCFS_POWER
 inline char *acpi_battery_units(struct acpi_battery *battery)
 {
-       return (battery->power_unit)?"mA":"mW";
+       return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
+               "mA" : "mW";
 }
 #endif
 
@@ -461,9 +461,17 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
        battery->update_time = jiffies;
        kfree(buffer.pointer);
 
-       if (test_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags) &&
-           battery->rate_now != -1)
+       /* For buggy DSDTs that report negative 16-bit values for either
+        * charging or discharging current and/or report 0 as 65536
+        * due to bad math.
+        */
+       if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA &&
+               battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
+               (s16)(battery->rate_now) < 0) {
                battery->rate_now = abs((s16)battery->rate_now);
+               printk_once(KERN_WARNING FW_BUG "battery: (dis)charge rate"
+                       " invalid.\n");
+       }
 
        if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
            && battery->capacity_now >= 0 && battery->capacity_now <= 100)
@@ -544,7 +552,7 @@ static int sysfs_add_battery(struct acpi_battery *battery)
 {
        int result;
 
-       if (battery->power_unit) {
+       if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
                battery->bat.properties = charge_battery_props;
                battery->bat.num_properties =
                        ARRAY_SIZE(charge_battery_props);
@@ -566,18 +574,16 @@ static int sysfs_add_battery(struct acpi_battery *battery)
 
 static void sysfs_remove_battery(struct acpi_battery *battery)
 {
-       if (!battery->bat.dev)
+       mutex_lock(&battery->sysfs_lock);
+       if (!battery->bat.dev) {
+               mutex_unlock(&battery->sysfs_lock);
                return;
+       }
+
        device_remove_file(battery->bat.dev, &alarm_attr);
        power_supply_unregister(&battery->bat);
        battery->bat.dev = NULL;
-}
-
-static void acpi_battery_quirks(struct acpi_battery *battery)
-{
-       if (dmi_name_in_vendors("Acer") && battery->power_unit) {
-               set_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags);
-       }
+       mutex_unlock(&battery->sysfs_lock);
 }
 
 /*
@@ -592,7 +598,7 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
  *
  * Handle this correctly so that they won't break userspace.
  */
-static void acpi_battery_quirks2(struct acpi_battery *battery)
+static void acpi_battery_quirks(struct acpi_battery *battery)
 {
        if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
                return ;
@@ -623,13 +629,15 @@ static int acpi_battery_update(struct acpi_battery *battery)
                result = acpi_battery_get_info(battery);
                if (result)
                        return result;
-               acpi_battery_quirks(battery);
                acpi_battery_init_alarm(battery);
        }
-       if (!battery->bat.dev)
-               sysfs_add_battery(battery);
+       if (!battery->bat.dev) {
+               result = sysfs_add_battery(battery);
+               if (result)
+                       return result;
+       }
        result = acpi_battery_get_state(battery);
-       acpi_battery_quirks2(battery);
+       acpi_battery_quirks(battery);
        return result;
 }
 
@@ -863,7 +871,7 @@ DECLARE_FILE_FUNCTIONS(alarm);
                }, \
        }
 
-static struct battery_file {
+static const struct battery_file {
        struct file_operations ops;
        mode_t mode;
        const char *name;
@@ -948,9 +956,12 @@ static int battery_notify(struct notifier_block *nb,
        struct acpi_battery *battery = container_of(nb, struct acpi_battery,
                                                    pm_nb);
        switch (mode) {
+       case PM_POST_HIBERNATION:
        case PM_POST_SUSPEND:
-               sysfs_remove_battery(battery);
-               sysfs_add_battery(battery);
+               if (battery->bat.dev) {
+                       sysfs_remove_battery(battery);
+                       sysfs_add_battery(battery);
+               }
                break;
        }
 
@@ -972,28 +983,38 @@ static int acpi_battery_add(struct acpi_device *device)
        strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
        device->driver_data = battery;
        mutex_init(&battery->lock);
+       mutex_init(&battery->sysfs_lock);
        if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle,
                        "_BIX", &handle)))
                set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
-       acpi_battery_update(battery);
+       result = acpi_battery_update(battery);
+       if (result)
+               goto fail;
 #ifdef CONFIG_ACPI_PROCFS_POWER
        result = acpi_battery_add_fs(device);
 #endif
-       if (!result) {
-               printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
-                       ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
-                       device->status.battery_present ? "present" : "absent");
-       } else {
+       if (result) {
 #ifdef CONFIG_ACPI_PROCFS_POWER
                acpi_battery_remove_fs(device);
 #endif
-               kfree(battery);
+               goto fail;
        }
 
+       printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
+               ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
+               device->status.battery_present ? "present" : "absent");
+
        battery->pm_nb.notifier_call = battery_notify;
        register_pm_notifier(&battery->pm_nb);
 
        return result;
+
+fail:
+       sysfs_remove_battery(battery);
+       mutex_destroy(&battery->lock);
+       mutex_destroy(&battery->sysfs_lock);
+       kfree(battery);
+       return result;
 }
 
 static int acpi_battery_remove(struct acpi_device *device, int type)
@@ -1009,6 +1030,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
 #endif
        sysfs_remove_battery(battery);
        mutex_destroy(&battery->lock);
+       mutex_destroy(&battery->sysfs_lock);
        kfree(battery);
        return 0;
 }
index d1e06c1..437ddbf 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/pci.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
+#include <acpi/apei.h>
 #include <linux/dmi.h>
 #include <linux/suspend.h>
 
@@ -519,6 +520,7 @@ out_kfree:
 }
 EXPORT_SYMBOL(acpi_run_osc);
 
+bool osc_sb_apei_support_acked;
 static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
 static void acpi_bus_osc_support(void)
 {
@@ -541,11 +543,19 @@ static void acpi_bus_osc_support(void)
 #if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
        capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT;
 #endif
+
+       if (!ghes_disable)
+               capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_APEI_SUPPORT;
        if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
                return;
-       if (ACPI_SUCCESS(acpi_run_osc(handle, &context)))
+       if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
+               u32 *capbuf_ret = context.ret.pointer;
+               if (context.ret.length > OSC_SUPPORT_TYPE)
+                       osc_sb_apei_support_acked =
+                               capbuf_ret[OSC_SUPPORT_TYPE] & OSC_SB_APEI_SUPPORT;
                kfree(context.ret.pointer);
-       /* do we need to check the returned cap? Sounds no */
+       }
+       /* do we need to check other returned cap? Sounds no */
 }
 
 /* --------------------------------------------------------------------------
index 1864ad3..19a6113 100644 (file)
@@ -77,7 +77,7 @@ struct dock_dependent_device {
        struct list_head list;
        struct list_head hotplug_list;
        acpi_handle handle;
-       struct acpi_dock_ops *ops;
+       const struct acpi_dock_ops *ops;
        void *context;
 };
 
@@ -589,7 +589,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier);
  * the dock driver after _DCK is executed.
  */
 int
-register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops,
+register_hotplug_dock_device(acpi_handle handle, const struct acpi_dock_ops *ops,
                             void *context)
 {
        struct dock_dependent_device *dd;
index 05b4420..22f918b 100644 (file)
@@ -92,7 +92,7 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf,
        return count;
 }
 
-static struct file_operations acpi_ec_io_ops = {
+static const struct file_operations acpi_ec_io_ops = {
        .owner = THIS_MODULE,
        .open  = acpi_ec_open_io,
        .read  = acpi_ec_read_io,
index 467479f..0f0356c 100644 (file)
@@ -110,7 +110,7 @@ fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
        return result;
 }
 
-static struct thermal_cooling_device_ops fan_cooling_ops = {
+static const struct thermal_cooling_device_ops fan_cooling_ops = {
        .get_max_state = fan_get_max_state,
        .get_cur_state = fan_get_cur_state,
        .set_cur_state = fan_set_cur_state,
index 372f9b7..fa32f58 100644 (file)
@@ -155,7 +155,7 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported)
 {
        if (!strcmp("Linux", interface)) {
 
-               printk(KERN_NOTICE FW_BUG PREFIX
+               printk_once(KERN_NOTICE FW_BUG PREFIX
                        "BIOS _OSI(Linux) query %s%s\n",
                        osi_linux.enable ? "honored" : "ignored",
                        osi_linux.cmdline ? " via cmdline" :
@@ -237,8 +237,23 @@ void acpi_os_vprintf(const char *fmt, va_list args)
 #endif
 }
 
+#ifdef CONFIG_KEXEC
+static unsigned long acpi_rsdp;
+static int __init setup_acpi_rsdp(char *arg)
+{
+       acpi_rsdp = simple_strtoul(arg, NULL, 16);
+       return 0;
+}
+early_param("acpi_rsdp", setup_acpi_rsdp);
+#endif
+
 acpi_physical_address __init acpi_os_get_root_pointer(void)
 {
+#ifdef CONFIG_KEXEC
+       if (acpi_rsdp)
+               return acpi_rsdp;
+#endif
+
        if (efi_enabled) {
                if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
                        return efi.acpi20;
@@ -1083,7 +1098,13 @@ struct osi_setup_entry {
        bool enable;
 };
 
-static struct osi_setup_entry __initdata osi_setup_entries[OSI_STRING_ENTRIES_MAX];
+static struct osi_setup_entry __initdata
+               osi_setup_entries[OSI_STRING_ENTRIES_MAX] = {
+       {"Module Device", true},
+       {"Processor Device", true},
+       {"3.0 _SCP Extensions", true},
+       {"Processor Aggregator Device", true},
+};
 
 void __init acpi_osi_setup(char *str)
 {
index f907cfb..7f9eba9 100644 (file)
@@ -303,6 +303,61 @@ void acpi_pci_irq_del_prt(struct pci_bus *bus)
 /* --------------------------------------------------------------------------
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
+#ifdef CONFIG_X86_IO_APIC
+extern int noioapicquirk;
+extern int noioapicreroute;
+
+static int bridge_has_boot_interrupt_variant(struct pci_bus *bus)
+{
+       struct pci_bus *bus_it;
+
+       for (bus_it = bus ; bus_it ; bus_it = bus_it->parent) {
+               if (!bus_it->self)
+                       return 0;
+               if (bus_it->self->irq_reroute_variant)
+                       return bus_it->self->irq_reroute_variant;
+       }
+       return 0;
+}
+
+/*
+ * Some chipsets (e.g. Intel 6700PXH) generate a legacy INTx when the IRQ
+ * entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel does
+ * during interrupt handling). When this INTx generation cannot be disabled,
+ * we reroute these interrupts to their legacy equivalent to get rid of
+ * spurious interrupts.
+ */
+static int acpi_reroute_boot_interrupt(struct pci_dev *dev,
+                                      struct acpi_prt_entry *entry)
+{
+       if (noioapicquirk || noioapicreroute) {
+               return 0;
+       } else {
+               switch (bridge_has_boot_interrupt_variant(dev->bus)) {
+               case 0:
+                       /* no rerouting necessary */
+                       return 0;
+               case INTEL_IRQ_REROUTE_VARIANT:
+                       /*
+                        * Remap according to INTx routing table in 6700PXH
+                        * specs, intel order number 302628-002, section
+                        * 2.15.2. Other chipsets (80332, ...) have the same
+                        * mapping and are handled here as well.
+                        */
+                       dev_info(&dev->dev, "PCI IRQ %d -> rerouted to legacy "
+                                "IRQ %d\n", entry->index,
+                                (entry->index % 4) + 16);
+                       entry->index = (entry->index % 4) + 16;
+                       return 1;
+               default:
+                       dev_warn(&dev->dev, "Cannot reroute IRQ %d to legacy "
+                                "IRQ: unknown mapping\n", entry->index);
+                       return -1;
+               }
+       }
+}
+#endif /* CONFIG_X86_IO_APIC */
+
 static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
 {
        struct acpi_prt_entry *entry;
@@ -311,6 +366,9 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
 
        entry = acpi_pci_irq_find_prt_entry(dev, pin);
        if (entry) {
+#ifdef CONFIG_X86_IO_APIC
+               acpi_reroute_boot_interrupt(dev, entry);
+#endif /* CONFIG_X86_IO_APIC */
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n",
                                  pci_name(dev), pin_name(pin)));
                return entry;
index d06078d..2672c79 100644 (file)
@@ -485,7 +485,8 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
                root->secondary.end = 0xFF;
                printk(KERN_WARNING FW_BUG PREFIX
                       "no secondary bus range in _CRS\n");
-               status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN,                                               NULL, &bus);
+               status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN,
+                                              NULL, &bus);
                if (ACPI_SUCCESS(status))
                        root->secondary.start = bus;
                else if (status == AE_NOT_FOUND)
index 79cb653..870550d 100644 (file)
@@ -244,7 +244,7 @@ processor_set_cur_state(struct thermal_cooling_device *cdev,
        return result;
 }
 
-struct thermal_cooling_device_ops processor_cooling_ops = {
+const struct thermal_cooling_device_ops processor_cooling_ops = {
        .get_max_state = processor_get_max_state,
        .get_cur_state = processor_get_cur_state,
        .set_cur_state = processor_set_cur_state,
index 50658ff..6e36d0c 100644 (file)
@@ -130,6 +130,9 @@ struct acpi_sbs {
 
 #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
 
+static int acpi_sbs_remove(struct acpi_device *device, int type);
+static int acpi_battery_get_state(struct acpi_battery *battery);
+
 static inline int battery_scale(int log)
 {
        int scale = 1;
@@ -195,6 +198,8 @@ static int acpi_sbs_battery_get_property(struct power_supply *psy,
 
        if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT)
                return -ENODEV;
+
+       acpi_battery_get_state(battery);
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
                if (battery->rate_now < 0)
@@ -225,11 +230,17 @@ static int acpi_sbs_battery_get_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_POWER_NOW:
                val->intval = abs(battery->rate_now) *
                                acpi_battery_ipscale(battery) * 1000;
+               val->intval *= (acpi_battery_mode(battery)) ?
+                               (battery->voltage_now *
+                               acpi_battery_vscale(battery) / 1000) : 1;
                break;
        case POWER_SUPPLY_PROP_CURRENT_AVG:
        case POWER_SUPPLY_PROP_POWER_AVG:
                val->intval = abs(battery->rate_avg) *
                                acpi_battery_ipscale(battery) * 1000;
+               val->intval *= (acpi_battery_mode(battery)) ?
+                               (battery->voltage_now *
+                               acpi_battery_vscale(battery) / 1000) : 1;
                break;
        case POWER_SUPPLY_PROP_CAPACITY:
                val->intval = battery->state_of_charge;
@@ -903,8 +914,6 @@ static void acpi_sbs_callback(void *context)
        }
 }
 
-static int acpi_sbs_remove(struct acpi_device *device, int type);
-
 static int acpi_sbs_add(struct acpi_device *device)
 {
        struct acpi_sbs *sbs;
index 6c94960..3ed80b2 100644 (file)
@@ -428,6 +428,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"),
                },
        },
+       {
+       .callback = init_old_suspend_ordering,
+       .ident = "Asus A8N-SLI DELUXE",
+       .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+               DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"),
+               },
+       },
+       {
+       .callback = init_old_suspend_ordering,
+       .ident = "Asus A8N-SLI Premium",
+       .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+               DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"),
+               },
+       },
        {},
 };
 #endif /* CONFIG_SUSPEND */
index 77255f2..c538d0e 100644 (file)
@@ -149,12 +149,12 @@ static int param_get_debug_level(char *buffer, const struct kernel_param *kp)
        return result;
 }
 
-static struct kernel_param_ops param_ops_debug_layer = {
+static const struct kernel_param_ops param_ops_debug_layer = {
        .set = param_set_uint,
        .get = param_get_debug_layer,
 };
 
-static struct kernel_param_ops param_ops_debug_level = {
+static const struct kernel_param_ops param_ops_debug_level = {
        .set = param_set_uint,
        .get = param_get_debug_level,
 };
index 2607e17..48fbc64 100644 (file)
@@ -812,7 +812,7 @@ acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
                                thermal_zone_unbind_cooling_device);
 }
 
-static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
+static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
        .bind = acpi_thermal_bind_cooling_device,
        .unbind = acpi_thermal_unbind_cooling_device,
        .get_temp = thermal_get_temp,
index ada4b4d..08a44b5 100644 (file)
@@ -307,7 +307,7 @@ video_set_cur_state(struct thermal_cooling_device *cooling_dev, unsigned long st
        return acpi_video_device_lcd_set_level(video, level);
 }
 
-static struct thermal_cooling_device_ops video_cooling_ops = {
+static const struct thermal_cooling_device_ops video_cooling_ops = {
        .get_max_state = video_get_max_state,
        .get_cur_state = video_get_cur_state,
        .set_cur_state = video_set_cur_state,
index e0a5b55..bb7c5f1 100644 (file)
@@ -218,12 +218,12 @@ static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data)
        ata_acpi_uevent(dev->link->ap, dev, event);
 }
 
-static struct acpi_dock_ops ata_acpi_dev_dock_ops = {
+static const struct acpi_dock_ops ata_acpi_dev_dock_ops = {
        .handler = ata_acpi_dev_notify_dock,
        .uevent = ata_acpi_dev_uevent,
 };
 
-static struct acpi_dock_ops ata_acpi_ap_dock_ops = {
+static const struct acpi_dock_ops ata_acpi_ap_dock_ops = {
        .handler = ata_acpi_ap_notify_dock,
        .uevent = ata_acpi_ap_uevent,
 };
index 9307141..f7ca4c1 100644 (file)
@@ -1134,7 +1134,8 @@ DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */
                                    skb_headlen(skb));
                        else
                                put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
-                                   skb_shinfo(skb)->frags[i].page + skb_shinfo(skb)->frags[i].page_offset,
+                                   skb_frag_page(&skb_shinfo(skb)->frags[i]) +
+                                       skb_shinfo(skb)->frags[i].page_offset,
                                    skb_shinfo(skb)->frags[i].size);
        }
        if (skb->len & 3)
index b89fffc..33e1bed 100644 (file)
@@ -166,7 +166,7 @@ static int create_path(const char *nodepath)
 {
        char *path;
        char *s;
-       int err;
+       int err = 0;
 
        /* parent directories do not exist, create them */
        path = kstrdup(nodepath, GFP_KERNEL);
index be8714a..e18566a 100644 (file)
@@ -80,7 +80,6 @@ static void genpd_set_active(struct generic_pm_domain *genpd)
 int pm_genpd_poweron(struct generic_pm_domain *genpd)
 {
        struct generic_pm_domain *parent = genpd->parent;
-       DEFINE_WAIT(wait);
        int ret = 0;
 
  start:
@@ -112,7 +111,7 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd)
        }
 
        if (genpd->power_on) {
-               int ret = genpd->power_on(genpd);
+               ret = genpd->power_on(genpd);
                if (ret)
                        goto out;
        }
index 8dc247c..acb3f83 100644 (file)
@@ -226,11 +226,17 @@ static int rpm_idle(struct device *dev, int rpmflags)
                callback = NULL;
 
        if (callback) {
-               spin_unlock_irq(&dev->power.lock);
+               if (dev->power.irq_safe)
+                       spin_unlock(&dev->power.lock);
+               else
+                       spin_unlock_irq(&dev->power.lock);
 
                callback(dev);
 
-               spin_lock_irq(&dev->power.lock);
+               if (dev->power.irq_safe)
+                       spin_lock(&dev->power.lock);
+               else
+                       spin_lock_irq(&dev->power.lock);
        }
 
        dev->power.idle_notification = false;
index 49502bc..423fd56 100644 (file)
@@ -616,5 +616,16 @@ config MSM_SMD_PKT
          Enables userspace clients to read and write to some packet SMD
          ports via device interface for MSM chipset.
 
+config TILE_SROM
+       bool "Character-device access via hypervisor to the Tilera SPI ROM"
+       depends on TILE
+       default y
+       ---help---
+         This device provides character-level read-write access
+         to the SROM, typically via the "0", "1", and "2" devices
+         in /dev/srom/.  The Tilera hypervisor makes the flash
+         device appear much like a simple EEPROM, and knows
+         how to partition a single ROM for multiple purposes.
+
 endmenu
 
index 7a00672..32762ba 100644 (file)
@@ -63,3 +63,5 @@ obj-$(CONFIG_RAMOOPS)         += ramoops.o
 
 obj-$(CONFIG_JS_RTC)           += js-rtc.o
 js-rtc-y = rtc.o
+
+obj-$(CONFIG_TILE_SROM)                += tile-srom.o
index ac6739e..c3de70d 100644 (file)
@@ -1,6 +1,6 @@
 /* n2-drv.c: Niagara-2 RNG driver.
  *
- * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 2008, 2011 David S. Miller <davem@davemloft.net>
  */
 
 #include <linux/kernel.h>
@@ -22,8 +22,8 @@
 
 #define DRV_MODULE_NAME                "n2rng"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "0.1"
-#define DRV_MODULE_RELDATE     "May 15, 2008"
+#define DRV_MODULE_VERSION     "0.2"
+#define DRV_MODULE_RELDATE     "July 27, 2011"
 
 static char version[] __devinitdata =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -623,14 +623,14 @@ static const struct of_device_id n2rng_match[];
 static int __devinit n2rng_probe(struct platform_device *op)
 {
        const struct of_device_id *match;
-       int victoria_falls;
+       int multi_capable;
        int err = -ENOMEM;
        struct n2rng *np;
 
        match = of_match_device(n2rng_match, &op->dev);
        if (!match)
                return -EINVAL;
-       victoria_falls = (match->data != NULL);
+       multi_capable = (match->data != NULL);
 
        n2rng_driver_version();
        np = kzalloc(sizeof(*np), GFP_KERNEL);
@@ -640,8 +640,8 @@ static int __devinit n2rng_probe(struct platform_device *op)
 
        INIT_DELAYED_WORK(&np->work, n2rng_work);
 
-       if (victoria_falls)
-               np->flags |= N2RNG_FLAG_VF;
+       if (multi_capable)
+               np->flags |= N2RNG_FLAG_MULTI;
 
        err = -ENODEV;
        np->hvapi_major = 2;
@@ -658,10 +658,10 @@ static int __devinit n2rng_probe(struct platform_device *op)
                }
        }
 
-       if (np->flags & N2RNG_FLAG_VF) {
+       if (np->flags & N2RNG_FLAG_MULTI) {
                if (np->hvapi_major < 2) {
-                       dev_err(&op->dev, "VF RNG requires HVAPI major "
-                               "version 2 or later, got %lu\n",
+                       dev_err(&op->dev, "multi-unit-capable RNG requires "
+                               "HVAPI major version 2 or later, got %lu\n",
                                np->hvapi_major);
                        goto out_hvapi_unregister;
                }
@@ -688,8 +688,8 @@ static int __devinit n2rng_probe(struct platform_device *op)
                goto out_free_units;
 
        dev_info(&op->dev, "Found %s RNG, units: %d\n",
-                ((np->flags & N2RNG_FLAG_VF) ?
-                 "Victoria Falls" : "Niagara2"),
+                ((np->flags & N2RNG_FLAG_MULTI) ?
+                 "multi-unit-capable" : "single-unit"),
                 np->num_units);
 
        np->hwrng.name = "n2rng";
@@ -751,6 +751,11 @@ static const struct of_device_id n2rng_match[] = {
                .compatible     = "SUNW,vf-rng",
                .data           = (void *) 1,
        },
+       {
+               .name           = "random-number-generator",
+               .compatible     = "SUNW,kt-rng",
+               .data           = (void *) 1,
+       },
        {},
 };
 MODULE_DEVICE_TABLE(of, n2rng_match);
index 4bea07f..f244ac8 100644 (file)
@@ -68,7 +68,7 @@ struct n2rng {
        struct platform_device  *op;
 
        unsigned long           flags;
-#define N2RNG_FLAG_VF          0x00000001 /* Victoria Falls RNG, else N2 */
+#define N2RNG_FLAG_MULTI       0x00000001 /* Multi-unit capable RNG */
 #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        */
index bd9b94b..810aff9 100644 (file)
@@ -22,6 +22,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/kernel.h>
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/kmsg_dump.h>
 #include <linux/time.h>
@@ -146,6 +147,14 @@ static int __init ramoops_probe(struct platform_device *pdev)
        cxt->phys_addr = pdata->mem_address;
        cxt->record_size = pdata->record_size;
        cxt->dump_oops = pdata->dump_oops;
+       /*
+        * Update the module parameter variables as well so they are visible
+        * through /sys/module/ramoops/parameters/
+        */
+       mem_size = pdata->mem_size;
+       mem_address = pdata->mem_address;
+       record_size = pdata->record_size;
+       dump_oops = pdata->dump_oops;
 
        if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) {
                pr_err("request mem region failed\n");
index 7292819..c35a785 100644 (file)
@@ -1300,345 +1300,14 @@ ctl_table random_table[] = {
 };
 #endif         /* CONFIG_SYSCTL */
 
-/********************************************************************
- *
- * Random functions for networking
- *
- ********************************************************************/
-
-/*
- * TCP initial sequence number picking.  This uses the random number
- * generator to pick an initial secret value.  This value is hashed
- * along with the TCP endpoint information to provide a unique
- * starting point for each pair of TCP endpoints.  This defeats
- * attacks which rely on guessing the initial TCP sequence number.
- * This algorithm was suggested by Steve Bellovin.
- *
- * Using a very strong hash was taking an appreciable amount of the total
- * TCP connection establishment time, so this is a weaker hash,
- * compensated for by changing the secret periodically.
- */
-
-/* F, G and H are basic MD4 functions: selection, majority, parity */
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-
-/*
- * The generic round function.  The application is so specific that
- * we don't bother protecting all the arguments with parens, as is generally
- * good macro practice, in favor of extra legibility.
- * Rotation is separate from addition to prevent recomputation
- */
-#define ROUND(f, a, b, c, d, x, s)     \
-       (a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s)))
-#define K1 0
-#define K2 013240474631UL
-#define K3 015666365641UL
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-
-static __u32 twothirdsMD4Transform(__u32 const buf[4], __u32 const in[12])
-{
-       __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-
-       /* Round 1 */
-       ROUND(F, a, b, c, d, in[ 0] + K1,  3);
-       ROUND(F, d, a, b, c, in[ 1] + K1,  7);
-       ROUND(F, c, d, a, b, in[ 2] + K1, 11);
-       ROUND(F, b, c, d, a, in[ 3] + K1, 19);
-       ROUND(F, a, b, c, d, in[ 4] + K1,  3);
-       ROUND(F, d, a, b, c, in[ 5] + K1,  7);
-       ROUND(F, c, d, a, b, in[ 6] + K1, 11);
-       ROUND(F, b, c, d, a, in[ 7] + K1, 19);
-       ROUND(F, a, b, c, d, in[ 8] + K1,  3);
-       ROUND(F, d, a, b, c, in[ 9] + K1,  7);
-       ROUND(F, c, d, a, b, in[10] + K1, 11);
-       ROUND(F, b, c, d, a, in[11] + K1, 19);
-
-       /* Round 2 */
-       ROUND(G, a, b, c, d, in[ 1] + K2,  3);
-       ROUND(G, d, a, b, c, in[ 3] + K2,  5);
-       ROUND(G, c, d, a, b, in[ 5] + K2,  9);
-       ROUND(G, b, c, d, a, in[ 7] + K2, 13);
-       ROUND(G, a, b, c, d, in[ 9] + K2,  3);
-       ROUND(G, d, a, b, c, in[11] + K2,  5);
-       ROUND(G, c, d, a, b, in[ 0] + K2,  9);
-       ROUND(G, b, c, d, a, in[ 2] + K2, 13);
-       ROUND(G, a, b, c, d, in[ 4] + K2,  3);
-       ROUND(G, d, a, b, c, in[ 6] + K2,  5);
-       ROUND(G, c, d, a, b, in[ 8] + K2,  9);
-       ROUND(G, b, c, d, a, in[10] + K2, 13);
-
-       /* Round 3 */
-       ROUND(H, a, b, c, d, in[ 3] + K3,  3);
-       ROUND(H, d, a, b, c, in[ 7] + K3,  9);
-       ROUND(H, c, d, a, b, in[11] + K3, 11);
-       ROUND(H, b, c, d, a, in[ 2] + K3, 15);
-       ROUND(H, a, b, c, d, in[ 6] + K3,  3);
-       ROUND(H, d, a, b, c, in[10] + K3,  9);
-       ROUND(H, c, d, a, b, in[ 1] + K3, 11);
-       ROUND(H, b, c, d, a, in[ 5] + K3, 15);
-       ROUND(H, a, b, c, d, in[ 9] + K3,  3);
-       ROUND(H, d, a, b, c, in[ 0] + K3,  9);
-       ROUND(H, c, d, a, b, in[ 4] + K3, 11);
-       ROUND(H, b, c, d, a, in[ 8] + K3, 15);
-
-       return buf[1] + b; /* "most hashed" word */
-       /* Alternative: return sum of all words? */
-}
-#endif
-
-#undef ROUND
-#undef F
-#undef G
-#undef H
-#undef K1
-#undef K2
-#undef K3
-
-/* This should not be decreased so low that ISNs wrap too fast. */
-#define REKEY_INTERVAL (300 * HZ)
-/*
- * Bit layout of the tcp sequence numbers (before adding current time):
- * bit 24-31: increased after every key exchange
- * bit 0-23: hash(source,dest)
- *
- * The implementation is similar to the algorithm described
- * in the Appendix of RFC 1185, except that
- * - it uses a 1 MHz clock instead of a 250 kHz clock
- * - it performs a rekey every 5 minutes, which is equivalent
- *     to a (source,dest) tulple dependent forward jump of the
- *     clock by 0..2^(HASH_BITS+1)
- *
- * Thus the average ISN wraparound time is 68 minutes instead of
- * 4.55 hours.
- *
- * SMP cleanup and lock avoidance with poor man's RCU.
- *                     Manfred Spraul <manfred@colorfullife.com>
- *
- */
-#define COUNT_BITS 8
-#define COUNT_MASK ((1 << COUNT_BITS) - 1)
-#define HASH_BITS 24
-#define HASH_MASK ((1 << HASH_BITS) - 1)
+static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
 
-static struct keydata {
-       __u32 count; /* already shifted to the final position */
-       __u32 secret[12];
-} ____cacheline_aligned ip_keydata[2];
-
-static unsigned int ip_cnt;
-
-static void rekey_seq_generator(struct work_struct *work);
-
-static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator);
-
-/*
- * Lock avoidance:
- * The ISN generation runs lockless - it's just a hash over random data.
- * State changes happen every 5 minutes when the random key is replaced.
- * Synchronization is performed by having two copies of the hash function
- * state and rekey_seq_generator always updates the inactive copy.
- * The copy is then activated by updating ip_cnt.
- * The implementation breaks down if someone blocks the thread
- * that processes SYN requests for more than 5 minutes. Should never
- * happen, and even if that happens only a not perfectly compliant
- * ISN is generated, nothing fatal.
- */
-static void rekey_seq_generator(struct work_struct *work)
+static int __init random_int_secret_init(void)
 {
-       struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)];
-
-       get_random_bytes(keyptr->secret, sizeof(keyptr->secret));
-       keyptr->count = (ip_cnt & COUNT_MASK) << HASH_BITS;
-       smp_wmb();
-       ip_cnt++;
-       schedule_delayed_work(&rekey_work,
-                             round_jiffies_relative(REKEY_INTERVAL));
-}
-
-static inline struct keydata *get_keyptr(void)
-{
-       struct keydata *keyptr = &ip_keydata[ip_cnt & 1];
-
-       smp_rmb();
-
-       return keyptr;
-}
-
-static __init int seqgen_init(void)
-{
-       rekey_seq_generator(NULL);
+       get_random_bytes(random_int_secret, sizeof(random_int_secret));
        return 0;
 }
-late_initcall(seqgen_init);
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-__u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
-                                  __be16 sport, __be16 dport)
-{
-       __u32 seq;
-       __u32 hash[12];
-       struct keydata *keyptr = get_keyptr();
-
-       /* The procedure is the same as for IPv4, but addresses are longer.
-        * Thus we must use twothirdsMD4Transform.
-        */
-
-       memcpy(hash, saddr, 16);
-       hash[4] = ((__force u16)sport << 16) + (__force u16)dport;
-       memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7);
-
-       seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK;
-       seq += keyptr->count;
-
-       seq += ktime_to_ns(ktime_get_real());
-
-       return seq;
-}
-EXPORT_SYMBOL(secure_tcpv6_sequence_number);
-#endif
-
-/*  The code below is shamelessly stolen from secure_tcp_sequence_number().
- *  All blames to Andrey V. Savochkin <saw@msu.ru>.
- */
-__u32 secure_ip_id(__be32 daddr)
-{
-       struct keydata *keyptr;
-       __u32 hash[4];
-
-       keyptr = get_keyptr();
-
-       /*
-        *  Pick a unique starting offset for each IP destination.
-        *  The dest ip address is placed in the starting vector,
-        *  which is then hashed with random data.
-        */
-       hash[0] = (__force __u32)daddr;
-       hash[1] = keyptr->secret[9];
-       hash[2] = keyptr->secret[10];
-       hash[3] = keyptr->secret[11];
-
-       return half_md4_transform(hash, keyptr->secret);
-}
-
-__u32 secure_ipv6_id(const __be32 daddr[4])
-{
-       const struct keydata *keyptr;
-       __u32 hash[4];
-
-       keyptr = get_keyptr();
-
-       hash[0] = (__force __u32)daddr[0];
-       hash[1] = (__force __u32)daddr[1];
-       hash[2] = (__force __u32)daddr[2];
-       hash[3] = (__force __u32)daddr[3];
-
-       return half_md4_transform(hash, keyptr->secret);
-}
-
-#ifdef CONFIG_INET
-
-__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
-                                __be16 sport, __be16 dport)
-{
-       __u32 seq;
-       __u32 hash[4];
-       struct keydata *keyptr = get_keyptr();
-
-       /*
-        *  Pick a unique starting offset for each TCP connection endpoints
-        *  (saddr, daddr, sport, dport).
-        *  Note that the words are placed into the starting vector, which is
-        *  then mixed with a partial MD4 over random data.
-        */
-       hash[0] = (__force u32)saddr;
-       hash[1] = (__force u32)daddr;
-       hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
-       hash[3] = keyptr->secret[11];
-
-       seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK;
-       seq += keyptr->count;
-       /*
-        *      As close as possible to RFC 793, which
-        *      suggests using a 250 kHz clock.
-        *      Further reading shows this assumes 2 Mb/s networks.
-        *      For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
-        *      For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
-        *      we also need to limit the resolution so that the u32 seq
-        *      overlaps less than one time per MSL (2 minutes).
-        *      Choosing a clock of 64 ns period is OK. (period of 274 s)
-        */
-       seq += ktime_to_ns(ktime_get_real()) >> 6;
-
-       return seq;
-}
-
-/* Generate secure starting point for ephemeral IPV4 transport port search */
-u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
-{
-       struct keydata *keyptr = get_keyptr();
-       u32 hash[4];
-
-       /*
-        *  Pick a unique starting offset for each ephemeral port search
-        *  (saddr, daddr, dport) and 48bits of random data.
-        */
-       hash[0] = (__force u32)saddr;
-       hash[1] = (__force u32)daddr;
-       hash[2] = (__force u32)dport ^ keyptr->secret[10];
-       hash[3] = keyptr->secret[11];
-
-       return half_md4_transform(hash, keyptr->secret);
-}
-EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
-                              __be16 dport)
-{
-       struct keydata *keyptr = get_keyptr();
-       u32 hash[12];
-
-       memcpy(hash, saddr, 16);
-       hash[4] = (__force u32)dport;
-       memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7);
-
-       return twothirdsMD4Transform((const __u32 *)daddr, hash);
-}
-#endif
-
-#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
-/* Similar to secure_tcp_sequence_number but generate a 48 bit value
- * bit's 32-47 increase every key exchange
- *       0-31  hash(source, dest)
- */
-u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
-                               __be16 sport, __be16 dport)
-{
-       u64 seq;
-       __u32 hash[4];
-       struct keydata *keyptr = get_keyptr();
-
-       hash[0] = (__force u32)saddr;
-       hash[1] = (__force u32)daddr;
-       hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
-       hash[3] = keyptr->secret[11];
-
-       seq = half_md4_transform(hash, keyptr->secret);
-       seq |= ((u64)keyptr->count) << (32 - HASH_BITS);
-
-       seq += ktime_to_ns(ktime_get_real());
-       seq &= (1ull << 48) - 1;
-
-       return seq;
-}
-EXPORT_SYMBOL(secure_dccp_sequence_number);
-#endif
-
-#endif /* CONFIG_INET */
-
+late_initcall(random_int_secret_init);
 
 /*
  * Get a random word for internal kernel use only. Similar to urandom but
@@ -1646,17 +1315,15 @@ EXPORT_SYMBOL(secure_dccp_sequence_number);
  * value is not cryptographically secure but for several uses the cost of
  * depleting entropy is too high
  */
-DEFINE_PER_CPU(__u32 [4], get_random_int_hash);
+DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
 unsigned int get_random_int(void)
 {
-       struct keydata *keyptr;
        __u32 *hash = get_cpu_var(get_random_int_hash);
-       int ret;
+       unsigned int ret;
 
-       keyptr = get_keyptr();
        hash[0] += current->pid + jiffies + get_cycles();
-
-       ret = half_md4_transform(hash, keyptr->secret);
+       md5_transform(hash, random_int_secret);
+       ret = hash[0];
        put_cpu_var(get_random_int_hash);
 
        return ret;
diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
new file mode 100644 (file)
index 0000000..cf3ee00
--- /dev/null
@@ -0,0 +1,481 @@
+/*
+ * Copyright 2011 Tilera 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, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ * SPI Flash ROM driver
+ *
+ * This source code is derived from code provided in "Linux Device
+ * Drivers, Third Edition", by Jonathan Corbet, Alessandro Rubini, and
+ * Greg Kroah-Hartman, published by O'Reilly Media, Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/kernel.h>      /* printk() */
+#include <linux/slab.h>                /* kmalloc() */
+#include <linux/fs.h>          /* everything... */
+#include <linux/errno.h>       /* error codes */
+#include <linux/types.h>       /* size_t */
+#include <linux/proc_fs.h>
+#include <linux/fcntl.h>       /* O_ACCMODE */
+#include <linux/aio.h>
+#include <linux/pagemap.h>
+#include <linux/hugetlb.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <hv/hypervisor.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/delay.h>
+#include <hv/drv_srom_intf.h>
+
+/*
+ * Size of our hypervisor I/O requests.  We break up large transfers
+ * so that we don't spend large uninterrupted spans of time in the
+ * hypervisor.  Erasing an SROM sector takes a significant fraction of
+ * a second, so if we allowed the user to, say, do one I/O to write the
+ * entire ROM, we'd get soft lockup timeouts, or worse.
+ */
+#define SROM_CHUNK_SIZE ((size_t)4096)
+
+/*
+ * When hypervisor is busy (e.g. erasing), poll the status periodically.
+ */
+
+/*
+ * Interval to poll the state in msec
+ */
+#define SROM_WAIT_TRY_INTERVAL 20
+
+/*
+ * Maximum times to poll the state
+ */
+#define SROM_MAX_WAIT_TRY_TIMES 1000
+
+struct srom_dev {
+       int hv_devhdl;                  /* Handle for hypervisor device */
+       u32 total_size;                 /* Size of this device */
+       u32 sector_size;                /* Size of a sector */
+       u32 page_size;                  /* Size of a page */
+       struct mutex lock;              /* Allow only one accessor at a time */
+};
+
+static int srom_major;                 /* Dynamic major by default */
+module_param(srom_major, int, 0);
+MODULE_AUTHOR("Tilera Corporation");
+MODULE_LICENSE("GPL");
+
+static int srom_devs;                  /* Number of SROM partitions */
+static struct cdev srom_cdev;
+static struct class *srom_class;
+static struct srom_dev *srom_devices;
+
+/*
+ * Handle calling the hypervisor and managing EAGAIN/EBUSY.
+ */
+
+static ssize_t _srom_read(int hv_devhdl, void *buf,
+                         loff_t off, size_t count)
+{
+       int retval, retries = SROM_MAX_WAIT_TRY_TIMES;
+       for (;;) {
+               retval = hv_dev_pread(hv_devhdl, 0, (HV_VirtAddr)buf,
+                                     count, off);
+               if (retval >= 0)
+                       return retval;
+               if (retval == HV_EAGAIN)
+                       continue;
+               if (retval == HV_EBUSY && --retries > 0) {
+                       msleep(SROM_WAIT_TRY_INTERVAL);
+                       continue;
+               }
+               pr_err("_srom_read: error %d\n", retval);
+               return -EIO;
+       }
+}
+
+static ssize_t _srom_write(int hv_devhdl, const void *buf,
+                          loff_t off, size_t count)
+{
+       int retval, retries = SROM_MAX_WAIT_TRY_TIMES;
+       for (;;) {
+               retval = hv_dev_pwrite(hv_devhdl, 0, (HV_VirtAddr)buf,
+                                      count, off);
+               if (retval >= 0)
+                       return retval;
+               if (retval == HV_EAGAIN)
+                       continue;
+               if (retval == HV_EBUSY && --retries > 0) {
+                       msleep(SROM_WAIT_TRY_INTERVAL);
+                       continue;
+               }
+               pr_err("_srom_write: error %d\n", retval);
+               return -EIO;
+       }
+}
+
+/**
+ * srom_open() - Device open routine.
+ * @inode: Inode for this device.
+ * @filp: File for this specific open of the device.
+ *
+ * Returns zero, or an error code.
+ */
+static int srom_open(struct inode *inode, struct file *filp)
+{
+       filp->private_data = &srom_devices[iminor(inode)];
+       return 0;
+}
+
+
+/**
+ * srom_release() - Device release routine.
+ * @inode: Inode for this device.
+ * @filp: File for this specific open of the device.
+ *
+ * Returns zero, or an error code.
+ */
+static int srom_release(struct inode *inode, struct file *filp)
+{
+       struct srom_dev *srom = filp->private_data;
+       char dummy;
+
+       /* Make sure we've flushed anything written to the ROM. */
+       mutex_lock(&srom->lock);
+       if (srom->hv_devhdl >= 0)
+               _srom_write(srom->hv_devhdl, &dummy, SROM_FLUSH_OFF, 1);
+       mutex_unlock(&srom->lock);
+
+       filp->private_data = NULL;
+
+       return 0;
+}
+
+
+/**
+ * srom_read() - Read data from the device.
+ * @filp: File for this specific open of the device.
+ * @buf: User's data buffer.
+ * @count: Number of bytes requested.
+ * @f_pos: File position.
+ *
+ * Returns number of bytes read, or an error code.
+ */
+static ssize_t srom_read(struct file *filp, char __user *buf,
+                        size_t count, loff_t *f_pos)
+{
+       int retval = 0;
+       void *kernbuf;
+       struct srom_dev *srom = filp->private_data;
+
+       kernbuf = kmalloc(SROM_CHUNK_SIZE, GFP_KERNEL);
+       if (!kernbuf)
+               return -ENOMEM;
+
+       if (mutex_lock_interruptible(&srom->lock)) {
+               retval = -ERESTARTSYS;
+               kfree(kernbuf);
+               return retval;
+       }
+
+       while (count) {
+               int hv_retval;
+               int bytes_this_pass = min(count, SROM_CHUNK_SIZE);
+
+               hv_retval = _srom_read(srom->hv_devhdl, kernbuf,
+                                      *f_pos, bytes_this_pass);
+               if (hv_retval > 0) {
+                       if (copy_to_user(buf, kernbuf, hv_retval) != 0) {
+                               retval = -EFAULT;
+                               break;
+                       }
+               } else if (hv_retval <= 0) {
+                       if (retval == 0)
+                               retval = hv_retval;
+                       break;
+               }
+
+               retval += hv_retval;
+               *f_pos += hv_retval;
+               buf += hv_retval;
+               count -= hv_retval;
+       }
+
+       mutex_unlock(&srom->lock);
+       kfree(kernbuf);
+
+       return retval;
+}
+
+/**
+ * srom_write() - Write data to the device.
+ * @filp: File for this specific open of the device.
+ * @buf: User's data buffer.
+ * @count: Number of bytes requested.
+ * @f_pos: File position.
+ *
+ * Returns number of bytes written, or an error code.
+ */
+static ssize_t srom_write(struct file *filp, const char __user *buf,
+                         size_t count, loff_t *f_pos)
+{
+       int retval = 0;
+       void *kernbuf;
+       struct srom_dev *srom = filp->private_data;
+
+       kernbuf = kmalloc(SROM_CHUNK_SIZE, GFP_KERNEL);
+       if (!kernbuf)
+               return -ENOMEM;
+
+       if (mutex_lock_interruptible(&srom->lock)) {
+               retval = -ERESTARTSYS;
+               kfree(kernbuf);
+               return retval;
+       }
+
+       while (count) {
+               int hv_retval;
+               int bytes_this_pass = min(count, SROM_CHUNK_SIZE);
+
+               if (copy_from_user(kernbuf, buf, bytes_this_pass) != 0) {
+                       retval = -EFAULT;
+                       break;
+               }
+
+               hv_retval = _srom_write(srom->hv_devhdl, kernbuf,
+                                       *f_pos, bytes_this_pass);
+               if (hv_retval <= 0) {
+                       if (retval == 0)
+                               retval = hv_retval;
+                       break;
+               }
+
+               retval += hv_retval;
+               *f_pos += hv_retval;
+               buf += hv_retval;
+               count -= hv_retval;
+       }
+
+       mutex_unlock(&srom->lock);
+       kfree(kernbuf);
+
+       return retval;
+}
+
+/* Provide our own implementation so we can use srom->total_size. */
+loff_t srom_llseek(struct file *filp, loff_t offset, int origin)
+{
+       struct srom_dev *srom = filp->private_data;
+
+       if (mutex_lock_interruptible(&srom->lock))
+               return -ERESTARTSYS;
+
+       switch (origin) {
+       case SEEK_END:
+               offset += srom->total_size;
+               break;
+       case SEEK_CUR:
+               offset += filp->f_pos;
+               break;
+       }
+
+       if (offset < 0 || offset > srom->total_size) {
+               offset = -EINVAL;
+       } else {
+               filp->f_pos = offset;
+               filp->f_version = 0;
+       }
+
+       mutex_unlock(&srom->lock);
+
+       return offset;
+}
+
+static ssize_t total_show(struct device *dev,
+                         struct device_attribute *attr, char *buf)
+{
+       struct srom_dev *srom = dev_get_drvdata(dev);
+       return sprintf(buf, "%u\n", srom->total_size);
+}
+
+static ssize_t sector_show(struct device *dev,
+                          struct device_attribute *attr, char *buf)
+{
+       struct srom_dev *srom = dev_get_drvdata(dev);
+       return sprintf(buf, "%u\n", srom->sector_size);
+}
+
+static ssize_t page_show(struct device *dev,
+                        struct device_attribute *attr, char *buf)
+{
+       struct srom_dev *srom = dev_get_drvdata(dev);
+       return sprintf(buf, "%u\n", srom->page_size);
+}
+
+static struct device_attribute srom_dev_attrs[] = {
+       __ATTR(total_size, S_IRUGO, total_show, NULL),
+       __ATTR(sector_size, S_IRUGO, sector_show, NULL),
+       __ATTR(page_size, S_IRUGO, page_show, NULL),
+       __ATTR_NULL
+};
+
+static char *srom_devnode(struct device *dev, mode_t *mode)
+{
+       *mode = S_IRUGO | S_IWUSR;
+       return kasprintf(GFP_KERNEL, "srom/%s", dev_name(dev));
+}
+
+/*
+ * The fops
+ */
+static const struct file_operations srom_fops = {
+       .owner =     THIS_MODULE,
+       .llseek =    srom_llseek,
+       .read =      srom_read,
+       .write =     srom_write,
+       .open =      srom_open,
+       .release =   srom_release,
+};
+
+/**
+ * srom_setup_minor() - Initialize per-minor information.
+ * @srom: Per-device SROM state.
+ * @index: Device to set up.
+ */
+static int srom_setup_minor(struct srom_dev *srom, int index)
+{
+       struct device *dev;
+       int devhdl = srom->hv_devhdl;
+
+       mutex_init(&srom->lock);
+
+       if (_srom_read(devhdl, &srom->total_size,
+                      SROM_TOTAL_SIZE_OFF, sizeof(srom->total_size)) < 0)
+               return -EIO;
+       if (_srom_read(devhdl, &srom->sector_size,
+                      SROM_SECTOR_SIZE_OFF, sizeof(srom->sector_size)) < 0)
+               return -EIO;
+       if (_srom_read(devhdl, &srom->page_size,
+                      SROM_PAGE_SIZE_OFF, sizeof(srom->page_size)) < 0)
+               return -EIO;
+
+       dev = device_create(srom_class, &platform_bus,
+                           MKDEV(srom_major, index), srom, "%d", index);
+       return IS_ERR(dev) ? PTR_ERR(dev) : 0;
+}
+
+/** srom_init() - Initialize the driver's module. */
+static int srom_init(void)
+{
+       int result, i;
+       dev_t dev = MKDEV(srom_major, 0);
+
+       /*
+        * Start with a plausible number of partitions; the krealloc() call
+        * below will yield about log(srom_devs) additional allocations.
+        */
+       srom_devices = kzalloc(4 * sizeof(struct srom_dev), GFP_KERNEL);
+
+       /* Discover the number of srom partitions. */
+       for (i = 0; ; i++) {
+               int devhdl;
+               char buf[20];
+               struct srom_dev *new_srom_devices =
+                       krealloc(srom_devices, (i+1) * sizeof(struct srom_dev),
+                                GFP_KERNEL | __GFP_ZERO);
+               if (!new_srom_devices) {
+                       result = -ENOMEM;
+                       goto fail_mem;
+               }
+               srom_devices = new_srom_devices;
+               sprintf(buf, "srom/0/%d", i);
+               devhdl = hv_dev_open((HV_VirtAddr)buf, 0);
+               if (devhdl < 0) {
+                       if (devhdl != HV_ENODEV)
+                               pr_notice("srom/%d: hv_dev_open failed: %d.\n",
+                                         i, devhdl);
+                       break;
+               }
+               srom_devices[i].hv_devhdl = devhdl;
+       }
+       srom_devs = i;
+
+       /* Bail out early if we have no partitions at all. */
+       if (srom_devs == 0) {
+               result = -ENODEV;
+               goto fail_mem;
+       }
+
+       /* Register our major, and accept a dynamic number. */
+       if (srom_major)
+               result = register_chrdev_region(dev, srom_devs, "srom");
+       else {
+               result = alloc_chrdev_region(&dev, 0, srom_devs, "srom");
+               srom_major = MAJOR(dev);
+       }
+       if (result < 0)
+               goto fail_mem;
+
+       /* Register a character device. */
+       cdev_init(&srom_cdev, &srom_fops);
+       srom_cdev.owner = THIS_MODULE;
+       srom_cdev.ops = &srom_fops;
+       result = cdev_add(&srom_cdev, dev, srom_devs);
+       if (result < 0)
+               goto fail_chrdev;
+
+       /* Create a sysfs class. */
+       srom_class = class_create(THIS_MODULE, "srom");
+       if (IS_ERR(srom_class)) {
+               result = PTR_ERR(srom_class);
+               goto fail_cdev;
+       }
+       srom_class->dev_attrs = srom_dev_attrs;
+       srom_class->devnode = srom_devnode;
+
+       /* Do per-partition initialization */
+       for (i = 0; i < srom_devs; i++) {
+               result = srom_setup_minor(srom_devices + i, i);
+               if (result < 0)
+                       goto fail_class;
+       }
+
+       return 0;
+
+fail_class:
+       for (i = 0; i < srom_devs; i++)
+               device_destroy(srom_class, MKDEV(srom_major, i));
+       class_destroy(srom_class);
+fail_cdev:
+       cdev_del(&srom_cdev);
+fail_chrdev:
+       unregister_chrdev_region(dev, srom_devs);
+fail_mem:
+       kfree(srom_devices);
+       return result;
+}
+
+/** srom_cleanup() - Clean up the driver's module. */
+static void srom_cleanup(void)
+{
+       int i;
+       for (i = 0; i < srom_devs; i++)
+               device_destroy(srom_class, MKDEV(srom_major, i));
+       class_destroy(srom_class);
+       cdev_del(&srom_cdev);
+       unregister_chrdev_region(MKDEV(srom_major, 0), srom_devs);
+       kfree(srom_devices);
+}
+
+module_init(srom_init);
+module_exit(srom_cleanup);
index 7fc2f10..3f4051a 100644 (file)
@@ -80,7 +80,7 @@ enum tis_defaults {
 static LIST_HEAD(tis_chips);
 static DEFINE_SPINLOCK(tis_lock);
 
-#ifdef CONFIG_PNP
+#if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
 static int is_itpm(struct pnp_dev *dev)
 {
        struct acpi_device *acpi = pnp_acpi_device(dev);
@@ -93,6 +93,11 @@ static int is_itpm(struct pnp_dev *dev)
 
        return 0;
 }
+#else
+static inline int is_itpm(struct pnp_dev *dev)
+{
+       return 0;
+}
 #endif
 
 static int check_locality(struct tpm_chip *chip, int l)
index 3ee1fdb..e55814b 100644 (file)
@@ -57,6 +57,7 @@ void proc_fork_connector(struct task_struct *task)
        struct proc_event *ev;
        __u8 buffer[CN_PROC_MSG_SIZE];
        struct timespec ts;
+       struct task_struct *parent;
 
        if (atomic_read(&proc_event_num_listeners) < 1)
                return;
@@ -67,8 +68,11 @@ void proc_fork_connector(struct task_struct *task)
        ktime_get_ts(&ts); /* get high res monotonic timestamp */
        put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
        ev->what = PROC_EVENT_FORK;
-       ev->event_data.fork.parent_pid = task->real_parent->pid;
-       ev->event_data.fork.parent_tgid = task->real_parent->tgid;
+       rcu_read_lock();
+       parent = rcu_dereference(task->real_parent);
+       ev->event_data.fork.parent_pid = parent->pid;
+       ev->event_data.fork.parent_tgid = parent->tgid;
+       rcu_read_unlock();
        ev->event_data.fork.child_pid = task->pid;
        ev->event_data.fork.child_tgid = task->tgid;
 
index bf50924..d4c5423 100644 (file)
@@ -25,9 +25,19 @@ DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
 
 DEFINE_MUTEX(cpuidle_lock);
 LIST_HEAD(cpuidle_detected_devices);
-static void (*pm_idle_old)(void);
 
 static int enabled_devices;
+static int off __read_mostly;
+static int initialized __read_mostly;
+
+int cpuidle_disabled(void)
+{
+       return off;
+}
+void disable_cpuidle(void)
+{
+       off = 1;
+}
 
 #if defined(CONFIG_ARCH_HAS_CPU_IDLE_WAIT)
 static void cpuidle_kick_cpus(void)
@@ -46,25 +56,23 @@ static int __cpuidle_register_device(struct cpuidle_device *dev);
  * cpuidle_idle_call - the main idle loop
  *
  * NOTE: no locks or semaphores should be used here
+ * return non-zero on failure
  */
-static void cpuidle_idle_call(void)
+int cpuidle_idle_call(void)
 {
        struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
        struct cpuidle_state *target_state;
        int next_state;
 
+       if (off)
+               return -ENODEV;
+
+       if (!initialized)
+               return -ENODEV;
+
        /* check if the device is ready */
-       if (!dev || !dev->enabled) {
-               if (pm_idle_old)
-                       pm_idle_old();
-               else
-#if defined(CONFIG_ARCH_HAS_DEFAULT_IDLE)
-                       default_idle();
-#else
-                       local_irq_enable();
-#endif
-               return;
-       }
+       if (!dev || !dev->enabled)
+               return -EBUSY;
 
 #if 0
        /* shows regressions, re-enable for 2.6.29 */
@@ -89,7 +97,7 @@ static void cpuidle_idle_call(void)
        next_state = cpuidle_curr_governor->select(dev);
        if (need_resched()) {
                local_irq_enable();
-               return;
+               return 0;
        }
 
        target_state = &dev->states[next_state];
@@ -114,6 +122,8 @@ static void cpuidle_idle_call(void)
        /* give the governor an opportunity to reflect on the outcome */
        if (cpuidle_curr_governor->reflect)
                cpuidle_curr_governor->reflect(dev);
+
+       return 0;
 }
 
 /**
@@ -121,10 +131,10 @@ static void cpuidle_idle_call(void)
  */
 void cpuidle_install_idle_handler(void)
 {
-       if (enabled_devices && (pm_idle != cpuidle_idle_call)) {
+       if (enabled_devices) {
                /* Make sure all changes finished before we switch to new idle */
                smp_wmb();
-               pm_idle = cpuidle_idle_call;
+               initialized = 1;
        }
 }
 
@@ -133,8 +143,8 @@ void cpuidle_install_idle_handler(void)
  */
 void cpuidle_uninstall_idle_handler(void)
 {
-       if (enabled_devices && pm_idle_old && (pm_idle != pm_idle_old)) {
-               pm_idle = pm_idle_old;
+       if (enabled_devices) {
+               initialized = 0;
                cpuidle_kick_cpus();
        }
 }
@@ -427,7 +437,8 @@ static int __init cpuidle_init(void)
 {
        int ret;
 
-       pm_idle_old = pm_idle;
+       if (cpuidle_disabled())
+               return -ENODEV;
 
        ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);
        if (ret)
@@ -438,4 +449,5 @@ static int __init cpuidle_init(void)
        return 0;
 }
 
+module_param(off, int, 0444);
 core_initcall(cpuidle_init);
index 33e50d5..38c3fd8 100644 (file)
@@ -13,6 +13,7 @@ extern struct list_head cpuidle_governors;
 extern struct list_head cpuidle_detected_devices;
 extern struct mutex cpuidle_lock;
 extern spinlock_t cpuidle_driver_lock;
+extern int cpuidle_disabled(void);
 
 /* idle loop */
 extern void cpuidle_install_idle_handler(void);
index fd1601e..3f7e3ce 100644 (file)
@@ -26,6 +26,9 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
        if (!drv)
                return -EINVAL;
 
+       if (cpuidle_disabled())
+               return -ENODEV;
+
        spin_lock(&cpuidle_driver_lock);
        if (cpuidle_curr_driver) {
                spin_unlock(&cpuidle_driver_lock);
index 724c164..ea2f8e7 100644 (file)
@@ -81,6 +81,9 @@ int cpuidle_register_governor(struct cpuidle_governor *gov)
        if (!gov || !gov->select)
                return -EINVAL;
 
+       if (cpuidle_disabled())
+               return -ENODEV;
+
        mutex_lock(&cpuidle_lock);
        if (__cpuidle_find_governor(gov->name) == NULL) {
                ret = 0;
index 2e5b204..d0183dd 100644 (file)
@@ -1,6 +1,6 @@
 /* n2_core.c: Niagara2 Stream Processing Unit (SPU) crypto support.
  *
- * Copyright (C) 2010 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 2010, 2011 David S. Miller <davem@davemloft.net>
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -31,8 +31,8 @@
 #include "n2_core.h"
 
 #define DRV_MODULE_NAME                "n2_crypto"
-#define DRV_MODULE_VERSION     "0.1"
-#define DRV_MODULE_RELDATE     "April 29, 2010"
+#define DRV_MODULE_VERSION     "0.2"
+#define DRV_MODULE_RELDATE     "July 28, 2011"
 
 static char version[] __devinitdata =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -1823,22 +1823,17 @@ static int spu_mdesc_scan(struct mdesc_handle *mdesc, struct platform_device *de
 static int __devinit get_irq_props(struct mdesc_handle *mdesc, u64 node,
                                   struct spu_mdesc_info *ip)
 {
-       const u64 *intr, *ino;
-       int intr_len, ino_len;
+       const u64 *ino;
+       int ino_len;
        int i;
 
-       intr = mdesc_get_property(mdesc, node, "intr", &intr_len);
-       if (!intr)
-               return -ENODEV;
-
        ino = mdesc_get_property(mdesc, node, "ino", &ino_len);
-       if (!ino)
+       if (!ino) {
+               printk("NO 'ino'\n");
                return -ENODEV;
+       }
 
-       if (intr_len != ino_len)
-               return -EINVAL;
-
-       ip->num_intrs = intr_len / sizeof(u64);
+       ip->num_intrs = ino_len / sizeof(u64);
        ip->ino_table = kzalloc((sizeof(struct ino_blob) *
                                 ip->num_intrs),
                                GFP_KERNEL);
@@ -1847,7 +1842,7 @@ static int __devinit get_irq_props(struct mdesc_handle *mdesc, u64 node,
 
        for (i = 0; i < ip->num_intrs; i++) {
                struct ino_blob *b = &ip->ino_table[i];
-               b->intr = intr[i];
+               b->intr = i + 1;
                b->ino = ino[i];
        }
 
@@ -2204,6 +2199,10 @@ static struct of_device_id n2_crypto_match[] = {
                .name = "n2cp",
                .compatible = "SUNW,vf-cwq",
        },
+       {
+               .name = "n2cp",
+               .compatible = "SUNW,kt-cwq",
+       },
        {},
 };
 
@@ -2228,6 +2227,10 @@ static struct of_device_id n2_mau_match[] = {
                .name = "ncp",
                .compatible = "SUNW,vf-mau",
        },
+       {
+               .name = "ncp",
+               .compatible = "SUNW,kt-mau",
+       },
        {},
 };
 
index a4af858..734ed02 100644 (file)
@@ -9,6 +9,5 @@ TODO for slave dma
        - mxs-dma.c
        - dw_dmac
        - intel_mid_dma
-       - ste_dma40
 4. Check other subsystems for dma drivers and merge/move to dmaengine
 5. Remove dma_slave_config's dma direction.
index e6d7228..be21e3f 100644 (file)
@@ -80,6 +80,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
 #include <linux/dmaengine.h>
 #include <linux/amba/bus.h>
@@ -156,14 +157,10 @@ struct pl08x_driver_data {
 #define PL08X_BOUNDARY_SHIFT           (10)    /* 1KB 0x400 */
 #define PL08X_BOUNDARY_SIZE            (1 << PL08X_BOUNDARY_SHIFT)
 
-/* Minimum period between work queue runs */
-#define PL08X_WQ_PERIODMIN     20
-
 /* Size (bytes) of each LLI buffer allocated for one transfer */
 # define PL08X_LLI_TSFR_SIZE   0x2000
 
 /* Maximum times we call dma_pool_alloc on this pool without freeing */
-#define PL08X_MAX_ALLOCS       0x40
 #define MAX_NUM_TSFR_LLIS      (PL08X_LLI_TSFR_SIZE/sizeof(struct pl08x_lli))
 #define PL08X_ALIGN            8
 
@@ -495,10 +492,10 @@ static inline u32 pl08x_cctl_bits(u32 cctl, u8 srcwidth, u8 dstwidth,
 
 struct pl08x_lli_build_data {
        struct pl08x_txd *txd;
-       struct pl08x_driver_data *pl08x;
        struct pl08x_bus_data srcbus;
        struct pl08x_bus_data dstbus;
        size_t remainder;
+       u32 lli_bus;
 };
 
 /*
@@ -551,8 +548,7 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
        llis_va[num_llis].src = bd->srcbus.addr;
        llis_va[num_llis].dst = bd->dstbus.addr;
        llis_va[num_llis].lli = llis_bus + (num_llis + 1) * sizeof(struct pl08x_lli);
-       if (bd->pl08x->lli_buses & PL08X_AHB2)
-               llis_va[num_llis].lli |= PL080_LLI_LM_AHB2;
+       llis_va[num_llis].lli |= bd->lli_bus;
 
        if (cctl & PL080_CONTROL_SRC_INCR)
                bd->srcbus.addr += len;
@@ -605,9 +601,9 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
        cctl = txd->cctl;
 
        bd.txd = txd;
-       bd.pl08x = pl08x;
        bd.srcbus.addr = txd->src_addr;
        bd.dstbus.addr = txd->dst_addr;
+       bd.lli_bus = (pl08x->lli_buses & PL08X_AHB2) ? PL080_LLI_LM_AHB2 : 0;
 
        /* Find maximum width of the source bus */
        bd.srcbus.maxwidth =
@@ -622,25 +618,15 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
        /* Set up the bus widths to the maximum */
        bd.srcbus.buswidth = bd.srcbus.maxwidth;
        bd.dstbus.buswidth = bd.dstbus.maxwidth;
-       dev_vdbg(&pl08x->adev->dev,
-                "%s source bus is %d bytes wide, dest bus is %d bytes wide\n",
-                __func__, bd.srcbus.buswidth, bd.dstbus.buswidth);
-
 
        /*
         * Bytes transferred == tsize * MIN(buswidths), not max(buswidths)
         */
        max_bytes_per_lli = min(bd.srcbus.buswidth, bd.dstbus.buswidth) *
                PL080_CONTROL_TRANSFER_SIZE_MASK;
-       dev_vdbg(&pl08x->adev->dev,
-                "%s max bytes per lli = %zu\n",
-                __func__, max_bytes_per_lli);
 
        /* We need to count this down to zero */
        bd.remainder = txd->len;
-       dev_vdbg(&pl08x->adev->dev,
-                "%s remainder = %zu\n",
-                __func__, bd.remainder);
 
        /*
         * Choose bus to align to
@@ -649,6 +635,16 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
         */
        pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl);
 
+       dev_vdbg(&pl08x->adev->dev, "src=0x%08x%s/%u dst=0x%08x%s/%u len=%zu llimax=%zu\n",
+                bd.srcbus.addr, cctl & PL080_CONTROL_SRC_INCR ? "+" : "",
+                bd.srcbus.buswidth,
+                bd.dstbus.addr, cctl & PL080_CONTROL_DST_INCR ? "+" : "",
+                bd.dstbus.buswidth,
+                bd.remainder, max_bytes_per_lli);
+       dev_vdbg(&pl08x->adev->dev, "mbus=%s sbus=%s\n",
+                mbus == &bd.srcbus ? "src" : "dst",
+                sbus == &bd.srcbus ? "src" : "dst");
+
        if (txd->len < mbus->buswidth) {
                /* Less than a bus width available - send as single bytes */
                while (bd.remainder) {
@@ -840,15 +836,14 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
        {
                int i;
 
+               dev_vdbg(&pl08x->adev->dev,
+                        "%-3s %-9s  %-10s %-10s %-10s %s\n",
+                        "lli", "", "csrc", "cdst", "clli", "cctl");
                for (i = 0; i < num_llis; i++) {
                        dev_vdbg(&pl08x->adev->dev,
-                                "lli %d @%p: csrc=0x%08x, cdst=0x%08x, cctl=0x%08x, clli=0x%08x\n",
-                                i,
-                                &llis_va[i],
-                                llis_va[i].src,
-                                llis_va[i].dst,
-                                llis_va[i].cctl,
-                                llis_va[i].lli
+                                "%3d @%p: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+                                i, &llis_va[i], llis_va[i].src,
+                                llis_va[i].dst, llis_va[i].lli, llis_va[i].cctl
                                );
                }
        }
@@ -1054,64 +1049,105 @@ pl08x_dma_tx_status(struct dma_chan *chan,
 
 /* PrimeCell DMA extension */
 struct burst_table {
-       int burstwords;
+       u32 burstwords;
        u32 reg;
 };
 
 static const struct burst_table burst_sizes[] = {
        {
                .burstwords = 256,
-               .reg = (PL080_BSIZE_256 << PL080_CONTROL_SB_SIZE_SHIFT) |
-                       (PL080_BSIZE_256 << PL080_CONTROL_DB_SIZE_SHIFT),
+               .reg = PL080_BSIZE_256,
        },
        {
                .burstwords = 128,
-               .reg = (PL080_BSIZE_128 << PL080_CONTROL_SB_SIZE_SHIFT) |
-                       (PL080_BSIZE_128 << PL080_CONTROL_DB_SIZE_SHIFT),
+               .reg = PL080_BSIZE_128,
        },
        {
                .burstwords = 64,
-               .reg = (PL080_BSIZE_64 << PL080_CONTROL_SB_SIZE_SHIFT) |
-                       (PL080_BSIZE_64 << PL080_CONTROL_DB_SIZE_SHIFT),
+               .reg = PL080_BSIZE_64,
        },
        {
                .burstwords = 32,
-               .reg = (PL080_BSIZE_32 << PL080_CONTROL_SB_SIZE_SHIFT) |
-                       (PL080_BSIZE_32 << PL080_CONTROL_DB_SIZE_SHIFT),
+               .reg = PL080_BSIZE_32,
        },
        {
                .burstwords = 16,
-               .reg = (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT) |
-                       (PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT),
+               .reg = PL080_BSIZE_16,
        },
        {
                .burstwords = 8,
-               .reg = (PL080_BSIZE_8 << PL080_CONTROL_SB_SIZE_SHIFT) |
-                       (PL080_BSIZE_8 << PL080_CONTROL_DB_SIZE_SHIFT),
+               .reg = PL080_BSIZE_8,
        },
        {
                .burstwords = 4,
-               .reg = (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT) |
-                       (PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT),
+               .reg = PL080_BSIZE_4,
        },
        {
-               .burstwords = 1,
-               .reg = (PL080_BSIZE_1 << PL080_CONTROL_SB_SIZE_SHIFT) |
-                       (PL080_BSIZE_1 << PL080_CONTROL_DB_SIZE_SHIFT),
+               .burstwords = 0,
+               .reg = PL080_BSIZE_1,
        },
 };
 
+/*
+ * Given the source and destination available bus masks, select which
+ * will be routed to each port.  We try to have source and destination
+ * on separate ports, but always respect the allowable settings.
+ */
+static u32 pl08x_select_bus(u8 src, u8 dst)
+{
+       u32 cctl = 0;
+
+       if (!(dst & PL08X_AHB1) || ((dst & PL08X_AHB2) && (src & PL08X_AHB1)))
+               cctl |= PL080_CONTROL_DST_AHB2;
+       if (!(src & PL08X_AHB1) || ((src & PL08X_AHB2) && !(dst & PL08X_AHB2)))
+               cctl |= PL080_CONTROL_SRC_AHB2;
+
+       return cctl;
+}
+
+static u32 pl08x_cctl(u32 cctl)
+{
+       cctl &= ~(PL080_CONTROL_SRC_AHB2 | PL080_CONTROL_DST_AHB2 |
+                 PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR |
+                 PL080_CONTROL_PROT_MASK);
+
+       /* Access the cell in privileged mode, non-bufferable, non-cacheable */
+       return cctl | PL080_CONTROL_PROT_SYS;
+}
+
+static u32 pl08x_width(enum dma_slave_buswidth width)
+{
+       switch (width) {
+       case DMA_SLAVE_BUSWIDTH_1_BYTE:
+               return PL080_WIDTH_8BIT;
+       case DMA_SLAVE_BUSWIDTH_2_BYTES:
+               return PL080_WIDTH_16BIT;
+       case DMA_SLAVE_BUSWIDTH_4_BYTES:
+               return PL080_WIDTH_32BIT;
+       default:
+               return ~0;
+       }
+}
+
+static u32 pl08x_burst(u32 maxburst)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(burst_sizes); i++)
+               if (burst_sizes[i].burstwords <= maxburst)
+                       break;
+
+       return burst_sizes[i].reg;
+}
+
 static int dma_set_runtime_config(struct dma_chan *chan,
                                  struct dma_slave_config *config)
 {
        struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
        struct pl08x_driver_data *pl08x = plchan->host;
-       struct pl08x_channel_data *cd = plchan->cd;
        enum dma_slave_buswidth addr_width;
-       dma_addr_t addr;
-       u32 maxburst;
+       u32 width, burst, maxburst;
        u32 cctl = 0;
-       int i;
 
        if (!plchan->slave)
                return -EINVAL;
@@ -1119,11 +1155,9 @@ static int dma_set_runtime_config(struct dma_chan *chan,
        /* Transfer direction */
        plchan->runtime_direction = config->direction;
        if (config->direction == DMA_TO_DEVICE) {
-               addr = config->dst_addr;
                addr_width = config->dst_addr_width;
                maxburst = config->dst_maxburst;
        } else if (config->direction == DMA_FROM_DEVICE) {
-               addr = config->src_addr;
                addr_width = config->src_addr_width;
                maxburst = config->src_maxburst;
        } else {
@@ -1132,46 +1166,40 @@ static int dma_set_runtime_config(struct dma_chan *chan,
                return -EINVAL;
        }
 
-       switch (addr_width) {
-       case DMA_SLAVE_BUSWIDTH_1_BYTE:
-               cctl |= (PL080_WIDTH_8BIT << PL080_CONTROL_SWIDTH_SHIFT) |
-                       (PL080_WIDTH_8BIT << PL080_CONTROL_DWIDTH_SHIFT);
-               break;
-       case DMA_SLAVE_BUSWIDTH_2_BYTES:
-               cctl |= (PL080_WIDTH_16BIT << PL080_CONTROL_SWIDTH_SHIFT) |
-                       (PL080_WIDTH_16BIT << PL080_CONTROL_DWIDTH_SHIFT);
-               break;
-       case DMA_SLAVE_BUSWIDTH_4_BYTES:
-               cctl |= (PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT) |
-                       (PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT);
-               break;
-       default:
+       width = pl08x_width(addr_width);
+       if (width == ~0) {
                dev_err(&pl08x->adev->dev,
                        "bad runtime_config: alien address width\n");
                return -EINVAL;
        }
 
+       cctl |= width << PL080_CONTROL_SWIDTH_SHIFT;
+       cctl |= width << PL080_CONTROL_DWIDTH_SHIFT;
+
        /*
-        * Now decide on a maxburst:
         * If this channel will only request single transfers, set this
         * down to ONE element.  Also select one element if no maxburst
         * is specified.
         */
-       if (plchan->cd->single || maxburst == 0) {
-               cctl |= (PL080_BSIZE_1 << PL080_CONTROL_SB_SIZE_SHIFT) |
-                       (PL080_BSIZE_1 << PL080_CONTROL_DB_SIZE_SHIFT);
+       if (plchan->cd->single)
+               maxburst = 1;
+
+       burst = pl08x_burst(maxburst);
+       cctl |= burst << PL080_CONTROL_SB_SIZE_SHIFT;
+       cctl |= burst << PL080_CONTROL_DB_SIZE_SHIFT;
+
+       if (plchan->runtime_direction == DMA_FROM_DEVICE) {
+               plchan->src_addr = config->src_addr;
+               plchan->src_cctl = pl08x_cctl(cctl) | PL080_CONTROL_DST_INCR |
+                       pl08x_select_bus(plchan->cd->periph_buses,
+                                        pl08x->mem_buses);
        } else {
-               for (i = 0; i < ARRAY_SIZE(burst_sizes); i++)
-                       if (burst_sizes[i].burstwords <= maxburst)
-                               break;
-               cctl |= burst_sizes[i].reg;
+               plchan->dst_addr = config->dst_addr;
+               plchan->dst_cctl = pl08x_cctl(cctl) | PL080_CONTROL_SRC_INCR |
+                       pl08x_select_bus(pl08x->mem_buses,
+                                        plchan->cd->periph_buses);
        }
 
-       plchan->runtime_addr = addr;
-
-       /* Modify the default channel data to fit PrimeCell request */
-       cd->cctl = cctl;
-
        dev_dbg(&pl08x->adev->dev,
                "configured channel %s (%s) for %s, data width %d, "
                "maxburst %d words, LE, CCTL=0x%08x\n",
@@ -1270,23 +1298,6 @@ static int pl08x_prep_channel_resources(struct pl08x_dma_chan *plchan,
        return 0;
 }
 
-/*
- * Given the source and destination available bus masks, select which
- * will be routed to each port.  We try to have source and destination
- * on separate ports, but always respect the allowable settings.
- */
-static u32 pl08x_select_bus(struct pl08x_driver_data *pl08x, u8 src, u8 dst)
-{
-       u32 cctl = 0;
-
-       if (!(dst & PL08X_AHB1) || ((dst & PL08X_AHB2) && (src & PL08X_AHB1)))
-               cctl |= PL080_CONTROL_DST_AHB2;
-       if (!(src & PL08X_AHB1) || ((src & PL08X_AHB2) && !(dst & PL08X_AHB2)))
-               cctl |= PL080_CONTROL_SRC_AHB2;
-
-       return cctl;
-}
-
 static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan,
        unsigned long flags)
 {
@@ -1338,8 +1349,8 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
        txd->cctl |= PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR;
 
        if (pl08x->vd->dualmaster)
-               txd->cctl |= pl08x_select_bus(pl08x,
-                                       pl08x->mem_buses, pl08x->mem_buses);
+               txd->cctl |= pl08x_select_bus(pl08x->mem_buses,
+                                             pl08x->mem_buses);
 
        ret = pl08x_prep_channel_resources(plchan, txd);
        if (ret)
@@ -1356,7 +1367,6 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
        struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
        struct pl08x_driver_data *pl08x = plchan->host;
        struct pl08x_txd *txd;
-       u8 src_buses, dst_buses;
        int ret;
 
        /*
@@ -1390,42 +1400,22 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
        txd->direction = direction;
        txd->len = sgl->length;
 
-       txd->cctl = plchan->cd->cctl &
-                       ~(PL080_CONTROL_SRC_AHB2 | PL080_CONTROL_DST_AHB2 |
-                         PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR |
-                         PL080_CONTROL_PROT_MASK);
-
-       /* Access the cell in privileged mode, non-bufferable, non-cacheable */
-       txd->cctl |= PL080_CONTROL_PROT_SYS;
-
        if (direction == DMA_TO_DEVICE) {
                txd->ccfg |= PL080_FLOW_MEM2PER << PL080_CONFIG_FLOW_CONTROL_SHIFT;
-               txd->cctl |= PL080_CONTROL_SRC_INCR;
+               txd->cctl = plchan->dst_cctl;
                txd->src_addr = sgl->dma_address;
-               if (plchan->runtime_addr)
-                       txd->dst_addr = plchan->runtime_addr;
-               else
-                       txd->dst_addr = plchan->cd->addr;
-               src_buses = pl08x->mem_buses;
-               dst_buses = plchan->cd->periph_buses;
+               txd->dst_addr = plchan->dst_addr;
        } else if (direction == DMA_FROM_DEVICE) {
                txd->ccfg |= PL080_FLOW_PER2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
-               txd->cctl |= PL080_CONTROL_DST_INCR;
-               if (plchan->runtime_addr)
-                       txd->src_addr = plchan->runtime_addr;
-               else
-                       txd->src_addr = plchan->cd->addr;
+               txd->cctl = plchan->src_cctl;
+               txd->src_addr = plchan->src_addr;
                txd->dst_addr = sgl->dma_address;
-               src_buses = plchan->cd->periph_buses;
-               dst_buses = pl08x->mem_buses;
        } else {
                dev_err(&pl08x->adev->dev,
                        "%s direction unsupported\n", __func__);
                return NULL;
        }
 
-       txd->cctl |= pl08x_select_bus(pl08x, src_buses, dst_buses);
-
        ret = pl08x_prep_channel_resources(plchan, txd);
        if (ret)
                return NULL;
@@ -1676,6 +1666,20 @@ static irqreturn_t pl08x_irq(int irq, void *dev)
        return mask ? IRQ_HANDLED : IRQ_NONE;
 }
 
+static void pl08x_dma_slave_init(struct pl08x_dma_chan *chan)
+{
+       u32 cctl = pl08x_cctl(chan->cd->cctl);
+
+       chan->slave = true;
+       chan->name = chan->cd->bus_id;
+       chan->src_addr = chan->cd->addr;
+       chan->dst_addr = chan->cd->addr;
+       chan->src_cctl = cctl | PL080_CONTROL_DST_INCR |
+               pl08x_select_bus(chan->cd->periph_buses, chan->host->mem_buses);
+       chan->dst_cctl = cctl | PL080_CONTROL_SRC_INCR |
+               pl08x_select_bus(chan->host->mem_buses, chan->cd->periph_buses);
+}
+
 /*
  * Initialise the DMAC memcpy/slave channels.
  * Make a local wrapper to hold required data
@@ -1707,9 +1711,8 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
                chan->state = PL08X_CHAN_IDLE;
 
                if (slave) {
-                       chan->slave = true;
-                       chan->name = pl08x->pd->slave_channels[i].bus_id;
                        chan->cd = &pl08x->pd->slave_channels[i];
+                       pl08x_dma_slave_init(chan);
                } else {
                        chan->cd = &pl08x->pd->memcpy_channel;
                        chan->name = kasprintf(GFP_KERNEL, "memcpy%d", i);
index 36144f8..6a483ea 100644 (file)
@@ -1216,7 +1216,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
        atdma->dma_common.cap_mask = pdata->cap_mask;
        atdma->all_chan_mask = (1 << pdata->nr_channels) - 1;
 
-       size = io->end - io->start + 1;
+       size = resource_size(io);
        if (!request_mem_region(io->start, size, pdev->dev.driver->name)) {
                err = -EBUSY;
                goto err_kfree;
@@ -1362,7 +1362,7 @@ static int __exit at_dma_remove(struct platform_device *pdev)
        atdma->regs = NULL;
 
        io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(io->start, io->end - io->start + 1);
+       release_mem_region(io->start, resource_size(io));
 
        kfree(atdma);
 
index a92d95e..4234f41 100644 (file)
@@ -41,6 +41,8 @@ struct coh901318_desc {
        struct coh901318_lli *lli;
        enum dma_data_direction dir;
        unsigned long flags;
+       u32 head_config;
+       u32 head_ctrl;
 };
 
 struct coh901318_base {
@@ -661,6 +663,9 @@ static struct coh901318_desc *coh901318_queue_start(struct coh901318_chan *cohc)
 
                coh901318_desc_submit(cohc, cohd);
 
+               /* Program the transaction head */
+               coh901318_set_conf(cohc, cohd->head_config);
+               coh901318_set_ctrl(cohc, cohd->head_ctrl);
                coh901318_prep_linked_list(cohc, cohd->lli);
 
                /* start dma job on this channel */
@@ -1091,8 +1096,6 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        } else
                goto err_direction;
 
-       coh901318_set_conf(cohc, config);
-
        /* The dma only supports transmitting packages up to
         * MAX_DMA_PACKET_SIZE. Calculate to total number of
         * dma elemts required to send the entire sg list
@@ -1129,16 +1132,18 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        if (ret)
                goto err_lli_fill;
 
-       /*
-        * Set the default ctrl for the channel to the one from the lli,
-        * things may have changed due to odd buffer alignment etc.
-        */
-       coh901318_set_ctrl(cohc, lli->control);
 
        COH_DBG(coh901318_list_print(cohc, lli));
 
        /* Pick a descriptor to handle this transfer */
        cohd = coh901318_desc_get(cohc);
+       cohd->head_config = config;
+       /*
+        * Set the default head ctrl for the channel to the one from the
+        * lli, things may have changed due to odd buffer alignment
+        * etc.
+        */
+       cohd->head_ctrl = lli->control;
        cohd->dir = direction;
        cohd->flags = flags;
        cohd->desc.tx_submit = coh901318_tx_submit;
index 48694c3..b48967b 100644 (file)
@@ -62,9 +62,9 @@
 #include <linux/slab.h>
 
 static DEFINE_MUTEX(dma_list_mutex);
+static DEFINE_IDR(dma_idr);
 static LIST_HEAD(dma_device_list);
 static long dmaengine_ref_count;
-static struct idr dma_idr;
 
 /* --- sysfs implementation --- */
 
@@ -510,8 +510,8 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v
                                         dma_chan_name(chan));
                                list_del_rcu(&device->global_node);
                        } else if (err)
-                               pr_err("dmaengine: failed to get %s: (%d)\n",
-                                      dma_chan_name(chan), err);
+                               pr_debug("dmaengine: failed to get %s: (%d)\n",
+                                        dma_chan_name(chan), err);
                        else
                                break;
                        if (--device->privatecnt == 0)
@@ -1050,8 +1050,6 @@ EXPORT_SYMBOL_GPL(dma_run_dependencies);
 
 static int __init dma_bus_init(void)
 {
-       idr_init(&dma_idr);
-       mutex_init(&dma_list_mutex);
        return class_register(&dma_devclass);
 }
 arch_initcall(dma_bus_init);
index 0766c1e..5d7a49b 100644 (file)
@@ -902,7 +902,7 @@ static void ep93xx_dma_free_chan_resources(struct dma_chan *chan)
  *
  * Returns a valid DMA descriptor or %NULL in case of failure.
  */
-struct dma_async_tx_descriptor *
+static struct dma_async_tx_descriptor *
 ep93xx_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
                           dma_addr_t src, size_t len, unsigned long flags)
 {
index 1ea47db..7bd7e98 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/dmaengine.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <asm/irq.h>
 #include <mach/sdma.h>
@@ -65,8 +67,8 @@
 #define SDMA_ONCE_RTB          0x060
 #define SDMA_XTRIG_CONF1       0x070
 #define SDMA_XTRIG_CONF2       0x074
-#define SDMA_CHNENBL0_V2       0x200
-#define SDMA_CHNENBL0_V1       0x080
+#define SDMA_CHNENBL0_IMX35    0x200
+#define SDMA_CHNENBL0_IMX31    0x080
 #define SDMA_CHNPRI_0          0x100
 
 /*
@@ -299,13 +301,18 @@ struct sdma_firmware_header {
        u32     ram_code_size;
 };
 
+enum sdma_devtype {
+       IMX31_SDMA,     /* runs on i.mx31 */
+       IMX35_SDMA,     /* runs on i.mx35 and later */
+};
+
 struct sdma_engine {
        struct device                   *dev;
        struct device_dma_parameters    dma_parms;
        struct sdma_channel             channel[MAX_DMA_CHANNELS];
        struct sdma_channel_control     *channel_control;
        void __iomem                    *regs;
-       unsigned int                    version;
+       enum sdma_devtype               devtype;
        unsigned int                    num_events;
        struct sdma_context_data        *context;
        dma_addr_t                      context_phys;
@@ -314,6 +321,26 @@ struct sdma_engine {
        struct sdma_script_start_addrs  *script_addrs;
 };
 
+static struct platform_device_id sdma_devtypes[] = {
+       {
+               .name = "imx31-sdma",
+               .driver_data = IMX31_SDMA,
+       }, {
+               .name = "imx35-sdma",
+               .driver_data = IMX35_SDMA,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, sdma_devtypes);
+
+static const struct of_device_id sdma_dt_ids[] = {
+       { .compatible = "fsl,imx31-sdma", .data = &sdma_devtypes[IMX31_SDMA], },
+       { .compatible = "fsl,imx35-sdma", .data = &sdma_devtypes[IMX35_SDMA], },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sdma_dt_ids);
+
 #define SDMA_H_CONFIG_DSPDMA   (1 << 12) /* indicates if the DSPDMA is used */
 #define SDMA_H_CONFIG_RTD_PINS (1 << 11) /* indicates if Real-Time Debug pins are enabled */
 #define SDMA_H_CONFIG_ACR      (1 << 4)  /* indicates if AHB freq /core freq = 2 or 1 */
@@ -321,8 +348,8 @@ struct sdma_engine {
 
 static inline u32 chnenbl_ofs(struct sdma_engine *sdma, unsigned int event)
 {
-       u32 chnenbl0 = (sdma->version == 2 ? SDMA_CHNENBL0_V2 : SDMA_CHNENBL0_V1);
-
+       u32 chnenbl0 = (sdma->devtype == IMX31_SDMA ? SDMA_CHNENBL0_IMX31 :
+                                                     SDMA_CHNENBL0_IMX35);
        return chnenbl0 + event * 4;
 }
 
@@ -1108,22 +1135,14 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma,
                const char *fw_name)
 {
        const struct firmware *fw;
-       char *fwname;
        const struct sdma_firmware_header *header;
        int ret;
        const struct sdma_script_start_addrs *addr;
        unsigned short *ram_code;
 
-       fwname = kasprintf(GFP_KERNEL, "%s", fw_name);
-       if (!fwname)
-               return -ENOMEM;
-
-       ret = request_firmware(&fw, fwname, sdma->dev);
-       if (ret) {
-               kfree(fwname);
+       ret = request_firmware(&fw, fw_name, sdma->dev);
+       if (ret)
                return ret;
-       }
-       kfree(fwname);
 
        if (fw->size < sizeof(*header))
                goto err_firmware;
@@ -1162,15 +1181,16 @@ static int __init sdma_init(struct sdma_engine *sdma)
        int i, ret;
        dma_addr_t ccb_phys;
 
-       switch (sdma->version) {
-       case 1:
+       switch (sdma->devtype) {
+       case IMX31_SDMA:
                sdma->num_events = 32;
                break;
-       case 2:
+       case IMX35_SDMA:
                sdma->num_events = 48;
                break;
        default:
-               dev_err(sdma->dev, "Unknown version %d. aborting\n", sdma->version);
+               dev_err(sdma->dev, "Unknown sdma type %d. aborting\n",
+                       sdma->devtype);
                return -ENODEV;
        }
 
@@ -1239,6 +1259,10 @@ err_dma_alloc:
 
 static int __init sdma_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *of_id =
+                       of_match_device(sdma_dt_ids, &pdev->dev);
+       struct device_node *np = pdev->dev.of_node;
+       const char *fw_name;
        int ret;
        int irq;
        struct resource *iores;
@@ -1254,7 +1278,7 @@ static int __init sdma_probe(struct platform_device *pdev)
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_irq(pdev, 0);
-       if (!iores || irq < 0 || !pdata) {
+       if (!iores || irq < 0) {
                ret = -EINVAL;
                goto err_irq;
        }
@@ -1281,10 +1305,14 @@ static int __init sdma_probe(struct platform_device *pdev)
                goto err_request_irq;
 
        sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL);
-       if (!sdma->script_addrs)
+       if (!sdma->script_addrs) {
+               ret = -ENOMEM;
                goto err_alloc;
+       }
 
-       sdma->version = pdata->sdma_version;
+       if (of_id)
+               pdev->id_entry = of_id->data;
+       sdma->devtype = pdev->id_entry->driver_data;
 
        dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask);
        dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask);
@@ -1314,10 +1342,30 @@ static int __init sdma_probe(struct platform_device *pdev)
        if (ret)
                goto err_init;
 
-       if (pdata->script_addrs)
+       if (pdata && pdata->script_addrs)
                sdma_add_scripts(sdma, pdata->script_addrs);
 
-       sdma_get_firmware(sdma, pdata->fw_name);
+       if (pdata) {
+               sdma_get_firmware(sdma, pdata->fw_name);
+       } else {
+               /*
+                * Because that device tree does not encode ROM script address,
+                * the RAM script in firmware is mandatory for device tree
+                * probe, otherwise it fails.
+                */
+               ret = of_property_read_string(np, "fsl,sdma-ram-script-name",
+                                             &fw_name);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to get firmware name\n");
+                       goto err_init;
+               }
+
+               ret = sdma_get_firmware(sdma, fw_name);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to get firmware\n");
+                       goto err_init;
+               }
+       }
 
        sdma->dma_device.dev = &pdev->dev;
 
@@ -1365,7 +1413,9 @@ static int __exit sdma_remove(struct platform_device *pdev)
 static struct platform_driver sdma_driver = {
        .driver         = {
                .name   = "imx-sdma",
+               .of_match_table = sdma_dt_ids,
        },
+       .id_table       = sdma_devtypes,
        .remove         = __exit_p(sdma_remove),
 };
 
index f653517..8a3fdd8 100644 (file)
@@ -1351,7 +1351,6 @@ int dma_suspend(struct pci_dev *pci, pm_message_t state)
                        return -EAGAIN;
        }
        device->state = SUSPENDED;
-       pci_set_drvdata(pci, device);
        pci_save_state(pci);
        pci_disable_device(pci);
        pci_set_power_state(pci, PCI_D3hot);
@@ -1380,7 +1379,6 @@ int dma_resume(struct pci_dev *pci)
        }
        device->state = RUNNING;
        iowrite32(REG_BIT0, device->dma_base + DMA_CFG);
-       pci_set_drvdata(pci, device);
        return 0;
 }
 
index d845dc4..f519c93 100644 (file)
 /* provide a lookup table for setting the source address in the base or
  * extended descriptor of an xor or pq descriptor
  */
-static const u8 xor_idx_to_desc __read_mostly = 0xd0;
-static const u8 xor_idx_to_field[] __read_mostly = { 1, 4, 5, 6, 7, 0, 1, 2 };
-static const u8 pq_idx_to_desc __read_mostly = 0xf8;
-static const u8 pq_idx_to_field[] __read_mostly = { 1, 4, 5, 0, 1, 2, 4, 5 };
+static const u8 xor_idx_to_desc = 0xe0;
+static const u8 xor_idx_to_field[] = { 1, 4, 5, 6, 7, 0, 1, 2 };
+static const u8 pq_idx_to_desc = 0xf8;
+static const u8 pq_idx_to_field[] = { 1, 4, 5, 0, 1, 2, 4, 5 };
 
 static dma_addr_t xor_get_src(struct ioat_raw_descriptor *descs[2], int idx)
 {
index fab37d1..5e3a40f 100644 (file)
@@ -72,6 +72,17 @@ static struct pci_device_id ioat_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF8) },
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF9) },
 
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB0) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB1) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB2) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB3) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB4) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB5) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB6) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB7) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB8) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB9) },
+
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, ioat_pci_tbl);
index fd7d2b3..6815905 100644 (file)
@@ -1706,16 +1706,14 @@ static int __init ipu_probe(struct platform_device *pdev)
                ipu_data.irq_fn, ipu_data.irq_err, ipu_data.irq_base);
 
        /* Remap IPU common registers */
-       ipu_data.reg_ipu = ioremap(mem_ipu->start,
-                                  mem_ipu->end - mem_ipu->start + 1);
+       ipu_data.reg_ipu = ioremap(mem_ipu->start, resource_size(mem_ipu));
        if (!ipu_data.reg_ipu) {
                ret = -ENOMEM;
                goto err_ioremap_ipu;
        }
 
        /* Remap Image Converter and Image DMA Controller registers */
-       ipu_data.reg_ic = ioremap(mem_ic->start,
-                                 mem_ic->end - mem_ic->start + 1);
+       ipu_data.reg_ic = ioremap(mem_ic->start, resource_size(mem_ic));
        if (!ipu_data.reg_ic) {
                ret = -ENOMEM;
                goto err_ioremap_ic;
index 06f9f27..9a353c2 100644 (file)
@@ -1304,7 +1304,8 @@ static int mv_xor_shared_probe(struct platform_device *pdev)
        if (!res)
                return -ENODEV;
 
-       msp->xor_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+       msp->xor_base = devm_ioremap(&pdev->dev, res->start,
+                                    resource_size(res));
        if (!msp->xor_base)
                return -EBUSY;
 
index 88aad4f..be641cb 100644 (file)
@@ -327,10 +327,12 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
 
        memset(mxs_chan->ccw, 0, PAGE_SIZE);
 
-       ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
-                               0, "mxs-dma", mxs_dma);
-       if (ret)
-               goto err_irq;
+       if (mxs_chan->chan_irq != NO_IRQ) {
+               ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
+                                       0, "mxs-dma", mxs_dma);
+               if (ret)
+                       goto err_irq;
+       }
 
        ret = clk_enable(mxs_dma->clk);
        if (ret)
@@ -535,6 +537,7 @@ static int mxs_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
        switch (cmd) {
        case DMA_TERMINATE_ALL:
                mxs_dma_disable_chan(mxs_chan);
+               mxs_dma_reset_chan(mxs_chan);
                break;
        case DMA_PAUSE:
                mxs_dma_pause_chan(mxs_chan);
@@ -707,6 +710,8 @@ static struct platform_device_id mxs_dma_type[] = {
        }, {
                .name = "mxs-dma-apbx",
                .driver_data = MXS_DMA_APBX,
+       }, {
+               /* end of list */
        }
 };
 
index ff5b38f..1ac8d4b 100644 (file)
@@ -45,7 +45,8 @@
 #define DMA_STATUS_MASK_BITS           0x3
 #define DMA_STATUS_SHIFT_BITS          16
 #define DMA_STATUS_IRQ(x)              (0x1 << (x))
-#define DMA_STATUS_ERR(x)              (0x1 << ((x) + 8))
+#define DMA_STATUS0_ERR(x)             (0x1 << ((x) + 8))
+#define DMA_STATUS2_ERR(x)             (0x1 << (x))
 
 #define DMA_DESC_WIDTH_SHIFT_BITS      12
 #define DMA_DESC_WIDTH_1_BYTE          (0x3 << DMA_DESC_WIDTH_SHIFT_BITS)
@@ -61,6 +62,9 @@
 
 #define MAX_CHAN_NR                    8
 
+#define DMA_MASK_CTL0_MODE     0x33333333
+#define DMA_MASK_CTL2_MODE     0x00003333
+
 static unsigned int init_nr_desc_per_channel = 64;
 module_param(init_nr_desc_per_channel, uint, 0644);
 MODULE_PARM_DESC(init_nr_desc_per_channel,
@@ -133,6 +137,7 @@ struct pch_dma {
 #define PCH_DMA_CTL3   0x0C
 #define PCH_DMA_STS0   0x10
 #define PCH_DMA_STS1   0x14
+#define PCH_DMA_STS2   0x18
 
 #define dma_readl(pd, name) \
        readl((pd)->membase + PCH_DMA_##name)
@@ -183,13 +188,19 @@ static void pdc_enable_irq(struct dma_chan *chan, int enable)
 {
        struct pch_dma *pd = to_pd(chan->device);
        u32 val;
+       int pos;
+
+       if (chan->chan_id < 8)
+               pos = chan->chan_id;
+       else
+               pos = chan->chan_id + 8;
 
        val = dma_readl(pd, CTL2);
 
        if (enable)
-               val |= 0x1 << chan->chan_id;
+               val |= 0x1 << pos;
        else
-               val &= ~(0x1 << chan->chan_id);
+               val &= ~(0x1 << pos);
 
        dma_writel(pd, CTL2, val);
 
@@ -202,10 +213,17 @@ static void pdc_set_dir(struct dma_chan *chan)
        struct pch_dma_chan *pd_chan = to_pd_chan(chan);
        struct pch_dma *pd = to_pd(chan->device);
        u32 val;
+       u32 mask_mode;
+       u32 mask_ctl;
 
        if (chan->chan_id < 8) {
                val = dma_readl(pd, CTL0);
 
+               mask_mode = DMA_CTL0_MODE_MASK_BITS <<
+                                       (DMA_CTL0_BITS_PER_CH * chan->chan_id);
+               mask_ctl = DMA_MASK_CTL0_MODE & ~(DMA_CTL0_MODE_MASK_BITS <<
+                                      (DMA_CTL0_BITS_PER_CH * chan->chan_id));
+               val &= mask_mode;
                if (pd_chan->dir == DMA_TO_DEVICE)
                        val |= 0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id +
                                       DMA_CTL0_DIR_SHIFT_BITS);
@@ -213,18 +231,24 @@ static void pdc_set_dir(struct dma_chan *chan)
                        val &= ~(0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id +
                                         DMA_CTL0_DIR_SHIFT_BITS));
 
+               val |= mask_ctl;
                dma_writel(pd, CTL0, val);
        } else {
                int ch = chan->chan_id - 8; /* ch8-->0 ch9-->1 ... ch11->3 */
                val = dma_readl(pd, CTL3);
 
+               mask_mode = DMA_CTL0_MODE_MASK_BITS <<
+                                               (DMA_CTL0_BITS_PER_CH * ch);
+               mask_ctl = DMA_MASK_CTL2_MODE & ~(DMA_CTL0_MODE_MASK_BITS <<
+                                                (DMA_CTL0_BITS_PER_CH * ch));
+               val &= mask_mode;
                if (pd_chan->dir == DMA_TO_DEVICE)
                        val |= 0x1 << (DMA_CTL0_BITS_PER_CH * ch +
                                       DMA_CTL0_DIR_SHIFT_BITS);
                else
                        val &= ~(0x1 << (DMA_CTL0_BITS_PER_CH * ch +
                                         DMA_CTL0_DIR_SHIFT_BITS));
-
+               val |= mask_ctl;
                dma_writel(pd, CTL3, val);
        }
 
@@ -236,33 +260,37 @@ static void pdc_set_mode(struct dma_chan *chan, u32 mode)
 {
        struct pch_dma *pd = to_pd(chan->device);
        u32 val;
+       u32 mask_ctl;
+       u32 mask_dir;
 
        if (chan->chan_id < 8) {
+               mask_ctl = DMA_MASK_CTL0_MODE & ~(DMA_CTL0_MODE_MASK_BITS <<
+                          (DMA_CTL0_BITS_PER_CH * chan->chan_id));
+               mask_dir = 1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id +\
+                                DMA_CTL0_DIR_SHIFT_BITS);
                val = dma_readl(pd, CTL0);
-
-               val &= ~(DMA_CTL0_MODE_MASK_BITS <<
-                       (DMA_CTL0_BITS_PER_CH * chan->chan_id));
+               val &= mask_dir;
                val |= mode << (DMA_CTL0_BITS_PER_CH * chan->chan_id);
-
+               val |= mask_ctl;
                dma_writel(pd, CTL0, val);
        } else {
                int ch = chan->chan_id - 8; /* ch8-->0 ch9-->1 ... ch11->3 */
-
+               mask_ctl = DMA_MASK_CTL2_MODE & ~(DMA_CTL0_MODE_MASK_BITS <<
+                                                (DMA_CTL0_BITS_PER_CH * ch));
+               mask_dir = 1 << (DMA_CTL0_BITS_PER_CH * ch +\
+                                DMA_CTL0_DIR_SHIFT_BITS);
                val = dma_readl(pd, CTL3);
-
-               val &= ~(DMA_CTL0_MODE_MASK_BITS <<
-                       (DMA_CTL0_BITS_PER_CH * ch));
+               val &= mask_dir;
                val |= mode << (DMA_CTL0_BITS_PER_CH * ch);
-
+               val |= mask_ctl;
                dma_writel(pd, CTL3, val);
-
        }
 
        dev_dbg(chan2dev(chan), "pdc_set_mode: chan %d -> %x\n",
                chan->chan_id, val);
 }
 
-static u32 pdc_get_status(struct pch_dma_chan *pd_chan)
+static u32 pdc_get_status0(struct pch_dma_chan *pd_chan)
 {
        struct pch_dma *pd = to_pd(pd_chan->chan.device);
        u32 val;
@@ -272,9 +300,27 @@ static u32 pdc_get_status(struct pch_dma_chan *pd_chan)
                        DMA_STATUS_BITS_PER_CH * pd_chan->chan.chan_id));
 }
 
+static u32 pdc_get_status2(struct pch_dma_chan *pd_chan)
+{
+       struct pch_dma *pd = to_pd(pd_chan->chan.device);
+       u32 val;
+
+       val = dma_readl(pd, STS2);
+       return DMA_STATUS_MASK_BITS & (val >> (DMA_STATUS_SHIFT_BITS +
+                       DMA_STATUS_BITS_PER_CH * (pd_chan->chan.chan_id - 8)));
+}
+
 static bool pdc_is_idle(struct pch_dma_chan *pd_chan)
 {
-       if (pdc_get_status(pd_chan) == DMA_STATUS_IDLE)
+       u32 sts;
+
+       if (pd_chan->chan.chan_id < 8)
+               sts = pdc_get_status0(pd_chan);
+       else
+               sts = pdc_get_status2(pd_chan);
+
+
+       if (sts == DMA_STATUS_IDLE)
                return true;
        else
                return false;
@@ -495,11 +541,11 @@ static int pd_alloc_chan_resources(struct dma_chan *chan)
                list_add_tail(&desc->desc_node, &tmp_list);
        }
 
-       spin_lock_bh(&pd_chan->lock);
+       spin_lock_irq(&pd_chan->lock);
        list_splice(&tmp_list, &pd_chan->free_list);
        pd_chan->descs_allocated = i;
        pd_chan->completed_cookie = chan->cookie = 1;
-       spin_unlock_bh(&pd_chan->lock);
+       spin_unlock_irq(&pd_chan->lock);
 
        pdc_enable_irq(chan, 1);
 
@@ -517,10 +563,10 @@ static void pd_free_chan_resources(struct dma_chan *chan)
        BUG_ON(!list_empty(&pd_chan->active_list));
        BUG_ON(!list_empty(&pd_chan->queue));
 
-       spin_lock_bh(&pd_chan->lock);
+       spin_lock_irq(&pd_chan->lock);
        list_splice_init(&pd_chan->free_list, &tmp_list);
        pd_chan->descs_allocated = 0;
-       spin_unlock_bh(&pd_chan->lock);
+       spin_unlock_irq(&pd_chan->lock);
 
        list_for_each_entry_safe(desc, _d, &tmp_list, desc_node)
                pci_pool_free(pd->pool, desc, desc->txd.phys);
@@ -536,10 +582,10 @@ static enum dma_status pd_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
        dma_cookie_t last_completed;
        int ret;
 
-       spin_lock_bh(&pd_chan->lock);
+       spin_lock_irq(&pd_chan->lock);
        last_completed = pd_chan->completed_cookie;
        last_used = chan->cookie;
-       spin_unlock_bh(&pd_chan->lock);
+       spin_unlock_irq(&pd_chan->lock);
 
        ret = dma_async_is_complete(cookie, last_completed, last_used);
 
@@ -654,7 +700,7 @@ static int pd_device_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
        if (cmd != DMA_TERMINATE_ALL)
                return -ENXIO;
 
-       spin_lock_bh(&pd_chan->lock);
+       spin_lock_irq(&pd_chan->lock);
 
        pdc_set_mode(&pd_chan->chan, DMA_CTL0_DISABLE);
 
@@ -664,7 +710,7 @@ static int pd_device_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
        list_for_each_entry_safe(desc, _d, &list, desc_node)
                pdc_chain_complete(pd_chan, desc);
 
-       spin_unlock_bh(&pd_chan->lock);
+       spin_unlock_irq(&pd_chan->lock);
 
        return 0;
 }
@@ -693,30 +739,45 @@ static irqreturn_t pd_irq(int irq, void *devid)
        struct pch_dma *pd = (struct pch_dma *)devid;
        struct pch_dma_chan *pd_chan;
        u32 sts0;
+       u32 sts2;
        int i;
-       int ret = IRQ_NONE;
+       int ret0 = IRQ_NONE;
+       int ret2 = IRQ_NONE;
 
        sts0 = dma_readl(pd, STS0);
+       sts2 = dma_readl(pd, STS2);
 
        dev_dbg(pd->dma.dev, "pd_irq sts0: %x\n", sts0);
 
        for (i = 0; i < pd->dma.chancnt; i++) {
                pd_chan = &pd->channels[i];
 
-               if (sts0 & DMA_STATUS_IRQ(i)) {
-                       if (sts0 & DMA_STATUS_ERR(i))
-                               set_bit(0, &pd_chan->err_status);
+               if (i < 8) {
+                       if (sts0 & DMA_STATUS_IRQ(i)) {
+                               if (sts0 & DMA_STATUS0_ERR(i))
+                                       set_bit(0, &pd_chan->err_status);
 
-                       tasklet_schedule(&pd_chan->tasklet);
-                       ret = IRQ_HANDLED;
-               }
+                               tasklet_schedule(&pd_chan->tasklet);
+                               ret0 = IRQ_HANDLED;
+                       }
+               } else {
+                       if (sts2 & DMA_STATUS_IRQ(i - 8)) {
+                               if (sts2 & DMA_STATUS2_ERR(i))
+                                       set_bit(0, &pd_chan->err_status);
 
+                               tasklet_schedule(&pd_chan->tasklet);
+                               ret2 = IRQ_HANDLED;
+                       }
+               }
        }
 
        /* clear interrupt bits in status register */
-       dma_writel(pd, STS0, sts0);
+       if (ret0)
+               dma_writel(pd, STS0, sts0);
+       if (ret2)
+               dma_writel(pd, STS2, sts2);
 
-       return ret;
+       return ret0 | ret2;
 }
 
 #ifdef CONFIG_PM
index 6abe1ec..00eee59 100644 (file)
@@ -82,7 +82,7 @@ struct dma_pl330_dmac {
        spinlock_t pool_lock;
 
        /* Peripheral channels connected to this DMAC */
-       struct dma_pl330_chan peripherals[0]; /* keep at end */
+       struct dma_pl330_chan *peripherals; /* keep at end */
 };
 
 struct dma_pl330_desc {
@@ -451,8 +451,13 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
        desc->txd.cookie = 0;
        async_tx_ack(&desc->txd);
 
-       desc->req.rqtype = peri->rqtype;
-       desc->req.peri = peri->peri_id;
+       if (peri) {
+               desc->req.rqtype = peri->rqtype;
+               desc->req.peri = peri->peri_id;
+       } else {
+               desc->req.rqtype = MEMTOMEM;
+               desc->req.peri = 0;
+       }
 
        dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
 
@@ -529,10 +534,10 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
        struct pl330_info *pi;
        int burst;
 
-       if (unlikely(!pch || !len || !peri))
+       if (unlikely(!pch || !len))
                return NULL;
 
-       if (peri->rqtype != MEMTOMEM)
+       if (peri && peri->rqtype != MEMTOMEM)
                return NULL;
 
        pi = &pch->dmac->pif;
@@ -577,7 +582,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        int i, burst_size;
        dma_addr_t addr;
 
-       if (unlikely(!pch || !sgl || !sg_len))
+       if (unlikely(!pch || !sgl || !sg_len || !peri))
                return NULL;
 
        /* Make sure the direction is consistent */
@@ -666,17 +671,12 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        struct dma_device *pd;
        struct resource *res;
        int i, ret, irq;
+       int num_chan;
 
        pdat = adev->dev.platform_data;
 
-       if (!pdat || !pdat->nr_valid_peri) {
-               dev_err(&adev->dev, "platform data missing\n");
-               return -ENODEV;
-       }
-
        /* Allocate a new DMAC and its Channels */
-       pdmac = kzalloc(pdat->nr_valid_peri * sizeof(*pch)
-                               + sizeof(*pdmac), GFP_KERNEL);
+       pdmac = kzalloc(sizeof(*pdmac), GFP_KERNEL);
        if (!pdmac) {
                dev_err(&adev->dev, "unable to allocate mem\n");
                return -ENOMEM;
@@ -685,7 +685,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        pi = &pdmac->pif;
        pi->dev = &adev->dev;
        pi->pl330_data = NULL;
-       pi->mcbufsz = pdat->mcbuf_sz;
+       pi->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
 
        res = &adev->res;
        request_mem_region(res->start, resource_size(res), "dma-pl330");
@@ -717,27 +717,35 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        INIT_LIST_HEAD(&pd->channels);
 
        /* Initialize channel parameters */
-       for (i = 0; i < pdat->nr_valid_peri; i++) {
-               struct dma_pl330_peri *peri = &pdat->peri[i];
-               pch = &pdmac->peripherals[i];
+       num_chan = max(pdat ? pdat->nr_valid_peri : 0, (u8)pi->pcfg.num_chan);
+       pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
 
-               switch (peri->rqtype) {
-               case MEMTOMEM:
+       for (i = 0; i < num_chan; i++) {
+               pch = &pdmac->peripherals[i];
+               if (pdat) {
+                       struct dma_pl330_peri *peri = &pdat->peri[i];
+
+                       switch (peri->rqtype) {
+                       case MEMTOMEM:
+                               dma_cap_set(DMA_MEMCPY, pd->cap_mask);
+                               break;
+                       case MEMTODEV:
+                       case DEVTOMEM:
+                               dma_cap_set(DMA_SLAVE, pd->cap_mask);
+                               break;
+                       default:
+                               dev_err(&adev->dev, "DEVTODEV Not Supported\n");
+                               continue;
+                       }
+                       pch->chan.private = peri;
+               } else {
                        dma_cap_set(DMA_MEMCPY, pd->cap_mask);
-                       break;
-               case MEMTODEV:
-               case DEVTOMEM:
-                       dma_cap_set(DMA_SLAVE, pd->cap_mask);
-                       break;
-               default:
-                       dev_err(&adev->dev, "DEVTODEV Not Supported\n");
-                       continue;
+                       pch->chan.private = NULL;
                }
 
                INIT_LIST_HEAD(&pch->work_list);
                spin_lock_init(&pch->lock);
                pch->pl330_chid = NULL;
-               pch->chan.private = peri;
                pch->chan.device = pd;
                pch->chan.chan_id = i;
                pch->dmac = pdmac;
index 0283300..7f49235 100644 (file)
@@ -70,12 +70,36 @@ static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg)
 
 static u16 dmaor_read(struct sh_dmae_device *shdev)
 {
-       return __raw_readw(shdev->chan_reg + DMAOR / sizeof(u32));
+       u32 __iomem *addr = shdev->chan_reg + DMAOR / sizeof(u32);
+
+       if (shdev->pdata->dmaor_is_32bit)
+               return __raw_readl(addr);
+       else
+               return __raw_readw(addr);
 }
 
 static void dmaor_write(struct sh_dmae_device *shdev, u16 data)
 {
-       __raw_writew(data, shdev->chan_reg + DMAOR / sizeof(u32));
+       u32 __iomem *addr = shdev->chan_reg + DMAOR / sizeof(u32);
+
+       if (shdev->pdata->dmaor_is_32bit)
+               __raw_writel(data, addr);
+       else
+               __raw_writew(data, addr);
+}
+
+static void chcr_write(struct sh_dmae_chan *sh_dc, u32 data)
+{
+       struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
+
+       __raw_writel(data, sh_dc->base + shdev->chcr_offset / sizeof(u32));
+}
+
+static u32 chcr_read(struct sh_dmae_chan *sh_dc)
+{
+       struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
+
+       return __raw_readl(sh_dc->base + shdev->chcr_offset / sizeof(u32));
 }
 
 /*
@@ -120,7 +144,7 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
 
 static bool dmae_is_busy(struct sh_dmae_chan *sh_chan)
 {
-       u32 chcr = sh_dmae_readl(sh_chan, CHCR);
+       u32 chcr = chcr_read(sh_chan);
 
        if ((chcr & (CHCR_DE | CHCR_TE)) == CHCR_DE)
                return true; /* working */
@@ -130,8 +154,7 @@ static bool dmae_is_busy(struct sh_dmae_chan *sh_chan)
 
 static unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan, u32 chcr)
 {
-       struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
-                                               struct sh_dmae_device, common);
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
        struct sh_dmae_pdata *pdata = shdev->pdata;
        int cnt = ((chcr & pdata->ts_low_mask) >> pdata->ts_low_shift) |
                ((chcr & pdata->ts_high_mask) >> pdata->ts_high_shift);
@@ -144,8 +167,7 @@ static unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan, u32 chcr)
 
 static u32 log2size_to_chcr(struct sh_dmae_chan *sh_chan, int l2size)
 {
-       struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
-                                               struct sh_dmae_device, common);
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
        struct sh_dmae_pdata *pdata = shdev->pdata;
        int i;
 
@@ -169,18 +191,23 @@ static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw)
 
 static void dmae_start(struct sh_dmae_chan *sh_chan)
 {
-       u32 chcr = sh_dmae_readl(sh_chan, CHCR);
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+       u32 chcr = chcr_read(sh_chan);
+
+       if (shdev->pdata->needs_tend_set)
+               sh_dmae_writel(sh_chan, 0xFFFFFFFF, TEND);
 
-       chcr |= CHCR_DE | CHCR_IE;
-       sh_dmae_writel(sh_chan, chcr & ~CHCR_TE, CHCR);
+       chcr |= CHCR_DE | shdev->chcr_ie_bit;
+       chcr_write(sh_chan, chcr & ~CHCR_TE);
 }
 
 static void dmae_halt(struct sh_dmae_chan *sh_chan)
 {
-       u32 chcr = sh_dmae_readl(sh_chan, CHCR);
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+       u32 chcr = chcr_read(sh_chan);
 
-       chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE);
-       sh_dmae_writel(sh_chan, chcr, CHCR);
+       chcr &= ~(CHCR_DE | CHCR_TE | shdev->chcr_ie_bit);
+       chcr_write(sh_chan, chcr);
 }
 
 static void dmae_init(struct sh_dmae_chan *sh_chan)
@@ -192,7 +219,7 @@ static void dmae_init(struct sh_dmae_chan *sh_chan)
        u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan,
                                                   LOG2_DEFAULT_XFER_SIZE);
        sh_chan->xmit_shift = calc_xmit_shift(sh_chan, chcr);
-       sh_dmae_writel(sh_chan, chcr, CHCR);
+       chcr_write(sh_chan, chcr);
 }
 
 static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val)
@@ -202,23 +229,25 @@ static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val)
                return -EBUSY;
 
        sh_chan->xmit_shift = calc_xmit_shift(sh_chan, val);
-       sh_dmae_writel(sh_chan, val, CHCR);
+       chcr_write(sh_chan, val);
 
        return 0;
 }
 
 static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
 {
-       struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
-                                               struct sh_dmae_device, common);
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
        struct sh_dmae_pdata *pdata = shdev->pdata;
        const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id];
        u16 __iomem *addr = shdev->dmars;
-       int shift = chan_pdata->dmars_bit;
+       unsigned int shift = chan_pdata->dmars_bit;
 
        if (dmae_is_busy(sh_chan))
                return -EBUSY;
 
+       if (pdata->no_dmars)
+               return 0;
+
        /* in the case of a missing DMARS resource use first memory window */
        if (!addr)
                addr = (u16 __iomem *)shdev->chan_reg;
@@ -296,9 +325,7 @@ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan)
 static const struct sh_dmae_slave_config *sh_dmae_find_slave(
        struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param)
 {
-       struct dma_device *dma_dev = sh_chan->common.device;
-       struct sh_dmae_device *shdev = container_of(dma_dev,
-                                       struct sh_dmae_device, common);
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
        struct sh_dmae_pdata *pdata = shdev->pdata;
        int i;
 
@@ -771,10 +798,8 @@ static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
 
        spin_lock_bh(&sh_chan->desc_lock);
        /* DMA work check */
-       if (dmae_is_busy(sh_chan)) {
-               spin_unlock_bh(&sh_chan->desc_lock);
-               return;
-       }
+       if (dmae_is_busy(sh_chan))
+               goto sh_chan_xfer_ld_queue_end;
 
        /* Find the first not transferred descriptor */
        list_for_each_entry(desc, &sh_chan->ld_queue, node)
@@ -788,6 +813,7 @@ static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
                        break;
                }
 
+sh_chan_xfer_ld_queue_end:
        spin_unlock_bh(&sh_chan->desc_lock);
 }
 
@@ -846,7 +872,7 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data)
 
        spin_lock(&sh_chan->desc_lock);
 
-       chcr = sh_dmae_readl(sh_chan, CHCR);
+       chcr = chcr_read(sh_chan);
 
        if (chcr & CHCR_TE) {
                /* DMA stop */
@@ -1144,6 +1170,16 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
        /* platform data */
        shdev->pdata = pdata;
 
+       if (pdata->chcr_offset)
+               shdev->chcr_offset = pdata->chcr_offset;
+       else
+               shdev->chcr_offset = CHCR;
+
+       if (pdata->chcr_ie_bit)
+               shdev->chcr_ie_bit = pdata->chcr_ie_bit;
+       else
+               shdev->chcr_ie_bit = CHCR_IE;
+
        platform_set_drvdata(pdev, shdev);
 
        pm_runtime_enable(&pdev->dev);
index 5ae9fc5..dc56576 100644 (file)
@@ -47,10 +47,14 @@ struct sh_dmae_device {
        struct list_head node;
        u32 __iomem *chan_reg;
        u16 __iomem *dmars;
+       unsigned int chcr_offset;
+       u32 chcr_ie_bit;
 };
 
 #define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common)
 #define to_sh_desc(lh) container_of(lh, struct sh_desc, node)
 #define tx_to_sh_desc(tx) container_of(tx, struct sh_desc, async_tx)
+#define to_sh_dev(chan) container_of(chan->common.device,\
+                                    struct sh_dmae_device, common)
 
 #endif /* __DMA_SHDMA_H */
index 29d1add..cd3a7c7 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/amba/bus.h>
 
 #include <plat/ste_dma40.h>
 
@@ -45,9 +46,6 @@
 #define D40_ALLOC_PHY          (1 << 30)
 #define D40_ALLOC_LOG_FREE     0
 
-/* Hardware designer of the block */
-#define D40_HW_DESIGNER 0x8
-
 /**
  * enum 40_command - The different commands and/or statuses.
  *
@@ -186,6 +184,8 @@ struct d40_base;
  * @log_def: Default logical channel settings.
  * @lcla: Space for one dst src pair for logical channel transfers.
  * @lcpa: Pointer to dst and src lcpa settings.
+ * @runtime_addr: runtime configured address.
+ * @runtime_direction: runtime configured direction.
  *
  * This struct can either "be" a logical or a physical channel.
  */
@@ -200,6 +200,7 @@ struct d40_chan {
        struct dma_chan                  chan;
        struct tasklet_struct            tasklet;
        struct list_head                 client;
+       struct list_head                 pending_queue;
        struct list_head                 active;
        struct list_head                 queue;
        struct stedma40_chan_cfg         dma_cfg;
@@ -645,7 +646,20 @@ static struct d40_desc *d40_first_active_get(struct d40_chan *d40c)
 
 static void d40_desc_queue(struct d40_chan *d40c, struct d40_desc *desc)
 {
-       list_add_tail(&desc->node, &d40c->queue);
+       list_add_tail(&desc->node, &d40c->pending_queue);
+}
+
+static struct d40_desc *d40_first_pending(struct d40_chan *d40c)
+{
+       struct d40_desc *d;
+
+       if (list_empty(&d40c->pending_queue))
+               return NULL;
+
+       d = list_first_entry(&d40c->pending_queue,
+                            struct d40_desc,
+                            node);
+       return d;
 }
 
 static struct d40_desc *d40_first_queued(struct d40_chan *d40c)
@@ -802,6 +816,11 @@ static void d40_term_all(struct d40_chan *d40c)
                d40_desc_free(d40c, d40d);
        }
 
+       /* Release pending descriptors */
+       while ((d40d = d40_first_pending(d40c))) {
+               d40_desc_remove(d40d);
+               d40_desc_free(d40c, d40d);
+       }
 
        d40c->pending_tx = 0;
        d40c->busy = false;
@@ -2092,7 +2111,7 @@ dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
        struct scatterlist *sg;
        int i;
 
-       sg = kcalloc(periods + 1, sizeof(struct scatterlist), GFP_KERNEL);
+       sg = kcalloc(periods + 1, sizeof(struct scatterlist), GFP_NOWAIT);
        for (i = 0; i < periods; i++) {
                sg_dma_address(&sg[i]) = dma_addr;
                sg_dma_len(&sg[i]) = period_len;
@@ -2152,24 +2171,87 @@ static void d40_issue_pending(struct dma_chan *chan)
 
        spin_lock_irqsave(&d40c->lock, flags);
 
-       /* Busy means that pending jobs are already being processed */
+       list_splice_tail_init(&d40c->pending_queue, &d40c->queue);
+
+       /* Busy means that queued jobs are already being processed */
        if (!d40c->busy)
                (void) d40_queue_start(d40c);
 
        spin_unlock_irqrestore(&d40c->lock, flags);
 }
 
+static int
+dma40_config_to_halfchannel(struct d40_chan *d40c,
+                           struct stedma40_half_channel_info *info,
+                           enum dma_slave_buswidth width,
+                           u32 maxburst)
+{
+       enum stedma40_periph_data_width addr_width;
+       int psize;
+
+       switch (width) {
+       case DMA_SLAVE_BUSWIDTH_1_BYTE:
+               addr_width = STEDMA40_BYTE_WIDTH;
+               break;
+       case DMA_SLAVE_BUSWIDTH_2_BYTES:
+               addr_width = STEDMA40_HALFWORD_WIDTH;
+               break;
+       case DMA_SLAVE_BUSWIDTH_4_BYTES:
+               addr_width = STEDMA40_WORD_WIDTH;
+               break;
+       case DMA_SLAVE_BUSWIDTH_8_BYTES:
+               addr_width = STEDMA40_DOUBLEWORD_WIDTH;
+               break;
+       default:
+               dev_err(d40c->base->dev,
+                       "illegal peripheral address width "
+                       "requested (%d)\n",
+                       width);
+               return -EINVAL;
+       }
+
+       if (chan_is_logical(d40c)) {
+               if (maxburst >= 16)
+                       psize = STEDMA40_PSIZE_LOG_16;
+               else if (maxburst >= 8)
+                       psize = STEDMA40_PSIZE_LOG_8;
+               else if (maxburst >= 4)
+                       psize = STEDMA40_PSIZE_LOG_4;
+               else
+                       psize = STEDMA40_PSIZE_LOG_1;
+       } else {
+               if (maxburst >= 16)
+                       psize = STEDMA40_PSIZE_PHY_16;
+               else if (maxburst >= 8)
+                       psize = STEDMA40_PSIZE_PHY_8;
+               else if (maxburst >= 4)
+                       psize = STEDMA40_PSIZE_PHY_4;
+               else
+                       psize = STEDMA40_PSIZE_PHY_1;
+       }
+
+       info->data_width = addr_width;
+       info->psize = psize;
+       info->flow_ctrl = STEDMA40_NO_FLOW_CTRL;
+
+       return 0;
+}
+
 /* Runtime reconfiguration extension */
-static void d40_set_runtime_config(struct dma_chan *chan,
-                              struct dma_slave_config *config)
+static int d40_set_runtime_config(struct dma_chan *chan,
+                                 struct dma_slave_config *config)
 {
        struct d40_chan *d40c = container_of(chan, struct d40_chan, chan);
        struct stedma40_chan_cfg *cfg = &d40c->dma_cfg;
-       enum dma_slave_buswidth config_addr_width;
+       enum dma_slave_buswidth src_addr_width, dst_addr_width;
        dma_addr_t config_addr;
-       u32 config_maxburst;
-       enum stedma40_periph_data_width addr_width;
-       int psize;
+       u32 src_maxburst, dst_maxburst;
+       int ret;
+
+       src_addr_width = config->src_addr_width;
+       src_maxburst = config->src_maxburst;
+       dst_addr_width = config->dst_addr_width;
+       dst_maxburst = config->dst_maxburst;
 
        if (config->direction == DMA_FROM_DEVICE) {
                dma_addr_t dev_addr_rx =
@@ -2188,8 +2270,11 @@ static void d40_set_runtime_config(struct dma_chan *chan,
                                cfg->dir);
                cfg->dir = STEDMA40_PERIPH_TO_MEM;
 
-               config_addr_width = config->src_addr_width;
-               config_maxburst = config->src_maxburst;
+               /* Configure the memory side */
+               if (dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+                       dst_addr_width = src_addr_width;
+               if (dst_maxburst == 0)
+                       dst_maxburst = src_maxburst;
 
        } else if (config->direction == DMA_TO_DEVICE) {
                dma_addr_t dev_addr_tx =
@@ -2208,68 +2293,39 @@ static void d40_set_runtime_config(struct dma_chan *chan,
                                cfg->dir);
                cfg->dir = STEDMA40_MEM_TO_PERIPH;
 
-               config_addr_width = config->dst_addr_width;
-               config_maxburst = config->dst_maxburst;
-
+               /* Configure the memory side */
+               if (src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+                       src_addr_width = dst_addr_width;
+               if (src_maxburst == 0)
+                       src_maxburst = dst_maxburst;
        } else {
                dev_err(d40c->base->dev,
                        "unrecognized channel direction %d\n",
                        config->direction);
-               return;
+               return -EINVAL;
        }
 
-       switch (config_addr_width) {
-       case DMA_SLAVE_BUSWIDTH_1_BYTE:
-               addr_width = STEDMA40_BYTE_WIDTH;
-               break;
-       case DMA_SLAVE_BUSWIDTH_2_BYTES:
-               addr_width = STEDMA40_HALFWORD_WIDTH;
-               break;
-       case DMA_SLAVE_BUSWIDTH_4_BYTES:
-               addr_width = STEDMA40_WORD_WIDTH;
-               break;
-       case DMA_SLAVE_BUSWIDTH_8_BYTES:
-               addr_width = STEDMA40_DOUBLEWORD_WIDTH;
-               break;
-       default:
+       if (src_maxburst * src_addr_width != dst_maxburst * dst_addr_width) {
                dev_err(d40c->base->dev,
-                       "illegal peripheral address width "
-                       "requested (%d)\n",
-                       config->src_addr_width);
-               return;
+                       "src/dst width/maxburst mismatch: %d*%d != %d*%d\n",
+                       src_maxburst,
+                       src_addr_width,
+                       dst_maxburst,
+                       dst_addr_width);
+               return -EINVAL;
        }
 
-       if (chan_is_logical(d40c)) {
-               if (config_maxburst >= 16)
-                       psize = STEDMA40_PSIZE_LOG_16;
-               else if (config_maxburst >= 8)
-                       psize = STEDMA40_PSIZE_LOG_8;
-               else if (config_maxburst >= 4)
-                       psize = STEDMA40_PSIZE_LOG_4;
-               else
-                       psize = STEDMA40_PSIZE_LOG_1;
-       } else {
-               if (config_maxburst >= 16)
-                       psize = STEDMA40_PSIZE_PHY_16;
-               else if (config_maxburst >= 8)
-                       psize = STEDMA40_PSIZE_PHY_8;
-               else if (config_maxburst >= 4)
-                       psize = STEDMA40_PSIZE_PHY_4;
-               else if (config_maxburst >= 2)
-                       psize = STEDMA40_PSIZE_PHY_2;
-               else
-                       psize = STEDMA40_PSIZE_PHY_1;
-       }
+       ret = dma40_config_to_halfchannel(d40c, &cfg->src_info,
+                                         src_addr_width,
+                                         src_maxburst);
+       if (ret)
+               return ret;
 
-       /* Set up all the endpoint configs */
-       cfg->src_info.data_width = addr_width;
-       cfg->src_info.psize = psize;
-       cfg->src_info.big_endian = false;
-       cfg->src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL;
-       cfg->dst_info.data_width = addr_width;
-       cfg->dst_info.psize = psize;
-       cfg->dst_info.big_endian = false;
-       cfg->dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL;
+       ret = dma40_config_to_halfchannel(d40c, &cfg->dst_info,
+                                         dst_addr_width,
+                                         dst_maxburst);
+       if (ret)
+               return ret;
 
        /* Fill in register values */
        if (chan_is_logical(d40c))
@@ -2282,12 +2338,14 @@ static void d40_set_runtime_config(struct dma_chan *chan,
        d40c->runtime_addr = config_addr;
        d40c->runtime_direction = config->direction;
        dev_dbg(d40c->base->dev,
-               "configured channel %s for %s, data width %d, "
-               "maxburst %d bytes, LE, no flow control\n",
+               "configured channel %s for %s, data width %d/%d, "
+               "maxburst %d/%d elements, LE, no flow control\n",
                dma_chan_name(chan),
                (config->direction == DMA_FROM_DEVICE) ? "RX" : "TX",
-               config_addr_width,
-               config_maxburst);
+               src_addr_width, dst_addr_width,
+               src_maxburst, dst_maxburst);
+
+       return 0;
 }
 
 static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
@@ -2308,9 +2366,8 @@ static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
        case DMA_RESUME:
                return d40_resume(d40c);
        case DMA_SLAVE_CONFIG:
-               d40_set_runtime_config(chan,
+               return d40_set_runtime_config(chan,
                        (struct dma_slave_config *) arg);
-               return 0;
        default:
                break;
        }
@@ -2341,6 +2398,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma,
 
                INIT_LIST_HEAD(&d40c->active);
                INIT_LIST_HEAD(&d40c->queue);
+               INIT_LIST_HEAD(&d40c->pending_queue);
                INIT_LIST_HEAD(&d40c->client);
 
                tasklet_init(&d40c->tasklet, dma_tasklet,
@@ -2502,25 +2560,6 @@ static int __init d40_phy_res_init(struct d40_base *base)
 
 static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
 {
-       static const struct d40_reg_val dma_id_regs[] = {
-               /* Peripheral Id */
-               { .reg = D40_DREG_PERIPHID0, .val = 0x0040},
-               { .reg = D40_DREG_PERIPHID1, .val = 0x0000},
-               /*
-                * D40_DREG_PERIPHID2 Depends on HW revision:
-                *  DB8500ed has 0x0008,
-                *  ? has 0x0018,
-                *  DB8500v1 has 0x0028
-                *  DB8500v2 has 0x0038
-                */
-               { .reg = D40_DREG_PERIPHID3, .val = 0x0000},
-
-               /* PCell Id */
-               { .reg = D40_DREG_CELLID0, .val = 0x000d},
-               { .reg = D40_DREG_CELLID1, .val = 0x00f0},
-               { .reg = D40_DREG_CELLID2, .val = 0x0005},
-               { .reg = D40_DREG_CELLID3, .val = 0x00b1}
-       };
        struct stedma40_platform_data *plat_data;
        struct clk *clk = NULL;
        void __iomem *virtbase = NULL;
@@ -2529,8 +2568,9 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
        int num_log_chans = 0;
        int num_phy_chans;
        int i;
-       u32 val;
-       u32 rev;
+       u32 pid;
+       u32 cid;
+       u8 rev;
 
        clk = clk_get(&pdev->dev, NULL);
 
@@ -2554,32 +2594,32 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
        if (!virtbase)
                goto failure;
 
-       /* HW version check */
-       for (i = 0; i < ARRAY_SIZE(dma_id_regs); i++) {
-               if (dma_id_regs[i].val !=
-                   readl(virtbase + dma_id_regs[i].reg)) {
-                       d40_err(&pdev->dev,
-                               "Unknown hardware! Expected 0x%x at 0x%x but got 0x%x\n",
-                               dma_id_regs[i].val,
-                               dma_id_regs[i].reg,
-                               readl(virtbase + dma_id_regs[i].reg));
-                       goto failure;
-               }
-       }
+       /* This is just a regular AMBA PrimeCell ID actually */
+       for (pid = 0, i = 0; i < 4; i++)
+               pid |= (readl(virtbase + resource_size(res) - 0x20 + 4 * i)
+                       & 255) << (i * 8);
+       for (cid = 0, i = 0; i < 4; i++)
+               cid |= (readl(virtbase + resource_size(res) - 0x10 + 4 * i)
+                       & 255) << (i * 8);
 
-       /* Get silicon revision and designer */
-       val = readl(virtbase + D40_DREG_PERIPHID2);
-
-       if ((val & D40_DREG_PERIPHID2_DESIGNER_MASK) !=
-           D40_HW_DESIGNER) {
+       if (cid != AMBA_CID) {
+               d40_err(&pdev->dev, "Unknown hardware! No PrimeCell ID\n");
+               goto failure;
+       }
+       if (AMBA_MANF_BITS(pid) != AMBA_VENDOR_ST) {
                d40_err(&pdev->dev, "Unknown designer! Got %x wanted %x\n",
-                       val & D40_DREG_PERIPHID2_DESIGNER_MASK,
-                       D40_HW_DESIGNER);
+                       AMBA_MANF_BITS(pid),
+                       AMBA_VENDOR_ST);
                goto failure;
        }
-
-       rev = (val & D40_DREG_PERIPHID2_REV_MASK) >>
-               D40_DREG_PERIPHID2_REV_POS;
+       /*
+        * HW revision:
+        * DB8500ed has revision 0
+        * ? has revision 1
+        * DB8500v1 has revision 2
+        * DB8500v2 has revision 3
+        */
+       rev = AMBA_REV_BITS(pid);
 
        /* The number of physical channels on this HW */
        num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4;
index 195ee65..b44c455 100644 (file)
 #define D40_DREG_PERIPHID0     0xFE0
 #define D40_DREG_PERIPHID1     0xFE4
 #define D40_DREG_PERIPHID2     0xFE8
-#define D40_DREG_PERIPHID2_REV_POS 4
-#define D40_DREG_PERIPHID2_REV_MASK (0xf << D40_DREG_PERIPHID2_REV_POS)
-#define D40_DREG_PERIPHID2_DESIGNER_MASK 0xf
 #define D40_DREG_PERIPHID3     0xFEC
 #define D40_DREG_CELLID0       0xFF0
 #define D40_DREG_CELLID1       0xFF4
index 30da70d..cdae207 100644 (file)
@@ -45,13 +45,13 @@ static int __init pci_eisa_init(struct pci_dev *pdev,
        return 0;
 }
 
-static struct pci_device_id __initdata pci_eisa_pci_tbl[] = {
+static struct pci_device_id pci_eisa_pci_tbl[] = {
        { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
          PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 },
        { 0, }
 };
 
-static struct pci_driver __initdata pci_eisa_driver = {
+static struct pci_driver __refdata pci_eisa_driver = {
        .name           = "pci_eisa",
        .id_table       = pci_eisa_pci_tbl,
        .probe          = pci_eisa_init,
index 5f29aaf..eb80b54 100644 (file)
@@ -78,6 +78,7 @@
 #include <linux/kobject.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <linux/pstore.h>
 
 #include <asm/uaccess.h>
 
@@ -89,6 +90,8 @@ MODULE_DESCRIPTION("sysfs interface to EFI Variables");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(EFIVARS_VERSION);
 
+#define DUMP_NAME_LEN 52
+
 /*
  * The maximum size of VariableName + Data = 1024
  * Therefore, it's reasonable to save that much
@@ -119,6 +122,10 @@ struct efivar_attribute {
        ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
 };
 
+#define PSTORE_EFI_ATTRIBUTES \
+       (EFI_VARIABLE_NON_VOLATILE | \
+        EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+        EFI_VARIABLE_RUNTIME_ACCESS)
 
 #define EFIVAR_ATTR(_name, _mode, _show, _store) \
 struct efivar_attribute efivar_attr_##_name = { \
@@ -141,38 +148,72 @@ efivar_create_sysfs_entry(struct efivars *efivars,
 
 /* Return the number of unicode characters in data */
 static unsigned long
-utf8_strlen(efi_char16_t *data, unsigned long maxlength)
+utf16_strnlen(efi_char16_t *s, size_t maxlength)
 {
        unsigned long length = 0;
 
-       while (*data++ != 0 && length < maxlength)
+       while (*s++ != 0 && length < maxlength)
                length++;
        return length;
 }
 
+static inline unsigned long
+utf16_strlen(efi_char16_t *s)
+{
+       return utf16_strnlen(s, ~0UL);
+}
+
 /*
  * Return the number of bytes is the length of this string
  * Note: this is NOT the same as the number of unicode characters
  */
 static inline unsigned long
-utf8_strsize(efi_char16_t *data, unsigned long maxlength)
+utf16_strsize(efi_char16_t *data, unsigned long maxlength)
 {
-       return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
+       return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
+}
+
+static inline int
+utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len)
+{
+       while (1) {
+               if (len == 0)
+                       return 0;
+               if (*a < *b)
+                       return -1;
+               if (*a > *b)
+                       return 1;
+               if (*a == 0) /* implies *b == 0 */
+                       return 0;
+               a++;
+               b++;
+               len--;
+       }
 }
 
 static efi_status_t
-get_var_data(struct efivars *efivars, struct efi_variable *var)
+get_var_data_locked(struct efivars *efivars, struct efi_variable *var)
 {
        efi_status_t status;
 
-       spin_lock(&efivars->lock);
        var->DataSize = 1024;
        status = efivars->ops->get_variable(var->VariableName,
                                            &var->VendorGuid,
                                            &var->Attributes,
                                            &var->DataSize,
                                            var->Data);
+       return status;
+}
+
+static efi_status_t
+get_var_data(struct efivars *efivars, struct efi_variable *var)
+{
+       efi_status_t status;
+
+       spin_lock(&efivars->lock);
+       status = get_var_data_locked(efivars, var);
        spin_unlock(&efivars->lock);
+
        if (status != EFI_SUCCESS) {
                printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
                        status);
@@ -387,12 +428,180 @@ static struct kobj_type efivar_ktype = {
        .default_attrs = def_attrs,
 };
 
+static struct pstore_info efi_pstore_info;
+
 static inline void
 efivar_unregister(struct efivar_entry *var)
 {
        kobject_put(&var->kobj);
 }
 
+#ifdef CONFIG_PSTORE
+
+static int efi_pstore_open(struct pstore_info *psi)
+{
+       struct efivars *efivars = psi->data;
+
+       spin_lock(&efivars->lock);
+       efivars->walk_entry = list_first_entry(&efivars->list,
+                                              struct efivar_entry, list);
+       return 0;
+}
+
+static int efi_pstore_close(struct pstore_info *psi)
+{
+       struct efivars *efivars = psi->data;
+
+       spin_unlock(&efivars->lock);
+       return 0;
+}
+
+static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
+                              struct timespec *timespec, struct pstore_info *psi)
+{
+       efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
+       struct efivars *efivars = psi->data;
+       char name[DUMP_NAME_LEN];
+       int i;
+       unsigned int part, size;
+       unsigned long time;
+
+       while (&efivars->walk_entry->list != &efivars->list) {
+               if (!efi_guidcmp(efivars->walk_entry->var.VendorGuid,
+                                vendor)) {
+                       for (i = 0; i < DUMP_NAME_LEN; i++) {
+                               name[i] = efivars->walk_entry->var.VariableName[i];
+                       }
+                       if (sscanf(name, "dump-type%u-%u-%lu", type, &part, &time) == 3) {
+                               *id = part;
+                               timespec->tv_sec = time;
+                               timespec->tv_nsec = 0;
+                               get_var_data_locked(efivars, &efivars->walk_entry->var);
+                               size = efivars->walk_entry->var.DataSize;
+                               memcpy(psi->buf, efivars->walk_entry->var.Data, size);
+                               efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
+                                                  struct efivar_entry, list);
+                               return size;
+                       }
+               }
+               efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
+                                                struct efivar_entry, list);
+       }
+       return 0;
+}
+
+static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
+                           size_t size, struct pstore_info *psi)
+{
+       char name[DUMP_NAME_LEN];
+       char stub_name[DUMP_NAME_LEN];
+       efi_char16_t efi_name[DUMP_NAME_LEN];
+       efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
+       struct efivars *efivars = psi->data;
+       struct efivar_entry *entry, *found = NULL;
+       int i;
+
+       sprintf(stub_name, "dump-type%u-%u-", type, part);
+       sprintf(name, "%s%lu", stub_name, get_seconds());
+
+       spin_lock(&efivars->lock);
+
+       for (i = 0; i < DUMP_NAME_LEN; i++)
+               efi_name[i] = stub_name[i];
+
+       /*
+        * Clean up any entries with the same name
+        */
+
+       list_for_each_entry(entry, &efivars->list, list) {
+               get_var_data_locked(efivars, &entry->var);
+
+               if (efi_guidcmp(entry->var.VendorGuid, vendor))
+                       continue;
+               if (utf16_strncmp(entry->var.VariableName, efi_name,
+                                 utf16_strlen(efi_name)))
+                       continue;
+               /* Needs to be a prefix */
+               if (entry->var.VariableName[utf16_strlen(efi_name)] == 0)
+                       continue;
+
+               /* found */
+               found = entry;
+               efivars->ops->set_variable(entry->var.VariableName,
+                                          &entry->var.VendorGuid,
+                                          PSTORE_EFI_ATTRIBUTES,
+                                          0, NULL);
+       }
+
+       if (found)
+               list_del(&found->list);
+
+       for (i = 0; i < DUMP_NAME_LEN; i++)
+               efi_name[i] = name[i];
+
+       efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES,
+                                  size, psi->buf);
+
+       spin_unlock(&efivars->lock);
+
+       if (found)
+               efivar_unregister(found);
+
+       if (size)
+               efivar_create_sysfs_entry(efivars,
+                                         utf16_strsize(efi_name,
+                                                       DUMP_NAME_LEN * 2),
+                                         efi_name, &vendor);
+
+       return part;
+};
+
+static int efi_pstore_erase(enum pstore_type_id type, u64 id,
+                           struct pstore_info *psi)
+{
+       efi_pstore_write(type, id, 0, psi);
+
+       return 0;
+}
+#else
+static int efi_pstore_open(struct pstore_info *psi)
+{
+       return 0;
+}
+
+static int efi_pstore_close(struct pstore_info *psi)
+{
+       return 0;
+}
+
+static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
+                              struct timespec *time, struct pstore_info *psi)
+{
+       return -1;
+}
+
+static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
+                           size_t size, struct pstore_info *psi)
+{
+       return 0;
+}
+
+static int efi_pstore_erase(enum pstore_type_id type, u64 id,
+                           struct pstore_info *psi)
+{
+       return 0;
+}
+#endif
+
+static struct pstore_info efi_pstore_info = {
+       .owner          = THIS_MODULE,
+       .name           = "efi",
+       .open           = efi_pstore_open,
+       .close          = efi_pstore_close,
+       .read           = efi_pstore_read,
+       .write          = efi_pstore_write,
+       .erase          = efi_pstore_erase,
+};
 
 static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
                             struct bin_attribute *bin_attr,
@@ -414,8 +623,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
         * Does this variable already exist?
         */
        list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
-               strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
-               strsize2 = utf8_strsize(new_var->VariableName, 1024);
+               strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
+               strsize2 = utf16_strsize(new_var->VariableName, 1024);
                if (strsize1 == strsize2 &&
                        !memcmp(&(search_efivar->var.VariableName),
                                new_var->VariableName, strsize1) &&
@@ -447,8 +656,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
 
        /* Create the entry in sysfs.  Locking is not required here */
        status = efivar_create_sysfs_entry(efivars,
-                                          utf8_strsize(new_var->VariableName,
-                                                       1024),
+                                          utf16_strsize(new_var->VariableName,
+                                                        1024),
                                           new_var->VariableName,
                                           &new_var->VendorGuid);
        if (status) {
@@ -477,8 +686,8 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
         * Does this variable already exist?
         */
        list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
-               strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
-               strsize2 = utf8_strsize(del_var->VariableName, 1024);
+               strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
+               strsize2 = utf16_strsize(del_var->VariableName, 1024);
                if (strsize1 == strsize2 &&
                        !memcmp(&(search_efivar->var.VariableName),
                                del_var->VariableName, strsize1) &&
@@ -763,6 +972,16 @@ int register_efivars(struct efivars *efivars,
        if (error)
                unregister_efivars(efivars);
 
+       efivars->efi_pstore_info = efi_pstore_info;
+
+       efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
+       if (efivars->efi_pstore_info.buf) {
+               efivars->efi_pstore_info.bufsize = 1024;
+               efivars->efi_pstore_info.data = efivars;
+               mutex_init(&efivars->efi_pstore_info.buf_mutex);
+               pstore_register(&efivars->efi_pstore_info);
+       }
+
 out:
        kfree(variable_name);
 
index 3634986..d539efd 100644 (file)
@@ -103,6 +103,22 @@ config GPIO_MPC5200
        def_bool y
        depends on PPC_MPC52xx
 
+config GPIO_MSM_V1
+       tristate "Qualcomm MSM GPIO v1"
+       depends on GPIOLIB && ARCH_MSM
+       help
+         Say yes here to support the GPIO interface on ARM v6 based
+         Qualcomm MSM chips.  Most of the pins on the MSM can be
+         selected for GPIO, and are controlled by this driver.
+
+config GPIO_MSM_V2
+       tristate "Qualcomm MSM GPIO v2"
+       depends on GPIOLIB && ARCH_MSM
+       help
+         Say yes here to support the GPIO interface on ARM v7 based
+         Qualcomm MSM chips.  Most of the pins on the MSM can be
+         selected for GPIO, and are controlled by this driver.
+
 config GPIO_MXC
        def_bool y
        depends on ARCH_MXC
@@ -280,6 +296,12 @@ config GPIO_TC3589X
          This enables support for the GPIOs found on the TC3589X
          I/O Expander.
 
+config GPIO_TPS65912
+       tristate "TI TPS65912 GPIO"
+       depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
+       help
+         This driver supports TPS65912 gpio chip
+
 config GPIO_TWL4030
        tristate "TWL4030, TWL5030, and TPS659x0 GPIOs"
        depends on TWL4030_CORE
index 7207112..9588948 100644 (file)
@@ -27,6 +27,8 @@ obj-$(CONFIG_GPIO_MC33880)    += gpio-mc33880.o
 obj-$(CONFIG_GPIO_MCP23S08)    += gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)      += gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MPC5200)     += gpio-mpc5200.o
+obj-$(CONFIG_GPIO_MSM_V1)      += gpio-msm-v1.o
+obj-$(CONFIG_GPIO_MSM_V2)      += gpio-msm-v2.o
 obj-$(CONFIG_GPIO_MXC)         += gpio-mxc.o
 obj-$(CONFIG_GPIO_MXS)         += gpio-mxs.o
 obj-$(CONFIG_PLAT_NOMADIK)     += gpio-nomadik.o
@@ -48,6 +50,7 @@ obj-$(CONFIG_GPIO_TC3589X)    += gpio-tc3589x.o
 obj-$(CONFIG_ARCH_TEGRA)       += gpio-tegra.o
 obj-$(CONFIG_GPIO_TIMBERDALE)  += gpio-timberdale.o
 obj-$(CONFIG_GPIO_TPS65910)    += gpio-tps65910.o
+obj-$(CONFIG_GPIO_TPS65912)    += gpio-tps65912.o
 obj-$(CONFIG_GPIO_TWL4030)     += gpio-twl4030.o
 obj-$(CONFIG_MACH_U300)                += gpio-u300.o
 obj-$(CONFIG_GPIO_UCB1400)     += gpio-ucb1400.o
index ed795e6..050c05d 100644 (file)
@@ -516,5 +516,5 @@ module_exit(ab8500_gpio_exit);
 
 MODULE_AUTHOR("BIBEK BASU <bibek.basu@stericsson.com>");
 MODULE_DESCRIPTION("Driver allows to use AB8500 unused pins to be used as GPIO");
-MODULE_ALIAS("AB8500 GPIO driver");
+MODULE_ALIAS("platform:ab8500-gpio");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-msm-v1.c b/drivers/gpio/gpio-msm-v1.c
new file mode 100644 (file)
index 0000000..52a4d42
--- /dev/null
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <mach/cpu.h>
+#include <mach/msm_gpiomux.h>
+#include <mach/msm_iomap.h>
+
+/* see 80-VA736-2 Rev C pp 695-751
+**
+** These are actually the *shadow* gpio registers, since the
+** real ones (which allow full access) are only available to the
+** ARM9 side of the world.
+**
+** Since the _BASE need to be page-aligned when we're mapping them
+** to virtual addresses, adjust for the additional offset in these
+** macros.
+*/
+
+#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + (off))
+#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off))
+#define MSM_GPIO1_SHADOW_REG(off) (MSM_GPIO1_BASE + 0x800 + (off))
+#define MSM_GPIO2_SHADOW_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off))
+
+/*
+ * MSM7X00 registers
+ */
+/* output value */
+#define MSM7X00_GPIO_OUT_0     MSM_GPIO1_SHADOW_REG(0x00)  /* gpio  15-0  */
+#define MSM7X00_GPIO_OUT_1     MSM_GPIO2_SHADOW_REG(0x00)  /* gpio  42-16 */
+#define MSM7X00_GPIO_OUT_2     MSM_GPIO1_SHADOW_REG(0x04)  /* gpio  67-43 */
+#define MSM7X00_GPIO_OUT_3     MSM_GPIO1_SHADOW_REG(0x08)  /* gpio  94-68 */
+#define MSM7X00_GPIO_OUT_4     MSM_GPIO1_SHADOW_REG(0x0C)  /* gpio 106-95 */
+#define MSM7X00_GPIO_OUT_5     MSM_GPIO1_SHADOW_REG(0x50)  /* gpio 107-121 */
+
+/* same pin map as above, output enable */
+#define MSM7X00_GPIO_OE_0      MSM_GPIO1_SHADOW_REG(0x10)
+#define MSM7X00_GPIO_OE_1      MSM_GPIO2_SHADOW_REG(0x08)
+#define MSM7X00_GPIO_OE_2      MSM_GPIO1_SHADOW_REG(0x14)
+#define MSM7X00_GPIO_OE_3      MSM_GPIO1_SHADOW_REG(0x18)
+#define MSM7X00_GPIO_OE_4      MSM_GPIO1_SHADOW_REG(0x1C)
+#define MSM7X00_GPIO_OE_5      MSM_GPIO1_SHADOW_REG(0x54)
+
+/* same pin map as above, input read */
+#define MSM7X00_GPIO_IN_0      MSM_GPIO1_SHADOW_REG(0x34)
+#define MSM7X00_GPIO_IN_1      MSM_GPIO2_SHADOW_REG(0x20)
+#define MSM7X00_GPIO_IN_2      MSM_GPIO1_SHADOW_REG(0x38)
+#define MSM7X00_GPIO_IN_3      MSM_GPIO1_SHADOW_REG(0x3C)
+#define MSM7X00_GPIO_IN_4      MSM_GPIO1_SHADOW_REG(0x40)
+#define MSM7X00_GPIO_IN_5      MSM_GPIO1_SHADOW_REG(0x44)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM7X00_GPIO_INT_EDGE_0        MSM_GPIO1_SHADOW_REG(0x60)
+#define MSM7X00_GPIO_INT_EDGE_1        MSM_GPIO2_SHADOW_REG(0x50)
+#define MSM7X00_GPIO_INT_EDGE_2        MSM_GPIO1_SHADOW_REG(0x64)
+#define MSM7X00_GPIO_INT_EDGE_3        MSM_GPIO1_SHADOW_REG(0x68)
+#define MSM7X00_GPIO_INT_EDGE_4        MSM_GPIO1_SHADOW_REG(0x6C)
+#define MSM7X00_GPIO_INT_EDGE_5        MSM_GPIO1_SHADOW_REG(0xC0)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM7X00_GPIO_INT_POS_0 MSM_GPIO1_SHADOW_REG(0x70)
+#define MSM7X00_GPIO_INT_POS_1 MSM_GPIO2_SHADOW_REG(0x58)
+#define MSM7X00_GPIO_INT_POS_2 MSM_GPIO1_SHADOW_REG(0x74)
+#define MSM7X00_GPIO_INT_POS_3 MSM_GPIO1_SHADOW_REG(0x78)
+#define MSM7X00_GPIO_INT_POS_4 MSM_GPIO1_SHADOW_REG(0x7C)
+#define MSM7X00_GPIO_INT_POS_5 MSM_GPIO1_SHADOW_REG(0xBC)
+
+/* same pin map as above, interrupt enable */
+#define MSM7X00_GPIO_INT_EN_0  MSM_GPIO1_SHADOW_REG(0x80)
+#define MSM7X00_GPIO_INT_EN_1  MSM_GPIO2_SHADOW_REG(0x60)
+#define MSM7X00_GPIO_INT_EN_2  MSM_GPIO1_SHADOW_REG(0x84)
+#define MSM7X00_GPIO_INT_EN_3  MSM_GPIO1_SHADOW_REG(0x88)
+#define MSM7X00_GPIO_INT_EN_4  MSM_GPIO1_SHADOW_REG(0x8C)
+#define MSM7X00_GPIO_INT_EN_5  MSM_GPIO1_SHADOW_REG(0xB8)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM7X00_GPIO_INT_CLEAR_0       MSM_GPIO1_SHADOW_REG(0x90)
+#define MSM7X00_GPIO_INT_CLEAR_1       MSM_GPIO2_SHADOW_REG(0x68)
+#define MSM7X00_GPIO_INT_CLEAR_2       MSM_GPIO1_SHADOW_REG(0x94)
+#define MSM7X00_GPIO_INT_CLEAR_3       MSM_GPIO1_SHADOW_REG(0x98)
+#define MSM7X00_GPIO_INT_CLEAR_4       MSM_GPIO1_SHADOW_REG(0x9C)
+#define MSM7X00_GPIO_INT_CLEAR_5       MSM_GPIO1_SHADOW_REG(0xB4)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM7X00_GPIO_INT_STATUS_0      MSM_GPIO1_SHADOW_REG(0xA0)
+#define MSM7X00_GPIO_INT_STATUS_1      MSM_GPIO2_SHADOW_REG(0x70)
+#define MSM7X00_GPIO_INT_STATUS_2      MSM_GPIO1_SHADOW_REG(0xA4)
+#define MSM7X00_GPIO_INT_STATUS_3      MSM_GPIO1_SHADOW_REG(0xA8)
+#define MSM7X00_GPIO_INT_STATUS_4      MSM_GPIO1_SHADOW_REG(0xAC)
+#define MSM7X00_GPIO_INT_STATUS_5      MSM_GPIO1_SHADOW_REG(0xB0)
+
+/*
+ * QSD8X50 registers
+ */
+/* output value */
+#define QSD8X50_GPIO_OUT_0     MSM_GPIO1_SHADOW_REG(0x00)  /* gpio  15-0   */
+#define QSD8X50_GPIO_OUT_1     MSM_GPIO2_SHADOW_REG(0x00)  /* gpio  42-16  */
+#define QSD8X50_GPIO_OUT_2     MSM_GPIO1_SHADOW_REG(0x04)  /* gpio  67-43  */
+#define QSD8X50_GPIO_OUT_3     MSM_GPIO1_SHADOW_REG(0x08)  /* gpio  94-68  */
+#define QSD8X50_GPIO_OUT_4     MSM_GPIO1_SHADOW_REG(0x0C)  /* gpio 103-95  */
+#define QSD8X50_GPIO_OUT_5     MSM_GPIO1_SHADOW_REG(0x10)  /* gpio 121-104 */
+#define QSD8X50_GPIO_OUT_6     MSM_GPIO1_SHADOW_REG(0x14)  /* gpio 152-122 */
+#define QSD8X50_GPIO_OUT_7     MSM_GPIO1_SHADOW_REG(0x18)  /* gpio 164-153 */
+
+/* same pin map as above, output enable */
+#define QSD8X50_GPIO_OE_0      MSM_GPIO1_SHADOW_REG(0x20)
+#define QSD8X50_GPIO_OE_1      MSM_GPIO2_SHADOW_REG(0x08)
+#define QSD8X50_GPIO_OE_2      MSM_GPIO1_SHADOW_REG(0x24)
+#define QSD8X50_GPIO_OE_3      MSM_GPIO1_SHADOW_REG(0x28)
+#define QSD8X50_GPIO_OE_4      MSM_GPIO1_SHADOW_REG(0x2C)
+#define QSD8X50_GPIO_OE_5      MSM_GPIO1_SHADOW_REG(0x30)
+#define QSD8X50_GPIO_OE_6      MSM_GPIO1_SHADOW_REG(0x34)
+#define QSD8X50_GPIO_OE_7      MSM_GPIO1_SHADOW_REG(0x38)
+
+/* same pin map as above, input read */
+#define QSD8X50_GPIO_IN_0      MSM_GPIO1_SHADOW_REG(0x50)
+#define QSD8X50_GPIO_IN_1      MSM_GPIO2_SHADOW_REG(0x20)
+#define QSD8X50_GPIO_IN_2      MSM_GPIO1_SHADOW_REG(0x54)
+#define QSD8X50_GPIO_IN_3      MSM_GPIO1_SHADOW_REG(0x58)
+#define QSD8X50_GPIO_IN_4      MSM_GPIO1_SHADOW_REG(0x5C)
+#define QSD8X50_GPIO_IN_5      MSM_GPIO1_SHADOW_REG(0x60)
+#define QSD8X50_GPIO_IN_6      MSM_GPIO1_SHADOW_REG(0x64)
+#define QSD8X50_GPIO_IN_7      MSM_GPIO1_SHADOW_REG(0x68)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define QSD8X50_GPIO_INT_EDGE_0        MSM_GPIO1_SHADOW_REG(0x70)
+#define QSD8X50_GPIO_INT_EDGE_1        MSM_GPIO2_SHADOW_REG(0x50)
+#define QSD8X50_GPIO_INT_EDGE_2        MSM_GPIO1_SHADOW_REG(0x74)
+#define QSD8X50_GPIO_INT_EDGE_3        MSM_GPIO1_SHADOW_REG(0x78)
+#define QSD8X50_GPIO_INT_EDGE_4        MSM_GPIO1_SHADOW_REG(0x7C)
+#define QSD8X50_GPIO_INT_EDGE_5        MSM_GPIO1_SHADOW_REG(0x80)
+#define QSD8X50_GPIO_INT_EDGE_6        MSM_GPIO1_SHADOW_REG(0x84)
+#define QSD8X50_GPIO_INT_EDGE_7        MSM_GPIO1_SHADOW_REG(0x88)
+
+/* same pin map as above, 1=positive 0=negative */
+#define QSD8X50_GPIO_INT_POS_0 MSM_GPIO1_SHADOW_REG(0x90)
+#define QSD8X50_GPIO_INT_POS_1 MSM_GPIO2_SHADOW_REG(0x58)
+#define QSD8X50_GPIO_INT_POS_2 MSM_GPIO1_SHADOW_REG(0x94)
+#define QSD8X50_GPIO_INT_POS_3 MSM_GPIO1_SHADOW_REG(0x98)
+#define QSD8X50_GPIO_INT_POS_4 MSM_GPIO1_SHADOW_REG(0x9C)
+#define QSD8X50_GPIO_INT_POS_5 MSM_GPIO1_SHADOW_REG(0xA0)
+#define QSD8X50_GPIO_INT_POS_6 MSM_GPIO1_SHADOW_REG(0xA4)
+#define QSD8X50_GPIO_INT_POS_7 MSM_GPIO1_SHADOW_REG(0xA8)
+
+/* same pin map as above, interrupt enable */
+#define QSD8X50_GPIO_INT_EN_0  MSM_GPIO1_SHADOW_REG(0xB0)
+#define QSD8X50_GPIO_INT_EN_1  MSM_GPIO2_SHADOW_REG(0x60)
+#define QSD8X50_GPIO_INT_EN_2  MSM_GPIO1_SHADOW_REG(0xB4)
+#define QSD8X50_GPIO_INT_EN_3  MSM_GPIO1_SHADOW_REG(0xB8)
+#define QSD8X50_GPIO_INT_EN_4  MSM_GPIO1_SHADOW_REG(0xBC)
+#define QSD8X50_GPIO_INT_EN_5  MSM_GPIO1_SHADOW_REG(0xC0)
+#define QSD8X50_GPIO_INT_EN_6  MSM_GPIO1_SHADOW_REG(0xC4)
+#define QSD8X50_GPIO_INT_EN_7  MSM_GPIO1_SHADOW_REG(0xC8)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define QSD8X50_GPIO_INT_CLEAR_0       MSM_GPIO1_SHADOW_REG(0xD0)
+#define QSD8X50_GPIO_INT_CLEAR_1       MSM_GPIO2_SHADOW_REG(0x68)
+#define QSD8X50_GPIO_INT_CLEAR_2       MSM_GPIO1_SHADOW_REG(0xD4)
+#define QSD8X50_GPIO_INT_CLEAR_3       MSM_GPIO1_SHADOW_REG(0xD8)
+#define QSD8X50_GPIO_INT_CLEAR_4       MSM_GPIO1_SHADOW_REG(0xDC)
+#define QSD8X50_GPIO_INT_CLEAR_5       MSM_GPIO1_SHADOW_REG(0xE0)
+#define QSD8X50_GPIO_INT_CLEAR_6       MSM_GPIO1_SHADOW_REG(0xE4)
+#define QSD8X50_GPIO_INT_CLEAR_7       MSM_GPIO1_SHADOW_REG(0xE8)
+
+/* same pin map as above, 1=interrupt pending */
+#define QSD8X50_GPIO_INT_STATUS_0      MSM_GPIO1_SHADOW_REG(0xF0)
+#define QSD8X50_GPIO_INT_STATUS_1      MSM_GPIO2_SHADOW_REG(0x70)
+#define QSD8X50_GPIO_INT_STATUS_2      MSM_GPIO1_SHADOW_REG(0xF4)
+#define QSD8X50_GPIO_INT_STATUS_3      MSM_GPIO1_SHADOW_REG(0xF8)
+#define QSD8X50_GPIO_INT_STATUS_4      MSM_GPIO1_SHADOW_REG(0xFC)
+#define QSD8X50_GPIO_INT_STATUS_5      MSM_GPIO1_SHADOW_REG(0x100)
+#define QSD8X50_GPIO_INT_STATUS_6      MSM_GPIO1_SHADOW_REG(0x104)
+#define QSD8X50_GPIO_INT_STATUS_7      MSM_GPIO1_SHADOW_REG(0x108)
+
+/*
+ * MSM7X30 registers
+ */
+/* output value */
+#define MSM7X30_GPIO_OUT_0     MSM_GPIO1_REG(0x00)   /* gpio  15-0   */
+#define MSM7X30_GPIO_OUT_1     MSM_GPIO2_REG(0x00)   /* gpio  43-16  */
+#define MSM7X30_GPIO_OUT_2     MSM_GPIO1_REG(0x04)   /* gpio  67-44  */
+#define MSM7X30_GPIO_OUT_3     MSM_GPIO1_REG(0x08)   /* gpio  94-68  */
+#define MSM7X30_GPIO_OUT_4     MSM_GPIO1_REG(0x0C)   /* gpio 106-95  */
+#define MSM7X30_GPIO_OUT_5     MSM_GPIO1_REG(0x50)   /* gpio 133-107 */
+#define MSM7X30_GPIO_OUT_6     MSM_GPIO1_REG(0xC4)   /* gpio 150-134 */
+#define MSM7X30_GPIO_OUT_7     MSM_GPIO1_REG(0x214)  /* gpio 181-151 */
+
+/* same pin map as above, output enable */
+#define MSM7X30_GPIO_OE_0      MSM_GPIO1_REG(0x10)
+#define MSM7X30_GPIO_OE_1      MSM_GPIO2_REG(0x08)
+#define MSM7X30_GPIO_OE_2      MSM_GPIO1_REG(0x14)
+#define MSM7X30_GPIO_OE_3      MSM_GPIO1_REG(0x18)
+#define MSM7X30_GPIO_OE_4      MSM_GPIO1_REG(0x1C)
+#define MSM7X30_GPIO_OE_5      MSM_GPIO1_REG(0x54)
+#define MSM7X30_GPIO_OE_6      MSM_GPIO1_REG(0xC8)
+#define MSM7X30_GPIO_OE_7      MSM_GPIO1_REG(0x218)
+
+/* same pin map as above, input read */
+#define MSM7X30_GPIO_IN_0      MSM_GPIO1_REG(0x34)
+#define MSM7X30_GPIO_IN_1      MSM_GPIO2_REG(0x20)
+#define MSM7X30_GPIO_IN_2      MSM_GPIO1_REG(0x38)
+#define MSM7X30_GPIO_IN_3      MSM_GPIO1_REG(0x3C)
+#define MSM7X30_GPIO_IN_4      MSM_GPIO1_REG(0x40)
+#define MSM7X30_GPIO_IN_5      MSM_GPIO1_REG(0x44)
+#define MSM7X30_GPIO_IN_6      MSM_GPIO1_REG(0xCC)
+#define MSM7X30_GPIO_IN_7      MSM_GPIO1_REG(0x21C)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM7X30_GPIO_INT_EDGE_0        MSM_GPIO1_REG(0x60)
+#define MSM7X30_GPIO_INT_EDGE_1        MSM_GPIO2_REG(0x50)
+#define MSM7X30_GPIO_INT_EDGE_2        MSM_GPIO1_REG(0x64)
+#define MSM7X30_GPIO_INT_EDGE_3        MSM_GPIO1_REG(0x68)
+#define MSM7X30_GPIO_INT_EDGE_4        MSM_GPIO1_REG(0x6C)
+#define MSM7X30_GPIO_INT_EDGE_5        MSM_GPIO1_REG(0xC0)
+#define MSM7X30_GPIO_INT_EDGE_6        MSM_GPIO1_REG(0xD0)
+#define MSM7X30_GPIO_INT_EDGE_7        MSM_GPIO1_REG(0x240)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM7X30_GPIO_INT_POS_0 MSM_GPIO1_REG(0x70)
+#define MSM7X30_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58)
+#define MSM7X30_GPIO_INT_POS_2 MSM_GPIO1_REG(0x74)
+#define MSM7X30_GPIO_INT_POS_3 MSM_GPIO1_REG(0x78)
+#define MSM7X30_GPIO_INT_POS_4 MSM_GPIO1_REG(0x7C)
+#define MSM7X30_GPIO_INT_POS_5 MSM_GPIO1_REG(0xBC)
+#define MSM7X30_GPIO_INT_POS_6 MSM_GPIO1_REG(0xD4)
+#define MSM7X30_GPIO_INT_POS_7 MSM_GPIO1_REG(0x228)
+
+/* same pin map as above, interrupt enable */
+#define MSM7X30_GPIO_INT_EN_0  MSM_GPIO1_REG(0x80)
+#define MSM7X30_GPIO_INT_EN_1  MSM_GPIO2_REG(0x60)
+#define MSM7X30_GPIO_INT_EN_2  MSM_GPIO1_REG(0x84)
+#define MSM7X30_GPIO_INT_EN_3  MSM_GPIO1_REG(0x88)
+#define MSM7X30_GPIO_INT_EN_4  MSM_GPIO1_REG(0x8C)
+#define MSM7X30_GPIO_INT_EN_5  MSM_GPIO1_REG(0xB8)
+#define MSM7X30_GPIO_INT_EN_6  MSM_GPIO1_REG(0xD8)
+#define MSM7X30_GPIO_INT_EN_7  MSM_GPIO1_REG(0x22C)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM7X30_GPIO_INT_CLEAR_0       MSM_GPIO1_REG(0x90)
+#define MSM7X30_GPIO_INT_CLEAR_1       MSM_GPIO2_REG(0x68)
+#define MSM7X30_GPIO_INT_CLEAR_2       MSM_GPIO1_REG(0x94)
+#define MSM7X30_GPIO_INT_CLEAR_3       MSM_GPIO1_REG(0x98)
+#define MSM7X30_GPIO_INT_CLEAR_4       MSM_GPIO1_REG(0x9C)
+#define MSM7X30_GPIO_INT_CLEAR_5       MSM_GPIO1_REG(0xB4)
+#define MSM7X30_GPIO_INT_CLEAR_6       MSM_GPIO1_REG(0xDC)
+#define MSM7X30_GPIO_INT_CLEAR_7       MSM_GPIO1_REG(0x230)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM7X30_GPIO_INT_STATUS_0      MSM_GPIO1_REG(0xA0)
+#define MSM7X30_GPIO_INT_STATUS_1      MSM_GPIO2_REG(0x70)
+#define MSM7X30_GPIO_INT_STATUS_2      MSM_GPIO1_REG(0xA4)
+#define MSM7X30_GPIO_INT_STATUS_3      MSM_GPIO1_REG(0xA8)
+#define MSM7X30_GPIO_INT_STATUS_4      MSM_GPIO1_REG(0xAC)
+#define MSM7X30_GPIO_INT_STATUS_5      MSM_GPIO1_REG(0xB0)
+#define MSM7X30_GPIO_INT_STATUS_6      MSM_GPIO1_REG(0xE0)
+#define MSM7X30_GPIO_INT_STATUS_7      MSM_GPIO1_REG(0x234)
+
+#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
+
+#define MSM_GPIO_BANK(soc, bank, first, last)                          \
+       {                                                               \
+               .regs = {                                               \
+                       .out =         soc##_GPIO_OUT_##bank,           \
+                       .in =          soc##_GPIO_IN_##bank,            \
+                       .int_status =  soc##_GPIO_INT_STATUS_##bank,    \
+                       .int_clear =   soc##_GPIO_INT_CLEAR_##bank,     \
+                       .int_en =      soc##_GPIO_INT_EN_##bank,        \
+                       .int_edge =    soc##_GPIO_INT_EDGE_##bank,      \
+                       .int_pos =     soc##_GPIO_INT_POS_##bank,       \
+                       .oe =          soc##_GPIO_OE_##bank,            \
+               },                                                      \
+               .chip = {                                               \
+                       .base = (first),                                \
+                       .ngpio = (last) - (first) + 1,                  \
+                       .get = msm_gpio_get,                            \
+                       .set = msm_gpio_set,                            \
+                       .direction_input = msm_gpio_direction_input,    \
+                       .direction_output = msm_gpio_direction_output,  \
+                       .to_irq = msm_gpio_to_irq,                      \
+                       .request = msm_gpio_request,                    \
+                       .free = msm_gpio_free,                          \
+               }                                                       \
+       }
+
+#define MSM_GPIO_BROKEN_INT_CLEAR 1
+
+struct msm_gpio_regs {
+       void __iomem *out;
+       void __iomem *in;
+       void __iomem *int_status;
+       void __iomem *int_clear;
+       void __iomem *int_en;
+       void __iomem *int_edge;
+       void __iomem *int_pos;
+       void __iomem *oe;
+};
+
+struct msm_gpio_chip {
+       spinlock_t              lock;
+       struct gpio_chip        chip;
+       struct msm_gpio_regs    regs;
+#if MSM_GPIO_BROKEN_INT_CLEAR
+       unsigned                int_status_copy;
+#endif
+       unsigned int            both_edge_detect;
+       unsigned int            int_enable[2]; /* 0: awake, 1: sleep */
+};
+
+static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
+                         unsigned offset, unsigned on)
+{
+       unsigned mask = BIT(offset);
+       unsigned val;
+
+       val = readl(msm_chip->regs.out);
+       if (on)
+               writel(val | mask, msm_chip->regs.out);
+       else
+               writel(val & ~mask, msm_chip->regs.out);
+       return 0;
+}
+
+static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
+{
+       int loop_limit = 100;
+       unsigned pol, val, val2, intstat;
+       do {
+               val = readl(msm_chip->regs.in);
+               pol = readl(msm_chip->regs.int_pos);
+               pol = (pol & ~msm_chip->both_edge_detect) |
+                     (~val & msm_chip->both_edge_detect);
+               writel(pol, msm_chip->regs.int_pos);
+               intstat = readl(msm_chip->regs.int_status);
+               val2 = readl(msm_chip->regs.in);
+               if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
+                       return;
+       } while (loop_limit-- > 0);
+       printk(KERN_ERR "msm_gpio_update_both_edge_detect, "
+              "failed to reach stable state %x != %x\n", val, val2);
+}
+
+static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip,
+                                       unsigned offset)
+{
+       unsigned bit = BIT(offset);
+
+#if MSM_GPIO_BROKEN_INT_CLEAR
+       /* Save interrupts that already triggered before we loose them. */
+       /* Any interrupt that triggers between the read of int_status */
+       /* and the write to int_clear will still be lost though. */
+       msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
+       msm_chip->int_status_copy &= ~bit;
+#endif
+       writel(bit, msm_chip->regs.int_clear);
+       msm_gpio_update_both_edge_detect(msm_chip);
+       return 0;
+}
+
+static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct msm_gpio_chip *msm_chip;
+       unsigned long irq_flags;
+
+       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+       return 0;
+}
+
+static int
+msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct msm_gpio_chip *msm_chip;
+       unsigned long irq_flags;
+
+       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       msm_gpio_write(msm_chip, offset, value);
+       writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+       return 0;
+}
+
+static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct msm_gpio_chip *msm_chip;
+
+       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+       return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0;
+}
+
+static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct msm_gpio_chip *msm_chip;
+       unsigned long irq_flags;
+
+       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       msm_gpio_write(msm_chip, offset, value);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       return MSM_GPIO_TO_INT(chip->base + offset);
+}
+
+#ifdef CONFIG_MSM_GPIOMUX
+static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       return msm_gpiomux_get(chip->base + offset);
+}
+
+static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       msm_gpiomux_put(chip->base + offset);
+}
+#else
+#define msm_gpio_request NULL
+#define msm_gpio_free NULL
+#endif
+
+static struct msm_gpio_chip *msm_gpio_chips;
+static int msm_gpio_count;
+
+static struct msm_gpio_chip msm_gpio_chips_msm7x01[] = {
+       MSM_GPIO_BANK(MSM7X00, 0,   0,  15),
+       MSM_GPIO_BANK(MSM7X00, 1,  16,  42),
+       MSM_GPIO_BANK(MSM7X00, 2,  43,  67),
+       MSM_GPIO_BANK(MSM7X00, 3,  68,  94),
+       MSM_GPIO_BANK(MSM7X00, 4,  95, 106),
+       MSM_GPIO_BANK(MSM7X00, 5, 107, 121),
+};
+
+static struct msm_gpio_chip msm_gpio_chips_msm7x30[] = {
+       MSM_GPIO_BANK(MSM7X30, 0,   0,  15),
+       MSM_GPIO_BANK(MSM7X30, 1,  16,  43),
+       MSM_GPIO_BANK(MSM7X30, 2,  44,  67),
+       MSM_GPIO_BANK(MSM7X30, 3,  68,  94),
+       MSM_GPIO_BANK(MSM7X30, 4,  95, 106),
+       MSM_GPIO_BANK(MSM7X30, 5, 107, 133),
+       MSM_GPIO_BANK(MSM7X30, 6, 134, 150),
+       MSM_GPIO_BANK(MSM7X30, 7, 151, 181),
+};
+
+static struct msm_gpio_chip msm_gpio_chips_qsd8x50[] = {
+       MSM_GPIO_BANK(QSD8X50, 0,   0,  15),
+       MSM_GPIO_BANK(QSD8X50, 1,  16,  42),
+       MSM_GPIO_BANK(QSD8X50, 2,  43,  67),
+       MSM_GPIO_BANK(QSD8X50, 3,  68,  94),
+       MSM_GPIO_BANK(QSD8X50, 4,  95, 103),
+       MSM_GPIO_BANK(QSD8X50, 5, 104, 121),
+       MSM_GPIO_BANK(QSD8X50, 6, 122, 152),
+       MSM_GPIO_BANK(QSD8X50, 7, 153, 164),
+};
+
+static void msm_gpio_irq_ack(struct irq_data *d)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       msm_gpio_clear_detect_status(msm_chip,
+                                    d->irq - gpio_to_irq(msm_chip->chip.base));
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static void msm_gpio_irq_mask(struct irq_data *d)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
+
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       /* level triggered interrupts are also latched */
+       if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
+               msm_gpio_clear_detect_status(msm_chip, offset);
+       msm_chip->int_enable[0] &= ~BIT(offset);
+       writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static void msm_gpio_irq_unmask(struct irq_data *d)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
+
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       /* level triggered interrupts are also latched */
+       if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
+               msm_gpio_clear_detect_status(msm_chip, offset);
+       msm_chip->int_enable[0] |= BIT(offset);
+       writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
+
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+
+       if (on)
+               msm_chip->int_enable[1] |= BIT(offset);
+       else
+               msm_chip->int_enable[1] &= ~BIT(offset);
+
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+       return 0;
+}
+
+static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
+       unsigned val, mask = BIT(offset);
+
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       val = readl(msm_chip->regs.int_edge);
+       if (flow_type & IRQ_TYPE_EDGE_BOTH) {
+               writel(val | mask, msm_chip->regs.int_edge);
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
+       } else {
+               writel(val & ~mask, msm_chip->regs.int_edge);
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+       }
+       if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+               msm_chip->both_edge_detect |= mask;
+               msm_gpio_update_both_edge_detect(msm_chip);
+       } else {
+               msm_chip->both_edge_detect &= ~mask;
+               val = readl(msm_chip->regs.int_pos);
+               if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
+                       writel(val | mask, msm_chip->regs.int_pos);
+               else
+                       writel(val & ~mask, msm_chip->regs.int_pos);
+       }
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+       return 0;
+}
+
+static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       int i, j, mask;
+       unsigned val;
+
+       for (i = 0; i < msm_gpio_count; i++) {
+               struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
+               val = readl(msm_chip->regs.int_status);
+               val &= msm_chip->int_enable[0];
+               while (val) {
+                       mask = val & -val;
+                       j = fls(mask) - 1;
+                       /* printk("%s %08x %08x bit %d gpio %d irq %d\n",
+                               __func__, v, m, j, msm_chip->chip.start + j,
+                               FIRST_GPIO_IRQ + msm_chip->chip.start + j); */
+                       val &= ~mask;
+                       generic_handle_irq(FIRST_GPIO_IRQ +
+                                          msm_chip->chip.base + j);
+               }
+       }
+       desc->irq_data.chip->irq_ack(&desc->irq_data);
+}
+
+static struct irq_chip msm_gpio_irq_chip = {
+       .name          = "msmgpio",
+       .irq_ack       = msm_gpio_irq_ack,
+       .irq_mask      = msm_gpio_irq_mask,
+       .irq_unmask    = msm_gpio_irq_unmask,
+       .irq_set_wake  = msm_gpio_irq_set_wake,
+       .irq_set_type  = msm_gpio_irq_set_type,
+};
+
+static int __init msm_init_gpio(void)
+{
+       int i, j = 0;
+
+       if (cpu_is_msm7x01()) {
+               msm_gpio_chips = msm_gpio_chips_msm7x01;
+               msm_gpio_count = ARRAY_SIZE(msm_gpio_chips_msm7x01);
+       } else if (cpu_is_msm7x30()) {
+               msm_gpio_chips = msm_gpio_chips_msm7x30;
+               msm_gpio_count = ARRAY_SIZE(msm_gpio_chips_msm7x30);
+       } else if (cpu_is_qsd8x50()) {
+               msm_gpio_chips = msm_gpio_chips_qsd8x50;
+               msm_gpio_count = ARRAY_SIZE(msm_gpio_chips_qsd8x50);
+       } else {
+               return 0;
+       }
+
+       for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
+               if (i - FIRST_GPIO_IRQ >=
+                       msm_gpio_chips[j].chip.base +
+                       msm_gpio_chips[j].chip.ngpio)
+                       j++;
+               irq_set_chip_data(i, &msm_gpio_chips[j]);
+               irq_set_chip_and_handler(i, &msm_gpio_irq_chip,
+                                        handle_edge_irq);
+               set_irq_flags(i, IRQF_VALID);
+       }
+
+       for (i = 0; i < msm_gpio_count; i++) {
+               spin_lock_init(&msm_gpio_chips[i].lock);
+               writel(0, msm_gpio_chips[i].regs.int_en);
+               gpiochip_add(&msm_gpio_chips[i].chip);
+       }
+
+       irq_set_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
+       irq_set_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
+       irq_set_irq_wake(INT_GPIO_GROUP1, 1);
+       irq_set_irq_wake(INT_GPIO_GROUP2, 2);
+       return 0;
+}
+
+postcore_initcall(msm_init_gpio);
similarity index 99%
rename from arch/arm/mach-msm/gpio-v2.c
rename to drivers/gpio/gpio-msm-v2.c
index cc9c4fd..5cb1227 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
@@ -30,8 +30,8 @@
 
 #include <asm/mach/irq.h>
 
+#include <mach/msm_gpiomux.h>
 #include <mach/msm_iomap.h>
-#include "gpiomux.h"
 
 /* Bits of interest in the GPIO_IN_OUT register.
  */
diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c
new file mode 100644 (file)
index 0000000..79e66c0
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya <magi@slimlogic.co.uk>
+ *
+ *  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 driver is based on wm8350 implementation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/mfd/tps65912.h>
+
+struct tps65912_gpio_data {
+       struct tps65912 *tps65912;
+       struct gpio_chip gpio_chip;
+};
+
+static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+       struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
+       int val;
+
+       val = tps65912_reg_read(tps65912, TPS65912_GPIO1 + offset);
+
+       if (val & GPIO_STS_MASK)
+               return 1;
+
+       return 0;
+}
+
+static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset,
+                             int value)
+{
+       struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
+
+       if (value)
+               tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset,
+                                                       GPIO_SET_MASK);
+       else
+               tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset,
+                                                               GPIO_SET_MASK);
+}
+
+static int tps65912_gpio_output(struct gpio_chip *gc, unsigned offset,
+                               int value)
+{
+       struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
+
+       /* Set the initial value */
+       tps65912_gpio_set(gc, offset, value);
+
+       return tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset,
+                                                               GPIO_CFG_MASK);
+}
+
+static int tps65912_gpio_input(struct gpio_chip *gc, unsigned offset)
+{
+       struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
+
+       return tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset,
+                                                               GPIO_CFG_MASK);
+
+}
+
+static struct gpio_chip template_chip = {
+       .label                  = "tps65912",
+       .owner                  = THIS_MODULE,
+       .direction_input        = tps65912_gpio_input,
+       .direction_output       = tps65912_gpio_output,
+       .get                    = tps65912_gpio_get,
+       .set                    = tps65912_gpio_set,
+       .can_sleep              = 1,
+       .ngpio                  = 5,
+       .base                   = -1,
+};
+
+static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
+{
+       struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
+       struct tps65912_board *pdata = tps65912->dev->platform_data;
+       struct tps65912_gpio_data *tps65912_gpio;
+       int ret;
+
+       tps65912_gpio = kzalloc(sizeof(*tps65912_gpio), GFP_KERNEL);
+       if (tps65912_gpio == NULL)
+               return -ENOMEM;
+
+       tps65912_gpio->tps65912 = tps65912;
+       tps65912_gpio->gpio_chip = template_chip;
+       tps65912_gpio->gpio_chip.dev = &pdev->dev;
+       if (pdata && pdata->gpio_base)
+               tps65912_gpio->gpio_chip.base = pdata->gpio_base;
+
+       ret = gpiochip_add(&tps65912_gpio->gpio_chip);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret);
+               goto err;
+       }
+
+       platform_set_drvdata(pdev, tps65912_gpio);
+
+       return ret;
+
+err:
+       kfree(tps65912_gpio);
+       return ret;
+}
+
+static int __devexit tps65912_gpio_remove(struct platform_device *pdev)
+{
+       struct tps65912_gpio_data  *tps65912_gpio = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = gpiochip_remove(&tps65912_gpio->gpio_chip);
+       if (ret == 0)
+               kfree(tps65912_gpio);
+
+       return ret;
+}
+
+static struct platform_driver tps65912_gpio_driver = {
+       .driver = {
+               .name = "tps65912-gpio",
+               .owner = THIS_MODULE,
+       },
+       .probe = tps65912_gpio_probe,
+       .remove = __devexit_p(tps65912_gpio_remove),
+};
+
+static int __init tps65912_gpio_init(void)
+{
+       return platform_driver_register(&tps65912_gpio_driver);
+}
+subsys_initcall(tps65912_gpio_init);
+
+static void __exit tps65912_gpio_exit(void)
+{
+       platform_driver_unregister(&tps65912_gpio_driver);
+}
+module_exit(tps65912_gpio_exit);
+
+MODULE_AUTHOR("Margarita Olaya Cabrera <magi@slimlogic.co.uk>");
+MODULE_DESCRIPTION("GPIO interface for TPS65912 PMICs");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tps65912-gpio");
index 9d8c892..9d2668a 100644 (file)
@@ -90,7 +90,6 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count,
        struct drm_device *dev = minor->dev;
        struct dentry *ent;
        struct drm_info_node *tmp;
-       char name[64];
        int i, ret;
 
        for (i = 0; i < count; i++) {
@@ -108,6 +107,9 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count,
                ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
                                          root, tmp, &drm_debugfs_fops);
                if (!ent) {
+                       char name[64];
+                       strncpy(name, root->d_name.name,
+                                               min(root->d_name.len, 64U));
                        DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/%s\n",
                                  name, files[i].name);
                        kfree(tmp);
index 756af4d..7425e5c 100644 (file)
@@ -127,6 +127,23 @@ static const u8 edid_header[] = {
        0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
 };
 
+ /*
+ * Sanity check the header of the base EDID block.  Return 8 if the header
+ * is perfect, down to 0 if it's totally wrong.
+ */
+int drm_edid_header_is_valid(const u8 *raw_edid)
+{
+       int i, score = 0;
+
+       for (i = 0; i < sizeof(edid_header); i++)
+               if (raw_edid[i] == edid_header[i])
+                       score++;
+
+       return score;
+}
+EXPORT_SYMBOL(drm_edid_header_is_valid);
+
+
 /*
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
@@ -139,12 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
        struct edid *edid = (struct edid *)raw_edid;
 
        if (raw_edid[0] == 0x00) {
-               int score = 0;
-
-               for (i = 0; i < sizeof(edid_header); i++)
-                       if (raw_edid[i] == edid_header[i])
-                               score++;
-
+               int score = drm_edid_header_is_valid(raw_edid);
                if (score == 8) ;
                else if (score >= 6) {
                        DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
@@ -1439,6 +1451,8 @@ EXPORT_SYMBOL(drm_detect_monitor_audio);
 static void drm_add_display_info(struct edid *edid,
                                 struct drm_display_info *info)
 {
+       u8 *edid_ext;
+
        info->width_mm = edid->width_cm * 10;
        info->height_mm = edid->height_cm * 10;
 
@@ -1483,6 +1497,13 @@ static void drm_add_display_info(struct edid *edid,
                info->color_formats = DRM_COLOR_FORMAT_YCRCB444;
        if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB422)
                info->color_formats = DRM_COLOR_FORMAT_YCRCB422;
+
+       /* Get data from CEA blocks if present */
+       edid_ext = drm_find_cea_extension(edid);
+       if (!edid_ext)
+               return;
+
+       info->cea_rev = edid_ext[1];
 }
 
 /**
index 2022a5c..3830e9e 100644 (file)
@@ -291,11 +291,14 @@ static void drm_irq_vgaarb_nokms(void *cookie, bool state)
        if (!dev->irq_enabled)
                return;
 
-       if (state)
-               dev->driver->irq_uninstall(dev);
-       else {
-               dev->driver->irq_preinstall(dev);
-               dev->driver->irq_postinstall(dev);
+       if (state) {
+               if (dev->driver->irq_uninstall)
+                       dev->driver->irq_uninstall(dev);
+       } else {
+               if (dev->driver->irq_preinstall)
+                       dev->driver->irq_preinstall(dev);
+               if (dev->driver->irq_postinstall)
+                       dev->driver->irq_postinstall(dev);
        }
 }
 
@@ -338,7 +341,8 @@ int drm_irq_install(struct drm_device *dev)
        DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev));
 
        /* Before installing handler */
-       dev->driver->irq_preinstall(dev);
+       if (dev->driver->irq_preinstall)
+               dev->driver->irq_preinstall(dev);
 
        /* Install handler */
        if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
@@ -363,11 +367,16 @@ int drm_irq_install(struct drm_device *dev)
                vga_client_register(dev->pdev, (void *)dev, drm_irq_vgaarb_nokms, NULL);
 
        /* After installing handler */
-       ret = dev->driver->irq_postinstall(dev);
+       if (dev->driver->irq_postinstall)
+               ret = dev->driver->irq_postinstall(dev);
+
        if (ret < 0) {
                mutex_lock(&dev->struct_mutex);
                dev->irq_enabled = 0;
                mutex_unlock(&dev->struct_mutex);
+               if (!drm_core_check_feature(dev, DRIVER_MODESET))
+                       vga_client_register(dev->pdev, NULL, NULL, NULL);
+               free_irq(drm_dev_to_irq(dev), dev);
        }
 
        return ret;
@@ -413,7 +422,8 @@ int drm_irq_uninstall(struct drm_device *dev)
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                vga_client_register(dev->pdev, NULL, NULL, NULL);
 
-       dev->driver->irq_uninstall(dev);
+       if (dev->driver->irq_uninstall)
+               dev->driver->irq_uninstall(dev);
 
        free_irq(drm_dev_to_irq(dev), dev);
 
index e266249..a8ab626 100644 (file)
@@ -1338,6 +1338,155 @@ static const struct file_operations i915_wedged_fops = {
        .llseek = default_llseek,
 };
 
+static int
+i915_max_freq_open(struct inode *inode,
+                  struct file *filp)
+{
+       filp->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t
+i915_max_freq_read(struct file *filp,
+                  char __user *ubuf,
+                  size_t max,
+                  loff_t *ppos)
+{
+       struct drm_device *dev = filp->private_data;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       char buf[80];
+       int len;
+
+       len = snprintf(buf, sizeof (buf),
+                      "max freq: %d\n", dev_priv->max_delay * 50);
+
+       if (len > sizeof (buf))
+               len = sizeof (buf);
+
+       return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+}
+
+static ssize_t
+i915_max_freq_write(struct file *filp,
+                 const char __user *ubuf,
+                 size_t cnt,
+                 loff_t *ppos)
+{
+       struct drm_device *dev = filp->private_data;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       char buf[20];
+       int val = 1;
+
+       if (cnt > 0) {
+               if (cnt > sizeof (buf) - 1)
+                       return -EINVAL;
+
+               if (copy_from_user(buf, ubuf, cnt))
+                       return -EFAULT;
+               buf[cnt] = 0;
+
+               val = simple_strtoul(buf, NULL, 0);
+       }
+
+       DRM_DEBUG_DRIVER("Manually setting max freq to %d\n", val);
+
+       /*
+        * Turbo will still be enabled, but won't go above the set value.
+        */
+       dev_priv->max_delay = val / 50;
+
+       gen6_set_rps(dev, val / 50);
+
+       return cnt;
+}
+
+static const struct file_operations i915_max_freq_fops = {
+       .owner = THIS_MODULE,
+       .open = i915_max_freq_open,
+       .read = i915_max_freq_read,
+       .write = i915_max_freq_write,
+       .llseek = default_llseek,
+};
+
+static int
+i915_cache_sharing_open(struct inode *inode,
+                  struct file *filp)
+{
+       filp->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t
+i915_cache_sharing_read(struct file *filp,
+                  char __user *ubuf,
+                  size_t max,
+                  loff_t *ppos)
+{
+       struct drm_device *dev = filp->private_data;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       char buf[80];
+       u32 snpcr;
+       int len;
+
+       mutex_lock(&dev_priv->dev->struct_mutex);
+       snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
+       mutex_unlock(&dev_priv->dev->struct_mutex);
+
+       len = snprintf(buf, sizeof (buf),
+                      "%d\n", (snpcr & GEN6_MBC_SNPCR_MASK) >>
+                      GEN6_MBC_SNPCR_SHIFT);
+
+       if (len > sizeof (buf))
+               len = sizeof (buf);
+
+       return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+}
+
+static ssize_t
+i915_cache_sharing_write(struct file *filp,
+                 const char __user *ubuf,
+                 size_t cnt,
+                 loff_t *ppos)
+{
+       struct drm_device *dev = filp->private_data;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       char buf[20];
+       u32 snpcr;
+       int val = 1;
+
+       if (cnt > 0) {
+               if (cnt > sizeof (buf) - 1)
+                       return -EINVAL;
+
+               if (copy_from_user(buf, ubuf, cnt))
+                       return -EFAULT;
+               buf[cnt] = 0;
+
+               val = simple_strtoul(buf, NULL, 0);
+       }
+
+       if (val < 0 || val > 3)
+               return -EINVAL;
+
+       DRM_DEBUG_DRIVER("Manually setting uncore sharing to %d\n", val);
+
+       /* Update the cache sharing policy here as well */
+       snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
+       snpcr &= ~GEN6_MBC_SNPCR_MASK;
+       snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
+       I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
+
+       return cnt;
+}
+
+static const struct file_operations i915_cache_sharing_fops = {
+       .owner = THIS_MODULE,
+       .open = i915_cache_sharing_open,
+       .read = i915_cache_sharing_read,
+       .write = i915_cache_sharing_write,
+       .llseek = default_llseek,
+};
+
 /* As the drm_debugfs_init() routines are called before dev->dev_private is
  * allocated we need to hook into the minor for release. */
 static int
@@ -1437,6 +1586,36 @@ static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor)
        return drm_add_fake_info_node(minor, ent, &i915_forcewake_fops);
 }
 
+static int i915_max_freq_create(struct dentry *root, struct drm_minor *minor)
+{
+       struct drm_device *dev = minor->dev;
+       struct dentry *ent;
+
+       ent = debugfs_create_file("i915_max_freq",
+                                 S_IRUGO | S_IWUSR,
+                                 root, dev,
+                                 &i915_max_freq_fops);
+       if (IS_ERR(ent))
+               return PTR_ERR(ent);
+
+       return drm_add_fake_info_node(minor, ent, &i915_max_freq_fops);
+}
+
+static int i915_cache_sharing_create(struct dentry *root, struct drm_minor *minor)
+{
+       struct drm_device *dev = minor->dev;
+       struct dentry *ent;
+
+       ent = debugfs_create_file("i915_cache_sharing",
+                                 S_IRUGO | S_IWUSR,
+                                 root, dev,
+                                 &i915_cache_sharing_fops);
+       if (IS_ERR(ent))
+               return PTR_ERR(ent);
+
+       return drm_add_fake_info_node(minor, ent, &i915_cache_sharing_fops);
+}
+
 static struct drm_info_list i915_debugfs_list[] = {
        {"i915_capabilities", i915_capabilities, 0},
        {"i915_gem_objects", i915_gem_object_info, 0},
@@ -1488,6 +1667,12 @@ int i915_debugfs_init(struct drm_minor *minor)
                return ret;
 
        ret = i915_forcewake_create(minor->debugfs_root, minor);
+       if (ret)
+               return ret;
+       ret = i915_max_freq_create(minor->debugfs_root, minor);
+       if (ret)
+               return ret;
+       ret = i915_cache_sharing_create(minor->debugfs_root, minor);
        if (ret)
                return ret;
 
@@ -1504,6 +1689,10 @@ void i915_debugfs_cleanup(struct drm_minor *minor)
                                 1, minor);
        drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops,
                                 1, minor);
+       drm_debugfs_remove_files((struct drm_info_list *) &i915_max_freq_fops,
+                                1, minor);
+       drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops,
+                                1, minor);
 }
 
 #endif /* CONFIG_DEBUG_FS */
index 1271282..8a3942c 100644 (file)
@@ -61,7 +61,6 @@ static void i915_write_hws_pga(struct drm_device *dev)
 static int i915_init_phys_hws(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct intel_ring_buffer *ring = LP_RING(dev_priv);
 
        /* Program Hardware Status Page */
        dev_priv->status_page_dmah =
@@ -71,10 +70,9 @@ static int i915_init_phys_hws(struct drm_device *dev)
                DRM_ERROR("Can not allocate hardware status page\n");
                return -ENOMEM;
        }
-       ring->status_page.page_addr =
-               (void __force __iomem *)dev_priv->status_page_dmah->vaddr;
 
-       memset_io(ring->status_page.page_addr, 0, PAGE_SIZE);
+       memset_io((void __force __iomem *)dev_priv->status_page_dmah->vaddr,
+                 0, PAGE_SIZE);
 
        i915_write_hws_pga(dev);
 
index 6867e19..feb4f16 100644 (file)
@@ -544,6 +544,7 @@ typedef struct drm_i915_private {
        u32 savePIPEB_LINK_M1;
        u32 savePIPEB_LINK_N1;
        u32 saveMCHBAR_RENDER_STANDBY;
+       u32 savePCH_PORT_HOTPLUG;
 
        struct {
                /** Bridge to intel-gtt-ko */
index d1cd8b8..a546a71 100644 (file)
@@ -3112,7 +3112,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
 
        if (pipelined != obj->ring) {
                ret = i915_gem_object_wait_rendering(obj);
-               if (ret)
+               if (ret == -ERESTARTSYS)
                        return ret;
        }
 
index 23d1ae6..02f96fd 100644 (file)
@@ -306,12 +306,15 @@ static void i915_hotplug_work_func(struct work_struct *work)
        struct drm_mode_config *mode_config = &dev->mode_config;
        struct intel_encoder *encoder;
 
+       mutex_lock(&mode_config->mutex);
        DRM_DEBUG_KMS("running encoder hotplug functions\n");
 
        list_for_each_entry(encoder, &mode_config->encoder_list, base.head)
                if (encoder->hot_plug)
                        encoder->hot_plug(encoder);
 
+       mutex_unlock(&mode_config->mutex);
+
        /* Just fire off a uevent and let userspace tell us what to do */
        drm_helper_hpd_irq_event(dev);
 }
index 02db299..d1331f7 100644 (file)
 #define  GRDOM_RENDER  (1<<2)
 #define  GRDOM_MEDIA   (3<<2)
 
+#define GEN6_MBCUNIT_SNPCR     0x900c /* for LLC config */
+#define   GEN6_MBC_SNPCR_SHIFT 21
+#define   GEN6_MBC_SNPCR_MASK  (3<<21)
+#define   GEN6_MBC_SNPCR_MAX   (0<<21)
+#define   GEN6_MBC_SNPCR_MED   (1<<21)
+#define   GEN6_MBC_SNPCR_LOW   (2<<21)
+#define   GEN6_MBC_SNPCR_MIN   (3<<21) /* only 1/16th of the cache is shared */
+
 #define GEN6_GDRST     0x941c
 #define  GEN6_GRDOM_FULL               (1 << 0)
 #define  GEN6_GRDOM_RENDER             (1 << 1)
 #define   VIDEO_DIP_SELECT_AVI         (0 << 19)
 #define   VIDEO_DIP_SELECT_VENDOR      (1 << 19)
 #define   VIDEO_DIP_SELECT_SPD         (3 << 19)
+#define   VIDEO_DIP_SELECT_MASK                (3 << 19)
 #define   VIDEO_DIP_FREQ_ONCE          (0 << 16)
 #define   VIDEO_DIP_FREQ_VSYNC         (1 << 16)
 #define   VIDEO_DIP_FREQ_2VSYNC                (2 << 16)
 #define   DP_PIPEB_SELECT              (1 << 30)
 #define   DP_PIPE_MASK                 (1 << 30)
 
-#define DP_PIPE_ENABLED(V, P) \
-       (((V) & (DP_PIPE_MASK | DP_PORT_EN)) == ((P) << 30 | DP_PORT_EN))
-
 /* Link training mode - select a suitable mode for each stage */
 #define   DP_LINK_TRAIN_PAT_1          (0 << 28)
 #define   DP_LINK_TRAIN_PAT_2          (1 << 28)
 #define _TRANSA_DP_LINK_M2       0xe0048
 #define _TRANSA_DP_LINK_N2       0xe004c
 
+/* Per-transcoder DIP controls */
+
+#define _VIDEO_DIP_CTL_A         0xe0200
+#define _VIDEO_DIP_DATA_A        0xe0208
+#define _VIDEO_DIP_GCP_A         0xe0210
+
+#define _VIDEO_DIP_CTL_B         0xe1200
+#define _VIDEO_DIP_DATA_B        0xe1208
+#define _VIDEO_DIP_GCP_B         0xe1210
+
+#define TVIDEO_DIP_CTL(pipe) _PIPE(pipe, _VIDEO_DIP_CTL_A, _VIDEO_DIP_CTL_B)
+#define TVIDEO_DIP_DATA(pipe) _PIPE(pipe, _VIDEO_DIP_DATA_A, _VIDEO_DIP_DATA_B)
+#define TVIDEO_DIP_GCP(pipe) _PIPE(pipe, _VIDEO_DIP_GCP_A, _VIDEO_DIP_GCP_B)
+
 #define _TRANS_HTOTAL_B          0xe1000
 #define _TRANS_HBLANK_B          0xe1004
 #define _TRANS_HSYNC_B           0xe1008
 #define  TRANS_6BPC             (2<<5)
 #define  TRANS_12BPC            (3<<5)
 
+#define _TRANSA_CHICKEN2        0xf0064
+#define _TRANSB_CHICKEN2        0xf1064
+#define TRANS_CHICKEN2(pipe) _PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2)
+#define   TRANS_AUTOTRAIN_GEN_STALL_DIS        (1<<31)
+
+#define SOUTH_CHICKEN1         0xc2000
+#define  FDIA_PHASE_SYNC_SHIFT_OVR     19
+#define  FDIA_PHASE_SYNC_SHIFT_EN      18
+#define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2)))
+#define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2)))
 #define SOUTH_CHICKEN2         0xc2004
 #define  DPLS_EDP_PPS_FIX_DIS  (1<<0)
 
index 2857586..87677d6 100644 (file)
@@ -812,6 +812,7 @@ int i915_save_state(struct drm_device *dev)
                dev_priv->saveFDI_RXB_IMR = I915_READ(_FDI_RXB_IMR);
                dev_priv->saveMCHBAR_RENDER_STANDBY =
                        I915_READ(RSTDBYCTL);
+               dev_priv->savePCH_PORT_HOTPLUG = I915_READ(PCH_PORT_HOTPLUG);
        } else {
                dev_priv->saveIER = I915_READ(IER);
                dev_priv->saveIMR = I915_READ(IMR);
@@ -863,6 +864,7 @@ int i915_restore_state(struct drm_device *dev)
                I915_WRITE(GTIMR, dev_priv->saveGTIMR);
                I915_WRITE(_FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR);
                I915_WRITE(_FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR);
+               I915_WRITE(PCH_PORT_HOTPLUG, dev_priv->savePCH_PORT_HOTPLUG);
        } else {
                I915_WRITE(IER, dev_priv->saveIER);
                I915_WRITE(IMR, dev_priv->saveIMR);
index 393a399..35364e6 100644 (file)
@@ -980,11 +980,29 @@ static void assert_transcoder_disabled(struct drm_i915_private *dev_priv,
             pipe_name(pipe));
 }
 
+static bool dp_pipe_enabled(struct drm_i915_private *dev_priv, enum pipe pipe,
+                           int reg, u32 port_sel, u32 val)
+{
+       if ((val & DP_PORT_EN) == 0)
+               return false;
+
+       if (HAS_PCH_CPT(dev_priv->dev)) {
+               u32     trans_dp_ctl_reg = TRANS_DP_CTL(pipe);
+               u32     trans_dp_ctl = I915_READ(trans_dp_ctl_reg);
+               if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel)
+                       return false;
+       } else {
+               if ((val & DP_PIPE_MASK) != (pipe << 30))
+                       return false;
+       }
+       return true;
+}
+
 static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
-                                  enum pipe pipe, int reg)
+                                  enum pipe pipe, int reg, u32 port_sel)
 {
        u32 val = I915_READ(reg);
-       WARN(DP_PIPE_ENABLED(val, pipe),
+       WARN(dp_pipe_enabled(dev_priv, pipe, reg, port_sel, val),
             "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
             reg, pipe_name(pipe));
 }
@@ -1004,9 +1022,9 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
        int reg;
        u32 val;
 
-       assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B);
-       assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C);
-       assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D);
+       assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B, TRANS_DP_PORT_SEL_B);
+       assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C, TRANS_DP_PORT_SEL_C);
+       assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D, TRANS_DP_PORT_SEL_D);
 
        reg = PCH_ADPA;
        val = I915_READ(reg);
@@ -1276,6 +1294,17 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv,
        intel_wait_for_pipe_off(dev_priv->dev, pipe);
 }
 
+/*
+ * Plane regs are double buffered, going from enabled->disabled needs a
+ * trigger in order to latch.  The display address reg provides this.
+ */
+static void intel_flush_display_plane(struct drm_i915_private *dev_priv,
+                                     enum plane plane)
+{
+       I915_WRITE(DSPADDR(plane), I915_READ(DSPADDR(plane)));
+       I915_WRITE(DSPSURF(plane), I915_READ(DSPSURF(plane)));
+}
+
 /**
  * intel_enable_plane - enable a display plane on a given pipe
  * @dev_priv: i915 private structure
@@ -1299,20 +1328,10 @@ static void intel_enable_plane(struct drm_i915_private *dev_priv,
                return;
 
        I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
+       intel_flush_display_plane(dev_priv, plane);
        intel_wait_for_vblank(dev_priv->dev, pipe);
 }
 
-/*
- * Plane regs are double buffered, going from enabled->disabled needs a
- * trigger in order to latch.  The display address reg provides this.
- */
-static void intel_flush_display_plane(struct drm_i915_private *dev_priv,
-                                     enum plane plane)
-{
-       u32 reg = DSPADDR(plane);
-       I915_WRITE(reg, I915_READ(reg));
-}
-
 /**
  * intel_disable_plane - disable a display plane
  * @dev_priv: i915 private structure
@@ -1338,19 +1357,24 @@ static void intel_disable_plane(struct drm_i915_private *dev_priv,
 }
 
 static void disable_pch_dp(struct drm_i915_private *dev_priv,
-                          enum pipe pipe, int reg)
+                          enum pipe pipe, int reg, u32 port_sel)
 {
        u32 val = I915_READ(reg);
-       if (DP_PIPE_ENABLED(val, pipe))
+       if (dp_pipe_enabled(dev_priv, pipe, reg, port_sel, val)) {
+               DRM_DEBUG_KMS("Disabling pch dp %x on pipe %d\n", reg, pipe);
                I915_WRITE(reg, val & ~DP_PORT_EN);
+       }
 }
 
 static void disable_pch_hdmi(struct drm_i915_private *dev_priv,
                             enum pipe pipe, int reg)
 {
        u32 val = I915_READ(reg);
-       if (HDMI_PIPE_ENABLED(val, pipe))
+       if (HDMI_PIPE_ENABLED(val, pipe)) {
+               DRM_DEBUG_KMS("Disabling pch HDMI %x on pipe %d\n",
+                             reg, pipe);
                I915_WRITE(reg, val & ~PORT_ENABLE);
+       }
 }
 
 /* Disable any ports connected to this transcoder */
@@ -1362,9 +1386,9 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
        val = I915_READ(PCH_PP_CONTROL);
        I915_WRITE(PCH_PP_CONTROL, val | PANEL_UNLOCK_REGS);
 
-       disable_pch_dp(dev_priv, pipe, PCH_DP_B);
-       disable_pch_dp(dev_priv, pipe, PCH_DP_C);
-       disable_pch_dp(dev_priv, pipe, PCH_DP_D);
+       disable_pch_dp(dev_priv, pipe, PCH_DP_B, TRANS_DP_PORT_SEL_B);
+       disable_pch_dp(dev_priv, pipe, PCH_DP_C, TRANS_DP_PORT_SEL_C);
+       disable_pch_dp(dev_priv, pipe, PCH_DP_D, TRANS_DP_PORT_SEL_D);
 
        reg = PCH_ADPA;
        val = I915_READ(reg);
@@ -2096,7 +2120,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 
        /* no fb bound */
        if (!crtc->fb) {
-               DRM_DEBUG_KMS("No FB bound\n");
+               DRM_ERROR("No FB bound\n");
                return 0;
        }
 
@@ -2105,6 +2129,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        case 1:
                break;
        default:
+               DRM_ERROR("no plane for crtc\n");
                return -EINVAL;
        }
 
@@ -2114,6 +2139,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                                         NULL);
        if (ret != 0) {
                mutex_unlock(&dev->struct_mutex);
+               DRM_ERROR("pin & fence failed\n");
                return ret;
        }
 
@@ -2142,6 +2168,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        if (ret) {
                i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj);
                mutex_unlock(&dev->struct_mutex);
+               DRM_ERROR("failed to update base address\n");
                return ret;
        }
 
@@ -2248,6 +2275,18 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
                           FDI_FE_ERRC_ENABLE);
 }
 
+static void cpt_phase_pointer_enable(struct drm_device *dev, int pipe)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 flags = I915_READ(SOUTH_CHICKEN1);
+
+       flags |= FDI_PHASE_SYNC_OVR(pipe);
+       I915_WRITE(SOUTH_CHICKEN1, flags); /* once to unlock... */
+       flags |= FDI_PHASE_SYNC_EN(pipe);
+       I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to enable */
+       POSTING_READ(SOUTH_CHICKEN1);
+}
+
 /* The FDI link training functions for ILK/Ibexpeak. */
 static void ironlake_fdi_link_train(struct drm_crtc *crtc)
 {
@@ -2398,6 +2437,9 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
        POSTING_READ(reg);
        udelay(150);
 
+       if (HAS_PCH_CPT(dev))
+               cpt_phase_pointer_enable(dev, pipe);
+
        for (i = 0; i < 4; i++ ) {
                reg = FDI_TX_CTL(pipe);
                temp = I915_READ(reg);
@@ -2514,6 +2556,9 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
        POSTING_READ(reg);
        udelay(150);
 
+       if (HAS_PCH_CPT(dev))
+               cpt_phase_pointer_enable(dev, pipe);
+
        for (i = 0; i < 4; i++ ) {
                reg = FDI_TX_CTL(pipe);
                temp = I915_READ(reg);
@@ -2623,6 +2668,17 @@ static void ironlake_fdi_pll_enable(struct drm_crtc *crtc)
        }
 }
 
+static void cpt_phase_pointer_disable(struct drm_device *dev, int pipe)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 flags = I915_READ(SOUTH_CHICKEN1);
+
+       flags &= ~(FDI_PHASE_SYNC_EN(pipe));
+       I915_WRITE(SOUTH_CHICKEN1, flags); /* once to disable... */
+       flags &= ~(FDI_PHASE_SYNC_OVR(pipe));
+       I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to lock */
+       POSTING_READ(SOUTH_CHICKEN1);
+}
 static void ironlake_fdi_disable(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -2652,6 +2708,8 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
                I915_WRITE(FDI_RX_CHICKEN(pipe),
                           I915_READ(FDI_RX_CHICKEN(pipe) &
                                     ~FDI_RX_PHASE_SYNC_POINTER_EN));
+       } else if (HAS_PCH_CPT(dev)) {
+               cpt_phase_pointer_disable(dev, pipe);
        }
 
        /* still set train pattern 1 */
@@ -2862,14 +2920,18 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
                I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size);
        }
 
+       /*
+        * On ILK+ LUT must be loaded before the pipe is running but with
+        * clocks enabled
+        */
+       intel_crtc_load_lut(crtc);
+
        intel_enable_pipe(dev_priv, pipe, is_pch_port);
        intel_enable_plane(dev_priv, plane, pipe);
 
        if (is_pch_port)
                ironlake_pch_enable(crtc);
 
-       intel_crtc_load_lut(crtc);
-
        mutex_lock(&dev->struct_mutex);
        intel_update_fbc(dev);
        mutex_unlock(&dev->struct_mutex);
@@ -4538,7 +4600,9 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                        if (connector->encoder != encoder)
                                continue;
 
-                       if (connector->display_info.bpc < display_bpc) {
+                       /* Don't use an invalid EDID bpc value */
+                       if (connector->display_info.bpc &&
+                           connector->display_info.bpc < display_bpc) {
                                DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
                                display_bpc = connector->display_info.bpc;
                        }
@@ -5153,7 +5217,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                temp |= PIPE_12BPC;
                break;
        default:
-               WARN(1, "intel_choose_pipe_bpp returned invalid value\n");
+               WARN(1, "intel_choose_pipe_bpp returned invalid value %d\n",
+                       pipe_bpp);
                temp |= PIPE_8BPC;
                pipe_bpp = 24;
                break;
@@ -5238,7 +5303,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        } else if (is_sdvo && is_tv)
                factor = 20;
 
-       if (clock.m1 < factor * clock.n)
+       if (clock.m < factor * clock.n)
                fp |= FP_CB_TUNE;
 
        dpll = 0;
@@ -5516,6 +5581,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
        drm_vblank_post_modeset(dev, pipe);
 
+       intel_crtc->dpms_mode = DRM_MODE_DPMS_ON;
+
        return ret;
 }
 
@@ -7714,10 +7781,12 @@ static void gen6_init_clock_gating(struct drm_device *dev)
                   ILK_DPARB_CLK_GATE  |
                   ILK_DPFD_CLK_GATE);
 
-       for_each_pipe(pipe)
+       for_each_pipe(pipe) {
                I915_WRITE(DSPCNTR(pipe),
                           I915_READ(DSPCNTR(pipe)) |
                           DISPPLANE_TRICKLE_FEED_DISABLE);
+               intel_flush_display_plane(dev_priv, pipe);
+       }
 }
 
 static void ivybridge_init_clock_gating(struct drm_device *dev)
@@ -7734,10 +7803,12 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
 
        I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
 
-       for_each_pipe(pipe)
+       for_each_pipe(pipe) {
                I915_WRITE(DSPCNTR(pipe),
                           I915_READ(DSPCNTR(pipe)) |
                           DISPPLANE_TRICKLE_FEED_DISABLE);
+               intel_flush_display_plane(dev_priv, pipe);
+       }
 }
 
 static void g4x_init_clock_gating(struct drm_device *dev)
@@ -7820,6 +7891,7 @@ static void ibx_init_clock_gating(struct drm_device *dev)
 static void cpt_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       int pipe;
 
        /*
         * On Ibex Peak and Cougar Point, we need to disable clock
@@ -7829,6 +7901,9 @@ static void cpt_init_clock_gating(struct drm_device *dev)
        I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
        I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) |
                   DPLS_EDP_PPS_FIX_DIS);
+       /* Without this, mode sets may fail silently on FDI */
+       for_each_pipe(pipe)
+               I915_WRITE(TRANS_CHICKEN2(pipe), TRANS_AUTOTRAIN_GEN_STALL_DIS);
 }
 
 static void ironlake_teardown_rc6(struct drm_device *dev)
@@ -8178,6 +8253,9 @@ struct intel_quirk intel_quirks[] = {
 
        /* Lenovo U160 cannot use SSC on LVDS */
        { 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable },
+
+       /* Sony Vaio Y cannot use SSC on LVDS */
+       { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable },
 };
 
 static void intel_init_quirks(struct drm_device *dev)
index f797fb5..0feae90 100644 (file)
@@ -50,9 +50,10 @@ struct intel_dp {
        bool has_audio;
        int force_audio;
        uint32_t color_range;
+       int dpms_mode;
        uint8_t link_bw;
        uint8_t lane_count;
-       uint8_t dpcd[4];
+       uint8_t dpcd[8];
        struct i2c_adapter adapter;
        struct i2c_algo_dp_aux_data algo;
        bool is_pch_edp;
@@ -316,9 +317,17 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
        else
                precharge = 5;
 
-       if (I915_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) {
-               DRM_ERROR("dp_aux_ch not started status 0x%08x\n",
-                         I915_READ(ch_ctl));
+       /* Try to wait for any previous AUX channel activity */
+       for (try = 0; try < 3; try++) {
+               status = I915_READ(ch_ctl);
+               if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
+                       break;
+               msleep(1);
+       }
+
+       if (try == 3) {
+               WARN(1, "dp_aux_ch not started status 0x%08x\n",
+                    I915_READ(ch_ctl));
                return -EBUSY;
        }
 
@@ -770,6 +779,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
        memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
        intel_dp->link_configuration[0] = intel_dp->link_bw;
        intel_dp->link_configuration[1] = intel_dp->lane_count;
+       intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B;
 
        /*
         * Check for DPCD version > 1.1 and enhanced framing support
@@ -1011,6 +1021,8 @@ static void intel_dp_commit(struct drm_encoder *encoder)
 
        if (is_edp(intel_dp))
                ironlake_edp_backlight_on(dev);
+
+       intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
 }
 
 static void
@@ -1045,6 +1057,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
                if (is_edp(intel_dp))
                        ironlake_edp_backlight_on(dev);
        }
+       intel_dp->dpms_mode = mode;
 }
 
 /*
@@ -1334,10 +1347,16 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
        u32 reg;
        uint32_t DP = intel_dp->DP;
 
-       /* Enable output, wait for it to become active */
-       I915_WRITE(intel_dp->output_reg, intel_dp->DP);
-       POSTING_READ(intel_dp->output_reg);
-       intel_wait_for_vblank(dev, intel_crtc->pipe);
+       /*
+        * On CPT we have to enable the port in training pattern 1, which
+        * will happen below in intel_dp_set_link_train.  Otherwise, enable
+        * the port and wait for it to become active.
+        */
+       if (!HAS_PCH_CPT(dev)) {
+               I915_WRITE(intel_dp->output_reg, intel_dp->DP);
+               POSTING_READ(intel_dp->output_reg);
+               intel_wait_for_vblank(dev, intel_crtc->pipe);
+       }
 
        /* Write the link configuration data */
        intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
@@ -1370,7 +1389,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                        reg = DP | DP_LINK_TRAIN_PAT_1;
 
                if (!intel_dp_set_link_train(intel_dp, reg,
-                                            DP_TRAINING_PATTERN_1))
+                                            DP_TRAINING_PATTERN_1 |
+                                            DP_LINK_SCRAMBLING_DISABLE))
                        break;
                /* Set training pattern 1 */
 
@@ -1445,7 +1465,8 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 
                /* channel eq pattern */
                if (!intel_dp_set_link_train(intel_dp, reg,
-                                            DP_TRAINING_PATTERN_2))
+                                            DP_TRAINING_PATTERN_2 |
+                                            DP_LINK_SCRAMBLING_DISABLE))
                        break;
 
                udelay(400);
@@ -1559,6 +1580,18 @@ intel_dp_link_down(struct intel_dp *intel_dp)
        POSTING_READ(intel_dp->output_reg);
 }
 
+static bool
+intel_dp_get_dpcd(struct intel_dp *intel_dp)
+{
+       if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,
+                                          sizeof (intel_dp->dpcd)) &&
+           (intel_dp->dpcd[DP_DPCD_REV] != 0)) {
+               return true;
+       }
+
+       return false;
+}
+
 /*
  * According to DP spec
  * 5.1.2:
@@ -1571,36 +1604,44 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 static void
 intel_dp_check_link_status(struct intel_dp *intel_dp)
 {
-       int ret;
+       if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
+               return;
 
        if (!intel_dp->base.base.crtc)
                return;
 
+       /* Try to read receiver status if the link appears to be up */
        if (!intel_dp_get_link_status(intel_dp)) {
                intel_dp_link_down(intel_dp);
                return;
        }
 
-       /* Try to read receiver status if the link appears to be up */
-       ret = intel_dp_aux_native_read(intel_dp,
-                                      0x000, intel_dp->dpcd,
-                                      sizeof (intel_dp->dpcd));
-       if (ret != sizeof(intel_dp->dpcd)) {
+       /* Now read the DPCD to see if it's actually running */
+       if (!intel_dp_get_dpcd(intel_dp)) {
                intel_dp_link_down(intel_dp);
                return;
        }
 
        if (!intel_channel_eq_ok(intel_dp)) {
+               DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
+                             drm_get_encoder_name(&intel_dp->base.base));
                intel_dp_start_link_train(intel_dp);
                intel_dp_complete_link_train(intel_dp);
        }
 }
 
+static enum drm_connector_status
+intel_dp_detect_dpcd(struct intel_dp *intel_dp)
+{
+       if (intel_dp_get_dpcd(intel_dp))
+               return connector_status_connected;
+       return connector_status_disconnected;
+}
+
 static enum drm_connector_status
 ironlake_dp_detect(struct intel_dp *intel_dp)
 {
        enum drm_connector_status status;
-       bool ret;
 
        /* Can't disconnect eDP, but you can close the lid... */
        if (is_edp(intel_dp)) {
@@ -1610,15 +1651,7 @@ ironlake_dp_detect(struct intel_dp *intel_dp)
                return status;
        }
 
-       status = connector_status_disconnected;
-       ret = intel_dp_aux_native_read_retry(intel_dp,
-                                            0x000, intel_dp->dpcd,
-                                            sizeof (intel_dp->dpcd));
-       if (ret && intel_dp->dpcd[DP_DPCD_REV] != 0)
-               status = connector_status_connected;
-       DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0],
-                     intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]);
-       return status;
+       return intel_dp_detect_dpcd(intel_dp);
 }
 
 static enum drm_connector_status
@@ -1626,7 +1659,6 @@ g4x_dp_detect(struct intel_dp *intel_dp)
 {
        struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       enum drm_connector_status status;
        uint32_t temp, bit;
 
        switch (intel_dp->output_reg) {
@@ -1648,15 +1680,7 @@ g4x_dp_detect(struct intel_dp *intel_dp)
        if ((temp & bit) == 0)
                return connector_status_disconnected;
 
-       status = connector_status_disconnected;
-       if (intel_dp_aux_native_read(intel_dp, 0x000, intel_dp->dpcd,
-                                    sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd))
-       {
-               if (intel_dp->dpcd[DP_DPCD_REV] != 0)
-                       status = connector_status_connected;
-       }
-
-       return status;
+       return intel_dp_detect_dpcd(intel_dp);
 }
 
 /**
@@ -1679,6 +1703,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
                status = ironlake_dp_detect(intel_dp);
        else
                status = g4x_dp_detect(intel_dp);
+
+       DRM_DEBUG_KMS("DPCD: %02hx%02hx%02hx%02hx%02hx%02hx%02hx%02hx\n",
+                     intel_dp->dpcd[0], intel_dp->dpcd[1], intel_dp->dpcd[2],
+                     intel_dp->dpcd[3], intel_dp->dpcd[4], intel_dp->dpcd[5],
+                     intel_dp->dpcd[6], intel_dp->dpcd[7]);
+
        if (status != connector_status_connected)
                return status;
 
@@ -1924,6 +1954,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                return;
 
        intel_dp->output_reg = output_reg;
+       intel_dp->dpms_mode = -1;
 
        intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
        if (!intel_connector) {
@@ -2000,7 +2031,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
        /* Cache some DPCD data in the eDP case */
        if (is_edp(intel_dp)) {
-               int ret;
+               bool ret;
                u32 pp_on, pp_div;
 
                pp_on = I915_READ(PCH_PP_ON_DELAYS);
@@ -2013,11 +2044,9 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                dev_priv->panel_t12 *= 100; /* t12 in 100ms units */
 
                ironlake_edp_panel_vdd_on(intel_dp);
-               ret = intel_dp_aux_native_read(intel_dp, DP_DPCD_REV,
-                                              intel_dp->dpcd,
-                                              sizeof(intel_dp->dpcd));
+               ret = intel_dp_get_dpcd(intel_dp);
                ironlake_edp_panel_vdd_off(intel_dp);
-               if (ret == sizeof(intel_dp->dpcd)) {
+               if (ret) {
                        if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
                                dev_priv->no_aux_handshake =
                                        intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
index 6e990f9..7b330e7 100644 (file)
@@ -178,10 +178,28 @@ struct intel_crtc {
 #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
 
+#define DIP_HEADER_SIZE        5
+
 #define DIP_TYPE_AVI    0x82
 #define DIP_VERSION_AVI 0x2
 #define DIP_LEN_AVI     13
 
+#define DIP_TYPE_SPD   0x3
+#define DIP_VERSION_SPD        0x1
+#define DIP_LEN_SPD    25
+#define DIP_SPD_UNKNOWN        0
+#define DIP_SPD_DSTB   0x1
+#define DIP_SPD_DVDP   0x2
+#define DIP_SPD_DVHS   0x3
+#define DIP_SPD_HDDVR  0x4
+#define DIP_SPD_DVC    0x5
+#define DIP_SPD_DSC    0x6
+#define DIP_SPD_VCD    0x7
+#define DIP_SPD_GAME   0x8
+#define DIP_SPD_PC     0x9
+#define DIP_SPD_BD     0xa
+#define DIP_SPD_SCD    0xb
+
 struct dip_infoframe {
        uint8_t type;           /* HB0 */
        uint8_t ver;            /* HB1 */
@@ -206,6 +224,11 @@ struct dip_infoframe {
                        uint16_t left_bar_end;
                        uint16_t right_bar_start;
                } avi;
+               struct {
+                       uint8_t vn[8];
+                       uint8_t pd[16];
+                       uint8_t sdi;
+               } spd;
                uint8_t payload[27];
        } __attribute__ ((packed)) body;
 } __attribute__((packed));
index 1ed8e69..226ba83 100644 (file)
@@ -45,6 +45,8 @@ struct intel_hdmi {
        bool has_hdmi_sink;
        bool has_audio;
        int force_audio;
+       void (*write_infoframe)(struct drm_encoder *encoder,
+                               struct dip_infoframe *frame);
 };
 
 static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
@@ -58,37 +60,70 @@ static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector)
                            struct intel_hdmi, base);
 }
 
-void intel_dip_infoframe_csum(struct dip_infoframe *avi_if)
+void intel_dip_infoframe_csum(struct dip_infoframe *frame)
 {
-       uint8_t *data = (uint8_t *)avi_if;
+       uint8_t *data = (uint8_t *)frame;
        uint8_t sum = 0;
        unsigned i;
 
-       avi_if->checksum = 0;
-       avi_if->ecc = 0;
+       frame->checksum = 0;
+       frame->ecc = 0;
 
-       for (i = 0; i < sizeof(*avi_if); i++)
+       /* Header isn't part of the checksum */
+       for (i = 5; i < frame->len; i++)
                sum += data[i];
 
-       avi_if->checksum = 0x100 - sum;
+       frame->checksum = 0x100 - sum;
 }
 
-static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
+static u32 intel_infoframe_index(struct dip_infoframe *frame)
 {
-       struct dip_infoframe avi_if = {
-               .type = DIP_TYPE_AVI,
-               .ver = DIP_VERSION_AVI,
-               .len = DIP_LEN_AVI,
-       };
-       uint32_t *data = (uint32_t *)&avi_if;
+       u32 flags = 0;
+
+       switch (frame->type) {
+       case DIP_TYPE_AVI:
+               flags |= VIDEO_DIP_SELECT_AVI;
+               break;
+       case DIP_TYPE_SPD:
+               flags |= VIDEO_DIP_SELECT_SPD;
+               break;
+       default:
+               DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
+               break;
+       }
+
+       return flags;
+}
+
+static u32 intel_infoframe_flags(struct dip_infoframe *frame)
+{
+       u32 flags = 0;
+
+       switch (frame->type) {
+       case DIP_TYPE_AVI:
+               flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC;
+               break;
+       case DIP_TYPE_SPD:
+               flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_2VSYNC;
+               break;
+       default:
+               DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
+               break;
+       }
+
+       return flags;
+}
+
+static void i9xx_write_infoframe(struct drm_encoder *encoder,
+                                struct dip_infoframe *frame)
+{
+       uint32_t *data = (uint32_t *)frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
-       u32 port;
-       unsigned i;
+       u32 port, flags, val = I915_READ(VIDEO_DIP_CTL);
+       unsigned i, len = DIP_HEADER_SIZE + frame->len;
 
-       if (!intel_hdmi->has_hdmi_sink)
-               return;
 
        /* XXX first guess at handling video port, is this corrent? */
        if (intel_hdmi->sdvox_reg == SDVOB)
@@ -98,18 +133,87 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
        else
                return;
 
-       I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | port |
-                  VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC);
+       flags = intel_infoframe_index(frame);
+
+       val &= ~VIDEO_DIP_SELECT_MASK;
 
-       intel_dip_infoframe_csum(&avi_if);
-       for (i = 0; i < sizeof(avi_if); i += 4) {
+       I915_WRITE(VIDEO_DIP_CTL, val | port | flags);
+
+       for (i = 0; i < len; i += 4) {
                I915_WRITE(VIDEO_DIP_DATA, *data);
                data++;
        }
 
-       I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | port |
-                  VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC |
-                  VIDEO_DIP_ENABLE_AVI);
+       flags |= intel_infoframe_flags(frame);
+
+       I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags);
+}
+
+static void ironlake_write_infoframe(struct drm_encoder *encoder,
+                                    struct dip_infoframe *frame)
+{
+       uint32_t *data = (uint32_t *)frame;
+       struct drm_device *dev = encoder->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = encoder->crtc;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
+       unsigned i, len = DIP_HEADER_SIZE + frame->len;
+       u32 flags, val = I915_READ(reg);
+
+       intel_wait_for_vblank(dev, intel_crtc->pipe);
+
+       flags = intel_infoframe_index(frame);
+
+       val &= ~VIDEO_DIP_SELECT_MASK;
+
+       I915_WRITE(reg, val | flags);
+
+       for (i = 0; i < len; i += 4) {
+               I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
+               data++;
+       }
+
+       flags |= intel_infoframe_flags(frame);
+
+       I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
+}
+static void intel_set_infoframe(struct drm_encoder *encoder,
+                               struct dip_infoframe *frame)
+{
+       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+
+       if (!intel_hdmi->has_hdmi_sink)
+               return;
+
+       intel_dip_infoframe_csum(frame);
+       intel_hdmi->write_infoframe(encoder, frame);
+}
+
+static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
+{
+       struct dip_infoframe avi_if = {
+               .type = DIP_TYPE_AVI,
+               .ver = DIP_VERSION_AVI,
+               .len = DIP_LEN_AVI,
+       };
+
+       intel_set_infoframe(encoder, &avi_if);
+}
+
+static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
+{
+       struct dip_infoframe spd_if;
+
+       memset(&spd_if, 0, sizeof(spd_if));
+       spd_if.type = DIP_TYPE_SPD;
+       spd_if.ver = DIP_VERSION_SPD;
+       spd_if.len = DIP_LEN_SPD;
+       strcpy(spd_if.body.spd.vn, "Intel");
+       strcpy(spd_if.body.spd.pd, "Integrated gfx");
+       spd_if.body.spd.sdi = DIP_SPD_PC;
+
+       intel_set_infoframe(encoder, &spd_if);
 }
 
 static void intel_hdmi_mode_set(struct drm_encoder *encoder,
@@ -156,6 +260,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
        POSTING_READ(intel_hdmi->sdvox_reg);
 
        intel_hdmi_set_avi_infoframe(encoder);
+       intel_hdmi_set_spd_infoframe(encoder);
 }
 
 static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
@@ -433,6 +538,11 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 
        intel_hdmi->sdvox_reg = sdvox_reg;
 
+       if (!HAS_PCH_SPLIT(dev))
+               intel_hdmi->write_infoframe = i9xx_write_infoframe;
+       else
+               intel_hdmi->write_infoframe = ironlake_write_infoframe;
+
        drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
 
        intel_hdmi_add_properties(intel_hdmi, connector);
index b28f7bd..2e8ddfc 100644 (file)
@@ -688,6 +688,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),
                },
        },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Dell OptiPlex FX170",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex FX170"),
+               },
+       },
        {
                .callback = intel_no_lvds_dmi_callback,
                .ident = "AOpen Mini PC",
index a06ff07..05f500c 100644 (file)
@@ -83,11 +83,15 @@ intel_pch_panel_fitting(struct drm_device *dev,
                        u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
                        if (scaled_width > scaled_height) { /* pillar */
                                width = scaled_height / mode->vdisplay;
+                               if (width & 1)
+                                       width++;
                                x = (adjusted_mode->hdisplay - width + 1) / 2;
                                y = 0;
                                height = adjusted_mode->vdisplay;
                        } else if (scaled_width < scaled_height) { /* letter */
                                height = scaled_width / mode->hdisplay;
+                               if (height & 1)
+                                   height++;
                                y = (adjusted_mode->vdisplay - height + 1) / 2;
                                x = 0;
                                width = adjusted_mode->hdisplay;
index e961568..47b9b27 100644 (file)
@@ -1321,6 +1321,9 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
                ring->get_seqno = pc_render_get_seqno;
        }
 
+       if (!I915_NEED_GFX_HWS(dev))
+               ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
+
        ring->dev = dev;
        INIT_LIST_HEAD(&ring->active_list);
        INIT_LIST_HEAD(&ring->request_list);
index 3896ef8..9f363e0 100644 (file)
@@ -5,6 +5,7 @@
 ccflags-y := -Iinclude/drm
 
 hostprogs-y := mkregtable
+clean-files := rn50_reg_safe.h r100_reg_safe.h r200_reg_safe.h rv515_reg_safe.h r300_reg_safe.h r420_reg_safe.h rs600_reg_safe.h r600_reg_safe.h evergreen_reg_safe.h cayman_reg_safe.h
 
 quiet_cmd_mkregtable = MKREGTABLE $@
       cmd_mkregtable = $(obj)/mkregtable $< > $@
index ebdb0fd..e88c644 100644 (file)
@@ -1245,6 +1245,9 @@ struct atom_context *atom_parse(struct card_info *card, void *bios)
        char name[512];
        int i;
 
+       if (!ctx)
+               return NULL;
+
        ctx->card = card;
        ctx->bios = bios;
 
index 189e865..a134790 100644 (file)
@@ -428,7 +428,7 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3
                last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
 
        i = (reg >> 7);
-       if (i > last_reg) {
+       if (i >= last_reg) {
                dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
                return -EINVAL;
        }
index db8ef19..cf83aa0 100644 (file)
@@ -915,12 +915,11 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
 {
        struct r600_cs_track *track = (struct r600_cs_track *)p->track;
        struct radeon_cs_reloc *reloc;
-       u32 last_reg = ARRAY_SIZE(r600_reg_safe_bm);
        u32 m, i, tmp, *ib;
        int r;
 
        i = (reg >> 7);
-       if (i > last_reg) {
+       if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
                dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
                return -EINVAL;
        }
index a74217c..e0138b6 100644 (file)
@@ -2557,6 +2557,7 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
        u16 offset, misc, misc2 = 0;
        u8 rev, blocks, tmp;
        int state_index = 0;
+       struct radeon_i2c_bus_rec i2c_bus;
 
        rdev->pm.default_power_state_index = -1;
 
@@ -2575,7 +2576,6 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
        offset = combios_get_table_offset(dev, COMBIOS_OVERDRIVE_INFO_TABLE);
        if (offset) {
                u8 thermal_controller = 0, gpio = 0, i2c_addr = 0, clk_bit = 0, data_bit = 0;
-               struct radeon_i2c_bus_rec i2c_bus;
 
                rev = RBIOS8(offset);
 
@@ -2617,6 +2617,25 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
                                i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
                        }
                }
+       } else {
+               /* boards with a thermal chip, but no overdrive table */
+
+               /* Asus 9600xt has an f75375 on the monid bus */
+               if ((dev->pdev->device == 0x4152) &&
+                   (dev->pdev->subsystem_vendor == 0x1043) &&
+                   (dev->pdev->subsystem_device == 0xc002)) {
+                       i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
+                       rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
+                       if (rdev->pm.i2c_bus) {
+                               struct i2c_board_info info = { };
+                               const char *name = "f75375";
+                               info.addr = 0x28;
+                               strlcpy(info.type, name, sizeof(info.type));
+                               i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
+                               DRM_INFO("Possible %s thermal controller at 0x%02x\n",
+                                        name, info.addr);
+                       }
+               }
        }
 
        if (rdev->flags & RADEON_IS_MOBILITY) {
index 9792d4f..6d6b5f1 100644 (file)
@@ -430,6 +430,45 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
        return 0;
 }
 
+/*
+ * Some integrated ATI Radeon chipset implementations (e. g.
+ * Asus M2A-VM HDMI) may indicate the availability of a DDC,
+ * even when there's no monitor connected. For these connectors
+ * following DDC probe extension will be applied: check also for the
+ * availability of EDID with at least a correct EDID header. Only then,
+ * DDC is assumed to be available. This prevents drm_get_edid() and
+ * drm_edid_block_valid() from periodically dumping data and kernel
+ * errors into the logs and onto the terminal.
+ */
+static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
+                                    uint32_t supported_device,
+                                    int connector_type)
+{
+       /* Asus M2A-VM HDMI board sends data to i2c bus even,
+        * if HDMI add-on card is not plugged in or HDMI is disabled in
+        * BIOS. Valid DDC can only be assumed, if also a valid EDID header
+        * can be retrieved via i2c bus during DDC probe */
+       if ((dev->pdev->device == 0x791e) &&
+           (dev->pdev->subsystem_vendor == 0x1043) &&
+           (dev->pdev->subsystem_device == 0x826d)) {
+               if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
+                   (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
+                       return true;
+       }
+       /* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
+        * for a DVI connector that is not implemented */
+       if ((dev->pdev->device == 0x796e) &&
+           (dev->pdev->subsystem_vendor == 0x1019) &&
+           (dev->pdev->subsystem_device == 0x2615)) {
+               if ((connector_type == DRM_MODE_CONNECTOR_DVID) &&
+                   (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
+                       return true;
+       }
+
+       /* Default: no EDID header probe required for DDC probing */
+       return false;
+}
+
 static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
                                          struct drm_connector *connector)
 {
@@ -661,7 +700,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
                ret = connector_status_disconnected;
 
        if (radeon_connector->ddc_bus)
-               dret = radeon_ddc_probe(radeon_connector);
+               dret = radeon_ddc_probe(radeon_connector,
+                                       radeon_connector->requires_extended_probe);
        if (dret) {
                if (radeon_connector->edid) {
                        kfree(radeon_connector->edid);
@@ -833,7 +873,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
        bool dret = false;
 
        if (radeon_connector->ddc_bus)
-               dret = radeon_ddc_probe(radeon_connector);
+               dret = radeon_ddc_probe(radeon_connector,
+                                       radeon_connector->requires_extended_probe);
        if (dret) {
                if (radeon_connector->edid) {
                        kfree(radeon_connector->edid);
@@ -1251,7 +1292,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                                if (radeon_dp_getdpcd(radeon_connector))
                                        ret = connector_status_connected;
                        } else {
-                               if (radeon_ddc_probe(radeon_connector))
+                               if (radeon_ddc_probe(radeon_connector,
+                                                    radeon_connector->requires_extended_probe))
                                        ret = connector_status_connected;
                        }
                }
@@ -1406,6 +1448,9 @@ radeon_add_atom_connector(struct drm_device *dev,
        radeon_connector->shared_ddc = shared_ddc;
        radeon_connector->connector_object_id = connector_object_id;
        radeon_connector->hpd = *hpd;
+       radeon_connector->requires_extended_probe =
+               radeon_connector_needs_extended_probe(rdev, supported_device,
+                                                       connector_type);
        radeon_connector->router = *router;
        if (router->ddc_valid || router->cd_valid) {
                radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
@@ -1752,6 +1797,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
        radeon_connector->devices = supported_device;
        radeon_connector->connector_object_id = connector_object_id;
        radeon_connector->hpd = *hpd;
+       radeon_connector->requires_extended_probe =
+               radeon_connector_needs_extended_probe(rdev, supported_device,
+                                                       connector_type);
        switch (connector_type) {
        case DRM_MODE_CONNECTOR_VGA:
                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
index 7cfaa7e..440e6ec 100644 (file)
@@ -704,8 +704,9 @@ int radeon_device_init(struct radeon_device *rdev,
        rdev->gpu_lockup = false;
        rdev->accel_working = false;
 
-       DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
-               radeon_family_name[rdev->family], pdev->vendor, pdev->device);
+       DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
+               radeon_family_name[rdev->family], pdev->vendor, pdev->device,
+               pdev->subsystem_vendor, pdev->subsystem_device);
 
        /* mutex initialization are all done here so we
         * can recall function without having locking issues */
index 28f4655..1a85894 100644 (file)
@@ -751,8 +751,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
        if (!radeon_connector->ddc_bus)
                return -1;
        edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+       /* Log EDID retrieval status here. In particular with regard to
+        * connectors with requires_extended_probe flag set, that will prevent
+        * function radeon_dvi_detect() to fetch EDID on this connector,
+        * as long as there is no valid EDID header found */
        if (edid) {
+               DRM_INFO("Radeon display connector %s: Found valid EDID",
+                               drm_get_connector_name(connector));
                kfree(edid);
+       } else {
+               DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
+                               drm_get_connector_name(connector));
        }
        return ret;
 }
index 85f033f..e71d2ed 100644 (file)
@@ -50,8 +50,8 @@
  *   2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs
  *   2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query
  *   2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query
- *   2.10.0 - fusion 2D tiling, initial compute support for the CS checker
- *   2.11.0 - backend map
+ *   2.10.0 - fusion 2D tiling
+ *   2.11.0 - backend map, initial compute support for the CS checker
  */
 #define KMS_DRIVER_MAJOR       2
 #define KMS_DRIVER_MINOR       11
index 781196d..6c111c1 100644 (file)
  * radeon_ddc_probe
  *
  */
-bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
+bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
 {
-       u8 out_buf[] = { 0x0, 0x0};
-       u8 buf[2];
+       u8 out = 0x0;
+       u8 buf[8];
        int ret;
        struct i2c_msg msgs[] = {
                {
                        .addr = 0x50,
                        .flags = 0,
                        .len = 1,
-                       .buf = out_buf,
+                       .buf = &out,
                },
                {
                        .addr = 0x50,
@@ -52,15 +52,31 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
                }
        };
 
+       /* Read 8 bytes from i2c for extended probe of EDID header */
+       if (requires_extended_probe)
+               msgs[1].len = 8;
+
        /* on hw with routers, select right port */
        if (radeon_connector->router.ddc_valid)
                radeon_router_select_ddc_port(radeon_connector);
 
        ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
-       if (ret == 2)
-               return true;
-
-       return false;
+       if (ret != 2)
+               /* Couldn't find an accessible DDC on this connector */
+               return false;
+       if (requires_extended_probe) {
+               /* Probe also for valid EDID header
+                * EDID header starts with:
+                * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
+                * Only the first 6 bytes must be valid as
+                * drm_edid_block_valid() can fix the last 2 bytes */
+               if (drm_edid_header_is_valid(buf) < 6) {
+                       /* Couldn't find an accessible EDID on this
+                        * connector */
+                       return false;
+               }
+       }
+       return true;
 }
 
 /* bit banging i2c */
index 6df4e3c..d09031c 100644 (file)
@@ -438,6 +438,9 @@ struct radeon_connector {
        struct radeon_i2c_chan *ddc_bus;
        /* some systems have an hdmi and vga port with a shared ddc line */
        bool shared_ddc;
+       /* for some Radeon chip families we apply an additional EDID header
+          check as part of the DDC probe */
+       bool requires_extended_probe;
        bool use_digital;
        /* we need to mind the EDID between detect
           and get modes due to analog/digital/tvencoder */
@@ -514,7 +517,8 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
                                u8 val);
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
+                       bool requires_extended_probe);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
index 0598cd2..0b62c3c 100644 (file)
@@ -623,7 +623,7 @@ config SENSORS_LM90
          LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A,
          Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
          MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008,
-         and Winbond/Nuvoton W83L771W/G/AWG/ASG sensor chips.
+         Winbond/Nuvoton W83L771W/G/AWG/ASG and Philips SA56004 sensor chips.
 
          This driver can also be built as a module.  If so, the module
          will be called lm90.
@@ -694,14 +694,24 @@ config SENSORS_LTC4261
          be called ltc4261.
 
 config SENSORS_LM95241
-       tristate "National Semiconductor LM95241 sensor chip"
+       tristate "National Semiconductor LM95241 and compatibles"
        depends on I2C
        help
-         If you say yes here you get support for LM95241 sensor chip.
+         If you say yes here you get support for LM95231 and LM95241 sensor
+         chips.
 
          This driver can also be built as a module.  If so, the module
          will be called lm95241.
 
+config SENSORS_LM95245
+       tristate "National Semiconductor LM95245 sensor chip"
+       depends on I2C && EXPERIMENTAL
+       help
+         If you say yes here you get support for LM95245 sensor chip.
+
+         This driver can also be built as a module.  If so, the module
+         will be called lm95245.
+
 config SENSORS_MAX1111
        tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip"
        depends on SPI_MASTER
@@ -736,6 +746,16 @@ config SENSORS_MAX1619
          This driver can also be built as a module.  If so, the module
          will be called max1619.
 
+config SENSORS_MAX1668
+       tristate "Maxim MAX1668 and compatibles"
+       depends on I2C && EXPERIMENTAL
+       help
+         If you say yes here you get support for MAX1668, MAX1989 and
+         MAX1805 chips.
+
+         This driver can also be built as a module.  If so, the module
+         will be called max1668.
+
 config SENSORS_MAX6639
        tristate "Maxim MAX6639 sensor chip"
        depends on I2C && EXPERIMENTAL
@@ -767,6 +787,20 @@ config SENSORS_MAX6650
          This driver can also be built as a module.  If so, the module
          will be called max6650.
 
+config SENSORS_NTC_THERMISTOR
+       tristate "NTC thermistor support"
+       depends on EXPERIMENTAL
+       help
+         This driver supports NTC thermistors sensor reading and its
+         interpretation. The driver can also monitor the temperature and
+         send notifications about the temperature.
+
+         Currently, this driver supports
+         NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, and NCP15WL333.
+
+         This driver can also be built as a module.  If so, the module
+         will be called ntc-thermistor.
+
 config SENSORS_PC87360
        tristate "National Semiconductor PC87360 family"
        select HWMON_VID
@@ -807,92 +841,7 @@ config SENSORS_PCF8591
          These devices are hard to detect and rarely found on mainstream
          hardware.  If unsure, say N.
 
-config PMBUS
-       tristate "PMBus support"
-       depends on I2C && EXPERIMENTAL
-       default n
-       help
-         Say yes here if you want to enable PMBus support.
-
-         This driver can also be built as a module. If so, the module will
-         be called pmbus_core.
-
-if PMBUS
-
-config SENSORS_PMBUS
-       tristate "Generic PMBus devices"
-       default n
-       help
-         If you say yes here you get hardware monitoring support for generic
-         PMBus devices, including but not limited to BMR450, BMR451, BMR453,
-         BMR454, and LTC2978.
-
-         This driver can also be built as a module. If so, the module will
-         be called pmbus.
-
-config SENSORS_ADM1275
-       tristate "Analog Devices ADM1275"
-       default n
-       help
-         If you say yes here you get hardware monitoring support for Analog
-         Devices ADM1275 Hot-Swap Controller and Digital Power Monitor.
-
-         This driver can also be built as a module. If so, the module will
-         be called adm1275.
-
-config SENSORS_MAX16064
-       tristate "Maxim MAX16064"
-       default n
-       help
-         If you say yes here you get hardware monitoring support for Maxim
-         MAX16064.
-
-         This driver can also be built as a module. If so, the module will
-         be called max16064.
-
-config SENSORS_MAX34440
-       tristate "Maxim MAX34440/MAX34441"
-       default n
-       help
-         If you say yes here you get hardware monitoring support for Maxim
-         MAX34440 and MAX34441.
-
-         This driver can also be built as a module. If so, the module will
-         be called max34440.
-
-config SENSORS_MAX8688
-       tristate "Maxim MAX8688"
-       default n
-       help
-         If you say yes here you get hardware monitoring support for Maxim
-         MAX8688.
-
-         This driver can also be built as a module. If so, the module will
-         be called max8688.
-
-config SENSORS_UCD9000
-       tristate "TI UCD90120, UCD90124, UCD9090, UCD90910"
-       default n
-       help
-         If you say yes here you get hardware monitoring support for TI
-         UCD90120, UCD90124, UCD9090, UCD90910 Sequencer and System Health
-         Controllers.
-
-         This driver can also be built as a module. If so, the module will
-         be called ucd9000.
-
-config SENSORS_UCD9200
-       tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248"
-       default n
-       help
-         If you say yes here you get hardware monitoring support for TI
-         UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248
-         Digital PWM System Controllers.
-
-         This driver can also be built as a module. If so, the module will
-         be called ucd9200.
-
-endif # PMBUS
+source drivers/hwmon/pmbus/Kconfig
 
 config SENSORS_SHT15
        tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
index d7995a1..3c9ccef 100644 (file)
@@ -80,6 +80,7 @@ obj-$(CONFIG_SENSORS_LM90)    += lm90.o
 obj-$(CONFIG_SENSORS_LM92)     += lm92.o
 obj-$(CONFIG_SENSORS_LM93)     += lm93.o
 obj-$(CONFIG_SENSORS_LM95241)  += lm95241.o
+obj-$(CONFIG_SENSORS_LM95245)  += lm95245.o
 obj-$(CONFIG_SENSORS_LTC4151)  += ltc4151.o
 obj-$(CONFIG_SENSORS_LTC4215)  += ltc4215.o
 obj-$(CONFIG_SENSORS_LTC4245)  += ltc4245.o
@@ -87,10 +88,12 @@ obj-$(CONFIG_SENSORS_LTC4261)       += ltc4261.o
 obj-$(CONFIG_SENSORS_MAX1111)  += max1111.o
 obj-$(CONFIG_SENSORS_MAX16065) += max16065.o
 obj-$(CONFIG_SENSORS_MAX1619)  += max1619.o
+obj-$(CONFIG_SENSORS_MAX1668)  += max1668.o
 obj-$(CONFIG_SENSORS_MAX6639)  += max6639.o
 obj-$(CONFIG_SENSORS_MAX6642)  += max6642.o
 obj-$(CONFIG_SENSORS_MAX6650)  += max6650.o
 obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
+obj-$(CONFIG_SENSORS_NTC_THERMISTOR)   += ntc_thermistor.o
 obj-$(CONFIG_SENSORS_PC87360)  += pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)  += pc87427.o
 obj-$(CONFIG_SENSORS_PCF8591)  += pcf8591.o
@@ -121,15 +124,7 @@ obj-$(CONFIG_SENSORS_W83L786NG)    += w83l786ng.o
 obj-$(CONFIG_SENSORS_WM831X)   += wm831x-hwmon.o
 obj-$(CONFIG_SENSORS_WM8350)   += wm8350-hwmon.o
 
-# PMBus drivers
-obj-$(CONFIG_PMBUS)            += pmbus_core.o
-obj-$(CONFIG_SENSORS_PMBUS)    += pmbus.o
-obj-$(CONFIG_SENSORS_ADM1275)  += adm1275.o
-obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
-obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
-obj-$(CONFIG_SENSORS_MAX8688)  += max8688.o
-obj-$(CONFIG_SENSORS_UCD9000)  += ucd9000.o
-obj-$(CONFIG_SENSORS_UCD9200)  += ucd9200.o
+obj-$(CONFIG_PMBUS)            += pmbus/
 
 ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
 
index 0070d54..59d83e8 100644 (file)
@@ -44,7 +44,9 @@
 #define BASE_SYSFS_ATTR_NO     2       /* Sysfs Base attr no for coretemp */
 #define NUM_REAL_CORES         16      /* Number of Real cores per cpu */
 #define CORETEMP_NAME_LENGTH   17      /* String Length of attrs */
-#define MAX_ATTRS              5       /* Maximum no of per-core attrs */
+#define MAX_CORE_ATTRS         4       /* Maximum no of basic attrs */
+#define MAX_THRESH_ATTRS       3       /* Maximum no of Threshold attrs */
+#define TOTAL_ATTRS            (MAX_CORE_ATTRS + MAX_THRESH_ATTRS)
 #define MAX_CORE_DATA          (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
 
 #ifdef CONFIG_SMP
@@ -67,6 +69,9 @@
  *             This value is passed as "id" field to rdmsr/wrmsr functions.
  * @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS,
  *             from where the temperature values should be read.
+ * @intrpt_reg: One of IA32_THERM_INTERRUPT or IA32_PACKAGE_THERM_INTERRUPT,
+ *             from where the thresholds are read.
+ * @attr_size:  Total number of pre-core attrs displayed in the sysfs.
  * @is_pkg_data: If this is 1, the temp_data holds pkgtemp data.
  *             Otherwise, temp_data holds coretemp data.
  * @valid: If this is 1, the current temperature is valid.
 struct temp_data {
        int temp;
        int ttarget;
+       int tmin;
        int tjmax;
        unsigned long last_updated;
        unsigned int cpu;
        u32 cpu_core_id;
        u32 status_reg;
+       u32 intrpt_reg;
+       int attr_size;
        bool is_pkg_data;
        bool valid;
-       struct sensor_device_attribute sd_attrs[MAX_ATTRS];
-       char attr_name[MAX_ATTRS][CORETEMP_NAME_LENGTH];
+       struct sensor_device_attribute sd_attrs[TOTAL_ATTRS];
+       char attr_name[TOTAL_ATTRS][CORETEMP_NAME_LENGTH];
        struct mutex update_lock;
 };
 
@@ -135,6 +143,19 @@ static ssize_t show_crit_alarm(struct device *dev,
        return sprintf(buf, "%d\n", (eax >> 5) & 1);
 }
 
+static ssize_t show_max_alarm(struct device *dev,
+                               struct device_attribute *devattr, char *buf)
+{
+       u32 eax, edx;
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct platform_data *pdata = dev_get_drvdata(dev);
+       struct temp_data *tdata = pdata->core_data[attr->index];
+
+       rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
+
+       return sprintf(buf, "%d\n", !!(eax & THERM_STATUS_THRESHOLD1));
+}
+
 static ssize_t show_tjmax(struct device *dev,
                        struct device_attribute *devattr, char *buf)
 {
@@ -153,6 +174,83 @@ static ssize_t show_ttarget(struct device *dev,
        return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget);
 }
 
+static ssize_t store_ttarget(struct device *dev,
+                               struct device_attribute *devattr,
+                               const char *buf, size_t count)
+{
+       struct platform_data *pdata = dev_get_drvdata(dev);
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct temp_data *tdata = pdata->core_data[attr->index];
+       u32 eax, edx;
+       unsigned long val;
+       int diff;
+
+       if (strict_strtoul(buf, 10, &val))
+               return -EINVAL;
+
+       /*
+        * THERM_MASK_THRESHOLD1 is 7 bits wide. Values are entered in terms
+        * of milli degree celsius. Hence don't accept val > (127 * 1000)
+        */
+       if (val > tdata->tjmax || val > 127000)
+               return -EINVAL;
+
+       diff = (tdata->tjmax - val) / 1000;
+
+       mutex_lock(&tdata->update_lock);
+       rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx);
+       eax = (eax & ~THERM_MASK_THRESHOLD1) |
+                               (diff << THERM_SHIFT_THRESHOLD1);
+       wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx);
+       tdata->ttarget = val;
+       mutex_unlock(&tdata->update_lock);
+
+       return count;
+}
+
+static ssize_t show_tmin(struct device *dev,
+                       struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct platform_data *pdata = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", pdata->core_data[attr->index]->tmin);
+}
+
+static ssize_t store_tmin(struct device *dev,
+                               struct device_attribute *devattr,
+                               const char *buf, size_t count)
+{
+       struct platform_data *pdata = dev_get_drvdata(dev);
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct temp_data *tdata = pdata->core_data[attr->index];
+       u32 eax, edx;
+       unsigned long val;
+       int diff;
+
+       if (strict_strtoul(buf, 10, &val))
+               return -EINVAL;
+
+       /*
+        * THERM_MASK_THRESHOLD0 is 7 bits wide. Values are entered in terms
+        * of milli degree celsius. Hence don't accept val > (127 * 1000)
+        */
+       if (val > tdata->tjmax || val > 127000)
+               return -EINVAL;
+
+       diff = (tdata->tjmax - val) / 1000;
+
+       mutex_lock(&tdata->update_lock);
+       rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx);
+       eax = (eax & ~THERM_MASK_THRESHOLD0) |
+                               (diff << THERM_SHIFT_THRESHOLD0);
+       wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx);
+       tdata->tmin = val;
+       mutex_unlock(&tdata->update_lock);
+
+       return count;
+}
+
 static ssize_t show_temp(struct device *dev,
                        struct device_attribute *devattr, char *buf)
 {
@@ -344,23 +442,31 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
                                int attr_no)
 {
        int err, i;
-       static ssize_t (*rd_ptr[MAX_ATTRS]) (struct device *dev,
+       static ssize_t (*rd_ptr[TOTAL_ATTRS]) (struct device *dev,
                        struct device_attribute *devattr, char *buf) = {
-                       show_label, show_crit_alarm, show_ttarget,
-                       show_temp, show_tjmax };
-       static const char *names[MAX_ATTRS] = {
+                       show_label, show_crit_alarm, show_temp, show_tjmax,
+                       show_max_alarm, show_ttarget, show_tmin };
+       static ssize_t (*rw_ptr[TOTAL_ATTRS]) (struct device *dev,
+                       struct device_attribute *devattr, const char *buf,
+                       size_t count) = { NULL, NULL, NULL, NULL, NULL,
+                                       store_ttarget, store_tmin };
+       static const char *names[TOTAL_ATTRS] = {
                                        "temp%d_label", "temp%d_crit_alarm",
-                                       "temp%d_max", "temp%d_input",
-                                       "temp%d_crit" };
+                                       "temp%d_input", "temp%d_crit",
+                                       "temp%d_max_alarm", "temp%d_max",
+                                       "temp%d_max_hyst" };
 
-       for (i = 0; i < MAX_ATTRS; i++) {
+       for (i = 0; i < tdata->attr_size; i++) {
                snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i],
                        attr_no);
                sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr);
                tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i];
                tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO;
+               if (rw_ptr[i]) {
+                       tdata->sd_attrs[i].dev_attr.attr.mode |= S_IWUSR;
+                       tdata->sd_attrs[i].dev_attr.store = rw_ptr[i];
+               }
                tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
-               tdata->sd_attrs[i].dev_attr.store = NULL;
                tdata->sd_attrs[i].index = attr_no;
                err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr);
                if (err)
@@ -374,38 +480,6 @@ exit_free:
        return err;
 }
 
-static void update_ttarget(__u8 cpu_model, struct temp_data *tdata,
-                               struct device *dev)
-{
-       int err;
-       u32 eax, edx;
-
-       /*
-        * Initialize ttarget value. Eventually this will be
-        * initialized with the value from MSR_IA32_THERM_INTERRUPT
-        * register. If IA32_TEMPERATURE_TARGET is supported, this
-        * value will be over written below.
-        * To Do: Patch to initialize ttarget from MSR_IA32_THERM_INTERRUPT
-        */
-       tdata->ttarget = tdata->tjmax - 20000;
-
-       /*
-        * Read the still undocumented IA32_TEMPERATURE_TARGET. It exists
-        * on older CPUs but not in this register,
-        * Atoms don't have it either.
-        */
-       if (cpu_model > 0xe && cpu_model != 0x1c) {
-               err = rdmsr_safe_on_cpu(tdata->cpu,
-                               MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
-               if (err) {
-                       dev_warn(dev,
-                       "Unable to read IA32_TEMPERATURE_TARGET MSR\n");
-               } else {
-                       tdata->ttarget = tdata->tjmax -
-                                       ((eax >> 8) & 0xff) * 1000;
-               }
-       }
-}
 
 static int __devinit chk_ucode_version(struct platform_device *pdev)
 {
@@ -464,9 +538,12 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)
 
        tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS :
                                                        MSR_IA32_THERM_STATUS;
+       tdata->intrpt_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_INTERRUPT :
+                                               MSR_IA32_THERM_INTERRUPT;
        tdata->is_pkg_data = pkg_flag;
        tdata->cpu = cpu;
        tdata->cpu_core_id = TO_CORE_ID(cpu);
+       tdata->attr_size = MAX_CORE_ATTRS;
        mutex_init(&tdata->update_lock);
        return tdata;
 }
@@ -516,7 +593,17 @@ static int create_core_data(struct platform_data *pdata,
        else
                tdata->tjmax = get_tjmax(c, cpu, &pdev->dev);
 
-       update_ttarget(c->x86_model, tdata, &pdev->dev);
+       /*
+        * Test if we can access the intrpt register. If so, increase the
+        * 'size' enough to have ttarget/tmin/max_alarm interfaces.
+        * Initialize ttarget with bits 16:22 of MSR_IA32_THERM_INTERRUPT
+        */
+       err = rdmsr_safe_on_cpu(cpu, tdata->intrpt_reg, &eax, &edx);
+       if (!err) {
+               tdata->attr_size += MAX_THRESH_ATTRS;
+               tdata->ttarget = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000;
+       }
+
        pdata->core_data[attr_no] = tdata;
 
        /* Create sysfs interfaces */
@@ -553,7 +640,7 @@ static void coretemp_remove_core(struct platform_data *pdata,
        struct temp_data *tdata = pdata->core_data[indx];
 
        /* Remove the sysfs attributes */
-       for (i = 0; i < MAX_ATTRS; i++)
+       for (i = 0; i < tdata->attr_size; i++)
                device_remove_file(dev, &tdata->sd_attrs[i].dev_attr);
 
        kfree(pdata->core_data[indx]);
index 2f94f95..90ddb87 100644 (file)
@@ -54,6 +54,9 @@
  * and extended mode. They are mostly compatible with LM90 except for a data
  * format difference for the temperature value registers.
  *
+ * This driver also supports the SA56004 from Philips. This device is
+ * pin-compatible with the LM86, the ED/EDP parts are also address-compatible.
+ *
  * Since the LM90 was the first chipset supported by this driver, most
  * comments will refer to this chipset, but are actually general and
  * concern all supported chipsets, unless mentioned otherwise.
  * MAX6659 can have address 0x4c, 0x4d or 0x4e.
  * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
  * 0x4c, 0x4d or 0x4e.
+ * SA56004 can have address 0x48 through 0x4F.
  */
 
 static const unsigned short normal_i2c[] = {
-       0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
+       0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+       0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
 
 enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
-       max6646, w83l771, max6696 };
+       max6646, w83l771, max6696, sa56004 };
 
 /*
  * The LM90 registers
@@ -152,6 +157,10 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
 #define MAX6659_REG_R_LOCAL_EMERG      0x17
 #define MAX6659_REG_W_LOCAL_EMERG      0x17
 
+/*  SA56004 registers */
+
+#define SA56004_REG_R_LOCAL_TEMPL 0x22
+
 #define LM90_DEF_CONVRATE_RVAL 6       /* Def conversion rate register value */
 #define LM90_MAX_CONVRATE_MS   16000   /* Maximum conversion rate in ms */
 
@@ -161,7 +170,6 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
 #define LM90_FLAG_ADT7461_EXT  (1 << 0) /* ADT7461 extended mode       */
 /* Device features */
 #define LM90_HAVE_OFFSET       (1 << 1) /* temperature offset register */
-#define LM90_HAVE_LOCAL_EXT    (1 << 2) /* extended local temperature  */
 #define LM90_HAVE_REM_LIMIT_EXT        (1 << 3) /* extended remote limit       */
 #define LM90_HAVE_EMERGENCY    (1 << 4) /* 3rd upper (emergency) limit */
 #define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm           */
@@ -192,6 +200,7 @@ static const struct i2c_device_id lm90_id[] = {
        { "max6696", max6696 },
        { "nct1008", adt7461 },
        { "w83l771", w83l771 },
+       { "sa56004", sa56004 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, lm90_id);
@@ -204,6 +213,7 @@ struct lm90_params {
        u16 alert_alarms;       /* Which alarm bits trigger ALERT# */
                                /* Upper 8 bits for max6695/96 */
        u8 max_convrate;        /* Maximum conversion rate register value */
+       u8 reg_local_ext;       /* Extended local temp register (optional) */
 };
 
 static const struct lm90_params lm90_params[] = {
@@ -235,19 +245,20 @@ static const struct lm90_params lm90_params[] = {
                .max_convrate = 9,
        },
        [max6646] = {
-               .flags = LM90_HAVE_LOCAL_EXT,
                .alert_alarms = 0x7c,
                .max_convrate = 6,
+               .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
        },
        [max6657] = {
-               .flags = LM90_HAVE_LOCAL_EXT,
                .alert_alarms = 0x7c,
                .max_convrate = 8,
+               .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
        },
        [max6659] = {
-               .flags = LM90_HAVE_LOCAL_EXT | LM90_HAVE_EMERGENCY,
+               .flags = LM90_HAVE_EMERGENCY,
                .alert_alarms = 0x7c,
                .max_convrate = 8,
+               .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
        },
        [max6680] = {
                .flags = LM90_HAVE_OFFSET,
@@ -255,16 +266,23 @@ static const struct lm90_params lm90_params[] = {
                .max_convrate = 7,
        },
        [max6696] = {
-               .flags = LM90_HAVE_LOCAL_EXT | LM90_HAVE_EMERGENCY
+               .flags = LM90_HAVE_EMERGENCY
                  | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3,
                .alert_alarms = 0x187c,
                .max_convrate = 6,
+               .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
        },
        [w83l771] = {
                .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
                .alert_alarms = 0x7c,
                .max_convrate = 8,
        },
+       [sa56004] = {
+               .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
+               .alert_alarms = 0x7b,
+               .max_convrate = 9,
+               .reg_local_ext = SA56004_REG_R_LOCAL_TEMPL,
+       },
 };
 
 /*
@@ -286,6 +304,7 @@ struct lm90_data {
        u16 alert_alarms;       /* Which alarm bits trigger ALERT# */
                                /* Upper 8 bits for max6695/96 */
        u8 max_convrate;        /* Maximum conversion rate */
+       u8 reg_local_ext;       /* local extension register offset */
 
        /* registers values */
        s8 temp8[8];    /* 0: local low limit
@@ -452,9 +471,9 @@ static struct lm90_data *lm90_update_device(struct device *dev)
                lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]);
                lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst);
 
-               if (data->flags & LM90_HAVE_LOCAL_EXT) {
+               if (data->reg_local_ext) {
                        lm90_read16(client, LM90_REG_R_LOCAL_TEMP,
-                                   MAX6657_REG_R_LOCAL_TEMPL,
+                                   data->reg_local_ext,
                                    &data->temp11[4]);
                } else {
                        if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP,
@@ -1092,7 +1111,7 @@ static int lm90_detect(struct i2c_client *new_client,
        struct i2c_adapter *adapter = new_client->adapter;
        int address = new_client->addr;
        const char *name = NULL;
-       int man_id, chip_id, reg_config1, reg_convrate;
+       int man_id, chip_id, reg_config1, reg_config2, reg_convrate;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
@@ -1108,15 +1127,16 @@ static int lm90_detect(struct i2c_client *new_client,
                                                LM90_REG_R_CONVRATE)) < 0)
                return -ENODEV;
 
-       if ((address == 0x4C || address == 0x4D)
-        && man_id == 0x01) { /* National Semiconductor */
-               int reg_config2;
-
+       if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) {
                reg_config2 = i2c_smbus_read_byte_data(new_client,
                                                LM90_REG_R_CONFIG2);
                if (reg_config2 < 0)
                        return -ENODEV;
+       } else
+               reg_config2 = 0;        /* Make compiler happy */
 
+       if ((address == 0x4C || address == 0x4D)
+        && man_id == 0x01) { /* National Semiconductor */
                if ((reg_config1 & 0x2A) == 0x00
                 && (reg_config2 & 0xF8) == 0x00
                 && reg_convrate <= 0x09) {
@@ -1245,13 +1265,6 @@ static int lm90_detect(struct i2c_client *new_client,
        } else
        if (address == 0x4C
         && man_id == 0x5C) { /* Winbond/Nuvoton */
-               int reg_config2;
-
-               reg_config2 = i2c_smbus_read_byte_data(new_client,
-                                               LM90_REG_R_CONFIG2);
-               if (reg_config2 < 0)
-                       return -ENODEV;
-
                if ((reg_config1 & 0x2A) == 0x00
                 && (reg_config2 & 0xF8) == 0x00) {
                        if (chip_id == 0x01 /* W83L771W/G */
@@ -1263,6 +1276,15 @@ static int lm90_detect(struct i2c_client *new_client,
                                name = "w83l771";
                        }
                }
+       } else
+       if (address >= 0x48 && address <= 0x4F
+        && man_id == 0xA1) { /*  NXP Semiconductor/Philips */
+               if (chip_id == 0x00
+                && (reg_config1 & 0x2A) == 0x00
+                && (reg_config2 & 0xFE) == 0x00
+                && reg_convrate <= 0x09) {
+                       name = "sa56004";
+               }
        }
 
        if (!name) { /* identification failed */
@@ -1368,6 +1390,7 @@ static int lm90_probe(struct i2c_client *new_client,
 
        /* Set chip capabilities */
        data->flags = lm90_params[data->kind].flags;
+       data->reg_local_ext = lm90_params[data->kind].reg_local_ext;
 
        /* Set maximum conversion rate */
        data->max_convrate = lm90_params[data->kind].max_convrate;
index d3b464b..513901d 100644 (file)
@@ -74,8 +74,9 @@ static const unsigned short normal_i2c[] = {
 #define TT_OFF 0
 #define TT_ON 1
 #define TT_MASK 7
-#define MANUFACTURER_ID 0x01
-#define DEFAULT_REVISION 0xA4
+#define NATSEMI_MAN_ID 0x01
+#define LM95231_CHIP_ID        0xA1
+#define LM95241_CHIP_ID        0xA4
 
 static const u8 lm95241_reg_address[] = {
        LM95241_REG_R_LOCAL_TEMPH,
@@ -338,20 +339,25 @@ static int lm95241_detect(struct i2c_client *new_client,
                          struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = new_client->adapter;
-       int address = new_client->addr;
        const char *name;
+       int mfg_id, chip_id;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
-       if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID)
-            == MANUFACTURER_ID)
-           && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
-               == DEFAULT_REVISION)) {
-               name = DEVNAME;
-       } else {
-               dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n",
-                       address);
+       mfg_id = i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID);
+       if (mfg_id != NATSEMI_MAN_ID)
+               return -ENODEV;
+
+       chip_id = i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID);
+       switch (chip_id) {
+       case LM95231_CHIP_ID:
+               name = "lm95231";
+               break;
+       case LM95241_CHIP_ID:
+               name = "lm95241";
+               break;
+       default:
                return -ENODEV;
        }
 
@@ -431,7 +437,8 @@ static int lm95241_remove(struct i2c_client *client)
 
 /* Driver data (common to all clients) */
 static const struct i2c_device_id lm95241_id[] = {
-       { DEVNAME, 0 },
+       { "lm95231", 0 },
+       { "lm95241", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, lm95241_id);
diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c
new file mode 100644 (file)
index 0000000..dce9e68
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+ * Copyright (C) 2011 Alexander Stein <alexander.stein@systec-electronic.com>
+ *
+ * The LM95245 is a sensor chip made by National Semiconductors.
+ * It reports up to two temperatures (its own plus an external one).
+ * Complete datasheet can be obtained from National's website at:
+ *   http://www.national.com/ds.cgi/LM/LM95245.pdf
+ *
+ * This driver is based on lm95241.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+
+#define DEVNAME "lm95245"
+
+static const unsigned short normal_i2c[] = {
+       0x18, 0x19, 0x29, 0x4c, 0x4d, I2C_CLIENT_END };
+
+/* LM95245 registers */
+/* general registers */
+#define LM95245_REG_RW_CONFIG1         0x03
+#define LM95245_REG_RW_CONVERS_RATE    0x04
+#define LM95245_REG_W_ONE_SHOT         0x0F
+
+/* diode configuration */
+#define LM95245_REG_RW_CONFIG2         0xBF
+#define LM95245_REG_RW_REMOTE_OFFH     0x11
+#define LM95245_REG_RW_REMOTE_OFFL     0x12
+
+/* status registers */
+#define LM95245_REG_R_STATUS1          0x02
+#define LM95245_REG_R_STATUS2          0x33
+
+/* limit registers */
+#define LM95245_REG_RW_REMOTE_OS_LIMIT         0x07
+#define LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT    0x20
+#define LM95245_REG_RW_REMOTE_TCRIT_LIMIT      0x19
+#define LM95245_REG_RW_COMMON_HYSTERESIS       0x21
+
+/* temperature signed */
+#define LM95245_REG_R_LOCAL_TEMPH_S    0x00
+#define LM95245_REG_R_LOCAL_TEMPL_S    0x30
+#define LM95245_REG_R_REMOTE_TEMPH_S   0x01
+#define LM95245_REG_R_REMOTE_TEMPL_S   0x10
+/* temperature unsigned */
+#define LM95245_REG_R_REMOTE_TEMPH_U   0x31
+#define LM95245_REG_R_REMOTE_TEMPL_U   0x32
+
+/* id registers */
+#define LM95245_REG_R_MAN_ID           0xFE
+#define LM95245_REG_R_CHIP_ID          0xFF
+
+/* LM95245 specific bitfields */
+#define CFG_STOP               0x40
+#define CFG_REMOTE_TCRIT_MASK  0x10
+#define CFG_REMOTE_OS_MASK     0x08
+#define CFG_LOCAL_TCRIT_MASK   0x04
+#define CFG_LOCAL_OS_MASK      0x02
+
+#define CFG2_OS_A0             0x40
+#define CFG2_DIODE_FAULT_OS    0x20
+#define CFG2_DIODE_FAULT_TCRIT 0x10
+#define CFG2_REMOTE_TT         0x08
+#define CFG2_REMOTE_FILTER_DIS 0x00
+#define CFG2_REMOTE_FILTER_EN  0x06
+
+/* conversation rate in ms */
+#define RATE_CR0063    0x00
+#define RATE_CR0364    0x01
+#define RATE_CR1000    0x02
+#define RATE_CR2500    0x03
+
+#define STATUS1_DIODE_FAULT    0x04
+#define STATUS1_RTCRIT         0x02
+#define STATUS1_LOC            0x01
+
+#define MANUFACTURER_ID                0x01
+#define DEFAULT_REVISION       0xB3
+
+static const u8 lm95245_reg_address[] = {
+       LM95245_REG_R_LOCAL_TEMPH_S,
+       LM95245_REG_R_LOCAL_TEMPL_S,
+       LM95245_REG_R_REMOTE_TEMPH_S,
+       LM95245_REG_R_REMOTE_TEMPL_S,
+       LM95245_REG_R_REMOTE_TEMPH_U,
+       LM95245_REG_R_REMOTE_TEMPL_U,
+       LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT,
+       LM95245_REG_RW_REMOTE_TCRIT_LIMIT,
+       LM95245_REG_RW_COMMON_HYSTERESIS,
+       LM95245_REG_R_STATUS1,
+};
+
+/* Client data (each client gets its own) */
+struct lm95245_data {
+       struct device *hwmon_dev;
+       struct mutex update_lock;
+       unsigned long last_updated;     /* in jiffies */
+       unsigned long interval; /* in msecs */
+       bool valid;             /* zero until following fields are valid */
+       /* registers values */
+       u8 regs[ARRAY_SIZE(lm95245_reg_address)];
+       u8 config1, config2;
+};
+
+/* Conversions */
+static int temp_from_reg_unsigned(u8 val_h, u8 val_l)
+{
+       return val_h * 1000 + val_l * 1000 / 256;
+}
+
+static int temp_from_reg_signed(u8 val_h, u8 val_l)
+{
+       if (val_h & 0x80)
+               return (val_h - 0x100) * 1000;
+       return temp_from_reg_unsigned(val_h, val_l);
+}
+
+static struct lm95245_data *lm95245_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm95245_data *data = i2c_get_clientdata(client);
+
+       mutex_lock(&data->update_lock);
+
+       if (time_after(jiffies, data->last_updated
+               + msecs_to_jiffies(data->interval)) || !data->valid) {
+               int i;
+
+               dev_dbg(&client->dev, "Updating lm95245 data.\n");
+               for (i = 0; i < ARRAY_SIZE(lm95245_reg_address); i++)
+                       data->regs[i]
+                         = i2c_smbus_read_byte_data(client,
+                                                    lm95245_reg_address[i]);
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+
+       mutex_unlock(&data->update_lock);
+
+       return data;
+}
+
+static unsigned long lm95245_read_conversion_rate(struct i2c_client *client)
+{
+       int rate;
+       unsigned long interval;
+
+       rate = i2c_smbus_read_byte_data(client, LM95245_REG_RW_CONVERS_RATE);
+
+       switch (rate) {
+       case RATE_CR0063:
+               interval = 63;
+               break;
+       case RATE_CR0364:
+               interval = 364;
+               break;
+       case RATE_CR1000:
+               interval = 1000;
+               break;
+       case RATE_CR2500:
+       default:
+               interval = 2500;
+               break;
+       }
+
+       return interval;
+}
+
+static unsigned long lm95245_set_conversion_rate(struct i2c_client *client,
+                       unsigned long interval)
+{
+       int rate;
+
+       if (interval <= 63) {
+               interval = 63;
+               rate = RATE_CR0063;
+       } else if (interval <= 364) {
+               interval = 364;
+               rate = RATE_CR0364;
+       } else if (interval <= 1000) {
+               interval = 1000;
+               rate = RATE_CR1000;
+       } else {
+               interval = 2500;
+               rate = RATE_CR2500;
+       }
+
+       i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONVERS_RATE, rate);
+
+       return interval;
+}
+
+/* Sysfs stuff */
+static ssize_t show_input(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct lm95245_data *data = lm95245_update_device(dev);
+       int temp;
+       int index = to_sensor_dev_attr(attr)->index;
+
+       /*
+        * Index 0 (Local temp) is always signed
+        * Index 2 (Remote temp) has both signed and unsigned data
+        * use signed calculation for remote if signed bit is set
+        */
+       if (index == 0 || data->regs[index] & 0x80)
+               temp = temp_from_reg_signed(data->regs[index],
+                           data->regs[index + 1]);
+       else
+               temp = temp_from_reg_unsigned(data->regs[index + 2],
+                           data->regs[index + 3]);
+
+       return snprintf(buf, PAGE_SIZE - 1, "%d\n", temp);
+}
+
+static ssize_t show_limit(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct lm95245_data *data = lm95245_update_device(dev);
+       int index = to_sensor_dev_attr(attr)->index;
+
+       return snprintf(buf, PAGE_SIZE - 1, "%d\n",
+                       data->regs[index] * 1000);
+}
+
+static ssize_t set_limit(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm95245_data *data = i2c_get_clientdata(client);
+       int index = to_sensor_dev_attr(attr)->index;
+       unsigned long val;
+
+       if (strict_strtoul(buf, 10, &val) < 0)
+               return -EINVAL;
+
+       val /= 1000;
+
+       val = SENSORS_LIMIT(val, 0, (index == 6 ? 127 : 255));
+
+       mutex_lock(&data->update_lock);
+
+       data->valid = 0;
+
+       i2c_smbus_write_byte_data(client, lm95245_reg_address[index], val);
+
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static ssize_t set_crit_hyst(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm95245_data *data = i2c_get_clientdata(client);
+       unsigned long val;
+
+       if (strict_strtoul(buf, 10, &val) < 0)
+               return -EINVAL;
+
+       val /= 1000;
+
+       val = SENSORS_LIMIT(val, 0, 31);
+
+       mutex_lock(&data->update_lock);
+
+       data->valid = 0;
+
+       /* shared crit hysteresis */
+       i2c_smbus_write_byte_data(client, LM95245_REG_RW_COMMON_HYSTERESIS,
+               val);
+
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static ssize_t show_type(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm95245_data *data = i2c_get_clientdata(client);
+
+       return snprintf(buf, PAGE_SIZE - 1,
+               data->config2 & CFG2_REMOTE_TT ? "1\n" : "2\n");
+}
+
+static ssize_t set_type(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm95245_data *data = i2c_get_clientdata(client);
+       unsigned long val;
+
+       if (strict_strtoul(buf, 10, &val) < 0)
+               return -EINVAL;
+       if (val != 1 && val != 2)
+               return -EINVAL;
+
+       mutex_lock(&data->update_lock);
+
+       if (val == 1)
+               data->config2 |= CFG2_REMOTE_TT;
+       else
+               data->config2 &= ~CFG2_REMOTE_TT;
+
+       data->valid = 0;
+
+       i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONFIG2,
+                                 data->config2);
+
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct lm95245_data *data = lm95245_update_device(dev);
+       int index = to_sensor_dev_attr(attr)->index;
+
+       return snprintf(buf, PAGE_SIZE - 1, "%d\n",
+                       !!(data->regs[9] & index));
+}
+
+static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct lm95245_data *data = lm95245_update_device(dev);
+
+       return snprintf(buf, PAGE_SIZE - 1, "%lu\n", data->interval);
+}
+
+static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm95245_data *data = i2c_get_clientdata(client);
+       unsigned long val;
+
+       if (strict_strtoul(buf, 10, &val) < 0)
+               return -EINVAL;
+
+       mutex_lock(&data->update_lock);
+
+       data->interval = lm95245_set_conversion_rate(client, val);
+
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_limit,
+               set_limit, 6);
+static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_limit,
+               set_crit_hyst, 8);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL,
+               STATUS1_LOC);
+
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_limit,
+               set_limit, 7);
+static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_limit,
+               set_crit_hyst, 8);
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL,
+               STATUS1_RTCRIT);
+static SENSOR_DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type,
+               set_type, 0);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL,
+               STATUS1_DIODE_FAULT);
+
+static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
+               set_interval);
+
+static struct attribute *lm95245_attributes[] = {
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_type.dev_attr.attr,
+       &sensor_dev_attr_temp2_fault.dev_attr.attr,
+       &dev_attr_update_interval.attr,
+       NULL
+};
+
+static const struct attribute_group lm95245_group = {
+       .attrs = lm95245_attributes,
+};
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm95245_detect(struct i2c_client *new_client,
+                         struct i2c_board_info *info)
+{
+       struct i2c_adapter *adapter = new_client->adapter;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -ENODEV;
+
+       if (i2c_smbus_read_byte_data(new_client, LM95245_REG_R_MAN_ID)
+                       != MANUFACTURER_ID
+               || i2c_smbus_read_byte_data(new_client, LM95245_REG_R_CHIP_ID)
+                       != DEFAULT_REVISION)
+               return -ENODEV;
+
+       strlcpy(info->type, DEVNAME, I2C_NAME_SIZE);
+       return 0;
+}
+
+static void lm95245_init_client(struct i2c_client *client)
+{
+       struct lm95245_data *data = i2c_get_clientdata(client);
+
+       data->valid = 0;
+       data->interval = lm95245_read_conversion_rate(client);
+
+       data->config1 = i2c_smbus_read_byte_data(client,
+               LM95245_REG_RW_CONFIG1);
+       data->config2 = i2c_smbus_read_byte_data(client,
+               LM95245_REG_RW_CONFIG2);
+
+       if (data->config1 & CFG_STOP) {
+               /* Clear the standby bit */
+               data->config1 &= ~CFG_STOP;
+               i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONFIG1,
+                       data->config1);
+       }
+}
+
+static int lm95245_probe(struct i2c_client *new_client,
+                        const struct i2c_device_id *id)
+{
+       struct lm95245_data *data;
+       int err;
+
+       data = kzalloc(sizeof(struct lm95245_data), GFP_KERNEL);
+       if (!data) {
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       i2c_set_clientdata(new_client, data);
+       mutex_init(&data->update_lock);
+
+       /* Initialize the LM95245 chip */
+       lm95245_init_client(new_client);
+
+       /* Register sysfs hooks */
+       err = sysfs_create_group(&new_client->dev.kobj, &lm95245_group);
+       if (err)
+               goto exit_free;
+
+       data->hwmon_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               err = PTR_ERR(data->hwmon_dev);
+               goto exit_remove_files;
+       }
+
+       return 0;
+
+exit_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &lm95245_group);
+exit_free:
+       kfree(data);
+exit:
+       return err;
+}
+
+static int lm95245_remove(struct i2c_client *client)
+{
+       struct lm95245_data *data = i2c_get_clientdata(client);
+
+       hwmon_device_unregister(data->hwmon_dev);
+       sysfs_remove_group(&client->dev.kobj, &lm95245_group);
+
+       kfree(data);
+       return 0;
+}
+
+/* Driver data (common to all clients) */
+static const struct i2c_device_id lm95245_id[] = {
+       { DEVNAME, 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, lm95245_id);
+
+static struct i2c_driver lm95245_driver = {
+       .class          = I2C_CLASS_HWMON,
+       .driver = {
+               .name   = DEVNAME,
+       },
+       .probe          = lm95245_probe,
+       .remove         = lm95245_remove,
+       .id_table       = lm95245_id,
+       .detect         = lm95245_detect,
+       .address_list   = normal_i2c,
+};
+
+static int __init sensors_lm95245_init(void)
+{
+       return i2c_add_driver(&lm95245_driver);
+}
+
+static void __exit sensors_lm95245_exit(void)
+{
+       i2c_del_driver(&lm95245_driver);
+}
+
+MODULE_AUTHOR("Alexander Stein <alexander.stein@systec-electronic.com>");
+MODULE_DESCRIPTION("LM95245 sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_lm95245_init);
+module_exit(sensors_lm95245_exit);
diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c
new file mode 100644 (file)
index 0000000..20d1b2d
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+    Copyright (c) 2011 David George <david.george@ska.ac.za>
+
+    based on adm1021.c
+    some credit to Christoph Scheurer, but largely a rewrite
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+/* Addresses to scan */
+static unsigned short max1668_addr_list[] = {
+       0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
+
+/* max1668 registers */
+
+#define MAX1668_REG_TEMP(nr)   (nr)
+#define MAX1668_REG_STAT1      0x05
+#define MAX1668_REG_STAT2      0x06
+#define MAX1668_REG_MAN_ID     0xfe
+#define MAX1668_REG_DEV_ID     0xff
+
+/* limits */
+
+/* write high limits */
+#define MAX1668_REG_LIMH_WR(nr)        (0x13 + 2 * (nr))
+/* write low limits */
+#define MAX1668_REG_LIML_WR(nr)        (0x14 + 2 * (nr))
+/* read high limits */
+#define MAX1668_REG_LIMH_RD(nr)        (0x08 + 2 * (nr))
+/* read low limits */
+#define MAX1668_REG_LIML_RD(nr)        (0x09 + 2 * (nr))
+
+/* manufacturer and device ID Constants */
+#define MAN_ID_MAXIM           0x4d
+#define DEV_ID_MAX1668         0x3
+#define DEV_ID_MAX1805         0x5
+#define DEV_ID_MAX1989         0xb
+
+/* read only mode module parameter */
+static int read_only;
+module_param(read_only, bool, 0);
+MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
+
+enum chips { max1668, max1805, max1989 };
+
+struct max1668_data {
+       struct device *hwmon_dev;
+       enum chips type;
+
+       struct mutex update_lock;
+       char valid;             /* !=0 if following fields are valid */
+       unsigned long last_updated;     /* In jiffies */
+
+       /* 1x local and 4x remote */
+       s8 temp_max[5];
+       s8 temp_min[5];
+       s8 temp[5];
+       u16 alarms;
+};
+
+static struct max1668_data *max1668_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct max1668_data *data = i2c_get_clientdata(client);
+       struct max1668_data *ret = data;
+       s32 val;
+       int i;
+
+       mutex_lock(&data->update_lock);
+
+       if (data->valid && !time_after(jiffies,
+                       data->last_updated + HZ + HZ / 2))
+               goto abort;
+
+       for (i = 0; i < 5; i++) {
+               val = i2c_smbus_read_byte_data(client, MAX1668_REG_TEMP(i));
+               if (unlikely(val < 0)) {
+                       ret = ERR_PTR(val);
+                       goto abort;
+               }
+               data->temp[i] = (s8) val;
+
+               val = i2c_smbus_read_byte_data(client, MAX1668_REG_LIMH_RD(i));
+               if (unlikely(val < 0)) {
+                       ret = ERR_PTR(val);
+                       goto abort;
+               }
+               data->temp_max[i] = (s8) val;
+
+               val = i2c_smbus_read_byte_data(client, MAX1668_REG_LIML_RD(i));
+               if (unlikely(val < 0)) {
+                       ret = ERR_PTR(val);
+                       goto abort;
+               }
+               data->temp_min[i] = (s8) val;
+       }
+
+       val = i2c_smbus_read_byte_data(client, MAX1668_REG_STAT1);
+       if (unlikely(val < 0)) {
+               ret = ERR_PTR(val);
+               goto abort;
+       }
+       data->alarms = val << 8;
+
+       val = i2c_smbus_read_byte_data(client, MAX1668_REG_STAT2);
+       if (unlikely(val < 0)) {
+               ret = ERR_PTR(val);
+               goto abort;
+       }
+       data->alarms |= val;
+
+       data->last_updated = jiffies;
+       data->valid = 1;
+abort:
+       mutex_unlock(&data->update_lock);
+
+       return ret;
+}
+
+static ssize_t show_temp(struct device *dev,
+                        struct device_attribute *devattr, char *buf)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct max1668_data *data = max1668_update_device(dev);
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       return sprintf(buf, "%d\n", data->temp[index] * 1000);
+}
+
+static ssize_t show_temp_max(struct device *dev,
+                            struct device_attribute *devattr, char *buf)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct max1668_data *data = max1668_update_device(dev);
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       return sprintf(buf, "%d\n", data->temp_max[index] * 1000);
+}
+
+static ssize_t show_temp_min(struct device *dev,
+                            struct device_attribute *devattr, char *buf)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct max1668_data *data = max1668_update_device(dev);
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       return sprintf(buf, "%d\n", data->temp_min[index] * 1000);
+}
+
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       int index = to_sensor_dev_attr(attr)->index;
+       struct max1668_data *data = max1668_update_device(dev);
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       return sprintf(buf, "%u\n", (data->alarms >> index) & 0x1);
+}
+
+static ssize_t show_fault(struct device *dev,
+                         struct device_attribute *devattr, char *buf)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct max1668_data *data = max1668_update_device(dev);
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       return sprintf(buf, "%u\n",
+                      (data->alarms & (1 << 12)) && data->temp[index] == 127);
+}
+
+static ssize_t set_temp_max(struct device *dev,
+                           struct device_attribute *devattr,
+                           const char *buf, size_t count)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct max1668_data *data = i2c_get_clientdata(client);
+       long temp;
+       int ret;
+
+       ret = kstrtol(buf, 10, &temp);
+       if (ret < 0)
+               return ret;
+
+       mutex_lock(&data->update_lock);
+       data->temp_max[index] = SENSORS_LIMIT(temp/1000, -128, 127);
+       if (i2c_smbus_write_byte_data(client,
+                                       MAX1668_REG_LIMH_WR(index),
+                                       data->temp_max[index]))
+               count = -EIO;
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static ssize_t set_temp_min(struct device *dev,
+                           struct device_attribute *devattr,
+                           const char *buf, size_t count)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct max1668_data *data = i2c_get_clientdata(client);
+       long temp;
+       int ret;
+
+       ret = kstrtol(buf, 10, &temp);
+       if (ret < 0)
+               return ret;
+
+       mutex_lock(&data->update_lock);
+       data->temp_min[index] = SENSORS_LIMIT(temp/1000, -128, 127);
+       if (i2c_smbus_write_byte_data(client,
+                                       MAX1668_REG_LIML_WR(index),
+                                       data->temp_max[index]))
+               count = -EIO;
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max,
+                               set_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_min,
+                               set_temp_min, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max,
+                               set_temp_max, 1);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_min,
+                               set_temp_min, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max,
+                               set_temp_max, 2);
+static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_min,
+                               set_temp_min, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max,
+                               set_temp_max, 3);
+static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_min,
+                               set_temp_min, 3);
+static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max,
+                               set_temp_max, 4);
+static SENSOR_DEVICE_ATTR(temp5_min, S_IRUGO, show_temp_min,
+                               set_temp_min, 4);
+
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 14);
+static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 13);
+static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL, 0);
+
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_fault, NULL, 4);
+
+/* Attributes common to MAX1668, MAX1989 and MAX1805 */
+static struct attribute *max1668_attribute_common[] = {
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_min.dev_attr.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_min.dev_attr.attr,
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp3_max.dev_attr.attr,
+       &sensor_dev_attr_temp3_min.dev_attr.attr,
+       &sensor_dev_attr_temp3_input.dev_attr.attr,
+
+       &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
+
+       &sensor_dev_attr_temp2_fault.dev_attr.attr,
+       &sensor_dev_attr_temp3_fault.dev_attr.attr,
+       NULL
+};
+
+/* Attributes not present on MAX1805 */
+static struct attribute *max1668_attribute_unique[] = {
+       &sensor_dev_attr_temp4_max.dev_attr.attr,
+       &sensor_dev_attr_temp4_min.dev_attr.attr,
+       &sensor_dev_attr_temp4_input.dev_attr.attr,
+       &sensor_dev_attr_temp5_max.dev_attr.attr,
+       &sensor_dev_attr_temp5_min.dev_attr.attr,
+       &sensor_dev_attr_temp5_input.dev_attr.attr,
+
+       &sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp4_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp5_min_alarm.dev_attr.attr,
+
+       &sensor_dev_attr_temp4_fault.dev_attr.attr,
+       &sensor_dev_attr_temp5_fault.dev_attr.attr,
+       NULL
+};
+
+static mode_t max1668_attribute_mode(struct kobject *kobj,
+                                    struct attribute *attr, int index)
+{
+       int ret = S_IRUGO;
+       if (read_only)
+               return ret;
+       if (attr == &sensor_dev_attr_temp1_max.dev_attr.attr ||
+           attr == &sensor_dev_attr_temp2_max.dev_attr.attr ||
+           attr == &sensor_dev_attr_temp3_max.dev_attr.attr ||
+           attr == &sensor_dev_attr_temp4_max.dev_attr.attr ||
+           attr == &sensor_dev_attr_temp5_max.dev_attr.attr ||
+           attr == &sensor_dev_attr_temp1_min.dev_attr.attr ||
+           attr == &sensor_dev_attr_temp2_min.dev_attr.attr ||
+           attr == &sensor_dev_attr_temp3_min.dev_attr.attr ||
+           attr == &sensor_dev_attr_temp4_min.dev_attr.attr ||
+           attr == &sensor_dev_attr_temp5_min.dev_attr.attr)
+               ret |= S_IWUSR;
+       return ret;
+}
+
+static const struct attribute_group max1668_group_common = {
+       .attrs = max1668_attribute_common,
+       .is_visible = max1668_attribute_mode
+};
+
+static const struct attribute_group max1668_group_unique = {
+       .attrs = max1668_attribute_unique,
+       .is_visible = max1668_attribute_mode
+};
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int max1668_detect(struct i2c_client *client,
+                         struct i2c_board_info *info)
+{
+       struct i2c_adapter *adapter = client->adapter;
+       const char *type_name;
+       int man_id, dev_id;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -ENODEV;
+
+       /* Check for unsupported part */
+       man_id = i2c_smbus_read_byte_data(client, MAX1668_REG_MAN_ID);
+       if (man_id != MAN_ID_MAXIM)
+               return -ENODEV;
+
+       dev_id = i2c_smbus_read_byte_data(client, MAX1668_REG_DEV_ID);
+       if (dev_id < 0)
+               return -ENODEV;
+
+       type_name = NULL;
+       if (dev_id == DEV_ID_MAX1668)
+               type_name = "max1668";
+       else if (dev_id == DEV_ID_MAX1805)
+               type_name = "max1805";
+       else if (dev_id == DEV_ID_MAX1989)
+               type_name = "max1989";
+
+       if (!type_name)
+               return -ENODEV;
+
+       strlcpy(info->type, type_name, I2C_NAME_SIZE);
+
+       return 0;
+}
+
+static int max1668_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct i2c_adapter *adapter = client->adapter;
+       struct max1668_data *data;
+       int err;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -ENODEV;
+
+       data = kzalloc(sizeof(struct max1668_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, data);
+       data->type = id->driver_data;
+       mutex_init(&data->update_lock);
+
+       /* Register sysfs hooks */
+       err = sysfs_create_group(&client->dev.kobj, &max1668_group_common);
+       if (err)
+               goto error_free;
+
+       if (data->type == max1668 || data->type == max1989) {
+               err = sysfs_create_group(&client->dev.kobj,
+                                        &max1668_group_unique);
+               if (err)
+                       goto error_sysrem0;
+       }
+
+       data->hwmon_dev = hwmon_device_register(&client->dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               err = PTR_ERR(data->hwmon_dev);
+               goto error_sysrem1;
+       }
+
+       return 0;
+
+error_sysrem1:
+       if (data->type == max1668 || data->type == max1989)
+               sysfs_remove_group(&client->dev.kobj, &max1668_group_unique);
+error_sysrem0:
+       sysfs_remove_group(&client->dev.kobj, &max1668_group_common);
+error_free:
+       kfree(data);
+       return err;
+}
+
+static int max1668_remove(struct i2c_client *client)
+{
+       struct max1668_data *data = i2c_get_clientdata(client);
+
+       hwmon_device_unregister(data->hwmon_dev);
+       if (data->type == max1668 || data->type == max1989)
+               sysfs_remove_group(&client->dev.kobj, &max1668_group_unique);
+
+       sysfs_remove_group(&client->dev.kobj, &max1668_group_common);
+
+       kfree(data);
+       return 0;
+}
+
+static const struct i2c_device_id max1668_id[] = {
+       { "max1668", max1668 },
+       { "max1805", max1805 },
+       { "max1989", max1989 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, max1668_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver max1668_driver = {
+       .class = I2C_CLASS_HWMON,
+       .driver = {
+                 .name = "max1668",
+                 },
+       .probe = max1668_probe,
+       .remove = max1668_remove,
+       .id_table = max1668_id,
+       .detect = max1668_detect,
+       .address_list = max1668_addr_list,
+};
+
+static int __init sensors_max1668_init(void)
+{
+       return i2c_add_driver(&max1668_driver);
+}
+
+static void __exit sensors_max1668_exit(void)
+{
+       i2c_del_driver(&max1668_driver);
+}
+
+MODULE_AUTHOR("David George <david.george@ska.ac.za>");
+MODULE_DESCRIPTION("MAX1668 remote temperature sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_max1668_init)
+module_exit(sensors_max1668_exit)
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
new file mode 100644 (file)
index 0000000..d7926f4
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+ * ntc_thermistor.c - NTC Thermistors
+ *
+ *  Copyright (C) 2010 Samsung Electronics
+ *  MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/math64.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+
+#include <linux/platform_data/ntc_thermistor.h>
+
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+struct ntc_compensation {
+       int             temp_C;
+       unsigned int    ohm;
+};
+
+/*
+ * A compensation table should be sorted by the values of .ohm
+ * in descending order.
+ * The following compensation tables are from the specification of Murata NTC
+ * Thermistors Datasheet
+ */
+const struct ntc_compensation ncpXXwb473[] = {
+       { .temp_C       = -40, .ohm     = 1747920 },
+       { .temp_C       = -35, .ohm     = 1245428 },
+       { .temp_C       = -30, .ohm     = 898485 },
+       { .temp_C       = -25, .ohm     = 655802 },
+       { .temp_C       = -20, .ohm     = 483954 },
+       { .temp_C       = -15, .ohm     = 360850 },
+       { .temp_C       = -10, .ohm     = 271697 },
+       { .temp_C       = -5, .ohm      = 206463 },
+       { .temp_C       = 0, .ohm       = 158214 },
+       { .temp_C       = 5, .ohm       = 122259 },
+       { .temp_C       = 10, .ohm      = 95227 },
+       { .temp_C       = 15, .ohm      = 74730 },
+       { .temp_C       = 20, .ohm      = 59065 },
+       { .temp_C       = 25, .ohm      = 47000 },
+       { .temp_C       = 30, .ohm      = 37643 },
+       { .temp_C       = 35, .ohm      = 30334 },
+       { .temp_C       = 40, .ohm      = 24591 },
+       { .temp_C       = 45, .ohm      = 20048 },
+       { .temp_C       = 50, .ohm      = 16433 },
+       { .temp_C       = 55, .ohm      = 13539 },
+       { .temp_C       = 60, .ohm      = 11209 },
+       { .temp_C       = 65, .ohm      = 9328 },
+       { .temp_C       = 70, .ohm      = 7798 },
+       { .temp_C       = 75, .ohm      = 6544 },
+       { .temp_C       = 80, .ohm      = 5518 },
+       { .temp_C       = 85, .ohm      = 4674 },
+       { .temp_C       = 90, .ohm      = 3972 },
+       { .temp_C       = 95, .ohm      = 3388 },
+       { .temp_C       = 100, .ohm     = 2902 },
+       { .temp_C       = 105, .ohm     = 2494 },
+       { .temp_C       = 110, .ohm     = 2150 },
+       { .temp_C       = 115, .ohm     = 1860 },
+       { .temp_C       = 120, .ohm     = 1615 },
+       { .temp_C       = 125, .ohm     = 1406 },
+};
+const struct ntc_compensation ncpXXwl333[] = {
+       { .temp_C       = -40, .ohm     = 1610154 },
+       { .temp_C       = -35, .ohm     = 1130850 },
+       { .temp_C       = -30, .ohm     = 802609 },
+       { .temp_C       = -25, .ohm     = 575385 },
+       { .temp_C       = -20, .ohm     = 416464 },
+       { .temp_C       = -15, .ohm     = 304219 },
+       { .temp_C       = -10, .ohm     = 224193 },
+       { .temp_C       = -5, .ohm      = 166623 },
+       { .temp_C       = 0, .ohm       = 124850 },
+       { .temp_C       = 5, .ohm       = 94287 },
+       { .temp_C       = 10, .ohm      = 71747 },
+       { .temp_C       = 15, .ohm      = 54996 },
+       { .temp_C       = 20, .ohm      = 42455 },
+       { .temp_C       = 25, .ohm      = 33000 },
+       { .temp_C       = 30, .ohm      = 25822 },
+       { .temp_C       = 35, .ohm      = 20335 },
+       { .temp_C       = 40, .ohm      = 16115 },
+       { .temp_C       = 45, .ohm      = 12849 },
+       { .temp_C       = 50, .ohm      = 10306 },
+       { .temp_C       = 55, .ohm      = 8314 },
+       { .temp_C       = 60, .ohm      = 6746 },
+       { .temp_C       = 65, .ohm      = 5503 },
+       { .temp_C       = 70, .ohm      = 4513 },
+       { .temp_C       = 75, .ohm      = 3721 },
+       { .temp_C       = 80, .ohm      = 3084 },
+       { .temp_C       = 85, .ohm      = 2569 },
+       { .temp_C       = 90, .ohm      = 2151 },
+       { .temp_C       = 95, .ohm      = 1809 },
+       { .temp_C       = 100, .ohm     = 1529 },
+       { .temp_C       = 105, .ohm     = 1299 },
+       { .temp_C       = 110, .ohm     = 1108 },
+       { .temp_C       = 115, .ohm     = 949 },
+       { .temp_C       = 120, .ohm     = 817 },
+       { .temp_C       = 125, .ohm     = 707 },
+};
+
+struct ntc_data {
+       struct device *hwmon_dev;
+       struct ntc_thermistor_platform_data *pdata;
+       const struct ntc_compensation *comp;
+       struct device *dev;
+       int n_comp;
+       char name[PLATFORM_NAME_SIZE];
+};
+
+static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
+{
+       if (divisor == 0 && dividend == 0)
+               return 0;
+       if (divisor == 0)
+               return UINT_MAX;
+       return div64_u64(dividend, divisor);
+}
+
+static unsigned int get_ohm_of_thermistor(struct ntc_data *data,
+               unsigned int uV)
+{
+       struct ntc_thermistor_platform_data *pdata = data->pdata;
+       u64 mV = uV / 1000;
+       u64 pmV = pdata->pullup_uV / 1000;
+       u64 N, puO, pdO;
+       puO = pdata->pullup_ohm;
+       pdO = pdata->pulldown_ohm;
+
+       if (mV == 0) {
+               if (pdata->connect == NTC_CONNECTED_POSITIVE)
+                       return UINT_MAX;
+               return 0;
+       }
+       if (mV >= pmV)
+               return (pdata->connect == NTC_CONNECTED_POSITIVE) ?
+                       0 : UINT_MAX;
+
+       if (pdata->connect == NTC_CONNECTED_POSITIVE && puO == 0)
+               N = div64_u64_safe(pdO * (pmV - mV), mV);
+       else if (pdata->connect == NTC_CONNECTED_GROUND && pdO == 0)
+               N = div64_u64_safe(puO * mV, pmV - mV);
+       else if (pdata->connect == NTC_CONNECTED_POSITIVE)
+               N = div64_u64_safe(pdO * puO * (pmV - mV),
+                               puO * mV - pdO * (pmV - mV));
+       else
+               N = div64_u64_safe(pdO * puO * mV, pdO * (pmV - mV) - puO * mV);
+
+       return (unsigned int) N;
+}
+
+static int lookup_comp(struct ntc_data *data,
+               unsigned int ohm, int *i_low, int *i_high)
+{
+       int start, end, mid = -1;
+
+       /* Do a binary search on compensation table */
+       start = 0;
+       end = data->n_comp;
+
+       while (end > start) {
+               mid = start + (end - start) / 2;
+               if (data->comp[mid].ohm < ohm)
+                       end = mid;
+               else if (data->comp[mid].ohm > ohm)
+                       start = mid + 1;
+               else
+                       break;
+       }
+
+       if (mid == 0) {
+               if (data->comp[mid].ohm > ohm) {
+                       *i_high = mid;
+                       *i_low = mid + 1;
+                       return 0;
+               } else {
+                       *i_low = mid;
+                       *i_high = -1;
+                       return -EINVAL;
+               }
+       }
+       if (mid == (data->n_comp - 1)) {
+               if (data->comp[mid].ohm <= ohm) {
+                       *i_low = mid;
+                       *i_high = mid - 1;
+                       return 0;
+               } else {
+                       *i_low = -1;
+                       *i_high = mid;
+                       return -EINVAL;
+               }
+       }
+
+       if (data->comp[mid].ohm <= ohm) {
+               *i_low = mid;
+               *i_high = mid - 1;
+       }
+       if (data->comp[mid].ohm > ohm) {
+               *i_low = mid + 1;
+               *i_high = mid;
+       }
+
+       return 0;
+}
+
+static int get_temp_mC(struct ntc_data *data, unsigned int ohm, int *temp)
+{
+       int low, high;
+       int ret;
+
+       ret = lookup_comp(data, ohm, &low, &high);
+       if (ret) {
+               /* Unable to use linear approximation */
+               if (low != -1)
+                       *temp = data->comp[low].temp_C * 1000;
+               else if (high != -1)
+                       *temp = data->comp[high].temp_C * 1000;
+               else
+                       return ret;
+       } else {
+               *temp = data->comp[low].temp_C * 1000 +
+                       ((data->comp[high].temp_C - data->comp[low].temp_C) *
+                        1000 * ((int)ohm - (int)data->comp[low].ohm)) /
+                       ((int)data->comp[high].ohm - (int)data->comp[low].ohm);
+       }
+
+       return 0;
+}
+
+static int ntc_thermistor_read(struct ntc_data *data, int *temp)
+{
+       int ret;
+       int read_ohm, read_uV;
+       unsigned int ohm = 0;
+
+       if (data->pdata->read_ohm) {
+               read_ohm = data->pdata->read_ohm();
+               if (read_ohm < 0)
+                       return read_ohm;
+               ohm = (unsigned int)read_ohm;
+       }
+
+       if (data->pdata->read_uV) {
+               read_uV = data->pdata->read_uV();
+               if (read_uV < 0)
+                       return read_uV;
+               ohm = get_ohm_of_thermistor(data, (unsigned int)read_uV);
+       }
+
+       ret = get_temp_mC(data, ohm, temp);
+       if (ret) {
+               dev_dbg(data->dev, "Sensor reading function not available.\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static ssize_t ntc_show_name(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct ntc_data *data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%s\n", data->name);
+}
+
+static ssize_t ntc_show_type(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "4\n");
+}
+
+static ssize_t ntc_show_temp(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct ntc_data *data = dev_get_drvdata(dev);
+       int temp, ret;
+
+       ret = ntc_thermistor_read(data, &temp);
+       if (ret)
+               return ret;
+       return sprintf(buf, "%d\n", temp);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, ntc_show_type, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ntc_show_temp, NULL, 0);
+static DEVICE_ATTR(name, S_IRUGO, ntc_show_name, NULL);
+
+static struct attribute *ntc_attributes[] = {
+       &dev_attr_name.attr,
+       &sensor_dev_attr_temp1_type.dev_attr.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       NULL,
+};
+
+static const struct attribute_group ntc_attr_group = {
+       .attrs = ntc_attributes,
+};
+
+static int __devinit ntc_thermistor_probe(struct platform_device *pdev)
+{
+       struct ntc_data *data;
+       struct ntc_thermistor_platform_data *pdata = pdev->dev.platform_data;
+       int ret = 0;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "No platform init data supplied.\n");
+               return -ENODEV;
+       }
+
+       /* Either one of the two is required. */
+       if (!pdata->read_uV && !pdata->read_ohm) {
+               dev_err(&pdev->dev, "Both read_uV and read_ohm missing."
+                               "Need either one of the two.\n");
+               return -EINVAL;
+       }
+
+       if (pdata->read_uV && pdata->read_ohm) {
+               dev_warn(&pdev->dev, "Only one of read_uV and read_ohm "
+                               "is needed; ignoring read_uV.\n");
+               pdata->read_uV = NULL;
+       }
+
+       if (pdata->read_uV && (pdata->pullup_uV == 0 ||
+                               (pdata->pullup_ohm == 0 && pdata->connect ==
+                                NTC_CONNECTED_GROUND) ||
+                               (pdata->pulldown_ohm == 0 && pdata->connect ==
+                                NTC_CONNECTED_POSITIVE) ||
+                               (pdata->connect != NTC_CONNECTED_POSITIVE &&
+                                pdata->connect != NTC_CONNECTED_GROUND))) {
+               dev_err(&pdev->dev, "Required data to use read_uV not "
+                               "supplied.\n");
+               return -EINVAL;
+       }
+
+       data = kzalloc(sizeof(struct ntc_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->dev = &pdev->dev;
+       data->pdata = pdata;
+       strncpy(data->name, pdev->id_entry->name, PLATFORM_NAME_SIZE);
+
+       switch (pdev->id_entry->driver_data) {
+       case TYPE_NCPXXWB473:
+               data->comp = ncpXXwb473;
+               data->n_comp = ARRAY_SIZE(ncpXXwb473);
+               break;
+       case TYPE_NCPXXWL333:
+               data->comp = ncpXXwl333;
+               data->n_comp = ARRAY_SIZE(ncpXXwl333);
+               break;
+       default:
+               dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n",
+                               pdev->id_entry->driver_data,
+                               pdev->id_entry->name);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       platform_set_drvdata(pdev, data);
+
+       ret = sysfs_create_group(&data->dev->kobj, &ntc_attr_group);
+       if (ret) {
+               dev_err(data->dev, "unable to create sysfs files\n");
+               goto err;
+       }
+
+       data->hwmon_dev = hwmon_device_register(data->dev);
+       if (IS_ERR_OR_NULL(data->hwmon_dev)) {
+               dev_err(data->dev, "unable to register as hwmon device.\n");
+               ret = -EINVAL;
+               goto err_after_sysfs;
+       }
+
+       dev_info(&pdev->dev, "Thermistor %s:%d (type: %s/%lu) successfully probed.\n",
+                       pdev->name, pdev->id, pdev->id_entry->name,
+                       pdev->id_entry->driver_data);
+       return 0;
+err_after_sysfs:
+       sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
+err:
+       kfree(data);
+       return ret;
+}
+
+static int __devexit ntc_thermistor_remove(struct platform_device *pdev)
+{
+       struct ntc_data *data = platform_get_drvdata(pdev);
+
+       hwmon_device_unregister(data->hwmon_dev);
+       sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
+       platform_set_drvdata(pdev, NULL);
+
+       kfree(data);
+
+       return 0;
+}
+
+static const struct platform_device_id ntc_thermistor_id[] = {
+       { "ncp15wb473", TYPE_NCPXXWB473 },
+       { "ncp18wb473", TYPE_NCPXXWB473 },
+       { "ncp21wb473", TYPE_NCPXXWB473 },
+       { "ncp03wb473", TYPE_NCPXXWB473 },
+       { "ncp15wl333", TYPE_NCPXXWL333 },
+       { },
+};
+
+static struct platform_driver ntc_thermistor_driver = {
+       .driver = {
+               .name = "ntc-thermistor",
+               .owner = THIS_MODULE,
+       },
+       .probe = ntc_thermistor_probe,
+       .remove = __devexit_p(ntc_thermistor_remove),
+       .id_table = ntc_thermistor_id,
+};
+
+static int __init ntc_thermistor_init(void)
+{
+       return platform_driver_register(&ntc_thermistor_driver);
+}
+
+module_init(ntc_thermistor_init);
+
+static void __exit ntc_thermistor_cleanup(void)
+{
+       platform_driver_unregister(&ntc_thermistor_driver);
+}
+
+module_exit(ntc_thermistor_cleanup);
+
+MODULE_DESCRIPTION("NTC Thermistor Driver");
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ntc-thermistor");
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
new file mode 100644 (file)
index 0000000..c9237b9
--- /dev/null
@@ -0,0 +1,100 @@
+#
+# PMBus chip drivers configuration
+#
+
+menuconfig PMBUS
+       tristate "PMBus support"
+       depends on I2C && EXPERIMENTAL
+       default n
+       help
+         Say yes here if you want to enable PMBus support.
+
+         This driver can also be built as a module. If so, the module will
+         be called pmbus_core.
+
+if PMBUS
+
+config SENSORS_PMBUS
+       tristate "Generic PMBus devices"
+       default y
+       help
+         If you say yes here you get hardware monitoring support for generic
+         PMBus devices, including but not limited to ADP4000, BMR450, BMR451,
+         BMR453, BMR454, LTC2978, NCP4200, and NCP4208.
+
+         This driver can also be built as a module. If so, the module will
+         be called pmbus.
+
+config SENSORS_ADM1275
+       tristate "Analog Devices ADM1275"
+       default n
+       help
+         If you say yes here you get hardware monitoring support for Analog
+         Devices ADM1275 Hot-Swap Controller and Digital Power Monitor.
+
+         This driver can also be built as a module. If so, the module will
+         be called adm1275.
+
+config SENSORS_LM25066
+       tristate "National Semiconductor LM25066 and compatibles"
+       default n
+       help
+         If you say yes here you get hardware monitoring support for National
+         Semiconductor LM25066, LM5064, and LM5066.
+
+         This driver can also be built as a module. If so, the module will
+         be called lm25066.
+
+config SENSORS_MAX16064
+       tristate "Maxim MAX16064"
+       default n
+       help
+         If you say yes here you get hardware monitoring support for Maxim
+         MAX16064.
+
+         This driver can also be built as a module. If so, the module will
+         be called max16064.
+
+config SENSORS_MAX34440
+       tristate "Maxim MAX34440/MAX34441"
+       default n
+       help
+         If you say yes here you get hardware monitoring support for Maxim
+         MAX34440 and MAX34441.
+
+         This driver can also be built as a module. If so, the module will
+         be called max34440.
+
+config SENSORS_MAX8688
+       tristate "Maxim MAX8688"
+       default n
+       help
+         If you say yes here you get hardware monitoring support for Maxim
+         MAX8688.
+
+         This driver can also be built as a module. If so, the module will
+         be called max8688.
+
+config SENSORS_UCD9000
+       tristate "TI UCD90120, UCD90124, UCD9090, UCD90910"
+       default n
+       help
+         If you say yes here you get hardware monitoring support for TI
+         UCD90120, UCD90124, UCD9090, UCD90910 Sequencer and System Health
+         Controllers.
+
+         This driver can also be built as a module. If so, the module will
+         be called ucd9000.
+
+config SENSORS_UCD9200
+       tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248"
+       default n
+       help
+         If you say yes here you get hardware monitoring support for TI
+         UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248
+         Digital PWM System Controllers.
+
+         This driver can also be built as a module. If so, the module will
+         be called ucd9200.
+
+endif # PMBUS
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
new file mode 100644 (file)
index 0000000..623eedb
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Makefile for PMBus chip drivers.
+#
+
+obj-$(CONFIG_PMBUS)            += pmbus_core.o
+obj-$(CONFIG_SENSORS_PMBUS)    += pmbus.o
+obj-$(CONFIG_SENSORS_ADM1275)  += adm1275.o
+obj-$(CONFIG_SENSORS_LM25066)  += lm25066.o
+obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
+obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
+obj-$(CONFIG_SENSORS_MAX8688)  += max8688.o
+obj-$(CONFIG_SENSORS_UCD9000)  += ucd9000.o
+obj-$(CONFIG_SENSORS_UCD9200)  += ucd9200.o
similarity index 67%
rename from drivers/hwmon/adm1275.c
rename to drivers/hwmon/pmbus/adm1275.c
index 8bc1bd6..c936e27 100644 (file)
 #include <linux/i2c.h>
 #include "pmbus.h"
 
+#define ADM1275_PEAK_IOUT              0xd0
+#define ADM1275_PEAK_VIN               0xd1
+#define ADM1275_PEAK_VOUT              0xd2
 #define ADM1275_PMON_CONFIG            0xd4
 
 #define ADM1275_VIN_VOUT_SELECT                (1 << 6)
 #define ADM1275_VRANGE                 (1 << 5)
 
+static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
+{
+       int ret;
+
+       if (page)
+               return -EINVAL;
+
+       switch (reg) {
+       case PMBUS_VIRT_READ_IOUT_MAX:
+               ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT);
+               break;
+       case PMBUS_VIRT_READ_VOUT_MAX:
+               ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VOUT);
+               break;
+       case PMBUS_VIRT_READ_VIN_MAX:
+               ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
+               break;
+       case PMBUS_VIRT_RESET_IOUT_HISTORY:
+       case PMBUS_VIRT_RESET_VOUT_HISTORY:
+       case PMBUS_VIRT_RESET_VIN_HISTORY:
+               ret = 0;
+               break;
+       default:
+               ret = -ENODATA;
+               break;
+       }
+       return ret;
+}
+
+static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
+                                  u16 word)
+{
+       int ret;
+
+       if (page)
+               return -EINVAL;
+
+       switch (reg) {
+       case PMBUS_VIRT_RESET_IOUT_HISTORY:
+               ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0);
+               break;
+       case PMBUS_VIRT_RESET_VOUT_HISTORY:
+               ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0);
+               break;
+       case PMBUS_VIRT_RESET_VIN_HISTORY:
+               ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0);
+               break;
+       default:
+               ret = -ENODATA;
+               break;
+       }
+       return ret;
+}
+
 static int adm1275_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
@@ -50,14 +107,17 @@ static int adm1275_probe(struct i2c_client *client,
        }
 
        info->pages = 1;
-       info->direct[PSC_VOLTAGE_IN] = true;
-       info->direct[PSC_VOLTAGE_OUT] = true;
-       info->direct[PSC_CURRENT_OUT] = true;
+       info->format[PSC_VOLTAGE_IN] = direct;
+       info->format[PSC_VOLTAGE_OUT] = direct;
+       info->format[PSC_CURRENT_OUT] = direct;
        info->m[PSC_CURRENT_OUT] = 807;
        info->b[PSC_CURRENT_OUT] = 20475;
        info->R[PSC_CURRENT_OUT] = -1;
        info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
 
+       info->read_word_data = adm1275_read_word_data;
+       info->write_word_data = adm1275_write_word_data;
+
        if (config & ADM1275_VRANGE) {
                info->m[PSC_VOLTAGE_IN] = 19199;
                info->b[PSC_VOLTAGE_IN] = 0;
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
new file mode 100644 (file)
index 0000000..d4bc114
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * Hardware monitoring driver for LM25066 / LM5064 / LM5066
+ *
+ * Copyright (c) 2011 Ericsson AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+enum chips { lm25066, lm5064, lm5066 };
+
+#define LM25066_READ_VAUX              0xd0
+#define LM25066_MFR_READ_IIN           0xd1
+#define LM25066_MFR_READ_PIN           0xd2
+#define LM25066_MFR_IIN_OC_WARN_LIMIT  0xd3
+#define LM25066_MFR_PIN_OP_WARN_LIMIT  0xd4
+#define LM25066_READ_PIN_PEAK          0xd5
+#define LM25066_CLEAR_PIN_PEAK         0xd6
+#define LM25066_DEVICE_SETUP           0xd9
+#define LM25066_READ_AVG_VIN           0xdc
+#define LM25066_READ_AVG_VOUT          0xdd
+#define LM25066_READ_AVG_IIN           0xde
+#define LM25066_READ_AVG_PIN           0xdf
+
+#define LM25066_DEV_SETUP_CL           (1 << 4)        /* Current limit */
+
+struct lm25066_data {
+       int id;
+       struct pmbus_driver_info info;
+};
+
+#define to_lm25066_data(x)  container_of(x, struct lm25066_data, info)
+
+static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
+{
+       const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+       const struct lm25066_data *data = to_lm25066_data(info);
+       int ret;
+
+       if (page > 1)
+               return -EINVAL;
+
+       /* Map READ_VAUX into READ_VOUT register on page 1 */
+       if (page == 1) {
+               switch (reg) {
+               case PMBUS_READ_VOUT:
+                       ret = pmbus_read_word_data(client, 0,
+                                                  LM25066_READ_VAUX);
+                       if (ret < 0)
+                               break;
+                       /* Adjust returned value to match VOUT coefficients */
+                       switch (data->id) {
+                       case lm25066:
+                               /* VOUT: 4.54 mV VAUX: 283.2 uV LSB */
+                               ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
+                               break;
+                       case lm5064:
+                               /* VOUT: 4.53 mV VAUX: 700 uV LSB */
+                               ret = DIV_ROUND_CLOSEST(ret * 70, 453);
+                               break;
+                       case lm5066:
+                               /* VOUT: 2.18 mV VAUX: 725 uV LSB */
+                               ret = DIV_ROUND_CLOSEST(ret * 725, 2180);
+                               break;
+                       }
+                       break;
+               default:
+                       /* No other valid registers on page 1 */
+                       ret = -EINVAL;
+                       break;
+               }
+               goto done;
+       }
+
+       switch (reg) {
+       case PMBUS_READ_IIN:
+               ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN);
+               break;
+       case PMBUS_READ_PIN:
+               ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN);
+               break;
+       case PMBUS_IIN_OC_WARN_LIMIT:
+               ret = pmbus_read_word_data(client, 0,
+                                          LM25066_MFR_IIN_OC_WARN_LIMIT);
+               break;
+       case PMBUS_PIN_OP_WARN_LIMIT:
+               ret = pmbus_read_word_data(client, 0,
+                                          LM25066_MFR_PIN_OP_WARN_LIMIT);
+               break;
+       case PMBUS_VIRT_READ_VIN_AVG:
+               ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN);
+               break;
+       case PMBUS_VIRT_READ_VOUT_AVG:
+               ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT);
+               break;
+       case PMBUS_VIRT_READ_IIN_AVG:
+               ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN);
+               break;
+       case PMBUS_VIRT_READ_PIN_AVG:
+               ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN);
+               break;
+       case PMBUS_VIRT_READ_PIN_MAX:
+               ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK);
+               break;
+       case PMBUS_VIRT_RESET_PIN_HISTORY:
+               ret = 0;
+               break;
+       default:
+               ret = -ENODATA;
+               break;
+       }
+done:
+       return ret;
+}
+
+static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
+                                  u16 word)
+{
+       int ret;
+
+       if (page > 1)
+               return -EINVAL;
+
+       switch (reg) {
+       case PMBUS_IIN_OC_WARN_LIMIT:
+               ret = pmbus_write_word_data(client, 0,
+                                           LM25066_MFR_IIN_OC_WARN_LIMIT,
+                                           word);
+               break;
+       case PMBUS_PIN_OP_WARN_LIMIT:
+               ret = pmbus_write_word_data(client, 0,
+                                           LM25066_MFR_PIN_OP_WARN_LIMIT,
+                                           word);
+               break;
+       case PMBUS_VIRT_RESET_PIN_HISTORY:
+               ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK);
+               break;
+       default:
+               ret = -ENODATA;
+               break;
+       }
+       return ret;
+}
+
+static int lm25066_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
+{
+       int config;
+       int ret;
+       struct lm25066_data *data;
+       struct pmbus_driver_info *info;
+
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_READ_BYTE_DATA))
+               return -ENODEV;
+
+       data = kzalloc(sizeof(struct lm25066_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP);
+       if (config < 0) {
+               ret = config;
+               goto err_mem;
+       }
+
+       data->id = id->driver_data;
+       info = &data->info;
+
+       info->pages = 2;
+       info->format[PSC_VOLTAGE_IN] = direct;
+       info->format[PSC_VOLTAGE_OUT] = direct;
+       info->format[PSC_CURRENT_IN] = direct;
+       info->format[PSC_TEMPERATURE] = direct;
+       info->format[PSC_POWER] = direct;
+
+       info->m[PSC_TEMPERATURE] = 16;
+       info->b[PSC_TEMPERATURE] = 0;
+       info->R[PSC_TEMPERATURE] = 0;
+
+       info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT
+         | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN
+         | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+       info->func[1] = PMBUS_HAVE_VOUT;
+
+       info->read_word_data = lm25066_read_word_data;
+       info->write_word_data = lm25066_write_word_data;
+
+       switch (id->driver_data) {
+       case lm25066:
+               info->m[PSC_VOLTAGE_IN] = 22070;
+               info->b[PSC_VOLTAGE_IN] = 0;
+               info->R[PSC_VOLTAGE_IN] = -2;
+               info->m[PSC_VOLTAGE_OUT] = 22070;
+               info->b[PSC_VOLTAGE_OUT] = 0;
+               info->R[PSC_VOLTAGE_OUT] = -2;
+
+               if (config & LM25066_DEV_SETUP_CL) {
+                       info->m[PSC_CURRENT_IN] = 6852;
+                       info->b[PSC_CURRENT_IN] = 0;
+                       info->R[PSC_CURRENT_IN] = -2;
+                       info->m[PSC_POWER] = 369;
+                       info->b[PSC_POWER] = 0;
+                       info->R[PSC_POWER] = -2;
+               } else {
+                       info->m[PSC_CURRENT_IN] = 13661;
+                       info->b[PSC_CURRENT_IN] = 0;
+                       info->R[PSC_CURRENT_IN] = -2;
+                       info->m[PSC_POWER] = 736;
+                       info->b[PSC_POWER] = 0;
+                       info->R[PSC_POWER] = -2;
+               }
+               break;
+       case lm5064:
+               info->m[PSC_VOLTAGE_IN] = 22075;
+               info->b[PSC_VOLTAGE_IN] = 0;
+               info->R[PSC_VOLTAGE_IN] = -2;
+               info->m[PSC_VOLTAGE_OUT] = 22075;
+               info->b[PSC_VOLTAGE_OUT] = 0;
+               info->R[PSC_VOLTAGE_OUT] = -2;
+
+               if (config & LM25066_DEV_SETUP_CL) {
+                       info->m[PSC_CURRENT_IN] = 6713;
+                       info->b[PSC_CURRENT_IN] = 0;
+                       info->R[PSC_CURRENT_IN] = -2;
+                       info->m[PSC_POWER] = 3619;
+                       info->b[PSC_POWER] = 0;
+                       info->R[PSC_POWER] = -3;
+               } else {
+                       info->m[PSC_CURRENT_IN] = 13426;
+                       info->b[PSC_CURRENT_IN] = 0;
+                       info->R[PSC_CURRENT_IN] = -2;
+                       info->m[PSC_POWER] = 7238;
+                       info->b[PSC_POWER] = 0;
+                       info->R[PSC_POWER] = -3;
+               }
+               break;
+       case lm5066:
+               info->m[PSC_VOLTAGE_IN] = 4587;
+               info->b[PSC_VOLTAGE_IN] = 0;
+               info->R[PSC_VOLTAGE_IN] = -2;
+               info->m[PSC_VOLTAGE_OUT] = 4587;
+               info->b[PSC_VOLTAGE_OUT] = 0;
+               info->R[PSC_VOLTAGE_OUT] = -2;
+
+               if (config & LM25066_DEV_SETUP_CL) {
+                       info->m[PSC_CURRENT_IN] = 10753;
+                       info->b[PSC_CURRENT_IN] = 0;
+                       info->R[PSC_CURRENT_IN] = -2;
+                       info->m[PSC_POWER] = 1204;
+                       info->b[PSC_POWER] = 0;
+                       info->R[PSC_POWER] = -3;
+               } else {
+                       info->m[PSC_CURRENT_IN] = 5405;
+                       info->b[PSC_CURRENT_IN] = 0;
+                       info->R[PSC_CURRENT_IN] = -2;
+                       info->m[PSC_POWER] = 605;
+                       info->b[PSC_POWER] = 0;
+                       info->R[PSC_POWER] = -3;
+               }
+               break;
+       default:
+               ret = -ENODEV;
+               goto err_mem;
+       }
+
+       ret = pmbus_do_probe(client, id, info);
+       if (ret)
+               goto err_mem;
+       return 0;
+
+err_mem:
+       kfree(data);
+       return ret;
+}
+
+static int lm25066_remove(struct i2c_client *client)
+{
+       const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+       const struct lm25066_data *data = to_lm25066_data(info);
+       int ret;
+
+       ret = pmbus_do_remove(client);
+       kfree(data);
+       return ret;
+}
+
+static const struct i2c_device_id lm25066_id[] = {
+       {"lm25066", lm25066},
+       {"lm5064", lm5064},
+       {"lm5066", lm5066},
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, lm25066_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver lm25066_driver = {
+       .driver = {
+                  .name = "lm25066",
+                  },
+       .probe = lm25066_probe,
+       .remove = lm25066_remove,
+       .id_table = lm25066_id,
+};
+
+static int __init lm25066_init(void)
+{
+       return i2c_add_driver(&lm25066_driver);
+}
+
+static void __exit lm25066_exit(void)
+{
+       i2c_del_driver(&lm25066_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for LM25066/LM5064/LM5066");
+MODULE_LICENSE("GPL");
+module_init(lm25066_init);
+module_exit(lm25066_exit);
similarity index 66%
rename from drivers/hwmon/max16064.c
rename to drivers/hwmon/pmbus/max16064.c
index 1d6d717..e50b296 100644 (file)
 #include <linux/i2c.h>
 #include "pmbus.h"
 
+#define MAX16064_MFR_VOUT_PEAK         0xd4
+#define MAX16064_MFR_TEMPERATURE_PEAK  0xd6
+
+static int max16064_read_word_data(struct i2c_client *client, int page, int reg)
+{
+       int ret;
+
+       switch (reg) {
+       case PMBUS_VIRT_READ_VOUT_MAX:
+               ret = pmbus_read_word_data(client, page,
+                                          MAX16064_MFR_VOUT_PEAK);
+               break;
+       case PMBUS_VIRT_READ_TEMP_MAX:
+               ret = pmbus_read_word_data(client, page,
+                                          MAX16064_MFR_TEMPERATURE_PEAK);
+               break;
+       case PMBUS_VIRT_RESET_VOUT_HISTORY:
+       case PMBUS_VIRT_RESET_TEMP_HISTORY:
+               ret = 0;
+               break;
+       default:
+               ret = -ENODATA;
+               break;
+       }
+       return ret;
+}
+
+static int max16064_write_word_data(struct i2c_client *client, int page,
+                                   int reg, u16 word)
+{
+       int ret;
+
+       switch (reg) {
+       case PMBUS_VIRT_RESET_VOUT_HISTORY:
+               ret = pmbus_write_word_data(client, page,
+                                           MAX16064_MFR_VOUT_PEAK, 0);
+               break;
+       case PMBUS_VIRT_RESET_TEMP_HISTORY:
+               ret = pmbus_write_word_data(client, page,
+                                           MAX16064_MFR_TEMPERATURE_PEAK,
+                                           0xffff);
+               break;
+       default:
+               ret = -ENODATA;
+               break;
+       }
+       return ret;
+}
+
 static struct pmbus_driver_info max16064_info = {
        .pages = 4,
-       .direct[PSC_VOLTAGE_IN] = true,
-       .direct[PSC_VOLTAGE_OUT] = true,
-       .direct[PSC_TEMPERATURE] = true,
+       .format[PSC_VOLTAGE_IN] = direct,
+       .format[PSC_VOLTAGE_OUT] = direct,
+       .format[PSC_TEMPERATURE] = direct,
        .m[PSC_VOLTAGE_IN] = 19995,
        .b[PSC_VOLTAGE_IN] = 0,
        .R[PSC_VOLTAGE_IN] = -1,
@@ -44,6 +93,8 @@ static struct pmbus_driver_info max16064_info = {
        .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
        .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
        .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
+       .read_word_data = max16064_read_word_data,
+       .write_word_data = max16064_write_word_data,
 };
 
 static int max16064_probe(struct i2c_client *client,
similarity index 76%
rename from drivers/hwmon/max34440.c
rename to drivers/hwmon/pmbus/max34440.c
index db11e1a..fda621d 100644 (file)
 
 enum chips { max34440, max34441 };
 
+#define MAX34440_MFR_VOUT_PEAK         0xd4
+#define MAX34440_MFR_IOUT_PEAK         0xd5
+#define MAX34440_MFR_TEMPERATURE_PEAK  0xd6
+
 #define MAX34440_STATUS_OC_WARN                (1 << 0)
 #define MAX34440_STATUS_OC_FAULT       (1 << 1)
 #define MAX34440_STATUS_OT_FAULT       (1 << 5)
 #define MAX34440_STATUS_OT_WARN                (1 << 6)
 
+static int max34440_read_word_data(struct i2c_client *client, int page, int reg)
+{
+       int ret;
+
+       switch (reg) {
+       case PMBUS_VIRT_READ_VOUT_MAX:
+               ret = pmbus_read_word_data(client, page,
+                                          MAX34440_MFR_VOUT_PEAK);
+               break;
+       case PMBUS_VIRT_READ_IOUT_MAX:
+               ret = pmbus_read_word_data(client, page,
+                                          MAX34440_MFR_IOUT_PEAK);
+               break;
+       case PMBUS_VIRT_READ_TEMP_MAX:
+               ret = pmbus_read_word_data(client, page,
+                                          MAX34440_MFR_TEMPERATURE_PEAK);
+               break;
+       case PMBUS_VIRT_RESET_VOUT_HISTORY:
+       case PMBUS_VIRT_RESET_IOUT_HISTORY:
+       case PMBUS_VIRT_RESET_TEMP_HISTORY:
+               ret = 0;
+               break;
+       default:
+               ret = -ENODATA;
+               break;
+       }
+       return ret;
+}
+
+static int max34440_write_word_data(struct i2c_client *client, int page,
+                                   int reg, u16 word)
+{
+       int ret;
+
+       switch (reg) {
+       case PMBUS_VIRT_RESET_VOUT_HISTORY:
+               ret = pmbus_write_word_data(client, page,
+                                           MAX34440_MFR_VOUT_PEAK, 0);
+               break;
+       case PMBUS_VIRT_RESET_IOUT_HISTORY:
+               ret = pmbus_write_word_data(client, page,
+                                           MAX34440_MFR_IOUT_PEAK, 0);
+               break;
+       case PMBUS_VIRT_RESET_TEMP_HISTORY:
+               ret = pmbus_write_word_data(client, page,
+                                           MAX34440_MFR_TEMPERATURE_PEAK,
+                                           0xffff);
+               break;
+       default:
+               ret = -ENODATA;
+               break;
+       }
+       return ret;
+}
+
 static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
 {
        int ret;
@@ -72,10 +131,10 @@ static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
 static struct pmbus_driver_info max34440_info[] = {
        [max34440] = {
                .pages = 14,
-               .direct[PSC_VOLTAGE_IN] = true,
-               .direct[PSC_VOLTAGE_OUT] = true,
-               .direct[PSC_TEMPERATURE] = true,
-               .direct[PSC_CURRENT_OUT] = true,
+               .format[PSC_VOLTAGE_IN] = direct,
+               .format[PSC_VOLTAGE_OUT] = direct,
+               .format[PSC_TEMPERATURE] = direct,
+               .format[PSC_CURRENT_OUT] = direct,
                .m[PSC_VOLTAGE_IN] = 1,
                .b[PSC_VOLTAGE_IN] = 0,
                .R[PSC_VOLTAGE_IN] = 3,     /* R = 0 in datasheet reflects mV */
@@ -109,14 +168,16 @@ static struct pmbus_driver_info max34440_info[] = {
                .func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
                .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
                .read_byte_data = max34440_read_byte_data,
+               .read_word_data = max34440_read_word_data,
+               .write_word_data = max34440_write_word_data,
        },
        [max34441] = {
                .pages = 12,
-               .direct[PSC_VOLTAGE_IN] = true,
-               .direct[PSC_VOLTAGE_OUT] = true,
-               .direct[PSC_TEMPERATURE] = true,
-               .direct[PSC_CURRENT_OUT] = true,
-               .direct[PSC_FAN] = true,
+               .format[PSC_VOLTAGE_IN] = direct,
+               .format[PSC_VOLTAGE_OUT] = direct,
+               .format[PSC_TEMPERATURE] = direct,
+               .format[PSC_CURRENT_OUT] = direct,
+               .format[PSC_FAN] = direct,
                .m[PSC_VOLTAGE_IN] = 1,
                .b[PSC_VOLTAGE_IN] = 0,
                .R[PSC_VOLTAGE_IN] = 3,
@@ -150,6 +211,8 @@ static struct pmbus_driver_info max34440_info[] = {
                .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
                .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
                .read_byte_data = max34440_read_byte_data,
+               .read_word_data = max34440_read_word_data,
+               .write_word_data = max34440_write_word_data,
        },
 };
 
similarity index 72%
rename from drivers/hwmon/max8688.c
rename to drivers/hwmon/pmbus/max8688.c
index 7fb93f4..c3e72f1 100644 (file)
@@ -25,6 +25,9 @@
 #include <linux/i2c.h>
 #include "pmbus.h"
 
+#define MAX8688_MFR_VOUT_PEAK          0xd4
+#define MAX8688_MFR_IOUT_PEAK          0xd5
+#define MAX8688_MFR_TEMPERATURE_PEAK   0xd6
 #define MAX8688_MFG_STATUS             0xd8
 
 #define MAX8688_STATUS_OC_FAULT                (1 << 4)
 #define MAX8688_STATUS_OT_FAULT                (1 << 13)
 #define MAX8688_STATUS_OT_WARNING      (1 << 14)
 
+static int max8688_read_word_data(struct i2c_client *client, int page, int reg)
+{
+       int ret;
+
+       if (page)
+               return -EINVAL;
+
+       switch (reg) {
+       case PMBUS_VIRT_READ_VOUT_MAX:
+               ret = pmbus_read_word_data(client, 0, MAX8688_MFR_VOUT_PEAK);
+               break;
+       case PMBUS_VIRT_READ_IOUT_MAX:
+               ret = pmbus_read_word_data(client, 0, MAX8688_MFR_IOUT_PEAK);
+               break;
+       case PMBUS_VIRT_READ_TEMP_MAX:
+               ret = pmbus_read_word_data(client, 0,
+                                          MAX8688_MFR_TEMPERATURE_PEAK);
+               break;
+       case PMBUS_VIRT_RESET_VOUT_HISTORY:
+       case PMBUS_VIRT_RESET_IOUT_HISTORY:
+       case PMBUS_VIRT_RESET_TEMP_HISTORY:
+               ret = 0;
+               break;
+       default:
+               ret = -ENODATA;
+               break;
+       }
+       return ret;
+}
+
+static int max8688_write_word_data(struct i2c_client *client, int page, int reg,
+                                  u16 word)
+{
+       int ret;
+
+       switch (reg) {
+       case PMBUS_VIRT_RESET_VOUT_HISTORY:
+               ret = pmbus_write_word_data(client, 0, MAX8688_MFR_VOUT_PEAK,
+                                           0);
+               break;
+       case PMBUS_VIRT_RESET_IOUT_HISTORY:
+               ret = pmbus_write_word_data(client, 0, MAX8688_MFR_IOUT_PEAK,
+                                           0);
+               break;
+       case PMBUS_VIRT_RESET_TEMP_HISTORY:
+               ret = pmbus_write_word_data(client, 0,
+                                           MAX8688_MFR_TEMPERATURE_PEAK,
+                                           0xffff);
+               break;
+       default:
+               ret = -ENODATA;
+               break;
+       }
+       return ret;
+}
+
 static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
 {
        int ret = 0;
@@ -91,10 +150,10 @@ static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
 
 static struct pmbus_driver_info max8688_info = {
        .pages = 1,
-       .direct[PSC_VOLTAGE_IN] = true,
-       .direct[PSC_VOLTAGE_OUT] = true,
-       .direct[PSC_TEMPERATURE] = true,
-       .direct[PSC_CURRENT_OUT] = true,
+       .format[PSC_VOLTAGE_IN] = direct,
+       .format[PSC_VOLTAGE_OUT] = direct,
+       .format[PSC_TEMPERATURE] = direct,
+       .format[PSC_CURRENT_OUT] = direct,
        .m[PSC_VOLTAGE_IN] = 19995,
        .b[PSC_VOLTAGE_IN] = 0,
        .R[PSC_VOLTAGE_IN] = -1,
@@ -111,6 +170,8 @@ static struct pmbus_driver_info max8688_info = {
                | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
                | PMBUS_HAVE_STATUS_TEMP,
        .read_byte_data = max8688_read_byte_data,
+       .read_word_data = max8688_read_word_data,
+       .write_word_data = max8688_write_word_data,
 };
 
 static int max8688_probe(struct i2c_client *client,
similarity index 89%
rename from drivers/hwmon/pmbus.c
rename to drivers/hwmon/pmbus/pmbus.c
index 9b1f0c3..73de9f1 100644 (file)
@@ -96,6 +96,8 @@ static void pmbus_find_sensor_groups(struct i2c_client *client,
 static int pmbus_identify(struct i2c_client *client,
                          struct pmbus_driver_info *info)
 {
+       int ret = 0;
+
        if (!info->pages) {
                /*
                 * Check if the PAGE command is supported. If it is,
@@ -117,6 +119,27 @@ static int pmbus_identify(struct i2c_client *client,
                }
        }
 
+       if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) {
+               int vout_mode;
+
+               vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
+               if (vout_mode >= 0 && vout_mode != 0xff) {
+                       switch (vout_mode >> 5) {
+                       case 0:
+                               break;
+                       case 1:
+                               info->format[PSC_VOLTAGE_OUT] = vid;
+                               break;
+                       case 2:
+                               info->format[PSC_VOLTAGE_OUT] = direct;
+                               break;
+                       default:
+                               ret = -ENODEV;
+                               goto abort;
+                       }
+               }
+       }
+
        /*
         * We should check if the COEFFICIENTS register is supported.
         * If it is, and the chip is configured for direct mode, we can read
@@ -125,13 +148,18 @@ static int pmbus_identify(struct i2c_client *client,
         *
         * To do this, we will need access to a chip which actually supports the
         * COEFFICIENTS command, since the command is too complex to implement
-        * without testing it.
+        * without testing it. Until then, abort if a chip configured for direct
+        * mode was detected.
         */
+       if (info->format[PSC_VOLTAGE_OUT] == direct) {
+               ret = -ENODEV;
+               goto abort;
+       }
 
        /* Try to find sensor groups  */
        pmbus_find_sensor_groups(client, info);
-
-       return 0;
+abort:
+       return ret;
 }
 
 static int pmbus_probe(struct i2c_client *client,
@@ -172,11 +200,14 @@ static int pmbus_remove(struct i2c_client *client)
  * Use driver_data to set the number of pages supported by the chip.
  */
 static const struct i2c_device_id pmbus_id[] = {
+       {"adp4000", 1},
        {"bmr450", 1},
        {"bmr451", 1},
        {"bmr453", 1},
        {"bmr454", 1},
        {"ltc2978", 8},
+       {"ncp4200", 1},
+       {"ncp4208", 1},
        {"pmbus", 0},
        {}
 };
similarity index 79%
rename from drivers/hwmon/pmbus.h
rename to drivers/hwmon/pmbus/pmbus.h
index 50647ab..0808d98 100644 (file)
 #define PMBUS_MFR_DATE                 0x9D
 #define PMBUS_MFR_SERIAL               0x9E
 
+/*
+ * Virtual registers.
+ * Useful to support attributes which are not supported by standard PMBus
+ * registers but exist as manufacturer specific registers on individual chips.
+ * Must be mapped to real registers in device specific code.
+ *
+ * Semantics:
+ * Virtual registers are all word size.
+ * READ registers are read-only; writes are either ignored or return an error.
+ * RESET registers are read/write. Reading returns zero (used for detection),
+ * writing any value causes the associated history to be reset.
+ */
+#define PMBUS_VIRT_BASE                        0x100
+#define PMBUS_VIRT_READ_TEMP_MIN       (PMBUS_VIRT_BASE + 0)
+#define PMBUS_VIRT_READ_TEMP_MAX       (PMBUS_VIRT_BASE + 1)
+#define PMBUS_VIRT_RESET_TEMP_HISTORY  (PMBUS_VIRT_BASE + 2)
+#define PMBUS_VIRT_READ_VIN_AVG                (PMBUS_VIRT_BASE + 3)
+#define PMBUS_VIRT_READ_VIN_MIN                (PMBUS_VIRT_BASE + 4)
+#define PMBUS_VIRT_READ_VIN_MAX                (PMBUS_VIRT_BASE + 5)
+#define PMBUS_VIRT_RESET_VIN_HISTORY   (PMBUS_VIRT_BASE + 6)
+#define PMBUS_VIRT_READ_IIN_AVG                (PMBUS_VIRT_BASE + 7)
+#define PMBUS_VIRT_READ_IIN_MIN                (PMBUS_VIRT_BASE + 8)
+#define PMBUS_VIRT_READ_IIN_MAX                (PMBUS_VIRT_BASE + 9)
+#define PMBUS_VIRT_RESET_IIN_HISTORY   (PMBUS_VIRT_BASE + 10)
+#define PMBUS_VIRT_READ_PIN_AVG                (PMBUS_VIRT_BASE + 11)
+#define PMBUS_VIRT_READ_PIN_MAX                (PMBUS_VIRT_BASE + 12)
+#define PMBUS_VIRT_RESET_PIN_HISTORY   (PMBUS_VIRT_BASE + 13)
+#define PMBUS_VIRT_READ_VOUT_AVG       (PMBUS_VIRT_BASE + 14)
+#define PMBUS_VIRT_READ_VOUT_MIN       (PMBUS_VIRT_BASE + 15)
+#define PMBUS_VIRT_READ_VOUT_MAX       (PMBUS_VIRT_BASE + 16)
+#define PMBUS_VIRT_RESET_VOUT_HISTORY  (PMBUS_VIRT_BASE + 17)
+#define PMBUS_VIRT_READ_IOUT_AVG       (PMBUS_VIRT_BASE + 18)
+#define PMBUS_VIRT_READ_IOUT_MIN       (PMBUS_VIRT_BASE + 19)
+#define PMBUS_VIRT_READ_IOUT_MAX       (PMBUS_VIRT_BASE + 20)
+#define PMBUS_VIRT_RESET_IOUT_HISTORY  (PMBUS_VIRT_BASE + 21)
+
 /*
  * CAPABILITY
  */
@@ -266,11 +302,11 @@ enum pmbus_sensor_classes {
 #define PMBUS_HAVE_STATUS_FAN12        (1 << 16)
 #define PMBUS_HAVE_STATUS_FAN34        (1 << 17)
 
+enum pmbus_data_format { linear = 0, direct, vid };
+
 struct pmbus_driver_info {
        int pages;              /* Total number of pages */
-       bool direct[PSC_NUM_CLASSES];
-                               /* true if device uses direct data format
-                                  for the given sensor class */
+       enum pmbus_data_format format[PSC_NUM_CLASSES];
        /*
         * Support one set of coefficients for each sensor type
         * Used for chips providing data in direct mode.
@@ -286,6 +322,9 @@ struct pmbus_driver_info {
         * necessary.
         */
        int (*read_byte_data)(struct i2c_client *client, int page, int reg);
+       int (*read_word_data)(struct i2c_client *client, int page, int reg);
+       int (*write_word_data)(struct i2c_client *client, int page, int reg,
+                              u16 word);
        /*
         * The identify function determines supported PMBus functionality.
         * This function is only necessary if a chip driver supports multiple
@@ -299,6 +338,9 @@ struct pmbus_driver_info {
 
 int pmbus_set_page(struct i2c_client *client, u8 page);
 int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
+int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word);
+int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
+int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
 void pmbus_clear_faults(struct i2c_client *client);
 bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
 bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
similarity index 84%
rename from drivers/hwmon/pmbus_core.c
rename to drivers/hwmon/pmbus/pmbus_core.c
index 8e31a8e..5c1b6cf 100644 (file)
 /*
  * Constants needed to determine number of sensors, booleans, and labels.
  */
-#define PMBUS_MAX_INPUT_SENSORS                11      /* 6*volt, 3*curr, 2*power */
-#define PMBUS_VOUT_SENSORS_PER_PAGE    5       /* input, min, max, lcrit,
-                                                  crit */
-#define PMBUS_IOUT_SENSORS_PER_PAGE    4       /* input, min, max, crit */
+#define PMBUS_MAX_INPUT_SENSORS                22      /* 10*volt, 7*curr, 5*power */
+#define PMBUS_VOUT_SENSORS_PER_PAGE    9       /* input, min, max, lcrit,
+                                                  crit, lowest, highest, avg,
+                                                  reset */
+#define PMBUS_IOUT_SENSORS_PER_PAGE    8       /* input, min, max, crit,
+                                                  lowest, highest, avg,
+                                                  reset */
 #define PMBUS_POUT_SENSORS_PER_PAGE    4       /* input, cap, max, crit */
 #define PMBUS_MAX_SENSORS_PER_FAN      1       /* input */
-#define PMBUS_MAX_SENSORS_PER_TEMP     5       /* input, min, max, lcrit,
-                                                  crit */
+#define PMBUS_MAX_SENSORS_PER_TEMP     8       /* input, min, max, lcrit,
+                                                  crit, lowest, highest,
+                                                  reset */
 
 #define PMBUS_MAX_INPUT_BOOLEANS       7       /* v: min_alarm, max_alarm,
                                                   lcrit_alarm, crit_alarm;
 #define PB_STATUS_INPUT_BASE   (PB_STATUS_FAN34_BASE + PMBUS_PAGES)
 #define PB_STATUS_TEMP_BASE    (PB_STATUS_INPUT_BASE + 1)
 
+#define PMBUS_NAME_SIZE                24
+
 struct pmbus_sensor {
-       char name[I2C_NAME_SIZE];       /* sysfs sensor name */
+       char name[PMBUS_NAME_SIZE];     /* sysfs sensor name */
        struct sensor_device_attribute attribute;
        u8 page;                /* page number */
-       u8 reg;                 /* register */
+       u16 reg;                /* register */
        enum pmbus_sensor_classes class;        /* sensor class */
        bool update;            /* runtime sensor update needed */
        int data;               /* Sensor data.
@@ -86,14 +92,14 @@ struct pmbus_sensor {
 };
 
 struct pmbus_boolean {
-       char name[I2C_NAME_SIZE];       /* sysfs boolean name */
+       char name[PMBUS_NAME_SIZE];     /* sysfs boolean name */
        struct sensor_device_attribute attribute;
 };
 
 struct pmbus_label {
-       char name[I2C_NAME_SIZE];       /* sysfs label name */
+       char name[PMBUS_NAME_SIZE];     /* sysfs label name */
        struct sensor_device_attribute attribute;
-       char label[I2C_NAME_SIZE];      /* label */
+       char label[PMBUS_NAME_SIZE];    /* label */
 };
 
 struct pmbus_data {
@@ -162,19 +168,21 @@ int pmbus_set_page(struct i2c_client *client, u8 page)
 }
 EXPORT_SYMBOL_GPL(pmbus_set_page);
 
-static int pmbus_write_byte(struct i2c_client *client, u8 page, u8 value)
+int pmbus_write_byte(struct i2c_client *client, int page, u8 value)
 {
        int rv;
 
-       rv = pmbus_set_page(client, page);
-       if (rv < 0)
-               return rv;
+       if (page >= 0) {
+               rv = pmbus_set_page(client, page);
+               if (rv < 0)
+                       return rv;
+       }
 
        return i2c_smbus_write_byte(client, value);
 }
+EXPORT_SYMBOL_GPL(pmbus_write_byte);
 
-static int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg,
-                                u16 word)
+int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word)
 {
        int rv;
 
@@ -184,6 +192,28 @@ static int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg,
 
        return i2c_smbus_write_word_data(client, reg, word);
 }
+EXPORT_SYMBOL_GPL(pmbus_write_word_data);
+
+/*
+ * _pmbus_write_word_data() is similar to pmbus_write_word_data(), but checks if
+ * a device specific mapping function exists and calls it if necessary.
+ */
+static int _pmbus_write_word_data(struct i2c_client *client, int page, int reg,
+                                 u16 word)
+{
+       struct pmbus_data *data = i2c_get_clientdata(client);
+       const struct pmbus_driver_info *info = data->info;
+       int status;
+
+       if (info->write_word_data) {
+               status = info->write_word_data(client, page, reg, word);
+               if (status != -ENODATA)
+                       return status;
+       }
+       if (reg >= PMBUS_VIRT_BASE)
+               return -EINVAL;
+       return pmbus_write_word_data(client, page, reg, word);
+}
 
 int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg)
 {
@@ -197,16 +227,57 @@ int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg)
 }
 EXPORT_SYMBOL_GPL(pmbus_read_word_data);
 
-static int pmbus_read_byte_data(struct i2c_client *client, u8 page, u8 reg)
+/*
+ * _pmbus_read_word_data() is similar to pmbus_read_word_data(), but checks if
+ * a device specific mapping function exists and calls it if necessary.
+ */
+static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg)
+{
+       struct pmbus_data *data = i2c_get_clientdata(client);
+       const struct pmbus_driver_info *info = data->info;
+       int status;
+
+       if (info->read_word_data) {
+               status = info->read_word_data(client, page, reg);
+               if (status != -ENODATA)
+                       return status;
+       }
+       if (reg >= PMBUS_VIRT_BASE)
+               return -EINVAL;
+       return pmbus_read_word_data(client, page, reg);
+}
+
+int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg)
 {
        int rv;
 
-       rv = pmbus_set_page(client, page);
-       if (rv < 0)
-               return rv;
+       if (page >= 0) {
+               rv = pmbus_set_page(client, page);
+               if (rv < 0)
+                       return rv;
+       }
 
        return i2c_smbus_read_byte_data(client, reg);
 }
+EXPORT_SYMBOL_GPL(pmbus_read_byte_data);
+
+/*
+ * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if
+ * a device specific mapping function exists and calls it if necessary.
+ */
+static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+       struct pmbus_data *data = i2c_get_clientdata(client);
+       const struct pmbus_driver_info *info = data->info;
+       int status;
+
+       if (info->read_byte_data) {
+               status = info->read_byte_data(client, page, reg);
+               if (status != -ENODATA)
+                       return status;
+       }
+       return pmbus_read_byte_data(client, page, reg);
+}
 
 static void pmbus_clear_fault_page(struct i2c_client *client, int page)
 {
@@ -223,13 +294,13 @@ void pmbus_clear_faults(struct i2c_client *client)
 }
 EXPORT_SYMBOL_GPL(pmbus_clear_faults);
 
-static int pmbus_check_status_cml(struct i2c_client *client, int page)
+static int pmbus_check_status_cml(struct i2c_client *client)
 {
        int status, status2;
 
-       status = pmbus_read_byte_data(client, page, PMBUS_STATUS_BYTE);
+       status = pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE);
        if (status < 0 || (status & PB_STATUS_CML)) {
-               status2 = pmbus_read_byte_data(client, page, PMBUS_STATUS_CML);
+               status2 = pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
                if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND))
                        return -EINVAL;
        }
@@ -241,10 +312,10 @@ bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg)
        int rv;
        struct pmbus_data *data = i2c_get_clientdata(client);
 
-       rv = pmbus_read_byte_data(client, page, reg);
+       rv = _pmbus_read_byte_data(client, page, reg);
        if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK))
-               rv = pmbus_check_status_cml(client, page);
-       pmbus_clear_fault_page(client, page);
+               rv = pmbus_check_status_cml(client);
+       pmbus_clear_fault_page(client, -1);
        return rv >= 0;
 }
 EXPORT_SYMBOL_GPL(pmbus_check_byte_register);
@@ -254,10 +325,10 @@ bool pmbus_check_word_register(struct i2c_client *client, int page, int reg)
        int rv;
        struct pmbus_data *data = i2c_get_clientdata(client);
 
-       rv = pmbus_read_word_data(client, page, reg);
+       rv = _pmbus_read_word_data(client, page, reg);
        if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK))
-               rv = pmbus_check_status_cml(client, page);
-       pmbus_clear_fault_page(client, page);
+               rv = pmbus_check_status_cml(client);
+       pmbus_clear_fault_page(client, -1);
        return rv >= 0;
 }
 EXPORT_SYMBOL_GPL(pmbus_check_word_register);
@@ -270,24 +341,6 @@ const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client *client)
 }
 EXPORT_SYMBOL_GPL(pmbus_get_driver_info);
 
-/*
- * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if
- * a device specific mapping funcion exists and calls it if necessary.
- */
-static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg)
-{
-       struct pmbus_data *data = i2c_get_clientdata(client);
-       const struct pmbus_driver_info *info = data->info;
-       int status;
-
-       if (info->read_byte_data) {
-               status = info->read_byte_data(client, page, reg);
-               if (status != -ENODATA)
-                       return status;
-       }
-       return pmbus_read_byte_data(client, page, reg);
-}
-
 static struct pmbus_data *pmbus_update_device(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
@@ -347,8 +400,9 @@ static struct pmbus_data *pmbus_update_device(struct device *dev)
 
                        if (!data->valid || sensor->update)
                                sensor->data
-                                   = pmbus_read_word_data(client, sensor->page,
-                                                          sensor->reg);
+                                   = _pmbus_read_word_data(client,
+                                                           sensor->page,
+                                                           sensor->reg);
                }
                pmbus_clear_faults(client);
                data->last_updated = jiffies;
@@ -443,15 +497,37 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
        return (val - b) / m;
 }
 
+/*
+ * Convert VID sensor values to milli- or micro-units
+ * depending on sensor type.
+ * We currently only support VR11.
+ */
+static long pmbus_reg2data_vid(struct pmbus_data *data,
+                              struct pmbus_sensor *sensor)
+{
+       long val = sensor->data;
+
+       if (val < 0x02 || val > 0xb2)
+               return 0;
+       return DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100);
+}
+
 static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
 {
        long val;
 
-       if (data->info->direct[sensor->class])
+       switch (data->info->format[sensor->class]) {
+       case direct:
                val = pmbus_reg2data_direct(data, sensor);
-       else
+               break;
+       case vid:
+               val = pmbus_reg2data_vid(data, sensor);
+               break;
+       case linear:
+       default:
                val = pmbus_reg2data_linear(data, sensor);
-
+               break;
+       }
        return val;
 }
 
@@ -561,16 +637,31 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data,
        return val;
 }
 
+static u16 pmbus_data2reg_vid(struct pmbus_data *data,
+                             enum pmbus_sensor_classes class, long val)
+{
+       val = SENSORS_LIMIT(val, 500, 1600);
+
+       return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625);
+}
+
 static u16 pmbus_data2reg(struct pmbus_data *data,
                          enum pmbus_sensor_classes class, long val)
 {
        u16 regval;
 
-       if (data->info->direct[class])
+       switch (data->info->format[class]) {
+       case direct:
                regval = pmbus_data2reg_direct(data, class, val);
-       else
+               break;
+       case vid:
+               regval = pmbus_data2reg_vid(data, class, val);
+               break;
+       case linear:
+       default:
                regval = pmbus_data2reg_linear(data, class, val);
-
+               break;
+       }
        return regval;
 }
 
@@ -682,7 +773,7 @@ static ssize_t pmbus_set_sensor(struct device *dev,
 
        mutex_lock(&data->update_lock);
        regval = pmbus_data2reg(data, sensor->class, val);
-       ret = pmbus_write_word_data(client, sensor->page, sensor->reg, regval);
+       ret = _pmbus_write_word_data(client, sensor->page, sensor->reg, regval);
        if (ret < 0)
                rv = ret;
        else
@@ -867,7 +958,8 @@ static void pmbus_find_max_attr(struct i2c_client *client,
  * and its associated alarm attribute.
  */
 struct pmbus_limit_attr {
-       u8 reg;                 /* Limit register */
+       u16 reg;                /* Limit register */
+       bool update;            /* True if register needs updates */
        const char *attr;       /* Attribute name */
        const char *alarm;      /* Alarm attribute name */
        u32 sbit;               /* Alarm attribute status bit */
@@ -912,9 +1004,10 @@ static bool pmbus_add_limit_attrs(struct i2c_client *client,
                if (pmbus_check_word_register(client, page, l->reg)) {
                        cindex = data->num_sensors;
                        pmbus_add_sensor(data, name, l->attr, index, page,
-                                        l->reg, attr->class, attr->update,
+                                        l->reg, attr->class,
+                                        attr->update || l->update,
                                         false);
-                       if (info->func[page] & attr->sfunc) {
+                       if (l->sbit && (info->func[page] & attr->sfunc)) {
                                if (attr->compare) {
                                        pmbus_add_boolean_cmp(data, name,
                                                l->alarm, index,
@@ -953,9 +1046,11 @@ static void pmbus_add_sensor_attrs_one(struct i2c_client *client,
                                                   index, page, cbase, attr);
                /*
                 * Add generic alarm attribute only if there are no individual
-                * alarm attributes, and if there is a global alarm bit.
+                * alarm attributes, if there is a global alarm bit, and if
+                * the generic status register for this page is accessible.
                 */
-               if (!have_alarm && attr->gbit)
+               if (!have_alarm && attr->gbit &&
+                   pmbus_check_byte_register(client, page, PMBUS_STATUS_BYTE))
                        pmbus_add_boolean_reg(data, name, "alarm", index,
                                              PB_STATUS_BASE + page,
                                              attr->gbit);
@@ -1008,6 +1103,21 @@ static const struct pmbus_limit_attr vin_limit_attrs[] = {
                .attr = "crit",
                .alarm = "crit_alarm",
                .sbit = PB_VOLTAGE_OV_FAULT,
+       }, {
+               .reg = PMBUS_VIRT_READ_VIN_AVG,
+               .update = true,
+               .attr = "average",
+       }, {
+               .reg = PMBUS_VIRT_READ_VIN_MIN,
+               .update = true,
+               .attr = "lowest",
+       }, {
+               .reg = PMBUS_VIRT_READ_VIN_MAX,
+               .update = true,
+               .attr = "highest",
+       }, {
+               .reg = PMBUS_VIRT_RESET_VIN_HISTORY,
+               .attr = "reset_history",
        },
 };
 
@@ -1032,6 +1142,21 @@ static const struct pmbus_limit_attr vout_limit_attrs[] = {
                .attr = "crit",
                .alarm = "crit_alarm",
                .sbit = PB_VOLTAGE_OV_FAULT,
+       }, {
+               .reg = PMBUS_VIRT_READ_VOUT_AVG,
+               .update = true,
+               .attr = "average",
+       }, {
+               .reg = PMBUS_VIRT_READ_VOUT_MIN,
+               .update = true,
+               .attr = "lowest",
+       }, {
+               .reg = PMBUS_VIRT_READ_VOUT_MAX,
+               .update = true,
+               .attr = "highest",
+       }, {
+               .reg = PMBUS_VIRT_RESET_VOUT_HISTORY,
+               .attr = "reset_history",
        }
 };
 
@@ -1078,6 +1203,21 @@ static const struct pmbus_limit_attr iin_limit_attrs[] = {
                .attr = "crit",
                .alarm = "crit_alarm",
                .sbit = PB_IIN_OC_FAULT,
+       }, {
+               .reg = PMBUS_VIRT_READ_IIN_AVG,
+               .update = true,
+               .attr = "average",
+       }, {
+               .reg = PMBUS_VIRT_READ_IIN_MIN,
+               .update = true,
+               .attr = "lowest",
+       }, {
+               .reg = PMBUS_VIRT_READ_IIN_MAX,
+               .update = true,
+               .attr = "highest",
+       }, {
+               .reg = PMBUS_VIRT_RESET_IIN_HISTORY,
+               .attr = "reset_history",
        }
 };
 
@@ -1097,6 +1237,21 @@ static const struct pmbus_limit_attr iout_limit_attrs[] = {
                .attr = "crit",
                .alarm = "crit_alarm",
                .sbit = PB_IOUT_OC_FAULT,
+       }, {
+               .reg = PMBUS_VIRT_READ_IOUT_AVG,
+               .update = true,
+               .attr = "average",
+       }, {
+               .reg = PMBUS_VIRT_READ_IOUT_MIN,
+               .update = true,
+               .attr = "lowest",
+       }, {
+               .reg = PMBUS_VIRT_READ_IOUT_MAX,
+               .update = true,
+               .attr = "highest",
+       }, {
+               .reg = PMBUS_VIRT_RESET_IOUT_HISTORY,
+               .attr = "reset_history",
        }
 };
 
@@ -1132,6 +1287,17 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = {
                .attr = "max",
                .alarm = "alarm",
                .sbit = PB_PIN_OP_WARNING,
+       }, {
+               .reg = PMBUS_VIRT_READ_PIN_AVG,
+               .update = true,
+               .attr = "average",
+       }, {
+               .reg = PMBUS_VIRT_READ_PIN_MAX,
+               .update = true,
+               .attr = "input_highest",
+       }, {
+               .reg = PMBUS_VIRT_RESET_PIN_HISTORY,
+               .attr = "reset_history",
        }
 };
 
@@ -1180,6 +1346,39 @@ static const struct pmbus_sensor_attr power_attributes[] = {
 /* Temperature atributes */
 
 static const struct pmbus_limit_attr temp_limit_attrs[] = {
+       {
+               .reg = PMBUS_UT_WARN_LIMIT,
+               .attr = "min",
+               .alarm = "min_alarm",
+               .sbit = PB_TEMP_UT_WARNING,
+       }, {
+               .reg = PMBUS_UT_FAULT_LIMIT,
+               .attr = "lcrit",
+               .alarm = "lcrit_alarm",
+               .sbit = PB_TEMP_UT_FAULT,
+       }, {
+               .reg = PMBUS_OT_WARN_LIMIT,
+               .attr = "max",
+               .alarm = "max_alarm",
+               .sbit = PB_TEMP_OT_WARNING,
+       }, {
+               .reg = PMBUS_OT_FAULT_LIMIT,
+               .attr = "crit",
+               .alarm = "crit_alarm",
+               .sbit = PB_TEMP_OT_FAULT,
+       }, {
+               .reg = PMBUS_VIRT_READ_TEMP_MIN,
+               .attr = "lowest",
+       }, {
+               .reg = PMBUS_VIRT_READ_TEMP_MAX,
+               .attr = "highest",
+       }, {
+               .reg = PMBUS_VIRT_RESET_TEMP_HISTORY,
+               .attr = "reset_history",
+       }
+};
+
+static const struct pmbus_limit_attr temp_limit_attrs23[] = {
        {
                .reg = PMBUS_UT_WARN_LIMIT,
                .attr = "min",
@@ -1226,8 +1425,8 @@ static const struct pmbus_sensor_attr temp_attributes[] = {
                .sfunc = PMBUS_HAVE_STATUS_TEMP,
                .sbase = PB_STATUS_TEMP_BASE,
                .gbit = PB_STATUS_TEMPERATURE,
-               .limit = temp_limit_attrs,
-               .nlimit = ARRAY_SIZE(temp_limit_attrs),
+               .limit = temp_limit_attrs23,
+               .nlimit = ARRAY_SIZE(temp_limit_attrs23),
        }, {
                .reg = PMBUS_READ_TEMPERATURE_3,
                .class = PSC_TEMPERATURE,
@@ -1238,8 +1437,8 @@ static const struct pmbus_sensor_attr temp_attributes[] = {
                .sfunc = PMBUS_HAVE_STATUS_TEMP,
                .sbase = PB_STATUS_TEMP_BASE,
                .gbit = PB_STATUS_TEMPERATURE,
-               .limit = temp_limit_attrs,
-               .nlimit = ARRAY_SIZE(temp_limit_attrs),
+               .limit = temp_limit_attrs23,
+               .nlimit = ARRAY_SIZE(temp_limit_attrs23),
        }
 };
 
@@ -1380,7 +1579,7 @@ static int pmbus_identify_common(struct i2c_client *client,
                 */
                switch (vout_mode >> 5) {
                case 0: /* linear mode      */
-                       if (data->info->direct[PSC_VOLTAGE_OUT])
+                       if (data->info->format[PSC_VOLTAGE_OUT] != linear)
                                return -ENODEV;
 
                        exponent = vout_mode & 0x1f;
@@ -1389,8 +1588,12 @@ static int pmbus_identify_common(struct i2c_client *client,
                                exponent |= ~0x1f;
                        data->exponent = exponent;
                        break;
+               case 1: /* VID mode         */
+                       if (data->info->format[PSC_VOLTAGE_OUT] != vid)
+                               return -ENODEV;
+                       break;
                case 2: /* direct mode      */
-                       if (!data->info->direct[PSC_VOLTAGE_OUT])
+                       if (data->info->format[PSC_VOLTAGE_OUT] != direct)
                                return -ENODEV;
                        break;
                default:
@@ -1457,18 +1660,6 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
                ret = -EINVAL;
                goto out_data;
        }
-       /*
-        * Bail out if more than one page was configured, but we can not
-        * select the highest page. This is an indication that the wrong
-        * chip type was selected. Better bail out now than keep
-        * returning errors later on.
-        */
-       if (info->pages > 1 && pmbus_set_page(client, info->pages - 1) < 0) {
-               dev_err(&client->dev, "Failed to select page %d\n",
-                       info->pages - 1);
-               ret = -EINVAL;
-               goto out_data;
-       }
 
        ret = pmbus_identify_common(client, data);
        if (ret < 0) {
index 3be60da..67cbcfa 100644 (file)
@@ -141,6 +141,8 @@ static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
                pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, time_16);
                pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, time_8);
        }
+       if (hwif->index > 0)
+               pci_dev_put(dev);
 }
 
 static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
index 542603b..962693b 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/ata_platform.h>
 #include <linux/platform_device.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 
 static void __devinit plat_ide_setup_ports(struct ide_hw *hw,
@@ -95,7 +96,10 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
        plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start);
        hw.dev = &pdev->dev;
 
-       d.irq_flags = res_irq->flags;
+       d.irq_flags = res_irq->flags & IRQF_TRIGGER_MASK;
+       if (res_irq->flags & IORESOURCE_IRQ_SHAREABLE)
+               d.irq_flags |= IRQF_SHARED;
+
        if (mmio)
                d.host_flags |= IDE_HFLAG_MMIO;
 
index 444470a..6a8f36e 100644 (file)
@@ -802,11 +802,9 @@ static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
                        maplen = frag->size;
-                       mapaddr =
-                           pci_map_page(c2dev->pcidev, frag->page,
-                                        frag->page_offset, maplen,
-                                        PCI_DMA_TODEVICE);
-
+                       mapaddr = skb_frag_dma_map(&c2dev->pcidev->dev, frag,
+                                                  0, maplen,
+                                                  PCI_DMA_TODEVICE);
                        elem = elem->next;
                        elem->skb = NULL;
                        elem->mapaddr = mapaddr;
index 621619c..2761364 100644 (file)
@@ -1,4 +1,4 @@
-ccflags-y := -Idrivers/net/cxgb3
+ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb3
 
 obj-$(CONFIG_INFINIBAND_CXGB3) += iw_cxgb3.o
 
index cd20b13..46b878c 100644 (file)
@@ -1,4 +1,4 @@
-ccflags-y := -Idrivers/net/cxgb4
+ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
 
 obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o
 
index bd995b2..24ab11a 100644 (file)
@@ -1,6 +1,7 @@
 config MLX4_INFINIBAND
        tristate "Mellanox ConnectX HCA support"
-       depends on NETDEVICES && NETDEV_10000 && PCI
+       depends on NETDEVICES && ETHERNET && PCI
+       select NET_VENDOR_MELLANOX
        select MLX4_CORE
        ---help---
          This driver provides low-level InfiniBand support for
index 9d7ffeb..96cb35a 100644 (file)
@@ -441,11 +441,11 @@ static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev)
                nesnic->tx_skb[nesnic->sq_head] = skb;
                for (skb_fragment_index = 0; skb_fragment_index < skb_shinfo(skb)->nr_frags;
                                skb_fragment_index++) {
-                       bus_address = pci_map_page( nesdev->pcidev,
-                                       skb_shinfo(skb)->frags[skb_fragment_index].page,
-                                       skb_shinfo(skb)->frags[skb_fragment_index].page_offset,
-                                       skb_shinfo(skb)->frags[skb_fragment_index].size,
-                                       PCI_DMA_TODEVICE);
+                       skb_frag_t *frag =
+                               &skb_shinfo(skb)->frags[skb_fragment_index];
+                       bus_address = skb_frag_dma_map(&nesdev->pcidev->dev,
+                                                      frag, 0, frag->size,
+                                                      PCI_DMA_TODEVICE);
                        wqe_fragment_length[wqe_fragment_index] =
                                        cpu_to_le16(skb_shinfo(skb)->frags[skb_fragment_index].size);
                        set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
@@ -561,11 +561,12 @@ tso_sq_no_longer_full:
                        /* Map all the buffers */
                        for (tso_frag_count=0; tso_frag_count < skb_shinfo(skb)->nr_frags;
                                        tso_frag_count++) {
-                               tso_bus_address[tso_frag_count] = pci_map_page( nesdev->pcidev,
-                                               skb_shinfo(skb)->frags[tso_frag_count].page,
-                                               skb_shinfo(skb)->frags[tso_frag_count].page_offset,
-                                               skb_shinfo(skb)->frags[tso_frag_count].size,
-                                               PCI_DMA_TODEVICE);
+                               skb_frag_t *frag =
+                                       &skb_shinfo(skb)->frags[tso_frag_count];
+                               tso_bus_address[tso_frag_count] =
+                                       skb_frag_dma_map(&nesdev->pcidev->dev,
+                                                        frag, 0, frag->size,
+                                                        PCI_DMA_TODEVICE);
                        }
 
                        tso_frag_index = 0;
@@ -1638,7 +1639,7 @@ static const struct net_device_ops nes_netdev_ops = {
        .ndo_get_stats          = nes_netdev_get_stats,
        .ndo_tx_timeout         = nes_netdev_tx_timeout,
        .ndo_set_mac_address    = nes_netdev_set_mac_address,
-       .ndo_set_multicast_list = nes_netdev_set_multicast_list,
+       .ndo_set_rx_mode        = nes_netdev_set_multicast_list,
        .ndo_change_mtu         = nes_netdev_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_fix_features       = nes_fix_features,
index 39913a0..67a477b 100644 (file)
@@ -169,7 +169,7 @@ static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev,
                        goto partial_error;
                skb_fill_page_desc(skb, i, page, 0, PAGE_SIZE);
 
-               mapping[i + 1] = ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[i].page,
+               mapping[i + 1] = ib_dma_map_page(priv->ca, page,
                                                 0, PAGE_SIZE, DMA_FROM_DEVICE);
                if (unlikely(ib_dma_mapping_error(priv->ca, mapping[i + 1])))
                        goto partial_error;
@@ -537,7 +537,8 @@ static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
 
                if (length == 0) {
                        /* don't need this page */
-                       skb_fill_page_desc(toskb, i, frag->page, 0, PAGE_SIZE);
+                       skb_fill_page_desc(toskb, i, skb_frag_page(frag),
+                                          0, PAGE_SIZE);
                        --skb_shinfo(skb)->nr_frags;
                } else {
                        size = min(length, (unsigned) PAGE_SIZE);
index 81ae61d..00435be 100644 (file)
@@ -182,7 +182,7 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id)
                        goto partial_error;
                skb_fill_page_desc(skb, 0, page, 0, PAGE_SIZE);
                mapping[1] =
-                       ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[0].page,
+                       ib_dma_map_page(priv->ca, page,
                                        0, PAGE_SIZE, DMA_FROM_DEVICE);
                if (unlikely(ib_dma_mapping_error(priv->ca, mapping[1])))
                        goto partial_error;
@@ -323,7 +323,8 @@ static int ipoib_dma_map_tx(struct ib_device *ca,
 
        for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
                skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-               mapping[i + off] = ib_dma_map_page(ca, frag->page,
+               mapping[i + off] = ib_dma_map_page(ca,
+                                                skb_frag_page(frag),
                                                 frag->page_offset, frag->size,
                                                 DMA_TO_DEVICE);
                if (unlikely(ib_dma_mapping_error(ca, mapping[i + off])))
index 43f89ba..aa30915 100644 (file)
@@ -996,7 +996,7 @@ static const struct net_device_ops ipoib_netdev_ops = {
        .ndo_fix_features        = ipoib_fix_features,
        .ndo_start_xmit          = ipoib_start_xmit,
        .ndo_tx_timeout          = ipoib_timeout,
-       .ndo_set_multicast_list  = ipoib_set_mcast_list,
+       .ndo_set_rx_mode         = ipoib_set_mcast_list,
        .ndo_neigh_setup         = ipoib_neigh_setup_dev,
 };
 
index ce281d1..67df91a 100644 (file)
@@ -483,7 +483,7 @@ static int gpio_keys_get_devtree_pdata(struct device *dev,
 
        buttons = kzalloc(pdata->nbuttons * (sizeof *buttons), GFP_KERNEL);
        if (!buttons)
-               return -ENODEV;
+               return -ENOMEM;
 
        pp = NULL;
        i = 0;
index ab0acaf..756348a 100644 (file)
@@ -754,8 +754,11 @@ fail3:
        device_remove_file(&client->dev, &dev_attr_disable_kp);
 fail2:
        while (--pwm >= 0)
-               if (lm->pwm[pwm].enabled)
+               if (lm->pwm[pwm].enabled) {
+                       device_remove_file(lm->pwm[pwm].cdev.dev,
+                                          &dev_attr_time);
                        led_classdev_unregister(&lm->pwm[pwm].cdev);
+               }
 fail1:
        input_free_device(idev);
        kfree(lm);
@@ -775,8 +778,10 @@ static int __devexit lm8323_remove(struct i2c_client *client)
        device_remove_file(&lm->client->dev, &dev_attr_disable_kp);
 
        for (i = 0; i < 3; i++)
-               if (lm->pwm[i].enabled)
+               if (lm->pwm[i].enabled) {
+                       device_remove_file(lm->pwm[i].cdev.dev, &dev_attr_time);
                        led_classdev_unregister(&lm->pwm[i].cdev);
+               }
 
        kfree(lm);
 
index da3828f..f270447 100644 (file)
@@ -19,6 +19,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/platform_device.h>
@@ -37,7 +38,7 @@
 #define KBC_ROW_SCAN_DLY       5
 
 /* KBC uses a 32KHz clock so a cycle = 1/32Khz */
-#define KBC_CYCLE_USEC 32
+#define KBC_CYCLE_MS   32
 
 /* KBC Registers */
 
@@ -647,7 +648,7 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
        debounce_cnt = min(pdata->debounce_cnt, KBC_MAX_DEBOUNCE_CNT);
        scan_time_rows = (KBC_ROW_SCAN_TIME + debounce_cnt) * num_rows;
        kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + pdata->repeat_cnt;
-       kbc->repoll_dly = ((kbc->repoll_dly * KBC_CYCLE_USEC) + 999) / 1000;
+       kbc->repoll_dly = DIV_ROUND_UP(kbc->repoll_dly, KBC_CYCLE_MS);
 
        input_dev->name = pdev->name;
        input_dev->id.bustype = BUS_HOST;
index c456f63..783597a 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/input/kxtj9.h>
 #include <linux/input-polldev.h>
index 20f8f92..6c76cf7 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/input-polldev.h>
+#include <linux/of_device.h>
 
 #define MMA8450_DRV_NAME       "mma8450"
 
@@ -229,10 +230,17 @@ static const struct i2c_device_id mma8450_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, mma8450_id);
 
+static const struct of_device_id mma8450_dt_ids[] = {
+       { .compatible = "fsl,mma8450", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, mma8450_dt_ids);
+
 static struct i2c_driver mma8450_driver = {
        .driver = {
                .name   = MMA8450_DRV_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = mma8450_dt_ids,
        },
        .probe          = mma8450_probe,
        .remove         = __devexit_p(mma8450_remove),
index 95577c1..4d17d9f 100644 (file)
@@ -32,6 +32,7 @@
 #define DEBUG
 #include <linux/slab.h>
 #include <linux/input.h>
+#include <linux/module.h>
 #include <linux/serio.h>
 #include <linux/libps2.h>
 #include <linux/delay.h>
index 80baa53..d64c5a4 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/io.h>
-
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 
index bc3b518..131f9d1 100644 (file)
@@ -249,12 +249,14 @@ static void __ad7879_enable(struct ad7879 *ts)
 
 static void __ad7879_disable(struct ad7879 *ts)
 {
+       u16 reg = (ts->cmd_crtl2 & ~AD7879_PM(-1)) |
+               AD7879_PM(AD7879_PM_SHUTDOWN);
        disable_irq(ts->irq);
 
        if (del_timer_sync(&ts->timer))
                ad7879_ts_event_release(ts);
 
-       ad7879_write(ts, AD7879_REG_CTRL2, AD7879_PM(AD7879_PM_SHUTDOWN));
+       ad7879_write(ts, AD7879_REG_CTRL2, reg);
 }
 
 
index 8420129..f75a66e 100644 (file)
@@ -241,12 +241,13 @@ config DM_MIRROR
          needed for live data migration tools such as 'pvmove'.
 
 config DM_RAID
-       tristate "RAID 4/5/6 target (EXPERIMENTAL)"
+       tristate "RAID 1/4/5/6 target (EXPERIMENTAL)"
        depends on BLK_DEV_DM && EXPERIMENTAL
+       select MD_RAID1
        select MD_RAID456
        select BLK_DEV_MD
        ---help---
-        A dm target that supports RAID4, RAID5 and RAID6 mappings
+        A dm target that supports RAID1, RAID4, RAID5 and RAID6 mappings
 
         A RAID-5 set of N drives with a capacity of C MB per drive provides
         the capacity of C * (N - 1) MB, and protects against a failure
index bae6c4e..49da55c 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/device-mapper.h>
 
 #define DM_MSG_PREFIX "crypt"
-#define MESG_STR(x) x, sizeof(x)
 
 /*
  * context holding the current state of a multi-part conversion
@@ -239,7 +238,7 @@ static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv,
                              struct dm_crypt_request *dmreq)
 {
        memset(iv, 0, cc->iv_size);
-       *(u32 *)iv = cpu_to_le32(dmreq->iv_sector & 0xffffffff);
+       *(__le32 *)iv = cpu_to_le32(dmreq->iv_sector & 0xffffffff);
 
        return 0;
 }
@@ -248,7 +247,7 @@ static int crypt_iv_plain64_gen(struct crypt_config *cc, u8 *iv,
                                struct dm_crypt_request *dmreq)
 {
        memset(iv, 0, cc->iv_size);
-       *(u64 *)iv = cpu_to_le64(dmreq->iv_sector);
+       *(__le64 *)iv = cpu_to_le64(dmreq->iv_sector);
 
        return 0;
 }
@@ -415,7 +414,7 @@ static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv,
        struct crypto_cipher *essiv_tfm = this_crypt_config(cc)->iv_private;
 
        memset(iv, 0, cc->iv_size);
-       *(u64 *)iv = cpu_to_le64(dmreq->iv_sector);
+       *(__le64 *)iv = cpu_to_le64(dmreq->iv_sector);
        crypto_cipher_encrypt_one(essiv_tfm, iv, iv);
 
        return 0;
@@ -1575,11 +1574,17 @@ bad_mem:
 static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
        struct crypt_config *cc;
-       unsigned int key_size;
+       unsigned int key_size, opt_params;
        unsigned long long tmpll;
        int ret;
+       struct dm_arg_set as;
+       const char *opt_string;
+
+       static struct dm_arg _args[] = {
+               {0, 1, "Invalid number of feature args"},
+       };
 
-       if (argc != 5) {
+       if (argc < 5) {
                ti->error = "Not enough arguments";
                return -EINVAL;
        }
@@ -1648,6 +1653,30 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        }
        cc->start = tmpll;
 
+       argv += 5;
+       argc -= 5;
+
+       /* Optional parameters */
+       if (argc) {
+               as.argc = argc;
+               as.argv = argv;
+
+               ret = dm_read_arg_group(_args, &as, &opt_params, &ti->error);
+               if (ret)
+                       goto bad;
+
+               opt_string = dm_shift_arg(&as);
+
+               if (opt_params == 1 && opt_string &&
+                   !strcasecmp(opt_string, "allow_discards"))
+                       ti->num_discard_requests = 1;
+               else if (opt_params) {
+                       ret = -EINVAL;
+                       ti->error = "Invalid feature arguments";
+                       goto bad;
+               }
+       }
+
        ret = -ENOMEM;
        cc->io_queue = alloc_workqueue("kcryptd_io",
                                       WQ_NON_REENTRANT|
@@ -1682,9 +1711,16 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
        struct dm_crypt_io *io;
        struct crypt_config *cc;
 
-       if (bio->bi_rw & REQ_FLUSH) {
+       /*
+        * If bio is REQ_FLUSH or REQ_DISCARD, just bypass crypt queues.
+        * - for REQ_FLUSH device-mapper core ensures that no IO is in-flight
+        * - for REQ_DISCARD caller must use flush if IO ordering matters
+        */
+       if (unlikely(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))) {
                cc = ti->private;
                bio->bi_bdev = cc->dev->bdev;
+               if (bio_sectors(bio))
+                       bio->bi_sector = cc->start + dm_target_offset(ti, bio->bi_sector);
                return DM_MAPIO_REMAPPED;
        }
 
@@ -1727,6 +1763,10 @@ static int crypt_status(struct dm_target *ti, status_type_t type,
 
                DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
                                cc->dev->name, (unsigned long long)cc->start);
+
+               if (ti->num_discard_requests)
+                       DMEMIT(" 1 allow_discards");
+
                break;
        }
        return 0;
@@ -1770,12 +1810,12 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
        if (argc < 2)
                goto error;
 
-       if (!strnicmp(argv[0], MESG_STR("key"))) {
+       if (!strcasecmp(argv[0], "key")) {
                if (!test_bit(DM_CRYPT_SUSPENDED, &cc->flags)) {
                        DMWARN("not suspended during key manipulation.");
                        return -EINVAL;
                }
-               if (argc == 3 && !strnicmp(argv[1], MESG_STR("set"))) {
+               if (argc == 3 && !strcasecmp(argv[1], "set")) {
                        ret = crypt_set_key(cc, argv[2]);
                        if (ret)
                                return ret;
@@ -1783,7 +1823,7 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
                                ret = cc->iv_gen_ops->init(cc);
                        return ret;
                }
-               if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe"))) {
+               if (argc == 2 && !strcasecmp(argv[1], "wipe")) {
                        if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) {
                                ret = cc->iv_gen_ops->wipe(cc);
                                if (ret)
@@ -1823,7 +1863,7 @@ static int crypt_iterate_devices(struct dm_target *ti,
 
 static struct target_type crypt_target = {
        .name   = "crypt",
-       .version = {1, 10, 0},
+       .version = {1, 11, 0},
        .module = THIS_MODULE,
        .ctr    = crypt_ctr,
        .dtr    = crypt_dtr,
index ea79062..89f73ca 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2003 Sistina Software (UK) Limited.
- * Copyright (C) 2004, 2010 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004, 2010-2011 Red Hat, Inc. All rights reserved.
  *
  * This file is released under the GPL.
  */
@@ -15,6 +15,9 @@
 
 #define DM_MSG_PREFIX "flakey"
 
+#define all_corrupt_bio_flags_match(bio, fc)   \
+       (((bio)->bi_rw & (fc)->corrupt_bio_flags) == (fc)->corrupt_bio_flags)
+
 /*
  * Flakey: Used for testing only, simulates intermittent,
  * catastrophic device failure.
@@ -25,60 +28,189 @@ struct flakey_c {
        sector_t start;
        unsigned up_interval;
        unsigned down_interval;
+       unsigned long flags;
+       unsigned corrupt_bio_byte;
+       unsigned corrupt_bio_rw;
+       unsigned corrupt_bio_value;
+       unsigned corrupt_bio_flags;
+};
+
+enum feature_flag_bits {
+       DROP_WRITES
 };
 
+static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
+                         struct dm_target *ti)
+{
+       int r;
+       unsigned argc;
+       const char *arg_name;
+
+       static struct dm_arg _args[] = {
+               {0, 6, "Invalid number of feature args"},
+               {1, UINT_MAX, "Invalid corrupt bio byte"},
+               {0, 255, "Invalid corrupt value to write into bio byte (0-255)"},
+               {0, UINT_MAX, "Invalid corrupt bio flags mask"},
+       };
+
+       /* No feature arguments supplied. */
+       if (!as->argc)
+               return 0;
+
+       r = dm_read_arg_group(_args, as, &argc, &ti->error);
+       if (r)
+               return r;
+
+       while (argc) {
+               arg_name = dm_shift_arg(as);
+               argc--;
+
+               /*
+                * drop_writes
+                */
+               if (!strcasecmp(arg_name, "drop_writes")) {
+                       if (test_and_set_bit(DROP_WRITES, &fc->flags)) {
+                               ti->error = "Feature drop_writes duplicated";
+                               return -EINVAL;
+                       }
+
+                       continue;
+               }
+
+               /*
+                * corrupt_bio_byte <Nth_byte> <direction> <value> <bio_flags>
+                */
+               if (!strcasecmp(arg_name, "corrupt_bio_byte")) {
+                       if (!argc)
+                               ti->error = "Feature corrupt_bio_byte requires parameters";
+
+                       r = dm_read_arg(_args + 1, as, &fc->corrupt_bio_byte, &ti->error);
+                       if (r)
+                               return r;
+                       argc--;
+
+                       /*
+                        * Direction r or w?
+                        */
+                       arg_name = dm_shift_arg(as);
+                       if (!strcasecmp(arg_name, "w"))
+                               fc->corrupt_bio_rw = WRITE;
+                       else if (!strcasecmp(arg_name, "r"))
+                               fc->corrupt_bio_rw = READ;
+                       else {
+                               ti->error = "Invalid corrupt bio direction (r or w)";
+                               return -EINVAL;
+                       }
+                       argc--;
+
+                       /*
+                        * Value of byte (0-255) to write in place of correct one.
+                        */
+                       r = dm_read_arg(_args + 2, as, &fc->corrupt_bio_value, &ti->error);
+                       if (r)
+                               return r;
+                       argc--;
+
+                       /*
+                        * Only corrupt bios with these flags set.
+                        */
+                       r = dm_read_arg(_args + 3, as, &fc->corrupt_bio_flags, &ti->error);
+                       if (r)
+                               return r;
+                       argc--;
+
+                       continue;
+               }
+
+               ti->error = "Unrecognised flakey feature requested";
+               return -EINVAL;
+       }
+
+       if (test_bit(DROP_WRITES, &fc->flags) && (fc->corrupt_bio_rw == WRITE)) {
+               ti->error = "drop_writes is incompatible with corrupt_bio_byte with the WRITE flag set";
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /*
- * Construct a flakey mapping: <dev_path> <offset> <up interval> <down interval>
+ * Construct a flakey mapping:
+ * <dev_path> <offset> <up interval> <down interval> [<#feature args> [<arg>]*]
+ *
+ *   Feature args:
+ *     [drop_writes]
+ *     [corrupt_bio_byte <Nth_byte> <direction> <value> <bio_flags>]
+ *
+ *   Nth_byte starts from 1 for the first byte.
+ *   Direction is r for READ or w for WRITE.
+ *   bio_flags is ignored if 0.
  */
 static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
+       static struct dm_arg _args[] = {
+               {0, UINT_MAX, "Invalid up interval"},
+               {0, UINT_MAX, "Invalid down interval"},
+       };
+
+       int r;
        struct flakey_c *fc;
-       unsigned long long tmp;
+       unsigned long long tmpll;
+       struct dm_arg_set as;
+       const char *devname;
 
-       if (argc != 4) {
-               ti->error = "dm-flakey: Invalid argument count";
+       as.argc = argc;
+       as.argv = argv;
+
+       if (argc < 4) {
+               ti->error = "Invalid argument count";
                return -EINVAL;
        }
 
-       fc = kmalloc(sizeof(*fc), GFP_KERNEL);
+       fc = kzalloc(sizeof(*fc), GFP_KERNEL);
        if (!fc) {
-               ti->error = "dm-flakey: Cannot allocate linear context";
+               ti->error = "Cannot allocate linear context";
                return -ENOMEM;
        }
        fc->start_time = jiffies;
 
-       if (sscanf(argv[1], "%llu", &tmp) != 1) {
-               ti->error = "dm-flakey: Invalid device sector";
+       devname = dm_shift_arg(&as);
+
+       if (sscanf(dm_shift_arg(&as), "%llu", &tmpll) != 1) {
+               ti->error = "Invalid device sector";
                goto bad;
        }
-       fc->start = tmp;
+       fc->start = tmpll;
 
-       if (sscanf(argv[2], "%u", &fc->up_interval) != 1) {
-               ti->error = "dm-flakey: Invalid up interval";
+       r = dm_read_arg(_args, &as, &fc->up_interval, &ti->error);
+       if (r)
                goto bad;
-       }
 
-       if (sscanf(argv[3], "%u", &fc->down_interval) != 1) {
-               ti->error = "dm-flakey: Invalid down interval";
+       r = dm_read_arg(_args, &as, &fc->down_interval, &ti->error);
+       if (r)
                goto bad;
-       }
 
        if (!(fc->up_interval + fc->down_interval)) {
-               ti->error = "dm-flakey: Total (up + down) interval is zero";
+               ti->error = "Total (up + down) interval is zero";
                goto bad;
        }
 
        if (fc->up_interval + fc->down_interval < fc->up_interval) {
-               ti->error = "dm-flakey: Interval overflow";
+               ti->error = "Interval overflow";
                goto bad;
        }
 
-       if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &fc->dev)) {
-               ti->error = "dm-flakey: Device lookup failed";
+       r = parse_features(&as, fc, ti);
+       if (r)
+               goto bad;
+
+       if (dm_get_device(ti, devname, dm_table_get_mode(ti->table), &fc->dev)) {
+               ti->error = "Device lookup failed";
                goto bad;
        }
 
        ti->num_flush_requests = 1;
+       ti->num_discard_requests = 1;
        ti->private = fc;
        return 0;
 
@@ -99,7 +231,7 @@ static sector_t flakey_map_sector(struct dm_target *ti, sector_t bi_sector)
 {
        struct flakey_c *fc = ti->private;
 
-       return fc->start + (bi_sector - ti->begin);
+       return fc->start + dm_target_offset(ti, bi_sector);
 }
 
 static void flakey_map_bio(struct dm_target *ti, struct bio *bio)
@@ -111,6 +243,25 @@ static void flakey_map_bio(struct dm_target *ti, struct bio *bio)
                bio->bi_sector = flakey_map_sector(ti, bio->bi_sector);
 }
 
+static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc)
+{
+       unsigned bio_bytes = bio_cur_bytes(bio);
+       char *data = bio_data(bio);
+
+       /*
+        * Overwrite the Nth byte of the data returned.
+        */
+       if (data && bio_bytes >= fc->corrupt_bio_byte) {
+               data[fc->corrupt_bio_byte - 1] = fc->corrupt_bio_value;
+
+               DMDEBUG("Corrupting data bio=%p by writing %u to byte %u "
+                       "(rw=%c bi_rw=%lu bi_sector=%llu cur_bytes=%u)\n",
+                       bio, fc->corrupt_bio_value, fc->corrupt_bio_byte,
+                       (bio_data_dir(bio) == WRITE) ? 'w' : 'r',
+                       bio->bi_rw, (unsigned long long)bio->bi_sector, bio_bytes);
+       }
+}
+
 static int flakey_map(struct dm_target *ti, struct bio *bio,
                      union map_info *map_context)
 {
@@ -119,18 +270,71 @@ static int flakey_map(struct dm_target *ti, struct bio *bio,
 
        /* Are we alive ? */
        elapsed = (jiffies - fc->start_time) / HZ;
-       if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval)
+       if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval) {
+               /*
+                * Flag this bio as submitted while down.
+                */
+               map_context->ll = 1;
+
+               /*
+                * Map reads as normal.
+                */
+               if (bio_data_dir(bio) == READ)
+                       goto map_bio;
+
+               /*
+                * Drop writes?
+                */
+               if (test_bit(DROP_WRITES, &fc->flags)) {
+                       bio_endio(bio, 0);
+                       return DM_MAPIO_SUBMITTED;
+               }
+
+               /*
+                * Corrupt matching writes.
+                */
+               if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == WRITE)) {
+                       if (all_corrupt_bio_flags_match(bio, fc))
+                               corrupt_bio_data(bio, fc);
+                       goto map_bio;
+               }
+
+               /*
+                * By default, error all I/O.
+                */
                return -EIO;
+       }
 
+map_bio:
        flakey_map_bio(ti, bio);
 
        return DM_MAPIO_REMAPPED;
 }
 
+static int flakey_end_io(struct dm_target *ti, struct bio *bio,
+                        int error, union map_info *map_context)
+{
+       struct flakey_c *fc = ti->private;
+       unsigned bio_submitted_while_down = map_context->ll;
+
+       /*
+        * Corrupt successful READs while in down state.
+        * If flags were specified, only corrupt those that match.
+        */
+       if (!error && bio_submitted_while_down &&
+           (bio_data_dir(bio) == READ) && (fc->corrupt_bio_rw == READ) &&
+           all_corrupt_bio_flags_match(bio, fc))
+               corrupt_bio_data(bio, fc);
+
+       return error;
+}
+
 static int flakey_status(struct dm_target *ti, status_type_t type,
                         char *result, unsigned int maxlen)
 {
+       unsigned sz = 0;
        struct flakey_c *fc = ti->private;
+       unsigned drop_writes;
 
        switch (type) {
        case STATUSTYPE_INFO:
@@ -138,9 +342,22 @@ static int flakey_status(struct dm_target *ti, status_type_t type,
                break;
 
        case STATUSTYPE_TABLE:
-               snprintf(result, maxlen, "%s %llu %u %u", fc->dev->name,
-                        (unsigned long long)fc->start, fc->up_interval,
-                        fc->down_interval);
+               DMEMIT("%s %llu %u %u ", fc->dev->name,
+                      (unsigned long long)fc->start, fc->up_interval,
+                      fc->down_interval);
+
+               drop_writes = test_bit(DROP_WRITES, &fc->flags);
+               DMEMIT("%u ", drop_writes + (fc->corrupt_bio_byte > 0) * 5);
+
+               if (drop_writes)
+                       DMEMIT("drop_writes ");
+
+               if (fc->corrupt_bio_byte)
+                       DMEMIT("corrupt_bio_byte %u %c %u %u ",
+                              fc->corrupt_bio_byte,
+                              (fc->corrupt_bio_rw == WRITE) ? 'w' : 'r',
+                              fc->corrupt_bio_value, fc->corrupt_bio_flags);
+
                break;
        }
        return 0;
@@ -177,11 +394,12 @@ static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_
 
 static struct target_type flakey_target = {
        .name   = "flakey",
-       .version = {1, 1, 0},
+       .version = {1, 2, 0},
        .module = THIS_MODULE,
        .ctr    = flakey_ctr,
        .dtr    = flakey_dtr,
        .map    = flakey_map,
+       .end_io = flakey_end_io,
        .status = flakey_status,
        .ioctl  = flakey_ioctl,
        .merge  = flakey_merge,
index 2067288..ad2eba4 100644 (file)
@@ -38,6 +38,8 @@ struct io {
        struct dm_io_client *client;
        io_notify_fn callback;
        void *context;
+       void *vma_invalidate_address;
+       unsigned long vma_invalidate_size;
 } __attribute__((aligned(DM_IO_MAX_REGIONS)));
 
 static struct kmem_cache *_dm_io_cache;
@@ -116,6 +118,10 @@ static void dec_count(struct io *io, unsigned int region, int error)
                set_bit(region, &io->error_bits);
 
        if (atomic_dec_and_test(&io->count)) {
+               if (io->vma_invalidate_size)
+                       invalidate_kernel_vmap_range(io->vma_invalidate_address,
+                                                    io->vma_invalidate_size);
+
                if (io->sleeper)
                        wake_up_process(io->sleeper);
 
@@ -159,6 +165,9 @@ struct dpages {
 
        unsigned context_u;
        void *context_ptr;
+
+       void *vma_invalidate_address;
+       unsigned long vma_invalidate_size;
 };
 
 /*
@@ -377,6 +386,9 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
        io->sleeper = current;
        io->client = client;
 
+       io->vma_invalidate_address = dp->vma_invalidate_address;
+       io->vma_invalidate_size = dp->vma_invalidate_size;
+
        dispatch_io(rw, num_regions, where, dp, io, 1);
 
        while (1) {
@@ -415,13 +427,21 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions,
        io->callback = fn;
        io->context = context;
 
+       io->vma_invalidate_address = dp->vma_invalidate_address;
+       io->vma_invalidate_size = dp->vma_invalidate_size;
+
        dispatch_io(rw, num_regions, where, dp, io, 0);
        return 0;
 }
 
-static int dp_init(struct dm_io_request *io_req, struct dpages *dp)
+static int dp_init(struct dm_io_request *io_req, struct dpages *dp,
+                  unsigned long size)
 {
        /* Set up dpages based on memory type */
+
+       dp->vma_invalidate_address = NULL;
+       dp->vma_invalidate_size = 0;
+
        switch (io_req->mem.type) {
        case DM_IO_PAGE_LIST:
                list_dp_init(dp, io_req->mem.ptr.pl, io_req->mem.offset);
@@ -432,6 +452,11 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp)
                break;
 
        case DM_IO_VMA:
+               flush_kernel_vmap_range(io_req->mem.ptr.vma, size);
+               if ((io_req->bi_rw & RW_MASK) == READ) {
+                       dp->vma_invalidate_address = io_req->mem.ptr.vma;
+                       dp->vma_invalidate_size = size;
+               }
                vm_dp_init(dp, io_req->mem.ptr.vma);
                break;
 
@@ -460,7 +485,7 @@ int dm_io(struct dm_io_request *io_req, unsigned num_regions,
        int r;
        struct dpages dp;
 
-       r = dp_init(io_req, &dp);
+       r = dp_init(io_req, &dp, (unsigned long)where->count << SECTOR_SHIFT);
        if (r)
                return r;
 
index 4cacdad..2e9a3ca 100644 (file)
@@ -128,6 +128,24 @@ static struct hash_cell *__get_uuid_cell(const char *str)
        return NULL;
 }
 
+static struct hash_cell *__get_dev_cell(uint64_t dev)
+{
+       struct mapped_device *md;
+       struct hash_cell *hc;
+
+       md = dm_get_md(huge_decode_dev(dev));
+       if (!md)
+               return NULL;
+
+       hc = dm_get_mdptr(md);
+       if (!hc) {
+               dm_put(md);
+               return NULL;
+       }
+
+       return hc;
+}
+
 /*-----------------------------------------------------------------
  * Inserting, removing and renaming a device.
  *---------------------------------------------------------------*/
@@ -718,25 +736,45 @@ static int dev_create(struct dm_ioctl *param, size_t param_size)
  */
 static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
 {
-       struct mapped_device *md;
-       void *mdptr = NULL;
+       struct hash_cell *hc = NULL;
 
-       if (*param->uuid)
-               return __get_uuid_cell(param->uuid);
+       if (*param->uuid) {
+               if (*param->name || param->dev)
+                       return NULL;
 
-       if (*param->name)
-               return __get_name_cell(param->name);
+               hc = __get_uuid_cell(param->uuid);
+               if (!hc)
+                       return NULL;
+       } else if (*param->name) {
+               if (param->dev)
+                       return NULL;
 
-       md = dm_get_md(huge_decode_dev(param->dev));
-       if (!md)
-               goto out;
+               hc = __get_name_cell(param->name);
+               if (!hc)
+                       return NULL;
+       } else if (param->dev) {
+               hc = __get_dev_cell(param->dev);
+               if (!hc)
+                       return NULL;
+       } else
+               return NULL;
 
-       mdptr = dm_get_mdptr(md);
-       if (!mdptr)
-               dm_put(md);
+       /*
+        * Sneakily write in both the name and the uuid
+        * while we have the cell.
+        */
+       strlcpy(param->name, hc->name, sizeof(param->name));
+       if (hc->uuid)
+               strlcpy(param->uuid, hc->uuid, sizeof(param->uuid));
+       else
+               param->uuid[0] = '\0';
 
-out:
-       return mdptr;
+       if (hc->new_map)
+               param->flags |= DM_INACTIVE_PRESENT_FLAG;
+       else
+               param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
+
+       return hc;
 }
 
 static struct mapped_device *find_device(struct dm_ioctl *param)
@@ -746,24 +784,8 @@ static struct mapped_device *find_device(struct dm_ioctl *param)
 
        down_read(&_hash_lock);
        hc = __find_device_hash_cell(param);
-       if (hc) {
+       if (hc)
                md = hc->md;
-
-               /*
-                * Sneakily write in both the name and the uuid
-                * while we have the cell.
-                */
-               strlcpy(param->name, hc->name, sizeof(param->name));
-               if (hc->uuid)
-                       strlcpy(param->uuid, hc->uuid, sizeof(param->uuid));
-               else
-                       param->uuid[0] = '\0';
-
-               if (hc->new_map)
-                       param->flags |= DM_INACTIVE_PRESENT_FLAG;
-               else
-                       param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
-       }
        up_read(&_hash_lock);
 
        return md;
@@ -1402,6 +1424,11 @@ static int target_message(struct dm_ioctl *param, size_t param_size)
                goto out;
        }
 
+       if (!argc) {
+               DMWARN("Empty message received.");
+               goto out;
+       }
+
        table = dm_get_live_table(md);
        if (!table)
                goto out_argv;
index 320401d..f821470 100644 (file)
@@ -224,8 +224,6 @@ struct kcopyd_job {
        unsigned int num_dests;
        struct dm_io_region dests[DM_KCOPYD_MAX_REGIONS];
 
-       sector_t offset;
-       unsigned int nr_pages;
        struct page_list *pages;
 
        /*
@@ -380,7 +378,7 @@ static int run_io_job(struct kcopyd_job *job)
                .bi_rw = job->rw,
                .mem.type = DM_IO_PAGE_LIST,
                .mem.ptr.pl = job->pages,
-               .mem.offset = job->offset,
+               .mem.offset = 0,
                .notify.fn = complete_io,
                .notify.context = job,
                .client = job->kc->io_client,
@@ -397,10 +395,9 @@ static int run_io_job(struct kcopyd_job *job)
 static int run_pages_job(struct kcopyd_job *job)
 {
        int r;
+       unsigned nr_pages = dm_div_up(job->dests[0].count, PAGE_SIZE >> 9);
 
-       job->nr_pages = dm_div_up(job->dests[0].count + job->offset,
-                                 PAGE_SIZE >> 9);
-       r = kcopyd_get_pages(job->kc, job->nr_pages, &job->pages);
+       r = kcopyd_get_pages(job->kc, nr_pages, &job->pages);
        if (!r) {
                /* this job is ready for io */
                push(&job->kc->io_jobs, job);
@@ -602,8 +599,6 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
        job->num_dests = num_dests;
        memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
 
-       job->offset = 0;
-       job->nr_pages = 0;
        job->pages = NULL;
 
        job->fn = fn;
@@ -622,6 +617,37 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
 }
 EXPORT_SYMBOL(dm_kcopyd_copy);
 
+void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc,
+                                dm_kcopyd_notify_fn fn, void *context)
+{
+       struct kcopyd_job *job;
+
+       job = mempool_alloc(kc->job_pool, GFP_NOIO);
+
+       memset(job, 0, sizeof(struct kcopyd_job));
+       job->kc = kc;
+       job->fn = fn;
+       job->context = context;
+
+       atomic_inc(&kc->nr_jobs);
+
+       return job;
+}
+EXPORT_SYMBOL(dm_kcopyd_prepare_callback);
+
+void dm_kcopyd_do_callback(void *j, int read_err, unsigned long write_err)
+{
+       struct kcopyd_job *job = j;
+       struct dm_kcopyd_client *kc = job->kc;
+
+       job->read_err = read_err;
+       job->write_err = write_err;
+
+       push(&kc->complete_jobs, job);
+       wake(kc);
+}
+EXPORT_SYMBOL(dm_kcopyd_do_callback);
+
 /*
  * Cancels a kcopyd job, eg. someone might be deactivating a
  * mirror.
index aa2e0c3..1021c89 100644 (file)
@@ -394,8 +394,7 @@ static int flush_by_group(struct log_c *lc, struct list_head *flush_list)
                        group[count] = fe->region;
                        count++;
 
-                       list_del(&fe->list);
-                       list_add(&fe->list, &tmp_list);
+                       list_move(&fe->list, &tmp_list);
 
                        type = fe->type;
                        if (count >= MAX_FLUSH_GROUP_COUNT)
index 948e3f4..3b52bb7 100644 (file)
@@ -197,15 +197,21 @@ EXPORT_SYMBOL(dm_dirty_log_destroy);
 #define MIRROR_DISK_VERSION 2
 #define LOG_OFFSET 2
 
-struct log_header {
-       uint32_t magic;
+struct log_header_disk {
+       __le32 magic;
 
        /*
         * Simple, incrementing version. no backward
         * compatibility.
         */
+       __le32 version;
+       __le64 nr_regions;
+} __packed;
+
+struct log_header_core {
+       uint32_t magic;
        uint32_t version;
-       sector_t nr_regions;
+       uint64_t nr_regions;
 };
 
 struct log_c {
@@ -239,10 +245,10 @@ struct log_c {
        int log_dev_failed;
        int log_dev_flush_failed;
        struct dm_dev *log_dev;
-       struct log_header header;
+       struct log_header_core header;
 
        struct dm_io_region header_location;
-       struct log_header *disk_header;
+       struct log_header_disk *disk_header;
 };
 
 /*
@@ -251,34 +257,34 @@ struct log_c {
  */
 static inline int log_test_bit(uint32_t *bs, unsigned bit)
 {
-       return test_bit_le(bit, (unsigned long *) bs) ? 1 : 0;
+       return test_bit_le(bit, bs) ? 1 : 0;
 }
 
 static inline void log_set_bit(struct log_c *l,
                               uint32_t *bs, unsigned bit)
 {
-       __test_and_set_bit_le(bit, (unsigned long *) bs);
+       __set_bit_le(bit, bs);
        l->touched_cleaned = 1;
 }
 
 static inline void log_clear_bit(struct log_c *l,
                                 uint32_t *bs, unsigned bit)
 {
-       __test_and_clear_bit_le(bit, (unsigned long *) bs);
+       __clear_bit_le(bit, bs);
        l->touched_dirtied = 1;
 }
 
 /*----------------------------------------------------------------
  * Header IO
  *--------------------------------------------------------------*/
-static void header_to_disk(struct log_header *core, struct log_header *disk)
+static void header_to_disk(struct log_header_core *core, struct log_header_disk *disk)
 {
        disk->magic = cpu_to_le32(core->magic);
        disk->version = cpu_to_le32(core->version);
        disk->nr_regions = cpu_to_le64(core->nr_regions);
 }
 
-static void header_from_disk(struct log_header *core, struct log_header *disk)
+static void header_from_disk(struct log_header_core *core, struct log_header_disk *disk)
 {
        core->magic = le32_to_cpu(disk->magic);
        core->version = le32_to_cpu(disk->version);
@@ -486,7 +492,7 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
        memset(lc->sync_bits, (sync == NOSYNC) ? -1 : 0, bitset_size);
        lc->sync_count = (sync == NOSYNC) ? region_count : 0;
 
-       lc->recovering_bits = vmalloc(bitset_size);
+       lc->recovering_bits = vzalloc(bitset_size);
        if (!lc->recovering_bits) {
                DMWARN("couldn't allocate sync bitset");
                vfree(lc->sync_bits);
@@ -498,7 +504,6 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
                kfree(lc);
                return -ENOMEM;
        }
-       memset(lc->recovering_bits, 0, bitset_size);
        lc->sync_search = 0;
        log->context = lc;
 
@@ -739,8 +744,7 @@ static int core_get_resync_work(struct dm_dirty_log *log, region_t *region)
                return 0;
 
        do {
-               *region = find_next_zero_bit_le(
-                                            (unsigned long *) lc->sync_bits,
+               *region = find_next_zero_bit_le(lc->sync_bits,
                                             lc->region_count,
                                             lc->sync_search);
                lc->sync_search = *region + 1;
index c354701..5e0090e 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/atomic.h>
 
 #define DM_MSG_PREFIX "multipath"
-#define MESG_STR(x) x, sizeof(x)
 #define DM_PG_INIT_DELAY_MSECS 2000
 #define DM_PG_INIT_DELAY_DEFAULT ((unsigned) -1)
 
@@ -505,80 +504,29 @@ static void trigger_event(struct work_struct *work)
  *      <#paths> <#per-path selector args>
  *         [<path> [<arg>]* ]+ ]+
  *---------------------------------------------------------------*/
-struct param {
-       unsigned min;
-       unsigned max;
-       char *error;
-};
-
-static int read_param(struct param *param, char *str, unsigned *v, char **error)
-{
-       if (!str ||
-           (sscanf(str, "%u", v) != 1) ||
-           (*v < param->min) ||
-           (*v > param->max)) {
-               *error = param->error;
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-struct arg_set {
-       unsigned argc;
-       char **argv;
-};
-
-static char *shift(struct arg_set *as)
-{
-       char *r;
-
-       if (as->argc) {
-               as->argc--;
-               r = *as->argv;
-               as->argv++;
-               return r;
-       }
-
-       return NULL;
-}
-
-static void consume(struct arg_set *as, unsigned n)
-{
-       BUG_ON (as->argc < n);
-       as->argc -= n;
-       as->argv += n;
-}
-
-static int parse_path_selector(struct arg_set *as, struct priority_group *pg,
+static int parse_path_selector(struct dm_arg_set *as, struct priority_group *pg,
                               struct dm_target *ti)
 {
        int r;
        struct path_selector_type *pst;
        unsigned ps_argc;
 
-       static struct param _params[] = {
+       static struct dm_arg _args[] = {
                {0, 1024, "invalid number of path selector args"},
        };
 
-       pst = dm_get_path_selector(shift(as));
+       pst = dm_get_path_selector(dm_shift_arg(as));
        if (!pst) {
                ti->error = "unknown path selector type";
                return -EINVAL;
        }
 
-       r = read_param(_params, shift(as), &ps_argc, &ti->error);
+       r = dm_read_arg_group(_args, as, &ps_argc, &ti->error);
        if (r) {
                dm_put_path_selector(pst);
                return -EINVAL;
        }
 
-       if (ps_argc > as->argc) {
-               dm_put_path_selector(pst);
-               ti->error = "not enough arguments for path selector";
-               return -EINVAL;
-       }
-
        r = pst->create(&pg->ps, ps_argc, as->argv);
        if (r) {
                dm_put_path_selector(pst);
@@ -587,12 +535,12 @@ static int parse_path_selector(struct arg_set *as, struct priority_group *pg,
        }
 
        pg->ps.type = pst;
-       consume(as, ps_argc);
+       dm_consume_args(as, ps_argc);
 
        return 0;
 }
 
-static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
+static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps,
                               struct dm_target *ti)
 {
        int r;
@@ -609,7 +557,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
        if (!p)
                return ERR_PTR(-ENOMEM);
 
-       r = dm_get_device(ti, shift(as), dm_table_get_mode(ti->table),
+       r = dm_get_device(ti, dm_shift_arg(as), dm_table_get_mode(ti->table),
                          &p->path.dev);
        if (r) {
                ti->error = "error getting device";
@@ -660,16 +608,16 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
        return ERR_PTR(r);
 }
 
-static struct priority_group *parse_priority_group(struct arg_set *as,
+static struct priority_group *parse_priority_group(struct dm_arg_set *as,
                                                   struct multipath *m)
 {
-       static struct param _params[] = {
+       static struct dm_arg _args[] = {
                {1, 1024, "invalid number of paths"},
                {0, 1024, "invalid number of selector args"}
        };
 
        int r;
-       unsigned i, nr_selector_args, nr_params;
+       unsigned i, nr_selector_args, nr_args;
        struct priority_group *pg;
        struct dm_target *ti = m->ti;
 
@@ -693,26 +641,26 @@ static struct priority_group *parse_priority_group(struct arg_set *as,
        /*
         * read the paths
         */
-       r = read_param(_params, shift(as), &pg->nr_pgpaths, &ti->error);
+       r = dm_read_arg(_args, as, &pg->nr_pgpaths, &ti->error);
        if (r)
                goto bad;
 
-       r = read_param(_params + 1, shift(as), &nr_selector_args, &ti->error);
+       r = dm_read_arg(_args + 1, as, &nr_selector_args, &ti->error);
        if (r)
                goto bad;
 
-       nr_params = 1 + nr_selector_args;
+       nr_args = 1 + nr_selector_args;
        for (i = 0; i < pg->nr_pgpaths; i++) {
                struct pgpath *pgpath;
-               struct arg_set path_args;
+               struct dm_arg_set path_args;
 
-               if (as->argc < nr_params) {
+               if (as->argc < nr_args) {
                        ti->error = "not enough path parameters";
                        r = -EINVAL;
                        goto bad;
                }
 
-               path_args.argc = nr_params;
+               path_args.argc = nr_args;
                path_args.argv = as->argv;
 
                pgpath = parse_path(&path_args, &pg->ps, ti);
@@ -723,7 +671,7 @@ static struct priority_group *parse_priority_group(struct arg_set *as,
 
                pgpath->pg = pg;
                list_add_tail(&pgpath->list, &pg->pgpaths);
-               consume(as, nr_params);
+               dm_consume_args(as, nr_args);
        }
 
        return pg;
@@ -733,28 +681,23 @@ static struct priority_group *parse_priority_group(struct arg_set *as,
        return ERR_PTR(r);
 }
 
-static int parse_hw_handler(struct arg_set *as, struct multipath *m)
+static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m)
 {
        unsigned hw_argc;
        int ret;
        struct dm_target *ti = m->ti;
 
-       static struct param _params[] = {
+       static struct dm_arg _args[] = {
                {0, 1024, "invalid number of hardware handler args"},
        };
 
-       if (read_param(_params, shift(as), &hw_argc, &ti->error))
+       if (dm_read_arg_group(_args, as, &hw_argc, &ti->error))
                return -EINVAL;
 
        if (!hw_argc)
                return 0;
 
-       if (hw_argc > as->argc) {
-               ti->error = "not enough arguments for hardware handler";
-               return -EINVAL;
-       }
-
-       m->hw_handler_name = kstrdup(shift(as), GFP_KERNEL);
+       m->hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL);
        request_module("scsi_dh_%s", m->hw_handler_name);
        if (scsi_dh_handler_exist(m->hw_handler_name) == 0) {
                ti->error = "unknown hardware handler type";
@@ -778,7 +721,7 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m)
                for (i = 0, p+=j+1; i <= hw_argc - 2; i++, p+=j+1)
                        j = sprintf(p, "%s", as->argv[i]);
        }
-       consume(as, hw_argc - 1);
+       dm_consume_args(as, hw_argc - 1);
 
        return 0;
 fail:
@@ -787,20 +730,20 @@ fail:
        return ret;
 }
 
-static int parse_features(struct arg_set *as, struct multipath *m)
+static int parse_features(struct dm_arg_set *as, struct multipath *m)
 {
        int r;
        unsigned argc;
        struct dm_target *ti = m->ti;
-       const char *param_name;
+       const char *arg_name;
 
-       static struct param _params[] = {
+       static struct dm_arg _args[] = {
                {0, 5, "invalid number of feature args"},
                {1, 50, "pg_init_retries must be between 1 and 50"},
                {0, 60000, "pg_init_delay_msecs must be between 0 and 60000"},
        };
 
-       r = read_param(_params, shift(as), &argc, &ti->error);
+       r = dm_read_arg_group(_args, as, &argc, &ti->error);
        if (r)
                return -EINVAL;
 
@@ -808,26 +751,24 @@ static int parse_features(struct arg_set *as, struct multipath *m)
                return 0;
 
        do {
-               param_name = shift(as);
+               arg_name = dm_shift_arg(as);
                argc--;
 
-               if (!strnicmp(param_name, MESG_STR("queue_if_no_path"))) {
+               if (!strcasecmp(arg_name, "queue_if_no_path")) {
                        r = queue_if_no_path(m, 1, 0);
                        continue;
                }
 
-               if (!strnicmp(param_name, MESG_STR("pg_init_retries")) &&
+               if (!strcasecmp(arg_name, "pg_init_retries") &&
                    (argc >= 1)) {
-                       r = read_param(_params + 1, shift(as),
-                                      &m->pg_init_retries, &ti->error);
+                       r = dm_read_arg(_args + 1, as, &m->pg_init_retries, &ti->error);
                        argc--;
                        continue;
                }
 
-               if (!strnicmp(param_name, MESG_STR("pg_init_delay_msecs")) &&
+               if (!strcasecmp(arg_name, "pg_init_delay_msecs") &&
                    (argc >= 1)) {
-                       r = read_param(_params + 2, shift(as),
-                                      &m->pg_init_delay_msecs, &ti->error);
+                       r = dm_read_arg(_args + 2, as, &m->pg_init_delay_msecs, &ti->error);
                        argc--;
                        continue;
                }
@@ -842,15 +783,15 @@ static int parse_features(struct arg_set *as, struct multipath *m)
 static int multipath_ctr(struct dm_target *ti, unsigned int argc,
                         char **argv)
 {
-       /* target parameters */
-       static struct param _params[] = {
+       /* target arguments */
+       static struct dm_arg _args[] = {
                {0, 1024, "invalid number of priority groups"},
                {0, 1024, "invalid initial priority group number"},
        };
 
        int r;
        struct multipath *m;
-       struct arg_set as;
+       struct dm_arg_set as;
        unsigned pg_count = 0;
        unsigned next_pg_num;
 
@@ -871,11 +812,11 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
        if (r)
                goto bad;
 
-       r = read_param(_params, shift(&as), &m->nr_priority_groups, &ti->error);
+       r = dm_read_arg(_args, &as, &m->nr_priority_groups, &ti->error);
        if (r)
                goto bad;
 
-       r = read_param(_params + 1, shift(&as), &next_pg_num, &ti->error);
+       r = dm_read_arg(_args + 1, &as, &next_pg_num, &ti->error);
        if (r)
                goto bad;
 
@@ -1505,10 +1446,10 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
        }
 
        if (argc == 1) {
-               if (!strnicmp(argv[0], MESG_STR("queue_if_no_path"))) {
+               if (!strcasecmp(argv[0], "queue_if_no_path")) {
                        r = queue_if_no_path(m, 1, 0);
                        goto out;
-               } else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path"))) {
+               } else if (!strcasecmp(argv[0], "fail_if_no_path")) {
                        r = queue_if_no_path(m, 0, 0);
                        goto out;
                }
@@ -1519,18 +1460,18 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
                goto out;
        }
 
-       if (!strnicmp(argv[0], MESG_STR("disable_group"))) {
+       if (!strcasecmp(argv[0], "disable_group")) {
                r = bypass_pg_num(m, argv[1], 1);
                goto out;
-       } else if (!strnicmp(argv[0], MESG_STR("enable_group"))) {
+       } else if (!strcasecmp(argv[0], "enable_group")) {
                r = bypass_pg_num(m, argv[1], 0);
                goto out;
-       } else if (!strnicmp(argv[0], MESG_STR("switch_group"))) {
+       } else if (!strcasecmp(argv[0], "switch_group")) {
                r = switch_pg_num(m, argv[1]);
                goto out;
-       } else if (!strnicmp(argv[0], MESG_STR("reinstate_path")))
+       } else if (!strcasecmp(argv[0], "reinstate_path"))
                action = reinstate_path;
-       else if (!strnicmp(argv[0], MESG_STR("fail_path")))
+       else if (!strcasecmp(argv[0], "fail_path"))
                action = fail_path;
        else {
                DMWARN("Unrecognised multipath message received.");
index e5d8904..a002dd8 100644 (file)
@@ -8,19 +8,19 @@
 #include <linux/slab.h>
 
 #include "md.h"
+#include "raid1.h"
 #include "raid5.h"
-#include "dm.h"
 #include "bitmap.h"
 
+#include <linux/device-mapper.h>
+
 #define DM_MSG_PREFIX "raid"
 
 /*
- * If the MD doesn't support MD_SYNC_STATE_FORCED yet, then
- * make it so the flag doesn't set anything.
+ * The following flags are used by dm-raid.c to set up the array state.
+ * They must be cleared before md_run is called.
  */
-#ifndef MD_SYNC_STATE_FORCED
-#define MD_SYNC_STATE_FORCED 0
-#endif
+#define FirstUse 10             /* rdev flag */
 
 struct raid_dev {
        /*
@@ -43,14 +43,15 @@ struct raid_dev {
 /*
  * Flags for rs->print_flags field.
  */
-#define DMPF_DAEMON_SLEEP      0x1
-#define DMPF_MAX_WRITE_BEHIND  0x2
-#define DMPF_SYNC              0x4
-#define DMPF_NOSYNC            0x8
-#define DMPF_STRIPE_CACHE      0x10
-#define DMPF_MIN_RECOVERY_RATE 0x20
-#define DMPF_MAX_RECOVERY_RATE 0x40
-
+#define DMPF_SYNC              0x1
+#define DMPF_NOSYNC            0x2
+#define DMPF_REBUILD           0x4
+#define DMPF_DAEMON_SLEEP      0x8
+#define DMPF_MIN_RECOVERY_RATE 0x10
+#define DMPF_MAX_RECOVERY_RATE 0x20
+#define DMPF_MAX_WRITE_BEHIND  0x40
+#define DMPF_STRIPE_CACHE      0x80
+#define DMPF_REGION_SIZE       0X100
 struct raid_set {
        struct dm_target *ti;
 
@@ -72,6 +73,7 @@ static struct raid_type {
        const unsigned level;           /* RAID level. */
        const unsigned algorithm;       /* RAID algorithm. */
 } raid_types[] = {
+       {"raid1",    "RAID1 (mirroring)",               0, 2, 1, 0 /* NONE */},
        {"raid4",    "RAID4 (dedicated parity disk)",   1, 2, 5, ALGORITHM_PARITY_0},
        {"raid5_la", "RAID5 (left asymmetric)",         1, 2, 5, ALGORITHM_LEFT_ASYMMETRIC},
        {"raid5_ra", "RAID5 (right asymmetric)",        1, 2, 5, ALGORITHM_RIGHT_ASYMMETRIC},
@@ -105,7 +107,8 @@ static struct raid_set *context_alloc(struct dm_target *ti, struct raid_type *ra
        }
 
        sectors_per_dev = ti->len;
-       if (sector_div(sectors_per_dev, (raid_devs - raid_type->parity_devs))) {
+       if ((raid_type->level > 1) &&
+           sector_div(sectors_per_dev, (raid_devs - raid_type->parity_devs))) {
                ti->error = "Target length not divisible by number of data devices";
                return ERR_PTR(-EINVAL);
        }
@@ -147,9 +150,16 @@ static void context_free(struct raid_set *rs)
 {
        int i;
 
-       for (i = 0; i < rs->md.raid_disks; i++)
+       for (i = 0; i < rs->md.raid_disks; i++) {
+               if (rs->dev[i].meta_dev)
+                       dm_put_device(rs->ti, rs->dev[i].meta_dev);
+               if (rs->dev[i].rdev.sb_page)
+                       put_page(rs->dev[i].rdev.sb_page);
+               rs->dev[i].rdev.sb_page = NULL;
+               rs->dev[i].rdev.sb_loaded = 0;
                if (rs->dev[i].data_dev)
                        dm_put_device(rs->ti, rs->dev[i].data_dev);
+       }
 
        kfree(rs);
 }
@@ -159,7 +169,16 @@ static void context_free(struct raid_set *rs)
  *  <meta_dev>: meta device name or '-' if missing
  *  <data_dev>: data device name or '-' if missing
  *
- * This code parses those words.
+ * The following are permitted:
+ *    - -
+ *    - <data_dev>
+ *    <meta_dev> <data_dev>
+ *
+ * The following is not allowed:
+ *    <meta_dev> -
+ *
+ * This code parses those words.  If there is a failure,
+ * the caller must use context_free to unwind the operations.
  */
 static int dev_parms(struct raid_set *rs, char **argv)
 {
@@ -182,8 +201,16 @@ static int dev_parms(struct raid_set *rs, char **argv)
                rs->dev[i].rdev.mddev = &rs->md;
 
                if (strcmp(argv[0], "-")) {
-                       rs->ti->error = "Metadata devices not supported";
-                       return -EINVAL;
+                       ret = dm_get_device(rs->ti, argv[0],
+                                           dm_table_get_mode(rs->ti->table),
+                                           &rs->dev[i].meta_dev);
+                       rs->ti->error = "RAID metadata device lookup failure";
+                       if (ret)
+                               return ret;
+
+                       rs->dev[i].rdev.sb_page = alloc_page(GFP_KERNEL);
+                       if (!rs->dev[i].rdev.sb_page)
+                               return -ENOMEM;
                }
 
                if (!strcmp(argv[1], "-")) {
@@ -193,6 +220,10 @@ static int dev_parms(struct raid_set *rs, char **argv)
                                return -EINVAL;
                        }
 
+                       rs->ti->error = "No data device supplied with metadata device";
+                       if (rs->dev[i].meta_dev)
+                               return -EINVAL;
+
                        continue;
                }
 
@@ -204,6 +235,10 @@ static int dev_parms(struct raid_set *rs, char **argv)
                        return ret;
                }
 
+               if (rs->dev[i].meta_dev) {
+                       metadata_available = 1;
+                       rs->dev[i].rdev.meta_bdev = rs->dev[i].meta_dev->bdev;
+               }
                rs->dev[i].rdev.bdev = rs->dev[i].data_dev->bdev;
                list_add(&rs->dev[i].rdev.same_set, &rs->md.disks);
                if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
@@ -234,34 +269,110 @@ static int dev_parms(struct raid_set *rs, char **argv)
        return 0;
 }
 
+/*
+ * validate_region_size
+ * @rs
+ * @region_size:  region size in sectors.  If 0, pick a size (4MiB default).
+ *
+ * Set rs->md.bitmap_info.chunksize (which really refers to 'region size').
+ * Ensure that (ti->len/region_size < 2^21) - required by MD bitmap.
+ *
+ * Returns: 0 on success, -EINVAL on failure.
+ */
+static int validate_region_size(struct raid_set *rs, unsigned long region_size)
+{
+       unsigned long min_region_size = rs->ti->len / (1 << 21);
+
+       if (!region_size) {
+               /*
+                * Choose a reasonable default.  All figures in sectors.
+                */
+               if (min_region_size > (1 << 13)) {
+                       DMINFO("Choosing default region size of %lu sectors",
+                              region_size);
+                       region_size = min_region_size;
+               } else {
+                       DMINFO("Choosing default region size of 4MiB");
+                       region_size = 1 << 13; /* sectors */
+               }
+       } else {
+               /*
+                * Validate user-supplied value.
+                */
+               if (region_size > rs->ti->len) {
+                       rs->ti->error = "Supplied region size is too large";
+                       return -EINVAL;
+               }
+
+               if (region_size < min_region_size) {
+                       DMERR("Supplied region_size (%lu sectors) below minimum (%lu)",
+                             region_size, min_region_size);
+                       rs->ti->error = "Supplied region size is too small";
+                       return -EINVAL;
+               }
+
+               if (!is_power_of_2(region_size)) {
+                       rs->ti->error = "Region size is not a power of 2";
+                       return -EINVAL;
+               }
+
+               if (region_size < rs->md.chunk_sectors) {
+                       rs->ti->error = "Region size is smaller than the chunk size";
+                       return -EINVAL;
+               }
+       }
+
+       /*
+        * Convert sectors to bytes.
+        */
+       rs->md.bitmap_info.chunksize = (region_size << 9);
+
+       return 0;
+}
+
 /*
  * Possible arguments are...
- * RAID456:
  *     <chunk_size> [optional_args]
  *
- * Optional args:
- *    [[no]sync]                       Force or prevent recovery of the entire array
+ * Argument definitions
+ *    <chunk_size>                     The number of sectors per disk that
+ *                                      will form the "stripe"
+ *    [[no]sync]                       Force or prevent recovery of the
+ *                                      entire array
  *    [rebuild <idx>]                  Rebuild the drive indicated by the index
- *    [daemon_sleep <ms>]              Time between bitmap daemon work to clear bits
+ *    [daemon_sleep <ms>]              Time between bitmap daemon work to
+ *                                      clear bits
  *    [min_recovery_rate <kB/sec/disk>]        Throttle RAID initialization
  *    [max_recovery_rate <kB/sec/disk>]        Throttle RAID initialization
+ *    [write_mostly <idx>]             Indicate a write mostly drive via index
  *    [max_write_behind <sectors>]     See '-write-behind=' (man mdadm)
  *    [stripe_cache <sectors>]         Stripe cache size for higher RAIDs
+ *    [region_size <sectors>]           Defines granularity of bitmap
  */
 static int parse_raid_params(struct raid_set *rs, char **argv,
                             unsigned num_raid_params)
 {
        unsigned i, rebuild_cnt = 0;
-       unsigned long value;
+       unsigned long value, region_size = 0;
        char *key;
 
        /*
         * First, parse the in-order required arguments
+        * "chunk_size" is the only argument of this type.
         */
-       if ((strict_strtoul(argv[0], 10, &value) < 0) ||
-           !is_power_of_2(value) || (value < 8)) {
+       if ((strict_strtoul(argv[0], 10, &value) < 0)) {
                rs->ti->error = "Bad chunk size";
                return -EINVAL;
+       } else if (rs->raid_type->level == 1) {
+               if (value)
+                       DMERR("Ignoring chunk size parameter for RAID 1");
+               value = 0;
+       } else if (!is_power_of_2(value)) {
+               rs->ti->error = "Chunk size must be a power of 2";
+               return -EINVAL;
+       } else if (value < 8) {
+               rs->ti->error = "Chunk size value is too small";
+               return -EINVAL;
        }
 
        rs->md.new_chunk_sectors = rs->md.chunk_sectors = value;
@@ -269,22 +380,39 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
        num_raid_params--;
 
        /*
-        * Second, parse the unordered optional arguments
+        * We set each individual device as In_sync with a completed
+        * 'recovery_offset'.  If there has been a device failure or
+        * replacement then one of the following cases applies:
+        *
+        *   1) User specifies 'rebuild'.
+        *      - Device is reset when param is read.
+        *   2) A new device is supplied.
+        *      - No matching superblock found, resets device.
+        *   3) Device failure was transient and returns on reload.
+        *      - Failure noticed, resets device for bitmap replay.
+        *   4) Device hadn't completed recovery after previous failure.
+        *      - Superblock is read and overrides recovery_offset.
+        *
+        * What is found in the superblocks of the devices is always
+        * authoritative, unless 'rebuild' or '[no]sync' was specified.
         */
-       for (i = 0; i < rs->md.raid_disks; i++)
+       for (i = 0; i < rs->md.raid_disks; i++) {
                set_bit(In_sync, &rs->dev[i].rdev.flags);
+               rs->dev[i].rdev.recovery_offset = MaxSector;
+       }
 
+       /*
+        * Second, parse the unordered optional arguments
+        */
        for (i = 0; i < num_raid_params; i++) {
-               if (!strcmp(argv[i], "nosync")) {
+               if (!strcasecmp(argv[i], "nosync")) {
                        rs->md.recovery_cp = MaxSector;
                        rs->print_flags |= DMPF_NOSYNC;
-                       rs->md.flags |= MD_SYNC_STATE_FORCED;
                        continue;
                }
-               if (!strcmp(argv[i], "sync")) {
+               if (!strcasecmp(argv[i], "sync")) {
                        rs->md.recovery_cp = 0;
                        rs->print_flags |= DMPF_SYNC;
-                       rs->md.flags |= MD_SYNC_STATE_FORCED;
                        continue;
                }
 
@@ -300,9 +428,13 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
                        return -EINVAL;
                }
 
-               if (!strcmp(key, "rebuild")) {
-                       if (++rebuild_cnt > rs->raid_type->parity_devs) {
-                               rs->ti->error = "Too many rebuild drives given";
+               if (!strcasecmp(key, "rebuild")) {
+                       rebuild_cnt++;
+                       if (((rs->raid_type->level != 1) &&
+                            (rebuild_cnt > rs->raid_type->parity_devs)) ||
+                           ((rs->raid_type->level == 1) &&
+                            (rebuild_cnt > (rs->md.raid_disks - 1)))) {
+                               rs->ti->error = "Too many rebuild devices specified for given RAID type";
                                return -EINVAL;
                        }
                        if (value > rs->md.raid_disks) {
@@ -311,7 +443,22 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
                        }
                        clear_bit(In_sync, &rs->dev[value].rdev.flags);
                        rs->dev[value].rdev.recovery_offset = 0;
-               } else if (!strcmp(key, "max_write_behind")) {
+                       rs->print_flags |= DMPF_REBUILD;
+               } else if (!strcasecmp(key, "write_mostly")) {
+                       if (rs->raid_type->level != 1) {
+                               rs->ti->error = "write_mostly option is only valid for RAID1";
+                               return -EINVAL;
+                       }
+                       if (value > rs->md.raid_disks) {
+                               rs->ti->error = "Invalid write_mostly drive index given";
+                               return -EINVAL;
+                       }
+                       set_bit(WriteMostly, &rs->dev[value].rdev.flags);
+               } else if (!strcasecmp(key, "max_write_behind")) {
+                       if (rs->raid_type->level != 1) {
+                               rs->ti->error = "max_write_behind option is only valid for RAID1";
+                               return -EINVAL;
+                       }
                        rs->print_flags |= DMPF_MAX_WRITE_BEHIND;
 
                        /*
@@ -324,14 +471,14 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
                                return -EINVAL;
                        }
                        rs->md.bitmap_info.max_write_behind = value;
-               } else if (!strcmp(key, "daemon_sleep")) {
+               } else if (!strcasecmp(key, "daemon_sleep")) {
                        rs->print_flags |= DMPF_DAEMON_SLEEP;
                        if (!value || (value > MAX_SCHEDULE_TIMEOUT)) {
                                rs->ti->error = "daemon sleep period out of range";
                                return -EINVAL;
                        }
                        rs->md.bitmap_info.daemon_sleep = value;
-               } else if (!strcmp(key, "stripe_cache")) {
+               } else if (!strcasecmp(key, "stripe_cache")) {
                        rs->print_flags |= DMPF_STRIPE_CACHE;
 
                        /*
@@ -348,20 +495,23 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
                                rs->ti->error = "Bad stripe_cache size";
                                return -EINVAL;
                        }
-               } else if (!strcmp(key, "min_recovery_rate")) {
+               } else if (!strcasecmp(key, "min_recovery_rate")) {
                        rs->print_flags |= DMPF_MIN_RECOVERY_RATE;
                        if (value > INT_MAX) {
                                rs->ti->error = "min_recovery_rate out of range";
                                return -EINVAL;
                        }
                        rs->md.sync_speed_min = (int)value;
-               } else if (!strcmp(key, "max_recovery_rate")) {
+               } else if (!strcasecmp(key, "max_recovery_rate")) {
                        rs->print_flags |= DMPF_MAX_RECOVERY_RATE;
                        if (value > INT_MAX) {
                                rs->ti->error = "max_recovery_rate out of range";
                                return -EINVAL;
                        }
                        rs->md.sync_speed_max = (int)value;
+               } else if (!strcasecmp(key, "region_size")) {
+                       rs->print_flags |= DMPF_REGION_SIZE;
+                       region_size = value;
                } else {
                        DMERR("Unable to parse RAID parameter: %s", key);
                        rs->ti->error = "Unable to parse RAID parameters";
@@ -369,6 +519,19 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
                }
        }
 
+       if (validate_region_size(rs, region_size))
+               return -EINVAL;
+
+       if (rs->md.chunk_sectors)
+               rs->ti->split_io = rs->md.chunk_sectors;
+       else
+               rs->ti->split_io = region_size;
+
+       if (rs->md.chunk_sectors)
+               rs->ti->split_io = rs->md.chunk_sectors;
+       else
+               rs->ti->split_io = region_size;
+
        /* Assume there are no metadata devices until the drives are parsed */
        rs->md.persistent = 0;
        rs->md.external = 1;
@@ -387,17 +550,351 @@ static int raid_is_congested(struct dm_target_callbacks *cb, int bits)
 {
        struct raid_set *rs = container_of(cb, struct raid_set, callbacks);
 
+       if (rs->raid_type->level == 1)
+               return md_raid1_congested(&rs->md, bits);
+
        return md_raid5_congested(&rs->md, bits);
 }
 
+/*
+ * This structure is never routinely used by userspace, unlike md superblocks.
+ * Devices with this superblock should only ever be accessed via device-mapper.
+ */
+#define DM_RAID_MAGIC 0x64526D44
+struct dm_raid_superblock {
+       __le32 magic;           /* "DmRd" */
+       __le32 features;        /* Used to indicate possible future changes */
+
+       __le32 num_devices;     /* Number of devices in this array. (Max 64) */
+       __le32 array_position;  /* The position of this drive in the array */
+
+       __le64 events;          /* Incremented by md when superblock updated */
+       __le64 failed_devices;  /* Bit field of devices to indicate failures */
+
+       /*
+        * This offset tracks the progress of the repair or replacement of
+        * an individual drive.
+        */
+       __le64 disk_recovery_offset;
+
+       /*
+        * This offset tracks the progress of the initial array
+        * synchronisation/parity calculation.
+        */
+       __le64 array_resync_offset;
+
+       /*
+        * RAID characteristics
+        */
+       __le32 level;
+       __le32 layout;
+       __le32 stripe_sectors;
+
+       __u8 pad[452];          /* Round struct to 512 bytes. */
+                               /* Always set to 0 when writing. */
+} __packed;
+
+static int read_disk_sb(mdk_rdev_t *rdev, int size)
+{
+       BUG_ON(!rdev->sb_page);
+
+       if (rdev->sb_loaded)
+               return 0;
+
+       if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, 1)) {
+               DMERR("Failed to read device superblock");
+               return -EINVAL;
+       }
+
+       rdev->sb_loaded = 1;
+
+       return 0;
+}
+
+static void super_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+       mdk_rdev_t *r, *t;
+       uint64_t failed_devices;
+       struct dm_raid_superblock *sb;
+
+       sb = page_address(rdev->sb_page);
+       failed_devices = le64_to_cpu(sb->failed_devices);
+
+       rdev_for_each(r, t, mddev)
+               if ((r->raid_disk >= 0) && test_bit(Faulty, &r->flags))
+                       failed_devices |= (1ULL << r->raid_disk);
+
+       memset(sb, 0, sizeof(*sb));
+
+       sb->magic = cpu_to_le32(DM_RAID_MAGIC);
+       sb->features = cpu_to_le32(0);  /* No features yet */
+
+       sb->num_devices = cpu_to_le32(mddev->raid_disks);
+       sb->array_position = cpu_to_le32(rdev->raid_disk);
+
+       sb->events = cpu_to_le64(mddev->events);
+       sb->failed_devices = cpu_to_le64(failed_devices);
+
+       sb->disk_recovery_offset = cpu_to_le64(rdev->recovery_offset);
+       sb->array_resync_offset = cpu_to_le64(mddev->recovery_cp);
+
+       sb->level = cpu_to_le32(mddev->level);
+       sb->layout = cpu_to_le32(mddev->layout);
+       sb->stripe_sectors = cpu_to_le32(mddev->chunk_sectors);
+}
+
+/*
+ * super_load
+ *
+ * This function creates a superblock if one is not found on the device
+ * and will decide which superblock to use if there's a choice.
+ *
+ * Return: 1 if use rdev, 0 if use refdev, -Exxx otherwise
+ */
+static int super_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev)
+{
+       int ret;
+       struct dm_raid_superblock *sb;
+       struct dm_raid_superblock *refsb;
+       uint64_t events_sb, events_refsb;
+
+       rdev->sb_start = 0;
+       rdev->sb_size = sizeof(*sb);
+
+       ret = read_disk_sb(rdev, rdev->sb_size);
+       if (ret)
+               return ret;
+
+       sb = page_address(rdev->sb_page);
+       if (sb->magic != cpu_to_le32(DM_RAID_MAGIC)) {
+               super_sync(rdev->mddev, rdev);
+
+               set_bit(FirstUse, &rdev->flags);
+
+               /* Force writing of superblocks to disk */
+               set_bit(MD_CHANGE_DEVS, &rdev->mddev->flags);
+
+               /* Any superblock is better than none, choose that if given */
+               return refdev ? 0 : 1;
+       }
+
+       if (!refdev)
+               return 1;
+
+       events_sb = le64_to_cpu(sb->events);
+
+       refsb = page_address(refdev->sb_page);
+       events_refsb = le64_to_cpu(refsb->events);
+
+       return (events_sb > events_refsb) ? 1 : 0;
+}
+
+static int super_init_validation(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+       int role;
+       struct raid_set *rs = container_of(mddev, struct raid_set, md);
+       uint64_t events_sb;
+       uint64_t failed_devices;
+       struct dm_raid_superblock *sb;
+       uint32_t new_devs = 0;
+       uint32_t rebuilds = 0;
+       mdk_rdev_t *r, *t;
+       struct dm_raid_superblock *sb2;
+
+       sb = page_address(rdev->sb_page);
+       events_sb = le64_to_cpu(sb->events);
+       failed_devices = le64_to_cpu(sb->failed_devices);
+
+       /*
+        * Initialise to 1 if this is a new superblock.
+        */
+       mddev->events = events_sb ? : 1;
+
+       /*
+        * Reshaping is not currently allowed
+        */
+       if ((le32_to_cpu(sb->level) != mddev->level) ||
+           (le32_to_cpu(sb->layout) != mddev->layout) ||
+           (le32_to_cpu(sb->stripe_sectors) != mddev->chunk_sectors)) {
+               DMERR("Reshaping arrays not yet supported.");
+               return -EINVAL;
+       }
+
+       /* We can only change the number of devices in RAID1 right now */
+       if ((rs->raid_type->level != 1) &&
+           (le32_to_cpu(sb->num_devices) != mddev->raid_disks)) {
+               DMERR("Reshaping arrays not yet supported.");
+               return -EINVAL;
+       }
+
+       if (!(rs->print_flags & (DMPF_SYNC | DMPF_NOSYNC)))
+               mddev->recovery_cp = le64_to_cpu(sb->array_resync_offset);
+
+       /*
+        * During load, we set FirstUse if a new superblock was written.
+        * There are two reasons we might not have a superblock:
+        * 1) The array is brand new - in which case, all of the
+        *    devices must have their In_sync bit set.  Also,
+        *    recovery_cp must be 0, unless forced.
+        * 2) This is a new device being added to an old array
+        *    and the new device needs to be rebuilt - in which
+        *    case the In_sync bit will /not/ be set and
+        *    recovery_cp must be MaxSector.
+        */
+       rdev_for_each(r, t, mddev) {
+               if (!test_bit(In_sync, &r->flags)) {
+                       if (!test_bit(FirstUse, &r->flags))
+                               DMERR("Superblock area of "
+                                     "rebuild device %d should have been "
+                                     "cleared.", r->raid_disk);
+                       set_bit(FirstUse, &r->flags);
+                       rebuilds++;
+               } else if (test_bit(FirstUse, &r->flags))
+                       new_devs++;
+       }
+
+       if (!rebuilds) {
+               if (new_devs == mddev->raid_disks) {
+                       DMINFO("Superblocks created for new array");
+                       set_bit(MD_ARRAY_FIRST_USE, &mddev->flags);
+               } else if (new_devs) {
+                       DMERR("New device injected "
+                             "into existing array without 'rebuild' "
+                             "parameter specified");
+                       return -EINVAL;
+               }
+       } else if (new_devs) {
+               DMERR("'rebuild' devices cannot be "
+                     "injected into an array with other first-time devices");
+               return -EINVAL;
+       } else if (mddev->recovery_cp != MaxSector) {
+               DMERR("'rebuild' specified while array is not in-sync");
+               return -EINVAL;
+       }
+
+       /*
+        * Now we set the Faulty bit for those devices that are
+        * recorded in the superblock as failed.
+        */
+       rdev_for_each(r, t, mddev) {
+               if (!r->sb_page)
+                       continue;
+               sb2 = page_address(r->sb_page);
+               sb2->failed_devices = 0;
+
+               /*
+                * Check for any device re-ordering.
+                */
+               if (!test_bit(FirstUse, &r->flags) && (r->raid_disk >= 0)) {
+                       role = le32_to_cpu(sb2->array_position);
+                       if (role != r->raid_disk) {
+                               if (rs->raid_type->level != 1) {
+                                       rs->ti->error = "Cannot change device "
+                                               "positions in RAID array";
+                                       return -EINVAL;
+                               }
+                               DMINFO("RAID1 device #%d now at position #%d",
+                                      role, r->raid_disk);
+                       }
+
+                       /*
+                        * Partial recovery is performed on
+                        * returning failed devices.
+                        */
+                       if (failed_devices & (1 << role))
+                               set_bit(Faulty, &r->flags);
+               }
+       }
+
+       return 0;
+}
+
+static int super_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+       struct dm_raid_superblock *sb = page_address(rdev->sb_page);
+
+       /*
+        * If mddev->events is not set, we know we have not yet initialized
+        * the array.
+        */
+       if (!mddev->events && super_init_validation(mddev, rdev))
+               return -EINVAL;
+
+       mddev->bitmap_info.offset = 4096 >> 9; /* Enable bitmap creation */
+       rdev->mddev->bitmap_info.default_offset = 4096 >> 9;
+       if (!test_bit(FirstUse, &rdev->flags)) {
+               rdev->recovery_offset = le64_to_cpu(sb->disk_recovery_offset);
+               if (rdev->recovery_offset != MaxSector)
+                       clear_bit(In_sync, &rdev->flags);
+       }
+
+       /*
+        * If a device comes back, set it as not In_sync and no longer faulty.
+        */
+       if (test_bit(Faulty, &rdev->flags)) {
+               clear_bit(Faulty, &rdev->flags);
+               clear_bit(In_sync, &rdev->flags);
+               rdev->saved_raid_disk = rdev->raid_disk;
+               rdev->recovery_offset = 0;
+       }
+
+       clear_bit(FirstUse, &rdev->flags);
+
+       return 0;
+}
+
+/*
+ * Analyse superblocks and select the freshest.
+ */
+static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
+{
+       int ret;
+       mdk_rdev_t *rdev, *freshest, *tmp;
+       mddev_t *mddev = &rs->md;
+
+       freshest = NULL;
+       rdev_for_each(rdev, tmp, mddev) {
+               if (!rdev->meta_bdev)
+                       continue;
+
+               ret = super_load(rdev, freshest);
+
+               switch (ret) {
+               case 1:
+                       freshest = rdev;
+                       break;
+               case 0:
+                       break;
+               default:
+                       ti->error = "Failed to load superblock";
+                       return ret;
+               }
+       }
+
+       if (!freshest)
+               return 0;
+
+       /*
+        * Validation of the freshest device provides the source of
+        * validation for the remaining devices.
+        */
+       ti->error = "Unable to assemble array: Invalid superblocks";
+       if (super_validate(mddev, freshest))
+               return -EINVAL;
+
+       rdev_for_each(rdev, tmp, mddev)
+               if ((rdev != freshest) && super_validate(mddev, rdev))
+                       return -EINVAL;
+
+       return 0;
+}
+
 /*
  * Construct a RAID4/5/6 mapping:
  * Args:
  *     <raid_type> <#raid_params> <raid_params>                \
  *     <#raid_devs> { <meta_dev1> <dev1> .. <meta_devN> <devN> }
  *
- * ** metadata devices are not supported yet, use '-' instead **
- *
  * <raid_params> varies by <raid_type>.  See 'parse_raid_params' for
  * details on possible <raid_params>.
  */
@@ -465,8 +962,12 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
        if (ret)
                goto bad;
 
+       rs->md.sync_super = super_sync;
+       ret = analyse_superblocks(ti, rs);
+       if (ret)
+               goto bad;
+
        INIT_WORK(&rs->md.event_work, do_table_event);
-       ti->split_io = rs->md.chunk_sectors;
        ti->private = rs;
 
        mutex_lock(&rs->md.reconfig_mutex);
@@ -482,6 +983,7 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
        rs->callbacks.congested_fn = raid_is_congested;
        dm_table_add_target_callbacks(ti->table, &rs->callbacks);
 
+       mddev_suspend(&rs->md);
        return 0;
 
 bad:
@@ -546,12 +1048,17 @@ static int raid_status(struct dm_target *ti, status_type_t type,
                break;
        case STATUSTYPE_TABLE:
                /* The string you would use to construct this array */
-               for (i = 0; i < rs->md.raid_disks; i++)
-                       if (rs->dev[i].data_dev &&
+               for (i = 0; i < rs->md.raid_disks; i++) {
+                       if ((rs->print_flags & DMPF_REBUILD) &&
+                           rs->dev[i].data_dev &&
                            !test_bit(In_sync, &rs->dev[i].rdev.flags))
-                               raid_param_cnt++; /* for rebuilds */
+                               raid_param_cnt += 2; /* for rebuilds */
+                       if (rs->dev[i].data_dev &&
+                           test_bit(WriteMostly, &rs->dev[i].rdev.flags))
+                               raid_param_cnt += 2;
+               }
 
-               raid_param_cnt += (hweight64(rs->print_flags) * 2);
+               raid_param_cnt += (hweight64(rs->print_flags & ~DMPF_REBUILD) * 2);
                if (rs->print_flags & (DMPF_SYNC | DMPF_NOSYNC))
                        raid_param_cnt--;
 
@@ -565,7 +1072,8 @@ static int raid_status(struct dm_target *ti, status_type_t type,
                        DMEMIT(" nosync");
 
                for (i = 0; i < rs->md.raid_disks; i++)
-                       if (rs->dev[i].data_dev &&
+                       if ((rs->print_flags & DMPF_REBUILD) &&
+                           rs->dev[i].data_dev &&
                            !test_bit(In_sync, &rs->dev[i].rdev.flags))
                                DMEMIT(" rebuild %u", i);
 
@@ -579,6 +1087,11 @@ static int raid_status(struct dm_target *ti, status_type_t type,
                if (rs->print_flags & DMPF_MAX_RECOVERY_RATE)
                        DMEMIT(" max_recovery_rate %d", rs->md.sync_speed_max);
 
+               for (i = 0; i < rs->md.raid_disks; i++)
+                       if (rs->dev[i].data_dev &&
+                           test_bit(WriteMostly, &rs->dev[i].rdev.flags))
+                               DMEMIT(" write_mostly %u", i);
+
                if (rs->print_flags & DMPF_MAX_WRITE_BEHIND)
                        DMEMIT(" max_write_behind %lu",
                               rs->md.bitmap_info.max_write_behind);
@@ -591,9 +1104,16 @@ static int raid_status(struct dm_target *ti, status_type_t type,
                               conf ? conf->max_nr_stripes * 2 : 0);
                }
 
+               if (rs->print_flags & DMPF_REGION_SIZE)
+                       DMEMIT(" region_size %lu",
+                              rs->md.bitmap_info.chunksize >> 9);
+
                DMEMIT(" %d", rs->md.raid_disks);
                for (i = 0; i < rs->md.raid_disks; i++) {
-                       DMEMIT(" -"); /* metadata device */
+                       if (rs->dev[i].meta_dev)
+                               DMEMIT(" %s", rs->dev[i].meta_dev->name);
+                       else
+                               DMEMIT(" -");
 
                        if (rs->dev[i].data_dev)
                                DMEMIT(" %s", rs->dev[i].data_dev->name);
@@ -650,12 +1170,13 @@ static void raid_resume(struct dm_target *ti)
 {
        struct raid_set *rs = ti->private;
 
+       bitmap_load(&rs->md);
        mddev_resume(&rs->md);
 }
 
 static struct target_type raid_target = {
        .name = "raid",
-       .version = {1, 0, 0},
+       .version = {1, 1, 0},
        .module = THIS_MODULE,
        .ctr = raid_ctr,
        .dtr = raid_dtr,
index 135c2f1..d1f1d70 100644 (file)
 #define NUM_SNAPSHOT_HDR_CHUNKS 1
 
 struct disk_header {
-       uint32_t magic;
+       __le32 magic;
 
        /*
         * Is this snapshot valid.  There is no way of recovering
         * an invalid snapshot.
         */
-       uint32_t valid;
+       __le32 valid;
 
        /*
         * Simple, incrementing version. no backward
         * compatibility.
         */
-       uint32_t version;
+       __le32 version;
 
        /* In sectors */
-       uint32_t chunk_size;
-};
+       __le32 chunk_size;
+} __packed;
 
 struct disk_exception {
+       __le64 old_chunk;
+       __le64 new_chunk;
+} __packed;
+
+struct core_exception {
        uint64_t old_chunk;
        uint64_t new_chunk;
 };
@@ -169,10 +174,9 @@ static int alloc_area(struct pstore *ps)
        if (!ps->area)
                goto err_area;
 
-       ps->zero_area = vmalloc(len);
+       ps->zero_area = vzalloc(len);
        if (!ps->zero_area)
                goto err_zero_area;
-       memset(ps->zero_area, 0, len);
 
        ps->header_area = vmalloc(len);
        if (!ps->header_area)
@@ -396,32 +400,32 @@ static struct disk_exception *get_exception(struct pstore *ps, uint32_t index)
 }
 
 static void read_exception(struct pstore *ps,
-                          uint32_t index, struct disk_exception *result)
+                          uint32_t index, struct core_exception *result)
 {
-       struct disk_exception *e = get_exception(ps, index);
+       struct disk_exception *de = get_exception(ps, index);
 
        /* copy it */
-       result->old_chunk = le64_to_cpu(e->old_chunk);
-       result->new_chunk = le64_to_cpu(e->new_chunk);
+       result->old_chunk = le64_to_cpu(de->old_chunk);
+       result->new_chunk = le64_to_cpu(de->new_chunk);
 }
 
 static void write_exception(struct pstore *ps,
-                           uint32_t index, struct disk_exception *de)
+                           uint32_t index, struct core_exception *e)
 {
-       struct disk_exception *e = get_exception(ps, index);
+       struct disk_exception *de = get_exception(ps, index);
 
        /* copy it */
-       e->old_chunk = cpu_to_le64(de->old_chunk);
-       e->new_chunk = cpu_to_le64(de->new_chunk);
+       de->old_chunk = cpu_to_le64(e->old_chunk);
+       de->new_chunk = cpu_to_le64(e->new_chunk);
 }
 
 static void clear_exception(struct pstore *ps, uint32_t index)
 {
-       struct disk_exception *e = get_exception(ps, index);
+       struct disk_exception *de = get_exception(ps, index);
 
        /* clear it */
-       e->old_chunk = 0;
-       e->new_chunk = 0;
+       de->old_chunk = 0;
+       de->new_chunk = 0;
 }
 
 /*
@@ -437,13 +441,13 @@ static int insert_exceptions(struct pstore *ps,
 {
        int r;
        unsigned int i;
-       struct disk_exception de;
+       struct core_exception e;
 
        /* presume the area is full */
        *full = 1;
 
        for (i = 0; i < ps->exceptions_per_area; i++) {
-               read_exception(ps, i, &de);
+               read_exception(ps, i, &e);
 
                /*
                 * If the new_chunk is pointing at the start of
@@ -451,7 +455,7 @@ static int insert_exceptions(struct pstore *ps,
                 * is we know that we've hit the end of the
                 * exceptions.  Therefore the area is not full.
                 */
-               if (de.new_chunk == 0LL) {
+               if (e.new_chunk == 0LL) {
                        ps->current_committed = i;
                        *full = 0;
                        break;
@@ -460,13 +464,13 @@ static int insert_exceptions(struct pstore *ps,
                /*
                 * Keep track of the start of the free chunks.
                 */
-               if (ps->next_free <= de.new_chunk)
-                       ps->next_free = de.new_chunk + 1;
+               if (ps->next_free <= e.new_chunk)
+                       ps->next_free = e.new_chunk + 1;
 
                /*
                 * Otherwise we add the exception to the snapshot.
                 */
-               r = callback(callback_context, de.old_chunk, de.new_chunk);
+               r = callback(callback_context, e.old_chunk, e.new_chunk);
                if (r)
                        return r;
        }
@@ -563,7 +567,7 @@ static int persistent_read_metadata(struct dm_exception_store *store,
        ps->exceptions_per_area = (ps->store->chunk_size << SECTOR_SHIFT) /
                                  sizeof(struct disk_exception);
        ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
-                       sizeof(*ps->callbacks));
+                                  sizeof(*ps->callbacks));
        if (!ps->callbacks)
                return -ENOMEM;
 
@@ -641,12 +645,12 @@ static void persistent_commit_exception(struct dm_exception_store *store,
 {
        unsigned int i;
        struct pstore *ps = get_info(store);
-       struct disk_exception de;
+       struct core_exception ce;
        struct commit_callback *cb;
 
-       de.old_chunk = e->old_chunk;
-       de.new_chunk = e->new_chunk;
-       write_exception(ps, ps->current_committed++, &de);
+       ce.old_chunk = e->old_chunk;
+       ce.new_chunk = e->new_chunk;
+       write_exception(ps, ps->current_committed++, &ce);
 
        /*
         * Add the callback to the back of the array.  This code
@@ -670,7 +674,7 @@ static void persistent_commit_exception(struct dm_exception_store *store,
         * If we completely filled the current area, then wipe the next one.
         */
        if ((ps->current_committed == ps->exceptions_per_area) &&
-            zero_disk_area(ps, ps->current_area + 1))
+           zero_disk_area(ps, ps->current_area + 1))
                ps->valid = 0;
 
        /*
@@ -701,7 +705,7 @@ static int persistent_prepare_merge(struct dm_exception_store *store,
                                    chunk_t *last_new_chunk)
 {
        struct pstore *ps = get_info(store);
-       struct disk_exception de;
+       struct core_exception ce;
        int nr_consecutive;
        int r;
 
@@ -722,9 +726,9 @@ static int persistent_prepare_merge(struct dm_exception_store *store,
                ps->current_committed = ps->exceptions_per_area;
        }
 
-       read_exception(ps, ps->current_committed - 1, &de);
-       *last_old_chunk = de.old_chunk;
-       *last_new_chunk = de.new_chunk;
+       read_exception(ps, ps->current_committed - 1, &ce);
+       *last_old_chunk = ce.old_chunk;
+       *last_new_chunk = ce.new_chunk;
 
        /*
         * Find number of consecutive chunks within the current area,
@@ -733,9 +737,9 @@ static int persistent_prepare_merge(struct dm_exception_store *store,
        for (nr_consecutive = 1; nr_consecutive < ps->current_committed;
             nr_consecutive++) {
                read_exception(ps, ps->current_committed - 1 - nr_consecutive,
-                              &de);
-               if (de.old_chunk != *last_old_chunk - nr_consecutive ||
-                   de.new_chunk != *last_new_chunk - nr_consecutive)
+                              &ce);
+               if (ce.old_chunk != *last_old_chunk - nr_consecutive ||
+                   ce.new_chunk != *last_new_chunk - nr_consecutive)
                        break;
        }
 
@@ -753,7 +757,7 @@ static int persistent_commit_merge(struct dm_exception_store *store,
        for (i = 0; i < nr_merged; i++)
                clear_exception(ps, ps->current_committed - 1 - i);
 
-       r = area_io(ps, WRITE);
+       r = area_io(ps, WRITE_FLUSH_FUA);
        if (r < 0)
                return r;
 
index 9ecff5f..6f75887 100644 (file)
@@ -29,16 +29,6 @@ static const char dm_snapshot_merge_target_name[] = "snapshot-merge";
 #define dm_target_is_snapshot_merge(ti) \
        ((ti)->type->name == dm_snapshot_merge_target_name)
 
-/*
- * The percentage increment we will wake up users at
- */
-#define WAKE_UP_PERCENT 5
-
-/*
- * kcopyd priority of snapshot operations
- */
-#define SNAPSHOT_COPY_PRIORITY 2
-
 /*
  * The size of the mempool used to track chunks in use.
  */
@@ -180,6 +170,13 @@ struct dm_snap_pending_exception {
         * kcopyd.
         */
        int started;
+
+       /*
+        * For writing a complete chunk, bypassing the copy.
+        */
+       struct bio *full_bio;
+       bio_end_io_t *full_bio_end_io;
+       void *full_bio_private;
 };
 
 /*
@@ -1055,8 +1052,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        s = kmalloc(sizeof(*s), GFP_KERNEL);
        if (!s) {
-               ti->error = "Cannot allocate snapshot context private "
-                   "structure";
+               ti->error = "Cannot allocate private snapshot structure";
                r = -ENOMEM;
                goto bad;
        }
@@ -1380,6 +1376,7 @@ static void pending_complete(struct dm_snap_pending_exception *pe, int success)
        struct dm_snapshot *s = pe->snap;
        struct bio *origin_bios = NULL;
        struct bio *snapshot_bios = NULL;
+       struct bio *full_bio = NULL;
        int error = 0;
 
        if (!success) {
@@ -1415,10 +1412,15 @@ static void pending_complete(struct dm_snap_pending_exception *pe, int success)
         */
        dm_insert_exception(&s->complete, e);
 
- out:
+out:
        dm_remove_exception(&pe->e);
        snapshot_bios = bio_list_get(&pe->snapshot_bios);
        origin_bios = bio_list_get(&pe->origin_bios);
+       full_bio = pe->full_bio;
+       if (full_bio) {
+               full_bio->bi_end_io = pe->full_bio_end_io;
+               full_bio->bi_private = pe->full_bio_private;
+       }
        free_pending_exception(pe);
 
        increment_pending_exceptions_done_count();
@@ -1426,10 +1428,15 @@ static void pending_complete(struct dm_snap_pending_exception *pe, int success)
        up_write(&s->lock);
 
        /* Submit any pending write bios */
-       if (error)
+       if (error) {
+               if (full_bio)
+                       bio_io_error(full_bio);
                error_bios(snapshot_bios);
-       else
+       } else {
+               if (full_bio)
+                       bio_endio(full_bio, 0);
                flush_bios(snapshot_bios);
+       }
 
        retry_origin_bios(s, origin_bios);
 }
@@ -1480,8 +1487,33 @@ static void start_copy(struct dm_snap_pending_exception *pe)
        dest.count = src.count;
 
        /* Hand over to kcopyd */
-       dm_kcopyd_copy(s->kcopyd_client,
-                   &src, 1, &dest, 0, copy_callback, pe);
+       dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, copy_callback, pe);
+}
+
+static void full_bio_end_io(struct bio *bio, int error)
+{
+       void *callback_data = bio->bi_private;
+
+       dm_kcopyd_do_callback(callback_data, 0, error ? 1 : 0);
+}
+
+static void start_full_bio(struct dm_snap_pending_exception *pe,
+                          struct bio *bio)
+{
+       struct dm_snapshot *s = pe->snap;
+       void *callback_data;
+
+       pe->full_bio = bio;
+       pe->full_bio_end_io = bio->bi_end_io;
+       pe->full_bio_private = bio->bi_private;
+
+       callback_data = dm_kcopyd_prepare_callback(s->kcopyd_client,
+                                                  copy_callback, pe);
+
+       bio->bi_end_io = full_bio_end_io;
+       bio->bi_private = callback_data;
+
+       generic_make_request(bio);
 }
 
 static struct dm_snap_pending_exception *
@@ -1519,6 +1551,7 @@ __find_pending_exception(struct dm_snapshot *s,
        bio_list_init(&pe->origin_bios);
        bio_list_init(&pe->snapshot_bios);
        pe->started = 0;
+       pe->full_bio = NULL;
 
        if (s->store->type->prepare_exception(s->store, &pe->e)) {
                free_pending_exception(pe);
@@ -1612,10 +1645,19 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
                }
 
                remap_exception(s, &pe->e, bio, chunk);
-               bio_list_add(&pe->snapshot_bios, bio);
 
                r = DM_MAPIO_SUBMITTED;
 
+               if (!pe->started &&
+                   bio->bi_size == (s->store->chunk_size << SECTOR_SHIFT)) {
+                       pe->started = 1;
+                       up_write(&s->lock);
+                       start_full_bio(pe, bio);
+                       goto out;
+               }
+
+               bio_list_add(&pe->snapshot_bios, bio);
+
                if (!pe->started) {
                        /* this is protected by snap->lock */
                        pe->started = 1;
@@ -1628,9 +1670,9 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
                map_context->ptr = track_chunk(s, chunk);
        }
 
- out_unlock:
+out_unlock:
        up_write(&s->lock);
- out:
+out:
        return r;
 }
 
@@ -1974,7 +2016,7 @@ static int __origin_write(struct list_head *snapshots, sector_t sector,
                        pe_to_start_now = pe;
                }
 
- next_snapshot:
+next_snapshot:
                up_write(&snap->lock);
 
                if (pe_to_start_now) {
index bfe9c23..986b875 100644 (file)
@@ -54,7 +54,6 @@ struct dm_table {
        sector_t *highs;
        struct dm_target *targets;
 
-       unsigned discards_supported:1;
        unsigned integrity_supported:1;
 
        /*
@@ -154,12 +153,11 @@ void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size)
                return NULL;
 
        size = nmemb * elem_size;
-       addr = vmalloc(size);
-       if (addr)
-               memset(addr, 0, size);
+       addr = vzalloc(size);
 
        return addr;
 }
+EXPORT_SYMBOL(dm_vcalloc);
 
 /*
  * highs, and targets are managed as dynamic arrays during a
@@ -209,7 +207,6 @@ int dm_table_create(struct dm_table **result, fmode_t mode,
        INIT_LIST_HEAD(&t->devices);
        INIT_LIST_HEAD(&t->target_callbacks);
        atomic_set(&t->holders, 0);
-       t->discards_supported = 1;
 
        if (!num_targets)
                num_targets = KEYS_PER_NODE;
@@ -281,6 +278,7 @@ void dm_table_get(struct dm_table *t)
 {
        atomic_inc(&t->holders);
 }
+EXPORT_SYMBOL(dm_table_get);
 
 void dm_table_put(struct dm_table *t)
 {
@@ -290,6 +288,7 @@ void dm_table_put(struct dm_table *t)
        smp_mb__before_atomic_dec();
        atomic_dec(&t->holders);
 }
+EXPORT_SYMBOL(dm_table_put);
 
 /*
  * Checks to see if we need to extend highs or targets.
@@ -455,13 +454,14 @@ static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode,
  * Add a device to the list, or just increment the usage count if
  * it's already present.
  */
-static int __table_get_device(struct dm_table *t, struct dm_target *ti,
-                     const char *path, fmode_t mode, struct dm_dev **result)
+int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
+                 struct dm_dev **result)
 {
        int r;
        dev_t uninitialized_var(dev);
        struct dm_dev_internal *dd;
        unsigned int major, minor;
+       struct dm_table *t = ti->table;
 
        BUG_ON(!t);
 
@@ -509,6 +509,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
        *result = &dd->dm_dev;
        return 0;
 }
+EXPORT_SYMBOL(dm_get_device);
 
 int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
                         sector_t start, sector_t len, void *data)
@@ -539,23 +540,15 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
         * If not we'll force DM to use PAGE_SIZE or
         * smaller I/O, just to be safe.
         */
-
-       if (q->merge_bvec_fn && !ti->type->merge)
+       if (dm_queue_merge_is_compulsory(q) && !ti->type->merge)
                blk_limits_max_hw_sectors(limits,
                                          (unsigned int) (PAGE_SIZE >> 9));
        return 0;
 }
 EXPORT_SYMBOL_GPL(dm_set_device_limits);
 
-int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
-                 struct dm_dev **result)
-{
-       return __table_get_device(ti->table, ti, path, mode, result);
-}
-
-
 /*
- * Decrement a devices use count and remove it if necessary.
+ * Decrement a device's use count and remove it if necessary.
  */
 void dm_put_device(struct dm_target *ti, struct dm_dev *d)
 {
@@ -568,6 +561,7 @@ void dm_put_device(struct dm_target *ti, struct dm_dev *d)
                kfree(dd);
        }
 }
+EXPORT_SYMBOL(dm_put_device);
 
 /*
  * Checks to see if the target joins onto the end of the table.
@@ -791,8 +785,9 @@ int dm_table_add_target(struct dm_table *t, const char *type,
 
        t->highs[t->num_targets++] = tgt->begin + tgt->len - 1;
 
-       if (!tgt->num_discard_requests)
-               t->discards_supported = 0;
+       if (!tgt->num_discard_requests && tgt->discards_supported)
+               DMWARN("%s: %s: ignoring discards_supported because num_discard_requests is zero.",
+                      dm_device_name(t->md), type);
 
        return 0;
 
@@ -802,6 +797,63 @@ int dm_table_add_target(struct dm_table *t, const char *type,
        return r;
 }
 
+/*
+ * Target argument parsing helpers.
+ */
+static int validate_next_arg(struct dm_arg *arg, struct dm_arg_set *arg_set,
+                            unsigned *value, char **error, unsigned grouped)
+{
+       const char *arg_str = dm_shift_arg(arg_set);
+
+       if (!arg_str ||
+           (sscanf(arg_str, "%u", value) != 1) ||
+           (*value < arg->min) ||
+           (*value > arg->max) ||
+           (grouped && arg_set->argc < *value)) {
+               *error = arg->error;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int dm_read_arg(struct dm_arg *arg, struct dm_arg_set *arg_set,
+               unsigned *value, char **error)
+{
+       return validate_next_arg(arg, arg_set, value, error, 0);
+}
+EXPORT_SYMBOL(dm_read_arg);
+
+int dm_read_arg_group(struct dm_arg *arg, struct dm_arg_set *arg_set,
+                     unsigned *value, char **error)
+{
+       return validate_next_arg(arg, arg_set, value, error, 1);
+}
+EXPORT_SYMBOL(dm_read_arg_group);
+
+const char *dm_shift_arg(struct dm_arg_set *as)
+{
+       char *r;
+
+       if (as->argc) {
+               as->argc--;
+               r = *as->argv;
+               as->argv++;
+               return r;
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL(dm_shift_arg);
+
+void dm_consume_args(struct dm_arg_set *as, unsigned num_args)
+{
+       BUG_ON(as->argc < num_args);
+       as->argc -= num_args;
+       as->argv += num_args;
+}
+EXPORT_SYMBOL(dm_consume_args);
+
 static int dm_table_set_type(struct dm_table *t)
 {
        unsigned i;
@@ -1077,11 +1129,13 @@ void dm_table_event(struct dm_table *t)
                t->event_fn(t->event_context);
        mutex_unlock(&_event_lock);
 }
+EXPORT_SYMBOL(dm_table_event);
 
 sector_t dm_table_get_size(struct dm_table *t)
 {
        return t->num_targets ? (t->highs[t->num_targets - 1] + 1) : 0;
 }
+EXPORT_SYMBOL(dm_table_get_size);
 
 struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index)
 {
@@ -1194,9 +1248,45 @@ static void dm_table_set_integrity(struct dm_table *t)
                               blk_get_integrity(template_disk));
 }
 
+static int device_flush_capable(struct dm_target *ti, struct dm_dev *dev,
+                               sector_t start, sector_t len, void *data)
+{
+       unsigned flush = (*(unsigned *)data);
+       struct request_queue *q = bdev_get_queue(dev->bdev);
+
+       return q && (q->flush_flags & flush);
+}
+
+static bool dm_table_supports_flush(struct dm_table *t, unsigned flush)
+{
+       struct dm_target *ti;
+       unsigned i = 0;
+
+       /*
+        * Require at least one underlying device to support flushes.
+        * t->devices includes internal dm devices such as mirror logs
+        * so we need to use iterate_devices here, which targets
+        * supporting flushes must provide.
+        */
+       while (i < dm_table_get_num_targets(t)) {
+               ti = dm_table_get_target(t, i++);
+
+               if (!ti->num_flush_requests)
+                       continue;
+
+               if (ti->type->iterate_devices &&
+                   ti->type->iterate_devices(ti, device_flush_capable, &flush))
+                       return 1;
+       }
+
+       return 0;
+}
+
 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
                               struct queue_limits *limits)
 {
+       unsigned flush = 0;
+
        /*
         * Copy table's limits to the DM device's request_queue
         */
@@ -1207,6 +1297,13 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
        else
                queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
 
+       if (dm_table_supports_flush(t, REQ_FLUSH)) {
+               flush |= REQ_FLUSH;
+               if (dm_table_supports_flush(t, REQ_FUA))
+                       flush |= REQ_FUA;
+       }
+       blk_queue_flush(q, flush);
+
        dm_table_set_integrity(t);
 
        /*
@@ -1237,6 +1334,7 @@ fmode_t dm_table_get_mode(struct dm_table *t)
 {
        return t->mode;
 }
+EXPORT_SYMBOL(dm_table_get_mode);
 
 static void suspend_targets(struct dm_table *t, unsigned postsuspend)
 {
@@ -1345,6 +1443,7 @@ struct mapped_device *dm_table_get_md(struct dm_table *t)
 {
        return t->md;
 }
+EXPORT_SYMBOL(dm_table_get_md);
 
 static int device_discard_capable(struct dm_target *ti, struct dm_dev *dev,
                                  sector_t start, sector_t len, void *data)
@@ -1359,19 +1458,19 @@ bool dm_table_supports_discards(struct dm_table *t)
        struct dm_target *ti;
        unsigned i = 0;
 
-       if (!t->discards_supported)
-               return 0;
-
        /*
         * Unless any target used by the table set discards_supported,
         * require at least one underlying device to support discards.
         * t->devices includes internal dm devices such as mirror logs
         * so we need to use iterate_devices here, which targets
-        * supporting discard must provide.
+        * supporting discard selectively must provide.
         */
        while (i < dm_table_get_num_targets(t)) {
                ti = dm_table_get_target(t, i++);
 
+               if (!ti->num_discard_requests)
+                       continue;
+
                if (ti->discards_supported)
                        return 1;
 
@@ -1382,13 +1481,3 @@ bool dm_table_supports_discards(struct dm_table *t)
 
        return 0;
 }
-
-EXPORT_SYMBOL(dm_vcalloc);
-EXPORT_SYMBOL(dm_get_device);
-EXPORT_SYMBOL(dm_put_device);
-EXPORT_SYMBOL(dm_table_event);
-EXPORT_SYMBOL(dm_table_get_size);
-EXPORT_SYMBOL(dm_table_get_mode);
-EXPORT_SYMBOL(dm_table_get_md);
-EXPORT_SYMBOL(dm_table_put);
-EXPORT_SYMBOL(dm_table_get);
index 0cf68b4..52b39f3 100644 (file)
@@ -37,6 +37,8 @@ static const char *_name = DM_NAME;
 static unsigned int major = 0;
 static unsigned int _major = 0;
 
+static DEFINE_IDR(_minor_idr);
+
 static DEFINE_SPINLOCK(_minor_lock);
 /*
  * For bio-based dm.
@@ -109,6 +111,7 @@ EXPORT_SYMBOL_GPL(dm_get_rq_mapinfo);
 #define DMF_FREEING 3
 #define DMF_DELETING 4
 #define DMF_NOFLUSH_SUSPENDING 5
+#define DMF_MERGE_IS_OPTIONAL 6
 
 /*
  * Work processed by per-device workqueue.
@@ -313,6 +316,12 @@ static void __exit dm_exit(void)
 
        while (i--)
                _exits[i]();
+
+       /*
+        * Should be empty by this point.
+        */
+       idr_remove_all(&_minor_idr);
+       idr_destroy(&_minor_idr);
 }
 
 /*
@@ -1171,7 +1180,8 @@ static int __clone_and_map_discard(struct clone_info *ci)
 
                /*
                 * Even though the device advertised discard support,
-                * reconfiguration might have changed that since the
+                * that does not mean every target supports it, and
+                * reconfiguration might also have changed that since the
                 * check was performed.
                 */
                if (!ti->num_discard_requests)
@@ -1705,8 +1715,6 @@ static int dm_any_congested(void *congested_data, int bdi_bits)
 /*-----------------------------------------------------------------
  * An IDR is used to keep track of allocated minor numbers.
  *---------------------------------------------------------------*/
-static DEFINE_IDR(_minor_idr);
-
 static void free_minor(int minor)
 {
        spin_lock(&_minor_lock);
@@ -1800,7 +1808,6 @@ static void dm_init_md_queue(struct mapped_device *md)
        blk_queue_make_request(md->queue, dm_request);
        blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
        blk_queue_merge_bvec(md->queue, dm_merge_bvec);
-       blk_queue_flush(md->queue, REQ_FLUSH | REQ_FUA);
 }
 
 /*
@@ -1985,6 +1992,59 @@ static void __set_size(struct mapped_device *md, sector_t size)
        i_size_write(md->bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
 }
 
+/*
+ * Return 1 if the queue has a compulsory merge_bvec_fn function.
+ *
+ * If this function returns 0, then the device is either a non-dm
+ * device without a merge_bvec_fn, or it is a dm device that is
+ * able to split any bios it receives that are too big.
+ */
+int dm_queue_merge_is_compulsory(struct request_queue *q)
+{
+       struct mapped_device *dev_md;
+
+       if (!q->merge_bvec_fn)
+               return 0;
+
+       if (q->make_request_fn == dm_request) {
+               dev_md = q->queuedata;
+               if (test_bit(DMF_MERGE_IS_OPTIONAL, &dev_md->flags))
+                       return 0;
+       }
+
+       return 1;
+}
+
+static int dm_device_merge_is_compulsory(struct dm_target *ti,
+                                        struct dm_dev *dev, sector_t start,
+                                        sector_t len, void *data)
+{
+       struct block_device *bdev = dev->bdev;
+       struct request_queue *q = bdev_get_queue(bdev);
+
+       return dm_queue_merge_is_compulsory(q);
+}
+
+/*
+ * Return 1 if it is acceptable to ignore merge_bvec_fn based
+ * on the properties of the underlying devices.
+ */
+static int dm_table_merge_is_optional(struct dm_table *table)
+{
+       unsigned i = 0;
+       struct dm_target *ti;
+
+       while (i < dm_table_get_num_targets(table)) {
+               ti = dm_table_get_target(table, i++);
+
+               if (ti->type->iterate_devices &&
+                   ti->type->iterate_devices(ti, dm_device_merge_is_compulsory, NULL))
+                       return 0;
+       }
+
+       return 1;
+}
+
 /*
  * Returns old map, which caller must destroy.
  */
@@ -1995,6 +2055,7 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
        struct request_queue *q = md->queue;
        sector_t size;
        unsigned long flags;
+       int merge_is_optional;
 
        size = dm_table_get_size(t);
 
@@ -2020,10 +2081,16 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
 
        __bind_mempools(md, t);
 
+       merge_is_optional = dm_table_merge_is_optional(t);
+
        write_lock_irqsave(&md->map_lock, flags);
        old_map = md->map;
        md->map = t;
        dm_table_set_restrictions(t, q, limits);
+       if (merge_is_optional)
+               set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
+       else
+               clear_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
        write_unlock_irqrestore(&md->map_lock, flags);
 
        return old_map;
index 1aaf167..6745dbd 100644 (file)
@@ -66,6 +66,8 @@ int dm_table_alloc_md_mempools(struct dm_table *t);
 void dm_table_free_md_mempools(struct dm_table *t);
 struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t);
 
+int dm_queue_merge_is_compulsory(struct request_queue *q);
+
 void dm_lock_md_type(struct mapped_device *md);
 void dm_unlock_md_type(struct mapped_device *md);
 void dm_set_md_type(struct mapped_device *md, unsigned type);
index 6995940..9575db4 100644 (file)
@@ -68,7 +68,6 @@ config VIDEO_V4L2_SUBDEV_API
 
 config DVB_CORE
        tristate "DVB for Linux"
-       depends on NET && INET
        select CRC32
        help
          DVB core utility functions for device handling, software fallbacks etc.
@@ -85,6 +84,19 @@ config DVB_CORE
 
          If unsure say N.
 
+config DVB_NET
+       bool "DVB Network Support"
+       default (NET && INET)
+       depends on NET && INET && DVB_CORE
+       help
+         This option enables DVB Network Support which is a part of the DVB
+         standard. It is used, for example, by automatic firmware updates used
+         on Set-Top-Boxes. It can also be used to access the Internet via the
+         DVB card, if the network provider supports it.
+
+         You may want to disable the network support on embedded devices. If
+         unsure say Y.
+
 config VIDEO_MEDIA
        tristate
        default (DVB_CORE && (VIDEO_DEV = n)) || (VIDEO_DEV && (DVB_CORE = n)) || (DVB_CORE && VIDEO_DEV)
index 22d3ca3..996302a 100644 (file)
@@ -23,6 +23,7 @@ config MEDIA_TUNER
        depends on VIDEO_MEDIA && I2C
        select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE
@@ -152,6 +153,15 @@ config MEDIA_TUNER_XC5000
          This device is only used inside a SiP called together with a
          demodulator for now.
 
+config MEDIA_TUNER_XC4000
+       tristate "Xceive XC4000 silicon tuner"
+       depends on VIDEO_MEDIA && I2C
+       default m if MEDIA_TUNER_CUSTOMISE
+       help
+         A driver for the silicon tuner XC4000 from Xceive.
+         This device is only used inside a SiP called together with a
+         demodulator for now.
+
 config MEDIA_TUNER_MXL5005S
        tristate "MaxLinear MSL5005S silicon tuner"
        depends on VIDEO_MEDIA && I2C
index 2cb4f53..20d24fc 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_MEDIA_TUNER_TDA9887) += tda9887.o
 obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda827x.o
 obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
 obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
+obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o
 obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
 obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
 obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
index afba6dc..94a603a 100644 (file)
@@ -1805,6 +1805,10 @@ struct tunertype tuners[] = {
                .name   = "Xceive 5000 tuner",
                /* see xc5000.c for details */
        },
+       [TUNER_XC4000] = { /* Xceive 4000 */
+               .name   = "Xceive 4000 tuner",
+               /* see xc4000.c for details */
+       },
        [TUNER_TCL_MF02GIP_5N] = { /* TCL tuner MF02GIP-5N-E */
                .name   = "TCL tuner MF02GIP-5N-E",
                .params = tuner_tcl_mf02gip_5n_params,
diff --git a/drivers/media/common/tuners/xc4000.c b/drivers/media/common/tuners/xc4000.c
new file mode 100644 (file)
index 0000000..634f4d9
--- /dev/null
@@ -0,0 +1,1691 @@
+/*
+ *  Driver for Xceive XC4000 "QAM/8VSB single chip tuner"
+ *
+ *  Copyright (c) 2007 Xceive Corporation
+ *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
+ *  Copyright (c) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
+ *  Copyright (c) 2009 Davide Ferri <d.ferri@zero11.it>
+ *  Copyright (c) 2010 Istvan Varga <istvan_v@mailbox.hu>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/videodev2.h>
+#include <linux/delay.h>
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <asm/unaligned.h>
+
+#include "dvb_frontend.h"
+
+#include "xc4000.h"
+#include "tuner-i2c.h"
+#include "tuner-xc2028-types.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debugging level (0 to 2, default: 0 (off)).");
+
+static int no_poweroff;
+module_param(no_poweroff, int, 0644);
+MODULE_PARM_DESC(no_poweroff, "Power management (1: disabled, 2: enabled, "
+       "0 (default): use device-specific default mode).");
+
+static int audio_std;
+module_param(audio_std, int, 0644);
+MODULE_PARM_DESC(audio_std, "Audio standard. XC4000 audio decoder explicitly "
+       "needs to know what audio standard is needed for some video standards "
+       "with audio A2 or NICAM. The valid settings are a sum of:\n"
+       " 1: use NICAM/B or A2/B instead of NICAM/A or A2/A\n"
+       " 2: use A2 instead of NICAM or BTSC\n"
+       " 4: use SECAM/K3 instead of K1\n"
+       " 8: use PAL-D/K audio for SECAM-D/K\n"
+       "16: use FM radio input 1 instead of input 2\n"
+       "32: use mono audio (the lower three bits are ignored)");
+
+static char firmware_name[30];
+module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
+MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
+       "default firmware name.");
+
+static DEFINE_MUTEX(xc4000_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
+
+#define dprintk(level, fmt, arg...) if (debug >= level) \
+       printk(KERN_INFO "%s: " fmt, "xc4000", ## arg)
+
+/* struct for storing firmware table */
+struct firmware_description {
+       unsigned int  type;
+       v4l2_std_id   id;
+       __u16         int_freq;
+       unsigned char *ptr;
+       unsigned int  size;
+};
+
+struct firmware_properties {
+       unsigned int    type;
+       v4l2_std_id     id;
+       v4l2_std_id     std_req;
+       __u16           int_freq;
+       unsigned int    scode_table;
+       int             scode_nr;
+};
+
+struct xc4000_priv {
+       struct tuner_i2c_props i2c_props;
+       struct list_head hybrid_tuner_instance_list;
+       struct firmware_description *firm;
+       int     firm_size;
+       u32     if_khz;
+       u32     freq_hz;
+       u32     bandwidth;
+       u8      video_standard;
+       u8      rf_mode;
+       u8      default_pm;
+       u8      dvb_amplitude;
+       u8      set_smoothedcvbs;
+       u8      ignore_i2c_write_errors;
+       __u16   firm_version;
+       struct firmware_properties cur_fw;
+       __u16   hwmodel;
+       __u16   hwvers;
+       struct mutex    lock;
+};
+
+#define XC4000_AUDIO_STD_B              1
+#define XC4000_AUDIO_STD_A2             2
+#define XC4000_AUDIO_STD_K3             4
+#define XC4000_AUDIO_STD_L              8
+#define XC4000_AUDIO_STD_INPUT1                16
+#define XC4000_AUDIO_STD_MONO          32
+
+#define XC4000_DEFAULT_FIRMWARE "dvb-fe-xc4000-1.4.fw"
+
+/* Misc Defines */
+#define MAX_TV_STANDARD                        24
+#define XC_MAX_I2C_WRITE_LENGTH                64
+#define XC_POWERED_DOWN                        0x80000000U
+
+/* Signal Types */
+#define XC_RF_MODE_AIR                 0
+#define XC_RF_MODE_CABLE               1
+
+/* Product id */
+#define XC_PRODUCT_ID_FW_NOT_LOADED    0x2000
+#define XC_PRODUCT_ID_XC4000           0x0FA0
+#define XC_PRODUCT_ID_XC4100           0x1004
+
+/* Registers (Write-only) */
+#define XREG_INIT         0x00
+#define XREG_VIDEO_MODE   0x01
+#define XREG_AUDIO_MODE   0x02
+#define XREG_RF_FREQ      0x03
+#define XREG_D_CODE       0x04
+#define XREG_DIRECTSITTING_MODE 0x05
+#define XREG_SEEK_MODE    0x06
+#define XREG_POWER_DOWN   0x08
+#define XREG_SIGNALSOURCE 0x0A
+#define XREG_SMOOTHEDCVBS 0x0E
+#define XREG_AMPLITUDE    0x10
+
+/* Registers (Read-only) */
+#define XREG_ADC_ENV      0x00
+#define XREG_QUALITY      0x01
+#define XREG_FRAME_LINES  0x02
+#define XREG_HSYNC_FREQ   0x03
+#define XREG_LOCK         0x04
+#define XREG_FREQ_ERROR   0x05
+#define XREG_SNR          0x06
+#define XREG_VERSION      0x07
+#define XREG_PRODUCT_ID   0x08
+
+/*
+   Basic firmware description. This will remain with
+   the driver for documentation purposes.
+
+   This represents an I2C firmware file encoded as a
+   string of unsigned char. Format is as follows:
+
+   char[0  ]=len0_MSB  -> len = len_MSB * 256 + len_LSB
+   char[1  ]=len0_LSB  -> length of first write transaction
+   char[2  ]=data0 -> first byte to be sent
+   char[3  ]=data1
+   char[4  ]=data2
+   char[   ]=...
+   char[M  ]=dataN  -> last byte to be sent
+   char[M+1]=len1_MSB  -> len = len_MSB * 256 + len_LSB
+   char[M+2]=len1_LSB  -> length of second write transaction
+   char[M+3]=data0
+   char[M+4]=data1
+   ...
+   etc.
+
+   The [len] value should be interpreted as follows:
+
+   len= len_MSB _ len_LSB
+   len=1111_1111_1111_1111   : End of I2C_SEQUENCE
+   len=0000_0000_0000_0000   : Reset command: Do hardware reset
+   len=0NNN_NNNN_NNNN_NNNN   : Normal transaction: number of bytes = {1:32767)
+   len=1WWW_WWWW_WWWW_WWWW   : Wait command: wait for {1:32767} ms
+
+   For the RESET and WAIT commands, the two following bytes will contain
+   immediately the length of the following transaction.
+*/
+
+struct XC_TV_STANDARD {
+       const char  *Name;
+       u16         audio_mode;
+       u16         video_mode;
+       u16         int_freq;
+};
+
+/* Tuner standards */
+#define XC4000_MN_NTSC_PAL_BTSC                0
+#define XC4000_MN_NTSC_PAL_A2          1
+#define XC4000_MN_NTSC_PAL_EIAJ                2
+#define XC4000_MN_NTSC_PAL_Mono                3
+#define XC4000_BG_PAL_A2               4
+#define XC4000_BG_PAL_NICAM            5
+#define XC4000_BG_PAL_MONO             6
+#define XC4000_I_PAL_NICAM             7
+#define XC4000_I_PAL_NICAM_MONO                8
+#define XC4000_DK_PAL_A2               9
+#define XC4000_DK_PAL_NICAM            10
+#define XC4000_DK_PAL_MONO             11
+#define XC4000_DK_SECAM_A2DK1          12
+#define XC4000_DK_SECAM_A2LDK3         13
+#define XC4000_DK_SECAM_A2MONO         14
+#define XC4000_DK_SECAM_NICAM          15
+#define XC4000_L_SECAM_NICAM           16
+#define XC4000_LC_SECAM_NICAM          17
+#define XC4000_DTV6                    18
+#define XC4000_DTV8                    19
+#define XC4000_DTV7_8                  20
+#define XC4000_DTV7                    21
+#define XC4000_FM_Radio_INPUT2         22
+#define XC4000_FM_Radio_INPUT1         23
+
+static struct XC_TV_STANDARD xc4000_standard[MAX_TV_STANDARD] = {
+       {"M/N-NTSC/PAL-BTSC",   0x0000, 0x80A0, 4500},
+       {"M/N-NTSC/PAL-A2",     0x0000, 0x80A0, 4600},
+       {"M/N-NTSC/PAL-EIAJ",   0x0040, 0x80A0, 4500},
+       {"M/N-NTSC/PAL-Mono",   0x0078, 0x80A0, 4500},
+       {"B/G-PAL-A2",          0x0000, 0x8159, 5640},
+       {"B/G-PAL-NICAM",       0x0004, 0x8159, 5740},
+       {"B/G-PAL-MONO",        0x0078, 0x8159, 5500},
+       {"I-PAL-NICAM",         0x0080, 0x8049, 6240},
+       {"I-PAL-NICAM-MONO",    0x0078, 0x8049, 6000},
+       {"D/K-PAL-A2",          0x0000, 0x8049, 6380},
+       {"D/K-PAL-NICAM",       0x0080, 0x8049, 6200},
+       {"D/K-PAL-MONO",        0x0078, 0x8049, 6500},
+       {"D/K-SECAM-A2 DK1",    0x0000, 0x8049, 6340},
+       {"D/K-SECAM-A2 L/DK3",  0x0000, 0x8049, 6000},
+       {"D/K-SECAM-A2 MONO",   0x0078, 0x8049, 6500},
+       {"D/K-SECAM-NICAM",     0x0080, 0x8049, 6200},
+       {"L-SECAM-NICAM",       0x8080, 0x0009, 6200},
+       {"L'-SECAM-NICAM",      0x8080, 0x4009, 6200},
+       {"DTV6",                0x00C0, 0x8002,    0},
+       {"DTV8",                0x00C0, 0x800B,    0},
+       {"DTV7/8",              0x00C0, 0x801B,    0},
+       {"DTV7",                0x00C0, 0x8007,    0},
+       {"FM Radio-INPUT2",     0x0008, 0x9800, 10700},
+       {"FM Radio-INPUT1",     0x0008, 0x9000, 10700}
+};
+
+static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val);
+static int xc4000_tuner_reset(struct dvb_frontend *fe);
+static void xc_debug_dump(struct xc4000_priv *priv);
+
+static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
+{
+       struct i2c_msg msg = { .addr = priv->i2c_props.addr,
+                              .flags = 0, .buf = buf, .len = len };
+       if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
+               if (priv->ignore_i2c_write_errors == 0) {
+                       printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n",
+                              len);
+                       if (len == 4) {
+                               printk(KERN_ERR "bytes %02x %02x %02x %02x\n", buf[0],
+                                      buf[1], buf[2], buf[3]);
+                       }
+                       return -EREMOTEIO;
+               }
+       }
+       return 0;
+}
+
+static int xc4000_tuner_reset(struct dvb_frontend *fe)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+       int ret;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (fe->callback) {
+               ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
+                                          fe->dvb->priv :
+                                          priv->i2c_props.adap->algo_data,
+                                          DVB_FRONTEND_COMPONENT_TUNER,
+                                          XC4000_TUNER_RESET, 0);
+               if (ret) {
+                       printk(KERN_ERR "xc4000: reset failed\n");
+                       return -EREMOTEIO;
+               }
+       } else {
+               printk(KERN_ERR "xc4000: no tuner reset callback function, "
+                               "fatal\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int xc_write_reg(struct xc4000_priv *priv, u16 regAddr, u16 i2cData)
+{
+       u8 buf[4];
+       int result;
+
+       buf[0] = (regAddr >> 8) & 0xFF;
+       buf[1] = regAddr & 0xFF;
+       buf[2] = (i2cData >> 8) & 0xFF;
+       buf[3] = i2cData & 0xFF;
+       result = xc_send_i2c_data(priv, buf, 4);
+
+       return result;
+}
+
+static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+
+       int i, nbytes_to_send, result;
+       unsigned int len, pos, index;
+       u8 buf[XC_MAX_I2C_WRITE_LENGTH];
+
+       index = 0;
+       while ((i2c_sequence[index] != 0xFF) ||
+               (i2c_sequence[index + 1] != 0xFF)) {
+               len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
+               if (len == 0x0000) {
+                       /* RESET command */
+                       /* NOTE: this is ignored, as the reset callback was */
+                       /* already called by check_firmware() */
+                       index += 2;
+               } else if (len & 0x8000) {
+                       /* WAIT command */
+                       msleep(len & 0x7FFF);
+                       index += 2;
+               } else {
+                       /* Send i2c data whilst ensuring individual transactions
+                        * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
+                        */
+                       index += 2;
+                       buf[0] = i2c_sequence[index];
+                       buf[1] = i2c_sequence[index + 1];
+                       pos = 2;
+                       while (pos < len) {
+                               if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
+                                       nbytes_to_send =
+                                               XC_MAX_I2C_WRITE_LENGTH;
+                               else
+                                       nbytes_to_send = (len - pos + 2);
+                               for (i = 2; i < nbytes_to_send; i++) {
+                                       buf[i] = i2c_sequence[index + pos +
+                                               i - 2];
+                               }
+                               result = xc_send_i2c_data(priv, buf,
+                                       nbytes_to_send);
+
+                               if (result != 0)
+                                       return result;
+
+                               pos += nbytes_to_send - 2;
+                       }
+                       index += len;
+               }
+       }
+       return 0;
+}
+
+static int xc_set_tv_standard(struct xc4000_priv *priv,
+       u16 video_mode, u16 audio_mode)
+{
+       int ret;
+       dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, video_mode, audio_mode);
+       dprintk(1, "%s() Standard = %s\n",
+               __func__,
+               xc4000_standard[priv->video_standard].Name);
+
+       /* Don't complain when the request fails because of i2c stretching */
+       priv->ignore_i2c_write_errors = 1;
+
+       ret = xc_write_reg(priv, XREG_VIDEO_MODE, video_mode);
+       if (ret == 0)
+               ret = xc_write_reg(priv, XREG_AUDIO_MODE, audio_mode);
+
+       priv->ignore_i2c_write_errors = 0;
+
+       return ret;
+}
+
+static int xc_set_signal_source(struct xc4000_priv *priv, u16 rf_mode)
+{
+       dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
+               rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
+
+       if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
+               rf_mode = XC_RF_MODE_CABLE;
+               printk(KERN_ERR
+                       "%s(), Invalid mode, defaulting to CABLE",
+                       __func__);
+       }
+       return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
+}
+
+static const struct dvb_tuner_ops xc4000_tuner_ops;
+
+static int xc_set_rf_frequency(struct xc4000_priv *priv, u32 freq_hz)
+{
+       u16 freq_code;
+
+       dprintk(1, "%s(%u)\n", __func__, freq_hz);
+
+       if ((freq_hz > xc4000_tuner_ops.info.frequency_max) ||
+           (freq_hz < xc4000_tuner_ops.info.frequency_min))
+               return -EINVAL;
+
+       freq_code = (u16)(freq_hz / 15625);
+
+       /* WAS: Starting in firmware version 1.1.44, Xceive recommends using the
+          FINERFREQ for all normal tuning (the doc indicates reg 0x03 should
+          only be used for fast scanning for channel lock) */
+       /* WAS: XREG_FINERFREQ */
+       return xc_write_reg(priv, XREG_RF_FREQ, freq_code);
+}
+
+static int xc_get_adc_envelope(struct xc4000_priv *priv, u16 *adc_envelope)
+{
+       return xc4000_readreg(priv, XREG_ADC_ENV, adc_envelope);
+}
+
+static int xc_get_frequency_error(struct xc4000_priv *priv, u32 *freq_error_hz)
+{
+       int result;
+       u16 regData;
+       u32 tmp;
+
+       result = xc4000_readreg(priv, XREG_FREQ_ERROR, &regData);
+       if (result != 0)
+               return result;
+
+       tmp = (u32)regData & 0xFFFFU;
+       tmp = (tmp < 0x8000U ? tmp : 0x10000U - tmp);
+       (*freq_error_hz) = tmp * 15625;
+       return result;
+}
+
+static int xc_get_lock_status(struct xc4000_priv *priv, u16 *lock_status)
+{
+       return xc4000_readreg(priv, XREG_LOCK, lock_status);
+}
+
+static int xc_get_version(struct xc4000_priv *priv,
+       u8 *hw_majorversion, u8 *hw_minorversion,
+       u8 *fw_majorversion, u8 *fw_minorversion)
+{
+       u16 data;
+       int result;
+
+       result = xc4000_readreg(priv, XREG_VERSION, &data);
+       if (result != 0)
+               return result;
+
+       (*hw_majorversion) = (data >> 12) & 0x0F;
+       (*hw_minorversion) = (data >>  8) & 0x0F;
+       (*fw_majorversion) = (data >>  4) & 0x0F;
+       (*fw_minorversion) = data & 0x0F;
+
+       return 0;
+}
+
+static int xc_get_hsync_freq(struct xc4000_priv *priv, u32 *hsync_freq_hz)
+{
+       u16 regData;
+       int result;
+
+       result = xc4000_readreg(priv, XREG_HSYNC_FREQ, &regData);
+       if (result != 0)
+               return result;
+
+       (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
+       return result;
+}
+
+static int xc_get_frame_lines(struct xc4000_priv *priv, u16 *frame_lines)
+{
+       return xc4000_readreg(priv, XREG_FRAME_LINES, frame_lines);
+}
+
+static int xc_get_quality(struct xc4000_priv *priv, u16 *quality)
+{
+       return xc4000_readreg(priv, XREG_QUALITY, quality);
+}
+
+static u16 xc_wait_for_lock(struct xc4000_priv *priv)
+{
+       u16     lock_state = 0;
+       int     watchdog_count = 40;
+
+       while ((lock_state == 0) && (watchdog_count > 0)) {
+               xc_get_lock_status(priv, &lock_state);
+               if (lock_state != 1) {
+                       msleep(5);
+                       watchdog_count--;
+               }
+       }
+       return lock_state;
+}
+
+static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz)
+{
+       int     found = 1;
+       int     result;
+
+       dprintk(1, "%s(%u)\n", __func__, freq_hz);
+
+       /* Don't complain when the request fails because of i2c stretching */
+       priv->ignore_i2c_write_errors = 1;
+       result = xc_set_rf_frequency(priv, freq_hz);
+       priv->ignore_i2c_write_errors = 0;
+
+       if (result != 0)
+               return 0;
+
+       /* wait for lock only in analog TV mode */
+       if ((priv->cur_fw.type & (FM | DTV6 | DTV7 | DTV78 | DTV8)) == 0) {
+               if (xc_wait_for_lock(priv) != 1)
+                       found = 0;
+       }
+
+       /* Wait for stats to stabilize.
+        * Frame Lines needs two frame times after initial lock
+        * before it is valid.
+        */
+       msleep(debug ? 100 : 10);
+
+       if (debug)
+               xc_debug_dump(priv);
+
+       return found;
+}
+
+static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val)
+{
+       u8 buf[2] = { reg >> 8, reg & 0xff };
+       u8 bval[2] = { 0, 0 };
+       struct i2c_msg msg[2] = {
+               { .addr = priv->i2c_props.addr,
+                       .flags = 0, .buf = &buf[0], .len = 2 },
+               { .addr = priv->i2c_props.addr,
+                       .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
+       };
+
+       if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
+               printk(KERN_ERR "xc4000: I2C read failed\n");
+               return -EREMOTEIO;
+       }
+
+       *val = (bval[0] << 8) | bval[1];
+       return 0;
+}
+
+#define dump_firm_type(t)      dump_firm_type_and_int_freq(t, 0)
+static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
+{
+        if (type & BASE)
+               printk(KERN_CONT "BASE ");
+        if (type & INIT1)
+               printk(KERN_CONT "INIT1 ");
+        if (type & F8MHZ)
+               printk(KERN_CONT "F8MHZ ");
+        if (type & MTS)
+               printk(KERN_CONT "MTS ");
+        if (type & D2620)
+               printk(KERN_CONT "D2620 ");
+        if (type & D2633)
+               printk(KERN_CONT "D2633 ");
+        if (type & DTV6)
+               printk(KERN_CONT "DTV6 ");
+        if (type & QAM)
+               printk(KERN_CONT "QAM ");
+        if (type & DTV7)
+               printk(KERN_CONT "DTV7 ");
+        if (type & DTV78)
+               printk(KERN_CONT "DTV78 ");
+        if (type & DTV8)
+               printk(KERN_CONT "DTV8 ");
+        if (type & FM)
+               printk(KERN_CONT "FM ");
+        if (type & INPUT1)
+               printk(KERN_CONT "INPUT1 ");
+        if (type & LCD)
+               printk(KERN_CONT "LCD ");
+        if (type & NOGD)
+               printk(KERN_CONT "NOGD ");
+        if (type & MONO)
+               printk(KERN_CONT "MONO ");
+        if (type & ATSC)
+               printk(KERN_CONT "ATSC ");
+        if (type & IF)
+               printk(KERN_CONT "IF ");
+        if (type & LG60)
+               printk(KERN_CONT "LG60 ");
+        if (type & ATI638)
+               printk(KERN_CONT "ATI638 ");
+        if (type & OREN538)
+               printk(KERN_CONT "OREN538 ");
+        if (type & OREN36)
+               printk(KERN_CONT "OREN36 ");
+        if (type & TOYOTA388)
+               printk(KERN_CONT "TOYOTA388 ");
+        if (type & TOYOTA794)
+               printk(KERN_CONT "TOYOTA794 ");
+        if (type & DIBCOM52)
+               printk(KERN_CONT "DIBCOM52 ");
+        if (type & ZARLINK456)
+               printk(KERN_CONT "ZARLINK456 ");
+        if (type & CHINA)
+               printk(KERN_CONT "CHINA ");
+        if (type & F6MHZ)
+               printk(KERN_CONT "F6MHZ ");
+        if (type & INPUT2)
+               printk(KERN_CONT "INPUT2 ");
+        if (type & SCODE)
+               printk(KERN_CONT "SCODE ");
+        if (type & HAS_IF)
+               printk(KERN_CONT "HAS_IF_%d ", int_freq);
+}
+
+static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+                        v4l2_std_id *id)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+       int             i, best_i = -1;
+       unsigned int    best_nr_diffs = 255U;
+
+       if (!priv->firm) {
+               printk(KERN_ERR "Error! firmware not loaded\n");
+               return -EINVAL;
+       }
+
+       if (((type & ~SCODE) == 0) && (*id == 0))
+               *id = V4L2_STD_PAL;
+
+       /* Seek for generic video standard match */
+       for (i = 0; i < priv->firm_size; i++) {
+               v4l2_std_id     id_diff_mask =
+                       (priv->firm[i].id ^ (*id)) & (*id);
+               unsigned int    type_diff_mask =
+                       (priv->firm[i].type ^ type)
+                       & (BASE_TYPES | DTV_TYPES | LCD | NOGD | MONO | SCODE);
+               unsigned int    nr_diffs;
+
+               if (type_diff_mask
+                   & (BASE | INIT1 | FM | DTV6 | DTV7 | DTV78 | DTV8 | SCODE))
+                       continue;
+
+               nr_diffs = hweight64(id_diff_mask) + hweight32(type_diff_mask);
+               if (!nr_diffs)  /* Supports all the requested standards */
+                       goto found;
+
+               if (nr_diffs < best_nr_diffs) {
+                       best_nr_diffs = nr_diffs;
+                       best_i = i;
+               }
+       }
+
+       /* FIXME: Would make sense to seek for type "hint" match ? */
+       if (best_i < 0) {
+               i = -ENOENT;
+               goto ret;
+       }
+
+       if (best_nr_diffs > 0U) {
+               printk(KERN_WARNING
+                      "Selecting best matching firmware (%u bits differ) for "
+                      "type=(%x), id %016llx:\n",
+                      best_nr_diffs, type, (unsigned long long)*id);
+               i = best_i;
+       }
+
+found:
+       *id = priv->firm[i].id;
+
+ret:
+       if (debug) {
+               printk(KERN_DEBUG "%s firmware for type=",
+                      (i < 0) ? "Can't find" : "Found");
+               dump_firm_type(type);
+               printk(KERN_DEBUG "(%x), id %016llx.\n", type, (unsigned long long)*id);
+       }
+       return i;
+}
+
+static int load_firmware(struct dvb_frontend *fe, unsigned int type,
+                        v4l2_std_id *id)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+       int                pos, rc;
+       unsigned char      *p;
+
+       pos = seek_firmware(fe, type, id);
+       if (pos < 0)
+               return pos;
+
+       p = priv->firm[pos].ptr;
+
+       /* Don't complain when the request fails because of i2c stretching */
+       priv->ignore_i2c_write_errors = 1;
+
+       rc = xc_load_i2c_sequence(fe, p);
+
+       priv->ignore_i2c_write_errors = 0;
+
+       return rc;
+}
+
+static int xc4000_fwupload(struct dvb_frontend *fe)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+       const struct firmware *fw   = NULL;
+       const unsigned char   *p, *endp;
+       int                   rc = 0;
+       int                   n, n_array;
+       char                  name[33];
+       const char            *fname;
+
+       if (firmware_name[0] != '\0')
+               fname = firmware_name;
+       else
+               fname = XC4000_DEFAULT_FIRMWARE;
+
+       dprintk(1, "Reading firmware %s\n", fname);
+       rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
+       if (rc < 0) {
+               if (rc == -ENOENT)
+                       printk(KERN_ERR "Error: firmware %s not found.\n", fname);
+               else
+                       printk(KERN_ERR "Error %d while requesting firmware %s\n",
+                              rc, fname);
+
+               return rc;
+       }
+       p = fw->data;
+       endp = p + fw->size;
+
+       if (fw->size < sizeof(name) - 1 + 2 + 2) {
+               printk(KERN_ERR "Error: firmware file %s has invalid size!\n",
+                      fname);
+               goto corrupt;
+       }
+
+       memcpy(name, p, sizeof(name) - 1);
+       name[sizeof(name) - 1] = '\0';
+       p += sizeof(name) - 1;
+
+       priv->firm_version = get_unaligned_le16(p);
+       p += 2;
+
+       n_array = get_unaligned_le16(p);
+       p += 2;
+
+       dprintk(1, "Loading %d firmware images from %s, type: %s, ver %d.%d\n",
+               n_array, fname, name,
+               priv->firm_version >> 8, priv->firm_version & 0xff);
+
+       priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
+       if (priv->firm == NULL) {
+               printk(KERN_ERR "Not enough memory to load firmware file.\n");
+               rc = -ENOMEM;
+               goto done;
+       }
+       priv->firm_size = n_array;
+
+       n = -1;
+       while (p < endp) {
+               __u32 type, size;
+               v4l2_std_id id;
+               __u16 int_freq = 0;
+
+               n++;
+               if (n >= n_array) {
+                       printk(KERN_ERR "More firmware images in file than "
+                              "were expected!\n");
+                       goto corrupt;
+               }
+
+               /* Checks if there's enough bytes to read */
+               if (endp - p < sizeof(type) + sizeof(id) + sizeof(size))
+                       goto header;
+
+               type = get_unaligned_le32(p);
+               p += sizeof(type);
+
+               id = get_unaligned_le64(p);
+               p += sizeof(id);
+
+               if (type & HAS_IF) {
+                       int_freq = get_unaligned_le16(p);
+                       p += sizeof(int_freq);
+                       if (endp - p < sizeof(size))
+                               goto header;
+               }
+
+               size = get_unaligned_le32(p);
+               p += sizeof(size);
+
+               if (!size || size > endp - p) {
+                       printk(KERN_ERR "Firmware type (%x), id %llx is corrupted (size=%d, expected %d)\n",
+                              type, (unsigned long long)id,
+                              (unsigned)(endp - p), size);
+                       goto corrupt;
+               }
+
+               priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
+               if (priv->firm[n].ptr == NULL) {
+                       printk(KERN_ERR "Not enough memory to load firmware file.\n");
+                       rc = -ENOMEM;
+                       goto done;
+               }
+
+               if (debug) {
+                       printk(KERN_DEBUG "Reading firmware type ");
+                       dump_firm_type_and_int_freq(type, int_freq);
+                       printk(KERN_DEBUG "(%x), id %llx, size=%d.\n",
+                              type, (unsigned long long)id, size);
+               }
+
+               memcpy(priv->firm[n].ptr, p, size);
+               priv->firm[n].type = type;
+               priv->firm[n].id   = id;
+               priv->firm[n].size = size;
+               priv->firm[n].int_freq = int_freq;
+
+               p += size;
+       }
+
+       if (n + 1 != priv->firm_size) {
+               printk(KERN_ERR "Firmware file is incomplete!\n");
+               goto corrupt;
+       }
+
+       goto done;
+
+header:
+       printk(KERN_ERR "Firmware header is incomplete!\n");
+corrupt:
+       rc = -EINVAL;
+       printk(KERN_ERR "Error: firmware file is corrupted!\n");
+
+done:
+       release_firmware(fw);
+       if (rc == 0)
+               dprintk(1, "Firmware files loaded.\n");
+
+       return rc;
+}
+
+static int load_scode(struct dvb_frontend *fe, unsigned int type,
+                        v4l2_std_id *id, __u16 int_freq, int scode)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+       int             pos, rc;
+       unsigned char   *p;
+       u8              scode_buf[13];
+       u8              indirect_mode[5];
+
+       dprintk(1, "%s called int_freq=%d\n", __func__, int_freq);
+
+       if (!int_freq) {
+               pos = seek_firmware(fe, type, id);
+               if (pos < 0)
+                       return pos;
+       } else {
+               for (pos = 0; pos < priv->firm_size; pos++) {
+                       if ((priv->firm[pos].int_freq == int_freq) &&
+                           (priv->firm[pos].type & HAS_IF))
+                               break;
+               }
+               if (pos == priv->firm_size)
+                       return -ENOENT;
+       }
+
+       p = priv->firm[pos].ptr;
+
+       if (priv->firm[pos].size != 12 * 16 || scode >= 16)
+               return -EINVAL;
+       p += 12 * scode;
+
+       if (debug) {
+               tuner_info("Loading SCODE for type=");
+               dump_firm_type_and_int_freq(priv->firm[pos].type,
+                                           priv->firm[pos].int_freq);
+               printk(KERN_CONT "(%x), id %016llx.\n", priv->firm[pos].type,
+                      (unsigned long long)*id);
+       }
+
+       scode_buf[0] = 0x00;
+       memcpy(&scode_buf[1], p, 12);
+
+       /* Enter direct-mode */
+       rc = xc_write_reg(priv, XREG_DIRECTSITTING_MODE, 0);
+       if (rc < 0) {
+               printk(KERN_ERR "failed to put device into direct mode!\n");
+               return -EIO;
+       }
+
+       rc = xc_send_i2c_data(priv, scode_buf, 13);
+       if (rc != 0) {
+               /* Even if the send failed, make sure we set back to indirect
+                  mode */
+               printk(KERN_ERR "Failed to set scode %d\n", rc);
+       }
+
+       /* Switch back to indirect-mode */
+       memset(indirect_mode, 0, sizeof(indirect_mode));
+       indirect_mode[4] = 0x88;
+       xc_send_i2c_data(priv, indirect_mode, sizeof(indirect_mode));
+       msleep(10);
+
+       return 0;
+}
+
+static int check_firmware(struct dvb_frontend *fe, unsigned int type,
+                         v4l2_std_id std, __u16 int_freq)
+{
+       struct xc4000_priv         *priv = fe->tuner_priv;
+       struct firmware_properties new_fw;
+       int                        rc = 0, is_retry = 0;
+       u16                        hwmodel;
+       v4l2_std_id                std0;
+       u8                         hw_major, hw_minor, fw_major, fw_minor;
+
+       dprintk(1, "%s called\n", __func__);
+
+       if (!priv->firm) {
+               rc = xc4000_fwupload(fe);
+               if (rc < 0)
+                       return rc;
+       }
+
+retry:
+       new_fw.type = type;
+       new_fw.id = std;
+       new_fw.std_req = std;
+       new_fw.scode_table = SCODE;
+       new_fw.scode_nr = 0;
+       new_fw.int_freq = int_freq;
+
+       dprintk(1, "checking firmware, user requested type=");
+       if (debug) {
+               dump_firm_type(new_fw.type);
+               printk(KERN_CONT "(%x), id %016llx, ", new_fw.type,
+                      (unsigned long long)new_fw.std_req);
+               if (!int_freq)
+                       printk(KERN_CONT "scode_tbl ");
+               else
+                       printk(KERN_CONT "int_freq %d, ", new_fw.int_freq);
+               printk(KERN_CONT "scode_nr %d\n", new_fw.scode_nr);
+       }
+
+       /* No need to reload base firmware if it matches */
+       if (priv->cur_fw.type & BASE) {
+               dprintk(1, "BASE firmware not changed.\n");
+               goto skip_base;
+       }
+
+       /* Updating BASE - forget about all currently loaded firmware */
+       memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
+
+       /* Reset is needed before loading firmware */
+       rc = xc4000_tuner_reset(fe);
+       if (rc < 0)
+               goto fail;
+
+       /* BASE firmwares are all std0 */
+       std0 = 0;
+       rc = load_firmware(fe, BASE, &std0);
+       if (rc < 0) {
+               printk(KERN_ERR "Error %d while loading base firmware\n", rc);
+               goto fail;
+       }
+
+       /* Load INIT1, if needed */
+       dprintk(1, "Load init1 firmware, if exists\n");
+
+       rc = load_firmware(fe, BASE | INIT1, &std0);
+       if (rc == -ENOENT)
+               rc = load_firmware(fe, BASE | INIT1, &std0);
+       if (rc < 0 && rc != -ENOENT) {
+               tuner_err("Error %d while loading init1 firmware\n",
+                         rc);
+               goto fail;
+       }
+
+skip_base:
+       /*
+        * No need to reload standard specific firmware if base firmware
+        * was not reloaded and requested video standards have not changed.
+        */
+       if (priv->cur_fw.type == (BASE | new_fw.type) &&
+           priv->cur_fw.std_req == std) {
+               dprintk(1, "Std-specific firmware already loaded.\n");
+               goto skip_std_specific;
+       }
+
+       /* Reloading std-specific firmware forces a SCODE update */
+       priv->cur_fw.scode_table = 0;
+
+       /* Load the standard firmware */
+       rc = load_firmware(fe, new_fw.type, &new_fw.id);
+
+       if (rc < 0)
+               goto fail;
+
+skip_std_specific:
+       if (priv->cur_fw.scode_table == new_fw.scode_table &&
+           priv->cur_fw.scode_nr == new_fw.scode_nr) {
+               dprintk(1, "SCODE firmware already loaded.\n");
+               goto check_device;
+       }
+
+       /* Load SCODE firmware, if exists */
+       rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id,
+                       new_fw.int_freq, new_fw.scode_nr);
+       if (rc != 0)
+               dprintk(1, "load scode failed %d\n", rc);
+
+check_device:
+       rc = xc4000_readreg(priv, XREG_PRODUCT_ID, &hwmodel);
+
+       if (xc_get_version(priv, &hw_major, &hw_minor, &fw_major,
+                          &fw_minor) != 0) {
+               printk(KERN_ERR "Unable to read tuner registers.\n");
+               goto fail;
+       }
+
+       dprintk(1, "Device is Xceive %d version %d.%d, "
+               "firmware version %d.%d\n",
+               hwmodel, hw_major, hw_minor, fw_major, fw_minor);
+
+       /* Check firmware version against what we downloaded. */
+       if (priv->firm_version != ((fw_major << 8) | fw_minor)) {
+               printk(KERN_WARNING
+                      "Incorrect readback of firmware version %d.%d.\n",
+                      fw_major, fw_minor);
+               goto fail;
+       }
+
+       /* Check that the tuner hardware model remains consistent over time. */
+       if (priv->hwmodel == 0 &&
+           (hwmodel == XC_PRODUCT_ID_XC4000 ||
+            hwmodel == XC_PRODUCT_ID_XC4100)) {
+               priv->hwmodel = hwmodel;
+               priv->hwvers = (hw_major << 8) | hw_minor;
+       } else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
+                  priv->hwvers != ((hw_major << 8) | hw_minor)) {
+               printk(KERN_WARNING
+                      "Read invalid device hardware information - tuner "
+                      "hung?\n");
+               goto fail;
+       }
+
+       memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw));
+
+       /*
+        * By setting BASE in cur_fw.type only after successfully loading all
+        * firmwares, we can:
+        * 1. Identify that BASE firmware with type=0 has been loaded;
+        * 2. Tell whether BASE firmware was just changed the next time through.
+        */
+       priv->cur_fw.type |= BASE;
+
+       return 0;
+
+fail:
+       memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
+       if (!is_retry) {
+               msleep(50);
+               is_retry = 1;
+               dprintk(1, "Retrying firmware load\n");
+               goto retry;
+       }
+
+       if (rc == -ENOENT)
+               rc = -EINVAL;
+       return rc;
+}
+
+static void xc_debug_dump(struct xc4000_priv *priv)
+{
+       u16     adc_envelope;
+       u32     freq_error_hz = 0;
+       u16     lock_status;
+       u32     hsync_freq_hz = 0;
+       u16     frame_lines;
+       u16     quality;
+       u8      hw_majorversion = 0, hw_minorversion = 0;
+       u8      fw_majorversion = 0, fw_minorversion = 0;
+
+       xc_get_adc_envelope(priv, &adc_envelope);
+       dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
+
+       xc_get_frequency_error(priv, &freq_error_hz);
+       dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
+
+       xc_get_lock_status(priv, &lock_status);
+       dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
+               lock_status);
+
+       xc_get_version(priv, &hw_majorversion, &hw_minorversion,
+                      &fw_majorversion, &fw_minorversion);
+       dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n",
+               hw_majorversion, hw_minorversion,
+               fw_majorversion, fw_minorversion);
+
+       if (priv->video_standard < XC4000_DTV6) {
+               xc_get_hsync_freq(priv, &hsync_freq_hz);
+               dprintk(1, "*** Horizontal sync frequency = %d Hz\n",
+                       hsync_freq_hz);
+
+               xc_get_frame_lines(priv, &frame_lines);
+               dprintk(1, "*** Frame lines = %d\n", frame_lines);
+       }
+
+       xc_get_quality(priv, &quality);
+       dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
+}
+
+static int xc4000_set_params(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *params)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+       unsigned int type;
+       int     ret = -EREMOTEIO;
+
+       dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
+
+       mutex_lock(&priv->lock);
+
+       if (fe->ops.info.type == FE_ATSC) {
+               dprintk(1, "%s() ATSC\n", __func__);
+               switch (params->u.vsb.modulation) {
+               case VSB_8:
+               case VSB_16:
+                       dprintk(1, "%s() VSB modulation\n", __func__);
+                       priv->rf_mode = XC_RF_MODE_AIR;
+                       priv->freq_hz = params->frequency - 1750000;
+                       priv->bandwidth = BANDWIDTH_6_MHZ;
+                       priv->video_standard = XC4000_DTV6;
+                       type = DTV6;
+                       break;
+               case QAM_64:
+               case QAM_256:
+               case QAM_AUTO:
+                       dprintk(1, "%s() QAM modulation\n", __func__);
+                       priv->rf_mode = XC_RF_MODE_CABLE;
+                       priv->freq_hz = params->frequency - 1750000;
+                       priv->bandwidth = BANDWIDTH_6_MHZ;
+                       priv->video_standard = XC4000_DTV6;
+                       type = DTV6;
+                       break;
+               default:
+                       ret = -EINVAL;
+                       goto fail;
+               }
+       } else if (fe->ops.info.type == FE_OFDM) {
+               dprintk(1, "%s() OFDM\n", __func__);
+               switch (params->u.ofdm.bandwidth) {
+               case BANDWIDTH_6_MHZ:
+                       priv->bandwidth = BANDWIDTH_6_MHZ;
+                       priv->video_standard = XC4000_DTV6;
+                       priv->freq_hz = params->frequency - 1750000;
+                       type = DTV6;
+                       break;
+               case BANDWIDTH_7_MHZ:
+                       priv->bandwidth = BANDWIDTH_7_MHZ;
+                       priv->video_standard = XC4000_DTV7;
+                       priv->freq_hz = params->frequency - 2250000;
+                       type = DTV7;
+                       break;
+               case BANDWIDTH_8_MHZ:
+                       priv->bandwidth = BANDWIDTH_8_MHZ;
+                       priv->video_standard = XC4000_DTV8;
+                       priv->freq_hz = params->frequency - 2750000;
+                       type = DTV8;
+                       break;
+               case BANDWIDTH_AUTO:
+                       if (params->frequency < 400000000) {
+                               priv->bandwidth = BANDWIDTH_7_MHZ;
+                               priv->freq_hz = params->frequency - 2250000;
+                       } else {
+                               priv->bandwidth = BANDWIDTH_8_MHZ;
+                               priv->freq_hz = params->frequency - 2750000;
+                       }
+                       priv->video_standard = XC4000_DTV7_8;
+                       type = DTV78;
+                       break;
+               default:
+                       printk(KERN_ERR "xc4000 bandwidth not set!\n");
+                       ret = -EINVAL;
+                       goto fail;
+               }
+               priv->rf_mode = XC_RF_MODE_AIR;
+       } else {
+               printk(KERN_ERR "xc4000 modulation type not supported!\n");
+               ret = -EINVAL;
+               goto fail;
+       }
+
+       dprintk(1, "%s() frequency=%d (compensated)\n",
+               __func__, priv->freq_hz);
+
+       /* Make sure the correct firmware type is loaded */
+       if (check_firmware(fe, type, 0, priv->if_khz) != 0)
+               goto fail;
+
+       ret = xc_set_signal_source(priv, priv->rf_mode);
+       if (ret != 0) {
+               printk(KERN_ERR "xc4000: xc_set_signal_source(%d) failed\n",
+                      priv->rf_mode);
+               goto fail;
+       } else {
+               u16     video_mode, audio_mode;
+               video_mode = xc4000_standard[priv->video_standard].video_mode;
+               audio_mode = xc4000_standard[priv->video_standard].audio_mode;
+               if (type == DTV6 && priv->firm_version != 0x0102)
+                       video_mode |= 0x0001;
+               ret = xc_set_tv_standard(priv, video_mode, audio_mode);
+               if (ret != 0) {
+                       printk(KERN_ERR "xc4000: xc_set_tv_standard failed\n");
+                       /* DJH - do not return when it fails... */
+                       /* goto fail; */
+               }
+       }
+
+       if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
+               ret = 0;
+       if (priv->dvb_amplitude != 0) {
+               if (xc_write_reg(priv, XREG_AMPLITUDE,
+                                (priv->firm_version != 0x0102 ||
+                                 priv->dvb_amplitude != 134 ?
+                                 priv->dvb_amplitude : 132)) != 0)
+                       ret = -EREMOTEIO;
+       }
+       if (priv->set_smoothedcvbs != 0) {
+               if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
+                       ret = -EREMOTEIO;
+       }
+       if (ret != 0) {
+               printk(KERN_ERR "xc4000: setting registers failed\n");
+               /* goto fail; */
+       }
+
+       xc_tune_channel(priv, priv->freq_hz);
+
+       ret = 0;
+
+fail:
+       mutex_unlock(&priv->lock);
+
+       return ret;
+}
+
+static int xc4000_set_analog_params(struct dvb_frontend *fe,
+       struct analog_parameters *params)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+       unsigned int type = 0;
+       int     ret = -EREMOTEIO;
+
+       if (params->mode == V4L2_TUNER_RADIO) {
+               dprintk(1, "%s() frequency=%d (in units of 62.5Hz)\n",
+                       __func__, params->frequency);
+
+               mutex_lock(&priv->lock);
+
+               params->std = 0;
+               priv->freq_hz = params->frequency * 125L / 2;
+
+               if (audio_std & XC4000_AUDIO_STD_INPUT1) {
+                       priv->video_standard = XC4000_FM_Radio_INPUT1;
+                       type = FM | INPUT1;
+               } else {
+                       priv->video_standard = XC4000_FM_Radio_INPUT2;
+                       type = FM | INPUT2;
+               }
+
+               goto tune_channel;
+       }
+
+       dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
+               __func__, params->frequency);
+
+       mutex_lock(&priv->lock);
+
+       /* params->frequency is in units of 62.5khz */
+       priv->freq_hz = params->frequency * 62500;
+
+       params->std &= V4L2_STD_ALL;
+       /* if std is not defined, choose one */
+       if (!params->std)
+               params->std = V4L2_STD_PAL_BG;
+
+       if (audio_std & XC4000_AUDIO_STD_MONO)
+               type = MONO;
+
+       if (params->std & V4L2_STD_MN) {
+               params->std = V4L2_STD_MN;
+               if (audio_std & XC4000_AUDIO_STD_MONO) {
+                       priv->video_standard = XC4000_MN_NTSC_PAL_Mono;
+               } else if (audio_std & XC4000_AUDIO_STD_A2) {
+                       params->std |= V4L2_STD_A2;
+                       priv->video_standard = XC4000_MN_NTSC_PAL_A2;
+               } else {
+                       params->std |= V4L2_STD_BTSC;
+                       priv->video_standard = XC4000_MN_NTSC_PAL_BTSC;
+               }
+               goto tune_channel;
+       }
+
+       if (params->std & V4L2_STD_PAL_BG) {
+               params->std = V4L2_STD_PAL_BG;
+               if (audio_std & XC4000_AUDIO_STD_MONO) {
+                       priv->video_standard = XC4000_BG_PAL_MONO;
+               } else if (!(audio_std & XC4000_AUDIO_STD_A2)) {
+                       if (!(audio_std & XC4000_AUDIO_STD_B)) {
+                               params->std |= V4L2_STD_NICAM_A;
+                               priv->video_standard = XC4000_BG_PAL_NICAM;
+                       } else {
+                               params->std |= V4L2_STD_NICAM_B;
+                               priv->video_standard = XC4000_BG_PAL_NICAM;
+                       }
+               } else {
+                       if (!(audio_std & XC4000_AUDIO_STD_B)) {
+                               params->std |= V4L2_STD_A2_A;
+                               priv->video_standard = XC4000_BG_PAL_A2;
+                       } else {
+                               params->std |= V4L2_STD_A2_B;
+                               priv->video_standard = XC4000_BG_PAL_A2;
+                       }
+               }
+               goto tune_channel;
+       }
+
+       if (params->std & V4L2_STD_PAL_I) {
+               /* default to NICAM audio standard */
+               params->std = V4L2_STD_PAL_I | V4L2_STD_NICAM;
+               if (audio_std & XC4000_AUDIO_STD_MONO)
+                       priv->video_standard = XC4000_I_PAL_NICAM_MONO;
+               else
+                       priv->video_standard = XC4000_I_PAL_NICAM;
+               goto tune_channel;
+       }
+
+       if (params->std & V4L2_STD_PAL_DK) {
+               params->std = V4L2_STD_PAL_DK;
+               if (audio_std & XC4000_AUDIO_STD_MONO) {
+                       priv->video_standard = XC4000_DK_PAL_MONO;
+               } else if (audio_std & XC4000_AUDIO_STD_A2) {
+                       params->std |= V4L2_STD_A2;
+                       priv->video_standard = XC4000_DK_PAL_A2;
+               } else {
+                       params->std |= V4L2_STD_NICAM;
+                       priv->video_standard = XC4000_DK_PAL_NICAM;
+               }
+               goto tune_channel;
+       }
+
+       if (params->std & V4L2_STD_SECAM_DK) {
+               /* default to A2 audio standard */
+               params->std = V4L2_STD_SECAM_DK | V4L2_STD_A2;
+               if (audio_std & XC4000_AUDIO_STD_L) {
+                       type = 0;
+                       priv->video_standard = XC4000_DK_SECAM_NICAM;
+               } else if (audio_std & XC4000_AUDIO_STD_MONO) {
+                       priv->video_standard = XC4000_DK_SECAM_A2MONO;
+               } else if (audio_std & XC4000_AUDIO_STD_K3) {
+                       params->std |= V4L2_STD_SECAM_K3;
+                       priv->video_standard = XC4000_DK_SECAM_A2LDK3;
+               } else {
+                       priv->video_standard = XC4000_DK_SECAM_A2DK1;
+               }
+               goto tune_channel;
+       }
+
+       if (params->std & V4L2_STD_SECAM_L) {
+               /* default to NICAM audio standard */
+               type = 0;
+               params->std = V4L2_STD_SECAM_L | V4L2_STD_NICAM;
+               priv->video_standard = XC4000_L_SECAM_NICAM;
+               goto tune_channel;
+       }
+
+       if (params->std & V4L2_STD_SECAM_LC) {
+               /* default to NICAM audio standard */
+               type = 0;
+               params->std = V4L2_STD_SECAM_LC | V4L2_STD_NICAM;
+               priv->video_standard = XC4000_LC_SECAM_NICAM;
+               goto tune_channel;
+       }
+
+tune_channel:
+       /* FIXME: it could be air. */
+       priv->rf_mode = XC_RF_MODE_CABLE;
+
+       if (check_firmware(fe, type, params->std,
+                          xc4000_standard[priv->video_standard].int_freq) != 0)
+               goto fail;
+
+       ret = xc_set_signal_source(priv, priv->rf_mode);
+       if (ret != 0) {
+               printk(KERN_ERR
+                      "xc4000: xc_set_signal_source(%d) failed\n",
+                      priv->rf_mode);
+               goto fail;
+       } else {
+               u16     video_mode, audio_mode;
+               video_mode = xc4000_standard[priv->video_standard].video_mode;
+               audio_mode = xc4000_standard[priv->video_standard].audio_mode;
+               if (priv->video_standard < XC4000_BG_PAL_A2) {
+                       if (type & NOGD)
+                               video_mode &= 0xFF7F;
+               } else if (priv->video_standard < XC4000_I_PAL_NICAM) {
+                       if (priv->firm_version == 0x0102)
+                               video_mode &= 0xFEFF;
+                       if (audio_std & XC4000_AUDIO_STD_B)
+                               video_mode |= 0x0080;
+               }
+               ret = xc_set_tv_standard(priv, video_mode, audio_mode);
+               if (ret != 0) {
+                       printk(KERN_ERR "xc4000: xc_set_tv_standard failed\n");
+                       goto fail;
+               }
+       }
+
+       if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
+               ret = 0;
+       if (xc_write_reg(priv, XREG_AMPLITUDE, 1) != 0)
+               ret = -EREMOTEIO;
+       if (priv->set_smoothedcvbs != 0) {
+               if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
+                       ret = -EREMOTEIO;
+       }
+       if (ret != 0) {
+               printk(KERN_ERR "xc4000: setting registers failed\n");
+               goto fail;
+       }
+
+       xc_tune_channel(priv, priv->freq_hz);
+
+       ret = 0;
+
+fail:
+       mutex_unlock(&priv->lock);
+
+       return ret;
+}
+
+static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+
+       *freq = priv->freq_hz;
+
+       if (debug) {
+               mutex_lock(&priv->lock);
+               if ((priv->cur_fw.type
+                    & (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) {
+                       u16     snr = 0;
+                       if (xc4000_readreg(priv, XREG_SNR, &snr) == 0) {
+                               mutex_unlock(&priv->lock);
+                               dprintk(1, "%s() freq = %u, SNR = %d\n",
+                                       __func__, *freq, snr);
+                               return 0;
+                       }
+               }
+               mutex_unlock(&priv->lock);
+       }
+
+       dprintk(1, "%s()\n", __func__);
+
+       return 0;
+}
+
+static int xc4000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+       dprintk(1, "%s()\n", __func__);
+
+       *bw = priv->bandwidth;
+       return 0;
+}
+
+static int xc4000_get_status(struct dvb_frontend *fe, u32 *status)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+       u16     lock_status = 0;
+
+       mutex_lock(&priv->lock);
+
+       if (priv->cur_fw.type & BASE)
+               xc_get_lock_status(priv, &lock_status);
+
+       *status = (lock_status == 1 ?
+                  TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO : 0);
+       if (priv->cur_fw.type & (DTV6 | DTV7 | DTV78 | DTV8))
+               *status &= (~TUNER_STATUS_STEREO);
+
+       mutex_unlock(&priv->lock);
+
+       dprintk(2, "%s() lock_status = %d\n", __func__, lock_status);
+
+       return 0;
+}
+
+static int xc4000_sleep(struct dvb_frontend *fe)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+       int     ret = 0;
+
+       dprintk(1, "%s()\n", __func__);
+
+       mutex_lock(&priv->lock);
+
+       /* Avoid firmware reload on slow devices */
+       if ((no_poweroff == 2 ||
+            (no_poweroff == 0 && priv->default_pm != 0)) &&
+           (priv->cur_fw.type & BASE) != 0) {
+               /* force reset and firmware reload */
+               priv->cur_fw.type = XC_POWERED_DOWN;
+
+               if (xc_write_reg(priv, XREG_POWER_DOWN, 0) != 0) {
+                       printk(KERN_ERR
+                              "xc4000: %s() unable to shutdown tuner\n",
+                              __func__);
+                       ret = -EREMOTEIO;
+               }
+               msleep(20);
+       }
+
+       mutex_unlock(&priv->lock);
+
+       return ret;
+}
+
+static int xc4000_init(struct dvb_frontend *fe)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       return 0;
+}
+
+static int xc4000_release(struct dvb_frontend *fe)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+
+       dprintk(1, "%s()\n", __func__);
+
+       mutex_lock(&xc4000_list_mutex);
+
+       if (priv)
+               hybrid_tuner_release_state(priv);
+
+       mutex_unlock(&xc4000_list_mutex);
+
+       fe->tuner_priv = NULL;
+
+       return 0;
+}
+
+static const struct dvb_tuner_ops xc4000_tuner_ops = {
+       .info = {
+               .name           = "Xceive XC4000",
+               .frequency_min  =    1000000,
+               .frequency_max  = 1023000000,
+               .frequency_step =      50000,
+       },
+
+       .release           = xc4000_release,
+       .init              = xc4000_init,
+       .sleep             = xc4000_sleep,
+
+       .set_params        = xc4000_set_params,
+       .set_analog_params = xc4000_set_analog_params,
+       .get_frequency     = xc4000_get_frequency,
+       .get_bandwidth     = xc4000_get_bandwidth,
+       .get_status        = xc4000_get_status
+};
+
+struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
+                                  struct i2c_adapter *i2c,
+                                  struct xc4000_config *cfg)
+{
+       struct xc4000_priv *priv = NULL;
+       int     instance;
+       u16     id = 0;
+
+       dprintk(1, "%s(%d-%04x)\n", __func__,
+               i2c ? i2c_adapter_id(i2c) : -1,
+               cfg ? cfg->i2c_address : -1);
+
+       mutex_lock(&xc4000_list_mutex);
+
+       instance = hybrid_tuner_request_state(struct xc4000_priv, priv,
+                                             hybrid_tuner_instance_list,
+                                             i2c, cfg->i2c_address, "xc4000");
+       switch (instance) {
+       case 0:
+               goto fail;
+               break;
+       case 1:
+               /* new tuner instance */
+               priv->bandwidth = BANDWIDTH_6_MHZ;
+               /* set default configuration */
+               priv->if_khz = 4560;
+               priv->default_pm = 0;
+               priv->dvb_amplitude = 134;
+               priv->set_smoothedcvbs = 1;
+               mutex_init(&priv->lock);
+               fe->tuner_priv = priv;
+               break;
+       default:
+               /* existing tuner instance */
+               fe->tuner_priv = priv;
+               break;
+       }
+
+       if (cfg->if_khz != 0) {
+               /* copy configuration if provided by the caller */
+               priv->if_khz = cfg->if_khz;
+               priv->default_pm = cfg->default_pm;
+               priv->dvb_amplitude = cfg->dvb_amplitude;
+               priv->set_smoothedcvbs = cfg->set_smoothedcvbs;
+       }
+
+       /* Check if firmware has been loaded. It is possible that another
+          instance of the driver has loaded the firmware.
+        */
+
+       if (instance == 1) {
+               if (xc4000_readreg(priv, XREG_PRODUCT_ID, &id) != 0)
+                       goto fail;
+       } else {
+               id = ((priv->cur_fw.type & BASE) != 0 ?
+                     priv->hwmodel : XC_PRODUCT_ID_FW_NOT_LOADED);
+       }
+
+       switch (id) {
+       case XC_PRODUCT_ID_XC4000:
+       case XC_PRODUCT_ID_XC4100:
+               printk(KERN_INFO
+                       "xc4000: Successfully identified at address 0x%02x\n",
+                       cfg->i2c_address);
+               printk(KERN_INFO
+                       "xc4000: Firmware has been loaded previously\n");
+               break;
+       case XC_PRODUCT_ID_FW_NOT_LOADED:
+               printk(KERN_INFO
+                       "xc4000: Successfully identified at address 0x%02x\n",
+                       cfg->i2c_address);
+               printk(KERN_INFO
+                       "xc4000: Firmware has not been loaded previously\n");
+               break;
+       default:
+               printk(KERN_ERR
+                       "xc4000: Device not found at addr 0x%02x (0x%x)\n",
+                       cfg->i2c_address, id);
+               goto fail;
+       }
+
+       mutex_unlock(&xc4000_list_mutex);
+
+       memcpy(&fe->ops.tuner_ops, &xc4000_tuner_ops,
+               sizeof(struct dvb_tuner_ops));
+
+       if (instance == 1) {
+               int     ret;
+               mutex_lock(&priv->lock);
+               ret = xc4000_fwupload(fe);
+               mutex_unlock(&priv->lock);
+               if (ret != 0)
+                       goto fail2;
+       }
+
+       return fe;
+fail:
+       mutex_unlock(&xc4000_list_mutex);
+fail2:
+       xc4000_release(fe);
+       return NULL;
+}
+EXPORT_SYMBOL(xc4000_attach);
+
+MODULE_AUTHOR("Steven Toth, Davide Ferri");
+MODULE_DESCRIPTION("Xceive xc4000 silicon tuner driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/xc4000.h b/drivers/media/common/tuners/xc4000.h
new file mode 100644 (file)
index 0000000..e6a44d1
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  Driver for Xceive XC4000 "QAM/8VSB single chip tuner"
+ *
+ *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __XC4000_H__
+#define __XC4000_H__
+
+#include <linux/firmware.h>
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+struct xc4000_config {
+       u8      i2c_address;
+       /* if non-zero, power management is enabled by default */
+       u8      default_pm;
+       /* value to be written to XREG_AMPLITUDE in DVB-T mode (0: no write) */
+       u8      dvb_amplitude;
+       /* if non-zero, register 0x0E is set to filter analog TV video output */
+       u8      set_smoothedcvbs;
+       /* IF for DVB-T */
+       u32     if_khz;
+};
+
+/* xc4000 callback command */
+#define XC4000_TUNER_RESET             0
+
+/* For each bridge framework, when it attaches either analog or digital,
+ * it has to store a reference back to its _core equivalent structure,
+ * so that it can service the hardware by steering gpio's etc.
+ * Each bridge implementation is different so cast devptr accordingly.
+ * The xc4000 driver cares not for this value, other than ensuring
+ * it's passed back to a bridge during tuner_callback().
+ */
+
+#if defined(CONFIG_MEDIA_TUNER_XC4000) || (defined(CONFIG_MEDIA_TUNER_XC4000_MODULE) && defined(MODULE))
+extern struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
+                                         struct i2c_adapter *i2c,
+                                         struct xc4000_config *cfg);
+#else
+static inline struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
+                                                struct i2c_adapter *i2c,
+                                                struct xc4000_config *cfg)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif
+
+#endif
index ee214c3..f6e40b3 100644 (file)
@@ -80,6 +80,10 @@ comment "Supported nGene Adapters"
        depends on DVB_CORE && PCI && I2C
        source "drivers/media/dvb/ngene/Kconfig"
 
+comment "Supported ddbridge ('Octopus') Adapters"
+       depends on DVB_CORE && PCI && I2C
+       source "drivers/media/dvb/ddbridge/Kconfig"
+
 comment "Supported DVB Frontends"
        depends on DVB_CORE
 source "drivers/media/dvb/frontends/Kconfig"
index a1a0875..b2cefe6 100644 (file)
@@ -15,6 +15,7 @@ obj-y        := dvb-core/     \
                dm1105/         \
                pt1/            \
                mantis/         \
-               ngene/
+               ngene/          \
+               ddbridge/
 
 obj-$(CONFIG_DVB_FIREDTV)      += firewire/
index 1e1106d..521d691 100644 (file)
@@ -892,7 +892,7 @@ static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
        if (!(bttv_pci_dev = bttv_get_pcidev(card->bttv_nr))) {
                printk("dvb_bt8xx: no pci device for card %d\n", card->bttv_nr);
                kfree(card);
-               return -EFAULT;
+               return -ENODEV;
        }
 
        if (!(card->bt = dvb_bt8xx_878_match(card->bttv_nr, bttv_pci_dev))) {
@@ -902,7 +902,7 @@ static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
                       "installed, try removing it.\n");
 
                kfree(card);
-               return -EFAULT;
+               return -ENODEV;
        }
 
        mutex_init(&card->bt->gpio_lock);
diff --git a/drivers/media/dvb/ddbridge/Kconfig b/drivers/media/dvb/ddbridge/Kconfig
new file mode 100644 (file)
index 0000000..d099e1a
--- /dev/null
@@ -0,0 +1,18 @@
+config DVB_DDBRIDGE
+       tristate "Digital Devices bridge support"
+       depends on DVB_CORE && PCI && I2C
+       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+       select DVB_STV6110x if !DVB_FE_CUSTOMISE
+       select DVB_STV090x if !DVB_FE_CUSTOMISE
+       select DVB_DRXK if !DVB_FE_CUSTOMISE
+       select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
+       ---help---
+         Support for cards with the Digital Devices PCI express bridge:
+         - Octopus PCIe Bridge
+         - Octopus mini PCIe Bridge
+         - Octopus LE
+         - DuoFlex S2 Octopus
+         - DuoFlex CT Octopus
+         - cineS2(v6)
+
+         Say Y if you own such a card and want to use it.
diff --git a/drivers/media/dvb/ddbridge/Makefile b/drivers/media/dvb/ddbridge/Makefile
new file mode 100644 (file)
index 0000000..de4fe19
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Makefile for the ddbridge device driver
+#
+
+ddbridge-objs := ddbridge-core.o
+
+obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
+EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+
+# For the staging CI driver cxd2099
+EXTRA_CFLAGS += -Idrivers/staging/cxd2099/
diff --git a/drivers/media/dvb/ddbridge/ddbridge-core.c b/drivers/media/dvb/ddbridge/ddbridge-core.c
new file mode 100644 (file)
index 0000000..573d540
--- /dev/null
@@ -0,0 +1,1719 @@
+/*
+ * ddbridge.c: Digital Devices PCIe bridge driver
+ *
+ * Copyright (C) 2010-2011 Digital Devices GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * 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
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/timer.h>
+#include <linux/version.h>
+#include <linux/i2c.h>
+#include <linux/swab.h>
+#include <linux/vmalloc.h>
+#include "ddbridge.h"
+
+#include "ddbridge-regs.h"
+
+#include "tda18271c2dd.h"
+#include "stv6110x.h"
+#include "stv090x.h"
+#include "lnbh24.h"
+#include "drxk.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+/* MSI had problems with lost interrupts, fixed but needs testing */
+#undef CONFIG_PCI_MSI
+
+/******************************************************************************/
+
+static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
+{
+       struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
+                                  .buf  = val,  .len   = 1 } };
+       return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
+}
+
+static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
+{
+       struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
+                                  .buf  = &reg, .len   = 1 },
+                                 {.addr = adr,  .flags = I2C_M_RD,
+                                  .buf  = val,  .len   = 1 } };
+       return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
+                         u16 reg, u8 *val)
+{
+       u8 msg[2] = {reg>>8, reg&0xff};
+       struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+                                  .buf  = msg, .len   = 2},
+                                 {.addr = adr, .flags = I2C_M_RD,
+                                  .buf  = val, .len   = 1} };
+       return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
+{
+       struct ddb *dev = i2c->dev;
+       int stat;
+       u32 val;
+
+       i2c->done = 0;
+       ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND);
+       stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ);
+       if (stat <= 0) {
+               printk(KERN_ERR "I2C timeout\n");
+               { /* MSI debugging*/
+                       u32 istat = ddbreadl(INTERRUPT_STATUS);
+                       printk(KERN_ERR "IRS %08x\n", istat);
+                       ddbwritel(istat, INTERRUPT_ACK);
+               }
+               return -EIO;
+       }
+       val = ddbreadl(i2c->regs+I2C_COMMAND);
+       if (val & 0x70000)
+               return -EIO;
+       return 0;
+}
+
+static int ddb_i2c_master_xfer(struct i2c_adapter *adapter,
+                              struct i2c_msg msg[], int num)
+{
+       struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter);
+       struct ddb *dev = i2c->dev;
+       u8 addr = 0;
+
+       if (num)
+               addr = msg[0].addr;
+
+       if (num == 2 && msg[1].flags & I2C_M_RD &&
+           !(msg[0].flags & I2C_M_RD)) {
+               memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf,
+                           msg[0].buf, msg[0].len);
+               ddbwritel(msg[0].len|(msg[1].len << 16),
+                         i2c->regs+I2C_TASKLENGTH);
+               if (!ddb_i2c_cmd(i2c, addr, 1)) {
+                       memcpy_fromio(msg[1].buf,
+                                     dev->regs + I2C_TASKMEM_BASE + i2c->rbuf,
+                                     msg[1].len);
+                       return num;
+               }
+       }
+
+       if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
+               ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len);
+               ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH);
+               if (!ddb_i2c_cmd(i2c, addr, 2))
+                       return num;
+       }
+       if (num == 1 && (msg[0].flags & I2C_M_RD)) {
+               ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
+               if (!ddb_i2c_cmd(i2c, addr, 3)) {
+                       ddbcpyfrom(msg[0].buf,
+                                  I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
+                       return num;
+               }
+       }
+       return -EIO;
+}
+
+
+static u32 ddb_i2c_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL;
+}
+
+struct i2c_algorithm ddb_i2c_algo = {
+       .master_xfer   = ddb_i2c_master_xfer,
+       .functionality = ddb_i2c_functionality,
+};
+
+static void ddb_i2c_release(struct ddb *dev)
+{
+       int i;
+       struct ddb_i2c *i2c;
+       struct i2c_adapter *adap;
+
+       for (i = 0; i < dev->info->port_num; i++) {
+               i2c = &dev->i2c[i];
+               adap = &i2c->adap;
+               i2c_del_adapter(adap);
+       }
+}
+
+static int ddb_i2c_init(struct ddb *dev)
+{
+       int i, j, stat = 0;
+       struct ddb_i2c *i2c;
+       struct i2c_adapter *adap;
+
+       for (i = 0; i < dev->info->port_num; i++) {
+               i2c = &dev->i2c[i];
+               i2c->dev = dev;
+               i2c->nr = i;
+               i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4);
+               i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8);
+               i2c->regs = 0x80 + i * 0x20;
+               ddbwritel(I2C_SPEED_100, i2c->regs + I2C_TIMING);
+               ddbwritel((i2c->rbuf << 16) | i2c->wbuf,
+                         i2c->regs + I2C_TASKADDRESS);
+               init_waitqueue_head(&i2c->wq);
+
+               adap = &i2c->adap;
+               i2c_set_adapdata(adap, i2c);
+#ifdef I2C_ADAP_CLASS_TV_DIGITAL
+               adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
+#else
+#ifdef I2C_CLASS_TV_ANALOG
+               adap->class = I2C_CLASS_TV_ANALOG;
+#endif
+#endif
+               strcpy(adap->name, "ddbridge");
+               adap->algo = &ddb_i2c_algo;
+               adap->algo_data = (void *)i2c;
+               adap->dev.parent = &dev->pdev->dev;
+               stat = i2c_add_adapter(adap);
+               if (stat)
+                       break;
+       }
+       if (stat)
+               for (j = 0; j < i; j++) {
+                       i2c = &dev->i2c[j];
+                       adap = &i2c->adap;
+                       i2c_del_adapter(adap);
+               }
+       return stat;
+}
+
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+#if 0
+static void set_table(struct ddb *dev, u32 off,
+                     dma_addr_t *pbuf, u32 num)
+{
+       u32 i, base;
+       u64 mem;
+
+       base = DMA_BASE_ADDRESS_TABLE + off;
+       for (i = 0; i < num; i++) {
+               mem = pbuf[i];
+               ddbwritel(mem & 0xffffffff, base + i * 8);
+               ddbwritel(mem >> 32, base + i * 8 + 4);
+       }
+}
+#endif
+
+static void ddb_address_table(struct ddb *dev)
+{
+       u32 i, j, base;
+       u64 mem;
+       dma_addr_t *pbuf;
+
+       for (i = 0; i < dev->info->port_num * 2; i++) {
+               base = DMA_BASE_ADDRESS_TABLE + i * 0x100;
+               pbuf = dev->input[i].pbuf;
+               for (j = 0; j < dev->input[i].dma_buf_num; j++) {
+                       mem = pbuf[j];
+                       ddbwritel(mem & 0xffffffff, base + j * 8);
+                       ddbwritel(mem >> 32, base + j * 8 + 4);
+               }
+       }
+       for (i = 0; i < dev->info->port_num; i++) {
+               base = DMA_BASE_ADDRESS_TABLE + 0x800 + i * 0x100;
+               pbuf = dev->output[i].pbuf;
+               for (j = 0; j < dev->output[i].dma_buf_num; j++) {
+                       mem = pbuf[j];
+                       ddbwritel(mem & 0xffffffff, base + j * 8);
+                       ddbwritel(mem >> 32, base + j * 8 + 4);
+               }
+       }
+}
+
+static void io_free(struct pci_dev *pdev, u8 **vbuf,
+                   dma_addr_t *pbuf, u32 size, int num)
+{
+       int i;
+
+       for (i = 0; i < num; i++) {
+               if (vbuf[i]) {
+                       pci_free_consistent(pdev, size, vbuf[i], pbuf[i]);
+                       vbuf[i] = 0;
+               }
+       }
+}
+
+static int io_alloc(struct pci_dev *pdev, u8 **vbuf,
+                   dma_addr_t *pbuf, u32 size, int num)
+{
+       int i;
+
+       for (i = 0; i < num; i++) {
+               vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]);
+               if (!vbuf[i])
+                       return -ENOMEM;
+       }
+       return 0;
+}
+
+static int ddb_buffers_alloc(struct ddb *dev)
+{
+       int i;
+       struct ddb_port *port;
+
+       for (i = 0; i < dev->info->port_num; i++) {
+               port = &dev->port[i];
+               switch (port->class) {
+               case DDB_PORT_TUNER:
+                       if (io_alloc(dev->pdev, port->input[0]->vbuf,
+                                    port->input[0]->pbuf,
+                                    port->input[0]->dma_buf_size,
+                                    port->input[0]->dma_buf_num) < 0)
+                               return -1;
+                       if (io_alloc(dev->pdev, port->input[1]->vbuf,
+                                    port->input[1]->pbuf,
+                                    port->input[1]->dma_buf_size,
+                                    port->input[1]->dma_buf_num) < 0)
+                               return -1;
+                       break;
+               case DDB_PORT_CI:
+                       if (io_alloc(dev->pdev, port->input[0]->vbuf,
+                                    port->input[0]->pbuf,
+                                    port->input[0]->dma_buf_size,
+                                    port->input[0]->dma_buf_num) < 0)
+                               return -1;
+                       if (io_alloc(dev->pdev, port->output->vbuf,
+                                    port->output->pbuf,
+                                    port->output->dma_buf_size,
+                                    port->output->dma_buf_num) < 0)
+                               return -1;
+                       break;
+               default:
+                       break;
+               }
+       }
+       ddb_address_table(dev);
+       return 0;
+}
+
+static void ddb_buffers_free(struct ddb *dev)
+{
+       int i;
+       struct ddb_port *port;
+
+       for (i = 0; i < dev->info->port_num; i++) {
+               port = &dev->port[i];
+               io_free(dev->pdev, port->input[0]->vbuf,
+                       port->input[0]->pbuf,
+                       port->input[0]->dma_buf_size,
+                       port->input[0]->dma_buf_num);
+               io_free(dev->pdev, port->input[1]->vbuf,
+                       port->input[1]->pbuf,
+                       port->input[1]->dma_buf_size,
+                       port->input[1]->dma_buf_num);
+               io_free(dev->pdev, port->output->vbuf,
+                       port->output->pbuf,
+                       port->output->dma_buf_size,
+                       port->output->dma_buf_num);
+       }
+}
+
+static void ddb_input_start(struct ddb_input *input)
+{
+       struct ddb *dev = input->port->dev;
+
+       spin_lock_irq(&input->lock);
+       input->cbuf = 0;
+       input->coff = 0;
+
+       /* reset */
+       ddbwritel(0, TS_INPUT_CONTROL(input->nr));
+       ddbwritel(2, TS_INPUT_CONTROL(input->nr));
+       ddbwritel(0, TS_INPUT_CONTROL(input->nr));
+
+       ddbwritel((1 << 16) |
+                 (input->dma_buf_num << 11) |
+                 (input->dma_buf_size >> 7),
+                 DMA_BUFFER_SIZE(input->nr));
+       ddbwritel(0, DMA_BUFFER_ACK(input->nr));
+
+       ddbwritel(1, DMA_BASE_WRITE);
+       ddbwritel(3, DMA_BUFFER_CONTROL(input->nr));
+       ddbwritel(9, TS_INPUT_CONTROL(input->nr));
+       input->running = 1;
+       spin_unlock_irq(&input->lock);
+}
+
+static void ddb_input_stop(struct ddb_input *input)
+{
+       struct ddb *dev = input->port->dev;
+
+       spin_lock_irq(&input->lock);
+       ddbwritel(0, TS_INPUT_CONTROL(input->nr));
+       ddbwritel(0, DMA_BUFFER_CONTROL(input->nr));
+       input->running = 0;
+       spin_unlock_irq(&input->lock);
+}
+
+static void ddb_output_start(struct ddb_output *output)
+{
+       struct ddb *dev = output->port->dev;
+
+       spin_lock_irq(&output->lock);
+       output->cbuf = 0;
+       output->coff = 0;
+       ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
+       ddbwritel(2, TS_OUTPUT_CONTROL(output->nr));
+       ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
+       ddbwritel(0x3c, TS_OUTPUT_CONTROL(output->nr));
+       ddbwritel((1 << 16) |
+                 (output->dma_buf_num << 11) |
+                 (output->dma_buf_size >> 7),
+                 DMA_BUFFER_SIZE(output->nr + 8));
+       ddbwritel(0, DMA_BUFFER_ACK(output->nr + 8));
+
+       ddbwritel(1, DMA_BASE_READ);
+       ddbwritel(3, DMA_BUFFER_CONTROL(output->nr + 8));
+       /* ddbwritel(0xbd, TS_OUTPUT_CONTROL(output->nr)); */
+       ddbwritel(0x1d, TS_OUTPUT_CONTROL(output->nr));
+       output->running = 1;
+       spin_unlock_irq(&output->lock);
+}
+
+static void ddb_output_stop(struct ddb_output *output)
+{
+       struct ddb *dev = output->port->dev;
+
+       spin_lock_irq(&output->lock);
+       ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
+       ddbwritel(0, DMA_BUFFER_CONTROL(output->nr + 8));
+       output->running = 0;
+       spin_unlock_irq(&output->lock);
+}
+
+static u32 ddb_output_free(struct ddb_output *output)
+{
+       u32 idx, off, stat = output->stat;
+       s32 diff;
+
+       idx = (stat >> 11) & 0x1f;
+       off = (stat & 0x7ff) << 7;
+
+       if (output->cbuf != idx) {
+               if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
+                   (output->dma_buf_size - output->coff <= 188))
+                       return 0;
+               return 188;
+       }
+       diff = off - output->coff;
+       if (diff <= 0 || diff > 188)
+               return 188;
+       return 0;
+}
+
+static ssize_t ddb_output_write(struct ddb_output *output,
+                               const u8 *buf, size_t count)
+{
+       struct ddb *dev = output->port->dev;
+       u32 idx, off, stat = output->stat;
+       u32 left = count, len;
+
+       idx = (stat >> 11) & 0x1f;
+       off = (stat & 0x7ff) << 7;
+
+       while (left) {
+               len = output->dma_buf_size - output->coff;
+               if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
+                   (off == 0)) {
+                       if (len <= 188)
+                               break;
+                       len -= 188;
+               }
+               if (output->cbuf == idx) {
+                       if (off > output->coff) {
+#if 1
+                               len = off - output->coff;
+                               len -= (len % 188);
+                               if (len <= 188)
+
+#endif
+                                       break;
+                               len -= 188;
+                       }
+               }
+               if (len > left)
+                       len = left;
+               if (copy_from_user(output->vbuf[output->cbuf] + output->coff,
+                                  buf, len))
+                       return -EIO;
+               left -= len;
+               buf += len;
+               output->coff += len;
+               if (output->coff == output->dma_buf_size) {
+                       output->coff = 0;
+                       output->cbuf = ((output->cbuf + 1) % output->dma_buf_num);
+               }
+               ddbwritel((output->cbuf << 11) | (output->coff >> 7),
+                         DMA_BUFFER_ACK(output->nr + 8));
+       }
+       return count - left;
+}
+
+static u32 ddb_input_avail(struct ddb_input *input)
+{
+       struct ddb *dev = input->port->dev;
+       u32 idx, off, stat = input->stat;
+       u32 ctrl = ddbreadl(DMA_BUFFER_CONTROL(input->nr));
+
+       idx = (stat >> 11) & 0x1f;
+       off = (stat & 0x7ff) << 7;
+
+       if (ctrl & 4) {
+               printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl);
+               ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr));
+               return 0;
+       }
+       if (input->cbuf != idx)
+               return 188;
+       return 0;
+}
+
+static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
+{
+       struct ddb *dev = input->port->dev;
+       u32 left = count;
+       u32 idx, off, free, stat = input->stat;
+       int ret;
+
+       idx = (stat >> 11) & 0x1f;
+       off = (stat & 0x7ff) << 7;
+
+       while (left) {
+               if (input->cbuf == idx)
+                       return count - left;
+               free = input->dma_buf_size - input->coff;
+               if (free > left)
+                       free = left;
+               ret = copy_to_user(buf, input->vbuf[input->cbuf] +
+                                  input->coff, free);
+               input->coff += free;
+               if (input->coff == input->dma_buf_size) {
+                       input->coff = 0;
+                       input->cbuf = (input->cbuf+1) % input->dma_buf_num;
+               }
+               left -= free;
+               ddbwritel((input->cbuf << 11) | (input->coff >> 7),
+                         DMA_BUFFER_ACK(input->nr));
+       }
+       return count;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+#if 0
+static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe)
+{
+       int i;
+
+       for (i = 0; i < dev->info->port_num * 2; i++) {
+               if (dev->input[i].fe == fe)
+                       return &dev->input[i];
+       }
+       return NULL;
+}
+#endif
+
+static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct ddb_input *input = fe->sec_priv;
+       struct ddb_port *port = input->port;
+       int status;
+
+       if (enable) {
+               mutex_lock(&port->i2c_gate_lock);
+               status = input->gate_ctrl(fe, 1);
+       } else {
+               status = input->gate_ctrl(fe, 0);
+               mutex_unlock(&port->i2c_gate_lock);
+       }
+       return status;
+}
+
+static int demod_attach_drxk(struct ddb_input *input)
+{
+       struct i2c_adapter *i2c = &input->port->i2c->adap;
+       struct dvb_frontend *fe;
+       struct drxk_config config;
+
+       memset(&config, 0, sizeof(config));
+       config.adr = 0x29 + (input->nr & 1);
+
+       fe = input->fe = dvb_attach(drxk_attach, &config, i2c, &input->fe2);
+       if (!input->fe) {
+               printk(KERN_ERR "No DRXK found!\n");
+               return -ENODEV;
+       }
+       fe->sec_priv = input;
+       input->gate_ctrl = fe->ops.i2c_gate_ctrl;
+       fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+       return 0;
+}
+
+static int tuner_attach_tda18271(struct ddb_input *input)
+{
+       struct i2c_adapter *i2c = &input->port->i2c->adap;
+       struct dvb_frontend *fe;
+
+       if (input->fe->ops.i2c_gate_ctrl)
+               input->fe->ops.i2c_gate_ctrl(input->fe, 1);
+       fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60);
+       if (!fe) {
+               printk(KERN_ERR "No TDA18271 found!\n");
+               return -ENODEV;
+       }
+       if (input->fe->ops.i2c_gate_ctrl)
+               input->fe->ops.i2c_gate_ctrl(input->fe, 0);
+       return 0;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+static struct stv090x_config stv0900 = {
+       .device         = STV0900,
+       .demod_mode     = STV090x_DUAL,
+       .clk_mode       = STV090x_CLK_EXT,
+
+       .xtal           = 27000000,
+       .address        = 0x69,
+
+       .ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+       .ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+
+       .repeater_level = STV090x_RPTLEVEL_16,
+
+       .adc1_range     = STV090x_ADC_1Vpp,
+       .adc2_range     = STV090x_ADC_1Vpp,
+
+       .diseqc_envelope_mode = true,
+};
+
+static struct stv090x_config stv0900_aa = {
+       .device         = STV0900,
+       .demod_mode     = STV090x_DUAL,
+       .clk_mode       = STV090x_CLK_EXT,
+
+       .xtal           = 27000000,
+       .address        = 0x68,
+
+       .ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+       .ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+
+       .repeater_level = STV090x_RPTLEVEL_16,
+
+       .adc1_range     = STV090x_ADC_1Vpp,
+       .adc2_range     = STV090x_ADC_1Vpp,
+
+       .diseqc_envelope_mode = true,
+};
+
+static struct stv6110x_config stv6110a = {
+       .addr    = 0x60,
+       .refclk  = 27000000,
+       .clk_div = 1,
+};
+
+static struct stv6110x_config stv6110b = {
+       .addr    = 0x63,
+       .refclk  = 27000000,
+       .clk_div = 1,
+};
+
+static int demod_attach_stv0900(struct ddb_input *input, int type)
+{
+       struct i2c_adapter *i2c = &input->port->i2c->adap;
+       struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
+
+       input->fe = dvb_attach(stv090x_attach, feconf, i2c,
+                              (input->nr & 1) ? STV090x_DEMODULATOR_1
+                              : STV090x_DEMODULATOR_0);
+       if (!input->fe) {
+               printk(KERN_ERR "No STV0900 found!\n");
+               return -ENODEV;
+       }
+       if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0,
+                       0, (input->nr & 1) ?
+                       (0x09 - type) : (0x0b - type))) {
+               printk(KERN_ERR "No LNBH24 found!\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static int tuner_attach_stv6110(struct ddb_input *input, int type)
+{
+       struct i2c_adapter *i2c = &input->port->i2c->adap;
+       struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
+       struct stv6110x_config *tunerconf = (input->nr & 1) ?
+               &stv6110b : &stv6110a;
+       struct stv6110x_devctl *ctl;
+
+       ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c);
+       if (!ctl) {
+               printk(KERN_ERR "No STV6110X found!\n");
+               return -ENODEV;
+       }
+       printk(KERN_INFO "attach tuner input %d adr %02x\n",
+                        input->nr, tunerconf->addr);
+
+       feconf->tuner_init          = ctl->tuner_init;
+       feconf->tuner_sleep         = ctl->tuner_sleep;
+       feconf->tuner_set_mode      = ctl->tuner_set_mode;
+       feconf->tuner_set_frequency = ctl->tuner_set_frequency;
+       feconf->tuner_get_frequency = ctl->tuner_get_frequency;
+       feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
+       feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
+       feconf->tuner_set_bbgain    = ctl->tuner_set_bbgain;
+       feconf->tuner_get_bbgain    = ctl->tuner_get_bbgain;
+       feconf->tuner_set_refclk    = ctl->tuner_set_refclk;
+       feconf->tuner_get_status    = ctl->tuner_get_status;
+
+       return 0;
+}
+
+static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
+                           int (*start_feed)(struct dvb_demux_feed *),
+                           int (*stop_feed)(struct dvb_demux_feed *),
+                           void *priv)
+{
+       dvbdemux->priv = priv;
+
+       dvbdemux->filternum = 256;
+       dvbdemux->feednum = 256;
+       dvbdemux->start_feed = start_feed;
+       dvbdemux->stop_feed = stop_feed;
+       dvbdemux->write_to_decoder = NULL;
+       dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+                                     DMX_SECTION_FILTERING |
+                                     DMX_MEMORY_BASED_FILTERING);
+       return dvb_dmx_init(dvbdemux);
+}
+
+static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
+                              struct dvb_demux *dvbdemux,
+                              struct dmx_frontend *hw_frontend,
+                              struct dmx_frontend *mem_frontend,
+                              struct dvb_adapter *dvb_adapter)
+{
+       int ret;
+
+       dmxdev->filternum = 256;
+       dmxdev->demux = &dvbdemux->dmx;
+       dmxdev->capabilities = 0;
+       ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
+       if (ret < 0)
+               return ret;
+
+       hw_frontend->source = DMX_FRONTEND_0;
+       dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
+       mem_frontend->source = DMX_MEMORY_FE;
+       dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
+       return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
+}
+
+static int start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+       struct ddb_input *input = dvbdmx->priv;
+
+       if (!input->users)
+               ddb_input_start(input);
+
+       return ++input->users;
+}
+
+static int stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+       struct ddb_input *input = dvbdmx->priv;
+
+       if (--input->users)
+               return input->users;
+
+       ddb_input_stop(input);
+       return 0;
+}
+
+
+static void dvb_input_detach(struct ddb_input *input)
+{
+       struct dvb_adapter *adap = &input->adap;
+       struct dvb_demux *dvbdemux = &input->demux;
+
+       switch (input->attached) {
+       case 5:
+               if (input->fe2)
+                       dvb_unregister_frontend(input->fe2);
+               if (input->fe) {
+                       dvb_unregister_frontend(input->fe);
+                       dvb_frontend_detach(input->fe);
+                       input->fe = NULL;
+               }
+       case 4:
+               dvb_net_release(&input->dvbnet);
+
+       case 3:
+               dvbdemux->dmx.close(&dvbdemux->dmx);
+               dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
+                                             &input->hw_frontend);
+               dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
+                                             &input->mem_frontend);
+               dvb_dmxdev_release(&input->dmxdev);
+
+       case 2:
+               dvb_dmx_release(&input->demux);
+
+       case 1:
+               dvb_unregister_adapter(adap);
+       }
+       input->attached = 0;
+}
+
+static int dvb_input_attach(struct ddb_input *input)
+{
+       int ret;
+       struct ddb_port *port = input->port;
+       struct dvb_adapter *adap = &input->adap;
+       struct dvb_demux *dvbdemux = &input->demux;
+
+       ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
+                                  &input->port->dev->pdev->dev,
+                                  adapter_nr);
+       if (ret < 0) {
+               printk(KERN_ERR "ddbridge: Could not register adapter."
+                      "Check if you enabled enough adapters in dvb-core!\n");
+               return ret;
+       }
+       input->attached = 1;
+
+       ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
+                                     start_feed,
+                                     stop_feed, input);
+       if (ret < 0)
+               return ret;
+       input->attached = 2;
+
+       ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux,
+                                        &input->hw_frontend,
+                                        &input->mem_frontend, adap);
+       if (ret < 0)
+               return ret;
+       input->attached = 3;
+
+       ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux);
+       if (ret < 0)
+               return ret;
+       input->attached = 4;
+
+       input->fe = 0;
+       switch (port->type) {
+       case DDB_TUNER_DVBS_ST:
+               if (demod_attach_stv0900(input, 0) < 0)
+                       return -ENODEV;
+               if (tuner_attach_stv6110(input, 0) < 0)
+                       return -ENODEV;
+               if (input->fe) {
+                       if (dvb_register_frontend(adap, input->fe) < 0)
+                               return -ENODEV;
+               }
+               break;
+       case DDB_TUNER_DVBS_ST_AA:
+               if (demod_attach_stv0900(input, 1) < 0)
+                       return -ENODEV;
+               if (tuner_attach_stv6110(input, 1) < 0)
+                       return -ENODEV;
+               if (input->fe) {
+                       if (dvb_register_frontend(adap, input->fe) < 0)
+                               return -ENODEV;
+               }
+               break;
+       case DDB_TUNER_DVBCT_TR:
+               if (demod_attach_drxk(input) < 0)
+                       return -ENODEV;
+               if (tuner_attach_tda18271(input) < 0)
+                       return -ENODEV;
+               if (input->fe) {
+                       if (dvb_register_frontend(adap, input->fe) < 0)
+                               return -ENODEV;
+               }
+               if (input->fe2) {
+                       if (dvb_register_frontend(adap, input->fe2) < 0)
+                               return -ENODEV;
+                       input->fe2->tuner_priv = input->fe->tuner_priv;
+                       memcpy(&input->fe2->ops.tuner_ops,
+                              &input->fe->ops.tuner_ops,
+                              sizeof(struct dvb_tuner_ops));
+               }
+               break;
+       }
+       input->attached = 5;
+       return 0;
+}
+
+/****************************************************************************/
+/****************************************************************************/
+
+static ssize_t ts_write(struct file *file, const char *buf,
+                       size_t count, loff_t *ppos)
+{
+       struct dvb_device *dvbdev = file->private_data;
+       struct ddb_output *output = dvbdev->priv;
+       size_t left = count;
+       int stat;
+
+       while (left) {
+               if (ddb_output_free(output) < 188) {
+                       if (file->f_flags & O_NONBLOCK)
+                               break;
+                       if (wait_event_interruptible(
+                                   output->wq, ddb_output_free(output) >= 188) < 0)
+                               break;
+               }
+               stat = ddb_output_write(output, buf, left);
+               if (stat < 0)
+                       break;
+               buf += stat;
+               left -= stat;
+       }
+       return (left == count) ? -EAGAIN : (count - left);
+}
+
+static ssize_t ts_read(struct file *file, char *buf,
+                      size_t count, loff_t *ppos)
+{
+       struct dvb_device *dvbdev = file->private_data;
+       struct ddb_output *output = dvbdev->priv;
+       struct ddb_input *input = output->port->input[0];
+       int left, read;
+
+       count -= count % 188;
+       left = count;
+       while (left) {
+               if (ddb_input_avail(input) < 188) {
+                       if (file->f_flags & O_NONBLOCK)
+                               break;
+                       if (wait_event_interruptible(
+                                   input->wq, ddb_input_avail(input) >= 188) < 0)
+                               break;
+               }
+               read = ddb_input_read(input, buf, left);
+               left -= read;
+               buf += read;
+       }
+       return (left == count) ? -EAGAIN : (count - left);
+}
+
+static unsigned int ts_poll(struct file *file, poll_table *wait)
+{
+       /*
+       struct dvb_device *dvbdev = file->private_data;
+       struct ddb_output *output = dvbdev->priv;
+       struct ddb_input *input = output->port->input[0];
+       */
+       unsigned int mask = 0;
+
+#if 0
+       if (data_avail_to_read)
+               mask |= POLLIN | POLLRDNORM;
+       if (data_avail_to_write)
+               mask |= POLLOUT | POLLWRNORM;
+
+       poll_wait(file, &read_queue, wait);
+       poll_wait(file, &write_queue, wait);
+#endif
+       return mask;
+}
+
+static const struct file_operations ci_fops = {
+       .owner   = THIS_MODULE,
+       .read    = ts_read,
+       .write   = ts_write,
+       .open    = dvb_generic_open,
+       .release = dvb_generic_release,
+       .poll    = ts_poll,
+       .mmap    = 0,
+};
+
+static struct dvb_device dvbdev_ci = {
+       .priv    = 0,
+       .readers = -1,
+       .writers = -1,
+       .users   = -1,
+       .fops    = &ci_fops,
+};
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static void input_tasklet(unsigned long data)
+{
+       struct ddb_input *input = (struct ddb_input *) data;
+       struct ddb *dev = input->port->dev;
+
+       spin_lock(&input->lock);
+       if (!input->running) {
+               spin_unlock(&input->lock);
+               return;
+       }
+       input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
+
+       if (input->port->class == DDB_PORT_TUNER) {
+               if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))
+                       printk(KERN_ERR "Overflow input %d\n", input->nr);
+               while (input->cbuf != ((input->stat >> 11) & 0x1f)
+                      || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) {
+                       dvb_dmx_swfilter_packets(&input->demux,
+                                                input->vbuf[input->cbuf],
+                                                input->dma_buf_size / 188);
+
+                       input->cbuf = (input->cbuf + 1) % input->dma_buf_num;
+                       ddbwritel((input->cbuf << 11),
+                                 DMA_BUFFER_ACK(input->nr));
+                       input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
+                      }
+       }
+       if (input->port->class == DDB_PORT_CI)
+               wake_up(&input->wq);
+       spin_unlock(&input->lock);
+}
+
+static void output_tasklet(unsigned long data)
+{
+       struct ddb_output *output = (struct ddb_output *) data;
+       struct ddb *dev = output->port->dev;
+
+       spin_lock(&output->lock);
+       if (!output->running) {
+               spin_unlock(&output->lock);
+               return;
+       }
+       output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8));
+       wake_up(&output->wq);
+       spin_unlock(&output->lock);
+}
+
+
+struct cxd2099_cfg cxd_cfg = {
+       .bitrate =  62000,
+       .adr     =  0x40,
+       .polarity = 1,
+       .clock_mode = 1,
+};
+
+static int ddb_ci_attach(struct ddb_port *port)
+{
+       int ret;
+
+       ret = dvb_register_adapter(&port->output->adap,
+                                  "DDBridge",
+                                  THIS_MODULE,
+                                  &port->dev->pdev->dev,
+                                  adapter_nr);
+       if (ret < 0)
+               return ret;
+       port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap);
+       if (!port->en) {
+               dvb_unregister_adapter(&port->output->adap);
+               return -ENODEV;
+       }
+       ddb_input_start(port->input[0]);
+       ddb_output_start(port->output);
+       dvb_ca_en50221_init(&port->output->adap,
+                           port->en, 0, 1);
+       ret = dvb_register_device(&port->output->adap, &port->output->dev,
+                                 &dvbdev_ci, (void *) port->output,
+                                 DVB_DEVICE_SEC);
+       return ret;
+}
+
+static int ddb_port_attach(struct ddb_port *port)
+{
+       int ret = 0;
+
+       switch (port->class) {
+       case DDB_PORT_TUNER:
+               ret = dvb_input_attach(port->input[0]);
+               if (ret < 0)
+                       break;
+               ret = dvb_input_attach(port->input[1]);
+               break;
+       case DDB_PORT_CI:
+               ret = ddb_ci_attach(port);
+               break;
+       default:
+               break;
+       }
+       if (ret < 0)
+               printk(KERN_ERR "port_attach on port %d failed\n", port->nr);
+       return ret;
+}
+
+static int ddb_ports_attach(struct ddb *dev)
+{
+       int i, ret = 0;
+       struct ddb_port *port;
+
+       for (i = 0; i < dev->info->port_num; i++) {
+               port = &dev->port[i];
+               ret = ddb_port_attach(port);
+               if (ret < 0)
+                       break;
+       }
+       return ret;
+}
+
+static void ddb_ports_detach(struct ddb *dev)
+{
+       int i;
+       struct ddb_port *port;
+
+       for (i = 0; i < dev->info->port_num; i++) {
+               port = &dev->port[i];
+               switch (port->class) {
+               case DDB_PORT_TUNER:
+                       dvb_input_detach(port->input[0]);
+                       dvb_input_detach(port->input[1]);
+                       break;
+               case DDB_PORT_CI:
+                       if (port->output->dev)
+                               dvb_unregister_device(port->output->dev);
+                       if (port->en) {
+                               ddb_input_stop(port->input[0]);
+                               ddb_output_stop(port->output);
+                               dvb_ca_en50221_release(port->en);
+                               kfree(port->en);
+                               port->en = 0;
+                               dvb_unregister_adapter(&port->output->adap);
+                       }
+                       break;
+               }
+       }
+}
+
+/****************************************************************************/
+/****************************************************************************/
+
+static int port_has_ci(struct ddb_port *port)
+{
+       u8 val;
+       return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1;
+}
+
+static int port_has_stv0900(struct ddb_port *port)
+{
+       u8 val;
+       if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0)
+               return 0;
+       return 1;
+}
+
+static int port_has_stv0900_aa(struct ddb_port *port)
+{
+       u8 val;
+       if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0)
+               return 0;
+       return 1;
+}
+
+static int port_has_drxks(struct ddb_port *port)
+{
+       u8 val;
+       if (i2c_read(&port->i2c->adap, 0x29, &val) < 0)
+               return 0;
+       if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0)
+               return 0;
+       return 1;
+}
+
+static void ddb_port_probe(struct ddb_port *port)
+{
+       struct ddb *dev = port->dev;
+       char *modname = "NO MODULE";
+
+       port->class = DDB_PORT_NONE;
+
+       if (port_has_ci(port)) {
+               modname = "CI";
+               port->class = DDB_PORT_CI;
+               ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+       } else if (port_has_stv0900(port)) {
+               modname = "DUAL DVB-S2";
+               port->class = DDB_PORT_TUNER;
+               port->type = DDB_TUNER_DVBS_ST;
+               ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
+       } else if (port_has_stv0900_aa(port)) {
+               modname = "DUAL DVB-S2";
+               port->class = DDB_PORT_TUNER;
+               port->type = DDB_TUNER_DVBS_ST_AA;
+               ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
+       } else if (port_has_drxks(port)) {
+               modname = "DUAL DVB-C/T";
+               port->class = DDB_PORT_TUNER;
+               port->type = DDB_TUNER_DVBCT_TR;
+               ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+       }
+       printk(KERN_INFO "Port %d (TAB %d): %s\n",
+                        port->nr, port->nr+1, modname);
+}
+
+static void ddb_input_init(struct ddb_port *port, int nr)
+{
+       struct ddb *dev = port->dev;
+       struct ddb_input *input = &dev->input[nr];
+
+       input->nr = nr;
+       input->port = port;
+       input->dma_buf_num = INPUT_DMA_BUFS;
+       input->dma_buf_size = INPUT_DMA_SIZE;
+       ddbwritel(0, TS_INPUT_CONTROL(nr));
+       ddbwritel(2, TS_INPUT_CONTROL(nr));
+       ddbwritel(0, TS_INPUT_CONTROL(nr));
+       ddbwritel(0, DMA_BUFFER_ACK(nr));
+       tasklet_init(&input->tasklet, input_tasklet, (unsigned long) input);
+       spin_lock_init(&input->lock);
+       init_waitqueue_head(&input->wq);
+}
+
+static void ddb_output_init(struct ddb_port *port, int nr)
+{
+       struct ddb *dev = port->dev;
+       struct ddb_output *output = &dev->output[nr];
+       output->nr = nr;
+       output->port = port;
+       output->dma_buf_num = OUTPUT_DMA_BUFS;
+       output->dma_buf_size = OUTPUT_DMA_SIZE;
+
+       ddbwritel(0, TS_OUTPUT_CONTROL(nr));
+       ddbwritel(2, TS_OUTPUT_CONTROL(nr));
+       ddbwritel(0, TS_OUTPUT_CONTROL(nr));
+       tasklet_init(&output->tasklet, output_tasklet, (unsigned long) output);
+       init_waitqueue_head(&output->wq);
+}
+
+static void ddb_ports_init(struct ddb *dev)
+{
+       int i;
+       struct ddb_port *port;
+
+       for (i = 0; i < dev->info->port_num; i++) {
+               port = &dev->port[i];
+               port->dev = dev;
+               port->nr = i;
+               port->i2c = &dev->i2c[i];
+               port->input[0] = &dev->input[2 * i];
+               port->input[1] = &dev->input[2 * i + 1];
+               port->output = &dev->output[i];
+
+               mutex_init(&port->i2c_gate_lock);
+               ddb_port_probe(port);
+               ddb_input_init(port, 2 * i);
+               ddb_input_init(port, 2 * i + 1);
+               ddb_output_init(port, i);
+       }
+}
+
+static void ddb_ports_release(struct ddb *dev)
+{
+       int i;
+       struct ddb_port *port;
+
+       for (i = 0; i < dev->info->port_num; i++) {
+               port = &dev->port[i];
+               port->dev = dev;
+               tasklet_kill(&port->input[0]->tasklet);
+               tasklet_kill(&port->input[1]->tasklet);
+               tasklet_kill(&port->output->tasklet);
+       }
+}
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static void irq_handle_i2c(struct ddb *dev, int n)
+{
+       struct ddb_i2c *i2c = &dev->i2c[n];
+
+       i2c->done = 1;
+       wake_up(&i2c->wq);
+}
+
+static irqreturn_t irq_handler(int irq, void *dev_id)
+{
+       struct ddb *dev = (struct ddb *) dev_id;
+       u32 s = ddbreadl(INTERRUPT_STATUS);
+
+       if (!s)
+               return IRQ_NONE;
+
+       do {
+               ddbwritel(s, INTERRUPT_ACK);
+
+               if (s & 0x00000001)
+                       irq_handle_i2c(dev, 0);
+               if (s & 0x00000002)
+                       irq_handle_i2c(dev, 1);
+               if (s & 0x00000004)
+                       irq_handle_i2c(dev, 2);
+               if (s & 0x00000008)
+                       irq_handle_i2c(dev, 3);
+
+               if (s & 0x00000100)
+                       tasklet_schedule(&dev->input[0].tasklet);
+               if (s & 0x00000200)
+                       tasklet_schedule(&dev->input[1].tasklet);
+               if (s & 0x00000400)
+                       tasklet_schedule(&dev->input[2].tasklet);
+               if (s & 0x00000800)
+                       tasklet_schedule(&dev->input[3].tasklet);
+               if (s & 0x00001000)
+                       tasklet_schedule(&dev->input[4].tasklet);
+               if (s & 0x00002000)
+                       tasklet_schedule(&dev->input[5].tasklet);
+               if (s & 0x00004000)
+                       tasklet_schedule(&dev->input[6].tasklet);
+               if (s & 0x00008000)
+                       tasklet_schedule(&dev->input[7].tasklet);
+
+               if (s & 0x00010000)
+                       tasklet_schedule(&dev->output[0].tasklet);
+               if (s & 0x00020000)
+                       tasklet_schedule(&dev->output[1].tasklet);
+               if (s & 0x00040000)
+                       tasklet_schedule(&dev->output[2].tasklet);
+               if (s & 0x00080000)
+                       tasklet_schedule(&dev->output[3].tasklet);
+
+               /* if (s & 0x000f0000)  printk(KERN_DEBUG "%08x\n", istat); */
+       } while ((s = ddbreadl(INTERRUPT_STATUS)));
+
+       return IRQ_HANDLED;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
+{
+       u32 data, shift;
+
+       if (wlen > 4)
+               ddbwritel(1, SPI_CONTROL);
+       while (wlen > 4) {
+               /* FIXME: check for big-endian */
+               data = swab32(*(u32 *)wbuf);
+               wbuf += 4;
+               wlen -= 4;
+               ddbwritel(data, SPI_DATA);
+               while (ddbreadl(SPI_CONTROL) & 0x0004)
+                       ;
+       }
+
+       if (rlen)
+               ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
+       else
+               ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
+
+       data = 0;
+       shift = ((4 - wlen) * 8);
+       while (wlen) {
+               data <<= 8;
+               data |= *wbuf;
+               wlen--;
+               wbuf++;
+       }
+       if (shift)
+               data <<= shift;
+       ddbwritel(data, SPI_DATA);
+       while (ddbreadl(SPI_CONTROL) & 0x0004)
+               ;
+
+       if (!rlen) {
+               ddbwritel(0, SPI_CONTROL);
+               return 0;
+       }
+       if (rlen > 4)
+               ddbwritel(1, SPI_CONTROL);
+
+       while (rlen > 4) {
+               ddbwritel(0xffffffff, SPI_DATA);
+               while (ddbreadl(SPI_CONTROL) & 0x0004)
+                       ;
+               data = ddbreadl(SPI_DATA);
+               *(u32 *) rbuf = swab32(data);
+               rbuf += 4;
+               rlen -= 4;
+       }
+       ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL);
+       ddbwritel(0xffffffff, SPI_DATA);
+       while (ddbreadl(SPI_CONTROL) & 0x0004)
+               ;
+
+       data = ddbreadl(SPI_DATA);
+       ddbwritel(0, SPI_CONTROL);
+
+       if (rlen < 4)
+               data <<= ((4 - rlen) * 8);
+
+       while (rlen > 0) {
+               *rbuf = ((data >> 24) & 0xff);
+               data <<= 8;
+               rbuf++;
+               rlen--;
+       }
+       return 0;
+}
+
+#define DDB_MAGIC 'd'
+
+struct ddb_flashio {
+       __u8 *write_buf;
+       __u32 write_len;
+       __u8 *read_buf;
+       __u32 read_len;
+};
+
+#define IOCTL_DDB_FLASHIO  _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
+
+#define DDB_NAME "ddbridge"
+
+static u32 ddb_num;
+static struct ddb *ddbs[32];
+static struct class *ddb_class;
+static int ddb_major;
+
+static int ddb_open(struct inode *inode, struct file *file)
+{
+       struct ddb *dev = ddbs[iminor(inode)];
+
+       file->private_data = dev;
+       return 0;
+}
+
+static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct ddb *dev = file->private_data;
+       void *parg = (void *)arg;
+       int res = -EFAULT;
+
+       switch (cmd) {
+       case IOCTL_DDB_FLASHIO:
+       {
+               struct ddb_flashio fio;
+               u8 *rbuf, *wbuf;
+
+               if (copy_from_user(&fio, parg, sizeof(fio)))
+                       break;
+               if (fio.write_len + fio.read_len > 1028) {
+                       printk(KERN_ERR "IOBUF too small\n");
+                       return -ENOMEM;
+               }
+               wbuf = &dev->iobuf[0];
+               if (!wbuf)
+                       return -ENOMEM;
+               rbuf = wbuf + fio.write_len;
+               if (copy_from_user(wbuf, fio.write_buf, fio.write_len)) {
+                       vfree(wbuf);
+                       break;
+               }
+               res = flashio(dev, wbuf, fio.write_len,
+                             rbuf, fio.read_len);
+               if (copy_to_user(fio.read_buf, rbuf, fio.read_len))
+                       res = -EFAULT;
+               break;
+       }
+       default:
+               break;
+       }
+       return res;
+}
+
+static const struct file_operations ddb_fops = {
+       .unlocked_ioctl = ddb_ioctl,
+       .open           = ddb_open,
+};
+
+static char *ddb_devnode(struct device *device, mode_t *mode)
+{
+       struct ddb *dev = dev_get_drvdata(device);
+
+       return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr);
+}
+
+static int ddb_class_create(void)
+{
+       ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops);
+       if (ddb_major < 0)
+               return ddb_major;
+
+       ddb_class = class_create(THIS_MODULE, DDB_NAME);
+       if (IS_ERR(ddb_class)) {
+               unregister_chrdev(ddb_major, DDB_NAME);
+               return -1;
+       }
+       ddb_class->devnode = ddb_devnode;
+       return 0;
+}
+
+static void ddb_class_destroy(void)
+{
+       class_destroy(ddb_class);
+       unregister_chrdev(ddb_major, DDB_NAME);
+}
+
+static int ddb_device_create(struct ddb *dev)
+{
+       dev->nr = ddb_num++;
+       dev->ddb_dev = device_create(ddb_class, NULL,
+                                    MKDEV(ddb_major, dev->nr),
+                                    dev, "ddbridge%d", dev->nr);
+       ddbs[dev->nr] = dev;
+       if (IS_ERR(dev->ddb_dev))
+               return -1;
+       return 0;
+}
+
+static void ddb_device_destroy(struct ddb *dev)
+{
+       ddb_num--;
+       if (IS_ERR(dev->ddb_dev))
+               return;
+       device_destroy(ddb_class, MKDEV(ddb_major, 0));
+}
+
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static void ddb_unmap(struct ddb *dev)
+{
+       if (dev->regs)
+               iounmap(dev->regs);
+       vfree(dev);
+}
+
+
+static void __devexit ddb_remove(struct pci_dev *pdev)
+{
+       struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
+
+       ddb_ports_detach(dev);
+       ddb_i2c_release(dev);
+
+       ddbwritel(0, INTERRUPT_ENABLE);
+       free_irq(dev->pdev->irq, dev);
+#ifdef CONFIG_PCI_MSI
+       if (dev->msi)
+               pci_disable_msi(dev->pdev);
+#endif
+       ddb_ports_release(dev);
+       ddb_buffers_free(dev);
+       ddb_device_destroy(dev);
+
+       ddb_unmap(dev);
+       pci_set_drvdata(pdev, 0);
+       pci_disable_device(pdev);
+}
+
+
+static int __devinit ddb_probe(struct pci_dev *pdev,
+                              const struct pci_device_id *id)
+{
+       struct ddb *dev;
+       int stat = 0;
+       int irq_flag = IRQF_SHARED;
+
+       if (pci_enable_device(pdev) < 0)
+               return -ENODEV;
+
+       dev = vmalloc(sizeof(struct ddb));
+       if (dev == NULL)
+               return -ENOMEM;
+       memset(dev, 0, sizeof(struct ddb));
+
+       dev->pdev = pdev;
+       pci_set_drvdata(pdev, dev);
+       dev->info = (struct ddb_info *) id->driver_data;
+       printk(KERN_INFO "DDBridge driver detected: %s\n", dev->info->name);
+
+       dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
+                           pci_resource_len(dev->pdev, 0));
+       if (!dev->regs) {
+               stat = -ENOMEM;
+               goto fail;
+       }
+       printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4));
+
+#ifdef CONFIG_PCI_MSI
+       if (pci_msi_enabled())
+               stat = pci_enable_msi(dev->pdev);
+       if (stat) {
+               printk(KERN_INFO ": MSI not available.\n");
+       } else {
+               irq_flag = 0;
+               dev->msi = 1;
+       }
+#endif
+       stat = request_irq(dev->pdev->irq, irq_handler,
+                          irq_flag, "DDBridge", (void *) dev);
+       if (stat < 0)
+               goto fail1;
+       ddbwritel(0, DMA_BASE_WRITE);
+       ddbwritel(0, DMA_BASE_READ);
+       ddbwritel(0xffffffff, INTERRUPT_ACK);
+       ddbwritel(0xfff0f, INTERRUPT_ENABLE);
+       ddbwritel(0, MSI1_ENABLE);
+
+       if (ddb_i2c_init(dev) < 0)
+               goto fail1;
+       ddb_ports_init(dev);
+       if (ddb_buffers_alloc(dev) < 0) {
+               printk(KERN_INFO ": Could not allocate buffer memory\n");
+               goto fail2;
+       }
+       if (ddb_ports_attach(dev) < 0)
+               goto fail3;
+       ddb_device_create(dev);
+       return 0;
+
+fail3:
+       ddb_ports_detach(dev);
+       printk(KERN_ERR "fail3\n");
+       ddb_ports_release(dev);
+fail2:
+       printk(KERN_ERR "fail2\n");
+       ddb_buffers_free(dev);
+fail1:
+       printk(KERN_ERR "fail1\n");
+       if (dev->msi)
+               pci_disable_msi(dev->pdev);
+       free_irq(dev->pdev->irq, dev);
+fail:
+       printk(KERN_ERR "fail\n");
+       ddb_unmap(dev);
+       pci_set_drvdata(pdev, 0);
+       pci_disable_device(pdev);
+       return -1;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+static struct ddb_info ddb_none = {
+       .type     = DDB_NONE,
+       .name     = "Digital Devices PCIe bridge",
+};
+
+static struct ddb_info ddb_octopus = {
+       .type     = DDB_OCTOPUS,
+       .name     = "Digital Devices Octopus DVB adapter",
+       .port_num = 4,
+};
+
+static struct ddb_info ddb_octopus_le = {
+       .type     = DDB_OCTOPUS,
+       .name     = "Digital Devices Octopus LE DVB adapter",
+       .port_num = 2,
+};
+
+static struct ddb_info ddb_v6 = {
+       .type     = DDB_OCTOPUS,
+       .name     = "Digital Devices Cine S2 V6 DVB adapter",
+       .port_num = 3,
+};
+
+#define DDVID 0xdd01 /* Digital Devices Vendor ID */
+
+#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) {  \
+       .vendor      = _vend,    .device    = _dev, \
+       .subvendor   = _subvend, .subdevice = _subdev, \
+       .driver_data = (unsigned long)&_driverdata }
+
+static const struct pci_device_id ddb_id_tbl[] __devinitdata = {
+       DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
+       DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
+       DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
+       DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus),
+       DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
+       /* in case sub-ids got deleted in flash */
+       DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
+       {0}
+};
+MODULE_DEVICE_TABLE(pci, ddb_id_tbl);
+
+
+static struct pci_driver ddb_pci_driver = {
+       .name        = "DDBridge",
+       .id_table    = ddb_id_tbl,
+       .probe       = ddb_probe,
+       .remove      = ddb_remove,
+};
+
+static __init int module_init_ddbridge(void)
+{
+       printk(KERN_INFO "Digital Devices PCIE bridge driver, "
+              "Copyright (C) 2010-11 Digital Devices GmbH\n");
+       if (ddb_class_create())
+               return -1;
+       return pci_register_driver(&ddb_pci_driver);
+}
+
+static __exit void module_exit_ddbridge(void)
+{
+       pci_unregister_driver(&ddb_pci_driver);
+       ddb_class_destroy();
+}
+
+module_init(module_init_ddbridge);
+module_exit(module_exit_ddbridge);
+
+MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
+MODULE_AUTHOR("Ralph Metzler");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.5");
diff --git a/drivers/media/dvb/ddbridge/ddbridge-regs.h b/drivers/media/dvb/ddbridge/ddbridge-regs.h
new file mode 100644 (file)
index 0000000..a3ccb31
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * ddbridge-regs.h: Digital Devices PCIe bridge driver
+ *
+ * Copyright (C) 2010-2011 Digital Devices GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * 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
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */
+
+/* Register Definitions */
+
+#define CUR_REGISTERMAP_VERSION 0x10000
+
+#define HARDWARE_VERSION       0x00
+#define REGISTERMAP_VERSION    0x04
+
+/* ------------------------------------------------------------------------- */
+/* SPI Controller */
+
+#define SPI_CONTROL     0x10
+#define SPI_DATA        0x14
+
+/* ------------------------------------------------------------------------- */
+
+/* Interrupt controller                                     */
+/* How many MSI's are available depends on HW (Min 2 max 8) */
+/* How many are usable also depends on Host platform        */
+
+#define INTERRUPT_BASE   (0x40)
+
+#define INTERRUPT_ENABLE (INTERRUPT_BASE + 0x00)
+#define MSI0_ENABLE      (INTERRUPT_BASE + 0x00)
+#define MSI1_ENABLE      (INTERRUPT_BASE + 0x04)
+#define MSI2_ENABLE      (INTERRUPT_BASE + 0x08)
+#define MSI3_ENABLE      (INTERRUPT_BASE + 0x0C)
+#define MSI4_ENABLE      (INTERRUPT_BASE + 0x10)
+#define MSI5_ENABLE      (INTERRUPT_BASE + 0x14)
+#define MSI6_ENABLE      (INTERRUPT_BASE + 0x18)
+#define MSI7_ENABLE      (INTERRUPT_BASE + 0x1C)
+
+#define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20)
+#define INTERRUPT_ACK    (INTERRUPT_BASE + 0x20)
+
+#define INTMASK_I2C1        (0x00000001)
+#define INTMASK_I2C2        (0x00000002)
+#define INTMASK_I2C3        (0x00000004)
+#define INTMASK_I2C4        (0x00000008)
+
+#define INTMASK_CIRQ1       (0x00000010)
+#define INTMASK_CIRQ2       (0x00000020)
+#define INTMASK_CIRQ3       (0x00000040)
+#define INTMASK_CIRQ4       (0x00000080)
+
+#define INTMASK_TSINPUT1    (0x00000100)
+#define INTMASK_TSINPUT2    (0x00000200)
+#define INTMASK_TSINPUT3    (0x00000400)
+#define INTMASK_TSINPUT4    (0x00000800)
+#define INTMASK_TSINPUT5    (0x00001000)
+#define INTMASK_TSINPUT6    (0x00002000)
+#define INTMASK_TSINPUT7    (0x00004000)
+#define INTMASK_TSINPUT8    (0x00008000)
+
+#define INTMASK_TSOUTPUT1   (0x00010000)
+#define INTMASK_TSOUTPUT2   (0x00020000)
+#define INTMASK_TSOUTPUT3   (0x00040000)
+#define INTMASK_TSOUTPUT4   (0x00080000)
+
+/* ------------------------------------------------------------------------- */
+/* I2C Master Controller */
+
+#define I2C_BASE        (0x80)  /* Byte offset */
+
+#define I2C_COMMAND     (0x00)
+#define I2C_TIMING      (0x04)
+#define I2C_TASKLENGTH  (0x08)     /* High read, low write */
+#define I2C_TASKADDRESS (0x0C)     /* High read, low write */
+
+#define I2C_MONITOR     (0x1C)
+
+#define I2C_BASE_1      (I2C_BASE + 0x00)
+#define I2C_BASE_2      (I2C_BASE + 0x20)
+#define I2C_BASE_3      (I2C_BASE + 0x40)
+#define I2C_BASE_4      (I2C_BASE + 0x60)
+
+#define I2C_BASE_N(i)   (I2C_BASE + (i) * 0x20)
+
+#define I2C_TASKMEM_BASE    (0x1000)    /* Byte offset */
+#define I2C_TASKMEM_SIZE    (0x1000)
+
+#define I2C_SPEED_400   (0x04030404)
+#define I2C_SPEED_200   (0x09080909)
+#define I2C_SPEED_154   (0x0C0B0C0C)
+#define I2C_SPEED_100   (0x13121313)
+#define I2C_SPEED_77    (0x19181919)
+#define I2C_SPEED_50    (0x27262727)
+
+
+/* ------------------------------------------------------------------------- */
+/* DMA  Controller */
+
+#define DMA_BASE_WRITE        (0x100)
+#define DMA_BASE_READ         (0x140)
+
+#define DMA_CONTROL     (0x00)                  /* 64 */
+#define DMA_ERROR       (0x04)                  /* 65 ( only read instance ) */
+
+#define DMA_DIAG_CONTROL                (0x1C)  /* 71 */
+#define DMA_DIAG_PACKETCOUNTER_LOW      (0x20)  /* 72 */
+#define DMA_DIAG_PACKETCOUNTER_HIGH     (0x24)  /* 73 */
+#define DMA_DIAG_TIMECOUNTER_LOW        (0x28)  /* 74 */
+#define DMA_DIAG_TIMECOUNTER_HIGH       (0x2C)  /* 75 */
+#define DMA_DIAG_RECHECKCOUNTER         (0x30)  /* 76  ( Split completions on read ) */
+#define DMA_DIAG_WAITTIMEOUTINIT        (0x34)  /* 77 */
+#define DMA_DIAG_WAITOVERFLOWCOUNTER    (0x38)  /* 78 */
+#define DMA_DIAG_WAITCOUNTER            (0x3C)  /* 79 */
+
+/* ------------------------------------------------------------------------- */
+/* DMA  Buffer */
+
+#define TS_INPUT_BASE       (0x200)
+#define TS_INPUT_CONTROL(i)         (TS_INPUT_BASE + (i) * 16 + 0x00)
+
+#define TS_OUTPUT_BASE       (0x280)
+#define TS_OUTPUT_CONTROL(i)         (TS_OUTPUT_BASE + (i) * 16 + 0x00)
+
+#define DMA_BUFFER_BASE     (0x300)
+
+#define DMA_BUFFER_CONTROL(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x00)
+#define DMA_BUFFER_ACK(i)           (DMA_BUFFER_BASE + (i) * 16 + 0x04)
+#define DMA_BUFFER_CURRENT(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x08)
+#define DMA_BUFFER_SIZE(i)          (DMA_BUFFER_BASE + (i) * 16 + 0x0c)
+
+#define DMA_BASE_ADDRESS_TABLE  (0x2000)
+#define DMA_BASE_ADDRESS_TABLE_ENTRIES (512)
+
diff --git a/drivers/media/dvb/ddbridge/ddbridge.h b/drivers/media/dvb/ddbridge/ddbridge.h
new file mode 100644 (file)
index 0000000..6d14893
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * ddbridge.h: Digital Devices PCIe bridge driver
+ *
+ * Copyright (C) 2010-2011 Digital Devices GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * 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
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef _DDBRIDGE_H_
+#define _DDBRIDGE_H_
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <asm/dma.h>
+#include <linux/dvb/frontend.h>
+#include <linux/dvb/ca.h>
+#include <linux/dvb/video.h>
+#include <linux/dvb/audio.h>
+#include <linux/socket.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_ringbuffer.h"
+#include "dvb_ca_en50221.h"
+#include "dvb_net.h"
+#include "cxd2099.h"
+
+#define DDB_MAX_I2C     4
+#define DDB_MAX_PORT    4
+#define DDB_MAX_INPUT   8
+#define DDB_MAX_OUTPUT  4
+
+struct ddb_info {
+       int   type;
+#define DDB_NONE         0
+#define DDB_OCTOPUS      1
+       char *name;
+       int   port_num;
+       u32   port_type[DDB_MAX_PORT];
+};
+
+/* DMA_SIZE MUST be divisible by 188 and 128 !!! */
+
+#define INPUT_DMA_MAX_BUFS 32      /* hardware table limit */
+#define INPUT_DMA_BUFS 8
+#define INPUT_DMA_SIZE (128*47*21)
+
+#define OUTPUT_DMA_MAX_BUFS 32
+#define OUTPUT_DMA_BUFS 8
+#define OUTPUT_DMA_SIZE (128*47*21)
+
+struct ddb;
+struct ddb_port;
+
+struct ddb_input {
+       struct ddb_port       *port;
+       u32                    nr;
+       int                    attached;
+
+       dma_addr_t             pbuf[INPUT_DMA_MAX_BUFS];
+       u8                    *vbuf[INPUT_DMA_MAX_BUFS];
+       u32                    dma_buf_num;
+       u32                    dma_buf_size;
+
+       struct tasklet_struct  tasklet;
+       spinlock_t             lock;
+       wait_queue_head_t      wq;
+       int                    running;
+       u32                    stat;
+       u32                    cbuf;
+       u32                    coff;
+
+       struct dvb_adapter     adap;
+       struct dvb_device     *dev;
+       struct dvb_frontend   *fe;
+       struct dvb_frontend   *fe2;
+       struct dmxdev          dmxdev;
+       struct dvb_demux       demux;
+       struct dvb_net         dvbnet;
+       struct dmx_frontend    hw_frontend;
+       struct dmx_frontend    mem_frontend;
+       int                    users;
+       int (*gate_ctrl)(struct dvb_frontend *, int);
+};
+
+struct ddb_output {
+       struct ddb_port       *port;
+       u32                    nr;
+       dma_addr_t             pbuf[OUTPUT_DMA_MAX_BUFS];
+       u8                    *vbuf[OUTPUT_DMA_MAX_BUFS];
+       u32                    dma_buf_num;
+       u32                    dma_buf_size;
+       struct tasklet_struct  tasklet;
+       spinlock_t             lock;
+       wait_queue_head_t      wq;
+       int                    running;
+       u32                    stat;
+       u32                    cbuf;
+       u32                    coff;
+
+       struct dvb_adapter     adap;
+       struct dvb_device     *dev;
+};
+
+struct ddb_i2c {
+       struct ddb            *dev;
+       u32                    nr;
+       struct i2c_adapter     adap;
+       struct i2c_adapter     adap2;
+       u32                    regs;
+       u32                    rbuf;
+       u32                    wbuf;
+       int                    done;
+       wait_queue_head_t      wq;
+};
+
+struct ddb_port {
+       struct ddb            *dev;
+       u32                    nr;
+       struct ddb_i2c        *i2c;
+       struct mutex           i2c_gate_lock;
+       u32                    class;
+#define DDB_PORT_NONE           0
+#define DDB_PORT_CI             1
+#define DDB_PORT_TUNER          2
+       u32                    type;
+#define DDB_TUNER_NONE          0
+#define DDB_TUNER_DVBS_ST       1
+#define DDB_TUNER_DVBS_ST_AA    2
+#define DDB_TUNER_DVBCT_TR     16
+#define DDB_TUNER_DVBCT_ST     17
+       u32                    adr;
+
+       struct ddb_input      *input[2];
+       struct ddb_output     *output;
+       struct dvb_ca_en50221 *en;
+};
+
+struct ddb {
+       struct pci_dev        *pdev;
+       unsigned char         *regs;
+       struct ddb_port        port[DDB_MAX_PORT];
+       struct ddb_i2c         i2c[DDB_MAX_I2C];
+       struct ddb_input       input[DDB_MAX_INPUT];
+       struct ddb_output      output[DDB_MAX_OUTPUT];
+
+       struct device         *ddb_dev;
+       int                    nr;
+       u8                     iobuf[1028];
+
+       struct ddb_info       *info;
+       int                    msi;
+};
+
+/****************************************************************************/
+
+#define ddbwritel(_val, _adr)        writel((_val), \
+                                    (char *) (dev->regs+(_adr)))
+#define ddbreadl(_adr)               readl((char *) (dev->regs+(_adr)))
+#define ddbcpyto(_adr, _src, _count) memcpy_toio((char *)      \
+                                    (dev->regs+(_adr)), (_src), (_count))
+#define ddbcpyfrom(_dst, _adr, _count) memcpy_fromio((_dst), (char *) \
+                                      (dev->regs+(_adr)), (_count))
+
+/****************************************************************************/
+
+#endif
index 0b51828..8f22bcd 100644 (file)
@@ -2,8 +2,10 @@
 # Makefile for the kernel DVB device drivers.
 #
 
+dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
+
 dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o    \
                 dvb_ca_en50221.o dvb_frontend.o                \
-                dvb_net.o dvb_ringbuffer.o dvb_math.o
+                $(dvb-net-y) dvb_ringbuffer.o dvb_math.o
 
 obj-$(CONFIG_DVB_CORE) += dvb-core.o
index 5b6b451..efe9c30 100644 (file)
@@ -904,7 +904,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
        .buffer = b \
 }
 
-static struct dtv_cmds_h dtv_cmds[] = {
+static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
        _DTV_CMD(DTV_TUNE, 1, 0),
        _DTV_CMD(DTV_CLEAR, 1, 0),
 
@@ -966,6 +966,7 @@ static struct dtv_cmds_h dtv_cmds[] = {
        _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 0, 0),
 
        _DTV_CMD(DTV_ISDBS_TS_ID, 1, 0),
+       _DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0),
 
        /* Get */
        _DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1),
index 51752a9..93d9869 100644 (file)
@@ -1230,7 +1230,7 @@ static const struct net_device_ops dvb_netdev_ops = {
        .ndo_open               = dvb_net_open,
        .ndo_stop               = dvb_net_stop,
        .ndo_start_xmit         = dvb_net_tx,
-       .ndo_set_multicast_list = dvb_net_set_multicast_list,
+       .ndo_set_rx_mode        = dvb_net_set_multicast_list,
        .ndo_set_mac_address    = dvb_net_set_mac,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
index 3a3126c..1e53acd 100644 (file)
@@ -32,6 +32,8 @@
 
 #define DVB_NET_DEVICES_MAX 10
 
+#ifdef CONFIG_DVB_NET
+
 struct dvb_net {
        struct dvb_device *dvbdev;
        struct net_device *device[DVB_NET_DEVICES_MAX];
@@ -40,8 +42,25 @@ struct dvb_net {
        struct dmx_demux *demux;
 };
 
-
 void dvb_net_release(struct dvb_net *);
 int  dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *);
 
+#else
+
+struct dvb_net {
+       struct dvb_device *dvbdev;
+};
+
+static inline void dvb_net_release(struct dvb_net *dvbnet)
+{
+}
+
+static inline int dvb_net_init(struct dvb_adapter *adap,
+                              struct dvb_net *dvbnet, struct dmx_demux *dmx)
+{
+       return 0;
+}
+
+#endif /* ifdef CONFIG_DVB_NET */
+
 #endif
index e85304c..5d73dec 100644 (file)
@@ -81,6 +81,7 @@ config DVB_USB_DIB0700
        select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
        help
          Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
index 100ebc3..d7ad05f 100644 (file)
@@ -91,7 +91,6 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req)
        case GET_CONFIG:
        case READ_MEMORY:
        case RECONNECT_USB:
-       case GET_IR_CODE:
                write = 0;
                break;
        case READ_I2C:
@@ -164,13 +163,6 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req)
        deb_xfer("<<< ");
        debug_dump(buf, act_len, deb_xfer);
 
-       /* remote controller query status is 1 if remote code is not received */
-       if (req->cmd == GET_IR_CODE && buf[1] == 1) {
-               buf[1] = 0; /* clear command "error" status */
-               memset(&buf[2], 0, req->data_len);
-               buf[3] = 1; /* no remote code received mark */
-       }
-
        /* check status */
        if (buf[1]) {
                err("command failed:%d", buf[1]);
@@ -292,6 +284,10 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
                }
 
                if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
+                       if (msg[i].len > 3 || msg[i+1].len > 61) {
+                               ret = -EOPNOTSUPP;
+                               goto error;
+                       }
                        if (msg[i].addr ==
                                af9015_af9013_config[0].demod_address)
                                req.cmd = READ_MEMORY;
@@ -306,12 +302,16 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
                        ret = af9015_ctrl_msg(d, &req);
                        i += 2;
                } else if (msg[i].flags & I2C_M_RD) {
-                       ret = -EINVAL;
+                       if (msg[i].len > 61) {
+                               ret = -EOPNOTSUPP;
+                               goto error;
+                       }
                        if (msg[i].addr ==
-                               af9015_af9013_config[0].demod_address)
+                               af9015_af9013_config[0].demod_address) {
+                               ret = -EINVAL;
                                goto error;
-                       else
-                               req.cmd = READ_I2C;
+                       }
+                       req.cmd = READ_I2C;
                        req.i2c_addr = msg[i].addr;
                        req.addr = addr;
                        req.mbox = mbox;
@@ -321,6 +321,10 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
                        ret = af9015_ctrl_msg(d, &req);
                        i += 1;
                } else {
+                       if (msg[i].len > 21) {
+                               ret = -EOPNOTSUPP;
+                               goto error;
+                       }
                        if (msg[i].addr ==
                                af9015_af9013_config[0].demod_address)
                                req.cmd = WRITE_MEMORY;
@@ -735,6 +739,7 @@ static const struct af9015_rc_setup af9015_rc_setup_hashes[] = {
        { 0xb8feb708, RC_MAP_MSI_DIGIVOX_II },
        { 0xa3703d00, RC_MAP_ALINK_DTU_M },
        { 0x9b7dc64e, RC_MAP_TOTAL_MEDIA_IN_HAND }, /* MYGICTV U718 */
+       { 0x5d49e3db, RC_MAP_DIGITTRADE }, /* LC-Power LC-USB-DVBT */
        { }
 };
 
@@ -749,6 +754,8 @@ static const struct af9015_rc_setup af9015_rc_setup_usbids[] = {
                RC_MAP_AZUREWAVE_AD_TU700 },
        { (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGI_VOX_MINI_III,
                RC_MAP_MSI_DIGIVOX_III },
+       { (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGIVOX_DUO,
+               RC_MAP_MSI_DIGIVOX_III },
        { (USB_VID_LEADTEK << 16) + USB_PID_WINFAST_DTV_DONGLE_GOLD,
                RC_MAP_LEADTEK_Y04G0051 },
        { (USB_VID_AVERMEDIA << 16) + USB_PID_AVERMEDIA_VOLAR_X,
@@ -759,6 +766,8 @@ static const struct af9015_rc_setup af9015_rc_setup_usbids[] = {
                RC_MAP_DIGITALNOW_TINYTWIN },
        { (USB_VID_GTEK << 16) + USB_PID_TINYTWIN_3,
                RC_MAP_DIGITALNOW_TINYTWIN },
+       { (USB_VID_KWORLD_2 << 16) + USB_PID_SVEON_STV22,
+               RC_MAP_MSI_DIGIVOX_III },
        { }
 };
 
@@ -1082,44 +1091,11 @@ error:
        return ret;
 }
 
-/* init 2nd I2C adapter */
-static int af9015_i2c_init(struct dvb_usb_device *d)
-{
-       int ret;
-       struct af9015_state *state = d->priv;
-       deb_info("%s:\n", __func__);
-
-       strncpy(state->i2c_adap.name, d->desc->name,
-               sizeof(state->i2c_adap.name));
-       state->i2c_adap.algo      = d->props.i2c_algo;
-       state->i2c_adap.algo_data = NULL;
-       state->i2c_adap.dev.parent = &d->udev->dev;
-
-       i2c_set_adapdata(&state->i2c_adap, d);
-
-       ret = i2c_add_adapter(&state->i2c_adap);
-       if (ret < 0)
-               err("could not add i2c adapter");
-
-       return ret;
-}
-
 static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
 {
        int ret;
-       struct af9015_state *state = adap->dev->priv;
-       struct i2c_adapter *i2c_adap;
-
-       if (adap->id == 0) {
-               /* select I2C adapter */
-               i2c_adap = &adap->dev->i2c_adap;
-
-               deb_info("%s: init I2C\n", __func__);
-               ret = af9015_i2c_init(adap->dev);
-       } else {
-               /* select I2C adapter */
-               i2c_adap = &state->i2c_adap;
 
+       if (adap->id == 1) {
                /* copy firmware to 2nd demodulator */
                if (af9015_config.dual_mode) {
                        ret = af9015_copy_firmware(adap->dev);
@@ -1136,7 +1112,7 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
 
        /* attach demodulator */
        adap->fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
-               i2c_adap);
+               &adap->dev->i2c_adap);
 
        return adap->fe == NULL ? -ENODEV : 0;
 }
@@ -1206,57 +1182,56 @@ static struct mxl5007t_config af9015_mxl5007t_config = {
 
 static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       struct af9015_state *state = adap->dev->priv;
-       struct i2c_adapter *i2c_adap;
        int ret;
        deb_info("%s:\n", __func__);
 
-       /* select I2C adapter */
-       if (adap->id == 0)
-               i2c_adap = &adap->dev->i2c_adap;
-       else
-               i2c_adap = &state->i2c_adap;
-
        switch (af9015_af9013_config[adap->id].tuner) {
        case AF9013_TUNER_MT2060:
        case AF9013_TUNER_MT2060_2:
-               ret = dvb_attach(mt2060_attach, adap->fe, i2c_adap,
+               ret = dvb_attach(mt2060_attach, adap->fe, &adap->dev->i2c_adap,
                        &af9015_mt2060_config,
                        af9015_config.mt2060_if1[adap->id])
                        == NULL ? -ENODEV : 0;
                break;
        case AF9013_TUNER_QT1010:
        case AF9013_TUNER_QT1010A:
-               ret = dvb_attach(qt1010_attach, adap->fe, i2c_adap,
+               ret = dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap,
                        &af9015_qt1010_config) == NULL ? -ENODEV : 0;
                break;
        case AF9013_TUNER_TDA18271:
-               ret = dvb_attach(tda18271_attach, adap->fe, 0xc0, i2c_adap,
+               ret = dvb_attach(tda18271_attach, adap->fe, 0xc0,
+                       &adap->dev->i2c_adap,
                        &af9015_tda18271_config) == NULL ? -ENODEV : 0;
                break;
        case AF9013_TUNER_TDA18218:
-               ret = dvb_attach(tda18218_attach, adap->fe, i2c_adap,
+               ret = dvb_attach(tda18218_attach, adap->fe,
+                       &adap->dev->i2c_adap,
                        &af9015_tda18218_config) == NULL ? -ENODEV : 0;
                break;
        case AF9013_TUNER_MXL5003D:
-               ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap,
+               ret = dvb_attach(mxl5005s_attach, adap->fe,
+                       &adap->dev->i2c_adap,
                        &af9015_mxl5003_config) == NULL ? -ENODEV : 0;
                break;
        case AF9013_TUNER_MXL5005D:
        case AF9013_TUNER_MXL5005R:
-               ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap,
+               ret = dvb_attach(mxl5005s_attach, adap->fe,
+                       &adap->dev->i2c_adap,
                        &af9015_mxl5005_config) == NULL ? -ENODEV : 0;
                break;
        case AF9013_TUNER_ENV77H11D5:
-               ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0, i2c_adap,
+               ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0,
+                       &adap->dev->i2c_adap,
                        DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
                break;
        case AF9013_TUNER_MC44S803:
-               ret = dvb_attach(mc44s803_attach, adap->fe, i2c_adap,
+               ret = dvb_attach(mc44s803_attach, adap->fe,
+                       &adap->dev->i2c_adap,
                        &af9015_mc44s803_config) == NULL ? -ENODEV : 0;
                break;
        case AF9013_TUNER_MXL5007T:
-               ret = dvb_attach(mxl5007t_attach, adap->fe, i2c_adap,
+               ret = dvb_attach(mxl5007t_attach, adap->fe,
+                       &adap->dev->i2c_adap,
                        0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0;
                break;
        case AF9013_TUNER_UNKNOWN:
@@ -1309,6 +1284,7 @@ static struct usb_device_id af9015_usb_table[] = {
                USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC)},
 /* 35 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T)},
        {USB_DEVICE(USB_VID_GTEK,      USB_PID_TINYTWIN_3)},
+       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_SVEON_STV22)},
        {0},
 };
 MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1502,7 +1478,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
 
                .i2c_algo = &af9015_i2c_algo,
 
-               .num_device_descs = 9, /* check max from dvb-usb.h */
+               .num_device_descs = 10, /* check max from dvb-usb.h */
                .devices = {
                        {
                                .name = "Xtensions XD-380",
@@ -1554,6 +1530,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
                                .cold_ids = {&af9015_usb_table[20], NULL},
                                .warm_ids = {NULL},
                        },
+                       {
+                               .name = "Sveon STV22 Dual USB DVB-T Tuner HDTV",
+                               .cold_ids = {&af9015_usb_table[37], NULL},
+                               .warm_ids = {NULL},
+                       },
                }
        }, {
                .caps = DVB_USB_IS_AN_I2C_ADAPTER,
@@ -1704,33 +1685,11 @@ static int af9015_usb_probe(struct usb_interface *intf,
        return ret;
 }
 
-static void af9015_i2c_exit(struct dvb_usb_device *d)
-{
-       struct af9015_state *state = d->priv;
-       deb_info("%s:\n", __func__);
-
-       /* remove 2nd I2C adapter */
-       if (d->state & DVB_USB_STATE_I2C)
-               i2c_del_adapter(&state->i2c_adap);
-}
-
-static void af9015_usb_device_exit(struct usb_interface *intf)
-{
-       struct dvb_usb_device *d = usb_get_intfdata(intf);
-       deb_info("%s:\n", __func__);
-
-       /* remove 2nd I2C adapter */
-       if (d != NULL && d->desc != NULL)
-               af9015_i2c_exit(d);
-
-       dvb_usb_device_exit(intf);
-}
-
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver af9015_usb_driver = {
        .name = "dvb_usb_af9015",
        .probe = af9015_usb_probe,
-       .disconnect = af9015_usb_device_exit,
+       .disconnect = dvb_usb_device_exit,
        .id_table = af9015_usb_table,
 };
 
index beb3004..6252ea6 100644 (file)
@@ -99,7 +99,6 @@ enum af9015_ir_mode {
 };
 
 struct af9015_state {
-       struct i2c_adapter i2c_adap; /* I2C adapter for 2nd FE */
        u8 rc_repeat;
        u32 rc_keycode;
        u8 rc_last[4];
index 7c327b5..2cbf19a 100644 (file)
@@ -347,15 +347,17 @@ static struct isl6423_config anysee_isl6423_config = {
  * PCB: ?
  * parts: DNOS404ZH102A(MT352, DTT7579(?))
  *
- * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=????????
- * PCB: ?
+ * E30 VID=04b4 PID=861f HW=2 FW=2.1 "anysee-T(LP)"
+ * PCB: PCB 507T (rev1.61)
  * parts: DNOS404ZH103A(ZL10353, DTT7579(?))
+ * OEA=0a OEB=00 OEC=00 OED=ff OEE=00
+ * IOA=45 IOB=ff IOC=00 IOD=ff IOE=00
  *
  * E30 Plus VID=04b4 PID=861f HW=6 FW=1.0 "anysee"
  * PCB: 507CD (rev1.1)
  * parts: DNOS404ZH103A(ZL10353, DTT7579(?)), CST56I01
- * OEA=80 OEB=00 OEC=00 OED=ff OEF=fe
- * IOA=4f IOB=ff IOC=00 IOD=06 IOF=01
+ * OEA=80 OEB=00 OEC=00 OED=ff OEE=fe
+ * IOA=4f IOB=ff IOC=00 IOD=06 IOE=01
  * IOD[0] ZL10353 1=enabled
  * IOA[7] TS 0=enabled
  * tuner is not behind ZL10353 I2C-gate (no care if gate disabled or not)
@@ -363,30 +365,30 @@ static struct isl6423_config anysee_isl6423_config = {
  * E30 C Plus VID=04b4 PID=861f HW=10 FW=1.0 "anysee-DC(LP)"
  * PCB: 507DC (rev0.2)
  * parts: TDA10023, DTOS403IH102B TM, CST56I01
- * OEA=80 OEB=00 OEC=00 OED=ff OEF=fe
- * IOA=4f IOB=ff IOC=00 IOD=26 IOF=01
+ * OEA=80 OEB=00 OEC=00 OED=ff OEE=fe
+ * IOA=4f IOB=ff IOC=00 IOD=26 IOE=01
  * IOD[0] TDA10023 1=enabled
  *
  * E30 S2 Plus VID=04b4 PID=861f HW=11 FW=0.1 "anysee-S2(LP)"
  * PCB: 507SI (rev2.1)
  * parts: BS2N10WCC01(CX24116, CX24118), ISL6423, TDA8024
- * OEA=80 OEB=00 OEC=ff OED=ff OEF=fe
- * IOA=4d IOB=ff IOC=00 IOD=26 IOF=01
+ * OEA=80 OEB=00 OEC=ff OED=ff OEE=fe
+ * IOA=4d IOB=ff IOC=00 IOD=26 IOE=01
  * IOD[0] CX24116 1=enabled
  *
  * E30 C Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)"
  * PCB: 507FA (rev0.4)
  * parts: TDA10023, DTOS403IH102B TM, TDA8024
- * OEA=80 OEB=00 OEC=ff OED=ff OEF=ff
- * IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0
+ * OEA=80 OEB=00 OEC=ff OED=ff OEE=ff
+ * IOA=4d IOB=ff IOC=00 IOD=00 IOE=c0
  * IOD[5] TDA10023 1=enabled
  * IOE[0] tuner 1=enabled
  *
  * E30 Combo Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)"
  * PCB: 507FA (rev1.1)
  * parts: ZL10353, TDA10023, DTOS403IH102B TM, TDA8024
- * OEA=80 OEB=00 OEC=ff OED=ff OEF=ff
- * IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0
+ * OEA=80 OEB=00 OEC=ff OED=ff OEE=ff
+ * IOA=4d IOB=ff IOC=00 IOD=00 IOE=c0
  * DVB-C:
  * IOD[5] TDA10023 1=enabled
  * IOE[0] tuner 1=enabled
@@ -398,8 +400,8 @@ static struct isl6423_config anysee_isl6423_config = {
  * E7 TC VID=1c73 PID=861f HW=18 FW=0.7 AMTCI=0.5 "anysee-E7TC(LP)"
  * PCB: 508TC (rev0.6)
  * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212)
- * OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff
- * IOA=4d IOB=00 IOC=cc IOD=48 IOF=e4
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
+ * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4
  * IOA[7] TS 1=enabled
  * IOE[4] TDA18212 1=enabled
  * DVB-C:
@@ -414,11 +416,34 @@ static struct isl6423_config anysee_isl6423_config = {
  * E7 S2 VID=1c73 PID=861f HW=19 FW=0.4 AMTCI=0.5 "anysee-E7S2(LP)"
  * PCB: 508S2 (rev0.7)
  * parts: DNBU10512IST(STV0903, STV6110), ISL6423
- * OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff
- * IOA=4d IOB=00 IOC=c4 IOD=08 IOF=e4
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
+ * IOA=4d IOB=00 IOC=c4 IOD=08 IOE=e4
  * IOA[7] TS 1=enabled
  * IOE[5] STV0903 1=enabled
  *
+ * E7 PTC VID=1c73 PID=861f HW=21 FW=0.1 AMTCI=?? "anysee-E7PTC(LP)"
+ * PCB: 508PTC (rev0.5)
+ * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212)
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
+ * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4
+ * IOA[7] TS 1=enabled
+ * IOE[4] TDA18212 1=enabled
+ * DVB-C:
+ * IOD[6] ZL10353 0=disabled
+ * IOD[5] TDA10023 1=enabled
+ * IOE[0] IF 1=enabled
+ * DVB-T:
+ * IOD[5] TDA10023 0=disabled
+ * IOD[6] ZL10353 1=enabled
+ * IOE[0] IF 0=enabled
+ *
+ * E7 S2 VID=1c73 PID=861f HW=22 FW=0.1 AMTCI=?? "anysee-E7PS2(LP)"
+ * PCB: 508PS2 (rev0.4)
+ * parts: DNBU10512IST(STV0903, STV6110), ISL6423
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
+ * IOA=4d IOB=00 IOC=c4 IOD=08 IOE=e4
+ * IOA[7] TS 1=enabled
+ * IOE[5] STV0903 1=enabled
  */
 
 static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
@@ -459,7 +484,7 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
        state->hw = hw_info[0];
 
        switch (state->hw) {
-       case ANYSEE_HW_02: /* 2 */
+       case ANYSEE_HW_507T: /* 2 */
                /* E30 */
 
                /* attach demod */
@@ -593,7 +618,9 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
 
                break;
        case ANYSEE_HW_508TC: /* 18 */
+       case ANYSEE_HW_508PTC: /* 21 */
                /* E7 TC */
+               /* E7 PTC */
 
                /* enable transport stream on IOA[7] */
                ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
@@ -650,7 +677,9 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
 
                break;
        case ANYSEE_HW_508S2: /* 19 */
+       case ANYSEE_HW_508PS2: /* 22 */
                /* E7 S2 */
+               /* E7 PS2 */
 
                /* enable transport stream on IOA[7] */
                ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
@@ -687,7 +716,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
        deb_info("%s:\n", __func__);
 
        switch (state->hw) {
-       case ANYSEE_HW_02: /* 2 */
+       case ANYSEE_HW_507T: /* 2 */
                /* E30 */
 
                /* attach tuner */
@@ -762,7 +791,9 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
 
                break;
        case ANYSEE_HW_508TC: /* 18 */
+       case ANYSEE_HW_508PTC: /* 21 */
                /* E7 TC */
+               /* E7 PTC */
 
                /* enable tuner on IOE[4] */
                ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
@@ -775,7 +806,9 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
 
                break;
        case ANYSEE_HW_508S2: /* 19 */
+       case ANYSEE_HW_508PS2: /* 22 */
                /* E7 S2 */
+               /* E7 PS2 */
 
                /* attach tuner */
                fe = dvb_attach(stv6110_attach, adap->fe,
index a7673aa..ad6ccd1 100644 (file)
@@ -61,13 +61,15 @@ struct anysee_state {
        u8 seq;
 };
 
-#define ANYSEE_HW_02     2 /* E30 */
-#define ANYSEE_HW_507CD  6 /* E30 Plus */
-#define ANYSEE_HW_507DC 10 /* E30 C Plus */
-#define ANYSEE_HW_507SI 11 /* E30 S2 Plus */
-#define ANYSEE_HW_507FA 15 /* E30 Combo Plus / E30 C Plus */
-#define ANYSEE_HW_508TC 18 /* E7 TC */
-#define ANYSEE_HW_508S2 19 /* E7 S2 */
+#define ANYSEE_HW_507T    2 /* E30 */
+#define ANYSEE_HW_507CD   6 /* E30 Plus */
+#define ANYSEE_HW_507DC  10 /* E30 C Plus */
+#define ANYSEE_HW_507SI  11 /* E30 S2 Plus */
+#define ANYSEE_HW_507FA  15 /* E30 Combo Plus / E30 C Plus */
+#define ANYSEE_HW_508TC  18 /* E7 TC */
+#define ANYSEE_HW_508S2  19 /* E7 S2 */
+#define ANYSEE_HW_508PTC 21 /* E7 PTC Plus */
+#define ANYSEE_HW_508PS2 22 /* E7 PS2 Plus */
 
 #define REG_IOA       0x80 /* Port A (bit addressable) */
 #define REG_IOB       0x90 /* Port B (bit addressable) */
index c519ad5..d0ea5b6 100644 (file)
@@ -17,6 +17,7 @@
 #include "mt2266.h"
 #include "tuner-xc2028.h"
 #include "xc5000.h"
+#include "xc4000.h"
 #include "s5h1411.h"
 #include "dib0070.h"
 #include "dib0090.h"
@@ -2655,6 +2656,156 @@ static int xc5000_tuner_attach(struct dvb_usb_adapter *adap)
                == NULL ? -ENODEV : 0;
 }
 
+static int dib0700_xc4000_tuner_callback(void *priv, int component,
+                                        int command, int arg)
+{
+       struct dvb_usb_adapter *adap = priv;
+
+       if (command == XC4000_TUNER_RESET) {
+               /* Reset the tuner */
+               dib7000p_set_gpio(adap->fe, 8, 0, 0);
+               msleep(10);
+               dib7000p_set_gpio(adap->fe, 8, 0, 1);
+       } else {
+               err("xc4000: unknown tuner callback command: %d\n", command);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct dibx000_agc_config stk7700p_7000p_xc4000_agc_config = {
+       .band_caps = BAND_UHF | BAND_VHF,
+       .setup = 0x64,
+       .inv_gain = 0x02c8,
+       .time_stabiliz = 0x15,
+       .alpha_level = 0x00,
+       .thlock = 0x76,
+       .wbd_inv = 0x01,
+       .wbd_ref = 0x0b33,
+       .wbd_sel = 0x00,
+       .wbd_alpha = 0x02,
+       .agc1_max = 0x00,
+       .agc1_min = 0x00,
+       .agc2_max = 0x9b26,
+       .agc2_min = 0x26ca,
+       .agc1_pt1 = 0x00,
+       .agc1_pt2 = 0x00,
+       .agc1_pt3 = 0x00,
+       .agc1_slope1 = 0x00,
+       .agc1_slope2 = 0x00,
+       .agc2_pt1 = 0x00,
+       .agc2_pt2 = 0x80,
+       .agc2_slope1 = 0x1d,
+       .agc2_slope2 = 0x1d,
+       .alpha_mant = 0x11,
+       .alpha_exp = 0x1b,
+       .beta_mant = 0x17,
+       .beta_exp = 0x33,
+       .perform_agc_softsplit = 0x00,
+};
+
+static struct dibx000_bandwidth_config stk7700p_xc4000_pll_config = {
+       60000, 30000,   /* internal, sampling */
+       1, 8, 3, 1, 0,  /* pll_cfg: prediv, ratio, range, reset, bypass */
+       0, 0, 1, 1, 0,  /* misc: refdiv, bypclk_div, IO_CLK_en_core, */
+                       /* ADClkSrc, modulo */
+       (3 << 14) | (1 << 12) | 524,    /* sad_cfg: refsel, sel, freq_15k */
+       39370534,       /* ifreq */
+       20452225,       /* timf */
+       30000000        /* xtal */
+};
+
+/* FIXME: none of these inputs are validated yet */
+static struct dib7000p_config pctv_340e_config = {
+       .output_mpeg2_in_188_bytes = 1,
+
+       .agc_config_count = 1,
+       .agc = &stk7700p_7000p_xc4000_agc_config,
+       .bw  = &stk7700p_xc4000_pll_config,
+
+       .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
+       .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
+       .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
+};
+
+/* PCTV 340e GPIOs map:
+   dib0700:
+   GPIO2  - CX25843 sleep
+   GPIO3  - CS5340 reset
+   GPIO5  - IRD
+   GPIO6  - Power Supply
+   GPIO8  - LNA (1=off 0=on)
+   GPIO10 - CX25843 reset
+   dib7000:
+   GPIO8  - xc4000 reset
+ */
+static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct dib0700_state *st = adap->dev->priv;
+
+       /* Power Supply on */
+       dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 0);
+       msleep(50);
+       dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 1);
+       msleep(100); /* Allow power supply to settle before probing */
+
+       /* cx25843 reset */
+       dib0700_set_gpio(adap->dev, GPIO10,  GPIO_OUT, 0);
+       msleep(1); /* cx25843 datasheet say 350us required */
+       dib0700_set_gpio(adap->dev, GPIO10,  GPIO_OUT, 1);
+
+       /* LNA off for now */
+       dib0700_set_gpio(adap->dev, GPIO8,  GPIO_OUT, 1);
+
+       /* Put the CX25843 to sleep for now since we're in digital mode */
+       dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1);
+
+       /* FIXME: not verified yet */
+       dib0700_ctrl_clock(adap->dev, 72, 1);
+
+       msleep(500);
+
+       if (dib7000pc_detection(&adap->dev->i2c_adap) == 0) {
+               /* Demodulator not found for some reason? */
+               return -ENODEV;
+       }
+
+       adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12,
+                             &pctv_340e_config);
+       st->is_dib7000pc = 1;
+
+       return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static struct xc4000_config dib7000p_xc4000_tunerconfig = {
+       .i2c_address      = 0x61,
+       .default_pm       = 1,
+       .dvb_amplitude    = 0,
+       .set_smoothedcvbs = 0,
+       .if_khz           = 5400
+};
+
+static int xc4000_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct i2c_adapter *tun_i2c;
+
+       /* The xc4000 is not on the main i2c bus */
+       tun_i2c = dib7000p_get_i2c_master(adap->fe,
+                                         DIBX000_I2C_INTERFACE_TUNER, 1);
+       if (tun_i2c == NULL) {
+               printk(KERN_ERR "Could not reach tuner i2c bus\n");
+               return 0;
+       }
+
+       /* Setup the reset callback */
+       adap->fe->callback = dib0700_xc4000_tuner_callback;
+
+       return dvb_attach(xc4000_attach, adap->fe, tun_i2c,
+                         &dib7000p_xc4000_tunerconfig)
+               == NULL ? -ENODEV : 0;
+}
+
 static struct lgdt3305_config hcw_lgdt3305_config = {
        .i2c_addr           = 0x0e,
        .mpeg_mode          = LGDT3305_MPEG_PARALLEL,
@@ -2802,6 +2953,8 @@ struct usb_device_id dib0700_usb_id_table[] = {
        { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE7090PVR) },
        { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2) },
 /* 75 */{ USB_DEVICE(USB_VID_MEDION,    USB_PID_CREATIX_CTX1921) },
+       { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV340E) },
+       { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV340E_SE) },
        { 0 }           /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -3762,6 +3915,41 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        },
                },
 
+               .rc.core = {
+                       .rc_interval      = DEFAULT_RC_INTERVAL,
+                       .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+                       .module_name      = "dib0700",
+                       .rc_query         = dib0700_rc_query_old_firmware,
+                       .allowed_protos   = RC_TYPE_RC5 |
+                                           RC_TYPE_RC6 |
+                                           RC_TYPE_NEC,
+                       .change_protocol  = dib0700_change_protocol,
+               },
+       }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+               .num_adapters = 1,
+               .adapter = {
+                       {
+                               .frontend_attach  = pctv340e_frontend_attach,
+                               .tuner_attach     = xc4000_tuner_attach,
+
+                               DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+                               .size_of_priv = sizeof(struct
+                                               dib0700_adapter_state),
+                       },
+               },
+
+               .num_device_descs = 2,
+               .devices = {
+                       {   "Pinnacle PCTV 340e HD Pro USB Stick",
+                               { &dib0700_usb_id_table[76], NULL },
+                               { NULL },
+                       },
+                       {   "Pinnacle PCTV Hybrid Stick Solo",
+                               { &dib0700_usb_id_table[77], NULL },
+                               { NULL },
+                       },
+               },
                .rc.core = {
                        .rc_interval      = DEFAULT_RC_INTERVAL,
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
index 21b1549..2a79b8f 100644 (file)
 #define USB_PID_PINNACLE_PCTV310E                      0x3211
 #define USB_PID_PINNACLE_PCTV801E                      0x023a
 #define USB_PID_PINNACLE_PCTV801E_SE                   0x023b
+#define USB_PID_PINNACLE_PCTV340E                      0x023d
+#define USB_PID_PINNACLE_PCTV340E_SE                   0x023e
 #define USB_PID_PINNACLE_PCTV73A                       0x0243
 #define USB_PID_PINNACLE_PCTV73ESE                     0x0245
 #define USB_PID_PINNACLE_PCTV74E                       0x0246
 #define USB_PID_FRIIO_WHITE                            0x0001
 #define USB_PID_TVWAY_PLUS                             0x0002
 #define USB_PID_SVEON_STV20                            0xe39d
+#define USB_PID_SVEON_STV22                            0xe401
 #define USB_PID_AZUREWAVE_AZ6027                       0x3275
 #define USB_PID_TERRATEC_DVBS2CI_V1                    0x10a4
 #define USB_PID_TERRATEC_DVBS2CI_V2                    0x10ac
index 76a8096..7d35d07 100644 (file)
@@ -85,7 +85,7 @@ static inline u8 rc5_data(struct rc_map_table *key)
        return key->scancode & 0xff;
 }
 
-static inline u8 rc5_scan(struct rc_map_table *key)
+static inline u16 rc5_scan(struct rc_map_table *key)
 {
        return key->scancode & 0xffff;
 }
index 831749a..ed32b9d 100644 (file)
@@ -78,9 +78,6 @@ extern int dvb_usb_gp8psk_debug;
 #define ADV_MOD_DVB_BPSK 9     /* DVB-S BPSK */
 
 #define GET_USB_SPEED                     0x07
- #define USB_SPEED_LOW                    0
- #define USB_SPEED_FULL                   1
- #define USB_SPEED_HIGH                   2
 
 #define RESET_FX2                         0x13
 
index 08f8842..473b95e 100644 (file)
@@ -765,10 +765,8 @@ static void technisat_usb2_disconnect(struct usb_interface *intf)
        /* work and stuff was only created when the device is is hot-state */
        if (dev != NULL) {
                struct technisat_usb2_state *state = dev->priv;
-               if (state != NULL) {
+               if (state != NULL)
                        cancel_delayed_work_sync(&state->green_led_work);
-                       flush_scheduled_work();
-               }
        }
 
        dvb_usb_device_exit(intf);
index 969688f..cf5ec46 100644 (file)
@@ -36,9 +36,6 @@
  #define Tuner_Power_OFF                  0
 
 #define GET_USB_SPEED                     0x07
- #define USB_SPEED_LOW                    0
- #define USB_SPEED_FULL                   1
- #define USB_SPEED_HIGH                   2
 
 #define LOCK_TUNER_COMMAND                0x09
 
index 21c52e3..489ae82 100644 (file)
@@ -1208,7 +1208,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
        if (r->response != AVC_RESPONSE_ACCEPTED) {
                dev_err(fdtv->device,
                        "CA PMT failed with response 0x%x\n", r->response);
-               ret = -EFAULT;
+               ret = -EACCES;
        }
 out:
        mutex_unlock(&fdtv->avc_mutex);
index 8ffb565..e5ebdbf 100644 (file)
@@ -45,11 +45,6 @@ static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
        return flags;
 }
 
-static int fdtv_ca_reset(struct firedtv *fdtv)
-{
-       return avc_ca_reset(fdtv) ? -EFAULT : 0;
-}
-
 static int fdtv_ca_get_caps(void *arg)
 {
        struct ca_caps *cap = arg;
@@ -65,12 +60,14 @@ static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
 {
        struct firedtv_tuner_status stat;
        struct ca_slot_info *slot = arg;
+       int err;
 
-       if (avc_tuner_status(fdtv, &stat))
-               return -EFAULT;
+       err = avc_tuner_status(fdtv, &stat);
+       if (err)
+               return err;
 
        if (slot->num != 0)
-               return -EFAULT;
+               return -EACCES;
 
        slot->type = CA_CI;
        slot->flags = fdtv_get_ca_flags(&stat);
@@ -81,21 +78,21 @@ static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
 {
        struct ca_msg *reply = arg;
 
-       return avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+       return avc_ca_app_info(fdtv, reply->msg, &reply->length);
 }
 
 static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
 {
        struct ca_msg *reply = arg;
 
-       return avc_ca_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+       return avc_ca_info(fdtv, reply->msg, &reply->length);
 }
 
 static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
 {
        struct ca_msg *reply = arg;
 
-       return avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+       return avc_ca_get_mmi(fdtv, reply->msg, &reply->length);
 }
 
 static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
@@ -111,14 +108,15 @@ static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
                err = fdtv_ca_info(fdtv, arg);
                break;
        default:
-               if (avc_tuner_status(fdtv, &stat))
-                       err = -EFAULT;
-               else if (stat.ca_mmi == 1)
+               err = avc_tuner_status(fdtv, &stat);
+               if (err)
+                       break;
+               if (stat.ca_mmi == 1)
                        err = fdtv_ca_get_mmi(fdtv, arg);
                else {
                        dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
                                 fdtv->ca_last_command);
-                       err = -EFAULT;
+                       err = -EACCES;
                }
        }
        fdtv->ca_last_command = 0;
@@ -141,7 +139,7 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
                data_length = msg->msg[3];
        }
 
-       return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? -EFAULT : 0;
+       return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
 }
 
 static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
@@ -170,7 +168,7 @@ static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
        default:
                dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
                        fdtv->ca_last_command);
-               err = -EFAULT;
+               err = -EACCES;
        }
        return err;
 }
@@ -184,7 +182,7 @@ static int fdtv_ca_ioctl(struct file *file, unsigned int cmd, void *arg)
 
        switch (cmd) {
        case CA_RESET:
-               err = fdtv_ca_reset(fdtv);
+               err = avc_ca_reset(fdtv);
                break;
        case CA_GET_CAP:
                err = fdtv_ca_get_caps(arg);
index 44b816f..32e08e3 100644 (file)
@@ -49,6 +49,27 @@ config DVB_STV6110x
        help
          A Silicon tuner that supports DVB-S and DVB-S2 modes
 
+comment "Multistandard (cable + terrestrial) frontends"
+       depends on DVB_CORE
+
+config DVB_DRXK
+       tristate "Micronas DRXK based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         Micronas DRX-K DVB-C/T demodulator.
+
+         Say Y when you want to support this frontend.
+
+config DVB_TDA18271C2DD
+       tristate "NXP TDA18271C2 silicon tuner"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         NXP TDA18271 silicon tuner.
+
+         Say Y when you want to support this tuner.
+
 comment "DVB-S (satellite) frontends"
        depends on DVB_CORE
 
index 2f3a6f7..6a6ba05 100644 (file)
@@ -10,6 +10,7 @@ stv0900-objs = stv0900_core.o stv0900_sw.o
 au8522-objs = au8522_dig.o au8522_decoder.o
 drxd-objs = drxd_firm.o drxd_hard.o
 cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
+drxk-objs := drxk_hard.o
 
 obj-$(CONFIG_DVB_PLL) += dvb-pll.o
 obj-$(CONFIG_DVB_STV0299) += stv0299.o
@@ -88,4 +89,6 @@ obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
 obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
 obj-$(CONFIG_DVB_STV0367) += stv0367.o
 obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
+obj-$(CONFIG_DVB_DRXK) += drxk.o
+obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
 
index b537891..2b248c1 100644 (file)
@@ -692,7 +692,7 @@ static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
        /* Interrogate the decoder to see if we are getting a real signal */
        lock_status = au8522_readreg(state, 0x00);
        if (lock_status == 0xa2)
-               vt->signal = 0x01;
+               vt->signal = 0xffff;
        else
                vt->signal = 0x00;
 
index e9ee555..c341d57 100644 (file)
@@ -31,8 +31,8 @@
 
 static int debug;
 
-#define info(args...) do { printk(KERN_INFO "CX24113: " args); } while (0)
-#define err(args...)  do { printk(KERN_ERR  "CX24113: " args); } while (0)
+#define cx_info(args...) do { printk(KERN_INFO "CX24113: " args); } while (0)
+#define cx_err(args...)  do { printk(KERN_ERR  "CX24113: " args); } while (0)
 
 #define dprintk(args...) \
        do { \
@@ -341,7 +341,7 @@ static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f)
        } while (N < 6 && R < 3);
 
        if (N < 6) {
-               err("strange frequency: N < 6\n");
+               cx_err("strange frequency: N < 6\n");
                return;
        }
        F = freq_hz;
@@ -563,7 +563,7 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
                kzalloc(sizeof(struct cx24113_state), GFP_KERNEL);
        int rc;
        if (state == NULL) {
-               err("Unable to kzalloc\n");
+               cx_err("Unable to kzalloc\n");
                goto error;
        }
 
@@ -571,7 +571,7 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
        state->config = config;
        state->i2c = i2c;
 
-       info("trying to detect myself\n");
+       cx_info("trying to detect myself\n");
 
        /* making a dummy read, because of some expected troubles
         * after power on */
@@ -579,24 +579,24 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
 
        rc = cx24113_readreg(state, 0x00);
        if (rc < 0) {
-               info("CX24113 not found.\n");
+               cx_info("CX24113 not found.\n");
                goto error;
        }
        state->rev = rc;
 
        switch (rc) {
        case 0x43:
-               info("detected CX24113 variant\n");
+               cx_info("detected CX24113 variant\n");
                break;
        case REV_CX24113:
-               info("successfully detected\n");
+               cx_info("successfully detected\n");
                break;
        default:
-               err("unsupported device id: %x\n", state->rev);
+               cx_err("unsupported device id: %x\n", state->rev);
                goto error;
        }
        state->ver = cx24113_readreg(state, 0x01);
-       info("version: %x\n", state->ver);
+       cx_info("version: %x\n", state->ver);
 
        /* create dvb_frontend */
        memcpy(&fe->ops.tuner_ops, &cx24113_tuner_ops,
index 95c6465..ccd0525 100644 (file)
@@ -1452,11 +1452,7 @@ tuned:  /* Set/Reset B/W */
        cmd.args[0x00] = CMD_BANDWIDTH;
        cmd.args[0x01] = 0x00;
        cmd.len = 0x02;
-       ret = cx24116_cmd_execute(fe, &cmd);
-       if (ret != 0)
-               return ret;
-
-       return ret;
+       return cx24116_cmd_execute(fe, &cmd);
 }
 
 static int cx24116_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *params,
index ad17845..2906582 100644 (file)
@@ -55,13 +55,13 @@ struct cxd2820r_config {
         * Default: 0
         * Values: 0, 1
         */
-       int if_agc_polarity:1;
+       bool if_agc_polarity;
 
        /* Spectrum inversion.
         * Default: 0
         * Values: 0, 1
         */
-       int spec_inv:1;
+       bool spec_inv;
 
        /* IFs for all used modes.
         * Default: none, must set
index 0779f69..d416e85 100644 (file)
@@ -314,6 +314,8 @@ static int cxd2820r_set_frontend(struct dvb_frontend *fe,
                        } else if (c->delivery_system == SYS_DVBT2) {
                                /* DVB-T => DVB-T2 */
                                ret = cxd2820r_sleep_t(fe);
+                               if (ret)
+                                       break;
                                ret = cxd2820r_set_frontend_t2(fe, p);
                        }
                        break;
@@ -324,6 +326,8 @@ static int cxd2820r_set_frontend(struct dvb_frontend *fe,
                        } else if (c->delivery_system == SYS_DVBT) {
                                /* DVB-T2 => DVB-T */
                                ret = cxd2820r_sleep_t2(fe);
+                               if (ret)
+                                       break;
                                ret = cxd2820r_set_frontend_t(fe, p);
                        }
                        break;
@@ -740,12 +744,13 @@ static int cxd2820r_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
        struct i2c_msg msg[], int num)
 {
        struct cxd2820r_priv *priv = i2c_get_adapdata(i2c_adap);
-       u8 obuf[msg[0].len + 2];
+       int ret;
+       u8 *obuf = kmalloc(msg[0].len + 2, GFP_KERNEL);
        struct i2c_msg msg2[2] = {
                {
                        .addr = priv->cfg.i2c_address,
                        .flags = 0,
-                       .len = sizeof(obuf),
+                       .len = msg[0].len + 2,
                        .buf = obuf,
                }, {
                        .addr = priv->cfg.i2c_address,
@@ -755,15 +760,24 @@ static int cxd2820r_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
                }
        };
 
+       if (!obuf)
+               return -ENOMEM;
+
        obuf[0] = 0x09;
        obuf[1] = (msg[0].addr << 1);
        if (num == 2) { /* I2C read */
                obuf[1] = (msg[0].addr << 1) | I2C_M_RD; /* I2C RD flag */
-               msg2[0].len = sizeof(obuf) - 1; /* maybe HW bug ? */
+               msg2[0].len = msg[0].len + 2 - 1; /* '-1' maybe HW bug ? */
        }
        memcpy(&obuf[2], msg[0].buf, msg[0].len);
 
-       return i2c_transfer(priv->i2c, msg2, num);
+       ret = i2c_transfer(priv->i2c, msg2, num);
+       if (ret < 0)
+               warn("tuner i2c failed ret:%d", ret);
+
+       kfree(obuf);
+
+       return ret;
 }
 
 static struct i2c_algorithm cxd2820r_tuner_i2c_algo = {
index 25adbee..0c0ebc9 100644 (file)
@@ -55,13 +55,13 @@ struct cxd2820r_priv {
        struct mutex fe_lock; /* FE lock */
        int active_fe:2; /* FE lock, -1=NONE, 0=DVB-T/T2, 1=DVB-C */
 
-       int ber_running:1;
+       bool ber_running;
 
        u8 bank[2];
        u8 gpio[3];
 
        fe_delivery_system_t delivery_system;
-       int last_tune_failed:1; /* for switch between T and T2 tune */
+       bool last_tune_failed; /* for switch between T and T2 tune */
 };
 
 /* cxd2820r_core.c */
index 0c9f40c..a64a538 100644 (file)
@@ -2336,6 +2336,11 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
                request_firmware() will hit an OOPS (this should be moved somewhere
                more common) */
 
+       /* FIXME: make sure the dev.parent field is initialized, or else
+          request_firmware() will hit an OOPS (this should be moved somewhere
+          more common) */
+       st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
+
        dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
 
        /* init 7090 tuner adapter */
index ea4c1c3..2238bf0 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/delay.h>
 #include <linux/firmware.h>
 #include <linux/i2c.h>
-#include <linux/version.h>
 #include <asm/div64.h>
 
 #include "dvb_frontend.h"
@@ -233,7 +232,7 @@ static int i2c_read(struct i2c_adapter *adap,
        return 0;
 }
 
-inline u32 MulDiv32(u32 a, u32 b, u32 c)
+static inline u32 MulDiv32(u32 a, u32 b, u32 c)
 {
        u64 tmp64;
 
@@ -910,14 +909,16 @@ static int load_firmware(struct drxd_state *state, const char *fw_name)
                return -EIO;
        }
 
-       state->microcode = kzalloc(fw->size, GFP_KERNEL);
+       state->microcode = kmalloc(fw->size, GFP_KERNEL);
        if (state->microcode == NULL) {
-               printk(KERN_ERR "drxd: firmware load failure: nomemory\n");
+               release_firmware(fw);
+               printk(KERN_ERR "drxd: firmware load failure: no memory\n");
                return -ENOMEM;
        }
 
        memcpy(state->microcode, fw->data, fw->size);
        state->microcode_length = fw->size;
+       release_firmware(fw);
        return 0;
 }
 
diff --git a/drivers/media/dvb/frontends/drxk.h b/drivers/media/dvb/frontends/drxk.h
new file mode 100644 (file)
index 0000000..58baf41
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef _DRXK_H_
+#define _DRXK_H_
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+
+/**
+ * struct drxk_config - Configure the initial parameters for DRX-K
+ *
+ * adr:                        I2C Address of the DRX-K
+ * single_master:      Device is on the single master mode
+ * no_i2c_bridge:      Don't switch the I2C bridge to talk with tuner
+ * antenna_gpio:       GPIO bit used to control the antenna
+ * antenna_dvbt:       GPIO bit for changing antenna to DVB-C. A value of 1
+ *                     means that 1=DVBC, 0 = DVBT. Zero means the opposite.
+ * microcode_name:     Name of the firmware file with the microcode
+ *
+ * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is
+ * UIO-3.
+ */
+struct drxk_config {
+       u8      adr;
+       bool    single_master;
+       bool    no_i2c_bridge;
+
+       bool    antenna_dvbt;
+       u16     antenna_gpio;
+
+       const char *microcode_name;
+};
+
+#if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \
+        && defined(MODULE))
+extern struct dvb_frontend *drxk_attach(const struct drxk_config *config,
+                                       struct i2c_adapter *i2c,
+                                       struct dvb_frontend **fe_t);
+#else
+static inline struct dvb_frontend *drxk_attach(const struct drxk_config *config,
+                                       struct i2c_adapter *i2c,
+                                       struct dvb_frontend **fe_t)
+{
+        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+        return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c
new file mode 100644 (file)
index 0000000..41b0838
--- /dev/null
@@ -0,0 +1,6454 @@
+/*
+ * drxk_hard: DRX-K DVB-C/T demodulator driver
+ *
+ * Copyright (C) 2010-2011 Digital Devices GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * 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
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/version.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "drxk.h"
+#include "drxk_hard.h"
+
+static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode);
+static int PowerDownQAM(struct drxk_state *state);
+static int SetDVBTStandard(struct drxk_state *state,
+                          enum OperationMode oMode);
+static int SetQAMStandard(struct drxk_state *state,
+                         enum OperationMode oMode);
+static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
+                 s32 tunerFreqOffset);
+static int SetDVBTStandard(struct drxk_state *state,
+                          enum OperationMode oMode);
+static int DVBTStart(struct drxk_state *state);
+static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
+                  s32 tunerFreqOffset);
+static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus);
+static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus);
+static int SwitchAntennaToQAM(struct drxk_state *state);
+static int SwitchAntennaToDVBT(struct drxk_state *state);
+
+static bool IsDVBT(struct drxk_state *state)
+{
+       return state->m_OperationMode == OM_DVBT;
+}
+
+static bool IsQAM(struct drxk_state *state)
+{
+       return state->m_OperationMode == OM_QAM_ITU_A ||
+           state->m_OperationMode == OM_QAM_ITU_B ||
+           state->m_OperationMode == OM_QAM_ITU_C;
+}
+
+bool IsA1WithPatchCode(struct drxk_state *state)
+{
+       return state->m_DRXK_A1_PATCH_CODE;
+}
+
+bool IsA1WithRomCode(struct drxk_state *state)
+{
+       return state->m_DRXK_A1_ROM_CODE;
+}
+
+#define NOA1ROM 0
+
+#define DRXDAP_FASI_SHORT_FORMAT(addr) (((addr) & 0xFC30FF80) == 0)
+#define DRXDAP_FASI_LONG_FORMAT(addr)  (((addr) & 0xFC30FF80) != 0)
+
+#define DEFAULT_MER_83  165
+#define DEFAULT_MER_93  250
+
+#ifndef DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH
+#define DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH (0x02)
+#endif
+
+#ifndef DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH
+#define DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH (0x03)
+#endif
+
+#ifndef DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH
+#define DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH (0x06)
+#endif
+
+#define DEFAULT_DRXK_MPEG_LOCK_TIMEOUT 700
+#define DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT 500
+
+#ifndef DRXK_KI_RAGC_ATV
+#define DRXK_KI_RAGC_ATV   4
+#endif
+#ifndef DRXK_KI_IAGC_ATV
+#define DRXK_KI_IAGC_ATV   6
+#endif
+#ifndef DRXK_KI_DAGC_ATV
+#define DRXK_KI_DAGC_ATV   7
+#endif
+
+#ifndef DRXK_KI_RAGC_QAM
+#define DRXK_KI_RAGC_QAM   3
+#endif
+#ifndef DRXK_KI_IAGC_QAM
+#define DRXK_KI_IAGC_QAM   4
+#endif
+#ifndef DRXK_KI_DAGC_QAM
+#define DRXK_KI_DAGC_QAM   7
+#endif
+#ifndef DRXK_KI_RAGC_DVBT
+#define DRXK_KI_RAGC_DVBT  (IsA1WithPatchCode(state) ? 3 : 2)
+#endif
+#ifndef DRXK_KI_IAGC_DVBT
+#define DRXK_KI_IAGC_DVBT  (IsA1WithPatchCode(state) ? 4 : 2)
+#endif
+#ifndef DRXK_KI_DAGC_DVBT
+#define DRXK_KI_DAGC_DVBT  (IsA1WithPatchCode(state) ? 10 : 7)
+#endif
+
+#ifndef DRXK_AGC_DAC_OFFSET
+#define DRXK_AGC_DAC_OFFSET (0x800)
+#endif
+
+#ifndef DRXK_BANDWIDTH_8MHZ_IN_HZ
+#define DRXK_BANDWIDTH_8MHZ_IN_HZ  (0x8B8249L)
+#endif
+
+#ifndef DRXK_BANDWIDTH_7MHZ_IN_HZ
+#define DRXK_BANDWIDTH_7MHZ_IN_HZ  (0x7A1200L)
+#endif
+
+#ifndef DRXK_BANDWIDTH_6MHZ_IN_HZ
+#define DRXK_BANDWIDTH_6MHZ_IN_HZ  (0x68A1B6L)
+#endif
+
+#ifndef DRXK_QAM_SYMBOLRATE_MAX
+#define DRXK_QAM_SYMBOLRATE_MAX         (7233000)
+#endif
+
+#define DRXK_BL_ROM_OFFSET_TAPS_DVBT    56
+#define DRXK_BL_ROM_OFFSET_TAPS_ITU_A   64
+#define DRXK_BL_ROM_OFFSET_TAPS_ITU_C   0x5FE0
+#define DRXK_BL_ROM_OFFSET_TAPS_BG      24
+#define DRXK_BL_ROM_OFFSET_TAPS_DKILLP  32
+#define DRXK_BL_ROM_OFFSET_TAPS_NTSC    40
+#define DRXK_BL_ROM_OFFSET_TAPS_FM      48
+#define DRXK_BL_ROM_OFFSET_UCODE        0
+
+#define DRXK_BLC_TIMEOUT                100
+
+#define DRXK_BLCC_NR_ELEMENTS_TAPS      2
+#define DRXK_BLCC_NR_ELEMENTS_UCODE     6
+
+#define DRXK_BLDC_NR_ELEMENTS_TAPS      28
+
+#ifndef DRXK_OFDM_NE_NOTCH_WIDTH
+#define DRXK_OFDM_NE_NOTCH_WIDTH             (4)
+#endif
+
+#define DRXK_QAM_SL_SIG_POWER_QAM16       (40960)
+#define DRXK_QAM_SL_SIG_POWER_QAM32       (20480)
+#define DRXK_QAM_SL_SIG_POWER_QAM64       (43008)
+#define DRXK_QAM_SL_SIG_POWER_QAM128      (20992)
+#define DRXK_QAM_SL_SIG_POWER_QAM256      (43520)
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+#define dprintk(level, fmt, arg...) do {                       \
+if (debug >= level)                                            \
+       printk(KERN_DEBUG "drxk: %s" fmt, __func__, ## arg);    \
+} while (0)
+
+
+static inline u32 MulDiv32(u32 a, u32 b, u32 c)
+{
+       u64 tmp64;
+
+       tmp64 = (u64) a * (u64) b;
+       do_div(tmp64, c);
+
+       return (u32) tmp64;
+}
+
+inline u32 Frac28a(u32 a, u32 c)
+{
+       int i = 0;
+       u32 Q1 = 0;
+       u32 R0 = 0;
+
+       R0 = (a % c) << 4;      /* 32-28 == 4 shifts possible at max */
+       Q1 = a / c;             /* integer part, only the 4 least significant bits
+                                  will be visible in the result */
+
+       /* division using radix 16, 7 nibbles in the result */
+       for (i = 0; i < 7; i++) {
+               Q1 = (Q1 << 4) | (R0 / c);
+               R0 = (R0 % c) << 4;
+       }
+       /* rounding */
+       if ((R0 >> 3) >= c)
+               Q1++;
+
+       return Q1;
+}
+
+static u32 Log10Times100(u32 x)
+{
+       static const u8 scale = 15;
+       static const u8 indexWidth = 5;
+       u8 i = 0;
+       u32 y = 0;
+       u32 d = 0;
+       u32 k = 0;
+       u32 r = 0;
+       /*
+          log2lut[n] = (1<<scale) * 200 * log2(1.0 + ((1.0/(1<<INDEXWIDTH)) * n))
+          0 <= n < ((1<<INDEXWIDTH)+1)
+        */
+
+       static const u32 log2lut[] = {
+               0,              /* 0.000000 */
+               290941,         /* 290941.300628 */
+               573196,         /* 573196.476418 */
+               847269,         /* 847269.179851 */
+               1113620,        /* 1113620.489452 */
+               1372674,        /* 1372673.576986 */
+               1624818,        /* 1624817.752104 */
+               1870412,        /* 1870411.981536 */
+               2109788,        /* 2109787.962654 */
+               2343253,        /* 2343252.817465 */
+               2571091,        /* 2571091.461923 */
+               2793569,        /* 2793568.696416 */
+               3010931,        /* 3010931.055901 */
+               3223408,        /* 3223408.452106 */
+               3431216,        /* 3431215.635215 */
+               3634553,        /* 3634553.498355 */
+               3833610,        /* 3833610.244726 */
+               4028562,        /* 4028562.434393 */
+               4219576,        /* 4219575.925308 */
+               4406807,        /* 4406806.721144 */
+               4590402,        /* 4590401.736809 */
+               4770499,        /* 4770499.491025 */
+               4947231,        /* 4947230.734179 */
+               5120719,        /* 5120719.018555 */
+               5291081,        /* 5291081.217197 */
+               5458428,        /* 5458427.996830 */
+               5622864,        /* 5622864.249668 */
+               5784489,        /* 5784489.488298 */
+               5943398,        /* 5943398.207380 */
+               6099680,        /* 6099680.215452 */
+               6253421,        /* 6253420.939751 */
+               6404702,        /* 6404701.706649 */
+               6553600,        /* 6553600.000000 */
+       };
+
+
+       if (x == 0)
+               return 0;
+
+       /* Scale x (normalize) */
+       /* computing y in log(x/y) = log(x) - log(y) */
+       if ((x & ((0xffffffff) << (scale + 1))) == 0) {
+               for (k = scale; k > 0; k--) {
+                       if (x & (((u32) 1) << scale))
+                               break;
+                       x <<= 1;
+               }
+       } else {
+               for (k = scale; k < 31; k++) {
+                       if ((x & (((u32) (-1)) << (scale + 1))) == 0)
+                               break;
+                       x >>= 1;
+               }
+       }
+       /*
+          Now x has binary point between bit[scale] and bit[scale-1]
+          and 1.0 <= x < 2.0 */
+
+       /* correction for divison: log(x) = log(x/y)+log(y) */
+       y = k * ((((u32) 1) << scale) * 200);
+
+       /* remove integer part */
+       x &= ((((u32) 1) << scale) - 1);
+       /* get index */
+       i = (u8) (x >> (scale - indexWidth));
+       /* compute delta (x - a) */
+       d = x & ((((u32) 1) << (scale - indexWidth)) - 1);
+       /* compute log, multiplication (d* (..)) must be within range ! */
+       y += log2lut[i] +
+           ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - indexWidth));
+       /* Conver to log10() */
+       y /= 108853;            /* (log2(10) << scale) */
+       r = (y >> 1);
+       /* rounding */
+       if (y & ((u32) 1))
+               r++;
+       return r;
+}
+
+/****************************************************************************/
+/* I2C **********************************************************************/
+/****************************************************************************/
+
+static int i2c_read1(struct i2c_adapter *adapter, u8 adr, u8 *val)
+{
+       struct i2c_msg msgs[1] = { {.addr = adr, .flags = I2C_M_RD,
+                                   .buf = val, .len = 1}
+       };
+
+       return i2c_transfer(adapter, msgs, 1);
+}
+
+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
+{
+       int status;
+       struct i2c_msg msg = {
+           .addr = adr, .flags = 0, .buf = data, .len = len };
+
+       dprintk(3, ":");
+       if (debug > 2) {
+               int i;
+               for (i = 0; i < len; i++)
+                       printk(KERN_CONT " %02x", data[i]);
+               printk(KERN_CONT "\n");
+       }
+       status = i2c_transfer(adap, &msg, 1);
+       if (status >= 0 && status != 1)
+               status = -EIO;
+
+       if (status < 0)
+               printk(KERN_ERR "drxk: i2c write error at addr 0x%02x\n", adr);
+
+       return status;
+}
+
+static int i2c_read(struct i2c_adapter *adap,
+                   u8 adr, u8 *msg, int len, u8 *answ, int alen)
+{
+       int status;
+       struct i2c_msg msgs[2] = {
+               {.addr = adr, .flags = 0,
+                                   .buf = msg, .len = len},
+               {.addr = adr, .flags = I2C_M_RD,
+                .buf = answ, .len = alen}
+       };
+
+       status = i2c_transfer(adap, msgs, 2);
+       if (status != 2) {
+               if (debug > 2)
+                       printk(KERN_CONT ": ERROR!\n");
+               if (status >= 0)
+                       status = -EIO;
+
+               printk(KERN_ERR "drxk: i2c read error at addr 0x%02x\n", adr);
+               return status;
+       }
+       if (debug > 2) {
+               int i;
+               dprintk(2, ": read from ");
+               for (i = 0; i < len; i++)
+                       printk(KERN_CONT " %02x", msg[i]);
+               printk(KERN_CONT "Value = ");
+               for (i = 0; i < alen; i++)
+                       printk(KERN_CONT " %02x", answ[i]);
+               printk(KERN_CONT "\n");
+       }
+       return 0;
+}
+
+static int read16_flags(struct drxk_state *state, u32 reg, u16 *data, u8 flags)
+{
+       int status;
+       u8 adr = state->demod_address, mm1[4], mm2[2], len;
+
+       if (state->single_master)
+               flags |= 0xC0;
+
+       if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
+               mm1[0] = (((reg << 1) & 0xFF) | 0x01);
+               mm1[1] = ((reg >> 16) & 0xFF);
+               mm1[2] = ((reg >> 24) & 0xFF) | flags;
+               mm1[3] = ((reg >> 7) & 0xFF);
+               len = 4;
+       } else {
+               mm1[0] = ((reg << 1) & 0xFF);
+               mm1[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
+               len = 2;
+       }
+       dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
+       status = i2c_read(state->i2c, adr, mm1, len, mm2, 2);
+       if (status < 0)
+               return status;
+       if (data)
+               *data = mm2[0] | (mm2[1] << 8);
+
+       return 0;
+}
+
+static int read16(struct drxk_state *state, u32 reg, u16 *data)
+{
+       return read16_flags(state, reg, data, 0);
+}
+
+static int read32_flags(struct drxk_state *state, u32 reg, u32 *data, u8 flags)
+{
+       int status;
+       u8 adr = state->demod_address, mm1[4], mm2[4], len;
+
+       if (state->single_master)
+               flags |= 0xC0;
+
+       if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
+               mm1[0] = (((reg << 1) & 0xFF) | 0x01);
+               mm1[1] = ((reg >> 16) & 0xFF);
+               mm1[2] = ((reg >> 24) & 0xFF) | flags;
+               mm1[3] = ((reg >> 7) & 0xFF);
+               len = 4;
+       } else {
+               mm1[0] = ((reg << 1) & 0xFF);
+               mm1[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
+               len = 2;
+       }
+       dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
+       status = i2c_read(state->i2c, adr, mm1, len, mm2, 4);
+       if (status < 0)
+               return status;
+       if (data)
+               *data = mm2[0] | (mm2[1] << 8) |
+                   (mm2[2] << 16) | (mm2[3] << 24);
+
+       return 0;
+}
+
+static int read32(struct drxk_state *state, u32 reg, u32 *data)
+{
+       return read32_flags(state, reg, data, 0);
+}
+
+static int write16_flags(struct drxk_state *state, u32 reg, u16 data, u8 flags)
+{
+       u8 adr = state->demod_address, mm[6], len;
+
+       if (state->single_master)
+               flags |= 0xC0;
+       if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
+               mm[0] = (((reg << 1) & 0xFF) | 0x01);
+               mm[1] = ((reg >> 16) & 0xFF);
+               mm[2] = ((reg >> 24) & 0xFF) | flags;
+               mm[3] = ((reg >> 7) & 0xFF);
+               len = 4;
+       } else {
+               mm[0] = ((reg << 1) & 0xFF);
+               mm[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
+               len = 2;
+       }
+       mm[len] = data & 0xff;
+       mm[len + 1] = (data >> 8) & 0xff;
+
+       dprintk(2, "(0x%08x, 0x%04x, 0x%02x)\n", reg, data, flags);
+       return i2c_write(state->i2c, adr, mm, len + 2);
+}
+
+static int write16(struct drxk_state *state, u32 reg, u16 data)
+{
+       return write16_flags(state, reg, data, 0);
+}
+
+static int write32_flags(struct drxk_state *state, u32 reg, u32 data, u8 flags)
+{
+       u8 adr = state->demod_address, mm[8], len;
+
+       if (state->single_master)
+               flags |= 0xC0;
+       if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
+               mm[0] = (((reg << 1) & 0xFF) | 0x01);
+               mm[1] = ((reg >> 16) & 0xFF);
+               mm[2] = ((reg >> 24) & 0xFF) | flags;
+               mm[3] = ((reg >> 7) & 0xFF);
+               len = 4;
+       } else {
+               mm[0] = ((reg << 1) & 0xFF);
+               mm[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
+               len = 2;
+       }
+       mm[len] = data & 0xff;
+       mm[len + 1] = (data >> 8) & 0xff;
+       mm[len + 2] = (data >> 16) & 0xff;
+       mm[len + 3] = (data >> 24) & 0xff;
+       dprintk(2, "(0x%08x, 0x%08x, 0x%02x)\n", reg, data, flags);
+
+       return i2c_write(state->i2c, adr, mm, len + 4);
+}
+
+static int write32(struct drxk_state *state, u32 reg, u32 data)
+{
+       return write32_flags(state, reg, data, 0);
+}
+
+static int write_block(struct drxk_state *state, u32 Address,
+                     const int BlockSize, const u8 pBlock[])
+{
+       int status = 0, BlkSize = BlockSize;
+       u8 Flags = 0;
+
+       if (state->single_master)
+               Flags |= 0xC0;
+
+       while (BlkSize > 0) {
+               int Chunk = BlkSize > state->m_ChunkSize ?
+                   state->m_ChunkSize : BlkSize;
+               u8 *AdrBuf = &state->Chunk[0];
+               u32 AdrLength = 0;
+
+               if (DRXDAP_FASI_LONG_FORMAT(Address) || (Flags != 0)) {
+                       AdrBuf[0] = (((Address << 1) & 0xFF) | 0x01);
+                       AdrBuf[1] = ((Address >> 16) & 0xFF);
+                       AdrBuf[2] = ((Address >> 24) & 0xFF);
+                       AdrBuf[3] = ((Address >> 7) & 0xFF);
+                       AdrBuf[2] |= Flags;
+                       AdrLength = 4;
+                       if (Chunk == state->m_ChunkSize)
+                               Chunk -= 2;
+               } else {
+                       AdrBuf[0] = ((Address << 1) & 0xFF);
+                       AdrBuf[1] = (((Address >> 16) & 0x0F) |
+                                    ((Address >> 18) & 0xF0));
+                       AdrLength = 2;
+               }
+               memcpy(&state->Chunk[AdrLength], pBlock, Chunk);
+               dprintk(2, "(0x%08x, 0x%02x)\n", Address, Flags);
+               if (debug > 1) {
+                       int i;
+                       if (pBlock)
+                               for (i = 0; i < Chunk; i++)
+                                       printk(KERN_CONT " %02x", pBlock[i]);
+                       printk(KERN_CONT "\n");
+               }
+               status = i2c_write(state->i2c, state->demod_address,
+                                  &state->Chunk[0], Chunk + AdrLength);
+               if (status < 0) {
+                       printk(KERN_ERR "drxk: %s: i2c write error at addr 0x%02x\n",
+                              __func__, Address);
+                       break;
+               }
+               pBlock += Chunk;
+               Address += (Chunk >> 1);
+               BlkSize -= Chunk;
+       }
+       return status;
+}
+
+#ifndef DRXK_MAX_RETRIES_POWERUP
+#define DRXK_MAX_RETRIES_POWERUP 20
+#endif
+
+int PowerUpDevice(struct drxk_state *state)
+{
+       int status;
+       u8 data = 0;
+       u16 retryCount = 0;
+
+       dprintk(1, "\n");
+
+       status = i2c_read1(state->i2c, state->demod_address, &data);
+       if (status < 0) {
+               do {
+                       data = 0;
+                       status = i2c_write(state->i2c, state->demod_address,
+                                          &data, 1);
+                       msleep(10);
+                       retryCount++;
+                       if (status < 0)
+                               continue;
+                       status = i2c_read1(state->i2c, state->demod_address,
+                                          &data);
+               } while (status < 0 &&
+                        (retryCount < DRXK_MAX_RETRIES_POWERUP));
+               if (status < 0 && retryCount >= DRXK_MAX_RETRIES_POWERUP)
+                       goto error;
+       }
+
+       /* Make sure all clk domains are active */
+       status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_NONE);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
+       if (status < 0)
+               goto error;
+       /* Enable pll lock tests */
+       status = write16(state, SIO_CC_PLL_LOCK__A, 1);
+       if (status < 0)
+               goto error;
+
+       state->m_currentPowerMode = DRX_POWER_UP;
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+
+static int init_state(struct drxk_state *state)
+{
+       /*
+        * FIXME: most (all?) of the values bellow should be moved into
+        * struct drxk_config, as they are probably board-specific
+        */
+       u32 ulVSBIfAgcMode = DRXK_AGC_CTRL_AUTO;
+       u32 ulVSBIfAgcOutputLevel = 0;
+       u32 ulVSBIfAgcMinLevel = 0;
+       u32 ulVSBIfAgcMaxLevel = 0x7FFF;
+       u32 ulVSBIfAgcSpeed = 3;
+
+       u32 ulVSBRfAgcMode = DRXK_AGC_CTRL_AUTO;
+       u32 ulVSBRfAgcOutputLevel = 0;
+       u32 ulVSBRfAgcMinLevel = 0;
+       u32 ulVSBRfAgcMaxLevel = 0x7FFF;
+       u32 ulVSBRfAgcSpeed = 3;
+       u32 ulVSBRfAgcTop = 9500;
+       u32 ulVSBRfAgcCutOffCurrent = 4000;
+
+       u32 ulATVIfAgcMode = DRXK_AGC_CTRL_AUTO;
+       u32 ulATVIfAgcOutputLevel = 0;
+       u32 ulATVIfAgcMinLevel = 0;
+       u32 ulATVIfAgcMaxLevel = 0;
+       u32 ulATVIfAgcSpeed = 3;
+
+       u32 ulATVRfAgcMode = DRXK_AGC_CTRL_OFF;
+       u32 ulATVRfAgcOutputLevel = 0;
+       u32 ulATVRfAgcMinLevel = 0;
+       u32 ulATVRfAgcMaxLevel = 0;
+       u32 ulATVRfAgcTop = 9500;
+       u32 ulATVRfAgcCutOffCurrent = 4000;
+       u32 ulATVRfAgcSpeed = 3;
+
+       u32 ulQual83 = DEFAULT_MER_83;
+       u32 ulQual93 = DEFAULT_MER_93;
+
+       u32 ulDVBTStaticTSClock = 1;
+       u32 ulDVBCStaticTSClock = 1;
+
+       u32 ulMpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT;
+       u32 ulDemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT;
+
+       /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
+       /* io_pad_cfg_mode output mode is drive always */
+       /* io_pad_cfg_drive is set to power 2 (23 mA) */
+       u32 ulGPIOCfg = 0x0113;
+       u32 ulSerialMode = 1;
+       u32 ulInvertTSClock = 0;
+       u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH;
+       u32 ulTSClockkStrength = DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH;
+       u32 ulDVBTBitrate = 50000000;
+       u32 ulDVBCBitrate = DRXK_QAM_SYMBOLRATE_MAX * 8;
+
+       u32 ulInsertRSByte = 0;
+
+       u32 ulRfMirror = 1;
+       u32 ulPowerDown = 0;
+
+       dprintk(1, "\n");
+
+       state->m_hasLNA = false;
+       state->m_hasDVBT = false;
+       state->m_hasDVBC = false;
+       state->m_hasATV = false;
+       state->m_hasOOB = false;
+       state->m_hasAudio = false;
+
+       state->m_ChunkSize = 124;
+
+       state->m_oscClockFreq = 0;
+       state->m_smartAntInverted = false;
+       state->m_bPDownOpenBridge = false;
+
+       /* real system clock frequency in kHz */
+       state->m_sysClockFreq = 151875;
+       /* Timing div, 250ns/Psys */
+       /* Timing div, = (delay (nano seconds) * sysclk (kHz))/ 1000 */
+       state->m_HICfgTimingDiv = ((state->m_sysClockFreq / 1000) *
+                                  HI_I2C_DELAY) / 1000;
+       /* Clipping */
+       if (state->m_HICfgTimingDiv > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M)
+               state->m_HICfgTimingDiv = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M;
+       state->m_HICfgWakeUpKey = (state->demod_address << 1);
+       /* port/bridge/power down ctrl */
+       state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE;
+
+       state->m_bPowerDown = (ulPowerDown != 0);
+
+       state->m_DRXK_A1_PATCH_CODE = false;
+       state->m_DRXK_A1_ROM_CODE = false;
+       state->m_DRXK_A2_ROM_CODE = false;
+       state->m_DRXK_A3_ROM_CODE = false;
+       state->m_DRXK_A2_PATCH_CODE = false;
+       state->m_DRXK_A3_PATCH_CODE = false;
+
+       /* Init AGC and PGA parameters */
+       /* VSB IF */
+       state->m_vsbIfAgcCfg.ctrlMode = (ulVSBIfAgcMode);
+       state->m_vsbIfAgcCfg.outputLevel = (ulVSBIfAgcOutputLevel);
+       state->m_vsbIfAgcCfg.minOutputLevel = (ulVSBIfAgcMinLevel);
+       state->m_vsbIfAgcCfg.maxOutputLevel = (ulVSBIfAgcMaxLevel);
+       state->m_vsbIfAgcCfg.speed = (ulVSBIfAgcSpeed);
+       state->m_vsbPgaCfg = 140;
+
+       /* VSB RF */
+       state->m_vsbRfAgcCfg.ctrlMode = (ulVSBRfAgcMode);
+       state->m_vsbRfAgcCfg.outputLevel = (ulVSBRfAgcOutputLevel);
+       state->m_vsbRfAgcCfg.minOutputLevel = (ulVSBRfAgcMinLevel);
+       state->m_vsbRfAgcCfg.maxOutputLevel = (ulVSBRfAgcMaxLevel);
+       state->m_vsbRfAgcCfg.speed = (ulVSBRfAgcSpeed);
+       state->m_vsbRfAgcCfg.top = (ulVSBRfAgcTop);
+       state->m_vsbRfAgcCfg.cutOffCurrent = (ulVSBRfAgcCutOffCurrent);
+       state->m_vsbPreSawCfg.reference = 0x07;
+       state->m_vsbPreSawCfg.usePreSaw = true;
+
+       state->m_Quality83percent = DEFAULT_MER_83;
+       state->m_Quality93percent = DEFAULT_MER_93;
+       if (ulQual93 <= 500 && ulQual83 < ulQual93) {
+               state->m_Quality83percent = ulQual83;
+               state->m_Quality93percent = ulQual93;
+       }
+
+       /* ATV IF */
+       state->m_atvIfAgcCfg.ctrlMode = (ulATVIfAgcMode);
+       state->m_atvIfAgcCfg.outputLevel = (ulATVIfAgcOutputLevel);
+       state->m_atvIfAgcCfg.minOutputLevel = (ulATVIfAgcMinLevel);
+       state->m_atvIfAgcCfg.maxOutputLevel = (ulATVIfAgcMaxLevel);
+       state->m_atvIfAgcCfg.speed = (ulATVIfAgcSpeed);
+
+       /* ATV RF */
+       state->m_atvRfAgcCfg.ctrlMode = (ulATVRfAgcMode);
+       state->m_atvRfAgcCfg.outputLevel = (ulATVRfAgcOutputLevel);
+       state->m_atvRfAgcCfg.minOutputLevel = (ulATVRfAgcMinLevel);
+       state->m_atvRfAgcCfg.maxOutputLevel = (ulATVRfAgcMaxLevel);
+       state->m_atvRfAgcCfg.speed = (ulATVRfAgcSpeed);
+       state->m_atvRfAgcCfg.top = (ulATVRfAgcTop);
+       state->m_atvRfAgcCfg.cutOffCurrent = (ulATVRfAgcCutOffCurrent);
+       state->m_atvPreSawCfg.reference = 0x04;
+       state->m_atvPreSawCfg.usePreSaw = true;
+
+
+       /* DVBT RF */
+       state->m_dvbtRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF;
+       state->m_dvbtRfAgcCfg.outputLevel = 0;
+       state->m_dvbtRfAgcCfg.minOutputLevel = 0;
+       state->m_dvbtRfAgcCfg.maxOutputLevel = 0xFFFF;
+       state->m_dvbtRfAgcCfg.top = 0x2100;
+       state->m_dvbtRfAgcCfg.cutOffCurrent = 4000;
+       state->m_dvbtRfAgcCfg.speed = 1;
+
+
+       /* DVBT IF */
+       state->m_dvbtIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO;
+       state->m_dvbtIfAgcCfg.outputLevel = 0;
+       state->m_dvbtIfAgcCfg.minOutputLevel = 0;
+       state->m_dvbtIfAgcCfg.maxOutputLevel = 9000;
+       state->m_dvbtIfAgcCfg.top = 13424;
+       state->m_dvbtIfAgcCfg.cutOffCurrent = 0;
+       state->m_dvbtIfAgcCfg.speed = 3;
+       state->m_dvbtIfAgcCfg.FastClipCtrlDelay = 30;
+       state->m_dvbtIfAgcCfg.IngainTgtMax = 30000;
+       /* state->m_dvbtPgaCfg = 140; */
+
+       state->m_dvbtPreSawCfg.reference = 4;
+       state->m_dvbtPreSawCfg.usePreSaw = false;
+
+       /* QAM RF */
+       state->m_qamRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF;
+       state->m_qamRfAgcCfg.outputLevel = 0;
+       state->m_qamRfAgcCfg.minOutputLevel = 6023;
+       state->m_qamRfAgcCfg.maxOutputLevel = 27000;
+       state->m_qamRfAgcCfg.top = 0x2380;
+       state->m_qamRfAgcCfg.cutOffCurrent = 4000;
+       state->m_qamRfAgcCfg.speed = 3;
+
+       /* QAM IF */
+       state->m_qamIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO;
+       state->m_qamIfAgcCfg.outputLevel = 0;
+       state->m_qamIfAgcCfg.minOutputLevel = 0;
+       state->m_qamIfAgcCfg.maxOutputLevel = 9000;
+       state->m_qamIfAgcCfg.top = 0x0511;
+       state->m_qamIfAgcCfg.cutOffCurrent = 0;
+       state->m_qamIfAgcCfg.speed = 3;
+       state->m_qamIfAgcCfg.IngainTgtMax = 5119;
+       state->m_qamIfAgcCfg.FastClipCtrlDelay = 50;
+
+       state->m_qamPgaCfg = 140;
+       state->m_qamPreSawCfg.reference = 4;
+       state->m_qamPreSawCfg.usePreSaw = false;
+
+       state->m_OperationMode = OM_NONE;
+       state->m_DrxkState = DRXK_UNINITIALIZED;
+
+       /* MPEG output configuration */
+       state->m_enableMPEGOutput = true;       /* If TRUE; enable MPEG ouput */
+       state->m_insertRSByte = false;  /* If TRUE; insert RS byte */
+       state->m_enableParallel = true; /* If TRUE;
+                                          parallel out otherwise serial */
+       state->m_invertDATA = false;    /* If TRUE; invert DATA signals */
+       state->m_invertERR = false;     /* If TRUE; invert ERR signal */
+       state->m_invertSTR = false;     /* If TRUE; invert STR signals */
+       state->m_invertVAL = false;     /* If TRUE; invert VAL signals */
+       state->m_invertCLK = (ulInvertTSClock != 0);    /* If TRUE; invert CLK signals */
+       state->m_DVBTStaticCLK = (ulDVBTStaticTSClock != 0);
+       state->m_DVBCStaticCLK = (ulDVBCStaticTSClock != 0);
+       /* If TRUE; static MPEG clockrate will be used;
+          otherwise clockrate will adapt to the bitrate of the TS */
+
+       state->m_DVBTBitrate = ulDVBTBitrate;
+       state->m_DVBCBitrate = ulDVBCBitrate;
+
+       state->m_TSDataStrength = (ulTSDataStrength & 0x07);
+       state->m_TSClockkStrength = (ulTSClockkStrength & 0x07);
+
+       /* Maximum bitrate in b/s in case static clockrate is selected */
+       state->m_mpegTsStaticBitrate = 19392658;
+       state->m_disableTEIhandling = false;
+
+       if (ulInsertRSByte)
+               state->m_insertRSByte = true;
+
+       state->m_MpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT;
+       if (ulMpegLockTimeOut < 10000)
+               state->m_MpegLockTimeOut = ulMpegLockTimeOut;
+       state->m_DemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT;
+       if (ulDemodLockTimeOut < 10000)
+               state->m_DemodLockTimeOut = ulDemodLockTimeOut;
+
+       /* QAM defaults */
+       state->m_Constellation = DRX_CONSTELLATION_AUTO;
+       state->m_qamInterleaveMode = DRXK_QAM_I12_J17;
+       state->m_fecRsPlen = 204 * 8;   /* fecRsPlen  annex A */
+       state->m_fecRsPrescale = 1;
+
+       state->m_sqiSpeed = DRXK_DVBT_SQI_SPEED_MEDIUM;
+       state->m_agcFastClipCtrlDelay = 0;
+
+       state->m_GPIOCfg = (ulGPIOCfg);
+
+       state->m_bPowerDown = false;
+       state->m_currentPowerMode = DRX_POWER_DOWN;
+
+       state->m_enableParallel = (ulSerialMode == 0);
+
+       state->m_rfmirror = (ulRfMirror == 0);
+       state->m_IfAgcPol = false;
+       return 0;
+}
+
+static int DRXX_Open(struct drxk_state *state)
+{
+       int status = 0;
+       u32 jtag = 0;
+       u16 bid = 0;
+       u16 key = 0;
+
+       dprintk(1, "\n");
+       /* stop lock indicator process */
+       status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
+       if (status < 0)
+               goto error;
+       /* Check device id */
+       status = read16(state, SIO_TOP_COMM_KEY__A, &key);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
+       if (status < 0)
+               goto error;
+       status = read32(state, SIO_TOP_JTAGID_LO__A, &jtag);
+       if (status < 0)
+               goto error;
+       status = read16(state, SIO_PDR_UIO_IN_HI__A, &bid);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_TOP_COMM_KEY__A, key);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int GetDeviceCapabilities(struct drxk_state *state)
+{
+       u16 sioPdrOhwCfg = 0;
+       u32 sioTopJtagidLo = 0;
+       int status;
+       const char *spin = "";
+
+       dprintk(1, "\n");
+
+       /* driver 0.9.0 */
+       /* stop lock indicator process */
+       status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA);
+       if (status < 0)
+               goto error;
+       status = read16(state, SIO_PDR_OHW_CFG__A, &sioPdrOhwCfg);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
+       if (status < 0)
+               goto error;
+
+       switch ((sioPdrOhwCfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) {
+       case 0:
+               /* ignore (bypass ?) */
+               break;
+       case 1:
+               /* 27 MHz */
+               state->m_oscClockFreq = 27000;
+               break;
+       case 2:
+               /* 20.25 MHz */
+               state->m_oscClockFreq = 20250;
+               break;
+       case 3:
+               /* 4 MHz */
+               state->m_oscClockFreq = 20250;
+               break;
+       default:
+               printk(KERN_ERR "drxk: Clock Frequency is unkonwn\n");
+               return -EINVAL;
+       }
+       /*
+               Determine device capabilities
+               Based on pinning v14
+               */
+       status = read32(state, SIO_TOP_JTAGID_LO__A, &sioTopJtagidLo);
+       if (status < 0)
+               goto error;
+       /* driver 0.9.0 */
+       switch ((sioTopJtagidLo >> 29) & 0xF) {
+       case 0:
+               state->m_deviceSpin = DRXK_SPIN_A1;
+               spin = "A1";
+               break;
+       case 2:
+               state->m_deviceSpin = DRXK_SPIN_A2;
+               spin = "A2";
+               break;
+       case 3:
+               state->m_deviceSpin = DRXK_SPIN_A3;
+               spin = "A3";
+               break;
+       default:
+               state->m_deviceSpin = DRXK_SPIN_UNKNOWN;
+               status = -EINVAL;
+               printk(KERN_ERR "drxk: Spin unknown\n");
+               goto error2;
+       }
+       switch ((sioTopJtagidLo >> 12) & 0xFF) {
+       case 0x13:
+               /* typeId = DRX3913K_TYPE_ID */
+               state->m_hasLNA = false;
+               state->m_hasOOB = false;
+               state->m_hasATV = false;
+               state->m_hasAudio = false;
+               state->m_hasDVBT = true;
+               state->m_hasDVBC = true;
+               state->m_hasSAWSW = true;
+               state->m_hasGPIO2 = false;
+               state->m_hasGPIO1 = false;
+               state->m_hasIRQN = false;
+               break;
+       case 0x15:
+               /* typeId = DRX3915K_TYPE_ID */
+               state->m_hasLNA = false;
+               state->m_hasOOB = false;
+               state->m_hasATV = true;
+               state->m_hasAudio = false;
+               state->m_hasDVBT = true;
+               state->m_hasDVBC = false;
+               state->m_hasSAWSW = true;
+               state->m_hasGPIO2 = true;
+               state->m_hasGPIO1 = true;
+               state->m_hasIRQN = false;
+               break;
+       case 0x16:
+               /* typeId = DRX3916K_TYPE_ID */
+               state->m_hasLNA = false;
+               state->m_hasOOB = false;
+               state->m_hasATV = true;
+               state->m_hasAudio = false;
+               state->m_hasDVBT = true;
+               state->m_hasDVBC = false;
+               state->m_hasSAWSW = true;
+               state->m_hasGPIO2 = true;
+               state->m_hasGPIO1 = true;
+               state->m_hasIRQN = false;
+               break;
+       case 0x18:
+               /* typeId = DRX3918K_TYPE_ID */
+               state->m_hasLNA = false;
+               state->m_hasOOB = false;
+               state->m_hasATV = true;
+               state->m_hasAudio = true;
+               state->m_hasDVBT = true;
+               state->m_hasDVBC = false;
+               state->m_hasSAWSW = true;
+               state->m_hasGPIO2 = true;
+               state->m_hasGPIO1 = true;
+               state->m_hasIRQN = false;
+               break;
+       case 0x21:
+               /* typeId = DRX3921K_TYPE_ID */
+               state->m_hasLNA = false;
+               state->m_hasOOB = false;
+               state->m_hasATV = true;
+               state->m_hasAudio = true;
+               state->m_hasDVBT = true;
+               state->m_hasDVBC = true;
+               state->m_hasSAWSW = true;
+               state->m_hasGPIO2 = true;
+               state->m_hasGPIO1 = true;
+               state->m_hasIRQN = false;
+               break;
+       case 0x23:
+               /* typeId = DRX3923K_TYPE_ID */
+               state->m_hasLNA = false;
+               state->m_hasOOB = false;
+               state->m_hasATV = true;
+               state->m_hasAudio = true;
+               state->m_hasDVBT = true;
+               state->m_hasDVBC = true;
+               state->m_hasSAWSW = true;
+               state->m_hasGPIO2 = true;
+               state->m_hasGPIO1 = true;
+               state->m_hasIRQN = false;
+               break;
+       case 0x25:
+               /* typeId = DRX3925K_TYPE_ID */
+               state->m_hasLNA = false;
+               state->m_hasOOB = false;
+               state->m_hasATV = true;
+               state->m_hasAudio = true;
+               state->m_hasDVBT = true;
+               state->m_hasDVBC = true;
+               state->m_hasSAWSW = true;
+               state->m_hasGPIO2 = true;
+               state->m_hasGPIO1 = true;
+               state->m_hasIRQN = false;
+               break;
+       case 0x26:
+               /* typeId = DRX3926K_TYPE_ID */
+               state->m_hasLNA = false;
+               state->m_hasOOB = false;
+               state->m_hasATV = true;
+               state->m_hasAudio = false;
+               state->m_hasDVBT = true;
+               state->m_hasDVBC = true;
+               state->m_hasSAWSW = true;
+               state->m_hasGPIO2 = true;
+               state->m_hasGPIO1 = true;
+               state->m_hasIRQN = false;
+               break;
+       default:
+               printk(KERN_ERR "drxk: DeviceID 0x%02x not supported\n",
+                       ((sioTopJtagidLo >> 12) & 0xFF));
+               status = -EINVAL;
+               goto error2;
+       }
+
+       printk(KERN_INFO
+              "drxk: detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n",
+              ((sioTopJtagidLo >> 12) & 0xFF), spin,
+              state->m_oscClockFreq / 1000,
+              state->m_oscClockFreq % 1000);
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+error2:
+       return status;
+}
+
+static int HI_Command(struct drxk_state *state, u16 cmd, u16 *pResult)
+{
+       int status;
+       bool powerdown_cmd;
+
+       dprintk(1, "\n");
+
+       /* Write command */
+       status = write16(state, SIO_HI_RA_RAM_CMD__A, cmd);
+       if (status < 0)
+               goto error;
+       if (cmd == SIO_HI_RA_RAM_CMD_RESET)
+               msleep(1);
+
+       powerdown_cmd =
+           (bool) ((cmd == SIO_HI_RA_RAM_CMD_CONFIG) &&
+                   ((state->m_HICfgCtrl) &
+                    SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) ==
+                   SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ);
+       if (powerdown_cmd == false) {
+               /* Wait until command rdy */
+               u32 retryCount = 0;
+               u16 waitCmd;
+
+               do {
+                       msleep(1);
+                       retryCount += 1;
+                       status = read16(state, SIO_HI_RA_RAM_CMD__A,
+                                         &waitCmd);
+               } while ((status < 0) && (retryCount < DRXK_MAX_RETRIES)
+                        && (waitCmd != 0));
+               if (status < 0)
+                       goto error;
+               status = read16(state, SIO_HI_RA_RAM_RES__A, pResult);
+       }
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+static int HI_CfgCommand(struct drxk_state *state)
+{
+       int status;
+
+       dprintk(1, "\n");
+
+       mutex_lock(&state->mutex);
+
+       status = write16(state, SIO_HI_RA_RAM_PAR_6__A, state->m_HICfgTimeout);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_HI_RA_RAM_PAR_5__A, state->m_HICfgCtrl);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_HI_RA_RAM_PAR_4__A, state->m_HICfgWakeUpKey);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_HI_RA_RAM_PAR_3__A, state->m_HICfgBridgeDelay);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_HI_RA_RAM_PAR_2__A, state->m_HICfgTimingDiv);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY);
+       if (status < 0)
+               goto error;
+       status = HI_Command(state, SIO_HI_RA_RAM_CMD_CONFIG, 0);
+       if (status < 0)
+               goto error;
+
+       state->m_HICfgCtrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
+error:
+       mutex_unlock(&state->mutex);
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int InitHI(struct drxk_state *state)
+{
+       dprintk(1, "\n");
+
+       state->m_HICfgWakeUpKey = (state->demod_address << 1);
+       state->m_HICfgTimeout = 0x96FF;
+       /* port/bridge/power down ctrl */
+       state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE;
+
+       return HI_CfgCommand(state);
+}
+
+static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable)
+{
+       int status = -1;
+       u16 sioPdrMclkCfg = 0;
+       u16 sioPdrMdxCfg = 0;
+
+       dprintk(1, "\n");
+
+       /* stop lock indicator process */
+       status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
+       if (status < 0)
+               goto error;
+
+       /*  MPEG TS pad configuration */
+       status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA);
+       if (status < 0)
+               goto error;
+
+       if (mpegEnable == false) {
+               /*  Set MPEG TS pads to inputmode */
+               status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MERR_CFG__A, 0x0000);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MCLK_CFG__A, 0x0000);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MVAL_CFG__A, 0x0000);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MD0_CFG__A, 0x0000);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MD1_CFG__A, 0x0000);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MD2_CFG__A, 0x0000);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MD3_CFG__A, 0x0000);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MD4_CFG__A, 0x0000);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MD5_CFG__A, 0x0000);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MD6_CFG__A, 0x0000);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MD7_CFG__A, 0x0000);
+               if (status < 0)
+                       goto error;
+       } else {
+               /* Enable MPEG output */
+               sioPdrMdxCfg =
+                       ((state->m_TSDataStrength <<
+                       SIO_PDR_MD0_CFG_DRIVE__B) | 0x0003);
+               sioPdrMclkCfg = ((state->m_TSClockkStrength <<
+                                       SIO_PDR_MCLK_CFG_DRIVE__B) |
+                                       0x0003);
+
+               status = write16(state, SIO_PDR_MSTRT_CFG__A, sioPdrMdxCfg);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MERR_CFG__A, 0x0000);   /* Disable */
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MVAL_CFG__A, 0x0000);   /* Disable */
+               if (status < 0)
+                       goto error;
+               if (state->m_enableParallel == true) {
+                       /* paralel -> enable MD1 to MD7 */
+                       status = write16(state, SIO_PDR_MD1_CFG__A, sioPdrMdxCfg);
+                       if (status < 0)
+                               goto error;
+                       status = write16(state, SIO_PDR_MD2_CFG__A, sioPdrMdxCfg);
+                       if (status < 0)
+                               goto error;
+                       status = write16(state, SIO_PDR_MD3_CFG__A, sioPdrMdxCfg);
+                       if (status < 0)
+                               goto error;
+                       status = write16(state, SIO_PDR_MD4_CFG__A, sioPdrMdxCfg);
+                       if (status < 0)
+                               goto error;
+                       status = write16(state, SIO_PDR_MD5_CFG__A, sioPdrMdxCfg);
+                       if (status < 0)
+                               goto error;
+                       status = write16(state, SIO_PDR_MD6_CFG__A, sioPdrMdxCfg);
+                       if (status < 0)
+                               goto error;
+                       status = write16(state, SIO_PDR_MD7_CFG__A, sioPdrMdxCfg);
+                       if (status < 0)
+                               goto error;
+               } else {
+                       sioPdrMdxCfg = ((state->m_TSDataStrength <<
+                                               SIO_PDR_MD0_CFG_DRIVE__B)
+                                       | 0x0003);
+                       /* serial -> disable MD1 to MD7 */
+                       status = write16(state, SIO_PDR_MD1_CFG__A, 0x0000);
+                       if (status < 0)
+                               goto error;
+                       status = write16(state, SIO_PDR_MD2_CFG__A, 0x0000);
+                       if (status < 0)
+                               goto error;
+                       status = write16(state, SIO_PDR_MD3_CFG__A, 0x0000);
+                       if (status < 0)
+                               goto error;
+                       status = write16(state, SIO_PDR_MD4_CFG__A, 0x0000);
+                       if (status < 0)
+                               goto error;
+                       status = write16(state, SIO_PDR_MD5_CFG__A, 0x0000);
+                       if (status < 0)
+                               goto error;
+                       status = write16(state, SIO_PDR_MD6_CFG__A, 0x0000);
+                       if (status < 0)
+                               goto error;
+                       status = write16(state, SIO_PDR_MD7_CFG__A, 0x0000);
+                       if (status < 0)
+                               goto error;
+               }
+               status = write16(state, SIO_PDR_MCLK_CFG__A, sioPdrMclkCfg);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_PDR_MD0_CFG__A, sioPdrMdxCfg);
+               if (status < 0)
+                       goto error;
+       }
+       /*  Enable MB output over MPEG pads and ctl input */
+       status = write16(state, SIO_PDR_MON_CFG__A, 0x0000);
+       if (status < 0)
+               goto error;
+       /*  Write nomagic word to enable pdr reg write */
+       status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int MPEGTSDisable(struct drxk_state *state)
+{
+       dprintk(1, "\n");
+
+       return MPEGTSConfigurePins(state, false);
+}
+
+static int BLChainCmd(struct drxk_state *state,
+                     u16 romOffset, u16 nrOfElements, u32 timeOut)
+{
+       u16 blStatus = 0;
+       int status;
+       unsigned long end;
+
+       dprintk(1, "\n");
+       mutex_lock(&state->mutex);
+       status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_CHAIN);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_BL_CHAIN_ADDR__A, romOffset);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_BL_CHAIN_LEN__A, nrOfElements);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON);
+       if (status < 0)
+               goto error;
+
+       end = jiffies + msecs_to_jiffies(timeOut);
+       do {
+               msleep(1);
+               status = read16(state, SIO_BL_STATUS__A, &blStatus);
+               if (status < 0)
+                       goto error;
+       } while ((blStatus == 0x1) &&
+                       ((time_is_after_jiffies(end))));
+
+       if (blStatus == 0x1) {
+               printk(KERN_ERR "drxk: SIO not ready\n");
+               status = -EINVAL;
+               goto error2;
+       }
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+error2:
+       mutex_unlock(&state->mutex);
+       return status;
+}
+
+
+static int DownloadMicrocode(struct drxk_state *state,
+                            const u8 pMCImage[], u32 Length)
+{
+       const u8 *pSrc = pMCImage;
+       u16 Flags;
+       u16 Drain;
+       u32 Address;
+       u16 nBlocks;
+       u16 BlockSize;
+       u16 BlockCRC;
+       u32 offset = 0;
+       u32 i;
+       int status = 0;
+
+       dprintk(1, "\n");
+
+       /* down the drain (we don care about MAGIC_WORD) */
+       Drain = (pSrc[0] << 8) | pSrc[1];
+       pSrc += sizeof(u16);
+       offset += sizeof(u16);
+       nBlocks = (pSrc[0] << 8) | pSrc[1];
+       pSrc += sizeof(u16);
+       offset += sizeof(u16);
+
+       for (i = 0; i < nBlocks; i += 1) {
+               Address = (pSrc[0] << 24) | (pSrc[1] << 16) |
+                   (pSrc[2] << 8) | pSrc[3];
+               pSrc += sizeof(u32);
+               offset += sizeof(u32);
+
+               BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16);
+               pSrc += sizeof(u16);
+               offset += sizeof(u16);
+
+               Flags = (pSrc[0] << 8) | pSrc[1];
+               pSrc += sizeof(u16);
+               offset += sizeof(u16);
+
+               BlockCRC = (pSrc[0] << 8) | pSrc[1];
+               pSrc += sizeof(u16);
+               offset += sizeof(u16);
+
+               if (offset + BlockSize > Length) {
+                       printk(KERN_ERR "drxk: Firmware is corrupted.\n");
+                       return -EINVAL;
+               }
+
+               status = write_block(state, Address, BlockSize, pSrc);
+               if (status < 0) {
+                       printk(KERN_ERR "drxk: Error %d while loading firmware\n", status);
+                       break;
+               }
+               pSrc += BlockSize;
+               offset += BlockSize;
+       }
+       return status;
+}
+
+static int DVBTEnableOFDMTokenRing(struct drxk_state *state, bool enable)
+{
+       int status;
+       u16 data = 0;
+       u16 desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON;
+       u16 desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED;
+       unsigned long end;
+
+       dprintk(1, "\n");
+
+       if (enable == false) {
+               desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF;
+               desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN;
+       }
+
+       status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data);
+       if (status >= 0 && data == desiredStatus) {
+               /* tokenring already has correct status */
+               return status;
+       }
+       /* Disable/enable dvbt tokenring bridge   */
+       status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desiredCtrl);
+
+       end = jiffies + msecs_to_jiffies(DRXK_OFDM_TR_SHUTDOWN_TIMEOUT);
+       do {
+               status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data);
+               if ((status >= 0 && data == desiredStatus) || time_is_after_jiffies(end))
+                       break;
+               msleep(1);
+       } while (1);
+       if (data != desiredStatus) {
+               printk(KERN_ERR "drxk: SIO not ready\n");
+               return -EINVAL;
+       }
+       return status;
+}
+
+static int MPEGTSStop(struct drxk_state *state)
+{
+       int status = 0;
+       u16 fecOcSncMode = 0;
+       u16 fecOcIprMode = 0;
+
+       dprintk(1, "\n");
+
+       /* Gracefull shutdown (byte boundaries) */
+       status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode);
+       if (status < 0)
+               goto error;
+       fecOcSncMode |= FEC_OC_SNC_MODE_SHUTDOWN__M;
+       status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode);
+       if (status < 0)
+               goto error;
+
+       /* Suppress MCLK during absence of data */
+       status = read16(state, FEC_OC_IPR_MODE__A, &fecOcIprMode);
+       if (status < 0)
+               goto error;
+       fecOcIprMode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M;
+       status = write16(state, FEC_OC_IPR_MODE__A, fecOcIprMode);
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+static int scu_command(struct drxk_state *state,
+                      u16 cmd, u8 parameterLen,
+                      u16 *parameter, u8 resultLen, u16 *result)
+{
+#if (SCU_RAM_PARAM_0__A - SCU_RAM_PARAM_15__A) != 15
+#error DRXK register mapping no longer compatible with this routine!
+#endif
+       u16 curCmd = 0;
+       int status = -EINVAL;
+       unsigned long end;
+       u8 buffer[34];
+       int cnt = 0, ii;
+       const char *p;
+       char errname[30];
+
+       dprintk(1, "\n");
+
+       if ((cmd == 0) || ((parameterLen > 0) && (parameter == NULL)) ||
+           ((resultLen > 0) && (result == NULL)))
+               goto error;
+
+       mutex_lock(&state->mutex);
+
+       /* assume that the command register is ready
+               since it is checked afterwards */
+       for (ii = parameterLen - 1; ii >= 0; ii -= 1) {
+               buffer[cnt++] = (parameter[ii] & 0xFF);
+               buffer[cnt++] = ((parameter[ii] >> 8) & 0xFF);
+       }
+       buffer[cnt++] = (cmd & 0xFF);
+       buffer[cnt++] = ((cmd >> 8) & 0xFF);
+
+       write_block(state, SCU_RAM_PARAM_0__A -
+                       (parameterLen - 1), cnt, buffer);
+       /* Wait until SCU has processed command */
+       end = jiffies + msecs_to_jiffies(DRXK_MAX_WAITTIME);
+       do {
+               msleep(1);
+               status = read16(state, SCU_RAM_COMMAND__A, &curCmd);
+               if (status < 0)
+                       goto error;
+       } while (!(curCmd == DRX_SCU_READY) && (time_is_after_jiffies(end)));
+       if (curCmd != DRX_SCU_READY) {
+               printk(KERN_ERR "drxk: SCU not ready\n");
+               status = -EIO;
+               goto error2;
+       }
+       /* read results */
+       if ((resultLen > 0) && (result != NULL)) {
+               s16 err;
+               int ii;
+
+               for (ii = resultLen - 1; ii >= 0; ii -= 1) {
+                       status = read16(state, SCU_RAM_PARAM_0__A - ii, &result[ii]);
+                       if (status < 0)
+                               goto error;
+               }
+
+               /* Check if an error was reported by SCU */
+               err = (s16)result[0];
+               if (err >= 0)
+                       goto error;
+
+               /* check for the known error codes */
+               switch (err) {
+               case SCU_RESULT_UNKCMD:
+                       p = "SCU_RESULT_UNKCMD";
+                       break;
+               case SCU_RESULT_UNKSTD:
+                       p = "SCU_RESULT_UNKSTD";
+                       break;
+               case SCU_RESULT_SIZE:
+                       p = "SCU_RESULT_SIZE";
+                       break;
+               case SCU_RESULT_INVPAR:
+                       p = "SCU_RESULT_INVPAR";
+                       break;
+               default: /* Other negative values are errors */
+                       sprintf(errname, "ERROR: %d\n", err);
+                       p = errname;
+               }
+               printk(KERN_ERR "drxk: %s while sending cmd 0x%04x with params:", p, cmd);
+               print_hex_dump_bytes("drxk: ", DUMP_PREFIX_NONE, buffer, cnt);
+               status = -EINVAL;
+               goto error2;
+       }
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+error2:
+       mutex_unlock(&state->mutex);
+       return status;
+}
+
+static int SetIqmAf(struct drxk_state *state, bool active)
+{
+       u16 data = 0;
+       int status;
+
+       dprintk(1, "\n");
+
+       /* Configure IQM */
+       status = read16(state, IQM_AF_STDBY__A, &data);
+       if (status < 0)
+               goto error;
+
+       if (!active) {
+               data |= (IQM_AF_STDBY_STDBY_ADC_STANDBY
+                               | IQM_AF_STDBY_STDBY_AMP_STANDBY
+                               | IQM_AF_STDBY_STDBY_PD_STANDBY
+                               | IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY
+                               | IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY);
+       } else {
+               data &= ((~IQM_AF_STDBY_STDBY_ADC_STANDBY)
+                               & (~IQM_AF_STDBY_STDBY_AMP_STANDBY)
+                               & (~IQM_AF_STDBY_STDBY_PD_STANDBY)
+                               & (~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY)
+                               & (~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY)
+                       );
+       }
+       status = write16(state, IQM_AF_STDBY__A, data);
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode)
+{
+       int status = 0;
+       u16 sioCcPwdMode = 0;
+
+       dprintk(1, "\n");
+
+       /* Check arguments */
+       if (mode == NULL)
+               return -EINVAL;
+
+       switch (*mode) {
+       case DRX_POWER_UP:
+               sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_NONE;
+               break;
+       case DRXK_POWER_DOWN_OFDM:
+               sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OFDM;
+               break;
+       case DRXK_POWER_DOWN_CORE:
+               sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_CLOCK;
+               break;
+       case DRXK_POWER_DOWN_PLL:
+               sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_PLL;
+               break;
+       case DRX_POWER_DOWN:
+               sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OSC;
+               break;
+       default:
+               /* Unknow sleep mode */
+               return -EINVAL;
+       }
+
+       /* If already in requested power mode, do nothing */
+       if (state->m_currentPowerMode == *mode)
+               return 0;
+
+       /* For next steps make sure to start from DRX_POWER_UP mode */
+       if (state->m_currentPowerMode != DRX_POWER_UP) {
+               status = PowerUpDevice(state);
+               if (status < 0)
+                       goto error;
+               status = DVBTEnableOFDMTokenRing(state, true);
+               if (status < 0)
+                       goto error;
+       }
+
+       if (*mode == DRX_POWER_UP) {
+               /* Restore analog & pin configuartion */
+       } else {
+               /* Power down to requested mode */
+               /* Backup some register settings */
+               /* Set pins with possible pull-ups connected
+                  to them in input mode */
+               /* Analog power down */
+               /* ADC power down */
+               /* Power down device */
+               /* stop all comm_exec */
+               /* Stop and power down previous standard */
+               switch (state->m_OperationMode) {
+               case OM_DVBT:
+                       status = MPEGTSStop(state);
+                       if (status < 0)
+                               goto error;
+                       status = PowerDownDVBT(state, false);
+                       if (status < 0)
+                               goto error;
+                       break;
+               case OM_QAM_ITU_A:
+               case OM_QAM_ITU_C:
+                       status = MPEGTSStop(state);
+                       if (status < 0)
+                               goto error;
+                       status = PowerDownQAM(state);
+                       if (status < 0)
+                               goto error;
+                       break;
+               default:
+                       break;
+               }
+               status = DVBTEnableOFDMTokenRing(state, false);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_CC_PWD_MODE__A, sioCcPwdMode);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
+               if (status < 0)
+                       goto error;
+
+               if (*mode != DRXK_POWER_DOWN_OFDM) {
+                       state->m_HICfgCtrl |=
+                               SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
+                       status = HI_CfgCommand(state);
+                       if (status < 0)
+                               goto error;
+               }
+       }
+       state->m_currentPowerMode = *mode;
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode)
+{
+       enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
+       u16 cmdResult = 0;
+       u16 data = 0;
+       int status;
+
+       dprintk(1, "\n");
+
+       status = read16(state, SCU_COMM_EXEC__A, &data);
+       if (status < 0)
+               goto error;
+       if (data == SCU_COMM_EXEC_ACTIVE) {
+               /* Send OFDM stop command */
+               status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult);
+               if (status < 0)
+                       goto error;
+               /* Send OFDM reset command */
+               status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult);
+               if (status < 0)
+                       goto error;
+       }
+
+       /* Reset datapath for OFDM, processors first */
+       status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
+       if (status < 0)
+               goto error;
+       status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
+       if (status < 0)
+               goto error;
+
+       /* powerdown AFE                   */
+       status = SetIqmAf(state, false);
+       if (status < 0)
+               goto error;
+
+       /* powerdown to OFDM mode          */
+       if (setPowerMode) {
+               status = CtrlPowerMode(state, &powerMode);
+               if (status < 0)
+                       goto error;
+       }
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int SetOperationMode(struct drxk_state *state,
+                           enum OperationMode oMode)
+{
+       int status = 0;
+
+       dprintk(1, "\n");
+       /*
+          Stop and power down previous standard
+          TODO investigate total power down instead of partial
+          power down depending on "previous" standard.
+        */
+
+       /* disable HW lock indicator */
+       status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
+       if (status < 0)
+               goto error;
+
+       /* Device is already at the required mode */
+       if (state->m_OperationMode == oMode)
+               return 0;
+
+       switch (state->m_OperationMode) {
+               /* OM_NONE was added for start up */
+       case OM_NONE:
+               break;
+       case OM_DVBT:
+               status = MPEGTSStop(state);
+               if (status < 0)
+                       goto error;
+               status = PowerDownDVBT(state, true);
+               if (status < 0)
+                       goto error;
+               state->m_OperationMode = OM_NONE;
+               break;
+       case OM_QAM_ITU_A:      /* fallthrough */
+       case OM_QAM_ITU_C:
+               status = MPEGTSStop(state);
+               if (status < 0)
+                       goto error;
+               status = PowerDownQAM(state);
+               if (status < 0)
+                       goto error;
+               state->m_OperationMode = OM_NONE;
+               break;
+       case OM_QAM_ITU_B:
+       default:
+               status = -EINVAL;
+               goto error;
+       }
+
+       /*
+               Power up new standard
+               */
+       switch (oMode) {
+       case OM_DVBT:
+               state->m_OperationMode = oMode;
+               status = SetDVBTStandard(state, oMode);
+               if (status < 0)
+                       goto error;
+               break;
+       case OM_QAM_ITU_A:      /* fallthrough */
+       case OM_QAM_ITU_C:
+               state->m_OperationMode = oMode;
+               status = SetQAMStandard(state, oMode);
+               if (status < 0)
+                       goto error;
+               break;
+       case OM_QAM_ITU_B:
+       default:
+               status = -EINVAL;
+       }
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int Start(struct drxk_state *state, s32 offsetFreq,
+                s32 IntermediateFrequency)
+{
+       int status = -EINVAL;
+
+       u16 IFreqkHz;
+       s32 OffsetkHz = offsetFreq / 1000;
+
+       dprintk(1, "\n");
+       if (state->m_DrxkState != DRXK_STOPPED &&
+               state->m_DrxkState != DRXK_DTV_STARTED)
+               goto error;
+
+       state->m_bMirrorFreqSpect = (state->param.inversion == INVERSION_ON);
+
+       if (IntermediateFrequency < 0) {
+               state->m_bMirrorFreqSpect = !state->m_bMirrorFreqSpect;
+               IntermediateFrequency = -IntermediateFrequency;
+       }
+
+       switch (state->m_OperationMode) {
+       case OM_QAM_ITU_A:
+       case OM_QAM_ITU_C:
+               IFreqkHz = (IntermediateFrequency / 1000);
+               status = SetQAM(state, IFreqkHz, OffsetkHz);
+               if (status < 0)
+                       goto error;
+               state->m_DrxkState = DRXK_DTV_STARTED;
+               break;
+       case OM_DVBT:
+               IFreqkHz = (IntermediateFrequency / 1000);
+               status = MPEGTSStop(state);
+               if (status < 0)
+                       goto error;
+               status = SetDVBT(state, IFreqkHz, OffsetkHz);
+               if (status < 0)
+                       goto error;
+               status = DVBTStart(state);
+               if (status < 0)
+                       goto error;
+               state->m_DrxkState = DRXK_DTV_STARTED;
+               break;
+       default:
+               break;
+       }
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int ShutDown(struct drxk_state *state)
+{
+       dprintk(1, "\n");
+
+       MPEGTSStop(state);
+       return 0;
+}
+
+static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus,
+                        u32 Time)
+{
+       int status = -EINVAL;
+
+       dprintk(1, "\n");
+
+       if (pLockStatus == NULL)
+               goto error;
+
+       *pLockStatus = NOT_LOCKED;
+
+       /* define the SCU command code */
+       switch (state->m_OperationMode) {
+       case OM_QAM_ITU_A:
+       case OM_QAM_ITU_B:
+       case OM_QAM_ITU_C:
+               status = GetQAMLockStatus(state, pLockStatus);
+               break;
+       case OM_DVBT:
+               status = GetDVBTLockStatus(state, pLockStatus);
+               break;
+       default:
+               break;
+       }
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int MPEGTSStart(struct drxk_state *state)
+{
+       int status;
+
+       u16 fecOcSncMode = 0;
+
+       /* Allow OC to sync again */
+       status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode);
+       if (status < 0)
+               goto error;
+       fecOcSncMode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M;
+       status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_SNC_UNLOCK__A, 1);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int MPEGTSDtoInit(struct drxk_state *state)
+{
+       int status;
+
+       dprintk(1, "\n");
+
+       /* Rate integration settings */
+       status = write16(state, FEC_OC_RCN_CTL_STEP_LO__A, 0x0000);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_RCN_CTL_STEP_HI__A, 0x000C);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_RCN_GAIN__A, 0x000A);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_AVR_PARM_A__A, 0x0008);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_AVR_PARM_B__A, 0x0006);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_TMD_HI_MARGIN__A, 0x0680);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_TMD_LO_MARGIN__A, 0x0080);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_TMD_COUNT__A, 0x03F4);
+       if (status < 0)
+               goto error;
+
+       /* Additional configuration */
+       status = write16(state, FEC_OC_OCR_INVERT__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_SNC_LWM__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_SNC_HWM__A, 12);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+static int MPEGTSDtoSetup(struct drxk_state *state,
+                         enum OperationMode oMode)
+{
+       int status;
+
+       u16 fecOcRegMode = 0;   /* FEC_OC_MODE       register value */
+       u16 fecOcRegIprMode = 0;        /* FEC_OC_IPR_MODE   register value */
+       u16 fecOcDtoMode = 0;   /* FEC_OC_IPR_INVERT register value */
+       u16 fecOcFctMode = 0;   /* FEC_OC_IPR_INVERT register value */
+       u16 fecOcDtoPeriod = 2; /* FEC_OC_IPR_INVERT register value */
+       u16 fecOcDtoBurstLen = 188;     /* FEC_OC_IPR_INVERT register value */
+       u32 fecOcRcnCtlRate = 0;        /* FEC_OC_IPR_INVERT register value */
+       u16 fecOcTmdMode = 0;
+       u16 fecOcTmdIntUpdRate = 0;
+       u32 maxBitRate = 0;
+       bool staticCLK = false;
+
+       dprintk(1, "\n");
+
+       /* Check insertion of the Reed-Solomon parity bytes */
+       status = read16(state, FEC_OC_MODE__A, &fecOcRegMode);
+       if (status < 0)
+               goto error;
+       status = read16(state, FEC_OC_IPR_MODE__A, &fecOcRegIprMode);
+       if (status < 0)
+               goto error;
+       fecOcRegMode &= (~FEC_OC_MODE_PARITY__M);
+       fecOcRegIprMode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M);
+       if (state->m_insertRSByte == true) {
+               /* enable parity symbol forward */
+               fecOcRegMode |= FEC_OC_MODE_PARITY__M;
+               /* MVAL disable during parity bytes */
+               fecOcRegIprMode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M;
+               /* TS burst length to 204 */
+               fecOcDtoBurstLen = 204;
+       }
+
+       /* Check serial or parrallel output */
+       fecOcRegIprMode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
+       if (state->m_enableParallel == false) {
+               /* MPEG data output is serial -> set ipr_mode[0] */
+               fecOcRegIprMode |= FEC_OC_IPR_MODE_SERIAL__M;
+       }
+
+       switch (oMode) {
+       case OM_DVBT:
+               maxBitRate = state->m_DVBTBitrate;
+               fecOcTmdMode = 3;
+               fecOcRcnCtlRate = 0xC00000;
+               staticCLK = state->m_DVBTStaticCLK;
+               break;
+       case OM_QAM_ITU_A:      /* fallthrough */
+       case OM_QAM_ITU_C:
+               fecOcTmdMode = 0x0004;
+               fecOcRcnCtlRate = 0xD2B4EE;     /* good for >63 Mb/s */
+               maxBitRate = state->m_DVBCBitrate;
+               staticCLK = state->m_DVBCStaticCLK;
+               break;
+       default:
+               status = -EINVAL;
+       }               /* switch (standard) */
+       if (status < 0)
+               goto error;
+
+       /* Configure DTO's */
+       if (staticCLK) {
+               u32 bitRate = 0;
+
+               /* Rational DTO for MCLK source (static MCLK rate),
+                       Dynamic DTO for optimal grouping
+                       (avoid intra-packet gaps),
+                       DTO offset enable to sync TS burst with MSTRT */
+               fecOcDtoMode = (FEC_OC_DTO_MODE_DYNAMIC__M |
+                               FEC_OC_DTO_MODE_OFFSET_ENABLE__M);
+               fecOcFctMode = (FEC_OC_FCT_MODE_RAT_ENA__M |
+                               FEC_OC_FCT_MODE_VIRT_ENA__M);
+
+               /* Check user defined bitrate */
+               bitRate = maxBitRate;
+               if (bitRate > 75900000UL) {     /* max is 75.9 Mb/s */
+                       bitRate = 75900000UL;
+               }
+               /* Rational DTO period:
+                       dto_period = (Fsys / bitrate) - 2
+
+                       Result should be floored,
+                       to make sure >= requested bitrate
+                       */
+               fecOcDtoPeriod = (u16) (((state->m_sysClockFreq)
+                                               * 1000) / bitRate);
+               if (fecOcDtoPeriod <= 2)
+                       fecOcDtoPeriod = 0;
+               else
+                       fecOcDtoPeriod -= 2;
+               fecOcTmdIntUpdRate = 8;
+       } else {
+               /* (commonAttr->staticCLK == false) => dynamic mode */
+               fecOcDtoMode = FEC_OC_DTO_MODE_DYNAMIC__M;
+               fecOcFctMode = FEC_OC_FCT_MODE__PRE;
+               fecOcTmdIntUpdRate = 5;
+       }
+
+       /* Write appropriate registers with requested configuration */
+       status = write16(state, FEC_OC_DTO_BURST_LEN__A, fecOcDtoBurstLen);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_DTO_PERIOD__A, fecOcDtoPeriod);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_DTO_MODE__A, fecOcDtoMode);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_FCT_MODE__A, fecOcFctMode);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_MODE__A, fecOcRegMode);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_IPR_MODE__A, fecOcRegIprMode);
+       if (status < 0)
+               goto error;
+
+       /* Rate integration settings */
+       status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fecOcRcnCtlRate);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, fecOcTmdIntUpdRate);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_TMD_MODE__A, fecOcTmdMode);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int MPEGTSConfigurePolarity(struct drxk_state *state)
+{
+       u16 fecOcRegIprInvert = 0;
+
+       /* Data mask for the output data byte */
+       u16 InvertDataMask =
+           FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M |
+           FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M |
+           FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M |
+           FEC_OC_IPR_INVERT_MD1__M | FEC_OC_IPR_INVERT_MD0__M;
+
+       dprintk(1, "\n");
+
+       /* Control selective inversion of output bits */
+       fecOcRegIprInvert &= (~(InvertDataMask));
+       if (state->m_invertDATA == true)
+               fecOcRegIprInvert |= InvertDataMask;
+       fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MERR__M));
+       if (state->m_invertERR == true)
+               fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MERR__M;
+       fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MSTRT__M));
+       if (state->m_invertSTR == true)
+               fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MSTRT__M;
+       fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MVAL__M));
+       if (state->m_invertVAL == true)
+               fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MVAL__M;
+       fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MCLK__M));
+       if (state->m_invertCLK == true)
+               fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MCLK__M;
+
+       return write16(state, FEC_OC_IPR_INVERT__A, fecOcRegIprInvert);
+}
+
+#define   SCU_RAM_AGC_KI_INV_RF_POL__M 0x4000
+
+static int SetAgcRf(struct drxk_state *state,
+                   struct SCfgAgc *pAgcCfg, bool isDTV)
+{
+       int status = -EINVAL;
+       u16 data = 0;
+       struct SCfgAgc *pIfAgcSettings;
+
+       dprintk(1, "\n");
+
+       if (pAgcCfg == NULL)
+               goto error;
+
+       switch (pAgcCfg->ctrlMode) {
+       case DRXK_AGC_CTRL_AUTO:
+               /* Enable RF AGC DAC */
+               status = read16(state, IQM_AF_STDBY__A, &data);
+               if (status < 0)
+                       goto error;
+               data &= ~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
+               status = write16(state, IQM_AF_STDBY__A, data);
+               if (status < 0)
+                       goto error;
+               status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
+               if (status < 0)
+                       goto error;
+
+               /* Enable SCU RF AGC loop */
+               data &= ~SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
+
+               /* Polarity */
+               if (state->m_RfAgcPol)
+                       data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
+               else
+                       data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
+               status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
+               if (status < 0)
+                       goto error;
+
+               /* Set speed (using complementary reduction value) */
+               status = read16(state, SCU_RAM_AGC_KI_RED__A, &data);
+               if (status < 0)
+                       goto error;
+
+               data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M;
+               data |= (~(pAgcCfg->speed <<
+                               SCU_RAM_AGC_KI_RED_RAGC_RED__B)
+                               & SCU_RAM_AGC_KI_RED_RAGC_RED__M);
+
+               status = write16(state, SCU_RAM_AGC_KI_RED__A, data);
+               if (status < 0)
+                       goto error;
+
+               if (IsDVBT(state))
+                       pIfAgcSettings = &state->m_dvbtIfAgcCfg;
+               else if (IsQAM(state))
+                       pIfAgcSettings = &state->m_qamIfAgcCfg;
+               else
+                       pIfAgcSettings = &state->m_atvIfAgcCfg;
+               if (pIfAgcSettings == NULL) {
+                       status = -EINVAL;
+                       goto error;
+               }
+
+               /* Set TOP, only if IF-AGC is in AUTO mode */
+               if (pIfAgcSettings->ctrlMode == DRXK_AGC_CTRL_AUTO)
+                       status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->top);
+                       if (status < 0)
+                               goto error;
+
+               /* Cut-Off current */
+               status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, pAgcCfg->cutOffCurrent);
+               if (status < 0)
+                       goto error;
+
+               /* Max. output level */
+               status = write16(state, SCU_RAM_AGC_RF_MAX__A, pAgcCfg->maxOutputLevel);
+               if (status < 0)
+                       goto error;
+
+               break;
+
+       case DRXK_AGC_CTRL_USER:
+               /* Enable RF AGC DAC */
+               status = read16(state, IQM_AF_STDBY__A, &data);
+               if (status < 0)
+                       goto error;
+               data &= ~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
+               status = write16(state, IQM_AF_STDBY__A, data);
+               if (status < 0)
+                       goto error;
+
+               /* Disable SCU RF AGC loop */
+               status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
+               if (status < 0)
+                       goto error;
+               data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
+               if (state->m_RfAgcPol)
+                       data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
+               else
+                       data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
+               status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
+               if (status < 0)
+                       goto error;
+
+               /* SCU c.o.c. to 0, enabling full control range */
+               status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, 0);
+               if (status < 0)
+                       goto error;
+
+               /* Write value to output pin */
+               status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, pAgcCfg->outputLevel);
+               if (status < 0)
+                       goto error;
+               break;
+
+       case DRXK_AGC_CTRL_OFF:
+               /* Disable RF AGC DAC */
+               status = read16(state, IQM_AF_STDBY__A, &data);
+               if (status < 0)
+                       goto error;
+               data |= IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
+               status = write16(state, IQM_AF_STDBY__A, data);
+               if (status < 0)
+                       goto error;
+
+               /* Disable SCU RF AGC loop */
+               status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
+               if (status < 0)
+                       goto error;
+               data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
+               status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
+               if (status < 0)
+                       goto error;
+               break;
+
+       default:
+               status = -EINVAL;
+
+       }
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+#define SCU_RAM_AGC_KI_INV_IF_POL__M 0x2000
+
+static int SetAgcIf(struct drxk_state *state,
+                   struct SCfgAgc *pAgcCfg, bool isDTV)
+{
+       u16 data = 0;
+       int status = 0;
+       struct SCfgAgc *pRfAgcSettings;
+
+       dprintk(1, "\n");
+
+       switch (pAgcCfg->ctrlMode) {
+       case DRXK_AGC_CTRL_AUTO:
+
+               /* Enable IF AGC DAC */
+               status = read16(state, IQM_AF_STDBY__A, &data);
+               if (status < 0)
+                       goto error;
+               data &= ~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
+               status = write16(state, IQM_AF_STDBY__A, data);
+               if (status < 0)
+                       goto error;
+
+               status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
+               if (status < 0)
+                       goto error;
+
+               /* Enable SCU IF AGC loop */
+               data &= ~SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
+
+               /* Polarity */
+               if (state->m_IfAgcPol)
+                       data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
+               else
+                       data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
+               status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
+               if (status < 0)
+                       goto error;
+
+               /* Set speed (using complementary reduction value) */
+               status = read16(state, SCU_RAM_AGC_KI_RED__A, &data);
+               if (status < 0)
+                       goto error;
+               data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M;
+               data |= (~(pAgcCfg->speed <<
+                               SCU_RAM_AGC_KI_RED_IAGC_RED__B)
+                               & SCU_RAM_AGC_KI_RED_IAGC_RED__M);
+
+               status = write16(state, SCU_RAM_AGC_KI_RED__A, data);
+               if (status < 0)
+                       goto error;
+
+               if (IsQAM(state))
+                       pRfAgcSettings = &state->m_qamRfAgcCfg;
+               else
+                       pRfAgcSettings = &state->m_atvRfAgcCfg;
+               if (pRfAgcSettings == NULL)
+                       return -1;
+               /* Restore TOP */
+               status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pRfAgcSettings->top);
+               if (status < 0)
+                       goto error;
+               break;
+
+       case DRXK_AGC_CTRL_USER:
+
+               /* Enable IF AGC DAC */
+               status = read16(state, IQM_AF_STDBY__A, &data);
+               if (status < 0)
+                       goto error;
+               data &= ~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
+               status = write16(state, IQM_AF_STDBY__A, data);
+               if (status < 0)
+                       goto error;
+
+               status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
+               if (status < 0)
+                       goto error;
+
+               /* Disable SCU IF AGC loop */
+               data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
+
+               /* Polarity */
+               if (state->m_IfAgcPol)
+                       data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
+               else
+                       data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
+               status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
+               if (status < 0)
+                       goto error;
+
+               /* Write value to output pin */
+               status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->outputLevel);
+               if (status < 0)
+                       goto error;
+               break;
+
+       case DRXK_AGC_CTRL_OFF:
+
+               /* Disable If AGC DAC */
+               status = read16(state, IQM_AF_STDBY__A, &data);
+               if (status < 0)
+                       goto error;
+               data |= IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
+               status = write16(state, IQM_AF_STDBY__A, data);
+               if (status < 0)
+                       goto error;
+
+               /* Disable SCU IF AGC loop */
+               status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
+               if (status < 0)
+                       goto error;
+               data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
+               status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
+               if (status < 0)
+                       goto error;
+               break;
+       }               /* switch (agcSettingsIf->ctrlMode) */
+
+       /* always set the top to support
+               configurations without if-loop */
+       status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, pAgcCfg->top);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int ReadIFAgc(struct drxk_state *state, u32 *pValue)
+{
+       u16 agcDacLvl;
+       int status;
+       u16 Level = 0;
+
+       dprintk(1, "\n");
+
+       status = read16(state, IQM_AF_AGC_IF__A, &agcDacLvl);
+       if (status < 0) {
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+               return status;
+       }
+
+       *pValue = 0;
+
+       if (agcDacLvl > DRXK_AGC_DAC_OFFSET)
+               Level = agcDacLvl - DRXK_AGC_DAC_OFFSET;
+       if (Level < 14000)
+               *pValue = (14000 - Level) / 4;
+       else
+               *pValue = 0;
+
+       return status;
+}
+
+static int GetQAMSignalToNoise(struct drxk_state *state,
+                              s32 *pSignalToNoise)
+{
+       int status = 0;
+       u16 qamSlErrPower = 0;  /* accum. error between
+                                       raw and sliced symbols */
+       u32 qamSlSigPower = 0;  /* used for MER, depends of
+                                       QAM constellation */
+       u32 qamSlMer = 0;       /* QAM MER */
+
+       dprintk(1, "\n");
+
+       /* MER calculation */
+
+       /* get the register value needed for MER */
+       status = read16(state, QAM_SL_ERR_POWER__A, &qamSlErrPower);
+       if (status < 0) {
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+               return -EINVAL;
+       }
+
+       switch (state->param.u.qam.modulation) {
+       case QAM_16:
+               qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM16 << 2;
+               break;
+       case QAM_32:
+               qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM32 << 2;
+               break;
+       case QAM_64:
+               qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM64 << 2;
+               break;
+       case QAM_128:
+               qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM128 << 2;
+               break;
+       default:
+       case QAM_256:
+               qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM256 << 2;
+               break;
+       }
+
+       if (qamSlErrPower > 0) {
+               qamSlMer = Log10Times100(qamSlSigPower) -
+                       Log10Times100((u32) qamSlErrPower);
+       }
+       *pSignalToNoise = qamSlMer;
+
+       return status;
+}
+
+static int GetDVBTSignalToNoise(struct drxk_state *state,
+                               s32 *pSignalToNoise)
+{
+       int status;
+       u16 regData = 0;
+       u32 EqRegTdSqrErrI = 0;
+       u32 EqRegTdSqrErrQ = 0;
+       u16 EqRegTdSqrErrExp = 0;
+       u16 EqRegTdTpsPwrOfs = 0;
+       u16 EqRegTdReqSmbCnt = 0;
+       u32 tpsCnt = 0;
+       u32 SqrErrIQ = 0;
+       u32 a = 0;
+       u32 b = 0;
+       u32 c = 0;
+       u32 iMER = 0;
+       u16 transmissionParams = 0;
+
+       dprintk(1, "\n");
+
+       status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, &EqRegTdTpsPwrOfs);
+       if (status < 0)
+               goto error;
+       status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, &EqRegTdReqSmbCnt);
+       if (status < 0)
+               goto error;
+       status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, &EqRegTdSqrErrExp);
+       if (status < 0)
+               goto error;
+       status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, &regData);
+       if (status < 0)
+               goto error;
+       /* Extend SQR_ERR_I operational range */
+       EqRegTdSqrErrI = (u32) regData;
+       if ((EqRegTdSqrErrExp > 11) &&
+               (EqRegTdSqrErrI < 0x00000FFFUL)) {
+               EqRegTdSqrErrI += 0x00010000UL;
+       }
+       status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, &regData);
+       if (status < 0)
+               goto error;
+       /* Extend SQR_ERR_Q operational range */
+       EqRegTdSqrErrQ = (u32) regData;
+       if ((EqRegTdSqrErrExp > 11) &&
+               (EqRegTdSqrErrQ < 0x00000FFFUL))
+               EqRegTdSqrErrQ += 0x00010000UL;
+
+       status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, &transmissionParams);
+       if (status < 0)
+               goto error;
+
+       /* Check input data for MER */
+
+       /* MER calculation (in 0.1 dB) without math.h */
+       if ((EqRegTdTpsPwrOfs == 0) || (EqRegTdReqSmbCnt == 0))
+               iMER = 0;
+       else if ((EqRegTdSqrErrI + EqRegTdSqrErrQ) == 0) {
+               /* No error at all, this must be the HW reset value
+                       * Apparently no first measurement yet
+                       * Set MER to 0.0 */
+               iMER = 0;
+       } else {
+               SqrErrIQ = (EqRegTdSqrErrI + EqRegTdSqrErrQ) <<
+                       EqRegTdSqrErrExp;
+               if ((transmissionParams &
+                       OFDM_SC_RA_RAM_OP_PARAM_MODE__M)
+                       == OFDM_SC_RA_RAM_OP_PARAM_MODE_2K)
+                       tpsCnt = 17;
+               else
+                       tpsCnt = 68;
+
+               /* IMER = 100 * log10 (x)
+                       where x = (EqRegTdTpsPwrOfs^2 *
+                       EqRegTdReqSmbCnt * tpsCnt)/SqrErrIQ
+
+                       => IMER = a + b -c
+                       where a = 100 * log10 (EqRegTdTpsPwrOfs^2)
+                       b = 100 * log10 (EqRegTdReqSmbCnt * tpsCnt)
+                       c = 100 * log10 (SqrErrIQ)
+                       */
+
+               /* log(x) x = 9bits * 9bits->18 bits  */
+               a = Log10Times100(EqRegTdTpsPwrOfs *
+                                       EqRegTdTpsPwrOfs);
+               /* log(x) x = 16bits * 7bits->23 bits  */
+               b = Log10Times100(EqRegTdReqSmbCnt * tpsCnt);
+               /* log(x) x = (16bits + 16bits) << 15 ->32 bits  */
+               c = Log10Times100(SqrErrIQ);
+
+               iMER = a + b;
+               /* No negative MER, clip to zero */
+               if (iMER > c)
+                       iMER -= c;
+               else
+                       iMER = 0;
+       }
+       *pSignalToNoise = iMER;
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int GetSignalToNoise(struct drxk_state *state, s32 *pSignalToNoise)
+{
+       dprintk(1, "\n");
+
+       *pSignalToNoise = 0;
+       switch (state->m_OperationMode) {
+       case OM_DVBT:
+               return GetDVBTSignalToNoise(state, pSignalToNoise);
+       case OM_QAM_ITU_A:
+       case OM_QAM_ITU_C:
+               return GetQAMSignalToNoise(state, pSignalToNoise);
+       default:
+               break;
+       }
+       return 0;
+}
+
+#if 0
+static int GetDVBTQuality(struct drxk_state *state, s32 *pQuality)
+{
+       /* SNR Values for quasi errorfree reception rom Nordig 2.2 */
+       int status = 0;
+
+       dprintk(1, "\n");
+
+       static s32 QE_SN[] = {
+               51,             /* QPSK 1/2 */
+               69,             /* QPSK 2/3 */
+               79,             /* QPSK 3/4 */
+               89,             /* QPSK 5/6 */
+               97,             /* QPSK 7/8 */
+               108,            /* 16-QAM 1/2 */
+               131,            /* 16-QAM 2/3 */
+               146,            /* 16-QAM 3/4 */
+               156,            /* 16-QAM 5/6 */
+               160,            /* 16-QAM 7/8 */
+               165,            /* 64-QAM 1/2 */
+               187,            /* 64-QAM 2/3 */
+               202,            /* 64-QAM 3/4 */
+               216,            /* 64-QAM 5/6 */
+               225,            /* 64-QAM 7/8 */
+       };
+
+       *pQuality = 0;
+
+       do {
+               s32 SignalToNoise = 0;
+               u16 Constellation = 0;
+               u16 CodeRate = 0;
+               u32 SignalToNoiseRel;
+               u32 BERQuality;
+
+               status = GetDVBTSignalToNoise(state, &SignalToNoise);
+               if (status < 0)
+                       break;
+               status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, &Constellation);
+               if (status < 0)
+                       break;
+               Constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M;
+
+               status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, &CodeRate);
+               if (status < 0)
+                       break;
+               CodeRate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M;
+
+               if (Constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM ||
+                   CodeRate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8)
+                       break;
+               SignalToNoiseRel = SignalToNoise -
+                   QE_SN[Constellation * 5 + CodeRate];
+               BERQuality = 100;
+
+               if (SignalToNoiseRel < -70)
+                       *pQuality = 0;
+               else if (SignalToNoiseRel < 30)
+                       *pQuality = ((SignalToNoiseRel + 70) *
+                                    BERQuality) / 100;
+               else
+                       *pQuality = BERQuality;
+       } while (0);
+       return 0;
+};
+
+static int GetDVBCQuality(struct drxk_state *state, s32 *pQuality)
+{
+       int status = 0;
+       *pQuality = 0;
+
+       dprintk(1, "\n");
+
+       do {
+               u32 SignalToNoise = 0;
+               u32 BERQuality = 100;
+               u32 SignalToNoiseRel = 0;
+
+               status = GetQAMSignalToNoise(state, &SignalToNoise);
+               if (status < 0)
+                       break;
+
+               switch (state->param.u.qam.modulation) {
+               case QAM_16:
+                       SignalToNoiseRel = SignalToNoise - 200;
+                       break;
+               case QAM_32:
+                       SignalToNoiseRel = SignalToNoise - 230;
+                       break;  /* Not in NorDig */
+               case QAM_64:
+                       SignalToNoiseRel = SignalToNoise - 260;
+                       break;
+               case QAM_128:
+                       SignalToNoiseRel = SignalToNoise - 290;
+                       break;
+               default:
+               case QAM_256:
+                       SignalToNoiseRel = SignalToNoise - 320;
+                       break;
+               }
+
+               if (SignalToNoiseRel < -70)
+                       *pQuality = 0;
+               else if (SignalToNoiseRel < 30)
+                       *pQuality = ((SignalToNoiseRel + 70) *
+                                    BERQuality) / 100;
+               else
+                       *pQuality = BERQuality;
+       } while (0);
+
+       return status;
+}
+
+static int GetQuality(struct drxk_state *state, s32 *pQuality)
+{
+       dprintk(1, "\n");
+
+       switch (state->m_OperationMode) {
+       case OM_DVBT:
+               return GetDVBTQuality(state, pQuality);
+       case OM_QAM_ITU_A:
+               return GetDVBCQuality(state, pQuality);
+       default:
+               break;
+       }
+
+       return 0;
+}
+#endif
+
+/* Free data ram in SIO HI */
+#define SIO_HI_RA_RAM_USR_BEGIN__A 0x420040
+#define SIO_HI_RA_RAM_USR_END__A   0x420060
+
+#define DRXK_HI_ATOMIC_BUF_START (SIO_HI_RA_RAM_USR_BEGIN__A)
+#define DRXK_HI_ATOMIC_BUF_END   (SIO_HI_RA_RAM_USR_BEGIN__A + 7)
+#define DRXK_HI_ATOMIC_READ      SIO_HI_RA_RAM_PAR_3_ACP_RW_READ
+#define DRXK_HI_ATOMIC_WRITE     SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE
+
+#define DRXDAP_FASI_ADDR2BLOCK(addr)  (((addr) >> 22) & 0x3F)
+#define DRXDAP_FASI_ADDR2BANK(addr)   (((addr) >> 16) & 0x3F)
+#define DRXDAP_FASI_ADDR2OFFSET(addr) ((addr) & 0x7FFF)
+
+static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge)
+{
+       int status = -EINVAL;
+
+       dprintk(1, "\n");
+
+       if (state->m_DrxkState == DRXK_UNINITIALIZED)
+               goto error;
+       if (state->m_DrxkState == DRXK_POWERED_DOWN)
+               goto error;
+
+       if (state->no_i2c_bridge)
+               return 0;
+
+       status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY);
+       if (status < 0)
+               goto error;
+       if (bEnableBridge) {
+               status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED);
+               if (status < 0)
+                       goto error;
+       } else {
+               status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN);
+               if (status < 0)
+                       goto error;
+       }
+
+       status = HI_Command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, 0);
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int SetPreSaw(struct drxk_state *state,
+                    struct SCfgPreSaw *pPreSawCfg)
+{
+       int status = -EINVAL;
+
+       dprintk(1, "\n");
+
+       if ((pPreSawCfg == NULL)
+           || (pPreSawCfg->reference > IQM_AF_PDREF__M))
+               goto error;
+
+       status = write16(state, IQM_AF_PDREF__A, pPreSawCfg->reference);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int BLDirectCmd(struct drxk_state *state, u32 targetAddr,
+                      u16 romOffset, u16 nrOfElements, u32 timeOut)
+{
+       u16 blStatus = 0;
+       u16 offset = (u16) ((targetAddr >> 0) & 0x00FFFF);
+       u16 blockbank = (u16) ((targetAddr >> 16) & 0x000FFF);
+       int status;
+       unsigned long end;
+
+       dprintk(1, "\n");
+
+       mutex_lock(&state->mutex);
+       status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_DIRECT);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_BL_TGT_HDR__A, blockbank);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_BL_TGT_ADDR__A, offset);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_BL_SRC_ADDR__A, romOffset);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_BL_SRC_LEN__A, nrOfElements);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON);
+       if (status < 0)
+               goto error;
+
+       end = jiffies + msecs_to_jiffies(timeOut);
+       do {
+               status = read16(state, SIO_BL_STATUS__A, &blStatus);
+               if (status < 0)
+                       goto error;
+       } while ((blStatus == 0x1) && time_is_after_jiffies(end));
+       if (blStatus == 0x1) {
+               printk(KERN_ERR "drxk: SIO not ready\n");
+               status = -EINVAL;
+               goto error2;
+       }
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+error2:
+       mutex_unlock(&state->mutex);
+       return status;
+
+}
+
+static int ADCSyncMeasurement(struct drxk_state *state, u16 *count)
+{
+       u16 data = 0;
+       int status;
+
+       dprintk(1, "\n");
+
+       /* Start measurement */
+       status = write16(state, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_AF_START_LOCK__A, 1);
+       if (status < 0)
+               goto error;
+
+       *count = 0;
+       status = read16(state, IQM_AF_PHASE0__A, &data);
+       if (status < 0)
+               goto error;
+       if (data == 127)
+               *count = *count + 1;
+       status = read16(state, IQM_AF_PHASE1__A, &data);
+       if (status < 0)
+               goto error;
+       if (data == 127)
+               *count = *count + 1;
+       status = read16(state, IQM_AF_PHASE2__A, &data);
+       if (status < 0)
+               goto error;
+       if (data == 127)
+               *count = *count + 1;
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int ADCSynchronization(struct drxk_state *state)
+{
+       u16 count = 0;
+       int status;
+
+       dprintk(1, "\n");
+
+       status = ADCSyncMeasurement(state, &count);
+       if (status < 0)
+               goto error;
+
+       if (count == 1) {
+               /* Try sampling on a diffrent edge */
+               u16 clkNeg = 0;
+
+               status = read16(state, IQM_AF_CLKNEG__A, &clkNeg);
+               if (status < 0)
+                       goto error;
+               if ((clkNeg | IQM_AF_CLKNEG_CLKNEGDATA__M) ==
+                       IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) {
+                       clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
+                       clkNeg |=
+                               IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_NEG;
+               } else {
+                       clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
+                       clkNeg |=
+                               IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS;
+               }
+               status = write16(state, IQM_AF_CLKNEG__A, clkNeg);
+               if (status < 0)
+                       goto error;
+               status = ADCSyncMeasurement(state, &count);
+               if (status < 0)
+                       goto error;
+       }
+
+       if (count < 2)
+               status = -EINVAL;
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int SetFrequencyShifter(struct drxk_state *state,
+                              u16 intermediateFreqkHz,
+                              s32 tunerFreqOffset, bool isDTV)
+{
+       bool selectPosImage = false;
+       u32 rfFreqResidual = tunerFreqOffset;
+       u32 fmFrequencyShift = 0;
+       bool tunerMirror = !state->m_bMirrorFreqSpect;
+       u32 adcFreq;
+       bool adcFlip;
+       int status;
+       u32 ifFreqActual;
+       u32 samplingFrequency = (u32) (state->m_sysClockFreq / 3);
+       u32 frequencyShift;
+       bool imageToSelect;
+
+       dprintk(1, "\n");
+
+       /*
+          Program frequency shifter
+          No need to account for mirroring on RF
+        */
+       if (isDTV) {
+               if ((state->m_OperationMode == OM_QAM_ITU_A) ||
+                   (state->m_OperationMode == OM_QAM_ITU_C) ||
+                   (state->m_OperationMode == OM_DVBT))
+                       selectPosImage = true;
+               else
+                       selectPosImage = false;
+       }
+       if (tunerMirror)
+               /* tuner doesn't mirror */
+               ifFreqActual = intermediateFreqkHz +
+                   rfFreqResidual + fmFrequencyShift;
+       else
+               /* tuner mirrors */
+               ifFreqActual = intermediateFreqkHz -
+                   rfFreqResidual - fmFrequencyShift;
+       if (ifFreqActual > samplingFrequency / 2) {
+               /* adc mirrors */
+               adcFreq = samplingFrequency - ifFreqActual;
+               adcFlip = true;
+       } else {
+               /* adc doesn't mirror */
+               adcFreq = ifFreqActual;
+               adcFlip = false;
+       }
+
+       frequencyShift = adcFreq;
+       imageToSelect = state->m_rfmirror ^ tunerMirror ^
+           adcFlip ^ selectPosImage;
+       state->m_IqmFsRateOfs =
+           Frac28a((frequencyShift), samplingFrequency);
+
+       if (imageToSelect)
+               state->m_IqmFsRateOfs = ~state->m_IqmFsRateOfs + 1;
+
+       /* Program frequency shifter with tuner offset compensation */
+       /* frequencyShift += tunerFreqOffset; TODO */
+       status = write32(state, IQM_FS_RATE_OFS_LO__A,
+                        state->m_IqmFsRateOfs);
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int InitAGC(struct drxk_state *state, bool isDTV)
+{
+       u16 ingainTgt = 0;
+       u16 ingainTgtMin = 0;
+       u16 ingainTgtMax = 0;
+       u16 clpCyclen = 0;
+       u16 clpSumMin = 0;
+       u16 clpDirTo = 0;
+       u16 snsSumMin = 0;
+       u16 snsSumMax = 0;
+       u16 clpSumMax = 0;
+       u16 snsDirTo = 0;
+       u16 kiInnergainMin = 0;
+       u16 ifIaccuHiTgt = 0;
+       u16 ifIaccuHiTgtMin = 0;
+       u16 ifIaccuHiTgtMax = 0;
+       u16 data = 0;
+       u16 fastClpCtrlDelay = 0;
+       u16 clpCtrlMode = 0;
+       int status = 0;
+
+       dprintk(1, "\n");
+
+       /* Common settings */
+       snsSumMax = 1023;
+       ifIaccuHiTgtMin = 2047;
+       clpCyclen = 500;
+       clpSumMax = 1023;
+
+       /* AGCInit() not available for DVBT; init done in microcode */
+       if (!IsQAM(state)) {
+               printk(KERN_ERR "drxk: %s: mode %d is not DVB-C\n", __func__, state->m_OperationMode);
+               return -EINVAL;
+       }
+
+       /* FIXME: Analog TV AGC require different settings */
+
+       /* Standard specific settings */
+       clpSumMin = 8;
+       clpDirTo = (u16) -9;
+       clpCtrlMode = 0;
+       snsSumMin = 8;
+       snsDirTo = (u16) -9;
+       kiInnergainMin = (u16) -1030;
+       ifIaccuHiTgtMax = 0x2380;
+       ifIaccuHiTgt = 0x2380;
+       ingainTgtMin = 0x0511;
+       ingainTgt = 0x0511;
+       ingainTgtMax = 5119;
+       fastClpCtrlDelay = state->m_qamIfAgcCfg.FastClipCtrlDelay;
+
+       status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, fastClpCtrlDelay);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clpCtrlMode);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingainTgt);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingainTgtMin);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingainTgtMax);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, ifIaccuHiTgtMin);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, ifIaccuHiTgtMax);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_IF_IACCU_HI__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_IF_IACCU_LO__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_RF_IACCU_LO__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clpSumMax);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, snsSumMax);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, kiInnergainMin);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, ifIaccuHiTgt);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clpCyclen);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_AGC_RF_SNS_DEV_MAX__A, 1023);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_RF_SNS_DEV_MIN__A, (u16) -1023);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A, 50);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clpSumMin);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, snsSumMin);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clpDirTo);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, snsDirTo);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_KI_MIN__A, 0x0117);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_KI_MAX__A, 0x0657);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_CLP_SUM__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_CLP_CYCCNT__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_CLP_DIR_WD__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_CLP_DIR_STP__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_SNS_SUM__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_SNS_CYCCNT__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_SNS_DIR_WD__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_SNS_DIR_STP__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_SNS_CYCLEN__A, 500);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_KI_CYCLEN__A, 500);
+       if (status < 0)
+               goto error;
+
+       /* Initialize inner-loop KI gain factors */
+       status = read16(state, SCU_RAM_AGC_KI__A, &data);
+       if (status < 0)
+               goto error;
+
+       data = 0x0657;
+       data &= ~SCU_RAM_AGC_KI_RF__M;
+       data |= (DRXK_KI_RAGC_QAM << SCU_RAM_AGC_KI_RF__B);
+       data &= ~SCU_RAM_AGC_KI_IF__M;
+       data |= (DRXK_KI_IAGC_QAM << SCU_RAM_AGC_KI_IF__B);
+
+       status = write16(state, SCU_RAM_AGC_KI__A, data);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int DVBTQAMGetAccPktErr(struct drxk_state *state, u16 *packetErr)
+{
+       int status;
+
+       dprintk(1, "\n");
+       if (packetErr == NULL)
+               status = write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
+       else
+               status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, packetErr);
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int DVBTScCommand(struct drxk_state *state,
+                        u16 cmd, u16 subcmd,
+                        u16 param0, u16 param1, u16 param2,
+                        u16 param3, u16 param4)
+{
+       u16 curCmd = 0;
+       u16 errCode = 0;
+       u16 retryCnt = 0;
+       u16 scExec = 0;
+       int status;
+
+       dprintk(1, "\n");
+       status = read16(state, OFDM_SC_COMM_EXEC__A, &scExec);
+       if (scExec != 1) {
+               /* SC is not running */
+               status = -EINVAL;
+       }
+       if (status < 0)
+               goto error;
+
+       /* Wait until sc is ready to receive command */
+       retryCnt = 0;
+       do {
+               msleep(1);
+               status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd);
+               retryCnt++;
+       } while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES));
+       if (retryCnt >= DRXK_MAX_RETRIES && (status < 0))
+               goto error;
+
+       /* Write sub-command */
+       switch (cmd) {
+               /* All commands using sub-cmd */
+       case OFDM_SC_RA_RAM_CMD_PROC_START:
+       case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
+       case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
+               status = write16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, subcmd);
+               if (status < 0)
+                       goto error;
+               break;
+       default:
+               /* Do nothing */
+               break;
+       }
+
+       /* Write needed parameters and the command */
+       switch (cmd) {
+               /* All commands using 5 parameters */
+               /* All commands using 4 parameters */
+               /* All commands using 3 parameters */
+               /* All commands using 2 parameters */
+       case OFDM_SC_RA_RAM_CMD_PROC_START:
+       case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
+       case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
+               status = write16(state, OFDM_SC_RA_RAM_PARAM1__A, param1);
+               /* All commands using 1 parameters */
+       case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
+       case OFDM_SC_RA_RAM_CMD_USER_IO:
+               status = write16(state, OFDM_SC_RA_RAM_PARAM0__A, param0);
+               /* All commands using 0 parameters */
+       case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
+       case OFDM_SC_RA_RAM_CMD_NULL:
+               /* Write command */
+               status = write16(state, OFDM_SC_RA_RAM_CMD__A, cmd);
+               break;
+       default:
+               /* Unknown command */
+               status = -EINVAL;
+       }
+       if (status < 0)
+               goto error;
+
+       /* Wait until sc is ready processing command */
+       retryCnt = 0;
+       do {
+               msleep(1);
+               status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd);
+               retryCnt++;
+       } while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES));
+       if (retryCnt >= DRXK_MAX_RETRIES && (status < 0))
+               goto error;
+
+       /* Check for illegal cmd */
+       status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &errCode);
+       if (errCode == 0xFFFF) {
+               /* illegal command */
+               status = -EINVAL;
+       }
+       if (status < 0)
+               goto error;
+
+       /* Retreive results parameters from SC */
+       switch (cmd) {
+               /* All commands yielding 5 results */
+               /* All commands yielding 4 results */
+               /* All commands yielding 3 results */
+               /* All commands yielding 2 results */
+               /* All commands yielding 1 result */
+       case OFDM_SC_RA_RAM_CMD_USER_IO:
+       case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
+               status = read16(state, OFDM_SC_RA_RAM_PARAM0__A, &(param0));
+               /* All commands yielding 0 results */
+       case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
+       case OFDM_SC_RA_RAM_CMD_SET_TIMER:
+       case OFDM_SC_RA_RAM_CMD_PROC_START:
+       case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
+       case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
+       case OFDM_SC_RA_RAM_CMD_NULL:
+               break;
+       default:
+               /* Unknown command */
+               status = -EINVAL;
+               break;
+       }                       /* switch (cmd->cmd) */
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int PowerUpDVBT(struct drxk_state *state)
+{
+       enum DRXPowerMode powerMode = DRX_POWER_UP;
+       int status;
+
+       dprintk(1, "\n");
+       status = CtrlPowerMode(state, &powerMode);
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int DVBTCtrlSetIncEnable(struct drxk_state *state, bool *enabled)
+{
+       int status;
+
+       dprintk(1, "\n");
+       if (*enabled == true)
+               status = write16(state, IQM_CF_BYPASSDET__A, 0);
+       else
+               status = write16(state, IQM_CF_BYPASSDET__A, 1);
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+#define DEFAULT_FR_THRES_8K     4000
+static int DVBTCtrlSetFrEnable(struct drxk_state *state, bool *enabled)
+{
+
+       int status;
+
+       dprintk(1, "\n");
+       if (*enabled == true) {
+               /* write mask to 1 */
+               status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A,
+                                  DEFAULT_FR_THRES_8K);
+       } else {
+               /* write mask to 0 */
+               status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, 0);
+       }
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+static int DVBTCtrlSetEchoThreshold(struct drxk_state *state,
+                                   struct DRXKCfgDvbtEchoThres_t *echoThres)
+{
+       u16 data = 0;
+       int status;
+
+       dprintk(1, "\n");
+       status = read16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, &data);
+       if (status < 0)
+               goto error;
+
+       switch (echoThres->fftMode) {
+       case DRX_FFTMODE_2K:
+               data &= ~OFDM_SC_RA_RAM_ECHO_THRES_2K__M;
+               data |= ((echoThres->threshold <<
+                       OFDM_SC_RA_RAM_ECHO_THRES_2K__B)
+                       & (OFDM_SC_RA_RAM_ECHO_THRES_2K__M));
+               break;
+       case DRX_FFTMODE_8K:
+               data &= ~OFDM_SC_RA_RAM_ECHO_THRES_8K__M;
+               data |= ((echoThres->threshold <<
+                       OFDM_SC_RA_RAM_ECHO_THRES_8K__B)
+                       & (OFDM_SC_RA_RAM_ECHO_THRES_8K__M));
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       status = write16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, data);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int DVBTCtrlSetSqiSpeed(struct drxk_state *state,
+                              enum DRXKCfgDvbtSqiSpeed *speed)
+{
+       int status = -EINVAL;
+
+       dprintk(1, "\n");
+
+       switch (*speed) {
+       case DRXK_DVBT_SQI_SPEED_FAST:
+       case DRXK_DVBT_SQI_SPEED_MEDIUM:
+       case DRXK_DVBT_SQI_SPEED_SLOW:
+               break;
+       default:
+               goto error;
+       }
+       status = write16(state, SCU_RAM_FEC_PRE_RS_BER_FILTER_SH__A,
+                          (u16) *speed);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Activate DVBT specific presets
+* \param demod instance of demodulator.
+* \return DRXStatus_t.
+*
+* Called in DVBTSetStandard
+*
+*/
+static int DVBTActivatePresets(struct drxk_state *state)
+{
+       int status;
+       bool setincenable = false;
+       bool setfrenable = true;
+
+       struct DRXKCfgDvbtEchoThres_t echoThres2k = { 0, DRX_FFTMODE_2K };
+       struct DRXKCfgDvbtEchoThres_t echoThres8k = { 0, DRX_FFTMODE_8K };
+
+       dprintk(1, "\n");
+       status = DVBTCtrlSetIncEnable(state, &setincenable);
+       if (status < 0)
+               goto error;
+       status = DVBTCtrlSetFrEnable(state, &setfrenable);
+       if (status < 0)
+               goto error;
+       status = DVBTCtrlSetEchoThreshold(state, &echoThres2k);
+       if (status < 0)
+               goto error;
+       status = DVBTCtrlSetEchoThreshold(state, &echoThres8k);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, state->m_dvbtIfAgcCfg.IngainTgtMax);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Initialize channelswitch-independent settings for DVBT.
+* \param demod instance of demodulator.
+* \return DRXStatus_t.
+*
+* For ROM code channel filter taps are loaded from the bootloader. For microcode
+* the DVB-T taps from the drxk_filters.h are used.
+*/
+static int SetDVBTStandard(struct drxk_state *state,
+                          enum OperationMode oMode)
+{
+       u16 cmdResult = 0;
+       u16 data = 0;
+       int status;
+
+       dprintk(1, "\n");
+
+       PowerUpDVBT(state);
+       /* added antenna switch */
+       SwitchAntennaToDVBT(state);
+       /* send OFDM reset command */
+       status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult);
+       if (status < 0)
+               goto error;
+
+       /* send OFDM setenv command */
+       status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 0, NULL, 1, &cmdResult);
+       if (status < 0)
+               goto error;
+
+       /* reset datapath for OFDM, processors first */
+       status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
+       if (status < 0)
+               goto error;
+       status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
+       if (status < 0)
+               goto error;
+
+       /* IQM setup */
+       /* synchronize on ofdstate->m_festart */
+       status = write16(state, IQM_AF_UPD_SEL__A, 1);
+       if (status < 0)
+               goto error;
+       /* window size for clipping ADC detection */
+       status = write16(state, IQM_AF_CLP_LEN__A, 0);
+       if (status < 0)
+               goto error;
+       /* window size for for sense pre-SAW detection */
+       status = write16(state, IQM_AF_SNS_LEN__A, 0);
+       if (status < 0)
+               goto error;
+       /* sense threshold for sense pre-SAW detection */
+       status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC);
+       if (status < 0)
+               goto error;
+       status = SetIqmAf(state, true);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, IQM_AF_AGC_RF__A, 0);
+       if (status < 0)
+               goto error;
+
+       /* Impulse noise cruncher setup */
+       status = write16(state, IQM_AF_INC_LCT__A, 0);  /* crunch in IQM_CF */
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_DET_LCT__A, 0);  /* detect in IQM_CF */
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_WND_LEN__A, 3);  /* peak detector window length */
+       if (status < 0)
+               goto error;
+
+       status = write16(state, IQM_RC_STRETCH__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_OUT_ENA__A, 0x4);        /* enable output 2 */
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_DS_ENA__A, 0x4); /* decimate output 2 */
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_SCALE__A, 1600);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_SCALE_SH__A, 0);
+       if (status < 0)
+               goto error;
+
+       /* virtual clipping threshold for clipping ADC detection */
+       status = write16(state, IQM_AF_CLP_TH__A, 448);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_DATATH__A, 495); /* crunching threshold */
+       if (status < 0)
+               goto error;
+
+       status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, IQM_CF_PKDTH__A, 2);    /* peak detector threshold */
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_POW_MEAS_LEN__A, 2);
+       if (status < 0)
+               goto error;
+       /* enable power measurement interrupt */
+       status = write16(state, IQM_CF_COMM_INT_MSK__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_ACTIVE);
+       if (status < 0)
+               goto error;
+
+       /* IQM will not be reset from here, sync ADC and update/init AGC */
+       status = ADCSynchronization(state);
+       if (status < 0)
+               goto error;
+       status = SetPreSaw(state, &state->m_dvbtPreSawCfg);
+       if (status < 0)
+               goto error;
+
+       /* Halt SCU to enable safe non-atomic accesses */
+       status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
+       if (status < 0)
+               goto error;
+
+       status = SetAgcRf(state, &state->m_dvbtRfAgcCfg, true);
+       if (status < 0)
+               goto error;
+       status = SetAgcIf(state, &state->m_dvbtIfAgcCfg, true);
+       if (status < 0)
+               goto error;
+
+       /* Set Noise Estimation notch width and enable DC fix */
+       status = read16(state, OFDM_SC_RA_RAM_CONFIG__A, &data);
+       if (status < 0)
+               goto error;
+       data |= OFDM_SC_RA_RAM_CONFIG_NE_FIX_ENABLE__M;
+       status = write16(state, OFDM_SC_RA_RAM_CONFIG__A, data);
+       if (status < 0)
+               goto error;
+
+       /* Activate SCU to enable SCU commands */
+       status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
+       if (status < 0)
+               goto error;
+
+       if (!state->m_DRXK_A3_ROM_CODE) {
+               /* AGCInit() is not done for DVBT, so set agcFastClipCtrlDelay  */
+               status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, state->m_dvbtIfAgcCfg.FastClipCtrlDelay);
+               if (status < 0)
+                       goto error;
+       }
+
+       /* OFDM_SC setup */
+#ifdef COMPILE_FOR_NONRT
+       status = write16(state, OFDM_SC_RA_RAM_BE_OPT_DELAY__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, OFDM_SC_RA_RAM_BE_OPT_INIT_DELAY__A, 2);
+       if (status < 0)
+               goto error;
+#endif
+
+       /* FEC setup */
+       status = write16(state, FEC_DI_INPUT_CTL__A, 1);        /* OFDM input */
+       if (status < 0)
+               goto error;
+
+
+#ifdef COMPILE_FOR_NONRT
+       status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, 0x400);
+       if (status < 0)
+               goto error;
+#else
+       status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, 0x1000);
+       if (status < 0)
+               goto error;
+#endif
+       status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, 0x0001);
+       if (status < 0)
+               goto error;
+
+       /* Setup MPEG bus */
+       status = MPEGTSDtoSetup(state, OM_DVBT);
+       if (status < 0)
+               goto error;
+       /* Set DVBT Presets */
+       status = DVBTActivatePresets(state);
+       if (status < 0)
+               goto error;
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+/*============================================================================*/
+/**
+* \brief Start dvbt demodulating for channel.
+* \param demod instance of demodulator.
+* \return DRXStatus_t.
+*/
+static int DVBTStart(struct drxk_state *state)
+{
+       u16 param1;
+       int status;
+       /* DRXKOfdmScCmd_t scCmd; */
+
+       dprintk(1, "\n");
+       /* Start correct processes to get in lock */
+       /* DRXK: OFDM_SC_RA_RAM_PROC_LOCKTRACK is no longer in mapfile! */
+       param1 = OFDM_SC_RA_RAM_LOCKTRACK_MIN;
+       status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, 0, 0, 0);
+       if (status < 0)
+               goto error;
+       /* Start FEC OC */
+       status = MPEGTSStart(state);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE);
+       if (status < 0)
+               goto error;
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+
+/*============================================================================*/
+
+/**
+* \brief Set up dvbt demodulator for channel.
+* \param demod instance of demodulator.
+* \return DRXStatus_t.
+* // original DVBTSetChannel()
+*/
+static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
+                  s32 tunerFreqOffset)
+{
+       u16 cmdResult = 0;
+       u16 transmissionParams = 0;
+       u16 operationMode = 0;
+       u32 iqmRcRateOfs = 0;
+       u32 bandwidth = 0;
+       u16 param1;
+       int status;
+
+       dprintk(1, "IF =%d, TFO = %d\n", IntermediateFreqkHz, tunerFreqOffset);
+
+       status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult);
+       if (status < 0)
+               goto error;
+
+       /* Halt SCU to enable safe non-atomic accesses */
+       status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
+       if (status < 0)
+               goto error;
+
+       /* Stop processors */
+       status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
+       if (status < 0)
+               goto error;
+       status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
+       if (status < 0)
+               goto error;
+
+       /* Mandatory fix, always stop CP, required to set spl offset back to
+               hardware default (is set to 0 by ucode during pilot detection */
+       status = write16(state, OFDM_CP_COMM_EXEC__A, OFDM_CP_COMM_EXEC_STOP);
+       if (status < 0)
+               goto error;
+
+       /*== Write channel settings to device =====================================*/
+
+       /* mode */
+       switch (state->param.u.ofdm.transmission_mode) {
+       case TRANSMISSION_MODE_AUTO:
+       default:
+               operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M;
+               /* fall through , try first guess DRX_FFTMODE_8K */
+       case TRANSMISSION_MODE_8K:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K;
+               break;
+       case TRANSMISSION_MODE_2K:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K;
+               break;
+       }
+
+       /* guard */
+       switch (state->param.u.ofdm.guard_interval) {
+       default:
+       case GUARD_INTERVAL_AUTO:
+               operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M;
+               /* fall through , try first guess DRX_GUARD_1DIV4 */
+       case GUARD_INTERVAL_1_4:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4;
+               break;
+       case GUARD_INTERVAL_1_32:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32;
+               break;
+       case GUARD_INTERVAL_1_16:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16;
+               break;
+       case GUARD_INTERVAL_1_8:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8;
+               break;
+       }
+
+       /* hierarchy */
+       switch (state->param.u.ofdm.hierarchy_information) {
+       case HIERARCHY_AUTO:
+       case HIERARCHY_NONE:
+       default:
+               operationMode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M;
+               /* fall through , try first guess SC_RA_RAM_OP_PARAM_HIER_NO */
+               /* transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */
+               /* break; */
+       case HIERARCHY_1:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1;
+               break;
+       case HIERARCHY_2:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2;
+               break;
+       case HIERARCHY_4:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4;
+               break;
+       }
+
+
+       /* constellation */
+       switch (state->param.u.ofdm.constellation) {
+       case QAM_AUTO:
+       default:
+               operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M;
+               /* fall through , try first guess DRX_CONSTELLATION_QAM64 */
+       case QAM_64:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64;
+               break;
+       case QPSK:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK;
+               break;
+       case QAM_16:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16;
+               break;
+       }
+#if 0
+       /* No hierachical channels support in BDA */
+       /* Priority (only for hierarchical channels) */
+       switch (channel->priority) {
+       case DRX_PRIORITY_LOW:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO;
+               WR16(devAddr, OFDM_EC_SB_PRIOR__A,
+                       OFDM_EC_SB_PRIOR_LO);
+               break;
+       case DRX_PRIORITY_HIGH:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
+               WR16(devAddr, OFDM_EC_SB_PRIOR__A,
+                       OFDM_EC_SB_PRIOR_HI));
+               break;
+       case DRX_PRIORITY_UNKNOWN:      /* fall through */
+       default:
+               status = -EINVAL;
+               goto error;
+       }
+#else
+       /* Set Priorty high */
+       transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
+       status = write16(state, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI);
+       if (status < 0)
+               goto error;
+#endif
+
+       /* coderate */
+       switch (state->param.u.ofdm.code_rate_HP) {
+       case FEC_AUTO:
+       default:
+               operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M;
+               /* fall through , try first guess DRX_CODERATE_2DIV3 */
+       case FEC_2_3:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3;
+               break;
+       case FEC_1_2:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2;
+               break;
+       case FEC_3_4:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4;
+               break;
+       case FEC_5_6:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6;
+               break;
+       case FEC_7_8:
+               transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8;
+               break;
+       }
+
+       /* SAW filter selection: normaly not necesarry, but if wanted
+               the application can select a SAW filter via the driver by using UIOs */
+       /* First determine real bandwidth (Hz) */
+       /* Also set delay for impulse noise cruncher */
+       /* Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is changed
+               by SC for fix for some 8K,1/8 guard but is restored by InitEC and ResetEC
+               functions */
+       switch (state->param.u.ofdm.bandwidth) {
+       case BANDWIDTH_AUTO:
+       case BANDWIDTH_8_MHZ:
+               bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ;
+               status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3052);
+               if (status < 0)
+                       goto error;
+               /* cochannel protection for PAL 8 MHz */
+               status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 7);
+               if (status < 0)
+                       goto error;
+               status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 7);
+               if (status < 0)
+                       goto error;
+               status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 7);
+               if (status < 0)
+                       goto error;
+               status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1);
+               if (status < 0)
+                       goto error;
+               break;
+       case BANDWIDTH_7_MHZ:
+               bandwidth = DRXK_BANDWIDTH_7MHZ_IN_HZ;
+               status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3491);
+               if (status < 0)
+                       goto error;
+               /* cochannel protection for PAL 7 MHz */
+               status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 8);
+               if (status < 0)
+                       goto error;
+               status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 8);
+               if (status < 0)
+                       goto error;
+               status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 4);
+               if (status < 0)
+                       goto error;
+               status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1);
+               if (status < 0)
+                       goto error;
+               break;
+       case BANDWIDTH_6_MHZ:
+               bandwidth = DRXK_BANDWIDTH_6MHZ_IN_HZ;
+               status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 4073);
+               if (status < 0)
+                       goto error;
+               /* cochannel protection for NTSC 6 MHz */
+               status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 19);
+               if (status < 0)
+                       goto error;
+               status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 19);
+               if (status < 0)
+                       goto error;
+               status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 14);
+               if (status < 0)
+                       goto error;
+               status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1);
+               if (status < 0)
+                       goto error;
+               break;
+       default:
+               status = -EINVAL;
+               goto error;
+       }
+
+       if (iqmRcRateOfs == 0) {
+               /* Now compute IQM_RC_RATE_OFS
+                       (((SysFreq/BandWidth)/2)/2) -1) * 2^23)
+                       =>
+                       ((SysFreq / BandWidth) * (2^21)) - (2^23)
+                       */
+               /* (SysFreq / BandWidth) * (2^28)  */
+               /* assert (MAX(sysClk)/MIN(bandwidth) < 16)
+                       => assert(MAX(sysClk) < 16*MIN(bandwidth))
+                       => assert(109714272 > 48000000) = true so Frac 28 can be used  */
+               iqmRcRateOfs = Frac28a((u32)
+                                       ((state->m_sysClockFreq *
+                                               1000) / 3), bandwidth);
+               /* (SysFreq / BandWidth) * (2^21), rounding before truncating  */
+               if ((iqmRcRateOfs & 0x7fL) >= 0x40)
+                       iqmRcRateOfs += 0x80L;
+               iqmRcRateOfs = iqmRcRateOfs >> 7;
+               /* ((SysFreq / BandWidth) * (2^21)) - (2^23)  */
+               iqmRcRateOfs = iqmRcRateOfs - (1 << 23);
+       }
+
+       iqmRcRateOfs &=
+               ((((u32) IQM_RC_RATE_OFS_HI__M) <<
+               IQM_RC_RATE_OFS_LO__W) | IQM_RC_RATE_OFS_LO__M);
+       status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRateOfs);
+       if (status < 0)
+               goto error;
+
+       /* Bandwidth setting done */
+
+#if 0
+       status = DVBTSetFrequencyShift(demod, channel, tunerOffset);
+       if (status < 0)
+               goto error;
+#endif
+       status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true);
+       if (status < 0)
+               goto error;
+
+       /*== Start SC, write channel settings to SC ===============================*/
+
+       /* Activate SCU to enable SCU commands */
+       status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
+       if (status < 0)
+               goto error;
+
+       /* Enable SC after setting all other parameters */
+       status = write16(state, OFDM_SC_COMM_STATE__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, OFDM_SC_COMM_EXEC__A, 1);
+       if (status < 0)
+               goto error;
+
+
+       status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult);
+       if (status < 0)
+               goto error;
+
+       /* Write SC parameter registers, set all AUTO flags in operation mode */
+       param1 = (OFDM_SC_RA_RAM_OP_AUTO_MODE__M |
+                       OFDM_SC_RA_RAM_OP_AUTO_GUARD__M |
+                       OFDM_SC_RA_RAM_OP_AUTO_CONST__M |
+                       OFDM_SC_RA_RAM_OP_AUTO_HIER__M |
+                       OFDM_SC_RA_RAM_OP_AUTO_RATE__M);
+       status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM,
+                               0, transmissionParams, param1, 0, 0, 0);
+       if (status < 0)
+               goto error;
+
+       if (!state->m_DRXK_A3_ROM_CODE)
+               status = DVBTCtrlSetSqiSpeed(state, &state->m_sqiSpeed);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+
+/*============================================================================*/
+
+/**
+* \brief Retreive lock status .
+* \param demod    Pointer to demodulator instance.
+* \param lockStat Pointer to lock status structure.
+* \return DRXStatus_t.
+*
+*/
+static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus)
+{
+       int status;
+       const u16 mpeg_lock_mask = (OFDM_SC_RA_RAM_LOCK_MPEG__M |
+                                   OFDM_SC_RA_RAM_LOCK_FEC__M);
+       const u16 fec_lock_mask = (OFDM_SC_RA_RAM_LOCK_FEC__M);
+       const u16 demod_lock_mask = OFDM_SC_RA_RAM_LOCK_DEMOD__M;
+
+       u16 ScRaRamLock = 0;
+       u16 ScCommExec = 0;
+
+       dprintk(1, "\n");
+
+       *pLockStatus = NOT_LOCKED;
+       /* driver 0.9.0 */
+       /* Check if SC is running */
+       status = read16(state, OFDM_SC_COMM_EXEC__A, &ScCommExec);
+       if (status < 0)
+               goto end;
+       if (ScCommExec == OFDM_SC_COMM_EXEC_STOP)
+               goto end;
+
+       status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &ScRaRamLock);
+       if (status < 0)
+               goto end;
+
+       if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask)
+               *pLockStatus = MPEG_LOCK;
+       else if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask)
+               *pLockStatus = FEC_LOCK;
+       else if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask)
+               *pLockStatus = DEMOD_LOCK;
+       else if (ScRaRamLock & OFDM_SC_RA_RAM_LOCK_NODVBT__M)
+               *pLockStatus = NEVER_LOCK;
+end:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+static int PowerUpQAM(struct drxk_state *state)
+{
+       enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
+       int status;
+
+       dprintk(1, "\n");
+       status = CtrlPowerMode(state, &powerMode);
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+
+/** Power Down QAM */
+static int PowerDownQAM(struct drxk_state *state)
+{
+       u16 data = 0;
+       u16 cmdResult;
+       int status = 0;
+
+       dprintk(1, "\n");
+       status = read16(state, SCU_COMM_EXEC__A, &data);
+       if (status < 0)
+               goto error;
+       if (data == SCU_COMM_EXEC_ACTIVE) {
+               /*
+                       STOP demodulator
+                       QAM and HW blocks
+                       */
+               /* stop all comstate->m_exec */
+               status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP);
+               if (status < 0)
+                       goto error;
+               status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult);
+               if (status < 0)
+                       goto error;
+       }
+       /* powerdown AFE                   */
+       status = SetIqmAf(state, false);
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Setup of the QAM Measurement intervals for signal quality
+* \param demod instance of demod.
+* \param constellation current constellation.
+* \return DRXStatus_t.
+*
+*  NOTE:
+*  Take into account that for certain settings the errorcounters can overflow.
+*  The implementation does not check this.
+*
+*/
+static int SetQAMMeasurement(struct drxk_state *state,
+                            enum EDrxkConstellation constellation,
+                            u32 symbolRate)
+{
+       u32 fecBitsDesired = 0; /* BER accounting period */
+       u32 fecRsPeriodTotal = 0;       /* Total period */
+       u16 fecRsPrescale = 0;  /* ReedSolomon Measurement Prescale */
+       u16 fecRsPeriod = 0;    /* Value for corresponding I2C register */
+       int status = 0;
+
+       dprintk(1, "\n");
+
+       fecRsPrescale = 1;
+       /* fecBitsDesired = symbolRate [kHz] *
+               FrameLenght [ms] *
+               (constellation + 1) *
+               SyncLoss (== 1) *
+               ViterbiLoss (==1)
+               */
+       switch (constellation) {
+       case DRX_CONSTELLATION_QAM16:
+               fecBitsDesired = 4 * symbolRate;
+               break;
+       case DRX_CONSTELLATION_QAM32:
+               fecBitsDesired = 5 * symbolRate;
+               break;
+       case DRX_CONSTELLATION_QAM64:
+               fecBitsDesired = 6 * symbolRate;
+               break;
+       case DRX_CONSTELLATION_QAM128:
+               fecBitsDesired = 7 * symbolRate;
+               break;
+       case DRX_CONSTELLATION_QAM256:
+               fecBitsDesired = 8 * symbolRate;
+               break;
+       default:
+               status = -EINVAL;
+       }
+       if (status < 0)
+               goto error;
+
+       fecBitsDesired /= 1000; /* symbolRate [Hz] -> symbolRate [kHz]  */
+       fecBitsDesired *= 500;  /* meas. period [ms] */
+
+       /* Annex A/C: bits/RsPeriod = 204 * 8 = 1632 */
+       /* fecRsPeriodTotal = fecBitsDesired / 1632 */
+       fecRsPeriodTotal = (fecBitsDesired / 1632UL) + 1;       /* roughly ceil */
+
+       /* fecRsPeriodTotal =  fecRsPrescale * fecRsPeriod  */
+       fecRsPrescale = 1 + (u16) (fecRsPeriodTotal >> 16);
+       if (fecRsPrescale == 0) {
+               /* Divide by zero (though impossible) */
+               status = -EINVAL;
+               if (status < 0)
+                       goto error;
+       }
+       fecRsPeriod =
+               ((u16) fecRsPeriodTotal +
+               (fecRsPrescale >> 1)) / fecRsPrescale;
+
+       /* write corresponding registers */
+       status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fecRsPeriod);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, fecRsPrescale);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fecRsPeriod);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int SetQAM16(struct drxk_state *state)
+{
+       int status = 0;
+
+       dprintk(1, "\n");
+       /* QAM Equalizer Setup */
+       /* Equalizer */
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 13517);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 13517);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 13517);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 13517);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13517);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 13517);
+       if (status < 0)
+               goto error;
+       /* Decision Feedback Equalizer */
+       status = write16(state, QAM_DQ_QUAL_FUN0__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN1__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN2__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN3__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN4__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, QAM_SY_SYNC_HWM__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_SY_SYNC_AWM__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_SY_SYNC_LWM__A, 3);
+       if (status < 0)
+               goto error;
+
+       /* QAM Slicer Settings */
+       status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM16);
+       if (status < 0)
+               goto error;
+
+       /* QAM Loop Controller Coeficients */
+       status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 80);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 32);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM State Machine (FSM) Thresholds */
+
+       status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 140);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 50);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 95);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 120);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 230);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 105);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 24);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM FSM Tracking Parameters */
+
+       status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 220);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 25);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 6);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -24);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -65);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -127);
+       if (status < 0)
+               goto error;
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief QAM32 specific setup
+* \param demod instance of demod.
+* \return DRXStatus_t.
+*/
+static int SetQAM32(struct drxk_state *state)
+{
+       int status = 0;
+
+       dprintk(1, "\n");
+
+       /* QAM Equalizer Setup */
+       /* Equalizer */
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 6707);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 6707);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 6707);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 6707);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 6707);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 6707);
+       if (status < 0)
+               goto error;
+
+       /* Decision Feedback Equalizer */
+       status = write16(state, QAM_DQ_QUAL_FUN0__A, 3);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN1__A, 3);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN2__A, 3);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN3__A, 3);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN4__A, 3);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, QAM_SY_SYNC_HWM__A, 6);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_SY_SYNC_AWM__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_SY_SYNC_LWM__A, 3);
+       if (status < 0)
+               goto error;
+
+       /* QAM Slicer Settings */
+
+       status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM32);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM Loop Controller Coeficients */
+
+       status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 80);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 0);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM State Machine (FSM) Thresholds */
+
+       status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 90);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 50);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 170);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 100);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 10);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM FSM Tracking Parameters */
+
+       status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 140);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) -8);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) -16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -26);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -56);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -86);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief QAM64 specific setup
+* \param demod instance of demod.
+* \return DRXStatus_t.
+*/
+static int SetQAM64(struct drxk_state *state)
+{
+       int status = 0;
+
+       dprintk(1, "\n");
+       /* QAM Equalizer Setup */
+       /* Equalizer */
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 13336);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 12618);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 11988);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 13809);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13809);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 15609);
+       if (status < 0)
+               goto error;
+
+       /* Decision Feedback Equalizer */
+       status = write16(state, QAM_DQ_QUAL_FUN0__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN1__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN2__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN3__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN4__A, 3);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, QAM_SY_SYNC_HWM__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_SY_SYNC_AWM__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_SY_SYNC_LWM__A, 3);
+       if (status < 0)
+               goto error;
+
+       /* QAM Slicer Settings */
+       status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM64);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM Loop Controller Coeficients */
+
+       status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 30);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 100);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 30);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 48);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM State Machine (FSM) Thresholds */
+
+       status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 100);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 110);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 200);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 95);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 15);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM FSM Tracking Parameters */
+
+       status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 141);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 7);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -15);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -45);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -80);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief QAM128 specific setup
+* \param demod: instance of demod.
+* \return DRXStatus_t.
+*/
+static int SetQAM128(struct drxk_state *state)
+{
+       int status = 0;
+
+       dprintk(1, "\n");
+       /* QAM Equalizer Setup */
+       /* Equalizer */
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 6564);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 6598);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 6394);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 6409);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 6656);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 7238);
+       if (status < 0)
+               goto error;
+
+       /* Decision Feedback Equalizer */
+       status = write16(state, QAM_DQ_QUAL_FUN0__A, 6);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN1__A, 6);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN2__A, 6);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN3__A, 6);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN4__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, QAM_SY_SYNC_HWM__A, 6);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_SY_SYNC_AWM__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_SY_SYNC_LWM__A, 3);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM Slicer Settings */
+
+       status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM128);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM Loop Controller Coeficients */
+
+       status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 40);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 120);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 40);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 60);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 64);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 0);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM State Machine (FSM) Thresholds */
+
+       status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 50);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 140);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 100);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 5);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 12);
+       if (status < 0)
+               goto error;
+
+       /* QAM FSM Tracking Parameters */
+
+       status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 8);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 65);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 3);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -1);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -23);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief QAM256 specific setup
+* \param demod: instance of demod.
+* \return DRXStatus_t.
+*/
+static int SetQAM256(struct drxk_state *state)
+{
+       int status = 0;
+
+       dprintk(1, "\n");
+       /* QAM Equalizer Setup */
+       /* Equalizer */
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 11502);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 12084);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 12543);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 12931);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13629);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 15385);
+       if (status < 0)
+               goto error;
+
+       /* Decision Feedback Equalizer */
+       status = write16(state, QAM_DQ_QUAL_FUN0__A, 8);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN1__A, 8);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN2__A, 8);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN3__A, 8);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN4__A, 6);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, QAM_SY_SYNC_HWM__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_SY_SYNC_AWM__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_SY_SYNC_LWM__A, 3);
+       if (status < 0)
+               goto error;
+
+       /* QAM Slicer Settings */
+
+       status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM256);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM Loop Controller Coeficients */
+
+       status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 50);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 250);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 50);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 125);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 48);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM State Machine (FSM) Thresholds */
+
+       status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 50);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 150);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 110);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 12);
+       if (status < 0)
+               goto error;
+
+
+       /* QAM FSM Tracking Parameters */
+
+       status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 8);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 74);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 18);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 13);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) 7);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -8);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+
+/*============================================================================*/
+/**
+* \brief Reset QAM block.
+* \param demod:   instance of demod.
+* \param channel: pointer to channel data.
+* \return DRXStatus_t.
+*/
+static int QAMResetQAM(struct drxk_state *state)
+{
+       int status;
+       u16 cmdResult;
+
+       dprintk(1, "\n");
+       /* Stop QAM comstate->m_exec */
+       status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP);
+       if (status < 0)
+               goto error;
+
+       status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Set QAM symbolrate.
+* \param demod:   instance of demod.
+* \param channel: pointer to channel data.
+* \return DRXStatus_t.
+*/
+static int QAMSetSymbolrate(struct drxk_state *state)
+{
+       u32 adcFrequency = 0;
+       u32 symbFreq = 0;
+       u32 iqmRcRate = 0;
+       u16 ratesel = 0;
+       u32 lcSymbRate = 0;
+       int status;
+
+       dprintk(1, "\n");
+       /* Select & calculate correct IQM rate */
+       adcFrequency = (state->m_sysClockFreq * 1000) / 3;
+       ratesel = 0;
+       /* printk(KERN_DEBUG "drxk: SR %d\n", state->param.u.qam.symbol_rate); */
+       if (state->param.u.qam.symbol_rate <= 1188750)
+               ratesel = 3;
+       else if (state->param.u.qam.symbol_rate <= 2377500)
+               ratesel = 2;
+       else if (state->param.u.qam.symbol_rate <= 4755000)
+               ratesel = 1;
+       status = write16(state, IQM_FD_RATESEL__A, ratesel);
+       if (status < 0)
+               goto error;
+
+       /*
+               IqmRcRate = ((Fadc / (symbolrate * (4<<ratesel))) - 1) * (1<<23)
+               */
+       symbFreq = state->param.u.qam.symbol_rate * (1 << ratesel);
+       if (symbFreq == 0) {
+               /* Divide by zero */
+               status = -EINVAL;
+               goto error;
+       }
+       iqmRcRate = (adcFrequency / symbFreq) * (1 << 21) +
+               (Frac28a((adcFrequency % symbFreq), symbFreq) >> 7) -
+               (1 << 23);
+       status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRate);
+       if (status < 0)
+               goto error;
+       state->m_iqmRcRate = iqmRcRate;
+       /*
+               LcSymbFreq = round (.125 *  symbolrate / adcFreq * (1<<15))
+               */
+       symbFreq = state->param.u.qam.symbol_rate;
+       if (adcFrequency == 0) {
+               /* Divide by zero */
+               status = -EINVAL;
+               goto error;
+       }
+       lcSymbRate = (symbFreq / adcFrequency) * (1 << 12) +
+               (Frac28a((symbFreq % adcFrequency), adcFrequency) >>
+               16);
+       if (lcSymbRate > 511)
+               lcSymbRate = 511;
+       status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lcSymbRate);
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Get QAM lock status.
+* \param demod:   instance of demod.
+* \param channel: pointer to channel data.
+* \return DRXStatus_t.
+*/
+
+static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus)
+{
+       int status;
+       u16 Result[2] = { 0, 0 };
+
+       dprintk(1, "\n");
+       *pLockStatus = NOT_LOCKED;
+       status = scu_command(state,
+                       SCU_RAM_COMMAND_STANDARD_QAM |
+                       SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2,
+                       Result);
+       if (status < 0)
+               printk(KERN_ERR "drxk: %s status = %08x\n", __func__, status);
+
+       if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) {
+               /* 0x0000 NOT LOCKED */
+       } else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) {
+               /* 0x4000 DEMOD LOCKED */
+               *pLockStatus = DEMOD_LOCK;
+       } else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) {
+               /* 0x8000 DEMOD + FEC LOCKED (system lock) */
+               *pLockStatus = MPEG_LOCK;
+       } else {
+               /* 0xC000 NEVER LOCKED */
+               /* (system will never be able to lock to the signal) */
+               /* TODO: check this, intermediate & standard specific lock states are not
+                  taken into account here */
+               *pLockStatus = NEVER_LOCK;
+       }
+       return status;
+}
+
+#define QAM_MIRROR__M         0x03
+#define QAM_MIRROR_NORMAL     0x00
+#define QAM_MIRRORED          0x01
+#define QAM_MIRROR_AUTO_ON    0x02
+#define QAM_LOCKRANGE__M      0x10
+#define QAM_LOCKRANGE_NORMAL  0x10
+
+static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
+                 s32 tunerFreqOffset)
+{
+       int status;
+       u16 setParamParameters[4] = { 0, 0, 0, 0 };
+       u16 cmdResult;
+
+       dprintk(1, "\n");
+       /*
+        * STEP 1: reset demodulator
+        *      resets FEC DI and FEC RS
+        *      resets QAM block
+        *      resets SCU variables
+        */
+       status = write16(state, FEC_DI_COMM_EXEC__A, FEC_DI_COMM_EXEC_STOP);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_RS_COMM_EXEC__A, FEC_RS_COMM_EXEC_STOP);
+       if (status < 0)
+               goto error;
+       status = QAMResetQAM(state);
+       if (status < 0)
+               goto error;
+
+       /*
+        * STEP 2: configure demodulator
+        *      -set params; resets IQM,QAM,FEC HW; initializes some
+        *       SCU variables
+        */
+       status = QAMSetSymbolrate(state);
+       if (status < 0)
+               goto error;
+
+       /* Set params */
+       switch (state->param.u.qam.modulation) {
+       case QAM_256:
+               state->m_Constellation = DRX_CONSTELLATION_QAM256;
+               break;
+       case QAM_AUTO:
+       case QAM_64:
+               state->m_Constellation = DRX_CONSTELLATION_QAM64;
+               break;
+       case QAM_16:
+               state->m_Constellation = DRX_CONSTELLATION_QAM16;
+               break;
+       case QAM_32:
+               state->m_Constellation = DRX_CONSTELLATION_QAM32;
+               break;
+       case QAM_128:
+               state->m_Constellation = DRX_CONSTELLATION_QAM128;
+               break;
+       default:
+               status = -EINVAL;
+               break;
+       }
+       if (status < 0)
+               goto error;
+       setParamParameters[0] = state->m_Constellation; /* constellation     */
+       setParamParameters[1] = DRXK_QAM_I12_J17;       /* interleave mode   */
+       if (state->m_OperationMode == OM_QAM_ITU_C)
+               setParamParameters[2] = QAM_TOP_ANNEX_C;
+       else
+               setParamParameters[2] = QAM_TOP_ANNEX_A;
+       setParamParameters[3] |= (QAM_MIRROR_AUTO_ON);
+       /* Env parameters */
+       /* check for LOCKRANGE Extented */
+       /* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */
+
+       status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 4, setParamParameters, 1, &cmdResult);
+       if (status < 0) {
+               /* Fall-back to the simpler call */
+               if (state->m_OperationMode == OM_QAM_ITU_C)
+                       setParamParameters[0] = QAM_TOP_ANNEX_C;
+               else
+                       setParamParameters[0] = QAM_TOP_ANNEX_A;
+               status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 1, setParamParameters, 1, &cmdResult);
+               if (status < 0)
+                       goto error;
+
+               setParamParameters[0] = state->m_Constellation; /* constellation     */
+               setParamParameters[1] = DRXK_QAM_I12_J17;       /* interleave mode   */
+               status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 2, setParamParameters, 1, &cmdResult);
+       }
+       if (status < 0)
+               goto error;
+
+       /*
+        * STEP 3: enable the system in a mode where the ADC provides valid
+        * signal setup constellation independent registers
+        */
+#if 0
+       status = SetFrequency(channel, tunerFreqOffset));
+       if (status < 0)
+               goto error;
+#endif
+       status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true);
+       if (status < 0)
+               goto error;
+
+       /* Setup BER measurement */
+       status = SetQAMMeasurement(state, state->m_Constellation, state->param.u. qam.symbol_rate);
+       if (status < 0)
+               goto error;
+
+       /* Reset default values */
+       status = write16(state, IQM_CF_SCALE_SH__A, IQM_CF_SCALE_SH__PRE);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_SY_TIMEOUT__A, QAM_SY_TIMEOUT__PRE);
+       if (status < 0)
+               goto error;
+
+       /* Reset default LC values */
+       status = write16(state, QAM_LC_RATE_LIMIT__A, 3);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_LPF_FACTORP__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_LPF_FACTORI__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_MODE__A, 7);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, QAM_LC_QUAL_TAB0__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB1__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB2__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB3__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB4__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB5__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB6__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB8__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB9__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB10__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB12__A, 2);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB15__A, 3);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB16__A, 3);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB20__A, 4);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_LC_QUAL_TAB25__A, 4);
+       if (status < 0)
+               goto error;
+
+       /* Mirroring, QAM-block starting point not inverted */
+       status = write16(state, QAM_SY_SP_INV__A, QAM_SY_SP_INV_SPECTRUM_INV_DIS);
+       if (status < 0)
+               goto error;
+
+       /* Halt SCU to enable safe non-atomic accesses */
+       status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
+       if (status < 0)
+               goto error;
+
+       /* STEP 4: constellation specific setup */
+       switch (state->param.u.qam.modulation) {
+       case QAM_16:
+               status = SetQAM16(state);
+               break;
+       case QAM_32:
+               status = SetQAM32(state);
+               break;
+       case QAM_AUTO:
+       case QAM_64:
+               status = SetQAM64(state);
+               break;
+       case QAM_128:
+               status = SetQAM128(state);
+               break;
+       case QAM_256:
+               status = SetQAM256(state);
+               break;
+       default:
+               status = -EINVAL;
+               break;
+       }
+       if (status < 0)
+               goto error;
+
+       /* Activate SCU to enable SCU commands */
+       status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
+       if (status < 0)
+               goto error;
+
+       /* Re-configure MPEG output, requires knowledge of channel bitrate */
+       /* extAttr->currentChannel.constellation = channel->constellation; */
+       /* extAttr->currentChannel.symbolrate    = channel->symbolrate; */
+       status = MPEGTSDtoSetup(state, state->m_OperationMode);
+       if (status < 0)
+               goto error;
+
+       /* Start processes */
+       status = MPEGTSStart(state);
+       if (status < 0)
+               goto error;
+       status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE);
+       if (status < 0)
+               goto error;
+       status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_ACTIVE);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_ACTIVE);
+       if (status < 0)
+               goto error;
+
+       /* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */
+       status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult);
+       if (status < 0)
+               goto error;
+
+       /* update global DRXK data container */
+/*?     extAttr->qamInterleaveMode = DRXK_QAM_I12_J17; */
+
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int SetQAMStandard(struct drxk_state *state,
+                         enum OperationMode oMode)
+{
+       int status;
+#ifdef DRXK_QAM_TAPS
+#define DRXK_QAMA_TAPS_SELECT
+#include "drxk_filters.h"
+#undef DRXK_QAMA_TAPS_SELECT
+#endif
+
+       dprintk(1, "\n");
+
+       /* added antenna switch */
+       SwitchAntennaToQAM(state);
+
+       /* Ensure correct power-up mode */
+       status = PowerUpQAM(state);
+       if (status < 0)
+               goto error;
+       /* Reset QAM block */
+       status = QAMResetQAM(state);
+       if (status < 0)
+               goto error;
+
+       /* Setup IQM */
+
+       status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC);
+       if (status < 0)
+               goto error;
+
+       /* Upload IQM Channel Filter settings by
+               boot loader from ROM table */
+       switch (oMode) {
+       case OM_QAM_ITU_A:
+               status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
+               break;
+       case OM_QAM_ITU_C:
+               status = BLDirectCmd(state, IQM_CF_TAP_RE0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
+               if (status < 0)
+                       goto error;
+               status = BLDirectCmd(state, IQM_CF_TAP_IM0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
+               break;
+       default:
+               status = -EINVAL;
+       }
+       if (status < 0)
+               goto error;
+
+       status = write16(state, IQM_CF_OUT_ENA__A, (1 << IQM_CF_OUT_ENA_QAM__B));
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_SYMMETRIC__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_MIDTAP__A, ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B)));
+       if (status < 0)
+               goto error;
+
+       status = write16(state, IQM_RC_STRETCH__A, 21);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_AF_CLP_LEN__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_AF_CLP_TH__A, 448);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_AF_SNS_LEN__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_POW_MEAS_LEN__A, 0);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, IQM_FS_ADJ_SEL__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_RC_ADJ_SEL__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_ADJ_SEL__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_AF_UPD_SEL__A, 0);
+       if (status < 0)
+               goto error;
+
+       /* IQM Impulse Noise Processing Unit */
+       status = write16(state, IQM_CF_CLP_VAL__A, 500);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_DATATH__A, 1000);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_BYPASSDET__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_DET_LCT__A, 0);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_WND_LEN__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_CF_PKDTH__A, 1);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_AF_INC_BYPASS__A, 1);
+       if (status < 0)
+               goto error;
+
+       /* turn on IQMAF. Must be done before setAgc**() */
+       status = SetIqmAf(state, true);
+       if (status < 0)
+               goto error;
+       status = write16(state, IQM_AF_START_LOCK__A, 0x01);
+       if (status < 0)
+               goto error;
+
+       /* IQM will not be reset from here, sync ADC and update/init AGC */
+       status = ADCSynchronization(state);
+       if (status < 0)
+               goto error;
+
+       /* Set the FSM step period */
+       status = write16(state, SCU_RAM_QAM_FSM_STEP_PERIOD__A, 2000);
+       if (status < 0)
+               goto error;
+
+       /* Halt SCU to enable safe non-atomic accesses */
+       status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
+       if (status < 0)
+               goto error;
+
+       /* No more resets of the IQM, current standard correctly set =>
+               now AGCs can be configured. */
+
+       status = InitAGC(state, true);
+       if (status < 0)
+               goto error;
+       status = SetPreSaw(state, &(state->m_qamPreSawCfg));
+       if (status < 0)
+               goto error;
+
+       /* Configure AGC's */
+       status = SetAgcRf(state, &(state->m_qamRfAgcCfg), true);
+       if (status < 0)
+               goto error;
+       status = SetAgcIf(state, &(state->m_qamIfAgcCfg), true);
+       if (status < 0)
+               goto error;
+
+       /* Activate SCU to enable SCU commands */
+       status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int WriteGPIO(struct drxk_state *state)
+{
+       int status;
+       u16 value = 0;
+
+       dprintk(1, "\n");
+       /* stop lock indicator process */
+       status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
+       if (status < 0)
+               goto error;
+
+       /*  Write magic word to enable pdr reg write               */
+       status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
+       if (status < 0)
+               goto error;
+
+       if (state->m_hasSAWSW) {
+               if (state->UIO_mask & 0x0001) { /* UIO-1 */
+                       /* write to io pad configuration register - output mode */
+                       status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg);
+                       if (status < 0)
+                               goto error;
+
+                       /* use corresponding bit in io data output registar */
+                       status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
+                       if (status < 0)
+                               goto error;
+                       if ((state->m_GPIO & 0x0001) == 0)
+                               value &= 0x7FFF;        /* write zero to 15th bit - 1st UIO */
+                       else
+                               value |= 0x8000;        /* write one to 15th bit - 1st UIO */
+                       /* write back to io data output register */
+                       status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
+                       if (status < 0)
+                               goto error;
+               }
+               if (state->UIO_mask & 0x0002) { /* UIO-2 */
+                       /* write to io pad configuration register - output mode */
+                       status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg);
+                       if (status < 0)
+                               goto error;
+
+                       /* use corresponding bit in io data output registar */
+                       status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
+                       if (status < 0)
+                               goto error;
+                       if ((state->m_GPIO & 0x0002) == 0)
+                               value &= 0xBFFF;        /* write zero to 14th bit - 2st UIO */
+                       else
+                               value |= 0x4000;        /* write one to 14th bit - 2st UIO */
+                       /* write back to io data output register */
+                       status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
+                       if (status < 0)
+                               goto error;
+               }
+               if (state->UIO_mask & 0x0004) { /* UIO-3 */
+                       /* write to io pad configuration register - output mode */
+                       status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg);
+                       if (status < 0)
+                               goto error;
+
+                       /* use corresponding bit in io data output registar */
+                       status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
+                       if (status < 0)
+                               goto error;
+                       if ((state->m_GPIO & 0x0004) == 0)
+                               value &= 0xFFFB;            /* write zero to 2nd bit - 3rd UIO */
+                       else
+                               value |= 0x0004;            /* write one to 2nd bit - 3rd UIO */
+                       /* write back to io data output register */
+                       status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
+                       if (status < 0)
+                               goto error;
+               }
+       }
+       /*  Write magic word to disable pdr reg write               */
+       status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int SwitchAntennaToQAM(struct drxk_state *state)
+{
+       int status = 0;
+       bool gpio_state;
+
+       dprintk(1, "\n");
+
+       if (!state->antenna_gpio)
+               return 0;
+
+       gpio_state = state->m_GPIO & state->antenna_gpio;
+
+       if (state->antenna_dvbt ^ gpio_state) {
+               /* Antenna is on DVB-T mode. Switch */
+               if (state->antenna_dvbt)
+                       state->m_GPIO &= ~state->antenna_gpio;
+               else
+                       state->m_GPIO |= state->antenna_gpio;
+               status = WriteGPIO(state);
+       }
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+static int SwitchAntennaToDVBT(struct drxk_state *state)
+{
+       int status = 0;
+       bool gpio_state;
+
+       dprintk(1, "\n");
+
+       if (!state->antenna_gpio)
+               return 0;
+
+       gpio_state = state->m_GPIO & state->antenna_gpio;
+
+       if (!(state->antenna_dvbt ^ gpio_state)) {
+               /* Antenna is on DVB-C mode. Switch */
+               if (state->antenna_dvbt)
+                       state->m_GPIO |= state->antenna_gpio;
+               else
+                       state->m_GPIO &= ~state->antenna_gpio;
+               status = WriteGPIO(state);
+       }
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+       return status;
+}
+
+
+static int PowerDownDevice(struct drxk_state *state)
+{
+       /* Power down to requested mode */
+       /* Backup some register settings */
+       /* Set pins with possible pull-ups connected to them in input mode */
+       /* Analog power down */
+       /* ADC power down */
+       /* Power down device */
+       int status;
+
+       dprintk(1, "\n");
+       if (state->m_bPDownOpenBridge) {
+               /* Open I2C bridge before power down of DRXK */
+               status = ConfigureI2CBridge(state, true);
+               if (status < 0)
+                       goto error;
+       }
+       /* driver 0.9.0 */
+       status = DVBTEnableOFDMTokenRing(state, false);
+       if (status < 0)
+               goto error;
+
+       status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_CLOCK);
+       if (status < 0)
+               goto error;
+       status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
+       if (status < 0)
+               goto error;
+       state->m_HICfgCtrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
+       status = HI_CfgCommand(state);
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+static int load_microcode(struct drxk_state *state, const char *mc_name)
+{
+       const struct firmware *fw = NULL;
+       int err = 0;
+
+       dprintk(1, "\n");
+
+       err = request_firmware(&fw, mc_name, state->i2c->dev.parent);
+       if (err < 0) {
+               printk(KERN_ERR
+                      "drxk: Could not load firmware file %s.\n", mc_name);
+               printk(KERN_INFO
+                      "drxk: Copy %s to your hotplug directory!\n", mc_name);
+               return err;
+       }
+       err = DownloadMicrocode(state, fw->data, fw->size);
+       release_firmware(fw);
+       return err;
+}
+
+static int init_drxk(struct drxk_state *state)
+{
+       int status = 0;
+       enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
+       u16 driverVersion;
+
+       dprintk(1, "\n");
+       if ((state->m_DrxkState == DRXK_UNINITIALIZED)) {
+               status = PowerUpDevice(state);
+               if (status < 0)
+                       goto error;
+               status = DRXX_Open(state);
+               if (status < 0)
+                       goto error;
+               /* Soft reset of OFDM-, sys- and osc-clockdomain */
+               status = write16(state, SIO_CC_SOFT_RST__A, SIO_CC_SOFT_RST_OFDM__M | SIO_CC_SOFT_RST_SYS__M | SIO_CC_SOFT_RST_OSC__M);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
+               if (status < 0)
+                       goto error;
+               /* TODO is this needed, if yes how much delay in worst case scenario */
+               msleep(1);
+               state->m_DRXK_A3_PATCH_CODE = true;
+               status = GetDeviceCapabilities(state);
+               if (status < 0)
+                       goto error;
+
+               /* Bridge delay, uses oscilator clock */
+               /* Delay = (delay (nano seconds) * oscclk (kHz))/ 1000 */
+               /* SDA brdige delay */
+               state->m_HICfgBridgeDelay =
+                       (u16) ((state->m_oscClockFreq / 1000) *
+                               HI_I2C_BRIDGE_DELAY) / 1000;
+               /* Clipping */
+               if (state->m_HICfgBridgeDelay >
+                       SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M) {
+                       state->m_HICfgBridgeDelay =
+                               SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M;
+               }
+               /* SCL bridge delay, same as SDA for now */
+               state->m_HICfgBridgeDelay +=
+                       state->m_HICfgBridgeDelay <<
+                       SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B;
+
+               status = InitHI(state);
+               if (status < 0)
+                       goto error;
+               /* disable various processes */
+#if NOA1ROM
+               if (!(state->m_DRXK_A1_ROM_CODE)
+                       && !(state->m_DRXK_A2_ROM_CODE))
+#endif
+               {
+                       status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
+                       if (status < 0)
+                               goto error;
+               }
+
+               /* disable MPEG port */
+               status = MPEGTSDisable(state);
+               if (status < 0)
+                       goto error;
+
+               /* Stop AUD and SCU */
+               status = write16(state, AUD_COMM_EXEC__A, AUD_COMM_EXEC_STOP);
+               if (status < 0)
+                       goto error;
+               status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_STOP);
+               if (status < 0)
+                       goto error;
+
+               /* enable token-ring bus through OFDM block for possible ucode upload */
+               status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_ON);
+               if (status < 0)
+                       goto error;
+
+               /* include boot loader section */
+               status = write16(state, SIO_BL_COMM_EXEC__A, SIO_BL_COMM_EXEC_ACTIVE);
+               if (status < 0)
+                       goto error;
+               status = BLChainCmd(state, 0, 6, 100);
+               if (status < 0)
+                       goto error;
+
+               if (!state->microcode_name)
+                       load_microcode(state, "drxk_a3.mc");
+               else
+                       load_microcode(state, state->microcode_name);
+
+               /* disable token-ring bus through OFDM block for possible ucode upload */
+               status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF);
+               if (status < 0)
+                       goto error;
+
+               /* Run SCU for a little while to initialize microcode version numbers */
+               status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
+               if (status < 0)
+                       goto error;
+               status = DRXX_Open(state);
+               if (status < 0)
+                       goto error;
+               /* added for test */
+               msleep(30);
+
+               powerMode = DRXK_POWER_DOWN_OFDM;
+               status = CtrlPowerMode(state, &powerMode);
+               if (status < 0)
+                       goto error;
+
+               /* Stamp driver version number in SCU data RAM in BCD code
+                       Done to enable field application engineers to retreive drxdriver version
+                       via I2C from SCU RAM.
+                       Not using SCU command interface for SCU register access since no
+                       microcode may be present.
+                       */
+               driverVersion =
+                       (((DRXK_VERSION_MAJOR / 100) % 10) << 12) +
+                       (((DRXK_VERSION_MAJOR / 10) % 10) << 8) +
+                       ((DRXK_VERSION_MAJOR % 10) << 4) +
+                       (DRXK_VERSION_MINOR % 10);
+               status = write16(state, SCU_RAM_DRIVER_VER_HI__A, driverVersion);
+               if (status < 0)
+                       goto error;
+               driverVersion =
+                       (((DRXK_VERSION_PATCH / 1000) % 10) << 12) +
+                       (((DRXK_VERSION_PATCH / 100) % 10) << 8) +
+                       (((DRXK_VERSION_PATCH / 10) % 10) << 4) +
+                       (DRXK_VERSION_PATCH % 10);
+               status = write16(state, SCU_RAM_DRIVER_VER_LO__A, driverVersion);
+               if (status < 0)
+                       goto error;
+
+               printk(KERN_INFO "DRXK driver version %d.%d.%d\n",
+                       DRXK_VERSION_MAJOR, DRXK_VERSION_MINOR,
+                       DRXK_VERSION_PATCH);
+
+               /* Dirty fix of default values for ROM/PATCH microcode
+                       Dirty because this fix makes it impossible to setup suitable values
+                       before calling DRX_Open. This solution requires changes to RF AGC speed
+                       to be done via the CTRL function after calling DRX_Open */
+
+               /* m_dvbtRfAgcCfg.speed = 3; */
+
+               /* Reset driver debug flags to 0 */
+               status = write16(state, SCU_RAM_DRIVER_DEBUG__A, 0);
+               if (status < 0)
+                       goto error;
+               /* driver 0.9.0 */
+               /* Setup FEC OC:
+                       NOTE: No more full FEC resets allowed afterwards!! */
+               status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP);
+               if (status < 0)
+                       goto error;
+               /* MPEGTS functions are still the same */
+               status = MPEGTSDtoInit(state);
+               if (status < 0)
+                       goto error;
+               status = MPEGTSStop(state);
+               if (status < 0)
+                       goto error;
+               status = MPEGTSConfigurePolarity(state);
+               if (status < 0)
+                       goto error;
+               status = MPEGTSConfigurePins(state, state->m_enableMPEGOutput);
+               if (status < 0)
+                       goto error;
+               /* added: configure GPIO */
+               status = WriteGPIO(state);
+               if (status < 0)
+                       goto error;
+
+               state->m_DrxkState = DRXK_STOPPED;
+
+               if (state->m_bPowerDown) {
+                       status = PowerDownDevice(state);
+                       if (status < 0)
+                               goto error;
+                       state->m_DrxkState = DRXK_POWERED_DOWN;
+               } else
+                       state->m_DrxkState = DRXK_STOPPED;
+       }
+error:
+       if (status < 0)
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+       return status;
+}
+
+static void drxk_c_release(struct dvb_frontend *fe)
+{
+       struct drxk_state *state = fe->demodulator_priv;
+
+       dprintk(1, "\n");
+       kfree(state);
+}
+
+static int drxk_c_init(struct dvb_frontend *fe)
+{
+       struct drxk_state *state = fe->demodulator_priv;
+
+       dprintk(1, "\n");
+       if (mutex_trylock(&state->ctlock) == 0)
+               return -EBUSY;
+       SetOperationMode(state, OM_QAM_ITU_A);
+       return 0;
+}
+
+static int drxk_c_sleep(struct dvb_frontend *fe)
+{
+       struct drxk_state *state = fe->demodulator_priv;
+
+       dprintk(1, "\n");
+       ShutDown(state);
+       mutex_unlock(&state->ctlock);
+       return 0;
+}
+
+static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct drxk_state *state = fe->demodulator_priv;
+
+       dprintk(1, "%s\n", enable ? "enable" : "disable");
+       return ConfigureI2CBridge(state, enable ? true : false);
+}
+
+static int drxk_set_parameters(struct dvb_frontend *fe,
+                              struct dvb_frontend_parameters *p)
+{
+       struct drxk_state *state = fe->demodulator_priv;
+       u32 IF;
+
+       dprintk(1, "\n");
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (fe->ops.tuner_ops.set_params)
+               fe->ops.tuner_ops.set_params(fe, p);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+       state->param = *p;
+       fe->ops.tuner_ops.get_frequency(fe, &IF);
+       Start(state, 0, IF);
+
+       /* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */
+
+       return 0;
+}
+
+static int drxk_c_get_frontend(struct dvb_frontend *fe,
+                              struct dvb_frontend_parameters *p)
+{
+       dprintk(1, "\n");
+       return 0;
+}
+
+static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct drxk_state *state = fe->demodulator_priv;
+       u32 stat;
+
+       dprintk(1, "\n");
+       *status = 0;
+       GetLockStatus(state, &stat, 0);
+       if (stat == MPEG_LOCK)
+               *status |= 0x1f;
+       if (stat == FEC_LOCK)
+               *status |= 0x0f;
+       if (stat == DEMOD_LOCK)
+               *status |= 0x07;
+       return 0;
+}
+
+static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       dprintk(1, "\n");
+
+       *ber = 0;
+       return 0;
+}
+
+static int drxk_read_signal_strength(struct dvb_frontend *fe,
+                                    u16 *strength)
+{
+       struct drxk_state *state = fe->demodulator_priv;
+       u32 val = 0;
+
+       dprintk(1, "\n");
+       ReadIFAgc(state, &val);
+       *strength = val & 0xffff;
+       return 0;
+}
+
+static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct drxk_state *state = fe->demodulator_priv;
+       s32 snr2;
+
+       dprintk(1, "\n");
+       GetSignalToNoise(state, &snr2);
+       *snr = snr2 & 0xffff;
+       return 0;
+}
+
+static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct drxk_state *state = fe->demodulator_priv;
+       u16 err;
+
+       dprintk(1, "\n");
+       DVBTQAMGetAccPktErr(state, &err);
+       *ucblocks = (u32) err;
+       return 0;
+}
+
+static int drxk_c_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings
+                                   *sets)
+{
+       dprintk(1, "\n");
+       sets->min_delay_ms = 3000;
+       sets->max_drift = 0;
+       sets->step_size = 0;
+       return 0;
+}
+
+static void drxk_t_release(struct dvb_frontend *fe)
+{
+       /*
+        * There's nothing to release here, as the state struct
+        * is already freed by drxk_c_release.
+        */
+}
+
+static int drxk_t_init(struct dvb_frontend *fe)
+{
+       struct drxk_state *state = fe->demodulator_priv;
+
+       dprintk(1, "\n");
+       if (mutex_trylock(&state->ctlock) == 0)
+               return -EBUSY;
+       SetOperationMode(state, OM_DVBT);
+       return 0;
+}
+
+static int drxk_t_sleep(struct dvb_frontend *fe)
+{
+       struct drxk_state *state = fe->demodulator_priv;
+
+       dprintk(1, "\n");
+       mutex_unlock(&state->ctlock);
+       return 0;
+}
+
+static int drxk_t_get_frontend(struct dvb_frontend *fe,
+                              struct dvb_frontend_parameters *p)
+{
+       dprintk(1, "\n");
+
+       return 0;
+}
+
+static struct dvb_frontend_ops drxk_c_ops = {
+       .info = {
+                .name = "DRXK DVB-C",
+                .type = FE_QAM,
+                .frequency_stepsize = 62500,
+                .frequency_min = 47000000,
+                .frequency_max = 862000000,
+                .symbol_rate_min = 870000,
+                .symbol_rate_max = 11700000,
+                .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+                FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO},
+       .release = drxk_c_release,
+       .init = drxk_c_init,
+       .sleep = drxk_c_sleep,
+       .i2c_gate_ctrl = drxk_gate_ctrl,
+
+       .set_frontend = drxk_set_parameters,
+       .get_frontend = drxk_c_get_frontend,
+       .get_tune_settings = drxk_c_get_tune_settings,
+
+       .read_status = drxk_read_status,
+       .read_ber = drxk_read_ber,
+       .read_signal_strength = drxk_read_signal_strength,
+       .read_snr = drxk_read_snr,
+       .read_ucblocks = drxk_read_ucblocks,
+};
+
+static struct dvb_frontend_ops drxk_t_ops = {
+       .info = {
+                .name = "DRXK DVB-T",
+                .type = FE_OFDM,
+                .frequency_min = 47125000,
+                .frequency_max = 865000000,
+                .frequency_stepsize = 166667,
+                .frequency_tolerance = 0,
+                .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+                FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
+                FE_CAN_FEC_AUTO |
+                FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+                FE_CAN_QAM_AUTO |
+                FE_CAN_TRANSMISSION_MODE_AUTO |
+                FE_CAN_GUARD_INTERVAL_AUTO |
+                FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS},
+       .release = drxk_t_release,
+       .init = drxk_t_init,
+       .sleep = drxk_t_sleep,
+       .i2c_gate_ctrl = drxk_gate_ctrl,
+
+       .set_frontend = drxk_set_parameters,
+       .get_frontend = drxk_t_get_frontend,
+
+       .read_status = drxk_read_status,
+       .read_ber = drxk_read_ber,
+       .read_signal_strength = drxk_read_signal_strength,
+       .read_snr = drxk_read_snr,
+       .read_ucblocks = drxk_read_ucblocks,
+};
+
+struct dvb_frontend *drxk_attach(const struct drxk_config *config,
+                                struct i2c_adapter *i2c,
+                                struct dvb_frontend **fe_t)
+{
+       struct drxk_state *state = NULL;
+       u8 adr = config->adr;
+
+       dprintk(1, "\n");
+       state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL);
+       if (!state)
+               return NULL;
+
+       state->i2c = i2c;
+       state->demod_address = adr;
+       state->single_master = config->single_master;
+       state->microcode_name = config->microcode_name;
+       state->no_i2c_bridge = config->no_i2c_bridge;
+       state->antenna_gpio = config->antenna_gpio;
+       state->antenna_dvbt = config->antenna_dvbt;
+
+       /* NOTE: as more UIO bits will be used, add them to the mask */
+       state->UIO_mask = config->antenna_gpio;
+
+       /* Default gpio to DVB-C */
+       if (!state->antenna_dvbt && state->antenna_gpio)
+               state->m_GPIO |= state->antenna_gpio;
+       else
+               state->m_GPIO &= ~state->antenna_gpio;
+
+       mutex_init(&state->mutex);
+       mutex_init(&state->ctlock);
+
+       memcpy(&state->c_frontend.ops, &drxk_c_ops,
+              sizeof(struct dvb_frontend_ops));
+       memcpy(&state->t_frontend.ops, &drxk_t_ops,
+              sizeof(struct dvb_frontend_ops));
+       state->c_frontend.demodulator_priv = state;
+       state->t_frontend.demodulator_priv = state;
+
+       init_state(state);
+       if (init_drxk(state) < 0)
+               goto error;
+       *fe_t = &state->t_frontend;
+
+       return &state->c_frontend;
+
+error:
+       printk(KERN_ERR "drxk: not found\n");
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL(drxk_attach);
+
+MODULE_DESCRIPTION("DRX-K driver");
+MODULE_AUTHOR("Ralph Metzler");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/drxk_hard.h b/drivers/media/dvb/frontends/drxk_hard.h
new file mode 100644 (file)
index 0000000..a05c32e
--- /dev/null
@@ -0,0 +1,348 @@
+#include "drxk_map.h"
+
+#define DRXK_VERSION_MAJOR 0
+#define DRXK_VERSION_MINOR 9
+#define DRXK_VERSION_PATCH 4300
+
+#define HI_I2C_DELAY        42
+#define HI_I2C_BRIDGE_DELAY 350
+#define DRXK_MAX_RETRIES    100
+
+#define DRIVER_4400 1
+
+#define DRXX_JTAGID   0x039210D9
+#define DRXX_J_JTAGID 0x239310D9
+#define DRXX_K_JTAGID 0x039210D9
+
+#define DRX_UNKNOWN     254
+#define DRX_AUTO        255
+
+#define DRX_SCU_READY   0
+#define DRXK_MAX_WAITTIME (200)
+#define SCU_RESULT_OK      0
+#define SCU_RESULT_SIZE   -4
+#define SCU_RESULT_INVPAR -3
+#define SCU_RESULT_UNKSTD -2
+#define SCU_RESULT_UNKCMD -1
+
+#ifndef DRXK_OFDM_TR_SHUTDOWN_TIMEOUT
+#define DRXK_OFDM_TR_SHUTDOWN_TIMEOUT (200)
+#endif
+
+#define DRXK_8VSB_MPEG_BIT_RATE     19392658UL  /*bps*/
+#define DRXK_DVBT_MPEG_BIT_RATE     32000000UL  /*bps*/
+#define DRXK_QAM16_MPEG_BIT_RATE    27000000UL  /*bps*/
+#define DRXK_QAM32_MPEG_BIT_RATE    33000000UL  /*bps*/
+#define DRXK_QAM64_MPEG_BIT_RATE    40000000UL  /*bps*/
+#define DRXK_QAM128_MPEG_BIT_RATE   46000000UL  /*bps*/
+#define DRXK_QAM256_MPEG_BIT_RATE   52000000UL  /*bps*/
+#define DRXK_MAX_MPEG_BIT_RATE      52000000UL  /*bps*/
+
+#define   IQM_CF_OUT_ENA_OFDM__M                                            0x4
+#define     IQM_FS_ADJ_SEL_B_QAM                                            0x1
+#define     IQM_FS_ADJ_SEL_B_OFF                                            0x0
+#define     IQM_FS_ADJ_SEL_B_VSB                                            0x2
+#define     IQM_RC_ADJ_SEL_B_OFF                                            0x0
+#define     IQM_RC_ADJ_SEL_B_QAM                                            0x1
+#define     IQM_RC_ADJ_SEL_B_VSB                                            0x2
+
+enum OperationMode {
+       OM_NONE,
+       OM_QAM_ITU_A,
+       OM_QAM_ITU_B,
+       OM_QAM_ITU_C,
+       OM_DVBT
+};
+
+enum DRXPowerMode {
+       DRX_POWER_UP = 0,
+       DRX_POWER_MODE_1,
+       DRX_POWER_MODE_2,
+       DRX_POWER_MODE_3,
+       DRX_POWER_MODE_4,
+       DRX_POWER_MODE_5,
+       DRX_POWER_MODE_6,
+       DRX_POWER_MODE_7,
+       DRX_POWER_MODE_8,
+
+       DRX_POWER_MODE_9,
+       DRX_POWER_MODE_10,
+       DRX_POWER_MODE_11,
+       DRX_POWER_MODE_12,
+       DRX_POWER_MODE_13,
+       DRX_POWER_MODE_14,
+       DRX_POWER_MODE_15,
+       DRX_POWER_MODE_16,
+       DRX_POWER_DOWN = 255
+};
+
+
+/** /brief Intermediate power mode for DRXK, power down OFDM clock domain */
+#ifndef DRXK_POWER_DOWN_OFDM
+#define DRXK_POWER_DOWN_OFDM        DRX_POWER_MODE_1
+#endif
+
+/** /brief Intermediate power mode for DRXK, power down core (sysclk) */
+#ifndef DRXK_POWER_DOWN_CORE
+#define DRXK_POWER_DOWN_CORE        DRX_POWER_MODE_9
+#endif
+
+/** /brief Intermediate power mode for DRXK, power down pll (only osc runs) */
+#ifndef DRXK_POWER_DOWN_PLL
+#define DRXK_POWER_DOWN_PLL         DRX_POWER_MODE_10
+#endif
+
+
+enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF };
+enum EDrxkState { DRXK_UNINITIALIZED = 0, DRXK_STOPPED, DRXK_DTV_STARTED, DRXK_ATV_STARTED, DRXK_POWERED_DOWN };
+enum EDrxkCoefArrayIndex {
+       DRXK_COEF_IDX_MN = 0,
+       DRXK_COEF_IDX_FM    ,
+       DRXK_COEF_IDX_L     ,
+       DRXK_COEF_IDX_LP    ,
+       DRXK_COEF_IDX_BG    ,
+       DRXK_COEF_IDX_DK    ,
+       DRXK_COEF_IDX_I     ,
+       DRXK_COEF_IDX_MAX
+};
+enum EDrxkSifAttenuation {
+       DRXK_SIF_ATTENUATION_0DB,
+       DRXK_SIF_ATTENUATION_3DB,
+       DRXK_SIF_ATTENUATION_6DB,
+       DRXK_SIF_ATTENUATION_9DB
+};
+enum EDrxkConstellation {
+       DRX_CONSTELLATION_BPSK = 0,
+       DRX_CONSTELLATION_QPSK,
+       DRX_CONSTELLATION_PSK8,
+       DRX_CONSTELLATION_QAM16,
+       DRX_CONSTELLATION_QAM32,
+       DRX_CONSTELLATION_QAM64,
+       DRX_CONSTELLATION_QAM128,
+       DRX_CONSTELLATION_QAM256,
+       DRX_CONSTELLATION_QAM512,
+       DRX_CONSTELLATION_QAM1024,
+       DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN,
+       DRX_CONSTELLATION_AUTO    = DRX_AUTO
+};
+enum EDrxkInterleaveMode {
+       DRXK_QAM_I12_J17    = 16,
+       DRXK_QAM_I_UNKNOWN  = DRX_UNKNOWN
+};
+enum {
+       DRXK_SPIN_A1 = 0,
+       DRXK_SPIN_A2,
+       DRXK_SPIN_A3,
+       DRXK_SPIN_UNKNOWN
+};
+
+enum DRXKCfgDvbtSqiSpeed {
+       DRXK_DVBT_SQI_SPEED_FAST = 0,
+       DRXK_DVBT_SQI_SPEED_MEDIUM,
+       DRXK_DVBT_SQI_SPEED_SLOW,
+       DRXK_DVBT_SQI_SPEED_UNKNOWN = DRX_UNKNOWN
+} ;
+
+enum DRXFftmode_t {
+       DRX_FFTMODE_2K = 0,
+       DRX_FFTMODE_4K,
+       DRX_FFTMODE_8K,
+       DRX_FFTMODE_UNKNOWN = DRX_UNKNOWN,
+       DRX_FFTMODE_AUTO    = DRX_AUTO
+};
+
+enum DRXMPEGStrWidth_t {
+       DRX_MPEG_STR_WIDTH_1,
+       DRX_MPEG_STR_WIDTH_8
+};
+
+enum DRXQamLockRange_t {
+       DRX_QAM_LOCKRANGE_NORMAL,
+       DRX_QAM_LOCKRANGE_EXTENDED
+};
+
+struct DRXKCfgDvbtEchoThres_t {
+       u16             threshold;
+       enum DRXFftmode_t      fftMode;
+} ;
+
+struct SCfgAgc {
+       enum AGC_CTRL_MODE     ctrlMode;        /* off, user, auto */
+       u16            outputLevel;     /* range dependent on AGC */
+       u16            minOutputLevel;  /* range dependent on AGC */
+       u16            maxOutputLevel;  /* range dependent on AGC */
+       u16            speed;           /* range dependent on AGC */
+       u16            top;             /* rf-agc take over point */
+       u16            cutOffCurrent;   /* rf-agc is accelerated if output current
+                                          is below cut-off current */
+       u16            IngainTgtMax;
+       u16            FastClipCtrlDelay;
+};
+
+struct SCfgPreSaw {
+       u16        reference; /* pre SAW reference value, range 0 .. 31 */
+       bool          usePreSaw; /* TRUE algorithms must use pre SAW sense */
+};
+
+struct DRXKOfdmScCmd_t {
+       u16 cmd;        /**< Command number */
+       u16 subcmd;     /**< Sub-command parameter*/
+       u16 param0;     /**< General purpous param */
+       u16 param1;     /**< General purpous param */
+       u16 param2;     /**< General purpous param */
+       u16 param3;     /**< General purpous param */
+       u16 param4;     /**< General purpous param */
+};
+
+struct drxk_state {
+       struct dvb_frontend c_frontend;
+       struct dvb_frontend t_frontend;
+       struct dvb_frontend_parameters param;
+       struct device *dev;
+
+       struct i2c_adapter *i2c;
+       u8     demod_address;
+       void  *priv;
+
+       struct mutex mutex;
+       struct mutex ctlock;
+
+       u32    m_Instance;           /**< Channel 1,2,3 or 4 */
+
+       int    m_ChunkSize;
+       u8 Chunk[256];
+
+       bool   m_hasLNA;
+       bool   m_hasDVBT;
+       bool   m_hasDVBC;
+       bool   m_hasAudio;
+       bool   m_hasATV;
+       bool   m_hasOOB;
+       bool   m_hasSAWSW;         /**< TRUE if mat_tx is available */
+       bool   m_hasGPIO1;         /**< TRUE if mat_rx is available */
+       bool   m_hasGPIO2;         /**< TRUE if GPIO is available */
+       bool   m_hasIRQN;          /**< TRUE if IRQN is available */
+       u16    m_oscClockFreq;
+       u16    m_HICfgTimingDiv;
+       u16    m_HICfgBridgeDelay;
+       u16    m_HICfgWakeUpKey;
+       u16    m_HICfgTimeout;
+       u16    m_HICfgCtrl;
+       s32    m_sysClockFreq;      /**< system clock frequency in kHz */
+
+       enum EDrxkState    m_DrxkState;      /**< State of Drxk (init,stopped,started) */
+       enum OperationMode m_OperationMode;  /**< digital standards */
+       struct SCfgAgc     m_vsbRfAgcCfg;    /**< settings for VSB RF-AGC */
+       struct SCfgAgc     m_vsbIfAgcCfg;    /**< settings for VSB IF-AGC */
+       u16                m_vsbPgaCfg;      /**< settings for VSB PGA */
+       struct SCfgPreSaw  m_vsbPreSawCfg;   /**< settings for pre SAW sense */
+       s32    m_Quality83percent;  /**< MER level (*0.1 dB) for 83% quality indication */
+       s32    m_Quality93percent;  /**< MER level (*0.1 dB) for 93% quality indication */
+       bool   m_smartAntInverted;
+       bool   m_bDebugEnableBridge;
+       bool   m_bPDownOpenBridge;  /**< only open DRXK bridge before power-down once it has been accessed */
+       bool   m_bPowerDown;        /**< Power down when not used */
+
+       u32    m_IqmFsRateOfs;      /**< frequency shift as written to DRXK register (28bit fixpoint) */
+
+       bool   m_enableMPEGOutput;  /**< If TRUE, enable MPEG output */
+       bool   m_insertRSByte;      /**< If TRUE, insert RS byte */
+       bool   m_enableParallel;    /**< If TRUE, parallel out otherwise serial */
+       bool   m_invertDATA;        /**< If TRUE, invert DATA signals */
+       bool   m_invertERR;         /**< If TRUE, invert ERR signal */
+       bool   m_invertSTR;         /**< If TRUE, invert STR signals */
+       bool   m_invertVAL;         /**< If TRUE, invert VAL signals */
+       bool   m_invertCLK;         /**< If TRUE, invert CLK signals */
+       bool   m_DVBCStaticCLK;
+       bool   m_DVBTStaticCLK;     /**< If TRUE, static MPEG clockrate will
+                                        be used, otherwise clockrate will
+                                        adapt to the bitrate of the TS */
+       u32    m_DVBTBitrate;
+       u32    m_DVBCBitrate;
+
+       u8     m_TSDataStrength;
+       u8     m_TSClockkStrength;
+
+       enum DRXMPEGStrWidth_t  m_widthSTR;    /**< MPEG start width */
+       u32    m_mpegTsStaticBitrate;          /**< Maximum bitrate in b/s in case
+                                                   static clockrate is selected */
+
+       /* LARGE_INTEGER   m_StartTime; */     /**< Contains the time of the last demod start */
+       s32    m_MpegLockTimeOut;      /**< WaitForLockStatus Timeout (counts from start time) */
+       s32    m_DemodLockTimeOut;     /**< WaitForLockStatus Timeout (counts from start time) */
+
+       bool   m_disableTEIhandling;
+
+       bool   m_RfAgcPol;
+       bool   m_IfAgcPol;
+
+       struct SCfgAgc    m_atvRfAgcCfg;  /**< settings for ATV RF-AGC */
+       struct SCfgAgc    m_atvIfAgcCfg;  /**< settings for ATV IF-AGC */
+       struct SCfgPreSaw m_atvPreSawCfg; /**< settings for ATV pre SAW sense */
+       bool              m_phaseCorrectionBypass;
+       s16               m_atvTopVidPeak;
+       u16               m_atvTopNoiseTh;
+       enum EDrxkSifAttenuation m_sifAttenuation;
+       bool              m_enableCVBSOutput;
+       bool              m_enableSIFOutput;
+       bool              m_bMirrorFreqSpect;
+       enum EDrxkConstellation  m_Constellation; /**< Constellation type of the channel */
+       u32               m_CurrSymbolRate;       /**< Current QAM symbol rate */
+       struct SCfgAgc    m_qamRfAgcCfg;          /**< settings for QAM RF-AGC */
+       struct SCfgAgc    m_qamIfAgcCfg;          /**< settings for QAM IF-AGC */
+       u16               m_qamPgaCfg;            /**< settings for QAM PGA */
+       struct SCfgPreSaw m_qamPreSawCfg;         /**< settings for QAM pre SAW sense */
+       enum EDrxkInterleaveMode m_qamInterleaveMode; /**< QAM Interleave mode */
+       u16               m_fecRsPlen;
+       u16               m_fecRsPrescale;
+
+       enum DRXKCfgDvbtSqiSpeed m_sqiSpeed;
+
+       u16               m_GPIO;
+       u16               m_GPIOCfg;
+
+       struct SCfgAgc    m_dvbtRfAgcCfg;     /**< settings for QAM RF-AGC */
+       struct SCfgAgc    m_dvbtIfAgcCfg;     /**< settings for QAM IF-AGC */
+       struct SCfgPreSaw m_dvbtPreSawCfg;    /**< settings for QAM pre SAW sense */
+
+       u16               m_agcFastClipCtrlDelay;
+       bool              m_adcCompPassed;
+       u16               m_adcCompCoef[64];
+       u16               m_adcState;
+
+       u8               *m_microcode;
+       int               m_microcode_length;
+       bool              m_DRXK_A1_PATCH_CODE;
+       bool              m_DRXK_A1_ROM_CODE;
+       bool              m_DRXK_A2_ROM_CODE;
+       bool              m_DRXK_A3_ROM_CODE;
+       bool              m_DRXK_A2_PATCH_CODE;
+       bool              m_DRXK_A3_PATCH_CODE;
+
+       bool              m_rfmirror;
+       u8                m_deviceSpin;
+       u32               m_iqmRcRate;
+
+       enum DRXPowerMode m_currentPowerMode;
+
+       /*
+        * Configurable parameters at the driver. They stores the values found
+        * at struct drxk_config.
+        */
+
+       u16     UIO_mask;       /* Bits used by UIO */
+
+       bool    single_master;
+       bool    no_i2c_bridge;
+       bool    antenna_dvbt;
+       u16     antenna_gpio;
+
+       const char *microcode_name;
+};
+
+#define NEVER_LOCK 0
+#define NOT_LOCKED 1
+#define DEMOD_LOCK 2
+#define FEC_LOCK   3
+#define MPEG_LOCK  4
+
diff --git a/drivers/media/dvb/frontends/drxk_map.h b/drivers/media/dvb/frontends/drxk_map.h
new file mode 100644 (file)
index 0000000..9b11a83
--- /dev/null
@@ -0,0 +1,449 @@
+#define  AUD_COMM_EXEC__A                                                  0x1000000
+#define    AUD_COMM_EXEC_STOP                                              0x0
+#define  FEC_COMM_EXEC__A                                                  0x1C00000
+#define    FEC_COMM_EXEC_STOP                                              0x0
+#define    FEC_COMM_EXEC_ACTIVE                                            0x1
+#define  FEC_DI_COMM_EXEC__A                                               0x1C20000
+#define    FEC_DI_COMM_EXEC_STOP                                           0x0
+#define  FEC_DI_INPUT_CTL__A                                               0x1C20016
+#define  FEC_RS_COMM_EXEC__A                                               0x1C30000
+#define    FEC_RS_COMM_EXEC_STOP                                           0x0
+#define  FEC_RS_MEASUREMENT_PERIOD__A                                      0x1C30012
+#define  FEC_RS_MEASUREMENT_PRESCALE__A                                    0x1C30013
+#define  FEC_OC_MODE__A                                                    0x1C40011
+#define    FEC_OC_MODE_PARITY__M                                           0x1
+#define  FEC_OC_DTO_MODE__A                                                0x1C40014
+#define    FEC_OC_DTO_MODE_DYNAMIC__M                                      0x1
+#define    FEC_OC_DTO_MODE_OFFSET_ENABLE__M                                0x4
+#define  FEC_OC_DTO_PERIOD__A                                              0x1C40015
+#define  FEC_OC_DTO_BURST_LEN__A                                           0x1C40018
+#define  FEC_OC_FCT_MODE__A                                                0x1C4001A
+#define  FEC_OC_FCT_MODE__PRE                                              0x0
+#define    FEC_OC_FCT_MODE_RAT_ENA__M                                      0x1
+#define    FEC_OC_FCT_MODE_VIRT_ENA__M                                     0x2
+#define  FEC_OC_TMD_MODE__A                                                0x1C4001E
+#define  FEC_OC_TMD_COUNT__A                                               0x1C4001F
+#define  FEC_OC_TMD_HI_MARGIN__A                                           0x1C40020
+#define  FEC_OC_TMD_LO_MARGIN__A                                           0x1C40021
+#define  FEC_OC_TMD_INT_UPD_RATE__A                                        0x1C40023
+#define  FEC_OC_AVR_PARM_A__A                                              0x1C40026
+#define  FEC_OC_AVR_PARM_B__A                                              0x1C40027
+#define  FEC_OC_RCN_GAIN__A                                                0x1C4002E
+#define  FEC_OC_RCN_CTL_RATE_LO__A                                         0x1C40030
+#define  FEC_OC_RCN_CTL_STEP_LO__A                                         0x1C40032
+#define  FEC_OC_RCN_CTL_STEP_HI__A                                         0x1C40033
+#define  FEC_OC_SNC_MODE__A                                                0x1C40040
+#define    FEC_OC_SNC_MODE_SHUTDOWN__M                                     0x10
+#define  FEC_OC_SNC_LWM__A                                                 0x1C40041
+#define  FEC_OC_SNC_HWM__A                                                 0x1C40042
+#define  FEC_OC_SNC_UNLOCK__A                                              0x1C40043
+#define  FEC_OC_SNC_FAIL_PERIOD__A                                         0x1C40046
+#define  FEC_OC_IPR_MODE__A                                                0x1C40048
+#define    FEC_OC_IPR_MODE_SERIAL__M                                       0x1
+#define    FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M                             0x4
+#define    FEC_OC_IPR_MODE_MVAL_DIS_PAR__M                                 0x10
+#define  FEC_OC_IPR_INVERT__A                                              0x1C40049
+#define    FEC_OC_IPR_INVERT_MD0__M                                        0x1
+#define    FEC_OC_IPR_INVERT_MD1__M                                        0x2
+#define    FEC_OC_IPR_INVERT_MD2__M                                        0x4
+#define    FEC_OC_IPR_INVERT_MD3__M                                        0x8
+#define    FEC_OC_IPR_INVERT_MD4__M                                        0x10
+#define    FEC_OC_IPR_INVERT_MD5__M                                        0x20
+#define    FEC_OC_IPR_INVERT_MD6__M                                        0x40
+#define    FEC_OC_IPR_INVERT_MD7__M                                        0x80
+#define    FEC_OC_IPR_INVERT_MERR__M                                       0x100
+#define    FEC_OC_IPR_INVERT_MSTRT__M                                      0x200
+#define    FEC_OC_IPR_INVERT_MVAL__M                                       0x400
+#define    FEC_OC_IPR_INVERT_MCLK__M                                       0x800
+#define  FEC_OC_OCR_INVERT__A                                              0x1C40052
+#define  IQM_COMM_EXEC__A                                                  0x1800000
+#define      IQM_COMM_EXEC_B_STOP                                          0x0
+#define      IQM_COMM_EXEC_B_ACTIVE                                        0x1
+#define  IQM_FS_RATE_OFS_LO__A                                             0x1820010
+#define  IQM_FS_ADJ_SEL__A                                                 0x1820014
+#define      IQM_FS_ADJ_SEL_B_OFF                                          0x0
+#define      IQM_FS_ADJ_SEL_B_QAM                                          0x1
+#define      IQM_FS_ADJ_SEL_B_VSB                                          0x2
+#define  IQM_FD_RATESEL__A                                                 0x1830010
+#define  IQM_RC_RATE_OFS_LO__A                                             0x1840010
+#define  IQM_RC_RATE_OFS_LO__W                                             16
+#define  IQM_RC_RATE_OFS_LO__M                                             0xFFFF
+#define  IQM_RC_RATE_OFS_HI__M                                             0xFF
+#define  IQM_RC_ADJ_SEL__A                                                 0x1840014
+#define      IQM_RC_ADJ_SEL_B_OFF                                          0x0
+#define      IQM_RC_ADJ_SEL_B_QAM                                          0x1
+#define      IQM_RC_ADJ_SEL_B_VSB                                          0x2
+#define  IQM_RC_STRETCH__A                                                 0x1840016
+#define  IQM_CF_COMM_INT_MSK__A                                            0x1860006
+#define  IQM_CF_SYMMETRIC__A                                               0x1860010
+#define  IQM_CF_MIDTAP__A                                                  0x1860011
+#define    IQM_CF_MIDTAP_RE__B                                             0
+#define    IQM_CF_MIDTAP_IM__B                                             1
+#define  IQM_CF_OUT_ENA__A                                                 0x1860012
+#define    IQM_CF_OUT_ENA_QAM__B                                           1
+#define    IQM_CF_OUT_ENA_OFDM__M                                          0x4
+#define  IQM_CF_ADJ_SEL__A                                                 0x1860013
+#define  IQM_CF_SCALE__A                                                   0x1860014
+#define  IQM_CF_SCALE_SH__A                                                0x1860015
+#define  IQM_CF_SCALE_SH__PRE                                              0x0
+#define  IQM_CF_POW_MEAS_LEN__A                                            0x1860017
+#define  IQM_CF_DS_ENA__A                                                  0x1860019
+#define  IQM_CF_TAP_RE0__A                                                 0x1860020
+#define  IQM_CF_TAP_IM0__A                                                 0x1860040
+#define  IQM_CF_CLP_VAL__A                                                 0x1860060
+#define  IQM_CF_DATATH__A                                                  0x1860061
+#define  IQM_CF_PKDTH__A                                                   0x1860062
+#define  IQM_CF_WND_LEN__A                                                 0x1860063
+#define  IQM_CF_DET_LCT__A                                                 0x1860064
+#define  IQM_CF_BYPASSDET__A                                               0x1860067
+#define  IQM_AF_COMM_EXEC__A                                               0x1870000
+#define    IQM_AF_COMM_EXEC_ACTIVE                                         0x1
+#define  IQM_AF_CLKNEG__A                                                  0x1870012
+#define    IQM_AF_CLKNEG_CLKNEGDATA__M                                     0x2
+#define      IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS                     0x0
+#define      IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_NEG                     0x2
+#define  IQM_AF_START_LOCK__A                                              0x187001B
+#define  IQM_AF_PHASE0__A                                                  0x187001C
+#define  IQM_AF_PHASE1__A                                                  0x187001D
+#define  IQM_AF_PHASE2__A                                                  0x187001E
+#define  IQM_AF_CLP_LEN__A                                                 0x1870023
+#define  IQM_AF_CLP_TH__A                                                  0x1870024
+#define  IQM_AF_SNS_LEN__A                                                 0x1870026
+#define  IQM_AF_AGC_IF__A                                                  0x1870028
+#define  IQM_AF_AGC_RF__A                                                  0x1870029
+#define  IQM_AF_PDREF__A                                                   0x187002B
+#define  IQM_AF_PDREF__M                                                   0x1F
+#define  IQM_AF_STDBY__A                                                   0x187002C
+#define      IQM_AF_STDBY_STDBY_ADC_STANDBY                                0x2
+#define      IQM_AF_STDBY_STDBY_AMP_STANDBY                                0x4
+#define      IQM_AF_STDBY_STDBY_PD_STANDBY                                 0x8
+#define      IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY                            0x10
+#define      IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY                            0x20
+#define  IQM_AF_AMUX__A                                                    0x187002D
+#define    IQM_AF_AMUX_SIGNAL2ADC                                          0x1
+#define  IQM_AF_UPD_SEL__A                                                 0x187002F
+#define  IQM_AF_INC_LCT__A                                                 0x1870034
+#define  IQM_AF_INC_BYPASS__A                                              0x1870036
+#define  OFDM_CP_COMM_EXEC__A                                              0x2800000
+#define    OFDM_CP_COMM_EXEC_STOP                                          0x0
+#define  OFDM_EC_SB_PRIOR__A                                               0x3410013
+#define    OFDM_EC_SB_PRIOR_HI                                             0x0
+#define    OFDM_EC_SB_PRIOR_LO                                             0x1
+#define  OFDM_EQ_TOP_TD_TPS_CONST__A                                       0x3010054
+#define  OFDM_EQ_TOP_TD_TPS_CONST__M                                       0x3
+#define    OFDM_EQ_TOP_TD_TPS_CONST_64QAM                                  0x2
+#define  OFDM_EQ_TOP_TD_TPS_CODE_HP__A                                     0x3010056
+#define  OFDM_EQ_TOP_TD_TPS_CODE_HP__M                                     0x7
+#define    OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8                                  0x4
+#define  OFDM_EQ_TOP_TD_SQR_ERR_I__A                                       0x301005E
+#define  OFDM_EQ_TOP_TD_SQR_ERR_Q__A                                       0x301005F
+#define  OFDM_EQ_TOP_TD_SQR_ERR_EXP__A                                     0x3010060
+#define  OFDM_EQ_TOP_TD_REQ_SMB_CNT__A                                     0x3010061
+#define  OFDM_EQ_TOP_TD_TPS_PWR_OFS__A                                     0x3010062
+#define  OFDM_LC_COMM_EXEC__A                                              0x3800000
+#define    OFDM_LC_COMM_EXEC_STOP                                          0x0
+#define  OFDM_SC_COMM_EXEC__A                                              0x3C00000
+#define    OFDM_SC_COMM_EXEC_STOP                                          0x0
+#define  OFDM_SC_COMM_STATE__A                                             0x3C00001
+#define  OFDM_SC_RA_RAM_PARAM0__A                                          0x3C20040
+#define  OFDM_SC_RA_RAM_PARAM1__A                                          0x3C20041
+#define  OFDM_SC_RA_RAM_CMD_ADDR__A                                        0x3C20042
+#define  OFDM_SC_RA_RAM_CMD__A                                             0x3C20043
+#define    OFDM_SC_RA_RAM_CMD_NULL                                         0x0
+#define    OFDM_SC_RA_RAM_CMD_PROC_START                                   0x1
+#define    OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM                               0x3
+#define    OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM                                0x4
+#define    OFDM_SC_RA_RAM_CMD_GET_OP_PARAM                                 0x5
+#define    OFDM_SC_RA_RAM_CMD_USER_IO                                      0x6
+#define    OFDM_SC_RA_RAM_CMD_SET_TIMER                                    0x7
+#define    OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING                              0x8
+#define    OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M                            0x1
+#define    OFDM_SC_RA_RAM_LOCKTRACK_MIN                                    0x1
+#define  OFDM_SC_RA_RAM_OP_PARAM__A                                        0x3C20048
+#define    OFDM_SC_RA_RAM_OP_PARAM_MODE__M                                 0x3
+#define      OFDM_SC_RA_RAM_OP_PARAM_MODE_2K                               0x0
+#define      OFDM_SC_RA_RAM_OP_PARAM_MODE_8K                               0x1
+#define      OFDM_SC_RA_RAM_OP_PARAM_GUARD_32                              0x0
+#define      OFDM_SC_RA_RAM_OP_PARAM_GUARD_16                              0x4
+#define      OFDM_SC_RA_RAM_OP_PARAM_GUARD_8                               0x8
+#define      OFDM_SC_RA_RAM_OP_PARAM_GUARD_4                               0xC
+#define      OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK                            0x0
+#define      OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16                           0x10
+#define      OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64                           0x20
+#define      OFDM_SC_RA_RAM_OP_PARAM_HIER_NO                               0x0
+#define      OFDM_SC_RA_RAM_OP_PARAM_HIER_A1                               0x40
+#define      OFDM_SC_RA_RAM_OP_PARAM_HIER_A2                               0x80
+#define      OFDM_SC_RA_RAM_OP_PARAM_HIER_A4                               0xC0
+#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2                              0x0
+#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3                              0x200
+#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4                              0x400
+#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6                              0x600
+#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8                              0x800
+#define      OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI                               0x0
+#define      OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO                               0x1000
+#define    OFDM_SC_RA_RAM_OP_AUTO_MODE__M                                  0x1
+#define    OFDM_SC_RA_RAM_OP_AUTO_GUARD__M                                 0x2
+#define    OFDM_SC_RA_RAM_OP_AUTO_CONST__M                                 0x4
+#define    OFDM_SC_RA_RAM_OP_AUTO_HIER__M                                  0x8
+#define    OFDM_SC_RA_RAM_OP_AUTO_RATE__M                                  0x10
+#define  OFDM_SC_RA_RAM_LOCK__A                                            0x3C2004B
+#define    OFDM_SC_RA_RAM_LOCK_DEMOD__M                                    0x1
+#define    OFDM_SC_RA_RAM_LOCK_FEC__M                                      0x2
+#define    OFDM_SC_RA_RAM_LOCK_MPEG__M                                     0x4
+#define    OFDM_SC_RA_RAM_LOCK_NODVBT__M                                   0x8
+#define  OFDM_SC_RA_RAM_BE_OPT_DELAY__A                                    0x3C2004D
+#define  OFDM_SC_RA_RAM_BE_OPT_INIT_DELAY__A                               0x3C2004E
+#define  OFDM_SC_RA_RAM_ECHO_THRES__A                                      0x3C2004F
+#define    OFDM_SC_RA_RAM_ECHO_THRES_8K__B                                 0
+#define    OFDM_SC_RA_RAM_ECHO_THRES_8K__M                                 0xFF
+#define    OFDM_SC_RA_RAM_ECHO_THRES_2K__B                                 8
+#define    OFDM_SC_RA_RAM_ECHO_THRES_2K__M                                 0xFF00
+#define  OFDM_SC_RA_RAM_CONFIG__A                                          0x3C20050
+#define    OFDM_SC_RA_RAM_CONFIG_NE_FIX_ENABLE__M                          0x800
+#define  OFDM_SC_RA_RAM_FR_THRES_8K__A                                     0x3C2007D
+#define  OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A                             0x3C200E0
+#define  OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A                            0x3C200E1
+#define  OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A                             0x3C200E3
+#define  OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A                            0x3C200E4
+#define  OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A                                0x3C200F8
+#define  QAM_COMM_EXEC__A                                                  0x1400000
+#define    QAM_COMM_EXEC_STOP                                              0x0
+#define    QAM_COMM_EXEC_ACTIVE                                            0x1
+#define    QAM_TOP_ANNEX_A                                                 0x0
+#define    QAM_TOP_ANNEX_C                                                 0x2
+#define  QAM_SL_ERR_POWER__A                                               0x1430017
+#define  QAM_DQ_QUAL_FUN0__A                                               0x1440018
+#define  QAM_DQ_QUAL_FUN1__A                                               0x1440019
+#define  QAM_DQ_QUAL_FUN2__A                                               0x144001A
+#define  QAM_DQ_QUAL_FUN3__A                                               0x144001B
+#define  QAM_DQ_QUAL_FUN4__A                                               0x144001C
+#define  QAM_DQ_QUAL_FUN5__A                                               0x144001D
+#define  QAM_LC_MODE__A                                                    0x1450010
+#define  QAM_LC_QUAL_TAB0__A                                               0x1450018
+#define  QAM_LC_QUAL_TAB1__A                                               0x1450019
+#define  QAM_LC_QUAL_TAB2__A                                               0x145001A
+#define  QAM_LC_QUAL_TAB3__A                                               0x145001B
+#define  QAM_LC_QUAL_TAB4__A                                               0x145001C
+#define  QAM_LC_QUAL_TAB5__A                                               0x145001D
+#define  QAM_LC_QUAL_TAB6__A                                               0x145001E
+#define  QAM_LC_QUAL_TAB8__A                                               0x145001F
+#define  QAM_LC_QUAL_TAB9__A                                               0x1450020
+#define  QAM_LC_QUAL_TAB10__A                                              0x1450021
+#define  QAM_LC_QUAL_TAB12__A                                              0x1450022
+#define  QAM_LC_QUAL_TAB15__A                                              0x1450023
+#define  QAM_LC_QUAL_TAB16__A                                              0x1450024
+#define  QAM_LC_QUAL_TAB20__A                                              0x1450025
+#define  QAM_LC_QUAL_TAB25__A                                              0x1450026
+#define  QAM_LC_LPF_FACTORP__A                                             0x1450028
+#define  QAM_LC_LPF_FACTORI__A                                             0x1450029
+#define  QAM_LC_RATE_LIMIT__A                                              0x145002A
+#define  QAM_LC_SYMBOL_FREQ__A                                             0x145002B
+#define  QAM_SY_TIMEOUT__A                                                 0x1470011
+#define  QAM_SY_TIMEOUT__PRE                                               0x3A98
+#define  QAM_SY_SYNC_LWM__A                                                0x1470012
+#define  QAM_SY_SYNC_AWM__A                                                0x1470013
+#define  QAM_SY_SYNC_HWM__A                                                0x1470014
+#define  QAM_SY_SP_INV__A                                                  0x1470017
+#define    QAM_SY_SP_INV_SPECTRUM_INV_DIS                                  0x0
+#define  SCU_COMM_EXEC__A                                                  0x800000
+#define    SCU_COMM_EXEC_STOP                                              0x0
+#define    SCU_COMM_EXEC_ACTIVE                                            0x1
+#define    SCU_COMM_EXEC_HOLD                                              0x2
+#define  SCU_RAM_DRIVER_DEBUG__A                                           0x831EBF
+#define  SCU_RAM_QAM_FSM_STEP_PERIOD__A                                    0x831EC4
+#define  SCU_RAM_GPIO__A                                                   0x831EC7
+#define      SCU_RAM_GPIO_HW_LOCK_IND_DISABLE                              0x0
+#define  SCU_RAM_AGC_CLP_CTRL_MODE__A                                      0x831EC8
+#define  SCU_RAM_FEC_ACCUM_PKT_FAILURES__A                                 0x831ECB
+#define  SCU_RAM_FEC_PRE_RS_BER_FILTER_SH__A                               0x831F05
+#define  SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A                                0x831F15
+#define  SCU_RAM_AGC_KI_CYCLEN__A                                          0x831F17
+#define  SCU_RAM_AGC_SNS_CYCLEN__A                                         0x831F18
+#define  SCU_RAM_AGC_RF_SNS_DEV_MAX__A                                     0x831F19
+#define  SCU_RAM_AGC_RF_SNS_DEV_MIN__A                                     0x831F1A
+#define  SCU_RAM_AGC_RF_MAX__A                                             0x831F1B
+#define  SCU_RAM_AGC_CONFIG__A                                             0x831F24
+#define    SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M                            0x1
+#define    SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M                            0x2
+#define    SCU_RAM_AGC_CONFIG_INV_IF_POL__M                                0x100
+#define    SCU_RAM_AGC_CONFIG_INV_RF_POL__M                                0x200
+#define  SCU_RAM_AGC_KI__A                                                 0x831F25
+#define    SCU_RAM_AGC_KI_RF__B                                            4
+#define    SCU_RAM_AGC_KI_RF__M                                            0xF0
+#define    SCU_RAM_AGC_KI_IF__B                                            8
+#define    SCU_RAM_AGC_KI_IF__M                                            0xF00
+#define  SCU_RAM_AGC_KI_RED__A                                             0x831F26
+#define    SCU_RAM_AGC_KI_RED_RAGC_RED__B                                  2
+#define    SCU_RAM_AGC_KI_RED_RAGC_RED__M                                  0xC
+#define    SCU_RAM_AGC_KI_RED_IAGC_RED__B                                  4
+#define    SCU_RAM_AGC_KI_RED_IAGC_RED__M                                  0x30
+#define  SCU_RAM_AGC_KI_INNERGAIN_MIN__A                                   0x831F27
+#define  SCU_RAM_AGC_KI_MINGAIN__A                                         0x831F28
+#define  SCU_RAM_AGC_KI_MAXGAIN__A                                         0x831F29
+#define  SCU_RAM_AGC_KI_MAXMINGAIN_TH__A                                   0x831F2A
+#define  SCU_RAM_AGC_KI_MIN__A                                             0x831F2B
+#define  SCU_RAM_AGC_KI_MAX__A                                             0x831F2C
+#define  SCU_RAM_AGC_CLP_SUM__A                                            0x831F2D
+#define  SCU_RAM_AGC_CLP_SUM_MIN__A                                        0x831F2E
+#define  SCU_RAM_AGC_CLP_SUM_MAX__A                                        0x831F2F
+#define  SCU_RAM_AGC_CLP_CYCLEN__A                                         0x831F30
+#define  SCU_RAM_AGC_CLP_CYCCNT__A                                         0x831F31
+#define  SCU_RAM_AGC_CLP_DIR_TO__A                                         0x831F32
+#define  SCU_RAM_AGC_CLP_DIR_WD__A                                         0x831F33
+#define  SCU_RAM_AGC_CLP_DIR_STP__A                                        0x831F34
+#define  SCU_RAM_AGC_SNS_SUM__A                                            0x831F35
+#define  SCU_RAM_AGC_SNS_SUM_MIN__A                                        0x831F36
+#define  SCU_RAM_AGC_SNS_SUM_MAX__A                                        0x831F37
+#define  SCU_RAM_AGC_SNS_CYCCNT__A                                         0x831F38
+#define  SCU_RAM_AGC_SNS_DIR_TO__A                                         0x831F39
+#define  SCU_RAM_AGC_SNS_DIR_WD__A                                         0x831F3A
+#define  SCU_RAM_AGC_SNS_DIR_STP__A                                        0x831F3B
+#define  SCU_RAM_AGC_INGAIN_TGT__A                                         0x831F3D
+#define  SCU_RAM_AGC_INGAIN_TGT_MIN__A                                     0x831F3E
+#define  SCU_RAM_AGC_INGAIN_TGT_MAX__A                                     0x831F3F
+#define  SCU_RAM_AGC_IF_IACCU_HI__A                                        0x831F40
+#define  SCU_RAM_AGC_IF_IACCU_LO__A                                        0x831F41
+#define  SCU_RAM_AGC_IF_IACCU_HI_TGT__A                                    0x831F42
+#define  SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A                                0x831F43
+#define  SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A                                0x831F44
+#define  SCU_RAM_AGC_RF_IACCU_HI__A                                        0x831F45
+#define  SCU_RAM_AGC_RF_IACCU_LO__A                                        0x831F46
+#define  SCU_RAM_AGC_RF_IACCU_HI_CO__A                                     0x831F47
+#define  SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A                                 0x831F84
+#define  SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A                                0x831F85
+#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A                                  0x831F86
+#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A                                  0x831F87
+#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A                                  0x831F88
+#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A                                  0x831F89
+#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A                                  0x831F8A
+#define  SCU_RAM_QAM_FSM_RTH__A                                            0x831F8E
+#define  SCU_RAM_QAM_FSM_FTH__A                                            0x831F8F
+#define  SCU_RAM_QAM_FSM_PTH__A                                            0x831F90
+#define  SCU_RAM_QAM_FSM_MTH__A                                            0x831F91
+#define  SCU_RAM_QAM_FSM_CTH__A                                            0x831F92
+#define  SCU_RAM_QAM_FSM_QTH__A                                            0x831F93
+#define  SCU_RAM_QAM_FSM_RATE_LIM__A                                       0x831F94
+#define  SCU_RAM_QAM_FSM_FREQ_LIM__A                                       0x831F95
+#define  SCU_RAM_QAM_FSM_COUNT_LIM__A                                      0x831F96
+#define  SCU_RAM_QAM_LC_CA_COARSE__A                                       0x831F97
+#define  SCU_RAM_QAM_LC_CA_FINE__A                                         0x831F99
+#define  SCU_RAM_QAM_LC_CP_COARSE__A                                       0x831F9A
+#define  SCU_RAM_QAM_LC_CP_MEDIUM__A                                       0x831F9B
+#define  SCU_RAM_QAM_LC_CP_FINE__A                                         0x831F9C
+#define  SCU_RAM_QAM_LC_CI_COARSE__A                                       0x831F9D
+#define  SCU_RAM_QAM_LC_CI_MEDIUM__A                                       0x831F9E
+#define  SCU_RAM_QAM_LC_CI_FINE__A                                         0x831F9F
+#define  SCU_RAM_QAM_LC_EP_COARSE__A                                       0x831FA0
+#define  SCU_RAM_QAM_LC_EP_MEDIUM__A                                       0x831FA1
+#define  SCU_RAM_QAM_LC_EP_FINE__A                                         0x831FA2
+#define  SCU_RAM_QAM_LC_EI_COARSE__A                                       0x831FA3
+#define  SCU_RAM_QAM_LC_EI_MEDIUM__A                                       0x831FA4
+#define  SCU_RAM_QAM_LC_EI_FINE__A                                         0x831FA5
+#define  SCU_RAM_QAM_LC_CF_COARSE__A                                       0x831FA6
+#define  SCU_RAM_QAM_LC_CF_MEDIUM__A                                       0x831FA7
+#define  SCU_RAM_QAM_LC_CF_FINE__A                                         0x831FA8
+#define  SCU_RAM_QAM_LC_CF1_COARSE__A                                      0x831FA9
+#define  SCU_RAM_QAM_LC_CF1_MEDIUM__A                                      0x831FAA
+#define  SCU_RAM_QAM_LC_CF1_FINE__A                                        0x831FAB
+#define  SCU_RAM_QAM_SL_SIG_POWER__A                                       0x831FAC
+#define  SCU_RAM_QAM_EQ_CMA_RAD0__A                                        0x831FAD
+#define  SCU_RAM_QAM_EQ_CMA_RAD1__A                                        0x831FAE
+#define  SCU_RAM_QAM_EQ_CMA_RAD2__A                                        0x831FAF
+#define  SCU_RAM_QAM_EQ_CMA_RAD3__A                                        0x831FB0
+#define  SCU_RAM_QAM_EQ_CMA_RAD4__A                                        0x831FB1
+#define  SCU_RAM_QAM_EQ_CMA_RAD5__A                                        0x831FB2
+#define      SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED                        0x4000
+#define      SCU_RAM_QAM_LOCKED_LOCKED_LOCKED                              0x8000
+#define      SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK                          0xC000
+#define  SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A                                0x831FEA
+#define  SCU_RAM_DRIVER_VER_HI__A                                          0x831FEB
+#define  SCU_RAM_DRIVER_VER_LO__A                                          0x831FEC
+#define  SCU_RAM_PARAM_15__A                                               0x831FED
+#define  SCU_RAM_PARAM_0__A                                                0x831FFC
+#define  SCU_RAM_COMMAND__A                                                0x831FFD
+#define    SCU_RAM_COMMAND_CMD_DEMOD_RESET                                 0x1
+#define    SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV                               0x2
+#define    SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM                             0x3
+#define    SCU_RAM_COMMAND_CMD_DEMOD_START                                 0x4
+#define    SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK                              0x5
+#define    SCU_RAM_COMMAND_CMD_DEMOD_STOP                                  0x9
+#define      SCU_RAM_COMMAND_STANDARD_QAM                                  0x200
+#define      SCU_RAM_COMMAND_STANDARD_OFDM                                 0x400
+#define  SIO_TOP_COMM_KEY__A                                               0x41000F
+#define    SIO_TOP_COMM_KEY_KEY                                            0xFABA
+#define  SIO_TOP_JTAGID_LO__A                                              0x410012
+#define  SIO_HI_RA_RAM_RES__A                                              0x420031
+#define  SIO_HI_RA_RAM_CMD__A                                              0x420032
+#define    SIO_HI_RA_RAM_CMD_RESET                                         0x2
+#define    SIO_HI_RA_RAM_CMD_CONFIG                                        0x3
+#define    SIO_HI_RA_RAM_CMD_BRDCTRL                                       0x7
+#define  SIO_HI_RA_RAM_PAR_1__A                                            0x420033
+#define      SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY                              0x3945
+#define  SIO_HI_RA_RAM_PAR_2__A                                            0x420034
+#define    SIO_HI_RA_RAM_PAR_2_CFG_DIV__M                                  0x7F
+#define      SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN                              0x0
+#define      SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED                            0x4
+#define  SIO_HI_RA_RAM_PAR_3__A                                            0x420035
+#define    SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M                              0x7F
+#define    SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B                              7
+#define      SIO_HI_RA_RAM_PAR_3_ACP_RW_READ                               0x0
+#define      SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE                              0x8
+#define  SIO_HI_RA_RAM_PAR_4__A                                            0x420036
+#define  SIO_HI_RA_RAM_PAR_5__A                                            0x420037
+#define      SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE                            0x1
+#define    SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M                                0x8
+#define      SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ                             0x8
+#define  SIO_HI_RA_RAM_PAR_6__A                                            0x420038
+#define  SIO_CC_PLL_LOCK__A                                                0x450012
+#define  SIO_CC_PWD_MODE__A                                                0x450015
+#define      SIO_CC_PWD_MODE_LEVEL_NONE                                    0x0
+#define      SIO_CC_PWD_MODE_LEVEL_OFDM                                    0x1
+#define      SIO_CC_PWD_MODE_LEVEL_CLOCK                                   0x2
+#define      SIO_CC_PWD_MODE_LEVEL_PLL                                     0x3
+#define      SIO_CC_PWD_MODE_LEVEL_OSC                                     0x4
+#define  SIO_CC_SOFT_RST__A                                                0x450016
+#define    SIO_CC_SOFT_RST_OFDM__M                                         0x1
+#define    SIO_CC_SOFT_RST_SYS__M                                          0x2
+#define    SIO_CC_SOFT_RST_OSC__M                                          0x4
+#define  SIO_CC_UPDATE__A                                                  0x450017
+#define    SIO_CC_UPDATE_KEY                                               0xFABA
+#define  SIO_OFDM_SH_OFDM_RING_ENABLE__A                                   0x470010
+#define    SIO_OFDM_SH_OFDM_RING_ENABLE_OFF                                0x0
+#define    SIO_OFDM_SH_OFDM_RING_ENABLE_ON                                 0x1
+#define  SIO_OFDM_SH_OFDM_RING_STATUS__A                                   0x470012
+#define    SIO_OFDM_SH_OFDM_RING_STATUS_DOWN                               0x0
+#define    SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED                            0x1
+#define  SIO_BL_COMM_EXEC__A                                               0x480000
+#define    SIO_BL_COMM_EXEC_ACTIVE                                         0x1
+#define  SIO_BL_STATUS__A                                                  0x480010
+#define  SIO_BL_MODE__A                                                    0x480011
+#define    SIO_BL_MODE_DIRECT                                              0x0
+#define    SIO_BL_MODE_CHAIN                                               0x1
+#define  SIO_BL_ENABLE__A                                                  0x480012
+#define    SIO_BL_ENABLE_ON                                                0x1
+#define  SIO_BL_TGT_HDR__A                                                 0x480014
+#define  SIO_BL_TGT_ADDR__A                                                0x480015
+#define  SIO_BL_SRC_ADDR__A                                                0x480016
+#define  SIO_BL_SRC_LEN__A                                                 0x480017
+#define  SIO_BL_CHAIN_ADDR__A                                              0x480018
+#define  SIO_BL_CHAIN_LEN__A                                               0x480019
+#define  SIO_PDR_MON_CFG__A                                                0x7F0010
+#define  SIO_PDR_UIO_IN_HI__A                                              0x7F0015
+#define  SIO_PDR_UIO_OUT_LO__A                                             0x7F0016
+#define  SIO_PDR_OHW_CFG__A                                                0x7F001F
+#define    SIO_PDR_OHW_CFG_FREF_SEL__M                                     0x3
+#define  SIO_PDR_MSTRT_CFG__A                                              0x7F0025
+#define  SIO_PDR_MERR_CFG__A                                               0x7F0026
+#define  SIO_PDR_MCLK_CFG__A                                               0x7F0028
+#define    SIO_PDR_MCLK_CFG_DRIVE__B                                       3
+#define  SIO_PDR_MVAL_CFG__A                                               0x7F0029
+#define  SIO_PDR_MD0_CFG__A                                                0x7F002A
+#define    SIO_PDR_MD0_CFG_DRIVE__B                                        3
+#define  SIO_PDR_MD1_CFG__A                                                0x7F002B
+#define  SIO_PDR_MD2_CFG__A                                                0x7F002C
+#define  SIO_PDR_MD3_CFG__A                                                0x7F002D
+#define  SIO_PDR_MD4_CFG__A                                                0x7F002F
+#define  SIO_PDR_MD5_CFG__A                                                0x7F0030
+#define  SIO_PDR_MD6_CFG__A                                                0x7F0031
+#define  SIO_PDR_MD7_CFG__A                                                0x7F0032
+#define  SIO_PDR_SMA_TX_CFG__A                                             0x7F0038
index f7a40a1..aa9ccb8 100644 (file)
@@ -35,21 +35,18 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
-#define deb(args...)  do { \
+#define itd_dbg(args...)  do { \
        if (debug) { \
                printk(KERN_DEBUG   "ITD1000: " args);\
-               printk("\n"); \
        } \
 } while (0)
 
-#define warn(args...) do { \
+#define itd_warn(args...) do { \
        printk(KERN_WARNING "ITD1000: " args); \
-       printk("\n"); \
 } while (0)
 
-#define info(args...) do { \
+#define itd_info(args...) do { \
        printk(KERN_INFO    "ITD1000: " args); \
-       printk("\n"); \
 } while (0)
 
 /* don't write more than one byte with flexcop behind */
@@ -62,7 +59,7 @@ static int itd1000_write_regs(struct itd1000_state *state, u8 reg, u8 v[], u8 le
        buf[0] = reg;
        memcpy(&buf[1], v, len);
 
-       /* deb("wr %02x: %02x", reg, v[0]); */
+       /* itd_dbg("wr %02x: %02x\n", reg, v[0]); */
 
        if (i2c_transfer(state->i2c, &msg, 1) != 1) {
                printk(KERN_WARNING "itd1000 I2C write failed\n");
@@ -83,7 +80,7 @@ static int itd1000_read_reg(struct itd1000_state *state, u8 reg)
        itd1000_write_regs(state, (reg - 1) & 0xff, &state->shadow[(reg - 1) & 0xff], 1);
 
        if (i2c_transfer(state->i2c, msg, 2) != 2) {
-               warn("itd1000 I2C read failed");
+               itd_warn("itd1000 I2C read failed\n");
                return -EREMOTEIO;
        }
        return val;
@@ -127,14 +124,14 @@ static void itd1000_set_lpf_bw(struct itd1000_state *state, u32 symbol_rate)
        u8 bbgvmin = itd1000_read_reg(state, BBGVMIN) & 0xf0;
        u8 bw      = itd1000_read_reg(state, BW)      & 0xf0;
 
-       deb("symbol_rate = %d", symbol_rate);
+       itd_dbg("symbol_rate = %d\n", symbol_rate);
 
        /* not sure what is that ? - starting to download the table */
        itd1000_write_reg(state, CON1, con1 | (1 << 1));
 
        for (i = 0; i < ARRAY_SIZE(itd1000_lpf_pga); i++)
                if (symbol_rate < itd1000_lpf_pga[i].symbol_rate) {
-                       deb("symrate: index: %d pgaext: %x, bbgvmin: %x", i, itd1000_lpf_pga[i].pgaext, itd1000_lpf_pga[i].bbgvmin);
+                       itd_dbg("symrate: index: %d pgaext: %x, bbgvmin: %x\n", i, itd1000_lpf_pga[i].pgaext, itd1000_lpf_pga[i].bbgvmin);
                        itd1000_write_reg(state, PLLFH,   pllfh | (itd1000_lpf_pga[i].pgaext << 4));
                        itd1000_write_reg(state, BBGVMIN, bbgvmin | (itd1000_lpf_pga[i].bbgvmin));
                        itd1000_write_reg(state, BW,      bw | (i & 0x0f));
@@ -182,7 +179,7 @@ static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz)
 
                        adcout = itd1000_read_reg(state, PLLLOCK) & 0x0f;
 
-                       deb("VCO: %dkHz: %d -> ADCOUT: %d %02x", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
+                       itd_dbg("VCO: %dkHz: %d -> ADCOUT: %d %02x\n", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
 
                        if (adcout > 13) {
                                if (!(itd1000_vcorg[i].vcorg == 7 || itd1000_vcorg[i].vcorg == 15))
@@ -232,7 +229,7 @@ static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
        pllf = (u32) tmp;
 
        state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF;
-       deb("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d", freq_khz, state->frequency, pllf, plln);
+       itd_dbg("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d\n", freq_khz, state->frequency, pllf, plln);
 
        itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */;
        itd1000_write_reg(state, PLLNL, plln & 0xff);
@@ -242,7 +239,7 @@ static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
 
        for (i = 0; i < ARRAY_SIZE(itd1000_fre_values); i++) {
                if (freq_khz <= itd1000_fre_values[i].freq) {
-                       deb("fre_values: %d", i);
+                       itd_dbg("fre_values: %d\n", i);
                        itd1000_write_reg(state, RFTR, itd1000_fre_values[i].values[0]);
                        for (j = 0; j < 9; j++)
                                itd1000_write_reg(state, RFST1+j, itd1000_fre_values[i].values[j+1]);
@@ -382,7 +379,7 @@ struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter
                kfree(state);
                return NULL;
        }
-       info("successfully identified (ID: %d)", i);
+       itd_info("successfully identified (ID: %d)\n", i);
 
        memset(state->shadow, 0xff, sizeof(state->shadow));
        for (i = 0x65; i < 0x9c; i++)
index a763ec7..6599b8f 100644 (file)
@@ -50,7 +50,7 @@ static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data)
        if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
                dprintk("nxt6000: nxt6000_write error (reg: 0x%02X, data: 0x%02X, ret: %d)\n", reg, data, ret);
 
-       return (ret != 1) ? -EFAULT : 0;
+       return (ret != 1) ? -EIO : 0;
 }
 
 static u8 nxt6000_readreg(struct nxt6000_state* state, u8 reg)
index 17f8cdf..3879d2e 100644 (file)
@@ -634,7 +634,7 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        struct s5h1420_state* state = fe->demodulator_priv;
        int frequency_delta;
        struct dvb_frontend_tune_settings fesettings;
-       uint8_t clock_settting;
+       uint8_t clock_setting;
 
        dprintk("enter %s\n", __func__);
 
@@ -684,19 +684,19 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        switch (state->fclk) {
        default:
        case 88000000:
-               clock_settting = 80;
+               clock_setting = 80;
                break;
        case 86000000:
-               clock_settting = 78;
+               clock_setting = 78;
                break;
        case 80000000:
-               clock_settting = 72;
+               clock_setting = 72;
                break;
        case 59000000:
-               clock_settting = 51;
+               clock_setting = 51;
                break;
        case 44000000:
-               clock_settting = 36;
+               clock_setting = 36;
                break;
        }
        dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
diff --git a/drivers/media/dvb/frontends/tda18271c2dd.c b/drivers/media/dvb/frontends/tda18271c2dd.c
new file mode 100644 (file)
index 0000000..0384e8d
--- /dev/null
@@ -0,0 +1,1251 @@
+/*
+ * tda18271c2dd: Driver for the TDA18271C2 tuner
+ *
+ * Copyright (C) 2010 Digital Devices GmbH
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * 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
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/version.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+
+struct SStandardParam {
+       s32   m_IFFrequency;
+       u32   m_BandWidth;
+       u8    m_EP3_4_0;
+       u8    m_EB22;
+};
+
+struct SMap {
+       u32   m_Frequency;
+       u8    m_Param;
+};
+
+struct SMapI {
+       u32   m_Frequency;
+       s32    m_Param;
+};
+
+struct SMap2 {
+       u32   m_Frequency;
+       u8    m_Param1;
+       u8    m_Param2;
+};
+
+struct SRFBandMap {
+       u32   m_RF_max;
+       u32   m_RF1_Default;
+       u32   m_RF2_Default;
+       u32   m_RF3_Default;
+};
+
+enum ERegister {
+       ID = 0,
+       TM,
+       PL,
+       EP1, EP2, EP3, EP4, EP5,
+       CPD, CD1, CD2, CD3,
+       MPD, MD1, MD2, MD3,
+       EB1, EB2, EB3, EB4, EB5, EB6, EB7, EB8, EB9, EB10,
+       EB11, EB12, EB13, EB14, EB15, EB16, EB17, EB18, EB19, EB20,
+       EB21, EB22, EB23,
+       NUM_REGS
+};
+
+struct tda_state {
+       struct i2c_adapter *i2c;
+       u8 adr;
+
+       u32   m_Frequency;
+       u32   IF;
+
+       u8    m_IFLevelAnalog;
+       u8    m_IFLevelDigital;
+       u8    m_IFLevelDVBC;
+       u8    m_IFLevelDVBT;
+
+       u8    m_EP4;
+       u8    m_EP3_Standby;
+
+       bool  m_bMaster;
+
+       s32   m_SettlingTime;
+
+       u8    m_Regs[NUM_REGS];
+
+       /* Tracking filter settings for band 0..6 */
+       u32   m_RF1[7];
+       s32   m_RF_A1[7];
+       s32   m_RF_B1[7];
+       u32   m_RF2[7];
+       s32   m_RF_A2[7];
+       s32   m_RF_B2[7];
+       u32   m_RF3[7];
+
+       u8    m_TMValue_RFCal;    /* Calibration temperatur */
+
+       bool  m_bFMInput;         /* true to use Pin 8 for FM Radio */
+
+};
+
+static int PowerScan(struct tda_state *state,
+                    u8 RFBand, u32 RF_in,
+                    u32 *pRF_Out, bool *pbcal);
+
+static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len)
+{
+       struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
+                                  .buf  = data, .len   = len} };
+       return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
+}
+
+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
+{
+       struct i2c_msg msg = {.addr = adr, .flags = 0,
+                             .buf = data, .len = len};
+
+       if (i2c_transfer(adap, &msg, 1) != 1) {
+               printk(KERN_ERR "tda18271c2dd: i2c write error at addr %i\n", adr);
+               return -1;
+       }
+       return 0;
+}
+
+static int WriteRegs(struct tda_state *state,
+                    u8 SubAddr, u8 *Regs, u16 nRegs)
+{
+       u8 data[nRegs+1];
+
+       data[0] = SubAddr;
+       memcpy(data + 1, Regs, nRegs);
+       return i2c_write(state->i2c, state->adr, data, nRegs+1);
+}
+
+static int WriteReg(struct tda_state *state, u8 SubAddr, u8 Reg)
+{
+       u8 msg[2] = {SubAddr, Reg};
+
+       return i2c_write(state->i2c, state->adr, msg, 2);
+}
+
+static int Read(struct tda_state *state, u8 * Regs)
+{
+       return i2c_readn(state->i2c, state->adr, Regs, 16);
+}
+
+static int ReadExtented(struct tda_state *state, u8 * Regs)
+{
+       return i2c_readn(state->i2c, state->adr, Regs, NUM_REGS);
+}
+
+static int UpdateRegs(struct tda_state *state, u8 RegFrom, u8 RegTo)
+{
+       return WriteRegs(state, RegFrom,
+                        &state->m_Regs[RegFrom], RegTo-RegFrom+1);
+}
+static int UpdateReg(struct tda_state *state, u8 Reg)
+{
+       return WriteReg(state, Reg, state->m_Regs[Reg]);
+}
+
+#include "tda18271c2dd_maps.h"
+
+static void reset(struct tda_state *state)
+{
+       u32   ulIFLevelAnalog = 0;
+       u32   ulIFLevelDigital = 2;
+       u32   ulIFLevelDVBC = 7;
+       u32   ulIFLevelDVBT = 6;
+       u32   ulXTOut = 0;
+       u32   ulStandbyMode = 0x06;    /* Send in stdb, but leave osc on */
+       u32   ulSlave = 0;
+       u32   ulFMInput = 0;
+       u32   ulSettlingTime = 100;
+
+       state->m_Frequency         = 0;
+       state->m_SettlingTime = 100;
+       state->m_IFLevelAnalog = (ulIFLevelAnalog & 0x07) << 2;
+       state->m_IFLevelDigital = (ulIFLevelDigital & 0x07) << 2;
+       state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07) << 2;
+       state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07) << 2;
+
+       state->m_EP4 = 0x20;
+       if (ulXTOut != 0)
+               state->m_EP4 |= 0x40;
+
+       state->m_EP3_Standby = ((ulStandbyMode & 0x07) << 5) | 0x0F;
+       state->m_bMaster = (ulSlave == 0);
+
+       state->m_SettlingTime = ulSettlingTime;
+
+       state->m_bFMInput = (ulFMInput == 2);
+}
+
+static bool SearchMap1(struct SMap Map[],
+                      u32 Frequency, u8 *pParam)
+{
+       int i = 0;
+
+       while ((Map[i].m_Frequency != 0) && (Frequency > Map[i].m_Frequency))
+               i += 1;
+       if (Map[i].m_Frequency == 0)
+               return false;
+       *pParam = Map[i].m_Param;
+       return true;
+}
+
+static bool SearchMap2(struct SMapI Map[],
+                      u32 Frequency, s32 *pParam)
+{
+       int i = 0;
+
+       while ((Map[i].m_Frequency != 0) &&
+              (Frequency > Map[i].m_Frequency))
+               i += 1;
+       if (Map[i].m_Frequency == 0)
+               return false;
+       *pParam = Map[i].m_Param;
+       return true;
+}
+
+static bool SearchMap3(struct SMap2 Map[], u32 Frequency,
+                      u8 *pParam1, u8 *pParam2)
+{
+       int i = 0;
+
+       while ((Map[i].m_Frequency != 0) &&
+              (Frequency > Map[i].m_Frequency))
+               i += 1;
+       if (Map[i].m_Frequency == 0)
+               return false;
+       *pParam1 = Map[i].m_Param1;
+       *pParam2 = Map[i].m_Param2;
+       return true;
+}
+
+static bool SearchMap4(struct SRFBandMap Map[],
+                      u32 Frequency, u8 *pRFBand)
+{
+       int i = 0;
+
+       while (i < 7 && (Frequency > Map[i].m_RF_max))
+               i += 1;
+       if (i == 7)
+               return false;
+       *pRFBand = i;
+       return true;
+}
+
+static int ThermometerRead(struct tda_state *state, u8 *pTM_Value)
+{
+       int status = 0;
+
+       do {
+               u8 Regs[16];
+               state->m_Regs[TM] |= 0x10;
+               status = UpdateReg(state, TM);
+               if (status < 0)
+                       break;
+               status = Read(state, Regs);
+               if (status < 0)
+                       break;
+               if (((Regs[TM] & 0x0F) == 0 && (Regs[TM] & 0x20) == 0x20) ||
+                   ((Regs[TM] & 0x0F) == 8 && (Regs[TM] & 0x20) == 0x00)) {
+                       state->m_Regs[TM] ^= 0x20;
+                       status = UpdateReg(state, TM);
+                       if (status < 0)
+                               break;
+                       msleep(10);
+                       status = Read(state, Regs);
+                       if (status < 0)
+                               break;
+               }
+               *pTM_Value = (Regs[TM] & 0x20)
+                               ? m_Thermometer_Map_2[Regs[TM] & 0x0F]
+                               : m_Thermometer_Map_1[Regs[TM] & 0x0F] ;
+               state->m_Regs[TM] &= ~0x10;        /* Thermometer off */
+               status = UpdateReg(state, TM);
+               if (status < 0)
+                       break;
+               state->m_Regs[EP4] &= ~0x03;       /* CAL_mode = 0 ????????? */
+               status = UpdateReg(state, EP4);
+               if (status < 0)
+                       break;
+       } while (0);
+
+       return status;
+}
+
+static int StandBy(struct tda_state *state)
+{
+       int status = 0;
+       do {
+               state->m_Regs[EB12] &= ~0x20;  /* PD_AGC1_Det = 0 */
+               status = UpdateReg(state, EB12);
+               if (status < 0)
+                       break;
+               state->m_Regs[EB18] &= ~0x83;  /* AGC1_loop_off = 0, AGC1_Gain = 6 dB */
+               status = UpdateReg(state, EB18);
+               if (status < 0)
+                       break;
+               state->m_Regs[EB21] |= 0x03; /* AGC2_Gain = -6 dB */
+               state->m_Regs[EP3] = state->m_EP3_Standby;
+               status = UpdateReg(state, EP3);
+               if (status < 0)
+                       break;
+               state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LP_Fc[2] = 0 */
+               status = UpdateRegs(state, EB21, EB23);
+               if (status < 0)
+                       break;
+       } while (0);
+       return status;
+}
+
+static int CalcMainPLL(struct tda_state *state, u32 freq)
+{
+
+       u8  PostDiv;
+       u8  Div;
+       u64 OscFreq;
+       u32 MainDiv;
+
+       if (!SearchMap3(m_Main_PLL_Map, freq, &PostDiv, &Div))
+               return -EINVAL;
+
+       OscFreq = (u64) freq * (u64) Div;
+       OscFreq *= (u64) 16384;
+       do_div(OscFreq, (u64)16000000);
+       MainDiv = OscFreq;
+
+       state->m_Regs[MPD] = PostDiv & 0x77;
+       state->m_Regs[MD1] = ((MainDiv >> 16) & 0x7F);
+       state->m_Regs[MD2] = ((MainDiv >>  8) & 0xFF);
+       state->m_Regs[MD3] = (MainDiv & 0xFF);
+
+       return UpdateRegs(state, MPD, MD3);
+}
+
+static int CalcCalPLL(struct tda_state *state, u32 freq)
+{
+       u8 PostDiv;
+       u8 Div;
+       u64 OscFreq;
+       u32 CalDiv;
+
+       if (!SearchMap3(m_Cal_PLL_Map, freq, &PostDiv, &Div))
+               return -EINVAL;
+
+       OscFreq = (u64)freq * (u64)Div;
+       /* CalDiv = u32( OscFreq * 16384 / 16000000 ); */
+       OscFreq *= (u64)16384;
+       do_div(OscFreq, (u64)16000000);
+       CalDiv = OscFreq;
+
+       state->m_Regs[CPD] = PostDiv;
+       state->m_Regs[CD1] = ((CalDiv >> 16) & 0xFF);
+       state->m_Regs[CD2] = ((CalDiv >>  8) & 0xFF);
+       state->m_Regs[CD3] = (CalDiv & 0xFF);
+
+       return UpdateRegs(state, CPD, CD3);
+}
+
+static int CalibrateRF(struct tda_state *state,
+                      u8 RFBand, u32 freq, s32 *pCprog)
+{
+       int status = 0;
+       u8 Regs[NUM_REGS];
+       do {
+               u8 BP_Filter = 0;
+               u8 GainTaper = 0;
+               u8 RFC_K = 0;
+               u8 RFC_M = 0;
+
+               state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 */
+               status = UpdateReg(state, EP4);
+               if (status < 0)
+                       break;
+               state->m_Regs[EB18] |= 0x03;  /* AGC1_Gain = 3 */
+               status = UpdateReg(state, EB18);
+               if (status < 0)
+                       break;
+
+               /* Switching off LT (as datasheet says) causes calibration on C1 to fail */
+               /* (Readout of Cprog is allways 255) */
+               if (state->m_Regs[ID] != 0x83)    /* C1: ID == 83, C2: ID == 84 */
+                       state->m_Regs[EP3] |= 0x40; /* SM_LT = 1 */
+
+               if (!(SearchMap1(m_BP_Filter_Map, freq, &BP_Filter) &&
+                       SearchMap1(m_GainTaper_Map, freq, &GainTaper) &&
+                       SearchMap3(m_KM_Map, freq, &RFC_K, &RFC_M)))
+                       return -EINVAL;
+
+               state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | BP_Filter;
+               state->m_Regs[EP2] = (RFBand << 5) | GainTaper;
+
+               state->m_Regs[EB13] = (state->m_Regs[EB13] & ~0x7C) | (RFC_K << 4) | (RFC_M << 2);
+
+               status = UpdateRegs(state, EP1, EP3);
+               if (status < 0)
+                       break;
+               status = UpdateReg(state, EB13);
+               if (status < 0)
+                       break;
+
+               state->m_Regs[EB4] |= 0x20;    /* LO_ForceSrce = 1 */
+               status = UpdateReg(state, EB4);
+               if (status < 0)
+                       break;
+
+               state->m_Regs[EB7] |= 0x20;    /* CAL_ForceSrce = 1 */
+               status = UpdateReg(state, EB7);
+               if (status < 0)
+                       break;
+
+               state->m_Regs[EB14] = 0; /* RFC_Cprog = 0 */
+               status = UpdateReg(state, EB14);
+               if (status < 0)
+                       break;
+
+               state->m_Regs[EB20] &= ~0x20;  /* ForceLock = 0; */
+               status = UpdateReg(state, EB20);
+               if (status < 0)
+                       break;
+
+               state->m_Regs[EP4] |= 0x03;  /* CAL_Mode = 3 */
+               status = UpdateRegs(state, EP4, EP5);
+               if (status < 0)
+                       break;
+
+               status = CalcCalPLL(state, freq);
+               if (status < 0)
+                       break;
+               status = CalcMainPLL(state, freq + 1000000);
+               if (status < 0)
+                       break;
+
+               msleep(5);
+               status = UpdateReg(state, EP2);
+               if (status < 0)
+                       break;
+               status = UpdateReg(state, EP1);
+               if (status < 0)
+                       break;
+               status = UpdateReg(state, EP2);
+               if (status < 0)
+                       break;
+               status = UpdateReg(state, EP1);
+               if (status < 0)
+                       break;
+
+               state->m_Regs[EB4] &= ~0x20;    /* LO_ForceSrce = 0 */
+               status = UpdateReg(state, EB4);
+               if (status < 0)
+                       break;
+
+               state->m_Regs[EB7] &= ~0x20;    /* CAL_ForceSrce = 0 */
+               status = UpdateReg(state, EB7);
+               if (status < 0)
+                       break;
+               msleep(10);
+
+               state->m_Regs[EB20] |= 0x20;  /* ForceLock = 1; */
+               status = UpdateReg(state, EB20);
+               if (status < 0)
+                       break;
+               msleep(60);
+
+               state->m_Regs[EP4] &= ~0x03;  /* CAL_Mode = 0 */
+               state->m_Regs[EP3] &= ~0x40; /* SM_LT = 0 */
+               state->m_Regs[EB18] &= ~0x03;  /* AGC1_Gain = 0 */
+               status = UpdateReg(state, EB18);
+               if (status < 0)
+                       break;
+               status = UpdateRegs(state, EP3, EP4);
+               if (status < 0)
+                       break;
+               status = UpdateReg(state, EP1);
+               if (status < 0)
+                       break;
+
+               status = ReadExtented(state, Regs);
+               if (status < 0)
+                       break;
+
+               *pCprog = Regs[EB14];
+
+       } while (0);
+       return status;
+}
+
+static int RFTrackingFiltersInit(struct tda_state *state,
+                                u8 RFBand)
+{
+       int status = 0;
+
+       u32   RF1 = m_RF_Band_Map[RFBand].m_RF1_Default;
+       u32   RF2 = m_RF_Band_Map[RFBand].m_RF2_Default;
+       u32   RF3 = m_RF_Band_Map[RFBand].m_RF3_Default;
+       bool    bcal = false;
+
+       s32    Cprog_cal1 = 0;
+       s32    Cprog_table1 = 0;
+       s32    Cprog_cal2 = 0;
+       s32    Cprog_table2 = 0;
+       s32    Cprog_cal3 = 0;
+       s32    Cprog_table3 = 0;
+
+       state->m_RF_A1[RFBand] = 0;
+       state->m_RF_B1[RFBand] = 0;
+       state->m_RF_A2[RFBand] = 0;
+       state->m_RF_B2[RFBand] = 0;
+
+       do {
+               status = PowerScan(state, RFBand, RF1, &RF1, &bcal);
+               if (status < 0)
+                       break;
+               if (bcal) {
+                       status = CalibrateRF(state, RFBand, RF1, &Cprog_cal1);
+                       if (status < 0)
+                               break;
+               }
+               SearchMap2(m_RF_Cal_Map, RF1, &Cprog_table1);
+               if (!bcal)
+                       Cprog_cal1 = Cprog_table1;
+               state->m_RF_B1[RFBand] = Cprog_cal1 - Cprog_table1;
+               /* state->m_RF_A1[RF_Band] = ???? */
+
+               if (RF2 == 0)
+                       break;
+
+               status = PowerScan(state, RFBand, RF2, &RF2, &bcal);
+               if (status < 0)
+                       break;
+               if (bcal) {
+                       status = CalibrateRF(state, RFBand, RF2, &Cprog_cal2);
+                       if (status < 0)
+                               break;
+               }
+               SearchMap2(m_RF_Cal_Map, RF2, &Cprog_table2);
+               if (!bcal)
+                       Cprog_cal2 = Cprog_table2;
+
+               state->m_RF_A1[RFBand] =
+                       (Cprog_cal2 - Cprog_table2 - Cprog_cal1 + Cprog_table1) /
+                       ((s32)(RF2) - (s32)(RF1));
+
+               if (RF3 == 0)
+                       break;
+
+               status = PowerScan(state, RFBand, RF3, &RF3, &bcal);
+               if (status < 0)
+                       break;
+               if (bcal) {
+                       status = CalibrateRF(state, RFBand, RF3, &Cprog_cal3);
+                       if (status < 0)
+                               break;
+               }
+               SearchMap2(m_RF_Cal_Map, RF3, &Cprog_table3);
+               if (!bcal)
+                       Cprog_cal3 = Cprog_table3;
+               state->m_RF_A2[RFBand] = (Cprog_cal3 - Cprog_table3 - Cprog_cal2 + Cprog_table2) / ((s32)(RF3) - (s32)(RF2));
+               state->m_RF_B2[RFBand] = Cprog_cal2 - Cprog_table2;
+
+       } while (0);
+
+       state->m_RF1[RFBand] = RF1;
+       state->m_RF2[RFBand] = RF2;
+       state->m_RF3[RFBand] = RF3;
+
+#if 0
+       printk(KERN_ERR "tda18271c2dd: %s %d RF1 = %d A1 = %d B1 = %d RF2 = %d A2 = %d B2 = %d RF3 = %d\n", __func__,
+              RFBand, RF1, state->m_RF_A1[RFBand], state->m_RF_B1[RFBand], RF2,
+              state->m_RF_A2[RFBand], state->m_RF_B2[RFBand], RF3);
+#endif
+
+       return status;
+}
+
+static int PowerScan(struct tda_state *state,
+                    u8 RFBand, u32 RF_in, u32 *pRF_Out, bool *pbcal)
+{
+       int status = 0;
+       do {
+               u8   Gain_Taper = 0;
+               s32  RFC_Cprog = 0;
+               u8   CID_Target = 0;
+               u8   CountLimit = 0;
+               u32  freq_MainPLL;
+               u8   Regs[NUM_REGS];
+               u8   CID_Gain;
+               s32  Count = 0;
+               int  sign  = 1;
+               bool wait = false;
+
+               if (!(SearchMap2(m_RF_Cal_Map, RF_in, &RFC_Cprog) &&
+                     SearchMap1(m_GainTaper_Map, RF_in, &Gain_Taper) &&
+                     SearchMap3(m_CID_Target_Map, RF_in, &CID_Target, &CountLimit))) {
+
+                       printk(KERN_ERR "tda18271c2dd: %s Search map failed\n", __func__);
+                       return -EINVAL;
+               }
+
+               state->m_Regs[EP2] = (RFBand << 5) | Gain_Taper;
+               state->m_Regs[EB14] = (RFC_Cprog);
+               status = UpdateReg(state, EP2);
+               if (status < 0)
+                       break;
+               status = UpdateReg(state, EB14);
+               if (status < 0)
+                       break;
+
+               freq_MainPLL = RF_in + 1000000;
+               status = CalcMainPLL(state, freq_MainPLL);
+               if (status < 0)
+                       break;
+               msleep(5);
+               state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x03) | 1;    /* CAL_mode = 1 */
+               status = UpdateReg(state, EP4);
+               if (status < 0)
+                       break;
+               status = UpdateReg(state, EP2);  /* Launch power measurement */
+               if (status < 0)
+                       break;
+               status = ReadExtented(state, Regs);
+               if (status < 0)
+                       break;
+               CID_Gain = Regs[EB10] & 0x3F;
+               state->m_Regs[ID] = Regs[ID];  /* Chip version, (needed for C1 workarround in CalibrateRF) */
+
+               *pRF_Out = RF_in;
+
+               while (CID_Gain < CID_Target) {
+                       freq_MainPLL = RF_in + sign * Count + 1000000;
+                       status = CalcMainPLL(state, freq_MainPLL);
+                       if (status < 0)
+                               break;
+                       msleep(wait ? 5 : 1);
+                       wait = false;
+                       status = UpdateReg(state, EP2);  /* Launch power measurement */
+                       if (status < 0)
+                               break;
+                       status = ReadExtented(state, Regs);
+                       if (status < 0)
+                               break;
+                       CID_Gain = Regs[EB10] & 0x3F;
+                       Count += 200000;
+
+                       if (Count < CountLimit * 100000)
+                               continue;
+                       if (sign < 0)
+                               break;
+
+                       sign = -sign;
+                       Count = 200000;
+                       wait = true;
+               }
+               status = status;
+               if (status < 0)
+                       break;
+               if (CID_Gain >= CID_Target) {
+                       *pbcal = true;
+                       *pRF_Out = freq_MainPLL - 1000000;
+               } else
+                       *pbcal = false;
+       } while (0);
+
+       return status;
+}
+
+static int PowerScanInit(struct tda_state *state)
+{
+       int status = 0;
+       do {
+               state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | 0x12;
+               state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x1F); /* If level = 0, Cal mode = 0 */
+               status = UpdateRegs(state, EP3, EP4);
+               if (status < 0)
+                       break;
+               state->m_Regs[EB18] = (state->m_Regs[EB18] & ~0x03); /* AGC 1 Gain = 0 */
+               status = UpdateReg(state, EB18);
+               if (status < 0)
+                       break;
+               state->m_Regs[EB21] = (state->m_Regs[EB21] & ~0x03); /* AGC 2 Gain = 0 (Datasheet = 3) */
+               state->m_Regs[EB23] = (state->m_Regs[EB23] | 0x06); /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
+               status = UpdateRegs(state, EB21, EB23);
+               if (status < 0)
+                       break;
+       } while (0);
+       return status;
+}
+
+static int CalcRFFilterCurve(struct tda_state *state)
+{
+       int status = 0;
+       do {
+               msleep(200);      /* Temperature stabilisation */
+               status = PowerScanInit(state);
+               if (status < 0)
+                       break;
+               status = RFTrackingFiltersInit(state, 0);
+               if (status < 0)
+                       break;
+               status = RFTrackingFiltersInit(state, 1);
+               if (status < 0)
+                       break;
+               status = RFTrackingFiltersInit(state, 2);
+               if (status < 0)
+                       break;
+               status = RFTrackingFiltersInit(state, 3);
+               if (status < 0)
+                       break;
+               status = RFTrackingFiltersInit(state, 4);
+               if (status < 0)
+                       break;
+               status = RFTrackingFiltersInit(state, 5);
+               if (status < 0)
+                       break;
+               status = RFTrackingFiltersInit(state, 6);
+               if (status < 0)
+                       break;
+               status = ThermometerRead(state, &state->m_TMValue_RFCal); /* also switches off Cal mode !!! */
+               if (status < 0)
+                       break;
+       } while (0);
+
+       return status;
+}
+
+static int FixedContentsI2CUpdate(struct tda_state *state)
+{
+       static u8 InitRegs[] = {
+               0x08, 0x80, 0xC6,
+               0xDF, 0x16, 0x60, 0x80,
+               0x80, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00,
+               0xFC, 0x01, 0x84, 0x41,
+               0x01, 0x84, 0x40, 0x07,
+               0x00, 0x00, 0x96, 0x3F,
+               0xC1, 0x00, 0x8F, 0x00,
+               0x00, 0x8C, 0x00, 0x20,
+               0xB3, 0x48, 0xB0,
+       };
+       int status = 0;
+       memcpy(&state->m_Regs[TM], InitRegs, EB23 - TM + 1);
+       do {
+               status = UpdateRegs(state, TM, EB23);
+               if (status < 0)
+                       break;
+
+               /* AGC1 gain setup */
+               state->m_Regs[EB17] = 0x00;
+               status = UpdateReg(state, EB17);
+               if (status < 0)
+                       break;
+               state->m_Regs[EB17] = 0x03;
+               status = UpdateReg(state, EB17);
+               if (status < 0)
+                       break;
+               state->m_Regs[EB17] = 0x43;
+               status = UpdateReg(state, EB17);
+               if (status < 0)
+                       break;
+               state->m_Regs[EB17] = 0x4C;
+               status = UpdateReg(state, EB17);
+               if (status < 0)
+                       break;
+
+               /* IRC Cal Low band */
+               state->m_Regs[EP3] = 0x1F;
+               state->m_Regs[EP4] = 0x66;
+               state->m_Regs[EP5] = 0x81;
+               state->m_Regs[CPD] = 0xCC;
+               state->m_Regs[CD1] = 0x6C;
+               state->m_Regs[CD2] = 0x00;
+               state->m_Regs[CD3] = 0x00;
+               state->m_Regs[MPD] = 0xC5;
+               state->m_Regs[MD1] = 0x77;
+               state->m_Regs[MD2] = 0x08;
+               state->m_Regs[MD3] = 0x00;
+               status = UpdateRegs(state, EP2, MD3); /* diff between sw and datasheet (ep3-md3) */
+               if (status < 0)
+                       break;
+
+#if 0
+               state->m_Regs[EB4] = 0x61;          /* missing in sw */
+               status = UpdateReg(state, EB4);
+               if (status < 0)
+                       break;
+               msleep(1);
+               state->m_Regs[EB4] = 0x41;
+               status = UpdateReg(state, EB4);
+               if (status < 0)
+                       break;
+#endif
+
+               msleep(5);
+               status = UpdateReg(state, EP1);
+               if (status < 0)
+                       break;
+               msleep(5);
+
+               state->m_Regs[EP5] = 0x85;
+               state->m_Regs[CPD] = 0xCB;
+               state->m_Regs[CD1] = 0x66;
+               state->m_Regs[CD2] = 0x70;
+               status = UpdateRegs(state, EP3, CD3);
+               if (status < 0)
+                       break;
+               msleep(5);
+               status = UpdateReg(state, EP2);
+               if (status < 0)
+                       break;
+               msleep(30);
+
+               /* IRC Cal mid band */
+               state->m_Regs[EP5] = 0x82;
+               state->m_Regs[CPD] = 0xA8;
+               state->m_Regs[CD2] = 0x00;
+               state->m_Regs[MPD] = 0xA1; /* Datasheet = 0xA9 */
+               state->m_Regs[MD1] = 0x73;
+               state->m_Regs[MD2] = 0x1A;
+               status = UpdateRegs(state, EP3, MD3);
+               if (status < 0)
+                       break;
+
+               msleep(5);
+               status = UpdateReg(state, EP1);
+               if (status < 0)
+                       break;
+               msleep(5);
+
+               state->m_Regs[EP5] = 0x86;
+               state->m_Regs[CPD] = 0xA8;
+               state->m_Regs[CD1] = 0x66;
+               state->m_Regs[CD2] = 0xA0;
+               status = UpdateRegs(state, EP3, CD3);
+               if (status < 0)
+                       break;
+               msleep(5);
+               status = UpdateReg(state, EP2);
+               if (status < 0)
+                       break;
+               msleep(30);
+
+               /* IRC Cal high band */
+               state->m_Regs[EP5] = 0x83;
+               state->m_Regs[CPD] = 0x98;
+               state->m_Regs[CD1] = 0x65;
+               state->m_Regs[CD2] = 0x00;
+               state->m_Regs[MPD] = 0x91;  /* Datasheet = 0x91 */
+               state->m_Regs[MD1] = 0x71;
+               state->m_Regs[MD2] = 0xCD;
+               status = UpdateRegs(state, EP3, MD3);
+               if (status < 0)
+                       break;
+               msleep(5);
+               status = UpdateReg(state, EP1);
+               if (status < 0)
+                       break;
+               msleep(5);
+               state->m_Regs[EP5] = 0x87;
+               state->m_Regs[CD1] = 0x65;
+               state->m_Regs[CD2] = 0x50;
+               status = UpdateRegs(state, EP3, CD3);
+               if (status < 0)
+                       break;
+               msleep(5);
+               status = UpdateReg(state, EP2);
+               if (status < 0)
+                       break;
+               msleep(30);
+
+               /* Back to normal */
+               state->m_Regs[EP4] = 0x64;
+               status = UpdateReg(state, EP4);
+               if (status < 0)
+                       break;
+               status = UpdateReg(state, EP1);
+               if (status < 0)
+                       break;
+
+       } while (0);
+       return status;
+}
+
+static int InitCal(struct tda_state *state)
+{
+       int status = 0;
+
+       do {
+               status = FixedContentsI2CUpdate(state);
+               if (status < 0)
+                       break;
+               status = CalcRFFilterCurve(state);
+               if (status < 0)
+                       break;
+               status = StandBy(state);
+               if (status < 0)
+                       break;
+               /* m_bInitDone = true; */
+       } while (0);
+       return status;
+};
+
+static int RFTrackingFiltersCorrection(struct tda_state *state,
+                                      u32 Frequency)
+{
+       int status = 0;
+       s32 Cprog_table;
+       u8 RFBand;
+       u8 dCoverdT;
+
+       if (!SearchMap2(m_RF_Cal_Map, Frequency, &Cprog_table) ||
+           !SearchMap4(m_RF_Band_Map, Frequency, &RFBand) ||
+           !SearchMap1(m_RF_Cal_DC_Over_DT_Map, Frequency, &dCoverdT))
+
+               return -EINVAL;
+
+       do {
+               u8 TMValue_Current;
+               u32   RF1 = state->m_RF1[RFBand];
+               u32   RF2 = state->m_RF1[RFBand];
+               u32   RF3 = state->m_RF1[RFBand];
+               s32    RF_A1 = state->m_RF_A1[RFBand];
+               s32    RF_B1 = state->m_RF_B1[RFBand];
+               s32    RF_A2 = state->m_RF_A2[RFBand];
+               s32    RF_B2 = state->m_RF_B2[RFBand];
+               s32 Capprox = 0;
+               int TComp;
+
+               state->m_Regs[EP3] &= ~0xE0;  /* Power up */
+               status = UpdateReg(state, EP3);
+               if (status < 0)
+                       break;
+
+               status = ThermometerRead(state, &TMValue_Current);
+               if (status < 0)
+                       break;
+
+               if (RF3 == 0 || Frequency < RF2)
+                       Capprox = RF_A1 * ((s32)(Frequency) - (s32)(RF1)) + RF_B1 + Cprog_table;
+               else
+                       Capprox = RF_A2 * ((s32)(Frequency) - (s32)(RF2)) + RF_B2 + Cprog_table;
+
+               TComp = (int)(dCoverdT) * ((int)(TMValue_Current) - (int)(state->m_TMValue_RFCal))/1000;
+
+               Capprox += TComp;
+
+               if (Capprox < 0)
+                       Capprox = 0;
+               else if (Capprox > 255)
+                       Capprox = 255;
+
+
+               /* TODO Temperature compensation. There is defenitely a scale factor */
+               /*      missing in the datasheet, so leave it out for now.           */
+               state->m_Regs[EB14] = Capprox;
+
+               status = UpdateReg(state, EB14);
+               if (status < 0)
+                       break;
+
+       } while (0);
+       return status;
+}
+
+static int ChannelConfiguration(struct tda_state *state,
+                               u32 Frequency, int Standard)
+{
+
+       s32 IntermediateFrequency = m_StandardTable[Standard].m_IFFrequency;
+       int status = 0;
+
+       u8 BP_Filter = 0;
+       u8 RF_Band = 0;
+       u8 GainTaper = 0;
+       u8 IR_Meas = 0;
+
+       state->IF = IntermediateFrequency;
+       /* printk("tda18271c2dd: %s Freq = %d Standard = %d IF = %d\n", __func__, Frequency, Standard, IntermediateFrequency); */
+       /* get values from tables */
+
+       if (!(SearchMap1(m_BP_Filter_Map, Frequency, &BP_Filter) &&
+              SearchMap1(m_GainTaper_Map, Frequency, &GainTaper) &&
+              SearchMap1(m_IR_Meas_Map, Frequency, &IR_Meas) &&
+              SearchMap4(m_RF_Band_Map, Frequency, &RF_Band))) {
+
+               printk(KERN_ERR "tda18271c2dd: %s SearchMap failed\n", __func__);
+               return -EINVAL;
+       }
+
+       do {
+               state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | m_StandardTable[Standard].m_EP3_4_0;
+               state->m_Regs[EP3] &= ~0x04;   /* switch RFAGC to high speed mode */
+
+               /* m_EP4 default for XToutOn, CAL_Mode (0) */
+               state->m_Regs[EP4] = state->m_EP4 | ((Standard > HF_AnalogMax) ? state->m_IFLevelDigital : state->m_IFLevelAnalog);
+               /* state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital; */
+               if (Standard <= HF_AnalogMax)
+                       state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelAnalog;
+               else if (Standard <= HF_ATSC)
+                       state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBT;
+               else if (Standard <= HF_DVBC)
+                       state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBC;
+               else
+                       state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
+
+               if ((Standard == HF_FM_Radio) && state->m_bFMInput)
+                       state->m_Regs[EP4] |= 80;
+
+               state->m_Regs[MPD] &= ~0x80;
+               if (Standard > HF_AnalogMax)
+                       state->m_Regs[MPD] |= 0x80; /* Add IF_notch for digital */
+
+               state->m_Regs[EB22] = m_StandardTable[Standard].m_EB22;
+
+               /* Note: This is missing from flowchart in TDA18271 specification ( 1.5 MHz cutoff for FM ) */
+               if (Standard == HF_FM_Radio)
+                       state->m_Regs[EB23] |=  0x06; /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
+               else
+                       state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LPFc[2] = 0 */
+
+               status = UpdateRegs(state, EB22, EB23);
+               if (status < 0)
+                       break;
+
+               state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | 0x40 | BP_Filter;   /* Dis_Power_level = 1, Filter */
+               state->m_Regs[EP5] = (state->m_Regs[EP5] & ~0x07) | IR_Meas;
+               state->m_Regs[EP2] = (RF_Band << 5) | GainTaper;
+
+               state->m_Regs[EB1] = (state->m_Regs[EB1] & ~0x07) |
+                       (state->m_bMaster ? 0x04 : 0x00); /* CALVCO_FortLOn = MS */
+               /* AGC1_always_master = 0 */
+               /* AGC_firstn = 0 */
+               status = UpdateReg(state, EB1);
+               if (status < 0)
+                       break;
+
+               if (state->m_bMaster) {
+                       status = CalcMainPLL(state, Frequency + IntermediateFrequency);
+                       if (status < 0)
+                               break;
+                       status = UpdateRegs(state, TM, EP5);
+                       if (status < 0)
+                               break;
+                       state->m_Regs[EB4] |= 0x20;    /* LO_forceSrce = 1 */
+                       status = UpdateReg(state, EB4);
+                       if (status < 0)
+                               break;
+                       msleep(1);
+                       state->m_Regs[EB4] &= ~0x20;   /* LO_forceSrce = 0 */
+                       status = UpdateReg(state, EB4);
+                       if (status < 0)
+                               break;
+               } else {
+                       u8 PostDiv = 0;
+                       u8 Div;
+                       status = CalcCalPLL(state, Frequency + IntermediateFrequency);
+                       if (status < 0)
+                               break;
+
+                       SearchMap3(m_Cal_PLL_Map, Frequency + IntermediateFrequency, &PostDiv, &Div);
+                       state->m_Regs[MPD] = (state->m_Regs[MPD] & ~0x7F) | (PostDiv & 0x77);
+                       status = UpdateReg(state, MPD);
+                       if (status < 0)
+                               break;
+                       status = UpdateRegs(state, TM, EP5);
+                       if (status < 0)
+                               break;
+
+                       state->m_Regs[EB7] |= 0x20;    /* CAL_forceSrce = 1 */
+                       status = UpdateReg(state, EB7);
+                       if (status < 0)
+                               break;
+                       msleep(1);
+                       state->m_Regs[EB7] &= ~0x20;   /* CAL_forceSrce = 0 */
+                       status = UpdateReg(state, EB7);
+                       if (status < 0)
+                               break;
+               }
+               msleep(20);
+               if (Standard != HF_FM_Radio)
+                       state->m_Regs[EP3] |= 0x04;    /* RFAGC to normal mode */
+               status = UpdateReg(state, EP3);
+               if (status < 0)
+                       break;
+
+       } while (0);
+       return status;
+}
+
+static int sleep(struct dvb_frontend *fe)
+{
+       struct tda_state *state = fe->tuner_priv;
+
+       StandBy(state);
+       return 0;
+}
+
+static int init(struct dvb_frontend *fe)
+{
+       return 0;
+}
+
+static int release(struct dvb_frontend *fe)
+{
+       kfree(fe->tuner_priv);
+       fe->tuner_priv = NULL;
+       return 0;
+}
+
+/*
+ * As defined on EN 300 429 Annex A and on ITU-T J.83 annex A, the DVB-C
+ * roll-off factor is 0.15.
+ * According with the specs, the amount of the needed bandwith is given by:
+ *     Bw = Symbol_rate * (1 + 0.15)
+ * As such, the maximum symbol rate supported by 6 MHz is
+ *     max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
+ *NOTE: For ITU-T J.83 Annex C, the roll-off factor is 0.13. So:
+ *     max_symbol_rate = 6 MHz / 1.13 = 5309735 Baud
+ *     That means that an adjustment is needed for Japan,
+ *     but, as currently DRX-K is hardcoded to Annex A, let's stick
+ *     with 0.15 roll-off factor.
+ */
+#define MAX_SYMBOL_RATE_6MHz   5217391
+
+static int set_params(struct dvb_frontend *fe,
+                     struct dvb_frontend_parameters *params)
+{
+       struct tda_state *state = fe->tuner_priv;
+       int status = 0;
+       int Standard;
+
+       state->m_Frequency = params->frequency;
+
+       if (fe->ops.info.type == FE_OFDM)
+               switch (params->u.ofdm.bandwidth) {
+               case BANDWIDTH_6_MHZ:
+                       Standard = HF_DVBT_6MHZ;
+                       break;
+               case BANDWIDTH_7_MHZ:
+                       Standard = HF_DVBT_7MHZ;
+                       break;
+               default:
+               case BANDWIDTH_8_MHZ:
+                       Standard = HF_DVBT_8MHZ;
+                       break;
+               }
+       else if (fe->ops.info.type == FE_QAM) {
+               if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz)
+                       Standard = HF_DVBC_6MHZ;
+               else
+                       Standard = HF_DVBC_8MHZ;
+       } else
+               return -EINVAL;
+       do {
+               status = RFTrackingFiltersCorrection(state, params->frequency);
+               if (status < 0)
+                       break;
+               status = ChannelConfiguration(state, params->frequency, Standard);
+               if (status < 0)
+                       break;
+
+               msleep(state->m_SettlingTime);  /* Allow AGC's to settle down */
+       } while (0);
+       return status;
+}
+
+#if 0
+static int GetSignalStrength(s32 *pSignalStrength, u32 RFAgc, u32 IFAgc)
+{
+       if (IFAgc < 500) {
+               /* Scale this from 0 to 50000 */
+               *pSignalStrength = IFAgc * 100;
+       } else {
+               /* Scale range 500-1500 to 50000-80000 */
+               *pSignalStrength = 50000 + (IFAgc - 500) * 30;
+       }
+
+       return 0;
+}
+#endif
+
+static int get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct tda_state *state = fe->tuner_priv;
+
+       *frequency = state->IF;
+       return 0;
+}
+
+static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+       /* struct tda_state *state = fe->tuner_priv; */
+       /* *bandwidth = priv->bandwidth; */
+       return 0;
+}
+
+
+static struct dvb_tuner_ops tuner_ops = {
+       .info = {
+               .name = "NXP TDA18271C2D",
+               .frequency_min  =  47125000,
+               .frequency_max  = 865000000,
+               .frequency_step =     62500
+       },
+       .init              = init,
+       .sleep             = sleep,
+       .set_params        = set_params,
+       .release           = release,
+       .get_frequency     = get_frequency,
+       .get_bandwidth     = get_bandwidth,
+};
+
+struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
+                                        struct i2c_adapter *i2c, u8 adr)
+{
+       struct tda_state *state;
+
+       state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
+       if (!state)
+               return NULL;
+
+       fe->tuner_priv = state;
+       state->adr = adr;
+       state->i2c = i2c;
+       memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
+       reset(state);
+       InitCal(state);
+
+       return fe;
+}
+EXPORT_SYMBOL_GPL(tda18271c2dd_attach);
+
+MODULE_DESCRIPTION("TDA18271C2 driver");
+MODULE_AUTHOR("DD");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda18271c2dd.h b/drivers/media/dvb/frontends/tda18271c2dd.h
new file mode 100644 (file)
index 0000000..1389c74
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _TDA18271C2DD_H_
+#define _TDA18271C2DD_H_
+#if defined(CONFIG_DVB_TDA18271C2DD) || (defined(CONFIG_DVB_TDA18271C2DD_MODULE) \
+        && defined(MODULE))
+struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
+                                        struct i2c_adapter *i2c, u8 adr);
+#else
+static inline struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
+                                        struct i2c_adapter *i2c, u8 adr)
+{
+        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+        return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb/frontends/tda18271c2dd_maps.h b/drivers/media/dvb/frontends/tda18271c2dd_maps.h
new file mode 100644 (file)
index 0000000..b87661b
--- /dev/null
@@ -0,0 +1,814 @@
+enum HF_S {
+       HF_None = 0, HF_B, HF_DK, HF_G, HF_I, HF_L, HF_L1, HF_MN, HF_FM_Radio,
+       HF_AnalogMax, HF_DVBT_6MHZ, HF_DVBT_7MHZ, HF_DVBT_8MHZ,
+       HF_DVBT, HF_ATSC,  HF_DVBC_6MHZ,  HF_DVBC_7MHZ,
+       HF_DVBC_8MHZ, HF_DVBC
+};
+
+struct SStandardParam m_StandardTable[] = {
+       {       0,        0, 0x00, 0x00 },    /* HF_None */
+       { 6000000,  7000000, 0x1D, 0x2C },    /* HF_B, */
+       { 6900000,  8000000, 0x1E, 0x2C },    /* HF_DK, */
+       { 7100000,  8000000, 0x1E, 0x2C },    /* HF_G, */
+       { 7250000,  8000000, 0x1E, 0x2C },    /* HF_I, */
+       { 6900000,  8000000, 0x1E, 0x2C },    /* HF_L, */
+       { 1250000,  8000000, 0x1E, 0x2C },    /* HF_L1, */
+       { 5400000,  6000000, 0x1C, 0x2C },    /* HF_MN, */
+       { 1250000,   500000, 0x18, 0x2C },    /* HF_FM_Radio, */
+       {       0,        0, 0x00, 0x00 },    /* HF_AnalogMax (Unused) */
+       { 3300000,  6000000, 0x1C, 0x58 },    /* HF_DVBT_6MHZ */
+       { 3500000,  7000000, 0x1C, 0x37 },    /* HF_DVBT_7MHZ */
+       { 4000000,  8000000, 0x1D, 0x37 },    /* HF_DVBT_8MHZ */
+       {       0,        0, 0x00, 0x00 },    /* HF_DVBT (Unused) */
+       { 5000000,  6000000, 0x1C, 0x37 },    /* HF_ATSC  (center = 3.25 MHz) */
+       { 4000000,  6000000, 0x1D, 0x58 },    /* HF_DVBC_6MHZ (Chicago) */
+       { 4500000,  7000000, 0x1E, 0x37 },    /* HF_DVBC_7MHZ (not documented by NXP) */
+       { 5000000,  8000000, 0x1F, 0x37 },    /* HF_DVBC_8MHZ */
+       {       0,        0, 0x00, 0x00 },    /* HF_DVBC (Unused) */
+};
+
+struct SMap  m_BP_Filter_Map[] = {
+       {   62000000,  0x00 },
+       {   84000000,  0x01 },
+       {  100000000,  0x02 },
+       {  140000000,  0x03 },
+       {  170000000,  0x04 },
+       {  180000000,  0x05 },
+       {  865000000,  0x06 },
+       {          0,  0x00 },    /* Table End */
+};
+
+static struct SMapI m_RF_Cal_Map[] = {
+       {   41000000,  0x0F },
+       {   43000000,  0x1C },
+       {   45000000,  0x2F },
+       {   46000000,  0x39 },
+       {   47000000,  0x40 },
+       {   47900000,  0x50 },
+       {   49100000,  0x16 },
+       {   50000000,  0x18 },
+       {   51000000,  0x20 },
+       {   53000000,  0x28 },
+       {   55000000,  0x2B },
+       {   56000000,  0x32 },
+       {   57000000,  0x35 },
+       {   58000000,  0x3E },
+       {   59000000,  0x43 },
+       {   60000000,  0x4E },
+       {   61100000,  0x55 },
+       {   63000000,  0x0F },
+       {   64000000,  0x11 },
+       {   65000000,  0x12 },
+       {   66000000,  0x15 },
+       {   67000000,  0x16 },
+       {   68000000,  0x17 },
+       {   70000000,  0x19 },
+       {   71000000,  0x1C },
+       {   72000000,  0x1D },
+       {   73000000,  0x1F },
+       {   74000000,  0x20 },
+       {   75000000,  0x21 },
+       {   76000000,  0x24 },
+       {   77000000,  0x25 },
+       {   78000000,  0x27 },
+       {   80000000,  0x28 },
+       {   81000000,  0x29 },
+       {   82000000,  0x2D },
+       {   83000000,  0x2E },
+       {   84000000,  0x2F },
+       {   85000000,  0x31 },
+       {   86000000,  0x33 },
+       {   87000000,  0x34 },
+       {   88000000,  0x35 },
+       {   89000000,  0x37 },
+       {   90000000,  0x38 },
+       {   91000000,  0x39 },
+       {   93000000,  0x3C },
+       {   94000000,  0x3E },
+       {   95000000,  0x3F },
+       {   96000000,  0x40 },
+       {   97000000,  0x42 },
+       {   99000000,  0x45 },
+       {  100000000,  0x46 },
+       {  102000000,  0x48 },
+       {  103000000,  0x4A },
+       {  105000000,  0x4D },
+       {  106000000,  0x4E },
+       {  107000000,  0x50 },
+       {  108000000,  0x51 },
+       {  110000000,  0x54 },
+       {  111000000,  0x56 },
+       {  112000000,  0x57 },
+       {  113000000,  0x58 },
+       {  114000000,  0x59 },
+       {  115000000,  0x5C },
+       {  116000000,  0x5D },
+       {  117000000,  0x5F },
+       {  119000000,  0x60 },
+       {  120000000,  0x64 },
+       {  121000000,  0x65 },
+       {  122000000,  0x66 },
+       {  123000000,  0x68 },
+       {  124000000,  0x69 },
+       {  125000000,  0x6C },
+       {  126000000,  0x6D },
+       {  127000000,  0x6E },
+       {  128000000,  0x70 },
+       {  129000000,  0x71 },
+       {  130000000,  0x75 },
+       {  131000000,  0x77 },
+       {  132000000,  0x78 },
+       {  133000000,  0x7B },
+       {  134000000,  0x7E },
+       {  135000000,  0x81 },
+       {  136000000,  0x82 },
+       {  137000000,  0x87 },
+       {  138000000,  0x88 },
+       {  139000000,  0x8D },
+       {  140000000,  0x8E },
+       {  141000000,  0x91 },
+       {  142000000,  0x95 },
+       {  143000000,  0x9A },
+       {  144000000,  0x9D },
+       {  145000000,  0xA1 },
+       {  146000000,  0xA2 },
+       {  147000000,  0xA4 },
+       {  148000000,  0xA9 },
+       {  149000000,  0xAE },
+       {  150000000,  0xB0 },
+       {  151000000,  0xB1 },
+       {  152000000,  0xB7 },
+       {  152600000,  0xBD },
+       {  154000000,  0x20 },
+       {  155000000,  0x22 },
+       {  156000000,  0x24 },
+       {  157000000,  0x25 },
+       {  158000000,  0x27 },
+       {  159000000,  0x29 },
+       {  160000000,  0x2C },
+       {  161000000,  0x2D },
+       {  163000000,  0x2E },
+       {  164000000,  0x2F },
+       {  164700000,  0x30 },
+       {  166000000,  0x11 },
+       {  167000000,  0x12 },
+       {  168000000,  0x13 },
+       {  169000000,  0x14 },
+       {  170000000,  0x15 },
+       {  172000000,  0x16 },
+       {  173000000,  0x17 },
+       {  174000000,  0x18 },
+       {  175000000,  0x1A },
+       {  176000000,  0x1B },
+       {  178000000,  0x1D },
+       {  179000000,  0x1E },
+       {  180000000,  0x1F },
+       {  181000000,  0x20 },
+       {  182000000,  0x21 },
+       {  183000000,  0x22 },
+       {  184000000,  0x24 },
+       {  185000000,  0x25 },
+       {  186000000,  0x26 },
+       {  187000000,  0x27 },
+       {  188000000,  0x29 },
+       {  189000000,  0x2A },
+       {  190000000,  0x2C },
+       {  191000000,  0x2D },
+       {  192000000,  0x2E },
+       {  193000000,  0x2F },
+       {  194000000,  0x30 },
+       {  195000000,  0x33 },
+       {  196000000,  0x35 },
+       {  198000000,  0x36 },
+       {  200000000,  0x38 },
+       {  201000000,  0x3C },
+       {  202000000,  0x3D },
+       {  203500000,  0x3E },
+       {  206000000,  0x0E },
+       {  208000000,  0x0F },
+       {  212000000,  0x10 },
+       {  216000000,  0x11 },
+       {  217000000,  0x12 },
+       {  218000000,  0x13 },
+       {  220000000,  0x14 },
+       {  222000000,  0x15 },
+       {  225000000,  0x16 },
+       {  228000000,  0x17 },
+       {  231000000,  0x18 },
+       {  234000000,  0x19 },
+       {  235000000,  0x1A },
+       {  236000000,  0x1B },
+       {  237000000,  0x1C },
+       {  240000000,  0x1D },
+       {  242000000,  0x1E },
+       {  244000000,  0x1F },
+       {  247000000,  0x20 },
+       {  249000000,  0x21 },
+       {  252000000,  0x22 },
+       {  253000000,  0x23 },
+       {  254000000,  0x24 },
+       {  256000000,  0x25 },
+       {  259000000,  0x26 },
+       {  262000000,  0x27 },
+       {  264000000,  0x28 },
+       {  267000000,  0x29 },
+       {  269000000,  0x2A },
+       {  271000000,  0x2B },
+       {  273000000,  0x2C },
+       {  275000000,  0x2D },
+       {  277000000,  0x2E },
+       {  279000000,  0x2F },
+       {  282000000,  0x30 },
+       {  284000000,  0x31 },
+       {  286000000,  0x32 },
+       {  287000000,  0x33 },
+       {  290000000,  0x34 },
+       {  293000000,  0x35 },
+       {  295000000,  0x36 },
+       {  297000000,  0x37 },
+       {  300000000,  0x38 },
+       {  303000000,  0x39 },
+       {  305000000,  0x3A },
+       {  306000000,  0x3B },
+       {  307000000,  0x3C },
+       {  310000000,  0x3D },
+       {  312000000,  0x3E },
+       {  315000000,  0x3F },
+       {  318000000,  0x40 },
+       {  320000000,  0x41 },
+       {  323000000,  0x42 },
+       {  324000000,  0x43 },
+       {  325000000,  0x44 },
+       {  327000000,  0x45 },
+       {  331000000,  0x46 },
+       {  334000000,  0x47 },
+       {  337000000,  0x48 },
+       {  339000000,  0x49 },
+       {  340000000,  0x4A },
+       {  341000000,  0x4B },
+       {  343000000,  0x4C },
+       {  345000000,  0x4D },
+       {  349000000,  0x4E },
+       {  352000000,  0x4F },
+       {  353000000,  0x50 },
+       {  355000000,  0x51 },
+       {  357000000,  0x52 },
+       {  359000000,  0x53 },
+       {  361000000,  0x54 },
+       {  362000000,  0x55 },
+       {  364000000,  0x56 },
+       {  368000000,  0x57 },
+       {  370000000,  0x58 },
+       {  372000000,  0x59 },
+       {  375000000,  0x5A },
+       {  376000000,  0x5B },
+       {  377000000,  0x5C },
+       {  379000000,  0x5D },
+       {  382000000,  0x5E },
+       {  384000000,  0x5F },
+       {  385000000,  0x60 },
+       {  386000000,  0x61 },
+       {  388000000,  0x62 },
+       {  390000000,  0x63 },
+       {  393000000,  0x64 },
+       {  394000000,  0x65 },
+       {  396000000,  0x66 },
+       {  397000000,  0x67 },
+       {  398000000,  0x68 },
+       {  400000000,  0x69 },
+       {  402000000,  0x6A },
+       {  403000000,  0x6B },
+       {  407000000,  0x6C },
+       {  408000000,  0x6D },
+       {  409000000,  0x6E },
+       {  410000000,  0x6F },
+       {  411000000,  0x70 },
+       {  412000000,  0x71 },
+       {  413000000,  0x72 },
+       {  414000000,  0x73 },
+       {  417000000,  0x74 },
+       {  418000000,  0x75 },
+       {  420000000,  0x76 },
+       {  422000000,  0x77 },
+       {  423000000,  0x78 },
+       {  424000000,  0x79 },
+       {  427000000,  0x7A },
+       {  428000000,  0x7B },
+       {  429000000,  0x7D },
+       {  432000000,  0x7F },
+       {  434000000,  0x80 },
+       {  435000000,  0x81 },
+       {  436000000,  0x83 },
+       {  437000000,  0x84 },
+       {  438000000,  0x85 },
+       {  439000000,  0x86 },
+       {  440000000,  0x87 },
+       {  441000000,  0x88 },
+       {  442000000,  0x89 },
+       {  445000000,  0x8A },
+       {  446000000,  0x8B },
+       {  447000000,  0x8C },
+       {  448000000,  0x8E },
+       {  449000000,  0x8F },
+       {  450000000,  0x90 },
+       {  452000000,  0x91 },
+       {  453000000,  0x93 },
+       {  454000000,  0x94 },
+       {  456000000,  0x96 },
+       {  457800000,  0x98 },
+       {  461000000,  0x11 },
+       {  468000000,  0x12 },
+       {  472000000,  0x13 },
+       {  473000000,  0x14 },
+       {  474000000,  0x15 },
+       {  481000000,  0x16 },
+       {  486000000,  0x17 },
+       {  491000000,  0x18 },
+       {  498000000,  0x19 },
+       {  499000000,  0x1A },
+       {  501000000,  0x1B },
+       {  506000000,  0x1C },
+       {  511000000,  0x1D },
+       {  516000000,  0x1E },
+       {  520000000,  0x1F },
+       {  521000000,  0x20 },
+       {  525000000,  0x21 },
+       {  529000000,  0x22 },
+       {  533000000,  0x23 },
+       {  539000000,  0x24 },
+       {  541000000,  0x25 },
+       {  547000000,  0x26 },
+       {  549000000,  0x27 },
+       {  551000000,  0x28 },
+       {  556000000,  0x29 },
+       {  561000000,  0x2A },
+       {  563000000,  0x2B },
+       {  565000000,  0x2C },
+       {  569000000,  0x2D },
+       {  571000000,  0x2E },
+       {  577000000,  0x2F },
+       {  580000000,  0x30 },
+       {  582000000,  0x31 },
+       {  584000000,  0x32 },
+       {  588000000,  0x33 },
+       {  591000000,  0x34 },
+       {  596000000,  0x35 },
+       {  598000000,  0x36 },
+       {  603000000,  0x37 },
+       {  604000000,  0x38 },
+       {  606000000,  0x39 },
+       {  612000000,  0x3A },
+       {  615000000,  0x3B },
+       {  617000000,  0x3C },
+       {  621000000,  0x3D },
+       {  622000000,  0x3E },
+       {  625000000,  0x3F },
+       {  632000000,  0x40 },
+       {  633000000,  0x41 },
+       {  634000000,  0x42 },
+       {  642000000,  0x43 },
+       {  643000000,  0x44 },
+       {  647000000,  0x45 },
+       {  650000000,  0x46 },
+       {  652000000,  0x47 },
+       {  657000000,  0x48 },
+       {  661000000,  0x49 },
+       {  662000000,  0x4A },
+       {  665000000,  0x4B },
+       {  667000000,  0x4C },
+       {  670000000,  0x4D },
+       {  673000000,  0x4E },
+       {  676000000,  0x4F },
+       {  677000000,  0x50 },
+       {  681000000,  0x51 },
+       {  683000000,  0x52 },
+       {  686000000,  0x53 },
+       {  688000000,  0x54 },
+       {  689000000,  0x55 },
+       {  691000000,  0x56 },
+       {  695000000,  0x57 },
+       {  698000000,  0x58 },
+       {  703000000,  0x59 },
+       {  704000000,  0x5A },
+       {  705000000,  0x5B },
+       {  707000000,  0x5C },
+       {  710000000,  0x5D },
+       {  712000000,  0x5E },
+       {  717000000,  0x5F },
+       {  718000000,  0x60 },
+       {  721000000,  0x61 },
+       {  722000000,  0x62 },
+       {  723000000,  0x63 },
+       {  725000000,  0x64 },
+       {  727000000,  0x65 },
+       {  730000000,  0x66 },
+       {  732000000,  0x67 },
+       {  735000000,  0x68 },
+       {  740000000,  0x69 },
+       {  741000000,  0x6A },
+       {  742000000,  0x6B },
+       {  743000000,  0x6C },
+       {  745000000,  0x6D },
+       {  747000000,  0x6E },
+       {  748000000,  0x6F },
+       {  750000000,  0x70 },
+       {  752000000,  0x71 },
+       {  754000000,  0x72 },
+       {  757000000,  0x73 },
+       {  758000000,  0x74 },
+       {  760000000,  0x75 },
+       {  763000000,  0x76 },
+       {  764000000,  0x77 },
+       {  766000000,  0x78 },
+       {  767000000,  0x79 },
+       {  768000000,  0x7A },
+       {  773000000,  0x7B },
+       {  774000000,  0x7C },
+       {  776000000,  0x7D },
+       {  777000000,  0x7E },
+       {  778000000,  0x7F },
+       {  779000000,  0x80 },
+       {  781000000,  0x81 },
+       {  783000000,  0x82 },
+       {  784000000,  0x83 },
+       {  785000000,  0x84 },
+       {  786000000,  0x85 },
+       {  793000000,  0x86 },
+       {  794000000,  0x87 },
+       {  795000000,  0x88 },
+       {  797000000,  0x89 },
+       {  799000000,  0x8A },
+       {  801000000,  0x8B },
+       {  802000000,  0x8C },
+       {  803000000,  0x8D },
+       {  804000000,  0x8E },
+       {  810000000,  0x90 },
+       {  811000000,  0x91 },
+       {  812000000,  0x92 },
+       {  814000000,  0x93 },
+       {  816000000,  0x94 },
+       {  817000000,  0x96 },
+       {  818000000,  0x97 },
+       {  820000000,  0x98 },
+       {  821000000,  0x99 },
+       {  822000000,  0x9A },
+       {  828000000,  0x9B },
+       {  829000000,  0x9D },
+       {  830000000,  0x9F },
+       {  831000000,  0xA0 },
+       {  833000000,  0xA1 },
+       {  835000000,  0xA2 },
+       {  836000000,  0xA3 },
+       {  837000000,  0xA4 },
+       {  838000000,  0xA6 },
+       {  840000000,  0xA8 },
+       {  842000000,  0xA9 },
+       {  845000000,  0xAA },
+       {  846000000,  0xAB },
+       {  847000000,  0xAD },
+       {  848000000,  0xAE },
+       {  852000000,  0xAF },
+       {  853000000,  0xB0 },
+       {  858000000,  0xB1 },
+       {  860000000,  0xB2 },
+       {  861000000,  0xB3 },
+       {  862000000,  0xB4 },
+       {  863000000,  0xB6 },
+       {  864000000,  0xB8 },
+       {  865000000,  0xB9 },
+       {          0,  0x00 },    /* Table End */
+};
+
+
+static struct SMap2  m_KM_Map[] = {
+       {   47900000,  3, 2 },
+       {   61100000,  3, 1 },
+       {  350000000,  3, 0 },
+       {  720000000,  2, 1 },
+       {  865000000,  3, 3 },
+       {          0,  0x00 },    /* Table End */
+};
+
+static struct SMap2 m_Main_PLL_Map[] = {
+       {  33125000, 0x57, 0xF0 },
+       {  35500000, 0x56, 0xE0 },
+       {  38188000, 0x55, 0xD0 },
+       {  41375000, 0x54, 0xC0 },
+       {  45125000, 0x53, 0xB0 },
+       {  49688000, 0x52, 0xA0 },
+       {  55188000, 0x51, 0x90 },
+       {  62125000, 0x50, 0x80 },
+       {  66250000, 0x47, 0x78 },
+       {  71000000, 0x46, 0x70 },
+       {  76375000, 0x45, 0x68 },
+       {  82750000, 0x44, 0x60 },
+       {  90250000, 0x43, 0x58 },
+       {  99375000, 0x42, 0x50 },
+       { 110375000, 0x41, 0x48 },
+       { 124250000, 0x40, 0x40 },
+       { 132500000, 0x37, 0x3C },
+       { 142000000, 0x36, 0x38 },
+       { 152750000, 0x35, 0x34 },
+       { 165500000, 0x34, 0x30 },
+       { 180500000, 0x33, 0x2C },
+       { 198750000, 0x32, 0x28 },
+       { 220750000, 0x31, 0x24 },
+       { 248500000, 0x30, 0x20 },
+       { 265000000, 0x27, 0x1E },
+       { 284000000, 0x26, 0x1C },
+       { 305500000, 0x25, 0x1A },
+       { 331000000, 0x24, 0x18 },
+       { 361000000, 0x23, 0x16 },
+       { 397500000, 0x22, 0x14 },
+       { 441500000, 0x21, 0x12 },
+       { 497000000, 0x20, 0x10 },
+       { 530000000, 0x17, 0x0F },
+       { 568000000, 0x16, 0x0E },
+       { 611000000, 0x15, 0x0D },
+       { 662000000, 0x14, 0x0C },
+       { 722000000, 0x13, 0x0B },
+       { 795000000, 0x12, 0x0A },
+       { 883000000, 0x11, 0x09 },
+       { 994000000, 0x10, 0x08 },
+       {         0, 0x00, 0x00 },    /* Table End */
+};
+
+static struct SMap2 m_Cal_PLL_Map[] = {
+       {  33813000, 0xDD, 0xD0 },
+       {  36625000, 0xDC, 0xC0 },
+       {  39938000, 0xDB, 0xB0 },
+       {  43938000, 0xDA, 0xA0 },
+       {  48813000, 0xD9, 0x90 },
+       {  54938000, 0xD8, 0x80 },
+       {  62813000, 0xD3, 0x70 },
+       {  67625000, 0xCD, 0x68 },
+       {  73250000, 0xCC, 0x60 },
+       {  79875000, 0xCB, 0x58 },
+       {  87875000, 0xCA, 0x50 },
+       {  97625000, 0xC9, 0x48 },
+       { 109875000, 0xC8, 0x40 },
+       { 125625000, 0xC3, 0x38 },
+       { 135250000, 0xBD, 0x34 },
+       { 146500000, 0xBC, 0x30 },
+       { 159750000, 0xBB, 0x2C },
+       { 175750000, 0xBA, 0x28 },
+       { 195250000, 0xB9, 0x24 },
+       { 219750000, 0xB8, 0x20 },
+       { 251250000, 0xB3, 0x1C },
+       { 270500000, 0xAD, 0x1A },
+       { 293000000, 0xAC, 0x18 },
+       { 319500000, 0xAB, 0x16 },
+       { 351500000, 0xAA, 0x14 },
+       { 390500000, 0xA9, 0x12 },
+       { 439500000, 0xA8, 0x10 },
+       { 502500000, 0xA3, 0x0E },
+       { 541000000, 0x9D, 0x0D },
+       { 586000000, 0x9C, 0x0C },
+       { 639000000, 0x9B, 0x0B },
+       { 703000000, 0x9A, 0x0A },
+       { 781000000, 0x99, 0x09 },
+       { 879000000, 0x98, 0x08 },
+       {         0, 0x00, 0x00 },    /* Table End */
+};
+
+static struct SMap  m_GainTaper_Map[] = {
+       {  45400000, 0x1F },
+       {  45800000, 0x1E },
+       {  46200000, 0x1D },
+       {  46700000, 0x1C },
+       {  47100000, 0x1B },
+       {  47500000, 0x1A },
+       {  47900000, 0x19 },
+       {  49600000, 0x17 },
+       {  51200000, 0x16 },
+       {  52900000, 0x15 },
+       {  54500000, 0x14 },
+       {  56200000, 0x13 },
+       {  57800000, 0x12 },
+       {  59500000, 0x11 },
+       {  61100000, 0x10 },
+       {  67600000, 0x0D },
+       {  74200000, 0x0C },
+       {  80700000, 0x0B },
+       {  87200000, 0x0A },
+       {  93800000, 0x09 },
+       { 100300000, 0x08 },
+       { 106900000, 0x07 },
+       { 113400000, 0x06 },
+       { 119900000, 0x05 },
+       { 126500000, 0x04 },
+       { 133000000, 0x03 },
+       { 139500000, 0x02 },
+       { 146100000, 0x01 },
+       { 152600000, 0x00 },
+       { 154300000, 0x1F },
+       { 156100000, 0x1E },
+       { 157800000, 0x1D },
+       { 159500000, 0x1C },
+       { 161200000, 0x1B },
+       { 163000000, 0x1A },
+       { 164700000, 0x19 },
+       { 170200000, 0x17 },
+       { 175800000, 0x16 },
+       { 181300000, 0x15 },
+       { 186900000, 0x14 },
+       { 192400000, 0x13 },
+       { 198000000, 0x12 },
+       { 203500000, 0x11 },
+       { 216200000, 0x14 },
+       { 228900000, 0x13 },
+       { 241600000, 0x12 },
+       { 254400000, 0x11 },
+       { 267100000, 0x10 },
+       { 279800000, 0x0F },
+       { 292500000, 0x0E },
+       { 305200000, 0x0D },
+       { 317900000, 0x0C },
+       { 330700000, 0x0B },
+       { 343400000, 0x0A },
+       { 356100000, 0x09 },
+       { 368800000, 0x08 },
+       { 381500000, 0x07 },
+       { 394200000, 0x06 },
+       { 406900000, 0x05 },
+       { 419700000, 0x04 },
+       { 432400000, 0x03 },
+       { 445100000, 0x02 },
+       { 457800000, 0x01 },
+       { 476300000, 0x19 },
+       { 494800000, 0x18 },
+       { 513300000, 0x17 },
+       { 531800000, 0x16 },
+       { 550300000, 0x15 },
+       { 568900000, 0x14 },
+       { 587400000, 0x13 },
+       { 605900000, 0x12 },
+       { 624400000, 0x11 },
+       { 642900000, 0x10 },
+       { 661400000, 0x0F },
+       { 679900000, 0x0E },
+       { 698400000, 0x0D },
+       { 716900000, 0x0C },
+       { 735400000, 0x0B },
+       { 753900000, 0x0A },
+       { 772500000, 0x09 },
+       { 791000000, 0x08 },
+       { 809500000, 0x07 },
+       { 828000000, 0x06 },
+       { 846500000, 0x05 },
+       { 865000000, 0x04 },
+       {         0, 0x00 },    /* Table End */
+};
+
+static struct SMap m_RF_Cal_DC_Over_DT_Map[] = {
+       {  47900000, 0x00 },
+       {  55000000, 0x00 },
+       {  61100000, 0x0A },
+       {  64000000, 0x0A },
+       {  82000000, 0x14 },
+       {  84000000, 0x19 },
+       { 119000000, 0x1C },
+       { 124000000, 0x20 },
+       { 129000000, 0x2A },
+       { 134000000, 0x32 },
+       { 139000000, 0x39 },
+       { 144000000, 0x3E },
+       { 149000000, 0x3F },
+       { 152600000, 0x40 },
+       { 154000000, 0x40 },
+       { 164700000, 0x41 },
+       { 203500000, 0x32 },
+       { 353000000, 0x19 },
+       { 356000000, 0x1A },
+       { 359000000, 0x1B },
+       { 363000000, 0x1C },
+       { 366000000, 0x1D },
+       { 369000000, 0x1E },
+       { 373000000, 0x1F },
+       { 376000000, 0x20 },
+       { 379000000, 0x21 },
+       { 383000000, 0x22 },
+       { 386000000, 0x23 },
+       { 389000000, 0x24 },
+       { 393000000, 0x25 },
+       { 396000000, 0x26 },
+       { 399000000, 0x27 },
+       { 402000000, 0x28 },
+       { 404000000, 0x29 },
+       { 407000000, 0x2A },
+       { 409000000, 0x2B },
+       { 412000000, 0x2C },
+       { 414000000, 0x2D },
+       { 417000000, 0x2E },
+       { 419000000, 0x2F },
+       { 422000000, 0x30 },
+       { 424000000, 0x31 },
+       { 427000000, 0x32 },
+       { 429000000, 0x33 },
+       { 432000000, 0x34 },
+       { 434000000, 0x35 },
+       { 437000000, 0x36 },
+       { 439000000, 0x37 },
+       { 442000000, 0x38 },
+       { 444000000, 0x39 },
+       { 447000000, 0x3A },
+       { 449000000, 0x3B },
+       { 457800000, 0x3C },
+       { 465000000, 0x0F },
+       { 477000000, 0x12 },
+       { 483000000, 0x14 },
+       { 502000000, 0x19 },
+       { 508000000, 0x1B },
+       { 519000000, 0x1C },
+       { 522000000, 0x1D },
+       { 524000000, 0x1E },
+       { 534000000, 0x1F },
+       { 549000000, 0x20 },
+       { 554000000, 0x22 },
+       { 584000000, 0x24 },
+       { 589000000, 0x26 },
+       { 658000000, 0x27 },
+       { 664000000, 0x2C },
+       { 669000000, 0x2D },
+       { 699000000, 0x2E },
+       { 704000000, 0x30 },
+       { 709000000, 0x31 },
+       { 714000000, 0x32 },
+       { 724000000, 0x33 },
+       { 729000000, 0x36 },
+       { 739000000, 0x38 },
+       { 744000000, 0x39 },
+       { 749000000, 0x3B },
+       { 754000000, 0x3C },
+       { 759000000, 0x3D },
+       { 764000000, 0x3E },
+       { 769000000, 0x3F },
+       { 774000000, 0x40 },
+       { 779000000, 0x41 },
+       { 784000000, 0x43 },
+       { 789000000, 0x46 },
+       { 794000000, 0x48 },
+       { 799000000, 0x4B },
+       { 804000000, 0x4F },
+       { 809000000, 0x54 },
+       { 814000000, 0x59 },
+       { 819000000, 0x5D },
+       { 824000000, 0x61 },
+       { 829000000, 0x68 },
+       { 834000000, 0x6E },
+       { 839000000, 0x75 },
+       { 844000000, 0x7E },
+       { 849000000, 0x82 },
+       { 854000000, 0x84 },
+       { 859000000, 0x8F },
+       { 865000000, 0x9A },
+       {         0, 0x00 },    /* Table End */
+};
+
+
+static struct SMap  m_IR_Meas_Map[] = {
+       { 200000000, 0x05 },
+       { 400000000, 0x06 },
+       { 865000000, 0x07 },
+       {         0, 0x00 },    /* Table End */
+};
+
+static struct SMap2 m_CID_Target_Map[] = {
+       {  46000000, 0x04, 18 },
+       {  52200000, 0x0A, 15 },
+       {  70100000, 0x01, 40 },
+       { 136800000, 0x18, 40 },
+       { 156700000, 0x18, 40 },
+       { 186250000, 0x0A, 40 },
+       { 230000000, 0x0A, 40 },
+       { 345000000, 0x18, 40 },
+       { 426000000, 0x0E, 40 },
+       { 489500000, 0x1E, 40 },
+       { 697500000, 0x32, 40 },
+       { 842000000, 0x3A, 40 },
+       {         0, 0x00,  0 },    /* Table End */
+};
+
+static struct SRFBandMap  m_RF_Band_Map[7] = {
+       {   47900000,   46000000,           0,          0},
+       {   61100000,   52200000,           0,          0},
+       {  152600000,   70100000,   136800000,          0},
+       {  164700000,  156700000,           0,          0},
+       {  203500000,  186250000,           0,          0},
+       {  457800000,  230000000,   345000000,  426000000},
+       {  865000000,  489500000,   697500000,  842000000},
+};
+
+u8 m_Thermometer_Map_1[16] = {
+       60, 62, 66, 64,
+       74, 72, 68, 70,
+       90, 88, 84, 86,
+       76, 78, 82, 80,
+};
+
+u8 m_Thermometer_Map_2[16] = {
+       92, 94, 98, 96,
+       106, 104, 100, 102,
+       122, 120, 116, 118,
+       108, 110, 114, 112,
+};
index cec242b..64c8470 100644 (file)
@@ -5,6 +5,8 @@ config DVB_NGENE
        select DVB_STV6110x if !DVB_FE_CUSTOMISE
        select DVB_STV090x if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_DRXK if !DVB_FE_CUSTOMISE
+       select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
        ---help---
          Support for Micronas PCI express cards with nGene bridge.
index fcf4be9..0564192 100644 (file)
@@ -40,6 +40,8 @@
 #include "lnbh24.h"
 #include "lgdt330x.h"
 #include "mt2131.h"
+#include "tda18271c2dd.h"
+#include "drxk.h"
 
 
 /****************************************************************************/
@@ -83,6 +85,49 @@ static int tuner_attach_stv6110(struct ngene_channel *chan)
 }
 
 
+static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct ngene_channel *chan = fe->sec_priv;
+       int status;
+
+       if (enable) {
+               down(&chan->dev->pll_mutex);
+               status = chan->gate_ctrl(fe, 1);
+       } else {
+               status = chan->gate_ctrl(fe, 0);
+               up(&chan->dev->pll_mutex);
+       }
+       return status;
+}
+
+static int tuner_attach_tda18271(struct ngene_channel *chan)
+{
+       struct i2c_adapter *i2c;
+       struct dvb_frontend *fe;
+
+       i2c = &chan->dev->channel[0].i2c_adapter;
+       if (chan->fe->ops.i2c_gate_ctrl)
+               chan->fe->ops.i2c_gate_ctrl(chan->fe, 1);
+       fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60);
+       if (chan->fe->ops.i2c_gate_ctrl)
+               chan->fe->ops.i2c_gate_ctrl(chan->fe, 0);
+       if (!fe) {
+               printk(KERN_ERR "No TDA18271 found!\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int tuner_attach_probe(struct ngene_channel *chan)
+{
+       if (chan->demod_type == 0)
+               return tuner_attach_stv6110(chan);
+       if (chan->demod_type == 1)
+               return tuner_attach_tda18271(chan);
+       return -EINVAL;
+}
+
 static int demod_attach_stv0900(struct ngene_channel *chan)
 {
        struct i2c_adapter *i2c;
@@ -130,6 +175,60 @@ static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
                up(&chan->dev->pll_mutex);
 }
 
+static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
+{
+       struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
+                                  .buf  = val,  .len   = 1 } };
+       return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
+}
+
+static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
+                         u16 reg, u8 *val)
+{
+       u8 msg[2] = {reg>>8, reg&0xff};
+       struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+                                  .buf  = msg, .len   = 2},
+                                 {.addr = adr, .flags = I2C_M_RD,
+                                  .buf  = val, .len   = 1} };
+       return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int port_has_stv0900(struct i2c_adapter *i2c, int port)
+{
+       u8 val;
+       if (i2c_read_reg16(i2c, 0x68+port/2, 0xf100, &val) < 0)
+               return 0;
+       return 1;
+}
+
+static int port_has_drxk(struct i2c_adapter *i2c, int port)
+{
+       u8 val;
+
+       if (i2c_read(i2c, 0x29+port, &val) < 0)
+               return 0;
+       return 1;
+}
+
+static int demod_attach_drxk(struct ngene_channel *chan,
+                            struct i2c_adapter *i2c)
+{
+       struct drxk_config config;
+
+       memset(&config, 0, sizeof(config));
+       config.adr = 0x29 + (chan->number ^ 2);
+
+       chan->fe = dvb_attach(drxk_attach, &config, i2c, &chan->fe2);
+       if (!chan->fe) {
+               printk(KERN_ERR "No DRXK found!\n");
+               return -ENODEV;
+       }
+       chan->fe->sec_priv = chan;
+       chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl;
+       chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+       return 0;
+}
+
 static int cineS2_probe(struct ngene_channel *chan)
 {
        struct i2c_adapter *i2c;
@@ -144,43 +243,42 @@ static int cineS2_probe(struct ngene_channel *chan)
        else
                i2c = &chan->dev->channel[1].i2c_adapter;
 
-       fe_conf = chan->dev->card_info->fe_config[chan->number];
-       i2c_msg.addr = fe_conf->address;
-
-       /* probe demod */
-       i2c_msg.len = 2;
-       buf[0] = 0xf1;
-       buf[1] = 0x00;
-       rc = i2c_transfer(i2c, &i2c_msg, 1);
-       if (rc != 1)
-               return -ENODEV;
-
-       /* demod found, attach it */
-       rc = demod_attach_stv0900(chan);
-       if (rc < 0 || chan->number < 2)
-               return rc;
-
-       /* demod #2: reprogram outputs DPN1 & DPN2 */
-       i2c_msg.len = 3;
-       buf[0] = 0xf1;
-       switch (chan->number) {
-       case 2:
-               buf[1] = 0x5c;
-               buf[2] = 0xc2;
-               break;
-       case 3:
-               buf[1] = 0x61;
-               buf[2] = 0xcc;
-               break;
-       default:
+       if (port_has_stv0900(i2c, chan->number)) {
+               chan->demod_type = 0;
+               fe_conf = chan->dev->card_info->fe_config[chan->number];
+               /* demod found, attach it */
+               rc = demod_attach_stv0900(chan);
+               if (rc < 0 || chan->number < 2)
+                       return rc;
+
+               /* demod #2: reprogram outputs DPN1 & DPN2 */
+               i2c_msg.addr = fe_conf->address;
+               i2c_msg.len = 3;
+               buf[0] = 0xf1;
+               switch (chan->number) {
+               case 2:
+                       buf[1] = 0x5c;
+                       buf[2] = 0xc2;
+                       break;
+               case 3:
+                       buf[1] = 0x61;
+                       buf[2] = 0xcc;
+                       break;
+               default:
+                       return -ENODEV;
+               }
+               rc = i2c_transfer(i2c, &i2c_msg, 1);
+               if (rc != 1) {
+                       printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
+                       return -EIO;
+               }
+       } else if (port_has_drxk(i2c, chan->number^2)) {
+               chan->demod_type = 1;
+               demod_attach_drxk(chan, i2c);
+       } else {
+               printk(KERN_ERR "No demod found on chan %d\n", chan->number);
                return -ENODEV;
        }
-       rc = i2c_transfer(i2c, &i2c_msg, 1);
-       if (rc != 1) {
-               printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
-               return -EIO;
-       }
-
        return 0;
 }
 
@@ -306,7 +404,7 @@ static struct ngene_info ngene_info_satixS2v2 = {
        .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
                           NGENE_IO_TSOUT},
        .demod_attach   = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
-       .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
+       .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe},
        .fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
        .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
        .lnb            = {0x0a, 0x08, 0x0b, 0x09},
@@ -321,7 +419,7 @@ static struct ngene_info ngene_info_cineS2v5 = {
        .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
                           NGENE_IO_TSOUT},
        .demod_attach   = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
-       .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
+       .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe},
        .fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
        .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
        .lnb            = {0x0a, 0x08, 0x0b, 0x09},
@@ -331,13 +429,13 @@ static struct ngene_info ngene_info_cineS2v5 = {
 };
 
 
-static struct ngene_info ngene_info_duoFlexS2 = {
+static struct ngene_info ngene_info_duoFlex = {
        .type           = NGENE_SIDEWINDER,
-       .name           = "Digital Devices DuoFlex S2 miniPCIe",
+       .name           = "Digital Devices DuoFlex PCIe or miniPCIe",
        .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
                           NGENE_IO_TSOUT},
        .demod_attach   = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe},
-       .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
+       .tuner_attach   = {tuner_attach_probe, tuner_attach_probe, tuner_attach_probe, tuner_attach_probe},
        .fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
        .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
        .lnb            = {0x0a, 0x08, 0x0b, 0x09},
@@ -385,8 +483,8 @@ static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
        NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
        NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2),
        NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5),
-       NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlexS2),
-       NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlexS2),
+       NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex),
+       NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex),
        NGENE_ID(0x1461, 0x062e, ngene_info_m780),
        {0}
 };
index 6927c72..f129a93 100644 (file)
@@ -41,7 +41,7 @@
 
 #include "ngene.h"
 
-static int one_adapter = 1;
+static int one_adapter;
 module_param(one_adapter, int, 0444);
 MODULE_PARM_DESC(one_adapter, "Use only one adapter.");
 
@@ -461,7 +461,7 @@ static u8 TSFeatureDecoderSetup[8 * 5] = {
        0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,
        0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXH */
        0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXHser */
-       0x72, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */
+       0x72, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */
        0x40, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* LGDT3303 */
 };
 
@@ -507,7 +507,7 @@ void FillTSBuffer(void *Buffer, int Length, u32 Flags)
 {
        u32 *ptr = Buffer;
 
-       memset(Buffer, 0xff, Length);
+       memset(Buffer, TS_FILLER, Length);
        while (Length > 0) {
                if (Flags & DF_SWAP32)
                        *ptr = 0x471FFF10;
@@ -1443,6 +1443,9 @@ static void release_channel(struct ngene_channel *chan)
                chan->ci_dev = NULL;
        }
 
+       if (chan->fe2)
+               dvb_unregister_frontend(chan->fe2);
+
        if (chan->fe) {
                dvb_unregister_frontend(chan->fe);
                dvb_frontend_detach(chan->fe);
@@ -1534,6 +1537,14 @@ static int init_channel(struct ngene_channel *chan)
                        goto err;
                chan->has_demux = true;
        }
+       if (chan->fe2) {
+               if (dvb_register_frontend(adapter, chan->fe2) < 0)
+                       goto err;
+               chan->fe2->tuner_priv = chan->fe->tuner_priv;
+               memcpy(&chan->fe2->ops.tuner_ops,
+                      &chan->fe->ops.tuner_ops,
+                      sizeof(struct dvb_tuner_ops));
+       }
 
        if (chan->has_demux) {
                ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
@@ -1571,11 +1582,18 @@ static int init_channels(struct ngene *dev)
        return 0;
 }
 
+static struct cxd2099_cfg cxd_cfg = {
+       .bitrate = 62000,
+       .adr = 0x40,
+       .polarity = 0,
+       .clock_mode = 0,
+};
+
 static void cxd_attach(struct ngene *dev)
 {
        struct ngene_ci *ci = &dev->ci;
 
-       ci->en = cxd2099_attach(0x40, dev, &dev->channel[0].i2c_adapter);
+       ci->en = cxd2099_attach(&cxd_cfg, dev, &dev->channel[0].i2c_adapter);
        ci->dev = dev;
        return;
 }
index 0b49432..fcb16a6 100644 (file)
@@ -118,6 +118,16 @@ static void swap_buffer(u32 *p, u32 len)
        }
 }
 
+/* start of filler packet */
+static u8 fill_ts[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER };
+
+/* #define DEBUG_CI_XFER */
+#ifdef DEBUG_CI_XFER
+static u32 ok;
+static u32 overflow;
+static u32 stripped;
+#endif
+
 void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
 {
        struct ngene_channel *chan = priv;
@@ -126,21 +136,41 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
 
        if (flags & DF_SWAP32)
                swap_buffer(buf, len);
+
        if (dev->ci.en && chan->number == 2) {
-               if (dvb_ringbuffer_free(&dev->tsin_rbuf) > len) {
-                       dvb_ringbuffer_write(&dev->tsin_rbuf, buf, len);
-                       wake_up_interruptible(&dev->tsin_rbuf.queue);
+               while (len >= 188) {
+                       if (memcmp(buf, fill_ts, sizeof fill_ts) != 0) {
+                               if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) {
+                                       dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188);
+                                       wake_up(&dev->tsin_rbuf.queue);
+#ifdef DEBUG_CI_XFER
+                                       ok++;
+#endif
+                               }
+#ifdef DEBUG_CI_XFER
+                               else
+                                       overflow++;
+#endif
+                       }
+#ifdef DEBUG_CI_XFER
+                       else
+                               stripped++;
+
+                       if (ok % 100 == 0 && overflow)
+                               printk(KERN_WARNING "%s: ok %u overflow %u dropped %u\n", __func__, ok, overflow, stripped);
+#endif
+                       buf += 188;
+                       len -= 188;
                }
-               return 0;
+               return NULL;
        }
-       if (chan->users > 0) {
+
+       if (chan->users > 0)
                dvb_dmx_swfilter(&chan->demux, buf, len);
-       }
+
        return NULL;
 }
 
-u8 fill_ts[188] = { 0x47, 0x1f, 0xff, 0x10 };
-
 void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
 {
        struct ngene_channel *chan = priv;
index 40fce9e..5443dc0 100644 (file)
@@ -641,8 +641,11 @@ struct ngene_channel {
        int                   mode;
        bool                  has_adapter;
        bool                  has_demux;
+       int                   demod_type;
+       int (*gate_ctrl)(struct dvb_frontend *, int);
 
        struct dvb_frontend  *fe;
+       struct dvb_frontend  *fe2;
        struct dmxdev         dmxdev;
        struct dvb_demux      demux;
        struct dvb_net        dvbnet;
@@ -786,6 +789,8 @@ struct ngene {
        u8                    uart_rbuf[UART_RBUF_LEN];
        int                   uart_rp, uart_wp;
 
+#define TS_FILLER  0x6f
+
        u8                   *tsout_buf;
 #define TSOUT_BUF_SIZE (512*188*8)
        struct dvb_ringbuffer tsout_rbuf;
@@ -852,7 +857,7 @@ struct ngene_info {
 };
 
 #ifdef NGENE_V4L
-struct ngene_format{
+struct ngene_format {
        char *name;
        int   fourcc;          /* video4linux 2      */
        int   btformat;        /* BT848_COLOR_FMT_*  */
index 78765ed..7331e84 100644 (file)
@@ -1147,7 +1147,7 @@ static int smscore_validate_client(struct smscore_device_t *coredev,
 
        if (!client) {
                sms_err("bad parameter.");
-               return -EFAULT;
+               return -EINVAL;
        }
        registered_client = smscore_find_client(coredev, data_type, id);
        if (registered_client == client)
index 8ecadec..c592ae0 100644 (file)
@@ -22,7 +22,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef __SMS_CORE_API_H__
 #define __SMS_CORE_API_H__
 
-#include <linux/version.h>
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/mm.h>
index 3d8cc42..25e58cb 100644 (file)
 /*
  * Version Information
  */
-#include <linux/version.h>     /* for KERNEL_VERSION MACRO     */
-
-#define DRIVER_VERSION "v0.46"
-#define RADIO_VERSION KERNEL_VERSION(0, 4, 6)
+#define DRIVER_VERSION "0.4.7"
 
 #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
 #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
@@ -335,7 +332,6 @@ static int vidioc_querycap(struct file *file, void *priv,
        strlcpy(v->driver, "dsbr100", sizeof(v->driver));
        strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
        usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER;
        return 0;
 }
@@ -647,3 +643,4 @@ module_exit (dsbr100_exit);
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
index 4ce10db..1c3f844 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/ioport.h>      /* request_region               */
 #include <linux/delay.h>       /* msleep                       */
 #include <linux/videodev2.h>   /* kernel radio structs         */
-#include <linux/version.h>     /* for KERNEL_VERSION MACRO     */
 #include <linux/io.h>          /* outb, outb_p                 */
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
@@ -41,6 +40,7 @@
 MODULE_AUTHOR("M.Kirkwood");
 MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card.");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.3");
 
 #ifndef CONFIG_RADIO_RTRACK_PORT
 #define CONFIG_RADIO_RTRACK_PORT -1
@@ -53,8 +53,6 @@ module_param(io, int, 0);
 MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)");
 module_param(radio_nr, int, 0);
 
-#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
-
 struct rtrack
 {
        struct v4l2_device v4l2_dev;
@@ -223,7 +221,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strlcpy(v->driver, "radio-aimslab", sizeof(v->driver));
        strlcpy(v->card, "RadioTrack", sizeof(v->card));
        strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
index dd8a6ab..eed7b08 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/ioport.h>      /* request_region               */
 #include <linux/delay.h>       /* udelay                       */
 #include <linux/videodev2.h>   /* kernel radio structs         */
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #include <linux/io.h>          /* outb, outb_p                 */
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
@@ -38,6 +37,7 @@
 MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
 MODULE_DESCRIPTION("A driver for the Aztech radio card.");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.3");
 
 /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
 
@@ -53,8 +53,6 @@ module_param(io, int, 0);
 module_param(radio_nr, int, 0);
 MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)");
 
-#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
-
 struct aztech
 {
        struct v4l2_device v4l2_dev;
@@ -188,7 +186,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strlcpy(v->driver, "radio-aztech", sizeof(v->driver));
        strlcpy(v->card, "Aztech Radio", sizeof(v->card));
        strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
index bc9ad08..16a089f 100644 (file)
@@ -30,7 +30,6 @@
  *             Changed API to V4L2
  */
 
-#include <linux/version.h>
 #include <linux/module.h>      /* Modules                      */
 #include <linux/init.h>                /* Initdata                     */
 #include <linux/ioport.h>      /* request_region               */
@@ -46,6 +45,7 @@
 MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
 MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card.");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.3.4");
 
 static int io = -1;            /* default to isapnp activation */
 static int radio_nr = -1;
@@ -54,8 +54,6 @@ module_param(io, int, 0);
 MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)");
 module_param(radio_nr, int, 0);
 
-#define CADET_VERSION KERNEL_VERSION(0, 3, 3)
-
 #define RDS_BUFFER 256
 #define RDS_RX_FLAG 1
 #define MBS_RX_FLAG 2
@@ -361,7 +359,6 @@ static int vidioc_querycap(struct file *file, void *priv,
        strlcpy(v->driver, "ADS Cadet", sizeof(v->driver));
        strlcpy(v->card, "ADS Cadet", sizeof(v->card));
        strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
-       v->version = CADET_VERSION;
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO |
                          V4L2_CAP_READWRITE | V4L2_CAP_RDS_CAPTURE;
        return 0;
index 2599364..edadc84 100644 (file)
 #include <linux/ioport.h>      /* request_region               */
 #include <linux/delay.h>       /* udelay                       */
 #include <linux/videodev2.h>   /* kernel radio structs         */
-#include <linux/version.h>     /* for KERNEL_VERSION MACRO     */
 #include <linux/mutex.h>
 #include <linux/io.h>          /* outb, outb_p                 */
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 
-#define RADIO_VERSION KERNEL_VERSION(0, 0, 3)
-
 /*
  * Module info.
  */
 
-MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen <pexu@kapsi.fi>");
+MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen <pexu@kapsi.fi>");
 MODULE_DESCRIPTION("A driver for the GemTek Radio card.");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.4");
 
 /*
  * Module params.
@@ -387,7 +385,6 @@ static int vidioc_querycap(struct file *file, void *priv,
        strlcpy(v->driver, "radio-gemtek", sizeof(v->driver));
        strlcpy(v->card, "GemTek", sizeof(v->card));
        strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
index e83e840..f872a54 100644 (file)
 #include <linux/mutex.h>
 #include <linux/pci.h>
 #include <linux/videodev2.h>
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 
+#define DRIVER_VERSION "0.7.8"
+
+
 MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net");
 MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio.");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
 
 static int radio_nr = -1;
 module_param(radio_nr, int, 0);
@@ -58,10 +61,6 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "activates debug info");
 
-#define DRIVER_VERSION "0.77"
-
-#define RADIO_VERSION KERNEL_VERSION(0, 7, 7)
-
 #define dprintk(dev, num, fmt, arg...) \
        v4l2_dbg(num, debug, &dev->v4l2_dev, fmt, ## arg)
 
@@ -195,7 +194,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strlcpy(v->driver, "radio-maxiradio", sizeof(v->driver));
        strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof(v->card));
        snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
index b3a635b..1742bd8 100644 (file)
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <linux/usb.h>
-#include <linux/version.h>     /* for KERNEL_VERSION MACRO */
 #include <linux/mutex.h>
 
 /* driver and module definitions */
 #define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
 #define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"
-#define DRIVER_VERSION "0.11"
-#define RADIO_VERSION KERNEL_VERSION(0, 1, 1)
+#define DRIVER_VERSION "0.1.2"
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
 
 #define USB_AMRADIO_VENDOR 0x07ca
 #define USB_AMRADIO_PRODUCT 0xb800
@@ -301,7 +300,6 @@ static int vidioc_querycap(struct file *file, void *priv,
        strlcpy(v->driver, "radio-mr800", sizeof(v->driver));
        strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
        usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER;
        return 0;
 }
index 8d6ea59..3628be6 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/delay.h>       /* udelay                       */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <linux/mutex.h>
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #include <linux/io.h>          /* outb, outb_p                 */
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
@@ -23,6 +22,7 @@
 MODULE_AUTHOR("Ben Pfaff");
 MODULE_DESCRIPTION("A driver for the RadioTrack II radio card.");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.3");
 
 #ifndef CONFIG_RADIO_RTRACK2_PORT
 #define CONFIG_RADIO_RTRACK2_PORT -1
@@ -35,8 +35,6 @@ module_param(io, int, 0);
 MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)");
 module_param(radio_nr, int, 0);
 
-#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
-
 struct rtrack2
 {
        struct v4l2_device v4l2_dev;
@@ -121,7 +119,6 @@ static int vidioc_querycap(struct file *file, void *priv,
        strlcpy(v->driver, "radio-rtrack2", sizeof(v->driver));
        strlcpy(v->card, "RadioTrack II", sizeof(v->card));
        strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
index b5a5f89..22c5743 100644 (file)
@@ -16,7 +16,6 @@
  * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  */
 
-#include <linux/version.h>
 #include <linux/kernel.h>      /* __setup                      */
 #include <linux/module.h>      /* Modules                      */
 #include <linux/init.h>                /* Initdata                     */
@@ -32,6 +31,7 @@
 MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
 MODULE_DESCRIPTION("A driver for the SF16-FMI and SF16-FMP radio.");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.3");
 
 static int io = -1;
 static int radio_nr = -1;
@@ -40,8 +40,6 @@ module_param(io, int, 0);
 MODULE_PARM_DESC(io, "I/O address of the SF16-FMI or SF16-FMP card (0x284 or 0x384)");
 module_param(radio_nr, int, 0);
 
-#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
-
 struct fmi
 {
        struct v4l2_device v4l2_dev;
@@ -134,7 +132,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strlcpy(v->driver, "radio-sf16fmi", sizeof(v->driver));
        strlcpy(v->card, "SF16-FMx radio", sizeof(v->card));
        strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
index 87bad76..2dd4859 100644 (file)
-/* SF16FMR2 radio driver for Linux radio support
- * heavily based on fmi driver...
- * (c) 2000-2002 Ziglio Frediano, freddy77@angelfire.com
+/* SF16-FMR2 radio driver for Linux
+ * Copyright (c) 2011 Ondrej Zary
  *
- * Notes on the hardware
- *
- *  Frequency control is done digitally -- ie out(port,encodefreq(95.8));
- *  No volume control - only mute/unmute - you have to use line volume
- *
- *  For read stereo/mono you must wait 0.1 sec after set frequency and
- *  card unmuted so I set frequency on unmute
- *  Signal handling seem to work only on autoscanning (not implemented)
- *
- *  Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
+ * Original driver was (c) 2000-2002 Ziglio Frediano, freddy77@angelfire.com
+ * but almost nothing remained here after conversion to generic TEA575x
+ * implementation
  */
 
+#include <linux/delay.h>
 #include <linux/module.h>      /* Modules                      */
 #include <linux/init.h>                /* Initdata                     */
 #include <linux/ioport.h>      /* request_region               */
-#include <linux/delay.h>       /* udelay                       */
-#include <linux/videodev2.h>   /* kernel radio structs         */
-#include <linux/mutex.h>
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #include <linux/io.h>          /* outb, outb_p                 */
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
+#include <sound/tea575x-tuner.h>
 
-MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com");
-MODULE_DESCRIPTION("A driver for the SF16FMR2 radio.");
+MODULE_AUTHOR("Ondrej Zary");
+MODULE_DESCRIPTION("MediaForte SF16-FMR2 FM radio card driver");
 MODULE_LICENSE("GPL");
 
-static int io = 0x384;
-static int radio_nr = -1;
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)");
-module_param(radio_nr, int, 0);
-
-#define RADIO_VERSION KERNEL_VERSION(0,0,2)
-
-#define AUD_VOL_INDEX 1
-
-#undef DEBUG
-//#define DEBUG 1
-
-#ifdef DEBUG
-# define  debug_print(s) printk s
-#else
-# define  debug_print(s)
-#endif
-
-/* this should be static vars for module size */
-struct fmr2
-{
-       struct v4l2_device v4l2_dev;
-       struct video_device vdev;
-       struct mutex lock;
+struct fmr2 {
        int io;
-       int curvol; /* 0-15 */
-       int mute;
-       int stereo; /* card is producing stereo audio */
-       unsigned long curfreq; /* freq in kHz */
-       int card_type;
+       struct snd_tea575x tea;
+       struct v4l2_ctrl *volume;
+       struct v4l2_ctrl *balance;
 };
 
+/* the port is hardwired so no need to support multiple cards */
+#define FMR2_PORT      0x384
 static struct fmr2 fmr2_card;
 
-/* hw precision is 12.5 kHz
- * It is only useful to give freq in interval of 200 (=0.0125Mhz),
- * other bits will be truncated
- */
-#define RSF16_ENCODE(x)        ((x) / 200 + 856)
-#define RSF16_MINFREQ (87 * 16000)
-#define RSF16_MAXFREQ (108 * 16000)
-
-static inline void wait(int n, int io)
-{
-       for (; n; --n)
-               inb(io);
-}
-
-static void outbits(int bits, unsigned int data, int nWait, int io)
-{
-       int bit;
-
-       for (; --bits >= 0;) {
-               bit = (data >> bits) & 1;
-               outb(bit, io);
-               wait(nWait, io);
-               outb(bit | 2, io);
-               wait(nWait, io);
-               outb(bit, io);
-               wait(nWait, io);
-       }
-}
-
-static inline void fmr2_mute(int io)
-{
-       outb(0x00, io);
-       wait(4, io);
-}
-
-static inline void fmr2_unmute(int io)
-{
-       outb(0x04, io);
-       wait(4, io);
-}
-
-static inline int fmr2_stereo_mode(int io)
-{
-       int n = inb(io);
-
-       outb(6, io);
-       inb(io);
-       n = ((n >> 3) & 1) ^ 1;
-       debug_print((KERN_DEBUG "stereo: %d\n", n));
-       return n;
-}
-
-static int fmr2_product_info(struct fmr2 *dev)
-{
-       int n = inb(dev->io);
-
-       n &= 0xC1;
-       if (n == 0) {
-               /* this should support volume set */
-               dev->card_type = 12;
-               return 0;
-       }
-       /* not volume (mine is 11) */
-       dev->card_type = (n == 128) ? 11 : 0;
-       return n;
-}
+/* TEA575x tuner pins */
+#define STR_DATA       (1 << 0)
+#define STR_CLK                (1 << 1)
+#define STR_WREN       (1 << 2)
+#define STR_MOST       (1 << 3)
+/* PT2254A/TC9154A volume control pins */
+#define PT_ST          (1 << 4)
+#define PT_CK          (1 << 5)
+#define PT_DATA                (1 << 6)
+/* volume control presence pin */
+#define FMR2_HASVOL    (1 << 7)
 
-static inline int fmr2_getsigstr(struct fmr2 *dev)
+static void fmr2_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
 {
-       /* !!! works only if scanning freq */
-       int res = 0xffff;
-
-       outb(5, dev->io);
-       wait(4, dev->io);
-       if (!(inb(dev->io) & 1))
-               res = 0;
-       debug_print((KERN_DEBUG "signal: %d\n", res));
-       return res;
-}
-
-/* set frequency and unmute card */
-static int fmr2_setfreq(struct fmr2 *dev)
-{
-       unsigned long freq = dev->curfreq;
-
-       fmr2_mute(dev->io);
-
-       /* 0x42 for mono output
-        * 0x102 forward scanning
-        * 0x182 scansione avanti
-        */
-       outbits(9, 0x2, 3, dev->io);
-       outbits(16, RSF16_ENCODE(freq), 2, dev->io);
-
-       fmr2_unmute(dev->io);
+       struct fmr2 *fmr2 = tea->private_data;
+       u8 bits = 0;
 
-       /* wait 0.11 sec */
-       msleep(110);
+       bits |= (pins & TEA575X_DATA) ? STR_DATA : 0;
+       bits |= (pins & TEA575X_CLK)  ? STR_CLK  : 0;
+       /* WRITE_ENABLE is inverted, DATA must be high during read */
+       bits |= (pins & TEA575X_WREN) ? 0 : STR_WREN | STR_DATA;
 
-       /* NOTE if mute this stop radio
-          you must set freq on unmute */
-       dev->stereo = fmr2_stereo_mode(dev->io);
-       return 0;
-}
-
-/* !!! not tested, in my card this doesn't work !!! */
-static int fmr2_setvolume(struct fmr2 *dev)
-{
-       int vol[16] = { 0x021, 0x084, 0x090, 0x104,
-                       0x110, 0x204, 0x210, 0x402,
-                       0x404, 0x408, 0x410, 0x801,
-                       0x802, 0x804, 0x808, 0x810 };
-       int i, a;
-       int n = vol[dev->curvol & 0x0f];
-
-       if (dev->card_type != 11)
-               return 1;
-
-       for (i = 12; --i >= 0; ) {
-               a = ((n >> i) & 1) << 6; /* if (a==0) a = 0; else a = 0x40; */
-               outb(a | 4, dev->io);
-               wait(4, dev->io);
-               outb(a | 0x24, dev->io);
-               wait(4, dev->io);
-               outb(a | 4, dev->io);
-               wait(4, dev->io);
-       }
-       for (i = 6; --i >= 0; ) {
-               a = ((0x18 >> i) & 1) << 6;
-               outb(a | 4, dev->io);
-               wait(4, dev->io);
-               outb(a | 0x24, dev->io);
-               wait(4, dev->io);
-               outb(a | 4, dev->io);
-               wait(4, dev->io);
-       }
-       wait(4, dev->io);
-       outb(0x14, dev->io);
-       return 0;
+       outb(bits, fmr2->io);
 }
 
-static int vidioc_querycap(struct file *file, void  *priv,
-                                       struct v4l2_capability *v)
+static u8 fmr2_tea575x_get_pins(struct snd_tea575x *tea)
 {
-       strlcpy(v->driver, "radio-sf16fmr2", sizeof(v->driver));
-       strlcpy(v->card, "SF16-FMR2 radio", sizeof(v->card));
-       strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
-       v->version = RADIO_VERSION;
-       v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
-       return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *v)
-{
-       struct fmr2 *fmr2 = video_drvdata(file);
-
-       if (v->index > 0)
-               return -EINVAL;
+       struct fmr2 *fmr2 = tea->private_data;
+       u8 bits = inb(fmr2->io);
 
-       strlcpy(v->name, "FM", sizeof(v->name));
-       v->type = V4L2_TUNER_RADIO;
-
-       v->rangelow = RSF16_MINFREQ;
-       v->rangehigh = RSF16_MAXFREQ;
-       v->rxsubchans = fmr2->stereo ? V4L2_TUNER_SUB_STEREO :
-                                       V4L2_TUNER_SUB_MONO;
-       v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW;
-       v->audmode = V4L2_TUNER_MODE_STEREO;
-       mutex_lock(&fmr2->lock);
-       v->signal = fmr2_getsigstr(fmr2);
-       mutex_unlock(&fmr2->lock);
-       return 0;
+       return  (bits & STR_DATA) ? TEA575X_DATA : 0 |
+               (bits & STR_MOST) ? TEA575X_MOST : 0;
 }
 
-static int vidioc_s_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *v)
+static void fmr2_tea575x_set_direction(struct snd_tea575x *tea, bool output)
 {
-       return v->index ? -EINVAL : 0;
 }
 
-static int vidioc_s_frequency(struct file *file, void *priv,
-                                       struct v4l2_frequency *f)
-{
-       struct fmr2 *fmr2 = video_drvdata(file);
+static struct snd_tea575x_ops fmr2_tea_ops = {
+       .set_pins = fmr2_tea575x_set_pins,
+       .get_pins = fmr2_tea575x_get_pins,
+       .set_direction = fmr2_tea575x_set_direction,
+};
 
-       if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
-               return -EINVAL;
-       if (f->frequency < RSF16_MINFREQ ||
-                       f->frequency > RSF16_MAXFREQ)
-               return -EINVAL;
-       /* rounding in steps of 200 to match the freq
-          that will be used */
-       fmr2->curfreq = (f->frequency / 200) * 200;
-
-       /* set card freq (if not muted) */
-       if (fmr2->curvol && !fmr2->mute) {
-               mutex_lock(&fmr2->lock);
-               fmr2_setfreq(fmr2);
-               mutex_unlock(&fmr2->lock);
+/* TC9154A/PT2254A volume control */
+
+/* 18-bit shift register bit definitions */
+#define TC9154A_ATT_MAJ_0DB    (1 << 0)
+#define TC9154A_ATT_MAJ_10DB   (1 << 1)
+#define TC9154A_ATT_MAJ_20DB   (1 << 2)
+#define TC9154A_ATT_MAJ_30DB   (1 << 3)
+#define TC9154A_ATT_MAJ_40DB   (1 << 4)
+#define TC9154A_ATT_MAJ_50DB   (1 << 5)
+#define TC9154A_ATT_MAJ_60DB   (1 << 6)
+
+#define TC9154A_ATT_MIN_0DB    (1 << 7)
+#define TC9154A_ATT_MIN_2DB    (1 << 8)
+#define TC9154A_ATT_MIN_4DB    (1 << 9)
+#define TC9154A_ATT_MIN_6DB    (1 << 10)
+#define TC9154A_ATT_MIN_8DB    (1 << 11)
+/* bit 12 is ignored */
+#define TC9154A_CHANNEL_LEFT   (1 << 13)
+#define TC9154A_CHANNEL_RIGHT  (1 << 14)
+/* bits 15, 16, 17 must be 0 */
+
+#define        TC9154A_ATT_MAJ(x)      (1 << x)
+#define TC9154A_ATT_MIN(x)     (1 << (7 + x))
+
+static void tc9154a_set_pins(struct fmr2 *fmr2, u8 pins)
+{
+       if (!fmr2->tea.mute)
+               pins |= STR_WREN;
+
+       outb(pins, fmr2->io);
+}
+
+static void tc9154a_set_attenuation(struct fmr2 *fmr2, int att, u32 channel)
+{
+       int i;
+       u32 reg;
+       u8 bit;
+
+       reg = TC9154A_ATT_MAJ(att / 10) | TC9154A_ATT_MIN((att % 10) / 2);
+       reg |= channel;
+       /* write 18-bit shift register, LSB first */
+       for (i = 0; i < 18; i++) {
+               bit = reg & (1 << i) ? PT_DATA : 0;
+               tc9154a_set_pins(fmr2, bit);
+               udelay(5);
+               tc9154a_set_pins(fmr2, bit | PT_CK);
+               udelay(5);
+               tc9154a_set_pins(fmr2, bit);
        }
-       return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-                                       struct v4l2_frequency *f)
-{
-       struct fmr2 *fmr2 = video_drvdata(file);
-
-       if (f->tuner != 0)
-               return -EINVAL;
-       f->type = V4L2_TUNER_RADIO;
-       f->frequency = fmr2->curfreq;
-       return 0;
-}
 
-static int vidioc_queryctrl(struct file *file, void *priv,
-                                       struct v4l2_queryctrl *qc)
-{
-       struct fmr2 *fmr2 = video_drvdata(file);
-
-       switch (qc->id) {
-       case V4L2_CID_AUDIO_MUTE:
-               return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
-       case V4L2_CID_AUDIO_VOLUME:
-               /* Only card_type == 11 implements volume */
-               if (fmr2->card_type == 11)
-                       return v4l2_ctrl_query_fill(qc, 0, 15, 1, 0);
-               return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
-       }
-       return -EINVAL;
+       /* latch register data */
+       udelay(5);
+       tc9154a_set_pins(fmr2, PT_ST);
+       udelay(5);
+       tc9154a_set_pins(fmr2, 0);
 }
 
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                                       struct v4l2_control *ctrl)
+static int fmr2_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-       struct fmr2 *fmr2 = video_drvdata(file);
+       struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler);
+       struct fmr2 *fmr2 = tea->private_data;
+       int volume, balance, left, right;
 
        switch (ctrl->id) {
-       case V4L2_CID_AUDIO_MUTE:
-               ctrl->value = fmr2->mute;
-               return 0;
        case V4L2_CID_AUDIO_VOLUME:
-               ctrl->value = fmr2->curvol;
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                                       struct v4l2_control *ctrl)
-{
-       struct fmr2 *fmr2 = video_drvdata(file);
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUDIO_MUTE:
-               fmr2->mute = ctrl->value;
+               volume = ctrl->val;
+               balance = fmr2->balance->cur.val;
                break;
-       case V4L2_CID_AUDIO_VOLUME:
-               fmr2->curvol = ctrl->value;
+       case V4L2_CID_AUDIO_BALANCE:
+               balance = ctrl->val;
+               volume = fmr2->volume->cur.val;
                break;
        default:
                return -EINVAL;
        }
 
-#ifdef DEBUG
-       if (fmr2->curvol && !fmr2->mute)
-               printk(KERN_DEBUG "unmute\n");
-       else
-               printk(KERN_DEBUG "mute\n");
-#endif
-
-       mutex_lock(&fmr2->lock);
-       if (fmr2->curvol && !fmr2->mute) {
-               fmr2_setvolume(fmr2);
-               /* Set frequency and unmute card */
-               fmr2_setfreq(fmr2);
-       } else
-               fmr2_mute(fmr2->io);
-       mutex_unlock(&fmr2->lock);
-       return 0;
-}
-
-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
+       left = right = volume;
+       if (balance < 0)
+               right = max(0, right + balance);
+       if (balance > 0)
+               left = max(0, left - balance);
 
-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
-       return i ? -EINVAL : 0;
-}
+       tc9154a_set_attenuation(fmr2, abs(left - 68), TC9154A_CHANNEL_LEFT);
+       tc9154a_set_attenuation(fmr2, abs(right - 68), TC9154A_CHANNEL_RIGHT);
 
-static int vidioc_g_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
-{
-       a->index = 0;
-       strlcpy(a->name, "Radio", sizeof(a->name));
-       a->capability = V4L2_AUDCAP_STEREO;
        return 0;
 }
 
-static int vidioc_s_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
+static const struct v4l2_ctrl_ops fmr2_ctrl_ops = {
+       .s_ctrl = fmr2_s_ctrl,
+};
+
+static int fmr2_tea_ext_init(struct snd_tea575x *tea)
 {
-       return a->index ? -EINVAL : 0;
-}
+       struct fmr2 *fmr2 = tea->private_data;
 
-static const struct v4l2_file_operations fmr2_fops = {
-       .owner          = THIS_MODULE,
-       .unlocked_ioctl = video_ioctl2,
-};
+       if (inb(fmr2->io) & FMR2_HASVOL) {
+               fmr2->volume = v4l2_ctrl_new_std(&tea->ctrl_handler, &fmr2_ctrl_ops, V4L2_CID_AUDIO_VOLUME, 0, 68, 2, 56);
+               fmr2->balance = v4l2_ctrl_new_std(&tea->ctrl_handler, &fmr2_ctrl_ops, V4L2_CID_AUDIO_BALANCE, -68, 68, 2, 0);
+               if (tea->ctrl_handler.error) {
+                       printk(KERN_ERR "radio-sf16fmr2: can't initialize contrls\n");
+                       return tea->ctrl_handler.error;
+               }
+       }
 
-static const struct v4l2_ioctl_ops fmr2_ioctl_ops = {
-       .vidioc_querycap    = vidioc_querycap,
-       .vidioc_g_tuner     = vidioc_g_tuner,
-       .vidioc_s_tuner     = vidioc_s_tuner,
-       .vidioc_g_audio     = vidioc_g_audio,
-       .vidioc_s_audio     = vidioc_s_audio,
-       .vidioc_g_input     = vidioc_g_input,
-       .vidioc_s_input     = vidioc_s_input,
-       .vidioc_g_frequency = vidioc_g_frequency,
-       .vidioc_s_frequency = vidioc_s_frequency,
-       .vidioc_queryctrl   = vidioc_queryctrl,
-       .vidioc_g_ctrl      = vidioc_g_ctrl,
-       .vidioc_s_ctrl      = vidioc_s_ctrl,
-};
+       return 0;
+}
 
 static int __init fmr2_init(void)
 {
        struct fmr2 *fmr2 = &fmr2_card;
-       struct v4l2_device *v4l2_dev = &fmr2->v4l2_dev;
-       int res;
 
-       strlcpy(v4l2_dev->name, "sf16fmr2", sizeof(v4l2_dev->name));
-       fmr2->io = io;
-       fmr2->stereo = 1;
-       mutex_init(&fmr2->lock);
+       fmr2->io = FMR2_PORT;
 
-       if (!request_region(fmr2->io, 2, "sf16fmr2")) {
-               v4l2_err(v4l2_dev, "request_region failed!\n");
+       if (!request_region(fmr2->io, 2, "SF16-FMR2")) {
+               printk(KERN_ERR "radio-sf16fmr2: I/O port 0x%x already in use\n", fmr2->io);
                return -EBUSY;
        }
 
-       res = v4l2_device_register(NULL, v4l2_dev);
-       if (res < 0) {
-               release_region(fmr2->io, 2);
-               v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
-               return res;
-       }
+       fmr2->tea.private_data = fmr2;
+       fmr2->tea.ops = &fmr2_tea_ops;
+       fmr2->tea.ext_init = fmr2_tea_ext_init;
+       strlcpy(fmr2->tea.card, "SF16-FMR2", sizeof(fmr2->tea.card));
+       strcpy(fmr2->tea.bus_info, "ISA");
 
-       strlcpy(fmr2->vdev.name, v4l2_dev->name, sizeof(fmr2->vdev.name));
-       fmr2->vdev.v4l2_dev = v4l2_dev;
-       fmr2->vdev.fops = &fmr2_fops;
-       fmr2->vdev.ioctl_ops = &fmr2_ioctl_ops;
-       fmr2->vdev.release = video_device_release_empty;
-       video_set_drvdata(&fmr2->vdev, fmr2);
-
-       /* mute card - prevents noisy bootups */
-       fmr2_mute(fmr2->io);
-       fmr2_product_info(fmr2);
-
-       if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
+       if (snd_tea575x_init(&fmr2->tea)) {
+               printk(KERN_ERR "radio-sf16fmr2: Unable to detect TEA575x tuner\n");
                release_region(fmr2->io, 2);
-               return -EINVAL;
+               return -ENODEV;
        }
 
-       v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io);
-       debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type));
+       printk(KERN_INFO "radio-sf16fmr2: SF16-FMR2 radio card at 0x%x.\n", fmr2->io);
        return 0;
 }
 
@@ -443,22 +211,9 @@ static void __exit fmr2_exit(void)
 {
        struct fmr2 *fmr2 = &fmr2_card;
 
-       video_unregister_device(&fmr2->vdev);
-       v4l2_device_unregister(&fmr2->v4l2_dev);
+       snd_tea575x_exit(&fmr2->tea);
        release_region(fmr2->io, 2);
 }
 
 module_init(fmr2_init);
 module_exit(fmr2_exit);
-
-#ifndef MODULE
-
-static int __init fmr2_setup_io(char *str)
-{
-       get_option(&str, &io);
-       return 1;
-}
-
-__setup("sf16fmr2=", fmr2_setup_io);
-
-#endif
index 0e71d81..95ddcc4 100644 (file)
 #include <linux/i2c.h>                 /* I2C                          */
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
-#include <linux/version.h>             /* for KERNEL_VERSION MACRO     */
 
-#define DRIVER_VERSION "v0.01"
-#define RADIO_VERSION  KERNEL_VERSION(0, 0, 1)
+#define DRIVER_VERSION "0.0.2"
 
 #define DRIVER_AUTHOR  "Fabio Belavenuto <belavenuto@gmail.com>"
 #define DRIVER_DESC    "A driver for the TEA5764 radio chip for EZX Phones."
@@ -300,7 +298,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strlcpy(v->card, dev->name, sizeof(v->card));
        snprintf(v->bus_info, sizeof(v->bus_info),
                 "I2C:%s", dev_name(&dev->dev));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
@@ -595,8 +592,9 @@ static void __exit tea5764_exit(void)
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
 
-module_param(use_xtal, int, 1);
+module_param(use_xtal, int, 0);
 MODULE_PARM_DESC(use_xtal, "Chip have a xtal connected in board");
 module_param(radio_nr, int, 0);
 MODULE_PARM_DESC(radio_nr, "video4linux device number to use");
index a326639..f2ed9cc 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/ioport.h>      /* request_region               */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <linux/mutex.h>
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #include <linux/io.h>          /* outb, outb_p                 */
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
@@ -37,6 +36,7 @@
 MODULE_AUTHOR("R.OFFERMANNS & others");
 MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card.");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.3");
 
 #ifndef CONFIG_RADIO_TERRATEC_PORT
 #define CONFIG_RADIO_TERRATEC_PORT 0x590
@@ -49,8 +49,6 @@ module_param(io, int, 0);
 MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x591)");
 module_param(radio_nr, int, 0);
 
-#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
-
 static struct v4l2_queryctrl radio_qctrl[] = {
        {
                .id            = V4L2_CID_AUDIO_MUTE,
@@ -205,7 +203,6 @@ static int vidioc_querycap(struct file *file, void *priv,
        strlcpy(v->driver, "radio-terratec", sizeof(v->driver));
        strlcpy(v->card, "ActiveRadio", sizeof(v->card));
        strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
index a185610..f17b540 100644 (file)
@@ -16,7 +16,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/version.h>
 #include <linux/io.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
@@ -44,7 +43,6 @@ static int timbradio_vidioc_querycap(struct file *file, void  *priv,
        strlcpy(v->driver, DRIVER_NAME, sizeof(v->driver));
        strlcpy(v->card, "Timberdale Radio", sizeof(v->card));
        snprintf(v->bus_info, sizeof(v->bus_info), "platform:"DRIVER_NAME);
-       v->version = KERNEL_VERSION(0, 0, 1);
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
@@ -245,4 +243,5 @@ module_exit(timbradio_exit);
 MODULE_DESCRIPTION("Timberdale Radio driver");
 MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
 MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.0.2");
 MODULE_ALIAS("platform:"DRIVER_NAME);
index 22fa9cc..b3f45a0 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #include <linux/videodev2.h>
 #include <linux/io.h>
 #include <media/v4l2-device.h>
@@ -28,6 +27,7 @@
 MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
 MODULE_DESCRIPTION("A driver for the Trust FM Radio card.");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.3");
 
 /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
 
@@ -42,8 +42,6 @@ module_param(io, int, 0);
 MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)");
 module_param(radio_nr, int, 0);
 
-#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
-
 struct trust {
        struct v4l2_device v4l2_dev;
        struct video_device vdev;
@@ -196,7 +194,6 @@ static int vidioc_querycap(struct file *file, void *priv,
        strlcpy(v->driver, "radio-trust", sizeof(v->driver));
        strlcpy(v->card, "Trust FM Radio", sizeof(v->card));
        strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
index 8dbbf08..398726a 100644 (file)
 #include <linux/module.h>      /* Modules                        */
 #include <linux/init.h>                /* Initdata                       */
 #include <linux/ioport.h>      /* request_region                 */
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #include <linux/videodev2.h>   /* kernel radio structs           */
 #include <linux/io.h>          /* outb, outb_p                   */
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 
+#define DRIVER_VERSION "0.1.2"
+
 MODULE_AUTHOR("Dr. Henrik Seidel");
 MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio).");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
 
 #ifndef CONFIG_RADIO_TYPHOON_PORT
 #define CONFIG_RADIO_TYPHOON_PORT -1
@@ -61,9 +63,7 @@ static unsigned long mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ;
 module_param(mutefreq, ulong, 0);
 MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
 
-#define RADIO_VERSION KERNEL_VERSION(0, 1, 1)
-
-#define BANNER "Typhoon Radio Card driver v0.1.1\n"
+#define BANNER "Typhoon Radio Card driver v" DRIVER_VERSION "\n"
 
 struct typhoon {
        struct v4l2_device v4l2_dev;
@@ -171,7 +171,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strlcpy(v->driver, "radio-typhoon", sizeof(v->driver));
        strlcpy(v->card, "Typhoon Radio", sizeof(v->card));
        strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
index 459f727..46cacf8 100644 (file)
@@ -1382,7 +1382,7 @@ static int wl1273_fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 
        switch (ctrl->id) {
        case  V4L2_CID_TUNE_ANTENNA_CAPACITOR:
-               ctrl->cur.val = wl1273_fm_get_tx_ctune(radio);
+               ctrl->val = wl1273_fm_get_tx_ctune(radio);
                break;
 
        default:
index af99c5b..f5613b9 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/delay.h>       /* udelay, msleep                 */
 #include <linux/videodev2.h>   /* kernel radio structs           */
 #include <linux/mutex.h>
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #include <linux/io.h>          /* outb, outb_p                   */
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
@@ -43,6 +42,7 @@
 MODULE_AUTHOR("C.van Schaik");
 MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus.");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.3");
 
 #ifndef CONFIG_RADIO_ZOLTRIX_PORT
 #define CONFIG_RADIO_ZOLTRIX_PORT -1
@@ -55,8 +55,6 @@ module_param(io, int, 0);
 MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)");
 module_param(radio_nr, int, 0);
 
-#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
-
 struct zoltrix {
        struct v4l2_device v4l2_dev;
        struct video_device vdev;
@@ -228,7 +226,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strlcpy(v->driver, "radio-zoltrix", sizeof(v->driver));
        strlcpy(v->card, "Zoltrix Radio", sizeof(v->card));
        strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
-       v->version = RADIO_VERSION;
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
index a2a6777..fd3541b 100644 (file)
 
 /* driver definitions */
 #define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>";
-#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 1)
 #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
 #define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers"
-#define DRIVER_VERSION "1.0.1"
+#define DRIVER_VERSION "1.0.2"
 
 /* kernel includes */
 #include <linux/i2c.h>
@@ -248,7 +247,6 @@ int si470x_vidioc_querycap(struct file *file, void *priv,
 {
        strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
        strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
-       capability->version = DRIVER_KERNEL_VERSION;
        capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
                V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 
index 392e84f..4cf5370 100644 (file)
@@ -29,7 +29,6 @@
 
 /* driver definitions */
 #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
-#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 10)
 #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
 #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
 #define DRIVER_VERSION "1.0.10"
@@ -626,7 +625,6 @@ int si470x_vidioc_querycap(struct file *file, void *priv,
        strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
        usb_make_path(radio->usbdev, capability->bus_info,
                        sizeof(capability->bus_info));
-       capability->version = DRIVER_KERNEL_VERSION;
        capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
                V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
 
@@ -699,7 +697,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
        radio->videodev = video_device_alloc();
        if (!radio->videodev) {
                retval = -ENOMEM;
-               goto err_intbuffer;
+               goto err_urb;
        }
        memcpy(radio->videodev, &si470x_viddev_template,
                        sizeof(si470x_viddev_template));
@@ -790,6 +788,8 @@ err_all:
        kfree(radio->buffer);
 err_video:
        video_device_release(radio->videodev);
+err_urb:
+       usb_free_urb(radio->int_in_urb);
 err_intbuffer:
        kfree(radio->int_in_buffer);
 err_radio:
index 68da001..f300a55 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/input.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 #include <linux/mutex.h>
 #include <media/v4l2-common.h>
index 1a45a5d..d84ad9d 100644 (file)
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <linux/timer.h>
-#include <linux/version.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
 
-#define FM_DRV_VERSION            "0.10"
-/* Should match with FM_DRV_VERSION */
-#define FM_DRV_RADIO_VERSION      KERNEL_VERSION(0, 0, 1)
+#define FM_DRV_VERSION            "0.1.1"
 #define FM_DRV_NAME               "ti_fmdrv"
 #define FM_DRV_CARD_SHORT_NAME    "TI FM Radio"
 #define FM_DRV_CARD_LONG_NAME     "Texas Instruments FM Radio"
index 8701072..8c0e192 100644 (file)
@@ -175,7 +175,6 @@ static int fm_v4l2_vidioc_querycap(struct file *file, void *priv,
        strlcpy(capability->card, FM_DRV_CARD_SHORT_NAME,
                        sizeof(capability->card));
        sprintf(capability->bus_info, "UART");
-       capability->version = FM_DRV_RADIO_VERSION;
        capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
                V4L2_CAP_RADIO | V4L2_CAP_MODULATOR |
                V4L2_CAP_AUDIO | V4L2_CAP_READWRITE |
@@ -191,7 +190,7 @@ static int fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 
        switch (ctrl->id) {
        case  V4L2_CID_TUNE_ANTENNA_CAPACITOR:
-               ctrl->cur.val = fm_tx_get_tune_cap_val(fmdev);
+               ctrl->val = fm_tx_get_tune_cap_val(fmdev);
                break;
        default:
                fmwarn("%s: Unknown IOCTL: %d\n", __func__, ctrl->id);
index 7d4bbc2..899f783 100644 (file)
@@ -87,6 +87,17 @@ config IR_RC5_SZ_DECODER
           uses an IR protocol that is almost standard RC-5, but not quite,
           as it uses an additional bit).
 
+config IR_MCE_KBD_DECODER
+       tristate "Enable IR raw decoder for the MCE keyboard/mouse protocol"
+       depends on RC_CORE
+       select BITREVERSE
+       default y
+
+       ---help---
+          Enable this option if you have a Microsoft Remote Keyboard for
+          Windows Media Center Edition, which you would like to use with
+          a raw IR receiver in your system.
+
 config IR_LIRC_CODEC
        tristate "Enable IR to LIRC bridge"
        depends on RC_CORE
index 52830e5..f224db0 100644 (file)
@@ -10,6 +10,7 @@ obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
 obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
 obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
 obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
+obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
 obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
 
 # stand-alone IR receivers/transmitters
index a43ed6c..2b9c256 100644 (file)
@@ -953,13 +953,13 @@ static void ene_set_idle(struct rc_dev *rdev, bool idle)
 }
 
 /* outside interface: transmit */
-static int ene_transmit(struct rc_dev *rdev, int *buf, u32 n)
+static int ene_transmit(struct rc_dev *rdev, unsigned *buf, unsigned n)
 {
        struct ene_device *dev = rdev->priv;
        unsigned long flags;
 
        dev->tx_buffer = buf;
-       dev->tx_len = n / sizeof(int);
+       dev->tx_len = n;
        dev->tx_pos = 0;
        dev->tx_reg = 0;
        dev->tx_done = 0;
index 337a41d..017c209 100644 (file)
@@ -235,7 +235,7 @@ struct ene_device {
        bool tx_sample_pulse;                   /* current sample is pulse */
 
        /* TX buffer */
-       int *tx_buffer;                         /* input samples buffer*/
+       unsigned *tx_buffer;                    /* input samples buffer*/
        int tx_pos;                             /* position in that bufer */
        int tx_len;                             /* current len of tx buffer */
        int tx_done;                            /* done transmitting */
index 1c5cc65..e5eeec4 100644 (file)
@@ -103,19 +103,19 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
 {
        struct lirc_codec *lirc;
        struct rc_dev *dev;
-       int *txbuf; /* buffer with values to transmit */
-       int ret = 0;
+       unsigned int *txbuf; /* buffer with values to transmit */
+       ssize_t ret = 0;
        size_t count;
 
        lirc = lirc_get_pdata(file);
        if (!lirc)
                return -EFAULT;
 
-       if (n % sizeof(int))
+       if (n < sizeof(unsigned) || n % sizeof(unsigned))
                return -EINVAL;
 
-       count = n / sizeof(int);
-       if (count > LIRCBUF_SIZE || count % 2 == 0 || n % sizeof(int) != 0)
+       count = n / sizeof(unsigned);
+       if (count > LIRCBUF_SIZE || count % 2 == 0)
                return -EINVAL;
 
        txbuf = memdup_user(buf, n);
@@ -129,7 +129,10 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
        }
 
        if (dev->tx_ir)
-               ret = dev->tx_ir(dev, txbuf, (u32)n);
+               ret = dev->tx_ir(dev, txbuf, count);
+
+       if (ret > 0)
+               ret *= sizeof(unsigned);
 
 out:
        kfree(txbuf);
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
new file mode 100644 (file)
index 0000000..3784ebf
--- /dev/null
@@ -0,0 +1,449 @@
+/* ir-mce_kbd-decoder.c - A decoder for the RC6-ish keyboard/mouse IR protocol
+ * used by the Microsoft Remote Keyboard for Windows Media Center Edition,
+ * referred to by Microsoft's Windows Media Center remote specification docs
+ * as "an internal protocol called MCIR-2".
+ *
+ * Copyright (C) 2011 by Jarod Wilson <jarod@redhat.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 version 2 of the License.
+ *
+ * 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.
+ */
+#include <linux/module.h>
+
+#include "rc-core-priv.h"
+
+/*
+ * This decoder currently supports:
+ * - MCIR-2 29-bit IR signals used for mouse movement and buttons
+ * - MCIR-2 32-bit IR signals used for standard keyboard keys
+ *
+ * The media keys on the keyboard send RC-6 signals that are inditinguishable
+ * from the keys of the same name on the stock MCE remote, and will be handled
+ * by the standard RC-6 decoder, and be made available to the system via the
+ * input device for the remote, rather than the keyboard/mouse one.
+ */
+
+#define MCIR2_UNIT             333333  /* ns */
+#define MCIR2_HEADER_NBITS     5
+#define MCIR2_MOUSE_NBITS      29
+#define MCIR2_KEYBOARD_NBITS   32
+#define MCIR2_PREFIX_PULSE     (8 * MCIR2_UNIT)
+#define MCIR2_PREFIX_SPACE     (1 * MCIR2_UNIT)
+#define MCIR2_MAX_LEN          (3 * MCIR2_UNIT)
+#define MCIR2_BIT_START                (1 * MCIR2_UNIT)
+#define MCIR2_BIT_END          (1 * MCIR2_UNIT)
+#define MCIR2_BIT_0            (1 * MCIR2_UNIT)
+#define MCIR2_BIT_SET          (2 * MCIR2_UNIT)
+#define MCIR2_MODE_MASK                0xf     /* for the header bits */
+#define MCIR2_KEYBOARD_HEADER  0x4
+#define MCIR2_MOUSE_HEADER     0x1
+#define MCIR2_MASK_KEYS_START  0xe0
+
+enum mce_kbd_mode {
+       MCIR2_MODE_KEYBOARD,
+       MCIR2_MODE_MOUSE,
+       MCIR2_MODE_UNKNOWN,
+};
+
+enum mce_kbd_state {
+       STATE_INACTIVE,
+       STATE_HEADER_BIT_START,
+       STATE_HEADER_BIT_END,
+       STATE_BODY_BIT_START,
+       STATE_BODY_BIT_END,
+       STATE_FINISHED,
+};
+
+static unsigned char kbd_keycodes[256] = {
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_A,
+       KEY_B,          KEY_C,          KEY_D,          KEY_E,          KEY_F,
+       KEY_G,          KEY_H,          KEY_I,          KEY_J,          KEY_K,
+       KEY_L,          KEY_M,          KEY_N,          KEY_O,          KEY_P,
+       KEY_Q,          KEY_R,          KEY_S,          KEY_T,          KEY_U,
+       KEY_V,          KEY_W,          KEY_X,          KEY_Y,          KEY_Z,
+       KEY_1,          KEY_2,          KEY_3,          KEY_4,          KEY_5,
+       KEY_6,          KEY_7,          KEY_8,          KEY_9,          KEY_0,
+       KEY_ENTER,      KEY_ESC,        KEY_BACKSPACE,  KEY_TAB,        KEY_SPACE,
+       KEY_MINUS,      KEY_EQUAL,      KEY_LEFTBRACE,  KEY_RIGHTBRACE, KEY_BACKSLASH,
+       KEY_RESERVED,   KEY_SEMICOLON,  KEY_APOSTROPHE, KEY_GRAVE,      KEY_COMMA,
+       KEY_DOT,        KEY_SLASH,      KEY_CAPSLOCK,   KEY_F1,         KEY_F2,
+       KEY_F3,         KEY_F4,         KEY_F5,         KEY_F6,         KEY_F7,
+       KEY_F8,         KEY_F9,         KEY_F10,        KEY_F11,        KEY_F12,
+       KEY_SYSRQ,      KEY_SCROLLLOCK, KEY_PAUSE,      KEY_INSERT,     KEY_HOME,
+       KEY_PAGEUP,     KEY_DELETE,     KEY_END,        KEY_PAGEDOWN,   KEY_RIGHT,
+       KEY_LEFT,       KEY_DOWN,       KEY_UP,         KEY_NUMLOCK,    KEY_KPSLASH,
+       KEY_KPASTERISK, KEY_KPMINUS,    KEY_KPPLUS,     KEY_KPENTER,    KEY_KP1,
+       KEY_KP2,        KEY_KP3,        KEY_KP4,        KEY_KP5,        KEY_KP6,
+       KEY_KP7,        KEY_KP8,        KEY_KP9,        KEY_KP0,        KEY_KPDOT,
+       KEY_102ND,      KEY_COMPOSE,    KEY_POWER,      KEY_KPEQUAL,    KEY_F13,
+       KEY_F14,        KEY_F15,        KEY_F16,        KEY_F17,        KEY_F18,
+       KEY_F19,        KEY_F20,        KEY_F21,        KEY_F22,        KEY_F23,
+       KEY_F24,        KEY_OPEN,       KEY_HELP,       KEY_PROPS,      KEY_FRONT,
+       KEY_STOP,       KEY_AGAIN,      KEY_UNDO,       KEY_CUT,        KEY_COPY,
+       KEY_PASTE,      KEY_FIND,       KEY_MUTE,       KEY_VOLUMEUP,   KEY_VOLUMEDOWN,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_KPCOMMA,    KEY_RESERVED,
+       KEY_RO,         KEY_KATAKANAHIRAGANA, KEY_YEN,  KEY_HENKAN,     KEY_MUHENKAN,
+       KEY_KPJPCOMMA,  KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_HANGUEL,
+       KEY_HANJA,      KEY_KATAKANA,   KEY_HIRAGANA,   KEY_ZENKAKUHANKAKU, KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,   KEY_LEFTCTRL,
+       KEY_LEFTSHIFT,  KEY_LEFTALT,    KEY_LEFTMETA,   KEY_RIGHTCTRL,  KEY_RIGHTSHIFT,
+       KEY_RIGHTALT,   KEY_RIGHTMETA,  KEY_PLAYPAUSE,  KEY_STOPCD,     KEY_PREVIOUSSONG,
+       KEY_NEXTSONG,   KEY_EJECTCD,    KEY_VOLUMEUP,   KEY_VOLUMEDOWN, KEY_MUTE,
+       KEY_WWW,        KEY_BACK,       KEY_FORWARD,    KEY_STOP,       KEY_FIND,
+       KEY_SCROLLUP,   KEY_SCROLLDOWN, KEY_EDIT,       KEY_SLEEP,      KEY_COFFEE,
+       KEY_REFRESH,    KEY_CALC,       KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
+       KEY_RESERVED
+};
+
+static void mce_kbd_rx_timeout(unsigned long data)
+{
+       struct mce_kbd_dec *mce_kbd = (struct mce_kbd_dec *)data;
+       int i;
+       unsigned char maskcode;
+
+       IR_dprintk(2, "timer callback clearing all keys\n");
+
+       for (i = 0; i < 7; i++) {
+               maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
+               input_report_key(mce_kbd->idev, maskcode, 0);
+       }
+
+       for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
+               input_report_key(mce_kbd->idev, kbd_keycodes[i], 0);
+}
+
+static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data)
+{
+       switch (data->header & MCIR2_MODE_MASK) {
+       case MCIR2_KEYBOARD_HEADER:
+               return MCIR2_MODE_KEYBOARD;
+       case MCIR2_MOUSE_HEADER:
+               return MCIR2_MODE_MOUSE;
+       default:
+               return MCIR2_MODE_UNKNOWN;
+       }
+}
+
+static void ir_mce_kbd_process_keyboard_data(struct input_dev *idev,
+                                            u32 scancode)
+{
+       u8 keydata   = (scancode >> 8) & 0xff;
+       u8 shiftmask = scancode & 0xff;
+       unsigned char keycode, maskcode;
+       int i, keystate;
+
+       IR_dprintk(1, "keyboard: keydata = 0x%02x, shiftmask = 0x%02x\n",
+                  keydata, shiftmask);
+
+       for (i = 0; i < 7; i++) {
+               maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
+               if (shiftmask & (1 << i))
+                       keystate = 1;
+               else
+                       keystate = 0;
+               input_report_key(idev, maskcode, keystate);
+       }
+
+       if (keydata) {
+               keycode = kbd_keycodes[keydata];
+               input_report_key(idev, keycode, 1);
+       } else {
+               for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
+                       input_report_key(idev, kbd_keycodes[i], 0);
+       }
+}
+
+static void ir_mce_kbd_process_mouse_data(struct input_dev *idev, u32 scancode)
+{
+       /* raw mouse coordinates */
+       u8 xdata = (scancode >> 7) & 0x7f;
+       u8 ydata = (scancode >> 14) & 0x7f;
+       int x, y;
+       /* mouse buttons */
+       bool right = scancode & 0x40;
+       bool left  = scancode & 0x20;
+
+       if (xdata & 0x40)
+               x = -((~xdata & 0x7f) + 1);
+       else
+               x = xdata;
+
+       if (ydata & 0x40)
+               y = -((~ydata & 0x7f) + 1);
+       else
+               y = ydata;
+
+       IR_dprintk(1, "mouse: x = %d, y = %d, btns = %s%s\n",
+                  x, y, left ? "L" : "", right ? "R" : "");
+
+       input_report_rel(idev, REL_X, x);
+       input_report_rel(idev, REL_Y, y);
+
+       input_report_key(idev, BTN_LEFT, left);
+       input_report_key(idev, BTN_RIGHT, right);
+}
+
+/**
+ * ir_mce_kbd_decode() - Decode one mce_kbd pulse or space
+ * @dev:       the struct rc_dev descriptor of the device
+ * @ev:                the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+       struct mce_kbd_dec *data = &dev->raw->mce_kbd;
+       u32 scancode;
+       unsigned long delay;
+
+       if (!(dev->raw->enabled_protocols & RC_TYPE_MCE_KBD))
+               return 0;
+
+       if (!is_timing_event(ev)) {
+               if (ev.reset)
+                       data->state = STATE_INACTIVE;
+               return 0;
+       }
+
+       if (!geq_margin(ev.duration, MCIR2_UNIT, MCIR2_UNIT / 2))
+               goto out;
+
+again:
+       IR_dprintk(2, "started at state %i (%uus %s)\n",
+                  data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+
+       if (!geq_margin(ev.duration, MCIR2_UNIT, MCIR2_UNIT / 2))
+               return 0;
+
+       switch (data->state) {
+
+       case STATE_INACTIVE:
+               if (!ev.pulse)
+                       break;
+
+               /* Note: larger margin on first pulse since each MCIR2_UNIT
+                  is quite short and some hardware takes some time to
+                  adjust to the signal */
+               if (!eq_margin(ev.duration, MCIR2_PREFIX_PULSE, MCIR2_UNIT))
+                       break;
+
+               data->state = STATE_HEADER_BIT_START;
+               data->count = 0;
+               data->header = 0;
+               return 0;
+
+       case STATE_HEADER_BIT_START:
+               if (geq_margin(ev.duration, MCIR2_MAX_LEN, MCIR2_UNIT / 2))
+                       break;
+
+               data->header <<= 1;
+               if (ev.pulse)
+                       data->header |= 1;
+               data->count++;
+               data->state = STATE_HEADER_BIT_END;
+               return 0;
+
+       case STATE_HEADER_BIT_END:
+               if (!is_transition(&ev, &dev->raw->prev_ev))
+                       break;
+
+               decrease_duration(&ev, MCIR2_BIT_END);
+
+               if (data->count != MCIR2_HEADER_NBITS) {
+                       data->state = STATE_HEADER_BIT_START;
+                       goto again;
+               }
+
+               switch (mce_kbd_mode(data)) {
+               case MCIR2_MODE_KEYBOARD:
+                       data->wanted_bits = MCIR2_KEYBOARD_NBITS;
+                       break;
+               case MCIR2_MODE_MOUSE:
+                       data->wanted_bits = MCIR2_MOUSE_NBITS;
+                       break;
+               default:
+                       IR_dprintk(1, "not keyboard or mouse data\n");
+                       goto out;
+               }
+
+               data->count = 0;
+               data->body = 0;
+               data->state = STATE_BODY_BIT_START;
+               goto again;
+
+       case STATE_BODY_BIT_START:
+               if (geq_margin(ev.duration, MCIR2_MAX_LEN, MCIR2_UNIT / 2))
+                       break;
+
+               data->body <<= 1;
+               if (ev.pulse)
+                       data->body |= 1;
+               data->count++;
+               data->state = STATE_BODY_BIT_END;
+               return 0;
+
+       case STATE_BODY_BIT_END:
+               if (!is_transition(&ev, &dev->raw->prev_ev))
+                       break;
+
+               if (data->count == data->wanted_bits)
+                       data->state = STATE_FINISHED;
+               else
+                       data->state = STATE_BODY_BIT_START;
+
+               decrease_duration(&ev, MCIR2_BIT_END);
+               goto again;
+
+       case STATE_FINISHED:
+               if (ev.pulse)
+                       break;
+
+               switch (data->wanted_bits) {
+               case MCIR2_KEYBOARD_NBITS:
+                       scancode = data->body & 0xffff;
+                       IR_dprintk(1, "keyboard data 0x%08x\n", data->body);
+                       if (dev->timeout)
+                               delay = usecs_to_jiffies(dev->timeout / 1000);
+                       else
+                               delay = msecs_to_jiffies(100);
+                       mod_timer(&data->rx_timeout, jiffies + delay);
+                       /* Pass data to keyboard buffer parser */
+                       ir_mce_kbd_process_keyboard_data(data->idev, scancode);
+                       break;
+               case MCIR2_MOUSE_NBITS:
+                       scancode = data->body & 0x1fffff;
+                       IR_dprintk(1, "mouse data 0x%06x\n", scancode);
+                       /* Pass data to mouse buffer parser */
+                       ir_mce_kbd_process_mouse_data(data->idev, scancode);
+                       break;
+               default:
+                       IR_dprintk(1, "not keyboard or mouse data\n");
+                       goto out;
+               }
+
+               data->state = STATE_INACTIVE;
+               input_sync(data->idev);
+               return 0;
+       }
+
+out:
+       IR_dprintk(1, "failed at state %i (%uus %s)\n",
+                  data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+       data->state = STATE_INACTIVE;
+       input_sync(data->idev);
+       return -EINVAL;
+}
+
+static int ir_mce_kbd_register(struct rc_dev *dev)
+{
+       struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd;
+       struct input_dev *idev;
+       int i, ret;
+
+       idev = input_allocate_device();
+       if (!idev)
+               return -ENOMEM;
+
+       snprintf(mce_kbd->name, sizeof(mce_kbd->name),
+                "MCE IR Keyboard/Mouse (%s)", dev->driver_name);
+       strlcat(mce_kbd->phys, "/input0", sizeof(mce_kbd->phys));
+
+       idev->name = mce_kbd->name;
+       idev->phys = mce_kbd->phys;
+
+       /* Keyboard bits */
+       set_bit(EV_KEY, idev->evbit);
+       set_bit(EV_REP, idev->evbit);
+       for (i = 0; i < sizeof(kbd_keycodes); i++)
+               set_bit(kbd_keycodes[i], idev->keybit);
+
+       /* Mouse bits */
+       set_bit(EV_REL, idev->evbit);
+       set_bit(REL_X, idev->relbit);
+       set_bit(REL_Y, idev->relbit);
+       set_bit(BTN_LEFT, idev->keybit);
+       set_bit(BTN_RIGHT, idev->keybit);
+
+       /* Report scancodes too */
+       set_bit(EV_MSC, idev->evbit);
+       set_bit(MSC_SCAN, idev->mscbit);
+
+       setup_timer(&mce_kbd->rx_timeout, mce_kbd_rx_timeout,
+                   (unsigned long)mce_kbd);
+
+       input_set_drvdata(idev, mce_kbd);
+
+#if 0
+       /* Adding this reference means two input devices are associated with
+        * this rc-core device, which ir-keytable doesn't cope with yet */
+       idev->dev.parent = &dev->dev;
+#endif
+
+       ret = input_register_device(idev);
+       if (ret < 0) {
+               input_free_device(idev);
+               return -EIO;
+       }
+
+       mce_kbd->idev = idev;
+
+       return 0;
+}
+
+static int ir_mce_kbd_unregister(struct rc_dev *dev)
+{
+       struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd;
+       struct input_dev *idev = mce_kbd->idev;
+
+       del_timer_sync(&mce_kbd->rx_timeout);
+       input_unregister_device(idev);
+
+       return 0;
+}
+
+static struct ir_raw_handler mce_kbd_handler = {
+       .protocols      = RC_TYPE_MCE_KBD,
+       .decode         = ir_mce_kbd_decode,
+       .raw_register   = ir_mce_kbd_register,
+       .raw_unregister = ir_mce_kbd_unregister,
+};
+
+static int __init ir_mce_kbd_decode_init(void)
+{
+       ir_raw_handler_register(&mce_kbd_handler);
+
+       printk(KERN_INFO "IR MCE Keyboard/mouse protocol handler initialized\n");
+       return 0;
+}
+
+static void __exit ir_mce_kbd_decode_exit(void)
+{
+       ir_raw_handler_unregister(&mce_kbd_handler);
+}
+
+module_init(ir_mce_kbd_decode_init);
+module_exit(ir_mce_kbd_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
+MODULE_DESCRIPTION("MCE Keyboard/mouse IR protocol decoder");
index 423ed45..27808bb 100644 (file)
@@ -355,6 +355,7 @@ static void init_decoders(struct work_struct *work)
        load_rc6_decode();
        load_jvc_decode();
        load_sony_decode();
+       load_mce_kbd_decode();
        load_lirc_codec();
 
        /* If needed, we may later add some init code. In this case,
index d20168f..682009d 100644 (file)
@@ -382,7 +382,7 @@ static int ite_set_tx_duty_cycle(struct rc_dev *rcdev, u32 duty_cycle)
 /* transmit out IR pulses; what you get here is a batch of alternating
  * pulse/space/pulse/space lengths that we should write out completely through
  * the FIFO, blocking on a full FIFO */
-static int ite_tx_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
+static int ite_tx_ir(struct rc_dev *rcdev, unsigned *txbuf, unsigned n)
 {
        unsigned long flags;
        struct ite_dev *dev = rcdev->priv;
@@ -398,9 +398,6 @@ static int ite_tx_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
        /* clear the array just in case */
        memset(last_sent, 0, ARRAY_SIZE(last_sent));
 
-       /* n comes in bytes; convert to ints */
-       n /= sizeof(int);
-
        spin_lock_irqsave(&dev->lock, flags);
 
        /* let everybody know we're now transmitting */
index 01b69bc..c3907e2 100644 (file)
@@ -29,7 +29,7 @@ static struct rc_map_table rc6_mce[] = {
 
        { 0x800f040a, KEY_DELETE },
        { 0x800f040b, KEY_ENTER },
-       { 0x800f040c, KEY_POWER },              /* PC Power */
+       { 0x800f040c, KEY_SLEEP },              /* Formerly PC Power */
        { 0x800f040d, KEY_MEDIA },              /* Windows MCE button */
        { 0x800f040e, KEY_MUTE },
        { 0x800f040f, KEY_INFO },
@@ -44,7 +44,6 @@ static struct rc_map_table rc6_mce[] = {
        { 0x800f0416, KEY_PLAY },
        { 0x800f0417, KEY_RECORD },
        { 0x800f0418, KEY_PAUSE },
-       { 0x800f046e, KEY_PLAYPAUSE },
        { 0x800f0419, KEY_STOP },
        { 0x800f041a, KEY_NEXT },
        { 0x800f041b, KEY_PREVIOUS },
index ec972dc..85ff9a1 100644 (file)
@@ -692,20 +692,18 @@ static void mce_flush_rx_buffer(struct mceusb_dev *ir, int size)
 }
 
 /* Send data out the IR blaster port(s) */
-static int mceusb_tx_ir(struct rc_dev *dev, int *txbuf, u32 n)
+static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
 {
        struct mceusb_dev *ir = dev->priv;
        int i, ret = 0;
-       int count, cmdcount = 0;
+       int cmdcount = 0;
        unsigned char *cmdbuf; /* MCE command buffer */
        long signal_duration = 0; /* Singnal length in us */
        struct timeval start_time, end_time;
 
        do_gettimeofday(&start_time);
 
-       count = n / sizeof(int);
-
-       cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL);
+       cmdbuf = kzalloc(sizeof(unsigned) * MCE_CMDBUF_SIZE, GFP_KERNEL);
        if (!cmdbuf)
                return -ENOMEM;
 
@@ -774,7 +772,7 @@ static int mceusb_tx_ir(struct rc_dev *dev, int *txbuf, u32 n)
 
 out:
        kfree(cmdbuf);
-       return ret ? ret : n;
+       return ret ? ret : count;
 }
 
 /* Sets active IR outputs -- mce devices typically have two */
index ce595f9..eae05b5 100644 (file)
@@ -546,24 +546,18 @@ static int nvt_set_tx_carrier(struct rc_dev *dev, u32 carrier)
  * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to
  * set TXFCONT as 0xff, until buf_count less than 0xff.
  */
-static int nvt_tx_ir(struct rc_dev *dev, int *txbuf, u32 n)
+static int nvt_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned n)
 {
        struct nvt_dev *nvt = dev->priv;
        unsigned long flags;
-       size_t cur_count;
        unsigned int i;
        u8 iren;
        int ret;
 
        spin_lock_irqsave(&nvt->tx.lock, flags);
 
-       if (n >= TX_BUF_LEN) {
-               nvt->tx.buf_count = cur_count = TX_BUF_LEN;
-               ret = TX_BUF_LEN;
-       } else {
-               nvt->tx.buf_count = cur_count = n;
-               ret = n;
-       }
+       ret = min((unsigned)(TX_BUF_LEN / sizeof(unsigned)), n);
+       nvt->tx.buf_count = (ret * sizeof(unsigned));
 
        memcpy(nvt->tx.buf, txbuf, nvt->tx.buf_count);
 
index 873b387..04c2c72 100644 (file)
@@ -84,6 +84,17 @@ struct ir_raw_event_ctrl {
                unsigned count;
                unsigned wanted_bits;
        } rc5_sz;
+       struct mce_kbd_dec {
+               struct input_dev *idev;
+               struct timer_list rx_timeout;
+               char name[64];
+               char phys[64];
+               int state;
+               u8 header;
+               u32 body;
+               unsigned count;
+               unsigned wanted_bits;
+       } mce_kbd;
        struct lirc_codec {
                struct rc_dev *dev;
                struct lirc_driver *drv;
@@ -182,6 +193,13 @@ void ir_raw_init(void);
 #define load_sony_decode()     0
 #endif
 
+/* from ir-mce_kbd-decoder.c */
+#ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE
+#define load_mce_kbd_decode()  request_module("ir-mce_kbd-decoder")
+#else
+#define load_mce_kbd_decode()  0
+#endif
+
 /* from ir-lirc-codec.c */
 #ifdef CONFIG_IR_LIRC_CODEC_MODULE
 #define load_lirc_codec()      request_module("ir-lirc-codec")
index cc846b2..efc6a51 100644 (file)
@@ -101,21 +101,14 @@ static int loop_set_rx_carrier_range(struct rc_dev *dev, u32 min, u32 max)
        return 0;
 }
 
-static int loop_tx_ir(struct rc_dev *dev, int *txbuf, u32 n)
+static int loop_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
 {
        struct loopback_dev *lodev = dev->priv;
        u32 rxmask;
-       unsigned count;
        unsigned total_duration = 0;
        unsigned i;
        DEFINE_IR_RAW_EVENT(rawir);
 
-       if (n == 0 || n % sizeof(int)) {
-               dprintk("invalid tx buffer size\n");
-               return -EINVAL;
-       }
-
-       count = n / sizeof(int);
        for (i = 0; i < count; i++)
                total_duration += abs(txbuf[i]);
 
@@ -142,7 +135,7 @@ static int loop_tx_ir(struct rc_dev *dev, int *txbuf, u32 n)
 
        for (i = 0; i < count; i++) {
                rawir.pulse = i % 2 ? false : true;
-               rawir.duration = abs(txbuf[i]) * 1000;
+               rawir.duration = txbuf[i] * 1000;
                if (rawir.duration)
                        ir_raw_event_store_with_filter(dev, &rawir);
        }
@@ -158,7 +151,7 @@ out:
        /* Lirc expects this function to take as long as the total duration */
        set_current_state(TASK_INTERRUPTIBLE);
        schedule_timeout(usecs_to_jiffies(total_duration));
-       return n;
+       return count;
 }
 
 static void loop_set_idle(struct rc_dev *dev, bool enable)
index 3186ac7..51a23f4 100644 (file)
@@ -735,6 +735,7 @@ static struct {
        { RC_TYPE_JVC,          "jvc"           },
        { RC_TYPE_SONY,         "sony"          },
        { RC_TYPE_RC5_SZ,       "rc-5-sz"       },
+       { RC_TYPE_MCE_KBD,      "mce_kbd"       },
        { RC_TYPE_LIRC,         "lirc"          },
        { RC_TYPE_OTHER,        "other"         },
 };
@@ -1099,7 +1100,6 @@ int rc_register_device(struct rc_dev *dev)
                if (rc < 0)
                        goto out_input;
        }
-       mutex_unlock(&dev->lock);
 
        if (dev->change_protocol) {
                rc = dev->change_protocol(dev, rc_map->rc_type);
@@ -1107,6 +1107,8 @@ int rc_register_device(struct rc_dev *dev)
                        goto out_raw;
        }
 
+       mutex_unlock(&dev->lock);
+
        IR_dprintk(1, "Registered rc%ld (driver: %s, remote: %s, mode %s)\n",
                   dev->devno,
                   dev->driver_name ? dev->driver_name : "unknown",
index 5147767..a166044 100644 (file)
@@ -205,6 +205,7 @@ struct redrat3_dev {
 
        /* rx signal timeout timer */
        struct timer_list rx_timeout;
+       u32 hw_timeout;
 
        /* Is the device currently receiving? */
        bool recv_in_progress;
@@ -414,20 +415,10 @@ static u32 redrat3_us_to_len(u32 microsec)
 
 }
 
-/* timer callback to send long trailing space on receive timeout */
+/* timer callback to send reset event */
 static void redrat3_rx_timeout(unsigned long data)
 {
        struct redrat3_dev *rr3 = (struct redrat3_dev *)data;
-       DEFINE_IR_RAW_EVENT(rawir);
-
-       rawir.pulse = false;
-       rawir.duration = rr3->rc->timeout;
-       rr3_dbg(rr3->dev, "storing trailing space with duration %d\n",
-               rawir.duration);
-       ir_raw_event_store_with_filter(rr3->rc, &rawir);
-
-       rr3_dbg(rr3->dev, "calling ir_raw_event_handle\n");
-       ir_raw_event_handle(rr3->rc);
 
        rr3_dbg(rr3->dev, "calling ir_raw_event_reset\n");
        ir_raw_event_reset(rr3->rc);
@@ -438,7 +429,7 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
        DEFINE_IR_RAW_EVENT(rawir);
        struct redrat3_signal_header header;
        struct device *dev;
-       int i;
+       int i, trailer = 0;
        unsigned long delay;
        u32 mod_freq, single_len;
        u16 *len_vals;
@@ -464,7 +455,8 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
        if (!(header.length >= RR3_HEADER_LENGTH))
                dev_warn(dev, "read returned less than rr3 header len\n");
 
-       delay = usecs_to_jiffies(rr3->rc->timeout / 1000);
+       /* Make sure we reset the IR kfifo after a bit of inactivity */
+       delay = usecs_to_jiffies(rr3->hw_timeout);
        mod_timer(&rr3->rx_timeout, jiffies + delay);
 
        memcpy(&tmp32, sig_data + RR3_PAUSE_OFFSET, sizeof(tmp32));
@@ -506,9 +498,6 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
                u16 val = len_vals[data_vals[i]];
                single_len = redrat3_len_to_us((u32)be16_to_cpu(val));
 
-               /* cap the value to IR_MAX_DURATION */
-               single_len &= IR_MAX_DURATION;
-
                /* we should always get pulse/space/pulse/space samples */
                if (i % 2)
                        rawir.pulse = false;
@@ -516,6 +505,12 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
                        rawir.pulse = true;
 
                rawir.duration = US_TO_NS(single_len);
+               /* Save initial pulse length to fudge trailer */
+               if (i == 0)
+                       trailer = rawir.duration;
+               /* cap the value to IR_MAX_DURATION */
+               rawir.duration &= IR_MAX_DURATION;
+
                rr3_dbg(dev, "storing %s with duration %d (i: %d)\n",
                        rawir.pulse ? "pulse" : "space", rawir.duration, i);
                ir_raw_event_store_with_filter(rr3->rc, &rawir);
@@ -525,7 +520,10 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
        if (i % 2) {
                rawir.pulse = false;
                /* this duration is made up, and may not be ideal... */
-               rawir.duration = rr3->rc->timeout / 2;
+               if (trailer < US_TO_NS(1000))
+                       rawir.duration = US_TO_NS(2800);
+               else
+                       rawir.duration = trailer;
                rr3_dbg(dev, "storing trailing space with duration %d\n",
                        rawir.duration);
                ir_raw_event_store_with_filter(rr3->rc, &rawir);
@@ -629,36 +627,31 @@ static inline void redrat3_delete(struct redrat3_dev *rr3,
        kfree(rr3);
 }
 
-static u32 redrat3_get_timeout(struct device *dev,
-                              struct rc_dev *rc, struct usb_device *udev)
+static u32 redrat3_get_timeout(struct redrat3_dev *rr3)
 {
        u32 *tmp;
-       u32 timeout = MS_TO_NS(150); /* a sane default, if things go haywire */
+       u32 timeout = MS_TO_US(150); /* a sane default, if things go haywire */
        int len, ret, pipe;
 
        len = sizeof(*tmp);
        tmp = kzalloc(len, GFP_KERNEL);
        if (!tmp) {
-               dev_warn(dev, "Memory allocation faillure\n");
+               dev_warn(rr3->dev, "Memory allocation faillure\n");
                return timeout;
        }
 
-       pipe = usb_rcvctrlpipe(udev, 0);
-       ret = usb_control_msg(udev, pipe, RR3_GET_IR_PARAM,
+       pipe = usb_rcvctrlpipe(rr3->udev, 0);
+       ret = usb_control_msg(rr3->udev, pipe, RR3_GET_IR_PARAM,
                              USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
                              RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, HZ * 5);
        if (ret != len) {
-               dev_warn(dev, "Failed to read timeout from hardware\n");
+               dev_warn(rr3->dev, "Failed to read timeout from hardware\n");
                return timeout;
        }
 
-       timeout = US_TO_NS(redrat3_len_to_us(be32_to_cpu(*tmp)));
-       if (timeout < rc->min_timeout)
-               timeout = rc->min_timeout;
-       else if (timeout > rc->max_timeout)
-               timeout = rc->max_timeout;
+       timeout = redrat3_len_to_us(be32_to_cpu(*tmp));
 
-       rr3_dbg(dev, "Got timeout of %d ms\n", timeout / (1000 * 1000));
+       rr3_dbg(rr3->dev, "Got timeout of %d ms\n", timeout / 1000);
        return timeout;
 }
 
@@ -1110,9 +1103,7 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)
        rc->priv = rr3;
        rc->driver_type = RC_DRIVER_IR_RAW;
        rc->allowed_protos = RC_TYPE_ALL;
-       rc->min_timeout = MS_TO_NS(RR3_RX_MIN_TIMEOUT);
-       rc->max_timeout = MS_TO_NS(RR3_RX_MAX_TIMEOUT);
-       rc->timeout = redrat3_get_timeout(dev, rc, rr3->udev);
+       rc->timeout = US_TO_NS(2750);
        rc->tx_ir = redrat3_transmit_ir;
        rc->s_tx_carrier = redrat3_set_tx_carrier;
        rc->driver_name = DRIVER_NAME;
@@ -1186,7 +1177,7 @@ static int __devinit redrat3_dev_probe(struct usb_interface *intf,
        rr3 = kzalloc(sizeof(*rr3), GFP_KERNEL);
        if (rr3 == NULL) {
                dev_err(dev, "Memory allocation failure\n");
-               goto error;
+               goto no_endpoints;
        }
 
        rr3->dev = &intf->dev;
@@ -1242,6 +1233,9 @@ static int __devinit redrat3_dev_probe(struct usb_interface *intf,
        if (retval < 0)
                goto error;
 
+       /* store current hardware timeout, in us, will use for kfifo resets */
+       rr3->hw_timeout = redrat3_get_timeout(rr3);
+
        /* default.. will get overridden by any sends with a freq defined */
        rr3->carrier = 38000;
 
@@ -1280,6 +1274,7 @@ static void __devexit redrat3_dev_disconnect(struct usb_interface *intf)
 
        usb_set_intfdata(intf, NULL);
        rc_unregister_device(rr3->rc);
+       del_timer_sync(&rr3->rx_timeout);
        redrat3_delete(rr3, udev);
 
        rr3_ftr(&intf->dev, "RedRat3 IR Transceiver now disconnected\n");
index 5d06b89..bec8abc 100644 (file)
@@ -6,8 +6,8 @@
  *  could probably support others (Winbond WEC102X, NatSemi, etc)
  *  with minor modifications.
  *
- *  Original Author: David Härdeman <david@hardeman.nu>
- *     Copyright (C) 2009 - 2010 David Härdeman <david@hardeman.nu>
+ *  Original Author: David Härdeman <david@hardeman.nu>
+ *     Copyright (C) 2009 - 2011 David Härdeman <david@hardeman.nu>
  *
  *  Dedicated to my daughter Matilda, without whose loving attention this
  *  driver would have been finished in half the time and with a fraction
@@ -577,16 +577,12 @@ wbcir_txmask(struct rc_dev *dev, u32 mask)
 }
 
 static int
-wbcir_tx(struct rc_dev *dev, int *buf, u32 bufsize)
+wbcir_tx(struct rc_dev *dev, unsigned *buf, unsigned count)
 {
        struct wbcir_data *data = dev->priv;
-       u32 count;
        unsigned i;
        unsigned long flags;
 
-       /* bufsize has been sanity checked by the caller */
-       count = bufsize / sizeof(int);
-
        /* Not sure if this is possible, but better safe than sorry */
        spin_lock_irqsave(&data->spinlock, flags);
        if (data->txstate != WBCIR_TXSTATE_INACTIVE) {
@@ -876,18 +872,8 @@ wbcir_init_hw(struct wbcir_data *data)
        /* prescaler 1.0, tx/rx fifo lvl 16 */
        outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2);
 
-       /* Set baud divisor to generate one byte per bit/cell */
-       switch (protocol) {
-       case IR_PROTOCOL_RC5:
-               outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL);
-               break;
-       case IR_PROTOCOL_RC6:
-               outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL);
-               break;
-       case IR_PROTOCOL_NEC:
-               outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL);
-               break;
-       }
+       /* Set baud divisor to sample every 10 us */
+       outb(0x0F, data->sbase + WBCIR_REG_SP3_BGDL);
        outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);
 
        /* Set CEIR mode */
@@ -896,9 +882,9 @@ wbcir_init_hw(struct wbcir_data *data)
        inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */
        inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */
 
-       /* Disable RX demod, run-length encoding/decoding, set freq span */
+       /* Disable RX demod, enable run-length enc/dec, set freq span */
        wbcir_select_bank(data, WBCIR_BANK_7);
-       outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG);
+       outb(0x90, data->sbase + WBCIR_REG_SP3_RCCFG);
 
        /* Disable timer */
        wbcir_select_bank(data, WBCIR_BANK_4);
index bb53de7..f574dc0 100644 (file)
@@ -489,6 +489,15 @@ config VIDEO_TCM825X
          This is a driver for the Toshiba TCM825x VGA camera sensor.
          It is used for example in Nokia N800.
 
+comment "Flash devices"
+
+config VIDEO_ADP1653
+       tristate "ADP1653 flash support"
+       depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+       ---help---
+         This is a driver for the ADP1653 flash controller. It is used for
+         example in Nokia N900.
+
 comment "Video improvement chips"
 
 config VIDEO_UPD64031A
@@ -707,6 +716,8 @@ source "drivers/media/video/cx18/Kconfig"
 
 source "drivers/media/video/saa7164/Kconfig"
 
+source "drivers/media/video/marvell-ccic/Kconfig"
+
 config VIDEO_M32R_AR
        tristate "AR devices"
        depends on M32R && VIDEO_V4L2
@@ -726,15 +737,6 @@ config VIDEO_M32R_AR_M64278
          To compile this driver as a module, choose M here: the
          module will be called arv.
 
-config VIDEO_CAFE_CCIC
-       tristate "Marvell 88ALP01 (Cafe) CMOS Camera Controller support"
-       depends on PCI && I2C && VIDEO_V4L2
-       select VIDEO_OV7670
-       ---help---
-         This is a video4linux2 driver for the Marvell 88ALP01 integrated
-         CMOS camera controller.  This is the controller found on first-
-         generation OLPC systems.
-
 config VIDEO_SR030PC30
        tristate "SR030PC30 VGA camera sensor support"
        depends on I2C && VIDEO_V4L2
@@ -846,6 +848,12 @@ config SOC_CAMERA_OV2640
        help
          This is a ov2640 camera driver
 
+config SOC_CAMERA_OV5642
+       tristate "ov5642 camera support"
+       depends on SOC_CAMERA && I2C
+       help
+         This is a V4L2 camera driver for the OmniVision OV5642 sensor
+
 config SOC_CAMERA_OV6650
        tristate "ov6650 sensor support"
        depends on SOC_CAMERA && I2C
@@ -952,6 +960,14 @@ config  VIDEO_SAMSUNG_S5P_FIMC
          To compile this driver as a module, choose M here: the
          module will be called s5p-fimc.
 
+config VIDEO_ATMEL_ISI
+       tristate "ATMEL Image Sensor Interface (ISI) support"
+       depends on VIDEO_DEV && SOC_CAMERA && ARCH_AT91
+       select VIDEOBUF2_DMA_CONTIG
+       ---help---
+         This module makes the ATMEL Image Sensor Interface available
+         as a v4l2 device.
+
 config VIDEO_S5P_MIPI_CSIS
        tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver"
        depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P && VIDEO_V4L2_SUBDEV_API
@@ -961,6 +977,8 @@ config VIDEO_S5P_MIPI_CSIS
          To compile this driver as a module, choose M here: the
          module will be called s5p-csis.
 
+source "drivers/media/video/s5p-tv/Kconfig"
+
 #
 # USB Multimedia device configuration
 #
@@ -1056,4 +1074,12 @@ config VIDEO_MEM2MEM_TESTDEV
          framework.
 
 
+config VIDEO_SAMSUNG_S5P_MFC
+       tristate "Samsung S5P MFC 5.1 Video Codec"
+       depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
+       select VIDEOBUF2_DMA_CONTIG
+       default n
+       help
+           MFC 5.1 driver for V4L2.
+
 endif # V4L_MEM2MEM_DRIVERS
index f0fecd6..2723900 100644 (file)
@@ -70,6 +70,7 @@ obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
 obj-$(CONFIG_VIDEO_SR030PC30)  += sr030pc30.o
 obj-$(CONFIG_VIDEO_NOON010PC30)        += noon010pc30.o
 obj-$(CONFIG_VIDEO_M5MOLS)     += m5mols/
+obj-$(CONFIG_VIDEO_ADP1653)    += adp1653.o
 
 obj-$(CONFIG_SOC_CAMERA_IMX074)                += imx074.o
 obj-$(CONFIG_SOC_CAMERA_MT9M001)       += mt9m001.o
@@ -78,6 +79,7 @@ obj-$(CONFIG_SOC_CAMERA_MT9T031)      += mt9t031.o
 obj-$(CONFIG_SOC_CAMERA_MT9T112)       += mt9t112.o
 obj-$(CONFIG_SOC_CAMERA_MT9V022)       += mt9v022.o
 obj-$(CONFIG_SOC_CAMERA_OV2640)                += ov2640.o
+obj-$(CONFIG_SOC_CAMERA_OV5642)                += ov5642.o
 obj-$(CONFIG_SOC_CAMERA_OV6650)                += ov6650.o
 obj-$(CONFIG_SOC_CAMERA_OV772X)                += ov772x.o
 obj-$(CONFIG_SOC_CAMERA_OV9640)                += ov9640.o
@@ -127,7 +129,8 @@ obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
 
 obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
 
-obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
+obj-$(CONFIG_VIDEO_CAFE_CCIC) += marvell-ccic/
+obj-$(CONFIG_VIDEO_MMP_CAMERA) += marvell-ccic/
 
 obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
 
@@ -166,8 +169,11 @@ obj-$(CONFIG_VIDEO_PXA27x)         += pxa_camera.o
 obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2)     += sh_mobile_csi2.o
 obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)      += sh_mobile_ceu_camera.o
 obj-$(CONFIG_VIDEO_OMAP1)              += omap1_camera.o
+obj-$(CONFIG_VIDEO_ATMEL_ISI)          += atmel-isi.o
 
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC)   += s5p-fimc/
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC)    += s5p-mfc/
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV)     += s5p-tv/
 
 obj-$(CONFIG_ARCH_DAVINCI)             += davinci/
 
diff --git a/drivers/media/video/adp1653.c b/drivers/media/video/adp1653.c
new file mode 100644 (file)
index 0000000..be7befd
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+ * drivers/media/video/adp1653.c
+ *
+ * Copyright (C) 2008--2011 Nokia Corporation
+ *
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * Contributors:
+ *     Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *     Tuukka Toivonen <tuukkat76@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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * TODO:
+ * - fault interrupt handling
+ * - hardware strobe
+ * - power doesn't need to be ON if all lights are off
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <media/adp1653.h>
+#include <media/v4l2-device.h>
+
+#define TIMEOUT_MAX            820000
+#define TIMEOUT_STEP           54600
+#define TIMEOUT_MIN            (TIMEOUT_MAX - ADP1653_REG_CONFIG_TMR_SET_MAX \
+                                * TIMEOUT_STEP)
+#define TIMEOUT_US_TO_CODE(t)  ((TIMEOUT_MAX + (TIMEOUT_STEP / 2) - (t)) \
+                                / TIMEOUT_STEP)
+#define TIMEOUT_CODE_TO_US(c)  (TIMEOUT_MAX - (c) * TIMEOUT_STEP)
+
+/* Write values into ADP1653 registers. */
+static int adp1653_update_hw(struct adp1653_flash *flash)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+       u8 out_sel;
+       u8 config = 0;
+       int rval;
+
+       out_sel = ADP1653_INDICATOR_INTENSITY_uA_TO_REG(
+               flash->indicator_intensity->val)
+               << ADP1653_REG_OUT_SEL_ILED_SHIFT;
+
+       switch (flash->led_mode->val) {
+       case V4L2_FLASH_LED_MODE_NONE:
+               break;
+       case V4L2_FLASH_LED_MODE_FLASH:
+               /* Flash mode, light on with strobe, duration from timer */
+               config = ADP1653_REG_CONFIG_TMR_CFG;
+               config |= TIMEOUT_US_TO_CODE(flash->flash_timeout->val)
+                         << ADP1653_REG_CONFIG_TMR_SET_SHIFT;
+               break;
+       case V4L2_FLASH_LED_MODE_TORCH:
+               /* Torch mode, light immediately on, duration indefinite */
+               out_sel |= ADP1653_FLASH_INTENSITY_mA_TO_REG(
+                       flash->torch_intensity->val)
+                       << ADP1653_REG_OUT_SEL_HPLED_SHIFT;
+               break;
+       }
+
+       rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
+       if (rval < 0)
+               return rval;
+
+       rval = i2c_smbus_write_byte_data(client, ADP1653_REG_CONFIG, config);
+       if (rval < 0)
+               return rval;
+
+       return 0;
+}
+
+static int adp1653_get_fault(struct adp1653_flash *flash)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+       int fault;
+       int rval;
+
+       fault = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
+       if (IS_ERR_VALUE(fault))
+               return fault;
+
+       flash->fault |= fault;
+
+       if (!flash->fault)
+               return 0;
+
+       /* Clear faults. */
+       rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
+       if (IS_ERR_VALUE(rval))
+               return rval;
+
+       flash->led_mode->val = V4L2_FLASH_LED_MODE_NONE;
+
+       rval = adp1653_update_hw(flash);
+       if (IS_ERR_VALUE(rval))
+               return rval;
+
+       return flash->fault;
+}
+
+static int adp1653_strobe(struct adp1653_flash *flash, int enable)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+       u8 out_sel = ADP1653_INDICATOR_INTENSITY_uA_TO_REG(
+               flash->indicator_intensity->val)
+               << ADP1653_REG_OUT_SEL_ILED_SHIFT;
+       int rval;
+
+       if (flash->led_mode->val != V4L2_FLASH_LED_MODE_FLASH)
+               return -EBUSY;
+
+       if (!enable)
+               return i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL,
+                                                out_sel);
+
+       out_sel |= ADP1653_FLASH_INTENSITY_mA_TO_REG(
+               flash->flash_intensity->val)
+               << ADP1653_REG_OUT_SEL_HPLED_SHIFT;
+       rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
+       if (rval)
+               return rval;
+
+       /* Software strobe using i2c */
+       rval = i2c_smbus_write_byte_data(client, ADP1653_REG_SW_STROBE,
+               ADP1653_REG_SW_STROBE_SW_STROBE);
+       if (rval)
+               return rval;
+       return i2c_smbus_write_byte_data(client, ADP1653_REG_SW_STROBE, 0);
+}
+
+/* --------------------------------------------------------------------------
+ * V4L2 controls
+ */
+
+static int adp1653_get_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct adp1653_flash *flash =
+               container_of(ctrl->handler, struct adp1653_flash, ctrls);
+       int rval;
+
+       rval = adp1653_get_fault(flash);
+       if (IS_ERR_VALUE(rval))
+               return rval;
+
+       ctrl->cur.val = 0;
+
+       if (flash->fault & ADP1653_REG_FAULT_FLT_SCP)
+               ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
+       if (flash->fault & ADP1653_REG_FAULT_FLT_OT)
+               ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
+       if (flash->fault & ADP1653_REG_FAULT_FLT_TMR)
+               ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
+       if (flash->fault & ADP1653_REG_FAULT_FLT_OV)
+               ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
+
+       flash->fault = 0;
+
+       return 0;
+}
+
+static int adp1653_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct adp1653_flash *flash =
+               container_of(ctrl->handler, struct adp1653_flash, ctrls);
+       int rval;
+
+       rval = adp1653_get_fault(flash);
+       if (IS_ERR_VALUE(rval))
+               return rval;
+       if ((rval & (ADP1653_REG_FAULT_FLT_SCP |
+                    ADP1653_REG_FAULT_FLT_OT |
+                    ADP1653_REG_FAULT_FLT_OV)) &&
+           (ctrl->id == V4L2_CID_FLASH_STROBE ||
+            ctrl->id == V4L2_CID_FLASH_TORCH_INTENSITY ||
+            ctrl->id == V4L2_CID_FLASH_LED_MODE))
+               return -EBUSY;
+
+       switch (ctrl->id) {
+       case V4L2_CID_FLASH_STROBE:
+               return adp1653_strobe(flash, 1);
+       case V4L2_CID_FLASH_STROBE_STOP:
+               return adp1653_strobe(flash, 0);
+       }
+
+       return adp1653_update_hw(flash);
+}
+
+static const struct v4l2_ctrl_ops adp1653_ctrl_ops = {
+       .g_volatile_ctrl = adp1653_get_ctrl,
+       .s_ctrl = adp1653_set_ctrl,
+};
+
+static int adp1653_init_controls(struct adp1653_flash *flash)
+{
+       struct v4l2_ctrl *fault;
+
+       v4l2_ctrl_handler_init(&flash->ctrls, 9);
+
+       flash->led_mode =
+               v4l2_ctrl_new_std_menu(&flash->ctrls, &adp1653_ctrl_ops,
+                                      V4L2_CID_FLASH_LED_MODE,
+                                      V4L2_FLASH_LED_MODE_TORCH, ~0x7, 0);
+       v4l2_ctrl_new_std_menu(&flash->ctrls, &adp1653_ctrl_ops,
+                              V4L2_CID_FLASH_STROBE_SOURCE,
+                              V4L2_FLASH_STROBE_SOURCE_SOFTWARE, ~0x1, 0);
+       v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+                         V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
+       v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+                         V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
+       flash->flash_timeout =
+               v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+                                 V4L2_CID_FLASH_TIMEOUT, TIMEOUT_MIN,
+                                 flash->platform_data->max_flash_timeout,
+                                 TIMEOUT_STEP,
+                                 flash->platform_data->max_flash_timeout);
+       flash->flash_intensity =
+               v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+                                 V4L2_CID_FLASH_INTENSITY,
+                                 ADP1653_FLASH_INTENSITY_MIN,
+                                 flash->platform_data->max_flash_intensity,
+                                 1, flash->platform_data->max_flash_intensity);
+       flash->torch_intensity =
+               v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+                                 V4L2_CID_FLASH_TORCH_INTENSITY,
+                                 ADP1653_TORCH_INTENSITY_MIN,
+                                 flash->platform_data->max_torch_intensity,
+                                 ADP1653_FLASH_INTENSITY_STEP,
+                                 flash->platform_data->max_torch_intensity);
+       flash->indicator_intensity =
+               v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+                                 V4L2_CID_FLASH_INDICATOR_INTENSITY,
+                                 ADP1653_INDICATOR_INTENSITY_MIN,
+                                 flash->platform_data->max_indicator_intensity,
+                                 ADP1653_INDICATOR_INTENSITY_STEP,
+                                 ADP1653_INDICATOR_INTENSITY_MIN);
+       fault = v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+                                 V4L2_CID_FLASH_FAULT, 0,
+                                 V4L2_FLASH_FAULT_OVER_VOLTAGE
+                                 | V4L2_FLASH_FAULT_OVER_TEMPERATURE
+                                 | V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0);
+
+       if (flash->ctrls.error)
+               return flash->ctrls.error;
+
+       fault->is_volatile = 1;
+
+       flash->subdev.ctrl_handler = &flash->ctrls;
+       return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+static int
+adp1653_init_device(struct adp1653_flash *flash)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+       int rval;
+
+       /* Clear FAULT register by writing zero to OUT_SEL */
+       rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
+       if (rval < 0) {
+               dev_err(&client->dev, "failed writing fault register\n");
+               return -EIO;
+       }
+
+       mutex_lock(&flash->ctrls.lock);
+       /* Reset faults before reading new ones. */
+       flash->fault = 0;
+       rval = adp1653_get_fault(flash);
+       mutex_unlock(&flash->ctrls.lock);
+       if (rval > 0) {
+               dev_err(&client->dev, "faults detected: 0x%1.1x\n", rval);
+               return -EIO;
+       }
+
+       mutex_lock(&flash->ctrls.lock);
+       rval = adp1653_update_hw(flash);
+       mutex_unlock(&flash->ctrls.lock);
+       if (rval) {
+               dev_err(&client->dev,
+                       "adp1653_update_hw failed at %s\n", __func__);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int
+__adp1653_set_power(struct adp1653_flash *flash, int on)
+{
+       int ret;
+
+       ret = flash->platform_data->power(&flash->subdev, on);
+       if (ret < 0)
+               return ret;
+
+       if (!on)
+               return 0;
+
+       ret = adp1653_init_device(flash);
+       if (ret < 0)
+               flash->platform_data->power(&flash->subdev, 0);
+
+       return ret;
+}
+
+static int
+adp1653_set_power(struct v4l2_subdev *subdev, int on)
+{
+       struct adp1653_flash *flash = to_adp1653_flash(subdev);
+       int ret = 0;
+
+       mutex_lock(&flash->power_lock);
+
+       /* If the power count is modified from 0 to != 0 or from != 0 to 0,
+        * update the power state.
+        */
+       if (flash->power_count == !on) {
+               ret = __adp1653_set_power(flash, !!on);
+               if (ret < 0)
+                       goto done;
+       }
+
+       /* Update the power count. */
+       flash->power_count += on ? 1 : -1;
+       WARN_ON(flash->power_count < 0);
+
+done:
+       mutex_unlock(&flash->power_lock);
+       return ret;
+}
+
+static int adp1653_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       return adp1653_set_power(sd, 1);
+}
+
+static int adp1653_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       return adp1653_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_core_ops adp1653_core_ops = {
+       .s_power = adp1653_set_power,
+};
+
+static const struct v4l2_subdev_ops adp1653_ops = {
+       .core = &adp1653_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops adp1653_internal_ops = {
+       .open = adp1653_open,
+       .close = adp1653_close,
+};
+
+/* --------------------------------------------------------------------------
+ * I2C driver
+ */
+#ifdef CONFIG_PM
+
+static int adp1653_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+       struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+       if (!flash->power_count)
+               return 0;
+
+       return __adp1653_set_power(flash, 0);
+}
+
+static int adp1653_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+       struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+       if (!flash->power_count)
+               return 0;
+
+       return __adp1653_set_power(flash, 1);
+}
+
+#else
+
+#define adp1653_suspend        NULL
+#define adp1653_resume NULL
+
+#endif /* CONFIG_PM */
+
+static int adp1653_probe(struct i2c_client *client,
+                        const struct i2c_device_id *devid)
+{
+       struct adp1653_flash *flash;
+       int ret;
+
+       flash = kzalloc(sizeof(*flash), GFP_KERNEL);
+       if (flash == NULL)
+               return -ENOMEM;
+
+       flash->platform_data = client->dev.platform_data;
+
+       mutex_init(&flash->power_lock);
+
+       v4l2_i2c_subdev_init(&flash->subdev, client, &adp1653_ops);
+       flash->subdev.internal_ops = &adp1653_internal_ops;
+       flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       adp1653_init_controls(flash);
+
+       ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0);
+       if (ret < 0)
+               kfree(flash);
+
+       return ret;
+}
+
+static int __exit adp1653_remove(struct i2c_client *client)
+{
+       struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+       struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+       v4l2_device_unregister_subdev(&flash->subdev);
+       v4l2_ctrl_handler_free(&flash->ctrls);
+       media_entity_cleanup(&flash->subdev.entity);
+       kfree(flash);
+       return 0;
+}
+
+static const struct i2c_device_id adp1653_id_table[] = {
+       { ADP1653_NAME, 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, adp1653_id_table);
+
+static struct dev_pm_ops adp1653_pm_ops = {
+       .suspend        = adp1653_suspend,
+       .resume         = adp1653_resume,
+};
+
+static struct i2c_driver adp1653_i2c_driver = {
+       .driver         = {
+               .name   = ADP1653_NAME,
+               .pm     = &adp1653_pm_ops,
+       },
+       .probe          = adp1653_probe,
+       .remove         = __exit_p(adp1653_remove),
+       .id_table       = adp1653_id_table,
+};
+
+static int __init adp1653_init(void)
+{
+       int rval;
+
+       rval = i2c_add_driver(&adp1653_i2c_driver);
+       if (rval)
+               printk(KERN_ALERT "%s: failed at i2c_add_driver\n", __func__);
+
+       return rval;
+}
+
+static void __exit adp1653_exit(void)
+{
+       i2c_del_driver(&adp1653_i2c_driver);
+}
+
+module_init(adp1653_init);
+module_exit(adp1653_exit);
+
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
+MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver");
+MODULE_LICENSE("GPL");
index f989f28..b6ed44a 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
@@ -54,7 +53,7 @@
  */
 #define USE_INT                0       /* Don't modify */
 
-#define VERSION        "0.04"
+#define VERSION        "0.0.5"
 
 #define ar_inl(addr)           inl((unsigned long)(addr))
 #define ar_outl(val, addr)     outl((unsigned long)(val), (unsigned long)(addr))
@@ -404,7 +403,6 @@ static int ar_querycap(struct file *file, void  *priv,
        strlcpy(vcap->driver, ar->vdev.name, sizeof(vcap->driver));
        strlcpy(vcap->card, "Colour AR VGA", sizeof(vcap->card));
        strlcpy(vcap->bus_info, "Platform", sizeof(vcap->bus_info));
-       vcap->version = KERNEL_VERSION(0, 0, 4);
        vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
        return 0;
 }
@@ -879,3 +877,4 @@ module_exit(ar_cleanup_module);
 MODULE_AUTHOR("Takeo Takahashi <takahashi.takeo@renesas.com>");
 MODULE_DESCRIPTION("Colour AR M64278(VGA) for Video4Linux");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(VERSION);
diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c
new file mode 100644 (file)
index 0000000..7b89f00
--- /dev/null
@@ -0,0 +1,1048 @@
+/*
+ * Copyright (c) 2011 Atmel Corporation
+ * Josh Wu, <josh.wu@atmel.com>
+ *
+ * Based on previous work by Lars Haring, <lars.haring@atmel.com>
+ * and Sedji Gaouaou
+ * Based on the bttv driver for Bt848 with respective copyright holders
+ *
+ * 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/completion.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <media/atmel-isi.h>
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
+#include <media/videobuf2-dma-contig.h>
+
+#define MAX_BUFFER_NUM                 32
+#define MAX_SUPPORT_WIDTH              2048
+#define MAX_SUPPORT_HEIGHT             2048
+#define VID_LIMIT_BYTES                        (16 * 1024 * 1024)
+#define MIN_FRAME_RATE                 15
+#define FRAME_INTERVAL_MILLI_SEC       (1000 / MIN_FRAME_RATE)
+
+/* ISI states */
+enum {
+       ISI_STATE_IDLE = 0,
+       ISI_STATE_READY,
+       ISI_STATE_WAIT_SOF,
+};
+
+/* Frame buffer descriptor */
+struct fbd {
+       /* Physical address of the frame buffer */
+       u32 fb_address;
+       /* DMA Control Register(only in HISI2) */
+       u32 dma_ctrl;
+       /* Physical address of the next fbd */
+       u32 next_fbd_address;
+};
+
+static void set_dma_ctrl(struct fbd *fb_desc, u32 ctrl)
+{
+       fb_desc->dma_ctrl = ctrl;
+}
+
+struct isi_dma_desc {
+       struct list_head list;
+       struct fbd *p_fbd;
+       u32 fbd_phys;
+};
+
+/* Frame buffer data */
+struct frame_buffer {
+       struct vb2_buffer vb;
+       struct isi_dma_desc *p_dma_desc;
+       struct list_head list;
+};
+
+struct atmel_isi {
+       /* Protects the access of variables shared with the ISR */
+       spinlock_t                      lock;
+       void __iomem                    *regs;
+
+       int                             sequence;
+       /* State of the ISI module in capturing mode */
+       int                             state;
+
+       /* Wait queue for waiting for SOF */
+       wait_queue_head_t               vsync_wq;
+
+       struct vb2_alloc_ctx            *alloc_ctx;
+
+       /* Allocate descriptors for dma buffer use */
+       struct fbd                      *p_fb_descriptors;
+       u32                             fb_descriptors_phys;
+       struct                          list_head dma_desc_head;
+       struct isi_dma_desc             dma_desc[MAX_BUFFER_NUM];
+
+       struct completion               complete;
+       struct clk                      *pclk;
+       unsigned int                    irq;
+
+       struct isi_platform_data        *pdata;
+
+       struct list_head                video_buffer_list;
+       struct frame_buffer             *active;
+
+       struct soc_camera_device        *icd;
+       struct soc_camera_host          soc_host;
+};
+
+static void isi_writel(struct atmel_isi *isi, u32 reg, u32 val)
+{
+       writel(val, isi->regs + reg);
+}
+static u32 isi_readl(struct atmel_isi *isi, u32 reg)
+{
+       return readl(isi->regs + reg);
+}
+
+static int configure_geometry(struct atmel_isi *isi, u32 width,
+                       u32 height, enum v4l2_mbus_pixelcode code)
+{
+       u32 cfg2, cr;
+
+       switch (code) {
+       /* YUV, including grey */
+       case V4L2_MBUS_FMT_Y8_1X8:
+               cr = ISI_CFG2_GRAYSCALE;
+               break;
+       case V4L2_MBUS_FMT_UYVY8_2X8:
+               cr = ISI_CFG2_YCC_SWAP_MODE_3;
+               break;
+       case V4L2_MBUS_FMT_VYUY8_2X8:
+               cr = ISI_CFG2_YCC_SWAP_MODE_2;
+               break;
+       case V4L2_MBUS_FMT_YUYV8_2X8:
+               cr = ISI_CFG2_YCC_SWAP_MODE_1;
+               break;
+       case V4L2_MBUS_FMT_YVYU8_2X8:
+               cr = ISI_CFG2_YCC_SWAP_DEFAULT;
+               break;
+       /* RGB, TODO */
+       default:
+               return -EINVAL;
+       }
+
+       isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
+
+       cfg2 = isi_readl(isi, ISI_CFG2);
+       cfg2 |= cr;
+       /* Set width */
+       cfg2 &= ~(ISI_CFG2_IM_HSIZE_MASK);
+       cfg2 |= ((width - 1) << ISI_CFG2_IM_HSIZE_OFFSET) &
+                       ISI_CFG2_IM_HSIZE_MASK;
+       /* Set height */
+       cfg2 &= ~(ISI_CFG2_IM_VSIZE_MASK);
+       cfg2 |= ((height - 1) << ISI_CFG2_IM_VSIZE_OFFSET)
+                       & ISI_CFG2_IM_VSIZE_MASK;
+       isi_writel(isi, ISI_CFG2, cfg2);
+
+       return 0;
+}
+
+static irqreturn_t atmel_isi_handle_streaming(struct atmel_isi *isi)
+{
+       if (isi->active) {
+               struct vb2_buffer *vb = &isi->active->vb;
+               struct frame_buffer *buf = isi->active;
+
+               list_del_init(&buf->list);
+               do_gettimeofday(&vb->v4l2_buf.timestamp);
+               vb->v4l2_buf.sequence = isi->sequence++;
+               vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+       }
+
+       if (list_empty(&isi->video_buffer_list)) {
+               isi->active = NULL;
+       } else {
+               /* start next dma frame. */
+               isi->active = list_entry(isi->video_buffer_list.next,
+                                       struct frame_buffer, list);
+               isi_writel(isi, ISI_DMA_C_DSCR,
+                       isi->active->p_dma_desc->fbd_phys);
+               isi_writel(isi, ISI_DMA_C_CTRL,
+                       ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE);
+               isi_writel(isi, ISI_DMA_CHER, ISI_DMA_CHSR_C_CH);
+       }
+       return IRQ_HANDLED;
+}
+
+/* ISI interrupt service routine */
+static irqreturn_t isi_interrupt(int irq, void *dev_id)
+{
+       struct atmel_isi *isi = dev_id;
+       u32 status, mask, pending;
+       irqreturn_t ret = IRQ_NONE;
+
+       spin_lock(&isi->lock);
+
+       status = isi_readl(isi, ISI_STATUS);
+       mask = isi_readl(isi, ISI_INTMASK);
+       pending = status & mask;
+
+       if (pending & ISI_CTRL_SRST) {
+               complete(&isi->complete);
+               isi_writel(isi, ISI_INTDIS, ISI_CTRL_SRST);
+               ret = IRQ_HANDLED;
+       } else if (pending & ISI_CTRL_DIS) {
+               complete(&isi->complete);
+               isi_writel(isi, ISI_INTDIS, ISI_CTRL_DIS);
+               ret = IRQ_HANDLED;
+       } else {
+               if ((pending & ISI_SR_VSYNC) &&
+                               (isi->state == ISI_STATE_IDLE)) {
+                       isi->state = ISI_STATE_READY;
+                       wake_up_interruptible(&isi->vsync_wq);
+                       ret = IRQ_HANDLED;
+               }
+               if (likely(pending & ISI_SR_CXFR_DONE))
+                       ret = atmel_isi_handle_streaming(isi);
+       }
+
+       spin_unlock(&isi->lock);
+       return ret;
+}
+
+#define        WAIT_ISI_RESET          1
+#define        WAIT_ISI_DISABLE        0
+static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset)
+{
+       unsigned long timeout;
+       /*
+        * The reset or disable will only succeed if we have a
+        * pixel clock from the camera.
+        */
+       init_completion(&isi->complete);
+
+       if (wait_reset) {
+               isi_writel(isi, ISI_INTEN, ISI_CTRL_SRST);
+               isi_writel(isi, ISI_CTRL, ISI_CTRL_SRST);
+       } else {
+               isi_writel(isi, ISI_INTEN, ISI_CTRL_DIS);
+               isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
+       }
+
+       timeout = wait_for_completion_timeout(&isi->complete,
+                       msecs_to_jiffies(100));
+       if (timeout == 0)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------
+       Videobuf operations
+   ------------------------------------------------------------------*/
+static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+                               unsigned int *nplanes, unsigned long sizes[],
+                               void *alloc_ctxs[])
+{
+       struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct atmel_isi *isi = ici->priv;
+       unsigned long size;
+       int ret, bytes_per_line;
+
+       /* Reset ISI */
+       ret = atmel_isi_wait_status(isi, WAIT_ISI_RESET);
+       if (ret < 0) {
+               dev_err(icd->parent, "Reset ISI timed out\n");
+               return ret;
+       }
+       /* Disable all interrupts */
+       isi_writel(isi, ISI_INTDIS, ~0UL);
+
+       bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+                                               icd->current_fmt->host_fmt);
+
+       if (bytes_per_line < 0)
+               return bytes_per_line;
+
+       size = bytes_per_line * icd->user_height;
+
+       if (!*nbuffers || *nbuffers > MAX_BUFFER_NUM)
+               *nbuffers = MAX_BUFFER_NUM;
+
+       if (size * *nbuffers > VID_LIMIT_BYTES)
+               *nbuffers = VID_LIMIT_BYTES / size;
+
+       *nplanes = 1;
+       sizes[0] = size;
+       alloc_ctxs[0] = isi->alloc_ctx;
+
+       isi->sequence = 0;
+       isi->active = NULL;
+
+       dev_dbg(icd->parent, "%s, count=%d, size=%ld\n", __func__,
+               *nbuffers, size);
+
+       return 0;
+}
+
+static int buffer_init(struct vb2_buffer *vb)
+{
+       struct frame_buffer *buf = container_of(vb, struct frame_buffer, vb);
+
+       buf->p_dma_desc = NULL;
+       INIT_LIST_HEAD(&buf->list);
+
+       return 0;
+}
+
+static int buffer_prepare(struct vb2_buffer *vb)
+{
+       struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
+       struct frame_buffer *buf = container_of(vb, struct frame_buffer, vb);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct atmel_isi *isi = ici->priv;
+       unsigned long size;
+       struct isi_dma_desc *desc;
+       int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+                                               icd->current_fmt->host_fmt);
+
+       if (bytes_per_line < 0)
+               return bytes_per_line;
+
+       size = bytes_per_line * icd->user_height;
+
+       if (vb2_plane_size(vb, 0) < size) {
+               dev_err(icd->parent, "%s data will not fit into plane (%lu < %lu)\n",
+                               __func__, vb2_plane_size(vb, 0), size);
+               return -EINVAL;
+       }
+
+       vb2_set_plane_payload(&buf->vb, 0, size);
+
+       if (!buf->p_dma_desc) {
+               if (list_empty(&isi->dma_desc_head)) {
+                       dev_err(icd->parent, "Not enough dma descriptors.\n");
+                       return -EINVAL;
+               } else {
+                       /* Get an available descriptor */
+                       desc = list_entry(isi->dma_desc_head.next,
+                                               struct isi_dma_desc, list);
+                       /* Delete the descriptor since now it is used */
+                       list_del_init(&desc->list);
+
+                       /* Initialize the dma descriptor */
+                       desc->p_fbd->fb_address =
+                                       vb2_dma_contig_plane_paddr(vb, 0);
+                       desc->p_fbd->next_fbd_address = 0;
+                       set_dma_ctrl(desc->p_fbd, ISI_DMA_CTRL_WB);
+
+                       buf->p_dma_desc = desc;
+               }
+       }
+       return 0;
+}
+
+static void buffer_cleanup(struct vb2_buffer *vb)
+{
+       struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct atmel_isi *isi = ici->priv;
+       struct frame_buffer *buf = container_of(vb, struct frame_buffer, vb);
+
+       /* This descriptor is available now and we add to head list */
+       if (buf->p_dma_desc)
+               list_add(&buf->p_dma_desc->list, &isi->dma_desc_head);
+}
+
+static void start_dma(struct atmel_isi *isi, struct frame_buffer *buffer)
+{
+       u32 ctrl, cfg1;
+
+       cfg1 = isi_readl(isi, ISI_CFG1);
+       /* Enable irq: cxfr for the codec path, pxfr for the preview path */
+       isi_writel(isi, ISI_INTEN,
+                       ISI_SR_CXFR_DONE | ISI_SR_PXFR_DONE);
+
+       /* Check if already in a frame */
+       if (isi_readl(isi, ISI_STATUS) & ISI_CTRL_CDC) {
+               dev_err(isi->icd->parent, "Already in frame handling.\n");
+               return;
+       }
+
+       isi_writel(isi, ISI_DMA_C_DSCR, buffer->p_dma_desc->fbd_phys);
+       isi_writel(isi, ISI_DMA_C_CTRL, ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE);
+       isi_writel(isi, ISI_DMA_CHER, ISI_DMA_CHSR_C_CH);
+
+       /* Enable linked list */
+       cfg1 |= isi->pdata->frate | ISI_CFG1_DISCR;
+
+       /* Enable codec path and ISI */
+       ctrl = ISI_CTRL_CDC | ISI_CTRL_EN;
+       isi_writel(isi, ISI_CTRL, ctrl);
+       isi_writel(isi, ISI_CFG1, cfg1);
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
+{
+       struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct atmel_isi *isi = ici->priv;
+       struct frame_buffer *buf = container_of(vb, struct frame_buffer, vb);
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&isi->lock, flags);
+       list_add_tail(&buf->list, &isi->video_buffer_list);
+
+       if (isi->active == NULL) {
+               isi->active = buf;
+               start_dma(isi, buf);
+       }
+       spin_unlock_irqrestore(&isi->lock, flags);
+}
+
+static int start_streaming(struct vb2_queue *vq)
+{
+       struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct atmel_isi *isi = ici->priv;
+
+       u32 sr = 0;
+       int ret;
+
+       spin_lock_irq(&isi->lock);
+       isi->state = ISI_STATE_IDLE;
+       /* Clear any pending SOF interrupt */
+       sr = isi_readl(isi, ISI_STATUS);
+       /* Enable VSYNC interrupt for SOF */
+       isi_writel(isi, ISI_INTEN, ISI_SR_VSYNC);
+       isi_writel(isi, ISI_CTRL, ISI_CTRL_EN);
+       spin_unlock_irq(&isi->lock);
+
+       dev_dbg(icd->parent, "Waiting for SOF\n");
+       ret = wait_event_interruptible(isi->vsync_wq,
+                                      isi->state != ISI_STATE_IDLE);
+       if (ret)
+               return ret;
+
+       if (isi->state != ISI_STATE_READY)
+               return -EIO;
+
+       spin_lock_irq(&isi->lock);
+       isi->state = ISI_STATE_WAIT_SOF;
+       isi_writel(isi, ISI_INTDIS, ISI_SR_VSYNC);
+       spin_unlock_irq(&isi->lock);
+
+       return 0;
+}
+
+/* abort streaming and wait for last buffer */
+static int stop_streaming(struct vb2_queue *vq)
+{
+       struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct atmel_isi *isi = ici->priv;
+       struct frame_buffer *buf, *node;
+       int ret = 0;
+       unsigned long timeout;
+
+       spin_lock_irq(&isi->lock);
+       isi->active = NULL;
+       /* Release all active buffers */
+       list_for_each_entry_safe(buf, node, &isi->video_buffer_list, list) {
+               list_del_init(&buf->list);
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+       }
+       spin_unlock_irq(&isi->lock);
+
+       timeout = jiffies + FRAME_INTERVAL_MILLI_SEC * HZ;
+       /* Wait until the end of the current frame. */
+       while ((isi_readl(isi, ISI_STATUS) & ISI_CTRL_CDC) &&
+                       time_before(jiffies, timeout))
+               msleep(1);
+
+       if (time_after(jiffies, timeout)) {
+               dev_err(icd->parent,
+                       "Timeout waiting for finishing codec request\n");
+               return -ETIMEDOUT;
+       }
+
+       /* Disable interrupts */
+       isi_writel(isi, ISI_INTDIS,
+                       ISI_SR_CXFR_DONE | ISI_SR_PXFR_DONE);
+
+       /* Disable ISI and wait for it is done */
+       ret = atmel_isi_wait_status(isi, WAIT_ISI_DISABLE);
+       if (ret < 0)
+               dev_err(icd->parent, "Disable ISI timed out\n");
+
+       return ret;
+}
+
+static struct vb2_ops isi_video_qops = {
+       .queue_setup            = queue_setup,
+       .buf_init               = buffer_init,
+       .buf_prepare            = buffer_prepare,
+       .buf_cleanup            = buffer_cleanup,
+       .buf_queue              = buffer_queue,
+       .start_streaming        = start_streaming,
+       .stop_streaming         = stop_streaming,
+       .wait_prepare           = soc_camera_unlock,
+       .wait_finish            = soc_camera_lock,
+};
+
+/* ------------------------------------------------------------------
+       SOC camera operations for the device
+   ------------------------------------------------------------------*/
+static int isi_camera_init_videobuf(struct vb2_queue *q,
+                                    struct soc_camera_device *icd)
+{
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       q->io_modes = VB2_MMAP;
+       q->drv_priv = icd;
+       q->buf_struct_size = sizeof(struct frame_buffer);
+       q->ops = &isi_video_qops;
+       q->mem_ops = &vb2_dma_contig_memops;
+
+       return vb2_queue_init(q);
+}
+
+static int isi_camera_set_fmt(struct soc_camera_device *icd,
+                             struct v4l2_format *f)
+{
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct atmel_isi *isi = ici->priv;
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+       const struct soc_camera_format_xlate *xlate;
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       struct v4l2_mbus_framefmt mf;
+       int ret;
+
+       xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
+       if (!xlate) {
+               dev_warn(icd->parent, "Format %x not found\n",
+                        pix->pixelformat);
+               return -EINVAL;
+       }
+
+       dev_dbg(icd->parent, "Plan to set format %dx%d\n",
+                       pix->width, pix->height);
+
+       mf.width        = pix->width;
+       mf.height       = pix->height;
+       mf.field        = pix->field;
+       mf.colorspace   = pix->colorspace;
+       mf.code         = xlate->code;
+
+       ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+       if (ret < 0)
+               return ret;
+
+       if (mf.code != xlate->code)
+               return -EINVAL;
+
+       ret = configure_geometry(isi, pix->width, pix->height, xlate->code);
+       if (ret < 0)
+               return ret;
+
+       pix->width              = mf.width;
+       pix->height             = mf.height;
+       pix->field              = mf.field;
+       pix->colorspace         = mf.colorspace;
+       icd->current_fmt        = xlate;
+
+       dev_dbg(icd->parent, "Finally set format %dx%d\n",
+               pix->width, pix->height);
+
+       return ret;
+}
+
+static int isi_camera_try_fmt(struct soc_camera_device *icd,
+                             struct v4l2_format *f)
+{
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+       const struct soc_camera_format_xlate *xlate;
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       struct v4l2_mbus_framefmt mf;
+       u32 pixfmt = pix->pixelformat;
+       int ret;
+
+       xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+       if (pixfmt && !xlate) {
+               dev_warn(icd->parent, "Format %x not found\n", pixfmt);
+               return -EINVAL;
+       }
+
+       /* limit to Atmel ISI hardware capabilities */
+       if (pix->height > MAX_SUPPORT_HEIGHT)
+               pix->height = MAX_SUPPORT_HEIGHT;
+       if (pix->width > MAX_SUPPORT_WIDTH)
+               pix->width = MAX_SUPPORT_WIDTH;
+
+       /* limit to sensor capabilities */
+       mf.width        = pix->width;
+       mf.height       = pix->height;
+       mf.field        = pix->field;
+       mf.colorspace   = pix->colorspace;
+       mf.code         = xlate->code;
+
+       ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+       if (ret < 0)
+               return ret;
+
+       pix->width      = mf.width;
+       pix->height     = mf.height;
+       pix->colorspace = mf.colorspace;
+
+       switch (mf.field) {
+       case V4L2_FIELD_ANY:
+               pix->field = V4L2_FIELD_NONE;
+               break;
+       case V4L2_FIELD_NONE:
+               break;
+       default:
+               dev_err(icd->parent, "Field type %d unsupported.\n",
+                       mf.field);
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static const struct soc_mbus_pixelfmt isi_camera_formats[] = {
+       {
+               .fourcc                 = V4L2_PIX_FMT_YUYV,
+               .name                   = "Packed YUV422 16 bit",
+               .bits_per_sample        = 8,
+               .packing                = SOC_MBUS_PACKING_2X8_PADHI,
+               .order                  = SOC_MBUS_ORDER_LE,
+       },
+};
+
+/* This will be corrected as we get more formats */
+static bool isi_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt)
+{
+       return  fmt->packing == SOC_MBUS_PACKING_NONE ||
+               (fmt->bits_per_sample == 8 &&
+                fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) ||
+               (fmt->bits_per_sample > 8 &&
+                fmt->packing == SOC_MBUS_PACKING_EXTEND16);
+}
+
+static unsigned long make_bus_param(struct atmel_isi *isi)
+{
+       unsigned long flags;
+       /*
+        * Platform specified synchronization and pixel clock polarities are
+        * only a recommendation and are only used during probing. Atmel ISI
+        * camera interface only works in master mode, i.e., uses HSYNC and
+        * VSYNC signals from the sensor
+        */
+       flags = SOCAM_MASTER |
+               SOCAM_HSYNC_ACTIVE_HIGH |
+               SOCAM_HSYNC_ACTIVE_LOW |
+               SOCAM_VSYNC_ACTIVE_HIGH |
+               SOCAM_VSYNC_ACTIVE_LOW |
+               SOCAM_PCLK_SAMPLE_RISING |
+               SOCAM_PCLK_SAMPLE_FALLING |
+               SOCAM_DATA_ACTIVE_HIGH;
+
+       if (isi->pdata->data_width_flags & ISI_DATAWIDTH_10)
+               flags |= SOCAM_DATAWIDTH_10;
+
+       if (isi->pdata->data_width_flags & ISI_DATAWIDTH_8)
+               flags |= SOCAM_DATAWIDTH_8;
+
+       if (flags & SOCAM_DATAWIDTH_MASK)
+               return flags;
+
+       return 0;
+}
+
+static int isi_camera_try_bus_param(struct soc_camera_device *icd,
+                                   unsigned char buswidth)
+{
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct atmel_isi *isi = ici->priv;
+       unsigned long camera_flags;
+       int ret;
+
+       camera_flags = icd->ops->query_bus_param(icd);
+       ret = soc_camera_bus_param_compatible(camera_flags,
+                                       make_bus_param(isi));
+       if (!ret)
+               return -EINVAL;
+       return 0;
+}
+
+
+static int isi_camera_get_formats(struct soc_camera_device *icd,
+                                 unsigned int idx,
+                                 struct soc_camera_format_xlate *xlate)
+{
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+       int formats = 0, ret;
+       /* sensor format */
+       enum v4l2_mbus_pixelcode code;
+       /* soc camera host format */
+       const struct soc_mbus_pixelfmt *fmt;
+
+       ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+       if (ret < 0)
+               /* No more formats */
+               return 0;
+
+       fmt = soc_mbus_get_fmtdesc(code);
+       if (!fmt) {
+               dev_err(icd->parent,
+                       "Invalid format code #%u: %d\n", idx, code);
+               return 0;
+       }
+
+       /* This also checks support for the requested bits-per-sample */
+       ret = isi_camera_try_bus_param(icd, fmt->bits_per_sample);
+       if (ret < 0) {
+               dev_err(icd->parent,
+                       "Fail to try the bus parameters.\n");
+               return 0;
+       }
+
+       switch (code) {
+       case V4L2_MBUS_FMT_UYVY8_2X8:
+       case V4L2_MBUS_FMT_VYUY8_2X8:
+       case V4L2_MBUS_FMT_YUYV8_2X8:
+       case V4L2_MBUS_FMT_YVYU8_2X8:
+               formats++;
+               if (xlate) {
+                       xlate->host_fmt = &isi_camera_formats[0];
+                       xlate->code     = code;
+                       xlate++;
+                       dev_dbg(icd->parent, "Providing format %s using code %d\n",
+                               isi_camera_formats[0].name, code);
+               }
+               break;
+       default:
+               if (!isi_camera_packing_supported(fmt))
+                       return 0;
+               if (xlate)
+                       dev_dbg(icd->parent,
+                               "Providing format %s in pass-through mode\n",
+                               fmt->name);
+       }
+
+       /* Generic pass-through */
+       formats++;
+       if (xlate) {
+               xlate->host_fmt = fmt;
+               xlate->code     = code;
+               xlate++;
+       }
+
+       return formats;
+}
+
+/* Called with .video_lock held */
+static int isi_camera_add_device(struct soc_camera_device *icd)
+{
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct atmel_isi *isi = ici->priv;
+       int ret;
+
+       if (isi->icd)
+               return -EBUSY;
+
+       ret = clk_enable(isi->pclk);
+       if (ret)
+               return ret;
+
+       isi->icd = icd;
+       dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n",
+                icd->devnum);
+       return 0;
+}
+/* Called with .video_lock held */
+static void isi_camera_remove_device(struct soc_camera_device *icd)
+{
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct atmel_isi *isi = ici->priv;
+
+       BUG_ON(icd != isi->icd);
+
+       clk_disable(isi->pclk);
+       isi->icd = NULL;
+
+       dev_dbg(icd->parent, "Atmel ISI Camera driver detached from camera %d\n",
+                icd->devnum);
+}
+
+static unsigned int isi_camera_poll(struct file *file, poll_table *pt)
+{
+       struct soc_camera_device *icd = file->private_data;
+
+       return vb2_poll(&icd->vb2_vidq, file, pt);
+}
+
+static int isi_camera_querycap(struct soc_camera_host *ici,
+                              struct v4l2_capability *cap)
+{
+       strcpy(cap->driver, "atmel-isi");
+       strcpy(cap->card, "Atmel Image Sensor Interface");
+       cap->capabilities = (V4L2_CAP_VIDEO_CAPTURE |
+                               V4L2_CAP_STREAMING);
+       return 0;
+}
+
+static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt)
+{
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct atmel_isi *isi = ici->priv;
+       unsigned long bus_flags, camera_flags, common_flags;
+       int ret;
+       u32 cfg1 = 0;
+
+       camera_flags = icd->ops->query_bus_param(icd);
+
+       bus_flags = make_bus_param(isi);
+       common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
+       dev_dbg(icd->parent, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
+               camera_flags, bus_flags, common_flags);
+       if (!common_flags)
+               return -EINVAL;
+
+       /* Make choises, based on platform preferences */
+       if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
+           (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+               if (isi->pdata->hsync_act_low)
+                       common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+               else
+                       common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+       }
+
+       if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
+           (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+               if (isi->pdata->vsync_act_low)
+                       common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+               else
+                       common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+       }
+
+       if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
+           (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+               if (isi->pdata->pclk_act_falling)
+                       common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+               else
+                       common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+       }
+
+       ret = icd->ops->set_bus_param(icd, common_flags);
+       if (ret < 0) {
+               dev_dbg(icd->parent, "Camera set_bus_param(%lx) returned %d\n",
+                       common_flags, ret);
+               return ret;
+       }
+
+       /* set bus param for ISI */
+       if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
+               cfg1 |= ISI_CFG1_HSYNC_POL_ACTIVE_LOW;
+       if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
+               cfg1 |= ISI_CFG1_VSYNC_POL_ACTIVE_LOW;
+       if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
+               cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING;
+
+       if (isi->pdata->has_emb_sync)
+               cfg1 |= ISI_CFG1_EMB_SYNC;
+       if (isi->pdata->isi_full_mode)
+               cfg1 |= ISI_CFG1_FULL_MODE;
+
+       isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
+       isi_writel(isi, ISI_CFG1, cfg1);
+
+       return 0;
+}
+
+static struct soc_camera_host_ops isi_soc_camera_host_ops = {
+       .owner          = THIS_MODULE,
+       .add            = isi_camera_add_device,
+       .remove         = isi_camera_remove_device,
+       .set_fmt        = isi_camera_set_fmt,
+       .try_fmt        = isi_camera_try_fmt,
+       .get_formats    = isi_camera_get_formats,
+       .init_videobuf2 = isi_camera_init_videobuf,
+       .poll           = isi_camera_poll,
+       .querycap       = isi_camera_querycap,
+       .set_bus_param  = isi_camera_set_bus_param,
+};
+
+/* -----------------------------------------------------------------------*/
+static int __devexit atmel_isi_remove(struct platform_device *pdev)
+{
+       struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+       struct atmel_isi *isi = container_of(soc_host,
+                                       struct atmel_isi, soc_host);
+
+       free_irq(isi->irq, isi);
+       soc_camera_host_unregister(soc_host);
+       vb2_dma_contig_cleanup_ctx(isi->alloc_ctx);
+       dma_free_coherent(&pdev->dev,
+                       sizeof(struct fbd) * MAX_BUFFER_NUM,
+                       isi->p_fb_descriptors,
+                       isi->fb_descriptors_phys);
+
+       iounmap(isi->regs);
+       clk_put(isi->pclk);
+       kfree(isi);
+
+       return 0;
+}
+
+static int __devinit atmel_isi_probe(struct platform_device *pdev)
+{
+       unsigned int irq;
+       struct atmel_isi *isi;
+       struct clk *pclk;
+       struct resource *regs;
+       int ret, i;
+       struct device *dev = &pdev->dev;
+       struct soc_camera_host *soc_host;
+       struct isi_platform_data *pdata;
+
+       pdata = dev->platform_data;
+       if (!pdata || !pdata->data_width_flags) {
+               dev_err(&pdev->dev,
+                       "No config available for Atmel ISI\n");
+               return -EINVAL;
+       }
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!regs)
+               return -ENXIO;
+
+       pclk = clk_get(&pdev->dev, "isi_clk");
+       if (IS_ERR(pclk))
+               return PTR_ERR(pclk);
+
+       isi = kzalloc(sizeof(struct atmel_isi), GFP_KERNEL);
+       if (!isi) {
+               ret = -ENOMEM;
+               dev_err(&pdev->dev, "Can't allocate interface!\n");
+               goto err_alloc_isi;
+       }
+
+       isi->pclk = pclk;
+       isi->pdata = pdata;
+       isi->active = NULL;
+       spin_lock_init(&isi->lock);
+       init_waitqueue_head(&isi->vsync_wq);
+       INIT_LIST_HEAD(&isi->video_buffer_list);
+       INIT_LIST_HEAD(&isi->dma_desc_head);
+
+       isi->p_fb_descriptors = dma_alloc_coherent(&pdev->dev,
+                               sizeof(struct fbd) * MAX_BUFFER_NUM,
+                               &isi->fb_descriptors_phys,
+                               GFP_KERNEL);
+       if (!isi->p_fb_descriptors) {
+               ret = -ENOMEM;
+               dev_err(&pdev->dev, "Can't allocate descriptors!\n");
+               goto err_alloc_descriptors;
+       }
+
+       for (i = 0; i < MAX_BUFFER_NUM; i++) {
+               isi->dma_desc[i].p_fbd = isi->p_fb_descriptors + i;
+               isi->dma_desc[i].fbd_phys = isi->fb_descriptors_phys +
+                                       i * sizeof(struct fbd);
+               list_add(&isi->dma_desc[i].list, &isi->dma_desc_head);
+       }
+
+       isi->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+       if (IS_ERR(isi->alloc_ctx)) {
+               ret = PTR_ERR(isi->alloc_ctx);
+               goto err_alloc_ctx;
+       }
+
+       isi->regs = ioremap(regs->start, resource_size(regs));
+       if (!isi->regs) {
+               ret = -ENOMEM;
+               goto err_ioremap;
+       }
+
+       isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               ret = irq;
+               goto err_req_irq;
+       }
+
+       ret = request_irq(irq, isi_interrupt, 0, "isi", isi);
+       if (ret) {
+               dev_err(&pdev->dev, "Unable to request irq %d\n", irq);
+               goto err_req_irq;
+       }
+       isi->irq = irq;
+
+       soc_host                = &isi->soc_host;
+       soc_host->drv_name      = "isi-camera";
+       soc_host->ops           = &isi_soc_camera_host_ops;
+       soc_host->priv          = isi;
+       soc_host->v4l2_dev.dev  = &pdev->dev;
+       soc_host->nr            = pdev->id;
+
+       ret = soc_camera_host_register(soc_host);
+       if (ret) {
+               dev_err(&pdev->dev, "Unable to register soc camera host\n");
+               goto err_register_soc_camera_host;
+       }
+       return 0;
+
+err_register_soc_camera_host:
+       free_irq(isi->irq, isi);
+err_req_irq:
+       iounmap(isi->regs);
+err_ioremap:
+       vb2_dma_contig_cleanup_ctx(isi->alloc_ctx);
+err_alloc_ctx:
+       dma_free_coherent(&pdev->dev,
+                       sizeof(struct fbd) * MAX_BUFFER_NUM,
+                       isi->p_fb_descriptors,
+                       isi->fb_descriptors_phys);
+err_alloc_descriptors:
+       kfree(isi);
+err_alloc_isi:
+       clk_put(isi->pclk);
+
+       return ret;
+}
+
+static struct platform_driver atmel_isi_driver = {
+       .probe          = atmel_isi_probe,
+       .remove         = __devexit_p(atmel_isi_remove),
+       .driver         = {
+               .name = "atmel_isi",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init atmel_isi_init_module(void)
+{
+       return  platform_driver_probe(&atmel_isi_driver, &atmel_isi_probe);
+}
+
+static void __exit atmel_isi_exit(void)
+{
+       platform_driver_unregister(&atmel_isi_driver);
+}
+module_init(atmel_isi_init_module);
+module_exit(atmel_isi_exit);
+
+MODULE_AUTHOR("Josh Wu <josh.wu@atmel.com>");
+MODULE_DESCRIPTION("The V4L2 driver for Atmel Linux");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("video");
index ca342e4..1e4ce50 100644 (file)
@@ -292,3 +292,4 @@ module_exit(au0828_exit);
 MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
 MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.2");
index c03eb29..0b3e481 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/suspend.h>
-#include <linux/version.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-chip-ident.h>
@@ -43,8 +42,6 @@
 
 static DEFINE_MUTEX(au0828_sysfs_lock);
 
-#define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1)
-
 /* ------------------------------------------------------------------
        Videobuf operations
    ------------------------------------------------------------------*/
@@ -1254,8 +1251,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strlcpy(cap->card, dev->board.name, sizeof(cap->card));
        strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
 
-       cap->version = AU0828_VERSION_CODE;
-
        /*set the device capabilities */
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_VBI_CAPTURE |
index 3c9e6c7..5b15f63 100644 (file)
@@ -2892,13 +2892,10 @@ void __devinit bttv_idcard(struct bttv *btv)
 {
        unsigned int gpiobits;
        int i,type;
-       unsigned short tmp;
 
        /* read PCI subsystem ID */
-       pci_read_config_word(btv->c.pci, PCI_SUBSYSTEM_ID, &tmp);
-       btv->cardid = tmp << 16;
-       pci_read_config_word(btv->c.pci, PCI_SUBSYSTEM_VENDOR_ID, &tmp);
-       btv->cardid |= tmp;
+       btv->cardid  = btv->c.pci->subsystem_device << 16;
+       btv->cardid |= btv->c.pci->subsystem_vendor;
 
        if (0 != btv->cardid && 0xffffffff != btv->cardid) {
                /* look for the card */
index 834a483..14444de 100644 (file)
@@ -57,6 +57,7 @@
 
 #include <media/saa6588.h>
 
+#define BTTV_VERSION "0.9.19"
 
 unsigned int bttv_num;                 /* number of Bt848s in use */
 struct bttv *bttvs[BTTV_MAX];
@@ -163,6 +164,7 @@ MODULE_PARM_DESC(radio_nr, "radio device numbers");
 MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
 MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(BTTV_VERSION);
 
 /* ----------------------------------------------------------------------- */
 /* sysfs                                                                   */
@@ -2616,7 +2618,6 @@ static int bttv_querycap(struct file *file, void  *priv,
        strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
        snprintf(cap->bus_info, sizeof(cap->bus_info),
                 "PCI:%s", pci_name(btv->c.pci));
-       cap->version = BTTV_VERSION_CODE;
        cap->capabilities =
                V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_VBI_CAPTURE |
@@ -3416,7 +3417,6 @@ static int radio_querycap(struct file *file, void *priv,
        strcpy(cap->driver, "bttv");
        strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
        sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
-       cap->version = BTTV_VERSION_CODE;
        cap->capabilities = V4L2_CAP_TUNER;
 
        return 0;
@@ -4585,14 +4585,8 @@ static int __init bttv_init_module(void)
 
        bttv_num = 0;
 
-       printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
-              (BTTV_VERSION_CODE >> 16) & 0xff,
-              (BTTV_VERSION_CODE >> 8) & 0xff,
-              BTTV_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
-       printk(KERN_INFO "bttv: snapshot date %04d-%02d-%02d\n",
-              SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+       printk(KERN_INFO "bttv: driver version %s loaded\n",
+              BTTV_VERSION);
        if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
                gbuffers = 2;
        if (gbufsize > BTTV_MAX_FBUF)
index 9b776fa..318edf2 100644 (file)
@@ -25,9 +25,6 @@
 #ifndef _BTTVP_H_
 #define _BTTVP_H_
 
-#include <linux/version.h>
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,18)
-
 #include <linux/types.h>
 #include <linux/wait.h>
 #include <linux/i2c.h>
index c119350..f09df9d 100644 (file)
@@ -71,7 +71,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <linux/mm.h>
 #include <linux/parport.h>
 #include <linux/sched.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
@@ -647,7 +646,6 @@ static int qcam_querycap(struct file *file, void  *priv,
        strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
        strlcpy(vcap->card, "B&W Quickcam", sizeof(vcap->card));
        strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
-       vcap->version = KERNEL_VERSION(0, 0, 2);
        vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
        return 0;
 }
@@ -895,6 +893,7 @@ static struct qcam *qcam_init(struct parport *port)
 
        if (v4l2_device_register(NULL, v4l2_dev) < 0) {
                v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+               kfree(qcam);
                return NULL;
        }
 
@@ -1092,3 +1091,4 @@ module_init(init_bw_qcams);
 module_exit(exit_bw_qcams);
 
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.3");
index 24fc009..cd8ff04 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/sched.h>
 #include <linux/mutex.h>
 #include <linux/jiffies.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 #include <asm/uaccess.h>
 #include <media/v4l2-device.h>
@@ -517,7 +516,6 @@ static int qcam_querycap(struct file *file, void  *priv,
        strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
        strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card));
        strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
-       vcap->version = KERNEL_VERSION(0, 0, 3);
        vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
        return 0;
 }
@@ -752,6 +750,7 @@ static struct qcam *qcam_init(struct parport *port)
 
        if (v4l2_device_register(NULL, v4l2_dev) < 0) {
                v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+               kfree(qcam);
                return NULL;
        }
 
@@ -886,6 +885,7 @@ static void __exit cqcam_cleanup(void)
 MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
 MODULE_DESCRIPTION(BANNER);
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.4");
 
 module_init(cqcam_init);
 module_exit(cqcam_cleanup);
diff --git a/drivers/media/video/cafe_ccic-regs.h b/drivers/media/video/cafe_ccic-regs.h
deleted file mode 100644 (file)
index 8e2a87c..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Register definitions for the m88alp01 camera interface.  Offsets in bytes
- * as given in the spec.
- *
- * Copyright 2006 One Laptop Per Child Association, Inc.
- *
- * Written by Jonathan Corbet, corbet@lwn.net.
- *
- * This file may be distributed under the terms of the GNU General
- * Public License, version 2.
- */
-#define REG_Y0BAR      0x00
-#define REG_Y1BAR      0x04
-#define REG_Y2BAR      0x08
-/* ... */
-
-#define REG_IMGPITCH   0x24    /* Image pitch register */
-#define   IMGP_YP_SHFT   2             /* Y pitch params */
-#define   IMGP_YP_MASK   0x00003ffc    /* Y pitch field */
-#define          IMGP_UVP_SHFT   18            /* UV pitch (planar) */
-#define   IMGP_UVP_MASK   0x3ffc0000
-#define REG_IRQSTATRAW 0x28    /* RAW IRQ Status */
-#define   IRQ_EOF0       0x00000001    /* End of frame 0 */
-#define   IRQ_EOF1       0x00000002    /* End of frame 1 */
-#define   IRQ_EOF2       0x00000004    /* End of frame 2 */
-#define   IRQ_SOF0       0x00000008    /* Start of frame 0 */
-#define   IRQ_SOF1       0x00000010    /* Start of frame 1 */
-#define   IRQ_SOF2       0x00000020    /* Start of frame 2 */
-#define   IRQ_OVERFLOW   0x00000040    /* FIFO overflow */
-#define   IRQ_TWSIW      0x00010000    /* TWSI (smbus) write */
-#define   IRQ_TWSIR      0x00020000    /* TWSI read */
-#define   IRQ_TWSIE      0x00040000    /* TWSI error */
-#define   TWSIIRQS (IRQ_TWSIW|IRQ_TWSIR|IRQ_TWSIE)
-#define   FRAMEIRQS (IRQ_EOF0|IRQ_EOF1|IRQ_EOF2|IRQ_SOF0|IRQ_SOF1|IRQ_SOF2)
-#define   ALLIRQS (TWSIIRQS|FRAMEIRQS|IRQ_OVERFLOW)
-#define REG_IRQMASK    0x2c    /* IRQ mask - same bits as IRQSTAT */
-#define REG_IRQSTAT    0x30    /* IRQ status / clear */
-
-#define REG_IMGSIZE    0x34    /* Image size */
-#define  IMGSZ_V_MASK    0x1fff0000
-#define  IMGSZ_V_SHIFT   16
-#define         IMGSZ_H_MASK     0x00003fff
-#define REG_IMGOFFSET  0x38    /* IMage offset */
-
-#define REG_CTRL0      0x3c    /* Control 0 */
-#define   C0_ENABLE      0x00000001    /* Makes the whole thing go */
-
-/* Mask for all the format bits */
-#define   C0_DF_MASK     0x00fffffc    /* Bits 2-23 */
-
-/* RGB ordering */
-#define   C0_RGB4_RGBX   0x00000000
-#define          C0_RGB4_XRGB    0x00000004
-#define          C0_RGB4_BGRX    0x00000008
-#define   C0_RGB4_XBGR   0x0000000c
-#define   C0_RGB5_RGGB   0x00000000
-#define          C0_RGB5_GRBG    0x00000004
-#define          C0_RGB5_GBRG    0x00000008
-#define   C0_RGB5_BGGR   0x0000000c
-
-/* Spec has two fields for DIN and DOUT, but they must match, so
-   combine them here. */
-#define   C0_DF_YUV      0x00000000    /* Data is YUV      */
-#define   C0_DF_RGB      0x000000a0    /* ... RGB                  */
-#define   C0_DF_BAYER     0x00000140   /* ... Bayer                */
-/* 8-8-8 must be missing from the below - ask */
-#define   C0_RGBF_565    0x00000000
-#define   C0_RGBF_444    0x00000800
-#define   C0_RGB_BGR     0x00001000    /* Blue comes first */
-#define   C0_YUV_PLANAR          0x00000000    /* YUV 422 planar format */
-#define   C0_YUV_PACKED          0x00008000    /* YUV 422 packed       */
-#define   C0_YUV_420PL   0x0000a000    /* YUV 420 planar       */
-/* Think that 420 packed must be 111 - ask */
-#define          C0_YUVE_YUYV    0x00000000    /* Y1CbY0Cr             */
-#define          C0_YUVE_YVYU    0x00010000    /* Y1CrY0Cb             */
-#define          C0_YUVE_VYUY    0x00020000    /* CrY1CbY0             */
-#define          C0_YUVE_UYVY    0x00030000    /* CbY1CrY0             */
-#define   C0_YUVE_XYUV   0x00000000    /* 420: .YUV            */
-#define          C0_YUVE_XYVU    0x00010000    /* 420: .YVU            */
-#define          C0_YUVE_XUVY    0x00020000    /* 420: .UVY            */
-#define          C0_YUVE_XVUY    0x00030000    /* 420: .VUY            */
-/* Bayer bits 18,19 if needed */
-#define   C0_HPOL_LOW    0x01000000    /* HSYNC polarity active low */
-#define   C0_VPOL_LOW    0x02000000    /* VSYNC polarity active low */
-#define   C0_VCLK_LOW    0x04000000    /* VCLK on falling edge */
-#define   C0_DOWNSCALE   0x08000000    /* Enable downscaler */
-#define          C0_SIFM_MASK    0xc0000000    /* SIF mode bits */
-#define   C0_SIF_HVSYNC          0x00000000    /* Use H/VSYNC */
-#define   CO_SOF_NOSYNC          0x40000000    /* Use inband active signaling */
-
-
-#define REG_CTRL1      0x40    /* Control 1 */
-#define   C1_444ALPHA    0x00f00000    /* Alpha field in RGB444 */
-#define   C1_ALPHA_SHFT          20
-#define   C1_DMAB32      0x00000000    /* 32-byte DMA burst */
-#define   C1_DMAB16      0x02000000    /* 16-byte DMA burst */
-#define          C1_DMAB64       0x04000000    /* 64-byte DMA burst */
-#define          C1_DMAB_MASK    0x06000000
-#define   C1_TWOBUFS     0x08000000    /* Use only two DMA buffers */
-#define   C1_PWRDWN      0x10000000    /* Power down */
-
-#define REG_CLKCTRL    0x88    /* Clock control */
-#define   CLK_DIV_MASK   0x0000ffff    /* Upper bits RW "reserved" */
-
-#define REG_GPR                0xb4    /* General purpose register.  This
-                                  controls inputs to the power and reset
-                                  pins on the OV7670 used with OLPC;
-                                  other deployments could differ.  */
-#define   GPR_C1EN       0x00000020    /* Pad 1 (power down) enable */
-#define   GPR_C0EN       0x00000010    /* Pad 0 (reset) enable */
-#define          GPR_C1          0x00000002    /* Control 1 value */
-/*
- * Control 0 is wired to reset on OLPC machines.  For ov7x sensors,
- * it is active low, for 0v6x, instead, it's active high.  What
- * fun.
- */
-#define   GPR_C0         0x00000001    /* Control 0 value */
-
-#define REG_TWSIC0     0xb8    /* TWSI (smbus) control 0 */
-#define   TWSIC0_EN       0x00000001   /* TWSI enable */
-#define   TWSIC0_MODE    0x00000002    /* 1 = 16-bit, 0 = 8-bit */
-#define   TWSIC0_SID     0x000003fc    /* Slave ID */
-#define   TWSIC0_SID_SHIFT 2
-#define   TWSIC0_CLKDIV   0x0007fc00   /* Clock divider */
-#define   TWSIC0_MASKACK  0x00400000   /* Mask ack from sensor */
-#define   TWSIC0_OVMAGIC  0x00800000   /* Make it work on OV sensors */
-
-#define REG_TWSIC1     0xbc    /* TWSI control 1 */
-#define   TWSIC1_DATA    0x0000ffff    /* Data to/from camchip */
-#define   TWSIC1_ADDR    0x00ff0000    /* Address (register) */
-#define   TWSIC1_ADDR_SHIFT 16
-#define   TWSIC1_READ    0x01000000    /* Set for read op */
-#define   TWSIC1_WSTAT   0x02000000    /* Write status */
-#define   TWSIC1_RVALID          0x04000000    /* Read data valid */
-#define   TWSIC1_ERROR   0x08000000    /* Something screwed up */
-
-
-#define REG_UBAR       0xc4    /* Upper base address register */
-
-/*
- * Here's the weird global control registers which are said to live
- * way up here.
- */
-#define REG_GL_CSR     0x3004  /* Control/status register */
-#define   GCSR_SRS      0x00000001     /* SW Reset set */
-#define   GCSR_SRC      0x00000002     /* SW Reset clear */
-#define          GCSR_MRS       0x00000004     /* Master reset set */
-#define          GCSR_MRC       0x00000008     /* HW Reset clear */
-#define   GCSR_CCIC_EN   0x00004000    /* CCIC Clock enable */
-#define REG_GL_IMASK   0x300c  /* Interrupt mask register */
-#define   GIMSK_CCIC_EN          0x00000004    /* CCIC Interrupt enable */
-
-#define REG_GL_FCR     0x3038  /* GPIO functional control register */
-#define          GFCR_GPIO_ON    0x08          /* Camera GPIO enabled */
-#define REG_GL_GPIOR   0x315c  /* GPIO register */
-#define   GGPIO_OUT            0x80000 /* GPIO output */
-#define   GGPIO_VAL            0x00008 /* Output pin value */
-
-#define REG_LEN                REG_GL_IMASK + 4
-
-
-/*
- * Useful stuff that probably belongs somewhere global.
- */
-#define VGA_WIDTH      640
-#define VGA_HEIGHT     480
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
deleted file mode 100644 (file)
index 6647033..0000000
+++ /dev/null
@@ -1,2267 +0,0 @@
-/*
- * A driver for the CMOS camera controller in the Marvell 88ALP01 "cafe"
- * multifunction chip.  Currently works with the Omnivision OV7670
- * sensor.
- *
- * The data sheet for this device can be found at:
- *    http://www.marvell.com/products/pc_connectivity/88alp01/ 
- *
- * Copyright 2006 One Laptop Per Child Association, Inc.
- * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
- *
- * Written by Jonathan Corbet, corbet@lwn.net.
- *
- * v4l2_device/v4l2_subdev conversion by:
- * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl>
- *
- * Note: this conversion is untested! Please contact the linux-media
- * mailinglist if you can test this, together with the test results.
- *
- * This file may be distributed under the terms of the GNU General
- * Public License, version 2.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/dmi.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/videodev2.h>
-#include <linux/slab.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-chip-ident.h>
-#include <linux/device.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/jiffies.h>
-#include <linux/vmalloc.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#include "ov7670.h"
-#include "cafe_ccic-regs.h"
-
-#define CAFE_VERSION 0x000002
-
-
-/*
- * Parameters.
- */
-MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
-MODULE_DESCRIPTION("Marvell 88ALP01 CMOS Camera Controller driver");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("Video");
-
-/*
- * Internal DMA buffer management.  Since the controller cannot do S/G I/O,
- * we must have physically contiguous buffers to bring frames into.
- * These parameters control how many buffers we use, whether we
- * allocate them at load time (better chance of success, but nails down
- * memory) or when somebody tries to use the camera (riskier), and,
- * for load-time allocation, how big they should be.
- *
- * The controller can cycle through three buffers.  We could use
- * more by flipping pointers around, but it probably makes little
- * sense.
- */
-
-#define MAX_DMA_BUFS 3
-static int alloc_bufs_at_read;
-module_param(alloc_bufs_at_read, bool, 0444);
-MODULE_PARM_DESC(alloc_bufs_at_read,
-               "Non-zero value causes DMA buffers to be allocated when the "
-               "video capture device is read, rather than at module load "
-               "time.  This saves memory, but decreases the chances of "
-               "successfully getting those buffers.");
-
-static int n_dma_bufs = 3;
-module_param(n_dma_bufs, uint, 0644);
-MODULE_PARM_DESC(n_dma_bufs,
-               "The number of DMA buffers to allocate.  Can be either two "
-               "(saves memory, makes timing tighter) or three.");
-
-static int dma_buf_size = VGA_WIDTH * VGA_HEIGHT * 2;  /* Worst case */
-module_param(dma_buf_size, uint, 0444);
-MODULE_PARM_DESC(dma_buf_size,
-               "The size of the allocated DMA buffers.  If actual operating "
-               "parameters require larger buffers, an attempt to reallocate "
-               "will be made.");
-
-static int min_buffers = 1;
-module_param(min_buffers, uint, 0644);
-MODULE_PARM_DESC(min_buffers,
-               "The minimum number of streaming I/O buffers we are willing "
-               "to work with.");
-
-static int max_buffers = 10;
-module_param(max_buffers, uint, 0644);
-MODULE_PARM_DESC(max_buffers,
-               "The maximum number of streaming I/O buffers an application "
-               "will be allowed to allocate.  These buffers are big and live "
-               "in vmalloc space.");
-
-static int flip;
-module_param(flip, bool, 0444);
-MODULE_PARM_DESC(flip,
-               "If set, the sensor will be instructed to flip the image "
-               "vertically.");
-
-
-enum cafe_state {
-       S_NOTREADY,     /* Not yet initialized */
-       S_IDLE,         /* Just hanging around */
-       S_FLAKED,       /* Some sort of problem */
-       S_SINGLEREAD,   /* In read() */
-       S_SPECREAD,     /* Speculative read (for future read()) */
-       S_STREAMING     /* Streaming data */
-};
-
-/*
- * Tracking of streaming I/O buffers.
- */
-struct cafe_sio_buffer {
-       struct list_head list;
-       struct v4l2_buffer v4lbuf;
-       char *buffer;   /* Where it lives in kernel space */
-       int mapcount;
-       struct cafe_camera *cam;
-};
-
-/*
- * A description of one of our devices.
- * Locking: controlled by s_mutex.  Certain fields, however, require
- *         the dev_lock spinlock; they are marked as such by comments.
- *         dev_lock is also required for access to device registers.
- */
-struct cafe_camera
-{
-       struct v4l2_device v4l2_dev;
-       enum cafe_state state;
-       unsigned long flags;            /* Buffer status, mainly (dev_lock) */
-       int users;                      /* How many open FDs */
-       struct file *owner;             /* Who has data access (v4l2) */
-
-       /*
-        * Subsystem structures.
-        */
-       struct pci_dev *pdev;
-       struct video_device vdev;
-       struct i2c_adapter i2c_adapter;
-       struct v4l2_subdev *sensor;
-       unsigned short sensor_addr;
-
-       unsigned char __iomem *regs;
-       struct list_head dev_list;      /* link to other devices */
-
-       /* DMA buffers */
-       unsigned int nbufs;             /* How many are alloc'd */
-       int next_buf;                   /* Next to consume (dev_lock) */
-       unsigned int dma_buf_size;      /* allocated size */
-       void *dma_bufs[MAX_DMA_BUFS];   /* Internal buffer addresses */
-       dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */
-       unsigned int specframes;        /* Unconsumed spec frames (dev_lock) */
-       unsigned int sequence;          /* Frame sequence number */
-       unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual buffers */
-
-       /* Streaming buffers */
-       unsigned int n_sbufs;           /* How many we have */
-       struct cafe_sio_buffer *sb_bufs; /* The array of housekeeping structs */
-       struct list_head sb_avail;      /* Available for data (we own) (dev_lock) */
-       struct list_head sb_full;       /* With data (user space owns) (dev_lock) */
-       struct tasklet_struct s_tasklet;
-
-       /* Current operating parameters */
-       u32 sensor_type;                /* Currently ov7670 only */
-       struct v4l2_pix_format pix_format;
-       enum v4l2_mbus_pixelcode mbus_code;
-
-       /* Locks */
-       struct mutex s_mutex; /* Access to this structure */
-       spinlock_t dev_lock;  /* Access to device */
-
-       /* Misc */
-       wait_queue_head_t smbus_wait;   /* Waiting on i2c events */
-       wait_queue_head_t iowait;       /* Waiting on frame data */
-};
-
-/*
- * Status flags.  Always manipulated with bit operations.
- */
-#define CF_BUF0_VALID   0      /* Buffers valid - first three */
-#define CF_BUF1_VALID   1
-#define CF_BUF2_VALID   2
-#define CF_DMA_ACTIVE   3      /* A frame is incoming */
-#define CF_CONFIG_NEEDED 4     /* Must configure hardware */
-
-#define sensor_call(cam, o, f, args...) \
-       v4l2_subdev_call(cam->sensor, o, f, ##args)
-
-static inline struct cafe_camera *to_cam(struct v4l2_device *dev)
-{
-       return container_of(dev, struct cafe_camera, v4l2_dev);
-}
-
-static struct cafe_format_struct {
-       __u8 *desc;
-       __u32 pixelformat;
-       int bpp;   /* Bytes per pixel */
-       enum v4l2_mbus_pixelcode mbus_code;
-} cafe_formats[] = {
-       {
-               .desc           = "YUYV 4:2:2",
-               .pixelformat    = V4L2_PIX_FMT_YUYV,
-               .mbus_code      = V4L2_MBUS_FMT_YUYV8_2X8,
-               .bpp            = 2,
-       },
-       {
-               .desc           = "RGB 444",
-               .pixelformat    = V4L2_PIX_FMT_RGB444,
-               .mbus_code      = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
-               .bpp            = 2,
-       },
-       {
-               .desc           = "RGB 565",
-               .pixelformat    = V4L2_PIX_FMT_RGB565,
-               .mbus_code      = V4L2_MBUS_FMT_RGB565_2X8_LE,
-               .bpp            = 2,
-       },
-       {
-               .desc           = "Raw RGB Bayer",
-               .pixelformat    = V4L2_PIX_FMT_SBGGR8,
-               .mbus_code      = V4L2_MBUS_FMT_SBGGR8_1X8,
-               .bpp            = 1
-       },
-};
-#define N_CAFE_FMTS ARRAY_SIZE(cafe_formats)
-
-static struct cafe_format_struct *cafe_find_format(u32 pixelformat)
-{
-       unsigned i;
-
-       for (i = 0; i < N_CAFE_FMTS; i++)
-               if (cafe_formats[i].pixelformat == pixelformat)
-                       return cafe_formats + i;
-       /* Not found? Then return the first format. */
-       return cafe_formats;
-}
-
-/*
- * Start over with DMA buffers - dev_lock needed.
- */
-static void cafe_reset_buffers(struct cafe_camera *cam)
-{
-       int i;
-
-       cam->next_buf = -1;
-       for (i = 0; i < cam->nbufs; i++)
-               clear_bit(i, &cam->flags);
-       cam->specframes = 0;
-}
-
-static inline int cafe_needs_config(struct cafe_camera *cam)
-{
-       return test_bit(CF_CONFIG_NEEDED, &cam->flags);
-}
-
-static void cafe_set_config_needed(struct cafe_camera *cam, int needed)
-{
-       if (needed)
-               set_bit(CF_CONFIG_NEEDED, &cam->flags);
-       else
-               clear_bit(CF_CONFIG_NEEDED, &cam->flags);
-}
-
-
-
-
-/*
- * Debugging and related.
- */
-#define cam_err(cam, fmt, arg...) \
-       dev_err(&(cam)->pdev->dev, fmt, ##arg);
-#define cam_warn(cam, fmt, arg...) \
-       dev_warn(&(cam)->pdev->dev, fmt, ##arg);
-#define cam_dbg(cam, fmt, arg...) \
-       dev_dbg(&(cam)->pdev->dev, fmt, ##arg);
-
-
-/* ---------------------------------------------------------------------*/
-
-/*
- * Device register I/O
- */
-static inline void cafe_reg_write(struct cafe_camera *cam, unsigned int reg,
-               unsigned int val)
-{
-       iowrite32(val, cam->regs + reg);
-}
-
-static inline unsigned int cafe_reg_read(struct cafe_camera *cam,
-               unsigned int reg)
-{
-       return ioread32(cam->regs + reg);
-}
-
-
-static inline void cafe_reg_write_mask(struct cafe_camera *cam, unsigned int reg,
-               unsigned int val, unsigned int mask)
-{
-       unsigned int v = cafe_reg_read(cam, reg);
-
-       v = (v & ~mask) | (val & mask);
-       cafe_reg_write(cam, reg, v);
-}
-
-static inline void cafe_reg_clear_bit(struct cafe_camera *cam,
-               unsigned int reg, unsigned int val)
-{
-       cafe_reg_write_mask(cam, reg, 0, val);
-}
-
-static inline void cafe_reg_set_bit(struct cafe_camera *cam,
-               unsigned int reg, unsigned int val)
-{
-       cafe_reg_write_mask(cam, reg, val, val);
-}
-
-
-
-/* -------------------------------------------------------------------- */
-/*
- * The I2C/SMBUS interface to the camera itself starts here.  The
- * controller handles SMBUS itself, presenting a relatively simple register
- * interface; all we have to do is to tell it where to route the data.
- */
-#define CAFE_SMBUS_TIMEOUT (HZ)  /* generous */
-
-static int cafe_smbus_write_done(struct cafe_camera *cam)
-{
-       unsigned long flags;
-       int c1;
-
-       /*
-        * We must delay after the interrupt, or the controller gets confused
-        * and never does give us good status.  Fortunately, we don't do this
-        * often.
-        */
-       udelay(20);
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       c1 = cafe_reg_read(cam, REG_TWSIC1);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-       return (c1 & (TWSIC1_WSTAT|TWSIC1_ERROR)) != TWSIC1_WSTAT;
-}
-
-static int cafe_smbus_write_data(struct cafe_camera *cam,
-               u16 addr, u8 command, u8 value)
-{
-       unsigned int rval;
-       unsigned long flags;
-
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID);
-       rval |= TWSIC0_OVMAGIC;  /* Make OV sensors work */
-       /*
-        * Marvell sez set clkdiv to all 1's for now.
-        */
-       rval |= TWSIC0_CLKDIV;
-       cafe_reg_write(cam, REG_TWSIC0, rval);
-       (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */
-       rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR);
-       cafe_reg_write(cam, REG_TWSIC1, rval);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-
-       /* Unfortunately, reading TWSIC1 too soon after sending a command
-        * causes the device to die.
-        * Use a busy-wait because we often send a large quantity of small
-        * commands at-once; using msleep() would cause a lot of context
-        * switches which take longer than 2ms, resulting in a noticeable
-        * boot-time and capture-start delays.
-        */
-       mdelay(2);
-
-       /*
-        * Another sad fact is that sometimes, commands silently complete but
-        * cafe_smbus_write_done() never becomes aware of this.
-        * This happens at random and appears to possible occur with any
-        * command.
-        * We don't understand why this is. We work around this issue
-        * with the timeout in the wait below, assuming that all commands
-        * complete within the timeout.
-        */
-       wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam),
-                       CAFE_SMBUS_TIMEOUT);
-
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       rval = cafe_reg_read(cam, REG_TWSIC1);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-
-       if (rval & TWSIC1_WSTAT) {
-               cam_err(cam, "SMBUS write (%02x/%02x/%02x) timed out\n", addr,
-                               command, value);
-               return -EIO;
-       }
-       if (rval & TWSIC1_ERROR) {
-               cam_err(cam, "SMBUS write (%02x/%02x/%02x) error\n", addr,
-                               command, value);
-               return -EIO;
-       }
-       return 0;
-}
-
-
-
-static int cafe_smbus_read_done(struct cafe_camera *cam)
-{
-       unsigned long flags;
-       int c1;
-
-       /*
-        * We must delay after the interrupt, or the controller gets confused
-        * and never does give us good status.  Fortunately, we don't do this
-        * often.
-        */
-       udelay(20);
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       c1 = cafe_reg_read(cam, REG_TWSIC1);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-       return c1 & (TWSIC1_RVALID|TWSIC1_ERROR);
-}
-
-
-
-static int cafe_smbus_read_data(struct cafe_camera *cam,
-               u16 addr, u8 command, u8 *value)
-{
-       unsigned int rval;
-       unsigned long flags;
-
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID);
-       rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */
-       /*
-        * Marvel sez set clkdiv to all 1's for now.
-        */
-       rval |= TWSIC0_CLKDIV;
-       cafe_reg_write(cam, REG_TWSIC0, rval);
-       (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */
-       rval = TWSIC1_READ | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR);
-       cafe_reg_write(cam, REG_TWSIC1, rval);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-
-       wait_event_timeout(cam->smbus_wait,
-                       cafe_smbus_read_done(cam), CAFE_SMBUS_TIMEOUT);
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       rval = cafe_reg_read(cam, REG_TWSIC1);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-
-       if (rval & TWSIC1_ERROR) {
-               cam_err(cam, "SMBUS read (%02x/%02x) error\n", addr, command);
-               return -EIO;
-       }
-       if (! (rval & TWSIC1_RVALID)) {
-               cam_err(cam, "SMBUS read (%02x/%02x) timed out\n", addr,
-                               command);
-               return -EIO;
-       }
-       *value = rval & 0xff;
-       return 0;
-}
-
-/*
- * Perform a transfer over SMBUS.  This thing is called under
- * the i2c bus lock, so we shouldn't race with ourselves...
- */
-static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
-               unsigned short flags, char rw, u8 command,
-               int size, union i2c_smbus_data *data)
-{
-       struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter);
-       struct cafe_camera *cam = to_cam(v4l2_dev);
-       int ret = -EINVAL;
-
-       /*
-        * This interface would appear to only do byte data ops.  OK
-        * it can do word too, but the cam chip has no use for that.
-        */
-       if (size != I2C_SMBUS_BYTE_DATA) {
-               cam_err(cam, "funky xfer size %d\n", size);
-               return -EINVAL;
-       }
-
-       if (rw == I2C_SMBUS_WRITE)
-               ret = cafe_smbus_write_data(cam, addr, command, data->byte);
-       else if (rw == I2C_SMBUS_READ)
-               ret = cafe_smbus_read_data(cam, addr, command, &data->byte);
-       return ret;
-}
-
-
-static void cafe_smbus_enable_irq(struct cafe_camera *cam)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       cafe_reg_set_bit(cam, REG_IRQMASK, TWSIIRQS);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-}
-
-static u32 cafe_smbus_func(struct i2c_adapter *adapter)
-{
-       return I2C_FUNC_SMBUS_READ_BYTE_DATA  |
-              I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
-}
-
-static struct i2c_algorithm cafe_smbus_algo = {
-       .smbus_xfer = cafe_smbus_xfer,
-       .functionality = cafe_smbus_func
-};
-
-/* Somebody is on the bus */
-static void cafe_ctlr_stop_dma(struct cafe_camera *cam);
-static void cafe_ctlr_power_down(struct cafe_camera *cam);
-
-static int cafe_smbus_setup(struct cafe_camera *cam)
-{
-       struct i2c_adapter *adap = &cam->i2c_adapter;
-       int ret;
-
-       cafe_smbus_enable_irq(cam);
-       adap->owner = THIS_MODULE;
-       adap->algo = &cafe_smbus_algo;
-       strcpy(adap->name, "cafe_ccic");
-       adap->dev.parent = &cam->pdev->dev;
-       i2c_set_adapdata(adap, &cam->v4l2_dev);
-       ret = i2c_add_adapter(adap);
-       if (ret)
-               printk(KERN_ERR "Unable to register cafe i2c adapter\n");
-       return ret;
-}
-
-static void cafe_smbus_shutdown(struct cafe_camera *cam)
-{
-       i2c_del_adapter(&cam->i2c_adapter);
-}
-
-
-/* ------------------------------------------------------------------- */
-/*
- * Deal with the controller.
- */
-
-/*
- * Do everything we think we need to have the interface operating
- * according to the desired format.
- */
-static void cafe_ctlr_dma(struct cafe_camera *cam)
-{
-       /*
-        * Store the first two Y buffers (we aren't supporting
-        * planar formats for now, so no UV bufs).  Then either
-        * set the third if it exists, or tell the controller
-        * to just use two.
-        */
-       cafe_reg_write(cam, REG_Y0BAR, cam->dma_handles[0]);
-       cafe_reg_write(cam, REG_Y1BAR, cam->dma_handles[1]);
-       if (cam->nbufs > 2) {
-               cafe_reg_write(cam, REG_Y2BAR, cam->dma_handles[2]);
-               cafe_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS);
-       }
-       else
-               cafe_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
-       cafe_reg_write(cam, REG_UBAR, 0); /* 32 bits only for now */
-}
-
-static void cafe_ctlr_image(struct cafe_camera *cam)
-{
-       int imgsz;
-       struct v4l2_pix_format *fmt = &cam->pix_format;
-
-       imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |
-               (fmt->bytesperline & IMGSZ_H_MASK);
-       cafe_reg_write(cam, REG_IMGSIZE, imgsz);
-       cafe_reg_write(cam, REG_IMGOFFSET, 0);
-       /* YPITCH just drops the last two bits */
-       cafe_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,
-                       IMGP_YP_MASK);
-       /*
-        * Tell the controller about the image format we are using.
-        */
-       switch (cam->pix_format.pixelformat) {
-       case V4L2_PIX_FMT_YUYV:
-           cafe_reg_write_mask(cam, REG_CTRL0,
-                           C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
-                           C0_DF_MASK);
-           break;
-
-       case V4L2_PIX_FMT_RGB444:
-           cafe_reg_write_mask(cam, REG_CTRL0,
-                           C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
-                           C0_DF_MASK);
-               /* Alpha value? */
-           break;
-
-       case V4L2_PIX_FMT_RGB565:
-           cafe_reg_write_mask(cam, REG_CTRL0,
-                           C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
-                           C0_DF_MASK);
-           break;
-
-       default:
-           cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
-           break;
-       }
-       /*
-        * Make sure it knows we want to use hsync/vsync.
-        */
-       cafe_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
-                       C0_SIFM_MASK);
-}
-
-
-/*
- * Configure the controller for operation; caller holds the
- * device mutex.
- */
-static int cafe_ctlr_configure(struct cafe_camera *cam)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       cafe_ctlr_dma(cam);
-       cafe_ctlr_image(cam);
-       cafe_set_config_needed(cam, 0);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-       return 0;
-}
-
-static void cafe_ctlr_irq_enable(struct cafe_camera *cam)
-{
-       /*
-        * Clear any pending interrupts, since we do not
-        * expect to have I/O active prior to enabling.
-        */
-       cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS);
-       cafe_reg_set_bit(cam, REG_IRQMASK, FRAMEIRQS);
-}
-
-static void cafe_ctlr_irq_disable(struct cafe_camera *cam)
-{
-       cafe_reg_clear_bit(cam, REG_IRQMASK, FRAMEIRQS);
-}
-
-/*
- * Make the controller start grabbing images.  Everything must
- * be set up before doing this.
- */
-static void cafe_ctlr_start(struct cafe_camera *cam)
-{
-       /* set_bit performs a read, so no other barrier should be
-          needed here */
-       cafe_reg_set_bit(cam, REG_CTRL0, C0_ENABLE);
-}
-
-static void cafe_ctlr_stop(struct cafe_camera *cam)
-{
-       cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
-}
-
-static void cafe_ctlr_init(struct cafe_camera *cam)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       /*
-        * Added magic to bring up the hardware on the B-Test board
-        */
-       cafe_reg_write(cam, 0x3038, 0x8);
-       cafe_reg_write(cam, 0x315c, 0x80008);
-       /*
-        * Go through the dance needed to wake the device up.
-        * Note that these registers are global and shared
-        * with the NAND and SD devices.  Interaction between the
-        * three still needs to be examined.
-        */
-       cafe_reg_write(cam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */
-       cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRC);
-       cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRS);
-       /*
-        * Here we must wait a bit for the controller to come around.
-        */
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-       msleep(5);
-       spin_lock_irqsave(&cam->dev_lock, flags);
-
-       cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC);
-       cafe_reg_set_bit(cam, REG_GL_IMASK, GIMSK_CCIC_EN);
-       /*
-        * Make sure it's not powered down.
-        */
-       cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
-       /*
-        * Turn off the enable bit.  It sure should be off anyway,
-        * but it's good to be sure.
-        */
-       cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
-       /*
-        * Mask all interrupts.
-        */
-       cafe_reg_write(cam, REG_IRQMASK, 0);
-       /*
-        * Clock the sensor appropriately.  Controller clock should
-        * be 48MHz, sensor "typical" value is half that.
-        */
-       cafe_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-}
-
-
-/*
- * Stop the controller, and don't return until we're really sure that no
- * further DMA is going on.
- */
-static void cafe_ctlr_stop_dma(struct cafe_camera *cam)
-{
-       unsigned long flags;
-
-       /*
-        * Theory: stop the camera controller (whether it is operating
-        * or not).  Delay briefly just in case we race with the SOF
-        * interrupt, then wait until no DMA is active.
-        */
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       cafe_ctlr_stop(cam);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-       mdelay(1);
-       wait_event_timeout(cam->iowait,
-                       !test_bit(CF_DMA_ACTIVE, &cam->flags), HZ);
-       if (test_bit(CF_DMA_ACTIVE, &cam->flags))
-               cam_err(cam, "Timeout waiting for DMA to end\n");
-               /* This would be bad news - what now? */
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       cam->state = S_IDLE;
-       cafe_ctlr_irq_disable(cam);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-}
-
-/*
- * Power up and down.
- */
-static void cafe_ctlr_power_up(struct cafe_camera *cam)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
-       /*
-        * Part one of the sensor dance: turn the global
-        * GPIO signal on.
-        */
-       cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON);
-       cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT|GGPIO_VAL);
-       /*
-        * Put the sensor into operational mode (assumes OLPC-style
-        * wiring).  Control 0 is reset - set to 1 to operate.
-        * Control 1 is power down, set to 0 to operate.
-        */
-       cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */
-/*     mdelay(1); */ /* Marvell says 1ms will do it */
-       cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0);
-/*     mdelay(1); */ /* Enough? */
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-       msleep(5); /* Just to be sure */
-}
-
-static void cafe_ctlr_power_down(struct cafe_camera *cam)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1);
-       cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON);
-       cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT);
-       cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-}
-
-/* -------------------------------------------------------------------- */
-/*
- * Communications with the sensor.
- */
-
-static int __cafe_cam_reset(struct cafe_camera *cam)
-{
-       return sensor_call(cam, core, reset, 0);
-}
-
-/*
- * We have found the sensor on the i2c.  Let's try to have a
- * conversation.
- */
-static int cafe_cam_init(struct cafe_camera *cam)
-{
-       struct v4l2_dbg_chip_ident chip;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       if (cam->state != S_NOTREADY)
-               cam_warn(cam, "Cam init with device in funky state %d",
-                               cam->state);
-       ret = __cafe_cam_reset(cam);
-       if (ret)
-               goto out;
-       chip.ident = V4L2_IDENT_NONE;
-       chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR;
-       chip.match.addr = cam->sensor_addr;
-       ret = sensor_call(cam, core, g_chip_ident, &chip);
-       if (ret)
-               goto out;
-       cam->sensor_type = chip.ident;
-       if (cam->sensor_type != V4L2_IDENT_OV7670) {
-               cam_err(cam, "Unsupported sensor type 0x%x", cam->sensor_type);
-               ret = -EINVAL;
-               goto out;
-       }
-/* Get/set parameters? */
-       ret = 0;
-       cam->state = S_IDLE;
-  out:
-       cafe_ctlr_power_down(cam);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-/*
- * Configure the sensor to match the parameters we have.  Caller should
- * hold s_mutex
- */
-static int cafe_cam_set_flip(struct cafe_camera *cam)
-{
-       struct v4l2_control ctrl;
-
-       memset(&ctrl, 0, sizeof(ctrl));
-       ctrl.id = V4L2_CID_VFLIP;
-       ctrl.value = flip;
-       return sensor_call(cam, core, s_ctrl, &ctrl);
-}
-
-
-static int cafe_cam_configure(struct cafe_camera *cam)
-{
-       struct v4l2_mbus_framefmt mbus_fmt;
-       int ret;
-
-       v4l2_fill_mbus_format(&mbus_fmt, &cam->pix_format, cam->mbus_code);
-       ret = sensor_call(cam, core, init, 0);
-       if (ret == 0)
-               ret = sensor_call(cam, video, s_mbus_fmt, &mbus_fmt);
-       /*
-        * OV7670 does weird things if flip is set *before* format...
-        */
-       ret += cafe_cam_set_flip(cam);
-       return ret;
-}
-
-/* -------------------------------------------------------------------- */
-/*
- * DMA buffer management.  These functions need s_mutex held.
- */
-
-/* FIXME: this is inefficient as hell, since dma_alloc_coherent just
- * does a get_free_pages() call, and we waste a good chunk of an orderN
- * allocation.  Should try to allocate the whole set in one chunk.
- */
-static int cafe_alloc_dma_bufs(struct cafe_camera *cam, int loadtime)
-{
-       int i;
-
-       cafe_set_config_needed(cam, 1);
-       if (loadtime)
-               cam->dma_buf_size = dma_buf_size;
-       else
-               cam->dma_buf_size = cam->pix_format.sizeimage;
-       if (n_dma_bufs > 3)
-               n_dma_bufs = 3;
-
-       cam->nbufs = 0;
-       for (i = 0; i < n_dma_bufs; i++) {
-               cam->dma_bufs[i] = dma_alloc_coherent(&cam->pdev->dev,
-                               cam->dma_buf_size, cam->dma_handles + i,
-                               GFP_KERNEL);
-               if (cam->dma_bufs[i] == NULL) {
-                       cam_warn(cam, "Failed to allocate DMA buffer\n");
-                       break;
-               }
-               /* For debug, remove eventually */
-               memset(cam->dma_bufs[i], 0xcc, cam->dma_buf_size);
-               (cam->nbufs)++;
-       }
-
-       switch (cam->nbufs) {
-       case 1:
-           dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size,
-                           cam->dma_bufs[0], cam->dma_handles[0]);
-           cam->nbufs = 0;
-       case 0:
-           cam_err(cam, "Insufficient DMA buffers, cannot operate\n");
-           return -ENOMEM;
-
-       case 2:
-           if (n_dma_bufs > 2)
-                   cam_warn(cam, "Will limp along with only 2 buffers\n");
-           break;
-       }
-       return 0;
-}
-
-static void cafe_free_dma_bufs(struct cafe_camera *cam)
-{
-       int i;
-
-       for (i = 0; i < cam->nbufs; i++) {
-               dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size,
-                               cam->dma_bufs[i], cam->dma_handles[i]);
-               cam->dma_bufs[i] = NULL;
-       }
-       cam->nbufs = 0;
-}
-
-
-
-
-
-/* ----------------------------------------------------------------------- */
-/*
- * Here starts the V4L2 interface code.
- */
-
-/*
- * Read an image from the device.
- */
-static ssize_t cafe_deliver_buffer(struct cafe_camera *cam,
-               char __user *buffer, size_t len, loff_t *pos)
-{
-       int bufno;
-       unsigned long flags;
-
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       if (cam->next_buf < 0) {
-               cam_err(cam, "deliver_buffer: No next buffer\n");
-               spin_unlock_irqrestore(&cam->dev_lock, flags);
-               return -EIO;
-       }
-       bufno = cam->next_buf;
-       clear_bit(bufno, &cam->flags);
-       if (++(cam->next_buf) >= cam->nbufs)
-               cam->next_buf = 0;
-       if (! test_bit(cam->next_buf, &cam->flags))
-               cam->next_buf = -1;
-       cam->specframes = 0;
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-
-       if (len > cam->pix_format.sizeimage)
-               len = cam->pix_format.sizeimage;
-       if (copy_to_user(buffer, cam->dma_bufs[bufno], len))
-               return -EFAULT;
-       (*pos) += len;
-       return len;
-}
-
-/*
- * Get everything ready, and start grabbing frames.
- */
-static int cafe_read_setup(struct cafe_camera *cam, enum cafe_state state)
-{
-       int ret;
-       unsigned long flags;
-
-       /*
-        * Configuration.  If we still don't have DMA buffers,
-        * make one last, desperate attempt.
-        */
-       if (cam->nbufs == 0)
-               if (cafe_alloc_dma_bufs(cam, 0))
-                       return -ENOMEM;
-
-       if (cafe_needs_config(cam)) {
-               cafe_cam_configure(cam);
-               ret = cafe_ctlr_configure(cam);
-               if (ret)
-                       return ret;
-       }
-
-       /*
-        * Turn it loose.
-        */
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       cafe_reset_buffers(cam);
-       cafe_ctlr_irq_enable(cam);
-       cam->state = state;
-       cafe_ctlr_start(cam);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-       return 0;
-}
-
-
-static ssize_t cafe_v4l_read(struct file *filp,
-               char __user *buffer, size_t len, loff_t *pos)
-{
-       struct cafe_camera *cam = filp->private_data;
-       int ret = 0;
-
-       /*
-        * Perhaps we're in speculative read mode and already
-        * have data?
-        */
-       mutex_lock(&cam->s_mutex);
-       if (cam->state == S_SPECREAD) {
-               if (cam->next_buf >= 0) {
-                       ret = cafe_deliver_buffer(cam, buffer, len, pos);
-                       if (ret != 0)
-                               goto out_unlock;
-               }
-       } else if (cam->state == S_FLAKED || cam->state == S_NOTREADY) {
-               ret = -EIO;
-               goto out_unlock;
-       } else if (cam->state != S_IDLE) {
-               ret = -EBUSY;
-               goto out_unlock;
-       }
-
-       /*
-        * v4l2: multiple processes can open the device, but only
-        * one gets to grab data from it.
-        */
-       if (cam->owner && cam->owner != filp) {
-               ret = -EBUSY;
-               goto out_unlock;
-       }
-       cam->owner = filp;
-
-       /*
-        * Do setup if need be.
-        */
-       if (cam->state != S_SPECREAD) {
-               ret = cafe_read_setup(cam, S_SINGLEREAD);
-               if (ret)
-                       goto out_unlock;
-       }
-       /*
-        * Wait for something to happen.  This should probably
-        * be interruptible (FIXME).
-        */
-       wait_event_timeout(cam->iowait, cam->next_buf >= 0, HZ);
-       if (cam->next_buf < 0) {
-               cam_err(cam, "read() operation timed out\n");
-               cafe_ctlr_stop_dma(cam);
-               ret = -EIO;
-               goto out_unlock;
-       }
-       /*
-        * Give them their data and we should be done.
-        */
-       ret = cafe_deliver_buffer(cam, buffer, len, pos);
-
-  out_unlock:
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-
-
-
-
-
-
-
-/*
- * Streaming I/O support.
- */
-
-
-
-static int cafe_vidioc_streamon(struct file *filp, void *priv,
-               enum v4l2_buf_type type)
-{
-       struct cafe_camera *cam = filp->private_data;
-       int ret = -EINVAL;
-
-       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               goto out;
-       mutex_lock(&cam->s_mutex);
-       if (cam->state != S_IDLE || cam->n_sbufs == 0)
-               goto out_unlock;
-
-       cam->sequence = 0;
-       ret = cafe_read_setup(cam, S_STREAMING);
-
-  out_unlock:
-       mutex_unlock(&cam->s_mutex);
-  out:
-       return ret;
-}
-
-
-static int cafe_vidioc_streamoff(struct file *filp, void *priv,
-               enum v4l2_buf_type type)
-{
-       struct cafe_camera *cam = filp->private_data;
-       int ret = -EINVAL;
-
-       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               goto out;
-       mutex_lock(&cam->s_mutex);
-       if (cam->state != S_STREAMING)
-               goto out_unlock;
-
-       cafe_ctlr_stop_dma(cam);
-       ret = 0;
-
-  out_unlock:
-       mutex_unlock(&cam->s_mutex);
-  out:
-       return ret;
-}
-
-
-
-static int cafe_setup_siobuf(struct cafe_camera *cam, int index)
-{
-       struct cafe_sio_buffer *buf = cam->sb_bufs + index;
-
-       INIT_LIST_HEAD(&buf->list);
-       buf->v4lbuf.length = PAGE_ALIGN(cam->pix_format.sizeimage);
-       buf->buffer = vmalloc_user(buf->v4lbuf.length);
-       if (buf->buffer == NULL)
-               return -ENOMEM;
-       buf->mapcount = 0;
-       buf->cam = cam;
-
-       buf->v4lbuf.index = index;
-       buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       buf->v4lbuf.field = V4L2_FIELD_NONE;
-       buf->v4lbuf.memory = V4L2_MEMORY_MMAP;
-       /*
-        * Offset: must be 32-bit even on a 64-bit system.  videobuf-dma-sg
-        * just uses the length times the index, but the spec warns
-        * against doing just that - vma merging problems.  So we
-        * leave a gap between each pair of buffers.
-        */
-       buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length;
-       return 0;
-}
-
-static int cafe_free_sio_buffers(struct cafe_camera *cam)
-{
-       int i;
-
-       /*
-        * If any buffers are mapped, we cannot free them at all.
-        */
-       for (i = 0; i < cam->n_sbufs; i++)
-               if (cam->sb_bufs[i].mapcount > 0)
-                       return -EBUSY;
-       /*
-        * OK, let's do it.
-        */
-       for (i = 0; i < cam->n_sbufs; i++)
-               vfree(cam->sb_bufs[i].buffer);
-       cam->n_sbufs = 0;
-       kfree(cam->sb_bufs);
-       cam->sb_bufs = NULL;
-       INIT_LIST_HEAD(&cam->sb_avail);
-       INIT_LIST_HEAD(&cam->sb_full);
-       return 0;
-}
-
-
-
-static int cafe_vidioc_reqbufs(struct file *filp, void *priv,
-               struct v4l2_requestbuffers *req)
-{
-       struct cafe_camera *cam = filp->private_data;
-       int ret = 0;  /* Silence warning */
-
-       /*
-        * Make sure it's something we can do.  User pointers could be
-        * implemented without great pain, but that's not been done yet.
-        */
-       if (req->memory != V4L2_MEMORY_MMAP)
-               return -EINVAL;
-       /*
-        * If they ask for zero buffers, they really want us to stop streaming
-        * (if it's happening) and free everything.  Should we check owner?
-        */
-       mutex_lock(&cam->s_mutex);
-       if (req->count == 0) {
-               if (cam->state == S_STREAMING)
-                       cafe_ctlr_stop_dma(cam);
-               ret = cafe_free_sio_buffers (cam);
-               goto out;
-       }
-       /*
-        * Device needs to be idle and working.  We *could* try to do the
-        * right thing in S_SPECREAD by shutting things down, but it
-        * probably doesn't matter.
-        */
-       if (cam->state != S_IDLE || (cam->owner && cam->owner != filp)) {
-               ret = -EBUSY;
-               goto out;
-       }
-       cam->owner = filp;
-
-       if (req->count < min_buffers)
-               req->count = min_buffers;
-       else if (req->count > max_buffers)
-               req->count = max_buffers;
-       if (cam->n_sbufs > 0) {
-               ret = cafe_free_sio_buffers(cam);
-               if (ret)
-                       goto out;
-       }
-
-       cam->sb_bufs = kzalloc(req->count*sizeof(struct cafe_sio_buffer),
-                       GFP_KERNEL);
-       if (cam->sb_bufs == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
-       for (cam->n_sbufs = 0; cam->n_sbufs < req->count; (cam->n_sbufs++)) {
-               ret = cafe_setup_siobuf(cam, cam->n_sbufs);
-               if (ret)
-                       break;
-       }
-
-       if (cam->n_sbufs == 0)  /* no luck at all - ret already set */
-               kfree(cam->sb_bufs);
-       req->count = cam->n_sbufs;  /* In case of partial success */
-
-  out:
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-
-static int cafe_vidioc_querybuf(struct file *filp, void *priv,
-               struct v4l2_buffer *buf)
-{
-       struct cafe_camera *cam = filp->private_data;
-       int ret = -EINVAL;
-
-       mutex_lock(&cam->s_mutex);
-       if (buf->index >= cam->n_sbufs)
-               goto out;
-       *buf = cam->sb_bufs[buf->index].v4lbuf;
-       ret = 0;
-  out:
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-static int cafe_vidioc_qbuf(struct file *filp, void *priv,
-               struct v4l2_buffer *buf)
-{
-       struct cafe_camera *cam = filp->private_data;
-       struct cafe_sio_buffer *sbuf;
-       int ret = -EINVAL;
-       unsigned long flags;
-
-       mutex_lock(&cam->s_mutex);
-       if (buf->index >= cam->n_sbufs)
-               goto out;
-       sbuf = cam->sb_bufs + buf->index;
-       if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) {
-               ret = 0; /* Already queued?? */
-               goto out;
-       }
-       if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_DONE) {
-               /* Spec doesn't say anything, seems appropriate tho */
-               ret = -EBUSY;
-               goto out;
-       }
-       sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED;
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       list_add(&sbuf->list, &cam->sb_avail);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-       ret = 0;
-  out:
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-static int cafe_vidioc_dqbuf(struct file *filp, void *priv,
-               struct v4l2_buffer *buf)
-{
-       struct cafe_camera *cam = filp->private_data;
-       struct cafe_sio_buffer *sbuf;
-       int ret = -EINVAL;
-       unsigned long flags;
-
-       mutex_lock(&cam->s_mutex);
-       if (cam->state != S_STREAMING)
-               goto out_unlock;
-       if (list_empty(&cam->sb_full) && filp->f_flags & O_NONBLOCK) {
-               ret = -EAGAIN;
-               goto out_unlock;
-       }
-
-       while (list_empty(&cam->sb_full) && cam->state == S_STREAMING) {
-               mutex_unlock(&cam->s_mutex);
-               if (wait_event_interruptible(cam->iowait,
-                                               !list_empty(&cam->sb_full))) {
-                       ret = -ERESTARTSYS;
-                       goto out;
-               }
-               mutex_lock(&cam->s_mutex);
-       }
-
-       if (cam->state != S_STREAMING)
-               ret = -EINTR;
-       else {
-               spin_lock_irqsave(&cam->dev_lock, flags);
-               /* Should probably recheck !list_empty() here */
-               sbuf = list_entry(cam->sb_full.next,
-                               struct cafe_sio_buffer, list);
-               list_del_init(&sbuf->list);
-               spin_unlock_irqrestore(&cam->dev_lock, flags);
-               sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE;
-               *buf = sbuf->v4lbuf;
-               ret = 0;
-       }
-
-  out_unlock:
-       mutex_unlock(&cam->s_mutex);
-  out:
-       return ret;
-}
-
-
-
-static void cafe_v4l_vm_open(struct vm_area_struct *vma)
-{
-       struct cafe_sio_buffer *sbuf = vma->vm_private_data;
-       /*
-        * Locking: done under mmap_sem, so we don't need to
-        * go back to the camera lock here.
-        */
-       sbuf->mapcount++;
-}
-
-
-static void cafe_v4l_vm_close(struct vm_area_struct *vma)
-{
-       struct cafe_sio_buffer *sbuf = vma->vm_private_data;
-
-       mutex_lock(&sbuf->cam->s_mutex);
-       sbuf->mapcount--;
-       /* Docs say we should stop I/O too... */
-       if (sbuf->mapcount == 0)
-               sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED;
-       mutex_unlock(&sbuf->cam->s_mutex);
-}
-
-static const struct vm_operations_struct cafe_v4l_vm_ops = {
-       .open = cafe_v4l_vm_open,
-       .close = cafe_v4l_vm_close
-};
-
-
-static int cafe_v4l_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       struct cafe_camera *cam = filp->private_data;
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       int ret = -EINVAL;
-       int i;
-       struct cafe_sio_buffer *sbuf = NULL;
-
-       if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED))
-               return -EINVAL;
-       /*
-        * Find the buffer they are looking for.
-        */
-       mutex_lock(&cam->s_mutex);
-       for (i = 0; i < cam->n_sbufs; i++)
-               if (cam->sb_bufs[i].v4lbuf.m.offset == offset) {
-                       sbuf = cam->sb_bufs + i;
-                       break;
-               }
-       if (sbuf == NULL)
-               goto out;
-
-       ret = remap_vmalloc_range(vma, sbuf->buffer, 0);
-       if (ret)
-               goto out;
-       vma->vm_flags |= VM_DONTEXPAND;
-       vma->vm_private_data = sbuf;
-       vma->vm_ops = &cafe_v4l_vm_ops;
-       sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED;
-       cafe_v4l_vm_open(vma);
-       ret = 0;
-  out:
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-
-
-static int cafe_v4l_open(struct file *filp)
-{
-       struct cafe_camera *cam = video_drvdata(filp);
-
-       filp->private_data = cam;
-
-       mutex_lock(&cam->s_mutex);
-       if (cam->users == 0) {
-               cafe_ctlr_power_up(cam);
-               __cafe_cam_reset(cam);
-               cafe_set_config_needed(cam, 1);
-       /* FIXME make sure this is complete */
-       }
-       (cam->users)++;
-       mutex_unlock(&cam->s_mutex);
-       return 0;
-}
-
-
-static int cafe_v4l_release(struct file *filp)
-{
-       struct cafe_camera *cam = filp->private_data;
-
-       mutex_lock(&cam->s_mutex);
-       (cam->users)--;
-       if (filp == cam->owner) {
-               cafe_ctlr_stop_dma(cam);
-               cafe_free_sio_buffers(cam);
-               cam->owner = NULL;
-       }
-       if (cam->users == 0) {
-               cafe_ctlr_power_down(cam);
-               if (alloc_bufs_at_read)
-                       cafe_free_dma_bufs(cam);
-       }
-       mutex_unlock(&cam->s_mutex);
-       return 0;
-}
-
-
-
-static unsigned int cafe_v4l_poll(struct file *filp,
-               struct poll_table_struct *pt)
-{
-       struct cafe_camera *cam = filp->private_data;
-
-       poll_wait(filp, &cam->iowait, pt);
-       if (cam->next_buf >= 0)
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-
-
-static int cafe_vidioc_queryctrl(struct file *filp, void *priv,
-               struct v4l2_queryctrl *qc)
-{
-       struct cafe_camera *cam = priv;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, core, queryctrl, qc);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-
-static int cafe_vidioc_g_ctrl(struct file *filp, void *priv,
-               struct v4l2_control *ctrl)
-{
-       struct cafe_camera *cam = priv;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, core, g_ctrl, ctrl);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-
-static int cafe_vidioc_s_ctrl(struct file *filp, void *priv,
-               struct v4l2_control *ctrl)
-{
-       struct cafe_camera *cam = priv;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, core, s_ctrl, ctrl);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-
-
-
-
-static int cafe_vidioc_querycap(struct file *file, void *priv,
-               struct v4l2_capability *cap)
-{
-       strcpy(cap->driver, "cafe_ccic");
-       strcpy(cap->card, "cafe_ccic");
-       cap->version = CAFE_VERSION;
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
-               V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
-       return 0;
-}
-
-
-/*
- * The default format we use until somebody says otherwise.
- */
-static const struct v4l2_pix_format cafe_def_pix_format = {
-       .width          = VGA_WIDTH,
-       .height         = VGA_HEIGHT,
-       .pixelformat    = V4L2_PIX_FMT_YUYV,
-       .field          = V4L2_FIELD_NONE,
-       .bytesperline   = VGA_WIDTH*2,
-       .sizeimage      = VGA_WIDTH*VGA_HEIGHT*2,
-};
-
-static const enum v4l2_mbus_pixelcode cafe_def_mbus_code =
-                                       V4L2_MBUS_FMT_YUYV8_2X8;
-
-static int cafe_vidioc_enum_fmt_vid_cap(struct file *filp,
-               void *priv, struct v4l2_fmtdesc *fmt)
-{
-       if (fmt->index >= N_CAFE_FMTS)
-               return -EINVAL;
-       strlcpy(fmt->description, cafe_formats[fmt->index].desc,
-                       sizeof(fmt->description));
-       fmt->pixelformat = cafe_formats[fmt->index].pixelformat;
-       return 0;
-}
-
-static int cafe_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
-               struct v4l2_format *fmt)
-{
-       struct cafe_camera *cam = priv;
-       struct cafe_format_struct *f;
-       struct v4l2_pix_format *pix = &fmt->fmt.pix;
-       struct v4l2_mbus_framefmt mbus_fmt;
-       int ret;
-
-       f = cafe_find_format(pix->pixelformat);
-       pix->pixelformat = f->pixelformat;
-       v4l2_fill_mbus_format(&mbus_fmt, pix, f->mbus_code);
-       mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
-       mutex_unlock(&cam->s_mutex);
-       v4l2_fill_pix_format(pix, &mbus_fmt);
-       pix->bytesperline = pix->width * f->bpp;
-       pix->sizeimage = pix->height * pix->bytesperline;
-       return ret;
-}
-
-static int cafe_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
-               struct v4l2_format *fmt)
-{
-       struct cafe_camera *cam = priv;
-       struct cafe_format_struct *f;
-       int ret;
-
-       /*
-        * Can't do anything if the device is not idle
-        * Also can't if there are streaming buffers in place.
-        */
-       if (cam->state != S_IDLE || cam->n_sbufs > 0)
-               return -EBUSY;
-
-       f = cafe_find_format(fmt->fmt.pix.pixelformat);
-
-       /*
-        * See if the formatting works in principle.
-        */
-       ret = cafe_vidioc_try_fmt_vid_cap(filp, priv, fmt);
-       if (ret)
-               return ret;
-       /*
-        * Now we start to change things for real, so let's do it
-        * under lock.
-        */
-       mutex_lock(&cam->s_mutex);
-       cam->pix_format = fmt->fmt.pix;
-       cam->mbus_code = f->mbus_code;
-
-       /*
-        * Make sure we have appropriate DMA buffers.
-        */
-       ret = -ENOMEM;
-       if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage)
-               cafe_free_dma_bufs(cam);
-       if (cam->nbufs == 0) {
-               if (cafe_alloc_dma_bufs(cam, 0))
-                       goto out;
-       }
-       /*
-        * It looks like this might work, so let's program the sensor.
-        */
-       ret = cafe_cam_configure(cam);
-       if (! ret)
-               ret = cafe_ctlr_configure(cam);
-  out:
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-/*
- * Return our stored notion of how the camera is/should be configured.
- * The V4l2 spec wants us to be smarter, and actually get this from
- * the camera (and not mess with it at open time).  Someday.
- */
-static int cafe_vidioc_g_fmt_vid_cap(struct file *filp, void *priv,
-               struct v4l2_format *f)
-{
-       struct cafe_camera *cam = priv;
-
-       f->fmt.pix = cam->pix_format;
-       return 0;
-}
-
-/*
- * We only have one input - the sensor - so minimize the nonsense here.
- */
-static int cafe_vidioc_enum_input(struct file *filp, void *priv,
-               struct v4l2_input *input)
-{
-       if (input->index != 0)
-               return -EINVAL;
-
-       input->type = V4L2_INPUT_TYPE_CAMERA;
-       input->std = V4L2_STD_ALL; /* Not sure what should go here */
-       strcpy(input->name, "Camera");
-       return 0;
-}
-
-static int cafe_vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-
-static int cafe_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
-       if (i != 0)
-               return -EINVAL;
-       return 0;
-}
-
-/* from vivi.c */
-static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
-{
-       return 0;
-}
-
-/*
- * G/S_PARM.  Most of this is done by the sensor, but we are
- * the level which controls the number of read buffers.
- */
-static int cafe_vidioc_g_parm(struct file *filp, void *priv,
-               struct v4l2_streamparm *parms)
-{
-       struct cafe_camera *cam = priv;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, video, g_parm, parms);
-       mutex_unlock(&cam->s_mutex);
-       parms->parm.capture.readbuffers = n_dma_bufs;
-       return ret;
-}
-
-static int cafe_vidioc_s_parm(struct file *filp, void *priv,
-               struct v4l2_streamparm *parms)
-{
-       struct cafe_camera *cam = priv;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, video, s_parm, parms);
-       mutex_unlock(&cam->s_mutex);
-       parms->parm.capture.readbuffers = n_dma_bufs;
-       return ret;
-}
-
-static int cafe_vidioc_g_chip_ident(struct file *file, void *priv,
-               struct v4l2_dbg_chip_ident *chip)
-{
-       struct cafe_camera *cam = priv;
-
-       chip->ident = V4L2_IDENT_NONE;
-       chip->revision = 0;
-       if (v4l2_chip_match_host(&chip->match)) {
-               chip->ident = V4L2_IDENT_CAFE;
-               return 0;
-       }
-       return sensor_call(cam, core, g_chip_ident, chip);
-}
-
-static int cafe_vidioc_enum_framesizes(struct file *filp, void *priv,
-               struct v4l2_frmsizeenum *sizes)
-{
-       struct cafe_camera *cam = priv;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, video, enum_framesizes, sizes);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-static int cafe_vidioc_enum_frameintervals(struct file *filp, void *priv,
-               struct v4l2_frmivalenum *interval)
-{
-       struct cafe_camera *cam = priv;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, video, enum_frameintervals, interval);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int cafe_vidioc_g_register(struct file *file, void *priv,
-               struct v4l2_dbg_register *reg)
-{
-       struct cafe_camera *cam = priv;
-
-       if (v4l2_chip_match_host(&reg->match)) {
-               reg->val = cafe_reg_read(cam, reg->reg);
-               reg->size = 4;
-               return 0;
-       }
-       return sensor_call(cam, core, g_register, reg);
-}
-
-static int cafe_vidioc_s_register(struct file *file, void *priv,
-               struct v4l2_dbg_register *reg)
-{
-       struct cafe_camera *cam = priv;
-
-       if (v4l2_chip_match_host(&reg->match)) {
-               cafe_reg_write(cam, reg->reg, reg->val);
-               return 0;
-       }
-       return sensor_call(cam, core, s_register, reg);
-}
-#endif
-
-/*
- * This template device holds all of those v4l2 methods; we
- * clone it for specific real devices.
- */
-
-static const struct v4l2_file_operations cafe_v4l_fops = {
-       .owner = THIS_MODULE,
-       .open = cafe_v4l_open,
-       .release = cafe_v4l_release,
-       .read = cafe_v4l_read,
-       .poll = cafe_v4l_poll,
-       .mmap = cafe_v4l_mmap,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = {
-       .vidioc_querycap        = cafe_vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap = cafe_vidioc_enum_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap = cafe_vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap   = cafe_vidioc_s_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap   = cafe_vidioc_g_fmt_vid_cap,
-       .vidioc_enum_input      = cafe_vidioc_enum_input,
-       .vidioc_g_input         = cafe_vidioc_g_input,
-       .vidioc_s_input         = cafe_vidioc_s_input,
-       .vidioc_s_std           = cafe_vidioc_s_std,
-       .vidioc_reqbufs         = cafe_vidioc_reqbufs,
-       .vidioc_querybuf        = cafe_vidioc_querybuf,
-       .vidioc_qbuf            = cafe_vidioc_qbuf,
-       .vidioc_dqbuf           = cafe_vidioc_dqbuf,
-       .vidioc_streamon        = cafe_vidioc_streamon,
-       .vidioc_streamoff       = cafe_vidioc_streamoff,
-       .vidioc_queryctrl       = cafe_vidioc_queryctrl,
-       .vidioc_g_ctrl          = cafe_vidioc_g_ctrl,
-       .vidioc_s_ctrl          = cafe_vidioc_s_ctrl,
-       .vidioc_g_parm          = cafe_vidioc_g_parm,
-       .vidioc_s_parm          = cafe_vidioc_s_parm,
-       .vidioc_enum_framesizes = cafe_vidioc_enum_framesizes,
-       .vidioc_enum_frameintervals = cafe_vidioc_enum_frameintervals,
-       .vidioc_g_chip_ident    = cafe_vidioc_g_chip_ident,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register      = cafe_vidioc_g_register,
-       .vidioc_s_register      = cafe_vidioc_s_register,
-#endif
-};
-
-static struct video_device cafe_v4l_template = {
-       .name = "cafe",
-       .tvnorms = V4L2_STD_NTSC_M,
-       .current_norm = V4L2_STD_NTSC_M,  /* make mplayer happy */
-
-       .fops = &cafe_v4l_fops,
-       .ioctl_ops = &cafe_v4l_ioctl_ops,
-       .release = video_device_release_empty,
-};
-
-
-/* ---------------------------------------------------------------------- */
-/*
- * Interrupt handler stuff
- */
-
-
-
-static void cafe_frame_tasklet(unsigned long data)
-{
-       struct cafe_camera *cam = (struct cafe_camera *) data;
-       int i;
-       unsigned long flags;
-       struct cafe_sio_buffer *sbuf;
-
-       spin_lock_irqsave(&cam->dev_lock, flags);
-       for (i = 0; i < cam->nbufs; i++) {
-               int bufno = cam->next_buf;
-               if (bufno < 0) {  /* "will never happen" */
-                       cam_err(cam, "No valid bufs in tasklet!\n");
-                       break;
-               }
-               if (++(cam->next_buf) >= cam->nbufs)
-                       cam->next_buf = 0;
-               if (! test_bit(bufno, &cam->flags))
-                       continue;
-               if (list_empty(&cam->sb_avail))
-                       break;  /* Leave it valid, hope for better later */
-               clear_bit(bufno, &cam->flags);
-               sbuf = list_entry(cam->sb_avail.next,
-                               struct cafe_sio_buffer, list);
-               /*
-                * Drop the lock during the big copy.  This *should* be safe...
-                */
-               spin_unlock_irqrestore(&cam->dev_lock, flags);
-               memcpy(sbuf->buffer, cam->dma_bufs[bufno],
-                               cam->pix_format.sizeimage);
-               sbuf->v4lbuf.bytesused = cam->pix_format.sizeimage;
-               sbuf->v4lbuf.sequence = cam->buf_seq[bufno];
-               sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;
-               sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE;
-               spin_lock_irqsave(&cam->dev_lock, flags);
-               list_move_tail(&sbuf->list, &cam->sb_full);
-       }
-       if (! list_empty(&cam->sb_full))
-               wake_up(&cam->iowait);
-       spin_unlock_irqrestore(&cam->dev_lock, flags);
-}
-
-
-
-static void cafe_frame_complete(struct cafe_camera *cam, int frame)
-{
-       /*
-        * Basic frame housekeeping.
-        */
-       if (test_bit(frame, &cam->flags) && printk_ratelimit())
-               cam_err(cam, "Frame overrun on %d, frames lost\n", frame);
-       set_bit(frame, &cam->flags);
-       clear_bit(CF_DMA_ACTIVE, &cam->flags);
-       if (cam->next_buf < 0)
-               cam->next_buf = frame;
-       cam->buf_seq[frame] = ++(cam->sequence);
-
-       switch (cam->state) {
-       /*
-        * If in single read mode, try going speculative.
-        */
-           case S_SINGLEREAD:
-               cam->state = S_SPECREAD;
-               cam->specframes = 0;
-               wake_up(&cam->iowait);
-               break;
-
-       /*
-        * If we are already doing speculative reads, and nobody is
-        * reading them, just stop.
-        */
-           case S_SPECREAD:
-               if (++(cam->specframes) >= cam->nbufs) {
-                       cafe_ctlr_stop(cam);
-                       cafe_ctlr_irq_disable(cam);
-                       cam->state = S_IDLE;
-               }
-               wake_up(&cam->iowait);
-               break;
-       /*
-        * For the streaming case, we defer the real work to the
-        * camera tasklet.
-        *
-        * FIXME: if the application is not consuming the buffers,
-        * we should eventually put things on hold and restart in
-        * vidioc_dqbuf().
-        */
-           case S_STREAMING:
-               tasklet_schedule(&cam->s_tasklet);
-               break;
-
-           default:
-               cam_err(cam, "Frame interrupt in non-operational state\n");
-               break;
-       }
-}
-
-
-
-
-static void cafe_frame_irq(struct cafe_camera *cam, unsigned int irqs)
-{
-       unsigned int frame;
-
-       cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); /* Clear'em all */
-       /*
-        * Handle any frame completions.  There really should
-        * not be more than one of these, or we have fallen
-        * far behind.
-        */
-       for (frame = 0; frame < cam->nbufs; frame++)
-               if (irqs & (IRQ_EOF0 << frame))
-                       cafe_frame_complete(cam, frame);
-       /*
-        * If a frame starts, note that we have DMA active.  This
-        * code assumes that we won't get multiple frame interrupts
-        * at once; may want to rethink that.
-        */
-       if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2))
-               set_bit(CF_DMA_ACTIVE, &cam->flags);
-}
-
-
-
-static irqreturn_t cafe_irq(int irq, void *data)
-{
-       struct cafe_camera *cam = data;
-       unsigned int irqs;
-
-       spin_lock(&cam->dev_lock);
-       irqs = cafe_reg_read(cam, REG_IRQSTAT);
-       if ((irqs & ALLIRQS) == 0) {
-               spin_unlock(&cam->dev_lock);
-               return IRQ_NONE;
-       }
-       if (irqs & FRAMEIRQS)
-               cafe_frame_irq(cam, irqs);
-       if (irqs & TWSIIRQS) {
-               cafe_reg_write(cam, REG_IRQSTAT, TWSIIRQS);
-               wake_up(&cam->smbus_wait);
-       }
-       spin_unlock(&cam->dev_lock);
-       return IRQ_HANDLED;
-}
-
-
-/* -------------------------------------------------------------------------- */
-/*
- * PCI interface stuff.
- */
-
-static const struct dmi_system_id olpc_xo1_dmi[] = {
-       {
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "OLPC"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "XO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "1"),
-               },
-       },
-       { }
-};
-
-static int cafe_pci_probe(struct pci_dev *pdev,
-               const struct pci_device_id *id)
-{
-       int ret;
-       struct cafe_camera *cam;
-       struct ov7670_config sensor_cfg = {
-               /* This controller only does SMBUS */
-               .use_smbus = true,
-
-               /*
-                * Exclude QCIF mode, because it only captures a tiny portion
-                * of the sensor FOV
-                */
-               .min_width = 320,
-               .min_height = 240,
-       };
-       struct i2c_board_info ov7670_info = {
-               .type = "ov7670",
-               .addr = 0x42,
-               .platform_data = &sensor_cfg,
-       };
-
-       /*
-        * Start putting together one of our big camera structures.
-        */
-       ret = -ENOMEM;
-       cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL);
-       if (cam == NULL)
-               goto out;
-       ret = v4l2_device_register(&pdev->dev, &cam->v4l2_dev);
-       if (ret)
-               goto out_free;
-
-       mutex_init(&cam->s_mutex);
-       spin_lock_init(&cam->dev_lock);
-       cam->state = S_NOTREADY;
-       cafe_set_config_needed(cam, 1);
-       init_waitqueue_head(&cam->smbus_wait);
-       init_waitqueue_head(&cam->iowait);
-       cam->pdev = pdev;
-       cam->pix_format = cafe_def_pix_format;
-       cam->mbus_code = cafe_def_mbus_code;
-       INIT_LIST_HEAD(&cam->dev_list);
-       INIT_LIST_HEAD(&cam->sb_avail);
-       INIT_LIST_HEAD(&cam->sb_full);
-       tasklet_init(&cam->s_tasklet, cafe_frame_tasklet, (unsigned long) cam);
-       /*
-        * Get set up on the PCI bus.
-        */
-       ret = pci_enable_device(pdev);
-       if (ret)
-               goto out_unreg;
-       pci_set_master(pdev);
-
-       ret = -EIO;
-       cam->regs = pci_iomap(pdev, 0, 0);
-       if (! cam->regs) {
-               printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n");
-               goto out_unreg;
-       }
-       ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam);
-       if (ret)
-               goto out_iounmap;
-       /*
-        * Initialize the controller and leave it powered up.  It will
-        * stay that way until the sensor driver shows up.
-        */
-       cafe_ctlr_init(cam);
-       cafe_ctlr_power_up(cam);
-       /*
-        * Set up I2C/SMBUS communications.  We have to drop the mutex here
-        * because the sensor could attach in this call chain, leading to
-        * unsightly deadlocks.
-        */
-       ret = cafe_smbus_setup(cam);
-       if (ret)
-               goto out_freeirq;
-
-       /* Apply XO-1 clock speed */
-       if (dmi_check_system(olpc_xo1_dmi))
-               sensor_cfg.clock_speed = 45;
-
-       cam->sensor_addr = ov7670_info.addr;
-       cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev, &cam->i2c_adapter,
-                       &ov7670_info, NULL);
-       if (cam->sensor == NULL) {
-               ret = -ENODEV;
-               goto out_smbus;
-       }
-
-       ret = cafe_cam_init(cam);
-       if (ret)
-               goto out_smbus;
-
-       /*
-        * Get the v4l2 setup done.
-        */
-       mutex_lock(&cam->s_mutex);
-       cam->vdev = cafe_v4l_template;
-       cam->vdev.debug = 0;
-/*     cam->vdev.debug = V4L2_DEBUG_IOCTL_ARG;*/
-       cam->vdev.v4l2_dev = &cam->v4l2_dev;
-       ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
-       if (ret)
-               goto out_unlock;
-       video_set_drvdata(&cam->vdev, cam);
-
-       /*
-        * If so requested, try to get our DMA buffers now.
-        */
-       if (!alloc_bufs_at_read) {
-               if (cafe_alloc_dma_bufs(cam, 1))
-                       cam_warn(cam, "Unable to alloc DMA buffers at load"
-                                       " will try again later.");
-       }
-
-       mutex_unlock(&cam->s_mutex);
-       return 0;
-
-out_unlock:
-       mutex_unlock(&cam->s_mutex);
-out_smbus:
-       cafe_smbus_shutdown(cam);
-out_freeirq:
-       cafe_ctlr_power_down(cam);
-       free_irq(pdev->irq, cam);
-out_iounmap:
-       pci_iounmap(pdev, cam->regs);
-out_free:
-       v4l2_device_unregister(&cam->v4l2_dev);
-out_unreg:
-       kfree(cam);
-out:
-       return ret;
-}
-
-
-/*
- * Shut down an initialized device
- */
-static void cafe_shutdown(struct cafe_camera *cam)
-{
-/* FIXME: Make sure we take care of everything here */
-       if (cam->n_sbufs > 0)
-               /* What if they are still mapped?  Shouldn't be, but... */
-               cafe_free_sio_buffers(cam);
-       cafe_ctlr_stop_dma(cam);
-       cafe_ctlr_power_down(cam);
-       cafe_smbus_shutdown(cam);
-       cafe_free_dma_bufs(cam);
-       free_irq(cam->pdev->irq, cam);
-       pci_iounmap(cam->pdev, cam->regs);
-       video_unregister_device(&cam->vdev);
-}
-
-
-static void cafe_pci_remove(struct pci_dev *pdev)
-{
-       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
-       struct cafe_camera *cam = to_cam(v4l2_dev);
-
-       if (cam == NULL) {
-               printk(KERN_WARNING "pci_remove on unknown pdev %p\n", pdev);
-               return;
-       }
-       mutex_lock(&cam->s_mutex);
-       if (cam->users > 0)
-               cam_warn(cam, "Removing a device with users!\n");
-       cafe_shutdown(cam);
-       v4l2_device_unregister(&cam->v4l2_dev);
-       kfree(cam);
-/* No unlock - it no longer exists */
-}
-
-
-#ifdef CONFIG_PM
-/*
- * Basic power management.
- */
-static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
-       struct cafe_camera *cam = to_cam(v4l2_dev);
-       int ret;
-       enum cafe_state cstate;
-
-       ret = pci_save_state(pdev);
-       if (ret)
-               return ret;
-       cstate = cam->state; /* HACK - stop_dma sets to idle */
-       cafe_ctlr_stop_dma(cam);
-       cafe_ctlr_power_down(cam);
-       pci_disable_device(pdev);
-       cam->state = cstate;
-       return 0;
-}
-
-
-static int cafe_pci_resume(struct pci_dev *pdev)
-{
-       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
-       struct cafe_camera *cam = to_cam(v4l2_dev);
-       int ret = 0;
-
-       pci_restore_state(pdev);
-       ret = pci_enable_device(pdev);
-
-       if (ret) {
-               cam_warn(cam, "Unable to re-enable device on resume!\n");
-               return ret;
-       }
-       cafe_ctlr_init(cam);
-
-       mutex_lock(&cam->s_mutex);
-       if (cam->users > 0) {
-               cafe_ctlr_power_up(cam);
-               __cafe_cam_reset(cam);
-       } else {
-               cafe_ctlr_power_down(cam);
-       }
-       mutex_unlock(&cam->s_mutex);
-
-       set_bit(CF_CONFIG_NEEDED, &cam->flags);
-       if (cam->state == S_SPECREAD)
-               cam->state = S_IDLE;  /* Don't bother restarting */
-       else if (cam->state == S_SINGLEREAD || cam->state == S_STREAMING)
-               ret = cafe_read_setup(cam, cam->state);
-       return ret;
-}
-
-#endif  /* CONFIG_PM */
-
-
-static struct pci_device_id cafe_ids[] = {
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL,
-                    PCI_DEVICE_ID_MARVELL_88ALP01_CCIC) },
-       { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, cafe_ids);
-
-static struct pci_driver cafe_pci_driver = {
-       .name = "cafe1000-ccic",
-       .id_table = cafe_ids,
-       .probe = cafe_pci_probe,
-       .remove = cafe_pci_remove,
-#ifdef CONFIG_PM
-       .suspend = cafe_pci_suspend,
-       .resume = cafe_pci_resume,
-#endif
-};
-
-
-
-
-static int __init cafe_init(void)
-{
-       int ret;
-
-       printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n",
-                       CAFE_VERSION);
-       ret = pci_register_driver(&cafe_pci_driver);
-       if (ret) {
-               printk(KERN_ERR "Unable to register cafe_ccic driver\n");
-               goto out;
-       }
-       ret = 0;
-
-  out:
-       return ret;
-}
-
-
-static void __exit cafe_exit(void)
-{
-       pci_unregister_driver(&cafe_pci_driver);
-}
-
-module_init(cafe_init);
-module_exit(cafe_exit);
index 6d6d184..ab25218 100644 (file)
@@ -31,7 +31,6 @@
 #ifndef __CPIA2_H__
 #define __CPIA2_H__
 
-#include <linux/version.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <linux/usb.h>
 /* define for verbose debug output */
 //#define _CPIA2_DEBUG_
 
-#define CPIA2_MAJ_VER  3
-#define CPIA2_MIN_VER   0
-#define CPIA2_PATCH_VER        0
-
 /***
  * Image defines
  ***/
index 40eb632..077eb1d 100644 (file)
@@ -29,8 +29,7 @@
  *             Alan Cox <alan@lxorguk.ukuu.org.uk>
  ****************************************************************************/
 
-#include <linux/version.h>
-
+#define CPIA_VERSION "3.0.1"
 
 #include <linux/module.h>
 #include <linux/time.h>
@@ -80,6 +79,7 @@ MODULE_AUTHOR("Steve Miller (STMicroelectronics) <steve.miller@st.com>");
 MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras");
 MODULE_SUPPORTED_DEVICE("video");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(CPIA_VERSION);
 
 #define ABOUT "V4L-Driver for Vision CPiA2 based cameras"
 
@@ -465,9 +465,6 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v
        if (usb_make_path(cam->dev, vc->bus_info, sizeof(vc->bus_info)) <0)
                memset(vc->bus_info,0, sizeof(vc->bus_info));
 
-       vc->version = KERNEL_VERSION(CPIA2_MAJ_VER, CPIA2_MIN_VER,
-                                    CPIA2_PATCH_VER);
-
        vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
                           V4L2_CAP_READWRITE |
                           V4L2_CAP_STREAMING;
@@ -1558,8 +1555,8 @@ static void __init check_parameters(void)
  *****************************************************************************/
 static int __init cpia2_init(void)
 {
-       LOG("%s v%d.%d.%d\n",
-           ABOUT, CPIA2_MAJ_VER, CPIA2_MIN_VER, CPIA2_PATCH_VER);
+       LOG("%s v%s\n",
+           ABOUT, CPIA_VERSION);
        check_parameters();
        cpia2_usb_init();
        return 0;
@@ -1579,4 +1576,3 @@ static void __exit cpia2_exit(void)
 
 module_init(cpia2_init);
 module_exit(cpia2_exit);
-
index d50d69d..a1e6c2a 100644 (file)
@@ -192,6 +192,7 @@ static int snd_cx18_init(struct v4l2_device *v4l2_dev)
 err_exit_free:
        if (sc != NULL)
                snd_card_free(sc);
+       kfree(cxsc);
 err_exit:
        return ret;
 }
index 0864272..1834207 100644 (file)
@@ -25,7 +25,6 @@
 #ifndef CX18_DRIVER_H
 #define CX18_DRIVER_H
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
index e80134f..afe0a29 100644 (file)
@@ -469,7 +469,6 @@ static int cx18_querycap(struct file *file, void *fh,
        strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
        snprintf(vcap->bus_info, sizeof(vcap->bus_info),
                 "PCI:%s", pci_name(cx->pci_dev));
-       vcap->version = CX18_DRIVER_VERSION;        /* version */
        vcap->capabilities = cx->v4l2_cap;          /* capabilities */
        return 0;
 }
index cd189b6..fed48b6 100644 (file)
 #define CX18_VERSION_H
 
 #define CX18_DRIVER_NAME "cx18"
-#define CX18_DRIVER_VERSION_MAJOR 1
-#define CX18_DRIVER_VERSION_MINOR 5
-#define CX18_DRIVER_VERSION_PATCHLEVEL 0
-
-#define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
-#define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \
-       CX18_DRIVER_VERSION_MINOR, CX18_DRIVER_VERSION_PATCHLEVEL)
+#define CX18_VERSION "1.5.1"
 
 #endif
index 8d78134..53ff26e 100644 (file)
@@ -355,6 +355,8 @@ int cx231xx_afe_update_power_control(struct cx231xx *dev,
        case CX231XX_BOARD_HAUPPAUGE_EXETER:
        case CX231XX_BOARD_HAUPPAUGE_USBLIVE2:
        case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
+       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
+       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
                if (avmode == POLARIS_AVMODE_ANALOGT_TV) {
                        while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
                                                FLD_PWRDN_ENABLE_PLL)) {
@@ -1733,6 +1735,8 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard)
                break;
        case CX231XX_BOARD_CNXT_RDE_253S:
        case CX231XX_BOARD_CNXT_RDU_253S:
+       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
+       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
                func_mode = 0x01;
                break;
        default:
index 2270381..53dae2a 100644 (file)
@@ -387,6 +387,7 @@ struct cx231xx_board cx231xx_boards[] = {
                .norm = V4L2_STD_NTSC,
                .no_alt_vanc = 1,
                .external_av = 1,
+               .dont_use_port_3 = 1,
                .input = {{
                        .type = CX231XX_VMUX_COMPOSITE1,
                        .vmux = CX231XX_VIN_2_1,
@@ -532,6 +533,76 @@ struct cx231xx_board cx231xx_boards[] = {
                        .gpio = NULL,
                } },
        },
+       [CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL] = {
+               .name = "Hauppauge WinTV USB2 FM (PAL)",
+               .tuner_type = TUNER_NXP_TDA18271,
+               .tuner_addr = 0x60,
+               .tuner_gpio = RDE250_XCV_TUNER,
+               .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+               .tuner_sda_gpio = 0x1b,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x0c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 1,
+               .norm = V4L2_STD_PAL,
+
+               .input = {{
+                       .type = CX231XX_VMUX_TELEVISION,
+                       .vmux = CX231XX_VIN_3_1,
+                       .amux = CX231XX_AMUX_VIDEO,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               } },
+       },
+       [CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC] = {
+               .name = "Hauppauge WinTV USB2 FM (NTSC)",
+               .tuner_type = TUNER_NXP_TDA18271,
+               .tuner_addr = 0x60,
+               .tuner_gpio = RDE250_XCV_TUNER,
+               .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+               .tuner_sda_gpio = 0x1b,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x0c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 1,
+               .norm = V4L2_STD_NTSC,
+
+               .input = {{
+                       .type = CX231XX_VMUX_TELEVISION,
+                       .vmux = CX231XX_VIN_3_1,
+                       .amux = CX231XX_AMUX_VIDEO,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               } },
+       },
 };
 const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
 
@@ -553,6 +624,10 @@ struct usb_device_id cx231xx_id_table[] = {
         .driver_info = CX231XX_BOARD_CNXT_RDE_250},
        {USB_DEVICE(0x0572, 0x58A0),
         .driver_info = CX231XX_BOARD_CNXT_RDU_250},
+       {USB_DEVICE(0x2040, 0xb110),
+        .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL},
+       {USB_DEVICE(0x2040, 0xb111),
+        .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC},
        {USB_DEVICE(0x2040, 0xb120),
         .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
        {USB_DEVICE(0x2040, 0xb140),
@@ -1051,6 +1126,9 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        if (assoc_desc->bFirstInterface != ifnum) {
                cx231xx_err(DRIVER_NAME ": Not found "
                            "matching IAD interface\n");
+               cx231xx_devused &= ~(1 << nr);
+               kfree(dev);
+               dev = NULL;
                return -ENODEV;
        }
 
index abe500f..d4457f9 100644 (file)
@@ -742,6 +742,8 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)
                case CX231XX_BOARD_CNXT_RDU_253S:
                case CX231XX_BOARD_HAUPPAUGE_EXETER:
                case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
+               case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
+               case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
                errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
                        break;
                default:
@@ -1381,6 +1383,8 @@ int cx231xx_dev_init(struct cx231xx *dev)
        case CX231XX_BOARD_CNXT_RDU_253S:
        case CX231XX_BOARD_HAUPPAUGE_EXETER:
        case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
+       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
+       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
        errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
                break;
        default:
index a69c24d..6e81f97 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/bitmap.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
-#include <linux/version.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
@@ -45,7 +44,7 @@
 #include "cx231xx.h"
 #include "cx231xx-vbi.h"
 
-#define CX231XX_VERSION_CODE            KERNEL_VERSION(0, 0, 1)
+#define CX231XX_VERSION "0.0.2"
 
 #define DRIVER_AUTHOR   "Srinivasa Deevi <srinivasa.deevi@conexant.com>"
 #define DRIVER_DESC     "Conexant cx231xx based USB video device driver"
@@ -70,6 +69,7 @@ do {\
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(CX231XX_VERSION);
 
 static unsigned int card[]     = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
 static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
@@ -1179,7 +1179,8 @@ static int vidioc_enum_input(struct file *file, void *priv,
 {
        struct cx231xx_fh *fh = priv;
        struct cx231xx *dev = fh->dev;
-       unsigned int n;
+       u32 gen_stat;
+       unsigned int ret, n;
 
        n = i->index;
        if (n >= MAX_CX231XX_INPUT)
@@ -1198,6 +1199,18 @@ static int vidioc_enum_input(struct file *file, void *priv,
 
        i->std = dev->vdev->tvnorms;
 
+       /* If they are asking about the active input, read signal status */
+       if (n == dev->video_input) {
+               ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+                                           GEN_STAT, 2, &gen_stat, 4);
+               if (ret > 0) {
+                       if ((gen_stat & FLD_VPRES) == 0x00)
+                               i->status |= V4L2_IN_ST_NO_SIGNAL;
+                       if ((gen_stat & FLD_HLOCK) == 0x00)
+                               i->status |= V4L2_IN_ST_NO_H_LOCK;
+               }
+       }
+
        return 0;
 }
 
@@ -1869,8 +1882,6 @@ static int vidioc_querycap(struct file *file, void *priv,
        strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
        usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
 
-       cap->version = CX231XX_VERSION_CODE;
-
        cap->capabilities = V4L2_CAP_VBI_CAPTURE |
 #if 0
                V4L2_CAP_SLICED_VBI_CAPTURE |
@@ -2057,7 +2068,6 @@ static int radio_querycap(struct file *file, void *priv,
        strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
        usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
 
-       cap->version = CX231XX_VERSION_CODE;
        cap->capabilities = V4L2_CAP_TUNER;
        return 0;
 }
@@ -2570,11 +2580,8 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
 {
        int ret;
 
-       cx231xx_info("%s: v4l2 driver version %d.%d.%d\n",
-                    dev->name,
-                    (CX231XX_VERSION_CODE >> 16) & 0xff,
-                    (CX231XX_VERSION_CODE >> 8) & 0xff,
-                    CX231XX_VERSION_CODE & 0xff);
+       cx231xx_info("%s: v4l2 driver version %s\n",
+                    dev->name, CX231XX_VERSION);
 
        /* set default norm */
        /*dev->norm = cx231xx_video_template.current_norm; */
index 46dd840..2000bc6 100644 (file)
@@ -43,7 +43,7 @@
 #include "cx231xx-conf-reg.h"
 
 #define DRIVER_NAME                     "cx231xx"
-#define PWR_SLEEP_INTERVAL              5
+#define PWR_SLEEP_INTERVAL              10
 
 /* I2C addresses for control block in Cx231xx */
 #define     AFE_DEVICE_ADDRESS         0x60
@@ -67,6 +67,8 @@
 #define CX231XX_BOARD_PV_XCAPTURE_USB 11
 #define CX231XX_BOARD_KWORLD_UB430_USB_HYBRID 12
 #define CX231XX_BOARD_ICONBIT_U100 13
+#define CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL 14
+#define CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC 15
 
 /* Limits minimum and default number of buffers */
 #define CX231XX_MIN_BUF                 4
        V4L2_STD_PAL_BG |  V4L2_STD_PAL_DK    |  V4L2_STD_PAL_I    | \
        V4L2_STD_PAL_M  |  V4L2_STD_PAL_N     |  V4L2_STD_PAL_Nc   | \
        V4L2_STD_PAL_60 |  V4L2_STD_SECAM_L   |  V4L2_STD_SECAM_DK)
-#define CX231xx_VERSION_CODE KERNEL_VERSION(0, 0, 2)
 
 #define SLEEP_S5H1432    30
 #define CX23417_OSC_EN   8
index 678539b..1fa8927 100644 (file)
@@ -52,7 +52,6 @@
  * |  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|
  * +-------+-------+-------+-------+-------+-------+-------+-------+
  */
-#include <linux/version.h>
 #include <media/videobuf-dma-sg.h>
 #include <media/videobuf-dvb.h>
 #include "altera-ci.h"
index 9a98dc5..67c4a59 100644 (file)
@@ -1359,7 +1359,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
                sizeof(cap->card));
        sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-       cap->version = CX23885_VERSION_CODE;
        cap->capabilities =
                V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_READWRITE     |
index 934185c..76b7563 100644 (file)
 #include "../../../staging/altera-stapl/altera.h"
 #include "cx23885.h"
 #include "tuner-xc2028.h"
+#include "netup-eeprom.h"
 #include "netup-init.h"
 #include "altera-ci.h"
+#include "xc4000.h"
 #include "xc5000.h"
 #include "cx23888-ir.h"
 
+static unsigned int netup_card_rev = 1;
+module_param(netup_card_rev, int, 0644);
+MODULE_PARM_DESC(netup_card_rev,
+               "NetUP Dual DVB-T/C CI card revision");
 static unsigned int enable_885_ir;
 module_param(enable_885_ir, int, 0644);
 MODULE_PARM_DESC(enable_885_ir,
@@ -175,6 +181,34 @@ struct cx23885_board cx23885_boards[] = {
                .name           = "Leadtek Winfast PxDVR3200 H",
                .portc          = CX23885_MPEG_DVB,
        },
+       [CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000] = {
+               .name           = "Leadtek Winfast PxDVR3200 H XC4000",
+               .porta          = CX23885_ANALOG_VIDEO,
+               .portc          = CX23885_MPEG_DVB,
+               .tuner_type     = TUNER_XC4000,
+               .tuner_addr     = 0x61,
+               .radio_type     = TUNER_XC4000,
+               .radio_addr     = 0x61,
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   = CX25840_VIN2_CH1 |
+                                 CX25840_VIN5_CH2 |
+                                 CX25840_NONE0_CH3,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   = CX25840_COMPOSITE1,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   = CX25840_SVIDEO_LUMA3 |
+                                 CX25840_SVIDEO_CHROMA4,
+               }, {
+                       .type   = CX23885_VMUX_COMPONENT,
+                       .vmux   = CX25840_VIN7_CH1 |
+                                 CX25840_VIN6_CH2 |
+                                 CX25840_VIN8_CH3 |
+                                 CX25840_COMPONENT_ON,
+               } },
+       },
        [CX23885_BOARD_COMPRO_VIDEOMATE_E650F] = {
                .name           = "Compro VideoMate E650F",
                .portc          = CX23885_MPEG_DVB,
@@ -432,6 +466,10 @@ struct cx23885_subid cx23885_subids[] = {
                .subvendor = 0x107d,
                .subdevice = 0x6681,
                .card      = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H,
+       }, {
+               .subvendor = 0x107d,
+               .subdevice = 0x6f39,
+               .card      = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000,
        }, {
                .subvendor = 0x185b,
                .subdevice = 0xe800,
@@ -749,6 +787,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
        case CX23885_BOARD_HAUPPAUGE_HVR1500:
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
        case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
        case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
        case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
        case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
@@ -909,6 +948,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
                cx_set(GP0_IO, 0x000f000f);
                break;
        case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
        case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
        case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
        case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
@@ -1097,12 +1137,19 @@ int cx23885_ir_init(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1800:
        case CX23885_BOARD_HAUPPAUGE_HVR1200:
        case CX23885_BOARD_HAUPPAUGE_HVR1400:
-       case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1275:
        case CX23885_BOARD_HAUPPAUGE_HVR1255:
        case CX23885_BOARD_HAUPPAUGE_HVR1210:
                /* FIXME: Implement me */
                break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
+               ret = cx23888_ir_probe(dev);
+               if (ret)
+                       break;
+               dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
+               v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
+                                ir_rx_pin_cfg_count, ir_rx_pin_cfg);
+               break;
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
                ret = cx23888_ir_probe(dev);
@@ -1156,6 +1203,7 @@ int cx23885_ir_init(struct cx23885_dev *dev)
 void cx23885_ir_fini(struct cx23885_dev *dev)
 {
        switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
                cx23885_irq_remove(dev, PCI_MSK_IR);
@@ -1199,6 +1247,7 @@ int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
 void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
 {
        switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
                if (dev->sd_ir)
@@ -1325,6 +1374,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1700:
        case CX23885_BOARD_HAUPPAUGE_HVR1400:
        case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
        case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
        case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1275:
@@ -1353,10 +1403,12 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
        case CX23885_BOARD_HAUPPAUGE_HVR1700:
        case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
        case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
        case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
        case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
        case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_MYGICA_X8506:
        case CX23885_BOARD_MAGICPRO_PROHDTVE2:
@@ -1383,6 +1435,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
                const struct firmware *fw;
                const char *filename = "dvb-netup-altera-01.fw";
                char *action = "configure";
+               static struct netup_card_info cinfo;
                struct altera_config netup_config = {
                        .dev = dev,
                        .action = action,
@@ -1391,6 +1444,21 @@ void cx23885_card_setup(struct cx23885_dev *dev)
 
                netup_initialize(dev);
 
+               netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
+               if (netup_card_rev)
+                       cinfo.rev = netup_card_rev;
+
+               switch (cinfo.rev) {
+               case 0x4:
+                       filename = "dvb-netup-altera-04.fw";
+                       break;
+               default:
+                       filename = "dvb-netup-altera-01.fw";
+                       break;
+               }
+               printk(KERN_INFO "NetUP card rev=0x%x fw_filename=%s\n",
+                               cinfo.rev, filename);
+
                ret = request_firmware(&fw, filename, &dev->pci->dev);
                if (ret != 0)
                        printk(KERN_ERR "did not find the firmware file. (%s) "
index 419777a..ee41a88 100644 (file)
@@ -42,6 +42,7 @@
 MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
 MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(CX23885_VERSION);
 
 static unsigned int debug;
 module_param(debug, int, 0644);
@@ -2147,14 +2148,8 @@ static struct pci_driver cx23885_pci_driver = {
 
 static int __init cx23885_init(void)
 {
-       printk(KERN_INFO "cx23885 driver version %d.%d.%d loaded\n",
-              (CX23885_VERSION_CODE >> 16) & 0xff,
-              (CX23885_VERSION_CODE >>  8) & 0xff,
-              CX23885_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
-       printk(KERN_INFO "cx23885: snapshot date %04d-%02d-%02d\n",
-              SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+       printk(KERN_INFO "cx23885 driver version %s loaded\n",
+               CX23885_VERSION);
        return pci_register_driver(&cx23885_pci_driver);
 }
 
@@ -2165,5 +2160,3 @@ static void __exit cx23885_fini(void)
 
 module_init(cx23885_init);
 module_exit(cx23885_fini);
-
-/* ----------------------------------------------------------- */
index 3c315f9..aa83f07 100644 (file)
@@ -37,6 +37,7 @@
 #include "tda8290.h"
 #include "tda18271.h"
 #include "lgdt330x.h"
+#include "xc4000.h"
 #include "xc5000.h"
 #include "max2165.h"
 #include "tda10048.h"
@@ -921,6 +922,26 @@ static int dvb_register(struct cx23885_tsport *port)
                                fe->ops.tuner_ops.set_config(fe, &ctl);
                }
                break;
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+               i2c_bus = &dev->i2c_bus[0];
+
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_xc3028,
+                                              &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       struct dvb_frontend     *fe;
+                       struct xc4000_config    cfg = {
+                               .i2c_address      = 0x61,
+                               .default_pm       = 0,
+                               .dvb_amplitude    = 134,
+                               .set_smoothedcvbs = 1,
+                               .if_khz           = 4560
+                       };
+
+                       fe = dvb_attach(xc4000_attach, fe0->dvb.frontend,
+                                       &dev->i2c_bus[1].i2c_adap, &cfg);
+               }
+               break;
        case CX23885_BOARD_TBS_6920:
                i2c_bus = &dev->i2c_bus[1];
 
@@ -1249,7 +1270,7 @@ int cx23885_dvb_unregister(struct cx23885_tsport *port)
         * implement MFE support.
         */
        fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
-       if (fe0->dvb.frontend)
+       if (fe0 && fe0->dvb.frontend)
                videobuf_dvb_unregister_bus(&port->frontends);
 
        switch (port->dev->board) {
index e97cafd..ce765e3 100644 (file)
@@ -82,6 +82,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
                return;
 
        switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
        case CX23885_BOARD_TEVII_S470:
@@ -133,6 +134,7 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev)
 
        v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
        switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
@@ -229,6 +231,9 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev)
                v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
                v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
        }
+       flush_work_sync(&dev->cx25840_work);
+       flush_work_sync(&dev->ir_rx_work);
+       flush_work_sync(&dev->ir_tx_work);
 }
 
 static void cx23885_input_ir_close(struct rc_dev *rc)
@@ -257,6 +262,7 @@ int cx23885_input_init(struct cx23885_dev *dev)
                return -ENODEV;
 
        switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
index ee57f6b..896bb32 100644 (file)
@@ -1000,7 +1000,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strlcpy(cap->card, cx23885_boards[dev->board].name,
                sizeof(cap->card));
        sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
-       cap->version = CX23885_VERSION_CODE;
        cap->capabilities =
                V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_READWRITE     |
index c186473..d86bc0b 100644 (file)
 #include "cx23885-reg.h"
 #include "media/cx2341x.h"
 
-#include <linux/version.h>
 #include <linux/mutex.h>
 
-#define CX23885_VERSION_CODE KERNEL_VERSION(0, 0, 2)
+#define CX23885_VERSION "0.0.3"
 
 #define UNSET (-1U)
 
@@ -86,6 +85,7 @@
 #define CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 28
 #define CX23885_BOARD_GOTVIEW_X5_3D_HYBRID     29
 #define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30
+#define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
index 423c1af..68d1240 100644 (file)
@@ -113,6 +113,8 @@ MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Ricardo Cerqueira");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
+
 MODULE_SUPPORTED_DEVICE("{{Conexant,23881},"
                        "{{Conexant,23882},"
                        "{{Conexant,23883}");
@@ -973,14 +975,8 @@ static struct pci_driver cx88_audio_pci_driver = {
  */
 static int __init cx88_audio_init(void)
 {
-       printk(KERN_INFO "cx2388x alsa driver version %d.%d.%d loaded\n",
-              (CX88_VERSION_CODE >> 16) & 0xff,
-              (CX88_VERSION_CODE >>  8) & 0xff,
-              CX88_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
-       printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
-              SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+       printk(KERN_INFO "cx2388x alsa driver version %s loaded\n",
+              CX88_VERSION);
        return pci_register_driver(&cx88_audio_pci_driver);
 }
 
@@ -994,10 +990,3 @@ static void __exit cx88_audio_fini(void)
 
 module_init(cx88_audio_init);
 module_exit(cx88_audio_fini);
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
index 11e49bb..e46446a 100644 (file)
@@ -42,6 +42,7 @@
 MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
 MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
 
 static unsigned int mpegbufs = 32;
 module_param(mpegbufs,int,0644);
@@ -730,7 +731,6 @@ static int vidioc_querycap (struct file *file, void  *priv,
        strcpy(cap->driver, "cx88_blackbird");
        strlcpy(cap->card, core->board.name, sizeof(cap->card));
        sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
-       cap->version = CX88_VERSION_CODE;
        cap->capabilities =
                V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_READWRITE     |
@@ -1368,14 +1368,8 @@ static struct cx8802_driver cx8802_blackbird_driver = {
 
 static int __init blackbird_init(void)
 {
-       printk(KERN_INFO "cx2388x blackbird driver version %d.%d.%d loaded\n",
-              (CX88_VERSION_CODE >> 16) & 0xff,
-              (CX88_VERSION_CODE >>  8) & 0xff,
-              CX88_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
-       printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
-              SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+       printk(KERN_INFO "cx2388x blackbird driver version %s loaded\n",
+              CX88_VERSION);
        return cx8802_register_driver(&cx8802_blackbird_driver);
 }
 
@@ -1389,11 +1383,3 @@ module_exit(blackbird_fini);
 
 module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
 MODULE_PARM_DESC(debug,"enable debug messages [video]");
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
index 27222c9..0d719fa 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "cx88.h"
 #include "tea5767.h"
+#include "xc4000.h"
 
 static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
 static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
@@ -2119,6 +2120,99 @@ static const struct cx88_board cx88_boards[] = {
                },
                .mpeg           = CX88_MPEG_DVB,
        },
+       [CX88_BOARD_WINFAST_DTV1800H_XC4000] = {
+               .name           = "Leadtek WinFast DTV1800 H (XC4000)",
+               .tuner_type     = TUNER_XC4000,
+               .radio_type     = TUNER_XC4000,
+               .tuner_addr     = 0x61,
+               .radio_addr     = 0x61,
+               /*
+                * GPIO setting
+                *
+                *  2: mute (0=off,1=on)
+                * 12: tuner reset pin
+                * 13: audio source (0=tuner audio,1=line in)
+                * 14: FM (0=on,1=off ???)
+                */
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6040,       /* pin 13 = 0, pin 14 = 1 */
+                       .gpio2  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
+                       .gpio2  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
+                       .gpio2  = 0x0000,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6000,       /* pin 13 = 0, pin 14 = 0 */
+                       .gpio2  = 0x0000,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_WINFAST_DTV2000H_PLUS] = {
+               .name           = "Leadtek WinFast DTV2000 H PLUS",
+               .tuner_type     = TUNER_XC4000,
+               .radio_type     = TUNER_XC4000,
+               .tuner_addr     = 0x61,
+               .radio_addr     = 0x61,
+               /*
+                * GPIO
+                *   2: 1: mute audio
+                *  12: 0: reset XC4000
+                *  13: 1: audio input is line in (0: tuner)
+                *  14: 0: FM radio
+                *  16: 0: RF input is cable
+                */
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0403,
+                       .gpio1  = 0xF0D7,
+                       .gpio2  = 0x0101,
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_CABLE,
+                       .vmux   = 0,
+                       .gpio0  = 0x0403,
+                       .gpio1  = 0xF0D7,
+                       .gpio2  = 0x0100,
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0403,       /* was 0x0407 */
+                       .gpio1  = 0xF0F7,
+                       .gpio2  = 0x0101,
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0403,       /* was 0x0407 */
+                       .gpio1  = 0xF0F7,
+                       .gpio2  = 0x0101,
+                       .gpio3  = 0x0000,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0403,
+                       .gpio1  = 0xF097,
+                       .gpio2  = 0x0100,
+                       .gpio3  = 0x0000,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
        [CX88_BOARD_PROF_7301] = {
                .name           = "Prof 7301 DVB-S/S2",
                .tuner_type     = UNSET,
@@ -2580,6 +2674,15 @@ static const struct cx88_subid cx88_subids[] = {
                .subvendor = 0x107d,
                .subdevice = 0x6654,
                .card      = CX88_BOARD_WINFAST_DTV1800H,
+       }, {
+               /* WinFast DTV1800 H with XC4000 tuner */
+               .subvendor = 0x107d,
+               .subdevice = 0x6f38,
+               .card      = CX88_BOARD_WINFAST_DTV1800H_XC4000,
+       }, {
+               .subvendor = 0x107d,
+               .subdevice = 0x6f42,
+               .card      = CX88_BOARD_WINFAST_DTV2000H_PLUS,
        }, {
                /* PVR2000 PAL Model [107d:6630] */
                .subvendor = 0x107d,
@@ -2846,6 +2949,23 @@ static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core,
        return -EINVAL;
 }
 
+static int cx88_xc4000_winfast2000h_plus_callback(struct cx88_core *core,
+                                                 int command, int arg)
+{
+       switch (command) {
+       case XC4000_TUNER_RESET:
+               /* GPIO 12 (xc4000 tuner reset) */
+               cx_set(MO_GP1_IO, 0x1010);
+               mdelay(50);
+               cx_clear(MO_GP1_IO, 0x10);
+               mdelay(75);
+               cx_set(MO_GP1_IO, 0x10);
+               mdelay(75);
+               return 0;
+       }
+       return -EINVAL;
+}
+
 /* ------------------------------------------------------------------- */
 /* some Divco specific stuff                                           */
 static int cx88_pv_8000gt_callback(struct cx88_core *core,
@@ -2948,6 +3068,19 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core,
        return -EINVAL;
 }
 
+static int cx88_xc4000_tuner_callback(struct cx88_core *core,
+                                     int command, int arg)
+{
+       /* Board-specific callbacks */
+       switch (core->boardnr) {
+       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+               return cx88_xc4000_winfast2000h_plus_callback(core,
+                                                             command, arg);
+       }
+       return -EINVAL;
+}
+
 /* ----------------------------------------------------------------------- */
 /* Tuner callback function. Currently only needed for the Pinnacle        *
  * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both      *
@@ -3022,6 +3155,9 @@ int cx88_tuner_callback(void *priv, int component, int command, int arg)
                case TUNER_XC2028:
                        info_printk(core, "Calling XC2028/3028 callback\n");
                        return cx88_xc2028_tuner_callback(core, command, arg);
+               case TUNER_XC4000:
+                       info_printk(core, "Calling XC4000 callback\n");
+                       return cx88_xc4000_tuner_callback(core, command, arg);
                case TUNER_XC5000:
                        info_printk(core, "Calling XC5000 callback\n");
                        return cx88_xc5000_tuner_callback(core, command, arg);
@@ -3109,13 +3245,13 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
 
        case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
        case CX88_BOARD_WINFAST_DTV1800H:
-               /* GPIO 12 (xc3028 tuner reset) */
-               cx_set(MO_GP1_IO, 0x1010);
-               mdelay(50);
-               cx_clear(MO_GP1_IO, 0x10);
-               mdelay(50);
-               cx_set(MO_GP1_IO, 0x10);
-               mdelay(50);
+               cx88_xc3028_winfast1800h_callback(core, XC2028_TUNER_RESET, 0);
+               break;
+
+       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+               cx88_xc4000_winfast2000h_plus_callback(core,
+                                                      XC4000_TUNER_RESET, 0);
                break;
 
        case CX88_BOARD_TWINHAN_VP1027_DVBS:
index 2e145f0..fbcaa1c 100644 (file)
@@ -636,6 +636,9 @@ int cx88_reset(struct cx88_core *core)
        cx_write(MO_PCI_INTSTAT,   0xFFFFFFFF); // Clear PCI int
        cx_write(MO_INT1_STAT,     0xFFFFFFFF); // Clear RISC int
 
+       /* set default notch filter */
+       cx_andor(MO_HTOTAL, 0x1800, (HLNotchFilter4xFsc << 11));
+
        /* Reset on-board parts */
        cx_write(MO_SRST_IO, 0);
        msleep(10);
@@ -759,8 +762,8 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig
        if (nocomb)
                value |= (3 << 5); // disable comb filter
 
-       cx_write(MO_FILTER_EVEN,  value);
-       cx_write(MO_FILTER_ODD,   value);
+       cx_andor(MO_FILTER_EVEN,  0x7ffc7f, value); /* preserve PEAKEN, PSEL */
+       cx_andor(MO_FILTER_ODD,   0x7ffc7f, value);
        dprintk(1,"set_scale: filter  0x%04x\n", value);
 
        return 0;
@@ -994,10 +997,10 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
        // htotal
        tmp64 = norm_htotal(norm) * (u64)vdec_clock;
        do_div(tmp64, fsc8);
-       htotal = (u32)tmp64 | (HLNotchFilter4xFsc << 11);
+       htotal = (u32)tmp64;
        dprintk(1,"set_tvnorm: MO_HTOTAL        0x%08x [old=0x%08x,htotal=%d]\n",
                htotal, cx_read(MO_HTOTAL), (u32)tmp64);
-       cx_write(MO_HTOTAL, htotal);
+       cx_andor(MO_HTOTAL, 0x07ff, htotal);
 
        // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
        // the effective vbi offset ~244 samples, the same as the Bt8x8
index c69df7e..cf3d33a 100644 (file)
@@ -41,6 +41,7 @@
 #include "or51132.h"
 #include "lgdt330x.h"
 #include "s5h1409.h"
+#include "xc4000.h"
 #include "xc5000.h"
 #include "nxt200x.h"
 #include "cx24123.h"
@@ -63,6 +64,7 @@ MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
 
 static unsigned int debug;
 module_param(debug, int, 0644);
@@ -605,6 +607,39 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
        return 0;
 }
 
+static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg)
+{
+       struct dvb_frontend *fe;
+       struct videobuf_dvb_frontend *fe0 = NULL;
+
+       /* Get the first frontend */
+       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+       if (!fe0)
+               return -EINVAL;
+
+       if (!fe0->dvb.frontend) {
+               printk(KERN_ERR "%s/2: dvb frontend not attached. "
+                               "Can't attach xc4000\n",
+                      dev->core->name);
+               return -EINVAL;
+       }
+
+       fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap,
+                       cfg);
+       if (!fe) {
+               printk(KERN_ERR "%s/2: xc4000 attach failed\n",
+                      dev->core->name);
+               dvb_frontend_detach(fe0->dvb.frontend);
+               dvb_unregister_frontend(fe0->dvb.frontend);
+               fe0->dvb.frontend = NULL;
+               return -EINVAL;
+       }
+
+       printk(KERN_INFO "%s/2: xc4000 attached\n", dev->core->name);
+
+       return 0;
+}
+
 static int cx24116_set_ts_param(struct dvb_frontend *fe,
        int is_punctured)
 {
@@ -1294,7 +1329,25 @@ static int dvb_register(struct cx8802_dev *dev)
                                goto frontend_detach;
                }
                break;
-        case CX88_BOARD_GENIATECH_X8000_MT:
+       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &cx88_pinnacle_hybrid_pctv,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       struct xc4000_config cfg = {
+                               .i2c_address      = 0x61,
+                               .default_pm       = 0,
+                               .dvb_amplitude    = 134,
+                               .set_smoothedcvbs = 1,
+                               .if_khz           = 4560
+                       };
+                       fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+                       if (attach_xc4000(dev, &cfg) < 0)
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_GENIATECH_X8000_MT:
                dev->ts_gen_cntrl = 0x00;
 
                fe0->dvb.frontend = dvb_attach(zl10353_attach,
@@ -1577,6 +1630,11 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
                udelay(1000);
                break;
 
+       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+               /* set RF input to AIR for DVB-T (GPIO 16) */
+               cx_write(MO_GP2_IO, 0x0101);
+               break;
+
        default:
                err = -ENODEV;
        }
@@ -1692,14 +1750,8 @@ static struct cx8802_driver cx8802_dvb_driver = {
 
 static int __init dvb_init(void)
 {
-       printk(KERN_INFO "cx88/2: cx2388x dvb driver version %d.%d.%d loaded\n",
-              (CX88_VERSION_CODE >> 16) & 0xff,
-              (CX88_VERSION_CODE >>  8) & 0xff,
-              CX88_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
-       printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
-              SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+       printk(KERN_INFO "cx88/2: cx2388x dvb driver version %s loaded\n",
+              CX88_VERSION);
        return cx8802_register_driver(&cx8802_dvb_driver);
 }
 
@@ -1710,10 +1762,3 @@ static void __exit dvb_fini(void)
 
 module_init(dvb_init);
 module_exit(dvb_fini);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * compile-command: "make DVB=1"
- * End:
- */
index 3f44200..e614201 100644 (file)
@@ -100,6 +100,8 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
                break;
        case CX88_BOARD_WINFAST_DTV1000:
        case CX88_BOARD_WINFAST_DTV1800H:
+       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
        case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
                gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
                auxgpio = gpio;
@@ -289,6 +291,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
        case CX88_BOARD_WINFAST_DTV2000H:
        case CX88_BOARD_WINFAST_DTV2000H_J:
        case CX88_BOARD_WINFAST_DTV1800H:
+       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
                ir_codes = RC_MAP_WINFAST;
                ir->gpio_addr = MO_GP0_IO;
                ir->mask_keycode = 0x8f8;
index 1a7b983..cd5386e 100644 (file)
@@ -39,6 +39,7 @@ MODULE_AUTHOR("Jelle Foks <jelle@foks.us>");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
 
 static unsigned int debug;
 module_param(debug,int,0644);
@@ -613,13 +614,17 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
            core->active_type_id != drv->type_id)
                return -EBUSY;
 
-       core->input = 0;
-       for (i = 0;
-            i < (sizeof(core->board.input) / sizeof(struct cx88_input));
-            i++) {
-               if (core->board.input[i].type == CX88_VMUX_DVB) {
-                       core->input = i;
-                       break;
+       if (drv->type_id == CX88_MPEG_DVB) {
+               /* When switching to DVB, always set the input to the tuner */
+               core->last_analog_input = core->input;
+               core->input = 0;
+               for (i = 0;
+                    i < (sizeof(core->board.input) / sizeof(struct cx88_input));
+                    i++) {
+                       if (core->board.input[i].type == CX88_VMUX_DVB) {
+                               core->input = i;
+                               break;
+                       }
                }
        }
 
@@ -644,6 +649,12 @@ static int cx8802_request_release(struct cx8802_driver *drv)
 
        if (drv->advise_release && --core->active_ref == 0)
        {
+               if (drv->type_id == CX88_MPEG_DVB) {
+                       /* If the DVB driver is releasing, reset the input
+                          state to the last configured analog input */
+                       core->input = core->last_analog_input;
+               }
+
                drv->advise_release(drv);
                core->active_type_id = CX88_BOARD_NONE;
                mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
@@ -890,14 +901,8 @@ static struct pci_driver cx8802_pci_driver = {
 
 static int __init cx8802_init(void)
 {
-       printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %d.%d.%d loaded\n",
-              (CX88_VERSION_CODE >> 16) & 0xff,
-              (CX88_VERSION_CODE >>  8) & 0xff,
-              CX88_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
-       printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
-              SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+       printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %s loaded\n",
+              CX88_VERSION);
        return pci_register_driver(&cx8802_pci_driver);
 }
 
index cef4f28..60d28fd 100644 (file)
@@ -45,6 +45,7 @@
 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
 
 /* ------------------------------------------------------------------ */
 
@@ -220,7 +221,23 @@ static const struct cx88_ctrl cx8800_ctls[] = {
                .reg                   = MO_UV_SATURATION,
                .mask                  = 0x00ff,
                .shift                 = 0,
-       },{
+       }, {
+               .v = {
+                       .id            = V4L2_CID_SHARPNESS,
+                       .name          = "Sharpness",
+                       .minimum       = 0,
+                       .maximum       = 4,
+                       .step          = 1,
+                       .default_value = 0x0,
+                       .type          = V4L2_CTRL_TYPE_INTEGER,
+               },
+               .off                   = 0,
+               /* NOTE: the value is converted and written to both even
+                  and odd registers in the code */
+               .reg                   = MO_FILTER_ODD,
+               .mask                  = 7 << 7,
+               .shift                 = 7,
+       }, {
                .v = {
                        .id            = V4L2_CID_CHROMA_AGC,
                        .name          = "Chroma AGC",
@@ -244,6 +261,20 @@ static const struct cx88_ctrl cx8800_ctls[] = {
                .reg                   = MO_INPUT_FORMAT,
                .mask                  = 1 << 9,
                .shift                 = 9,
+       }, {
+               .v = {
+                       .id            = V4L2_CID_BAND_STOP_FILTER,
+                       .name          = "Notch filter",
+                       .minimum       = 0,
+                       .maximum       = 3,
+                       .step          = 1,
+                       .default_value = 0x0,
+                       .type          = V4L2_CTRL_TYPE_INTEGER,
+               },
+               .off                   = 0,
+               .reg                   = MO_HTOTAL,
+               .mask                  = 3 << 11,
+               .shift                 = 11,
        }, {
        /* --- audio --- */
                .v = {
@@ -300,8 +331,10 @@ const u32 cx88_user_ctrls[] = {
        V4L2_CID_AUDIO_VOLUME,
        V4L2_CID_AUDIO_BALANCE,
        V4L2_CID_AUDIO_MUTE,
+       V4L2_CID_SHARPNESS,
        V4L2_CID_CHROMA_AGC,
        V4L2_CID_COLOR_KILLER,
+       V4L2_CID_BAND_STOP_FILTER,
        0
 };
 EXPORT_SYMBOL(cx88_user_ctrls);
@@ -962,6 +995,10 @@ int cx88_get_control (struct cx88_core  *core, struct v4l2_control *ctl)
        case V4L2_CID_AUDIO_VOLUME:
                ctl->value = 0x3f - (value & 0x3f);
                break;
+       case V4L2_CID_SHARPNESS:
+               ctl->value = ((value & 0x0200) ? (((value & 0x0180) >> 7) + 1)
+                                                : 0);
+               break;
        default:
                ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift;
                break;
@@ -1039,6 +1076,12 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
                }
                mask=0xffff;
                break;
+       case V4L2_CID_SHARPNESS:
+               /* 0b000, 0b100, 0b101, 0b110, or 0b111 */
+               value = (ctl->value < 1 ? 0 : ((ctl->value + 3) << 7));
+               /* needs to be set for both fields */
+               cx_andor(MO_FILTER_EVEN, mask, value);
+               break;
        case V4L2_CID_CHROMA_AGC:
                /* Do not allow chroma AGC to be enabled for SECAM */
                value = ((ctl->value - c->off) << c->shift) & c->mask;
@@ -1161,7 +1204,6 @@ static int vidioc_querycap (struct file *file, void  *priv,
        strcpy(cap->driver, "cx8800");
        strlcpy(cap->card, core->board.name, sizeof(cap->card));
        sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
-       cap->version = CX88_VERSION_CODE;
        cap->capabilities =
                V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_READWRITE     |
@@ -1480,7 +1522,6 @@ static int radio_querycap (struct file *file, void  *priv,
        strcpy(cap->driver, "cx8800");
        strlcpy(cap->card, core->board.name, sizeof(cap->card));
        sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
-       cap->version = CX88_VERSION_CODE;
        cap->capabilities = V4L2_CAP_TUNER;
        return 0;
 }
@@ -2139,14 +2180,8 @@ static struct pci_driver cx8800_pci_driver = {
 
 static int __init cx8800_init(void)
 {
-       printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %d.%d.%d loaded\n",
-              (CX88_VERSION_CODE >> 16) & 0xff,
-              (CX88_VERSION_CODE >>  8) & 0xff,
-              CX88_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
-       printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
-              SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+       printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %s loaded\n",
+              CX88_VERSION);
        return pci_register_driver(&cx8800_pci_driver);
 }
 
@@ -2157,11 +2192,3 @@ static void __exit cx8800_fini(void)
 
 module_init(cx8800_init);
 module_exit(cx8800_fini);
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
index a399a8b..fa8d307 100644 (file)
@@ -39,9 +39,9 @@
 #include "cx88-reg.h"
 #include "tuner-xc2028.h"
 
-#include <linux/version.h>
 #include <linux/mutex.h>
-#define CX88_VERSION_CODE KERNEL_VERSION(0, 0, 8)
+
+#define CX88_VERSION "0.0.9"
 
 #define UNSET (-1U)
 
@@ -242,6 +242,8 @@ extern const struct sram_channel const cx88_sram_channels[];
 #define CX88_BOARD_SAMSUNG_SMT_7020        84
 #define CX88_BOARD_TWINHAN_VP1027_DVBS     85
 #define CX88_BOARD_TEVII_S464              86
+#define CX88_BOARD_WINFAST_DTV2000H_PLUS   87
+#define CX88_BOARD_WINFAST_DTV1800H_XC4000 88
 
 enum cx88_itype {
        CX88_VMUX_COMPOSITE1 = 1,
@@ -375,6 +377,7 @@ struct cx88_core {
        u32                        audiomode_manual;
        u32                        audiomode_current;
        u32                        input;
+       u32                        last_analog_input;
        u32                        astat;
        u32                        use_nicam;
        unsigned long              last_change;
index 6b19540..60a456e 100644 (file)
@@ -91,3 +91,26 @@ config VIDEO_ISIF
 
           To compile this driver as a module, choose M here: the
           module will be called vpfe.
+
+config VIDEO_DM644X_VPBE
+       tristate "DM644X VPBE HW module"
+       depends on ARCH_DAVINCI_DM644x
+       select VIDEO_VPSS_SYSTEM
+       select VIDEOBUF_DMA_CONTIG
+       help
+           Enables VPBE modules used for display on a DM644x
+           SoC.
+
+           To compile this driver as a module, choose M here: the
+           module will be called vpbe.
+
+
+config VIDEO_VPBE_DISPLAY
+       tristate "VPBE V4L2 Display driver"
+       depends on ARCH_DAVINCI_DM644x
+       select VIDEO_DM644X_VPBE
+       help
+           Enables VPBE V4L2 Display driver on a DM644x device
+
+           To compile this driver as a module, choose M here: the
+           module will be called vpbe_display.
index a379557..ae7dafb 100644 (file)
@@ -16,3 +16,5 @@ obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o
 obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o
 obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o
 obj-$(CONFIG_VIDEO_ISIF) += isif.o
+obj-$(CONFIG_VIDEO_DM644X_VPBE) += vpbe.o vpbe_osd.o vpbe_venc.o
+obj-$(CONFIG_VIDEO_VPBE_DISPLAY) += vpbe_display.o
diff --git a/drivers/media/video/davinci/vpbe.c b/drivers/media/video/davinci/vpbe.c
new file mode 100644 (file)
index 0000000..d773d30
--- /dev/null
@@ -0,0 +1,864 @@
+/*
+ * Copyright (C) 2010 Texas Instruments 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <media/v4l2-device.h>
+#include <media/davinci/vpbe_types.h>
+#include <media/davinci/vpbe.h>
+#include <media/davinci/vpss.h>
+#include <media/davinci/vpbe_venc.h>
+
+#define VPBE_DEFAULT_OUTPUT    "Composite"
+#define VPBE_DEFAULT_MODE      "ntsc"
+
+static char *def_output = VPBE_DEFAULT_OUTPUT;
+static char *def_mode = VPBE_DEFAULT_MODE;
+static int debug;
+
+module_param(def_output, charp, S_IRUGO);
+module_param(def_mode, charp, S_IRUGO);
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(def_output, "vpbe output name (default:Composite)");
+MODULE_PARM_DESC(def_mode, "vpbe output mode name (default:ntsc");
+MODULE_PARM_DESC(debug, "Debug level 0-1");
+
+MODULE_DESCRIPTION("TI DMXXX VPBE Display controller");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Texas Instruments");
+
+/**
+ * vpbe_current_encoder_info - Get config info for current encoder
+ * @vpbe_dev - vpbe device ptr
+ *
+ * Return ptr to current encoder config info
+ */
+static struct encoder_config_info*
+vpbe_current_encoder_info(struct vpbe_device *vpbe_dev)
+{
+       struct vpbe_config *cfg = vpbe_dev->cfg;
+       int index = vpbe_dev->current_sd_index;
+
+       return ((index == 0) ? &cfg->venc :
+                               &cfg->ext_encoders[index-1]);
+}
+
+/**
+ * vpbe_find_encoder_sd_index - Given a name find encoder sd index
+ *
+ * @vpbe_config - ptr to vpbe cfg
+ * @output_index - index used by application
+ *
+ * Return sd index of the encoder
+ */
+static int vpbe_find_encoder_sd_index(struct vpbe_config *cfg,
+                            int index)
+{
+       char *encoder_name = cfg->outputs[index].subdev_name;
+       int i;
+
+       /* Venc is always first */
+       if (!strcmp(encoder_name, cfg->venc.module_name))
+               return 0;
+
+       for (i = 0; i < cfg->num_ext_encoders; i++) {
+               if (!strcmp(encoder_name,
+                    cfg->ext_encoders[i].module_name))
+                       return i+1;
+       }
+
+       return -EINVAL;
+}
+
+/**
+ * vpbe_g_cropcap - Get crop capabilities of the display
+ * @vpbe_dev - vpbe device ptr
+ * @cropcap - cropcap is a ptr to struct v4l2_cropcap
+ *
+ * Update the crop capabilities in crop cap for current
+ * mode
+ */
+static int vpbe_g_cropcap(struct vpbe_device *vpbe_dev,
+                         struct v4l2_cropcap *cropcap)
+{
+       if (NULL == cropcap)
+               return -EINVAL;
+       cropcap->bounds.left = 0;
+       cropcap->bounds.top = 0;
+       cropcap->bounds.width = vpbe_dev->current_timings.xres;
+       cropcap->bounds.height = vpbe_dev->current_timings.yres;
+       cropcap->defrect = cropcap->bounds;
+
+       return 0;
+}
+
+/**
+ * vpbe_enum_outputs - enumerate outputs
+ * @vpbe_dev - vpbe device ptr
+ * @output - ptr to v4l2_output structure
+ *
+ * Enumerates the outputs available at the vpbe display
+ * returns the status, -EINVAL if end of output list
+ */
+static int vpbe_enum_outputs(struct vpbe_device *vpbe_dev,
+                            struct v4l2_output *output)
+{
+       struct vpbe_config *cfg = vpbe_dev->cfg;
+       int temp_index = output->index;
+
+       if (temp_index >= cfg->num_outputs)
+               return -EINVAL;
+
+       *output = cfg->outputs[temp_index].output;
+       output->index = temp_index;
+
+       return 0;
+}
+
+static int vpbe_get_mode_info(struct vpbe_device *vpbe_dev, char *mode)
+{
+       struct vpbe_config *cfg = vpbe_dev->cfg;
+       struct vpbe_enc_mode_info var;
+       int curr_output = vpbe_dev->current_out_index;
+       int i;
+
+       if (NULL == mode)
+               return -EINVAL;
+
+       for (i = 0; i < cfg->outputs[curr_output].num_modes; i++) {
+               var = cfg->outputs[curr_output].modes[i];
+               if (!strcmp(mode, var.name)) {
+                       vpbe_dev->current_timings = var;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int vpbe_get_current_mode_info(struct vpbe_device *vpbe_dev,
+                                     struct vpbe_enc_mode_info *mode_info)
+{
+       if (NULL == mode_info)
+               return -EINVAL;
+
+       *mode_info = vpbe_dev->current_timings;
+
+       return 0;
+}
+
+static int vpbe_get_dv_preset_info(struct vpbe_device *vpbe_dev,
+                                  unsigned int dv_preset)
+{
+       struct vpbe_config *cfg = vpbe_dev->cfg;
+       struct vpbe_enc_mode_info var;
+       int curr_output = vpbe_dev->current_out_index;
+       int i;
+
+       for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
+               var = cfg->outputs[curr_output].modes[i];
+               if ((var.timings_type & VPBE_ENC_DV_PRESET) &&
+                 (var.timings.dv_preset == dv_preset)) {
+                       vpbe_dev->current_timings = var;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+/* Get std by std id */
+static int vpbe_get_std_info(struct vpbe_device *vpbe_dev,
+                            v4l2_std_id std_id)
+{
+       struct vpbe_config *cfg = vpbe_dev->cfg;
+       struct vpbe_enc_mode_info var;
+       int curr_output = vpbe_dev->current_out_index;
+       int i;
+
+       for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
+               var = cfg->outputs[curr_output].modes[i];
+               if ((var.timings_type & VPBE_ENC_STD) &&
+                 (var.timings.std_id & std_id)) {
+                       vpbe_dev->current_timings = var;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int vpbe_get_std_info_by_name(struct vpbe_device *vpbe_dev,
+                               char *std_name)
+{
+       struct vpbe_config *cfg = vpbe_dev->cfg;
+       struct vpbe_enc_mode_info var;
+       int curr_output = vpbe_dev->current_out_index;
+       int i;
+
+       for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
+               var = cfg->outputs[curr_output].modes[i];
+               if (!strcmp(var.name, std_name)) {
+                       vpbe_dev->current_timings = var;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+/**
+ * vpbe_set_output - Set output
+ * @vpbe_dev - vpbe device ptr
+ * @index - index of output
+ *
+ * Set vpbe output to the output specified by the index
+ */
+static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index)
+{
+       struct encoder_config_info *curr_enc_info =
+                       vpbe_current_encoder_info(vpbe_dev);
+       struct vpbe_config *cfg = vpbe_dev->cfg;
+       int enc_out_index;
+       int sd_index;
+       int ret = 0;
+
+       if (index >= cfg->num_outputs)
+               return -EINVAL;
+
+       mutex_lock(&vpbe_dev->lock);
+
+       sd_index = vpbe_dev->current_sd_index;
+       enc_out_index = cfg->outputs[index].output.index;
+       /*
+        * Currently we switch the encoder based on output selected
+        * by the application. If media controller is implemented later
+        * there is will be an API added to setup_link between venc
+        * and external encoder. So in that case below comparison always
+        * match and encoder will not be switched. But if application
+        * chose not to use media controller, then this provides current
+        * way of switching encoder at the venc output.
+        */
+       if (strcmp(curr_enc_info->module_name,
+                  cfg->outputs[index].subdev_name)) {
+               /* Need to switch the encoder at the output */
+               sd_index = vpbe_find_encoder_sd_index(cfg, index);
+               if (sd_index < 0) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               if (ret)
+                       goto out;
+       }
+
+       /* Set output at the encoder */
+       ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
+                                      s_routing, 0, enc_out_index, 0);
+       if (ret)
+               goto out;
+
+       /*
+        * It is assumed that venc or extenal encoder will set a default
+        * mode in the sub device. For external encoder or LCD pannel output,
+        * we also need to set up the lcd port for the required mode. So setup
+        * the lcd port for the default mode that is configured in the board
+        * arch/arm/mach-davinci/board-dm355-evm.setup file for the external
+        * encoder.
+        */
+       ret = vpbe_get_mode_info(vpbe_dev,
+                                cfg->outputs[index].default_mode);
+       if (!ret) {
+               struct osd_state *osd_device = vpbe_dev->osd_device;
+
+               osd_device->ops.set_left_margin(osd_device,
+                       vpbe_dev->current_timings.left_margin);
+               osd_device->ops.set_top_margin(osd_device,
+               vpbe_dev->current_timings.upper_margin);
+               vpbe_dev->current_sd_index = sd_index;
+               vpbe_dev->current_out_index = index;
+       }
+out:
+       mutex_unlock(&vpbe_dev->lock);
+       return ret;
+}
+
+static int vpbe_set_default_output(struct vpbe_device *vpbe_dev)
+{
+       struct vpbe_config *cfg = vpbe_dev->cfg;
+       int ret = 0;
+       int i;
+
+       for (i = 0; i < cfg->num_outputs; i++) {
+               if (!strcmp(def_output,
+                           cfg->outputs[i].output.name)) {
+                       ret = vpbe_set_output(vpbe_dev, i);
+                       if (!ret)
+                               vpbe_dev->current_out_index = i;
+                       return ret;
+               }
+       }
+       return ret;
+}
+
+/**
+ * vpbe_get_output - Get output
+ * @vpbe_dev - vpbe device ptr
+ *
+ * return current vpbe output to the the index
+ */
+static unsigned int vpbe_get_output(struct vpbe_device *vpbe_dev)
+{
+       return vpbe_dev->current_out_index;
+}
+
+/**
+ * vpbe_s_dv_preset - Set the given preset timings in the encoder
+ *
+ * Sets the preset if supported by the current encoder. Return the status.
+ * 0 - success & -EINVAL on error
+ */
+static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev,
+                    struct v4l2_dv_preset *dv_preset)
+{
+       struct vpbe_config *cfg = vpbe_dev->cfg;
+       int out_index = vpbe_dev->current_out_index;
+       int sd_index = vpbe_dev->current_sd_index;
+       int ret;
+
+
+       if (!(cfg->outputs[out_index].output.capabilities &
+           V4L2_OUT_CAP_PRESETS))
+               return -EINVAL;
+
+       ret = vpbe_get_dv_preset_info(vpbe_dev, dv_preset->preset);
+
+       if (ret)
+               return ret;
+
+       mutex_lock(&vpbe_dev->lock);
+
+
+       ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
+                                       s_dv_preset, dv_preset);
+       /* set the lcd controller output for the given mode */
+       if (!ret) {
+               struct osd_state *osd_device = vpbe_dev->osd_device;
+
+               osd_device->ops.set_left_margin(osd_device,
+               vpbe_dev->current_timings.left_margin);
+               osd_device->ops.set_top_margin(osd_device,
+               vpbe_dev->current_timings.upper_margin);
+       }
+       mutex_unlock(&vpbe_dev->lock);
+
+       return ret;
+}
+
+/**
+ * vpbe_g_dv_preset - Get the preset in the current encoder
+ *
+ * Get the preset in the current encoder. Return the status. 0 - success
+ * -EINVAL on error
+ */
+static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev,
+                    struct v4l2_dv_preset *dv_preset)
+{
+       if (vpbe_dev->current_timings.timings_type &
+         VPBE_ENC_DV_PRESET) {
+               dv_preset->preset = vpbe_dev->current_timings.timings.dv_preset;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+/**
+ * vpbe_enum_dv_presets - Enumerate the dv presets in the current encoder
+ *
+ * Get the preset in the current encoder. Return the status. 0 - success
+ * -EINVAL on error
+ */
+static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
+                        struct v4l2_dv_enum_preset *preset_info)
+{
+       struct vpbe_config *cfg = vpbe_dev->cfg;
+       int out_index = vpbe_dev->current_out_index;
+       struct vpbe_output *output = &cfg->outputs[out_index];
+       int j = 0;
+       int i;
+
+       if (!(output->output.capabilities & V4L2_OUT_CAP_PRESETS))
+               return -EINVAL;
+
+       for (i = 0; i < output->num_modes; i++) {
+               if (output->modes[i].timings_type == VPBE_ENC_DV_PRESET) {
+                       if (j == preset_info->index)
+                               break;
+                       j++;
+               }
+       }
+
+       if (i == output->num_modes)
+               return -EINVAL;
+
+       return v4l_fill_dv_preset_info(output->modes[i].timings.dv_preset,
+                                       preset_info);
+}
+
+/**
+ * vpbe_s_std - Set the given standard in the encoder
+ *
+ * Sets the standard if supported by the current encoder. Return the status.
+ * 0 - success & -EINVAL on error
+ */
+static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
+{
+       struct vpbe_config *cfg = vpbe_dev->cfg;
+       int out_index = vpbe_dev->current_out_index;
+       int sd_index = vpbe_dev->current_sd_index;
+       int ret;
+
+       if (!(cfg->outputs[out_index].output.capabilities &
+               V4L2_OUT_CAP_STD))
+               return -EINVAL;
+
+       ret = vpbe_get_std_info(vpbe_dev, *std_id);
+       if (ret)
+               return ret;
+
+       mutex_lock(&vpbe_dev->lock);
+
+       ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
+                              s_std_output, *std_id);
+       /* set the lcd controller output for the given mode */
+       if (!ret) {
+               struct osd_state *osd_device = vpbe_dev->osd_device;
+
+               osd_device->ops.set_left_margin(osd_device,
+               vpbe_dev->current_timings.left_margin);
+               osd_device->ops.set_top_margin(osd_device,
+               vpbe_dev->current_timings.upper_margin);
+       }
+       mutex_unlock(&vpbe_dev->lock);
+
+       return ret;
+}
+
+/**
+ * vpbe_g_std - Get the standard in the current encoder
+ *
+ * Get the standard in the current encoder. Return the status. 0 - success
+ * -EINVAL on error
+ */
+static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
+{
+       struct vpbe_enc_mode_info cur_timings = vpbe_dev->current_timings;
+
+       if (cur_timings.timings_type & VPBE_ENC_STD) {
+               *std_id = cur_timings.timings.std_id;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+/**
+ * vpbe_set_mode - Set mode in the current encoder using mode info
+ *
+ * Use the mode string to decide what timings to set in the encoder
+ * This is typically useful when fbset command is used to change the current
+ * timings by specifying a string to indicate the timings.
+ */
+static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
+                        struct vpbe_enc_mode_info *mode_info)
+{
+       struct vpbe_enc_mode_info *preset_mode = NULL;
+       struct vpbe_config *cfg = vpbe_dev->cfg;
+       struct v4l2_dv_preset dv_preset;
+       struct osd_state *osd_device;
+       int out_index = vpbe_dev->current_out_index;
+       int ret = 0;
+       int i;
+
+       if ((NULL == mode_info) || (NULL == mode_info->name))
+               return -EINVAL;
+
+       for (i = 0; i < cfg->outputs[out_index].num_modes; i++) {
+               if (!strcmp(mode_info->name,
+                    cfg->outputs[out_index].modes[i].name)) {
+                       preset_mode = &cfg->outputs[out_index].modes[i];
+                       /*
+                        * it may be one of the 3 timings type. Check and
+                        * invoke right API
+                        */
+                       if (preset_mode->timings_type & VPBE_ENC_STD)
+                               return vpbe_s_std(vpbe_dev,
+                                                &preset_mode->timings.std_id);
+                       if (preset_mode->timings_type & VPBE_ENC_DV_PRESET) {
+                               dv_preset.preset =
+                                       preset_mode->timings.dv_preset;
+                               return vpbe_s_dv_preset(vpbe_dev, &dv_preset);
+                       }
+               }
+       }
+
+       /* Only custom timing should reach here */
+       if (preset_mode == NULL)
+               return -EINVAL;
+
+       mutex_lock(&vpbe_dev->lock);
+
+       osd_device = vpbe_dev->osd_device;
+       vpbe_dev->current_timings = *preset_mode;
+       osd_device->ops.set_left_margin(osd_device,
+               vpbe_dev->current_timings.left_margin);
+       osd_device->ops.set_top_margin(osd_device,
+               vpbe_dev->current_timings.upper_margin);
+
+       mutex_unlock(&vpbe_dev->lock);
+
+       return ret;
+}
+
+static int vpbe_set_default_mode(struct vpbe_device *vpbe_dev)
+{
+       int ret;
+
+       ret = vpbe_get_std_info_by_name(vpbe_dev, def_mode);
+       if (ret)
+               return ret;
+
+       /* set the default mode in the encoder */
+       return vpbe_set_mode(vpbe_dev, &vpbe_dev->current_timings);
+}
+
+static int platform_device_get(struct device *dev, void *data)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct vpbe_device *vpbe_dev = data;
+
+       if (strcmp("vpbe-osd", pdev->name) == 0)
+               vpbe_dev->osd_device = platform_get_drvdata(pdev);
+
+       return 0;
+}
+
+/**
+ * vpbe_initialize() - Initialize the vpbe display controller
+ * @vpbe_dev - vpbe device ptr
+ *
+ * Master frame buffer device drivers calls this to initialize vpbe
+ * display controller. This will then registers v4l2 device and the sub
+ * devices and sets a current encoder sub device for display. v4l2 display
+ * device driver is the master and frame buffer display device driver is
+ * the slave. Frame buffer display driver checks the initialized during
+ * probe and exit if not initialized. Returns status.
+ */
+static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
+{
+       struct encoder_config_info *enc_info;
+       struct v4l2_subdev **enc_subdev;
+       struct osd_state *osd_device;
+       struct i2c_adapter *i2c_adap;
+       int output_index;
+       int num_encoders;
+       int ret = 0;
+       int err;
+       int i;
+
+       /*
+        * v4l2 abd FBDev frame buffer devices will get the vpbe_dev pointer
+        * from the platform device by iteration of platform drivers and
+        * matching with device name
+        */
+       if (NULL == vpbe_dev || NULL == dev) {
+               printk(KERN_ERR "Null device pointers.\n");
+               return -ENODEV;
+       }
+
+       if (vpbe_dev->initialized)
+               return 0;
+
+       mutex_lock(&vpbe_dev->lock);
+
+       if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) {
+               /* We have dac clock available for platform */
+               vpbe_dev->dac_clk = clk_get(vpbe_dev->pdev, "vpss_dac");
+               if (IS_ERR(vpbe_dev->dac_clk)) {
+                       ret =  PTR_ERR(vpbe_dev->dac_clk);
+                       goto vpbe_unlock;
+               }
+               if (clk_enable(vpbe_dev->dac_clk)) {
+                       ret =  -ENODEV;
+                       goto vpbe_unlock;
+               }
+       }
+
+       /* first enable vpss clocks */
+       vpss_enable_clock(VPSS_VPBE_CLOCK, 1);
+
+       /* First register a v4l2 device */
+       ret = v4l2_device_register(dev, &vpbe_dev->v4l2_dev);
+       if (ret) {
+               v4l2_err(dev->driver,
+                       "Unable to register v4l2 device.\n");
+               goto vpbe_fail_clock;
+       }
+       v4l2_info(&vpbe_dev->v4l2_dev, "vpbe v4l2 device registered\n");
+
+       err = bus_for_each_dev(&platform_bus_type, NULL, vpbe_dev,
+                              platform_device_get);
+       if (err < 0)
+               return err;
+
+       vpbe_dev->venc = venc_sub_dev_init(&vpbe_dev->v4l2_dev,
+                                          vpbe_dev->cfg->venc.module_name);
+       /* register venc sub device */
+       if (vpbe_dev->venc == NULL) {
+               v4l2_err(&vpbe_dev->v4l2_dev,
+                       "vpbe unable to init venc sub device\n");
+               ret = -ENODEV;
+               goto vpbe_fail_v4l2_device;
+       }
+       /* initialize osd device */
+       osd_device = vpbe_dev->osd_device;
+
+       if (NULL != osd_device->ops.initialize) {
+               err = osd_device->ops.initialize(osd_device);
+               if (err) {
+                       v4l2_err(&vpbe_dev->v4l2_dev,
+                                "unable to initialize the OSD device");
+                       err = -ENOMEM;
+                       goto vpbe_fail_v4l2_device;
+               }
+       }
+
+       /*
+        * Register any external encoders that are configured. At index 0 we
+        * store venc sd index.
+        */
+       num_encoders = vpbe_dev->cfg->num_ext_encoders + 1;
+       vpbe_dev->encoders = kmalloc(
+                               sizeof(struct v4l2_subdev *)*num_encoders,
+                               GFP_KERNEL);
+       if (NULL == vpbe_dev->encoders) {
+               v4l2_err(&vpbe_dev->v4l2_dev,
+                       "unable to allocate memory for encoders sub devices");
+               ret = -ENOMEM;
+               goto vpbe_fail_v4l2_device;
+       }
+
+       i2c_adap = i2c_get_adapter(vpbe_dev->cfg->i2c_adapter_id);
+       for (i = 0; i < (vpbe_dev->cfg->num_ext_encoders + 1); i++) {
+               if (i == 0) {
+                       /* venc is at index 0 */
+                       enc_subdev = &vpbe_dev->encoders[i];
+                       *enc_subdev = vpbe_dev->venc;
+                       continue;
+               }
+               enc_info = &vpbe_dev->cfg->ext_encoders[i];
+               if (enc_info->is_i2c) {
+                       enc_subdev = &vpbe_dev->encoders[i];
+                       *enc_subdev = v4l2_i2c_new_subdev_board(
+                                               &vpbe_dev->v4l2_dev, i2c_adap,
+                                               &enc_info->board_info, NULL);
+                       if (*enc_subdev)
+                               v4l2_info(&vpbe_dev->v4l2_dev,
+                                         "v4l2 sub device %s registered\n",
+                                         enc_info->module_name);
+                       else {
+                               v4l2_err(&vpbe_dev->v4l2_dev, "encoder %s"
+                                        " failed to register",
+                                        enc_info->module_name);
+                               ret = -ENODEV;
+                               goto vpbe_fail_sd_register;
+                       }
+               } else
+                       v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders"
+                                " currently not supported");
+       }
+
+       /* set the current encoder and output to that of venc by default */
+       vpbe_dev->current_sd_index = 0;
+       vpbe_dev->current_out_index = 0;
+       output_index = 0;
+
+       mutex_unlock(&vpbe_dev->lock);
+
+       printk(KERN_NOTICE "Setting default output to %s\n", def_output);
+       ret = vpbe_set_default_output(vpbe_dev);
+       if (ret) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default output %s",
+                        def_output);
+               return ret;
+       }
+
+       printk(KERN_NOTICE "Setting default mode to %s\n", def_mode);
+       ret = vpbe_set_default_mode(vpbe_dev);
+       if (ret) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default mode %s",
+                        def_mode);
+               return ret;
+       }
+       vpbe_dev->initialized = 1;
+       /* TBD handling of bootargs for default output and mode */
+       return 0;
+
+vpbe_fail_sd_register:
+       kfree(vpbe_dev->encoders);
+vpbe_fail_v4l2_device:
+       v4l2_device_unregister(&vpbe_dev->v4l2_dev);
+vpbe_fail_clock:
+       if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
+               clk_put(vpbe_dev->dac_clk);
+vpbe_unlock:
+       mutex_unlock(&vpbe_dev->lock);
+       return ret;
+}
+
+/**
+ * vpbe_deinitialize() - de-initialize the vpbe display controller
+ * @dev - Master and slave device ptr
+ *
+ * vpbe_master and slave frame buffer devices calls this to de-initialize
+ * the display controller. It is called when master and slave device
+ * driver modules are removed and no longer requires the display controller.
+ */
+static void vpbe_deinitialize(struct device *dev, struct vpbe_device *vpbe_dev)
+{
+       v4l2_device_unregister(&vpbe_dev->v4l2_dev);
+       if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
+               clk_put(vpbe_dev->dac_clk);
+
+       kfree(vpbe_dev->encoders);
+       vpbe_dev->initialized = 0;
+       /* disable vpss clocks */
+       vpss_enable_clock(VPSS_VPBE_CLOCK, 0);
+}
+
+static struct vpbe_device_ops vpbe_dev_ops = {
+       .g_cropcap = vpbe_g_cropcap,
+       .enum_outputs = vpbe_enum_outputs,
+       .set_output = vpbe_set_output,
+       .get_output = vpbe_get_output,
+       .s_dv_preset = vpbe_s_dv_preset,
+       .g_dv_preset = vpbe_g_dv_preset,
+       .enum_dv_presets = vpbe_enum_dv_presets,
+       .s_std = vpbe_s_std,
+       .g_std = vpbe_g_std,
+       .initialize = vpbe_initialize,
+       .deinitialize = vpbe_deinitialize,
+       .get_mode_info = vpbe_get_current_mode_info,
+       .set_mode = vpbe_set_mode,
+};
+
+static __devinit int vpbe_probe(struct platform_device *pdev)
+{
+       struct vpbe_device *vpbe_dev;
+       struct vpbe_config *cfg;
+       int ret = -EINVAL;
+
+       if (pdev->dev.platform_data == NULL) {
+               v4l2_err(pdev->dev.driver, "No platform data\n");
+               return -ENODEV;
+       }
+       cfg = pdev->dev.platform_data;
+
+       if (!cfg->module_name[0] ||
+           !cfg->osd.module_name[0] ||
+           !cfg->venc.module_name[0]) {
+               v4l2_err(pdev->dev.driver, "vpbe display module names not"
+                        " defined\n");
+               return ret;
+       }
+
+       vpbe_dev = kzalloc(sizeof(*vpbe_dev), GFP_KERNEL);
+       if (vpbe_dev == NULL) {
+               v4l2_err(pdev->dev.driver, "Unable to allocate memory"
+                        " for vpbe_device\n");
+               return -ENOMEM;
+       }
+       vpbe_dev->cfg = cfg;
+       vpbe_dev->ops = vpbe_dev_ops;
+       vpbe_dev->pdev = &pdev->dev;
+
+       if (cfg->outputs->num_modes > 0)
+               vpbe_dev->current_timings = vpbe_dev->cfg->outputs[0].modes[0];
+       else
+               return -ENODEV;
+
+       /* set the driver data in platform device */
+       platform_set_drvdata(pdev, vpbe_dev);
+       mutex_init(&vpbe_dev->lock);
+
+       return 0;
+}
+
+static int vpbe_remove(struct platform_device *device)
+{
+       struct vpbe_device *vpbe_dev = platform_get_drvdata(device);
+
+       kfree(vpbe_dev);
+
+       return 0;
+}
+
+static struct platform_driver vpbe_driver = {
+       .driver = {
+               .name   = "vpbe_controller",
+               .owner  = THIS_MODULE,
+       },
+       .probe = vpbe_probe,
+       .remove = vpbe_remove,
+};
+
+/**
+ * vpbe_init: initialize the vpbe driver
+ *
+ * This function registers device and driver to the kernel
+ */
+static __init int vpbe_init(void)
+{
+       return platform_driver_register(&vpbe_driver);
+}
+
+/**
+ * vpbe_cleanup : cleanup function for vpbe driver
+ *
+ * This will un-registers the device and driver to the kernel
+ */
+static void vpbe_cleanup(void)
+{
+       platform_driver_unregister(&vpbe_driver);
+}
+
+/* Function for module initialization and cleanup */
+module_init(vpbe_init);
+module_exit(vpbe_cleanup);
diff --git a/drivers/media/video/davinci/vpbe_display.c b/drivers/media/video/davinci/vpbe_display.c
new file mode 100644 (file)
index 0000000..7f1d83a
--- /dev/null
@@ -0,0 +1,1860 @@
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.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 version 2.
+ *
+ * This program is distributed WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+
+#include <asm/pgtable.h>
+#include <mach/cputype.h>
+
+#include <media/v4l2-dev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/davinci/vpbe_display.h>
+#include <media/davinci/vpbe_types.h>
+#include <media/davinci/vpbe.h>
+#include <media/davinci/vpbe_venc.h>
+#include <media/davinci/vpbe_osd.h>
+#include "vpbe_venc_regs.h"
+
+#define VPBE_DISPLAY_DRIVER "vpbe-v4l2"
+
+static int debug;
+
+#define VPBE_DISPLAY_SD_BUF_SIZE (720*576*2)
+#define VPBE_DEFAULT_NUM_BUFS 3
+
+module_param(debug, int, 0644);
+
+static int venc_is_second_field(struct vpbe_display *disp_dev)
+{
+       struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
+       int ret;
+       int val;
+
+       ret = v4l2_subdev_call(vpbe_dev->venc,
+                              core,
+                              ioctl,
+                              VENC_GET_FLD,
+                              &val);
+       if (ret < 0) {
+               v4l2_err(&vpbe_dev->v4l2_dev,
+                        "Error in getting Field ID 0\n");
+       }
+       return val;
+}
+
+static void vpbe_isr_even_field(struct vpbe_display *disp_obj,
+                               struct vpbe_layer *layer)
+{
+       struct timespec timevalue;
+
+       if (layer->cur_frm == layer->next_frm)
+               return;
+       ktime_get_ts(&timevalue);
+       layer->cur_frm->ts.tv_sec = timevalue.tv_sec;
+       layer->cur_frm->ts.tv_usec = timevalue.tv_nsec / NSEC_PER_USEC;
+       layer->cur_frm->state = VIDEOBUF_DONE;
+       wake_up_interruptible(&layer->cur_frm->done);
+       /* Make cur_frm pointing to next_frm */
+       layer->cur_frm = layer->next_frm;
+}
+
+static void vpbe_isr_odd_field(struct vpbe_display *disp_obj,
+                               struct vpbe_layer *layer)
+{
+       struct osd_state *osd_device = disp_obj->osd_device;
+       unsigned long addr;
+
+       spin_lock(&disp_obj->dma_queue_lock);
+       if (list_empty(&layer->dma_queue) ||
+               (layer->cur_frm != layer->next_frm)) {
+               spin_unlock(&disp_obj->dma_queue_lock);
+               return;
+       }
+       /*
+        * one field is displayed configure
+        * the next frame if it is available
+        * otherwise hold on current frame
+        * Get next from the buffer queue
+        */
+       layer->next_frm = list_entry(
+                               layer->dma_queue.next,
+                               struct  videobuf_buffer,
+                               queue);
+       /* Remove that from the buffer queue */
+       list_del(&layer->next_frm->queue);
+       spin_unlock(&disp_obj->dma_queue_lock);
+       /* Mark state of the frame to active */
+       layer->next_frm->state = VIDEOBUF_ACTIVE;
+       addr = videobuf_to_dma_contig(layer->next_frm);
+       osd_device->ops.start_layer(osd_device,
+                       layer->layer_info.id,
+                       addr,
+                       disp_obj->cbcr_ofst);
+}
+
+/* interrupt service routine */
+static irqreturn_t venc_isr(int irq, void *arg)
+{
+       struct vpbe_display *disp_dev = (struct vpbe_display *)arg;
+       struct vpbe_layer *layer;
+       static unsigned last_event;
+       unsigned event = 0;
+       int fid;
+       int i;
+
+       if ((NULL == arg) || (NULL == disp_dev->dev[0]))
+               return IRQ_HANDLED;
+
+       if (venc_is_second_field(disp_dev))
+               event |= VENC_SECOND_FIELD;
+       else
+               event |= VENC_FIRST_FIELD;
+
+       if (event == (last_event & ~VENC_END_OF_FRAME)) {
+               /*
+               * If the display is non-interlaced, then we need to flag the
+               * end-of-frame event at every interrupt regardless of the
+               * value of the FIDST bit.  We can conclude that the display is
+               * non-interlaced if the value of the FIDST bit is unchanged
+               * from the previous interrupt.
+               */
+               event |= VENC_END_OF_FRAME;
+       } else if (event == VENC_SECOND_FIELD) {
+               /* end-of-frame for interlaced display */
+               event |= VENC_END_OF_FRAME;
+       }
+       last_event = event;
+
+       for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
+               layer = disp_dev->dev[i];
+               /* If streaming is started in this layer */
+               if (!layer->started)
+                       continue;
+
+               if (layer->layer_first_int) {
+                       layer->layer_first_int = 0;
+                       continue;
+               }
+               /* Check the field format */
+               if ((V4L2_FIELD_NONE == layer->pix_fmt.field) &&
+                       (event & VENC_END_OF_FRAME)) {
+                       /* Progressive mode */
+
+                       vpbe_isr_even_field(disp_dev, layer);
+                       vpbe_isr_odd_field(disp_dev, layer);
+               } else {
+               /* Interlaced mode */
+
+                       layer->field_id ^= 1;
+                       if (event & VENC_FIRST_FIELD)
+                               fid = 0;
+                       else
+                               fid = 1;
+
+                       /*
+                       * If field id does not match with store
+                       * field id
+                       */
+                       if (fid != layer->field_id) {
+                               /* Make them in sync */
+                               layer->field_id = fid;
+                               continue;
+                       }
+                       /*
+                       * device field id and local field id are
+                       * in sync. If this is even field
+                       */
+                       if (0 == fid)
+                               vpbe_isr_even_field(disp_dev, layer);
+                       else  /* odd field */
+                               vpbe_isr_odd_field(disp_dev, layer);
+               }
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * vpbe_buffer_prepare()
+ * This is the callback function called from videobuf_qbuf() function
+ * the buffer is prepared and user space virtual address is converted into
+ * physical address
+ */
+static int vpbe_buffer_prepare(struct videobuf_queue *q,
+                                 struct videobuf_buffer *vb,
+                                 enum v4l2_field field)
+{
+       struct vpbe_fh *fh = q->priv_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       unsigned long addr;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+                               "vpbe_buffer_prepare\n");
+
+       /* If buffer is not initialized, initialize it */
+       if (VIDEOBUF_NEEDS_INIT == vb->state) {
+               vb->width = layer->pix_fmt.width;
+               vb->height = layer->pix_fmt.height;
+               vb->size = layer->pix_fmt.sizeimage;
+               vb->field = field;
+
+               ret = videobuf_iolock(q, vb, NULL);
+               if (ret < 0) {
+                       v4l2_err(&vpbe_dev->v4l2_dev, "Failed to map \
+                               user address\n");
+                       return -EINVAL;
+               }
+
+               addr = videobuf_to_dma_contig(vb);
+
+               if (q->streaming) {
+                       if (!IS_ALIGNED(addr, 8)) {
+                               v4l2_err(&vpbe_dev->v4l2_dev,
+                                       "buffer_prepare:offset is \
+                                       not aligned to 32 bytes\n");
+                               return -EINVAL;
+                       }
+               }
+               vb->state = VIDEOBUF_PREPARED;
+       }
+       return 0;
+}
+
+/*
+ * vpbe_buffer_setup()
+ * This function allocates memory for the buffers
+ */
+static int vpbe_buffer_setup(struct videobuf_queue *q,
+                               unsigned int *count,
+                               unsigned int *size)
+{
+       /* Get the file handle object and layer object */
+       struct vpbe_fh *fh = q->priv_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_buffer_setup\n");
+
+       *size = layer->pix_fmt.sizeimage;
+
+       /* Store number of buffers allocated in numbuffer member */
+       if (*count < VPBE_DEFAULT_NUM_BUFS)
+               *count = layer->numbuffers = VPBE_DEFAULT_NUM_BUFS;
+
+       return 0;
+}
+
+/*
+ * vpbe_buffer_queue()
+ * This function adds the buffer to DMA queue
+ */
+static void vpbe_buffer_queue(struct videobuf_queue *q,
+                                struct videobuf_buffer *vb)
+{
+       /* Get the file handle object and layer object */
+       struct vpbe_fh *fh = q->priv_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_display *disp = fh->disp_dev;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       unsigned long flags;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+                       "vpbe_buffer_queue\n");
+
+       /* add the buffer to the DMA queue */
+       spin_lock_irqsave(&disp->dma_queue_lock, flags);
+       list_add_tail(&vb->queue, &layer->dma_queue);
+       spin_unlock_irqrestore(&disp->dma_queue_lock, flags);
+       /* Change state of the buffer */
+       vb->state = VIDEOBUF_QUEUED;
+}
+
+/*
+ * vpbe_buffer_release()
+ * This function is called from the videobuf layer to free memory allocated to
+ * the buffers
+ */
+static void vpbe_buffer_release(struct videobuf_queue *q,
+                                  struct videobuf_buffer *vb)
+{
+       /* Get the file handle object and layer object */
+       struct vpbe_fh *fh = q->priv_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+                       "vpbe_buffer_release\n");
+
+       if (V4L2_MEMORY_USERPTR != layer->memory)
+               videobuf_dma_contig_free(q, vb);
+
+       vb->state = VIDEOBUF_NEEDS_INIT;
+}
+
+static struct videobuf_queue_ops video_qops = {
+       .buf_setup = vpbe_buffer_setup,
+       .buf_prepare = vpbe_buffer_prepare,
+       .buf_queue = vpbe_buffer_queue,
+       .buf_release = vpbe_buffer_release,
+};
+
+static
+struct vpbe_layer*
+_vpbe_display_get_other_win_layer(struct vpbe_display *disp_dev,
+                       struct vpbe_layer *layer)
+{
+       enum vpbe_display_device_id thiswin, otherwin;
+       thiswin = layer->device_id;
+
+       otherwin = (thiswin == VPBE_DISPLAY_DEVICE_0) ?
+       VPBE_DISPLAY_DEVICE_1 : VPBE_DISPLAY_DEVICE_0;
+       return disp_dev->dev[otherwin];
+}
+
+static int vpbe_set_osd_display_params(struct vpbe_display *disp_dev,
+                       struct vpbe_layer *layer)
+{
+       struct osd_layer_config *cfg  = &layer->layer_info.config;
+       struct osd_state *osd_device = disp_dev->osd_device;
+       struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
+       unsigned long addr;
+       int ret;
+
+       addr = videobuf_to_dma_contig(layer->cur_frm);
+       /* Set address in the display registers */
+       osd_device->ops.start_layer(osd_device,
+                                   layer->layer_info.id,
+                                   addr,
+                                   disp_dev->cbcr_ofst);
+
+       ret = osd_device->ops.enable_layer(osd_device,
+                               layer->layer_info.id, 0);
+       if (ret < 0) {
+               v4l2_err(&vpbe_dev->v4l2_dev,
+                       "Error in enabling osd window layer 0\n");
+               return -1;
+       }
+
+       /* Enable the window */
+       layer->layer_info.enable = 1;
+       if (cfg->pixfmt == PIXFMT_NV12) {
+               struct vpbe_layer *otherlayer =
+                       _vpbe_display_get_other_win_layer(disp_dev, layer);
+
+               ret = osd_device->ops.enable_layer(osd_device,
+                               otherlayer->layer_info.id, 1);
+               if (ret < 0) {
+                       v4l2_err(&vpbe_dev->v4l2_dev,
+                               "Error in enabling osd window layer 1\n");
+                       return -1;
+               }
+               otherlayer->layer_info.enable = 1;
+       }
+       return 0;
+}
+
+static void
+vpbe_disp_calculate_scale_factor(struct vpbe_display *disp_dev,
+                       struct vpbe_layer *layer,
+                       int expected_xsize, int expected_ysize)
+{
+       struct display_layer_info *layer_info = &layer->layer_info;
+       struct v4l2_pix_format *pixfmt = &layer->pix_fmt;
+       struct osd_layer_config *cfg  = &layer->layer_info.config;
+       struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
+       int calculated_xsize;
+       int h_exp = 0;
+       int v_exp = 0;
+       int h_scale;
+       int v_scale;
+
+       v4l2_std_id standard_id = vpbe_dev->current_timings.timings.std_id;
+
+       /*
+        * Application initially set the image format. Current display
+        * size is obtained from the vpbe display controller. expected_xsize
+        * and expected_ysize are set through S_CROP ioctl. Based on this,
+        * driver will calculate the scale factors for vertical and
+        * horizontal direction so that the image is displayed scaled
+        * and expanded. Application uses expansion to display the image
+        * in a square pixel. Otherwise it is displayed using displays
+        * pixel aspect ratio.It is expected that application chooses
+        * the crop coordinates for cropped or scaled display. if crop
+        * size is less than the image size, it is displayed cropped or
+        * it is displayed scaled and/or expanded.
+        *
+        * to begin with, set the crop window same as expected. Later we
+        * will override with scaled window size
+        */
+
+       cfg->xsize = pixfmt->width;
+       cfg->ysize = pixfmt->height;
+       layer_info->h_zoom = ZOOM_X1;   /* no horizontal zoom */
+       layer_info->v_zoom = ZOOM_X1;   /* no horizontal zoom */
+       layer_info->h_exp = H_EXP_OFF;  /* no horizontal zoom */
+       layer_info->v_exp = V_EXP_OFF;  /* no horizontal zoom */
+
+       if (pixfmt->width < expected_xsize) {
+               h_scale = vpbe_dev->current_timings.xres / pixfmt->width;
+               if (h_scale < 2)
+                       h_scale = 1;
+               else if (h_scale >= 4)
+                       h_scale = 4;
+               else
+                       h_scale = 2;
+               cfg->xsize *= h_scale;
+               if (cfg->xsize < expected_xsize) {
+                       if ((standard_id & V4L2_STD_525_60) ||
+                       (standard_id & V4L2_STD_625_50)) {
+                               calculated_xsize = (cfg->xsize *
+                                       VPBE_DISPLAY_H_EXP_RATIO_N) /
+                                       VPBE_DISPLAY_H_EXP_RATIO_D;
+                               if (calculated_xsize <= expected_xsize) {
+                                       h_exp = 1;
+                                       cfg->xsize = calculated_xsize;
+                               }
+                       }
+               }
+               if (h_scale == 2)
+                       layer_info->h_zoom = ZOOM_X2;
+               else if (h_scale == 4)
+                       layer_info->h_zoom = ZOOM_X4;
+               if (h_exp)
+                       layer_info->h_exp = H_EXP_9_OVER_8;
+       } else {
+               /* no scaling, only cropping. Set display area to crop area */
+               cfg->xsize = expected_xsize;
+       }
+
+       if (pixfmt->height < expected_ysize) {
+               v_scale = expected_ysize / pixfmt->height;
+               if (v_scale < 2)
+                       v_scale = 1;
+               else if (v_scale >= 4)
+                       v_scale = 4;
+               else
+                       v_scale = 2;
+               cfg->ysize *= v_scale;
+               if (cfg->ysize < expected_ysize) {
+                       if ((standard_id & V4L2_STD_625_50)) {
+                               calculated_xsize = (cfg->ysize *
+                                       VPBE_DISPLAY_V_EXP_RATIO_N) /
+                                       VPBE_DISPLAY_V_EXP_RATIO_D;
+                               if (calculated_xsize <= expected_ysize) {
+                                       v_exp = 1;
+                                       cfg->ysize = calculated_xsize;
+                               }
+                       }
+               }
+               if (v_scale == 2)
+                       layer_info->v_zoom = ZOOM_X2;
+               else if (v_scale == 4)
+                       layer_info->v_zoom = ZOOM_X4;
+               if (v_exp)
+                       layer_info->h_exp = V_EXP_6_OVER_5;
+       } else {
+               /* no scaling, only cropping. Set display area to crop area */
+               cfg->ysize = expected_ysize;
+       }
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+               "crop display xsize = %d, ysize = %d\n",
+               cfg->xsize, cfg->ysize);
+}
+
+static void vpbe_disp_adj_position(struct vpbe_display *disp_dev,
+                       struct vpbe_layer *layer,
+                       int top, int left)
+{
+       struct osd_layer_config *cfg = &layer->layer_info.config;
+       struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
+
+       cfg->xpos = min((unsigned int)left,
+                       vpbe_dev->current_timings.xres - cfg->xsize);
+       cfg->ypos = min((unsigned int)top,
+                       vpbe_dev->current_timings.yres - cfg->ysize);
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+               "new xpos = %d, ypos = %d\n",
+               cfg->xpos, cfg->ypos);
+}
+
+static void vpbe_disp_check_window_params(struct vpbe_display *disp_dev,
+                       struct v4l2_rect *c)
+{
+       struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
+
+       if ((c->width == 0) ||
+         ((c->width + c->left) > vpbe_dev->current_timings.xres))
+               c->width = vpbe_dev->current_timings.xres - c->left;
+
+       if ((c->height == 0) || ((c->height + c->top) >
+         vpbe_dev->current_timings.yres))
+               c->height = vpbe_dev->current_timings.yres - c->top;
+
+       /* window height must be even for interlaced display */
+       if (vpbe_dev->current_timings.interlaced)
+               c->height &= (~0x01);
+
+}
+
+/**
+ * vpbe_try_format()
+ * If user application provides width and height, and have bytesperline set
+ * to zero, driver calculates bytesperline and sizeimage based on hardware
+ * limits.
+ */
+static int vpbe_try_format(struct vpbe_display *disp_dev,
+                       struct v4l2_pix_format *pixfmt, int check)
+{
+       struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
+       int min_height = 1;
+       int min_width = 32;
+       int max_height;
+       int max_width;
+       int bpp;
+
+       if ((pixfmt->pixelformat != V4L2_PIX_FMT_UYVY) &&
+           (pixfmt->pixelformat != V4L2_PIX_FMT_NV12))
+               /* choose default as V4L2_PIX_FMT_UYVY */
+               pixfmt->pixelformat = V4L2_PIX_FMT_UYVY;
+
+       /* Check the field format */
+       if ((pixfmt->field != V4L2_FIELD_INTERLACED) &&
+               (pixfmt->field != V4L2_FIELD_NONE)) {
+               if (vpbe_dev->current_timings.interlaced)
+                       pixfmt->field = V4L2_FIELD_INTERLACED;
+               else
+                       pixfmt->field = V4L2_FIELD_NONE;
+       }
+
+       if (pixfmt->field == V4L2_FIELD_INTERLACED)
+               min_height = 2;
+
+       if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12)
+               bpp = 1;
+       else
+               bpp = 2;
+
+       max_width = vpbe_dev->current_timings.xres;
+       max_height = vpbe_dev->current_timings.yres;
+
+       min_width /= bpp;
+
+       if (!pixfmt->width || (pixfmt->width < min_width) ||
+               (pixfmt->width > max_width)) {
+               pixfmt->width = vpbe_dev->current_timings.xres;
+       }
+
+       if (!pixfmt->height || (pixfmt->height  < min_height) ||
+               (pixfmt->height  > max_height)) {
+               pixfmt->height = vpbe_dev->current_timings.yres;
+       }
+
+       if (pixfmt->bytesperline < (pixfmt->width * bpp))
+               pixfmt->bytesperline = pixfmt->width * bpp;
+
+       /* Make the bytesperline 32 byte aligned */
+       pixfmt->bytesperline = ((pixfmt->width * bpp + 31) & ~31);
+
+       if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12)
+               pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height +
+                               (pixfmt->bytesperline * pixfmt->height >> 1);
+       else
+               pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
+
+       return 0;
+}
+
+static int vpbe_display_g_priority(struct file *file, void *priv,
+                               enum v4l2_priority *p)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+
+       *p = v4l2_prio_max(&layer->prio);
+
+       return 0;
+}
+
+static int vpbe_display_s_priority(struct file *file, void *priv,
+                               enum v4l2_priority p)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       int ret;
+
+       ret = v4l2_prio_change(&layer->prio, &fh->prio, p);
+
+       return ret;
+}
+
+static int vpbe_display_querycap(struct file *file, void  *priv,
+                              struct v4l2_capability *cap)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+       cap->version = VPBE_DISPLAY_VERSION_CODE;
+       cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+       strlcpy(cap->driver, VPBE_DISPLAY_DRIVER, sizeof(cap->driver));
+       strlcpy(cap->bus_info, "platform", sizeof(cap->bus_info));
+       strlcpy(cap->card, vpbe_dev->cfg->module_name, sizeof(cap->card));
+
+       return 0;
+}
+
+static int vpbe_display_s_crop(struct file *file, void *priv,
+                            struct v4l2_crop *crop)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_display *disp_dev = fh->disp_dev;
+       struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
+       struct osd_layer_config *cfg = &layer->layer_info.config;
+       struct osd_state *osd_device = disp_dev->osd_device;
+       struct v4l2_rect *rect = &crop->c;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+               "VIDIOC_S_CROP, layer id = %d\n", layer->device_id);
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buf type\n");
+               return -EINVAL;
+       }
+
+       if (rect->top < 0)
+               rect->top = 0;
+       if (rect->left < 0)
+               rect->left = 0;
+
+       vpbe_disp_check_window_params(disp_dev, rect);
+
+       osd_device->ops.get_layer_config(osd_device,
+                       layer->layer_info.id, cfg);
+
+       vpbe_disp_calculate_scale_factor(disp_dev, layer,
+                                       rect->width,
+                                       rect->height);
+       vpbe_disp_adj_position(disp_dev, layer, rect->top,
+                                       rect->left);
+       ret = osd_device->ops.set_layer_config(osd_device,
+                               layer->layer_info.id, cfg);
+       if (ret < 0) {
+               v4l2_err(&vpbe_dev->v4l2_dev,
+                       "Error in set layer config:\n");
+               return -EINVAL;
+       }
+
+       /* apply zooming and h or v expansion */
+       osd_device->ops.set_zoom(osd_device,
+                       layer->layer_info.id,
+                       layer->layer_info.h_zoom,
+                       layer->layer_info.v_zoom);
+       ret = osd_device->ops.set_vid_expansion(osd_device,
+                       layer->layer_info.h_exp,
+                       layer->layer_info.v_exp);
+       if (ret < 0) {
+               v4l2_err(&vpbe_dev->v4l2_dev,
+               "Error in set vid expansion:\n");
+               return -EINVAL;
+       }
+
+       if ((layer->layer_info.h_zoom != ZOOM_X1) ||
+               (layer->layer_info.v_zoom != ZOOM_X1) ||
+               (layer->layer_info.h_exp != H_EXP_OFF) ||
+               (layer->layer_info.v_exp != V_EXP_OFF))
+               /* Enable expansion filter */
+               osd_device->ops.set_interpolation_filter(osd_device, 1);
+       else
+               osd_device->ops.set_interpolation_filter(osd_device, 0);
+
+       return 0;
+}
+
+static int vpbe_display_g_crop(struct file *file, void *priv,
+                            struct v4l2_crop *crop)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct osd_layer_config *cfg = &layer->layer_info.config;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       struct osd_state *osd_device = fh->disp_dev->osd_device;
+       struct v4l2_rect *rect = &crop->c;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+                       "VIDIOC_G_CROP, layer id = %d\n",
+                       layer->device_id);
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buf type\n");
+               ret = -EINVAL;
+       }
+       osd_device->ops.get_layer_config(osd_device,
+                               layer->layer_info.id, cfg);
+       rect->top = cfg->ypos;
+       rect->left = cfg->xpos;
+       rect->width = cfg->xsize;
+       rect->height = cfg->ysize;
+
+       return 0;
+}
+
+static int vpbe_display_cropcap(struct file *file, void *priv,
+                             struct v4l2_cropcap *cropcap)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_CROPCAP ioctl\n");
+
+       cropcap->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       cropcap->bounds.left = 0;
+       cropcap->bounds.top = 0;
+       cropcap->bounds.width = vpbe_dev->current_timings.xres;
+       cropcap->bounds.height = vpbe_dev->current_timings.yres;
+       cropcap->pixelaspect = vpbe_dev->current_timings.aspect;
+       cropcap->defrect = cropcap->bounds;
+       return 0;
+}
+
+static int vpbe_display_g_fmt(struct file *file, void *priv,
+                               struct v4l2_format *fmt)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+                       "VIDIOC_G_FMT, layer id = %d\n",
+                       layer->device_id);
+
+       /* If buffer type is video output */
+       if (V4L2_BUF_TYPE_VIDEO_OUTPUT != fmt->type) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "invalid type\n");
+               return -EINVAL;
+       }
+       /* Fill in the information about format */
+       fmt->fmt.pix = layer->pix_fmt;
+
+       return 0;
+}
+
+static int vpbe_display_enum_fmt(struct file *file, void  *priv,
+                                  struct v4l2_fmtdesc *fmt)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       unsigned int index = 0;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+                               "VIDIOC_ENUM_FMT, layer id = %d\n",
+                               layer->device_id);
+       if (fmt->index > 1) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Invalid format index\n");
+               return -EINVAL;
+       }
+
+       /* Fill in the information about format */
+       index = fmt->index;
+       memset(fmt, 0, sizeof(*fmt));
+       fmt->index = index;
+       fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       if (index == 0) {
+               strcpy(fmt->description, "YUV 4:2:2 - UYVY");
+               fmt->pixelformat = V4L2_PIX_FMT_UYVY;
+       } else {
+               strcpy(fmt->description, "Y/CbCr 4:2:0");
+               fmt->pixelformat = V4L2_PIX_FMT_NV12;
+       }
+
+       return 0;
+}
+
+static int vpbe_display_s_fmt(struct file *file, void *priv,
+                               struct v4l2_format *fmt)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_display *disp_dev = fh->disp_dev;
+       struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
+       struct osd_layer_config *cfg  = &layer->layer_info.config;
+       struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+       struct osd_state *osd_device = disp_dev->osd_device;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+                       "VIDIOC_S_FMT, layer id = %d\n",
+                       layer->device_id);
+
+       /* If streaming is started, return error */
+       if (layer->started) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
+               return -EBUSY;
+       }
+       if (V4L2_BUF_TYPE_VIDEO_OUTPUT != fmt->type) {
+               v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "invalid type\n");
+               return -EINVAL;
+       }
+       /* Check for valid pixel format */
+       ret = vpbe_try_format(disp_dev, pixfmt, 1);
+       if (ret)
+               return ret;
+
+       /* YUV420 is requested, check availability of the
+       other video window */
+
+       layer->pix_fmt = *pixfmt;
+
+       /* Get osd layer config */
+       osd_device->ops.get_layer_config(osd_device,
+                       layer->layer_info.id, cfg);
+       /* Store the pixel format in the layer object */
+       cfg->xsize = pixfmt->width;
+       cfg->ysize = pixfmt->height;
+       cfg->line_length = pixfmt->bytesperline;
+       cfg->ypos = 0;
+       cfg->xpos = 0;
+       cfg->interlaced = vpbe_dev->current_timings.interlaced;
+
+       if (V4L2_PIX_FMT_UYVY == pixfmt->pixelformat)
+               cfg->pixfmt = PIXFMT_YCbCrI;
+
+       /* Change of the default pixel format for both video windows */
+       if (V4L2_PIX_FMT_NV12 == pixfmt->pixelformat) {
+               struct vpbe_layer *otherlayer;
+               cfg->pixfmt = PIXFMT_NV12;
+               otherlayer = _vpbe_display_get_other_win_layer(disp_dev,
+                                                               layer);
+               otherlayer->layer_info.config.pixfmt = PIXFMT_NV12;
+       }
+
+       /* Set the layer config in the osd window */
+       ret = osd_device->ops.set_layer_config(osd_device,
+                               layer->layer_info.id, cfg);
+       if (ret < 0) {
+               v4l2_err(&vpbe_dev->v4l2_dev,
+                               "Error in S_FMT params:\n");
+               return -EINVAL;
+       }
+
+       /* Readback and fill the local copy of current pix format */
+       osd_device->ops.get_layer_config(osd_device,
+                       layer->layer_info.id, cfg);
+
+       return 0;
+}
+
+static int vpbe_display_try_fmt(struct file *file, void *priv,
+                                 struct v4l2_format *fmt)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_display *disp_dev = fh->disp_dev;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_TRY_FMT\n");
+
+       if (V4L2_BUF_TYPE_VIDEO_OUTPUT != fmt->type) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "invalid type\n");
+               return -EINVAL;
+       }
+
+       /* Check for valid field format */
+       return  vpbe_try_format(disp_dev, pixfmt, 0);
+
+}
+
+/**
+ * vpbe_display_s_std - Set the given standard in the encoder
+ *
+ * Sets the standard if supported by the current encoder. Return the status.
+ * 0 - success & -EINVAL on error
+ */
+static int vpbe_display_s_std(struct file *file, void *priv,
+                               v4l2_std_id *std_id)
+{
+       struct vpbe_fh *fh = priv;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_STD\n");
+
+       /* If streaming is started, return error */
+       if (layer->started) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
+               return -EBUSY;
+       }
+       if (NULL != vpbe_dev->ops.s_std) {
+               ret = vpbe_dev->ops.s_std(vpbe_dev, std_id);
+               if (ret) {
+                       v4l2_err(&vpbe_dev->v4l2_dev,
+                       "Failed to set standard for sub devices\n");
+                       return -EINVAL;
+               }
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * vpbe_display_g_std - Get the standard in the current encoder
+ *
+ * Get the standard in the current encoder. Return the status. 0 - success
+ * -EINVAL on error
+ */
+static int vpbe_display_g_std(struct file *file, void *priv,
+                               v4l2_std_id *std_id)
+{
+       struct vpbe_fh *fh = priv;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_STD\n");
+
+       /* Get the standard from the current encoder */
+       if (vpbe_dev->current_timings.timings_type & VPBE_ENC_STD) {
+               *std_id = vpbe_dev->current_timings.timings.std_id;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+/**
+ * vpbe_display_enum_output - enumerate outputs
+ *
+ * Enumerates the outputs available at the vpbe display
+ * returns the status, -EINVAL if end of output list
+ */
+static int vpbe_display_enum_output(struct file *file, void *priv,
+                                   struct v4l2_output *output)
+{
+       struct vpbe_fh *fh = priv;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_OUTPUT\n");
+
+       /* Enumerate outputs */
+
+       if (NULL == vpbe_dev->ops.enum_outputs)
+               return -EINVAL;
+
+       ret = vpbe_dev->ops.enum_outputs(vpbe_dev, output);
+       if (ret) {
+               v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+                       "Failed to enumerate outputs\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * vpbe_display_s_output - Set output to
+ * the output specified by the index
+ */
+static int vpbe_display_s_output(struct file *file, void *priv,
+                               unsigned int i)
+{
+       struct vpbe_fh *fh = priv;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_OUTPUT\n");
+       /* If streaming is started, return error */
+       if (layer->started) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
+               return -EBUSY;
+       }
+       if (NULL == vpbe_dev->ops.set_output)
+               return -EINVAL;
+
+       ret = vpbe_dev->ops.set_output(vpbe_dev, i);
+       if (ret) {
+               v4l2_err(&vpbe_dev->v4l2_dev,
+                       "Failed to set output for sub devices\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * vpbe_display_g_output - Get output from subdevice
+ * for a given by the index
+ */
+static int vpbe_display_g_output(struct file *file, void *priv,
+                               unsigned int *i)
+{
+       struct vpbe_fh *fh = priv;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_OUTPUT\n");
+       /* Get the standard from the current encoder */
+       *i = vpbe_dev->current_out_index;
+
+       return 0;
+}
+
+/**
+ * vpbe_display_enum_dv_presets - Enumerate the dv presets
+ *
+ * enum the preset in the current encoder. Return the status. 0 - success
+ * -EINVAL on error
+ */
+static int
+vpbe_display_enum_dv_presets(struct file *file, void *priv,
+                       struct v4l2_dv_enum_preset *preset)
+{
+       struct vpbe_fh *fh = priv;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_PRESETS\n");
+
+       /* Enumerate outputs */
+       if (NULL == vpbe_dev->ops.enum_dv_presets)
+               return -EINVAL;
+
+       ret = vpbe_dev->ops.enum_dv_presets(vpbe_dev, preset);
+       if (ret) {
+               v4l2_err(&vpbe_dev->v4l2_dev,
+                       "Failed to enumerate dv presets info\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * vpbe_display_s_dv_preset - Set the dv presets
+ *
+ * Set the preset in the current encoder. Return the status. 0 - success
+ * -EINVAL on error
+ */
+static int
+vpbe_display_s_dv_preset(struct file *file, void *priv,
+                               struct v4l2_dv_preset *preset)
+{
+       struct vpbe_fh *fh = priv;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_PRESETS\n");
+
+
+       /* If streaming is started, return error */
+       if (layer->started) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
+               return -EBUSY;
+       }
+
+       /* Set the given standard in the encoder */
+       if (NULL != vpbe_dev->ops.s_dv_preset)
+               return -EINVAL;
+
+       ret = vpbe_dev->ops.s_dv_preset(vpbe_dev, preset);
+       if (ret) {
+               v4l2_err(&vpbe_dev->v4l2_dev,
+                       "Failed to set the dv presets info\n");
+               return -EINVAL;
+       }
+       /* set the current norm to zero to be consistent. If STD is used
+        * v4l2 layer will set the norm properly on successful s_std call
+        */
+       layer->video_dev.current_norm = 0;
+
+       return 0;
+}
+
+/**
+ * vpbe_display_g_dv_preset - Set the dv presets
+ *
+ * Get the preset in the current encoder. Return the status. 0 - success
+ * -EINVAL on error
+ */
+static int
+vpbe_display_g_dv_preset(struct file *file, void *priv,
+                               struct v4l2_dv_preset *dv_preset)
+{
+       struct vpbe_fh *fh = priv;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_PRESETS\n");
+
+       /* Get the given standard in the encoder */
+
+       if (vpbe_dev->current_timings.timings_type &
+                               VPBE_ENC_DV_PRESET) {
+               dv_preset->preset =
+                       vpbe_dev->current_timings.timings.dv_preset;
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vpbe_display_streamoff(struct file *file, void *priv,
+                               enum v4l2_buf_type buf_type)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       struct osd_state *osd_device = fh->disp_dev->osd_device;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+                       "VIDIOC_STREAMOFF,layer id = %d\n",
+                       layer->device_id);
+
+       if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf_type) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+               return -EINVAL;
+       }
+
+       /* If io is allowed for this file handle, return error */
+       if (!fh->io_allowed) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
+               return -EACCES;
+       }
+
+       /* If streaming is not started, return error */
+       if (!layer->started) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "streaming not started in layer"
+                       " id = %d\n", layer->device_id);
+               return -EINVAL;
+       }
+
+       osd_device->ops.disable_layer(osd_device,
+                       layer->layer_info.id);
+       layer->started = 0;
+       ret = videobuf_streamoff(&layer->buffer_queue);
+
+       return ret;
+}
+
+static int vpbe_display_streamon(struct file *file, void *priv,
+                        enum v4l2_buf_type buf_type)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_display *disp_dev = fh->disp_dev;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       struct osd_state *osd_device = disp_dev->osd_device;
+       int ret;
+
+       osd_device->ops.disable_layer(osd_device,
+                       layer->layer_info.id);
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_STREAMON, layerid=%d\n",
+                                               layer->device_id);
+
+       if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf_type) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+               return -EINVAL;
+       }
+
+       /* If file handle is not allowed IO, return error */
+       if (!fh->io_allowed) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
+               return -EACCES;
+       }
+       /* If Streaming is already started, return error */
+       if (layer->started) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "layer is already streaming\n");
+               return -EBUSY;
+       }
+
+       /*
+        * Call videobuf_streamon to start streaming
+        * in videobuf
+        */
+       ret = videobuf_streamon(&layer->buffer_queue);
+       if (ret) {
+               v4l2_err(&vpbe_dev->v4l2_dev,
+               "error in videobuf_streamon\n");
+               return ret;
+       }
+       /* If buffer queue is empty, return error */
+       if (list_empty(&layer->dma_queue)) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "buffer queue is empty\n");
+               goto streamoff;
+       }
+       /* Get the next frame from the buffer queue */
+       layer->next_frm = layer->cur_frm = list_entry(layer->dma_queue.next,
+                               struct videobuf_buffer, queue);
+       /* Remove buffer from the buffer queue */
+       list_del(&layer->cur_frm->queue);
+       /* Mark state of the current frame to active */
+       layer->cur_frm->state = VIDEOBUF_ACTIVE;
+       /* Initialize field_id and started member */
+       layer->field_id = 0;
+
+       /* Set parameters in OSD and VENC */
+       ret = vpbe_set_osd_display_params(disp_dev, layer);
+       if (ret < 0)
+               goto streamoff;
+
+       /*
+        * if request format is yuv420 semiplanar, need to
+        * enable both video windows
+        */
+       layer->started = 1;
+
+       layer->layer_first_int = 1;
+
+       return ret;
+streamoff:
+       ret = videobuf_streamoff(&layer->buffer_queue);
+       return ret;
+}
+
+static int vpbe_display_dqbuf(struct file *file, void *priv,
+                     struct v4l2_buffer *buf)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+               "VIDIOC_DQBUF, layer id = %d\n",
+               layer->device_id);
+
+       if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf->type) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+               return -EINVAL;
+       }
+       /* If this file handle is not allowed to do IO, return error */
+       if (!fh->io_allowed) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
+               return -EACCES;
+       }
+       if (file->f_flags & O_NONBLOCK)
+               /* Call videobuf_dqbuf for non blocking mode */
+               ret = videobuf_dqbuf(&layer->buffer_queue, buf, 1);
+       else
+               /* Call videobuf_dqbuf for blocking mode */
+               ret = videobuf_dqbuf(&layer->buffer_queue, buf, 0);
+
+       return ret;
+}
+
+static int vpbe_display_qbuf(struct file *file, void *priv,
+                    struct v4l2_buffer *p)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+               "VIDIOC_QBUF, layer id = %d\n",
+               layer->device_id);
+
+       if (V4L2_BUF_TYPE_VIDEO_OUTPUT != p->type) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+               return -EINVAL;
+       }
+
+       /* If this file handle is not allowed to do IO, return error */
+       if (!fh->io_allowed) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
+               return -EACCES;
+       }
+
+       return videobuf_qbuf(&layer->buffer_queue, p);
+}
+
+static int vpbe_display_querybuf(struct file *file, void *priv,
+                        struct v4l2_buffer *buf)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+               "VIDIOC_QUERYBUF, layer id = %d\n",
+               layer->device_id);
+
+       if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf->type) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+               return -EINVAL;
+       }
+
+       /* Call videobuf_querybuf to get information */
+       ret = videobuf_querybuf(&layer->buffer_queue, buf);
+
+       return ret;
+}
+
+static int vpbe_display_reqbufs(struct file *file, void *priv,
+                       struct v4l2_requestbuffers *req_buf)
+{
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_reqbufs\n");
+
+       if (V4L2_BUF_TYPE_VIDEO_OUTPUT != req_buf->type) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+               return -EINVAL;
+       }
+
+       /* If io users of the layer is not zero, return error */
+       if (0 != layer->io_usrs) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "not IO user\n");
+               return -EBUSY;
+       }
+       /* Initialize videobuf queue as per the buffer type */
+       videobuf_queue_dma_contig_init(&layer->buffer_queue,
+                               &video_qops,
+                               vpbe_dev->pdev,
+                               &layer->irqlock,
+                               V4L2_BUF_TYPE_VIDEO_OUTPUT,
+                               layer->pix_fmt.field,
+                               sizeof(struct videobuf_buffer),
+                               fh, NULL);
+
+       /* Set io allowed member of file handle to TRUE */
+       fh->io_allowed = 1;
+       /* Increment io usrs member of layer object to 1 */
+       layer->io_usrs = 1;
+       /* Store type of memory requested in layer object */
+       layer->memory = req_buf->memory;
+       /* Initialize buffer queue */
+       INIT_LIST_HEAD(&layer->dma_queue);
+       /* Allocate buffers */
+       ret = videobuf_reqbufs(&layer->buffer_queue, req_buf);
+
+       return ret;
+}
+
+/*
+ * vpbe_display_mmap()
+ * It is used to map kernel space buffers into user spaces
+ */
+static int vpbe_display_mmap(struct file *filep, struct vm_area_struct *vma)
+{
+       /* Get the layer object and file handle object */
+       struct vpbe_fh *fh = filep->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_mmap\n");
+
+       return videobuf_mmap_mapper(&layer->buffer_queue, vma);
+}
+
+/* vpbe_display_poll(): It is used for select/poll system call
+ */
+static unsigned int vpbe_display_poll(struct file *filep, poll_table *wait)
+{
+       struct vpbe_fh *fh = filep->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       unsigned int err = 0;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_poll\n");
+       if (layer->started)
+               err = videobuf_poll_stream(filep, &layer->buffer_queue, wait);
+       return err;
+}
+
+/*
+ * vpbe_display_open()
+ * It creates object of file handle structure and stores it in private_data
+ * member of filepointer
+ */
+static int vpbe_display_open(struct file *file)
+{
+       struct vpbe_fh *fh = NULL;
+       struct vpbe_layer *layer = video_drvdata(file);
+       struct vpbe_display *disp_dev = layer->disp_dev;
+       struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
+       struct osd_state *osd_device = disp_dev->osd_device;
+       int err;
+
+       /* Allocate memory for the file handle object */
+       fh = kmalloc(sizeof(struct vpbe_fh), GFP_KERNEL);
+       if (fh == NULL) {
+               v4l2_err(&vpbe_dev->v4l2_dev,
+                       "unable to allocate memory for file handle object\n");
+               return -ENOMEM;
+       }
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+                       "vpbe display open plane = %d\n",
+                       layer->device_id);
+
+       /* store pointer to fh in private_data member of filep */
+       file->private_data = fh;
+       fh->layer = layer;
+       fh->disp_dev = disp_dev;
+
+       if (!layer->usrs) {
+
+               /* First claim the layer for this device */
+               err = osd_device->ops.request_layer(osd_device,
+                                               layer->layer_info.id);
+               if (err < 0) {
+                       /* Couldn't get layer */
+                       v4l2_err(&vpbe_dev->v4l2_dev,
+                               "Display Manager failed to allocate layer\n");
+                       kfree(fh);
+                       return -EINVAL;
+               }
+       }
+       /* Increment layer usrs counter */
+       layer->usrs++;
+       /* Set io_allowed member to false */
+       fh->io_allowed = 0;
+       /* Initialize priority of this instance to default priority */
+       fh->prio = V4L2_PRIORITY_UNSET;
+       v4l2_prio_open(&layer->prio, &fh->prio);
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+                       "vpbe display device opened successfully\n");
+       return 0;
+}
+
+/*
+ * vpbe_display_release()
+ * This function deletes buffer queue, frees the buffers and the davinci
+ * display file * handle
+ */
+static int vpbe_display_release(struct file *file)
+{
+       /* Get the layer object and file handle object */
+       struct vpbe_fh *fh = file->private_data;
+       struct vpbe_layer *layer = fh->layer;
+       struct osd_layer_config *cfg  = &layer->layer_info.config;
+       struct vpbe_display *disp_dev = fh->disp_dev;
+       struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
+       struct osd_state *osd_device = disp_dev->osd_device;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_release\n");
+
+       /* if this instance is doing IO */
+       if (fh->io_allowed) {
+               /* Reset io_usrs member of layer object */
+               layer->io_usrs = 0;
+
+               osd_device->ops.disable_layer(osd_device,
+                               layer->layer_info.id);
+               layer->started = 0;
+               /* Free buffers allocated */
+               videobuf_queue_cancel(&layer->buffer_queue);
+               videobuf_mmap_free(&layer->buffer_queue);
+       }
+
+       /* Decrement layer usrs counter */
+       layer->usrs--;
+       /* If this file handle has initialize encoder device, reset it */
+       if (!layer->usrs) {
+               if (cfg->pixfmt == PIXFMT_NV12) {
+                       struct vpbe_layer *otherlayer;
+                       otherlayer =
+                       _vpbe_display_get_other_win_layer(disp_dev, layer);
+                       osd_device->ops.disable_layer(osd_device,
+                                       otherlayer->layer_info.id);
+                       osd_device->ops.release_layer(osd_device,
+                                       otherlayer->layer_info.id);
+               }
+               osd_device->ops.disable_layer(osd_device,
+                               layer->layer_info.id);
+               osd_device->ops.release_layer(osd_device,
+                               layer->layer_info.id);
+       }
+       /* Close the priority */
+       v4l2_prio_close(&layer->prio, fh->prio);
+       file->private_data = NULL;
+
+       /* Free memory allocated to file handle object */
+       kfree(fh);
+
+       disp_dev->cbcr_ofst = 0;
+
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vpbe_display_g_register(struct file *file, void *priv,
+                       struct v4l2_dbg_register *reg)
+{
+       struct v4l2_dbg_match *match = &reg->match;
+
+       if (match->type >= 2) {
+               v4l2_subdev_call(vpbe_dev->venc,
+                                core,
+                                g_register,
+                                reg);
+       }
+
+       return 0;
+}
+
+static int vpbe_display_s_register(struct file *file, void *priv,
+                       struct v4l2_dbg_register *reg)
+{
+       return 0;
+}
+#endif
+
+/* vpbe capture ioctl operations */
+static const struct v4l2_ioctl_ops vpbe_ioctl_ops = {
+       .vidioc_querycap         = vpbe_display_querycap,
+       .vidioc_g_fmt_vid_out    = vpbe_display_g_fmt,
+       .vidioc_enum_fmt_vid_out = vpbe_display_enum_fmt,
+       .vidioc_s_fmt_vid_out    = vpbe_display_s_fmt,
+       .vidioc_try_fmt_vid_out  = vpbe_display_try_fmt,
+       .vidioc_reqbufs          = vpbe_display_reqbufs,
+       .vidioc_querybuf         = vpbe_display_querybuf,
+       .vidioc_qbuf             = vpbe_display_qbuf,
+       .vidioc_dqbuf            = vpbe_display_dqbuf,
+       .vidioc_streamon         = vpbe_display_streamon,
+       .vidioc_streamoff        = vpbe_display_streamoff,
+       .vidioc_cropcap          = vpbe_display_cropcap,
+       .vidioc_g_crop           = vpbe_display_g_crop,
+       .vidioc_s_crop           = vpbe_display_s_crop,
+       .vidioc_g_priority       = vpbe_display_g_priority,
+       .vidioc_s_priority       = vpbe_display_s_priority,
+       .vidioc_s_std            = vpbe_display_s_std,
+       .vidioc_g_std            = vpbe_display_g_std,
+       .vidioc_enum_output      = vpbe_display_enum_output,
+       .vidioc_s_output         = vpbe_display_s_output,
+       .vidioc_g_output         = vpbe_display_g_output,
+       .vidioc_s_dv_preset      = vpbe_display_s_dv_preset,
+       .vidioc_g_dv_preset      = vpbe_display_g_dv_preset,
+       .vidioc_enum_dv_presets  = vpbe_display_enum_dv_presets,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register       = vpbe_display_g_register,
+       .vidioc_s_register       = vpbe_display_s_register,
+#endif
+};
+
+static struct v4l2_file_operations vpbe_fops = {
+       .owner = THIS_MODULE,
+       .open = vpbe_display_open,
+       .release = vpbe_display_release,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap = vpbe_display_mmap,
+       .poll = vpbe_display_poll
+};
+
+static int vpbe_device_get(struct device *dev, void *data)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct vpbe_display *vpbe_disp  = data;
+
+       if (strcmp("vpbe_controller", pdev->name) == 0)
+               vpbe_disp->vpbe_dev = platform_get_drvdata(pdev);
+
+       if (strcmp("vpbe-osd", pdev->name) == 0)
+               vpbe_disp->osd_device = platform_get_drvdata(pdev);
+
+       return 0;
+}
+
+static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev,
+                                    struct platform_device *pdev)
+{
+       struct vpbe_layer *vpbe_display_layer = NULL;
+       struct video_device *vbd = NULL;
+
+       /* Allocate memory for four plane display objects */
+
+       disp_dev->dev[i] =
+               kzalloc(sizeof(struct vpbe_layer), GFP_KERNEL);
+
+       /* If memory allocation fails, return error */
+       if (!disp_dev->dev[i]) {
+               printk(KERN_ERR "ran out of memory\n");
+               return  -ENOMEM;
+       }
+       spin_lock_init(&disp_dev->dev[i]->irqlock);
+       mutex_init(&disp_dev->dev[i]->opslock);
+
+       /* Get the pointer to the layer object */
+       vpbe_display_layer = disp_dev->dev[i];
+       vbd = &vpbe_display_layer->video_dev;
+       /* Initialize field of video device */
+       vbd->release    = video_device_release_empty;
+       vbd->fops       = &vpbe_fops;
+       vbd->ioctl_ops  = &vpbe_ioctl_ops;
+       vbd->minor      = -1;
+       vbd->v4l2_dev   = &disp_dev->vpbe_dev->v4l2_dev;
+       vbd->lock       = &vpbe_display_layer->opslock;
+
+       if (disp_dev->vpbe_dev->current_timings.timings_type &
+                       VPBE_ENC_STD) {
+               vbd->tvnorms = (V4L2_STD_525_60 | V4L2_STD_625_50);
+               vbd->current_norm =
+                       disp_dev->vpbe_dev->
+                       current_timings.timings.std_id;
+       } else
+               vbd->current_norm = 0;
+
+       snprintf(vbd->name, sizeof(vbd->name),
+                       "DaVinci_VPBE Display_DRIVER_V%d.%d.%d",
+                       (VPBE_DISPLAY_VERSION_CODE >> 16) & 0xff,
+                       (VPBE_DISPLAY_VERSION_CODE >> 8) & 0xff,
+                       (VPBE_DISPLAY_VERSION_CODE) & 0xff);
+
+       vpbe_display_layer->device_id = i;
+
+       vpbe_display_layer->layer_info.id =
+               ((i == VPBE_DISPLAY_DEVICE_0) ? WIN_VID0 : WIN_VID1);
+
+       /* Initialize prio member of layer object */
+       v4l2_prio_init(&vpbe_display_layer->prio);
+
+       return 0;
+}
+
+static __devinit int register_device(struct vpbe_layer *vpbe_display_layer,
+                                       struct vpbe_display *disp_dev,
+                                       struct platform_device *pdev) {
+       int err;
+
+       v4l2_info(&disp_dev->vpbe_dev->v4l2_dev,
+                 "Trying to register VPBE display device.\n");
+       v4l2_info(&disp_dev->vpbe_dev->v4l2_dev,
+                 "layer=%x,layer->video_dev=%x\n",
+                 (int)vpbe_display_layer,
+                 (int)&vpbe_display_layer->video_dev);
+
+       err = video_register_device(&vpbe_display_layer->video_dev,
+                                   VFL_TYPE_GRABBER,
+                                   -1);
+       if (err)
+               return -ENODEV;
+
+       vpbe_display_layer->disp_dev = disp_dev;
+       /* set the driver data in platform device */
+       platform_set_drvdata(pdev, disp_dev);
+       video_set_drvdata(&vpbe_display_layer->video_dev,
+                         vpbe_display_layer);
+
+       return 0;
+}
+
+
+
+/*
+ * vpbe_display_probe()
+ * This function creates device entries by register itself to the V4L2 driver
+ * and initializes fields of each layer objects
+ */
+static __devinit int vpbe_display_probe(struct platform_device *pdev)
+{
+       struct vpbe_layer *vpbe_display_layer;
+       struct vpbe_display *disp_dev;
+       struct resource *res = NULL;
+       int k;
+       int i;
+       int err;
+       int irq;
+
+       printk(KERN_DEBUG "vpbe_display_probe\n");
+       /* Allocate memory for vpbe_display */
+       disp_dev = kzalloc(sizeof(struct vpbe_display), GFP_KERNEL);
+       if (!disp_dev) {
+               printk(KERN_ERR "ran out of memory\n");
+               return -ENOMEM;
+       }
+
+       spin_lock_init(&disp_dev->dma_queue_lock);
+       /*
+        * Scan all the platform devices to find the vpbe
+        * controller device and get the vpbe_dev object
+        */
+       err = bus_for_each_dev(&platform_bus_type, NULL, disp_dev,
+                       vpbe_device_get);
+       if (err < 0)
+               return err;
+       /* Initialize the vpbe display controller */
+       if (NULL != disp_dev->vpbe_dev->ops.initialize) {
+               err = disp_dev->vpbe_dev->ops.initialize(&pdev->dev,
+                                                        disp_dev->vpbe_dev);
+               if (err) {
+                       v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
+                                       "Error initing vpbe\n");
+                       err = -ENOMEM;
+                       goto probe_out;
+               }
+       }
+
+       for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
+               if (init_vpbe_layer(i, disp_dev, pdev)) {
+                       err = -ENODEV;
+                       goto probe_out;
+               }
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
+                        "Unable to get VENC interrupt resource\n");
+               err = -ENODEV;
+               goto probe_out;
+       }
+
+       irq = res->start;
+       if (request_irq(irq, venc_isr,  IRQF_DISABLED, VPBE_DISPLAY_DRIVER,
+               disp_dev)) {
+               v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
+                               "Unable to request interrupt\n");
+               err = -ENODEV;
+               goto probe_out;
+       }
+
+       for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
+               if (register_device(disp_dev->dev[i], disp_dev, pdev)) {
+                       err = -ENODEV;
+                       goto probe_out;
+               }
+       }
+
+       printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n");
+       return 0;
+
+probe_out:
+       free_irq(res->start, disp_dev);
+       for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) {
+               /* Get the pointer to the layer object */
+               vpbe_display_layer = disp_dev->dev[k];
+               /* Unregister video device */
+               if (vpbe_display_layer) {
+                       video_unregister_device(
+                               &vpbe_display_layer->video_dev);
+                               kfree(disp_dev->dev[k]);
+               }
+       }
+       kfree(disp_dev);
+       return err;
+}
+
+/*
+ * vpbe_display_remove()
+ * It un-register hardware layer from V4L2 driver
+ */
+static int vpbe_display_remove(struct platform_device *pdev)
+{
+       struct vpbe_layer *vpbe_display_layer;
+       struct vpbe_display *disp_dev = platform_get_drvdata(pdev);
+       struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
+       struct resource *res;
+       int i;
+
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_remove\n");
+
+       /* unregister irq */
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       free_irq(res->start, disp_dev);
+
+       /* deinitialize the vpbe display controller */
+       if (NULL != vpbe_dev->ops.deinitialize)
+               vpbe_dev->ops.deinitialize(&pdev->dev, vpbe_dev);
+       /* un-register device */
+       for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
+               /* Get the pointer to the layer object */
+               vpbe_display_layer = disp_dev->dev[i];
+               /* Unregister video device */
+               video_unregister_device(&vpbe_display_layer->video_dev);
+
+       }
+       for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
+               kfree(disp_dev->dev[i]);
+               disp_dev->dev[i] = NULL;
+       }
+
+       return 0;
+}
+
+static struct platform_driver vpbe_display_driver = {
+       .driver = {
+               .name = VPBE_DISPLAY_DRIVER,
+               .owner = THIS_MODULE,
+               .bus = &platform_bus_type,
+       },
+       .probe = vpbe_display_probe,
+       .remove = __devexit_p(vpbe_display_remove),
+};
+
+/*
+ * vpbe_display_init()
+ * This function registers device and driver to the kernel, requests irq
+ * handler and allocates memory for layer objects
+ */
+static __devinit int vpbe_display_init(void)
+{
+       int err;
+
+       printk(KERN_DEBUG "vpbe_display_init\n");
+
+       /* Register driver to the kernel */
+       err = platform_driver_register(&vpbe_display_driver);
+       if (0 != err)
+               return err;
+
+       printk(KERN_DEBUG "vpbe_display_init:"
+                       "VPBE V4L2 Display Driver V1.0 loaded\n");
+       return 0;
+}
+
+/*
+ * vpbe_display_cleanup()
+ * This function un-registers device and driver to the kernel, frees requested
+ * irq handler and de-allocates memory allocated for layer objects.
+ */
+static void vpbe_display_cleanup(void)
+{
+       printk(KERN_DEBUG "vpbe_display_cleanup\n");
+
+       /* platform driver unregister */
+       platform_driver_unregister(&vpbe_display_driver);
+}
+
+/* Function for module initialization and cleanup */
+module_init(vpbe_display_init);
+module_exit(vpbe_display_cleanup);
+
+MODULE_DESCRIPTION("TI DM644x/DM355/DM365 VPBE Display controller");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/media/video/davinci/vpbe_osd.c b/drivers/media/video/davinci/vpbe_osd.c
new file mode 100644 (file)
index 0000000..5352884
--- /dev/null
@@ -0,0 +1,1231 @@
+/*
+ * Copyright (C) 2007-2010 Texas Instruments Inc
+ * Copyright (C) 2007 MontaVista Software, Inc.
+ *
+ * Andy Lowe (alowe@mvista.com), MontaVista Software
+ * - Initial version
+ * Murali Karicheri (mkaricheri@gmail.com), Texas Instruments Ltd.
+ * - ported to sub device interface
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+
+#include <mach/io.h>
+#include <mach/cputype.h>
+#include <mach/hardware.h>
+
+#include <media/davinci/vpss.h>
+#include <media/v4l2-device.h>
+#include <media/davinci/vpbe_types.h>
+#include <media/davinci/vpbe_osd.h>
+
+#include <linux/io.h>
+#include "vpbe_osd_regs.h"
+
+#define MODULE_NAME    VPBE_OSD_SUBDEV_NAME
+
+/* register access routines */
+static inline u32 osd_read(struct osd_state *sd, u32 offset)
+{
+       struct osd_state *osd = sd;
+
+       return readl(osd->osd_base + offset);
+}
+
+static inline u32 osd_write(struct osd_state *sd, u32 val, u32 offset)
+{
+       struct osd_state *osd = sd;
+
+       writel(val, osd->osd_base + offset);
+
+       return val;
+}
+
+static inline u32 osd_set(struct osd_state *sd, u32 mask, u32 offset)
+{
+       struct osd_state *osd = sd;
+
+       u32 addr = osd->osd_base + offset;
+       u32 val = readl(addr) | mask;
+
+       writel(val, addr);
+
+       return val;
+}
+
+static inline u32 osd_clear(struct osd_state *sd, u32 mask, u32 offset)
+{
+       struct osd_state *osd = sd;
+
+       u32 addr = osd->osd_base + offset;
+       u32 val = readl(addr) & ~mask;
+
+       writel(val, addr);
+
+       return val;
+}
+
+static inline u32 osd_modify(struct osd_state *sd, u32 mask, u32 val,
+                                u32 offset)
+{
+       struct osd_state *osd = sd;
+
+       u32 addr = osd->osd_base + offset;
+       u32 new_val = (readl(addr) & ~mask) | (val & mask);
+
+       writel(new_val, addr);
+
+       return new_val;
+}
+
+/* define some macros for layer and pixfmt classification */
+#define is_osd_win(layer) (((layer) == WIN_OSD0) || ((layer) == WIN_OSD1))
+#define is_vid_win(layer) (((layer) == WIN_VID0) || ((layer) == WIN_VID1))
+#define is_rgb_pixfmt(pixfmt) \
+       (((pixfmt) == PIXFMT_RGB565) || ((pixfmt) == PIXFMT_RGB888))
+#define is_yc_pixfmt(pixfmt) \
+       (((pixfmt) == PIXFMT_YCbCrI) || ((pixfmt) == PIXFMT_YCrCbI) || \
+       ((pixfmt) == PIXFMT_NV12))
+#define MAX_WIN_SIZE OSD_VIDWIN0XP_V0X
+#define MAX_LINE_LENGTH (OSD_VIDWIN0OFST_V0LO << 5)
+
+/**
+ * _osd_dm6446_vid0_pingpong() - field inversion fix for DM6446
+ * @sd - ptr to struct osd_state
+ * @field_inversion - inversion flag
+ * @fb_base_phys - frame buffer address
+ * @lconfig - ptr to layer config
+ *
+ * This routine implements a workaround for the field signal inversion silicon
+ * erratum described in Advisory 1.3.8 for the DM6446.  The fb_base_phys and
+ * lconfig parameters apply to the vid0 window.  This routine should be called
+ * whenever the vid0 layer configuration or start address is modified, or when
+ * the OSD field inversion setting is modified.
+ * Returns: 1 if the ping-pong buffers need to be toggled in the vsync isr, or
+ *          0 otherwise
+ */
+static int _osd_dm6446_vid0_pingpong(struct osd_state *sd,
+                                    int field_inversion,
+                                    unsigned long fb_base_phys,
+                                    const struct osd_layer_config *lconfig)
+{
+       struct osd_platform_data *pdata;
+
+       pdata = (struct osd_platform_data *)sd->dev->platform_data;
+       if (pdata->field_inv_wa_enable) {
+
+               if (!field_inversion || !lconfig->interlaced) {
+                       osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
+                       osd_write(sd, fb_base_phys & ~0x1F, OSD_PPVWIN0ADR);
+                       osd_modify(sd, OSD_MISCCTL_PPSW | OSD_MISCCTL_PPRV, 0,
+                                  OSD_MISCCTL);
+                       return 0;
+               } else {
+                       unsigned miscctl = OSD_MISCCTL_PPRV;
+
+                       osd_write(sd,
+                               (fb_base_phys & ~0x1F) - lconfig->line_length,
+                               OSD_VIDWIN0ADR);
+                       osd_write(sd,
+                               (fb_base_phys & ~0x1F) + lconfig->line_length,
+                               OSD_PPVWIN0ADR);
+                       osd_modify(sd,
+                               OSD_MISCCTL_PPSW | OSD_MISCCTL_PPRV, miscctl,
+                               OSD_MISCCTL);
+
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static void _osd_set_field_inversion(struct osd_state *sd, int enable)
+{
+       unsigned fsinv = 0;
+
+       if (enable)
+               fsinv = OSD_MODE_FSINV;
+
+       osd_modify(sd, OSD_MODE_FSINV, fsinv, OSD_MODE);
+}
+
+static void _osd_set_blink_attribute(struct osd_state *sd, int enable,
+                                    enum osd_blink_interval blink)
+{
+       u32 osdatrmd = 0;
+
+       if (enable) {
+               osdatrmd |= OSD_OSDATRMD_BLNK;
+               osdatrmd |= blink << OSD_OSDATRMD_BLNKINT_SHIFT;
+       }
+       /* caller must ensure that OSD1 is configured in attribute mode */
+       osd_modify(sd, OSD_OSDATRMD_BLNKINT | OSD_OSDATRMD_BLNK, osdatrmd,
+                 OSD_OSDATRMD);
+}
+
+static void _osd_set_rom_clut(struct osd_state *sd,
+                             enum osd_rom_clut rom_clut)
+{
+       if (rom_clut == ROM_CLUT0)
+               osd_clear(sd, OSD_MISCCTL_RSEL, OSD_MISCCTL);
+       else
+               osd_set(sd, OSD_MISCCTL_RSEL, OSD_MISCCTL);
+}
+
+static void _osd_set_palette_map(struct osd_state *sd,
+                                enum osd_win_layer osdwin,
+                                unsigned char pixel_value,
+                                unsigned char clut_index,
+                                enum osd_pix_format pixfmt)
+{
+       static const int map_2bpp[] = { 0, 5, 10, 15 };
+       static const int map_1bpp[] = { 0, 15 };
+       int bmp_offset;
+       int bmp_shift;
+       int bmp_mask;
+       int bmp_reg;
+
+       switch (pixfmt) {
+       case PIXFMT_1BPP:
+               bmp_reg = map_1bpp[pixel_value & 0x1];
+               break;
+       case PIXFMT_2BPP:
+               bmp_reg = map_2bpp[pixel_value & 0x3];
+               break;
+       case PIXFMT_4BPP:
+               bmp_reg = pixel_value & 0xf;
+               break;
+       default:
+               return;
+       }
+
+       switch (osdwin) {
+       case OSDWIN_OSD0:
+               bmp_offset = OSD_W0BMP01 + (bmp_reg >> 1) * sizeof(u32);
+               break;
+       case OSDWIN_OSD1:
+               bmp_offset = OSD_W1BMP01 + (bmp_reg >> 1) * sizeof(u32);
+               break;
+       default:
+               return;
+       }
+
+       if (bmp_reg & 1) {
+               bmp_shift = 8;
+               bmp_mask = 0xff << 8;
+       } else {
+               bmp_shift = 0;
+               bmp_mask = 0xff;
+       }
+
+       osd_modify(sd, bmp_mask, clut_index << bmp_shift, bmp_offset);
+}
+
+static void _osd_set_rec601_attenuation(struct osd_state *sd,
+                                       enum osd_win_layer osdwin, int enable)
+{
+       switch (osdwin) {
+       case OSDWIN_OSD0:
+               osd_modify(sd, OSD_OSDWIN0MD_ATN0E,
+                         enable ? OSD_OSDWIN0MD_ATN0E : 0,
+                         OSD_OSDWIN0MD);
+               break;
+       case OSDWIN_OSD1:
+               osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
+                         enable ? OSD_OSDWIN1MD_ATN1E : 0,
+                         OSD_OSDWIN1MD);
+               break;
+       }
+}
+
+static void _osd_set_blending_factor(struct osd_state *sd,
+                                    enum osd_win_layer osdwin,
+                                    enum osd_blending_factor blend)
+{
+       switch (osdwin) {
+       case OSDWIN_OSD0:
+               osd_modify(sd, OSD_OSDWIN0MD_BLND0,
+                         blend << OSD_OSDWIN0MD_BLND0_SHIFT, OSD_OSDWIN0MD);
+               break;
+       case OSDWIN_OSD1:
+               osd_modify(sd, OSD_OSDWIN1MD_BLND1,
+                         blend << OSD_OSDWIN1MD_BLND1_SHIFT, OSD_OSDWIN1MD);
+               break;
+       }
+}
+
+static void _osd_enable_color_key(struct osd_state *sd,
+                                 enum osd_win_layer osdwin,
+                                 unsigned colorkey,
+                                 enum osd_pix_format pixfmt)
+{
+       switch (pixfmt) {
+       case PIXFMT_RGB565:
+               osd_write(sd, colorkey & OSD_TRANSPVAL_RGBTRANS,
+                         OSD_TRANSPVAL);
+               break;
+       default:
+               break;
+       }
+
+       switch (osdwin) {
+       case OSDWIN_OSD0:
+               osd_set(sd, OSD_OSDWIN0MD_TE0, OSD_OSDWIN0MD);
+               break;
+       case OSDWIN_OSD1:
+               osd_set(sd, OSD_OSDWIN1MD_TE1, OSD_OSDWIN1MD);
+               break;
+       }
+}
+
+static void _osd_disable_color_key(struct osd_state *sd,
+                                  enum osd_win_layer osdwin)
+{
+       switch (osdwin) {
+       case OSDWIN_OSD0:
+               osd_clear(sd, OSD_OSDWIN0MD_TE0, OSD_OSDWIN0MD);
+               break;
+       case OSDWIN_OSD1:
+               osd_clear(sd, OSD_OSDWIN1MD_TE1, OSD_OSDWIN1MD);
+               break;
+       }
+}
+
+static void _osd_set_osd_clut(struct osd_state *sd,
+                             enum osd_win_layer osdwin,
+                             enum osd_clut clut)
+{
+       u32 winmd = 0;
+
+       switch (osdwin) {
+       case OSDWIN_OSD0:
+               if (clut == RAM_CLUT)
+                       winmd |= OSD_OSDWIN0MD_CLUTS0;
+               osd_modify(sd, OSD_OSDWIN0MD_CLUTS0, winmd, OSD_OSDWIN0MD);
+               break;
+       case OSDWIN_OSD1:
+               if (clut == RAM_CLUT)
+                       winmd |= OSD_OSDWIN1MD_CLUTS1;
+               osd_modify(sd, OSD_OSDWIN1MD_CLUTS1, winmd, OSD_OSDWIN1MD);
+               break;
+       }
+}
+
+static void _osd_set_zoom(struct osd_state *sd, enum osd_layer layer,
+                         enum osd_zoom_factor h_zoom,
+                         enum osd_zoom_factor v_zoom)
+{
+       u32 winmd = 0;
+
+       switch (layer) {
+       case WIN_OSD0:
+               winmd |= (h_zoom << OSD_OSDWIN0MD_OHZ0_SHIFT);
+               winmd |= (v_zoom << OSD_OSDWIN0MD_OVZ0_SHIFT);
+               osd_modify(sd, OSD_OSDWIN0MD_OHZ0 | OSD_OSDWIN0MD_OVZ0, winmd,
+                         OSD_OSDWIN0MD);
+               break;
+       case WIN_VID0:
+               winmd |= (h_zoom << OSD_VIDWINMD_VHZ0_SHIFT);
+               winmd |= (v_zoom << OSD_VIDWINMD_VVZ0_SHIFT);
+               osd_modify(sd, OSD_VIDWINMD_VHZ0 | OSD_VIDWINMD_VVZ0, winmd,
+                         OSD_VIDWINMD);
+               break;
+       case WIN_OSD1:
+               winmd |= (h_zoom << OSD_OSDWIN1MD_OHZ1_SHIFT);
+               winmd |= (v_zoom << OSD_OSDWIN1MD_OVZ1_SHIFT);
+               osd_modify(sd, OSD_OSDWIN1MD_OHZ1 | OSD_OSDWIN1MD_OVZ1, winmd,
+                         OSD_OSDWIN1MD);
+               break;
+       case WIN_VID1:
+               winmd |= (h_zoom << OSD_VIDWINMD_VHZ1_SHIFT);
+               winmd |= (v_zoom << OSD_VIDWINMD_VVZ1_SHIFT);
+               osd_modify(sd, OSD_VIDWINMD_VHZ1 | OSD_VIDWINMD_VVZ1, winmd,
+                         OSD_VIDWINMD);
+               break;
+       }
+}
+
+static void _osd_disable_layer(struct osd_state *sd, enum osd_layer layer)
+{
+       switch (layer) {
+       case WIN_OSD0:
+               osd_clear(sd, OSD_OSDWIN0MD_OACT0, OSD_OSDWIN0MD);
+               break;
+       case WIN_VID0:
+               osd_clear(sd, OSD_VIDWINMD_ACT0, OSD_VIDWINMD);
+               break;
+       case WIN_OSD1:
+               /* disable attribute mode as well as disabling the window */
+               osd_clear(sd, OSD_OSDWIN1MD_OASW | OSD_OSDWIN1MD_OACT1,
+                         OSD_OSDWIN1MD);
+               break;
+       case WIN_VID1:
+               osd_clear(sd, OSD_VIDWINMD_ACT1, OSD_VIDWINMD);
+               break;
+       }
+}
+
+static void osd_disable_layer(struct osd_state *sd, enum osd_layer layer)
+{
+       struct osd_state *osd = sd;
+       struct osd_window_state *win = &osd->win[layer];
+       unsigned long flags;
+
+       spin_lock_irqsave(&osd->lock, flags);
+
+       if (!win->is_enabled) {
+               spin_unlock_irqrestore(&osd->lock, flags);
+               return;
+       }
+       win->is_enabled = 0;
+
+       _osd_disable_layer(sd, layer);
+
+       spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void _osd_enable_attribute_mode(struct osd_state *sd)
+{
+       /* enable attribute mode for OSD1 */
+       osd_set(sd, OSD_OSDWIN1MD_OASW, OSD_OSDWIN1MD);
+}
+
+static void _osd_enable_layer(struct osd_state *sd, enum osd_layer layer)
+{
+       switch (layer) {
+       case WIN_OSD0:
+               osd_set(sd, OSD_OSDWIN0MD_OACT0, OSD_OSDWIN0MD);
+               break;
+       case WIN_VID0:
+               osd_set(sd, OSD_VIDWINMD_ACT0, OSD_VIDWINMD);
+               break;
+       case WIN_OSD1:
+               /* enable OSD1 and disable attribute mode */
+               osd_modify(sd, OSD_OSDWIN1MD_OASW | OSD_OSDWIN1MD_OACT1,
+                         OSD_OSDWIN1MD_OACT1, OSD_OSDWIN1MD);
+               break;
+       case WIN_VID1:
+               osd_set(sd, OSD_VIDWINMD_ACT1, OSD_VIDWINMD);
+               break;
+       }
+}
+
+static int osd_enable_layer(struct osd_state *sd, enum osd_layer layer,
+                           int otherwin)
+{
+       struct osd_state *osd = sd;
+       struct osd_window_state *win = &osd->win[layer];
+       struct osd_layer_config *cfg = &win->lconfig;
+       unsigned long flags;
+
+       spin_lock_irqsave(&osd->lock, flags);
+
+       /*
+        * use otherwin flag to know this is the other vid window
+        * in YUV420 mode, if is, skip this check
+        */
+       if (!otherwin && (!win->is_allocated ||
+                       !win->fb_base_phys ||
+                       !cfg->line_length ||
+                       !cfg->xsize ||
+                       !cfg->ysize)) {
+               spin_unlock_irqrestore(&osd->lock, flags);
+               return -1;
+       }
+
+       if (win->is_enabled) {
+               spin_unlock_irqrestore(&osd->lock, flags);
+               return 0;
+       }
+       win->is_enabled = 1;
+
+       if (cfg->pixfmt != PIXFMT_OSD_ATTR)
+               _osd_enable_layer(sd, layer);
+       else {
+               _osd_enable_attribute_mode(sd);
+               _osd_set_blink_attribute(sd, osd->is_blinking, osd->blink);
+       }
+
+       spin_unlock_irqrestore(&osd->lock, flags);
+
+       return 0;
+}
+
+static void _osd_start_layer(struct osd_state *sd, enum osd_layer layer,
+                            unsigned long fb_base_phys,
+                            unsigned long cbcr_ofst)
+{
+       switch (layer) {
+       case WIN_OSD0:
+               osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN0ADR);
+               break;
+       case WIN_VID0:
+               osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
+               break;
+       case WIN_OSD1:
+               osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN1ADR);
+               break;
+       case WIN_VID1:
+               osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN1ADR);
+               break;
+       }
+}
+
+static void osd_start_layer(struct osd_state *sd, enum osd_layer layer,
+                           unsigned long fb_base_phys,
+                           unsigned long cbcr_ofst)
+{
+       struct osd_state *osd = sd;
+       struct osd_window_state *win = &osd->win[layer];
+       struct osd_layer_config *cfg = &win->lconfig;
+       unsigned long flags;
+
+       spin_lock_irqsave(&osd->lock, flags);
+
+       win->fb_base_phys = fb_base_phys & ~0x1F;
+       _osd_start_layer(sd, layer, fb_base_phys, cbcr_ofst);
+
+       if (layer == WIN_VID0) {
+               osd->pingpong =
+                   _osd_dm6446_vid0_pingpong(sd, osd->field_inversion,
+                                                      win->fb_base_phys,
+                                                      cfg);
+       }
+
+       spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void osd_get_layer_config(struct osd_state *sd, enum osd_layer layer,
+                                struct osd_layer_config *lconfig)
+{
+       struct osd_state *osd = sd;
+       struct osd_window_state *win = &osd->win[layer];
+       unsigned long flags;
+
+       spin_lock_irqsave(&osd->lock, flags);
+
+       *lconfig = win->lconfig;
+
+       spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+/**
+ * try_layer_config() - Try a specific configuration for the layer
+ * @sd  - ptr to struct osd_state
+ * @layer - layer to configure
+ * @lconfig - layer configuration to try
+ *
+ * If the requested lconfig is completely rejected and the value of lconfig on
+ * exit is the current lconfig, then try_layer_config() returns 1.  Otherwise,
+ * try_layer_config() returns 0.  A return value of 0 does not necessarily mean
+ * that the value of lconfig on exit is identical to the value of lconfig on
+ * entry, but merely that it represents a change from the current lconfig.
+ */
+static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
+                           struct osd_layer_config *lconfig)
+{
+       struct osd_state *osd = sd;
+       struct osd_window_state *win = &osd->win[layer];
+       int bad_config;
+
+       /* verify that the pixel format is compatible with the layer */
+       switch (lconfig->pixfmt) {
+       case PIXFMT_1BPP:
+       case PIXFMT_2BPP:
+       case PIXFMT_4BPP:
+       case PIXFMT_8BPP:
+       case PIXFMT_RGB565:
+               bad_config = !is_osd_win(layer);
+               break;
+       case PIXFMT_YCbCrI:
+       case PIXFMT_YCrCbI:
+               bad_config = !is_vid_win(layer);
+               break;
+       case PIXFMT_RGB888:
+               bad_config = !is_vid_win(layer);
+               break;
+       case PIXFMT_NV12:
+               bad_config = 1;
+               break;
+       case PIXFMT_OSD_ATTR:
+               bad_config = (layer != WIN_OSD1);
+               break;
+       default:
+               bad_config = 1;
+               break;
+       }
+       if (bad_config) {
+               /*
+                * The requested pixel format is incompatible with the layer,
+                * so keep the current layer configuration.
+                */
+               *lconfig = win->lconfig;
+               return bad_config;
+       }
+
+       /* DM6446: */
+       /* only one OSD window at a time can use RGB pixel formats */
+       if (is_osd_win(layer) && is_rgb_pixfmt(lconfig->pixfmt)) {
+               enum osd_pix_format pixfmt;
+               if (layer == WIN_OSD0)
+                       pixfmt = osd->win[WIN_OSD1].lconfig.pixfmt;
+               else
+                       pixfmt = osd->win[WIN_OSD0].lconfig.pixfmt;
+
+               if (is_rgb_pixfmt(pixfmt)) {
+                       /*
+                        * The other OSD window is already configured for an
+                        * RGB, so keep the current layer configuration.
+                        */
+                       *lconfig = win->lconfig;
+                       return 1;
+               }
+       }
+
+       /* DM6446: only one video window at a time can use RGB888 */
+       if (is_vid_win(layer) && lconfig->pixfmt == PIXFMT_RGB888) {
+               enum osd_pix_format pixfmt;
+
+               if (layer == WIN_VID0)
+                       pixfmt = osd->win[WIN_VID1].lconfig.pixfmt;
+               else
+                       pixfmt = osd->win[WIN_VID0].lconfig.pixfmt;
+
+               if (pixfmt == PIXFMT_RGB888) {
+                       /*
+                        * The other video window is already configured for
+                        * RGB888, so keep the current layer configuration.
+                        */
+                       *lconfig = win->lconfig;
+                       return 1;
+               }
+       }
+
+       /* window dimensions must be non-zero */
+       if (!lconfig->line_length || !lconfig->xsize || !lconfig->ysize) {
+               *lconfig = win->lconfig;
+               return 1;
+       }
+
+       /* round line_length up to a multiple of 32 */
+       lconfig->line_length = ((lconfig->line_length + 31) / 32) * 32;
+       lconfig->line_length =
+           min(lconfig->line_length, (unsigned)MAX_LINE_LENGTH);
+       lconfig->xsize = min(lconfig->xsize, (unsigned)MAX_WIN_SIZE);
+       lconfig->ysize = min(lconfig->ysize, (unsigned)MAX_WIN_SIZE);
+       lconfig->xpos = min(lconfig->xpos, (unsigned)MAX_WIN_SIZE);
+       lconfig->ypos = min(lconfig->ypos, (unsigned)MAX_WIN_SIZE);
+       lconfig->interlaced = (lconfig->interlaced != 0);
+       if (lconfig->interlaced) {
+               /* ysize and ypos must be even for interlaced displays */
+               lconfig->ysize &= ~1;
+               lconfig->ypos &= ~1;
+       }
+
+       return 0;
+}
+
+static void _osd_disable_vid_rgb888(struct osd_state *sd)
+{
+       /*
+        * The DM6446 supports RGB888 pixel format in a single video window.
+        * This routine disables RGB888 pixel format for both video windows.
+        * The caller must ensure that neither video window is currently
+        * configured for RGB888 pixel format.
+        */
+       osd_clear(sd, OSD_MISCCTL_RGBEN, OSD_MISCCTL);
+}
+
+static void _osd_enable_vid_rgb888(struct osd_state *sd,
+                                  enum osd_layer layer)
+{
+       /*
+        * The DM6446 supports RGB888 pixel format in a single video window.
+        * This routine enables RGB888 pixel format for the specified video
+        * window.  The caller must ensure that the other video window is not
+        * currently configured for RGB888 pixel format, as this routine will
+        * disable RGB888 pixel format for the other window.
+        */
+       if (layer == WIN_VID0) {
+               osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
+                         OSD_MISCCTL_RGBEN, OSD_MISCCTL);
+       } else if (layer == WIN_VID1) {
+               osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
+                         OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
+                         OSD_MISCCTL);
+       }
+}
+
+static void _osd_set_cbcr_order(struct osd_state *sd,
+                               enum osd_pix_format pixfmt)
+{
+       /*
+        * The caller must ensure that all windows using YC pixfmt use the same
+        * Cb/Cr order.
+        */
+       if (pixfmt == PIXFMT_YCbCrI)
+               osd_clear(sd, OSD_MODE_CS, OSD_MODE);
+       else if (pixfmt == PIXFMT_YCrCbI)
+               osd_set(sd, OSD_MODE_CS, OSD_MODE);
+}
+
+static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
+                                 const struct osd_layer_config *lconfig)
+{
+       u32 winmd = 0, winmd_mask = 0, bmw = 0;
+
+       _osd_set_cbcr_order(sd, lconfig->pixfmt);
+
+       switch (layer) {
+       case WIN_OSD0:
+               winmd_mask |= OSD_OSDWIN0MD_RGB0E;
+               if (lconfig->pixfmt == PIXFMT_RGB565)
+                       winmd |= OSD_OSDWIN0MD_RGB0E;
+
+               winmd_mask |= OSD_OSDWIN0MD_BMW0 | OSD_OSDWIN0MD_OFF0;
+
+               switch (lconfig->pixfmt) {
+               case PIXFMT_1BPP:
+                       bmw = 0;
+                       break;
+               case PIXFMT_2BPP:
+                       bmw = 1;
+                       break;
+               case PIXFMT_4BPP:
+                       bmw = 2;
+                       break;
+               case PIXFMT_8BPP:
+                       bmw = 3;
+                       break;
+               default:
+                       break;
+               }
+               winmd |= (bmw << OSD_OSDWIN0MD_BMW0_SHIFT);
+
+               if (lconfig->interlaced)
+                       winmd |= OSD_OSDWIN0MD_OFF0;
+
+               osd_modify(sd, winmd_mask, winmd, OSD_OSDWIN0MD);
+               osd_write(sd, lconfig->line_length >> 5, OSD_OSDWIN0OFST);
+               osd_write(sd, lconfig->xpos, OSD_OSDWIN0XP);
+               osd_write(sd, lconfig->xsize, OSD_OSDWIN0XL);
+               if (lconfig->interlaced) {
+                       osd_write(sd, lconfig->ypos >> 1, OSD_OSDWIN0YP);
+                       osd_write(sd, lconfig->ysize >> 1, OSD_OSDWIN0YL);
+               } else {
+                       osd_write(sd, lconfig->ypos, OSD_OSDWIN0YP);
+                       osd_write(sd, lconfig->ysize, OSD_OSDWIN0YL);
+               }
+               break;
+       case WIN_VID0:
+               winmd_mask |= OSD_VIDWINMD_VFF0;
+               if (lconfig->interlaced)
+                       winmd |= OSD_VIDWINMD_VFF0;
+
+               osd_modify(sd, winmd_mask, winmd, OSD_VIDWINMD);
+               osd_write(sd, lconfig->line_length >> 5, OSD_VIDWIN0OFST);
+               osd_write(sd, lconfig->xpos, OSD_VIDWIN0XP);
+               osd_write(sd, lconfig->xsize, OSD_VIDWIN0XL);
+               /*
+                * For YUV420P format the register contents are
+                * duplicated in both VID registers
+                */
+               if (lconfig->interlaced) {
+                       osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN0YP);
+                       osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN0YL);
+               } else {
+                       osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP);
+                       osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL);
+               }
+               break;
+       case WIN_OSD1:
+               /*
+                * The caller must ensure that OSD1 is disabled prior to
+                * switching from a normal mode to attribute mode or from
+                * attribute mode to a normal mode.
+                */
+               if (lconfig->pixfmt == PIXFMT_OSD_ATTR) {
+                       winmd_mask |=
+                           OSD_OSDWIN1MD_ATN1E | OSD_OSDWIN1MD_RGB1E |
+                           OSD_OSDWIN1MD_CLUTS1 |
+                           OSD_OSDWIN1MD_BLND1 | OSD_OSDWIN1MD_TE1;
+               } else {
+                       winmd_mask |= OSD_OSDWIN1MD_RGB1E;
+                       if (lconfig->pixfmt == PIXFMT_RGB565)
+                               winmd |= OSD_OSDWIN1MD_RGB1E;
+
+                       winmd_mask |= OSD_OSDWIN1MD_BMW1;
+                       switch (lconfig->pixfmt) {
+                       case PIXFMT_1BPP:
+                               bmw = 0;
+                               break;
+                       case PIXFMT_2BPP:
+                               bmw = 1;
+                               break;
+                       case PIXFMT_4BPP:
+                               bmw = 2;
+                               break;
+                       case PIXFMT_8BPP:
+                               bmw = 3;
+                               break;
+                       default:
+                               break;
+                       }
+                       winmd |= (bmw << OSD_OSDWIN1MD_BMW1_SHIFT);
+               }
+
+               winmd_mask |= OSD_OSDWIN1MD_OFF1;
+               if (lconfig->interlaced)
+                       winmd |= OSD_OSDWIN1MD_OFF1;
+
+               osd_modify(sd, winmd_mask, winmd, OSD_OSDWIN1MD);
+               osd_write(sd, lconfig->line_length >> 5, OSD_OSDWIN1OFST);
+               osd_write(sd, lconfig->xpos, OSD_OSDWIN1XP);
+               osd_write(sd, lconfig->xsize, OSD_OSDWIN1XL);
+               if (lconfig->interlaced) {
+                       osd_write(sd, lconfig->ypos >> 1, OSD_OSDWIN1YP);
+                       osd_write(sd, lconfig->ysize >> 1, OSD_OSDWIN1YL);
+               } else {
+                       osd_write(sd, lconfig->ypos, OSD_OSDWIN1YP);
+                       osd_write(sd, lconfig->ysize, OSD_OSDWIN1YL);
+               }
+               break;
+       case WIN_VID1:
+               winmd_mask |= OSD_VIDWINMD_VFF1;
+               if (lconfig->interlaced)
+                       winmd |= OSD_VIDWINMD_VFF1;
+
+               osd_modify(sd, winmd_mask, winmd, OSD_VIDWINMD);
+               osd_write(sd, lconfig->line_length >> 5, OSD_VIDWIN1OFST);
+               osd_write(sd, lconfig->xpos, OSD_VIDWIN1XP);
+               osd_write(sd, lconfig->xsize, OSD_VIDWIN1XL);
+               /*
+                * For YUV420P format the register contents are
+                * duplicated in both VID registers
+                */
+               osd_modify(sd, OSD_MISCCTL_S420D, ~OSD_MISCCTL_S420D,
+                          OSD_MISCCTL);
+
+               if (lconfig->interlaced) {
+                       osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN1YP);
+                       osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN1YL);
+               } else {
+                       osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP);
+                       osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL);
+               }
+               break;
+       }
+}
+
+static int osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
+                               struct osd_layer_config *lconfig)
+{
+       struct osd_state *osd = sd;
+       struct osd_window_state *win = &osd->win[layer];
+       struct osd_layer_config *cfg = &win->lconfig;
+       unsigned long flags;
+       int reject_config;
+
+       spin_lock_irqsave(&osd->lock, flags);
+
+       reject_config = try_layer_config(sd, layer, lconfig);
+       if (reject_config) {
+               spin_unlock_irqrestore(&osd->lock, flags);
+               return reject_config;
+       }
+
+       /* update the current Cb/Cr order */
+       if (is_yc_pixfmt(lconfig->pixfmt))
+               osd->yc_pixfmt = lconfig->pixfmt;
+
+       /*
+        * If we are switching OSD1 from normal mode to attribute mode or from
+        * attribute mode to normal mode, then we must disable the window.
+        */
+       if (layer == WIN_OSD1) {
+               if (((lconfig->pixfmt == PIXFMT_OSD_ATTR) &&
+                 (cfg->pixfmt != PIXFMT_OSD_ATTR)) ||
+                 ((lconfig->pixfmt != PIXFMT_OSD_ATTR) &&
+                 (cfg->pixfmt == PIXFMT_OSD_ATTR))) {
+                       win->is_enabled = 0;
+                       _osd_disable_layer(sd, layer);
+               }
+       }
+
+       _osd_set_layer_config(sd, layer, lconfig);
+
+       if (layer == WIN_OSD1) {
+               struct osd_osdwin_state *osdwin_state =
+                   &osd->osdwin[OSDWIN_OSD1];
+
+               if ((lconfig->pixfmt != PIXFMT_OSD_ATTR) &&
+                 (cfg->pixfmt == PIXFMT_OSD_ATTR)) {
+                       /*
+                        * We just switched OSD1 from attribute mode to normal
+                        * mode, so we must initialize the CLUT select, the
+                        * blend factor, transparency colorkey enable, and
+                        * attenuation enable (DM6446 only) bits in the
+                        * OSDWIN1MD register.
+                        */
+                       _osd_set_osd_clut(sd, OSDWIN_OSD1,
+                                                  osdwin_state->clut);
+                       _osd_set_blending_factor(sd, OSDWIN_OSD1,
+                                                         osdwin_state->blend);
+                       if (osdwin_state->colorkey_blending) {
+                               _osd_enable_color_key(sd, OSDWIN_OSD1,
+                                                              osdwin_state->
+                                                              colorkey,
+                                                              lconfig->pixfmt);
+                       } else
+                               _osd_disable_color_key(sd, OSDWIN_OSD1);
+                       _osd_set_rec601_attenuation(sd, OSDWIN_OSD1,
+                                                   osdwin_state->
+                                                   rec601_attenuation);
+               } else if ((lconfig->pixfmt == PIXFMT_OSD_ATTR) &&
+                 (cfg->pixfmt != PIXFMT_OSD_ATTR)) {
+                       /*
+                        * We just switched OSD1 from normal mode to attribute
+                        * mode, so we must initialize the blink enable and
+                        * blink interval bits in the OSDATRMD register.
+                        */
+                       _osd_set_blink_attribute(sd, osd->is_blinking,
+                                                         osd->blink);
+               }
+       }
+
+       /*
+        * If we just switched to a 1-, 2-, or 4-bits-per-pixel bitmap format
+        * then configure a default palette map.
+        */
+       if ((lconfig->pixfmt != cfg->pixfmt) &&
+         ((lconfig->pixfmt == PIXFMT_1BPP) ||
+         (lconfig->pixfmt == PIXFMT_2BPP) ||
+         (lconfig->pixfmt == PIXFMT_4BPP))) {
+               enum osd_win_layer osdwin =
+                   ((layer == WIN_OSD0) ? OSDWIN_OSD0 : OSDWIN_OSD1);
+               struct osd_osdwin_state *osdwin_state =
+                   &osd->osdwin[osdwin];
+               unsigned char clut_index;
+               unsigned char clut_entries = 0;
+
+               switch (lconfig->pixfmt) {
+               case PIXFMT_1BPP:
+                       clut_entries = 2;
+                       break;
+               case PIXFMT_2BPP:
+                       clut_entries = 4;
+                       break;
+               case PIXFMT_4BPP:
+                       clut_entries = 16;
+                       break;
+               default:
+                       break;
+               }
+               /*
+                * The default palette map maps the pixel value to the clut
+                * index, i.e. pixel value 0 maps to clut entry 0, pixel value
+                * 1 maps to clut entry 1, etc.
+                */
+               for (clut_index = 0; clut_index < 16; clut_index++) {
+                       osdwin_state->palette_map[clut_index] = clut_index;
+                       if (clut_index < clut_entries) {
+                               _osd_set_palette_map(sd, osdwin, clut_index,
+                                                    clut_index,
+                                                    lconfig->pixfmt);
+                       }
+               }
+       }
+
+       *cfg = *lconfig;
+       /* DM6446: configure the RGB888 enable and window selection */
+       if (osd->win[WIN_VID0].lconfig.pixfmt == PIXFMT_RGB888)
+               _osd_enable_vid_rgb888(sd, WIN_VID0);
+       else if (osd->win[WIN_VID1].lconfig.pixfmt == PIXFMT_RGB888)
+               _osd_enable_vid_rgb888(sd, WIN_VID1);
+       else
+               _osd_disable_vid_rgb888(sd);
+
+       if (layer == WIN_VID0) {
+               osd->pingpong =
+                   _osd_dm6446_vid0_pingpong(sd, osd->field_inversion,
+                                                      win->fb_base_phys,
+                                                      cfg);
+       }
+
+       spin_unlock_irqrestore(&osd->lock, flags);
+
+       return 0;
+}
+
+static void osd_init_layer(struct osd_state *sd, enum osd_layer layer)
+{
+       struct osd_state *osd = sd;
+       struct osd_window_state *win = &osd->win[layer];
+       enum osd_win_layer osdwin;
+       struct osd_osdwin_state *osdwin_state;
+       struct osd_layer_config *cfg = &win->lconfig;
+       unsigned long flags;
+
+       spin_lock_irqsave(&osd->lock, flags);
+
+       win->is_enabled = 0;
+       _osd_disable_layer(sd, layer);
+
+       win->h_zoom = ZOOM_X1;
+       win->v_zoom = ZOOM_X1;
+       _osd_set_zoom(sd, layer, win->h_zoom, win->v_zoom);
+
+       win->fb_base_phys = 0;
+       _osd_start_layer(sd, layer, win->fb_base_phys, 0);
+
+       cfg->line_length = 0;
+       cfg->xsize = 0;
+       cfg->ysize = 0;
+       cfg->xpos = 0;
+       cfg->ypos = 0;
+       cfg->interlaced = 0;
+       switch (layer) {
+       case WIN_OSD0:
+       case WIN_OSD1:
+               osdwin = (layer == WIN_OSD0) ? OSDWIN_OSD0 : OSDWIN_OSD1;
+               osdwin_state = &osd->osdwin[osdwin];
+               /*
+                * Other code relies on the fact that OSD windows default to a
+                * bitmap pixel format when they are deallocated, so don't
+                * change this default pixel format.
+                */
+               cfg->pixfmt = PIXFMT_8BPP;
+               _osd_set_layer_config(sd, layer, cfg);
+               osdwin_state->clut = RAM_CLUT;
+               _osd_set_osd_clut(sd, osdwin, osdwin_state->clut);
+               osdwin_state->colorkey_blending = 0;
+               _osd_disable_color_key(sd, osdwin);
+               osdwin_state->blend = OSD_8_VID_0;
+               _osd_set_blending_factor(sd, osdwin, osdwin_state->blend);
+               osdwin_state->rec601_attenuation = 0;
+               _osd_set_rec601_attenuation(sd, osdwin,
+                                                    osdwin_state->
+                                                    rec601_attenuation);
+               if (osdwin == OSDWIN_OSD1) {
+                       osd->is_blinking = 0;
+                       osd->blink = BLINK_X1;
+               }
+               break;
+       case WIN_VID0:
+       case WIN_VID1:
+               cfg->pixfmt = osd->yc_pixfmt;
+               _osd_set_layer_config(sd, layer, cfg);
+               break;
+       }
+
+       spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void osd_release_layer(struct osd_state *sd, enum osd_layer layer)
+{
+       struct osd_state *osd = sd;
+       struct osd_window_state *win = &osd->win[layer];
+       unsigned long flags;
+
+       spin_lock_irqsave(&osd->lock, flags);
+
+       if (!win->is_allocated) {
+               spin_unlock_irqrestore(&osd->lock, flags);
+               return;
+       }
+
+       spin_unlock_irqrestore(&osd->lock, flags);
+       osd_init_layer(sd, layer);
+       spin_lock_irqsave(&osd->lock, flags);
+
+       win->is_allocated = 0;
+
+       spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static int osd_request_layer(struct osd_state *sd, enum osd_layer layer)
+{
+       struct osd_state *osd = sd;
+       struct osd_window_state *win = &osd->win[layer];
+       unsigned long flags;
+
+       spin_lock_irqsave(&osd->lock, flags);
+
+       if (win->is_allocated) {
+               spin_unlock_irqrestore(&osd->lock, flags);
+               return -1;
+       }
+       win->is_allocated = 1;
+
+       spin_unlock_irqrestore(&osd->lock, flags);
+
+       return 0;
+}
+
+static void _osd_init(struct osd_state *sd)
+{
+       osd_write(sd, 0, OSD_MODE);
+       osd_write(sd, 0, OSD_VIDWINMD);
+       osd_write(sd, 0, OSD_OSDWIN0MD);
+       osd_write(sd, 0, OSD_OSDWIN1MD);
+       osd_write(sd, 0, OSD_RECTCUR);
+       osd_write(sd, 0, OSD_MISCCTL);
+}
+
+static void osd_set_left_margin(struct osd_state *sd, u32 val)
+{
+       osd_write(sd, val, OSD_BASEPX);
+}
+
+static void osd_set_top_margin(struct osd_state *sd, u32 val)
+{
+       osd_write(sd, val, OSD_BASEPY);
+}
+
+static int osd_initialize(struct osd_state *osd)
+{
+       if (osd == NULL)
+               return -ENODEV;
+       _osd_init(osd);
+
+       /* set default Cb/Cr order */
+       osd->yc_pixfmt = PIXFMT_YCbCrI;
+
+       _osd_set_field_inversion(osd, osd->field_inversion);
+       _osd_set_rom_clut(osd, osd->rom_clut);
+
+       osd_init_layer(osd, WIN_OSD0);
+       osd_init_layer(osd, WIN_VID0);
+       osd_init_layer(osd, WIN_OSD1);
+       osd_init_layer(osd, WIN_VID1);
+
+       return 0;
+}
+
+static const struct vpbe_osd_ops osd_ops = {
+       .initialize = osd_initialize,
+       .request_layer = osd_request_layer,
+       .release_layer = osd_release_layer,
+       .enable_layer = osd_enable_layer,
+       .disable_layer = osd_disable_layer,
+       .set_layer_config = osd_set_layer_config,
+       .get_layer_config = osd_get_layer_config,
+       .start_layer = osd_start_layer,
+       .set_left_margin = osd_set_left_margin,
+       .set_top_margin = osd_set_top_margin,
+};
+
+static int osd_probe(struct platform_device *pdev)
+{
+       struct osd_platform_data *pdata;
+       struct osd_state *osd;
+       struct resource *res;
+       int ret = 0;
+
+       osd = kzalloc(sizeof(struct osd_state), GFP_KERNEL);
+       if (osd == NULL)
+               return -ENOMEM;
+
+       osd->dev = &pdev->dev;
+       pdata = (struct osd_platform_data *)pdev->dev.platform_data;
+       osd->vpbe_type = (enum vpbe_version)pdata->vpbe_type;
+       if (NULL == pdev->dev.platform_data) {
+               dev_err(osd->dev, "No platform data defined for OSD"
+                       " sub device\n");
+               ret = -ENOENT;
+               goto free_mem;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(osd->dev, "Unable to get OSD register address map\n");
+               ret = -ENODEV;
+               goto free_mem;
+       }
+       osd->osd_base_phys = res->start;
+       osd->osd_size = res->end - res->start + 1;
+       if (!request_mem_region(osd->osd_base_phys, osd->osd_size,
+                               MODULE_NAME)) {
+               dev_err(osd->dev, "Unable to reserve OSD MMIO region\n");
+               ret = -ENODEV;
+               goto free_mem;
+       }
+       osd->osd_base = (unsigned long)ioremap_nocache(res->start,
+                                                       osd->osd_size);
+       if (!osd->osd_base) {
+               dev_err(osd->dev, "Unable to map the OSD region\n");
+               ret = -ENODEV;
+               goto release_mem_region;
+       }
+       spin_lock_init(&osd->lock);
+       osd->ops = osd_ops;
+       platform_set_drvdata(pdev, osd);
+       dev_notice(osd->dev, "OSD sub device probe success\n");
+       return ret;
+
+release_mem_region:
+       release_mem_region(osd->osd_base_phys, osd->osd_size);
+free_mem:
+       kfree(osd);
+       return ret;
+}
+
+static int osd_remove(struct platform_device *pdev)
+{
+       struct osd_state *osd = platform_get_drvdata(pdev);
+
+       iounmap((void *)osd->osd_base);
+       release_mem_region(osd->osd_base_phys, osd->osd_size);
+       kfree(osd);
+       return 0;
+}
+
+static struct platform_driver osd_driver = {
+       .probe          = osd_probe,
+       .remove         = osd_remove,
+       .driver         = {
+               .name   = MODULE_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int osd_init(void)
+{
+       if (platform_driver_register(&osd_driver)) {
+               printk(KERN_ERR "Unable to register davinci osd driver\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void osd_exit(void)
+{
+       platform_driver_unregister(&osd_driver);
+}
+
+module_init(osd_init);
+module_exit(osd_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DaVinci OSD Manager Driver");
+MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/media/video/davinci/vpbe_osd_regs.h b/drivers/media/video/davinci/vpbe_osd_regs.h
new file mode 100644 (file)
index 0000000..584520f
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2006-2010 Texas Instruments 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 version 2.
+ *
+ * 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 _VPBE_OSD_REGS_H
+#define _VPBE_OSD_REGS_H
+
+/* VPBE Global Registers */
+#define VPBE_PID                               0x0
+#define VPBE_PCR                               0x4
+
+/* VPSS CLock Registers */
+#define VPSSCLK_PID                            0x00
+#define VPSSCLK_CLKCTRL                                0x04
+
+/* VPSS Buffer Logic Registers */
+#define VPSSBL_PID                             0x00
+#define VPSSBL_PCR                             0x04
+#define VPSSBL_BCR                             0x08
+#define VPSSBL_INTSTAT                         0x0C
+#define VPSSBL_INTSEL                          0x10
+#define VPSSBL_EVTSEL                          0x14
+#define VPSSBL_MEMCTRL                         0x18
+#define VPSSBL_CCDCMUX                         0x1C
+
+/* DM365 ISP5 system configuration */
+#define ISP5_PID                               0x0
+#define ISP5_PCCR                              0x4
+#define ISP5_BCR                               0x8
+#define ISP5_INTSTAT                           0xC
+#define ISP5_INTSEL1                           0x10
+#define ISP5_INTSEL2                           0x14
+#define ISP5_INTSEL3                           0x18
+#define ISP5_EVTSEL                            0x1c
+#define ISP5_CCDCMUX                           0x20
+
+/* VPBE On-Screen Display Subsystem Registers (OSD) */
+#define OSD_MODE                               0x00
+#define OSD_VIDWINMD                           0x04
+#define OSD_OSDWIN0MD                          0x08
+#define OSD_OSDWIN1MD                          0x0C
+#define OSD_OSDATRMD                           0x0C
+#define OSD_RECTCUR                            0x10
+#define OSD_VIDWIN0OFST                                0x18
+#define OSD_VIDWIN1OFST                                0x1C
+#define OSD_OSDWIN0OFST                                0x20
+#define OSD_OSDWIN1OFST                                0x24
+#define OSD_VIDWINADH                          0x28
+#define OSD_VIDWIN0ADL                         0x2C
+#define OSD_VIDWIN0ADR                         0x2C
+#define OSD_VIDWIN1ADL                         0x30
+#define OSD_VIDWIN1ADR                         0x30
+#define OSD_OSDWINADH                          0x34
+#define OSD_OSDWIN0ADL                         0x38
+#define OSD_OSDWIN0ADR                         0x38
+#define OSD_OSDWIN1ADL                         0x3C
+#define OSD_OSDWIN1ADR                         0x3C
+#define OSD_BASEPX                             0x40
+#define OSD_BASEPY                             0x44
+#define OSD_VIDWIN0XP                          0x48
+#define OSD_VIDWIN0YP                          0x4C
+#define OSD_VIDWIN0XL                          0x50
+#define OSD_VIDWIN0YL                          0x54
+#define OSD_VIDWIN1XP                          0x58
+#define OSD_VIDWIN1YP                          0x5C
+#define OSD_VIDWIN1XL                          0x60
+#define OSD_VIDWIN1YL                          0x64
+#define OSD_OSDWIN0XP                          0x68
+#define OSD_OSDWIN0YP                          0x6C
+#define OSD_OSDWIN0XL                          0x70
+#define OSD_OSDWIN0YL                          0x74
+#define OSD_OSDWIN1XP                          0x78
+#define OSD_OSDWIN1YP                          0x7C
+#define OSD_OSDWIN1XL                          0x80
+#define OSD_OSDWIN1YL                          0x84
+#define OSD_CURXP                              0x88
+#define OSD_CURYP                              0x8C
+#define OSD_CURXL                              0x90
+#define OSD_CURYL                              0x94
+#define OSD_W0BMP01                            0xA0
+#define OSD_W0BMP23                            0xA4
+#define OSD_W0BMP45                            0xA8
+#define OSD_W0BMP67                            0xAC
+#define OSD_W0BMP89                            0xB0
+#define OSD_W0BMPAB                            0xB4
+#define OSD_W0BMPCD                            0xB8
+#define OSD_W0BMPEF                            0xBC
+#define OSD_W1BMP01                            0xC0
+#define OSD_W1BMP23                            0xC4
+#define OSD_W1BMP45                            0xC8
+#define OSD_W1BMP67                            0xCC
+#define OSD_W1BMP89                            0xD0
+#define OSD_W1BMPAB                            0xD4
+#define OSD_W1BMPCD                            0xD8
+#define OSD_W1BMPEF                            0xDC
+#define OSD_VBNDRY                             0xE0
+#define OSD_EXTMODE                            0xE4
+#define OSD_MISCCTL                            0xE8
+#define OSD_CLUTRAMYCB                         0xEC
+#define OSD_CLUTRAMCR                          0xF0
+#define OSD_TRANSPVAL                          0xF4
+#define OSD_TRANSPVALL                         0xF4
+#define OSD_TRANSPVALU                         0xF8
+#define OSD_TRANSPBMPIDX                       0xFC
+#define OSD_PPVWIN0ADR                         0xFC
+
+/* bit definitions */
+#define VPBE_PCR_VENC_DIV                      (1 << 1)
+#define VPBE_PCR_CLK_OFF                       (1 << 0)
+
+#define VPSSBL_INTSTAT_HSSIINT                 (1 << 14)
+#define VPSSBL_INTSTAT_CFALDINT                        (1 << 13)
+#define VPSSBL_INTSTAT_IPIPE_INT5              (1 << 12)
+#define VPSSBL_INTSTAT_IPIPE_INT4              (1 << 11)
+#define VPSSBL_INTSTAT_IPIPE_INT3              (1 << 10)
+#define VPSSBL_INTSTAT_IPIPE_INT2              (1 << 9)
+#define VPSSBL_INTSTAT_IPIPE_INT1              (1 << 8)
+#define VPSSBL_INTSTAT_IPIPE_INT0              (1 << 7)
+#define VPSSBL_INTSTAT_IPIPEIFINT              (1 << 6)
+#define VPSSBL_INTSTAT_OSDINT                  (1 << 5)
+#define VPSSBL_INTSTAT_VENCINT                 (1 << 4)
+#define VPSSBL_INTSTAT_H3AINT                  (1 << 3)
+#define VPSSBL_INTSTAT_CCDC_VDINT2             (1 << 2)
+#define VPSSBL_INTSTAT_CCDC_VDINT1             (1 << 1)
+#define VPSSBL_INTSTAT_CCDC_VDINT0             (1 << 0)
+
+/* DM365 ISP5 bit definitions */
+#define ISP5_INTSTAT_VENCINT                   (1 << 21)
+#define ISP5_INTSTAT_OSDINT                    (1 << 20)
+
+/* VMOD TVTYP options for HDMD=0 */
+#define SDTV_NTSC                              0
+#define SDTV_PAL                               1
+/* VMOD TVTYP options for HDMD=1 */
+#define HDTV_525P                              0
+#define HDTV_625P                              1
+#define HDTV_1080I                             2
+#define HDTV_720P                              3
+
+#define OSD_MODE_CS                            (1 << 15)
+#define OSD_MODE_OVRSZ                         (1 << 14)
+#define OSD_MODE_OHRSZ                         (1 << 13)
+#define OSD_MODE_EF                            (1 << 12)
+#define OSD_MODE_VVRSZ                         (1 << 11)
+#define OSD_MODE_VHRSZ                         (1 << 10)
+#define OSD_MODE_FSINV                         (1 << 9)
+#define OSD_MODE_BCLUT                         (1 << 8)
+#define OSD_MODE_CABG_SHIFT                    0
+#define OSD_MODE_CABG                          (0xff << 0)
+
+#define OSD_VIDWINMD_VFINV                     (1 << 15)
+#define OSD_VIDWINMD_V1EFC                     (1 << 14)
+#define OSD_VIDWINMD_VHZ1_SHIFT                        12
+#define OSD_VIDWINMD_VHZ1                      (3 << 12)
+#define OSD_VIDWINMD_VVZ1_SHIFT                        10
+#define OSD_VIDWINMD_VVZ1                      (3 << 10)
+#define OSD_VIDWINMD_VFF1                      (1 << 9)
+#define OSD_VIDWINMD_ACT1                      (1 << 8)
+#define OSD_VIDWINMD_V0EFC                     (1 << 6)
+#define OSD_VIDWINMD_VHZ0_SHIFT                        4
+#define OSD_VIDWINMD_VHZ0                      (3 << 4)
+#define OSD_VIDWINMD_VVZ0_SHIFT                        2
+#define OSD_VIDWINMD_VVZ0                      (3 << 2)
+#define OSD_VIDWINMD_VFF0                      (1 << 1)
+#define OSD_VIDWINMD_ACT0                      (1 << 0)
+
+#define OSD_OSDWIN0MD_ATN0E                    (1 << 14)
+#define OSD_OSDWIN0MD_RGB0E                    (1 << 13)
+#define OSD_OSDWIN0MD_BMP0MD_SHIFT             13
+#define OSD_OSDWIN0MD_BMP0MD                   (3 << 13)
+#define OSD_OSDWIN0MD_CLUTS0                   (1 << 12)
+#define OSD_OSDWIN0MD_OHZ0_SHIFT               10
+#define OSD_OSDWIN0MD_OHZ0                     (3 << 10)
+#define OSD_OSDWIN0MD_OVZ0_SHIFT               8
+#define OSD_OSDWIN0MD_OVZ0                     (3 << 8)
+#define OSD_OSDWIN0MD_BMW0_SHIFT               6
+#define OSD_OSDWIN0MD_BMW0                     (3 << 6)
+#define OSD_OSDWIN0MD_BLND0_SHIFT              3
+#define OSD_OSDWIN0MD_BLND0                    (7 << 3)
+#define OSD_OSDWIN0MD_TE0                      (1 << 2)
+#define OSD_OSDWIN0MD_OFF0                     (1 << 1)
+#define OSD_OSDWIN0MD_OACT0                    (1 << 0)
+
+#define OSD_OSDWIN1MD_OASW                     (1 << 15)
+#define OSD_OSDWIN1MD_ATN1E                    (1 << 14)
+#define OSD_OSDWIN1MD_RGB1E                    (1 << 13)
+#define OSD_OSDWIN1MD_BMP1MD_SHIFT             13
+#define OSD_OSDWIN1MD_BMP1MD                   (3 << 13)
+#define OSD_OSDWIN1MD_CLUTS1                   (1 << 12)
+#define OSD_OSDWIN1MD_OHZ1_SHIFT               10
+#define OSD_OSDWIN1MD_OHZ1                     (3 << 10)
+#define OSD_OSDWIN1MD_OVZ1_SHIFT               8
+#define OSD_OSDWIN1MD_OVZ1                     (3 << 8)
+#define OSD_OSDWIN1MD_BMW1_SHIFT               6
+#define OSD_OSDWIN1MD_BMW1                     (3 << 6)
+#define OSD_OSDWIN1MD_BLND1_SHIFT              3
+#define OSD_OSDWIN1MD_BLND1                    (7 << 3)
+#define OSD_OSDWIN1MD_TE1                      (1 << 2)
+#define OSD_OSDWIN1MD_OFF1                     (1 << 1)
+#define OSD_OSDWIN1MD_OACT1                    (1 << 0)
+
+#define OSD_OSDATRMD_OASW                      (1 << 15)
+#define OSD_OSDATRMD_OHZA_SHIFT                        10
+#define OSD_OSDATRMD_OHZA                      (3 << 10)
+#define OSD_OSDATRMD_OVZA_SHIFT                        8
+#define OSD_OSDATRMD_OVZA                      (3 << 8)
+#define OSD_OSDATRMD_BLNKINT_SHIFT             6
+#define OSD_OSDATRMD_BLNKINT                   (3 << 6)
+#define OSD_OSDATRMD_OFFA                      (1 << 1)
+#define OSD_OSDATRMD_BLNK                      (1 << 0)
+
+#define OSD_RECTCUR_RCAD_SHIFT                 8
+#define OSD_RECTCUR_RCAD                       (0xff << 8)
+#define OSD_RECTCUR_CLUTSR                     (1 << 7)
+#define OSD_RECTCUR_RCHW_SHIFT                 4
+#define OSD_RECTCUR_RCHW                       (7 << 4)
+#define OSD_RECTCUR_RCVW_SHIFT                 1
+#define OSD_RECTCUR_RCVW                       (7 << 1)
+#define OSD_RECTCUR_RCACT                      (1 << 0)
+
+#define OSD_VIDWIN0OFST_V0LO                   (0x1ff << 0)
+
+#define OSD_VIDWIN1OFST_V1LO                   (0x1ff << 0)
+
+#define OSD_OSDWIN0OFST_O0LO                   (0x1ff << 0)
+
+#define OSD_OSDWIN1OFST_O1LO                   (0x1ff << 0)
+
+#define OSD_WINOFST_AH_SHIFT                   9
+
+#define OSD_VIDWIN0OFST_V0AH                   (0xf << 9)
+#define OSD_VIDWIN1OFST_V1AH                   (0xf << 9)
+#define OSD_OSDWIN0OFST_O0AH                   (0xf << 9)
+#define OSD_OSDWIN1OFST_O1AH                   (0xf << 9)
+
+#define OSD_VIDWINADH_V1AH_SHIFT               8
+#define OSD_VIDWINADH_V1AH                     (0x7f << 8)
+#define OSD_VIDWINADH_V0AH_SHIFT               0
+#define OSD_VIDWINADH_V0AH                     (0x7f << 0)
+
+#define OSD_VIDWIN0ADL_V0AL                    (0xffff << 0)
+
+#define OSD_VIDWIN1ADL_V1AL                    (0xffff << 0)
+
+#define OSD_OSDWINADH_O1AH_SHIFT               8
+#define OSD_OSDWINADH_O1AH                     (0x7f << 8)
+#define OSD_OSDWINADH_O0AH_SHIFT               0
+#define OSD_OSDWINADH_O0AH                     (0x7f << 0)
+
+#define OSD_OSDWIN0ADL_O0AL                    (0xffff << 0)
+
+#define OSD_OSDWIN1ADL_O1AL                    (0xffff << 0)
+
+#define OSD_BASEPX_BPX                         (0x3ff << 0)
+
+#define OSD_BASEPY_BPY                         (0x1ff << 0)
+
+#define OSD_VIDWIN0XP_V0X                      (0x7ff << 0)
+
+#define OSD_VIDWIN0YP_V0Y                      (0x7ff << 0)
+
+#define OSD_VIDWIN0XL_V0W                      (0x7ff << 0)
+
+#define OSD_VIDWIN0YL_V0H                      (0x7ff << 0)
+
+#define OSD_VIDWIN1XP_V1X                      (0x7ff << 0)
+
+#define OSD_VIDWIN1YP_V1Y                      (0x7ff << 0)
+
+#define OSD_VIDWIN1XL_V1W                      (0x7ff << 0)
+
+#define OSD_VIDWIN1YL_V1H                      (0x7ff << 0)
+
+#define OSD_OSDWIN0XP_W0X                      (0x7ff << 0)
+
+#define OSD_OSDWIN0YP_W0Y                      (0x7ff << 0)
+
+#define OSD_OSDWIN0XL_W0W                      (0x7ff << 0)
+
+#define OSD_OSDWIN0YL_W0H                      (0x7ff << 0)
+
+#define OSD_OSDWIN1XP_W1X                      (0x7ff << 0)
+
+#define OSD_OSDWIN1YP_W1Y                      (0x7ff << 0)
+
+#define OSD_OSDWIN1XL_W1W                      (0x7ff << 0)
+
+#define OSD_OSDWIN1YL_W1H                      (0x7ff << 0)
+
+#define OSD_CURXP_RCSX                         (0x7ff << 0)
+
+#define OSD_CURYP_RCSY                         (0x7ff << 0)
+
+#define OSD_CURXL_RCSW                         (0x7ff << 0)
+
+#define OSD_CURYL_RCSH                         (0x7ff << 0)
+
+#define OSD_EXTMODE_EXPMDSEL                   (1 << 15)
+#define OSD_EXTMODE_SCRNHEXP_SHIFT             13
+#define OSD_EXTMODE_SCRNHEXP                   (3 << 13)
+#define OSD_EXTMODE_SCRNVEXP                   (1 << 12)
+#define OSD_EXTMODE_OSD1BLDCHR                 (1 << 11)
+#define OSD_EXTMODE_OSD0BLDCHR                 (1 << 10)
+#define OSD_EXTMODE_ATNOSD1EN                  (1 << 9)
+#define OSD_EXTMODE_ATNOSD0EN                  (1 << 8)
+#define OSD_EXTMODE_OSDHRSZ15                  (1 << 7)
+#define OSD_EXTMODE_VIDHRSZ15                  (1 << 6)
+#define OSD_EXTMODE_ZMFILV1HEN                 (1 << 5)
+#define OSD_EXTMODE_ZMFILV1VEN                 (1 << 4)
+#define OSD_EXTMODE_ZMFILV0HEN                 (1 << 3)
+#define OSD_EXTMODE_ZMFILV0VEN                 (1 << 2)
+#define OSD_EXTMODE_EXPFILHEN                  (1 << 1)
+#define OSD_EXTMODE_EXPFILVEN                  (1 << 0)
+
+#define OSD_MISCCTL_BLDSEL                     (1 << 15)
+#define OSD_MISCCTL_S420D                      (1 << 14)
+#define OSD_MISCCTL_BMAPT                      (1 << 13)
+#define OSD_MISCCTL_DM365M                     (1 << 12)
+#define OSD_MISCCTL_RGBEN                      (1 << 7)
+#define OSD_MISCCTL_RGBWIN                     (1 << 6)
+#define OSD_MISCCTL_DMANG                      (1 << 6)
+#define OSD_MISCCTL_TMON                       (1 << 5)
+#define OSD_MISCCTL_RSEL                       (1 << 4)
+#define OSD_MISCCTL_CPBSY                      (1 << 3)
+#define OSD_MISCCTL_PPSW                       (1 << 2)
+#define OSD_MISCCTL_PPRV                       (1 << 1)
+
+#define OSD_CLUTRAMYCB_Y_SHIFT                 8
+#define OSD_CLUTRAMYCB_Y                       (0xff << 8)
+#define OSD_CLUTRAMYCB_CB_SHIFT                        0
+#define OSD_CLUTRAMYCB_CB                      (0xff << 0)
+
+#define OSD_CLUTRAMCR_CR_SHIFT                 8
+#define OSD_CLUTRAMCR_CR                       (0xff << 8)
+#define OSD_CLUTRAMCR_CADDR_SHIFT              0
+#define OSD_CLUTRAMCR_CADDR                    (0xff << 0)
+
+#define OSD_TRANSPVAL_RGBTRANS                 (0xffff << 0)
+
+#define OSD_TRANSPVALL_RGBL                    (0xffff << 0)
+
+#define OSD_TRANSPVALU_Y_SHIFT                 8
+#define OSD_TRANSPVALU_Y                       (0xff << 8)
+#define OSD_TRANSPVALU_RGBU_SHIFT              0
+#define OSD_TRANSPVALU_RGBU                    (0xff << 0)
+
+#define OSD_TRANSPBMPIDX_BMP1_SHIFT            8
+#define OSD_TRANSPBMPIDX_BMP1                  (0xff << 8)
+#define OSD_TRANSPBMPIDX_BMP0_SHIFT            0
+#define OSD_TRANSPBMPIDX_BMP0                  0xff
+
+#endif                         /* _DAVINCI_VPBE_H_ */
diff --git a/drivers/media/video/davinci/vpbe_venc.c b/drivers/media/video/davinci/vpbe_venc.c
new file mode 100644 (file)
index 0000000..03a3e5c
--- /dev/null
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2010 Texas Instruments 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+
+#include <mach/hardware.h>
+#include <mach/mux.h>
+#include <mach/io.h>
+#include <mach/i2c.h>
+
+#include <linux/io.h>
+
+#include <media/davinci/vpbe_types.h>
+#include <media/davinci/vpbe_venc.h>
+#include <media/davinci/vpss.h>
+#include <media/v4l2-device.h>
+
+#include "vpbe_venc_regs.h"
+
+#define MODULE_NAME    VPBE_VENC_SUBDEV_NAME
+
+static int debug = 2;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level 0-2");
+
+struct venc_state {
+       struct v4l2_subdev sd;
+       struct venc_callback *callback;
+       struct venc_platform_data *pdata;
+       struct device *pdev;
+       u32 output;
+       v4l2_std_id std;
+       spinlock_t lock;
+       void __iomem *venc_base;
+       void __iomem *vdaccfg_reg;
+};
+
+static inline struct venc_state *to_state(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct venc_state, sd);
+}
+
+static inline u32 venc_read(struct v4l2_subdev *sd, u32 offset)
+{
+       struct venc_state *venc = to_state(sd);
+
+       return readl(venc->venc_base + offset);
+}
+
+static inline u32 venc_write(struct v4l2_subdev *sd, u32 offset, u32 val)
+{
+       struct venc_state *venc = to_state(sd);
+
+       writel(val, (venc->venc_base + offset));
+
+       return val;
+}
+
+static inline u32 venc_modify(struct v4l2_subdev *sd, u32 offset,
+                                u32 val, u32 mask)
+{
+       u32 new_val = (venc_read(sd, offset) & ~mask) | (val & mask);
+
+       venc_write(sd, offset, new_val);
+
+       return new_val;
+}
+
+static inline u32 vdaccfg_write(struct v4l2_subdev *sd, u32 val)
+{
+       struct venc_state *venc = to_state(sd);
+
+       writel(val, venc->vdaccfg_reg);
+
+       val = readl(venc->vdaccfg_reg);
+
+       return val;
+}
+
+/* This function sets the dac of the VPBE for various outputs
+ */
+static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
+{
+       switch (out_index) {
+       case 0:
+               v4l2_dbg(debug, 1, sd, "Setting output to Composite\n");
+               venc_write(sd, VENC_DACSEL, 0);
+               break;
+       case 1:
+               v4l2_dbg(debug, 1, sd, "Setting output to S-Video\n");
+               venc_write(sd, VENC_DACSEL, 0x210);
+               break;
+       case  2:
+               venc_write(sd, VENC_DACSEL, 0x543);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
+{
+       v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n");
+
+       if (benable) {
+               venc_write(sd, VENC_VMOD, 0);
+               venc_write(sd, VENC_CVBS, 0);
+               venc_write(sd, VENC_LCDOUT, 0);
+               venc_write(sd, VENC_HSPLS, 0);
+               venc_write(sd, VENC_HSTART, 0);
+               venc_write(sd, VENC_HVALID, 0);
+               venc_write(sd, VENC_HINT, 0);
+               venc_write(sd, VENC_VSPLS, 0);
+               venc_write(sd, VENC_VSTART, 0);
+               venc_write(sd, VENC_VVALID, 0);
+               venc_write(sd, VENC_VINT, 0);
+               venc_write(sd, VENC_YCCCTL, 0);
+               venc_write(sd, VENC_DACSEL, 0);
+
+       } else {
+               venc_write(sd, VENC_VMOD, 0);
+               /* disable VCLK output pin enable */
+               venc_write(sd, VENC_VIDCTL, 0x141);
+
+               /* Disable output sync pins */
+               venc_write(sd, VENC_SYNCCTL, 0);
+
+               /* Disable DCLOCK */
+               venc_write(sd, VENC_DCLKCTL, 0);
+               venc_write(sd, VENC_DRGBX1, 0x0000057C);
+
+               /* Disable LCD output control (accepting default polarity) */
+               venc_write(sd, VENC_LCDOUT, 0);
+               venc_write(sd, VENC_CMPNT, 0x100);
+               venc_write(sd, VENC_HSPLS, 0);
+               venc_write(sd, VENC_HINT, 0);
+               venc_write(sd, VENC_HSTART, 0);
+               venc_write(sd, VENC_HVALID, 0);
+
+               venc_write(sd, VENC_VSPLS, 0);
+               venc_write(sd, VENC_VINT, 0);
+               venc_write(sd, VENC_VSTART, 0);
+               venc_write(sd, VENC_VVALID, 0);
+
+               venc_write(sd, VENC_HSDLY, 0);
+               venc_write(sd, VENC_VSDLY, 0);
+
+               venc_write(sd, VENC_YCCCTL, 0);
+               venc_write(sd, VENC_VSTARTA, 0);
+
+               /* Set OSD clock and OSD Sync Adavance registers */
+               venc_write(sd, VENC_OSDCLK0, 1);
+               venc_write(sd, VENC_OSDCLK1, 2);
+       }
+}
+
+/*
+ * setting NTSC mode
+ */
+static int venc_set_ntsc(struct v4l2_subdev *sd)
+{
+       struct venc_state *venc = to_state(sd);
+       struct venc_platform_data *pdata = venc->pdata;
+
+       v4l2_dbg(debug, 2, sd, "venc_set_ntsc\n");
+
+       /* Setup clock at VPSS & VENC for SD */
+       vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
+       if (pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_525_60) < 0)
+               return -EINVAL;
+
+       venc_enabledigitaloutput(sd, 0);
+
+       /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
+       venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
+       /* Set REC656 Mode */
+       venc_write(sd, VENC_YCCCTL, 0x1);
+       venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ);
+       venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS);
+
+       venc_write(sd, VENC_VMOD, 0);
+       venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
+                       VENC_VMOD_VIE);
+       venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
+       venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_TVTYP_SHIFT),
+                       VENC_VMOD_TVTYP);
+       venc_write(sd, VENC_DACTST, 0x0);
+       venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
+
+       return 0;
+}
+
+/*
+ * setting PAL mode
+ */
+static int venc_set_pal(struct v4l2_subdev *sd)
+{
+       struct venc_state *venc = to_state(sd);
+
+       v4l2_dbg(debug, 2, sd, "venc_set_pal\n");
+
+       /* Setup clock at VPSS & VENC for SD */
+       vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
+       if (venc->pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_625_50) < 0)
+               return -EINVAL;
+
+       venc_enabledigitaloutput(sd, 0);
+
+       /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
+       venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
+       /* Set REC656 Mode */
+       venc_write(sd, VENC_YCCCTL, 0x1);
+
+       venc_modify(sd, VENC_SYNCCTL, 1 << VENC_SYNCCTL_OVD_SHIFT,
+                       VENC_SYNCCTL_OVD);
+       venc_write(sd, VENC_VMOD, 0);
+       venc_modify(sd, VENC_VMOD,
+                       (1 << VENC_VMOD_VIE_SHIFT),
+                       VENC_VMOD_VIE);
+       venc_modify(sd, VENC_VMOD,
+                       (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
+       venc_modify(sd, VENC_VMOD,
+                       (1 << VENC_VMOD_TVTYP_SHIFT),
+                       VENC_VMOD_TVTYP);
+       venc_write(sd, VENC_DACTST, 0x0);
+       venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
+
+       return 0;
+}
+
+/*
+ * venc_set_480p59_94
+ *
+ * This function configures the video encoder to EDTV(525p) component setting.
+ */
+static int venc_set_480p59_94(struct v4l2_subdev *sd)
+{
+       struct venc_state *venc = to_state(sd);
+       struct venc_platform_data *pdata = venc->pdata;
+
+       v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n");
+
+       /* Setup clock at VPSS & VENC for SD */
+       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0)
+               return -EINVAL;
+
+       venc_enabledigitaloutput(sd, 0);
+
+       venc_write(sd, VENC_OSDCLK0, 0);
+       venc_write(sd, VENC_OSDCLK1, 1);
+       venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
+                   VENC_VDPRO_DAFRQ);
+       venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
+                   VENC_VDPRO_DAUPS);
+       venc_write(sd, VENC_VMOD, 0);
+       venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
+                   VENC_VMOD_VIE);
+       venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
+       venc_modify(sd, VENC_VMOD, (HDTV_525P << VENC_VMOD_TVTYP_SHIFT),
+                   VENC_VMOD_TVTYP);
+       venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
+                   VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
+
+       venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
+
+       return 0;
+}
+
+/*
+ * venc_set_625p
+ *
+ * This function configures the video encoder to HDTV(625p) component setting
+ */
+static int venc_set_576p50(struct v4l2_subdev *sd)
+{
+       struct venc_state *venc = to_state(sd);
+       struct venc_platform_data *pdata = venc->pdata;
+
+       v4l2_dbg(debug, 2, sd, "venc_set_576p50\n");
+
+       /* Setup clock at VPSS & VENC for SD */
+       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0)
+               return -EINVAL;
+
+       venc_enabledigitaloutput(sd, 0);
+
+       venc_write(sd, VENC_OSDCLK0, 0);
+       venc_write(sd, VENC_OSDCLK1, 1);
+
+       venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
+                   VENC_VDPRO_DAFRQ);
+       venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
+                   VENC_VDPRO_DAUPS);
+
+       venc_write(sd, VENC_VMOD, 0);
+       venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
+                   VENC_VMOD_VIE);
+       venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
+       venc_modify(sd, VENC_VMOD, (HDTV_625P << VENC_VMOD_TVTYP_SHIFT),
+                   VENC_VMOD_TVTYP);
+
+       venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
+                   VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
+       venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
+
+       return 0;
+}
+
+static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+       v4l2_dbg(debug, 1, sd, "venc_s_std_output\n");
+
+       if (norm & V4L2_STD_525_60)
+               return venc_set_ntsc(sd);
+       else if (norm & V4L2_STD_625_50)
+               return venc_set_pal(sd);
+
+       return -EINVAL;
+}
+
+static int venc_s_dv_preset(struct v4l2_subdev *sd,
+                           struct v4l2_dv_preset *dv_preset)
+{
+       v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n");
+
+       if (dv_preset->preset == V4L2_DV_576P50)
+               return venc_set_576p50(sd);
+       else if (dv_preset->preset == V4L2_DV_480P59_94)
+               return venc_set_480p59_94(sd);
+
+       return -EINVAL;
+}
+
+static int venc_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
+                         u32 config)
+{
+       struct venc_state *venc = to_state(sd);
+       int ret;
+
+       v4l2_dbg(debug, 1, sd, "venc_s_routing\n");
+
+       ret = venc_set_dac(sd, output);
+       if (!ret)
+               venc->output = output;
+
+       return ret;
+}
+
+static long venc_ioctl(struct v4l2_subdev *sd,
+                       unsigned int cmd,
+                       void *arg)
+{
+       u32 val;
+
+       switch (cmd) {
+       case VENC_GET_FLD:
+               val = venc_read(sd, VENC_VSTAT);
+               *((int *)arg) = ((val & VENC_VSTAT_FIDST) ==
+               VENC_VSTAT_FIDST);
+               break;
+       default:
+               v4l2_err(sd, "Wrong IOCTL cmd\n");
+               break;
+       }
+
+       return 0;
+}
+
+static const struct v4l2_subdev_core_ops venc_core_ops = {
+       .ioctl      = venc_ioctl,
+};
+
+static const struct v4l2_subdev_video_ops venc_video_ops = {
+       .s_routing = venc_s_routing,
+       .s_std_output = venc_s_std_output,
+       .s_dv_preset = venc_s_dv_preset,
+};
+
+static const struct v4l2_subdev_ops venc_ops = {
+       .core = &venc_core_ops,
+       .video = &venc_video_ops,
+};
+
+static int venc_initialize(struct v4l2_subdev *sd)
+{
+       struct venc_state *venc = to_state(sd);
+       int ret;
+
+       /* Set default to output to composite and std to NTSC */
+       venc->output = 0;
+       venc->std = V4L2_STD_525_60;
+
+       ret = venc_s_routing(sd, 0, venc->output, 0);
+       if (ret < 0) {
+               v4l2_err(sd, "Error setting output during init\n");
+               return -EINVAL;
+       }
+
+       ret = venc_s_std_output(sd, venc->std);
+       if (ret < 0) {
+               v4l2_err(sd, "Error setting std during init\n");
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+static int venc_device_get(struct device *dev, void *data)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct venc_state **venc = data;
+
+       if (strcmp(MODULE_NAME, pdev->name) == 0)
+               *venc = platform_get_drvdata(pdev);
+
+       return 0;
+}
+
+struct v4l2_subdev *venc_sub_dev_init(struct v4l2_device *v4l2_dev,
+               const char *venc_name)
+{
+       struct venc_state *venc;
+       int err;
+
+       err = bus_for_each_dev(&platform_bus_type, NULL, &venc,
+                       venc_device_get);
+       if (venc == NULL)
+               return NULL;
+
+       v4l2_subdev_init(&venc->sd, &venc_ops);
+
+       strcpy(venc->sd.name, venc_name);
+       if (v4l2_device_register_subdev(v4l2_dev, &venc->sd) < 0) {
+               v4l2_err(v4l2_dev,
+                       "vpbe unable to register venc sub device\n");
+               return NULL;
+       }
+       if (venc_initialize(&venc->sd)) {
+               v4l2_err(v4l2_dev,
+                       "vpbe venc initialization failed\n");
+               return NULL;
+       }
+
+       return &venc->sd;
+}
+EXPORT_SYMBOL(venc_sub_dev_init);
+
+static int venc_probe(struct platform_device *pdev)
+{
+       struct venc_state *venc;
+       struct resource *res;
+       int ret;
+
+       venc = kzalloc(sizeof(struct venc_state), GFP_KERNEL);
+       if (venc == NULL)
+               return -ENOMEM;
+
+       venc->pdev = &pdev->dev;
+       venc->pdata = pdev->dev.platform_data;
+       if (NULL == venc->pdata) {
+               dev_err(venc->pdev, "Unable to get platform data for"
+                       " VENC sub device");
+               ret = -ENOENT;
+               goto free_mem;
+       }
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(venc->pdev,
+                       "Unable to get VENC register address map\n");
+               ret = -ENODEV;
+               goto free_mem;
+       }
+
+       if (!request_mem_region(res->start, resource_size(res), "venc")) {
+               dev_err(venc->pdev, "Unable to reserve VENC MMIO region\n");
+               ret = -ENODEV;
+               goto free_mem;
+       }
+
+       venc->venc_base = ioremap_nocache(res->start, resource_size(res));
+       if (!venc->venc_base) {
+               dev_err(venc->pdev, "Unable to map VENC IO space\n");
+               ret = -ENODEV;
+               goto release_venc_mem_region;
+       }
+
+       spin_lock_init(&venc->lock);
+       platform_set_drvdata(pdev, venc);
+       dev_notice(venc->pdev, "VENC sub device probe success\n");
+       return 0;
+
+release_venc_mem_region:
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, resource_size(res));
+free_mem:
+       kfree(venc);
+       return ret;
+}
+
+static int venc_remove(struct platform_device *pdev)
+{
+       struct venc_state *venc = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       iounmap((void *)venc->venc_base);
+       release_mem_region(res->start, resource_size(res));
+       kfree(venc);
+
+       return 0;
+}
+
+static struct platform_driver venc_driver = {
+       .probe          = venc_probe,
+       .remove         = venc_remove,
+       .driver         = {
+               .name   = MODULE_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int venc_init(void)
+{
+       if (platform_driver_register(&venc_driver)) {
+               printk(KERN_ERR "Unable to register venc driver\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static void venc_exit(void)
+{
+       platform_driver_unregister(&venc_driver);
+       return;
+}
+
+module_init(venc_init);
+module_exit(venc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("VPBE VENC Driver");
+MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/media/video/davinci/vpbe_venc_regs.h b/drivers/media/video/davinci/vpbe_venc_regs.h
new file mode 100644 (file)
index 0000000..947cb15
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2006-2010 Texas Instruments 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 version 2..
+ *
+ * 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 _VPBE_VENC_REGS_H
+#define _VPBE_VENC_REGS_H
+
+/* VPBE Video Encoder / Digital LCD Subsystem Registers (VENC) */
+#define VENC_VMOD                              0x00
+#define VENC_VIDCTL                            0x04
+#define VENC_VDPRO                             0x08
+#define VENC_SYNCCTL                           0x0C
+#define VENC_HSPLS                             0x10
+#define VENC_VSPLS                             0x14
+#define VENC_HINT                              0x18
+#define VENC_HSTART                            0x1C
+#define VENC_HVALID                            0x20
+#define VENC_VINT                              0x24
+#define VENC_VSTART                            0x28
+#define VENC_VVALID                            0x2C
+#define VENC_HSDLY                             0x30
+#define VENC_VSDLY                             0x34
+#define VENC_YCCCTL                            0x38
+#define VENC_RGBCTL                            0x3C
+#define VENC_RGBCLP                            0x40
+#define VENC_LINECTL                           0x44
+#define VENC_CULLLINE                          0x48
+#define VENC_LCDOUT                            0x4C
+#define VENC_BRTS                              0x50
+#define VENC_BRTW                              0x54
+#define VENC_ACCTL                             0x58
+#define VENC_PWMP                              0x5C
+#define VENC_PWMW                              0x60
+#define VENC_DCLKCTL                           0x64
+#define VENC_DCLKPTN0                          0x68
+#define VENC_DCLKPTN1                          0x6C
+#define VENC_DCLKPTN2                          0x70
+#define VENC_DCLKPTN3                          0x74
+#define VENC_DCLKPTN0A                         0x78
+#define VENC_DCLKPTN1A                         0x7C
+#define VENC_DCLKPTN2A                         0x80
+#define VENC_DCLKPTN3A                         0x84
+#define VENC_DCLKHS                            0x88
+#define VENC_DCLKHSA                           0x8C
+#define VENC_DCLKHR                            0x90
+#define VENC_DCLKVS                            0x94
+#define VENC_DCLKVR                            0x98
+#define VENC_CAPCTL                            0x9C
+#define VENC_CAPDO                             0xA0
+#define VENC_CAPDE                             0xA4
+#define VENC_ATR0                              0xA8
+#define VENC_ATR1                              0xAC
+#define VENC_ATR2                              0xB0
+#define VENC_VSTAT                             0xB8
+#define VENC_RAMADR                            0xBC
+#define VENC_RAMPORT                           0xC0
+#define VENC_DACTST                            0xC4
+#define VENC_YCOLVL                            0xC8
+#define VENC_SCPROG                            0xCC
+#define VENC_CVBS                              0xDC
+#define VENC_CMPNT                             0xE0
+#define VENC_ETMG0                             0xE4
+#define VENC_ETMG1                             0xE8
+#define VENC_ETMG2                             0xEC
+#define VENC_ETMG3                             0xF0
+#define VENC_DACSEL                            0xF4
+#define VENC_ARGBX0                            0x100
+#define VENC_ARGBX1                            0x104
+#define VENC_ARGBX2                            0x108
+#define VENC_ARGBX3                            0x10C
+#define VENC_ARGBX4                            0x110
+#define VENC_DRGBX0                            0x114
+#define VENC_DRGBX1                            0x118
+#define VENC_DRGBX2                            0x11C
+#define VENC_DRGBX3                            0x120
+#define VENC_DRGBX4                            0x124
+#define VENC_VSTARTA                           0x128
+#define VENC_OSDCLK0                           0x12C
+#define VENC_OSDCLK1                           0x130
+#define VENC_HVLDCL0                           0x134
+#define VENC_HVLDCL1                           0x138
+#define VENC_OSDHADV                           0x13C
+#define VENC_CLKCTL                            0x140
+#define VENC_GAMCTL                            0x144
+#define VENC_XHINTVL                           0x174
+
+/* bit definitions */
+#define VPBE_PCR_VENC_DIV                      (1 << 1)
+#define VPBE_PCR_CLK_OFF                       (1 << 0)
+
+#define VENC_VMOD_VDMD_SHIFT                   12
+#define VENC_VMOD_VDMD_YCBCR16                 0
+#define VENC_VMOD_VDMD_YCBCR8                  1
+#define VENC_VMOD_VDMD_RGB666                  2
+#define VENC_VMOD_VDMD_RGB8                    3
+#define VENC_VMOD_VDMD_EPSON                   4
+#define VENC_VMOD_VDMD_CASIO                   5
+#define VENC_VMOD_VDMD_UDISPQVGA               6
+#define VENC_VMOD_VDMD_STNLCD                  7
+#define VENC_VMOD_VIE_SHIFT                    1
+#define VENC_VMOD_VDMD                         (7 << 12)
+#define VENC_VMOD_ITLCL                                (1 << 11)
+#define VENC_VMOD_ITLC                         (1 << 10)
+#define VENC_VMOD_NSIT                         (1 << 9)
+#define VENC_VMOD_HDMD                         (1 << 8)
+#define VENC_VMOD_TVTYP_SHIFT                  6
+#define VENC_VMOD_TVTYP                                (3 << 6)
+#define VENC_VMOD_SLAVE                                (1 << 5)
+#define VENC_VMOD_VMD                          (1 << 4)
+#define VENC_VMOD_BLNK                         (1 << 3)
+#define VENC_VMOD_VIE                          (1 << 1)
+#define VENC_VMOD_VENC                         (1 << 0)
+
+/* VMOD TVTYP options for HDMD=0 */
+#define SDTV_NTSC                              0
+#define SDTV_PAL                               1
+/* VMOD TVTYP options for HDMD=1 */
+#define HDTV_525P                              0
+#define HDTV_625P                              1
+#define HDTV_1080I                             2
+#define HDTV_720P                              3
+
+#define VENC_VIDCTL_VCLKP                      (1 << 14)
+#define VENC_VIDCTL_VCLKE_SHIFT                        13
+#define VENC_VIDCTL_VCLKE                      (1 << 13)
+#define VENC_VIDCTL_VCLKZ_SHIFT                        12
+#define VENC_VIDCTL_VCLKZ                      (1 << 12)
+#define VENC_VIDCTL_SYDIR_SHIFT                        8
+#define VENC_VIDCTL_SYDIR                      (1 << 8)
+#define VENC_VIDCTL_DOMD_SHIFT                 4
+#define VENC_VIDCTL_DOMD                       (3 << 4)
+#define VENC_VIDCTL_YCDIR_SHIFT                        0
+#define VENC_VIDCTL_YCDIR                      (1 << 0)
+
+#define VENC_VDPRO_ATYCC_SHIFT                 5
+#define VENC_VDPRO_ATYCC                       (1 << 5)
+#define VENC_VDPRO_ATCOM_SHIFT                 4
+#define VENC_VDPRO_ATCOM                       (1 << 4)
+#define VENC_VDPRO_DAFRQ                       (1 << 3)
+#define VENC_VDPRO_DAUPS                       (1 << 2)
+#define VENC_VDPRO_CUPS                                (1 << 1)
+#define VENC_VDPRO_YUPS                                (1 << 0)
+
+#define VENC_SYNCCTL_VPL_SHIFT                 3
+#define VENC_SYNCCTL_VPL                       (1 << 3)
+#define VENC_SYNCCTL_HPL_SHIFT                 2
+#define VENC_SYNCCTL_HPL                       (1 << 2)
+#define VENC_SYNCCTL_SYEV_SHIFT                        1
+#define VENC_SYNCCTL_SYEV                      (1 << 1)
+#define VENC_SYNCCTL_SYEH_SHIFT                        0
+#define VENC_SYNCCTL_SYEH                      (1 << 0)
+#define VENC_SYNCCTL_OVD_SHIFT                 14
+#define VENC_SYNCCTL_OVD                       (1 << 14)
+
+#define VENC_DCLKCTL_DCKEC_SHIFT               11
+#define VENC_DCLKCTL_DCKEC                     (1 << 11)
+#define VENC_DCLKCTL_DCKPW_SHIFT               0
+#define VENC_DCLKCTL_DCKPW                     (0x3f << 0)
+
+#define VENC_VSTAT_FIDST                       (1 << 4)
+
+#define VENC_CMPNT_MRGB_SHIFT                  14
+#define VENC_CMPNT_MRGB                                (1 << 14)
+
+#endif                         /* _VPBE_VENC_REGS_H */
index d93ad74..49e4deb 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/version.h>
 #include <linux/slab.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
@@ -44,6 +43,7 @@
 
 MODULE_DESCRIPTION("TI DaVinci VPIF Capture driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(VPIF_CAPTURE_VERSION);
 
 #define vpif_err(fmt, arg...)  v4l2_err(&vpif_obj.v4l2_dev, fmt, ## arg)
 #define vpif_dbg(level, debug, fmt, arg...)    \
@@ -1677,7 +1677,6 @@ static int vpif_querycap(struct file *file, void  *priv,
 {
        struct vpif_capture_config *config = vpif_dev->platform_data;
 
-       cap->version = VPIF_CAPTURE_VERSION_CODE;
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
        strlcpy(cap->driver, "vpif capture", sizeof(cap->driver));
        strlcpy(cap->bus_info, "DM646x Platform", sizeof(cap->bus_info));
@@ -2211,10 +2210,8 @@ static __init int vpif_probe(struct platform_device *pdev)
                vfd->v4l2_dev = &vpif_obj.v4l2_dev;
                vfd->release = video_device_release;
                snprintf(vfd->name, sizeof(vfd->name),
-                        "DM646x_VPIFCapture_DRIVER_V%d.%d.%d",
-                        (VPIF_CAPTURE_VERSION_CODE >> 16) & 0xff,
-                        (VPIF_CAPTURE_VERSION_CODE >> 8) & 0xff,
-                        (VPIF_CAPTURE_VERSION_CODE) & 0xff);
+                        "DM646x_VPIFCapture_DRIVER_V%s",
+                        VPIF_CAPTURE_VERSION);
                /* Set video_dev to the video device */
                ch->video_dev = vfd;
        }
index 7a4196d..064550f 100644 (file)
@@ -23,7 +23,6 @@
 
 /* Header files */
 #include <linux/videodev2.h>
-#include <linux/version.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 #include <media/videobuf-core.h>
 #include "vpif.h"
 
 /* Macros */
-#define VPIF_MAJOR_RELEASE             0
-#define VPIF_MINOR_RELEASE             0
-#define VPIF_BUILD                     1
-#define VPIF_CAPTURE_VERSION_CODE      ((VPIF_MAJOR_RELEASE << 16) | \
-       (VPIF_MINOR_RELEASE << 8) | VPIF_BUILD)
+#define VPIF_CAPTURE_VERSION           "0.0.2"
 
 #define VPIF_VALID_FIELD(field)                (((V4L2_FIELD_ANY == field) || \
        (V4L2_FIELD_NONE == field)) || \
index cdf659a..286f029 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/version.h>
 #include <linux/slab.h>
 
 #include <asm/irq.h>
@@ -47,6 +46,7 @@
 
 MODULE_DESCRIPTION("TI DaVinci VPIF Display driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(VPIF_DISPLAY_VERSION);
 
 #define DM646X_V4L2_STD (V4L2_STD_525_60 | V4L2_STD_625_50)
 
@@ -701,7 +701,6 @@ static int vpif_querycap(struct file *file, void  *priv,
 {
        struct vpif_display_config *config = vpif_dev->platform_data;
 
-       cap->version = VPIF_DISPLAY_VERSION_CODE;
        cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
        strlcpy(cap->driver, "vpif display", sizeof(cap->driver));
        strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info));
@@ -1740,10 +1739,8 @@ static __init int vpif_probe(struct platform_device *pdev)
                vfd->v4l2_dev = &vpif_obj.v4l2_dev;
                vfd->release = video_device_release;
                snprintf(vfd->name, sizeof(vfd->name),
-                        "DM646x_VPIFDisplay_DRIVER_V%d.%d.%d",
-                        (VPIF_DISPLAY_VERSION_CODE >> 16) & 0xff,
-                        (VPIF_DISPLAY_VERSION_CODE >> 8) & 0xff,
-                        (VPIF_DISPLAY_VERSION_CODE) & 0xff);
+                        "DM646x_VPIFDisplay_DRIVER_V%s",
+                        VPIF_DISPLAY_VERSION);
 
                /* Set video_dev to the video device */
                ch->video_dev = vfd;
index b53aaa8..5d1936d 100644 (file)
@@ -18,7 +18,6 @@
 
 /* Header files */
 #include <linux/videodev2.h>
-#include <linux/version.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 #include <media/videobuf-core.h>
 #include "vpif.h"
 
 /* Macros */
-#define VPIF_MAJOR_RELEASE     (0)
-#define VPIF_MINOR_RELEASE     (0)
-#define VPIF_BUILD             (1)
-
-#define VPIF_DISPLAY_VERSION_CODE \
-       ((VPIF_MAJOR_RELEASE << 16) | (VPIF_MINOR_RELEASE << 8) | VPIF_BUILD)
+#define VPIF_DISPLAY_VERSION   "0.0.2"
 
 #define VPIF_VALID_FIELD(field) \
        (((V4L2_FIELD_ANY == field) || (V4L2_FIELD_NONE == field)) || \
index 3cb78f2..281ee42 100644 (file)
@@ -3,7 +3,6 @@ config VIDEO_EM28XX
        depends on VIDEO_DEV && I2C
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
-       depends on RC_CORE
        select VIDEOBUF_VMALLOC
        select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
@@ -40,7 +39,18 @@ config VIDEO_EM28XX_DVB
        select DVB_S921 if !DVB_FE_CUSTOMISE
        select DVB_DRXD if !DVB_FE_CUSTOMISE
        select DVB_CXD2820R if !DVB_FE_CUSTOMISE
+       select DVB_DRXK if !DVB_FE_CUSTOMISE
+       select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
        select VIDEOBUF_DVB
        ---help---
          This adds support for DVB cards based on the
          Empiatech em28xx chips.
+
+config VIDEO_EM28XX_RC
+        bool "EM28XX Remote Controller support"
+        depends on RC_CORE
+        depends on VIDEO_EM28XX
+        depends on !(RC_CORE=m && VIDEO_EM28XX=y)
+        default y
+        ---help---
+          Enables Remote Controller support on em28xx driver.
index d0f093d..38aaa00 100644 (file)
@@ -1,5 +1,7 @@
-em28xx-objs     := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \
-                  em28xx-input.o em28xx-vbi.o
+em28xx-y :=    em28xx-video.o em28xx-i2c.o em28xx-cards.o
+em28xx-y +=    em28xx-core.o  em28xx-vbi.o
+
+em28xx-$(CONFIG_VIDEO_EM28XX_RC) += em28xx-input.o
 
 em28xx-alsa-objs := em28xx-audio.o
 
index 3c48a72..cff0768 100644 (file)
@@ -3,9 +3,9 @@
  *
  *  Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com>
  *
- *  Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *  Copyright (C) 2007-2011 Mauro Carvalho Chehab <mchehab@redhat.com>
  *     - Port to work with the in-kernel driver
- *     - Several cleanups
+ *     - Cleanups, fixes, alsa-controls, etc.
  *
  *  This driver is based on my previous au600 usb pstn audio driver
  *  and inherits all the copyrights
@@ -41,6 +41,7 @@
 #include <sound/info.h>
 #include <sound/initval.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <media/v4l2-common.h>
 #include "em28xx.h"
 
@@ -212,9 +213,12 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
        for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
                errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
                if (errCode) {
+                       em28xx_errdev("submit of audio urb failed\n");
                        em28xx_deinit_isoc_audio(dev);
+                       atomic_set(&dev->stream_started, 0);
                        return errCode;
                }
+
        }
 
        return 0;
@@ -245,6 +249,7 @@ static struct snd_pcm_hardware snd_em28xx_hw_capture = {
        .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
                SNDRV_PCM_INFO_MMAP           |
                SNDRV_PCM_INFO_INTERLEAVED    |
+               SNDRV_PCM_INFO_BATCH          |
                SNDRV_PCM_INFO_MMAP_VALID,
 
        .formats = SNDRV_PCM_FMTBIT_S16_LE,
@@ -276,24 +281,27 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
                return -ENODEV;
        }
 
-       /* Sets volume, mute, etc */
+       runtime->hw = snd_em28xx_hw_capture;
+       if ((dev->alt == 0 || dev->audio_ifnum) && dev->adev.users == 0) {
+               if (dev->audio_ifnum)
+                       dev->alt = 1;
+               else
+                       dev->alt = 7;
 
-       dev->mute = 0;
-       mutex_lock(&dev->lock);
-       ret = em28xx_audio_analog_set(dev);
-       if (ret < 0)
-               goto err;
+               dprintk("changing alternate number on interface %d to %d\n",
+                       dev->audio_ifnum, dev->alt);
+               usb_set_interface(dev->udev, dev->audio_ifnum, dev->alt);
 
-       runtime->hw = snd_em28xx_hw_capture;
-       if (dev->alt == 0 && dev->adev.users == 0) {
-               int errCode;
-               dev->alt = 7;
-               dprintk("changing alternate number to 7\n");
-               errCode = usb_set_interface(dev->udev, 0, 7);
-       }
+               /* Sets volume, mute, etc */
+               dev->mute = 0;
+               mutex_lock(&dev->lock);
+               ret = em28xx_audio_analog_set(dev);
+               if (ret < 0)
+                       goto err;
 
-       dev->adev.users++;
-       mutex_unlock(&dev->lock);
+               dev->adev.users++;
+               mutex_unlock(&dev->lock);
+       }
 
        snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
        dev->adev.capture_pcm_substream = substream;
@@ -342,6 +350,8 @@ static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream,
 
        ret = snd_pcm_alloc_vmalloc_buffer(substream,
                                params_buffer_bytes(hw_params));
+       if (ret < 0)
+               return ret;
        format = params_format(hw_params);
        rate = params_rate(hw_params);
        channels = params_channels(hw_params);
@@ -393,20 +403,24 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
                                      int cmd)
 {
        struct em28xx *dev = snd_pcm_substream_chip(substream);
-       int retval;
+       int retval = 0;
 
        switch (cmd) {
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
+       case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
        case SNDRV_PCM_TRIGGER_START:
                atomic_set(&dev->stream_started, 1);
                break;
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
+       case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
        case SNDRV_PCM_TRIGGER_STOP:
-               atomic_set(&dev->stream_started, 1);
+               atomic_set(&dev->stream_started, 0);
                break;
        default:
                retval = -EINVAL;
        }
        schedule_work(&dev->wq_trigger);
-       return 0;
+       return retval;
 }
 
 static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
@@ -432,6 +446,179 @@ static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
        return vmalloc_to_page(pageptr);
 }
 
+/*
+ * AC97 volume control support
+ */
+static int em28xx_vol_info(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_info *info)
+{
+       info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       info->count = 2;
+       info->value.integer.min = 0;
+       info->value.integer.max = 0x1f;
+
+       return 0;
+}
+
+static int em28xx_vol_put(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+       u16 val = (0x1f - (value->value.integer.value[0] & 0x1f)) |
+                 (0x1f - (value->value.integer.value[1] & 0x1f)) << 8;
+       int rc;
+
+       mutex_lock(&dev->lock);
+       rc = em28xx_read_ac97(dev, kcontrol->private_value);
+       if (rc < 0)
+               goto err;
+
+       val |= rc & 0x8000;     /* Preserve the mute flag */
+
+       rc = em28xx_write_ac97(dev, kcontrol->private_value, val);
+       if (rc < 0)
+               goto err;
+
+       dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n",
+               (val & 0x8000) ? "muted " : "",
+               0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
+               val, (int)kcontrol->private_value);
+
+err:
+       mutex_unlock(&dev->lock);
+       return rc;
+}
+
+static int em28xx_vol_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+       int val;
+
+       mutex_lock(&dev->lock);
+       val = em28xx_read_ac97(dev, kcontrol->private_value);
+       mutex_unlock(&dev->lock);
+       if (val < 0)
+               return val;
+
+       dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n",
+               (val & 0x8000) ? "muted " : "",
+               0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
+               val, (int)kcontrol->private_value);
+
+       value->value.integer.value[0] = 0x1f - (val & 0x1f);
+       value->value.integer.value[1] = 0x1f - ((val << 8) & 0x1f);
+
+       return 0;
+}
+
+static int em28xx_vol_put_mute(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+       u16 val = value->value.integer.value[0];
+       int rc;
+
+       mutex_lock(&dev->lock);
+       rc = em28xx_read_ac97(dev, kcontrol->private_value);
+       if (rc < 0)
+               goto err;
+
+       if (val)
+               rc &= 0x1f1f;
+       else
+               rc |= 0x8000;
+
+       rc = em28xx_write_ac97(dev, kcontrol->private_value, rc);
+       if (rc < 0)
+               goto err;
+
+       dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n",
+               (val & 0x8000) ? "muted " : "",
+               0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
+               val, (int)kcontrol->private_value);
+
+err:
+       mutex_unlock(&dev->lock);
+       return rc;
+}
+
+static int em28xx_vol_get_mute(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+       int val;
+
+       mutex_lock(&dev->lock);
+       val = em28xx_read_ac97(dev, kcontrol->private_value);
+       mutex_unlock(&dev->lock);
+       if (val < 0)
+               return val;
+
+       if (val & 0x8000)
+               value->value.integer.value[0] = 0;
+       else
+               value->value.integer.value[0] = 1;
+
+       dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n",
+               (val & 0x8000) ? "muted " : "",
+               0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
+               val, (int)kcontrol->private_value);
+
+       return 0;
+}
+
+static const DECLARE_TLV_DB_SCALE(em28xx_db_scale, -3450, 150, 0);
+
+static int em28xx_cvol_new(struct snd_card *card, struct em28xx *dev,
+                          char *name, int id)
+{
+       int err;
+       char ctl_name[44];
+       struct snd_kcontrol *kctl;
+       struct snd_kcontrol_new tmp;
+
+       memset (&tmp, 0, sizeof(tmp));
+       tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       tmp.private_value = id,
+       tmp.name  = ctl_name,
+
+       /* Add Mute Control */
+       sprintf(ctl_name, "%s Switch", name);
+       tmp.get  = em28xx_vol_get_mute;
+       tmp.put  = em28xx_vol_put_mute;
+       tmp.info = snd_ctl_boolean_mono_info;
+       kctl = snd_ctl_new1(&tmp, dev);
+       err = snd_ctl_add(card, kctl);
+       if (err < 0)
+               return err;
+       dprintk("Added control %s for ac97 volume control 0x%04x\n",
+               ctl_name, id);
+
+       memset (&tmp, 0, sizeof(tmp));
+       tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       tmp.private_value = id,
+       tmp.name  = ctl_name,
+
+       /* Add Volume Control */
+       sprintf(ctl_name, "%s Volume", name);
+       tmp.get   = em28xx_vol_get;
+       tmp.put   = em28xx_vol_put;
+       tmp.info  = em28xx_vol_info;
+       tmp.tlv.p = em28xx_db_scale,
+       kctl = snd_ctl_new1(&tmp, dev);
+       err = snd_ctl_add(card, kctl);
+       if (err < 0)
+               return err;
+       dprintk("Added control %s for ac97 volume control 0x%04x\n",
+               ctl_name, id);
+
+       return 0;
+}
+
+/*
+ * register/unregister code and data
+ */
 static struct snd_pcm_ops snd_em28xx_pcm_capture = {
        .open      = snd_em28xx_capture_open,
        .close     = snd_em28xx_pcm_close,
@@ -452,17 +639,17 @@ static int em28xx_audio_init(struct em28xx *dev)
        static int          devnr;
        int                 err;
 
-       if (dev->has_alsa_audio != 1) {
+       if (!dev->has_alsa_audio || dev->audio_ifnum < 0) {
                /* This device does not support the extension (in this case
                   the device is expecting the snd-usb-audio module or
                   doesn't have analog audio support at all) */
                return 0;
        }
 
-       printk(KERN_INFO "em28xx-audio.c: probing for em28x1 "
-                        "non standard usbaudio\n");
+       printk(KERN_INFO "em28xx-audio.c: probing for em28xx Audio Vendor Class\n");
        printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
                         "Rechberger\n");
+       printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2007-2011 Mauro Carvalho Chehab\n");
 
        err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0,
                              &card);
@@ -488,6 +675,22 @@ static int em28xx_audio_init(struct em28xx *dev)
 
        INIT_WORK(&dev->wq_trigger, audio_trigger);
 
+       if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
+               em28xx_cvol_new(card, dev, "Video", AC97_VIDEO_VOL);
+               em28xx_cvol_new(card, dev, "Line In", AC97_LINEIN_VOL);
+               em28xx_cvol_new(card, dev, "Phone", AC97_PHONE_VOL);
+               em28xx_cvol_new(card, dev, "Microphone", AC97_PHONE_VOL);
+               em28xx_cvol_new(card, dev, "CD", AC97_CD_VOL);
+               em28xx_cvol_new(card, dev, "AUX", AC97_AUX_VOL);
+               em28xx_cvol_new(card, dev, "PCM", AC97_PCM_OUT_VOL);
+
+               em28xx_cvol_new(card, dev, "Master", AC97_MASTER_VOL);
+               em28xx_cvol_new(card, dev, "Line", AC97_LINE_LEVEL_VOL);
+               em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO_VOL);
+               em28xx_cvol_new(card, dev, "LFE", AC97_LFE_MASTER_VOL);
+               em28xx_cvol_new(card, dev, "Surround", AC97_SURR_MASTER_VOL);
+       }
+
        err = snd_card_register(card);
        if (err < 0) {
                snd_card_free(card);
@@ -538,7 +741,7 @@ static void __exit em28xx_alsa_unregister(void)
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
 MODULE_DESCRIPTION("Em28xx Audio driver");
 
 module_init(em28xx_alsa_register);
index 4e37375..3e3959f 100644 (file)
@@ -289,7 +289,7 @@ static struct em28xx_reg_seq leadership_reset[] = {
        {       -1,             -1,     -1,     -1},
 };
 
-/* 2013:024f PCTV Systems nanoStick T2 290e
+/* 2013:024f PCTV nanoStick T2 290e
  * GPIO_6 - demod reset
  * GPIO_7 - LED
  */
@@ -300,6 +300,23 @@ static struct em28xx_reg_seq pctv_290e[] = {
        {-1,                    -1,     -1,             -1},
 };
 
+#if 0
+static struct em28xx_reg_seq terratec_h5_gpio[] = {
+       {EM28XX_R08_GPIO,       0xff,   0xff,   10},
+       {EM2874_R80_GPIO,       0xf6,   0xff,   100},
+       {EM2874_R80_GPIO,       0xf2,   0xff,   50},
+       {EM2874_R80_GPIO,       0xf6,   0xff,   50},
+       { -1,                   -1,     -1,     -1},
+};
+
+static struct em28xx_reg_seq terratec_h5_digital[] = {
+       {EM2874_R80_GPIO,       0xf6,   0xff,   10},
+       {EM2874_R80_GPIO,       0xe6,   0xff,   100},
+       {EM2874_R80_GPIO,       0xa6,   0xff,   10},
+       { -1,                   -1,     -1,     -1},
+};
+#endif
+
 /*
  *  Board definitions
  */
@@ -843,6 +860,19 @@ struct em28xx_board em28xx_boards[] = {
                        .gpio     = terratec_cinergy_USB_XS_FR_analog,
                } },
        },
+       [EM2884_BOARD_TERRATEC_H5] = {
+               .name         = "Terratec Cinergy H5",
+               .has_dvb      = 1,
+#if 0
+               .tuner_type   = TUNER_PHILIPS_TDA8290,
+               .tuner_addr   = 0x41,
+               .dvb_gpio     = terratec_h5_digital, /* FIXME: probably wrong */
+               .tuner_gpio   = terratec_h5_gpio,
+#endif
+               .i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
+                               EM28XX_I2C_CLK_WAIT_ENABLE |
+                               EM28XX_I2C_FREQ_400_KHZ,
+       },
        [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = {
                .name         = "Hauppauge WinTV HVR 900",
                .tda9887_conf = TDA9887_PRESENT,
@@ -1259,7 +1289,7 @@ struct em28xx_board em28xx_boards[] = {
                } },
        },
 
-       [EM2874_LEADERSHIP_ISDBT] = {
+       [EM2874_BOARD_LEADERSHIP_ISDBT] = {
                .i2c_speed      = EM2874_I2C_SECONDARY_BUS_SELECT |
                                  EM28XX_I2C_CLK_WAIT_ENABLE |
                                  EM28XX_I2C_FREQ_100_KHZ,
@@ -1319,7 +1349,6 @@ struct em28xx_board em28xx_boards[] = {
        },
        [EM2880_BOARD_KWORLD_DVB_305U] = {
                .name         = "KWorld DVB-T 305U",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .tuner_type   = TUNER_XC2028,
                .tuner_gpio   = default_tuner_gpio,
                .decoder      = EM28XX_TVP5150,
@@ -1770,16 +1799,16 @@ struct em28xx_board em28xx_boards[] = {
                .dvb_gpio   = kworld_a340_digital,
                .tuner_gpio = default_tuner_gpio,
        },
-       /* 2013:024f PCTV Systems nanoStick T2 290e.
+       /* 2013:024f PCTV nanoStick T2 290e.
         * Empia EM28174, Sony CXD2820R and NXP TDA18271HD/C2 */
        [EM28174_BOARD_PCTV_290E] = {
+               .name          = "PCTV nanoStick T2 290e",
                .i2c_speed      = EM2874_I2C_SECONDARY_BUS_SELECT |
                        EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ,
-               .xclk          = EM28XX_XCLK_FREQUENCY_12MHZ,
-               .name          = "PCTV Systems nanoStick T2 290e",
                .tuner_type    = TUNER_ABSENT,
                .tuner_gpio    = pctv_290e,
                .has_dvb       = 1,
+               .ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
        },
 };
 const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
@@ -1855,8 +1884,10 @@ struct usb_device_id em28xx_id_table[] = {
        { USB_DEVICE(0x0ccd, 0x0042),
                        .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS },
        { USB_DEVICE(0x0ccd, 0x0043),
-                       .driver_info = EM2870_BOARD_TERRATEC_XS },
-       { USB_DEVICE(0x0ccd, 0x0047),
+                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
+       { USB_DEVICE(0x0ccd, 0x10a2),   /* Rev. 1 */
+                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
+       { USB_DEVICE(0x0ccd, 0x10ad),   /* Rev. 2 */
                        .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS },
        { USB_DEVICE(0x0ccd, 0x0084),
                        .driver_info = EM2860_BOARD_TERRATEC_AV350 },
@@ -1937,7 +1968,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
        {0x77800080, EM2860_BOARD_TVP5150_REFERENCE_DESIGN, TUNER_ABSENT},
        {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC},
        {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF},
-       {0x6b800080, EM2874_LEADERSHIP_ISDBT, TUNER_ABSENT},
+       {0x6b800080, EM2874_BOARD_LEADERSHIP_ISDBT, TUNER_ABSENT},
 };
 
 /* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
@@ -2660,10 +2691,9 @@ void em28xx_card_setup(struct em28xx *dev)
                        .addr = 0xba >> 1,
                        .platform_data = &pdata,
                };
-               struct v4l2_subdev *sd;
 
                pdata.xtal = dev->sensor_xtal;
-               sd = v4l2_i2c_new_subdev_board(&dev->v4l2_dev, &dev->i2c_adap,
+               v4l2_i2c_new_subdev_board(&dev->v4l2_dev, &dev->i2c_adap,
                                &mt9v011_info, NULL);
        }
 
@@ -2842,11 +2872,26 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
                        em28xx_info("chip ID is em2882/em2883\n");
                        dev->wait_after_write = 0;
                        break;
+               case CHIP_ID_EM2884:
+                       em28xx_info("chip ID is em2884\n");
+                       dev->reg_gpio_num = EM2874_R80_GPIO;
+                       dev->wait_after_write = 0;
+                       break;
                default:
                        em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
                }
        }
 
+       if (dev->is_audio_only) {
+               errCode = em28xx_audio_setup(dev);
+               if (errCode)
+                       return -ENODEV;
+               em28xx_add_into_devlist(dev);
+               em28xx_init_extension(dev);
+
+               return 0;
+       }
+
        /* Prepopulate cached GPO register content */
        retval = em28xx_read_reg(dev, dev->reg_gpo_num);
        if (retval >= 0)
@@ -2947,6 +2992,9 @@ fail_reg_devices:
        return retval;
 }
 
+/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
+#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
+
 /*
  * em28xx_usb_probe()
  * checks for supported devices
@@ -2956,15 +3004,15 @@ static int em28xx_usb_probe(struct usb_interface *interface,
 {
        const struct usb_endpoint_descriptor *endpoint;
        struct usb_device *udev;
-       struct usb_interface *uif;
        struct em28xx *dev = NULL;
        int retval;
-       int i, nr, ifnum, isoc_pipe;
+       bool is_audio_only = false, has_audio = false;
+       int i, nr, isoc_pipe;
+       const int ifnum = interface->altsetting[0].desc.bInterfaceNumber;
        char *speed;
        char descr[255] = "";
 
        udev = usb_get_dev(interface_to_usbdev(interface));
-       ifnum = interface->altsetting[0].desc.bInterfaceNumber;
 
        /* Check to see next free device and mark as used */
        nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
@@ -2984,6 +3032,19 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                goto err;
        }
 
+       /* Get endpoints */
+       for (i = 0; i < interface->num_altsetting; i++) {
+               int ep;
+
+               for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
+                       struct usb_host_endpoint        *e;
+                       e = &interface->altsetting[i].endpoint[ep];
+
+                       if (e->desc.bEndpointAddress == 0x83)
+                               has_audio = true;
+               }
+       }
+
        endpoint = &interface->cur_altsetting->endpoint[0].desc;
 
        /* check if the device has the iso in endpoint at the correct place */
@@ -3003,19 +3064,22 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                        check_interface = 0;
 
                if (!check_interface) {
-                       em28xx_err(DRIVER_NAME " video device (%04x:%04x): "
-                               "interface %i, class %i found.\n",
-                               le16_to_cpu(udev->descriptor.idVendor),
-                               le16_to_cpu(udev->descriptor.idProduct),
-                               ifnum,
-                               interface->altsetting[0].desc.bInterfaceClass);
-
-                       em28xx_err(DRIVER_NAME " This is an anciliary "
-                               "interface not used by the driver\n");
-
-                       em28xx_devused &= ~(1<<nr);
-                       retval = -ENODEV;
-                       goto err;
+                       if (has_audio) {
+                               is_audio_only = true;
+                       } else {
+                               em28xx_err(DRIVER_NAME " video device (%04x:%04x): "
+                                       "interface %i, class %i found.\n",
+                                       le16_to_cpu(udev->descriptor.idVendor),
+                                       le16_to_cpu(udev->descriptor.idProduct),
+                                       ifnum,
+                                       interface->altsetting[0].desc.bInterfaceClass);
+                               em28xx_err(DRIVER_NAME " This is an anciliary "
+                                       "interface not used by the driver\n");
+
+                               em28xx_devused &= ~(1<<nr);
+                               retval = -ENODEV;
+                               goto err;
+                       }
                }
        }
 
@@ -3045,8 +3109,8 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        if (*descr)
                strlcat(descr, " ", sizeof(descr));
 
-       printk(DRIVER_NAME ": New device %s@ %s Mbps "
-               "(%04x:%04x, interface %d, class %d)\n",
+       printk(KERN_INFO DRIVER_NAME
+               ": New device %s@ %s Mbps (%04x:%04x, interface %d, class %d)\n",
                descr,
                speed,
                le16_to_cpu(udev->descriptor.idVendor),
@@ -3054,6 +3118,11 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                ifnum,
                interface->altsetting->desc.bInterfaceNumber);
 
+       if (has_audio)
+               printk(KERN_INFO DRIVER_NAME
+                      ": Audio Vendor Class interface %i found\n",
+                      ifnum);
+
        /*
         * Make sure we have 480 Mbps of bandwidth, otherwise things like
         * video stream wouldn't likely work, since 12 Mbps is generally
@@ -3089,10 +3158,13 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        dev->devno = nr;
        dev->model = id->driver_info;
        dev->alt   = -1;
+       dev->is_audio_only = is_audio_only;
+       dev->has_alsa_audio = has_audio;
+       dev->audio_ifnum = ifnum;
 
        /* Checks if audio is provided by some interface */
        for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {
-               uif = udev->config->interface[i];
+               struct usb_interface *uif = udev->config->interface[i];
                if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
                        dev->has_audio_class = 1;
                        break;
@@ -3100,9 +3172,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        }
 
        /* compute alternate max packet sizes */
-       uif = udev->actconfig->interface[0];
-
-       dev->num_alt = uif->num_altsetting;
+       dev->num_alt = interface->num_altsetting;
        dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL);
 
        if (dev->alt_max_pkt_size == NULL) {
@@ -3114,14 +3184,21 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        }
 
        for (i = 0; i < dev->num_alt ; i++) {
-               u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
-               dev->alt_max_pkt_size[i] =
-                   (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+               u16 tmp = le16_to_cpu(interface->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
+               unsigned int size = tmp & 0x7ff;
+
+               if (udev->speed == USB_SPEED_HIGH)
+                       size = size * hb_mult(tmp);
+
+               dev->alt_max_pkt_size[i] = size;
        }
 
        if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
                dev->model = card[nr];
 
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(interface, dev);
+
        /* allocate device struct */
        mutex_init(&dev->lock);
        mutex_lock(&dev->lock);
@@ -3133,9 +3210,6 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                goto err;
        }
 
-       /* save our data pointer in this interface device */
-       usb_set_intfdata(interface, dev);
-
        request_modules(dev);
 
        /* Should be the last thing to do, to avoid newer udev's to
@@ -3164,6 +3238,13 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
        if (!dev)
                return;
 
+       if (dev->is_audio_only) {
+               mutex_lock(&dev->lock);
+               em28xx_close_extension(dev);
+               mutex_unlock(&dev->lock);
+               return;
+       }
+
        em28xx_info("disconnecting %s\n", dev->vdev->name);
 
        flush_request_modules(dev);
index e33f145..57b1b5c 100644 (file)
@@ -211,6 +211,7 @@ int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val)
 {
        return em28xx_write_regs(dev, reg, &val, 1);
 }
+EXPORT_SYMBOL_GPL(em28xx_write_reg);
 
 /*
  * em28xx_write_reg_bits()
@@ -286,6 +287,7 @@ int em28xx_read_ac97(struct em28xx *dev, u8 reg)
                return ret;
        return le16_to_cpu(val);
 }
+EXPORT_SYMBOL_GPL(em28xx_read_ac97);
 
 /*
  * em28xx_write_ac97()
@@ -313,13 +315,14 @@ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(em28xx_write_ac97);
 
-struct em28xx_vol_table {
+struct em28xx_vol_itable {
        enum em28xx_amux mux;
        u8               reg;
 };
 
-static struct em28xx_vol_table inputs[] = {
+static struct em28xx_vol_itable inputs[] = {
        { EM28XX_AMUX_VIDEO,    AC97_VIDEO_VOL   },
        { EM28XX_AMUX_LINE_IN,  AC97_LINEIN_VOL  },
        { EM28XX_AMUX_PHONE,    AC97_PHONE_VOL   },
@@ -403,7 +406,12 @@ static int em28xx_set_audio_source(struct em28xx *dev)
        return ret;
 }
 
-static const struct em28xx_vol_table outputs[] = {
+struct em28xx_vol_otable {
+       enum em28xx_aout mux;
+       u8               reg;
+};
+
+static const struct em28xx_vol_otable outputs[] = {
        { EM28XX_AOUT_MASTER, AC97_MASTER_VOL      },
        { EM28XX_AOUT_LINE,   AC97_LINE_LEVEL_VOL  },
        { EM28XX_AOUT_MONO,   AC97_MASTER_MONO_VOL },
@@ -492,17 +500,13 @@ int em28xx_audio_setup(struct em28xx *dev)
        if (dev->chip_id == CHIP_ID_EM2870 || dev->chip_id == CHIP_ID_EM2874
                || dev->chip_id == CHIP_ID_EM28174) {
                /* Digital only device - don't load any alsa module */
-               dev->audio_mode.has_audio = 0;
-               dev->has_audio_class = 0;
-               dev->has_alsa_audio = 0;
+               dev->audio_mode.has_audio = false;
+               dev->has_audio_class = false;
+               dev->has_alsa_audio = false;
                return 0;
        }
 
-       /* If device doesn't support Usb Audio Class, use vendor class */
-       if (!dev->has_audio_class)
-               dev->has_alsa_audio = 1;
-
-       dev->audio_mode.has_audio = 1;
+       dev->audio_mode.has_audio = true;
 
        /* See how this device is configured */
        cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG);
@@ -512,8 +516,8 @@ int em28xx_audio_setup(struct em28xx *dev)
                cfg = EM28XX_CHIPCFG_AC97; /* Be conservative */
        } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == 0x00) {
                /* The device doesn't have vendor audio at all */
-               dev->has_alsa_audio = 0;
-               dev->audio_mode.has_audio = 0;
+               dev->has_alsa_audio = false;
+               dev->audio_mode.has_audio = false;
                return 0;
        } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
                   EM28XX_CHIPCFG_I2S_3_SAMPRATES) {
@@ -542,8 +546,8 @@ int em28xx_audio_setup(struct em28xx *dev)
                 */
                em28xx_warn("AC97 chip type couldn't be determined\n");
                dev->audio_mode.ac97 = EM28XX_NO_AC97;
-               dev->has_alsa_audio = 0;
-               dev->audio_mode.has_audio = 0;
+               dev->has_alsa_audio = false;
+               dev->audio_mode.has_audio = false;
                goto init_audio;
        }
 
@@ -615,7 +619,9 @@ int em28xx_capture_start(struct em28xx *dev, int start)
 {
        int rc;
 
-       if (dev->chip_id == CHIP_ID_EM2874 || dev->chip_id == CHIP_ID_EM28174) {
+       if (dev->chip_id == CHIP_ID_EM2874 ||
+           dev->chip_id == CHIP_ID_EM2884 ||
+           dev->chip_id == CHIP_ID_EM28174) {
                /* The Transport Stream Enable Register moved in em2874 */
                if (!start) {
                        rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
@@ -884,6 +890,7 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
        }
        return rc;
 }
+EXPORT_SYMBOL_GPL(em28xx_gpio_set);
 
 int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
 {
@@ -917,7 +924,7 @@ EXPORT_SYMBOL_GPL(em28xx_set_mode);
 static void em28xx_irq_callback(struct urb *urb)
 {
        struct em28xx *dev = urb->context;
-       int rc, i;
+       int i;
 
        switch (urb->status) {
        case 0:             /* success */
@@ -934,7 +941,7 @@ static void em28xx_irq_callback(struct urb *urb)
 
        /* Copy data from URB */
        spin_lock(&dev->slock);
-       rc = dev->isoc_ctl.isoc_copy(dev, urb);
+       dev->isoc_ctl.isoc_copy(dev, urb);
        spin_unlock(&dev->slock);
 
        /* Reset urb buffers */
@@ -1106,17 +1113,19 @@ EXPORT_SYMBOL_GPL(em28xx_init_isoc);
 int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev)
 {
        unsigned int chip_cfg2;
-       unsigned int packet_size = 564;
-
-       if (dev->chip_id == CHIP_ID_EM2874) {
-               /* FIXME - for now assume 564 like it was before, but the
-                  em2874 code should be added to return the proper value... */
-               packet_size = 564;
-       } else if (dev->chip_id == CHIP_ID_EM28174) {
-               /* FIXME same as em2874. 564 was enough for 22 Mbit DVB-T
-                  but too much for 44 Mbit DVB-C. */
-               packet_size = 752;
-       } else {
+       unsigned int packet_size;
+
+       switch (dev->chip_id) {
+       case CHIP_ID_EM2710:
+       case CHIP_ID_EM2750:
+       case CHIP_ID_EM2800:
+       case CHIP_ID_EM2820:
+       case CHIP_ID_EM2840:
+       case CHIP_ID_EM2860:
+               /* No DVB support */
+               return -EINVAL;
+       case CHIP_ID_EM2870:
+       case CHIP_ID_EM2883:
                /* TS max packet size stored in bits 1-0 of R01 */
                chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2);
                switch (chip_cfg2 & EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK) {
@@ -1133,9 +1142,24 @@ int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev)
                        packet_size = 752;
                        break;
                }
+               break;
+       case CHIP_ID_EM2874:
+               /*
+                * FIXME: for now assumes 564 like it was before, but the
+                * em2874 code should be added to return the proper value
+                */
+               packet_size = 564;
+               break;
+       case CHIP_ID_EM2884:
+       case CHIP_ID_EM28174:
+       default:
+               /*
+                * FIXME: same as em2874. 564 was enough for 22 Mbit DVB-T
+                * but not enough for 44 Mbit DVB-C.
+                */
+               packet_size = 752;
        }
 
-       em28xx_coredbg("dvb max packet size=%d\n", packet_size);
        return packet_size;
 }
 EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize);
index 7904ca4..e5916de 100644 (file)
@@ -1,7 +1,7 @@
 /*
  DVB device driver for em28xx
 
- (c) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
+ (c) 2008-2011 Mauro Carvalho Chehab <mchehab@infradead.org>
 
  (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
        - Fixes for the driver to properly work with HVR-950
@@ -40,6 +40,8 @@
 #include "s921.h"
 #include "drxd.h"
 #include "cxd2820r.h"
+#include "tda18271c2dd.h"
+#include "drxk.h"
 
 MODULE_DESCRIPTION("driver for em28xx based DVB cards");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -73,6 +75,11 @@ struct em28xx_dvb {
        struct dmx_frontend        fe_hw;
        struct dmx_frontend        fe_mem;
        struct dvb_net             net;
+
+       /* Due to DRX-K - probably need changes */
+       int (*gate_ctrl)(struct dvb_frontend *, int);
+       struct semaphore      pll_mutex;
+       bool                    dont_attach_fe1;
 };
 
 
@@ -160,6 +167,11 @@ static int start_streaming(struct em28xx_dvb *dvb)
                return rc;
 
        max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev);
+       if (max_dvb_packet_size < 0)
+               return max_dvb_packet_size;
+       dprintk(1, "Using %d buffers each with %d bytes\n",
+               EM28XX_DVB_NUM_BUFS,
+               max_dvb_packet_size);
 
        return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
                                EM28XX_DVB_NUM_BUFS, max_dvb_packet_size,
@@ -295,6 +307,79 @@ static struct drxd_config em28xx_drxd = {
        .disable_i2c_gate_ctrl = 1,
 };
 
+struct drxk_config terratec_h5_drxk = {
+       .adr = 0x29,
+       .single_master = 1,
+       .no_i2c_bridge = 1,
+       .microcode_name = "dvb-usb-terratec-h5-drxk.fw",
+};
+
+static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct em28xx_dvb *dvb = fe->sec_priv;
+       int status;
+
+       if (!dvb)
+               return -EINVAL;
+
+       if (enable) {
+               down(&dvb->pll_mutex);
+               status = dvb->gate_ctrl(fe, 1);
+       } else {
+               status = dvb->gate_ctrl(fe, 0);
+               up(&dvb->pll_mutex);
+       }
+       return status;
+}
+
+static void terratec_h5_init(struct em28xx *dev)
+{
+       int i;
+       struct em28xx_reg_seq terratec_h5_init[] = {
+               {EM28XX_R08_GPIO,       0xff,   0xff,   10},
+               {EM2874_R80_GPIO,       0xf6,   0xff,   100},
+               {EM2874_R80_GPIO,       0xf2,   0xff,   50},
+               {EM2874_R80_GPIO,       0xf6,   0xff,   100},
+               { -1,                   -1,     -1,     -1},
+       };
+       struct em28xx_reg_seq terratec_h5_end[] = {
+               {EM2874_R80_GPIO,       0xe6,   0xff,   100},
+               {EM2874_R80_GPIO,       0xa6,   0xff,   50},
+               {EM2874_R80_GPIO,       0xe6,   0xff,   100},
+               { -1,                   -1,     -1,     -1},
+       };
+       struct {
+               unsigned char r[4];
+               int len;
+       } regs[] = {
+               {{ 0x06, 0x02, 0x00, 0x31 }, 4},
+               {{ 0x01, 0x02 }, 2},
+               {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0xff, 0xaf }, 4},
+               {{ 0x01, 0x00, 0x03, 0xa0 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0x73, 0xaf }, 4},
+               {{ 0x04, 0x00 }, 2},
+               {{ 0x00, 0x04 }, 2},
+               {{ 0x00, 0x04, 0x00, 0x0a }, 4},
+               {{ 0x04, 0x14 }, 2},
+               {{ 0x04, 0x14, 0x00, 0x00 }, 4},
+       };
+
+       em28xx_gpio_set(dev, terratec_h5_init);
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+       msleep(10);
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
+       msleep(10);
+
+       dev->i2c_client.addr = 0x82 >> 1;
+
+       for (i = 0; i < ARRAY_SIZE(regs); i++)
+               i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+       em28xx_gpio_set(dev, terratec_h5_end);
+};
+
 static int mt352_terratec_xs_init(struct dvb_frontend *fe)
 {
        /* Values extracted from a USB trace of the Terratec Windows driver */
@@ -516,7 +601,7 @@ static void unregister_dvb(struct em28xx_dvb *dvb)
        if (dvb->fe[1])
                dvb_unregister_frontend(dvb->fe[1]);
        dvb_unregister_frontend(dvb->fe[0]);
-       if (dvb->fe[1])
+       if (dvb->fe[1] && !dvb->dont_attach_fe1)
                dvb_frontend_detach(dvb->fe[1]);
        dvb_frontend_detach(dvb->fe[0]);
        dvb_unregister_adapter(&dvb->adapter);
@@ -546,7 +631,7 @@ static int dvb_init(struct em28xx *dev)
        em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
        /* init frontend */
        switch (dev->model) {
-       case EM2874_LEADERSHIP_ISDBT:
+       case EM2874_BOARD_LEADERSHIP_ISDBT:
                dvb->fe[0] = dvb_attach(s921_attach,
                                &sharp_isdbt, &dev->i2c_adap);
 
@@ -688,6 +773,41 @@ static int dvb_init(struct em28xx *dev)
                                /* leave FE 0 still active */
                        }
                }
+               break;
+       case EM2884_BOARD_TERRATEC_H5:
+               terratec_h5_init(dev);
+
+               dvb->dont_attach_fe1 = 1;
+
+               dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap, &dvb->fe[1]);
+               if (!dvb->fe[0]) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
+               /* FIXME: do we need a pll semaphore? */
+               dvb->fe[0]->sec_priv = dvb;
+               sema_init(&dvb->pll_mutex, 1);
+               dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
+               dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+               dvb->fe[1]->id = 1;
+
+               /* Attach tda18271 to DVB-C frontend */
+               if (dvb->fe[0]->ops.i2c_gate_ctrl)
+                       dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
+               if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap, 0x60)) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               if (dvb->fe[0]->ops.i2c_gate_ctrl)
+                       dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
+
+               /* Hack - needed by drxk/tda18271c2dd */
+               dvb->fe[1]->tuner_priv = dvb->fe[0]->tuner_priv;
+               memcpy(&dvb->fe[1]->ops.tuner_ops,
+                      &dvb->fe[0]->ops.tuner_ops,
+                      sizeof(dvb->fe[0]->ops.tuner_ops));
+
                break;
        default:
                em28xx_errdev("/2: The frontend of your DVB/ATSC card"
index 4739fc7..36f5a9b 100644 (file)
@@ -181,16 +181,25 @@ static int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
 
 /*
  * em28xx_i2c_send_bytes()
- * untested for more than 4 bytes
  */
 static int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf,
                                 short len, int stop)
 {
        int wrcount = 0;
        struct em28xx *dev = (struct em28xx *)data;
+       int write_timeout, ret;
 
        wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
 
+       /* Seems to be required after a write */
+       for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
+            write_timeout -= 5) {
+               ret = dev->em28xx_read_reg(dev, 0x05);
+               if (!ret)
+                       break;
+               msleep(5);
+       }
+
        return wrcount;
 }
 
@@ -218,9 +227,7 @@ static int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
  */
 static int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
 {
-       char msg;
        int ret;
-       msg = addr;
 
        ret = dev->em28xx_read_reg_req(dev, 2, addr);
        if (ret < 0) {
@@ -332,7 +339,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
        struct em28xx_eeprom *em_eeprom = (void *)eedata;
        int i, err, size = len, block;
 
-       if (dev->chip_id == CHIP_ID_EM2874 || dev->chip_id == CHIP_ID_EM28174) {
+       if (dev->chip_id == CHIP_ID_EM2874 ||
+           dev->chip_id == CHIP_ID_EM28174 ||
+           dev->chip_id == CHIP_ID_EM2884) {
                /* Empia switched to a 16-bit addressable eeprom in newer
                   devices.  While we could certainly write a routine to read
                   the eeprom, there is nothing of use in there that cannot be
index ba1ba86..5d12b14 100644 (file)
@@ -372,6 +372,7 @@ int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
                ir->get_key = default_polling_getkey;
                break;
        case CHIP_ID_EM2874:
+       case CHIP_ID_EM28174:
                ir->get_key = em2874_polling_getkey;
                em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
                break;
index e92a28e..66f7923 100644 (file)
@@ -201,6 +201,7 @@ enum em28xx_chip_id {
        CHIP_ID_EM2870 = 35,
        CHIP_ID_EM2883 = 36,
        CHIP_ID_EM2874 = 65,
+       CHIP_ID_EM2884 = 68,
        CHIP_ID_EM28174 = 113,
 };
 
index 7b6461d..d176dc0 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/bitmap.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
-#include <linux/version.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
@@ -50,7 +49,8 @@
                      "Sascha Sommer <saschasommer@freenet.de>"
 
 #define DRIVER_DESC         "Empia em28xx based USB video device driver"
-#define EM28XX_VERSION_CODE  KERNEL_VERSION(0, 1, 2)
+
+#define EM28XX_VERSION "0.1.3"
 
 #define em28xx_videodbg(fmt, arg...) do {\
        if (video_debug) \
@@ -72,6 +72,7 @@ do {\
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(EM28XX_VERSION);
 
 static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
 static unsigned int vbi_nr[]   = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
@@ -1757,8 +1758,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
        usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
 
-       cap->version = EM28XX_VERSION_CODE;
-
        cap->capabilities =
                        V4L2_CAP_SLICED_VBI_CAPTURE |
                        V4L2_CAP_VIDEO_CAPTURE |
@@ -1976,7 +1975,6 @@ static int radio_querycap(struct file *file, void  *priv,
        strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
        usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
 
-       cap->version = EM28XX_VERSION_CODE;
        cap->capabilities = V4L2_CAP_TUNER;
        return 0;
 }
@@ -2450,10 +2448,8 @@ int em28xx_register_analog_devices(struct em28xx *dev)
       u8 val;
        int ret;
 
-       printk(KERN_INFO "%s: v4l2 driver version %d.%d.%d\n",
-               dev->name,
-               (EM28XX_VERSION_CODE >> 16) & 0xff,
-               (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff);
+       printk(KERN_INFO "%s: v4l2 driver version %s\n",
+               dev->name, EM28XX_VERSION);
 
        /* set default norm */
        dev->norm = em28xx_video_template.current_norm;
index 3cca331..d80658b 100644 (file)
 #define EM2800_BOARD_VC211A                      74
 #define EM2882_BOARD_DIKOM_DK300                 75
 #define EM2870_BOARD_KWORLD_A340                 76
-#define EM2874_LEADERSHIP_ISDBT                          77
+#define EM2874_BOARD_LEADERSHIP_ISDBT            77
 #define EM28174_BOARD_PCTV_290E                   78
-
+#define EM2884_BOARD_TERRATEC_H5                 79
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
@@ -487,6 +487,8 @@ struct em28xx {
        int devno;              /* marks the number of this device */
        enum em28xx_chip_id chip_id;
 
+       int audio_ifnum;
+
        struct v4l2_device v4l2_dev;
        struct em28xx_board board;
 
@@ -503,6 +505,7 @@ struct em28xx {
 
        unsigned int has_audio_class:1;
        unsigned int has_alsa_audio:1;
+       unsigned int is_audio_only:1;
 
        /* Controls audio streaming */
        struct work_struct wq_trigger;              /* Trigger to start/stop audio for alsa module */
@@ -697,6 +700,9 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
 void em28xx_release_resources(struct em28xx *dev);
 
 /* Provided by em28xx-input.c */
+
+#ifdef CONFIG_VIDEO_EM28XX_RC
+
 int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
 int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
 int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
@@ -709,6 +715,20 @@ void em28xx_deregister_snapshot_button(struct em28xx *dev);
 int em28xx_ir_init(struct em28xx *dev);
 int em28xx_ir_fini(struct em28xx *dev);
 
+#else
+
+#define em28xx_get_key_terratec                        NULL
+#define em28xx_get_key_em_haup                 NULL
+#define em28xx_get_key_pinnacle_usb_grey       NULL
+#define em28xx_get_key_winfast_usbii_deluxe    NULL
+
+static inline void em28xx_register_snapshot_button(struct em28xx *dev) {}
+static inline void em28xx_deregister_snapshot_button(struct em28xx *dev) {}
+static inline int em28xx_ir_init(struct em28xx *dev) { return 0; }
+static inline int em28xx_ir_fini(struct em28xx *dev) { return 0; }
+
+#endif
+
 /* Provided by em28xx-vbi.c */
 extern struct videobuf_queue_ops em28xx_vbi_qops;
 
index bf66189..14bb907 100644 (file)
@@ -21,7 +21,6 @@
 #ifndef _ET61X251_H_
 #define _ET61X251_H_
 
-#include <linux/version.h>
 #include <linux/usb.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
index a982750..9a1e80a 100644 (file)
@@ -18,6 +18,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
  ***************************************************************************/
 
+#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -48,8 +49,7 @@
 #define ET61X251_MODULE_AUTHOR  "(C) 2006-2007 Luca Risolia"
 #define ET61X251_AUTHOR_EMAIL   "<luca.risolia@studio.unibo.it>"
 #define ET61X251_MODULE_LICENSE "GPL"
-#define ET61X251_MODULE_VERSION "1:1.09"
-#define ET61X251_MODULE_VERSION_CODE  KERNEL_VERSION(1, 1, 9)
+#define ET61X251_MODULE_VERSION "1.1.10"
 
 /*****************************************************************************/
 
@@ -1579,7 +1579,7 @@ et61x251_vidioc_querycap(struct et61x251_device* cam, void __user * arg)
 {
        struct v4l2_capability cap = {
                .driver = "et61x251",
-               .version = ET61X251_MODULE_VERSION_CODE,
+               .version = LINUX_VERSION_CODE,
                .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
                                V4L2_CAP_STREAMING,
        };
@@ -2480,16 +2480,8 @@ static long et61x251_ioctl_v4l2(struct file *filp,
        case VIDIOC_S_PARM:
                return et61x251_vidioc_s_parm(cam, arg);
 
-       case VIDIOC_G_STD:
-       case VIDIOC_S_STD:
-       case VIDIOC_QUERYSTD:
-       case VIDIOC_ENUMSTD:
-       case VIDIOC_QUERYMENU:
-       case VIDIOC_ENUM_FRAMEINTERVALS:
-               return -EINVAL;
-
        default:
-               return -EINVAL;
+               return -ENOTTY;
 
        }
 }
index 908d701..27cb197 100644 (file)
 #include <linux/io.h>
 #include <linux/of_platform.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/videobuf-dma-contig.h>
 
 #define DRV_NAME               "fsl_viu"
-#define VIU_MAJOR_VERSION      0
-#define VIU_MINOR_VERSION      5
-#define VIU_RELEASE            0
-#define VIU_VERSION            KERNEL_VERSION(VIU_MAJOR_VERSION, \
-                                              VIU_MINOR_VERSION, \
-                                              VIU_RELEASE)
+#define VIU_VERSION            "0.5.1"
 
 #define BUFFER_TIMEOUT         msecs_to_jiffies(500)  /* 0.5 seconds */
 
@@ -610,7 +604,6 @@ static int vidioc_querycap(struct file *file, void *priv,
 {
        strcpy(cap->driver, "viu");
        strcpy(cap->card, "viu");
-       cap->version = VIU_VERSION;
        cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
                                V4L2_CAP_STREAMING     |
                                V4L2_CAP_VIDEO_OVERLAY |
@@ -1684,3 +1677,4 @@ module_exit(viu_exit);
 MODULE_DESCRIPTION("Freescale Video-In(VIU)");
 MODULE_AUTHOR("Hongjun Chen");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(VIU_VERSION);
index 34ae2c2..43d9a20 100644 (file)
@@ -179,6 +179,16 @@ config USB_GSPCA_PAC7311
          To compile this driver as a module, choose M here: the
          module will be called gspca_pac7311.
 
+config USB_GSPCA_SE401
+       tristate "SE401 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+        Say Y here if you want support for cameras based on the
+        Endpoints (formerly known as AOX) se401 chip.
+
+        To compile this driver as a module, choose M here: the
+        module will be called gspca_se401.
+
 config USB_GSPCA_SN9C2028
        tristate "SONIX Dual-Mode USB Camera Driver"
        depends on VIDEO_V4L2 && USB_GSPCA
index 802fbe1..d6364a8 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_USB_GSPCA_OV534_9)  += gspca_ov534_9.o
 obj-$(CONFIG_USB_GSPCA_PAC207)   += gspca_pac207.o
 obj-$(CONFIG_USB_GSPCA_PAC7302)  += gspca_pac7302.o
 obj-$(CONFIG_USB_GSPCA_PAC7311)  += gspca_pac7311.o
+obj-$(CONFIG_USB_GSPCA_SE401)    += gspca_se401.o
 obj-$(CONFIG_USB_GSPCA_SN9C2028) += gspca_sn9c2028.o
 obj-$(CONFIG_USB_GSPCA_SN9C20X)  += gspca_sn9c20x.o
 obj-$(CONFIG_USB_GSPCA_SONIXB)   += gspca_sonixb.o
@@ -58,6 +59,7 @@ gspca_ov534_9-objs  := ov534_9.o
 gspca_pac207-objs   := pac207.o
 gspca_pac7302-objs  := pac7302.o
 gspca_pac7311-objs  := pac7311.o
+gspca_se401-objs    := se401.o
 gspca_sn9c2028-objs := sn9c2028.o
 gspca_sn9c20x-objs  := sn9c20x.o
 gspca_sonixb-objs   := sonixb.o
index 49ad4ac..0330a02 100644 (file)
@@ -18,7 +18,6 @@
  */
 #ifndef GL860_DEV_H
 #define GL860_DEV_H
-#include <linux/version.h>
 
 #include "gspca.h"
 
index 08ce994..5da4879 100644 (file)
@@ -24,7 +24,6 @@
 #define MODULE_NAME "gspca"
 
 #include <linux/init.h>
-#include <linux/version.h>
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
 #include <linux/sched.h>
 #error "DEF_NURBS too big"
 #endif
 
+#define DRIVER_VERSION_NUMBER  "2.13.0"
+
 MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
 MODULE_DESCRIPTION("GSPCA USB Camera Driver");
 MODULE_LICENSE("GPL");
-
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 13, 0)
+MODULE_VERSION(DRIVER_VERSION_NUMBER);
 
 #ifdef GSPCA_DEBUG
 int gspca_debug = D_ERR | D_PROBE;
@@ -443,8 +443,11 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
        } else {
                switch (gspca_dev->last_packet_type) {
                case DISCARD_PACKET:
-                       if (packet_type == LAST_PACKET)
+                       if (packet_type == LAST_PACKET) {
                                gspca_dev->last_packet_type = packet_type;
+                               gspca_dev->image = NULL;
+                               gspca_dev->image_len = 0;
+                       }
                        return;
                case LAST_PACKET:
                        return;
@@ -1278,10 +1281,10 @@ static int vidioc_querycap(struct file *file, void  *priv,
                ret = -ENODEV;
                goto out;
        }
-       strncpy((char *) cap->driver, gspca_dev->sd_desc->name,
+       strlcpy((char *) cap->driver, gspca_dev->sd_desc->name,
                        sizeof cap->driver);
        if (gspca_dev->dev->product != NULL) {
-               strncpy((char *) cap->card, gspca_dev->dev->product,
+               strlcpy((char *) cap->card, gspca_dev->dev->product,
                        sizeof cap->card);
        } else {
                snprintf((char *) cap->card, sizeof cap->card,
@@ -1291,7 +1294,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        }
        usb_make_path(gspca_dev->dev, (char *) cap->bus_info,
                        sizeof(cap->bus_info));
-       cap->version = DRIVER_VERSION_NUMBER;
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
                          | V4L2_CAP_STREAMING
                          | V4L2_CAP_READWRITE;
@@ -1460,7 +1462,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
                return -EINVAL;
        input->type = V4L2_INPUT_TYPE_CAMERA;
        input->status = gspca_dev->cam.input_flags;
-       strncpy(input->name, gspca_dev->sd_desc->name,
+       strlcpy(input->name, gspca_dev->sd_desc->name,
                sizeof input->name);
        return 0;
 }
@@ -2478,10 +2480,7 @@ EXPORT_SYMBOL(gspca_auto_gain_n_exposure);
 /* -- module insert / remove -- */
 static int __init gspca_init(void)
 {
-       info("v%d.%d.%d registered",
-               (DRIVER_VERSION_NUMBER >> 16) & 0xff,
-               (DRIVER_VERSION_NUMBER >> 8) & 0xff,
-               DRIVER_VERSION_NUMBER & 0xff);
+       info("v" DRIVER_VERSION_NUMBER " registered");
        return 0;
 }
 static void __exit gspca_exit(void)
index 057e287..0800433 100644 (file)
@@ -134,6 +134,7 @@ enum sensors {
        SEN_OV7670,
        SEN_OV76BE,
        SEN_OV8610,
+       SEN_OV9600,
 };
 
 /* Note this is a bit of a hack, but the w9968cf driver needs the code for all
@@ -340,6 +341,10 @@ static const unsigned ctrl_dis[] = {
                        (1 << EXPOSURE) |
                        (1 << AUTOGAIN) |
                        (1 << FREQ),
+[SEN_OV9600] =         ((1 << NCTRL) - 1)      /* no control */
+                       ^ ((1 << EXPOSURE)      /* but exposure */
+                        | (1 << AUTOGAIN)),    /* and autogain */
+
 };
 
 static const struct v4l2_pix_format ov519_vga_mode[] = {
@@ -525,6 +530,17 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 0},
 };
+static const struct v4l2_pix_format ovfx2_ov9600_mode[] = {
+       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 1280,
+               .sizeimage = 1280 * 1024,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+};
 
 /* Registers common to OV511 / OV518 */
 #define R51x_FIFO_PSIZE                        0x30    /* 2 bytes wide w/ OV518(+) */
@@ -1807,6 +1823,22 @@ static const struct ov_i2c_regvals norm_7660[] = {
                        | OV7670_COM8_AEC},
        {0xa1, 0xc8}
 };
+static const struct ov_i2c_regvals norm_9600[] = {
+       {0x12, 0x80},
+       {0x0c, 0x28},
+       {0x11, 0x80},
+       {0x13, 0xb5},
+       {0x14, 0x3e},
+       {0x1b, 0x04},
+       {0x24, 0xb0},
+       {0x25, 0x90},
+       {0x26, 0x94},
+       {0x35, 0x90},
+       {0x37, 0x07},
+       {0x38, 0x08},
+       {0x01, 0x8e},
+       {0x02, 0x85}
+};
 
 /* 7670. Defaults taken from OmniVision provided data,
 *  as provided by Jonathan Corbet of OLPC              */
@@ -2400,9 +2432,12 @@ static int ov518_i2c_r(struct sd *sd, u8 reg)
 
        /* Initiate 2-byte write cycle */
        reg_w(sd, R518_I2C_CTL, 0x03);
+       reg_r8(sd, R518_I2C_CTL);
 
        /* Initiate 2-byte read cycle */
        reg_w(sd, R518_I2C_CTL, 0x05);
+       reg_r8(sd, R518_I2C_CTL);
+
        value = reg_r(sd, R51x_I2C_DATA);
        PDEBUG(D_USBI, "ov518_i2c_r %02x %02x", reg, value);
        return value;
@@ -2686,7 +2721,7 @@ static void write_i2c_regvals(struct sd *sd,
  *
  ***************************************************************************/
 
-/* This initializes the OV2x10 / OV3610 / OV3620 */
+/* This initializes the OV2x10 / OV3610 / OV3620 / OV9600 */
 static void ov_hires_configure(struct sd *sd)
 {
        int high, low;
@@ -2702,19 +2737,32 @@ static void ov_hires_configure(struct sd *sd)
        high = i2c_r(sd, 0x0a);
        low = i2c_r(sd, 0x0b);
        /* info("%x, %x", high, low); */
-       if (high == 0x96 && low == 0x40) {
-               PDEBUG(D_PROBE, "Sensor is an OV2610");
-               sd->sensor = SEN_OV2610;
-       } else if (high == 0x96 && low == 0x41) {
-               PDEBUG(D_PROBE, "Sensor is an OV2610AE");
-               sd->sensor = SEN_OV2610AE;
-       } else if (high == 0x36 && (low & 0x0f) == 0x00) {
-               PDEBUG(D_PROBE, "Sensor is an OV3610");
-               sd->sensor = SEN_OV3610;
-       } else {
-               err("Error unknown sensor type: %02x%02x",
-                       high, low);
+       switch (high) {
+       case 0x96:
+               switch (low) {
+               case 0x40:
+                       PDEBUG(D_PROBE, "Sensor is a OV2610");
+                       sd->sensor = SEN_OV2610;
+                       return;
+               case 0x41:
+                       PDEBUG(D_PROBE, "Sensor is a OV2610AE");
+                       sd->sensor = SEN_OV2610AE;
+                       return;
+               case 0xb1:
+                       PDEBUG(D_PROBE, "Sensor is a OV9600");
+                       sd->sensor = SEN_OV9600;
+                       return;
+               }
+               break;
+       case 0x36:
+               if ((low & 0x0f) == 0x00) {
+                       PDEBUG(D_PROBE, "Sensor is a OV3610");
+                       sd->sensor = SEN_OV3610;
+                       return;
+               }
+               break;
        }
+       err("Error unknown sensor type: %02x%02x", high, low);
 }
 
 /* This initializes the OV8110, OV8610 sensor. The OV8110 uses
@@ -3400,6 +3448,10 @@ static int sd_init(struct gspca_dev *gspca_dev)
                        cam->cam_mode = ovfx2_ov3610_mode;
                        cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode);
                        break;
+               case SEN_OV9600:
+                       cam->cam_mode = ovfx2_ov9600_mode;
+                       cam->nmodes = ARRAY_SIZE(ovfx2_ov9600_mode);
+                       break;
                default:
                        if (sd->sif) {
                                cam->cam_mode = ov519_sif_mode;
@@ -3497,6 +3549,12 @@ static int sd_init(struct gspca_dev *gspca_dev)
        case SEN_OV8610:
                write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610));
                break;
+       case SEN_OV9600:
+               write_i2c_regvals(sd, norm_9600, ARRAY_SIZE(norm_9600));
+
+               /* enable autoexpo */
+/*             i2c_w_mask(sd, 0x13, 0x05, 0x05); */
+               break;
        }
        return gspca_dev->usb_err;
 error:
@@ -4085,6 +4143,33 @@ static void mode_init_ov_sensor_regs(struct sd *sd)
                i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
                i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
                break;
+       case SEN_OV9600: {
+               const struct ov_i2c_regvals *vals;
+               static const struct ov_i2c_regvals sxga_15[] = {
+                       {0x11, 0x80}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
+               };
+               static const struct ov_i2c_regvals sxga_7_5[] = {
+                       {0x11, 0x81}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
+               };
+               static const struct ov_i2c_regvals vga_30[] = {
+                       {0x11, 0x81}, {0x14, 0x7e}, {0x24, 0x70}, {0x25, 0x60}
+               };
+               static const struct ov_i2c_regvals vga_15[] = {
+                       {0x11, 0x83}, {0x14, 0x3e}, {0x24, 0x80}, {0x25, 0x70}
+               };
+
+               /* frame rates:
+                *      15fps / 7.5 fps for 1280x1024
+                *      30fps / 15fps for 640x480
+                */
+               i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0x40);
+               if (qvga)
+                       vals = sd->frame_rate < 30 ? vga_15 : vga_30;
+               else
+                       vals = sd->frame_rate < 15 ? sxga_7_5 : sxga_15;
+               write_i2c_regvals(sd, vals, ARRAY_SIZE(sxga_15));
+               return;
+           }
        default:
                return;
        }
@@ -4120,6 +4205,7 @@ static void set_ov_sensor_window(struct sd *sd)
        case SEN_OV2610AE:
        case SEN_OV3610:
        case SEN_OV7670:
+       case SEN_OV9600:
                mode_init_ov_sensor_regs(sd);
                return;
        case SEN_OV7660:
@@ -4920,7 +5006,8 @@ static const struct sd_desc sd_desc = {
 static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF },
        {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x041e, 0x405f),
+               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
        {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x041e, 0x4064),
diff --git a/drivers/media/video/gspca/se401.c b/drivers/media/video/gspca/se401.c
new file mode 100644 (file)
index 0000000..4c283c2
--- /dev/null
@@ -0,0 +1,774 @@
+/*
+ * GSPCA Endpoints (formerly known as AOX) se401 USB Camera sub Driver
+ *
+ * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on the v4l1 se401 driver which is:
+ *
+ * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define MODULE_NAME "se401"
+
+#define BULK_SIZE 4096
+#define PACKET_SIZE 1024
+#define READ_REQ_SIZE 64
+#define MAX_MODES ((READ_REQ_SIZE - 6) / 4)
+/* The se401 compression algorithm uses a fixed quant factor, which
+   can be configured by setting the high nibble of the SE401_OPERATINGMODE
+   feature. This needs to exactly match what is in libv4l! */
+#define SE401_QUANT_FACT 8
+
+#include <linux/input.h>
+#include <linux/slab.h>
+#include "gspca.h"
+#include "se401.h"
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("Endpoints se401");
+MODULE_LICENSE("GPL");
+
+/* controls */
+enum e_ctrl {
+       BRIGHTNESS,
+       GAIN,
+       EXPOSURE,
+       FREQ,
+       NCTRL   /* number of controls */
+};
+
+/* exposure change state machine states */
+enum {
+       EXPO_CHANGED,
+       EXPO_DROP_FRAME,
+       EXPO_NO_CHANGE,
+};
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+       struct gspca_ctrl ctrls[NCTRL];
+       struct v4l2_pix_format fmts[MAX_MODES];
+       int pixels_read;
+       int packet_read;
+       u8 packet[PACKET_SIZE];
+       u8 restart_stream;
+       u8 button_state;
+       u8 resetlevel;
+       u8 resetlevel_frame_count;
+       int resetlevel_adjust_dir;
+       int expo_change_state;
+};
+
+static void setbrightness(struct gspca_dev *gspca_dev);
+static void setgain(struct gspca_dev *gspca_dev);
+static void setexposure(struct gspca_dev *gspca_dev);
+
+static const struct ctrl sd_ctrls[NCTRL] = {
+[BRIGHTNESS] = {
+               {
+                       .id      = V4L2_CID_BRIGHTNESS,
+                       .type    = V4L2_CTRL_TYPE_INTEGER,
+                       .name    = "Brightness",
+                       .minimum = 0,
+                       .maximum = 255,
+                       .step    = 1,
+                       .default_value = 15,
+               },
+               .set_control = setbrightness
+       },
+[GAIN] = {
+               {
+                       .id      = V4L2_CID_GAIN,
+                       .type    = V4L2_CTRL_TYPE_INTEGER,
+                       .name    = "Gain",
+                       .minimum = 0,
+                       .maximum = 50, /* Really 63 but > 50 is not pretty */
+                       .step    = 1,
+                       .default_value = 25,
+               },
+               .set_control = setgain
+       },
+[EXPOSURE] = {
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "Exposure",
+                       .minimum = 0,
+                       .maximum = 32767,
+                       .step = 1,
+                       .default_value = 15000,
+               },
+               .set_control = setexposure
+       },
+[FREQ] = {
+               {
+                       .id      = V4L2_CID_POWER_LINE_FREQUENCY,
+                       .type    = V4L2_CTRL_TYPE_MENU,
+                       .name    = "Light frequency filter",
+                       .minimum = 0,
+                       .maximum = 2,
+                       .step    = 1,
+                       .default_value = 0,
+               },
+               .set_control = setexposure
+       },
+};
+
+static void se401_write_req(struct gspca_dev *gspca_dev, u16 req, u16 value,
+                           int silent)
+{
+       int err;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       err = usb_control_msg(gspca_dev->dev,
+                             usb_sndctrlpipe(gspca_dev->dev, 0), req,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             value, 0, NULL, 0, 1000);
+       if (err < 0) {
+               if (!silent)
+                       err("write req failed req %#04x val %#04x error %d",
+                           req, value, err);
+               gspca_dev->usb_err = err;
+       }
+}
+
+static void se401_read_req(struct gspca_dev *gspca_dev, u16 req, int silent)
+{
+       int err;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       if (USB_BUF_SZ < READ_REQ_SIZE) {
+               err("USB_BUF_SZ too small!!");
+               gspca_dev->usb_err = -ENOBUFS;
+               return;
+       }
+
+       err = usb_control_msg(gspca_dev->dev,
+                             usb_rcvctrlpipe(gspca_dev->dev, 0), req,
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0, 0, gspca_dev->usb_buf, READ_REQ_SIZE, 1000);
+       if (err < 0) {
+               if (!silent)
+                       err("read req failed req %#04x error %d", req, err);
+               gspca_dev->usb_err = err;
+       }
+}
+
+static void se401_set_feature(struct gspca_dev *gspca_dev,
+                             u16 selector, u16 param)
+{
+       int err;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       err = usb_control_msg(gspca_dev->dev,
+                             usb_sndctrlpipe(gspca_dev->dev, 0),
+                             SE401_REQ_SET_EXT_FEATURE,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             param, selector, NULL, 0, 1000);
+       if (err < 0) {
+               err("set feature failed sel %#04x param %#04x error %d",
+                   selector, param, err);
+               gspca_dev->usb_err = err;
+       }
+}
+
+static int se401_get_feature(struct gspca_dev *gspca_dev, u16 selector)
+{
+       int err;
+
+       if (gspca_dev->usb_err < 0)
+               return gspca_dev->usb_err;
+
+       if (USB_BUF_SZ < 2) {
+               err("USB_BUF_SZ too small!!");
+               gspca_dev->usb_err = -ENOBUFS;
+               return gspca_dev->usb_err;
+       }
+
+       err = usb_control_msg(gspca_dev->dev,
+                             usb_rcvctrlpipe(gspca_dev->dev, 0),
+                             SE401_REQ_GET_EXT_FEATURE,
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0, selector, gspca_dev->usb_buf, 2, 1000);
+       if (err < 0) {
+               err("get feature failed sel %#04x error %d", selector, err);
+               gspca_dev->usb_err = err;
+               return err;
+       }
+       return gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS))
+               return;
+
+       /* HDG: this does not seem to do anything on my cam */
+       se401_write_req(gspca_dev, SE401_REQ_SET_BRT,
+                       sd->ctrls[BRIGHTNESS].val, 0);
+}
+
+static void setgain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 gain = 63 - sd->ctrls[GAIN].val;
+
+       /* red color gain */
+       se401_set_feature(gspca_dev, HV7131_REG_ARCG, gain);
+       /* green color gain */
+       se401_set_feature(gspca_dev, HV7131_REG_AGCG, gain);
+       /* blue color gain */
+       se401_set_feature(gspca_dev, HV7131_REG_ABCG, gain);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int integration = sd->ctrls[EXPOSURE].val << 6;
+       u8 expose_h, expose_m, expose_l;
+
+       /* Do this before the set_feature calls, for proper timing wrt
+          the interrupt driven pkt_scan. Note we may still race but that
+          is not a big issue, the expo change state machine is merely for
+          avoiding underexposed frames getting send out, if one sneaks
+          through so be it */
+       sd->expo_change_state = EXPO_CHANGED;
+
+       if (sd->ctrls[FREQ].val == V4L2_CID_POWER_LINE_FREQUENCY_50HZ)
+               integration = integration - integration % 106667;
+       if (sd->ctrls[FREQ].val == V4L2_CID_POWER_LINE_FREQUENCY_60HZ)
+               integration = integration - integration % 88889;
+
+       expose_h = (integration >> 16);
+       expose_m = (integration >> 8);
+       expose_l = integration;
+
+       /* integration time low */
+       se401_set_feature(gspca_dev, HV7131_REG_TITL, expose_l);
+       /* integration time mid */
+       se401_set_feature(gspca_dev, HV7131_REG_TITM, expose_m);
+       /* integration time high */
+       se401_set_feature(gspca_dev, HV7131_REG_TITU, expose_h);
+}
+
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
+       u8 *cd = gspca_dev->usb_buf;
+       int i, j, n;
+       int widths[MAX_MODES], heights[MAX_MODES];
+
+       /* Read the camera descriptor */
+       se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 1);
+       if (gspca_dev->usb_err) {
+               /* Sometimes after being idle for a while the se401 won't
+                  respond and needs a good kicking  */
+               usb_reset_device(gspca_dev->dev);
+               gspca_dev->usb_err = 0;
+               se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0);
+       }
+
+       /* Some cameras start with their LED on */
+       se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0);
+       if (gspca_dev->usb_err)
+               return gspca_dev->usb_err;
+
+       if (cd[1] != 0x41) {
+               err("Wrong descriptor type");
+               return -ENODEV;
+       }
+
+       if (!(cd[2] & SE401_FORMAT_BAYER)) {
+               err("Bayer format not supported!");
+               return -ENODEV;
+       }
+
+       if (cd[3])
+               info("ExtraFeatures: %d", cd[3]);
+
+       n = cd[4] | (cd[5] << 8);
+       if (n > MAX_MODES) {
+               err("Too many frame sizes");
+               return -ENODEV;
+       }
+
+       for (i = 0; i < n ; i++) {
+               widths[i] = cd[6 + i * 4 + 0] | (cd[6 + i * 4 + 1] << 8);
+               heights[i] = cd[6 + i * 4 + 2] | (cd[6 + i * 4 + 3] << 8);
+       }
+
+       for (i = 0; i < n ; i++) {
+               sd->fmts[i].width = widths[i];
+               sd->fmts[i].height = heights[i];
+               sd->fmts[i].field = V4L2_FIELD_NONE;
+               sd->fmts[i].colorspace = V4L2_COLORSPACE_SRGB;
+               sd->fmts[i].priv = 1;
+
+               /* janggu compression only works for 1/4th or 1/16th res */
+               for (j = 0; j < n; j++) {
+                       if (widths[j] / 2 == widths[i] &&
+                           heights[j] / 2 == heights[i]) {
+                               sd->fmts[i].priv = 2;
+                               break;
+                       }
+               }
+               /* 1/16th if available too is better then 1/4th, because
+                  we then use a larger area of the sensor */
+               for (j = 0; j < n; j++) {
+                       if (widths[j] / 4 == widths[i] &&
+                           heights[j] / 4 == heights[i]) {
+                               sd->fmts[i].priv = 4;
+                               break;
+                       }
+               }
+
+               if (sd->fmts[i].priv == 1) {
+                       /* Not a 1/4th or 1/16th res, use bayer */
+                       sd->fmts[i].pixelformat = V4L2_PIX_FMT_SBGGR8;
+                       sd->fmts[i].bytesperline = widths[i];
+                       sd->fmts[i].sizeimage = widths[i] * heights[i];
+                       info("Frame size: %dx%d bayer", widths[i], heights[i]);
+               } else {
+                       /* Found a match use janggu compression */
+                       sd->fmts[i].pixelformat = V4L2_PIX_FMT_SE401;
+                       sd->fmts[i].bytesperline = 0;
+                       sd->fmts[i].sizeimage = widths[i] * heights[i] * 3;
+                       info("Frame size: %dx%d 1/%dth janggu",
+                            widths[i], heights[i],
+                            sd->fmts[i].priv * sd->fmts[i].priv);
+               }
+       }
+
+       cam->cam_mode = sd->fmts;
+       cam->nmodes = n;
+       cam->bulk = 1;
+       cam->bulk_size = BULK_SIZE;
+       cam->bulk_nurbs = 4;
+       cam->ctrls = sd->ctrls;
+       gspca_dev->nbalt = 1;  /* Ignore the bogus isoc alt settings */
+       sd->resetlevel = 0x2d; /* Set initial resetlevel */
+
+       /* See if the camera supports brightness */
+       se401_read_req(gspca_dev, SE401_REQ_GET_BRT, 1);
+       if (gspca_dev->usb_err) {
+               gspca_dev->ctrl_dis = (1 << BRIGHTNESS);
+               gspca_dev->usb_err = 0;
+       }
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       return 0;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+       int mode = 0;
+
+       se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 1);
+       if (gspca_dev->usb_err) {
+               /* Sometimes after being idle for a while the se401 won't
+                  respond and needs a good kicking  */
+               usb_reset_device(gspca_dev->dev);
+               gspca_dev->usb_err = 0;
+               se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 0);
+       }
+       se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 1, 0);
+
+       se401_set_feature(gspca_dev, HV7131_REG_MODE_B, 0x05);
+
+       /* set size + mode */
+       se401_write_req(gspca_dev, SE401_REQ_SET_WIDTH,
+                       gspca_dev->width * mult, 0);
+       se401_write_req(gspca_dev, SE401_REQ_SET_HEIGHT,
+                       gspca_dev->height * mult, 0);
+       /*
+        * HDG: disabled this as it does not seem to do anything
+        * se401_write_req(gspca_dev, SE401_REQ_SET_OUTPUT_MODE,
+        *                 SE401_FORMAT_BAYER, 0);
+        */
+
+       switch (mult) {
+       case 1: /* Raw bayer */
+               mode = 0x03; break;
+       case 2: /* 1/4th janggu */
+               mode = SE401_QUANT_FACT << 4; break;
+       case 4: /* 1/16th janggu */
+               mode = (SE401_QUANT_FACT << 4) | 0x02; break;
+       }
+       se401_set_feature(gspca_dev, SE401_OPERATINGMODE, mode);
+
+       setbrightness(gspca_dev);
+       setgain(gspca_dev);
+       setexposure(gspca_dev);
+       se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
+
+       sd->packet_read = 0;
+       sd->pixels_read = 0;
+       sd->restart_stream = 0;
+       sd->resetlevel_frame_count = 0;
+       sd->resetlevel_adjust_dir = 0;
+       sd->expo_change_state = EXPO_NO_CHANGE;
+
+       se401_write_req(gspca_dev, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, 0);
+
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       se401_write_req(gspca_dev, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, 0);
+       se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0);
+       se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 0, 0);
+}
+
+static void sd_dq_callback(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       unsigned int ahrc, alrc;
+       int oldreset, adjust_dir;
+
+       /* Restart the stream if requested do so by pkt_scan */
+       if (sd->restart_stream) {
+               sd_stopN(gspca_dev);
+               sd_start(gspca_dev);
+               sd->restart_stream = 0;
+       }
+
+       /* Automatically adjust sensor reset level
+          Hyundai have some really nice docs about this and other sensor
+          related stuff on their homepage: www.hei.co.kr */
+       sd->resetlevel_frame_count++;
+       if (sd->resetlevel_frame_count < 20)
+               return;
+
+       /* For some reason this normally read-only register doesn't get reset
+          to zero after reading them just once... */
+       se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH);
+       se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL);
+       se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH);
+       se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL);
+       ahrc = 256*se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH) +
+           se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL);
+       alrc = 256*se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH) +
+           se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL);
+
+       /* Not an exact science, but it seems to work pretty well... */
+       oldreset = sd->resetlevel;
+       if (alrc > 10) {
+               while (alrc >= 10 && sd->resetlevel < 63) {
+                       sd->resetlevel++;
+                       alrc /= 2;
+               }
+       } else if (ahrc > 20) {
+               while (ahrc >= 20 && sd->resetlevel > 0) {
+                       sd->resetlevel--;
+                       ahrc /= 2;
+               }
+       }
+       /* Detect ping-pong-ing and halve adjustment to avoid overshoot */
+       if (sd->resetlevel > oldreset)
+               adjust_dir = 1;
+       else
+               adjust_dir = -1;
+       if (sd->resetlevel_adjust_dir &&
+           sd->resetlevel_adjust_dir != adjust_dir)
+               sd->resetlevel = oldreset + (sd->resetlevel - oldreset) / 2;
+
+       if (sd->resetlevel != oldreset) {
+               sd->resetlevel_adjust_dir = adjust_dir;
+               se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
+       }
+
+       sd->resetlevel_frame_count = 0;
+}
+
+static void sd_complete_frame(struct gspca_dev *gspca_dev, u8 *data, int len)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+
+       switch (sd->expo_change_state) {
+       case EXPO_CHANGED:
+               /* The exposure was changed while this frame
+                  was being send, so this frame is ok */
+               sd->expo_change_state = EXPO_DROP_FRAME;
+               break;
+       case EXPO_DROP_FRAME:
+               /* The exposure was changed while this frame
+                  was being captured, drop it! */
+               gspca_dev->last_packet_type = DISCARD_PACKET;
+               sd->expo_change_state = EXPO_NO_CHANGE;
+               break;
+       case EXPO_NO_CHANGE:
+               break;
+       }
+       gspca_frame_add(gspca_dev, LAST_PACKET, data, len);
+}
+
+static void sd_pkt_scan_janggu(struct gspca_dev *gspca_dev, u8 *data, int len)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       int imagesize = gspca_dev->width * gspca_dev->height;
+       int i, plen, bits, pixels, info, count;
+
+       if (sd->restart_stream)
+               return;
+
+       /* Sometimes a 1024 bytes garbage bulk packet is send between frames */
+       if (gspca_dev->last_packet_type == LAST_PACKET && len == 1024) {
+               gspca_dev->last_packet_type = DISCARD_PACKET;
+               return;
+       }
+
+       i = 0;
+       while (i < len) {
+               /* Read header if not already be present from prev bulk pkt */
+               if (sd->packet_read < 4) {
+                       count = 4 - sd->packet_read;
+                       if (count > len - i)
+                               count = len - i;
+                       memcpy(&sd->packet[sd->packet_read], &data[i], count);
+                       sd->packet_read += count;
+                       i += count;
+                       if (sd->packet_read < 4)
+                               break;
+               }
+               bits   = sd->packet[3] + (sd->packet[2] << 8);
+               pixels = sd->packet[1] + ((sd->packet[0] & 0x3f) << 8);
+               info   = (sd->packet[0] & 0xc0) >> 6;
+               plen   = ((bits + 47) >> 4) << 1;
+               /* Sanity checks */
+               if (plen > 1024) {
+                       err("invalid packet len %d restarting stream", plen);
+                       goto error;
+               }
+               if (info == 3) {
+                       err("unknown frame info value restarting stream");
+                       goto error;
+               }
+
+               /* Read (remainder of) packet contents */
+               count = plen - sd->packet_read;
+               if (count > len - i)
+                       count = len - i;
+               memcpy(&sd->packet[sd->packet_read], &data[i], count);
+               sd->packet_read += count;
+               i += count;
+               if (sd->packet_read < plen)
+                       break;
+
+               sd->pixels_read += pixels;
+               sd->packet_read = 0;
+
+               switch (info) {
+               case 0: /* Frame data */
+                       gspca_frame_add(gspca_dev, INTER_PACKET, sd->packet,
+                                       plen);
+                       break;
+               case 1: /* EOF */
+                       if (sd->pixels_read != imagesize) {
+                               err("frame size %d expected %d",
+                                   sd->pixels_read, imagesize);
+                               goto error;
+                       }
+                       sd_complete_frame(gspca_dev, sd->packet, plen);
+                       return; /* Discard the rest of the bulk packet !! */
+               case 2: /* SOF */
+                       gspca_frame_add(gspca_dev, FIRST_PACKET, sd->packet,
+                                       plen);
+                       sd->pixels_read = pixels;
+                       break;
+               }
+       }
+       return;
+
+error:
+       sd->restart_stream = 1;
+       /* Give userspace a 0 bytes frame, so our dq callback gets
+          called and it can restart the stream */
+       gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
+       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+}
+
+static void sd_pkt_scan_bayer(struct gspca_dev *gspca_dev, u8 *data, int len)
+{
+       struct cam *cam = &gspca_dev->cam;
+       int imagesize = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
+
+       if (gspca_dev->image_len == 0) {
+               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+               return;
+       }
+
+       if (gspca_dev->image_len + len >= imagesize) {
+               sd_complete_frame(gspca_dev, data, len);
+               return;
+       }
+
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
+{
+       int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+
+       if (len == 0)
+               return;
+
+       if (mult == 1) /* mult == 1 means raw bayer */
+               sd_pkt_scan_bayer(gspca_dev, data, len);
+       else
+               sd_pkt_scan_janggu(gspca_dev, data, len);
+}
+
+static int sd_querymenu(struct gspca_dev *gspca_dev,
+                       struct v4l2_querymenu *menu)
+{
+       switch (menu->id) {
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               switch (menu->index) {
+               case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED:
+                       strcpy((char *) menu->name, "NoFliker");
+                       return 0;
+               case V4L2_CID_POWER_LINE_FREQUENCY_50HZ:
+                       strcpy((char *) menu->name, "50 Hz");
+                       return 0;
+               case V4L2_CID_POWER_LINE_FREQUENCY_60HZ:
+                       strcpy((char *) menu->name, "60 Hz");
+                       return 0;
+               }
+               break;
+       }
+       return -EINVAL;
+}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       u8 state;
+
+       if (len != 2)
+               return -EINVAL;
+
+       switch (data[0]) {
+       case 0:
+       case 1:
+               state = data[0];
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (sd->button_state != state) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
+               input_sync(gspca_dev->input_dev);
+               sd->button_state = state;
+       }
+
+       return 0;
+}
+#endif
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name = MODULE_NAME,
+       .ctrls = sd_ctrls,
+       .nctrls = ARRAY_SIZE(sd_ctrls),
+       .config = sd_config,
+       .init = sd_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .dq_callback = sd_dq_callback,
+       .pkt_scan = sd_pkt_scan,
+       .querymenu = sd_querymenu,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .int_pkt_scan = sd_int_pkt_scan,
+#endif
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x03e8, 0x0004)}, /* Endpoints/Aox SE401 */
+       {USB_DEVICE(0x0471, 0x030b)}, /* Philips PCVC665K */
+       {USB_DEVICE(0x047d, 0x5001)}, /* Kensington 67014 */
+       {USB_DEVICE(0x047d, 0x5002)}, /* Kensington 6701(5/7) */
+       {USB_DEVICE(0x047d, 0x5003)}, /* Kensington 67016 */
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+                       const struct usb_device_id *id)
+{
+       return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+                               THIS_MODULE);
+}
+
+static int sd_pre_reset(struct usb_interface *intf)
+{
+       return 0;
+}
+
+static int sd_post_reset(struct usb_interface *intf)
+{
+       return 0;
+}
+
+static struct usb_driver sd_driver = {
+       .name = MODULE_NAME,
+       .id_table = device_table,
+       .probe = sd_probe,
+       .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
+       .pre_reset = sd_pre_reset,
+       .post_reset = sd_post_reset,
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+       return usb_register(&sd_driver);
+}
+static void __exit sd_mod_exit(void)
+{
+       usb_deregister(&sd_driver);
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/se401.h b/drivers/media/video/gspca/se401.h
new file mode 100644 (file)
index 0000000..96d8ebf
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * GSPCA Endpoints (formerly known as AOX) se401 USB Camera sub Driver
+ *
+ * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on the v4l1 se401 driver which is:
+ *
+ * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define SE401_REQ_GET_CAMERA_DESCRIPTOR                0x06
+#define SE401_REQ_START_CONTINUOUS_CAPTURE     0x41
+#define SE401_REQ_STOP_CONTINUOUS_CAPTURE      0x42
+#define SE401_REQ_CAPTURE_FRAME                        0x43
+#define SE401_REQ_GET_BRT                      0x44
+#define SE401_REQ_SET_BRT                      0x45
+#define SE401_REQ_GET_WIDTH                    0x4c
+#define SE401_REQ_SET_WIDTH                    0x4d
+#define SE401_REQ_GET_HEIGHT                   0x4e
+#define SE401_REQ_SET_HEIGHT                   0x4f
+#define SE401_REQ_GET_OUTPUT_MODE              0x50
+#define SE401_REQ_SET_OUTPUT_MODE              0x51
+#define SE401_REQ_GET_EXT_FEATURE              0x52
+#define SE401_REQ_SET_EXT_FEATURE              0x53
+#define SE401_REQ_CAMERA_POWER                 0x56
+#define SE401_REQ_LED_CONTROL                  0x57
+#define SE401_REQ_BIOS                         0xff
+
+#define SE401_BIOS_READ                                0x07
+
+#define SE401_FORMAT_BAYER     0x40
+
+/* Hyundai hv7131b registers
+   7121 and 7141 should be the same (haven't really checked...) */
+/* Mode registers: */
+#define HV7131_REG_MODE_A              0x00
+#define HV7131_REG_MODE_B              0x01
+#define HV7131_REG_MODE_C              0x02
+/* Frame registers: */
+#define HV7131_REG_FRSU                0x10
+#define HV7131_REG_FRSL                0x11
+#define HV7131_REG_FCSU                0x12
+#define HV7131_REG_FCSL                0x13
+#define HV7131_REG_FWHU                0x14
+#define HV7131_REG_FWHL                0x15
+#define HV7131_REG_FWWU                0x16
+#define HV7131_REG_FWWL                0x17
+/* Timing registers: */
+#define HV7131_REG_THBU                0x20
+#define HV7131_REG_THBL                0x21
+#define HV7131_REG_TVBU                0x22
+#define HV7131_REG_TVBL                0x23
+#define HV7131_REG_TITU                0x25
+#define HV7131_REG_TITM                0x26
+#define HV7131_REG_TITL                0x27
+#define HV7131_REG_TMCD                0x28
+/* Adjust Registers: */
+#define HV7131_REG_ARLV                0x30
+#define HV7131_REG_ARCG                0x31
+#define HV7131_REG_AGCG                0x32
+#define HV7131_REG_ABCG                0x33
+#define HV7131_REG_APBV                0x34
+#define HV7131_REG_ASLP                0x54
+/* Offset Registers: */
+#define HV7131_REG_OFSR                0x50
+#define HV7131_REG_OFSG                0x51
+#define HV7131_REG_OFSB                0x52
+/* REset level statistics registers: */
+#define HV7131_REG_LOREFNOH    0x57
+#define HV7131_REG_LOREFNOL    0x58
+#define HV7131_REG_HIREFNOH    0x59
+#define HV7131_REG_HIREFNOL    0x5a
+
+/* se401 registers */
+#define SE401_OPERATINGMODE    0x2000
index b089c0d..6ec2329 100644 (file)
@@ -247,7 +247,6 @@ static const struct cmd spca504A_clicksmart420_init_data[] = {
        {0x30, 0x0004, 0x000a},
        {0xb0, 0x0001, 0x0000},
 
-
        {0xa1, 0x0080, 0x0001},
        {0x30, 0x0049, 0x0000},
        {0x30, 0x0060, 0x0005},
@@ -256,8 +255,6 @@ static const struct cmd spca504A_clicksmart420_init_data[] = {
        {0x00, 0x0000, 0x2000},
        {0x00, 0x0013, 0x2301},
        {0x00, 0x0003, 0x2000},
-       {0x00, 0x0000, 0x2000},
-
 };
 
 /* clicksmart 420 open data ? */
index 7e762d5..d1d733b 100644 (file)
@@ -1387,7 +1387,7 @@ static int sd_querymenu(struct gspca_dev *gspca_dev,
                return 0;
        case V4L2_CID_EFFECTS:
                if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
-                       strncpy((char *) menu->name,
+                       strlcpy((char *) menu->name,
                                effects_control[menu->index],
                                sizeof menu->name);
                        return 0;
index 5f1db46..441dacf 100644 (file)
@@ -474,5 +474,6 @@ module_init(hdpvr_init);
 module_exit(hdpvr_exit);
 
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.2.1");
 MODULE_AUTHOR("Janne Grunau");
 MODULE_DESCRIPTION("Hauppauge HD PVR driver");
index 514aea7..087f7c0 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
-#include <linux/version.h>
 #include <linux/workqueue.h>
 
 #include <linux/videodev2.h>
@@ -574,7 +573,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strcpy(cap->driver, "hdpvr");
        strcpy(cap->card, "Hauppauge HD PVR");
        usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-       cap->version = HDPVR_VERSION;
        cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
                                V4L2_CAP_AUDIO         |
                                V4L2_CAP_READWRITE;
index 072f23c..d6439db 100644 (file)
 #include <media/v4l2-device.h>
 #include <media/ir-kbd-i2c.h>
 
-#define HDPVR_MAJOR_VERSION 0
-#define HDPVR_MINOR_VERSION 2
-#define HDPVR_RELEASE 0
-#define HDPVR_VERSION \
-       KERNEL_VERSION(HDPVR_MAJOR_VERSION, HDPVR_MINOR_VERSION, HDPVR_RELEASE)
-
 #define HDPVR_MAX 8
 #define HDPVR_I2C_MAX_SIZE 128
 
index 84bdf0f..8f9cc17 100644 (file)
@@ -36,7 +36,6 @@
  *                using information provided by Jiun-Kuei Jung @ AVerMedia.
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
index a7f54b0..38f0522 100644 (file)
@@ -722,8 +722,8 @@ unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait)
 
        /* If there are subscribed events, then only use the new event
           API instead of the old video.h based API. */
-       if (!list_empty(&id->fh.events->subscribed)) {
-               poll_wait(filp, &id->fh.events->wait, wait);
+       if (!list_empty(&id->fh.subscribed)) {
+               poll_wait(filp, &id->fh.wait, wait);
                /* Turn off the old-style vsync events */
                clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
                if (v4l2_event_pending(&id->fh))
@@ -750,6 +750,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
        struct ivtv *itv = id->itv;
        struct ivtv_stream *s = &itv->streams[id->type];
        int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+       unsigned res = 0;
 
        /* Start a capture if there is none */
        if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
@@ -769,12 +770,16 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
        /* add stream's waitq to the poll list */
        IVTV_DEBUG_HI_FILE("Encoder poll\n");
        poll_wait(filp, &s->waitq, wait);
+       if (v4l2_event_pending(&id->fh))
+               res |= POLLPRI;
+       else
+               poll_wait(filp, &id->fh.wait, wait);
 
        if (s->q_full.length || s->q_io.length)
-               return POLLIN | POLLRDNORM;
+               return res | POLLIN | POLLRDNORM;
        if (eof)
-               return POLLHUP;
-       return 0;
+               return res | POLLHUP;
+       return res;
 }
 
 void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end)
@@ -961,10 +966,6 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
                return -ENOMEM;
        }
        v4l2_fh_init(&item->fh, s->vdev);
-       if (s->type == IVTV_DEC_STREAM_TYPE_YUV ||
-           s->type == IVTV_DEC_STREAM_TYPE_MPG) {
-               res = v4l2_event_alloc(&item->fh, 60);
-       }
        if (res < 0) {
                v4l2_fh_exit(&item->fh);
                kfree(item);
index 120c7d8..3e5c090 100644 (file)
@@ -757,7 +757,6 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc
        strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
        strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
        snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));
-       vcap->version = IVTV_DRIVER_VERSION;        /* version */
        vcap->capabilities = itv->v4l2_cap;         /* capabilities */
        return 0;
 }
@@ -1451,11 +1450,11 @@ static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscripti
        switch (sub->type) {
        case V4L2_EVENT_VSYNC:
        case V4L2_EVENT_EOS:
-               break;
+       case V4L2_EVENT_CTRL:
+               return v4l2_event_subscribe(fh, sub, 0);
        default:
                return -EINVAL;
        }
-       return v4l2_event_subscribe(fh, sub);
 }
 
 static int ivtv_log_status(struct file *file, void *fh)
index b67a404..a20f346 100644 (file)
 #define IVTV_VERSION_H
 
 #define IVTV_DRIVER_NAME "ivtv"
-#define IVTV_DRIVER_VERSION_MAJOR 1
-#define IVTV_DRIVER_VERSION_MINOR 4
-#define IVTV_DRIVER_VERSION_PATCHLEVEL 2
-
-#define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL)
-#define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL)
+#define IVTV_VERSION "1.4.3"
 
 #endif
index a45d8f0..3248ac8 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/version.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/videodev2.h>
index 43c68f5..fb8e4a7 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/version.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/videodev2.h>
diff --git a/drivers/media/video/marvell-ccic/Kconfig b/drivers/media/video/marvell-ccic/Kconfig
new file mode 100644 (file)
index 0000000..bf739e3
--- /dev/null
@@ -0,0 +1,23 @@
+config VIDEO_CAFE_CCIC
+       tristate "Marvell 88ALP01 (Cafe) CMOS Camera Controller support"
+       depends on PCI && I2C && VIDEO_V4L2
+       select VIDEO_OV7670
+       select VIDEOBUF2_VMALLOC
+       select VIDEOBUF2_DMA_CONTIG
+       ---help---
+         This is a video4linux2 driver for the Marvell 88ALP01 integrated
+         CMOS camera controller.  This is the controller found on first-
+         generation OLPC systems.
+
+config VIDEO_MMP_CAMERA
+       tristate "Marvell Armada 610 integrated camera controller support"
+       depends on ARCH_MMP && I2C && VIDEO_V4L2
+       select VIDEO_OV7670
+       select I2C_GPIO
+       select VIDEOBUF2_DMA_SG
+       ---help---
+         This is a Video4Linux2 driver for the integrated camera
+         controller found on Marvell Armada 610 application
+         processors (and likely beyond).  This is the controller found
+         in OLPC XO 1.75 systems.
+
diff --git a/drivers/media/video/marvell-ccic/Makefile b/drivers/media/video/marvell-ccic/Makefile
new file mode 100644 (file)
index 0000000..05a792c
--- /dev/null
@@ -0,0 +1,6 @@
+obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
+cafe_ccic-y := cafe-driver.o mcam-core.o
+
+obj-$(CONFIG_VIDEO_MMP_CAMERA) += mmp_camera.o
+mmp_camera-y := mmp-driver.o mcam-core.o
+
diff --git a/drivers/media/video/marvell-ccic/cafe-driver.c b/drivers/media/video/marvell-ccic/cafe-driver.c
new file mode 100644 (file)
index 0000000..d030f9b
--- /dev/null
@@ -0,0 +1,654 @@
+/*
+ * A driver for the CMOS camera controller in the Marvell 88ALP01 "cafe"
+ * multifunction chip.  Currently works with the Omnivision OV7670
+ * sensor.
+ *
+ * The data sheet for this device can be found at:
+ *    http://www.marvell.com/products/pc_connectivity/88alp01/
+ *
+ * Copyright 2006-11 One Laptop Per Child Association, Inc.
+ * Copyright 2006-11 Jonathan Corbet <corbet@lwn.net>
+ *
+ * Written by Jonathan Corbet, corbet@lwn.net.
+ *
+ * v4l2_device/v4l2_subdev conversion by:
+ * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This file may be distributed under the terms of the GNU General
+ * Public License, version 2.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "mcam-core.h"
+
+#define CAFE_VERSION 0x000002
+
+
+/*
+ * Parameters.
+ */
+MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
+MODULE_DESCRIPTION("Marvell 88ALP01 CMOS Camera Controller driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("Video");
+
+
+
+
+struct cafe_camera {
+       int registered;                 /* Fully initialized? */
+       struct mcam_camera mcam;
+       struct pci_dev *pdev;
+       wait_queue_head_t smbus_wait;   /* Waiting on i2c events */
+};
+
+/*
+ * Most of the camera controller registers are defined in mcam-core.h,
+ * but the Cafe platform has some additional registers of its own;
+ * they are described here.
+ */
+
+/*
+ * "General purpose register" has a couple of GPIOs used for sensor
+ * power and reset on OLPC XO 1.0 systems.
+ */
+#define REG_GPR                0xb4
+#define          GPR_C1EN        0x00000020    /* Pad 1 (power down) enable */
+#define          GPR_C0EN        0x00000010    /* Pad 0 (reset) enable */
+#define          GPR_C1          0x00000002    /* Control 1 value */
+/*
+ * Control 0 is wired to reset on OLPC machines.  For ov7x sensors,
+ * it is active low.
+ */
+#define          GPR_C0          0x00000001    /* Control 0 value */
+
+/*
+ * These registers control the SMBUS module for communicating
+ * with the sensor.
+ */
+#define REG_TWSIC0     0xb8    /* TWSI (smbus) control 0 */
+#define          TWSIC0_EN       0x00000001    /* TWSI enable */
+#define          TWSIC0_MODE     0x00000002    /* 1 = 16-bit, 0 = 8-bit */
+#define          TWSIC0_SID      0x000003fc    /* Slave ID */
+/*
+ * Subtle trickery: the slave ID field starts with bit 2.  But the
+ * Linux i2c stack wants to treat the bottommost bit as a separate
+ * read/write bit, which is why slave ID's are usually presented
+ * >>1.  For consistency with that behavior, we shift over three
+ * bits instead of two.
+ */
+#define          TWSIC0_SID_SHIFT 3
+#define          TWSIC0_CLKDIV   0x0007fc00    /* Clock divider */
+#define          TWSIC0_MASKACK  0x00400000    /* Mask ack from sensor */
+#define          TWSIC0_OVMAGIC  0x00800000    /* Make it work on OV sensors */
+
+#define REG_TWSIC1     0xbc    /* TWSI control 1 */
+#define          TWSIC1_DATA     0x0000ffff    /* Data to/from camchip */
+#define          TWSIC1_ADDR     0x00ff0000    /* Address (register) */
+#define          TWSIC1_ADDR_SHIFT 16
+#define          TWSIC1_READ     0x01000000    /* Set for read op */
+#define          TWSIC1_WSTAT    0x02000000    /* Write status */
+#define          TWSIC1_RVALID   0x04000000    /* Read data valid */
+#define          TWSIC1_ERROR    0x08000000    /* Something screwed up */
+
+/*
+ * Here's the weird global control registers
+ */
+#define REG_GL_CSR     0x3004  /* Control/status register */
+#define          GCSR_SRS       0x00000001     /* SW Reset set */
+#define          GCSR_SRC       0x00000002     /* SW Reset clear */
+#define          GCSR_MRS       0x00000004     /* Master reset set */
+#define          GCSR_MRC       0x00000008     /* HW Reset clear */
+#define          GCSR_CCIC_EN   0x00004000    /* CCIC Clock enable */
+#define REG_GL_IMASK   0x300c  /* Interrupt mask register */
+#define          GIMSK_CCIC_EN          0x00000004    /* CCIC Interrupt enable */
+
+#define REG_GL_FCR     0x3038  /* GPIO functional control register */
+#define          GFCR_GPIO_ON    0x08          /* Camera GPIO enabled */
+#define REG_GL_GPIOR   0x315c  /* GPIO register */
+#define          GGPIO_OUT             0x80000 /* GPIO output */
+#define          GGPIO_VAL             0x00008 /* Output pin value */
+
+#define REG_LEN                       (REG_GL_IMASK + 4)
+
+
+/*
+ * Debugging and related.
+ */
+#define cam_err(cam, fmt, arg...) \
+       dev_err(&(cam)->pdev->dev, fmt, ##arg);
+#define cam_warn(cam, fmt, arg...) \
+       dev_warn(&(cam)->pdev->dev, fmt, ##arg);
+
+/* -------------------------------------------------------------------- */
+/*
+ * The I2C/SMBUS interface to the camera itself starts here.  The
+ * controller handles SMBUS itself, presenting a relatively simple register
+ * interface; all we have to do is to tell it where to route the data.
+ */
+#define CAFE_SMBUS_TIMEOUT (HZ)  /* generous */
+
+static inline struct cafe_camera *to_cam(struct v4l2_device *dev)
+{
+       struct mcam_camera *m = container_of(dev, struct mcam_camera, v4l2_dev);
+       return container_of(m, struct cafe_camera, mcam);
+}
+
+
+static int cafe_smbus_write_done(struct mcam_camera *mcam)
+{
+       unsigned long flags;
+       int c1;
+
+       /*
+        * We must delay after the interrupt, or the controller gets confused
+        * and never does give us good status.  Fortunately, we don't do this
+        * often.
+        */
+       udelay(20);
+       spin_lock_irqsave(&mcam->dev_lock, flags);
+       c1 = mcam_reg_read(mcam, REG_TWSIC1);
+       spin_unlock_irqrestore(&mcam->dev_lock, flags);
+       return (c1 & (TWSIC1_WSTAT|TWSIC1_ERROR)) != TWSIC1_WSTAT;
+}
+
+static int cafe_smbus_write_data(struct cafe_camera *cam,
+               u16 addr, u8 command, u8 value)
+{
+       unsigned int rval;
+       unsigned long flags;
+       struct mcam_camera *mcam = &cam->mcam;
+
+       spin_lock_irqsave(&mcam->dev_lock, flags);
+       rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID);
+       rval |= TWSIC0_OVMAGIC;  /* Make OV sensors work */
+       /*
+        * Marvell sez set clkdiv to all 1's for now.
+        */
+       rval |= TWSIC0_CLKDIV;
+       mcam_reg_write(mcam, REG_TWSIC0, rval);
+       (void) mcam_reg_read(mcam, REG_TWSIC1); /* force write */
+       rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR);
+       mcam_reg_write(mcam, REG_TWSIC1, rval);
+       spin_unlock_irqrestore(&mcam->dev_lock, flags);
+
+       /* Unfortunately, reading TWSIC1 too soon after sending a command
+        * causes the device to die.
+        * Use a busy-wait because we often send a large quantity of small
+        * commands at-once; using msleep() would cause a lot of context
+        * switches which take longer than 2ms, resulting in a noticeable
+        * boot-time and capture-start delays.
+        */
+       mdelay(2);
+
+       /*
+        * Another sad fact is that sometimes, commands silently complete but
+        * cafe_smbus_write_done() never becomes aware of this.
+        * This happens at random and appears to possible occur with any
+        * command.
+        * We don't understand why this is. We work around this issue
+        * with the timeout in the wait below, assuming that all commands
+        * complete within the timeout.
+        */
+       wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(mcam),
+                       CAFE_SMBUS_TIMEOUT);
+
+       spin_lock_irqsave(&mcam->dev_lock, flags);
+       rval = mcam_reg_read(mcam, REG_TWSIC1);
+       spin_unlock_irqrestore(&mcam->dev_lock, flags);
+
+       if (rval & TWSIC1_WSTAT) {
+               cam_err(cam, "SMBUS write (%02x/%02x/%02x) timed out\n", addr,
+                               command, value);
+               return -EIO;
+       }
+       if (rval & TWSIC1_ERROR) {
+               cam_err(cam, "SMBUS write (%02x/%02x/%02x) error\n", addr,
+                               command, value);
+               return -EIO;
+       }
+       return 0;
+}
+
+
+
+static int cafe_smbus_read_done(struct mcam_camera *mcam)
+{
+       unsigned long flags;
+       int c1;
+
+       /*
+        * We must delay after the interrupt, or the controller gets confused
+        * and never does give us good status.  Fortunately, we don't do this
+        * often.
+        */
+       udelay(20);
+       spin_lock_irqsave(&mcam->dev_lock, flags);
+       c1 = mcam_reg_read(mcam, REG_TWSIC1);
+       spin_unlock_irqrestore(&mcam->dev_lock, flags);
+       return c1 & (TWSIC1_RVALID|TWSIC1_ERROR);
+}
+
+
+
+static int cafe_smbus_read_data(struct cafe_camera *cam,
+               u16 addr, u8 command, u8 *value)
+{
+       unsigned int rval;
+       unsigned long flags;
+       struct mcam_camera *mcam = &cam->mcam;
+
+       spin_lock_irqsave(&mcam->dev_lock, flags);
+       rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID);
+       rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */
+       /*
+        * Marvel sez set clkdiv to all 1's for now.
+        */
+       rval |= TWSIC0_CLKDIV;
+       mcam_reg_write(mcam, REG_TWSIC0, rval);
+       (void) mcam_reg_read(mcam, REG_TWSIC1); /* force write */
+       rval = TWSIC1_READ | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR);
+       mcam_reg_write(mcam, REG_TWSIC1, rval);
+       spin_unlock_irqrestore(&mcam->dev_lock, flags);
+
+       wait_event_timeout(cam->smbus_wait,
+                       cafe_smbus_read_done(mcam), CAFE_SMBUS_TIMEOUT);
+       spin_lock_irqsave(&mcam->dev_lock, flags);
+       rval = mcam_reg_read(mcam, REG_TWSIC1);
+       spin_unlock_irqrestore(&mcam->dev_lock, flags);
+
+       if (rval & TWSIC1_ERROR) {
+               cam_err(cam, "SMBUS read (%02x/%02x) error\n", addr, command);
+               return -EIO;
+       }
+       if (!(rval & TWSIC1_RVALID)) {
+               cam_err(cam, "SMBUS read (%02x/%02x) timed out\n", addr,
+                               command);
+               return -EIO;
+       }
+       *value = rval & 0xff;
+       return 0;
+}
+
+/*
+ * Perform a transfer over SMBUS.  This thing is called under
+ * the i2c bus lock, so we shouldn't race with ourselves...
+ */
+static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+               unsigned short flags, char rw, u8 command,
+               int size, union i2c_smbus_data *data)
+{
+       struct cafe_camera *cam = i2c_get_adapdata(adapter);
+       int ret = -EINVAL;
+
+       /*
+        * This interface would appear to only do byte data ops.  OK
+        * it can do word too, but the cam chip has no use for that.
+        */
+       if (size != I2C_SMBUS_BYTE_DATA) {
+               cam_err(cam, "funky xfer size %d\n", size);
+               return -EINVAL;
+       }
+
+       if (rw == I2C_SMBUS_WRITE)
+               ret = cafe_smbus_write_data(cam, addr, command, data->byte);
+       else if (rw == I2C_SMBUS_READ)
+               ret = cafe_smbus_read_data(cam, addr, command, &data->byte);
+       return ret;
+}
+
+
+static void cafe_smbus_enable_irq(struct cafe_camera *cam)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->mcam.dev_lock, flags);
+       mcam_reg_set_bit(&cam->mcam, REG_IRQMASK, TWSIIRQS);
+       spin_unlock_irqrestore(&cam->mcam.dev_lock, flags);
+}
+
+static u32 cafe_smbus_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_SMBUS_READ_BYTE_DATA  |
+              I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
+}
+
+static struct i2c_algorithm cafe_smbus_algo = {
+       .smbus_xfer = cafe_smbus_xfer,
+       .functionality = cafe_smbus_func
+};
+
+static int cafe_smbus_setup(struct cafe_camera *cam)
+{
+       struct i2c_adapter *adap;
+       int ret;
+
+       adap = kzalloc(sizeof(*adap), GFP_KERNEL);
+       if (adap == NULL)
+               return -ENOMEM;
+       cam->mcam.i2c_adapter = adap;
+       cafe_smbus_enable_irq(cam);
+       adap->owner = THIS_MODULE;
+       adap->algo = &cafe_smbus_algo;
+       strcpy(adap->name, "cafe_ccic");
+       adap->dev.parent = &cam->pdev->dev;
+       i2c_set_adapdata(adap, cam);
+       ret = i2c_add_adapter(adap);
+       if (ret)
+               printk(KERN_ERR "Unable to register cafe i2c adapter\n");
+       return ret;
+}
+
+static void cafe_smbus_shutdown(struct cafe_camera *cam)
+{
+       i2c_del_adapter(cam->mcam.i2c_adapter);
+       kfree(cam->mcam.i2c_adapter);
+}
+
+
+/*
+ * Controller-level stuff
+ */
+
+static void cafe_ctlr_init(struct mcam_camera *mcam)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&mcam->dev_lock, flags);
+       /*
+        * Added magic to bring up the hardware on the B-Test board
+        */
+       mcam_reg_write(mcam, 0x3038, 0x8);
+       mcam_reg_write(mcam, 0x315c, 0x80008);
+       /*
+        * Go through the dance needed to wake the device up.
+        * Note that these registers are global and shared
+        * with the NAND and SD devices.  Interaction between the
+        * three still needs to be examined.
+        */
+       mcam_reg_write(mcam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */
+       mcam_reg_write(mcam, REG_GL_CSR, GCSR_SRC|GCSR_MRC);
+       mcam_reg_write(mcam, REG_GL_CSR, GCSR_SRC|GCSR_MRS);
+       /*
+        * Here we must wait a bit for the controller to come around.
+        */
+       spin_unlock_irqrestore(&mcam->dev_lock, flags);
+       msleep(5);
+       spin_lock_irqsave(&mcam->dev_lock, flags);
+
+       mcam_reg_write(mcam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC);
+       mcam_reg_set_bit(mcam, REG_GL_IMASK, GIMSK_CCIC_EN);
+       /*
+        * Mask all interrupts.
+        */
+       mcam_reg_write(mcam, REG_IRQMASK, 0);
+       spin_unlock_irqrestore(&mcam->dev_lock, flags);
+}
+
+
+static void cafe_ctlr_power_up(struct mcam_camera *mcam)
+{
+       /*
+        * Part one of the sensor dance: turn the global
+        * GPIO signal on.
+        */
+       mcam_reg_write(mcam, REG_GL_FCR, GFCR_GPIO_ON);
+       mcam_reg_write(mcam, REG_GL_GPIOR, GGPIO_OUT|GGPIO_VAL);
+       /*
+        * Put the sensor into operational mode (assumes OLPC-style
+        * wiring).  Control 0 is reset - set to 1 to operate.
+        * Control 1 is power down, set to 0 to operate.
+        */
+       mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */
+       mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0);
+}
+
+static void cafe_ctlr_power_down(struct mcam_camera *mcam)
+{
+       mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1);
+       mcam_reg_write(mcam, REG_GL_FCR, GFCR_GPIO_ON);
+       mcam_reg_write(mcam, REG_GL_GPIOR, GGPIO_OUT);
+}
+
+
+
+/*
+ * The platform interrupt handler.
+ */
+static irqreturn_t cafe_irq(int irq, void *data)
+{
+       struct cafe_camera *cam = data;
+       struct mcam_camera *mcam = &cam->mcam;
+       unsigned int irqs, handled;
+
+       spin_lock(&mcam->dev_lock);
+       irqs = mcam_reg_read(mcam, REG_IRQSTAT);
+       handled = cam->registered && mccic_irq(mcam, irqs);
+       if (irqs & TWSIIRQS) {
+               mcam_reg_write(mcam, REG_IRQSTAT, TWSIIRQS);
+               wake_up(&cam->smbus_wait);
+               handled = 1;
+       }
+       spin_unlock(&mcam->dev_lock);
+       return IRQ_RETVAL(handled);
+}
+
+
+/* -------------------------------------------------------------------------- */
+/*
+ * PCI interface stuff.
+ */
+
+static int cafe_pci_probe(struct pci_dev *pdev,
+               const struct pci_device_id *id)
+{
+       int ret;
+       struct cafe_camera *cam;
+       struct mcam_camera *mcam;
+
+       /*
+        * Start putting together one of our big camera structures.
+        */
+       ret = -ENOMEM;
+       cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL);
+       if (cam == NULL)
+               goto out;
+       cam->pdev = pdev;
+       mcam = &cam->mcam;
+       mcam->chip_id = V4L2_IDENT_CAFE;
+       spin_lock_init(&mcam->dev_lock);
+       init_waitqueue_head(&cam->smbus_wait);
+       mcam->plat_power_up = cafe_ctlr_power_up;
+       mcam->plat_power_down = cafe_ctlr_power_down;
+       mcam->dev = &pdev->dev;
+       /*
+        * Set the clock speed for the XO 1; I don't believe this
+        * driver has ever run anywhere else.
+        */
+       mcam->clock_speed = 45;
+       mcam->use_smbus = 1;
+       /*
+        * Vmalloc mode for buffers is traditional with this driver.
+        * We *might* be able to run DMA_contig, especially on a system
+        * with CMA in it.
+        */
+       mcam->buffer_mode = B_vmalloc;
+       /*
+        * Get set up on the PCI bus.
+        */
+       ret = pci_enable_device(pdev);
+       if (ret)
+               goto out_free;
+       pci_set_master(pdev);
+
+       ret = -EIO;
+       mcam->regs = pci_iomap(pdev, 0, 0);
+       if (!mcam->regs) {
+               printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n");
+               goto out_disable;
+       }
+       ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam);
+       if (ret)
+               goto out_iounmap;
+
+       /*
+        * Initialize the controller and leave it powered up.  It will
+        * stay that way until the sensor driver shows up.
+        */
+       cafe_ctlr_init(mcam);
+       cafe_ctlr_power_up(mcam);
+       /*
+        * Set up I2C/SMBUS communications.  We have to drop the mutex here
+        * because the sensor could attach in this call chain, leading to
+        * unsightly deadlocks.
+        */
+       ret = cafe_smbus_setup(cam);
+       if (ret)
+               goto out_pdown;
+
+       ret = mccic_register(mcam);
+       if (ret == 0) {
+               cam->registered = 1;
+               return 0;
+       }
+
+       cafe_smbus_shutdown(cam);
+out_pdown:
+       cafe_ctlr_power_down(mcam);
+       free_irq(pdev->irq, cam);
+out_iounmap:
+       pci_iounmap(pdev, mcam->regs);
+out_disable:
+       pci_disable_device(pdev);
+out_free:
+       kfree(cam);
+out:
+       return ret;
+}
+
+
+/*
+ * Shut down an initialized device
+ */
+static void cafe_shutdown(struct cafe_camera *cam)
+{
+       mccic_shutdown(&cam->mcam);
+       cafe_smbus_shutdown(cam);
+       free_irq(cam->pdev->irq, cam);
+       pci_iounmap(cam->pdev, cam->mcam.regs);
+}
+
+
+static void cafe_pci_remove(struct pci_dev *pdev)
+{
+       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+       struct cafe_camera *cam = to_cam(v4l2_dev);
+
+       if (cam == NULL) {
+               printk(KERN_WARNING "pci_remove on unknown pdev %p\n", pdev);
+               return;
+       }
+       cafe_shutdown(cam);
+       kfree(cam);
+}
+
+
+#ifdef CONFIG_PM
+/*
+ * Basic power management.
+ */
+static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+       struct cafe_camera *cam = to_cam(v4l2_dev);
+       int ret;
+
+       ret = pci_save_state(pdev);
+       if (ret)
+               return ret;
+       mccic_suspend(&cam->mcam);
+       pci_disable_device(pdev);
+       return 0;
+}
+
+
+static int cafe_pci_resume(struct pci_dev *pdev)
+{
+       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+       struct cafe_camera *cam = to_cam(v4l2_dev);
+       int ret = 0;
+
+       pci_restore_state(pdev);
+       ret = pci_enable_device(pdev);
+
+       if (ret) {
+               cam_warn(cam, "Unable to re-enable device on resume!\n");
+               return ret;
+       }
+       cafe_ctlr_init(&cam->mcam);
+       return mccic_resume(&cam->mcam);
+}
+
+#endif  /* CONFIG_PM */
+
+static struct pci_device_id cafe_ids[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL,
+                    PCI_DEVICE_ID_MARVELL_88ALP01_CCIC) },
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, cafe_ids);
+
+static struct pci_driver cafe_pci_driver = {
+       .name = "cafe1000-ccic",
+       .id_table = cafe_ids,
+       .probe = cafe_pci_probe,
+       .remove = cafe_pci_remove,
+#ifdef CONFIG_PM
+       .suspend = cafe_pci_suspend,
+       .resume = cafe_pci_resume,
+#endif
+};
+
+
+
+
+static int __init cafe_init(void)
+{
+       int ret;
+
+       printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n",
+                       CAFE_VERSION);
+       ret = pci_register_driver(&cafe_pci_driver);
+       if (ret) {
+               printk(KERN_ERR "Unable to register cafe_ccic driver\n");
+               goto out;
+       }
+       ret = 0;
+
+out:
+       return ret;
+}
+
+
+static void __exit cafe_exit(void)
+{
+       pci_unregister_driver(&cafe_pci_driver);
+}
+
+module_init(cafe_init);
+module_exit(cafe_exit);
diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/video/marvell-ccic/mcam-core.c
new file mode 100644 (file)
index 0000000..83c1451
--- /dev/null
@@ -0,0 +1,1843 @@
+/*
+ * The Marvell camera core.  This device appears in a number of settings,
+ * so it needs platform-specific support outside of the core.
+ *
+ * Copyright 2011 Jonathan Corbet corbet@lwn.net
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/ov7670.h>
+#include <media/videobuf2-vmalloc.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-dma-sg.h>
+
+#include "mcam-core.h"
+
+/*
+ * Basic frame stats - to be deleted shortly
+ */
+static int frames;
+static int singles;
+static int delivered;
+
+#ifdef MCAM_MODE_VMALLOC
+/*
+ * Internal DMA buffer management.  Since the controller cannot do S/G I/O,
+ * we must have physically contiguous buffers to bring frames into.
+ * These parameters control how many buffers we use, whether we
+ * allocate them at load time (better chance of success, but nails down
+ * memory) or when somebody tries to use the camera (riskier), and,
+ * for load-time allocation, how big they should be.
+ *
+ * The controller can cycle through three buffers.  We could use
+ * more by flipping pointers around, but it probably makes little
+ * sense.
+ */
+
+static int alloc_bufs_at_read;
+module_param(alloc_bufs_at_read, bool, 0444);
+MODULE_PARM_DESC(alloc_bufs_at_read,
+               "Non-zero value causes DMA buffers to be allocated when the "
+               "video capture device is read, rather than at module load "
+               "time.  This saves memory, but decreases the chances of "
+               "successfully getting those buffers.  This parameter is "
+               "only used in the vmalloc buffer mode");
+
+static int n_dma_bufs = 3;
+module_param(n_dma_bufs, uint, 0644);
+MODULE_PARM_DESC(n_dma_bufs,
+               "The number of DMA buffers to allocate.  Can be either two "
+               "(saves memory, makes timing tighter) or three.");
+
+static int dma_buf_size = VGA_WIDTH * VGA_HEIGHT * 2;  /* Worst case */
+module_param(dma_buf_size, uint, 0444);
+MODULE_PARM_DESC(dma_buf_size,
+               "The size of the allocated DMA buffers.  If actual operating "
+               "parameters require larger buffers, an attempt to reallocate "
+               "will be made.");
+#else /* MCAM_MODE_VMALLOC */
+static const int alloc_bufs_at_read = 0;
+static const int n_dma_bufs = 3;  /* Used by S/G_PARM */
+#endif /* MCAM_MODE_VMALLOC */
+
+static int flip;
+module_param(flip, bool, 0444);
+MODULE_PARM_DESC(flip,
+               "If set, the sensor will be instructed to flip the image "
+               "vertically.");
+
+static int buffer_mode = -1;
+module_param(buffer_mode, int, 0444);
+MODULE_PARM_DESC(buffer_mode,
+               "Set the buffer mode to be used; default is to go with what "
+               "the platform driver asks for.  Set to 0 for vmalloc, 1 for "
+               "DMA contiguous.");
+
+/*
+ * Status flags.  Always manipulated with bit operations.
+ */
+#define CF_BUF0_VALID   0      /* Buffers valid - first three */
+#define CF_BUF1_VALID   1
+#define CF_BUF2_VALID   2
+#define CF_DMA_ACTIVE   3      /* A frame is incoming */
+#define CF_CONFIG_NEEDED 4     /* Must configure hardware */
+#define CF_SINGLE_BUFFER 5     /* Running with a single buffer */
+#define CF_SG_RESTART   6      /* SG restart needed */
+
+#define sensor_call(cam, o, f, args...) \
+       v4l2_subdev_call(cam->sensor, o, f, ##args)
+
+static struct mcam_format_struct {
+       __u8 *desc;
+       __u32 pixelformat;
+       int bpp;   /* Bytes per pixel */
+       enum v4l2_mbus_pixelcode mbus_code;
+} mcam_formats[] = {
+       {
+               .desc           = "YUYV 4:2:2",
+               .pixelformat    = V4L2_PIX_FMT_YUYV,
+               .mbus_code      = V4L2_MBUS_FMT_YUYV8_2X8,
+               .bpp            = 2,
+       },
+       {
+               .desc           = "RGB 444",
+               .pixelformat    = V4L2_PIX_FMT_RGB444,
+               .mbus_code      = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
+               .bpp            = 2,
+       },
+       {
+               .desc           = "RGB 565",
+               .pixelformat    = V4L2_PIX_FMT_RGB565,
+               .mbus_code      = V4L2_MBUS_FMT_RGB565_2X8_LE,
+               .bpp            = 2,
+       },
+       {
+               .desc           = "Raw RGB Bayer",
+               .pixelformat    = V4L2_PIX_FMT_SBGGR8,
+               .mbus_code      = V4L2_MBUS_FMT_SBGGR8_1X8,
+               .bpp            = 1
+       },
+};
+#define N_MCAM_FMTS ARRAY_SIZE(mcam_formats)
+
+static struct mcam_format_struct *mcam_find_format(u32 pixelformat)
+{
+       unsigned i;
+
+       for (i = 0; i < N_MCAM_FMTS; i++)
+               if (mcam_formats[i].pixelformat == pixelformat)
+                       return mcam_formats + i;
+       /* Not found? Then return the first format. */
+       return mcam_formats;
+}
+
+/*
+ * The default format we use until somebody says otherwise.
+ */
+static const struct v4l2_pix_format mcam_def_pix_format = {
+       .width          = VGA_WIDTH,
+       .height         = VGA_HEIGHT,
+       .pixelformat    = V4L2_PIX_FMT_YUYV,
+       .field          = V4L2_FIELD_NONE,
+       .bytesperline   = VGA_WIDTH*2,
+       .sizeimage      = VGA_WIDTH*VGA_HEIGHT*2,
+};
+
+static const enum v4l2_mbus_pixelcode mcam_def_mbus_code =
+                                       V4L2_MBUS_FMT_YUYV8_2X8;
+
+
+/*
+ * The two-word DMA descriptor format used by the Armada 610 and like.  There
+ * Is a three-word format as well (set C1_DESC_3WORD) where the third
+ * word is a pointer to the next descriptor, but we don't use it.  Two-word
+ * descriptors have to be contiguous in memory.
+ */
+struct mcam_dma_desc {
+       u32 dma_addr;
+       u32 segment_len;
+};
+
+/*
+ * Our buffer type for working with videobuf2.  Note that the vb2
+ * developers have decreed that struct vb2_buffer must be at the
+ * beginning of this structure.
+ */
+struct mcam_vb_buffer {
+       struct vb2_buffer vb_buf;
+       struct list_head queue;
+       struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */
+       dma_addr_t dma_desc_pa;         /* Descriptor physical address */
+       int dma_desc_nent;              /* Number of mapped descriptors */
+};
+
+static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
+{
+       return container_of(vb, struct mcam_vb_buffer, vb_buf);
+}
+
+/*
+ * Hand a completed buffer back to user space.
+ */
+static void mcam_buffer_done(struct mcam_camera *cam, int frame,
+               struct vb2_buffer *vbuf)
+{
+       vbuf->v4l2_buf.bytesused = cam->pix_format.sizeimage;
+       vbuf->v4l2_buf.sequence = cam->buf_seq[frame];
+       vb2_set_plane_payload(vbuf, 0, cam->pix_format.sizeimage);
+       vb2_buffer_done(vbuf, VB2_BUF_STATE_DONE);
+}
+
+
+
+/*
+ * Debugging and related.
+ */
+#define cam_err(cam, fmt, arg...) \
+       dev_err((cam)->dev, fmt, ##arg);
+#define cam_warn(cam, fmt, arg...) \
+       dev_warn((cam)->dev, fmt, ##arg);
+#define cam_dbg(cam, fmt, arg...) \
+       dev_dbg((cam)->dev, fmt, ##arg);
+
+
+/*
+ * Flag manipulation helpers
+ */
+static void mcam_reset_buffers(struct mcam_camera *cam)
+{
+       int i;
+
+       cam->next_buf = -1;
+       for (i = 0; i < cam->nbufs; i++)
+               clear_bit(i, &cam->flags);
+}
+
+static inline int mcam_needs_config(struct mcam_camera *cam)
+{
+       return test_bit(CF_CONFIG_NEEDED, &cam->flags);
+}
+
+static void mcam_set_config_needed(struct mcam_camera *cam, int needed)
+{
+       if (needed)
+               set_bit(CF_CONFIG_NEEDED, &cam->flags);
+       else
+               clear_bit(CF_CONFIG_NEEDED, &cam->flags);
+}
+
+/* ------------------------------------------------------------------- */
+/*
+ * Make the controller start grabbing images.  Everything must
+ * be set up before doing this.
+ */
+static void mcam_ctlr_start(struct mcam_camera *cam)
+{
+       /* set_bit performs a read, so no other barrier should be
+          needed here */
+       mcam_reg_set_bit(cam, REG_CTRL0, C0_ENABLE);
+}
+
+static void mcam_ctlr_stop(struct mcam_camera *cam)
+{
+       mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
+}
+
+/* ------------------------------------------------------------------- */
+
+#ifdef MCAM_MODE_VMALLOC
+/*
+ * Code specific to the vmalloc buffer mode.
+ */
+
+/*
+ * Allocate in-kernel DMA buffers for vmalloc mode.
+ */
+static int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
+{
+       int i;
+
+       mcam_set_config_needed(cam, 1);
+       if (loadtime)
+               cam->dma_buf_size = dma_buf_size;
+       else
+               cam->dma_buf_size = cam->pix_format.sizeimage;
+       if (n_dma_bufs > 3)
+               n_dma_bufs = 3;
+
+       cam->nbufs = 0;
+       for (i = 0; i < n_dma_bufs; i++) {
+               cam->dma_bufs[i] = dma_alloc_coherent(cam->dev,
+                               cam->dma_buf_size, cam->dma_handles + i,
+                               GFP_KERNEL);
+               if (cam->dma_bufs[i] == NULL) {
+                       cam_warn(cam, "Failed to allocate DMA buffer\n");
+                       break;
+               }
+               (cam->nbufs)++;
+       }
+
+       switch (cam->nbufs) {
+       case 1:
+               dma_free_coherent(cam->dev, cam->dma_buf_size,
+                               cam->dma_bufs[0], cam->dma_handles[0]);
+               cam->nbufs = 0;
+       case 0:
+               cam_err(cam, "Insufficient DMA buffers, cannot operate\n");
+               return -ENOMEM;
+
+       case 2:
+               if (n_dma_bufs > 2)
+                       cam_warn(cam, "Will limp along with only 2 buffers\n");
+               break;
+       }
+       return 0;
+}
+
+static void mcam_free_dma_bufs(struct mcam_camera *cam)
+{
+       int i;
+
+       for (i = 0; i < cam->nbufs; i++) {
+               dma_free_coherent(cam->dev, cam->dma_buf_size,
+                               cam->dma_bufs[i], cam->dma_handles[i]);
+               cam->dma_bufs[i] = NULL;
+       }
+       cam->nbufs = 0;
+}
+
+
+/*
+ * Set up DMA buffers when operating in vmalloc mode
+ */
+static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam)
+{
+       /*
+        * Store the first two Y buffers (we aren't supporting
+        * planar formats for now, so no UV bufs).  Then either
+        * set the third if it exists, or tell the controller
+        * to just use two.
+        */
+       mcam_reg_write(cam, REG_Y0BAR, cam->dma_handles[0]);
+       mcam_reg_write(cam, REG_Y1BAR, cam->dma_handles[1]);
+       if (cam->nbufs > 2) {
+               mcam_reg_write(cam, REG_Y2BAR, cam->dma_handles[2]);
+               mcam_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS);
+       } else
+               mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
+       if (cam->chip_id == V4L2_IDENT_CAFE)
+               mcam_reg_write(cam, REG_UBAR, 0); /* 32 bits only */
+}
+
+/*
+ * Copy data out to user space in the vmalloc case
+ */
+static void mcam_frame_tasklet(unsigned long data)
+{
+       struct mcam_camera *cam = (struct mcam_camera *) data;
+       int i;
+       unsigned long flags;
+       struct mcam_vb_buffer *buf;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       for (i = 0; i < cam->nbufs; i++) {
+               int bufno = cam->next_buf;
+
+               if (cam->state != S_STREAMING || bufno < 0)
+                       break;  /* I/O got stopped */
+               if (++(cam->next_buf) >= cam->nbufs)
+                       cam->next_buf = 0;
+               if (!test_bit(bufno, &cam->flags))
+                       continue;
+               if (list_empty(&cam->buffers)) {
+                       singles++;
+                       break;  /* Leave it valid, hope for better later */
+               }
+               delivered++;
+               clear_bit(bufno, &cam->flags);
+               buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer,
+                               queue);
+               list_del_init(&buf->queue);
+               /*
+                * Drop the lock during the big copy.  This *should* be safe...
+                */
+               spin_unlock_irqrestore(&cam->dev_lock, flags);
+               memcpy(vb2_plane_vaddr(&buf->vb_buf, 0), cam->dma_bufs[bufno],
+                               cam->pix_format.sizeimage);
+               mcam_buffer_done(cam, bufno, &buf->vb_buf);
+               spin_lock_irqsave(&cam->dev_lock, flags);
+       }
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+
+/*
+ * Make sure our allocated buffers are up to the task.
+ */
+static int mcam_check_dma_buffers(struct mcam_camera *cam)
+{
+       if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage)
+                       mcam_free_dma_bufs(cam);
+       if (cam->nbufs == 0)
+               return mcam_alloc_dma_bufs(cam, 0);
+       return 0;
+}
+
+static void mcam_vmalloc_done(struct mcam_camera *cam, int frame)
+{
+       tasklet_schedule(&cam->s_tasklet);
+}
+
+#else /* MCAM_MODE_VMALLOC */
+
+static inline int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
+{
+       return 0;
+}
+
+static inline void mcam_free_dma_bufs(struct mcam_camera *cam)
+{
+       return;
+}
+
+static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
+{
+       return 0;
+}
+
+
+
+#endif /* MCAM_MODE_VMALLOC */
+
+
+#ifdef MCAM_MODE_DMA_CONTIG
+/* ---------------------------------------------------------------------- */
+/*
+ * DMA-contiguous code.
+ */
+/*
+ * Set up a contiguous buffer for the given frame.  Here also is where
+ * the underrun strategy is set: if there is no buffer available, reuse
+ * the buffer from the other BAR and set the CF_SINGLE_BUFFER flag to
+ * keep the interrupt handler from giving that buffer back to user
+ * space.  In this way, we always have a buffer to DMA to and don't
+ * have to try to play games stopping and restarting the controller.
+ */
+static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
+{
+       struct mcam_vb_buffer *buf;
+       /*
+        * If there are no available buffers, go into single mode
+        */
+       if (list_empty(&cam->buffers)) {
+               buf = cam->vb_bufs[frame ^ 0x1];
+               cam->vb_bufs[frame] = buf;
+               mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
+                               vb2_dma_contig_plane_paddr(&buf->vb_buf, 0));
+               set_bit(CF_SINGLE_BUFFER, &cam->flags);
+               singles++;
+               return;
+       }
+       /*
+        * OK, we have a buffer we can use.
+        */
+       buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue);
+       list_del_init(&buf->queue);
+       mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
+                       vb2_dma_contig_plane_paddr(&buf->vb_buf, 0));
+       cam->vb_bufs[frame] = buf;
+       clear_bit(CF_SINGLE_BUFFER, &cam->flags);
+}
+
+/*
+ * Initial B_DMA_contig setup.
+ */
+static void mcam_ctlr_dma_contig(struct mcam_camera *cam)
+{
+       mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
+       cam->nbufs = 2;
+       mcam_set_contig_buffer(cam, 0);
+       mcam_set_contig_buffer(cam, 1);
+}
+
+/*
+ * Frame completion handling.
+ */
+static void mcam_dma_contig_done(struct mcam_camera *cam, int frame)
+{
+       struct mcam_vb_buffer *buf = cam->vb_bufs[frame];
+
+       if (!test_bit(CF_SINGLE_BUFFER, &cam->flags)) {
+               delivered++;
+               mcam_buffer_done(cam, frame, &buf->vb_buf);
+       }
+       mcam_set_contig_buffer(cam, frame);
+}
+
+#endif /* MCAM_MODE_DMA_CONTIG */
+
+#ifdef MCAM_MODE_DMA_SG
+/* ---------------------------------------------------------------------- */
+/*
+ * Scatter/gather-specific code.
+ */
+
+/*
+ * Set up the next buffer for S/G I/O; caller should be sure that
+ * the controller is stopped and a buffer is available.
+ */
+static void mcam_sg_next_buffer(struct mcam_camera *cam)
+{
+       struct mcam_vb_buffer *buf;
+
+       buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue);
+       list_del_init(&buf->queue);
+       mcam_reg_write(cam, REG_DMA_DESC_Y, buf->dma_desc_pa);
+       mcam_reg_write(cam, REG_DESC_LEN_Y,
+                       buf->dma_desc_nent*sizeof(struct mcam_dma_desc));
+       mcam_reg_write(cam, REG_DESC_LEN_U, 0);
+       mcam_reg_write(cam, REG_DESC_LEN_V, 0);
+       cam->vb_bufs[0] = buf;
+}
+
+/*
+ * Initial B_DMA_sg setup
+ */
+static void mcam_ctlr_dma_sg(struct mcam_camera *cam)
+{
+       mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_3WORD);
+       mcam_sg_next_buffer(cam);
+       mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA);
+       cam->nbufs = 3;
+}
+
+
+/*
+ * Frame completion with S/G is trickier.  We can't muck with
+ * a descriptor chain on the fly, since the controller buffers it
+ * internally.  So we have to actually stop and restart; Marvell
+ * says this is the way to do it.
+ *
+ * Of course, stopping is easier said than done; experience shows
+ * that the controller can start a frame *after* C0_ENABLE has been
+ * cleared.  So when running in S/G mode, the controller is "stopped"
+ * on receipt of the start-of-frame interrupt.  That means we can
+ * safely change the DMA descriptor array here and restart things
+ * (assuming there's another buffer waiting to go).
+ */
+static void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
+{
+       struct mcam_vb_buffer *buf = cam->vb_bufs[0];
+
+       /*
+        * Very Bad Not Good Things happen if you don't clear
+        * C1_DESC_ENA before making any descriptor changes.
+        */
+       mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA);
+       /*
+        * If we have another buffer available, put it in and
+        * restart the engine.
+        */
+       if (!list_empty(&cam->buffers)) {
+               mcam_sg_next_buffer(cam);
+               mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA);
+               mcam_ctlr_start(cam);
+       /*
+        * Otherwise set CF_SG_RESTART and the controller will
+        * be restarted once another buffer shows up.
+        */
+       } else {
+               set_bit(CF_SG_RESTART, &cam->flags);
+               singles++;
+       }
+       /*
+        * Now we can give the completed frame back to user space.
+        */
+       delivered++;
+       mcam_buffer_done(cam, frame, &buf->vb_buf);
+}
+
+
+/*
+ * Scatter/gather mode requires stopping the controller between
+ * frames so we can put in a new DMA descriptor array.  If no new
+ * buffer exists at frame completion, the controller is left stopped;
+ * this function is charged with gettig things going again.
+ */
+static void mcam_sg_restart(struct mcam_camera *cam)
+{
+       mcam_ctlr_dma_sg(cam);
+       mcam_ctlr_start(cam);
+       clear_bit(CF_SG_RESTART, &cam->flags);
+}
+
+#else /* MCAM_MODE_DMA_SG */
+
+static inline void mcam_sg_restart(struct mcam_camera *cam)
+{
+       return;
+}
+
+#endif /* MCAM_MODE_DMA_SG */
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Buffer-mode-independent controller code.
+ */
+
+/*
+ * Image format setup
+ */
+static void mcam_ctlr_image(struct mcam_camera *cam)
+{
+       int imgsz;
+       struct v4l2_pix_format *fmt = &cam->pix_format;
+
+       imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |
+               (fmt->bytesperline & IMGSZ_H_MASK);
+       mcam_reg_write(cam, REG_IMGSIZE, imgsz);
+       mcam_reg_write(cam, REG_IMGOFFSET, 0);
+       /* YPITCH just drops the last two bits */
+       mcam_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,
+                       IMGP_YP_MASK);
+       /*
+        * Tell the controller about the image format we are using.
+        */
+       switch (cam->pix_format.pixelformat) {
+       case V4L2_PIX_FMT_YUYV:
+           mcam_reg_write_mask(cam, REG_CTRL0,
+                           C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
+                           C0_DF_MASK);
+           break;
+
+       case V4L2_PIX_FMT_RGB444:
+           mcam_reg_write_mask(cam, REG_CTRL0,
+                           C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
+                           C0_DF_MASK);
+               /* Alpha value? */
+           break;
+
+       case V4L2_PIX_FMT_RGB565:
+           mcam_reg_write_mask(cam, REG_CTRL0,
+                           C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
+                           C0_DF_MASK);
+           break;
+
+       default:
+           cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
+           break;
+       }
+       /*
+        * Make sure it knows we want to use hsync/vsync.
+        */
+       mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
+                       C0_SIFM_MASK);
+}
+
+
+/*
+ * Configure the controller for operation; caller holds the
+ * device mutex.
+ */
+static int mcam_ctlr_configure(struct mcam_camera *cam)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       cam->dma_setup(cam);
+       mcam_ctlr_image(cam);
+       mcam_set_config_needed(cam, 0);
+       clear_bit(CF_SG_RESTART, &cam->flags);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       return 0;
+}
+
+static void mcam_ctlr_irq_enable(struct mcam_camera *cam)
+{
+       /*
+        * Clear any pending interrupts, since we do not
+        * expect to have I/O active prior to enabling.
+        */
+       mcam_reg_write(cam, REG_IRQSTAT, FRAMEIRQS);
+       mcam_reg_set_bit(cam, REG_IRQMASK, FRAMEIRQS);
+}
+
+static void mcam_ctlr_irq_disable(struct mcam_camera *cam)
+{
+       mcam_reg_clear_bit(cam, REG_IRQMASK, FRAMEIRQS);
+}
+
+
+
+static void mcam_ctlr_init(struct mcam_camera *cam)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       /*
+        * Make sure it's not powered down.
+        */
+       mcam_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
+       /*
+        * Turn off the enable bit.  It sure should be off anyway,
+        * but it's good to be sure.
+        */
+       mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
+       /*
+        * Clock the sensor appropriately.  Controller clock should
+        * be 48MHz, sensor "typical" value is half that.
+        */
+       mcam_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+
+/*
+ * Stop the controller, and don't return until we're really sure that no
+ * further DMA is going on.
+ */
+static void mcam_ctlr_stop_dma(struct mcam_camera *cam)
+{
+       unsigned long flags;
+
+       /*
+        * Theory: stop the camera controller (whether it is operating
+        * or not).  Delay briefly just in case we race with the SOF
+        * interrupt, then wait until no DMA is active.
+        */
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       clear_bit(CF_SG_RESTART, &cam->flags);
+       mcam_ctlr_stop(cam);
+       cam->state = S_IDLE;
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       msleep(40);
+       if (test_bit(CF_DMA_ACTIVE, &cam->flags))
+               cam_err(cam, "Timeout waiting for DMA to end\n");
+               /* This would be bad news - what now? */
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       mcam_ctlr_irq_disable(cam);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+/*
+ * Power up and down.
+ */
+static void mcam_ctlr_power_up(struct mcam_camera *cam)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       cam->plat_power_up(cam);
+       mcam_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       msleep(5); /* Just to be sure */
+}
+
+static void mcam_ctlr_power_down(struct mcam_camera *cam)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       /*
+        * School of hard knocks department: be sure we do any register
+        * twiddling on the controller *before* calling the platform
+        * power down routine.
+        */
+       mcam_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN);
+       cam->plat_power_down(cam);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+/* -------------------------------------------------------------------- */
+/*
+ * Communications with the sensor.
+ */
+
+static int __mcam_cam_reset(struct mcam_camera *cam)
+{
+       return sensor_call(cam, core, reset, 0);
+}
+
+/*
+ * We have found the sensor on the i2c.  Let's try to have a
+ * conversation.
+ */
+static int mcam_cam_init(struct mcam_camera *cam)
+{
+       struct v4l2_dbg_chip_ident chip;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       if (cam->state != S_NOTREADY)
+               cam_warn(cam, "Cam init with device in funky state %d",
+                               cam->state);
+       ret = __mcam_cam_reset(cam);
+       if (ret)
+               goto out;
+       chip.ident = V4L2_IDENT_NONE;
+       chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR;
+       chip.match.addr = cam->sensor_addr;
+       ret = sensor_call(cam, core, g_chip_ident, &chip);
+       if (ret)
+               goto out;
+       cam->sensor_type = chip.ident;
+       if (cam->sensor_type != V4L2_IDENT_OV7670) {
+               cam_err(cam, "Unsupported sensor type 0x%x", cam->sensor_type);
+               ret = -EINVAL;
+               goto out;
+       }
+/* Get/set parameters? */
+       ret = 0;
+       cam->state = S_IDLE;
+out:
+       mcam_ctlr_power_down(cam);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+/*
+ * Configure the sensor to match the parameters we have.  Caller should
+ * hold s_mutex
+ */
+static int mcam_cam_set_flip(struct mcam_camera *cam)
+{
+       struct v4l2_control ctrl;
+
+       memset(&ctrl, 0, sizeof(ctrl));
+       ctrl.id = V4L2_CID_VFLIP;
+       ctrl.value = flip;
+       return sensor_call(cam, core, s_ctrl, &ctrl);
+}
+
+
+static int mcam_cam_configure(struct mcam_camera *cam)
+{
+       struct v4l2_mbus_framefmt mbus_fmt;
+       int ret;
+
+       v4l2_fill_mbus_format(&mbus_fmt, &cam->pix_format, cam->mbus_code);
+       ret = sensor_call(cam, core, init, 0);
+       if (ret == 0)
+               ret = sensor_call(cam, video, s_mbus_fmt, &mbus_fmt);
+       /*
+        * OV7670 does weird things if flip is set *before* format...
+        */
+       ret += mcam_cam_set_flip(cam);
+       return ret;
+}
+
+/*
+ * Get everything ready, and start grabbing frames.
+ */
+static int mcam_read_setup(struct mcam_camera *cam)
+{
+       int ret;
+       unsigned long flags;
+
+       /*
+        * Configuration.  If we still don't have DMA buffers,
+        * make one last, desperate attempt.
+        */
+       if (cam->buffer_mode == B_vmalloc && cam->nbufs == 0 &&
+                       mcam_alloc_dma_bufs(cam, 0))
+               return -ENOMEM;
+
+       if (mcam_needs_config(cam)) {
+               mcam_cam_configure(cam);
+               ret = mcam_ctlr_configure(cam);
+               if (ret)
+                       return ret;
+       }
+
+       /*
+        * Turn it loose.
+        */
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       mcam_reset_buffers(cam);
+       mcam_ctlr_irq_enable(cam);
+       cam->state = S_STREAMING;
+       mcam_ctlr_start(cam);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+/*
+ * Videobuf2 interface code.
+ */
+
+static int mcam_vb_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
+               unsigned int *num_planes, unsigned long sizes[],
+               void *alloc_ctxs[])
+{
+       struct mcam_camera *cam = vb2_get_drv_priv(vq);
+       int minbufs = (cam->buffer_mode == B_DMA_contig) ? 3 : 2;
+
+       sizes[0] = cam->pix_format.sizeimage;
+       *num_planes = 1; /* Someday we have to support planar formats... */
+       if (*nbufs < minbufs)
+               *nbufs = minbufs;
+       if (cam->buffer_mode == B_DMA_contig)
+               alloc_ctxs[0] = cam->vb_alloc_ctx;
+       return 0;
+}
+
+
+static void mcam_vb_buf_queue(struct vb2_buffer *vb)
+{
+       struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+       struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+       unsigned long flags;
+       int start;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers);
+       list_add(&mvb->queue, &cam->buffers);
+       if (test_bit(CF_SG_RESTART, &cam->flags))
+               mcam_sg_restart(cam);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       if (start)
+               mcam_read_setup(cam);
+}
+
+
+/*
+ * vb2 uses these to release the mutex when waiting in dqbuf.  I'm
+ * not actually sure we need to do this (I'm not sure that vb2_dqbuf() needs
+ * to be called with the mutex held), but better safe than sorry.
+ */
+static void mcam_vb_wait_prepare(struct vb2_queue *vq)
+{
+       struct mcam_camera *cam = vb2_get_drv_priv(vq);
+
+       mutex_unlock(&cam->s_mutex);
+}
+
+static void mcam_vb_wait_finish(struct vb2_queue *vq)
+{
+       struct mcam_camera *cam = vb2_get_drv_priv(vq);
+
+       mutex_lock(&cam->s_mutex);
+}
+
+/*
+ * These need to be called with the mutex held from vb2
+ */
+static int mcam_vb_start_streaming(struct vb2_queue *vq)
+{
+       struct mcam_camera *cam = vb2_get_drv_priv(vq);
+
+       if (cam->state != S_IDLE)
+               return -EINVAL;
+       cam->sequence = 0;
+       /*
+        * Videobuf2 sneakily hoards all the buffers and won't
+        * give them to us until *after* streaming starts.  But
+        * we can't actually start streaming until we have a
+        * destination.  So go into a wait state and hope they
+        * give us buffers soon.
+        */
+       if (cam->buffer_mode != B_vmalloc && list_empty(&cam->buffers)) {
+               cam->state = S_BUFWAIT;
+               return 0;
+       }
+       return mcam_read_setup(cam);
+}
+
+static int mcam_vb_stop_streaming(struct vb2_queue *vq)
+{
+       struct mcam_camera *cam = vb2_get_drv_priv(vq);
+       unsigned long flags;
+
+       if (cam->state == S_BUFWAIT) {
+               /* They never gave us buffers */
+               cam->state = S_IDLE;
+               return 0;
+       }
+       if (cam->state != S_STREAMING)
+               return -EINVAL;
+       mcam_ctlr_stop_dma(cam);
+       /*
+        * VB2 reclaims the buffers, so we need to forget
+        * about them.
+        */
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       INIT_LIST_HEAD(&cam->buffers);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       return 0;
+}
+
+
+static const struct vb2_ops mcam_vb2_ops = {
+       .queue_setup            = mcam_vb_queue_setup,
+       .buf_queue              = mcam_vb_buf_queue,
+       .start_streaming        = mcam_vb_start_streaming,
+       .stop_streaming         = mcam_vb_stop_streaming,
+       .wait_prepare           = mcam_vb_wait_prepare,
+       .wait_finish            = mcam_vb_wait_finish,
+};
+
+
+#ifdef MCAM_MODE_DMA_SG
+/*
+ * Scatter/gather mode uses all of the above functions plus a
+ * few extras to deal with DMA mapping.
+ */
+static int mcam_vb_sg_buf_init(struct vb2_buffer *vb)
+{
+       struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+       struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+       int ndesc = cam->pix_format.sizeimage/PAGE_SIZE + 1;
+
+       mvb->dma_desc = dma_alloc_coherent(cam->dev,
+                       ndesc * sizeof(struct mcam_dma_desc),
+                       &mvb->dma_desc_pa, GFP_KERNEL);
+       if (mvb->dma_desc == NULL) {
+               cam_err(cam, "Unable to get DMA descriptor array\n");
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
+{
+       struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+       struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+       struct vb2_dma_sg_desc *sgd = vb2_dma_sg_plane_desc(vb, 0);
+       struct mcam_dma_desc *desc = mvb->dma_desc;
+       struct scatterlist *sg;
+       int i;
+
+       mvb->dma_desc_nent = dma_map_sg(cam->dev, sgd->sglist, sgd->num_pages,
+                       DMA_FROM_DEVICE);
+       if (mvb->dma_desc_nent <= 0)
+               return -EIO;  /* Not sure what's right here */
+       for_each_sg(sgd->sglist, sg, mvb->dma_desc_nent, i) {
+               desc->dma_addr = sg_dma_address(sg);
+               desc->segment_len = sg_dma_len(sg);
+               desc++;
+       }
+       return 0;
+}
+
+static int mcam_vb_sg_buf_finish(struct vb2_buffer *vb)
+{
+       struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+       struct vb2_dma_sg_desc *sgd = vb2_dma_sg_plane_desc(vb, 0);
+
+       dma_unmap_sg(cam->dev, sgd->sglist, sgd->num_pages, DMA_FROM_DEVICE);
+       return 0;
+}
+
+static void mcam_vb_sg_buf_cleanup(struct vb2_buffer *vb)
+{
+       struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+       struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+       int ndesc = cam->pix_format.sizeimage/PAGE_SIZE + 1;
+
+       dma_free_coherent(cam->dev, ndesc * sizeof(struct mcam_dma_desc),
+                       mvb->dma_desc, mvb->dma_desc_pa);
+}
+
+
+static const struct vb2_ops mcam_vb2_sg_ops = {
+       .queue_setup            = mcam_vb_queue_setup,
+       .buf_init               = mcam_vb_sg_buf_init,
+       .buf_prepare            = mcam_vb_sg_buf_prepare,
+       .buf_queue              = mcam_vb_buf_queue,
+       .buf_finish             = mcam_vb_sg_buf_finish,
+       .buf_cleanup            = mcam_vb_sg_buf_cleanup,
+       .start_streaming        = mcam_vb_start_streaming,
+       .stop_streaming         = mcam_vb_stop_streaming,
+       .wait_prepare           = mcam_vb_wait_prepare,
+       .wait_finish            = mcam_vb_wait_finish,
+};
+
+#endif /* MCAM_MODE_DMA_SG */
+
+static int mcam_setup_vb2(struct mcam_camera *cam)
+{
+       struct vb2_queue *vq = &cam->vb_queue;
+
+       memset(vq, 0, sizeof(*vq));
+       vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       vq->drv_priv = cam;
+       INIT_LIST_HEAD(&cam->buffers);
+       switch (cam->buffer_mode) {
+       case B_DMA_contig:
+#ifdef MCAM_MODE_DMA_CONTIG
+               vq->ops = &mcam_vb2_ops;
+               vq->mem_ops = &vb2_dma_contig_memops;
+               cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
+               vq->io_modes = VB2_MMAP | VB2_USERPTR;
+               cam->dma_setup = mcam_ctlr_dma_contig;
+               cam->frame_complete = mcam_dma_contig_done;
+#endif
+               break;
+       case B_DMA_sg:
+#ifdef MCAM_MODE_DMA_SG
+               vq->ops = &mcam_vb2_sg_ops;
+               vq->mem_ops = &vb2_dma_sg_memops;
+               vq->io_modes = VB2_MMAP | VB2_USERPTR;
+               cam->dma_setup = mcam_ctlr_dma_sg;
+               cam->frame_complete = mcam_dma_sg_done;
+#endif
+               break;
+       case B_vmalloc:
+#ifdef MCAM_MODE_VMALLOC
+               tasklet_init(&cam->s_tasklet, mcam_frame_tasklet,
+                               (unsigned long) cam);
+               vq->ops = &mcam_vb2_ops;
+               vq->mem_ops = &vb2_vmalloc_memops;
+               vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
+               vq->io_modes = VB2_MMAP;
+               cam->dma_setup = mcam_ctlr_dma_vmalloc;
+               cam->frame_complete = mcam_vmalloc_done;
+#endif
+               break;
+       }
+       return vb2_queue_init(vq);
+}
+
+static void mcam_cleanup_vb2(struct mcam_camera *cam)
+{
+       vb2_queue_release(&cam->vb_queue);
+#ifdef MCAM_MODE_DMA_CONTIG
+       if (cam->buffer_mode == B_DMA_contig)
+               vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
+#endif
+}
+
+
+/* ---------------------------------------------------------------------- */
+/*
+ * The long list of V4L2 ioctl() operations.
+ */
+
+static int mcam_vidioc_streamon(struct file *filp, void *priv,
+               enum v4l2_buf_type type)
+{
+       struct mcam_camera *cam = filp->private_data;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = vb2_streamon(&cam->vb_queue, type);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+static int mcam_vidioc_streamoff(struct file *filp, void *priv,
+               enum v4l2_buf_type type)
+{
+       struct mcam_camera *cam = filp->private_data;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = vb2_streamoff(&cam->vb_queue, type);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+static int mcam_vidioc_reqbufs(struct file *filp, void *priv,
+               struct v4l2_requestbuffers *req)
+{
+       struct mcam_camera *cam = filp->private_data;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = vb2_reqbufs(&cam->vb_queue, req);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+static int mcam_vidioc_querybuf(struct file *filp, void *priv,
+               struct v4l2_buffer *buf)
+{
+       struct mcam_camera *cam = filp->private_data;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = vb2_querybuf(&cam->vb_queue, buf);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+static int mcam_vidioc_qbuf(struct file *filp, void *priv,
+               struct v4l2_buffer *buf)
+{
+       struct mcam_camera *cam = filp->private_data;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = vb2_qbuf(&cam->vb_queue, buf);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+static int mcam_vidioc_dqbuf(struct file *filp, void *priv,
+               struct v4l2_buffer *buf)
+{
+       struct mcam_camera *cam = filp->private_data;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = vb2_dqbuf(&cam->vb_queue, buf, filp->f_flags & O_NONBLOCK);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+
+static int mcam_vidioc_queryctrl(struct file *filp, void *priv,
+               struct v4l2_queryctrl *qc)
+{
+       struct mcam_camera *cam = priv;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = sensor_call(cam, core, queryctrl, qc);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+static int mcam_vidioc_g_ctrl(struct file *filp, void *priv,
+               struct v4l2_control *ctrl)
+{
+       struct mcam_camera *cam = priv;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = sensor_call(cam, core, g_ctrl, ctrl);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+static int mcam_vidioc_s_ctrl(struct file *filp, void *priv,
+               struct v4l2_control *ctrl)
+{
+       struct mcam_camera *cam = priv;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = sensor_call(cam, core, s_ctrl, ctrl);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+static int mcam_vidioc_querycap(struct file *file, void *priv,
+               struct v4l2_capability *cap)
+{
+       strcpy(cap->driver, "marvell_ccic");
+       strcpy(cap->card, "marvell_ccic");
+       cap->version = 1;
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+       return 0;
+}
+
+
+static int mcam_vidioc_enum_fmt_vid_cap(struct file *filp,
+               void *priv, struct v4l2_fmtdesc *fmt)
+{
+       if (fmt->index >= N_MCAM_FMTS)
+               return -EINVAL;
+       strlcpy(fmt->description, mcam_formats[fmt->index].desc,
+                       sizeof(fmt->description));
+       fmt->pixelformat = mcam_formats[fmt->index].pixelformat;
+       return 0;
+}
+
+static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
+               struct v4l2_format *fmt)
+{
+       struct mcam_camera *cam = priv;
+       struct mcam_format_struct *f;
+       struct v4l2_pix_format *pix = &fmt->fmt.pix;
+       struct v4l2_mbus_framefmt mbus_fmt;
+       int ret;
+
+       f = mcam_find_format(pix->pixelformat);
+       pix->pixelformat = f->pixelformat;
+       v4l2_fill_mbus_format(&mbus_fmt, pix, f->mbus_code);
+       mutex_lock(&cam->s_mutex);
+       ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
+       mutex_unlock(&cam->s_mutex);
+       v4l2_fill_pix_format(pix, &mbus_fmt);
+       pix->bytesperline = pix->width * f->bpp;
+       pix->sizeimage = pix->height * pix->bytesperline;
+       return ret;
+}
+
+static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
+               struct v4l2_format *fmt)
+{
+       struct mcam_camera *cam = priv;
+       struct mcam_format_struct *f;
+       int ret;
+
+       /*
+        * Can't do anything if the device is not idle
+        * Also can't if there are streaming buffers in place.
+        */
+       if (cam->state != S_IDLE || cam->vb_queue.num_buffers > 0)
+               return -EBUSY;
+
+       f = mcam_find_format(fmt->fmt.pix.pixelformat);
+
+       /*
+        * See if the formatting works in principle.
+        */
+       ret = mcam_vidioc_try_fmt_vid_cap(filp, priv, fmt);
+       if (ret)
+               return ret;
+       /*
+        * Now we start to change things for real, so let's do it
+        * under lock.
+        */
+       mutex_lock(&cam->s_mutex);
+       cam->pix_format = fmt->fmt.pix;
+       cam->mbus_code = f->mbus_code;
+
+       /*
+        * Make sure we have appropriate DMA buffers.
+        */
+       if (cam->buffer_mode == B_vmalloc) {
+               ret = mcam_check_dma_buffers(cam);
+               if (ret)
+                       goto out;
+       }
+       mcam_set_config_needed(cam, 1);
+       ret = 0;
+out:
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+/*
+ * Return our stored notion of how the camera is/should be configured.
+ * The V4l2 spec wants us to be smarter, and actually get this from
+ * the camera (and not mess with it at open time).  Someday.
+ */
+static int mcam_vidioc_g_fmt_vid_cap(struct file *filp, void *priv,
+               struct v4l2_format *f)
+{
+       struct mcam_camera *cam = priv;
+
+       f->fmt.pix = cam->pix_format;
+       return 0;
+}
+
+/*
+ * We only have one input - the sensor - so minimize the nonsense here.
+ */
+static int mcam_vidioc_enum_input(struct file *filp, void *priv,
+               struct v4l2_input *input)
+{
+       if (input->index != 0)
+               return -EINVAL;
+
+       input->type = V4L2_INPUT_TYPE_CAMERA;
+       input->std = V4L2_STD_ALL; /* Not sure what should go here */
+       strcpy(input->name, "Camera");
+       return 0;
+}
+
+static int mcam_vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int mcam_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+       if (i != 0)
+               return -EINVAL;
+       return 0;
+}
+
+/* from vivi.c */
+static int mcam_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
+{
+       return 0;
+}
+
+/*
+ * G/S_PARM.  Most of this is done by the sensor, but we are
+ * the level which controls the number of read buffers.
+ */
+static int mcam_vidioc_g_parm(struct file *filp, void *priv,
+               struct v4l2_streamparm *parms)
+{
+       struct mcam_camera *cam = priv;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = sensor_call(cam, video, g_parm, parms);
+       mutex_unlock(&cam->s_mutex);
+       parms->parm.capture.readbuffers = n_dma_bufs;
+       return ret;
+}
+
+static int mcam_vidioc_s_parm(struct file *filp, void *priv,
+               struct v4l2_streamparm *parms)
+{
+       struct mcam_camera *cam = priv;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = sensor_call(cam, video, s_parm, parms);
+       mutex_unlock(&cam->s_mutex);
+       parms->parm.capture.readbuffers = n_dma_bufs;
+       return ret;
+}
+
+static int mcam_vidioc_g_chip_ident(struct file *file, void *priv,
+               struct v4l2_dbg_chip_ident *chip)
+{
+       struct mcam_camera *cam = priv;
+
+       chip->ident = V4L2_IDENT_NONE;
+       chip->revision = 0;
+       if (v4l2_chip_match_host(&chip->match)) {
+               chip->ident = cam->chip_id;
+               return 0;
+       }
+       return sensor_call(cam, core, g_chip_ident, chip);
+}
+
+static int mcam_vidioc_enum_framesizes(struct file *filp, void *priv,
+               struct v4l2_frmsizeenum *sizes)
+{
+       struct mcam_camera *cam = priv;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = sensor_call(cam, video, enum_framesizes, sizes);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+static int mcam_vidioc_enum_frameintervals(struct file *filp, void *priv,
+               struct v4l2_frmivalenum *interval)
+{
+       struct mcam_camera *cam = priv;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = sensor_call(cam, video, enum_frameintervals, interval);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mcam_vidioc_g_register(struct file *file, void *priv,
+               struct v4l2_dbg_register *reg)
+{
+       struct mcam_camera *cam = priv;
+
+       if (v4l2_chip_match_host(&reg->match)) {
+               reg->val = mcam_reg_read(cam, reg->reg);
+               reg->size = 4;
+               return 0;
+       }
+       return sensor_call(cam, core, g_register, reg);
+}
+
+static int mcam_vidioc_s_register(struct file *file, void *priv,
+               struct v4l2_dbg_register *reg)
+{
+       struct mcam_camera *cam = priv;
+
+       if (v4l2_chip_match_host(&reg->match)) {
+               mcam_reg_write(cam, reg->reg, reg->val);
+               return 0;
+       }
+       return sensor_call(cam, core, s_register, reg);
+}
+#endif
+
+static const struct v4l2_ioctl_ops mcam_v4l_ioctl_ops = {
+       .vidioc_querycap        = mcam_vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = mcam_vidioc_enum_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = mcam_vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap   = mcam_vidioc_s_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap   = mcam_vidioc_g_fmt_vid_cap,
+       .vidioc_enum_input      = mcam_vidioc_enum_input,
+       .vidioc_g_input         = mcam_vidioc_g_input,
+       .vidioc_s_input         = mcam_vidioc_s_input,
+       .vidioc_s_std           = mcam_vidioc_s_std,
+       .vidioc_reqbufs         = mcam_vidioc_reqbufs,
+       .vidioc_querybuf        = mcam_vidioc_querybuf,
+       .vidioc_qbuf            = mcam_vidioc_qbuf,
+       .vidioc_dqbuf           = mcam_vidioc_dqbuf,
+       .vidioc_streamon        = mcam_vidioc_streamon,
+       .vidioc_streamoff       = mcam_vidioc_streamoff,
+       .vidioc_queryctrl       = mcam_vidioc_queryctrl,
+       .vidioc_g_ctrl          = mcam_vidioc_g_ctrl,
+       .vidioc_s_ctrl          = mcam_vidioc_s_ctrl,
+       .vidioc_g_parm          = mcam_vidioc_g_parm,
+       .vidioc_s_parm          = mcam_vidioc_s_parm,
+       .vidioc_enum_framesizes = mcam_vidioc_enum_framesizes,
+       .vidioc_enum_frameintervals = mcam_vidioc_enum_frameintervals,
+       .vidioc_g_chip_ident    = mcam_vidioc_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register      = mcam_vidioc_g_register,
+       .vidioc_s_register      = mcam_vidioc_s_register,
+#endif
+};
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Our various file operations.
+ */
+static int mcam_v4l_open(struct file *filp)
+{
+       struct mcam_camera *cam = video_drvdata(filp);
+       int ret = 0;
+
+       filp->private_data = cam;
+
+       frames = singles = delivered = 0;
+       mutex_lock(&cam->s_mutex);
+       if (cam->users == 0) {
+               ret = mcam_setup_vb2(cam);
+               if (ret)
+                       goto out;
+               mcam_ctlr_power_up(cam);
+               __mcam_cam_reset(cam);
+               mcam_set_config_needed(cam, 1);
+       }
+       (cam->users)++;
+out:
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+static int mcam_v4l_release(struct file *filp)
+{
+       struct mcam_camera *cam = filp->private_data;
+
+       cam_err(cam, "Release, %d frames, %d singles, %d delivered\n", frames,
+                       singles, delivered);
+       mutex_lock(&cam->s_mutex);
+       (cam->users)--;
+       if (filp == cam->owner) {
+               mcam_ctlr_stop_dma(cam);
+               cam->owner = NULL;
+       }
+       if (cam->users == 0) {
+               mcam_cleanup_vb2(cam);
+               mcam_ctlr_power_down(cam);
+               if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read)
+                       mcam_free_dma_bufs(cam);
+       }
+       mutex_unlock(&cam->s_mutex);
+       return 0;
+}
+
+static ssize_t mcam_v4l_read(struct file *filp,
+               char __user *buffer, size_t len, loff_t *pos)
+{
+       struct mcam_camera *cam = filp->private_data;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = vb2_read(&cam->vb_queue, buffer, len, pos,
+                       filp->f_flags & O_NONBLOCK);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+
+static unsigned int mcam_v4l_poll(struct file *filp,
+               struct poll_table_struct *pt)
+{
+       struct mcam_camera *cam = filp->private_data;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = vb2_poll(&cam->vb_queue, filp, pt);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+static int mcam_v4l_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       struct mcam_camera *cam = filp->private_data;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = vb2_mmap(&cam->vb_queue, vma);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+
+static const struct v4l2_file_operations mcam_v4l_fops = {
+       .owner = THIS_MODULE,
+       .open = mcam_v4l_open,
+       .release = mcam_v4l_release,
+       .read = mcam_v4l_read,
+       .poll = mcam_v4l_poll,
+       .mmap = mcam_v4l_mmap,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+
+/*
+ * This template device holds all of those v4l2 methods; we
+ * clone it for specific real devices.
+ */
+static struct video_device mcam_v4l_template = {
+       .name = "mcam",
+       .tvnorms = V4L2_STD_NTSC_M,
+       .current_norm = V4L2_STD_NTSC_M,  /* make mplayer happy */
+
+       .fops = &mcam_v4l_fops,
+       .ioctl_ops = &mcam_v4l_ioctl_ops,
+       .release = video_device_release_empty,
+};
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Interrupt handler stuff
+ */
+static void mcam_frame_complete(struct mcam_camera *cam, int frame)
+{
+       /*
+        * Basic frame housekeeping.
+        */
+       set_bit(frame, &cam->flags);
+       clear_bit(CF_DMA_ACTIVE, &cam->flags);
+       cam->next_buf = frame;
+       cam->buf_seq[frame] = ++(cam->sequence);
+       frames++;
+       /*
+        * "This should never happen"
+        */
+       if (cam->state != S_STREAMING)
+               return;
+       /*
+        * Process the frame and set up the next one.
+        */
+       cam->frame_complete(cam, frame);
+}
+
+
+/*
+ * The interrupt handler; this needs to be called from the
+ * platform irq handler with the lock held.
+ */
+int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
+{
+       unsigned int frame, handled = 0;
+
+       mcam_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); /* Clear'em all */
+       /*
+        * Handle any frame completions.  There really should
+        * not be more than one of these, or we have fallen
+        * far behind.
+        *
+        * When running in S/G mode, the frame number lacks any
+        * real meaning - there's only one descriptor array - but
+        * the controller still picks a different one to signal
+        * each time.
+        */
+       for (frame = 0; frame < cam->nbufs; frame++)
+               if (irqs & (IRQ_EOF0 << frame)) {
+                       mcam_frame_complete(cam, frame);
+                       handled = 1;
+               }
+       /*
+        * If a frame starts, note that we have DMA active.  This
+        * code assumes that we won't get multiple frame interrupts
+        * at once; may want to rethink that.
+        */
+       if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) {
+               set_bit(CF_DMA_ACTIVE, &cam->flags);
+               handled = 1;
+               if (cam->buffer_mode == B_DMA_sg)
+                       mcam_ctlr_stop(cam);
+       }
+       return handled;
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Registration and such.
+ */
+static struct ov7670_config sensor_cfg = {
+       /*
+        * Exclude QCIF mode, because it only captures a tiny portion
+        * of the sensor FOV
+        */
+       .min_width = 320,
+       .min_height = 240,
+};
+
+
+int mccic_register(struct mcam_camera *cam)
+{
+       struct i2c_board_info ov7670_info = {
+               .type = "ov7670",
+               .addr = 0x42 >> 1,
+               .platform_data = &sensor_cfg,
+       };
+       int ret;
+
+       /*
+        * Validate the requested buffer mode.
+        */
+       if (buffer_mode >= 0)
+               cam->buffer_mode = buffer_mode;
+       if (cam->buffer_mode == B_DMA_sg &&
+                       cam->chip_id == V4L2_IDENT_CAFE) {
+               printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O, "
+                       "attempting vmalloc mode instead\n");
+               cam->buffer_mode = B_vmalloc;
+       }
+       if (!mcam_buffer_mode_supported(cam->buffer_mode)) {
+               printk(KERN_ERR "marvell-cam: buffer mode %d unsupported\n",
+                               cam->buffer_mode);
+               return -EINVAL;
+       }
+       /*
+        * Register with V4L
+        */
+       ret = v4l2_device_register(cam->dev, &cam->v4l2_dev);
+       if (ret)
+               return ret;
+
+       mutex_init(&cam->s_mutex);
+       cam->state = S_NOTREADY;
+       mcam_set_config_needed(cam, 1);
+       cam->pix_format = mcam_def_pix_format;
+       cam->mbus_code = mcam_def_mbus_code;
+       INIT_LIST_HEAD(&cam->buffers);
+       mcam_ctlr_init(cam);
+
+       /*
+        * Try to find the sensor.
+        */
+       sensor_cfg.clock_speed = cam->clock_speed;
+       sensor_cfg.use_smbus = cam->use_smbus;
+       cam->sensor_addr = ov7670_info.addr;
+       cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev,
+                       cam->i2c_adapter, &ov7670_info, NULL);
+       if (cam->sensor == NULL) {
+               ret = -ENODEV;
+               goto out_unregister;
+       }
+
+       ret = mcam_cam_init(cam);
+       if (ret)
+               goto out_unregister;
+       /*
+        * Get the v4l2 setup done.
+        */
+       mutex_lock(&cam->s_mutex);
+       cam->vdev = mcam_v4l_template;
+       cam->vdev.debug = 0;
+       cam->vdev.v4l2_dev = &cam->v4l2_dev;
+       ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
+       if (ret)
+               goto out;
+       video_set_drvdata(&cam->vdev, cam);
+
+       /*
+        * If so requested, try to get our DMA buffers now.
+        */
+       if (cam->buffer_mode == B_vmalloc && !alloc_bufs_at_read) {
+               if (mcam_alloc_dma_bufs(cam, 1))
+                       cam_warn(cam, "Unable to alloc DMA buffers at load"
+                                       " will try again later.");
+       }
+
+out:
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+out_unregister:
+       v4l2_device_unregister(&cam->v4l2_dev);
+       return ret;
+}
+
+
+void mccic_shutdown(struct mcam_camera *cam)
+{
+       /*
+        * If we have no users (and we really, really should have no
+        * users) the device will already be powered down.  Trying to
+        * take it down again will wedge the machine, which is frowned
+        * upon.
+        */
+       if (cam->users > 0) {
+               cam_warn(cam, "Removing a device with users!\n");
+               mcam_ctlr_power_down(cam);
+       }
+       vb2_queue_release(&cam->vb_queue);
+       if (cam->buffer_mode == B_vmalloc)
+               mcam_free_dma_bufs(cam);
+       video_unregister_device(&cam->vdev);
+       v4l2_device_unregister(&cam->v4l2_dev);
+}
+
+/*
+ * Power management
+ */
+#ifdef CONFIG_PM
+
+void mccic_suspend(struct mcam_camera *cam)
+{
+       enum mcam_state cstate = cam->state;
+
+       mcam_ctlr_stop_dma(cam);
+       mcam_ctlr_power_down(cam);
+       cam->state = cstate;
+}
+
+int mccic_resume(struct mcam_camera *cam)
+{
+       int ret = 0;
+
+       mutex_lock(&cam->s_mutex);
+       if (cam->users > 0) {
+               mcam_ctlr_power_up(cam);
+               __mcam_cam_reset(cam);
+       } else {
+               mcam_ctlr_power_down(cam);
+       }
+       mutex_unlock(&cam->s_mutex);
+
+       set_bit(CF_CONFIG_NEEDED, &cam->flags);
+       if (cam->state == S_STREAMING)
+               ret = mcam_read_setup(cam);
+       return ret;
+}
+#endif /* CONFIG_PM */
diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h
new file mode 100644 (file)
index 0000000..917200e
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Marvell camera core structures.
+ *
+ * Copyright 2011 Jonathan Corbet corbet@lwn.net
+ */
+#ifndef _MCAM_CORE_H
+#define _MCAM_CORE_H
+
+#include <linux/list.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-dev.h>
+#include <media/videobuf2-core.h>
+
+/*
+ * Create our own symbols for the supported buffer modes, but, for now,
+ * base them entirely on which videobuf2 options have been selected.
+ */
+#if defined(CONFIG_VIDEOBUF2_VMALLOC) || defined(CONFIG_VIDEOBUF2_VMALLOC_MODULE)
+#define MCAM_MODE_VMALLOC 1
+#endif
+
+#if defined(CONFIG_VIDEOBUF2_DMA_CONTIG) || defined(CONFIG_VIDEOBUF2_DMA_CONTIG_MODULE)
+#define MCAM_MODE_DMA_CONTIG 1
+#endif
+
+#if defined(CONFIG_VIDEOBUF2_DMA_SG) || defined(CONFIG_VIDEOBUF2_DMA_SG_MODULE)
+#define MCAM_MODE_DMA_SG 1
+#endif
+
+#if !defined(MCAM_MODE_VMALLOC) && !defined(MCAM_MODE_DMA_CONTIG) && \
+       !defined(MCAM_MODE_DMA_SG)
+#error One of the videobuf buffer modes must be selected in the config
+#endif
+
+
+enum mcam_state {
+       S_NOTREADY,     /* Not yet initialized */
+       S_IDLE,         /* Just hanging around */
+       S_FLAKED,       /* Some sort of problem */
+       S_STREAMING,    /* Streaming data */
+       S_BUFWAIT       /* streaming requested but no buffers yet */
+};
+#define MAX_DMA_BUFS 3
+
+/*
+ * Different platforms work best with different buffer modes, so we
+ * let the platform pick.
+ */
+enum mcam_buffer_mode {
+       B_vmalloc = 0,
+       B_DMA_contig = 1,
+       B_DMA_sg = 2
+};
+
+/*
+ * Is a given buffer mode supported by the current kernel configuration?
+ */
+static inline int mcam_buffer_mode_supported(enum mcam_buffer_mode mode)
+{
+       switch (mode) {
+#ifdef MCAM_MODE_VMALLOC
+       case B_vmalloc:
+#endif
+#ifdef MCAM_MODE_DMA_CONTIG
+       case B_DMA_contig:
+#endif
+#ifdef MCAM_MODE_DMA_SG
+       case B_DMA_sg:
+#endif
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+
+/*
+ * A description of one of our devices.
+ * Locking: controlled by s_mutex.  Certain fields, however, require
+ *          the dev_lock spinlock; they are marked as such by comments.
+ *          dev_lock is also required for access to device registers.
+ */
+struct mcam_camera {
+       /*
+        * These fields should be set by the platform code prior to
+        * calling mcam_register().
+        */
+       struct i2c_adapter *i2c_adapter;
+       unsigned char __iomem *regs;
+       spinlock_t dev_lock;
+       struct device *dev; /* For messages, dma alloc */
+       unsigned int chip_id;
+       short int clock_speed;  /* Sensor clock speed, default 30 */
+       short int use_smbus;    /* SMBUS or straight I2c? */
+       enum mcam_buffer_mode buffer_mode;
+       /*
+        * Callbacks from the core to the platform code.
+        */
+       void (*plat_power_up) (struct mcam_camera *cam);
+       void (*plat_power_down) (struct mcam_camera *cam);
+
+       /*
+        * Everything below here is private to the mcam core and
+        * should not be touched by the platform code.
+        */
+       struct v4l2_device v4l2_dev;
+       enum mcam_state state;
+       unsigned long flags;            /* Buffer status, mainly (dev_lock) */
+       int users;                      /* How many open FDs */
+       struct file *owner;             /* Who has data access (v4l2) */
+
+       /*
+        * Subsystem structures.
+        */
+       struct video_device vdev;
+       struct v4l2_subdev *sensor;
+       unsigned short sensor_addr;
+
+       /* Videobuf2 stuff */
+       struct vb2_queue vb_queue;
+       struct list_head buffers;       /* Available frames */
+
+       unsigned int nbufs;             /* How many are alloc'd */
+       int next_buf;                   /* Next to consume (dev_lock) */
+
+       /* DMA buffers - vmalloc mode */
+#ifdef MCAM_MODE_VMALLOC
+       unsigned int dma_buf_size;      /* allocated size */
+       void *dma_bufs[MAX_DMA_BUFS];   /* Internal buffer addresses */
+       dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */
+       struct tasklet_struct s_tasklet;
+#endif
+       unsigned int sequence;          /* Frame sequence number */
+       unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */
+
+       /* DMA buffers - DMA modes */
+       struct mcam_vb_buffer *vb_bufs[MAX_DMA_BUFS];
+       struct vb2_alloc_ctx *vb_alloc_ctx;
+
+       /* Mode-specific ops, set at open time */
+       void (*dma_setup)(struct mcam_camera *cam);
+       void (*frame_complete)(struct mcam_camera *cam, int frame);
+
+       /* Current operating parameters */
+       u32 sensor_type;                /* Currently ov7670 only */
+       struct v4l2_pix_format pix_format;
+       enum v4l2_mbus_pixelcode mbus_code;
+
+       /* Locks */
+       struct mutex s_mutex; /* Access to this structure */
+};
+
+
+/*
+ * Register I/O functions.  These are here because the platform code
+ * may legitimately need to mess with the register space.
+ */
+/*
+ * Device register I/O
+ */
+static inline void mcam_reg_write(struct mcam_camera *cam, unsigned int reg,
+               unsigned int val)
+{
+       iowrite32(val, cam->regs + reg);
+}
+
+static inline unsigned int mcam_reg_read(struct mcam_camera *cam,
+               unsigned int reg)
+{
+       return ioread32(cam->regs + reg);
+}
+
+
+static inline void mcam_reg_write_mask(struct mcam_camera *cam, unsigned int reg,
+               unsigned int val, unsigned int mask)
+{
+       unsigned int v = mcam_reg_read(cam, reg);
+
+       v = (v & ~mask) | (val & mask);
+       mcam_reg_write(cam, reg, v);
+}
+
+static inline void mcam_reg_clear_bit(struct mcam_camera *cam,
+               unsigned int reg, unsigned int val)
+{
+       mcam_reg_write_mask(cam, reg, 0, val);
+}
+
+static inline void mcam_reg_set_bit(struct mcam_camera *cam,
+               unsigned int reg, unsigned int val)
+{
+       mcam_reg_write_mask(cam, reg, val, val);
+}
+
+/*
+ * Functions for use by platform code.
+ */
+int mccic_register(struct mcam_camera *cam);
+int mccic_irq(struct mcam_camera *cam, unsigned int irqs);
+void mccic_shutdown(struct mcam_camera *cam);
+#ifdef CONFIG_PM
+void mccic_suspend(struct mcam_camera *cam);
+int mccic_resume(struct mcam_camera *cam);
+#endif
+
+/*
+ * Register definitions for the m88alp01 camera interface.  Offsets in bytes
+ * as given in the spec.
+ */
+#define REG_Y0BAR      0x00
+#define REG_Y1BAR      0x04
+#define REG_Y2BAR      0x08
+/* ... */
+
+#define REG_IMGPITCH   0x24    /* Image pitch register */
+#define   IMGP_YP_SHFT   2             /* Y pitch params */
+#define   IMGP_YP_MASK   0x00003ffc    /* Y pitch field */
+#define          IMGP_UVP_SHFT   18            /* UV pitch (planar) */
+#define   IMGP_UVP_MASK   0x3ffc0000
+#define REG_IRQSTATRAW 0x28    /* RAW IRQ Status */
+#define   IRQ_EOF0       0x00000001    /* End of frame 0 */
+#define   IRQ_EOF1       0x00000002    /* End of frame 1 */
+#define   IRQ_EOF2       0x00000004    /* End of frame 2 */
+#define   IRQ_SOF0       0x00000008    /* Start of frame 0 */
+#define   IRQ_SOF1       0x00000010    /* Start of frame 1 */
+#define   IRQ_SOF2       0x00000020    /* Start of frame 2 */
+#define   IRQ_OVERFLOW   0x00000040    /* FIFO overflow */
+#define   IRQ_TWSIW      0x00010000    /* TWSI (smbus) write */
+#define   IRQ_TWSIR      0x00020000    /* TWSI read */
+#define   IRQ_TWSIE      0x00040000    /* TWSI error */
+#define   TWSIIRQS (IRQ_TWSIW|IRQ_TWSIR|IRQ_TWSIE)
+#define   FRAMEIRQS (IRQ_EOF0|IRQ_EOF1|IRQ_EOF2|IRQ_SOF0|IRQ_SOF1|IRQ_SOF2)
+#define   ALLIRQS (TWSIIRQS|FRAMEIRQS|IRQ_OVERFLOW)
+#define REG_IRQMASK    0x2c    /* IRQ mask - same bits as IRQSTAT */
+#define REG_IRQSTAT    0x30    /* IRQ status / clear */
+
+#define REG_IMGSIZE    0x34    /* Image size */
+#define  IMGSZ_V_MASK    0x1fff0000
+#define  IMGSZ_V_SHIFT   16
+#define         IMGSZ_H_MASK     0x00003fff
+#define REG_IMGOFFSET  0x38    /* IMage offset */
+
+#define REG_CTRL0      0x3c    /* Control 0 */
+#define   C0_ENABLE      0x00000001    /* Makes the whole thing go */
+
+/* Mask for all the format bits */
+#define   C0_DF_MASK     0x00fffffc    /* Bits 2-23 */
+
+/* RGB ordering */
+#define          C0_RGB4_RGBX    0x00000000
+#define          C0_RGB4_XRGB    0x00000004
+#define          C0_RGB4_BGRX    0x00000008
+#define          C0_RGB4_XBGR    0x0000000c
+#define          C0_RGB5_RGGB    0x00000000
+#define          C0_RGB5_GRBG    0x00000004
+#define          C0_RGB5_GBRG    0x00000008
+#define          C0_RGB5_BGGR    0x0000000c
+
+/* Spec has two fields for DIN and DOUT, but they must match, so
+   combine them here. */
+#define          C0_DF_YUV       0x00000000    /* Data is YUV      */
+#define          C0_DF_RGB       0x000000a0    /* ... RGB                  */
+#define          C0_DF_BAYER     0x00000140    /* ... Bayer                */
+/* 8-8-8 must be missing from the below - ask */
+#define          C0_RGBF_565     0x00000000
+#define          C0_RGBF_444     0x00000800
+#define          C0_RGB_BGR      0x00001000    /* Blue comes first */
+#define          C0_YUV_PLANAR   0x00000000    /* YUV 422 planar format */
+#define          C0_YUV_PACKED   0x00008000    /* YUV 422 packed       */
+#define          C0_YUV_420PL    0x0000a000    /* YUV 420 planar       */
+/* Think that 420 packed must be 111 - ask */
+#define          C0_YUVE_YUYV    0x00000000    /* Y1CbY0Cr             */
+#define          C0_YUVE_YVYU    0x00010000    /* Y1CrY0Cb             */
+#define          C0_YUVE_VYUY    0x00020000    /* CrY1CbY0             */
+#define          C0_YUVE_UYVY    0x00030000    /* CbY1CrY0             */
+#define          C0_YUVE_XYUV    0x00000000    /* 420: .YUV            */
+#define          C0_YUVE_XYVU    0x00010000    /* 420: .YVU            */
+#define          C0_YUVE_XUVY    0x00020000    /* 420: .UVY            */
+#define          C0_YUVE_XVUY    0x00030000    /* 420: .VUY            */
+/* Bayer bits 18,19 if needed */
+#define          C0_HPOL_LOW     0x01000000    /* HSYNC polarity active low */
+#define          C0_VPOL_LOW     0x02000000    /* VSYNC polarity active low */
+#define          C0_VCLK_LOW     0x04000000    /* VCLK on falling edge */
+#define          C0_DOWNSCALE    0x08000000    /* Enable downscaler */
+#define          C0_SIFM_MASK    0xc0000000    /* SIF mode bits */
+#define          C0_SIF_HVSYNC   0x00000000    /* Use H/VSYNC */
+#define          CO_SOF_NOSYNC   0x40000000    /* Use inband active signaling */
+
+/* Bits below C1_444ALPHA are not present in Cafe */
+#define REG_CTRL1      0x40    /* Control 1 */
+#define          C1_CLKGATE      0x00000001    /* Sensor clock gate */
+#define   C1_DESC_ENA    0x00000100    /* DMA descriptor enable */
+#define   C1_DESC_3WORD   0x00000200   /* Three-word descriptors used */
+#define          C1_444ALPHA     0x00f00000    /* Alpha field in RGB444 */
+#define          C1_ALPHA_SHFT   20
+#define          C1_DMAB32       0x00000000    /* 32-byte DMA burst */
+#define          C1_DMAB16       0x02000000    /* 16-byte DMA burst */
+#define          C1_DMAB64       0x04000000    /* 64-byte DMA burst */
+#define          C1_DMAB_MASK    0x06000000
+#define          C1_TWOBUFS      0x08000000    /* Use only two DMA buffers */
+#define          C1_PWRDWN       0x10000000    /* Power down */
+
+#define REG_CLKCTRL    0x88    /* Clock control */
+#define          CLK_DIV_MASK    0x0000ffff    /* Upper bits RW "reserved" */
+
+/* This appears to be a Cafe-only register */
+#define REG_UBAR       0xc4    /* Upper base address register */
+
+/* Armada 610 DMA descriptor registers */
+#define        REG_DMA_DESC_Y  0x200
+#define        REG_DMA_DESC_U  0x204
+#define        REG_DMA_DESC_V  0x208
+#define REG_DESC_LEN_Y 0x20c   /* Lengths are in bytes */
+#define        REG_DESC_LEN_U  0x210
+#define REG_DESC_LEN_V 0x214
+
+/*
+ * Useful stuff that probably belongs somewhere global.
+ */
+#define VGA_WIDTH      640
+#define VGA_HEIGHT     480
+
+#endif /* _MCAM_CORE_H */
diff --git a/drivers/media/video/marvell-ccic/mmp-driver.c b/drivers/media/video/marvell-ccic/mmp-driver.c
new file mode 100644 (file)
index 0000000..d6b7645
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * Support for the camera device found on Marvell MMP processors; known
+ * to work with the Armada 610 as used in the OLPC 1.75 system.
+ *
+ * Copyright 2011 Jonathan Corbet <corbet@lwn.net>
+ *
+ * This file may be distributed under the terms of the GNU General
+ * Public License, version 2.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/mmp-camera.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+
+#include "mcam-core.h"
+
+MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
+MODULE_LICENSE("GPL");
+
+struct mmp_camera {
+       void *power_regs;
+       struct platform_device *pdev;
+       struct mcam_camera mcam;
+       struct list_head devlist;
+       int irq;
+};
+
+static inline struct mmp_camera *mcam_to_cam(struct mcam_camera *mcam)
+{
+       return container_of(mcam, struct mmp_camera, mcam);
+}
+
+/*
+ * A silly little infrastructure so we can keep track of our devices.
+ * Chances are that we will never have more than one of them, but
+ * the Armada 610 *does* have two controllers...
+ */
+
+static LIST_HEAD(mmpcam_devices);
+static struct mutex mmpcam_devices_lock;
+
+static void mmpcam_add_device(struct mmp_camera *cam)
+{
+       mutex_lock(&mmpcam_devices_lock);
+       list_add(&cam->devlist, &mmpcam_devices);
+       mutex_unlock(&mmpcam_devices_lock);
+}
+
+static void mmpcam_remove_device(struct mmp_camera *cam)
+{
+       mutex_lock(&mmpcam_devices_lock);
+       list_del(&cam->devlist);
+       mutex_unlock(&mmpcam_devices_lock);
+}
+
+/*
+ * Platform dev remove passes us a platform_device, and there's
+ * no handy unused drvdata to stash a backpointer in.  So just
+ * dig it out of our list.
+ */
+static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev)
+{
+       struct mmp_camera *cam;
+
+       mutex_lock(&mmpcam_devices_lock);
+       list_for_each_entry(cam, &mmpcam_devices, devlist) {
+               if (cam->pdev == pdev) {
+                       mutex_unlock(&mmpcam_devices_lock);
+                       return cam;
+               }
+       }
+       mutex_unlock(&mmpcam_devices_lock);
+       return NULL;
+}
+
+
+
+
+/*
+ * Power-related registers; this almost certainly belongs
+ * somewhere else.
+ *
+ * ARMADA 610 register manual, sec 7.2.1, p1842.
+ */
+#define CPU_SUBSYS_PMU_BASE    0xd4282800
+#define REG_CCIC_DCGCR         0x28    /* CCIC dyn clock gate ctrl reg */
+#define REG_CCIC_CRCR          0x50    /* CCIC clk reset ctrl reg      */
+
+/*
+ * Power control.
+ */
+static void mmpcam_power_up(struct mcam_camera *mcam)
+{
+       struct mmp_camera *cam = mcam_to_cam(mcam);
+       struct mmp_camera_platform_data *pdata;
+/*
+ * Turn on power and clocks to the controller.
+ */
+       iowrite32(0x3f, cam->power_regs + REG_CCIC_DCGCR);
+       iowrite32(0x3805b, cam->power_regs + REG_CCIC_CRCR);
+       mdelay(1);
+/*
+ * Provide power to the sensor.
+ */
+       mcam_reg_write(mcam, REG_CLKCTRL, 0x60000002);
+       pdata = cam->pdev->dev.platform_data;
+       gpio_set_value(pdata->sensor_power_gpio, 1);
+       mdelay(5);
+       mcam_reg_clear_bit(mcam, REG_CTRL1, 0x10000000);
+       gpio_set_value(pdata->sensor_reset_gpio, 0); /* reset is active low */
+       mdelay(5);
+       gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */
+       mdelay(5);
+}
+
+static void mmpcam_power_down(struct mcam_camera *mcam)
+{
+       struct mmp_camera *cam = mcam_to_cam(mcam);
+       struct mmp_camera_platform_data *pdata;
+/*
+ * Turn off clocks and set reset lines
+ */
+       iowrite32(0, cam->power_regs + REG_CCIC_DCGCR);
+       iowrite32(0, cam->power_regs + REG_CCIC_CRCR);
+/*
+ * Shut down the sensor.
+ */
+       pdata = cam->pdev->dev.platform_data;
+       gpio_set_value(pdata->sensor_power_gpio, 0);
+       gpio_set_value(pdata->sensor_reset_gpio, 0);
+}
+
+
+static irqreturn_t mmpcam_irq(int irq, void *data)
+{
+       struct mcam_camera *mcam = data;
+       unsigned int irqs, handled;
+
+       spin_lock(&mcam->dev_lock);
+       irqs = mcam_reg_read(mcam, REG_IRQSTAT);
+       handled = mccic_irq(mcam, irqs);
+       spin_unlock(&mcam->dev_lock);
+       return IRQ_RETVAL(handled);
+}
+
+
+static int mmpcam_probe(struct platform_device *pdev)
+{
+       struct mmp_camera *cam;
+       struct mcam_camera *mcam;
+       struct resource *res;
+       struct mmp_camera_platform_data *pdata;
+       int ret;
+
+       cam = kzalloc(sizeof(*cam), GFP_KERNEL);
+       if (cam == NULL)
+               return -ENOMEM;
+       cam->pdev = pdev;
+       INIT_LIST_HEAD(&cam->devlist);
+
+       mcam = &cam->mcam;
+       mcam->platform = MHP_Armada610;
+       mcam->plat_power_up = mmpcam_power_up;
+       mcam->plat_power_down = mmpcam_power_down;
+       mcam->dev = &pdev->dev;
+       mcam->use_smbus = 0;
+       mcam->chip_id = V4L2_IDENT_ARMADA610;
+       mcam->buffer_mode = B_DMA_sg;
+       spin_lock_init(&mcam->dev_lock);
+       /*
+        * Get our I/O memory.
+        */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no iomem resource!\n");
+               ret = -ENODEV;
+               goto out_free;
+       }
+       mcam->regs = ioremap(res->start, resource_size(res));
+       if (mcam->regs == NULL) {
+               dev_err(&pdev->dev, "MMIO ioremap fail\n");
+               ret = -ENODEV;
+               goto out_free;
+       }
+       /*
+        * Power/clock memory is elsewhere; get it too.  Perhaps this
+        * should really be managed outside of this driver?
+        */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no power resource!\n");
+               ret = -ENODEV;
+               goto out_unmap1;
+       }
+       cam->power_regs = ioremap(res->start, resource_size(res));
+       if (cam->power_regs == NULL) {
+               dev_err(&pdev->dev, "power MMIO ioremap fail\n");
+               ret = -ENODEV;
+               goto out_unmap1;
+       }
+       /*
+        * Find the i2c adapter.  This assumes, of course, that the
+        * i2c bus is already up and functioning.
+        */
+       pdata = pdev->dev.platform_data;
+       mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device);
+       if (mcam->i2c_adapter == NULL) {
+               ret = -ENODEV;
+               dev_err(&pdev->dev, "No i2c adapter\n");
+               goto out_unmap2;
+       }
+       /*
+        * Sensor GPIO pins.
+        */
+       ret = gpio_request(pdata->sensor_power_gpio, "cam-power");
+       if (ret) {
+               dev_err(&pdev->dev, "Can't get sensor power gpio %d",
+                               pdata->sensor_power_gpio);
+               goto out_unmap2;
+       }
+       gpio_direction_output(pdata->sensor_power_gpio, 0);
+       ret = gpio_request(pdata->sensor_reset_gpio, "cam-reset");
+       if (ret) {
+               dev_err(&pdev->dev, "Can't get sensor reset gpio %d",
+                               pdata->sensor_reset_gpio);
+               goto out_gpio;
+       }
+       gpio_direction_output(pdata->sensor_reset_gpio, 0);
+       /*
+        * Power the device up and hand it off to the core.
+        */
+       mmpcam_power_up(mcam);
+       ret = mccic_register(mcam);
+       if (ret)
+               goto out_gpio2;
+       /*
+        * Finally, set up our IRQ now that the core is ready to
+        * deal with it.
+        */
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (res == NULL) {
+               ret = -ENODEV;
+               goto out_unregister;
+       }
+       cam->irq = res->start;
+       ret = request_irq(cam->irq, mmpcam_irq, IRQF_SHARED,
+                       "mmp-camera", mcam);
+       if (ret == 0) {
+               mmpcam_add_device(cam);
+               return 0;
+       }
+
+out_unregister:
+       mccic_shutdown(mcam);
+out_gpio2:
+       mmpcam_power_down(mcam);
+       gpio_free(pdata->sensor_reset_gpio);
+out_gpio:
+       gpio_free(pdata->sensor_power_gpio);
+out_unmap2:
+       iounmap(cam->power_regs);
+out_unmap1:
+       iounmap(mcam->regs);
+out_free:
+       kfree(cam);
+       return ret;
+}
+
+
+static int mmpcam_remove(struct mmp_camera *cam)
+{
+       struct mcam_camera *mcam = &cam->mcam;
+       struct mmp_camera_platform_data *pdata;
+
+       mmpcam_remove_device(cam);
+       free_irq(cam->irq, mcam);
+       mccic_shutdown(mcam);
+       mmpcam_power_down(mcam);
+       pdata = cam->pdev->dev.platform_data;
+       gpio_free(pdata->sensor_reset_gpio);
+       gpio_free(pdata->sensor_power_gpio);
+       iounmap(cam->power_regs);
+       iounmap(mcam->regs);
+       kfree(cam);
+       return 0;
+}
+
+static int mmpcam_platform_remove(struct platform_device *pdev)
+{
+       struct mmp_camera *cam = mmpcam_find_device(pdev);
+
+       if (cam == NULL)
+               return -ENODEV;
+       return mmpcam_remove(cam);
+}
+
+
+static struct platform_driver mmpcam_driver = {
+       .probe          = mmpcam_probe,
+       .remove         = mmpcam_platform_remove,
+       .driver = {
+               .name   = "mmp-camera",
+               .owner  = THIS_MODULE
+       }
+};
+
+
+static int __init mmpcam_init_module(void)
+{
+       mutex_init(&mmpcam_devices_lock);
+       return platform_driver_register(&mmpcam_driver);
+}
+
+static void __exit mmpcam_exit_module(void)
+{
+       platform_driver_unregister(&mmpcam_driver);
+       /*
+        * platform_driver_unregister() should have emptied the list
+        */
+       if (!list_empty(&mmpcam_devices))
+               printk(KERN_ERR "mmp_camera leaving devices behind\n");
+}
+
+module_init(mmpcam_init_module);
+module_exit(mmpcam_exit_module);
index b03d74e..166bf93 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
-#include <linux/version.h>
 #include <linux/timer.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -35,7 +34,7 @@
 MODULE_DESCRIPTION("Virtual device for mem2mem framework testing");
 MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
 MODULE_LICENSE("GPL");
-
+MODULE_VERSION("0.1.1");
 
 #define MIN_W 32
 #define MIN_H 32
@@ -380,7 +379,6 @@ static int vidioc_querycap(struct file *file, void *priv,
        strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
        strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
        cap->bus_info[0] = 0;
-       cap->version = KERNEL_VERSION(0, 1, 0);
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
                          | V4L2_CAP_STREAMING;
 
index e2bbd8c..4da9cca 100644 (file)
@@ -603,13 +603,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd,
        unsigned long flags;
        int ret;
 
-       /*
-        * We must have a parent by now. And it cannot be a wrong one.
-        * So this entire test is completely redundant.
-        */
-       if (!icd->dev.parent ||
-           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
-               return -ENODEV;
+       /* We must have a parent by now. And it cannot be a wrong one. */
+       BUG_ON(!icd->parent ||
+              to_soc_camera_host(icd->parent)->nr != icd->iface);
 
        /* Enable the chip */
        data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
@@ -675,8 +671,8 @@ static void mt9m001_video_remove(struct soc_camera_device *icd)
 {
        struct soc_camera_link *icl = to_soc_camera_link(icd);
 
-       dev_dbg(&icd->dev, "Video removed: %p, %p\n",
-               icd->dev.parent, icd->vdev);
+       dev_dbg(icd->pdev, "Video removed: %p, %p\n",
+               icd->parent, icd->vdev);
        if (icl->free_bus)
                icl->free_bus(icl);
 }
index ebebed9..a357aa8 100644 (file)
 #define MT9M111_RESET_RESTART_FRAME    (1 << 1)
 #define MT9M111_RESET_RESET_MODE       (1 << 0)
 
+#define MT9M111_RM_FULL_POWER_RD       (0 << 10)
+#define MT9M111_RM_LOW_POWER_RD                (1 << 10)
+#define MT9M111_RM_COL_SKIP_4X         (1 << 5)
+#define MT9M111_RM_ROW_SKIP_4X         (1 << 4)
+#define MT9M111_RM_COL_SKIP_2X         (1 << 3)
+#define MT9M111_RM_ROW_SKIP_2X         (1 << 2)
 #define MT9M111_RMB_MIRROR_COLS                (1 << 1)
 #define MT9M111_RMB_MIRROR_ROWS                (1 << 0)
 #define MT9M111_CTXT_CTRL_RESTART      (1 << 15)
 
 #define MT9M111_OPMODE_AUTOEXPO_EN     (1 << 14)
 #define MT9M111_OPMODE_AUTOWHITEBAL_EN (1 << 1)
-
+#define MT9M111_OUTFMT_FLIP_BAYER_COL  (1 << 9)
+#define MT9M111_OUTFMT_FLIP_BAYER_ROW  (1 << 8)
 #define MT9M111_OUTFMT_PROCESSED_BAYER (1 << 14)
 #define MT9M111_OUTFMT_BYPASS_IFP      (1 << 10)
 #define MT9M111_OUTFMT_INV_PIX_CLOCK   (1 << 9)
 #define MT9M111_OUTFMT_TST_RAMP_FRAME  (3 << 4)
 #define MT9M111_OUTFMT_SHIFT_3_UP      (1 << 3)
 #define MT9M111_OUTFMT_AVG_CHROMA      (1 << 2)
-#define MT9M111_OUTFMT_SWAP_YCbCr_C_Y  (1 << 1)
-#define MT9M111_OUTFMT_SWAP_RGB_EVEN   (1 << 1)
-#define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr        (1 << 0)
+#define MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN (1 << 1)
+#define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B        (1 << 0)
 
 /*
  * Camera control register addresses (0x200..0x2ff not implemented)
 #define reg_write(reg, val) mt9m111_reg_write(client, MT9M111_##reg, (val))
 #define reg_set(reg, val) mt9m111_reg_set(client, MT9M111_##reg, (val))
 #define reg_clear(reg, val) mt9m111_reg_clear(client, MT9M111_##reg, (val))
+#define reg_mask(reg, val, mask) mt9m111_reg_mask(client, MT9M111_##reg, \
+               (val), (mask))
 
 #define MT9M111_MIN_DARK_ROWS  8
 #define MT9M111_MIN_DARK_COLS  26
@@ -153,7 +161,11 @@ static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {
        {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
        {V4L2_MBUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG},
        {V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
+       {V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
        {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
+       {V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
+       {V4L2_MBUS_FMT_BGR565_2X8_LE, V4L2_COLORSPACE_SRGB},
+       {V4L2_MBUS_FMT_BGR565_2X8_BE, V4L2_COLORSPACE_SRGB},
        {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
        {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
 };
@@ -169,6 +181,8 @@ struct mt9m111 {
                         * from v4l2-chip-ident.h */
        enum mt9m111_context context;
        struct v4l2_rect rect;
+       struct mutex power_lock; /* lock to protect power_count */
+       int power_count;
        const struct mt9m111_datafmt *fmt;
        unsigned int gain;
        unsigned char autoexposure;
@@ -176,10 +190,6 @@ struct mt9m111 {
        unsigned int powered:1;
        unsigned int hflip:1;
        unsigned int vflip:1;
-       unsigned int swap_rgb_even_odd:1;
-       unsigned int swap_rgb_red_blue:1;
-       unsigned int swap_yuv_y_chromas:1;
-       unsigned int swap_yuv_cb_cr:1;
        unsigned int autowhitebalance:1;
 };
 
@@ -248,12 +258,26 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,
        int ret;
 
        ret = mt9m111_reg_read(client, reg);
-       return mt9m111_reg_write(client, reg, ret & ~data);
+       if (ret >= 0)
+               ret = mt9m111_reg_write(client, reg, ret & ~data);
+       return ret;
 }
 
-static int mt9m111_set_context(struct i2c_client *client,
+static int mt9m111_reg_mask(struct i2c_client *client, const u16 reg,
+                           const u16 data, const u16 mask)
+{
+       int ret;
+
+       ret = mt9m111_reg_read(client, reg);
+       if (ret >= 0)
+               ret = mt9m111_reg_write(client, reg, (ret & ~mask) | data);
+       return ret;
+}
+
+static int mt9m111_set_context(struct mt9m111 *mt9m111,
                               enum mt9m111_context ctxt)
 {
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
                | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
                | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
@@ -267,10 +291,10 @@ static int mt9m111_set_context(struct i2c_client *client,
                return reg_write(CONTEXT_CONTROL, valA);
 }
 
-static int mt9m111_setup_rect(struct i2c_client *client,
+static int mt9m111_setup_rect(struct mt9m111 *mt9m111,
                              struct v4l2_rect *rect)
 {
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        int ret, is_raw_format;
        int width = rect->width;
        int height = rect->height;
@@ -312,81 +336,9 @@ static int mt9m111_setup_rect(struct i2c_client *client,
        return ret;
 }
 
-static int mt9m111_setup_pixfmt(struct i2c_client *client, u16 outfmt)
+static int mt9m111_enable(struct mt9m111 *mt9m111)
 {
-       int ret;
-       u16 mask = MT9M111_OUTFMT_PROCESSED_BAYER | MT9M111_OUTFMT_RGB |
-               MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_SWAP_RGB_EVEN |
-               MT9M111_OUTFMT_RGB565 | MT9M111_OUTFMT_RGB555 |
-               MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr |
-               MT9M111_OUTFMT_SWAP_YCbCr_C_Y;
-
-       ret = reg_read(OUTPUT_FORMAT_CTRL2_A);
-       if (ret >= 0)
-               ret = reg_write(OUTPUT_FORMAT_CTRL2_A, (ret & ~mask) | outfmt);
-       if (!ret)
-               ret = reg_read(OUTPUT_FORMAT_CTRL2_B);
-       if (ret >= 0)
-               ret = reg_write(OUTPUT_FORMAT_CTRL2_B, (ret & ~mask) | outfmt);
-
-       return ret;
-}
-
-static int mt9m111_setfmt_bayer8(struct i2c_client *client)
-{
-       return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_PROCESSED_BAYER |
-                                   MT9M111_OUTFMT_RGB);
-}
-
-static int mt9m111_setfmt_bayer10(struct i2c_client *client)
-{
-       return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_BYPASS_IFP);
-}
-
-static int mt9m111_setfmt_rgb565(struct i2c_client *client)
-{
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
-       int val = 0;
-
-       if (mt9m111->swap_rgb_red_blue)
-               val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr;
-       if (mt9m111->swap_rgb_even_odd)
-               val |= MT9M111_OUTFMT_SWAP_RGB_EVEN;
-       val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565;
-
-       return mt9m111_setup_pixfmt(client, val);
-}
-
-static int mt9m111_setfmt_rgb555(struct i2c_client *client)
-{
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
-       int val = 0;
-
-       if (mt9m111->swap_rgb_red_blue)
-               val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr;
-       if (mt9m111->swap_rgb_even_odd)
-               val |= MT9M111_OUTFMT_SWAP_RGB_EVEN;
-       val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555;
-
-       return mt9m111_setup_pixfmt(client, val);
-}
-
-static int mt9m111_setfmt_yuv(struct i2c_client *client)
-{
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
-       int val = 0;
-
-       if (mt9m111->swap_yuv_cb_cr)
-               val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr;
-       if (mt9m111->swap_yuv_y_chromas)
-               val |= MT9M111_OUTFMT_SWAP_YCbCr_C_Y;
-
-       return mt9m111_setup_pixfmt(client, val);
-}
-
-static int mt9m111_enable(struct i2c_client *client)
-{
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        int ret;
 
        ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE);
@@ -395,8 +347,9 @@ static int mt9m111_enable(struct i2c_client *client)
        return ret;
 }
 
-static int mt9m111_reset(struct i2c_client *client)
+static int mt9m111_reset(struct mt9m111 *mt9m111)
 {
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        int ret;
 
        ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
@@ -424,11 +377,9 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
        return 0;
 }
 
-static int mt9m111_make_rect(struct i2c_client *client,
+static int mt9m111_make_rect(struct mt9m111 *mt9m111,
                             struct v4l2_rect *rect)
 {
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
-
        if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
            mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
                /* Bayer format - even size lengths */
@@ -444,14 +395,14 @@ static int mt9m111_make_rect(struct i2c_client *client,
        soc_camera_limit_side(&rect->top, &rect->height,
                     MT9M111_MIN_DARK_ROWS, 2, MT9M111_MAX_HEIGHT);
 
-       return mt9m111_setup_rect(client, rect);
+       return mt9m111_setup_rect(mt9m111, rect);
 }
 
 static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
        struct v4l2_rect rect = a->c;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
        int ret;
 
        dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
@@ -460,7 +411,7 @@ static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
        if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
-       ret = mt9m111_make_rect(client, &rect);
+       ret = mt9m111_make_rect(mt9m111, &rect);
        if (!ret)
                mt9m111->rect = rect;
        return ret;
@@ -468,8 +419,7 @@ static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 
 static int mt9m111_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
 
        a->c    = mt9m111->rect;
        a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -496,8 +446,7 @@ static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 static int mt9m111_g_fmt(struct v4l2_subdev *sd,
                         struct v4l2_mbus_framefmt *mf)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
 
        mf->width       = mt9m111->rect.width;
        mf->height      = mt9m111->rect.height;
@@ -508,51 +457,73 @@ static int mt9m111_g_fmt(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int mt9m111_set_pixfmt(struct i2c_client *client,
+static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111,
                              enum v4l2_mbus_pixelcode code)
 {
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+       u16 data_outfmt2, mask_outfmt2 = MT9M111_OUTFMT_PROCESSED_BAYER |
+               MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_RGB |
+               MT9M111_OUTFMT_RGB565 | MT9M111_OUTFMT_RGB555 |
+               MT9M111_OUTFMT_RGB444x | MT9M111_OUTFMT_RGBx444 |
+               MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
+               MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
        int ret;
 
        switch (code) {
        case V4L2_MBUS_FMT_SBGGR8_1X8:
-               ret = mt9m111_setfmt_bayer8(client);
+               data_outfmt2 = MT9M111_OUTFMT_PROCESSED_BAYER |
+                       MT9M111_OUTFMT_RGB;
                break;
        case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
-               ret = mt9m111_setfmt_bayer10(client);
+               data_outfmt2 = MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_RGB;
                break;
        case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
-               ret = mt9m111_setfmt_rgb555(client);
+               data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555 |
+                       MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
+               break;
+       case V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE:
+               data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555;
                break;
        case V4L2_MBUS_FMT_RGB565_2X8_LE:
-               ret = mt9m111_setfmt_rgb565(client);
+               data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
+                       MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
+               break;
+       case V4L2_MBUS_FMT_RGB565_2X8_BE:
+               data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565;
+               break;
+       case V4L2_MBUS_FMT_BGR565_2X8_BE:
+               data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
+                       MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
+               break;
+       case V4L2_MBUS_FMT_BGR565_2X8_LE:
+               data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
+                       MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
+                       MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
                break;
        case V4L2_MBUS_FMT_UYVY8_2X8:
-               mt9m111->swap_yuv_y_chromas = 0;
-               mt9m111->swap_yuv_cb_cr = 0;
-               ret = mt9m111_setfmt_yuv(client);
+               data_outfmt2 = 0;
                break;
        case V4L2_MBUS_FMT_VYUY8_2X8:
-               mt9m111->swap_yuv_y_chromas = 0;
-               mt9m111->swap_yuv_cb_cr = 1;
-               ret = mt9m111_setfmt_yuv(client);
+               data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
                break;
        case V4L2_MBUS_FMT_YUYV8_2X8:
-               mt9m111->swap_yuv_y_chromas = 1;
-               mt9m111->swap_yuv_cb_cr = 0;
-               ret = mt9m111_setfmt_yuv(client);
+               data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
                break;
        case V4L2_MBUS_FMT_YVYU8_2X8:
-               mt9m111->swap_yuv_y_chromas = 1;
-               mt9m111->swap_yuv_cb_cr = 1;
-               ret = mt9m111_setfmt_yuv(client);
+               data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
+                       MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
                break;
        default:
-               dev_err(&client->dev, "Pixel format not handled : %x\n",
-                       code);
-               ret = -EINVAL;
+               dev_err(&client->dev, "Pixel format not handled: %x\n", code);
+               return -EINVAL;
        }
 
+       ret = reg_mask(OUTPUT_FORMAT_CTRL2_A, data_outfmt2,
+                      mask_outfmt2);
+       if (!ret)
+               ret = reg_mask(OUTPUT_FORMAT_CTRL2_B, data_outfmt2,
+                              mask_outfmt2);
+
        return ret;
 }
 
@@ -561,7 +532,7 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd,
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        const struct mt9m111_datafmt *fmt;
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
        struct v4l2_rect rect = {
                .left   = mt9m111->rect.left,
                .top    = mt9m111->rect.top,
@@ -579,9 +550,9 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd,
                "%s code=%x left=%d, top=%d, width=%d, height=%d\n", __func__,
                mf->code, rect.left, rect.top, rect.width, rect.height);
 
-       ret = mt9m111_make_rect(client, &rect);
+       ret = mt9m111_make_rect(mt9m111, &rect);
        if (!ret)
-               ret = mt9m111_set_pixfmt(client, mf->code);
+               ret = mt9m111_set_pixfmt(mt9m111, mf->code);
        if (!ret) {
                mt9m111->rect   = rect;
                mt9m111->fmt    = fmt;
@@ -594,8 +565,7 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd,
 static int mt9m111_try_fmt(struct v4l2_subdev *sd,
                           struct v4l2_mbus_framefmt *mf)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
        const struct mt9m111_datafmt *fmt;
        bool bayer = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
                mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE;
@@ -635,7 +605,7 @@ static int mt9m111_g_chip_ident(struct v4l2_subdev *sd,
                                struct v4l2_dbg_chip_ident *id)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
 
        if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
                return -EINVAL;
@@ -726,21 +696,16 @@ static const struct v4l2_queryctrl mt9m111_controls[] = {
        }
 };
 
-static int mt9m111_resume(struct soc_camera_device *icd);
-static int mt9m111_suspend(struct soc_camera_device *icd, pm_message_t state);
-
 static struct soc_camera_ops mt9m111_ops = {
-       .suspend                = mt9m111_suspend,
-       .resume                 = mt9m111_resume,
        .query_bus_param        = mt9m111_query_bus_param,
        .set_bus_param          = mt9m111_set_bus_param,
        .controls               = mt9m111_controls,
        .num_controls           = ARRAY_SIZE(mt9m111_controls),
 };
 
-static int mt9m111_set_flip(struct i2c_client *client, int flip, int mask)
+static int mt9m111_set_flip(struct mt9m111 *mt9m111, int flip, int mask)
 {
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        int ret;
 
        if (mt9m111->context == HIGHPOWER) {
@@ -758,8 +723,9 @@ static int mt9m111_set_flip(struct i2c_client *client, int flip, int mask)
        return ret;
 }
 
-static int mt9m111_get_global_gain(struct i2c_client *client)
+static int mt9m111_get_global_gain(struct mt9m111 *mt9m111)
 {
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        int data;
 
        data = reg_read(GLOBAL_GAIN);
@@ -769,9 +735,9 @@ static int mt9m111_get_global_gain(struct i2c_client *client)
        return data;
 }
 
-static int mt9m111_set_global_gain(struct i2c_client *client, int gain)
+static int mt9m111_set_global_gain(struct mt9m111 *mt9m111, int gain)
 {
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        u16 val;
 
        if (gain > 63 * 2 * 2)
@@ -788,9 +754,9 @@ static int mt9m111_set_global_gain(struct i2c_client *client, int gain)
        return reg_write(GLOBAL_GAIN, val);
 }
 
-static int mt9m111_set_autoexposure(struct i2c_client *client, int on)
+static int mt9m111_set_autoexposure(struct mt9m111 *mt9m111, int on)
 {
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        int ret;
 
        if (on)
@@ -804,9 +770,9 @@ static int mt9m111_set_autoexposure(struct i2c_client *client, int on)
        return ret;
 }
 
-static int mt9m111_set_autowhitebalance(struct i2c_client *client, int on)
+static int mt9m111_set_autowhitebalance(struct mt9m111 *mt9m111, int on)
 {
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        int ret;
 
        if (on)
@@ -823,7 +789,7 @@ static int mt9m111_set_autowhitebalance(struct i2c_client *client, int on)
 static int mt9m111_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
        int data;
 
        switch (ctrl->id) {
@@ -848,7 +814,7 @@ static int mt9m111_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
                ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS);
                break;
        case V4L2_CID_GAIN:
-               data = mt9m111_get_global_gain(client);
+               data = mt9m111_get_global_gain(mt9m111);
                if (data < 0)
                        return data;
                ctrl->value = data;
@@ -865,8 +831,7 @@ static int mt9m111_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 
 static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
        const struct v4l2_queryctrl *qctrl;
        int ret;
 
@@ -877,22 +842,22 @@ static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
                mt9m111->vflip = ctrl->value;
-               ret = mt9m111_set_flip(client, ctrl->value,
+               ret = mt9m111_set_flip(mt9m111, ctrl->value,
                                        MT9M111_RMB_MIRROR_ROWS);
                break;
        case V4L2_CID_HFLIP:
                mt9m111->hflip = ctrl->value;
-               ret = mt9m111_set_flip(client, ctrl->value,
+               ret = mt9m111_set_flip(mt9m111, ctrl->value,
                                        MT9M111_RMB_MIRROR_COLS);
                break;
        case V4L2_CID_GAIN:
-               ret = mt9m111_set_global_gain(client, ctrl->value);
+               ret = mt9m111_set_global_gain(mt9m111, ctrl->value);
                break;
        case V4L2_CID_EXPOSURE_AUTO:
-               ret =  mt9m111_set_autoexposure(client, ctrl->value);
+               ret =  mt9m111_set_autoexposure(mt9m111, ctrl->value);
                break;
        case V4L2_CID_AUTO_WHITE_BALANCE:
-               ret =  mt9m111_set_autowhitebalance(client, ctrl->value);
+               ret =  mt9m111_set_autowhitebalance(mt9m111, ctrl->value);
                break;
        default:
                ret = -EINVAL;
@@ -901,60 +866,52 @@ static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
        return ret;
 }
 
-static int mt9m111_suspend(struct soc_camera_device *icd, pm_message_t state)
+static int mt9m111_suspend(struct mt9m111 *mt9m111)
 {
-       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
-
-       mt9m111->gain = mt9m111_get_global_gain(client);
+       mt9m111->gain = mt9m111_get_global_gain(mt9m111);
 
        return 0;
 }
 
-static int mt9m111_restore_state(struct i2c_client *client)
+static void mt9m111_restore_state(struct mt9m111 *mt9m111)
 {
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
-
-       mt9m111_set_context(client, mt9m111->context);
-       mt9m111_set_pixfmt(client, mt9m111->fmt->code);
-       mt9m111_setup_rect(client, &mt9m111->rect);
-       mt9m111_set_flip(client, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS);
-       mt9m111_set_flip(client, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS);
-       mt9m111_set_global_gain(client, mt9m111->gain);
-       mt9m111_set_autoexposure(client, mt9m111->autoexposure);
-       mt9m111_set_autowhitebalance(client, mt9m111->autowhitebalance);
-       return 0;
+       mt9m111_set_context(mt9m111, mt9m111->context);
+       mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code);
+       mt9m111_setup_rect(mt9m111, &mt9m111->rect);
+       mt9m111_set_flip(mt9m111, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS);
+       mt9m111_set_flip(mt9m111, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS);
+       mt9m111_set_global_gain(mt9m111, mt9m111->gain);
+       mt9m111_set_autoexposure(mt9m111, mt9m111->autoexposure);
+       mt9m111_set_autowhitebalance(mt9m111, mt9m111->autowhitebalance);
 }
 
-static int mt9m111_resume(struct soc_camera_device *icd)
+static int mt9m111_resume(struct mt9m111 *mt9m111)
 {
-       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
        int ret = 0;
 
        if (mt9m111->powered) {
-               ret = mt9m111_enable(client);
+               ret = mt9m111_enable(mt9m111);
                if (!ret)
-                       ret = mt9m111_reset(client);
+                       ret = mt9m111_reset(mt9m111);
                if (!ret)
-                       ret = mt9m111_restore_state(client);
+                       mt9m111_restore_state(mt9m111);
        }
        return ret;
 }
 
-static int mt9m111_init(struct i2c_client *client)
+static int mt9m111_init(struct mt9m111 *mt9m111)
 {
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        int ret;
 
        mt9m111->context = HIGHPOWER;
-       ret = mt9m111_enable(client);
+       ret = mt9m111_enable(mt9m111);
        if (!ret)
-               ret = mt9m111_reset(client);
+               ret = mt9m111_reset(mt9m111);
        if (!ret)
-               ret = mt9m111_set_context(client, mt9m111->context);
+               ret = mt9m111_set_context(mt9m111, mt9m111->context);
        if (!ret)
-               ret = mt9m111_set_autoexposure(client, mt9m111->autoexposure);
+               ret = mt9m111_set_autoexposure(mt9m111, mt9m111->autoexposure);
        if (ret)
                dev_err(&client->dev, "mt9m111 init failed: %d\n", ret);
        return ret;
@@ -971,20 +928,13 @@ static int mt9m111_video_probe(struct soc_camera_device *icd,
        s32 data;
        int ret;
 
-       /*
-        * We must have a parent by now. And it cannot be a wrong one.
-        * So this entire test is completely redundant.
-        */
-       if (!icd->dev.parent ||
-           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
-               return -ENODEV;
+       /* We must have a parent by now. And it cannot be a wrong one. */
+       BUG_ON(!icd->parent ||
+              to_soc_camera_host(icd->parent)->nr != icd->iface);
 
        mt9m111->autoexposure = 1;
        mt9m111->autowhitebalance = 1;
 
-       mt9m111->swap_rgb_even_odd = 1;
-       mt9m111->swap_rgb_red_blue = 1;
-
        data = reg_read(CHIP_VERSION);
 
        switch (data) {
@@ -1005,16 +955,51 @@ static int mt9m111_video_probe(struct soc_camera_device *icd,
                goto ei2c;
        }
 
-       ret = mt9m111_init(client);
+       ret = mt9m111_init(mt9m111);
 
 ei2c:
        return ret;
 }
 
+static int mt9m111_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       int ret = 0;
+
+       mutex_lock(&mt9m111->power_lock);
+
+       /*
+        * If the power count is modified from 0 to != 0 or from != 0 to 0,
+        * update the power state.
+        */
+       if (mt9m111->power_count == !on) {
+               if (on) {
+                       ret = mt9m111_resume(mt9m111);
+                       if (ret) {
+                               dev_err(&client->dev,
+                                       "Failed to resume the sensor: %d\n", ret);
+                               goto out;
+                       }
+               } else {
+                       mt9m111_suspend(mt9m111);
+               }
+       }
+
+       /* Update the power count. */
+       mt9m111->power_count += on ? 1 : -1;
+       WARN_ON(mt9m111->power_count < 0);
+
+out:
+       mutex_unlock(&mt9m111->power_lock);
+       return ret;
+}
+
 static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
        .g_ctrl         = mt9m111_g_ctrl,
        .s_ctrl         = mt9m111_s_ctrl,
        .g_chip_ident   = mt9m111_g_chip_ident,
+       .s_power        = mt9m111_s_power,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register     = mt9m111_g_register,
        .s_register     = mt9m111_s_register,
index 7ce279c..30547cc 100644 (file)
@@ -700,8 +700,7 @@ static int mt9t031_runtime_suspend(struct device *dev)
 static int mt9t031_runtime_resume(struct device *dev)
 {
        struct video_device *vdev = to_video_device(dev);
-       struct soc_camera_device *icd = container_of(vdev->parent,
-               struct soc_camera_device, dev);
+       struct soc_camera_device *icd = dev_get_drvdata(vdev->parent);
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9t031 *mt9t031 = to_mt9t031(client);
index bffa9ee..d2e0a50 100644 (file)
@@ -1057,13 +1057,9 @@ static int mt9t112_camera_probe(struct soc_camera_device *icd,
        const char          *devname;
        int                  chipid;
 
-       /*
-        * We must have a parent by now. And it cannot be a wrong one.
-        * So this entire test is completely redundant.
-        */
-       if (!icd->dev.parent ||
-           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
-               return -ENODEV;
+       /* We must have a parent by now. And it cannot be a wrong one. */
+       BUG_ON(!icd->parent ||
+              to_soc_camera_host(icd->parent)->nr != icd->iface);
 
        /*
         * check and show chip ID
index 4904d25..893a8b8 100644 (file)
@@ -54,10 +54,19 @@ static struct v4l2_queryctrl mt9v011_qctrl[] = {
                .type = V4L2_CTRL_TYPE_INTEGER,
                .name = "Gain",
                .minimum = 0,
-               .maximum = (1 << 10) - 1,
+               .maximum = (1 << 12) - 1 - 0x0020,
                .step = 1,
                .default_value = 0x0020,
                .flags = 0,
+       }, {
+               .id = V4L2_CID_EXPOSURE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Exposure",
+               .minimum = 0,
+               .maximum = 2047,
+               .step = 1,
+               .default_value = 0x01fc,
+               .flags = 0,
        }, {
                .id = V4L2_CID_RED_BALANCE,
                .type = V4L2_CTRL_TYPE_INTEGER,
@@ -105,7 +114,8 @@ struct mt9v011 {
        unsigned hflip:1;
        unsigned vflip:1;
 
-       u16 global_gain, red_bal, blue_bal;
+       u16 global_gain, exposure;
+       s16 red_bal, blue_bal;
 };
 
 static inline struct mt9v011 *to_mt9v011(struct v4l2_subdev *sd)
@@ -180,24 +190,68 @@ static const struct i2c_reg_value mt9v011_init_default[] = {
                { R07_MT9V011_OUT_CTRL, 0x0002 },       /* chip enable */
 };
 
+
+static u16 calc_mt9v011_gain(s16 lineargain)
+{
+
+       u16 digitalgain = 0;
+       u16 analogmult = 0;
+       u16 analoginit = 0;
+
+       if (lineargain < 0)
+               lineargain = 0;
+
+       /* recommended minimum */
+       lineargain += 0x0020;
+
+       if (lineargain > 2047)
+               lineargain = 2047;
+
+       if (lineargain > 1023) {
+               digitalgain = 3;
+               analogmult = 3;
+               analoginit = lineargain / 16;
+       } else if (lineargain > 511) {
+               digitalgain = 1;
+               analogmult = 3;
+               analoginit = lineargain / 8;
+       } else if (lineargain > 255) {
+               analogmult = 3;
+               analoginit = lineargain / 4;
+       } else if (lineargain > 127) {
+               analogmult = 1;
+               analoginit = lineargain / 2;
+       } else
+               analoginit = lineargain;
+
+       return analoginit + (analogmult << 7) + (digitalgain << 9);
+
+}
+
 static void set_balance(struct v4l2_subdev *sd)
 {
        struct mt9v011 *core = to_mt9v011(sd);
-       u16 green1_gain, green2_gain, blue_gain, red_gain;
+       u16 green_gain, blue_gain, red_gain;
+       u16 exposure;
+       s16 bal;
 
-       green1_gain = core->global_gain;
-       green2_gain = core->global_gain;
+       exposure = core->exposure;
 
-       blue_gain = core->global_gain +
-                   core->global_gain * core->blue_bal / (1 << 9);
+       green_gain = calc_mt9v011_gain(core->global_gain);
 
-       red_gain = core->global_gain +
-                  core->global_gain * core->blue_bal / (1 << 9);
+       bal = core->global_gain;
+       bal += (core->blue_bal * core->global_gain / (1 << 7));
+       blue_gain = calc_mt9v011_gain(bal);
 
-       mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green1_gain);
-       mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN,  green1_gain);
+       bal = core->global_gain;
+       bal += (core->red_bal * core->global_gain / (1 << 7));
+       red_gain = calc_mt9v011_gain(bal);
+
+       mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green_gain);
+       mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN, green_gain);
        mt9v011_write(sd, R2C_MT9V011_BLUE_GAIN, blue_gain);
        mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain);
+       mt9v011_write(sd, R09_MT9V011_SHUTTER_WIDTH, exposure);
 }
 
 static void calc_fps(struct v4l2_subdev *sd, u32 *numerator, u32 *denominator)
@@ -286,7 +340,7 @@ static void set_res(struct v4l2_subdev *sd)
         * be missing.
         */
 
-       hstart = 14 + (640 - core->width) / 2;
+       hstart = 20 + (640 - core->width) / 2;
        mt9v011_write(sd, R02_MT9V011_COLSTART, hstart);
        mt9v011_write(sd, R04_MT9V011_WIDTH, core->width);
        mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width);
@@ -338,6 +392,9 @@ static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
        case V4L2_CID_GAIN:
                ctrl->value = core->global_gain;
                return 0;
+       case V4L2_CID_EXPOSURE:
+               ctrl->value = core->exposure;
+               return 0;
        case V4L2_CID_RED_BALANCE:
                ctrl->value = core->red_bal;
                return 0;
@@ -392,6 +449,9 @@ static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
        case V4L2_CID_GAIN:
                core->global_gain = ctrl->value;
                break;
+       case V4L2_CID_EXPOSURE:
+               core->exposure = ctrl->value;
+               break;
        case V4L2_CID_RED_BALANCE:
                core->red_bal = ctrl->value;
                break;
@@ -598,6 +658,7 @@ static int mt9v011_probe(struct i2c_client *c,
        }
 
        core->global_gain = 0x0024;
+       core->exposure = 0x01fc;
        core->width  = 640;
        core->height = 480;
        core->xtal = 27000000;  /* Hz */
index fc76ed1..51b0fcc 100644 (file)
@@ -728,9 +728,9 @@ static int mt9v022_video_probe(struct soc_camera_device *icd,
        int ret;
        unsigned long flags;
 
-       if (!icd->dev.parent ||
-           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
-               return -ENODEV;
+       /* We must have a parent by now. And it cannot be a wrong one. */
+       BUG_ON(!icd->parent ||
+              to_soc_camera_host(icd->parent)->nr != icd->iface);
 
        /* Read out the chip version register */
        data = reg_read(client, MT9V022_CHIP_VERSION);
@@ -809,8 +809,8 @@ static void mt9v022_video_remove(struct soc_camera_device *icd)
 {
        struct soc_camera_link *icl = to_soc_camera_link(icd);
 
-       dev_dbg(&icd->dev, "Video removed: %p, %p\n",
-               icd->dev.parent, icd->vdev);
+       dev_dbg(icd->pdev, "Video removed: %p, %p\n",
+               icd->parent, icd->vdev);
        if (icl->free_bus)
                icl->free_bus(icl);
 }
index 1319c2c..c64e1dc 100644 (file)
 #define MT9V032_CHIP_VERSION                           0x00
 #define                MT9V032_CHIP_ID_REV1                    0x1311
 #define                MT9V032_CHIP_ID_REV3                    0x1313
-#define MT9V032_ROW_START                              0x01
-#define                MT9V032_ROW_START_MIN                   4
-#define                MT9V032_ROW_START_DEF                   10
-#define                MT9V032_ROW_START_MAX                   482
-#define MT9V032_COLUMN_START                           0x02
+#define MT9V032_COLUMN_START                           0x01
 #define                MT9V032_COLUMN_START_MIN                1
-#define                MT9V032_COLUMN_START_DEF                2
+#define                MT9V032_COLUMN_START_DEF                1
 #define                MT9V032_COLUMN_START_MAX                752
+#define MT9V032_ROW_START                              0x02
+#define                MT9V032_ROW_START_MIN                   4
+#define                MT9V032_ROW_START_DEF                   5
+#define                MT9V032_ROW_START_MAX                   482
 #define MT9V032_WINDOW_HEIGHT                          0x03
 #define                MT9V032_WINDOW_HEIGHT_MIN               1
 #define                MT9V032_WINDOW_HEIGHT_DEF               480
@@ -420,13 +420,13 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
        struct v4l2_rect *__crop;
        struct v4l2_rect rect;
 
-       /* Clamp the crop rectangle boundaries and align them to a multiple of 2
-        * pixels.
+       /* Clamp the crop rectangle boundaries and align them to a non multiple
+        * of 2 pixels to ensure a GRBG Bayer pattern.
         */
-       rect.left = clamp(ALIGN(crop->rect.left, 2),
+       rect.left = clamp(ALIGN(crop->rect.left + 1, 2) - 1,
                          MT9V032_COLUMN_START_MIN,
                          MT9V032_COLUMN_START_MAX);
-       rect.top = clamp(ALIGN(crop->rect.top, 2),
+       rect.top = clamp(ALIGN(crop->rect.top + 1, 2) - 1,
                         MT9V032_ROW_START_MIN,
                         MT9V032_ROW_START_MAX);
        rect.width = clamp(ALIGN(crop->rect.width, 2),
index 63f8a0c..087db12 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/time.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 
 #include <media/soc_camera.h>
@@ -73,7 +72,7 @@
 #define CSISR_SOF_INT          (1 << 16)
 #define CSISR_DRDY             (1 << 0)
 
-#define VERSION_CODE KERNEL_VERSION(0, 0, 1)
+#define DRIVER_VERSION "0.0.2"
 #define DRIVER_NAME "mx1-camera"
 
 #define CSI_IRQ_MASK   (CSISR_SFF_OR_INT | CSISR_RFF_OR_INT | \
@@ -142,7 +141,7 @@ static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
        if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
                *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size;
 
-       dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size);
+       dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size);
 
        return 0;
 }
@@ -154,7 +153,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx1_buffer *buf)
 
        BUG_ON(in_interrupt());
 
-       dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                vb, vb->baddr, vb->bsize);
 
        /*
@@ -179,7 +178,7 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq,
        if (bytes_per_line < 0)
                return bytes_per_line;
 
-       dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                vb, vb->baddr, vb->bsize);
 
        /* Added list head initialization on alloc */
@@ -232,7 +231,7 @@ out:
 static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev)
 {
        struct videobuf_buffer *vbuf = &pcdev->active->vb;
-       struct device *dev = pcdev->icd->dev.parent;
+       struct device *dev = pcdev->icd->parent;
        int ret;
 
        if (unlikely(!pcdev->active)) {
@@ -256,11 +255,11 @@ static void mx1_videobuf_queue(struct videobuf_queue *vq,
                                                struct videobuf_buffer *vb)
 {
        struct soc_camera_device *icd = vq->priv_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx1_camera_dev *pcdev = ici->priv;
        struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
 
-       dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                vb, vb->baddr, vb->bsize);
 
        list_add_tail(&vb->queue, &pcdev->capture);
@@ -287,7 +286,7 @@ static void mx1_videobuf_release(struct videobuf_queue *vq,
        struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
 #ifdef DEBUG
        struct soc_camera_device *icd = vq->priv_data;
-       struct device *dev = icd->dev.parent;
+       struct device *dev = icd->parent;
 
        dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                vb, vb->baddr, vb->bsize);
@@ -343,7 +342,7 @@ static void mx1_camera_wakeup(struct mx1_camera_dev *pcdev,
 static void mx1_camera_dma_irq(int channel, void *data)
 {
        struct mx1_camera_dev *pcdev = data;
-       struct device *dev = pcdev->icd->dev.parent;
+       struct device *dev = pcdev->icd->parent;
        struct mx1_buffer *buf;
        struct videobuf_buffer *vb;
        unsigned long flags;
@@ -378,10 +377,10 @@ static struct videobuf_queue_ops mx1_videobuf_ops = {
 static void mx1_camera_init_videobuf(struct videobuf_queue *q,
                                     struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx1_camera_dev *pcdev = ici->priv;
 
-       videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->dev.parent,
+       videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->parent,
                                &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
                                V4L2_FIELD_NONE,
                                sizeof(struct mx1_buffer), icd, &icd->video_lock);
@@ -401,7 +400,7 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev)
         */
        div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1;
 
-       dev_dbg(pcdev->icd->dev.parent,
+       dev_dbg(pcdev->icd->parent,
                "System clock %lukHz, target freq %dkHz, divisor %lu\n",
                lcdclk / 1000, mclk / 1000, div);
 
@@ -412,7 +411,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev)
 {
        unsigned int csicr1 = CSICR1_EN;
 
-       dev_dbg(pcdev->icd->dev.parent, "Activate device\n");
+       dev_dbg(pcdev->icd->parent, "Activate device\n");
 
        clk_enable(pcdev->clk);
 
@@ -428,7 +427,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev)
 
 static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev)
 {
-       dev_dbg(pcdev->icd->dev.parent, "Deactivate device\n");
+       dev_dbg(pcdev->icd->parent, "Deactivate device\n");
 
        /* Disable all CSI interface */
        __raw_writel(0x00, pcdev->base + CSICR1);
@@ -442,13 +441,13 @@ static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev)
  */
 static int mx1_camera_add_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx1_camera_dev *pcdev = ici->priv;
 
        if (pcdev->icd)
                return -EBUSY;
 
-       dev_info(icd->dev.parent, "MX1 Camera driver attached to camera %d\n",
+       dev_info(icd->parent, "MX1 Camera driver attached to camera %d\n",
                 icd->devnum);
 
        mx1_camera_activate(pcdev);
@@ -460,7 +459,7 @@ static int mx1_camera_add_device(struct soc_camera_device *icd)
 
 static void mx1_camera_remove_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx1_camera_dev *pcdev = ici->priv;
        unsigned int csicr1;
 
@@ -473,7 +472,7 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd)
        /* Stop DMA engine */
        imx_dma_disable(pcdev->dma_chan);
 
-       dev_info(icd->dev.parent, "MX1 Camera driver detached from camera %d\n",
+       dev_info(icd->parent, "MX1 Camera driver detached from camera %d\n",
                 icd->devnum);
 
        mx1_camera_deactivate(pcdev);
@@ -491,7 +490,7 @@ static int mx1_camera_set_crop(struct soc_camera_device *icd,
 
 static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx1_camera_dev *pcdev = ici->priv;
        unsigned long camera_flags, common_flags;
        unsigned int csicr1;
@@ -562,14 +561,14 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd,
 
        xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
        if (!xlate) {
-               dev_warn(icd->dev.parent, "Format %x not found\n",
+               dev_warn(icd->parent, "Format %x not found\n",
                         pix->pixelformat);
                return -EINVAL;
        }
 
        buswidth = xlate->host_fmt->bits_per_sample;
        if (buswidth > 8) {
-               dev_warn(icd->dev.parent,
+               dev_warn(icd->parent,
                         "bits-per-sample %d for format %x unsupported\n",
                         buswidth, pix->pixelformat);
                return -EINVAL;
@@ -609,7 +608,7 @@ static int mx1_camera_try_fmt(struct soc_camera_device *icd,
 
        xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
        if (!xlate) {
-               dev_warn(icd->dev.parent, "Format %x not found\n",
+               dev_warn(icd->parent, "Format %x not found\n",
                         pix->pixelformat);
                return -EINVAL;
        }
@@ -676,7 +675,6 @@ static int mx1_camera_querycap(struct soc_camera_host *ici,
 {
        /* cap->name is set by the friendly caller:-> */
        strlcpy(cap->card, "i.MX1/i.MXL Camera", sizeof(cap->card));
-       cap->version = VERSION_CODE;
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 
        return 0;
@@ -883,4 +881,5 @@ module_exit(mx1_camera_exit);
 MODULE_DESCRIPTION("i.MX1/i.MXL SoC Camera Host driver");
 MODULE_AUTHOR("Paulius Zaleckas <paulius.zaleckas@teltonika.lt>");
 MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRIVER_VERSION);
 MODULE_ALIAS("platform:" DRIVER_NAME);
index 4eab1c6..ec2410c 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/mm.h>
 #include <linux/moduleparam.h>
 #include <linux/time.h>
-#include <linux/version.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
@@ -47,7 +46,7 @@
 #include <asm/dma.h>
 
 #define MX2_CAM_DRV_NAME "mx2-camera"
-#define MX2_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5)
+#define MX2_CAM_VERSION "0.0.6"
 #define MX2_CAM_DRIVER_DESCRIPTION "i.MX2x_Camera"
 
 /* reset values */
@@ -278,7 +277,7 @@ static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)
  */
 static int mx2_camera_add_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
        int ret;
        u32 csicr1;
@@ -303,7 +302,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
 
        pcdev->icd = icd;
 
-       dev_info(icd->dev.parent, "Camera driver attached to camera %d\n",
+       dev_info(icd->parent, "Camera driver attached to camera %d\n",
                 icd->devnum);
 
        return 0;
@@ -311,12 +310,12 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
 
 static void mx2_camera_remove_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
 
        BUG_ON(icd != pcdev->icd);
 
-       dev_info(icd->dev.parent, "Camera driver detached from camera %d\n",
+       dev_info(icd->parent, "Camera driver detached from camera %d\n",
                 icd->devnum);
 
        mx2_camera_deactivate(pcdev);
@@ -437,7 +436,7 @@ static int mx2_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
        int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
                        icd->current_fmt->host_fmt);
 
-       dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
+       dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size);
 
        if (bytes_per_line < 0)
                return bytes_per_line;
@@ -457,7 +456,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf)
        struct soc_camera_device *icd = vq->priv_data;
        struct videobuf_buffer *vb = &buf->vb;
 
-       dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                vb, vb->baddr, vb->bsize);
 
        /*
@@ -467,7 +466,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf)
        videobuf_waiton(vq, vb, 0, 0);
 
        videobuf_dma_contig_free(vq, vb);
-       dev_dbg(&icd->dev, "%s freed\n", __func__);
+       dev_dbg(icd->parent, "%s freed\n", __func__);
 
        vb->state = VIDEOBUF_NEEDS_INIT;
 }
@@ -481,7 +480,7 @@ static int mx2_videobuf_prepare(struct videobuf_queue *vq,
                        icd->current_fmt->host_fmt);
        int ret = 0;
 
-       dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                vb, vb->baddr, vb->bsize);
 
        if (bytes_per_line < 0)
@@ -533,12 +532,12 @@ static void mx2_videobuf_queue(struct videobuf_queue *vq,
 {
        struct soc_camera_device *icd = vq->priv_data;
        struct soc_camera_host *ici =
-               to_soc_camera_host(icd->dev.parent);
+               to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
        struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
        unsigned long flags;
 
-       dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                vb, vb->baddr, vb->bsize);
 
        spin_lock_irqsave(&pcdev->lock, flags);
@@ -611,27 +610,27 @@ static void mx2_videobuf_release(struct videobuf_queue *vq,
                                 struct videobuf_buffer *vb)
 {
        struct soc_camera_device *icd = vq->priv_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
        struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
        unsigned long flags;
 
 #ifdef DEBUG
-       dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                vb, vb->baddr, vb->bsize);
 
        switch (vb->state) {
        case VIDEOBUF_ACTIVE:
-               dev_info(&icd->dev, "%s (active)\n", __func__);
+               dev_info(icd->parent, "%s (active)\n", __func__);
                break;
        case VIDEOBUF_QUEUED:
-               dev_info(&icd->dev, "%s (queued)\n", __func__);
+               dev_info(icd->parent, "%s (queued)\n", __func__);
                break;
        case VIDEOBUF_PREPARED:
-               dev_info(&icd->dev, "%s (prepared)\n", __func__);
+               dev_info(icd->parent, "%s (prepared)\n", __func__);
                break;
        default:
-               dev_info(&icd->dev, "%s (unknown) %d\n", __func__,
+               dev_info(icd->parent, "%s (unknown) %d\n", __func__,
                                vb->state);
                break;
        }
@@ -678,7 +677,7 @@ static struct videobuf_queue_ops mx2_videobuf_ops = {
 static void mx2_camera_init_videobuf(struct videobuf_queue *q,
                              struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
 
        videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev,
@@ -719,7 +718,7 @@ static void mx27_camera_emma_buf_init(struct soc_camera_device *icd,
                int bytesperline)
 {
        struct soc_camera_host *ici =
-               to_soc_camera_host(icd->dev.parent);
+               to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
 
        writel(pcdev->discard_buffer_dma,
@@ -772,7 +771,7 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd,
                __u32 pixfmt)
 {
        struct soc_camera_host *ici =
-               to_soc_camera_host(icd->dev.parent);
+               to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
        unsigned long camera_flags, common_flags;
        int ret = 0;
@@ -891,7 +890,7 @@ static int mx2_camera_set_crop(struct soc_camera_device *icd,
        if (ret < 0)
                return ret;
 
-       dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n",
+       dev_dbg(icd->parent, "Sensor cropped %dx%d\n",
                mf.width, mf.height);
 
        icd->user_width         = mf.width;
@@ -911,7 +910,7 @@ static int mx2_camera_set_fmt(struct soc_camera_device *icd,
 
        xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
        if (!xlate) {
-               dev_warn(icd->dev.parent, "Format %x not found\n",
+               dev_warn(icd->parent, "Format %x not found\n",
                                pix->pixelformat);
                return -EINVAL;
        }
@@ -951,7 +950,7 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
 
        xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
        if (pixfmt && !xlate) {
-               dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt);
+               dev_warn(icd->parent, "Format %x not found\n", pixfmt);
                return -EINVAL;
        }
 
@@ -974,11 +973,16 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
                if (pix->bytesperline < 0)
                        return pix->bytesperline;
                pix->sizeimage = pix->height * pix->bytesperline;
-               if (pix->sizeimage > (4 * 0x3ffff)) { /* CSIRXCNT limit */
-                       dev_warn(icd->dev.parent,
-                                       "Image size (%u) above limit\n",
-                                       pix->sizeimage);
-                       return -EINVAL;
+               /* Check against the CSIRXCNT limit */
+               if (pix->sizeimage > 4 * 0x3ffff) {
+                       /* Adjust geometry, preserve aspect ratio */
+                       unsigned int new_height = int_sqrt(4 * 0x3ffff *
+                                       pix->height / pix->bytesperline);
+                       pix->width = new_height * pix->width / pix->height;
+                       pix->height = new_height;
+                       pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
+                                                       xlate->host_fmt);
+                       BUG_ON(pix->bytesperline < 0);
                }
        }
 
@@ -996,7 +1000,7 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
        if (mf.field == V4L2_FIELD_ANY)
                mf.field = V4L2_FIELD_NONE;
        if (mf.field != V4L2_FIELD_NONE) {
-               dev_err(icd->dev.parent, "Field type %d unsupported.\n",
+               dev_err(icd->parent, "Field type %d unsupported.\n",
                                mf.field);
                return -EINVAL;
        }
@@ -1014,7 +1018,6 @@ static int mx2_camera_querycap(struct soc_camera_host *ici,
 {
        /* cap->name is set by the friendly caller:-> */
        strlcpy(cap->card, MX2_CAM_DRIVER_DESCRIPTION, sizeof(cap->card));
-       cap->version = MX2_CAM_VERSION_CODE;
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 
        return 0;
@@ -1523,3 +1526,4 @@ module_exit(mx2_camera_exit);
 MODULE_DESCRIPTION("i.MX27/i.MX25 SoC Camera Host driver");
 MODULE_AUTHOR("Sascha Hauer <sha@pengutronix.de>");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(MX2_CAM_VERSION);
index c7680eb..c045b47 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
@@ -195,7 +194,7 @@ static int mx3_videobuf_setup(struct vb2_queue *vq,
                        unsigned long sizes[], void *alloc_ctxs[])
 {
        struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
                                                icd->current_fmt->host_fmt);
@@ -224,7 +223,7 @@ static int mx3_videobuf_setup(struct vb2_queue *vq,
 static int mx3_videobuf_prepare(struct vb2_buffer *vb)
 {
        struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
        struct scatterlist *sg;
@@ -242,7 +241,7 @@ static int mx3_videobuf_prepare(struct vb2_buffer *vb)
        new_size = bytes_per_line * icd->user_height;
 
        if (vb2_plane_size(vb, 0) < new_size) {
-               dev_err(icd->dev.parent, "Buffer too small (%lu < %zu)\n",
+               dev_err(icd->parent, "Buffer too small (%lu < %zu)\n",
                        vb2_plane_size(vb, 0), new_size);
                return -ENOBUFS;
        }
@@ -284,7 +283,7 @@ static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc)
 static void mx3_videobuf_queue(struct vb2_buffer *vb)
 {
        struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        struct mx3_camera_buffer *buf = to_mx3_vb(vb);
        struct dma_async_tx_descriptor *txd = buf->txd;
@@ -337,7 +336,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)
        spin_unlock_irq(&mx3_cam->lock);
 
        cookie = txd->tx_submit(txd);
-       dev_dbg(icd->dev.parent, "Submitted cookie %d DMA 0x%08x\n",
+       dev_dbg(icd->parent, "Submitted cookie %d DMA 0x%08x\n",
                cookie, sg_dma_address(&buf->sg));
 
        if (cookie >= 0)
@@ -358,13 +357,13 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)
 static void mx3_videobuf_release(struct vb2_buffer *vb)
 {
        struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        struct mx3_camera_buffer *buf = to_mx3_vb(vb);
        struct dma_async_tx_descriptor *txd = buf->txd;
        unsigned long flags;
 
-       dev_dbg(icd->dev.parent,
+       dev_dbg(icd->parent,
                "Release%s DMA 0x%08x, queue %sempty\n",
                mx3_cam->active == buf ? " active" : "", sg_dma_address(&buf->sg),
                list_empty(&buf->queue) ? "" : "not ");
@@ -403,7 +402,7 @@ static int mx3_videobuf_init(struct vb2_buffer *vb)
 static int mx3_stop_streaming(struct vb2_queue *q)
 {
        struct soc_camera_device *icd = soc_camera_from_vb2q(q);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
        struct dma_chan *chan;
@@ -499,7 +498,7 @@ static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam,
 
        clk_enable(mx3_cam->clk);
        rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk);
-       dev_dbg(icd->dev.parent, "Set SENS_CONF to %x, rate %ld\n", conf, rate);
+       dev_dbg(icd->parent, "Set SENS_CONF to %x, rate %ld\n", conf, rate);
        if (rate)
                clk_set_rate(mx3_cam->clk, rate);
 }
@@ -507,7 +506,7 @@ static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam,
 /* Called with .video_lock held */
 static int mx3_camera_add_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
 
        if (mx3_cam->icd)
@@ -517,7 +516,7 @@ static int mx3_camera_add_device(struct soc_camera_device *icd)
 
        mx3_cam->icd = icd;
 
-       dev_info(icd->dev.parent, "MX3 Camera driver attached to camera %d\n",
+       dev_info(icd->parent, "MX3 Camera driver attached to camera %d\n",
                 icd->devnum);
 
        return 0;
@@ -526,7 +525,7 @@ static int mx3_camera_add_device(struct soc_camera_device *icd)
 /* Called with .video_lock held */
 static void mx3_camera_remove_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        struct idmac_channel **ichan = &mx3_cam->idmac_channel[0];
 
@@ -541,7 +540,7 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd)
 
        mx3_cam->icd = NULL;
 
-       dev_info(icd->dev.parent, "MX3 Camera driver detached from camera %d\n",
+       dev_info(icd->parent, "MX3 Camera driver detached from camera %d\n",
                 icd->devnum);
 }
 
@@ -608,12 +607,12 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam,
 static int mx3_camera_try_bus_param(struct soc_camera_device *icd,
                                    const unsigned int depth)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        unsigned long bus_flags, camera_flags;
        int ret = test_platform_param(mx3_cam, depth, &bus_flags);
 
-       dev_dbg(icd->dev.parent, "request bus width %d bit: %d\n", depth, ret);
+       dev_dbg(icd->parent, "request bus width %d bit: %d\n", depth, ret);
 
        if (ret < 0)
                return ret;
@@ -622,7 +621,7 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd,
 
        ret = soc_camera_bus_param_compatible(camera_flags, bus_flags);
        if (ret < 0)
-               dev_warn(icd->dev.parent,
+               dev_warn(icd->parent,
                         "Flags incompatible: camera %lx, host %lx\n",
                         camera_flags, bus_flags);
 
@@ -676,7 +675,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id
                                  struct soc_camera_format_xlate *xlate)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct device *dev = icd->dev.parent;
+       struct device *dev = icd->parent;
        int formats = 0, ret;
        enum v4l2_mbus_pixelcode code;
        const struct soc_mbus_pixelfmt *fmt;
@@ -688,7 +687,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id
 
        fmt = soc_mbus_get_fmtdesc(code);
        if (!fmt) {
-               dev_warn(icd->dev.parent,
+               dev_warn(icd->parent,
                         "Unsupported format code #%u: %d\n", idx, code);
                return 0;
        }
@@ -816,7 +815,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd,
                               struct v4l2_crop *a)
 {
        struct v4l2_rect *rect = &a->c;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct v4l2_mbus_framefmt mf;
@@ -849,7 +848,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd,
                configure_geometry(mx3_cam, mf.width, mf.height,
                                   icd->current_fmt->host_fmt);
 
-       dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n",
+       dev_dbg(icd->parent, "Sensor cropped %dx%d\n",
                mf.width, mf.height);
 
        icd->user_width         = mf.width;
@@ -861,7 +860,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd,
 static int mx3_camera_set_fmt(struct soc_camera_device *icd,
                              struct v4l2_format *f)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        const struct soc_camera_format_xlate *xlate;
@@ -871,13 +870,13 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
 
        xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
        if (!xlate) {
-               dev_warn(icd->dev.parent, "Format %x not found\n",
+               dev_warn(icd->parent, "Format %x not found\n",
                         pix->pixelformat);
                return -EINVAL;
        }
 
        stride_align(&pix->width);
-       dev_dbg(icd->dev.parent, "Set format %dx%d\n", pix->width, pix->height);
+       dev_dbg(icd->parent, "Set format %dx%d\n", pix->width, pix->height);
 
        /*
         * Might have to perform a complete interface initialisation like in
@@ -913,13 +912,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
        pix->colorspace         = mf.colorspace;
        icd->current_fmt        = xlate;
 
-       pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
-                                                   xlate->host_fmt);
-       if (pix->bytesperline < 0)
-               return pix->bytesperline;
-       pix->sizeimage = pix->height * pix->bytesperline;
-
-       dev_dbg(icd->dev.parent, "Sensor set %dx%d\n", pix->width, pix->height);
+       dev_dbg(icd->parent, "Sensor set %dx%d\n", pix->width, pix->height);
 
        return ret;
 }
@@ -936,7 +929,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd,
 
        xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
        if (pixfmt && !xlate) {
-               dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt);
+               dev_warn(icd->parent, "Format %x not found\n", pixfmt);
                return -EINVAL;
        }
 
@@ -946,12 +939,6 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd,
        if (pix->width > 4096)
                pix->width = 4096;
 
-       pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
-                                                   xlate->host_fmt);
-       if (pix->bytesperline < 0)
-               return pix->bytesperline;
-       pix->sizeimage = pix->height * pix->bytesperline;
-
        /* limit to sensor capabilities */
        mf.width        = pix->width;
        mf.height       = pix->height;
@@ -974,7 +961,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd,
        case V4L2_FIELD_NONE:
                break;
        default:
-               dev_err(icd->dev.parent, "Field type %d unsupported.\n",
+               dev_err(icd->parent, "Field type %d unsupported.\n",
                        mf.field);
                ret = -EINVAL;
        }
@@ -1000,7 +987,6 @@ static int mx3_camera_querycap(struct soc_camera_host *ici,
 {
        /* cap->name is set by the firendly caller:-> */
        strlcpy(cap->card, "i.MX3x Camera", sizeof(cap->card));
-       cap->version = KERNEL_VERSION(0, 2, 2);
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 
        return 0;
@@ -1008,7 +994,7 @@ static int mx3_camera_querycap(struct soc_camera_host *ici,
 
 static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        unsigned long bus_flags, camera_flags, common_flags;
        u32 dw, sens_conf;
@@ -1016,7 +1002,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
        int buswidth;
        int ret;
        const struct soc_camera_format_xlate *xlate;
-       struct device *dev = icd->dev.parent;
+       struct device *dev = icd->parent;
 
        fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
        if (!fmt)
@@ -1325,4 +1311,5 @@ module_exit(mx3_camera_exit);
 MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver");
 MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
 MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.2.3");
 MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME);
index e63233f..390ab09 100644 (file)
@@ -1,11 +1,14 @@
+config VIDEO_OMAP2_VOUT_VRFB
+       bool
+
 config VIDEO_OMAP2_VOUT
        tristate "OMAP2/OMAP3 V4L2-Display driver"
        depends on ARCH_OMAP2 || ARCH_OMAP3
        select VIDEOBUF_GEN
        select VIDEOBUF_DMA_CONTIG
        select OMAP2_DSS
-       select OMAP2_VRAM
-       select OMAP2_VRFB
+       select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
+       select VIDEO_OMAP2_VOUT_VRFB if VIDEO_OMAP2_VOUT && OMAP2_VRFB
        default n
        ---help---
          V4L2 Display driver support for OMAP2/3 based boards.
index b287880..fc410b4 100644 (file)
@@ -4,4 +4,5 @@
 
 # OMAP2/3 Display driver
 omap-vout-y := omap_vout.o omap_voutlib.o
+omap-vout-$(CONFIG_VIDEO_OMAP2_VOUT_VRFB) += omap_vout_vrfb.o
 obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout.o
index a647894..b5ef362 100644 (file)
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
 #include <linux/irq.h>
 #include <linux/videodev2.h>
-#include <linux/slab.h>
+#include <linux/dma-mapping.h>
 
 #include <media/videobuf-dma-contig.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 
 #include <plat/dma.h>
-#include <plat/vram.h>
 #include <plat/vrfb.h>
 #include <video/omapdss.h>
 
 #include "omap_voutlib.h"
 #include "omap_voutdef.h"
+#include "omap_vout_vrfb.h"
 
 MODULE_AUTHOR("Texas Instruments");
 MODULE_DESCRIPTION("OMAP Video for Linux Video out driver");
 MODULE_LICENSE("GPL");
 
-
 /* Driver Configuration macros */
 #define VOUT_NAME              "omap_vout"
 
@@ -65,31 +63,6 @@ enum omap_vout_channels {
        OMAP_VIDEO2,
 };
 
-enum dma_channel_state {
-       DMA_CHAN_NOT_ALLOTED,
-       DMA_CHAN_ALLOTED,
-};
-
-#define QQVGA_WIDTH            160
-#define QQVGA_HEIGHT           120
-
-/* Max Resolution supported by the driver */
-#define VID_MAX_WIDTH          1280    /* Largest width */
-#define VID_MAX_HEIGHT         720     /* Largest height */
-
-/* Mimimum requirement is 2x2 for DSS */
-#define VID_MIN_WIDTH          2
-#define VID_MIN_HEIGHT         2
-
-/* 2048 x 2048 is max res supported by OMAP display controller */
-#define MAX_PIXELS_PER_LINE     2048
-
-#define VRFB_TX_TIMEOUT         1000
-#define VRFB_NUM_BUFS          4
-
-/* Max buffer size tobe allocated during init */
-#define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4)
-
 static struct videobuf_queue_ops video_vbq_ops;
 /* Variables configurable through module params*/
 static u32 video1_numbuffers = 3;
@@ -171,84 +144,6 @@ static const struct v4l2_fmtdesc omap_formats[] = {
 
 #define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats))
 
-/*
- * Allocate buffers
- */
-static unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr)
-{
-       u32 order, size;
-       unsigned long virt_addr, addr;
-
-       size = PAGE_ALIGN(buf_size);
-       order = get_order(size);
-       virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, order);
-       addr = virt_addr;
-
-       if (virt_addr) {
-               while (size > 0) {
-                       SetPageReserved(virt_to_page(addr));
-                       addr += PAGE_SIZE;
-                       size -= PAGE_SIZE;
-               }
-       }
-       *phys_addr = (u32) virt_to_phys((void *) virt_addr);
-       return virt_addr;
-}
-
-/*
- * Free buffers
- */
-static void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size)
-{
-       u32 order, size;
-       unsigned long addr = virtaddr;
-
-       size = PAGE_ALIGN(buf_size);
-       order = get_order(size);
-
-       while (size > 0) {
-               ClearPageReserved(virt_to_page(addr));
-               addr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-       free_pages((unsigned long) virtaddr, order);
-}
-
-/*
- * Function for allocating video buffers
- */
-static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout,
-               unsigned int *count, int startindex)
-{
-       int i, j;
-
-       for (i = 0; i < *count; i++) {
-               if (!vout->smsshado_virt_addr[i]) {
-                       vout->smsshado_virt_addr[i] =
-                               omap_vout_alloc_buffer(vout->smsshado_size,
-                                               &vout->smsshado_phy_addr[i]);
-               }
-               if (!vout->smsshado_virt_addr[i] && startindex != -1) {
-                       if (V4L2_MEMORY_MMAP == vout->memory && i >= startindex)
-                               break;
-               }
-               if (!vout->smsshado_virt_addr[i]) {
-                       for (j = 0; j < i; j++) {
-                               omap_vout_free_buffer(
-                                               vout->smsshado_virt_addr[j],
-                                               vout->smsshado_size);
-                               vout->smsshado_virt_addr[j] = 0;
-                               vout->smsshado_phy_addr[j] = 0;
-                       }
-                       *count = 0;
-                       return -ENOMEM;
-               }
-               memset((void *) vout->smsshado_virt_addr[i], 0,
-                               vout->smsshado_size);
-       }
-       return 0;
-}
-
 /*
  * Try format
  */
@@ -341,74 +236,10 @@ static u32 omap_vout_uservirt_to_phys(u32 virtp)
        return physp;
 }
 
-/*
- * Wakes up the application once the DMA transfer to VRFB space is completed.
- */
-static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data)
-{
-       struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data;
-
-       t->tx_status = 1;
-       wake_up_interruptible(&t->wait);
-}
-
-/*
- * Release the VRFB context once the module exits
- */
-static void omap_vout_release_vrfb(struct omap_vout_device *vout)
-{
-       int i;
-
-       for (i = 0; i < VRFB_NUM_BUFS; i++)
-               omap_vrfb_release_ctx(&vout->vrfb_context[i]);
-
-       if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) {
-               vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
-               omap_free_dma(vout->vrfb_dma_tx.dma_ch);
-       }
-}
-
-/*
- * Return true if rotation is 90 or 270
- */
-static inline int rotate_90_or_270(const struct omap_vout_device *vout)
-{
-       return (vout->rotation == dss_rotation_90_degree ||
-                       vout->rotation == dss_rotation_270_degree);
-}
-
-/*
- * Return true if rotation is enabled
- */
-static inline int rotation_enabled(const struct omap_vout_device *vout)
-{
-       return vout->rotation || vout->mirror;
-}
-
-/*
- * Reverse the rotation degree if mirroring is enabled
- */
-static inline int calc_rotation(const struct omap_vout_device *vout)
-{
-       if (!vout->mirror)
-               return vout->rotation;
-
-       switch (vout->rotation) {
-       case dss_rotation_90_degree:
-               return dss_rotation_270_degree;
-       case dss_rotation_270_degree:
-               return dss_rotation_90_degree;
-       case dss_rotation_180_degree:
-               return dss_rotation_0_degree;
-       default:
-               return dss_rotation_180_degree;
-       }
-}
-
 /*
  * Free the V4L2 buffers
  */
-static void omap_vout_free_buffers(struct omap_vout_device *vout)
+void omap_vout_free_buffers(struct omap_vout_device *vout)
 {
        int i, numbuffers;
 
@@ -424,52 +255,6 @@ static void omap_vout_free_buffers(struct omap_vout_device *vout)
        }
 }
 
-/*
- * Free VRFB buffers
- */
-static void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout)
-{
-       int j;
-
-       for (j = 0; j < VRFB_NUM_BUFS; j++) {
-               omap_vout_free_buffer(vout->smsshado_virt_addr[j],
-                               vout->smsshado_size);
-               vout->smsshado_virt_addr[j] = 0;
-               vout->smsshado_phy_addr[j] = 0;
-       }
-}
-
-/*
- * Allocate the buffers for the VRFB space.  Data is copied from V4L2
- * buffers to the VRFB buffers using the DMA engine.
- */
-static int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
-                         unsigned int *count, unsigned int startindex)
-{
-       int i;
-       bool yuv_mode;
-
-       /* Allocate the VRFB buffers only if the buffers are not
-        * allocated during init time.
-        */
-       if ((rotation_enabled(vout)) && !vout->vrfb_static_allocation)
-               if (omap_vout_allocate_vrfb_buffers(vout, count, startindex))
-                       return -ENOMEM;
-
-       if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 ||
-                       vout->dss_mode == OMAP_DSS_COLOR_UYVY)
-               yuv_mode = true;
-       else
-               yuv_mode = false;
-
-       for (i = 0; i < *count; i++)
-               omap_vrfb_setup(&vout->vrfb_context[i],
-                               vout->smsshado_phy_addr[i], vout->pix.width,
-                               vout->pix.height, vout->bpp, yuv_mode);
-
-       return 0;
-}
-
 /*
  * Convert V4L2 rotation to DSS rotation
  *     V4L2 understand 0, 90, 180, 270.
@@ -499,124 +284,38 @@ static int v4l2_rot_to_dss_rot(int v4l2_rotation,
        return ret;
 }
 
-/*
- * Calculate the buffer offsets from which the streaming should
- * start. This offset calculation is mainly required because of
- * the VRFB 32 pixels alignment with rotation.
- */
 static int omap_vout_calculate_offset(struct omap_vout_device *vout)
 {
-       struct omap_overlay *ovl;
-       enum dss_rotation rotation;
        struct omapvideo_info *ovid;
-       bool mirroring = vout->mirror;
-       struct omap_dss_device *cur_display;
        struct v4l2_rect *crop = &vout->crop;
        struct v4l2_pix_format *pix = &vout->pix;
        int *cropped_offset = &vout->cropped_offset;
-       int vr_ps = 1, ps = 2, temp_ps = 2;
-       int offset = 0, ctop = 0, cleft = 0, line_length = 0;
+       int ps = 2, line_length = 0;
 
        ovid = &vout->vid_info;
-       ovl = ovid->overlays[0];
-       /* get the display device attached to the overlay */
-       if (!ovl->manager || !ovl->manager->device)
-               return -1;
 
-       cur_display = ovl->manager->device;
-       rotation = calc_rotation(vout);
+       if (ovid->rotation_type == VOUT_ROT_VRFB) {
+               omap_vout_calculate_vrfb_offset(vout);
+       } else {
+               vout->line_length = line_length = pix->width;
 
-       if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
-                       V4L2_PIX_FMT_UYVY == pix->pixelformat) {
-               if (rotation_enabled(vout)) {
-                       /*
-                        * ps    - Actual pixel size for YUYV/UYVY for
-                        *         VRFB/Mirroring is 4 bytes
-                        * vr_ps - Virtually pixel size for YUYV/UYVY is
-                        *         2 bytes
-                        */
+               if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
+                       V4L2_PIX_FMT_UYVY == pix->pixelformat)
+                       ps = 2;
+               else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat)
                        ps = 4;
-                       vr_ps = 2;
-               } else {
-                       ps = 2; /* otherwise the pixel size is 2 byte */
-               }
-       } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) {
-               ps = 4;
-       } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) {
-               ps = 3;
-       }
-       vout->ps = ps;
-       vout->vr_ps = vr_ps;
-
-       if (rotation_enabled(vout)) {
-               line_length = MAX_PIXELS_PER_LINE;
-               ctop = (pix->height - crop->height) - crop->top;
-               cleft = (pix->width - crop->width) - crop->left;
-       } else {
-               line_length = pix->width;
-       }
-       vout->line_length = line_length;
-       switch (rotation) {
-       case dss_rotation_90_degree:
-               offset = vout->vrfb_context[0].yoffset *
-                       vout->vrfb_context[0].bytespp;
-               temp_ps = ps / vr_ps;
-               if (mirroring == 0) {
-                       *cropped_offset = offset + line_length *
-                               temp_ps * cleft + crop->top * temp_ps;
-               } else {
-                       *cropped_offset = offset + line_length * temp_ps *
-                               cleft + crop->top * temp_ps + (line_length *
-                               ((crop->width / (vr_ps)) - 1) * ps);
-               }
-               break;
-       case dss_rotation_180_degree:
-               offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset *
-                       vout->vrfb_context[0].bytespp) +
-                       (vout->vrfb_context[0].xoffset *
-                       vout->vrfb_context[0].bytespp));
-               if (mirroring == 0) {
-                       *cropped_offset = offset + (line_length * ps * ctop) +
-                               (cleft / vr_ps) * ps;
+               else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat)
+                       ps = 3;
 
-               } else {
-                       *cropped_offset = offset + (line_length * ps * ctop) +
-                               (cleft / vr_ps) * ps + (line_length *
-                               (crop->height - 1) * ps);
-               }
-               break;
-       case dss_rotation_270_degree:
-               offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset *
-                       vout->vrfb_context[0].bytespp;
-               temp_ps = ps / vr_ps;
-               if (mirroring == 0) {
-                       *cropped_offset = offset + line_length *
-                           temp_ps * crop->left + ctop * ps;
-               } else {
-                       *cropped_offset = offset + line_length *
-                               temp_ps * crop->left + ctop * ps +
-                               (line_length * ((crop->width / vr_ps) - 1) *
-                                ps);
-               }
-               break;
-       case dss_rotation_0_degree:
-               if (mirroring == 0) {
-                       *cropped_offset = (line_length * ps) *
-                               crop->top + (crop->left / vr_ps) * ps;
-               } else {
-                       *cropped_offset = (line_length * ps) *
-                               crop->top + (crop->left / vr_ps) * ps +
-                               (line_length * (crop->height - 1) * ps);
-               }
-               break;
-       default:
-               *cropped_offset = (line_length * ps * crop->top) /
-                       vr_ps + (crop->left * ps) / vr_ps +
-                       ((crop->width / vr_ps) - 1) * ps;
-               break;
+               vout->ps = ps;
+
+               *cropped_offset = (line_length * ps) *
+                       crop->top + crop->left * ps;
        }
+
        v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n",
-                       __func__, *cropped_offset);
+                       __func__, vout->cropped_offset);
+
        return 0;
 }
 
@@ -664,7 +363,7 @@ static int video_mode_to_dss_mode(struct omap_vout_device *vout)
 /*
  * Setup the overlay
  */
-int omapvid_setup_overlay(struct omap_vout_device *vout,
+static int omapvid_setup_overlay(struct omap_vout_device *vout,
                struct omap_overlay *ovl, int posx, int posy, int outw,
                int outh, u32 addr)
 {
@@ -687,7 +386,7 @@ int omapvid_setup_overlay(struct omap_vout_device *vout,
        /* Setup the input plane parameters according to
         * rotation value selected.
         */
-       if (rotate_90_or_270(vout)) {
+       if (is_rotation_90_or_270(vout)) {
                cropheight = vout->crop.width;
                cropwidth = vout->crop.height;
                pixheight = vout->pix.width;
@@ -711,7 +410,7 @@ int omapvid_setup_overlay(struct omap_vout_device *vout,
        info.out_width = outw;
        info.out_height = outh;
        info.global_alpha = vout->win.global_alpha;
-       if (!rotation_enabled(vout)) {
+       if (!is_rotation_enabled(vout)) {
                info.rotation = 0;
                info.rotation_type = OMAP_DSS_ROT_DMA;
                info.screen_width = pixwidth;
@@ -744,7 +443,7 @@ setup_ovl_err:
 /*
  * Initialize the overlay structure
  */
-int omapvid_init(struct omap_vout_device *vout, u32 addr)
+static int omapvid_init(struct omap_vout_device *vout, u32 addr)
 {
        int ret = 0, i;
        struct v4l2_window *win;
@@ -809,7 +508,7 @@ omapvid_init_err:
 /*
  * Apply the changes set the go bit of DSS
  */
-int omapvid_apply_changes(struct omap_vout_device *vout)
+static int omapvid_apply_changes(struct omap_vout_device *vout)
 {
        int i;
        struct omap_overlay *ovl;
@@ -825,7 +524,7 @@ int omapvid_apply_changes(struct omap_vout_device *vout)
        return 0;
 }
 
-void omap_vout_isr(void *arg, unsigned int irqstatus)
+static void omap_vout_isr(void *arg, unsigned int irqstatus)
 {
        int ret;
        u32 addr, fid;
@@ -848,10 +547,20 @@ void omap_vout_isr(void *arg, unsigned int irqstatus)
 
        spin_lock(&vout->vbq_lock);
        do_gettimeofday(&timevalue);
-       if (cur_display->type == OMAP_DISPLAY_TYPE_DPI) {
-               if (!(irqstatus & DISPC_IRQ_VSYNC))
-                       goto vout_isr_err;
 
+       if (cur_display->type != OMAP_DISPLAY_TYPE_VENC) {
+               switch (cur_display->type) {
+               case OMAP_DISPLAY_TYPE_DPI:
+                       if (!(irqstatus & (DISPC_IRQ_VSYNC | DISPC_IRQ_VSYNC2)))
+                               goto vout_isr_err;
+                       break;
+               case OMAP_DISPLAY_TYPE_HDMI:
+                       if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN))
+                               goto vout_isr_err;
+                       break;
+               default:
+                       goto vout_isr_err;
+               }
                if (!vout->first_int && (vout->cur_frm != vout->next_frm)) {
                        vout->cur_frm->ts = timevalue;
                        vout->cur_frm->state = VIDEOBUF_DONE;
@@ -875,7 +584,7 @@ void omap_vout_isr(void *arg, unsigned int irqstatus)
                ret = omapvid_init(vout, addr);
                if (ret)
                        printk(KERN_ERR VOUT_NAME
-                                       "failed to set overlay info\n");
+                               "failed to set overlay info\n");
                /* Enable the pipeline and set the Go bit */
                ret = omapvid_apply_changes(vout);
                if (ret)
@@ -954,6 +663,7 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
        int startindex = 0, i, j;
        u32 phy_addr = 0, virt_addr = 0;
        struct omap_vout_device *vout = q->priv_data;
+       struct omapvideo_info *ovid = &vout->vid_info;
 
        if (!vout)
                return -EINVAL;
@@ -966,13 +676,10 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
        if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex)
                *count = startindex;
 
-       if ((rotation_enabled(vout)) && *count > VRFB_NUM_BUFS)
-               *count = VRFB_NUM_BUFS;
-
-       /* If rotation is enabled, allocate memory for VRFB space also */
-       if (rotation_enabled(vout))
+       if (ovid->rotation_type == VOUT_ROT_VRFB) {
                if (omap_vout_vrfb_buffer_setup(vout, count, startindex))
                        return -ENOMEM;
+       }
 
        if (V4L2_MEMORY_MMAP != vout->memory)
                return 0;
@@ -996,8 +703,11 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
                virt_addr = omap_vout_alloc_buffer(vout->buffer_size,
                                &phy_addr);
                if (!virt_addr) {
-                       if (!rotation_enabled(vout))
+                       if (ovid->rotation_type == VOUT_ROT_NONE) {
                                break;
+                       } else {
+                               if (!is_rotation_enabled(vout))
+                                       break;
                        /* Free the VRFB buffers if no space for V4L2 buffers */
                        for (j = i; j < *count; j++) {
                                omap_vout_free_buffer(
@@ -1005,6 +715,7 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
                                                vout->smsshado_size);
                                vout->smsshado_virt_addr[j] = 0;
                                vout->smsshado_phy_addr[j] = 0;
+                               }
                        }
                }
                vout->buf_virt_addr[i] = virt_addr;
@@ -1017,9 +728,9 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
 
 /*
  * Free the V4L2 buffers additionally allocated than default
- * number of buffers and free all the VRFB buffers
+ * number of buffers
  */
-static void omap_vout_free_allbuffers(struct omap_vout_device *vout)
+static void omap_vout_free_extra_buffers(struct omap_vout_device *vout)
 {
        int num_buffers = 0, i;
 
@@ -1034,20 +745,6 @@ static void omap_vout_free_allbuffers(struct omap_vout_device *vout)
                vout->buf_virt_addr[i] = 0;
                vout->buf_phy_addr[i] = 0;
        }
-       /* Free the VRFB buffers only if they are allocated
-        * during reqbufs.  Don't free if init time allocated
-        */
-       if (!vout->vrfb_static_allocation) {
-               for (i = 0; i < VRFB_NUM_BUFS; i++) {
-                       if (vout->smsshado_virt_addr[i]) {
-                               omap_vout_free_buffer(
-                                               vout->smsshado_virt_addr[i],
-                                               vout->smsshado_size);
-                               vout->smsshado_virt_addr[i] = 0;
-                               vout->smsshado_phy_addr[i] = 0;
-                       }
-               }
-       }
        vout->buffer_allocated = num_buffers;
 }
 
@@ -1059,16 +756,11 @@ static void omap_vout_free_allbuffers(struct omap_vout_device *vout)
  * buffer into VRFB memory space before giving it to the DSS.
  */
 static int omap_vout_buffer_prepare(struct videobuf_queue *q,
-                           struct videobuf_buffer *vb,
-                           enum v4l2_field field)
+                       struct videobuf_buffer *vb,
+                       enum v4l2_field field)
 {
-       dma_addr_t dmabuf;
-       struct vid_vrfb_dma *tx;
-       enum dss_rotation rotation;
        struct omap_vout_device *vout = q->priv_data;
-       u32 dest_frame_index = 0, src_element_index = 0;
-       u32 dest_element_index = 0, src_frame_index = 0;
-       u32 elem_count = 0, frame_count = 0, pixsize = 2;
+       struct omapvideo_info *ovid = &vout->vid_info;
 
        if (VIDEOBUF_NEEDS_INIT == vb->state) {
                vb->width = vout->pix.width;
@@ -1087,66 +779,24 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,
                vout->queued_buf_addr[vb->i] = (u8 *)
                        omap_vout_uservirt_to_phys(vb->baddr);
        } else {
-               vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i];
-       }
+               u32 addr, dma_addr;
+               unsigned long size;
 
-       if (!rotation_enabled(vout))
-               return 0;
+               addr = (unsigned long) vout->buf_virt_addr[vb->i];
+               size = (unsigned long) vb->size;
 
-       dmabuf = vout->buf_phy_addr[vb->i];
-       /* If rotation is enabled, copy input buffer into VRFB
-        * memory space using DMA. We are copying input buffer
-        * into VRFB memory space of desired angle and DSS will
-        * read image VRFB memory for 0 degree angle
-        */
-       pixsize = vout->bpp * vout->vrfb_bpp;
-       /*
-        * DMA transfer in double index mode
-        */
+               dma_addr = dma_map_single(vout->vid_dev->v4l2_dev.dev, (void *) addr,
+                               size, DMA_TO_DEVICE);
+               if (dma_mapping_error(vout->vid_dev->v4l2_dev.dev, dma_addr))
+                       v4l2_err(&vout->vid_dev->v4l2_dev, "dma_map_single failed\n");
 
-       /* Frame index */
-       dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) -
-                       (vout->pix.width * vout->bpp)) + 1;
-
-       /* Source and destination parameters */
-       src_element_index = 0;
-       src_frame_index = 0;
-       dest_element_index = 1;
-       /* Number of elements per frame */
-       elem_count = vout->pix.width * vout->bpp;
-       frame_count = vout->pix.height;
-       tx = &vout->vrfb_dma_tx;
-       tx->tx_status = 0;
-       omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32,
-                       (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT,
-                       tx->dev_id, 0x0);
-       /* src_port required only for OMAP1 */
-       omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
-                       dmabuf, src_element_index, src_frame_index);
-       /*set dma source burst mode for VRFB */
-       omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
-       rotation = calc_rotation(vout);
-
-       /* dest_port required only for OMAP1 */
-       omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX,
-                       vout->vrfb_context[vb->i].paddr[0], dest_element_index,
-                       dest_frame_index);
-       /*set dma dest burst mode for VRFB */
-       omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
-       omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0);
-
-       omap_start_dma(tx->dma_ch);
-       interruptible_sleep_on_timeout(&tx->wait, VRFB_TX_TIMEOUT);
-
-       if (tx->tx_status == 0) {
-               omap_stop_dma(tx->dma_ch);
-               return -EINVAL;
+               vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i];
        }
-       /* Store buffers physical address into an array. Addresses
-        * from this array will be used to configure DSS */
-       vout->queued_buf_addr[vb->i] = (u8 *)
-               vout->vrfb_context[vb->i].paddr[rotation];
-       return 0;
+
+       if (ovid->rotation_type == VOUT_ROT_VRFB)
+               return omap_vout_prepare_vrfb(vout, vb);
+       else
+               return 0;
 }
 
 /*
@@ -1298,7 +948,15 @@ static int omap_vout_release(struct file *file)
                                "Unable to apply changes\n");
 
        /* Free all buffers */
-       omap_vout_free_allbuffers(vout);
+       omap_vout_free_extra_buffers(vout);
+
+       /* Free the VRFB buffers only if they are allocated
+        * during reqbufs.  Don't free if init time allocated
+        */
+       if (ovid->rotation_type == VOUT_ROT_VRFB) {
+               if (!vout->vrfb_static_allocation)
+                       omap_vout_free_vrfb_buffers(vout);
+       }
        videobuf_mmap_free(q);
 
        /* Even if apply changes fails we should continue
@@ -1307,7 +965,7 @@ static int omap_vout_release(struct file *file)
                u32 mask = 0;
 
                mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN |
-                       DISPC_IRQ_EVSYNC_ODD;
+                       DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_VSYNC2;
                omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
                vout->streaming = 0;
 
@@ -1383,10 +1041,7 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *fh,
                        struct v4l2_fmtdesc *fmt)
 {
        int index = fmt->index;
-       enum v4l2_buf_type type = fmt->type;
 
-       fmt->index = index;
-       fmt->type = type;
        if (index >= NUM_OUTPUT_FORMATS)
                return -EINVAL;
 
@@ -1457,7 +1112,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
 
        /* We dont support RGB24-packed mode if vrfb rotation
         * is enabled*/
-       if ((rotation_enabled(vout)) &&
+       if ((is_rotation_enabled(vout)) &&
                        f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
                ret = -EINVAL;
                goto s_fmt_vid_out_exit;
@@ -1465,7 +1120,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
 
        /* get the framebuffer parameters */
 
-       if (rotate_90_or_270(vout)) {
+       if (is_rotation_90_or_270(vout)) {
                vout->fbuf.fmt.height = timing->x_res;
                vout->fbuf.fmt.width = timing->y_res;
        } else {
@@ -1555,10 +1210,7 @@ static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh,
                        struct v4l2_fmtdesc *fmt)
 {
        int index = fmt->index;
-       enum v4l2_buf_type type = fmt->type;
 
-       fmt->index = index;
-       fmt->type = type;
        if (index >= NUM_OUTPUT_FORMATS)
                return -EINVAL;
 
@@ -1645,7 +1297,7 @@ static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
        /* get the display device attached to the overlay */
        timing = &ovl->manager->device->panel.timings;
 
-       if (rotate_90_or_270(vout)) {
+       if (is_rotation_90_or_270(vout)) {
                vout->fbuf.fmt.height = timing->x_res;
                vout->fbuf.fmt.width = timing->y_res;
        } else {
@@ -1725,9 +1377,17 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
        switch (a->id) {
        case V4L2_CID_ROTATE:
        {
+               struct omapvideo_info *ovid;
                int rotation = a->value;
 
+               ovid = &vout->vid_info;
+
                mutex_lock(&vout->lock);
+               if (rotation && ovid->rotation_type == VOUT_ROT_NONE) {
+                       mutex_unlock(&vout->lock);
+                       ret = -ERANGE;
+                       break;
+               }
 
                if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
                        mutex_unlock(&vout->lock);
@@ -1783,6 +1443,11 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
                ovl = ovid->overlays[0];
 
                mutex_lock(&vout->lock);
+               if (mirror && ovid->rotation_type == VOUT_ROT_NONE) {
+                       mutex_unlock(&vout->lock);
+                       ret = -ERANGE;
+                       break;
+               }
 
                if (mirror  && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
                        mutex_unlock(&vout->lock);
@@ -1893,7 +1558,7 @@ static int vidioc_qbuf(struct file *file, void *fh,
                }
        }
 
-       if ((rotation_enabled(vout)) &&
+       if ((is_rotation_enabled(vout)) &&
                        vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED) {
                v4l2_warn(&vout->vid_dev->v4l2_dev,
                                "DMA Channel not allocated for Rotation\n");
@@ -1908,15 +1573,28 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
        struct omap_vout_device *vout = fh;
        struct videobuf_queue *q = &vout->vbq;
 
+       int ret;
+       u32 addr;
+       unsigned long size;
+       struct videobuf_buffer *vb;
+
+       vb = q->bufs[b->index];
+
        if (!vout->streaming)
                return -EINVAL;
 
        if (file->f_flags & O_NONBLOCK)
                /* Call videobuf_dqbuf for non blocking mode */
-               return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
+               ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
        else
                /* Call videobuf_dqbuf for  blocking mode */
-               return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
+               ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
+
+       addr = (unsigned long) vout->buf_phy_addr[vb->i];
+       size = (unsigned long) vb->size;
+       dma_unmap_single(vout->vid_dev->v4l2_dev.dev,  addr,
+                               size, DMA_TO_DEVICE);
+       return ret;
 }
 
 static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
@@ -1965,7 +1643,8 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
        addr = (unsigned long) vout->queued_buf_addr[vout->cur_frm->i]
                + vout->cropped_offset;
 
-       mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
+       mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
+               | DISPC_IRQ_VSYNC2;
 
        omap_dispc_register_isr(omap_vout_isr, vout, mask);
 
@@ -2015,7 +1694,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
                return -EINVAL;
 
        vout->streaming = 0;
-       mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
+       mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
+               | DISPC_IRQ_VSYNC2;
 
        omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
 
@@ -2228,7 +1908,8 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
        vout->mirror = 0;
        vout->control[2].id = V4L2_CID_HFLIP;
        vout->control[2].value = 0;
-       vout->vrfb_bpp = 2;
+       if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
+               vout->vrfb_bpp = 2;
 
        control[1].id = V4L2_CID_BG_COLOR;
        control[1].value = 0;
@@ -2260,17 +1941,15 @@ static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
                int vid_num)
 {
        u32 numbuffers;
-       int ret = 0, i, j;
-       int image_width, image_height;
-       struct video_device *vfd;
+       int ret = 0, i;
+       struct omapvideo_info *ovid;
        struct omap_vout_device *vout;
-       int static_vrfb_allocation = 0, vrfb_num_bufs = VRFB_NUM_BUFS;
        struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
        struct omap2video_device *vid_dev =
                container_of(v4l2_dev, struct omap2video_device, v4l2_dev);
 
        vout = vid_dev->vouts[vid_num];
-       vfd = vout->vfd;
+       ovid = &vout->vid_info;
 
        numbuffers = (vid_num == 0) ? video1_numbuffers : video2_numbuffers;
        vout->buffer_size = (vid_num == 0) ? video1_bufsize : video2_bufsize;
@@ -2287,66 +1966,16 @@ static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
                }
        }
 
-       for (i = 0; i < VRFB_NUM_BUFS; i++) {
-               if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) {
-                       dev_info(&pdev->dev, ": VRFB allocation failed\n");
-                       for (j = 0; j < i; j++)
-                               omap_vrfb_release_ctx(&vout->vrfb_context[j]);
-                       ret = -ENOMEM;
-                       goto free_buffers;
-               }
-       }
        vout->cropped_offset = 0;
 
-       /* Calculate VRFB memory size */
-       /* allocate for worst case size */
-       image_width = VID_MAX_WIDTH / TILE_SIZE;
-       if (VID_MAX_WIDTH % TILE_SIZE)
-               image_width++;
-
-       image_width = image_width * TILE_SIZE;
-       image_height = VID_MAX_HEIGHT / TILE_SIZE;
-
-       if (VID_MAX_HEIGHT % TILE_SIZE)
-               image_height++;
-
-       image_height = image_height * TILE_SIZE;
-       vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2);
-
-       /*
-        * Request and Initialize DMA, for DMA based VRFB transfer
-        */
-       vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE;
-       vout->vrfb_dma_tx.dma_ch = -1;
-       vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED;
-       ret = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX",
-                       omap_vout_vrfb_dma_tx_callback,
-                       (void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch);
-       if (ret < 0) {
-               vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
-               dev_info(&pdev->dev, ": failed to allocate DMA Channel for"
-                               " video%d\n", vfd->minor);
-       }
-       init_waitqueue_head(&vout->vrfb_dma_tx.wait);
-
-       /* Allocate VRFB buffers if selected through bootargs */
-       static_vrfb_allocation = (vid_num == 0) ?
-               vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
-
-       /* statically allocated the VRFB buffer is done through
-          commands line aruments */
-       if (static_vrfb_allocation) {
-               if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) {
-                       ret =  -ENOMEM;
-                       goto release_vrfb_ctx;
-               }
-               vout->vrfb_static_allocation = 1;
+       if (ovid->rotation_type == VOUT_ROT_VRFB) {
+               int static_vrfb_allocation = (vid_num == 0) ?
+                       vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
+               ret = omap_vout_setup_vrfb_bufs(pdev, vid_num,
+                               static_vrfb_allocation);
        }
-       return 0;
 
-release_vrfb_ctx:
-       for (j = 0; j < VRFB_NUM_BUFS; j++)
-               omap_vrfb_release_ctx(&vout->vrfb_context[j]);
+       return ret;
 
 free_buffers:
        for (i = 0; i < numbuffers; i++) {
@@ -2389,6 +2018,10 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
                vout->vid_info.num_overlays = 1;
                vout->vid_info.id = k + 1;
 
+               /* Set VRFB as rotation_type for omap2 and omap3 */
+               if (cpu_is_omap24xx() || cpu_is_omap34xx())
+                       vout->vid_info.rotation_type = VOUT_ROT_VRFB;
+
                /* Setup the default configuration for the video devices
                 */
                if (omap_vout_setup_video_data(vout) != 0) {
@@ -2422,7 +2055,8 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
                        goto success;
 
 error2:
-               omap_vout_release_vrfb(vout);
+               if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
+                       omap_vout_release_vrfb(vout);
                omap_vout_free_buffers(vout);
 error1:
                video_device_release(vfd);
@@ -2443,11 +2077,13 @@ success:
 static void omap_vout_cleanup_device(struct omap_vout_device *vout)
 {
        struct video_device *vfd;
+       struct omapvideo_info *ovid;
 
        if (!vout)
                return;
 
        vfd = vout->vfd;
+       ovid = &vout->vid_info;
        if (vfd) {
                if (!video_is_registered(vfd)) {
                        /*
@@ -2463,14 +2099,15 @@ static void omap_vout_cleanup_device(struct omap_vout_device *vout)
                        video_unregister_device(vfd);
                }
        }
-
-       omap_vout_release_vrfb(vout);
+       if (ovid->rotation_type == VOUT_ROT_VRFB) {
+               omap_vout_release_vrfb(vout);
+               /* Free the VRFB buffer if allocated
+                * init time
+                */
+               if (vout->vrfb_static_allocation)
+                       omap_vout_free_vrfb_buffers(vout);
+       }
        omap_vout_free_buffers(vout);
-       /* Free the VRFB buffer if allocated
-        * init time
-        */
-       if (vout->vrfb_static_allocation)
-               omap_vout_free_vrfb_buffers(vout);
 
        kfree(vout);
 }
diff --git a/drivers/media/video/omap/omap_vout_vrfb.c b/drivers/media/video/omap/omap_vout_vrfb.c
new file mode 100644 (file)
index 0000000..ebebcac
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ * omap_vout_vrfb.c
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+
+#include <media/videobuf-dma-contig.h>
+#include <media/v4l2-device.h>
+
+#include <plat/dma.h>
+#include <plat/vrfb.h>
+
+#include "omap_voutdef.h"
+#include "omap_voutlib.h"
+
+/*
+ * Function for allocating video buffers
+ */
+static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout,
+               unsigned int *count, int startindex)
+{
+       int i, j;
+
+       for (i = 0; i < *count; i++) {
+               if (!vout->smsshado_virt_addr[i]) {
+                       vout->smsshado_virt_addr[i] =
+                               omap_vout_alloc_buffer(vout->smsshado_size,
+                                               &vout->smsshado_phy_addr[i]);
+               }
+               if (!vout->smsshado_virt_addr[i] && startindex != -1) {
+                       if (V4L2_MEMORY_MMAP == vout->memory && i >= startindex)
+                               break;
+               }
+               if (!vout->smsshado_virt_addr[i]) {
+                       for (j = 0; j < i; j++) {
+                               omap_vout_free_buffer(
+                                               vout->smsshado_virt_addr[j],
+                                               vout->smsshado_size);
+                               vout->smsshado_virt_addr[j] = 0;
+                               vout->smsshado_phy_addr[j] = 0;
+                       }
+                       *count = 0;
+                       return -ENOMEM;
+               }
+               memset((void *) vout->smsshado_virt_addr[i], 0,
+                               vout->smsshado_size);
+       }
+       return 0;
+}
+
+/*
+ * Wakes up the application once the DMA transfer to VRFB space is completed.
+ */
+static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data)
+{
+       struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data;
+
+       t->tx_status = 1;
+       wake_up_interruptible(&t->wait);
+}
+
+/*
+ * Free VRFB buffers
+ */
+void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout)
+{
+       int j;
+
+       for (j = 0; j < VRFB_NUM_BUFS; j++) {
+               omap_vout_free_buffer(vout->smsshado_virt_addr[j],
+                               vout->smsshado_size);
+               vout->smsshado_virt_addr[j] = 0;
+               vout->smsshado_phy_addr[j] = 0;
+       }
+}
+
+int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
+                       u32 static_vrfb_allocation)
+{
+       int ret = 0, i, j;
+       struct omap_vout_device *vout;
+       struct video_device *vfd;
+       int image_width, image_height;
+       int vrfb_num_bufs = VRFB_NUM_BUFS;
+       struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
+       struct omap2video_device *vid_dev =
+               container_of(v4l2_dev, struct omap2video_device, v4l2_dev);
+
+       vout = vid_dev->vouts[vid_num];
+       vfd = vout->vfd;
+
+       for (i = 0; i < VRFB_NUM_BUFS; i++) {
+               if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) {
+                       dev_info(&pdev->dev, ": VRFB allocation failed\n");
+                       for (j = 0; j < i; j++)
+                               omap_vrfb_release_ctx(&vout->vrfb_context[j]);
+                       ret = -ENOMEM;
+                       goto free_buffers;
+               }
+       }
+
+       /* Calculate VRFB memory size */
+       /* allocate for worst case size */
+       image_width = VID_MAX_WIDTH / TILE_SIZE;
+       if (VID_MAX_WIDTH % TILE_SIZE)
+               image_width++;
+
+       image_width = image_width * TILE_SIZE;
+       image_height = VID_MAX_HEIGHT / TILE_SIZE;
+
+       if (VID_MAX_HEIGHT % TILE_SIZE)
+               image_height++;
+
+       image_height = image_height * TILE_SIZE;
+       vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2);
+
+       /*
+        * Request and Initialize DMA, for DMA based VRFB transfer
+        */
+       vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE;
+       vout->vrfb_dma_tx.dma_ch = -1;
+       vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED;
+       ret = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX",
+                       omap_vout_vrfb_dma_tx_callback,
+                       (void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch);
+       if (ret < 0) {
+               vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
+               dev_info(&pdev->dev, ": failed to allocate DMA Channel for"
+                               " video%d\n", vfd->minor);
+       }
+       init_waitqueue_head(&vout->vrfb_dma_tx.wait);
+
+       /* statically allocated the VRFB buffer is done through
+          commands line aruments */
+       if (static_vrfb_allocation) {
+               if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) {
+                       ret =  -ENOMEM;
+                       goto release_vrfb_ctx;
+               }
+               vout->vrfb_static_allocation = 1;
+       }
+       return 0;
+
+release_vrfb_ctx:
+       for (j = 0; j < VRFB_NUM_BUFS; j++)
+               omap_vrfb_release_ctx(&vout->vrfb_context[j]);
+free_buffers:
+       omap_vout_free_buffers(vout);
+
+       return ret;
+}
+
+/*
+ * Release the VRFB context once the module exits
+ */
+void omap_vout_release_vrfb(struct omap_vout_device *vout)
+{
+       int i;
+
+       for (i = 0; i < VRFB_NUM_BUFS; i++)
+               omap_vrfb_release_ctx(&vout->vrfb_context[i]);
+
+       if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) {
+               vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
+               omap_free_dma(vout->vrfb_dma_tx.dma_ch);
+       }
+}
+
+/*
+ * Allocate the buffers for the VRFB space.  Data is copied from V4L2
+ * buffers to the VRFB buffers using the DMA engine.
+ */
+int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
+                         unsigned int *count, unsigned int startindex)
+{
+       int i;
+       bool yuv_mode;
+
+       if (!is_rotation_enabled(vout))
+               return 0;
+
+       /* If rotation is enabled, allocate memory for VRFB space also */
+       *count = *count > VRFB_NUM_BUFS ? VRFB_NUM_BUFS : *count;
+
+       /* Allocate the VRFB buffers only if the buffers are not
+        * allocated during init time.
+        */
+       if (!vout->vrfb_static_allocation)
+               if (omap_vout_allocate_vrfb_buffers(vout, count, startindex))
+                       return -ENOMEM;
+
+       if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 ||
+                       vout->dss_mode == OMAP_DSS_COLOR_UYVY)
+               yuv_mode = true;
+       else
+               yuv_mode = false;
+
+       for (i = 0; i < *count; i++)
+               omap_vrfb_setup(&vout->vrfb_context[i],
+                               vout->smsshado_phy_addr[i], vout->pix.width,
+                               vout->pix.height, vout->bpp, yuv_mode);
+
+       return 0;
+}
+
+int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
+                               struct videobuf_buffer *vb)
+{
+       dma_addr_t dmabuf;
+       struct vid_vrfb_dma *tx;
+       enum dss_rotation rotation;
+       u32 dest_frame_index = 0, src_element_index = 0;
+       u32 dest_element_index = 0, src_frame_index = 0;
+       u32 elem_count = 0, frame_count = 0, pixsize = 2;
+
+       if (!is_rotation_enabled(vout))
+               return 0;
+
+       dmabuf = vout->buf_phy_addr[vb->i];
+       /* If rotation is enabled, copy input buffer into VRFB
+        * memory space using DMA. We are copying input buffer
+        * into VRFB memory space of desired angle and DSS will
+        * read image VRFB memory for 0 degree angle
+        */
+       pixsize = vout->bpp * vout->vrfb_bpp;
+       /*
+        * DMA transfer in double index mode
+        */
+
+       /* Frame index */
+       dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) -
+                       (vout->pix.width * vout->bpp)) + 1;
+
+       /* Source and destination parameters */
+       src_element_index = 0;
+       src_frame_index = 0;
+       dest_element_index = 1;
+       /* Number of elements per frame */
+       elem_count = vout->pix.width * vout->bpp;
+       frame_count = vout->pix.height;
+       tx = &vout->vrfb_dma_tx;
+       tx->tx_status = 0;
+       omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32,
+                       (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT,
+                       tx->dev_id, 0x0);
+       /* src_port required only for OMAP1 */
+       omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
+                       dmabuf, src_element_index, src_frame_index);
+       /*set dma source burst mode for VRFB */
+       omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
+       rotation = calc_rotation(vout);
+
+       /* dest_port required only for OMAP1 */
+       omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX,
+                       vout->vrfb_context[vb->i].paddr[0], dest_element_index,
+                       dest_frame_index);
+       /*set dma dest burst mode for VRFB */
+       omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
+       omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0);
+
+       omap_start_dma(tx->dma_ch);
+       interruptible_sleep_on_timeout(&tx->wait, VRFB_TX_TIMEOUT);
+
+       if (tx->tx_status == 0) {
+               omap_stop_dma(tx->dma_ch);
+               return -EINVAL;
+       }
+       /* Store buffers physical address into an array. Addresses
+        * from this array will be used to configure DSS */
+       vout->queued_buf_addr[vb->i] = (u8 *)
+               vout->vrfb_context[vb->i].paddr[rotation];
+       return 0;
+}
+
+/*
+ * Calculate the buffer offsets from which the streaming should
+ * start. This offset calculation is mainly required because of
+ * the VRFB 32 pixels alignment with rotation.
+ */
+void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout)
+{
+       enum dss_rotation rotation;
+       bool mirroring = vout->mirror;
+       struct v4l2_rect *crop = &vout->crop;
+       struct v4l2_pix_format *pix = &vout->pix;
+       int *cropped_offset = &vout->cropped_offset;
+       int vr_ps = 1, ps = 2, temp_ps = 2;
+       int offset = 0, ctop = 0, cleft = 0, line_length = 0;
+
+       rotation = calc_rotation(vout);
+
+       if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
+                       V4L2_PIX_FMT_UYVY == pix->pixelformat) {
+               if (is_rotation_enabled(vout)) {
+                       /*
+                        * ps    - Actual pixel size for YUYV/UYVY for
+                        *         VRFB/Mirroring is 4 bytes
+                        * vr_ps - Virtually pixel size for YUYV/UYVY is
+                        *         2 bytes
+                        */
+                       ps = 4;
+                       vr_ps = 2;
+               } else {
+                       ps = 2; /* otherwise the pixel size is 2 byte */
+               }
+       } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) {
+               ps = 4;
+       } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) {
+               ps = 3;
+       }
+       vout->ps = ps;
+       vout->vr_ps = vr_ps;
+
+       if (is_rotation_enabled(vout)) {
+               line_length = MAX_PIXELS_PER_LINE;
+               ctop = (pix->height - crop->height) - crop->top;
+               cleft = (pix->width - crop->width) - crop->left;
+       } else {
+               line_length = pix->width;
+       }
+       vout->line_length = line_length;
+       switch (rotation) {
+       case dss_rotation_90_degree:
+               offset = vout->vrfb_context[0].yoffset *
+                       vout->vrfb_context[0].bytespp;
+               temp_ps = ps / vr_ps;
+               if (mirroring == 0) {
+                       *cropped_offset = offset + line_length *
+                               temp_ps * cleft + crop->top * temp_ps;
+               } else {
+                       *cropped_offset = offset + line_length * temp_ps *
+                               cleft + crop->top * temp_ps + (line_length *
+                               ((crop->width / (vr_ps)) - 1) * ps);
+               }
+               break;
+       case dss_rotation_180_degree:
+               offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset *
+                       vout->vrfb_context[0].bytespp) +
+                       (vout->vrfb_context[0].xoffset *
+                       vout->vrfb_context[0].bytespp));
+               if (mirroring == 0) {
+                       *cropped_offset = offset + (line_length * ps * ctop) +
+                               (cleft / vr_ps) * ps;
+
+               } else {
+                       *cropped_offset = offset + (line_length * ps * ctop) +
+                               (cleft / vr_ps) * ps + (line_length *
+                               (crop->height - 1) * ps);
+               }
+               break;
+       case dss_rotation_270_degree:
+               offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset *
+                       vout->vrfb_context[0].bytespp;
+               temp_ps = ps / vr_ps;
+               if (mirroring == 0) {
+                       *cropped_offset = offset + line_length *
+                           temp_ps * crop->left + ctop * ps;
+               } else {
+                       *cropped_offset = offset + line_length *
+                               temp_ps * crop->left + ctop * ps +
+                               (line_length * ((crop->width / vr_ps) - 1) *
+                                ps);
+               }
+               break;
+       case dss_rotation_0_degree:
+               if (mirroring == 0) {
+                       *cropped_offset = (line_length * ps) *
+                               crop->top + (crop->left / vr_ps) * ps;
+               } else {
+                       *cropped_offset = (line_length * ps) *
+                               crop->top + (crop->left / vr_ps) * ps +
+                               (line_length * (crop->height - 1) * ps);
+               }
+               break;
+       default:
+               *cropped_offset = (line_length * ps * crop->top) /
+                       vr_ps + (crop->left * ps) / vr_ps +
+                       ((crop->width / vr_ps) - 1) * ps;
+               break;
+       }
+}
diff --git a/drivers/media/video/omap/omap_vout_vrfb.h b/drivers/media/video/omap/omap_vout_vrfb.h
new file mode 100644 (file)
index 0000000..ffde741
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * omap_vout_vrfb.h
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#ifndef OMAP_VOUT_VRFB_H
+#define OMAP_VOUT_VRFB_H
+
+#ifdef CONFIG_VIDEO_OMAP2_VOUT_VRFB
+void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout);
+int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
+                       u32 static_vrfb_allocation);
+void omap_vout_release_vrfb(struct omap_vout_device *vout);
+int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
+                       unsigned int *count, unsigned int startindex);
+int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
+                       struct videobuf_buffer *vb);
+void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout);
+#else
+void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout) { }
+int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
+                       u32 static_vrfb_allocation)
+               { return 0; }
+void omap_vout_release_vrfb(struct omap_vout_device *vout) { }
+int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
+                       unsigned int *count, unsigned int startindex)
+               { return 0; }
+int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
+                       struct videobuf_buffer *vb)
+               { return 0; }
+void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout) { }
+#endif
+
+#endif
index 659497b..d793501 100644 (file)
@@ -12,6 +12,7 @@
 #define OMAP_VOUTDEF_H
 
 #include <video/omapdss.h>
+#include <plat/vrfb.h>
 
 #define YUYV_BPP        2
 #define RGB565_BPP      2
 #define MAX_DISPLAYS   3
 #define MAX_MANAGERS   3
 
+#define QQVGA_WIDTH            160
+#define QQVGA_HEIGHT           120
+
+/* Max Resolution supported by the driver */
+#define VID_MAX_WIDTH          1280    /* Largest width */
+#define VID_MAX_HEIGHT         720     /* Largest height */
+
+/* Mimimum requirement is 2x2 for DSS */
+#define VID_MIN_WIDTH          2
+#define VID_MIN_HEIGHT         2
+
+/* 2048 x 2048 is max res supported by OMAP display controller */
+#define MAX_PIXELS_PER_LINE     2048
+
+#define VRFB_TX_TIMEOUT         1000
+#define VRFB_NUM_BUFS          4
+
+/* Max buffer size tobe allocated during init */
+#define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4)
+
+enum dma_channel_state {
+       DMA_CHAN_NOT_ALLOTED,
+       DMA_CHAN_ALLOTED,
+};
+
 /* Enum for Rotation
  * DSS understands rotation in 0, 1, 2, 3 context
  * while V4L2 driver understands it as 0, 90, 180, 270
@@ -37,6 +63,18 @@ enum dss_rotation {
        dss_rotation_180_degree = 2,
        dss_rotation_270_degree = 3,
 };
+
+/* Enum for choosing rotation type for vout
+ * DSS2 doesn't understand no rotation as an
+ * option while V4L2 driver doesn't support
+ * rotation in the case where VRFB is not built in
+ * the kernel
+ */
+enum vout_rotaion_type {
+       VOUT_ROT_NONE   = 0,
+       VOUT_ROT_VRFB   = 1,
+};
+
 /*
  * This structure is used to store the DMA transfer parameters
  * for VRFB hidden buffer
@@ -53,6 +91,7 @@ struct omapvideo_info {
        int id;
        int num_overlays;
        struct omap_overlay *overlays[MAX_OVLS];
+       enum vout_rotaion_type rotation_type;
 };
 
 struct omap2video_device {
@@ -144,4 +183,43 @@ struct omap_vout_device {
        int io_allowed;
 
 };
+
+/*
+ * Return true if rotation is 90 or 270
+ */
+static inline int is_rotation_90_or_270(const struct omap_vout_device *vout)
+{
+       return (vout->rotation == dss_rotation_90_degree ||
+                       vout->rotation == dss_rotation_270_degree);
+}
+
+/*
+ * Return true if rotation is enabled
+ */
+static inline int is_rotation_enabled(const struct omap_vout_device *vout)
+{
+       return vout->rotation || vout->mirror;
+}
+
+/*
+ * Reverse the rotation degree if mirroring is enabled
+ */
+static inline int calc_rotation(const struct omap_vout_device *vout)
+{
+       if (!vout->mirror)
+               return vout->rotation;
+
+       switch (vout->rotation) {
+       case dss_rotation_90_degree:
+               return dss_rotation_270_degree;
+       case dss_rotation_270_degree:
+               return dss_rotation_90_degree;
+       case dss_rotation_180_degree:
+               return dss_rotation_0_degree;
+       default:
+               return dss_rotation_180_degree;
+       }
+}
+
+void omap_vout_free_buffers(struct omap_vout_device *vout);
 #endif /* ifndef OMAP_VOUTDEF_H */
index 8ae7481..115408b 100644 (file)
 #include <linux/types.h>
 #include <linux/videodev2.h>
 
+#include <linux/dma-mapping.h>
+
 #include <plat/cpu.h>
 
+#include "omap_voutlib.h"
+
 MODULE_AUTHOR("Texas Instruments");
 MODULE_DESCRIPTION("OMAP Video library");
 MODULE_LICENSE("GPL");
@@ -291,3 +295,45 @@ void omap_vout_new_format(struct v4l2_pix_format *pix,
 }
 EXPORT_SYMBOL_GPL(omap_vout_new_format);
 
+/*
+ * Allocate buffers
+ */
+unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr)
+{
+       u32 order, size;
+       unsigned long virt_addr, addr;
+
+       size = PAGE_ALIGN(buf_size);
+       order = get_order(size);
+       virt_addr = __get_free_pages(GFP_KERNEL, order);
+       addr = virt_addr;
+
+       if (virt_addr) {
+               while (size > 0) {
+                       SetPageReserved(virt_to_page(addr));
+                       addr += PAGE_SIZE;
+                       size -= PAGE_SIZE;
+               }
+       }
+       *phys_addr = (u32) virt_to_phys((void *) virt_addr);
+       return virt_addr;
+}
+
+/*
+ * Free buffers
+ */
+void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size)
+{
+       u32 order, size;
+       unsigned long addr = virtaddr;
+
+       size = PAGE_ALIGN(buf_size);
+       order = get_order(size);
+
+       while (size > 0) {
+               ClearPageReserved(virt_to_page(addr));
+               addr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+       free_pages((unsigned long) virtaddr, order);
+}
index a60b16e..e51750a 100644 (file)
 #ifndef OMAP_VOUTLIB_H
 #define OMAP_VOUTLIB_H
 
-extern void omap_vout_default_crop(struct v4l2_pix_format *pix,
+void omap_vout_default_crop(struct v4l2_pix_format *pix,
                struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop);
 
-extern int omap_vout_new_crop(struct v4l2_pix_format *pix,
+int omap_vout_new_crop(struct v4l2_pix_format *pix,
                struct v4l2_rect *crop, struct v4l2_window *win,
                struct v4l2_framebuffer *fbuf,
                const struct v4l2_rect *new_crop);
 
-extern int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
+int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
                struct v4l2_window *new_win);
 
-extern int omap_vout_new_window(struct v4l2_rect *crop,
+int omap_vout_new_window(struct v4l2_rect *crop,
                struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
                struct v4l2_window *new_win);
 
-extern void omap_vout_new_format(struct v4l2_pix_format *pix,
+void omap_vout_new_format(struct v4l2_pix_format *pix,
                struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
                struct v4l2_window *win);
+unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr);
+void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size);
 #endif /* #ifndef OMAP_VOUTLIB_H */
 
index e7cfc85..8a947e6 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 
 #include <media/omap1_camera.h>
 #include <media/soc_camera.h>
@@ -38,7 +37,7 @@
 
 
 #define DRIVER_NAME            "omap1-camera"
-#define VERSION_CODE           KERNEL_VERSION(0, 0, 1)
+#define DRIVER_VERSION         "0.0.2"
 
 
 /*
@@ -208,7 +207,7 @@ static int omap1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
        struct soc_camera_device *icd = vq->priv_data;
        int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
                        icd->current_fmt->host_fmt);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
 
        if (bytes_per_line < 0)
@@ -222,7 +221,7 @@ static int omap1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
        if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
                *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size;
 
-       dev_dbg(icd->dev.parent,
+       dev_dbg(icd->parent,
                        "%s: count=%d, size=%d\n", __func__, *count, *size);
 
        return 0;
@@ -241,7 +240,7 @@ static void free_buffer(struct videobuf_queue *vq, struct omap1_cam_buf *buf,
                videobuf_dma_contig_free(vq, vb);
        } else {
                struct soc_camera_device *icd = vq->priv_data;
-               struct device *dev = icd->dev.parent;
+               struct device *dev = icd->parent;
                struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
 
                videobuf_dma_unmap(dev, dma);
@@ -258,7 +257,7 @@ static int omap1_videobuf_prepare(struct videobuf_queue *vq,
        struct omap1_cam_buf *buf = container_of(vb, struct omap1_cam_buf, vb);
        int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
                        icd->current_fmt->host_fmt);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
        int ret;
 
@@ -490,7 +489,7 @@ static void omap1_videobuf_queue(struct videobuf_queue *vq,
                                                struct videobuf_buffer *vb)
 {
        struct soc_camera_device *icd = vq->priv_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
        struct omap1_cam_buf *buf;
        u32 mode;
@@ -519,7 +518,7 @@ static void omap1_videobuf_queue(struct videobuf_queue *vq,
        pcdev->active = buf;
        pcdev->ready = NULL;
 
-       dev_dbg(icd->dev.parent,
+       dev_dbg(icd->parent,
                "%s: capture not active, setup FIFO, start DMA\n", __func__);
        mode = CAM_READ_CACHE(pcdev, MODE) & ~THRESHOLD_MASK;
        mode |= THRESHOLD_LEVEL(pcdev->vb_mode) << THRESHOLD_SHIFT;
@@ -543,8 +542,8 @@ static void omap1_videobuf_release(struct videobuf_queue *vq,
        struct omap1_cam_buf *buf =
                        container_of(vb, struct omap1_cam_buf, vb);
        struct soc_camera_device *icd = vq->priv_data;
-       struct device *dev = icd->dev.parent;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct device *dev = icd->parent;
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct omap1_cam_dev *pcdev = ici->priv;
 
        switch (vb->state) {
@@ -573,7 +572,7 @@ static void videobuf_done(struct omap1_cam_dev *pcdev,
 {
        struct omap1_cam_buf *buf = pcdev->active;
        struct videobuf_buffer *vb;
-       struct device *dev = pcdev->icd->dev.parent;
+       struct device *dev = pcdev->icd->parent;
 
        if (WARN_ON(!buf)) {
                suspend_capture(pcdev);
@@ -799,7 +798,7 @@ out:
 static irqreturn_t cam_isr(int irq, void *data)
 {
        struct omap1_cam_dev *pcdev = data;
-       struct device *dev = pcdev->icd->dev.parent;
+       struct device *dev = pcdev->icd->parent;
        struct omap1_cam_buf *buf = pcdev->active;
        u32 it_status;
        unsigned long flags;
@@ -909,7 +908,7 @@ static void sensor_reset(struct omap1_cam_dev *pcdev, bool reset)
  */
 static int omap1_cam_add_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
        u32 ctrlclock;
 
@@ -952,14 +951,14 @@ static int omap1_cam_add_device(struct soc_camera_device *icd)
 
        pcdev->icd = icd;
 
-       dev_dbg(icd->dev.parent, "OMAP1 Camera driver attached to camera %d\n",
+       dev_dbg(icd->parent, "OMAP1 Camera driver attached to camera %d\n",
                        icd->devnum);
        return 0;
 }
 
 static void omap1_cam_remove_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
        u32 ctrlclock;
 
@@ -985,7 +984,7 @@ static void omap1_cam_remove_device(struct soc_camera_device *icd)
 
        pcdev->icd = NULL;
 
-       dev_dbg(icd->dev.parent,
+       dev_dbg(icd->parent,
                "OMAP1 Camera driver detached from camera %d\n", icd->devnum);
 }
 
@@ -1070,7 +1069,7 @@ static int omap1_cam_get_formats(struct soc_camera_device *icd,
                unsigned int idx, struct soc_camera_format_xlate *xlate)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct device *dev = icd->dev.parent;
+       struct device *dev = icd->parent;
        int formats = 0, ret;
        enum v4l2_mbus_pixelcode code;
        const struct soc_mbus_pixelfmt *fmt;
@@ -1222,9 +1221,9 @@ static int omap1_cam_set_crop(struct soc_camera_device *icd,
        struct v4l2_rect *rect = &crop->c;
        const struct soc_camera_format_xlate *xlate = icd->current_fmt;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct device *dev = icd->parent;
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct omap1_cam_dev *pcdev = ici->priv;
-       struct device *dev = icd->dev.parent;
        struct v4l2_mbus_framefmt mf;
        int ret;
 
@@ -1270,8 +1269,8 @@ static int omap1_cam_set_fmt(struct soc_camera_device *icd,
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        const struct soc_camera_format_xlate *xlate;
-       struct device *dev = icd->dev.parent;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct device *dev = icd->parent;
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct omap1_cam_dev *pcdev = ici->priv;
        struct v4l2_pix_format *pix = &f->fmt.pix;
        struct v4l2_mbus_framefmt mf;
@@ -1326,7 +1325,7 @@ static int omap1_cam_try_fmt(struct soc_camera_device *icd,
 
        xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
        if (!xlate) {
-               dev_warn(icd->dev.parent, "Format %#x not found\n",
+               dev_warn(icd->parent, "Format %#x not found\n",
                         pix->pixelformat);
                return -EINVAL;
        }
@@ -1362,7 +1361,7 @@ static int omap1_cam_mmap_mapper(struct videobuf_queue *q,
                                  struct vm_area_struct *vma)
 {
        struct soc_camera_device *icd = q->priv_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
        int ret;
 
@@ -1377,17 +1376,17 @@ static int omap1_cam_mmap_mapper(struct videobuf_queue *q,
 static void omap1_cam_init_videobuf(struct videobuf_queue *q,
                                     struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
 
        if (!sg_mode)
                videobuf_queue_dma_contig_init(q, &omap1_videobuf_ops,
-                               icd->dev.parent, &pcdev->lock,
+                               icd->parent, &pcdev->lock,
                                V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
                                sizeof(struct omap1_cam_buf), icd, &icd->video_lock);
        else
                videobuf_queue_sg_init(q, &omap1_videobuf_ops,
-                               icd->dev.parent, &pcdev->lock,
+                               icd->parent, &pcdev->lock,
                                V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
                                sizeof(struct omap1_cam_buf), icd, &icd->video_lock);
 
@@ -1431,7 +1430,6 @@ static int omap1_cam_querycap(struct soc_camera_host *ici,
 {
        /* cap->name is set by the friendly caller:-> */
        strlcpy(cap->card, "OMAP1 Camera", sizeof(cap->card));
-       cap->version = VERSION_CODE;
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 
        return 0;
@@ -1440,9 +1438,9 @@ static int omap1_cam_querycap(struct soc_camera_host *ici,
 static int omap1_cam_set_bus_param(struct soc_camera_device *icd,
                __u32 pixfmt)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct device *dev = icd->parent;
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct omap1_cam_dev *pcdev = ici->priv;
-       struct device *dev = icd->dev.parent;
        const struct soc_camera_format_xlate *xlate;
        const struct soc_mbus_pixelfmt *fmt;
        unsigned long camera_flags, common_flags;
@@ -1718,4 +1716,5 @@ MODULE_PARM_DESC(sg_mode, "videobuf mode, 0: dma-contig (default), 1: dma-sg");
 MODULE_DESCRIPTION("OMAP1 Camera Interface driver");
 MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
 MODULE_LICENSE("GPL v2");
+MODULE_LICENSE(DRIVER_VERSION);
 MODULE_ALIAS("platform:" DRIVER_NAME);
index 69b60ba..eb97bff 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/interrupt.h>
 #include <linux/videodev2.h>
 #include <linux/pci.h>         /* needed for videobufs */
-#include <linux/version.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/io.h>
@@ -43,7 +42,7 @@
 
 #include "omap24xxcam.h"
 
-#define OMAP24XXCAM_VERSION KERNEL_VERSION(0, 0, 0)
+#define OMAP24XXCAM_VERSION "0.0.1"
 
 #define RESET_TIMEOUT_NS 10000
 
@@ -309,11 +308,11 @@ static int omap24xxcam_vbq_alloc_mmap_buffer(struct videobuf_buffer *vb)
                        order--;
 
                /* try to allocate as many contiguous pages as possible */
-               page = alloc_pages(GFP_KERNEL | GFP_DMA, order);
+               page = alloc_pages(GFP_KERNEL, order);
                /* if allocation fails, try to allocate smaller amount */
                while (page == NULL) {
                        order--;
-                       page = alloc_pages(GFP_KERNEL | GFP_DMA, order);
+                       page = alloc_pages(GFP_KERNEL, order);
                        if (page == NULL && !order) {
                                err = -ENOMEM;
                                goto out;
@@ -993,7 +992,6 @@ static int vidioc_querycap(struct file *file, void *fh,
 
        strlcpy(cap->driver, CAM_NAME, sizeof(cap->driver));
        strlcpy(cap->card, cam->vfd->name, sizeof(cap->card));
-       cap->version = OMAP24XXCAM_VERSION;
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 
        return 0;
@@ -1888,6 +1886,7 @@ static void __exit omap24xxcam_cleanup(void)
 MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
 MODULE_DESCRIPTION("OMAP24xx Video for Linux camera driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(OMAP24XXCAM_VERSION);
 module_param(video_nr, int, 0);
 MODULE_PARM_DESC(video_nr,
                 "Minor number for video device (-1 ==> auto assign)");
index 94b6ed8..5cea2bb 100644 (file)
@@ -2234,3 +2234,4 @@ module_exit(isp_cleanup);
 MODULE_AUTHOR("Nokia Corporation");
 MODULE_DESCRIPTION("TI OMAP3 ISP driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(ISP_VIDEO_DRIVER_VERSION);
index 2620c40..529e582 100644 (file)
@@ -139,6 +139,10 @@ struct isp_reg {
  *             3 - CAMEXT[13:6] -> CAM[7:0]
  * @clk_pol: Pixel clock polarity
  *             0 - Non Inverted, 1 - Inverted
+ * @hs_pol: Horizontal synchronization polarity
+ *             0 - Active high, 1 - Active low
+ * @vs_pol: Vertical synchronization polarity
+ *             0 - Active high, 1 - Active low
  * @bridge: CCDC Bridge input control
  *             ISPCTRL_PAR_BRIDGE_DISABLE - Disable
  *             ISPCTRL_PAR_BRIDGE_LENDIAN - Little endian
@@ -147,6 +151,8 @@ struct isp_reg {
 struct isp_parallel_platform_data {
        unsigned int data_lane_shift:2;
        unsigned int clk_pol:1;
+       unsigned int hs_pol:1;
+       unsigned int vs_pol:1;
        unsigned int bridge:4;
 };
 
index 39d501b..9d3459d 100644 (file)
@@ -1148,6 +1148,8 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
        omap3isp_configure_bridge(isp, ccdc->input, pdata, shift);
 
        ccdc->syncif.datsz = depth_out;
+       ccdc->syncif.hdpol = pdata ? pdata->hs_pol : 0;
+       ccdc->syncif.vdpol = pdata ? pdata->vs_pol : 0;
        ccdc_config_sync_if(ccdc, &ccdc->syncif);
 
        /* CCDC_PAD_SINK */
@@ -1691,7 +1693,7 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
        if (sub->type != V4L2_EVENT_OMAP3ISP_HS_VS)
                return -EINVAL;
 
-       return v4l2_event_subscribe(fh, sub);
+       return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS);
 }
 
 static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
@@ -2162,7 +2164,6 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
        sd->grp_id = 1 << 16;   /* group ID for isp subdevs */
        v4l2_set_subdevdata(sd, ccdc);
        sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
-       sd->nevents = OMAP3ISP_CCDC_NEVENTS;
 
        pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
        pads[CCDC_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
@@ -2257,8 +2258,6 @@ int omap3isp_ccdc_init(struct isp_device *isp)
        ccdc->syncif.fldout = 0;
        ccdc->syncif.fldpol = 0;
        ccdc->syncif.fldstat = 0;
-       ccdc->syncif.hdpol = 0;
-       ccdc->syncif.vdpol = 0;
 
        ccdc->clamp.oblen = 0;
        ccdc->clamp.dcsubval = 0;
index 0e16cab..ec9e395 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
+#include <linux/regulator/consumer.h>
 
 #include "isp.h"
 #include "ispreg.h"
@@ -163,6 +164,9 @@ static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable)
        struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
        int i;
 
+       if (enable && ccp2->vdds_csib)
+               regulator_enable(ccp2->vdds_csib);
+
        /* Enable/Disable all the LCx channels */
        for (i = 0; i < CCP2_LCx_CHANS_NUM; i++)
                isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i),
@@ -186,6 +190,9 @@ static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable)
                                    ISPCCP2_LC01_IRQENABLE,
                                    ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ);
        }
+
+       if (!enable && ccp2->vdds_csib)
+               regulator_disable(ccp2->vdds_csib);
 }
 
 /*
@@ -1137,6 +1144,9 @@ error:
  */
 void omap3isp_ccp2_cleanup(struct isp_device *isp)
 {
+       struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
+
+       regulator_put(ccp2->vdds_csib);
 }
 
 /*
@@ -1151,14 +1161,27 @@ int omap3isp_ccp2_init(struct isp_device *isp)
 
        init_waitqueue_head(&ccp2->wait);
 
-       /* On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with
+       /*
+        * On the OMAP34xx the CSI1 receiver is operated in the CSIb IO
+        * complex, which is powered by vdds_csib power rail. Hence the
+        * request for the regulator.
+        *
+        * On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with
         * the CSI2c or CSI2a receivers. The PHY then needs to be explicitly
         * configured.
         *
         * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c).
         */
-       if (isp->revision == ISP_REVISION_15_0)
+       if (isp->revision == ISP_REVISION_2_0) {
+               ccp2->vdds_csib = regulator_get(isp->dev, "vdds_csib");
+               if (IS_ERR(ccp2->vdds_csib)) {
+                       dev_dbg(isp->dev,
+                               "Could not get regulator vdds_csib\n");
+                       ccp2->vdds_csib = NULL;
+               }
+       } else if (isp->revision == ISP_REVISION_15_0) {
                ccp2->phy = &isp->isp_csiphy1;
+       }
 
        ret = ccp2_init_entities(ccp2);
        if (ret < 0)
index 5505a86..6674e9d 100644 (file)
@@ -81,6 +81,7 @@ struct isp_ccp2_device {
        struct isp_interface_mem_config mem_cfg;
        struct isp_video video_in;
        struct isp_csiphy *phy;
+       struct regulator *vdds_csib;
        unsigned int error;
        enum isp_pipeline_stream_state state;
        wait_queue_head_t wait;
index b44cb68..8080659 100644 (file)
@@ -1032,7 +1032,6 @@ static int isp_stat_init_entities(struct ispstat *stat, const char *name,
        snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "OMAP3 ISP %s", name);
        subdev->grp_id = 1 << 16;       /* group ID for isp subdevs */
        subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
-       subdev->nevents = STAT_NEVENTS;
        v4l2_set_subdevdata(subdev, stat);
 
        stat->pad.flags = MEDIA_PAD_FL_SINK;
@@ -1050,7 +1049,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
        if (sub->type != stat->event_type)
                return -EINVAL;
 
-       return v4l2_event_subscribe(fh, sub);
+       return v4l2_event_subscribe(fh, sub, STAT_NEVENTS);
 }
 
 int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
index 9cd8f1a..fd965ad 100644 (file)
@@ -695,7 +695,6 @@ isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
        strlcpy(cap->driver, ISP_VIDEO_DRIVER_NAME, sizeof(cap->driver));
        strlcpy(cap->card, video->video.name, sizeof(cap->card));
        strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
-       cap->version = ISP_VIDEO_DRIVER_VERSION;
 
        if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
                cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
index 911bea6..53160aa 100644 (file)
@@ -27,7 +27,6 @@
 #define OMAP3_ISP_VIDEO_H
 
 #include <linux/v4l2-mediabus.h>
-#include <linux/version.h>
 #include <media/media-entity.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-fh.h>
@@ -35,7 +34,7 @@
 #include "ispqueue.h"
 
 #define ISP_VIDEO_DRIVER_NAME          "ispvideo"
-#define ISP_VIDEO_DRIVER_VERSION       KERNEL_VERSION(0, 0, 1)
+#define ISP_VIDEO_DRIVER_VERSION       "0.0.2"
 
 struct isp_device;
 struct isp_video;
index 0cea0cf..9ce2fa0 100644 (file)
@@ -1031,16 +1031,9 @@ static int ov2640_video_probe(struct soc_camera_device *icd,
        const char *devname;
        int ret;
 
-       /*
-        * we must have a parent by now. And it cannot be a wrong one.
-        * So this entire test is completely redundant.
-        */
-       if (!icd->dev.parent ||
-           to_soc_camera_host(icd->dev.parent)->nr != icd->iface) {
-               dev_err(&client->dev, "Parent missing or invalid!\n");
-               ret = -ENODEV;
-               goto err;
-       }
+       /* We must have a parent by now. And it cannot be a wrong one. */
+       BUG_ON(!icd->parent ||
+              to_soc_camera_host(icd->parent)->nr != icd->iface);
 
        /*
         * check and show product ID and manufacturer ID
diff --git a/drivers/media/video/ov5642.c b/drivers/media/video/ov5642.c
new file mode 100644 (file)
index 0000000..349a4ad
--- /dev/null
@@ -0,0 +1,1012 @@
+/*
+ * Driver for OV5642 CMOS Image Sensor from Omnivision
+ *
+ * Copyright (C) 2011, Bastian Hecht <hechtb@gmail.com>
+ *
+ * Based on Sony IMX074 Camera Driver
+ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * Based on Omnivision OV7670 Camera Driver
+ * Copyright (C) 2006-7 Jonathan Corbet <corbet@lwn.net>
+ *
+ * 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/i2c.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-subdev.h>
+
+/* OV5642 registers */
+#define REG_CHIP_ID_HIGH               0x300a
+#define REG_CHIP_ID_LOW                        0x300b
+
+#define REG_WINDOW_START_X_HIGH                0x3800
+#define REG_WINDOW_START_X_LOW         0x3801
+#define REG_WINDOW_START_Y_HIGH                0x3802
+#define REG_WINDOW_START_Y_LOW         0x3803
+#define REG_WINDOW_WIDTH_HIGH          0x3804
+#define REG_WINDOW_WIDTH_LOW           0x3805
+#define REG_WINDOW_HEIGHT_HIGH                 0x3806
+#define REG_WINDOW_HEIGHT_LOW          0x3807
+#define REG_OUT_WIDTH_HIGH             0x3808
+#define REG_OUT_WIDTH_LOW              0x3809
+#define REG_OUT_HEIGHT_HIGH            0x380a
+#define REG_OUT_HEIGHT_LOW             0x380b
+#define REG_OUT_TOTAL_WIDTH_HIGH       0x380c
+#define REG_OUT_TOTAL_WIDTH_LOW                0x380d
+#define REG_OUT_TOTAL_HEIGHT_HIGH      0x380e
+#define REG_OUT_TOTAL_HEIGHT_LOW       0x380f
+
+/*
+ * define standard resolution.
+ * Works currently only for up to 720 lines
+ * eg. 320x240, 640x480, 800x600, 1280x720, 2048x720
+ */
+
+#define OV5642_WIDTH           1280
+#define OV5642_HEIGHT          720
+#define OV5642_TOTAL_WIDTH     3200
+#define OV5642_TOTAL_HEIGHT    2000
+#define OV5642_SENSOR_SIZE_X   2592
+#define OV5642_SENSOR_SIZE_Y   1944
+
+struct regval_list {
+       u16 reg_num;
+       u8 value;
+};
+
+static struct regval_list ov5642_default_regs_init[] = {
+       { 0x3103, 0x93 },
+       { 0x3008, 0x82 },
+       { 0x3017, 0x7f },
+       { 0x3018, 0xfc },
+       { 0x3810, 0xc2 },
+       { 0x3615, 0xf0 },
+       { 0x3000, 0x0  },
+       { 0x3001, 0x0  },
+       { 0x3002, 0x0  },
+       { 0x3003, 0x0  },
+       { 0x3004, 0xff },
+       { 0x3030, 0x2b },
+       { 0x3011, 0x8  },
+       { 0x3010, 0x10 },
+       { 0x3604, 0x60 },
+       { 0x3622, 0x60 },
+       { 0x3621, 0x9  },
+       { 0x3709, 0x0  },
+       { 0x4000, 0x21 },
+       { 0x401d, 0x22 },
+       { 0x3600, 0x54 },
+       { 0x3605, 0x4  },
+       { 0x3606, 0x3f },
+       { 0x3c01, 0x80 },
+       { 0x300d, 0x22 },
+       { 0x3623, 0x22 },
+       { 0x5000, 0x4f },
+       { 0x5020, 0x4  },
+       { 0x5181, 0x79 },
+       { 0x5182, 0x0  },
+       { 0x5185, 0x22 },
+       { 0x5197, 0x1  },
+       { 0x5500, 0xa  },
+       { 0x5504, 0x0  },
+       { 0x5505, 0x7f },
+       { 0x5080, 0x8  },
+       { 0x300e, 0x18 },
+       { 0x4610, 0x0  },
+       { 0x471d, 0x5  },
+       { 0x4708, 0x6  },
+       { 0x370c, 0xa0 },
+       { 0x5687, 0x94 },
+       { 0x501f, 0x0  },
+       { 0x5000, 0x4f },
+       { 0x5001, 0xcf },
+       { 0x4300, 0x30 },
+       { 0x4300, 0x30 },
+       { 0x460b, 0x35 },
+       { 0x471d, 0x0  },
+       { 0x3002, 0xc  },
+       { 0x3002, 0x0  },
+       { 0x4713, 0x3  },
+       { 0x471c, 0x50 },
+       { 0x4721, 0x2  },
+       { 0x4402, 0x90 },
+       { 0x460c, 0x22 },
+       { 0x3815, 0x44 },
+       { 0x3503, 0x7  },
+       { 0x3501, 0x73 },
+       { 0x3502, 0x80 },
+       { 0x350b, 0x0  },
+       { 0x3818, 0xc8 },
+       { 0x3824, 0x11 },
+       { 0x3a00, 0x78 },
+       { 0x3a1a, 0x4  },
+       { 0x3a13, 0x30 },
+       { 0x3a18, 0x0  },
+       { 0x3a19, 0x7c },
+       { 0x3a08, 0x12 },
+       { 0x3a09, 0xc0 },
+       { 0x3a0a, 0xf  },
+       { 0x3a0b, 0xa0 },
+       { 0x350c, 0x7  },
+       { 0x350d, 0xd0 },
+       { 0x3a0d, 0x8  },
+       { 0x3a0e, 0x6  },
+       { 0x3500, 0x0  },
+       { 0x3501, 0x0  },
+       { 0x3502, 0x0  },
+       { 0x350a, 0x0  },
+       { 0x350b, 0x0  },
+       { 0x3503, 0x0  },
+       { 0x3a0f, 0x3c },
+       { 0x3a10, 0x32 },
+       { 0x3a1b, 0x3c },
+       { 0x3a1e, 0x32 },
+       { 0x3a11, 0x80 },
+       { 0x3a1f, 0x20 },
+       { 0x3030, 0x2b },
+       { 0x3a02, 0x0  },
+       { 0x3a03, 0x7d },
+       { 0x3a04, 0x0  },
+       { 0x3a14, 0x0  },
+       { 0x3a15, 0x7d },
+       { 0x3a16, 0x0  },
+       { 0x3a00, 0x78 },
+       { 0x3a08, 0x9  },
+       { 0x3a09, 0x60 },
+       { 0x3a0a, 0x7  },
+       { 0x3a0b, 0xd0 },
+       { 0x3a0d, 0x10 },
+       { 0x3a0e, 0xd  },
+       { 0x4407, 0x4  },
+       { 0x5193, 0x70 },
+       { 0x589b, 0x0  },
+       { 0x589a, 0xc0 },
+       { 0x401e, 0x20 },
+       { 0x4001, 0x42 },
+       { 0x401c, 0x6  },
+       { 0x3825, 0xac },
+       { 0x3827, 0xc  },
+       { 0x528a, 0x1  },
+       { 0x528b, 0x4  },
+       { 0x528c, 0x8  },
+       { 0x528d, 0x10 },
+       { 0x528e, 0x20 },
+       { 0x528f, 0x28 },
+       { 0x5290, 0x30 },
+       { 0x5292, 0x0  },
+       { 0x5293, 0x1  },
+       { 0x5294, 0x0  },
+       { 0x5295, 0x4  },
+       { 0x5296, 0x0  },
+       { 0x5297, 0x8  },
+       { 0x5298, 0x0  },
+       { 0x5299, 0x10 },
+       { 0x529a, 0x0  },
+       { 0x529b, 0x20 },
+       { 0x529c, 0x0  },
+       { 0x529d, 0x28 },
+       { 0x529e, 0x0  },
+       { 0x529f, 0x30 },
+       { 0x5282, 0x0  },
+       { 0x5300, 0x0  },
+       { 0x5301, 0x20 },
+       { 0x5302, 0x0  },
+       { 0x5303, 0x7c },
+       { 0x530c, 0x0  },
+       { 0x530d, 0xc  },
+       { 0x530e, 0x20 },
+       { 0x530f, 0x80 },
+       { 0x5310, 0x20 },
+       { 0x5311, 0x80 },
+       { 0x5308, 0x20 },
+       { 0x5309, 0x40 },
+       { 0x5304, 0x0  },
+       { 0x5305, 0x30 },
+       { 0x5306, 0x0  },
+       { 0x5307, 0x80 },
+       { 0x5314, 0x8  },
+       { 0x5315, 0x20 },
+       { 0x5319, 0x30 },
+       { 0x5316, 0x10 },
+       { 0x5317, 0x0  },
+       { 0x5318, 0x2  },
+       { 0x5380, 0x1  },
+       { 0x5381, 0x0  },
+       { 0x5382, 0x0  },
+       { 0x5383, 0x4e },
+       { 0x5384, 0x0  },
+       { 0x5385, 0xf  },
+       { 0x5386, 0x0  },
+       { 0x5387, 0x0  },
+       { 0x5388, 0x1  },
+       { 0x5389, 0x15 },
+       { 0x538a, 0x0  },
+       { 0x538b, 0x31 },
+       { 0x538c, 0x0  },
+       { 0x538d, 0x0  },
+       { 0x538e, 0x0  },
+       { 0x538f, 0xf  },
+       { 0x5390, 0x0  },
+       { 0x5391, 0xab },
+       { 0x5392, 0x0  },
+       { 0x5393, 0xa2 },
+       { 0x5394, 0x8  },
+       { 0x5480, 0x14 },
+       { 0x5481, 0x21 },
+       { 0x5482, 0x36 },
+       { 0x5483, 0x57 },
+       { 0x5484, 0x65 },
+       { 0x5485, 0x71 },
+       { 0x5486, 0x7d },
+       { 0x5487, 0x87 },
+       { 0x5488, 0x91 },
+       { 0x5489, 0x9a },
+       { 0x548a, 0xaa },
+       { 0x548b, 0xb8 },
+       { 0x548c, 0xcd },
+       { 0x548d, 0xdd },
+       { 0x548e, 0xea },
+       { 0x548f, 0x1d },
+       { 0x5490, 0x5  },
+       { 0x5491, 0x0  },
+       { 0x5492, 0x4  },
+       { 0x5493, 0x20 },
+       { 0x5494, 0x3  },
+       { 0x5495, 0x60 },
+       { 0x5496, 0x2  },
+       { 0x5497, 0xb8 },
+       { 0x5498, 0x2  },
+       { 0x5499, 0x86 },
+       { 0x549a, 0x2  },
+       { 0x549b, 0x5b },
+       { 0x549c, 0x2  },
+       { 0x549d, 0x3b },
+       { 0x549e, 0x2  },
+       { 0x549f, 0x1c },
+       { 0x54a0, 0x2  },
+       { 0x54a1, 0x4  },
+       { 0x54a2, 0x1  },
+       { 0x54a3, 0xed },
+       { 0x54a4, 0x1  },
+       { 0x54a5, 0xc5 },
+       { 0x54a6, 0x1  },
+       { 0x54a7, 0xa5 },
+       { 0x54a8, 0x1  },
+       { 0x54a9, 0x6c },
+       { 0x54aa, 0x1  },
+       { 0x54ab, 0x41 },
+       { 0x54ac, 0x1  },
+       { 0x54ad, 0x20 },
+       { 0x54ae, 0x0  },
+       { 0x54af, 0x16 },
+       { 0x54b0, 0x1  },
+       { 0x54b1, 0x20 },
+       { 0x54b2, 0x0  },
+       { 0x54b3, 0x10 },
+       { 0x54b4, 0x0  },
+       { 0x54b5, 0xf0 },
+       { 0x54b6, 0x0  },
+       { 0x54b7, 0xdf },
+       { 0x5402, 0x3f },
+       { 0x5403, 0x0  },
+       { 0x3406, 0x0  },
+       { 0x5180, 0xff },
+       { 0x5181, 0x52 },
+       { 0x5182, 0x11 },
+       { 0x5183, 0x14 },
+       { 0x5184, 0x25 },
+       { 0x5185, 0x24 },
+       { 0x5186, 0x6  },
+       { 0x5187, 0x8  },
+       { 0x5188, 0x8  },
+       { 0x5189, 0x7c },
+       { 0x518a, 0x60 },
+       { 0x518b, 0xb2 },
+       { 0x518c, 0xb2 },
+       { 0x518d, 0x44 },
+       { 0x518e, 0x3d },
+       { 0x518f, 0x58 },
+       { 0x5190, 0x46 },
+       { 0x5191, 0xf8 },
+       { 0x5192, 0x4  },
+       { 0x5193, 0x70 },
+       { 0x5194, 0xf0 },
+       { 0x5195, 0xf0 },
+       { 0x5196, 0x3  },
+       { 0x5197, 0x1  },
+       { 0x5198, 0x4  },
+       { 0x5199, 0x12 },
+       { 0x519a, 0x4  },
+       { 0x519b, 0x0  },
+       { 0x519c, 0x6  },
+       { 0x519d, 0x82 },
+       { 0x519e, 0x0  },
+       { 0x5025, 0x80 },
+       { 0x3a0f, 0x38 },
+       { 0x3a10, 0x30 },
+       { 0x3a1b, 0x3a },
+       { 0x3a1e, 0x2e },
+       { 0x3a11, 0x60 },
+       { 0x3a1f, 0x10 },
+       { 0x5688, 0xa6 },
+       { 0x5689, 0x6a },
+       { 0x568a, 0xea },
+       { 0x568b, 0xae },
+       { 0x568c, 0xa6 },
+       { 0x568d, 0x6a },
+       { 0x568e, 0x62 },
+       { 0x568f, 0x26 },
+       { 0x5583, 0x40 },
+       { 0x5584, 0x40 },
+       { 0x5580, 0x2  },
+       { 0x5000, 0xcf },
+       { 0x5800, 0x27 },
+       { 0x5801, 0x19 },
+       { 0x5802, 0x12 },
+       { 0x5803, 0xf  },
+       { 0x5804, 0x10 },
+       { 0x5805, 0x15 },
+       { 0x5806, 0x1e },
+       { 0x5807, 0x2f },
+       { 0x5808, 0x15 },
+       { 0x5809, 0xd  },
+       { 0x580a, 0xa  },
+       { 0x580b, 0x9  },
+       { 0x580c, 0xa  },
+       { 0x580d, 0xc  },
+       { 0x580e, 0x12 },
+       { 0x580f, 0x19 },
+       { 0x5810, 0xb  },
+       { 0x5811, 0x7  },
+       { 0x5812, 0x4  },
+       { 0x5813, 0x3  },
+       { 0x5814, 0x3  },
+       { 0x5815, 0x6  },
+       { 0x5816, 0xa  },
+       { 0x5817, 0xf  },
+       { 0x5818, 0xa  },
+       { 0x5819, 0x5  },
+       { 0x581a, 0x1  },
+       { 0x581b, 0x0  },
+       { 0x581c, 0x0  },
+       { 0x581d, 0x3  },
+       { 0x581e, 0x8  },
+       { 0x581f, 0xc  },
+       { 0x5820, 0xa  },
+       { 0x5821, 0x5  },
+       { 0x5822, 0x1  },
+       { 0x5823, 0x0  },
+       { 0x5824, 0x0  },
+       { 0x5825, 0x3  },
+       { 0x5826, 0x8  },
+       { 0x5827, 0xc  },
+       { 0x5828, 0xe  },
+       { 0x5829, 0x8  },
+       { 0x582a, 0x6  },
+       { 0x582b, 0x4  },
+       { 0x582c, 0x5  },
+       { 0x582d, 0x7  },
+       { 0x582e, 0xb  },
+       { 0x582f, 0x12 },
+       { 0x5830, 0x18 },
+       { 0x5831, 0x10 },
+       { 0x5832, 0xc  },
+       { 0x5833, 0xa  },
+       { 0x5834, 0xb  },
+       { 0x5835, 0xe  },
+       { 0x5836, 0x15 },
+       { 0x5837, 0x19 },
+       { 0x5838, 0x32 },
+       { 0x5839, 0x1f },
+       { 0x583a, 0x18 },
+       { 0x583b, 0x16 },
+       { 0x583c, 0x17 },
+       { 0x583d, 0x1e },
+       { 0x583e, 0x26 },
+       { 0x583f, 0x53 },
+       { 0x5840, 0x10 },
+       { 0x5841, 0xf  },
+       { 0x5842, 0xd  },
+       { 0x5843, 0xc  },
+       { 0x5844, 0xe  },
+       { 0x5845, 0x9  },
+       { 0x5846, 0x11 },
+       { 0x5847, 0x10 },
+       { 0x5848, 0x10 },
+       { 0x5849, 0x10 },
+       { 0x584a, 0x10 },
+       { 0x584b, 0xe  },
+       { 0x584c, 0x10 },
+       { 0x584d, 0x10 },
+       { 0x584e, 0x11 },
+       { 0x584f, 0x10 },
+       { 0x5850, 0xf  },
+       { 0x5851, 0xc  },
+       { 0x5852, 0xf  },
+       { 0x5853, 0x10 },
+       { 0x5854, 0x10 },
+       { 0x5855, 0xf  },
+       { 0x5856, 0xe  },
+       { 0x5857, 0xb  },
+       { 0x5858, 0x10 },
+       { 0x5859, 0xd  },
+       { 0x585a, 0xd  },
+       { 0x585b, 0xc  },
+       { 0x585c, 0xc  },
+       { 0x585d, 0xc  },
+       { 0x585e, 0xb  },
+       { 0x585f, 0xc  },
+       { 0x5860, 0xc  },
+       { 0x5861, 0xc  },
+       { 0x5862, 0xd  },
+       { 0x5863, 0x8  },
+       { 0x5864, 0x11 },
+       { 0x5865, 0x18 },
+       { 0x5866, 0x18 },
+       { 0x5867, 0x19 },
+       { 0x5868, 0x17 },
+       { 0x5869, 0x19 },
+       { 0x586a, 0x16 },
+       { 0x586b, 0x13 },
+       { 0x586c, 0x13 },
+       { 0x586d, 0x12 },
+       { 0x586e, 0x13 },
+       { 0x586f, 0x16 },
+       { 0x5870, 0x14 },
+       { 0x5871, 0x12 },
+       { 0x5872, 0x10 },
+       { 0x5873, 0x11 },
+       { 0x5874, 0x11 },
+       { 0x5875, 0x16 },
+       { 0x5876, 0x14 },
+       { 0x5877, 0x11 },
+       { 0x5878, 0x10 },
+       { 0x5879, 0xf  },
+       { 0x587a, 0x10 },
+       { 0x587b, 0x14 },
+       { 0x587c, 0x13 },
+       { 0x587d, 0x12 },
+       { 0x587e, 0x11 },
+       { 0x587f, 0x11 },
+       { 0x5880, 0x12 },
+       { 0x5881, 0x15 },
+       { 0x5882, 0x14 },
+       { 0x5883, 0x15 },
+       { 0x5884, 0x15 },
+       { 0x5885, 0x15 },
+       { 0x5886, 0x13 },
+       { 0x5887, 0x17 },
+       { 0x3710, 0x10 },
+       { 0x3632, 0x51 },
+       { 0x3702, 0x10 },
+       { 0x3703, 0xb2 },
+       { 0x3704, 0x18 },
+       { 0x370b, 0x40 },
+       { 0x370d, 0x3  },
+       { 0x3631, 0x1  },
+       { 0x3632, 0x52 },
+       { 0x3606, 0x24 },
+       { 0x3620, 0x96 },
+       { 0x5785, 0x7  },
+       { 0x3a13, 0x30 },
+       { 0x3600, 0x52 },
+       { 0x3604, 0x48 },
+       { 0x3606, 0x1b },
+       { 0x370d, 0xb  },
+       { 0x370f, 0xc0 },
+       { 0x3709, 0x1  },
+       { 0x3823, 0x0  },
+       { 0x5007, 0x0  },
+       { 0x5009, 0x0  },
+       { 0x5011, 0x0  },
+       { 0x5013, 0x0  },
+       { 0x519e, 0x0  },
+       { 0x5086, 0x0  },
+       { 0x5087, 0x0  },
+       { 0x5088, 0x0  },
+       { 0x5089, 0x0  },
+       { 0x302b, 0x0  },
+       { 0x3503, 0x7  },
+       { 0x3011, 0x8  },
+       { 0x350c, 0x2  },
+       { 0x350d, 0xe4 },
+       { 0x3621, 0xc9 },
+       { 0x370a, 0x81 },
+       { 0xffff, 0xff },
+};
+
+static struct regval_list ov5642_default_regs_finalise[] = {
+       { 0x3810, 0xc2 },
+       { 0x3818, 0xc9 },
+       { 0x381c, 0x10 },
+       { 0x381d, 0xa0 },
+       { 0x381e, 0x5  },
+       { 0x381f, 0xb0 },
+       { 0x3820, 0x0  },
+       { 0x3821, 0x0  },
+       { 0x3824, 0x11 },
+       { 0x3a08, 0x1b },
+       { 0x3a09, 0xc0 },
+       { 0x3a0a, 0x17 },
+       { 0x3a0b, 0x20 },
+       { 0x3a0d, 0x2  },
+       { 0x3a0e, 0x1  },
+       { 0x401c, 0x4  },
+       { 0x5682, 0x5  },
+       { 0x5683, 0x0  },
+       { 0x5686, 0x2  },
+       { 0x5687, 0xcc },
+       { 0x5001, 0x4f },
+       { 0x589b, 0x6  },
+       { 0x589a, 0xc5 },
+       { 0x3503, 0x0  },
+       { 0x460c, 0x20 },
+       { 0x460b, 0x37 },
+       { 0x471c, 0xd0 },
+       { 0x471d, 0x5  },
+       { 0x3815, 0x1  },
+       { 0x3818, 0xc1 },
+       { 0x501f, 0x0  },
+       { 0x5002, 0xe0 },
+       { 0x4300, 0x32 }, /* UYVY */
+       { 0x3002, 0x1c },
+       { 0x4800, 0x14 },
+       { 0x4801, 0xf  },
+       { 0x3007, 0x3b },
+       { 0x300e, 0x4  },
+       { 0x4803, 0x50 },
+       { 0x3815, 0x1  },
+       { 0x4713, 0x2  },
+       { 0x4842, 0x1  },
+       { 0x300f, 0xe  },
+       { 0x3003, 0x3  },
+       { 0x3003, 0x1  },
+       { 0xffff, 0xff },
+};
+
+struct ov5642_datafmt {
+       enum v4l2_mbus_pixelcode        code;
+       enum v4l2_colorspace            colorspace;
+};
+
+struct ov5642 {
+       struct v4l2_subdev              subdev;
+       const struct ov5642_datafmt     *fmt;
+};
+
+static const struct ov5642_datafmt ov5642_colour_fmts[] = {
+       {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
+};
+
+static struct ov5642 *to_ov5642(const struct i2c_client *client)
+{
+       return container_of(i2c_get_clientdata(client), struct ov5642, subdev);
+}
+
+/* Find a data format by a pixel code in an array */
+static const struct ov5642_datafmt
+                       *ov5642_find_datafmt(enum v4l2_mbus_pixelcode code)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ov5642_colour_fmts); i++)
+               if (ov5642_colour_fmts[i].code == code)
+                       return ov5642_colour_fmts + i;
+
+       return NULL;
+}
+
+static int reg_read(struct i2c_client *client, u16 reg, u8 *val)
+{
+       int ret;
+       /* We have 16-bit i2c addresses - care for endianess */
+       unsigned char data[2] = { reg >> 8, reg & 0xff };
+
+       ret = i2c_master_send(client, data, 2);
+       if (ret < 2) {
+               dev_err(&client->dev, "%s: i2c read error, reg: %x\n",
+                       __func__, reg);
+               return ret < 0 ? ret : -EIO;
+       }
+
+       ret = i2c_master_recv(client, val, 1);
+       if (ret < 1) {
+               dev_err(&client->dev, "%s: i2c read error, reg: %x\n",
+                               __func__, reg);
+               return ret < 0 ? ret : -EIO;
+       }
+       return 0;
+}
+
+static int reg_write(struct i2c_client *client, u16 reg, u8 val)
+{
+       int ret;
+       unsigned char data[3] = { reg >> 8, reg & 0xff, val };
+
+       ret = i2c_master_send(client, data, 3);
+       if (ret < 3) {
+               dev_err(&client->dev, "%s: i2c write error, reg: %x\n",
+                       __func__, reg);
+               return ret < 0 ? ret : -EIO;
+       }
+
+       return 0;
+}
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov5642_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       int ret;
+       u8 val;
+
+       if (reg->reg & ~0xffff)
+               return -EINVAL;
+
+       reg->size = 1;
+
+       ret = reg_read(client, reg->reg, &val);
+       if (!ret)
+               reg->val = (__u64)val;
+
+       return ret;
+}
+
+static int ov5642_set_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       if (reg->reg & ~0xffff || reg->val & ~0xff)
+               return -EINVAL;
+
+       return reg_write(client, reg->reg, reg->val);
+}
+#endif
+
+static int ov5642_write_array(struct i2c_client *client,
+                               struct regval_list *vals)
+{
+       while (vals->reg_num != 0xffff || vals->value != 0xff) {
+               int ret = reg_write(client, vals->reg_num, vals->value);
+               if (ret < 0)
+                       return ret;
+               vals++;
+       }
+       dev_dbg(&client->dev, "Register list loaded\n");
+       return 0;
+}
+
+static int ov5642_set_resolution(struct i2c_client *client)
+{
+       int ret;
+       u8 start_x_high = ((OV5642_SENSOR_SIZE_X - OV5642_WIDTH) / 2) >> 8;
+       u8 start_x_low  = ((OV5642_SENSOR_SIZE_X - OV5642_WIDTH) / 2) & 0xff;
+       u8 start_y_high = ((OV5642_SENSOR_SIZE_Y - OV5642_HEIGHT) / 2) >> 8;
+       u8 start_y_low  = ((OV5642_SENSOR_SIZE_Y - OV5642_HEIGHT) / 2) & 0xff;
+
+       u8 width_high   = OV5642_WIDTH  >> 8;
+       u8 width_low    = OV5642_WIDTH  & 0xff;
+       u8 height_high  = OV5642_HEIGHT >> 8;
+       u8 height_low   = OV5642_HEIGHT & 0xff;
+
+       u8 total_width_high  = OV5642_TOTAL_WIDTH  >> 8;
+       u8 total_width_low   = OV5642_TOTAL_WIDTH  & 0xff;
+       u8 total_height_high = OV5642_TOTAL_HEIGHT >> 8;
+       u8 total_height_low  = OV5642_TOTAL_HEIGHT & 0xff;
+
+       ret = reg_write(client, REG_WINDOW_START_X_HIGH, start_x_high);
+       if (!ret)
+               ret = reg_write(client, REG_WINDOW_START_X_LOW, start_x_low);
+       if (!ret)
+               ret = reg_write(client, REG_WINDOW_START_Y_HIGH, start_y_high);
+       if (!ret)
+               ret = reg_write(client, REG_WINDOW_START_Y_LOW, start_y_low);
+
+       if (!ret)
+               ret = reg_write(client, REG_WINDOW_WIDTH_HIGH, width_high);
+       if (!ret)
+               ret = reg_write(client, REG_WINDOW_WIDTH_LOW , width_low);
+       if (!ret)
+               ret = reg_write(client, REG_WINDOW_HEIGHT_HIGH, height_high);
+       if (!ret)
+               ret = reg_write(client, REG_WINDOW_HEIGHT_LOW,  height_low);
+
+       if (!ret)
+               ret = reg_write(client, REG_OUT_WIDTH_HIGH, width_high);
+       if (!ret)
+               ret = reg_write(client, REG_OUT_WIDTH_LOW , width_low);
+       if (!ret)
+               ret = reg_write(client, REG_OUT_HEIGHT_HIGH, height_high);
+       if (!ret)
+               ret = reg_write(client, REG_OUT_HEIGHT_LOW,  height_low);
+
+       if (!ret)
+               ret = reg_write(client, REG_OUT_TOTAL_WIDTH_HIGH, total_width_high);
+       if (!ret)
+               ret = reg_write(client, REG_OUT_TOTAL_WIDTH_LOW, total_width_low);
+       if (!ret)
+               ret = reg_write(client, REG_OUT_TOTAL_HEIGHT_HIGH, total_height_high);
+       if (!ret)
+               ret = reg_write(client, REG_OUT_TOTAL_HEIGHT_LOW,  total_height_low);
+
+       return ret;
+}
+
+static int ov5642_try_fmt(struct v4l2_subdev *sd,
+                         struct v4l2_mbus_framefmt *mf)
+{
+       const struct ov5642_datafmt *fmt = ov5642_find_datafmt(mf->code);
+
+       dev_dbg(sd->v4l2_dev->dev, "%s(%u) width: %u heigth: %u\n",
+                       __func__, mf->code, mf->width, mf->height);
+
+       if (!fmt) {
+               mf->code        = ov5642_colour_fmts[0].code;
+               mf->colorspace  = ov5642_colour_fmts[0].colorspace;
+       }
+
+       mf->width       = OV5642_WIDTH;
+       mf->height      = OV5642_HEIGHT;
+       mf->field       = V4L2_FIELD_NONE;
+
+       return 0;
+}
+
+static int ov5642_s_fmt(struct v4l2_subdev *sd,
+                       struct v4l2_mbus_framefmt *mf)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5642 *priv = to_ov5642(client);
+
+       dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
+
+       /* MIPI CSI could have changed the format, double-check */
+       if (!ov5642_find_datafmt(mf->code))
+               return -EINVAL;
+
+       ov5642_try_fmt(sd, mf);
+
+       priv->fmt = ov5642_find_datafmt(mf->code);
+
+       ov5642_write_array(client, ov5642_default_regs_init);
+       ov5642_set_resolution(client);
+       ov5642_write_array(client, ov5642_default_regs_finalise);
+
+       return 0;
+}
+
+static int ov5642_g_fmt(struct v4l2_subdev *sd,
+                       struct v4l2_mbus_framefmt *mf)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5642 *priv = to_ov5642(client);
+
+       const struct ov5642_datafmt *fmt = priv->fmt;
+
+       mf->code        = fmt->code;
+       mf->colorspace  = fmt->colorspace;
+       mf->width       = OV5642_WIDTH;
+       mf->height      = OV5642_HEIGHT;
+       mf->field       = V4L2_FIELD_NONE;
+
+       return 0;
+}
+
+static int ov5642_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+                          enum v4l2_mbus_pixelcode *code)
+{
+       if (index >= ARRAY_SIZE(ov5642_colour_fmts))
+               return -EINVAL;
+
+       *code = ov5642_colour_fmts[index].code;
+       return 0;
+}
+
+static int ov5642_g_chip_ident(struct v4l2_subdev *sd,
+                              struct v4l2_dbg_chip_ident *id)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+               return -EINVAL;
+
+       if (id->match.addr != client->addr)
+               return -ENODEV;
+
+       id->ident       = V4L2_IDENT_OV5642;
+       id->revision    = 0;
+
+       return 0;
+}
+
+static int ov5642_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+       struct v4l2_rect *rect = &a->c;
+
+       a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       rect->top       = 0;
+       rect->left      = 0;
+       rect->width     = OV5642_WIDTH;
+       rect->height    = OV5642_HEIGHT;
+
+       return 0;
+}
+
+static int ov5642_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+       a->bounds.left                  = 0;
+       a->bounds.top                   = 0;
+       a->bounds.width                 = OV5642_WIDTH;
+       a->bounds.height                = OV5642_HEIGHT;
+       a->defrect                      = a->bounds;
+       a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       a->pixelaspect.numerator        = 1;
+       a->pixelaspect.denominator      = 1;
+
+       return 0;
+}
+
+static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = {
+       .s_mbus_fmt     = ov5642_s_fmt,
+       .g_mbus_fmt     = ov5642_g_fmt,
+       .try_mbus_fmt   = ov5642_try_fmt,
+       .enum_mbus_fmt  = ov5642_enum_fmt,
+       .g_crop         = ov5642_g_crop,
+       .cropcap        = ov5642_cropcap,
+};
+
+static struct v4l2_subdev_core_ops ov5642_subdev_core_ops = {
+       .g_chip_ident   = ov5642_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .g_register     = ov5642_get_register,
+       .s_register     = ov5642_set_register,
+#endif
+};
+
+static struct v4l2_subdev_ops ov5642_subdev_ops = {
+       .core   = &ov5642_subdev_core_ops,
+       .video  = &ov5642_subdev_video_ops,
+};
+
+/*
+ * We have to provide soc-camera operations, but we don't have anything to say
+ * there. The MIPI CSI2 driver will provide .query_bus_param and .set_bus_param
+ */
+static unsigned long soc_ov5642_query_bus_param(struct soc_camera_device *icd)
+{
+       return 0;
+}
+
+static int soc_ov5642_set_bus_param(struct soc_camera_device *icd,
+                                unsigned long flags)
+{
+       return -EINVAL;
+}
+
+static struct soc_camera_ops soc_ov5642_ops = {
+       .query_bus_param        = soc_ov5642_query_bus_param,
+       .set_bus_param          = soc_ov5642_set_bus_param,
+};
+
+static int ov5642_video_probe(struct soc_camera_device *icd,
+                             struct i2c_client *client)
+{
+       int ret;
+       u8 id_high, id_low;
+       u16 id;
+
+       /* Read sensor Model ID */
+       ret = reg_read(client, REG_CHIP_ID_HIGH, &id_high);
+       if (ret < 0)
+               return ret;
+
+       id = id_high << 8;
+
+       ret = reg_read(client, REG_CHIP_ID_LOW, &id_low);
+       if (ret < 0)
+               return ret;
+
+       id |= id_low;
+
+       dev_info(&client->dev, "Chip ID 0x%04x detected\n", id);
+
+       if (id != 0x5642)
+               return -ENODEV;
+
+       return 0;
+}
+
+static int ov5642_probe(struct i2c_client *client,
+                       const struct i2c_device_id *did)
+{
+       struct ov5642 *priv;
+       struct soc_camera_device *icd = client->dev.platform_data;
+       struct soc_camera_link *icl;
+       int ret;
+
+       if (!icd) {
+               dev_err(&client->dev, "OV5642: missing soc-camera data!\n");
+               return -EINVAL;
+       }
+
+       icl = to_soc_camera_link(icd);
+       if (!icl) {
+               dev_err(&client->dev, "OV5642: missing platform data!\n");
+               return -EINVAL;
+       }
+
+       priv = kzalloc(sizeof(struct ov5642), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       v4l2_i2c_subdev_init(&priv->subdev, client, &ov5642_subdev_ops);
+
+       icd->ops        = &soc_ov5642_ops;
+       priv->fmt       = &ov5642_colour_fmts[0];
+
+       ret = ov5642_video_probe(icd, client);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       icd->ops = NULL;
+       kfree(priv);
+       return ret;
+}
+
+static int ov5642_remove(struct i2c_client *client)
+{
+       struct ov5642 *priv = to_ov5642(client);
+       struct soc_camera_device *icd = client->dev.platform_data;
+       struct soc_camera_link *icl = to_soc_camera_link(icd);
+
+       icd->ops = NULL;
+       if (icl->free_bus)
+               icl->free_bus(icl);
+       kfree(priv);
+
+       return 0;
+}
+
+static const struct i2c_device_id ov5642_id[] = {
+       { "ov5642", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ov5642_id);
+
+static struct i2c_driver ov5642_i2c_driver = {
+       .driver = {
+               .name = "ov5642",
+       },
+       .probe          = ov5642_probe,
+       .remove         = ov5642_remove,
+       .id_table       = ov5642_id,
+};
+
+static int __init ov5642_mod_init(void)
+{
+       return i2c_add_driver(&ov5642_i2c_driver);
+}
+
+static void __exit ov5642_mod_exit(void)
+{
+       i2c_del_driver(&ov5642_i2c_driver);
+}
+
+module_init(ov5642_mod_init);
+module_exit(ov5642_mod_exit);
+
+MODULE_DESCRIPTION("Omnivision OV5642 Camera driver");
+MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>");
+MODULE_LICENSE("GPL v2");
index d4e7c11..8aa0585 100644 (file)
@@ -19,8 +19,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-mediabus.h>
-
-#include "ov7670.h"
+#include <media/ov7670.h>
 
 MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
 MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors");
index 48895ef..397870f 100644 (file)
@@ -1032,13 +1032,9 @@ static int ov772x_video_probe(struct soc_camera_device *icd,
        u8                  pid, ver;
        const char         *devname;
 
-       /*
-        * We must have a parent by now. And it cannot be a wrong one.
-        * So this entire test is completely redundant.
-        */
-       if (!icd->dev.parent ||
-           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
-               return -ENODEV;
+       /* We must have a parent by now. And it cannot be a wrong one. */
+       BUG_ON(!icd->parent ||
+              to_soc_camera_host(icd->parent)->nr != icd->iface);
 
        /*
         * check and show product ID and manufacturer ID
index 5173ac4..3681a6f 100644 (file)
@@ -657,16 +657,9 @@ static int ov9640_video_probe(struct soc_camera_device *icd,
        const char      *devname;
        int             ret = 0;
 
-       /*
-        * We must have a parent by now. And it cannot be a wrong one.
-        * So this entire test is completely redundant.
-        */
-       if (!icd->dev.parent ||
-           to_soc_camera_host(icd->dev.parent)->nr != icd->iface) {
-               dev_err(&client->dev, "Parent missing or invalid!\n");
-               ret = -ENODEV;
-               goto err;
-       }
+       /* We must have a parent by now. And it cannot be a wrong one. */
+       BUG_ON(!icd->parent ||
+              to_soc_camera_host(icd->parent)->nr != icd->iface);
 
        /*
         * check and show product ID and manufacturer ID
index 4d4ee4f..edd1ffc 100644 (file)
 #define OV9740_Y_ADDR_START_LO         0x0347
 #define OV9740_X_ADDR_END_HI           0x0348
 #define OV9740_X_ADDR_END_LO           0x0349
-#define OV9740_Y_ADDR_END_HI           0x034A
-#define OV9740_Y_ADDR_END_LO           0x034B
-#define OV9740_X_OUTPUT_SIZE_HI                0x034C
-#define OV9740_X_OUTPUT_SIZE_LO                0x034D
-#define OV9740_Y_OUTPUT_SIZE_HI                0x034E
-#define OV9740_Y_OUTPUT_SIZE_LO                0x034F
+#define OV9740_Y_ADDR_END_HI           0x034a
+#define OV9740_Y_ADDR_END_LO           0x034b
+#define OV9740_X_OUTPUT_SIZE_HI                0x034c
+#define OV9740_X_OUTPUT_SIZE_LO                0x034d
+#define OV9740_Y_OUTPUT_SIZE_HI                0x034e
+#define OV9740_Y_OUTPUT_SIZE_LO                0x034f
 
 /* IO Control Registers */
 #define OV9740_IO_CREL00               0x3002
@@ -68,6 +68,7 @@
 #define OV9740_ANALOG_CTRL04           0x3604
 #define OV9740_ANALOG_CTRL10           0x3610
 #define OV9740_ANALOG_CTRL12           0x3612
+#define OV9740_ANALOG_CTRL15           0x3615
 #define OV9740_ANALOG_CTRL20           0x3620
 #define OV9740_ANALOG_CTRL21           0x3621
 #define OV9740_ANALOG_CTRL22           0x3622
 #define OV9740_TIMING_CTRL35           0x3835
 
 /* Banding Filter */
-#define OV9740_AEC_MAXEXPO_60_H                0x3A02
-#define OV9740_AEC_MAXEXPO_60_L                0x3A03
-#define OV9740_AEC_B50_STEP_HI         0x3A08
-#define OV9740_AEC_B50_STEP_LO         0x3A09
-#define OV9740_AEC_B60_STEP_HI         0x3A0A
-#define OV9740_AEC_B60_STEP_LO         0x3A0B
-#define OV9740_AEC_CTRL0D              0x3A0D
-#define OV9740_AEC_CTRL0E              0x3A0E
-#define OV9740_AEC_MAXEXPO_50_H                0x3A14
-#define OV9740_AEC_MAXEXPO_50_L                0x3A15
+#define OV9740_AEC_MAXEXPO_60_H                0x3a02
+#define OV9740_AEC_MAXEXPO_60_L                0x3a03
+#define OV9740_AEC_B50_STEP_HI         0x3a08
+#define OV9740_AEC_B50_STEP_LO         0x3a09
+#define OV9740_AEC_B60_STEP_HI         0x3a0a
+#define OV9740_AEC_B60_STEP_LO         0x3a0b
+#define OV9740_AEC_CTRL0D              0x3a0d
+#define OV9740_AEC_CTRL0E              0x3a0e
+#define OV9740_AEC_MAXEXPO_50_H                0x3a14
+#define OV9740_AEC_MAXEXPO_50_L                0x3a15
 
 /* AEC/AGC Control */
 #define OV9740_AEC_ENABLE              0x3503
-#define OV9740_GAIN_CEILING_01         0x3A18
-#define OV9740_GAIN_CEILING_02         0x3A19
-#define OV9740_AEC_HI_THRESHOLD                0x3A11
-#define OV9740_AEC_3A1A                        0x3A1A
-#define OV9740_AEC_CTRL1B_WPT2         0x3A1B
-#define OV9740_AEC_CTRL0F_WPT          0x3A0F
-#define OV9740_AEC_CTRL10_BPT          0x3A10
-#define OV9740_AEC_CTRL1E_BPT2         0x3A1E
-#define OV9740_AEC_LO_THRESHOLD                0x3A1F
+#define OV9740_GAIN_CEILING_01         0x3a18
+#define OV9740_GAIN_CEILING_02         0x3a19
+#define OV9740_AEC_HI_THRESHOLD                0x3a11
+#define OV9740_AEC_3A1A                        0x3a1a
+#define OV9740_AEC_CTRL1B_WPT2         0x3a1b
+#define OV9740_AEC_CTRL0F_WPT          0x3a0f
+#define OV9740_AEC_CTRL10_BPT          0x3a10
+#define OV9740_AEC_CTRL1E_BPT2         0x3a1e
+#define OV9740_AEC_LO_THRESHOLD                0x3a1f
 
 /* BLC Control */
 #define OV9740_BLC_AUTO_ENABLE         0x4002
 #define OV9740_VT_SYS_CLK_DIV          0x0303
 #define OV9740_VT_PIX_CLK_DIV          0x0301
 #define OV9740_PLL_CTRL3010            0x3010
-#define OV9740_VFIFO_CTRL00            0x460E
+#define OV9740_VFIFO_CTRL00            0x460e
 
 /* ISP Control */
 #define OV9740_ISP_CTRL00              0x5000
 #define OV9740_ISP_CTRL05              0x5005
 #define OV9740_ISP_CTRL12              0x5012
 #define OV9740_ISP_CTRL19              0x5019
-#define OV9740_ISP_CTRL1A              0x501A
-#define OV9740_ISP_CTRL1E              0x501E
-#define OV9740_ISP_CTRL1F              0x501F
+#define OV9740_ISP_CTRL1A              0x501a
+#define OV9740_ISP_CTRL1E              0x501e
+#define OV9740_ISP_CTRL1F              0x501f
 #define OV9740_ISP_CTRL20              0x5020
 #define OV9740_ISP_CTRL21              0x5021
 
 #define OV9740_AWB_ADV_CTRL04          0x5187
 #define OV9740_AWB_ADV_CTRL05          0x5188
 #define OV9740_AWB_ADV_CTRL06          0x5189
-#define OV9740_AWB_ADV_CTRL07          0x518A
-#define OV9740_AWB_ADV_CTRL08          0x518B
-#define OV9740_AWB_ADV_CTRL09          0x518C
-#define OV9740_AWB_ADV_CTRL10          0x518D
-#define OV9740_AWB_ADV_CTRL11          0x518E
-#define OV9740_AWB_CTRL0F              0x518F
+#define OV9740_AWB_ADV_CTRL07          0x518a
+#define OV9740_AWB_ADV_CTRL08          0x518b
+#define OV9740_AWB_ADV_CTRL09          0x518c
+#define OV9740_AWB_ADV_CTRL10          0x518d
+#define OV9740_AWB_ADV_CTRL11          0x518e
+#define OV9740_AWB_CTRL0F              0x518f
 #define OV9740_AWB_CTRL10              0x5190
 #define OV9740_AWB_CTRL11              0x5191
 #define OV9740_AWB_CTRL12              0x5192
 #define OV9740_MIPI_CTRL_3012          0x3012
 #define OV9740_SC_CMMM_MIPI_CTR                0x3014
 
-/* supported resolutions */
-enum {
-       OV9740_VGA,
-       OV9740_720P,
-};
-
-struct ov9740_resolution {
-       unsigned int width;
-       unsigned int height;
-};
-
-static struct ov9740_resolution ov9740_resolutions[] = {
-       [OV9740_VGA] = {
-               .width  = 640,
-               .height = 480,
-       },
-       [OV9740_720P] = {
-               .width  = 1280,
-               .height = 720,
-       },
-};
+#define OV9740_MAX_WIDTH               1280
+#define OV9740_MAX_HEIGHT              720
 
 /* Misc. structures */
 struct ov9740_reg {
@@ -219,9 +201,16 @@ struct ov9740_priv {
 
        bool                            flag_vflip;
        bool                            flag_hflip;
+
+       /* For suspend/resume. */
+       struct v4l2_mbus_framefmt       current_mf;
+       bool                            current_enable;
 };
 
 static const struct ov9740_reg ov9740_defaults[] = {
+       /* Software Reset */
+       { OV9740_SOFTWARE_RESET,        0x01 },
+
        /* Banding Filter */
        { OV9740_AEC_B50_STEP_HI,       0x00 },
        { OV9740_AEC_B50_STEP_LO,       0xe8 },
@@ -241,36 +230,36 @@ static const struct ov9740_reg ov9740_defaults[] = {
        /* Un-documented OV9740 registers */
        { 0x5800, 0x29 }, { 0x5801, 0x25 }, { 0x5802, 0x20 }, { 0x5803, 0x21 },
        { 0x5804, 0x26 }, { 0x5805, 0x2e }, { 0x5806, 0x11 }, { 0x5807, 0x0c },
-       { 0x5808, 0x09 }, { 0x5809, 0x0a }, { 0x580A, 0x0e }, { 0x580B, 0x16 },
-       { 0x580C, 0x06 }, { 0x580D, 0x02 }, { 0x580E, 0x00 }, { 0x580F, 0x00 },
+       { 0x5808, 0x09 }, { 0x5809, 0x0a }, { 0x580a, 0x0e }, { 0x580b, 0x16 },
+       { 0x580c, 0x06 }, { 0x580d, 0x02 }, { 0x580e, 0x00 }, { 0x580f, 0x00 },
        { 0x5810, 0x04 }, { 0x5811, 0x0a }, { 0x5812, 0x05 }, { 0x5813, 0x02 },
        { 0x5814, 0x00 }, { 0x5815, 0x00 }, { 0x5816, 0x03 }, { 0x5817, 0x09 },
-       { 0x5818, 0x0f }, { 0x5819, 0x0a }, { 0x581A, 0x07 }, { 0x581B, 0x08 },
-       { 0x581C, 0x0b }, { 0x581D, 0x14 }, { 0x581E, 0x28 }, { 0x581F, 0x23 },
+       { 0x5818, 0x0f }, { 0x5819, 0x0a }, { 0x581a, 0x07 }, { 0x581b, 0x08 },
+       { 0x581c, 0x0b }, { 0x581d, 0x14 }, { 0x581e, 0x28 }, { 0x581f, 0x23 },
        { 0x5820, 0x1d }, { 0x5821, 0x1e }, { 0x5822, 0x24 }, { 0x5823, 0x2a },
        { 0x5824, 0x4f }, { 0x5825, 0x6f }, { 0x5826, 0x5f }, { 0x5827, 0x7f },
-       { 0x5828, 0x9f }, { 0x5829, 0x5f }, { 0x582A, 0x8f }, { 0x582B, 0x9e },
-       { 0x582C, 0x8f }, { 0x582D, 0x9f }, { 0x582E, 0x4f }, { 0x582F, 0x87 },
+       { 0x5828, 0x9f }, { 0x5829, 0x5f }, { 0x582a, 0x8f }, { 0x582b, 0x9e },
+       { 0x582c, 0x8f }, { 0x582d, 0x9f }, { 0x582e, 0x4f }, { 0x582f, 0x87 },
        { 0x5830, 0x86 }, { 0x5831, 0x97 }, { 0x5832, 0xae }, { 0x5833, 0x3f },
        { 0x5834, 0x8e }, { 0x5835, 0x7c }, { 0x5836, 0x7e }, { 0x5837, 0xaf },
-       { 0x5838, 0x8f }, { 0x5839, 0x8f }, { 0x583A, 0x9f }, { 0x583B, 0x7f },
-       { 0x583C, 0x5f },
+       { 0x5838, 0x8f }, { 0x5839, 0x8f }, { 0x583a, 0x9f }, { 0x583b, 0x7f },
+       { 0x583c, 0x5f },
 
        /* Y Gamma */
        { 0x5480, 0x07 }, { 0x5481, 0x18 }, { 0x5482, 0x2c }, { 0x5483, 0x4e },
        { 0x5484, 0x5e }, { 0x5485, 0x6b }, { 0x5486, 0x77 }, { 0x5487, 0x82 },
-       { 0x5488, 0x8c }, { 0x5489, 0x95 }, { 0x548A, 0xa4 }, { 0x548B, 0xb1 },
-       { 0x548C, 0xc6 }, { 0x548D, 0xd8 }, { 0x548E, 0xe9 },
+       { 0x5488, 0x8c }, { 0x5489, 0x95 }, { 0x548a, 0xa4 }, { 0x548b, 0xb1 },
+       { 0x548c, 0xc6 }, { 0x548d, 0xd8 }, { 0x548e, 0xe9 },
 
        /* UV Gamma */
        { 0x5490, 0x0f }, { 0x5491, 0xff }, { 0x5492, 0x0d }, { 0x5493, 0x05 },
        { 0x5494, 0x07 }, { 0x5495, 0x1a }, { 0x5496, 0x04 }, { 0x5497, 0x01 },
-       { 0x5498, 0x03 }, { 0x5499, 0x53 }, { 0x549A, 0x02 }, { 0x549B, 0xeb },
-       { 0x549C, 0x02 }, { 0x549D, 0xa0 }, { 0x549E, 0x02 }, { 0x549F, 0x67 },
-       { 0x54A0, 0x02 }, { 0x54A1, 0x3b }, { 0x54A2, 0x02 }, { 0x54A3, 0x18 },
-       { 0x54A4, 0x01 }, { 0x54A5, 0xe7 }, { 0x54A6, 0x01 }, { 0x54A7, 0xc3 },
-       { 0x54A8, 0x01 }, { 0x54A9, 0x94 }, { 0x54AA, 0x01 }, { 0x54AB, 0x72 },
-       { 0x54AC, 0x01 }, { 0x54AD, 0x57 },
+       { 0x5498, 0x03 }, { 0x5499, 0x53 }, { 0x549a, 0x02 }, { 0x549b, 0xeb },
+       { 0x549c, 0x02 }, { 0x549d, 0xa0 }, { 0x549e, 0x02 }, { 0x549f, 0x67 },
+       { 0x54a0, 0x02 }, { 0x54a1, 0x3b }, { 0x54a2, 0x02 }, { 0x54a3, 0x18 },
+       { 0x54a4, 0x01 }, { 0x54a5, 0xe7 }, { 0x54a6, 0x01 }, { 0x54a7, 0xc3 },
+       { 0x54a8, 0x01 }, { 0x54a9, 0x94 }, { 0x54aa, 0x01 }, { 0x54ab, 0x72 },
+       { 0x54ac, 0x01 }, { 0x54ad, 0x57 },
 
        /* AWB */
        { OV9740_AWB_CTRL00,            0xf0 },
@@ -296,18 +285,18 @@ static const struct ov9740_reg ov9740_defaults[] = {
        { OV9740_AWB_CTRL14,            0x00 },
 
        /* CIP */
-       { 0x530D, 0x12 },
+       { 0x530d, 0x12 },
 
        /* CMX */
        { 0x5380, 0x01 }, { 0x5381, 0x00 }, { 0x5382, 0x00 }, { 0x5383, 0x17 },
        { 0x5384, 0x00 }, { 0x5385, 0x01 }, { 0x5386, 0x00 }, { 0x5387, 0x00 },
-       { 0x5388, 0x00 }, { 0x5389, 0xe0 }, { 0x538A, 0x00 }, { 0x538B, 0x20 },
-       { 0x538C, 0x00 }, { 0x538D, 0x00 }, { 0x538E, 0x00 }, { 0x538F, 0x16 },
+       { 0x5388, 0x00 }, { 0x5389, 0xe0 }, { 0x538a, 0x00 }, { 0x538b, 0x20 },
+       { 0x538c, 0x00 }, { 0x538d, 0x00 }, { 0x538e, 0x00 }, { 0x538f, 0x16 },
        { 0x5390, 0x00 }, { 0x5391, 0x9c }, { 0x5392, 0x00 }, { 0x5393, 0xa0 },
        { 0x5394, 0x18 },
 
        /* 50/60 Detection */
-       { 0x3C0A, 0x9c }, { 0x3C0B, 0x3f },
+       { 0x3c0a, 0x9c }, { 0x3c0b, 0x3f },
 
        /* Output Select */
        { OV9740_IO_OUTPUT_SEL01,       0x00 },
@@ -333,6 +322,7 @@ static const struct ov9740_reg ov9740_defaults[] = {
        { OV9740_ANALOG_CTRL10,         0xa1 },
        { OV9740_ANALOG_CTRL12,         0x24 },
        { OV9740_ANALOG_CTRL22,         0x9f },
+       { OV9740_ANALOG_CTRL15,         0xf0 },
 
        /* Sensor Control */
        { OV9740_SENSOR_CTRL03,         0x42 },
@@ -385,7 +375,7 @@ static const struct ov9740_reg ov9740_defaults[] = {
        { OV9740_LN_LENGTH_PCK_LO,      0x62 },
 
        /* MIPI Control */
-       { OV9740_MIPI_CTRL00,           0x44 },
+       { OV9740_MIPI_CTRL00,           0x44 }, /* 0x64 for discontinuous clk */
        { OV9740_MIPI_3837,             0x01 },
        { OV9740_MIPI_CTRL01,           0x0f },
        { OV9740_MIPI_CTRL03,           0x05 },
@@ -393,54 +383,9 @@ static const struct ov9740_reg ov9740_defaults[] = {
        { OV9740_VFIFO_RD_CTRL,         0x16 },
        { OV9740_MIPI_CTRL_3012,        0x70 },
        { OV9740_SC_CMMM_MIPI_CTR,      0x01 },
-};
-
-static const struct ov9740_reg ov9740_regs_vga[] = {
-       { OV9740_X_ADDR_START_HI,       0x00 },
-       { OV9740_X_ADDR_START_LO,       0xa0 },
-       { OV9740_Y_ADDR_START_HI,       0x00 },
-       { OV9740_Y_ADDR_START_LO,       0x00 },
-       { OV9740_X_ADDR_END_HI,         0x04 },
-       { OV9740_X_ADDR_END_LO,         0x63 },
-       { OV9740_Y_ADDR_END_HI,         0x02 },
-       { OV9740_Y_ADDR_END_LO,         0xd3 },
-       { OV9740_X_OUTPUT_SIZE_HI,      0x02 },
-       { OV9740_X_OUTPUT_SIZE_LO,      0x80 },
-       { OV9740_Y_OUTPUT_SIZE_HI,      0x01 },
-       { OV9740_Y_OUTPUT_SIZE_LO,      0xe0 },
-       { OV9740_ISP_CTRL1E,            0x03 },
-       { OV9740_ISP_CTRL1F,            0xc0 },
-       { OV9740_ISP_CTRL20,            0x02 },
-       { OV9740_ISP_CTRL21,            0xd0 },
-       { OV9740_VFIFO_READ_START_HI,   0x01 },
-       { OV9740_VFIFO_READ_START_LO,   0x40 },
-       { OV9740_ISP_CTRL00,            0xff },
-       { OV9740_ISP_CTRL01,            0xff },
-       { OV9740_ISP_CTRL03,            0xff },
-};
 
-static const struct ov9740_reg ov9740_regs_720p[] = {
-       { OV9740_X_ADDR_START_HI,       0x00 },
-       { OV9740_X_ADDR_START_LO,       0x00 },
-       { OV9740_Y_ADDR_START_HI,       0x00 },
-       { OV9740_Y_ADDR_START_LO,       0x00 },
-       { OV9740_X_ADDR_END_HI,         0x05 },
-       { OV9740_X_ADDR_END_LO,         0x03 },
-       { OV9740_Y_ADDR_END_HI,         0x02 },
-       { OV9740_Y_ADDR_END_LO,         0xd3 },
-       { OV9740_X_OUTPUT_SIZE_HI,      0x05 },
-       { OV9740_X_OUTPUT_SIZE_LO,      0x00 },
-       { OV9740_Y_OUTPUT_SIZE_HI,      0x02 },
-       { OV9740_Y_OUTPUT_SIZE_LO,      0xd0 },
-       { OV9740_ISP_CTRL1E,            0x05 },
-       { OV9740_ISP_CTRL1F,            0x00 },
-       { OV9740_ISP_CTRL20,            0x02 },
-       { OV9740_ISP_CTRL21,            0xd0 },
-       { OV9740_VFIFO_READ_START_HI,   0x02 },
-       { OV9740_VFIFO_READ_START_LO,   0x30 },
-       { OV9740_ISP_CTRL00,            0xff },
-       { OV9740_ISP_CTRL01,            0xef },
-       { OV9740_ISP_CTRL03,            0xff },
+       /* YUYV order */
+       { OV9740_ISP_CTRL19,            0x02 },
 };
 
 static enum v4l2_mbus_pixelcode ov9740_codes[] = {
@@ -537,7 +482,8 @@ static int ov9740_reg_rmw(struct i2c_client *client, u16 reg, u8 set, u8 unset)
        ret = ov9740_reg_read(client, reg, &val);
        if (ret < 0) {
                dev_err(&client->dev,
-                       "[Read]-Modify-Write of register %02x failed!\n", reg);
+                       "[Read]-Modify-Write of register 0x%04x failed!\n",
+                       reg);
                return ret;
        }
 
@@ -547,7 +493,8 @@ static int ov9740_reg_rmw(struct i2c_client *client, u16 reg, u8 set, u8 unset)
        ret = ov9740_reg_write(client, reg, val);
        if (ret < 0) {
                dev_err(&client->dev,
-                       "Read-Modify-[Write] of register %02x failed!\n", reg);
+                       "Read-Modify-[Write] of register 0x%04x failed!\n",
+                       reg);
                return ret;
        }
 
@@ -608,6 +555,8 @@ static int ov9740_s_stream(struct v4l2_subdev *sd, int enable)
                                               0x00);
        }
 
+       priv->current_enable = enable;
+
        return ret;
 }
 
@@ -630,126 +579,127 @@ static unsigned long ov9740_query_bus_param(struct soc_camera_device *icd)
        return soc_camera_apply_sensor_flags(icl, flags);
 }
 
-/* Get status of additional camera capabilities */
-static int ov9740_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-       struct ov9740_priv *priv = to_ov9740(sd);
-
-       switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               ctrl->value = priv->flag_vflip;
-               break;
-       case V4L2_CID_HFLIP:
-               ctrl->value = priv->flag_hflip;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/* Set status of additional camera capabilities */
-static int ov9740_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-       struct ov9740_priv *priv = to_ov9740(sd);
-
-       switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               priv->flag_vflip = ctrl->value;
-               break;
-       case V4L2_CID_HFLIP:
-               priv->flag_hflip = ctrl->value;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/* Get chip identification */
-static int ov9740_g_chip_ident(struct v4l2_subdev *sd,
-                              struct v4l2_dbg_chip_ident *id)
+/* select nearest higher resolution for capture */
+static void ov9740_res_roundup(u32 *width, u32 *height)
 {
-       struct ov9740_priv *priv = to_ov9740(sd);
+       /* Width must be a multiple of 4 pixels. */
+       *width = ALIGN(*width, 4);
 
-       id->ident = priv->ident;
-       id->revision = priv->revision;
+       /* Max resolution is 1280x720 (720p). */
+       if (*width > OV9740_MAX_WIDTH)
+               *width = OV9740_MAX_WIDTH;
 
-       return 0;
+       if (*height > OV9740_MAX_HEIGHT)
+               *height = OV9740_MAX_HEIGHT;
 }
 
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int ov9740_get_register(struct v4l2_subdev *sd,
-                              struct v4l2_dbg_register *reg)
+/* Setup registers according to resolution and color encoding */
+static int ov9740_set_res(struct i2c_client *client, u32 width, u32 height)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       u32 x_start;
+       u32 y_start;
+       u32 x_end;
+       u32 y_end;
+       bool scaling = 0;
+       u32 scale_input_x;
+       u32 scale_input_y;
        int ret;
-       u8 val;
-
-       if (reg->reg & ~0xffff)
-               return -EINVAL;
 
-       reg->size = 2;
-
-       ret = ov9740_reg_read(client, reg->reg, &val);
-       if (ret)
-               return ret;
-
-       reg->val = (__u64)val;
+       if ((width != OV9740_MAX_WIDTH) || (height != OV9740_MAX_HEIGHT))
+               scaling = 1;
 
-       return ret;
-}
-
-static int ov9740_set_register(struct v4l2_subdev *sd,
-                              struct v4l2_dbg_register *reg)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       /*
+        * Try to use as much of the sensor area as possible when supporting
+        * smaller resolutions.  Depending on the aspect ratio of the
+        * chosen resolution, we can either use the full width of the sensor,
+        * or the full height of the sensor (or both if the aspect ratio is
+        * the same as 1280x720.
+        */
+       if ((OV9740_MAX_WIDTH * height) > (OV9740_MAX_HEIGHT * width)) {
+               scale_input_x = (OV9740_MAX_HEIGHT * width) / height;
+               scale_input_y = OV9740_MAX_HEIGHT;
+       } else {
+               scale_input_x = OV9740_MAX_WIDTH;
+               scale_input_y = (OV9740_MAX_WIDTH * height) / width;
+       }
 
-       if (reg->reg & ~0xffff || reg->val & ~0xff)
-               return -EINVAL;
+       /* These describe the area of the sensor to use. */
+       x_start = (OV9740_MAX_WIDTH - scale_input_x) / 2;
+       y_start = (OV9740_MAX_HEIGHT - scale_input_y) / 2;
+       x_end = x_start + scale_input_x - 1;
+       y_end = y_start + scale_input_y - 1;
 
-       return ov9740_reg_write(client, reg->reg, reg->val);
-}
-#endif
+       ret = ov9740_reg_write(client, OV9740_X_ADDR_START_HI, x_start >> 8);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_X_ADDR_START_LO, x_start & 0xff);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_Y_ADDR_START_HI, y_start >> 8);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_Y_ADDR_START_LO, y_start & 0xff);
+       if (ret)
+               goto done;
 
-/* select nearest higher resolution for capture */
-static void ov9740_res_roundup(u32 *width, u32 *height)
-{
-       int i;
+       ret = ov9740_reg_write(client, OV9740_X_ADDR_END_HI, x_end >> 8);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_X_ADDR_END_LO, x_end & 0xff);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_Y_ADDR_END_HI, y_end >> 8);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_Y_ADDR_END_LO, y_end & 0xff);
+       if (ret)
+               goto done;
 
-       for (i = 0; i < ARRAY_SIZE(ov9740_resolutions); i++)
-               if ((ov9740_resolutions[i].width >= *width) &&
-                   (ov9740_resolutions[i].height >= *height)) {
-                       *width = ov9740_resolutions[i].width;
-                       *height = ov9740_resolutions[i].height;
-                       return;
-               }
+       ret = ov9740_reg_write(client, OV9740_X_OUTPUT_SIZE_HI, width >> 8);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_X_OUTPUT_SIZE_LO, width & 0xff);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_Y_OUTPUT_SIZE_HI, height >> 8);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_Y_OUTPUT_SIZE_LO, height & 0xff);
+       if (ret)
+               goto done;
 
-       *width = ov9740_resolutions[OV9740_720P].width;
-       *height = ov9740_resolutions[OV9740_720P].height;
-}
+       ret = ov9740_reg_write(client, OV9740_ISP_CTRL1E, scale_input_x >> 8);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_ISP_CTRL1F, scale_input_x & 0xff);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_ISP_CTRL20, scale_input_y >> 8);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_ISP_CTRL21, scale_input_y & 0xff);
+       if (ret)
+               goto done;
 
-/* Setup registers according to resolution and color encoding */
-static int ov9740_set_res(struct i2c_client *client, u32 width)
-{
-       int ret;
+       ret = ov9740_reg_write(client, OV9740_VFIFO_READ_START_HI,
+                              (scale_input_x - width) >> 8);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_VFIFO_READ_START_LO,
+                              (scale_input_x - width) & 0xff);
+       if (ret)
+               goto done;
 
-       /* select register configuration for given resolution */
-       if (width == ov9740_resolutions[OV9740_VGA].width) {
-               dev_dbg(&client->dev, "Setting image size to 640x480\n");
-               ret = ov9740_reg_write_array(client, ov9740_regs_vga,
-                                            ARRAY_SIZE(ov9740_regs_vga));
-       } else if (width == ov9740_resolutions[OV9740_720P].width) {
-               dev_dbg(&client->dev, "Setting image size to 1280x720\n");
-               ret = ov9740_reg_write_array(client, ov9740_regs_720p,
-                                            ARRAY_SIZE(ov9740_regs_720p));
-       } else {
-               dev_err(&client->dev, "Failed to select resolution!\n");
-               return -EINVAL;
-       }
+       ret = ov9740_reg_write(client, OV9740_ISP_CTRL00, 0xff);
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_ISP_CTRL01, 0xef |
+                                                         (scaling << 4));
+       if (ret)
+               goto done;
+       ret = ov9740_reg_write(client, OV9740_ISP_CTRL03, 0xff);
 
+done:
        return ret;
 }
 
@@ -758,6 +708,7 @@ static int ov9740_s_fmt(struct v4l2_subdev *sd,
                        struct v4l2_mbus_framefmt *mf)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov9740_priv *priv = to_ov9740(sd);
        enum v4l2_colorspace cspace;
        enum v4l2_mbus_pixelcode code = mf->code;
        int ret;
@@ -777,13 +728,15 @@ static int ov9740_s_fmt(struct v4l2_subdev *sd,
        if (ret < 0)
                return ret;
 
-       ret = ov9740_set_res(client, mf->width);
+       ret = ov9740_set_res(client, mf->width, mf->height);
        if (ret < 0)
                return ret;
 
        mf->code        = code;
        mf->colorspace  = cspace;
 
+       memcpy(&priv->current_mf, mf, sizeof(struct v4l2_mbus_framefmt));
+
        return ret;
 }
 
@@ -814,8 +767,8 @@ static int ov9740_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 {
        a->bounds.left          = 0;
        a->bounds.top           = 0;
-       a->bounds.width         = ov9740_resolutions[OV9740_720P].width;
-       a->bounds.height        = ov9740_resolutions[OV9740_720P].height;
+       a->bounds.width         = OV9740_MAX_WIDTH;
+       a->bounds.height        = OV9740_MAX_HEIGHT;
        a->defrect              = a->bounds;
        a->type                 = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        a->pixelaspect.numerator        = 1;
@@ -828,13 +781,115 @@ static int ov9740_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
        a->c.left               = 0;
        a->c.top                = 0;
-       a->c.width              = ov9740_resolutions[OV9740_720P].width;
-       a->c.height             = ov9740_resolutions[OV9740_720P].height;
+       a->c.width              = OV9740_MAX_WIDTH;
+       a->c.height             = OV9740_MAX_HEIGHT;
        a->type                 = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
        return 0;
 }
 
+/* Get status of additional camera capabilities */
+static int ov9740_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+       struct ov9740_priv *priv = to_ov9740(sd);
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               ctrl->value = priv->flag_vflip;
+               break;
+       case V4L2_CID_HFLIP:
+               ctrl->value = priv->flag_hflip;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* Set status of additional camera capabilities */
+static int ov9740_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+       struct ov9740_priv *priv = to_ov9740(sd);
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               priv->flag_vflip = ctrl->value;
+               break;
+       case V4L2_CID_HFLIP:
+               priv->flag_hflip = ctrl->value;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* Get chip identification */
+static int ov9740_g_chip_ident(struct v4l2_subdev *sd,
+                              struct v4l2_dbg_chip_ident *id)
+{
+       struct ov9740_priv *priv = to_ov9740(sd);
+
+       id->ident = priv->ident;
+       id->revision = priv->revision;
+
+       return 0;
+}
+
+static int ov9740_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct ov9740_priv *priv = to_ov9740(sd);
+
+       if (!priv->current_enable)
+               return 0;
+
+       if (on) {
+               ov9740_s_fmt(sd, &priv->current_mf);
+               ov9740_s_stream(sd, priv->current_enable);
+       } else {
+               ov9740_s_stream(sd, 0);
+               priv->current_enable = true;
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov9740_get_register(struct v4l2_subdev *sd,
+                              struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       int ret;
+       u8 val;
+
+       if (reg->reg & ~0xffff)
+               return -EINVAL;
+
+       reg->size = 2;
+
+       ret = ov9740_reg_read(client, reg->reg, &val);
+       if (ret)
+               return ret;
+
+       reg->val = (__u64)val;
+
+       return ret;
+}
+
+static int ov9740_set_register(struct v4l2_subdev *sd,
+                              struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       if (reg->reg & ~0xffff || reg->val & ~0xff)
+               return -EINVAL;
+
+       return ov9740_reg_write(client, reg->reg, reg->val);
+}
+#endif
+
 static int ov9740_video_probe(struct soc_camera_device *icd,
                              struct i2c_client *client)
 {
@@ -843,16 +898,9 @@ static int ov9740_video_probe(struct soc_camera_device *icd,
        u8 modelhi, modello;
        int ret;
 
-       /*
-        * We must have a parent by now. And it cannot be a wrong one.
-        * So this entire test is completely redundant.
-        */
-       if (!icd->dev.parent ||
-           to_soc_camera_host(icd->dev.parent)->nr != icd->iface) {
-               dev_err(&client->dev, "Parent missing or invalid!\n");
-               ret = -ENODEV;
-               goto err;
-       }
+       /* We must have a parent by now. And it cannot be a wrong one. */
+       BUG_ON(!icd->parent ||
+              to_soc_camera_host(icd->parent)->nr != icd->iface);
 
        /*
         * check and show product ID and manufacturer ID
@@ -901,24 +949,24 @@ static struct soc_camera_ops ov9740_ops = {
        .num_controls           = ARRAY_SIZE(ov9740_controls),
 };
 
+static struct v4l2_subdev_video_ops ov9740_video_ops = {
+       .s_stream               = ov9740_s_stream,
+       .s_mbus_fmt             = ov9740_s_fmt,
+       .try_mbus_fmt           = ov9740_try_fmt,
+       .enum_mbus_fmt          = ov9740_enum_fmt,
+       .cropcap                = ov9740_cropcap,
+       .g_crop                 = ov9740_g_crop,
+};
+
 static struct v4l2_subdev_core_ops ov9740_core_ops = {
        .g_ctrl                 = ov9740_g_ctrl,
        .s_ctrl                 = ov9740_s_ctrl,
        .g_chip_ident           = ov9740_g_chip_ident,
+       .s_power                = ov9740_s_power,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register             = ov9740_get_register,
        .s_register             = ov9740_set_register,
 #endif
-
-};
-
-static struct v4l2_subdev_video_ops ov9740_video_ops = {
-       .s_stream               = ov9740_s_stream,
-       .s_mbus_fmt             = ov9740_s_fmt,
-       .try_mbus_fmt           = ov9740_try_fmt,
-       .enum_mbus_fmt          = ov9740_enum_fmt,
-       .cropcap                = ov9740_cropcap,
-       .g_crop                 = ov9740_g_crop,
 };
 
 static struct v4l2_subdev_ops ov9740_subdev_ops = {
index 7551907..e753b5e 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/version.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <asm/io.h>
@@ -39,7 +38,7 @@
 #include <media/v4l2-device.h>
 
 MODULE_LICENSE("GPL");
-
+MODULE_VERSION("0.0.4");
 
 #define MOTOROLA       1
 #define PHILIPS2       2               /* SAA7191 */
@@ -678,7 +677,6 @@ static int pms_querycap(struct file *file, void  *priv,
        strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver));
        strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card));
        strlcpy(vcap->bus_info, "ISA", sizeof(vcap->bus_info));
-       vcap->version = KERNEL_VERSION(0, 0, 3);
        vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
        return 0;
 }
index 2254194..c1d9bb6 100644 (file)
@@ -168,6 +168,7 @@ module_exit(pvr_exit);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.9.1");
 
 
 /*
index 3876114..e27f8ab 100644 (file)
@@ -91,7 +91,7 @@ static struct v4l2_capability pvr_capability ={
        .driver         = "pvrusb2",
        .card           = "Hauppauge WinTV pvr-usb2",
        .bus_info       = "usb",
-       .version        = KERNEL_VERSION(0, 9, 0),
+       .version        = LINUX_VERSION_CODE,
        .capabilities   = (V4L2_CAP_VIDEO_CAPTURE |
                           V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
                           V4L2_CAP_READWRITE),
@@ -369,11 +369,6 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                break;
        }
 
-       case VIDIOC_S_AUDIO:
-       {
-               ret = -EINVAL;
-               break;
-       }
        case VIDIOC_G_TUNER:
        {
                struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
@@ -850,7 +845,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 #endif
 
        default :
-               ret = -EINVAL;
+               ret = -ENOTTY;
                break;
        }
 
index 8da42e4..d63d0a8 100644 (file)
@@ -1,6 +1,7 @@
 config USB_PWC
        tristate "USB Philips Cameras"
        depends on VIDEO_V4L2
+       select VIDEOBUF2_VMALLOC
        ---help---
          Say Y or M here if you want to use one of these Philips & OEM
          webcams:
index 760b4de..3977add 100644 (file)
@@ -3,6 +3,7 @@
    video modes.
    (C) 1999-2003 Nemosoft Unv.
    (C) 2004-2006 Luc Saillard (luc@saillard.org)
+   (C) 2011 Hans de Goede <hdegoede@redhat.com>
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
 #include <asm/errno.h>
 
 #include "pwc.h"
-#include "pwc-uncompress.h"
 #include "pwc-kiara.h"
 #include "pwc-timon.h"
 #include "pwc-dec1.h"
 #include "pwc-dec23.h"
 
-/* Request types: video */
-#define SET_LUM_CTL                    0x01
-#define GET_LUM_CTL                    0x02
-#define SET_CHROM_CTL                  0x03
-#define GET_CHROM_CTL                  0x04
-#define SET_STATUS_CTL                 0x05
-#define GET_STATUS_CTL                 0x06
-#define SET_EP_STREAM_CTL              0x07
-#define GET_EP_STREAM_CTL              0x08
-#define GET_XX_CTL                     0x09
-#define SET_XX_CTL                     0x0A
-#define GET_XY_CTL                     0x0B
-#define SET_XY_CTL                     0x0C
-#define SET_MPT_CTL                    0x0D
-#define GET_MPT_CTL                    0x0E
-
-/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
-#define AGC_MODE_FORMATTER                     0x2000
-#define PRESET_AGC_FORMATTER                   0x2100
-#define SHUTTER_MODE_FORMATTER                 0x2200
-#define PRESET_SHUTTER_FORMATTER               0x2300
-#define PRESET_CONTOUR_FORMATTER               0x2400
-#define AUTO_CONTOUR_FORMATTER                 0x2500
-#define BACK_LIGHT_COMPENSATION_FORMATTER      0x2600
-#define CONTRAST_FORMATTER                     0x2700
-#define DYNAMIC_NOISE_CONTROL_FORMATTER                0x2800
-#define FLICKERLESS_MODE_FORMATTER             0x2900
-#define AE_CONTROL_SPEED                       0x2A00
-#define BRIGHTNESS_FORMATTER                   0x2B00
-#define GAMMA_FORMATTER                                0x2C00
-
-/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
-#define WB_MODE_FORMATTER                      0x1000
-#define AWB_CONTROL_SPEED_FORMATTER            0x1100
-#define AWB_CONTROL_DELAY_FORMATTER            0x1200
-#define PRESET_MANUAL_RED_GAIN_FORMATTER       0x1300
-#define PRESET_MANUAL_BLUE_GAIN_FORMATTER      0x1400
-#define COLOUR_MODE_FORMATTER                  0x1500
-#define SATURATION_MODE_FORMATTER1             0x1600
-#define SATURATION_MODE_FORMATTER2             0x1700
-
-/* Selectors for the Status controls [GS]ET_STATUS_CTL */
-#define SAVE_USER_DEFAULTS_FORMATTER           0x0200
-#define RESTORE_USER_DEFAULTS_FORMATTER                0x0300
-#define RESTORE_FACTORY_DEFAULTS_FORMATTER     0x0400
-#define READ_AGC_FORMATTER                     0x0500
-#define READ_SHUTTER_FORMATTER                 0x0600
-#define READ_RED_GAIN_FORMATTER                        0x0700
-#define READ_BLUE_GAIN_FORMATTER               0x0800
+/* Selectors for status controls used only in this file */
 #define GET_STATUS_B00                         0x0B00
 #define SENSOR_TYPE_FORMATTER1                 0x0C00
 #define GET_STATUS_3000                                0x3000
 /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
 #define VIDEO_OUTPUT_CONTROL_FORMATTER         0x0100
 
-/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */
-#define PT_RELATIVE_CONTROL_FORMATTER          0x01
-#define PT_RESET_CONTROL_FORMATTER             0x02
-#define PT_STATUS_FORMATTER                    0x03
-
 static const char *size2name[PSZ_MAX] =
 {
        "subQCIF",
@@ -160,7 +107,7 @@ static void pwc_set_image_buffer_size(struct pwc_device *pdev);
 /****************************************************************************/
 
 static int _send_control_msg(struct pwc_device *pdev,
-       u8 request, u16 value, int index, void *buf, int buflen, int timeout)
+       u8 request, u16 value, int index, void *buf, int buflen)
 {
        int rc;
        void *kbuf = NULL;
@@ -177,7 +124,7 @@ static int _send_control_msg(struct pwc_device *pdev,
                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                value,
                index,
-               kbuf, buflen, timeout);
+               kbuf, buflen, USB_CTRL_SET_TIMEOUT);
 
        kfree(kbuf);
        return rc;
@@ -197,9 +144,13 @@ static int recv_control_msg(struct pwc_device *pdev,
                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                value,
                pdev->vcinterface,
-               kbuf, buflen, 500);
+               kbuf, buflen, USB_CTRL_GET_TIMEOUT);
        memcpy(buf, kbuf, buflen);
        kfree(kbuf);
+
+       if (rc < 0)
+               PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
+                         rc, request, value);
        return rc;
 }
 
@@ -210,18 +161,16 @@ static inline int send_video_command(struct pwc_device *pdev,
                SET_EP_STREAM_CTL,
                VIDEO_OUTPUT_CONTROL_FORMATTER,
                index,
-               buf, buflen, 1000);
+               buf, buflen);
 }
 
-static inline int send_control_msg(struct pwc_device *pdev,
+int send_control_msg(struct pwc_device *pdev,
        u8 request, u16 value, void *buf, int buflen)
 {
        return _send_control_msg(pdev,
-               request, value, pdev->vcinterface, buf, buflen, 500);
+               request, value, pdev->vcinterface, buf, buflen);
 }
 
-
-
 static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
 {
        unsigned char buf[3];
@@ -261,8 +210,11 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
                PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
                return ret;
        }
-       if (pEntry->compressed && pdev->pixfmt == V4L2_PIX_FMT_YUV420)
-               pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+       if (pEntry->compressed && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
+               ret = pwc_dec1_init(pdev, pdev->type, pdev->release, buf);
+               if (ret < 0)
+                       return ret;
+       }
 
        pdev->cmd_len = 3;
        memcpy(pdev->cmd_buf, buf, 3);
@@ -321,8 +273,11 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, i
        if (ret < 0)
                return ret;
 
-       if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420)
-               pwc_dec23_init(pdev, pdev->type, buf);
+       if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
+               ret = pwc_dec23_init(pdev, pdev->type, buf);
+               if (ret < 0)
+                       return ret;
+       }
 
        pdev->cmd_len = 13;
        memcpy(pdev->cmd_buf, buf, 13);
@@ -394,8 +349,11 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i
        if (ret < 0)
                return ret;
 
-       if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420)
-               pwc_dec23_init(pdev, pdev->type, buf);
+       if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
+               ret = pwc_dec23_init(pdev, pdev->type, buf);
+               if (ret < 0)
+                       return ret;
+       }
 
        pdev->cmd_len = 12;
        memcpy(pdev->cmd_buf, buf, 12);
@@ -452,6 +410,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
        }
        pdev->view.x = width;
        pdev->view.y = height;
+       pdev->vcompression = compression;
        pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
        pwc_set_image_buffer_size(pdev);
        PWC_DEBUG_SIZE("Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y);
@@ -511,13 +470,9 @@ unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned i
        return ret;
 }
 
-#define BLACK_Y 0
-#define BLACK_U 128
-#define BLACK_V 128
-
 static void pwc_set_image_buffer_size(struct pwc_device *pdev)
 {
-       int i, factor = 0;
+       int factor = 0;
 
        /* for V4L2_PIX_FMT_YUV420 */
        switch (pdev->pixfmt) {
@@ -541,442 +496,108 @@ static void pwc_set_image_buffer_size(struct pwc_device *pdev)
         */
        pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
        pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
-
-       /* Fill buffers with black colors */
-       for (i = 0; i < pwc_mbufs; i++) {
-               unsigned char *p = pdev->image_data + pdev->images[i].offset;
-               memset(p, BLACK_Y, pdev->view.x * pdev->view.y);
-               p += pdev->view.x * pdev->view.y;
-               memset(p, BLACK_U, pdev->view.x * pdev->view.y/4);
-               p += pdev->view.x * pdev->view.y/4;
-               memset(p, BLACK_V, pdev->view.x * pdev->view.y/4);
-       }
 }
 
-
-
-/* BRIGHTNESS */
-
-int pwc_get_brightness(struct pwc_device *pdev)
+int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
 {
-       char buf;
        int ret;
+       u8 buf;
 
-       ret = recv_control_msg(pdev,
-               GET_LUM_CTL, BRIGHTNESS_FORMATTER, &buf, sizeof(buf));
+       ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
        if (ret < 0)
                return ret;
-       return buf;
-}
 
-int pwc_set_brightness(struct pwc_device *pdev, int value)
-{
-       char buf;
-
-       if (value < 0)
-               value = 0;
-       if (value > 0xffff)
-               value = 0xffff;
-       buf = (value >> 9) & 0x7f;
-       return send_control_msg(pdev,
-               SET_LUM_CTL, BRIGHTNESS_FORMATTER, &buf, sizeof(buf));
+       *data = buf;
+       return 0;
 }
 
-/* CONTRAST */
-
-int pwc_get_contrast(struct pwc_device *pdev)
+int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
 {
-       char buf;
        int ret;
 
-       ret = recv_control_msg(pdev,
-               GET_LUM_CTL, CONTRAST_FORMATTER, &buf, sizeof(buf));
+       ret = send_control_msg(pdev, request, value, &data, sizeof(data));
        if (ret < 0)
                return ret;
-       return buf;
-}
 
-int pwc_set_contrast(struct pwc_device *pdev, int value)
-{
-       char buf;
-
-       if (value < 0)
-               value = 0;
-       if (value > 0xffff)
-               value = 0xffff;
-       buf = (value >> 10) & 0x3f;
-       return send_control_msg(pdev,
-               SET_LUM_CTL, CONTRAST_FORMATTER, &buf, sizeof(buf));
+       return 0;
 }
 
-/* GAMMA */
-
-int pwc_get_gamma(struct pwc_device *pdev)
+int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
 {
-       char buf;
        int ret;
+       s8 buf;
 
-       ret = recv_control_msg(pdev,
-               GET_LUM_CTL, GAMMA_FORMATTER, &buf, sizeof(buf));
+       ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
        if (ret < 0)
                return ret;
-       return buf;
-}
-
-int pwc_set_gamma(struct pwc_device *pdev, int value)
-{
-       char buf;
 
-       if (value < 0)
-               value = 0;
-       if (value > 0xffff)
-               value = 0xffff;
-       buf = (value >> 11) & 0x1f;
-       return send_control_msg(pdev,
-               SET_LUM_CTL, GAMMA_FORMATTER, &buf, sizeof(buf));
-}
-
-
-/* SATURATION */
-
-/* return a value between [-100 , 100] */
-int pwc_get_saturation(struct pwc_device *pdev, int *value)
-{
-       char buf;
-       int ret, saturation_register;
-
-       if (pdev->type < 675)
-               return -EINVAL;
-       if (pdev->type < 730)
-               saturation_register = SATURATION_MODE_FORMATTER2;
-       else
-               saturation_register = SATURATION_MODE_FORMATTER1;
-       ret = recv_control_msg(pdev,
-               GET_CHROM_CTL, saturation_register, &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-       *value = (signed)buf;
+       *data = buf;
        return 0;
 }
 
-/* @param value saturation color between [-100 , 100] */
-int pwc_set_saturation(struct pwc_device *pdev, int value)
+int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
 {
-       char buf;
-       int saturation_register;
-
-       if (pdev->type < 675)
-               return -EINVAL;
-       if (value < -100)
-               value = -100;
-       if (value > 100)
-               value = 100;
-       if (pdev->type < 730)
-               saturation_register = SATURATION_MODE_FORMATTER2;
-       else
-               saturation_register = SATURATION_MODE_FORMATTER1;
-       return send_control_msg(pdev,
-               SET_CHROM_CTL, saturation_register, &buf, sizeof(buf));
-}
-
-/* AGC */
-
-int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
-{
-       char buf;
        int ret;
+       u8 buf[2];
 
-       if (mode)
-               buf = 0x0; /* auto */
-       else
-               buf = 0xff; /* fixed */
-
-       ret = send_control_msg(pdev,
-               SET_LUM_CTL, AGC_MODE_FORMATTER, &buf, sizeof(buf));
-
-       if (!mode && ret >= 0) {
-               if (value < 0)
-                       value = 0;
-               if (value > 0xffff)
-                       value = 0xffff;
-               buf = (value >> 10) & 0x3F;
-               ret = send_control_msg(pdev,
-                       SET_LUM_CTL, PRESET_AGC_FORMATTER, &buf, sizeof(buf));
-       }
+       ret = recv_control_msg(pdev, request, value, buf, sizeof(buf));
        if (ret < 0)
                return ret;
+
+       *data = (buf[1] << 8) | buf[0];
        return 0;
 }
 
-int pwc_get_agc(struct pwc_device *pdev, int *value)
+int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
 {
-       unsigned char buf;
        int ret;
+       u8 buf[2];
 
-       ret = recv_control_msg(pdev,
-               GET_LUM_CTL, AGC_MODE_FORMATTER, &buf, sizeof(buf));
+       buf[0] = data & 0xff;
+       buf[1] = data >> 8;
+       ret = send_control_msg(pdev, request, value, buf, sizeof(buf));
        if (ret < 0)
                return ret;
 
-       if (buf != 0) { /* fixed */
-               ret = recv_control_msg(pdev,
-                       GET_LUM_CTL, PRESET_AGC_FORMATTER, &buf, sizeof(buf));
-               if (ret < 0)
-                       return ret;
-               if (buf > 0x3F)
-                       buf = 0x3F;
-               *value = (buf << 10);
-       }
-       else { /* auto */
-               ret = recv_control_msg(pdev,
-                       GET_STATUS_CTL, READ_AGC_FORMATTER, &buf, sizeof(buf));
-               if (ret < 0)
-                       return ret;
-               /* Gah... this value ranges from 0x00 ... 0x9F */
-               if (buf > 0x9F)
-                       buf = 0x9F;
-               *value = -(48 + buf * 409);
-       }
-
        return 0;
 }
 
-int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
-{
-       char buf[2];
-       int speed, ret;
-
-
-       if (mode)
-               buf[0] = 0x0;   /* auto */
-       else
-               buf[0] = 0xff; /* fixed */
-
-       ret = send_control_msg(pdev,
-               SET_LUM_CTL, SHUTTER_MODE_FORMATTER, &buf, 1);
-
-       if (!mode && ret >= 0) {
-               if (value < 0)
-                       value = 0;
-               if (value > 0xffff)
-                       value = 0xffff;
-
-               if (DEVICE_USE_CODEC2(pdev->type)) {
-                       /* speed ranges from 0x0 to 0x290 (656) */
-                       speed = (value / 100);
-                       buf[1] = speed >> 8;
-                       buf[0] = speed & 0xff;
-               } else if (DEVICE_USE_CODEC3(pdev->type)) {
-                       /* speed seems to range from 0x0 to 0xff */
-                       buf[1] = 0;
-                       buf[0] = value >> 8;
-               }
-
-               ret = send_control_msg(pdev,
-                       SET_LUM_CTL, PRESET_SHUTTER_FORMATTER,
-                       &buf, sizeof(buf));
-       }
-       return ret;
-}
-
-/* This function is not exported to v4l1, so output values between 0 -> 256 */
-int pwc_get_shutter_speed(struct pwc_device *pdev, int *value)
+int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
 {
-       unsigned char buf[2];
        int ret;
 
-       ret = recv_control_msg(pdev,
-               GET_STATUS_CTL, READ_SHUTTER_FORMATTER, &buf, sizeof(buf));
+       ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0);
        if (ret < 0)
                return ret;
-       *value = buf[0] + (buf[1] << 8);
-       if (DEVICE_USE_CODEC2(pdev->type)) {
-               /* speed ranges from 0x0 to 0x290 (656) */
-               *value *= 256/656;
-       } else if (DEVICE_USE_CODEC3(pdev->type)) {
-               /* speed seems to range from 0x0 to 0xff */
-       }
+
        return 0;
 }
 
-
 /* POWER */
-
-int pwc_camera_power(struct pwc_device *pdev, int power)
+void pwc_camera_power(struct pwc_device *pdev, int power)
 {
        char buf;
+       int r;
+
+       if (!pdev->power_save)
+               return;
 
        if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
-               return 0;       /* Not supported by Nala or Timon < release 6 */
+               return; /* Not supported by Nala or Timon < release 6 */
 
        if (power)
                buf = 0x00; /* active */
        else
                buf = 0xFF; /* power save */
-       return send_control_msg(pdev,
+       r = send_control_msg(pdev,
                SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER,
                &buf, sizeof(buf));
-}
-
-
-
-/* private calls */
-
-int pwc_restore_user(struct pwc_device *pdev)
-{
-       return send_control_msg(pdev,
-               SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, NULL, 0);
-}
-
-int pwc_save_user(struct pwc_device *pdev)
-{
-       return send_control_msg(pdev,
-               SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, NULL, 0);
-}
-
-int pwc_restore_factory(struct pwc_device *pdev)
-{
-       return send_control_msg(pdev,
-               SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, NULL, 0);
-}
-
- /* ************************************************* */
- /* Patch by Alvarado: (not in the original version   */
-
- /*
-  * the camera recognizes modes from 0 to 4:
-  *
-  * 00: indoor (incandescant lighting)
-  * 01: outdoor (sunlight)
-  * 02: fluorescent lighting
-  * 03: manual
-  * 04: auto
-  */
-int pwc_set_awb(struct pwc_device *pdev, int mode)
-{
-       char buf;
-       int ret;
-
-       if (mode < 0)
-           mode = 0;
-
-       if (mode > 4)
-           mode = 4;
-
-       buf = mode & 0x07; /* just the lowest three bits */
-
-       ret = send_control_msg(pdev,
-               SET_CHROM_CTL, WB_MODE_FORMATTER, &buf, sizeof(buf));
-
-       if (ret < 0)
-               return ret;
-       return 0;
-}
-
-int pwc_get_awb(struct pwc_device *pdev)
-{
-       unsigned char buf;
-       int ret;
-
-       ret = recv_control_msg(pdev,
-               GET_CHROM_CTL, WB_MODE_FORMATTER, &buf, sizeof(buf));
-
-       if (ret < 0)
-               return ret;
-       return buf;
-}
-
-int pwc_set_red_gain(struct pwc_device *pdev, int value)
-{
-       unsigned char buf;
-
-       if (value < 0)
-               value = 0;
-       if (value > 0xffff)
-               value = 0xffff;
-       /* only the msb is considered */
-       buf = value >> 8;
-       return send_control_msg(pdev,
-               SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER,
-               &buf, sizeof(buf));
-}
-
-int pwc_get_red_gain(struct pwc_device *pdev, int *value)
-{
-       unsigned char buf;
-       int ret;
-
-       ret = recv_control_msg(pdev,
-               GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER,
-               &buf, sizeof(buf));
-       if (ret < 0)
-           return ret;
-       *value = buf << 8;
-       return 0;
-}
-
-
-int pwc_set_blue_gain(struct pwc_device *pdev, int value)
-{
-       unsigned char buf;
-
-       if (value < 0)
-               value = 0;
-       if (value > 0xffff)
-               value = 0xffff;
-       /* only the msb is considered */
-       buf = value >> 8;
-       return send_control_msg(pdev,
-               SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER,
-               &buf, sizeof(buf));
-}
-
-int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
-{
-       unsigned char buf;
-       int ret;
-
-       ret = recv_control_msg(pdev,
-               GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER,
-               &buf, sizeof(buf));
-       if (ret < 0)
-           return ret;
-       *value = buf << 8;
-       return 0;
-}
-
 
-/* The following two functions are different, since they only read the
-   internal red/blue gains, which may be different from the manual
-   gains set or read above.
- */
-static int pwc_read_red_gain(struct pwc_device *pdev, int *value)
-{
-       unsigned char buf;
-       int ret;
-
-       ret = recv_control_msg(pdev,
-               GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-       *value = buf << 8;
-       return 0;
+       if (r < 0)
+               PWC_ERROR("Failed to power %s camera (%d)\n",
+                         power ? "on" : "off", r);
 }
 
-static int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
-{
-       unsigned char buf;
-       int ret;
-
-       ret = recv_control_msg(pdev,
-               GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-       *value = buf << 8;
-       return 0;
-}
-
-
 static int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
 {
        unsigned char buf;
@@ -1028,6 +649,7 @@ static int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
 int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
 {
        unsigned char buf[2];
+       int r;
 
        if (pdev->type < 730)
                return 0;
@@ -1045,8 +667,12 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
        buf[0] = on_value;
        buf[1] = off_value;
 
-       return send_control_msg(pdev,
+       r = send_control_msg(pdev,
                SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
+       if (r < 0)
+               PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
+
+       return r;
 }
 
 static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
@@ -1069,164 +695,6 @@ static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
        return 0;
 }
 
-int pwc_set_contour(struct pwc_device *pdev, int contour)
-{
-       unsigned char buf;
-       int ret;
-
-       if (contour < 0)
-               buf = 0xff; /* auto contour on */
-       else
-               buf = 0x0; /* auto contour off */
-       ret = send_control_msg(pdev,
-               SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-
-       if (contour < 0)
-               return 0;
-       if (contour > 0xffff)
-               contour = 0xffff;
-
-       buf = (contour >> 10); /* contour preset is [0..3f] */
-       ret = send_control_msg(pdev,
-               SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-       return 0;
-}
-
-int pwc_get_contour(struct pwc_device *pdev, int *contour)
-{
-       unsigned char buf;
-       int ret;
-
-       ret = recv_control_msg(pdev,
-               GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-
-       if (buf == 0) {
-               /* auto mode off, query current preset value */
-               ret = recv_control_msg(pdev,
-                       GET_LUM_CTL, PRESET_CONTOUR_FORMATTER,
-                       &buf, sizeof(buf));
-               if (ret < 0)
-                       return ret;
-               *contour = buf << 10;
-       }
-       else
-               *contour = -1;
-       return 0;
-}
-
-
-int pwc_set_backlight(struct pwc_device *pdev, int backlight)
-{
-       unsigned char buf;
-
-       if (backlight)
-               buf = 0xff;
-       else
-               buf = 0x0;
-       return send_control_msg(pdev,
-               SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER,
-               &buf, sizeof(buf));
-}
-
-int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
-{
-       int ret;
-       unsigned char buf;
-
-       ret = recv_control_msg(pdev,
-               GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER,
-               &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-       *backlight = !!buf;
-       return 0;
-}
-
-int pwc_set_colour_mode(struct pwc_device *pdev, int colour)
-{
-       unsigned char buf;
-
-       if (colour)
-               buf = 0xff;
-       else
-               buf = 0x0;
-       return send_control_msg(pdev,
-               SET_CHROM_CTL, COLOUR_MODE_FORMATTER, &buf, sizeof(buf));
-}
-
-int pwc_get_colour_mode(struct pwc_device *pdev, int *colour)
-{
-       int ret;
-       unsigned char buf;
-
-       ret = recv_control_msg(pdev,
-               GET_CHROM_CTL, COLOUR_MODE_FORMATTER, &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-       *colour = !!buf;
-       return 0;
-}
-
-
-int pwc_set_flicker(struct pwc_device *pdev, int flicker)
-{
-       unsigned char buf;
-
-       if (flicker)
-               buf = 0xff;
-       else
-               buf = 0x0;
-       return send_control_msg(pdev,
-               SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, &buf, sizeof(buf));
-}
-
-int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
-{
-       int ret;
-       unsigned char buf;
-
-       ret = recv_control_msg(pdev,
-               GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-       *flicker = !!buf;
-       return 0;
-}
-
-int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
-{
-       unsigned char buf;
-
-       if (noise < 0)
-               noise = 0;
-       if (noise > 3)
-               noise = 3;
-       buf = noise;
-       return send_control_msg(pdev,
-               SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER,
-               &buf, sizeof(buf));
-}
-
-int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
-{
-       int ret;
-       unsigned char buf;
-
-       ret = recv_control_msg(pdev,
-               GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER,
-               &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-       *noise = buf;
-       return 0;
-}
-
 static int _pwc_mpt_reset(struct pwc_device *pdev, int flags)
 {
        unsigned char buf;
@@ -1309,7 +777,7 @@ static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *st
        return 0;
 }
 
-
+#ifdef CONFIG_USB_PWC_DEBUG
 int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
 {
        unsigned char buf;
@@ -1332,7 +800,7 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
                *sensor = buf;
        return 0;
 }
-
+#endif
 
  /* End of Add-Ons                                    */
  /* ************************************************* */
@@ -1356,37 +824,41 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
 /* copy local variable to arg */
 #define ARG_OUT(ARG_name) /* nothing */
 
+/*
+ * Our ctrls use native values, but the old custom pwc ioctl interface expects
+ * values from 0 - 65535, define 2 helper functions to scale things. */
+static int pwc_ioctl_g_ctrl(struct v4l2_ctrl *ctrl)
+{
+       return v4l2_ctrl_g_ctrl(ctrl) * 65535 / ctrl->maximum;
+}
+
+static int pwc_ioctl_s_ctrl(struct v4l2_ctrl *ctrl, int val)
+{
+       return v4l2_ctrl_s_ctrl(ctrl, val * ctrl->maximum / 65535);
+}
+
 long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
 {
        long ret = 0;
 
        switch(cmd) {
        case VIDIOCPWCRUSER:
-       {
-               if (pwc_restore_user(pdev))
-                       ret = -EINVAL;
+               ret = pwc_button_ctrl(pdev, RESTORE_USER_DEFAULTS_FORMATTER);
                break;
-       }
 
        case VIDIOCPWCSUSER:
-       {
-               if (pwc_save_user(pdev))
-                       ret = -EINVAL;
+               ret = pwc_button_ctrl(pdev, SAVE_USER_DEFAULTS_FORMATTER);
                break;
-       }
 
        case VIDIOCPWCFACTORY:
-       {
-               if (pwc_restore_factory(pdev))
-                       ret = -EINVAL;
+               ret = pwc_button_ctrl(pdev, RESTORE_FACTORY_DEFAULTS_FORMATTER);
                break;
-       }
 
        case VIDIOCPWCSCQUAL:
        {
                ARG_DEF(int, qual)
 
-               if (pdev->iso_init) {
+               if (vb2_is_streaming(&pdev->vb_queue)) {
                        ret = -EBUSY;
                        break;
                }
@@ -1396,8 +868,6 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
                        ret = -EINVAL;
                else
                        ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
-               if (ret >= 0)
-                       pdev->vcompression = ARGR(qual);
                break;
        }
 
@@ -1432,71 +902,59 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
        case VIDIOCPWCSAGC:
        {
                ARG_DEF(int, agc)
-
                ARG_IN(agc)
-               if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc)))
-                       ret = -EINVAL;
+               ret = v4l2_ctrl_s_ctrl(pdev->autogain, ARGR(agc) < 0);
+               if (ret == 0 && ARGR(agc) >= 0)
+                       ret = pwc_ioctl_s_ctrl(pdev->gain, ARGR(agc));
                break;
        }
 
        case VIDIOCPWCGAGC:
        {
                ARG_DEF(int, agc)
-
-               if (pwc_get_agc(pdev, ARGA(agc)))
-                       ret = -EINVAL;
+               if (v4l2_ctrl_g_ctrl(pdev->autogain))
+                       ARGR(agc) = -1;
+               else
+                       ARGR(agc) = pwc_ioctl_g_ctrl(pdev->gain);
                ARG_OUT(agc)
                break;
        }
 
        case VIDIOCPWCSSHUTTER:
        {
-               ARG_DEF(int, shutter_speed)
-
-               ARG_IN(shutter_speed)
-               ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed));
+               ARG_DEF(int, shutter)
+               ARG_IN(shutter)
+               ret = v4l2_ctrl_s_ctrl(pdev->exposure_auto,
+                                      /* Menu idx 0 = auto, idx 1 = manual */
+                                      ARGR(shutter) >= 0);
+               if (ret == 0 && ARGR(shutter) >= 0)
+                       ret = pwc_ioctl_s_ctrl(pdev->exposure, ARGR(shutter));
                break;
        }
 
        case VIDIOCPWCSAWB:
        {
                ARG_DEF(struct pwc_whitebalance, wb)
-
                ARG_IN(wb)
-               ret = pwc_set_awb(pdev, ARGR(wb).mode);
-               if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) {
-                       pwc_set_red_gain(pdev, ARGR(wb).manual_red);
-                       pwc_set_blue_gain(pdev, ARGR(wb).manual_blue);
-               }
+               ret = v4l2_ctrl_s_ctrl(pdev->auto_white_balance,
+                                      ARGR(wb).mode);
+               if (ret == 0 && ARGR(wb).mode == PWC_WB_MANUAL)
+                       ret = pwc_ioctl_s_ctrl(pdev->red_balance,
+                                              ARGR(wb).manual_red);
+               if (ret == 0 && ARGR(wb).mode == PWC_WB_MANUAL)
+                       ret = pwc_ioctl_s_ctrl(pdev->blue_balance,
+                                              ARGR(wb).manual_blue);
                break;
        }
 
        case VIDIOCPWCGAWB:
        {
                ARG_DEF(struct pwc_whitebalance, wb)
-
-               memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance));
-               ARGR(wb).mode = pwc_get_awb(pdev);
-               if (ARGR(wb).mode < 0)
-                       ret = -EINVAL;
-               else {
-                       if (ARGR(wb).mode == PWC_WB_MANUAL) {
-                               ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red);
-                               if (ret < 0)
-                                       break;
-                               ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue);
-                               if (ret < 0)
-                                       break;
-                       }
-                       if (ARGR(wb).mode == PWC_WB_AUTO) {
-                               ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);
-                               if (ret < 0)
-                                       break;
-                               ret = pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
-                               if (ret < 0)
-                                       break;
-                       }
-               }
+               ARGR(wb).mode = v4l2_ctrl_g_ctrl(pdev->auto_white_balance);
+               ARGR(wb).manual_red = ARGR(wb).read_red =
+                       pwc_ioctl_g_ctrl(pdev->red_balance);
+               ARGR(wb).manual_blue = ARGR(wb).read_blue =
+                       pwc_ioctl_g_ctrl(pdev->blue_balance);
                ARG_OUT(wb)
                break;
        }
@@ -1550,17 +1008,20 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
        case VIDIOCPWCSCONTOUR:
        {
                ARG_DEF(int, contour)
-
                ARG_IN(contour)
-               ret = pwc_set_contour(pdev, ARGR(contour));
+               ret = v4l2_ctrl_s_ctrl(pdev->autocontour, ARGR(contour) < 0);
+               if (ret == 0 && ARGR(contour) >= 0)
+                       ret = pwc_ioctl_s_ctrl(pdev->contour, ARGR(contour));
                break;
        }
 
        case VIDIOCPWCGCONTOUR:
        {
                ARG_DEF(int, contour)
-
-               ret = pwc_get_contour(pdev, ARGA(contour));
+               if (v4l2_ctrl_g_ctrl(pdev->autocontour))
+                       ARGR(contour) = -1;
+               else
+                       ARGR(contour) = pwc_ioctl_g_ctrl(pdev->contour);
                ARG_OUT(contour)
                break;
        }
@@ -1568,17 +1029,15 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
        case VIDIOCPWCSBACKLIGHT:
        {
                ARG_DEF(int, backlight)
-
                ARG_IN(backlight)
-               ret = pwc_set_backlight(pdev, ARGR(backlight));
+               ret = v4l2_ctrl_s_ctrl(pdev->backlight, ARGR(backlight));
                break;
        }
 
        case VIDIOCPWCGBACKLIGHT:
        {
                ARG_DEF(int, backlight)
-
-               ret = pwc_get_backlight(pdev, ARGA(backlight));
+               ARGR(backlight) = v4l2_ctrl_g_ctrl(pdev->backlight);
                ARG_OUT(backlight)
                break;
        }
@@ -1586,17 +1045,15 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
        case VIDIOCPWCSFLICKER:
        {
                ARG_DEF(int, flicker)
-
                ARG_IN(flicker)
-               ret = pwc_set_flicker(pdev, ARGR(flicker));
+               ret = v4l2_ctrl_s_ctrl(pdev->flicker, ARGR(flicker));
                break;
        }
 
        case VIDIOCPWCGFLICKER:
        {
                ARG_DEF(int, flicker)
-
-               ret = pwc_get_flicker(pdev, ARGA(flicker));
+               ARGR(flicker) = v4l2_ctrl_g_ctrl(pdev->flicker);
                ARG_OUT(flicker)
                break;
        }
@@ -1604,17 +1061,15 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
        case VIDIOCPWCSDYNNOISE:
        {
                ARG_DEF(int, dynnoise)
-
                ARG_IN(dynnoise)
-               ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise));
+               ret = v4l2_ctrl_s_ctrl(pdev->noise_reduction, ARGR(dynnoise));
                break;
        }
 
        case VIDIOCPWCGDYNNOISE:
        {
                ARG_DEF(int, dynnoise)
-
-               ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));
+               ARGR(dynnoise) = v4l2_ctrl_g_ctrl(pdev->noise_reduction);
                ARG_OUT(dynnoise);
                break;
        }
index c29593f..be0e02c 100644 (file)
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
-
-
-
 #include "pwc-dec1.h"
 
-
-void pwc_dec1_init(int type, int release, void *buffer, void *table)
+int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer)
 {
+       struct pwc_dec1_private *pdec;
 
-}
-
-void pwc_dec1_exit(void)
-{
+       if (pwc->decompress_data == NULL) {
+               pdec = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL);
+               if (pdec == NULL)
+                       return -ENOMEM;
+               pwc->decompress_data = pdec;
+       }
+       pdec = pwc->decompress_data;
 
-
-
-}
-
-int pwc_dec1_alloc(struct pwc_device *pwc)
-{
-       pwc->decompress_data = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL);
-       if (pwc->decompress_data == NULL)
-               return -ENOMEM;
        return 0;
 }
-
index 8b62ddc..a57d860 100644 (file)
@@ -22,8 +22,6 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
-
-
 #ifndef PWC_DEC1_H
 #define PWC_DEC1_H
 
 struct pwc_dec1_private
 {
        int version;
-
 };
 
-int  pwc_dec1_alloc(struct pwc_device *pwc);
-void pwc_dec1_init(int type, int release, void *buffer, void *private_data);
-void pwc_dec1_exit(void);
+int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer);
 
 #endif
-
index 0c801b8..06a4e87 100644 (file)
@@ -916,27 +916,5 @@ void pwc_dec23_decompress(const struct pwc_device *pwc,
                        pout_planar_v += pwc->view.x;
 
                }
-
        }
-
 }
-
-void pwc_dec23_exit(void)
-{
-       /* Do nothing */
-
-}
-
-/**
- * Allocate a private structure used by lookup table.
- * You must call kfree() to free the memory allocated.
- */
-int pwc_dec23_alloc(struct pwc_device *pwc)
-{
-       pwc->decompress_data = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
-       if (pwc->decompress_data == NULL)
-               return -ENOMEM;
-       return 0;
-}
-
-/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
index 1c55298..a0ac4f3 100644 (file)
@@ -49,19 +49,9 @@ struct pwc_dec23_private
 
 };
 
-
-int pwc_dec23_alloc(struct pwc_device *pwc);
 int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd);
-void pwc_dec23_exit(void);
 void pwc_dec23_decompress(const struct pwc_device *pwc,
                          const void *src,
                          void *dst,
                          int flags);
-
-
-
 #endif
-
-
-/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
-
index b0bde5a..51ca358 100644 (file)
@@ -2,6 +2,7 @@
    USB and Video4Linux interface part.
    (C) 1999-2004 Nemosoft Unv.
    (C) 2004-2006 Luc Saillard (luc@saillard.org)
+   (C) 2011 Hans de Goede <hdegoede@redhat.com>
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -74,7 +75,6 @@
 #include "pwc-timon.h"
 #include "pwc-dec23.h"
 #include "pwc-dec1.h"
-#include "pwc-uncompress.h"
 
 /* Function prototypes and driver templates */
 
@@ -116,6 +116,7 @@ MODULE_DEVICE_TABLE(usb, pwc_device_table);
 
 static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id);
 static void usb_pwc_disconnect(struct usb_interface *intf);
+static void pwc_isoc_cleanup(struct pwc_device *pdev);
 
 static struct usb_driver pwc_driver = {
        .name =                 "Philips webcam",       /* name */
@@ -127,14 +128,11 @@ static struct usb_driver pwc_driver = {
 #define MAX_DEV_HINTS  20
 #define MAX_ISOC_ERRORS        20
 
-static int default_size = PSZ_QCIF;
 static int default_fps = 10;
-static int default_fbufs = 3;   /* Default number of frame buffers */
-       int pwc_mbufs = 2;      /* Default number of mmap() buffers */
 #ifdef CONFIG_USB_PWC_DEBUG
        int pwc_trace = PWC_DEBUG_LEVEL;
 #endif
-static int power_save;
+static int power_save = -1;
 static int led_on = 100, led_off; /* defaults to LED that is on while in use */
 static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
 static struct {
@@ -173,389 +171,20 @@ static struct video_device pwc_template = {
 /***************************************************************************/
 /* Private functions */
 
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
- */
-
-
-
-static void *pwc_rvmalloc(unsigned long size)
-{
-       void * mem;
-       unsigned long adr;
-
-       mem=vmalloc_32(size);
-       if (!mem)
-               return NULL;
-
-       memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-       adr=(unsigned long) mem;
-       while (size > 0)
-        {
-          SetPageReserved(vmalloc_to_page((void *)adr));
-          adr  += PAGE_SIZE;
-          size -= PAGE_SIZE;
-        }
-       return mem;
-}
-
-static void pwc_rvfree(void * mem, unsigned long size)
-{
-       unsigned long adr;
-
-       if (!mem)
-               return;
-
-       adr=(unsigned long) mem;
-       while ((long) size > 0)
-        {
-          ClearPageReserved(vmalloc_to_page((void *)adr));
-          adr  += PAGE_SIZE;
-          size -= PAGE_SIZE;
-        }
-       vfree(mem);
-}
-
-
-
-
-static int pwc_allocate_buffers(struct pwc_device *pdev)
-{
-       int i, err;
-       void *kbuf;
-
-       PWC_DEBUG_MEMORY(">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
-
-       if (pdev == NULL)
-               return -ENXIO;
-
-       /* Allocate Isochronuous pipe buffers */
-       for (i = 0; i < MAX_ISO_BUFS; i++) {
-               if (pdev->sbuf[i].data == NULL) {
-                       kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
-                       if (kbuf == NULL) {
-                               PWC_ERROR("Failed to allocate iso buffer %d.\n", i);
-                               return -ENOMEM;
-                       }
-                       PWC_DEBUG_MEMORY("Allocated iso buffer at %p.\n", kbuf);
-                       pdev->sbuf[i].data = kbuf;
-               }
-       }
-
-       /* Allocate frame buffer structure */
-       if (pdev->fbuf == NULL) {
-               kbuf = kzalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
-               if (kbuf == NULL) {
-                       PWC_ERROR("Failed to allocate frame buffer structure.\n");
-                       return -ENOMEM;
-               }
-               PWC_DEBUG_MEMORY("Allocated frame buffer structure at %p.\n", kbuf);
-               pdev->fbuf = kbuf;
-       }
-
-       /* create frame buffers, and make circular ring */
-       for (i = 0; i < default_fbufs; i++) {
-               if (pdev->fbuf[i].data == NULL) {
-                       kbuf = vzalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
-                       if (kbuf == NULL) {
-                               PWC_ERROR("Failed to allocate frame buffer %d.\n", i);
-                               return -ENOMEM;
-                       }
-                       PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf);
-                       pdev->fbuf[i].data = kbuf;
-               }
-       }
-
-       /* Allocate decompressor table space */
-       if (DEVICE_USE_CODEC1(pdev->type))
-               err = pwc_dec1_alloc(pdev);
-       else
-               err = pwc_dec23_alloc(pdev);
-
-       if (err) {
-               PWC_ERROR("Failed to allocate decompress table.\n");
-               return err;
-       }
-
-       /* Allocate image buffer; double buffer for mmap() */
-       kbuf = pwc_rvmalloc(pwc_mbufs * pdev->len_per_image);
-       if (kbuf == NULL) {
-               PWC_ERROR("Failed to allocate image buffer(s). needed (%d)\n",
-                               pwc_mbufs * pdev->len_per_image);
-               return -ENOMEM;
-       }
-       PWC_DEBUG_MEMORY("Allocated image buffer at %p.\n", kbuf);
-       pdev->image_data = kbuf;
-       for (i = 0; i < pwc_mbufs; i++) {
-               pdev->images[i].offset = i * pdev->len_per_image;
-               pdev->images[i].vma_use_count = 0;
-       }
-       for (; i < MAX_IMAGES; i++) {
-               pdev->images[i].offset = 0;
-       }
-
-       kbuf = NULL;
-
-       PWC_DEBUG_MEMORY("<< pwc_allocate_buffers()\n");
-       return 0;
-}
-
-static void pwc_free_buffers(struct pwc_device *pdev)
-{
-       int i;
-
-       PWC_DEBUG_MEMORY("Entering free_buffers(%p).\n", pdev);
-
-       if (pdev == NULL)
-               return;
-       /* Release Iso-pipe buffers */
-       for (i = 0; i < MAX_ISO_BUFS; i++)
-               if (pdev->sbuf[i].data != NULL) {
-                       PWC_DEBUG_MEMORY("Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
-                       kfree(pdev->sbuf[i].data);
-                       pdev->sbuf[i].data = NULL;
-               }
-
-       /* The same for frame buffers */
-       if (pdev->fbuf != NULL) {
-               for (i = 0; i < default_fbufs; i++) {
-                       if (pdev->fbuf[i].data != NULL) {
-                               PWC_DEBUG_MEMORY("Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
-                               vfree(pdev->fbuf[i].data);
-                               pdev->fbuf[i].data = NULL;
-                       }
-               }
-               kfree(pdev->fbuf);
-               pdev->fbuf = NULL;
-       }
-
-       /* Intermediate decompression buffer & tables */
-       if (pdev->decompress_data != NULL) {
-               PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n", pdev->decompress_data);
-               kfree(pdev->decompress_data);
-               pdev->decompress_data = NULL;
-       }
-
-       /* Release image buffers */
-       if (pdev->image_data != NULL) {
-               PWC_DEBUG_MEMORY("Freeing image buffer at %p.\n", pdev->image_data);
-               pwc_rvfree(pdev->image_data, pwc_mbufs * pdev->len_per_image);
-       }
-       pdev->image_data = NULL;
-
-       PWC_DEBUG_MEMORY("Leaving free_buffers().\n");
-}
-
-/* The frame & image buffer mess.
-
-   Yes, this is a mess. Well, it used to be simple, but alas...  In this
-   module, 3 buffers schemes are used to get the data from the USB bus to
-   the user program. The first scheme involves the ISO buffers (called thus
-   since they transport ISO data from the USB controller), and not really
-   interesting. Suffices to say the data from this buffer is quickly
-   gathered in an interrupt handler (pwc_isoc_handler) and placed into the
-   frame buffer.
-
-   The frame buffer is the second scheme, and is the central element here.
-   It collects the data from a single frame from the camera (hence, the
-   name). Frames are delimited by the USB camera with a short USB packet,
-   so that's easy to detect. The frame buffers form a list that is filled
-   by the camera+USB controller and drained by the user process through
-   either read() or mmap().
-
-   The image buffer is the third scheme, in which frames are decompressed
-   and converted into planar format. For mmap() there is more than
-   one image buffer available.
-
-   The frame buffers provide the image buffering. In case the user process
-   is a bit slow, this introduces lag and some undesired side-effects.
-   The problem arises when the frame buffer is full. I used to drop the last
-   frame, which makes the data in the queue stale very quickly. But dropping
-   the frame at the head of the queue proved to be a litte bit more difficult.
-   I tried a circular linked scheme, but this introduced more problems than
-   it solved.
-
-   Because filling and draining are completely asynchronous processes, this
-   requires some fiddling with pointers and mutexes.
-
-   Eventually, I came up with a system with 2 lists: an 'empty' frame list
-   and a 'full' frame list:
-     * Initially, all frame buffers but one are on the 'empty' list; the one
-       remaining buffer is our initial fill frame.
-     * If a frame is needed for filling, we try to take it from the 'empty'
-       list, unless that list is empty, in which case we take the buffer at
-       the head of the 'full' list.
-     * When our fill buffer has been filled, it is appended to the 'full'
-       list.
-     * If a frame is needed by read() or mmap(), it is taken from the head of
-       the 'full' list, handled, and then appended to the 'empty' list. If no
-       buffer is present on the 'full' list, we wait.
-   The advantage is that the buffer that is currently being decompressed/
-   converted, is on neither list, and thus not in our way (any other scheme
-   I tried had the problem of old data lingering in the queue).
-
-   Whatever strategy you choose, it always remains a tradeoff: with more
-   frame buffers the chances of a missed frame are reduced. On the other
-   hand, on slower machines it introduces lag because the queue will
-   always be full.
- */
-
-/**
-  \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
- */
-static int pwc_next_fill_frame(struct pwc_device *pdev)
-{
-       int ret;
-       unsigned long flags;
-
-       ret = 0;
-       spin_lock_irqsave(&pdev->ptrlock, flags);
-       if (pdev->fill_frame != NULL) {
-               /* append to 'full' list */
-               if (pdev->full_frames == NULL) {
-                       pdev->full_frames = pdev->fill_frame;
-                       pdev->full_frames_tail = pdev->full_frames;
-               }
-               else {
-                       pdev->full_frames_tail->next = pdev->fill_frame;
-                       pdev->full_frames_tail = pdev->fill_frame;
-               }
-       }
-       if (pdev->empty_frames != NULL) {
-               /* We have empty frames available. That's easy */
-               pdev->fill_frame = pdev->empty_frames;
-               pdev->empty_frames = pdev->empty_frames->next;
-       }
-       else {
-               /* Hmm. Take it from the full list */
-               /* sanity check */
-               if (pdev->full_frames == NULL) {
-                       PWC_ERROR("Neither empty or full frames available!\n");
-                       spin_unlock_irqrestore(&pdev->ptrlock, flags);
-                       return -EINVAL;
-               }
-               pdev->fill_frame = pdev->full_frames;
-               pdev->full_frames = pdev->full_frames->next;
-               ret = 1;
-       }
-       pdev->fill_frame->next = NULL;
-       spin_unlock_irqrestore(&pdev->ptrlock, flags);
-       return ret;
-}
-
-
-/**
-  \brief Reset all buffers, pointers and lists, except for the image_used[] buffer.
-
-  If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble.
- */
-static void pwc_reset_buffers(struct pwc_device *pdev)
-{
-       int i;
-       unsigned long flags;
-
-       PWC_DEBUG_MEMORY(">> %s __enter__\n", __func__);
-
-       spin_lock_irqsave(&pdev->ptrlock, flags);
-       pdev->full_frames = NULL;
-       pdev->full_frames_tail = NULL;
-       for (i = 0; i < default_fbufs; i++) {
-               pdev->fbuf[i].filled = 0;
-               if (i > 0)
-                       pdev->fbuf[i].next = &pdev->fbuf[i - 1];
-               else
-                       pdev->fbuf->next = NULL;
-       }
-       pdev->empty_frames = &pdev->fbuf[default_fbufs - 1];
-       pdev->empty_frames_tail = pdev->fbuf;
-       pdev->read_frame = NULL;
-       pdev->fill_frame = pdev->empty_frames;
-       pdev->empty_frames = pdev->empty_frames->next;
-
-       pdev->image_read_pos = 0;
-       pdev->fill_image = 0;
-       spin_unlock_irqrestore(&pdev->ptrlock, flags);
-
-       PWC_DEBUG_MEMORY("<< %s __leaving__\n", __func__);
-}
-
-
-/**
-  \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
- */
-int pwc_handle_frame(struct pwc_device *pdev)
+struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev)
 {
-       int ret = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&pdev->ptrlock, flags);
-       /* First grab our read_frame; this is removed from all lists, so
-          we can release the lock after this without problems */
-       if (pdev->read_frame != NULL) {
-               /* This can't theoretically happen */
-               PWC_ERROR("Huh? Read frame still in use?\n");
-               spin_unlock_irqrestore(&pdev->ptrlock, flags);
-               return ret;
-       }
-
-
-       if (pdev->full_frames == NULL) {
-               PWC_ERROR("Woops. No frames ready.\n");
-       }
-       else {
-               pdev->read_frame = pdev->full_frames;
-               pdev->full_frames = pdev->full_frames->next;
-               pdev->read_frame->next = NULL;
-       }
-
-       if (pdev->read_frame != NULL) {
-               /* Decompression is a lengthy process, so it's outside of the lock.
-                  This gives the isoc_handler the opportunity to fill more frames
-                  in the mean time.
-               */
-               spin_unlock_irqrestore(&pdev->ptrlock, flags);
-               ret = pwc_decompress(pdev);
-               spin_lock_irqsave(&pdev->ptrlock, flags);
-
-               /* We're done with read_buffer, tack it to the end of the empty buffer list */
-               if (pdev->empty_frames == NULL) {
-                       pdev->empty_frames = pdev->read_frame;
-                       pdev->empty_frames_tail = pdev->empty_frames;
-               }
-               else {
-                       pdev->empty_frames_tail->next = pdev->read_frame;
-                       pdev->empty_frames_tail = pdev->read_frame;
-               }
-               pdev->read_frame = NULL;
-       }
-       spin_unlock_irqrestore(&pdev->ptrlock, flags);
-       return ret;
-}
-
-/**
-  \brief Advance pointers of image buffer (after each user request)
-*/
-void pwc_next_image(struct pwc_device *pdev)
-{
-       pdev->image_used[pdev->fill_image] = 0;
-       pdev->fill_image = (pdev->fill_image + 1) % pwc_mbufs;
-}
-
-/**
- * Print debug information when a frame is discarded because all of our buffer
- * is full
- */
-static void pwc_frame_dumped(struct pwc_device *pdev)
-{
-       pdev->vframes_dumped++;
-       if (pdev->vframe_count < FRAME_LOWMARK)
-               return;
-
-       if (pdev->vframes_dumped < 20)
-               PWC_DEBUG_FLOW("Dumping frame %d\n", pdev->vframe_count);
-       else if (pdev->vframes_dumped == 20)
-               PWC_DEBUG_FLOW("Dumping frame %d (last message)\n",
-                               pdev->vframe_count);
+       unsigned long flags = 0;
+       struct pwc_frame_buf *buf = NULL;
+
+       spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
+       if (list_empty(&pdev->queued_bufs))
+               goto leave;
+
+       buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf, list);
+       list_del(&buf->list);
+leave:
+       spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
+       return buf;
 }
 
 static void pwc_snapshot_button(struct pwc_device *pdev, int down)
@@ -575,9 +204,9 @@ static void pwc_snapshot_button(struct pwc_device *pdev, int down)
 #endif
 }
 
-static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf)
+static void pwc_frame_complete(struct pwc_device *pdev)
 {
-       int awake = 0;
+       struct pwc_frame_buf *fbuf = pdev->fill_buf;
 
        /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
           frames on the USB wire after an exposure change. This conditition is
@@ -589,7 +218,6 @@ static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_
                if (ptr[1] == 1 && ptr[0] & 0x10) {
                        PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
                        pdev->drop_frames += 2;
-                       pdev->vframes_error++;
                }
                if ((ptr[0] ^ pdev->vmirror) & 0x01) {
                        pwc_snapshot_button(pdev, ptr[0] & 0x01);
@@ -612,8 +240,7 @@ static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_
                   */
                if (fbuf->filled == 4)
                        pdev->drop_frames++;
-       }
-       else if (pdev->type == 740 || pdev->type == 720) {
+       } else if (pdev->type == 740 || pdev->type == 720) {
                unsigned char *ptr = (unsigned char *)fbuf->data;
                if ((ptr[0] ^ pdev->vmirror) & 0x01) {
                        pwc_snapshot_button(pdev, ptr[0] & 0x01);
@@ -621,33 +248,23 @@ static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_
                pdev->vmirror = ptr[0] & 0x03;
        }
 
-       /* In case we were instructed to drop the frame, do so silently.
-          The buffer pointers are not updated either (but the counters are reset below).
-          */
-       if (pdev->drop_frames > 0)
+       /* In case we were instructed to drop the frame, do so silently. */
+       if (pdev->drop_frames > 0) {
                pdev->drop_frames--;
-       else {
+       else {
                /* Check for underflow first */
                if (fbuf->filled < pdev->frame_total_size) {
                        PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
                                       " discarded.\n", fbuf->filled);
-                       pdev->vframes_error++;
-               }
-               else {
-                       /* Send only once per EOF */
-                       awake = 1; /* delay wake_ups */
-
-                       /* Find our next frame to fill. This will always succeed, since we
-                        * nick a frame from either empty or full list, but if we had to
-                        * take it from the full list, it means a frame got dropped.
-                        */
-                       if (pwc_next_fill_frame(pdev))
-                               pwc_frame_dumped(pdev);
-
+               } else {
+                       fbuf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
+                       fbuf->vb.v4l2_buf.sequence = pdev->vframe_count;
+                       vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+                       pdev->fill_buf = NULL;
+                       pdev->vsync = 0;
                }
        } /* !drop_frames */
        pdev->vframe_count++;
-       return awake;
 }
 
 /* This gets called for the Isochronous pipe (video). This is done in
@@ -655,24 +272,20 @@ static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_
  */
 static void pwc_isoc_handler(struct urb *urb)
 {
-       struct pwc_device *pdev;
+       struct pwc_device *pdev = (struct pwc_device *)urb->context;
        int i, fst, flen;
-       int awake;
-       struct pwc_frame_buf *fbuf;
-       unsigned char *fillptr = NULL, *iso_buf = NULL;
+       unsigned char *iso_buf = NULL;
 
-       awake = 0;
-       pdev = (struct pwc_device *)urb->context;
-       if (pdev == NULL) {
-               PWC_ERROR("isoc_handler() called with NULL device?!\n");
-               return;
-       }
-
-       if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
+       if (urb->status == -ENOENT || urb->status == -ECONNRESET ||
+           urb->status == -ESHUTDOWN) {
                PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
                return;
        }
-       if (urb->status != -EINPROGRESS && urb->status != 0) {
+
+       if (pdev->fill_buf == NULL)
+               pdev->fill_buf = pwc_get_next_fill_buf(pdev);
+
+       if (urb->status != 0) {
                const char *errmsg;
 
                errmsg = "Unknown";
@@ -684,29 +297,21 @@ static void pwc_isoc_handler(struct urb *urb)
                        case -EILSEQ:           errmsg = "CRC/Timeout (could be anything)"; break;
                        case -ETIME:            errmsg = "Device does not respond"; break;
                }
-               PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
-               /* Give up after a number of contiguous errors on the USB bus.
-                  Appearantly something is wrong so we simulate an unplug event.
-                */
+               PWC_ERROR("pwc_isoc_handler() called with status %d [%s].\n",
+                         urb->status, errmsg);
+               /* Give up after a number of contiguous errors */
                if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
                {
-                       PWC_INFO("Too many ISOC errors, bailing out.\n");
-                       pdev->error_status = EIO;
-                       awake = 1;
-                       wake_up_interruptible(&pdev->frameq);
+                       PWC_ERROR("Too many ISOC errors, bailing out.\n");
+                       if (pdev->fill_buf) {
+                               vb2_buffer_done(&pdev->fill_buf->vb,
+                                               VB2_BUF_STATE_ERROR);
+                               pdev->fill_buf = NULL;
+                       }
                }
-               goto handler_end; // ugly, but practical
-       }
-
-       fbuf = pdev->fill_frame;
-       if (fbuf == NULL) {
-               PWC_ERROR("pwc_isoc_handler without valid fill frame.\n");
-               awake = 1;
+               pdev->vsync = 0; /* Drop the current frame */
                goto handler_end;
        }
-       else {
-               fillptr = fbuf->data + fbuf->filled;
-       }
 
        /* Reset ISOC error counter. We did get here, after all. */
        pdev->visoc_errors = 0;
@@ -720,89 +325,73 @@ static void pwc_isoc_handler(struct urb *urb)
                fst  = urb->iso_frame_desc[i].status;
                flen = urb->iso_frame_desc[i].actual_length;
                iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-               if (fst == 0) {
-                       if (flen > 0) { /* if valid data... */
-                               if (pdev->vsync > 0) { /* ...and we are not sync-hunting... */
-                                       pdev->vsync = 2;
-
-                                       /* ...copy data to frame buffer, if possible */
-                                       if (flen + fbuf->filled > pdev->frame_total_size) {
-                                               PWC_DEBUG_FLOW("Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size);
-                                               pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
-                                               pdev->vframes_error++;
-                                       }
-                                       else {
-                                               memmove(fillptr, iso_buf, flen);
-                                               fillptr += flen;
-                                       }
-                               }
+               if (fst != 0) {
+                       PWC_ERROR("Iso frame %d has error %d\n", i, fst);
+                       continue;
+               }
+               if (flen > 0 && pdev->vsync) {
+                       struct pwc_frame_buf *fbuf = pdev->fill_buf;
+
+                       if (pdev->vsync == 1) {
+                               do_gettimeofday(&fbuf->vb.v4l2_buf.timestamp);
+                               pdev->vsync = 2;
+                       }
+
+                       if (flen + fbuf->filled > pdev->frame_total_size) {
+                               PWC_ERROR("Frame overflow (%d > %d)\n",
+                                         flen + fbuf->filled,
+                                         pdev->frame_total_size);
+                               pdev->vsync = 0; /* Let's wait for an EOF */
+                       } else {
+                               memcpy(fbuf->data + fbuf->filled, iso_buf,
+                                      flen);
                                fbuf->filled += flen;
-                       } /* ..flen > 0 */
-
-                       if (flen < pdev->vlast_packet_size) {
-                               /* Shorter packet... We probably have the end of an image-frame;
-                                  wake up read() process and let select()/poll() do something.
-                                  Decompression is done in user time over there.
-                                  */
-                               if (pdev->vsync == 2) {
-                                       if (pwc_rcv_short_packet(pdev, fbuf)) {
-                                               awake = 1;
-                                               fbuf = pdev->fill_frame;
-                                       }
-                               }
-                               fbuf->filled = 0;
-                               fillptr = fbuf->data;
+                       }
+               }
+               if (flen < pdev->vlast_packet_size) {
+                       /* Shorter packet... end of frame */
+                       if (pdev->vsync == 2)
+                               pwc_frame_complete(pdev);
+                       if (pdev->fill_buf == NULL)
+                               pdev->fill_buf = pwc_get_next_fill_buf(pdev);
+                       if (pdev->fill_buf) {
+                               pdev->fill_buf->filled = 0;
                                pdev->vsync = 1;
                        }
-
-                       pdev->vlast_packet_size = flen;
-               } /* ..status == 0 */
-               else {
-                       /* This is normally not interesting to the user, unless
-                        * you are really debugging something, default = 0 */
-                       static int iso_error;
-                       iso_error++;
-                       if (iso_error < 20)
-                               PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst);
                }
+               pdev->vlast_packet_size = flen;
        }
 
 handler_end:
-       if (awake)
-               wake_up_interruptible(&pdev->frameq);
-
-       urb->dev = pdev->udev;
        i = usb_submit_urb(urb, GFP_ATOMIC);
        if (i != 0)
                PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
 }
 
-
-int pwc_isoc_init(struct pwc_device *pdev)
+static int pwc_isoc_init(struct pwc_device *pdev)
 {
        struct usb_device *udev;
        struct urb *urb;
        int i, j, ret;
-
        struct usb_interface *intf;
        struct usb_host_interface *idesc = NULL;
 
-       if (pdev == NULL)
-               return -EFAULT;
        if (pdev->iso_init)
                return 0;
+
        pdev->vsync = 0;
+       pdev->vlast_packet_size = 0;
+       pdev->fill_buf = NULL;
+       pdev->vframe_count = 0;
+       pdev->visoc_errors = 0;
        udev = pdev->udev;
 
        /* Get the current alternate interface, adjust packet size */
-       if (!udev->actconfig)
-               return -EFAULT;
        intf = usb_ifnum_to_if(udev, 0);
        if (intf)
                idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
-
        if (!idesc)
-               return -EFAULT;
+               return -EIO;
 
        /* Search video endpoint */
        pdev->vmax_packet_size = -1;
@@ -825,34 +414,32 @@ int pwc_isoc_init(struct pwc_device *pdev)
        if (ret < 0)
                return ret;
 
+       /* Allocate and init Isochronuous urbs */
        for (i = 0; i < MAX_ISO_BUFS; i++) {
                urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
                if (urb == NULL) {
                        PWC_ERROR("Failed to allocate urb %d\n", i);
-                       ret = -ENOMEM;
-                       break;
+                       pdev->iso_init = 1;
+                       pwc_isoc_cleanup(pdev);
+                       return -ENOMEM;
                }
-               pdev->sbuf[i].urb = urb;
+               pdev->urbs[i] = urb;
                PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
-       }
-       if (ret) {
-               /* De-allocate in reverse order */
-               while (i--) {
-                       usb_free_urb(pdev->sbuf[i].urb);
-                       pdev->sbuf[i].urb = NULL;
-               }
-               return ret;
-       }
-
-       /* init URB structure */
-       for (i = 0; i < MAX_ISO_BUFS; i++) {
-               urb = pdev->sbuf[i].urb;
 
                urb->interval = 1; // devik
                urb->dev = udev;
                urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
-               urb->transfer_flags = URB_ISO_ASAP;
-               urb->transfer_buffer = pdev->sbuf[i].data;
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+               urb->transfer_buffer = usb_alloc_coherent(udev,
+                                                         ISO_BUFFER_SIZE,
+                                                         GFP_KERNEL,
+                                                         &urb->transfer_dma);
+               if (urb->transfer_buffer == NULL) {
+                       PWC_ERROR("Failed to allocate urb buffer %d\n", i);
+                       pdev->iso_init = 1;
+                       pwc_isoc_cleanup(pdev);
+                       return -ENOMEM;
+               }
                urb->transfer_buffer_length = ISO_BUFFER_SIZE;
                urb->complete = pwc_isoc_handler;
                urb->context = pdev;
@@ -866,14 +453,14 @@ int pwc_isoc_init(struct pwc_device *pdev)
 
        /* link */
        for (i = 0; i < MAX_ISO_BUFS; i++) {
-               ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
+               ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL);
                if (ret) {
                        PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
                        pdev->iso_init = 1;
                        pwc_isoc_cleanup(pdev);
                        return ret;
                }
-               PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb);
+               PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->urbs[i]);
        }
 
        /* All is done... */
@@ -888,12 +475,9 @@ static void pwc_iso_stop(struct pwc_device *pdev)
 
        /* Unlinking ISOC buffers one by one */
        for (i = 0; i < MAX_ISO_BUFS; i++) {
-               struct urb *urb;
-
-               urb = pdev->sbuf[i].urb;
-               if (urb) {
-                       PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb);
-                       usb_kill_urb(urb);
+               if (pdev->urbs[i]) {
+                       PWC_DEBUG_MEMORY("Unlinking URB %p\n", pdev->urbs[i]);
+                       usb_kill_urb(pdev->urbs[i]);
                }
        }
 }
@@ -904,40 +488,51 @@ static void pwc_iso_free(struct pwc_device *pdev)
 
        /* Freeing ISOC buffers one by one */
        for (i = 0; i < MAX_ISO_BUFS; i++) {
-               struct urb *urb;
-
-               urb = pdev->sbuf[i].urb;
-               if (urb) {
+               if (pdev->urbs[i]) {
                        PWC_DEBUG_MEMORY("Freeing URB\n");
-                       usb_free_urb(urb);
-                       pdev->sbuf[i].urb = NULL;
+                       if (pdev->urbs[i]->transfer_buffer) {
+                               usb_free_coherent(pdev->udev,
+                                       pdev->urbs[i]->transfer_buffer_length,
+                                       pdev->urbs[i]->transfer_buffer,
+                                       pdev->urbs[i]->transfer_dma);
+                       }
+                       usb_free_urb(pdev->urbs[i]);
+                       pdev->urbs[i] = NULL;
                }
        }
 }
 
-void pwc_isoc_cleanup(struct pwc_device *pdev)
+static void pwc_isoc_cleanup(struct pwc_device *pdev)
 {
        PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
-       if (pdev == NULL)
-               return;
+
        if (pdev->iso_init == 0)
                return;
 
        pwc_iso_stop(pdev);
        pwc_iso_free(pdev);
-
-       /* Stop camera, but only if we are sure the camera is still there (unplug
-          is signalled by EPIPE)
-        */
-       if (pdev->error_status != EPIPE) {
-               PWC_DEBUG_OPEN("Setting alternate interface 0.\n");
-               usb_set_interface(pdev->udev, 0, 0);
-       }
+       usb_set_interface(pdev->udev, 0, 0);
 
        pdev->iso_init = 0;
        PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
 }
 
+/*
+ * Release all queued buffers, no need to take queued_bufs_lock, since all
+ * iso urbs have been killed when we're called so pwc_isoc_handler won't run.
+ */
+static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
+{
+       while (!list_empty(&pdev->queued_bufs)) {
+               struct pwc_frame_buf *buf;
+
+               buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf,
+                                list);
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+       }
+}
+
 /*********
  * sysfs
  *********/
@@ -1051,98 +646,15 @@ static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
 
 static int pwc_video_open(struct file *file)
 {
-       int i, ret;
        struct video_device *vdev = video_devdata(file);
        struct pwc_device *pdev;
 
        PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
 
        pdev = video_get_drvdata(vdev);
-       BUG_ON(!pdev);
-       if (pdev->vopen) {
-               PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n");
-               return -EBUSY;
-       }
-
-       pwc_construct(pdev); /* set min/max sizes correct */
-       if (!pdev->usb_init) {
-               PWC_DEBUG_OPEN("Doing first time initialization.\n");
-               pdev->usb_init = 1;
-
-               /* Query sensor type */
-               ret = pwc_get_cmos_sensor(pdev, &i);
-               if (ret >= 0)
-               {
-                       PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
-                                       pdev->vdev.name,
-                                       pwc_sensor_type_to_string(i), i);
-               }
-       }
-
-       /* Turn on camera */
-       if (power_save) {
-               i = pwc_camera_power(pdev, 1);
-               if (i < 0)
-                       PWC_DEBUG_OPEN("Failed to restore power to the camera! (%d)\n", i);
-       }
-       /* Set LED on/off time */
-       if (pwc_set_leds(pdev, led_on, led_off) < 0)
-               PWC_DEBUG_OPEN("Failed to set LED on/off time.\n");
-
-
-       /* So far, so good. Allocate memory. */
-       i = pwc_allocate_buffers(pdev);
-       if (i < 0) {
-               PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n");
-               pwc_free_buffers(pdev);
-               return i;
-       }
-
-       /* Reset buffers & parameters */
-       pwc_reset_buffers(pdev);
-       for (i = 0; i < pwc_mbufs; i++)
-               pdev->image_used[i] = 0;
-       pdev->vframe_count = 0;
-       pdev->vframes_dumped = 0;
-       pdev->vframes_error = 0;
-       pdev->visoc_errors = 0;
-       pdev->error_status = 0;
-       pwc_construct(pdev); /* set min/max sizes correct */
-
-       /* Set some defaults */
-       pdev->vsnapshot = 0;
-
-       /* Set video size, first try the last used video size
-          (or the default one); if that fails try QCIF/10 or QSIF/10;
-          it that fails too, give up.
-        */
-       i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0);
-       if (i)  {
-               unsigned int default_resolution;
-               PWC_DEBUG_OPEN("First attempt at set_video_mode failed.\n");
-               if (pdev->type>= 730)
-                       default_resolution = PSZ_QSIF;
-               else
-                       default_resolution = PSZ_QCIF;
-
-               i = pwc_set_video_mode(pdev,
-                                      pwc_image_sizes[default_resolution].x,
-                                      pwc_image_sizes[default_resolution].y,
-                                      10,
-                                      pdev->vcompression,
-                                      0);
-       }
-       if (i) {
-               PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n");
-               pwc_free_buffers(pdev);
-               return i;
-       }
-
-       /* Initialize the webcam to sane value */
-       pwc_set_brightness(pdev, 0x7fff);
-       pwc_set_agc(pdev, 1, 0);
+       if (!pdev->udev)
+               return -ENODEV;
 
-       pdev->vopen++;
        file->private_data = vdev;
        PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
        return 0;
@@ -1158,239 +670,211 @@ static void pwc_video_release(struct video_device *vfd)
                if (device_hint[hint].pdev == pdev)
                        device_hint[hint].pdev = NULL;
 
+       /* Free intermediate decompression buffer & tables */
+       if (pdev->decompress_data != NULL) {
+               PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n",
+                                pdev->decompress_data);
+               kfree(pdev->decompress_data);
+               pdev->decompress_data = NULL;
+       }
+
+       v4l2_ctrl_handler_free(&pdev->ctrl_handler);
+
        kfree(pdev);
 }
 
-/* Note that all cleanup is done in the reverse order as in _open */
 static int pwc_video_close(struct file *file)
 {
        struct video_device *vdev = file->private_data;
        struct pwc_device *pdev;
-       int i;
 
        PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
 
        pdev = video_get_drvdata(vdev);
-       if (pdev->vopen == 0)
-               PWC_DEBUG_MODULE("video_close() called on closed device?\n");
-
-       /* Dump statistics, but only if a reasonable amount of frames were
-          processed (to prevent endless log-entries in case of snap-shot
-          programs)
-        */
-       if (pdev->vframe_count > 20)
-               PWC_DEBUG_MODULE("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
-
-       if (DEVICE_USE_CODEC1(pdev->type))
-           pwc_dec1_exit();
-       else
-           pwc_dec23_exit();
-
-       pwc_isoc_cleanup(pdev);
-       pwc_free_buffers(pdev);
-
-       /* Turn off LEDS and power down camera, but only when not unplugged */
-       if (!pdev->unplugged) {
-               /* Turn LEDs off */
-               if (pwc_set_leds(pdev, 0, 0) < 0)
-                       PWC_DEBUG_MODULE("Failed to set LED on/off time.\n");
-               if (power_save) {
-                       i = pwc_camera_power(pdev, 0);
-                       if (i < 0)
-                               PWC_ERROR("Failed to power down camera (%d)\n", i);
-               }
-               pdev->vopen--;
-               PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
+       if (pdev->capt_file == file) {
+               vb2_queue_release(&pdev->vb_queue);
+               pdev->capt_file = NULL;
        }
 
+       PWC_DEBUG_OPEN("<< video_close()\n");
        return 0;
 }
 
-/*
- *     FIXME: what about two parallel reads ????
- *      ANSWER: Not supported. You can't open the device more than once,
-               despite what the V4L1 interface says. First, I don't see
-               the need, second there's no mechanism of alerting the
-               2nd/3rd/... process of events like changing image size.
-               And I don't see the point of blocking that for the
-               2nd/3rd/... process.
-               In multi-threaded environments reading parallel from any
-               device is tricky anyhow.
- */
-
 static ssize_t pwc_video_read(struct file *file, char __user *buf,
-                         size_t count, loff_t *ppos)
+                             size_t count, loff_t *ppos)
 {
        struct video_device *vdev = file->private_data;
-       struct pwc_device *pdev;
-       int noblock = file->f_flags & O_NONBLOCK;
-       DECLARE_WAITQUEUE(wait, current);
-       int bytes_to_read, rv = 0;
-       void *image_buffer_addr;
-
-       PWC_DEBUG_READ("pwc_video_read(vdev=0x%p, buf=%p, count=%zd) called.\n",
-                       vdev, buf, count);
-       if (vdev == NULL)
-               return -EFAULT;
-       pdev = video_get_drvdata(vdev);
-       if (pdev == NULL)
-               return -EFAULT;
+       struct pwc_device *pdev = video_get_drvdata(vdev);
 
-       if (pdev->error_status) {
-               rv = -pdev->error_status; /* Something happened, report what. */
-               goto err_out;
-       }
+       if (!pdev->udev)
+               return -ENODEV;
 
-       /* Start the stream (if not already started) */
-       rv = pwc_isoc_init(pdev);
-       if (rv)
-               goto err_out;
-
-       /* In case we're doing partial reads, we don't have to wait for a frame */
-       if (pdev->image_read_pos == 0) {
-               /* Do wait queueing according to the (doc)book */
-               add_wait_queue(&pdev->frameq, &wait);
-               while (pdev->full_frames == NULL) {
-                       /* Check for unplugged/etc. here */
-                       if (pdev->error_status) {
-                               remove_wait_queue(&pdev->frameq, &wait);
-                               set_current_state(TASK_RUNNING);
-                               rv = -pdev->error_status ;
-                               goto err_out;
-                       }
-                       if (noblock) {
-                               remove_wait_queue(&pdev->frameq, &wait);
-                               set_current_state(TASK_RUNNING);
-                               rv = -EWOULDBLOCK;
-                               goto err_out;
-                       }
-                       if (signal_pending(current)) {
-                               remove_wait_queue(&pdev->frameq, &wait);
-                               set_current_state(TASK_RUNNING);
-                               rv = -ERESTARTSYS;
-                               goto err_out;
-                       }
-                       mutex_unlock(&pdev->modlock);
-                       schedule();
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       mutex_lock(&pdev->modlock);
-               }
-               remove_wait_queue(&pdev->frameq, &wait);
-               set_current_state(TASK_RUNNING);
+       if (pdev->capt_file != NULL &&
+           pdev->capt_file != file)
+               return -EBUSY;
 
-               /* Decompress and release frame */
-               if (pwc_handle_frame(pdev)) {
-                       rv = -EFAULT;
-                       goto err_out;
-               }
-       }
+       pdev->capt_file = file;
 
-       PWC_DEBUG_READ("Copying data to user space.\n");
-       if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
-               bytes_to_read = pdev->frame_size + sizeof(struct pwc_raw_frame);
-       else
-               bytes_to_read = pdev->view.size;
-
-       /* copy bytes to user space; we allow for partial reads */
-       if (count + pdev->image_read_pos > bytes_to_read)
-               count = bytes_to_read - pdev->image_read_pos;
-       image_buffer_addr = pdev->image_data;
-       image_buffer_addr += pdev->images[pdev->fill_image].offset;
-       image_buffer_addr += pdev->image_read_pos;
-       if (copy_to_user(buf, image_buffer_addr, count)) {
-               rv = -EFAULT;
-               goto err_out;
-       }
-       pdev->image_read_pos += count;
-       if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */
-               pdev->image_read_pos = 0;
-               pwc_next_image(pdev);
-       }
-       return count;
-err_out:
-       return rv;
+       return vb2_read(&pdev->vb_queue, buf, count, ppos,
+                       file->f_flags & O_NONBLOCK);
 }
 
 static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
 {
        struct video_device *vdev = file->private_data;
-       struct pwc_device *pdev;
-       int ret;
+       struct pwc_device *pdev = video_get_drvdata(vdev);
 
-       if (vdev == NULL)
-               return -EFAULT;
-       pdev = video_get_drvdata(vdev);
-       if (pdev == NULL)
-               return -EFAULT;
+       if (!pdev->udev)
+               return POLL_ERR;
 
-       /* Start the stream (if not already started) */
-       ret = pwc_isoc_init(pdev);
-       if (ret)
-               return ret;
+       return vb2_poll(&pdev->vb_queue, file, wait);
+}
+
+static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct video_device *vdev = file->private_data;
+       struct pwc_device *pdev = video_get_drvdata(vdev);
+
+       if (pdev->capt_file != file)
+               return -EBUSY;
+
+       return vb2_mmap(&pdev->vb_queue, vma);
+}
+
+/***************************************************************************/
+/* Videobuf2 operations */
+
+static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+                               unsigned int *nplanes, unsigned long sizes[],
+                               void *alloc_ctxs[])
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vq);
+
+       if (*nbuffers < MIN_FRAMES)
+               *nbuffers = MIN_FRAMES;
+       else if (*nbuffers > MAX_FRAMES)
+               *nbuffers = MAX_FRAMES;
+
+       *nplanes = 1;
 
-       poll_wait(file, &pdev->frameq, wait);
-       if (pdev->error_status)
-               return POLLERR;
-       if (pdev->full_frames != NULL) /* we have frames waiting */
-               return (POLLIN | POLLRDNORM);
+       sizes[0] = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2);
 
        return 0;
 }
 
-static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
+static int buffer_init(struct vb2_buffer *vb)
 {
-       struct video_device *vdev = file->private_data;
-       struct pwc_device *pdev;
-       unsigned long start;
-       unsigned long size;
-       unsigned long page, pos = 0;
-       int index;
+       struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
 
-       PWC_DEBUG_MEMORY(">> %s\n", __func__);
-       pdev = video_get_drvdata(vdev);
-       size = vma->vm_end - vma->vm_start;
-       start = vma->vm_start;
+       /* need vmalloc since frame buffer > 128K */
+       buf->data = vzalloc(PWC_FRAME_SIZE);
+       if (buf->data == NULL)
+               return -ENOMEM;
 
-       /* Find the idx buffer for this mapping */
-       for (index = 0; index < pwc_mbufs; index++) {
-               pos = pdev->images[index].offset;
-               if ((pos>>PAGE_SHIFT) == vma->vm_pgoff)
-                       break;
+       return 0;
+}
+
+static int buffer_prepare(struct vb2_buffer *vb)
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
+
+       /* Don't allow queing new buffers after device disconnection */
+       if (!pdev->udev)
+               return -ENODEV;
+
+       return 0;
+}
+
+static int buffer_finish(struct vb2_buffer *vb)
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
+       struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+
+       /*
+        * Application has called dqbuf and is getting back a buffer we've
+        * filled, take the pwc data we've stored in buf->data and decompress
+        * it into a usable format, storing the result in the vb2_buffer
+        */
+       return pwc_decompress(pdev, buf);
+}
+
+static void buffer_cleanup(struct vb2_buffer *vb)
+{
+       struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+
+       vfree(buf->data);
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
+       struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
+       list_add_tail(&buf->list, &pdev->queued_bufs);
+       spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
+}
+
+static int start_streaming(struct vb2_queue *vq)
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vq);
+
+       if (!pdev->udev)
+               return -ENODEV;
+
+       /* Turn on camera and set LEDS on */
+       pwc_camera_power(pdev, 1);
+       if (pdev->power_save) {
+               /* Restore video mode */
+               pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y,
+                                  pdev->vframes, pdev->vcompression,
+                                  pdev->vsnapshot);
        }
-       if (index == MAX_IMAGES)
-               return -EINVAL;
-       if (index == 0) {
-               /*
-                * Special case for v4l1. In v4l1, we map only one big buffer,
-                * but in v4l2 each buffer is mapped
-                */
-               unsigned long total_size;
-               total_size = pwc_mbufs * pdev->len_per_image;
-               if (size != pdev->len_per_image && size != total_size) {
-                       PWC_ERROR("Wrong size (%lu) needed to be len_per_image=%d or total_size=%lu\n",
-                                  size, pdev->len_per_image, total_size);
-                       return -EINVAL;
-               }
-       } else if (size > pdev->len_per_image)
-               return -EINVAL;
-
-       vma->vm_flags |= VM_IO; /* from 2.6.9-acX */
-
-       pos += (unsigned long)pdev->image_data;
-       while (size > 0) {
-               page = vmalloc_to_pfn((void *)pos);
-               if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-                       return -EAGAIN;
-               start += PAGE_SIZE;
-               pos += PAGE_SIZE;
-               if (size > PAGE_SIZE)
-                       size -= PAGE_SIZE;
-               else
-                       size = 0;
+       pwc_set_leds(pdev, led_on, led_off);
+
+       return pwc_isoc_init(pdev);
+}
+
+static int stop_streaming(struct vb2_queue *vq)
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vq);
+
+       if (pdev->udev) {
+               pwc_set_leds(pdev, 0, 0);
+               pwc_camera_power(pdev, 0);
+               pwc_isoc_cleanup(pdev);
        }
+       pwc_cleanup_queued_bufs(pdev);
+
        return 0;
 }
 
+static void pwc_lock(struct vb2_queue *vq)
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vq);
+       mutex_lock(&pdev->modlock);
+}
+
+static void pwc_unlock(struct vb2_queue *vq)
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vq);
+       mutex_unlock(&pdev->modlock);
+}
+
+static struct vb2_ops pwc_vb_queue_ops = {
+       .queue_setup            = queue_setup,
+       .buf_init               = buffer_init,
+       .buf_prepare            = buffer_prepare,
+       .buf_finish             = buffer_finish,
+       .buf_cleanup            = buffer_cleanup,
+       .buf_queue              = buffer_queue,
+       .start_streaming        = start_streaming,
+       .stop_streaming         = stop_streaming,
+       .wait_prepare           = pwc_unlock,
+       .wait_finish            = pwc_lock,
+};
+
 /***************************************************************************/
 /* USB functions */
 
@@ -1406,6 +890,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        int hint, rc;
        int features = 0;
        int video_nr = -1; /* default: use next available device */
+       int my_power_save = power_save;
        char serial_number[30], *name;
 
        vendor_id = le16_to_cpu(udev->descriptor.idVendor);
@@ -1513,6 +998,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                        PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
                        name = "Logitech QuickCam Pro 4000";
                        type_id = 740; /* CCD sensor */
+                       if (my_power_save == -1)
+                               my_power_save = 1;
                        break;
                case 0x08b3:
                        PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
@@ -1523,12 +1010,15 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                        PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
                        name = "Logitech QuickCam Zoom";
                        type_id = 740; /* CCD sensor */
-                       power_save = 1;
+                       if (my_power_save == -1)
+                               my_power_save = 1;
                        break;
                case 0x08b5:
                        PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
                        name = "Logitech QuickCam Orbit";
                        type_id = 740; /* CCD sensor */
+                       if (my_power_save == -1)
+                               my_power_save = 1;
                        features |= FEATURE_MOTOR_PANTILT;
                        break;
                case 0x08b6:
@@ -1583,6 +1073,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                        PWC_INFO("Creative Labs Webcam 5 detected.\n");
                        name = "Creative Labs Webcam 5";
                        type_id = 730;
+                       if (my_power_save == -1)
+                               my_power_save = 1;
                        break;
                case 0x4011:
                        PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
@@ -1640,6 +1132,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        else
                return -ENODEV; /* Not any of the know types; but the list keeps growing. */
 
+       if (my_power_save == -1)
+               my_power_save = 0;
+
        memset(serial_number, 0, 30);
        usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
        PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
@@ -1654,7 +1149,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                return -ENOMEM;
        }
        pdev->type = type_id;
-       pdev->vsize = default_size;
        pdev->vframes = default_fps;
        strcpy(pdev->serial, serial_number);
        pdev->features = features;
@@ -1668,13 +1162,26 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                pdev->angle_range.tilt_min = -3000;
                pdev->angle_range.tilt_max =  2500;
        }
+       pwc_construct(pdev); /* set min/max sizes correct */
 
        mutex_init(&pdev->modlock);
-       spin_lock_init(&pdev->ptrlock);
+       mutex_init(&pdev->udevlock);
+       spin_lock_init(&pdev->queued_bufs_lock);
+       INIT_LIST_HEAD(&pdev->queued_bufs);
 
        pdev->udev = udev;
-       init_waitqueue_head(&pdev->frameq);
        pdev->vcompression = pwc_preferred_compression;
+       pdev->power_save = my_power_save;
+
+       /* Init videobuf2 queue structure */
+       memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue));
+       pdev->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       pdev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+       pdev->vb_queue.drv_priv = pdev;
+       pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf);
+       pdev->vb_queue.ops = &pwc_vb_queue_ops;
+       pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
+       vb2_queue_init(&pdev->vb_queue);
 
        /* Init video_device structure */
        memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
@@ -1707,14 +1214,40 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
        usb_set_intfdata(intf, pdev);
 
+#ifdef CONFIG_USB_PWC_DEBUG
+       /* Query sensor type */
+       if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
+               PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
+                               pdev->vdev.name,
+                               pwc_sensor_type_to_string(rc), rc);
+       }
+#endif
+
        /* Set the leds off */
        pwc_set_leds(pdev, 0, 0);
+
+       /* Setup intial videomode */
+       rc = pwc_set_video_mode(pdev, pdev->view_max.x, pdev->view_max.y,
+                               pdev->vframes, pdev->vcompression, 0);
+       if (rc)
+               goto err_free_mem;
+
+       /* Register controls (and read default values from camera */
+       rc = pwc_init_controls(pdev);
+       if (rc) {
+               PWC_ERROR("Failed to register v4l2 controls (%d).\n", rc);
+               goto err_free_mem;
+       }
+
+       pdev->vdev.ctrl_handler = &pdev->ctrl_handler;
+
+       /* And powerdown the camera until streaming starts */
        pwc_camera_power(pdev, 0);
 
        rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
        if (rc < 0) {
                PWC_ERROR("Failed to register as video device (%d).\n", rc);
-               goto err_free_mem;
+               goto err_free_controls;
        }
        rc = pwc_create_sysfs_files(pdev);
        if (rc)
@@ -1757,7 +1290,10 @@ err_video_unreg:
        if (hint < MAX_DEV_HINTS)
                device_hint[hint].pdev = NULL;
        video_unregister_device(&pdev->vdev);
+err_free_controls:
+       v4l2_ctrl_handler_free(&pdev->ctrl_handler);
 err_free_mem:
+       usb_set_intfdata(intf, NULL);
        kfree(pdev);
        return rc;
 }
@@ -1767,33 +1303,17 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
 {
        struct pwc_device *pdev  = usb_get_intfdata(intf);
 
+       mutex_lock(&pdev->udevlock);
        mutex_lock(&pdev->modlock);
-       usb_set_intfdata (intf, NULL);
-       if (pdev == NULL) {
-               PWC_ERROR("pwc_disconnect() Called without private pointer.\n");
-               goto disconnect_out;
-       }
-       if (pdev->udev == NULL) {
-               PWC_ERROR("pwc_disconnect() already called for %p\n", pdev);
-               goto disconnect_out;
-       }
-       if (pdev->udev != interface_to_usbdev(intf)) {
-               PWC_ERROR("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
-               goto disconnect_out;
-       }
-
-       /* We got unplugged; this is signalled by an EPIPE error code */
-       pdev->error_status = EPIPE;
-       pdev->unplugged = 1;
-
-       /* Alert waiting processes */
-       wake_up_interruptible(&pdev->frameq);
 
+       usb_set_intfdata(intf, NULL);
        /* No need to keep the urbs around after disconnection */
        pwc_isoc_cleanup(pdev);
+       pwc_cleanup_queued_bufs(pdev);
+       pdev->udev = NULL;
 
-disconnect_out:
        mutex_unlock(&pdev->modlock);
+       mutex_unlock(&pdev->udevlock);
 
        pwc_remove_sysfs_files(pdev);
        video_unregister_device(&pdev->vdev);
@@ -1809,36 +1329,27 @@ disconnect_out:
  * Initialization code & module stuff
  */
 
-static char *size;
 static int fps;
-static int fbufs;
-static int mbufs;
 static int compression = -1;
 static int leds[2] = { -1, -1 };
 static unsigned int leds_nargs;
 static char *dev_hint[MAX_DEV_HINTS];
 static unsigned int dev_hint_nargs;
 
-module_param(size, charp, 0444);
 module_param(fps, int, 0444);
-module_param(fbufs, int, 0444);
-module_param(mbufs, int, 0444);
 #ifdef CONFIG_USB_PWC_DEBUG
 module_param_named(trace, pwc_trace, int, 0644);
 #endif
-module_param(power_save, int, 0444);
+module_param(power_save, int, 0644);
 module_param(compression, int, 0444);
 module_param_array(leds, int, &leds_nargs, 0444);
 module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
 
-MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
 MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
-MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
-MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
 #ifdef CONFIG_USB_PWC_DEBUG
 MODULE_PARM_DESC(trace, "For debugging purposes");
 #endif
-MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
+MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
 MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
 MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
 MODULE_PARM_DESC(dev_hint, "Device node hints");
@@ -1851,14 +1362,19 @@ MODULE_VERSION( PWC_VERSION );
 
 static int __init usb_pwc_init(void)
 {
-       int i, sz;
-       char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
+       int i;
 
+#ifdef CONFIG_USB_PWC_DEBUG
        PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
        PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
        PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
        PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
 
+       if (pwc_trace >= 0) {
+               PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
+       }
+#endif
+
        if (fps) {
                if (fps < 4 || fps > 30) {
                        PWC_ERROR("Framerate out of bounds (4-30).\n");
@@ -1868,41 +1384,6 @@ static int __init usb_pwc_init(void)
                PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
        }
 
-       if (size) {
-               /* string; try matching with array */
-               for (sz = 0; sz < PSZ_MAX; sz++) {
-                       if (!strcmp(sizenames[sz], size)) { /* Found! */
-                               default_size = sz;
-                               break;
-                       }
-               }
-               if (sz == PSZ_MAX) {
-                       PWC_ERROR("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
-                       return -EINVAL;
-               }
-               PWC_DEBUG_MODULE("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
-       }
-       if (mbufs) {
-               if (mbufs < 1 || mbufs > MAX_IMAGES) {
-                       PWC_ERROR("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
-                       return -EINVAL;
-               }
-               pwc_mbufs = mbufs;
-               PWC_DEBUG_MODULE("Number of image buffers set to %d.\n", pwc_mbufs);
-       }
-       if (fbufs) {
-               if (fbufs < 2 || fbufs > MAX_FRAMES) {
-                       PWC_ERROR("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
-                       return -EINVAL;
-               }
-               default_fbufs = fbufs;
-               PWC_DEBUG_MODULE("Number of frame buffers set to %d.\n", default_fbufs);
-       }
-#ifdef CONFIG_USB_PWC_DEBUG
-       if (pwc_trace >= 0) {
-               PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
-       }
-#endif
        if (compression >= 0) {
                if (compression > 3) {
                        PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
@@ -1911,8 +1392,6 @@ static int __init usb_pwc_init(void)
                pwc_preferred_compression = compression;
                PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
        }
-       if (power_save)
-               PWC_DEBUG_MODULE("Enabling power save on open/close.\n");
        if (leds[0] >= 0)
                led_on = leds[0];
        if (leds[1] >= 0)
diff --git a/drivers/media/video/pwc/pwc-ioctl.h b/drivers/media/video/pwc/pwc-ioctl.h
deleted file mode 100644 (file)
index 8c0cae7..0000000
+++ /dev/null
@@ -1,323 +0,0 @@
-#ifndef PWC_IOCTL_H
-#define PWC_IOCTL_H
-
-/* (C) 2001-2004 Nemosoft Unv.
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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
-*/
-
-/* This is pwc-ioctl.h belonging to PWC 10.0.10
-   It contains structures and defines to communicate from user space
-   directly to the driver.
- */
-
-/*
-   Changes
-   2001/08/03  Alvarado   Added ioctl constants to access methods for
-                         changing white balance and red/blue gains
-   2002/12/15  G. H. Fernandez-Toribio   VIDIOCGREALSIZE
-   2003/12/13  Nemosft Unv. Some modifications to make interfacing to
-              PWCX easier
- */
-
-/* These are private ioctl() commands, specific for the Philips webcams.
-   They contain functions not found in other webcams, and settings not
-   specified in the Video4Linux API.
-
-   The #define names are built up like follows:
-   VIDIOC              VIDeo IOCtl prefix
-        PWC            Philps WebCam
-           G           optional: Get
-           S           optional: Set
-            ...        the function
- */
-
-#include <linux/types.h>
-#include <linux/version.h>
-
- /* Enumeration of image sizes */
-#define PSZ_SQCIF      0x00
-#define PSZ_QSIF       0x01
-#define PSZ_QCIF       0x02
-#define PSZ_SIF                0x03
-#define PSZ_CIF                0x04
-#define PSZ_VGA                0x05
-#define PSZ_MAX                6
-
-
-/* The frame rate is encoded in the video_window.flags parameter using
-   the upper 16 bits, since some flags are defined nowadays. The following
-   defines provide a mask and shift to filter out this value.
-   This value can also be passing using the private flag when using v4l2 and
-   VIDIOC_S_FMT ioctl.
-
-   In 'Snapshot' mode the camera freezes its automatic exposure and colour
-   balance controls.
- */
-#define PWC_FPS_SHIFT          16
-#define PWC_FPS_MASK           0x00FF0000
-#define PWC_FPS_FRMASK         0x003F0000
-#define PWC_FPS_SNAPSHOT       0x00400000
-#define PWC_QLT_MASK           0x03000000
-#define PWC_QLT_SHIFT          24
-
-
-/* structure for transferring x & y coordinates */
-struct pwc_coord
-{
-       int x, y;               /* guess what */
-       int size;               /* size, or offset */
-};
-
-
-/* Used with VIDIOCPWCPROBE */
-struct pwc_probe
-{
-       char name[32];
-       int type;
-};
-
-struct pwc_serial
-{
-       char serial[30];        /* String with serial number. Contains terminating 0 */
-};
-
-/* pwc_whitebalance.mode values */
-#define PWC_WB_INDOOR          0
-#define PWC_WB_OUTDOOR         1
-#define PWC_WB_FL              2
-#define PWC_WB_MANUAL          3
-#define PWC_WB_AUTO            4
-
-/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
-   Set mode to one of the PWC_WB_* values above.
-   *red and *blue are the respective gains of these colour components inside
-   the camera; range 0..65535
-   When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
-   otherwise undefined.
-   'read_red' and 'read_blue' are read-only.
-*/
-struct pwc_whitebalance
-{
-       int mode;
-       int manual_red, manual_blue;    /* R/W */
-       int read_red, read_blue;        /* R/O */
-};
-
-/*
-   'control_speed' and 'control_delay' are used in automatic whitebalance mode,
-   and tell the camera how fast it should react to changes in lighting, and
-   with how much delay. Valid values are 0..65535.
-*/
-struct pwc_wb_speed
-{
-       int control_speed;
-       int control_delay;
-
-};
-
-/* Used with VIDIOCPWC[SG]LED */
-struct pwc_leds
-{
-       int led_on;                     /* Led on-time; range = 0..25000 */
-       int led_off;                    /* Led off-time; range = 0..25000  */
-};
-
-/* Image size (used with GREALSIZE) */
-struct pwc_imagesize
-{
-       int width;
-       int height;
-};
-
-/* Defines and structures for Motorized Pan & Tilt */
-#define PWC_MPT_PAN            0x01
-#define PWC_MPT_TILT           0x02
-#define PWC_MPT_TIMEOUT                0x04 /* for status */
-
-/* Set angles; when absolute != 0, the angle is absolute and the
-   driver calculates the relative offset for you. This can only
-   be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
-   absolute angles.
- */
-struct pwc_mpt_angles
-{
-       int absolute;           /* write-only */
-       int pan;                /* degrees * 100 */
-       int tilt;               /* degress * 100 */
-};
-
-/* Range of angles of the camera, both horizontally and vertically.
- */
-struct pwc_mpt_range
-{
-       int pan_min, pan_max;           /* degrees * 100 */
-       int tilt_min, tilt_max;
-};
-
-struct pwc_mpt_status
-{
-       int status;
-       int time_pan;
-       int time_tilt;
-};
-
-
-/* This is used for out-of-kernel decompression. With it, you can get
-   all the necessary information to initialize and use the decompressor
-   routines in standalone applications.
- */
-struct pwc_video_command
-{
-       int type;               /* camera type (645, 675, 730, etc.) */
-       int release;            /* release number */
-
-       int size;               /* one of PSZ_* */
-       int alternate;
-       int command_len;        /* length of USB video command */
-       unsigned char command_buf[13];  /* Actual USB video command */
-       int bandlength;         /* >0 = compressed */
-       int frame_size;         /* Size of one (un)compressed frame */
-};
-
-/* Flags for PWCX subroutines. Not all modules honour all flags. */
-#define PWCX_FLAG_PLANAR       0x0001
-#define PWCX_FLAG_BAYER                0x0008
-
-
-/* IOCTL definitions */
-
- /* Restore user settings */
-#define VIDIOCPWCRUSER         _IO('v', 192)
- /* Save user settings */
-#define VIDIOCPWCSUSER         _IO('v', 193)
- /* Restore factory settings */
-#define VIDIOCPWCFACTORY       _IO('v', 194)
-
- /* You can manipulate the compression factor. A compression preference of 0
-    means use uncompressed modes when available; 1 is low compression, 2 is
-    medium and 3 is high compression preferred. Of course, the higher the
-    compression, the lower the bandwidth used but more chance of artefacts
-    in the image. The driver automatically chooses a higher compression when
-    the preferred mode is not available.
-  */
- /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
-#define VIDIOCPWCSCQUAL                _IOW('v', 195, int)
- /* Get preferred compression quality */
-#define VIDIOCPWCGCQUAL                _IOR('v', 195, int)
-
-
-/* Retrieve serial number of camera */
-#define VIDIOCPWCGSERIAL       _IOR('v', 198, struct pwc_serial)
-
- /* This is a probe function; since so many devices are supported, it
-    becomes difficult to include all the names in programs that want to
-    check for the enhanced Philips stuff. So in stead, try this PROBE;
-    it returns a structure with the original name, and the corresponding
-    Philips type.
-    To use, fill the structure with zeroes, call PROBE and if that succeeds,
-    compare the name with that returned from VIDIOCGCAP; they should be the
-    same. If so, you can be assured it is a Philips (OEM) cam and the type
-    is valid.
- */
-#define VIDIOCPWCPROBE         _IOR('v', 199, struct pwc_probe)
-
- /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
-#define VIDIOCPWCSAGC          _IOW('v', 200, int)
- /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
-#define VIDIOCPWCGAGC          _IOR('v', 200, int)
- /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
-#define VIDIOCPWCSSHUTTER      _IOW('v', 201, int)
-
- /* Color compensation (Auto White Balance) */
-#define VIDIOCPWCSAWB           _IOW('v', 202, struct pwc_whitebalance)
-#define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
-
- /* Auto WB speed */
-#define VIDIOCPWCSAWBSPEED     _IOW('v', 203, struct pwc_wb_speed)
-#define VIDIOCPWCGAWBSPEED     _IOR('v', 203, struct pwc_wb_speed)
-
- /* LEDs on/off/blink; int range 0..65535 */
-#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
-#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
-
-  /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
-#define VIDIOCPWCSCONTOUR      _IOW('v', 206, int)
-#define VIDIOCPWCGCONTOUR      _IOR('v', 206, int)
-
-  /* Backlight compensation; 0 = off, otherwise on */
-#define VIDIOCPWCSBACKLIGHT    _IOW('v', 207, int)
-#define VIDIOCPWCGBACKLIGHT    _IOR('v', 207, int)
-
-  /* Flickerless mode; = 0 off, otherwise on */
-#define VIDIOCPWCSFLICKER      _IOW('v', 208, int)
-#define VIDIOCPWCGFLICKER      _IOR('v', 208, int)
-
-  /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
-#define VIDIOCPWCSDYNNOISE     _IOW('v', 209, int)
-#define VIDIOCPWCGDYNNOISE     _IOR('v', 209, int)
-
- /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
-#define VIDIOCPWCGREALSIZE     _IOR('v', 210, struct pwc_imagesize)
-
- /* Motorized pan & tilt functions */
-#define VIDIOCPWCMPTRESET      _IOW('v', 211, int)
-#define VIDIOCPWCMPTGRANGE     _IOR('v', 211, struct pwc_mpt_range)
-#define VIDIOCPWCMPTSANGLE     _IOW('v', 212, struct pwc_mpt_angles)
-#define VIDIOCPWCMPTGANGLE     _IOR('v', 212, struct pwc_mpt_angles)
-#define VIDIOCPWCMPTSTATUS     _IOR('v', 213, struct pwc_mpt_status)
-
- /* Get the USB set-video command; needed for initializing libpwcx */
-#define VIDIOCPWCGVIDCMD       _IOR('v', 215, struct pwc_video_command)
-struct pwc_table_init_buffer {
-   int len;
-   char *buffer;
-
-};
-#define VIDIOCPWCGVIDTABLE     _IOR('v', 216, struct pwc_table_init_buffer)
-
-/*
- * This is private command used when communicating with v4l2.
- * In the future all private ioctl will be remove/replace to
- * use interface offer by v4l2.
- */
-
-#define V4L2_CID_PRIVATE_SAVE_USER       (V4L2_CID_PRIVATE_BASE + 0)
-#define V4L2_CID_PRIVATE_RESTORE_USER    (V4L2_CID_PRIVATE_BASE + 1)
-#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2)
-#define V4L2_CID_PRIVATE_COLOUR_MODE     (V4L2_CID_PRIVATE_BASE + 3)
-#define V4L2_CID_PRIVATE_AUTOCONTOUR     (V4L2_CID_PRIVATE_BASE + 4)
-#define V4L2_CID_PRIVATE_CONTOUR         (V4L2_CID_PRIVATE_BASE + 5)
-#define V4L2_CID_PRIVATE_BACKLIGHT       (V4L2_CID_PRIVATE_BASE + 6)
-#define V4L2_CID_PRIVATE_FLICKERLESS     (V4L2_CID_PRIVATE_BASE + 7)
-#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8)
-
-struct pwc_raw_frame {
-   __le16 type;                /* type of the webcam */
-   __le16 vbandlength; /* Size of 4lines compressed (used by the decompressor) */
-   __u8   cmd[4];      /* the four byte of the command (in case of nala,
-                          only the first 3 bytes is filled) */
-   __u8   rawframe[0]; /* frame_size = H/4*vbandlength */
-} __attribute__ ((packed));
-
-
-#endif
index f4ae83c..e5f4fd8 100644 (file)
@@ -40,7 +40,6 @@
 
 
 #include "pwc-kiara.h"
-#include "pwc-uncompress.h"
 
 const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA] = { 5, 10, 15, 20, 25, 30 };
 
index 6af5bb5..0b03133 100644 (file)
@@ -126,8 +126,4 @@ void pwc_construct(struct pwc_device *pdev)
        pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */
        pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
        pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
-       /* length of image, in YUV format; always allocate enough memory. */
-       pdev->len_per_image = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2);
 }
-
-
index 3b73f29..5126509 100644 (file)
 #include <asm/types.h>
 
 #include "pwc.h"
-#include "pwc-uncompress.h"
 #include "pwc-dec1.h"
 #include "pwc-dec23.h"
 
-int pwc_decompress(struct pwc_device *pdev)
+int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
 {
-       struct pwc_frame_buf *fbuf;
        int n, line, col, stride;
        void *yuv, *image;
        u16 *src;
        u16 *dsty, *dstu, *dstv;
 
-       if (pdev == NULL)
-               return -EFAULT;
-
-       fbuf = pdev->read_frame;
-       if (fbuf == NULL)
-               return -EFAULT;
-       image  = pdev->image_data;
-       image += pdev->images[pdev->fill_image].offset;
+       image = vb2_plane_vaddr(&fbuf->vb, 0);
 
        yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
 
@@ -64,9 +55,13 @@ int pwc_decompress(struct pwc_device *pdev)
                         * determine this using the type of the webcam */
                memcpy(raw_frame->cmd, pdev->cmd_buf, 4);
                memcpy(raw_frame+1, yuv, pdev->frame_size);
+               vb2_set_plane_payload(&fbuf->vb, 0,
+                       pdev->frame_size + sizeof(struct pwc_raw_frame));
                return 0;
        }
 
+       vb2_set_plane_payload(&fbuf->vb, 0, pdev->view.size);
+
        if (pdev->vbandlength == 0) {
                /* Uncompressed mode.
                 * We copy the data into the output buffer, using the viewport
diff --git a/drivers/media/video/pwc/pwc-uncompress.h b/drivers/media/video/pwc/pwc-uncompress.h
deleted file mode 100644 (file)
index 43028e7..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* (C) 1999-2003 Nemosoft Unv.
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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
-*/
-
-/* This file is the bridge between the kernel module and the plugin; it
-   describes the structures and datatypes used in both modules. Any
-   significant change should be reflected by increasing the
-   pwc_decompressor_version major number.
- */
-#ifndef PWC_UNCOMPRESS_H
-#define PWC_UNCOMPRESS_H
-
-
-#include <media/pwc-ioctl.h>
-
-/* from pwc-dec.h */
-#define PWCX_FLAG_PLANAR        0x0001
-/* */
-
-#endif
index f85c512..e9a0e94 100644 (file)
@@ -2,6 +2,7 @@
    USB and Video4Linux interface part.
    (C) 1999-2004 Nemosoft Unv.
    (C) 2004-2006 Luc Saillard (luc@saillard.org)
+   (C) 2011 Hans de Goede <hdegoede@redhat.com>
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/vmalloc.h>
+#include <linux/jiffies.h>
 #include <asm/io.h>
 
 #include "pwc.h"
 
-static struct v4l2_queryctrl pwc_controls[] = {
-       {
-           .id      = V4L2_CID_BRIGHTNESS,
-           .type    = V4L2_CTRL_TYPE_INTEGER,
-           .name    = "Brightness",
-           .minimum = 0,
-           .maximum = 128,
-           .step    = 1,
-           .default_value = 64,
-       },
-       {
-           .id      = V4L2_CID_CONTRAST,
-           .type    = V4L2_CTRL_TYPE_INTEGER,
-           .name    = "Contrast",
-           .minimum = 0,
-           .maximum = 64,
-           .step    = 1,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_SATURATION,
-           .type    = V4L2_CTRL_TYPE_INTEGER,
-           .name    = "Saturation",
-           .minimum = -100,
-           .maximum = 100,
-           .step    = 1,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_GAMMA,
-           .type    = V4L2_CTRL_TYPE_INTEGER,
-           .name    = "Gamma",
-           .minimum = 0,
-           .maximum = 32,
-           .step    = 1,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_RED_BALANCE,
-           .type    = V4L2_CTRL_TYPE_INTEGER,
-           .name    = "Red Gain",
-           .minimum = 0,
-           .maximum = 256,
-           .step    = 1,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_BLUE_BALANCE,
-           .type    = V4L2_CTRL_TYPE_INTEGER,
-           .name    = "Blue Gain",
-           .minimum = 0,
-           .maximum = 256,
-           .step    = 1,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_AUTO_WHITE_BALANCE,
-           .type    = V4L2_CTRL_TYPE_BOOLEAN,
-           .name    = "Auto White Balance",
-           .minimum = 0,
-           .maximum = 1,
-           .step    = 1,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_EXPOSURE,
-           .type    = V4L2_CTRL_TYPE_INTEGER,
-           .name    = "Shutter Speed (Exposure)",
-           .minimum = 0,
-           .maximum = 256,
-           .step    = 1,
-           .default_value = 200,
-       },
-       {
-           .id      = V4L2_CID_AUTOGAIN,
-           .type    = V4L2_CTRL_TYPE_BOOLEAN,
-           .name    = "Auto Gain Enabled",
-           .minimum = 0,
-           .maximum = 1,
-           .step    = 1,
-           .default_value = 1,
-       },
-       {
-           .id      = V4L2_CID_GAIN,
-           .type    = V4L2_CTRL_TYPE_INTEGER,
-           .name    = "Gain Level",
-           .minimum = 0,
-           .maximum = 256,
-           .step    = 1,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_PRIVATE_SAVE_USER,
-           .type    = V4L2_CTRL_TYPE_BUTTON,
-           .name    = "Save User Settings",
-           .minimum = 0,
-           .maximum = 0,
-           .step    = 0,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_PRIVATE_RESTORE_USER,
-           .type    = V4L2_CTRL_TYPE_BUTTON,
-           .name    = "Restore User Settings",
-           .minimum = 0,
-           .maximum = 0,
-           .step    = 0,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_PRIVATE_RESTORE_FACTORY,
-           .type    = V4L2_CTRL_TYPE_BUTTON,
-           .name    = "Restore Factory Settings",
-           .minimum = 0,
-           .maximum = 0,
-           .step    = 0,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_PRIVATE_COLOUR_MODE,
-           .type    = V4L2_CTRL_TYPE_BOOLEAN,
-           .name    = "Colour mode",
-           .minimum = 0,
-           .maximum = 1,
-           .step    = 1,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_PRIVATE_AUTOCONTOUR,
-           .type    = V4L2_CTRL_TYPE_BOOLEAN,
-           .name    = "Auto contour",
-           .minimum = 0,
-           .maximum = 1,
-           .step    = 1,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_PRIVATE_CONTOUR,
-           .type    = V4L2_CTRL_TYPE_INTEGER,
-           .name    = "Contour",
-           .minimum = 0,
-           .maximum = 63,
-           .step    = 1,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_PRIVATE_BACKLIGHT,
-           .type    = V4L2_CTRL_TYPE_BOOLEAN,
-           .name    = "Backlight compensation",
-           .minimum = 0,
-           .maximum = 1,
-           .step    = 1,
-           .default_value = 0,
-       },
-       {
-         .id      = V4L2_CID_PRIVATE_FLICKERLESS,
-           .type    = V4L2_CTRL_TYPE_BOOLEAN,
-           .name    = "Flickerless",
-           .minimum = 0,
-           .maximum = 1,
-           .step    = 1,
-           .default_value = 0,
-       },
-       {
-           .id      = V4L2_CID_PRIVATE_NOISE_REDUCTION,
-           .type    = V4L2_CTRL_TYPE_INTEGER,
-           .name    = "Noise reduction",
-           .minimum = 0,
-           .maximum = 3,
-           .step    = 1,
-           .default_value = 0,
-       },
+#define PWC_CID_CUSTOM(ctrl) ((V4L2_CID_USER_BASE | 0xf000) + custom_ ## ctrl)
+
+static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl);
+static int pwc_s_ctrl(struct v4l2_ctrl *ctrl);
+
+static const struct v4l2_ctrl_ops pwc_ctrl_ops = {
+       .g_volatile_ctrl = pwc_g_volatile_ctrl,
+       .s_ctrl = pwc_s_ctrl,
+};
+
+enum { awb_indoor, awb_outdoor, awb_fl, awb_manual, awb_auto };
+enum { custom_autocontour, custom_contour, custom_noise_reduction,
+       custom_save_user, custom_restore_user, custom_restore_factory };
+
+const char * const pwc_auto_whitebal_qmenu[] = {
+       "Indoor (Incandescant Lighting) Mode",
+       "Outdoor (Sunlight) Mode",
+       "Indoor (Fluorescent Lighting) Mode",
+       "Manual Mode",
+       "Auto Mode",
+       NULL
+};
+
+static const struct v4l2_ctrl_config pwc_auto_white_balance_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = V4L2_CID_AUTO_WHITE_BALANCE,
+       .type   = V4L2_CTRL_TYPE_MENU,
+       .max    = awb_auto,
+       .qmenu  = pwc_auto_whitebal_qmenu,
+};
+
+static const struct v4l2_ctrl_config pwc_autocontour_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(autocontour),
+       .type   = V4L2_CTRL_TYPE_BOOLEAN,
+       .name   = "Auto contour",
+       .min    = 0,
+       .max    = 1,
+       .step   = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_contour_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(contour),
+       .type   = V4L2_CTRL_TYPE_INTEGER,
+       .name   = "Contour",
+       .min    = 0,
+       .max    = 63,
+       .step   = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_backlight_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = V4L2_CID_BACKLIGHT_COMPENSATION,
+       .type   = V4L2_CTRL_TYPE_BOOLEAN,
+       .min    = 0,
+       .max    = 1,
+       .step   = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_flicker_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = V4L2_CID_BAND_STOP_FILTER,
+       .type   = V4L2_CTRL_TYPE_BOOLEAN,
+       .min    = 0,
+       .max    = 1,
+       .step   = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_noise_reduction_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(noise_reduction),
+       .type   = V4L2_CTRL_TYPE_INTEGER,
+       .name   = "Dynamic Noise Reduction",
+       .min    = 0,
+       .max    = 3,
+       .step   = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_save_user_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(save_user),
+       .type   = V4L2_CTRL_TYPE_BUTTON,
+       .name    = "Save User Settings",
 };
 
+static const struct v4l2_ctrl_config pwc_restore_user_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(restore_user),
+       .type   = V4L2_CTRL_TYPE_BUTTON,
+       .name    = "Restore User Settings",
+};
+
+static const struct v4l2_ctrl_config pwc_restore_factory_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(restore_factory),
+       .type   = V4L2_CTRL_TYPE_BUTTON,
+       .name    = "Restore Factory Settings",
+};
+
+int pwc_init_controls(struct pwc_device *pdev)
+{
+       struct v4l2_ctrl_handler *hdl;
+       struct v4l2_ctrl_config cfg;
+       int r, def;
+
+       hdl = &pdev->ctrl_handler;
+       r = v4l2_ctrl_handler_init(hdl, 20);
+       if (r)
+               return r;
+
+       /* Brightness, contrast, saturation, gamma */
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, BRIGHTNESS_FORMATTER, &def);
+       if (r || def > 127)
+               def = 63;
+       pdev->brightness = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_BRIGHTNESS, 0, 127, 1, def);
+
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, CONTRAST_FORMATTER, &def);
+       if (r || def > 63)
+               def = 31;
+       pdev->contrast = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_CONTRAST, 0, 63, 1, def);
+
+       if (pdev->type >= 675) {
+               if (pdev->type < 730)
+                       pdev->saturation_fmt = SATURATION_MODE_FORMATTER2;
+               else
+                       pdev->saturation_fmt = SATURATION_MODE_FORMATTER1;
+               r = pwc_get_s8_ctrl(pdev, GET_CHROM_CTL, pdev->saturation_fmt,
+                                   &def);
+               if (r || def < -100 || def > 100)
+                       def = 0;
+               pdev->saturation = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                                     V4L2_CID_SATURATION, -100, 100, 1, def);
+       }
+
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, GAMMA_FORMATTER, &def);
+       if (r || def > 31)
+               def = 15;
+       pdev->gamma = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_GAMMA, 0, 31, 1, def);
+
+       /* auto white balance, red gain, blue gain */
+       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, WB_MODE_FORMATTER, &def);
+       if (r || def > awb_auto)
+               def = awb_auto;
+       cfg = pwc_auto_white_balance_cfg;
+       cfg.name = v4l2_ctrl_get_name(cfg.id);
+       cfg.def = def;
+       pdev->auto_white_balance = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+       /* check auto controls to avoid NULL deref in v4l2_ctrl_auto_cluster */
+       if (!pdev->auto_white_balance)
+               return hdl->error;
+
+       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+                           PRESET_MANUAL_RED_GAIN_FORMATTER, &def);
+       if (r)
+               def = 127;
+       pdev->red_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_RED_BALANCE, 0, 255, 1, def);
+
+       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+                           PRESET_MANUAL_BLUE_GAIN_FORMATTER, &def);
+       if (r)
+               def = 127;
+       pdev->blue_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_BLUE_BALANCE, 0, 255, 1, def);
+
+       v4l2_ctrl_auto_cluster(3, &pdev->auto_white_balance, awb_manual,
+                              pdev->auto_white_balance->cur.val == awb_auto);
+
+       /* autogain, gain */
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AGC_MODE_FORMATTER, &def);
+       if (r || (def != 0 && def != 0xff))
+               def = 0;
+       /* Note a register value if 0 means auto gain is on */
+       pdev->autogain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_AUTOGAIN, 0, 1, 1, def == 0);
+       if (!pdev->autogain)
+               return hdl->error;
+
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, PRESET_AGC_FORMATTER, &def);
+       if (r || def > 63)
+               def = 31;
+       pdev->gain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_GAIN, 0, 63, 1, def);
+
+       /* auto exposure, exposure */
+       if (DEVICE_USE_CODEC2(pdev->type)) {
+               r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, SHUTTER_MODE_FORMATTER,
+                                   &def);
+               if (r || (def != 0 && def != 0xff))
+                       def = 0;
+               /*
+                * def = 0 auto, def = ff manual
+                * menu idx 0 = auto, idx 1 = manual
+                */
+               pdev->exposure_auto = v4l2_ctrl_new_std_menu(hdl,
+                                       &pwc_ctrl_ops,
+                                       V4L2_CID_EXPOSURE_AUTO,
+                                       1, 0, def != 0);
+               if (!pdev->exposure_auto)
+                       return hdl->error;
+
+               /* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */
+               r = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
+                                    READ_SHUTTER_FORMATTER, &def);
+               if (r || def > 655)
+                       def = 655;
+               pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                                       V4L2_CID_EXPOSURE, 0, 655, 1, def);
+               /* CODEC2: separate auto gain & auto exposure */
+               v4l2_ctrl_auto_cluster(2, &pdev->autogain, 0, true);
+               v4l2_ctrl_auto_cluster(2, &pdev->exposure_auto,
+                                      V4L2_EXPOSURE_MANUAL, true);
+       } else if (DEVICE_USE_CODEC3(pdev->type)) {
+               /* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */
+               r = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
+                                    READ_SHUTTER_FORMATTER, &def);
+               if (r || def > 255)
+                       def = 255;
+               pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                                       V4L2_CID_EXPOSURE, 0, 255, 1, def);
+               /* CODEC3: both gain and exposure controlled by autogain */
+               pdev->autogain_expo_cluster[0] = pdev->autogain;
+               pdev->autogain_expo_cluster[1] = pdev->gain;
+               pdev->autogain_expo_cluster[2] = pdev->exposure;
+               v4l2_ctrl_auto_cluster(3, pdev->autogain_expo_cluster,
+                                      0, true);
+       }
+
+       /* color / bw setting */
+       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, COLOUR_MODE_FORMATTER,
+                        &def);
+       if (r || (def != 0 && def != 0xff))
+               def = 0xff;
+       /* def = 0 bw, def = ff color, menu idx 0 = color, idx 1 = bw */
+       pdev->colorfx = v4l2_ctrl_new_std_menu(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_COLORFX, 1, 0, def == 0);
+
+       /* autocontour, contour */
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &def);
+       if (r || (def != 0 && def != 0xff))
+               def = 0;
+       cfg = pwc_autocontour_cfg;
+       cfg.def = def == 0;
+       pdev->autocontour = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+       if (!pdev->autocontour)
+               return hdl->error;
+
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, &def);
+       if (r || def > 63)
+               def = 31;
+       cfg = pwc_contour_cfg;
+       cfg.def = def;
+       pdev->contour = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+       v4l2_ctrl_auto_cluster(2, &pdev->autocontour, 0, false);
+
+       /* backlight */
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
+                           BACK_LIGHT_COMPENSATION_FORMATTER, &def);
+       if (r || (def != 0 && def != 0xff))
+               def = 0;
+       cfg = pwc_backlight_cfg;
+       cfg.name = v4l2_ctrl_get_name(cfg.id);
+       cfg.def = def == 0;
+       pdev->backlight = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+       /* flikker rediction */
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
+                           FLICKERLESS_MODE_FORMATTER, &def);
+       if (r || (def != 0 && def != 0xff))
+               def = 0;
+       cfg = pwc_flicker_cfg;
+       cfg.name = v4l2_ctrl_get_name(cfg.id);
+       cfg.def = def == 0;
+       pdev->flicker = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+       /* Dynamic noise reduction */
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
+                           DYNAMIC_NOISE_CONTROL_FORMATTER, &def);
+       if (r || def > 3)
+               def = 2;
+       cfg = pwc_noise_reduction_cfg;
+       cfg.def = def;
+       pdev->noise_reduction = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+       /* Save / Restore User / Factory Settings */
+       pdev->save_user = v4l2_ctrl_new_custom(hdl, &pwc_save_user_cfg, NULL);
+       pdev->restore_user = v4l2_ctrl_new_custom(hdl, &pwc_restore_user_cfg,
+                                                 NULL);
+       if (pdev->restore_user)
+               pdev->restore_user->flags = V4L2_CTRL_FLAG_UPDATE;
+       pdev->restore_factory = v4l2_ctrl_new_custom(hdl,
+                                                    &pwc_restore_factory_cfg,
+                                                    NULL);
+       if (pdev->restore_factory)
+               pdev->restore_factory->flags = V4L2_CTRL_FLAG_UPDATE;
+
+       if (!pdev->features & FEATURE_MOTOR_PANTILT)
+               return hdl->error;
+
+       /* Motor pan / tilt / reset */
+       pdev->motor_pan = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_PAN_RELATIVE, -4480, 4480, 64, 0);
+       if (!pdev->motor_pan)
+               return hdl->error;
+       pdev->motor_tilt = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_TILT_RELATIVE, -1920, 1920, 64, 0);
+       pdev->motor_pan_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_PAN_RESET, 0, 0, 0, 0);
+       pdev->motor_tilt_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_TILT_RESET, 0, 0, 0, 0);
+       v4l2_ctrl_cluster(4, &pdev->motor_pan);
+
+       return hdl->error;
+}
 
 static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f)
 {
@@ -284,10 +431,21 @@ static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
 }
 
 /* ioctl(VIDIOC_SET_FMT) */
-static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+
+static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
 {
+       struct pwc_device *pdev = video_drvdata(file);
        int ret, fps, snapshot, compression, pixelformat;
 
+       if (!pdev->udev)
+               return -ENODEV;
+
+       if (pdev->capt_file != NULL &&
+           pdev->capt_file != file)
+               return -EBUSY;
+
+       pdev->capt_file = file;
+
        ret = pwc_vidioc_try_fmt(pdev, f);
        if (ret<0)
                return ret;
@@ -309,7 +467,7 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
            pixelformat != V4L2_PIX_FMT_PWC2)
                return -EINVAL;
 
-       if (pdev->iso_init)
+       if (vb2_is_streaming(&pdev->vb_queue))
                return -EBUSY;
 
        PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d "
@@ -343,13 +501,14 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
 
 static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
 {
-       struct video_device *vdev = video_devdata(file);
        struct pwc_device *pdev = video_drvdata(file);
 
+       if (!pdev->udev)
+               return -ENODEV;
+
        strcpy(cap->driver, PWC_NAME);
-       strlcpy(cap->card, vdev->name, sizeof(cap->card));
+       strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card));
        usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info));
-       cap->version = PWC_VERSION_CODE;
        cap->capabilities =
                V4L2_CAP_VIDEO_CAPTURE  |
                V4L2_CAP_STREAMING      |
@@ -377,255 +536,396 @@ static int pwc_s_input(struct file *file, void *fh, unsigned int i)
        return i ? -EINVAL : 0;
 }
 
-static int pwc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c)
+static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
-       int i, idx;
-       u32 id;
-
-       id = c->id;
-       if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
-               id &= V4L2_CTRL_ID_MASK;
-               id++;
-               idx = -1;
-               for (i = 0; i < ARRAY_SIZE(pwc_controls); i++) {
-                       if (pwc_controls[i].id < id)
-                               continue;
-                       if (idx >= 0
-                        && pwc_controls[i].id > pwc_controls[idx].id)
-                               continue;
-                       idx = i;
+       struct pwc_device *pdev =
+               container_of(ctrl->handler, struct pwc_device, ctrl_handler);
+       int ret = 0;
+
+       /*
+        * Sometimes it can take quite long for the pwc to complete usb control
+        * transfers, so release the modlock to give streaming by another
+        * process / thread the chance to continue with a dqbuf.
+        */
+       mutex_unlock(&pdev->modlock);
+
+       /*
+        * Take the udev-lock to protect against the disconnect handler
+        * completing and setting dev->udev to NULL underneath us. Other code
+        * does not need to do this since it is protected by the modlock.
+        */
+       mutex_lock(&pdev->udevlock);
+
+       if (!pdev->udev) {
+               ret = -ENODEV;
+               goto leave;
+       }
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               if (pdev->color_bal_valid && time_before(jiffies,
+                               pdev->last_color_bal_update + HZ / 4)) {
+                       pdev->red_balance->val  = pdev->last_red_balance;
+                       pdev->blue_balance->val = pdev->last_blue_balance;
+                       break;
                }
-               if (idx < 0)
-                       return -EINVAL;
-               memcpy(c, &pwc_controls[idx], sizeof pwc_controls[0]);
-               return 0;
+               ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+                                     READ_RED_GAIN_FORMATTER,
+                                     &pdev->red_balance->val);
+               if (ret)
+                       break;
+               ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+                                     READ_BLUE_GAIN_FORMATTER,
+                                     &pdev->blue_balance->val);
+               if (ret)
+                       break;
+               pdev->last_red_balance  = pdev->red_balance->val;
+               pdev->last_blue_balance = pdev->blue_balance->val;
+               pdev->last_color_bal_update = jiffies;
+               pdev->color_bal_valid = true;
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (pdev->gain_valid && time_before(jiffies,
+                               pdev->last_gain_update + HZ / 4)) {
+                       pdev->gain->val = pdev->last_gain;
+                       break;
+               }
+               ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+                                     READ_AGC_FORMATTER, &pdev->gain->val);
+               if (ret)
+                       break;
+               pdev->last_gain = pdev->gain->val;
+               pdev->last_gain_update = jiffies;
+               pdev->gain_valid = true;
+               if (!DEVICE_USE_CODEC3(pdev->type))
+                       break;
+               /* Fall through for CODEC3 where autogain also controls expo */
+       case V4L2_CID_EXPOSURE_AUTO:
+               if (pdev->exposure_valid && time_before(jiffies,
+                               pdev->last_exposure_update + HZ / 4)) {
+                       pdev->exposure->val = pdev->last_exposure;
+                       break;
+               }
+               ret = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
+                                      READ_SHUTTER_FORMATTER,
+                                      &pdev->exposure->val);
+               if (ret)
+                       break;
+               pdev->last_exposure = pdev->exposure->val;
+               pdev->last_exposure_update = jiffies;
+               pdev->exposure_valid = true;
+               break;
+       default:
+               ret = -EINVAL;
        }
-       for (i = 0; i < sizeof(pwc_controls) / sizeof(struct v4l2_queryctrl); i++) {
-               if (pwc_controls[i].id == c->id) {
-                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n");
-                       memcpy(c, &pwc_controls[i], sizeof(struct v4l2_queryctrl));
-                       return 0;
+
+       if (ret)
+               PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret);
+
+leave:
+       mutex_unlock(&pdev->udevlock);
+       mutex_lock(&pdev->modlock);
+       return ret;
+}
+
+static int pwc_set_awb(struct pwc_device *pdev)
+{
+       int ret = 0;
+
+       if (pdev->auto_white_balance->is_new) {
+               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+                                     WB_MODE_FORMATTER,
+                                     pdev->auto_white_balance->val);
+               if (ret)
+                       return ret;
+
+               /* Update val when coming from auto or going to a preset */
+               if (pdev->red_balance->is_volatile ||
+                   pdev->auto_white_balance->val == awb_indoor ||
+                   pdev->auto_white_balance->val == awb_outdoor ||
+                   pdev->auto_white_balance->val == awb_fl) {
+                       if (!pdev->red_balance->is_new)
+                               pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+                                       READ_RED_GAIN_FORMATTER,
+                                       &pdev->red_balance->val);
+                       if (!pdev->blue_balance->is_new)
+                               pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+                                       READ_BLUE_GAIN_FORMATTER,
+                                       &pdev->blue_balance->val);
+               }
+               if (pdev->auto_white_balance->val == awb_auto) {
+                       pdev->red_balance->is_volatile = true;
+                       pdev->blue_balance->is_volatile = true;
+                       pdev->color_bal_valid = false; /* Force cache update */
+               } else {
+                       pdev->red_balance->is_volatile = false;
+                       pdev->blue_balance->is_volatile = false;
                }
        }
-       return -EINVAL;
+
+       if (ret == 0 && pdev->red_balance->is_new) {
+               if (pdev->auto_white_balance->val != awb_manual)
+                       return -EBUSY;
+               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+                                     PRESET_MANUAL_RED_GAIN_FORMATTER,
+                                     pdev->red_balance->val);
+       }
+
+       if (ret == 0 && pdev->blue_balance->is_new) {
+               if (pdev->auto_white_balance->val != awb_manual)
+                       return -EBUSY;
+               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+                                     PRESET_MANUAL_BLUE_GAIN_FORMATTER,
+                                     pdev->blue_balance->val);
+       }
+       return ret;
 }
 
-static int pwc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+/* For CODEC2 models which have separate autogain and auto exposure */
+static int pwc_set_autogain(struct pwc_device *pdev)
 {
-       struct pwc_device *pdev = video_drvdata(file);
-       int ret;
+       int ret = 0;
+
+       if (pdev->autogain->is_new) {
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     AGC_MODE_FORMATTER,
+                                     pdev->autogain->val ? 0 : 0xff);
+               if (ret)
+                       return ret;
+               if (pdev->autogain->val)
+                       pdev->gain_valid = false; /* Force cache update */
+               else if (!pdev->gain->is_new)
+                       pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+                                       READ_AGC_FORMATTER,
+                                       &pdev->gain->val);
+       }
+       if (ret == 0 && pdev->gain->is_new) {
+               if (pdev->autogain->val)
+                       return -EBUSY;
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     PRESET_AGC_FORMATTER,
+                                     pdev->gain->val);
+       }
+       return ret;
+}
 
-       switch (c->id) {
-       case V4L2_CID_BRIGHTNESS:
-               c->value = pwc_get_brightness(pdev);
-               if (c->value < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_CONTRAST:
-               c->value = pwc_get_contrast(pdev);
-               if (c->value < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_SATURATION:
-               ret = pwc_get_saturation(pdev, &c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_GAMMA:
-               c->value = pwc_get_gamma(pdev);
-               if (c->value < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_RED_BALANCE:
-               ret = pwc_get_red_gain(pdev, &c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               c->value >>= 8;
-               return 0;
-       case V4L2_CID_BLUE_BALANCE:
-               ret = pwc_get_blue_gain(pdev, &c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               c->value >>= 8;
-               return 0;
-       case V4L2_CID_AUTO_WHITE_BALANCE:
-               ret = pwc_get_awb(pdev);
-               if (ret < 0)
-                       return -EINVAL;
-               c->value = (ret == PWC_WB_MANUAL) ? 0 : 1;
-               return 0;
-       case V4L2_CID_GAIN:
-               ret = pwc_get_agc(pdev, &c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               c->value >>= 8;
-               return 0;
-       case V4L2_CID_AUTOGAIN:
-               ret = pwc_get_agc(pdev, &c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               c->value = (c->value < 0) ? 1 : 0;
-               return 0;
-       case V4L2_CID_EXPOSURE:
-               ret = pwc_get_shutter_speed(pdev, &c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_PRIVATE_COLOUR_MODE:
-               ret = pwc_get_colour_mode(pdev, &c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_PRIVATE_AUTOCONTOUR:
-               ret = pwc_get_contour(pdev, &c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               c->value = (c->value == -1 ? 1 : 0);
-               return 0;
-       case V4L2_CID_PRIVATE_CONTOUR:
-               ret = pwc_get_contour(pdev, &c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               c->value >>= 10;
-               return 0;
-       case V4L2_CID_PRIVATE_BACKLIGHT:
-               ret = pwc_get_backlight(pdev, &c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_PRIVATE_FLICKERLESS:
-               ret = pwc_get_flicker(pdev, &c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               c->value = (c->value ? 1 : 0);
-               return 0;
-       case V4L2_CID_PRIVATE_NOISE_REDUCTION:
-               ret = pwc_get_dynamic_noise(pdev, &c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
+/* For CODEC2 models which have separate autogain and auto exposure */
+static int pwc_set_exposure_auto(struct pwc_device *pdev)
+{
+       int ret = 0;
+       int is_auto = pdev->exposure_auto->val == V4L2_EXPOSURE_AUTO;
+
+       if (pdev->exposure_auto->is_new) {
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     SHUTTER_MODE_FORMATTER,
+                                     is_auto ? 0 : 0xff);
+               if (ret)
+                       return ret;
+               if (is_auto)
+                       pdev->exposure_valid = false; /* Force cache update */
+               else if (!pdev->exposure->is_new)
+                       pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
+                                        READ_SHUTTER_FORMATTER,
+                                        &pdev->exposure->val);
+       }
+       if (ret == 0 && pdev->exposure->is_new) {
+               if (is_auto)
+                       return -EBUSY;
+               ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
+                                      PRESET_SHUTTER_FORMATTER,
+                                      pdev->exposure->val);
+       }
+       return ret;
+}
 
-       case V4L2_CID_PRIVATE_SAVE_USER:
-       case V4L2_CID_PRIVATE_RESTORE_USER:
-       case V4L2_CID_PRIVATE_RESTORE_FACTORY:
-               return -EINVAL;
+/* For CODEC3 models which have autogain controlling both gain and exposure */
+static int pwc_set_autogain_expo(struct pwc_device *pdev)
+{
+       int ret = 0;
+
+       if (pdev->autogain->is_new) {
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     AGC_MODE_FORMATTER,
+                                     pdev->autogain->val ? 0 : 0xff);
+               if (ret)
+                       return ret;
+               if (pdev->autogain->val) {
+                       pdev->gain_valid     = false; /* Force cache update */
+                       pdev->exposure_valid = false; /* Force cache update */
+               } else {
+                       if (!pdev->gain->is_new)
+                               pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+                                               READ_AGC_FORMATTER,
+                                               &pdev->gain->val);
+                       if (!pdev->exposure->is_new)
+                               pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
+                                                READ_SHUTTER_FORMATTER,
+                                                &pdev->exposure->val);
+               }
        }
-       return -EINVAL;
+       if (ret == 0 && pdev->gain->is_new) {
+               if (pdev->autogain->val)
+                       return -EBUSY;
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     PRESET_AGC_FORMATTER,
+                                     pdev->gain->val);
+       }
+       if (ret == 0 && pdev->exposure->is_new) {
+               if (pdev->autogain->val)
+                       return -EBUSY;
+               ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
+                                      PRESET_SHUTTER_FORMATTER,
+                                      pdev->exposure->val);
+       }
+       return ret;
 }
 
-static int pwc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+static int pwc_set_motor(struct pwc_device *pdev)
 {
-       struct pwc_device *pdev = video_drvdata(file);
        int ret;
+       u8 buf[4];
+
+       buf[0] = 0;
+       if (pdev->motor_pan_reset->is_new)
+               buf[0] |= 0x01;
+       if (pdev->motor_tilt_reset->is_new)
+               buf[0] |= 0x02;
+       if (pdev->motor_pan_reset->is_new || pdev->motor_tilt_reset->is_new) {
+               ret = send_control_msg(pdev, SET_MPT_CTL,
+                                      PT_RESET_CONTROL_FORMATTER, buf, 1);
+               if (ret < 0)
+                       return ret;
+       }
 
-       switch (c->id) {
-       case V4L2_CID_BRIGHTNESS:
-               c->value <<= 9;
-               ret = pwc_set_brightness(pdev, c->value);
+       memset(buf, 0, sizeof(buf));
+       if (pdev->motor_pan->is_new) {
+               buf[0] = pdev->motor_pan->val & 0xFF;
+               buf[1] = (pdev->motor_pan->val >> 8);
+       }
+       if (pdev->motor_tilt->is_new) {
+               buf[2] = pdev->motor_tilt->val & 0xFF;
+               buf[3] = (pdev->motor_tilt->val >> 8);
+       }
+       if (pdev->motor_pan->is_new || pdev->motor_tilt->is_new) {
+               ret = send_control_msg(pdev, SET_MPT_CTL,
+                                      PT_RELATIVE_CONTROL_FORMATTER,
+                                      buf, sizeof(buf));
                if (ret < 0)
-                       return -EINVAL;
-               return 0;
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct pwc_device *pdev =
+               container_of(ctrl->handler, struct pwc_device, ctrl_handler);
+       int ret = 0;
+
+       /* See the comments on locking in pwc_g_volatile_ctrl */
+       mutex_unlock(&pdev->modlock);
+       mutex_lock(&pdev->udevlock);
+
+       if (!pdev->udev) {
+               ret = -ENODEV;
+               goto leave;
+       }
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     BRIGHTNESS_FORMATTER, ctrl->val);
+               break;
        case V4L2_CID_CONTRAST:
-               c->value <<= 10;
-               ret = pwc_set_contrast(pdev, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     CONTRAST_FORMATTER, ctrl->val);
+               break;
        case V4L2_CID_SATURATION:
-               ret = pwc_set_saturation(pdev, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
+               ret = pwc_set_s8_ctrl(pdev, SET_CHROM_CTL,
+                                     pdev->saturation_fmt, ctrl->val);
+               break;
        case V4L2_CID_GAMMA:
-               c->value <<= 11;
-               ret = pwc_set_gamma(pdev, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_RED_BALANCE:
-               c->value <<= 8;
-               ret = pwc_set_red_gain(pdev, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_BLUE_BALANCE:
-               c->value <<= 8;
-               ret = pwc_set_blue_gain(pdev, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     GAMMA_FORMATTER, ctrl->val);
+               break;
        case V4L2_CID_AUTO_WHITE_BALANCE:
-               c->value = (c->value == 0) ? PWC_WB_MANUAL : PWC_WB_AUTO;
-               ret = pwc_set_awb(pdev, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_EXPOSURE:
-               c->value <<= 8;
-               ret = pwc_set_shutter_speed(pdev, c->value ? 0 : 1, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
+               ret = pwc_set_awb(pdev);
+               break;
        case V4L2_CID_AUTOGAIN:
-               /* autogain off means nothing without a gain */
-               if (c->value == 0)
-                       return 0;
-               ret = pwc_set_agc(pdev, c->value, 0);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_GAIN:
-               c->value <<= 8;
-               ret = pwc_set_agc(pdev, 0, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_PRIVATE_SAVE_USER:
-               if (pwc_save_user(pdev))
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_PRIVATE_RESTORE_USER:
-               if (pwc_restore_user(pdev))
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_PRIVATE_RESTORE_FACTORY:
-               if (pwc_restore_factory(pdev))
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_PRIVATE_COLOUR_MODE:
-               ret = pwc_set_colour_mode(pdev, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_PRIVATE_AUTOCONTOUR:
-               c->value = (c->value == 1) ? -1 : 0;
-               ret = pwc_set_contour(pdev, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_PRIVATE_CONTOUR:
-               c->value <<= 10;
-               ret = pwc_set_contour(pdev, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_PRIVATE_BACKLIGHT:
-               ret = pwc_set_backlight(pdev, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-       case V4L2_CID_PRIVATE_FLICKERLESS:
-               ret = pwc_set_flicker(pdev, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-       case V4L2_CID_PRIVATE_NOISE_REDUCTION:
-               ret = pwc_set_dynamic_noise(pdev, c->value);
-               if (ret < 0)
-                       return -EINVAL;
-               return 0;
-
+               if (DEVICE_USE_CODEC2(pdev->type))
+                       ret = pwc_set_autogain(pdev);
+               else if (DEVICE_USE_CODEC3(pdev->type))
+                       ret = pwc_set_autogain_expo(pdev);
+               else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+               if (DEVICE_USE_CODEC2(pdev->type))
+                       ret = pwc_set_exposure_auto(pdev);
+               else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_COLORFX:
+               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+                                     COLOUR_MODE_FORMATTER,
+                                     ctrl->val ? 0 : 0xff);
+               break;
+       case PWC_CID_CUSTOM(autocontour):
+               if (pdev->autocontour->is_new) {
+                       ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                       AUTO_CONTOUR_FORMATTER,
+                                       pdev->autocontour->val ? 0 : 0xff);
+               }
+               if (ret == 0 && pdev->contour->is_new) {
+                       if (pdev->autocontour->val) {
+                               ret = -EBUSY;
+                               break;
+                       }
+                       ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                             PRESET_CONTOUR_FORMATTER,
+                                             pdev->contour->val);
+               }
+               break;
+       case V4L2_CID_BACKLIGHT_COMPENSATION:
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     BACK_LIGHT_COMPENSATION_FORMATTER,
+                                     ctrl->val ? 0 : 0xff);
+               break;
+       case V4L2_CID_BAND_STOP_FILTER:
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     FLICKERLESS_MODE_FORMATTER,
+                                     ctrl->val ? 0 : 0xff);
+               break;
+       case PWC_CID_CUSTOM(noise_reduction):
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     DYNAMIC_NOISE_CONTROL_FORMATTER,
+                                     ctrl->val);
+               break;
+       case PWC_CID_CUSTOM(save_user):
+               ret = pwc_button_ctrl(pdev, SAVE_USER_DEFAULTS_FORMATTER);
+               break;
+       case PWC_CID_CUSTOM(restore_user):
+               ret = pwc_button_ctrl(pdev, RESTORE_USER_DEFAULTS_FORMATTER);
+               break;
+       case PWC_CID_CUSTOM(restore_factory):
+               ret = pwc_button_ctrl(pdev,
+                                     RESTORE_FACTORY_DEFAULTS_FORMATTER);
+               break;
+       case V4L2_CID_PAN_RELATIVE:
+               ret = pwc_set_motor(pdev);
+               break;
+       default:
+               ret = -EINVAL;
        }
-       return -EINVAL;
+
+       if (ret)
+               PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret);
+
+leave:
+       mutex_unlock(&pdev->udevlock);
+       mutex_lock(&pdev->modlock);
+       return ret;
 }
 
 static int pwc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
@@ -667,157 +967,77 @@ static int pwc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *
        return pwc_vidioc_try_fmt(pdev, f);
 }
 
-static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+static int pwc_reqbufs(struct file *file, void *fh,
+                      struct v4l2_requestbuffers *rb)
 {
        struct pwc_device *pdev = video_drvdata(file);
 
-       return pwc_vidioc_set_fmt(pdev, f);
-}
-
-static int pwc_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
-{
-       int nbuffers;
+       if (pdev->capt_file != NULL &&
+           pdev->capt_file != file)
+               return -EBUSY;
 
-       PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n", rb->count);
-       if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       if (rb->memory != V4L2_MEMORY_MMAP)
-               return -EINVAL;
+       pdev->capt_file = file;
 
-       nbuffers = rb->count;
-       if (nbuffers < 2)
-               nbuffers = 2;
-       else if (nbuffers > pwc_mbufs)
-               nbuffers = pwc_mbufs;
-       /* Force to use our # of buffers */
-       rb->count = pwc_mbufs;
-       return 0;
+       return vb2_reqbufs(&pdev->vb_queue, rb);
 }
 
 static int pwc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
 {
        struct pwc_device *pdev = video_drvdata(file);
-       int index;
 
-       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n", buf->index);
-       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n");
-               return -EINVAL;
-       }
-       index = buf->index;
-       if (index < 0 || index >= pwc_mbufs) {
-               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index);
-               return -EINVAL;
-       }
-
-       buf->m.offset = index * pdev->len_per_image;
-       if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
-               buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
-       else
-               buf->bytesused = pdev->view.size;
-       buf->field = V4L2_FIELD_NONE;
-       buf->memory = V4L2_MEMORY_MMAP;
-       /*buf->flags = V4L2_BUF_FLAG_MAPPED;*/
-       buf->length = pdev->len_per_image;
-
-       PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n", buf->index);
-       PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n", buf->m.offset);
-       PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n", buf->bytesused);
-
-       return 0;
+       return vb2_querybuf(&pdev->vb_queue, buf);
 }
 
 static int pwc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
 {
-       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n", buf->index);
-       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       if (buf->memory != V4L2_MEMORY_MMAP)
-               return -EINVAL;
-       if (buf->index >= pwc_mbufs)
-               return -EINVAL;
+       struct pwc_device *pdev = video_drvdata(file);
 
-       buf->flags |= V4L2_BUF_FLAG_QUEUED;
-       buf->flags &= ~V4L2_BUF_FLAG_DONE;
+       if (!pdev->udev)
+               return -ENODEV;
 
-       return 0;
+       if (pdev->capt_file != file)
+               return -EBUSY;
+
+       return vb2_qbuf(&pdev->vb_queue, buf);
 }
 
 static int pwc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
 {
-       DECLARE_WAITQUEUE(wait, current);
        struct pwc_device *pdev = video_drvdata(file);
-       int ret;
 
-       PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n");
+       if (!pdev->udev)
+               return -ENODEV;
 
-       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       add_wait_queue(&pdev->frameq, &wait);
-       while (pdev->full_frames == NULL) {
-               if (pdev->error_status) {
-                       remove_wait_queue(&pdev->frameq, &wait);
-                       set_current_state(TASK_RUNNING);
-                       return -pdev->error_status;
-               }
-
-               if (signal_pending(current)) {
-                       remove_wait_queue(&pdev->frameq, &wait);
-                       set_current_state(TASK_RUNNING);
-                       return -ERESTARTSYS;
-               }
-               mutex_unlock(&pdev->modlock);
-               schedule();
-               set_current_state(TASK_INTERRUPTIBLE);
-               mutex_lock(&pdev->modlock);
-       }
-       remove_wait_queue(&pdev->frameq, &wait);
-       set_current_state(TASK_RUNNING);
-
-       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n");
-       /* Decompress data in pdev->images[pdev->fill_image] */
-       ret = pwc_handle_frame(pdev);
-       if (ret)
-               return -EFAULT;
-       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
-
-       buf->index = pdev->fill_image;
-       if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
-               buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
-       else
-               buf->bytesused = pdev->view.size;
-       buf->flags = V4L2_BUF_FLAG_MAPPED;
-       buf->field = V4L2_FIELD_NONE;
-       do_gettimeofday(&buf->timestamp);
-       buf->sequence = 0;
-       buf->memory = V4L2_MEMORY_MMAP;
-       buf->m.offset = pdev->fill_image * pdev->len_per_image;
-       buf->length = pdev->len_per_image;
-       pwc_next_image(pdev);
-
-       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n", buf->index);
-       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n", buf->length);
-       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n", buf->m.offset);
-       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n", buf->bytesused);
-       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n");
-       return 0;
+       if (pdev->capt_file != file)
+               return -EBUSY;
 
+       return vb2_dqbuf(&pdev->vb_queue, buf, file->f_flags & O_NONBLOCK);
 }
 
 static int pwc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
 {
        struct pwc_device *pdev = video_drvdata(file);
 
-       return pwc_isoc_init(pdev);
+       if (!pdev->udev)
+               return -ENODEV;
+
+       if (pdev->capt_file != file)
+               return -EBUSY;
+
+       return vb2_streamon(&pdev->vb_queue, i);
 }
 
 static int pwc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
 {
        struct pwc_device *pdev = video_drvdata(file);
 
-       pwc_isoc_cleanup(pdev);
-       return 0;
+       if (!pdev->udev)
+               return -ENODEV;
+
+       if (pdev->capt_file != file)
+               return -EBUSY;
+
+       return vb2_streamoff(&pdev->vb_queue, i);
 }
 
 static int pwc_enum_framesizes(struct file *file, void *fh,
@@ -896,9 +1116,6 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = {
        .vidioc_g_fmt_vid_cap               = pwc_g_fmt_vid_cap,
        .vidioc_s_fmt_vid_cap               = pwc_s_fmt_vid_cap,
        .vidioc_try_fmt_vid_cap             = pwc_try_fmt_vid_cap,
-       .vidioc_queryctrl                   = pwc_queryctrl,
-       .vidioc_g_ctrl                      = pwc_g_ctrl,
-       .vidioc_s_ctrl                      = pwc_s_ctrl,
        .vidioc_reqbufs                     = pwc_reqbufs,
        .vidioc_querybuf                    = pwc_querybuf,
        .vidioc_qbuf                        = pwc_qbuf,
index 083f8b1..0e4e2d7 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/usb.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
-#include <linux/version.h>
 #include <linux/mutex.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/videobuf2-vmalloc.h>
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
 #include <linux/input.h>
 #endif
 
-#include "pwc-uncompress.h"
 #include <media/pwc-ioctl.h>
 
 /* Version block */
-#define PWC_MAJOR      10
-#define PWC_MINOR      0
-#define PWC_EXTRAMINOR 12
-#define PWC_VERSION_CODE KERNEL_VERSION(PWC_MAJOR,PWC_MINOR,PWC_EXTRAMINOR)
-#define PWC_VERSION    "10.0.14"
+#define PWC_VERSION    "10.0.15"
 #define PWC_NAME       "pwc"
 #define PFX            PWC_NAME ": "
 
@@ -81,9 +77,9 @@
 #define PWC_DEBUG_LEVEL        (PWC_DEBUG_LEVEL_MODULE)
 
 #define PWC_DEBUG(level, fmt, args...) do {\
-         if ((PWC_DEBUG_LEVEL_ ##level) & pwc_trace) \
-            printk(KERN_DEBUG PFX fmt, ##args); \
-         } while(0)
+       if ((PWC_DEBUG_LEVEL_ ##level) & pwc_trace) \
+               printk(KERN_DEBUG PFX fmt, ##args); \
+       } while (0)
 
 #define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
 #define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
 #define FEATURE_CODEC1                 0x0002
 #define FEATURE_CODEC2                 0x0004
 
-/* Turn certain features on/off */
-#define PWC_INT_PIPE 0
-
 /* Ignore errors in the first N frames, to allow for startup delays */
 #define FRAME_LOWMARK 5
 
 /* Size and number of buffers for the ISO pipe. */
-#define MAX_ISO_BUFS           2
+#define MAX_ISO_BUFS           3
 #define ISO_FRAMES_PER_DESC    10
 #define ISO_MAX_FRAME_SIZE     960
 #define ISO_BUFFER_SIZE        (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
 
-/* Frame buffers: contains compressed or uncompressed video data. */
-#define MAX_FRAMES             5
 /* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
 #define PWC_FRAME_SIZE                 (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
 
-/* Absolute maximum number of buffers available for mmap() */
-#define MAX_IMAGES             10
+/* Absolute minimum and maximum number of buffers available for mmap() */
+#define MIN_FRAMES             2
+#define MAX_FRAMES             16
 
 /* Some macros to quickly find the type of a webcam */
 #define DEVICE_USE_CODEC1(x) ((x)<675)
 #define DEVICE_USE_CODEC3(x) ((x)>=700)
 #define DEVICE_USE_CODEC23(x) ((x)>=675)
 
-/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
-struct pwc_iso_buf
-{
-       void *data;
-       int  length;
-       int  read;
-       struct urb *urb;
-};
+/* from pwc-dec.h */
+#define PWCX_FLAG_PLANAR        0x0001
+
+/* Request types: video */
+#define SET_LUM_CTL                    0x01
+#define GET_LUM_CTL                    0x02
+#define SET_CHROM_CTL                  0x03
+#define GET_CHROM_CTL                  0x04
+#define SET_STATUS_CTL                 0x05
+#define GET_STATUS_CTL                 0x06
+#define SET_EP_STREAM_CTL              0x07
+#define GET_EP_STREAM_CTL              0x08
+#define GET_XX_CTL                     0x09
+#define SET_XX_CTL                     0x0A
+#define GET_XY_CTL                     0x0B
+#define SET_XY_CTL                     0x0C
+#define SET_MPT_CTL                    0x0D
+#define GET_MPT_CTL                    0x0E
+
+/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
+#define AGC_MODE_FORMATTER                     0x2000
+#define PRESET_AGC_FORMATTER                   0x2100
+#define SHUTTER_MODE_FORMATTER                 0x2200
+#define PRESET_SHUTTER_FORMATTER               0x2300
+#define PRESET_CONTOUR_FORMATTER               0x2400
+#define AUTO_CONTOUR_FORMATTER                 0x2500
+#define BACK_LIGHT_COMPENSATION_FORMATTER      0x2600
+#define CONTRAST_FORMATTER                     0x2700
+#define DYNAMIC_NOISE_CONTROL_FORMATTER                0x2800
+#define FLICKERLESS_MODE_FORMATTER             0x2900
+#define AE_CONTROL_SPEED                       0x2A00
+#define BRIGHTNESS_FORMATTER                   0x2B00
+#define GAMMA_FORMATTER                                0x2C00
+
+/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
+#define WB_MODE_FORMATTER                      0x1000
+#define AWB_CONTROL_SPEED_FORMATTER            0x1100
+#define AWB_CONTROL_DELAY_FORMATTER            0x1200
+#define PRESET_MANUAL_RED_GAIN_FORMATTER       0x1300
+#define PRESET_MANUAL_BLUE_GAIN_FORMATTER      0x1400
+#define COLOUR_MODE_FORMATTER                  0x1500
+#define SATURATION_MODE_FORMATTER1             0x1600
+#define SATURATION_MODE_FORMATTER2             0x1700
+
+/* Selectors for the Status controls [GS]ET_STATUS_CTL */
+#define SAVE_USER_DEFAULTS_FORMATTER           0x0200
+#define RESTORE_USER_DEFAULTS_FORMATTER                0x0300
+#define RESTORE_FACTORY_DEFAULTS_FORMATTER     0x0400
+#define READ_AGC_FORMATTER                     0x0500
+#define READ_SHUTTER_FORMATTER                 0x0600
+#define READ_RED_GAIN_FORMATTER                        0x0700
+#define READ_BLUE_GAIN_FORMATTER               0x0800
+
+/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */
+#define PT_RELATIVE_CONTROL_FORMATTER          0x01
+#define PT_RESET_CONTROL_FORMATTER             0x02
+#define PT_STATUS_FORMATTER                    0x03
 
 /* intermediate buffers with raw data from the USB cam */
 struct pwc_frame_buf
 {
-   void *data;
-   volatile int filled;                /* number of bytes filled */
-   struct pwc_frame_buf *next; /* list */
-};
-
-/* additionnal informations used when dealing image between kernel and userland */
-struct pwc_imgbuf
-{
-       unsigned long offset;   /* offset of this buffer in the big array of image_data */
-       int   vma_use_count;    /* count the number of time this memory is mapped */
+       struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
+       struct list_head list;
+       void *data;
+       int filled;             /* number of bytes filled */
 };
 
 struct pwc_device
 {
        struct video_device vdev;
-
-   /* Pointer to our usb_device, may be NULL after unplug */
-   struct usb_device *udev;
-
-   int type;                    /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
-   int release;                        /* release number */
-   int features;               /* feature bits */
-   char serial[30];            /* serial number (string) */
-   int error_status;           /* set when something goes wrong with the cam (unplugged, USB errors) */
-   int usb_init;               /* set when the cam has been initialized over USB */
-
-   /*** Video data ***/
-   int vopen;                  /* flag */
-   int vendpoint;              /* video isoc endpoint */
-   int vcinterface;            /* video control interface */
-   int valternate;             /* alternate interface needed */
-   int vframes, vsize;         /* frames-per-second & size (see PSZ_*) */
-   int pixfmt;                 /* pixelformat: V4L2_PIX_FMT_YUV420 or raw: _PWC1, _PWC2 */
-   int vframe_count;           /* received frames */
-   int vframes_dumped;                 /* counter for dumped frames */
-   int vframes_error;          /* frames received in error */
-   int vmax_packet_size;       /* USB maxpacket size */
-   int vlast_packet_size;      /* for frame synchronisation */
-   int visoc_errors;           /* number of contiguous ISOC errors */
-   int vcompression;           /* desired compression factor */
-   int vbandlength;            /* compressed band length; 0 is uncompressed */
-   char vsnapshot;             /* snapshot mode */
-   char vsync;                 /* used by isoc handler */
-   char vmirror;               /* for ToUCaM series */
-       char unplugged;
-
-   int cmd_len;
-   unsigned char cmd_buf[13];
-
-   /* The image acquisition requires 3 to 4 steps:
-      1. data is gathered in short packets from the USB controller
-      2. data is synchronized and packed into a frame buffer
-      3a. in case data is compressed, decompress it directly into image buffer
-      3b. in case data is uncompressed, copy into image buffer with viewport
-      4. data is transferred to the user process
-
-      Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES....
-      We have in effect a back-to-back-double-buffer system.
-    */
-   /* 1: isoc */
-   struct pwc_iso_buf sbuf[MAX_ISO_BUFS];
-   char iso_init;
-
-   /* 2: frame */
-   struct pwc_frame_buf *fbuf; /* all frames */
-   struct pwc_frame_buf *empty_frames, *empty_frames_tail;     /* all empty frames */
-   struct pwc_frame_buf *full_frames, *full_frames_tail;       /* all filled frames */
-   struct pwc_frame_buf *fill_frame;   /* frame currently being filled */
-   struct pwc_frame_buf *read_frame;   /* frame currently read by user process */
-   int frame_header_size, frame_trailer_size;
-   int frame_size;
-   int frame_total_size; /* including header & trailer */
-   int drop_frames;
-
-   /* 3: decompression */
-   void *decompress_data;              /* private data for decompression engine */
-
-   /* 4: image */
-   /* We have an 'image' and a 'view', where 'image' is the fixed-size image
-      as delivered by the camera, and 'view' is the size requested by the
-      program. The camera image is centered in this viewport, laced with
-      a gray or black border. view_min <= image <= view <= view_max;
-    */
-   int image_mask;                     /* bitmask of supported sizes */
-   struct pwc_coord view_min, view_max;        /* minimum and maximum viewable sizes */
-   struct pwc_coord abs_max;            /* maximum supported size with compression */
-   struct pwc_coord image, view;       /* image and viewport size */
-   struct pwc_coord offset;            /* offset within the viewport */
-
-   void *image_data;                   /* total buffer, which is subdivided into ... */
-   struct pwc_imgbuf images[MAX_IMAGES];/* ...several images... */
-   int fill_image;                     /* ...which are rotated. */
-   int len_per_image;                  /* length per image */
-   int image_read_pos;                 /* In case we read data in pieces, keep track of were we are in the imagebuffer */
-   int image_used[MAX_IMAGES];         /* For MCAPTURE and SYNC */
-
-   struct mutex modlock;               /* to prevent races in video_open(), etc */
-   spinlock_t ptrlock;                 /* for manipulating the buffer pointers */
-
-   /*** motorized pan/tilt feature */
-   struct pwc_mpt_range angle_range;
-   int pan_angle;                      /* in degrees * 100 */
-   int tilt_angle;                     /* absolute angle; 0,0 is home position */
-   int snapshot_button_status;         /* set to 1 when the user push the button, reset to 0 when this value is read */
+       struct mutex modlock;
+
+       /* Pointer to our usb_device, may be NULL after unplug */
+       struct usb_device *udev;
+       /* Protects the setting of udev to NULL by our disconnect handler */
+       struct mutex udevlock;
+
+       /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
+       int type;
+       int release;            /* release number */
+       int features;           /* feature bits */
+       char serial[30];        /* serial number (string) */
+
+       /*** Video data ***/
+       struct file *capt_file; /* file doing video capture */
+       int vendpoint;          /* video isoc endpoint */
+       int vcinterface;        /* video control interface */
+       int valternate;         /* alternate interface needed */
+       int vframes, vsize;     /* frames-per-second & size (see PSZ_*) */
+       int pixfmt;             /* pixelformat: V4L2_PIX_FMT_YUV420 or _PWCX */
+       int vframe_count;       /* received frames */
+       int vmax_packet_size;   /* USB maxpacket size */
+       int vlast_packet_size;  /* for frame synchronisation */
+       int visoc_errors;       /* number of contiguous ISOC errors */
+       int vcompression;       /* desired compression factor */
+       int vbandlength;        /* compressed band length; 0 is uncompressed */
+       char vsnapshot;         /* snapshot mode */
+       char vsync;             /* used by isoc handler */
+       char vmirror;           /* for ToUCaM series */
+       char power_save;        /* Do powersaving for this cam */
+
+       int cmd_len;
+       unsigned char cmd_buf[13];
+
+       struct urb *urbs[MAX_ISO_BUFS];
+       char iso_init;
+
+       /* videobuf2 queue and queued buffers list */
+       struct vb2_queue vb_queue;
+       struct list_head queued_bufs;
+       spinlock_t queued_bufs_lock;
+
+       /*
+        * Frame currently being filled, this only gets touched by the
+        * isoc urb complete handler, and by stream start / stop since
+        * start / stop touch it before / after starting / killing the urbs
+        * no locking is needed around this
+        */
+       struct pwc_frame_buf *fill_buf;
+
+       int frame_header_size, frame_trailer_size;
+       int frame_size;
+       int frame_total_size;   /* including header & trailer */
+       int drop_frames;
+
+       void *decompress_data;  /* private data for decompression engine */
+
+       /*
+        * We have an 'image' and a 'view', where 'image' is the fixed-size img
+        * as delivered by the camera, and 'view' is the size requested by the
+        * program. The camera image is centered in this viewport, laced with
+        * a gray or black border. view_min <= image <= view <= view_max;
+        */
+       int image_mask;                         /* supported sizes */
+       struct pwc_coord view_min, view_max;    /* minimum and maximum view */
+       struct pwc_coord abs_max;               /* maximum supported size */
+       struct pwc_coord image, view;           /* image and viewport size */
+       struct pwc_coord offset;                /* offset of the viewport */
+
+       /*** motorized pan/tilt feature */
+       struct pwc_mpt_range angle_range;
+       int pan_angle;                  /* in degrees * 100 */
+       int tilt_angle;                 /* absolute angle; 0,0 is home */
+
+       /*
+        * Set to 1 when the user push the button, reset to 0
+        * when this value is read from sysfs.
+        */
+       int snapshot_button_status;
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
-   struct input_dev *button_dev;       /* webcam snapshot button input */
-   char button_phys[64];
+       struct input_dev *button_dev;   /* webcam snapshot button input */
+       char button_phys[64];
 #endif
 
-   /*** Misc. data ***/
-   wait_queue_head_t frameq;           /* When waiting for a frame to finish... */
-#if PWC_INT_PIPE
-   void *usb_int_handler;              /* for the interrupt endpoint */
-#endif
+       /* controls */
+       struct v4l2_ctrl_handler        ctrl_handler;
+       u16                             saturation_fmt;
+       struct v4l2_ctrl                *brightness;
+       struct v4l2_ctrl                *contrast;
+       struct v4l2_ctrl                *saturation;
+       struct v4l2_ctrl                *gamma;
+       struct {
+               /* awb / red-blue balance cluster */
+               struct v4l2_ctrl        *auto_white_balance;
+               struct v4l2_ctrl        *red_balance;
+               struct v4l2_ctrl        *blue_balance;
+               /* usb ctrl transfers are slow, so we cache things */
+               int                     color_bal_valid;
+               unsigned long           last_color_bal_update; /* In jiffies */
+               s32                     last_red_balance;
+               s32                     last_blue_balance;
+       };
+       struct {
+               /* autogain / gain cluster */
+               struct v4l2_ctrl        *autogain;
+               struct v4l2_ctrl        *gain;
+               int                     gain_valid;
+               unsigned long           last_gain_update; /* In jiffies */
+               s32                     last_gain;
+       };
+       struct {
+               /* exposure_auto / exposure cluster */
+               struct v4l2_ctrl        *exposure_auto;
+               struct v4l2_ctrl        *exposure;
+               int                     exposure_valid;
+               unsigned long           last_exposure_update; /* In jiffies */
+               s32                     last_exposure;
+       };
+       struct v4l2_ctrl                *colorfx;
+       struct {
+               /* autocontour/contour cluster */
+               struct v4l2_ctrl        *autocontour;
+               struct v4l2_ctrl        *contour;
+       };
+       struct v4l2_ctrl                *backlight;
+       struct v4l2_ctrl                *flicker;
+       struct v4l2_ctrl                *noise_reduction;
+       struct v4l2_ctrl                *save_user;
+       struct v4l2_ctrl                *restore_user;
+       struct v4l2_ctrl                *restore_factory;
+       struct {
+               /* motor control cluster */
+               struct v4l2_ctrl        *motor_pan;
+               struct v4l2_ctrl        *motor_tilt;
+               struct v4l2_ctrl        *motor_pan_reset;
+               struct v4l2_ctrl        *motor_tilt_reset;
+       };
+       /* CODEC3 models have both gain and exposure controlled by autogain */
+       struct v4l2_ctrl                *autogain_expo_cluster[3];
 };
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* Global variables */
 #ifdef CONFIG_USB_PWC_DEBUG
 extern int pwc_trace;
 #endif
-extern int pwc_mbufs;
-
-/** functions in pwc-if.c */
-int pwc_handle_frame(struct pwc_device *pdev);
-void pwc_next_image(struct pwc_device *pdev);
-int pwc_isoc_init(struct pwc_device *pdev);
-void pwc_isoc_cleanup(struct pwc_device *pdev);
 
 /** Functions in pwc-misc.c */
 /* sizes in pixels */
@@ -291,50 +355,25 @@ void pwc_construct(struct pwc_device *pdev);
 /* Request a certain video mode. Returns < 0 if not possible */
 extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
 extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size);
-/* Calculate the number of bytes per image (not frame) */
 extern int pwc_mpt_reset(struct pwc_device *pdev, int flags);
 extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt);
-
-/* Various controls; should be obvious. Value 0..65535, or < 0 on error */
-extern int pwc_get_brightness(struct pwc_device *pdev);
-extern int pwc_set_brightness(struct pwc_device *pdev, int value);
-extern int pwc_get_contrast(struct pwc_device *pdev);
-extern int pwc_set_contrast(struct pwc_device *pdev, int value);
-extern int pwc_get_gamma(struct pwc_device *pdev);
-extern int pwc_set_gamma(struct pwc_device *pdev, int value);
-extern int pwc_get_saturation(struct pwc_device *pdev, int *value);
-extern int pwc_set_saturation(struct pwc_device *pdev, int value);
 extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
 extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
-extern int pwc_restore_user(struct pwc_device *pdev);
-extern int pwc_save_user(struct pwc_device *pdev);
-extern int pwc_restore_factory(struct pwc_device *pdev);
-
-/* exported for use by v4l2 controls */
-extern int pwc_get_red_gain(struct pwc_device *pdev, int *value);
-extern int pwc_set_red_gain(struct pwc_device *pdev, int value);
-extern int pwc_get_blue_gain(struct pwc_device *pdev, int *value);
-extern int pwc_set_blue_gain(struct pwc_device *pdev, int value);
-extern int pwc_get_awb(struct pwc_device *pdev);
-extern int pwc_set_awb(struct pwc_device *pdev, int mode);
-extern int pwc_set_agc(struct pwc_device *pdev, int mode, int value);
-extern int pwc_get_agc(struct pwc_device *pdev, int *value);
-extern int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value);
-extern int pwc_get_shutter_speed(struct pwc_device *pdev, int *value);
-
-extern int pwc_set_colour_mode(struct pwc_device *pdev, int colour);
-extern int pwc_get_colour_mode(struct pwc_device *pdev, int *colour);
-extern int pwc_set_contour(struct pwc_device *pdev, int contour);
-extern int pwc_get_contour(struct pwc_device *pdev, int *contour);
-extern int pwc_set_backlight(struct pwc_device *pdev, int backlight);
-extern int pwc_get_backlight(struct pwc_device *pdev, int *backlight);
-extern int pwc_set_flicker(struct pwc_device *pdev, int flicker);
-extern int pwc_get_flicker(struct pwc_device *pdev, int *flicker);
-extern int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise);
-extern int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise);
+extern int send_control_msg(struct pwc_device *pdev,
+                           u8 request, u16 value, void *buf, int buflen);
+
+/* Control get / set helpers */
+int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data);
+int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data);
+int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data);
+#define pwc_set_s8_ctrl pwc_set_u8_ctrl
+int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *dat);
+int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data);
+int pwc_button_ctrl(struct pwc_device *pdev, u16 value);
+int pwc_init_controls(struct pwc_device *pdev);
 
 /* Power down or up the camera; not supported by all models */
-extern int pwc_camera_power(struct pwc_device *pdev, int power);
+extern void pwc_camera_power(struct pwc_device *pdev, int power);
 
 /* Private ioctl()s; see pwc-ioctl.h */
 extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
@@ -343,12 +382,6 @@ extern const struct v4l2_ioctl_ops pwc_ioctl_ops;
 
 /** pwc-uncompress.c */
 /* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
-extern int pwc_decompress(struct pwc_device *pdev);
-
-#ifdef __cplusplus
-}
-#endif
-
+int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf);
 
 #endif
-/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
index b42bfa5..d07df22 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/mm.h>
 #include <linux/moduleparam.h>
 #include <linux/time.h>
-#include <linux/version.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
@@ -40,7 +39,7 @@
 #include <mach/dma.h>
 #include <mach/camera.h>
 
-#define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5)
+#define PXA_CAM_VERSION "0.0.6"
 #define PXA_CAM_DRV_NAME "pxa27x-camera"
 
 /* Camera Interface */
@@ -247,7 +246,7 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
        if (bytes_per_line < 0)
                return bytes_per_line;
 
-       dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size);
+       dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size);
 
        *size = bytes_per_line * icd->user_height;
 
@@ -262,13 +261,13 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
 static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
 {
        struct soc_camera_device *icd = vq->priv_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
        int i;
 
        BUG_ON(in_interrupt());
 
-       dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                &buf->vb, buf->vb.baddr, buf->vb.bsize);
 
        /*
@@ -429,7 +428,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
                struct videobuf_buffer *vb, enum v4l2_field field)
 {
        struct soc_camera_device *icd = vq->priv_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct pxa_camera_dev *pcdev = ici->priv;
        struct device *dev = pcdev->soc_host.v4l2_dev.dev;
        struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
@@ -636,11 +635,11 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq,
                               struct videobuf_buffer *vb)
 {
        struct soc_camera_device *icd = vq->priv_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct pxa_camera_dev *pcdev = ici->priv;
        struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
 
-       dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d active=%p\n",
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d active=%p\n",
                __func__, vb, vb->baddr, vb->bsize, pcdev->active);
 
        list_add_tail(&vb->queue, &pcdev->capture);
@@ -658,7 +657,7 @@ static void pxa_videobuf_release(struct videobuf_queue *vq,
        struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
 #ifdef DEBUG
        struct soc_camera_device *icd = vq->priv_data;
-       struct device *dev = icd->dev.parent;
+       struct device *dev = icd->parent;
 
        dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                vb, vb->baddr, vb->bsize);
@@ -843,7 +842,7 @@ static struct videobuf_queue_ops pxa_videobuf_ops = {
 static void pxa_camera_init_videobuf(struct videobuf_queue *q,
                              struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct pxa_camera_dev *pcdev = ici->priv;
 
        /*
@@ -972,7 +971,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data)
  */
 static int pxa_camera_add_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct pxa_camera_dev *pcdev = ici->priv;
 
        if (pcdev->icd)
@@ -982,7 +981,7 @@ static int pxa_camera_add_device(struct soc_camera_device *icd)
 
        pcdev->icd = icd;
 
-       dev_info(icd->dev.parent, "PXA Camera driver attached to camera %d\n",
+       dev_info(icd->parent, "PXA Camera driver attached to camera %d\n",
                 icd->devnum);
 
        return 0;
@@ -991,12 +990,12 @@ static int pxa_camera_add_device(struct soc_camera_device *icd)
 /* Called with .video_lock held */
 static void pxa_camera_remove_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct pxa_camera_dev *pcdev = ici->priv;
 
        BUG_ON(icd != pcdev->icd);
 
-       dev_info(icd->dev.parent, "PXA Camera driver detached from camera %d\n",
+       dev_info(icd->parent, "PXA Camera driver detached from camera %d\n",
                 icd->devnum);
 
        /* disable capture, disable interrupts */
@@ -1057,7 +1056,7 @@ static int test_platform_param(struct pxa_camera_dev *pcdev,
 static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
                                  unsigned long flags, __u32 pixfmt)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct pxa_camera_dev *pcdev = ici->priv;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        unsigned long dw, bpp;
@@ -1152,7 +1151,7 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
 
 static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct pxa_camera_dev *pcdev = ici->priv;
        unsigned long bus_flags, camera_flags, common_flags;
        int ret;
@@ -1210,7 +1209,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
 static int pxa_camera_try_bus_param(struct soc_camera_device *icd,
                                    unsigned char buswidth)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct pxa_camera_dev *pcdev = ici->priv;
        unsigned long bus_flags, camera_flags;
        int ret = test_platform_param(pcdev, buswidth, &bus_flags);
@@ -1247,7 +1246,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, unsigned int id
                                  struct soc_camera_format_xlate *xlate)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct device *dev = icd->dev.parent;
+       struct device *dev = icd->parent;
        int formats = 0, ret;
        struct pxa_cam *cam;
        enum v4l2_mbus_pixelcode code;
@@ -1335,9 +1334,9 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
                               struct v4l2_crop *a)
 {
        struct v4l2_rect *rect = &a->c;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct device *dev = icd->parent;
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct pxa_camera_dev *pcdev = ici->priv;
-       struct device *dev = icd->dev.parent;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_sense sense = {
                .master_clock = pcdev->mclk,
@@ -1379,7 +1378,7 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
                        return ret;
 
                if (pxa_camera_check_frame(mf.width, mf.height)) {
-                       dev_warn(icd->dev.parent,
+                       dev_warn(icd->parent,
                                 "Inconsistent state. Use S_FMT to repair\n");
                        return -EINVAL;
                }
@@ -1406,9 +1405,9 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
 static int pxa_camera_set_fmt(struct soc_camera_device *icd,
                              struct v4l2_format *f)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct device *dev = icd->parent;
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct pxa_camera_dev *pcdev = ici->priv;
-       struct device *dev = icd->dev.parent;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        const struct soc_camera_format_xlate *xlate = NULL;
        struct soc_camera_sense sense = {
@@ -1485,7 +1484,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd,
 
        xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
        if (!xlate) {
-               dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt);
+               dev_warn(icd->parent, "Format %x not found\n", pixfmt);
                return -EINVAL;
        }
 
@@ -1499,16 +1498,11 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd,
                              &pix->height, 32, 2048, 0,
                              pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0);
 
-       pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
-                                                   xlate->host_fmt);
-       if (pix->bytesperline < 0)
-               return pix->bytesperline;
-       pix->sizeimage = pix->height * pix->bytesperline;
-
        /* limit to sensor capabilities */
        mf.width        = pix->width;
        mf.height       = pix->height;
-       mf.field        = pix->field;
+       /* Only progressive video supported so far */
+       mf.field        = V4L2_FIELD_NONE;
        mf.colorspace   = pix->colorspace;
        mf.code         = xlate->code;
 
@@ -1527,7 +1521,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd,
                break;
        default:
                /* TODO: support interlaced at least in pass-through mode */
-               dev_err(icd->dev.parent, "Field type %d unsupported.\n",
+               dev_err(icd->parent, "Field type %d unsupported.\n",
                        mf.field);
                return -EINVAL;
        }
@@ -1578,15 +1572,14 @@ static int pxa_camera_querycap(struct soc_camera_host *ici,
 {
        /* cap->name is set by the firendly caller:-> */
        strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card));
-       cap->version = PXA_CAM_VERSION_CODE;
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 
        return 0;
 }
 
-static int pxa_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
+static int pxa_camera_suspend(struct device *dev)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct pxa_camera_dev *pcdev = ici->priv;
        int i = 0, ret = 0;
 
@@ -1596,15 +1589,19 @@ static int pxa_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
        pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR3);
        pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR4);
 
-       if ((pcdev->icd) && (pcdev->icd->ops->suspend))
-               ret = pcdev->icd->ops->suspend(pcdev->icd, state);
+       if (pcdev->icd) {
+               struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->icd);
+               ret = v4l2_subdev_call(sd, core, s_power, 0);
+               if (ret == -ENOIOCTLCMD)
+                       ret = 0;
+       }
 
        return ret;
 }
 
-static int pxa_camera_resume(struct soc_camera_device *icd)
+static int pxa_camera_resume(struct device *dev)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct pxa_camera_dev *pcdev = ici->priv;
        int i = 0, ret = 0;
 
@@ -1618,8 +1615,12 @@ static int pxa_camera_resume(struct soc_camera_device *icd)
        __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR3);
        __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR4);
 
-       if ((pcdev->icd) && (pcdev->icd->ops->resume))
-               ret = pcdev->icd->ops->resume(pcdev->icd);
+       if (pcdev->icd) {
+               struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->icd);
+               ret = v4l2_subdev_call(sd, core, s_power, 1);
+               if (ret == -ENOIOCTLCMD)
+                       ret = 0;
+       }
 
        /* Restart frame capture if active buffer exists */
        if (!ret && pcdev->active)
@@ -1632,8 +1633,6 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
        .owner          = THIS_MODULE,
        .add            = pxa_camera_add_device,
        .remove         = pxa_camera_remove_device,
-       .suspend        = pxa_camera_suspend,
-       .resume         = pxa_camera_resume,
        .set_crop       = pxa_camera_set_crop,
        .get_formats    = pxa_camera_get_formats,
        .put_formats    = pxa_camera_put_formats,
@@ -1818,9 +1817,15 @@ static int __devexit pxa_camera_remove(struct platform_device *pdev)
        return 0;
 }
 
+static struct dev_pm_ops pxa_camera_pm = {
+       .suspend        = pxa_camera_suspend,
+       .resume         = pxa_camera_resume,
+};
+
 static struct platform_driver pxa_camera_driver = {
        .driver         = {
                .name   = PXA_CAM_DRV_NAME,
+               .pm     = &pxa_camera_pm,
        },
        .probe          = pxa_camera_probe,
        .remove         = __devexit_p(pxa_camera_remove),
@@ -1843,4 +1848,5 @@ module_exit(pxa_camera_exit);
 MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
 MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(PXA_CAM_VERSION);
 MODULE_ALIAS("platform:" PXA_CAM_DRV_NAME);
index 57e11b6..847ccc0 100644 (file)
@@ -1364,10 +1364,9 @@ static int rj54n1_video_probe(struct soc_camera_device *icd,
        int data1, data2;
        int ret;
 
-       /* This could be a BUG_ON() or a WARN_ON(), or remove it completely */
-       if (!icd->dev.parent ||
-           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
-               return -ENODEV;
+       /* We must have a parent by now. And it cannot be a wrong one. */
+       BUG_ON(!icd->parent ||
+              to_soc_camera_host(icd->parent)->nr != icd->iface);
 
        /* Read out the chip version register */
        data1 = reg_read(client, RJ54N1_DEV_CODE);
index 5b9dce8..803c9c8 100644 (file)
  * Example maximum bandwidth utilization:
  *
  * -full size, color mode YUYV or YUV422P: 2 channels at once
- *
  * -full or half size Grey scale: all 4 channels at once
- *
  * -half size, color mode YUYV or YUV422P: all 4 channels at once
- *
  * -full size, color mode YUYV or YUV422P 1/2 frame rate: all 4 channels
  *  at once.
- *  (TODO: Incorporate videodev2 frame rate(FR) enumeration,
- *  which is currently experimental.)
  *
  * 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
@@ -47,7 +42,6 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
-#include <linux/version.h>
 #include <linux/mm.h>
 #include <media/videobuf-vmalloc.h>
 #include <media/v4l2-common.h>
 #include <linux/vmalloc.h>
 #include <linux/usb.h>
 
-#define S2255_MAJOR_VERSION    1
-#define S2255_MINOR_VERSION    21
-#define S2255_RELEASE          0
-#define S2255_VERSION          KERNEL_VERSION(S2255_MAJOR_VERSION, \
-                                              S2255_MINOR_VERSION, \
-                                              S2255_RELEASE)
+#define S2255_VERSION          "1.22.1"
 #define FIRMWARE_FILE_NAME "f2255usb.bin"
 
 /* default JPEG quality */
 #define MASK_COLOR       0x000000ff
 #define MASK_JPG_QUALITY 0x0000ff00
 #define MASK_INPUT_TYPE  0x000f0000
-/* frame decimation. Not implemented by V4L yet(experimental in V4L) */
+/* frame decimation. */
 #define FDEC_1         1       /* capture every frame. default */
 #define FDEC_2         2       /* capture every 2nd frame */
 #define FDEC_3         3       /* capture every 3rd frame */
@@ -312,9 +301,9 @@ struct s2255_fh {
 };
 
 /* current cypress EEPROM firmware version */
-#define S2255_CUR_USB_FWVER    ((3 << 8) | 11)
+#define S2255_CUR_USB_FWVER    ((3 << 8) | 12)
 /* current DSP FW version */
-#define S2255_CUR_DSP_FWVER     10102
+#define S2255_CUR_DSP_FWVER     10104
 /* Need DSP version 5+ for video status feature */
 #define S2255_MIN_DSP_STATUS      5
 #define S2255_MIN_DSP_COLORFILTER 8
@@ -502,7 +491,7 @@ static void planar422p_to_yuv_packed(const unsigned char *in,
 
 static void s2255_reset_dsppower(struct s2255_dev *dev)
 {
-       s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b01, NULL, 0, 1);
+       s2255_vendor_req(dev, 0x40, 0x0000, 0x0001, NULL, 0, 1);
        msleep(10);
        s2255_vendor_req(dev, 0x50, 0x0000, 0x0000, NULL, 0, 1);
        msleep(600);
@@ -856,7 +845,6 @@ static int vidioc_querycap(struct file *file, void *priv,
        strlcpy(cap->driver, "s2255", sizeof(cap->driver));
        strlcpy(cap->card, "s2255", sizeof(cap->card));
        usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-       cap->version = S2255_VERSION;
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
        return 0;
 }
@@ -1984,9 +1972,8 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
                          video_device_node_name(&channel->vdev));
 
        }
-       printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %d.%d\n",
-              S2255_MAJOR_VERSION,
-              S2255_MINOR_VERSION);
+       printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %s\n",
+              S2255_VERSION);
        /* if no channels registered, return error and probe will fail*/
        if (atomic_read(&dev->num_channels) == 0) {
                v4l2_device_unregister(&dev->v4l2_dev);
@@ -2302,15 +2289,12 @@ static int s2255_board_init(struct s2255_dev *dev)
        /* query the firmware */
        fw_ver = s2255_get_fx2fw(dev);
 
-       printk(KERN_INFO "2255 usb firmware version %d.%d\n",
+       printk(KERN_INFO "s2255: usb firmware version %d.%d\n",
               (fw_ver >> 8) & 0xff,
               fw_ver & 0xff);
 
        if (fw_ver < S2255_CUR_USB_FWVER)
-               dev_err(&dev->udev->dev,
-                       "usb firmware not up to date %d.%d\n",
-                       (fw_ver >> 8) & 0xff,
-                       fw_ver & 0xff);
+               printk(KERN_INFO "s2255: newer USB firmware available\n");
 
        for (j = 0; j < MAX_CHANNELS; j++) {
                struct s2255_channel *channel = &dev->channel[j];
@@ -2721,3 +2705,4 @@ module_exit(usb_s2255_exit);
 MODULE_DESCRIPTION("Sensoray 2255 Video for Linux driver");
 MODULE_AUTHOR("Dean Anderson (Sensoray Company Inc.)");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(S2255_VERSION);
index 81b4a82..0d730e5 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/bug.h>
@@ -451,7 +450,6 @@ static int fimc_vidioc_querycap_capture(struct file *file, void *priv,
        strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1);
        strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
        cap->bus_info[0] = 0;
-       cap->version = KERNEL_VERSION(1, 0, 0);
        cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
                            V4L2_CAP_VIDEO_CAPTURE_MPLANE;
 
index bdf19ad..aa55066 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/bug.h>
@@ -774,7 +773,6 @@ static int fimc_m2m_querycap(struct file *file, void *priv,
        strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1);
        strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
        cap->bus_info[0] = 0;
-       cap->version = KERNEL_VERSION(1, 0, 0);
        cap->capabilities = V4L2_CAP_STREAMING |
                V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
                V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
@@ -1937,3 +1935,4 @@ module_exit(fimc_exit);
 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
 MODULE_DESCRIPTION("S5P FIMC camera host interface/video postprocessor driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0.1");
diff --git a/drivers/media/video/s5p-mfc/Makefile b/drivers/media/video/s5p-mfc/Makefile
new file mode 100644 (file)
index 0000000..d066340
--- /dev/null
@@ -0,0 +1,5 @@
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
+s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
+s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
+s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
+s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o
diff --git a/drivers/media/video/s5p-mfc/regs-mfc.h b/drivers/media/video/s5p-mfc/regs-mfc.h
new file mode 100644 (file)
index 0000000..053a8a8
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Register definition file for Samsung MFC V5.1 Interface (FIMV) driver
+ *
+ * Kamil Debski, Copyright (c) 2010 Samsung Electronics
+ * http://www.samsung.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 _REGS_FIMV_H
+#define _REGS_FIMV_H
+
+#define S5P_FIMV_REG_SIZE      (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
+#define S5P_FIMV_REG_COUNT     ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
+
+/* Number of bits that the buffer address should be shifted for particular
+ * MFC buffers.  */
+#define S5P_FIMV_START_ADDR            0x0000
+#define S5P_FIMV_END_ADDR              0xe008
+
+#define S5P_FIMV_SW_RESET              0x0000
+#define S5P_FIMV_RISC_HOST_INT         0x0008
+
+/* Command from HOST to RISC */
+#define S5P_FIMV_HOST2RISC_CMD         0x0030
+#define S5P_FIMV_HOST2RISC_ARG1                0x0034
+#define S5P_FIMV_HOST2RISC_ARG2                0x0038
+#define S5P_FIMV_HOST2RISC_ARG3                0x003c
+#define S5P_FIMV_HOST2RISC_ARG4                0x0040
+
+/* Command from RISC to HOST */
+#define S5P_FIMV_RISC2HOST_CMD         0x0044
+#define S5P_FIMV_RISC2HOST_CMD_MASK    0x1FFFF
+#define S5P_FIMV_RISC2HOST_ARG1                0x0048
+#define S5P_FIMV_RISC2HOST_ARG2                0x004c
+#define S5P_FIMV_RISC2HOST_ARG3                0x0050
+#define S5P_FIMV_RISC2HOST_ARG4                0x0054
+
+#define S5P_FIMV_FW_VERSION            0x0058
+#define S5P_FIMV_SYS_MEM_SZ            0x005c
+#define S5P_FIMV_FW_STATUS             0x0080
+
+/* Memory controller register */
+#define S5P_FIMV_MC_DRAMBASE_ADR_A     0x0508
+#define S5P_FIMV_MC_DRAMBASE_ADR_B     0x050c
+#define S5P_FIMV_MC_STATUS             0x0510
+
+/* Common register */
+#define S5P_FIMV_COMMON_BASE_A         0x0600
+#define S5P_FIMV_COMMON_BASE_B         0x0700
+
+/* Decoder */
+#define S5P_FIMV_DEC_CHROMA_ADR                (S5P_FIMV_COMMON_BASE_A)
+#define S5P_FIMV_DEC_LUMA_ADR          (S5P_FIMV_COMMON_BASE_B)
+
+/* H.264 decoding */
+#define S5P_FIMV_H264_VERT_NB_MV_ADR   (S5P_FIMV_COMMON_BASE_A + 0x8c)
+                                       /* vertical neighbor motion vector */
+#define S5P_FIMV_H264_NB_IP_ADR                (S5P_FIMV_COMMON_BASE_A + 0x90)
+                                       /* neighbor pixels for intra pred */
+#define S5P_FIMV_H264_MV_ADR           (S5P_FIMV_COMMON_BASE_B + 0x80)
+                                       /* H264 motion vector */
+
+/* MPEG4 decoding */
+#define S5P_FIMV_MPEG4_NB_DCAC_ADR     (S5P_FIMV_COMMON_BASE_A + 0x8c)
+                                       /* neighbor AC/DC coeff. */
+#define S5P_FIMV_MPEG4_UP_NB_MV_ADR    (S5P_FIMV_COMMON_BASE_A + 0x90)
+                                       /* upper neighbor motion vector */
+#define S5P_FIMV_MPEG4_SA_MV_ADR       (S5P_FIMV_COMMON_BASE_A + 0x94)
+                                       /* subseq. anchor motion vector */
+#define S5P_FIMV_MPEG4_OT_LINE_ADR     (S5P_FIMV_COMMON_BASE_A + 0x98)
+                                       /* overlap transform line */
+#define S5P_FIMV_MPEG4_SP_ADR          (S5P_FIMV_COMMON_BASE_A + 0xa8)
+                                       /* syntax parser */
+
+/* H.263 decoding */
+#define S5P_FIMV_H263_NB_DCAC_ADR      (S5P_FIMV_COMMON_BASE_A + 0x8c)
+#define S5P_FIMV_H263_UP_NB_MV_ADR     (S5P_FIMV_COMMON_BASE_A + 0x90)
+#define S5P_FIMV_H263_SA_MV_ADR                (S5P_FIMV_COMMON_BASE_A + 0x94)
+#define S5P_FIMV_H263_OT_LINE_ADR      (S5P_FIMV_COMMON_BASE_A + 0x98)
+
+/* VC-1 decoding */
+#define S5P_FIMV_VC1_NB_DCAC_ADR       (S5P_FIMV_COMMON_BASE_A + 0x8c)
+#define S5P_FIMV_VC1_UP_NB_MV_ADR      (S5P_FIMV_COMMON_BASE_A + 0x90)
+#define S5P_FIMV_VC1_SA_MV_ADR         (S5P_FIMV_COMMON_BASE_A + 0x94)
+#define S5P_FIMV_VC1_OT_LINE_ADR       (S5P_FIMV_COMMON_BASE_A + 0x98)
+#define S5P_FIMV_VC1_BITPLANE3_ADR     (S5P_FIMV_COMMON_BASE_A + 0x9c)
+                                       /* bitplane3 */
+#define S5P_FIMV_VC1_BITPLANE2_ADR     (S5P_FIMV_COMMON_BASE_A + 0xa0)
+                                       /* bitplane2 */
+#define S5P_FIMV_VC1_BITPLANE1_ADR     (S5P_FIMV_COMMON_BASE_A + 0xa4)
+                                       /* bitplane1 */
+
+/* Encoder */
+#define S5P_FIMV_ENC_REF0_LUMA_ADR     (S5P_FIMV_COMMON_BASE_A + 0x1c)
+#define S5P_FIMV_ENC_REF1_LUMA_ADR     (S5P_FIMV_COMMON_BASE_A + 0x20)
+                                       /* reconstructed luma */
+#define S5P_FIMV_ENC_REF0_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B)
+#define S5P_FIMV_ENC_REF1_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B + 0x04)
+                                       /* reconstructed chroma */
+#define S5P_FIMV_ENC_REF2_LUMA_ADR     (S5P_FIMV_COMMON_BASE_B + 0x10)
+#define S5P_FIMV_ENC_REF2_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B + 0x08)
+#define S5P_FIMV_ENC_REF3_LUMA_ADR     (S5P_FIMV_COMMON_BASE_B + 0x14)
+#define S5P_FIMV_ENC_REF3_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B + 0x0c)
+
+/* H.264 encoding */
+#define S5P_FIMV_H264_UP_MV_ADR                (S5P_FIMV_COMMON_BASE_A)
+                                       /* upper motion vector */
+#define S5P_FIMV_H264_NBOR_INFO_ADR    (S5P_FIMV_COMMON_BASE_A + 0x04)
+                                       /* entropy engine's neighbor info. */
+#define S5P_FIMV_H264_UP_INTRA_MD_ADR  (S5P_FIMV_COMMON_BASE_A + 0x08)
+                                       /* upper intra MD */
+#define S5P_FIMV_H264_COZERO_FLAG_ADR  (S5P_FIMV_COMMON_BASE_A + 0x10)
+                                       /* direct cozero flag */
+#define S5P_FIMV_H264_UP_INTRA_PRED_ADR        (S5P_FIMV_COMMON_BASE_B + 0x40)
+                                       /* upper intra PRED */
+
+/* H.263 encoding */
+#define S5P_FIMV_H263_UP_MV_ADR                (S5P_FIMV_COMMON_BASE_A)
+                                       /* upper motion vector */
+#define S5P_FIMV_H263_ACDC_COEF_ADR    (S5P_FIMV_COMMON_BASE_A + 0x04)
+                                       /* upper Q coeff. */
+
+/* MPEG4 encoding */
+#define S5P_FIMV_MPEG4_UP_MV_ADR       (S5P_FIMV_COMMON_BASE_A)
+                                       /* upper motion vector */
+#define S5P_FIMV_MPEG4_ACDC_COEF_ADR   (S5P_FIMV_COMMON_BASE_A + 0x04)
+                                       /* upper Q coeff. */
+#define S5P_FIMV_MPEG4_COZERO_FLAG_ADR (S5P_FIMV_COMMON_BASE_A + 0x10)
+                                       /* direct cozero flag */
+
+#define S5P_FIMV_ENC_REF_B_LUMA_ADR     0x062c /* ref B Luma addr */
+#define S5P_FIMV_ENC_REF_B_CHROMA_ADR   0x0630 /* ref B Chroma addr */
+
+#define S5P_FIMV_ENC_CUR_LUMA_ADR      0x0718 /* current Luma addr */
+#define S5P_FIMV_ENC_CUR_CHROMA_ADR    0x071C /* current Chroma addr */
+
+/* Codec common register */
+#define S5P_FIMV_ENC_HSIZE_PX          0x0818 /* frame width at encoder */
+#define S5P_FIMV_ENC_VSIZE_PX          0x081c /* frame height at encoder */
+#define S5P_FIMV_ENC_PROFILE           0x0830 /* profile register */
+#define S5P_FIMV_ENC_PROFILE_H264_MAIN                 0
+#define S5P_FIMV_ENC_PROFILE_H264_HIGH                 1
+#define S5P_FIMV_ENC_PROFILE_H264_BASELINE             2
+#define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE              0
+#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE     1
+#define S5P_FIMV_ENC_PIC_STRUCT                0x083c /* picture field/frame flag */
+#define S5P_FIMV_ENC_LF_CTRL           0x0848 /* loop filter control */
+#define S5P_FIMV_ENC_ALPHA_OFF         0x084c /* loop filter alpha offset */
+#define S5P_FIMV_ENC_BETA_OFF          0x0850 /* loop filter beta offset */
+#define S5P_FIMV_MR_BUSIF_CTRL         0x0854 /* hidden, bus interface ctrl */
+#define S5P_FIMV_ENC_PXL_CACHE_CTRL    0x0a00 /* pixel cache control */
+
+/* Channel & stream interface register */
+#define S5P_FIMV_SI_RTN_CHID           0x2000 /* Return CH inst ID register */
+#define S5P_FIMV_SI_CH0_INST_ID                0x2040 /* codec instance ID */
+#define S5P_FIMV_SI_CH1_INST_ID                0x2080 /* codec instance ID */
+/* Decoder */
+#define S5P_FIMV_SI_VRESOL             0x2004 /* vertical res of decoder */
+#define S5P_FIMV_SI_HRESOL             0x2008 /* horizontal res of decoder */
+#define S5P_FIMV_SI_BUF_NUMBER         0x200c /* number of frames in the
+                                                               decoded pic */
+#define S5P_FIMV_SI_DISPLAY_Y_ADR      0x2010 /* luma addr of displayed pic */
+#define S5P_FIMV_SI_DISPLAY_C_ADR      0x2014 /* chroma addrof displayed pic */
+#define S5P_FIMV_SI_CONSUMED_BYTES     0x2018 /* Consumed number of bytes to
+                                                       decode a frame */
+#define S5P_FIMV_SI_DISPLAY_STATUS     0x201c /* status of decoded picture */
+
+#define S5P_FIMV_SI_CH0_SB_ST_ADR      0x2044 /* start addr of stream buf */
+#define S5P_FIMV_SI_CH0_SB_FRM_SIZE    0x2048 /* size of stream buf */
+#define S5P_FIMV_SI_CH0_DESC_ADR       0x204c /* addr of descriptor buf */
+#define S5P_FIMV_SI_CH0_CPB_SIZE       0x2058 /* max size of coded pic. buf */
+#define S5P_FIMV_SI_CH0_DESC_SIZE      0x205c /* max size of descriptor buf */
+
+#define S5P_FIMV_SI_CH1_SB_ST_ADR      0x2084 /* start addr of stream buf */
+#define S5P_FIMV_SI_CH1_SB_FRM_SIZE    0x2088 /* size of stream buf */
+#define S5P_FIMV_SI_CH1_DESC_ADR       0x208c /* addr of descriptor buf */
+#define S5P_FIMV_SI_CH1_CPB_SIZE       0x2098 /* max size of coded pic. buf */
+#define S5P_FIMV_SI_CH1_DESC_SIZE      0x209c /* max size of descriptor buf */
+
+#define S5P_FIMV_CRC_LUMA0             0x2030 /* luma crc data per frame
+                                                               (top field) */
+#define S5P_FIMV_CRC_CHROMA0           0x2034 /* chroma crc data per frame
+                                                               (top field) */
+#define S5P_FIMV_CRC_LUMA1             0x2038 /* luma crc data per bottom
+                                                               field */
+#define S5P_FIMV_CRC_CHROMA1           0x203c /* chroma crc data per bottom
+                                                               field */
+
+/* Display status */
+#define S5P_FIMV_DEC_STATUS_DECODING_ONLY              0
+#define S5P_FIMV_DEC_STATUS_DECODING_DISPLAY           1
+#define S5P_FIMV_DEC_STATUS_DISPLAY_ONLY               2
+#define S5P_FIMV_DEC_STATUS_DECODING_EMPTY             3
+#define S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK       7
+#define S5P_FIMV_DEC_STATUS_PROGRESSIVE                        (0<<3)
+#define S5P_FIMV_DEC_STATUS_INTERLACE                  (1<<3)
+#define S5P_FIMV_DEC_STATUS_INTERLACE_MASK             (1<<3)
+#define S5P_FIMV_DEC_STATUS_CRC_NUMBER_TWO             (0<<4)
+#define S5P_FIMV_DEC_STATUS_CRC_NUMBER_FOUR            (1<<4)
+#define S5P_FIMV_DEC_STATUS_CRC_NUMBER_MASK            (1<<4)
+#define S5P_FIMV_DEC_STATUS_CRC_GENERATED              (1<<5)
+#define S5P_FIMV_DEC_STATUS_CRC_NOT_GENERATED          (0<<5)
+#define S5P_FIMV_DEC_STATUS_CRC_MASK                   (1<<5)
+
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK            (3<<4)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_INC             (1<<4)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC             (2<<4)
+
+/* Decode frame address */
+#define S5P_FIMV_DECODE_Y_ADR                  0x2024
+#define S5P_FIMV_DECODE_C_ADR                  0x2028
+
+/* Decoded frame tpe */
+#define S5P_FIMV_DECODE_FRAME_TYPE             0x2020
+#define S5P_FIMV_DECODE_FRAME_MASK             7
+
+#define S5P_FIMV_DECODE_FRAME_SKIPPED          0
+#define S5P_FIMV_DECODE_FRAME_I_FRAME          1
+#define S5P_FIMV_DECODE_FRAME_P_FRAME          2
+#define S5P_FIMV_DECODE_FRAME_B_FRAME          3
+#define S5P_FIMV_DECODE_FRAME_OTHER_FRAME      4
+
+/* Sizes of buffers required for decoding */
+#define S5P_FIMV_DEC_NB_IP_SIZE                        (32 * 1024)
+#define S5P_FIMV_DEC_VERT_NB_MV_SIZE           (16 * 1024)
+#define S5P_FIMV_DEC_NB_DCAC_SIZE              (16 * 1024)
+#define S5P_FIMV_DEC_UPNB_MV_SIZE              (68 * 1024)
+#define S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE                (136 * 1024)
+#define S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE     (32 * 1024)
+#define S5P_FIMV_DEC_VC1_BITPLANE_SIZE         (2 * 1024)
+#define S5P_FIMV_DEC_STX_PARSER_SIZE           (68 * 1024)
+
+#define S5P_FIMV_DEC_BUF_ALIGN                 (8 * 1024)
+#define S5P_FIMV_ENC_BUF_ALIGN                 (8 * 1024)
+#define S5P_FIMV_NV12M_HALIGN                  16
+#define S5P_FIMV_NV12M_LVALIGN                 16
+#define S5P_FIMV_NV12M_CVALIGN                 8
+#define S5P_FIMV_NV12MT_HALIGN                 128
+#define S5P_FIMV_NV12MT_VALIGN                 32
+#define S5P_FIMV_NV12M_SALIGN                  2048
+#define S5P_FIMV_NV12MT_SALIGN                 8192
+
+/* Sizes of buffers required for encoding */
+#define S5P_FIMV_ENC_UPMV_SIZE         0x10000
+#define S5P_FIMV_ENC_COLFLG_SIZE       0x10000
+#define S5P_FIMV_ENC_INTRAMD_SIZE      0x10000
+#define S5P_FIMV_ENC_INTRAPRED_SIZE    0x4000
+#define S5P_FIMV_ENC_NBORINFO_SIZE     0x10000
+#define S5P_FIMV_ENC_ACDCCOEF_SIZE     0x10000
+
+/* Encoder */
+#define S5P_FIMV_ENC_SI_STRM_SIZE      0x2004 /* stream size */
+#define S5P_FIMV_ENC_SI_PIC_CNT                0x2008 /* picture count */
+#define S5P_FIMV_ENC_SI_WRITE_PTR      0x200c /* write pointer */
+#define S5P_FIMV_ENC_SI_SLICE_TYPE     0x2010 /* slice type(I/P/B/IDR) */
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_NON_CODED   0
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_I           1
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_P           2
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_B           3
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_SKIPPED     4
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_OTHERS      5
+#define S5P_FIMV_ENCODED_Y_ADDR         0x2014 /* the addr of the encoded
+                                                               luma pic */
+#define S5P_FIMV_ENCODED_C_ADDR         0x2018 /* the addr of the encoded
+                                                               chroma pic */
+
+#define S5P_FIMV_ENC_SI_CH0_SB_ADR     0x2044 /* addr of stream buf */
+#define S5P_FIMV_ENC_SI_CH0_SB_SIZE    0x204c /* size of stream buf */
+#define S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR  0x2050 /* current Luma addr */
+#define S5P_FIMV_ENC_SI_CH0_CUR_C_ADR  0x2054 /* current Chroma addr */
+#define S5P_FIMV_ENC_SI_CH0_FRAME_INS  0x2058 /* frame insertion */
+
+#define S5P_FIMV_ENC_SI_CH1_SB_ADR     0x2084 /* addr of stream buf */
+#define S5P_FIMV_ENC_SI_CH1_SB_SIZE    0x208c /* size of stream buf */
+#define S5P_FIMV_ENC_SI_CH1_CUR_Y_ADR  0x2090 /* current Luma addr */
+#define S5P_FIMV_ENC_SI_CH1_CUR_C_ADR  0x2094 /* current Chroma addr */
+#define S5P_FIMV_ENC_SI_CH1_FRAME_INS  0x2098 /* frame insertion */
+
+#define S5P_FIMV_ENC_PIC_TYPE_CTRL     0xc504 /* pic type level control */
+#define S5P_FIMV_ENC_B_RECON_WRITE_ON  0xc508 /* B frame recon write ctrl */
+#define S5P_FIMV_ENC_MSLICE_CTRL       0xc50c /* multi slice control */
+#define S5P_FIMV_ENC_MSLICE_MB         0xc510 /* MB number in the one slice */
+#define S5P_FIMV_ENC_MSLICE_BIT                0xc514 /* bit count for one slice */
+#define S5P_FIMV_ENC_CIR_CTRL          0xc518 /* number of intra refresh MB */
+#define S5P_FIMV_ENC_MAP_FOR_CUR       0xc51c /* linear or tiled mode */
+#define S5P_FIMV_ENC_PADDING_CTRL      0xc520 /* padding control */
+
+#define S5P_FIMV_ENC_RC_CONFIG         0xc5a0 /* RC config */
+#define S5P_FIMV_ENC_RC_BIT_RATE       0xc5a8 /* bit rate */
+#define S5P_FIMV_ENC_RC_QBOUND         0xc5ac /* max/min QP */
+#define S5P_FIMV_ENC_RC_RPARA          0xc5b0 /* rate control reaction coeff */
+#define S5P_FIMV_ENC_RC_MB_CTRL                0xc5b4 /* MB adaptive scaling */
+
+/* Encoder for H264 only */
+#define S5P_FIMV_ENC_H264_ENTROPY_MODE 0xd004 /* CAVLC or CABAC */
+#define S5P_FIMV_ENC_H264_ALPHA_OFF    0xd008 /* loop filter alpha offset */
+#define S5P_FIMV_ENC_H264_BETA_OFF     0xd00c /* loop filter beta offset */
+#define S5P_FIMV_ENC_H264_NUM_OF_REF   0xd010 /* number of reference for P/B */
+#define S5P_FIMV_ENC_H264_TRANS_FLAG   0xd034 /* 8x8 transform flag in PPS &
+                                                               high profile */
+
+#define S5P_FIMV_ENC_RC_FRAME_RATE     0xd0d0 /* frame rate */
+
+/* Encoder for MPEG4 only */
+#define S5P_FIMV_ENC_MPEG4_QUART_PXL   0xe008 /* qpel interpolation ctrl */
+
+/* Additional */
+#define S5P_FIMV_SI_CH0_DPB_CONF_CTRL   0x2068 /* DPB Config Control Register */
+#define S5P_FIMV_SLICE_INT_MASK                1
+#define S5P_FIMV_SLICE_INT_SHIFT       31
+#define S5P_FIMV_DDELAY_ENA_SHIFT      30
+#define S5P_FIMV_DDELAY_VAL_MASK       0xff
+#define S5P_FIMV_DDELAY_VAL_SHIFT      16
+#define S5P_FIMV_DPB_COUNT_MASK                0xffff
+#define S5P_FIMV_DPB_FLUSH_MASK                1
+#define S5P_FIMV_DPB_FLUSH_SHIFT       14
+
+
+#define S5P_FIMV_SI_CH0_RELEASE_BUF     0x2060 /* DPB release buffer register */
+#define S5P_FIMV_SI_CH0_HOST_WR_ADR    0x2064 /* address of shared memory */
+
+/* Codec numbers  */
+#define S5P_FIMV_CODEC_NONE            -1
+
+#define S5P_FIMV_CODEC_H264_DEC                0
+#define S5P_FIMV_CODEC_VC1_DEC         1
+#define S5P_FIMV_CODEC_MPEG4_DEC       2
+#define S5P_FIMV_CODEC_MPEG2_DEC       3
+#define S5P_FIMV_CODEC_H263_DEC                4
+#define S5P_FIMV_CODEC_VC1RCV_DEC      5
+
+#define S5P_FIMV_CODEC_H264_ENC                16
+#define S5P_FIMV_CODEC_MPEG4_ENC       17
+#define S5P_FIMV_CODEC_H263_ENC                18
+
+/* Channel Control Register */
+#define S5P_FIMV_CH_SEQ_HEADER         1
+#define S5P_FIMV_CH_FRAME_START                2
+#define S5P_FIMV_CH_LAST_FRAME         3
+#define S5P_FIMV_CH_INIT_BUFS          4
+#define S5P_FIMV_CH_FRAME_START_REALLOC        5
+#define S5P_FIMV_CH_MASK               7
+#define S5P_FIMV_CH_SHIFT              16
+
+
+/* Host to RISC command */
+#define S5P_FIMV_H2R_CMD_EMPTY         0
+#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE 1
+#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE        2
+#define S5P_FIMV_H2R_CMD_SYS_INIT      3
+#define S5P_FIMV_H2R_CMD_FLUSH         4
+#define S5P_FIMV_H2R_CMD_SLEEP         5
+#define S5P_FIMV_H2R_CMD_WAKEUP                6
+
+#define S5P_FIMV_R2H_CMD_EMPTY                 0
+#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET     1
+#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET    2
+#define S5P_FIMV_R2H_CMD_RSV_RET               3
+#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET          4
+#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET                5
+#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET                6
+#define S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET      7
+#define S5P_FIMV_R2H_CMD_SYS_INIT_RET          8
+#define S5P_FIMV_R2H_CMD_FW_STATUS_RET         9
+#define S5P_FIMV_R2H_CMD_SLEEP_RET             10
+#define S5P_FIMV_R2H_CMD_WAKEUP_RET            11
+#define S5P_FIMV_R2H_CMD_FLUSH_RET             12
+#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET      15
+#define S5P_FIMV_R2H_CMD_EDFU_INIT_RET         16
+#define S5P_FIMV_R2H_CMD_ERR_RET               32
+
+/* Error handling defines */
+#define S5P_FIMV_ERR_WARNINGS_START            145
+#define S5P_FIMV_ERR_DEC_MASK                  0xFFFF
+#define S5P_FIMV_ERR_DEC_SHIFT                 0
+#define S5P_FIMV_ERR_DSPL_MASK                 0xFFFF0000
+#define S5P_FIMV_ERR_DSPL_SHIFT                        16
+
+/* Shared memory registers' offsets */
+
+/* An offset of the start position in the stream when
+ * the start position is not aligned */
+#define S5P_FIMV_SHARED_CROP_INFO_H            0x0020
+#define S5P_FIMV_SHARED_CROP_LEFT_MASK         0xFFFF
+#define S5P_FIMV_SHARED_CROP_LEFT_SHIFT                0
+#define S5P_FIMV_SHARED_CROP_RIGHT_MASK                0xFFFF0000
+#define S5P_FIMV_SHARED_CROP_RIGHT_SHIFT       16
+#define S5P_FIMV_SHARED_CROP_INFO_V            0x0024
+#define S5P_FIMV_SHARED_CROP_TOP_MASK          0xFFFF
+#define S5P_FIMV_SHARED_CROP_TOP_SHIFT         0
+#define S5P_FIMV_SHARED_CROP_BOTTOM_MASK       0xFFFF0000
+#define S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT      16
+#define S5P_FIMV_SHARED_SET_FRAME_TAG          0x0004
+#define S5P_FIMV_SHARED_GET_FRAME_TAG_TOP      0x0008
+#define S5P_FIMV_SHARED_GET_FRAME_TAG_BOT      0x000C
+#define S5P_FIMV_SHARED_START_BYTE_NUM         0x0018
+#define S5P_FIMV_SHARED_RC_VOP_TIMING          0x0030
+#define S5P_FIMV_SHARED_LUMA_DPB_SIZE          0x0064
+#define S5P_FIMV_SHARED_CHROMA_DPB_SIZE                0x0068
+#define S5P_FIMV_SHARED_MV_SIZE                        0x006C
+#define S5P_FIMV_SHARED_PIC_TIME_TOP           0x0010
+#define S5P_FIMV_SHARED_PIC_TIME_BOTTOM                0x0014
+#define S5P_FIMV_SHARED_EXT_ENC_CONTROL                0x0028
+#define S5P_FIMV_SHARED_P_B_FRAME_QP           0x0070
+#define S5P_FIMV_SHARED_ASPECT_RATIO_IDC       0x0074
+#define S5P_FIMV_SHARED_EXTENDED_SAR           0x0078
+#define S5P_FIMV_SHARED_H264_I_PERIOD          0x009C
+#define S5P_FIMV_SHARED_RC_CONTROL_CONFIG      0x00A0
+
+#endif /* _REGS_FIMV_H */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c
new file mode 100644 (file)
index 0000000..7dc7eab
--- /dev/null
@@ -0,0 +1,1274 @@
+/*
+ * Samsung S5P Multi Format Codec v 5.1
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Kamil Debski, <k.debski@samsung.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/videodev2.h>
+#include <linux/workqueue.h>
+#include <media/videobuf2-core.h>
+#include "regs-mfc.h"
+#include "s5p_mfc_ctrl.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_dec.h"
+#include "s5p_mfc_enc.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_shm.h"
+
+#define S5P_MFC_NAME           "s5p-mfc"
+#define S5P_MFC_DEC_NAME       "s5p-mfc-dec"
+#define S5P_MFC_ENC_NAME       "s5p-mfc-enc"
+
+int debug;
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug level - higher value produces more verbose messages");
+
+/* Helper functions for interrupt processing */
+/* Remove from hw execution round robin */
+static void clear_work_bit(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       spin_lock(&dev->condlock);
+       clear_bit(ctx->num, &dev->ctx_work_bits);
+       spin_unlock(&dev->condlock);
+}
+
+/* Wake up context wait_queue */
+static void wake_up_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason,
+                       unsigned int err)
+{
+       ctx->int_cond = 1;
+       ctx->int_type = reason;
+       ctx->int_err = err;
+       wake_up(&ctx->queue);
+}
+
+/* Wake up device wait_queue */
+static void wake_up_dev(struct s5p_mfc_dev *dev, unsigned int reason,
+                       unsigned int err)
+{
+       dev->int_cond = 1;
+       dev->int_type = reason;
+       dev->int_err = err;
+       wake_up(&dev->queue);
+}
+
+void s5p_mfc_watchdog(unsigned long arg)
+{
+       struct s5p_mfc_dev *dev = (struct s5p_mfc_dev *)arg;
+
+       if (test_bit(0, &dev->hw_lock))
+               atomic_inc(&dev->watchdog_cnt);
+       if (atomic_read(&dev->watchdog_cnt) >= MFC_WATCHDOG_CNT) {
+               /* This means that hw is busy and no interrupts were
+                * generated by hw for the Nth time of running this
+                * watchdog timer. This usually means a serious hw
+                * error. Now it is time to kill all instances and
+                * reset the MFC. */
+               mfc_err("Time out during waiting for HW\n");
+               queue_work(dev->watchdog_workqueue, &dev->watchdog_work);
+       }
+       dev->watchdog_timer.expires = jiffies +
+                                       msecs_to_jiffies(MFC_WATCHDOG_INTERVAL);
+       add_timer(&dev->watchdog_timer);
+}
+
+static void s5p_mfc_watchdog_worker(struct work_struct *work)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_ctx *ctx;
+       unsigned long flags;
+       int mutex_locked;
+       int i, ret;
+
+       dev = container_of(work, struct s5p_mfc_dev, watchdog_work);
+
+       mfc_err("Driver timeout error handling\n");
+       /* Lock the mutex that protects open and release.
+        * This is necessary as they may load and unload firmware. */
+       mutex_locked = mutex_trylock(&dev->mfc_mutex);
+       if (!mutex_locked)
+               mfc_err("Error: some instance may be closing/opening\n");
+       spin_lock_irqsave(&dev->irqlock, flags);
+
+       s5p_mfc_clock_off();
+
+       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+               ctx = dev->ctx[i];
+               if (!ctx)
+                       continue;
+               ctx->state = MFCINST_ERROR;
+               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               clear_work_bit(ctx);
+               wake_up_ctx(ctx, S5P_FIMV_R2H_CMD_ERR_RET, 0);
+       }
+       clear_bit(0, &dev->hw_lock);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       /* Double check if there is at least one instance running.
+        * If no instance is in memory than no firmware should be present */
+       if (dev->num_inst > 0) {
+               ret = s5p_mfc_reload_firmware(dev);
+               if (ret) {
+                       mfc_err("Failed to reload FW\n");
+                       goto unlock;
+               }
+               s5p_mfc_clock_on();
+               ret = s5p_mfc_init_hw(dev);
+               if (ret)
+                       mfc_err("Failed to reinit FW\n");
+       }
+unlock:
+       if (mutex_locked)
+               mutex_unlock(&dev->mfc_mutex);
+}
+
+static enum s5p_mfc_node_type s5p_mfc_get_node_type(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       if (!vdev) {
+               mfc_err("failed to get video_device");
+               return MFCNODE_INVALID;
+       }
+       if (vdev->index == 0)
+               return MFCNODE_DECODER;
+       else if (vdev->index == 1)
+               return MFCNODE_ENCODER;
+       return MFCNODE_INVALID;
+}
+
+static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
+{
+       mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
+       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+       mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
+}
+
+static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_buf *dst_buf;
+
+       ctx->state = MFCINST_FINISHED;
+       ctx->sequence++;
+       while (!list_empty(&ctx->dst_queue)) {
+               dst_buf = list_entry(ctx->dst_queue.next,
+                                    struct s5p_mfc_buf, list);
+               mfc_debug(2, "Cleaning up buffer: %d\n",
+                                         dst_buf->b->v4l2_buf.index);
+               vb2_set_plane_payload(dst_buf->b, 0, 0);
+               vb2_set_plane_payload(dst_buf->b, 1, 0);
+               list_del(&dst_buf->list);
+               ctx->dst_queue_cnt--;
+               dst_buf->b->v4l2_buf.sequence = (ctx->sequence++);
+
+               if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
+                       s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
+                       dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
+               else
+                       dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED;
+
+               ctx->dec_dst_flag &= ~(1 << dst_buf->b->v4l2_buf.index);
+               vb2_buffer_done(dst_buf->b, VB2_BUF_STATE_DONE);
+       }
+}
+
+static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf  *dst_buf, *src_buf;
+       size_t dec_y_addr = s5p_mfc_get_dec_y_adr();
+       unsigned int frame_type = s5p_mfc_get_frame_type();
+
+       /* Copy timestamp / timecode from decoded src to dst and set
+          appropraite flags */
+       src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
+               if (vb2_dma_contig_plane_paddr(dst_buf->b, 0) == dec_y_addr) {
+                       memcpy(&dst_buf->b->v4l2_buf.timecode,
+                               &src_buf->b->v4l2_buf.timecode,
+                               sizeof(struct v4l2_timecode));
+                       memcpy(&dst_buf->b->v4l2_buf.timestamp,
+                               &src_buf->b->v4l2_buf.timestamp,
+                               sizeof(struct timeval));
+                       switch (frame_type) {
+                       case S5P_FIMV_DECODE_FRAME_I_FRAME:
+                               dst_buf->b->v4l2_buf.flags |=
+                                               V4L2_BUF_FLAG_KEYFRAME;
+                               break;
+                       case S5P_FIMV_DECODE_FRAME_P_FRAME:
+                               dst_buf->b->v4l2_buf.flags |=
+                                               V4L2_BUF_FLAG_PFRAME;
+                               break;
+                       case S5P_FIMV_DECODE_FRAME_B_FRAME:
+                               dst_buf->b->v4l2_buf.flags |=
+                                               V4L2_BUF_FLAG_BFRAME;
+                               break;
+                       }
+                       break;
+               }
+       }
+}
+
+static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf  *dst_buf;
+       size_t dspl_y_addr = s5p_mfc_get_dspl_y_adr();
+       unsigned int frame_type = s5p_mfc_get_frame_type();
+       unsigned int index;
+
+       /* If frame is same as previous then skip and do not dequeue */
+       if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) {
+               if (!ctx->after_packed_pb)
+                       ctx->sequence++;
+               ctx->after_packed_pb = 0;
+               return;
+       }
+       ctx->sequence++;
+       /* The MFC returns address of the buffer, now we have to
+        * check which videobuf does it correspond to */
+       list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
+               /* Check if this is the buffer we're looking for */
+               if (vb2_dma_contig_plane_paddr(dst_buf->b, 0) == dspl_y_addr) {
+                       list_del(&dst_buf->list);
+                       ctx->dst_queue_cnt--;
+                       dst_buf->b->v4l2_buf.sequence = ctx->sequence;
+                       if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
+                               s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
+                               dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
+                       else
+                               dst_buf->b->v4l2_buf.field =
+                                                       V4L2_FIELD_INTERLACED;
+                       vb2_set_plane_payload(dst_buf->b, 0, ctx->luma_size);
+                       vb2_set_plane_payload(dst_buf->b, 1, ctx->chroma_size);
+                       clear_bit(dst_buf->b->v4l2_buf.index,
+                                                       &ctx->dec_dst_flag);
+
+                       vb2_buffer_done(dst_buf->b,
+                               err ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+
+                       index = dst_buf->b->v4l2_buf.index;
+                       break;
+               }
+       }
+}
+
+/* Handle frame decoding interrupt */
+static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
+                                       unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int dst_frame_status;
+       struct s5p_mfc_buf *src_buf;
+       unsigned long flags;
+       unsigned int res_change;
+
+       unsigned int index;
+
+       dst_frame_status = s5p_mfc_get_dspl_status()
+                               & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
+       res_change = s5p_mfc_get_dspl_status()
+                               & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
+       mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
+       if (ctx->state == MFCINST_RES_CHANGE_INIT)
+               ctx->state = MFCINST_RES_CHANGE_FLUSH;
+       if (res_change) {
+               ctx->state = MFCINST_RES_CHANGE_INIT;
+               s5p_mfc_clear_int_flags(dev);
+               wake_up_ctx(ctx, reason, err);
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                       BUG();
+               s5p_mfc_clock_off();
+               s5p_mfc_try_run(dev);
+               return;
+       }
+       if (ctx->dpb_flush_flag)
+               ctx->dpb_flush_flag = 0;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+       /* All frames remaining in the buffer have been extracted  */
+       if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_EMPTY) {
+               if (ctx->state == MFCINST_RES_CHANGE_FLUSH) {
+                       s5p_mfc_handle_frame_all_extracted(ctx);
+                       ctx->state = MFCINST_RES_CHANGE_END;
+                       goto leave_handle_frame;
+               } else {
+                       s5p_mfc_handle_frame_all_extracted(ctx);
+               }
+       }
+
+       if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY ||
+               dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_ONLY)
+               s5p_mfc_handle_frame_copy_time(ctx);
+
+       /* A frame has been decoded and is in the buffer  */
+       if (dst_frame_status == S5P_FIMV_DEC_STATUS_DISPLAY_ONLY ||
+           dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY) {
+               s5p_mfc_handle_frame_new(ctx, err);
+       } else {
+               mfc_debug(2, "No frame decode\n");
+       }
+       /* Mark source buffer as complete */
+       if (dst_frame_status != S5P_FIMV_DEC_STATUS_DISPLAY_ONLY
+               && !list_empty(&ctx->src_queue)) {
+               src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
+                                                               list);
+               ctx->consumed_stream += s5p_mfc_get_consumed_stream();
+               if (ctx->codec_mode != S5P_FIMV_CODEC_H264_DEC &&
+                       s5p_mfc_get_frame_type() == S5P_FIMV_DECODE_FRAME_P_FRAME
+                                       && ctx->consumed_stream + STUFF_BYTE <
+                                       src_buf->b->v4l2_planes[0].bytesused) {
+                       /* Run MFC again on the same buffer */
+                       mfc_debug(2, "Running again the same buffer\n");
+                       ctx->after_packed_pb = 1;
+               } else {
+                       index = src_buf->b->v4l2_buf.index;
+                       mfc_debug(2, "MFC needs next buffer\n");
+                       ctx->consumed_stream = 0;
+                       list_del(&src_buf->list);
+                       ctx->src_queue_cnt--;
+                       if (s5p_mfc_err_dec(err) > 0)
+                               vb2_buffer_done(src_buf->b, VB2_BUF_STATE_ERROR);
+                       else
+                               vb2_buffer_done(src_buf->b, VB2_BUF_STATE_DONE);
+               }
+       }
+leave_handle_frame:
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING)
+                                   || ctx->dst_queue_cnt < ctx->dpb_count)
+               clear_work_bit(ctx);
+       s5p_mfc_clear_int_flags(dev);
+       wake_up_ctx(ctx, reason, err);
+       if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+               BUG();
+       s5p_mfc_clock_off();
+       s5p_mfc_try_run(dev);
+}
+
+/* Error handling for interrupt */
+static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
+                                unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_dev *dev;
+       unsigned long flags;
+
+       /* If no context is available then all necessary
+        * processing has been done. */
+       if (ctx == 0)
+               return;
+
+       dev = ctx->dev;
+       mfc_err("Interrupt Error: %08x\n", err);
+       s5p_mfc_clear_int_flags(dev);
+       wake_up_dev(dev, reason, err);
+
+       /* Error recovery is dependent on the state of context */
+       switch (ctx->state) {
+       case MFCINST_INIT:
+               /* This error had to happen while acquireing instance */
+       case MFCINST_GOT_INST:
+               /* This error had to happen while parsing the header */
+       case MFCINST_HEAD_PARSED:
+               /* This error had to happen while setting dst buffers */
+       case MFCINST_RETURN_INST:
+               /* This error had to happen while releasing instance */
+               clear_work_bit(ctx);
+               wake_up_ctx(ctx, reason, err);
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                       BUG();
+               s5p_mfc_clock_off();
+               ctx->state = MFCINST_ERROR;
+               break;
+       case MFCINST_FINISHING:
+       case MFCINST_FINISHED:
+       case MFCINST_RUNNING:
+               /* It is higly probable that an error occured
+                * while decoding a frame */
+               clear_work_bit(ctx);
+               ctx->state = MFCINST_ERROR;
+               /* Mark all dst buffers as having an error */
+               spin_lock_irqsave(&dev->irqlock, flags);
+               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               /* Mark all src buffers as having an error */
+               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                       BUG();
+               s5p_mfc_clock_off();
+               break;
+       default:
+               mfc_err("Encountered an error interrupt which had not been handled\n");
+               break;
+       }
+       return;
+}
+
+/* Header parsing interrupt handling */
+static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
+                                unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_dev *dev;
+       unsigned int guard_width, guard_height;
+
+       if (ctx == 0)
+               return;
+       dev = ctx->dev;
+       if (ctx->c_ops->post_seq_start) {
+               if (ctx->c_ops->post_seq_start(ctx))
+                       mfc_err("post_seq_start() failed\n");
+       } else {
+               ctx->img_width = s5p_mfc_get_img_width();
+               ctx->img_height = s5p_mfc_get_img_height();
+
+               ctx->buf_width = ALIGN(ctx->img_width,
+                                               S5P_FIMV_NV12MT_HALIGN);
+               ctx->buf_height = ALIGN(ctx->img_height,
+                                               S5P_FIMV_NV12MT_VALIGN);
+               mfc_debug(2, "SEQ Done: Movie dimensions %dx%d, "
+                       "buffer dimensions: %dx%d\n", ctx->img_width,
+                               ctx->img_height, ctx->buf_width,
+                                               ctx->buf_height);
+               if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
+                       ctx->luma_size = ALIGN(ctx->buf_width *
+                               ctx->buf_height, S5P_FIMV_DEC_BUF_ALIGN);
+                       ctx->chroma_size = ALIGN(ctx->buf_width *
+                                        ALIGN((ctx->img_height >> 1),
+                                              S5P_FIMV_NV12MT_VALIGN),
+                                              S5P_FIMV_DEC_BUF_ALIGN);
+                       ctx->mv_size = ALIGN(ctx->buf_width *
+                                       ALIGN((ctx->buf_height >> 2),
+                                       S5P_FIMV_NV12MT_VALIGN),
+                                       S5P_FIMV_DEC_BUF_ALIGN);
+               } else {
+                       guard_width = ALIGN(ctx->img_width + 24,
+                                       S5P_FIMV_NV12MT_HALIGN);
+                       guard_height = ALIGN(ctx->img_height + 16,
+                                               S5P_FIMV_NV12MT_VALIGN);
+                       ctx->luma_size = ALIGN(guard_width *
+                               guard_height, S5P_FIMV_DEC_BUF_ALIGN);
+                       guard_width = ALIGN(ctx->img_width + 16,
+                                               S5P_FIMV_NV12MT_HALIGN);
+                       guard_height = ALIGN((ctx->img_height >> 1) + 4,
+                                               S5P_FIMV_NV12MT_VALIGN);
+                       ctx->chroma_size = ALIGN(guard_width *
+                               guard_height, S5P_FIMV_DEC_BUF_ALIGN);
+                       ctx->mv_size = 0;
+               }
+               ctx->dpb_count = s5p_mfc_get_dpb_count();
+               if (ctx->img_width == 0 || ctx->img_width == 0)
+                       ctx->state = MFCINST_ERROR;
+               else
+                       ctx->state = MFCINST_HEAD_PARSED;
+       }
+       s5p_mfc_clear_int_flags(dev);
+       clear_work_bit(ctx);
+       if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+               BUG();
+       s5p_mfc_clock_off();
+       s5p_mfc_try_run(dev);
+       wake_up_ctx(ctx, reason, err);
+}
+
+/* Header parsing interrupt handling */
+static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
+                                unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_buf *src_buf;
+       struct s5p_mfc_dev *dev;
+       unsigned long flags;
+
+       if (ctx == 0)
+               return;
+       dev = ctx->dev;
+       s5p_mfc_clear_int_flags(dev);
+       ctx->int_type = reason;
+       ctx->int_err = err;
+       ctx->int_cond = 1;
+       spin_lock(&dev->condlock);
+       clear_bit(ctx->num, &dev->ctx_work_bits);
+       spin_unlock(&dev->condlock);
+       if (err == 0) {
+               ctx->state = MFCINST_RUNNING;
+               if (!ctx->dpb_flush_flag) {
+                       spin_lock_irqsave(&dev->irqlock, flags);
+                       if (!list_empty(&ctx->src_queue)) {
+                               src_buf = list_entry(ctx->src_queue.next,
+                                            struct s5p_mfc_buf, list);
+                               list_del(&src_buf->list);
+                               ctx->src_queue_cnt--;
+                               vb2_buffer_done(src_buf->b,
+                                               VB2_BUF_STATE_DONE);
+                       }
+                       spin_unlock_irqrestore(&dev->irqlock, flags);
+               } else {
+                       ctx->dpb_flush_flag = 0;
+               }
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                       BUG();
+
+               s5p_mfc_clock_off();
+
+               wake_up(&ctx->queue);
+               s5p_mfc_try_run(dev);
+       } else {
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                       BUG();
+
+               s5p_mfc_clock_off();
+
+               wake_up(&ctx->queue);
+       }
+}
+
+/* Interrupt processing */
+static irqreturn_t s5p_mfc_irq(int irq, void *priv)
+{
+       struct s5p_mfc_dev *dev = priv;
+       struct s5p_mfc_ctx *ctx;
+       unsigned int reason;
+       unsigned int err;
+
+       mfc_debug_enter();
+       /* Reset the timeout watchdog */
+       atomic_set(&dev->watchdog_cnt, 0);
+       ctx = dev->ctx[dev->curr_ctx];
+       /* Get the reason of interrupt and the error code */
+       reason = s5p_mfc_get_int_reason();
+       err = s5p_mfc_get_int_err();
+       mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
+       switch (reason) {
+       case S5P_FIMV_R2H_CMD_ERR_RET:
+               /* An error has occured */
+               if (ctx->state == MFCINST_RUNNING &&
+                       s5p_mfc_err_dec(err) >= S5P_FIMV_ERR_WARNINGS_START)
+                       s5p_mfc_handle_frame(ctx, reason, err);
+               else
+                       s5p_mfc_handle_error(ctx, reason, err);
+               clear_bit(0, &dev->enter_suspend);
+               break;
+
+       case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
+       case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
+               if (ctx->c_ops->post_frame_start) {
+                       if (ctx->c_ops->post_frame_start(ctx))
+                               mfc_err("post_frame_start() failed\n");
+                       s5p_mfc_clear_int_flags(dev);
+                       wake_up_ctx(ctx, reason, err);
+                       if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                               BUG();
+                       s5p_mfc_clock_off();
+                       s5p_mfc_try_run(dev);
+               } else {
+                       s5p_mfc_handle_frame(ctx, reason, err);
+               }
+               break;
+
+       case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
+               s5p_mfc_handle_seq_done(ctx, reason, err);
+               break;
+
+       case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
+               ctx->inst_no = s5p_mfc_get_inst_no();
+               ctx->state = MFCINST_GOT_INST;
+               clear_work_bit(ctx);
+               wake_up(&ctx->queue);
+               goto irq_cleanup_hw;
+
+       case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
+               clear_work_bit(ctx);
+               ctx->state = MFCINST_FREE;
+               wake_up(&ctx->queue);
+               goto irq_cleanup_hw;
+
+       case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
+       case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
+       case S5P_FIMV_R2H_CMD_SLEEP_RET:
+       case S5P_FIMV_R2H_CMD_WAKEUP_RET:
+               if (ctx)
+                       clear_work_bit(ctx);
+               s5p_mfc_clear_int_flags(dev);
+               wake_up_dev(dev, reason, err);
+               clear_bit(0, &dev->hw_lock);
+               clear_bit(0, &dev->enter_suspend);
+               break;
+
+       case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
+               s5p_mfc_handle_init_buffers(ctx, reason, err);
+               break;
+       default:
+               mfc_debug(2, "Unknown int reason\n");
+               s5p_mfc_clear_int_flags(dev);
+       }
+       mfc_debug_leave();
+       return IRQ_HANDLED;
+irq_cleanup_hw:
+       s5p_mfc_clear_int_flags(dev);
+       ctx->int_type = reason;
+       ctx->int_err = err;
+       ctx->int_cond = 1;
+       if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+               mfc_err("Failed to unlock hw\n");
+
+       s5p_mfc_clock_off();
+
+       s5p_mfc_try_run(dev);
+       mfc_debug(2, "Exit via irq_cleanup_hw\n");
+       return IRQ_HANDLED;
+}
+
+/* Open an MFC node */
+static int s5p_mfc_open(struct file *file)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_ctx *ctx = NULL;
+       struct vb2_queue *q;
+       unsigned long flags;
+       int ret = 0;
+
+       mfc_debug_enter();
+       dev->num_inst++;        /* It is guarded by mfc_mutex in vfd */
+       /* Allocate memory for context */
+       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       if (!ctx) {
+               mfc_err("Not enough memory\n");
+               ret = -ENOMEM;
+               goto err_alloc;
+       }
+       v4l2_fh_init(&ctx->fh, video_devdata(file));
+       file->private_data = &ctx->fh;
+       v4l2_fh_add(&ctx->fh);
+       ctx->dev = dev;
+       INIT_LIST_HEAD(&ctx->src_queue);
+       INIT_LIST_HEAD(&ctx->dst_queue);
+       ctx->src_queue_cnt = 0;
+       ctx->dst_queue_cnt = 0;
+       /* Get context number */
+       ctx->num = 0;
+       while (dev->ctx[ctx->num]) {
+               ctx->num++;
+               if (ctx->num >= MFC_NUM_CONTEXTS) {
+                       mfc_err("Too many open contexts\n");
+                       ret = -EBUSY;
+                       goto err_no_ctx;
+               }
+       }
+       /* Mark context as idle */
+       spin_lock_irqsave(&dev->condlock, flags);
+       clear_bit(ctx->num, &dev->ctx_work_bits);
+       spin_unlock_irqrestore(&dev->condlock, flags);
+       dev->ctx[ctx->num] = ctx;
+       if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
+               ctx->type = MFCINST_DECODER;
+               ctx->c_ops = get_dec_codec_ops();
+               /* Setup ctrl handler */
+               ret = s5p_mfc_dec_ctrls_setup(ctx);
+               if (ret) {
+                       mfc_err("Failed to setup mfc controls\n");
+                       goto err_ctrls_setup;
+               }
+       } else if (s5p_mfc_get_node_type(file) == MFCNODE_ENCODER) {
+               ctx->type = MFCINST_ENCODER;
+               ctx->c_ops = get_enc_codec_ops();
+               /* only for encoder */
+               INIT_LIST_HEAD(&ctx->ref_queue);
+               ctx->ref_queue_cnt = 0;
+               /* Setup ctrl handler */
+               ret = s5p_mfc_enc_ctrls_setup(ctx);
+               if (ret) {
+                       mfc_err("Failed to setup mfc controls\n");
+                       goto err_ctrls_setup;
+               }
+       } else {
+               ret = -ENOENT;
+               goto err_bad_node;
+       }
+       ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+       ctx->inst_no = -1;
+       /* Load firmware if this is the first instance */
+       if (dev->num_inst == 1) {
+               dev->watchdog_timer.expires = jiffies +
+                                       msecs_to_jiffies(MFC_WATCHDOG_INTERVAL);
+               add_timer(&dev->watchdog_timer);
+               ret = s5p_mfc_power_on();
+               if (ret < 0) {
+                       mfc_err("power on failed\n");
+                       goto err_pwr_enable;
+               }
+               s5p_mfc_clock_on();
+               ret = s5p_mfc_alloc_and_load_firmware(dev);
+               if (ret)
+                       goto err_alloc_fw;
+               /* Init the FW */
+               ret = s5p_mfc_init_hw(dev);
+               if (ret)
+                       goto err_init_hw;
+               s5p_mfc_clock_off();
+       }
+       /* Init videobuf2 queue for CAPTURE */
+       q = &ctx->vq_dst;
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       q->drv_priv = &ctx->fh;
+       if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
+               q->io_modes = VB2_MMAP;
+               q->ops = get_dec_queue_ops();
+       } else if (s5p_mfc_get_node_type(file) == MFCNODE_ENCODER) {
+               q->io_modes = VB2_MMAP | VB2_USERPTR;
+               q->ops = get_enc_queue_ops();
+       } else {
+               ret = -ENOENT;
+               goto err_queue_init;
+       }
+       q->mem_ops = (struct vb2_mem_ops *)&vb2_dma_contig_memops;
+       ret = vb2_queue_init(q);
+       if (ret) {
+               mfc_err("Failed to initialize videobuf2 queue(capture)\n");
+               goto err_queue_init;
+       }
+       /* Init videobuf2 queue for OUTPUT */
+       q = &ctx->vq_src;
+       q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       q->io_modes = VB2_MMAP;
+       q->drv_priv = &ctx->fh;
+       if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
+               q->io_modes = VB2_MMAP;
+               q->ops = get_dec_queue_ops();
+       } else if (s5p_mfc_get_node_type(file) == MFCNODE_ENCODER) {
+               q->io_modes = VB2_MMAP | VB2_USERPTR;
+               q->ops = get_enc_queue_ops();
+       } else {
+               ret = -ENOENT;
+               goto err_queue_init;
+       }
+       q->mem_ops = (struct vb2_mem_ops *)&vb2_dma_contig_memops;
+       ret = vb2_queue_init(q);
+       if (ret) {
+               mfc_err("Failed to initialize videobuf2 queue(output)\n");
+               goto err_queue_init;
+       }
+       init_waitqueue_head(&ctx->queue);
+       mfc_debug_leave();
+       return ret;
+       /* Deinit when failure occured */
+err_queue_init:
+err_init_hw:
+       s5p_mfc_release_firmware(dev);
+err_alloc_fw:
+       dev->ctx[ctx->num] = 0;
+       del_timer_sync(&dev->watchdog_timer);
+       s5p_mfc_clock_off();
+err_pwr_enable:
+       if (dev->num_inst == 1) {
+               if (s5p_mfc_power_off() < 0)
+                       mfc_err("power off failed\n");
+               s5p_mfc_release_firmware(dev);
+       }
+err_ctrls_setup:
+       s5p_mfc_dec_ctrls_delete(ctx);
+err_bad_node:
+err_no_ctx:
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       kfree(ctx);
+err_alloc:
+       dev->num_inst--;
+       mfc_debug_leave();
+       return ret;
+}
+
+/* Release MFC context */
+static int s5p_mfc_release(struct file *file)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+
+       mfc_debug_enter();
+       s5p_mfc_clock_on();
+       vb2_queue_release(&ctx->vq_src);
+       vb2_queue_release(&ctx->vq_dst);
+       /* Mark context as idle */
+       spin_lock_irqsave(&dev->condlock, flags);
+       clear_bit(ctx->num, &dev->ctx_work_bits);
+       spin_unlock_irqrestore(&dev->condlock, flags);
+       /* If instance was initialised then
+        * return instance and free reosurces */
+       if (ctx->inst_no != MFC_NO_INSTANCE_SET) {
+               mfc_debug(2, "Has to free instance\n");
+               ctx->state = MFCINST_RETURN_INST;
+               spin_lock_irqsave(&dev->condlock, flags);
+               set_bit(ctx->num, &dev->ctx_work_bits);
+               spin_unlock_irqrestore(&dev->condlock, flags);
+               s5p_mfc_clean_ctx_int_flags(ctx);
+               s5p_mfc_try_run(dev);
+               /* Wait until instance is returned or timeout occured */
+               if (s5p_mfc_wait_for_done_ctx
+                   (ctx, S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
+                       s5p_mfc_clock_off();
+                       mfc_err("Err returning instance\n");
+               }
+               mfc_debug(2, "After free instance\n");
+               /* Free resources */
+               s5p_mfc_release_codec_buffers(ctx);
+               s5p_mfc_release_instance_buffer(ctx);
+               if (ctx->type == MFCINST_DECODER)
+                       s5p_mfc_release_dec_desc_buffer(ctx);
+
+               ctx->inst_no = MFC_NO_INSTANCE_SET;
+       }
+       /* hardware locking scheme */
+       if (dev->curr_ctx == ctx->num)
+               clear_bit(0, &dev->hw_lock);
+       dev->num_inst--;
+       if (dev->num_inst == 0) {
+               mfc_debug(2, "Last instance - release firmware\n");
+               /* reset <-> F/W release */
+               s5p_mfc_reset(dev);
+               s5p_mfc_release_firmware(dev);
+               del_timer_sync(&dev->watchdog_timer);
+               if (s5p_mfc_power_off() < 0)
+                       mfc_err("Power off failed\n");
+       }
+       mfc_debug(2, "Shutting down clock\n");
+       s5p_mfc_clock_off();
+       dev->ctx[ctx->num] = 0;
+       s5p_mfc_dec_ctrls_delete(ctx);
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       kfree(ctx);
+       mfc_debug_leave();
+       return 0;
+}
+
+/* Poll */
+static unsigned int s5p_mfc_poll(struct file *file,
+                                struct poll_table_struct *wait)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct vb2_queue *src_q, *dst_q;
+       struct vb2_buffer *src_vb = NULL, *dst_vb = NULL;
+       unsigned int rc = 0;
+       unsigned long flags;
+
+       src_q = &ctx->vq_src;
+       dst_q = &ctx->vq_dst;
+       /*
+        * There has to be at least one buffer queued on each queued_list, which
+        * means either in driver already or waiting for driver to claim it
+        * and start processing.
+        */
+       if ((!src_q->streaming || list_empty(&src_q->queued_list))
+               && (!dst_q->streaming || list_empty(&dst_q->queued_list))) {
+               rc = POLLERR;
+               goto end;
+       }
+       mutex_unlock(&dev->mfc_mutex);
+       poll_wait(file, &src_q->done_wq, wait);
+       poll_wait(file, &dst_q->done_wq, wait);
+       mutex_lock(&dev->mfc_mutex);
+       spin_lock_irqsave(&src_q->done_lock, flags);
+       if (!list_empty(&src_q->done_list))
+               src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer,
+                                                               done_entry);
+       if (src_vb && (src_vb->state == VB2_BUF_STATE_DONE
+                               || src_vb->state == VB2_BUF_STATE_ERROR))
+               rc |= POLLOUT | POLLWRNORM;
+       spin_unlock_irqrestore(&src_q->done_lock, flags);
+       spin_lock_irqsave(&dst_q->done_lock, flags);
+       if (!list_empty(&dst_q->done_list))
+               dst_vb = list_first_entry(&dst_q->done_list, struct vb2_buffer,
+                                                               done_entry);
+       if (dst_vb && (dst_vb->state == VB2_BUF_STATE_DONE
+                               || dst_vb->state == VB2_BUF_STATE_ERROR))
+               rc |= POLLIN | POLLRDNORM;
+       spin_unlock_irqrestore(&dst_q->done_lock, flags);
+end:
+       return rc;
+}
+
+/* Mmap */
+static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       int ret;
+       if (offset < DST_QUEUE_OFF_BASE) {
+               mfc_debug(2, "mmaping source\n");
+               ret = vb2_mmap(&ctx->vq_src, vma);
+       } else {                /* capture */
+               mfc_debug(2, "mmaping destination\n");
+               vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT);
+               ret = vb2_mmap(&ctx->vq_dst, vma);
+       }
+       return ret;
+}
+
+/* v4l2 ops */
+static const struct v4l2_file_operations s5p_mfc_fops = {
+       .owner = THIS_MODULE,
+       .open = s5p_mfc_open,
+       .release = s5p_mfc_release,
+       .poll = s5p_mfc_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap = s5p_mfc_mmap,
+};
+
+static int match_child(struct device *dev, void *data)
+{
+       if (!dev_name(dev))
+               return 0;
+       return !strcmp(dev_name(dev), (char *)data);
+}
+
+
+/* MFC probe function */
+static int __devinit s5p_mfc_probe(struct platform_device *pdev)
+{
+       struct s5p_mfc_dev *dev;
+       struct video_device *vfd;
+       struct resource *res;
+       int ret;
+
+       pr_debug("%s++\n", __func__);
+       dev = kzalloc(sizeof *dev, GFP_KERNEL);
+       if (!dev) {
+               dev_err(&pdev->dev, "Not enough memory for MFC device\n");
+               return -ENOMEM;
+       }
+
+       spin_lock_init(&dev->irqlock);
+       spin_lock_init(&dev->condlock);
+       dev->plat_dev = pdev;
+       if (!dev->plat_dev) {
+               dev_err(&pdev->dev, "No platform data specified\n");
+               ret = -ENODEV;
+               goto err_dev;
+       }
+
+       ret = s5p_mfc_init_pm(dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to get mfc clock source\n");
+               goto err_clk;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to get memory region resource\n");
+               ret = -ENOENT;
+               goto err_res;
+       }
+
+       dev->mfc_mem = request_mem_region(res->start, resource_size(res),
+                                         pdev->name);
+       if (dev->mfc_mem == NULL) {
+               dev_err(&pdev->dev, "failed to get memory region\n");
+               ret = -ENOENT;
+               goto err_mem_reg;
+       }
+       dev->regs_base = ioremap(dev->mfc_mem->start, resource_size(dev->mfc_mem));
+       if (dev->regs_base == NULL) {
+               dev_err(&pdev->dev, "failed to ioremap address region\n");
+               ret = -ENOENT;
+               goto err_ioremap;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to get irq resource\n");
+               ret = -ENOENT;
+               goto err_get_res;
+       }
+       dev->irq = res->start;
+       ret = request_irq(dev->irq, s5p_mfc_irq, IRQF_DISABLED, pdev->name,
+                                                                       dev);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to install irq (%d)\n", ret);
+               goto err_req_irq;
+       }
+
+       dev->mem_dev_l = device_find_child(&dev->plat_dev->dev, "s5p-mfc-l",
+                                          match_child);
+       if (!dev->mem_dev_l) {
+               mfc_err("Mem child (L) device get failed\n");
+               ret = -ENODEV;
+               goto err_find_child;
+       }
+       dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r",
+                                          match_child);
+       if (!dev->mem_dev_r) {
+               mfc_err("Mem child (R) device get failed\n");
+               ret = -ENODEV;
+               goto err_find_child;
+       }
+
+       dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l);
+       if (IS_ERR_OR_NULL(dev->alloc_ctx[0])) {
+               ret = PTR_ERR(dev->alloc_ctx[0]);
+               goto err_mem_init_ctx_0;
+       }
+       dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r);
+       if (IS_ERR_OR_NULL(dev->alloc_ctx[1])) {
+               ret = PTR_ERR(dev->alloc_ctx[1]);
+               goto err_mem_init_ctx_1;
+       }
+
+       mutex_init(&dev->mfc_mutex);
+
+       ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+       if (ret)
+               goto err_v4l2_dev_reg;
+       init_waitqueue_head(&dev->queue);
+
+       /* decoder */
+       vfd = video_device_alloc();
+       if (!vfd) {
+               v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
+               ret = -ENOMEM;
+               goto err_dec_alloc;
+       }
+       vfd->fops       = &s5p_mfc_fops,
+       vfd->ioctl_ops  = get_dec_v4l2_ioctl_ops();
+       vfd->release    = video_device_release,
+       vfd->lock       = &dev->mfc_mutex;
+       vfd->v4l2_dev   = &dev->v4l2_dev;
+       snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME);
+       dev->vfd_dec    = vfd;
+       ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+               video_device_release(vfd);
+               goto err_dec_reg;
+       }
+       v4l2_info(&dev->v4l2_dev,
+                 "decoder registered as /dev/video%d\n", vfd->num);
+       video_set_drvdata(vfd, dev);
+
+       /* encoder */
+       vfd = video_device_alloc();
+       if (!vfd) {
+               v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
+               ret = -ENOMEM;
+               goto err_enc_alloc;
+       }
+       vfd->fops       = &s5p_mfc_fops,
+       vfd->ioctl_ops  = get_enc_v4l2_ioctl_ops();
+       vfd->release    = video_device_release,
+       vfd->lock       = &dev->mfc_mutex;
+       vfd->v4l2_dev   = &dev->v4l2_dev;
+       snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
+       dev->vfd_enc    = vfd;
+       ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+               video_device_release(vfd);
+               goto err_enc_reg;
+       }
+       v4l2_info(&dev->v4l2_dev,
+                 "encoder registered as /dev/video%d\n", vfd->num);
+       video_set_drvdata(vfd, dev);
+       platform_set_drvdata(pdev, dev);
+
+       dev->hw_lock = 0;
+       dev->watchdog_workqueue = create_singlethread_workqueue(S5P_MFC_NAME);
+       INIT_WORK(&dev->watchdog_work, s5p_mfc_watchdog_worker);
+       atomic_set(&dev->watchdog_cnt, 0);
+       init_timer(&dev->watchdog_timer);
+       dev->watchdog_timer.data = (unsigned long)dev;
+       dev->watchdog_timer.function = s5p_mfc_watchdog;
+
+       pr_debug("%s--\n", __func__);
+       return 0;
+
+/* Deinit MFC if probe had failed */
+err_enc_reg:
+       video_device_release(dev->vfd_enc);
+err_enc_alloc:
+       video_unregister_device(dev->vfd_dec);
+err_dec_reg:
+       video_device_release(dev->vfd_dec);
+err_dec_alloc:
+       v4l2_device_unregister(&dev->v4l2_dev);
+err_v4l2_dev_reg:
+       vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
+err_mem_init_ctx_1:
+       vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
+err_mem_init_ctx_0:
+err_find_child:
+       free_irq(dev->irq, dev);
+err_req_irq:
+err_get_res:
+       iounmap(dev->regs_base);
+       dev->regs_base = NULL;
+err_ioremap:
+       release_resource(dev->mfc_mem);
+       kfree(dev->mfc_mem);
+err_mem_reg:
+err_res:
+       s5p_mfc_final_pm(dev);
+err_clk:
+err_dev:
+       kfree(dev);
+       pr_debug("%s-- with error\n", __func__);
+       return ret;
+
+}
+
+/* Remove the driver */
+static int __devexit s5p_mfc_remove(struct platform_device *pdev)
+{
+       struct s5p_mfc_dev *dev = platform_get_drvdata(pdev);
+
+       v4l2_info(&dev->v4l2_dev, "Removing %s\n", pdev->name);
+
+       del_timer_sync(&dev->watchdog_timer);
+       flush_workqueue(dev->watchdog_workqueue);
+       destroy_workqueue(dev->watchdog_workqueue);
+
+       video_unregister_device(dev->vfd_enc);
+       video_unregister_device(dev->vfd_dec);
+       v4l2_device_unregister(&dev->v4l2_dev);
+       vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
+       vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
+
+       free_irq(dev->irq, dev);
+       iounmap(dev->regs_base);
+       if (dev->mfc_mem) {
+               release_resource(dev->mfc_mem);
+               kfree(dev->mfc_mem);
+               dev->mfc_mem = NULL;
+       }
+       s5p_mfc_final_pm(dev);
+       kfree(dev);
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int s5p_mfc_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct s5p_mfc_dev *m_dev = platform_get_drvdata(pdev);
+       int ret;
+
+       if (m_dev->num_inst == 0)
+               return 0;
+       return s5p_mfc_sleep(m_dev);
+       if (test_and_set_bit(0, &m_dev->enter_suspend) != 0) {
+               mfc_err("Error: going to suspend for a second time\n");
+               return -EIO;
+       }
+
+       /* Check if we're processing then wait if it necessary. */
+       while (test_and_set_bit(0, &m_dev->hw_lock) != 0) {
+               /* Try and lock the HW */
+               /* Wait on the interrupt waitqueue */
+               ret = wait_event_interruptible_timeout(m_dev->queue,
+                       m_dev->int_cond || m_dev->ctx[m_dev->curr_ctx]->int_cond,
+                       msecs_to_jiffies(MFC_INT_TIMEOUT));
+
+               if (ret == 0) {
+                       mfc_err("Waiting for hardware to finish timed out\n");
+                       return -EIO;
+               }
+       }
+       return 0;
+}
+
+static int s5p_mfc_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct s5p_mfc_dev *m_dev = platform_get_drvdata(pdev);
+
+       if (m_dev->num_inst == 0)
+               return 0;
+       return s5p_mfc_wakeup(m_dev);
+}
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int s5p_mfc_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct s5p_mfc_dev *m_dev = platform_get_drvdata(pdev);
+
+       atomic_set(&m_dev->pm.power, 0);
+       return 0;
+}
+
+static int s5p_mfc_runtime_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct s5p_mfc_dev *m_dev = platform_get_drvdata(pdev);
+       int pre_power;
+
+       if (!m_dev->alloc_ctx)
+               return 0;
+       pre_power = atomic_read(&m_dev->pm.power);
+       atomic_set(&m_dev->pm.power, 1);
+       return 0;
+}
+#endif
+
+/* Power management */
+static const struct dev_pm_ops s5p_mfc_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(s5p_mfc_suspend, s5p_mfc_resume)
+       SET_RUNTIME_PM_OPS(s5p_mfc_runtime_suspend, s5p_mfc_runtime_resume,
+                          NULL)
+};
+
+static struct platform_driver s5p_mfc_pdrv = {
+       .probe  = s5p_mfc_probe,
+       .remove = __devexit_p(s5p_mfc_remove),
+       .driver = {
+               .name   = S5P_MFC_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &s5p_mfc_pm_ops
+       },
+};
+
+static char banner[] __initdata =
+                       "S5P MFC V4L2 Driver, (C) 2011 Samsung Electronics\n";
+
+static int __init s5p_mfc_init(void)
+{
+       int ret;
+
+       pr_info("%s", banner);
+       ret = platform_driver_register(&s5p_mfc_pdrv);
+       if (ret)
+               pr_err("Platform device registration failed.\n");
+       return ret;
+}
+
+static void __devexit s5p_mfc_exit(void)
+{
+       platform_driver_unregister(&s5p_mfc_pdrv);
+}
+
+module_init(s5p_mfc_init);
+module_exit(s5p_mfc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
+MODULE_DESCRIPTION("Samsung S5P Multi Format Codec V4L2 driver");
+
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
new file mode 100644 (file)
index 0000000..f0665ed
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+
+#include "regs-mfc.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+
+/* This function is used to send a command to the MFC */
+static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
+                                               struct s5p_mfc_cmd_args *args)
+{
+       int cur_cmd;
+       unsigned long timeout;
+
+       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+       /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
+       do {
+               if (time_after(jiffies, timeout)) {
+                       mfc_err("Timeout while waiting for hardware\n");
+                       return -EIO;
+               }
+               cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
+       } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
+       mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
+       mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
+       mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
+       mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
+       /* Issue the command */
+       mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
+       return 0;
+}
+
+/* Initialize the MFC */
+int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       h2r_args.arg[0] = dev->fw_size;
+       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
+}
+
+/* Suspend the MFC hardware */
+int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
+}
+
+/* Wake up the MFC hardware */
+int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
+}
+
+
+int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int ret;
+
+       /* Preparing decoding - getting instance number */
+       mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
+       dev->curr_ctx = ctx->num;
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       h2r_args.arg[0] = ctx->codec_mode;
+       h2r_args.arg[1] = 0; /* no crc & no pixelcache */
+       h2r_args.arg[2] = ctx->ctx_ofs;
+       h2r_args.arg[3] = ctx->ctx_size;
+       ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
+                                                               &h2r_args);
+       if (ret) {
+               mfc_err("Failed to create a new instance\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int ret;
+
+       if (ctx->state == MFCINST_FREE) {
+               mfc_err("Instance already returned\n");
+               ctx->state = MFCINST_ERROR;
+               return -EINVAL;
+       }
+       /* Closing decoding instance  */
+       mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
+       dev->curr_ctx = ctx->num;
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       h2r_args.arg[0] = ctx->inst_no;
+       ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
+                                                               &h2r_args);
+       if (ret) {
+               mfc_err("Failed to return an instance\n");
+               ctx->state = MFCINST_ERROR;
+               return -EINVAL;
+       }
+       return 0;
+}
+
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
new file mode 100644 (file)
index 0000000..5ceebfe
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+
+#ifndef S5P_MFC_CMD_H_
+#define S5P_MFC_CMD_H_
+
+#include "s5p_mfc_common.h"
+
+#define MAX_H2R_ARG    4
+
+struct s5p_mfc_cmd_args {
+       unsigned int    arg[MAX_H2R_ARG];
+};
+
+int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev);
+int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev);
+int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev);
+int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx);
+
+#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_common.h b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
new file mode 100644 (file)
index 0000000..91146fa
--- /dev/null
@@ -0,0 +1,572 @@
+/*
+ * Samsung S5P Multi Format Codec v 5.0
+ *
+ * This file contains definitions of enums and structs used by the codec
+ * driver.
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Kamil Debski, <k.debski@samsung.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
+ */
+
+#ifndef S5P_MFC_COMMON_H_
+#define S5P_MFC_COMMON_H_
+
+#include "regs-mfc.h"
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+
+/* Definitions related to MFC memory */
+
+/* Offset base used to differentiate between CAPTURE and OUTPUT
+*  while mmaping */
+#define DST_QUEUE_OFF_BASE      (TASK_SIZE / 2)
+
+/* Offset used by the hardware to store addresses */
+#define MFC_OFFSET_SHIFT       11
+
+#define FIRMWARE_ALIGN         0x20000         /* 128KB */
+#define MFC_H264_CTX_BUF_SIZE  0x96000         /* 600KB per H264 instance */
+#define MFC_CTX_BUF_SIZE       0x2800          /* 10KB per instance */
+#define DESC_BUF_SIZE          0x20000         /* 128KB for DESC buffer */
+#define SHARED_BUF_SIZE                0x2000          /* 8KB for shared buffer */
+
+#define DEF_CPB_SIZE           0x40000         /* 512KB */
+
+#define MFC_BANK1_ALLOC_CTX    0
+#define MFC_BANK2_ALLOC_CTX    1
+
+#define MFC_BANK1_ALIGN_ORDER  13
+#define MFC_BANK2_ALIGN_ORDER  13
+#define MFC_BASE_ALIGN_ORDER   17
+
+#include <media/videobuf2-dma-contig.h>
+
+static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
+{
+       /* Same functionality as the vb2_dma_contig_plane_paddr */
+       dma_addr_t *paddr = vb2_dma_contig_memops.cookie(b);
+
+       return *paddr;
+}
+
+/* MFC definitions */
+#define MFC_MAX_EXTRA_DPB       5
+#define MFC_MAX_BUFFERS                32
+#define MFC_NUM_CONTEXTS       4
+/* Interrupt timeout */
+#define MFC_INT_TIMEOUT                2000
+/* Busy wait timeout */
+#define MFC_BW_TIMEOUT         500
+/* Watchdog interval */
+#define MFC_WATCHDOG_INTERVAL   1000
+/* After how many executions watchdog should assume lock up */
+#define MFC_WATCHDOG_CNT        10
+#define MFC_NO_INSTANCE_SET    -1
+#define MFC_ENC_CAP_PLANE_COUNT        1
+#define MFC_ENC_OUT_PLANE_COUNT        2
+#define STUFF_BYTE             4
+#define MFC_MAX_CTRLS          64
+
+#define mfc_read(dev, offset)          readl(dev->regs_base + (offset))
+#define mfc_write(dev, data, offset)   writel((data), dev->regs_base + \
+                                                               (offset))
+
+/**
+ * enum s5p_mfc_fmt_type - type of the pixelformat
+ */
+enum s5p_mfc_fmt_type {
+       MFC_FMT_DEC,
+       MFC_FMT_ENC,
+       MFC_FMT_RAW,
+};
+
+/**
+ * enum s5p_mfc_node_type - The type of an MFC device node.
+ */
+enum s5p_mfc_node_type {
+       MFCNODE_INVALID = -1,
+       MFCNODE_DECODER = 0,
+       MFCNODE_ENCODER = 1,
+};
+
+/**
+ * enum s5p_mfc_inst_type - The type of an MFC instance.
+ */
+enum s5p_mfc_inst_type {
+       MFCINST_INVALID,
+       MFCINST_DECODER,
+       MFCINST_ENCODER,
+};
+
+/**
+ * enum s5p_mfc_inst_state - The state of an MFC instance.
+ */
+enum s5p_mfc_inst_state {
+       MFCINST_FREE = 0,
+       MFCINST_INIT = 100,
+       MFCINST_GOT_INST,
+       MFCINST_HEAD_PARSED,
+       MFCINST_BUFS_SET,
+       MFCINST_RUNNING,
+       MFCINST_FINISHING,
+       MFCINST_FINISHED,
+       MFCINST_RETURN_INST,
+       MFCINST_ERROR,
+       MFCINST_ABORT,
+       MFCINST_RES_CHANGE_INIT,
+       MFCINST_RES_CHANGE_FLUSH,
+       MFCINST_RES_CHANGE_END,
+};
+
+/**
+ * enum s5p_mfc_queue_state - The state of buffer queue.
+ */
+enum s5p_mfc_queue_state {
+       QUEUE_FREE,
+       QUEUE_BUFS_REQUESTED,
+       QUEUE_BUFS_QUERIED,
+       QUEUE_BUFS_MMAPED,
+};
+
+/**
+ * enum s5p_mfc_decode_arg - type of frame decoding
+ */
+enum s5p_mfc_decode_arg {
+       MFC_DEC_FRAME,
+       MFC_DEC_LAST_FRAME,
+       MFC_DEC_RES_CHANGE,
+};
+
+struct s5p_mfc_ctx;
+
+/**
+ * struct s5p_mfc_buf - MFC buffer
+ */
+struct s5p_mfc_buf {
+       struct list_head list;
+       struct vb2_buffer *b;
+       union {
+               struct {
+                       size_t luma;
+                       size_t chroma;
+               } raw;
+               size_t stream;
+       } cookie;
+       int used;
+};
+
+/**
+ * struct s5p_mfc_pm - power management data structure
+ */
+struct s5p_mfc_pm {
+       struct clk      *clock;
+       struct clk      *clock_gate;
+       atomic_t        power;
+       struct device   *device;
+};
+
+/**
+ * struct s5p_mfc_dev - The struct containing driver internal parameters.
+ *
+ * @v4l2_dev:          v4l2_device
+ * @vfd_dec:           video device for decoding
+ * @vfd_enc:           video device for encoding
+ * @plat_dev:          platform device
+ * @mem_dev_l:         child device of the left memory bank (0)
+ * @mem_dev_r:         child device of the right memory bank (1)
+ * @regs_base:         base address of the MFC hw registers
+ * @irq:               irq resource
+ * @mfc_mem:           MFC registers memory resource
+ * @dec_ctrl_handler:  control framework handler for decoding
+ * @enc_ctrl_handler:  control framework handler for encoding
+ * @pm:                        power management control
+ * @num_inst:          couter of active MFC instances
+ * @irqlock:           lock for operations on videobuf2 queues
+ * @condlock:          lock for changing/checking if a context is ready to be
+ *                     processed
+ * @mfc_mutex:         lock for video_device
+ * @int_cond:          variable used by the waitqueue
+ * @int_type:          type of last interrupt
+ * @int_err:           error number for last interrupt
+ * @queue:             waitqueue for waiting for completion of device commands
+ * @fw_size:           size of firmware
+ * @bank1:             address of the beggining of bank 1 memory
+ * @bank2:             address of the beggining of bank 2 memory
+ * @hw_lock:           used for hardware locking
+ * @ctx:               array of driver contexts
+ * @curr_ctx:          number of the currently running context
+ * @ctx_work_bits:     used to mark which contexts are waiting for hardware
+ * @watchdog_cnt:      counter for the watchdog
+ * @watchdog_workqueue:        workqueue for the watchdog
+ * @watchdog_work:     worker for the watchdog
+ * @alloc_ctx:         videobuf2 allocator contexts for two memory banks
+ * @enter_suspend:     flag set when entering suspend
+ *
+ */
+struct s5p_mfc_dev {
+       struct v4l2_device      v4l2_dev;
+       struct video_device     *vfd_dec;
+       struct video_device     *vfd_enc;
+       struct platform_device  *plat_dev;
+       struct device           *mem_dev_l;
+       struct device           *mem_dev_r;
+       void __iomem            *regs_base;
+       int                     irq;
+       struct resource         *mfc_mem;
+       struct v4l2_ctrl_handler dec_ctrl_handler;
+       struct v4l2_ctrl_handler enc_ctrl_handler;
+       struct s5p_mfc_pm       pm;
+       int num_inst;
+       spinlock_t irqlock;     /* lock when operating on videobuf2 queues */
+       spinlock_t condlock;    /* lock when changing/checking if a context is
+                                       ready to be processed */
+       struct mutex mfc_mutex; /* video_device lock */
+       int int_cond;
+       int int_type;
+       unsigned int int_err;
+       wait_queue_head_t queue;
+       size_t fw_size;
+       size_t bank1;
+       size_t bank2;
+       unsigned long hw_lock;
+       struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS];
+       int curr_ctx;
+       unsigned long ctx_work_bits;
+       atomic_t watchdog_cnt;
+       struct timer_list watchdog_timer;
+       struct workqueue_struct *watchdog_workqueue;
+       struct work_struct watchdog_work;
+       void *alloc_ctx[2];
+       unsigned long enter_suspend;
+};
+
+/**
+ * struct s5p_mfc_h264_enc_params - encoding parameters for h264
+ */
+struct s5p_mfc_h264_enc_params {
+       enum v4l2_mpeg_video_h264_profile profile;
+       enum v4l2_mpeg_video_h264_loop_filter_mode loop_filter_mode;
+       s8 loop_filter_alpha;
+       s8 loop_filter_beta;
+       enum v4l2_mpeg_video_h264_entropy_mode entropy_mode;
+       u8 max_ref_pic;
+       u8 num_ref_pic_4p;
+       int _8x8_transform;
+       int rc_mb;
+       int rc_mb_dark;
+       int rc_mb_smooth;
+       int rc_mb_static;
+       int rc_mb_activity;
+       int vui_sar;
+       u8 vui_sar_idc;
+       u16 vui_ext_sar_width;
+       u16 vui_ext_sar_height;
+       int open_gop;
+       u16 open_gop_size;
+       u8 rc_frame_qp;
+       u8 rc_min_qp;
+       u8 rc_max_qp;
+       u8 rc_p_frame_qp;
+       u8 rc_b_frame_qp;
+       enum v4l2_mpeg_video_h264_level level_v4l2;
+       int level;
+       u16 cpb_size;
+};
+
+/**
+ * struct s5p_mfc_mpeg4_enc_params - encoding parameters for h263 and mpeg4
+ */
+struct s5p_mfc_mpeg4_enc_params {
+       /* MPEG4 Only */
+       enum v4l2_mpeg_video_mpeg4_profile profile;
+       int quarter_pixel;
+       /* Common for MPEG4, H263 */
+       u16 vop_time_res;
+       u16 vop_frm_delta;
+       u8 rc_frame_qp;
+       u8 rc_min_qp;
+       u8 rc_max_qp;
+       u8 rc_p_frame_qp;
+       u8 rc_b_frame_qp;
+       enum v4l2_mpeg_video_mpeg4_level level_v4l2;
+       int level;
+};
+
+/**
+ * struct s5p_mfc_enc_params - general encoding parameters
+ */
+struct s5p_mfc_enc_params {
+       u16 width;
+       u16 height;
+
+       u16 gop_size;
+       enum v4l2_mpeg_video_multi_slice_mode slice_mode;
+       u16 slice_mb;
+       u32 slice_bit;
+       u16 intra_refresh_mb;
+       int pad;
+       u8 pad_luma;
+       u8 pad_cb;
+       u8 pad_cr;
+       int rc_frame;
+       u32 rc_bitrate;
+       u16 rc_reaction_coeff;
+       u16 vbv_size;
+
+       enum v4l2_mpeg_video_header_mode seq_hdr_mode;
+       enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
+       int fixed_target_bit;
+
+       u8 num_b_frame;
+       u32 rc_framerate_num;
+       u32 rc_framerate_denom;
+       int interlace;
+
+       union {
+               struct s5p_mfc_h264_enc_params h264;
+               struct s5p_mfc_mpeg4_enc_params mpeg4;
+       } codec;
+
+};
+
+/**
+ * struct s5p_mfc_codec_ops - codec ops, used by encoding
+ */
+struct s5p_mfc_codec_ops {
+       /* initialization routines */
+       int (*pre_seq_start) (struct s5p_mfc_ctx *ctx);
+       int (*post_seq_start) (struct s5p_mfc_ctx *ctx);
+       /* execution routines */
+       int (*pre_frame_start) (struct s5p_mfc_ctx *ctx);
+       int (*post_frame_start) (struct s5p_mfc_ctx *ctx);
+};
+
+#define call_cop(c, op, args...)                               \
+       (((c)->c_ops->op) ?                                     \
+               ((c)->c_ops->op(args)) : 0)
+
+/**
+ * struct s5p_mfc_ctx - This struct contains the instance context
+ *
+ * @dev:               pointer to the s5p_mfc_dev of the device
+ * @fh:                        struct v4l2_fh
+ * @num:               number of the context that this structure describes
+ * @int_cond:          variable used by the waitqueue
+ * @int_type:          type of the last interrupt
+ * @int_err:           error number received from MFC hw in the interrupt
+ * @queue:             waitqueue that can be used to wait for this context to
+ *                     finish
+ * @src_fmt:           source pixelformat information
+ * @dst_fmt:           destination pixelformat information
+ * @vq_src:            vb2 queue for source buffers
+ * @vq_dst:            vb2 queue for destination buffers
+ * @src_queue:         driver internal queue for source buffers
+ * @dst_queue:         driver internal queue for destination buffers
+ * @src_queue_cnt:     number of buffers queued on the source internal queue
+ * @dst_queue_cnt:     number of buffers queued on the dest internal queue
+ * @type:              type of the instance - decoder or encoder
+ * @state:             state of the context
+ * @inst_no:           number of hw instance associated with the context
+ * @img_width:         width of the image that is decoded or encoded
+ * @img_height:                height of the image that is decoded or encoded
+ * @buf_width:         width of the buffer for processed image
+ * @buf_height:                height of the buffer for processed image
+ * @luma_size:         size of a luma plane
+ * @chroma_size:       size of a chroma plane
+ * @mv_size:           size of a motion vectors buffer
+ * @consumed_stream:   number of bytes that have been used so far from the
+ *                     decoding buffer
+ * @dpb_flush_flag:    flag used to indicate that a DPB buffers are being
+ *                     flushed
+ * @bank1_buf:         handle to memory allocated for temporary buffers from
+ *                     memory bank 1
+ * @bank1_phys:                address of the temporary buffers from memory bank 1
+ * @bank1_size:                size of the memory allocated for temporary buffers from
+ *                     memory bank 1
+ * @bank2_buf:         handle to memory allocated for temporary buffers from
+ *                     memory bank 2
+ * @bank2_phys:                address of the temporary buffers from memory bank 2
+ * @bank2_size:                size of the memory allocated for temporary buffers from
+ *                     memory bank 2
+ * @capture_state:     state of the capture buffers queue
+ * @output_state:      state of the output buffers queue
+ * @src_bufs:          information on allocated source buffers
+ * @dst_bufs:          information on allocated destination buffers
+ * @sequence:          counter for the sequence number for v4l2
+ * @dec_dst_flag:      flags for buffers queued in the hardware
+ * @dec_src_buf_size:  size of the buffer for source buffers in decoding
+ * @codec_mode:                number of codec mode used by MFC hw
+ * @slice_interface:   slice interface flag
+ * @loop_filter_mpeg4: loop filter for MPEG4 flag
+ * @display_delay:     value of the display delay for H264
+ * @display_delay_enable:      display delay for H264 enable flag
+ * @after_packed_pb:   flag used to track buffer when stream is in
+ *                     Packed PB format
+ * @dpb_count:         count of the DPB buffers required by MFC hw
+ * @total_dpb_count:   count of DPB buffers with additional buffers
+ *                     requested by the application
+ * @ctx_buf:           handle to the memory associated with this context
+ * @ctx_phys:          address of the memory associated with this context
+ * @ctx_size:          size of the memory associated with this context
+ * @desc_buf:          description buffer for decoding handle
+ * @desc_phys:         description buffer for decoding address
+ * @shm_alloc:         handle for the shared memory buffer
+ * @shm:               virtual address for the shared memory buffer
+ * @shm_ofs:           address offset for shared memory
+ * @enc_params:                encoding parameters for MFC
+ * @enc_dst_buf_size:  size of the buffers for encoder output
+ * @frame_type:                used to force the type of the next encoded frame
+ * @ref_queue:         list of the reference buffers for encoding
+ * @ref_queue_cnt:     number of the buffers in the reference list
+ * @c_ops:             ops for encoding
+ * @ctrls:             array of controls, used when adding controls to the
+ *                     v4l2 control framework
+ * @ctrl_handler:      handler for v4l2 framework
+ */
+struct s5p_mfc_ctx {
+       struct s5p_mfc_dev *dev;
+       struct v4l2_fh fh;
+
+       int num;
+
+       int int_cond;
+       int int_type;
+       unsigned int int_err;
+       wait_queue_head_t queue;
+
+       struct s5p_mfc_fmt *src_fmt;
+       struct s5p_mfc_fmt *dst_fmt;
+
+       struct vb2_queue vq_src;
+       struct vb2_queue vq_dst;
+
+       struct list_head src_queue;
+       struct list_head dst_queue;
+
+       unsigned int src_queue_cnt;
+       unsigned int dst_queue_cnt;
+
+       enum s5p_mfc_inst_type type;
+       enum s5p_mfc_inst_state state;
+       int inst_no;
+
+       /* Image parameters */
+       int img_width;
+       int img_height;
+       int buf_width;
+       int buf_height;
+
+       int luma_size;
+       int chroma_size;
+       int mv_size;
+
+       unsigned long consumed_stream;
+
+       unsigned int dpb_flush_flag;
+
+       /* Buffers */
+       void *bank1_buf;
+       size_t bank1_phys;
+       size_t bank1_size;
+
+       void *bank2_buf;
+       size_t bank2_phys;
+       size_t bank2_size;
+
+       enum s5p_mfc_queue_state capture_state;
+       enum s5p_mfc_queue_state output_state;
+
+       struct s5p_mfc_buf src_bufs[MFC_MAX_BUFFERS];
+       int src_bufs_cnt;
+       struct s5p_mfc_buf dst_bufs[MFC_MAX_BUFFERS];
+       int dst_bufs_cnt;
+
+       unsigned int sequence;
+       unsigned long dec_dst_flag;
+       size_t dec_src_buf_size;
+
+       /* Control values */
+       int codec_mode;
+       int slice_interface;
+       int loop_filter_mpeg4;
+       int display_delay;
+       int display_delay_enable;
+       int after_packed_pb;
+
+       int dpb_count;
+       int total_dpb_count;
+
+       /* Buffers */
+       void *ctx_buf;
+       size_t ctx_phys;
+       size_t ctx_ofs;
+       size_t ctx_size;
+
+       void *desc_buf;
+       size_t desc_phys;
+
+
+       void *shm_alloc;
+       void *shm;
+       size_t shm_ofs;
+
+       struct s5p_mfc_enc_params enc_params;
+
+       size_t enc_dst_buf_size;
+
+       enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
+
+       struct list_head ref_queue;
+       unsigned int ref_queue_cnt;
+
+       struct s5p_mfc_codec_ops *c_ops;
+
+       struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
+       struct v4l2_ctrl_handler ctrl_handler;
+};
+
+/*
+ * struct s5p_mfc_fmt -        structure used to store information about pixelformats
+ *                     used by the MFC
+ */
+struct s5p_mfc_fmt {
+       char *name;
+       u32 fourcc;
+       u32 codec_mode;
+       enum s5p_mfc_fmt_type type;
+       u32 num_planes;
+};
+
+/**
+ * struct mfc_control -        structure used to store information about MFC controls
+ *                     it is used to initialize the control framework.
+ */
+struct mfc_control {
+       __u32                   id;
+       enum v4l2_ctrl_type     type;
+       __u8                    name[32];  /* Whatever */
+       __s32                   minimum;   /* Note signedness */
+       __s32                   maximum;
+       __s32                   step;
+       __u32                   menu_skip_mask;
+       __s32                   default_value;
+       __u32                   flags;
+       __u32                   reserved[2];
+       __u8                    is_volatile;
+};
+
+
+#define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh)
+#define ctrl_to_ctx(__ctrl) \
+       container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler)
+
+#endif /* S5P_MFC_COMMON_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
new file mode 100644 (file)
index 0000000..5f4da80
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include "regs-mfc.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_pm.h"
+
+static void *s5p_mfc_bitproc_buf;
+static size_t s5p_mfc_bitproc_phys;
+static unsigned char *s5p_mfc_bitproc_virt;
+
+/* Allocate and load firmware */
+int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
+{
+       struct firmware *fw_blob;
+       size_t bank2_base_phys;
+       void *b_base;
+       int err;
+
+       /* Firmare has to be present as a separate file or compiled
+        * into kernel. */
+       mfc_debug_enter();
+       err = request_firmware((const struct firmware **)&fw_blob,
+                                    "s5pc110-mfc.fw", dev->v4l2_dev.dev);
+       if (err != 0) {
+               mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
+               return -EINVAL;
+       }
+       dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
+       if (s5p_mfc_bitproc_buf) {
+               mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
+               release_firmware(fw_blob);
+               return -ENOMEM;
+       }
+       s5p_mfc_bitproc_buf = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], dev->fw_size);
+       if (IS_ERR(s5p_mfc_bitproc_buf)) {
+               s5p_mfc_bitproc_buf = 0;
+               mfc_err("Allocating bitprocessor buffer failed\n");
+               release_firmware(fw_blob);
+               return -ENOMEM;
+       }
+       s5p_mfc_bitproc_phys = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], s5p_mfc_bitproc_buf);
+       if (s5p_mfc_bitproc_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
+               mfc_err("The base memory for bank 1 is not aligned to 128KB\n");
+               vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+               s5p_mfc_bitproc_phys = 0;
+               s5p_mfc_bitproc_buf = 0;
+               release_firmware(fw_blob);
+               return -EIO;
+       }
+       s5p_mfc_bitproc_virt = vb2_dma_contig_memops.vaddr(s5p_mfc_bitproc_buf);
+       if (!s5p_mfc_bitproc_virt) {
+               mfc_err("Bitprocessor memory remap failed\n");
+               vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+               s5p_mfc_bitproc_phys = 0;
+               s5p_mfc_bitproc_buf = 0;
+               release_firmware(fw_blob);
+               return -EIO;
+       }
+       dev->bank1 = s5p_mfc_bitproc_phys;
+       b_base = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BANK2_ALIGN_ORDER);
+       if (IS_ERR(b_base)) {
+               vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+               s5p_mfc_bitproc_phys = 0;
+               s5p_mfc_bitproc_buf = 0;
+               mfc_err("Allocating bank2 base failed\n");
+       release_firmware(fw_blob);
+               return -ENOMEM;
+       }
+       bank2_base_phys = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
+       vb2_dma_contig_memops.put(b_base);
+       if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
+               mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
+               vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+               s5p_mfc_bitproc_phys = 0;
+               s5p_mfc_bitproc_buf = 0;
+               release_firmware(fw_blob);
+               return -EIO;
+       }
+       dev->bank2 = bank2_base_phys;
+       memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
+       wmb();
+       release_firmware(fw_blob);
+       mfc_debug_leave();
+       return 0;
+}
+
+/* Reload firmware to MFC */
+int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
+{
+       struct firmware *fw_blob;
+       int err;
+
+       /* Firmare has to be present as a separate file or compiled
+        * into kernel. */
+       mfc_debug_enter();
+       err = request_firmware((const struct firmware **)&fw_blob,
+                                    "s5pc110-mfc.fw", dev->v4l2_dev.dev);
+       if (err != 0) {
+               mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
+               return -EINVAL;
+       }
+       if (fw_blob->size > dev->fw_size) {
+               mfc_err("MFC firmware is too big to be loaded\n");
+               release_firmware(fw_blob);
+               return -ENOMEM;
+       }
+       if (s5p_mfc_bitproc_buf == 0 || s5p_mfc_bitproc_phys == 0) {
+               mfc_err("MFC firmware is not allocated or was not mapped correctly\n");
+               release_firmware(fw_blob);
+               return -EINVAL;
+       }
+       memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
+       wmb();
+       release_firmware(fw_blob);
+       mfc_debug_leave();
+       return 0;
+}
+
+/* Release firmware memory */
+int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev)
+{
+       /* Before calling this function one has to make sure
+        * that MFC is no longer processing */
+       if (!s5p_mfc_bitproc_buf)
+               return -EINVAL;
+       vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+       s5p_mfc_bitproc_virt =  0;
+       s5p_mfc_bitproc_phys = 0;
+       s5p_mfc_bitproc_buf = 0;
+       return 0;
+}
+
+/* Reset the device */
+int s5p_mfc_reset(struct s5p_mfc_dev *dev)
+{
+       unsigned int mc_status;
+       unsigned long timeout;
+
+       mfc_debug_enter();
+       /* Stop procedure */
+       /*  reset RISC */
+       mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
+       /*  All reset except for MC */
+       mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
+       mdelay(10);
+
+       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+       /* Check MC status */
+       do {
+               if (time_after(jiffies, timeout)) {
+                       mfc_err("Timeout while resetting MFC\n");
+                       return -EIO;
+               }
+
+               mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
+
+       } while (mc_status & 0x3);
+
+       mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
+       mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
+       mfc_debug_leave();
+       return 0;
+}
+
+static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
+{
+       mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
+       mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
+       mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
+}
+
+static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
+{
+       mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
+       mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
+       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+       mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
+}
+
+/* Initialize hardware */
+int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
+{
+       unsigned int ver;
+       int ret;
+
+       mfc_debug_enter();
+       if (!s5p_mfc_bitproc_buf)
+               return -EINVAL;
+
+       /* 0. MFC reset */
+       mfc_debug(2, "MFC reset..\n");
+       s5p_mfc_clock_on();
+       ret = s5p_mfc_reset(dev);
+       if (ret) {
+               mfc_err("Failed to reset MFC - timeout\n");
+               return ret;
+       }
+       mfc_debug(2, "Done MFC reset..\n");
+       /* 1. Set DRAM base Addr */
+       s5p_mfc_init_memctrl(dev);
+       /* 2. Initialize registers of channel I/F */
+       s5p_mfc_clear_cmds(dev);
+       /* 3. Release reset signal to the RISC */
+       s5p_mfc_clean_dev_int_flags(dev);
+       mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+       mfc_debug(2, "Will now wait for completion of firmware transfer\n");
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
+               mfc_err("Failed to load firmware\n");
+               s5p_mfc_reset(dev);
+               s5p_mfc_clock_off();
+               return -EIO;
+       }
+       s5p_mfc_clean_dev_int_flags(dev);
+       /* 4. Initialize firmware */
+       ret = s5p_mfc_sys_init_cmd(dev);
+       if (ret) {
+               mfc_err("Failed to send command to MFC - timeout\n");
+               s5p_mfc_reset(dev);
+               s5p_mfc_clock_off();
+               return ret;
+       }
+       mfc_debug(2, "Ok, now will write a command to init the system\n");
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
+               mfc_err("Failed to load firmware\n");
+               s5p_mfc_reset(dev);
+               s5p_mfc_clock_off();
+               return -EIO;
+       }
+       dev->int_cond = 0;
+       if (dev->int_err != 0 || dev->int_type !=
+                                       S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
+               /* Failure. */
+               mfc_err("Failed to init firmware - error: %d int: %d\n",
+                                               dev->int_err, dev->int_type);
+               s5p_mfc_reset(dev);
+               s5p_mfc_clock_off();
+               return -EIO;
+       }
+       ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
+       mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
+               (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
+       s5p_mfc_clock_off();
+       mfc_debug_leave();
+       return 0;
+}
+
+
+int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
+{
+       int ret;
+
+       mfc_debug_enter();
+       s5p_mfc_clock_on();
+       s5p_mfc_clean_dev_int_flags(dev);
+       ret = s5p_mfc_sleep_cmd(dev);
+       if (ret) {
+               mfc_err("Failed to send command to MFC - timeout\n");
+               return ret;
+       }
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) {
+               mfc_err("Failed to sleep\n");
+               return -EIO;
+       }
+       s5p_mfc_clock_off();
+       dev->int_cond = 0;
+       if (dev->int_err != 0 || dev->int_type !=
+                                               S5P_FIMV_R2H_CMD_SLEEP_RET) {
+               /* Failure. */
+               mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
+                                                               dev->int_type);
+               return -EIO;
+       }
+       mfc_debug_leave();
+       return ret;
+}
+
+int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
+{
+       int ret;
+
+       mfc_debug_enter();
+       /* 0. MFC reset */
+       mfc_debug(2, "MFC reset..\n");
+       s5p_mfc_clock_on();
+       ret = s5p_mfc_reset(dev);
+       if (ret) {
+               mfc_err("Failed to reset MFC - timeout\n");
+               return ret;
+       }
+       mfc_debug(2, "Done MFC reset..\n");
+       /* 1. Set DRAM base Addr */
+       s5p_mfc_init_memctrl(dev);
+       /* 2. Initialize registers of channel I/F */
+       s5p_mfc_clear_cmds(dev);
+       s5p_mfc_clean_dev_int_flags(dev);
+       /* 3. Initialize firmware */
+       ret = s5p_mfc_wakeup_cmd(dev);
+       if (ret) {
+               mfc_err("Failed to send command to MFC - timeout\n");
+               return ret;
+       }
+       /* 4. Release reset signal to the RISC */
+       mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+       mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
+               mfc_err("Failed to load firmware\n");
+               return -EIO;
+       }
+       s5p_mfc_clock_off();
+       dev->int_cond = 0;
+       if (dev->int_err != 0 || dev->int_type !=
+                                               S5P_FIMV_R2H_CMD_WAKEUP_RET) {
+               /* Failure. */
+               mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err,
+                                                               dev->int_type);
+               return -EIO;
+       }
+       mfc_debug_leave();
+       return 0;
+}
+
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
new file mode 100644 (file)
index 0000000..61dc23b
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+
+#ifndef S5P_MFC_CTRL_H
+#define S5P_MFC_CTRL_H
+
+#include "s5p_mfc_common.h"
+
+int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev);
+int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev);
+int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_sleep(struct s5p_mfc_dev *dev);
+int s5p_mfc_wakeup(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_reset(struct s5p_mfc_dev *dev);
+
+#endif /* S5P_MFC_CTRL_H */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_debug.h b/drivers/media/video/s5p-mfc/s5p_mfc_debug.h
new file mode 100644 (file)
index 0000000..ecb8616
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * drivers/media/video/samsung/mfc5/s5p_mfc_debug.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains debug macros
+ *
+ * Kamil Debski, Copyright (c) 2011 Samsung Electronics
+ * http://www.samsung.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 S5P_MFC_DEBUG_H_
+#define S5P_MFC_DEBUG_H_
+
+#define DEBUG
+
+#ifdef DEBUG
+extern int debug;
+
+#define mfc_debug(level, fmt, args...)                         \
+       do {                                                    \
+               if (debug >= level)                             \
+                       printk(KERN_DEBUG "%s:%d: " fmt,        \
+                               __func__, __LINE__, ##args);    \
+       } while (0)
+#else
+#define mfc_debug(level, fmt, args...)
+#endif
+
+#define mfc_debug_enter() mfc_debug(5, "enter")
+#define mfc_debug_leave() mfc_debug(5, "leave")
+
+#define mfc_err(fmt, args...)                          \
+       do {                                            \
+               printk(KERN_ERR "%s:%d: " fmt,          \
+                      __func__, __LINE__, ##args);     \
+       } while (0)
+
+#define mfc_info(fmt, args...)                         \
+       do {                                            \
+               printk(KERN_INFO "%s:%d: " fmt,         \
+                      __func__, __LINE__, ##args);     \
+       } while (0)
+
+#endif /* S5P_MFC_DEBUG_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
new file mode 100644 (file)
index 0000000..b2c5052
--- /dev/null
@@ -0,0 +1,1036 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ * Kamil Debski, <k.debski@samsung.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/videodev2.h>
+#include <linux/workqueue.h>
+#include <media/v4l2-ctrls.h>
+#include <media/videobuf2-core.h>
+#include "regs-mfc.h"
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_dec.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_shm.h"
+
+static struct s5p_mfc_fmt formats[] = {
+       {
+               .name           = "4:2:0 2 Planes 64x32 Tiles",
+               .fourcc         = V4L2_PIX_FMT_NV12MT,
+               .codec_mode     = S5P_FIMV_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+        },
+       {
+               .name = "4:2:0 2 Planes",
+               .fourcc = V4L2_PIX_FMT_NV12M,
+               .codec_mode = S5P_FIMV_CODEC_NONE,
+               .type = MFC_FMT_RAW,
+               .num_planes = 2,
+       },
+       {
+               .name = "H264 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_H264,
+               .codec_mode = S5P_FIMV_CODEC_H264_DEC,
+               .type = MFC_FMT_DEC,
+               .num_planes = 1,
+       },
+       {
+               .name = "H263 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_H263,
+               .codec_mode = S5P_FIMV_CODEC_H263_DEC,
+               .type = MFC_FMT_DEC,
+               .num_planes = 1,
+       },
+       {
+               .name = "MPEG1 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_MPEG1,
+               .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
+               .type = MFC_FMT_DEC,
+               .num_planes = 1,
+       },
+       {
+               .name = "MPEG2 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_MPEG2,
+               .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
+               .type = MFC_FMT_DEC,
+               .num_planes = 1,
+       },
+       {
+               .name = "MPEG4 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_MPEG4,
+               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
+               .type = MFC_FMT_DEC,
+               .num_planes = 1,
+       },
+       {
+               .name = "XviD Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_XVID,
+               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
+               .type = MFC_FMT_DEC,
+               .num_planes = 1,
+       },
+       {
+               .name = "VC1 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
+               .codec_mode = S5P_FIMV_CODEC_VC1_DEC,
+               .type = MFC_FMT_DEC,
+               .num_planes = 1,
+       },
+       {
+               .name = "VC1 RCV Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
+               .codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC,
+               .type = MFC_FMT_DEC,
+               .num_planes = 1,
+       },
+};
+
+#define NUM_FORMATS ARRAY_SIZE(formats)
+
+/* Find selected format description */
+static struct s5p_mfc_fmt *find_format(struct v4l2_format *f, unsigned int t)
+{
+       unsigned int i;
+
+       for (i = 0; i < NUM_FORMATS; i++) {
+               if (formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
+                   formats[i].type == t)
+                       return &formats[i];
+       }
+       return NULL;
+}
+
+static struct mfc_control controls[] = {
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 Display Delay",
+               .minimum = 0,
+               .maximum = 16383,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 Display Delay Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Mpeg4 Loop Filter Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Slice Interface Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Minimum number of cap bufs",
+               .minimum = 1,
+               .maximum = 32,
+               .step = 1,
+               .default_value = 1,
+               .is_volatile = 1,
+       },
+};
+
+#define NUM_CTRLS ARRAY_SIZE(controls)
+
+/* Check whether a context should be run on hardware */
+static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
+{
+       /* Context is to parse header */
+       if (ctx->src_queue_cnt >= 1 && ctx->state == MFCINST_GOT_INST)
+               return 1;
+       /* Context is to decode a frame */
+       if (ctx->src_queue_cnt >= 1 &&
+           ctx->state == MFCINST_RUNNING &&
+           ctx->dst_queue_cnt >= ctx->dpb_count)
+               return 1;
+       /* Context is to return last frame */
+       if (ctx->state == MFCINST_FINISHING &&
+           ctx->dst_queue_cnt >= ctx->dpb_count)
+               return 1;
+       /* Context is to set buffers */
+       if (ctx->src_queue_cnt >= 1 &&
+           ctx->state == MFCINST_HEAD_PARSED &&
+           ctx->capture_state == QUEUE_BUFS_MMAPED)
+               return 1;
+       /* Resolution change */
+       if ((ctx->state == MFCINST_RES_CHANGE_INIT ||
+               ctx->state == MFCINST_RES_CHANGE_FLUSH) &&
+               ctx->dst_queue_cnt >= ctx->dpb_count)
+               return 1;
+       if (ctx->state == MFCINST_RES_CHANGE_END &&
+               ctx->src_queue_cnt >= 1)
+               return 1;
+       mfc_debug(2, "ctx is not ready\n");
+       return 0;
+}
+
+static struct s5p_mfc_codec_ops decoder_codec_ops = {
+       .pre_seq_start          = NULL,
+       .post_seq_start         = NULL,
+       .pre_frame_start        = NULL,
+       .post_frame_start       = NULL,
+};
+
+/* Query capabilities of the device */
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+
+       strncpy(cap->driver, dev->plat_dev->name, sizeof(cap->driver) - 1);
+       strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
+       cap->bus_info[0] = 0;
+       cap->version = KERNEL_VERSION(1, 0, 0);
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
+                                                   | V4L2_CAP_STREAMING;
+       return 0;
+}
+
+/* Enumerate format */
+static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out)
+{
+       struct s5p_mfc_fmt *fmt;
+       int i, j = 0;
+
+       for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+               if (mplane && formats[i].num_planes == 1)
+                       continue;
+               else if (!mplane && formats[i].num_planes > 1)
+                       continue;
+               if (out && formats[i].type != MFC_FMT_DEC)
+                       continue;
+               else if (!out && formats[i].type != MFC_FMT_RAW)
+                       continue;
+
+               if (j == f->index)
+                       break;
+               ++j;
+       }
+       if (i == ARRAY_SIZE(formats))
+               return -EINVAL;
+       fmt = &formats[i];
+       strlcpy(f->description, fmt->name, sizeof(f->description));
+       f->pixelformat = fmt->fourcc;
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv,
+                                                       struct v4l2_fmtdesc *f)
+{
+       return vidioc_enum_fmt(f, false, false);
+}
+
+static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
+                                                       struct v4l2_fmtdesc *f)
+{
+       return vidioc_enum_fmt(f, true, false);
+}
+
+static int vidioc_enum_fmt_vid_out(struct file *file, void *prov,
+                                                       struct v4l2_fmtdesc *f)
+{
+       return vidioc_enum_fmt(f, false, true);
+}
+
+static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
+                                                       struct v4l2_fmtdesc *f)
+{
+       return vidioc_enum_fmt(f, true, true);
+}
+
+/* Get format */
+static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct v4l2_pix_format_mplane *pix_mp;
+
+       mfc_debug_enter();
+       pix_mp = &f->fmt.pix_mp;
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+           (ctx->state == MFCINST_GOT_INST || ctx->state ==
+                                               MFCINST_RES_CHANGE_END)) {
+               /* If the MFC is parsing the header,
+                * so wait until it is finished */
+               s5p_mfc_clean_ctx_int_flags(ctx);
+               s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_SEQ_DONE_RET,
+                                                                       0);
+       }
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+           ctx->state >= MFCINST_HEAD_PARSED &&
+           ctx->state < MFCINST_ABORT) {
+               /* This is run on CAPTURE (decode output) */
+               /* Width and height are set to the dimensions
+                  of the movie, the buffer is bigger and
+                  further processing stages should crop to this
+                  rectangle. */
+               pix_mp->width = ctx->buf_width;
+               pix_mp->height = ctx->buf_height;
+               pix_mp->field = V4L2_FIELD_NONE;
+               pix_mp->num_planes = 2;
+               /* Set pixelformat to the format in which MFC
+                  outputs the decoded frame */
+               pix_mp->pixelformat = V4L2_PIX_FMT_NV12MT;
+               pix_mp->plane_fmt[0].bytesperline = ctx->buf_width;
+               pix_mp->plane_fmt[0].sizeimage = ctx->luma_size;
+               pix_mp->plane_fmt[1].bytesperline = ctx->buf_width;
+               pix_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               /* This is run on OUTPUT
+                  The buffer contains compressed image
+                  so width and height have no meaning */
+               pix_mp->width = 0;
+               pix_mp->height = 0;
+               pix_mp->field = V4L2_FIELD_NONE;
+               pix_mp->plane_fmt[0].bytesperline = ctx->dec_src_buf_size;
+               pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size;
+               pix_mp->pixelformat = ctx->src_fmt->fourcc;
+               pix_mp->num_planes = ctx->src_fmt->num_planes;
+       } else {
+               mfc_err("Format could not be read\n");
+               mfc_debug(2, "%s-- with error\n", __func__);
+               return -EINVAL;
+       }
+       mfc_debug_leave();
+       return 0;
+}
+
+/* Try format */
+static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_fmt *fmt;
+
+       if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_err("This node supports decoding only\n");
+               return -EINVAL;
+       }
+       fmt = find_format(f, MFC_FMT_DEC);
+       if (!fmt) {
+               mfc_err("Unsupported format\n");
+               return -EINVAL;
+       }
+       if (fmt->type != MFC_FMT_DEC) {
+               mfc_err("\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* Set format */
+static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret = 0;
+       struct s5p_mfc_fmt *fmt;
+       struct v4l2_pix_format_mplane *pix_mp;
+
+       mfc_debug_enter();
+       ret = vidioc_try_fmt(file, priv, f);
+       pix_mp = &f->fmt.pix_mp;
+       if (ret)
+               return ret;
+       if (ctx->vq_src.streaming || ctx->vq_dst.streaming) {
+               v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
+               ret = -EBUSY;
+               goto out;
+       }
+       fmt = find_format(f, MFC_FMT_DEC);
+       if (!fmt || fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
+               mfc_err("Unknown codec\n");
+               ret = -EINVAL;
+               goto out;
+       }
+       if (fmt->type != MFC_FMT_DEC) {
+               mfc_err("Wrong format selected, you should choose "
+                                       "format for decoding\n");
+               ret = -EINVAL;
+               goto out;
+       }
+       ctx->src_fmt = fmt;
+       ctx->codec_mode = fmt->codec_mode;
+       mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
+       pix_mp->height = 0;
+       pix_mp->width = 0;
+       if (pix_mp->plane_fmt[0].sizeimage)
+               ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
+       else
+               pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size =
+                                                               DEF_CPB_SIZE;
+       pix_mp->plane_fmt[0].bytesperline = 0;
+       ctx->state = MFCINST_INIT;
+out:
+       mfc_debug_leave();
+       return ret;
+}
+
+/* Reqeust buffers */
+static int vidioc_reqbufs(struct file *file, void *priv,
+                                         struct v4l2_requestbuffers *reqbufs)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret = 0;
+       unsigned long flags;
+
+       if (reqbufs->memory != V4L2_MEMORY_MMAP) {
+               mfc_err("Only V4L2_MEMORY_MAP is supported\n");
+               return -EINVAL;
+       }
+       if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               /* Can only request buffers after an instance has been opened.*/
+               if (ctx->state == MFCINST_INIT) {
+                       ctx->src_bufs_cnt = 0;
+                       if (reqbufs->count == 0) {
+                               mfc_debug(2, "Freeing buffers\n");
+                               s5p_mfc_clock_on();
+                               ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+                               s5p_mfc_clock_off();
+                               return ret;
+                       }
+                       /* Decoding */
+                       if (ctx->output_state != QUEUE_FREE) {
+                               mfc_err("Bufs have already been requested\n");
+                               return -EINVAL;
+                       }
+                       s5p_mfc_clock_on();
+                       ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+                       s5p_mfc_clock_off();
+                       if (ret) {
+                               mfc_err("vb2_reqbufs on output failed\n");
+                               return ret;
+                       }
+                       mfc_debug(2, "vb2_reqbufs: %d\n", ret);
+                       ctx->output_state = QUEUE_BUFS_REQUESTED;
+               }
+       } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               ctx->dst_bufs_cnt = 0;
+               if (reqbufs->count == 0) {
+                       mfc_debug(2, "Freeing buffers\n");
+                       s5p_mfc_clock_on();
+                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                       s5p_mfc_clock_off();
+                       return ret;
+               }
+               if (ctx->capture_state != QUEUE_FREE) {
+                       mfc_err("Bufs have already been requested\n");
+                       return -EINVAL;
+               }
+               ctx->capture_state = QUEUE_BUFS_REQUESTED;
+               s5p_mfc_clock_on();
+               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+               s5p_mfc_clock_off();
+               if (ret) {
+                       mfc_err("vb2_reqbufs on capture failed\n");
+                       return ret;
+               }
+               if (reqbufs->count < ctx->dpb_count) {
+                       mfc_err("Not enough buffers allocated\n");
+                       reqbufs->count = 0;
+                       s5p_mfc_clock_on();
+                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                       s5p_mfc_clock_off();
+                       return -ENOMEM;
+               }
+               ctx->total_dpb_count = reqbufs->count;
+               ret = s5p_mfc_alloc_codec_buffers(ctx);
+               if (ret) {
+                       mfc_err("Failed to allocate decoding buffers\n");
+                       reqbufs->count = 0;
+                       s5p_mfc_clock_on();
+                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                       s5p_mfc_clock_off();
+                       return -ENOMEM;
+               }
+               if (ctx->dst_bufs_cnt == ctx->total_dpb_count) {
+                       ctx->capture_state = QUEUE_BUFS_MMAPED;
+               } else {
+                       mfc_err("Not all buffers passed to buf_init\n");
+                       reqbufs->count = 0;
+                       s5p_mfc_clock_on();
+                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                       s5p_mfc_release_codec_buffers(ctx);
+                       s5p_mfc_clock_off();
+                       return -ENOMEM;
+               }
+               if (s5p_mfc_ctx_ready(ctx)) {
+                       spin_lock_irqsave(&dev->condlock, flags);
+                       set_bit(ctx->num, &dev->ctx_work_bits);
+                       spin_unlock_irqrestore(&dev->condlock, flags);
+               }
+               s5p_mfc_try_run(dev);
+               s5p_mfc_wait_for_done_ctx(ctx,
+                                        S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
+       }
+       return ret;
+}
+
+/* Query buffer */
+static int vidioc_querybuf(struct file *file, void *priv,
+                                                  struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret;
+       int i;
+
+       if (buf->memory != V4L2_MEMORY_MMAP) {
+               mfc_err("Only mmaped buffers can be used\n");
+               return -EINVAL;
+       }
+       mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type);
+       if (ctx->state == MFCINST_INIT &&
+                       buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ret = vb2_querybuf(&ctx->vq_src, buf);
+       } else if (ctx->state == MFCINST_RUNNING &&
+                       buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               ret = vb2_querybuf(&ctx->vq_dst, buf);
+               for (i = 0; i < buf->length; i++)
+                       buf->m.planes[i].m.mem_offset += DST_QUEUE_OFF_BASE;
+       } else {
+               mfc_err("vidioc_querybuf called in an inappropriate state\n");
+               ret = -EINVAL;
+       }
+       mfc_debug_leave();
+       return ret;
+}
+
+/* Queue a buffer */
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (ctx->state == MFCINST_ERROR) {
+               mfc_err("Call on QBUF after unrecoverable error\n");
+               return -EIO;
+       }
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_qbuf(&ctx->vq_src, buf);
+       else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_qbuf(&ctx->vq_dst, buf);
+       return -EINVAL;
+}
+
+/* Dequeue a buffer */
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (ctx->state == MFCINST_ERROR) {
+               mfc_err("Call on DQBUF after unrecoverable error\n");
+               return -EIO;
+       }
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
+       else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
+       return -EINVAL;
+}
+
+/* Stream on */
+static int vidioc_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type type)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       mfc_debug_enter();
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+
+               if (ctx->state == MFCINST_INIT) {
+                       ctx->dst_bufs_cnt = 0;
+                       ctx->src_bufs_cnt = 0;
+                       ctx->capture_state = QUEUE_FREE;
+                       ctx->output_state = QUEUE_FREE;
+                       s5p_mfc_alloc_instance_buffer(ctx);
+                       s5p_mfc_alloc_dec_temp_buffers(ctx);
+                       spin_lock_irqsave(&dev->condlock, flags);
+                       set_bit(ctx->num, &dev->ctx_work_bits);
+                       spin_unlock_irqrestore(&dev->condlock, flags);
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       s5p_mfc_try_run(dev);
+
+                       if (s5p_mfc_wait_for_done_ctx(ctx,
+                               S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
+                               /* Error or timeout */
+                               mfc_err("Error getting instance from hardware\n");
+                               s5p_mfc_release_instance_buffer(ctx);
+                               s5p_mfc_release_dec_desc_buffer(ctx);
+                               return -EIO;
+                       }
+                       mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
+               }
+               ret = vb2_streamon(&ctx->vq_src, type);
+               }
+       else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               ret = vb2_streamon(&ctx->vq_dst, type);
+       mfc_debug_leave();
+       return ret;
+}
+
+/* Stream off, which equals to a pause */
+static int vidioc_streamoff(struct file *file, void *priv,
+                           enum v4l2_buf_type type)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_streamoff(&ctx->vq_src, type);
+       else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_streamoff(&ctx->vq_dst, type);
+       return -EINVAL;
+}
+
+/* Set controls - v4l2 control framework */
+static int s5p_mfc_dec_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:
+               ctx->loop_filter_mpeg4 = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE:
+               ctx->display_delay_enable = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
+               ctx->display_delay = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
+               ctx->slice_interface = ctrl->val;
+               break;
+       default:
+               mfc_err("Invalid control 0x%08x\n", ctrl->id);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+               if (ctx->state >= MFCINST_HEAD_PARSED &&
+                   ctx->state < MFCINST_ABORT) {
+                       ctrl->val = ctx->dpb_count;
+                       break;
+               } else if (ctx->state != MFCINST_INIT) {
+                       v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");
+                       return -EINVAL;
+               }
+               /* Should wait for the header to be parsed */
+               s5p_mfc_clean_ctx_int_flags(ctx);
+               s5p_mfc_wait_for_done_ctx(ctx,
+                               S5P_FIMV_R2H_CMD_SEQ_DONE_RET, 0);
+               if (ctx->state >= MFCINST_HEAD_PARSED &&
+                   ctx->state < MFCINST_ABORT) {
+                       ctrl->val = ctx->dpb_count;
+               } else {
+                       v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");
+                       return -EINVAL;
+               }
+               break;
+       }
+       return 0;
+}
+
+
+static const struct v4l2_ctrl_ops s5p_mfc_dec_ctrl_ops = {
+       .s_ctrl = s5p_mfc_dec_s_ctrl,
+       .g_volatile_ctrl = s5p_mfc_dec_g_v_ctrl,
+};
+
+/* Get cropping information */
+static int vidioc_g_crop(struct file *file, void *priv,
+               struct v4l2_crop *cr)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       u32 left, right, top, bottom;
+
+       if (ctx->state != MFCINST_HEAD_PARSED &&
+       ctx->state != MFCINST_RUNNING && ctx->state != MFCINST_FINISHING
+                                       && ctx->state != MFCINST_FINISHED) {
+                       mfc_err("Cannont set crop\n");
+                       return -EINVAL;
+               }
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {
+               left = s5p_mfc_read_shm(ctx, CROP_INFO_H);
+               right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;
+               left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;
+               top = s5p_mfc_read_shm(ctx, CROP_INFO_V);
+               bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;
+               top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;
+               cr->c.left = left;
+               cr->c.top = top;
+               cr->c.width = ctx->img_width - left - right;
+               cr->c.height = ctx->img_height - top - bottom;
+               mfc_debug(2, "Cropping info [h264]: l=%d t=%d "
+                       "w=%d h=%d (r=%d b=%d fw=%d fh=%d\n", left, top,
+                       cr->c.width, cr->c.height, right, bottom,
+                       ctx->buf_width, ctx->buf_height);
+       } else {
+               cr->c.left = 0;
+               cr->c.top = 0;
+               cr->c.width = ctx->img_width;
+               cr->c.height = ctx->img_height;
+               mfc_debug(2, "Cropping info: w=%d h=%d fw=%d "
+                       "fh=%d\n", cr->c.width, cr->c.height, ctx->buf_width,
+                                                       ctx->buf_height);
+       }
+       return 0;
+}
+
+/* v4l2_ioctl_ops */
+static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
+       .vidioc_querycap = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
+       .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
+       .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
+       .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt,
+       .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt,
+       .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,
+       .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,
+       .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt,
+       .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt,
+       .vidioc_reqbufs = vidioc_reqbufs,
+       .vidioc_querybuf = vidioc_querybuf,
+       .vidioc_qbuf = vidioc_qbuf,
+       .vidioc_dqbuf = vidioc_dqbuf,
+       .vidioc_streamon = vidioc_streamon,
+       .vidioc_streamoff = vidioc_streamoff,
+       .vidioc_g_crop = vidioc_g_crop,
+};
+
+static int s5p_mfc_queue_setup(struct vb2_queue *vq, unsigned int *buf_count,
+                              unsigned int *plane_count, unsigned long psize[],
+                              void *allocators[])
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+
+       /* Video output for decoding (source)
+        * this can be set after getting an instance */
+       if (ctx->state == MFCINST_INIT &&
+           vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               /* A single plane is required for input */
+               *plane_count = 1;
+               if (*buf_count < 1)
+                       *buf_count = 1;
+               if (*buf_count > MFC_MAX_BUFFERS)
+                       *buf_count = MFC_MAX_BUFFERS;
+       /* Video capture for decoding (destination)
+        * this can be set after the header was parsed */
+       } else if (ctx->state == MFCINST_HEAD_PARSED &&
+                  vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               /* Output plane count is 2 - one for Y and one for CbCr */
+               *plane_count = 2;
+               /* Setup buffer count */
+               if (*buf_count < ctx->dpb_count)
+                       *buf_count = ctx->dpb_count;
+               if (*buf_count > ctx->dpb_count + MFC_MAX_EXTRA_DPB)
+                       *buf_count = ctx->dpb_count + MFC_MAX_EXTRA_DPB;
+               if (*buf_count > MFC_MAX_BUFFERS)
+                       *buf_count = MFC_MAX_BUFFERS;
+       } else {
+               mfc_err("State seems invalid. State = %d, vq->type = %d\n",
+                                                       ctx->state, vq->type);
+               return -EINVAL;
+       }
+       mfc_debug(2, "Buffer count=%d, plane count=%d\n",
+                                               *buf_count, *plane_count);
+       if (ctx->state == MFCINST_HEAD_PARSED &&
+           vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               psize[0] = ctx->luma_size;
+               psize[1] = ctx->chroma_size;
+               allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+               allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+                  ctx->state == MFCINST_INIT) {
+               psize[0] = ctx->dec_src_buf_size;
+               allocators[0] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+       } else {
+               mfc_err("This video node is dedicated to decoding. Decoding not initalised\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void s5p_mfc_unlock(struct vb2_queue *q)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mutex_unlock(&dev->mfc_mutex);
+}
+
+static void s5p_mfc_lock(struct vb2_queue *q)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mutex_lock(&dev->mfc_mutex);
+}
+
+static int s5p_mfc_buf_init(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       unsigned int i;
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               if (ctx->capture_state == QUEUE_BUFS_MMAPED)
+                       return 0;
+               for (i = 0; i <= ctx->src_fmt->num_planes ; i++) {
+                       if (IS_ERR_OR_NULL(ERR_PTR(
+                                       vb2_dma_contig_plane_paddr(vb, i)))) {
+                               mfc_err("Plane mem not allocated\n");
+                               return -EINVAL;
+                       }
+               }
+               if (vb2_plane_size(vb, 0) < ctx->luma_size ||
+                       vb2_plane_size(vb, 1) < ctx->chroma_size) {
+                       mfc_err("Plane buffer (CAPTURE) is too small\n");
+                       return -EINVAL;
+               }
+               i = vb->v4l2_buf.index;
+               ctx->dst_bufs[i].b = vb;
+               ctx->dst_bufs[i].cookie.raw.luma =
+                                       vb2_dma_contig_plane_paddr(vb, 0);
+               ctx->dst_bufs[i].cookie.raw.chroma =
+                                       vb2_dma_contig_plane_paddr(vb, 1);
+               ctx->dst_bufs_cnt++;
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (IS_ERR_OR_NULL(ERR_PTR(
+                                       vb2_dma_contig_plane_paddr(vb, 0)))) {
+                       mfc_err("Plane memory not allocated\n");
+                       return -EINVAL;
+               }
+               if (vb2_plane_size(vb, 0) < ctx->dec_src_buf_size) {
+                       mfc_err("Plane buffer (OUTPUT) is too small\n");
+                       return -EINVAL;
+               }
+
+               i = vb->v4l2_buf.index;
+               ctx->src_bufs[i].b = vb;
+               ctx->src_bufs[i].cookie.stream =
+                                       vb2_dma_contig_plane_paddr(vb, 0);
+               ctx->src_bufs_cnt++;
+       } else {
+               mfc_err("s5p_mfc_buf_init: unknown queue type\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_start_streaming(struct vb2_queue *q)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+
+       v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
+       if (ctx->state == MFCINST_FINISHING ||
+               ctx->state == MFCINST_FINISHED)
+               ctx->state = MFCINST_RUNNING;
+       /* If context is ready then dev = work->data;schedule it to run */
+       if (s5p_mfc_ctx_ready(ctx)) {
+               spin_lock_irqsave(&dev->condlock, flags);
+               set_bit(ctx->num, &dev->ctx_work_bits);
+               spin_unlock_irqrestore(&dev->condlock, flags);
+       }
+       s5p_mfc_try_run(dev);
+       return 0;
+}
+
+static int s5p_mfc_stop_streaming(struct vb2_queue *q)
+{
+       unsigned long flags;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int aborted = 0;
+
+       if ((ctx->state == MFCINST_FINISHING ||
+               ctx->state ==  MFCINST_RUNNING) &&
+               dev->curr_ctx == ctx->num && dev->hw_lock) {
+               ctx->state = MFCINST_ABORT;
+               s5p_mfc_wait_for_done_ctx(ctx,
+                                       S5P_FIMV_R2H_CMD_FRAME_DONE_RET, 0);
+               aborted = 1;
+       }
+       spin_lock_irqsave(&dev->irqlock, flags);
+       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               INIT_LIST_HEAD(&ctx->dst_queue);
+               ctx->dst_queue_cnt = 0;
+               ctx->dpb_flush_flag = 1;
+               ctx->dec_dst_flag = 0;
+       }
+       if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               INIT_LIST_HEAD(&ctx->src_queue);
+               ctx->src_queue_cnt = 0;
+       }
+       if (aborted)
+               ctx->state = MFCINST_RUNNING;
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       return 0;
+}
+
+
+static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf;
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index];
+               mfc_buf->used = 0;
+               spin_lock_irqsave(&dev->irqlock, flags);
+               list_add_tail(&mfc_buf->list, &ctx->src_queue);
+               ctx->src_queue_cnt++;
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index];
+               mfc_buf->used = 0;
+               /* Mark destination as available for use by MFC */
+               spin_lock_irqsave(&dev->irqlock, flags);
+               set_bit(vb->v4l2_buf.index, &ctx->dec_dst_flag);
+               list_add_tail(&mfc_buf->list, &ctx->dst_queue);
+               ctx->dst_queue_cnt++;
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+       } else {
+               mfc_err("Unsupported buffer type (%d)\n", vq->type);
+       }
+       if (s5p_mfc_ctx_ready(ctx)) {
+               spin_lock_irqsave(&dev->condlock, flags);
+               set_bit(ctx->num, &dev->ctx_work_bits);
+               spin_unlock_irqrestore(&dev->condlock, flags);
+       }
+       s5p_mfc_try_run(dev);
+}
+
+static struct vb2_ops s5p_mfc_dec_qops = {
+       .queue_setup            = s5p_mfc_queue_setup,
+       .wait_prepare           = s5p_mfc_unlock,
+       .wait_finish            = s5p_mfc_lock,
+       .buf_init               = s5p_mfc_buf_init,
+       .start_streaming        = s5p_mfc_start_streaming,
+       .stop_streaming         = s5p_mfc_stop_streaming,
+       .buf_queue              = s5p_mfc_buf_queue,
+};
+
+struct s5p_mfc_codec_ops *get_dec_codec_ops(void)
+{
+       return &decoder_codec_ops;
+}
+
+struct vb2_ops *get_dec_queue_ops(void)
+{
+       return &s5p_mfc_dec_qops;
+}
+
+const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void)
+{
+       return &s5p_mfc_dec_ioctl_ops;
+}
+
+#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2CLASS(x) == V4L2_CTRL_CLASS_MPEG) \
+                                               && V4L2_CTRL_DRIVER_PRIV(x))
+
+int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx)
+{
+       struct v4l2_ctrl_config cfg;
+       int i;
+
+       v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS);
+       if (ctx->ctrl_handler.error) {
+               mfc_err("v4l2_ctrl_handler_init failed\n");
+               return ctx->ctrl_handler.error;
+       }
+
+       for (i = 0; i < NUM_CTRLS; i++) {
+               if (IS_MFC51_PRIV(controls[i].id)) {
+                       cfg.ops = &s5p_mfc_dec_ctrl_ops;
+                       cfg.id = controls[i].id;
+                       cfg.min = controls[i].minimum;
+                       cfg.max = controls[i].maximum;
+                       cfg.def = controls[i].default_value;
+                       cfg.name = controls[i].name;
+                       cfg.type = controls[i].type;
+
+                       cfg.step = controls[i].step;
+                       cfg.menu_skip_mask = 0;
+
+                       ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler,
+                                       &cfg, NULL);
+               } else {
+                       ctx->ctrls[i] = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+                                       &s5p_mfc_dec_ctrl_ops,
+                                       controls[i].id, controls[i].minimum,
+                                       controls[i].maximum, controls[i].step,
+                                       controls[i].default_value);
+               }
+               if (ctx->ctrl_handler.error) {
+                       mfc_err("Adding control (%d) failed\n", i);
+                       return ctx->ctrl_handler.error;
+               }
+               if (controls[i].is_volatile && ctx->ctrls[i])
+                       ctx->ctrls[i]->is_volatile = 1;
+       }
+       return 0;
+}
+
+void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)
+{
+       int i;
+
+       v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+       for (i = 0; i < NUM_CTRLS; i++)
+               ctx->ctrls[i] = NULL;
+}
+
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.h b/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
new file mode 100644 (file)
index 0000000..fb8b215
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+
+#ifndef S5P_MFC_DEC_H_
+#define S5P_MFC_DEC_H_
+
+struct s5p_mfc_codec_ops *get_dec_codec_ops(void);
+struct vb2_ops *get_dec_queue_ops(void);
+const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
+struct s5p_mfc_fmt *get_dec_def_fmt(bool src);
+int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx);
+
+#endif /* S5P_MFC_DEC_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
new file mode 100644 (file)
index 0000000..fee094a
--- /dev/null
@@ -0,0 +1,1829 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Jeongtae Park       <jtp.park@samsung.com>
+ * Kamil Debski                <k.debski@samsung.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/version.h>
+#include <linux/videodev2.h>
+#include <linux/workqueue.h>
+#include <media/v4l2-ctrls.h>
+#include <media/videobuf2-core.h>
+#include "regs-mfc.h"
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_enc.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
+
+static struct s5p_mfc_fmt formats[] = {
+       {
+               .name = "4:2:0 2 Planes 64x32 Tiles",
+               .fourcc = V4L2_PIX_FMT_NV12MT,
+               .codec_mode = S5P_FIMV_CODEC_NONE,
+               .type = MFC_FMT_RAW,
+               .num_planes = 2,
+       },
+       {
+               .name = "4:2:0 2 Planes",
+               .fourcc = V4L2_PIX_FMT_NV12M,
+               .codec_mode = S5P_FIMV_CODEC_NONE,
+               .type = MFC_FMT_RAW,
+               .num_planes = 2,
+       },
+       {
+               .name = "H264 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_H264,
+               .codec_mode = S5P_FIMV_CODEC_H264_ENC,
+               .type = MFC_FMT_ENC,
+               .num_planes = 1,
+       },
+       {
+               .name = "MPEG4 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_MPEG4,
+               .codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
+               .type = MFC_FMT_ENC,
+               .num_planes = 1,
+       },
+       {
+               .name = "H264 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_H263,
+               .codec_mode = S5P_FIMV_CODEC_H263_ENC,
+               .type = MFC_FMT_ENC,
+               .num_planes = 1,
+       },
+};
+
+#define NUM_FORMATS ARRAY_SIZE(formats)
+static struct s5p_mfc_fmt *find_format(struct v4l2_format *f, unsigned int t)
+{
+       unsigned int i;
+
+       for (i = 0; i < NUM_FORMATS; i++) {
+               if (formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
+                   formats[i].type == t)
+                       return &formats[i];
+       }
+       return NULL;
+}
+
+static struct mfc_control controls[] = {
+       {
+               .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
+               .maximum = V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES,
+               .default_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1900,
+               .maximum = (1 << 30) - 1,
+               .step = 1,
+               .default_value = 1900,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Padding Control Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Padding Color YUV Value",
+               .minimum = 0,
+               .maximum = (1 << 25) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_BITRATE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = (1 << 30) - 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Rate Control Reaction Coeff.",
+               .minimum = 1,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .name = "Force frame type",
+               .minimum = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED,
+               .maximum = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED,
+               .default_value = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VBV_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEADER_MODE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
+               .maximum = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+               .default_value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .name = "Frame Skip Enable",
+               .minimum = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED,
+               .maximum = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
+               .menu_skip_mask = 0,
+               .default_value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Fixed Target Bit Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .default_value = 0,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 2,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+               .maximum = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH,
+               .default_value = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+               .menu_skip_mask = ~(
+                               (1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
+                               (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+                               (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)
+                               ),
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+               .maximum = V4L2_MPEG_VIDEO_H264_LEVEL_4_0,
+               .default_value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+               .menu_skip_mask = ~(
+                               (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
+                               (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
+                               (1 << V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
+                               (1 << V4L2_MPEG_VIDEO_H264_LEVEL_5_1)
+                               ),
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
+               .maximum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5,
+               .default_value = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
+               .maximum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY,
+               .default_value = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = -6,
+               .maximum = 6,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = -6,
+               .maximum = 6,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+               .maximum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
+               .default_value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "The Number of Ref. Pic for P",
+               .minimum = 1,
+               .maximum = 2,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 I-Frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 Minimum QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 Maximum QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 P frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 B frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 I-Frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 Minimum QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 Maximum QP value",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 P frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 B frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 Dark Reg Adaptive RC",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 Smooth Reg Adaptive RC",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 Static Reg Adaptive RC",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 Activity Reg Adaptive RC",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED,
+               .maximum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED,
+               .default_value = 0,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
+               .maximum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE,
+               .default_value = 0,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_QPEL,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+};
+
+#define NUM_CTRLS ARRAY_SIZE(controls)
+static const char * const *mfc51_get_menu(u32 id)
+{
+       static const char * const mfc51_video_frame_skip[] = {
+               "Disabled",
+               "Level Limit",
+               "VBV/CPB Limit",
+               NULL,
+       };
+       static const char * const mfc51_video_force_frame[] = {
+               "Disabled",
+               "I Frame",
+               "Not Coded",
+               NULL,
+       };
+       switch (id) {
+       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE:
+               return mfc51_video_frame_skip;
+       case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
+               return mfc51_video_force_frame;
+       }
+       return NULL;
+}
+
+static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
+{
+       mfc_debug(2, "src=%d, dst=%d, state=%d\n",
+                 ctx->src_queue_cnt, ctx->dst_queue_cnt, ctx->state);
+       /* context is ready to make header */
+       if (ctx->state == MFCINST_GOT_INST && ctx->dst_queue_cnt >= 1)
+               return 1;
+       /* context is ready to encode a frame */
+       if (ctx->state == MFCINST_RUNNING &&
+               ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
+               return 1;
+       /* context is ready to encode remain frames */
+       if (ctx->state == MFCINST_FINISHING &&
+               ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
+               return 1;
+       mfc_debug(2, "ctx is not ready\n");
+       return 0;
+}
+
+static void cleanup_ref_queue(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_buf *mb_entry;
+       unsigned long mb_y_addr, mb_c_addr;
+
+       /* move buffers in ref queue to src queue */
+       while (!list_empty(&ctx->ref_queue)) {
+               mb_entry = list_entry((&ctx->ref_queue)->next,
+                                               struct s5p_mfc_buf, list);
+               mb_y_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 0);
+               mb_c_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 1);
+               list_del(&mb_entry->list);
+               ctx->ref_queue_cnt--;
+               list_add_tail(&mb_entry->list, &ctx->src_queue);
+               ctx->src_queue_cnt++;
+       }
+       mfc_debug(2, "enc src count: %d, enc ref count: %d\n",
+                 ctx->src_queue_cnt, ctx->ref_queue_cnt);
+       INIT_LIST_HEAD(&ctx->ref_queue);
+       ctx->ref_queue_cnt = 0;
+}
+
+static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned long dst_addr;
+       unsigned int dst_size;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
+       dst_size = vb2_plane_size(dst_mb->b, 0);
+       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       return 0;
+}
+
+static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned long flags;
+
+       if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) {
+               spin_lock_irqsave(&dev->irqlock, flags);
+               dst_mb = list_entry(ctx->dst_queue.next,
+                               struct s5p_mfc_buf, list);
+               list_del(&dst_mb->list);
+               ctx->dst_queue_cnt--;
+               vb2_set_plane_payload(dst_mb->b, 0,
+                                               s5p_mfc_get_enc_strm_size());
+               vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+       }
+       ctx->state = MFCINST_RUNNING;
+       if (s5p_mfc_ctx_ready(ctx)) {
+               spin_lock_irqsave(&dev->condlock, flags);
+               set_bit(ctx->num, &dev->ctx_work_bits);
+               spin_unlock_irqrestore(&dev->condlock, flags);
+       }
+       s5p_mfc_try_run(dev);
+       return 0;
+}
+
+static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *dst_mb;
+       struct s5p_mfc_buf *src_mb;
+       unsigned long flags;
+       unsigned long src_y_addr, src_c_addr, dst_addr;
+       unsigned int dst_size;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+       src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       src_y_addr = vb2_dma_contig_plane_paddr(src_mb->b, 0);
+       src_c_addr = vb2_dma_contig_plane_paddr(src_mb->b, 1);
+       s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
+       dst_size = vb2_plane_size(dst_mb->b, 0);
+       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+
+       return 0;
+}
+
+static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *mb_entry;
+       unsigned long enc_y_addr, enc_c_addr;
+       unsigned long mb_y_addr, mb_c_addr;
+       int slice_type;
+       unsigned int strm_size;
+       unsigned long flags;
+
+       slice_type = s5p_mfc_get_enc_slice_type();
+       strm_size = s5p_mfc_get_enc_strm_size();
+       mfc_debug(2, "Encoded slice type: %d", slice_type);
+       mfc_debug(2, "Encoded stream size: %d", strm_size);
+       mfc_debug(2, "Display order: %d",
+                 mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT));
+       spin_lock_irqsave(&dev->irqlock, flags);
+       if (slice_type >= 0) {
+               s5p_mfc_get_enc_frame_buffer(ctx, &enc_y_addr, &enc_c_addr);
+               list_for_each_entry(mb_entry, &ctx->src_queue, list) {
+                       mb_y_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 0);
+                       mb_c_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 1);
+                       if ((enc_y_addr == mb_y_addr) &&
+                                               (enc_c_addr == mb_c_addr)) {
+                               list_del(&mb_entry->list);
+                               ctx->src_queue_cnt--;
+                               vb2_buffer_done(mb_entry->b,
+                                                       VB2_BUF_STATE_DONE);
+                               break;
+                       }
+               }
+               list_for_each_entry(mb_entry, &ctx->ref_queue, list) {
+                       mb_y_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 0);
+                       mb_c_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 1);
+                       if ((enc_y_addr == mb_y_addr) &&
+                                               (enc_c_addr == mb_c_addr)) {
+                               list_del(&mb_entry->list);
+                               ctx->ref_queue_cnt--;
+                               vb2_buffer_done(mb_entry->b,
+                                                       VB2_BUF_STATE_DONE);
+                               break;
+                       }
+               }
+       }
+       if ((ctx->src_queue_cnt > 0) && (ctx->state == MFCINST_RUNNING)) {
+               mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
+                                                                       list);
+               if (mb_entry->used) {
+                       list_del(&mb_entry->list);
+                       ctx->src_queue_cnt--;
+                       list_add_tail(&mb_entry->list, &ctx->ref_queue);
+                       ctx->ref_queue_cnt++;
+               }
+               mfc_debug(2, "enc src count: %d, enc ref count: %d\n",
+                         ctx->src_queue_cnt, ctx->ref_queue_cnt);
+       }
+       if (strm_size > 0) {
+               /* at least one more dest. buffers exist always  */
+               mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf,
+                                                                       list);
+               list_del(&mb_entry->list);
+               ctx->dst_queue_cnt--;
+               switch (slice_type) {
+               case S5P_FIMV_ENC_SI_SLICE_TYPE_I:
+                       mb_entry->b->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+                       break;
+               case S5P_FIMV_ENC_SI_SLICE_TYPE_P:
+                       mb_entry->b->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
+                       break;
+               case S5P_FIMV_ENC_SI_SLICE_TYPE_B:
+                       mb_entry->b->v4l2_buf.flags |= V4L2_BUF_FLAG_BFRAME;
+                       break;
+               }
+               vb2_set_plane_payload(mb_entry->b, 0, strm_size);
+               vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE);
+       }
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0)) {
+               spin_lock(&dev->condlock);
+               clear_bit(ctx->num, &dev->ctx_work_bits);
+               spin_unlock(&dev->condlock);
+       }
+       return 0;
+}
+
+static struct s5p_mfc_codec_ops encoder_codec_ops = {
+       .pre_seq_start          = enc_pre_seq_start,
+       .post_seq_start         = enc_post_seq_start,
+       .pre_frame_start        = enc_pre_frame_start,
+       .post_frame_start       = enc_post_frame_start,
+};
+
+/* Query capabilities of the device */
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+
+       strncpy(cap->driver, dev->plat_dev->name, sizeof(cap->driver) - 1);
+       strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
+       cap->bus_info[0] = 0;
+       cap->version = KERNEL_VERSION(1, 0, 0);
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
+                         | V4L2_CAP_VIDEO_OUTPUT
+                         | V4L2_CAP_STREAMING;
+       return 0;
+}
+
+static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out)
+{
+       struct s5p_mfc_fmt *fmt;
+       int i, j = 0;
+
+       for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+               if (mplane && formats[i].num_planes == 1)
+                       continue;
+               else if (!mplane && formats[i].num_planes > 1)
+                       continue;
+               if (out && formats[i].type != MFC_FMT_RAW)
+                       continue;
+               else if (!out && formats[i].type != MFC_FMT_ENC)
+                       continue;
+               if (j == f->index) {
+                       fmt = &formats[i];
+                       strlcpy(f->description, fmt->name,
+                               sizeof(f->description));
+                       f->pixelformat = fmt->fourcc;
+                       return 0;
+               }
+               ++j;
+       }
+       return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return vidioc_enum_fmt(f, false, false);
+}
+
+static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
+                                         struct v4l2_fmtdesc *f)
+{
+       return vidioc_enum_fmt(f, true, false);
+}
+
+static int vidioc_enum_fmt_vid_out(struct file *file, void *prov,
+                                  struct v4l2_fmtdesc *f)
+{
+       return vidioc_enum_fmt(f, false, true);
+}
+
+static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
+                                         struct v4l2_fmtdesc *f)
+{
+       return vidioc_enum_fmt(f, true, true);
+}
+
+static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+       mfc_debug(2, "f->type = %d ctx->state = %d\n", f->type, ctx->state);
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               /* This is run on output (encoder dest) */
+               pix_fmt_mp->width = 0;
+               pix_fmt_mp->height = 0;
+               pix_fmt_mp->field = V4L2_FIELD_NONE;
+               pix_fmt_mp->pixelformat = ctx->dst_fmt->fourcc;
+               pix_fmt_mp->num_planes = ctx->dst_fmt->num_planes;
+
+               pix_fmt_mp->plane_fmt[0].bytesperline = ctx->enc_dst_buf_size;
+               pix_fmt_mp->plane_fmt[0].sizeimage = ctx->enc_dst_buf_size;
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               /* This is run on capture (encoder src) */
+               pix_fmt_mp->width = ctx->img_width;
+               pix_fmt_mp->height = ctx->img_height;
+
+               pix_fmt_mp->field = V4L2_FIELD_NONE;
+               pix_fmt_mp->pixelformat = ctx->src_fmt->fourcc;
+               pix_fmt_mp->num_planes = ctx->src_fmt->num_planes;
+
+               pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
+               pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
+               pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
+               pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
+       } else {
+               mfc_err("invalid buf type\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_fmt *fmt;
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               fmt = find_format(f, MFC_FMT_ENC);
+               if (!fmt) {
+                       mfc_err("failed to try output format\n");
+                       return -EINVAL;
+               }
+
+               if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) {
+                       mfc_err("must be set encoding output size\n");
+                       return -EINVAL;
+               }
+
+               pix_fmt_mp->plane_fmt[0].bytesperline =
+                       pix_fmt_mp->plane_fmt[0].sizeimage;
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               fmt = find_format(f, MFC_FMT_RAW);
+               if (!fmt) {
+                       mfc_err("failed to try output format\n");
+                       return -EINVAL;
+               }
+
+               if (fmt->num_planes != pix_fmt_mp->num_planes) {
+                       mfc_err("failed to try output format\n");
+                       return -EINVAL;
+               }
+       } else {
+               mfc_err("invalid buf type\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct s5p_mfc_fmt *fmt;
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+       unsigned long flags;
+       int ret = 0;
+
+       ret = vidioc_try_fmt(file, priv, f);
+       if (ret)
+               return ret;
+       if (ctx->vq_src.streaming || ctx->vq_dst.streaming) {
+               v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
+               ret = -EBUSY;
+               goto out;
+       }
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               fmt = find_format(f, MFC_FMT_ENC);
+               if (!fmt) {
+                       mfc_err("failed to set capture format\n");
+                       return -EINVAL;
+               }
+               ctx->state = MFCINST_INIT;
+               ctx->dst_fmt = fmt;
+               ctx->codec_mode = ctx->dst_fmt->codec_mode;
+               ctx->enc_dst_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage;
+               pix_fmt_mp->plane_fmt[0].bytesperline = 0;
+               ctx->dst_bufs_cnt = 0;
+               ctx->capture_state = QUEUE_FREE;
+               s5p_mfc_alloc_instance_buffer(ctx);
+               spin_lock_irqsave(&dev->condlock, flags);
+               set_bit(ctx->num, &dev->ctx_work_bits);
+               spin_unlock_irqrestore(&dev->condlock, flags);
+               s5p_mfc_clean_ctx_int_flags(ctx);
+               s5p_mfc_try_run(dev);
+               if (s5p_mfc_wait_for_done_ctx(ctx, \
+                               S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 1)) {
+                               /* Error or timeout */
+                       mfc_err("Error getting instance from hardware\n");
+                       s5p_mfc_release_instance_buffer(ctx);
+                       ret = -EIO;
+                       goto out;
+               }
+               mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               fmt = find_format(f, MFC_FMT_RAW);
+               if (!fmt) {
+                       mfc_err("failed to set output format\n");
+                       return -EINVAL;
+               }
+               if (fmt->num_planes != pix_fmt_mp->num_planes) {
+                       mfc_err("failed to set output format\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+               ctx->src_fmt = fmt;
+               ctx->img_width = pix_fmt_mp->width;
+               ctx->img_height = pix_fmt_mp->height;
+               mfc_debug(2, "codec number: %d\n", ctx->src_fmt->codec_mode);
+               mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n",
+                       pix_fmt_mp->width, pix_fmt_mp->height,
+                       ctx->img_width, ctx->img_height);
+               if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
+                       ctx->buf_width = ALIGN(ctx->img_width,
+                                                       S5P_FIMV_NV12M_HALIGN);
+                       ctx->luma_size = ALIGN(ctx->img_width,
+                               S5P_FIMV_NV12M_HALIGN) * ALIGN(ctx->img_height,
+                               S5P_FIMV_NV12M_LVALIGN);
+                       ctx->chroma_size = ALIGN(ctx->img_width,
+                               S5P_FIMV_NV12M_HALIGN) * ALIGN((ctx->img_height
+                               >> 1), S5P_FIMV_NV12M_CVALIGN);
+
+                       ctx->luma_size = ALIGN(ctx->luma_size,
+                                                       S5P_FIMV_NV12M_SALIGN);
+                       ctx->chroma_size = ALIGN(ctx->chroma_size,
+                                                       S5P_FIMV_NV12M_SALIGN);
+
+                       pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
+                       pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
+                       pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
+                       pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
+
+               } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
+                       ctx->buf_width = ALIGN(ctx->img_width,
+                                                       S5P_FIMV_NV12MT_HALIGN);
+                       ctx->luma_size = ALIGN(ctx->img_width,
+                               S5P_FIMV_NV12MT_HALIGN) * ALIGN(ctx->img_height,
+                               S5P_FIMV_NV12MT_VALIGN);
+                       ctx->chroma_size = ALIGN(ctx->img_width,
+                               S5P_FIMV_NV12MT_HALIGN) * ALIGN((ctx->img_height
+                               >> 1), S5P_FIMV_NV12MT_VALIGN);
+                       ctx->luma_size = ALIGN(ctx->luma_size,
+                                                       S5P_FIMV_NV12MT_SALIGN);
+                       ctx->chroma_size = ALIGN(ctx->chroma_size,
+                                                       S5P_FIMV_NV12MT_SALIGN);
+
+                       pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
+                       pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
+                       pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
+                       pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
+               }
+               ctx->src_bufs_cnt = 0;
+               ctx->output_state = QUEUE_FREE;
+       } else {
+               mfc_err("invalid buf type\n");
+               return -EINVAL;
+       }
+out:
+       mfc_debug_leave();
+       return ret;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                                         struct v4l2_requestbuffers *reqbufs)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret = 0;
+
+       /* if memory is not mmp or userptr return error */
+       if ((reqbufs->memory != V4L2_MEMORY_MMAP) &&
+               (reqbufs->memory != V4L2_MEMORY_USERPTR))
+               return -EINVAL;
+       if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               if (ctx->capture_state != QUEUE_FREE) {
+                       mfc_err("invalid capture state: %d\n",
+                                                       ctx->capture_state);
+                       return -EINVAL;
+               }
+               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+               if (ret != 0) {
+                       mfc_err("error in vb2_reqbufs() for E(D)\n");
+                       return ret;
+               }
+               ctx->capture_state = QUEUE_BUFS_REQUESTED;
+               ret = s5p_mfc_alloc_codec_buffers(ctx);
+               if (ret) {
+                       mfc_err("Failed to allocate encoding buffers\n");
+                       reqbufs->count = 0;
+                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                       return -ENOMEM;
+               }
+       } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (ctx->output_state != QUEUE_FREE) {
+                       mfc_err("invalid output state: %d\n",
+                                                       ctx->output_state);
+                       return -EINVAL;
+               }
+               ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+               if (ret != 0) {
+                       mfc_err("error in vb2_reqbufs() for E(S)\n");
+                       return ret;
+               }
+               ctx->output_state = QUEUE_BUFS_REQUESTED;
+       } else {
+               mfc_err("invalid buf type\n");
+               return -EINVAL;
+       }
+       return ret;
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                                                  struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret = 0;
+
+       /* if memory is not mmp or userptr return error */
+       if ((buf->memory != V4L2_MEMORY_MMAP) &&
+               (buf->memory != V4L2_MEMORY_USERPTR))
+               return -EINVAL;
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               if (ctx->state != MFCINST_GOT_INST) {
+                       mfc_err("invalid context state: %d\n", ctx->state);
+                       return -EINVAL;
+               }
+               ret = vb2_querybuf(&ctx->vq_dst, buf);
+               if (ret != 0) {
+                       mfc_err("error in vb2_querybuf() for E(D)\n");
+                       return ret;
+               }
+               buf->m.planes[0].m.mem_offset += DST_QUEUE_OFF_BASE;
+       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ret = vb2_querybuf(&ctx->vq_src, buf);
+               if (ret != 0) {
+                       mfc_err("error in vb2_querybuf() for E(S)\n");
+                       return ret;
+               }
+       } else {
+               mfc_err("invalid buf type\n");
+               return -EINVAL;
+       }
+       return ret;
+}
+
+/* Queue a buffer */
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (ctx->state == MFCINST_ERROR) {
+               mfc_err("Call on QBUF after unrecoverable error\n");
+               return -EIO;
+       }
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_qbuf(&ctx->vq_src, buf);
+       else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_qbuf(&ctx->vq_dst, buf);
+       return -EINVAL;
+}
+
+/* Dequeue a buffer */
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (ctx->state == MFCINST_ERROR) {
+               mfc_err("Call on DQBUF after unrecoverable error\n");
+               return -EIO;
+       }
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
+       else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
+       return -EINVAL;
+}
+
+/* Stream on */
+static int vidioc_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type type)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_streamon(&ctx->vq_src, type);
+       else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_streamon(&ctx->vq_dst, type);
+       return -EINVAL;
+}
+
+/* Stream off, which equals to a pause */
+static int vidioc_streamoff(struct file *file, void *priv,
+                           enum v4l2_buf_type type)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_streamoff(&ctx->vq_src, type);
+       else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_streamoff(&ctx->vq_dst, type);
+       return -EINVAL;
+}
+
+static inline int h264_level(enum v4l2_mpeg_video_h264_level lvl)
+{
+       static unsigned int t[V4L2_MPEG_VIDEO_H264_LEVEL_4_0 + 1] = {
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_1_0   */ 10,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_1B    */ 9,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_1_1   */ 11,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_1_2   */ 12,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_1_3   */ 13,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_2_0   */ 20,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_2_1   */ 21,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_2_2   */ 22,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_3_0   */ 30,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_3_1   */ 31,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_3_2   */ 32,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_4_0   */ 40,
+       };
+       return t[lvl];
+}
+
+static inline int mpeg4_level(enum v4l2_mpeg_video_mpeg4_level lvl)
+{
+       static unsigned int t[V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 + 1] = {
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0    */ 0,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B   */ 9,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_1    */ 1,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_2    */ 2,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_3    */ 3,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B   */ 7,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_4    */ 4,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_5    */ 5,
+       };
+       return t[lvl];
+}
+
+static inline int vui_sar_idc(enum v4l2_mpeg_video_h264_vui_sar_idc sar)
+{
+       static unsigned int t[V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED + 1] = {
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED     */ 0,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1             */ 1,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_12x11           */ 2,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_10x11           */ 3,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_16x11           */ 4,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_40x33           */ 5,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_24x11           */ 6,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_20x11           */ 7,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_32x11           */ 8,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_80x33           */ 9,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_18x11           */ 10,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_15x11           */ 11,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_64x33           */ 12,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_160x99          */ 13,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_4x3             */ 14,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_3x2             */ 15,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1             */ 16,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED        */ 255,
+       };
+       return t[sar];
+}
+
+static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               p->gop_size = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
+               p->slice_mode = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
+               p->slice_mb = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
+               p->slice_bit = ctrl->val * 8;
+               break;
+       case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
+               p->intra_refresh_mb = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_PADDING:
+               p->pad = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV:
+               p->pad_luma = (ctrl->val >> 16) & 0xff;
+               p->pad_cb = (ctrl->val >> 8) & 0xff;
+               p->pad_cr = (ctrl->val >> 0) & 0xff;
+               break;
+       case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
+               p->rc_frame = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               p->rc_bitrate = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF:
+               p->rc_reaction_coeff = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
+               ctx->force_frame_type = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VBV_SIZE:
+               p->vbv_size = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE:
+               p->codec.h264.cpb_size = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+               p->seq_hdr_mode = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE:
+               p->frame_skip_mode = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT:
+               p->fixed_target_bit = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               p->num_b_frame = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+               switch (ctrl->val) {
+               case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+                       p->codec.h264.profile =
+                                       S5P_FIMV_ENC_PROFILE_H264_MAIN;
+                       break;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
+                       p->codec.h264.profile =
+                                       S5P_FIMV_ENC_PROFILE_H264_HIGH;
+                       break;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+                       p->codec.h264.profile =
+                               S5P_FIMV_ENC_PROFILE_H264_BASELINE;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+               p->codec.h264.level_v4l2 = ctrl->val;
+               p->codec.h264.level = h264_level(ctrl->val);
+               if (p->codec.h264.level < 0) {
+                       mfc_err("Level number is wrong\n");
+                       ret = p->codec.h264.level;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+               p->codec.mpeg4.level_v4l2 = ctrl->val;
+               p->codec.mpeg4.level = mpeg4_level(ctrl->val);
+               if (p->codec.mpeg4.level < 0) {
+                       mfc_err("Level number is wrong\n");
+                       ret = p->codec.mpeg4.level;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
+               p->codec.h264.loop_filter_mode = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
+               p->codec.h264.loop_filter_alpha = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
+               p->codec.h264.loop_filter_beta = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+               p->codec.h264.entropy_mode = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P:
+               p->codec.h264.num_ref_pic_4p = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
+               p->codec.h264._8x8_transform = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
+               p->codec.h264.rc_mb = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+               p->codec.h264.rc_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+               p->codec.h264.rc_min_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+               p->codec.h264.rc_max_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+               p->codec.h264.rc_p_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+               p->codec.h264.rc_b_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+       case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
+               p->codec.mpeg4.rc_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+       case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+               p->codec.mpeg4.rc_min_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+       case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+               p->codec.mpeg4.rc_max_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+       case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
+               p->codec.mpeg4.rc_p_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
+       case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
+               p->codec.mpeg4.rc_b_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK:
+               p->codec.h264.rc_mb_dark = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH:
+               p->codec.h264.rc_mb_smooth = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC:
+               p->codec.h264.rc_mb_static = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY:
+               p->codec.h264.rc_mb_activity = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
+               p->codec.h264.vui_sar = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
+               p->codec.h264.vui_sar_idc = vui_sar_idc(ctrl->val);
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:
+               p->codec.h264.vui_ext_sar_width = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:
+               p->codec.h264.vui_ext_sar_height = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+               p->codec.h264.open_gop = !ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
+               p->codec.h264.open_gop_size = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
+               switch (ctrl->val) {
+               case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
+                       p->codec.mpeg4.profile =
+                               S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE;
+                       break;
+               case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE:
+                       p->codec.mpeg4.profile =
+                       S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
+               p->codec.mpeg4.quarter_pixel = ctrl->val;
+               break;
+       default:
+               v4l2_err(&dev->v4l2_dev, "Invalid control, id=%d, val=%d\n",
+                                                       ctrl->id, ctrl->val);
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static const struct v4l2_ctrl_ops s5p_mfc_enc_ctrl_ops = {
+       .s_ctrl = s5p_mfc_enc_s_ctrl,
+};
+
+int vidioc_s_parm(struct file *file, void *priv, struct v4l2_streamparm *a)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ctx->enc_params.rc_framerate_num =
+                                       a->parm.output.timeperframe.denominator;
+               ctx->enc_params.rc_framerate_denom =
+                                       a->parm.output.timeperframe.numerator;
+       } else {
+               mfc_err("Setting FPS is only possible for the output queue\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+int vidioc_g_parm(struct file *file, void *priv, struct v4l2_streamparm *a)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               a->parm.output.timeperframe.denominator =
+                                       ctx->enc_params.rc_framerate_num;
+               a->parm.output.timeperframe.numerator =
+                                       ctx->enc_params.rc_framerate_denom;
+       } else {
+               mfc_err("Setting FPS is only possible for the output queue\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
+       .vidioc_querycap = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
+       .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
+       .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
+       .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt,
+       .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt,
+       .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,
+       .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,
+       .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt,
+       .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt,
+       .vidioc_reqbufs = vidioc_reqbufs,
+       .vidioc_querybuf = vidioc_querybuf,
+       .vidioc_qbuf = vidioc_qbuf,
+       .vidioc_dqbuf = vidioc_dqbuf,
+       .vidioc_streamon = vidioc_streamon,
+       .vidioc_streamoff = vidioc_streamoff,
+       .vidioc_s_parm = vidioc_s_parm,
+       .vidioc_g_parm = vidioc_g_parm,
+};
+
+static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
+{
+       int i;
+
+       if (!fmt)
+               return -EINVAL;
+       if (fmt->num_planes != vb->num_planes) {
+               mfc_err("invalid plane number for the format\n");
+               return -EINVAL;
+       }
+       for (i = 0; i < fmt->num_planes; i++) {
+               if (!vb2_dma_contig_plane_paddr(vb, i)) {
+                       mfc_err("failed to get plane cookie\n");
+                       return -EINVAL;
+               }
+               mfc_debug(2, "index: %d, plane[%d] cookie: 0x%08zx",
+                               vb->v4l2_buf.index, i,
+                               vb2_dma_contig_plane_paddr(vb, i));
+       }
+       return 0;
+}
+
+static int s5p_mfc_queue_setup(struct vb2_queue *vq,
+                      unsigned int *buf_count, unsigned int *plane_count,
+                      unsigned long psize[], void *allocators[])
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+
+       if (ctx->state != MFCINST_GOT_INST) {
+               mfc_err("inavlid state: %d\n", ctx->state);
+               return -EINVAL;
+       }
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               if (ctx->dst_fmt)
+                       *plane_count = ctx->dst_fmt->num_planes;
+               else
+                       *plane_count = MFC_ENC_CAP_PLANE_COUNT;
+               if (*buf_count < 1)
+                       *buf_count = 1;
+               if (*buf_count > MFC_MAX_BUFFERS)
+                       *buf_count = MFC_MAX_BUFFERS;
+               psize[0] = ctx->enc_dst_buf_size;
+               allocators[0] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (ctx->src_fmt)
+                       *plane_count = ctx->src_fmt->num_planes;
+               else
+                       *plane_count = MFC_ENC_OUT_PLANE_COUNT;
+
+               if (*buf_count < 1)
+                       *buf_count = 1;
+               if (*buf_count > MFC_MAX_BUFFERS)
+                       *buf_count = MFC_MAX_BUFFERS;
+               psize[0] = ctx->luma_size;
+               psize[1] = ctx->chroma_size;
+               allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+               allocators[1] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+       } else {
+               mfc_err("inavlid queue type: %d\n", vq->type);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void s5p_mfc_unlock(struct vb2_queue *q)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mutex_unlock(&dev->mfc_mutex);
+}
+
+static void s5p_mfc_lock(struct vb2_queue *q)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mutex_lock(&dev->mfc_mutex);
+}
+
+static int s5p_mfc_buf_init(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       unsigned int i;
+       int ret;
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               ret = check_vb_with_fmt(ctx->dst_fmt, vb);
+               if (ret < 0)
+                       return ret;
+               i = vb->v4l2_buf.index;
+               ctx->dst_bufs[i].b = vb;
+               ctx->dst_bufs[i].cookie.stream =
+                                       vb2_dma_contig_plane_paddr(vb, 0);
+               ctx->dst_bufs_cnt++;
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ret = check_vb_with_fmt(ctx->src_fmt, vb);
+               if (ret < 0)
+                       return ret;
+               i = vb->v4l2_buf.index;
+               ctx->src_bufs[i].b = vb;
+               ctx->src_bufs[i].cookie.raw.luma =
+                                       vb2_dma_contig_plane_paddr(vb, 0);
+               ctx->src_bufs[i].cookie.raw.chroma =
+                                       vb2_dma_contig_plane_paddr(vb, 1);
+               ctx->src_bufs_cnt++;
+       } else {
+               mfc_err("inavlid queue type: %d\n", vq->type);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_buf_prepare(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       int ret;
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               ret = check_vb_with_fmt(ctx->dst_fmt, vb);
+               if (ret < 0)
+                       return ret;
+               mfc_debug(2, "plane size: %ld, dst size: %d\n",
+                       vb2_plane_size(vb, 0), ctx->enc_dst_buf_size);
+               if (vb2_plane_size(vb, 0) < ctx->enc_dst_buf_size) {
+                       mfc_err("plane size is too small for capture\n");
+                       return -EINVAL;
+               }
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ret = check_vb_with_fmt(ctx->src_fmt, vb);
+               if (ret < 0)
+                       return ret;
+               mfc_debug(2, "plane size: %ld, luma size: %d\n",
+                       vb2_plane_size(vb, 0), ctx->luma_size);
+               mfc_debug(2, "plane size: %ld, chroma size: %d\n",
+                       vb2_plane_size(vb, 1), ctx->chroma_size);
+               if (vb2_plane_size(vb, 0) < ctx->luma_size ||
+                   vb2_plane_size(vb, 1) < ctx->chroma_size) {
+                       mfc_err("plane size is too small for output\n");
+                       return -EINVAL;
+               }
+       } else {
+               mfc_err("inavlid queue type: %d\n", vq->type);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_start_streaming(struct vb2_queue *q)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+
+       v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
+       /* If context is ready then dev = work->data;schedule it to run */
+       if (s5p_mfc_ctx_ready(ctx)) {
+               spin_lock_irqsave(&dev->condlock, flags);
+               set_bit(ctx->num, &dev->ctx_work_bits);
+               spin_unlock_irqrestore(&dev->condlock, flags);
+       }
+       s5p_mfc_try_run(dev);
+       return 0;
+}
+
+static int s5p_mfc_stop_streaming(struct vb2_queue *q)
+{
+       unsigned long flags;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       if ((ctx->state == MFCINST_FINISHING ||
+               ctx->state == MFCINST_RUNNING) &&
+               dev->curr_ctx == ctx->num && dev->hw_lock) {
+               ctx->state = MFCINST_ABORT;
+               s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_FRAME_DONE_RET,
+                                         0);
+       }
+       ctx->state = MFCINST_FINISHED;
+       spin_lock_irqsave(&dev->irqlock, flags);
+       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               INIT_LIST_HEAD(&ctx->dst_queue);
+               ctx->dst_queue_cnt = 0;
+       }
+       if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               cleanup_ref_queue(ctx);
+               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               INIT_LIST_HEAD(&ctx->src_queue);
+               ctx->src_queue_cnt = 0;
+       }
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       return 0;
+}
+
+static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf;
+
+       if (ctx->state == MFCINST_ERROR) {
+               vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+               cleanup_ref_queue(ctx);
+               return;
+       }
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index];
+               mfc_buf->used = 0;
+               /* Mark destination as available for use by MFC */
+               spin_lock_irqsave(&dev->irqlock, flags);
+               list_add_tail(&mfc_buf->list, &ctx->dst_queue);
+               ctx->dst_queue_cnt++;
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index];
+               mfc_buf->used = 0;
+               spin_lock_irqsave(&dev->irqlock, flags);
+               if (vb->v4l2_planes[0].bytesused == 0) {
+                       mfc_debug(1, "change state to FINISHING\n");
+                       ctx->state = MFCINST_FINISHING;
+                       vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+                       cleanup_ref_queue(ctx);
+               } else {
+                       list_add_tail(&mfc_buf->list, &ctx->src_queue);
+                       ctx->src_queue_cnt++;
+               }
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+       } else {
+               mfc_err("unsupported buffer type (%d)\n", vq->type);
+       }
+       if (s5p_mfc_ctx_ready(ctx)) {
+               spin_lock_irqsave(&dev->condlock, flags);
+               set_bit(ctx->num, &dev->ctx_work_bits);
+               spin_unlock_irqrestore(&dev->condlock, flags);
+       }
+       s5p_mfc_try_run(dev);
+}
+
+static struct vb2_ops s5p_mfc_enc_qops = {
+       .queue_setup            = s5p_mfc_queue_setup,
+       .wait_prepare           = s5p_mfc_unlock,
+       .wait_finish            = s5p_mfc_lock,
+       .buf_init               = s5p_mfc_buf_init,
+       .buf_prepare            = s5p_mfc_buf_prepare,
+       .start_streaming        = s5p_mfc_start_streaming,
+       .stop_streaming         = s5p_mfc_stop_streaming,
+       .buf_queue              = s5p_mfc_buf_queue,
+};
+
+struct s5p_mfc_codec_ops *get_enc_codec_ops(void)
+{
+       return &encoder_codec_ops;
+}
+
+struct vb2_ops *get_enc_queue_ops(void)
+{
+       return &s5p_mfc_enc_qops;
+}
+
+const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void)
+{
+       return &s5p_mfc_enc_ioctl_ops;
+}
+
+#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2CLASS(x) == V4L2_CTRL_CLASS_MPEG) \
+                                               && V4L2_CTRL_DRIVER_PRIV(x))
+
+int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx)
+{
+       struct v4l2_ctrl_config cfg;
+       int i;
+
+       v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS);
+       if (ctx->ctrl_handler.error) {
+               mfc_err("v4l2_ctrl_handler_init failed\n");
+               return ctx->ctrl_handler.error;
+       }
+       for (i = 0; i < NUM_CTRLS; i++) {
+               if (IS_MFC51_PRIV(controls[i].id)) {
+                       cfg.ops = &s5p_mfc_enc_ctrl_ops;
+                       cfg.id = controls[i].id;
+                       cfg.min = controls[i].minimum;
+                       cfg.max = controls[i].maximum;
+                       cfg.def = controls[i].default_value;
+                       cfg.name = controls[i].name;
+                       cfg.type = controls[i].type;
+                       cfg.flags = 0;
+
+                       if (cfg.type == V4L2_CTRL_TYPE_MENU) {
+                               cfg.step = 0;
+                               cfg.menu_skip_mask = cfg.menu_skip_mask;
+                               cfg.qmenu = mfc51_get_menu(cfg.id);
+                       } else {
+                               cfg.step = controls[i].step;
+                               cfg.menu_skip_mask = 0;
+                       }
+                       ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler,
+                                       &cfg, NULL);
+               } else {
+                       if (controls[i].type == V4L2_CTRL_TYPE_MENU) {
+                               ctx->ctrls[i] = v4l2_ctrl_new_std_menu(
+                                       &ctx->ctrl_handler,
+                                       &s5p_mfc_enc_ctrl_ops, controls[i].id,
+                                       controls[i].maximum, 0,
+                                       controls[i].default_value);
+                       } else {
+                               ctx->ctrls[i] = v4l2_ctrl_new_std(
+                                       &ctx->ctrl_handler,
+                                       &s5p_mfc_enc_ctrl_ops, controls[i].id,
+                                       controls[i].minimum,
+                                       controls[i].maximum, controls[i].step,
+                                       controls[i].default_value);
+                       }
+               }
+               if (ctx->ctrl_handler.error) {
+                       mfc_err("Adding control (%d) failed\n", i);
+                       return ctx->ctrl_handler.error;
+               }
+               if (controls[i].is_volatile && ctx->ctrls[i])
+                       ctx->ctrls[i]->is_volatile = 1;
+       }
+       return 0;
+}
+
+void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx)
+{
+       int i;
+
+       v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+       for (i = 0; i < NUM_CTRLS; i++)
+               ctx->ctrls[i] = NULL;
+}
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
new file mode 100644 (file)
index 0000000..405bdd3
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+
+#ifndef S5P_MFC_ENC_H_
+#define S5P_MFC_ENC_H_
+
+struct s5p_mfc_codec_ops *get_enc_codec_ops(void);
+struct vb2_ops *get_enc_queue_ops(void);
+const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
+struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
+int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
+
+#endif /* S5P_MFC_ENC_H_  */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
new file mode 100644 (file)
index 0000000..8f2f8bf
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * drivers/media/video/samsung/mfc5/s5p_mfc_intr.c
+ *
+ * C file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains functions used to wait for command completion.
+ *
+ * Kamil Debski, Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.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/delay.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include "regs-mfc.h"
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+
+int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
+{
+       int ret;
+
+       ret = wait_event_interruptible_timeout(dev->queue,
+               (dev->int_cond && (dev->int_type == command
+               || dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
+               msecs_to_jiffies(MFC_INT_TIMEOUT));
+       if (ret == 0) {
+               mfc_err("Interrupt (dev->int_type:%d, command:%d) timed out\n",
+                                                       dev->int_type, command);
+               return 1;
+       } else if (ret == -ERESTARTSYS) {
+               mfc_err("Interrupted by a signal\n");
+               return 1;
+       }
+       mfc_debug(1, "Finished waiting (dev->int_type:%d, command: %d)\n",
+                                                       dev->int_type, command);
+       if (dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
+               return 1;
+       return 0;
+}
+
+void s5p_mfc_clean_dev_int_flags(struct s5p_mfc_dev *dev)
+{
+       dev->int_cond = 0;
+       dev->int_type = 0;
+       dev->int_err = 0;
+}
+
+int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
+                                   int command, int interrupt)
+{
+       int ret;
+
+       if (interrupt) {
+               ret = wait_event_interruptible_timeout(ctx->queue,
+                               (ctx->int_cond && (ctx->int_type == command
+                       || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
+                                       msecs_to_jiffies(MFC_INT_TIMEOUT));
+       } else {
+               ret = wait_event_timeout(ctx->queue,
+                               (ctx->int_cond && (ctx->int_type == command
+                       || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
+                                       msecs_to_jiffies(MFC_INT_TIMEOUT));
+       }
+       if (ret == 0) {
+               mfc_err("Interrupt (ctx->int_type:%d, command:%d) timed out\n",
+                                                       ctx->int_type, command);
+               return 1;
+       } else if (ret == -ERESTARTSYS) {
+               mfc_err("Interrupted by a signal\n");
+               return 1;
+       }
+       mfc_debug(1, "Finished waiting (ctx->int_type:%d, command: %d)\n",
+                                                       ctx->int_type, command);
+       if (ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
+               return 1;
+       return 0;
+}
+
+void s5p_mfc_clean_ctx_int_flags(struct s5p_mfc_ctx *ctx)
+{
+       ctx->int_cond = 0;
+       ctx->int_type = 0;
+       ctx->int_err = 0;
+}
+
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_intr.h b/drivers/media/video/s5p-mfc/s5p_mfc_intr.h
new file mode 100644 (file)
index 0000000..122d773
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * drivers/media/video/samsung/mfc5/s5p_mfc_intr.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * It contains waiting functions declarations.
+ *
+ * Kamil Debski, Copyright (C) 2011 Samsung Electronics
+ * http://www.samsung.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 S5P_MFC_INTR_H_
+#define S5P_MFC_INTR_H_
+
+#include "s5p_mfc_common.h"
+
+int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
+                             int command, int interrupt);
+int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command);
+void s5p_mfc_clean_ctx_int_flags(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_clean_dev_int_flags(struct s5p_mfc_dev *dev);
+
+#endif /* S5P_MFC_INTR_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
new file mode 100644 (file)
index 0000000..7b23916
--- /dev/null
@@ -0,0 +1,1397 @@
+/*
+ * drivers/media/video/samsung/mfc5/s5p_mfc_opr.c
+ *
+ * Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains hw related functions.
+ *
+ * Kamil Debski, Copyright (c) 2011 Samsung Electronics
+ * http://www.samsung.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 "regs-mfc.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_ctrl.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_shm.h"
+#include <asm/cacheflush.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#define OFFSETA(x)             (((x) - dev->bank1) >> MFC_OFFSET_SHIFT)
+#define OFFSETB(x)             (((x) - dev->bank2) >> MFC_OFFSET_SHIFT)
+
+/* Allocate temporary buffers for decoding */
+int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
+{
+       void *desc_virt;
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       ctx->desc_buf = vb2_dma_contig_memops.alloc(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
+       if (IS_ERR_VALUE((int)ctx->desc_buf)) {
+               ctx->desc_buf = 0;
+               mfc_err("Allocating DESC buffer failed\n");
+               return -ENOMEM;
+       }
+       ctx->desc_phys = s5p_mfc_mem_cookie(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
+       BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
+       if (desc_virt == NULL) {
+               vb2_dma_contig_memops.put(ctx->desc_buf);
+               ctx->desc_phys = 0;
+               ctx->desc_buf = 0;
+               mfc_err("Remapping DESC buffer failed\n");
+               return -ENOMEM;
+       }
+       memset(desc_virt, 0, DESC_BUF_SIZE);
+       wmb();
+       return 0;
+}
+
+/* Release temporary buffers for decoding */
+void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->desc_phys) {
+               vb2_dma_contig_memops.put(ctx->desc_buf);
+               ctx->desc_phys = 0;
+               ctx->desc_buf = 0;
+       }
+}
+
+/* Allocate codec buffers */
+int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int enc_ref_y_size = 0;
+       unsigned int enc_ref_c_size = 0;
+       unsigned int guard_width, guard_height;
+
+       if (ctx->type == MFCINST_DECODER) {
+               mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
+                         ctx->luma_size, ctx->chroma_size, ctx->mv_size);
+               mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
+       } else if (ctx->type == MFCINST_ENCODER) {
+               enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+               enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
+
+               if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
+                       enc_ref_c_size = ALIGN(ctx->img_width,
+                                               S5P_FIMV_NV12MT_HALIGN)
+                                               * ALIGN(ctx->img_height >> 1,
+                                               S5P_FIMV_NV12MT_VALIGN);
+                       enc_ref_c_size = ALIGN(enc_ref_c_size,
+                                                       S5P_FIMV_NV12MT_SALIGN);
+               } else {
+                       guard_width = ALIGN(ctx->img_width + 16,
+                                                       S5P_FIMV_NV12MT_HALIGN);
+                       guard_height = ALIGN((ctx->img_height >> 1) + 4,
+                                                       S5P_FIMV_NV12MT_VALIGN);
+                       enc_ref_c_size = ALIGN(guard_width * guard_height,
+                                              S5P_FIMV_NV12MT_SALIGN);
+               }
+               mfc_debug(2, "recon luma size: %d chroma size: %d\n",
+                         enc_ref_y_size, enc_ref_c_size);
+       } else {
+               return -EINVAL;
+       }
+       /* Codecs have different memory requirements */
+       switch (ctx->codec_mode) {
+       case S5P_FIMV_CODEC_H264_DEC:
+               ctx->bank1_size =
+                   ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
+                                       S5P_FIMV_DEC_VERT_NB_MV_SIZE,
+                                       S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size;
+               break;
+       case S5P_FIMV_CODEC_MPEG4_DEC:
+               ctx->bank1_size =
+                   ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
+                                    S5P_FIMV_DEC_UPNB_MV_SIZE +
+                                    S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+                                    S5P_FIMV_DEC_STX_PARSER_SIZE +
+                                    S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
+                                    S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2_size = 0;
+               break;
+       case S5P_FIMV_CODEC_VC1RCV_DEC:
+       case S5P_FIMV_CODEC_VC1_DEC:
+               ctx->bank1_size =
+                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
+                            S5P_FIMV_DEC_UPNB_MV_SIZE +
+                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+                            S5P_FIMV_DEC_NB_DCAC_SIZE +
+                            3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
+                            S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2_size = 0;
+               break;
+       case S5P_FIMV_CODEC_MPEG2_DEC:
+               ctx->bank1_size = 0;
+               ctx->bank2_size = 0;
+               break;
+       case S5P_FIMV_CODEC_H263_DEC:
+               ctx->bank1_size =
+                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
+                            S5P_FIMV_DEC_UPNB_MV_SIZE +
+                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+                            S5P_FIMV_DEC_NB_DCAC_SIZE,
+                            S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2_size = 0;
+               break;
+       case S5P_FIMV_CODEC_H264_ENC:
+               ctx->bank1_size = (enc_ref_y_size * 2) +
+                                  S5P_FIMV_ENC_UPMV_SIZE +
+                                  S5P_FIMV_ENC_COLFLG_SIZE +
+                                  S5P_FIMV_ENC_INTRAMD_SIZE +
+                                  S5P_FIMV_ENC_NBORINFO_SIZE;
+               ctx->bank2_size = (enc_ref_y_size * 2) +
+                                  (enc_ref_c_size * 4) +
+                                  S5P_FIMV_ENC_INTRAPRED_SIZE;
+               break;
+       case S5P_FIMV_CODEC_MPEG4_ENC:
+               ctx->bank1_size = (enc_ref_y_size * 2) +
+                                  S5P_FIMV_ENC_UPMV_SIZE +
+                                  S5P_FIMV_ENC_COLFLG_SIZE +
+                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               ctx->bank2_size = (enc_ref_y_size * 2) +
+                                  (enc_ref_c_size * 4);
+               break;
+       case S5P_FIMV_CODEC_H263_ENC:
+               ctx->bank1_size = (enc_ref_y_size * 2) +
+                                  S5P_FIMV_ENC_UPMV_SIZE +
+                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               ctx->bank2_size = (enc_ref_y_size * 2) +
+                                  (enc_ref_c_size * 4);
+               break;
+       default:
+               break;
+       }
+       /* Allocate only if memory from bank 1 is necessary */
+       if (ctx->bank1_size > 0) {
+               ctx->bank1_buf = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
+               if (IS_ERR(ctx->bank1_buf)) {
+                       ctx->bank1_buf = 0;
+                       printk(KERN_ERR
+                              "Buf alloc for decoding failed (port A)\n");
+                       return -ENOMEM;
+               }
+               ctx->bank1_phys = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
+               BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       }
+       /* Allocate only if memory from bank 2 is necessary */
+       if (ctx->bank2_size > 0) {
+               ctx->bank2_buf = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size);
+               if (IS_ERR(ctx->bank2_buf)) {
+                       ctx->bank2_buf = 0;
+                       mfc_err("Buf alloc for decoding failed (port B)\n");
+                       return -ENOMEM;
+               }
+               ctx->bank2_phys = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf);
+               BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
+       }
+       return 0;
+}
+
+/* Release buffers allocated for codec */
+void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->bank1_buf) {
+               vb2_dma_contig_memops.put(ctx->bank1_buf);
+               ctx->bank1_buf = 0;
+               ctx->bank1_phys = 0;
+               ctx->bank1_size = 0;
+       }
+       if (ctx->bank2_buf) {
+               vb2_dma_contig_memops.put(ctx->bank2_buf);
+               ctx->bank2_buf = 0;
+               ctx->bank2_phys = 0;
+               ctx->bank2_size = 0;
+       }
+}
+
+/* Allocate memory for instance data buffer */
+int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
+{
+       void *context_virt;
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
+               ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
+               ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
+       else
+               ctx->ctx_size = MFC_CTX_BUF_SIZE;
+       ctx->ctx_buf = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
+       if (IS_ERR(ctx->ctx_buf)) {
+               mfc_err("Allocating context buffer failed\n");
+               ctx->ctx_phys = 0;
+               ctx->ctx_buf = 0;
+               return -ENOMEM;
+       }
+       ctx->ctx_phys = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
+       BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
+       context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
+       if (context_virt == NULL) {
+               mfc_err("Remapping instance buffer failed\n");
+               vb2_dma_contig_memops.put(ctx->ctx_buf);
+               ctx->ctx_phys = 0;
+               ctx->ctx_buf = 0;
+               return -ENOMEM;
+       }
+       /* Zero content of the allocated memory */
+       memset(context_virt, 0, ctx->ctx_size);
+       wmb();
+       if (s5p_mfc_init_shm(ctx) < 0) {
+               vb2_dma_contig_memops.put(ctx->ctx_buf);
+               ctx->ctx_phys = 0;
+               ctx->ctx_buf = 0;
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+/* Release instance buffer */
+void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->ctx_buf) {
+               vb2_dma_contig_memops.put(ctx->ctx_buf);
+               ctx->ctx_phys = 0;
+               ctx->ctx_buf = 0;
+       }
+       if (ctx->shm_alloc) {
+               vb2_dma_contig_memops.put(ctx->shm_alloc);
+               ctx->shm_alloc = 0;
+               ctx->shm = 0;
+       }
+}
+
+/* Set registers for decoding temporary buffers */
+void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
+       mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
+}
+
+/* Set registers for shared buffer */
+void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
+}
+
+/* Set registers for decoding stream buffer */
+int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
+                 unsigned int start_num_byte, unsigned int buf_size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
+       mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
+       mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
+       s5p_mfc_write_shm(ctx, start_num_byte, START_BYTE_NUM);
+       return 0;
+}
+
+/* Set decoding frame buffer */
+int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int frame_size, i;
+       unsigned int frame_size_ch, frame_size_mv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int dpb;
+       size_t buf_addr1, buf_addr2;
+       int buf_size1, buf_size2;
+
+       buf_addr1 = ctx->bank1_phys;
+       buf_size1 = ctx->bank1_size;
+       buf_addr2 = ctx->bank2_phys;
+       buf_size2 = ctx->bank2_size;
+       dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
+                                               ~S5P_FIMV_DPB_COUNT_MASK;
+       mfc_write(dev, ctx->total_dpb_count | dpb,
+                                               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+       s5p_mfc_set_shared_buffer(ctx);
+       switch (ctx->codec_mode) {
+       case S5P_FIMV_CODEC_H264_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                               S5P_FIMV_H264_VERT_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
+               break;
+       case S5P_FIMV_CODEC_MPEG4_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
+               buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR);
+               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               break;
+       case S5P_FIMV_CODEC_H263_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
+               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+               break;
+       case S5P_FIMV_CODEC_VC1_DEC:
+       case S5P_FIMV_CODEC_VC1RCV_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
+               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               break;
+       case S5P_FIMV_CODEC_MPEG2_DEC:
+               break;
+       default:
+               mfc_err("Unknown codec for decoding (%x)\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+               break;
+       }
+       frame_size = ctx->luma_size;
+       frame_size_ch = ctx->chroma_size;
+       frame_size_mv = ctx->mv_size;
+       mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size, frame_size_ch,
+                                                               frame_size_mv);
+       for (i = 0; i < ctx->total_dpb_count; i++) {
+               /* Bank2 */
+               mfc_debug(2, "Luma %d: %x\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.luma);
+               mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
+                                               S5P_FIMV_DEC_LUMA_ADR + i * 4);
+               mfc_debug(2, "\tChroma %d: %x\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.chroma);
+               mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
+                                              S5P_FIMV_DEC_CHROMA_ADR + i * 4);
+               if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
+                       mfc_debug(2, "\tBuf2: %x, size: %d\n",
+                                                       buf_addr2, buf_size2);
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                                               S5P_FIMV_H264_MV_ADR + i * 4);
+                       buf_addr2 += frame_size_mv;
+                       buf_size2 -= frame_size_mv;
+               }
+       }
+       mfc_debug(2, "Buf1: %u, buf_size1: %d\n", buf_addr1, buf_size1);
+       mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
+                       buf_size1,  buf_size2, ctx->total_dpb_count);
+       if (buf_size1 < 0 || buf_size2 < 0) {
+               mfc_debug(2, "Not enough memory has been allocated\n");
+               return -ENOMEM;
+       }
+       s5p_mfc_write_shm(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
+       s5p_mfc_write_shm(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
+       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC)
+               s5p_mfc_write_shm(ctx, frame_size_mv, ALLOC_MV_SIZE);
+       mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
+                                       << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
+                                               S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+/* Set registers for encoding stream buffer */
+int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
+               unsigned long addr, unsigned int size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
+       mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
+       return 0;
+}
+
+void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+               unsigned long y_addr, unsigned long c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
+       mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
+}
+
+void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+               unsigned long *y_addr, unsigned long *c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR)
+                                                       << MFC_OFFSET_SHIFT);
+       *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR)
+                                                       << MFC_OFFSET_SHIFT);
+}
+
+/* Set encoding ref & codec buffer */
+int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       size_t buf_addr1, buf_addr2;
+       size_t buf_size1, buf_size2;
+       unsigned int enc_ref_y_size, enc_ref_c_size;
+       unsigned int guard_width, guard_height;
+       int i;
+
+       buf_addr1 = ctx->bank1_phys;
+       buf_size1 = ctx->bank1_size;
+       buf_addr2 = ctx->bank2_phys;
+       buf_size2 = ctx->bank2_size;
+       enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+               * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+       enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
+       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
+               enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
+               enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN);
+       } else {
+               guard_width = ALIGN(ctx->img_width + 16,
+                                               S5P_FIMV_NV12MT_HALIGN);
+               guard_height = ALIGN((ctx->img_height >> 1) + 4,
+                                               S5P_FIMV_NV12MT_VALIGN);
+               enc_ref_c_size = ALIGN(guard_width * guard_height,
+                                      S5P_FIMV_NV12MT_SALIGN);
+       }
+       mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", buf_size1, buf_size2);
+       switch (ctx->codec_mode) {
+       case S5P_FIMV_CODEC_H264_ENC:
+               for (i = 0; i < 2; i++) {
+                       mfc_write(dev, OFFSETA(buf_addr1),
+                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+                       buf_addr1 += enc_ref_y_size;
+                       buf_size1 -= enc_ref_y_size;
+
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_y_size;
+                       buf_size2 -= enc_ref_y_size;
+               }
+               for (i = 0; i < 4; i++) {
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_c_size;
+                       buf_size2 -= enc_ref_c_size;
+               }
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
+               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                       S5P_FIMV_H264_COZERO_FLAG_ADR);
+               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                       S5P_FIMV_H264_UP_INTRA_MD_ADR);
+               buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
+               mfc_write(dev, OFFSETB(buf_addr2),
+                                       S5P_FIMV_H264_UP_INTRA_PRED_ADR);
+               buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
+               buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                       S5P_FIMV_H264_NBOR_INFO_ADR);
+               buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
+               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
+                       buf_size1, buf_size2);
+               break;
+       case S5P_FIMV_CODEC_MPEG4_ENC:
+               for (i = 0; i < 2; i++) {
+                       mfc_write(dev, OFFSETA(buf_addr1),
+                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+                       buf_addr1 += enc_ref_y_size;
+                       buf_size1 -= enc_ref_y_size;
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_y_size;
+                       buf_size2 -= enc_ref_y_size;
+               }
+               for (i = 0; i < 4; i++) {
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_c_size;
+                       buf_size2 -= enc_ref_c_size;
+               }
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
+               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                               S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
+               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                               S5P_FIMV_MPEG4_ACDC_COEF_ADR);
+               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
+                       buf_size1, buf_size2);
+               break;
+       case S5P_FIMV_CODEC_H263_ENC:
+               for (i = 0; i < 2; i++) {
+                       mfc_write(dev, OFFSETA(buf_addr1),
+                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+                       buf_addr1 += enc_ref_y_size;
+                       buf_size1 -= enc_ref_y_size;
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_y_size;
+                       buf_size2 -= enc_ref_y_size;
+               }
+               for (i = 0; i < 4; i++) {
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_c_size;
+                       buf_size2 -= enc_ref_c_size;
+               }
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
+               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR);
+               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
+                       buf_size1, buf_size2);
+               break;
+       default:
+               mfc_err("Unknown codec set for encoding: %d\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       unsigned int reg;
+       unsigned int shm;
+
+       /* width */
+       mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
+       /* height */
+       mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
+       /* pictype : enable, IDR period */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       reg |= (1 << 18);
+       reg &= ~(0xFFFF);
+       reg |= p->gop_size;
+       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
+       /* multi-slice control */
+       /* multi-slice MB number or bit size */
+       mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
+       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+               mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
+       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+               mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
+       } else {
+               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
+               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
+       }
+       /* cyclic intra refresh */
+       mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
+       /* memory structure cur. frame */
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
+               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
+       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
+               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
+       /* padding control & value */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
+       if (p->pad) {
+               /** enable */
+               reg |= (1 << 31);
+               /** cr value */
+               reg &= ~(0xFF << 16);
+               reg |= (p->pad_cr << 16);
+               /** cb value */
+               reg &= ~(0xFF << 8);
+               reg |= (p->pad_cb << 8);
+               /** y value */
+               reg &= ~(0xFF);
+               reg |= (p->pad_luma);
+       } else {
+               /** disable & all value clear */
+               reg = 0;
+       }
+       mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /** frame-level rate control */
+       reg &= ~(0x1 << 9);
+       reg |= (p->rc_frame << 9);
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* bit rate */
+       if (p->rc_frame)
+               mfc_write(dev, p->rc_bitrate,
+                       S5P_FIMV_ENC_RC_BIT_RATE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
+       /* reaction coefficient */
+       if (p->rc_frame)
+               mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
+       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
+       /* seq header ctrl */
+       shm &= ~(0x1 << 3);
+       shm |= (p->seq_hdr_mode << 3);
+       /* frame skip mode */
+       shm &= ~(0x3 << 1);
+       shm |= (p->frame_skip_mode << 1);
+       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
+       /* fixed target bit */
+       s5p_mfc_write_shm(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
+       unsigned int reg;
+       unsigned int shm;
+
+       s5p_mfc_set_enc_params(ctx);
+       /* pictype : number of B */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* num_b_frame - 0 ~ 2 */
+       reg &= ~(0x3 << 16);
+       reg |= (p->num_b_frame << 16);
+       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* profile & level */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
+       /* level */
+       reg &= ~(0xFF << 8);
+       reg |= (p_264->level << 8);
+       /* profile - 0 ~ 2 */
+       reg &= ~(0x3F);
+       reg |= p_264->profile;
+       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
+       /* interlace  */
+       mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
+       /* height */
+       if (p->interlace)
+               mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
+       /* loopfilter ctrl */
+       mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
+       /* loopfilter alpha offset */
+       if (p_264->loop_filter_alpha < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_264->loop_filter_alpha) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_264->loop_filter_alpha & 0xF);
+       }
+       mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
+       /* loopfilter beta offset */
+       if (p_264->loop_filter_beta < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_264->loop_filter_beta) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_264->loop_filter_beta & 0xF);
+       }
+       mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
+       /* entropy coding mode */
+       if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
+               mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
+       /* number of ref. picture */
+       reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
+       /* num of ref. pictures of P */
+       reg &= ~(0x3 << 5);
+       reg |= (p_264->num_ref_pic_4p << 5);
+       /* max number of ref. pictures */
+       reg &= ~(0x1F);
+       reg |= p_264->max_ref_pic;
+       mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
+       /* 8x8 transform enable */
+       mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /* macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= (p_264->rc_mb << 8);
+       /* frame QP */
+       reg &= ~(0x3F);
+       reg |= p_264->rc_frame_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_denom)
+               mfc_write(dev, p->rc_framerate_num * 1000
+                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+       /* max & min value of QP */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+       /* max QP */
+       reg &= ~(0x3F << 8);
+       reg |= (p_264->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0x3F);
+       reg |= p_264->rc_min_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+       /* macroblock adaptive scaling features */
+       if (p_264->rc_mb) {
+               reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
+               /* dark region */
+               reg &= ~(0x1 << 3);
+               reg |= (p_264->rc_mb_dark << 3);
+               /* smooth region */
+               reg &= ~(0x1 << 2);
+               reg |= (p_264->rc_mb_smooth << 2);
+               /* static region */
+               reg &= ~(0x1 << 1);
+               reg |= (p_264->rc_mb_static << 1);
+               /* high activity region */
+               reg &= ~(0x1);
+               reg |= p_264->rc_mb_activity;
+               mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
+       }
+       if (!p->rc_frame &&
+           !p_264->rc_mb) {
+               shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
+               shm &= ~(0xFFF);
+               shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
+               shm |= (p_264->rc_p_frame_qp & 0x3F);
+               s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
+       }
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
+       /* AR VUI control */
+       shm &= ~(0x1 << 15);
+       shm |= (p_264->vui_sar << 1);
+       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
+       if (p_264->vui_sar) {
+               /* aspect ration IDC */
+               shm = s5p_mfc_read_shm(ctx, SAMPLE_ASPECT_RATIO_IDC);
+               shm &= ~(0xFF);
+               shm |= p_264->vui_sar_idc;
+               s5p_mfc_write_shm(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
+               if (p_264->vui_sar_idc == 0xFF) {
+                       /* sample  AR info */
+                       shm = s5p_mfc_read_shm(ctx, EXTENDED_SAR);
+                       shm &= ~(0xFFFFFFFF);
+                       shm |= p_264->vui_ext_sar_width << 16;
+                       shm |= p_264->vui_ext_sar_height;
+                       s5p_mfc_write_shm(ctx, shm, EXTENDED_SAR);
+               }
+       }
+       /* intra picture period for H.264 */
+       shm = s5p_mfc_read_shm(ctx, H264_I_PERIOD);
+       /* control */
+       shm &= ~(0x1 << 16);
+       shm |= (p_264->open_gop << 16);
+       /* value */
+       if (p_264->open_gop) {
+               shm &= ~(0xFFFF);
+               shm |= p_264->open_gop_size;
+       }
+       s5p_mfc_write_shm(ctx, shm, H264_I_PERIOD);
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               shm &= ~(0xFFFF << 16);
+               shm |= (p_264->cpb_size << 16);
+       }
+       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
+       unsigned int reg;
+       unsigned int shm;
+       unsigned int framerate;
+
+       s5p_mfc_set_enc_params(ctx);
+       /* pictype : number of B */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* num_b_frame - 0 ~ 2 */
+       reg &= ~(0x3 << 16);
+       reg |= (p->num_b_frame << 16);
+       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* profile & level */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
+       /* level */
+       reg &= ~(0xFF << 8);
+       reg |= (p_mpeg4->level << 8);
+       /* profile - 0 ~ 2 */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->profile;
+       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
+       /* quarter_pixel */
+       mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
+       /* qp */
+       if (!p->rc_frame) {
+               shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
+               shm &= ~(0xFFF);
+               shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
+               shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
+               s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
+       }
+       /* frame rate */
+       if (p->rc_frame) {
+               if (p->rc_framerate_denom > 0) {
+                       framerate = p->rc_framerate_num * 1000 /
+                                               p->rc_framerate_denom;
+                       mfc_write(dev, framerate,
+                               S5P_FIMV_ENC_RC_FRAME_RATE);
+                       shm = s5p_mfc_read_shm(ctx, RC_VOP_TIMING);
+                       shm &= ~(0xFFFFFFFF);
+                       shm |= (1 << 31);
+                       shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
+                       shm |= (p->rc_framerate_denom & 0xFFFF);
+                       s5p_mfc_write_shm(ctx, shm, RC_VOP_TIMING);
+               }
+       } else {
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+       }
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /* frame QP */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->rc_frame_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* max & min value of QP */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+       /* max QP */
+       reg &= ~(0x3F << 8);
+       reg |= (p_mpeg4->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->rc_min_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               shm &= ~(0xFFFF << 16);
+               shm |= (p->vbv_size << 16);
+       }
+       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
+       unsigned int reg;
+       unsigned int shm;
+
+       s5p_mfc_set_enc_params(ctx);
+       /* qp */
+       if (!p->rc_frame) {
+               shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
+               shm &= ~(0xFFF);
+               shm |= (p_h263->rc_p_frame_qp & 0x3F);
+               s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
+       }
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_denom)
+               mfc_write(dev, p->rc_framerate_num * 1000
+                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /* frame QP */
+       reg &= ~(0x3F);
+       reg |= p_h263->rc_frame_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* max & min value of QP */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+       /* max QP */
+       reg &= ~(0x3F << 8);
+       reg |= (p_h263->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0x3F);
+       reg |= p_h263->rc_min_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               shm &= ~(0xFFFF << 16);
+               shm |= (p->vbv_size << 16);
+       }
+       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
+       return 0;
+}
+
+/* Initialize decoding */
+int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       s5p_mfc_set_shared_buffer(ctx);
+       /* Setup loop filter, for decoding this is only valid for MPEG4 */
+       if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_DEC)
+               mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
+       mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
+               S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
+               S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
+               S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
+               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+       mfc_write(dev,
+       ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
+                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int dpb;
+
+       if (flush)
+               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
+                       S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
+       else
+               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
+                       ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
+       mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+}
+
+/* Decode a single frame */
+int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
+                                       enum s5p_mfc_decode_arg last_frame)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
+       s5p_mfc_set_shared_buffer(ctx);
+       s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
+       /* Issue different commands to instance basing on whether it
+        * is the last frame or not. */
+       switch (last_frame) {
+       case MFC_DEC_FRAME:
+               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) <<
+               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+               break;
+       case MFC_DEC_LAST_FRAME:
+               mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
+               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+               break;
+       case MFC_DEC_RES_CHANGE:
+               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
+               S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
+               S5P_FIMV_SI_CH0_INST_ID);
+               break;
+       }
+       mfc_debug(2, "Decoding a usual frame\n");
+       return 0;
+}
+
+int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
+               s5p_mfc_set_enc_params_h264(ctx);
+       else if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_ENC)
+               s5p_mfc_set_enc_params_mpeg4(ctx);
+       else if (ctx->codec_mode == S5P_FIMV_CODEC_H263_ENC)
+               s5p_mfc_set_enc_params_h263(ctx);
+       else {
+               mfc_err("Unknown codec for encoding (%x)\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+       s5p_mfc_set_shared_buffer(ctx);
+       mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
+               (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+/* Encode a single frame */
+int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       /* memory structure cur. frame */
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
+               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
+       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
+               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
+       s5p_mfc_set_shared_buffer(ctx);
+       mfc_write(dev, (S5P_FIMV_CH_FRAME_START << 16 & 0x70000) |
+               (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
+{
+       unsigned long flags;
+       int new_ctx;
+       int cnt;
+
+       spin_lock_irqsave(&dev->condlock, flags);
+       new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
+       cnt = 0;
+       while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
+               new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
+               if (++cnt > MFC_NUM_CONTEXTS) {
+                       /* No contexts to run */
+                       spin_unlock_irqrestore(&dev->condlock, flags);
+                       return -EAGAIN;
+               }
+       }
+       spin_unlock_irqrestore(&dev->condlock, flags);
+       return new_ctx;
+}
+
+static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       s5p_mfc_set_dec_stream_buffer(ctx, 0, 0, 0);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_decode_one_frame(ctx, MFC_DEC_RES_CHANGE);
+}
+
+static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *temp_vb;
+       unsigned long flags;
+       unsigned int index;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+       /* Frames are being decoded */
+       if (list_empty(&ctx->src_queue)) {
+               mfc_debug(2, "No src buffers\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+       /* Get the next source buffer */
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       temp_vb->used = 1;
+       s5p_mfc_set_dec_stream_buffer(ctx,
+               vb2_dma_contig_plane_paddr(temp_vb->b, 0), ctx->consumed_stream,
+                                       temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       index = temp_vb->b->v4l2_buf.index;
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
+               last_frame = MFC_DEC_LAST_FRAME;
+               mfc_debug(2, "Setting ctx->state to FINISHING\n");
+               ctx->state = MFCINST_FINISHING;
+       }
+       s5p_mfc_decode_one_frame(ctx, last_frame);
+       return 0;
+}
+
+static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *dst_mb;
+       struct s5p_mfc_buf *src_mb;
+       unsigned long src_y_addr, src_c_addr, dst_addr;
+       unsigned int dst_size;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+       if (list_empty(&ctx->src_queue)) {
+               mfc_debug(2, "no src buffers\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+       if (list_empty(&ctx->dst_queue)) {
+               mfc_debug(2, "no dst buffers\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+       src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       src_mb->used = 1;
+       src_y_addr = vb2_dma_contig_plane_paddr(src_mb->b, 0);
+       src_c_addr = vb2_dma_contig_plane_paddr(src_mb->b, 1);
+       s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_mb->used = 1;
+       dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
+       dst_size = vb2_plane_size(dst_mb->b, 0);
+       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_encode_one_frame(ctx);
+       return 0;
+}
+
+static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *temp_vb;
+
+       /* Initializing decoding - parsing header */
+       spin_lock_irqsave(&dev->irqlock, flags);
+       mfc_debug(2, "Preparing to init decoding\n");
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       s5p_mfc_set_dec_desc_buffer(ctx);
+       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+       s5p_mfc_set_dec_stream_buffer(ctx,
+                               vb2_dma_contig_plane_paddr(temp_vb->b, 0),
+                               0, temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_init_decode(ctx);
+}
+
+static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned long dst_addr;
+       unsigned int dst_size;
+
+       s5p_mfc_set_enc_ref_buffer(ctx);
+       spin_lock_irqsave(&dev->irqlock, flags);
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
+       dst_size = vb2_plane_size(dst_mb->b, 0);
+       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_init_encode(ctx);
+}
+
+static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *temp_vb;
+       int ret;
+
+       /*
+        * Header was parsed now starting processing
+        * First set the output frame buffers
+        */
+       if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
+               mfc_err("It seems that not all destionation buffers were "
+                       "mmaped\nMFC requires that all destination are mmaped "
+                       "before starting processing\n");
+               return -EAGAIN;
+       }
+       spin_lock_irqsave(&dev->irqlock, flags);
+       if (list_empty(&ctx->src_queue)) {
+               mfc_err("Header has been deallocated in the middle of"
+                       " initialization\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EIO;
+       }
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+       s5p_mfc_set_dec_stream_buffer(ctx,
+                               vb2_dma_contig_plane_paddr(temp_vb->b, 0),
+                               0, temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       ret = s5p_mfc_set_dec_frame_buffer(ctx);
+       if (ret) {
+               mfc_err("Failed to alloc frame mem\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+/* Try running an operation on hardware */
+void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx *ctx;
+       int new_ctx;
+       unsigned int ret = 0;
+
+       if (test_bit(0, &dev->enter_suspend)) {
+               mfc_debug(1, "Entering suspend so do not schedule any jobs\n");
+               return;
+       }
+       /* Check whether hardware is not running */
+       if (test_and_set_bit(0, &dev->hw_lock) != 0) {
+               /* This is perfectly ok, the scheduled ctx should wait */
+               mfc_debug(1, "Couldn't lock HW\n");
+               return;
+       }
+       /* Choose the context to run */
+       new_ctx = s5p_mfc_get_new_ctx(dev);
+       if (new_ctx < 0) {
+               /* No contexts to run */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
+                       mfc_err("Failed to unlock hardware\n");
+                       return;
+               }
+               mfc_debug(1, "No ctx is scheduled to be run\n");
+               return;
+       }
+       ctx = dev->ctx[new_ctx];
+       /* Got context to run in ctx */
+       /*
+        * Last frame has already been sent to MFC.
+        * Now obtaining frames from MFC buffer
+        */
+       s5p_mfc_clock_on();
+       if (ctx->type == MFCINST_DECODER) {
+               s5p_mfc_set_dec_desc_buffer(ctx);
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
+                       break;
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
+                       break;
+               case MFCINST_INIT:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_open_inst_cmd(ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_close_inst_cmd(ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               case MFCINST_HEAD_PARSED:
+                       ret = s5p_mfc_run_init_dec_buffers(ctx);
+                       mfc_debug(1, "head parsed\n");
+                       break;
+               case MFCINST_RES_CHANGE_INIT:
+                       s5p_mfc_run_res_change(ctx);
+                       break;
+               case MFCINST_RES_CHANGE_FLUSH:
+                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
+                       break;
+               case MFCINST_RES_CHANGE_END:
+                       mfc_debug(2, "Finished remaining frames after resolution change\n");
+                       ctx->capture_state = QUEUE_FREE;
+                       mfc_debug(2, "Will re-init the codec\n");
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else if (ctx->type == MFCINST_ENCODER) {
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_enc_frame(ctx);
+                       break;
+               case MFCINST_INIT:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_open_inst_cmd(ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_close_inst_cmd(ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_enc(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else {
+               mfc_err("Invalid context type: %d\n", ctx->type);
+               ret = -EAGAIN;
+       }
+
+       if (ret) {
+               /* Free hardware lock */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                       mfc_err("Failed to unlock hardware\n");
+
+               /* This is in deed imporant, as no operation has been
+                * scheduled, reduce the clock count as no one will
+                * ever do this, because no interrupt related to this try_run
+                * will ever come from hardware. */
+               s5p_mfc_clock_off();
+       }
+}
+
+
+void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
+{
+       struct s5p_mfc_buf *b;
+       int i;
+
+       while (!list_empty(lh)) {
+               b = list_entry(lh->next, struct s5p_mfc_buf, list);
+               for (i = 0; i < b->b->num_planes; i++)
+                       vb2_set_plane_payload(b->b, i, 0);
+               vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
+               list_del(&b->list);
+       }
+}
+
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.h b/drivers/media/video/s5p-mfc/s5p_mfc_opr.h
new file mode 100644 (file)
index 0000000..db83836
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * drivers/media/video/samsung/mfc5/s5p_mfc_opr.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * Contains declarations of hw related functions.
+ *
+ * Kamil Debski, Copyright (C) 2011 Samsung Electronics
+ * http://www.samsung.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 S5P_MFC_OPR_H_
+#define S5P_MFC_OPR_H_
+
+#include "s5p_mfc_common.h"
+
+int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_init_encode(struct s5p_mfc_ctx *mfc_ctx);
+
+/* Decoding functions */
+int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
+                                                 unsigned int start_num_byte,
+                                                 unsigned int buf_size);
+
+/* Encoding functions */
+void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+               unsigned long y_addr, unsigned long c_addr);
+int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
+               unsigned long addr, unsigned int size);
+void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+               unsigned long *y_addr, unsigned long *c_addr);
+int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *mfc_ctx);
+
+int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
+                                       enum s5p_mfc_decode_arg last_frame);
+int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *mfc_ctx);
+
+/* Memory allocation */
+int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
+
+int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
+
+int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
+
+void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
+void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
+
+#define s5p_mfc_get_dspl_y_adr()       (readl(dev->regs_base + \
+                                       S5P_FIMV_SI_DISPLAY_Y_ADR) << \
+                                       MFC_OFFSET_SHIFT)
+#define s5p_mfc_get_dec_y_adr()                (readl(dev->regs_base + \
+                                       S5P_FIMV_SI_DISPLAY_Y_ADR) << \
+                                       MFC_OFFSET_SHIFT)
+#define s5p_mfc_get_dspl_status()      readl(dev->regs_base + \
+                                               S5P_FIMV_SI_DISPLAY_STATUS)
+#define s5p_mfc_get_frame_type()       (readl(dev->regs_base + \
+                                               S5P_FIMV_DECODE_FRAME_TYPE) \
+                                       & S5P_FIMV_DECODE_FRAME_MASK)
+#define s5p_mfc_get_consumed_stream()  readl(dev->regs_base + \
+                                               S5P_FIMV_SI_CONSUMED_BYTES)
+#define s5p_mfc_get_int_reason()       (readl(dev->regs_base + \
+                                       S5P_FIMV_RISC2HOST_CMD) & \
+                                       S5P_FIMV_RISC2HOST_CMD_MASK)
+#define s5p_mfc_get_int_err()          readl(dev->regs_base + \
+                                               S5P_FIMV_RISC2HOST_ARG2)
+#define s5p_mfc_err_dec(x)             (((x) & S5P_FIMV_ERR_DEC_MASK) >> \
+                                                       S5P_FIMV_ERR_DEC_SHIFT)
+#define s5p_mfc_err_dspl(x)            (((x) & S5P_FIMV_ERR_DSPL_MASK) >> \
+                                                       S5P_FIMV_ERR_DSPL_SHIFT)
+#define s5p_mfc_get_img_width()                readl(dev->regs_base + \
+                                               S5P_FIMV_SI_HRESOL)
+#define s5p_mfc_get_img_height()       readl(dev->regs_base + \
+                                               S5P_FIMV_SI_VRESOL)
+#define s5p_mfc_get_dpb_count()                readl(dev->regs_base + \
+                                               S5P_FIMV_SI_BUF_NUMBER)
+#define s5p_mfc_get_inst_no()          readl(dev->regs_base + \
+                                               S5P_FIMV_RISC2HOST_ARG1)
+#define s5p_mfc_get_enc_strm_size()    readl(dev->regs_base + \
+                                               S5P_FIMV_ENC_SI_STRM_SIZE)
+#define s5p_mfc_get_enc_slice_type()   readl(dev->regs_base + \
+                                               S5P_FIMV_ENC_SI_SLICE_TYPE)
+
+#endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
new file mode 100644 (file)
index 0000000..f6a3035
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#ifdef CONFIG_PM_RUNTIME
+#include <linux/pm_runtime.h>
+#endif
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_pm.h"
+
+#define MFC_CLKNAME            "sclk_mfc"
+#define MFC_GATE_CLK_NAME      "mfc"
+
+#define CLK_DEBUG
+
+static struct s5p_mfc_pm *pm;
+static struct s5p_mfc_dev *p_dev;
+
+#ifdef CLK_DEBUG
+atomic_t clk_ref;
+#endif
+
+int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
+{
+       int ret = 0;
+
+       pm = &dev->pm;
+       p_dev = dev;
+       pm->clock_gate = clk_get(&dev->plat_dev->dev, MFC_GATE_CLK_NAME);
+       if (IS_ERR(pm->clock_gate)) {
+               mfc_err("Failed to get clock-gating control\n");
+               ret = -ENOENT;
+               goto err_g_ip_clk;
+       }
+       pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME);
+       if (IS_ERR(pm->clock)) {
+               mfc_err("Failed to get MFC clock\n");
+               ret = -ENOENT;
+               goto err_g_ip_clk_2;
+       }
+       atomic_set(&pm->power, 0);
+#ifdef CONFIG_PM_RUNTIME
+       pm->device = &dev->plat_dev->dev;
+       pm_runtime_enable(pm->device);
+#endif
+#ifdef CLK_DEBUG
+       atomic_set(&clk_ref, 0);
+#endif
+       return 0;
+err_g_ip_clk_2:
+       clk_put(pm->clock_gate);
+err_g_ip_clk:
+       return ret;
+}
+
+void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
+{
+       clk_put(pm->clock_gate);
+       clk_put(pm->clock);
+#ifdef CONFIG_PM_RUNTIME
+       pm_runtime_disable(pm->device);
+#endif
+}
+
+int s5p_mfc_clock_on(void)
+{
+       int ret;
+#ifdef CLK_DEBUG
+       atomic_inc(&clk_ref);
+       mfc_debug(3, "+ %d", atomic_read(&clk_ref));
+#endif
+       ret = clk_enable(pm->clock_gate);
+       return ret;
+}
+
+void s5p_mfc_clock_off(void)
+{
+#ifdef CLK_DEBUG
+       atomic_dec(&clk_ref);
+       mfc_debug(3, "- %d", atomic_read(&clk_ref));
+#endif
+       clk_disable(pm->clock_gate);
+}
+
+int s5p_mfc_power_on(void)
+{
+#ifdef CONFIG_PM_RUNTIME
+       return pm_runtime_get_sync(pm->device);
+#else
+       atomic_set(&pm->power, 1);
+       return 0;
+#endif
+}
+
+int s5p_mfc_power_off(void)
+{
+#ifdef CONFIG_PM_RUNTIME
+       return pm_runtime_put_sync(pm->device);
+#else
+       atomic_set(&pm->power, 0);
+       return 0;
+#endif
+}
+
+
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_pm.h b/drivers/media/video/s5p-mfc/s5p_mfc_pm.h
new file mode 100644 (file)
index 0000000..5107914
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_pm.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+
+#ifndef S5P_MFC_PM_H_
+#define S5P_MFC_PM_H_
+
+int s5p_mfc_init_pm(struct s5p_mfc_dev *dev);
+void s5p_mfc_final_pm(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_clock_on(void);
+void s5p_mfc_clock_off(void);
+int s5p_mfc_power_on(void);
+int s5p_mfc_power_off(void);
+
+#endif /* S5P_MFC_PM_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.c b/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
new file mode 100644 (file)
index 0000000..91fdbac
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+
+#ifdef CONFIG_ARCH_EXYNOS4
+#include <linux/dma-mapping.h>
+#endif
+#include <linux/io.h>
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+
+int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       void *shm_alloc_ctx = dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+
+       ctx->shm_alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
+                                                       SHARED_BUF_SIZE);
+       if (IS_ERR(ctx->shm_alloc)) {
+               mfc_err("failed to allocate shared memory\n");
+               return PTR_ERR(ctx->shm_alloc);
+       }
+       /* shm_ofs only keeps the offset from base (port a) */
+       ctx->shm_ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm_alloc)
+                                                               - dev->bank1;
+       BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
+       if (!ctx->shm) {
+               vb2_dma_contig_memops.put(ctx->shm_alloc);
+               ctx->shm_ofs = 0;
+               ctx->shm_alloc = NULL;
+               mfc_err("failed to virt addr of shared memory\n");
+               return -ENOMEM;
+       }
+       memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
+       wmb();
+       return 0;
+}
+
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.h b/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
new file mode 100644 (file)
index 0000000..764eac6
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+
+#ifndef S5P_MFC_SHM_H_
+#define S5P_MFC_SHM_H_
+
+enum MFC_SHM_OFS
+{
+       EXTENEDED_DECODE_STATUS = 0x00, /* D */
+       SET_FRAME_TAG           = 0x04, /* D */
+       GET_FRAME_TAG_TOP       = 0x08, /* D */
+       GET_FRAME_TAG_BOT       = 0x0C, /* D */
+       PIC_TIME_TOP            = 0x10, /* D */
+       PIC_TIME_BOT            = 0x14, /* D */
+       START_BYTE_NUM          = 0x18, /* D */
+
+       CROP_INFO_H             = 0x20, /* D */
+       CROP_INFO_V             = 0x24, /* D */
+       EXT_ENC_CONTROL         = 0x28, /* E */
+       ENC_PARAM_CHANGE        = 0x2C, /* E */
+       RC_VOP_TIMING           = 0x30, /* E, MPEG4 */
+       HEC_PERIOD              = 0x34, /* E, MPEG4 */
+       METADATA_ENABLE         = 0x38, /* C */
+       METADATA_STATUS         = 0x3C, /* C */
+       METADATA_DISPLAY_INDEX  = 0x40, /* C */
+       EXT_METADATA_START_ADDR = 0x44, /* C */
+       PUT_EXTRADATA           = 0x48, /* C */
+       EXTRADATA_ADDR          = 0x4C, /* C */
+
+       ALLOC_LUMA_DPB_SIZE     = 0x64, /* D */
+       ALLOC_CHROMA_DPB_SIZE   = 0x68, /* D */
+       ALLOC_MV_SIZE           = 0x6C, /* D */
+       P_B_FRAME_QP            = 0x70, /* E */
+       SAMPLE_ASPECT_RATIO_IDC = 0x74, /* E, H.264, depend on
+                               ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
+       EXTENDED_SAR            = 0x78, /* E, H.264, depned on
+                               ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
+       DISP_PIC_PROFILE        = 0x7C, /* D */
+       FLUSH_CMD_TYPE          = 0x80, /* C */
+       FLUSH_CMD_INBUF1        = 0x84, /* C */
+       FLUSH_CMD_INBUF2        = 0x88, /* C */
+       FLUSH_CMD_OUTBUF        = 0x8C, /* E */
+       NEW_RC_BIT_RATE         = 0x90, /* E, format as RC_BIT_RATE(0xC5A8)
+                       depend on RC_BIT_RATE_CHANGE in ENC_PARAM_CHANGE */
+       NEW_RC_FRAME_RATE       = 0x94, /* E, format as RC_FRAME_RATE(0xD0D0)
+                       depend on RC_FRAME_RATE_CHANGE in ENC_PARAM_CHANGE */
+       NEW_I_PERIOD            = 0x98, /* E, format as I_FRM_CTRL(0xC504)
+                       depend on I_PERIOD_CHANGE in ENC_PARAM_CHANGE */
+       H264_I_PERIOD           = 0x9C, /* E, H.264, open GOP */
+       RC_CONTROL_CONFIG       = 0xA0, /* E */
+       BATCH_INPUT_ADDR        = 0xA4, /* E */
+       BATCH_OUTPUT_ADDR       = 0xA8, /* E */
+       BATCH_OUTPUT_SIZE       = 0xAC, /* E */
+       MIN_LUMA_DPB_SIZE       = 0xB0, /* D */
+       DEVICE_FORMAT_ID        = 0xB4, /* C */
+       H264_POC_TYPE           = 0xB8, /* D */
+       MIN_CHROMA_DPB_SIZE     = 0xBC, /* D */
+       DISP_PIC_FRAME_TYPE     = 0xC0, /* D */
+       FREE_LUMA_DPB           = 0xC4, /* D, VC1 MPEG4 */
+       ASPECT_RATIO_INFO       = 0xC8, /* D, MPEG4 */
+       EXTENDED_PAR            = 0xCC, /* D, MPEG4 */
+       DBG_HISTORY_INPUT0      = 0xD0, /* C */
+       DBG_HISTORY_INPUT1      = 0xD4, /* C */
+       DBG_HISTORY_OUTPUT      = 0xD8, /* C */
+       HIERARCHICAL_P_QP       = 0xE0, /* E, H.264 */
+};
+
+int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx);
+
+#define s5p_mfc_write_shm(ctx, x, ofs)         \
+       do {                                    \
+               writel(x, (ctx->shm + ofs));    \
+               wmb();                          \
+       } while (0)
+
+static inline u32 s5p_mfc_read_shm(struct s5p_mfc_ctx *ctx, unsigned int ofs)
+{
+       rmb();
+       return readl(ctx->shm + ofs);
+}
+
+#endif /* S5P_MFC_SHM_H_ */
diff --git a/drivers/media/video/s5p-tv/Kconfig b/drivers/media/video/s5p-tv/Kconfig
new file mode 100644 (file)
index 0000000..9c37dee
--- /dev/null
@@ -0,0 +1,76 @@
+# drivers/media/video/s5p-tv/Kconfig
+#
+# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+#      http://www.samsung.com/
+# Tomasz Stanislawski <t.stanislaws@samsung.com>
+#
+# Licensed under GPL
+
+config VIDEO_SAMSUNG_S5P_TV
+       bool "Samsung TV driver for S5P platform (experimental)"
+       depends on PLAT_S5P
+       depends on EXPERIMENTAL
+       default n
+       ---help---
+         Say Y here to enable selecting the TV output devices for
+         Samsung S5P platform.
+
+if VIDEO_SAMSUNG_S5P_TV
+
+config VIDEO_SAMSUNG_S5P_HDMI
+       tristate "Samsung HDMI Driver"
+       depends on VIDEO_V4L2
+       depends on VIDEO_SAMSUNG_S5P_TV
+       select VIDEO_SAMSUNG_S5P_HDMIPHY
+       help
+         Say Y here if you want support for the HDMI output
+         interface in S5P Samsung SoC. The driver can be compiled
+         as module. It is an auxiliary driver, that exposes a V4L2
+         subdev for use by other drivers. This driver requires
+         hdmiphy driver to work correctly.
+
+config VIDEO_SAMSUNG_S5P_HDMI_DEBUG
+       bool "Enable debug for HDMI Driver"
+       depends on VIDEO_SAMSUNG_S5P_HDMI
+       default n
+       help
+         Enables debugging for HDMI driver.
+
+config VIDEO_SAMSUNG_S5P_HDMIPHY
+       tristate "Samsung HDMIPHY Driver"
+       depends on VIDEO_DEV && VIDEO_V4L2 && I2C
+       depends on VIDEO_SAMSUNG_S5P_TV
+       help
+         Say Y here if you want support for the physical HDMI
+         interface in S5P Samsung SoC. The driver can be compiled
+         as module. It is an I2C driver, that exposes a V4L2
+         subdev for use by other drivers.
+
+config VIDEO_SAMSUNG_S5P_SDO
+       tristate "Samsung Analog TV Driver"
+       depends on VIDEO_DEV && VIDEO_V4L2
+       depends on VIDEO_SAMSUNG_S5P_TV
+       help
+         Say Y here if you want support for the analog TV output
+         interface in S5P Samsung SoC. The driver can be compiled
+         as module. It is an auxiliary driver, that exposes a V4L2
+         subdev for use by other drivers. This driver requires
+         hdmiphy driver to work correctly.
+
+config VIDEO_SAMSUNG_S5P_MIXER
+       tristate "Samsung Mixer and Video Processor Driver"
+       depends on VIDEO_DEV && VIDEO_V4L2
+       depends on VIDEO_SAMSUNG_S5P_TV
+       select VIDEOBUF2_DMA_CONTIG
+       help
+         Say Y here if you want support for the Mixer in Samsung S5P SoCs.
+         This device produce image data to one of output interfaces.
+
+config VIDEO_SAMSUNG_S5P_MIXER_DEBUG
+       bool "Enable debug for Mixer Driver"
+       depends on VIDEO_SAMSUNG_S5P_MIXER
+       default n
+       help
+         Enables debugging for Mixer driver.
+
+endif # VIDEO_SAMSUNG_S5P_TV
diff --git a/drivers/media/video/s5p-tv/Makefile b/drivers/media/video/s5p-tv/Makefile
new file mode 100644 (file)
index 0000000..37e4c17
--- /dev/null
@@ -0,0 +1,17 @@
+# drivers/media/video/samsung/tvout/Makefile
+#
+# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+#      http://www.samsung.com/
+# Tomasz Stanislawski <t.stanislaws@samsung.com>
+#
+# Licensed under GPL
+
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMIPHY) += s5p-hdmiphy.o
+s5p-hdmiphy-y += hdmiphy_drv.o
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI) += s5p-hdmi.o
+s5p-hdmi-y += hdmi_drv.o
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SDO) += s5p-sdo.o
+s5p-sdo-y += sdo_drv.o
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MIXER) += s5p-mixer.o
+s5p-mixer-y += mixer_drv.o mixer_video.o mixer_reg.o mixer_grp_layer.o mixer_vp_layer.o
+
diff --git a/drivers/media/video/s5p-tv/hdmi_drv.c b/drivers/media/video/s5p-tv/hdmi_drv.c
new file mode 100644 (file)
index 0000000..06d6663
--- /dev/null
@@ -0,0 +1,1042 @@
+/*
+ * Samsung HDMI interface driver
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *
+ * Tomasz Stanislawski, <t.stanislaws@samsung.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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#ifdef CONFIG_VIDEO_SAMSUNG_S5P_HDMI_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-subdev.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/bug.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+
+#include "regs-hdmi.h"
+
+MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>");
+MODULE_DESCRIPTION("Samsung HDMI");
+MODULE_LICENSE("GPL");
+
+/* default preset configured on probe */
+#define HDMI_DEFAULT_PRESET V4L2_DV_1080P60
+
+struct hdmi_resources {
+       struct clk *hdmi;
+       struct clk *sclk_hdmi;
+       struct clk *sclk_pixel;
+       struct clk *sclk_hdmiphy;
+       struct clk *hdmiphy;
+       struct regulator_bulk_data *regul_bulk;
+       int regul_count;
+};
+
+struct hdmi_device {
+       /** base address of HDMI registers */
+       void __iomem *regs;
+       /** HDMI interrupt */
+       unsigned int irq;
+       /** pointer to device parent */
+       struct device *dev;
+       /** subdev generated by HDMI device */
+       struct v4l2_subdev sd;
+       /** V4L2 device structure */
+       struct v4l2_device v4l2_dev;
+       /** subdev of HDMIPHY interface */
+       struct v4l2_subdev *phy_sd;
+       /** configuration of current graphic mode */
+       const struct hdmi_preset_conf *cur_conf;
+       /** current preset */
+       u32 cur_preset;
+       /** other resources */
+       struct hdmi_resources res;
+};
+
+struct hdmi_driver_data {
+       int hdmiphy_bus;
+};
+
+struct hdmi_tg_regs {
+       u8 cmd;
+       u8 h_fsz_l;
+       u8 h_fsz_h;
+       u8 hact_st_l;
+       u8 hact_st_h;
+       u8 hact_sz_l;
+       u8 hact_sz_h;
+       u8 v_fsz_l;
+       u8 v_fsz_h;
+       u8 vsync_l;
+       u8 vsync_h;
+       u8 vsync2_l;
+       u8 vsync2_h;
+       u8 vact_st_l;
+       u8 vact_st_h;
+       u8 vact_sz_l;
+       u8 vact_sz_h;
+       u8 field_chg_l;
+       u8 field_chg_h;
+       u8 vact_st2_l;
+       u8 vact_st2_h;
+       u8 vsync_top_hdmi_l;
+       u8 vsync_top_hdmi_h;
+       u8 vsync_bot_hdmi_l;
+       u8 vsync_bot_hdmi_h;
+       u8 field_top_hdmi_l;
+       u8 field_top_hdmi_h;
+       u8 field_bot_hdmi_l;
+       u8 field_bot_hdmi_h;
+};
+
+struct hdmi_core_regs {
+       u8 h_blank[2];
+       u8 v_blank[3];
+       u8 h_v_line[3];
+       u8 vsync_pol[1];
+       u8 int_pro_mode[1];
+       u8 v_blank_f[3];
+       u8 h_sync_gen[3];
+       u8 v_sync_gen1[3];
+       u8 v_sync_gen2[3];
+       u8 v_sync_gen3[3];
+};
+
+struct hdmi_preset_conf {
+       struct hdmi_core_regs core;
+       struct hdmi_tg_regs tg;
+       struct v4l2_mbus_framefmt mbus_fmt;
+};
+
+/* I2C module and id for HDMIPHY */
+static struct i2c_board_info hdmiphy_info = {
+       I2C_BOARD_INFO("hdmiphy", 0x38),
+};
+
+static struct hdmi_driver_data hdmi_driver_data[] = {
+       { .hdmiphy_bus = 3 },
+       { .hdmiphy_bus = 8 },
+};
+
+static struct platform_device_id hdmi_driver_types[] = {
+       {
+               .name           = "s5pv210-hdmi",
+               .driver_data    = (unsigned long)&hdmi_driver_data[0],
+       }, {
+               .name           = "exynos4-hdmi",
+               .driver_data    = (unsigned long)&hdmi_driver_data[1],
+       }, {
+               /* end node */
+       }
+};
+
+static const struct v4l2_subdev_ops hdmi_sd_ops;
+
+static struct hdmi_device *sd_to_hdmi_dev(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct hdmi_device, sd);
+}
+
+static inline
+void hdmi_write(struct hdmi_device *hdev, u32 reg_id, u32 value)
+{
+       writel(value, hdev->regs + reg_id);
+}
+
+static inline
+void hdmi_write_mask(struct hdmi_device *hdev, u32 reg_id, u32 value, u32 mask)
+{
+       u32 old = readl(hdev->regs + reg_id);
+       value = (value & mask) | (old & ~mask);
+       writel(value, hdev->regs + reg_id);
+}
+
+static inline
+void hdmi_writeb(struct hdmi_device *hdev, u32 reg_id, u8 value)
+{
+       writeb(value, hdev->regs + reg_id);
+}
+
+static inline u32 hdmi_read(struct hdmi_device *hdev, u32 reg_id)
+{
+       return readl(hdev->regs + reg_id);
+}
+
+static irqreturn_t hdmi_irq_handler(int irq, void *dev_data)
+{
+       struct hdmi_device *hdev = dev_data;
+       u32 intc_flag;
+
+       (void)irq;
+       intc_flag = hdmi_read(hdev, HDMI_INTC_FLAG);
+       /* clearing flags for HPD plug/unplug */
+       if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
+               printk(KERN_INFO "unplugged\n");
+               hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0,
+                       HDMI_INTC_FLAG_HPD_UNPLUG);
+       }
+       if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
+               printk(KERN_INFO "plugged\n");
+               hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0,
+                       HDMI_INTC_FLAG_HPD_PLUG);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void hdmi_reg_init(struct hdmi_device *hdev)
+{
+       /* enable HPD interrupts */
+       hdmi_write_mask(hdev, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL |
+               HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
+       /* choose HDMI mode */
+       hdmi_write_mask(hdev, HDMI_MODE_SEL,
+               HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
+       /* disable bluescreen */
+       hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
+       /* choose bluescreen (fecal) color */
+       hdmi_writeb(hdev, HDMI_BLUE_SCREEN_0, 0x12);
+       hdmi_writeb(hdev, HDMI_BLUE_SCREEN_1, 0x34);
+       hdmi_writeb(hdev, HDMI_BLUE_SCREEN_2, 0x56);
+       /* enable AVI packet every vsync, fixes purple line problem */
+       hdmi_writeb(hdev, HDMI_AVI_CON, 0x02);
+       /* force YUV444, look to CEA-861-D, table 7 for more detail */
+       hdmi_writeb(hdev, HDMI_AVI_BYTE(0), 2 << 5);
+       hdmi_write_mask(hdev, HDMI_CON_1, 2, 3 << 5);
+}
+
+static void hdmi_timing_apply(struct hdmi_device *hdev,
+       const struct hdmi_preset_conf *conf)
+{
+       const struct hdmi_core_regs *core = &conf->core;
+       const struct hdmi_tg_regs *tg = &conf->tg;
+
+       /* setting core registers */
+       hdmi_writeb(hdev, HDMI_H_BLANK_0, core->h_blank[0]);
+       hdmi_writeb(hdev, HDMI_H_BLANK_1, core->h_blank[1]);
+       hdmi_writeb(hdev, HDMI_V_BLANK_0, core->v_blank[0]);
+       hdmi_writeb(hdev, HDMI_V_BLANK_1, core->v_blank[1]);
+       hdmi_writeb(hdev, HDMI_V_BLANK_2, core->v_blank[2]);
+       hdmi_writeb(hdev, HDMI_H_V_LINE_0, core->h_v_line[0]);
+       hdmi_writeb(hdev, HDMI_H_V_LINE_1, core->h_v_line[1]);
+       hdmi_writeb(hdev, HDMI_H_V_LINE_2, core->h_v_line[2]);
+       hdmi_writeb(hdev, HDMI_VSYNC_POL, core->vsync_pol[0]);
+       hdmi_writeb(hdev, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
+       hdmi_writeb(hdev, HDMI_V_BLANK_F_0, core->v_blank_f[0]);
+       hdmi_writeb(hdev, HDMI_V_BLANK_F_1, core->v_blank_f[1]);
+       hdmi_writeb(hdev, HDMI_V_BLANK_F_2, core->v_blank_f[2]);
+       hdmi_writeb(hdev, HDMI_H_SYNC_GEN_0, core->h_sync_gen[0]);
+       hdmi_writeb(hdev, HDMI_H_SYNC_GEN_1, core->h_sync_gen[1]);
+       hdmi_writeb(hdev, HDMI_H_SYNC_GEN_2, core->h_sync_gen[2]);
+       hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
+       hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
+       hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
+       hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
+       hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
+       hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
+       hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
+       hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
+       hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
+       /* Timing generator registers */
+       hdmi_writeb(hdev, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
+       hdmi_writeb(hdev, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
+       hdmi_writeb(hdev, HDMI_TG_HACT_ST_L, tg->hact_st_l);
+       hdmi_writeb(hdev, HDMI_TG_HACT_ST_H, tg->hact_st_h);
+       hdmi_writeb(hdev, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
+       hdmi_writeb(hdev, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
+       hdmi_writeb(hdev, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
+       hdmi_writeb(hdev, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
+       hdmi_writeb(hdev, HDMI_TG_VSYNC_L, tg->vsync_l);
+       hdmi_writeb(hdev, HDMI_TG_VSYNC_H, tg->vsync_h);
+       hdmi_writeb(hdev, HDMI_TG_VSYNC2_L, tg->vsync2_l);
+       hdmi_writeb(hdev, HDMI_TG_VSYNC2_H, tg->vsync2_h);
+       hdmi_writeb(hdev, HDMI_TG_VACT_ST_L, tg->vact_st_l);
+       hdmi_writeb(hdev, HDMI_TG_VACT_ST_H, tg->vact_st_h);
+       hdmi_writeb(hdev, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
+       hdmi_writeb(hdev, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
+       hdmi_writeb(hdev, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
+       hdmi_writeb(hdev, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
+       hdmi_writeb(hdev, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
+       hdmi_writeb(hdev, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
+       hdmi_writeb(hdev, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
+       hdmi_writeb(hdev, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
+       hdmi_writeb(hdev, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
+       hdmi_writeb(hdev, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
+       hdmi_writeb(hdev, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
+       hdmi_writeb(hdev, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
+       hdmi_writeb(hdev, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
+       hdmi_writeb(hdev, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
+}
+
+static int hdmi_conf_apply(struct hdmi_device *hdmi_dev)
+{
+       struct device *dev = hdmi_dev->dev;
+       const struct hdmi_preset_conf *conf = hdmi_dev->cur_conf;
+       struct v4l2_dv_preset preset;
+       int ret;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       /* reset hdmiphy */
+       hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
+       mdelay(10);
+       hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT,  0, HDMI_PHY_SW_RSTOUT);
+       mdelay(10);
+
+       /* configure presets */
+       preset.preset = hdmi_dev->cur_preset;
+       ret = v4l2_subdev_call(hdmi_dev->phy_sd, video, s_dv_preset, &preset);
+       if (ret) {
+               dev_err(dev, "failed to set preset (%u)\n", preset.preset);
+               return ret;
+       }
+
+       /* resetting HDMI core */
+       hdmi_write_mask(hdmi_dev, HDMI_CORE_RSTOUT,  0, HDMI_CORE_SW_RSTOUT);
+       mdelay(10);
+       hdmi_write_mask(hdmi_dev, HDMI_CORE_RSTOUT, ~0, HDMI_CORE_SW_RSTOUT);
+       mdelay(10);
+
+       hdmi_reg_init(hdmi_dev);
+
+       /* setting core registers */
+       hdmi_timing_apply(hdmi_dev, conf);
+
+       return 0;
+}
+
+static void hdmi_dumpregs(struct hdmi_device *hdev, char *prefix)
+{
+#define DUMPREG(reg_id) \
+       dev_dbg(hdev->dev, "%s:" #reg_id " = %08x\n", prefix, \
+               readl(hdev->regs + reg_id))
+
+       dev_dbg(hdev->dev, "%s: ---- CONTROL REGISTERS ----\n", prefix);
+       DUMPREG(HDMI_INTC_FLAG);
+       DUMPREG(HDMI_INTC_CON);
+       DUMPREG(HDMI_HPD_STATUS);
+       DUMPREG(HDMI_PHY_RSTOUT);
+       DUMPREG(HDMI_PHY_VPLL);
+       DUMPREG(HDMI_PHY_CMU);
+       DUMPREG(HDMI_CORE_RSTOUT);
+
+       dev_dbg(hdev->dev, "%s: ---- CORE REGISTERS ----\n", prefix);
+       DUMPREG(HDMI_CON_0);
+       DUMPREG(HDMI_CON_1);
+       DUMPREG(HDMI_CON_2);
+       DUMPREG(HDMI_SYS_STATUS);
+       DUMPREG(HDMI_PHY_STATUS);
+       DUMPREG(HDMI_STATUS_EN);
+       DUMPREG(HDMI_HPD);
+       DUMPREG(HDMI_MODE_SEL);
+       DUMPREG(HDMI_HPD_GEN);
+       DUMPREG(HDMI_DC_CONTROL);
+       DUMPREG(HDMI_VIDEO_PATTERN_GEN);
+
+       dev_dbg(hdev->dev, "%s: ---- CORE SYNC REGISTERS ----\n", prefix);
+       DUMPREG(HDMI_H_BLANK_0);
+       DUMPREG(HDMI_H_BLANK_1);
+       DUMPREG(HDMI_V_BLANK_0);
+       DUMPREG(HDMI_V_BLANK_1);
+       DUMPREG(HDMI_V_BLANK_2);
+       DUMPREG(HDMI_H_V_LINE_0);
+       DUMPREG(HDMI_H_V_LINE_1);
+       DUMPREG(HDMI_H_V_LINE_2);
+       DUMPREG(HDMI_VSYNC_POL);
+       DUMPREG(HDMI_INT_PRO_MODE);
+       DUMPREG(HDMI_V_BLANK_F_0);
+       DUMPREG(HDMI_V_BLANK_F_1);
+       DUMPREG(HDMI_V_BLANK_F_2);
+       DUMPREG(HDMI_H_SYNC_GEN_0);
+       DUMPREG(HDMI_H_SYNC_GEN_1);
+       DUMPREG(HDMI_H_SYNC_GEN_2);
+       DUMPREG(HDMI_V_SYNC_GEN_1_0);
+       DUMPREG(HDMI_V_SYNC_GEN_1_1);
+       DUMPREG(HDMI_V_SYNC_GEN_1_2);
+       DUMPREG(HDMI_V_SYNC_GEN_2_0);
+       DUMPREG(HDMI_V_SYNC_GEN_2_1);
+       DUMPREG(HDMI_V_SYNC_GEN_2_2);
+       DUMPREG(HDMI_V_SYNC_GEN_3_0);
+       DUMPREG(HDMI_V_SYNC_GEN_3_1);
+       DUMPREG(HDMI_V_SYNC_GEN_3_2);
+
+       dev_dbg(hdev->dev, "%s: ---- TG REGISTERS ----\n", prefix);
+       DUMPREG(HDMI_TG_CMD);
+       DUMPREG(HDMI_TG_H_FSZ_L);
+       DUMPREG(HDMI_TG_H_FSZ_H);
+       DUMPREG(HDMI_TG_HACT_ST_L);
+       DUMPREG(HDMI_TG_HACT_ST_H);
+       DUMPREG(HDMI_TG_HACT_SZ_L);
+       DUMPREG(HDMI_TG_HACT_SZ_H);
+       DUMPREG(HDMI_TG_V_FSZ_L);
+       DUMPREG(HDMI_TG_V_FSZ_H);
+       DUMPREG(HDMI_TG_VSYNC_L);
+       DUMPREG(HDMI_TG_VSYNC_H);
+       DUMPREG(HDMI_TG_VSYNC2_L);
+       DUMPREG(HDMI_TG_VSYNC2_H);
+       DUMPREG(HDMI_TG_VACT_ST_L);
+       DUMPREG(HDMI_TG_VACT_ST_H);
+       DUMPREG(HDMI_TG_VACT_SZ_L);
+       DUMPREG(HDMI_TG_VACT_SZ_H);
+       DUMPREG(HDMI_TG_FIELD_CHG_L);
+       DUMPREG(HDMI_TG_FIELD_CHG_H);
+       DUMPREG(HDMI_TG_VACT_ST2_L);
+       DUMPREG(HDMI_TG_VACT_ST2_H);
+       DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
+       DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
+       DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
+       DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
+       DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
+       DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
+       DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
+       DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
+#undef DUMPREG
+}
+
+static const struct hdmi_preset_conf hdmi_conf_480p = {
+       .core = {
+               .h_blank = {0x8a, 0x00},
+               .v_blank = {0x0d, 0x6a, 0x01},
+               .h_v_line = {0x0d, 0xa2, 0x35},
+               .vsync_pol = {0x01},
+               .int_pro_mode = {0x00},
+               .v_blank_f = {0x00, 0x00, 0x00},
+               .h_sync_gen = {0x0e, 0x30, 0x11},
+               .v_sync_gen1 = {0x0f, 0x90, 0x00},
+               /* other don't care */
+       },
+       .tg = {
+               0x00, /* cmd */
+               0x5a, 0x03, /* h_fsz */
+               0x8a, 0x00, 0xd0, 0x02, /* hact */
+               0x0d, 0x02, /* v_fsz */
+               0x01, 0x00, 0x33, 0x02, /* vsync */
+               0x2d, 0x00, 0xe0, 0x01, /* vact */
+               0x33, 0x02, /* field_chg */
+               0x49, 0x02, /* vact_st2 */
+               0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
+               0x01, 0x00, 0x33, 0x02, /* field top/bot */
+       },
+       .mbus_fmt = {
+               .width = 720,
+               .height = 480,
+               .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
+               .field = V4L2_FIELD_NONE,
+       },
+};
+
+static const struct hdmi_preset_conf hdmi_conf_720p60 = {
+       .core = {
+               .h_blank = {0x72, 0x01},
+               .v_blank = {0xee, 0xf2, 0x00},
+               .h_v_line = {0xee, 0x22, 0x67},
+               .vsync_pol = {0x00},
+               .int_pro_mode = {0x00},
+               .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
+               .h_sync_gen = {0x6c, 0x50, 0x02},
+               .v_sync_gen1 = {0x0a, 0x50, 0x00},
+               /* other don't care */
+       },
+       .tg = {
+               0x00, /* cmd */
+               0x72, 0x06, /* h_fsz */
+               0x72, 0x01, 0x00, 0x05, /* hact */
+               0xee, 0x02, /* v_fsz */
+               0x01, 0x00, 0x33, 0x02, /* vsync */
+               0x1e, 0x00, 0xd0, 0x02, /* vact */
+               0x33, 0x02, /* field_chg */
+               0x49, 0x02, /* vact_st2 */
+               0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
+               0x01, 0x00, 0x33, 0x02, /* field top/bot */
+       },
+       .mbus_fmt = {
+               .width = 1280,
+               .height = 720,
+               .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
+               .field = V4L2_FIELD_NONE,
+       },
+};
+
+static const struct hdmi_preset_conf hdmi_conf_1080p50 = {
+       .core = {
+               .h_blank = {0xd0, 0x02},
+               .v_blank = {0x65, 0x6c, 0x01},
+               .h_v_line = {0x65, 0x04, 0xa5},
+               .vsync_pol = {0x00},
+               .int_pro_mode = {0x00},
+               .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
+               .h_sync_gen = {0x0e, 0xea, 0x08},
+               .v_sync_gen1 = {0x09, 0x40, 0x00},
+               /* other don't care */
+       },
+       .tg = {
+               0x00, /* cmd */
+               0x98, 0x08, /* h_fsz */
+               0x18, 0x01, 0x80, 0x07, /* hact */
+               0x65, 0x04, /* v_fsz */
+               0x01, 0x00, 0x33, 0x02, /* vsync */
+               0x2d, 0x00, 0x38, 0x04, /* vact */
+               0x33, 0x02, /* field_chg */
+               0x49, 0x02, /* vact_st2 */
+               0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
+               0x01, 0x00, 0x33, 0x02, /* field top/bot */
+       },
+       .mbus_fmt = {
+               .width = 1920,
+               .height = 1080,
+               .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
+               .field = V4L2_FIELD_NONE,
+       },
+};
+
+static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
+       .core = {
+               .h_blank = {0x18, 0x01},
+               .v_blank = {0x65, 0x6c, 0x01},
+               .h_v_line = {0x65, 0x84, 0x89},
+               .vsync_pol = {0x00},
+               .int_pro_mode = {0x00},
+               .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
+               .h_sync_gen = {0x56, 0x08, 0x02},
+               .v_sync_gen1 = {0x09, 0x40, 0x00},
+               /* other don't care */
+       },
+       .tg = {
+               0x00, /* cmd */
+               0x98, 0x08, /* h_fsz */
+               0x18, 0x01, 0x80, 0x07, /* hact */
+               0x65, 0x04, /* v_fsz */
+               0x01, 0x00, 0x33, 0x02, /* vsync */
+               0x2d, 0x00, 0x38, 0x04, /* vact */
+               0x33, 0x02, /* field_chg */
+               0x48, 0x02, /* vact_st2 */
+               0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
+               0x01, 0x00, 0x33, 0x02, /* field top/bot */
+       },
+       .mbus_fmt = {
+               .width = 1920,
+               .height = 1080,
+               .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
+               .field = V4L2_FIELD_NONE,
+       },
+};
+
+static const struct {
+       u32 preset;
+       const struct hdmi_preset_conf *conf;
+} hdmi_conf[] = {
+       { V4L2_DV_480P59_94, &hdmi_conf_480p },
+       { V4L2_DV_720P59_94, &hdmi_conf_720p60 },
+       { V4L2_DV_1080P50, &hdmi_conf_1080p50 },
+       { V4L2_DV_1080P30, &hdmi_conf_1080p60 },
+       { V4L2_DV_1080P60, &hdmi_conf_1080p60 },
+};
+
+static const struct hdmi_preset_conf *hdmi_preset2conf(u32 preset)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(hdmi_conf); ++i)
+               if (hdmi_conf[i].preset == preset)
+                       return  hdmi_conf[i].conf;
+       return NULL;
+}
+
+static int hdmi_streamon(struct hdmi_device *hdev)
+{
+       struct device *dev = hdev->dev;
+       struct hdmi_resources *res = &hdev->res;
+       int ret, tries;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       ret = v4l2_subdev_call(hdev->phy_sd, video, s_stream, 1);
+       if (ret)
+               return ret;
+
+       /* waiting for HDMIPHY's PLL to get to steady state */
+       for (tries = 100; tries; --tries) {
+               u32 val = hdmi_read(hdev, HDMI_PHY_STATUS);
+               if (val & HDMI_PHY_STATUS_READY)
+                       break;
+               mdelay(1);
+       }
+       /* steady state not achieved */
+       if (tries == 0) {
+               dev_err(dev, "hdmiphy's pll could not reach steady state.\n");
+               v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0);
+               hdmi_dumpregs(hdev, "s_stream");
+               return -EIO;
+       }
+
+       /* hdmiphy clock is used for HDMI in streaming mode */
+       clk_disable(res->sclk_hdmi);
+       clk_set_parent(res->sclk_hdmi, res->sclk_hdmiphy);
+       clk_enable(res->sclk_hdmi);
+
+       /* enable HDMI and timing generator */
+       hdmi_write_mask(hdev, HDMI_CON_0, ~0, HDMI_EN);
+       hdmi_write_mask(hdev, HDMI_TG_CMD, ~0, HDMI_TG_EN);
+       hdmi_dumpregs(hdev, "streamon");
+       return 0;
+}
+
+static int hdmi_streamoff(struct hdmi_device *hdev)
+{
+       struct device *dev = hdev->dev;
+       struct hdmi_resources *res = &hdev->res;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_EN);
+       hdmi_write_mask(hdev, HDMI_TG_CMD, 0, HDMI_TG_EN);
+
+       /* pixel(vpll) clock is used for HDMI in config mode */
+       clk_disable(res->sclk_hdmi);
+       clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
+       clk_enable(res->sclk_hdmi);
+
+       v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0);
+
+       hdmi_dumpregs(hdev, "streamoff");
+       return 0;
+}
+
+static int hdmi_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
+       struct device *dev = hdev->dev;
+
+       dev_dbg(dev, "%s(%d)\n", __func__, enable);
+       if (enable)
+               return hdmi_streamon(hdev);
+       return hdmi_streamoff(hdev);
+}
+
+static void hdmi_resource_poweron(struct hdmi_resources *res)
+{
+       /* turn HDMI power on */
+       regulator_bulk_enable(res->regul_count, res->regul_bulk);
+       /* power-on hdmi physical interface */
+       clk_enable(res->hdmiphy);
+       /* use VPP as parent clock; HDMIPHY is not working yet */
+       clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
+       /* turn clocks on */
+       clk_enable(res->sclk_hdmi);
+}
+
+static void hdmi_resource_poweroff(struct hdmi_resources *res)
+{
+       /* turn clocks off */
+       clk_disable(res->sclk_hdmi);
+       /* power-off hdmiphy */
+       clk_disable(res->hdmiphy);
+       /* turn HDMI power off */
+       regulator_bulk_disable(res->regul_count, res->regul_bulk);
+}
+
+static int hdmi_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
+       int ret;
+
+       if (on)
+               ret = pm_runtime_get_sync(hdev->dev);
+       else
+               ret = pm_runtime_put_sync(hdev->dev);
+       /* only values < 0 indicate errors */
+       return IS_ERR_VALUE(ret) ? ret : 0;
+}
+
+static int hdmi_s_dv_preset(struct v4l2_subdev *sd,
+       struct v4l2_dv_preset *preset)
+{
+       struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
+       struct device *dev = hdev->dev;
+       const struct hdmi_preset_conf *conf;
+
+       conf = hdmi_preset2conf(preset->preset);
+       if (conf == NULL) {
+               dev_err(dev, "preset (%u) not supported\n", preset->preset);
+               return -EINVAL;
+       }
+       hdev->cur_conf = conf;
+       hdev->cur_preset = preset->preset;
+       return 0;
+}
+
+static int hdmi_g_dv_preset(struct v4l2_subdev *sd,
+       struct v4l2_dv_preset *preset)
+{
+       memset(preset, 0, sizeof(*preset));
+       preset->preset = sd_to_hdmi_dev(sd)->cur_preset;
+       return 0;
+}
+
+static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd,
+         struct v4l2_mbus_framefmt *fmt)
+{
+       struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
+       struct device *dev = hdev->dev;
+
+       dev_dbg(dev, "%s\n", __func__);
+       if (!hdev->cur_conf)
+               return -EINVAL;
+       *fmt = hdev->cur_conf->mbus_fmt;
+       return 0;
+}
+
+static int hdmi_enum_dv_presets(struct v4l2_subdev *sd,
+       struct v4l2_dv_enum_preset *preset)
+{
+       if (preset->index >= ARRAY_SIZE(hdmi_conf))
+               return -EINVAL;
+       return v4l_fill_dv_preset_info(hdmi_conf[preset->index].preset, preset);
+}
+
+static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = {
+       .s_power = hdmi_s_power,
+};
+
+static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = {
+       .s_dv_preset = hdmi_s_dv_preset,
+       .g_dv_preset = hdmi_g_dv_preset,
+       .enum_dv_presets = hdmi_enum_dv_presets,
+       .g_mbus_fmt = hdmi_g_mbus_fmt,
+       .s_stream = hdmi_s_stream,
+};
+
+static const struct v4l2_subdev_ops hdmi_sd_ops = {
+       .core = &hdmi_sd_core_ops,
+       .video = &hdmi_sd_video_ops,
+};
+
+static int hdmi_runtime_suspend(struct device *dev)
+{
+       struct v4l2_subdev *sd = dev_get_drvdata(dev);
+       struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
+
+       dev_dbg(dev, "%s\n", __func__);
+       hdmi_resource_poweroff(&hdev->res);
+       return 0;
+}
+
+static int hdmi_runtime_resume(struct device *dev)
+{
+       struct v4l2_subdev *sd = dev_get_drvdata(dev);
+       struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
+       int ret = 0;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       hdmi_resource_poweron(&hdev->res);
+
+       ret = hdmi_conf_apply(hdev);
+       if (ret)
+               goto fail;
+
+       dev_dbg(dev, "poweron succeed\n");
+
+       return 0;
+
+fail:
+       hdmi_resource_poweroff(&hdev->res);
+       dev_err(dev, "poweron failed\n");
+
+       return ret;
+}
+
+static const struct dev_pm_ops hdmi_pm_ops = {
+       .runtime_suspend = hdmi_runtime_suspend,
+       .runtime_resume  = hdmi_runtime_resume,
+};
+
+static void hdmi_resources_cleanup(struct hdmi_device *hdev)
+{
+       struct hdmi_resources *res = &hdev->res;
+
+       dev_dbg(hdev->dev, "HDMI resource cleanup\n");
+       /* put clocks, power */
+       if (res->regul_count)
+               regulator_bulk_free(res->regul_count, res->regul_bulk);
+       /* kfree is NULL-safe */
+       kfree(res->regul_bulk);
+       if (!IS_ERR_OR_NULL(res->hdmiphy))
+               clk_put(res->hdmiphy);
+       if (!IS_ERR_OR_NULL(res->sclk_hdmiphy))
+               clk_put(res->sclk_hdmiphy);
+       if (!IS_ERR_OR_NULL(res->sclk_pixel))
+               clk_put(res->sclk_pixel);
+       if (!IS_ERR_OR_NULL(res->sclk_hdmi))
+               clk_put(res->sclk_hdmi);
+       if (!IS_ERR_OR_NULL(res->hdmi))
+               clk_put(res->hdmi);
+       memset(res, 0, sizeof *res);
+}
+
+static int hdmi_resources_init(struct hdmi_device *hdev)
+{
+       struct device *dev = hdev->dev;
+       struct hdmi_resources *res = &hdev->res;
+       static char *supply[] = {
+               "hdmi-en",
+               "vdd",
+               "vdd_osc",
+               "vdd_pll",
+       };
+       int i, ret;
+
+       dev_dbg(dev, "HDMI resource init\n");
+
+       memset(res, 0, sizeof *res);
+       /* get clocks, power */
+
+       res->hdmi = clk_get(dev, "hdmi");
+       if (IS_ERR_OR_NULL(res->hdmi)) {
+               dev_err(dev, "failed to get clock 'hdmi'\n");
+               goto fail;
+       }
+       res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
+       if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
+               dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
+               goto fail;
+       }
+       res->sclk_pixel = clk_get(dev, "sclk_pixel");
+       if (IS_ERR_OR_NULL(res->sclk_pixel)) {
+               dev_err(dev, "failed to get clock 'sclk_pixel'\n");
+               goto fail;
+       }
+       res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy");
+       if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
+               dev_err(dev, "failed to get clock 'sclk_hdmiphy'\n");
+               goto fail;
+       }
+       res->hdmiphy = clk_get(dev, "hdmiphy");
+       if (IS_ERR_OR_NULL(res->hdmiphy)) {
+               dev_err(dev, "failed to get clock 'hdmiphy'\n");
+               goto fail;
+       }
+       res->regul_bulk = kzalloc(ARRAY_SIZE(supply) *
+               sizeof res->regul_bulk[0], GFP_KERNEL);
+       if (!res->regul_bulk) {
+               dev_err(dev, "failed to get memory for regulators\n");
+               goto fail;
+       }
+       for (i = 0; i < ARRAY_SIZE(supply); ++i) {
+               res->regul_bulk[i].supply = supply[i];
+               res->regul_bulk[i].consumer = NULL;
+       }
+
+       ret = regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
+       if (ret) {
+               dev_err(dev, "failed to get regulators\n");
+               goto fail;
+       }
+       res->regul_count = ARRAY_SIZE(supply);
+
+       return 0;
+fail:
+       dev_err(dev, "HDMI resource init - failed\n");
+       hdmi_resources_cleanup(hdev);
+       return -ENODEV;
+}
+
+static int __devinit hdmi_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       struct i2c_adapter *phy_adapter;
+       struct v4l2_subdev *sd;
+       struct hdmi_device *hdmi_dev = NULL;
+       struct hdmi_driver_data *drv_data;
+       int ret;
+
+       dev_dbg(dev, "probe start\n");
+
+       hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL);
+       if (!hdmi_dev) {
+               dev_err(dev, "out of memory\n");
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       hdmi_dev->dev = dev;
+
+       ret = hdmi_resources_init(hdmi_dev);
+       if (ret)
+               goto fail_hdev;
+
+       /* mapping HDMI registers */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(dev, "get memory resource failed.\n");
+               ret = -ENXIO;
+               goto fail_init;
+       }
+
+       hdmi_dev->regs = ioremap(res->start, resource_size(res));
+       if (hdmi_dev->regs == NULL) {
+               dev_err(dev, "register mapping failed.\n");
+               ret = -ENXIO;
+               goto fail_hdev;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (res == NULL) {
+               dev_err(dev, "get interrupt resource failed.\n");
+               ret = -ENXIO;
+               goto fail_regs;
+       }
+
+       ret = request_irq(res->start, hdmi_irq_handler, 0, "hdmi", hdmi_dev);
+       if (ret) {
+               dev_err(dev, "request interrupt failed.\n");
+               goto fail_regs;
+       }
+       hdmi_dev->irq = res->start;
+
+       /* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
+       strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
+               sizeof(hdmi_dev->v4l2_dev.name));
+       /* passing NULL owner prevents driver from erasing drvdata */
+       ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
+       if (ret) {
+               dev_err(dev, "could not register v4l2 device.\n");
+               goto fail_irq;
+       }
+
+       drv_data = (struct hdmi_driver_data *)
+               platform_get_device_id(pdev)->driver_data;
+       phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus);
+       if (phy_adapter == NULL) {
+               dev_err(dev, "adapter request failed\n");
+               ret = -ENXIO;
+               goto fail_vdev;
+       }
+
+       hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev,
+               phy_adapter, &hdmiphy_info, NULL);
+       /* on failure or not adapter is no longer useful */
+       i2c_put_adapter(phy_adapter);
+       if (hdmi_dev->phy_sd == NULL) {
+               dev_err(dev, "missing subdev for hdmiphy\n");
+               ret = -ENODEV;
+               goto fail_vdev;
+       }
+
+       clk_enable(hdmi_dev->res.hdmi);
+
+       pm_runtime_enable(dev);
+
+       sd = &hdmi_dev->sd;
+       v4l2_subdev_init(sd, &hdmi_sd_ops);
+       sd->owner = THIS_MODULE;
+
+       strlcpy(sd->name, "s5p-hdmi", sizeof sd->name);
+       hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET;
+       /* FIXME: missing fail preset is not supported */
+       hdmi_dev->cur_conf = hdmi_preset2conf(hdmi_dev->cur_preset);
+
+       /* storing subdev for call that have only access to struct device */
+       dev_set_drvdata(dev, sd);
+
+       dev_info(dev, "probe sucessful\n");
+
+       return 0;
+
+fail_vdev:
+       v4l2_device_unregister(&hdmi_dev->v4l2_dev);
+
+fail_irq:
+       free_irq(hdmi_dev->irq, hdmi_dev);
+
+fail_regs:
+       iounmap(hdmi_dev->regs);
+
+fail_init:
+       hdmi_resources_cleanup(hdmi_dev);
+
+fail_hdev:
+       kfree(hdmi_dev);
+
+fail:
+       dev_err(dev, "probe failed\n");
+       return ret;
+}
+
+static int __devexit hdmi_remove(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct v4l2_subdev *sd = dev_get_drvdata(dev);
+       struct hdmi_device *hdmi_dev = sd_to_hdmi_dev(sd);
+
+       pm_runtime_disable(dev);
+       clk_disable(hdmi_dev->res.hdmi);
+       v4l2_device_unregister(&hdmi_dev->v4l2_dev);
+       disable_irq(hdmi_dev->irq);
+       free_irq(hdmi_dev->irq, hdmi_dev);
+       iounmap(hdmi_dev->regs);
+       hdmi_resources_cleanup(hdmi_dev);
+       kfree(hdmi_dev);
+       dev_info(dev, "remove sucessful\n");
+
+       return 0;
+}
+
+static struct platform_driver hdmi_driver __refdata = {
+       .probe = hdmi_probe,
+       .remove = __devexit_p(hdmi_remove),
+       .id_table = hdmi_driver_types,
+       .driver = {
+               .name = "s5p-hdmi",
+               .owner = THIS_MODULE,
+               .pm = &hdmi_pm_ops,
+       }
+};
+
+/* D R I V E R   I N I T I A L I Z A T I O N */
+
+static int __init hdmi_init(void)
+{
+       int ret;
+       static const char banner[] __initdata = KERN_INFO \
+               "Samsung HDMI output driver, "
+               "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
+       printk(banner);
+
+       ret = platform_driver_register(&hdmi_driver);
+       if (ret)
+               printk(KERN_ERR "HDMI platform driver register failed\n");
+
+       return ret;
+}
+module_init(hdmi_init);
+
+static void __exit hdmi_exit(void)
+{
+       platform_driver_unregister(&hdmi_driver);
+}
+module_exit(hdmi_exit);
+
+
diff --git a/drivers/media/video/s5p-tv/hdmiphy_drv.c b/drivers/media/video/s5p-tv/hdmiphy_drv.c
new file mode 100644 (file)
index 0000000..6693f4a
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Samsung HDMI Physical interface driver
+ *
+ * Copyright (C) 2010-2011 Samsung Electronics Co.Ltd
+ * Author: Tomasz Stanislawski <t.stanislaws@samsung.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.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+
+#include <media/v4l2-subdev.h>
+
+MODULE_AUTHOR("Tomasz Stanislawski <t.stanislaws@samsung.com>");
+MODULE_DESCRIPTION("Samsung HDMI Physical interface driver");
+MODULE_LICENSE("GPL");
+
+struct hdmiphy_conf {
+       u32 preset;
+       const u8 *data;
+};
+
+static const u8 hdmiphy_conf27[32] = {
+       0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
+       0x6B, 0x10, 0x02, 0x51, 0xDf, 0xF2, 0x54, 0x87,
+       0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
+       0x22, 0x40, 0xe3, 0x26, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u8 hdmiphy_conf74_175[32] = {
+       0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
+       0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
+       0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
+       0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
+};
+
+static const u8 hdmiphy_conf74_25[32] = {
+       0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
+       0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
+       0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xe0,
+       0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
+};
+
+static const u8 hdmiphy_conf148_5[32] = {
+       0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
+       0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
+       0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
+       0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
+};
+
+static const struct hdmiphy_conf hdmiphy_conf[] = {
+       { V4L2_DV_480P59_94, hdmiphy_conf27 },
+       { V4L2_DV_1080P30, hdmiphy_conf74_175 },
+       { V4L2_DV_720P59_94, hdmiphy_conf74_175 },
+       { V4L2_DV_720P60, hdmiphy_conf74_25 },
+       { V4L2_DV_1080P50, hdmiphy_conf148_5 },
+       { V4L2_DV_1080P60, hdmiphy_conf148_5 },
+};
+
+const u8 *hdmiphy_preset2conf(u32 preset)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(hdmiphy_conf); ++i)
+               if (hdmiphy_conf[i].preset == preset)
+                       return hdmiphy_conf[i].data;
+       return NULL;
+}
+
+static int hdmiphy_s_power(struct v4l2_subdev *sd, int on)
+{
+       /* to be implemented */
+       return 0;
+}
+
+static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd,
+       struct v4l2_dv_preset *preset)
+{
+       const u8 *data;
+       u8 buffer[32];
+       int ret;
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct device *dev = &client->dev;
+
+       dev_info(dev, "s_dv_preset(preset = %d)\n", preset->preset);
+       data = hdmiphy_preset2conf(preset->preset);
+       if (!data) {
+               dev_err(dev, "format not supported\n");
+               return -EINVAL;
+       }
+
+       /* storing configuration to the device */
+       memcpy(buffer, data, 32);
+       ret = i2c_master_send(client, buffer, 32);
+       if (ret != 32) {
+               dev_err(dev, "failed to configure HDMIPHY via I2C\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int hdmiphy_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct device *dev = &client->dev;
+       u8 buffer[2];
+       int ret;
+
+       dev_info(dev, "s_stream(%d)\n", enable);
+       /* going to/from configuration from/to operation mode */
+       buffer[0] = 0x1f;
+       buffer[1] = enable ? 0x80 : 0x00;
+
+       ret = i2c_master_send(client, buffer, 2);
+       if (ret != 2) {
+               dev_err(dev, "stream (%d) failed\n", enable);
+               return -EIO;
+       }
+       return 0;
+}
+
+static const struct v4l2_subdev_core_ops hdmiphy_core_ops = {
+       .s_power =  hdmiphy_s_power,
+};
+
+static const struct v4l2_subdev_video_ops hdmiphy_video_ops = {
+       .s_dv_preset = hdmiphy_s_dv_preset,
+       .s_stream =  hdmiphy_s_stream,
+};
+
+static const struct v4l2_subdev_ops hdmiphy_ops = {
+       .core = &hdmiphy_core_ops,
+       .video = &hdmiphy_video_ops,
+};
+
+static int __devinit hdmiphy_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       static struct v4l2_subdev sd;
+
+       v4l2_i2c_subdev_init(&sd, client, &hdmiphy_ops);
+       dev_info(&client->dev, "probe successful\n");
+       return 0;
+}
+
+static int __devexit hdmiphy_remove(struct i2c_client *client)
+{
+       dev_info(&client->dev, "remove successful\n");
+       return 0;
+}
+
+static const struct i2c_device_id hdmiphy_id[] = {
+       { "hdmiphy", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, hdmiphy_id);
+
+static struct i2c_driver hdmiphy_driver = {
+       .driver = {
+               .name   = "s5p-hdmiphy",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = hdmiphy_probe,
+       .remove         = __devexit_p(hdmiphy_remove),
+       .id_table = hdmiphy_id,
+};
+
+static int __init hdmiphy_init(void)
+{
+       return i2c_add_driver(&hdmiphy_driver);
+}
+module_init(hdmiphy_init);
+
+static void __exit hdmiphy_exit(void)
+{
+       i2c_del_driver(&hdmiphy_driver);
+}
+module_exit(hdmiphy_exit);
diff --git a/drivers/media/video/s5p-tv/mixer.h b/drivers/media/video/s5p-tv/mixer.h
new file mode 100644 (file)
index 0000000..e224224
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *
+ * Tomasz Stanislawski, <t.stanislaws@samsung.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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#ifndef SAMSUNG_MIXER_H
+#define SAMSUNG_MIXER_H
+
+#ifdef CONFIG_VIDEO_SAMSUNG_S5P_MIXER_DEBUG
+       #define DEBUG
+#endif
+
+#include <linux/fb.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <media/v4l2-device.h>
+#include <media/videobuf2-core.h>
+
+#include "regs-mixer.h"
+
+/** maximum number of output interfaces */
+#define MXR_MAX_OUTPUTS 2
+/** maximum number of input interfaces (layers) */
+#define MXR_MAX_LAYERS 3
+#define MXR_DRIVER_NAME "s5p-mixer"
+/** maximal number of planes for every layer */
+#define MXR_MAX_PLANES 2
+
+#define MXR_ENABLE 1
+#define MXR_DISABLE 0
+
+/** description of a macroblock for packed formats */
+struct mxr_block {
+       /** vertical number of pixels in macroblock */
+       unsigned int width;
+       /** horizontal number of pixels in macroblock */
+       unsigned int height;
+       /** size of block in bytes */
+       unsigned int size;
+};
+
+/** description of supported format */
+struct mxr_format {
+       /** format name/mnemonic */
+       const char *name;
+       /** fourcc identifier */
+       u32 fourcc;
+       /** colorspace identifier */
+       enum v4l2_colorspace colorspace;
+       /** number of planes in image data */
+       int num_planes;
+       /** description of block for each plane */
+       struct mxr_block plane[MXR_MAX_PLANES];
+       /** number of subframes in image data */
+       int num_subframes;
+       /** specifies to which subframe belong given plane */
+       int plane2subframe[MXR_MAX_PLANES];
+       /** internal code, driver dependant */
+       unsigned long cookie;
+};
+
+/** description of crop configuration for image */
+struct mxr_crop {
+       /** width of layer in pixels */
+       unsigned int full_width;
+       /** height of layer in pixels */
+       unsigned int full_height;
+       /** horizontal offset of first pixel to be displayed */
+       unsigned int x_offset;
+       /** vertical offset of first pixel to be displayed */
+       unsigned int y_offset;
+       /** width of displayed data in pixels */
+       unsigned int width;
+       /** height of displayed data in pixels */
+       unsigned int height;
+       /** indicate which fields are present in buffer */
+       unsigned int field;
+};
+
+/** description of transformation from source to destination image */
+struct mxr_geometry {
+       /** cropping for source image */
+       struct mxr_crop src;
+       /** cropping for destination image */
+       struct mxr_crop dst;
+       /** layer-dependant description of horizontal scaling */
+       unsigned int x_ratio;
+       /** layer-dependant description of vertical scaling */
+       unsigned int y_ratio;
+};
+
+/** instance of a buffer */
+struct mxr_buffer {
+       /** common v4l buffer stuff -- must be first */
+       struct vb2_buffer       vb;
+       /** node for layer's lists */
+       struct list_head        list;
+};
+
+
+/** internal states of layer */
+enum mxr_layer_state {
+       /** layers is not shown */
+       MXR_LAYER_IDLE = 0,
+       /** state between STREAMON and hardware start */
+       MXR_LAYER_STREAMING_START,
+       /** layer is shown */
+       MXR_LAYER_STREAMING,
+       /** state before STREAMOFF is finished */
+       MXR_LAYER_STREAMING_FINISH,
+};
+
+/** forward declarations */
+struct mxr_device;
+struct mxr_layer;
+
+/** callback for layers operation */
+struct mxr_layer_ops {
+       /* TODO: try to port it to subdev API */
+       /** handler for resource release function */
+       void (*release)(struct mxr_layer *);
+       /** setting buffer to HW */
+       void (*buffer_set)(struct mxr_layer *, struct mxr_buffer *);
+       /** setting format and geometry in HW */
+       void (*format_set)(struct mxr_layer *);
+       /** streaming stop/start */
+       void (*stream_set)(struct mxr_layer *, int);
+       /** adjusting geometry */
+       void (*fix_geometry)(struct mxr_layer *);
+};
+
+/** layer instance, a single window and content displayed on output */
+struct mxr_layer {
+       /** parent mixer device */
+       struct mxr_device *mdev;
+       /** layer index (unique identifier) */
+       int idx;
+       /** callbacks for layer methods */
+       struct mxr_layer_ops ops;
+       /** format array */
+       const struct mxr_format **fmt_array;
+       /** size of format array */
+       unsigned long fmt_array_size;
+
+       /** lock for protection of list and state fields */
+       spinlock_t enq_slock;
+       /** list for enqueued buffers */
+       struct list_head enq_list;
+       /** buffer currently owned by hardware in temporary registers */
+       struct mxr_buffer *update_buf;
+       /** buffer currently owned by hardware in shadow registers */
+       struct mxr_buffer *shadow_buf;
+       /** state of layer IDLE/STREAMING */
+       enum mxr_layer_state state;
+
+       /** mutex for protection of fields below */
+       struct mutex mutex;
+       /** handler for video node */
+       struct video_device vfd;
+       /** queue for output buffers */
+       struct vb2_queue vb_queue;
+       /** current image format */
+       const struct mxr_format *fmt;
+       /** current geometry of image */
+       struct mxr_geometry geo;
+};
+
+/** description of mixers output interface */
+struct mxr_output {
+       /** name of output */
+       char name[32];
+       /** output subdev */
+       struct v4l2_subdev *sd;
+       /** cookie used for configuration of registers */
+       int cookie;
+};
+
+/** specify source of output subdevs */
+struct mxr_output_conf {
+       /** name of output (connector) */
+       char *output_name;
+       /** name of module that generates output subdev */
+       char *module_name;
+       /** cookie need for mixer HW */
+       int cookie;
+};
+
+struct clk;
+struct regulator;
+
+/** auxiliary resources used my mixer */
+struct mxr_resources {
+       /** interrupt index */
+       int irq;
+       /** pointer to Mixer registers */
+       void __iomem *mxr_regs;
+       /** pointer to Video Processor registers */
+       void __iomem *vp_regs;
+       /** other resources, should used under mxr_device.mutex */
+       struct clk *mixer;
+       struct clk *vp;
+       struct clk *sclk_mixer;
+       struct clk *sclk_hdmi;
+       struct clk *sclk_dac;
+};
+
+/* event flags used  */
+enum mxr_devide_flags {
+       MXR_EVENT_VSYNC = 0,
+};
+
+/** drivers instance */
+struct mxr_device {
+       /** master device */
+       struct device *dev;
+       /** state of each layer */
+       struct mxr_layer *layer[MXR_MAX_LAYERS];
+       /** state of each output */
+       struct mxr_output *output[MXR_MAX_OUTPUTS];
+       /** number of registered outputs */
+       int output_cnt;
+
+       /* video resources */
+
+       /** V4L2 device */
+       struct v4l2_device v4l2_dev;
+       /** context of allocator */
+       void *alloc_ctx;
+       /** event wait queue */
+       wait_queue_head_t event_queue;
+       /** state flags */
+       unsigned long event_flags;
+
+       /** spinlock for protection of registers */
+       spinlock_t reg_slock;
+
+       /** mutex for protection of fields below */
+       struct mutex mutex;
+       /** number of entities depndant on output configuration */
+       int n_output;
+       /** number of users that do streaming */
+       int n_streamer;
+       /** index of current output */
+       int current_output;
+       /** auxiliary resources used my mixer */
+       struct mxr_resources res;
+};
+
+/** transform device structure into mixer device */
+static inline struct mxr_device *to_mdev(struct device *dev)
+{
+       struct v4l2_device *vdev = dev_get_drvdata(dev);
+       return container_of(vdev, struct mxr_device, v4l2_dev);
+}
+
+/** get current output data, should be called under mdev's mutex */
+static inline struct mxr_output *to_output(struct mxr_device *mdev)
+{
+       return mdev->output[mdev->current_output];
+}
+
+/** get current output subdev, should be called under mdev's mutex */
+static inline struct v4l2_subdev *to_outsd(struct mxr_device *mdev)
+{
+       struct mxr_output *out = to_output(mdev);
+       return out ? out->sd : NULL;
+}
+
+/** forward declaration for mixer platform data */
+struct mxr_platform_data;
+
+/** acquiring common video resources */
+int __devinit mxr_acquire_video(struct mxr_device *mdev,
+       struct mxr_output_conf *output_cont, int output_count);
+
+/** releasing common video resources */
+void __devexit mxr_release_video(struct mxr_device *mdev);
+
+struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int idx);
+struct mxr_layer *mxr_vp_layer_create(struct mxr_device *mdev, int idx);
+struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
+       int idx, char *name, struct mxr_layer_ops *ops);
+
+void mxr_base_layer_release(struct mxr_layer *layer);
+void mxr_layer_release(struct mxr_layer *layer);
+
+int mxr_base_layer_register(struct mxr_layer *layer);
+void mxr_base_layer_unregister(struct mxr_layer *layer);
+
+unsigned long mxr_get_plane_size(const struct mxr_block *blk,
+       unsigned int width, unsigned int height);
+
+/** adds new consumer for mixer's power */
+int __must_check mxr_power_get(struct mxr_device *mdev);
+/** removes consumer for mixer's power */
+void mxr_power_put(struct mxr_device *mdev);
+/** add new client for output configuration */
+void mxr_output_get(struct mxr_device *mdev);
+/** removes new client for output configuration */
+void mxr_output_put(struct mxr_device *mdev);
+/** add new client for streaming */
+void mxr_streamer_get(struct mxr_device *mdev);
+/** removes new client for streaming */
+void mxr_streamer_put(struct mxr_device *mdev);
+/** returns format of data delivared to current output */
+void mxr_get_mbus_fmt(struct mxr_device *mdev,
+       struct v4l2_mbus_framefmt *mbus_fmt);
+
+/* Debug */
+
+#define mxr_err(mdev, fmt, ...)  dev_err(mdev->dev, fmt, ##__VA_ARGS__)
+#define mxr_warn(mdev, fmt, ...) dev_warn(mdev->dev, fmt, ##__VA_ARGS__)
+#define mxr_info(mdev, fmt, ...) dev_info(mdev->dev, fmt, ##__VA_ARGS__)
+
+#ifdef CONFIG_VIDEO_SAMSUNG_S5P_MIXER_DEBUG
+       #define mxr_dbg(mdev, fmt, ...)  dev_dbg(mdev->dev, fmt, ##__VA_ARGS__)
+#else
+       #define mxr_dbg(mdev, fmt, ...)  do { (void) mdev; } while (0)
+#endif
+
+/* accessing Mixer's and Video Processor's registers */
+
+void mxr_vsync_set_update(struct mxr_device *mdev, int en);
+void mxr_reg_reset(struct mxr_device *mdev);
+irqreturn_t mxr_irq_handler(int irq, void *dev_data);
+void mxr_reg_s_output(struct mxr_device *mdev, int cookie);
+void mxr_reg_streamon(struct mxr_device *mdev);
+void mxr_reg_streamoff(struct mxr_device *mdev);
+int mxr_reg_wait4vsync(struct mxr_device *mdev);
+void mxr_reg_set_mbus_fmt(struct mxr_device *mdev,
+       struct v4l2_mbus_framefmt *fmt);
+void mxr_reg_graph_layer_stream(struct mxr_device *mdev, int idx, int en);
+void mxr_reg_graph_buffer(struct mxr_device *mdev, int idx, dma_addr_t addr);
+void mxr_reg_graph_format(struct mxr_device *mdev, int idx,
+       const struct mxr_format *fmt, const struct mxr_geometry *geo);
+
+void mxr_reg_vp_layer_stream(struct mxr_device *mdev, int en);
+void mxr_reg_vp_buffer(struct mxr_device *mdev,
+       dma_addr_t luma_addr[2], dma_addr_t chroma_addr[2]);
+void mxr_reg_vp_format(struct mxr_device *mdev,
+       const struct mxr_format *fmt, const struct mxr_geometry *geo);
+void mxr_reg_dump(struct mxr_device *mdev);
+
+#endif /* SAMSUNG_MIXER_H */
+
diff --git a/drivers/media/video/s5p-tv/mixer_drv.c b/drivers/media/video/s5p-tv/mixer_drv.c
new file mode 100644 (file)
index 0000000..0064309
--- /dev/null
@@ -0,0 +1,487 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *
+ * Tomasz Stanislawski, <t.stanislaws@samsung.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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#include "mixer.h"
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+
+MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>");
+MODULE_DESCRIPTION("Samsung MIXER");
+MODULE_LICENSE("GPL");
+
+/* --------- DRIVER PARAMETERS ---------- */
+
+static struct mxr_output_conf mxr_output_conf[] = {
+       {
+               .output_name = "S5P HDMI connector",
+               .module_name = "s5p-hdmi",
+               .cookie = 1,
+       },
+       {
+               .output_name = "S5P SDO connector",
+               .module_name = "s5p-sdo",
+               .cookie = 0,
+       },
+};
+
+void mxr_get_mbus_fmt(struct mxr_device *mdev,
+       struct v4l2_mbus_framefmt *mbus_fmt)
+{
+       struct v4l2_subdev *sd;
+       int ret;
+
+       mutex_lock(&mdev->mutex);
+       sd = to_outsd(mdev);
+       ret = v4l2_subdev_call(sd, video, g_mbus_fmt, mbus_fmt);
+       WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name);
+       mutex_unlock(&mdev->mutex);
+}
+
+void mxr_streamer_get(struct mxr_device *mdev)
+{
+       mutex_lock(&mdev->mutex);
+       ++mdev->n_streamer;
+       mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer);
+       if (mdev->n_streamer == 1) {
+               struct v4l2_subdev *sd = to_outsd(mdev);
+               struct v4l2_mbus_framefmt mbus_fmt;
+               struct mxr_resources *res = &mdev->res;
+               int ret;
+
+               if (to_output(mdev)->cookie == 0)
+                       clk_set_parent(res->sclk_mixer, res->sclk_dac);
+               else
+                       clk_set_parent(res->sclk_mixer, res->sclk_hdmi);
+               mxr_reg_s_output(mdev, to_output(mdev)->cookie);
+
+               ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mbus_fmt);
+               WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name);
+               ret = v4l2_subdev_call(sd, video, s_stream, 1);
+               WARN(ret, "starting stream failed for output %s\n", sd->name);
+
+               mxr_reg_set_mbus_fmt(mdev, &mbus_fmt);
+               mxr_reg_streamon(mdev);
+               ret = mxr_reg_wait4vsync(mdev);
+               WARN(ret, "failed to get vsync (%d) from output\n", ret);
+       }
+       mutex_unlock(&mdev->mutex);
+       mxr_reg_dump(mdev);
+       /* FIXME: what to do when streaming fails? */
+}
+
+void mxr_streamer_put(struct mxr_device *mdev)
+{
+       mutex_lock(&mdev->mutex);
+       --mdev->n_streamer;
+       mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer);
+       if (mdev->n_streamer == 0) {
+               int ret;
+               struct v4l2_subdev *sd = to_outsd(mdev);
+
+               mxr_reg_streamoff(mdev);
+               /* vsync applies Mixer setup */
+               ret = mxr_reg_wait4vsync(mdev);
+               WARN(ret, "failed to get vsync (%d) from output\n", ret);
+               ret = v4l2_subdev_call(sd, video, s_stream, 0);
+               WARN(ret, "stopping stream failed for output %s\n", sd->name);
+       }
+       WARN(mdev->n_streamer < 0, "negative number of streamers (%d)\n",
+               mdev->n_streamer);
+       mutex_unlock(&mdev->mutex);
+       mxr_reg_dump(mdev);
+}
+
+void mxr_output_get(struct mxr_device *mdev)
+{
+       mutex_lock(&mdev->mutex);
+       ++mdev->n_output;
+       mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_output);
+       /* turn on auxiliary driver */
+       if (mdev->n_output == 1)
+               v4l2_subdev_call(to_outsd(mdev), core, s_power, 1);
+       mutex_unlock(&mdev->mutex);
+}
+
+void mxr_output_put(struct mxr_device *mdev)
+{
+       mutex_lock(&mdev->mutex);
+       --mdev->n_output;
+       mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_output);
+       /* turn on auxiliary driver */
+       if (mdev->n_output == 0)
+               v4l2_subdev_call(to_outsd(mdev), core, s_power, 0);
+       WARN(mdev->n_output < 0, "negative number of output users (%d)\n",
+               mdev->n_output);
+       mutex_unlock(&mdev->mutex);
+}
+
+int mxr_power_get(struct mxr_device *mdev)
+{
+       int ret = pm_runtime_get_sync(mdev->dev);
+
+       /* returning 1 means that power is already enabled,
+        * so zero success be returned */
+       if (IS_ERR_VALUE(ret))
+               return ret;
+       return 0;
+}
+
+void mxr_power_put(struct mxr_device *mdev)
+{
+       pm_runtime_put_sync(mdev->dev);
+}
+
+/* --------- RESOURCE MANAGEMENT -------------*/
+
+static int __devinit mxr_acquire_plat_resources(struct mxr_device *mdev,
+       struct platform_device *pdev)
+{
+       struct resource *res;
+       int ret;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
+       if (res == NULL) {
+               mxr_err(mdev, "get memory resource failed.\n");
+               ret = -ENXIO;
+               goto fail;
+       }
+
+       mdev->res.mxr_regs = ioremap(res->start, resource_size(res));
+       if (mdev->res.mxr_regs == NULL) {
+               mxr_err(mdev, "register mapping failed.\n");
+               ret = -ENXIO;
+               goto fail;
+       }
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
+       if (res == NULL) {
+               mxr_err(mdev, "get memory resource failed.\n");
+               ret = -ENXIO;
+               goto fail_mxr_regs;
+       }
+
+       mdev->res.vp_regs = ioremap(res->start, resource_size(res));
+       if (mdev->res.vp_regs == NULL) {
+               mxr_err(mdev, "register mapping failed.\n");
+               ret = -ENXIO;
+               goto fail_mxr_regs;
+       }
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
+       if (res == NULL) {
+               mxr_err(mdev, "get interrupt resource failed.\n");
+               ret = -ENXIO;
+               goto fail_vp_regs;
+       }
+
+       ret = request_irq(res->start, mxr_irq_handler, 0, "s5p-mixer", mdev);
+       if (ret) {
+               mxr_err(mdev, "request interrupt failed.\n");
+               goto fail_vp_regs;
+       }
+       mdev->res.irq = res->start;
+
+       return 0;
+
+fail_vp_regs:
+       iounmap(mdev->res.vp_regs);
+
+fail_mxr_regs:
+       iounmap(mdev->res.mxr_regs);
+
+fail:
+       return ret;
+}
+
+static void mxr_release_plat_resources(struct mxr_device *mdev)
+{
+       free_irq(mdev->res.irq, mdev);
+       iounmap(mdev->res.vp_regs);
+       iounmap(mdev->res.mxr_regs);
+}
+
+static void mxr_release_clocks(struct mxr_device *mdev)
+{
+       struct mxr_resources *res = &mdev->res;
+
+       if (!IS_ERR_OR_NULL(res->sclk_dac))
+               clk_put(res->sclk_dac);
+       if (!IS_ERR_OR_NULL(res->sclk_hdmi))
+               clk_put(res->sclk_hdmi);
+       if (!IS_ERR_OR_NULL(res->sclk_mixer))
+               clk_put(res->sclk_mixer);
+       if (!IS_ERR_OR_NULL(res->vp))
+               clk_put(res->vp);
+       if (!IS_ERR_OR_NULL(res->mixer))
+               clk_put(res->mixer);
+}
+
+static int mxr_acquire_clocks(struct mxr_device *mdev)
+{
+       struct mxr_resources *res = &mdev->res;
+       struct device *dev = mdev->dev;
+
+       res->mixer = clk_get(dev, "mixer");
+       if (IS_ERR_OR_NULL(res->mixer)) {
+               mxr_err(mdev, "failed to get clock 'mixer'\n");
+               goto fail;
+       }
+       res->vp = clk_get(dev, "vp");
+       if (IS_ERR_OR_NULL(res->vp)) {
+               mxr_err(mdev, "failed to get clock 'vp'\n");
+               goto fail;
+       }
+       res->sclk_mixer = clk_get(dev, "sclk_mixer");
+       if (IS_ERR_OR_NULL(res->sclk_mixer)) {
+               mxr_err(mdev, "failed to get clock 'sclk_mixer'\n");
+               goto fail;
+       }
+       res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
+       if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
+               mxr_err(mdev, "failed to get clock 'sclk_hdmi'\n");
+               goto fail;
+       }
+       res->sclk_dac = clk_get(dev, "sclk_dac");
+       if (IS_ERR_OR_NULL(res->sclk_dac)) {
+               mxr_err(mdev, "failed to get clock 'sclk_dac'\n");
+               goto fail;
+       }
+
+       return 0;
+fail:
+       mxr_release_clocks(mdev);
+       return -ENODEV;
+}
+
+static int __devinit mxr_acquire_resources(struct mxr_device *mdev,
+       struct platform_device *pdev)
+{
+       int ret;
+       ret = mxr_acquire_plat_resources(mdev, pdev);
+
+       if (ret)
+               goto fail;
+
+       ret = mxr_acquire_clocks(mdev);
+       if (ret)
+               goto fail_plat;
+
+       mxr_info(mdev, "resources acquired\n");
+       return 0;
+
+fail_plat:
+       mxr_release_plat_resources(mdev);
+fail:
+       mxr_err(mdev, "resources acquire failed\n");
+       return ret;
+}
+
+static void mxr_release_resources(struct mxr_device *mdev)
+{
+       mxr_release_clocks(mdev);
+       mxr_release_plat_resources(mdev);
+       memset(&mdev->res, 0, sizeof mdev->res);
+}
+
+static void mxr_release_layers(struct mxr_device *mdev)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mdev->layer); ++i)
+               if (mdev->layer[i])
+                       mxr_layer_release(mdev->layer[i]);
+}
+
+static int __devinit mxr_acquire_layers(struct mxr_device *mdev,
+       struct mxr_platform_data *pdata)
+{
+       mdev->layer[0] = mxr_graph_layer_create(mdev, 0);
+       mdev->layer[1] = mxr_graph_layer_create(mdev, 1);
+       mdev->layer[2] = mxr_vp_layer_create(mdev, 0);
+
+       if (!mdev->layer[0] || !mdev->layer[1] || !mdev->layer[2]) {
+               mxr_err(mdev, "failed to acquire layers\n");
+               goto fail;
+       }
+
+       return 0;
+
+fail:
+       mxr_release_layers(mdev);
+       return -ENODEV;
+}
+
+/* ---------- POWER MANAGEMENT ----------- */
+
+static int mxr_runtime_resume(struct device *dev)
+{
+       struct mxr_device *mdev = to_mdev(dev);
+       struct mxr_resources *res = &mdev->res;
+
+       mxr_dbg(mdev, "resume - start\n");
+       mutex_lock(&mdev->mutex);
+       /* turn clocks on */
+       clk_enable(res->mixer);
+       clk_enable(res->vp);
+       clk_enable(res->sclk_mixer);
+       /* apply default configuration */
+       mxr_reg_reset(mdev);
+       mxr_dbg(mdev, "resume - finished\n");
+
+       mutex_unlock(&mdev->mutex);
+       return 0;
+}
+
+static int mxr_runtime_suspend(struct device *dev)
+{
+       struct mxr_device *mdev = to_mdev(dev);
+       struct mxr_resources *res = &mdev->res;
+       mxr_dbg(mdev, "suspend - start\n");
+       mutex_lock(&mdev->mutex);
+       /* turn clocks off */
+       clk_disable(res->sclk_mixer);
+       clk_disable(res->vp);
+       clk_disable(res->mixer);
+       mutex_unlock(&mdev->mutex);
+       mxr_dbg(mdev, "suspend - finished\n");
+       return 0;
+}
+
+static const struct dev_pm_ops mxr_pm_ops = {
+       .runtime_suspend = mxr_runtime_suspend,
+       .runtime_resume  = mxr_runtime_resume,
+};
+
+/* --------- DRIVER INITIALIZATION ---------- */
+
+static int __devinit mxr_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct mxr_platform_data *pdata = dev->platform_data;
+       struct mxr_device *mdev;
+       int ret;
+
+       /* mdev does not exist yet so no mxr_dbg is used */
+       dev_info(dev, "probe start\n");
+
+       mdev = kzalloc(sizeof *mdev, GFP_KERNEL);
+       if (!mdev) {
+               mxr_err(mdev, "not enough memory.\n");
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       /* setup pointer to master device */
+       mdev->dev = dev;
+
+       mutex_init(&mdev->mutex);
+       spin_lock_init(&mdev->reg_slock);
+       init_waitqueue_head(&mdev->event_queue);
+
+       /* acquire resources: regs, irqs, clocks, regulators */
+       ret = mxr_acquire_resources(mdev, pdev);
+       if (ret)
+               goto fail_mem;
+
+       /* configure resources for video output */
+       ret = mxr_acquire_video(mdev, mxr_output_conf,
+               ARRAY_SIZE(mxr_output_conf));
+       if (ret)
+               goto fail_resources;
+
+       /* configure layers */
+       ret = mxr_acquire_layers(mdev, pdata);
+       if (ret)
+               goto fail_video;
+
+       pm_runtime_enable(dev);
+
+       mxr_info(mdev, "probe successful\n");
+       return 0;
+
+fail_video:
+       mxr_release_video(mdev);
+
+fail_resources:
+       mxr_release_resources(mdev);
+
+fail_mem:
+       kfree(mdev);
+
+fail:
+       dev_info(dev, "probe failed\n");
+       return ret;
+}
+
+static int __devexit mxr_remove(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct mxr_device *mdev = to_mdev(dev);
+
+       pm_runtime_disable(dev);
+
+       mxr_release_layers(mdev);
+       mxr_release_video(mdev);
+       mxr_release_resources(mdev);
+
+       kfree(mdev);
+
+       dev_info(dev, "remove sucessful\n");
+       return 0;
+}
+
+static struct platform_driver mxr_driver __refdata = {
+       .probe = mxr_probe,
+       .remove = __devexit_p(mxr_remove),
+       .driver = {
+               .name = MXR_DRIVER_NAME,
+               .owner = THIS_MODULE,
+               .pm = &mxr_pm_ops,
+       }
+};
+
+static int __init mxr_init(void)
+{
+       int i, ret;
+       static const char banner[] __initdata = KERN_INFO
+               "Samsung TV Mixer driver, "
+               "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
+       printk(banner);
+
+       /* Loading auxiliary modules */
+       for (i = 0; i < ARRAY_SIZE(mxr_output_conf); ++i)
+               request_module(mxr_output_conf[i].module_name);
+
+       ret = platform_driver_register(&mxr_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "registration of MIXER driver failed\n");
+               return -ENXIO;
+       }
+
+       return 0;
+}
+module_init(mxr_init);
+
+static void __exit mxr_exit(void)
+{
+       platform_driver_unregister(&mxr_driver);
+}
+module_exit(mxr_exit);
diff --git a/drivers/media/video/s5p-tv/mixer_grp_layer.c b/drivers/media/video/s5p-tv/mixer_grp_layer.c
new file mode 100644 (file)
index 0000000..58f0ba4
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *
+ * Tomasz Stanislawski, <t.stanislaws@samsung.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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#include "mixer.h"
+
+#include <media/videobuf2-dma-contig.h>
+
+/* FORMAT DEFINITIONS */
+
+static const struct mxr_format mxr_fb_fmt_rgb565 = {
+       .name = "RGB565",
+       .fourcc = V4L2_PIX_FMT_RGB565,
+       .colorspace = V4L2_COLORSPACE_SRGB,
+       .num_planes = 1,
+       .plane = {
+               { .width = 1, .height = 1, .size = 2 },
+       },
+       .num_subframes = 1,
+       .cookie = 4,
+};
+
+static const struct mxr_format mxr_fb_fmt_argb1555 = {
+       .name = "ARGB1555",
+       .num_planes = 1,
+       .fourcc = V4L2_PIX_FMT_RGB555,
+       .colorspace = V4L2_COLORSPACE_SRGB,
+       .plane = {
+               { .width = 1, .height = 1, .size = 2 },
+       },
+       .num_subframes = 1,
+       .cookie = 5,
+};
+
+static const struct mxr_format mxr_fb_fmt_argb4444 = {
+       .name = "ARGB4444",
+       .num_planes = 1,
+       .fourcc = V4L2_PIX_FMT_RGB444,
+       .colorspace = V4L2_COLORSPACE_SRGB,
+       .plane = {
+               { .width = 1, .height = 1, .size = 2 },
+       },
+       .num_subframes = 1,
+       .cookie = 6,
+};
+
+static const struct mxr_format mxr_fb_fmt_argb8888 = {
+       .name = "ARGB8888",
+       .fourcc = V4L2_PIX_FMT_BGR32,
+       .colorspace = V4L2_COLORSPACE_SRGB,
+       .num_planes = 1,
+       .plane = {
+               { .width = 1, .height = 1, .size = 4 },
+       },
+       .num_subframes = 1,
+       .cookie = 7,
+};
+
+static const struct mxr_format *mxr_graph_format[] = {
+       &mxr_fb_fmt_rgb565,
+       &mxr_fb_fmt_argb1555,
+       &mxr_fb_fmt_argb4444,
+       &mxr_fb_fmt_argb8888,
+};
+
+/* AUXILIARY CALLBACKS */
+
+static void mxr_graph_layer_release(struct mxr_layer *layer)
+{
+       mxr_base_layer_unregister(layer);
+       mxr_base_layer_release(layer);
+}
+
+static void mxr_graph_buffer_set(struct mxr_layer *layer,
+       struct mxr_buffer *buf)
+{
+       dma_addr_t addr = 0;
+
+       if (buf)
+               addr = vb2_dma_contig_plane_paddr(&buf->vb, 0);
+       mxr_reg_graph_buffer(layer->mdev, layer->idx, addr);
+}
+
+static void mxr_graph_stream_set(struct mxr_layer *layer, int en)
+{
+       mxr_reg_graph_layer_stream(layer->mdev, layer->idx, en);
+}
+
+static void mxr_graph_format_set(struct mxr_layer *layer)
+{
+       mxr_reg_graph_format(layer->mdev, layer->idx,
+               layer->fmt, &layer->geo);
+}
+
+static void mxr_graph_fix_geometry(struct mxr_layer *layer)
+{
+       struct mxr_geometry *geo = &layer->geo;
+
+       /* limit to boundary size */
+       geo->src.full_width = clamp_val(geo->src.full_width, 1, 32767);
+       geo->src.full_height = clamp_val(geo->src.full_height, 1, 2047);
+       geo->src.width = clamp_val(geo->src.width, 1, geo->src.full_width);
+       geo->src.width = min(geo->src.width, 2047U);
+       /* not possible to crop of Y axis */
+       geo->src.y_offset = min(geo->src.y_offset, geo->src.full_height - 1);
+       geo->src.height = geo->src.full_height - geo->src.y_offset;
+       /* limitting offset */
+       geo->src.x_offset = min(geo->src.x_offset,
+               geo->src.full_width - geo->src.width);
+
+       /* setting position in output */
+       geo->dst.width = min(geo->dst.width, geo->dst.full_width);
+       geo->dst.height = min(geo->dst.height, geo->dst.full_height);
+
+       /* Mixer supports only 1x and 2x scaling */
+       if (geo->dst.width >= 2 * geo->src.width) {
+               geo->x_ratio = 1;
+               geo->dst.width = 2 * geo->src.width;
+       } else {
+               geo->x_ratio = 0;
+               geo->dst.width = geo->src.width;
+       }
+
+       if (geo->dst.height >= 2 * geo->src.height) {
+               geo->y_ratio = 1;
+               geo->dst.height = 2 * geo->src.height;
+       } else {
+               geo->y_ratio = 0;
+               geo->dst.height = geo->src.height;
+       }
+
+       geo->dst.x_offset = min(geo->dst.x_offset,
+               geo->dst.full_width - geo->dst.width);
+       geo->dst.y_offset = min(geo->dst.y_offset,
+               geo->dst.full_height - geo->dst.height);
+}
+
+/* PUBLIC API */
+
+struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int idx)
+{
+       struct mxr_layer *layer;
+       int ret;
+       struct mxr_layer_ops ops = {
+               .release = mxr_graph_layer_release,
+               .buffer_set = mxr_graph_buffer_set,
+               .stream_set = mxr_graph_stream_set,
+               .format_set = mxr_graph_format_set,
+               .fix_geometry = mxr_graph_fix_geometry,
+       };
+       char name[32];
+
+       sprintf(name, "graph%d", idx);
+
+       layer = mxr_base_layer_create(mdev, idx, name, &ops);
+       if (layer == NULL) {
+               mxr_err(mdev, "failed to initialize layer(%d) base\n", idx);
+               goto fail;
+       }
+
+       layer->fmt_array = mxr_graph_format;
+       layer->fmt_array_size = ARRAY_SIZE(mxr_graph_format);
+
+       ret = mxr_base_layer_register(layer);
+       if (ret)
+               goto fail_layer;
+
+       return layer;
+
+fail_layer:
+       mxr_base_layer_release(layer);
+
+fail:
+       return NULL;
+}
+
diff --git a/drivers/media/video/s5p-tv/mixer_reg.c b/drivers/media/video/s5p-tv/mixer_reg.c
new file mode 100644 (file)
index 0000000..38dac67
--- /dev/null
@@ -0,0 +1,541 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *
+ * Tomasz Stanislawski, <t.stanislaws@samsung.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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#include "mixer.h"
+#include "regs-mixer.h"
+#include "regs-vp.h"
+
+#include <linux/delay.h>
+
+/* Register access subroutines */
+
+static inline u32 vp_read(struct mxr_device *mdev, u32 reg_id)
+{
+       return readl(mdev->res.vp_regs + reg_id);
+}
+
+static inline void vp_write(struct mxr_device *mdev, u32 reg_id, u32 val)
+{
+       writel(val, mdev->res.vp_regs + reg_id);
+}
+
+static inline void vp_write_mask(struct mxr_device *mdev, u32 reg_id,
+       u32 val, u32 mask)
+{
+       u32 old = vp_read(mdev, reg_id);
+
+       val = (val & mask) | (old & ~mask);
+       writel(val, mdev->res.vp_regs + reg_id);
+}
+
+static inline u32 mxr_read(struct mxr_device *mdev, u32 reg_id)
+{
+       return readl(mdev->res.mxr_regs + reg_id);
+}
+
+static inline void mxr_write(struct mxr_device *mdev, u32 reg_id, u32 val)
+{
+       writel(val, mdev->res.mxr_regs + reg_id);
+}
+
+static inline void mxr_write_mask(struct mxr_device *mdev, u32 reg_id,
+       u32 val, u32 mask)
+{
+       u32 old = mxr_read(mdev, reg_id);
+
+       val = (val & mask) | (old & ~mask);
+       writel(val, mdev->res.mxr_regs + reg_id);
+}
+
+void mxr_vsync_set_update(struct mxr_device *mdev, int en)
+{
+       /* block update on vsync */
+       mxr_write_mask(mdev, MXR_STATUS, en ? MXR_STATUS_SYNC_ENABLE : 0,
+               MXR_STATUS_SYNC_ENABLE);
+       vp_write(mdev, VP_SHADOW_UPDATE, en ? VP_SHADOW_UPDATE_ENABLE : 0);
+}
+
+static void __mxr_reg_vp_reset(struct mxr_device *mdev)
+{
+       int tries = 100;
+
+       vp_write(mdev, VP_SRESET, VP_SRESET_PROCESSING);
+       for (tries = 100; tries; --tries) {
+               /* waiting until VP_SRESET_PROCESSING is 0 */
+               if (~vp_read(mdev, VP_SRESET) & VP_SRESET_PROCESSING)
+                       break;
+               mdelay(10);
+       }
+       WARN(tries == 0, "failed to reset Video Processor\n");
+}
+
+static void mxr_reg_vp_default_filter(struct mxr_device *mdev);
+
+void mxr_reg_reset(struct mxr_device *mdev)
+{
+       unsigned long flags;
+       u32 val; /* value stored to register */
+
+       spin_lock_irqsave(&mdev->reg_slock, flags);
+       mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+       /* set output in RGB888 mode */
+       mxr_write(mdev, MXR_CFG, MXR_CFG_OUT_YUV444);
+
+       /* 16 beat burst in DMA */
+       mxr_write_mask(mdev, MXR_STATUS, MXR_STATUS_16_BURST,
+               MXR_STATUS_BURST_MASK);
+
+       /* setting default layer priority: layer1 > video > layer0
+        * because typical usage scenario would be
+        * layer0 - framebuffer
+        * video - video overlay
+        * layer1 - OSD
+        */
+       val  = MXR_LAYER_CFG_GRP0_VAL(1);
+       val |= MXR_LAYER_CFG_VP_VAL(2);
+       val |= MXR_LAYER_CFG_GRP1_VAL(3);
+       mxr_write(mdev, MXR_LAYER_CFG, val);
+
+       /* use dark gray background color */
+       mxr_write(mdev, MXR_BG_COLOR0, 0x808080);
+       mxr_write(mdev, MXR_BG_COLOR1, 0x808080);
+       mxr_write(mdev, MXR_BG_COLOR2, 0x808080);
+
+       /* setting graphical layers */
+
+       val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
+       val |= MXR_GRP_CFG_BLEND_PRE_MUL; /* premul mode */
+       val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
+
+       /* the same configuration for both layers */
+       mxr_write(mdev, MXR_GRAPHIC_CFG(0), val);
+       mxr_write(mdev, MXR_GRAPHIC_CFG(1), val);
+
+       /* configuration of Video Processor Registers */
+       __mxr_reg_vp_reset(mdev);
+       mxr_reg_vp_default_filter(mdev);
+
+       /* enable all interrupts */
+       mxr_write_mask(mdev, MXR_INT_EN, ~0, MXR_INT_EN_ALL);
+
+       mxr_vsync_set_update(mdev, MXR_ENABLE);
+       spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+void mxr_reg_graph_format(struct mxr_device *mdev, int idx,
+       const struct mxr_format *fmt, const struct mxr_geometry *geo)
+{
+       u32 val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&mdev->reg_slock, flags);
+       mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+       /* setup format */
+       mxr_write_mask(mdev, MXR_GRAPHIC_CFG(idx),
+               MXR_GRP_CFG_FORMAT_VAL(fmt->cookie), MXR_GRP_CFG_FORMAT_MASK);
+
+       /* setup geometry */
+       mxr_write(mdev, MXR_GRAPHIC_SPAN(idx), geo->src.full_width);
+       val  = MXR_GRP_WH_WIDTH(geo->src.width);
+       val |= MXR_GRP_WH_HEIGHT(geo->src.height);
+       val |= MXR_GRP_WH_H_SCALE(geo->x_ratio);
+       val |= MXR_GRP_WH_V_SCALE(geo->y_ratio);
+       mxr_write(mdev, MXR_GRAPHIC_WH(idx), val);
+
+       /* setup offsets in source image */
+       val  = MXR_GRP_SXY_SX(geo->src.x_offset);
+       val |= MXR_GRP_SXY_SY(geo->src.y_offset);
+       mxr_write(mdev, MXR_GRAPHIC_SXY(idx), val);
+
+       /* setup offsets in display image */
+       val  = MXR_GRP_DXY_DX(geo->dst.x_offset);
+       val |= MXR_GRP_DXY_DY(geo->dst.y_offset);
+       mxr_write(mdev, MXR_GRAPHIC_DXY(idx), val);
+
+       mxr_vsync_set_update(mdev, MXR_ENABLE);
+       spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+void mxr_reg_vp_format(struct mxr_device *mdev,
+       const struct mxr_format *fmt, const struct mxr_geometry *geo)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&mdev->reg_slock, flags);
+       mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+       vp_write_mask(mdev, VP_MODE, fmt->cookie, VP_MODE_FMT_MASK);
+
+       /* setting size of input image */
+       vp_write(mdev, VP_IMG_SIZE_Y, VP_IMG_HSIZE(geo->src.full_width) |
+               VP_IMG_VSIZE(geo->src.full_height));
+       /* chroma height has to reduced by 2 to avoid chroma distorions */
+       vp_write(mdev, VP_IMG_SIZE_C, VP_IMG_HSIZE(geo->src.full_width) |
+               VP_IMG_VSIZE(geo->src.full_height / 2));
+
+       vp_write(mdev, VP_SRC_WIDTH, geo->src.width);
+       vp_write(mdev, VP_SRC_HEIGHT, geo->src.height);
+       vp_write(mdev, VP_SRC_H_POSITION,
+               VP_SRC_H_POSITION_VAL(geo->src.x_offset));
+       vp_write(mdev, VP_SRC_V_POSITION, geo->src.y_offset);
+
+       vp_write(mdev, VP_DST_WIDTH, geo->dst.width);
+       vp_write(mdev, VP_DST_H_POSITION, geo->dst.x_offset);
+       if (geo->dst.field == V4L2_FIELD_INTERLACED) {
+               vp_write(mdev, VP_DST_HEIGHT, geo->dst.height / 2);
+               vp_write(mdev, VP_DST_V_POSITION, geo->dst.y_offset / 2);
+       } else {
+               vp_write(mdev, VP_DST_HEIGHT, geo->dst.height);
+               vp_write(mdev, VP_DST_V_POSITION, geo->dst.y_offset);
+       }
+
+       vp_write(mdev, VP_H_RATIO, geo->x_ratio);
+       vp_write(mdev, VP_V_RATIO, geo->y_ratio);
+
+       vp_write(mdev, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
+
+       mxr_vsync_set_update(mdev, MXR_ENABLE);
+       spin_unlock_irqrestore(&mdev->reg_slock, flags);
+
+}
+
+void mxr_reg_graph_buffer(struct mxr_device *mdev, int idx, dma_addr_t addr)
+{
+       u32 val = addr ? ~0 : 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&mdev->reg_slock, flags);
+       mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+       if (idx == 0)
+               mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
+       else
+               mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
+       mxr_write(mdev, MXR_GRAPHIC_BASE(idx), addr);
+
+       mxr_vsync_set_update(mdev, MXR_ENABLE);
+       spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+void mxr_reg_vp_buffer(struct mxr_device *mdev,
+       dma_addr_t luma_addr[2], dma_addr_t chroma_addr[2])
+{
+       u32 val = luma_addr[0] ? ~0 : 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&mdev->reg_slock, flags);
+       mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+       mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_VP_ENABLE);
+       vp_write_mask(mdev, VP_ENABLE, val, VP_ENABLE_ON);
+       /* TODO: fix tiled mode */
+       vp_write(mdev, VP_TOP_Y_PTR, luma_addr[0]);
+       vp_write(mdev, VP_TOP_C_PTR, chroma_addr[0]);
+       vp_write(mdev, VP_BOT_Y_PTR, luma_addr[1]);
+       vp_write(mdev, VP_BOT_C_PTR, chroma_addr[1]);
+
+       mxr_vsync_set_update(mdev, MXR_ENABLE);
+       spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+static void mxr_irq_layer_handle(struct mxr_layer *layer)
+{
+       struct list_head *head = &layer->enq_list;
+       struct mxr_buffer *done;
+
+       /* skip non-existing layer */
+       if (layer == NULL)
+               return;
+
+       spin_lock(&layer->enq_slock);
+       if (layer->state == MXR_LAYER_IDLE)
+               goto done;
+
+       done = layer->shadow_buf;
+       layer->shadow_buf = layer->update_buf;
+
+       if (list_empty(head)) {
+               if (layer->state != MXR_LAYER_STREAMING)
+                       layer->update_buf = NULL;
+       } else {
+               struct mxr_buffer *next;
+               next = list_first_entry(head, struct mxr_buffer, list);
+               list_del(&next->list);
+               layer->update_buf = next;
+       }
+
+       layer->ops.buffer_set(layer, layer->update_buf);
+
+       if (done && done != layer->shadow_buf)
+               vb2_buffer_done(&done->vb, VB2_BUF_STATE_DONE);
+
+done:
+       spin_unlock(&layer->enq_slock);
+}
+
+irqreturn_t mxr_irq_handler(int irq, void *dev_data)
+{
+       struct mxr_device *mdev = dev_data;
+       u32 i, val;
+
+       spin_lock(&mdev->reg_slock);
+       val = mxr_read(mdev, MXR_INT_STATUS);
+
+       /* wake up process waiting for VSYNC */
+       if (val & MXR_INT_STATUS_VSYNC) {
+               set_bit(MXR_EVENT_VSYNC, &mdev->event_flags);
+               wake_up(&mdev->event_queue);
+       }
+
+       /* clear interrupts */
+       if (~val & MXR_INT_EN_VSYNC) {
+               /* vsync interrupt use different bit for read and clear */
+               val &= ~MXR_INT_EN_VSYNC;
+               val |= MXR_INT_CLEAR_VSYNC;
+       }
+       mxr_write(mdev, MXR_INT_STATUS, val);
+
+       spin_unlock(&mdev->reg_slock);
+       /* leave on non-vsync event */
+       if (~val & MXR_INT_CLEAR_VSYNC)
+               return IRQ_HANDLED;
+       for (i = 0; i < MXR_MAX_LAYERS; ++i)
+               mxr_irq_layer_handle(mdev->layer[i]);
+       return IRQ_HANDLED;
+}
+
+void mxr_reg_s_output(struct mxr_device *mdev, int cookie)
+{
+       u32 val;
+
+       val = cookie == 0 ? MXR_CFG_DST_SDO : MXR_CFG_DST_HDMI;
+       mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_DST_MASK);
+}
+
+void mxr_reg_streamon(struct mxr_device *mdev)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&mdev->reg_slock, flags);
+       /* single write -> no need to block vsync update */
+
+       /* start MIXER */
+       mxr_write_mask(mdev, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
+
+       spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+void mxr_reg_streamoff(struct mxr_device *mdev)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&mdev->reg_slock, flags);
+       /* single write -> no need to block vsync update */
+
+       /* stop MIXER */
+       mxr_write_mask(mdev, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
+
+       spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+int mxr_reg_wait4vsync(struct mxr_device *mdev)
+{
+       int ret;
+
+       clear_bit(MXR_EVENT_VSYNC, &mdev->event_flags);
+       /* TODO: consider adding interruptible */
+       ret = wait_event_timeout(mdev->event_queue,
+               test_bit(MXR_EVENT_VSYNC, &mdev->event_flags),
+               msecs_to_jiffies(1000));
+       if (ret > 0)
+               return 0;
+       if (ret < 0)
+               return ret;
+       mxr_warn(mdev, "no vsync detected - timeout\n");
+       return -ETIME;
+}
+
+void mxr_reg_set_mbus_fmt(struct mxr_device *mdev,
+       struct v4l2_mbus_framefmt *fmt)
+{
+       u32 val = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&mdev->reg_slock, flags);
+       mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+       /* choosing between interlace and progressive mode */
+       if (fmt->field == V4L2_FIELD_INTERLACED)
+               val |= MXR_CFG_SCAN_INTERLACE;
+       else
+               val |= MXR_CFG_SCAN_PROGRASSIVE;
+
+       /* choosing between porper HD and SD mode */
+       if (fmt->height == 480)
+               val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
+       else if (fmt->height == 576)
+               val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
+       else if (fmt->height == 720)
+               val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
+       else if (fmt->height == 1080)
+               val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
+       else
+               WARN(1, "unrecognized mbus height %u!\n", fmt->height);
+
+       mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_SCAN_MASK);
+
+       val = (fmt->field == V4L2_FIELD_INTERLACED) ? ~0 : 0;
+       vp_write_mask(mdev, VP_MODE, val,
+               VP_MODE_LINE_SKIP | VP_MODE_FIELD_ID_AUTO_TOGGLING);
+
+       mxr_vsync_set_update(mdev, MXR_ENABLE);
+       spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+void mxr_reg_graph_layer_stream(struct mxr_device *mdev, int idx, int en)
+{
+       /* no extra actions need to be done */
+}
+
+void mxr_reg_vp_layer_stream(struct mxr_device *mdev, int en)
+{
+       /* no extra actions need to be done */
+}
+
+static const u8 filter_y_horiz_tap8[] = {
+       0,      -1,     -1,     -1,     -1,     -1,     -1,     -1,
+       -1,     -1,     -1,     -1,     -1,     0,      0,      0,
+       0,      2,      4,      5,      6,      6,      6,      6,
+       6,      5,      5,      4,      3,      2,      1,      1,
+       0,      -6,     -12,    -16,    -18,    -20,    -21,    -20,
+       -20,    -18,    -16,    -13,    -10,    -8,     -5,     -2,
+       127,    126,    125,    121,    114,    107,    99,     89,
+       79,     68,     57,     46,     35,     25,     16,     8,
+};
+
+static const u8 filter_y_vert_tap4[] = {
+       0,      -3,     -6,     -8,     -8,     -8,     -8,     -7,
+       -6,     -5,     -4,     -3,     -2,     -1,     -1,     0,
+       127,    126,    124,    118,    111,    102,    92,     81,
+       70,     59,     48,     37,     27,     19,     11,     5,
+       0,      5,      11,     19,     27,     37,     48,     59,
+       70,     81,     92,     102,    111,    118,    124,    126,
+       0,      0,      -1,     -1,     -2,     -3,     -4,     -5,
+       -6,     -7,     -8,     -8,     -8,     -8,     -6,     -3,
+};
+
+static const u8 filter_cr_horiz_tap4[] = {
+       0,      -3,     -6,     -8,     -8,     -8,     -8,     -7,
+       -6,     -5,     -4,     -3,     -2,     -1,     -1,     0,
+       127,    126,    124,    118,    111,    102,    92,     81,
+       70,     59,     48,     37,     27,     19,     11,     5,
+};
+
+static inline void mxr_reg_vp_filter_set(struct mxr_device *mdev,
+       int reg_id, const u8 *data, unsigned int size)
+{
+       /* assure 4-byte align */
+       BUG_ON(size & 3);
+       for (; size; size -= 4, reg_id += 4, data += 4) {
+               u32 val = (data[0] << 24) |  (data[1] << 16) |
+                       (data[2] << 8) | data[3];
+               vp_write(mdev, reg_id, val);
+       }
+}
+
+static void mxr_reg_vp_default_filter(struct mxr_device *mdev)
+{
+       mxr_reg_vp_filter_set(mdev, VP_POLY8_Y0_LL,
+               filter_y_horiz_tap8, sizeof filter_y_horiz_tap8);
+       mxr_reg_vp_filter_set(mdev, VP_POLY4_Y0_LL,
+               filter_y_vert_tap4, sizeof filter_y_vert_tap4);
+       mxr_reg_vp_filter_set(mdev, VP_POLY4_C0_LL,
+               filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4);
+}
+
+static void mxr_reg_mxr_dump(struct mxr_device *mdev)
+{
+#define DUMPREG(reg_id) \
+do { \
+       mxr_dbg(mdev, #reg_id " = %08x\n", \
+               (u32)readl(mdev->res.mxr_regs + reg_id)); \
+} while (0)
+
+       DUMPREG(MXR_STATUS);
+       DUMPREG(MXR_CFG);
+       DUMPREG(MXR_INT_EN);
+       DUMPREG(MXR_INT_STATUS);
+
+       DUMPREG(MXR_LAYER_CFG);
+       DUMPREG(MXR_VIDEO_CFG);
+
+       DUMPREG(MXR_GRAPHIC0_CFG);
+       DUMPREG(MXR_GRAPHIC0_BASE);
+       DUMPREG(MXR_GRAPHIC0_SPAN);
+       DUMPREG(MXR_GRAPHIC0_WH);
+       DUMPREG(MXR_GRAPHIC0_SXY);
+       DUMPREG(MXR_GRAPHIC0_DXY);
+
+       DUMPREG(MXR_GRAPHIC1_CFG);
+       DUMPREG(MXR_GRAPHIC1_BASE);
+       DUMPREG(MXR_GRAPHIC1_SPAN);
+       DUMPREG(MXR_GRAPHIC1_WH);
+       DUMPREG(MXR_GRAPHIC1_SXY);
+       DUMPREG(MXR_GRAPHIC1_DXY);
+#undef DUMPREG
+}
+
+static void mxr_reg_vp_dump(struct mxr_device *mdev)
+{
+#define DUMPREG(reg_id) \
+do { \
+       mxr_dbg(mdev, #reg_id " = %08x\n", \
+               (u32) readl(mdev->res.vp_regs + reg_id)); \
+} while (0)
+
+
+       DUMPREG(VP_ENABLE);
+       DUMPREG(VP_SRESET);
+       DUMPREG(VP_SHADOW_UPDATE);
+       DUMPREG(VP_FIELD_ID);
+       DUMPREG(VP_MODE);
+       DUMPREG(VP_IMG_SIZE_Y);
+       DUMPREG(VP_IMG_SIZE_C);
+       DUMPREG(VP_PER_RATE_CTRL);
+       DUMPREG(VP_TOP_Y_PTR);
+       DUMPREG(VP_BOT_Y_PTR);
+       DUMPREG(VP_TOP_C_PTR);
+       DUMPREG(VP_BOT_C_PTR);
+       DUMPREG(VP_ENDIAN_MODE);
+       DUMPREG(VP_SRC_H_POSITION);
+       DUMPREG(VP_SRC_V_POSITION);
+       DUMPREG(VP_SRC_WIDTH);
+       DUMPREG(VP_SRC_HEIGHT);
+       DUMPREG(VP_DST_H_POSITION);
+       DUMPREG(VP_DST_V_POSITION);
+       DUMPREG(VP_DST_WIDTH);
+       DUMPREG(VP_DST_HEIGHT);
+       DUMPREG(VP_H_RATIO);
+       DUMPREG(VP_V_RATIO);
+
+#undef DUMPREG
+}
+
+void mxr_reg_dump(struct mxr_device *mdev)
+{
+       mxr_reg_mxr_dump(mdev);
+       mxr_reg_vp_dump(mdev);
+}
+
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
new file mode 100644 (file)
index 0000000..43ac22f
--- /dev/null
@@ -0,0 +1,1006 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *
+ * Tomasz Stanislawski, <t.stanislaws@samsung.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
+ */
+
+#include "mixer.h"
+
+#include <media/v4l2-ioctl.h>
+#include <linux/videodev2.h>
+#include <linux/mm.h>
+#include <linux/version.h>
+#include <linux/timer.h>
+#include <media/videobuf2-dma-contig.h>
+
+static int find_reg_callback(struct device *dev, void *p)
+{
+       struct v4l2_subdev **sd = p;
+
+       *sd = dev_get_drvdata(dev);
+       /* non-zero value stops iteration */
+       return 1;
+}
+
+static struct v4l2_subdev *find_and_register_subdev(
+       struct mxr_device *mdev, char *module_name)
+{
+       struct device_driver *drv;
+       struct v4l2_subdev *sd = NULL;
+       int ret;
+
+       /* TODO: add waiting until probe is finished */
+       drv = driver_find(module_name, &platform_bus_type);
+       if (!drv) {
+               mxr_warn(mdev, "module %s is missing\n", module_name);
+               return NULL;
+       }
+       /* driver refcnt is increased, it is safe to iterate over devices */
+       ret = driver_for_each_device(drv, NULL, &sd, find_reg_callback);
+       /* ret == 0 means that find_reg_callback was never executed */
+       if (sd == NULL) {
+               mxr_warn(mdev, "module %s provides no subdev!\n", module_name);
+               goto done;
+       }
+       /* v4l2_device_register_subdev detects if sd is NULL */
+       ret = v4l2_device_register_subdev(&mdev->v4l2_dev, sd);
+       if (ret) {
+               mxr_warn(mdev, "failed to register subdev %s\n", sd->name);
+               sd = NULL;
+       }
+
+done:
+       put_driver(drv);
+       return sd;
+}
+
+int __devinit mxr_acquire_video(struct mxr_device *mdev,
+       struct mxr_output_conf *output_conf, int output_count)
+{
+       struct device *dev = mdev->dev;
+       struct v4l2_device *v4l2_dev = &mdev->v4l2_dev;
+       int i;
+       int ret = 0;
+       struct v4l2_subdev *sd;
+
+       strlcpy(v4l2_dev->name, dev_name(mdev->dev), sizeof(v4l2_dev->name));
+       /* prepare context for V4L2 device */
+       ret = v4l2_device_register(dev, v4l2_dev);
+       if (ret) {
+               mxr_err(mdev, "could not register v4l2 device.\n");
+               goto fail;
+       }
+
+       mdev->alloc_ctx = vb2_dma_contig_init_ctx(mdev->dev);
+       if (IS_ERR_OR_NULL(mdev->alloc_ctx)) {
+               mxr_err(mdev, "could not acquire vb2 allocator\n");
+               goto fail_v4l2_dev;
+       }
+
+       /* registering outputs */
+       mdev->output_cnt = 0;
+       for (i = 0; i < output_count; ++i) {
+               struct mxr_output_conf *conf = &output_conf[i];
+               struct mxr_output *out;
+
+               sd = find_and_register_subdev(mdev, conf->module_name);
+               /* trying to register next output */
+               if (sd == NULL)
+                       continue;
+               out = kzalloc(sizeof *out, GFP_KERNEL);
+               if (out == NULL) {
+                       mxr_err(mdev, "no memory for '%s'\n",
+                               conf->output_name);
+                       ret = -ENOMEM;
+                       /* registered subdevs are removed in fail_v4l2_dev */
+                       goto fail_output;
+               }
+               strlcpy(out->name, conf->output_name, sizeof(out->name));
+               out->sd = sd;
+               out->cookie = conf->cookie;
+               mdev->output[mdev->output_cnt++] = out;
+               mxr_info(mdev, "added output '%s' from module '%s'\n",
+                       conf->output_name, conf->module_name);
+               /* checking if maximal number of outputs is reached */
+               if (mdev->output_cnt >= MXR_MAX_OUTPUTS)
+                       break;
+       }
+
+       if (mdev->output_cnt == 0) {
+               mxr_err(mdev, "failed to register any output\n");
+               ret = -ENODEV;
+               /* skipping fail_output because there is nothing to free */
+               goto fail_vb2_allocator;
+       }
+
+       return 0;
+
+fail_output:
+       /* kfree is NULL-safe */
+       for (i = 0; i < mdev->output_cnt; ++i)
+               kfree(mdev->output[i]);
+       memset(mdev->output, 0, sizeof mdev->output);
+
+fail_vb2_allocator:
+       /* freeing allocator context */
+       vb2_dma_contig_cleanup_ctx(mdev->alloc_ctx);
+
+fail_v4l2_dev:
+       /* NOTE: automatically unregister all subdevs */
+       v4l2_device_unregister(v4l2_dev);
+
+fail:
+       return ret;
+}
+
+void __devexit mxr_release_video(struct mxr_device *mdev)
+{
+       int i;
+
+       /* kfree is NULL-safe */
+       for (i = 0; i < mdev->output_cnt; ++i)
+               kfree(mdev->output[i]);
+
+       vb2_dma_contig_cleanup_ctx(mdev->alloc_ctx);
+       v4l2_device_unregister(&mdev->v4l2_dev);
+}
+
+static int mxr_querycap(struct file *file, void *priv,
+       struct v4l2_capability *cap)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+
+       strlcpy(cap->driver, MXR_DRIVER_NAME, sizeof cap->driver);
+       strlcpy(cap->card, layer->vfd.name, sizeof cap->card);
+       sprintf(cap->bus_info, "%d", layer->idx);
+       cap->version = KERNEL_VERSION(0, 1, 0);
+       cap->capabilities = V4L2_CAP_STREAMING |
+               V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
+
+       return 0;
+}
+
+/* Geometry handling */
+static void mxr_layer_geo_fix(struct mxr_layer *layer)
+{
+       struct mxr_device *mdev = layer->mdev;
+       struct v4l2_mbus_framefmt mbus_fmt;
+
+       /* TODO: add some dirty flag to avoid unnecessary adjustments */
+       mxr_get_mbus_fmt(mdev, &mbus_fmt);
+       layer->geo.dst.full_width = mbus_fmt.width;
+       layer->geo.dst.full_height = mbus_fmt.height;
+       layer->geo.dst.field = mbus_fmt.field;
+       layer->ops.fix_geometry(layer);
+}
+
+static void mxr_layer_default_geo(struct mxr_layer *layer)
+{
+       struct mxr_device *mdev = layer->mdev;
+       struct v4l2_mbus_framefmt mbus_fmt;
+
+       memset(&layer->geo, 0, sizeof layer->geo);
+
+       mxr_get_mbus_fmt(mdev, &mbus_fmt);
+
+       layer->geo.dst.full_width = mbus_fmt.width;
+       layer->geo.dst.full_height = mbus_fmt.height;
+       layer->geo.dst.width = layer->geo.dst.full_width;
+       layer->geo.dst.height = layer->geo.dst.full_height;
+       layer->geo.dst.field = mbus_fmt.field;
+
+       layer->geo.src.full_width = mbus_fmt.width;
+       layer->geo.src.full_height = mbus_fmt.height;
+       layer->geo.src.width = layer->geo.src.full_width;
+       layer->geo.src.height = layer->geo.src.full_height;
+
+       layer->ops.fix_geometry(layer);
+}
+
+static void mxr_geometry_dump(struct mxr_device *mdev, struct mxr_geometry *geo)
+{
+       mxr_dbg(mdev, "src.full_size = (%u, %u)\n",
+               geo->src.full_width, geo->src.full_height);
+       mxr_dbg(mdev, "src.size = (%u, %u)\n",
+               geo->src.width, geo->src.height);
+       mxr_dbg(mdev, "src.offset = (%u, %u)\n",
+               geo->src.x_offset, geo->src.y_offset);
+       mxr_dbg(mdev, "dst.full_size = (%u, %u)\n",
+               geo->dst.full_width, geo->dst.full_height);
+       mxr_dbg(mdev, "dst.size = (%u, %u)\n",
+               geo->dst.width, geo->dst.height);
+       mxr_dbg(mdev, "dst.offset = (%u, %u)\n",
+               geo->dst.x_offset, geo->dst.y_offset);
+       mxr_dbg(mdev, "ratio = (%u, %u)\n",
+               geo->x_ratio, geo->y_ratio);
+}
+
+
+static const struct mxr_format *find_format_by_fourcc(
+       struct mxr_layer *layer, unsigned long fourcc);
+static const struct mxr_format *find_format_by_index(
+       struct mxr_layer *layer, unsigned long index);
+
+static int mxr_enum_fmt(struct file *file, void  *priv,
+       struct v4l2_fmtdesc *f)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_device *mdev = layer->mdev;
+       const struct mxr_format *fmt;
+
+       mxr_dbg(mdev, "%s\n", __func__);
+       fmt = find_format_by_index(layer, f->index);
+       if (fmt == NULL)
+               return -EINVAL;
+
+       strlcpy(f->description, fmt->name, sizeof(f->description));
+       f->pixelformat = fmt->fourcc;
+
+       return 0;
+}
+
+static int mxr_s_fmt(struct file *file, void *priv,
+       struct v4l2_format *f)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       const struct mxr_format *fmt;
+       struct v4l2_pix_format_mplane *pix;
+       struct mxr_device *mdev = layer->mdev;
+       struct mxr_geometry *geo = &layer->geo;
+
+       mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__);
+
+       pix = &f->fmt.pix_mp;
+       fmt = find_format_by_fourcc(layer, pix->pixelformat);
+       if (fmt == NULL) {
+               mxr_warn(mdev, "not recognized fourcc: %08x\n",
+                       pix->pixelformat);
+               return -EINVAL;
+       }
+       layer->fmt = fmt;
+       geo->src.full_width = pix->width;
+       geo->src.width = pix->width;
+       geo->src.full_height = pix->height;
+       geo->src.height = pix->height;
+       /* assure consistency of geometry */
+       mxr_layer_geo_fix(layer);
+       mxr_dbg(mdev, "width=%u height=%u span=%u\n",
+               geo->src.width, geo->src.height, geo->src.full_width);
+
+       return 0;
+}
+
+static unsigned int divup(unsigned int divident, unsigned int divisor)
+{
+       return (divident + divisor - 1) / divisor;
+}
+
+unsigned long mxr_get_plane_size(const struct mxr_block *blk,
+       unsigned int width, unsigned int height)
+{
+       unsigned int bl_width = divup(width, blk->width);
+       unsigned int bl_height = divup(height, blk->height);
+
+       return bl_width * bl_height * blk->size;
+}
+
+static void mxr_mplane_fill(struct v4l2_plane_pix_format *planes,
+       const struct mxr_format *fmt, u32 width, u32 height)
+{
+       int i;
+
+       memset(planes, 0, sizeof(*planes) * fmt->num_subframes);
+       for (i = 0; i < fmt->num_planes; ++i) {
+               struct v4l2_plane_pix_format *plane = planes
+                       + fmt->plane2subframe[i];
+               const struct mxr_block *blk = &fmt->plane[i];
+               u32 bl_width = divup(width, blk->width);
+               u32 bl_height = divup(height, blk->height);
+               u32 sizeimage = bl_width * bl_height * blk->size;
+               u16 bytesperline = bl_width * blk->size / blk->height;
+
+               plane->sizeimage += sizeimage;
+               plane->bytesperline = max(plane->bytesperline, bytesperline);
+       }
+}
+
+static int mxr_g_fmt(struct file *file, void *priv,
+                            struct v4l2_format *f)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+
+       pix->width = layer->geo.src.full_width;
+       pix->height = layer->geo.src.full_height;
+       pix->field = V4L2_FIELD_NONE;
+       pix->pixelformat = layer->fmt->fourcc;
+       pix->colorspace = layer->fmt->colorspace;
+       mxr_mplane_fill(pix->plane_fmt, layer->fmt, pix->width, pix->height);
+
+       return 0;
+}
+
+static inline struct mxr_crop *choose_crop_by_type(struct mxr_geometry *geo,
+       enum v4l2_buf_type type)
+{
+       switch (type) {
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+               return &geo->dst;
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+               return &geo->src;
+       default:
+               return NULL;
+       }
+}
+
+static int mxr_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_crop *crop;
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+       crop = choose_crop_by_type(&layer->geo, a->type);
+       if (crop == NULL)
+               return -EINVAL;
+       mxr_layer_geo_fix(layer);
+       a->c.left = crop->x_offset;
+       a->c.top = crop->y_offset;
+       a->c.width = crop->width;
+       a->c.height = crop->height;
+       return 0;
+}
+
+static int mxr_s_crop(struct file *file, void *fh, struct v4l2_crop *a)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_crop *crop;
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+       crop = choose_crop_by_type(&layer->geo, a->type);
+       if (crop == NULL)
+               return -EINVAL;
+       crop->x_offset = a->c.left;
+       crop->y_offset = a->c.top;
+       crop->width = a->c.width;
+       crop->height = a->c.height;
+       mxr_layer_geo_fix(layer);
+       return 0;
+}
+
+static int mxr_cropcap(struct file *file, void *fh, struct v4l2_cropcap *a)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_crop *crop;
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+       crop = choose_crop_by_type(&layer->geo, a->type);
+       if (crop == NULL)
+               return -EINVAL;
+       mxr_layer_geo_fix(layer);
+       a->bounds.left = 0;
+       a->bounds.top = 0;
+       a->bounds.width = crop->full_width;
+       a->bounds.top = crop->full_height;
+       a->defrect = a->bounds;
+       /* setting pixel aspect to 1/1 */
+       a->pixelaspect.numerator = 1;
+       a->pixelaspect.denominator = 1;
+       return 0;
+}
+
+static int mxr_enum_dv_presets(struct file *file, void *fh,
+       struct v4l2_dv_enum_preset *preset)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_device *mdev = layer->mdev;
+       int ret;
+
+       /* lock protects from changing sd_out */
+       mutex_lock(&mdev->mutex);
+       ret = v4l2_subdev_call(to_outsd(mdev), video, enum_dv_presets, preset);
+       mutex_unlock(&mdev->mutex);
+
+       return ret ? -EINVAL : 0;
+}
+
+static int mxr_s_dv_preset(struct file *file, void *fh,
+       struct v4l2_dv_preset *preset)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_device *mdev = layer->mdev;
+       int ret;
+
+       /* lock protects from changing sd_out */
+       mutex_lock(&mdev->mutex);
+
+       /* preset change cannot be done while there is an entity
+        * dependant on output configuration
+        */
+       if (mdev->n_output > 0) {
+               mutex_unlock(&mdev->mutex);
+               return -EBUSY;
+       }
+
+       ret = v4l2_subdev_call(to_outsd(mdev), video, s_dv_preset, preset);
+
+       mutex_unlock(&mdev->mutex);
+
+       /* any failure should return EINVAL according to V4L2 doc */
+       return ret ? -EINVAL : 0;
+}
+
+static int mxr_g_dv_preset(struct file *file, void *fh,
+       struct v4l2_dv_preset *preset)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_device *mdev = layer->mdev;
+       int ret;
+
+       /* lock protects from changing sd_out */
+       mutex_lock(&mdev->mutex);
+       ret = v4l2_subdev_call(to_outsd(mdev), video, g_dv_preset, preset);
+       mutex_unlock(&mdev->mutex);
+
+       return ret ? -EINVAL : 0;
+}
+
+static int mxr_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_device *mdev = layer->mdev;
+       int ret;
+
+       /* lock protects from changing sd_out */
+       mutex_lock(&mdev->mutex);
+
+       /* standard change cannot be done while there is an entity
+        * dependant on output configuration
+        */
+       if (mdev->n_output > 0) {
+               mutex_unlock(&mdev->mutex);
+               return -EBUSY;
+       }
+
+       ret = v4l2_subdev_call(to_outsd(mdev), video, s_std_output, *norm);
+
+       mutex_unlock(&mdev->mutex);
+
+       return ret ? -EINVAL : 0;
+}
+
+static int mxr_g_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_device *mdev = layer->mdev;
+       int ret;
+
+       /* lock protects from changing sd_out */
+       mutex_lock(&mdev->mutex);
+       ret = v4l2_subdev_call(to_outsd(mdev), video, g_std_output, norm);
+       mutex_unlock(&mdev->mutex);
+
+       return ret ? -EINVAL : 0;
+}
+
+static int mxr_enum_output(struct file *file, void *fh, struct v4l2_output *a)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_device *mdev = layer->mdev;
+       struct mxr_output *out;
+       struct v4l2_subdev *sd;
+
+       if (a->index >= mdev->output_cnt)
+               return -EINVAL;
+       out = mdev->output[a->index];
+       BUG_ON(out == NULL);
+       sd = out->sd;
+       strlcpy(a->name, out->name, sizeof(a->name));
+
+       /* try to obtain supported tv norms */
+       v4l2_subdev_call(sd, video, g_tvnorms_output, &a->std);
+       a->capabilities = 0;
+       if (sd->ops->video && sd->ops->video->s_dv_preset)
+               a->capabilities |= V4L2_OUT_CAP_PRESETS;
+       if (sd->ops->video && sd->ops->video->s_std_output)
+               a->capabilities |= V4L2_OUT_CAP_STD;
+       a->type = V4L2_OUTPUT_TYPE_ANALOG;
+
+       return 0;
+}
+
+static int mxr_s_output(struct file *file, void *fh, unsigned int i)
+{
+       struct video_device *vfd = video_devdata(file);
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_device *mdev = layer->mdev;
+       int ret = 0;
+
+       if (i >= mdev->output_cnt || mdev->output[i] == NULL)
+               return -EINVAL;
+
+       mutex_lock(&mdev->mutex);
+       if (mdev->n_output > 0) {
+               ret = -EBUSY;
+               goto done;
+       }
+       mdev->current_output = i;
+       vfd->tvnorms = 0;
+       v4l2_subdev_call(to_outsd(mdev), video, g_tvnorms_output,
+               &vfd->tvnorms);
+       mxr_dbg(mdev, "tvnorms = %08llx\n", vfd->tvnorms);
+
+done:
+       mutex_unlock(&mdev->mutex);
+       return ret;
+}
+
+static int mxr_g_output(struct file *file, void *fh, unsigned int *p)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_device *mdev = layer->mdev;
+
+       mutex_lock(&mdev->mutex);
+       *p = mdev->current_output;
+       mutex_unlock(&mdev->mutex);
+
+       return 0;
+}
+
+static int mxr_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *p)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+       return vb2_reqbufs(&layer->vb_queue, p);
+}
+
+static int mxr_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+       return vb2_querybuf(&layer->vb_queue, p);
+}
+
+static int mxr_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+
+       mxr_dbg(layer->mdev, "%s:%d(%d)\n", __func__, __LINE__, p->index);
+       return vb2_qbuf(&layer->vb_queue, p);
+}
+
+static int mxr_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+       return vb2_dqbuf(&layer->vb_queue, p, file->f_flags & O_NONBLOCK);
+}
+
+static int mxr_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+       return vb2_streamon(&layer->vb_queue, i);
+}
+
+static int mxr_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+       return vb2_streamoff(&layer->vb_queue, i);
+}
+
+static const struct v4l2_ioctl_ops mxr_ioctl_ops = {
+       .vidioc_querycap = mxr_querycap,
+       /* format handling */
+       .vidioc_enum_fmt_vid_out = mxr_enum_fmt,
+       .vidioc_s_fmt_vid_out_mplane = mxr_s_fmt,
+       .vidioc_g_fmt_vid_out_mplane = mxr_g_fmt,
+       /* buffer control */
+       .vidioc_reqbufs = mxr_reqbufs,
+       .vidioc_querybuf = mxr_querybuf,
+       .vidioc_qbuf = mxr_qbuf,
+       .vidioc_dqbuf = mxr_dqbuf,
+       /* Streaming control */
+       .vidioc_streamon = mxr_streamon,
+       .vidioc_streamoff = mxr_streamoff,
+       /* Preset functions */
+       .vidioc_enum_dv_presets = mxr_enum_dv_presets,
+       .vidioc_s_dv_preset = mxr_s_dv_preset,
+       .vidioc_g_dv_preset = mxr_g_dv_preset,
+       /* analog TV standard functions */
+       .vidioc_s_std = mxr_s_std,
+       .vidioc_g_std = mxr_g_std,
+       /* Output handling */
+       .vidioc_enum_output = mxr_enum_output,
+       .vidioc_s_output = mxr_s_output,
+       .vidioc_g_output = mxr_g_output,
+       /* Crop ioctls */
+       .vidioc_g_crop = mxr_g_crop,
+       .vidioc_s_crop = mxr_s_crop,
+       .vidioc_cropcap = mxr_cropcap,
+};
+
+static int mxr_video_open(struct file *file)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+       struct mxr_device *mdev = layer->mdev;
+       int ret = 0;
+
+       mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__);
+       /* assure device probe is finished */
+       wait_for_device_probe();
+       /* creating context for file descriptor */
+       ret = v4l2_fh_open(file);
+       if (ret) {
+               mxr_err(mdev, "v4l2_fh_open failed\n");
+               return ret;
+       }
+
+       /* leaving if layer is already initialized */
+       if (!v4l2_fh_is_singular_file(file))
+               return 0;
+
+       /* FIXME: should power be enabled on open? */
+       ret = mxr_power_get(mdev);
+       if (ret) {
+               mxr_err(mdev, "power on failed\n");
+               goto fail_fh_open;
+       }
+
+       ret = vb2_queue_init(&layer->vb_queue);
+       if (ret != 0) {
+               mxr_err(mdev, "failed to initialize vb2 queue\n");
+               goto fail_power;
+       }
+       /* set default format, first on the list */
+       layer->fmt = layer->fmt_array[0];
+       /* setup default geometry */
+       mxr_layer_default_geo(layer);
+
+       return 0;
+
+fail_power:
+       mxr_power_put(mdev);
+
+fail_fh_open:
+       v4l2_fh_release(file);
+
+       return ret;
+}
+
+static unsigned int
+mxr_video_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+
+       return vb2_poll(&layer->vb_queue, file, wait);
+}
+
+static int mxr_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+
+       return vb2_mmap(&layer->vb_queue, vma);
+}
+
+static int mxr_video_release(struct file *file)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+       if (v4l2_fh_is_singular_file(file)) {
+               vb2_queue_release(&layer->vb_queue);
+               mxr_power_put(layer->mdev);
+       }
+       v4l2_fh_release(file);
+       return 0;
+}
+
+static const struct v4l2_file_operations mxr_fops = {
+       .owner = THIS_MODULE,
+       .open = mxr_video_open,
+       .poll = mxr_video_poll,
+       .mmap = mxr_video_mmap,
+       .release = mxr_video_release,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+       unsigned int *nplanes, unsigned long sizes[],
+       void *alloc_ctxs[])
+{
+       struct mxr_layer *layer = vb2_get_drv_priv(vq);
+       const struct mxr_format *fmt = layer->fmt;
+       int i;
+       struct mxr_device *mdev = layer->mdev;
+       struct v4l2_plane_pix_format planes[3];
+
+       mxr_dbg(mdev, "%s\n", __func__);
+       /* checking if format was configured */
+       if (fmt == NULL)
+               return -EINVAL;
+       mxr_dbg(mdev, "fmt = %s\n", fmt->name);
+       mxr_mplane_fill(planes, fmt, layer->geo.src.full_width,
+               layer->geo.src.full_height);
+
+       *nplanes = fmt->num_subframes;
+       for (i = 0; i < fmt->num_subframes; ++i) {
+               alloc_ctxs[i] = layer->mdev->alloc_ctx;
+               sizes[i] = PAGE_ALIGN(planes[i].sizeimage);
+               mxr_dbg(mdev, "size[%d] = %08lx\n", i, sizes[i]);
+       }
+
+       if (*nbuffers == 0)
+               *nbuffers = 1;
+
+       return 0;
+}
+
+static void buf_queue(struct vb2_buffer *vb)
+{
+       struct mxr_buffer *buffer = container_of(vb, struct mxr_buffer, vb);
+       struct mxr_layer *layer = vb2_get_drv_priv(vb->vb2_queue);
+       struct mxr_device *mdev = layer->mdev;
+       unsigned long flags;
+       int must_start = 0;
+
+       spin_lock_irqsave(&layer->enq_slock, flags);
+       if (layer->state == MXR_LAYER_STREAMING_START) {
+               layer->state = MXR_LAYER_STREAMING;
+               must_start = 1;
+       }
+       list_add_tail(&buffer->list, &layer->enq_list);
+       spin_unlock_irqrestore(&layer->enq_slock, flags);
+       if (must_start) {
+               layer->ops.stream_set(layer, MXR_ENABLE);
+               mxr_streamer_get(mdev);
+       }
+
+       mxr_dbg(mdev, "queuing buffer\n");
+}
+
+static void wait_lock(struct vb2_queue *vq)
+{
+       struct mxr_layer *layer = vb2_get_drv_priv(vq);
+
+       mxr_dbg(layer->mdev, "%s\n", __func__);
+       mutex_lock(&layer->mutex);
+}
+
+static void wait_unlock(struct vb2_queue *vq)
+{
+       struct mxr_layer *layer = vb2_get_drv_priv(vq);
+
+       mxr_dbg(layer->mdev, "%s\n", __func__);
+       mutex_unlock(&layer->mutex);
+}
+
+static int start_streaming(struct vb2_queue *vq)
+{
+       struct mxr_layer *layer = vb2_get_drv_priv(vq);
+       struct mxr_device *mdev = layer->mdev;
+       unsigned long flags;
+
+       mxr_dbg(mdev, "%s\n", __func__);
+       /* block any changes in output configuration */
+       mxr_output_get(mdev);
+
+       /* update layers geometry */
+       mxr_layer_geo_fix(layer);
+       mxr_geometry_dump(mdev, &layer->geo);
+
+       layer->ops.format_set(layer);
+       /* enabling layer in hardware */
+       spin_lock_irqsave(&layer->enq_slock, flags);
+       layer->state = MXR_LAYER_STREAMING_START;
+       spin_unlock_irqrestore(&layer->enq_slock, flags);
+
+       return 0;
+}
+
+static void mxr_watchdog(unsigned long arg)
+{
+       struct mxr_layer *layer = (struct mxr_layer *) arg;
+       struct mxr_device *mdev = layer->mdev;
+       unsigned long flags;
+
+       mxr_err(mdev, "watchdog fired for layer %s\n", layer->vfd.name);
+
+       spin_lock_irqsave(&layer->enq_slock, flags);
+
+       if (layer->update_buf == layer->shadow_buf)
+               layer->update_buf = NULL;
+       if (layer->update_buf) {
+               vb2_buffer_done(&layer->update_buf->vb, VB2_BUF_STATE_ERROR);
+               layer->update_buf = NULL;
+       }
+       if (layer->shadow_buf) {
+               vb2_buffer_done(&layer->shadow_buf->vb, VB2_BUF_STATE_ERROR);
+               layer->shadow_buf = NULL;
+       }
+       spin_unlock_irqrestore(&layer->enq_slock, flags);
+}
+
+static int stop_streaming(struct vb2_queue *vq)
+{
+       struct mxr_layer *layer = vb2_get_drv_priv(vq);
+       struct mxr_device *mdev = layer->mdev;
+       unsigned long flags;
+       struct timer_list watchdog;
+       struct mxr_buffer *buf, *buf_tmp;
+
+       mxr_dbg(mdev, "%s\n", __func__);
+
+       spin_lock_irqsave(&layer->enq_slock, flags);
+
+       /* reset list */
+       layer->state = MXR_LAYER_STREAMING_FINISH;
+
+       /* set all buffer to be done */
+       list_for_each_entry_safe(buf, buf_tmp, &layer->enq_list, list) {
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+       }
+
+       spin_unlock_irqrestore(&layer->enq_slock, flags);
+
+       /* give 1 seconds to complete to complete last buffers */
+       setup_timer_on_stack(&watchdog, mxr_watchdog,
+               (unsigned long)layer);
+       mod_timer(&watchdog, jiffies + msecs_to_jiffies(1000));
+
+       /* wait until all buffers are goes to done state */
+       vb2_wait_for_all_buffers(vq);
+
+       /* stop timer if all synchronization is done */
+       del_timer_sync(&watchdog);
+       destroy_timer_on_stack(&watchdog);
+
+       /* stopping hardware */
+       spin_lock_irqsave(&layer->enq_slock, flags);
+       layer->state = MXR_LAYER_IDLE;
+       spin_unlock_irqrestore(&layer->enq_slock, flags);
+
+       /* disabling layer in hardware */
+       layer->ops.stream_set(layer, MXR_DISABLE);
+       /* remove one streamer */
+       mxr_streamer_put(mdev);
+       /* allow changes in output configuration */
+       mxr_output_put(mdev);
+       return 0;
+}
+
+static struct vb2_ops mxr_video_qops = {
+       .queue_setup = queue_setup,
+       .buf_queue = buf_queue,
+       .wait_prepare = wait_unlock,
+       .wait_finish = wait_lock,
+       .start_streaming = start_streaming,
+       .stop_streaming = stop_streaming,
+};
+
+/* FIXME: try to put this functions to mxr_base_layer_create */
+int mxr_base_layer_register(struct mxr_layer *layer)
+{
+       struct mxr_device *mdev = layer->mdev;
+       int ret;
+
+       ret = video_register_device(&layer->vfd, VFL_TYPE_GRABBER, -1);
+       if (ret)
+               mxr_err(mdev, "failed to register video device\n");
+       else
+               mxr_info(mdev, "registered layer %s as /dev/video%d\n",
+                       layer->vfd.name, layer->vfd.num);
+       return ret;
+}
+
+void mxr_base_layer_unregister(struct mxr_layer *layer)
+{
+       video_unregister_device(&layer->vfd);
+}
+
+void mxr_layer_release(struct mxr_layer *layer)
+{
+       if (layer->ops.release)
+               layer->ops.release(layer);
+}
+
+void mxr_base_layer_release(struct mxr_layer *layer)
+{
+       kfree(layer);
+}
+
+static void mxr_vfd_release(struct video_device *vdev)
+{
+       printk(KERN_INFO "video device release\n");
+}
+
+struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
+       int idx, char *name, struct mxr_layer_ops *ops)
+{
+       struct mxr_layer *layer;
+
+       layer = kzalloc(sizeof *layer, GFP_KERNEL);
+       if (layer == NULL) {
+               mxr_err(mdev, "not enough memory for layer.\n");
+               goto fail;
+       }
+
+       layer->mdev = mdev;
+       layer->idx = idx;
+       layer->ops = *ops;
+
+       spin_lock_init(&layer->enq_slock);
+       INIT_LIST_HEAD(&layer->enq_list);
+       mutex_init(&layer->mutex);
+
+       layer->vfd = (struct video_device) {
+               .minor = -1,
+               .release = mxr_vfd_release,
+               .fops = &mxr_fops,
+               .ioctl_ops = &mxr_ioctl_ops,
+       };
+       strlcpy(layer->vfd.name, name, sizeof(layer->vfd.name));
+       /* let framework control PRIORITY */
+       set_bit(V4L2_FL_USE_FH_PRIO, &layer->vfd.flags);
+
+       video_set_drvdata(&layer->vfd, layer);
+       layer->vfd.lock = &layer->mutex;
+       layer->vfd.v4l2_dev = &mdev->v4l2_dev;
+
+       layer->vb_queue = (struct vb2_queue) {
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+               .io_modes = VB2_MMAP | VB2_USERPTR,
+               .drv_priv = layer,
+               .buf_struct_size = sizeof(struct mxr_buffer),
+               .ops = &mxr_video_qops,
+               .mem_ops = &vb2_dma_contig_memops,
+       };
+
+       return layer;
+
+fail:
+       return NULL;
+}
+
+static const struct mxr_format *find_format_by_fourcc(
+       struct mxr_layer *layer, unsigned long fourcc)
+{
+       int i;
+
+       for (i = 0; i < layer->fmt_array_size; ++i)
+               if (layer->fmt_array[i]->fourcc == fourcc)
+                       return layer->fmt_array[i];
+       return NULL;
+}
+
+static const struct mxr_format *find_format_by_index(
+       struct mxr_layer *layer, unsigned long index)
+{
+       if (index >= layer->fmt_array_size)
+               return NULL;
+       return layer->fmt_array[index];
+}
+
diff --git a/drivers/media/video/s5p-tv/mixer_vp_layer.c b/drivers/media/video/s5p-tv/mixer_vp_layer.c
new file mode 100644 (file)
index 0000000..6950ed8
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *
+ * Tomasz Stanislawski, <t.stanislaws@samsung.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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#include "mixer.h"
+
+#include "regs-vp.h"
+
+#include <media/videobuf2-dma-contig.h>
+
+/* FORMAT DEFINITIONS */
+static const struct mxr_format mxr_fmt_nv12 = {
+       .name = "NV12",
+       .fourcc = V4L2_PIX_FMT_NV12,
+       .colorspace = V4L2_COLORSPACE_JPEG,
+       .num_planes = 2,
+       .plane = {
+               { .width = 1, .height = 1, .size = 1 },
+               { .width = 2, .height = 2, .size = 2 },
+       },
+       .num_subframes = 1,
+       .cookie = VP_MODE_NV12 | VP_MODE_MEM_LINEAR,
+};
+
+static const struct mxr_format mxr_fmt_nv21 = {
+       .name = "NV21",
+       .fourcc = V4L2_PIX_FMT_NV21,
+       .colorspace = V4L2_COLORSPACE_JPEG,
+       .num_planes = 2,
+       .plane = {
+               { .width = 1, .height = 1, .size = 1 },
+               { .width = 2, .height = 2, .size = 2 },
+       },
+       .num_subframes = 1,
+       .cookie = VP_MODE_NV21 | VP_MODE_MEM_LINEAR,
+};
+
+static const struct mxr_format mxr_fmt_nv12m = {
+       .name = "NV12 (mplane)",
+       .fourcc = V4L2_PIX_FMT_NV12M,
+       .colorspace = V4L2_COLORSPACE_JPEG,
+       .num_planes = 2,
+       .plane = {
+               { .width = 1, .height = 1, .size = 1 },
+               { .width = 2, .height = 2, .size = 2 },
+       },
+       .num_subframes = 2,
+       .plane2subframe = {0, 1},
+       .cookie = VP_MODE_NV12 | VP_MODE_MEM_LINEAR,
+};
+
+static const struct mxr_format mxr_fmt_nv12mt = {
+       .name = "NV12 tiled (mplane)",
+       .fourcc = V4L2_PIX_FMT_NV12MT,
+       .colorspace = V4L2_COLORSPACE_JPEG,
+       .num_planes = 2,
+       .plane = {
+               { .width = 128, .height = 32, .size = 4096 },
+               { .width = 128, .height = 32, .size = 2048 },
+       },
+       .num_subframes = 2,
+       .plane2subframe = {0, 1},
+       .cookie = VP_MODE_NV12 | VP_MODE_MEM_TILED,
+};
+
+static const struct mxr_format *mxr_video_format[] = {
+       &mxr_fmt_nv12,
+       &mxr_fmt_nv21,
+       &mxr_fmt_nv12m,
+       &mxr_fmt_nv12mt,
+};
+
+/* AUXILIARY CALLBACKS */
+
+static void mxr_vp_layer_release(struct mxr_layer *layer)
+{
+       mxr_base_layer_unregister(layer);
+       mxr_base_layer_release(layer);
+}
+
+static void mxr_vp_buffer_set(struct mxr_layer *layer,
+       struct mxr_buffer *buf)
+{
+       dma_addr_t luma_addr[2] = {0, 0};
+       dma_addr_t chroma_addr[2] = {0, 0};
+
+       if (buf == NULL) {
+               mxr_reg_vp_buffer(layer->mdev, luma_addr, chroma_addr);
+               return;
+       }
+       luma_addr[0] = vb2_dma_contig_plane_paddr(&buf->vb, 0);
+       if (layer->fmt->num_subframes == 2) {
+               chroma_addr[0] = vb2_dma_contig_plane_paddr(&buf->vb, 1);
+       } else {
+               /* FIXME: mxr_get_plane_size compute integer division,
+                * which is slow and should not be performed in interrupt */
+               chroma_addr[0] = luma_addr[0] + mxr_get_plane_size(
+                       &layer->fmt->plane[0], layer->geo.src.full_width,
+                       layer->geo.src.full_height);
+       }
+       if (layer->fmt->cookie & VP_MODE_MEM_TILED) {
+               luma_addr[1] = luma_addr[0] + 0x40;
+               chroma_addr[1] = chroma_addr[0] + 0x40;
+       } else {
+               luma_addr[1] = luma_addr[0] + layer->geo.src.full_width;
+               chroma_addr[1] = chroma_addr[0];
+       }
+       mxr_reg_vp_buffer(layer->mdev, luma_addr, chroma_addr);
+}
+
+static void mxr_vp_stream_set(struct mxr_layer *layer, int en)
+{
+       mxr_reg_vp_layer_stream(layer->mdev, en);
+}
+
+static void mxr_vp_format_set(struct mxr_layer *layer)
+{
+       mxr_reg_vp_format(layer->mdev, layer->fmt, &layer->geo);
+}
+
+static void mxr_vp_fix_geometry(struct mxr_layer *layer)
+{
+       struct mxr_geometry *geo = &layer->geo;
+
+       /* align horizontal size to 8 pixels */
+       geo->src.full_width = ALIGN(geo->src.full_width, 8);
+       /* limit to boundary size */
+       geo->src.full_width = clamp_val(geo->src.full_width, 8, 8192);
+       geo->src.full_height = clamp_val(geo->src.full_height, 1, 8192);
+       geo->src.width = clamp_val(geo->src.width, 32, geo->src.full_width);
+       geo->src.width = min(geo->src.width, 2047U);
+       geo->src.height = clamp_val(geo->src.height, 4, geo->src.full_height);
+       geo->src.height = min(geo->src.height, 2047U);
+
+       /* setting size of output window */
+       geo->dst.width = clamp_val(geo->dst.width, 8, geo->dst.full_width);
+       geo->dst.height = clamp_val(geo->dst.height, 1, geo->dst.full_height);
+
+       /* ensure that scaling is in range 1/4x to 16x */
+       if (geo->src.width >= 4 * geo->dst.width)
+               geo->src.width = 4 * geo->dst.width;
+       if (geo->dst.width >= 16 * geo->src.width)
+               geo->dst.width = 16 * geo->src.width;
+       if (geo->src.height >= 4 * geo->dst.height)
+               geo->src.height = 4 * geo->dst.height;
+       if (geo->dst.height >= 16 * geo->src.height)
+               geo->dst.height = 16 * geo->src.height;
+
+       /* setting scaling ratio */
+       geo->x_ratio = (geo->src.width << 16) / geo->dst.width;
+       geo->y_ratio = (geo->src.height << 16) / geo->dst.height;
+
+       /* adjust offsets */
+       geo->src.x_offset = min(geo->src.x_offset,
+               geo->src.full_width - geo->src.width);
+       geo->src.y_offset = min(geo->src.y_offset,
+               geo->src.full_height - geo->src.height);
+       geo->dst.x_offset = min(geo->dst.x_offset,
+               geo->dst.full_width - geo->dst.width);
+       geo->dst.y_offset = min(geo->dst.y_offset,
+               geo->dst.full_height - geo->dst.height);
+}
+
+/* PUBLIC API */
+
+struct mxr_layer *mxr_vp_layer_create(struct mxr_device *mdev, int idx)
+{
+       struct mxr_layer *layer;
+       int ret;
+       struct mxr_layer_ops ops = {
+               .release = mxr_vp_layer_release,
+               .buffer_set = mxr_vp_buffer_set,
+               .stream_set = mxr_vp_stream_set,
+               .format_set = mxr_vp_format_set,
+               .fix_geometry = mxr_vp_fix_geometry,
+       };
+       char name[32];
+
+       sprintf(name, "video%d", idx);
+
+       layer = mxr_base_layer_create(mdev, idx, name, &ops);
+       if (layer == NULL) {
+               mxr_err(mdev, "failed to initialize layer(%d) base\n", idx);
+               goto fail;
+       }
+
+       layer->fmt_array = mxr_video_format;
+       layer->fmt_array_size = ARRAY_SIZE(mxr_video_format);
+
+       ret = mxr_base_layer_register(layer);
+       if (ret)
+               goto fail_layer;
+
+       return layer;
+
+fail_layer:
+       mxr_base_layer_release(layer);
+
+fail:
+       return NULL;
+}
+
diff --git a/drivers/media/video/s5p-tv/regs-hdmi.h b/drivers/media/video/s5p-tv/regs-hdmi.h
new file mode 100644 (file)
index 0000000..ac93ad6
--- /dev/null
@@ -0,0 +1,141 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-hdmi.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * HDMI register header file for Samsung TVOUT driver
+ *
+ * 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 SAMSUNG_REGS_HDMI_H
+#define SAMSUNG_REGS_HDMI_H
+
+/*
+ * Register part
+*/
+
+#define HDMI_CTRL_BASE(x)              ((x) + 0x00000000)
+#define HDMI_CORE_BASE(x)              ((x) + 0x00010000)
+#define HDMI_TG_BASE(x)                        ((x) + 0x00050000)
+
+/* Control registers */
+#define HDMI_INTC_CON                  HDMI_CTRL_BASE(0x0000)
+#define HDMI_INTC_FLAG                 HDMI_CTRL_BASE(0x0004)
+#define HDMI_HPD_STATUS                        HDMI_CTRL_BASE(0x000C)
+#define HDMI_PHY_RSTOUT                        HDMI_CTRL_BASE(0x0014)
+#define HDMI_PHY_VPLL                  HDMI_CTRL_BASE(0x0018)
+#define HDMI_PHY_CMU                   HDMI_CTRL_BASE(0x001C)
+#define HDMI_CORE_RSTOUT               HDMI_CTRL_BASE(0x0020)
+
+/* Core registers */
+#define HDMI_CON_0                     HDMI_CORE_BASE(0x0000)
+#define HDMI_CON_1                     HDMI_CORE_BASE(0x0004)
+#define HDMI_CON_2                     HDMI_CORE_BASE(0x0008)
+#define HDMI_SYS_STATUS                        HDMI_CORE_BASE(0x0010)
+#define HDMI_PHY_STATUS                        HDMI_CORE_BASE(0x0014)
+#define HDMI_STATUS_EN                 HDMI_CORE_BASE(0x0020)
+#define HDMI_HPD                       HDMI_CORE_BASE(0x0030)
+#define HDMI_MODE_SEL                  HDMI_CORE_BASE(0x0040)
+#define HDMI_BLUE_SCREEN_0             HDMI_CORE_BASE(0x0050)
+#define HDMI_BLUE_SCREEN_1             HDMI_CORE_BASE(0x0054)
+#define HDMI_BLUE_SCREEN_2             HDMI_CORE_BASE(0x0058)
+#define HDMI_H_BLANK_0                 HDMI_CORE_BASE(0x00A0)
+#define HDMI_H_BLANK_1                 HDMI_CORE_BASE(0x00A4)
+#define HDMI_V_BLANK_0                 HDMI_CORE_BASE(0x00B0)
+#define HDMI_V_BLANK_1                 HDMI_CORE_BASE(0x00B4)
+#define HDMI_V_BLANK_2                 HDMI_CORE_BASE(0x00B8)
+#define HDMI_H_V_LINE_0                        HDMI_CORE_BASE(0x00C0)
+#define HDMI_H_V_LINE_1                        HDMI_CORE_BASE(0x00C4)
+#define HDMI_H_V_LINE_2                        HDMI_CORE_BASE(0x00C8)
+#define HDMI_VSYNC_POL                 HDMI_CORE_BASE(0x00E4)
+#define HDMI_INT_PRO_MODE              HDMI_CORE_BASE(0x00E8)
+#define HDMI_V_BLANK_F_0               HDMI_CORE_BASE(0x0110)
+#define HDMI_V_BLANK_F_1               HDMI_CORE_BASE(0x0114)
+#define HDMI_V_BLANK_F_2               HDMI_CORE_BASE(0x0118)
+#define HDMI_H_SYNC_GEN_0              HDMI_CORE_BASE(0x0120)
+#define HDMI_H_SYNC_GEN_1              HDMI_CORE_BASE(0x0124)
+#define HDMI_H_SYNC_GEN_2              HDMI_CORE_BASE(0x0128)
+#define HDMI_V_SYNC_GEN_1_0            HDMI_CORE_BASE(0x0130)
+#define HDMI_V_SYNC_GEN_1_1            HDMI_CORE_BASE(0x0134)
+#define HDMI_V_SYNC_GEN_1_2            HDMI_CORE_BASE(0x0138)
+#define HDMI_V_SYNC_GEN_2_0            HDMI_CORE_BASE(0x0140)
+#define HDMI_V_SYNC_GEN_2_1            HDMI_CORE_BASE(0x0144)
+#define HDMI_V_SYNC_GEN_2_2            HDMI_CORE_BASE(0x0148)
+#define HDMI_V_SYNC_GEN_3_0            HDMI_CORE_BASE(0x0150)
+#define HDMI_V_SYNC_GEN_3_1            HDMI_CORE_BASE(0x0154)
+#define HDMI_V_SYNC_GEN_3_2            HDMI_CORE_BASE(0x0158)
+#define HDMI_AVI_CON                   HDMI_CORE_BASE(0x0300)
+#define HDMI_AVI_BYTE(n)               HDMI_CORE_BASE(0x0320 + 4 * (n))
+#define        HDMI_DC_CONTROL                 HDMI_CORE_BASE(0x05C0)
+#define HDMI_VIDEO_PATTERN_GEN         HDMI_CORE_BASE(0x05C4)
+#define HDMI_HPD_GEN                   HDMI_CORE_BASE(0x05C8)
+
+/* Timing generator registers */
+#define HDMI_TG_CMD                    HDMI_TG_BASE(0x0000)
+#define HDMI_TG_H_FSZ_L                        HDMI_TG_BASE(0x0018)
+#define HDMI_TG_H_FSZ_H                        HDMI_TG_BASE(0x001C)
+#define HDMI_TG_HACT_ST_L              HDMI_TG_BASE(0x0020)
+#define HDMI_TG_HACT_ST_H              HDMI_TG_BASE(0x0024)
+#define HDMI_TG_HACT_SZ_L              HDMI_TG_BASE(0x0028)
+#define HDMI_TG_HACT_SZ_H              HDMI_TG_BASE(0x002C)
+#define HDMI_TG_V_FSZ_L                        HDMI_TG_BASE(0x0030)
+#define HDMI_TG_V_FSZ_H                        HDMI_TG_BASE(0x0034)
+#define HDMI_TG_VSYNC_L                        HDMI_TG_BASE(0x0038)
+#define HDMI_TG_VSYNC_H                        HDMI_TG_BASE(0x003C)
+#define HDMI_TG_VSYNC2_L               HDMI_TG_BASE(0x0040)
+#define HDMI_TG_VSYNC2_H               HDMI_TG_BASE(0x0044)
+#define HDMI_TG_VACT_ST_L              HDMI_TG_BASE(0x0048)
+#define HDMI_TG_VACT_ST_H              HDMI_TG_BASE(0x004C)
+#define HDMI_TG_VACT_SZ_L              HDMI_TG_BASE(0x0050)
+#define HDMI_TG_VACT_SZ_H              HDMI_TG_BASE(0x0054)
+#define HDMI_TG_FIELD_CHG_L            HDMI_TG_BASE(0x0058)
+#define HDMI_TG_FIELD_CHG_H            HDMI_TG_BASE(0x005C)
+#define HDMI_TG_VACT_ST2_L             HDMI_TG_BASE(0x0060)
+#define HDMI_TG_VACT_ST2_H             HDMI_TG_BASE(0x0064)
+#define HDMI_TG_VSYNC_TOP_HDMI_L       HDMI_TG_BASE(0x0078)
+#define HDMI_TG_VSYNC_TOP_HDMI_H       HDMI_TG_BASE(0x007C)
+#define HDMI_TG_VSYNC_BOT_HDMI_L       HDMI_TG_BASE(0x0080)
+#define HDMI_TG_VSYNC_BOT_HDMI_H       HDMI_TG_BASE(0x0084)
+#define HDMI_TG_FIELD_TOP_HDMI_L       HDMI_TG_BASE(0x0088)
+#define HDMI_TG_FIELD_TOP_HDMI_H       HDMI_TG_BASE(0x008C)
+#define HDMI_TG_FIELD_BOT_HDMI_L       HDMI_TG_BASE(0x0090)
+#define HDMI_TG_FIELD_BOT_HDMI_H       HDMI_TG_BASE(0x0094)
+
+/*
+ * Bit definition part
+ */
+
+/* HDMI_INTC_CON */
+#define HDMI_INTC_EN_GLOBAL            (1 << 6)
+#define HDMI_INTC_EN_HPD_PLUG          (1 << 3)
+#define HDMI_INTC_EN_HPD_UNPLUG                (1 << 2)
+
+/* HDMI_INTC_FLAG */
+#define HDMI_INTC_FLAG_HPD_PLUG                (1 << 3)
+#define HDMI_INTC_FLAG_HPD_UNPLUG      (1 << 2)
+
+/* HDMI_PHY_RSTOUT */
+#define HDMI_PHY_SW_RSTOUT             (1 << 0)
+
+/* HDMI_CORE_RSTOUT */
+#define HDMI_CORE_SW_RSTOUT            (1 << 0)
+
+/* HDMI_CON_0 */
+#define HDMI_BLUE_SCR_EN               (1 << 5)
+#define HDMI_EN                                (1 << 0)
+
+/* HDMI_PHY_STATUS */
+#define HDMI_PHY_STATUS_READY          (1 << 0)
+
+/* HDMI_MODE_SEL */
+#define HDMI_MODE_HDMI_EN              (1 << 1)
+#define HDMI_MODE_DVI_EN               (1 << 0)
+#define HDMI_MODE_MASK                 (3 << 0)
+
+/* HDMI_TG_CMD */
+#define HDMI_TG_EN                     (1 << 0)
+
+#endif /* SAMSUNG_REGS_HDMI_H */
diff --git a/drivers/media/video/s5p-tv/regs-mixer.h b/drivers/media/video/s5p-tv/regs-mixer.h
new file mode 100644 (file)
index 0000000..3c84426
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Mixer register header file for Samsung Mixer driver
+ *
+ * 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 SAMSUNG_REGS_MIXER_H
+#define SAMSUNG_REGS_MIXER_H
+
+/*
+ * Register part
+ */
+#define MXR_STATUS                     0x0000
+#define MXR_CFG                                0x0004
+#define MXR_INT_EN                     0x0008
+#define MXR_INT_STATUS                 0x000C
+#define MXR_LAYER_CFG                  0x0010
+#define MXR_VIDEO_CFG                  0x0014
+#define MXR_GRAPHIC0_CFG               0x0020
+#define MXR_GRAPHIC0_BASE              0x0024
+#define MXR_GRAPHIC0_SPAN              0x0028
+#define MXR_GRAPHIC0_SXY               0x002C
+#define MXR_GRAPHIC0_WH                        0x0030
+#define MXR_GRAPHIC0_DXY               0x0034
+#define MXR_GRAPHIC0_BLANK             0x0038
+#define MXR_GRAPHIC1_CFG               0x0040
+#define MXR_GRAPHIC1_BASE              0x0044
+#define MXR_GRAPHIC1_SPAN              0x0048
+#define MXR_GRAPHIC1_SXY               0x004C
+#define MXR_GRAPHIC1_WH                        0x0050
+#define MXR_GRAPHIC1_DXY               0x0054
+#define MXR_GRAPHIC1_BLANK             0x0058
+#define MXR_BG_CFG                     0x0060
+#define MXR_BG_COLOR0                  0x0064
+#define MXR_BG_COLOR1                  0x0068
+#define MXR_BG_COLOR2                  0x006C
+
+/* for parametrized access to layer registers */
+#define MXR_GRAPHIC_CFG(i)             (0x0020 + (i) * 0x20)
+#define MXR_GRAPHIC_BASE(i)            (0x0024 + (i) * 0x20)
+#define MXR_GRAPHIC_SPAN(i)            (0x0028 + (i) * 0x20)
+#define MXR_GRAPHIC_SXY(i)             (0x002C + (i) * 0x20)
+#define MXR_GRAPHIC_WH(i)              (0x0030 + (i) * 0x20)
+#define MXR_GRAPHIC_DXY(i)             (0x0034 + (i) * 0x20)
+
+/*
+ * Bit definition part
+ */
+
+/* generates mask for range of bits */
+#define MXR_MASK(high_bit, low_bit) \
+       (((2 << ((high_bit) - (low_bit))) - 1) << (low_bit))
+
+#define MXR_MASK_VAL(val, high_bit, low_bit) \
+       (((val) << (low_bit)) & MXR_MASK(high_bit, low_bit))
+
+/* bits for MXR_STATUS */
+#define MXR_STATUS_16_BURST            (1 << 7)
+#define MXR_STATUS_BURST_MASK          (1 << 7)
+#define MXR_STATUS_SYNC_ENABLE         (1 << 2)
+#define MXR_STATUS_REG_RUN             (1 << 0)
+
+/* bits for MXR_CFG */
+#define MXR_CFG_OUT_YUV444             (0 << 8)
+#define MXR_CFG_OUT_RGB888             (1 << 8)
+#define MXR_CFG_DST_SDO                        (0 << 7)
+#define MXR_CFG_DST_HDMI               (1 << 7)
+#define MXR_CFG_DST_MASK               (1 << 7)
+#define MXR_CFG_SCAN_HD_720            (0 << 6)
+#define MXR_CFG_SCAN_HD_1080           (1 << 6)
+#define MXR_CFG_GRP1_ENABLE            (1 << 5)
+#define MXR_CFG_GRP0_ENABLE            (1 << 4)
+#define MXR_CFG_VP_ENABLE              (1 << 3)
+#define MXR_CFG_SCAN_INTERLACE         (0 << 2)
+#define MXR_CFG_SCAN_PROGRASSIVE       (1 << 2)
+#define MXR_CFG_SCAN_NTSC              (0 << 1)
+#define MXR_CFG_SCAN_PAL               (1 << 1)
+#define MXR_CFG_SCAN_SD                        (0 << 0)
+#define MXR_CFG_SCAN_HD                        (1 << 0)
+#define MXR_CFG_SCAN_MASK              0x47
+
+/* bits for MXR_GRAPHICn_CFG */
+#define MXR_GRP_CFG_COLOR_KEY_DISABLE  (1 << 21)
+#define MXR_GRP_CFG_BLEND_PRE_MUL      (1 << 20)
+#define MXR_GRP_CFG_FORMAT_VAL(x)      MXR_MASK_VAL(x, 11, 8)
+#define MXR_GRP_CFG_FORMAT_MASK                MXR_GRP_CFG_FORMAT_VAL(~0)
+#define MXR_GRP_CFG_ALPHA_VAL(x)       MXR_MASK_VAL(x, 7, 0)
+
+/* bits for MXR_GRAPHICn_WH */
+#define MXR_GRP_WH_H_SCALE(x)          MXR_MASK_VAL(x, 28, 28)
+#define MXR_GRP_WH_V_SCALE(x)          MXR_MASK_VAL(x, 12, 12)
+#define MXR_GRP_WH_WIDTH(x)            MXR_MASK_VAL(x, 26, 16)
+#define MXR_GRP_WH_HEIGHT(x)           MXR_MASK_VAL(x, 10, 0)
+
+/* bits for MXR_GRAPHICn_SXY */
+#define MXR_GRP_SXY_SX(x)              MXR_MASK_VAL(x, 26, 16)
+#define MXR_GRP_SXY_SY(x)              MXR_MASK_VAL(x, 10, 0)
+
+/* bits for MXR_GRAPHICn_DXY */
+#define MXR_GRP_DXY_DX(x)              MXR_MASK_VAL(x, 26, 16)
+#define MXR_GRP_DXY_DY(x)              MXR_MASK_VAL(x, 10, 0)
+
+/* bits for MXR_INT_EN */
+#define MXR_INT_EN_VSYNC               (1 << 11)
+#define MXR_INT_EN_ALL                 (0x0f << 8)
+
+/* bit for MXR_INT_STATUS */
+#define MXR_INT_CLEAR_VSYNC            (1 << 11)
+#define MXR_INT_STATUS_VSYNC           (1 << 0)
+
+/* bit for MXR_LAYER_CFG */
+#define MXR_LAYER_CFG_GRP1_VAL(x)      MXR_MASK_VAL(x, 11, 8)
+#define MXR_LAYER_CFG_GRP0_VAL(x)      MXR_MASK_VAL(x, 7, 4)
+#define MXR_LAYER_CFG_VP_VAL(x)                MXR_MASK_VAL(x, 3, 0)
+
+#endif /* SAMSUNG_REGS_MIXER_H */
+
diff --git a/drivers/media/video/s5p-tv/regs-sdo.h b/drivers/media/video/s5p-tv/regs-sdo.h
new file mode 100644 (file)
index 0000000..7f7c2b8
--- /dev/null
@@ -0,0 +1,63 @@
+/* drivers/media/video/s5p-tv/regs-sdo.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * SDO register description file
+ *
+ * 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 SAMSUNG_REGS_SDO_H
+#define SAMSUNG_REGS_SDO_H
+
+/*
+ * Register part
+ */
+
+#define SDO_CLKCON                     0x0000
+#define SDO_CONFIG                     0x0008
+#define SDO_VBI                                0x0014
+#define SDO_DAC                                0x003C
+#define SDO_CCCON                      0x0180
+#define SDO_IRQ                                0x0280
+#define SDO_IRQMASK                    0x0284
+#define SDO_VERSION                    0x03D8
+
+/*
+ * Bit definition part
+ */
+
+/* SDO Clock Control Register (SDO_CLKCON) */
+#define SDO_TVOUT_SW_RESET             (1 << 4)
+#define SDO_TVOUT_CLOCK_READY          (1 << 1)
+#define SDO_TVOUT_CLOCK_ON             (1 << 0)
+
+/* SDO Video Standard Configuration Register (SDO_CONFIG) */
+#define SDO_PROGRESSIVE                        (1 << 4)
+#define SDO_NTSC_M                     0
+#define SDO_PAL_M                      1
+#define SDO_PAL_BGHID                  2
+#define SDO_PAL_N                      3
+#define SDO_PAL_NC                     4
+#define SDO_NTSC_443                   8
+#define SDO_PAL_60                     9
+#define SDO_STANDARD_MASK              0xf
+
+/* SDO VBI Configuration Register (SDO_VBI) */
+#define SDO_CVBS_WSS_INS               (1 << 14)
+#define SDO_CVBS_CLOSED_CAPTION_MASK   (3 << 12)
+
+/* SDO DAC Configuration Register (SDO_DAC) */
+#define SDO_POWER_ON_DAC               (1 << 0)
+
+/* SDO Color Compensation On/Off Control (SDO_CCCON) */
+#define SDO_COMPENSATION_BHS_ADJ_OFF   (1 << 4)
+#define SDO_COMPENSATION_CVBS_COMP_OFF (1 << 0)
+
+/* SDO Interrupt Request Register (SDO_IRQ) */
+#define SDO_VSYNC_IRQ_PEND             (1 << 0)
+
+#endif /* SAMSUNG_REGS_SDO_H */
diff --git a/drivers/media/video/s5p-tv/regs-vp.h b/drivers/media/video/s5p-tv/regs-vp.h
new file mode 100644 (file)
index 0000000..6c63984
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Video processor register header file for Samsung Mixer driver
+ *
+ * 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 SAMSUNG_REGS_VP_H
+#define SAMSUNG_REGS_VP_H
+
+/*
+ * Register part
+ */
+
+#define VP_ENABLE                      0x0000
+#define VP_SRESET                      0x0004
+#define VP_SHADOW_UPDATE               0x0008
+#define VP_FIELD_ID                    0x000C
+#define VP_MODE                                0x0010
+#define VP_IMG_SIZE_Y                  0x0014
+#define VP_IMG_SIZE_C                  0x0018
+#define VP_PER_RATE_CTRL               0x001C
+#define VP_TOP_Y_PTR                   0x0028
+#define VP_BOT_Y_PTR                   0x002C
+#define VP_TOP_C_PTR                   0x0030
+#define VP_BOT_C_PTR                   0x0034
+#define VP_ENDIAN_MODE                 0x03CC
+#define VP_SRC_H_POSITION              0x0044
+#define VP_SRC_V_POSITION              0x0048
+#define VP_SRC_WIDTH                   0x004C
+#define VP_SRC_HEIGHT                  0x0050
+#define VP_DST_H_POSITION              0x0054
+#define VP_DST_V_POSITION              0x0058
+#define VP_DST_WIDTH                   0x005C
+#define VP_DST_HEIGHT                  0x0060
+#define VP_H_RATIO                     0x0064
+#define VP_V_RATIO                     0x0068
+#define VP_POLY8_Y0_LL                 0x006C
+#define VP_POLY4_Y0_LL                 0x00EC
+#define VP_POLY4_C0_LL                 0x012C
+
+/*
+ * Bit definition part
+ */
+
+/* generates mask for range of bits */
+
+#define VP_MASK(high_bit, low_bit) \
+       (((2 << ((high_bit) - (low_bit))) - 1) << (low_bit))
+
+#define VP_MASK_VAL(val, high_bit, low_bit) \
+       (((val) << (low_bit)) & VP_MASK(high_bit, low_bit))
+
+ /* VP_ENABLE */
+#define VP_ENABLE_ON                   (1 << 0)
+
+/* VP_SRESET */
+#define VP_SRESET_PROCESSING           (1 << 0)
+
+/* VP_SHADOW_UPDATE */
+#define VP_SHADOW_UPDATE_ENABLE                (1 << 0)
+
+/* VP_MODE */
+#define VP_MODE_NV12                   (0 << 6)
+#define VP_MODE_NV21                   (1 << 6)
+#define VP_MODE_LINE_SKIP              (1 << 5)
+#define VP_MODE_MEM_LINEAR             (0 << 4)
+#define VP_MODE_MEM_TILED              (1 << 4)
+#define VP_MODE_FMT_MASK               (5 << 4)
+#define VP_MODE_FIELD_ID_AUTO_TOGGLING (1 << 2)
+#define VP_MODE_2D_IPC                 (1 << 1)
+
+/* VP_IMG_SIZE_Y */
+/* VP_IMG_SIZE_C */
+#define VP_IMG_HSIZE(x)                        VP_MASK_VAL(x, 29, 16)
+#define VP_IMG_VSIZE(x)                        VP_MASK_VAL(x, 13, 0)
+
+/* VP_SRC_H_POSITION */
+#define VP_SRC_H_POSITION_VAL(x)       VP_MASK_VAL(x, 14, 4)
+
+/* VP_ENDIAN_MODE */
+#define VP_ENDIAN_MODE_LITTLE          (1 << 0)
+
+#endif /* SAMSUNG_REGS_VP_H */
diff --git a/drivers/media/video/s5p-tv/sdo_drv.c b/drivers/media/video/s5p-tv/sdo_drv.c
new file mode 100644 (file)
index 0000000..4dddd6b
--- /dev/null
@@ -0,0 +1,479 @@
+/*
+ * Samsung Standard Definition Output (SDO) driver
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *
+ * Tomasz Stanislawski, <t.stanislaws@samsung.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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-subdev.h>
+
+#include "regs-sdo.h"
+
+MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>");
+MODULE_DESCRIPTION("Samsung Standard Definition Output (SDO)");
+MODULE_LICENSE("GPL");
+
+#define SDO_DEFAULT_STD        V4L2_STD_PAL
+
+struct sdo_format {
+       v4l2_std_id id;
+       /* all modes are 720 pixels wide */
+       unsigned int height;
+       unsigned int cookie;
+};
+
+struct sdo_device {
+       /** pointer to device parent */
+       struct device *dev;
+       /** base address of SDO registers */
+       void __iomem *regs;
+       /** SDO interrupt */
+       unsigned int irq;
+       /** DAC source clock */
+       struct clk *sclk_dac;
+       /** DAC clock */
+       struct clk *dac;
+       /** DAC physical interface */
+       struct clk *dacphy;
+       /** clock for control of VPLL */
+       struct clk *fout_vpll;
+       /** regulator for SDO IP power */
+       struct regulator *vdac;
+       /** regulator for SDO plug detection */
+       struct regulator *vdet;
+       /** subdev used as device interface */
+       struct v4l2_subdev sd;
+       /** current format */
+       const struct sdo_format *fmt;
+};
+
+static inline struct sdo_device *sd_to_sdev(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct sdo_device, sd);
+}
+
+static inline
+void sdo_write_mask(struct sdo_device *sdev, u32 reg_id, u32 value, u32 mask)
+{
+       u32 old = readl(sdev->regs + reg_id);
+       value = (value & mask) | (old & ~mask);
+       writel(value, sdev->regs + reg_id);
+}
+
+static inline
+void sdo_write(struct sdo_device *sdev, u32 reg_id, u32 value)
+{
+       writel(value, sdev->regs + reg_id);
+}
+
+static inline
+u32 sdo_read(struct sdo_device *sdev, u32 reg_id)
+{
+       return readl(sdev->regs + reg_id);
+}
+
+static irqreturn_t sdo_irq_handler(int irq, void *dev_data)
+{
+       struct sdo_device *sdev = dev_data;
+
+       /* clear interrupt */
+       sdo_write_mask(sdev, SDO_IRQ, ~0, SDO_VSYNC_IRQ_PEND);
+       return IRQ_HANDLED;
+}
+
+static void sdo_reg_debug(struct sdo_device *sdev)
+{
+#define DBGREG(reg_id) \
+       dev_info(sdev->dev, #reg_id " = %08x\n", \
+               sdo_read(sdev, reg_id))
+
+       DBGREG(SDO_CLKCON);
+       DBGREG(SDO_CONFIG);
+       DBGREG(SDO_VBI);
+       DBGREG(SDO_DAC);
+       DBGREG(SDO_IRQ);
+       DBGREG(SDO_IRQMASK);
+       DBGREG(SDO_VERSION);
+}
+
+static const struct sdo_format sdo_format[] = {
+       { V4L2_STD_PAL_N,       .height = 576, .cookie = SDO_PAL_N },
+       { V4L2_STD_PAL_Nc,      .height = 576, .cookie = SDO_PAL_NC },
+       { V4L2_STD_PAL_M,       .height = 480, .cookie = SDO_PAL_M },
+       { V4L2_STD_PAL_60,      .height = 480, .cookie = SDO_PAL_60 },
+       { V4L2_STD_NTSC_443,    .height = 480, .cookie = SDO_NTSC_443 },
+       { V4L2_STD_PAL,         .height = 576, .cookie = SDO_PAL_BGHID },
+       { V4L2_STD_NTSC_M,      .height = 480, .cookie = SDO_NTSC_M },
+};
+
+static const struct sdo_format *sdo_find_format(v4l2_std_id id)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(sdo_format); ++i)
+               if (sdo_format[i].id & id)
+                       return &sdo_format[i];
+       return NULL;
+}
+
+static int sdo_g_tvnorms_output(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+       *std = V4L2_STD_NTSC_M | V4L2_STD_PAL_M | V4L2_STD_PAL |
+               V4L2_STD_PAL_N | V4L2_STD_PAL_Nc |
+               V4L2_STD_NTSC_443 | V4L2_STD_PAL_60;
+       return 0;
+}
+
+static int sdo_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+       struct sdo_device *sdev = sd_to_sdev(sd);
+       const struct sdo_format *fmt;
+       fmt = sdo_find_format(std);
+       if (fmt == NULL)
+               return -EINVAL;
+       sdev->fmt = fmt;
+       return 0;
+}
+
+static int sdo_g_std_output(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+       *std = sd_to_sdev(sd)->fmt->id;
+       return 0;
+}
+
+static int sdo_g_mbus_fmt(struct v4l2_subdev *sd,
+       struct v4l2_mbus_framefmt *fmt)
+{
+       struct sdo_device *sdev = sd_to_sdev(sd);
+
+       if (!sdev->fmt)
+               return -ENXIO;
+       /* all modes are 720 pixels wide */
+       fmt->width = 720;
+       fmt->height = sdev->fmt->height;
+       fmt->code = V4L2_MBUS_FMT_FIXED;
+       fmt->field = V4L2_FIELD_INTERLACED;
+       return 0;
+}
+
+static int sdo_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct sdo_device *sdev = sd_to_sdev(sd);
+       struct device *dev = sdev->dev;
+       int ret;
+
+       dev_info(dev, "sdo_s_power(%d)\n", on);
+
+       if (on)
+               ret = pm_runtime_get_sync(dev);
+       else
+               ret = pm_runtime_put_sync(dev);
+
+       /* only values < 0 indicate errors */
+       return IS_ERR_VALUE(ret) ? ret : 0;
+}
+
+static int sdo_streamon(struct sdo_device *sdev)
+{
+       /* set proper clock for Timing Generator */
+       clk_set_rate(sdev->fout_vpll, 54000000);
+       dev_info(sdev->dev, "fout_vpll.rate = %lu\n",
+       clk_get_rate(sdev->fout_vpll));
+       /* enable clock in SDO */
+       sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_CLOCK_ON);
+       clk_enable(sdev->dacphy);
+       /* enable DAC */
+       sdo_write_mask(sdev, SDO_DAC, ~0, SDO_POWER_ON_DAC);
+       sdo_reg_debug(sdev);
+       return 0;
+}
+
+static int sdo_streamoff(struct sdo_device *sdev)
+{
+       int tries;
+
+       sdo_write_mask(sdev, SDO_DAC, 0, SDO_POWER_ON_DAC);
+       clk_disable(sdev->dacphy);
+       sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_CLOCK_ON);
+       for (tries = 100; tries; --tries) {
+               if (sdo_read(sdev, SDO_CLKCON) & SDO_TVOUT_CLOCK_READY)
+                       break;
+               mdelay(1);
+       }
+       if (tries == 0)
+               dev_err(sdev->dev, "failed to stop streaming\n");
+       return tries ? 0 : -EIO;
+}
+
+static int sdo_s_stream(struct v4l2_subdev *sd, int on)
+{
+       struct sdo_device *sdev = sd_to_sdev(sd);
+       return on ? sdo_streamon(sdev) : sdo_streamoff(sdev);
+}
+
+static const struct v4l2_subdev_core_ops sdo_sd_core_ops = {
+       .s_power = sdo_s_power,
+};
+
+static const struct v4l2_subdev_video_ops sdo_sd_video_ops = {
+       .s_std_output = sdo_s_std_output,
+       .g_std_output = sdo_g_std_output,
+       .g_tvnorms_output = sdo_g_tvnorms_output,
+       .g_mbus_fmt = sdo_g_mbus_fmt,
+       .s_stream = sdo_s_stream,
+};
+
+static const struct v4l2_subdev_ops sdo_sd_ops = {
+       .core = &sdo_sd_core_ops,
+       .video = &sdo_sd_video_ops,
+};
+
+static int sdo_runtime_suspend(struct device *dev)
+{
+       struct v4l2_subdev *sd = dev_get_drvdata(dev);
+       struct sdo_device *sdev = sd_to_sdev(sd);
+
+       dev_info(dev, "suspend\n");
+       regulator_disable(sdev->vdet);
+       regulator_disable(sdev->vdac);
+       clk_disable(sdev->sclk_dac);
+       return 0;
+}
+
+static int sdo_runtime_resume(struct device *dev)
+{
+       struct v4l2_subdev *sd = dev_get_drvdata(dev);
+       struct sdo_device *sdev = sd_to_sdev(sd);
+
+       dev_info(dev, "resume\n");
+       clk_enable(sdev->sclk_dac);
+       regulator_enable(sdev->vdac);
+       regulator_enable(sdev->vdet);
+
+       /* software reset */
+       sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_SW_RESET);
+       mdelay(10);
+       sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_SW_RESET);
+
+       /* setting TV mode */
+       sdo_write_mask(sdev, SDO_CONFIG, sdev->fmt->cookie, SDO_STANDARD_MASK);
+       /* XXX: forcing interlaced mode using undocumented bit */
+       sdo_write_mask(sdev, SDO_CONFIG, 0, SDO_PROGRESSIVE);
+       /* turn all VBI off */
+       sdo_write_mask(sdev, SDO_VBI, 0, SDO_CVBS_WSS_INS |
+               SDO_CVBS_CLOSED_CAPTION_MASK);
+       /* turn all post processing off */
+       sdo_write_mask(sdev, SDO_CCCON, ~0, SDO_COMPENSATION_BHS_ADJ_OFF |
+               SDO_COMPENSATION_CVBS_COMP_OFF);
+       sdo_reg_debug(sdev);
+       return 0;
+}
+
+static const struct dev_pm_ops sdo_pm_ops = {
+       .runtime_suspend = sdo_runtime_suspend,
+       .runtime_resume  = sdo_runtime_resume,
+};
+
+static int __devinit sdo_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct sdo_device *sdev;
+       struct resource *res;
+       int ret = 0;
+       struct clk *sclk_vpll;
+
+       dev_info(dev, "probe start\n");
+       sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
+       if (!sdev) {
+               dev_err(dev, "not enough memory.\n");
+               ret = -ENOMEM;
+               goto fail;
+       }
+       sdev->dev = dev;
+
+       /* mapping registers */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(dev, "get memory resource failed.\n");
+               ret = -ENXIO;
+               goto fail_sdev;
+       }
+
+       sdev->regs = ioremap(res->start, resource_size(res));
+       if (sdev->regs == NULL) {
+               dev_err(dev, "register mapping failed.\n");
+               ret = -ENXIO;
+               goto fail_sdev;
+       }
+
+       /* acquiring interrupt */
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (res == NULL) {
+               dev_err(dev, "get interrupt resource failed.\n");
+               ret = -ENXIO;
+               goto fail_regs;
+       }
+       ret = request_irq(res->start, sdo_irq_handler, 0, "s5p-sdo", sdev);
+       if (ret) {
+               dev_err(dev, "request interrupt failed.\n");
+               goto fail_regs;
+       }
+       sdev->irq = res->start;
+
+       /* acquire clocks */
+       sdev->sclk_dac = clk_get(dev, "sclk_dac");
+       if (IS_ERR_OR_NULL(sdev->sclk_dac)) {
+               dev_err(dev, "failed to get clock 'sclk_dac'\n");
+               ret = -ENXIO;
+               goto fail_irq;
+       }
+       sdev->dac = clk_get(dev, "dac");
+       if (IS_ERR_OR_NULL(sdev->dac)) {
+               dev_err(dev, "failed to get clock 'dac'\n");
+               ret = -ENXIO;
+               goto fail_sclk_dac;
+       }
+       sdev->dacphy = clk_get(dev, "dacphy");
+       if (IS_ERR_OR_NULL(sdev->dacphy)) {
+               dev_err(dev, "failed to get clock 'dacphy'\n");
+               ret = -ENXIO;
+               goto fail_dac;
+       }
+       sclk_vpll = clk_get(dev, "sclk_vpll");
+       if (IS_ERR_OR_NULL(sclk_vpll)) {
+               dev_err(dev, "failed to get clock 'sclk_vpll'\n");
+               ret = -ENXIO;
+               goto fail_dacphy;
+       }
+       clk_set_parent(sdev->sclk_dac, sclk_vpll);
+       clk_put(sclk_vpll);
+       sdev->fout_vpll = clk_get(dev, "fout_vpll");
+       if (IS_ERR_OR_NULL(sdev->fout_vpll)) {
+               dev_err(dev, "failed to get clock 'fout_vpll'\n");
+               goto fail_dacphy;
+       }
+       dev_info(dev, "fout_vpll.rate = %lu\n", clk_get_rate(sclk_vpll));
+
+       /* acquire regulator */
+       sdev->vdac = regulator_get(dev, "vdd33a_dac");
+       if (IS_ERR_OR_NULL(sdev->vdac)) {
+               dev_err(dev, "failed to get regulator 'vdac'\n");
+               goto fail_fout_vpll;
+       }
+       sdev->vdet = regulator_get(dev, "vdet");
+       if (IS_ERR_OR_NULL(sdev->vdet)) {
+               dev_err(dev, "failed to get regulator 'vdet'\n");
+               goto fail_vdac;
+       }
+
+       /* enable gate for dac clock, because mixer uses it */
+       clk_enable(sdev->dac);
+
+       /* configure power management */
+       pm_runtime_enable(dev);
+
+       /* configuration of interface subdevice */
+       v4l2_subdev_init(&sdev->sd, &sdo_sd_ops);
+       sdev->sd.owner = THIS_MODULE;
+       strlcpy(sdev->sd.name, "s5p-sdo", sizeof sdev->sd.name);
+
+       /* set default format */
+       sdev->fmt = sdo_find_format(SDO_DEFAULT_STD);
+       BUG_ON(sdev->fmt == NULL);
+
+       /* keeping subdev in device's private for use by other drivers */
+       dev_set_drvdata(dev, &sdev->sd);
+
+       dev_info(dev, "probe succeeded\n");
+       return 0;
+
+fail_vdac:
+       regulator_put(sdev->vdac);
+fail_fout_vpll:
+       clk_put(sdev->fout_vpll);
+fail_dacphy:
+       clk_put(sdev->dacphy);
+fail_dac:
+       clk_put(sdev->dac);
+fail_sclk_dac:
+       clk_put(sdev->sclk_dac);
+fail_irq:
+       free_irq(sdev->irq, sdev);
+fail_regs:
+       iounmap(sdev->regs);
+fail_sdev:
+       kfree(sdev);
+fail:
+       dev_info(dev, "probe failed\n");
+       return ret;
+}
+
+static int __devexit sdo_remove(struct platform_device *pdev)
+{
+       struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev);
+       struct sdo_device *sdev = sd_to_sdev(sd);
+
+       pm_runtime_disable(&pdev->dev);
+       clk_disable(sdev->dac);
+       regulator_put(sdev->vdet);
+       regulator_put(sdev->vdac);
+       clk_put(sdev->fout_vpll);
+       clk_put(sdev->dacphy);
+       clk_put(sdev->dac);
+       clk_put(sdev->sclk_dac);
+       free_irq(sdev->irq, sdev);
+       iounmap(sdev->regs);
+       kfree(sdev);
+
+       dev_info(&pdev->dev, "remove successful\n");
+       return 0;
+}
+
+static struct platform_driver sdo_driver __refdata = {
+       .probe = sdo_probe,
+       .remove = __devexit_p(sdo_remove),
+       .driver = {
+               .name = "s5p-sdo",
+               .owner = THIS_MODULE,
+               .pm = &sdo_pm_ops,
+       }
+};
+
+static int __init sdo_init(void)
+{
+       int ret;
+       static const char banner[] __initdata = KERN_INFO \
+               "Samsung Standard Definition Output (SDO) driver, "
+               "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
+       printk(banner);
+
+       ret = platform_driver_register(&sdo_driver);
+       if (ret)
+               printk(KERN_ERR "SDO platform driver register failed\n");
+
+       return ret;
+}
+module_init(sdo_init);
+
+static void __exit sdo_exit(void)
+{
+       platform_driver_unregister(&sdo_driver);
+}
+module_exit(sdo_exit);
index 0db9092..f2ae405 100644 (file)
@@ -757,8 +757,8 @@ static int saa711x_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
        switch (ctrl->id) {
        case V4L2_CID_CHROMA_AGC:
                /* chroma gain cluster */
-               if (state->agc->cur.val)
-                       state->gain->cur.val =
+               if (state->agc->val)
+                       state->gain->val =
                                saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
                break;
        }
index e2062b2..0f9fb99 100644 (file)
@@ -4951,8 +4951,9 @@ struct saa7134_board saa7134_boards[] = {
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_XC2028,
                .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
+               .tuner_addr     = 0x61,
                .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
                .inputs = {{
                        .name   = name_tv,
                        .vmux   = 3,
@@ -6992,6 +6993,11 @@ static int saa7134_xc2028_callback(struct saa7134_dev *dev,
                        msleep(10);
                        saa7134_set_gpio(dev, 18, 1);
                break;
+               case SAA7134_BOARD_VIDEOMATE_T750:
+                       saa7134_set_gpio(dev, 20, 0);
+                       msleep(10);
+                       saa7134_set_gpio(dev, 20, 1);
+               break;
                }
        return 0;
        }
@@ -7451,6 +7457,11 @@ int saa7134_board_init1(struct saa7134_dev *dev)
                saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x0e050000, 0x0c050000);
                saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0e050000, 0x0c050000);
                break;
+       case SAA7134_BOARD_VIDEOMATE_T750:
+               /* enable the analog tuner */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x00008000, 0x00008000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000);
+               break;
        }
        return 0;
 }
index f9be737..ca65cda 100644 (file)
@@ -39,6 +39,8 @@
 MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(SAA7134_VERSION);
+
 
 /* ------------------------------------------------------------------ */
 
@@ -1332,14 +1334,8 @@ static struct pci_driver saa7134_pci_driver = {
 static int __init saa7134_init(void)
 {
        INIT_LIST_HEAD(&saa7134_devlist);
-       printk(KERN_INFO "saa7130/34: v4l2 driver version %d.%d.%d loaded\n",
-              (SAA7134_VERSION_CODE >> 16) & 0xff,
-              (SAA7134_VERSION_CODE >>  8) & 0xff,
-              SAA7134_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
-       printk(KERN_INFO "saa7130/34: snapshot date %04d-%02d-%02d\n",
-              SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+       printk(KERN_INFO "saa7130/34: v4l2 driver version %s loaded\n",
+              SAA7134_VERSION);
        return pci_register_driver(&saa7134_pci_driver);
 }
 
index 996a206..1e4ef16 100644 (file)
@@ -56,6 +56,7 @@
 #include "lgs8gxx.h"
 
 #include "zl10353.h"
+#include "qt1010.h"
 
 #include "zl10036.h"
 #include "zl10039.h"
@@ -939,6 +940,18 @@ static struct zl10353_config behold_x7_config = {
        .disable_i2c_gate_ctrl = 1,
 };
 
+static struct zl10353_config videomate_t750_zl10353_config = {
+       .demod_address         = 0x0f,
+       .no_tuner              = 1,
+       .parallel_ts           = 1,
+       .disable_i2c_gate_ctrl = 1,
+};
+
+static struct qt1010_config videomate_t750_qt1010_config = {
+       .i2c_address = 0x62
+};
+
+
 /* ==================================================================
  * tda10086 based DVB-S cards, helper functions
  */
@@ -1649,6 +1662,18 @@ static int dvb_init(struct saa7134_dev *dev)
                                wprintk("%s: No zl10039 found!\n",
                                        __func__);
 
+               break;
+       case SAA7134_BOARD_VIDEOMATE_T750:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                               &videomate_t750_zl10353_config,
+                                               &dev->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (dvb_attach(qt1010_attach,
+                                       fe0->dvb.frontend,
+                                       &dev->i2c_adap,
+                                       &videomate_t750_qt1010_config) == NULL)
+                               wprintk("error attaching QT1010\n");
+               }
                break;
        case SAA7134_BOARD_ZOLID_HYBRID_PCI:
                fe0->dvb.frontend = dvb_attach(tda10048_attach,
index 18294db..dde361a 100644 (file)
@@ -172,7 +172,6 @@ static int empress_querycap(struct file *file, void  *priv,
        strlcpy(cap->card, saa7134_boards[dev->board].name,
                sizeof(cap->card));
        sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-       cap->version = SAA7134_VERSION_CODE;
        cap->capabilities =
                V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_READWRITE |
index 776ba2d..9cf7914 100644 (file)
@@ -1810,7 +1810,6 @@ static int saa7134_querycap(struct file *file, void  *priv,
        strlcpy(cap->card, saa7134_boards[dev->board].name,
                sizeof(cap->card));
        sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-       cap->version = SAA7134_VERSION_CODE;
        cap->capabilities =
                V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_VBI_CAPTURE |
@@ -2307,7 +2306,6 @@ static int radio_querycap(struct file *file, void *priv,
        strcpy(cap->driver, "saa7134");
        strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card));
        sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-       cap->version = SAA7134_VERSION_CODE;
        cap->capabilities = V4L2_CAP_TUNER;
        return 0;
 }
index 28eb103..bc8d6bb 100644 (file)
@@ -19,8 +19,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/version.h>
-#define SAA7134_VERSION_CODE KERNEL_VERSION(0, 2, 16)
+#define SAA7134_VERSION "0, 2, 17"
 
 #include <linux/pci.h>
 #include <linux/i2c.h>
index 4003645..2fd38a0 100644 (file)
@@ -1246,7 +1246,6 @@ static unsigned int fops_poll(struct file *file, poll_table *wait)
        struct saa7164_encoder_fh *fh =
                (struct saa7164_encoder_fh *)file->private_data;
        struct saa7164_port *port = fh->port;
-       struct saa7164_user_buffer *ubuf;
        unsigned int mask = 0;
 
        port->last_poll_msecs_diff = port->last_poll_msecs;
@@ -1278,10 +1277,7 @@ static unsigned int fops_poll(struct file *file, poll_table *wait)
        }
 
        /* Pull the first buffer from the used list */
-       ubuf = list_first_entry(&port->list_buf_used.list,
-               struct saa7164_user_buffer, list);
-
-       if (ubuf)
+       if (!list_empty(&port->list_buf_used.list))
                mask |= POLLIN | POLLRDNORM;
 
        return mask;
index bc1fced..e2e0341 100644 (file)
@@ -1192,7 +1192,6 @@ static unsigned int fops_poll(struct file *file, poll_table *wait)
 {
        struct saa7164_vbi_fh *fh = (struct saa7164_vbi_fh *)file->private_data;
        struct saa7164_port *port = fh->port;
-       struct saa7164_user_buffer *ubuf;
        unsigned int mask = 0;
 
        port->last_poll_msecs_diff = port->last_poll_msecs;
@@ -1224,10 +1223,7 @@ static unsigned int fops_poll(struct file *file, poll_table *wait)
        }
 
        /* Pull the first buffer from the used list */
-       ubuf = list_first_entry(&port->list_buf_used.list,
-               struct saa7164_user_buffer, list);
-
-       if (ubuf)
+       if (!list_empty(&port->list_buf_used.list))
                mask |= POLLIN | POLLRDNORM;
 
        return mask;
index 16745d2..6678bf1 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/kdev_t.h>
-#include <linux/version.h>
 #include <linux/mutex.h>
 #include <linux/crc32.h>
 #include <linux/kthread.h>
index 3ae5c9c..e540898 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/mm.h>
 #include <linux/moduleparam.h>
 #include <linux/time.h>
-#include <linux/version.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
@@ -39,6 +38,7 @@
 #include <media/v4l2-dev.h>
 #include <media/soc_camera.h>
 #include <media/sh_mobile_ceu.h>
+#include <media/sh_mobile_csi2.h>
 #include <media/videobuf2-dma-contig.h>
 #include <media/v4l2-mediabus.h>
 #include <media/soc_mediabus.h>
@@ -96,6 +96,7 @@ struct sh_mobile_ceu_buffer {
 struct sh_mobile_ceu_dev {
        struct soc_camera_host ici;
        struct soc_camera_device *icd;
+       struct platform_device *csi2_pdev;
 
        unsigned int irq;
        void __iomem *base;
@@ -205,7 +206,7 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev)
 
 
        if (2 != success) {
-               dev_warn(&icd->dev, "soft reset time out\n");
+               dev_warn(icd->pdev, "soft reset time out\n");
                return -EIO;
        }
 
@@ -220,7 +221,7 @@ static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
                        unsigned long sizes[], void *alloc_ctxs[])
 {
        struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
        int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
                                                icd->current_fmt->host_fmt);
@@ -242,7 +243,7 @@ static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
                        *count = pcdev->video_limit / PAGE_ALIGN(sizes[0]);
        }
 
-       dev_dbg(icd->dev.parent, "count=%d, size=%lu\n", *count, sizes[0]);
+       dev_dbg(icd->parent, "count=%d, size=%lu\n", *count, sizes[0]);
 
        return 0;
 }
@@ -351,7 +352,7 @@ static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb)
 
        buf = to_ceu_vb(vb);
 
-       dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
                vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
 
        /* Added list head initialization on alloc */
@@ -371,7 +372,7 @@ static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb)
        size = icd->user_height * bytes_per_line;
 
        if (vb2_plane_size(vb, 0) < size) {
-               dev_err(icd->dev.parent, "Buffer too small (%lu < %lu)\n",
+               dev_err(icd->parent, "Buffer too small (%lu < %lu)\n",
                        vb2_plane_size(vb, 0), size);
                return -ENOBUFS;
        }
@@ -384,11 +385,11 @@ static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb)
 static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
 {
        struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
        struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
 
-       dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
                vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
 
        spin_lock_irq(&pcdev->lock);
@@ -409,7 +410,7 @@ static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
 static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
 {
        struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
 
@@ -421,8 +422,12 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
                pcdev->active = NULL;
        }
 
-       /* Doesn't hurt also if the list is empty */
-       list_del_init(&buf->queue);
+       /*
+        * Doesn't hurt also if the list is empty, but it hurts, if queuing the
+        * buffer failed, and .buf_init() hasn't been called
+        */
+       if (buf->queue.next)
+               list_del_init(&buf->queue);
 
        spin_unlock_irq(&pcdev->lock);
 }
@@ -437,7 +442,7 @@ static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb)
 static int sh_mobile_ceu_stop_streaming(struct vb2_queue *q)
 {
        struct soc_camera_device *icd = container_of(q, struct soc_camera_device, vb2_vidq);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
        struct list_head *buf_head, *tmp;
 
@@ -499,25 +504,48 @@ out:
        return IRQ_HANDLED;
 }
 
+static struct v4l2_subdev *find_csi2(struct sh_mobile_ceu_dev *pcdev)
+{
+       struct v4l2_subdev *sd;
+
+       if (!pcdev->csi2_pdev)
+               return NULL;
+
+       v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev)
+               if (&pcdev->csi2_pdev->dev == v4l2_get_subdevdata(sd))
+                       return sd;
+
+       return NULL;
+}
+
 /* Called with .video_lock held */
 static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
+       struct v4l2_subdev *csi2_sd;
        int ret;
 
        if (pcdev->icd)
                return -EBUSY;
 
-       dev_info(icd->dev.parent,
+       dev_info(icd->parent,
                 "SuperH Mobile CEU driver attached to camera %d\n",
                 icd->devnum);
 
        pm_runtime_get_sync(ici->v4l2_dev.dev);
 
        ret = sh_mobile_ceu_soft_reset(pcdev);
-       if (!ret)
+
+       csi2_sd = find_csi2(pcdev);
+
+       ret = v4l2_subdev_call(csi2_sd, core, s_power, 1);
+       if (ret != -ENODEV && ret != -ENOIOCTLCMD && ret < 0) {
+               pm_runtime_put_sync(ici->v4l2_dev.dev);
+       } else {
                pcdev->icd = icd;
+               ret = 0;
+       }
 
        return ret;
 }
@@ -525,11 +553,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
 /* Called with .video_lock held */
 static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
+       struct v4l2_subdev *csi2_sd = find_csi2(pcdev);
 
        BUG_ON(icd != pcdev->icd);
 
+       v4l2_subdev_call(csi2_sd, core, s_power, 0);
        /* disable capture, disable interrupts */
        ceu_write(pcdev, CEIER, 0);
        sh_mobile_ceu_soft_reset(pcdev);
@@ -545,7 +575,7 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
 
        pm_runtime_put_sync(ici->v4l2_dev.dev);
 
-       dev_info(icd->dev.parent,
+       dev_info(icd->parent,
                 "SuperH Mobile CEU driver detached from camera %d\n",
                 icd->devnum);
 
@@ -585,14 +615,14 @@ static u16 calc_scale(unsigned int src, unsigned int *dst)
 /* rect is guaranteed to not exceed the scaled camera rectangle */
 static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_cam *cam = icd->host_priv;
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
        unsigned int height, width, cdwdr_width, in_width, in_height;
        unsigned int left_offset, top_offset;
        u32 camor;
 
-       dev_geo(icd->dev.parent, "Crop %ux%u@%u:%u\n",
+       dev_geo(icd->parent, "Crop %ux%u@%u:%u\n",
                icd->user_width, icd->user_height, cam->ceu_left, cam->ceu_top);
 
        left_offset     = cam->ceu_left;
@@ -641,7 +671,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd)
        }
 
        /* CSI2 special configuration */
-       if (pcdev->pdata->csi2_dev) {
+       if (pcdev->pdata->csi2) {
                in_width = ((in_width - 2) * 2);
                left_offset *= 2;
        }
@@ -649,7 +679,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd)
        /* Set CAMOR, CAPWR, CFSZR, take care of CDWDR */
        camor = left_offset | (top_offset << 16);
 
-       dev_geo(icd->dev.parent,
+       dev_geo(icd->parent,
                "CAMOR 0x%x, CAPWR 0x%x, CFSZR 0x%x, CDWDR 0x%x\n", camor,
                (in_height << 16) | in_width, (height << 16) | width,
                cdwdr_width);
@@ -697,7 +727,7 @@ static void capture_restore(struct sh_mobile_ceu_dev *pcdev, u32 capsr)
 static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
                                       __u32 pixfmt)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
        int ret;
        unsigned long camera_flags, common_flags, value;
@@ -783,7 +813,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
        value |= pcdev->is_16bit ? 1 << 12 : 0;
 
        /* CSI2 mode */
-       if (pcdev->pdata->csi2_dev)
+       if (pcdev->pdata->csi2)
                value |= 3 << 12;
 
        ceu_write(pcdev, CAMCR, value);
@@ -806,7 +836,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
        sh_mobile_ceu_set_rect(icd);
        mdelay(1);
 
-       dev_geo(icd->dev.parent, "CFLCR 0x%x\n", pcdev->cflcr);
+       dev_geo(icd->parent, "CFLCR 0x%x\n", pcdev->cflcr);
        ceu_write(pcdev, CFLCR, pcdev->cflcr);
 
        /*
@@ -829,7 +859,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
        ceu_write(pcdev, CDOCR, value);
        ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */
 
-       dev_dbg(icd->dev.parent, "S_FMT successful for %c%c%c%c %ux%u\n",
+       dev_dbg(icd->parent, "S_FMT successful for %c%c%c%c %ux%u\n",
                pixfmt & 0xff, (pixfmt >> 8) & 0xff,
                (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff,
                icd->user_width, icd->user_height);
@@ -843,7 +873,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
 static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd,
                                       unsigned char buswidth)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
        unsigned long camera_flags, common_flags;
 
@@ -901,7 +931,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int
                                     struct soc_camera_format_xlate *xlate)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct device *dev = icd->dev.parent;
+       struct device *dev = icd->parent;
        struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
        int ret, k, n;
@@ -921,7 +951,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int
                return 0;
        }
 
-       if (!pcdev->pdata->csi2_dev) {
+       if (!pcdev->pdata->csi2) {
                ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample);
                if (ret < 0)
                        return 0;
@@ -1244,7 +1274,7 @@ static int client_s_fmt(struct soc_camera_device *icd,
 {
        struct sh_mobile_ceu_cam *cam = icd->host_priv;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct device *dev = icd->dev.parent;
+       struct device *dev = icd->parent;
        unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h;
        unsigned int max_width, max_height;
        struct v4l2_cropcap cap;
@@ -1313,7 +1343,7 @@ static int client_scale(struct soc_camera_device *icd,
                        bool ceu_can_scale)
 {
        struct sh_mobile_ceu_cam *cam = icd->host_priv;
-       struct device *dev = icd->dev.parent;
+       struct device *dev = icd->parent;
        struct v4l2_mbus_framefmt mf_tmp = *mf;
        unsigned int scale_h, scale_v;
        int ret;
@@ -1363,13 +1393,13 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
                                  struct v4l2_crop *a)
 {
        struct v4l2_rect *rect = &a->c;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct device *dev = icd->parent;
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
        struct v4l2_crop cam_crop;
        struct sh_mobile_ceu_cam *cam = icd->host_priv;
        struct v4l2_rect *cam_rect = &cam_crop.c;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct device *dev = icd->dev.parent;
        struct v4l2_mbus_framefmt mf;
        unsigned int scale_cam_h, scale_cam_v, scale_ceu_h, scale_ceu_v,
                out_width, out_height;
@@ -1511,7 +1541,7 @@ static void calculate_client_output(struct soc_camera_device *icd,
                struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf)
 {
        struct sh_mobile_ceu_cam *cam = icd->host_priv;
-       struct device *dev = icd->dev.parent;
+       struct device *dev = icd->parent;
        struct v4l2_rect *cam_subrect = &cam->subrect;
        unsigned int scale_v, scale_h;
 
@@ -1555,12 +1585,12 @@ static void calculate_client_output(struct soc_camera_device *icd,
 static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
                                 struct v4l2_format *f)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct device *dev = icd->parent;
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
        struct sh_mobile_ceu_cam *cam = icd->host_priv;
        struct v4l2_pix_format *pix = &f->fmt.pix;
        struct v4l2_mbus_framefmt mf;
-       struct device *dev = icd->dev.parent;
        __u32 pixfmt = pix->pixelformat;
        const struct soc_camera_format_xlate *xlate;
        /* Keep Compiler Happy */
@@ -1684,12 +1714,12 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
        int width, height;
        int ret;
 
-       dev_geo(icd->dev.parent, "TRY_FMT(pix=0x%x, %ux%u)\n",
+       dev_geo(icd->parent, "TRY_FMT(pix=0x%x, %ux%u)\n",
                 pixfmt, pix->width, pix->height);
 
        xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
        if (!xlate) {
-               dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt);
+               dev_warn(icd->parent, "Format %x not found\n", pixfmt);
                return -EINVAL;
        }
 
@@ -1701,11 +1731,6 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
        width = pix->width;
        height = pix->height;
 
-       pix->bytesperline = soc_mbus_bytes_per_line(width, xlate->host_fmt);
-       if ((int)pix->bytesperline < 0)
-               return pix->bytesperline;
-       pix->sizeimage = height * pix->bytesperline;
-
        /* limit to sensor capabilities */
        mf.width        = pix->width;
        mf.height       = pix->height;
@@ -1741,7 +1766,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
                                                         try_mbus_fmt, &mf);
                        if (ret < 0) {
                                /* Shouldn't actually happen... */
-                               dev_err(icd->dev.parent,
+                               dev_err(icd->parent,
                                        "FIXME: client try_fmt() = %d\n", ret);
                                return ret;
                        }
@@ -1753,7 +1778,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
                        pix->height = height;
        }
 
-       dev_geo(icd->dev.parent, "%s(): return %d, fmt 0x%x, %ux%u\n",
+       dev_geo(icd->parent, "%s(): return %d, fmt 0x%x, %ux%u\n",
                __func__, ret, pix->pixelformat, pix->width, pix->height);
 
        return ret;
@@ -1763,7 +1788,7 @@ static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
                                      struct v4l2_crop *a)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
        u32 out_width = icd->user_width, out_height = icd->user_height;
        int ret;
@@ -1775,13 +1800,13 @@ static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
        /* Stop the client */
        ret = v4l2_subdev_call(sd, video, s_stream, 0);
        if (ret < 0)
-               dev_warn(icd->dev.parent,
+               dev_warn(icd->parent,
                         "Client failed to stop the stream: %d\n", ret);
        else
                /* Do the crop, if it fails, there's nothing more we can do */
                sh_mobile_ceu_set_crop(icd, a);
 
-       dev_geo(icd->dev.parent, "Output after crop: %ux%u\n", icd->user_width, icd->user_height);
+       dev_geo(icd->parent, "Output after crop: %ux%u\n", icd->user_width, icd->user_height);
 
        if (icd->user_width != out_width || icd->user_height != out_height) {
                struct v4l2_format f = {
@@ -1827,7 +1852,6 @@ static int sh_mobile_ceu_querycap(struct soc_camera_host *ici,
                                  struct v4l2_capability *cap)
 {
        strlcpy(cap->card, "SuperH_Mobile_CEU", sizeof(cap->card));
-       cap->version = KERNEL_VERSION(0, 0, 5);
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
        return 0;
 }
@@ -1848,7 +1872,7 @@ static int sh_mobile_ceu_init_videobuf(struct vb2_queue *q,
 static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd,
                                  struct v4l2_control *ctrl)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
        u32 val;
 
@@ -1864,7 +1888,7 @@ static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd,
 static int sh_mobile_ceu_set_ctrl(struct soc_camera_device *icd,
                                  struct v4l2_control *ctrl)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
 
        switch (ctrl->id) {
@@ -1950,7 +1974,7 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)
                .completion = COMPLETION_INITIALIZER_ONSTACK(wait.completion),
                .notifier.notifier_call = bus_notify,
        };
-       struct device *csi2;
+       struct sh_mobile_ceu_companion *csi2;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_irq(pdev, 0);
@@ -2023,26 +2047,61 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)
        pcdev->ici.drv_name = dev_name(&pdev->dev);
        pcdev->ici.ops = &sh_mobile_ceu_host_ops;
 
+       pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+       if (IS_ERR(pcdev->alloc_ctx)) {
+               err = PTR_ERR(pcdev->alloc_ctx);
+               goto exit_free_clk;
+       }
+
+       err = soc_camera_host_register(&pcdev->ici);
+       if (err)
+               goto exit_free_ctx;
+
        /* CSI2 interfacing */
-       csi2 = pcdev->pdata->csi2_dev;
+       csi2 = pcdev->pdata->csi2;
        if (csi2) {
-               wait.dev = csi2;
+               struct platform_device *csi2_pdev =
+                       platform_device_alloc("sh-mobile-csi2", csi2->id);
+               struct sh_csi2_pdata *csi2_pdata = csi2->platform_data;
+
+               if (!csi2_pdev) {
+                       err = -ENOMEM;
+                       goto exit_host_unregister;
+               }
+
+               pcdev->csi2_pdev                = csi2_pdev;
+
+               err = platform_device_add_data(csi2_pdev, csi2_pdata, sizeof(*csi2_pdata));
+               if (err < 0)
+                       goto exit_pdev_put;
+
+               csi2_pdata                      = csi2_pdev->dev.platform_data;
+               csi2_pdata->v4l2_dev            = &pcdev->ici.v4l2_dev;
+
+               csi2_pdev->resource             = csi2->resource;
+               csi2_pdev->num_resources        = csi2->num_resources;
+
+               err = platform_device_add(csi2_pdev);
+               if (err < 0)
+                       goto exit_pdev_put;
+
+               wait.dev = &csi2_pdev->dev;
 
                err = bus_register_notifier(&platform_bus_type, &wait.notifier);
                if (err < 0)
-                       goto exit_free_clk;
+                       goto exit_pdev_unregister;
 
                /*
                 * From this point the driver module will not unload, until
                 * we complete the completion.
                 */
 
-               if (!csi2->driver) {
+               if (!csi2_pdev->dev.driver) {
                        complete(&wait.completion);
                        /* Either too late, or probing failed */
                        bus_unregister_notifier(&platform_bus_type, &wait.notifier);
                        err = -ENXIO;
-                       goto exit_free_clk;
+                       goto exit_pdev_unregister;
                }
 
                /*
@@ -2051,34 +2110,28 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)
                 * the "owner" is safe!
                 */
 
-               err = try_module_get(csi2->driver->owner);
+               err = try_module_get(csi2_pdev->dev.driver->owner);
 
                /* Let notifier complete, if it has been locked */
                complete(&wait.completion);
                bus_unregister_notifier(&platform_bus_type, &wait.notifier);
                if (!err) {
                        err = -ENODEV;
-                       goto exit_free_clk;
+                       goto exit_pdev_unregister;
                }
        }
 
-       pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
-       if (IS_ERR(pcdev->alloc_ctx)) {
-               err = PTR_ERR(pcdev->alloc_ctx);
-               goto exit_module_put;
-       }
-
-       err = soc_camera_host_register(&pcdev->ici);
-       if (err)
-               goto exit_free_ctx;
-
        return 0;
 
+exit_pdev_unregister:
+       platform_device_del(pcdev->csi2_pdev);
+exit_pdev_put:
+       pcdev->csi2_pdev->resource = NULL;
+       platform_device_put(pcdev->csi2_pdev);
+exit_host_unregister:
+       soc_camera_host_unregister(&pcdev->ici);
 exit_free_ctx:
        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
-exit_module_put:
-       if (csi2 && csi2->driver)
-               module_put(csi2->driver->owner);
 exit_free_clk:
        pm_runtime_disable(&pdev->dev);
        free_irq(pcdev->irq, pcdev);
@@ -2098,7 +2151,7 @@ static int __devexit sh_mobile_ceu_remove(struct platform_device *pdev)
        struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
        struct sh_mobile_ceu_dev *pcdev = container_of(soc_host,
                                        struct sh_mobile_ceu_dev, ici);
-       struct device *csi2 = pcdev->pdata->csi2_dev;
+       struct platform_device *csi2_pdev = pcdev->csi2_pdev;
 
        soc_camera_host_unregister(soc_host);
        pm_runtime_disable(&pdev->dev);
@@ -2107,8 +2160,13 @@ static int __devexit sh_mobile_ceu_remove(struct platform_device *pdev)
                dma_release_declared_memory(&pdev->dev);
        iounmap(pcdev->base);
        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
-       if (csi2 && csi2->driver)
-               module_put(csi2->driver->owner);
+       if (csi2_pdev && csi2_pdev->dev.driver) {
+               struct module *csi2_drv = csi2_pdev->dev.driver->owner;
+               platform_device_del(csi2_pdev);
+               csi2_pdev->resource = NULL;
+               platform_device_put(csi2_pdev);
+               module_put(csi2_drv);
+       }
        kfree(pcdev);
 
        return 0;
@@ -2158,4 +2216,5 @@ module_exit(sh_mobile_ceu_exit);
 MODULE_DESCRIPTION("SuperH Mobile CEU driver");
 MODULE_AUTHOR("Magnus Damm");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.6");
 MODULE_ALIAS("platform:sh_mobile_ceu");
index 98b8748..2893a01 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 
+#include <media/sh_mobile_ceu.h>
 #include <media/sh_mobile_csi2.h>
 #include <media/soc_camera.h>
 #include <media/v4l2-common.h>
@@ -33,7 +34,6 @@
 struct sh_csi2 {
        struct v4l2_subdev              subdev;
        struct list_head                list;
-       struct notifier_block           notifier;
        unsigned int                    irq;
        void __iomem                    *base;
        struct platform_device          *pdev;
@@ -132,13 +132,6 @@ static struct v4l2_subdev_video_ops sh_csi2_subdev_video_ops = {
        .try_mbus_fmt   = sh_csi2_try_fmt,
 };
 
-static struct v4l2_subdev_core_ops sh_csi2_subdev_core_ops;
-
-static struct v4l2_subdev_ops sh_csi2_subdev_ops = {
-       .core   = &sh_csi2_subdev_core_ops,
-       .video  = &sh_csi2_subdev_video_ops,
-};
-
 static void sh_csi2_hwinit(struct sh_csi2 *priv)
 {
        struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data;
@@ -186,65 +179,84 @@ static unsigned long sh_csi2_query_bus_param(struct soc_camera_device *icd)
        return soc_camera_apply_sensor_flags(icl, flags);
 }
 
-static int sh_csi2_notify(struct notifier_block *nb,
-                         unsigned long action, void *data)
+static int sh_csi2_client_connect(struct sh_csi2 *priv)
 {
-       struct device *dev = data;
-       struct soc_camera_device *icd = to_soc_camera_dev(dev);
-       struct v4l2_device *v4l2_dev = dev_get_drvdata(dev->parent);
-       struct sh_csi2 *priv =
-               container_of(nb, struct sh_csi2, notifier);
        struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data;
-       int ret, i;
+       struct v4l2_subdev *sd, *csi2_sd = &priv->subdev;
+       struct soc_camera_device *icd = NULL;
+       struct device *dev = v4l2_get_subdevdata(&priv->subdev);
+       int i;
+
+       v4l2_device_for_each_subdev(sd, csi2_sd->v4l2_dev)
+               if (sd->grp_id) {
+                       icd = (struct soc_camera_device *)sd->grp_id;
+                       break;
+               }
+
+       if (!icd)
+               return -EINVAL;
 
        for (i = 0; i < pdata->num_clients; i++)
                if (&pdata->clients[i].pdev->dev == icd->pdev)
                        break;
 
-       dev_dbg(dev, "%s(%p): action = %lu, found #%d\n", __func__, dev, action, i);
+       dev_dbg(dev, "%s(%p): found #%d\n", __func__, dev, i);
 
        if (i == pdata->num_clients)
-               return NOTIFY_DONE;
+               return -ENODEV;
 
-       switch (action) {
-       case BUS_NOTIFY_BOUND_DRIVER:
-               snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s%s",
-                        dev_name(v4l2_dev->dev), ".mipi-csi");
-               priv->subdev.grp_id = (long)icd;
-               ret = v4l2_device_register_subdev(v4l2_dev, &priv->subdev);
-               dev_dbg(dev, "%s(%p): ret(register_subdev) = %d\n", __func__, priv, ret);
-               if (ret < 0)
-                       return NOTIFY_DONE;
+       priv->client = pdata->clients + i;
 
-               priv->client = pdata->clients + i;
+       priv->set_bus_param             = icd->ops->set_bus_param;
+       priv->query_bus_param           = icd->ops->query_bus_param;
+       icd->ops->set_bus_param         = sh_csi2_set_bus_param;
+       icd->ops->query_bus_param       = sh_csi2_query_bus_param;
 
-               priv->set_bus_param             = icd->ops->set_bus_param;
-               priv->query_bus_param           = icd->ops->query_bus_param;
-               icd->ops->set_bus_param         = sh_csi2_set_bus_param;
-               icd->ops->query_bus_param       = sh_csi2_query_bus_param;
+       csi2_sd->grp_id = (long)icd;
 
-               pm_runtime_get_sync(v4l2_get_subdevdata(&priv->subdev));
+       pm_runtime_get_sync(dev);
 
-               sh_csi2_hwinit(priv);
-               break;
-       case BUS_NOTIFY_UNBIND_DRIVER:
-               priv->client = NULL;
+       sh_csi2_hwinit(priv);
 
-               /* Driver is about to be unbound */
-               icd->ops->set_bus_param         = priv->set_bus_param;
-               icd->ops->query_bus_param       = priv->query_bus_param;
-               priv->set_bus_param             = NULL;
-               priv->query_bus_param           = NULL;
+       return 0;
+}
 
-               v4l2_device_unregister_subdev(&priv->subdev);
+static void sh_csi2_client_disconnect(struct sh_csi2 *priv)
+{
+       struct soc_camera_device *icd = (struct soc_camera_device *)priv->subdev.grp_id;
 
-               pm_runtime_put(v4l2_get_subdevdata(&priv->subdev));
-               break;
-       }
+       priv->client = NULL;
+       priv->subdev.grp_id = 0;
 
-       return NOTIFY_OK;
+       /* Driver is about to be unbound */
+       icd->ops->set_bus_param         = priv->set_bus_param;
+       icd->ops->query_bus_param       = priv->query_bus_param;
+       priv->set_bus_param             = NULL;
+       priv->query_bus_param           = NULL;
+
+       pm_runtime_put(v4l2_get_subdevdata(&priv->subdev));
 }
 
+static int sh_csi2_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct sh_csi2 *priv = container_of(sd, struct sh_csi2, subdev);
+
+       if (on)
+               return sh_csi2_client_connect(priv);
+
+       sh_csi2_client_disconnect(priv);
+       return 0;
+}
+
+static struct v4l2_subdev_core_ops sh_csi2_subdev_core_ops = {
+       .s_power        = sh_csi2_s_power,
+};
+
+static struct v4l2_subdev_ops sh_csi2_subdev_ops = {
+       .core   = &sh_csi2_subdev_core_ops,
+       .video  = &sh_csi2_subdev_video_ops,
+};
+
 static __devinit int sh_csi2_probe(struct platform_device *pdev)
 {
        struct resource *res;
@@ -274,14 +286,6 @@ static __devinit int sh_csi2_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        priv->irq = irq;
-       priv->notifier.notifier_call = sh_csi2_notify;
-
-       /* We MUST attach after the MIPI sensor */
-       ret = bus_register_notifier(&soc_camera_bus_type, &priv->notifier);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "CSI2 cannot register notifier\n");
-               goto ernotify;
-       }
 
        if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
                dev_err(&pdev->dev, "CSI2 register region already claimed\n");
@@ -297,11 +301,17 @@ static __devinit int sh_csi2_probe(struct platform_device *pdev)
        }
 
        priv->pdev = pdev;
+       platform_set_drvdata(pdev, priv);
 
        v4l2_subdev_init(&priv->subdev, &sh_csi2_subdev_ops);
        v4l2_set_subdevdata(&priv->subdev, &pdev->dev);
 
-       platform_set_drvdata(pdev, priv);
+       snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s.mipi-csi",
+                dev_name(pdata->v4l2_dev->dev));
+       ret = v4l2_device_register_subdev(pdata->v4l2_dev, &priv->subdev);
+       dev_dbg(&pdev->dev, "%s(%p): ret(register_subdev) = %d\n", __func__, priv, ret);
+       if (ret < 0)
+               goto esdreg;
 
        pm_runtime_enable(&pdev->dev);
 
@@ -309,11 +319,11 @@ static __devinit int sh_csi2_probe(struct platform_device *pdev)
 
        return 0;
 
+esdreg:
+       iounmap(priv->base);
 eremap:
        release_mem_region(res->start, resource_size(res));
 ereqreg:
-       bus_unregister_notifier(&soc_camera_bus_type, &priv->notifier);
-ernotify:
        kfree(priv);
 
        return ret;
@@ -324,7 +334,7 @@ static __devexit int sh_csi2_remove(struct platform_device *pdev)
        struct sh_csi2 *priv = platform_get_drvdata(pdev);
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-       bus_unregister_notifier(&soc_camera_bus_type, &priv->notifier);
+       v4l2_device_unregister_subdev(&priv->subdev);
        pm_runtime_disable(&pdev->dev);
        iounmap(priv->base);
        release_mem_region(res->start, resource_size(res));
@@ -335,8 +345,9 @@ static __devexit int sh_csi2_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver __refdata sh_csi2_pdrv = {
-       .remove  = __devexit_p(sh_csi2_remove),
-       .driver  = {
+       .remove = __devexit_p(sh_csi2_remove),
+       .probe  = sh_csi2_probe,
+       .driver = {
                .name   = "sh-mobile-csi2",
                .owner  = THIS_MODULE,
        },
@@ -344,7 +355,7 @@ static struct platform_driver __refdata sh_csi2_pdrv = {
 
 static int __init sh_csi2_init(void)
 {
-       return platform_driver_probe(&sh_csi2_pdrv, sh_csi2_probe);
+       return platform_driver_register(&sh_csi2_pdrv);
 }
 
 static void __exit sh_csi2_exit(void)
index 07cf0c6..6a72987 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 
 #include <media/sh_vou.h>
@@ -393,7 +392,6 @@ static int sh_vou_querycap(struct file *file, void  *priv,
        dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
 
        strlcpy(cap->card, "SuperH VOU", sizeof(cap->card));
-       cap->version = KERNEL_VERSION(0, 1, 0);
        cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
        return 0;
 }
@@ -1490,4 +1488,5 @@ module_exit(sh_vou_exit);
 MODULE_DESCRIPTION("SuperH VOU driver");
 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
 MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.1.0");
 MODULE_ALIAS("platform:sh-vou");
index cbfc444..22ea211 100644 (file)
@@ -21,7 +21,6 @@
 #ifndef _SN9C102_H_
 #define _SN9C102_H_
 
-#include <linux/version.h>
 #include <linux/usb.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
index 0e07c49..16cb07c 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
+#include <linux/version.h>
 #include <linux/page-flags.h>
 #include <asm/byteorder.h>
 #include <asm/page.h>
@@ -47,8 +48,7 @@
 #define SN9C102_MODULE_AUTHOR   "(C) 2004-2007 Luca Risolia"
 #define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
 #define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.47pre49"
-#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 1, 47)
+#define SN9C102_MODULE_VERSION  "1:1.48"
 
 /*****************************************************************************/
 
@@ -2158,7 +2158,7 @@ sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg)
 {
        struct v4l2_capability cap = {
                .driver = "sn9c102",
-               .version = SN9C102_MODULE_VERSION_CODE,
+               .version = LINUX_VERSION_CODE,
                .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
                                V4L2_CAP_STREAMING,
        };
@@ -3187,16 +3187,8 @@ static long sn9c102_ioctl_v4l2(struct file *filp,
        case VIDIOC_S_AUDIO:
                return sn9c102_vidioc_s_audio(cam, arg);
 
-       case VIDIOC_G_STD:
-       case VIDIOC_S_STD:
-       case VIDIOC_QUERYSTD:
-       case VIDIOC_ENUMSTD:
-       case VIDIOC_QUERYMENU:
-       case VIDIOC_ENUM_FRAMEINTERVALS:
-               return -EINVAL;
-
        default:
-               return -EINVAL;
+               return -ENOTTY;
 
        }
 }
index 4e4d412..5bdfe7e 100644 (file)
@@ -60,14 +60,14 @@ static int soc_camera_power_set(struct soc_camera_device *icd,
                ret = regulator_bulk_enable(icl->num_regulators,
                                            icl->regulators);
                if (ret < 0) {
-                       dev_err(&icd->dev, "Cannot enable regulators\n");
+                       dev_err(icd->pdev, "Cannot enable regulators\n");
                        return ret;
                }
 
                if (icl->power)
                        ret = icl->power(icd->pdev, power_on);
                if (ret < 0) {
-                       dev_err(&icd->dev,
+                       dev_err(icd->pdev,
                                "Platform failed to power-on the camera.\n");
 
                        regulator_bulk_disable(icl->num_regulators,
@@ -79,7 +79,7 @@ static int soc_camera_power_set(struct soc_camera_device *icd,
                if (icl->power)
                        ret = icl->power(icd->pdev, 0);
                if (ret < 0) {
-                       dev_err(&icd->dev,
+                       dev_err(icd->pdev,
                                "Platform failed to power-off the camera.\n");
                        return ret;
                }
@@ -87,7 +87,7 @@ static int soc_camera_power_set(struct soc_camera_device *icd,
                ret = regulator_bulk_disable(icl->num_regulators,
                                             icl->regulators);
                if (ret < 0) {
-                       dev_err(&icd->dev, "Cannot disable regulators\n");
+                       dev_err(icd->pdev, "Cannot disable regulators\n");
                        return ret;
                }
        }
@@ -147,11 +147,11 @@ EXPORT_SYMBOL(soc_camera_apply_sensor_flags);
 static int soc_camera_try_fmt(struct soc_camera_device *icd,
                              struct v4l2_format *f)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct v4l2_pix_format *pix = &f->fmt.pix;
        int ret;
 
-       dev_dbg(&icd->dev, "TRY_FMT(%c%c%c%c, %ux%u)\n",
+       dev_dbg(icd->pdev, "TRY_FMT(%c%c%c%c, %ux%u)\n",
                pixfmtstr(pix->pixelformat), pix->width, pix->height);
 
        pix->bytesperline = 0;
@@ -199,22 +199,15 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
 static int soc_camera_enum_input(struct file *file, void *priv,
                                 struct v4l2_input *inp)
 {
-       struct soc_camera_device *icd = file->private_data;
-       int ret = 0;
-
        if (inp->index != 0)
                return -EINVAL;
 
-       if (icd->ops->enum_input)
-               ret = icd->ops->enum_input(icd, inp);
-       else {
-               /* default is camera */
-               inp->type = V4L2_INPUT_TYPE_CAMERA;
-               inp->std  = V4L2_STD_UNKNOWN;
-               strcpy(inp->name, "Camera");
-       }
+       /* default is camera */
+       inp->type = V4L2_INPUT_TYPE_CAMERA;
+       inp->std  = V4L2_STD_UNKNOWN;
+       strcpy(inp->name, "Camera");
 
-       return ret;
+       return 0;
 }
 
 static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i)
@@ -244,7 +237,7 @@ static int soc_camera_enum_fsizes(struct file *file, void *fh,
                                         struct v4l2_frmsizeenum *fsize)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        return ici->ops->enum_fsizes(icd, fsize);
 }
@@ -254,7 +247,7 @@ static int soc_camera_reqbufs(struct file *file, void *priv,
 {
        int ret;
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        WARN_ON(priv != file->private_data);
 
@@ -281,7 +274,7 @@ static int soc_camera_querybuf(struct file *file, void *priv,
                               struct v4l2_buffer *p)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        WARN_ON(priv != file->private_data);
 
@@ -295,7 +288,7 @@ static int soc_camera_qbuf(struct file *file, void *priv,
                           struct v4l2_buffer *p)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        WARN_ON(priv != file->private_data);
 
@@ -312,7 +305,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
                            struct v4l2_buffer *p)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        WARN_ON(priv != file->private_data);
 
@@ -329,7 +322,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
 static int soc_camera_init_user_formats(struct soc_camera_device *icd)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        unsigned int i, fmts = 0, raw_fmts = 0;
        int ret;
        enum v4l2_mbus_pixelcode code;
@@ -363,7 +356,7 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
        if (!icd->user_formats)
                return -ENOMEM;
 
-       dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts);
+       dev_dbg(icd->pdev, "Found %d supported formats.\n", fmts);
 
        /* Second pass - actually fill data formats */
        fmts = 0;
@@ -395,7 +388,7 @@ egfmt:
 /* Always entered with .video_lock held */
 static void soc_camera_free_user_formats(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        if (ici->ops->put_formats)
                ici->ops->put_formats(icd);
@@ -409,11 +402,11 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd)
 static int soc_camera_set_fmt(struct soc_camera_device *icd,
                              struct v4l2_format *f)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct v4l2_pix_format *pix = &f->fmt.pix;
        int ret;
 
-       dev_dbg(&icd->dev, "S_FMT(%c%c%c%c, %ux%u)\n",
+       dev_dbg(icd->pdev, "S_FMT(%c%c%c%c, %ux%u)\n",
                pixfmtstr(pix->pixelformat), pix->width, pix->height);
 
        /* We always call try_fmt() before set_fmt() or set_crop() */
@@ -426,7 +419,7 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd,
                return ret;
        } else if (!icd->current_fmt ||
                   icd->current_fmt->host_fmt->fourcc != pix->pixelformat) {
-               dev_err(&icd->dev,
+               dev_err(icd->pdev,
                        "Host driver hasn't set up current format correctly!\n");
                return -EINVAL;
        }
@@ -440,7 +433,7 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd,
        if (ici->ops->init_videobuf)
                icd->vb_vidq.field = pix->field;
 
-       dev_dbg(&icd->dev, "set width: %d height: %d\n",
+       dev_dbg(icd->pdev, "set width: %d height: %d\n",
                icd->user_width, icd->user_height);
 
        /* set physical bus parameters */
@@ -450,9 +443,7 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd,
 static int soc_camera_open(struct file *file)
 {
        struct video_device *vdev = video_devdata(file);
-       struct soc_camera_device *icd = container_of(vdev->parent,
-                                                    struct soc_camera_device,
-                                                    dev);
+       struct soc_camera_device *icd = dev_get_drvdata(vdev->parent);
        struct soc_camera_link *icl = to_soc_camera_link(icd);
        struct soc_camera_host *ici;
        int ret;
@@ -461,10 +452,10 @@ static int soc_camera_open(struct file *file)
                /* No device driver attached */
                return -ENODEV;
 
-       ici = to_soc_camera_host(icd->dev.parent);
+       ici = to_soc_camera_host(icd->parent);
 
        if (!try_module_get(ici->ops->owner)) {
-               dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
+               dev_err(icd->pdev, "Couldn't lock capture bus driver.\n");
                return -EINVAL;
        }
 
@@ -495,7 +486,7 @@ static int soc_camera_open(struct file *file)
 
                ret = ici->ops->add(icd);
                if (ret < 0) {
-                       dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
+                       dev_err(icd->pdev, "Couldn't activate the camera: %d\n", ret);
                        goto eiciadd;
                }
 
@@ -524,7 +515,7 @@ static int soc_camera_open(struct file *file)
        }
 
        file->private_data = icd;
-       dev_dbg(&icd->dev, "camera device open\n");
+       dev_dbg(icd->pdev, "camera device open\n");
 
        return 0;
 
@@ -549,7 +540,7 @@ epower:
 static int soc_camera_close(struct file *file)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        icd->use_count--;
        if (!icd->use_count) {
@@ -570,7 +561,7 @@ static int soc_camera_close(struct file *file)
 
        module_put(ici->ops->owner);
 
-       dev_dbg(&icd->dev, "camera device close\n");
+       dev_dbg(icd->pdev, "camera device close\n");
 
        return 0;
 }
@@ -581,7 +572,7 @@ static ssize_t soc_camera_read(struct file *file, char __user *buf,
        struct soc_camera_device *icd = file->private_data;
        int err = -EINVAL;
 
-       dev_err(&icd->dev, "camera device read not implemented\n");
+       dev_err(icd->pdev, "camera device read not implemented\n");
 
        return err;
 }
@@ -589,10 +580,10 @@ static ssize_t soc_camera_read(struct file *file, char __user *buf,
 static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        int err;
 
-       dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
+       dev_dbg(icd->pdev, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
 
        if (icd->streamer != file)
                return -EBUSY;
@@ -602,7 +593,7 @@ static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
        else
                err = vb2_mmap(&icd->vb2_vidq, vma);
 
-       dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n",
+       dev_dbg(icd->pdev, "vma start=0x%08lx, size=%ld, ret=%d\n",
                (unsigned long)vma->vm_start,
                (unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
                err);
@@ -613,13 +604,13 @@ static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
 static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        if (icd->streamer != file)
                return -EBUSY;
 
        if (ici->ops->init_videobuf && list_empty(&icd->vb_vidq.stream)) {
-               dev_err(&icd->dev, "Trying to poll with no queued buffers!\n");
+               dev_err(icd->pdev, "Trying to poll with no queued buffers!\n");
                return POLLERR;
        }
 
@@ -659,15 +650,15 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
        WARN_ON(priv != file->private_data);
 
        if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               dev_warn(&icd->dev, "Wrong buf-type %d\n", f->type);
+               dev_warn(icd->pdev, "Wrong buf-type %d\n", f->type);
                return -EINVAL;
        }
 
        if (icd->streamer && icd->streamer != file)
                return -EBUSY;
 
-       if (is_streaming(to_soc_camera_host(icd->dev.parent), icd)) {
-               dev_err(&icd->dev, "S_FMT denied: queue initialised\n");
+       if (is_streaming(to_soc_camera_host(icd->parent), icd)) {
+               dev_err(icd->pdev, "S_FMT denied: queue initialised\n");
                return -EBUSY;
        }
 
@@ -716,7 +707,7 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv,
        pix->field              = icd->field;
        pix->pixelformat        = icd->current_fmt->host_fmt->fourcc;
        pix->colorspace         = icd->colorspace;
-       dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n",
+       dev_dbg(icd->pdev, "current_fmt->fourcc: 0x%08x\n",
                icd->current_fmt->host_fmt->fourcc);
        return 0;
 }
@@ -725,7 +716,7 @@ static int soc_camera_querycap(struct file *file, void  *priv,
                               struct v4l2_capability *cap)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        WARN_ON(priv != file->private_data);
 
@@ -737,7 +728,7 @@ static int soc_camera_streamon(struct file *file, void *priv,
                               enum v4l2_buf_type i)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        int ret;
 
@@ -766,7 +757,7 @@ static int soc_camera_streamoff(struct file *file, void *priv,
 {
        struct soc_camera_device *icd = file->private_data;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        WARN_ON(priv != file->private_data);
 
@@ -794,7 +785,7 @@ static int soc_camera_queryctrl(struct file *file, void *priv,
                                struct v4l2_queryctrl *qc)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        int i;
 
        WARN_ON(priv != file->private_data);
@@ -825,7 +816,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv,
                             struct v4l2_control *ctrl)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        int ret;
 
@@ -844,7 +835,7 @@ static int soc_camera_s_ctrl(struct file *file, void *priv,
                             struct v4l2_control *ctrl)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        int ret;
 
@@ -863,7 +854,7 @@ static int soc_camera_cropcap(struct file *file, void *fh,
                              struct v4l2_cropcap *a)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        return ici->ops->cropcap(icd, a);
 }
@@ -872,7 +863,7 @@ static int soc_camera_g_crop(struct file *file, void *fh,
                             struct v4l2_crop *a)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        int ret;
 
        ret = ici->ops->get_crop(icd, a);
@@ -889,7 +880,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
                             struct v4l2_crop *a)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct v4l2_rect *rect = &a->c;
        struct v4l2_crop current_crop;
        int ret;
@@ -897,7 +888,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
        if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
-       dev_dbg(&icd->dev, "S_CROP(%ux%u@%u:%u)\n",
+       dev_dbg(icd->pdev, "S_CROP(%ux%u@%u:%u)\n",
                rect->width, rect->height, rect->left, rect->top);
 
        /* If get_crop fails, we'll let host and / or client drivers decide */
@@ -905,7 +896,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
 
        /* Prohibit window size change with initialised buffers */
        if (ret < 0) {
-               dev_err(&icd->dev,
+               dev_err(icd->pdev,
                        "S_CROP denied: getting current crop failed\n");
        } else if ((a->c.width == current_crop.c.width &&
                    a->c.height == current_crop.c.height) ||
@@ -915,7 +906,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
        } else if (ici->ops->set_livecrop) {
                ret = ici->ops->set_livecrop(icd, a);
        } else {
-               dev_err(&icd->dev,
+               dev_err(icd->pdev,
                        "S_CROP denied: queue initialised and sizes differ\n");
                ret = -EBUSY;
        }
@@ -927,7 +918,7 @@ static int soc_camera_g_parm(struct file *file, void *fh,
                             struct v4l2_streamparm *a)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        if (ici->ops->get_parm)
                return ici->ops->get_parm(icd, a);
@@ -939,7 +930,7 @@ static int soc_camera_s_parm(struct file *file, void *fh,
                             struct v4l2_streamparm *a)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
        if (ici->ops->set_parm)
                return ici->ops->set_parm(icd, a);
@@ -976,6 +967,8 @@ static int soc_camera_s_register(struct file *file, void *fh,
 }
 #endif
 
+static int soc_camera_probe(struct soc_camera_device *icd);
+
 /* So far this function cannot fail */
 static void scan_add_host(struct soc_camera_host *ici)
 {
@@ -986,15 +979,9 @@ static void scan_add_host(struct soc_camera_host *ici)
        list_for_each_entry(icd, &devices, list) {
                if (icd->iface == ici->nr) {
                        int ret;
-                       icd->dev.parent = ici->v4l2_dev.dev;
-                       dev_set_name(&icd->dev, "%u-%u", icd->iface,
-                                    icd->devnum);
-                       ret = device_register(&icd->dev);
-                       if (ret < 0) {
-                               icd->dev.parent = NULL;
-                               dev_err(&icd->dev,
-                                       "Cannot register device: %d\n", ret);
-                       }
+
+                       icd->parent = ici->v4l2_dev.dev;
+                       ret = soc_camera_probe(icd);
                }
        }
 
@@ -1006,12 +993,12 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd,
                               struct soc_camera_link *icl)
 {
        struct i2c_client *client;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id);
        struct v4l2_subdev *subdev;
 
        if (!adap) {
-               dev_err(&icd->dev, "Cannot get I2C adapter #%d. No driver?\n",
+               dev_err(icd->pdev, "Cannot get I2C adapter #%d. No driver?\n",
                        icl->i2c_adapter_id);
                goto ei2cga;
        }
@@ -1026,7 +1013,7 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd,
        client = v4l2_get_subdevdata(subdev);
 
        /* Use to_i2c_client(dev) to recover the i2c client */
-       dev_set_drvdata(&icd->dev, &client->dev);
+       icd->control = &client->dev;
 
        return 0;
 ei2cnd:
@@ -1040,7 +1027,8 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd)
        struct i2c_client *client =
                to_i2c_client(to_soc_camera_control(icd));
        struct i2c_adapter *adap = client->adapter;
-       dev_set_drvdata(&icd->dev, NULL);
+
+       icd->control = NULL;
        v4l2_device_unregister_subdev(i2c_get_clientdata(client));
        i2c_unregister_device(client);
        i2c_put_adapter(adap);
@@ -1053,17 +1041,16 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd)
 static int soc_camera_video_start(struct soc_camera_device *icd);
 static int video_dev_create(struct soc_camera_device *icd);
 /* Called during host-driver probe */
-static int soc_camera_probe(struct device *dev)
+static int soc_camera_probe(struct soc_camera_device *icd)
 {
-       struct soc_camera_device *icd = to_soc_camera_dev(dev);
-       struct soc_camera_host *ici = to_soc_camera_host(dev->parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct soc_camera_link *icl = to_soc_camera_link(icd);
        struct device *control = NULL;
        struct v4l2_subdev *sd;
        struct v4l2_mbus_framefmt mf;
        int ret;
 
-       dev_info(dev, "Probing %s\n", dev_name(dev));
+       dev_info(icd->pdev, "Probing %s\n", dev_name(icd->pdev));
 
        ret = regulator_bulk_get(icd->pdev, icl->num_regulators,
                                 icl->regulators);
@@ -1099,7 +1086,7 @@ static int soc_camera_probe(struct device *dev)
                if (icl->module_name)
                        ret = request_module(icl->module_name);
 
-               ret = icl->add_device(icl, &icd->dev);
+               ret = icl->add_device(icd);
                if (ret < 0)
                        goto eadddev;
 
@@ -1110,7 +1097,7 @@ static int soc_camera_probe(struct device *dev)
                control = to_soc_camera_control(icd);
                if (!control || !control->driver || !dev_get_drvdata(control) ||
                    !try_module_get(control->driver->owner)) {
-                       icl->del_device(icl);
+                       icl->del_device(icd);
                        goto enodrv;
                }
        }
@@ -1125,8 +1112,6 @@ static int soc_camera_probe(struct device *dev)
 
        icd->field = V4L2_FIELD_ANY;
 
-       icd->vdev->lock = &icd->video_lock;
-
        /*
         * ..._video_start() will create a device node, video_register_device()
         * itself is protected against concurrent open() calls, but we also have
@@ -1146,11 +1131,6 @@ static int soc_camera_probe(struct device *dev)
                icd->field              = mf.field;
        }
 
-       /* Do we have to sysfs_remove_link() before device_unregister()? */
-       if (sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj,
-                             "control"))
-               dev_warn(&icd->dev, "Failed creating the control symlink\n");
-
        ici->ops->remove(icd);
 
        soc_camera_power_set(icd, icl, 0);
@@ -1166,7 +1146,7 @@ eiufmt:
        if (icl->board_info) {
                soc_camera_free_i2c(icd);
        } else {
-               icl->del_device(icl);
+               icl->del_device(icd);
                module_put(control->driver->owner);
        }
 enodrv:
@@ -1186,13 +1166,12 @@ ereg:
  * This is called on device_unregister, which only means we have to disconnect
  * from the host, but not remove ourselves from the device list
  */
-static int soc_camera_remove(struct device *dev)
+static int soc_camera_remove(struct soc_camera_device *icd)
 {
-       struct soc_camera_device *icd = to_soc_camera_dev(dev);
        struct soc_camera_link *icl = to_soc_camera_link(icd);
        struct video_device *vdev = icd->vdev;
 
-       BUG_ON(!dev->parent);
+       BUG_ON(!icd->parent);
 
        if (vdev) {
                video_unregister_device(vdev);
@@ -1202,10 +1181,9 @@ static int soc_camera_remove(struct device *dev)
        if (icl->board_info) {
                soc_camera_free_i2c(icd);
        } else {
-               struct device_driver *drv = to_soc_camera_control(icd) ?
-                       to_soc_camera_control(icd)->driver : NULL;
+               struct device_driver *drv = to_soc_camera_control(icd)->driver;
                if (drv) {
-                       icl->del_device(icl);
+                       icl->del_device(icd);
                        module_put(drv->owner);
                }
        }
@@ -1216,49 +1194,6 @@ static int soc_camera_remove(struct device *dev)
        return 0;
 }
 
-static int soc_camera_suspend(struct device *dev, pm_message_t state)
-{
-       struct soc_camera_device *icd = to_soc_camera_dev(dev);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-       int ret = 0;
-
-       if (ici->ops->suspend)
-               ret = ici->ops->suspend(icd, state);
-
-       return ret;
-}
-
-static int soc_camera_resume(struct device *dev)
-{
-       struct soc_camera_device *icd = to_soc_camera_dev(dev);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-       int ret = 0;
-
-       if (ici->ops->resume)
-               ret = ici->ops->resume(icd);
-
-       return ret;
-}
-
-struct bus_type soc_camera_bus_type = {
-       .name           = "soc-camera",
-       .probe          = soc_camera_probe,
-       .remove         = soc_camera_remove,
-       .suspend        = soc_camera_suspend,
-       .resume         = soc_camera_resume,
-};
-EXPORT_SYMBOL_GPL(soc_camera_bus_type);
-
-static struct device_driver ic_drv = {
-       .name   = "camera",
-       .bus    = &soc_camera_bus_type,
-       .owner  = THIS_MODULE,
-};
-
-static void dummy_release(struct device *dev)
-{
-}
-
 static int default_cropcap(struct soc_camera_device *icd,
                           struct v4l2_cropcap *a)
 {
@@ -1317,13 +1252,6 @@ static int default_enum_fsizes(struct soc_camera_device *icd,
        return 0;
 }
 
-static void soc_camera_device_init(struct device *dev, void *pdata)
-{
-       dev->platform_data      = pdata;
-       dev->bus                = &soc_camera_bus_type;
-       dev->release            = dummy_release;
-}
-
 int soc_camera_host_register(struct soc_camera_host *ici)
 {
        struct soc_camera_host *ix;
@@ -1389,24 +1317,9 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
        mutex_lock(&list_lock);
 
        list_del(&ici->list);
-
-       list_for_each_entry(icd, &devices, list) {
-               if (icd->iface == ici->nr) {
-                       void *pdata = icd->dev.platform_data;
-                       /* The bus->remove will be called */
-                       device_unregister(&icd->dev);
-                       /*
-                        * Not before device_unregister(), .remove
-                        * needs parent to call ici->ops->remove().
-                        * If the host module is loaded again, device_register()
-                        * would complain "already initialised," since 2.6.32
-                        * this is also needed to prevent use-after-free of the
-                        * device private data.
-                        */
-                       memset(&icd->dev, 0, sizeof(icd->dev));
-                       soc_camera_device_init(&icd->dev, pdata);
-               }
-       }
+       list_for_each_entry(icd, &devices, list)
+               if (icd->iface == ici->nr && to_soc_camera_control(icd))
+                       soc_camera_remove(icd);
 
        mutex_unlock(&list_lock);
 
@@ -1448,11 +1361,6 @@ static int soc_camera_device_register(struct soc_camera_device *icd)
        return 0;
 }
 
-static void soc_camera_device_unregister(struct soc_camera_device *icd)
-{
-       list_del(&icd->list);
-}
-
 static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
        .vidioc_querycap         = soc_camera_querycap,
        .vidioc_g_fmt_vid_cap    = soc_camera_g_fmt_vid_cap,
@@ -1487,7 +1395,7 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
 
 static int video_dev_create(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct video_device *vdev = video_device_alloc();
 
        if (!vdev)
@@ -1495,12 +1403,13 @@ static int video_dev_create(struct soc_camera_device *icd)
 
        strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
 
-       vdev->parent            = &icd->dev;
+       vdev->parent            = icd->pdev;
        vdev->current_norm      = V4L2_STD_UNKNOWN;
        vdev->fops              = &soc_camera_fops;
        vdev->ioctl_ops         = &soc_camera_ioctl_ops;
        vdev->release           = video_device_release;
        vdev->tvnorms           = V4L2_STD_UNKNOWN;
+       vdev->lock              = &icd->video_lock;
 
        icd->vdev = vdev;
 
@@ -1515,7 +1424,7 @@ static int soc_camera_video_start(struct soc_camera_device *icd)
        const struct device_type *type = icd->vdev->dev.type;
        int ret;
 
-       if (!icd->dev.parent)
+       if (!icd->parent)
                return -ENODEV;
 
        if (!icd->ops ||
@@ -1525,7 +1434,7 @@ static int soc_camera_video_start(struct soc_camera_device *icd)
 
        ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, -1);
        if (ret < 0) {
-               dev_err(&icd->dev, "video_register_device failed: %d\n", ret);
+               dev_err(icd->pdev, "video_register_device failed: %d\n", ret);
                return ret;
        }
 
@@ -1549,6 +1458,7 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        icd->iface = icl->bus_id;
+       icd->link = icl;
        icd->pdev = &pdev->dev;
        platform_set_drvdata(pdev, icd);
 
@@ -1556,8 +1466,6 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
        if (ret < 0)
                goto escdevreg;
 
-       soc_camera_device_init(&icd->dev, icl);
-
        icd->user_width         = DEFAULT_WIDTH;
        icd->user_height        = DEFAULT_HEIGHT;
 
@@ -1581,7 +1489,7 @@ static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
        if (!icd)
                return -EINVAL;
 
-       soc_camera_device_unregister(icd);
+       list_del(&icd->list);
 
        kfree(icd);
 
@@ -1598,31 +1506,12 @@ static struct platform_driver __refdata soc_camera_pdrv = {
 
 static int __init soc_camera_init(void)
 {
-       int ret = bus_register(&soc_camera_bus_type);
-       if (ret)
-               return ret;
-       ret = driver_register(&ic_drv);
-       if (ret)
-               goto edrvr;
-
-       ret = platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe);
-       if (ret)
-               goto epdr;
-
-       return 0;
-
-epdr:
-       driver_unregister(&ic_drv);
-edrvr:
-       bus_unregister(&soc_camera_bus_type);
-       return ret;
+       return platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe);
 }
 
 static void __exit soc_camera_exit(void)
 {
        platform_driver_unregister(&soc_camera_pdrv);
-       driver_unregister(&ic_drv);
-       bus_unregister(&soc_camera_bus_type);
 }
 
 module_init(soc_camera_init);
index bf406e8..8069cd6 100644 (file)
@@ -146,7 +146,7 @@ static int soc_camera_platform_probe(struct platform_device *pdev)
        if (!p)
                return -EINVAL;
 
-       if (!p->dev) {
+       if (!p->icd) {
                dev_err(&pdev->dev,
                        "Platform has not set soc_camera_device pointer!\n");
                return -EINVAL;
@@ -156,16 +156,16 @@ static int soc_camera_platform_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
-       icd = to_soc_camera_dev(p->dev);
+       icd = p->icd;
 
        /* soc-camera convention: control's drvdata points to the subdev */
        platform_set_drvdata(pdev, &priv->subdev);
        /* Set the control device reference */
-       dev_set_drvdata(&icd->dev, &pdev->dev);
+       icd->control = &pdev->dev;
 
        icd->ops = &soc_camera_platform_ops;
 
-       ici = to_soc_camera_host(icd->dev.parent);
+       ici = to_soc_camera_host(icd->parent);
 
        v4l2_subdev_init(&priv->subdev, &platform_subdev_ops);
        v4l2_set_subdevdata(&priv->subdev, p);
@@ -188,7 +188,7 @@ static int soc_camera_platform_remove(struct platform_device *pdev)
 {
        struct soc_camera_platform_priv *priv = get_priv(pdev);
        struct soc_camera_platform_info *p = pdev->dev.platform_data;
-       struct soc_camera_device *icd = to_soc_camera_dev(p->dev);
+       struct soc_camera_device *icd = p->icd;
 
        v4l2_device_unregister_subdev(&priv->subdev);
        icd->ops = NULL;
index c901721..8afb0e8 100644 (file)
@@ -726,8 +726,10 @@ static int sr030pc30_s_power(struct v4l2_subdev *sd, int on)
        const struct sr030pc30_platform_data *pdata = info->pdata;
        int ret;
 
-       if (WARN(pdata == NULL, "No platform data!\n"))
-               return -ENOMEM;
+       if (pdata == NULL) {
+               WARN(1, "No platform data!\n");
+               return -EINVAL;
+       }
 
        /*
         * Put sensor into power sleep mode before switching off
@@ -746,6 +748,7 @@ static int sr030pc30_s_power(struct v4l2_subdev *sd, int on)
        if (on) {
                ret = sr030pc30_base_config(sd);
        } else {
+               ret = 0;
                info->curr_win = NULL;
                info->curr_fmt = NULL;
        }
index 3941f95..bd21854 100644 (file)
@@ -49,10 +49,11 @@ static int maxvol;
 static int loudness; /* disable loudness by default */
 static int debug;       /* insmod parameter */
 module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Set debugging level from 0 to 3. Default is off(0).");
 module_param(loudness, int, S_IRUGO);
-MODULE_PARM_DESC(maxvol,"Set maximium volume to +20db (0), default is 0db(1)");
+MODULE_PARM_DESC(loudness, "Turn loudness on(1) else off(0). Default is off(0).");
 module_param(maxvol, int, S_IRUGO | S_IWUSR);
-
+MODULE_PARM_DESC(maxvol, "Set maximium volume to +20dB(0) else +0dB(1). Default is +20dB(0).");
 
 
 /* Structure of address and subaddresses for the tda7432 */
index fc611eb..84cd1b6 100644 (file)
@@ -20,7 +20,6 @@
  * Timberdale FPGA LogiWin Video In
  */
 
-#include <linux/version.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dmaengine.h>
index 46066bd..56564e6 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef PD_COMMON_H
 #define PD_COMMON_H
 
-#include <linux/version.h>
 #include <linux/fs.h>
 #include <linux/wait.h>
 #include <linux/list.h>
index 99c81a9..129f135 100644 (file)
@@ -531,3 +531,4 @@ module_exit(poseidon_exit);
 MODULE_AUTHOR("Telegent Systems");
 MODULE_DESCRIPTION("For tlg2300-based USB device ");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.2");
index fae84c2..4fad1df 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/usb.h>
 #include <linux/i2c.h>
 #include <media/v4l2-dev.h>
-#include <linux/version.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <media/v4l2-ioctl.h>
@@ -149,7 +148,6 @@ static int vidioc_querycap(struct file *file, void *priv,
        strlcpy(v->driver, "tele-radio", sizeof(v->driver));
        strlcpy(v->card, "Telegent Poseidon", sizeof(v->card));
        usb_make_path(p->udev, v->bus_info, sizeof(v->bus_info));
-       v->version = KERNEL_VERSION(0, 0, 1);
        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
        return 0;
 }
index a03945a..11cc980 100644 (file)
@@ -39,6 +39,7 @@
 #include "tda9887.h"
 #include "xc5000.h"
 #include "tda18271.h"
+#include "xc4000.h"
 
 #define UNSET (-1U)
 
@@ -391,6 +392,23 @@ static void set_type(struct i2c_client *c, unsigned int type,
                tune_now = 0;
                break;
        }
+       case TUNER_XC4000:
+       {
+               struct xc4000_config xc4000_cfg = {
+                       .i2c_address      = t->i2c->addr,
+                       /* FIXME: the correct parameters will be set */
+                       /* only when the digital dvb_attach() occurs */
+                       .default_pm       = 0,
+                       .dvb_amplitude    = 0,
+                       .set_smoothedcvbs = 0,
+                       .if_khz           = 0
+               };
+               if (!dvb_attach(xc4000_attach,
+                               &t->fe, t->i2c->adapter, &xc4000_cfg))
+                       goto attach_failed;
+               tune_now = 0;
+               break;
+       }
        default:
                if (!dvb_attach(simple_tuner_attach, &t->fe,
                                t->i2c->adapter, t->i2c->addr, t->type))
index 0347bbe..742482e 100644 (file)
@@ -552,16 +552,6 @@ static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
        return ret;
 }
 
-static int tw9910_enum_input(struct soc_camera_device *icd,
-                            struct v4l2_input *inp)
-{
-       inp->type = V4L2_INPUT_TYPE_TUNER;
-       inp->std  = V4L2_STD_UNKNOWN;
-       strcpy(inp->name, "Video");
-
-       return 0;
-}
-
 static int tw9910_g_chip_ident(struct v4l2_subdev *sd,
                               struct v4l2_dbg_chip_ident *id)
 {
@@ -846,13 +836,9 @@ static int tw9910_video_probe(struct soc_camera_device *icd,
        struct tw9910_priv *priv = to_tw9910(client);
        s32 id;
 
-       /*
-        * We must have a parent by now. And it cannot be a wrong one.
-        * So this entire test is completely redundant.
-        */
-       if (!icd->dev.parent ||
-           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
-               return -ENODEV;
+       /* We must have a parent by now. And it cannot be a wrong one. */
+       BUG_ON(!icd->parent ||
+              to_soc_camera_host(icd->parent)->nr != icd->iface);
 
        /*
         * tw9910 only use 8 or 16 bit bus width
@@ -891,7 +877,6 @@ static int tw9910_video_probe(struct soc_camera_device *icd,
 static struct soc_camera_ops tw9910_ops = {
        .set_bus_param          = tw9910_set_bus_param,
        .query_bus_param        = tw9910_query_bus_param,
-       .enum_input             = tw9910_enum_input,
 };
 
 static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
index ea8ea8a..5a74f5e 100644 (file)
@@ -45,7 +45,6 @@
  *
  */
 
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/timer.h>
 #define DRIVER_ALIAS "USBVision"
 #define DRIVER_DESC "USBVision USB Video Device Driver for Linux"
 #define DRIVER_LICENSE "GPL"
-#define USBVISION_DRIVER_VERSION_MAJOR 0
-#define USBVISION_DRIVER_VERSION_MINOR 9
-#define USBVISION_DRIVER_VERSION_PATCHLEVEL 10
-#define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,\
-USBVISION_DRIVER_VERSION_MINOR,\
-USBVISION_DRIVER_VERSION_PATCHLEVEL)
-#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) \
-"." __stringify(USBVISION_DRIVER_VERSION_MINOR) \
-"." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL)
+#define USBVISION_VERSION_STRING "0.9.11"
 
 #define        ENABLE_HEXDUMP  0       /* Enable if you need it */
 
@@ -516,7 +507,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
                usbvision_device_data[usbvision->dev_model].model_string,
                sizeof(vc->card));
        usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info));
-       vc->version = USBVISION_DRIVER_VERSION;
        vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_AUDIO |
                V4L2_CAP_READWRITE |
index 2c8954e..10c2364 100644 (file)
@@ -1664,8 +1664,8 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
                return -EINVAL;
        }
 
-       /* Search for the matching (GUID/CS) control in the given device */
-       list_for_each_entry(entity, &dev->entities, list) {
+       /* Search for the matching (GUID/CS) control on the current chain */
+       list_for_each_entry(entity, &chain->entities, chain) {
                unsigned int i;
 
                if (UVC_ENTITY_TYPE(entity) != UVC_VC_EXTENSION_UNIT ||
index b6eae48..d29f9c2 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
+#include <linux/version.h>
 #include <asm/atomic.h>
 #include <asm/unaligned.h>
 
@@ -1857,7 +1858,7 @@ static int uvc_probe(struct usb_interface *intf,
                        sizeof(dev->mdev.serial));
        strcpy(dev->mdev.bus_info, udev->devpath);
        dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
-       dev->mdev.driver_version = DRIVER_VERSION_NUMBER;
+       dev->mdev.driver_version = LINUX_VERSION_CODE;
        if (media_device_register(&dev->mdev) < 0)
                goto error;
 
@@ -2130,6 +2131,15 @@ static struct usb_device_id uvc_ids[] = {
          .bInterfaceProtocol   = 0,
          .driver_info          = UVC_QUIRK_PROBE_MINMAX
                                | UVC_QUIRK_BUILTIN_ISIGHT },
+       /* Foxlink ("HP Webcam" on HP Mini 5103) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x05c8,
+         .idProduct            = 0x0403,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
        /* Genesys Logic USB 2.0 PC Camera */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
index dde6533..ea71d5f 100644 (file)
@@ -83,7 +83,7 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
        default:
                uvc_trace(UVC_TRACE_CONTROL, "Unsupported V4L2 control type "
                          "%u.\n", xmap->v4l2_type);
-               ret = -EINVAL;
+               ret = -ENOTTY;
                goto done;
        }
 
@@ -571,7 +571,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                strlcpy(cap->card, vdev->name, sizeof cap->card);
                usb_make_path(stream->dev->udev,
                              cap->bus_info, sizeof(cap->bus_info));
-               cap->version = DRIVER_VERSION_NUMBER;
+               cap->version = LINUX_VERSION_CODE;
                if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
                        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
                                          | V4L2_CAP_STREAMING;
index 20107fd..df32a43 100644 (file)
@@ -183,8 +183,7 @@ struct uvc_xu_control {
  * Driver specific constants.
  */
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(1, 1, 0)
-#define DRIVER_VERSION         "v1.1.0"
+#define DRIVER_VERSION         "1.1.1"
 
 /* Number of isochronous URBs. */
 #define UVC_URBS               5
index 06b9f9f..5c6100f 100644 (file)
@@ -105,6 +105,9 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
                    menu_items[ctrl->value][0] == '\0')
                        return -EINVAL;
        }
+       if (qctrl->type == V4L2_CTRL_TYPE_BITMASK &&
+                       (ctrl->value & ~qctrl->maximum))
+               return -ERANGE;
        return 0;
 }
 EXPORT_SYMBOL(v4l2_ctrl_check);
index 7c26947..61979b7 100644 (file)
@@ -662,6 +662,32 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
        return 0;
 }
 
+struct v4l2_event32 {
+       __u32                           type;
+       union {
+               __u8                    data[64];
+       } u;
+       __u32                           pending;
+       __u32                           sequence;
+       struct compat_timespec          timestamp;
+       __u32                           id;
+       __u32                           reserved[8];
+};
+
+static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up)
+{
+       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) ||
+               put_user(kp->type, &up->type) ||
+               copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
+               put_user(kp->pending, &up->pending) ||
+               put_user(kp->sequence, &up->sequence) ||
+               put_compat_timespec(&kp->timestamp, &up->timestamp) ||
+               put_user(kp->id, &up->id) ||
+               copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
+                       return -EFAULT;
+       return 0;
+}
+
 #define VIDIOC_G_FMT32         _IOWR('V',  4, struct v4l2_format32)
 #define VIDIOC_S_FMT32         _IOWR('V',  5, struct v4l2_format32)
 #define VIDIOC_QUERYBUF32      _IOWR('V',  9, struct v4l2_buffer32)
@@ -675,6 +701,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
 #define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
+#define        VIDIOC_DQEVENT32        _IOR ('V', 89, struct v4l2_event32)
 
 #define VIDIOC_OVERLAY32       _IOW ('V', 14, s32)
 #define VIDIOC_STREAMON32      _IOW ('V', 18, s32)
@@ -693,6 +720,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                struct v4l2_input v2i;
                struct v4l2_standard v2s;
                struct v4l2_ext_controls v2ecs;
+               struct v4l2_event v2ev;
                unsigned long vx;
                int vi;
        } karg;
@@ -715,6 +743,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
        case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break;
        case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
        case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
+       case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break;
        case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
        case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
        case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
@@ -778,6 +807,9 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                err = get_v4l2_ext_controls32(&karg.v2ecs, up);
                compatible_arg = 0;
                break;
+       case VIDIOC_DQEVENT:
+               compatible_arg = 0;
+               break;
        }
        if (err)
                return err;
@@ -818,6 +850,10 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                err = put_v4l2_framebuffer32(&karg.v2fb, up);
                break;
 
+       case VIDIOC_DQEVENT:
+               err = put_v4l2_event32(&karg.v2ev, up);
+               break;
+
        case VIDIOC_G_FMT:
        case VIDIOC_S_FMT:
        case VIDIOC_TRY_FMT:
@@ -920,6 +956,7 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case VIDIOC_S_DV_TIMINGS:
        case VIDIOC_G_DV_TIMINGS:
        case VIDIOC_DQEVENT:
+       case VIDIOC_DQEVENT32:
        case VIDIOC_SUBSCRIBE_EVENT:
        case VIDIOC_UNSUBSCRIBE_EVENT:
                ret = do_video_ioctl(file, cmd, arg);
index 2412f08..06b6014 100644 (file)
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
 #include <media/v4l2-dev.h>
 
+#define has_op(master, op) \
+       (master->ops && master->ops->op)
+#define call_op(master, op) \
+       (has_op(master, op) ? master->ops->op(master) : 0)
+
 /* Internal temporary helper struct, one for each v4l2_ext_control */
-struct ctrl_helper {
+struct v4l2_ctrl_helper {
+       /* Pointer to the control reference of the master control */
+       struct v4l2_ctrl_ref *mref;
        /* The control corresponding to the v4l2_ext_control ID field. */
        struct v4l2_ctrl *ctrl;
-       /* Used internally to mark whether this control was already
-          processed. */
-       bool handled;
+       /* v4l2_ext_control index of the next control belonging to the
+          same cluster, or 0 if there isn't any. */
+       u32 next;
 };
 
+/* Small helper function to determine if the autocluster is set to manual
+   mode. In that case the is_volatile flag should be ignored. */
+static bool is_cur_manual(const struct v4l2_ctrl *master)
+{
+       return master->is_auto && master->cur.val == master->manual_mode_value;
+}
+
+/* Same as above, but this checks the against the new value instead of the
+   current value. */
+static bool is_new_manual(const struct v4l2_ctrl *master)
+{
+       return master->is_auto && master->val == master->manual_mode_value;
+}
+
 /* Returns NULL or a character pointer array containing the menu for
    the given control ID. The pointer array ends with a NULL pointer.
    An empty string signifies a menu entry that is invalid. This allows
@@ -181,7 +203,7 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
        };
        static const char * const mpeg_stream_vbi_fmt[] = {
                "No VBI",
-               "Private packet, IVTV format",
+               "Private Packet, IVTV Format",
                NULL
        };
        static const char * const camera_power_line_frequency[] = {
@@ -204,18 +226,130 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
                "Negative",
                "Emboss",
                "Sketch",
-               "Sky blue",
-               "Grass green",
-               "Skin whiten",
+               "Sky Blue",
+               "Grass Green",
+               "Skin Whiten",
                "Vivid",
                NULL
        };
        static const char * const tune_preemphasis[] = {
-               "No preemphasis",
+               "No Preemphasis",
                "50 useconds",
                "75 useconds",
                NULL,
        };
+       static const char * const header_mode[] = {
+               "Separate Buffer",
+               "Joined With 1st Frame",
+               NULL,
+       };
+       static const char * const multi_slice[] = {
+               "Single",
+               "Max Macroblocks",
+               "Max Bytes",
+               NULL,
+       };
+       static const char * const entropy_mode[] = {
+               "CAVLC",
+               "CABAC",
+               NULL,
+       };
+       static const char * const mpeg_h264_level[] = {
+               "1",
+               "1b",
+               "1.1",
+               "1.2",
+               "1.3",
+               "2",
+               "2.1",
+               "2.2",
+               "3",
+               "3.1",
+               "3.2",
+               "4",
+               "4.1",
+               "4.2",
+               "5",
+               "5.1",
+               NULL,
+       };
+       static const char * const h264_loop_filter[] = {
+               "Enabled",
+               "Disabled",
+               "Disabled at Slice Boundary",
+               NULL,
+       };
+       static const char * const h264_profile[] = {
+               "Baseline",
+               "Constrained Baseline",
+               "Main",
+               "Extended",
+               "High",
+               "High 10",
+               "High 422",
+               "High 444 Predictive",
+               "High 10 Intra",
+               "High 422 Intra",
+               "High 444 Intra",
+               "CAVLC 444 Intra",
+               "Scalable Baseline",
+               "Scalable High",
+               "Scalable High Intra",
+               "Multiview High",
+               NULL,
+       };
+       static const char * const vui_sar_idc[] = {
+               "Unspecified",
+               "1:1",
+               "12:11",
+               "10:11",
+               "16:11",
+               "40:33",
+               "24:11",
+               "20:11",
+               "32:11",
+               "80:33",
+               "18:11",
+               "15:11",
+               "64:33",
+               "160:99",
+               "4:3",
+               "3:2",
+               "2:1",
+               "Extended SAR",
+               NULL,
+       };
+       static const char * const mpeg_mpeg4_level[] = {
+               "0",
+               "0b",
+               "1",
+               "2",
+               "3",
+               "3b",
+               "4",
+               "5",
+               NULL,
+       };
+       static const char * const mpeg4_profile[] = {
+               "Simple",
+               "Adcanved Simple",
+               "Core",
+               "Simple Scalable",
+               "Advanced Coding Efficency",
+               NULL,
+       };
+
+       static const char * const flash_led_mode[] = {
+               "Off",
+               "Flash",
+               "Torch",
+               NULL,
+       };
+       static const char * const flash_strobe_source[] = {
+               "Software",
+               "External",
+               NULL,
+       };
 
        switch (id) {
        case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
@@ -256,6 +390,28 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
                return colorfx;
        case V4L2_CID_TUNE_PREEMPHASIS:
                return tune_preemphasis;
+       case V4L2_CID_FLASH_LED_MODE:
+               return flash_led_mode;
+       case V4L2_CID_FLASH_STROBE_SOURCE:
+               return flash_strobe_source;
+       case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+               return header_mode;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
+               return multi_slice;
+       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+               return entropy_mode;
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+               return mpeg_h264_level;
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
+               return h264_loop_filter;
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+               return h264_profile;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
+               return vui_sar_idc;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+               return mpeg_mpeg4_level;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
+               return mpeg4_profile;
        default:
                return NULL;
        }
@@ -307,6 +463,8 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_CHROMA_GAIN:              return "Chroma Gain";
        case V4L2_CID_ILLUMINATORS_1:           return "Illuminator 1";
        case V4L2_CID_ILLUMINATORS_2:           return "Illuminator 2";
+       case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:  return "Minimum Number of Capture Buffers";
+       case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:   return "Minimum Number of Output Buffers";
 
        /* MPEG controls */
        /* Keep the order of the 'case's the same as in videodev2.h! */
@@ -343,6 +501,48 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation";
        case V4L2_CID_MPEG_VIDEO_MUTE:          return "Video Mute";
        case V4L2_CID_MPEG_VIDEO_MUTE_YUV:      return "Video Mute YUV";
+       case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:       return "Decoder Slice Interface";
+       case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:  return "MPEG4 Loop Filter Enable";
+       case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:       return "The Number of Intra Refresh MBs";
+       case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:               return "Frame Level Rate Control Enable";
+       case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:                  return "H264 MB Level Rate Control";
+       case V4L2_CID_MPEG_VIDEO_HEADER_MODE:                   return "Sequence Header Mode";
+       case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC:                   return "The Max Number of Reference Picture";
+       case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:               return "H263 I-Frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:               return "H263 P frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:               return "H263 B frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:                   return "H263 Minimum QP Value";
+       case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:                   return "H263 Maximum QP Value";
+       case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:               return "H264 I-Frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:               return "H264 P frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:               return "H264 B frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:                   return "H264 Maximum QP Value";
+       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:                   return "H264 Minimum QP Value";
+       case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:            return "H264 8x8 Transform Enable";
+       case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE:                 return "H264 CPB Buffer Size";
+       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:             return "H264 Entorpy Mode";
+       case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:                 return "H264 I Period";
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:                    return "H264 Level";
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:        return "H264 Loop Filter Alpha Offset";
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:         return "H264 Loop Filter Beta Offset";
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:         return "H264 Loop Filter Mode";
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:                  return "H264 Profile";
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:       return "Vertical Size of SAR";
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:        return "Horizontal Size of SAR";
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:           return "Aspect Ratio VUI Enable";
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:              return "VUI Aspect Ratio IDC";
+       case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:              return "MPEG4 I-Frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:              return "MPEG4 P frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:              return "MPEG4 B frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:                  return "MPEG4 Minimum QP Value";
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:                  return "MPEG4 Maximum QP Value";
+       case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:                   return "MPEG4 Level";
+       case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:                 return "MPEG4 Profile";
+       case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:                    return "Quarter Pixel Search Enable";
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:         return "The Maximum Bytes Per Slice";
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:            return "The Number of MB in a Slice";
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:              return "The Slice Partitioning Method";
+       case V4L2_CID_MPEG_VIDEO_VBV_SIZE:                      return "VBV Buffer Size";
 
        /* CAMERA controls */
        /* Keep the order of the 'case's the same as in videodev2.h! */
@@ -389,6 +589,21 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_TUNE_POWER_LEVEL:         return "Tune Power Level";
        case V4L2_CID_TUNE_ANTENNA_CAPACITOR:   return "Tune Antenna Capacitor";
 
+       /* Flash controls */
+       case V4L2_CID_FLASH_CLASS:              return "Flash controls";
+       case V4L2_CID_FLASH_LED_MODE:           return "LED mode";
+       case V4L2_CID_FLASH_STROBE_SOURCE:      return "Strobe source";
+       case V4L2_CID_FLASH_STROBE:             return "Strobe";
+       case V4L2_CID_FLASH_STROBE_STOP:        return "Stop strobe";
+       case V4L2_CID_FLASH_STROBE_STATUS:      return "Strobe status";
+       case V4L2_CID_FLASH_TIMEOUT:            return "Strobe timeout";
+       case V4L2_CID_FLASH_INTENSITY:          return "Intensity, flash mode";
+       case V4L2_CID_FLASH_TORCH_INTENSITY:    return "Intensity, torch mode";
+       case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, indicator";
+       case V4L2_CID_FLASH_FAULT:              return "Faults";
+       case V4L2_CID_FLASH_CHARGE:             return "Charge";
+       case V4L2_CID_FLASH_READY:              return "Ready to strobe";
+
        default:
                return NULL;
        }
@@ -423,12 +638,24 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_PILOT_TONE_ENABLED:
        case V4L2_CID_ILLUMINATORS_1:
        case V4L2_CID_ILLUMINATORS_2:
+       case V4L2_CID_FLASH_STROBE_STATUS:
+       case V4L2_CID_FLASH_CHARGE:
+       case V4L2_CID_FLASH_READY:
+       case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
+       case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
+       case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
+       case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
+       case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
+       case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
                *type = V4L2_CTRL_TYPE_BOOLEAN;
                *min = 0;
                *max = *step = 1;
                break;
        case V4L2_CID_PAN_RESET:
        case V4L2_CID_TILT_RESET:
+       case V4L2_CID_FLASH_STROBE:
+       case V4L2_CID_FLASH_STROBE_STOP:
                *type = V4L2_CTRL_TYPE_BUTTON;
                *flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
                *min = *max = *step = *def = 0;
@@ -452,6 +679,17 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_EXPOSURE_AUTO:
        case V4L2_CID_COLORFX:
        case V4L2_CID_TUNE_PREEMPHASIS:
+       case V4L2_CID_FLASH_LED_MODE:
+       case V4L2_CID_FLASH_STROBE_SOURCE:
+       case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
+       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
+       case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+       case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
                *type = V4L2_CTRL_TYPE_MENU;
                break;
        case V4L2_CID_RDS_TX_PS_NAME:
@@ -462,6 +700,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_CAMERA_CLASS:
        case V4L2_CID_MPEG_CLASS:
        case V4L2_CID_FM_TX_CLASS:
+       case V4L2_CID_FLASH_CLASS:
                *type = V4L2_CTRL_TYPE_CTRL_CLASS;
                /* You can neither read not write these */
                *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY;
@@ -474,6 +713,14 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
                /* Max is calculated as RGB888 that is 2^24 */
                *max = 0xFFFFFF;
                break;
+       case V4L2_CID_FLASH_FAULT:
+               *type = V4L2_CTRL_TYPE_BITMASK;
+               break;
+       case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+       case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
+               *type = V4L2_CTRL_TYPE_INTEGER;
+               *flags |= V4L2_CTRL_FLAG_READ_ONLY;
+               break;
        default:
                *type = V4L2_CTRL_TYPE_INTEGER;
                break;
@@ -519,6 +766,10 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_ZOOM_RELATIVE:
                *flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
                break;
+       case V4L2_CID_FLASH_STROBE_STATUS:
+       case V4L2_CID_FLASH_READY:
+               *flags |= V4L2_CTRL_FLAG_READ_ONLY;
+               break;
        }
 }
 EXPORT_SYMBOL(v4l2_ctrl_fill);
@@ -537,6 +788,42 @@ static bool type_is_int(const struct v4l2_ctrl *ctrl)
        }
 }
 
+static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes)
+{
+       memset(ev->reserved, 0, sizeof(ev->reserved));
+       ev->type = V4L2_EVENT_CTRL;
+       ev->id = ctrl->id;
+       ev->u.ctrl.changes = changes;
+       ev->u.ctrl.type = ctrl->type;
+       ev->u.ctrl.flags = ctrl->flags;
+       if (ctrl->type == V4L2_CTRL_TYPE_STRING)
+               ev->u.ctrl.value64 = 0;
+       else
+               ev->u.ctrl.value64 = ctrl->cur.val64;
+       ev->u.ctrl.minimum = ctrl->minimum;
+       ev->u.ctrl.maximum = ctrl->maximum;
+       if (ctrl->type == V4L2_CTRL_TYPE_MENU)
+               ev->u.ctrl.step = 1;
+       else
+               ev->u.ctrl.step = ctrl->step;
+       ev->u.ctrl.default_value = ctrl->default_value;
+}
+
+static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes)
+{
+       struct v4l2_event ev;
+       struct v4l2_subscribed_event *sev;
+
+       if (list_empty(&ctrl->ev_subs))
+               return;
+       fill_event(&ev, ctrl, changes);
+
+       list_for_each_entry(sev, &ctrl->ev_subs, node)
+               if (sev->fh && (sev->fh != fh ||
+                               (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)))
+                       v4l2_event_queue_fh(sev->fh, &ev);
+}
+
 /* Helper function: copy the current control value back to the caller */
 static int cur_to_user(struct v4l2_ext_control *c,
                       struct v4l2_ctrl *ctrl)
@@ -624,22 +911,45 @@ static int new_to_user(struct v4l2_ext_control *c,
 }
 
 /* Copy the new value to the current value. */
-static void new_to_cur(struct v4l2_ctrl *ctrl)
+static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
+                                               bool update_inactive)
 {
+       bool changed = false;
+
        if (ctrl == NULL)
                return;
        switch (ctrl->type) {
+       case V4L2_CTRL_TYPE_BUTTON:
+               changed = true;
+               break;
        case V4L2_CTRL_TYPE_STRING:
                /* strings are always 0-terminated */
+               changed = strcmp(ctrl->string, ctrl->cur.string);
                strcpy(ctrl->cur.string, ctrl->string);
                break;
        case V4L2_CTRL_TYPE_INTEGER64:
+               changed = ctrl->val64 != ctrl->cur.val64;
                ctrl->cur.val64 = ctrl->val64;
                break;
        default:
+               changed = ctrl->val != ctrl->cur.val;
                ctrl->cur.val = ctrl->val;
                break;
        }
+       if (update_inactive) {
+               ctrl->flags &= ~V4L2_CTRL_FLAG_INACTIVE;
+               if (!is_cur_manual(ctrl->cluster[0]))
+                       ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+       }
+       if (changed || update_inactive) {
+               /* If a control was changed that was not one of the controls
+                  modified by the application, then send the event to all. */
+               if (!ctrl->is_new)
+                       fh = NULL;
+               send_event(fh, ctrl,
+                       (changed ? V4L2_EVENT_CTRL_CH_VALUE : 0) |
+                       (update_inactive ? V4L2_EVENT_CTRL_CH_FLAGS : 0));
+       }
 }
 
 /* Copy the current value to the new value */
@@ -692,13 +1002,11 @@ static int cluster_changed(struct v4l2_ctrl *master)
        return diff;
 }
 
-/* Validate a new control */
-static int validate_new(struct v4l2_ctrl *ctrl)
+/* Validate integer-type control */
+static int validate_new_int(const struct v4l2_ctrl *ctrl, s32 *pval)
 {
-       s32 val = ctrl->val;
-       char *s = ctrl->string;
+       s32 val = *pval;
        u32 offset;
-       size_t len;
 
        switch (ctrl->type) {
        case V4L2_CTRL_TYPE_INTEGER:
@@ -711,11 +1019,11 @@ static int validate_new(struct v4l2_ctrl *ctrl)
                offset = val - ctrl->minimum;
                offset = ctrl->step * (offset / ctrl->step);
                val = ctrl->minimum + offset;
-               ctrl->val = val;
+               *pval = val;
                return 0;
 
        case V4L2_CTRL_TYPE_BOOLEAN:
-               ctrl->val = !!ctrl->val;
+               *pval = !!val;
                return 0;
 
        case V4L2_CTRL_TYPE_MENU:
@@ -726,11 +1034,35 @@ static int validate_new(struct v4l2_ctrl *ctrl)
                        return -EINVAL;
                return 0;
 
+       case V4L2_CTRL_TYPE_BITMASK:
+               *pval &= ctrl->maximum;
+               return 0;
+
        case V4L2_CTRL_TYPE_BUTTON:
        case V4L2_CTRL_TYPE_CTRL_CLASS:
-               ctrl->val64 = 0;
+               *pval = 0;
                return 0;
 
+       default:
+               return -EINVAL;
+       }
+}
+
+/* Validate a new control */
+static int validate_new(const struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
+{
+       char *s = c->string;
+       size_t len;
+
+       switch (ctrl->type) {
+       case V4L2_CTRL_TYPE_INTEGER:
+       case V4L2_CTRL_TYPE_BOOLEAN:
+       case V4L2_CTRL_TYPE_MENU:
+       case V4L2_CTRL_TYPE_BITMASK:
+       case V4L2_CTRL_TYPE_BUTTON:
+       case V4L2_CTRL_TYPE_CTRL_CLASS:
+               return validate_new_int(ctrl, &c->value);
+
        case V4L2_CTRL_TYPE_INTEGER64:
                return 0;
 
@@ -780,6 +1112,7 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
 {
        struct v4l2_ctrl_ref *ref, *next_ref;
        struct v4l2_ctrl *ctrl, *next_ctrl;
+       struct v4l2_subscribed_event *sev, *next_sev;
 
        if (hdl == NULL || hdl->buckets == NULL)
                return;
@@ -793,6 +1126,8 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
        /* Free all controls owned by the handler */
        list_for_each_entry_safe(ctrl, next_ctrl, &hdl->ctrls, node) {
                list_del(&ctrl->node);
+               list_for_each_entry_safe(sev, next_sev, &ctrl->ev_subs, node)
+                       list_del(&sev->node);
                kfree(ctrl);
        }
        kfree(hdl->buckets);
@@ -962,13 +1297,17 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 
        /* Sanity checks */
        if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE ||
-           max < min ||
            (type == V4L2_CTRL_TYPE_INTEGER && step == 0) ||
+           (type == V4L2_CTRL_TYPE_BITMASK && max == 0) ||
            (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
            (type == V4L2_CTRL_TYPE_STRING && max == 0)) {
                handler_set_err(hdl, -ERANGE);
                return NULL;
        }
+       if (type != V4L2_CTRL_TYPE_BITMASK && max < min) {
+               handler_set_err(hdl, -ERANGE);
+               return NULL;
+       }
        if ((type == V4L2_CTRL_TYPE_INTEGER ||
             type == V4L2_CTRL_TYPE_MENU ||
             type == V4L2_CTRL_TYPE_BOOLEAN) &&
@@ -976,6 +1315,10 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
                handler_set_err(hdl, -ERANGE);
                return NULL;
        }
+       if (type == V4L2_CTRL_TYPE_BITMASK && ((def & ~max) || min || step)) {
+               handler_set_err(hdl, -ERANGE);
+               return NULL;
+       }
 
        if (type == V4L2_CTRL_TYPE_BUTTON)
                flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
@@ -991,6 +1334,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
        }
 
        INIT_LIST_HEAD(&ctrl->node);
+       INIT_LIST_HEAD(&ctrl->ev_subs);
        ctrl->handler = hdl;
        ctrl->ops = ops;
        ctrl->id = id;
@@ -1132,6 +1476,9 @@ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
                /* Skip handler-private controls. */
                if (ctrl->is_private)
                        continue;
+               /* And control classes */
+               if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
+                       continue;
                ret = handler_new_ref(hdl, ctrl);
                if (ret)
                        break;
@@ -1147,7 +1494,7 @@ void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
        int i;
 
        /* The first control is the master control and it must not be NULL */
-       BUG_ON(controls[0] == NULL);
+       BUG_ON(ncontrols == 0 || controls[0] == NULL);
 
        for (i = 0; i < ncontrols; i++) {
                if (controls[i]) {
@@ -1158,18 +1505,47 @@ void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
 }
 EXPORT_SYMBOL(v4l2_ctrl_cluster);
 
+void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
+                           u8 manual_val, bool set_volatile)
+{
+       struct v4l2_ctrl *master = controls[0];
+       u32 flag;
+       int i;
+
+       v4l2_ctrl_cluster(ncontrols, controls);
+       WARN_ON(ncontrols <= 1);
+       WARN_ON(manual_val < master->minimum || manual_val > master->maximum);
+       master->is_auto = true;
+       master->manual_mode_value = manual_val;
+       master->flags |= V4L2_CTRL_FLAG_UPDATE;
+       flag = is_cur_manual(master) ? 0 : V4L2_CTRL_FLAG_INACTIVE;
+
+       for (i = 1; i < ncontrols; i++)
+               if (controls[i]) {
+                       controls[i]->is_volatile = set_volatile;
+                       controls[i]->flags |= flag;
+               }
+}
+EXPORT_SYMBOL(v4l2_ctrl_auto_cluster);
+
 /* Activate/deactivate a control. */
 void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active)
 {
+       /* invert since the actual flag is called 'inactive' */
+       bool inactive = !active;
+       bool old;
+
        if (ctrl == NULL)
                return;
 
-       if (!active)
+       if (inactive)
                /* set V4L2_CTRL_FLAG_INACTIVE */
-               set_bit(4, &ctrl->flags);
+               old = test_and_set_bit(4, &ctrl->flags);
        else
                /* clear V4L2_CTRL_FLAG_INACTIVE */
-               clear_bit(4, &ctrl->flags);
+               old = test_and_clear_bit(4, &ctrl->flags);
+       if (old != inactive)
+               send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_FLAGS);
 }
 EXPORT_SYMBOL(v4l2_ctrl_activate);
 
@@ -1181,15 +1557,21 @@ EXPORT_SYMBOL(v4l2_ctrl_activate);
    these controls. */
 void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed)
 {
+       bool old;
+
        if (ctrl == NULL)
                return;
 
+       v4l2_ctrl_lock(ctrl);
        if (grabbed)
                /* set V4L2_CTRL_FLAG_GRABBED */
-               set_bit(1, &ctrl->flags);
+               old = test_and_set_bit(1, &ctrl->flags);
        else
                /* clear V4L2_CTRL_FLAG_GRABBED */
-               clear_bit(1, &ctrl->flags);
+               old = test_and_clear_bit(1, &ctrl->flags);
+       if (old != grabbed)
+               send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_FLAGS);
+       v4l2_ctrl_unlock(ctrl);
 }
 EXPORT_SYMBOL(v4l2_ctrl_grab);
 
@@ -1217,6 +1599,9 @@ static void log_ctrl(const struct v4l2_ctrl *ctrl,
        case V4L2_CTRL_TYPE_MENU:
                printk(KERN_CONT "%s", ctrl->qmenu[ctrl->cur.val]);
                break;
+       case V4L2_CTRL_TYPE_BITMASK:
+               printk(KERN_CONT "0x%08x", ctrl->cur.val);
+               break;
        case V4L2_CTRL_TYPE_INTEGER64:
                printk(KERN_CONT "%lld", ctrl->cur.val64);
                break;
@@ -1277,26 +1662,21 @@ int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)
                int i;
 
                /* Skip if this control was already handled by a cluster. */
-               if (ctrl->done)
+               /* Skip button controls and read-only controls. */
+               if (ctrl->done || ctrl->type == V4L2_CTRL_TYPE_BUTTON ||
+                   (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY))
                        continue;
 
                for (i = 0; i < master->ncontrols; i++) {
                        if (master->cluster[i]) {
                                cur_to_new(master->cluster[i]);
                                master->cluster[i]->is_new = 1;
+                               master->cluster[i]->done = true;
                        }
                }
-
-               /* Skip button controls and read-only controls. */
-               if (ctrl->type == V4L2_CTRL_TYPE_BUTTON ||
-                   (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY))
-                       continue;
-               ret = master->ops->s_ctrl(master);
+               ret = call_op(master, s_ctrl);
                if (ret)
                        break;
-               for (i = 0; i < master->ncontrols; i++)
-                       if (master->cluster[i])
-                               master->cluster[i]->done = true;
        }
        mutex_unlock(&hdl->lock);
        return ret;
@@ -1447,18 +1827,19 @@ EXPORT_SYMBOL(v4l2_subdev_querymenu);
    Find the controls in the control array and do some basic checks. */
 static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
                             struct v4l2_ext_controls *cs,
-                            struct ctrl_helper *helpers,
-                            bool try)
+                            struct v4l2_ctrl_helper *helpers)
 {
+       struct v4l2_ctrl_helper *h;
+       bool have_clusters = false;
        u32 i;
 
-       for (i = 0; i < cs->count; i++) {
+       for (i = 0, h = helpers; i < cs->count; i++, h++) {
                struct v4l2_ext_control *c = &cs->controls[i];
+               struct v4l2_ctrl_ref *ref;
                struct v4l2_ctrl *ctrl;
                u32 id = c->id & V4L2_CTRL_ID_MASK;
 
-               if (try)
-                       cs->error_idx = i;
+               cs->error_idx = i;
 
                if (cs->ctrl_class && V4L2_CTRL_ID2CLASS(id) != cs->ctrl_class)
                        return -EINVAL;
@@ -1467,53 +1848,59 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
                   extended controls */
                if (id >= V4L2_CID_PRIVATE_BASE)
                        return -EINVAL;
-               ctrl = v4l2_ctrl_find(hdl, id);
-               if (ctrl == NULL)
+               ref = find_ref_lock(hdl, id);
+               if (ref == NULL)
                        return -EINVAL;
+               ctrl = ref->ctrl;
                if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED)
                        return -EINVAL;
 
-               helpers[i].ctrl = ctrl;
-               helpers[i].handled = false;
+               if (ctrl->cluster[0]->ncontrols > 1)
+                       have_clusters = true;
+               if (ctrl->cluster[0] != ctrl)
+                       ref = find_ref_lock(hdl, ctrl->cluster[0]->id);
+               /* Store the ref to the master control of the cluster */
+               h->mref = ref;
+               h->ctrl = ctrl;
+               /* Initially set next to 0, meaning that there is no other
+                  control in this helper array belonging to the same
+                  cluster */
+               h->next = 0;
        }
-       return 0;
-}
 
-typedef int (*cluster_func)(struct v4l2_ext_control *c,
-                           struct v4l2_ctrl *ctrl);
+       /* We are done if there were no controls that belong to a multi-
+          control cluster. */
+       if (!have_clusters)
+               return 0;
 
-/* Walk over all controls in v4l2_ext_controls belonging to the same cluster
-   and call the provided function. */
-static int cluster_walk(unsigned from,
-                       struct v4l2_ext_controls *cs,
-                       struct ctrl_helper *helpers,
-                       cluster_func f)
-{
-       struct v4l2_ctrl **cluster = helpers[from].ctrl->cluster;
-       int ret = 0;
-       int i;
+       /* The code below figures out in O(n) time which controls in the list
+          belong to the same cluster. */
 
-       /* Find any controls from the same cluster and call the function */
-       for (i = from; !ret && i < cs->count; i++) {
-               struct v4l2_ctrl *ctrl = helpers[i].ctrl;
+       /* This has to be done with the handler lock taken. */
+       mutex_lock(&hdl->lock);
 
-               if (!helpers[i].handled && ctrl->cluster == cluster)
-                       ret = f(&cs->controls[i], ctrl);
+       /* First zero the helper field in the master control references */
+       for (i = 0; i < cs->count; i++)
+               helpers[i].mref->helper = 0;
+       for (i = 0, h = helpers; i < cs->count; i++, h++) {
+               struct v4l2_ctrl_ref *mref = h->mref;
+
+               /* If the mref->helper is set, then it points to an earlier
+                  helper that belongs to the same cluster. */
+               if (mref->helper) {
+                       /* Set the next field of mref->helper to the current
+                          index: this means that that earlier helper now
+                          points to the next helper in the same cluster. */
+                       mref->helper->next = i;
+                       /* mref should be set only for the first helper in the
+                          cluster, clear the others. */
+                       h->mref = NULL;
+               }
+               /* Point the mref helper to the current helper struct. */
+               mref->helper = h;
        }
-       return ret;
-}
-
-static void cluster_done(unsigned from,
-                        struct v4l2_ext_controls *cs,
-                        struct ctrl_helper *helpers)
-{
-       struct v4l2_ctrl **cluster = helpers[from].ctrl->cluster;
-       int i;
-
-       /* Find any controls from the same cluster and mark them as handled */
-       for (i = from; i < cs->count; i++)
-               if (helpers[i].ctrl->cluster == cluster)
-                       helpers[i].handled = true;
+       mutex_unlock(&hdl->lock);
+       return 0;
 }
 
 /* Handles the corner case where cs->count == 0. It checks whether the
@@ -1531,10 +1918,10 @@ static int class_check(struct v4l2_ctrl_handler *hdl, u32 ctrl_class)
 /* Get extended controls. Allocates the helpers array if needed. */
 int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs)
 {
-       struct ctrl_helper helper[4];
-       struct ctrl_helper *helpers = helper;
+       struct v4l2_ctrl_helper helper[4];
+       struct v4l2_ctrl_helper *helpers = helper;
        int ret;
-       int i;
+       int i, j;
 
        cs->error_idx = cs->count;
        cs->ctrl_class = V4L2_CTRL_ID2CLASS(cs->ctrl_class);
@@ -1551,30 +1938,46 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs
                        return -ENOMEM;
        }
 
-       ret = prepare_ext_ctrls(hdl, cs, helpers, false);
+       ret = prepare_ext_ctrls(hdl, cs, helpers);
+       cs->error_idx = cs->count;
 
        for (i = 0; !ret && i < cs->count; i++)
                if (helpers[i].ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
                        ret = -EACCES;
 
        for (i = 0; !ret && i < cs->count; i++) {
-               struct v4l2_ctrl *ctrl = helpers[i].ctrl;
-               struct v4l2_ctrl *master = ctrl->cluster[0];
+               int (*ctrl_to_user)(struct v4l2_ext_control *c,
+                                   struct v4l2_ctrl *ctrl) = cur_to_user;
+               struct v4l2_ctrl *master;
 
-               if (helpers[i].handled)
+               if (helpers[i].mref == NULL)
                        continue;
 
+               master = helpers[i].mref->ctrl;
                cs->error_idx = i;
 
                v4l2_ctrl_lock(master);
-               /* g_volatile_ctrl will update the current control values */
-               if (ctrl->is_volatile && master->ops->g_volatile_ctrl)
-                       ret = master->ops->g_volatile_ctrl(master);
-               /* If OK, then copy the current control values to the caller */
-               if (!ret)
-                       ret = cluster_walk(i, cs, helpers, cur_to_user);
+
+               /* g_volatile_ctrl will update the new control values */
+               if (has_op(master, g_volatile_ctrl) && !is_cur_manual(master)) {
+                       for (j = 0; j < master->ncontrols; j++)
+                               cur_to_new(master->cluster[j]);
+                       ret = call_op(master, g_volatile_ctrl);
+                       ctrl_to_user = new_to_user;
+               }
+               /* If OK, then copy the current (for non-volatile controls)
+                  or the new (for volatile controls) control values to the
+                  caller */
+               if (!ret) {
+                       u32 idx = i;
+
+                       do {
+                               ret = ctrl_to_user(cs->controls + idx,
+                                                  helpers[idx].ctrl);
+                               idx = helpers[idx].next;
+                       } while (!ret && idx);
+               }
                v4l2_ctrl_unlock(master);
-               cluster_done(i, cs, helpers);
        }
 
        if (cs->count > ARRAY_SIZE(helper))
@@ -1594,15 +1997,21 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
 {
        struct v4l2_ctrl *master = ctrl->cluster[0];
        int ret = 0;
+       int i;
 
        if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
                return -EACCES;
 
        v4l2_ctrl_lock(master);
        /* g_volatile_ctrl will update the current control values */
-       if (ctrl->is_volatile && master->ops->g_volatile_ctrl)
-               ret = master->ops->g_volatile_ctrl(master);
-       *val = ctrl->cur.val;
+       if (ctrl->is_volatile && !is_cur_manual(master)) {
+               for (i = 0; i < master->ncontrols; i++)
+                       cur_to_new(master->cluster[i]);
+               ret = call_op(master, g_volatile_ctrl);
+               *val = ctrl->val;
+       } else {
+               *val = ctrl->cur.val;
+       }
        v4l2_ctrl_unlock(master);
        return ret;
 }
@@ -1638,72 +2047,61 @@ EXPORT_SYMBOL(v4l2_ctrl_g_ctrl);
 /* Core function that calls try/s_ctrl and ensures that the new value is
    copied to the current value on a set.
    Must be called with ctrl->handler->lock held. */
-static int try_or_set_control_cluster(struct v4l2_ctrl *master, bool set)
+static int try_or_set_cluster(struct v4l2_fh *fh,
+                             struct v4l2_ctrl *master, bool set)
 {
-       bool try = !set;
-       int ret = 0;
+       bool update_flag;
+       int ret;
        int i;
 
        /* Go through the cluster and either validate the new value or
           (if no new value was set), copy the current value to the new
           value, ensuring a consistent view for the control ops when
           called. */
-       for (i = 0; !ret && i < master->ncontrols; i++) {
+       for (i = 0; i < master->ncontrols; i++) {
                struct v4l2_ctrl *ctrl = master->cluster[i];
 
                if (ctrl == NULL)
                        continue;
 
-               if (ctrl->is_new) {
-                       /* Double check this: it may have changed since the
-                          last check in try_or_set_ext_ctrls(). */
-                       if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
-                               return -EBUSY;
-
-                       /* Validate if required */
-                       if (!set)
-                               ret = validate_new(ctrl);
+               if (!ctrl->is_new) {
+                       cur_to_new(ctrl);
                        continue;
                }
-               /* No new value was set, so copy the current and force
-                  a call to try_ctrl later, since the values for the cluster
-                  may now have changed and the end result might be invalid. */
-               try = true;
-               cur_to_new(ctrl);
+               /* Check again: it may have changed since the
+                  previous check in try_or_set_ext_ctrls(). */
+               if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
+                       return -EBUSY;
        }
 
-       /* For larger clusters you have to call try_ctrl again to
-          verify that the controls are still valid after the
-          'cur_to_new' above. */
-       if (!ret && master->ops->try_ctrl && try)
-               ret = master->ops->try_ctrl(master);
+       ret = call_op(master, try_ctrl);
 
        /* Don't set if there is no change */
-       if (!ret && set && cluster_changed(master)) {
-               ret = master->ops->s_ctrl(master);
-               /* If OK, then make the new values permanent. */
-               if (!ret)
-                       for (i = 0; i < master->ncontrols; i++)
-                               new_to_cur(master->cluster[i]);
-       }
-       return ret;
+       if (ret || !set || !cluster_changed(master))
+               return ret;
+       ret = call_op(master, s_ctrl);
+       if (ret)
+               return ret;
+
+       /* If OK, then make the new values permanent. */
+       update_flag = is_cur_manual(master) != is_new_manual(master);
+       for (i = 0; i < master->ncontrols; i++)
+               new_to_cur(fh, master->cluster[i], update_flag && i > 0);
+       return 0;
 }
 
-/* Try or set controls. */
-static int try_or_set_ext_ctrls(struct v4l2_ctrl_handler *hdl,
-                               struct v4l2_ext_controls *cs,
-                               struct ctrl_helper *helpers,
-                               bool set)
+/* Validate controls. */
+static int validate_ctrls(struct v4l2_ext_controls *cs,
+                         struct v4l2_ctrl_helper *helpers, bool set)
 {
-       unsigned i, j;
+       unsigned i;
        int ret = 0;
 
        cs->error_idx = cs->count;
        for (i = 0; i < cs->count; i++) {
                struct v4l2_ctrl *ctrl = helpers[i].ctrl;
 
-               if (!set)
-                       cs->error_idx = i;
+               cs->error_idx = i;
 
                if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
                        return -EACCES;
@@ -1715,50 +2113,22 @@ static int try_or_set_ext_ctrls(struct v4l2_ctrl_handler *hdl,
                   best-effort to avoid that. */
                if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
                        return -EBUSY;
+               ret = validate_new(ctrl, &cs->controls[i]);
+               if (ret)
+                       return ret;
        }
-
-       for (i = 0; !ret && i < cs->count; i++) {
-               struct v4l2_ctrl *ctrl = helpers[i].ctrl;
-               struct v4l2_ctrl *master = ctrl->cluster[0];
-
-               cs->error_idx = i;
-
-               if (helpers[i].handled)
-                       continue;
-
-               v4l2_ctrl_lock(ctrl);
-
-               /* Reset the 'is_new' flags of the cluster */
-               for (j = 0; j < master->ncontrols; j++)
-                       if (master->cluster[j])
-                               master->cluster[j]->is_new = 0;
-
-               /* Copy the new caller-supplied control values.
-                  user_to_new() sets 'is_new' to 1. */
-               ret = cluster_walk(i, cs, helpers, user_to_new);
-
-               if (!ret)
-                       ret = try_or_set_control_cluster(master, set);
-
-               /* Copy the new values back to userspace. */
-               if (!ret)
-                       ret = cluster_walk(i, cs, helpers, new_to_user);
-
-               v4l2_ctrl_unlock(ctrl);
-               cluster_done(i, cs, helpers);
-       }
-       return ret;
+       return 0;
 }
 
 /* Try or try-and-set controls */
-static int try_set_ext_ctrls(struct v4l2_ctrl_handler *hdl,
+static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
                             struct v4l2_ext_controls *cs,
                             bool set)
 {
-       struct ctrl_helper helper[4];
-       struct ctrl_helper *helpers = helper;
+       struct v4l2_ctrl_helper helper[4];
+       struct v4l2_ctrl_helper *helpers = helper;
+       unsigned i, j;
        int ret;
-       int i;
 
        cs->error_idx = cs->count;
        cs->ctrl_class = V4L2_CTRL_ID2CLASS(cs->ctrl_class);
@@ -1774,25 +2144,49 @@ static int try_set_ext_ctrls(struct v4l2_ctrl_handler *hdl,
                if (!helpers)
                        return -ENOMEM;
        }
-       ret = prepare_ext_ctrls(hdl, cs, helpers, !set);
-       if (ret)
-               goto free;
-
-       /* First 'try' all controls and abort on error */
-       ret = try_or_set_ext_ctrls(hdl, cs, helpers, false);
-       /* If this is a 'set' operation and the initial 'try' failed,
-          then set error_idx to count to tell the application that no
-          controls changed value yet. */
-       if (set)
+       ret = prepare_ext_ctrls(hdl, cs, helpers);
+       if (!ret)
+               ret = validate_ctrls(cs, helpers, set);
+       if (ret && set)
                cs->error_idx = cs->count;
-       if (!ret && set) {
-               /* Reset 'handled' state */
-               for (i = 0; i < cs->count; i++)
-                       helpers[i].handled = false;
-               ret = try_or_set_ext_ctrls(hdl, cs, helpers, true);
+       for (i = 0; !ret && i < cs->count; i++) {
+               struct v4l2_ctrl *master;
+               u32 idx = i;
+
+               if (helpers[i].mref == NULL)
+                       continue;
+
+               cs->error_idx = i;
+               master = helpers[i].mref->ctrl;
+               v4l2_ctrl_lock(master);
+
+               /* Reset the 'is_new' flags of the cluster */
+               for (j = 0; j < master->ncontrols; j++)
+                       if (master->cluster[j])
+                               master->cluster[j]->is_new = 0;
+
+               /* Copy the new caller-supplied control values.
+                  user_to_new() sets 'is_new' to 1. */
+               do {
+                       ret = user_to_new(cs->controls + idx, helpers[idx].ctrl);
+                       idx = helpers[idx].next;
+               } while (!ret && idx);
+
+               if (!ret)
+                       ret = try_or_set_cluster(fh, master, set);
+
+               /* Copy the new values back to userspace. */
+               if (!ret) {
+                       idx = i;
+                       do {
+                               ret = new_to_user(cs->controls + idx,
+                                               helpers[idx].ctrl);
+                               idx = helpers[idx].next;
+                       } while (!ret && idx);
+               }
+               v4l2_ctrl_unlock(master);
        }
 
-free:
        if (cs->count > ARRAY_SIZE(helper))
                kfree(helpers);
        return ret;
@@ -1800,37 +2194,39 @@ free:
 
 int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs)
 {
-       return try_set_ext_ctrls(hdl, cs, false);
+       return try_set_ext_ctrls(NULL, hdl, cs, false);
 }
 EXPORT_SYMBOL(v4l2_try_ext_ctrls);
 
-int v4l2_s_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs)
+int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
+                                       struct v4l2_ext_controls *cs)
 {
-       return try_set_ext_ctrls(hdl, cs, true);
+       return try_set_ext_ctrls(fh, hdl, cs, true);
 }
 EXPORT_SYMBOL(v4l2_s_ext_ctrls);
 
 int v4l2_subdev_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs)
 {
-       return try_set_ext_ctrls(sd->ctrl_handler, cs, false);
+       return try_set_ext_ctrls(NULL, sd->ctrl_handler, cs, false);
 }
 EXPORT_SYMBOL(v4l2_subdev_try_ext_ctrls);
 
 int v4l2_subdev_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs)
 {
-       return try_set_ext_ctrls(sd->ctrl_handler, cs, true);
+       return try_set_ext_ctrls(NULL, sd->ctrl_handler, cs, true);
 }
 EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls);
 
 /* Helper function for VIDIOC_S_CTRL compatibility */
-static int set_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
+static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val)
 {
        struct v4l2_ctrl *master = ctrl->cluster[0];
        int ret;
        int i;
 
-       if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
-               return -EACCES;
+       ret = validate_new_int(ctrl, val);
+       if (ret)
+               return ret;
 
        v4l2_ctrl_lock(ctrl);
 
@@ -1841,28 +2237,30 @@ static int set_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
 
        ctrl->val = *val;
        ctrl->is_new = 1;
-       ret = try_or_set_control_cluster(master, false);
-       if (!ret)
-               ret = try_or_set_control_cluster(master, true);
+       ret = try_or_set_cluster(fh, master, true);
        *val = ctrl->cur.val;
        v4l2_ctrl_unlock(ctrl);
        return ret;
 }
 
-int v4l2_s_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control)
+int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
+                                       struct v4l2_control *control)
 {
        struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
 
        if (ctrl == NULL || !type_is_int(ctrl))
                return -EINVAL;
 
-       return set_ctrl(ctrl, &control->value);
+       if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
+               return -EACCES;
+
+       return set_ctrl(fh, ctrl, &control->value);
 }
 EXPORT_SYMBOL(v4l2_s_ctrl);
 
 int v4l2_subdev_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *control)
 {
-       return v4l2_s_ctrl(sd->ctrl_handler, control);
+       return v4l2_s_ctrl(NULL, sd->ctrl_handler, control);
 }
 EXPORT_SYMBOL(v4l2_subdev_s_ctrl);
 
@@ -1870,6 +2268,34 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
 {
        /* It's a driver bug if this happens. */
        WARN_ON(!type_is_int(ctrl));
-       return set_ctrl(ctrl, &val);
+       return set_ctrl(NULL, ctrl, &val);
 }
 EXPORT_SYMBOL(v4l2_ctrl_s_ctrl);
+
+void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl,
+                               struct v4l2_subscribed_event *sev)
+{
+       v4l2_ctrl_lock(ctrl);
+       list_add_tail(&sev->node, &ctrl->ev_subs);
+       if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS &&
+           (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL)) {
+               struct v4l2_event ev;
+               u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
+
+               if (!(ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY))
+                       changes |= V4L2_EVENT_CTRL_CH_VALUE;
+               fill_event(&ev, ctrl, changes);
+               v4l2_event_queue_fh(sev->fh, &ev);
+       }
+       v4l2_ctrl_unlock(ctrl);
+}
+EXPORT_SYMBOL(v4l2_ctrl_add_event);
+
+void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl,
+                               struct v4l2_subscribed_event *sev)
+{
+       v4l2_ctrl_lock(ctrl);
+       list_del(&sev->node);
+       v4l2_ctrl_unlock(ctrl);
+}
+EXPORT_SYMBOL(v4l2_ctrl_del_event);
index 4aae501..c72856c 100644 (file)
@@ -209,6 +209,7 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
                vdev->v4l2_dev = v4l2_dev;
                vdev->fops = &v4l2_subdev_fops;
                vdev->release = video_device_release_empty;
+               vdev->ctrl_handler = sd->ctrl_handler;
                err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
                                              sd->owner);
                if (err < 0)
index 69fd343..53b190c 100644 (file)
 #include <media/v4l2-dev.h>
 #include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
+#include <media/v4l2-ctrls.h>
 
 #include <linux/sched.h>
 #include <linux/slab.h>
 
-int v4l2_event_init(struct v4l2_fh *fh)
+static unsigned sev_pos(const struct v4l2_subscribed_event *sev, unsigned idx)
 {
-       fh->events = kzalloc(sizeof(*fh->events), GFP_KERNEL);
-       if (fh->events == NULL)
-               return -ENOMEM;
-
-       init_waitqueue_head(&fh->events->wait);
-
-       INIT_LIST_HEAD(&fh->events->free);
-       INIT_LIST_HEAD(&fh->events->available);
-       INIT_LIST_HEAD(&fh->events->subscribed);
-
-       fh->events->sequence = -1;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(v4l2_event_init);
-
-int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n)
-{
-       struct v4l2_events *events = fh->events;
-       unsigned long flags;
-
-       if (!events) {
-               WARN_ON(1);
-               return -ENOMEM;
-       }
-
-       while (events->nallocated < n) {
-               struct v4l2_kevent *kev;
-
-               kev = kzalloc(sizeof(*kev), GFP_KERNEL);
-               if (kev == NULL)
-                       return -ENOMEM;
-
-               spin_lock_irqsave(&fh->vdev->fh_lock, flags);
-               list_add_tail(&kev->list, &events->free);
-               events->nallocated++;
-               spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(v4l2_event_alloc);
-
-#define list_kfree(list, type, member)                         \
-       while (!list_empty(list)) {                             \
-               type *hi;                                       \
-               hi = list_first_entry(list, type, member);      \
-               list_del(&hi->member);                          \
-               kfree(hi);                                      \
-       }
-
-void v4l2_event_free(struct v4l2_fh *fh)
-{
-       struct v4l2_events *events = fh->events;
-
-       if (!events)
-               return;
-
-       list_kfree(&events->free, struct v4l2_kevent, list);
-       list_kfree(&events->available, struct v4l2_kevent, list);
-       list_kfree(&events->subscribed, struct v4l2_subscribed_event, list);
-
-       kfree(events);
-       fh->events = NULL;
+       idx += sev->first;
+       return idx >= sev->elems ? idx - sev->elems : idx;
 }
-EXPORT_SYMBOL_GPL(v4l2_event_free);
 
 static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event)
 {
-       struct v4l2_events *events = fh->events;
        struct v4l2_kevent *kev;
        unsigned long flags;
 
        spin_lock_irqsave(&fh->vdev->fh_lock, flags);
 
-       if (list_empty(&events->available)) {
+       if (list_empty(&fh->available)) {
                spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
                return -ENOENT;
        }
 
-       WARN_ON(events->navailable == 0);
+       WARN_ON(fh->navailable == 0);
 
-       kev = list_first_entry(&events->available, struct v4l2_kevent, list);
-       list_move(&kev->list, &events->free);
-       events->navailable--;
+       kev = list_first_entry(&fh->available, struct v4l2_kevent, list);
+       list_del(&kev->list);
+       fh->navailable--;
 
-       kev->event.pending = events->navailable;
+       kev->event.pending = fh->navailable;
        *event = kev->event;
+       kev->sev->first = sev_pos(kev->sev, 1);
+       kev->sev->in_use--;
 
        spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
 
@@ -128,7 +67,6 @@ static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event)
 int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
                       int nonblocking)
 {
-       struct v4l2_events *events = fh->events;
        int ret;
 
        if (nonblocking)
@@ -139,8 +77,8 @@ int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
                mutex_unlock(fh->vdev->lock);
 
        do {
-               ret = wait_event_interruptible(events->wait,
-                                              events->navailable != 0);
+               ret = wait_event_interruptible(fh->wait,
+                                              fh->navailable != 0);
                if (ret < 0)
                        break;
 
@@ -154,23 +92,72 @@ int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
 }
 EXPORT_SYMBOL_GPL(v4l2_event_dequeue);
 
-/* Caller must hold fh->event->lock! */
+/* Caller must hold fh->vdev->fh_lock! */
 static struct v4l2_subscribed_event *v4l2_event_subscribed(
-       struct v4l2_fh *fh, u32 type)
+               struct v4l2_fh *fh, u32 type, u32 id)
 {
-       struct v4l2_events *events = fh->events;
        struct v4l2_subscribed_event *sev;
 
        assert_spin_locked(&fh->vdev->fh_lock);
 
-       list_for_each_entry(sev, &events->subscribed, list) {
-               if (sev->type == type)
+       list_for_each_entry(sev, &fh->subscribed, list)
+               if (sev->type == type && sev->id == id)
                        return sev;
-       }
 
        return NULL;
 }
 
+static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev,
+               const struct timespec *ts)
+{
+       struct v4l2_subscribed_event *sev;
+       struct v4l2_kevent *kev;
+       bool copy_payload = true;
+
+       /* Are we subscribed? */
+       sev = v4l2_event_subscribed(fh, ev->type, ev->id);
+       if (sev == NULL)
+               return;
+
+       /* Increase event sequence number on fh. */
+       fh->sequence++;
+
+       /* Do we have any free events? */
+       if (sev->in_use == sev->elems) {
+               /* no, remove the oldest one */
+               kev = sev->events + sev_pos(sev, 0);
+               list_del(&kev->list);
+               sev->in_use--;
+               sev->first = sev_pos(sev, 1);
+               fh->navailable--;
+               if (sev->elems == 1) {
+                       if (sev->replace) {
+                               sev->replace(&kev->event, ev);
+                               copy_payload = false;
+                       }
+               } else if (sev->merge) {
+                       struct v4l2_kevent *second_oldest =
+                               sev->events + sev_pos(sev, 0);
+                       sev->merge(&kev->event, &second_oldest->event);
+               }
+       }
+
+       /* Take one and fill it. */
+       kev = sev->events + sev_pos(sev, sev->in_use);
+       kev->event.type = ev->type;
+       if (copy_payload)
+               kev->event.u = ev->u;
+       kev->event.id = ev->id;
+       kev->event.timestamp = *ts;
+       kev->event.sequence = fh->sequence;
+       sev->in_use++;
+       list_add_tail(&kev->list, &fh->available);
+
+       fh->navailable++;
+
+       wake_up_all(&fh->wait);
+}
+
 void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev)
 {
        struct v4l2_fh *fh;
@@ -181,81 +168,95 @@ void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev)
 
        spin_lock_irqsave(&vdev->fh_lock, flags);
 
-       list_for_each_entry(fh, &vdev->fh_list, list) {
-               struct v4l2_events *events = fh->events;
-               struct v4l2_kevent *kev;
+       list_for_each_entry(fh, &vdev->fh_list, list)
+               __v4l2_event_queue_fh(fh, ev, &timestamp);
 
-               /* Are we subscribed? */
-               if (!v4l2_event_subscribed(fh, ev->type))
-                       continue;
+       spin_unlock_irqrestore(&vdev->fh_lock, flags);
+}
+EXPORT_SYMBOL_GPL(v4l2_event_queue);
 
-               /* Increase event sequence number on fh. */
-               events->sequence++;
+void v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev)
+{
+       unsigned long flags;
+       struct timespec timestamp;
 
-               /* Do we have any free events? */
-               if (list_empty(&events->free))
-                       continue;
+       ktime_get_ts(&timestamp);
 
-               /* Take one and fill it. */
-               kev = list_first_entry(&events->free, struct v4l2_kevent, list);
-               kev->event.type = ev->type;
-               kev->event.u = ev->u;
-               kev->event.timestamp = timestamp;
-               kev->event.sequence = events->sequence;
-               list_move_tail(&kev->list, &events->available);
+       spin_lock_irqsave(&fh->vdev->fh_lock, flags);
+       __v4l2_event_queue_fh(fh, ev, &timestamp);
+       spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
+}
+EXPORT_SYMBOL_GPL(v4l2_event_queue_fh);
 
-               events->navailable++;
+int v4l2_event_pending(struct v4l2_fh *fh)
+{
+       return fh->navailable;
+}
+EXPORT_SYMBOL_GPL(v4l2_event_pending);
 
-               wake_up_all(&events->wait);
-       }
+static void ctrls_replace(struct v4l2_event *old, const struct v4l2_event *new)
+{
+       u32 old_changes = old->u.ctrl.changes;
 
-       spin_unlock_irqrestore(&vdev->fh_lock, flags);
+       old->u.ctrl = new->u.ctrl;
+       old->u.ctrl.changes |= old_changes;
 }
-EXPORT_SYMBOL_GPL(v4l2_event_queue);
 
-int v4l2_event_pending(struct v4l2_fh *fh)
+static void ctrls_merge(const struct v4l2_event *old, struct v4l2_event *new)
 {
-       return fh->events->navailable;
+       new->u.ctrl.changes |= old->u.ctrl.changes;
 }
-EXPORT_SYMBOL_GPL(v4l2_event_pending);
 
 int v4l2_event_subscribe(struct v4l2_fh *fh,
-                        struct v4l2_event_subscription *sub)
+                        struct v4l2_event_subscription *sub, unsigned elems)
 {
-       struct v4l2_events *events = fh->events;
-       struct v4l2_subscribed_event *sev;
+       struct v4l2_subscribed_event *sev, *found_ev;
+       struct v4l2_ctrl *ctrl = NULL;
        unsigned long flags;
-
-       if (fh->events == NULL) {
-               WARN_ON(1);
-               return -ENOMEM;
+       unsigned i;
+
+       if (elems < 1)
+               elems = 1;
+       if (sub->type == V4L2_EVENT_CTRL) {
+               ctrl = v4l2_ctrl_find(fh->ctrl_handler, sub->id);
+               if (ctrl == NULL)
+                       return -EINVAL;
        }
 
-       sev = kmalloc(sizeof(*sev), GFP_KERNEL);
+       sev = kzalloc(sizeof(*sev) + sizeof(struct v4l2_kevent) * elems, GFP_KERNEL);
        if (!sev)
                return -ENOMEM;
-
-       spin_lock_irqsave(&fh->vdev->fh_lock, flags);
-
-       if (v4l2_event_subscribed(fh, sub->type) == NULL) {
-               INIT_LIST_HEAD(&sev->list);
-               sev->type = sub->type;
-
-               list_add(&sev->list, &events->subscribed);
-               sev = NULL;
+       for (i = 0; i < elems; i++)
+               sev->events[i].sev = sev;
+       sev->type = sub->type;
+       sev->id = sub->id;
+       sev->flags = sub->flags;
+       sev->fh = fh;
+       sev->elems = elems;
+       if (ctrl) {
+               sev->replace = ctrls_replace;
+               sev->merge = ctrls_merge;
        }
 
+       spin_lock_irqsave(&fh->vdev->fh_lock, flags);
+       found_ev = v4l2_event_subscribed(fh, sub->type, sub->id);
+       if (!found_ev)
+               list_add(&sev->list, &fh->subscribed);
        spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
 
-       kfree(sev);
+       /* v4l2_ctrl_add_event uses a mutex, so do this outside the spin lock */
+       if (found_ev)
+               kfree(sev);
+       else if (ctrl)
+               v4l2_ctrl_add_event(ctrl, sev);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_event_subscribe);
 
-static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh)
+void v4l2_event_unsubscribe_all(struct v4l2_fh *fh)
 {
-       struct v4l2_events *events = fh->events;
+       struct v4l2_event_subscription sub;
        struct v4l2_subscribed_event *sev;
        unsigned long flags;
 
@@ -263,15 +264,18 @@ static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh)
                sev = NULL;
 
                spin_lock_irqsave(&fh->vdev->fh_lock, flags);
-               if (!list_empty(&events->subscribed)) {
-                       sev = list_first_entry(&events->subscribed,
-                                      struct v4l2_subscribed_event, list);
-                       list_del(&sev->list);
+               if (!list_empty(&fh->subscribed)) {
+                       sev = list_first_entry(&fh->subscribed,
+                                       struct v4l2_subscribed_event, list);
+                       sub.type = sev->type;
+                       sub.id = sev->id;
                }
                spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
-               kfree(sev);
+               if (sev)
+                       v4l2_event_unsubscribe(fh, &sub);
        } while (sev);
 }
+EXPORT_SYMBOL_GPL(v4l2_event_unsubscribe_all);
 
 int v4l2_event_unsubscribe(struct v4l2_fh *fh,
                           struct v4l2_event_subscription *sub)
@@ -286,11 +290,19 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
 
        spin_lock_irqsave(&fh->vdev->fh_lock, flags);
 
-       sev = v4l2_event_subscribed(fh, sub->type);
-       if (sev != NULL)
+       sev = v4l2_event_subscribed(fh, sub->type, sub->id);
+       if (sev != NULL) {
                list_del(&sev->list);
+               sev->fh = NULL;
+       }
 
        spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
+       if (sev && sev->type == V4L2_EVENT_CTRL) {
+               struct v4l2_ctrl *ctrl = v4l2_ctrl_find(fh->ctrl_handler, sev->id);
+
+               if (ctrl)
+                       v4l2_ctrl_del_event(ctrl, sev);
+       }
 
        kfree(sev);
 
index 717f71e..122822d 100644 (file)
 #include <media/v4l2-event.h>
 #include <media/v4l2-ioctl.h>
 
-int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
+void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
 {
        fh->vdev = vdev;
+       /* Inherit from video_device. May be overridden by the driver. */
+       fh->ctrl_handler = vdev->ctrl_handler;
        INIT_LIST_HEAD(&fh->list);
        set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags);
        fh->prio = V4L2_PRIORITY_UNSET;
-
-       /*
-        * fh->events only needs to be initialized if the driver
-        * supports the VIDIOC_SUBSCRIBE_EVENT ioctl.
-        */
-       if (vdev->ioctl_ops && vdev->ioctl_ops->vidioc_subscribe_event)
-               return v4l2_event_init(fh);
-
-       fh->events = NULL;
-
-       return 0;
+       init_waitqueue_head(&fh->wait);
+       INIT_LIST_HEAD(&fh->available);
+       INIT_LIST_HEAD(&fh->subscribed);
+       fh->sequence = -1;
 }
 EXPORT_SYMBOL_GPL(v4l2_fh_init);
 
@@ -91,10 +86,8 @@ void v4l2_fh_exit(struct v4l2_fh *fh)
 {
        if (fh->vdev == NULL)
                return;
-
+       v4l2_event_unsubscribe_all(fh);
        fh->vdev = NULL;
-
-       v4l2_event_free(fh);
 }
 EXPORT_SYMBOL_GPL(v4l2_fh_exit);
 
index 69e8c6f..002ce13 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/version.h>
 
 #include <linux/videodev2.h>
 
@@ -542,12 +543,12 @@ static long __video_do_ioctl(struct file *file,
        struct v4l2_fh *vfh = NULL;
        struct v4l2_format f_copy;
        int use_fh_prio = 0;
-       long ret = -EINVAL;
+       long ret = -ENOTTY;
 
        if (ops == NULL) {
                printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n",
                                vfd->name);
-               return -EINVAL;
+               return ret;
        }
 
        if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
@@ -605,6 +606,7 @@ static long __video_do_ioctl(struct file *file,
                if (!ops->vidioc_querycap)
                        break;
 
+               cap->version = LINUX_VERSION_CODE;
                ret = ops->vidioc_querycap(file, fh, cap);
                if (!ret)
                        dbgarg(cmd, "driver=%s, card=%s, bus=%s, "
@@ -1418,7 +1420,9 @@ static long __video_do_ioctl(struct file *file,
        {
                struct v4l2_queryctrl *p = arg;
 
-               if (vfd->ctrl_handler)
+               if (vfh && vfh->ctrl_handler)
+                       ret = v4l2_queryctrl(vfh->ctrl_handler, p);
+               else if (vfd->ctrl_handler)
                        ret = v4l2_queryctrl(vfd->ctrl_handler, p);
                else if (ops->vidioc_queryctrl)
                        ret = ops->vidioc_queryctrl(file, fh, p);
@@ -1438,7 +1442,9 @@ static long __video_do_ioctl(struct file *file,
        {
                struct v4l2_control *p = arg;
 
-               if (vfd->ctrl_handler)
+               if (vfh && vfh->ctrl_handler)
+                       ret = v4l2_g_ctrl(vfh->ctrl_handler, p);
+               else if (vfd->ctrl_handler)
                        ret = v4l2_g_ctrl(vfd->ctrl_handler, p);
                else if (ops->vidioc_g_ctrl)
                        ret = ops->vidioc_g_ctrl(file, fh, p);
@@ -1470,14 +1476,18 @@ static long __video_do_ioctl(struct file *file,
                struct v4l2_ext_controls ctrls;
                struct v4l2_ext_control ctrl;
 
-               if (!vfd->ctrl_handler &&
+               if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
                        !ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
                        break;
 
                dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
 
+               if (vfh && vfh->ctrl_handler) {
+                       ret = v4l2_s_ctrl(vfh, vfh->ctrl_handler, p);
+                       break;
+               }
                if (vfd->ctrl_handler) {
-                       ret = v4l2_s_ctrl(vfd->ctrl_handler, p);
+                       ret = v4l2_s_ctrl(NULL, vfd->ctrl_handler, p);
                        break;
                }
                if (ops->vidioc_s_ctrl) {
@@ -1501,7 +1511,9 @@ static long __video_do_ioctl(struct file *file,
                struct v4l2_ext_controls *p = arg;
 
                p->error_idx = p->count;
-               if (vfd->ctrl_handler)
+               if (vfh && vfh->ctrl_handler)
+                       ret = v4l2_g_ext_ctrls(vfh->ctrl_handler, p);
+               else if (vfd->ctrl_handler)
                        ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
                else if (ops->vidioc_g_ext_ctrls && check_ext_ctrls(p, 0))
                        ret = ops->vidioc_g_ext_ctrls(file, fh, p);
@@ -1515,11 +1527,14 @@ static long __video_do_ioctl(struct file *file,
                struct v4l2_ext_controls *p = arg;
 
                p->error_idx = p->count;
-               if (!vfd->ctrl_handler && !ops->vidioc_s_ext_ctrls)
+               if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
+                               !ops->vidioc_s_ext_ctrls)
                        break;
                v4l_print_ext_ctrls(cmd, vfd, p, 1);
-               if (vfd->ctrl_handler)
-                       ret = v4l2_s_ext_ctrls(vfd->ctrl_handler, p);
+               if (vfh && vfh->ctrl_handler)
+                       ret = v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p);
+               else if (vfd->ctrl_handler)
+                       ret = v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p);
                else if (check_ext_ctrls(p, 0))
                        ret = ops->vidioc_s_ext_ctrls(file, fh, p);
                break;
@@ -1529,10 +1544,13 @@ static long __video_do_ioctl(struct file *file,
                struct v4l2_ext_controls *p = arg;
 
                p->error_idx = p->count;
-               if (!vfd->ctrl_handler && !ops->vidioc_try_ext_ctrls)
+               if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
+                               !ops->vidioc_try_ext_ctrls)
                        break;
                v4l_print_ext_ctrls(cmd, vfd, p, 1);
-               if (vfd->ctrl_handler)
+               if (vfh && vfh->ctrl_handler)
+                       ret = v4l2_try_ext_ctrls(vfh->ctrl_handler, p);
+               else if (vfd->ctrl_handler)
                        ret = v4l2_try_ext_ctrls(vfd->ctrl_handler, p);
                else if (check_ext_ctrls(p, 0))
                        ret = ops->vidioc_try_ext_ctrls(file, fh, p);
@@ -1542,7 +1560,9 @@ static long __video_do_ioctl(struct file *file,
        {
                struct v4l2_querymenu *p = arg;
 
-               if (vfd->ctrl_handler)
+               if (vfh && vfh->ctrl_handler)
+                       ret = v4l2_querymenu(vfh->ctrl_handler, p);
+               else if (vfd->ctrl_handler)
                        ret = v4l2_querymenu(vfd->ctrl_handler, p);
                else if (ops->vidioc_querymenu)
                        ret = ops->vidioc_querymenu(file, fh, p);
@@ -2276,7 +2296,7 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
                                break;
                        }
                        *user_ptr = (void __user *)buf->m.planes;
-                       *kernel_ptr = (void **)&buf->m.planes;
+                       *kernel_ptr = (void *)&buf->m.planes;
                        *array_size = sizeof(struct v4l2_plane) * buf->length;
                        ret = 1;
                }
@@ -2290,7 +2310,7 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
 
                if (ctrls->count != 0) {
                        *user_ptr = (void __user *)ctrls->controls;
-                       *kernel_ptr = (void **)&ctrls->controls;
+                       *kernel_ptr = (void *)&ctrls->controls;
                        *array_size = sizeof(struct v4l2_ext_control)
                                    * ctrls->count;
                        ret = 1;
index 812729e..b7967c9 100644 (file)
@@ -75,20 +75,7 @@ static int subdev_open(struct file *file)
                return ret;
        }
 
-       ret = v4l2_fh_init(&subdev_fh->vfh, vdev);
-       if (ret)
-               goto err;
-
-       if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) {
-               ret = v4l2_event_init(&subdev_fh->vfh);
-               if (ret)
-                       goto err;
-
-               ret = v4l2_event_alloc(&subdev_fh->vfh, sd->nevents);
-               if (ret)
-                       goto err;
-       }
-
+       v4l2_fh_init(&subdev_fh->vfh, vdev);
        v4l2_fh_add(&subdev_fh->vfh);
        file->private_data = &subdev_fh->vfh;
 #if defined(CONFIG_MEDIA_CONTROLLER)
@@ -155,25 +142,25 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
        switch (cmd) {
        case VIDIOC_QUERYCTRL:
-               return v4l2_queryctrl(sd->ctrl_handler, arg);
+               return v4l2_queryctrl(vfh->ctrl_handler, arg);
 
        case VIDIOC_QUERYMENU:
-               return v4l2_querymenu(sd->ctrl_handler, arg);
+               return v4l2_querymenu(vfh->ctrl_handler, arg);
 
        case VIDIOC_G_CTRL:
-               return v4l2_g_ctrl(sd->ctrl_handler, arg);
+               return v4l2_g_ctrl(vfh->ctrl_handler, arg);
 
        case VIDIOC_S_CTRL:
-               return v4l2_s_ctrl(sd->ctrl_handler, arg);
+               return v4l2_s_ctrl(vfh, vfh->ctrl_handler, arg);
 
        case VIDIOC_G_EXT_CTRLS:
-               return v4l2_g_ext_ctrls(sd->ctrl_handler, arg);
+               return v4l2_g_ext_ctrls(vfh->ctrl_handler, arg);
 
        case VIDIOC_S_EXT_CTRLS:
-               return v4l2_s_ext_ctrls(sd->ctrl_handler, arg);
+               return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, arg);
 
        case VIDIOC_TRY_EXT_CTRLS:
-               return v4l2_try_ext_ctrls(sd->ctrl_handler, arg);
+               return v4l2_try_ext_ctrls(vfh->ctrl_handler, arg);
 
        case VIDIOC_DQEVENT:
                if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
@@ -297,7 +284,7 @@ static unsigned int subdev_poll(struct file *file, poll_table *wait)
        if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
                return POLLERR;
 
-       poll_wait(file, &fh->events->wait, wait);
+       poll_wait(file, &fh->wait, wait);
 
        if (v4l2_event_pending(fh))
                return POLLPRI;
index ddb8f4b..f300dea 100644 (file)
@@ -108,8 +108,9 @@ static struct scatterlist *videobuf_pages_to_sg(struct page **pages,
        if (PageHighMem(pages[0]))
                /* DMA to highmem pages might not work */
                goto highmem;
-       sg_set_page(&sglist[0], pages[0], PAGE_SIZE - offset, offset);
-       size -= PAGE_SIZE - offset;
+       sg_set_page(&sglist[0], pages[0],
+                       min_t(size_t, PAGE_SIZE - offset, size), offset);
+       size -= min_t(size_t, PAGE_SIZE - offset, size);
        for (i = 1; i < nr_pages; i++) {
                if (NULL == pages[i])
                        goto nopage;
index 10a20d9..065f468 100644 (file)
@@ -48,12 +48,10 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size)
        buf->sg_desc.size = size;
        buf->sg_desc.num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
-       buf->sg_desc.sglist = vmalloc(buf->sg_desc.num_pages *
+       buf->sg_desc.sglist = vzalloc(buf->sg_desc.num_pages *
                                      sizeof(*buf->sg_desc.sglist));
        if (!buf->sg_desc.sglist)
                goto fail_sglist_alloc;
-       memset(buf->sg_desc.sglist, 0, buf->sg_desc.num_pages *
-              sizeof(*buf->sg_desc.sglist));
        sg_init_table(buf->sg_desc.sglist, buf->sg_desc.num_pages);
 
        buf->pages = kzalloc(buf->sg_desc.num_pages * sizeof(struct page *),
@@ -136,13 +134,11 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
        last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
        buf->sg_desc.num_pages = last - first + 1;
 
-       buf->sg_desc.sglist = vmalloc(
+       buf->sg_desc.sglist = vzalloc(
                buf->sg_desc.num_pages * sizeof(*buf->sg_desc.sglist));
        if (!buf->sg_desc.sglist)
                goto userptr_fail_sglist_alloc;
 
-       memset(buf->sg_desc.sglist, 0,
-               buf->sg_desc.num_pages * sizeof(*buf->sg_desc.sglist));
        sg_init_table(buf->sg_desc.sglist, buf->sg_desc.num_pages);
 
        buf->pages = kzalloc(buf->sg_desc.num_pages * sizeof(struct page *),
index b03c3ae..569eeb3 100644 (file)
@@ -176,7 +176,7 @@ int vb2_mmap_pfn_range(struct vm_area_struct *vma, unsigned long paddr,
 
        vma->vm_ops->open(vma);
 
-       printk(KERN_DEBUG "%s: mapped paddr 0x%08lx at 0x%08lx, size %ld\n",
+       pr_debug("%s: mapped paddr 0x%08lx at 0x%08lx, size %ld\n",
                        __func__, paddr, vma->vm_start, size);
 
        return 0;
@@ -194,7 +194,7 @@ static void vb2_common_vm_open(struct vm_area_struct *vma)
 {
        struct vb2_vmarea_handler *h = vma->vm_private_data;
 
-       printk(KERN_DEBUG "%s: %p, refcount: %d, vma: %08lx-%08lx\n",
+       pr_debug("%s: %p, refcount: %d, vma: %08lx-%08lx\n",
               __func__, h, atomic_read(h->refcount), vma->vm_start,
               vma->vm_end);
 
@@ -212,7 +212,7 @@ static void vb2_common_vm_close(struct vm_area_struct *vma)
 {
        struct vb2_vmarea_handler *h = vma->vm_private_data;
 
-       printk(KERN_DEBUG "%s: %p, refcount: %d, vma: %08lx-%08lx\n",
+       pr_debug("%s: %p, refcount: %d, vma: %08lx-%08lx\n",
               __func__, h, atomic_read(h->refcount), vma->vm_start,
               vma->vm_end);
 
index d63e9d9..52a0a37 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/time.h>
-#include <linux/version.h>
 #include <linux/kmod.h>
 
 #include <linux/i2c.h>
@@ -61,8 +60,7 @@
 // #define VINO_DEBUG
 // #define VINO_DEBUG_INT
 
-#define VINO_MODULE_VERSION "0.0.6"
-#define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 6)
+#define VINO_MODULE_VERSION "0.0.7"
 
 MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver");
 MODULE_VERSION(VINO_MODULE_VERSION);
@@ -2934,7 +2932,6 @@ static int vino_querycap(struct file *file, void *__fh,
        strcpy(cap->driver, vino_driver_name);
        strcpy(cap->card, vino_driver_description);
        strcpy(cap->bus_info, vino_bus_name);
-       cap->version = VINO_VERSION_CODE;
        cap->capabilities =
                V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_STREAMING;
index 2238a61..a848bd2 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/font.h>
-#include <linux/version.h>
 #include <linux/mutex.h>
 #include <linux/videodev2.h>
 #include <linux/kthread.h>
@@ -32,6 +31,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
 #include <media/v4l2-common.h>
 
 #define VIVI_MODULE_NAME "vivi"
 #define MAX_WIDTH 1920
 #define MAX_HEIGHT 1200
 
-#define VIVI_MAJOR_VERSION 0
-#define VIVI_MINOR_VERSION 8
-#define VIVI_RELEASE 0
-#define VIVI_VERSION \
-       KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
+#define VIVI_VERSION "0.8.1"
 
 MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
 MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(VIVI_VERSION);
 
 static unsigned video_nr = -1;
 module_param(video_nr, uint, 0644);
@@ -167,6 +164,11 @@ struct vivi_dev {
        struct v4l2_ctrl           *contrast;
        struct v4l2_ctrl           *saturation;
        struct v4l2_ctrl           *hue;
+       struct {
+               /* autogain/gain cluster */
+               struct v4l2_ctrl           *autogain;
+               struct v4l2_ctrl           *gain;
+       };
        struct v4l2_ctrl           *volume;
        struct v4l2_ctrl           *button;
        struct v4l2_ctrl           *boolean;
@@ -174,6 +176,7 @@ struct vivi_dev {
        struct v4l2_ctrl           *int64;
        struct v4l2_ctrl           *menu;
        struct v4l2_ctrl           *string;
+       struct v4l2_ctrl           *bitmask;
 
        spinlock_t                 slock;
        struct mutex               mutex;
@@ -457,6 +460,7 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
        unsigned ms;
        char str[100];
        int h, line = 1;
+       s32 gain;
 
        if (!vbuf)
                return;
@@ -479,6 +483,7 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
                        dev->width, dev->height, dev->input);
        gen_text(dev, vbuf, line++ * 16, 16, str);
 
+       gain = v4l2_ctrl_g_ctrl(dev->gain);
        mutex_lock(&dev->ctrl_handler.lock);
        snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
                        dev->brightness->cur.val,
@@ -486,11 +491,13 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
                        dev->saturation->cur.val,
                        dev->hue->cur.val);
        gen_text(dev, vbuf, line++ * 16, 16, str);
-       snprintf(str, sizeof(str), " volume %3d ", dev->volume->cur.val);
+       snprintf(str, sizeof(str), " autogain %d, gain %3d, volume %3d ",
+                       dev->autogain->cur.val, gain, dev->volume->cur.val);
        gen_text(dev, vbuf, line++ * 16, 16, str);
-       snprintf(str, sizeof(str), " int32 %d, int64 %lld ",
+       snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
                        dev->int32->cur.val,
-                       dev->int64->cur.val64);
+                       dev->int64->cur.val64,
+                       dev->bitmask->cur.val);
        gen_text(dev, vbuf, line++ * 16, 16, str);
        snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
                        dev->boolean->cur.val,
@@ -524,11 +531,13 @@ static void vivi_thread_tick(struct vivi_dev *dev)
        spin_lock_irqsave(&dev->slock, flags);
        if (list_empty(&dma_q->active)) {
                dprintk(dev, 1, "No active queue to serve\n");
-               goto unlock;
+               spin_unlock_irqrestore(&dev->slock, flags);
+               return;
        }
 
        buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
        list_del(&buf->list);
+       spin_unlock_irqrestore(&dev->slock, flags);
 
        do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
 
@@ -538,8 +547,6 @@ static void vivi_thread_tick(struct vivi_dev *dev)
 
        vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
        dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
-unlock:
-       spin_unlock_irqrestore(&dev->slock, flags);
 }
 
 #define frames_to_ms(frames)                                   \
@@ -812,7 +819,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strcpy(cap->driver, "vivi");
        strcpy(cap->card, "vivi");
        strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
-       cap->version = VIVI_VERSION;
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
                            V4L2_CAP_READWRITE;
        return 0;
@@ -975,14 +981,37 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
        if (i >= NUM_INPUTS)
                return -EINVAL;
 
+       if (i == dev->input)
+               return 0;
+
        dev->input = i;
        precalculate_bars(dev);
        precalculate_line(dev);
        return 0;
 }
 
+static int vidioc_subscribe_event(struct v4l2_fh *fh,
+                               struct v4l2_event_subscription *sub)
+{
+       switch (sub->type) {
+       case V4L2_EVENT_CTRL:
+               return v4l2_event_subscribe(fh, sub, 0);
+       default:
+               return -EINVAL;
+       }
+}
+
 /* --- controls ---------------------------------------------- */
 
+static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
+
+       if (ctrl == dev->autogain)
+               dev->gain->val = jiffies & 0xff;
+       return 0;
+}
+
 static int vivi_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
@@ -1010,10 +1039,17 @@ static unsigned int
 vivi_poll(struct file *file, struct poll_table_struct *wait)
 {
        struct vivi_dev *dev = video_drvdata(file);
+       struct v4l2_fh *fh = file->private_data;
        struct vb2_queue *q = &dev->vb_vidq;
+       unsigned int res;
 
        dprintk(dev, 1, "%s\n", __func__);
-       return vb2_poll(q, file, wait);
+       res = vb2_poll(q, file, wait);
+       if (v4l2_event_pending(fh))
+               res |= POLLPRI;
+       else
+               poll_wait(file, &fh->wait, wait);
+       return res;
 }
 
 static int vivi_close(struct file *file)
@@ -1045,6 +1081,7 @@ static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
 }
 
 static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
+       .g_volatile_ctrl = vivi_g_volatile_ctrl,
        .s_ctrl = vivi_s_ctrl,
 };
 
@@ -1117,9 +1154,20 @@ static const struct v4l2_ctrl_config vivi_ctrl_string = {
        .step = 1,
 };
 
+static const struct v4l2_ctrl_config vivi_ctrl_bitmask = {
+       .ops = &vivi_ctrl_ops,
+       .id = VIVI_CID_CUSTOM_BASE + 6,
+       .name = "Bitmask",
+       .type = V4L2_CTRL_TYPE_BITMASK,
+       .def = 0x80002000,
+       .min = 0,
+       .max = 0x80402010,
+       .step = 0,
+};
+
 static const struct v4l2_file_operations vivi_fops = {
        .owner          = THIS_MODULE,
-       .open           = v4l2_fh_open,
+       .open           = v4l2_fh_open,
        .release        = vivi_close,
        .read           = vivi_read,
        .poll           = vivi_poll,
@@ -1143,6 +1191,8 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
        .vidioc_s_input       = vidioc_s_input,
        .vidioc_streamon      = vidioc_streamon,
        .vidioc_streamoff     = vidioc_streamoff,
+       .vidioc_subscribe_event = vidioc_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static struct video_device vivi_template = {
@@ -1213,16 +1263,22 @@ static int __init vivi_create_instance(int inst)
                        V4L2_CID_SATURATION, 0, 255, 1, 127);
        dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
                        V4L2_CID_HUE, -128, 127, 1, 0);
+       dev->autogain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       dev->gain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 255, 1, 100);
        dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
        dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
        dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);
        dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL);
        dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL);
        dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL);
+       dev->bitmask = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_bitmask, NULL);
        if (hdl->error) {
                ret = hdl->error;
                goto unreg_dev;
        }
+       v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
        dev->v4l2_dev.ctrl_handler = hdl;
 
        /* initialize locks */
@@ -1325,9 +1381,8 @@ static int __init vivi_init(void)
        }
 
        printk(KERN_INFO "Video Technology Magazine Virtual Video "
-                       "Capture Board ver %u.%u.%u successfully loaded.\n",
-                       (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
-                       VIVI_VERSION & 0xFF);
+                       "Capture Board ver %s successfully loaded.\n",
+                       VIVI_VERSION);
 
        /* n_devs will reflect the actual number of allocated devices */
        n_devs = i;
index fa35639..453dbbd 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 #include <linux/slab.h>
 #include <media/v4l2-common.h>
@@ -127,7 +126,7 @@ struct w9966 {
 MODULE_AUTHOR("Jakob Kemi <jakob.kemi@post.utfors.se>");
 MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)");
 MODULE_LICENSE("GPL");
-
+MODULE_VERSION("0.33.1");
 
 #ifdef MODULE
 static const char *pardev[] = {[0 ... W9966_MAXCAMS] = ""};
@@ -568,7 +567,6 @@ static int cam_querycap(struct file *file, void  *priv,
        strlcpy(vcap->driver, cam->v4l2_dev.name, sizeof(vcap->driver));
        strlcpy(vcap->card, W9966_DRIVERNAME, sizeof(vcap->card));
        strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
-       vcap->version = KERNEL_VERSION(0, 33, 0);
        vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
        return 0;
 }
index f3f6400..d7166af 100644 (file)
@@ -41,10 +41,6 @@ struct zoran_sync {
 };
 
 
-#define MAJOR_VERSION 0                /* driver major version */
-#define MINOR_VERSION 10       /* driver minor version */
-#define RELEASE_VERSION 0      /* release version */
-
 #define ZORAN_NAME    "ZORAN"  /* name of the device */
 
 #define ZR_DEVNAME(zr) ((zr)->name)
index 79b04ac..c3602d6 100644 (file)
@@ -123,9 +123,12 @@ int zr36067_debug = 1;
 module_param_named(debug, zr36067_debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level (0-5)");
 
+#define ZORAN_VERSION "0.10.1"
+
 MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver");
 MODULE_AUTHOR("Serguei Miridonov");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(ZORAN_VERSION);
 
 #define ZR_DEVICE(subven, subdev, data)        { \
        .vendor = PCI_VENDOR_ID_ZORAN, .device = PCI_DEVICE_ID_ZORAN_36057, \
@@ -1459,8 +1462,8 @@ static int __init zoran_init(void)
 {
        int res;
 
-       printk(KERN_INFO "Zoran MJPEG board driver version %d.%d.%d\n",
-              MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION);
+       printk(KERN_INFO "Zoran MJPEG board driver version %s\n",
+              ZORAN_VERSION);
 
        /* check the parameters we have been given, adjust if necessary */
        if (v4l_nbufs < 2)
index 2771d81..d4d05d2 100644 (file)
@@ -44,7 +44,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -1538,8 +1537,6 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability
        strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
        snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
                 pci_name(zr->pci_dev));
-       cap->version = KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION,
-                          RELEASE_VERSION);
        cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
                            V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY;
        return 0;
index 7dfb01e..c492846 100644 (file)
@@ -29,7 +29,6 @@
 
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/usb.h>
 #include <linux/vmalloc.h>
@@ -42,8 +41,7 @@
 
 
 /* Version Information */
-#define DRIVER_VERSION "v0.73"
-#define ZR364XX_VERSION_CODE KERNEL_VERSION(0, 7, 3)
+#define DRIVER_VERSION "0.7.4"
 #define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
 #define DRIVER_DESC "Zoran 364xx"
 
@@ -744,7 +742,6 @@ static int zr364xx_vidioc_querycap(struct file *file, void *priv,
        strlcpy(cap->card, cam->udev->product, sizeof(cap->card));
        strlcpy(cap->bus_info, dev_name(&cam->udev->dev),
                sizeof(cap->bus_info));
-       cap->version = ZR364XX_VERSION_CODE;
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
                            V4L2_CAP_READWRITE |
                            V4L2_CAP_STREAMING;
@@ -1721,3 +1718,4 @@ module_exit(zr364xx_exit);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
index a1d4ee6..ce61a57 100644 (file)
@@ -827,7 +827,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                 * DID_SOFT_ERROR is set.
                                 */
                                if (ioc->bus_type == SPI) {
-                                       if (pScsiReq->CDB[0] == READ_6  ||
+                                       if ((pScsiReq->CDB[0] == READ_6  && ((pScsiReq->CDB[1] & 0x02) == 0)) ||
                                            pScsiReq->CDB[0] == READ_10 ||
                                            pScsiReq->CDB[0] == READ_12 ||
                                            pScsiReq->CDB[0] == READ_16 ||
index 37b83eb..21574bd 100644 (file)
@@ -171,6 +171,37 @@ config MFD_TPS6586X
          This driver can also be built as a module.  If so, the module
          will be called tps6586x.
 
+config MFD_TPS65910
+       bool "TPS65910 Power Management chip"
+       depends on I2C=y && GPIOLIB
+       select MFD_CORE
+       select GPIO_TPS65910
+       help
+         if you say yes here you get support for the TPS65910 series of
+         Power Management chips.
+
+config MFD_TPS65912
+       bool
+       depends on GPIOLIB
+
+config MFD_TPS65912_I2C
+       bool "TPS95612 Power Management chip with I2C"
+       select MFD_CORE
+       select MFD_TPS65912
+       depends on I2C=y && GPIOLIB
+       help
+         If you say yes here you get support for the TPS65912 series of
+         PM chips with I2C interface.
+
+config MFD_TPS65912_SPI
+       bool "TPS65912 Power Management chip with SPI"
+       select MFD_CORE
+       select MFD_TPS65912
+       depends on SPI_MASTER && GPIOLIB
+       help
+         If you say yes here you get support for the TPS65912 series of
+         PM chips with SPI interface.
+
 config MENELAUS
        bool "Texas Instruments TWL92330/Menelaus PM chip"
        depends on I2C=y && ARCH_OMAP2
@@ -662,8 +693,9 @@ config MFD_JANZ_CMODIO
          CAN and GPIO controllers.
 
 config MFD_JZ4740_ADC
-       tristate "Support for the JZ4740 SoC ADC core"
+       bool "Support for the JZ4740 SoC ADC core"
        select MFD_CORE
+       select GENERIC_IRQ_CHIP
        depends on MACH_JZ4740
        help
          Say yes here if you want support for the ADC unit in the JZ4740 SoC.
@@ -725,18 +757,19 @@ config MFD_PM8XXX_IRQ
          This is required to use certain other PM 8xxx features, such as GPIO
          and MPP.
 
-config MFD_TPS65910
-       bool "TPS65910 Power Management chip"
-       depends on I2C=y && GPIOLIB
-       select MFD_CORE
-       select GPIO_TPS65910
-       help
-         if you say yes here you get support for the TPS65910 series of
-         Power Management chips.
-
 config TPS65911_COMPARATOR
        tristate
 
+config MFD_AAT2870_CORE
+       bool "Support for the AnalogicTech AAT2870"
+       select MFD_CORE
+       depends on I2C=y && GPIOLIB
+       help
+         If you say yes here you get support for the AAT2870.
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the
+         functionality of the device.
+
 endif # MFD_SUPPORT
 
 menu "Multimedia Capabilities Port drivers"
index 22a280f..c580203 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_MFD_TC6393XB)    += tc6393xb.o tmio_core.o
 
 obj-$(CONFIG_MFD_WM8400)       += wm8400-core.o
 wm831x-objs                    := wm831x-core.o wm831x-irq.o wm831x-otp.o
+wm831x-objs                    += wm831x-auxadc.o
 obj-$(CONFIG_MFD_WM831X)       += wm831x.o
 obj-$(CONFIG_MFD_WM831X_I2C)   += wm831x-i2c.o
 obj-$(CONFIG_MFD_WM831X_SPI)   += wm831x-spi.o
@@ -35,6 +36,11 @@ obj-$(CONFIG_MFD_WM8994)     += wm8994-core.o wm8994-irq.o
 obj-$(CONFIG_TPS6105X)         += tps6105x.o
 obj-$(CONFIG_TPS65010)         += tps65010.o
 obj-$(CONFIG_TPS6507X)         += tps6507x.o
+obj-$(CONFIG_MFD_TPS65910)     += tps65910.o tps65910-irq.o
+tps65912-objs                   := tps65912-core.o tps65912-irq.o
+obj-$(CONFIG_MFD_TPS65912)     += tps65912.o
+obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o
+obj-$(CONFIG_MFD_TPS65912_SPI)  += tps65912-spi.o
 obj-$(CONFIG_MENELAUS)         += menelaus.o
 
 obj-$(CONFIG_TWL4030_CORE)     += twl-core.o twl4030-irq.o twl6030-irq.o
@@ -94,5 +100,5 @@ obj-$(CONFIG_MFD_CS5535)     += cs5535-mfd.o
 obj-$(CONFIG_MFD_OMAP_USB_HOST)        += omap-usb-host.o
 obj-$(CONFIG_MFD_PM8921_CORE)  += pm8921-core.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ)   += pm8xxx-irq.o
-obj-$(CONFIG_MFD_TPS65910)     += tps65910.o tps65910-irq.o
 obj-$(CONFIG_TPS65911_COMPARATOR)      += tps65911-comparator.o
+obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c
new file mode 100644 (file)
index 0000000..345dc65
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * linux/drivers/mfd/aat2870-core.c
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ * Author: Jin Park <jinyoungp@nvidia.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/aat2870.h>
+#include <linux/regulator/machine.h>
+
+static struct aat2870_register aat2870_regs[AAT2870_REG_NUM] = {
+       /* readable, writeable, value */
+       { 0, 1, 0x00 }, /* 0x00 AAT2870_BL_CH_EN */
+       { 0, 1, 0x16 }, /* 0x01 AAT2870_BLM */
+       { 0, 1, 0x16 }, /* 0x02 AAT2870_BLS */
+       { 0, 1, 0x56 }, /* 0x03 AAT2870_BL1 */
+       { 0, 1, 0x56 }, /* 0x04 AAT2870_BL2 */
+       { 0, 1, 0x56 }, /* 0x05 AAT2870_BL3 */
+       { 0, 1, 0x56 }, /* 0x06 AAT2870_BL4 */
+       { 0, 1, 0x56 }, /* 0x07 AAT2870_BL5 */
+       { 0, 1, 0x56 }, /* 0x08 AAT2870_BL6 */
+       { 0, 1, 0x56 }, /* 0x09 AAT2870_BL7 */
+       { 0, 1, 0x56 }, /* 0x0A AAT2870_BL8 */
+       { 0, 1, 0x00 }, /* 0x0B AAT2870_FLR */
+       { 0, 1, 0x03 }, /* 0x0C AAT2870_FM */
+       { 0, 1, 0x03 }, /* 0x0D AAT2870_FS */
+       { 0, 1, 0x10 }, /* 0x0E AAT2870_ALS_CFG0 */
+       { 0, 1, 0x06 }, /* 0x0F AAT2870_ALS_CFG1 */
+       { 0, 1, 0x00 }, /* 0x10 AAT2870_ALS_CFG2 */
+       { 1, 0, 0x00 }, /* 0x11 AAT2870_AMB */
+       { 0, 1, 0x00 }, /* 0x12 AAT2870_ALS0 */
+       { 0, 1, 0x00 }, /* 0x13 AAT2870_ALS1 */
+       { 0, 1, 0x00 }, /* 0x14 AAT2870_ALS2 */
+       { 0, 1, 0x00 }, /* 0x15 AAT2870_ALS3 */
+       { 0, 1, 0x00 }, /* 0x16 AAT2870_ALS4 */
+       { 0, 1, 0x00 }, /* 0x17 AAT2870_ALS5 */
+       { 0, 1, 0x00 }, /* 0x18 AAT2870_ALS6 */
+       { 0, 1, 0x00 }, /* 0x19 AAT2870_ALS7 */
+       { 0, 1, 0x00 }, /* 0x1A AAT2870_ALS8 */
+       { 0, 1, 0x00 }, /* 0x1B AAT2870_ALS9 */
+       { 0, 1, 0x00 }, /* 0x1C AAT2870_ALSA */
+       { 0, 1, 0x00 }, /* 0x1D AAT2870_ALSB */
+       { 0, 1, 0x00 }, /* 0x1E AAT2870_ALSC */
+       { 0, 1, 0x00 }, /* 0x1F AAT2870_ALSD */
+       { 0, 1, 0x00 }, /* 0x20 AAT2870_ALSE */
+       { 0, 1, 0x00 }, /* 0x21 AAT2870_ALSF */
+       { 0, 1, 0x00 }, /* 0x22 AAT2870_SUB_SET */
+       { 0, 1, 0x00 }, /* 0x23 AAT2870_SUB_CTRL */
+       { 0, 1, 0x00 }, /* 0x24 AAT2870_LDO_AB */
+       { 0, 1, 0x00 }, /* 0x25 AAT2870_LDO_CD */
+       { 0, 1, 0x00 }, /* 0x26 AAT2870_LDO_EN */
+};
+
+static struct mfd_cell aat2870_devs[] = {
+       {
+               .name = "aat2870-backlight",
+               .id = AAT2870_ID_BL,
+               .pdata_size = sizeof(struct aat2870_bl_platform_data),
+       },
+       {
+               .name = "aat2870-regulator",
+               .id = AAT2870_ID_LDOA,
+               .pdata_size = sizeof(struct regulator_init_data),
+       },
+       {
+               .name = "aat2870-regulator",
+               .id = AAT2870_ID_LDOB,
+               .pdata_size = sizeof(struct regulator_init_data),
+       },
+       {
+               .name = "aat2870-regulator",
+               .id = AAT2870_ID_LDOC,
+               .pdata_size = sizeof(struct regulator_init_data),
+       },
+       {
+               .name = "aat2870-regulator",
+               .id = AAT2870_ID_LDOD,
+               .pdata_size = sizeof(struct regulator_init_data),
+       },
+};
+
+static int __aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val)
+{
+       int ret;
+
+       if (addr >= AAT2870_REG_NUM) {
+               dev_err(aat2870->dev, "Invalid address, 0x%02x\n", addr);
+               return -EINVAL;
+       }
+
+       if (!aat2870->reg_cache[addr].readable) {
+               *val = aat2870->reg_cache[addr].value;
+               goto out;
+       }
+
+       ret = i2c_master_send(aat2870->client, &addr, 1);
+       if (ret < 0)
+               return ret;
+       if (ret != 1)
+               return -EIO;
+
+       ret = i2c_master_recv(aat2870->client, val, 1);
+       if (ret < 0)
+               return ret;
+       if (ret != 1)
+               return -EIO;
+
+out:
+       dev_dbg(aat2870->dev, "read: addr=0x%02x, val=0x%02x\n", addr, *val);
+       return 0;
+}
+
+static int __aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val)
+{
+       u8 msg[2];
+       int ret;
+
+       if (addr >= AAT2870_REG_NUM) {
+               dev_err(aat2870->dev, "Invalid address, 0x%02x\n", addr);
+               return -EINVAL;
+       }
+
+       if (!aat2870->reg_cache[addr].writeable) {
+               dev_err(aat2870->dev, "Address 0x%02x is not writeable\n",
+                       addr);
+               return -EINVAL;
+       }
+
+       msg[0] = addr;
+       msg[1] = val;
+       ret = i2c_master_send(aat2870->client, msg, 2);
+       if (ret < 0)
+               return ret;
+       if (ret != 2)
+               return -EIO;
+
+       aat2870->reg_cache[addr].value = val;
+
+       dev_dbg(aat2870->dev, "write: addr=0x%02x, val=0x%02x\n", addr, val);
+       return 0;
+}
+
+static int aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val)
+{
+       int ret;
+
+       mutex_lock(&aat2870->io_lock);
+       ret = __aat2870_read(aat2870, addr, val);
+       mutex_unlock(&aat2870->io_lock);
+
+       return ret;
+}
+
+static int aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val)
+{
+       int ret;
+
+       mutex_lock(&aat2870->io_lock);
+       ret = __aat2870_write(aat2870, addr, val);
+       mutex_unlock(&aat2870->io_lock);
+
+       return ret;
+}
+
+static int aat2870_update(struct aat2870_data *aat2870, u8 addr, u8 mask,
+                         u8 val)
+{
+       int change;
+       u8 old_val, new_val;
+       int ret;
+
+       mutex_lock(&aat2870->io_lock);
+
+       ret = __aat2870_read(aat2870, addr, &old_val);
+       if (ret)
+               goto out_unlock;
+
+       new_val = (old_val & ~mask) | (val & mask);
+       change = old_val != new_val;
+       if (change)
+               ret = __aat2870_write(aat2870, addr, new_val);
+
+out_unlock:
+       mutex_unlock(&aat2870->io_lock);
+
+       return ret;
+}
+
+static inline void aat2870_enable(struct aat2870_data *aat2870)
+{
+       if (aat2870->en_pin >= 0)
+               gpio_set_value(aat2870->en_pin, 1);
+
+       aat2870->is_enable = 1;
+}
+
+static inline void aat2870_disable(struct aat2870_data *aat2870)
+{
+       if (aat2870->en_pin >= 0)
+               gpio_set_value(aat2870->en_pin, 0);
+
+       aat2870->is_enable = 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static ssize_t aat2870_dump_reg(struct aat2870_data *aat2870, char *buf)
+{
+       u8 addr, val;
+       ssize_t count = 0;
+       int ret;
+
+       count += sprintf(buf, "aat2870 registers\n");
+       for (addr = 0; addr < AAT2870_REG_NUM; addr++) {
+               count += sprintf(buf + count, "0x%02x: ", addr);
+               if (count >= PAGE_SIZE - 1)
+                       break;
+
+               ret = aat2870->read(aat2870, addr, &val);
+               if (ret == 0)
+                       count += snprintf(buf + count, PAGE_SIZE - count,
+                                         "0x%02x", val);
+               else
+                       count += snprintf(buf + count, PAGE_SIZE - count,
+                                         "<read fail: %d>", ret);
+
+               if (count >= PAGE_SIZE - 1)
+                       break;
+
+               count += snprintf(buf + count, PAGE_SIZE - count, "\n");
+               if (count >= PAGE_SIZE - 1)
+                       break;
+       }
+
+       /* Truncate count; min() would cause a warning */
+       if (count >= PAGE_SIZE)
+               count = PAGE_SIZE - 1;
+
+       return count;
+}
+
+static int aat2870_reg_open_file(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+
+       return 0;
+}
+
+static ssize_t aat2870_reg_read_file(struct file *file, char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       struct aat2870_data *aat2870 = file->private_data;
+       char *buf;
+       ssize_t ret;
+
+       buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       ret = aat2870_dump_reg(aat2870, buf);
+       if (ret >= 0)
+               ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+
+       kfree(buf);
+
+       return ret;
+}
+
+static ssize_t aat2870_reg_write_file(struct file *file,
+                                     const char __user *user_buf, size_t count,
+                                     loff_t *ppos)
+{
+       struct aat2870_data *aat2870 = file->private_data;
+       char buf[32];
+       int buf_size;
+       char *start = buf;
+       unsigned long addr, val;
+       int ret;
+
+       buf_size = min(count, (sizeof(buf)-1));
+       if (copy_from_user(buf, user_buf, buf_size)) {
+               dev_err(aat2870->dev, "Failed to copy from user\n");
+               return -EFAULT;
+       }
+       buf[buf_size] = 0;
+
+       while (*start == ' ')
+               start++;
+
+       addr = simple_strtoul(start, &start, 16);
+       if (addr >= AAT2870_REG_NUM) {
+               dev_err(aat2870->dev, "Invalid address, 0x%lx\n", addr);
+               return -EINVAL;
+       }
+
+       while (*start == ' ')
+               start++;
+
+       if (strict_strtoul(start, 16, &val))
+               return -EINVAL;
+
+       ret = aat2870->write(aat2870, (u8)addr, (u8)val);
+       if (ret)
+               return ret;
+
+       return buf_size;
+}
+
+static const struct file_operations aat2870_reg_fops = {
+       .open = aat2870_reg_open_file,
+       .read = aat2870_reg_read_file,
+       .write = aat2870_reg_write_file,
+};
+
+static void aat2870_init_debugfs(struct aat2870_data *aat2870)
+{
+       aat2870->dentry_root = debugfs_create_dir("aat2870", NULL);
+       if (!aat2870->dentry_root) {
+               dev_warn(aat2870->dev,
+                        "Failed to create debugfs root directory\n");
+               return;
+       }
+
+       aat2870->dentry_reg = debugfs_create_file("regs", 0644,
+                                                 aat2870->dentry_root,
+                                                 aat2870, &aat2870_reg_fops);
+       if (!aat2870->dentry_reg)
+               dev_warn(aat2870->dev,
+                        "Failed to create debugfs register file\n");
+}
+
+static void aat2870_uninit_debugfs(struct aat2870_data *aat2870)
+{
+       debugfs_remove_recursive(aat2870->dentry_root);
+}
+#else
+static inline void aat2870_init_debugfs(struct aat2870_data *aat2870)
+{
+}
+
+static inline void aat2870_uninit_debugfs(struct aat2870_data *aat2870)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static int aat2870_i2c_probe(struct i2c_client *client,
+                            const struct i2c_device_id *id)
+{
+       struct aat2870_platform_data *pdata = client->dev.platform_data;
+       struct aat2870_data *aat2870;
+       int i, j;
+       int ret = 0;
+
+       aat2870 = kzalloc(sizeof(struct aat2870_data), GFP_KERNEL);
+       if (!aat2870) {
+               dev_err(&client->dev,
+                       "Failed to allocate memory for aat2870\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       aat2870->dev = &client->dev;
+       dev_set_drvdata(aat2870->dev, aat2870);
+
+       aat2870->client = client;
+       i2c_set_clientdata(client, aat2870);
+
+       aat2870->reg_cache = aat2870_regs;
+
+       if (pdata->en_pin < 0)
+               aat2870->en_pin = -1;
+       else
+               aat2870->en_pin = pdata->en_pin;
+
+       aat2870->init = pdata->init;
+       aat2870->uninit = pdata->uninit;
+       aat2870->read = aat2870_read;
+       aat2870->write = aat2870_write;
+       aat2870->update = aat2870_update;
+
+       mutex_init(&aat2870->io_lock);
+
+       if (aat2870->init)
+               aat2870->init(aat2870);
+
+       if (aat2870->en_pin >= 0) {
+               ret = gpio_request(aat2870->en_pin, "aat2870-en");
+               if (ret < 0) {
+                       dev_err(&client->dev,
+                               "Failed to request GPIO %d\n", aat2870->en_pin);
+                       goto out_kfree;
+               }
+               gpio_direction_output(aat2870->en_pin, 1);
+       }
+
+       aat2870_enable(aat2870);
+
+       for (i = 0; i < pdata->num_subdevs; i++) {
+               for (j = 0; j < ARRAY_SIZE(aat2870_devs); j++) {
+                       if ((pdata->subdevs[i].id == aat2870_devs[j].id) &&
+                                       !strcmp(pdata->subdevs[i].name,
+                                               aat2870_devs[j].name)) {
+                               aat2870_devs[j].platform_data =
+                                       pdata->subdevs[i].platform_data;
+                               break;
+                       }
+               }
+       }
+
+       ret = mfd_add_devices(aat2870->dev, 0, aat2870_devs,
+                             ARRAY_SIZE(aat2870_devs), NULL, 0);
+       if (ret != 0) {
+               dev_err(aat2870->dev, "Failed to add subdev: %d\n", ret);
+               goto out_disable;
+       }
+
+       aat2870_init_debugfs(aat2870);
+
+       return 0;
+
+out_disable:
+       aat2870_disable(aat2870);
+       if (aat2870->en_pin >= 0)
+               gpio_free(aat2870->en_pin);
+out_kfree:
+       kfree(aat2870);
+out:
+       return ret;
+}
+
+static int aat2870_i2c_remove(struct i2c_client *client)
+{
+       struct aat2870_data *aat2870 = i2c_get_clientdata(client);
+
+       aat2870_uninit_debugfs(aat2870);
+
+       mfd_remove_devices(aat2870->dev);
+       aat2870_disable(aat2870);
+       if (aat2870->en_pin >= 0)
+               gpio_free(aat2870->en_pin);
+       if (aat2870->uninit)
+               aat2870->uninit(aat2870);
+       kfree(aat2870);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int aat2870_i2c_suspend(struct i2c_client *client, pm_message_t state)
+{
+       struct aat2870_data *aat2870 = i2c_get_clientdata(client);
+
+       aat2870_disable(aat2870);
+
+       return 0;
+}
+
+static int aat2870_i2c_resume(struct i2c_client *client)
+{
+       struct aat2870_data *aat2870 = i2c_get_clientdata(client);
+       struct aat2870_register *reg = NULL;
+       int i;
+
+       aat2870_enable(aat2870);
+
+       /* restore registers */
+       for (i = 0; i < AAT2870_REG_NUM; i++) {
+               reg = &aat2870->reg_cache[i];
+               if (reg->writeable)
+                       aat2870->write(aat2870, i, reg->value);
+       }
+
+       return 0;
+}
+#else
+#define aat2870_i2c_suspend    NULL
+#define aat2870_i2c_resume     NULL
+#endif /* CONFIG_PM */
+
+static struct i2c_device_id aat2870_i2c_id_table[] = {
+       { "aat2870", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, aat2870_i2c_id_table);
+
+static struct i2c_driver aat2870_i2c_driver = {
+       .driver = {
+               .name   = "aat2870",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = aat2870_i2c_probe,
+       .remove         = aat2870_i2c_remove,
+       .suspend        = aat2870_i2c_suspend,
+       .resume         = aat2870_i2c_resume,
+       .id_table       = aat2870_i2c_id_table,
+};
+
+static int __init aat2870_init(void)
+{
+       return i2c_add_driver(&aat2870_i2c_driver);
+}
+subsys_initcall(aat2870_init);
+
+static void __exit aat2870_exit(void)
+{
+       i2c_del_driver(&aat2870_i2c_driver);
+}
+module_exit(aat2870_exit);
+
+MODULE_DESCRIPTION("Core support for the AnalogicTech AAT2870");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");
index 3d7dce6..56ba194 100644 (file)
@@ -879,20 +879,13 @@ static ssize_t ab3550_bank_write(struct file *file,
        size_t count, loff_t *ppos)
 {
        struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
        unsigned long user_bank;
        int err;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf) - 1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
-
-       err = strict_strtoul(buf, 0, &user_bank);
+       err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
        if (err)
-               return -EINVAL;
+               return err;
 
        if (user_bank >= AB3550_NUM_BANKS) {
                dev_err(&ab->i2c_client[0]->dev,
@@ -902,7 +895,7 @@ static ssize_t ab3550_bank_write(struct file *file,
 
        ab->debug_bank = user_bank;
 
-       return buf_size;
+       return count;
 }
 
 static int ab3550_address_print(struct seq_file *s, void *p)
@@ -923,27 +916,21 @@ static ssize_t ab3550_address_write(struct file *file,
        size_t count, loff_t *ppos)
 {
        struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
        unsigned long user_address;
        int err;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf) - 1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
-
-       err = strict_strtoul(buf, 0, &user_address);
+       err = kstrtoul_from_user(user_buf, count, 0, &user_address);
        if (err)
-               return -EINVAL;
+               return err;
+
        if (user_address > 0xff) {
                dev_err(&ab->i2c_client[0]->dev,
                        "debugfs error input > 0xff\n");
                return -EINVAL;
        }
        ab->debug_address = user_address;
-       return buf_size;
+       return count;
 }
 
 static int ab3550_val_print(struct seq_file *s, void *p)
@@ -971,21 +958,15 @@ static ssize_t ab3550_val_write(struct file *file,
        size_t count, loff_t *ppos)
 {
        struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
        unsigned long user_val;
        int err;
        u8 regvalue;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf)-1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
-
-       err = strict_strtoul(buf, 0, &user_val);
+       err = kstrtoul_from_user(user_buf, count, 0, &user_val);
        if (err)
-               return -EINVAL;
+               return err;
+
        if (user_val > 0xff) {
                dev_err(&ab->i2c_client[0]->dev,
                        "debugfs error input > 0xff\n");
@@ -1002,7 +983,7 @@ static ssize_t ab3550_val_write(struct file *file,
        if (err)
                return -EINVAL;
 
-       return buf_size;
+       return count;
 }
 
 static const struct file_operations ab3550_bank_fops = {
index fc0c1af..387705e 100644 (file)
@@ -363,7 +363,7 @@ static void ab8500_irq_remove(struct ab8500 *ab8500)
        }
 }
 
-static struct resource ab8500_gpio_resources[] = {
+static struct resource __devinitdata ab8500_gpio_resources[] = {
        {
                .name   = "GPIO_INT6",
                .start  = AB8500_INT_GPIO6R,
@@ -372,7 +372,7 @@ static struct resource ab8500_gpio_resources[] = {
        }
 };
 
-static struct resource ab8500_gpadc_resources[] = {
+static struct resource __devinitdata ab8500_gpadc_resources[] = {
        {
                .name   = "HW_CONV_END",
                .start  = AB8500_INT_GP_HW_ADC_CONV_END,
@@ -387,7 +387,7 @@ static struct resource ab8500_gpadc_resources[] = {
        },
 };
 
-static struct resource ab8500_rtc_resources[] = {
+static struct resource __devinitdata ab8500_rtc_resources[] = {
        {
                .name   = "60S",
                .start  = AB8500_INT_RTC_60S,
@@ -402,7 +402,7 @@ static struct resource ab8500_rtc_resources[] = {
        },
 };
 
-static struct resource ab8500_poweronkey_db_resources[] = {
+static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
        {
                .name   = "ONKEY_DBF",
                .start  = AB8500_INT_PON_KEY1DB_F,
@@ -417,19 +417,46 @@ static struct resource ab8500_poweronkey_db_resources[] = {
        },
 };
 
-static struct resource ab8500_bm_resources[] = {
+static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
        {
-               .name = "MAIN_EXT_CH_NOT_OK",
-               .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
-               .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
-               .flags = IORESOURCE_IRQ,
+              .name = "ACC_DETECT_1DB_F",
+              .start = AB8500_INT_ACC_DETECT_1DB_F,
+              .end = AB8500_INT_ACC_DETECT_1DB_F,
+              .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "BATT_OVV",
-               .start = AB8500_INT_BATT_OVV,
-               .end = AB8500_INT_BATT_OVV,
-               .flags = IORESOURCE_IRQ,
+              .name = "ACC_DETECT_1DB_R",
+              .start = AB8500_INT_ACC_DETECT_1DB_R,
+              .end = AB8500_INT_ACC_DETECT_1DB_R,
+              .flags = IORESOURCE_IRQ,
+       },
+       {
+              .name = "ACC_DETECT_21DB_F",
+              .start = AB8500_INT_ACC_DETECT_21DB_F,
+              .end = AB8500_INT_ACC_DETECT_21DB_F,
+              .flags = IORESOURCE_IRQ,
+       },
+       {
+              .name = "ACC_DETECT_21DB_R",
+              .start = AB8500_INT_ACC_DETECT_21DB_R,
+              .end = AB8500_INT_ACC_DETECT_21DB_R,
+              .flags = IORESOURCE_IRQ,
+       },
+       {
+              .name = "ACC_DETECT_22DB_F",
+              .start = AB8500_INT_ACC_DETECT_22DB_F,
+              .end = AB8500_INT_ACC_DETECT_22DB_F,
+              .flags = IORESOURCE_IRQ,
        },
+       {
+              .name = "ACC_DETECT_22DB_R",
+              .start = AB8500_INT_ACC_DETECT_22DB_R,
+              .end = AB8500_INT_ACC_DETECT_22DB_R,
+              .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource __devinitdata ab8500_charger_resources[] = {
        {
                .name = "MAIN_CH_UNPLUG_DET",
                .start = AB8500_INT_MAIN_CH_UNPLUG_DET,
@@ -442,12 +469,6 @@ static struct resource ab8500_bm_resources[] = {
                .end = AB8500_INT_MAIN_CH_PLUG_DET,
                .flags = IORESOURCE_IRQ,
        },
-       {
-               .name = "VBUS_DET_F",
-               .start = AB8500_INT_VBUS_DET_F,
-               .end = AB8500_INT_VBUS_DET_F,
-               .flags = IORESOURCE_IRQ,
-       },
        {
                .name = "VBUS_DET_R",
                .start = AB8500_INT_VBUS_DET_R,
@@ -455,15 +476,21 @@ static struct resource ab8500_bm_resources[] = {
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "BAT_CTRL_INDB",
-               .start = AB8500_INT_BAT_CTRL_INDB,
-               .end = AB8500_INT_BAT_CTRL_INDB,
+               .name = "VBUS_DET_F",
+               .start = AB8500_INT_VBUS_DET_F,
+               .end = AB8500_INT_VBUS_DET_F,
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "CH_WD_EXP",
-               .start = AB8500_INT_CH_WD_EXP,
-               .end = AB8500_INT_CH_WD_EXP,
+               .name = "USB_LINK_STATUS",
+               .start = AB8500_INT_USB_LINK_STATUS,
+               .end = AB8500_INT_USB_LINK_STATUS,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "USB_CHARGE_DET_DONE",
+               .start = AB8500_INT_USB_CHG_DET_DONE,
+               .end = AB8500_INT_USB_CHG_DET_DONE,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -473,21 +500,60 @@ static struct resource ab8500_bm_resources[] = {
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "NCONV_ACCU",
-               .start = AB8500_INT_CCN_CONV_ACC,
-               .end = AB8500_INT_CCN_CONV_ACC,
+               .name = "USB_CH_TH_PROT_R",
+               .start = AB8500_INT_USB_CH_TH_PROT_R,
+               .end = AB8500_INT_USB_CH_TH_PROT_R,
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "LOW_BAT_F",
-               .start = AB8500_INT_LOW_BAT_F,
-               .end = AB8500_INT_LOW_BAT_F,
+               .name = "USB_CH_TH_PROT_F",
+               .start = AB8500_INT_USB_CH_TH_PROT_F,
+               .end = AB8500_INT_USB_CH_TH_PROT_F,
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "LOW_BAT_R",
-               .start = AB8500_INT_LOW_BAT_R,
-               .end = AB8500_INT_LOW_BAT_R,
+               .name = "MAIN_EXT_CH_NOT_OK",
+               .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
+               .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "MAIN_CH_TH_PROT_R",
+               .start = AB8500_INT_MAIN_CH_TH_PROT_R,
+               .end = AB8500_INT_MAIN_CH_TH_PROT_R,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "MAIN_CH_TH_PROT_F",
+               .start = AB8500_INT_MAIN_CH_TH_PROT_F,
+               .end = AB8500_INT_MAIN_CH_TH_PROT_F,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "USB_CHARGER_NOT_OKR",
+               .start = AB8500_INT_USB_CHARGER_NOT_OK,
+               .end = AB8500_INT_USB_CHARGER_NOT_OK,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "USB_CHARGER_NOT_OKF",
+               .start = AB8500_INT_USB_CHARGER_NOT_OKF,
+               .end = AB8500_INT_USB_CHARGER_NOT_OKF,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "CH_WD_EXP",
+               .start = AB8500_INT_CH_WD_EXP,
+               .end = AB8500_INT_CH_WD_EXP,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource __devinitdata ab8500_btemp_resources[] = {
+       {
+               .name = "BAT_CTRL_INDB",
+               .start = AB8500_INT_BAT_CTRL_INDB,
+               .end = AB8500_INT_BAT_CTRL_INDB,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -503,38 +569,55 @@ static struct resource ab8500_bm_resources[] = {
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "USB_CHARGER_NOT_OKR",
-               .start = AB8500_INT_USB_CHARGER_NOT_OK,
-               .end = AB8500_INT_USB_CHARGER_NOT_OK,
+               .name = "BTEMP_LOW_MEDIUM",
+               .start = AB8500_INT_BTEMP_LOW_MEDIUM,
+               .end = AB8500_INT_BTEMP_LOW_MEDIUM,
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "USB_CHARGE_DET_DONE",
-               .start = AB8500_INT_USB_CHG_DET_DONE,
-               .end = AB8500_INT_USB_CHG_DET_DONE,
+               .name = "BTEMP_MEDIUM_HIGH",
+               .start = AB8500_INT_BTEMP_MEDIUM_HIGH,
+               .end = AB8500_INT_BTEMP_MEDIUM_HIGH,
                .flags = IORESOURCE_IRQ,
        },
+};
+
+static struct resource __devinitdata ab8500_fg_resources[] = {
        {
-               .name = "USB_CH_TH_PROT_R",
-               .start = AB8500_INT_USB_CH_TH_PROT_R,
-               .end = AB8500_INT_USB_CH_TH_PROT_R,
+               .name = "NCONV_ACCU",
+               .start = AB8500_INT_CCN_CONV_ACC,
+               .end = AB8500_INT_CCN_CONV_ACC,
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "MAIN_CH_TH_PROT_R",
-               .start = AB8500_INT_MAIN_CH_TH_PROT_R,
-               .end = AB8500_INT_MAIN_CH_TH_PROT_R,
+               .name = "BATT_OVV",
+               .start = AB8500_INT_BATT_OVV,
+               .end = AB8500_INT_BATT_OVV,
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "USB_CHARGER_NOT_OKF",
-               .start = AB8500_INT_USB_CHARGER_NOT_OKF,
-               .end = AB8500_INT_USB_CHARGER_NOT_OKF,
+               .name = "LOW_BAT_F",
+               .start = AB8500_INT_LOW_BAT_F,
+               .end = AB8500_INT_LOW_BAT_F,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "LOW_BAT_R",
+               .start = AB8500_INT_LOW_BAT_R,
+               .end = AB8500_INT_LOW_BAT_R,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "CC_INT_CALIB",
+               .start = AB8500_INT_CC_INT_CALIB,
+               .end = AB8500_INT_CC_INT_CALIB,
                .flags = IORESOURCE_IRQ,
        },
 };
 
-static struct resource ab8500_debug_resources[] = {
+static struct resource __devinitdata ab8500_chargalg_resources[] = {};
+
+static struct resource __devinitdata ab8500_debug_resources[] = {
        {
                .name   = "IRQ_FIRST",
                .start  = AB8500_INT_MAIN_EXT_CH_NOT_OK,
@@ -549,7 +632,7 @@ static struct resource ab8500_debug_resources[] = {
        },
 };
 
-static struct resource ab8500_usb_resources[] = {
+static struct resource __devinitdata ab8500_usb_resources[] = {
        {
                .name = "ID_WAKEUP_R",
                .start = AB8500_INT_ID_WAKEUP_R,
@@ -580,9 +663,21 @@ static struct resource ab8500_usb_resources[] = {
                .end = AB8500_INT_USB_LINK_STATUS,
                .flags = IORESOURCE_IRQ,
        },
+       {
+               .name = "USB_ADP_PROBE_PLUG",
+               .start = AB8500_INT_ADP_PROBE_PLUG,
+               .end = AB8500_INT_ADP_PROBE_PLUG,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "USB_ADP_PROBE_UNPLUG",
+               .start = AB8500_INT_ADP_PROBE_UNPLUG,
+               .end = AB8500_INT_ADP_PROBE_UNPLUG,
+               .flags = IORESOURCE_IRQ,
+       },
 };
 
-static struct resource ab8500_temp_resources[] = {
+static struct resource __devinitdata ab8500_temp_resources[] = {
        {
                .name  = "AB8500_TEMP_WARM",
                .start = AB8500_INT_TEMP_WARM,
@@ -591,7 +686,7 @@ static struct resource ab8500_temp_resources[] = {
        },
 };
 
-static struct mfd_cell ab8500_devs[] = {
+static struct mfd_cell __devinitdata ab8500_devs[] = {
 #ifdef CONFIG_DEBUG_FS
        {
                .name = "ab8500-debug",
@@ -621,11 +716,33 @@ static struct mfd_cell ab8500_devs[] = {
                .resources = ab8500_rtc_resources,
        },
        {
-               .name = "ab8500-bm",
-               .num_resources = ARRAY_SIZE(ab8500_bm_resources),
-               .resources = ab8500_bm_resources,
+               .name = "ab8500-charger",
+               .num_resources = ARRAY_SIZE(ab8500_charger_resources),
+               .resources = ab8500_charger_resources,
+       },
+       {
+               .name = "ab8500-btemp",
+               .num_resources = ARRAY_SIZE(ab8500_btemp_resources),
+               .resources = ab8500_btemp_resources,
+       },
+       {
+               .name = "ab8500-fg",
+               .num_resources = ARRAY_SIZE(ab8500_fg_resources),
+               .resources = ab8500_fg_resources,
+       },
+       {
+               .name = "ab8500-chargalg",
+               .num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
+               .resources = ab8500_chargalg_resources,
+       },
+       {
+               .name = "ab8500-acc-det",
+               .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
+               .resources = ab8500_av_acc_detect_resources,
+       },
+       {
+               .name = "ab8500-codec",
        },
-       { .name = "ab8500-codec", },
        {
                .name = "ab8500-usb",
                .num_resources = ARRAY_SIZE(ab8500_usb_resources),
index 64748e4..64bdeeb 100644 (file)
@@ -419,20 +419,13 @@ static ssize_t ab8500_bank_write(struct file *file,
        size_t count, loff_t *ppos)
 {
        struct device *dev = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
        unsigned long user_bank;
        int err;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf) - 1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
-
-       err = strict_strtoul(buf, 0, &user_bank);
+       err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
        if (err)
-               return -EINVAL;
+               return err;
 
        if (user_bank >= AB8500_NUM_BANKS) {
                dev_err(dev, "debugfs error input > number of banks\n");
@@ -441,7 +434,7 @@ static ssize_t ab8500_bank_write(struct file *file,
 
        debug_bank = user_bank;
 
-       return buf_size;
+       return count;
 }
 
 static int ab8500_address_print(struct seq_file *s, void *p)
@@ -459,26 +452,20 @@ static ssize_t ab8500_address_write(struct file *file,
        size_t count, loff_t *ppos)
 {
        struct device *dev = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
        unsigned long user_address;
        int err;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf) - 1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
-
-       err = strict_strtoul(buf, 0, &user_address);
+       err = kstrtoul_from_user(user_buf, count, 0, &user_address);
        if (err)
-               return -EINVAL;
+               return err;
+
        if (user_address > 0xff) {
                dev_err(dev, "debugfs error input > 0xff\n");
                return -EINVAL;
        }
        debug_address = user_address;
-       return buf_size;
+       return count;
 }
 
 static int ab8500_val_print(struct seq_file *s, void *p)
@@ -509,20 +496,14 @@ static ssize_t ab8500_val_write(struct file *file,
        size_t count, loff_t *ppos)
 {
        struct device *dev = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
        unsigned long user_val;
        int err;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf)-1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
-
-       err = strict_strtoul(buf, 0, &user_val);
+       err = kstrtoul_from_user(user_buf, count, 0, &user_val);
        if (err)
-               return -EINVAL;
+               return err;
+
        if (user_val > 0xff) {
                dev_err(dev, "debugfs error input > 0xff\n");
                return -EINVAL;
@@ -534,7 +515,7 @@ static ssize_t ab8500_val_write(struct file *file,
                return -EINVAL;
        }
 
-       return buf_size;
+       return count;
 }
 
 static const struct file_operations ab8500_bank_fops = {
index a0bd0cf..21131c7 100644 (file)
@@ -56,7 +56,7 @@ struct jz4740_adc {
        void __iomem *base;
 
        int irq;
-       int irq_base;
+       struct irq_chip_generic *gc;
 
        struct clk *clk;
        atomic_t clk_ref;
@@ -64,63 +64,17 @@ struct jz4740_adc {
        spinlock_t lock;
 };
 
-static inline void jz4740_adc_irq_set_masked(struct jz4740_adc *adc, int irq,
-       bool masked)
-{
-       unsigned long flags;
-       uint8_t val;
-
-       irq -= adc->irq_base;
-
-       spin_lock_irqsave(&adc->lock, flags);
-
-       val = readb(adc->base + JZ_REG_ADC_CTRL);
-       if (masked)
-               val |= BIT(irq);
-       else
-               val &= ~BIT(irq);
-       writeb(val, adc->base + JZ_REG_ADC_CTRL);
-
-       spin_unlock_irqrestore(&adc->lock, flags);
-}
-
-static void jz4740_adc_irq_mask(struct irq_data *data)
-{
-       struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
-       jz4740_adc_irq_set_masked(adc, data->irq, true);
-}
-
-static void jz4740_adc_irq_unmask(struct irq_data *data)
-{
-       struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
-       jz4740_adc_irq_set_masked(adc, data->irq, false);
-}
-
-static void jz4740_adc_irq_ack(struct irq_data *data)
-{
-       struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
-       unsigned int irq = data->irq - adc->irq_base;
-       writeb(BIT(irq), adc->base + JZ_REG_ADC_STATUS);
-}
-
-static struct irq_chip jz4740_adc_irq_chip = {
-       .name = "jz4740-adc",
-       .irq_mask = jz4740_adc_irq_mask,
-       .irq_unmask = jz4740_adc_irq_unmask,
-       .irq_ack = jz4740_adc_irq_ack,
-};
-
 static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-       struct jz4740_adc *adc = irq_desc_get_handler_data(desc);
+       struct irq_chip_generic *gc = irq_desc_get_handler_data(desc);
        uint8_t status;
        unsigned int i;
 
-       status = readb(adc->base + JZ_REG_ADC_STATUS);
+       status = readb(gc->reg_base + JZ_REG_ADC_STATUS);
 
        for (i = 0; i < 5; ++i) {
                if (status & BIT(i))
-                       generic_handle_irq(adc->irq_base + i);
+                       generic_handle_irq(gc->irq_base + i);
        }
 }
 
@@ -249,10 +203,12 @@ const struct mfd_cell jz4740_adc_cells[] = {
 
 static int __devinit jz4740_adc_probe(struct platform_device *pdev)
 {
-       int ret;
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
        struct jz4740_adc *adc;
        struct resource *mem_base;
-       int irq;
+       int ret;
+       int irq_base;
 
        adc = kmalloc(sizeof(*adc), GFP_KERNEL);
        if (!adc) {
@@ -267,9 +223,9 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)
                goto err_free;
        }
 
-       adc->irq_base = platform_get_irq(pdev, 1);
-       if (adc->irq_base < 0) {
-               ret = adc->irq_base;
+       irq_base = platform_get_irq(pdev, 1);
+       if (irq_base < 0) {
+               ret = irq_base;
                dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret);
                goto err_free;
        }
@@ -309,20 +265,28 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, adc);
 
-       for (irq = adc->irq_base; irq < adc->irq_base + 5; ++irq) {
-               irq_set_chip_data(irq, adc);
-               irq_set_chip_and_handler(irq, &jz4740_adc_irq_chip,
-                                        handle_level_irq);
-       }
+       gc = irq_alloc_generic_chip("INTC", 1, irq_base, adc->base,
+               handle_level_irq);
+
+       ct = gc->chip_types;
+       ct->regs.mask = JZ_REG_ADC_CTRL;
+       ct->regs.ack = JZ_REG_ADC_STATUS;
+       ct->chip.irq_mask = irq_gc_mask_set_bit;
+       ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+       ct->chip.irq_ack = irq_gc_ack;
+
+       irq_setup_generic_chip(gc, IRQ_MSK(5), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
+
+       adc->gc = gc;
 
-       irq_set_handler_data(adc->irq, adc);
+       irq_set_handler_data(adc->irq, gc);
        irq_set_chained_handler(adc->irq, jz4740_adc_irq_demux);
 
        writeb(0x00, adc->base + JZ_REG_ADC_ENABLE);
        writeb(0xff, adc->base + JZ_REG_ADC_CTRL);
 
        ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells,
-               ARRAY_SIZE(jz4740_adc_cells), mem_base, adc->irq_base);
+               ARRAY_SIZE(jz4740_adc_cells), mem_base, irq_base);
        if (ret < 0)
                goto err_clk_put;
 
@@ -347,6 +311,8 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev)
 
        mfd_remove_devices(&pdev->dev);
 
+       irq_remove_generic_chip(adc->gc, IRQ_MSK(5), IRQ_NOPROBE | IRQ_LEVEL, 0);
+       kfree(adc->gc);
        irq_set_handler_data(adc->irq, NULL);
        irq_set_chained_handler(adc->irq, NULL);
 
index ea3f52c..ea1169b 100644 (file)
@@ -37,6 +37,9 @@
 #define GPIOBASE       0x44
 #define GPIO_IO_SIZE   64
 
+#define WDTBASE                0x84
+#define WDT_IO_SIZE    64
+
 static struct resource smbus_sch_resource = {
                .flags = IORESOURCE_IO,
 };
@@ -59,6 +62,18 @@ static struct mfd_cell lpc_sch_cells[] = {
        },
 };
 
+static struct resource wdt_sch_resource = {
+               .flags = IORESOURCE_IO,
+};
+
+static struct mfd_cell tunnelcreek_cells[] = {
+       {
+               .name = "tunnelcreek_wdt",
+               .num_resources = 1,
+               .resources = &wdt_sch_resource,
+       },
+};
+
 static struct pci_device_id lpc_sch_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) },
@@ -72,6 +87,7 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
        unsigned int base_addr_cfg;
        unsigned short base_addr;
        int i;
+       int ret;
 
        pci_read_config_dword(dev, SMBASE, &base_addr_cfg);
        if (!(base_addr_cfg & (1 << 31))) {
@@ -104,8 +120,39 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
        for (i=0; i < ARRAY_SIZE(lpc_sch_cells); i++)
                lpc_sch_cells[i].id = id->device;
 
-       return mfd_add_devices(&dev->dev, 0,
+       ret = mfd_add_devices(&dev->dev, 0,
                        lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0);
+       if (ret)
+               goto out_dev;
+
+       if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC) {
+               pci_read_config_dword(dev, WDTBASE, &base_addr_cfg);
+               if (!(base_addr_cfg & (1 << 31))) {
+                       dev_err(&dev->dev, "Decode of the WDT I/O range disabled\n");
+                       ret = -ENODEV;
+                       goto out_dev;
+               }
+               base_addr = (unsigned short)base_addr_cfg;
+               if (base_addr == 0) {
+                       dev_err(&dev->dev, "I/O space for WDT uninitialized\n");
+                       ret = -ENODEV;
+                       goto out_dev;
+               }
+
+               wdt_sch_resource.start = base_addr;
+               wdt_sch_resource.end = base_addr + WDT_IO_SIZE - 1;
+
+               for (i = 0; i < ARRAY_SIZE(tunnelcreek_cells); i++)
+                       tunnelcreek_cells[i].id = id->device;
+
+               ret = mfd_add_devices(&dev->dev, 0, tunnelcreek_cells,
+                       ARRAY_SIZE(tunnelcreek_cells), NULL, 0);
+       }
+
+       return ret;
+out_dev:
+       mfd_remove_devices(&dev->dev);
+       return ret;
 }
 
 static void __devexit lpc_sch_remove(struct pci_dev *dev)
index 638bf7e..09274cf 100644 (file)
@@ -58,8 +58,6 @@ static struct i2c_client *get_i2c(struct max8997_dev *max8997,
        default:
                return ERR_PTR(-EINVAL);
        }
-
-       return ERR_PTR(-EINVAL);
 }
 
 struct max8997_irq_data {
index 9ec7570..de4096a 100644 (file)
@@ -39,6 +39,8 @@ static struct mfd_cell max8998_devs[] = {
                .name = "max8998-pmic",
        }, {
                .name = "max8998-rtc",
+       }, {
+               .name = "max8998-battery",
        },
 };
 
index 1717144..29601e7 100644 (file)
@@ -998,9 +998,9 @@ static void usbhs_disable(struct device *dev)
 
        if (is_omap_usbhs_rev2(omap)) {
                if (is_ehci_tll_mode(pdata->port_mode[0]))
-                       clk_enable(omap->usbtll_p1_fck);
+                       clk_disable(omap->usbtll_p1_fck);
                if (is_ehci_tll_mode(pdata->port_mode[1]))
-                       clk_enable(omap->usbtll_p2_fck);
+                       clk_disable(omap->usbtll_p2_fck);
                clk_disable(omap->utmi_p2_fck);
                clk_disable(omap->utmi_p1_fck);
        }
index 7ab7746..2963689 100644 (file)
@@ -228,7 +228,7 @@ int stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length,
 EXPORT_SYMBOL_GPL(stmpe_block_write);
 
 /**
- * stmpe_set_altfunc: set the alternate function for STMPE pins
+ * stmpe_set_altfunc()- set the alternate function for STMPE pins
  * @stmpe:     Device to configure
  * @pins:      Bitmask of pins to affect
  * @block:     block to enable alternate functions for
index 0dbdc4e..e4ee389 100644 (file)
@@ -42,6 +42,7 @@ struct stmpe_variant_block {
  * @id_mask:   bits valid in CHIPID register for comparison with id_val
  * @num_gpios: number of GPIOS
  * @af_bits:   number of bits used to specify the alternate function
+ * @regs: variant specific registers.
  * @blocks:    list of blocks present on this device
  * @num_blocks:        number of blocks present on this device
  * @num_irqs:  number of internal IRQs available on this device
index 69272e4..696879e 100644 (file)
@@ -287,12 +287,8 @@ static __devinitdata struct i2c_board_info timberdale_saa7706_i2c_board_info = {
 static __devinitdata struct timb_radio_platform_data
        timberdale_radio_platform_data = {
        .i2c_adapter = 0,
-       .tuner = {
-               .info = &timberdale_tef6868_i2c_board_info
-       },
-       .dsp = {
-               .info = &timberdale_saa7706_i2c_board_info
-       }
+       .tuner = &timberdale_tef6868_i2c_board_info,
+       .dsp = &timberdale_saa7706_i2c_board_info
 };
 
 static const __devinitconst struct resource timberdale_video_resources[] = {
index 2229e66..6f5b8cf 100644 (file)
@@ -147,12 +147,11 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
        if (init_data == NULL)
                return -ENOMEM;
 
-       init_data->irq = pmic_plat_data->irq;
-       init_data->irq_base = pmic_plat_data->irq;
-
        tps65910 = kzalloc(sizeof(struct tps65910), GFP_KERNEL);
-       if (tps65910 == NULL)
+       if (tps65910 == NULL) {
+               kfree(init_data);
                return -ENOMEM;
+       }
 
        i2c_set_clientdata(i2c, tps65910);
        tps65910->dev = &i2c->dev;
@@ -168,17 +167,22 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
        if (ret < 0)
                goto err;
 
+       init_data->irq = pmic_plat_data->irq;
+       init_data->irq_base = pmic_plat_data->irq;
+
        tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base);
 
        ret = tps65910_irq_init(tps65910, init_data->irq, init_data);
        if (ret < 0)
                goto err;
 
+       kfree(init_data);
        return ret;
 
 err:
        mfd_remove_devices(tps65910->dev);
        kfree(tps65910);
+       kfree(init_data);
        return ret;
 }
 
@@ -187,6 +191,7 @@ static int tps65910_i2c_remove(struct i2c_client *i2c)
        struct tps65910 *tps65910 = i2c_get_clientdata(i2c);
 
        mfd_remove_devices(tps65910->dev);
+       tps65910_irq_exit(tps65910);
        kfree(tps65910);
 
        return 0;
index 283ac67..e7ff783 100644 (file)
@@ -157,6 +157,8 @@ static __devexit int tps65911_comparator_remove(struct platform_device *pdev)
        struct tps65910 *tps65910;
 
        tps65910 = dev_get_drvdata(pdev->dev.parent);
+       device_remove_file(&pdev->dev, &dev_attr_comp2_threshold);
+       device_remove_file(&pdev->dev, &dev_attr_comp1_threshold);
 
        return 0;
 }
diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c
new file mode 100644 (file)
index 0000000..955bc00
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * tps65912-core.c  --  TI TPS65912x
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk>
+ *
+ *  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 driver is based on wm8350 implementation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65912.h>
+
+static struct mfd_cell tps65912s[] = {
+       {
+               .name = "tps65912-pmic",
+       },
+};
+
+int tps65912_set_bits(struct tps65912 *tps65912, u8 reg, u8 mask)
+{
+       u8 data;
+       int err;
+
+       mutex_lock(&tps65912->io_mutex);
+
+       err = tps65912->read(tps65912, reg, 1, &data);
+       if (err) {
+               dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg);
+               goto out;
+       }
+
+       data |= mask;
+       err = tps65912->write(tps65912, reg, 1, &data);
+       if (err)
+               dev_err(tps65912->dev, "Write to reg 0x%x failed\n", reg);
+
+out:
+       mutex_unlock(&tps65912->io_mutex);
+       return err;
+}
+EXPORT_SYMBOL_GPL(tps65912_set_bits);
+
+int tps65912_clear_bits(struct tps65912 *tps65912, u8 reg, u8 mask)
+{
+       u8 data;
+       int err;
+
+       mutex_lock(&tps65912->io_mutex);
+       err = tps65912->read(tps65912, reg, 1, &data);
+       if (err) {
+               dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg);
+               goto out;
+       }
+
+       data &= ~mask;
+       err = tps65912->write(tps65912, reg, 1, &data);
+       if (err)
+               dev_err(tps65912->dev, "Write to reg 0x%x failed\n", reg);
+
+out:
+       mutex_unlock(&tps65912->io_mutex);
+       return err;
+}
+EXPORT_SYMBOL_GPL(tps65912_clear_bits);
+
+static inline int tps65912_read(struct tps65912 *tps65912, u8 reg)
+{
+       u8 val;
+       int err;
+
+       err = tps65912->read(tps65912, reg, 1, &val);
+       if (err < 0)
+               return err;
+
+       return val;
+}
+
+static inline int tps65912_write(struct tps65912 *tps65912, u8 reg, u8 val)
+{
+       return tps65912->write(tps65912, reg, 1, &val);
+}
+
+int tps65912_reg_read(struct tps65912 *tps65912, u8 reg)
+{
+       int data;
+
+       mutex_lock(&tps65912->io_mutex);
+
+       data = tps65912_read(tps65912, reg);
+       if (data < 0)
+               dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg);
+
+       mutex_unlock(&tps65912->io_mutex);
+       return data;
+}
+EXPORT_SYMBOL_GPL(tps65912_reg_read);
+
+int tps65912_reg_write(struct tps65912 *tps65912, u8 reg, u8 val)
+{
+       int err;
+
+       mutex_lock(&tps65912->io_mutex);
+
+       err = tps65912_write(tps65912, reg, val);
+       if (err < 0)
+               dev_err(tps65912->dev, "Write for reg 0x%x failed\n", reg);
+
+       mutex_unlock(&tps65912->io_mutex);
+       return err;
+}
+EXPORT_SYMBOL_GPL(tps65912_reg_write);
+
+int tps65912_device_init(struct tps65912 *tps65912)
+{
+       struct tps65912_board *pmic_plat_data = tps65912->dev->platform_data;
+       struct tps65912_platform_data *init_data;
+       int ret, dcdc_avs, value;
+
+       init_data = kzalloc(sizeof(struct tps65912_platform_data), GFP_KERNEL);
+       if (init_data == NULL)
+               return -ENOMEM;
+
+       init_data->irq = pmic_plat_data->irq;
+       init_data->irq_base = pmic_plat_data->irq;
+
+       mutex_init(&tps65912->io_mutex);
+       dev_set_drvdata(tps65912->dev, tps65912);
+
+       dcdc_avs = (pmic_plat_data->is_dcdc1_avs << 0 |
+                       pmic_plat_data->is_dcdc2_avs  << 1 |
+                               pmic_plat_data->is_dcdc3_avs << 2 |
+                                       pmic_plat_data->is_dcdc4_avs << 3);
+       if (dcdc_avs) {
+               tps65912->read(tps65912, TPS65912_I2C_SPI_CFG, 1, &value);
+               dcdc_avs |= value;
+               tps65912->write(tps65912, TPS65912_I2C_SPI_CFG, 1, &dcdc_avs);
+       }
+
+       ret = mfd_add_devices(tps65912->dev, -1,
+                             tps65912s, ARRAY_SIZE(tps65912s),
+                             NULL, 0);
+       if (ret < 0)
+               goto err;
+
+       ret = tps65912_irq_init(tps65912, init_data->irq, init_data);
+       if (ret < 0)
+               goto err;
+
+       return ret;
+
+err:
+       kfree(init_data);
+       mfd_remove_devices(tps65912->dev);
+       kfree(tps65912);
+       return ret;
+}
+
+void tps65912_device_exit(struct tps65912 *tps65912)
+{
+       mfd_remove_devices(tps65912->dev);
+       kfree(tps65912);
+}
+
+MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>");
+MODULE_DESCRIPTION("TPS65912x chip family multi-function driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tps65912-i2c.c b/drivers/mfd/tps65912-i2c.c
new file mode 100644 (file)
index 0000000..c041f2c
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * tps65912-i2c.c  --  I2C access for TI TPS65912x PMIC
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk>
+ *
+ *  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 driver is based on wm8350 implementation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65912.h>
+
+static int tps65912_i2c_read(struct tps65912 *tps65912, u8 reg,
+                                 int bytes, void *dest)
+{
+       struct i2c_client *i2c = tps65912->control_data;
+       struct i2c_msg xfer[2];
+       int ret;
+
+       /* Write register */
+       xfer[0].addr = i2c->addr;
+       xfer[0].flags = 0;
+       xfer[0].len = 1;
+       xfer[0].buf = &reg;
+
+       /* Read data */
+       xfer[1].addr = i2c->addr;
+       xfer[1].flags = I2C_M_RD;
+       xfer[1].len = bytes;
+       xfer[1].buf = dest;
+
+       ret = i2c_transfer(i2c->adapter, xfer, 2);
+       if (ret == 2)
+               ret = 0;
+       else if (ret >= 0)
+               ret = -EIO;
+       return ret;
+}
+
+static int tps65912_i2c_write(struct tps65912 *tps65912, u8 reg,
+                                  int bytes, void *src)
+{
+       struct i2c_client *i2c = tps65912->control_data;
+       /* we add 1 byte for device register */
+       u8 msg[TPS6591X_MAX_REGISTER + 1];
+       int ret;
+
+       if (bytes > TPS6591X_MAX_REGISTER)
+               return -EINVAL;
+
+       msg[0] = reg;
+       memcpy(&msg[1], src, bytes);
+
+       ret = i2c_master_send(i2c, msg, bytes + 1);
+       if (ret < 0)
+               return ret;
+       if (ret != bytes + 1)
+               return -EIO;
+
+       return 0;
+}
+
+static int tps65912_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
+{
+       struct tps65912 *tps65912;
+
+       tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL);
+       if (tps65912 == NULL)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, tps65912);
+       tps65912->dev = &i2c->dev;
+       tps65912->control_data = i2c;
+       tps65912->read = tps65912_i2c_read;
+       tps65912->write = tps65912_i2c_write;
+
+       return tps65912_device_init(tps65912);
+}
+
+static int tps65912_i2c_remove(struct i2c_client *i2c)
+{
+       struct tps65912 *tps65912 = i2c_get_clientdata(i2c);
+
+       tps65912_device_exit(tps65912);
+
+       return 0;
+}
+
+static const struct i2c_device_id tps65912_i2c_id[] = {
+       {"tps65912", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, tps65912_i2c_id);
+
+static struct i2c_driver tps65912_i2c_driver = {
+       .driver = {
+                  .name = "tps65912",
+                  .owner = THIS_MODULE,
+       },
+       .probe = tps65912_i2c_probe,
+       .remove = tps65912_i2c_remove,
+       .id_table = tps65912_i2c_id,
+};
+
+static int __init tps65912_i2c_init(void)
+{
+       int ret;
+
+       ret = i2c_add_driver(&tps65912_i2c_driver);
+       if (ret != 0)
+               pr_err("Failed to register TPS65912 I2C driver: %d\n", ret);
+
+       return ret;
+}
+/* init early so consumer devices can complete system boot */
+subsys_initcall(tps65912_i2c_init);
+
+static void __exit tps65912_i2c_exit(void)
+{
+       i2c_del_driver(&tps65912_i2c_driver);
+}
+module_exit(tps65912_i2c_exit);
+
+MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>");
+MODULE_DESCRIPTION("TPS6591x chip family multi-function driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tps65912-irq.c b/drivers/mfd/tps65912-irq.c
new file mode 100644 (file)
index 0000000..d360a83
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * tps65912-irq.c  --  TI TPS6591x
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya <magi@slimlogic.co.uk>
+ *
+ *  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 driver is based on wm8350 implementation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/mfd/tps65912.h>
+
+static inline int irq_to_tps65912_irq(struct tps65912 *tps65912,
+                                                       int irq)
+{
+       return irq - tps65912->irq_base;
+}
+
+/*
+ * This is a threaded IRQ handler so can access I2C/SPI.  Since the
+ * IRQ handler explicitly clears the IRQ it handles the IRQ line
+ * will be reasserted and the physical IRQ will be handled again if
+ * another interrupt is asserted while we run - in the normal course
+ * of events this is a rare occurrence so we save I2C/SPI reads. We're
+ * also assuming that it's rare to get lots of interrupts firing
+ * simultaneously so try to minimise I/O.
+ */
+static irqreturn_t tps65912_irq(int irq, void *irq_data)
+{
+       struct tps65912 *tps65912 = irq_data;
+       u32 irq_sts;
+       u32 irq_mask;
+       u8 reg;
+       int i;
+
+
+       tps65912->read(tps65912, TPS65912_INT_STS, 1, &reg);
+       irq_sts = reg;
+       tps65912->read(tps65912, TPS65912_INT_STS2, 1, &reg);
+       irq_sts |= reg << 8;
+       tps65912->read(tps65912, TPS65912_INT_STS3, 1, &reg);
+       irq_sts |= reg << 16;
+       tps65912->read(tps65912, TPS65912_INT_STS4, 1, &reg);
+       irq_sts |= reg << 24;
+
+       tps65912->read(tps65912, TPS65912_INT_MSK, 1, &reg);
+       irq_mask = reg;
+       tps65912->read(tps65912, TPS65912_INT_MSK2, 1, &reg);
+       irq_mask |= reg << 8;
+       tps65912->read(tps65912, TPS65912_INT_MSK3, 1, &reg);
+       irq_mask |= reg << 16;
+       tps65912->read(tps65912, TPS65912_INT_MSK4, 1, &reg);
+       irq_mask |= reg << 24;
+
+       irq_sts &= ~irq_mask;
+       if (!irq_sts)
+               return IRQ_NONE;
+
+       for (i = 0; i < tps65912->irq_num; i++) {
+               if (!(irq_sts & (1 << i)))
+                       continue;
+
+               handle_nested_irq(tps65912->irq_base + i);
+       }
+
+       /* Write the STS register back to clear IRQs we handled */
+       reg = irq_sts & 0xFF;
+       irq_sts >>= 8;
+       if (reg)
+               tps65912->write(tps65912, TPS65912_INT_STS, 1, &reg);
+       reg = irq_sts & 0xFF;
+       irq_sts >>= 8;
+       if (reg)
+               tps65912->write(tps65912, TPS65912_INT_STS2, 1, &reg);
+       reg = irq_sts & 0xFF;
+       irq_sts >>= 8;
+       if (reg)
+               tps65912->write(tps65912, TPS65912_INT_STS3, 1, &reg);
+       reg = irq_sts & 0xFF;
+       if (reg)
+               tps65912->write(tps65912, TPS65912_INT_STS4, 1, &reg);
+
+       return IRQ_HANDLED;
+}
+
+static void tps65912_irq_lock(struct irq_data *data)
+{
+       struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
+
+       mutex_lock(&tps65912->irq_lock);
+}
+
+static void tps65912_irq_sync_unlock(struct irq_data *data)
+{
+       struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
+       u32 reg_mask;
+       u8 reg;
+
+       tps65912->read(tps65912, TPS65912_INT_MSK, 1, &reg);
+       reg_mask = reg;
+       tps65912->read(tps65912, TPS65912_INT_MSK2, 1, &reg);
+       reg_mask |= reg << 8;
+       tps65912->read(tps65912, TPS65912_INT_MSK3, 1, &reg);
+       reg_mask |= reg << 16;
+       tps65912->read(tps65912, TPS65912_INT_MSK4, 1, &reg);
+       reg_mask |= reg << 24;
+
+       if (tps65912->irq_mask != reg_mask) {
+               reg = tps65912->irq_mask & 0xFF;
+               tps65912->write(tps65912, TPS65912_INT_MSK, 1, &reg);
+               reg = tps65912->irq_mask >> 8 & 0xFF;
+               tps65912->write(tps65912, TPS65912_INT_MSK2, 1, &reg);
+               reg = tps65912->irq_mask >> 16 & 0xFF;
+               tps65912->write(tps65912, TPS65912_INT_MSK3, 1, &reg);
+               reg = tps65912->irq_mask >> 24 & 0xFF;
+               tps65912->write(tps65912, TPS65912_INT_MSK4, 1, &reg);
+       }
+
+       mutex_unlock(&tps65912->irq_lock);
+}
+
+static void tps65912_irq_enable(struct irq_data *data)
+{
+       struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
+
+       tps65912->irq_mask &= ~(1 << irq_to_tps65912_irq(tps65912, data->irq));
+}
+
+static void tps65912_irq_disable(struct irq_data *data)
+{
+       struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
+
+       tps65912->irq_mask |= (1 << irq_to_tps65912_irq(tps65912, data->irq));
+}
+
+static struct irq_chip tps65912_irq_chip = {
+       .name = "tps65912",
+       .irq_bus_lock = tps65912_irq_lock,
+       .irq_bus_sync_unlock = tps65912_irq_sync_unlock,
+       .irq_disable = tps65912_irq_disable,
+       .irq_enable = tps65912_irq_enable,
+};
+
+int tps65912_irq_init(struct tps65912 *tps65912, int irq,
+                           struct tps65912_platform_data *pdata)
+{
+       int ret, cur_irq;
+       int flags = IRQF_ONESHOT;
+       u8 reg;
+
+       if (!irq) {
+               dev_warn(tps65912->dev, "No interrupt support, no core IRQ\n");
+               return 0;
+       }
+
+       if (!pdata || !pdata->irq_base) {
+               dev_warn(tps65912->dev, "No interrupt support, no IRQ base\n");
+               return 0;
+       }
+
+       /* Clear unattended interrupts */
+       tps65912->read(tps65912, TPS65912_INT_STS, 1, &reg);
+       tps65912->write(tps65912, TPS65912_INT_STS, 1, &reg);
+       tps65912->read(tps65912, TPS65912_INT_STS2, 1, &reg);
+       tps65912->write(tps65912, TPS65912_INT_STS2, 1, &reg);
+       tps65912->read(tps65912, TPS65912_INT_STS3, 1, &reg);
+       tps65912->write(tps65912, TPS65912_INT_STS3, 1, &reg);
+       tps65912->read(tps65912, TPS65912_INT_STS4, 1, &reg);
+       tps65912->write(tps65912, TPS65912_INT_STS4, 1, &reg);
+
+       /* Mask top level interrupts */
+       tps65912->irq_mask = 0xFFFFFFFF;
+
+       mutex_init(&tps65912->irq_lock);
+       tps65912->chip_irq = irq;
+       tps65912->irq_base = pdata->irq_base;
+
+       tps65912->irq_num = TPS65912_NUM_IRQ;
+
+       /* Register with genirq */
+       for (cur_irq = tps65912->irq_base;
+            cur_irq < tps65912->irq_num + tps65912->irq_base;
+            cur_irq++) {
+               irq_set_chip_data(cur_irq, tps65912);
+               irq_set_chip_and_handler(cur_irq, &tps65912_irq_chip,
+                                        handle_edge_irq);
+               irq_set_nested_thread(cur_irq, 1);
+               /* ARM needs us to explicitly flag the IRQ as valid
+                * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+               set_irq_flags(cur_irq, IRQF_VALID);
+#else
+               irq_set_noprobe(cur_irq);
+#endif
+       }
+
+       ret = request_threaded_irq(irq, NULL, tps65912_irq, flags,
+                                  "tps65912", tps65912);
+
+       irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
+       if (ret != 0)
+               dev_err(tps65912->dev, "Failed to request IRQ: %d\n", ret);
+
+       return ret;
+}
+
+int tps65912_irq_exit(struct tps65912 *tps65912)
+{
+       free_irq(tps65912->chip_irq, tps65912);
+       return 0;
+}
diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
new file mode 100644 (file)
index 0000000..6d71e0d
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * tps65912-spi.c  --  SPI access for TI TPS65912x PMIC
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk>
+ *
+ *  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 driver is based on wm8350 implementation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65912.h>
+
+static int tps65912_spi_write(struct tps65912 *tps65912, u8 addr,
+                                                       int bytes, void *src)
+{
+       struct spi_device *spi = tps65912->control_data;
+       u8 *data = (u8 *) src;
+       int ret;
+       /* bit 23 is the read/write bit */
+       unsigned long spi_data = 1 << 23 | addr << 15 | *data;
+       struct spi_transfer xfer;
+       struct spi_message msg;
+       u32 tx_buf, rx_buf;
+
+       tx_buf = spi_data;
+       rx_buf = 0;
+
+       xfer.tx_buf     = &tx_buf;
+       xfer.rx_buf     = NULL;
+       xfer.len        = sizeof(unsigned long);
+       xfer.bits_per_word = 24;
+
+       spi_message_init(&msg);
+       spi_message_add_tail(&xfer, &msg);
+
+       ret = spi_sync(spi, &msg);
+       return ret;
+}
+
+static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr,
+                                                       int bytes, void *dest)
+{
+       struct spi_device *spi = tps65912->control_data;
+       /* bit 23 is the read/write bit */
+       unsigned long spi_data = 0 << 23 | addr << 15;
+       struct spi_transfer xfer;
+       struct spi_message msg;
+       int ret;
+       u8 *data = (u8 *) dest;
+       u32 tx_buf, rx_buf;
+
+       tx_buf = spi_data;
+       rx_buf = 0;
+
+       xfer.tx_buf     = &tx_buf;
+       xfer.rx_buf     = &rx_buf;
+       xfer.len        = sizeof(unsigned long);
+       xfer.bits_per_word = 24;
+
+       spi_message_init(&msg);
+       spi_message_add_tail(&xfer, &msg);
+
+       if (spi == NULL)
+               return 0;
+
+       ret = spi_sync(spi, &msg);
+       if (ret == 0)
+               *data = (u8) (rx_buf & 0xFF);
+       return ret;
+}
+
+static int __devinit tps65912_spi_probe(struct spi_device *spi)
+{
+       struct tps65912 *tps65912;
+
+       tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL);
+       if (tps65912 == NULL)
+               return -ENOMEM;
+
+       tps65912->dev = &spi->dev;
+       tps65912->control_data = spi;
+       tps65912->read = tps65912_spi_read;
+       tps65912->write = tps65912_spi_write;
+
+       spi_set_drvdata(spi, tps65912);
+
+       return tps65912_device_init(tps65912);
+}
+
+static int __devexit tps65912_spi_remove(struct spi_device *spi)
+{
+       struct tps65912 *tps65912 = spi_get_drvdata(spi);
+
+       tps65912_device_exit(tps65912);
+
+       return 0;
+}
+
+static struct spi_driver tps65912_spi_driver = {
+       .driver = {
+               .name = "tps65912",
+               .bus = &spi_bus_type,
+               .owner = THIS_MODULE,
+       },
+       .probe  = tps65912_spi_probe,
+       .remove = __devexit_p(tps65912_spi_remove),
+};
+
+static int __init tps65912_spi_init(void)
+{
+       int ret;
+
+       ret = spi_register_driver(&tps65912_spi_driver);
+       if (ret != 0)
+               pr_err("Failed to register TPS65912 SPI driver: %d\n", ret);
+
+       return 0;
+}
+/* init early so consumer devices can complete system boot */
+subsys_initcall(tps65912_spi_init);
+
+static void __exit tps65912_spi_exit(void)
+{
+       spi_unregister_driver(&tps65912_spi_driver);
+}
+module_exit(tps65912_spi_exit);
+
+MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>");
+MODULE_DESCRIPTION("SPI support for TPS65912 chip family mfd");
+MODULE_LICENSE("GPL");
index a2eddc7..01ecfee 100644 (file)
@@ -1283,6 +1283,8 @@ static const struct i2c_device_id twl_ids[] = {
        { "tps65950", 0 },              /* catalog version of twl5030 */
        { "tps65930", TPS_SUBSET },     /* fewer LDOs and DACs; no charger */
        { "tps65920", TPS_SUBSET },     /* fewer LDOs; no codec or charger */
+       { "tps65921", TPS_SUBSET },     /* fewer LDOs; no codec, no LED
+                                          and vibrator. Charger in USB module*/
        { "twl6030", TWL6030_CLASS },   /* "Phoenix power chip" */
        { "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */
        { /* end of list */ },
index 3941ddc..b5d598c 100644 (file)
@@ -530,13 +530,13 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
        if (ret) {
                dev_err(twl4030_madc->dev,
                        "unable to write sel register 0x%X\n", method->sel + 1);
-               return ret;
+               goto out;
        }
        ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_lsb, method->sel);
        if (ret) {
                dev_err(twl4030_madc->dev,
                        "unable to write sel register 0x%X\n", method->sel + 1);
-               return ret;
+               goto out;
        }
        /* Select averaging for all channels if do_avg is set */
        if (req->do_avg) {
@@ -546,7 +546,7 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
                        dev_err(twl4030_madc->dev,
                                "unable to write avg register 0x%X\n",
                                method->avg + 1);
-                       return ret;
+                       goto out;
                }
                ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
                                       ch_lsb, method->avg);
@@ -554,7 +554,7 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
                        dev_err(twl4030_madc->dev,
                                "unable to write sel reg 0x%X\n",
                                method->sel + 1);
-                       return ret;
+                       goto out;
                }
        }
        if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
index 5d25bdc..e8fee14 100644 (file)
@@ -161,3 +161,5 @@ void pwm_free(struct pwm_device *pwm)
        kfree(pwm);
 }
 EXPORT_SYMBOL(pwm_free);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/wm831x-auxadc.c b/drivers/mfd/wm831x-auxadc.c
new file mode 100644 (file)
index 0000000..8721095
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * wm831x-auxadc.c  --  AUXADC for Wolfson WM831x PMICs
+ *
+ * Copyright 2009-2011 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mfd/core.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/auxadc.h>
+#include <linux/mfd/wm831x/otp.h>
+#include <linux/mfd/wm831x/regulator.h>
+
+struct wm831x_auxadc_req {
+       struct list_head list;
+       enum wm831x_auxadc input;
+       int val;
+       struct completion done;
+};
+
+static int wm831x_auxadc_read_irq(struct wm831x *wm831x,
+                                 enum wm831x_auxadc input)
+{
+       struct wm831x_auxadc_req *req;
+       int ret;
+       bool ena = false;
+
+       req = kzalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+
+       init_completion(&req->done);
+       req->input = input;
+       req->val = -ETIMEDOUT;
+
+       mutex_lock(&wm831x->auxadc_lock);
+
+       /* Enqueue the request */
+       list_add(&req->list, &wm831x->auxadc_pending);
+
+       ena = !wm831x->auxadc_active;
+
+       if (ena) {
+               ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
+                                     WM831X_AUX_ENA, WM831X_AUX_ENA);
+               if (ret != 0) {
+                       dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n",
+                               ret);
+                       goto out;
+               }
+       }
+
+       /* Enable the conversion if not already running */
+       if (!(wm831x->auxadc_active & (1 << input))) {
+               ret = wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE,
+                                     1 << input, 1 << input);
+               if (ret != 0) {
+                       dev_err(wm831x->dev,
+                               "Failed to set AUXADC source: %d\n", ret);
+                       goto out;
+               }
+
+               wm831x->auxadc_active |= 1 << input;
+       }
+
+       /* We convert at the fastest rate possible */
+       if (ena) {
+               ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
+                                     WM831X_AUX_CVT_ENA |
+                                     WM831X_AUX_RATE_MASK,
+                                     WM831X_AUX_CVT_ENA |
+                                     WM831X_AUX_RATE_MASK);
+               if (ret != 0) {
+                       dev_err(wm831x->dev, "Failed to start AUXADC: %d\n",
+                               ret);
+                       goto out;
+               }
+       }
+
+       mutex_unlock(&wm831x->auxadc_lock);
+
+       /* Wait for an interrupt */
+       wait_for_completion_timeout(&req->done, msecs_to_jiffies(500));
+
+       mutex_lock(&wm831x->auxadc_lock);
+
+       list_del(&req->list);
+       ret = req->val;
+
+out:
+       mutex_unlock(&wm831x->auxadc_lock);
+
+       kfree(req);
+
+       return ret;
+}
+
+static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
+{
+       struct wm831x *wm831x = irq_data;
+       struct wm831x_auxadc_req *req;
+       int ret, input, val;
+
+       ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
+       if (ret < 0) {
+               dev_err(wm831x->dev,
+                       "Failed to read AUXADC data: %d\n", ret);
+               return IRQ_NONE;
+       }
+
+       input = ((ret & WM831X_AUX_DATA_SRC_MASK)
+                >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
+
+       if (input == 14)
+               input = WM831X_AUX_CAL;
+
+       val = ret & WM831X_AUX_DATA_MASK;
+
+       mutex_lock(&wm831x->auxadc_lock);
+
+       /* Disable this conversion, we're about to complete all users */
+       wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE,
+                       1 << input, 0);
+       wm831x->auxadc_active &= ~(1 << input);
+
+       /* Turn off the entire convertor if idle */
+       if (!wm831x->auxadc_active)
+               wm831x_reg_write(wm831x, WM831X_AUXADC_CONTROL, 0);
+
+       /* Wake up any threads waiting for this request */
+       list_for_each_entry(req, &wm831x->auxadc_pending, list) {
+               if (req->input == input) {
+                       req->val = val;
+                       complete(&req->done);
+               }
+       }
+
+       mutex_unlock(&wm831x->auxadc_lock);
+
+       return IRQ_HANDLED;
+}
+
+static int wm831x_auxadc_read_polled(struct wm831x *wm831x,
+                                    enum wm831x_auxadc input)
+{
+       int ret, src, timeout;
+
+       mutex_lock(&wm831x->auxadc_lock);
+
+       ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
+                             WM831X_AUX_ENA, WM831X_AUX_ENA);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", ret);
+               goto out;
+       }
+
+       /* We force a single source at present */
+       src = input;
+       ret = wm831x_reg_write(wm831x, WM831X_AUXADC_SOURCE,
+                              1 << src);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to set AUXADC source: %d\n", ret);
+               goto out;
+       }
+
+       ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
+                             WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", ret);
+               goto disable;
+       }
+
+       /* If we're not using interrupts then poll the
+        * interrupt status register */
+       timeout = 5;
+       while (timeout) {
+               msleep(1);
+
+               ret = wm831x_reg_read(wm831x,
+                                     WM831X_INTERRUPT_STATUS_1);
+               if (ret < 0) {
+                       dev_err(wm831x->dev,
+                               "ISR 1 read failed: %d\n", ret);
+                       goto disable;
+               }
+
+               /* Did it complete? */
+               if (ret & WM831X_AUXADC_DATA_EINT) {
+                       wm831x_reg_write(wm831x,
+                                        WM831X_INTERRUPT_STATUS_1,
+                                        WM831X_AUXADC_DATA_EINT);
+                       break;
+               } else {
+                       dev_err(wm831x->dev,
+                               "AUXADC conversion timeout\n");
+                       ret = -EBUSY;
+                       goto disable;
+               }
+       }
+
+       ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
+       if (ret < 0) {
+               dev_err(wm831x->dev,
+                       "Failed to read AUXADC data: %d\n", ret);
+               goto disable;
+       }
+
+       src = ((ret & WM831X_AUX_DATA_SRC_MASK)
+              >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
+
+       if (src == 14)
+               src = WM831X_AUX_CAL;
+
+       if (src != input) {
+               dev_err(wm831x->dev, "Data from source %d not %d\n",
+                       src, input);
+               ret = -EINVAL;
+       } else {
+               ret &= WM831X_AUX_DATA_MASK;
+       }
+
+disable:
+       wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, WM831X_AUX_ENA, 0);
+out:
+       mutex_unlock(&wm831x->auxadc_lock);
+       return ret;
+}
+
+/**
+ * wm831x_auxadc_read: Read a value from the WM831x AUXADC
+ *
+ * @wm831x: Device to read from.
+ * @input: AUXADC input to read.
+ */
+int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
+{
+       return wm831x->auxadc_read(wm831x, input);
+}
+EXPORT_SYMBOL_GPL(wm831x_auxadc_read);
+
+/**
+ * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC
+ *
+ * @wm831x: Device to read from.
+ * @input: AUXADC input to read.
+ */
+int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input)
+{
+       int ret;
+
+       ret = wm831x_auxadc_read(wm831x, input);
+       if (ret < 0)
+               return ret;
+
+       ret *= 1465;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm831x_auxadc_read_uv);
+
+void wm831x_auxadc_init(struct wm831x *wm831x)
+{
+       int ret;
+
+       mutex_init(&wm831x->auxadc_lock);
+       INIT_LIST_HEAD(&wm831x->auxadc_pending);
+
+       if (wm831x->irq && wm831x->irq_base) {
+               wm831x->auxadc_read = wm831x_auxadc_read_irq;
+
+               ret = request_threaded_irq(wm831x->irq_base +
+                                          WM831X_IRQ_AUXADC_DATA,
+                                          NULL, wm831x_auxadc_irq, 0,
+                                          "auxadc", wm831x);
+               if (ret < 0) {
+                       dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n",
+                               ret);
+                       wm831x->auxadc_read = NULL;
+               }
+       }
+
+       if (!wm831x->auxadc_read)
+               wm831x->auxadc_read = wm831x_auxadc_read_polled;
+}
index 265f75f..282e76a 100644 (file)
@@ -295,7 +295,7 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
                goto out;
 
        r &= ~mask;
-       r |= val;
+       r |= val & mask;
 
        ret = wm831x_write(wm831x, reg, 2, &r);
 
@@ -306,146 +306,6 @@ out:
 }
 EXPORT_SYMBOL_GPL(wm831x_set_bits);
 
-/**
- * wm831x_auxadc_read: Read a value from the WM831x AUXADC
- *
- * @wm831x: Device to read from.
- * @input: AUXADC input to read.
- */
-int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
-{
-       int ret, src, irq_masked, timeout;
-
-       /* Are we using the interrupt? */
-       irq_masked = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_1_MASK);
-       irq_masked &= WM831X_AUXADC_DATA_EINT;
-
-       mutex_lock(&wm831x->auxadc_lock);
-
-       ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
-                             WM831X_AUX_ENA, WM831X_AUX_ENA);
-       if (ret < 0) {
-               dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", ret);
-               goto out;
-       }
-
-       /* We force a single source at present */
-       src = input;
-       ret = wm831x_reg_write(wm831x, WM831X_AUXADC_SOURCE,
-                              1 << src);
-       if (ret < 0) {
-               dev_err(wm831x->dev, "Failed to set AUXADC source: %d\n", ret);
-               goto out;
-       }
-
-       /* Clear any notification from a very late arriving interrupt */
-       try_wait_for_completion(&wm831x->auxadc_done);
-
-       ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
-                             WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA);
-       if (ret < 0) {
-               dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", ret);
-               goto disable;
-       }
-
-       if (irq_masked) {
-               /* If we're not using interrupts then poll the
-                * interrupt status register */
-               timeout = 5;
-               while (timeout) {
-                       msleep(1);
-
-                       ret = wm831x_reg_read(wm831x,
-                                             WM831X_INTERRUPT_STATUS_1);
-                       if (ret < 0) {
-                               dev_err(wm831x->dev,
-                                       "ISR 1 read failed: %d\n", ret);
-                               goto disable;
-                       }
-
-                       /* Did it complete? */
-                       if (ret & WM831X_AUXADC_DATA_EINT) {
-                               wm831x_reg_write(wm831x,
-                                                WM831X_INTERRUPT_STATUS_1,
-                                                WM831X_AUXADC_DATA_EINT);
-                               break;
-                       } else {
-                               dev_err(wm831x->dev,
-                                       "AUXADC conversion timeout\n");
-                               ret = -EBUSY;
-                               goto disable;
-                       }
-               }
-       } else {
-               /* If we are using interrupts then wait for the
-                * interrupt to complete.  Use an extremely long
-                * timeout to handle situations with heavy load where
-                * the notification of the interrupt may be delayed by
-                * threaded IRQ handling. */
-               if (!wait_for_completion_timeout(&wm831x->auxadc_done,
-                                                msecs_to_jiffies(500))) {
-                       dev_err(wm831x->dev, "Timed out waiting for AUXADC\n");
-                       ret = -EBUSY;
-                       goto disable;
-               }
-       }
-
-       ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
-       if (ret < 0) {
-               dev_err(wm831x->dev, "Failed to read AUXADC data: %d\n", ret);
-       } else {
-               src = ((ret & WM831X_AUX_DATA_SRC_MASK)
-                      >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
-
-               if (src == 14)
-                       src = WM831X_AUX_CAL;
-
-               if (src != input) {
-                       dev_err(wm831x->dev, "Data from source %d not %d\n",
-                               src, input);
-                       ret = -EINVAL;
-               } else {
-                       ret &= WM831X_AUX_DATA_MASK;
-               }
-       }
-
-disable:
-       wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, WM831X_AUX_ENA, 0);
-out:
-       mutex_unlock(&wm831x->auxadc_lock);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(wm831x_auxadc_read);
-
-static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
-{
-       struct wm831x *wm831x = irq_data;
-
-       complete(&wm831x->auxadc_done);
-
-       return IRQ_HANDLED;
-}
-
-/**
- * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC
- *
- * @wm831x: Device to read from.
- * @input: AUXADC input to read.
- */
-int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input)
-{
-       int ret;
-
-       ret = wm831x_auxadc_read(wm831x, input);
-       if (ret < 0)
-               return ret;
-
-       ret *= 1465;
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(wm831x_auxadc_read_uv);
-
 static struct resource wm831x_dcdc1_resources[] = {
        {
                .start = WM831X_DC1_CONTROL_1,
@@ -871,6 +731,9 @@ static struct mfd_cell wm8310_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
                .resources = wm831x_dcdc4_resources,
        },
+       {
+               .name = "wm831x-clk",
+       },
        {
                .name = "wm831x-epe",
                .id = 1,
@@ -975,11 +838,6 @@ static struct mfd_cell wm8310_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_power_resources),
                .resources = wm831x_power_resources,
        },
-       {
-               .name = "wm831x-rtc",
-               .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
-               .resources = wm831x_rtc_resources,
-       },
        {
                .name = "wm831x-status",
                .id = 1,
@@ -1027,6 +885,9 @@ static struct mfd_cell wm8311_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
                .resources = wm831x_dcdc4_resources,
        },
+       {
+               .name = "wm831x-clk",
+       },
        {
                .name = "wm831x-epe",
                .id = 1,
@@ -1107,11 +968,6 @@ static struct mfd_cell wm8311_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_power_resources),
                .resources = wm831x_power_resources,
        },
-       {
-               .name = "wm831x-rtc",
-               .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
-               .resources = wm831x_rtc_resources,
-       },
        {
                .name = "wm831x-status",
                .id = 1,
@@ -1124,11 +980,6 @@ static struct mfd_cell wm8311_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_status2_resources),
                .resources = wm831x_status2_resources,
        },
-       {
-               .name = "wm831x-touch",
-               .num_resources = ARRAY_SIZE(wm831x_touch_resources),
-               .resources = wm831x_touch_resources,
-       },
        {
                .name = "wm831x-watchdog",
                .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
@@ -1164,6 +1015,9 @@ static struct mfd_cell wm8312_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
                .resources = wm831x_dcdc4_resources,
        },
+       {
+               .name = "wm831x-clk",
+       },
        {
                .name = "wm831x-epe",
                .id = 1,
@@ -1268,11 +1122,6 @@ static struct mfd_cell wm8312_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_power_resources),
                .resources = wm831x_power_resources,
        },
-       {
-               .name = "wm831x-rtc",
-               .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
-               .resources = wm831x_rtc_resources,
-       },
        {
                .name = "wm831x-status",
                .id = 1,
@@ -1285,11 +1134,6 @@ static struct mfd_cell wm8312_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_status2_resources),
                .resources = wm831x_status2_resources,
        },
-       {
-               .name = "wm831x-touch",
-               .num_resources = ARRAY_SIZE(wm831x_touch_resources),
-               .resources = wm831x_touch_resources,
-       },
        {
                .name = "wm831x-watchdog",
                .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
@@ -1325,6 +1169,9 @@ static struct mfd_cell wm8320_devs[] = {
                .num_resources = ARRAY_SIZE(wm8320_dcdc4_buck_resources),
                .resources = wm8320_dcdc4_buck_resources,
        },
+       {
+               .name = "wm831x-clk",
+       },
        {
                .name = "wm831x-gpio",
                .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
@@ -1404,11 +1251,6 @@ static struct mfd_cell wm8320_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_on_resources),
                .resources = wm831x_on_resources,
        },
-       {
-               .name = "wm831x-rtc",
-               .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
-               .resources = wm831x_rtc_resources,
-       },
        {
                .name = "wm831x-status",
                .id = 1,
@@ -1428,6 +1270,22 @@ static struct mfd_cell wm8320_devs[] = {
        },
 };
 
+static struct mfd_cell touch_devs[] = {
+       {
+               .name = "wm831x-touch",
+               .num_resources = ARRAY_SIZE(wm831x_touch_resources),
+               .resources = wm831x_touch_resources,
+       },
+};
+
+static struct mfd_cell rtc_devs[] = {
+       {
+               .name = "wm831x-rtc",
+               .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
+               .resources = wm831x_rtc_resources,
+       },
+};
+
 static struct mfd_cell backlight_devs[] = {
        {
                .name = "wm831x-backlight",
@@ -1440,14 +1298,12 @@ static struct mfd_cell backlight_devs[] = {
 int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
 {
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-       int rev;
+       int rev, wm831x_num;
        enum wm831x_parent parent;
        int ret, i;
 
        mutex_init(&wm831x->io_lock);
        mutex_init(&wm831x->key_lock);
-       mutex_init(&wm831x->auxadc_lock);
-       init_completion(&wm831x->auxadc_done);
        dev_set_drvdata(wm831x->dev, wm831x);
 
        ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
@@ -1592,45 +1448,51 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
                }
        }
 
+       /* Multiply by 10 as we have many subdevices of the same type */
+       if (pdata && pdata->wm831x_num)
+               wm831x_num = pdata->wm831x_num * 10;
+       else
+               wm831x_num = -1;
+
        ret = wm831x_irq_init(wm831x, irq);
        if (ret != 0)
                goto err;
 
-       if (wm831x->irq_base) {
-               ret = request_threaded_irq(wm831x->irq_base +
-                                          WM831X_IRQ_AUXADC_DATA,
-                                          NULL, wm831x_auxadc_irq, 0,
-                                          "auxadc", wm831x);
-               if (ret < 0)
-                       dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n",
-                               ret);
-       }
+       wm831x_auxadc_init(wm831x);
 
        /* The core device is up, instantiate the subdevices. */
        switch (parent) {
        case WM8310:
-               ret = mfd_add_devices(wm831x->dev, -1,
+               ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      wm8310_devs, ARRAY_SIZE(wm8310_devs),
                                      NULL, wm831x->irq_base);
                break;
 
        case WM8311:
-               ret = mfd_add_devices(wm831x->dev, -1,
+               ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      wm8311_devs, ARRAY_SIZE(wm8311_devs),
                                      NULL, wm831x->irq_base);
+               if (!pdata || !pdata->disable_touch)
+                       mfd_add_devices(wm831x->dev, wm831x_num,
+                                       touch_devs, ARRAY_SIZE(touch_devs),
+                                       NULL, wm831x->irq_base);
                break;
 
        case WM8312:
-               ret = mfd_add_devices(wm831x->dev, -1,
+               ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      wm8312_devs, ARRAY_SIZE(wm8312_devs),
                                      NULL, wm831x->irq_base);
+               if (!pdata || !pdata->disable_touch)
+                       mfd_add_devices(wm831x->dev, wm831x_num,
+                                       touch_devs, ARRAY_SIZE(touch_devs),
+                                       NULL, wm831x->irq_base);
                break;
 
        case WM8320:
        case WM8321:
        case WM8325:
        case WM8326:
-               ret = mfd_add_devices(wm831x->dev, -1,
+               ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      wm8320_devs, ARRAY_SIZE(wm8320_devs),
                                      NULL, wm831x->irq_base);
                break;
@@ -1645,9 +1507,30 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
                goto err_irq;
        }
 
+       /* The RTC can only be used if the 32.768kHz crystal is
+        * enabled; this can't be controlled by software at runtime.
+        */
+       ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to read clock status: %d\n", ret);
+               goto err_irq;
+       }
+
+       if (ret & WM831X_XTAL_ENA) {
+               ret = mfd_add_devices(wm831x->dev, wm831x_num,
+                                     rtc_devs, ARRAY_SIZE(rtc_devs),
+                                     NULL, wm831x->irq_base);
+               if (ret != 0) {
+                       dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret);
+                       goto err_irq;
+               }
+       } else {
+               dev_info(wm831x->dev, "32.768kHz clock disabled, no RTC\n");
+       }
+
        if (pdata && pdata->backlight) {
                /* Treat errors as non-critical */
-               ret = mfd_add_devices(wm831x->dev, -1, backlight_devs,
+               ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs,
                                      ARRAY_SIZE(backlight_devs), NULL,
                                      wm831x->irq_base);
                if (ret < 0)
index 42b928e..ada1835 100644 (file)
@@ -348,6 +348,15 @@ static void wm831x_irq_sync_unlock(struct irq_data *data)
        struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
        int i;
 
+       for (i = 0; i < ARRAY_SIZE(wm831x->gpio_update); i++) {
+               if (wm831x->gpio_update[i]) {
+                       wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + i,
+                                       WM831X_GPN_INT_MODE | WM831X_GPN_POL,
+                                       wm831x->gpio_update[i]);
+                       wm831x->gpio_update[i] = 0;
+               }
+       }
+
        for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
                /* If there's been a change in the mask write it back
                 * to the hardware. */
@@ -387,7 +396,7 @@ static void wm831x_irq_disable(struct irq_data *data)
 static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
 {
        struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
-       int val, irq;
+       int irq;
 
        irq = data->irq - wm831x->irq_base;
 
@@ -399,22 +408,30 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
                        return -EINVAL;
        }
 
+       /* Rebase the IRQ into the GPIO range so we've got a sensible array
+        * index.
+        */
+       irq -= WM831X_IRQ_GPIO_1;
+
+       /* We set the high bit to flag that we need an update; don't
+        * do the update here as we can be called with the bus lock
+        * held.
+        */
        switch (type) {
        case IRQ_TYPE_EDGE_BOTH:
-               val = WM831X_GPN_INT_MODE;
+               wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE;
                break;
        case IRQ_TYPE_EDGE_RISING:
-               val = WM831X_GPN_POL;
+               wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL;
                break;
        case IRQ_TYPE_EDGE_FALLING:
-               val = 0;
+               wm831x->gpio_update[irq] = 0x10000;
                break;
        default:
                return -EINVAL;
        }
 
-       return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + irq,
-                              WM831X_GPN_INT_MODE | WM831X_GPN_POL, val);
+       return 0;
 }
 
 static struct irq_chip wm831x_irq_chip = {
@@ -432,7 +449,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
 {
        struct wm831x *wm831x = data;
        unsigned int i;
-       int primary;
+       int primary, status_addr;
        int status_regs[WM831X_NUM_IRQ_REGS] = { 0 };
        int read[WM831X_NUM_IRQ_REGS] = { 0 };
        int *status;
@@ -467,8 +484,9 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
                /* Hopefully there should only be one register to read
                 * each time otherwise we ought to do a block read. */
                if (!read[offset]) {
-                       *status = wm831x_reg_read(wm831x,
-                                    irq_data_to_status_reg(&wm831x_irqs[i]));
+                       status_addr = irq_data_to_status_reg(&wm831x_irqs[i]);
+
+                       *status = wm831x_reg_read(wm831x, status_addr);
                        if (*status < 0) {
                                dev_err(wm831x->dev,
                                        "Failed to read IRQ status: %d\n",
@@ -477,26 +495,21 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
                        }
 
                        read[offset] = 1;
+
+                       /* Ignore any bits that we don't think are masked */
+                       *status &= ~wm831x->irq_masks_cur[offset];
+
+                       /* Acknowledge now so we don't miss
+                        * notifications while we handle.
+                        */
+                       wm831x_reg_write(wm831x, status_addr, *status);
                }
 
-               /* Report it if it isn't masked, or forget the status. */
-               if ((*status & ~wm831x->irq_masks_cur[offset])
-                   & wm831x_irqs[i].mask)
+               if (*status & wm831x_irqs[i].mask)
                        handle_nested_irq(wm831x->irq_base + i);
-               else
-                       *status &= ~wm831x_irqs[i].mask;
        }
 
 out:
-       /* Touchscreen interrupts are handled specially in the driver */
-       status_regs[0] &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT);
-
-       for (i = 0; i < ARRAY_SIZE(status_regs); i++) {
-               if (status_regs[i])
-                       wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i,
-                                        status_regs[i]);
-       }
-
        return IRQ_HANDLED;
 }
 
@@ -515,13 +528,22 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
                                 0xffff);
        }
 
-       if (!pdata || !pdata->irq_base) {
-               dev_err(wm831x->dev,
-                       "No interrupt base specified, no interrupts\n");
+       /* Try to dynamically allocate IRQs if no base is specified */
+       if (!pdata || !pdata->irq_base)
+               wm831x->irq_base = -1;
+       else
+               wm831x->irq_base = pdata->irq_base;
+
+       wm831x->irq_base = irq_alloc_descs(wm831x->irq_base, 0,
+                                          WM831X_NUM_IRQS, 0);
+       if (wm831x->irq_base < 0) {
+               dev_warn(wm831x->dev, "Failed to allocate IRQs: %d\n",
+                        wm831x->irq_base);
+               wm831x->irq_base = 0;
                return 0;
        }
 
-       if (pdata->irq_cmos)
+       if (pdata && pdata->irq_cmos)
                i = 0;
        else
                i = WM831X_IRQ_OD;
@@ -541,7 +563,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
        }
 
        wm831x->irq = irq;
-       wm831x->irq_base = pdata->irq_base;
 
        /* Register them with genirq */
        for (cur_irq = wm831x->irq_base;
index ed4b22a..8a1fafd 100644 (file)
@@ -473,17 +473,13 @@ int wm8350_irq_init(struct wm8350 *wm8350, int irq,
 {
        int ret, cur_irq, i;
        int flags = IRQF_ONESHOT;
+       int irq_base = -1;
 
        if (!irq) {
                dev_warn(wm8350->dev, "No interrupt support, no core IRQ\n");
                return 0;
        }
 
-       if (!pdata || !pdata->irq_base) {
-               dev_warn(wm8350->dev, "No interrupt support, no IRQ base\n");
-               return 0;
-       }
-
        /* Mask top level interrupts */
        wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF);
 
@@ -502,7 +498,17 @@ int wm8350_irq_init(struct wm8350 *wm8350, int irq,
        wm8350->chip_irq = irq;
        wm8350->irq_base = pdata->irq_base;
 
-       if (pdata->irq_high) {
+       if (pdata && pdata->irq_base > 0)
+               irq_base = pdata->irq_base;
+
+       wm8350->irq_base = irq_alloc_descs(irq_base, 0, ARRAY_SIZE(wm8350_irqs), 0);
+       if (wm8350->irq_base < 0) {
+               dev_warn(wm8350->dev, "Allocating irqs failed with %d\n",
+                       wm8350->irq_base);
+               return 0;
+       }
+
+       if (pdata && pdata->irq_high) {
                flags |= IRQF_TRIGGER_HIGH;
 
                wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1,
index e198d40..96479c9 100644 (file)
@@ -316,7 +316,7 @@ static int wm8994_suspend(struct device *dev)
 static int wm8994_resume(struct device *dev)
 {
        struct wm8994 *wm8994 = dev_get_drvdata(dev);
-       int ret;
+       int ret, i;
 
        /* We may have lied to the PM core about suspending */
        if (!wm8994->suspended)
@@ -329,10 +329,16 @@ static int wm8994_resume(struct device *dev)
                return ret;
        }
 
-       ret = wm8994_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK,
-                          WM8994_NUM_IRQ_REGS * 2, &wm8994->irq_masks_cur);
-       if (ret < 0)
-               dev_err(dev, "Failed to restore interrupt masks: %d\n", ret);
+       /* Write register at a time as we use the cache on the CPU so store
+        * it in native endian.
+        */
+       for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
+               ret = wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK
+                                      + i, wm8994->irq_masks_cur[i]);
+               if (ret < 0)
+                       dev_err(dev, "Failed to restore interrupt masks: %d\n",
+                               ret);
+       }
 
        ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
                           &wm8994->ldo_regs);
@@ -403,7 +409,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                break;
        default:
                BUG();
-               return -EINVAL;
+               goto err;
        }
 
        wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
@@ -425,7 +431,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                break;
        default:
                BUG();
-               return -EINVAL;
+               goto err;
        }
                
        ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,
@@ -476,13 +482,18 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                goto err_enable;
        }
 
-       switch (ret) {
-       case 0:
-       case 1:
-               if (wm8994->type == WM8994)
+       switch (wm8994->type) {
+       case WM8994:
+               switch (ret) {
+               case 0:
+               case 1:
                        dev_warn(wm8994->dev,
                                 "revision %c not fully supported\n",
                                 'A' + ret);
+                       break;
+               default:
+                       break;
+               }
                break;
        default:
                break;
index 71c6e8f..d682f7b 100644 (file)
@@ -231,12 +231,6 @@ static irqreturn_t wm8994_irq_thread(int irq, void *data)
                status[i] &= ~wm8994->irq_masks_cur[i];
        }
 
-       /* Report */
-       for (i = 0; i < ARRAY_SIZE(wm8994_irqs); i++) {
-               if (status[wm8994_irqs[i].reg - 1] & wm8994_irqs[i].mask)
-                       handle_nested_irq(wm8994->irq_base + i);
-       }
-
        /* Ack any unmasked IRQs */
        for (i = 0; i < ARRAY_SIZE(status); i++) {
                if (status[i])
@@ -244,6 +238,12 @@ static irqreturn_t wm8994_irq_thread(int irq, void *data)
                                         status[i]);
        }
 
+       /* Report */
+       for (i = 0; i < ARRAY_SIZE(wm8994_irqs); i++) {
+               if (status[wm8994_irqs[i].reg - 1] & wm8994_irqs[i].mask)
+                       handle_nested_irq(wm8994->irq_base + i);
+       }
+
        return IRQ_HANDLED;
 }
 
index 710b706..9ebfb4b 100644 (file)
@@ -20,7 +20,9 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sdio.h>
-#include <mach/hardware.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <mach/esdhc.h>
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
@@ -29,7 +31,6 @@
 #define SDHCI_VENDOR_SPEC              0xC0
 #define  SDHCI_VENDOR_SPEC_SDIO_QUIRK  0x00000002
 
-#define ESDHC_FLAG_GPIO_FOR_CD         (1 << 0)
 /*
  * The CMDTYPE of the CMD register (offset 0xE) should be set to
  * "11" when the STOP CMD12 is issued on imx53 to abort one
  */
 #define ESDHC_FLAG_MULTIBLK_NO_INT     (1 << 1)
 
+enum imx_esdhc_type {
+       IMX25_ESDHC,
+       IMX35_ESDHC,
+       IMX51_ESDHC,
+       IMX53_ESDHC,
+};
+
 struct pltfm_imx_data {
        int flags;
        u32 scratchpad;
+       enum imx_esdhc_type devtype;
+       struct esdhc_platform_data boarddata;
+};
+
+static struct platform_device_id imx_esdhc_devtype[] = {
+       {
+               .name = "sdhci-esdhc-imx25",
+               .driver_data = IMX25_ESDHC,
+       }, {
+               .name = "sdhci-esdhc-imx35",
+               .driver_data = IMX35_ESDHC,
+       }, {
+               .name = "sdhci-esdhc-imx51",
+               .driver_data = IMX51_ESDHC,
+       }, {
+               .name = "sdhci-esdhc-imx53",
+               .driver_data = IMX53_ESDHC,
+       }, {
+               /* sentinel */
+       }
 };
+MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype);
+
+static const struct of_device_id imx_esdhc_dt_ids[] = {
+       { .compatible = "fsl,imx25-esdhc", .data = &imx_esdhc_devtype[IMX25_ESDHC], },
+       { .compatible = "fsl,imx35-esdhc", .data = &imx_esdhc_devtype[IMX35_ESDHC], },
+       { .compatible = "fsl,imx51-esdhc", .data = &imx_esdhc_devtype[IMX51_ESDHC], },
+       { .compatible = "fsl,imx53-esdhc", .data = &imx_esdhc_devtype[IMX53_ESDHC], },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
+
+static inline int is_imx25_esdhc(struct pltfm_imx_data *data)
+{
+       return data->devtype == IMX25_ESDHC;
+}
+
+static inline int is_imx35_esdhc(struct pltfm_imx_data *data)
+{
+       return data->devtype == IMX35_ESDHC;
+}
+
+static inline int is_imx51_esdhc(struct pltfm_imx_data *data)
+{
+       return data->devtype == IMX51_ESDHC;
+}
+
+static inline int is_imx53_esdhc(struct pltfm_imx_data *data)
+{
+       return data->devtype == IMX53_ESDHC;
+}
 
 static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg)
 {
@@ -60,17 +118,14 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct pltfm_imx_data *imx_data = pltfm_host->priv;
+       struct esdhc_platform_data *boarddata = &imx_data->boarddata;
 
-       /* fake CARD_PRESENT flag on mx25/35 */
+       /* fake CARD_PRESENT flag */
        u32 val = readl(host->ioaddr + reg);
 
        if (unlikely((reg == SDHCI_PRESENT_STATE)
-                       && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) {
-               struct esdhc_platform_data *boarddata =
-                               host->mmc->parent->platform_data;
-
-               if (boarddata && gpio_is_valid(boarddata->cd_gpio)
-                               && gpio_get_value(boarddata->cd_gpio))
+                       && gpio_is_valid(boarddata->cd_gpio))) {
+               if (gpio_get_value(boarddata->cd_gpio))
                        /* no card, if a valid gpio says so... */
                        val &= ~SDHCI_CARD_PRESENT;
                else
@@ -85,12 +140,12 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct pltfm_imx_data *imx_data = pltfm_host->priv;
+       struct esdhc_platform_data *boarddata = &imx_data->boarddata;
 
        if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
-                       && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD)))
+                       && (boarddata->cd_type == ESDHC_CD_GPIO)))
                /*
                 * these interrupts won't work with a custom card_detect gpio
-                * (only applied to mx25/35)
                 */
                val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
 
@@ -173,6 +228,17 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
                return;
        }
        esdhc_clrset_le(host, 0xff, val, reg);
+
+       /*
+        * The esdhc has a design violation to SDHC spec which tells
+        * that software reset should not affect card detection circuit.
+        * But esdhc clears its SYSCTL register bits [0..2] during the
+        * software reset.  This will stop those clocks that card detection
+        * circuit relies on.  To work around it, we turn the clocks on back
+        * to keep card detection circuit functional.
+        */
+       if ((reg == SDHCI_SOFTWARE_RESET) && (val & 1))
+               esdhc_clrset_le(host, 0x7, 0x7, ESDHC_SYSTEM_CONTROL);
 }
 
 static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
@@ -189,6 +255,26 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
        return clk_get_rate(pltfm_host->clk) / 256 / 16;
 }
 
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct pltfm_imx_data *imx_data = pltfm_host->priv;
+       struct esdhc_platform_data *boarddata = &imx_data->boarddata;
+
+       switch (boarddata->wp_type) {
+       case ESDHC_WP_GPIO:
+               if (gpio_is_valid(boarddata->wp_gpio))
+                       return gpio_get_value(boarddata->wp_gpio);
+       case ESDHC_WP_CONTROLLER:
+               return !(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
+                              SDHCI_WRITE_PROTECT);
+       case ESDHC_WP_NONE:
+               break;
+       }
+
+       return -ENOSYS;
+}
+
 static struct sdhci_ops sdhci_esdhc_ops = {
        .read_l = esdhc_readl_le,
        .read_w = esdhc_readw_le,
@@ -198,6 +284,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
        .set_clock = esdhc_set_clock,
        .get_max_clock = esdhc_pltfm_get_max_clock,
        .get_min_clock = esdhc_pltfm_get_min_clock,
+       .get_ro = esdhc_pltfm_get_ro,
 };
 
 static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
@@ -207,17 +294,6 @@ static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
        .ops = &sdhci_esdhc_ops,
 };
 
-static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
-{
-       struct esdhc_platform_data *boarddata =
-                       host->mmc->parent->platform_data;
-
-       if (boarddata && gpio_is_valid(boarddata->wp_gpio))
-               return gpio_get_value(boarddata->wp_gpio);
-       else
-               return -ENOSYS;
-}
-
 static irqreturn_t cd_irq(int irq, void *data)
 {
        struct sdhci_host *sdhost = (struct sdhci_host *)data;
@@ -226,8 +302,48 @@ static irqreturn_t cd_irq(int irq, void *data)
        return IRQ_HANDLED;
 };
 
+#ifdef CONFIG_OF
+static int __devinit
+sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
+                        struct esdhc_platform_data *boarddata)
+{
+       struct device_node *np = pdev->dev.of_node;
+
+       if (!np)
+               return -ENODEV;
+
+       if (of_get_property(np, "fsl,card-wired", NULL))
+               boarddata->cd_type = ESDHC_CD_PERMANENT;
+
+       if (of_get_property(np, "fsl,cd-controller", NULL))
+               boarddata->cd_type = ESDHC_CD_CONTROLLER;
+
+       if (of_get_property(np, "fsl,wp-controller", NULL))
+               boarddata->wp_type = ESDHC_WP_CONTROLLER;
+
+       boarddata->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
+       if (gpio_is_valid(boarddata->cd_gpio))
+               boarddata->cd_type = ESDHC_CD_GPIO;
+
+       boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
+       if (gpio_is_valid(boarddata->wp_gpio))
+               boarddata->wp_type = ESDHC_WP_GPIO;
+
+       return 0;
+}
+#else
+static inline int
+sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
+                        struct esdhc_platform_data *boarddata)
+{
+       return -ENODEV;
+}
+#endif
+
 static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *of_id =
+                       of_match_device(imx_esdhc_dt_ids, &pdev->dev);
        struct sdhci_pltfm_host *pltfm_host;
        struct sdhci_host *host;
        struct esdhc_platform_data *boarddata;
@@ -242,8 +358,14 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
        pltfm_host = sdhci_priv(host);
 
        imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
-       if (!imx_data)
-               return -ENOMEM;
+       if (!imx_data) {
+               err = -ENOMEM;
+               goto err_imx_data;
+       }
+
+       if (of_id)
+               pdev->id_entry = of_id->data;
+       imx_data->devtype = pdev->id_entry->driver_data;
        pltfm_host->priv = imx_data;
 
        clk = clk_get(mmc_dev(host->mmc), NULL);
@@ -255,50 +377,72 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
        clk_enable(clk);
        pltfm_host->clk = clk;
 
-       if (!cpu_is_mx25())
+       if (!is_imx25_esdhc(imx_data))
                host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
-       if (cpu_is_mx25() || cpu_is_mx35()) {
+       if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data))
                /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
                host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
-               /* write_protect can't be routed to controller, use gpio */
-               sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
-       }
 
-       if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
+       if (is_imx53_esdhc(imx_data))
                imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
 
-       boarddata = host->mmc->parent->platform_data;
-       if (boarddata) {
+       boarddata = &imx_data->boarddata;
+       if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
+               if (!host->mmc->parent->platform_data) {
+                       dev_err(mmc_dev(host->mmc), "no board data!\n");
+                       err = -EINVAL;
+                       goto no_board_data;
+               }
+               imx_data->boarddata = *((struct esdhc_platform_data *)
+                                       host->mmc->parent->platform_data);
+       }
+
+       /* write_protect */
+       if (boarddata->wp_type == ESDHC_WP_GPIO) {
                err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
                if (err) {
                        dev_warn(mmc_dev(host->mmc),
-                               "no write-protect pin available!\n");
-                       boarddata->wp_gpio = err;
+                                "no write-protect pin available!\n");
+                       boarddata->wp_gpio = -EINVAL;
                }
+       } else {
+               boarddata->wp_gpio = -EINVAL;
+       }
+
+       /* card_detect */
+       if (boarddata->cd_type != ESDHC_CD_GPIO)
+               boarddata->cd_gpio = -EINVAL;
 
+       switch (boarddata->cd_type) {
+       case ESDHC_CD_GPIO:
                err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
                if (err) {
-                       dev_warn(mmc_dev(host->mmc),
+                       dev_err(mmc_dev(host->mmc),
                                "no card-detect pin available!\n");
                        goto no_card_detect_pin;
                }
 
-               /* i.MX5x has issues to be researched */
-               if (!cpu_is_mx25() && !cpu_is_mx35())
-                       goto not_supported;
-
                err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
                                 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
                                 mmc_hostname(host->mmc), host);
                if (err) {
-                       dev_warn(mmc_dev(host->mmc), "request irq error\n");
+                       dev_err(mmc_dev(host->mmc), "request irq error\n");
                        goto no_card_detect_irq;
                }
+               /* fall through */
 
-               imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD;
-               /* Now we have a working card_detect again */
+       case ESDHC_CD_CONTROLLER:
+               /* we have a working card_detect back */
                host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+               break;
+
+       case ESDHC_CD_PERMANENT:
+               host->mmc->caps = MMC_CAP_NONREMOVABLE;
+               break;
+
+       case ESDHC_CD_NONE:
+               break;
        }
 
        err = sdhci_add_host(host);
@@ -307,16 +451,21 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 
        return 0;
 
- no_card_detect_irq:
-       gpio_free(boarddata->cd_gpio);
- no_card_detect_pin:
-       boarddata->cd_gpio = err;
- not_supported:
-       kfree(imx_data);
- err_add_host:
+err_add_host:
+       if (gpio_is_valid(boarddata->cd_gpio))
+               free_irq(gpio_to_irq(boarddata->cd_gpio), host);
+no_card_detect_irq:
+       if (gpio_is_valid(boarddata->cd_gpio))
+               gpio_free(boarddata->cd_gpio);
+       if (gpio_is_valid(boarddata->wp_gpio))
+               gpio_free(boarddata->wp_gpio);
+no_card_detect_pin:
+no_board_data:
        clk_disable(pltfm_host->clk);
        clk_put(pltfm_host->clk);
- err_clk_get:
+err_clk_get:
+       kfree(imx_data);
+err_imx_data:
        sdhci_pltfm_free(pdev);
        return err;
 }
@@ -325,20 +474,18 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
 {
        struct sdhci_host *host = platform_get_drvdata(pdev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
        struct pltfm_imx_data *imx_data = pltfm_host->priv;
+       struct esdhc_platform_data *boarddata = &imx_data->boarddata;
        int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
 
        sdhci_remove_host(host, dead);
 
-       if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+       if (gpio_is_valid(boarddata->wp_gpio))
                gpio_free(boarddata->wp_gpio);
 
-       if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
+       if (gpio_is_valid(boarddata->cd_gpio)) {
+               free_irq(gpio_to_irq(boarddata->cd_gpio), host);
                gpio_free(boarddata->cd_gpio);
-
-               if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
-                       free_irq(gpio_to_irq(boarddata->cd_gpio), host);
        }
 
        clk_disable(pltfm_host->clk);
@@ -354,7 +501,9 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
        .driver         = {
                .name   = "sdhci-esdhc-imx",
                .owner  = THIS_MODULE,
+               .of_match_table = imx_esdhc_dt_ids,
        },
+       .id_table       = imx_esdhc_devtype,
        .probe          = sdhci_esdhc_imx_probe,
        .remove         = __devexit_p(sdhci_esdhc_imx_remove),
 #ifdef CONFIG_PM
index 71c0ce1..6414efe 100644 (file)
@@ -85,6 +85,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
 {
        struct sdhci_host *host;
        struct sdhci_pltfm_host *pltfm_host;
+       struct device_node *np = pdev->dev.of_node;
        struct resource *iomem;
        int ret;
 
@@ -98,7 +99,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
                dev_err(&pdev->dev, "Invalid iomem size!\n");
 
        /* Some PCI-based MFD need the parent here */
-       if (pdev->dev.parent != &platform_bus)
+       if (pdev->dev.parent != &platform_bus && !np)
                host = sdhci_alloc_host(pdev->dev.parent, sizeof(*pltfm_host));
        else
                host = sdhci_alloc_host(&pdev->dev, sizeof(*pltfm_host));
index 8d0314d..583f66c 100644 (file)
@@ -2,9 +2,6 @@
 # Network device configuration
 #
 
-config HAVE_NET_MACB
-       bool
-
 menuconfig NETDEVICES
        default y if UML
        depends on NET
@@ -28,18 +25,32 @@ menuconfig NETDEVICES
 # that for each of the symbols.
 if NETDEVICES
 
-config IFB
-       tristate "Intermediate Functional Block support"
-       depends on NET_CLS_ACT
+config NET_CORE
+       default y
+       bool "Network core driver support"
        ---help---
-         This is an intermediate driver that allows sharing of
-         resources.
+         You can say N here if you do not intend to use any of the
+         networking core drivers (i.e. VLAN, bridging, bonding, etc.)
+
+if NET_CORE
+
+config BONDING
+       tristate "Bonding driver support"
+       depends on INET
+       depends on IPV6 || IPV6=n
+       ---help---
+         Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet
+         Channels together. This is called 'Etherchannel' by Cisco,
+         'Trunking' by Sun, 802.3ad by the IEEE, and 'Bonding' in Linux.
+
+         The driver supports multiple bonding modes to allow for both high
+         performance and high availability operation.
+
+         Refer to <file:Documentation/networking/bonding.txt> for more
+         information.
+
          To compile this driver as a module, choose M here: the module
-         will be called ifb.  If you want to use more than one ifb
-         device at a time, you need to compile this driver as a module.
-         Instead of 'ifb', the devices will then be called 'ifb0',
-         'ifb1' etc.
-         Look at the iproute2 documentation directory for usage etc
+         will be called bonding.
 
 config DUMMY
        tristate "Dummy net driver support"
@@ -60,23 +71,59 @@ config DUMMY
          Instead of 'dummy', the devices will then be called 'dummy0',
          'dummy1' etc.
 
-config BONDING
-       tristate "Bonding driver support"
-       depends on INET
-       depends on IPV6 || IPV6=n
+config EQUALIZER
+       tristate "EQL (serial line load balancing) support"
        ---help---
-         Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet
-         Channels together. This is called 'Etherchannel' by Cisco,
-         'Trunking' by Sun, 802.3ad by the IEEE, and 'Bonding' in Linux.
+         If you have two serial connections to some other computer (this
+         usually requires two modems and two telephone lines) and you use
+         SLIP (the protocol for sending Internet traffic over telephone
+         lines) or PPP (a better SLIP) on them, you can make them behave like
+         one double speed connection using this driver.  Naturally, this has
+         to be supported at the other end as well, either with a similar EQL
+         Linux driver or with a Livingston Portmaster 2e.
 
-         The driver supports multiple bonding modes to allow for both high
-         performance and high availability operation.
+         Say Y if you want this and read
+         <file:Documentation/networking/eql.txt>.  You may also want to read
+         section 6.2 of the NET-3-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
 
-         Refer to <file:Documentation/networking/bonding.txt> for more
-         information.
+         To compile this driver as a module, choose M here: the module
+         will be called eql.  If unsure, say N.
+
+config NET_FC
+       bool "Fibre Channel driver support"
+       depends on SCSI && PCI
+       help
+         Fibre Channel is a high speed serial protocol mainly used to connect
+         large storage devices to the computer; it is compatible with and
+         intended to replace SCSI.
 
+         If you intend to use Fibre Channel, you need to have a Fibre channel
+         adaptor card in your computer; say Y here and to the driver for your
+         adaptor below. You also should have said Y to "SCSI support" and
+         "SCSI generic support".
+
+config MII
+       tristate "Generic Media Independent Interface device support"
+       help
+         Most ethernet controllers have MII transceiver either as an external
+         or internal device.  It is safe to say Y or M here even if your
+         ethernet card lacks MII.
+
+source "drivers/ieee802154/Kconfig"
+
+config IFB
+       tristate "Intermediate Functional Block support"
+       depends on NET_CLS_ACT
+       ---help---
+         This is an intermediate driver that allows sharing of
+         resources.
          To compile this driver as a module, choose M here: the module
-         will be called bonding.
+         will be called ifb.  If you want to use more than one ifb
+         device at a time, you need to compile this driver as a module.
+         Instead of 'ifb', the devices will then be called 'ifb0',
+         'ifb1' etc.
+         Look at the iproute2 documentation directory for usage etc
 
 config MACVLAN
        tristate "MAC-VLAN support (EXPERIMENTAL)"
@@ -105,24 +152,46 @@ config MACVTAP
          To compile this driver as a module, choose M here: the module
          will be called macvtap.
 
-config EQUALIZER
-       tristate "EQL (serial line load balancing) support"
+config NETCONSOLE
+       tristate "Network console logging support"
        ---help---
-         If you have two serial connections to some other computer (this
-         usually requires two modems and two telephone lines) and you use
-         SLIP (the protocol for sending Internet traffic over telephone
-         lines) or PPP (a better SLIP) on them, you can make them behave like
-         one double speed connection using this driver.  Naturally, this has
-         to be supported at the other end as well, either with a similar EQL
-         Linux driver or with a Livingston Portmaster 2e.
+       If you want to log kernel messages over the network, enable this.
+       See <file:Documentation/networking/netconsole.txt> for details.
 
-         Say Y if you want this and read
-         <file:Documentation/networking/eql.txt>.  You may also want to read
-         section 6.2 of the NET-3-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
+config NETCONSOLE_DYNAMIC
+       bool "Dynamic reconfiguration of logging targets"
+       depends on NETCONSOLE && SYSFS && CONFIGFS_FS && \
+                       !(NETCONSOLE=y && CONFIGFS_FS=m)
+       help
+         This option enables the ability to dynamically reconfigure target
+         parameters (interface, IP addresses, port numbers, MAC addresses)
+         at runtime through a userspace interface exported using configfs.
+         See <file:Documentation/networking/netconsole.txt> for details.
 
-         To compile this driver as a module, choose M here: the module
-         will be called eql.  If unsure, say N.
+config NETPOLL
+       def_bool NETCONSOLE
+
+config NETPOLL_TRAP
+       bool "Netpoll traffic trapping"
+       default n
+       depends on NETPOLL
+
+config NET_POLL_CONTROLLER
+       def_bool NETPOLL
+
+config RIONET
+       tristate "RapidIO Ethernet over messaging driver support"
+       depends on RAPIDIO
+
+config RIONET_TX_SIZE
+       int "Number of outbound queue entries"
+       depends on RIONET
+       default "128"
+
+config RIONET_RX_SIZE
+       int "Number of inbound queue entries"
+       depends on RIONET
+       default "128"
 
 config TUN
        tristate "Universal TUN/TAP device driver support"
@@ -154,6 +223,28 @@ config VETH
          When one end receives the packet it appears on its pair and vice
          versa.
 
+config VIRTIO_NET
+       tristate "Virtio network driver (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && VIRTIO
+       ---help---
+         This is the virtual network driver for virtio.  It can be used with
+         lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
+
+endif # NET_CORE
+
+config SUNGEM_PHY
+       tristate
+
+source "drivers/net/arcnet/Kconfig"
+
+source "drivers/atm/Kconfig"
+
+source "drivers/net/caif/Kconfig"
+
+source "drivers/net/ethernet/Kconfig"
+
+source "drivers/net/fddi/Kconfig"
+
 config NET_SB1000
        tristate "General Instruments Surfboard 1000"
        depends on PNP
@@ -178,3271 +269,65 @@ config NET_SB1000
 
          If you don't have this card, of course say N.
 
-source "drivers/net/arcnet/Kconfig"
-
-config MII
-       tristate "Generic Media Independent Interface device support"
-       help
-         Most ethernet controllers have MII transceiver either as an external
-         or internal device.  It is safe to say Y or M here even if your
-         ethernet card lacks MII.
-
 source "drivers/net/phy/Kconfig"
 
-#
-#      Ethernet
-#
-
-menuconfig NET_ETHERNET
-       bool "Ethernet (10 or 100Mbit)"
-       depends on !UML
-       ---help---
-         Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
-         type of Local Area Network (LAN) in universities and companies.
-
-         Common varieties of Ethernet are: 10BASE-2 or Thinnet (10 Mbps over
-         coaxial cable, linking computers in a chain), 10BASE-T or twisted
-         pair (10 Mbps over twisted pair cable, linking computers to central
-         hubs), 10BASE-F (10 Mbps over optical fiber links, using hubs),
-         100BASE-TX (100 Mbps over two twisted pair cables, using hubs),
-         100BASE-T4 (100 Mbps over 4 standard voice-grade twisted pair
-         cables, using hubs), 100BASE-FX (100 Mbps over optical fiber links)
-         [the 100BASE varieties are also known as Fast Ethernet], and Gigabit
-         Ethernet (1 Gbps over optical fiber or short copper links).
-
-         If your Linux machine will be connected to an Ethernet and you have
-         an Ethernet network interface card (NIC) installed in your computer,
-         say Y here and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>. You will then also have
-         to say Y to the driver for your particular NIC.
-
-         Note that the answer to this question won't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the questions about Ethernet network cards. If unsure, say N.
-
-if NET_ETHERNET
-
-config MACB
-       tristate "Atmel MACB support"
-       depends on HAVE_NET_MACB
-       select PHYLIB
-       help
-         The Atmel MACB ethernet interface is found on many AT32 and AT91
-         parts. Say Y to include support for the MACB chip.
-
-         To compile this driver as a module, choose M here: the module
-         will be called macb.
-
-source "drivers/net/arm/Kconfig"
-
-config AX88796
-       tristate "ASIX AX88796 NE2000 clone support"
-       depends on ARM || MIPS || SUPERH
-       select PHYLIB
-       select MDIO_BITBANG
-       help
-         AX88796 driver, using platform bus to provide
-         chip detection and resources
-
-config AX88796_93CX6
-       bool "ASIX AX88796 external 93CX6 eeprom support"
-       depends on AX88796
-       select EEPROM_93CX6
-       help
-         Select this if your platform comes with an external 93CX6 eeprom.
-
-config MACE
-       tristate "MACE (Power Mac ethernet) support"
-       depends on PPC_PMAC && PPC32
-       select CRC32
-       help
-         Power Macintoshes and clones with Ethernet built-in on the
-         motherboard will usually use a MACE (Medium Access Control for
-         Ethernet) interface. Say Y to include support for the MACE chip.
-
-         To compile this driver as a module, choose M here: the module
-         will be called mace.
+source "drivers/net/plip/Kconfig"
 
-config MACE_AAUI_PORT
-       bool "Use AAUI port instead of TP by default"
-       depends on MACE
-       help
-         Some Apple machines (notably the Apple Network Server) which use the
-         MACE ethernet chip have an Apple AUI port (small 15-pin connector),
-         instead of an 8-pin RJ45 connector for twisted-pair ethernet.  Say
-         Y here if you have such a machine.  If unsure, say N.
-         The driver will default to AAUI on ANS anyway, and if you use it as
-         a module, you can provide the port_aaui=0|1 to force the driver.
-
-config BMAC
-       tristate "BMAC (G3 ethernet) support"
-       depends on PPC_PMAC && PPC32
-       select CRC32
-       help
-         Say Y for support of BMAC Ethernet interfaces. These are used on G3
-         computers.
+source "drivers/net/ppp/Kconfig"
 
-         To compile this driver as a module, choose M here: the module
-         will be called bmac.
+source "drivers/net/slip/Kconfig"
 
-config ARIADNE
-       tristate "Ariadne support"
-       depends on ZORRO
-       help
-         If you have a Village Tronic Ariadne Ethernet adapter, say Y.
-         Otherwise, say N.
+source "drivers/s390/net/Kconfig"
 
-         To compile this driver as a module, choose M here: the module
-         will be called ariadne.
+source "drivers/net/tokenring/Kconfig"
 
-config A2065
-       tristate "A2065 support"
-       depends on ZORRO
-       select CRC32
-       help
-         If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
-         say N.
+source "drivers/net/usb/Kconfig"
 
-         To compile this driver as a module, choose M here: the module
-         will be called a2065.
+source "drivers/net/wireless/Kconfig"
 
-config HYDRA
-       tristate "Hydra support"
-       depends on ZORRO
-       select CRC32
-       help
-         If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
+source "drivers/net/wimax/Kconfig"
 
-         To compile this driver as a module, choose M here: the module
-         will be called hydra.
+source "drivers/net/wan/Kconfig"
 
-config ZORRO8390
-       tristate "Zorro NS8390-based Ethernet support"
-       depends on ZORRO
-       select CRC32
+config XEN_NETDEV_FRONTEND
+       tristate "Xen network device frontend driver"
+       depends on XEN
+       select XEN_XENBUS_FRONTEND
+       default y
        help
-         This driver is for Zorro Ethernet cards using an NS8390-compatible
-         chipset, like the Village Tronic Ariadne II and the Individual
-         Computers X-Surf Ethernet cards. If you have such a card, say Y.
-         Otherwise, say N.
-
-         To compile this driver as a module, choose M here: the module
-         will be called zorro8390.
+         This driver provides support for Xen paravirtual network
+         devices exported by a Xen network driver domain (often
+         domain 0).
 
-config APNE
-       tristate "PCMCIA NE2000 support"
-       depends on AMIGA_PCMCIA
-       select CRC32
-       help
-         If you have a PCMCIA NE2000 compatible adapter, say Y.  Otherwise,
-         say N.
+         The corresponding Linux backend driver is enabled by the
+         CONFIG_XEN_NETDEV_BACKEND option.
 
-         To compile this driver as a module, choose M here: the module
-         will be called apne.
+         If you are compiling a kernel for use as Xen guest, you
+         should say Y here. To compile this driver as a module, chose
+         M here: the module will be called xen-netfront.
 
-config MAC8390
-       bool "Macintosh NS 8390 based ethernet cards"
-       depends on MAC
-       select CRC32
+config XEN_NETDEV_BACKEND
+       tristate "Xen backend network device"
+       depends on XEN_BACKEND
        help
-         If you want to include a driver to support Nubus or LC-PDS
-         Ethernet cards using an NS8390 chipset or its equivalent, say Y
-         and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-config MAC89x0
-       tristate "Macintosh CS89x0 based ethernet cards"
-       depends on MAC
-       ---help---
-         Support for CS89x0 chipset based Ethernet cards.  If you have a
-         Nubus or LC-PDS network (Ethernet) card of this type, say Y and
-         read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. This module will
-         be called mac89x0.
-
-config MACSONIC
-       tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)"
-       depends on MAC
-       ---help---
-         Support for NatSemi SONIC based Ethernet devices.  This includes
-         the onboard Ethernet in many Quadras as well as some LC-PDS,
-         a few Nubus and all known Comm Slot Ethernet cards.  If you have
-         one of these say Y and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. This module will
-         be called macsonic.
+         This driver allows the kernel to act as a Xen network driver
+         domain which exports paravirtual network devices to other
+         Xen domains. These devices can be accessed by any operating
+         system that implements a compatible front end.
 
-config MACMACE
-       bool "Macintosh (AV) onboard MACE ethernet"
-       depends on MAC
-       select CRC32
-       help
-         Support for the onboard AMD 79C940 MACE Ethernet controller used in
-         the 660AV and 840AV Macintosh.  If you have one of these Macintoshes
-         say Y and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
+         The corresponding Linux frontend driver is enabled by the
+         CONFIG_XEN_NETDEV_FRONTEND configuration option.
 
-config MVME147_NET
-       tristate "MVME147 (Lance) Ethernet support"
-       depends on MVME147
-       select CRC32
-       help
-         Support for the on-board Ethernet interface on the Motorola MVME147
-         single-board computer.  Say Y here to include the
-         driver for this chip in your kernel.
-         To compile this driver as a module, choose M here.
-
-config MVME16x_NET
-       tristate "MVME16x Ethernet support"
-       depends on MVME16x
-       help
-         This is the driver for the Ethernet interface on the Motorola
-         MVME162, 166, 167, 172 and 177 boards.  Say Y here to include the
-         driver for this chip in your kernel.
-         To compile this driver as a module, choose M here.
-
-config BVME6000_NET
-       tristate "BVME6000 Ethernet support"
-       depends on BVME6000
-       help
-         This is the driver for the Ethernet interface on BVME4000 and
-         BVME6000 VME boards.  Say Y here to include the driver for this chip
-         in your kernel.
-         To compile this driver as a module, choose M here.
-
-config ATARILANCE
-       tristate "Atari Lance support"
-       depends on ATARI
-       help
-         Say Y to include support for several Atari Ethernet adapters based
-         on the AMD Lance chipset: RieblCard (with or without battery), or
-         PAMCard VME (also the version by Rhotron, with different addresses).
-
-config SUN3LANCE
-       tristate "Sun3/Sun3x on-board LANCE support"
-       depends on SUN3 || SUN3X
-       help
-         Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
-         featured an AMD Lance 10Mbit Ethernet controller on board; say Y
-         here to compile in the Linux driver for this and enable Ethernet.
-         General Linux information on the Sun 3 and 3x series (now
-         discontinued) is at
-         <http://www.angelfire.com/ca2/tech68k/sun3.html>.
-
-         If you're not building a kernel for a Sun 3, say N.
-
-config SUN3_82586
-       bool "Sun3 on-board Intel 82586 support"
-       depends on SUN3
-       help
-         This driver enables support for the on-board Intel 82586 based
-         Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards.  Note
-         that this driver does not support 82586-based adapters on additional
-         VME boards.
-
-config HPLANCE
-       bool "HP on-board LANCE support"
-       depends on DIO
-       select CRC32
-       help
-         If you want to use the builtin "LANCE" Ethernet controller on an
-         HP300 machine, say Y here.
-
-config LASI_82596
-       tristate "Lasi ethernet"
-       depends on GSC
-       help
-         Say Y here to support the builtin Intel 82596 ethernet controller
-         found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
-
-config SNI_82596
-       tristate "SNI RM ethernet"
-       depends on NET_ETHERNET && SNI_RM
-       help
-         Say Y here to support the on-board Intel 82596 ethernet controller
-         built into SNI RM machines.
-
-config KORINA
-       tristate "Korina (IDT RC32434) Ethernet support"
-       depends on NET_ETHERNET && MIKROTIK_RB532
-       help
-         If you have a Mikrotik RouterBoard 500 or IDT RC32434
-         based system say Y. Otherwise say N.
-
-config MIPS_JAZZ_SONIC
-       tristate "MIPS JAZZ onboard SONIC Ethernet support"
-       depends on MACH_JAZZ
-       help
-         This is the driver for the onboard card of MIPS Magnum 4000,
-         Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
-
-config XTENSA_XT2000_SONIC
-       tristate "Xtensa XT2000 onboard SONIC Ethernet support"
-       depends on XTENSA_PLATFORM_XT2000
-       help
-         This is the driver for the onboard card of the Xtensa XT2000 board.
-
-config MIPS_AU1X00_ENET
-       tristate "MIPS AU1000 Ethernet support"
-       depends on MIPS_ALCHEMY
-       select PHYLIB
-       select CRC32
-       help
-         If you have an Alchemy Semi AU1X00 based system
-         say Y.  Otherwise, say N.
-
-config SGI_IOC3_ETH
-       bool "SGI IOC3 Ethernet"
-       depends on PCI && SGI_IP27
-       select CRC32
-       select MII
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-config MIPS_SIM_NET
-       tristate "MIPS simulator Network device"
-       depends on MIPS_SIM
-       help
-         The MIPSNET device is a simple Ethernet network device which is
-         emulated by the MIPS Simulator.
-         If you are not using a MIPSsim or are unsure, say N.
-
-config SGI_O2MACE_ETH
-       tristate "SGI O2 MACE Fast Ethernet support"
-       depends on SGI_IP32=y
-
-config STNIC
-       tristate "National DP83902AV  support"
-       depends on SUPERH
-       select CRC32
-       help
-         Support for cards based on the National Semiconductor DP83902AV
-         ST-NIC Serial Network Interface Controller for Twisted Pair.  This
-         is a 10Mbit/sec Ethernet controller.  Product overview and specs at
-         <http://www.national.com/pf/DP/DP83902A.html>.
-
-         If unsure, say N.
-
-config SH_ETH
-       tristate "Renesas SuperH Ethernet support"
-       depends on SUPERH && \
-               (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
-                CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
-                CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7757)
-       select CRC32
-       select MII
-       select MDIO_BITBANG
-       select PHYLIB
-       help
-         Renesas SuperH Ethernet device driver.
-         This driver supporting CPUs are:
-               - SH7710, SH7712, SH7763, SH7619, SH7724, and SH7757.
-
-config SUNLANCE
-       tristate "Sun LANCE support"
-       depends on SBUS
-       select CRC32
-       help
-         This driver supports the "le" interface present on all 32-bit Sparc
-         systems, on some older Ultra systems and as an Sbus option.  These
-         cards are based on the AMD Lance chipset, which is better known
-         via the NE2100 cards.
-
-         To compile this driver as a module, choose M here: the module
-         will be called sunlance.
-
-config HAPPYMEAL
-       tristate "Sun Happy Meal 10/100baseT support"
-       depends on SBUS || PCI
-       select CRC32
-       help
-         This driver supports the "hme" interface present on most Ultra
-         systems and as an option on older Sbus systems. This driver supports
-         both PCI and Sbus devices. This driver also supports the "qfe" quad
-         100baseT device available in both PCI and Sbus configurations.
-
-         To compile this driver as a module, choose M here: the module
-         will be called sunhme.
-
-config SUNBMAC
-       tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)"
-       depends on SBUS && EXPERIMENTAL
-       select CRC32
-       help
-         This driver supports the "be" interface available as an Sbus option.
-         This is Sun's older 100baseT Ethernet device.
-
-         To compile this driver as a module, choose M here: the module
-         will be called sunbmac.
-
-config SUNQE
-       tristate "Sun QuadEthernet support"
-       depends on SBUS
-       select CRC32
-       help
-         This driver supports the "qe" 10baseT Ethernet device, available as
-         an Sbus option. Note that this is not the same as Quad FastEthernet
-         "qfe" which is supported by the Happy Meal driver instead.
-
-         To compile this driver as a module, choose M here: the module
-         will be called sunqe.
-
-config SUNGEM
-       tristate "Sun GEM support"
-       depends on PCI
-       select CRC32
-       help
-         Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0.  See also
-         <http://www.sun.com/products-n-solutions/hardware/docs/pdf/806-3985-10.pdf>.
-
-config CASSINI
-       tristate "Sun Cassini support"
-       depends on PCI
-       select CRC32
-       help
-         Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
-         <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
-
-config SUNVNET
-       tristate "Sun Virtual Network support"
-       depends on SUN_LDOMS
-       help
-         Support for virtual network devices under Sun Logical Domains.
-
-config NET_VENDOR_3COM
-       bool "3COM cards"
-       depends on ISA || EISA || MCA || PCI
-       help
-         If you have a network (Ethernet) card belonging to this class, say Y
-         and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         Note that the answer to this question doesn't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the questions about 3COM cards. If you say Y, you will be asked for
-         your specific card in the following questions.
-
-config EL1
-       tristate "3c501 \"EtherLink\" support"
-       depends on NET_VENDOR_3COM && ISA
-       ---help---
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.  Also, consider buying a
-         new card, since the 3c501 is slow, broken, and obsolete: you will
-         have problems.  Some people suggest to ping ("man ping") a nearby
-         machine every minute ("man cron") when using this card.
-
-         To compile this driver as a module, choose M here. The module
-         will be called 3c501.
-
-config EL2
-       tristate "3c503 \"EtherLink II\" support"
-       depends on NET_VENDOR_3COM && ISA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called 3c503.
-
-config ELPLUS
-       tristate "3c505 \"EtherLink Plus\" support"
-       depends on NET_VENDOR_3COM && ISA && ISA_DMA_API
-       ---help---
-         Information about this network (Ethernet) card can be found in
-         <file:Documentation/networking/3c505.txt>.  If you have a card of
-         this type, say Y and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called 3c505.
-
-config EL16
-       tristate "3c507 \"EtherLink 16\" support (EXPERIMENTAL)"
-       depends on NET_VENDOR_3COM && ISA && EXPERIMENTAL
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called 3c507.
-
-config EL3
-       tristate "3c509/3c529 (MCA)/3c579 \"EtherLink III\" support"
-       depends on NET_VENDOR_3COM && (ISA || EISA || MCA)
-       ---help---
-         If you have a network (Ethernet) card belonging to the 3Com
-         EtherLinkIII series, say Y and read the Ethernet-HOWTO, available
-         from <http://www.tldp.org/docs.html#howto>.
-
-         If your card is not working you may need to use the DOS
-         setup disk to disable Plug & Play mode, and to select the default
-         media type.
-
-         To compile this driver as a module, choose M here. The module
-         will be called 3c509.
-
-config 3C515
-       tristate "3c515 ISA \"Fast EtherLink\""
-       depends on NET_VENDOR_3COM && (ISA || EISA) && ISA_DMA_API
-       help
-         If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet
-         network card, say Y and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called 3c515.
-
-config ELMC
-       tristate "3c523 \"EtherLink/MC\" support"
-       depends on NET_VENDOR_3COM && MCA_LEGACY
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called 3c523.
-
-config ELMC_II
-       tristate "3c527 \"EtherLink/MC 32\" support (EXPERIMENTAL)"
-       depends on NET_VENDOR_3COM && MCA && MCA_LEGACY
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called 3c527.
-
-config VORTEX
-       tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support"
-       depends on NET_VENDOR_3COM && (PCI || EISA)
-       select MII
-       ---help---
-         This option enables driver support for a large number of 10Mbps and
-         10/100Mbps EISA, PCI and PCMCIA 3Com network cards:
-
-         "Vortex"    (Fast EtherLink 3c590/3c592/3c595/3c597) EISA and PCI
-         "Boomerang" (EtherLink XL 3c900 or 3c905)            PCI
-         "Cyclone"   (3c540/3c900/3c905/3c980/3c575/3c656)    PCI and Cardbus
-         "Tornado"   (3c905)                                  PCI
-         "Hurricane" (3c555/3cSOHO)                           PCI
-
-         If you have such a card, say Y and read the Ethernet-HOWTO,
-         available from <http://www.tldp.org/docs.html#howto>. More
-         specific information is in
-         <file:Documentation/networking/vortex.txt> and in the comments at
-         the beginning of <file:drivers/net/3c59x.c>.
-
-         To compile this support as a module, choose M here.
-
-config TYPHOON
-       tristate "3cr990 series \"Typhoon\" support"
-       depends on NET_VENDOR_3COM && PCI
-       select CRC32
-       ---help---
-         This option enables driver support for the 3cr990 series of cards:
-
-         3C990-TX, 3CR990-TX-95, 3CR990-TX-97, 3CR990-FX-95, 3CR990-FX-97,
-         3CR990SVR, 3CR990SVR95, 3CR990SVR97, 3CR990-FX-95 Server,
-         3CR990-FX-97 Server, 3C990B-TX-M, 3C990BSVR
-
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called typhoon.
-
-config LANCE
-       tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
-       depends on ISA && ISA_DMA_API
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>. Some LinkSys cards are
-         of this type.
-
-         To compile this driver as a module, choose M here: the module
-         will be called lance.  This is recommended.
-
-config NET_VENDOR_SMC
-       bool "Western Digital/SMC cards"
-       depends on ISA || MCA || EISA || MAC
-       help
-         If you have a network (Ethernet) card belonging to this class, say Y
-         and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         Note that the answer to this question doesn't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the questions about Western Digital cards. If you say Y, you will be
-         asked for your specific card in the following questions.
-
-config WD80x3
-       tristate "WD80*3 support"
-       depends on NET_VENDOR_SMC && ISA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called wd.
-
-config ULTRAMCA
-       tristate "SMC Ultra MCA support"
-       depends on NET_VENDOR_SMC && MCA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type and are running
-         an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
-         available from <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called smc-mca.
-
-config ULTRA
-       tristate "SMC Ultra support"
-       depends on NET_VENDOR_SMC && ISA
-       select CRC32
-       ---help---
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         Important: There have been many reports that, with some motherboards
-         mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible,
-         such as some BusLogic models) causes corruption problems with many
-         operating systems. The Linux smc-ultra driver has a work-around for
-         this but keep it in mind if you have such a SCSI card and have
-         problems.
-
-         To compile this driver as a module, choose M here. The module
-         will be called smc-ultra.
-
-config ULTRA32
-       tristate "SMC Ultra32 EISA support"
-       depends on NET_VENDOR_SMC && EISA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called smc-ultra32.
-
-config BFIN_MAC
-       tristate "Blackfin on-chip MAC support"
-       depends on NET_ETHERNET && (BF516 || BF518 || BF526 || BF527 || BF536 || BF537)
-       select CRC32
-       select MII
-       select PHYLIB
-       select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE
-       help
-         This is the driver for Blackfin on-chip mac device. Say Y if you want it
-         compiled into the kernel. This driver is also available as a module
-         ( = code which can be inserted in and removed from the running kernel
-         whenever you want). The module will be called bfin_mac.
-
-config BFIN_MAC_USE_L1
-       bool "Use L1 memory for rx/tx packets"
-       depends on BFIN_MAC && (BF527 || BF537)
-       default y
-       help
-         To get maximum network performance, you should use L1 memory as rx/tx buffers.
-         Say N here if you want to reserve L1 memory for other uses.
-
-config BFIN_TX_DESC_NUM
-       int "Number of transmit buffer packets"
-       depends on BFIN_MAC
-       range 6 10 if BFIN_MAC_USE_L1
-       range 10 100
-       default "10"
-       help
-         Set the number of buffer packets used in driver.
-
-config BFIN_RX_DESC_NUM
-       int "Number of receive buffer packets"
-       depends on BFIN_MAC
-       range 20 100 if BFIN_MAC_USE_L1
-       range 20 800
-       default "20"
-       help
-         Set the number of buffer packets used in driver.
-
-config BFIN_MAC_USE_HWSTAMP
-       bool "Use IEEE 1588 hwstamp"
-       depends on BFIN_MAC && BF518
-       default y
-       help
-         To support the IEEE 1588 Precision Time Protocol (PTP), select y here
-
-config SMC9194
-       tristate "SMC 9194 support"
-       depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
-       select CRC32
-       ---help---
-         This is support for the SMC9xxx based Ethernet cards. Choose this
-         option if you have a DELL laptop with the docking station, or
-         another SMC9192/9194 based chipset.  Say Y if you want it compiled
-         into the kernel, and read the file
-         <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
-         available from <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called smc9194.
-
-config SMC91X
-       tristate "SMC 91C9x/91C1xxx support"
-       select CRC32
-       select MII
-       depends on ARM || M32R || SUPERH || \
-               MIPS || BLACKFIN || MN10300 || COLDFIRE
-       help
-         This is a driver for SMC's 91x series of Ethernet chipsets,
-         including the SMC91C94 and the SMC91C111. Say Y if you want it
-         compiled into the kernel, and read the file
-         <file:Documentation/networking/smc9.txt>  and the Ethernet-HOWTO,
-         available from  <http://www.tldp.org/docs.html#howto>.
-
-         This driver is also available as a module ( = code which can be
-         inserted in and removed from the running kernel whenever you want).
-         The module will be called smc91x.  If you want to compile it as a
-         module, say M here and read <file:Documentation/kbuild/modules.txt>.
-
-config PXA168_ETH
-       tristate "Marvell pxa168 ethernet support"
-       depends on CPU_PXA168
-       select PHYLIB
-       help
-         This driver supports the pxa168 Ethernet ports.
-
-         To compile this driver as a module, choose M here. The module
-         will be called pxa168_eth.
-
-config NET_NETX
-       tristate "NetX Ethernet support"
-       select MII
-       depends on ARCH_NETX
-       help
-         This is support for the Hilscher netX builtin Ethernet ports
-
-         To compile this driver as a module, choose M here. The module
-         will be called netx-eth.
-
-config TI_DAVINCI_EMAC
-       tristate "TI DaVinci EMAC Support"
-       depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
-       select TI_DAVINCI_MDIO
-       select TI_DAVINCI_CPDMA
-       select PHYLIB
-       help
-         This driver supports TI's DaVinci Ethernet .
-
-         To compile this driver as a module, choose M here: the module
-         will be called davinci_emac_driver.  This is recommended.
-
-config TI_DAVINCI_MDIO
-       tristate "TI DaVinci MDIO Support"
-       depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
-       select PHYLIB
-       help
-         This driver supports TI's DaVinci MDIO module.
-
-         To compile this driver as a module, choose M here: the module
-         will be called davinci_mdio.  This is recommended.
-
-config TI_DAVINCI_CPDMA
-       tristate "TI DaVinci CPDMA Support"
-       depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
-       help
-         This driver supports TI's DaVinci CPDMA dma engine.
-
-         To compile this driver as a module, choose M here: the module
-         will be called davinci_cpdma.  This is recommended.
-
-config DM9000
-       tristate "DM9000 support"
-       depends on ARM || BLACKFIN || MIPS
-       select CRC32
-       select MII
-       ---help---
-         Support for DM9000 chipset.
-
-         To compile this driver as a module, choose M here.  The module
-         will be called dm9000.
-
-config DM9000_DEBUGLEVEL
-       int "DM9000 maximum debug level"
-       depends on DM9000
-       default 4
-       help
-         The maximum level of debugging code compiled into the DM9000
-         driver.
-
-config DM9000_FORCE_SIMPLE_PHY_POLL
-       bool "Force simple NSR based PHY polling"
-       depends on DM9000
-       ---help---
-         This configuration forces the DM9000 to use the NSR's LinkStatus
-         bit to determine if the link is up or down instead of the more
-         costly MII PHY reads. Note, this will not work if the chip is
-         operating with an external PHY.
-
-config ENC28J60
-       tristate "ENC28J60 support"
-       depends on EXPERIMENTAL && SPI && NET_ETHERNET
-       select CRC32
-       ---help---
-         Support for the Microchip EN28J60 ethernet chip.
-
-         To compile this driver as a module, choose M here. The module will be
-         called enc28j60.
-
-config ENC28J60_WRITEVERIFY
-       bool "Enable write verify"
-       depends on ENC28J60
-       ---help---
-         Enable the verify after the buffer write useful for debugging purpose.
-         If unsure, say N.
-
-config ETHOC
-       tristate "OpenCores 10/100 Mbps Ethernet MAC support"
-       depends on NET_ETHERNET && HAS_IOMEM && HAS_DMA
-       select MII
-       select PHYLIB
-       select CRC32
-       select BITREVERSE
-       help
-         Say Y here if you want to use the OpenCores 10/100 Mbps Ethernet MAC.
-
-config GRETH
-       tristate "Aeroflex Gaisler GRETH Ethernet MAC support"
-       depends on SPARC
-       select PHYLIB
-       select CRC32
-       help
-         Say Y here if you want to use the Aeroflex Gaisler GRETH Ethernet MAC.
-
-config SMC911X
-       tristate "SMSC LAN911[5678] support"
-       select CRC32
-       select MII
-       depends on ARM || SUPERH || MN10300
-       help
-         This is a driver for SMSC's LAN911x series of Ethernet chipsets
-         including the new LAN9115, LAN9116, LAN9117, and LAN9118.
-         Say Y if you want it compiled into the kernel, 
-         and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         This driver is also available as a module. The module will be 
-         called smc911x.  If you want to compile it as a module, say M 
-         here and read <file:Documentation/kbuild/modules.txt>
-
-config SMSC911X
-       tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
-       depends on ARM || SUPERH || BLACKFIN || MIPS || MN10300
-       select CRC32
-       select MII
-       select PHYLIB
-       ---help---
-         Say Y here if you want support for SMSC LAN911x and LAN921x families
-         of ethernet controllers.
-
-         To compile this driver as a module, choose M here and read
-         <file:Documentation/networking/net-modules.txt>. The module
-         will be called smsc911x.
-
-config SMSC911X_ARCH_HOOKS
-       def_bool n
-       depends on SMSC911X
-       help
-         If the arch enables this, it allows the arch to implement various
-         hooks for more comprehensive interrupt control and also to override
-         the source of the MAC address.
-
-config NET_VENDOR_RACAL
-       bool "Racal-Interlan (Micom) NI cards"
-       depends on ISA
-       help
-         If you have a network (Ethernet) card belonging to this class, such
-         as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
-         available from <http://www.tldp.org/docs.html#howto>.
-
-         Note that the answer to this question doesn't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the questions about NI cards. If you say Y, you will be asked for
-         your specific card in the following questions.
-
-config NI5010
-       tristate "NI5010 support (EXPERIMENTAL)"
-       depends on NET_VENDOR_RACAL && ISA && EXPERIMENTAL && BROKEN_ON_SMP
-       ---help---
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>. Note that this is still
-         experimental code.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ni5010.
-
-config NI52
-       tristate "NI5210 support"
-       depends on NET_VENDOR_RACAL && ISA
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ni52.
-
-config NI65
-       tristate "NI6510 support"
-       depends on NET_VENDOR_RACAL && ISA && ISA_DMA_API
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ni65.
-
-config DNET
-       tristate "Dave ethernet support (DNET)"
-       depends on NET_ETHERNET && HAS_IOMEM
-       select PHYLIB
-       help
-         The Dave ethernet interface (DNET) is found on Qong Board FPGA.
-         Say Y to include support for the DNET chip.
-
-         To compile this driver as a module, choose M here: the module
-         will be called dnet.
-
-source "drivers/net/tulip/Kconfig"
-
-config AT1700
-       tristate "AT1700/1720 support (EXPERIMENTAL)"
-       depends on (ISA || MCA_LEGACY) && EXPERIMENTAL
-       select CRC32
-       ---help---
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called at1700.
-
-config DEPCA
-       tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support"
-       depends on ISA || EISA || MCA
-       select CRC32
-       ---help---
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto> as well as
-         <file:drivers/net/depca.c>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called depca.
-
-config HP100
-       tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support"
-       depends on ISA || EISA || PCI
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called hp100.
-
-config NET_ISA
-       bool "Other ISA cards"
-       depends on ISA
-       ---help---
-         If your network (Ethernet) card hasn't been mentioned yet and its
-         bus system (that's the way the cards talks to the other components
-         of your computer) is ISA (as opposed to EISA, VLB or PCI), say Y.
-         Make sure you know the name of your card. Read the Ethernet-HOWTO,
-         available from <http://www.tldp.org/docs.html#howto>.
-
-         If unsure, say Y.
-
-         Note that the answer to this question doesn't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the remaining ISA network card questions. If you say Y, you will be
-         asked for your specific card in the following questions.
-
-config E2100
-       tristate "Cabletron E21xx support"
-       depends on NET_ISA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called e2100.
-
-config EWRK3
-       tristate "EtherWORKS 3 (DE203, DE204, DE205) support"
-       depends on NET_ISA
-       select CRC32
-       ---help---
-         This driver supports the DE203, DE204 and DE205 network (Ethernet)
-         cards. If this is for you, say Y and read
-         <file:Documentation/networking/ewrk3.txt> in the kernel source as
-         well as the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ewrk3.
-
-config EEXPRESS
-       tristate "EtherExpress 16 support"
-       depends on NET_ISA
-       ---help---
-         If you have an EtherExpress16 network (Ethernet) card, say Y and
-         read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.  Note that the Intel
-         EtherExpress16 card used to be regarded as a very poor choice
-         because the driver was very unreliable. We now have a new driver
-         that should do better.
-
-         To compile this driver as a module, choose M here. The module
-         will be called eexpress.
-
-config EEXPRESS_PRO
-       tristate "EtherExpressPro support/EtherExpress 10 (i82595) support"
-       depends on NET_ISA
-       ---help---
-         If you have a network (Ethernet) card of this type, say Y. This
-         driver supports Intel i82595{FX,TX} based boards. Note however
-         that the EtherExpress PRO/100 Ethernet card has its own separate
-         driver.  Please read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called eepro.
-
-config HPLAN_PLUS
-       tristate "HP PCLAN+ (27247B and 27252A) support"
-       depends on NET_ISA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called hp-plus.
-
-config HPLAN
-       tristate "HP PCLAN (27245 and other 27xxx series) support"
-       depends on NET_ISA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called hp.
-
-config LP486E
-       tristate "LP486E on board Ethernet"
-       depends on NET_ISA
-       help
-         Say Y here to support the 82596-based on-board Ethernet controller
-         for the Panther motherboard, which is one of the two shipped in the
-         Intel Professional Workstation.
-
-config ETH16I
-       tristate "ICL EtherTeam 16i/32 support"
-       depends on NET_ISA
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called eth16i.
-
-config NE2000
-       tristate "NE2000/NE1000 support"
-       depends on NET_ISA || (Q40 && m) || M32R || MACH_TX49XX
-       select CRC32
-       ---help---
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.  Many Ethernet cards
-         without a specific driver are compatible with NE2000.
-
-         If you have a PCI NE2000 card however, say N here and Y to "PCI
-         NE2000 and clone support" under "EISA, VLB, PCI and on board
-         controllers" below. If you have a NE2000 card and are running on
-         an MCA system (a bus system used on some IBM PS/2 computers and
-         laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
-         below.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ne.
-
-config ZNET
-       tristate "Zenith Z-Note support (EXPERIMENTAL)"
-       depends on NET_ISA && EXPERIMENTAL && ISA_DMA_API
-       help
-         The Zenith Z-Note notebook computer has a built-in network
-         (Ethernet) card, and this is the Linux driver for it. Note that the
-         IBM Thinkpad 300 is compatible with the Z-Note and is also supported
-         by this driver. Read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-config SEEQ8005
-       tristate "SEEQ8005 support (EXPERIMENTAL)"
-       depends on NET_ISA && EXPERIMENTAL
-       help
-         This is a driver for the SEEQ 8005 network (Ethernet) card.  If this
-         is for you, read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called seeq8005.
-
-config NE2_MCA
-       tristate "NE/2 (ne2000 MCA version) support"
-       depends on MCA_LEGACY
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ne2.
-
-config IBMLANA
-       tristate "IBM LAN Adapter/A support"
-       depends on MCA
-       ---help---
-         This is a Micro Channel Ethernet adapter.  You need to set
-         CONFIG_MCA to use this driver.  It is both available as an in-kernel
-         driver and as a module.
-
-         To compile this driver as a module, choose M here. The only
-         currently supported card is the IBM LAN Adapter/A for Ethernet.  It
-         will both support 16K and 32K memory windows, however a 32K window
-         gives a better security against packet losses.  Usage of multiple
-         boards with this driver should be possible, but has not been tested
-         up to now due to lack of hardware.
-
-config IBMVETH
-       tristate "IBM LAN Virtual Ethernet support"
-       depends on PPC_PSERIES
-       ---help---
-         This driver supports virtual ethernet adapters on newer IBM iSeries
-         and pSeries systems.
-
-         To compile this driver as a module, choose M here. The module will
-         be called ibmveth.
-
-source "drivers/net/ibm_newemac/Kconfig"
-
-config NET_PCI
-       bool "EISA, VLB, PCI and on board controllers"
-       depends on ISA || EISA || PCI
-       help
-         This is another class of network cards which attach directly to the
-         bus. If you have one of those, say Y and read the Ethernet-HOWTO,
-         available from <http://www.tldp.org/docs.html#howto>.
-
-         Note that the answer to this question doesn't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the questions about this class of network cards. If you say Y, you
-         will be asked for your specific card in the following questions. If
-         you are unsure, say Y.
-
-config PCNET32
-       tristate "AMD PCnet32 PCI support"
-       depends on NET_PCI && PCI
-       select CRC32
-       select MII
-       help
-         If you have a PCnet32 or PCnetPCI based network (Ethernet) card,
-         answer Y here and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called pcnet32.
-
-config AMD8111_ETH
-       tristate "AMD 8111 (new PCI lance) support"
-       depends on NET_PCI && PCI
-       select CRC32
-       select MII
-       help
-         If you have an AMD 8111-based PCI lance ethernet card,
-         answer Y here and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called amd8111e.
-
-config ADAPTEC_STARFIRE
-       tristate "Adaptec Starfire/DuraLAN support"
-       depends on NET_PCI && PCI
-       select CRC32
-       select MII
-       help
-         Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network
-         adapter. The DuraLAN chip is used on the 64 bit PCI boards from
-         Adaptec e.g. the ANA-6922A. The older 32 bit boards use the tulip
-         driver.
-
-         To compile this driver as a module, choose M here: the module
-         will be called starfire.  This is recommended.
-
-config AC3200
-       tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)"
-       depends on NET_PCI && (ISA || EISA) && EXPERIMENTAL
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ac3200.
-
-config KSZ884X_PCI
-       tristate "Micrel KSZ8841/2 PCI"
-       depends on NET_PCI && PCI
-       select MII
-       select CRC32
-       help
-         This PCI driver is for Micrel KSZ8841/KSZ8842 PCI Ethernet chip.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ksz884x.
-
-config APRICOT
-       tristate "Apricot Xen-II on board Ethernet"
-       depends on NET_PCI && ISA
-       help
-         If you have a network (Ethernet) controller of this type, say Y and
-         read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called apricot.
-
-config B44
-       tristate "Broadcom 440x/47xx ethernet support"
-       depends on SSB_POSSIBLE && HAS_DMA
-       select SSB
-       select MII
-       help
-         If you have a network (Ethernet) controller of this type, say Y
-         or M and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called b44.
-
-# Auto-select SSB PCI-HOST support, if possible
-config B44_PCI_AUTOSELECT
-       bool
-       depends on B44 && SSB_PCIHOST_POSSIBLE
-       select SSB_PCIHOST
-       default y
-
-# Auto-select SSB PCICORE driver, if possible
-config B44_PCICORE_AUTOSELECT
-       bool
-       depends on B44 && SSB_DRIVER_PCICORE_POSSIBLE
-       select SSB_DRIVER_PCICORE
-       default y
-
-config B44_PCI
-       bool
-       depends on B44_PCI_AUTOSELECT && B44_PCICORE_AUTOSELECT
-       default y
-
-config FORCEDETH
-       tristate "nForce Ethernet support"
-       depends on NET_PCI && PCI
-       help
-         If you have a network (Ethernet) controller of this type, say Y and
-         read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called forcedeth.
-
-config CS89x0
-       tristate "CS89x0 support"
-       depends on NET_ETHERNET && (ISA || EISA || MACH_IXDP2351 \
-               || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440)
-       ---help---
-         Support for CS89x0 chipset based Ethernet cards. If you have a
-         network (Ethernet) card of this type, say Y and read the
-         Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto> as well as
-         <file:Documentation/networking/cs89x0.txt>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called cs89x0.
-
-config CS89x0_NONISA_IRQ
-       def_bool y
-       depends on CS89x0 != n
-       depends on MACH_IXDP2351 || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440
-
-config TC35815
-       tristate "TOSHIBA TC35815 Ethernet support"
-       depends on NET_PCI && PCI && MIPS
-       select PHYLIB
-
-config E100
-       tristate "Intel(R) PRO/100+ support"
-       depends on NET_PCI && PCI
-       select MII
-       ---help---
-         This driver supports Intel(R) PRO/100 family of adapters.
-         To verify that your adapter is supported, find the board ID number 
-         on the adapter. Look for a label that has a barcode and a number 
-         in the format 123456-001 (six digits hyphen three digits). 
-
-         Use the above information and the Adapter & Driver ID Guide at:
-
-         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
-         to identify the adapter.
-
-         For the latest Intel PRO/100 network driver for Linux, see:
-
-         <http://www.intel.com/p/en_US/support/highlights/network/pro100plus>
-
-         More specific information on configuring the driver is in 
-         <file:Documentation/networking/e100.txt>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called e100.
-
-config LNE390
-       tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
-       depends on NET_PCI && EISA && EXPERIMENTAL
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called lne390.
-
-config FEALNX
-       tristate "Myson MTD-8xx PCI Ethernet support"
-       depends on NET_PCI && PCI
-       select CRC32
-       select MII
-       help
-         Say Y here to support the Myson MTD-800 family of PCI-based Ethernet 
-         cards. <http://www.myson.com.tw/>
-
-config NATSEMI
-       tristate "National Semiconductor DP8381x series PCI Ethernet support"
-       depends on NET_PCI && PCI
-       select CRC32
-       help
-         This driver is for the National Semiconductor DP83810 series,
-         which is used in cards from PureData, NetGear, Linksys
-         and others, including the 83815 chip.
-         More specific information and updates are available from
-         <http://www.scyld.com/network/natsemi.html>.
-
-config NE2K_PCI
-       tristate "PCI NE2000 and clones support (see help)"
-       depends on NET_PCI && PCI
-       select CRC32
-       ---help---
-         This driver is for NE2000 compatible PCI cards. It will not work
-         with ISA NE2000 cards (they have their own driver, "NE2000/NE1000
-         support" below). If you have a PCI NE2000 network (Ethernet) card,
-         say Y and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         This driver also works for the following NE2000 clone cards:
-         RealTek RTL-8029  Winbond 89C940  Compex RL2000  KTI ET32P2
-         NetVin NV5000SC   Via 86C926      SureCom NE34   Winbond
-         Holtek HT80232    Holtek HT80229
-
-         To compile this driver as a module, choose M here. The module
-         will be called ne2k-pci.
-
-config NE3210
-       tristate "Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)"
-       depends on NET_PCI && EISA && EXPERIMENTAL
-       select CRC32
-       ---help---
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.  Note that this driver
-         will NOT WORK for NE3200 cards as they are completely different.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ne3210.
-
-config ES3210
-       tristate "Racal-Interlan EISA ES3210 support (EXPERIMENTAL)"
-       depends on NET_PCI && EISA && EXPERIMENTAL
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called es3210.
-
-config 8139CP
-       tristate "RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL)"
-       depends on NET_PCI && PCI && EXPERIMENTAL
-       select CRC32
-       select MII
-       help
-         This is a driver for the Fast Ethernet PCI network cards based on
-         the RTL8139C+ chips. If you have one of those, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here: the module
-         will be called 8139cp.  This is recommended.
-
-config 8139TOO
-       tristate "RealTek RTL-8129/8130/8139 PCI Fast Ethernet Adapter support"
-       depends on NET_PCI && PCI
-       select CRC32
-       select MII
-       ---help---
-         This is a driver for the Fast Ethernet PCI network cards based on
-         the RTL 8129/8130/8139 chips. If you have one of those, say Y and
-         read the Ethernet-HOWTO <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here: the module
-         will be called 8139too.  This is recommended.
-
-config 8139TOO_PIO
-       bool "Use PIO instead of MMIO"
-       default y
-       depends on 8139TOO
-       help
-         This instructs the driver to use programmed I/O ports (PIO) instead
-         of PCI shared memory (MMIO).  This can possibly solve some problems
-         in case your mainboard has memory consistency issues.  If unsure,
-         say N.
-
-config 8139TOO_TUNE_TWISTER
-       bool "Support for uncommon RTL-8139 rev. K (automatic channel equalization)"
-       depends on 8139TOO
-       help
-         This implements a function which might come in handy in case you
-         are using low quality on long cabling. It is required for RealTek
-         RTL-8139 revision K boards, and totally unused otherwise.  It tries
-         to match the transceiver to the cable characteristics. This is
-         experimental since hardly documented by the manufacturer.
-         If unsure, say Y.
-
-config 8139TOO_8129
-       bool "Support for older RTL-8129/8130 boards"
-       depends on 8139TOO
-       help
-         This enables support for the older and uncommon RTL-8129 and
-         RTL-8130 chips, which support MII via an external transceiver,
-         instead of an internal one.  Disabling this option will save some
-         memory by making the code size smaller.  If unsure, say Y.
-
-config 8139_OLD_RX_RESET
-       bool "Use older RX-reset method"
-       depends on 8139TOO
-       help
-         The 8139too driver was recently updated to contain a more rapid
-         reset sequence, in the face of severe receive errors.  This "new"
-         RX-reset method should be adequate for all boards.  But if you
-         experience problems, you can enable this option to restore the
-         old RX-reset behavior.  If unsure, say N.
-
-config R6040
-       tristate "RDC R6040 Fast Ethernet Adapter support"
-       depends on NET_PCI && PCI
-       select CRC32
-       select MII
-       select PHYLIB
-       help
-         This is a driver for the R6040 Fast Ethernet MACs found in the
-         the RDC R-321x System-on-chips.
-
-         To compile this driver as a module, choose M here: the module
-         will be called r6040. This is recommended.
-
-config SIS900
-       tristate "SiS 900/7016 PCI Fast Ethernet Adapter support"
-       depends on NET_PCI && PCI
-       select CRC32
-       select MII
-       ---help---
-         This is a driver for the Fast Ethernet PCI network cards based on
-         the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in
-         SiS 630 and SiS 540 chipsets.
-
-         This driver also supports AMD 79C901 HomePNA so that you can use
-         your phone line as a network cable.
-
-         To compile this driver as a module, choose M here: the module
-         will be called sis900.  This is recommended.
-
-config EPIC100
-       tristate "SMC EtherPower II"
-       depends on NET_PCI && PCI
-       select CRC32
-       select MII
-       help
-         This driver is for the SMC EtherPower II 9432 PCI Ethernet NIC,
-         which is based on the SMC83c17x (EPIC/100).
-         More specific information and updates are available from
-         <http://www.scyld.com/network/epic100.html>.
-
-config SMSC9420
-       tristate "SMSC LAN9420 PCI ethernet adapter support"
-       depends on NET_PCI && PCI
-       select CRC32
-       select PHYLIB
-       select SMSC_PHY
-       help
-         This is a driver for SMSC's LAN9420 PCI ethernet adapter.
-         Say Y if you want it compiled into the kernel,
-         and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         This driver is also available as a module. The module will be
-         called smsc9420.  If you want to compile it as a module, say M
-         here and read <file:Documentation/kbuild/modules.txt>
-
-config SUNDANCE
-       tristate "Sundance Alta support"
-       depends on NET_PCI && PCI
-       select CRC32
-       select MII
-       help
-         This driver is for the Sundance "Alta" chip.
-         More specific information and updates are available from
-         <http://www.scyld.com/network/sundance.html>.
-
-config SUNDANCE_MMIO
-       bool "Use MMIO instead of PIO"
-       depends on SUNDANCE
-       help
-         Enable memory-mapped I/O for interaction with Sundance NIC registers.
-         Do NOT enable this by default, PIO (enabled when MMIO is disabled)
-         is known to solve bugs on certain chips.
-
-         If unsure, say N.
-
-config TLAN
-       tristate "TI ThunderLAN support"
-       depends on NET_PCI && (PCI || EISA)
-       ---help---
-         If you have a PCI Ethernet network card based on the ThunderLAN chip
-         which is supported by this driver, say Y and read the
-         Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         Devices currently supported by this driver are Compaq Netelligent,
-         Compaq NetFlex and Olicom cards.  Please read the file
-         <file:Documentation/networking/tlan.txt> for more details.
-
-         To compile this driver as a module, choose M here. The module
-         will be called tlan.
-
-         Please email feedback to <torben.mathiasen@compaq.com>.
-
-config KS8842
-       tristate "Micrel KSZ8841/42 with generic bus interface"
-       depends on HAS_IOMEM && DMA_ENGINE
-       help
-         This platform driver is for KSZ8841(1-port) / KS8842(2-port)
-         ethernet switch chip (managed, VLAN, QoS) from Micrel or
-         Timberdale(FPGA).
-
-config KS8851
-       tristate "Micrel KS8851 SPI"
-       depends on SPI
-       select MII
-       select CRC32
-       help
-         SPI driver for Micrel KS8851 SPI attached network chip.
-
-config KS8851_MLL
-       tristate "Micrel KS8851 MLL"
-       depends on HAS_IOMEM
-       select MII
-       help
-         This platform driver is for Micrel KS8851 Address/data bus
-         multiplexed network chip.
-
-config VIA_RHINE
-       tristate "VIA Rhine support"
-       depends on NET_PCI && PCI
-       select CRC32
-       select MII
-       help
-         If you have a VIA "Rhine" based network card (Rhine-I (VT86C100A),
-         Rhine-II (VT6102), or Rhine-III (VT6105)), say Y here. Rhine-type
-         Ethernet functions can also be found integrated on South Bridges
-         (e.g. VT8235).
-
-         To compile this driver as a module, choose M here. The module
-         will be called via-rhine.
-
-config VIA_RHINE_MMIO
-       bool "Use MMIO instead of PIO"
-       depends on VIA_RHINE
-       help
-         This instructs the driver to use PCI shared memory (MMIO) instead of
-         programmed I/O ports (PIO). Enabling this gives an improvement in
-         processing time in parts of the driver.
-
-         If unsure, say Y.
-
-config SC92031
-       tristate "Silan SC92031 PCI Fast Ethernet Adapter driver (EXPERIMENTAL)"
-       depends on NET_PCI && PCI && EXPERIMENTAL
-       select CRC32
-       ---help---
-         This is a driver for the Fast Ethernet PCI network cards based on
-         the Silan SC92031 chip (sometimes also called Rsltek 8139D). If you
-         have one of these, say Y here.
-
-         To compile this driver as a module, choose M here: the module
-         will be called sc92031.  This is recommended.
-
-config CPMAC
-       tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)"
-       depends on NET_ETHERNET && EXPERIMENTAL && AR7
-       select PHYLIB
-       help
-         TI AR7 CPMAC Ethernet support
-
-config NET_POCKET
-       bool "Pocket and portable adapters"
-       depends on PARPORT
-       ---help---
-         Cute little network (Ethernet) devices which attach to the parallel
-         port ("pocket adapters"), commonly used with laptops. If you have
-         one of those, say Y and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         If you want to plug a network (or some other) card into the PCMCIA
-         (or PC-card) slot of your laptop instead (PCMCIA is the standard for
-         credit card size extension cards used by all modern laptops), you
-         need the pcmcia-cs package (location contained in the file
-         <file:Documentation/Changes>) and you can say N here.
-
-         Laptop users should read the Linux Laptop home page at
-         <http://www.linux-on-laptops.com/> or
-         Tuxmobil - Linux on Mobile Computers at <http://www.tuxmobil.org/>.
-
-         Note that the answer to this question doesn't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the questions about this class of network devices. If you say Y, you
-         will be asked for your specific device in the following questions.
-
-config ATP
-       tristate "AT-LAN-TEC/RealTek pocket adapter support"
-       depends on NET_POCKET && PARPORT && X86
-       select CRC32
-       ---help---
-         This is a network (Ethernet) device which attaches to your parallel
-         port. Read <file:drivers/net/atp.c> as well as the Ethernet-HOWTO,
-         available from <http://www.tldp.org/docs.html#howto>, if you
-         want to use this.  If you intend to use this driver, you should have
-         said N to the "Parallel printer support", because the two drivers
-         don't like each other.
-
-         To compile this driver as a module, choose M here: the module
-         will be called atp.
-
-config DE600
-       tristate "D-Link DE600 pocket adapter support"
-       depends on NET_POCKET && PARPORT
-       ---help---
-         This is a network (Ethernet) device which attaches to your parallel
-         port. Read <file:Documentation/networking/DLINK.txt> as well as the
-         Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, if you want to use
-         this. It is possible to have several devices share a single parallel
-         port and it is safe to compile the corresponding drivers into the
-         kernel.
-
-         To compile this driver as a module, choose M here: the module
-         will be called de600.
-
-config DE620
-       tristate "D-Link DE620 pocket adapter support"
-       depends on NET_POCKET && PARPORT
-       ---help---
-         This is a network (Ethernet) device which attaches to your parallel
-         port. Read <file:Documentation/networking/DLINK.txt> as well as the
-         Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, if you want to use
-         this. It is possible to have several devices share a single parallel
-         port and it is safe to compile the corresponding drivers into the
-         kernel.
-
-         To compile this driver as a module, choose M here: the module
-         will be called de620.
-
-config SGISEEQ
-       tristate "SGI Seeq ethernet controller support"
-       depends on SGI_HAS_SEEQ
-       help
-         Say Y here if you have an Seeq based Ethernet network card. This is
-         used in many Silicon Graphics machines.
-
-config DECLANCE
-       tristate "DEC LANCE ethernet controller support"
-       depends on MACH_DECSTATION
-       select CRC32
-       help
-         This driver is for the series of Ethernet controllers produced by
-         DEC (now Compaq) based on the AMD Lance chipset, including the
-         DEPCA series.  (This chipset is better known via the NE2100 cards.)
-
-config FEC
-       bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
-       depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
-               IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC
-       default IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC if ARM
-       select PHYLIB
-       help
-         Say Y here if you want to use the built-in 10/100 Fast ethernet
-         controller on some Motorola ColdFire and Freescale i.MX processors.
-
-config FEC_MPC52xx
-       tristate "MPC52xx FEC driver"
-       depends on PPC_MPC52xx && PPC_BESTCOMM
-       select CRC32
-       select PHYLIB
-       select PPC_BESTCOMM_FEC
-       ---help---
-         This option enables support for the MPC5200's on-chip
-         Fast Ethernet Controller
-         If compiled as module, it will be called fec_mpc52xx.
-
-config FEC_MPC52xx_MDIO
-       bool "MPC52xx FEC MDIO bus driver"
-       depends on FEC_MPC52xx
-       default y
-       ---help---
-         The MPC5200's FEC can connect to the Ethernet either with
-         an external MII PHY chip or 10 Mbps 7-wire interface
-         (Motorola? industry standard).
-         If your board uses an external PHY connected to FEC, enable this.
-         If not sure, enable.
-         If compiled as module, it will be called fec_mpc52xx_phy.
-
-config NE_H8300
-       tristate "NE2000 compatible support for H8/300"
-       depends on H8300
-       help
-         Say Y here if you want to use the NE2000 compatible
-         controller on the Renesas H8/300 processor.
-
-config ATL2
-       tristate "Atheros L2 Fast Ethernet support"
-       depends on PCI
-       select CRC32
-       select MII
-       help
-         This driver supports the Atheros L2 fast ethernet adapter.
-
-         To compile this driver as a module, choose M here.  The module
-         will be called atl2.
-
-config XILINX_EMACLITE
-       tristate "Xilinx 10/100 Ethernet Lite support"
-       depends on PPC32 || MICROBLAZE
-       select PHYLIB
-       help
-         This driver supports the 10/100 Ethernet Lite from Xilinx.
-
-config BCM63XX_ENET
-       tristate "Broadcom 63xx internal mac support"
-       depends on BCM63XX
-       select MII
-       select PHYLIB
-       help
-         This driver supports the ethernet MACs in the Broadcom 63xx
-         MIPS chipset family (BCM63XX).
-
-config FTMAC100
-       tristate "Faraday FTMAC100 10/100 Ethernet support"
-       depends on ARM
-       select MII
-       help
-         This driver supports the FTMAC100 10/100 Ethernet controller
-         from Faraday. It is used on Faraday A320, Andes AG101 and some
-         other ARM/NDS32 SoC's.
-
-config LANTIQ_ETOP
-       tristate "Lantiq SoC ETOP driver"
-       depends on SOC_TYPE_XWAY
-       help
-         Support for the MII0 inside the Lantiq SoC
-
-
-source "drivers/net/fs_enet/Kconfig"
-
-source "drivers/net/octeon/Kconfig"
-
-endif # NET_ETHERNET
-
-#
-#      Gigabit Ethernet
-#
-
-menuconfig NETDEV_1000
-       bool "Ethernet (1000 Mbit)"
-       depends on !UML
-       default y
-       ---help---
-         Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
-         type of Local Area Network (LAN) in universities and companies.
-
-         Say Y here to get to see options for Gigabit Ethernet drivers.
-         This option alone does not add any kernel code.
-         Note that drivers supporting both 100 and 1000 MBit may be listed
-         under "Ethernet (10 or 100MBit)" instead.
-
-         If you say N, all options in this submenu will be skipped and disabled.
-
-if NETDEV_1000
-
-config ACENIC
-       tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
-       depends on PCI
-       ---help---
-         Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear
-         GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit Ethernet
-         adapter. The driver allows for using the Jumbo Frame option (9000
-         bytes/frame) however it requires that your switches can handle this
-         as well. To enable Jumbo Frames, add `mtu 9000' to your ifconfig
-         line.
-
-         To compile this driver as a module, choose M here: the
-         module will be called acenic.
-
-config ACENIC_OMIT_TIGON_I
-       bool "Omit support for old Tigon I based AceNICs"
-       depends on ACENIC
-       help
-         Say Y here if you only have Tigon II based AceNICs and want to leave
-         out support for the older Tigon I based cards which are no longer
-         being sold (ie. the original Alteon AceNIC and 3Com 3C985 (non B
-         version)).  This will reduce the size of the driver object by
-         app. 100KB.  If you are not sure whether your card is a Tigon I or a
-         Tigon II, say N here.
-
-         The safe and default value for this is N.
-
-config DL2K
-       tristate "DL2000/TC902x-based Gigabit Ethernet support"
-       depends on PCI
-       select CRC32
-       help
-         This driver supports DL2000/TC902x-based Gigabit ethernet cards,
-         which includes
-         D-Link DGE-550T Gigabit Ethernet Adapter.
-         D-Link DL2000-based Gigabit Ethernet Adapter.
-         Sundance/Tamarack TC902x Gigabit Ethernet Adapter.
-
-         To compile this driver as a module, choose M here: the
-         module will be called dl2k.
-
-config E1000
-       tristate "Intel(R) PRO/1000 Gigabit Ethernet support"
-       depends on PCI
-       ---help---
-         This driver supports Intel(R) PRO/1000 gigabit ethernet family of
-         adapters.  For more information on how to identify your adapter, go 
-         to the Adapter & Driver ID Guide at:
-
-         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
-         For general information and support, go to the Intel support
-         website at:
-
-         <http://support.intel.com>
-
-         More specific information on configuring the driver is in 
-         <file:Documentation/networking/e1000.txt>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called e1000.
-
-config E1000E
-       tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
-       depends on PCI && (!SPARC32 || BROKEN)
-       select CRC32
-       ---help---
-         This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
-         ethernet family of adapters. For PCI or PCI-X e1000 adapters,
-         use the regular e1000 driver For more information on how to
-         identify your adapter, go to the Adapter & Driver ID Guide at:
-
-         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
-         For general information and support, go to the Intel support
-         website at:
-
-         <http://support.intel.com>
-
-         To compile this driver as a module, choose M here. The module
-         will be called e1000e.
-
-config IP1000
-       tristate "IP1000 Gigabit Ethernet support"
-       depends on PCI && EXPERIMENTAL
-       select MII
-       ---help---
-         This driver supports IP1000 gigabit Ethernet cards.
-
-         To compile this driver as a module, choose M here: the module
-         will be called ipg.  This is recommended.
-
-config IGB
-       tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
-       depends on PCI
-       ---help---
-         This driver supports Intel(R) 82575/82576 gigabit ethernet family of
-         adapters.  For more information on how to identify your adapter, go
-         to the Adapter & Driver ID Guide at:
-
-         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
-         For general information and support, go to the Intel support
-         website at:
-
-         <http://support.intel.com>
-
-         More specific information on configuring the driver is in
-         <file:Documentation/networking/e1000.txt>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called igb.
-
-config IGB_DCA
-       bool "Direct Cache Access (DCA) Support"
-       default y
-       depends on IGB && DCA && !(IGB=y && DCA=m)
-       ---help---
-         Say Y here if you want to use Direct Cache Access (DCA) in the
-         driver.  DCA is a method for warming the CPU cache before data
-         is used, with the intent of lessening the impact of cache misses.
-
-config IGBVF
-       tristate "Intel(R) 82576 Virtual Function Ethernet support"
-       depends on PCI
-       ---help---
-         This driver supports Intel(R) 82576 virtual functions.  For more
-         information on how to identify your adapter, go to the Adapter &
-         Driver ID Guide at:
-
-         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
-         For general information and support, go to the Intel support
-         website at:
-
-         <http://support.intel.com>
-
-         More specific information on configuring the driver is in
-         <file:Documentation/networking/e1000.txt>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called igbvf.
-
-source "drivers/net/ixp2000/Kconfig"
-
-config NS83820
-       tristate "National Semiconductor DP83820 support"
-       depends on PCI
-       help
-         This is a driver for the National Semiconductor DP83820 series
-         of gigabit ethernet MACs.  Cards using this chipset include
-         the D-Link DGE-500T, PureData's PDP8023Z-TG, SMC's SMC9462TX,
-         SOHO-GA2000T, SOHO-GA2500T.  The driver supports the use of
-         zero copy.
-
-config HAMACHI
-       tristate "Packet Engines Hamachi GNIC-II support"
-       depends on PCI
-       select MII
-       help
-         If you have a Gigabit Ethernet card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module will be
-         called hamachi.
-
-config YELLOWFIN
-       tristate "Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)"
-       depends on PCI && EXPERIMENTAL
-       select CRC32
-       ---help---
-         Say Y here if you have a Packet Engines G-NIC PCI Gigabit Ethernet
-         adapter or the SYM53C885 Ethernet controller. The Gigabit adapter is
-         used by the Beowulf Linux cluster project.  See
-         <http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html> for more
-         information about this driver in particular and Beowulf in general.
-
-         To compile this driver as a module, choose M here: the module
-         will be called yellowfin.  This is recommended.
-
-config R8169
-       tristate "Realtek 8169 gigabit ethernet support"
-       depends on PCI
-       select FW_LOADER
-       select CRC32
-       select MII
-       ---help---
-         Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter.
-
-         To compile this driver as a module, choose M here: the module
-         will be called r8169.  This is recommended.
-
-config SB1250_MAC
-       tristate "SB1250 Gigabit Ethernet support"
-       depends on SIBYTE_SB1xxx_SOC
-       select PHYLIB
-       ---help---
-         This driver supports Gigabit Ethernet interfaces based on the
-         Broadcom SiByte family of System-On-a-Chip parts.  They include
-         the BCM1120, BCM1125, BCM1125H, BCM1250, BCM1255, BCM1280, BCM1455
-         and BCM1480 chips.
-
-         To compile this driver as a module, choose M here: the module
-         will be called sb1250-mac.
-
-config SIS190
-       tristate "SiS190/SiS191 gigabit ethernet support"
-       depends on PCI
-       select CRC32
-       select MII
-       ---help---
-         Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or
-         a SiS 191 PCI Gigabit Ethernet adapter. Both are expected to
-         appear in lan on motherboard designs which are based on SiS 965
-         and SiS 966 south bridge.
-
-         To compile this driver as a module, choose M here: the module
-         will be called sis190.  This is recommended.
-
-config SKGE
-       tristate "Marvell Yukon Gigabit Ethernet support"
-       depends on PCI
-       select CRC32
-       ---help---
-         This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
-         and related Gigabit Ethernet adapters. It is a new smaller driver
-         with better performance and more complete ethtool support.
-
-         It does not support the link failover and network management 
-         features that "portable" vendor supplied sk98lin driver does.
-
-         This driver supports adapters based on the original Yukon chipset:
-         Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T,
-         Linksys EG1032/EG1064, 3Com 3C940/3C940B, SysKonnect SK-9871/9872.
-
-         It does not support the newer Yukon2 chipset: a separate driver,
-         sky2, is provided for these adapters.
-
-         To compile this driver as a module, choose M here: the module
-         will be called skge.  This is recommended.
-
-config SKGE_DEBUG
-       bool "Debugging interface"
-       depends on SKGE && DEBUG_FS
-       help
-         This option adds the ability to dump driver state for debugging.
-         The file /sys/kernel/debug/skge/ethX displays the state of the internal
-         transmit and receive rings.
-
-         If unsure, say N.
-
-config SKGE_GENESIS
-       bool "Support for older SysKonnect Genesis boards"
-       depends on SKGE
-       help
-         This enables support for the older and uncommon SysKonnect Genesis
-        chips, which support MII via an external transceiver, instead of
-        an internal one. Disabling this option will save some memory
-        by making code smaller. If unsure say Y.
-
-config SKY2
-       tristate "Marvell Yukon 2 support"
-       depends on PCI
-       select CRC32
-       ---help---
-         This driver supports Gigabit Ethernet adapters based on the
-         Marvell Yukon 2 chipset:
-         Marvell 88E8021/88E8022/88E8035/88E8036/88E8038/88E8050/88E8052/
-         88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21
-
-         There is companion driver for the older Marvell Yukon and
-         SysKonnect Genesis based adapters: skge.
-
-         To compile this driver as a module, choose M here: the module
-         will be called sky2.  This is recommended.
-
-config SKY2_DEBUG
-       bool "Debugging interface"
-       depends on SKY2 && DEBUG_FS
-       help
-         This option adds the ability to dump driver state for debugging.
-         The file /sys/kernel/debug/sky2/ethX displays the state of the internal
-         transmit and receive rings.
-
-         If unsure, say N.
-
-config VIA_VELOCITY
-       tristate "VIA Velocity support"
-       depends on PCI
-       select CRC32
-       select CRC_CCITT
-       select MII
-       help
-         If you have a VIA "Velocity" based network card say Y here.
-
-         To compile this driver as a module, choose M here. The module
-         will be called via-velocity.
-
-config TIGON3
-       tristate "Broadcom Tigon3 support"
-       depends on PCI
-       select PHYLIB
-       help
-         This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
-
-         To compile this driver as a module, choose M here: the module
-         will be called tg3.  This is recommended.
-
-config BNX2
-       tristate "Broadcom NetXtremeII support"
-       depends on PCI
-       select CRC32
-       select FW_LOADER
-       help
-         This driver supports Broadcom NetXtremeII gigabit Ethernet cards.
-
-         To compile this driver as a module, choose M here: the module
-         will be called bnx2.  This is recommended.
-
-config CNIC
-       tristate "Broadcom CNIC support"
-       depends on PCI
-       select BNX2
-       select UIO
-       help
-         This driver supports offload features of Broadcom NetXtremeII
-         gigabit Ethernet cards.
-
-         To compile this driver as a module, choose M here: the module
-         will be called cnic.  This is recommended.
-
-config SPIDER_NET
-       tristate "Spider Gigabit Ethernet driver"
-       depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB)
-       select FW_LOADER
-       help
-         This driver supports the Gigabit Ethernet chips present on the
-         Cell Processor-Based Blades from IBM.
-
-config TSI108_ETH
-       tristate "Tundra TSI108 gigabit Ethernet support"
-       depends on TSI108_BRIDGE
-       help
-         This driver supports Tundra TSI108 gigabit Ethernet ports.
-         To compile this driver as a module, choose M here: the module
-         will be called tsi108_eth.
-
-config GELIC_NET
-       tristate "PS3 Gigabit Ethernet driver"
-       depends on PPC_PS3
-       select PS3_SYS_MANAGER
-       help
-         This driver supports the network device on the PS3 game
-         console.  This driver has built-in support for Ethernet.
-
-         To compile this driver as a module, choose M here: the
-         module will be called ps3_gelic.
-
-config GELIC_WIRELESS
-       bool "PS3 Wireless support"
-       depends on WLAN
-       depends on GELIC_NET
-       select WIRELESS_EXT
-       help
-         This option adds the support for the wireless feature of PS3.
-         If you have the wireless-less model of PS3 or have no plan to
-         use wireless feature, disabling this option saves memory.  As
-         the driver automatically distinguishes the models, you can
-         safely enable this option even if you have a wireless-less model.
-
-config FSL_PQ_MDIO
-       tristate "Freescale PQ MDIO"
-       depends on FSL_SOC
-       select PHYLIB
-       help
-         This driver supports the MDIO bus used by the gianfar and UCC drivers.
-
-config GIANFAR
-       tristate "Gianfar Ethernet"
-       depends on FSL_SOC
-       select FSL_PQ_MDIO
-       select PHYLIB
-       select CRC32
-       help
-         This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
-         and MPC86xx family of chips, and the FEC on the 8540.
-
-config UCC_GETH
-       tristate "Freescale QE Gigabit Ethernet"
-       depends on QUICC_ENGINE
-       select FSL_PQ_MDIO
-       select PHYLIB
-       help
-         This driver supports the Gigabit Ethernet mode of the QUICC Engine,
-         which is available on some Freescale SOCs.
-
-config UGETH_TX_ON_DEMAND
-       bool "Transmit on Demand support"
-       depends on UCC_GETH
-
-config MV643XX_ETH
-       tristate "Marvell Discovery (643XX) and Orion ethernet support"
-       depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
-       select INET_LRO
-       select PHYLIB
-       help
-         This driver supports the gigabit ethernet MACs in the
-         Marvell Discovery PPC/MIPS chipset family (MV643XX) and
-         in the Marvell Orion ARM SoC family.
-
-         Some boards that use the Discovery chipset are the Momenco
-         Ocelot C and Jaguar ATX and Pegasos II.
-
-config XILINX_LL_TEMAC
-       tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
-       depends on PPC || MICROBLAZE
-       select PHYLIB
-       help
-         This driver supports the Xilinx 10/100/1000 LocalLink TEMAC
-         core used in Xilinx Spartan and Virtex FPGAs
-
-config QLA3XXX
-       tristate "QLogic QLA3XXX Network Driver Support"
-       depends on PCI
-       help
-         This driver supports QLogic ISP3XXX gigabit Ethernet cards.
-
-         To compile this driver as a module, choose M here: the module
-         will be called qla3xxx.
-
-config ATL1
-       tristate "Atheros/Attansic L1 Gigabit Ethernet support"
-       depends on PCI
-       select CRC32
-       select MII
-       help
-         This driver supports the Atheros/Attansic L1 gigabit ethernet
-         adapter.
-
-         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.
-
-config ATL1C
-       tristate "Atheros L1C Gigabit Ethernet support (EXPERIMENTAL)"
-       depends on PCI && EXPERIMENTAL
-       select CRC32
-       select MII
-       help
-         This driver supports the Atheros L1C gigabit ethernet adapter.
-
-         To compile this driver as a module, choose M here.  The module
-         will be called atl1c.
-
-config JME
-       tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
-       depends on PCI
-       select CRC32
-       select MII
-       ---help---
-         This driver supports the PCI-Express gigabit ethernet adapters
-         based on JMicron JMC250 chipset.
-
-         To compile this driver as a module, choose M here. The module
-         will be called jme.
-
-config S6GMAC
-       tristate "S6105 GMAC ethernet support"
-       depends on XTENSA_VARIANT_S6000
-       select PHYLIB
-       help
-         This driver supports the on chip ethernet device on the
-         S6105 xtensa processor.
-
-         To compile this driver as a module, choose M here. The module
-         will be called s6gmac.
-
-source "drivers/net/stmmac/Kconfig"
-
-config PCH_GBE
-       tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GbE"
-       depends on PCI
-       select MII
-       ---help---
-         This is a gigabit ethernet driver for EG20T PCH.
-         EG20T PCH is the platform controller hub that is used in Intel's
-         general embedded platform.
-         EG20T PCH has Gigabit Ethernet interface.
-         Using this interface, it is able to access system devices connected
-         to Gigabit Ethernet.
-         This driver enables Gigabit Ethernet function.
-
-         This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
-         Output Hub), ML7223.
-         ML7223 IOH is for MP(Media Phone) use.
-         ML7223 is companion chip for Intel Atom E6xx series.
-         ML7223 is completely compatible for Intel EG20T PCH.
-
-config FTGMAC100
-       tristate "Faraday FTGMAC100 Gigabit Ethernet support"
-       depends on ARM
-       select PHYLIB
-       help
-         This driver supports the FTGMAC100 Gigabit Ethernet controller
-         from Faraday. It is used on Faraday A369, Andes AG102 and some
-         other ARM/NDS32 SoC's.
-
-endif # NETDEV_1000
-
-#
-#      10 Gigabit Ethernet
-#
-
-menuconfig NETDEV_10000
-       bool "Ethernet (10000 Mbit)"
-       depends on !UML
-       default y
-       ---help---
-         Say Y here to get to see options for 10 Gigabit Ethernet drivers.
-         This option alone does not add any kernel code.
-
-         If you say N, all options in this submenu will be skipped and disabled.
-
-if NETDEV_10000
-
-config MDIO
-       tristate
-
-config CHELSIO_T1
-       tristate "Chelsio 10Gb Ethernet support"
-       depends on PCI
-       select CRC32
-       select MDIO
-       help
-         This driver supports Chelsio gigabit and 10-gigabit
-         Ethernet cards. More information about adapter features and
-         performance tuning is in <file:Documentation/networking/cxgb.txt>.
-
-         For general information about Chelsio and our products, visit
-         our website at <http://www.chelsio.com>.
-
-         For customer support, please visit our customer support page at
-         <http://www.chelsio.com/support.html>.
-
-         Please send feedback to <linux-bugs@chelsio.com>.
-
-         To compile this driver as a module, choose M here: the module
-         will be called cxgb.
-
-config CHELSIO_T1_1G
-       bool "Chelsio gigabit Ethernet support"
-       depends on CHELSIO_T1
-       help
-         Enables support for Chelsio's gigabit Ethernet PCI cards.  If you
-         are using only 10G cards say 'N' here.
-
-config CHELSIO_T3
-       tristate "Chelsio Communications T3 10Gb Ethernet support"
-       depends on PCI && INET
-       select FW_LOADER
-       select MDIO
-       help
-         This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
-         adapters.
-
-         For general information about Chelsio and our products, visit
-         our website at <http://www.chelsio.com>.
-
-         For customer support, please visit our customer support page at
-         <http://www.chelsio.com/support.html>.
-
-         Please send feedback to <linux-bugs@chelsio.com>.
-
-         To compile this driver as a module, choose M here: the module
-         will be called cxgb3.
-
-config CHELSIO_T4
-       tristate "Chelsio Communications T4 Ethernet support"
-       depends on PCI
-       select FW_LOADER
-       select MDIO
-       help
-         This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
-         adapters.
-
-         For general information about Chelsio and our products, visit
-         our website at <http://www.chelsio.com>.
-
-         For customer support, please visit our customer support page at
-         <http://www.chelsio.com/support.html>.
-
-         Please send feedback to <linux-bugs@chelsio.com>.
-
-         To compile this driver as a module choose M here; the module
-         will be called cxgb4.
-
-config CHELSIO_T4VF
-       tristate "Chelsio Communications T4 Virtual Function Ethernet support"
-       depends on PCI
-       help
-         This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
-         adapters with PCI-E SR-IOV Virtual Functions.
-
-         For general information about Chelsio and our products, visit
-         our website at <http://www.chelsio.com>.
-
-         For customer support, please visit our customer support page at
-         <http://www.chelsio.com/support.html>.
-
-         Please send feedback to <linux-bugs@chelsio.com>.
-
-         To compile this driver as a module choose M here; the module
-         will be called cxgb4vf.
-
-config EHEA
-       tristate "eHEA Ethernet support"
-       depends on IBMEBUS && INET && SPARSEMEM
-       select INET_LRO
-       ---help---
-         This driver supports the IBM pSeries eHEA ethernet adapter.
-
-         To compile the driver as a module, choose M here. The module
-         will be called ehea.
-
-config ENIC
-       tristate "Cisco VIC Ethernet NIC Support"
-       depends on PCI && INET
-       help
-         This enables the support for the Cisco VIC Ethernet card.
-
-config IXGBE
-       tristate "Intel(R) 10GbE PCI Express adapters support"
-       depends on PCI && INET
-       select MDIO
-       ---help---
-         This driver supports Intel(R) 10GbE PCI Express family of
-         adapters.  For more information on how to identify your adapter, go
-         to the Adapter & Driver ID Guide at:
-
-         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
-         For general information and support, go to the Intel support
-         website at:
-
-         <http://support.intel.com>
-
-         To compile this driver as a module, choose M here. The module
-         will be called ixgbe.
-
-config IXGBE_DCA
-       bool "Direct Cache Access (DCA) Support"
-       default y
-       depends on IXGBE && DCA && !(IXGBE=y && DCA=m)
-       ---help---
-         Say Y here if you want to use Direct Cache Access (DCA) in the
-         driver.  DCA is a method for warming the CPU cache before data
-         is used, with the intent of lessening the impact of cache misses.
-
-config IXGBE_DCB
-       bool "Data Center Bridging (DCB) Support"
-       default n
-       depends on IXGBE && DCB
-       ---help---
-         Say Y here if you want to use Data Center Bridging (DCB) in the
-         driver.
-
-         If unsure, say N.
-
-config IXGBEVF
-       tristate "Intel(R) 82599 Virtual Function Ethernet support"
-       depends on PCI_MSI
-       ---help---
-         This driver supports Intel(R) 82599 virtual functions.  For more
-         information on how to identify your adapter, go to the Adapter &
-         Driver ID Guide at:
-
-         <http://support.intel.com/support/network/sb/CS-008441.htm>
-
-         For general information and support, go to the Intel support
-         website at:
-
-         <http://support.intel.com>
-
-         More specific information on configuring the driver is in
-         <file:Documentation/networking/ixgbevf.txt>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ixgbevf.  MSI-X interrupt support is required
-         for this driver to work correctly.
-
-config IXGB
-       tristate "Intel(R) PRO/10GbE support"
-       depends on PCI
-       ---help---
-         This driver supports Intel(R) PRO/10GbE family of adapters for
-         PCI-X type cards. For PCI-E type cards, use the "ixgbe" driver
-         instead. For more information on how to identify your adapter, go
-         to the Adapter & Driver ID Guide at:
-
-         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
-         For general information and support, go to the Intel support
-         website at:
-
-         <http://support.intel.com>
-
-         More specific information on configuring the driver is in 
-         <file:Documentation/networking/ixgb.txt>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ixgb.
-
-config S2IO
-       tristate "Exar Xframe 10Gb Ethernet Adapter"
-       depends on PCI
-       ---help---
-         This driver supports Exar Corp's Xframe Series 10Gb Ethernet Adapters.
-
-         More specific information on configuring the driver is in 
-         <file:Documentation/networking/s2io.txt>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called s2io.
-
-config VXGE
-       tristate "Exar X3100 Series 10GbE PCIe Server Adapter"
-       depends on PCI && INET
-       ---help---
-         This driver supports Exar Corp's X3100 Series 10 GbE PCIe
-         I/O Virtualized Server Adapter.
-
-         More specific information on configuring the driver is in
-         <file:Documentation/networking/vxge.txt>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called vxge.
-
-config VXGE_DEBUG_TRACE_ALL
-       bool "Enabling All Debug trace statments in driver"
-       default n
-       depends on VXGE
-       ---help---
-         Say Y here if you want to enabling all the debug trace statements in
-         the vxge driver. By default only few debug trace statements are
-         enabled.
-
-config MYRI10GE
-       tristate "Myricom Myri-10G Ethernet support"
-       depends on PCI && INET
-       select FW_LOADER
-       select CRC32
-       select INET_LRO
-       ---help---
-         This driver supports Myricom Myri-10G Dual Protocol interface in
-         Ethernet mode. If the eeprom on your board is not recent enough,
-         you will need a newer firmware image.
-         You may get this image or more information, at:
-
-         <http://www.myri.com/scs/download-Myri10GE.html>
-
-         To compile this driver as a module, choose M here. The module
-         will be called myri10ge.
-
-config MYRI10GE_DCA
-       bool "Direct Cache Access (DCA) Support"
-       default y
-       depends on MYRI10GE && DCA && !(MYRI10GE=y && DCA=m)
-       ---help---
-         Say Y here if you want to use Direct Cache Access (DCA) in the
-         driver.  DCA is a method for warming the CPU cache before data
-         is used, with the intent of lessening the impact of cache misses.
-
-config NETXEN_NIC
-       tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
-       depends on PCI
-       select FW_LOADER
-       help
-         This enables the support for NetXen's Gigabit Ethernet card.
-
-config NIU
-       tristate "Sun Neptune 10Gbit Ethernet support"
-       depends on PCI
-       select CRC32
-       help
-         This enables support for cards based upon Sun's
-         Neptune chipset.
-
-config PASEMI_MAC
-       tristate "PA Semi 1/10Gbit MAC"
-       depends on PPC_PASEMI && PCI && INET
-       select PHYLIB
-       select INET_LRO
-       help
-         This driver supports the on-chip 1/10Gbit Ethernet controller on
-         PA Semi's PWRficient line of chips.
-
-config MLX4_EN
-       tristate "Mellanox Technologies 10Gbit Ethernet support"
-       depends on PCI && INET
-       select MLX4_CORE
-       select INET_LRO
-       help
-         This driver supports Mellanox Technologies ConnectX Ethernet
-         devices.
-
-config MLX4_CORE
-       tristate
-       depends on PCI
-       default n
-
-config MLX4_DEBUG
-       bool "Verbose debugging output" if (MLX4_CORE && EXPERT)
-       depends on MLX4_CORE
-       default y
-       ---help---
-         This option causes debugging code to be compiled into the
-         mlx4_core driver.  The output can be turned on via the
-         debug_level module parameter (which can also be set after
-         the driver is loaded through sysfs).
-
-config TEHUTI
-       tristate "Tehuti Networks 10G Ethernet"
-       depends on PCI
-       help
-         Tehuti Networks 10G Ethernet NIC
-
-config BNX2X
-       tristate "Broadcom NetXtremeII 10Gb support"
-       depends on PCI
-       select FW_LOADER
-       select ZLIB_INFLATE
-       select LIBCRC32C
-       select MDIO
-       help
-         This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards.
-         To compile this driver as a module, choose M here: the module
-         will be called bnx2x.  This is recommended.
-
-config QLCNIC
-       tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support"
-       depends on PCI
-       select FW_LOADER
-       help
-         This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet
-         devices.
-
-config QLGE
-       tristate "QLogic QLGE 10Gb Ethernet Driver Support"
-       depends on PCI
-       help
-         This driver supports QLogic ISP8XXX 10Gb Ethernet cards.
-
-         To compile this driver as a module, choose M here: the module
-         will be called qlge.
-
-config BNA
-       tristate "Brocade 1010/1020 10Gb Ethernet Driver support"
-       depends on PCI
-       ---help---
-         This driver supports Brocade 1010/1020 10Gb CEE capable Ethernet
-         cards.
-         To compile this driver as a module, choose M here: the module
-         will be called bna.
-
-         For general information and support, go to the Brocade support
-         website at:
-
-         <http://support.brocade.com>
-
-source "drivers/net/sfc/Kconfig"
-
-source "drivers/net/benet/Kconfig"
-
-endif # NETDEV_10000
-
-source "drivers/net/tokenring/Kconfig"
-
-source "drivers/net/wireless/Kconfig"
-
-source "drivers/net/wimax/Kconfig"
-
-source "drivers/net/usb/Kconfig"
-
-source "drivers/net/pcmcia/Kconfig"
-
-source "drivers/net/wan/Kconfig"
-
-source "drivers/atm/Kconfig"
-
-source "drivers/ieee802154/Kconfig"
-
-source "drivers/s390/net/Kconfig"
-
-source "drivers/net/caif/Kconfig"
-
-config TILE_NET
-       tristate "Tilera GBE/XGBE network driver support"
-       depends on TILE
-       default y
-       select CRC32
-       help
-         This is a standard Linux network device driver for the
-         on-chip Tilera Gigabit Ethernet and XAUI interfaces.
-
-         To compile this driver as a module, choose M here: the module
-         will be called tile_net.
-
-config XEN_NETDEV_FRONTEND
-       tristate "Xen network device frontend driver"
-       depends on XEN
-       select XEN_XENBUS_FRONTEND
-       default y
-       help
-         This driver provides support for Xen paravirtual network
-         devices exported by a Xen network driver domain (often
-         domain 0).
-
-         The corresponding Linux backend driver is enabled by the
-         CONFIG_XEN_NETDEV_BACKEND option.
-
-         If you are compiling a kernel for use as Xen guest, you
-         should say Y here. To compile this driver as a module, chose
-         M here: the module will be called xen-netfront.
-
-config XEN_NETDEV_BACKEND
-       tristate "Xen backend network device"
-       depends on XEN_BACKEND
-       help
-         This driver allows the kernel to act as a Xen network driver
-         domain which exports paravirtual network devices to other
-         Xen domains. These devices can be accessed by any operating
-         system that implements a compatible front end.
-
-         The corresponding Linux frontend driver is enabled by the
-         CONFIG_XEN_NETDEV_FRONTEND configuration option.
-
-         The backend driver presents a standard network device
-         endpoint for each paravirtual network device to the driver
-         domain network stack. These can then be bridged or routed
-         etc in order to provide full network connectivity.
+         The backend driver presents a standard network device
+         endpoint for each paravirtual network device to the driver
+         domain network stack. These can then be bridged or routed
+         etc in order to provide full network connectivity.
 
          If you are compiling a kernel to run in a Xen network driver
          domain (often this is domain 0) you should say Y here. To
          compile this driver as a module, chose M here: the module
          will be called xen-netback.
 
-config ISERIES_VETH
-       tristate "iSeries Virtual Ethernet driver support"
-       depends on PPC_ISERIES
-
-config RIONET
-       tristate "RapidIO Ethernet over messaging driver support"
-       depends on RAPIDIO
-
-config RIONET_TX_SIZE
-       int "Number of outbound queue entries"
-       depends on RIONET
-       default "128"
-
-config RIONET_RX_SIZE
-       int "Number of inbound queue entries"
-       depends on RIONET
-       default "128"
-
-config FDDI
-       tristate "FDDI driver support"
-       depends on (PCI || EISA || TC)
-       help
-         Fiber Distributed Data Interface is a high speed local area network
-         design; essentially a replacement for high speed Ethernet. FDDI can
-         run over copper or fiber. If you are connected to such a network and
-         want a driver for the FDDI card in your computer, say Y here (and
-         then also Y to the driver for your FDDI card, below). Most people
-         will say N.
-
-config DEFXX
-       tristate "Digital DEFTA/DEFEA/DEFPA adapter support"
-       depends on FDDI && (PCI || EISA || TC)
-       ---help---
-         This is support for the DIGITAL series of TURBOchannel (DEFTA),
-         EISA (DEFEA) and PCI (DEFPA) controllers which can connect you
-         to a local FDDI network.
-
-         To compile this driver as a module, choose M here: the module
-         will be called defxx.  If unsure, say N.
-
-config DEFXX_MMIO
-       bool
-       prompt "Use MMIO instead of PIO" if PCI || EISA
-       depends on DEFXX
-       default n if PCI || EISA
-       default y
-       ---help---
-         This instructs the driver to use EISA or PCI memory-mapped I/O
-         (MMIO) as appropriate instead of programmed I/O ports (PIO).
-         Enabling this gives an improvement in processing time in parts
-         of the driver, but it may cause problems with EISA (DEFEA)
-         adapters.  TURBOchannel does not have the concept of I/O ports,
-         so MMIO is always used for these (DEFTA) adapters.
-
-         If unsure, say N.
-
-config SKFP
-       tristate "SysKonnect FDDI PCI support"
-       depends on FDDI && PCI
-       select BITREVERSE
-       ---help---
-         Say Y here if you have a SysKonnect FDDI PCI adapter.
-         The following adapters are supported by this driver:
-         - SK-5521 (SK-NET FDDI-UP)
-         - SK-5522 (SK-NET FDDI-UP DAS)
-         - SK-5541 (SK-NET FDDI-FP)
-         - SK-5543 (SK-NET FDDI-LP)
-         - SK-5544 (SK-NET FDDI-LP DAS)
-         - SK-5821 (SK-NET FDDI-UP64)
-         - SK-5822 (SK-NET FDDI-UP64 DAS)
-         - SK-5841 (SK-NET FDDI-FP64)
-         - SK-5843 (SK-NET FDDI-LP64)
-         - SK-5844 (SK-NET FDDI-LP64 DAS)
-         - Netelligent 100 FDDI DAS Fibre SC
-         - Netelligent 100 FDDI SAS Fibre SC
-         - Netelligent 100 FDDI DAS UTP
-         - Netelligent 100 FDDI SAS UTP
-         - Netelligent 100 FDDI SAS Fibre MIC
-
-         Read <file:Documentation/networking/skfp.txt> for information about
-         the driver.
-
-         Questions concerning this driver can be addressed to:
-         <linux@syskonnect.de>
-
-         To compile this driver as a module, choose M here: the module
-         will be called skfp.  This is recommended.
-
-config HIPPI
-       bool "HIPPI driver support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && INET && PCI
-       help
-         HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and
-         1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI
-         can run over copper (25m) or fiber (300m on multi-mode or 10km on
-         single-mode). HIPPI networks are commonly used for clusters and to
-         connect to super computers. If you are connected to a HIPPI network
-         and have a HIPPI network card in your computer that you want to use
-         under Linux, say Y here (you must also remember to enable the driver
-         for your HIPPI card below). Most people will say N here.
-
-config ROADRUNNER
-       tristate "Essential RoadRunner HIPPI PCI adapter support (EXPERIMENTAL)"
-       depends on HIPPI && PCI
-       help
-         Say Y here if this is your PCI HIPPI network card.
-
-         To compile this driver as a module, choose M here: the module
-         will be called rrunner.  If unsure, say N.
-
-config ROADRUNNER_LARGE_RINGS
-       bool "Use large TX/RX rings (EXPERIMENTAL)"
-       depends on ROADRUNNER
-       help
-         If you say Y here, the RoadRunner driver will preallocate up to 2 MB
-         of additional memory to allow for fastest operation, both for
-         transmitting and receiving. This memory cannot be used by any other
-         kernel code or by user space programs. Say Y here only if you have
-         the memory.
-
-config PLIP
-       tristate "PLIP (parallel port) support"
-       depends on PARPORT
-       ---help---
-         PLIP (Parallel Line Internet Protocol) is used to create a
-         reasonably fast mini network consisting of two (or, rarely, more)
-         local machines.  A PLIP link from a Linux box is a popular means to
-         install a Linux distribution on a machine which doesn't have a
-         CD-ROM drive (a minimal system has to be transferred with floppies
-         first). The kernels on both machines need to have this PLIP option
-         enabled for this to work.
-
-         The PLIP driver has two modes, mode 0 and mode 1.  The parallel
-         ports (the connectors at the computers with 25 holes) are connected
-         with "null printer" or "Turbo Laplink" cables which can transmit 4
-         bits at a time (mode 0) or with special PLIP cables, to be used on
-         bidirectional parallel ports only, which can transmit 8 bits at a
-         time (mode 1); you can find the wiring of these cables in
-         <file:Documentation/networking/PLIP.txt>.  The cables can be up to
-         15m long.  Mode 0 works also if one of the machines runs DOS/Windows
-         and has some PLIP software installed, e.g. the Crynwr PLIP packet
-         driver (<http://oak.oakland.edu/simtel.net/msdos/pktdrvr-pre.html>)
-         and winsock or NCSA's telnet.
-
-         If you want to use PLIP, say Y and read the PLIP mini-HOWTO as well
-         as the NET-3-HOWTO, both available from
-         <http://www.tldp.org/docs.html#howto>.  Note that the PLIP
-         protocol has been changed and this PLIP driver won't work together
-         with the PLIP support in Linux versions 1.0.x.  This option enlarges
-         your kernel by about 8 KB.
-
-         To compile this driver as a module, choose M here. The module
-         will be called plip. If unsure, say Y or M, in case you buy
-         a laptop later.
-
-config PPP
-       tristate "PPP (point-to-point protocol) support"
-       select SLHC
-       ---help---
-         PPP (Point to Point Protocol) is a newer and better SLIP.  It serves
-         the same purpose: sending Internet traffic over telephone (and other
-         serial) lines.  Ask your access provider if they support it, because
-         otherwise you can't use it; most Internet access providers these
-         days support PPP rather than SLIP.
-
-         To use PPP, you need an additional program called pppd as described
-         in the PPP-HOWTO, available at
-         <http://www.tldp.org/docs.html#howto>.  Make sure that you have
-         the version of pppd recommended in <file:Documentation/Changes>.
-         The PPP option enlarges your kernel by about 16 KB.
-
-         There are actually two versions of PPP: the traditional PPP for
-         asynchronous lines, such as regular analog phone lines, and
-         synchronous PPP which can be used over digital ISDN lines for
-         example.  If you want to use PPP over phone lines or other
-         asynchronous serial lines, you need to say Y (or M) here and also to
-         the next option, "PPP support for async serial ports".  For PPP over
-         synchronous lines, you should say Y (or M) here and to "Support
-         synchronous PPP", below.
-
-         If you said Y to "Version information on all symbols" above, then
-         you cannot compile the PPP driver into the kernel; you can then only
-         compile it as a module. To compile this driver as a module, choose M
-         here. The module will be called ppp_generic.
-
-config PPP_MULTILINK
-       bool "PPP multilink support (EXPERIMENTAL)"
-       depends on PPP && EXPERIMENTAL
-       help
-         PPP multilink is a protocol (defined in RFC 1990) which allows you
-         to combine several (logical or physical) lines into one logical PPP
-         connection, so that you can utilize your full bandwidth.
-
-         This has to be supported at the other end as well and you need a
-         version of the pppd daemon which understands the multilink protocol.
-
-         If unsure, say N.
-
-config PPP_FILTER
-       bool "PPP filtering"
-       depends on PPP
-       help
-         Say Y here if you want to be able to filter the packets passing over
-         PPP interfaces.  This allows you to control which packets count as
-         activity (i.e. which packets will reset the idle timer or bring up
-         a demand-dialed link) and which packets are to be dropped entirely.
-         You need to say Y here if you wish to use the pass-filter and
-         active-filter options to pppd.
-
-         If unsure, say N.
-
-config PPP_ASYNC
-       tristate "PPP support for async serial ports"
-       depends on PPP
-       select CRC_CCITT
-       ---help---
-         Say Y (or M) here if you want to be able to use PPP over standard
-         asynchronous serial ports, such as COM1 or COM2 on a PC.  If you use
-         a modem (not a synchronous or ISDN modem) to contact your ISP, you
-         need this option.
-
-         To compile this driver as a module, choose M here.
-
-         If unsure, say Y.
-
-config PPP_SYNC_TTY
-       tristate "PPP support for sync tty ports"
-       depends on PPP
-       help
-         Say Y (or M) here if you want to be able to use PPP over synchronous
-         (HDLC) tty devices, such as the SyncLink adapter. These devices
-         are often used for high-speed leased lines like T1/E1.
-
-         To compile this driver as a module, choose M here.
-
-config PPP_DEFLATE
-       tristate "PPP Deflate compression"
-       depends on PPP
-       select ZLIB_INFLATE
-       select ZLIB_DEFLATE
-       ---help---
-         Support for the Deflate compression method for PPP, which uses the
-         Deflate algorithm (the same algorithm that gzip uses) to compress
-         each PPP packet before it is sent over the wire.  The machine at the
-         other end of the PPP link (usually your ISP) has to support the
-         Deflate compression method as well for this to be useful.  Even if
-         they don't support it, it is safe to say Y here.
-
-         To compile this driver as a module, choose M here.
-
-config PPP_BSDCOMP
-       tristate "PPP BSD-Compress compression"
-       depends on PPP
-       ---help---
-         Support for the BSD-Compress compression method for PPP, which uses
-         the LZW compression method to compress each PPP packet before it is
-         sent over the wire. The machine at the other end of the PPP link
-         (usually your ISP) has to support the BSD-Compress compression
-         method as well for this to be useful. Even if they don't support it,
-         it is safe to say Y here.
-
-         The PPP Deflate compression method ("PPP Deflate compression",
-         above) is preferable to BSD-Compress, because it compresses better
-         and is patent-free.
-
-         Note that the BSD compression code will always be compiled as a
-         module; it is called bsd_comp and will show up in the directory
-         modules once you have said "make modules". If unsure, say N.
-
-config PPP_MPPE
-       tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)"
-       depends on PPP && EXPERIMENTAL
-       select CRYPTO
-       select CRYPTO_SHA1
-       select CRYPTO_ARC4
-       select CRYPTO_ECB
-       ---help---
-         Support for the MPPE Encryption protocol, as employed by the
-         Microsoft Point-to-Point Tunneling Protocol.
-
-         See http://pptpclient.sourceforge.net/ for information on
-         configuring PPTP clients and servers to utilize this method.
-
-config PPPOE
-       tristate "PPP over Ethernet (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && PPP
-       help
-         Support for PPP over Ethernet.
-
-         This driver requires the latest version of pppd from the CVS
-         repository at cvs.samba.org.  Alternatively, see the 
-         RoaringPenguin package (<http://www.roaringpenguin.com/pppoe>)
-         which contains instruction on how to use this driver (under 
-         the heading "Kernel mode PPPoE").
-
-config PPTP
-       tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX
-       help
-         Support for PPP over IPv4.(Point-to-Point Tunneling Protocol)
-
-         This driver requires pppd plugin to work in client mode or
-         modified pptpd (poptop) to work in server mode.
-         See http://accel-pptp.sourceforge.net/ for information how to
-         utilize this module.
-
-config PPPOATM
-       tristate "PPP over ATM"
-       depends on ATM && PPP
-       help
-         Support PPP (Point to Point Protocol) encapsulated in ATM frames.
-         This implementation does not yet comply with section 8 of RFC2364,
-         which can lead to bad results if the ATM peer loses state and
-         changes its encapsulation unilaterally.
-
-config PPPOL2TP
-       tristate "PPP over L2TP (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && L2TP && PPP
-       help
-         Support for PPP-over-L2TP socket family. L2TP is a protocol
-         used by ISPs and enterprises to tunnel PPP traffic over UDP
-         tunnels. L2TP is replacing PPTP for VPN uses.
-
-config SLIP
-       tristate "SLIP (serial line) support"
-       ---help---
-         Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to
-         connect to your Internet service provider or to connect to some
-         other local Unix box or if you want to configure your Linux box as a
-         Slip/CSlip server for other people to dial in. SLIP (Serial Line
-         Internet Protocol) is a protocol used to send Internet traffic over
-         serial connections such as telephone lines or null modem cables;
-         nowadays, the protocol PPP is more commonly used for this same
-         purpose.
-
-         Normally, your access provider has to support SLIP in order for you
-         to be able to use it, but there is now a SLIP emulator called SLiRP
-         around (available from
-         <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
-         allows you to use SLIP over a regular dial up shell connection. If
-         you plan to use SLiRP, make sure to say Y to CSLIP, below. The
-         NET-3-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, explains how to
-         configure SLIP. Note that you don't need this option if you just
-         want to run term (term is a program which gives you almost full
-         Internet connectivity if you have a regular dial up shell account on
-         some Internet connected Unix computer. Read
-         <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP
-         support will enlarge your kernel by about 4 KB. If unsure, say N.
-
-         To compile this driver as a module, choose M here. The module
-         will be called slip.
-
-config SLIP_COMPRESSED
-       bool "CSLIP compressed headers"
-       depends on SLIP
-       select SLHC
-       ---help---
-         This protocol is faster than SLIP because it uses compression on the
-         TCP/IP headers (not on the data itself), but it has to be supported
-         on both ends. Ask your access provider if you are not sure and
-         answer Y, just in case. You will still be able to use plain SLIP. If
-         you plan to use SLiRP, the SLIP emulator (available from
-         <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
-         allows you to use SLIP over a regular dial up shell connection, you
-         definitely want to say Y here. The NET-3-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, explains how to configure
-         CSLIP. This won't enlarge your kernel.
-
-config SLHC
-       tristate
-       help
-         This option enables Van Jacobsen serial line header compression
-         routines.
-
-config SLIP_SMART
-       bool "Keepalive and linefill"
-       depends on SLIP
-       help
-         Adds additional capabilities to the SLIP driver to support the
-         RELCOM line fill and keepalive monitoring. Ideal on poor quality
-         analogue lines.
-
-config SLIP_MODE_SLIP6
-       bool "Six bit SLIP encapsulation"
-       depends on SLIP
-       help
-         Just occasionally you may need to run IP over hostile serial
-         networks that don't pass all control characters or are only seven
-         bit. Saying Y here adds an extra mode you can use with SLIP:
-         "slip6". In this mode, SLIP will only send normal ASCII symbols over
-         the serial device. Naturally, this has to be supported at the other
-         end of the link as well. It's good enough, for example, to run IP
-         over the async ports of a Camtec JNT Pad. If unsure, say N.
-
-config NET_FC
-       bool "Fibre Channel driver support"
-       depends on SCSI && PCI
-       help
-         Fibre Channel is a high speed serial protocol mainly used to connect
-         large storage devices to the computer; it is compatible with and
-         intended to replace SCSI.
-
-         If you intend to use Fibre Channel, you need to have a Fibre channel
-         adaptor card in your computer; say Y here and to the driver for your
-         adaptor below. You also should have said Y to "SCSI support" and
-         "SCSI generic support".
-
-config NETCONSOLE
-       tristate "Network console logging support"
-       ---help---
-       If you want to log kernel messages over the network, enable this.
-       See <file:Documentation/networking/netconsole.txt> for details.
-
-config NETCONSOLE_DYNAMIC
-       bool "Dynamic reconfiguration of logging targets"
-       depends on NETCONSOLE && SYSFS && CONFIGFS_FS && \
-                       !(NETCONSOLE=y && CONFIGFS_FS=m)
-       help
-         This option enables the ability to dynamically reconfigure target
-         parameters (interface, IP addresses, port numbers, MAC addresses)
-         at runtime through a userspace interface exported using configfs.
-         See <file:Documentation/networking/netconsole.txt> for details.
-
-config NETPOLL
-       def_bool NETCONSOLE
-
-config NETPOLL_TRAP
-       bool "Netpoll traffic trapping"
-       default n
-       depends on NETPOLL
-
-config NET_POLL_CONTROLLER
-       def_bool NETPOLL
-
-config VIRTIO_NET
-       tristate "Virtio network driver (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && VIRTIO
-       ---help---
-         This is the virtual network driver for virtio.  It can be used with
-         lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
-
 config VMXNET3
        tristate "VMware VMXNET3 ethernet driver"
        depends on PCI && INET
index e1eca2a..1f52e73 100644 (file)
 #
-# Makefile for the Linux network (ethercard) device drivers.
+# Makefile for the Linux network device drivers.
 #
 
-obj-$(CONFIG_MII) += mii.o
-obj-$(CONFIG_MDIO) += mdio.o
-obj-$(CONFIG_PHYLIB) += phy/
-
-obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
-obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
-obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
-
-obj-$(CONFIG_E1000) += e1000/
-obj-$(CONFIG_E1000E) += e1000e/
-obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/
-obj-$(CONFIG_IGB) += igb/
-obj-$(CONFIG_IGBVF) += igbvf/
-obj-$(CONFIG_IXGBE) += ixgbe/
-obj-$(CONFIG_IXGBEVF) += ixgbevf/
-obj-$(CONFIG_IXGB) += ixgb/
-obj-$(CONFIG_IP1000) += ipg.o
-obj-$(CONFIG_CHELSIO_T1) += chelsio/
-obj-$(CONFIG_CHELSIO_T3) += cxgb3/
-obj-$(CONFIG_CHELSIO_T4) += cxgb4/
-obj-$(CONFIG_CHELSIO_T4VF) += cxgb4vf/
-obj-$(CONFIG_EHEA) += ehea/
-obj-$(CONFIG_CAN) += can/
-obj-$(CONFIG_BONDING) += bonding/
-obj-$(CONFIG_ATL1) += atlx/
-obj-$(CONFIG_ATL2) += atlx/
-obj-$(CONFIG_ATL1E) += atl1e/
-obj-$(CONFIG_ATL1C) += atl1c/
-obj-$(CONFIG_GIANFAR) += gianfar_driver.o
-obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o
-obj-$(CONFIG_TEHUTI) += tehuti.o
-obj-$(CONFIG_ENIC) += enic/
-obj-$(CONFIG_JME) += jme.o
-obj-$(CONFIG_BE2NET) += benet/
-obj-$(CONFIG_VMXNET3) += vmxnet3/
-obj-$(CONFIG_BNA) += bna/
-
-gianfar_driver-objs := gianfar.o \
-               gianfar_ethtool.o \
-               gianfar_sysfs.o
-
-obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
-ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
-
-obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o
-
-#
-# link order important here
 #
-obj-$(CONFIG_PLIP) += plip.o
-
-obj-$(CONFIG_ROADRUNNER) += rrunner.o
-
-obj-$(CONFIG_HAPPYMEAL) += sunhme.o
-obj-$(CONFIG_SUNLANCE) += sunlance.o
-obj-$(CONFIG_SUNQE) += sunqe.o
-obj-$(CONFIG_SUNBMAC) += sunbmac.o
-obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
-obj-$(CONFIG_CASSINI) += cassini.o
-obj-$(CONFIG_SUNVNET) += sunvnet.o
-
-obj-$(CONFIG_MACE) += mace.o
-obj-$(CONFIG_BMAC) += bmac.o
-
-obj-$(CONFIG_VORTEX) += 3c59x.o
-obj-$(CONFIG_TYPHOON) += typhoon.o
-obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
-obj-$(CONFIG_PCNET32) += pcnet32.o
-obj-$(CONFIG_E100) += e100.o
-obj-$(CONFIG_TLAN) += tlan.o
-obj-$(CONFIG_EPIC100) += epic100.o
-obj-$(CONFIG_SMSC9420) += smsc9420.o
-obj-$(CONFIG_SIS190) += sis190.o
-obj-$(CONFIG_SIS900) += sis900.o
-obj-$(CONFIG_R6040) += r6040.o
-obj-$(CONFIG_YELLOWFIN) += yellowfin.o
-obj-$(CONFIG_ACENIC) += acenic.o
-obj-$(CONFIG_ISERIES_VETH) += iseries_veth.o
-obj-$(CONFIG_NATSEMI) += natsemi.o
-obj-$(CONFIG_NS83820) += ns83820.o
-obj-$(CONFIG_STNIC) += stnic.o 8390.o
-obj-$(CONFIG_FEALNX) += fealnx.o
-obj-$(CONFIG_TIGON3) += tg3.o
-obj-$(CONFIG_BNX2) += bnx2.o
-obj-$(CONFIG_CNIC) += cnic.o
-obj-$(CONFIG_BNX2X) += bnx2x/
-spidernet-y += spider_net.o spider_net_ethtool.o
-obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o
-obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
-gelic_wireless-$(CONFIG_GELIC_WIRELESS) += ps3_gelic_wireless.o
-ps3_gelic-objs += ps3_gelic_net.o $(gelic_wireless-y)
-obj-$(CONFIG_TC35815) += tc35815.o
-obj-$(CONFIG_SKGE) += skge.o
-obj-$(CONFIG_SKY2) += sky2.o
-obj-$(CONFIG_SKFP) += skfp/
-obj-$(CONFIG_KS8842)   += ks8842.o
-obj-$(CONFIG_KS8851)   += ks8851.o
-obj-$(CONFIG_KS8851_MLL)       += ks8851_mll.o
-obj-$(CONFIG_KSZ884X_PCI)      += ksz884x.o
-obj-$(CONFIG_VIA_RHINE) += via-rhine.o
-obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
-obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
-obj-$(CONFIG_RIONET) += rionet.o
-obj-$(CONFIG_SH_ETH) += sh_eth.o
-obj-$(CONFIG_STMMAC_ETH) += stmmac/
-
+# Networking Core Drivers
 #
-# end link order section
-#
-
-obj-$(CONFIG_SUNDANCE) += sundance.o
-obj-$(CONFIG_HAMACHI) += hamachi.o
-obj-$(CONFIG_NET) += Space.o loopback.o
-obj-$(CONFIG_SEEQ8005) += seeq8005.o
-obj-$(CONFIG_NET_SB1000) += sb1000.o
-obj-$(CONFIG_MAC8390) += mac8390.o
-obj-$(CONFIG_APNE) += apne.o 8390.o
-obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
-obj-$(CONFIG_HP100) += hp100.o
-obj-$(CONFIG_SMC9194) += smc9194.o
-obj-$(CONFIG_FEC) += fec.o
-obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
-ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
-       obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
-endif
-obj-$(CONFIG_WD80x3) += wd.o 8390.o
-obj-$(CONFIG_EL2) += 3c503.o 8390p.o
-obj-$(CONFIG_NE2000) += ne.o 8390p.o
-obj-$(CONFIG_NE2_MCA) += ne2.o 8390p.o
-obj-$(CONFIG_HPLAN) += hp.o 8390p.o
-obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390p.o
-obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
-obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
-obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
-obj-$(CONFIG_E2100) += e2100.o 8390.o
-obj-$(CONFIG_ES3210) += es3210.o 8390.o
-obj-$(CONFIG_LNE390) += lne390.o 8390.o
-obj-$(CONFIG_NE3210) += ne3210.o 8390.o
-obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
-obj-$(CONFIG_B44) += b44.o
-obj-$(CONFIG_FORCEDETH) += forcedeth.o
-obj-$(CONFIG_NE_H8300) += ne-h8300.o
-obj-$(CONFIG_AX88796) += ax88796.o
-obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
-obj-$(CONFIG_FTGMAC100) += ftgmac100.o
-obj-$(CONFIG_FTMAC100) += ftmac100.o
-
-obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
-obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
-ll_temac-objs := ll_temac_main.o ll_temac_mdio.o
-obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o
-obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
-obj-$(CONFIG_QLA3XXX) += qla3xxx.o
-obj-$(CONFIG_QLCNIC) += qlcnic/
-obj-$(CONFIG_QLGE) += qlge/
-
-obj-$(CONFIG_PPP) += ppp_generic.o
-obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
-obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
-obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
-obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
-obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
-obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
-obj-$(CONFIG_PPPOL2TP) += pppox.o
-obj-$(CONFIG_PPTP) += pppox.o pptp.o
-
-obj-$(CONFIG_SLIP) += slip.o
-obj-$(CONFIG_SLHC) += slhc.o
-
-obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
-obj-$(CONFIG_XEN_NETDEV_BACKEND) += xen-netback/
-
+obj-$(CONFIG_BONDING) += bonding/
 obj-$(CONFIG_DUMMY) += dummy.o
+obj-$(CONFIG_EQUALIZER) += eql.o
 obj-$(CONFIG_IFB) += ifb.o
 obj-$(CONFIG_MACVLAN) += macvlan.o
 obj-$(CONFIG_MACVTAP) += macvtap.o
-obj-$(CONFIG_DE600) += de600.o
-obj-$(CONFIG_DE620) += de620.o
-obj-$(CONFIG_LANCE) += lance.o
-obj-$(CONFIG_SUN3_82586) += sun3_82586.o
-obj-$(CONFIG_SUN3LANCE) += sun3lance.o
-obj-$(CONFIG_DEFXX) += defxx.o
-obj-$(CONFIG_SGISEEQ) += sgiseeq.o
-obj-$(CONFIG_SGI_O2MACE_ETH) += meth.o
-obj-$(CONFIG_AT1700) += at1700.o
-obj-$(CONFIG_EL1) += 3c501.o
-obj-$(CONFIG_EL16) += 3c507.o
-obj-$(CONFIG_ELMC) += 3c523.o
-obj-$(CONFIG_IBMLANA) += ibmlana.o
-obj-$(CONFIG_ELMC_II) += 3c527.o
-obj-$(CONFIG_EL3) += 3c509.o
-obj-$(CONFIG_3C515) += 3c515.o
-obj-$(CONFIG_EEXPRESS) += eexpress.o
-obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
-obj-$(CONFIG_8139CP) += 8139cp.o
-obj-$(CONFIG_8139TOO) += 8139too.o
-obj-$(CONFIG_ZNET) += znet.o
-obj-$(CONFIG_CPMAC) += cpmac.o
-obj-$(CONFIG_DEPCA) += depca.o
-obj-$(CONFIG_EWRK3) += ewrk3.o
-obj-$(CONFIG_ATP) += atp.o
-obj-$(CONFIG_NI5010) += ni5010.o
-obj-$(CONFIG_NI52) += ni52.o
-obj-$(CONFIG_NI65) += ni65.o
-obj-$(CONFIG_ELPLUS) += 3c505.o
-obj-$(CONFIG_AC3200) += ac3200.o 8390.o
-obj-$(CONFIG_APRICOT) += 82596.o
-obj-$(CONFIG_LASI_82596) += lasi_82596.o
-obj-$(CONFIG_SNI_82596) += sni_82596.o
-obj-$(CONFIG_MVME16x_NET) += 82596.o
-obj-$(CONFIG_BVME6000_NET) += 82596.o
-obj-$(CONFIG_SC92031) += sc92031.o
-
-# This is also a 82596 and should probably be merged
-obj-$(CONFIG_LP486E) += lp486e.o
-
-obj-$(CONFIG_ETH16I) += eth16i.o
-obj-$(CONFIG_ZORRO8390) += zorro8390.o
-obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
-obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
-obj-$(CONFIG_EQUALIZER) += eql.o
-obj-$(CONFIG_KORINA) += korina.o
-obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
-obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
-obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
-obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
-obj-$(CONFIG_DECLANCE) += declance.o
-obj-$(CONFIG_ATARILANCE) += atarilance.o
-obj-$(CONFIG_A2065) += a2065.o
-obj-$(CONFIG_HYDRA) += hydra.o
-obj-$(CONFIG_ARIADNE) += ariadne.o
-obj-$(CONFIG_CS89x0) += cs89x0.o
-obj-$(CONFIG_MACSONIC) += macsonic.o
-obj-$(CONFIG_MACMACE) += macmace.o
-obj-$(CONFIG_MAC89x0) += mac89x0.o
+obj-$(CONFIG_MII) += mii.o
+obj-$(CONFIG_MDIO) += mdio.o
+obj-$(CONFIG_NET) += Space.o loopback.o
+obj-$(CONFIG_NETCONSOLE) += netconsole.o
+obj-$(CONFIG_PHYLIB) += phy/
+obj-$(CONFIG_RIONET) += rionet.o
 obj-$(CONFIG_TUN) += tun.o
 obj-$(CONFIG_VETH) += veth.o
-obj-$(CONFIG_NET_NETX) += netx-eth.o
-obj-$(CONFIG_DL2K) += dl2k.o
-obj-$(CONFIG_R8169) += r8169.o
-obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
-obj-$(CONFIG_IBMVETH) += ibmveth.o
-obj-$(CONFIG_S2IO) += s2io.o
-obj-$(CONFIG_VXGE) += vxge/
-obj-$(CONFIG_MYRI10GE) += myri10ge/
-obj-$(CONFIG_SMC91X) += smc91x.o
-obj-$(CONFIG_SMC911X) += smc911x.o
-obj-$(CONFIG_SMSC911X) += smsc911x.o
-obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
-obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
-obj-$(CONFIG_DM9000) += dm9000.o
-obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o
-pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o
-obj-$(CONFIG_MLX4_CORE) += mlx4/
-obj-$(CONFIG_ENC28J60) += enc28j60.o
-obj-$(CONFIG_ETHOC) += ethoc.o
-obj-$(CONFIG_GRETH) += greth.o
-obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
-
-obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
-
-obj-$(CONFIG_DNET) += dnet.o
-obj-$(CONFIG_MACB) += macb.o
-obj-$(CONFIG_S6GMAC) += s6gmac.o
+obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
 
-obj-$(CONFIG_ARM) += arm/
+#
+# Networking Drivers
+#
+obj-$(CONFIG_ARCNET) += arcnet/
 obj-$(CONFIG_DEV_APPLETALK) += appletalk/
+obj-$(CONFIG_CAIF) += caif/
+obj-$(CONFIG_CAN) += can/
+obj-$(CONFIG_ETRAX_ETHERNET) += cris/
+obj-$(CONFIG_ETHERNET) += ethernet/
+obj-$(CONFIG_FDDI) += fddi/
+obj-$(CONFIG_HIPPI) += hippi/
+obj-$(CONFIG_HAMRADIO) += hamradio/
+obj-$(CONFIG_IRDA) += irda/
+obj-$(CONFIG_PLIP) += plip/
+onj-$(CONFIG_PPP) += ppp/
+obj-$(CONFIG_PPP_ASYNC) += ppp/
+obj-$(CONFIG_PPP_BSDCOMP) += ppp/
+obj-$(CONFIG_PPP_DEFLATE) += ppp/
+obj-$(CONFIG_PPP_MPPE) += ppp/
+obj-$(CONFIG_PPP_SYNC_TTY) += ppp/
+obj-$(CONFIG_PPPOE) += ppp/
+obj-$(CONFIG_PPPOL2TP) += ppp/
+obj-$(CONFIG_PPTP) += ppp/
+onj-$(CONFIG_SLIP) += slip/
+obj-$(CONFIG_SLHC) += slip/
+obj-$(CONFIG_NET_SB1000) += sb1000.o
+onj-$(CONFIG_SLIP) += slip/
+obj-$(CONFIG_SUNGEM_PHY) += sungem_phy.o
 obj-$(CONFIG_TR) += tokenring/
 obj-$(CONFIG_WAN) += wan/
-obj-$(CONFIG_ARCNET) += arcnet/
-obj-$(CONFIG_NET_PCMCIA) += pcmcia/
+obj-$(CONFIG_WLAN) += wireless/
+obj-$(CONFIG_WIMAX) += wimax/
+
+obj-$(CONFIG_VMXNET3) += vmxnet3/
+obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
+obj-$(CONFIG_XEN_NETDEV_BACKEND) += xen-netback/
 
 obj-$(CONFIG_USB_CATC)          += usb/
 obj-$(CONFIG_USB_KAWETH)        += usb/
@@ -283,26 +67,3 @@ obj-$(CONFIG_USB_USBNET)        += usb/
 obj-$(CONFIG_USB_ZD1201)        += usb/
 obj-$(CONFIG_USB_IPHETH)        += usb/
 obj-$(CONFIG_USB_CDC_PHONET)   += usb/
-
-obj-$(CONFIG_WLAN) += wireless/
-obj-$(CONFIG_NET_TULIP) += tulip/
-obj-$(CONFIG_HAMRADIO) += hamradio/
-obj-$(CONFIG_IRDA) += irda/
-obj-$(CONFIG_ETRAX_ETHERNET) += cris/
-obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/
-
-obj-$(CONFIG_NETCONSOLE) += netconsole.o
-
-obj-$(CONFIG_FS_ENET) += fs_enet/
-
-obj-$(CONFIG_NETXEN_NIC) += netxen/
-obj-$(CONFIG_NIU) += niu.o
-obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
-obj-$(CONFIG_SFC) += sfc/
-
-obj-$(CONFIG_WIMAX) += wimax/
-obj-$(CONFIG_CAIF) += caif/
-
-obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
-obj-$(CONFIG_PCH_GBE) += pch_gbe/
-obj-$(CONFIG_TILE_NET) += tile/
index 748c9f5..9abd4eb 100644 (file)
@@ -264,7 +264,7 @@ static const struct net_device_ops cops_netdev_ops = {
        .ndo_start_xmit         = cops_send_packet,
        .ndo_tx_timeout         = cops_timeout,
         .ndo_do_ioctl           = cops_ioctl,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
 };
 
 /*
index 34ffb54..6057b30 100644 (file)
@@ -1014,7 +1014,7 @@ static int __init ltpc_probe_dma(int base, int dma)
 static const struct net_device_ops ltpc_netdev = {
        .ndo_start_xmit         = ltpc_xmit,
        .ndo_do_ioctl           = ltpc_ioctl,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
 };
 
 struct net_device * __init ltpc_probe(void)
index 3b2f7f1..a73d9dc 100644 (file)
@@ -3,8 +3,8 @@
 #
 
 menuconfig ARCNET
-       depends on NETDEVICES && (ISA || PCI)
-       tristate "ARCnet support"
+       depends on NETDEVICES && (ISA || PCI || PCMCIA)
+       bool "ARCnet support"
        ---help---
          If you have a network card of this type, say Y and check out the
          (arguably) beautiful poetry in
@@ -123,4 +123,14 @@ config ARCNET_COM20020_PCI
        tristate "Support for COM20020 on PCI"
        depends on ARCNET_COM20020 && PCI
 
+config ARCNET_COM20020_CS
+       tristate "COM20020 ARCnet PCMCIA support"
+       depends on ARCNET_COM20020 && PCMCIA
+       help
+         Say Y here if you intend to attach this type of ARCnet PCMCIA card
+         to your computer.
+
+         To compile this driver as a module, choose M here: the module will be
+         called com20020_cs.  If unsure, say N.
+
 endif # ARCNET
index 5861af5..5ce8ee6 100644 (file)
@@ -12,3 +12,4 @@ obj-$(CONFIG_ARCNET_RIM_I) += arc-rimi.o
 obj-$(CONFIG_ARCNET_COM20020) += com20020.o
 obj-$(CONFIG_ARCNET_COM20020_ISA) += com20020-isa.o
 obj-$(CONFIG_ARCNET_COM20020_PCI) += com20020-pci.o
+obj-$(CONFIG_ARCNET_COM20020_CS) += com20020_cs.o
index 7bfb91f..7b96c5f 100644 (file)
@@ -154,7 +154,7 @@ const struct net_device_ops com20020_netdev_ops = {
        .ndo_stop       = arcnet_close,
        .ndo_start_xmit = arcnet_send_packet,
        .ndo_tx_timeout = arcnet_timeout,
-       .ndo_set_multicast_list = com20020_set_mc_list,
+       .ndo_set_rx_mode = com20020_set_mc_list,
 };
 
 /* Set up the struct net_device associated with this card.  Called after
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
deleted file mode 100644 (file)
index 39e1c0d..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# Acorn Network device configuration
-#  These are for Acorn's Expansion card network interfaces
-#
-config ARM_AM79C961A
-       bool "ARM EBSA110 AM79C961A support"
-       depends on ARM && ARCH_EBSA110
-       select CRC32
-       help
-         If you wish to compile a kernel for the EBSA-110, then you should
-         always answer Y to this.
-
-config ARM_ETHER1
-       tristate "Acorn Ether1 support"
-       depends on ARM && ARCH_ACORN
-       help
-         If you have an Acorn system with one of these (AKA25) network cards,
-         you should say Y to this option if you wish to use it with Linux.
-
-config ARM_ETHER3
-       tristate "Acorn/ANT Ether3 support"
-       depends on ARM && ARCH_ACORN
-       help
-         If you have an Acorn system with one of these network cards, you
-         should say Y to this option if you wish to use it with Linux.
-
-config ARM_ETHERH
-       tristate "I-cubed EtherH/ANT EtherM support"
-       depends on ARM && ARCH_ACORN
-       select CRC32
-       help
-         If you have an Acorn system with one of these network cards, you
-         should say Y to this option if you wish to use it with Linux.
-
-config ARM_AT91_ETHER
-       tristate "AT91RM9200 Ethernet support"
-       depends on ARM && ARCH_AT91RM9200
-       select MII
-       help
-         If you wish to compile a kernel for the AT91RM9200 and enable
-         ethernet support, then you should always answer Y to this.
-
-config ARM_KS8695_ETHER
-       tristate "KS8695 Ethernet support"
-       depends on ARM && ARCH_KS8695
-       select MII
-       help
-         If you wish to compile a kernel for the KS8695 and want to
-         use the internal ethernet then you should answer Y to this.
-
-config EP93XX_ETH
-       tristate "EP93xx Ethernet support"
-       depends on ARM && ARCH_EP93XX
-       select MII
-       help
-         This is a driver for the ethernet hardware included in EP93xx CPUs.
-         Say Y if you are building a kernel for EP93xx based devices.
-
-config IXP4XX_ETH
-       tristate "Intel IXP4xx Ethernet support"
-       depends on ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR
-       select PHYLIB
-       help
-         Say Y here if you want to use built-in Ethernet ports
-         on IXP4xx processor.
-
-config W90P910_ETH
-       tristate "Nuvoton w90p910 Ethernet support"
-       depends on ARM && ARCH_W90X900
-       select PHYLIB
-       select MII
-       help
-         Say Y here if you want to use built-in Ethernet ports
-         on w90p910 processor.
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
deleted file mode 100644 (file)
index 303171f..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# File: drivers/net/arm/Makefile
-#
-# Makefile for the ARM network device drivers
-#
-
-obj-$(CONFIG_ARM_AM79C961A)    += am79c961a.o
-obj-$(CONFIG_ARM_ETHERH)       += etherh.o
-obj-$(CONFIG_ARM_ETHER3)       += ether3.o
-obj-$(CONFIG_ARM_ETHER1)       += ether1.o
-obj-$(CONFIG_ARM_AT91_ETHER)   += at91_ether.o
-obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o
-obj-$(CONFIG_EP93XX_ETH)       += ep93xx_eth.o
-obj-$(CONFIG_IXP4XX_ETH)       += ixp4xx_eth.o
-obj-$(CONFIG_W90P910_ETH)      += w90p910_ether.o
diff --git a/drivers/net/benet/Kconfig b/drivers/net/benet/Kconfig
deleted file mode 100644 (file)
index 1a41a49..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-config BE2NET
-       tristate "ServerEngines' 10Gbps NIC - BladeEngine"
-       depends on PCI && INET
-       help
-       This driver implements the NIC functionality for ServerEngines'
-       10Gbps network adapter - BladeEngine.
diff --git a/drivers/net/bna/bfi_ctreg.h b/drivers/net/bna/bfi_ctreg.h
deleted file mode 100644 (file)
index 5130d79..0000000
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-/*
- * bfi_ctreg.h catapult host block register definitions
- *
- * !!! Do not edit. Auto generated. !!!
- */
-
-#ifndef __BFI_CTREG_H__
-#define __BFI_CTREG_H__
-
-#define HOSTFN0_LPU_MBOX0_0            0x00019200
-#define HOSTFN1_LPU_MBOX0_8            0x00019260
-#define LPU_HOSTFN0_MBOX0_0            0x00019280
-#define LPU_HOSTFN1_MBOX0_8            0x000192e0
-#define HOSTFN2_LPU_MBOX0_0            0x00019400
-#define HOSTFN3_LPU_MBOX0_8            0x00019460
-#define LPU_HOSTFN2_MBOX0_0            0x00019480
-#define LPU_HOSTFN3_MBOX0_8            0x000194e0
-#define HOSTFN0_INT_STATUS             0x00014000
-#define __HOSTFN0_HALT_OCCURRED                0x01000000
-#define __HOSTFN0_INT_STATUS_LVL_MK    0x00f00000
-#define __HOSTFN0_INT_STATUS_LVL_SH    20
-#define __HOSTFN0_INT_STATUS_LVL(_v)   ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
-#define __HOSTFN0_INT_STATUS_P_MK      0x000f0000
-#define __HOSTFN0_INT_STATUS_P_SH      16
-#define __HOSTFN0_INT_STATUS_P(_v)     ((_v) << __HOSTFN0_INT_STATUS_P_SH)
-#define __HOSTFN0_INT_STATUS_F         0x0000ffff
-#define HOSTFN0_INT_MSK                        0x00014004
-#define HOST_PAGE_NUM_FN0              0x00014008
-#define __HOST_PAGE_NUM_FN             0x000001ff
-#define HOST_MSIX_ERR_INDEX_FN0                0x0001400c
-#define __MSIX_ERR_INDEX_FN            0x000001ff
-#define HOSTFN1_INT_STATUS             0x00014100
-#define __HOSTFN1_HALT_OCCURRED                0x01000000
-#define __HOSTFN1_INT_STATUS_LVL_MK    0x00f00000
-#define __HOSTFN1_INT_STATUS_LVL_SH    20
-#define __HOSTFN1_INT_STATUS_LVL(_v)   ((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
-#define __HOSTFN1_INT_STATUS_P_MK      0x000f0000
-#define __HOSTFN1_INT_STATUS_P_SH      16
-#define __HOSTFN1_INT_STATUS_P(_v)     ((_v) << __HOSTFN1_INT_STATUS_P_SH)
-#define __HOSTFN1_INT_STATUS_F         0x0000ffff
-#define HOSTFN1_INT_MSK                        0x00014104
-#define HOST_PAGE_NUM_FN1              0x00014108
-#define HOST_MSIX_ERR_INDEX_FN1                0x0001410c
-#define APP_PLL_425_CTL_REG            0x00014204
-#define __P_425_PLL_LOCK               0x80000000
-#define __APP_PLL_425_SRAM_USE_100MHZ  0x00100000
-#define __APP_PLL_425_RESET_TIMER_MK   0x000e0000
-#define __APP_PLL_425_RESET_TIMER_SH   17
-#define __APP_PLL_425_RESET_TIMER(_v)  ((_v) << __APP_PLL_425_RESET_TIMER_SH)
-#define __APP_PLL_425_LOGIC_SOFT_RESET 0x00010000
-#define __APP_PLL_425_CNTLMT0_1_MK     0x0000c000
-#define __APP_PLL_425_CNTLMT0_1_SH     14
-#define __APP_PLL_425_CNTLMT0_1(_v)    ((_v) << __APP_PLL_425_CNTLMT0_1_SH)
-#define __APP_PLL_425_JITLMT0_1_MK     0x00003000
-#define __APP_PLL_425_JITLMT0_1_SH     12
-#define __APP_PLL_425_JITLMT0_1(_v)    ((_v) << __APP_PLL_425_JITLMT0_1_SH)
-#define __APP_PLL_425_HREF             0x00000800
-#define __APP_PLL_425_HDIV             0x00000400
-#define __APP_PLL_425_P0_1_MK          0x00000300
-#define __APP_PLL_425_P0_1_SH          8
-#define __APP_PLL_425_P0_1(_v)         ((_v) << __APP_PLL_425_P0_1_SH)
-#define __APP_PLL_425_Z0_2_MK          0x000000e0
-#define __APP_PLL_425_Z0_2_SH          5
-#define __APP_PLL_425_Z0_2(_v)         ((_v) << __APP_PLL_425_Z0_2_SH)
-#define __APP_PLL_425_RSEL200500       0x00000010
-#define __APP_PLL_425_ENARST           0x00000008
-#define __APP_PLL_425_BYPASS           0x00000004
-#define __APP_PLL_425_LRESETN          0x00000002
-#define __APP_PLL_425_ENABLE           0x00000001
-#define APP_PLL_312_CTL_REG            0x00014208
-#define __P_312_PLL_LOCK               0x80000000
-#define __ENABLE_MAC_AHB_1             0x00800000
-#define __ENABLE_MAC_AHB_0             0x00400000
-#define __ENABLE_MAC_1                 0x00200000
-#define __ENABLE_MAC_0                 0x00100000
-#define __APP_PLL_312_RESET_TIMER_MK   0x000e0000
-#define __APP_PLL_312_RESET_TIMER_SH   17
-#define __APP_PLL_312_RESET_TIMER(_v)  ((_v) << __APP_PLL_312_RESET_TIMER_SH)
-#define __APP_PLL_312_LOGIC_SOFT_RESET 0x00010000
-#define __APP_PLL_312_CNTLMT0_1_MK     0x0000c000
-#define __APP_PLL_312_CNTLMT0_1_SH     14
-#define __APP_PLL_312_CNTLMT0_1(_v)    ((_v) << __APP_PLL_312_CNTLMT0_1_SH)
-#define __APP_PLL_312_JITLMT0_1_MK     0x00003000
-#define __APP_PLL_312_JITLMT0_1_SH     12
-#define __APP_PLL_312_JITLMT0_1(_v)    ((_v) << __APP_PLL_312_JITLMT0_1_SH)
-#define __APP_PLL_312_HREF             0x00000800
-#define __APP_PLL_312_HDIV             0x00000400
-#define __APP_PLL_312_P0_1_MK          0x00000300
-#define __APP_PLL_312_P0_1_SH          8
-#define __APP_PLL_312_P0_1(_v)         ((_v) << __APP_PLL_312_P0_1_SH)
-#define __APP_PLL_312_Z0_2_MK          0x000000e0
-#define __APP_PLL_312_Z0_2_SH          5
-#define __APP_PLL_312_Z0_2(_v)         ((_v) << __APP_PLL_312_Z0_2_SH)
-#define __APP_PLL_312_RSEL200500       0x00000010
-#define __APP_PLL_312_ENARST           0x00000008
-#define __APP_PLL_312_BYPASS           0x00000004
-#define __APP_PLL_312_LRESETN          0x00000002
-#define __APP_PLL_312_ENABLE           0x00000001
-#define MBIST_CTL_REG                  0x00014220
-#define __EDRAM_BISTR_START            0x00000004
-#define __MBIST_RESET                  0x00000002
-#define __MBIST_START                  0x00000001
-#define MBIST_STAT_REG                 0x00014224
-#define __EDRAM_BISTR_STATUS           0x00000008
-#define __EDRAM_BISTR_DONE             0x00000004
-#define __MEM_BIT_STATUS               0x00000002
-#define __MBIST_DONE                   0x00000001
-#define HOST_SEM0_REG                  0x00014230
-#define __HOST_SEMAPHORE               0x00000001
-#define HOST_SEM1_REG                  0x00014234
-#define HOST_SEM2_REG                  0x00014238
-#define HOST_SEM3_REG                  0x0001423c
-#define HOST_SEM0_INFO_REG             0x00014240
-#define HOST_SEM1_INFO_REG             0x00014244
-#define HOST_SEM2_INFO_REG             0x00014248
-#define HOST_SEM3_INFO_REG             0x0001424c
-#define ETH_MAC_SER_REG                        0x00014288
-#define __APP_EMS_CKBUFAMPIN           0x00000020
-#define __APP_EMS_REFCLKSEL            0x00000010
-#define __APP_EMS_CMLCKSEL             0x00000008
-#define __APP_EMS_REFCKBUFEN2          0x00000004
-#define __APP_EMS_REFCKBUFEN1          0x00000002
-#define __APP_EMS_CHANNEL_SEL          0x00000001
-#define HOSTFN2_INT_STATUS             0x00014300
-#define __HOSTFN2_HALT_OCCURRED                0x01000000
-#define __HOSTFN2_INT_STATUS_LVL_MK    0x00f00000
-#define __HOSTFN2_INT_STATUS_LVL_SH    20
-#define __HOSTFN2_INT_STATUS_LVL(_v)   ((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
-#define __HOSTFN2_INT_STATUS_P_MK      0x000f0000
-#define __HOSTFN2_INT_STATUS_P_SH      16
-#define __HOSTFN2_INT_STATUS_P(_v)     ((_v) << __HOSTFN2_INT_STATUS_P_SH)
-#define __HOSTFN2_INT_STATUS_F         0x0000ffff
-#define HOSTFN2_INT_MSK                        0x00014304
-#define HOST_PAGE_NUM_FN2              0x00014308
-#define HOST_MSIX_ERR_INDEX_FN2                0x0001430c
-#define HOSTFN3_INT_STATUS             0x00014400
-#define __HALT_OCCURRED                        0x01000000
-#define __HOSTFN3_INT_STATUS_LVL_MK    0x00f00000
-#define __HOSTFN3_INT_STATUS_LVL_SH    20
-#define __HOSTFN3_INT_STATUS_LVL(_v)   ((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
-#define __HOSTFN3_INT_STATUS_P_MK      0x000f0000
-#define __HOSTFN3_INT_STATUS_P_SH      16
-#define __HOSTFN3_INT_STATUS_P(_v)     ((_v) << __HOSTFN3_INT_STATUS_P_SH)
-#define __HOSTFN3_INT_STATUS_F         0x0000ffff
-#define HOSTFN3_INT_MSK                        0x00014404
-#define HOST_PAGE_NUM_FN3              0x00014408
-#define HOST_MSIX_ERR_INDEX_FN3                0x0001440c
-#define FNC_ID_REG                     0x00014600
-#define __FUNCTION_NUMBER              0x00000007
-#define FNC_PERS_REG                   0x00014604
-#define __F3_FUNCTION_ACTIVE           0x80000000
-#define __F3_FUNCTION_MODE             0x40000000
-#define __F3_PORT_MAP_MK               0x30000000
-#define __F3_PORT_MAP_SH               28
-#define __F3_PORT_MAP(_v)              ((_v) << __F3_PORT_MAP_SH)
-#define __F3_VM_MODE                   0x08000000
-#define __F3_INTX_STATUS_MK            0x07000000
-#define __F3_INTX_STATUS_SH            24
-#define __F3_INTX_STATUS(_v)           ((_v) << __F3_INTX_STATUS_SH)
-#define __F2_FUNCTION_ACTIVE           0x00800000
-#define __F2_FUNCTION_MODE             0x00400000
-#define __F2_PORT_MAP_MK               0x00300000
-#define __F2_PORT_MAP_SH               20
-#define __F2_PORT_MAP(_v)              ((_v) << __F2_PORT_MAP_SH)
-#define __F2_VM_MODE                   0x00080000
-#define __F2_INTX_STATUS_MK            0x00070000
-#define __F2_INTX_STATUS_SH            16
-#define __F2_INTX_STATUS(_v)           ((_v) << __F2_INTX_STATUS_SH)
-#define __F1_FUNCTION_ACTIVE           0x00008000
-#define __F1_FUNCTION_MODE             0x00004000
-#define __F1_PORT_MAP_MK               0x00003000
-#define __F1_PORT_MAP_SH               12
-#define __F1_PORT_MAP(_v)              ((_v) << __F1_PORT_MAP_SH)
-#define __F1_VM_MODE                   0x00000800
-#define __F1_INTX_STATUS_MK            0x00000700
-#define __F1_INTX_STATUS_SH            8
-#define __F1_INTX_STATUS(_v)           ((_v) << __F1_INTX_STATUS_SH)
-#define __F0_FUNCTION_ACTIVE           0x00000080
-#define __F0_FUNCTION_MODE             0x00000040
-#define __F0_PORT_MAP_MK               0x00000030
-#define __F0_PORT_MAP_SH               4
-#define __F0_PORT_MAP(_v)              ((_v) << __F0_PORT_MAP_SH)
-#define __F0_VM_MODE           0x00000008
-#define __F0_INTX_STATUS               0x00000007
-enum {
-       __F0_INTX_STATUS_MSIX           = 0x0,
-       __F0_INTX_STATUS_INTA           = 0x1,
-       __F0_INTX_STATUS_INTB           = 0x2,
-       __F0_INTX_STATUS_INTC           = 0x3,
-       __F0_INTX_STATUS_INTD           = 0x4,
-};
-#define OP_MODE                                0x0001460c
-#define __APP_ETH_CLK_LOWSPEED         0x00000004
-#define __GLOBAL_CORECLK_HALFSPEED     0x00000002
-#define __GLOBAL_FCOE_MODE             0x00000001
-#define HOST_SEM4_REG                  0x00014610
-#define HOST_SEM5_REG                  0x00014614
-#define HOST_SEM6_REG                  0x00014618
-#define HOST_SEM7_REG                  0x0001461c
-#define HOST_SEM4_INFO_REG             0x00014620
-#define HOST_SEM5_INFO_REG             0x00014624
-#define HOST_SEM6_INFO_REG             0x00014628
-#define HOST_SEM7_INFO_REG             0x0001462c
-#define HOSTFN0_LPU0_MBOX0_CMD_STAT    0x00019000
-#define __HOSTFN0_LPU0_MBOX0_INFO_MK   0xfffffffe
-#define __HOSTFN0_LPU0_MBOX0_INFO_SH   1
-#define __HOSTFN0_LPU0_MBOX0_INFO(_v)  ((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN0_LPU1_MBOX0_CMD_STAT    0x00019004
-#define __HOSTFN0_LPU1_MBOX0_INFO_MK   0xfffffffe
-#define __HOSTFN0_LPU1_MBOX0_INFO_SH   1
-#define __HOSTFN0_LPU1_MBOX0_INFO(_v)  ((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN0_MBOX0_CMD_STAT    0x00019008
-#define __LPU0_HOSTFN0_MBOX0_INFO_MK   0xfffffffe
-#define __LPU0_HOSTFN0_MBOX0_INFO_SH   1
-#define __LPU0_HOSTFN0_MBOX0_INFO(_v)  ((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN0_MBOX0_CMD_STAT    0x0001900c
-#define __LPU1_HOSTFN0_MBOX0_INFO_MK   0xfffffffe
-#define __LPU1_HOSTFN0_MBOX0_INFO_SH   1
-#define __LPU1_HOSTFN0_MBOX0_INFO(_v)  ((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN1_LPU0_MBOX0_CMD_STAT    0x00019010
-#define __HOSTFN1_LPU0_MBOX0_INFO_MK   0xfffffffe
-#define __HOSTFN1_LPU0_MBOX0_INFO_SH   1
-#define __HOSTFN1_LPU0_MBOX0_INFO(_v)  ((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN1_LPU1_MBOX0_CMD_STAT    0x00019014
-#define __HOSTFN1_LPU1_MBOX0_INFO_MK   0xfffffffe
-#define __HOSTFN1_LPU1_MBOX0_INFO_SH   1
-#define __HOSTFN1_LPU1_MBOX0_INFO(_v)  ((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN1_MBOX0_CMD_STAT    0x00019018
-#define __LPU0_HOSTFN1_MBOX0_INFO_MK   0xfffffffe
-#define __LPU0_HOSTFN1_MBOX0_INFO_SH   1
-#define __LPU0_HOSTFN1_MBOX0_INFO(_v)  ((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN1_MBOX0_CMD_STAT    0x0001901c
-#define __LPU1_HOSTFN1_MBOX0_INFO_MK   0xfffffffe
-#define __LPU1_HOSTFN1_MBOX0_INFO_SH   1
-#define __LPU1_HOSTFN1_MBOX0_INFO(_v)  ((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN2_LPU0_MBOX0_CMD_STAT    0x00019150
-#define __HOSTFN2_LPU0_MBOX0_INFO_MK   0xfffffffe
-#define __HOSTFN2_LPU0_MBOX0_INFO_SH   1
-#define __HOSTFN2_LPU0_MBOX0_INFO(_v)  ((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN2_LPU1_MBOX0_CMD_STAT    0x00019154
-#define __HOSTFN2_LPU1_MBOX0_INFO_MK   0xfffffffe
-#define __HOSTFN2_LPU1_MBOX0_INFO_SH   1
-#define __HOSTFN2_LPU1_MBOX0_INFO(_v)  ((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN2_MBOX0_CMD_STAT    0x00019158
-#define __LPU0_HOSTFN2_MBOX0_INFO_MK   0xfffffffe
-#define __LPU0_HOSTFN2_MBOX0_INFO_SH   1
-#define __LPU0_HOSTFN2_MBOX0_INFO(_v)  ((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN2_MBOX0_CMD_STAT    0x0001915c
-#define __LPU1_HOSTFN2_MBOX0_INFO_MK   0xfffffffe
-#define __LPU1_HOSTFN2_MBOX0_INFO_SH   1
-#define __LPU1_HOSTFN2_MBOX0_INFO(_v)  ((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN3_LPU0_MBOX0_CMD_STAT    0x00019160
-#define __HOSTFN3_LPU0_MBOX0_INFO_MK   0xfffffffe
-#define __HOSTFN3_LPU0_MBOX0_INFO_SH   1
-#define __HOSTFN3_LPU0_MBOX0_INFO(_v)  ((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN3_LPU1_MBOX0_CMD_STAT    0x00019164
-#define __HOSTFN3_LPU1_MBOX0_INFO_MK   0xfffffffe
-#define __HOSTFN3_LPU1_MBOX0_INFO_SH   1
-#define __HOSTFN3_LPU1_MBOX0_INFO(_v)  ((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN3_MBOX0_CMD_STAT    0x00019168
-#define __LPU0_HOSTFN3_MBOX0_INFO_MK   0xfffffffe
-#define __LPU0_HOSTFN3_MBOX0_INFO_SH   1
-#define __LPU0_HOSTFN3_MBOX0_INFO(_v)  ((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN3_MBOX0_CMD_STAT    0x0001916c
-#define __LPU1_HOSTFN3_MBOX0_INFO_MK   0xfffffffe
-#define __LPU1_HOSTFN3_MBOX0_INFO_SH   1
-#define __LPU1_HOSTFN3_MBOX0_INFO(_v)  ((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS        0x00000001
-#define FW_INIT_HALT_P0                        0x000191ac
-#define __FW_INIT_HALT_P               0x00000001
-#define FW_INIT_HALT_P1                        0x000191bc
-#define CPE_PI_PTR_Q0                  0x00038000
-#define __CPE_PI_UNUSED_MK             0xffff0000
-#define __CPE_PI_UNUSED_SH             16
-#define __CPE_PI_UNUSED(_v)            ((_v) << __CPE_PI_UNUSED_SH)
-#define __CPE_PI_PTR                   0x0000ffff
-#define CPE_PI_PTR_Q1                  0x00038040
-#define CPE_CI_PTR_Q0                  0x00038004
-#define __CPE_CI_UNUSED_MK             0xffff0000
-#define __CPE_CI_UNUSED_SH             16
-#define __CPE_CI_UNUSED(_v)            ((_v) << __CPE_CI_UNUSED_SH)
-#define __CPE_CI_PTR                   0x0000ffff
-#define CPE_CI_PTR_Q1                  0x00038044
-#define CPE_DEPTH_Q0                   0x00038008
-#define __CPE_DEPTH_UNUSED_MK          0xf8000000
-#define __CPE_DEPTH_UNUSED_SH          27
-#define __CPE_DEPTH_UNUSED(_v)         ((_v) << __CPE_DEPTH_UNUSED_SH)
-#define __CPE_MSIX_VEC_INDEX_MK                0x07ff0000
-#define __CPE_MSIX_VEC_INDEX_SH                16
-#define __CPE_MSIX_VEC_INDEX(_v)       ((_v) << __CPE_MSIX_VEC_INDEX_SH)
-#define __CPE_DEPTH                    0x0000ffff
-#define CPE_DEPTH_Q1                   0x00038048
-#define CPE_QCTRL_Q0                   0x0003800c
-#define __CPE_CTRL_UNUSED30_MK         0xfc000000
-#define __CPE_CTRL_UNUSED30_SH         26
-#define __CPE_CTRL_UNUSED30(_v)                ((_v) << __CPE_CTRL_UNUSED30_SH)
-#define __CPE_FUNC_INT_CTRL_MK         0x03000000
-#define __CPE_FUNC_INT_CTRL_SH         24
-#define __CPE_FUNC_INT_CTRL(_v)                ((_v) << __CPE_FUNC_INT_CTRL_SH)
-enum {
-       __CPE_FUNC_INT_CTRL_DISABLE             = 0x0,
-       __CPE_FUNC_INT_CTRL_F2NF                = 0x1,
-       __CPE_FUNC_INT_CTRL_3QUART              = 0x2,
-       __CPE_FUNC_INT_CTRL_HALF                = 0x3,
-};
-#define __CPE_CTRL_UNUSED20_MK         0x00f00000
-#define __CPE_CTRL_UNUSED20_SH         20
-#define __CPE_CTRL_UNUSED20(_v)                ((_v) << __CPE_CTRL_UNUSED20_SH)
-#define __CPE_SCI_TH_MK                        0x000f0000
-#define __CPE_SCI_TH_SH                        16
-#define __CPE_SCI_TH(_v)               ((_v) << __CPE_SCI_TH_SH)
-#define __CPE_CTRL_UNUSED10_MK         0x0000c000
-#define __CPE_CTRL_UNUSED10_SH         14
-#define __CPE_CTRL_UNUSED10(_v)                ((_v) << __CPE_CTRL_UNUSED10_SH)
-#define __CPE_ACK_PENDING              0x00002000
-#define __CPE_CTRL_UNUSED40_MK         0x00001c00
-#define __CPE_CTRL_UNUSED40_SH         10
-#define __CPE_CTRL_UNUSED40(_v)                ((_v) << __CPE_CTRL_UNUSED40_SH)
-#define __CPE_PCIEID_MK                        0x00000300
-#define __CPE_PCIEID_SH                        8
-#define __CPE_PCIEID(_v)               ((_v) << __CPE_PCIEID_SH)
-#define __CPE_CTRL_UNUSED00_MK         0x000000fe
-#define __CPE_CTRL_UNUSED00_SH         1
-#define __CPE_CTRL_UNUSED00(_v)                ((_v) << __CPE_CTRL_UNUSED00_SH)
-#define __CPE_ESIZE                    0x00000001
-#define CPE_QCTRL_Q1                   0x0003804c
-#define __CPE_CTRL_UNUSED31_MK         0xfc000000
-#define __CPE_CTRL_UNUSED31_SH         26
-#define __CPE_CTRL_UNUSED31(_v)                ((_v) << __CPE_CTRL_UNUSED31_SH)
-#define __CPE_CTRL_UNUSED21_MK         0x00f00000
-#define __CPE_CTRL_UNUSED21_SH         20
-#define __CPE_CTRL_UNUSED21(_v)                ((_v) << __CPE_CTRL_UNUSED21_SH)
-#define __CPE_CTRL_UNUSED11_MK         0x0000c000
-#define __CPE_CTRL_UNUSED11_SH         14
-#define __CPE_CTRL_UNUSED11(_v)                ((_v) << __CPE_CTRL_UNUSED11_SH)
-#define __CPE_CTRL_UNUSED41_MK         0x00001c00
-#define __CPE_CTRL_UNUSED41_SH         10
-#define __CPE_CTRL_UNUSED41(_v)                ((_v) << __CPE_CTRL_UNUSED41_SH)
-#define __CPE_CTRL_UNUSED01_MK         0x000000fe
-#define __CPE_CTRL_UNUSED01_SH         1
-#define __CPE_CTRL_UNUSED01(_v)                ((_v) << __CPE_CTRL_UNUSED01_SH)
-#define RME_PI_PTR_Q0                  0x00038020
-#define __LATENCY_TIME_STAMP_MK                0xffff0000
-#define __LATENCY_TIME_STAMP_SH                16
-#define __LATENCY_TIME_STAMP(_v)       ((_v) << __LATENCY_TIME_STAMP_SH)
-#define __RME_PI_PTR                   0x0000ffff
-#define RME_PI_PTR_Q1                  0x00038060
-#define RME_CI_PTR_Q0                  0x00038024
-#define __DELAY_TIME_STAMP_MK          0xffff0000
-#define __DELAY_TIME_STAMP_SH          16
-#define __DELAY_TIME_STAMP(_v)         ((_v) << __DELAY_TIME_STAMP_SH)
-#define __RME_CI_PTR                   0x0000ffff
-#define RME_CI_PTR_Q1                  0x00038064
-#define RME_DEPTH_Q0                   0x00038028
-#define __RME_DEPTH_UNUSED_MK          0xf8000000
-#define __RME_DEPTH_UNUSED_SH          27
-#define __RME_DEPTH_UNUSED(_v)         ((_v) << __RME_DEPTH_UNUSED_SH)
-#define __RME_MSIX_VEC_INDEX_MK                0x07ff0000
-#define __RME_MSIX_VEC_INDEX_SH                16
-#define __RME_MSIX_VEC_INDEX(_v)       ((_v) << __RME_MSIX_VEC_INDEX_SH)
-#define __RME_DEPTH                    0x0000ffff
-#define RME_DEPTH_Q1                   0x00038068
-#define RME_QCTRL_Q0                   0x0003802c
-#define __RME_INT_LATENCY_TIMER_MK     0xff000000
-#define __RME_INT_LATENCY_TIMER_SH     24
-#define __RME_INT_LATENCY_TIMER(_v)    ((_v) << __RME_INT_LATENCY_TIMER_SH)
-#define __RME_INT_DELAY_TIMER_MK       0x00ff0000
-#define __RME_INT_DELAY_TIMER_SH       16
-#define __RME_INT_DELAY_TIMER(_v)      ((_v) << __RME_INT_DELAY_TIMER_SH)
-#define __RME_INT_DELAY_DISABLE                0x00008000
-#define __RME_DLY_DELAY_DISABLE                0x00004000
-#define __RME_ACK_PENDING              0x00002000
-#define __RME_FULL_INTERRUPT_DISABLE   0x00001000
-#define __RME_CTRL_UNUSED10_MK         0x00000c00
-#define __RME_CTRL_UNUSED10_SH         10
-#define __RME_CTRL_UNUSED10(_v)                ((_v) << __RME_CTRL_UNUSED10_SH)
-#define __RME_PCIEID_MK                        0x00000300
-#define __RME_PCIEID_SH                        8
-#define __RME_PCIEID(_v)               ((_v) << __RME_PCIEID_SH)
-#define __RME_CTRL_UNUSED00_MK         0x000000fe
-#define __RME_CTRL_UNUSED00_SH         1
-#define __RME_CTRL_UNUSED00(_v)                ((_v) << __RME_CTRL_UNUSED00_SH)
-#define __RME_ESIZE                    0x00000001
-#define RME_QCTRL_Q1                   0x0003806c
-#define __RME_CTRL_UNUSED11_MK         0x00000c00
-#define __RME_CTRL_UNUSED11_SH         10
-#define __RME_CTRL_UNUSED11(_v)                ((_v) << __RME_CTRL_UNUSED11_SH)
-#define __RME_CTRL_UNUSED01_MK         0x000000fe
-#define __RME_CTRL_UNUSED01_SH         1
-#define __RME_CTRL_UNUSED01(_v)                ((_v) << __RME_CTRL_UNUSED01_SH)
-#define PSS_CTL_REG                    0x00018800
-#define __PSS_I2C_CLK_DIV_MK           0x007f0000
-#define __PSS_I2C_CLK_DIV_SH           16
-#define __PSS_I2C_CLK_DIV(_v)          ((_v) << __PSS_I2C_CLK_DIV_SH)
-#define __PSS_LMEM_INIT_DONE           0x00001000
-#define __PSS_LMEM_RESET               0x00000200
-#define __PSS_LMEM_INIT_EN             0x00000100
-#define __PSS_LPU1_RESET               0x00000002
-#define __PSS_LPU0_RESET               0x00000001
-#define PSS_ERR_STATUS_REG             0x00018810
-#define __PSS_LPU1_TCM_READ_ERR                0x00200000
-#define __PSS_LPU0_TCM_READ_ERR                0x00100000
-#define __PSS_LMEM5_CORR_ERR           0x00080000
-#define __PSS_LMEM4_CORR_ERR           0x00040000
-#define __PSS_LMEM3_CORR_ERR           0x00020000
-#define __PSS_LMEM2_CORR_ERR           0x00010000
-#define __PSS_LMEM1_CORR_ERR           0x00008000
-#define __PSS_LMEM0_CORR_ERR           0x00004000
-#define __PSS_LMEM5_UNCORR_ERR         0x00002000
-#define __PSS_LMEM4_UNCORR_ERR         0x00001000
-#define __PSS_LMEM3_UNCORR_ERR         0x00000800
-#define __PSS_LMEM2_UNCORR_ERR         0x00000400
-#define __PSS_LMEM1_UNCORR_ERR         0x00000200
-#define __PSS_LMEM0_UNCORR_ERR         0x00000100
-#define __PSS_BAL_PERR                 0x00000080
-#define __PSS_DIP_IF_ERR               0x00000040
-#define __PSS_IOH_IF_ERR               0x00000020
-#define __PSS_TDS_IF_ERR               0x00000010
-#define __PSS_RDS_IF_ERR               0x00000008
-#define __PSS_SGM_IF_ERR               0x00000004
-#define __PSS_LPU1_RAM_ERR             0x00000002
-#define __PSS_LPU0_RAM_ERR             0x00000001
-#define ERR_SET_REG                    0x00018818
-#define __PSS_ERR_STATUS_SET           0x003fffff
-#define PMM_1T_RESET_REG_P0            0x0002381c
-#define __PMM_1T_RESET_P               0x00000001
-#define PMM_1T_RESET_REG_P1            0x00023c1c
-#define HQM_QSET0_RXQ_DRBL_P0          0x00038000
-#define __RXQ0_ADD_VECTORS_P           0x80000000
-#define __RXQ0_STOP_P                  0x40000000
-#define __RXQ0_PRD_PTR_P               0x0000ffff
-#define HQM_QSET1_RXQ_DRBL_P0          0x00038080
-#define __RXQ1_ADD_VECTORS_P           0x80000000
-#define __RXQ1_STOP_P                  0x40000000
-#define __RXQ1_PRD_PTR_P               0x0000ffff
-#define HQM_QSET0_RXQ_DRBL_P1          0x0003c000
-#define HQM_QSET1_RXQ_DRBL_P1          0x0003c080
-#define HQM_QSET0_TXQ_DRBL_P0          0x00038020
-#define __TXQ0_ADD_VECTORS_P           0x80000000
-#define __TXQ0_STOP_P                  0x40000000
-#define __TXQ0_PRD_PTR_P               0x0000ffff
-#define HQM_QSET1_TXQ_DRBL_P0          0x000380a0
-#define __TXQ1_ADD_VECTORS_P           0x80000000
-#define __TXQ1_STOP_P                  0x40000000
-#define __TXQ1_PRD_PTR_P               0x0000ffff
-#define HQM_QSET0_TXQ_DRBL_P1          0x0003c020
-#define HQM_QSET1_TXQ_DRBL_P1          0x0003c0a0
-#define HQM_QSET0_IB_DRBL_1_P0         0x00038040
-#define __IB1_0_ACK_P                  0x80000000
-#define __IB1_0_DISABLE_P              0x40000000
-#define __IB1_0_COALESCING_CFG_P_MK    0x00ff0000
-#define __IB1_0_COALESCING_CFG_P_SH    16
-#define __IB1_0_COALESCING_CFG_P(_v)   ((_v) << __IB1_0_COALESCING_CFG_P_SH)
-#define __IB1_0_NUM_OF_ACKED_EVENTS_P  0x0000ffff
-#define HQM_QSET1_IB_DRBL_1_P0         0x000380c0
-#define __IB1_1_ACK_P                  0x80000000
-#define __IB1_1_DISABLE_P              0x40000000
-#define __IB1_1_COALESCING_CFG_P_MK    0x00ff0000
-#define __IB1_1_COALESCING_CFG_P_SH    16
-#define __IB1_1_COALESCING_CFG_P(_v)   ((_v) << __IB1_1_COALESCING_CFG_P_SH)
-#define __IB1_1_NUM_OF_ACKED_EVENTS_P  0x0000ffff
-#define HQM_QSET0_IB_DRBL_1_P1         0x0003c040
-#define HQM_QSET1_IB_DRBL_1_P1         0x0003c0c0
-#define HQM_QSET0_IB_DRBL_2_P0         0x00038060
-#define __IB2_0_ACK_P                  0x80000000
-#define __IB2_0_DISABLE_P              0x40000000
-#define __IB2_0_COALESCING_CFG_P_MK    0x00ff0000
-#define __IB2_0_COALESCING_CFG_P_SH    16
-#define __IB2_0_COALESCING_CFG_P(_v)   ((_v) << __IB2_0_COALESCING_CFG_P_SH)
-#define __IB2_0_NUM_OF_ACKED_EVENTS_P  0x0000ffff
-#define HQM_QSET1_IB_DRBL_2_P0         0x000380e0
-#define __IB2_1_ACK_P                  0x80000000
-#define __IB2_1_DISABLE_P              0x40000000
-#define __IB2_1_COALESCING_CFG_P_MK    0x00ff0000
-#define __IB2_1_COALESCING_CFG_P_SH    16
-#define __IB2_1_COALESCING_CFG_P(_v)   ((_v) << __IB2_1_COALESCING_CFG_P_SH)
-#define __IB2_1_NUM_OF_ACKED_EVENTS_P  0x0000ffff
-#define HQM_QSET0_IB_DRBL_2_P1         0x0003c060
-#define HQM_QSET1_IB_DRBL_2_P1         0x0003c0e0
-
-/*
- * These definitions are either in error/missing in spec. Its auto-generated
- * from hard coded values in regparse.pl.
- */
-#define __EMPHPOST_AT_4G_MK_FIX                0x0000001c
-#define __EMPHPOST_AT_4G_SH_FIX                0x00000002
-#define __EMPHPRE_AT_4G_FIX            0x00000003
-#define __SFP_TXRATE_EN_FIX            0x00000100
-#define __SFP_RXRATE_EN_FIX            0x00000080
-
-/*
- * These register definitions are auto-generated from hard coded values
- * in regparse.pl.
- */
-
-/*
- * These register mapping definitions are auto-generated from mapping tables
- * in regparse.pl.
- */
-#define BFA_IOC0_HBEAT_REG             HOST_SEM0_INFO_REG
-#define BFA_IOC0_STATE_REG             HOST_SEM1_INFO_REG
-#define BFA_IOC1_HBEAT_REG             HOST_SEM2_INFO_REG
-#define BFA_IOC1_STATE_REG             HOST_SEM3_INFO_REG
-#define BFA_FW_USE_COUNT                HOST_SEM4_INFO_REG
-#define BFA_IOC_FAIL_SYNC              HOST_SEM5_INFO_REG
-
-#define CPE_DEPTH_Q(__n) \
-       (CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
-#define CPE_QCTRL_Q(__n) \
-       (CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
-#define CPE_PI_PTR_Q(__n) \
-       (CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
-#define CPE_CI_PTR_Q(__n) \
-       (CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
-#define RME_DEPTH_Q(__n) \
-       (RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
-#define RME_QCTRL_Q(__n) \
-       (RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
-#define RME_PI_PTR_Q(__n) \
-       (RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
-#define RME_CI_PTR_Q(__n) \
-       (RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
-#define HQM_QSET_RXQ_DRBL_P0(__n) \
-       (HQM_QSET0_RXQ_DRBL_P0 + (__n) * \
-               (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
-#define HQM_QSET_TXQ_DRBL_P0(__n) \
-       (HQM_QSET0_TXQ_DRBL_P0 + (__n) * \
-               (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
-#define HQM_QSET_IB_DRBL_1_P0(__n) \
-       (HQM_QSET0_IB_DRBL_1_P0 + (__n) * \
-               (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
-#define HQM_QSET_IB_DRBL_2_P0(__n) \
-       (HQM_QSET0_IB_DRBL_2_P0 + (__n) * \
-               (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
-#define HQM_QSET_RXQ_DRBL_P1(__n) \
-       (HQM_QSET0_RXQ_DRBL_P1 + (__n) * \
-               (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
-#define HQM_QSET_TXQ_DRBL_P1(__n) \
-       (HQM_QSET0_TXQ_DRBL_P1 + (__n) * \
-               (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
-#define HQM_QSET_IB_DRBL_1_P1(__n) \
-       (HQM_QSET0_IB_DRBL_1_P1 + (__n) * \
-               (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
-#define HQM_QSET_IB_DRBL_2_P1(__n) \
-       (HQM_QSET0_IB_DRBL_2_P1 + (__n) * \
-               (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
-
-#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
-#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
-#define CPE_Q_MASK(__q) ((__q) & 0x3)
-#define RME_Q_MASK(__q) ((__q) & 0x3)
-
-/*
- * PCI MSI-X vector defines
- */
-enum {
-       BFA_MSIX_CPE_Q0 = 0,
-       BFA_MSIX_CPE_Q1 = 1,
-       BFA_MSIX_CPE_Q2 = 2,
-       BFA_MSIX_CPE_Q3 = 3,
-       BFA_MSIX_RME_Q0 = 4,
-       BFA_MSIX_RME_Q1 = 5,
-       BFA_MSIX_RME_Q2 = 6,
-       BFA_MSIX_RME_Q3 = 7,
-       BFA_MSIX_LPU_ERR = 8,
-       BFA_MSIX_CT_MAX = 9,
-};
-
-/*
- * And corresponding host interrupt status bit field defines
- */
-#define __HFN_INT_CPE_Q0               0x00000001U
-#define __HFN_INT_CPE_Q1               0x00000002U
-#define __HFN_INT_CPE_Q2               0x00000004U
-#define __HFN_INT_CPE_Q3               0x00000008U
-#define __HFN_INT_CPE_Q4               0x00000010U
-#define __HFN_INT_CPE_Q5               0x00000020U
-#define __HFN_INT_CPE_Q6               0x00000040U
-#define __HFN_INT_CPE_Q7               0x00000080U
-#define __HFN_INT_RME_Q0               0x00000100U
-#define __HFN_INT_RME_Q1               0x00000200U
-#define __HFN_INT_RME_Q2               0x00000400U
-#define __HFN_INT_RME_Q3               0x00000800U
-#define __HFN_INT_RME_Q4               0x00001000U
-#define __HFN_INT_RME_Q5               0x00002000U
-#define __HFN_INT_RME_Q6               0x00004000U
-#define __HFN_INT_RME_Q7               0x00008000U
-#define __HFN_INT_ERR_EMC              0x00010000U
-#define __HFN_INT_ERR_LPU0             0x00020000U
-#define __HFN_INT_ERR_LPU1             0x00040000U
-#define __HFN_INT_ERR_PSS              0x00080000U
-#define __HFN_INT_MBOX_LPU0            0x00100000U
-#define __HFN_INT_MBOX_LPU1            0x00200000U
-#define __HFN_INT_MBOX1_LPU0           0x00400000U
-#define __HFN_INT_MBOX1_LPU1           0x00800000U
-#define __HFN_INT_LL_HALT              0x01000000U
-#define __HFN_INT_CPE_MASK             0x000000ffU
-#define __HFN_INT_RME_MASK             0x0000ff00U
-
-/*
- * catapult memory map.
- */
-#define LL_PGN_HQM0            0x0096
-#define LL_PGN_HQM1            0x0097
-#define PSS_SMEM_PAGE_START    0x8000
-#define PSS_SMEM_PGNUM(_pg0, _ma)      ((_pg0) + ((_ma) >> 15))
-#define PSS_SMEM_PGOFF(_ma)    ((_ma) & 0x7fff)
-
-/*
- * End of catapult memory map
- */
-
-#endif /* __BFI_CTREG_H__ */
diff --git a/drivers/net/bna/bfi_ll.h b/drivers/net/bna/bfi_ll.h
deleted file mode 100644 (file)
index bee4d05..0000000
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#ifndef __BFI_LL_H__
-#define __BFI_LL_H__
-
-#include "bfi.h"
-
-#pragma pack(1)
-
-/**
- * @brief
- *     "enums" for all LL mailbox messages other than IOC
- */
-enum {
-       BFI_LL_H2I_MAC_UCAST_SET_REQ = 1,
-       BFI_LL_H2I_MAC_UCAST_ADD_REQ = 2,
-       BFI_LL_H2I_MAC_UCAST_DEL_REQ = 3,
-
-       BFI_LL_H2I_MAC_MCAST_ADD_REQ = 4,
-       BFI_LL_H2I_MAC_MCAST_DEL_REQ = 5,
-       BFI_LL_H2I_MAC_MCAST_FILTER_REQ = 6,
-       BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ = 7,
-
-       BFI_LL_H2I_PORT_ADMIN_REQ = 8,
-       BFI_LL_H2I_STATS_GET_REQ = 9,
-       BFI_LL_H2I_STATS_CLEAR_REQ = 10,
-
-       BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ = 11,
-       BFI_LL_H2I_RXF_DEFAULT_SET_REQ = 12,
-
-       BFI_LL_H2I_TXQ_STOP_REQ = 13,
-       BFI_LL_H2I_RXQ_STOP_REQ = 14,
-
-       BFI_LL_H2I_DIAG_LOOPBACK_REQ = 15,
-
-       BFI_LL_H2I_SET_PAUSE_REQ = 16,
-       BFI_LL_H2I_MTU_INFO_REQ = 17,
-
-       BFI_LL_H2I_RX_REQ = 18,
-} ;
-
-enum {
-       BFI_LL_I2H_MAC_UCAST_SET_RSP = BFA_I2HM(1),
-       BFI_LL_I2H_MAC_UCAST_ADD_RSP = BFA_I2HM(2),
-       BFI_LL_I2H_MAC_UCAST_DEL_RSP = BFA_I2HM(3),
-
-       BFI_LL_I2H_MAC_MCAST_ADD_RSP = BFA_I2HM(4),
-       BFI_LL_I2H_MAC_MCAST_DEL_RSP = BFA_I2HM(5),
-       BFI_LL_I2H_MAC_MCAST_FILTER_RSP = BFA_I2HM(6),
-       BFI_LL_I2H_MAC_MCAST_DEL_ALL_RSP = BFA_I2HM(7),
-
-       BFI_LL_I2H_PORT_ADMIN_RSP = BFA_I2HM(8),
-       BFI_LL_I2H_STATS_GET_RSP = BFA_I2HM(9),
-       BFI_LL_I2H_STATS_CLEAR_RSP = BFA_I2HM(10),
-
-       BFI_LL_I2H_RXF_PROMISCUOUS_SET_RSP = BFA_I2HM(11),
-       BFI_LL_I2H_RXF_DEFAULT_SET_RSP = BFA_I2HM(12),
-
-       BFI_LL_I2H_TXQ_STOP_RSP = BFA_I2HM(13),
-       BFI_LL_I2H_RXQ_STOP_RSP = BFA_I2HM(14),
-
-       BFI_LL_I2H_DIAG_LOOPBACK_RSP = BFA_I2HM(15),
-
-       BFI_LL_I2H_SET_PAUSE_RSP = BFA_I2HM(16),
-
-       BFI_LL_I2H_MTU_INFO_RSP = BFA_I2HM(17),
-       BFI_LL_I2H_RX_RSP = BFA_I2HM(18),
-
-       BFI_LL_I2H_LINK_DOWN_AEN = BFA_I2HM(19),
-       BFI_LL_I2H_LINK_UP_AEN = BFA_I2HM(20),
-
-       BFI_LL_I2H_PORT_ENABLE_AEN = BFA_I2HM(21),
-       BFI_LL_I2H_PORT_DISABLE_AEN = BFA_I2HM(22),
-} ;
-
-/**
- * @brief bfi_ll_mac_addr_req is used by:
- *        BFI_LL_H2I_MAC_UCAST_SET_REQ
- *        BFI_LL_H2I_MAC_UCAST_ADD_REQ
- *        BFI_LL_H2I_MAC_UCAST_DEL_REQ
- *        BFI_LL_H2I_MAC_MCAST_ADD_REQ
- *        BFI_LL_H2I_MAC_MCAST_DEL_REQ
- */
-struct bfi_ll_mac_addr_req {
-       struct bfi_mhdr mh;             /*!< common msg header */
-       u8              rxf_id;
-       u8              rsvd1[3];
-       mac_t           mac_addr;
-       u8              rsvd2[2];
-};
-
-/**
- * @brief bfi_ll_mcast_filter_req is used by:
- *       BFI_LL_H2I_MAC_MCAST_FILTER_REQ
- */
-struct bfi_ll_mcast_filter_req {
-       struct bfi_mhdr mh;             /*!< common msg header */
-       u8              rxf_id;
-       u8              enable;
-       u8              rsvd[2];
-};
-
-/**
- * @brief bfi_ll_mcast_del_all is used by:
- *       BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ
- */
-struct bfi_ll_mcast_del_all_req {
-       struct bfi_mhdr mh;             /*!< common msg header */
-       u8                 rxf_id;
-       u8                 rsvd[3];
-};
-
-/**
- * @brief bfi_ll_q_stop_req is used by:
- *     BFI_LL_H2I_TXQ_STOP_REQ
- *     BFI_LL_H2I_RXQ_STOP_REQ
- */
-struct bfi_ll_q_stop_req {
-       struct bfi_mhdr mh;             /*!< common msg header */
-       u32     q_id_mask[2];   /* !< bit-mask for queue ids */
-};
-
-/**
- * @brief bfi_ll_stats_req is used by:
- *    BFI_LL_I2H_STATS_GET_REQ
- *    BFI_LL_I2H_STATS_CLEAR_REQ
- */
-struct bfi_ll_stats_req {
-       struct bfi_mhdr mh;     /*!< common msg header */
-       u16 stats_mask; /* !< bit-mask for non-function statistics */
-       u8      rsvd[2];
-       u32 rxf_id_mask[2];     /* !< bit-mask for RxF Statistics */
-       u32 txf_id_mask[2];     /* !< bit-mask for TxF Statistics */
-       union bfi_addr_u  host_buffer;  /* !< where statistics are returned */
-};
-
-/**
- * @brief defines for "stats_mask" above.
- */
-#define BFI_LL_STATS_MAC       (1 << 0)        /* !< MAC Statistics */
-#define BFI_LL_STATS_BPC       (1 << 1)        /* !< Pause Stats from BPC */
-#define BFI_LL_STATS_RAD       (1 << 2)        /* !< Rx Admission Statistics */
-#define BFI_LL_STATS_RX_FC     (1 << 3)        /* !< Rx FC Stats from RxA */
-#define BFI_LL_STATS_TX_FC     (1 << 4)        /* !< Tx FC Stats from TxA */
-
-#define BFI_LL_STATS_ALL       0x1f
-
-/**
- * @brief bfi_ll_port_admin_req
- */
-struct bfi_ll_port_admin_req {
-       struct bfi_mhdr mh;             /*!< common msg header */
-       u8               up;
-       u8               rsvd[3];
-};
-
-/**
- * @brief bfi_ll_rxf_req is used by:
- *      BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ
- *      BFI_LL_H2I_RXF_DEFAULT_SET_REQ
- */
-struct bfi_ll_rxf_req {
-       struct bfi_mhdr mh;             /*!< common msg header */
-       u8              rxf_id;
-       u8              enable;
-       u8              rsvd[2];
-};
-
-/**
- * @brief bfi_ll_rxf_multi_req is used by:
- *     BFI_LL_H2I_RX_REQ
- */
-struct bfi_ll_rxf_multi_req {
-       struct bfi_mhdr mh;             /*!< common msg header */
-       u32     rxf_id_mask[2];
-       u8              enable;
-       u8              rsvd[3];
-};
-
-/**
- * @brief enum for Loopback opmodes
- */
-enum {
-       BFI_LL_DIAG_LB_OPMODE_EXT = 0,
-       BFI_LL_DIAG_LB_OPMODE_CBL = 1,
-};
-
-/**
- * @brief bfi_ll_set_pause_req is used by:
- *     BFI_LL_H2I_SET_PAUSE_REQ
- */
-struct bfi_ll_set_pause_req {
-       struct bfi_mhdr mh;
-       u8              tx_pause; /* 1 = enable, 0 =  disable */
-       u8              rx_pause; /* 1 = enable, 0 =  disable */
-       u8              rsvd[2];
-};
-
-/**
- * @brief bfi_ll_mtu_info_req is used by:
- *     BFI_LL_H2I_MTU_INFO_REQ
- */
-struct bfi_ll_mtu_info_req {
-       struct bfi_mhdr mh;
-       u16     mtu;
-       u8              rsvd[2];
-};
-
-/**
- * @brief
- *       Response header format used by all responses
- *       For both responses and asynchronous notifications
- */
-struct bfi_ll_rsp {
-       struct bfi_mhdr mh;             /*!< common msg header */
-       u8              error;
-       u8              rsvd[3];
-};
-
-/**
- * @brief bfi_ll_cee_aen is used by:
- *     BFI_LL_I2H_LINK_DOWN_AEN
- *     BFI_LL_I2H_LINK_UP_AEN
- */
-struct bfi_ll_aen {
-       struct bfi_mhdr mh;             /*!< common msg header */
-       u32     reason;
-       u8              cee_linkup;
-       u8              prio_map;    /*!< LL priority bit-map */
-       u8              rsvd[2];
-};
-
-/**
- * @brief
- *     The following error codes can be returned
- *     by the mbox commands
- */
-enum {
-       BFI_LL_CMD_OK           = 0,
-       BFI_LL_CMD_FAIL         = 1,
-       BFI_LL_CMD_DUP_ENTRY    = 2,    /* !< Duplicate entry in CAM */
-       BFI_LL_CMD_CAM_FULL     = 3,    /* !< CAM is full */
-       BFI_LL_CMD_NOT_OWNER    = 4,    /* !< Not permitted, b'cos not owner */
-       BFI_LL_CMD_NOT_EXEC     = 5,    /* !< Was not sent to f/w at all */
-       BFI_LL_CMD_WAITING      = 6,    /* !< Waiting for completion (VMware) */
-       BFI_LL_CMD_PORT_DISABLED        = 7,    /* !< port in disabled state */
-} ;
-
-/* Statistics */
-#define BFI_LL_TXF_ID_MAX      64
-#define BFI_LL_RXF_ID_MAX      64
-
-/* TxF Frame Statistics */
-struct bfi_ll_stats_txf {
-       u64 ucast_octets;
-       u64 ucast;
-       u64 ucast_vlan;
-
-       u64 mcast_octets;
-       u64 mcast;
-       u64 mcast_vlan;
-
-       u64 bcast_octets;
-       u64 bcast;
-       u64 bcast_vlan;
-
-       u64 errors;
-       u64 filter_vlan;      /* frames filtered due to VLAN */
-       u64 filter_mac_sa;    /* frames filtered due to SA check */
-};
-
-/* RxF Frame Statistics */
-struct bfi_ll_stats_rxf {
-       u64 ucast_octets;
-       u64 ucast;
-       u64 ucast_vlan;
-
-       u64 mcast_octets;
-       u64 mcast;
-       u64 mcast_vlan;
-
-       u64 bcast_octets;
-       u64 bcast;
-       u64 bcast_vlan;
-       u64 frame_drops;
-};
-
-/* FC Tx Frame Statistics */
-struct bfi_ll_stats_fc_tx {
-       u64 txf_ucast_octets;
-       u64 txf_ucast;
-       u64 txf_ucast_vlan;
-
-       u64 txf_mcast_octets;
-       u64 txf_mcast;
-       u64 txf_mcast_vlan;
-
-       u64 txf_bcast_octets;
-       u64 txf_bcast;
-       u64 txf_bcast_vlan;
-
-       u64 txf_parity_errors;
-       u64 txf_timeout;
-       u64 txf_fid_parity_errors;
-};
-
-/* FC Rx Frame Statistics */
-struct bfi_ll_stats_fc_rx {
-       u64 rxf_ucast_octets;
-       u64 rxf_ucast;
-       u64 rxf_ucast_vlan;
-
-       u64 rxf_mcast_octets;
-       u64 rxf_mcast;
-       u64 rxf_mcast_vlan;
-
-       u64 rxf_bcast_octets;
-       u64 rxf_bcast;
-       u64 rxf_bcast_vlan;
-};
-
-/* RAD Frame Statistics */
-struct bfi_ll_stats_rad {
-       u64 rx_frames;
-       u64 rx_octets;
-       u64 rx_vlan_frames;
-
-       u64 rx_ucast;
-       u64 rx_ucast_octets;
-       u64 rx_ucast_vlan;
-
-       u64 rx_mcast;
-       u64 rx_mcast_octets;
-       u64 rx_mcast_vlan;
-
-       u64 rx_bcast;
-       u64 rx_bcast_octets;
-       u64 rx_bcast_vlan;
-
-       u64 rx_drops;
-};
-
-/* BPC Tx Registers */
-struct bfi_ll_stats_bpc {
-       /* transmit stats */
-       u64 tx_pause[8];
-       u64 tx_zero_pause[8];   /*!< Pause cancellation */
-       /*!<Pause initiation rather than retention */
-       u64 tx_first_pause[8];
-
-       /* receive stats */
-       u64 rx_pause[8];
-       u64 rx_zero_pause[8];   /*!< Pause cancellation */
-       /*!<Pause initiation rather than retention */
-       u64 rx_first_pause[8];
-};
-
-/* MAC Rx Statistics */
-struct bfi_ll_stats_mac {
-       u64 frame_64;           /* both rx and tx counter */
-       u64 frame_65_127;               /* both rx and tx counter */
-       u64 frame_128_255;              /* both rx and tx counter */
-       u64 frame_256_511;              /* both rx and tx counter */
-       u64 frame_512_1023;     /* both rx and tx counter */
-       u64 frame_1024_1518;    /* both rx and tx counter */
-       u64 frame_1519_1522;    /* both rx and tx counter */
-
-       /* receive stats */
-       u64 rx_bytes;
-       u64 rx_packets;
-       u64 rx_fcs_error;
-       u64 rx_multicast;
-       u64 rx_broadcast;
-       u64 rx_control_frames;
-       u64 rx_pause;
-       u64 rx_unknown_opcode;
-       u64 rx_alignment_error;
-       u64 rx_frame_length_error;
-       u64 rx_code_error;
-       u64 rx_carrier_sense_error;
-       u64 rx_undersize;
-       u64 rx_oversize;
-       u64 rx_fragments;
-       u64 rx_jabber;
-       u64 rx_drop;
-
-       /* transmit stats */
-       u64 tx_bytes;
-       u64 tx_packets;
-       u64 tx_multicast;
-       u64 tx_broadcast;
-       u64 tx_pause;
-       u64 tx_deferral;
-       u64 tx_excessive_deferral;
-       u64 tx_single_collision;
-       u64 tx_muliple_collision;
-       u64 tx_late_collision;
-       u64 tx_excessive_collision;
-       u64 tx_total_collision;
-       u64 tx_pause_honored;
-       u64 tx_drop;
-       u64 tx_jabber;
-       u64 tx_fcs_error;
-       u64 tx_control_frame;
-       u64 tx_oversize;
-       u64 tx_undersize;
-       u64 tx_fragments;
-};
-
-/* Complete statistics */
-struct bfi_ll_stats {
-       struct bfi_ll_stats_mac         mac_stats;
-       struct bfi_ll_stats_bpc         bpc_stats;
-       struct bfi_ll_stats_rad         rad_stats;
-       struct bfi_ll_stats_fc_rx       fc_rx_stats;
-       struct bfi_ll_stats_fc_tx       fc_tx_stats;
-       struct bfi_ll_stats_rxf rxf_stats[BFI_LL_RXF_ID_MAX];
-       struct bfi_ll_stats_txf txf_stats[BFI_LL_TXF_ID_MAX];
-};
-
-#pragma pack()
-
-#endif  /* __BFI_LL_H__ */
diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c
deleted file mode 100644 (file)
index cb2594c..0000000
+++ /dev/null
@@ -1,3076 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#include "bna.h"
-#include "bfa_cs.h"
-
-static void bna_device_cb_port_stopped(void *arg, enum bna_cb_status status);
-
-static void
-bna_port_cb_link_up(struct bna_port *port, struct bfi_ll_aen *aen,
-                       int status)
-{
-       int i;
-       u8 prio_map;
-
-       port->llport.link_status = BNA_LINK_UP;
-       if (aen->cee_linkup)
-               port->llport.link_status = BNA_CEE_UP;
-
-       /* Compute the priority */
-       prio_map = aen->prio_map;
-       if (prio_map) {
-               for (i = 0; i < 8; i++) {
-                       if ((prio_map >> i) & 0x1)
-                               break;
-               }
-               port->priority = i;
-       } else
-               port->priority = 0;
-
-       /* Dispatch events */
-       bna_tx_mod_cee_link_status(&port->bna->tx_mod, aen->cee_linkup);
-       bna_tx_mod_prio_changed(&port->bna->tx_mod, port->priority);
-       port->link_cbfn(port->bna->bnad, port->llport.link_status);
-}
-
-static void
-bna_port_cb_link_down(struct bna_port *port, int status)
-{
-       port->llport.link_status = BNA_LINK_DOWN;
-
-       /* Dispatch events */
-       bna_tx_mod_cee_link_status(&port->bna->tx_mod, BNA_LINK_DOWN);
-       port->link_cbfn(port->bna->bnad, BNA_LINK_DOWN);
-}
-
-static inline int
-llport_can_be_up(struct bna_llport *llport)
-{
-       int ready = 0;
-       if (llport->type == BNA_PORT_T_REGULAR)
-               ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) &&
-                        (llport->flags & BNA_LLPORT_F_RX_STARTED) &&
-                        (llport->flags & BNA_LLPORT_F_PORT_ENABLED));
-       else
-               ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) &&
-                        (llport->flags & BNA_LLPORT_F_RX_STARTED) &&
-                        !(llport->flags & BNA_LLPORT_F_PORT_ENABLED));
-       return ready;
-}
-
-#define llport_is_up llport_can_be_up
-
-enum bna_llport_event {
-       LLPORT_E_START                  = 1,
-       LLPORT_E_STOP                   = 2,
-       LLPORT_E_FAIL                   = 3,
-       LLPORT_E_UP                     = 4,
-       LLPORT_E_DOWN                   = 5,
-       LLPORT_E_FWRESP_UP_OK           = 6,
-       LLPORT_E_FWRESP_UP_FAIL         = 7,
-       LLPORT_E_FWRESP_DOWN            = 8
-};
-
-static void
-bna_llport_cb_port_enabled(struct bna_llport *llport)
-{
-       llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
-
-       if (llport_can_be_up(llport))
-               bfa_fsm_send_event(llport, LLPORT_E_UP);
-}
-
-static void
-bna_llport_cb_port_disabled(struct bna_llport *llport)
-{
-       int llport_up = llport_is_up(llport);
-
-       llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
-
-       if (llport_up)
-               bfa_fsm_send_event(llport, LLPORT_E_DOWN);
-}
-
-/**
- * MBOX
- */
-static int
-bna_is_aen(u8 msg_id)
-{
-       switch (msg_id) {
-       case BFI_LL_I2H_LINK_DOWN_AEN:
-       case BFI_LL_I2H_LINK_UP_AEN:
-       case BFI_LL_I2H_PORT_ENABLE_AEN:
-       case BFI_LL_I2H_PORT_DISABLE_AEN:
-               return 1;
-
-       default:
-               return 0;
-       }
-}
-
-static void
-bna_mbox_aen_callback(struct bna *bna, struct bfi_mbmsg *msg)
-{
-       struct bfi_ll_aen *aen = (struct bfi_ll_aen *)(msg);
-
-       switch (aen->mh.msg_id) {
-       case BFI_LL_I2H_LINK_UP_AEN:
-               bna_port_cb_link_up(&bna->port, aen, aen->reason);
-               break;
-       case BFI_LL_I2H_LINK_DOWN_AEN:
-               bna_port_cb_link_down(&bna->port, aen->reason);
-               break;
-       case BFI_LL_I2H_PORT_ENABLE_AEN:
-               bna_llport_cb_port_enabled(&bna->port.llport);
-               break;
-       case BFI_LL_I2H_PORT_DISABLE_AEN:
-               bna_llport_cb_port_disabled(&bna->port.llport);
-               break;
-       default:
-               break;
-       }
-}
-
-static void
-bna_ll_isr(void *llarg, struct bfi_mbmsg *msg)
-{
-       struct bna *bna = (struct bna *)(llarg);
-       struct bfi_ll_rsp *mb_rsp = (struct bfi_ll_rsp *)(msg);
-       struct bfi_mhdr *cmd_h, *rsp_h;
-       struct bna_mbox_qe *mb_qe = NULL;
-       int to_post = 0;
-       u8 aen = 0;
-       char message[BNA_MESSAGE_SIZE];
-
-       aen = bna_is_aen(mb_rsp->mh.msg_id);
-
-       if (!aen) {
-               mb_qe = bfa_q_first(&bna->mbox_mod.posted_q);
-               cmd_h = (struct bfi_mhdr *)(&mb_qe->cmd.msg[0]);
-               rsp_h = (struct bfi_mhdr *)(&mb_rsp->mh);
-
-               if ((BFA_I2HM(cmd_h->msg_id) == rsp_h->msg_id) &&
-                   (cmd_h->mtag.i2htok == rsp_h->mtag.i2htok)) {
-                       /* Remove the request from posted_q, update state  */
-                       list_del(&mb_qe->qe);
-                       bna->mbox_mod.msg_pending--;
-                       if (list_empty(&bna->mbox_mod.posted_q))
-                               bna->mbox_mod.state = BNA_MBOX_FREE;
-                       else
-                               to_post = 1;
-
-                       /* Dispatch the cbfn */
-                       if (mb_qe->cbfn)
-                               mb_qe->cbfn(mb_qe->cbarg, mb_rsp->error);
-
-                       /* Post the next entry, if needed */
-                       if (to_post) {
-                               mb_qe = bfa_q_first(&bna->mbox_mod.posted_q);
-                               bfa_nw_ioc_mbox_queue(&bna->device.ioc,
-                                                       &mb_qe->cmd);
-                       }
-               } else {
-                       snprintf(message, BNA_MESSAGE_SIZE,
-                                      "No matching rsp for [%d:%d:%d]\n",
-                                      mb_rsp->mh.msg_class, mb_rsp->mh.msg_id,
-                                      mb_rsp->mh.mtag.i2htok);
-               pr_info("%s", message);
-               }
-
-       } else
-               bna_mbox_aen_callback(bna, msg);
-}
-
-static void
-bna_err_handler(struct bna *bna, u32 intr_status)
-{
-       u32 init_halt;
-
-       if (intr_status & __HALT_STATUS_BITS) {
-               init_halt = readl(bna->device.ioc.ioc_regs.ll_halt);
-               init_halt &= ~__FW_INIT_HALT_P;
-               writel(init_halt, bna->device.ioc.ioc_regs.ll_halt);
-       }
-
-       bfa_nw_ioc_error_isr(&bna->device.ioc);
-}
-
-void
-bna_mbox_handler(struct bna *bna, u32 intr_status)
-{
-       if (BNA_IS_ERR_INTR(intr_status)) {
-               bna_err_handler(bna, intr_status);
-               return;
-       }
-       if (BNA_IS_MBOX_INTR(intr_status))
-               bfa_nw_ioc_mbox_isr(&bna->device.ioc);
-}
-
-void
-bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe)
-{
-       struct bfi_mhdr *mh;
-
-       mh = (struct bfi_mhdr *)(&mbox_qe->cmd.msg[0]);
-
-       mh->mtag.i2htok = htons(bna->mbox_mod.msg_ctr);
-       bna->mbox_mod.msg_ctr++;
-       bna->mbox_mod.msg_pending++;
-       if (bna->mbox_mod.state == BNA_MBOX_FREE) {
-               list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q);
-               bfa_nw_ioc_mbox_queue(&bna->device.ioc, &mbox_qe->cmd);
-               bna->mbox_mod.state = BNA_MBOX_POSTED;
-       } else {
-               list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q);
-       }
-}
-
-static void
-bna_mbox_flush_q(struct bna *bna, struct list_head *q)
-{
-       struct bna_mbox_qe *mb_qe = NULL;
-       struct list_head                        *mb_q;
-       void                    (*cbfn)(void *arg, int status);
-       void                    *cbarg;
-
-       mb_q = &bna->mbox_mod.posted_q;
-
-       while (!list_empty(mb_q)) {
-               bfa_q_deq(mb_q, &mb_qe);
-               cbfn = mb_qe->cbfn;
-               cbarg = mb_qe->cbarg;
-               bfa_q_qe_init(mb_qe);
-               bna->mbox_mod.msg_pending--;
-
-               if (cbfn)
-                       cbfn(cbarg, BNA_CB_NOT_EXEC);
-       }
-
-       bna->mbox_mod.state = BNA_MBOX_FREE;
-}
-
-static void
-bna_mbox_mod_start(struct bna_mbox_mod *mbox_mod)
-{
-}
-
-static void
-bna_mbox_mod_stop(struct bna_mbox_mod *mbox_mod)
-{
-       bna_mbox_flush_q(mbox_mod->bna, &mbox_mod->posted_q);
-}
-
-static void
-bna_mbox_mod_init(struct bna_mbox_mod *mbox_mod, struct bna *bna)
-{
-       bfa_nw_ioc_mbox_regisr(&bna->device.ioc, BFI_MC_LL, bna_ll_isr, bna);
-       mbox_mod->state = BNA_MBOX_FREE;
-       mbox_mod->msg_ctr = mbox_mod->msg_pending = 0;
-       INIT_LIST_HEAD(&mbox_mod->posted_q);
-       mbox_mod->bna = bna;
-}
-
-static void
-bna_mbox_mod_uninit(struct bna_mbox_mod *mbox_mod)
-{
-       mbox_mod->bna = NULL;
-}
-
-/**
- * LLPORT
- */
-#define call_llport_stop_cbfn(llport, status)\
-do {\
-       if ((llport)->stop_cbfn)\
-               (llport)->stop_cbfn(&(llport)->bna->port, status);\
-       (llport)->stop_cbfn = NULL;\
-} while (0)
-
-static void bna_fw_llport_up(struct bna_llport *llport);
-static void bna_fw_cb_llport_up(void *arg, int status);
-static void bna_fw_llport_down(struct bna_llport *llport);
-static void bna_fw_cb_llport_down(void *arg, int status);
-static void bna_llport_start(struct bna_llport *llport);
-static void bna_llport_stop(struct bna_llport *llport);
-static void bna_llport_fail(struct bna_llport *llport);
-
-enum bna_llport_state {
-       BNA_LLPORT_STOPPED              = 1,
-       BNA_LLPORT_DOWN                 = 2,
-       BNA_LLPORT_UP_RESP_WAIT         = 3,
-       BNA_LLPORT_DOWN_RESP_WAIT       = 4,
-       BNA_LLPORT_UP                   = 5,
-       BNA_LLPORT_LAST_RESP_WAIT       = 6
-};
-
-bfa_fsm_state_decl(bna_llport, stopped, struct bna_llport,
-                       enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, down, struct bna_llport,
-                       enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, up_resp_wait, struct bna_llport,
-                       enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, down_resp_wait, struct bna_llport,
-                       enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, up, struct bna_llport,
-                       enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, last_resp_wait, struct bna_llport,
-                       enum bna_llport_event);
-
-static struct bfa_sm_table llport_sm_table[] = {
-       {BFA_SM(bna_llport_sm_stopped), BNA_LLPORT_STOPPED},
-       {BFA_SM(bna_llport_sm_down), BNA_LLPORT_DOWN},
-       {BFA_SM(bna_llport_sm_up_resp_wait), BNA_LLPORT_UP_RESP_WAIT},
-       {BFA_SM(bna_llport_sm_down_resp_wait), BNA_LLPORT_DOWN_RESP_WAIT},
-       {BFA_SM(bna_llport_sm_up), BNA_LLPORT_UP},
-       {BFA_SM(bna_llport_sm_last_resp_wait), BNA_LLPORT_LAST_RESP_WAIT}
-};
-
-static void
-bna_llport_sm_stopped_entry(struct bna_llport *llport)
-{
-       llport->bna->port.link_cbfn((llport)->bna->bnad, BNA_LINK_DOWN);
-       call_llport_stop_cbfn(llport, BNA_CB_SUCCESS);
-}
-
-static void
-bna_llport_sm_stopped(struct bna_llport *llport,
-                       enum bna_llport_event event)
-{
-       switch (event) {
-       case LLPORT_E_START:
-               bfa_fsm_set_state(llport, bna_llport_sm_down);
-               break;
-
-       case LLPORT_E_STOP:
-               call_llport_stop_cbfn(llport, BNA_CB_SUCCESS);
-               break;
-
-       case LLPORT_E_FAIL:
-               break;
-
-       case LLPORT_E_DOWN:
-               /* This event is received due to Rx objects failing */
-               /* No-op */
-               break;
-
-       case LLPORT_E_FWRESP_UP_OK:
-       case LLPORT_E_FWRESP_DOWN:
-               /**
-                * These events are received due to flushing of mbox when
-                * device fails
-                */
-               /* No-op */
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_llport_sm_down_entry(struct bna_llport *llport)
-{
-       bnad_cb_port_link_status((llport)->bna->bnad, BNA_LINK_DOWN);
-}
-
-static void
-bna_llport_sm_down(struct bna_llport *llport,
-                       enum bna_llport_event event)
-{
-       switch (event) {
-       case LLPORT_E_STOP:
-               bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-               break;
-
-       case LLPORT_E_FAIL:
-               bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-               break;
-
-       case LLPORT_E_UP:
-               bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
-               bna_fw_llport_up(llport);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_llport_sm_up_resp_wait_entry(struct bna_llport *llport)
-{
-       BUG_ON(!llport_can_be_up(llport));
-       /**
-        * NOTE: Do not call bna_fw_llport_up() here. That will over step
-        * mbox due to down_resp_wait -> up_resp_wait transition on event
-        * LLPORT_E_UP
-        */
-}
-
-static void
-bna_llport_sm_up_resp_wait(struct bna_llport *llport,
-                       enum bna_llport_event event)
-{
-       switch (event) {
-       case LLPORT_E_STOP:
-               bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
-               break;
-
-       case LLPORT_E_FAIL:
-               bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-               break;
-
-       case LLPORT_E_DOWN:
-               bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
-               break;
-
-       case LLPORT_E_FWRESP_UP_OK:
-               bfa_fsm_set_state(llport, bna_llport_sm_up);
-               break;
-
-       case LLPORT_E_FWRESP_UP_FAIL:
-               bfa_fsm_set_state(llport, bna_llport_sm_down);
-               break;
-
-       case LLPORT_E_FWRESP_DOWN:
-               /* down_resp_wait -> up_resp_wait transition on LLPORT_E_UP */
-               bna_fw_llport_up(llport);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_llport_sm_down_resp_wait_entry(struct bna_llport *llport)
-{
-       /**
-        * NOTE: Do not call bna_fw_llport_down() here. That will over step
-        * mbox due to up_resp_wait -> down_resp_wait transition on event
-        * LLPORT_E_DOWN
-        */
-}
-
-static void
-bna_llport_sm_down_resp_wait(struct bna_llport *llport,
-                       enum bna_llport_event event)
-{
-       switch (event) {
-       case LLPORT_E_STOP:
-               bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
-               break;
-
-       case LLPORT_E_FAIL:
-               bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-               break;
-
-       case LLPORT_E_UP:
-               bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
-               break;
-
-       case LLPORT_E_FWRESP_UP_OK:
-               /* up_resp_wait->down_resp_wait transition on LLPORT_E_DOWN */
-               bna_fw_llport_down(llport);
-               break;
-
-       case LLPORT_E_FWRESP_UP_FAIL:
-       case LLPORT_E_FWRESP_DOWN:
-               bfa_fsm_set_state(llport, bna_llport_sm_down);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_llport_sm_up_entry(struct bna_llport *llport)
-{
-}
-
-static void
-bna_llport_sm_up(struct bna_llport *llport,
-                       enum bna_llport_event event)
-{
-       switch (event) {
-       case LLPORT_E_STOP:
-               bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
-               bna_fw_llport_down(llport);
-               break;
-
-       case LLPORT_E_FAIL:
-               bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-               break;
-
-       case LLPORT_E_DOWN:
-               bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
-               bna_fw_llport_down(llport);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_llport_sm_last_resp_wait_entry(struct bna_llport *llport)
-{
-}
-
-static void
-bna_llport_sm_last_resp_wait(struct bna_llport *llport,
-                       enum bna_llport_event event)
-{
-       switch (event) {
-       case LLPORT_E_FAIL:
-               bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-               break;
-
-       case LLPORT_E_DOWN:
-               /**
-                * This event is received due to Rx objects stopping in
-                * parallel to llport
-                */
-               /* No-op */
-               break;
-
-       case LLPORT_E_FWRESP_UP_OK:
-               /* up_resp_wait->last_resp_wait transition on LLPORT_T_STOP */
-               bna_fw_llport_down(llport);
-               break;
-
-       case LLPORT_E_FWRESP_UP_FAIL:
-       case LLPORT_E_FWRESP_DOWN:
-               bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_fw_llport_admin_up(struct bna_llport *llport)
-{
-       struct bfi_ll_port_admin_req ll_req;
-
-       memset(&ll_req, 0, sizeof(ll_req));
-       ll_req.mh.msg_class = BFI_MC_LL;
-       ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ;
-       ll_req.mh.mtag.h2i.lpu_id = 0;
-
-       ll_req.up = BNA_STATUS_T_ENABLED;
-
-       bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req),
-                       bna_fw_cb_llport_up, llport);
-
-       bna_mbox_send(llport->bna, &llport->mbox_qe);
-}
-
-static void
-bna_fw_llport_up(struct bna_llport *llport)
-{
-       if (llport->type == BNA_PORT_T_REGULAR)
-               bna_fw_llport_admin_up(llport);
-}
-
-static void
-bna_fw_cb_llport_up(void *arg, int status)
-{
-       struct bna_llport *llport = (struct bna_llport *)arg;
-
-       bfa_q_qe_init(&llport->mbox_qe.qe);
-       if (status == BFI_LL_CMD_FAIL) {
-               if (llport->type == BNA_PORT_T_REGULAR)
-                       llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
-               else
-                       llport->flags &= ~BNA_LLPORT_F_ADMIN_UP;
-               bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_FAIL);
-       } else
-               bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_OK);
-}
-
-static void
-bna_fw_llport_admin_down(struct bna_llport *llport)
-{
-       struct bfi_ll_port_admin_req ll_req;
-
-       memset(&ll_req, 0, sizeof(ll_req));
-       ll_req.mh.msg_class = BFI_MC_LL;
-       ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ;
-       ll_req.mh.mtag.h2i.lpu_id = 0;
-
-       ll_req.up = BNA_STATUS_T_DISABLED;
-
-       bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req),
-                       bna_fw_cb_llport_down, llport);
-
-       bna_mbox_send(llport->bna, &llport->mbox_qe);
-}
-
-static void
-bna_fw_llport_down(struct bna_llport *llport)
-{
-       if (llport->type == BNA_PORT_T_REGULAR)
-               bna_fw_llport_admin_down(llport);
-}
-
-static void
-bna_fw_cb_llport_down(void *arg, int status)
-{
-       struct bna_llport *llport = (struct bna_llport *)arg;
-
-       bfa_q_qe_init(&llport->mbox_qe.qe);
-       bfa_fsm_send_event(llport, LLPORT_E_FWRESP_DOWN);
-}
-
-static void
-bna_port_cb_llport_stopped(struct bna_port *port,
-                               enum bna_cb_status status)
-{
-       bfa_wc_down(&port->chld_stop_wc);
-}
-
-static void
-bna_llport_init(struct bna_llport *llport, struct bna *bna)
-{
-       llport->flags |= BNA_LLPORT_F_ADMIN_UP;
-       llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
-       llport->type = BNA_PORT_T_REGULAR;
-       llport->bna = bna;
-
-       llport->link_status = BNA_LINK_DOWN;
-
-       llport->rx_started_count = 0;
-
-       llport->stop_cbfn = NULL;
-
-       bfa_q_qe_init(&llport->mbox_qe.qe);
-
-       bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-}
-
-static void
-bna_llport_uninit(struct bna_llport *llport)
-{
-       llport->flags &= ~BNA_LLPORT_F_ADMIN_UP;
-       llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
-
-       llport->bna = NULL;
-}
-
-static void
-bna_llport_start(struct bna_llport *llport)
-{
-       bfa_fsm_send_event(llport, LLPORT_E_START);
-}
-
-static void
-bna_llport_stop(struct bna_llport *llport)
-{
-       llport->stop_cbfn = bna_port_cb_llport_stopped;
-
-       bfa_fsm_send_event(llport, LLPORT_E_STOP);
-}
-
-static void
-bna_llport_fail(struct bna_llport *llport)
-{
-       /* Reset the physical port status to enabled */
-       llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
-       bfa_fsm_send_event(llport, LLPORT_E_FAIL);
-}
-
-static int
-bna_llport_state_get(struct bna_llport *llport)
-{
-       return bfa_sm_to_state(llport_sm_table, llport->fsm);
-}
-
-void
-bna_llport_rx_started(struct bna_llport *llport)
-{
-       llport->rx_started_count++;
-
-       if (llport->rx_started_count == 1) {
-
-               llport->flags |= BNA_LLPORT_F_RX_STARTED;
-
-               if (llport_can_be_up(llport))
-                       bfa_fsm_send_event(llport, LLPORT_E_UP);
-       }
-}
-
-void
-bna_llport_rx_stopped(struct bna_llport *llport)
-{
-       int llport_up = llport_is_up(llport);
-
-       llport->rx_started_count--;
-
-       if (llport->rx_started_count == 0) {
-
-               llport->flags &= ~BNA_LLPORT_F_RX_STARTED;
-
-               if (llport_up)
-                       bfa_fsm_send_event(llport, LLPORT_E_DOWN);
-       }
-}
-
-/**
- * PORT
- */
-#define bna_port_chld_start(port)\
-do {\
-       enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
-                                       BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\
-       enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
-                                       BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
-       bna_llport_start(&(port)->llport);\
-       bna_tx_mod_start(&(port)->bna->tx_mod, tx_type);\
-       bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\
-} while (0)
-
-#define bna_port_chld_stop(port)\
-do {\
-       enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
-                                       BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\
-       enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
-                                       BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
-       bfa_wc_up(&(port)->chld_stop_wc);\
-       bfa_wc_up(&(port)->chld_stop_wc);\
-       bfa_wc_up(&(port)->chld_stop_wc);\
-       bna_llport_stop(&(port)->llport);\
-       bna_tx_mod_stop(&(port)->bna->tx_mod, tx_type);\
-       bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\
-} while (0)
-
-#define bna_port_chld_fail(port)\
-do {\
-       bna_llport_fail(&(port)->llport);\
-       bna_tx_mod_fail(&(port)->bna->tx_mod);\
-       bna_rx_mod_fail(&(port)->bna->rx_mod);\
-} while (0)
-
-#define bna_port_rx_start(port)\
-do {\
-       enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
-                                       BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
-       bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\
-} while (0)
-
-#define bna_port_rx_stop(port)\
-do {\
-       enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
-                                       BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
-       bfa_wc_up(&(port)->chld_stop_wc);\
-       bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\
-} while (0)
-
-#define call_port_stop_cbfn(port, status)\
-do {\
-       if ((port)->stop_cbfn)\
-               (port)->stop_cbfn((port)->stop_cbarg, status);\
-       (port)->stop_cbfn = NULL;\
-       (port)->stop_cbarg = NULL;\
-} while (0)
-
-#define call_port_pause_cbfn(port, status)\
-do {\
-       if ((port)->pause_cbfn)\
-               (port)->pause_cbfn((port)->bna->bnad, status);\
-       (port)->pause_cbfn = NULL;\
-} while (0)
-
-#define call_port_mtu_cbfn(port, status)\
-do {\
-       if ((port)->mtu_cbfn)\
-               (port)->mtu_cbfn((port)->bna->bnad, status);\
-       (port)->mtu_cbfn = NULL;\
-} while (0)
-
-static void bna_fw_pause_set(struct bna_port *port);
-static void bna_fw_cb_pause_set(void *arg, int status);
-static void bna_fw_mtu_set(struct bna_port *port);
-static void bna_fw_cb_mtu_set(void *arg, int status);
-
-enum bna_port_event {
-       PORT_E_START                    = 1,
-       PORT_E_STOP                     = 2,
-       PORT_E_FAIL                     = 3,
-       PORT_E_PAUSE_CFG                = 4,
-       PORT_E_MTU_CFG                  = 5,
-       PORT_E_CHLD_STOPPED             = 6,
-       PORT_E_FWRESP_PAUSE             = 7,
-       PORT_E_FWRESP_MTU               = 8
-};
-
-enum bna_port_state {
-       BNA_PORT_STOPPED                = 1,
-       BNA_PORT_MTU_INIT_WAIT          = 2,
-       BNA_PORT_PAUSE_INIT_WAIT        = 3,
-       BNA_PORT_LAST_RESP_WAIT         = 4,
-       BNA_PORT_STARTED                = 5,
-       BNA_PORT_PAUSE_CFG_WAIT         = 6,
-       BNA_PORT_RX_STOP_WAIT           = 7,
-       BNA_PORT_MTU_CFG_WAIT           = 8,
-       BNA_PORT_CHLD_STOP_WAIT         = 9
-};
-
-bfa_fsm_state_decl(bna_port, stopped, struct bna_port,
-                       enum bna_port_event);
-bfa_fsm_state_decl(bna_port, mtu_init_wait, struct bna_port,
-                       enum bna_port_event);
-bfa_fsm_state_decl(bna_port, pause_init_wait, struct bna_port,
-                       enum bna_port_event);
-bfa_fsm_state_decl(bna_port, last_resp_wait, struct bna_port,
-                       enum bna_port_event);
-bfa_fsm_state_decl(bna_port, started, struct bna_port,
-                       enum bna_port_event);
-bfa_fsm_state_decl(bna_port, pause_cfg_wait, struct bna_port,
-                       enum bna_port_event);
-bfa_fsm_state_decl(bna_port, rx_stop_wait, struct bna_port,
-                       enum bna_port_event);
-bfa_fsm_state_decl(bna_port, mtu_cfg_wait, struct bna_port,
-                       enum bna_port_event);
-bfa_fsm_state_decl(bna_port, chld_stop_wait, struct bna_port,
-                       enum bna_port_event);
-
-static struct bfa_sm_table port_sm_table[] = {
-       {BFA_SM(bna_port_sm_stopped), BNA_PORT_STOPPED},
-       {BFA_SM(bna_port_sm_mtu_init_wait), BNA_PORT_MTU_INIT_WAIT},
-       {BFA_SM(bna_port_sm_pause_init_wait), BNA_PORT_PAUSE_INIT_WAIT},
-       {BFA_SM(bna_port_sm_last_resp_wait), BNA_PORT_LAST_RESP_WAIT},
-       {BFA_SM(bna_port_sm_started), BNA_PORT_STARTED},
-       {BFA_SM(bna_port_sm_pause_cfg_wait), BNA_PORT_PAUSE_CFG_WAIT},
-       {BFA_SM(bna_port_sm_rx_stop_wait), BNA_PORT_RX_STOP_WAIT},
-       {BFA_SM(bna_port_sm_mtu_cfg_wait), BNA_PORT_MTU_CFG_WAIT},
-       {BFA_SM(bna_port_sm_chld_stop_wait), BNA_PORT_CHLD_STOP_WAIT}
-};
-
-static void
-bna_port_sm_stopped_entry(struct bna_port *port)
-{
-       call_port_pause_cbfn(port, BNA_CB_SUCCESS);
-       call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
-       call_port_stop_cbfn(port, BNA_CB_SUCCESS);
-}
-
-static void
-bna_port_sm_stopped(struct bna_port *port, enum bna_port_event event)
-{
-       switch (event) {
-       case PORT_E_START:
-               bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait);
-               break;
-
-       case PORT_E_STOP:
-               call_port_stop_cbfn(port, BNA_CB_SUCCESS);
-               break;
-
-       case PORT_E_FAIL:
-               /* No-op */
-               break;
-
-       case PORT_E_PAUSE_CFG:
-               call_port_pause_cbfn(port, BNA_CB_SUCCESS);
-               break;
-
-       case PORT_E_MTU_CFG:
-               call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
-               break;
-
-       case PORT_E_CHLD_STOPPED:
-               /**
-                * This event is received due to LLPort, Tx and Rx objects
-                * failing
-                */
-               /* No-op */
-               break;
-
-       case PORT_E_FWRESP_PAUSE:
-       case PORT_E_FWRESP_MTU:
-               /**
-                * These events are received due to flushing of mbox when
-                * device fails
-                */
-               /* No-op */
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_port_sm_mtu_init_wait_entry(struct bna_port *port)
-{
-       bna_fw_mtu_set(port);
-}
-
-static void
-bna_port_sm_mtu_init_wait(struct bna_port *port, enum bna_port_event event)
-{
-       switch (event) {
-       case PORT_E_STOP:
-               bfa_fsm_set_state(port, bna_port_sm_last_resp_wait);
-               break;
-
-       case PORT_E_FAIL:
-               bfa_fsm_set_state(port, bna_port_sm_stopped);
-               break;
-
-       case PORT_E_PAUSE_CFG:
-               /* No-op */
-               break;
-
-       case PORT_E_MTU_CFG:
-               port->flags |= BNA_PORT_F_MTU_CHANGED;
-               break;
-
-       case PORT_E_FWRESP_MTU:
-               if (port->flags & BNA_PORT_F_MTU_CHANGED) {
-                       port->flags &= ~BNA_PORT_F_MTU_CHANGED;
-                       bna_fw_mtu_set(port);
-               } else {
-                       bfa_fsm_set_state(port, bna_port_sm_pause_init_wait);
-               }
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_port_sm_pause_init_wait_entry(struct bna_port *port)
-{
-       bna_fw_pause_set(port);
-}
-
-static void
-bna_port_sm_pause_init_wait(struct bna_port *port,
-                               enum bna_port_event event)
-{
-       switch (event) {
-       case PORT_E_STOP:
-               bfa_fsm_set_state(port, bna_port_sm_last_resp_wait);
-               break;
-
-       case PORT_E_FAIL:
-               bfa_fsm_set_state(port, bna_port_sm_stopped);
-               break;
-
-       case PORT_E_PAUSE_CFG:
-               port->flags |= BNA_PORT_F_PAUSE_CHANGED;
-               break;
-
-       case PORT_E_MTU_CFG:
-               port->flags |= BNA_PORT_F_MTU_CHANGED;
-               break;
-
-       case PORT_E_FWRESP_PAUSE:
-               if (port->flags & BNA_PORT_F_PAUSE_CHANGED) {
-                       port->flags &= ~BNA_PORT_F_PAUSE_CHANGED;
-                       bna_fw_pause_set(port);
-               } else if (port->flags & BNA_PORT_F_MTU_CHANGED) {
-                       port->flags &= ~BNA_PORT_F_MTU_CHANGED;
-                       bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait);
-               } else {
-                       bfa_fsm_set_state(port, bna_port_sm_started);
-                       bna_port_chld_start(port);
-               }
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_port_sm_last_resp_wait_entry(struct bna_port *port)
-{
-}
-
-static void
-bna_port_sm_last_resp_wait(struct bna_port *port,
-                               enum bna_port_event event)
-{
-       switch (event) {
-       case PORT_E_FAIL:
-       case PORT_E_FWRESP_PAUSE:
-       case PORT_E_FWRESP_MTU:
-               bfa_fsm_set_state(port, bna_port_sm_stopped);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_port_sm_started_entry(struct bna_port *port)
-{
-       /**
-        * NOTE: Do not call bna_port_chld_start() here, since it will be
-        * inadvertently called during pause_cfg_wait->started transition
-        * as well
-        */
-       call_port_pause_cbfn(port, BNA_CB_SUCCESS);
-       call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
-}
-
-static void
-bna_port_sm_started(struct bna_port *port,
-                       enum bna_port_event event)
-{
-       switch (event) {
-       case PORT_E_STOP:
-               bfa_fsm_set_state(port, bna_port_sm_chld_stop_wait);
-               break;
-
-       case PORT_E_FAIL:
-               bfa_fsm_set_state(port, bna_port_sm_stopped);
-               bna_port_chld_fail(port);
-               break;
-
-       case PORT_E_PAUSE_CFG:
-               bfa_fsm_set_state(port, bna_port_sm_pause_cfg_wait);
-               break;
-
-       case PORT_E_MTU_CFG:
-               bfa_fsm_set_state(port, bna_port_sm_rx_stop_wait);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_port_sm_pause_cfg_wait_entry(struct bna_port *port)
-{
-       bna_fw_pause_set(port);
-}
-
-static void
-bna_port_sm_pause_cfg_wait(struct bna_port *port,
-                               enum bna_port_event event)
-{
-       switch (event) {
-       case PORT_E_FAIL:
-               bfa_fsm_set_state(port, bna_port_sm_stopped);
-               bna_port_chld_fail(port);
-               break;
-
-       case PORT_E_FWRESP_PAUSE:
-               bfa_fsm_set_state(port, bna_port_sm_started);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_port_sm_rx_stop_wait_entry(struct bna_port *port)
-{
-       bna_port_rx_stop(port);
-}
-
-static void
-bna_port_sm_rx_stop_wait(struct bna_port *port,
-                               enum bna_port_event event)
-{
-       switch (event) {
-       case PORT_E_FAIL:
-               bfa_fsm_set_state(port, bna_port_sm_stopped);
-               bna_port_chld_fail(port);
-               break;
-
-       case PORT_E_CHLD_STOPPED:
-               bfa_fsm_set_state(port, bna_port_sm_mtu_cfg_wait);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_port_sm_mtu_cfg_wait_entry(struct bna_port *port)
-{
-       bna_fw_mtu_set(port);
-}
-
-static void
-bna_port_sm_mtu_cfg_wait(struct bna_port *port, enum bna_port_event event)
-{
-       switch (event) {
-       case PORT_E_FAIL:
-               bfa_fsm_set_state(port, bna_port_sm_stopped);
-               bna_port_chld_fail(port);
-               break;
-
-       case PORT_E_FWRESP_MTU:
-               bfa_fsm_set_state(port, bna_port_sm_started);
-               bna_port_rx_start(port);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_port_sm_chld_stop_wait_entry(struct bna_port *port)
-{
-       bna_port_chld_stop(port);
-}
-
-static void
-bna_port_sm_chld_stop_wait(struct bna_port *port,
-                               enum bna_port_event event)
-{
-       switch (event) {
-       case PORT_E_FAIL:
-               bfa_fsm_set_state(port, bna_port_sm_stopped);
-               bna_port_chld_fail(port);
-               break;
-
-       case PORT_E_CHLD_STOPPED:
-               bfa_fsm_set_state(port, bna_port_sm_stopped);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_fw_pause_set(struct bna_port *port)
-{
-       struct bfi_ll_set_pause_req ll_req;
-
-       memset(&ll_req, 0, sizeof(ll_req));
-       ll_req.mh.msg_class = BFI_MC_LL;
-       ll_req.mh.msg_id = BFI_LL_H2I_SET_PAUSE_REQ;
-       ll_req.mh.mtag.h2i.lpu_id = 0;
-
-       ll_req.tx_pause = port->pause_config.tx_pause;
-       ll_req.rx_pause = port->pause_config.rx_pause;
-
-       bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req),
-                       bna_fw_cb_pause_set, port);
-
-       bna_mbox_send(port->bna, &port->mbox_qe);
-}
-
-static void
-bna_fw_cb_pause_set(void *arg, int status)
-{
-       struct bna_port *port = (struct bna_port *)arg;
-
-       bfa_q_qe_init(&port->mbox_qe.qe);
-       bfa_fsm_send_event(port, PORT_E_FWRESP_PAUSE);
-}
-
-void
-bna_fw_mtu_set(struct bna_port *port)
-{
-       struct bfi_ll_mtu_info_req ll_req;
-
-       bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_MTU_INFO_REQ, 0);
-       ll_req.mtu = htons((u16)port->mtu);
-
-       bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req),
-                               bna_fw_cb_mtu_set, port);
-       bna_mbox_send(port->bna, &port->mbox_qe);
-}
-
-void
-bna_fw_cb_mtu_set(void *arg, int status)
-{
-       struct bna_port *port = (struct bna_port *)arg;
-
-       bfa_q_qe_init(&port->mbox_qe.qe);
-       bfa_fsm_send_event(port, PORT_E_FWRESP_MTU);
-}
-
-static void
-bna_port_cb_chld_stopped(void *arg)
-{
-       struct bna_port *port = (struct bna_port *)arg;
-
-       bfa_fsm_send_event(port, PORT_E_CHLD_STOPPED);
-}
-
-static void
-bna_port_init(struct bna_port *port, struct bna *bna)
-{
-       port->bna = bna;
-       port->flags = 0;
-       port->mtu = 0;
-       port->type = BNA_PORT_T_REGULAR;
-
-       port->link_cbfn = bnad_cb_port_link_status;
-
-       port->chld_stop_wc.wc_resume = bna_port_cb_chld_stopped;
-       port->chld_stop_wc.wc_cbarg = port;
-       port->chld_stop_wc.wc_count = 0;
-
-       port->stop_cbfn = NULL;
-       port->stop_cbarg = NULL;
-
-       port->pause_cbfn = NULL;
-
-       port->mtu_cbfn = NULL;
-
-       bfa_q_qe_init(&port->mbox_qe.qe);
-
-       bfa_fsm_set_state(port, bna_port_sm_stopped);
-
-       bna_llport_init(&port->llport, bna);
-}
-
-static void
-bna_port_uninit(struct bna_port *port)
-{
-       bna_llport_uninit(&port->llport);
-
-       port->flags = 0;
-
-       port->bna = NULL;
-}
-
-static int
-bna_port_state_get(struct bna_port *port)
-{
-       return bfa_sm_to_state(port_sm_table, port->fsm);
-}
-
-static void
-bna_port_start(struct bna_port *port)
-{
-       port->flags |= BNA_PORT_F_DEVICE_READY;
-       if (port->flags & BNA_PORT_F_ENABLED)
-               bfa_fsm_send_event(port, PORT_E_START);
-}
-
-static void
-bna_port_stop(struct bna_port *port)
-{
-       port->stop_cbfn = bna_device_cb_port_stopped;
-       port->stop_cbarg = &port->bna->device;
-
-       port->flags &= ~BNA_PORT_F_DEVICE_READY;
-       bfa_fsm_send_event(port, PORT_E_STOP);
-}
-
-static void
-bna_port_fail(struct bna_port *port)
-{
-       port->flags &= ~BNA_PORT_F_DEVICE_READY;
-       bfa_fsm_send_event(port, PORT_E_FAIL);
-}
-
-void
-bna_port_cb_tx_stopped(struct bna_port *port, enum bna_cb_status status)
-{
-       bfa_wc_down(&port->chld_stop_wc);
-}
-
-void
-bna_port_cb_rx_stopped(struct bna_port *port, enum bna_cb_status status)
-{
-       bfa_wc_down(&port->chld_stop_wc);
-}
-
-int
-bna_port_mtu_get(struct bna_port *port)
-{
-       return port->mtu;
-}
-
-void
-bna_port_enable(struct bna_port *port)
-{
-       if (port->fsm != (bfa_sm_t)bna_port_sm_stopped)
-               return;
-
-       port->flags |= BNA_PORT_F_ENABLED;
-
-       if (port->flags & BNA_PORT_F_DEVICE_READY)
-               bfa_fsm_send_event(port, PORT_E_START);
-}
-
-void
-bna_port_disable(struct bna_port *port, enum bna_cleanup_type type,
-                void (*cbfn)(void *, enum bna_cb_status))
-{
-       if (type == BNA_SOFT_CLEANUP) {
-               (*cbfn)(port->bna->bnad, BNA_CB_SUCCESS);
-               return;
-       }
-
-       port->stop_cbfn = cbfn;
-       port->stop_cbarg = port->bna->bnad;
-
-       port->flags &= ~BNA_PORT_F_ENABLED;
-
-       bfa_fsm_send_event(port, PORT_E_STOP);
-}
-
-void
-bna_port_pause_config(struct bna_port *port,
-                     struct bna_pause_config *pause_config,
-                     void (*cbfn)(struct bnad *, enum bna_cb_status))
-{
-       port->pause_config = *pause_config;
-
-       port->pause_cbfn = cbfn;
-
-       bfa_fsm_send_event(port, PORT_E_PAUSE_CFG);
-}
-
-void
-bna_port_mtu_set(struct bna_port *port, int mtu,
-                void (*cbfn)(struct bnad *, enum bna_cb_status))
-{
-       port->mtu = mtu;
-
-       port->mtu_cbfn = cbfn;
-
-       bfa_fsm_send_event(port, PORT_E_MTU_CFG);
-}
-
-void
-bna_port_mac_get(struct bna_port *port, mac_t *mac)
-{
-       *mac = bfa_nw_ioc_get_mac(&port->bna->device.ioc);
-}
-
-/**
- * DEVICE
- */
-#define enable_mbox_intr(_device)\
-do {\
-       u32 intr_status;\
-       bna_intr_status_get((_device)->bna, intr_status);\
-       bnad_cb_device_enable_mbox_intr((_device)->bna->bnad);\
-       bna_mbox_intr_enable((_device)->bna);\
-} while (0)
-
-#define disable_mbox_intr(_device)\
-do {\
-       bna_mbox_intr_disable((_device)->bna);\
-       bnad_cb_device_disable_mbox_intr((_device)->bna->bnad);\
-} while (0)
-
-static const struct bna_chip_regs_offset reg_offset[] =
-{{HOST_PAGE_NUM_FN0, HOSTFN0_INT_STATUS,
-       HOSTFN0_INT_MASK, HOST_MSIX_ERR_INDEX_FN0},
-{HOST_PAGE_NUM_FN1, HOSTFN1_INT_STATUS,
-       HOSTFN1_INT_MASK, HOST_MSIX_ERR_INDEX_FN1},
-{HOST_PAGE_NUM_FN2, HOSTFN2_INT_STATUS,
-       HOSTFN2_INT_MASK, HOST_MSIX_ERR_INDEX_FN2},
-{HOST_PAGE_NUM_FN3, HOSTFN3_INT_STATUS,
-       HOSTFN3_INT_MASK, HOST_MSIX_ERR_INDEX_FN3},
-};
-
-enum bna_device_event {
-       DEVICE_E_ENABLE                 = 1,
-       DEVICE_E_DISABLE                = 2,
-       DEVICE_E_IOC_READY              = 3,
-       DEVICE_E_IOC_FAILED             = 4,
-       DEVICE_E_IOC_DISABLED           = 5,
-       DEVICE_E_IOC_RESET              = 6,
-       DEVICE_E_PORT_STOPPED           = 7,
-};
-
-enum bna_device_state {
-       BNA_DEVICE_STOPPED              = 1,
-       BNA_DEVICE_IOC_READY_WAIT       = 2,
-       BNA_DEVICE_READY                = 3,
-       BNA_DEVICE_PORT_STOP_WAIT       = 4,
-       BNA_DEVICE_IOC_DISABLE_WAIT     = 5,
-       BNA_DEVICE_FAILED               = 6
-};
-
-bfa_fsm_state_decl(bna_device, stopped, struct bna_device,
-                       enum bna_device_event);
-bfa_fsm_state_decl(bna_device, ioc_ready_wait, struct bna_device,
-                       enum bna_device_event);
-bfa_fsm_state_decl(bna_device, ready, struct bna_device,
-                       enum bna_device_event);
-bfa_fsm_state_decl(bna_device, port_stop_wait, struct bna_device,
-                       enum bna_device_event);
-bfa_fsm_state_decl(bna_device, ioc_disable_wait, struct bna_device,
-                       enum bna_device_event);
-bfa_fsm_state_decl(bna_device, failed, struct bna_device,
-                       enum bna_device_event);
-
-static struct bfa_sm_table device_sm_table[] = {
-       {BFA_SM(bna_device_sm_stopped), BNA_DEVICE_STOPPED},
-       {BFA_SM(bna_device_sm_ioc_ready_wait), BNA_DEVICE_IOC_READY_WAIT},
-       {BFA_SM(bna_device_sm_ready), BNA_DEVICE_READY},
-       {BFA_SM(bna_device_sm_port_stop_wait), BNA_DEVICE_PORT_STOP_WAIT},
-       {BFA_SM(bna_device_sm_ioc_disable_wait), BNA_DEVICE_IOC_DISABLE_WAIT},
-       {BFA_SM(bna_device_sm_failed), BNA_DEVICE_FAILED},
-};
-
-static void
-bna_device_sm_stopped_entry(struct bna_device *device)
-{
-       if (device->stop_cbfn)
-               device->stop_cbfn(device->stop_cbarg, BNA_CB_SUCCESS);
-
-       device->stop_cbfn = NULL;
-       device->stop_cbarg = NULL;
-}
-
-static void
-bna_device_sm_stopped(struct bna_device *device,
-                       enum bna_device_event event)
-{
-       switch (event) {
-       case DEVICE_E_ENABLE:
-               if (device->intr_type == BNA_INTR_T_MSIX)
-                       bna_mbox_msix_idx_set(device);
-               bfa_nw_ioc_enable(&device->ioc);
-               bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait);
-               break;
-
-       case DEVICE_E_DISABLE:
-               bfa_fsm_set_state(device, bna_device_sm_stopped);
-               break;
-
-       case DEVICE_E_IOC_RESET:
-               enable_mbox_intr(device);
-               break;
-
-       case DEVICE_E_IOC_FAILED:
-               bfa_fsm_set_state(device, bna_device_sm_failed);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_device_sm_ioc_ready_wait_entry(struct bna_device *device)
-{
-       /**
-        * Do not call bfa_ioc_enable() here. It must be called in the
-        * previous state due to failed -> ioc_ready_wait transition.
-        */
-}
-
-static void
-bna_device_sm_ioc_ready_wait(struct bna_device *device,
-                               enum bna_device_event event)
-{
-       switch (event) {
-       case DEVICE_E_DISABLE:
-               if (device->ready_cbfn)
-                       device->ready_cbfn(device->ready_cbarg,
-                                               BNA_CB_INTERRUPT);
-               device->ready_cbfn = NULL;
-               device->ready_cbarg = NULL;
-               bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
-               break;
-
-       case DEVICE_E_IOC_READY:
-               bfa_fsm_set_state(device, bna_device_sm_ready);
-               break;
-
-       case DEVICE_E_IOC_FAILED:
-               bfa_fsm_set_state(device, bna_device_sm_failed);
-               break;
-
-       case DEVICE_E_IOC_RESET:
-               enable_mbox_intr(device);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_device_sm_ready_entry(struct bna_device *device)
-{
-       bna_mbox_mod_start(&device->bna->mbox_mod);
-       bna_port_start(&device->bna->port);
-
-       if (device->ready_cbfn)
-               device->ready_cbfn(device->ready_cbarg,
-                                       BNA_CB_SUCCESS);
-       device->ready_cbfn = NULL;
-       device->ready_cbarg = NULL;
-}
-
-static void
-bna_device_sm_ready(struct bna_device *device, enum bna_device_event event)
-{
-       switch (event) {
-       case DEVICE_E_DISABLE:
-               bfa_fsm_set_state(device, bna_device_sm_port_stop_wait);
-               break;
-
-       case DEVICE_E_IOC_FAILED:
-               bfa_fsm_set_state(device, bna_device_sm_failed);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_device_sm_port_stop_wait_entry(struct bna_device *device)
-{
-       bna_port_stop(&device->bna->port);
-}
-
-static void
-bna_device_sm_port_stop_wait(struct bna_device *device,
-                               enum bna_device_event event)
-{
-       switch (event) {
-       case DEVICE_E_PORT_STOPPED:
-               bna_mbox_mod_stop(&device->bna->mbox_mod);
-               bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
-               break;
-
-       case DEVICE_E_IOC_FAILED:
-               disable_mbox_intr(device);
-               bna_port_fail(&device->bna->port);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_device_sm_ioc_disable_wait_entry(struct bna_device *device)
-{
-       bfa_nw_ioc_disable(&device->ioc);
-}
-
-static void
-bna_device_sm_ioc_disable_wait(struct bna_device *device,
-                               enum bna_device_event event)
-{
-       switch (event) {
-       case DEVICE_E_IOC_DISABLED:
-               disable_mbox_intr(device);
-               bfa_fsm_set_state(device, bna_device_sm_stopped);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_device_sm_failed_entry(struct bna_device *device)
-{
-       disable_mbox_intr(device);
-       bna_port_fail(&device->bna->port);
-       bna_mbox_mod_stop(&device->bna->mbox_mod);
-
-       if (device->ready_cbfn)
-               device->ready_cbfn(device->ready_cbarg,
-                                       BNA_CB_FAIL);
-       device->ready_cbfn = NULL;
-       device->ready_cbarg = NULL;
-}
-
-static void
-bna_device_sm_failed(struct bna_device *device,
-                       enum bna_device_event event)
-{
-       switch (event) {
-       case DEVICE_E_DISABLE:
-               bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
-               break;
-
-       case DEVICE_E_IOC_RESET:
-               enable_mbox_intr(device);
-               bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-/* IOC callback functions */
-
-static void
-bna_device_cb_iocll_ready(void *dev, enum bfa_status error)
-{
-       struct bna_device *device = (struct bna_device *)dev;
-
-       if (error)
-               bfa_fsm_send_event(device, DEVICE_E_IOC_FAILED);
-       else
-               bfa_fsm_send_event(device, DEVICE_E_IOC_READY);
-}
-
-static void
-bna_device_cb_iocll_disabled(void *dev)
-{
-       struct bna_device *device = (struct bna_device *)dev;
-
-       bfa_fsm_send_event(device, DEVICE_E_IOC_DISABLED);
-}
-
-static void
-bna_device_cb_iocll_failed(void *dev)
-{
-       struct bna_device *device = (struct bna_device *)dev;
-
-       bfa_fsm_send_event(device, DEVICE_E_IOC_FAILED);
-}
-
-static void
-bna_device_cb_iocll_reset(void *dev)
-{
-       struct bna_device *device = (struct bna_device *)dev;
-
-       bfa_fsm_send_event(device, DEVICE_E_IOC_RESET);
-}
-
-static struct bfa_ioc_cbfn bfa_iocll_cbfn = {
-       bna_device_cb_iocll_ready,
-       bna_device_cb_iocll_disabled,
-       bna_device_cb_iocll_failed,
-       bna_device_cb_iocll_reset
-};
-
-/* device */
-static void
-bna_adv_device_init(struct bna_device *device, struct bna *bna,
-               struct bna_res_info *res_info)
-{
-       u8 *kva;
-       u64 dma;
-
-       device->bna = bna;
-
-       kva = res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mdl[0].kva;
-
-       /**
-        * Attach common modules (Diag, SFP, CEE, Port) and claim respective
-        * DMA memory.
-        */
-       BNA_GET_DMA_ADDR(
-               &res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].dma, dma);
-       kva = res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].kva;
-
-       bfa_nw_cee_attach(&bna->cee, &device->ioc, bna);
-       bfa_nw_cee_mem_claim(&bna->cee, kva, dma);
-       kva += bfa_nw_cee_meminfo();
-       dma += bfa_nw_cee_meminfo();
-
-}
-
-static void
-bna_device_init(struct bna_device *device, struct bna *bna,
-               struct bna_res_info *res_info)
-{
-       u64 dma;
-
-       device->bna = bna;
-
-       /**
-        * Attach IOC and claim:
-        *      1. DMA memory for IOC attributes
-        *      2. Kernel memory for FW trace
-        */
-       bfa_nw_ioc_attach(&device->ioc, device, &bfa_iocll_cbfn);
-       bfa_nw_ioc_pci_init(&device->ioc, &bna->pcidev, BFI_MC_LL);
-
-       BNA_GET_DMA_ADDR(
-               &res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].dma, dma);
-       bfa_nw_ioc_mem_claim(&device->ioc,
-               res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].kva,
-                         dma);
-
-       bna_adv_device_init(device, bna, res_info);
-       /*
-        * Initialize mbox_mod only after IOC, so that mbox handler
-        * registration goes through
-        */
-       device->intr_type =
-               res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.intr_type;
-       device->vector =
-               res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.idl[0].vector;
-       bna_mbox_mod_init(&bna->mbox_mod, bna);
-
-       device->ready_cbfn = device->stop_cbfn = NULL;
-       device->ready_cbarg = device->stop_cbarg = NULL;
-
-       bfa_fsm_set_state(device, bna_device_sm_stopped);
-}
-
-static void
-bna_device_uninit(struct bna_device *device)
-{
-       bna_mbox_mod_uninit(&device->bna->mbox_mod);
-
-       bfa_nw_ioc_detach(&device->ioc);
-
-       device->bna = NULL;
-}
-
-static void
-bna_device_cb_port_stopped(void *arg, enum bna_cb_status status)
-{
-       struct bna_device *device = (struct bna_device *)arg;
-
-       bfa_fsm_send_event(device, DEVICE_E_PORT_STOPPED);
-}
-
-static int
-bna_device_status_get(struct bna_device *device)
-{
-       return device->fsm == (bfa_fsm_t)bna_device_sm_ready;
-}
-
-void
-bna_device_enable(struct bna_device *device)
-{
-       if (device->fsm != (bfa_fsm_t)bna_device_sm_stopped) {
-               bnad_cb_device_enabled(device->bna->bnad, BNA_CB_BUSY);
-               return;
-       }
-
-       device->ready_cbfn = bnad_cb_device_enabled;
-       device->ready_cbarg = device->bna->bnad;
-
-       bfa_fsm_send_event(device, DEVICE_E_ENABLE);
-}
-
-void
-bna_device_disable(struct bna_device *device, enum bna_cleanup_type type)
-{
-       if (type == BNA_SOFT_CLEANUP) {
-               bnad_cb_device_disabled(device->bna->bnad, BNA_CB_SUCCESS);
-               return;
-       }
-
-       device->stop_cbfn = bnad_cb_device_disabled;
-       device->stop_cbarg = device->bna->bnad;
-
-       bfa_fsm_send_event(device, DEVICE_E_DISABLE);
-}
-
-static int
-bna_device_state_get(struct bna_device *device)
-{
-       return bfa_sm_to_state(device_sm_table, device->fsm);
-}
-
-const u32 bna_napi_dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX] = {
-       {12, 12},
-       {6, 10},
-       {5, 10},
-       {4, 8},
-       {3, 6},
-       {3, 6},
-       {2, 4},
-       {1, 2},
-};
-
-/* utils */
-
-static void
-bna_adv_res_req(struct bna_res_info *res_info)
-{
-       /* DMA memory for COMMON_MODULE */
-       res_info[BNA_RES_MEM_T_COM].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
-       res_info[BNA_RES_MEM_T_COM].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_COM].res_u.mem_info.len = ALIGN(
-                               bfa_nw_cee_meminfo(), PAGE_SIZE);
-
-       /* Virtual memory for retreiving fw_trc */
-       res_info[BNA_RES_MEM_T_FWTRC].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mem_type = BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.num = 0;
-       res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.len = 0;
-
-       /* DMA memory for retreiving stats */
-       res_info[BNA_RES_MEM_T_STATS].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
-       res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.len =
-                               ALIGN(BFI_HW_STATS_SIZE, PAGE_SIZE);
-
-       /* Virtual memory for soft stats */
-       res_info[BNA_RES_MEM_T_SWSTATS].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.mem_type = BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.len =
-                               sizeof(struct bna_sw_stats);
-}
-
-static void
-bna_sw_stats_get(struct bna *bna, struct bna_sw_stats *sw_stats)
-{
-       struct bna_tx *tx;
-       struct bna_txq *txq;
-       struct bna_rx *rx;
-       struct bna_rxp *rxp;
-       struct list_head *qe;
-       struct list_head *txq_qe;
-       struct list_head *rxp_qe;
-       struct list_head *mac_qe;
-       int i;
-
-       sw_stats->device_state = bna_device_state_get(&bna->device);
-       sw_stats->port_state = bna_port_state_get(&bna->port);
-       sw_stats->port_flags = bna->port.flags;
-       sw_stats->llport_state = bna_llport_state_get(&bna->port.llport);
-       sw_stats->priority = bna->port.priority;
-
-       i = 0;
-       list_for_each(qe, &bna->tx_mod.tx_active_q) {
-               tx = (struct bna_tx *)qe;
-               sw_stats->tx_stats[i].tx_state = bna_tx_state_get(tx);
-               sw_stats->tx_stats[i].tx_flags = tx->flags;
-
-               sw_stats->tx_stats[i].num_txqs = 0;
-               sw_stats->tx_stats[i].txq_bmap[0] = 0;
-               sw_stats->tx_stats[i].txq_bmap[1] = 0;
-               list_for_each(txq_qe, &tx->txq_q) {
-                       txq = (struct bna_txq *)txq_qe;
-                       if (txq->txq_id < 32)
-                               sw_stats->tx_stats[i].txq_bmap[0] |=
-                                               ((u32)1 << txq->txq_id);
-                       else
-                               sw_stats->tx_stats[i].txq_bmap[1] |=
-                                               ((u32)
-                                                1 << (txq->txq_id - 32));
-                       sw_stats->tx_stats[i].num_txqs++;
-               }
-
-               sw_stats->tx_stats[i].txf_id = tx->txf.txf_id;
-
-               i++;
-       }
-       sw_stats->num_active_tx = i;
-
-       i = 0;
-       list_for_each(qe, &bna->rx_mod.rx_active_q) {
-               rx = (struct bna_rx *)qe;
-               sw_stats->rx_stats[i].rx_state = bna_rx_state_get(rx);
-               sw_stats->rx_stats[i].rx_flags = rx->rx_flags;
-
-               sw_stats->rx_stats[i].num_rxps = 0;
-               sw_stats->rx_stats[i].num_rxqs = 0;
-               sw_stats->rx_stats[i].rxq_bmap[0] = 0;
-               sw_stats->rx_stats[i].rxq_bmap[1] = 0;
-               sw_stats->rx_stats[i].cq_bmap[0] = 0;
-               sw_stats->rx_stats[i].cq_bmap[1] = 0;
-               list_for_each(rxp_qe, &rx->rxp_q) {
-                       rxp = (struct bna_rxp *)rxp_qe;
-
-                       sw_stats->rx_stats[i].num_rxqs += 1;
-
-                       if (rxp->type == BNA_RXP_SINGLE) {
-                               if (rxp->rxq.single.only->rxq_id < 32) {
-                                       sw_stats->rx_stats[i].rxq_bmap[0] |=
-                                       ((u32)1 <<
-                                       rxp->rxq.single.only->rxq_id);
-                               } else {
-                                       sw_stats->rx_stats[i].rxq_bmap[1] |=
-                                       ((u32)1 <<
-                                       (rxp->rxq.single.only->rxq_id - 32));
-                               }
-                       } else {
-                               if (rxp->rxq.slr.large->rxq_id < 32) {
-                                       sw_stats->rx_stats[i].rxq_bmap[0] |=
-                                       ((u32)1 <<
-                                       rxp->rxq.slr.large->rxq_id);
-                               } else {
-                                       sw_stats->rx_stats[i].rxq_bmap[1] |=
-                                       ((u32)1 <<
-                                       (rxp->rxq.slr.large->rxq_id - 32));
-                               }
-
-                               if (rxp->rxq.slr.small->rxq_id < 32) {
-                                       sw_stats->rx_stats[i].rxq_bmap[0] |=
-                                       ((u32)1 <<
-                                       rxp->rxq.slr.small->rxq_id);
-                               } else {
-                                       sw_stats->rx_stats[i].rxq_bmap[1] |=
-                               ((u32)1 <<
-                                (rxp->rxq.slr.small->rxq_id - 32));
-                               }
-                               sw_stats->rx_stats[i].num_rxqs += 1;
-                       }
-
-                       if (rxp->cq.cq_id < 32)
-                               sw_stats->rx_stats[i].cq_bmap[0] |=
-                                       (1 << rxp->cq.cq_id);
-                       else
-                               sw_stats->rx_stats[i].cq_bmap[1] |=
-                                       (1 << (rxp->cq.cq_id - 32));
-
-                       sw_stats->rx_stats[i].num_rxps++;
-               }
-
-               sw_stats->rx_stats[i].rxf_id = rx->rxf.rxf_id;
-               sw_stats->rx_stats[i].rxf_state = bna_rxf_state_get(&rx->rxf);
-               sw_stats->rx_stats[i].rxf_oper_state = rx->rxf.rxf_oper_state;
-
-               sw_stats->rx_stats[i].num_active_ucast = 0;
-               if (rx->rxf.ucast_active_mac)
-                       sw_stats->rx_stats[i].num_active_ucast++;
-               list_for_each(mac_qe, &rx->rxf.ucast_active_q)
-                       sw_stats->rx_stats[i].num_active_ucast++;
-
-               sw_stats->rx_stats[i].num_active_mcast = 0;
-               list_for_each(mac_qe, &rx->rxf.mcast_active_q)
-                       sw_stats->rx_stats[i].num_active_mcast++;
-
-               sw_stats->rx_stats[i].rxmode_active = rx->rxf.rxmode_active;
-               sw_stats->rx_stats[i].vlan_filter_status =
-                                               rx->rxf.vlan_filter_status;
-               memcpy(sw_stats->rx_stats[i].vlan_filter_table,
-                               rx->rxf.vlan_filter_table,
-                               sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32));
-
-               sw_stats->rx_stats[i].rss_status = rx->rxf.rss_status;
-               sw_stats->rx_stats[i].hds_status = rx->rxf.hds_status;
-
-               i++;
-       }
-       sw_stats->num_active_rx = i;
-}
-
-static void
-bna_fw_cb_stats_get(void *arg, int status)
-{
-       struct bna *bna = (struct bna *)arg;
-       u64 *p_stats;
-       int i, count;
-       int rxf_count, txf_count;
-       u64 rxf_bmap, txf_bmap;
-
-       bfa_q_qe_init(&bna->mbox_qe.qe);
-
-       if (status == 0) {
-               p_stats = (u64 *)bna->stats.hw_stats;
-               count = sizeof(struct bfi_ll_stats) / sizeof(u64);
-               for (i = 0; i < count; i++)
-                       p_stats[i] = cpu_to_be64(p_stats[i]);
-
-               rxf_count = 0;
-               rxf_bmap = (u64)bna->stats.rxf_bmap[0] |
-                       ((u64)bna->stats.rxf_bmap[1] << 32);
-               for (i = 0; i < BFI_LL_RXF_ID_MAX; i++)
-                       if (rxf_bmap & ((u64)1 << i))
-                               rxf_count++;
-
-               txf_count = 0;
-               txf_bmap = (u64)bna->stats.txf_bmap[0] |
-                       ((u64)bna->stats.txf_bmap[1] << 32);
-               for (i = 0; i < BFI_LL_TXF_ID_MAX; i++)
-                       if (txf_bmap & ((u64)1 << i))
-                               txf_count++;
-
-               p_stats = (u64 *)&bna->stats.hw_stats->rxf_stats[0] +
-                               ((rxf_count * sizeof(struct bfi_ll_stats_rxf) +
-                               txf_count * sizeof(struct bfi_ll_stats_txf))/
-                               sizeof(u64));
-
-               /* Populate the TXF stats from the firmware DMAed copy */
-               for (i = (BFI_LL_TXF_ID_MAX - 1); i >= 0; i--)
-                       if (txf_bmap & ((u64)1 << i)) {
-                               p_stats -= sizeof(struct bfi_ll_stats_txf)/
-                                               sizeof(u64);
-                               memcpy(&bna->stats.hw_stats->txf_stats[i],
-                                       p_stats,
-                                       sizeof(struct bfi_ll_stats_txf));
-                       }
-
-               /* Populate the RXF stats from the firmware DMAed copy */
-               for (i = (BFI_LL_RXF_ID_MAX - 1); i >= 0; i--)
-                       if (rxf_bmap & ((u64)1 << i)) {
-                               p_stats -= sizeof(struct bfi_ll_stats_rxf)/
-                                               sizeof(u64);
-                               memcpy(&bna->stats.hw_stats->rxf_stats[i],
-                                       p_stats,
-                                       sizeof(struct bfi_ll_stats_rxf));
-                       }
-
-               bna_sw_stats_get(bna, bna->stats.sw_stats);
-               bnad_cb_stats_get(bna->bnad, BNA_CB_SUCCESS, &bna->stats);
-       } else
-               bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats);
-}
-
-static void
-bna_fw_stats_get(struct bna *bna)
-{
-       struct bfi_ll_stats_req ll_req;
-
-       bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_GET_REQ, 0);
-       ll_req.stats_mask = htons(BFI_LL_STATS_ALL);
-
-       ll_req.rxf_id_mask[0] = htonl(bna->rx_mod.rxf_bmap[0]);
-       ll_req.rxf_id_mask[1] = htonl(bna->rx_mod.rxf_bmap[1]);
-       ll_req.txf_id_mask[0] = htonl(bna->tx_mod.txf_bmap[0]);
-       ll_req.txf_id_mask[1] = htonl(bna->tx_mod.txf_bmap[1]);
-
-       ll_req.host_buffer.a32.addr_hi = bna->hw_stats_dma.msb;
-       ll_req.host_buffer.a32.addr_lo = bna->hw_stats_dma.lsb;
-
-       bna_mbox_qe_fill(&bna->mbox_qe, &ll_req, sizeof(ll_req),
-                               bna_fw_cb_stats_get, bna);
-       bna_mbox_send(bna, &bna->mbox_qe);
-
-       bna->stats.rxf_bmap[0] = bna->rx_mod.rxf_bmap[0];
-       bna->stats.rxf_bmap[1] = bna->rx_mod.rxf_bmap[1];
-       bna->stats.txf_bmap[0] = bna->tx_mod.txf_bmap[0];
-       bna->stats.txf_bmap[1] = bna->tx_mod.txf_bmap[1];
-}
-
-void
-bna_stats_get(struct bna *bna)
-{
-       if (bna_device_status_get(&bna->device))
-               bna_fw_stats_get(bna);
-       else
-               bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats);
-}
-
-/* IB */
-static void
-bna_ib_coalescing_timeo_set(struct bna_ib *ib, u8 coalescing_timeo)
-{
-       ib->ib_config.coalescing_timeo = coalescing_timeo;
-
-       if (ib->start_count)
-               ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK(
-                               (u32)ib->ib_config.coalescing_timeo, 0);
-}
-
-/* RxF */
-void
-bna_rxf_adv_init(struct bna_rxf *rxf,
-               struct bna_rx *rx,
-               struct bna_rx_config *q_config)
-{
-       switch (q_config->rxp_type) {
-       case BNA_RXP_SINGLE:
-               /* No-op */
-               break;
-       case BNA_RXP_SLR:
-               rxf->ctrl_flags |= BNA_RXF_CF_SM_LG_RXQ;
-               break;
-       case BNA_RXP_HDS:
-               rxf->hds_cfg.hdr_type = q_config->hds_config.hdr_type;
-               rxf->hds_cfg.header_size =
-                               q_config->hds_config.header_size;
-               rxf->forced_offset = 0;
-               break;
-       default:
-               break;
-       }
-
-       if (q_config->rss_status == BNA_STATUS_T_ENABLED) {
-               rxf->ctrl_flags |= BNA_RXF_CF_RSS_ENABLE;
-               rxf->rss_cfg.hash_type = q_config->rss_config.hash_type;
-               rxf->rss_cfg.hash_mask = q_config->rss_config.hash_mask;
-               memcpy(&rxf->rss_cfg.toeplitz_hash_key[0],
-                       &q_config->rss_config.toeplitz_hash_key[0],
-                       sizeof(rxf->rss_cfg.toeplitz_hash_key));
-       }
-}
-
-static void
-rxf_fltr_mbox_cmd(struct bna_rxf *rxf, u8 cmd, enum bna_status status)
-{
-       struct bfi_ll_rxf_req req;
-
-       bfi_h2i_set(req.mh, BFI_MC_LL, cmd, 0);
-
-       req.rxf_id = rxf->rxf_id;
-       req.enable = status;
-
-       bna_mbox_qe_fill(&rxf->mbox_qe, &req, sizeof(req),
-                       rxf_cb_cam_fltr_mbox_cmd, rxf);
-
-       bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-int
-rxf_process_packet_filter_ucast(struct bna_rxf *rxf)
-{
-       struct bna_mac *mac = NULL;
-       struct list_head *qe;
-
-       /* Add additional MAC entries */
-       if (!list_empty(&rxf->ucast_pending_add_q)) {
-               bfa_q_deq(&rxf->ucast_pending_add_q, &qe);
-               bfa_q_qe_init(qe);
-               mac = (struct bna_mac *)qe;
-               rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_ADD_REQ, mac);
-               list_add_tail(&mac->qe, &rxf->ucast_active_q);
-               return 1;
-       }
-
-       /* Delete MAC addresses previousely added */
-       if (!list_empty(&rxf->ucast_pending_del_q)) {
-               bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
-               bfa_q_qe_init(qe);
-               mac = (struct bna_mac *)qe;
-               rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
-               bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
-               return 1;
-       }
-
-       return 0;
-}
-
-int
-rxf_process_packet_filter_promisc(struct bna_rxf *rxf)
-{
-       struct bna *bna = rxf->rx->bna;
-
-       /* Enable/disable promiscuous mode */
-       if (is_promisc_enable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask)) {
-               /* move promisc configuration from pending -> active */
-               promisc_inactive(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               rxf->rxmode_active |= BNA_RXMODE_PROMISC;
-
-               /* Disable VLAN filter to allow all VLANs */
-               __rxf_vlan_filter_set(rxf, BNA_STATUS_T_DISABLED);
-               rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
-                               BNA_STATUS_T_ENABLED);
-               return 1;
-       } else if (is_promisc_disable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask)) {
-               /* move promisc configuration from pending -> active */
-               promisc_inactive(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
-               bna->rxf_promisc_id = BFI_MAX_RXF;
-
-               /* Revert VLAN filter */
-               __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
-               rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
-                               BNA_STATUS_T_DISABLED);
-               return 1;
-       }
-
-       return 0;
-}
-
-int
-rxf_process_packet_filter_allmulti(struct bna_rxf *rxf)
-{
-       /* Enable/disable allmulti mode */
-       if (is_allmulti_enable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask)) {
-               /* move allmulti configuration from pending -> active */
-               allmulti_inactive(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               rxf->rxmode_active |= BNA_RXMODE_ALLMULTI;
-
-               rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
-                               BNA_STATUS_T_ENABLED);
-               return 1;
-       } else if (is_allmulti_disable(rxf->rxmode_pending,
-                                       rxf->rxmode_pending_bitmask)) {
-               /* move allmulti configuration from pending -> active */
-               allmulti_inactive(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
-
-               rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
-                               BNA_STATUS_T_DISABLED);
-               return 1;
-       }
-
-       return 0;
-}
-
-int
-rxf_clear_packet_filter_ucast(struct bna_rxf *rxf)
-{
-       struct bna_mac *mac = NULL;
-       struct list_head *qe;
-
-       /* 1. delete pending ucast entries */
-       if (!list_empty(&rxf->ucast_pending_del_q)) {
-               bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
-               bfa_q_qe_init(qe);
-               mac = (struct bna_mac *)qe;
-               rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
-               bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
-               return 1;
-       }
-
-       /* 2. clear active ucast entries; move them to pending_add_q */
-       if (!list_empty(&rxf->ucast_active_q)) {
-               bfa_q_deq(&rxf->ucast_active_q, &qe);
-               bfa_q_qe_init(qe);
-               mac = (struct bna_mac *)qe;
-               rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
-               list_add_tail(&mac->qe, &rxf->ucast_pending_add_q);
-               return 1;
-       }
-
-       return 0;
-}
-
-int
-rxf_clear_packet_filter_promisc(struct bna_rxf *rxf)
-{
-       struct bna *bna = rxf->rx->bna;
-
-       /* 6. Execute pending promisc mode disable command */
-       if (is_promisc_disable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask)) {
-               /* move promisc configuration from pending -> active */
-               promisc_inactive(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
-               bna->rxf_promisc_id = BFI_MAX_RXF;
-
-               /* Revert VLAN filter */
-               __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
-               rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
-                               BNA_STATUS_T_DISABLED);
-               return 1;
-       }
-
-       /* 7. Clear active promisc mode; move it to pending enable */
-       if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
-               /* move promisc configuration from active -> pending */
-               promisc_enable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
-
-               /* Revert VLAN filter */
-               __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
-               rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
-                               BNA_STATUS_T_DISABLED);
-               return 1;
-       }
-
-       return 0;
-}
-
-int
-rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf)
-{
-       /* 10. Execute pending allmulti mode disable command */
-       if (is_allmulti_disable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask)) {
-               /* move allmulti configuration from pending -> active */
-               allmulti_inactive(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
-               rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
-                               BNA_STATUS_T_DISABLED);
-               return 1;
-       }
-
-       /* 11. Clear active allmulti mode; move it to pending enable */
-       if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
-               /* move allmulti configuration from active -> pending */
-               allmulti_enable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
-               rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
-                               BNA_STATUS_T_DISABLED);
-               return 1;
-       }
-
-       return 0;
-}
-
-void
-rxf_reset_packet_filter_ucast(struct bna_rxf *rxf)
-{
-       struct list_head *qe;
-       struct bna_mac *mac;
-
-       /* 1. Move active ucast entries to pending_add_q */
-       while (!list_empty(&rxf->ucast_active_q)) {
-               bfa_q_deq(&rxf->ucast_active_q, &qe);
-               bfa_q_qe_init(qe);
-               list_add_tail(qe, &rxf->ucast_pending_add_q);
-       }
-
-       /* 2. Throw away delete pending ucast entries */
-       while (!list_empty(&rxf->ucast_pending_del_q)) {
-               bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
-               bfa_q_qe_init(qe);
-               mac = (struct bna_mac *)qe;
-               bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
-       }
-}
-
-void
-rxf_reset_packet_filter_promisc(struct bna_rxf *rxf)
-{
-       struct bna *bna = rxf->rx->bna;
-
-       /* 6. Clear pending promisc mode disable */
-       if (is_promisc_disable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask)) {
-               promisc_inactive(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
-               bna->rxf_promisc_id = BFI_MAX_RXF;
-       }
-
-       /* 7. Move promisc mode config from active -> pending */
-       if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
-               promisc_enable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
-       }
-
-}
-
-void
-rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf)
-{
-       /* 10. Clear pending allmulti mode disable */
-       if (is_allmulti_disable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask)) {
-               allmulti_inactive(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
-       }
-
-       /* 11. Move allmulti mode config from active -> pending */
-       if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
-               allmulti_enable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
-       }
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- *  Returns:
- *     0 = no h/w change
- *     1 = need h/w change
- */
-static int
-rxf_promisc_enable(struct bna_rxf *rxf)
-{
-       struct bna *bna = rxf->rx->bna;
-       int ret = 0;
-
-       /* There can not be any pending disable command */
-
-       /* Do nothing if pending enable or already enabled */
-       if (is_promisc_enable(rxf->rxmode_pending,
-                       rxf->rxmode_pending_bitmask) ||
-                       (rxf->rxmode_active & BNA_RXMODE_PROMISC)) {
-               /* Schedule enable */
-       } else {
-               /* Promisc mode should not be active in the system */
-               promisc_enable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               bna->rxf_promisc_id = rxf->rxf_id;
-               ret = 1;
-       }
-
-       return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- *  Returns:
- *     0 = no h/w change
- *     1 = need h/w change
- */
-static int
-rxf_promisc_disable(struct bna_rxf *rxf)
-{
-       struct bna *bna = rxf->rx->bna;
-       int ret = 0;
-
-       /* There can not be any pending disable */
-
-       /* Turn off pending enable command , if any */
-       if (is_promisc_enable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask)) {
-               /* Promisc mode should not be active */
-               /* system promisc state should be pending */
-               promisc_inactive(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               /* Remove the promisc state from the system */
-               bna->rxf_promisc_id = BFI_MAX_RXF;
-
-               /* Schedule disable */
-       } else if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
-               /* Promisc mode should be active in the system */
-               promisc_disable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               ret = 1;
-
-       /* Do nothing if already disabled */
-       } else {
-       }
-
-       return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- *  Returns:
- *     0 = no h/w change
- *     1 = need h/w change
- */
-static int
-rxf_allmulti_enable(struct bna_rxf *rxf)
-{
-       int ret = 0;
-
-       /* There can not be any pending disable command */
-
-       /* Do nothing if pending enable or already enabled */
-       if (is_allmulti_enable(rxf->rxmode_pending,
-                       rxf->rxmode_pending_bitmask) ||
-                       (rxf->rxmode_active & BNA_RXMODE_ALLMULTI)) {
-               /* Schedule enable */
-       } else {
-               allmulti_enable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               ret = 1;
-       }
-
-       return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- *  Returns:
- *     0 = no h/w change
- *     1 = need h/w change
- */
-static int
-rxf_allmulti_disable(struct bna_rxf *rxf)
-{
-       int ret = 0;
-
-       /* There can not be any pending disable */
-
-       /* Turn off pending enable command , if any */
-       if (is_allmulti_enable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask)) {
-               /* Allmulti mode should not be active */
-               allmulti_inactive(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-
-       /* Schedule disable */
-       } else if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
-               allmulti_disable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-               ret = 1;
-       }
-
-       return ret;
-}
-
-/* RxF <- bnad */
-enum bna_cb_status
-bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode new_mode,
-               enum bna_rxmode bitmask,
-               void (*cbfn)(struct bnad *, struct bna_rx *,
-                            enum bna_cb_status))
-{
-       struct bna_rxf *rxf = &rx->rxf;
-       int need_hw_config = 0;
-
-       /* Process the commands */
-
-       if (is_promisc_enable(new_mode, bitmask)) {
-               /* If promisc mode is already enabled elsewhere in the system */
-               if ((rx->bna->rxf_promisc_id != BFI_MAX_RXF) &&
-                       (rx->bna->rxf_promisc_id != rxf->rxf_id))
-                       goto err_return;
-               if (rxf_promisc_enable(rxf))
-                       need_hw_config = 1;
-       } else if (is_promisc_disable(new_mode, bitmask)) {
-               if (rxf_promisc_disable(rxf))
-                       need_hw_config = 1;
-       }
-
-       if (is_allmulti_enable(new_mode, bitmask)) {
-               if (rxf_allmulti_enable(rxf))
-                       need_hw_config = 1;
-       } else if (is_allmulti_disable(new_mode, bitmask)) {
-               if (rxf_allmulti_disable(rxf))
-                       need_hw_config = 1;
-       }
-
-       /* Trigger h/w if needed */
-
-       if (need_hw_config) {
-               rxf->cam_fltr_cbfn = cbfn;
-               rxf->cam_fltr_cbarg = rx->bna->bnad;
-               bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-       } else if (cbfn)
-               (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
-
-       return BNA_CB_SUCCESS;
-
-err_return:
-       return BNA_CB_FAIL;
-}
-
-void
-/* RxF <- bnad */
-bna_rx_vlanfilter_enable(struct bna_rx *rx)
-{
-       struct bna_rxf *rxf = &rx->rxf;
-
-       if (rxf->vlan_filter_status == BNA_STATUS_T_DISABLED) {
-               rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
-               rxf->vlan_filter_status = BNA_STATUS_T_ENABLED;
-               bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-       }
-}
-
-/* Rx */
-
-/* Rx <- bnad */
-void
-bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo)
-{
-       struct bna_rxp *rxp;
-       struct list_head *qe;
-
-       list_for_each(qe, &rx->rxp_q) {
-               rxp = (struct bna_rxp *)qe;
-               rxp->cq.ccb->rx_coalescing_timeo = coalescing_timeo;
-               bna_ib_coalescing_timeo_set(rxp->cq.ib, coalescing_timeo);
-       }
-}
-
-/* Rx <- bnad */
-void
-bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX])
-{
-       int i, j;
-
-       for (i = 0; i < BNA_LOAD_T_MAX; i++)
-               for (j = 0; j < BNA_BIAS_T_MAX; j++)
-                       bna->rx_mod.dim_vector[i][j] = vector[i][j];
-}
-
-/* Rx <- bnad */
-void
-bna_rx_dim_update(struct bna_ccb *ccb)
-{
-       struct bna *bna = ccb->cq->rx->bna;
-       u32 load, bias;
-       u32 pkt_rt, small_rt, large_rt;
-       u8 coalescing_timeo;
-
-       if ((ccb->pkt_rate.small_pkt_cnt == 0) &&
-               (ccb->pkt_rate.large_pkt_cnt == 0))
-               return;
-
-       /* Arrive at preconfigured coalescing timeo value based on pkt rate */
-
-       small_rt = ccb->pkt_rate.small_pkt_cnt;
-       large_rt = ccb->pkt_rate.large_pkt_cnt;
-
-       pkt_rt = small_rt + large_rt;
-
-       if (pkt_rt < BNA_PKT_RATE_10K)
-               load = BNA_LOAD_T_LOW_4;
-       else if (pkt_rt < BNA_PKT_RATE_20K)
-               load = BNA_LOAD_T_LOW_3;
-       else if (pkt_rt < BNA_PKT_RATE_30K)
-               load = BNA_LOAD_T_LOW_2;
-       else if (pkt_rt < BNA_PKT_RATE_40K)
-               load = BNA_LOAD_T_LOW_1;
-       else if (pkt_rt < BNA_PKT_RATE_50K)
-               load = BNA_LOAD_T_HIGH_1;
-       else if (pkt_rt < BNA_PKT_RATE_60K)
-               load = BNA_LOAD_T_HIGH_2;
-       else if (pkt_rt < BNA_PKT_RATE_80K)
-               load = BNA_LOAD_T_HIGH_3;
-       else
-               load = BNA_LOAD_T_HIGH_4;
-
-       if (small_rt > (large_rt << 1))
-               bias = 0;
-       else
-               bias = 1;
-
-       ccb->pkt_rate.small_pkt_cnt = 0;
-       ccb->pkt_rate.large_pkt_cnt = 0;
-
-       coalescing_timeo = bna->rx_mod.dim_vector[load][bias];
-       ccb->rx_coalescing_timeo = coalescing_timeo;
-
-       /* Set it to IB */
-       bna_ib_coalescing_timeo_set(ccb->cq->ib, coalescing_timeo);
-}
-
-/* Tx */
-/* TX <- bnad */
-void
-bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo)
-{
-       struct bna_txq *txq;
-       struct list_head *qe;
-
-       list_for_each(qe, &tx->txq_q) {
-               txq = (struct bna_txq *)qe;
-               bna_ib_coalescing_timeo_set(txq->ib, coalescing_timeo);
-       }
-}
-
-/*
- * Private data
- */
-
-struct bna_ritseg_pool_cfg {
-       u32     pool_size;
-       u32     pool_entry_size;
-};
-init_ritseg_pool(ritseg_pool_cfg);
-
-/*
- * Private functions
- */
-static void
-bna_ucam_mod_init(struct bna_ucam_mod *ucam_mod, struct bna *bna,
-                 struct bna_res_info *res_info)
-{
-       int i;
-
-       ucam_mod->ucmac = (struct bna_mac *)
-               res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
-
-       INIT_LIST_HEAD(&ucam_mod->free_q);
-       for (i = 0; i < BFI_MAX_UCMAC; i++) {
-               bfa_q_qe_init(&ucam_mod->ucmac[i].qe);
-               list_add_tail(&ucam_mod->ucmac[i].qe, &ucam_mod->free_q);
-       }
-
-       ucam_mod->bna = bna;
-}
-
-static void
-bna_ucam_mod_uninit(struct bna_ucam_mod *ucam_mod)
-{
-       struct list_head *qe;
-       int i = 0;
-
-       list_for_each(qe, &ucam_mod->free_q)
-               i++;
-
-       ucam_mod->bna = NULL;
-}
-
-static void
-bna_mcam_mod_init(struct bna_mcam_mod *mcam_mod, struct bna *bna,
-                 struct bna_res_info *res_info)
-{
-       int i;
-
-       mcam_mod->mcmac = (struct bna_mac *)
-               res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
-
-       INIT_LIST_HEAD(&mcam_mod->free_q);
-       for (i = 0; i < BFI_MAX_MCMAC; i++) {
-               bfa_q_qe_init(&mcam_mod->mcmac[i].qe);
-               list_add_tail(&mcam_mod->mcmac[i].qe, &mcam_mod->free_q);
-       }
-
-       mcam_mod->bna = bna;
-}
-
-static void
-bna_mcam_mod_uninit(struct bna_mcam_mod *mcam_mod)
-{
-       struct list_head *qe;
-       int i = 0;
-
-       list_for_each(qe, &mcam_mod->free_q)
-               i++;
-
-       mcam_mod->bna = NULL;
-}
-
-static void
-bna_rit_mod_init(struct bna_rit_mod *rit_mod,
-               struct bna_res_info *res_info)
-{
-       int i;
-       int j;
-       int count;
-       int offset;
-
-       rit_mod->rit = (struct bna_rit_entry *)
-               res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.mdl[0].kva;
-       rit_mod->rit_segment = (struct bna_rit_segment *)
-               res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.mdl[0].kva;
-
-       count = 0;
-       offset = 0;
-       for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
-               INIT_LIST_HEAD(&rit_mod->rit_seg_pool[i]);
-               for (j = 0; j < ritseg_pool_cfg[i].pool_size; j++) {
-                       bfa_q_qe_init(&rit_mod->rit_segment[count].qe);
-                       rit_mod->rit_segment[count].max_rit_size =
-                                       ritseg_pool_cfg[i].pool_entry_size;
-                       rit_mod->rit_segment[count].rit_offset = offset;
-                       rit_mod->rit_segment[count].rit =
-                                       &rit_mod->rit[offset];
-                       list_add_tail(&rit_mod->rit_segment[count].qe,
-                               &rit_mod->rit_seg_pool[i]);
-                       count++;
-                       offset += ritseg_pool_cfg[i].pool_entry_size;
-               }
-       }
-}
-
-/*
- * Public functions
- */
-
-/* Called during probe(), before calling bna_init() */
-void
-bna_res_req(struct bna_res_info *res_info)
-{
-       bna_adv_res_req(res_info);
-
-       /* DMA memory for retrieving IOC attributes */
-       res_info[BNA_RES_MEM_T_ATTR].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
-       res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.len =
-                               ALIGN(bfa_nw_ioc_meminfo(), PAGE_SIZE);
-
-       /* DMA memory for index segment of an IB */
-       res_info[BNA_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
-       res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.len =
-                               BFI_IBIDX_SIZE * BFI_IBIDX_MAX_SEGSIZE;
-       res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.num = BFI_MAX_IB;
-
-       /* Virtual memory for IB objects - stored by IB module */
-       res_info[BNA_RES_MEM_T_IB_ARRAY].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.mem_type =
-                                                               BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.len =
-                               BFI_MAX_IB * sizeof(struct bna_ib);
-
-       /* Virtual memory for intr objects - stored by IB module */
-       res_info[BNA_RES_MEM_T_INTR_ARRAY].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.mem_type =
-                                                               BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.len =
-                               BFI_MAX_IB * sizeof(struct bna_intr);
-
-       /* Virtual memory for idx_seg objects - stored by IB module */
-       res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.mem_type =
-                                                               BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.len =
-                       BFI_IBIDX_TOTAL_SEGS * sizeof(struct bna_ibidx_seg);
-
-       /* Virtual memory for Tx objects - stored by Tx module */
-       res_info[BNA_RES_MEM_T_TX_ARRAY].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.mem_type =
-                                                               BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.len =
-                       BFI_MAX_TXQ * sizeof(struct bna_tx);
-
-       /* Virtual memory for TxQ - stored by Tx module */
-       res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mem_type =
-                                                               BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.len =
-                       BFI_MAX_TXQ * sizeof(struct bna_txq);
-
-       /* Virtual memory for Rx objects - stored by Rx module */
-       res_info[BNA_RES_MEM_T_RX_ARRAY].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.mem_type =
-                                                               BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.len =
-                       BFI_MAX_RXQ * sizeof(struct bna_rx);
-
-       /* Virtual memory for RxPath - stored by Rx module */
-       res_info[BNA_RES_MEM_T_RXP_ARRAY].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mem_type =
-                                                               BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.len =
-                       BFI_MAX_RXQ * sizeof(struct bna_rxp);
-
-       /* Virtual memory for RxQ - stored by Rx module */
-       res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mem_type =
-                                                               BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.len =
-                       BFI_MAX_RXQ * sizeof(struct bna_rxq);
-
-       /* Virtual memory for Unicast MAC address - stored by ucam module */
-       res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mem_type =
-                                                               BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.len =
-                       BFI_MAX_UCMAC * sizeof(struct bna_mac);
-
-       /* Virtual memory for Multicast MAC address - stored by mcam module */
-       res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mem_type =
-                                                               BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.len =
-                       BFI_MAX_MCMAC * sizeof(struct bna_mac);
-
-       /* Virtual memory for RIT entries */
-       res_info[BNA_RES_MEM_T_RIT_ENTRY].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.mem_type =
-                                                               BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.len =
-                       BFI_MAX_RIT_SIZE * sizeof(struct bna_rit_entry);
-
-       /* Virtual memory for RIT segment table */
-       res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_type = BNA_RES_T_MEM;
-       res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.mem_type =
-                                                               BNA_MEM_T_KVA;
-       res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.num = 1;
-       res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.len =
-                       BFI_RIT_TOTAL_SEGS * sizeof(struct bna_rit_segment);
-
-       /* Interrupt resource for mailbox interrupt */
-       res_info[BNA_RES_INTR_T_MBOX].res_type = BNA_RES_T_INTR;
-       res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.intr_type =
-                                                       BNA_INTR_T_MSIX;
-       res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.num = 1;
-}
-
-/* Called during probe() */
-void
-bna_init(struct bna *bna, struct bnad *bnad, struct bfa_pcidev *pcidev,
-               struct bna_res_info *res_info)
-{
-       bna->bnad = bnad;
-       bna->pcidev = *pcidev;
-
-       bna->stats.hw_stats = (struct bfi_ll_stats *)
-               res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].kva;
-       bna->hw_stats_dma.msb =
-               res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.msb;
-       bna->hw_stats_dma.lsb =
-               res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.lsb;
-       bna->stats.sw_stats = (struct bna_sw_stats *)
-               res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.mdl[0].kva;
-
-       bna->regs.page_addr = bna->pcidev.pci_bar_kva +
-                               reg_offset[bna->pcidev.pci_func].page_addr;
-       bna->regs.fn_int_status = bna->pcidev.pci_bar_kva +
-                               reg_offset[bna->pcidev.pci_func].fn_int_status;
-       bna->regs.fn_int_mask = bna->pcidev.pci_bar_kva +
-                               reg_offset[bna->pcidev.pci_func].fn_int_mask;
-
-       if (bna->pcidev.pci_func < 3)
-               bna->port_num = 0;
-       else
-               bna->port_num = 1;
-
-       /* Also initializes diag, cee, sfp, phy_port and mbox_mod */
-       bna_device_init(&bna->device, bna, res_info);
-
-       bna_port_init(&bna->port, bna);
-
-       bna_tx_mod_init(&bna->tx_mod, bna, res_info);
-
-       bna_rx_mod_init(&bna->rx_mod, bna, res_info);
-
-       bna_ib_mod_init(&bna->ib_mod, bna, res_info);
-
-       bna_rit_mod_init(&bna->rit_mod, res_info);
-
-       bna_ucam_mod_init(&bna->ucam_mod, bna, res_info);
-
-       bna_mcam_mod_init(&bna->mcam_mod, bna, res_info);
-
-       bna->rxf_promisc_id = BFI_MAX_RXF;
-
-       /* Mbox q element for posting stat request to f/w */
-       bfa_q_qe_init(&bna->mbox_qe.qe);
-}
-
-void
-bna_uninit(struct bna *bna)
-{
-       bna_mcam_mod_uninit(&bna->mcam_mod);
-
-       bna_ucam_mod_uninit(&bna->ucam_mod);
-
-       bna_ib_mod_uninit(&bna->ib_mod);
-
-       bna_rx_mod_uninit(&bna->rx_mod);
-
-       bna_tx_mod_uninit(&bna->tx_mod);
-
-       bna_port_uninit(&bna->port);
-
-       bna_device_uninit(&bna->device);
-
-       bna->bnad = NULL;
-}
-
-struct bna_mac *
-bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod)
-{
-       struct list_head *qe;
-
-       if (list_empty(&ucam_mod->free_q))
-               return NULL;
-
-       bfa_q_deq(&ucam_mod->free_q, &qe);
-
-       return (struct bna_mac *)qe;
-}
-
-void
-bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod, struct bna_mac *mac)
-{
-       list_add_tail(&mac->qe, &ucam_mod->free_q);
-}
-
-struct bna_mac *
-bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod)
-{
-       struct list_head *qe;
-
-       if (list_empty(&mcam_mod->free_q))
-               return NULL;
-
-       bfa_q_deq(&mcam_mod->free_q, &qe);
-
-       return (struct bna_mac *)qe;
-}
-
-void
-bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod, struct bna_mac *mac)
-{
-       list_add_tail(&mac->qe, &mcam_mod->free_q);
-}
-
-/**
- * Note: This should be called in the same locking context as the call to
- * bna_rit_mod_seg_get()
- */
-int
-bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size)
-{
-       int i;
-
-       /* Select the pool for seg_size */
-       for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
-               if (seg_size <= ritseg_pool_cfg[i].pool_entry_size)
-                       break;
-       }
-
-       if (i == BFI_RIT_SEG_TOTAL_POOLS)
-               return 0;
-
-       if (list_empty(&rit_mod->rit_seg_pool[i]))
-               return 0;
-
-       return 1;
-}
-
-struct bna_rit_segment *
-bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size)
-{
-       struct bna_rit_segment *seg;
-       struct list_head *qe;
-       int i;
-
-       /* Select the pool for seg_size */
-       for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
-               if (seg_size <= ritseg_pool_cfg[i].pool_entry_size)
-                       break;
-       }
-
-       if (i == BFI_RIT_SEG_TOTAL_POOLS)
-               return NULL;
-
-       if (list_empty(&rit_mod->rit_seg_pool[i]))
-               return NULL;
-
-       bfa_q_deq(&rit_mod->rit_seg_pool[i], &qe);
-       seg = (struct bna_rit_segment *)qe;
-       bfa_q_qe_init(&seg->qe);
-       seg->rit_size = seg_size;
-
-       return seg;
-}
-
-void
-bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod,
-                       struct bna_rit_segment *seg)
-{
-       int i;
-
-       /* Select the pool for seg->max_rit_size */
-       for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
-               if (seg->max_rit_size == ritseg_pool_cfg[i].pool_entry_size)
-                       break;
-       }
-
-       seg->rit_size = 0;
-       list_add_tail(&seg->qe, &rit_mod->rit_seg_pool[i]);
-}
diff --git a/drivers/net/bna/bna_hw.h b/drivers/net/bna/bna_hw.h
deleted file mode 100644 (file)
index cad233d..0000000
+++ /dev/null
@@ -1,1490 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * File for interrupt macros and functions
- */
-
-#ifndef __BNA_HW_H__
-#define __BNA_HW_H__
-
-#include "bfi_ctreg.h"
-
-/**
- *
- * SW imposed limits
- *
- */
-
-#ifndef BNA_BIOS_BUILD
-
-#define BFI_MAX_TXQ                    64
-#define BFI_MAX_RXQ                    64
-#define        BFI_MAX_RXF                     64
-#define BFI_MAX_IB                     128
-#define        BFI_MAX_RIT_SIZE                256
-#define        BFI_RSS_RIT_SIZE                64
-#define        BFI_NONRSS_RIT_SIZE             1
-#define BFI_MAX_UCMAC                  256
-#define BFI_MAX_MCMAC                  512
-#define BFI_IBIDX_SIZE                 4
-#define BFI_MAX_VLAN                   4095
-
-/**
- * There are 2 free IB index pools:
- *     pool1: 120 segments of 1 index each
- *     pool8: 1 segment of 8 indexes
- */
-#define BFI_IBIDX_POOL1_SIZE           116
-#define        BFI_IBIDX_POOL1_ENTRY_SIZE      1
-#define BFI_IBIDX_POOL2_SIZE           2
-#define        BFI_IBIDX_POOL2_ENTRY_SIZE      2
-#define        BFI_IBIDX_POOL8_SIZE            1
-#define        BFI_IBIDX_POOL8_ENTRY_SIZE      8
-#define        BFI_IBIDX_TOTAL_POOLS           3
-#define        BFI_IBIDX_TOTAL_SEGS            119 /* (POOL1 + POOL2 + POOL8)_SIZE */
-#define        BFI_IBIDX_MAX_SEGSIZE           8
-#define init_ibidx_pool(name)                                          \
-static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] =             \
-{                                                                      \
-       { BFI_IBIDX_POOL1_SIZE, BFI_IBIDX_POOL1_ENTRY_SIZE },           \
-       { BFI_IBIDX_POOL2_SIZE, BFI_IBIDX_POOL2_ENTRY_SIZE },           \
-       { BFI_IBIDX_POOL8_SIZE, BFI_IBIDX_POOL8_ENTRY_SIZE }            \
-}
-
-/**
- * There are 2 free RIT segment pools:
- *     Pool1: 192 segments of 1 RIT entry each
- *     Pool2: 1 segment of 64 RIT entry
- */
-#define BFI_RIT_SEG_POOL1_SIZE         192
-#define BFI_RIT_SEG_POOL1_ENTRY_SIZE   1
-#define BFI_RIT_SEG_POOLRSS_SIZE       1
-#define BFI_RIT_SEG_POOLRSS_ENTRY_SIZE 64
-#define BFI_RIT_SEG_TOTAL_POOLS                2
-#define BFI_RIT_TOTAL_SEGS             193 /* POOL1_SIZE + POOLRSS_SIZE */
-#define init_ritseg_pool(name)                                         \
-static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] =      \
-{                                                                      \
-       { BFI_RIT_SEG_POOL1_SIZE, BFI_RIT_SEG_POOL1_ENTRY_SIZE },       \
-       { BFI_RIT_SEG_POOLRSS_SIZE, BFI_RIT_SEG_POOLRSS_ENTRY_SIZE }    \
-}
-
-#else /* BNA_BIOS_BUILD */
-
-#define BFI_MAX_TXQ                    1
-#define BFI_MAX_RXQ                    1
-#define        BFI_MAX_RXF                     1
-#define BFI_MAX_IB                     2
-#define        BFI_MAX_RIT_SIZE                2
-#define        BFI_RSS_RIT_SIZE                64
-#define        BFI_NONRSS_RIT_SIZE             1
-#define BFI_MAX_UCMAC                  1
-#define BFI_MAX_MCMAC                  8
-#define BFI_IBIDX_SIZE                 4
-#define BFI_MAX_VLAN                   4095
-/* There is one free pool: 2 segments of 1 index each */
-#define BFI_IBIDX_POOL1_SIZE           2
-#define        BFI_IBIDX_POOL1_ENTRY_SIZE      1
-#define        BFI_IBIDX_TOTAL_POOLS           1
-#define        BFI_IBIDX_TOTAL_SEGS            2 /* POOL1_SIZE */
-#define        BFI_IBIDX_MAX_SEGSIZE           1
-#define init_ibidx_pool(name)                                          \
-static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] =             \
-{                                                                      \
-       { BFI_IBIDX_POOL1_SIZE, BFI_IBIDX_POOL1_ENTRY_SIZE }            \
-}
-
-#define BFI_RIT_SEG_POOL1_SIZE         1
-#define BFI_RIT_SEG_POOL1_ENTRY_SIZE   1
-#define BFI_RIT_SEG_TOTAL_POOLS                1
-#define BFI_RIT_TOTAL_SEGS             1 /* POOL1_SIZE */
-#define init_ritseg_pool(name)                                         \
-static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] =      \
-{                                                                      \
-       { BFI_RIT_SEG_POOL1_SIZE, BFI_RIT_SEG_POOL1_ENTRY_SIZE }        \
-}
-
-#endif /* BNA_BIOS_BUILD */
-
-#define BFI_RSS_HASH_KEY_LEN           10
-
-#define BFI_COALESCING_TIMER_UNIT      5       /* 5us */
-#define BFI_MAX_COALESCING_TIMEO       0xFF    /* in 5us units */
-#define BFI_MAX_INTERPKT_COUNT         0xFF
-#define BFI_MAX_INTERPKT_TIMEO         0xF     /* in 0.5us units */
-#define BFI_TX_COALESCING_TIMEO                20      /* 20 * 5 = 100us */
-#define BFI_TX_INTERPKT_COUNT          32
-#define        BFI_RX_COALESCING_TIMEO         12      /* 12 * 5 = 60us */
-#define        BFI_RX_INTERPKT_COUNT           6       /* Pkt Cnt = 6 */
-#define        BFI_RX_INTERPKT_TIMEO           3       /* 3 * 0.5 = 1.5us */
-
-#define BFI_TXQ_WI_SIZE                        64      /* bytes */
-#define BFI_RXQ_WI_SIZE                        8       /* bytes */
-#define BFI_CQ_WI_SIZE                 16      /* bytes */
-#define BFI_TX_MAX_WRR_QUOTA           0xFFF
-
-#define BFI_TX_MAX_VECTORS_PER_WI      4
-#define BFI_TX_MAX_VECTORS_PER_PKT     0xFF
-#define BFI_TX_MAX_DATA_PER_VECTOR     0xFFFF
-#define BFI_TX_MAX_DATA_PER_PKT                0xFFFFFF
-
-/* Small Q buffer size */
-#define BFI_SMALL_RXBUF_SIZE           128
-
-/* Defined separately since BFA_FLASH_DMA_BUF_SZ is in bfa_flash.c */
-#define BFI_FLASH_DMA_BUF_SZ           0x010000 /* 64K DMA */
-#define BFI_HW_STATS_SIZE              0x4000 /* 16K DMA */
-
-/**
- *
- * HW register offsets, macros
- *
- */
-
-/* DMA Block Register Host Window Start Address */
-#define DMA_BLK_REG_ADDR               0x00013000
-
-/* DMA Block Internal Registers */
-#define DMA_CTRL_REG0                  (DMA_BLK_REG_ADDR + 0x000)
-#define DMA_CTRL_REG1                  (DMA_BLK_REG_ADDR + 0x004)
-#define DMA_ERR_INT_STATUS             (DMA_BLK_REG_ADDR + 0x008)
-#define DMA_ERR_INT_ENABLE             (DMA_BLK_REG_ADDR + 0x00c)
-#define DMA_ERR_INT_STATUS_SET         (DMA_BLK_REG_ADDR + 0x010)
-
-/* APP Block Register Address Offset from BAR0 */
-#define APP_BLK_REG_ADDR               0x00014000
-
-/* Host Function Interrupt Mask Registers */
-#define HOSTFN0_INT_MASK               (APP_BLK_REG_ADDR + 0x004)
-#define HOSTFN1_INT_MASK               (APP_BLK_REG_ADDR + 0x104)
-#define HOSTFN2_INT_MASK               (APP_BLK_REG_ADDR + 0x304)
-#define HOSTFN3_INT_MASK               (APP_BLK_REG_ADDR + 0x404)
-
-/**
- * Host Function PCIe Error Registers
- * Duplicates "Correctable" & "Uncorrectable"
- * registers in PCIe Config space.
- */
-#define FN0_PCIE_ERR_REG               (APP_BLK_REG_ADDR + 0x014)
-#define FN1_PCIE_ERR_REG               (APP_BLK_REG_ADDR + 0x114)
-#define FN2_PCIE_ERR_REG               (APP_BLK_REG_ADDR + 0x314)
-#define FN3_PCIE_ERR_REG               (APP_BLK_REG_ADDR + 0x414)
-
-/* Host Function Error Type Status Registers */
-#define FN0_ERR_TYPE_STATUS_REG                (APP_BLK_REG_ADDR + 0x018)
-#define FN1_ERR_TYPE_STATUS_REG                (APP_BLK_REG_ADDR + 0x118)
-#define FN2_ERR_TYPE_STATUS_REG                (APP_BLK_REG_ADDR + 0x318)
-#define FN3_ERR_TYPE_STATUS_REG                (APP_BLK_REG_ADDR + 0x418)
-
-/* Host Function Error Type Mask Registers */
-#define FN0_ERR_TYPE_MSK_STATUS_REG    (APP_BLK_REG_ADDR + 0x01c)
-#define FN1_ERR_TYPE_MSK_STATUS_REG    (APP_BLK_REG_ADDR + 0x11c)
-#define FN2_ERR_TYPE_MSK_STATUS_REG    (APP_BLK_REG_ADDR + 0x31c)
-#define FN3_ERR_TYPE_MSK_STATUS_REG    (APP_BLK_REG_ADDR + 0x41c)
-
-/* Catapult Host Semaphore Status Registers (App block) */
-#define HOST_SEM_STS0_REG              (APP_BLK_REG_ADDR + 0x630)
-#define HOST_SEM_STS1_REG              (APP_BLK_REG_ADDR + 0x634)
-#define HOST_SEM_STS2_REG              (APP_BLK_REG_ADDR + 0x638)
-#define HOST_SEM_STS3_REG              (APP_BLK_REG_ADDR + 0x63c)
-#define HOST_SEM_STS4_REG              (APP_BLK_REG_ADDR + 0x640)
-#define HOST_SEM_STS5_REG              (APP_BLK_REG_ADDR + 0x644)
-#define HOST_SEM_STS6_REG              (APP_BLK_REG_ADDR + 0x648)
-#define HOST_SEM_STS7_REG              (APP_BLK_REG_ADDR + 0x64c)
-
-/* PCIe Misc Register */
-#define PCIE_MISC_REG                  (APP_BLK_REG_ADDR + 0x200)
-
-/* Temp Sensor Control Registers */
-#define TEMPSENSE_CNTL_REG             (APP_BLK_REG_ADDR + 0x250)
-#define TEMPSENSE_STAT_REG             (APP_BLK_REG_ADDR + 0x254)
-
-/* APP Block local error registers */
-#define APP_LOCAL_ERR_STAT             (APP_BLK_REG_ADDR + 0x258)
-#define APP_LOCAL_ERR_MSK              (APP_BLK_REG_ADDR + 0x25c)
-
-/* PCIe Link Error registers */
-#define PCIE_LNK_ERR_STAT              (APP_BLK_REG_ADDR + 0x260)
-#define PCIE_LNK_ERR_MSK               (APP_BLK_REG_ADDR + 0x264)
-
-/**
- * FCoE/FIP Ethertype Register
- * 31:16 -- Chip wide value for FIP type
- * 15:0  -- Chip wide value for FCoE type
- */
-#define FCOE_FIP_ETH_TYPE              (APP_BLK_REG_ADDR + 0x280)
-
-/**
- * Reserved Ethertype Register
- * 31:16 -- Reserved
- * 15:0  -- Other ethertype
- */
-#define RESV_ETH_TYPE                  (APP_BLK_REG_ADDR + 0x284)
-
-/**
- * Host Command Status Registers
- * Each set consists of 3 registers :
- * clear, set, cmd
- * 16 such register sets in all
- * See catapult_spec.pdf for detailed functionality
- * Put each type in a single macro accessed by _num ?
- */
-#define HOST_CMDSTS0_CLR_REG           (APP_BLK_REG_ADDR + 0x500)
-#define HOST_CMDSTS0_SET_REG           (APP_BLK_REG_ADDR + 0x504)
-#define HOST_CMDSTS0_REG               (APP_BLK_REG_ADDR + 0x508)
-#define HOST_CMDSTS1_CLR_REG           (APP_BLK_REG_ADDR + 0x510)
-#define HOST_CMDSTS1_SET_REG           (APP_BLK_REG_ADDR + 0x514)
-#define HOST_CMDSTS1_REG               (APP_BLK_REG_ADDR + 0x518)
-#define HOST_CMDSTS2_CLR_REG           (APP_BLK_REG_ADDR + 0x520)
-#define HOST_CMDSTS2_SET_REG           (APP_BLK_REG_ADDR + 0x524)
-#define HOST_CMDSTS2_REG               (APP_BLK_REG_ADDR + 0x528)
-#define HOST_CMDSTS3_CLR_REG           (APP_BLK_REG_ADDR + 0x530)
-#define HOST_CMDSTS3_SET_REG           (APP_BLK_REG_ADDR + 0x534)
-#define HOST_CMDSTS3_REG               (APP_BLK_REG_ADDR + 0x538)
-#define HOST_CMDSTS4_CLR_REG           (APP_BLK_REG_ADDR + 0x540)
-#define HOST_CMDSTS4_SET_REG           (APP_BLK_REG_ADDR + 0x544)
-#define HOST_CMDSTS4_REG               (APP_BLK_REG_ADDR + 0x548)
-#define HOST_CMDSTS5_CLR_REG           (APP_BLK_REG_ADDR + 0x550)
-#define HOST_CMDSTS5_SET_REG           (APP_BLK_REG_ADDR + 0x554)
-#define HOST_CMDSTS5_REG               (APP_BLK_REG_ADDR + 0x558)
-#define HOST_CMDSTS6_CLR_REG           (APP_BLK_REG_ADDR + 0x560)
-#define HOST_CMDSTS6_SET_REG           (APP_BLK_REG_ADDR + 0x564)
-#define HOST_CMDSTS6_REG               (APP_BLK_REG_ADDR + 0x568)
-#define HOST_CMDSTS7_CLR_REG           (APP_BLK_REG_ADDR + 0x570)
-#define HOST_CMDSTS7_SET_REG           (APP_BLK_REG_ADDR + 0x574)
-#define HOST_CMDSTS7_REG               (APP_BLK_REG_ADDR + 0x578)
-#define HOST_CMDSTS8_CLR_REG           (APP_BLK_REG_ADDR + 0x580)
-#define HOST_CMDSTS8_SET_REG           (APP_BLK_REG_ADDR + 0x584)
-#define HOST_CMDSTS8_REG               (APP_BLK_REG_ADDR + 0x588)
-#define HOST_CMDSTS9_CLR_REG           (APP_BLK_REG_ADDR + 0x590)
-#define HOST_CMDSTS9_SET_REG           (APP_BLK_REG_ADDR + 0x594)
-#define HOST_CMDSTS9_REG               (APP_BLK_REG_ADDR + 0x598)
-#define HOST_CMDSTS10_CLR_REG          (APP_BLK_REG_ADDR + 0x5A0)
-#define HOST_CMDSTS10_SET_REG          (APP_BLK_REG_ADDR + 0x5A4)
-#define HOST_CMDSTS10_REG              (APP_BLK_REG_ADDR + 0x5A8)
-#define HOST_CMDSTS11_CLR_REG          (APP_BLK_REG_ADDR + 0x5B0)
-#define HOST_CMDSTS11_SET_REG          (APP_BLK_REG_ADDR + 0x5B4)
-#define HOST_CMDSTS11_REG              (APP_BLK_REG_ADDR + 0x5B8)
-#define HOST_CMDSTS12_CLR_REG          (APP_BLK_REG_ADDR + 0x5C0)
-#define HOST_CMDSTS12_SET_REG          (APP_BLK_REG_ADDR + 0x5C4)
-#define HOST_CMDSTS12_REG              (APP_BLK_REG_ADDR + 0x5C8)
-#define HOST_CMDSTS13_CLR_REG          (APP_BLK_REG_ADDR + 0x5D0)
-#define HOST_CMDSTS13_SET_REG          (APP_BLK_REG_ADDR + 0x5D4)
-#define HOST_CMDSTS13_REG              (APP_BLK_REG_ADDR + 0x5D8)
-#define HOST_CMDSTS14_CLR_REG          (APP_BLK_REG_ADDR + 0x5E0)
-#define HOST_CMDSTS14_SET_REG          (APP_BLK_REG_ADDR + 0x5E4)
-#define HOST_CMDSTS14_REG              (APP_BLK_REG_ADDR + 0x5E8)
-#define HOST_CMDSTS15_CLR_REG          (APP_BLK_REG_ADDR + 0x5F0)
-#define HOST_CMDSTS15_SET_REG          (APP_BLK_REG_ADDR + 0x5F4)
-#define HOST_CMDSTS15_REG              (APP_BLK_REG_ADDR + 0x5F8)
-
-/**
- * LPU0 Block Register Address Offset from BAR0
- * Range 0x18000 - 0x18033
- */
-#define LPU0_BLK_REG_ADDR              0x00018000
-
-/**
- * LPU0 Registers
- * Should they be directly used from host,
- * except for diagnostics ?
- * CTL_REG : Control register
- * CMD_REG : Triggers exec. of cmd. in
- *           Mailbox memory
- */
-#define LPU0_MBOX_CTL_REG              (LPU0_BLK_REG_ADDR + 0x000)
-#define LPU0_MBOX_CMD_REG              (LPU0_BLK_REG_ADDR + 0x004)
-#define LPU0_MBOX_LINK_0REG            (LPU0_BLK_REG_ADDR + 0x008)
-#define LPU1_MBOX_LINK_0REG            (LPU0_BLK_REG_ADDR + 0x00c)
-#define LPU0_MBOX_STATUS_0REG          (LPU0_BLK_REG_ADDR + 0x010)
-#define LPU1_MBOX_STATUS_0REG          (LPU0_BLK_REG_ADDR + 0x014)
-#define LPU0_ERR_STATUS_REG            (LPU0_BLK_REG_ADDR + 0x018)
-#define LPU0_ERR_SET_REG               (LPU0_BLK_REG_ADDR + 0x020)
-
-/**
- * LPU1 Block Register Address Offset from BAR0
- * Range 0x18400 - 0x18433
- */
-#define LPU1_BLK_REG_ADDR              0x00018400
-
-/**
- * LPU1 Registers
- * Same as LPU0 registers above
- */
-#define LPU1_MBOX_CTL_REG              (LPU1_BLK_REG_ADDR + 0x000)
-#define LPU1_MBOX_CMD_REG              (LPU1_BLK_REG_ADDR + 0x004)
-#define LPU0_MBOX_LINK_1REG            (LPU1_BLK_REG_ADDR + 0x008)
-#define LPU1_MBOX_LINK_1REG            (LPU1_BLK_REG_ADDR + 0x00c)
-#define LPU0_MBOX_STATUS_1REG          (LPU1_BLK_REG_ADDR + 0x010)
-#define LPU1_MBOX_STATUS_1REG          (LPU1_BLK_REG_ADDR + 0x014)
-#define LPU1_ERR_STATUS_REG            (LPU1_BLK_REG_ADDR + 0x018)
-#define LPU1_ERR_SET_REG               (LPU1_BLK_REG_ADDR + 0x020)
-
-/**
- * PSS Block Register Address Offset from BAR0
- * Range 0x18800 - 0x188DB
- */
-#define PSS_BLK_REG_ADDR               0x00018800
-
-/**
- * PSS Registers
- * For details, see catapult_spec.pdf
- * ERR_STATUS_REG : Indicates error in PSS module
- * RAM_ERR_STATUS_REG : Indicates RAM module that detected error
- */
-#define ERR_STATUS_SET                 (PSS_BLK_REG_ADDR + 0x018)
-#define PSS_RAM_ERR_STATUS_REG         (PSS_BLK_REG_ADDR + 0x01C)
-
-/**
- * PSS Semaphore Lock Registers, total 16
- * First read when unlocked returns 0,
- * and is set to 1, atomically.
- * Subsequent reads returns 1.
- * To clear set the value to 0.
- * Range : 0x20 to 0x5c
- */
-#define PSS_SEM_LOCK_REG(_num)         \
-       (PSS_BLK_REG_ADDR + 0x020 + ((_num) << 2))
-
-/**
- * PSS Semaphore Status Registers,
- * corresponding to the lock registers above
- */
-#define PSS_SEM_STATUS_REG(_num)               \
-       (PSS_BLK_REG_ADDR + 0x060 + ((_num) << 2))
-
-/**
- * Catapult CPQ Registers
- * Defines for Mailbox Registers
- * Used to send mailbox commands to firmware from
- * host. The data part is written to the MBox
- * memory, registers are used to indicate that
- * a commnad is resident in memory.
- *
- * Note : LPU0<->LPU1 mailboxes are not listed here
- */
-#define CPQ_BLK_REG_ADDR               0x00019000
-
-#define HOSTFN0_LPU0_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x130)
-#define HOSTFN0_LPU1_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x134)
-#define LPU0_HOSTFN0_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x138)
-#define LPU1_HOSTFN0_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x13C)
-
-#define HOSTFN1_LPU0_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x140)
-#define HOSTFN1_LPU1_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x144)
-#define LPU0_HOSTFN1_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x148)
-#define LPU1_HOSTFN1_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x14C)
-
-#define HOSTFN2_LPU0_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x170)
-#define HOSTFN2_LPU1_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x174)
-#define LPU0_HOSTFN2_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x178)
-#define LPU1_HOSTFN2_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x17C)
-
-#define HOSTFN3_LPU0_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x180)
-#define HOSTFN3_LPU1_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x184)
-#define LPU0_HOSTFN3_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x188)
-#define LPU1_HOSTFN3_MBOX1_CMD_STAT    (CPQ_BLK_REG_ADDR + 0x18C)
-
-/* Host Function Force Parity Error Registers */
-#define HOSTFN0_LPU_FORCE_PERR         (CPQ_BLK_REG_ADDR + 0x120)
-#define HOSTFN1_LPU_FORCE_PERR         (CPQ_BLK_REG_ADDR + 0x124)
-#define HOSTFN2_LPU_FORCE_PERR         (CPQ_BLK_REG_ADDR + 0x128)
-#define HOSTFN3_LPU_FORCE_PERR         (CPQ_BLK_REG_ADDR + 0x12C)
-
-/* LL Port[0|1] Halt Mask Registers */
-#define LL_HALT_MSK_P0                 (CPQ_BLK_REG_ADDR + 0x1A0)
-#define LL_HALT_MSK_P1                 (CPQ_BLK_REG_ADDR + 0x1B0)
-
-/* LL Port[0|1] Error Mask Registers */
-#define LL_ERR_MSK_P0                  (CPQ_BLK_REG_ADDR + 0x1D0)
-#define LL_ERR_MSK_P1                  (CPQ_BLK_REG_ADDR + 0x1D4)
-
-/* EMC FLI (Flash Controller) Block Register Address Offset from BAR0 */
-#define FLI_BLK_REG_ADDR               0x0001D000
-
-/* EMC FLI Registers */
-#define FLI_CMD_REG                    (FLI_BLK_REG_ADDR + 0x000)
-#define FLI_ADDR_REG                   (FLI_BLK_REG_ADDR + 0x004)
-#define FLI_CTL_REG                    (FLI_BLK_REG_ADDR + 0x008)
-#define FLI_WRDATA_REG                 (FLI_BLK_REG_ADDR + 0x00C)
-#define FLI_RDDATA_REG                 (FLI_BLK_REG_ADDR + 0x010)
-#define FLI_DEV_STATUS_REG             (FLI_BLK_REG_ADDR + 0x014)
-#define FLI_SIG_WD_REG                 (FLI_BLK_REG_ADDR + 0x018)
-
-/**
- * RO register
- * 31:16 -- Vendor Id
- * 15:0  -- Device Id
- */
-#define FLI_DEV_VENDOR_REG             (FLI_BLK_REG_ADDR + 0x01C)
-#define FLI_ERR_STATUS_REG             (FLI_BLK_REG_ADDR + 0x020)
-
-/**
- * RAD (RxAdm) Block Register Address Offset from BAR0
- * RAD0 Range : 0x20000 - 0x203FF
- * RAD1 Range : 0x20400 - 0x207FF
- */
-#define RAD0_BLK_REG_ADDR              0x00020000
-#define RAD1_BLK_REG_ADDR              0x00020400
-
-/* RAD0 Registers */
-#define RAD0_CTL_REG                   (RAD0_BLK_REG_ADDR + 0x000)
-#define RAD0_PE_PARM_REG               (RAD0_BLK_REG_ADDR + 0x004)
-#define RAD0_BCN_REG                   (RAD0_BLK_REG_ADDR + 0x008)
-
-/* Default function ID register */
-#define RAD0_DEFAULT_REG               (RAD0_BLK_REG_ADDR + 0x00C)
-
-/* Default promiscuous ID register */
-#define RAD0_PROMISC_REG               (RAD0_BLK_REG_ADDR + 0x010)
-
-#define RAD0_BCNQ_REG                  (RAD0_BLK_REG_ADDR + 0x014)
-
-/*
- * This register selects 1 of 8 PM Q's using
- * VLAN pri, for non-BCN packets without a VLAN tag
- */
-#define RAD0_DEFAULTQ_REG              (RAD0_BLK_REG_ADDR + 0x018)
-
-#define RAD0_ERR_STS                   (RAD0_BLK_REG_ADDR + 0x01C)
-#define RAD0_SET_ERR_STS               (RAD0_BLK_REG_ADDR + 0x020)
-#define RAD0_ERR_INT_EN                        (RAD0_BLK_REG_ADDR + 0x024)
-#define RAD0_FIRST_ERR                 (RAD0_BLK_REG_ADDR + 0x028)
-#define RAD0_FORCE_ERR                 (RAD0_BLK_REG_ADDR + 0x02C)
-
-#define RAD0_IF_RCVD                   (RAD0_BLK_REG_ADDR + 0x030)
-#define RAD0_IF_RCVD_OCTETS_HIGH       (RAD0_BLK_REG_ADDR + 0x034)
-#define RAD0_IF_RCVD_OCTETS_LOW                (RAD0_BLK_REG_ADDR + 0x038)
-#define RAD0_IF_RCVD_VLAN              (RAD0_BLK_REG_ADDR + 0x03C)
-#define RAD0_IF_RCVD_UCAST             (RAD0_BLK_REG_ADDR + 0x040)
-#define RAD0_IF_RCVD_UCAST_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x044)
-#define RAD0_IF_RCVD_UCAST_OCTETS_LOW   (RAD0_BLK_REG_ADDR + 0x048)
-#define RAD0_IF_RCVD_UCAST_VLAN                (RAD0_BLK_REG_ADDR + 0x04C)
-#define RAD0_IF_RCVD_MCAST             (RAD0_BLK_REG_ADDR + 0x050)
-#define RAD0_IF_RCVD_MCAST_OCTETS_HIGH  (RAD0_BLK_REG_ADDR + 0x054)
-#define RAD0_IF_RCVD_MCAST_OCTETS_LOW   (RAD0_BLK_REG_ADDR + 0x058)
-#define RAD0_IF_RCVD_MCAST_VLAN                (RAD0_BLK_REG_ADDR + 0x05C)
-#define RAD0_IF_RCVD_BCAST             (RAD0_BLK_REG_ADDR + 0x060)
-#define RAD0_IF_RCVD_BCAST_OCTETS_HIGH  (RAD0_BLK_REG_ADDR + 0x064)
-#define RAD0_IF_RCVD_BCAST_OCTETS_LOW   (RAD0_BLK_REG_ADDR + 0x068)
-#define RAD0_IF_RCVD_BCAST_VLAN                (RAD0_BLK_REG_ADDR + 0x06C)
-#define RAD0_DROPPED_FRAMES            (RAD0_BLK_REG_ADDR + 0x070)
-
-#define RAD0_MAC_MAN_1H                        (RAD0_BLK_REG_ADDR + 0x080)
-#define RAD0_MAC_MAN_1L                        (RAD0_BLK_REG_ADDR + 0x084)
-#define RAD0_MAC_MAN_2H                        (RAD0_BLK_REG_ADDR + 0x088)
-#define RAD0_MAC_MAN_2L                        (RAD0_BLK_REG_ADDR + 0x08C)
-#define RAD0_MAC_MAN_3H                        (RAD0_BLK_REG_ADDR + 0x090)
-#define RAD0_MAC_MAN_3L                        (RAD0_BLK_REG_ADDR + 0x094)
-#define RAD0_MAC_MAN_4H                        (RAD0_BLK_REG_ADDR + 0x098)
-#define RAD0_MAC_MAN_4L                        (RAD0_BLK_REG_ADDR + 0x09C)
-
-#define RAD0_LAST4_IP                  (RAD0_BLK_REG_ADDR + 0x100)
-
-/* RAD1 Registers */
-#define RAD1_CTL_REG                   (RAD1_BLK_REG_ADDR + 0x000)
-#define RAD1_PE_PARM_REG               (RAD1_BLK_REG_ADDR + 0x004)
-#define RAD1_BCN_REG                   (RAD1_BLK_REG_ADDR + 0x008)
-
-/* Default function ID register */
-#define RAD1_DEFAULT_REG               (RAD1_BLK_REG_ADDR + 0x00C)
-
-/* Promiscuous function ID register */
-#define RAD1_PROMISC_REG               (RAD1_BLK_REG_ADDR + 0x010)
-
-#define RAD1_BCNQ_REG                  (RAD1_BLK_REG_ADDR + 0x014)
-
-/*
- * This register selects 1 of 8 PM Q's using
- * VLAN pri, for non-BCN packets without a VLAN tag
- */
-#define RAD1_DEFAULTQ_REG              (RAD1_BLK_REG_ADDR + 0x018)
-
-#define RAD1_ERR_STS                   (RAD1_BLK_REG_ADDR + 0x01C)
-#define RAD1_SET_ERR_STS               (RAD1_BLK_REG_ADDR + 0x020)
-#define RAD1_ERR_INT_EN                        (RAD1_BLK_REG_ADDR + 0x024)
-
-/**
- * TXA Block Register Address Offset from BAR0
- * TXA0 Range : 0x21000 - 0x213FF
- * TXA1 Range : 0x21400 - 0x217FF
- */
-#define TXA0_BLK_REG_ADDR              0x00021000
-#define TXA1_BLK_REG_ADDR              0x00021400
-
-/* TXA Registers */
-#define TXA0_CTRL_REG                  (TXA0_BLK_REG_ADDR + 0x000)
-#define TXA1_CTRL_REG                  (TXA1_BLK_REG_ADDR + 0x000)
-
-/**
- * TSO Sequence # Registers (RO)
- * Total 8 (for 8 queues)
- * Holds the last seq.# for TSO frames
- * See catapult_spec.pdf for more details
- */
-#define TXA0_TSO_TCP_SEQ_REG(_num)             \
-       (TXA0_BLK_REG_ADDR + 0x020 + ((_num) << 2))
-
-#define TXA1_TSO_TCP_SEQ_REG(_num)             \
-       (TXA1_BLK_REG_ADDR + 0x020 + ((_num) << 2))
-
-/**
- * TSO IP ID # Registers (RO)
- * Total 8 (for 8 queues)
- * Holds the last IP ID for TSO frames
- * See catapult_spec.pdf for more details
- */
-#define TXA0_TSO_IP_INFO_REG(_num)             \
-       (TXA0_BLK_REG_ADDR + 0x040 + ((_num) << 2))
-
-#define TXA1_TSO_IP_INFO_REG(_num)             \
-       (TXA1_BLK_REG_ADDR + 0x040 + ((_num) << 2))
-
-/**
- * RXA Block Register Address Offset from BAR0
- * RXA0 Range : 0x21800 - 0x21BFF
- * RXA1 Range : 0x21C00 - 0x21FFF
- */
-#define RXA0_BLK_REG_ADDR              0x00021800
-#define RXA1_BLK_REG_ADDR              0x00021C00
-
-/* RXA Registers */
-#define RXA0_CTL_REG                   (RXA0_BLK_REG_ADDR + 0x040)
-#define RXA1_CTL_REG                   (RXA1_BLK_REG_ADDR + 0x040)
-
-/**
- * PPLB Block Register Address Offset from BAR0
- * PPLB0 Range : 0x22000 - 0x223FF
- * PPLB1 Range : 0x22400 - 0x227FF
- */
-#define PLB0_BLK_REG_ADDR              0x00022000
-#define PLB1_BLK_REG_ADDR              0x00022400
-
-/**
- * PLB Registers
- * Holds RL timer used time stamps in RLT tagged frames
- */
-#define PLB0_ECM_TIMER_REG             (PLB0_BLK_REG_ADDR + 0x05C)
-#define PLB1_ECM_TIMER_REG             (PLB1_BLK_REG_ADDR + 0x05C)
-
-/* Controls the rate-limiter on each of the priority class */
-#define PLB0_RL_CTL                    (PLB0_BLK_REG_ADDR + 0x060)
-#define PLB1_RL_CTL                    (PLB1_BLK_REG_ADDR + 0x060)
-
-/**
- * Max byte register, total 8, 0-7
- * see catapult_spec.pdf for details
- */
-#define PLB0_RL_MAX_BC(_num)                   \
-       (PLB0_BLK_REG_ADDR + 0x064 + ((_num) << 2))
-#define PLB1_RL_MAX_BC(_num)                   \
-       (PLB1_BLK_REG_ADDR + 0x064 + ((_num) << 2))
-
-/**
- * RL Time Unit Register for priority 0-7
- * 4 bits per priority
- * (2^rl_unit)*1us is the actual time period
- */
-#define PLB0_RL_TU_PRIO                        (PLB0_BLK_REG_ADDR + 0x084)
-#define PLB1_RL_TU_PRIO                        (PLB1_BLK_REG_ADDR + 0x084)
-
-/**
- * RL byte count register,
- * bytes transmitted in (rl_unit*1)us time period
- * 1 per priority, 8 in all, 0-7.
- */
-#define PLB0_RL_BYTE_CNT(_num)                 \
-       (PLB0_BLK_REG_ADDR + 0x088 + ((_num) << 2))
-#define PLB1_RL_BYTE_CNT(_num)                 \
-       (PLB1_BLK_REG_ADDR + 0x088 + ((_num) << 2))
-
-/**
- * RL Min factor register
- * 2 bits per priority,
- * 4 factors possible: 1, 0.5, 0.25, 0
- * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1
- */
-#define PLB0_RL_MIN_REG                        (PLB0_BLK_REG_ADDR + 0x0A8)
-#define PLB1_RL_MIN_REG                        (PLB1_BLK_REG_ADDR + 0x0A8)
-
-/**
- * RL Max factor register
- * 2 bits per priority,
- * 4 factors possible: 1, 0.5, 0.25, 0
- * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1
- */
-#define PLB0_RL_MAX_REG                        (PLB0_BLK_REG_ADDR + 0x0AC)
-#define PLB1_RL_MAX_REG                        (PLB1_BLK_REG_ADDR + 0x0AC)
-
-/* MAC SERDES Address Paging register */
-#define PLB0_EMS_ADD_REG               (PLB0_BLK_REG_ADDR + 0xD0)
-#define PLB1_EMS_ADD_REG               (PLB1_BLK_REG_ADDR + 0xD0)
-
-/* LL EMS Registers */
-#define LL_EMS0_BLK_REG_ADDR           0x00026800
-#define LL_EMS1_BLK_REG_ADDR           0x00026C00
-
-/**
- * BPC Block Register Address Offset from BAR0
- * BPC0 Range : 0x23000 - 0x233FF
- * BPC1 Range : 0x23400 - 0x237FF
- */
-#define BPC0_BLK_REG_ADDR              0x00023000
-#define BPC1_BLK_REG_ADDR              0x00023400
-
-/**
- * PMM Block Register Address Offset from BAR0
- * PMM0 Range : 0x23800 - 0x23BFF
- * PMM1 Range : 0x23C00 - 0x23FFF
- */
-#define PMM0_BLK_REG_ADDR              0x00023800
-#define PMM1_BLK_REG_ADDR              0x00023C00
-
-/**
- * HQM Block Register Address Offset from BAR0
- * HQM0 Range : 0x24000 - 0x243FF
- * HQM1 Range : 0x24400 - 0x247FF
- */
-#define HQM0_BLK_REG_ADDR              0x00024000
-#define HQM1_BLK_REG_ADDR              0x00024400
-
-/**
- * HQM Control Register
- * Controls some aspects of IB
- * See catapult_spec.pdf for details
- */
-#define HQM0_CTL_REG                   (HQM0_BLK_REG_ADDR + 0x000)
-#define HQM1_CTL_REG                   (HQM1_BLK_REG_ADDR + 0x000)
-
-/**
- * HQM Stop Q Semaphore Registers.
- * Only one Queue resource can be stopped at
- * any given time. This register controls access
- * to the single stop Q resource.
- * See catapult_spec.pdf for details
- */
-#define HQM0_RXQ_STOP_SEM              (HQM0_BLK_REG_ADDR + 0x028)
-#define HQM0_TXQ_STOP_SEM              (HQM0_BLK_REG_ADDR + 0x02C)
-#define HQM1_RXQ_STOP_SEM              (HQM1_BLK_REG_ADDR + 0x028)
-#define HQM1_TXQ_STOP_SEM              (HQM1_BLK_REG_ADDR + 0x02C)
-
-/**
- * LUT Block Register Address Offset from BAR0
- * LUT0 Range : 0x25800 - 0x25BFF
- * LUT1 Range : 0x25C00 - 0x25FFF
- */
-#define LUT0_BLK_REG_ADDR              0x00025800
-#define LUT1_BLK_REG_ADDR              0x00025C00
-
-/**
- * LUT Registers
- * See catapult_spec.pdf for details
- */
-#define LUT0_ERR_STS                   (LUT0_BLK_REG_ADDR + 0x000)
-#define LUT1_ERR_STS                   (LUT1_BLK_REG_ADDR + 0x000)
-#define LUT0_SET_ERR_STS               (LUT0_BLK_REG_ADDR + 0x004)
-#define LUT1_SET_ERR_STS               (LUT1_BLK_REG_ADDR + 0x004)
-
-/**
- * TRC (Debug/Trace) Register Offset from BAR0
- * Range : 0x26000 -- 0x263FFF
- */
-#define TRC_BLK_REG_ADDR               0x00026000
-
-/**
- * TRC Registers
- * See catapult_spec.pdf for details of each
- */
-#define TRC_CTL_REG                    (TRC_BLK_REG_ADDR + 0x000)
-#define TRC_MODS_REG                   (TRC_BLK_REG_ADDR + 0x004)
-#define TRC_TRGC_REG                   (TRC_BLK_REG_ADDR + 0x008)
-#define TRC_CNT1_REG                   (TRC_BLK_REG_ADDR + 0x010)
-#define TRC_CNT2_REG                   (TRC_BLK_REG_ADDR + 0x014)
-#define TRC_NXTS_REG                   (TRC_BLK_REG_ADDR + 0x018)
-#define TRC_DIRR_REG                   (TRC_BLK_REG_ADDR + 0x01C)
-
-/**
- * TRC Trigger match filters, total 10
- * Determines the trigger condition
- */
-#define TRC_TRGM_REG(_num)             \
-       (TRC_BLK_REG_ADDR + 0x040 + ((_num) << 2))
-
-/**
- * TRC Next State filters, total 10
- * Determines the next state conditions
- */
-#define TRC_NXTM_REG(_num)             \
-       (TRC_BLK_REG_ADDR + 0x080 + ((_num) << 2))
-
-/**
- * TRC Store Match filters, total 10
- * Determines the store conditions
- */
-#define TRC_STRM_REG(_num)             \
-       (TRC_BLK_REG_ADDR + 0x0C0 + ((_num) << 2))
-
-/* DOORBELLS ACCESS */
-
-/**
- * Catapult doorbells
- * Each doorbell-queue set has
- * 1 RxQ, 1 TxQ, 2 IBs in that order
- * Size of each entry in 32 bytes, even though only 1 word
- * is used. For Non-VM case each doorbell-q set is
- * separated by 128 bytes, for VM case it is separated
- * by 4K bytes
- * Non VM case Range : 0x38000 - 0x39FFF
- * VM case Range     : 0x100000 - 0x11FFFF
- * The range applies to both HQMs
- */
-#define HQM_DOORBELL_BLK_BASE_ADDR     0x00038000
-#define HQM_DOORBELL_VM_BLK_BASE_ADDR  0x00100000
-
-/* MEMORY ACCESS */
-
-/**
- * Catapult H/W Block Memory Access Address
- * To the host a memory space of 32K (page) is visible
- * at a time. The address range is from 0x08000 to 0x0FFFF
- */
-#define HW_BLK_HOST_MEM_ADDR           0x08000
-
-/**
- * Catapult LUT Memory Access Page Numbers
- * Range : LUT0 0xa0-0xa1
- *         LUT1 0xa2-0xa3
- */
-#define LUT0_MEM_BLK_BASE_PG_NUM       0x000000A0
-#define LUT1_MEM_BLK_BASE_PG_NUM       0x000000A2
-
-/**
- * Catapult RxFn Database Memory Block Base Offset
- *
- * The Rx function database exists in LUT block.
- * In PCIe space this is accessible as a 256x32
- * bit block. Each entry in this database is 4
- * (4 byte) words. Max. entries is 64.
- * Address of an entry corresponding to a function
- * = base_addr + (function_no. * 16)
- */
-#define RX_FNDB_RAM_BASE_OFFSET                0x0000B400
-
-/**
- * Catapult TxFn Database Memory Block Base Offset Address
- *
- * The Tx function database exists in LUT block.
- * In PCIe space this is accessible as a 64x32
- * bit block. Each entry in this database is 1
- * (4 byte) word. Max. entries is 64.
- * Address of an entry corresponding to a function
- * = base_addr + (function_no. * 4)
- */
-#define TX_FNDB_RAM_BASE_OFFSET                0x0000B800
-
-/**
- * Catapult Unicast CAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Shared by both the LL & FCoE driver.
- * Size is 256x48 bits; mapped to PCIe space
- * 512x32 bit blocks. For each address, bits
- * are written in the order : [47:32] and then
- * [31:0].
- */
-#define UCAST_CAM_BASE_OFFSET          0x0000A800
-
-/**
- * Catapult Unicast RAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Shared by both the LL & FCoE driver.
- * Size is 256x9 bits.
- */
-#define UCAST_RAM_BASE_OFFSET          0x0000B000
-
-/**
- * Catapult Mulicast CAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Shared by both the LL & FCoE driver.
- * Size is 256x48 bits; mapped to PCIe space
- * 512x32 bit blocks. For each address, bits
- * are written in the order : [47:32] and then
- * [31:0].
- */
-#define MCAST_CAM_BASE_OFFSET          0x0000A000
-
-/**
- * Catapult VLAN RAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Size is 4096x66 bits; mapped to PCIe space as
- * 8192x32 bit blocks.
- * All the 4K entries are within the address range
- * 0x0000 to 0x8000, so in the first LUT page.
- */
-#define VLAN_RAM_BASE_OFFSET           0x00000000
-
-/**
- * Catapult Tx Stats RAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Size is 1024x33 bits;
- * Each Tx function has 64 bytes of space
- */
-#define TX_STATS_RAM_BASE_OFFSET       0x00009000
-
-/**
- * Catapult Rx Stats RAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Size is 1024x33 bits;
- * Each Rx function has 64 bytes of space
- */
-#define RX_STATS_RAM_BASE_OFFSET       0x00008000
-
-/* Catapult RXA Memory Access Page Numbers */
-#define RXA0_MEM_BLK_BASE_PG_NUM       0x0000008C
-#define RXA1_MEM_BLK_BASE_PG_NUM       0x0000008D
-
-/**
- * Catapult Multicast Vector Table Base Offset Address
- *
- * Exists in RxA memory space.
- * Organized as 512x65 bit block.
- * However for each entry 16 bytes allocated (power of 2)
- * Total size 512*16 bytes.
- * There are two logical divisions, 256 entries each :
- * a) Entries 0x00 to 0xff (256) -- Approx. MVT
- *    Offset 0x000 to 0xFFF
- * b) Entries 0x100 to 0x1ff (256) -- Exact MVT
- *    Offsets 0x1000 to 0x1FFF
- */
-#define MCAST_APPROX_MVT_BASE_OFFSET   0x00000000
-#define MCAST_EXACT_MVT_BASE_OFFSET    0x00001000
-
-/**
- * Catapult RxQ Translate Table (RIT) Base Offset Address
- *
- * Exists in RxA memory space
- * Total no. of entries 64
- * Each entry is 1 (4 byte) word.
- * 31:12 -- Reserved
- * 11:0  -- Two 6 bit RxQ Ids
- */
-#define FUNCTION_TO_RXQ_TRANSLATE      0x00002000
-
-/* Catapult RxAdm (RAD) Memory Access Page Numbers */
-#define RAD0_MEM_BLK_BASE_PG_NUM       0x00000086
-#define RAD1_MEM_BLK_BASE_PG_NUM       0x00000087
-
-/**
- * Catapult RSS Table Base Offset Address
- *
- * Exists in RAD memory space.
- * Each entry is 352 bits, but aligned on
- * 64 byte (512 bit) boundary. Accessed
- * 4 byte words, the whole entry can be
- * broken into 11 word accesses.
- */
-#define RSS_TABLE_BASE_OFFSET          0x00000800
-
-/**
- * Catapult CPQ Block Page Number
- * This value is written to the page number registers
- * to access the memory associated with the mailboxes.
- */
-#define CPQ_BLK_PG_NUM                 0x00000005
-
-/**
- * Clarification :
- * LL functions are 2 & 3; can HostFn0/HostFn1
- * <-> LPU0/LPU1 memories be used ?
- */
-/**
- * Catapult HostFn0/HostFn1 to LPU0/LPU1 Mbox memory
- * Per catapult_spec.pdf, the offset of the mbox
- * memory is in the register space at an offset of 0x200
- */
-#define CPQ_BLK_REG_MBOX_ADDR          (CPQ_BLK_REG_ADDR + 0x200)
-
-#define HOSTFN_LPU_MBOX                        (CPQ_BLK_REG_MBOX_ADDR + 0x000)
-
-/* Catapult LPU0/LPU1 to HostFn0/HostFn1 Mbox memory */
-#define LPU_HOSTFN_MBOX                        (CPQ_BLK_REG_MBOX_ADDR + 0x080)
-
-/**
- * Catapult HQM Block Page Number
- * This is written to the page number register for
- * the appropriate function to access the memory
- * associated with HQM
- */
-#define HQM0_BLK_PG_NUM                        0x00000096
-#define HQM1_BLK_PG_NUM                        0x00000097
-
-/**
- * Note that TxQ and RxQ entries are interlaced
- * the HQM memory, i.e RXQ0, TXQ0, RXQ1, TXQ1.. etc.
- */
-
-#define HQM_RXTX_Q_RAM_BASE_OFFSET     0x00004000
-
-/**
- * CQ Memory
- * Exists in HQM Memory space
- * Each entry is 16 (4 byte) words of which
- * only 12 words are used for configuration
- * Total 64 entries per HQM memory space
- */
-#define HQM_CQ_RAM_BASE_OFFSET         0x00006000
-
-/**
- * Interrupt Block (IB) Memory
- * Exists in HQM Memory space
- * Each entry is 8 (4 byte) words of which
- * only 5 words are used for configuration
- * Total 128 entries per HQM memory space
- */
-#define HQM_IB_RAM_BASE_OFFSET         0x00001000
-
-/**
- * Index Table (IT) Memory
- * Exists in HQM Memory space
- * Each entry is 1 (4 byte) word which
- * is used for configuration
- * Total 128 entries per HQM memory space
- */
-#define HQM_INDX_TBL_RAM_BASE_OFFSET   0x00002000
-
-/**
- * PSS Block Memory Page Number
- * This is written to the appropriate page number
- * register to access the CPU memory.
- * Also known as the PSS secondary memory (SMEM).
- * Range : 0x180 to 0x1CF
- * See catapult_spec.pdf for details
- */
-#define PSS_BLK_PG_NUM                 0x00000180
-
-/**
- * Offsets of different instances of PSS SMEM
- * 2.5M of continuous 1T memory space : 2 blocks
- * of 1M each (32 pages each, page=32KB) and 4 smaller
- * blocks of 128K each (4 pages each, page=32KB)
- * PSS_LMEM_INST0 is used for firmware download
- */
-#define PSS_LMEM_INST0                 0x00000000
-#define PSS_LMEM_INST1                 0x00100000
-#define PSS_LMEM_INST2                 0x00200000
-#define PSS_LMEM_INST3                 0x00220000
-#define PSS_LMEM_INST4                 0x00240000
-#define PSS_LMEM_INST5                 0x00260000
-
-#define BNA_PCI_REG_CT_ADDRSZ          (0x40000)
-
-#define BNA_GET_PAGE_NUM(_base_page, _offset)   \
-       ((_base_page) + ((_offset) >> 15))
-
-#define BNA_GET_PAGE_OFFSET(_offset)    \
-       ((_offset) & 0x7fff)
-
-#define BNA_GET_MEM_BASE_ADDR(_bar0, _base_offset)     \
-       ((_bar0) + HW_BLK_HOST_MEM_ADDR         \
-         + BNA_GET_PAGE_OFFSET((_base_offset)))
-
-#define BNA_GET_VLAN_MEM_ENTRY_ADDR(_bar0, _fn_id, _vlan_id)\
-       (_bar0 + (HW_BLK_HOST_MEM_ADDR)  \
-       + (BNA_GET_PAGE_OFFSET(VLAN_RAM_BASE_OFFSET))   \
-       + (((_fn_id) & 0x3f) << 9)        \
-       + (((_vlan_id) & 0xfe0) >> 3))
-
-/**
- *
- *  Interrupt related bits, flags and macros
- *
- */
-
-#define __LPU02HOST_MBOX0_STATUS_BITS 0x00100000
-#define __LPU12HOST_MBOX0_STATUS_BITS 0x00200000
-#define __LPU02HOST_MBOX1_STATUS_BITS 0x00400000
-#define __LPU12HOST_MBOX1_STATUS_BITS 0x00800000
-
-#define __LPU02HOST_MBOX0_MASK_BITS    0x00100000
-#define __LPU12HOST_MBOX0_MASK_BITS    0x00200000
-#define __LPU02HOST_MBOX1_MASK_BITS    0x00400000
-#define __LPU12HOST_MBOX1_MASK_BITS    0x00800000
-
-#define __LPU2HOST_MBOX_MASK_BITS                       \
-       (__LPU02HOST_MBOX0_MASK_BITS | __LPU02HOST_MBOX1_MASK_BITS |    \
-         __LPU12HOST_MBOX0_MASK_BITS | __LPU12HOST_MBOX1_MASK_BITS)
-
-#define __LPU2HOST_IB_STATUS_BITS      0x0000ffff
-
-#define BNA_IS_LPU0_MBOX_INTR(_intr_status) \
-       ((_intr_status) & (__LPU02HOST_MBOX0_STATUS_BITS | \
-                       __LPU02HOST_MBOX1_STATUS_BITS))
-
-#define BNA_IS_LPU1_MBOX_INTR(_intr_status) \
-       ((_intr_status) & (__LPU12HOST_MBOX0_STATUS_BITS | \
-               __LPU12HOST_MBOX1_STATUS_BITS))
-
-#define BNA_IS_MBOX_INTR(_intr_status)         \
-       ((_intr_status) &                       \
-       (__LPU02HOST_MBOX0_STATUS_BITS |        \
-        __LPU02HOST_MBOX1_STATUS_BITS |        \
-        __LPU12HOST_MBOX0_STATUS_BITS |        \
-        __LPU12HOST_MBOX1_STATUS_BITS))
-
-#define __EMC_ERROR_STATUS_BITS                0x00010000
-#define __LPU0_ERROR_STATUS_BITS       0x00020000
-#define __LPU1_ERROR_STATUS_BITS       0x00040000
-#define __PSS_ERROR_STATUS_BITS                0x00080000
-
-#define __HALT_STATUS_BITS             0x01000000
-
-#define __EMC_ERROR_MASK_BITS          0x00010000
-#define __LPU0_ERROR_MASK_BITS         0x00020000
-#define __LPU1_ERROR_MASK_BITS         0x00040000
-#define __PSS_ERROR_MASK_BITS          0x00080000
-
-#define __HALT_MASK_BITS               0x01000000
-
-#define __ERROR_MASK_BITS              \
-       (__EMC_ERROR_MASK_BITS | __LPU0_ERROR_MASK_BITS | \
-         __LPU1_ERROR_MASK_BITS | __PSS_ERROR_MASK_BITS | \
-         __HALT_MASK_BITS)
-
-#define BNA_IS_ERR_INTR(_intr_status)  \
-       ((_intr_status) &               \
-       (__EMC_ERROR_STATUS_BITS |      \
-        __LPU0_ERROR_STATUS_BITS |     \
-        __LPU1_ERROR_STATUS_BITS |     \
-        __PSS_ERROR_STATUS_BITS  |     \
-        __HALT_STATUS_BITS))
-
-#define BNA_IS_MBOX_ERR_INTR(_intr_status)     \
-       (BNA_IS_MBOX_INTR((_intr_status)) |     \
-        BNA_IS_ERR_INTR((_intr_status)))
-
-#define BNA_IS_INTX_DATA_INTR(_intr_status)    \
-       ((_intr_status) & __LPU2HOST_IB_STATUS_BITS)
-
-#define BNA_INTR_STATUS_MBOX_CLR(_intr_status)                 \
-do {                                                           \
-       (_intr_status) &= ~(__LPU02HOST_MBOX0_STATUS_BITS |     \
-                       __LPU02HOST_MBOX1_STATUS_BITS |         \
-                       __LPU12HOST_MBOX0_STATUS_BITS |         \
-                       __LPU12HOST_MBOX1_STATUS_BITS);         \
-} while (0)
-
-#define BNA_INTR_STATUS_ERR_CLR(_intr_status)          \
-do {                                                   \
-       (_intr_status) &= ~(__EMC_ERROR_STATUS_BITS |   \
-               __LPU0_ERROR_STATUS_BITS |              \
-               __LPU1_ERROR_STATUS_BITS |              \
-               __PSS_ERROR_STATUS_BITS  |              \
-               __HALT_STATUS_BITS);                    \
-} while (0)
-
-#define bna_intx_disable(_bna, _cur_mask)              \
-{                                                      \
-       (_cur_mask) = readl((_bna)->regs.fn_int_mask);\
-       writel(0xffffffff, (_bna)->regs.fn_int_mask);\
-}
-
-#define bna_intx_enable(bna, new_mask)                 \
-       writel((new_mask), (bna)->regs.fn_int_mask)
-
-#define bna_mbox_intr_disable(bna)             \
-       writel((readl((bna)->regs.fn_int_mask) | \
-            (__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)), \
-            (bna)->regs.fn_int_mask)
-
-#define bna_mbox_intr_enable(bna)              \
-       writel((readl((bna)->regs.fn_int_mask) & \
-            ~(__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)), \
-            (bna)->regs.fn_int_mask)
-
-#define bna_intr_status_get(_bna, _status)                             \
-{                                                                      \
-       (_status) = readl((_bna)->regs.fn_int_status);          \
-       if ((_status)) {                                                \
-               writel((_status) & ~(__LPU02HOST_MBOX0_STATUS_BITS |\
-                                         __LPU02HOST_MBOX1_STATUS_BITS |\
-                                         __LPU12HOST_MBOX0_STATUS_BITS |\
-                                         __LPU12HOST_MBOX1_STATUS_BITS), \
-                             (_bna)->regs.fn_int_status);\
-       }                                                               \
-}
-
-#define bna_intr_status_get_no_clr(_bna, _status)              \
-       (_status) = readl((_bna)->regs.fn_int_status)
-
-#define bna_intr_mask_get(bna, mask)           \
-       (*mask) = readl((bna)->regs.fn_int_mask)
-
-#define bna_intr_ack(bna, intr_bmap)           \
-       writel((intr_bmap), (bna)->regs.fn_int_status)
-
-#define bna_ib_intx_disable(bna, ib_id)                \
-       writel(readl((bna)->regs.fn_int_mask) | \
-           (1 << (ib_id)), \
-           (bna)->regs.fn_int_mask)
-
-#define bna_ib_intx_enable(bna, ib_id)         \
-       writel(readl((bna)->regs.fn_int_mask) & \
-           ~(1 << (ib_id)), \
-           (bna)->regs.fn_int_mask)
-
-#define bna_mbox_msix_idx_set(_device) \
-do {\
-       writel(((_device)->vector & 0x000001FF), \
-               (_device)->bna->pcidev.pci_bar_kva + \
-               reg_offset[(_device)->bna->pcidev.pci_func].msix_idx);\
-} while (0)
-
-/**
- *
- * TxQ, RxQ, CQ related bits, offsets, macros
- *
- */
-
-#define        BNA_Q_IDLE_STATE        0x00008001
-
-#define BNA_GET_DOORBELL_BASE_ADDR(_bar0)      \
-       ((_bar0) + HQM_DOORBELL_BLK_BASE_ADDR)
-
-#define BNA_GET_DOORBELL_ENTRY_OFFSET(_entry)          \
-       ((HQM_DOORBELL_BLK_BASE_ADDR)           \
-       + (_entry << 7))
-
-#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
-               (0x80000000 | ((_timeout) << 16) | (_events))
-
-#define BNA_DOORBELL_IB_INT_DISABLE            (0x40000000)
-
-/* TxQ Entry Opcodes */
-#define BNA_TXQ_WI_SEND                        (0x402) /* Single Frame Transmission */
-#define BNA_TXQ_WI_SEND_LSO            (0x403) /* Multi-Frame Transmission */
-#define BNA_TXQ_WI_EXTENSION           (0x104) /* Extension WI */
-
-/* TxQ Entry Control Flags */
-#define BNA_TXQ_WI_CF_FCOE_CRC         (1 << 8)
-#define BNA_TXQ_WI_CF_IPID_MODE                (1 << 5)
-#define BNA_TXQ_WI_CF_INS_PRIO         (1 << 4)
-#define BNA_TXQ_WI_CF_INS_VLAN         (1 << 3)
-#define BNA_TXQ_WI_CF_UDP_CKSUM                (1 << 2)
-#define BNA_TXQ_WI_CF_TCP_CKSUM                (1 << 1)
-#define BNA_TXQ_WI_CF_IP_CKSUM         (1 << 0)
-
-#define BNA_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \
-               (((_hdr_size) << 10) | ((_offset) & 0x3FF))
-
-/*
- * Completion Q defines
- */
-/* CQ Entry Flags */
-#define        BNA_CQ_EF_MAC_ERROR     (1 <<  0)
-#define        BNA_CQ_EF_FCS_ERROR     (1 <<  1)
-#define        BNA_CQ_EF_TOO_LONG      (1 <<  2)
-#define        BNA_CQ_EF_FC_CRC_OK     (1 <<  3)
-
-#define        BNA_CQ_EF_RSVD1         (1 <<  4)
-#define        BNA_CQ_EF_L4_CKSUM_OK   (1 <<  5)
-#define        BNA_CQ_EF_L3_CKSUM_OK   (1 <<  6)
-#define        BNA_CQ_EF_HDS_HEADER    (1 <<  7)
-
-#define        BNA_CQ_EF_UDP           (1 <<  8)
-#define        BNA_CQ_EF_TCP           (1 <<  9)
-#define        BNA_CQ_EF_IP_OPTIONS    (1 << 10)
-#define        BNA_CQ_EF_IPV6          (1 << 11)
-
-#define        BNA_CQ_EF_IPV4          (1 << 12)
-#define        BNA_CQ_EF_VLAN          (1 << 13)
-#define        BNA_CQ_EF_RSS           (1 << 14)
-#define        BNA_CQ_EF_RSVD2         (1 << 15)
-
-#define        BNA_CQ_EF_MCAST_MATCH   (1 << 16)
-#define        BNA_CQ_EF_MCAST         (1 << 17)
-#define BNA_CQ_EF_BCAST                (1 << 18)
-#define        BNA_CQ_EF_REMOTE        (1 << 19)
-
-#define        BNA_CQ_EF_LOCAL         (1 << 20)
-
-/**
- *
- * Data structures
- *
- */
-
-enum txf_flags {
-       BFI_TXF_CF_ENABLE               = 1 << 0,
-       BFI_TXF_CF_VLAN_FILTER          = 1 << 8,
-       BFI_TXF_CF_VLAN_ADMIT           = 1 << 9,
-       BFI_TXF_CF_VLAN_INSERT          = 1 << 10,
-       BFI_TXF_CF_RSVD1                = 1 << 11,
-       BFI_TXF_CF_MAC_SA_CHECK         = 1 << 12,
-       BFI_TXF_CF_VLAN_WI_BASED        = 1 << 13,
-       BFI_TXF_CF_VSWITCH_MCAST        = 1 << 14,
-       BFI_TXF_CF_VSWITCH_UCAST        = 1 << 15,
-       BFI_TXF_CF_RSVD2                = 0x7F << 1
-};
-
-enum ib_flags {
-       BFI_IB_CF_MASTER_ENABLE         = (1 << 0),
-       BFI_IB_CF_MSIX_MODE             = (1 << 1),
-       BFI_IB_CF_COALESCING_MODE       = (1 << 2),
-       BFI_IB_CF_INTER_PKT_ENABLE      = (1 << 3),
-       BFI_IB_CF_INT_ENABLE            = (1 << 4),
-       BFI_IB_CF_INTER_PKT_DMA         = (1 << 5),
-       BFI_IB_CF_ACK_PENDING           = (1 << 6),
-       BFI_IB_CF_RESERVED1             = (1 << 7)
-};
-
-enum rss_hash_type {
-       BFI_RSS_T_V4_TCP                = (1 << 11),
-       BFI_RSS_T_V4_IP                 = (1 << 10),
-       BFI_RSS_T_V6_TCP                = (1 <<  9),
-       BFI_RSS_T_V6_IP                 = (1 <<  8)
-};
-enum hds_header_type {
-       BNA_HDS_T_V4_TCP        = (1 << 11),
-       BNA_HDS_T_V4_UDP        = (1 << 10),
-       BNA_HDS_T_V6_TCP        = (1 << 9),
-       BNA_HDS_T_V6_UDP        = (1 << 8),
-       BNA_HDS_FORCED          = (1 << 7),
-};
-enum rxf_flags {
-       BNA_RXF_CF_SM_LG_RXQ                    = (1 << 15),
-       BNA_RXF_CF_DEFAULT_VLAN                 = (1 << 14),
-       BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE      = (1 << 13),
-       BNA_RXF_CF_VLAN_STRIP                   = (1 << 12),
-       BNA_RXF_CF_RSS_ENABLE                   = (1 <<  8)
-};
-struct bna_chip_regs_offset {
-       u32 page_addr;
-       u32 fn_int_status;
-       u32 fn_int_mask;
-       u32 msix_idx;
-};
-
-struct bna_chip_regs {
-       void __iomem *page_addr;
-       void __iomem *fn_int_status;
-       void __iomem *fn_int_mask;
-};
-
-struct bna_txq_mem {
-       u32 pg_tbl_addr_lo;
-       u32 pg_tbl_addr_hi;
-       u32 cur_q_entry_lo;
-       u32 cur_q_entry_hi;
-       u32 reserved1;
-       u32 reserved2;
-       u32 pg_cnt_n_prd_ptr;   /* 31:16->total page count */
-                                       /* 15:0 ->producer pointer (index?) */
-       u32 entry_n_pg_size;    /* 31:16->entry size */
-                                       /* 15:0 ->page size */
-       u32 int_blk_n_cns_ptr;  /* 31:24->Int Blk Id;  */
-                                       /* 23:16->Int Blk Offset */
-                                       /* 15:0 ->consumer pointer(index?) */
-       u32 cns_ptr2_n_q_state; /* 31:16->cons. ptr 2; 15:0-> Q state */
-       u32 nxt_qid_n_fid_n_pri;        /* 17:10->next */
-                                       /* QId;9:3->FID;2:0->Priority */
-       u32 wvc_n_cquota_n_rquota; /* 31:24->WI Vector Count; */
-                                       /* 23:12->Cfg Quota; */
-                                       /* 11:0 ->Run Quota */
-       u32 reserved3[4];
-};
-
-struct bna_rxq_mem {
-       u32 pg_tbl_addr_lo;
-       u32 pg_tbl_addr_hi;
-       u32 cur_q_entry_lo;
-       u32 cur_q_entry_hi;
-       u32 reserved1;
-       u32 reserved2;
-       u32 pg_cnt_n_prd_ptr;   /* 31:16->total page count */
-                                       /* 15:0 ->producer pointer (index?) */
-       u32 entry_n_pg_size;    /* 31:16->entry size */
-                                       /* 15:0 ->page size */
-       u32 sg_n_cq_n_cns_ptr;  /* 31:28->reserved; 27:24->sg count */
-                                       /* 23:16->CQ; */
-                                       /* 15:0->consumer pointer(index?) */
-       u32 buf_sz_n_q_state;   /* 31:16->buffer size; 15:0-> Q state */
-       u32 next_qid;           /* 17:10->next QId */
-       u32 reserved3;
-       u32 reserved4[4];
-};
-
-struct bna_rxtx_q_mem {
-       struct bna_rxq_mem rxq;
-       struct bna_txq_mem txq;
-};
-
-struct bna_cq_mem {
-       u32 pg_tbl_addr_lo;
-       u32 pg_tbl_addr_hi;
-       u32 cur_q_entry_lo;
-       u32 cur_q_entry_hi;
-
-       u32 reserved1;
-       u32 reserved2;
-       u32 pg_cnt_n_prd_ptr;   /* 31:16->total page count */
-                                       /* 15:0 ->producer pointer (index?) */
-       u32 entry_n_pg_size;    /* 31:16->entry size */
-                                       /* 15:0 ->page size */
-       u32 int_blk_n_cns_ptr;  /* 31:24->Int Blk Id; */
-                                       /* 23:16->Int Blk Offset */
-                                       /* 15:0 ->consumer pointer(index?) */
-       u32 q_state;            /* 31:16->reserved; 15:0-> Q state */
-       u32 reserved3[2];
-       u32 reserved4[4];
-};
-
-struct bna_ib_blk_mem {
-       u32 host_addr_lo;
-       u32 host_addr_hi;
-       u32 clsc_n_ctrl_n_msix; /* 31:24->coalescing; */
-                                       /* 23:16->coalescing cfg; */
-                                       /* 15:8 ->control; */
-                                       /* 7:0 ->msix; */
-       u32 ipkt_n_ent_n_idxof;
-       u32 ipkt_cnt_cfg_n_unacked;
-
-       u32 reserved[3];
-};
-
-struct bna_idx_tbl_mem {
-       u32 idx;          /* !< 31:16->res;15:0->idx; */
-};
-
-struct bna_doorbell_qset {
-       u32 rxq[0x20 >> 2];
-       u32 txq[0x20 >> 2];
-       u32 ib0[0x20 >> 2];
-       u32 ib1[0x20 >> 2];
-};
-
-struct bna_rx_fndb_ram {
-       u32 rss_prop;
-       u32 size_routing_props;
-       u32 rit_hds_mcastq;
-       u32 control_flags;
-};
-
-struct bna_tx_fndb_ram {
-       u32 vlan_n_ctrl_flags;
-};
-
-/**
- * @brief
- *  Structure which maps to RxFn Indirection Table (RIT)
- *  Size : 1 word
- *  See catapult_spec.pdf, RxA for details
- */
-struct bna_rit_mem {
-       u32 rxq_ids;    /* !< 31:12->res;11:0->two 6 bit RxQ Ids */
-};
-
-/**
- * @brief
- *  Structure which maps to RSS Table entry
- *  Size : 16 words
- *  See catapult_spec.pdf, RAD for details
- */
-struct bna_rss_mem {
-       /*
-        * 31:12-> res
-        * 11:8 -> protocol type
-        *  7:0 -> hash index
-        */
-       u32 type_n_hash;
-       u32 hash_key[10];  /* !< 40 byte Toeplitz hash key */
-       u32 reserved[5];
-};
-
-/* TxQ Vector (a.k.a. Tx-Buffer Descriptor) */
-struct bna_dma_addr {
-       u32             msb;
-       u32             lsb;
-};
-
-struct bna_txq_wi_vector {
-       u16             reserved;
-       u16             length;         /* Only 14 LSB are valid */
-       struct bna_dma_addr host_addr; /* Tx-Buf DMA addr */
-};
-
-typedef u16 bna_txq_wi_opcode_t;
-
-typedef u16 bna_txq_wi_ctrl_flag_t;
-
-/**
- *  TxQ Entry Structure
- *
- *  BEWARE:  Load values into this structure with correct endianess.
- */
-struct bna_txq_entry {
-       union {
-               struct {
-                       u8 reserved;
-                       u8 num_vectors; /* number of vectors present */
-                       bna_txq_wi_opcode_t opcode; /* Either */
-                                                   /* BNA_TXQ_WI_SEND or */
-                                                   /* BNA_TXQ_WI_SEND_LSO */
-                       bna_txq_wi_ctrl_flag_t flags; /* OR of all the flags */
-                       u16 l4_hdr_size_n_offset;
-                       u16 vlan_tag;
-                       u16 lso_mss;    /* Only 14 LSB are valid */
-                       u32 frame_length;       /* Only 24 LSB are valid */
-               } wi;
-
-               struct {
-                       u16 reserved;
-                       bna_txq_wi_opcode_t opcode; /* Must be */
-                                                   /* BNA_TXQ_WI_EXTENSION */
-                       u32 reserved2[3];       /* Place holder for */
-                                               /* removed vector (12 bytes) */
-               } wi_ext;
-       } hdr;
-       struct bna_txq_wi_vector vector[4];
-};
-#define wi_hdr         hdr.wi
-#define wi_ext_hdr  hdr.wi_ext
-
-/* RxQ Entry Structure */
-struct bna_rxq_entry {         /* Rx-Buffer */
-       struct bna_dma_addr host_addr; /* Rx-Buffer DMA address */
-};
-
-typedef u32 bna_cq_e_flag_t;
-
-/* CQ Entry Structure */
-struct bna_cq_entry {
-       bna_cq_e_flag_t flags;
-       u16 vlan_tag;
-       u16 length;
-       u32 rss_hash;
-       u8 valid;
-       u8 reserved1;
-       u8 reserved2;
-       u8 rxq_id;
-};
-
-#endif /* __BNA_HW_H__ */
diff --git a/drivers/net/bna/bna_txrx.c b/drivers/net/bna/bna_txrx.c
deleted file mode 100644 (file)
index f0983c8..0000000
+++ /dev/null
@@ -1,4185 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * 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.
-  */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#include "bna.h"
-#include "bfa_cs.h"
-#include "bfi.h"
-
-/**
- * IB
- */
-#define bna_ib_find_free_ibidx(_mask, _pos)\
-do {\
-       (_pos) = 0;\
-       while (((_pos) < (BFI_IBIDX_MAX_SEGSIZE)) &&\
-               ((1 << (_pos)) & (_mask)))\
-               (_pos)++;\
-} while (0)
-
-#define bna_ib_count_ibidx(_mask, _count)\
-do {\
-       int pos = 0;\
-       (_count) = 0;\
-       while (pos < (BFI_IBIDX_MAX_SEGSIZE)) {\
-               if ((1 << pos) & (_mask))\
-                       (_count) = pos + 1;\
-               pos++;\
-       } \
-} while (0)
-
-#define bna_ib_select_segpool(_count, _q_idx)\
-do {\
-       int i;\
-       (_q_idx) = -1;\
-       for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {\
-               if ((_count <= ibidx_pool[i].pool_entry_size)) {\
-                       (_q_idx) = i;\
-                       break;\
-               } \
-       } \
-} while (0)
-
-struct bna_ibidx_pool {
-       int     pool_size;
-       int     pool_entry_size;
-};
-init_ibidx_pool(ibidx_pool);
-
-static struct bna_intr *
-bna_intr_get(struct bna_ib_mod *ib_mod, enum bna_intr_type intr_type,
-               int vector)
-{
-       struct bna_intr *intr;
-       struct list_head *qe;
-
-       list_for_each(qe, &ib_mod->intr_active_q) {
-               intr = (struct bna_intr *)qe;
-
-               if ((intr->intr_type == intr_type) &&
-                       (intr->vector == vector)) {
-                       intr->ref_count++;
-                       return intr;
-               }
-       }
-
-       if (list_empty(&ib_mod->intr_free_q))
-               return NULL;
-
-       bfa_q_deq(&ib_mod->intr_free_q, &intr);
-       bfa_q_qe_init(&intr->qe);
-
-       intr->ref_count = 1;
-       intr->intr_type = intr_type;
-       intr->vector = vector;
-
-       list_add_tail(&intr->qe, &ib_mod->intr_active_q);
-
-       return intr;
-}
-
-static void
-bna_intr_put(struct bna_ib_mod *ib_mod,
-               struct bna_intr *intr)
-{
-       intr->ref_count--;
-
-       if (intr->ref_count == 0) {
-               intr->ib = NULL;
-               list_del(&intr->qe);
-               bfa_q_qe_init(&intr->qe);
-               list_add_tail(&intr->qe, &ib_mod->intr_free_q);
-       }
-}
-
-void
-bna_ib_mod_init(struct bna_ib_mod *ib_mod, struct bna *bna,
-               struct bna_res_info *res_info)
-{
-       int i;
-       int j;
-       int count;
-       u8 offset;
-       struct bna_doorbell_qset *qset;
-       unsigned long off;
-
-       ib_mod->bna = bna;
-
-       ib_mod->ib = (struct bna_ib *)
-               res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.mdl[0].kva;
-       ib_mod->intr = (struct bna_intr *)
-               res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.mdl[0].kva;
-       ib_mod->idx_seg = (struct bna_ibidx_seg *)
-               res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.mdl[0].kva;
-
-       INIT_LIST_HEAD(&ib_mod->ib_free_q);
-       INIT_LIST_HEAD(&ib_mod->intr_free_q);
-       INIT_LIST_HEAD(&ib_mod->intr_active_q);
-
-       for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++)
-               INIT_LIST_HEAD(&ib_mod->ibidx_seg_pool[i]);
-
-       for (i = 0; i < BFI_MAX_IB; i++) {
-               ib_mod->ib[i].ib_id = i;
-
-               ib_mod->ib[i].ib_seg_host_addr_kva =
-               res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].kva;
-               ib_mod->ib[i].ib_seg_host_addr.lsb =
-               res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.lsb;
-               ib_mod->ib[i].ib_seg_host_addr.msb =
-               res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.msb;
-
-               qset = (struct bna_doorbell_qset *)0;
-               off = (unsigned long)(&qset[i >> 1].ib0[(i & 0x1)
-                                       * (0x20 >> 2)]);
-               ib_mod->ib[i].door_bell.doorbell_addr = off +
-                       BNA_GET_DOORBELL_BASE_ADDR(bna->pcidev.pci_bar_kva);
-
-               bfa_q_qe_init(&ib_mod->ib[i].qe);
-               list_add_tail(&ib_mod->ib[i].qe, &ib_mod->ib_free_q);
-
-               bfa_q_qe_init(&ib_mod->intr[i].qe);
-               list_add_tail(&ib_mod->intr[i].qe, &ib_mod->intr_free_q);
-       }
-
-       count = 0;
-       offset = 0;
-       for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {
-               for (j = 0; j < ibidx_pool[i].pool_size; j++) {
-                       bfa_q_qe_init(&ib_mod->idx_seg[count]);
-                       ib_mod->idx_seg[count].ib_seg_size =
-                                       ibidx_pool[i].pool_entry_size;
-                       ib_mod->idx_seg[count].ib_idx_tbl_offset = offset;
-                       list_add_tail(&ib_mod->idx_seg[count].qe,
-                               &ib_mod->ibidx_seg_pool[i]);
-                       count++;
-                       offset += ibidx_pool[i].pool_entry_size;
-               }
-       }
-}
-
-void
-bna_ib_mod_uninit(struct bna_ib_mod *ib_mod)
-{
-       int i;
-       int j;
-       struct list_head *qe;
-
-       i = 0;
-       list_for_each(qe, &ib_mod->ib_free_q)
-               i++;
-
-       i = 0;
-       list_for_each(qe, &ib_mod->intr_free_q)
-               i++;
-
-       for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {
-               j = 0;
-               list_for_each(qe, &ib_mod->ibidx_seg_pool[i])
-                       j++;
-       }
-
-       ib_mod->bna = NULL;
-}
-
-static struct bna_ib *
-bna_ib_get(struct bna_ib_mod *ib_mod,
-               enum bna_intr_type intr_type,
-               int vector)
-{
-       struct bna_ib *ib;
-       struct bna_intr *intr;
-
-       if (intr_type == BNA_INTR_T_INTX)
-               vector = (1 << vector);
-
-       intr = bna_intr_get(ib_mod, intr_type, vector);
-       if (intr == NULL)
-               return NULL;
-
-       if (intr->ib) {
-               if (intr->ib->ref_count == BFI_IBIDX_MAX_SEGSIZE) {
-                       bna_intr_put(ib_mod, intr);
-                       return NULL;
-               }
-               intr->ib->ref_count++;
-               return intr->ib;
-       }
-
-       if (list_empty(&ib_mod->ib_free_q)) {
-               bna_intr_put(ib_mod, intr);
-               return NULL;
-       }
-
-       bfa_q_deq(&ib_mod->ib_free_q, &ib);
-       bfa_q_qe_init(&ib->qe);
-
-       ib->ref_count = 1;
-       ib->start_count = 0;
-       ib->idx_mask = 0;
-
-       ib->intr = intr;
-       ib->idx_seg = NULL;
-       intr->ib = ib;
-
-       ib->bna = ib_mod->bna;
-
-       return ib;
-}
-
-static void
-bna_ib_put(struct bna_ib_mod *ib_mod, struct bna_ib *ib)
-{
-       bna_intr_put(ib_mod, ib->intr);
-
-       ib->ref_count--;
-
-       if (ib->ref_count == 0) {
-               ib->intr = NULL;
-               ib->bna = NULL;
-               list_add_tail(&ib->qe, &ib_mod->ib_free_q);
-       }
-}
-
-/* Returns index offset - starting from 0 */
-static int
-bna_ib_reserve_idx(struct bna_ib *ib)
-{
-       struct bna_ib_mod *ib_mod = &ib->bna->ib_mod;
-       struct bna_ibidx_seg *idx_seg;
-       int idx;
-       int num_idx;
-       int q_idx;
-
-       /* Find the first free index position */
-       bna_ib_find_free_ibidx(ib->idx_mask, idx);
-       if (idx == BFI_IBIDX_MAX_SEGSIZE)
-               return -1;
-
-       /*
-        * Calculate the total number of indexes held by this IB,
-        * including the index newly reserved above.
-        */
-       bna_ib_count_ibidx((ib->idx_mask | (1 << idx)), num_idx);
-
-       /* See if there is a free space in the index segment held by this IB */
-       if (ib->idx_seg && (num_idx <= ib->idx_seg->ib_seg_size)) {
-               ib->idx_mask |= (1 << idx);
-               return idx;
-       }
-
-       if (ib->start_count)
-               return -1;
-
-       /* Allocate a new segment */
-       bna_ib_select_segpool(num_idx, q_idx);
-       while (1) {
-               if (q_idx == BFI_IBIDX_TOTAL_POOLS)
-                       return -1;
-               if (!list_empty(&ib_mod->ibidx_seg_pool[q_idx]))
-                       break;
-               q_idx++;
-       }
-       bfa_q_deq(&ib_mod->ibidx_seg_pool[q_idx], &idx_seg);
-       bfa_q_qe_init(&idx_seg->qe);
-
-       /* Free the old segment */
-       if (ib->idx_seg) {
-               bna_ib_select_segpool(ib->idx_seg->ib_seg_size, q_idx);
-               list_add_tail(&ib->idx_seg->qe, &ib_mod->ibidx_seg_pool[q_idx]);
-       }
-
-       ib->idx_seg = idx_seg;
-
-       ib->idx_mask |= (1 << idx);
-
-       return idx;
-}
-
-static void
-bna_ib_release_idx(struct bna_ib *ib, int idx)
-{
-       struct bna_ib_mod *ib_mod = &ib->bna->ib_mod;
-       struct bna_ibidx_seg *idx_seg;
-       int num_idx;
-       int cur_q_idx;
-       int new_q_idx;
-
-       ib->idx_mask &= ~(1 << idx);
-
-       if (ib->start_count)
-               return;
-
-       bna_ib_count_ibidx(ib->idx_mask, num_idx);
-
-       /*
-        * Free the segment, if there are no more indexes in the segment
-        * held by this IB
-        */
-       if (!num_idx) {
-               bna_ib_select_segpool(ib->idx_seg->ib_seg_size, cur_q_idx);
-               list_add_tail(&ib->idx_seg->qe,
-                       &ib_mod->ibidx_seg_pool[cur_q_idx]);
-               ib->idx_seg = NULL;
-               return;
-       }
-
-       /* See if we can move to a smaller segment */
-       bna_ib_select_segpool(num_idx, new_q_idx);
-       bna_ib_select_segpool(ib->idx_seg->ib_seg_size, cur_q_idx);
-       while (new_q_idx < cur_q_idx) {
-               if (!list_empty(&ib_mod->ibidx_seg_pool[new_q_idx]))
-                       break;
-               new_q_idx++;
-       }
-       if (new_q_idx < cur_q_idx) {
-               /* Select the new smaller segment */
-               bfa_q_deq(&ib_mod->ibidx_seg_pool[new_q_idx], &idx_seg);
-               bfa_q_qe_init(&idx_seg->qe);
-               /* Free the old segment */
-               list_add_tail(&ib->idx_seg->qe,
-                       &ib_mod->ibidx_seg_pool[cur_q_idx]);
-               ib->idx_seg = idx_seg;
-       }
-}
-
-static int
-bna_ib_config(struct bna_ib *ib, struct bna_ib_config *ib_config)
-{
-       if (ib->start_count)
-               return -1;
-
-       ib->ib_config.coalescing_timeo = ib_config->coalescing_timeo;
-       ib->ib_config.interpkt_timeo = ib_config->interpkt_timeo;
-       ib->ib_config.interpkt_count = ib_config->interpkt_count;
-       ib->ib_config.ctrl_flags = ib_config->ctrl_flags;
-
-       ib->ib_config.ctrl_flags |= BFI_IB_CF_MASTER_ENABLE;
-       if (ib->intr->intr_type == BNA_INTR_T_MSIX)
-               ib->ib_config.ctrl_flags |= BFI_IB_CF_MSIX_MODE;
-
-       return 0;
-}
-
-static void
-bna_ib_start(struct bna_ib *ib)
-{
-       struct bna_ib_blk_mem ib_cfg;
-       struct bna_ib_blk_mem *ib_mem;
-       u32 pg_num;
-       u32 intx_mask;
-       int i;
-       void __iomem *base_addr;
-       unsigned long off;
-
-       ib->start_count++;
-
-       if (ib->start_count > 1)
-               return;
-
-       ib_cfg.host_addr_lo = (u32)(ib->ib_seg_host_addr.lsb);
-       ib_cfg.host_addr_hi = (u32)(ib->ib_seg_host_addr.msb);
-
-       ib_cfg.clsc_n_ctrl_n_msix = (((u32)
-                                    ib->ib_config.coalescing_timeo << 16) |
-                               ((u32)ib->ib_config.ctrl_flags << 8) |
-                               (ib->intr->vector));
-       ib_cfg.ipkt_n_ent_n_idxof =
-                               ((u32)
-                                (ib->ib_config.interpkt_timeo & 0xf) << 16) |
-                               ((u32)ib->idx_seg->ib_seg_size << 8) |
-                               (ib->idx_seg->ib_idx_tbl_offset);
-       ib_cfg.ipkt_cnt_cfg_n_unacked = ((u32)
-                                        ib->ib_config.interpkt_count << 24);
-
-       pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + ib->bna->port_num,
-                               HQM_IB_RAM_BASE_OFFSET);
-       writel(pg_num, ib->bna->regs.page_addr);
-
-       base_addr = BNA_GET_MEM_BASE_ADDR(ib->bna->pcidev.pci_bar_kva,
-                                       HQM_IB_RAM_BASE_OFFSET);
-
-       ib_mem = (struct bna_ib_blk_mem *)0;
-       off = (unsigned long)&ib_mem[ib->ib_id].host_addr_lo;
-       writel(htonl(ib_cfg.host_addr_lo), base_addr + off);
-
-       off = (unsigned long)&ib_mem[ib->ib_id].host_addr_hi;
-       writel(htonl(ib_cfg.host_addr_hi), base_addr + off);
-
-       off = (unsigned long)&ib_mem[ib->ib_id].clsc_n_ctrl_n_msix;
-       writel(ib_cfg.clsc_n_ctrl_n_msix, base_addr + off);
-
-       off = (unsigned long)&ib_mem[ib->ib_id].ipkt_n_ent_n_idxof;
-       writel(ib_cfg.ipkt_n_ent_n_idxof, base_addr + off);
-
-       off = (unsigned long)&ib_mem[ib->ib_id].ipkt_cnt_cfg_n_unacked;
-       writel(ib_cfg.ipkt_cnt_cfg_n_unacked, base_addr + off);
-
-       ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK(
-                               (u32)ib->ib_config.coalescing_timeo, 0);
-
-       pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + ib->bna->port_num,
-                               HQM_INDX_TBL_RAM_BASE_OFFSET);
-       writel(pg_num, ib->bna->regs.page_addr);
-
-       base_addr = BNA_GET_MEM_BASE_ADDR(ib->bna->pcidev.pci_bar_kva,
-                                       HQM_INDX_TBL_RAM_BASE_OFFSET);
-       for (i = 0; i < ib->idx_seg->ib_seg_size; i++) {
-               off = (unsigned long)
-               ((ib->idx_seg->ib_idx_tbl_offset + i) * BFI_IBIDX_SIZE);
-               writel(0, base_addr + off);
-       }
-
-       if (ib->intr->intr_type == BNA_INTR_T_INTX) {
-               bna_intx_disable(ib->bna, intx_mask);
-               intx_mask &= ~(ib->intr->vector);
-               bna_intx_enable(ib->bna, intx_mask);
-       }
-}
-
-static void
-bna_ib_stop(struct bna_ib *ib)
-{
-       u32 intx_mask;
-
-       ib->start_count--;
-
-       if (ib->start_count == 0) {
-               writel(BNA_DOORBELL_IB_INT_DISABLE,
-                               ib->door_bell.doorbell_addr);
-               if (ib->intr->intr_type == BNA_INTR_T_INTX) {
-                       bna_intx_disable(ib->bna, intx_mask);
-                       intx_mask |= (ib->intr->vector);
-                       bna_intx_enable(ib->bna, intx_mask);
-               }
-       }
-}
-
-static void
-bna_ib_fail(struct bna_ib *ib)
-{
-       ib->start_count = 0;
-}
-
-/**
- * RXF
- */
-static void rxf_enable(struct bna_rxf *rxf);
-static void rxf_disable(struct bna_rxf *rxf);
-static void __rxf_config_set(struct bna_rxf *rxf);
-static void __rxf_rit_set(struct bna_rxf *rxf);
-static void __bna_rxf_stat_clr(struct bna_rxf *rxf);
-static int rxf_process_packet_filter(struct bna_rxf *rxf);
-static int rxf_clear_packet_filter(struct bna_rxf *rxf);
-static void rxf_reset_packet_filter(struct bna_rxf *rxf);
-static void rxf_cb_enabled(void *arg, int status);
-static void rxf_cb_disabled(void *arg, int status);
-static void bna_rxf_cb_stats_cleared(void *arg, int status);
-static void __rxf_enable(struct bna_rxf *rxf);
-static void __rxf_disable(struct bna_rxf *rxf);
-
-bfa_fsm_state_decl(bna_rxf, stopped, struct bna_rxf,
-                       enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, start_wait, struct bna_rxf,
-                       enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, cam_fltr_mod_wait, struct bna_rxf,
-                       enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, started, struct bna_rxf,
-                       enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, cam_fltr_clr_wait, struct bna_rxf,
-                       enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, stop_wait, struct bna_rxf,
-                       enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, pause_wait, struct bna_rxf,
-                       enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, resume_wait, struct bna_rxf,
-                       enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, stat_clr_wait, struct bna_rxf,
-                       enum bna_rxf_event);
-
-static struct bfa_sm_table rxf_sm_table[] = {
-       {BFA_SM(bna_rxf_sm_stopped), BNA_RXF_STOPPED},
-       {BFA_SM(bna_rxf_sm_start_wait), BNA_RXF_START_WAIT},
-       {BFA_SM(bna_rxf_sm_cam_fltr_mod_wait), BNA_RXF_CAM_FLTR_MOD_WAIT},
-       {BFA_SM(bna_rxf_sm_started), BNA_RXF_STARTED},
-       {BFA_SM(bna_rxf_sm_cam_fltr_clr_wait), BNA_RXF_CAM_FLTR_CLR_WAIT},
-       {BFA_SM(bna_rxf_sm_stop_wait), BNA_RXF_STOP_WAIT},
-       {BFA_SM(bna_rxf_sm_pause_wait), BNA_RXF_PAUSE_WAIT},
-       {BFA_SM(bna_rxf_sm_resume_wait), BNA_RXF_RESUME_WAIT},
-       {BFA_SM(bna_rxf_sm_stat_clr_wait), BNA_RXF_STAT_CLR_WAIT}
-};
-
-static void
-bna_rxf_sm_stopped_entry(struct bna_rxf *rxf)
-{
-       call_rxf_stop_cbfn(rxf, BNA_CB_SUCCESS);
-}
-
-static void
-bna_rxf_sm_stopped(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-       switch (event) {
-       case RXF_E_START:
-               bfa_fsm_set_state(rxf, bna_rxf_sm_start_wait);
-               break;
-
-       case RXF_E_STOP:
-               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-               break;
-
-       case RXF_E_FAIL:
-               /* No-op */
-               break;
-
-       case RXF_E_CAM_FLTR_MOD:
-               call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
-               break;
-
-       case RXF_E_STARTED:
-       case RXF_E_STOPPED:
-       case RXF_E_CAM_FLTR_RESP:
-               /**
-                * These events are received due to flushing of mbox
-                * when device fails
-                */
-               /* No-op */
-               break;
-
-       case RXF_E_PAUSE:
-               rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
-               call_rxf_pause_cbfn(rxf, BNA_CB_SUCCESS);
-               break;
-
-       case RXF_E_RESUME:
-               rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
-               call_rxf_resume_cbfn(rxf, BNA_CB_SUCCESS);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_rxf_sm_start_wait_entry(struct bna_rxf *rxf)
-{
-       __rxf_config_set(rxf);
-       __rxf_rit_set(rxf);
-       rxf_enable(rxf);
-}
-
-static void
-bna_rxf_sm_start_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-       switch (event) {
-       case RXF_E_STOP:
-               /**
-                * STOP is originated from bnad. When this happens,
-                * it can not be waiting for filter update
-                */
-               call_rxf_start_cbfn(rxf, BNA_CB_INTERRUPT);
-               bfa_fsm_set_state(rxf, bna_rxf_sm_stop_wait);
-               break;
-
-       case RXF_E_FAIL:
-               call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
-               call_rxf_start_cbfn(rxf, BNA_CB_FAIL);
-               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-               break;
-
-       case RXF_E_CAM_FLTR_MOD:
-               /* No-op */
-               break;
-
-       case RXF_E_STARTED:
-               /**
-                * Force rxf_process_filter() to go through initial
-                * config
-                */
-               if ((rxf->ucast_active_mac != NULL) &&
-                       (rxf->ucast_pending_set == 0))
-                       rxf->ucast_pending_set = 1;
-
-               if (rxf->rss_status == BNA_STATUS_T_ENABLED)
-                       rxf->rxf_flags |= BNA_RXF_FL_RSS_CONFIG_PENDING;
-
-               rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
-
-               bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_mod_wait);
-               break;
-
-       case RXF_E_PAUSE:
-       case RXF_E_RESUME:
-               rxf->rxf_flags |= BNA_RXF_FL_OPERSTATE_CHANGED;
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_rxf_sm_cam_fltr_mod_wait_entry(struct bna_rxf *rxf)
-{
-       if (!rxf_process_packet_filter(rxf)) {
-               /* No more pending CAM entries to update */
-               bfa_fsm_set_state(rxf, bna_rxf_sm_started);
-       }
-}
-
-static void
-bna_rxf_sm_cam_fltr_mod_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-       switch (event) {
-       case RXF_E_STOP:
-               /**
-                * STOP is originated from bnad. When this happens,
-                * it can not be waiting for filter update
-                */
-               call_rxf_start_cbfn(rxf, BNA_CB_INTERRUPT);
-               bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_clr_wait);
-               break;
-
-       case RXF_E_FAIL:
-               rxf_reset_packet_filter(rxf);
-               call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
-               call_rxf_start_cbfn(rxf, BNA_CB_FAIL);
-               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-               break;
-
-       case RXF_E_CAM_FLTR_MOD:
-               /* No-op */
-               break;
-
-       case RXF_E_CAM_FLTR_RESP:
-               if (!rxf_process_packet_filter(rxf)) {
-                       /* No more pending CAM entries to update */
-                       call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
-                       bfa_fsm_set_state(rxf, bna_rxf_sm_started);
-               }
-               break;
-
-       case RXF_E_PAUSE:
-       case RXF_E_RESUME:
-               rxf->rxf_flags |= BNA_RXF_FL_OPERSTATE_CHANGED;
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_rxf_sm_started_entry(struct bna_rxf *rxf)
-{
-       call_rxf_start_cbfn(rxf, BNA_CB_SUCCESS);
-
-       if (rxf->rxf_flags & BNA_RXF_FL_OPERSTATE_CHANGED) {
-               if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
-                       bfa_fsm_send_event(rxf, RXF_E_PAUSE);
-               else
-                       bfa_fsm_send_event(rxf, RXF_E_RESUME);
-       }
-
-}
-
-static void
-bna_rxf_sm_started(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-       switch (event) {
-       case RXF_E_STOP:
-               bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_clr_wait);
-               /* Hack to get FSM start clearing CAM entries */
-               bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_RESP);
-               break;
-
-       case RXF_E_FAIL:
-               rxf_reset_packet_filter(rxf);
-               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-               break;
-
-       case RXF_E_CAM_FLTR_MOD:
-               bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_mod_wait);
-               break;
-
-       case RXF_E_PAUSE:
-               bfa_fsm_set_state(rxf, bna_rxf_sm_pause_wait);
-               break;
-
-       case RXF_E_RESUME:
-               bfa_fsm_set_state(rxf, bna_rxf_sm_resume_wait);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_rxf_sm_cam_fltr_clr_wait_entry(struct bna_rxf *rxf)
-{
-       /**
-        *  Note: Do not add rxf_clear_packet_filter here.
-        * It will overstep mbox when this transition happens:
-        *      cam_fltr_mod_wait -> cam_fltr_clr_wait on RXF_E_STOP event
-        */
-}
-
-static void
-bna_rxf_sm_cam_fltr_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-       switch (event) {
-       case RXF_E_FAIL:
-               /**
-                * FSM was in the process of stopping, initiated by
-                * bnad. When this happens, no one can be waiting for
-                * start or filter update
-                */
-               rxf_reset_packet_filter(rxf);
-               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-               break;
-
-       case RXF_E_CAM_FLTR_RESP:
-               if (!rxf_clear_packet_filter(rxf)) {
-                       /* No more pending CAM entries to clear */
-                       bfa_fsm_set_state(rxf, bna_rxf_sm_stop_wait);
-                       rxf_disable(rxf);
-               }
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_rxf_sm_stop_wait_entry(struct bna_rxf *rxf)
-{
-       /**
-        * NOTE: Do not add  rxf_disable here.
-        * It will overstep mbox when this transition happens:
-        *      start_wait -> stop_wait on RXF_E_STOP event
-        */
-}
-
-static void
-bna_rxf_sm_stop_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-       switch (event) {
-       case RXF_E_FAIL:
-               /**
-                * FSM was in the process of stopping, initiated by
-                * bnad. When this happens, no one can be waiting for
-                * start or filter update
-                */
-               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-               break;
-
-       case RXF_E_STARTED:
-               /**
-                * This event is received due to abrupt transition from
-                * bna_rxf_sm_start_wait state on receiving
-                * RXF_E_STOP event
-                */
-               rxf_disable(rxf);
-               break;
-
-       case RXF_E_STOPPED:
-               /**
-                * FSM was in the process of stopping, initiated by
-                * bnad. When this happens, no one can be waiting for
-                * start or filter update
-                */
-               bfa_fsm_set_state(rxf, bna_rxf_sm_stat_clr_wait);
-               break;
-
-       case RXF_E_PAUSE:
-               rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
-               break;
-
-       case RXF_E_RESUME:
-               rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_rxf_sm_pause_wait_entry(struct bna_rxf *rxf)
-{
-       rxf->rxf_flags &=
-               ~(BNA_RXF_FL_OPERSTATE_CHANGED | BNA_RXF_FL_RXF_ENABLED);
-       __rxf_disable(rxf);
-}
-
-static void
-bna_rxf_sm_pause_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-       switch (event) {
-       case RXF_E_FAIL:
-               /**
-                * FSM was in the process of disabling rxf, initiated by
-                * bnad.
-                */
-               call_rxf_pause_cbfn(rxf, BNA_CB_FAIL);
-               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-               break;
-
-       case RXF_E_STOPPED:
-               rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
-               call_rxf_pause_cbfn(rxf, BNA_CB_SUCCESS);
-               bfa_fsm_set_state(rxf, bna_rxf_sm_started);
-               break;
-
-       /*
-        * Since PAUSE/RESUME can only be sent by bnad, we don't expect
-        * any other event during these states
-        */
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_rxf_sm_resume_wait_entry(struct bna_rxf *rxf)
-{
-       rxf->rxf_flags &= ~(BNA_RXF_FL_OPERSTATE_CHANGED);
-       rxf->rxf_flags |= BNA_RXF_FL_RXF_ENABLED;
-       __rxf_enable(rxf);
-}
-
-static void
-bna_rxf_sm_resume_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-       switch (event) {
-       case RXF_E_FAIL:
-               /**
-                * FSM was in the process of disabling rxf, initiated by
-                * bnad.
-                */
-               call_rxf_resume_cbfn(rxf, BNA_CB_FAIL);
-               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-               break;
-
-       case RXF_E_STARTED:
-               rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
-               call_rxf_resume_cbfn(rxf, BNA_CB_SUCCESS);
-               bfa_fsm_set_state(rxf, bna_rxf_sm_started);
-               break;
-
-       /*
-        * Since PAUSE/RESUME can only be sent by bnad, we don't expect
-        * any other event during these states
-        */
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_rxf_sm_stat_clr_wait_entry(struct bna_rxf *rxf)
-{
-       __bna_rxf_stat_clr(rxf);
-}
-
-static void
-bna_rxf_sm_stat_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-       switch (event) {
-       case RXF_E_FAIL:
-       case RXF_E_STAT_CLEARED:
-               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-__rxf_enable(struct bna_rxf *rxf)
-{
-       struct bfi_ll_rxf_multi_req ll_req;
-       u32 bm[2] = {0, 0};
-
-       if (rxf->rxf_id < 32)
-               bm[0] = 1 << rxf->rxf_id;
-       else
-               bm[1] = 1 << (rxf->rxf_id - 32);
-
-       bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
-       ll_req.rxf_id_mask[0] = htonl(bm[0]);
-       ll_req.rxf_id_mask[1] = htonl(bm[1]);
-       ll_req.enable = 1;
-
-       bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
-                       rxf_cb_enabled, rxf);
-
-       bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-static void
-__rxf_disable(struct bna_rxf *rxf)
-{
-       struct bfi_ll_rxf_multi_req ll_req;
-       u32 bm[2] = {0, 0};
-
-       if (rxf->rxf_id < 32)
-               bm[0] = 1 << rxf->rxf_id;
-       else
-               bm[1] = 1 << (rxf->rxf_id - 32);
-
-       bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
-       ll_req.rxf_id_mask[0] = htonl(bm[0]);
-       ll_req.rxf_id_mask[1] = htonl(bm[1]);
-       ll_req.enable = 0;
-
-       bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
-                       rxf_cb_disabled, rxf);
-
-       bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-static void
-__rxf_config_set(struct bna_rxf *rxf)
-{
-       u32 i;
-       struct bna_rss_mem *rss_mem;
-       struct bna_rx_fndb_ram *rx_fndb_ram;
-       struct bna *bna = rxf->rx->bna;
-       void __iomem *base_addr;
-       unsigned long off;
-
-       base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
-                       RSS_TABLE_BASE_OFFSET);
-
-       rss_mem = (struct bna_rss_mem *)0;
-
-       /* Configure RSS if required */
-       if (rxf->ctrl_flags & BNA_RXF_CF_RSS_ENABLE) {
-               /* configure RSS Table */
-               writel(BNA_GET_PAGE_NUM(RAD0_MEM_BLK_BASE_PG_NUM +
-                       bna->port_num, RSS_TABLE_BASE_OFFSET),
-                                       bna->regs.page_addr);
-
-               /* temporarily disable RSS, while hash value is written */
-               off = (unsigned long)&rss_mem[0].type_n_hash;
-               writel(0, base_addr + off);
-
-               for (i = 0; i < BFI_RSS_HASH_KEY_LEN; i++) {
-                       off = (unsigned long)
-                       &rss_mem[0].hash_key[(BFI_RSS_HASH_KEY_LEN - 1) - i];
-                       writel(htonl(rxf->rss_cfg.toeplitz_hash_key[i]),
-                       base_addr + off);
-               }
-
-               off = (unsigned long)&rss_mem[0].type_n_hash;
-               writel(rxf->rss_cfg.hash_type | rxf->rss_cfg.hash_mask,
-                       base_addr + off);
-       }
-
-       /* Configure RxF */
-       writel(BNA_GET_PAGE_NUM(
-               LUT0_MEM_BLK_BASE_PG_NUM + (bna->port_num * 2),
-               RX_FNDB_RAM_BASE_OFFSET),
-               bna->regs.page_addr);
-
-       base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
-               RX_FNDB_RAM_BASE_OFFSET);
-
-       rx_fndb_ram = (struct bna_rx_fndb_ram *)0;
-
-       /* We always use RSS table 0 */
-       off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].rss_prop;
-       writel(rxf->ctrl_flags & BNA_RXF_CF_RSS_ENABLE,
-               base_addr + off);
-
-       /* small large buffer enable/disable */
-       off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].size_routing_props;
-       writel((rxf->ctrl_flags & BNA_RXF_CF_SM_LG_RXQ) | 0x80,
-               base_addr + off);
-
-       /* RIT offset,  HDS forced offset, multicast RxQ Id */
-       off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].rit_hds_mcastq;
-       writel((rxf->rit_segment->rit_offset << 16) |
-               (rxf->forced_offset << 8) |
-               (rxf->hds_cfg.hdr_type & BNA_HDS_FORCED) | rxf->mcast_rxq_id,
-               base_addr + off);
-
-       /*
-        * default vlan tag, default function enable, strip vlan bytes,
-        * HDS type, header size
-        */
-
-       off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].control_flags;
-        writel(((u32)rxf->default_vlan_tag << 16) |
-               (rxf->ctrl_flags &
-                       (BNA_RXF_CF_DEFAULT_VLAN |
-                       BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE |
-                       BNA_RXF_CF_VLAN_STRIP)) |
-               (rxf->hds_cfg.hdr_type & ~BNA_HDS_FORCED) |
-               rxf->hds_cfg.header_size,
-               base_addr + off);
-}
-
-void
-__rxf_vlan_filter_set(struct bna_rxf *rxf, enum bna_status status)
-{
-       struct bna *bna = rxf->rx->bna;
-       int i;
-
-       writel(BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
-                       (bna->port_num * 2), VLAN_RAM_BASE_OFFSET),
-                       bna->regs.page_addr);
-
-       if (status == BNA_STATUS_T_ENABLED) {
-               /* enable VLAN filtering on this function */
-               for (i = 0; i <= BFI_MAX_VLAN / 32; i++) {
-                       writel(rxf->vlan_filter_table[i],
-                                       BNA_GET_VLAN_MEM_ENTRY_ADDR
-                                       (bna->pcidev.pci_bar_kva, rxf->rxf_id,
-                                               i * 32));
-               }
-       } else {
-               /* disable VLAN filtering on this function */
-               for (i = 0; i <= BFI_MAX_VLAN / 32; i++) {
-                       writel(0xffffffff,
-                                       BNA_GET_VLAN_MEM_ENTRY_ADDR
-                                       (bna->pcidev.pci_bar_kva, rxf->rxf_id,
-                                               i * 32));
-               }
-       }
-}
-
-static void
-__rxf_rit_set(struct bna_rxf *rxf)
-{
-       struct bna *bna = rxf->rx->bna;
-       struct bna_rit_mem *rit_mem;
-       int i;
-       void __iomem *base_addr;
-       unsigned long off;
-
-       base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
-                       FUNCTION_TO_RXQ_TRANSLATE);
-
-       rit_mem = (struct bna_rit_mem *)0;
-
-       writel(BNA_GET_PAGE_NUM(RXA0_MEM_BLK_BASE_PG_NUM + bna->port_num,
-               FUNCTION_TO_RXQ_TRANSLATE),
-               bna->regs.page_addr);
-
-       for (i = 0; i < rxf->rit_segment->rit_size; i++) {
-               off = (unsigned long)&rit_mem[i + rxf->rit_segment->rit_offset];
-               writel(rxf->rit_segment->rit[i].large_rxq_id << 6 |
-                       rxf->rit_segment->rit[i].small_rxq_id,
-                       base_addr + off);
-       }
-}
-
-static void
-__bna_rxf_stat_clr(struct bna_rxf *rxf)
-{
-       struct bfi_ll_stats_req ll_req;
-       u32 bm[2] = {0, 0};
-
-       if (rxf->rxf_id < 32)
-               bm[0] = 1 << rxf->rxf_id;
-       else
-               bm[1] = 1 << (rxf->rxf_id - 32);
-
-       bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0);
-       ll_req.stats_mask = 0;
-       ll_req.txf_id_mask[0] = 0;
-       ll_req.txf_id_mask[1] = 0;
-
-       ll_req.rxf_id_mask[0] = htonl(bm[0]);
-       ll_req.rxf_id_mask[1] = htonl(bm[1]);
-
-       bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
-                       bna_rxf_cb_stats_cleared, rxf);
-       bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-static void
-rxf_enable(struct bna_rxf *rxf)
-{
-       if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
-               bfa_fsm_send_event(rxf, RXF_E_STARTED);
-       else {
-               rxf->rxf_flags |= BNA_RXF_FL_RXF_ENABLED;
-               __rxf_enable(rxf);
-       }
-}
-
-static void
-rxf_cb_enabled(void *arg, int status)
-{
-       struct bna_rxf *rxf = (struct bna_rxf *)arg;
-
-       bfa_q_qe_init(&rxf->mbox_qe.qe);
-       bfa_fsm_send_event(rxf, RXF_E_STARTED);
-}
-
-static void
-rxf_disable(struct bna_rxf *rxf)
-{
-       if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
-               bfa_fsm_send_event(rxf, RXF_E_STOPPED);
-       else
-               rxf->rxf_flags &= ~BNA_RXF_FL_RXF_ENABLED;
-               __rxf_disable(rxf);
-}
-
-static void
-rxf_cb_disabled(void *arg, int status)
-{
-       struct bna_rxf *rxf = (struct bna_rxf *)arg;
-
-       bfa_q_qe_init(&rxf->mbox_qe.qe);
-       bfa_fsm_send_event(rxf, RXF_E_STOPPED);
-}
-
-void
-rxf_cb_cam_fltr_mbox_cmd(void *arg, int status)
-{
-       struct bna_rxf *rxf = (struct bna_rxf *)arg;
-
-       bfa_q_qe_init(&rxf->mbox_qe.qe);
-
-       bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_RESP);
-}
-
-static void
-bna_rxf_cb_stats_cleared(void *arg, int status)
-{
-       struct bna_rxf *rxf = (struct bna_rxf *)arg;
-
-       bfa_q_qe_init(&rxf->mbox_qe.qe);
-       bfa_fsm_send_event(rxf, RXF_E_STAT_CLEARED);
-}
-
-void
-rxf_cam_mbox_cmd(struct bna_rxf *rxf, u8 cmd,
-               const struct bna_mac *mac_addr)
-{
-       struct bfi_ll_mac_addr_req req;
-
-       bfi_h2i_set(req.mh, BFI_MC_LL, cmd, 0);
-
-       req.rxf_id = rxf->rxf_id;
-       memcpy(&req.mac_addr, (void *)&mac_addr->addr, ETH_ALEN);
-
-       bna_mbox_qe_fill(&rxf->mbox_qe, &req, sizeof(req),
-                               rxf_cb_cam_fltr_mbox_cmd, rxf);
-
-       bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-static int
-rxf_process_packet_filter_mcast(struct bna_rxf *rxf)
-{
-       struct bna_mac *mac = NULL;
-       struct list_head *qe;
-
-       /* Add multicast entries */
-       if (!list_empty(&rxf->mcast_pending_add_q)) {
-               bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
-               bfa_q_qe_init(qe);
-               mac = (struct bna_mac *)qe;
-               rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_ADD_REQ, mac);
-               list_add_tail(&mac->qe, &rxf->mcast_active_q);
-               return 1;
-       }
-
-       /* Delete multicast entries previousely added */
-       if (!list_empty(&rxf->mcast_pending_del_q)) {
-               bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
-               bfa_q_qe_init(qe);
-               mac = (struct bna_mac *)qe;
-               rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
-               bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
-               return 1;
-       }
-
-       return 0;
-}
-
-static int
-rxf_process_packet_filter_vlan(struct bna_rxf *rxf)
-{
-       /* Apply the VLAN filter */
-       if (rxf->rxf_flags & BNA_RXF_FL_VLAN_CONFIG_PENDING) {
-               rxf->rxf_flags &= ~BNA_RXF_FL_VLAN_CONFIG_PENDING;
-               if (!(rxf->rxmode_active & BNA_RXMODE_PROMISC))
-                       __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
-       }
-
-       /* Apply RSS configuration */
-       if (rxf->rxf_flags & BNA_RXF_FL_RSS_CONFIG_PENDING) {
-               rxf->rxf_flags &= ~BNA_RXF_FL_RSS_CONFIG_PENDING;
-               if (rxf->rss_status == BNA_STATUS_T_DISABLED) {
-                       /* RSS is being disabled */
-                       rxf->ctrl_flags &= ~BNA_RXF_CF_RSS_ENABLE;
-                       __rxf_rit_set(rxf);
-                       __rxf_config_set(rxf);
-               } else {
-                       /* RSS is being enabled or reconfigured */
-                       rxf->ctrl_flags |= BNA_RXF_CF_RSS_ENABLE;
-                       __rxf_rit_set(rxf);
-                       __rxf_config_set(rxf);
-               }
-       }
-
-       return 0;
-}
-
-/**
- * Processes pending ucast, mcast entry addition/deletion and issues mailbox
- * command. Also processes pending filter configuration - promiscuous mode,
- * default mode, allmutli mode and issues mailbox command or directly applies
- * to h/w
- */
-static int
-rxf_process_packet_filter(struct bna_rxf *rxf)
-{
-       /* Set the default MAC first */
-       if (rxf->ucast_pending_set > 0) {
-               rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_SET_REQ,
-                               rxf->ucast_active_mac);
-               rxf->ucast_pending_set--;
-               return 1;
-       }
-
-       if (rxf_process_packet_filter_ucast(rxf))
-               return 1;
-
-       if (rxf_process_packet_filter_mcast(rxf))
-               return 1;
-
-       if (rxf_process_packet_filter_promisc(rxf))
-               return 1;
-
-       if (rxf_process_packet_filter_allmulti(rxf))
-               return 1;
-
-       if (rxf_process_packet_filter_vlan(rxf))
-               return 1;
-
-       return 0;
-}
-
-static int
-rxf_clear_packet_filter_mcast(struct bna_rxf *rxf)
-{
-       struct bna_mac *mac = NULL;
-       struct list_head *qe;
-
-       /* 3. delete pending mcast entries */
-       if (!list_empty(&rxf->mcast_pending_del_q)) {
-               bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
-               bfa_q_qe_init(qe);
-               mac = (struct bna_mac *)qe;
-               rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
-               bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
-               return 1;
-       }
-
-       /* 4. clear active mcast entries; move them to pending_add_q */
-       if (!list_empty(&rxf->mcast_active_q)) {
-               bfa_q_deq(&rxf->mcast_active_q, &qe);
-               bfa_q_qe_init(qe);
-               mac = (struct bna_mac *)qe;
-               rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
-               list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
-               return 1;
-       }
-
-       return 0;
-}
-
-/**
- * In the rxf stop path, processes pending ucast/mcast delete queue and issues
- * the mailbox command. Moves the active ucast/mcast entries to pending add q,
- * so that they are added to CAM again in the rxf start path. Moves the current
- * filter settings - promiscuous, default, allmutli - to pending filter
- * configuration
- */
-static int
-rxf_clear_packet_filter(struct bna_rxf *rxf)
-{
-       if (rxf_clear_packet_filter_ucast(rxf))
-               return 1;
-
-       if (rxf_clear_packet_filter_mcast(rxf))
-               return 1;
-
-       /* 5. clear active default MAC in the CAM */
-       if (rxf->ucast_pending_set > 0)
-               rxf->ucast_pending_set = 0;
-
-       if (rxf_clear_packet_filter_promisc(rxf))
-               return 1;
-
-       if (rxf_clear_packet_filter_allmulti(rxf))
-               return 1;
-
-       return 0;
-}
-
-static void
-rxf_reset_packet_filter_mcast(struct bna_rxf *rxf)
-{
-       struct list_head *qe;
-       struct bna_mac *mac;
-
-       /* 3. Move active mcast entries to pending_add_q */
-       while (!list_empty(&rxf->mcast_active_q)) {
-               bfa_q_deq(&rxf->mcast_active_q, &qe);
-               bfa_q_qe_init(qe);
-               list_add_tail(qe, &rxf->mcast_pending_add_q);
-       }
-
-       /* 4. Throw away delete pending mcast entries */
-       while (!list_empty(&rxf->mcast_pending_del_q)) {
-               bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
-               bfa_q_qe_init(qe);
-               mac = (struct bna_mac *)qe;
-               bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
-       }
-}
-
-/**
- * In the rxf fail path, throws away the ucast/mcast entries pending for
- * deletion, moves all active ucast/mcast entries to pending queue so that
- * they are added back to CAM in the rxf start path. Also moves the current
- * filter configuration to pending filter configuration.
- */
-static void
-rxf_reset_packet_filter(struct bna_rxf *rxf)
-{
-       rxf_reset_packet_filter_ucast(rxf);
-
-       rxf_reset_packet_filter_mcast(rxf);
-
-       /* 5. Turn off ucast set flag */
-       rxf->ucast_pending_set = 0;
-
-       rxf_reset_packet_filter_promisc(rxf);
-
-       rxf_reset_packet_filter_allmulti(rxf);
-}
-
-static void
-bna_rxf_init(struct bna_rxf *rxf,
-               struct bna_rx *rx,
-               struct bna_rx_config *q_config)
-{
-       struct list_head *qe;
-       struct bna_rxp *rxp;
-
-       /* rxf_id is initialized during rx_mod init */
-       rxf->rx = rx;
-
-       INIT_LIST_HEAD(&rxf->ucast_pending_add_q);
-       INIT_LIST_HEAD(&rxf->ucast_pending_del_q);
-       rxf->ucast_pending_set = 0;
-       INIT_LIST_HEAD(&rxf->ucast_active_q);
-       rxf->ucast_active_mac = NULL;
-
-       INIT_LIST_HEAD(&rxf->mcast_pending_add_q);
-       INIT_LIST_HEAD(&rxf->mcast_pending_del_q);
-       INIT_LIST_HEAD(&rxf->mcast_active_q);
-
-       bfa_q_qe_init(&rxf->mbox_qe.qe);
-
-       if (q_config->vlan_strip_status == BNA_STATUS_T_ENABLED)
-               rxf->ctrl_flags |= BNA_RXF_CF_VLAN_STRIP;
-
-       rxf->rxf_oper_state = (q_config->paused) ?
-               BNA_RXF_OPER_STATE_PAUSED : BNA_RXF_OPER_STATE_RUNNING;
-
-       bna_rxf_adv_init(rxf, rx, q_config);
-
-       rxf->rit_segment = bna_rit_mod_seg_get(&rxf->rx->bna->rit_mod,
-                                       q_config->num_paths);
-
-       list_for_each(qe, &rx->rxp_q) {
-               rxp = (struct bna_rxp *)qe;
-               if (q_config->rxp_type == BNA_RXP_SINGLE)
-                       rxf->mcast_rxq_id = rxp->rxq.single.only->rxq_id;
-               else
-                       rxf->mcast_rxq_id = rxp->rxq.slr.large->rxq_id;
-               break;
-       }
-
-       rxf->vlan_filter_status = BNA_STATUS_T_DISABLED;
-       memset(rxf->vlan_filter_table, 0,
-                       (sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32)));
-
-       /* Set up VLAN 0 for pure priority tagged packets */
-       rxf->vlan_filter_table[0] |= 1;
-
-       bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-}
-
-static void
-bna_rxf_uninit(struct bna_rxf *rxf)
-{
-       struct bna *bna = rxf->rx->bna;
-       struct bna_mac *mac;
-
-       bna_rit_mod_seg_put(&rxf->rx->bna->rit_mod, rxf->rit_segment);
-       rxf->rit_segment = NULL;
-
-       rxf->ucast_pending_set = 0;
-
-       while (!list_empty(&rxf->ucast_pending_add_q)) {
-               bfa_q_deq(&rxf->ucast_pending_add_q, &mac);
-               bfa_q_qe_init(&mac->qe);
-               bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
-       }
-
-       if (rxf->ucast_active_mac) {
-               bfa_q_qe_init(&rxf->ucast_active_mac->qe);
-               bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod,
-                       rxf->ucast_active_mac);
-               rxf->ucast_active_mac = NULL;
-       }
-
-       while (!list_empty(&rxf->mcast_pending_add_q)) {
-               bfa_q_deq(&rxf->mcast_pending_add_q, &mac);
-               bfa_q_qe_init(&mac->qe);
-               bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
-       }
-
-       /* Turn off pending promisc mode */
-       if (is_promisc_enable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask)) {
-               /* system promisc state should be pending */
-               BUG_ON(!(bna->rxf_promisc_id == rxf->rxf_id));
-               promisc_inactive(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-                bna->rxf_promisc_id = BFI_MAX_RXF;
-       }
-       /* Promisc mode should not be active */
-       BUG_ON(rxf->rxmode_active & BNA_RXMODE_PROMISC);
-
-       /* Turn off pending all-multi mode */
-       if (is_allmulti_enable(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask)) {
-               allmulti_inactive(rxf->rxmode_pending,
-                               rxf->rxmode_pending_bitmask);
-       }
-       /* Allmulti mode should not be active */
-       BUG_ON(rxf->rxmode_active & BNA_RXMODE_ALLMULTI);
-
-       rxf->rx = NULL;
-}
-
-static void
-bna_rx_cb_rxf_started(struct bna_rx *rx, enum bna_cb_status status)
-{
-       bfa_fsm_send_event(rx, RX_E_RXF_STARTED);
-       if (rx->rxf.rxf_id < 32)
-               rx->bna->rx_mod.rxf_bmap[0] |= ((u32)1 << rx->rxf.rxf_id);
-       else
-               rx->bna->rx_mod.rxf_bmap[1] |= ((u32)
-                               1 << (rx->rxf.rxf_id - 32));
-}
-
-static void
-bna_rxf_start(struct bna_rxf *rxf)
-{
-       rxf->start_cbfn = bna_rx_cb_rxf_started;
-       rxf->start_cbarg = rxf->rx;
-       rxf->rxf_flags &= ~BNA_RXF_FL_FAILED;
-       bfa_fsm_send_event(rxf, RXF_E_START);
-}
-
-static void
-bna_rx_cb_rxf_stopped(struct bna_rx *rx, enum bna_cb_status status)
-{
-       bfa_fsm_send_event(rx, RX_E_RXF_STOPPED);
-       if (rx->rxf.rxf_id < 32)
-               rx->bna->rx_mod.rxf_bmap[0] &= ~(u32)1 << rx->rxf.rxf_id;
-       else
-               rx->bna->rx_mod.rxf_bmap[1] &= ~(u32)
-                               1 << (rx->rxf.rxf_id - 32);
-}
-
-static void
-bna_rxf_stop(struct bna_rxf *rxf)
-{
-       rxf->stop_cbfn = bna_rx_cb_rxf_stopped;
-       rxf->stop_cbarg = rxf->rx;
-       bfa_fsm_send_event(rxf, RXF_E_STOP);
-}
-
-static void
-bna_rxf_fail(struct bna_rxf *rxf)
-{
-       rxf->rxf_flags |= BNA_RXF_FL_FAILED;
-       bfa_fsm_send_event(rxf, RXF_E_FAIL);
-}
-
-int
-bna_rxf_state_get(struct bna_rxf *rxf)
-{
-       return bfa_sm_to_state(rxf_sm_table, rxf->fsm);
-}
-
-enum bna_cb_status
-bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,
-                void (*cbfn)(struct bnad *, struct bna_rx *,
-                             enum bna_cb_status))
-{
-       struct bna_rxf *rxf = &rx->rxf;
-
-       if (rxf->ucast_active_mac == NULL) {
-               rxf->ucast_active_mac =
-                               bna_ucam_mod_mac_get(&rxf->rx->bna->ucam_mod);
-               if (rxf->ucast_active_mac == NULL)
-                       return BNA_CB_UCAST_CAM_FULL;
-               bfa_q_qe_init(&rxf->ucast_active_mac->qe);
-       }
-
-       memcpy(rxf->ucast_active_mac->addr, ucmac, ETH_ALEN);
-       rxf->ucast_pending_set++;
-       rxf->cam_fltr_cbfn = cbfn;
-       rxf->cam_fltr_cbarg = rx->bna->bnad;
-
-       bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-
-       return BNA_CB_SUCCESS;
-}
-
-enum bna_cb_status
-bna_rx_mcast_add(struct bna_rx *rx, u8 *addr,
-                void (*cbfn)(struct bnad *, struct bna_rx *,
-                             enum bna_cb_status))
-{
-       struct bna_rxf *rxf = &rx->rxf;
-       struct list_head        *qe;
-       struct bna_mac *mac;
-
-       /* Check if already added */
-       list_for_each(qe, &rxf->mcast_active_q) {
-               mac = (struct bna_mac *)qe;
-               if (BNA_MAC_IS_EQUAL(mac->addr, addr)) {
-                       if (cbfn)
-                               (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
-                       return BNA_CB_SUCCESS;
-               }
-       }
-
-       /* Check if pending addition */
-       list_for_each(qe, &rxf->mcast_pending_add_q) {
-               mac = (struct bna_mac *)qe;
-               if (BNA_MAC_IS_EQUAL(mac->addr, addr)) {
-                       if (cbfn)
-                               (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
-                       return BNA_CB_SUCCESS;
-               }
-       }
-
-       mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
-       if (mac == NULL)
-               return BNA_CB_MCAST_LIST_FULL;
-       bfa_q_qe_init(&mac->qe);
-       memcpy(mac->addr, addr, ETH_ALEN);
-       list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
-
-       rxf->cam_fltr_cbfn = cbfn;
-       rxf->cam_fltr_cbarg = rx->bna->bnad;
-
-       bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-
-       return BNA_CB_SUCCESS;
-}
-
-enum bna_cb_status
-bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist,
-                    void (*cbfn)(struct bnad *, struct bna_rx *,
-                                 enum bna_cb_status))
-{
-       struct bna_rxf *rxf = &rx->rxf;
-       struct list_head list_head;
-       struct list_head *qe;
-       u8 *mcaddr;
-       struct bna_mac *mac;
-       struct bna_mac *mac1;
-       int skip;
-       int delete;
-       int need_hw_config = 0;
-       int i;
-
-       /* Allocate nodes */
-       INIT_LIST_HEAD(&list_head);
-       for (i = 0, mcaddr = mclist; i < count; i++) {
-               mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
-               if (mac == NULL)
-                       goto err_return;
-               bfa_q_qe_init(&mac->qe);
-               memcpy(mac->addr, mcaddr, ETH_ALEN);
-               list_add_tail(&mac->qe, &list_head);
-
-               mcaddr += ETH_ALEN;
-       }
-
-       /* Schedule for addition */
-       while (!list_empty(&list_head)) {
-               bfa_q_deq(&list_head, &qe);
-               mac = (struct bna_mac *)qe;
-               bfa_q_qe_init(&mac->qe);
-
-               skip = 0;
-
-               /* Skip if already added */
-               list_for_each(qe, &rxf->mcast_active_q) {
-                       mac1 = (struct bna_mac *)qe;
-                       if (BNA_MAC_IS_EQUAL(mac1->addr, mac->addr)) {
-                               bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod,
-                                                       mac);
-                               skip = 1;
-                               break;
-                       }
-               }
-
-               if (skip)
-                       continue;
-
-               /* Skip if pending addition */
-               list_for_each(qe, &rxf->mcast_pending_add_q) {
-                       mac1 = (struct bna_mac *)qe;
-                       if (BNA_MAC_IS_EQUAL(mac1->addr, mac->addr)) {
-                               bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod,
-                                                       mac);
-                               skip = 1;
-                               break;
-                       }
-               }
-
-               if (skip)
-                       continue;
-
-               need_hw_config = 1;
-               list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
-       }
-
-       /**
-        * Delete the entries that are in the pending_add_q but not
-        * in the new list
-        */
-       while (!list_empty(&rxf->mcast_pending_add_q)) {
-               bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
-               mac = (struct bna_mac *)qe;
-               bfa_q_qe_init(&mac->qe);
-               for (i = 0, mcaddr = mclist, delete = 1; i < count; i++) {
-                       if (BNA_MAC_IS_EQUAL(mcaddr, mac->addr)) {
-                               delete = 0;
-                               break;
-                       }
-                       mcaddr += ETH_ALEN;
-               }
-               if (delete)
-                       bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
-               else
-                       list_add_tail(&mac->qe, &list_head);
-       }
-       while (!list_empty(&list_head)) {
-               bfa_q_deq(&list_head, &qe);
-               mac = (struct bna_mac *)qe;
-               bfa_q_qe_init(&mac->qe);
-               list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
-       }
-
-       /**
-        * Schedule entries for deletion that are in the active_q but not
-        * in the new list
-        */
-       while (!list_empty(&rxf->mcast_active_q)) {
-               bfa_q_deq(&rxf->mcast_active_q, &qe);
-               mac = (struct bna_mac *)qe;
-               bfa_q_qe_init(&mac->qe);
-               for (i = 0, mcaddr = mclist, delete = 1; i < count; i++) {
-                       if (BNA_MAC_IS_EQUAL(mcaddr, mac->addr)) {
-                               delete = 0;
-                               break;
-                       }
-                       mcaddr += ETH_ALEN;
-               }
-               if (delete) {
-                       list_add_tail(&mac->qe, &rxf->mcast_pending_del_q);
-                       need_hw_config = 1;
-               } else {
-                       list_add_tail(&mac->qe, &list_head);
-               }
-       }
-       while (!list_empty(&list_head)) {
-               bfa_q_deq(&list_head, &qe);
-               mac = (struct bna_mac *)qe;
-               bfa_q_qe_init(&mac->qe);
-               list_add_tail(&mac->qe, &rxf->mcast_active_q);
-       }
-
-       if (need_hw_config) {
-               rxf->cam_fltr_cbfn = cbfn;
-               rxf->cam_fltr_cbarg = rx->bna->bnad;
-               bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-       } else if (cbfn)
-               (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
-
-       return BNA_CB_SUCCESS;
-
-err_return:
-       while (!list_empty(&list_head)) {
-               bfa_q_deq(&list_head, &qe);
-               mac = (struct bna_mac *)qe;
-               bfa_q_qe_init(&mac->qe);
-               bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
-       }
-
-       return BNA_CB_MCAST_LIST_FULL;
-}
-
-void
-bna_rx_vlan_add(struct bna_rx *rx, int vlan_id)
-{
-       struct bna_rxf *rxf = &rx->rxf;
-       int index = (vlan_id >> 5);
-       int bit = (1 << (vlan_id & 0x1F));
-
-       rxf->vlan_filter_table[index] |= bit;
-       if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
-               rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
-               bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-       }
-}
-
-void
-bna_rx_vlan_del(struct bna_rx *rx, int vlan_id)
-{
-       struct bna_rxf *rxf = &rx->rxf;
-       int index = (vlan_id >> 5);
-       int bit = (1 << (vlan_id & 0x1F));
-
-       rxf->vlan_filter_table[index] &= ~bit;
-       if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
-               rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
-               bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-       }
-}
-
-/**
- * RX
- */
-#define        RXQ_RCB_INIT(q, rxp, qdepth, bna, _id, unmapq_mem)      do {    \
-       struct bna_doorbell_qset *_qset;                                \
-       unsigned long off;                                              \
-       (q)->rcb->producer_index = (q)->rcb->consumer_index = 0;        \
-       (q)->rcb->q_depth = (qdepth);                                   \
-       (q)->rcb->unmap_q = unmapq_mem;                                 \
-       (q)->rcb->rxq = (q);                                            \
-       (q)->rcb->cq = &(rxp)->cq;                                      \
-       (q)->rcb->bnad = (bna)->bnad;                                   \
-       _qset = (struct bna_doorbell_qset *)0;                  \
-       off = (unsigned long)&_qset[(q)->rxq_id].rxq[0];                \
-       (q)->rcb->q_dbell = off +                                       \
-               BNA_GET_DOORBELL_BASE_ADDR((bna)->pcidev.pci_bar_kva);  \
-       (q)->rcb->id = _id;                                             \
-} while (0)
-
-#define        BNA_GET_RXQS(qcfg)      (((qcfg)->rxp_type == BNA_RXP_SINGLE) ? \
-       (qcfg)->num_paths : ((qcfg)->num_paths * 2))
-
-#define        SIZE_TO_PAGES(size)     (((size) >> PAGE_SHIFT) + ((((size) &\
-       (PAGE_SIZE - 1)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
-
-#define        call_rx_stop_callback(rx, status)                               \
-       if ((rx)->stop_cbfn) {                                          \
-               (*(rx)->stop_cbfn)((rx)->stop_cbarg, rx, (status));     \
-               (rx)->stop_cbfn = NULL;                                 \
-               (rx)->stop_cbarg = NULL;                                \
-       }
-
-/*
- * Since rx_enable is synchronous callback, there is no start_cbfn required.
- * Instead, we'll call bnad_rx_post(rxp) so that bnad can post the buffers
- * for each rxpath.
- */
-
-#define        call_rx_disable_cbfn(rx, status)                                \
-               if ((rx)->disable_cbfn) {                               \
-                       (*(rx)->disable_cbfn)((rx)->disable_cbarg,      \
-                                       status);                        \
-                       (rx)->disable_cbfn = NULL;                      \
-                       (rx)->disable_cbarg = NULL;                     \
-               }                                                       \
-
-#define        rxqs_reqd(type, num_rxqs)                                       \
-       (((type) == BNA_RXP_SINGLE) ? (num_rxqs) : ((num_rxqs) * 2))
-
-#define rx_ib_fail(rx)                                         \
-do {                                                           \
-       struct bna_rxp *rxp;                                    \
-       struct list_head *qe;                                           \
-       list_for_each(qe, &(rx)->rxp_q) {                               \
-               rxp = (struct bna_rxp *)qe;                     \
-               bna_ib_fail(rxp->cq.ib);                        \
-       }                                                       \
-} while (0)
-
-static void __bna_multi_rxq_stop(struct bna_rxp *, u32 *);
-static void __bna_rxq_start(struct bna_rxq *rxq);
-static void __bna_cq_start(struct bna_cq *cq);
-static void bna_rit_create(struct bna_rx *rx);
-static void bna_rx_cb_multi_rxq_stopped(void *arg, int status);
-static void bna_rx_cb_rxq_stopped_all(void *arg);
-
-bfa_fsm_state_decl(bna_rx, stopped,
-       struct bna_rx, enum bna_rx_event);
-bfa_fsm_state_decl(bna_rx, rxf_start_wait,
-       struct bna_rx, enum bna_rx_event);
-bfa_fsm_state_decl(bna_rx, started,
-       struct bna_rx, enum bna_rx_event);
-bfa_fsm_state_decl(bna_rx, rxf_stop_wait,
-       struct bna_rx, enum bna_rx_event);
-bfa_fsm_state_decl(bna_rx, rxq_stop_wait,
-       struct bna_rx, enum bna_rx_event);
-
-static const struct bfa_sm_table rx_sm_table[] = {
-       {BFA_SM(bna_rx_sm_stopped), BNA_RX_STOPPED},
-       {BFA_SM(bna_rx_sm_rxf_start_wait), BNA_RX_RXF_START_WAIT},
-       {BFA_SM(bna_rx_sm_started), BNA_RX_STARTED},
-       {BFA_SM(bna_rx_sm_rxf_stop_wait), BNA_RX_RXF_STOP_WAIT},
-       {BFA_SM(bna_rx_sm_rxq_stop_wait), BNA_RX_RXQ_STOP_WAIT},
-};
-
-static void bna_rx_sm_stopped_entry(struct bna_rx *rx)
-{
-       struct bna_rxp *rxp;
-       struct list_head *qe_rxp;
-
-       list_for_each(qe_rxp, &rx->rxp_q) {
-               rxp = (struct bna_rxp *)qe_rxp;
-               rx->rx_cleanup_cbfn(rx->bna->bnad, rxp->cq.ccb);
-       }
-
-       call_rx_stop_callback(rx, BNA_CB_SUCCESS);
-}
-
-static void bna_rx_sm_stopped(struct bna_rx *rx,
-                               enum bna_rx_event event)
-{
-       switch (event) {
-       case RX_E_START:
-               bfa_fsm_set_state(rx, bna_rx_sm_rxf_start_wait);
-               break;
-       case RX_E_STOP:
-               call_rx_stop_callback(rx, BNA_CB_SUCCESS);
-               break;
-       case RX_E_FAIL:
-               /* no-op */
-               break;
-       default:
-               bfa_sm_fault(event);
-               break;
-       }
-
-}
-
-static void bna_rx_sm_rxf_start_wait_entry(struct bna_rx *rx)
-{
-       struct bna_rxp *rxp;
-       struct list_head *qe_rxp;
-       struct bna_rxq *q0 = NULL, *q1 = NULL;
-
-       /* Setup the RIT */
-       bna_rit_create(rx);
-
-       list_for_each(qe_rxp, &rx->rxp_q) {
-               rxp = (struct bna_rxp *)qe_rxp;
-               bna_ib_start(rxp->cq.ib);
-               GET_RXQS(rxp, q0, q1);
-               q0->buffer_size = bna_port_mtu_get(&rx->bna->port);
-               __bna_rxq_start(q0);
-               rx->rx_post_cbfn(rx->bna->bnad, q0->rcb);
-               if (q1)  {
-                       __bna_rxq_start(q1);
-                       rx->rx_post_cbfn(rx->bna->bnad, q1->rcb);
-               }
-               __bna_cq_start(&rxp->cq);
-       }
-
-       bna_rxf_start(&rx->rxf);
-}
-
-static void bna_rx_sm_rxf_start_wait(struct bna_rx *rx,
-                               enum bna_rx_event event)
-{
-       switch (event) {
-       case RX_E_STOP:
-               bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
-               break;
-       case RX_E_FAIL:
-               bfa_fsm_set_state(rx, bna_rx_sm_stopped);
-               rx_ib_fail(rx);
-               bna_rxf_fail(&rx->rxf);
-               break;
-       case RX_E_RXF_STARTED:
-               bfa_fsm_set_state(rx, bna_rx_sm_started);
-               break;
-       default:
-               bfa_sm_fault(event);
-               break;
-       }
-}
-
-void
-bna_rx_sm_started_entry(struct bna_rx *rx)
-{
-       struct bna_rxp *rxp;
-       struct list_head *qe_rxp;
-
-       /* Start IB */
-       list_for_each(qe_rxp, &rx->rxp_q) {
-               rxp = (struct bna_rxp *)qe_rxp;
-               bna_ib_ack(&rxp->cq.ib->door_bell, 0);
-       }
-
-       bna_llport_rx_started(&rx->bna->port.llport);
-}
-
-void
-bna_rx_sm_started(struct bna_rx *rx, enum bna_rx_event event)
-{
-       switch (event) {
-       case RX_E_FAIL:
-               bna_llport_rx_stopped(&rx->bna->port.llport);
-               bfa_fsm_set_state(rx, bna_rx_sm_stopped);
-               rx_ib_fail(rx);
-               bna_rxf_fail(&rx->rxf);
-               break;
-       case RX_E_STOP:
-               bna_llport_rx_stopped(&rx->bna->port.llport);
-               bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
-               break;
-       default:
-               bfa_sm_fault(event);
-               break;
-       }
-}
-
-void
-bna_rx_sm_rxf_stop_wait_entry(struct bna_rx *rx)
-{
-       bna_rxf_stop(&rx->rxf);
-}
-
-void
-bna_rx_sm_rxf_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
-{
-       switch (event) {
-       case RX_E_RXF_STOPPED:
-               bfa_fsm_set_state(rx, bna_rx_sm_rxq_stop_wait);
-               break;
-       case RX_E_RXF_STARTED:
-               /**
-                * RxF was in the process of starting up when
-                * RXF_E_STOP was issued. Ignore this event
-                */
-               break;
-       case RX_E_FAIL:
-               bfa_fsm_set_state(rx, bna_rx_sm_stopped);
-               rx_ib_fail(rx);
-               bna_rxf_fail(&rx->rxf);
-               break;
-       default:
-               bfa_sm_fault(event);
-               break;
-       }
-
-}
-
-void
-bna_rx_sm_rxq_stop_wait_entry(struct bna_rx *rx)
-{
-       struct bna_rxp *rxp = NULL;
-       struct bna_rxq *q0 = NULL;
-       struct bna_rxq *q1 = NULL;
-       struct list_head        *qe;
-       u32 rxq_mask[2] = {0, 0};
-
-       /* Only one call to multi-rxq-stop for all RXPs in this RX */
-       bfa_wc_up(&rx->rxq_stop_wc);
-       list_for_each(qe, &rx->rxp_q) {
-               rxp = (struct bna_rxp *)qe;
-               GET_RXQS(rxp, q0, q1);
-               if (q0->rxq_id < 32)
-                       rxq_mask[0] |= ((u32)1 << q0->rxq_id);
-               else
-                       rxq_mask[1] |= ((u32)1 << (q0->rxq_id - 32));
-               if (q1) {
-                       if (q1->rxq_id < 32)
-                               rxq_mask[0] |= ((u32)1 << q1->rxq_id);
-                       else
-                               rxq_mask[1] |= ((u32)
-                                               1 << (q1->rxq_id - 32));
-               }
-       }
-
-       __bna_multi_rxq_stop(rxp, rxq_mask);
-}
-
-void
-bna_rx_sm_rxq_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
-{
-       struct bna_rxp *rxp = NULL;
-       struct list_head        *qe;
-
-       switch (event) {
-       case RX_E_RXQ_STOPPED:
-               list_for_each(qe, &rx->rxp_q) {
-                       rxp = (struct bna_rxp *)qe;
-                       bna_ib_stop(rxp->cq.ib);
-               }
-               /* Fall through */
-       case RX_E_FAIL:
-               bfa_fsm_set_state(rx, bna_rx_sm_stopped);
-               break;
-       default:
-               bfa_sm_fault(event);
-               break;
-       }
-}
-
-void
-__bna_multi_rxq_stop(struct bna_rxp *rxp, u32 * rxq_id_mask)
-{
-       struct bfi_ll_q_stop_req ll_req;
-
-       bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RXQ_STOP_REQ, 0);
-       ll_req.q_id_mask[0] = htonl(rxq_id_mask[0]);
-       ll_req.q_id_mask[1] = htonl(rxq_id_mask[1]);
-       bna_mbox_qe_fill(&rxp->mbox_qe, &ll_req, sizeof(ll_req),
-               bna_rx_cb_multi_rxq_stopped, rxp);
-       bna_mbox_send(rxp->rx->bna, &rxp->mbox_qe);
-}
-
-void
-__bna_rxq_start(struct bna_rxq *rxq)
-{
-       struct bna_rxtx_q_mem *q_mem;
-       struct bna_rxq_mem rxq_cfg, *rxq_mem;
-       struct bna_dma_addr cur_q_addr;
-       /* struct bna_doorbell_qset *qset; */
-       struct bna_qpt *qpt;
-       u32 pg_num;
-       struct bna *bna = rxq->rx->bna;
-       void __iomem *base_addr;
-       unsigned long off;
-
-       qpt = &rxq->qpt;
-       cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
-
-       rxq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
-       rxq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
-       rxq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
-       rxq_cfg.cur_q_entry_hi = cur_q_addr.msb;
-
-       rxq_cfg.pg_cnt_n_prd_ptr = ((u32)qpt->page_count << 16) | 0x0;
-       rxq_cfg.entry_n_pg_size = ((u32)(BFI_RXQ_WI_SIZE >> 2) << 16) |
-               (qpt->page_size >> 2);
-       rxq_cfg.sg_n_cq_n_cns_ptr =
-               ((u32)(rxq->rxp->cq.cq_id & 0xff) << 16) | 0x0;
-       rxq_cfg.buf_sz_n_q_state = ((u32)rxq->buffer_size << 16) |
-               BNA_Q_IDLE_STATE;
-       rxq_cfg.next_qid = 0x0 | (0x3 << 8);
-
-       /* Write the page number register */
-       pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + bna->port_num,
-                       HQM_RXTX_Q_RAM_BASE_OFFSET);
-       writel(pg_num, bna->regs.page_addr);
-
-       /* Write to h/w */
-       base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
-                                       HQM_RXTX_Q_RAM_BASE_OFFSET);
-
-       q_mem = (struct bna_rxtx_q_mem *)0;
-       rxq_mem = &q_mem[rxq->rxq_id].rxq;
-
-       off = (unsigned long)&rxq_mem->pg_tbl_addr_lo;
-       writel(htonl(rxq_cfg.pg_tbl_addr_lo), base_addr + off);
-
-       off = (unsigned long)&rxq_mem->pg_tbl_addr_hi;
-       writel(htonl(rxq_cfg.pg_tbl_addr_hi), base_addr + off);
-
-       off = (unsigned long)&rxq_mem->cur_q_entry_lo;
-       writel(htonl(rxq_cfg.cur_q_entry_lo), base_addr + off);
-
-       off = (unsigned long)&rxq_mem->cur_q_entry_hi;
-       writel(htonl(rxq_cfg.cur_q_entry_hi), base_addr + off);
-
-       off = (unsigned long)&rxq_mem->pg_cnt_n_prd_ptr;
-       writel(rxq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
-
-       off = (unsigned long)&rxq_mem->entry_n_pg_size;
-       writel(rxq_cfg.entry_n_pg_size, base_addr + off);
-
-       off = (unsigned long)&rxq_mem->sg_n_cq_n_cns_ptr;
-       writel(rxq_cfg.sg_n_cq_n_cns_ptr, base_addr + off);
-
-       off = (unsigned long)&rxq_mem->buf_sz_n_q_state;
-       writel(rxq_cfg.buf_sz_n_q_state, base_addr + off);
-
-       off = (unsigned long)&rxq_mem->next_qid;
-       writel(rxq_cfg.next_qid, base_addr + off);
-
-       rxq->rcb->producer_index = 0;
-       rxq->rcb->consumer_index = 0;
-}
-
-void
-__bna_cq_start(struct bna_cq *cq)
-{
-       struct bna_cq_mem cq_cfg, *cq_mem;
-       const struct bna_qpt *qpt;
-       struct bna_dma_addr cur_q_addr;
-       u32 pg_num;
-       struct bna *bna = cq->rx->bna;
-       void __iomem *base_addr;
-       unsigned long off;
-
-       qpt = &cq->qpt;
-       cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
-
-       /*
-        * Fill out structure, to be subsequently written
-        * to hardware
-        */
-       cq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
-       cq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
-       cq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
-       cq_cfg.cur_q_entry_hi = cur_q_addr.msb;
-
-       cq_cfg.pg_cnt_n_prd_ptr = (qpt->page_count << 16) | 0x0;
-       cq_cfg.entry_n_pg_size =
-               ((u32)(BFI_CQ_WI_SIZE >> 2) << 16) | (qpt->page_size >> 2);
-       cq_cfg.int_blk_n_cns_ptr = ((((u32)cq->ib_seg_offset) << 24) |
-                       ((u32)(cq->ib->ib_id & 0xff)  << 16) | 0x0);
-       cq_cfg.q_state = BNA_Q_IDLE_STATE;
-
-       /* Write the page number register */
-       pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + bna->port_num,
-                                 HQM_CQ_RAM_BASE_OFFSET);
-
-       writel(pg_num, bna->regs.page_addr);
-
-       /* H/W write */
-       base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
-                                       HQM_CQ_RAM_BASE_OFFSET);
-
-       cq_mem = (struct bna_cq_mem *)0;
-
-       off = (unsigned long)&cq_mem[cq->cq_id].pg_tbl_addr_lo;
-       writel(htonl(cq_cfg.pg_tbl_addr_lo), base_addr + off);
-
-       off = (unsigned long)&cq_mem[cq->cq_id].pg_tbl_addr_hi;
-       writel(htonl(cq_cfg.pg_tbl_addr_hi), base_addr + off);
-
-       off = (unsigned long)&cq_mem[cq->cq_id].cur_q_entry_lo;
-       writel(htonl(cq_cfg.cur_q_entry_lo), base_addr + off);
-
-       off = (unsigned long)&cq_mem[cq->cq_id].cur_q_entry_hi;
-       writel(htonl(cq_cfg.cur_q_entry_hi), base_addr + off);
-
-       off = (unsigned long)&cq_mem[cq->cq_id].pg_cnt_n_prd_ptr;
-       writel(cq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
-
-       off = (unsigned long)&cq_mem[cq->cq_id].entry_n_pg_size;
-       writel(cq_cfg.entry_n_pg_size, base_addr + off);
-
-       off = (unsigned long)&cq_mem[cq->cq_id].int_blk_n_cns_ptr;
-       writel(cq_cfg.int_blk_n_cns_ptr, base_addr + off);
-
-       off = (unsigned long)&cq_mem[cq->cq_id].q_state;
-       writel(cq_cfg.q_state, base_addr + off);
-
-       cq->ccb->producer_index = 0;
-       *(cq->ccb->hw_producer_index) = 0;
-}
-
-void
-bna_rit_create(struct bna_rx *rx)
-{
-       struct list_head        *qe_rxp;
-       struct bna_rxp *rxp;
-       struct bna_rxq *q0 = NULL;
-       struct bna_rxq *q1 = NULL;
-       int offset;
-
-       offset = 0;
-       list_for_each(qe_rxp, &rx->rxp_q) {
-               rxp = (struct bna_rxp *)qe_rxp;
-               GET_RXQS(rxp, q0, q1);
-               rx->rxf.rit_segment->rit[offset].large_rxq_id = q0->rxq_id;
-               rx->rxf.rit_segment->rit[offset].small_rxq_id =
-                                               (q1 ? q1->rxq_id : 0);
-               offset++;
-       }
-}
-
-static int
-_rx_can_satisfy(struct bna_rx_mod *rx_mod,
-               struct bna_rx_config *rx_cfg)
-{
-       if ((rx_mod->rx_free_count == 0) ||
-               (rx_mod->rxp_free_count == 0) ||
-               (rx_mod->rxq_free_count == 0))
-               return 0;
-
-       if (rx_cfg->rxp_type == BNA_RXP_SINGLE) {
-               if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
-                       (rx_mod->rxq_free_count < rx_cfg->num_paths))
-                               return 0;
-       } else {
-               if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
-                       (rx_mod->rxq_free_count < (2 * rx_cfg->num_paths)))
-                       return 0;
-       }
-
-       if (!bna_rit_mod_can_satisfy(&rx_mod->bna->rit_mod, rx_cfg->num_paths))
-               return 0;
-
-       return 1;
-}
-
-static struct bna_rxq *
-_get_free_rxq(struct bna_rx_mod *rx_mod)
-{
-       struct bna_rxq *rxq = NULL;
-       struct list_head        *qe = NULL;
-
-       bfa_q_deq(&rx_mod->rxq_free_q, &qe);
-       if (qe) {
-               rx_mod->rxq_free_count--;
-               rxq = (struct bna_rxq *)qe;
-       }
-       return rxq;
-}
-
-static void
-_put_free_rxq(struct bna_rx_mod *rx_mod, struct bna_rxq *rxq)
-{
-       bfa_q_qe_init(&rxq->qe);
-       list_add_tail(&rxq->qe, &rx_mod->rxq_free_q);
-       rx_mod->rxq_free_count++;
-}
-
-static struct bna_rxp *
-_get_free_rxp(struct bna_rx_mod *rx_mod)
-{
-       struct list_head        *qe = NULL;
-       struct bna_rxp *rxp = NULL;
-
-       bfa_q_deq(&rx_mod->rxp_free_q, &qe);
-       if (qe) {
-               rx_mod->rxp_free_count--;
-
-               rxp = (struct bna_rxp *)qe;
-       }
-
-       return rxp;
-}
-
-static void
-_put_free_rxp(struct bna_rx_mod *rx_mod, struct bna_rxp *rxp)
-{
-       bfa_q_qe_init(&rxp->qe);
-       list_add_tail(&rxp->qe, &rx_mod->rxp_free_q);
-       rx_mod->rxp_free_count++;
-}
-
-static struct bna_rx *
-_get_free_rx(struct bna_rx_mod *rx_mod)
-{
-       struct list_head        *qe = NULL;
-       struct bna_rx *rx = NULL;
-
-       bfa_q_deq(&rx_mod->rx_free_q, &qe);
-       if (qe) {
-               rx_mod->rx_free_count--;
-
-               rx = (struct bna_rx *)qe;
-               bfa_q_qe_init(qe);
-               list_add_tail(&rx->qe, &rx_mod->rx_active_q);
-       }
-
-       return rx;
-}
-
-static void
-_put_free_rx(struct bna_rx_mod *rx_mod, struct bna_rx *rx)
-{
-       bfa_q_qe_init(&rx->qe);
-       list_add_tail(&rx->qe, &rx_mod->rx_free_q);
-       rx_mod->rx_free_count++;
-}
-
-static void
-_rx_init(struct bna_rx *rx, struct bna *bna)
-{
-       rx->bna = bna;
-       rx->rx_flags = 0;
-
-       INIT_LIST_HEAD(&rx->rxp_q);
-
-       rx->rxq_stop_wc.wc_resume = bna_rx_cb_rxq_stopped_all;
-       rx->rxq_stop_wc.wc_cbarg = rx;
-       rx->rxq_stop_wc.wc_count = 0;
-
-       rx->stop_cbfn = NULL;
-       rx->stop_cbarg = NULL;
-}
-
-static void
-_rxp_add_rxqs(struct bna_rxp *rxp,
-               struct bna_rxq *q0,
-               struct bna_rxq *q1)
-{
-       switch (rxp->type) {
-       case BNA_RXP_SINGLE:
-               rxp->rxq.single.only = q0;
-               rxp->rxq.single.reserved = NULL;
-               break;
-       case BNA_RXP_SLR:
-               rxp->rxq.slr.large = q0;
-               rxp->rxq.slr.small = q1;
-               break;
-       case BNA_RXP_HDS:
-               rxp->rxq.hds.data = q0;
-               rxp->rxq.hds.hdr = q1;
-               break;
-       default:
-               break;
-       }
-}
-
-static void
-_rxq_qpt_init(struct bna_rxq *rxq,
-               struct bna_rxp *rxp,
-               u32 page_count,
-               u32 page_size,
-               struct bna_mem_descr *qpt_mem,
-               struct bna_mem_descr *swqpt_mem,
-               struct bna_mem_descr *page_mem)
-{
-       int     i;
-
-       rxq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
-       rxq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
-       rxq->qpt.kv_qpt_ptr = qpt_mem->kva;
-       rxq->qpt.page_count = page_count;
-       rxq->qpt.page_size = page_size;
-
-       rxq->rcb->sw_qpt = (void **) swqpt_mem->kva;
-
-       for (i = 0; i < rxq->qpt.page_count; i++) {
-               rxq->rcb->sw_qpt[i] = page_mem[i].kva;
-               ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].lsb =
-                       page_mem[i].dma.lsb;
-               ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].msb =
-                       page_mem[i].dma.msb;
-
-       }
-}
-
-static void
-_rxp_cqpt_setup(struct bna_rxp *rxp,
-               u32 page_count,
-               u32 page_size,
-               struct bna_mem_descr *qpt_mem,
-               struct bna_mem_descr *swqpt_mem,
-               struct bna_mem_descr *page_mem)
-{
-       int     i;
-
-       rxp->cq.qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
-       rxp->cq.qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
-       rxp->cq.qpt.kv_qpt_ptr = qpt_mem->kva;
-       rxp->cq.qpt.page_count = page_count;
-       rxp->cq.qpt.page_size = page_size;
-
-       rxp->cq.ccb->sw_qpt = (void **) swqpt_mem->kva;
-
-       for (i = 0; i < rxp->cq.qpt.page_count; i++) {
-               rxp->cq.ccb->sw_qpt[i] = page_mem[i].kva;
-
-               ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].lsb =
-                       page_mem[i].dma.lsb;
-               ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].msb =
-                       page_mem[i].dma.msb;
-
-       }
-}
-
-static void
-_rx_add_rxp(struct bna_rx *rx, struct bna_rxp *rxp)
-{
-       list_add_tail(&rxp->qe, &rx->rxp_q);
-}
-
-static void
-_init_rxmod_queues(struct bna_rx_mod *rx_mod)
-{
-       INIT_LIST_HEAD(&rx_mod->rx_free_q);
-       INIT_LIST_HEAD(&rx_mod->rxq_free_q);
-       INIT_LIST_HEAD(&rx_mod->rxp_free_q);
-       INIT_LIST_HEAD(&rx_mod->rx_active_q);
-
-       rx_mod->rx_free_count = 0;
-       rx_mod->rxq_free_count = 0;
-       rx_mod->rxp_free_count = 0;
-}
-
-static void
-_rx_ctor(struct bna_rx *rx, int id)
-{
-       bfa_q_qe_init(&rx->qe);
-       INIT_LIST_HEAD(&rx->rxp_q);
-       rx->bna = NULL;
-
-       rx->rxf.rxf_id = id;
-
-       /* FIXME: mbox_qe ctor()?? */
-       bfa_q_qe_init(&rx->mbox_qe.qe);
-
-       rx->stop_cbfn = NULL;
-       rx->stop_cbarg = NULL;
-}
-
-void
-bna_rx_cb_multi_rxq_stopped(void *arg, int status)
-{
-       struct bna_rxp *rxp = (struct bna_rxp *)arg;
-
-       bfa_wc_down(&rxp->rx->rxq_stop_wc);
-}
-
-void
-bna_rx_cb_rxq_stopped_all(void *arg)
-{
-       struct bna_rx *rx = (struct bna_rx *)arg;
-
-       bfa_fsm_send_event(rx, RX_E_RXQ_STOPPED);
-}
-
-static void
-bna_rx_mod_cb_rx_stopped(void *arg, struct bna_rx *rx,
-                        enum bna_cb_status status)
-{
-       struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
-
-       bfa_wc_down(&rx_mod->rx_stop_wc);
-}
-
-static void
-bna_rx_mod_cb_rx_stopped_all(void *arg)
-{
-       struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
-
-       if (rx_mod->stop_cbfn)
-               rx_mod->stop_cbfn(&rx_mod->bna->port, BNA_CB_SUCCESS);
-       rx_mod->stop_cbfn = NULL;
-}
-
-static void
-bna_rx_start(struct bna_rx *rx)
-{
-       rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
-       if (rx->rx_flags & BNA_RX_F_ENABLE)
-               bfa_fsm_send_event(rx, RX_E_START);
-}
-
-static void
-bna_rx_stop(struct bna_rx *rx)
-{
-       rx->rx_flags &= ~BNA_RX_F_PORT_ENABLED;
-       if (rx->fsm == (bfa_fsm_t) bna_rx_sm_stopped)
-               bna_rx_mod_cb_rx_stopped(&rx->bna->rx_mod, rx, BNA_CB_SUCCESS);
-       else {
-               rx->stop_cbfn = bna_rx_mod_cb_rx_stopped;
-               rx->stop_cbarg = &rx->bna->rx_mod;
-               bfa_fsm_send_event(rx, RX_E_STOP);
-       }
-}
-
-static void
-bna_rx_fail(struct bna_rx *rx)
-{
-       /* Indicate port is not enabled, and failed */
-       rx->rx_flags &= ~BNA_RX_F_PORT_ENABLED;
-       rx->rx_flags |= BNA_RX_F_PORT_FAILED;
-       bfa_fsm_send_event(rx, RX_E_FAIL);
-}
-
-void
-bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
-{
-       struct bna_rx *rx;
-       struct list_head *qe;
-
-       rx_mod->flags |= BNA_RX_MOD_F_PORT_STARTED;
-       if (type == BNA_RX_T_LOOPBACK)
-               rx_mod->flags |= BNA_RX_MOD_F_PORT_LOOPBACK;
-
-       list_for_each(qe, &rx_mod->rx_active_q) {
-               rx = (struct bna_rx *)qe;
-               if (rx->type == type)
-                       bna_rx_start(rx);
-       }
-}
-
-void
-bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
-{
-       struct bna_rx *rx;
-       struct list_head *qe;
-
-       rx_mod->flags &= ~BNA_RX_MOD_F_PORT_STARTED;
-       rx_mod->flags &= ~BNA_RX_MOD_F_PORT_LOOPBACK;
-
-       rx_mod->stop_cbfn = bna_port_cb_rx_stopped;
-
-       /**
-        * Before calling bna_rx_stop(), increment rx_stop_wc as many times
-        * as we are going to call bna_rx_stop
-        */
-       list_for_each(qe, &rx_mod->rx_active_q) {
-               rx = (struct bna_rx *)qe;
-               if (rx->type == type)
-                       bfa_wc_up(&rx_mod->rx_stop_wc);
-       }
-
-       if (rx_mod->rx_stop_wc.wc_count == 0) {
-               rx_mod->stop_cbfn(&rx_mod->bna->port, BNA_CB_SUCCESS);
-               rx_mod->stop_cbfn = NULL;
-               return;
-       }
-
-       list_for_each(qe, &rx_mod->rx_active_q) {
-               rx = (struct bna_rx *)qe;
-               if (rx->type == type)
-                       bna_rx_stop(rx);
-       }
-}
-
-void
-bna_rx_mod_fail(struct bna_rx_mod *rx_mod)
-{
-       struct bna_rx *rx;
-       struct list_head *qe;
-
-       rx_mod->flags &= ~BNA_RX_MOD_F_PORT_STARTED;
-       rx_mod->flags &= ~BNA_RX_MOD_F_PORT_LOOPBACK;
-
-       list_for_each(qe, &rx_mod->rx_active_q) {
-               rx = (struct bna_rx *)qe;
-               bna_rx_fail(rx);
-       }
-}
-
-void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
-                       struct bna_res_info *res_info)
-{
-       int     index;
-       struct bna_rx *rx_ptr;
-       struct bna_rxp *rxp_ptr;
-       struct bna_rxq *rxq_ptr;
-
-       rx_mod->bna = bna;
-       rx_mod->flags = 0;
-
-       rx_mod->rx = (struct bna_rx *)
-               res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.mdl[0].kva;
-       rx_mod->rxp = (struct bna_rxp *)
-               res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mdl[0].kva;
-       rx_mod->rxq = (struct bna_rxq *)
-               res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mdl[0].kva;
-
-       /* Initialize the queues */
-       _init_rxmod_queues(rx_mod);
-
-       /* Build RX queues */
-       for (index = 0; index < BFI_MAX_RXQ; index++) {
-               rx_ptr = &rx_mod->rx[index];
-               _rx_ctor(rx_ptr, index);
-               list_add_tail(&rx_ptr->qe, &rx_mod->rx_free_q);
-               rx_mod->rx_free_count++;
-       }
-
-       /* build RX-path queue */
-       for (index = 0; index < BFI_MAX_RXQ; index++) {
-               rxp_ptr = &rx_mod->rxp[index];
-               rxp_ptr->cq.cq_id = index;
-               bfa_q_qe_init(&rxp_ptr->qe);
-               list_add_tail(&rxp_ptr->qe, &rx_mod->rxp_free_q);
-               rx_mod->rxp_free_count++;
-       }
-
-       /* build RXQ queue */
-       for (index = 0; index < BFI_MAX_RXQ; index++) {
-               rxq_ptr = &rx_mod->rxq[index];
-               rxq_ptr->rxq_id = index;
-
-               bfa_q_qe_init(&rxq_ptr->qe);
-               list_add_tail(&rxq_ptr->qe, &rx_mod->rxq_free_q);
-               rx_mod->rxq_free_count++;
-       }
-
-       rx_mod->rx_stop_wc.wc_resume = bna_rx_mod_cb_rx_stopped_all;
-       rx_mod->rx_stop_wc.wc_cbarg = rx_mod;
-       rx_mod->rx_stop_wc.wc_count = 0;
-}
-
-void
-bna_rx_mod_uninit(struct bna_rx_mod *rx_mod)
-{
-       struct list_head                *qe;
-       int i;
-
-       i = 0;
-       list_for_each(qe, &rx_mod->rx_free_q)
-               i++;
-
-       i = 0;
-       list_for_each(qe, &rx_mod->rxp_free_q)
-               i++;
-
-       i = 0;
-       list_for_each(qe, &rx_mod->rxq_free_q)
-               i++;
-
-       rx_mod->bna = NULL;
-}
-
-int
-bna_rx_state_get(struct bna_rx *rx)
-{
-       return bfa_sm_to_state(rx_sm_table, rx->fsm);
-}
-
-void
-bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info)
-{
-       u32 cq_size, hq_size, dq_size;
-       u32 cpage_count, hpage_count, dpage_count;
-       struct bna_mem_info *mem_info;
-       u32 cq_depth;
-       u32 hq_depth;
-       u32 dq_depth;
-
-       dq_depth = q_cfg->q_depth;
-       hq_depth = ((q_cfg->rxp_type == BNA_RXP_SINGLE) ? 0 : q_cfg->q_depth);
-       cq_depth = dq_depth + hq_depth;
-
-       BNA_TO_POWER_OF_2_HIGH(cq_depth);
-       cq_size = cq_depth * BFI_CQ_WI_SIZE;
-       cq_size = ALIGN(cq_size, PAGE_SIZE);
-       cpage_count = SIZE_TO_PAGES(cq_size);
-
-       BNA_TO_POWER_OF_2_HIGH(dq_depth);
-       dq_size = dq_depth * BFI_RXQ_WI_SIZE;
-       dq_size = ALIGN(dq_size, PAGE_SIZE);
-       dpage_count = SIZE_TO_PAGES(dq_size);
-
-       if (BNA_RXP_SINGLE != q_cfg->rxp_type) {
-               BNA_TO_POWER_OF_2_HIGH(hq_depth);
-               hq_size = hq_depth * BFI_RXQ_WI_SIZE;
-               hq_size = ALIGN(hq_size, PAGE_SIZE);
-               hpage_count = SIZE_TO_PAGES(hq_size);
-       } else {
-               hpage_count = 0;
-       }
-
-       /* CCB structures */
-       res_info[BNA_RX_RES_MEM_T_CCB].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_KVA;
-       mem_info->len = sizeof(struct bna_ccb);
-       mem_info->num = q_cfg->num_paths;
-
-       /* RCB structures */
-       res_info[BNA_RX_RES_MEM_T_RCB].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_KVA;
-       mem_info->len = sizeof(struct bna_rcb);
-       mem_info->num = BNA_GET_RXQS(q_cfg);
-
-       /* Completion QPT */
-       res_info[BNA_RX_RES_MEM_T_CQPT].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_DMA;
-       mem_info->len = cpage_count * sizeof(struct bna_dma_addr);
-       mem_info->num = q_cfg->num_paths;
-
-       /* Completion s/w QPT */
-       res_info[BNA_RX_RES_MEM_T_CSWQPT].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_KVA;
-       mem_info->len = cpage_count * sizeof(void *);
-       mem_info->num = q_cfg->num_paths;
-
-       /* Completion QPT pages */
-       res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_DMA;
-       mem_info->len = PAGE_SIZE;
-       mem_info->num = cpage_count * q_cfg->num_paths;
-
-       /* Data QPTs */
-       res_info[BNA_RX_RES_MEM_T_DQPT].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_DMA;
-       mem_info->len = dpage_count * sizeof(struct bna_dma_addr);
-       mem_info->num = q_cfg->num_paths;
-
-       /* Data s/w QPTs */
-       res_info[BNA_RX_RES_MEM_T_DSWQPT].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_KVA;
-       mem_info->len = dpage_count * sizeof(void *);
-       mem_info->num = q_cfg->num_paths;
-
-       /* Data QPT pages */
-       res_info[BNA_RX_RES_MEM_T_DPAGE].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_DMA;
-       mem_info->len = PAGE_SIZE;
-       mem_info->num = dpage_count * q_cfg->num_paths;
-
-       /* Hdr QPTs */
-       res_info[BNA_RX_RES_MEM_T_HQPT].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_DMA;
-       mem_info->len = hpage_count * sizeof(struct bna_dma_addr);
-       mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
-
-       /* Hdr s/w QPTs */
-       res_info[BNA_RX_RES_MEM_T_HSWQPT].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_KVA;
-       mem_info->len = hpage_count * sizeof(void *);
-       mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
-
-       /* Hdr QPT pages */
-       res_info[BNA_RX_RES_MEM_T_HPAGE].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_DMA;
-       mem_info->len = (hpage_count ? PAGE_SIZE : 0);
-       mem_info->num = (hpage_count ? (hpage_count * q_cfg->num_paths) : 0);
-
-       /* RX Interrupts */
-       res_info[BNA_RX_RES_T_INTR].res_type = BNA_RES_T_INTR;
-       res_info[BNA_RX_RES_T_INTR].res_u.intr_info.intr_type = BNA_INTR_T_MSIX;
-       res_info[BNA_RX_RES_T_INTR].res_u.intr_info.num = q_cfg->num_paths;
-}
-
-struct bna_rx *
-bna_rx_create(struct bna *bna, struct bnad *bnad,
-               struct bna_rx_config *rx_cfg,
-               struct bna_rx_event_cbfn *rx_cbfn,
-               struct bna_res_info *res_info,
-               void *priv)
-{
-       struct bna_rx_mod *rx_mod = &bna->rx_mod;
-       struct bna_rx *rx;
-       struct bna_rxp *rxp;
-       struct bna_rxq *q0;
-       struct bna_rxq *q1;
-       struct bna_intr_info *intr_info;
-       u32 page_count;
-       struct bna_mem_descr *ccb_mem;
-       struct bna_mem_descr *rcb_mem;
-       struct bna_mem_descr *unmapq_mem;
-       struct bna_mem_descr *cqpt_mem;
-       struct bna_mem_descr *cswqpt_mem;
-       struct bna_mem_descr *cpage_mem;
-       struct bna_mem_descr *hqpt_mem; /* Header/Small Q qpt */
-       struct bna_mem_descr *dqpt_mem; /* Data/Large Q qpt */
-       struct bna_mem_descr *hsqpt_mem;        /* s/w qpt for hdr */
-       struct bna_mem_descr *dsqpt_mem;        /* s/w qpt for data */
-       struct bna_mem_descr *hpage_mem;        /* hdr page mem */
-       struct bna_mem_descr *dpage_mem;        /* data page mem */
-       int i, cpage_idx = 0, dpage_idx = 0, hpage_idx = 0;
-       int dpage_count, hpage_count, rcb_idx;
-       struct bna_ib_config ibcfg;
-       /* Fail if we don't have enough RXPs, RXQs */
-       if (!_rx_can_satisfy(rx_mod, rx_cfg))
-               return NULL;
-
-       /* Initialize resource pointers */
-       intr_info = &res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
-       ccb_mem = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info.mdl[0];
-       rcb_mem = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info.mdl[0];
-       unmapq_mem = &res_info[BNA_RX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[0];
-       cqpt_mem = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info.mdl[0];
-       cswqpt_mem = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info.mdl[0];
-       cpage_mem = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.mdl[0];
-       hqpt_mem = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info.mdl[0];
-       dqpt_mem = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info.mdl[0];
-       hsqpt_mem = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info.mdl[0];
-       dsqpt_mem = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info.mdl[0];
-       hpage_mem = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.mdl[0];
-       dpage_mem = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.mdl[0];
-
-       /* Compute q depth & page count */
-       page_count = res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.num /
-                       rx_cfg->num_paths;
-
-       dpage_count = res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.num /
-                       rx_cfg->num_paths;
-
-       hpage_count = res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.num /
-                       rx_cfg->num_paths;
-       /* Get RX pointer */
-       rx = _get_free_rx(rx_mod);
-       _rx_init(rx, bna);
-       rx->priv = priv;
-       rx->type = rx_cfg->rx_type;
-
-       rx->rcb_setup_cbfn = rx_cbfn->rcb_setup_cbfn;
-       rx->rcb_destroy_cbfn = rx_cbfn->rcb_destroy_cbfn;
-       rx->ccb_setup_cbfn = rx_cbfn->ccb_setup_cbfn;
-       rx->ccb_destroy_cbfn = rx_cbfn->ccb_destroy_cbfn;
-       /* Following callbacks are mandatory */
-       rx->rx_cleanup_cbfn = rx_cbfn->rx_cleanup_cbfn;
-       rx->rx_post_cbfn = rx_cbfn->rx_post_cbfn;
-
-       if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_PORT_STARTED) {
-               switch (rx->type) {
-               case BNA_RX_T_REGULAR:
-                       if (!(rx->bna->rx_mod.flags &
-                               BNA_RX_MOD_F_PORT_LOOPBACK))
-                               rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
-                       break;
-               case BNA_RX_T_LOOPBACK:
-                       if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_PORT_LOOPBACK)
-                               rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
-                       break;
-               }
-       }
-
-       for (i = 0, rcb_idx = 0; i < rx_cfg->num_paths; i++) {
-               rxp = _get_free_rxp(rx_mod);
-               rxp->type = rx_cfg->rxp_type;
-               rxp->rx = rx;
-               rxp->cq.rx = rx;
-
-               /* Get required RXQs, and queue them to rx-path */
-               q0 = _get_free_rxq(rx_mod);
-               if (BNA_RXP_SINGLE == rx_cfg->rxp_type)
-                       q1 = NULL;
-               else
-                       q1 = _get_free_rxq(rx_mod);
-
-               /* Initialize IB */
-               if (1 == intr_info->num) {
-                       rxp->cq.ib = bna_ib_get(&bna->ib_mod,
-                                       intr_info->intr_type,
-                                       intr_info->idl[0].vector);
-                       rxp->vector = intr_info->idl[0].vector;
-               } else {
-                       rxp->cq.ib = bna_ib_get(&bna->ib_mod,
-                                       intr_info->intr_type,
-                                       intr_info->idl[i].vector);
-
-                       /* Map the MSI-x vector used for this RXP */
-                       rxp->vector = intr_info->idl[i].vector;
-               }
-
-               rxp->cq.ib_seg_offset = bna_ib_reserve_idx(rxp->cq.ib);
-
-               ibcfg.coalescing_timeo = BFI_RX_COALESCING_TIMEO;
-               ibcfg.interpkt_count = BFI_RX_INTERPKT_COUNT;
-               ibcfg.interpkt_timeo = BFI_RX_INTERPKT_TIMEO;
-               ibcfg.ctrl_flags = BFI_IB_CF_INT_ENABLE;
-
-               bna_ib_config(rxp->cq.ib, &ibcfg);
-
-               /* Link rxqs to rxp */
-               _rxp_add_rxqs(rxp, q0, q1);
-
-               /* Link rxp to rx */
-               _rx_add_rxp(rx, rxp);
-
-               q0->rx = rx;
-               q0->rxp = rxp;
-
-               /* Initialize RCB for the large / data q */
-               q0->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
-               RXQ_RCB_INIT(q0, rxp, rx_cfg->q_depth, bna, 0,
-                       (void *)unmapq_mem[rcb_idx].kva);
-               rcb_idx++;
-               (q0)->rx_packets = (q0)->rx_bytes = 0;
-               (q0)->rx_packets_with_error = (q0)->rxbuf_alloc_failed = 0;
-
-               /* Initialize RXQs */
-               _rxq_qpt_init(q0, rxp, dpage_count, PAGE_SIZE,
-                       &dqpt_mem[i], &dsqpt_mem[i], &dpage_mem[dpage_idx]);
-               q0->rcb->page_idx = dpage_idx;
-               q0->rcb->page_count = dpage_count;
-               dpage_idx += dpage_count;
-
-               /* Call bnad to complete rcb setup */
-               if (rx->rcb_setup_cbfn)
-                       rx->rcb_setup_cbfn(bnad, q0->rcb);
-
-               if (q1) {
-                       q1->rx = rx;
-                       q1->rxp = rxp;
-
-                       q1->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
-                       RXQ_RCB_INIT(q1, rxp, rx_cfg->q_depth, bna, 1,
-                               (void *)unmapq_mem[rcb_idx].kva);
-                       rcb_idx++;
-                       (q1)->buffer_size = (rx_cfg)->small_buff_size;
-                       (q1)->rx_packets = (q1)->rx_bytes = 0;
-                       (q1)->rx_packets_with_error =
-                               (q1)->rxbuf_alloc_failed = 0;
-
-                       _rxq_qpt_init(q1, rxp, hpage_count, PAGE_SIZE,
-                               &hqpt_mem[i], &hsqpt_mem[i],
-                               &hpage_mem[hpage_idx]);
-                       q1->rcb->page_idx = hpage_idx;
-                       q1->rcb->page_count = hpage_count;
-                       hpage_idx += hpage_count;
-
-                       /* Call bnad to complete rcb setup */
-                       if (rx->rcb_setup_cbfn)
-                               rx->rcb_setup_cbfn(bnad, q1->rcb);
-               }
-               /* Setup RXP::CQ */
-               rxp->cq.ccb = (struct bna_ccb *) ccb_mem[i].kva;
-               _rxp_cqpt_setup(rxp, page_count, PAGE_SIZE,
-                       &cqpt_mem[i], &cswqpt_mem[i], &cpage_mem[cpage_idx]);
-               rxp->cq.ccb->page_idx = cpage_idx;
-               rxp->cq.ccb->page_count = page_count;
-               cpage_idx += page_count;
-
-               rxp->cq.ccb->pkt_rate.small_pkt_cnt = 0;
-               rxp->cq.ccb->pkt_rate.large_pkt_cnt = 0;
-
-               rxp->cq.ccb->producer_index = 0;
-               rxp->cq.ccb->q_depth =  rx_cfg->q_depth +
-                                       ((rx_cfg->rxp_type == BNA_RXP_SINGLE) ?
-                                       0 : rx_cfg->q_depth);
-               rxp->cq.ccb->i_dbell = &rxp->cq.ib->door_bell;
-               rxp->cq.ccb->rcb[0] = q0->rcb;
-               if (q1)
-                       rxp->cq.ccb->rcb[1] = q1->rcb;
-               rxp->cq.ccb->cq = &rxp->cq;
-               rxp->cq.ccb->bnad = bna->bnad;
-               rxp->cq.ccb->hw_producer_index =
-                       ((volatile u32 *)rxp->cq.ib->ib_seg_host_addr_kva +
-                                     (rxp->cq.ib_seg_offset * BFI_IBIDX_SIZE));
-               *(rxp->cq.ccb->hw_producer_index) = 0;
-               rxp->cq.ccb->intr_type = intr_info->intr_type;
-               rxp->cq.ccb->intr_vector = (intr_info->num == 1) ?
-                                               intr_info->idl[0].vector :
-                                               intr_info->idl[i].vector;
-               rxp->cq.ccb->rx_coalescing_timeo =
-                                       rxp->cq.ib->ib_config.coalescing_timeo;
-               rxp->cq.ccb->id = i;
-
-               /* Call bnad to complete CCB setup */
-               if (rx->ccb_setup_cbfn)
-                       rx->ccb_setup_cbfn(bnad, rxp->cq.ccb);
-
-       } /* for each rx-path */
-
-       bna_rxf_init(&rx->rxf, rx, rx_cfg);
-
-       bfa_fsm_set_state(rx, bna_rx_sm_stopped);
-
-       return rx;
-}
-
-void
-bna_rx_destroy(struct bna_rx *rx)
-{
-       struct bna_rx_mod *rx_mod = &rx->bna->rx_mod;
-       struct bna_ib_mod *ib_mod = &rx->bna->ib_mod;
-       struct bna_rxq *q0 = NULL;
-       struct bna_rxq *q1 = NULL;
-       struct bna_rxp *rxp;
-       struct list_head *qe;
-
-       bna_rxf_uninit(&rx->rxf);
-
-       while (!list_empty(&rx->rxp_q)) {
-               bfa_q_deq(&rx->rxp_q, &rxp);
-               GET_RXQS(rxp, q0, q1);
-               /* Callback to bnad for destroying RCB */
-               if (rx->rcb_destroy_cbfn)
-                       rx->rcb_destroy_cbfn(rx->bna->bnad, q0->rcb);
-               q0->rcb = NULL;
-               q0->rxp = NULL;
-               q0->rx = NULL;
-               _put_free_rxq(rx_mod, q0);
-               if (q1) {
-                       /* Callback to bnad for destroying RCB */
-                       if (rx->rcb_destroy_cbfn)
-                               rx->rcb_destroy_cbfn(rx->bna->bnad, q1->rcb);
-                       q1->rcb = NULL;
-                       q1->rxp = NULL;
-                       q1->rx = NULL;
-                       _put_free_rxq(rx_mod, q1);
-               }
-               rxp->rxq.slr.large = NULL;
-               rxp->rxq.slr.small = NULL;
-               if (rxp->cq.ib) {
-                       if (rxp->cq.ib_seg_offset != 0xff)
-                               bna_ib_release_idx(rxp->cq.ib,
-                                               rxp->cq.ib_seg_offset);
-                       bna_ib_put(ib_mod, rxp->cq.ib);
-                       rxp->cq.ib = NULL;
-               }
-               /* Callback to bnad for destroying CCB */
-               if (rx->ccb_destroy_cbfn)
-                       rx->ccb_destroy_cbfn(rx->bna->bnad, rxp->cq.ccb);
-               rxp->cq.ccb = NULL;
-               rxp->rx = NULL;
-               _put_free_rxp(rx_mod, rxp);
-       }
-
-       list_for_each(qe, &rx_mod->rx_active_q) {
-               if (qe == &rx->qe) {
-                       list_del(&rx->qe);
-                       bfa_q_qe_init(&rx->qe);
-                       break;
-               }
-       }
-
-       rx->bna = NULL;
-       rx->priv = NULL;
-       _put_free_rx(rx_mod, rx);
-}
-
-void
-bna_rx_enable(struct bna_rx *rx)
-{
-       if (rx->fsm != (bfa_sm_t)bna_rx_sm_stopped)
-               return;
-
-       rx->rx_flags |= BNA_RX_F_ENABLE;
-       if (rx->rx_flags & BNA_RX_F_PORT_ENABLED)
-               bfa_fsm_send_event(rx, RX_E_START);
-}
-
-void
-bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type,
-               void (*cbfn)(void *, struct bna_rx *,
-                               enum bna_cb_status))
-{
-       if (type == BNA_SOFT_CLEANUP) {
-               /* h/w should not be accessed. Treat we're stopped */
-               (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
-       } else {
-               rx->stop_cbfn = cbfn;
-               rx->stop_cbarg = rx->bna->bnad;
-
-               rx->rx_flags &= ~BNA_RX_F_ENABLE;
-
-               bfa_fsm_send_event(rx, RX_E_STOP);
-       }
-}
-
-/**
- * TX
- */
-#define call_tx_stop_cbfn(tx, status)\
-do {\
-       if ((tx)->stop_cbfn)\
-               (tx)->stop_cbfn((tx)->stop_cbarg, (tx), status);\
-       (tx)->stop_cbfn = NULL;\
-       (tx)->stop_cbarg = NULL;\
-} while (0)
-
-#define call_tx_prio_change_cbfn(tx, status)\
-do {\
-       if ((tx)->prio_change_cbfn)\
-               (tx)->prio_change_cbfn((tx)->bna->bnad, (tx), status);\
-       (tx)->prio_change_cbfn = NULL;\
-} while (0)
-
-static void bna_tx_mod_cb_tx_stopped(void *tx_mod, struct bna_tx *tx,
-                                       enum bna_cb_status status);
-static void bna_tx_cb_txq_stopped(void *arg, int status);
-static void bna_tx_cb_stats_cleared(void *arg, int status);
-static void __bna_tx_stop(struct bna_tx *tx);
-static void __bna_tx_start(struct bna_tx *tx);
-static void __bna_txf_stat_clr(struct bna_tx *tx);
-
-enum bna_tx_event {
-       TX_E_START                      = 1,
-       TX_E_STOP                       = 2,
-       TX_E_FAIL                       = 3,
-       TX_E_TXQ_STOPPED                = 4,
-       TX_E_PRIO_CHANGE                = 5,
-       TX_E_STAT_CLEARED               = 6,
-};
-
-enum bna_tx_state {
-       BNA_TX_STOPPED                  = 1,
-       BNA_TX_STARTED                  = 2,
-       BNA_TX_TXQ_STOP_WAIT            = 3,
-       BNA_TX_PRIO_STOP_WAIT           = 4,
-       BNA_TX_STAT_CLR_WAIT            = 5,
-};
-
-bfa_fsm_state_decl(bna_tx, stopped, struct bna_tx,
-                       enum bna_tx_event);
-bfa_fsm_state_decl(bna_tx, started, struct bna_tx,
-                       enum bna_tx_event);
-bfa_fsm_state_decl(bna_tx, txq_stop_wait, struct bna_tx,
-                       enum bna_tx_event);
-bfa_fsm_state_decl(bna_tx, prio_stop_wait, struct bna_tx,
-                       enum bna_tx_event);
-bfa_fsm_state_decl(bna_tx, stat_clr_wait, struct bna_tx,
-                       enum bna_tx_event);
-
-static struct bfa_sm_table tx_sm_table[] = {
-       {BFA_SM(bna_tx_sm_stopped), BNA_TX_STOPPED},
-       {BFA_SM(bna_tx_sm_started), BNA_TX_STARTED},
-       {BFA_SM(bna_tx_sm_txq_stop_wait), BNA_TX_TXQ_STOP_WAIT},
-       {BFA_SM(bna_tx_sm_prio_stop_wait), BNA_TX_PRIO_STOP_WAIT},
-       {BFA_SM(bna_tx_sm_stat_clr_wait), BNA_TX_STAT_CLR_WAIT},
-};
-
-static void
-bna_tx_sm_stopped_entry(struct bna_tx *tx)
-{
-       struct bna_txq *txq;
-       struct list_head                 *qe;
-
-       list_for_each(qe, &tx->txq_q) {
-               txq = (struct bna_txq *)qe;
-               (tx->tx_cleanup_cbfn)(tx->bna->bnad, txq->tcb);
-       }
-
-       call_tx_stop_cbfn(tx, BNA_CB_SUCCESS);
-}
-
-static void
-bna_tx_sm_stopped(struct bna_tx *tx, enum bna_tx_event event)
-{
-       switch (event) {
-       case TX_E_START:
-               bfa_fsm_set_state(tx, bna_tx_sm_started);
-               break;
-
-       case TX_E_STOP:
-               bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-               break;
-
-       case TX_E_FAIL:
-               /* No-op */
-               break;
-
-       case TX_E_PRIO_CHANGE:
-               call_tx_prio_change_cbfn(tx, BNA_CB_SUCCESS);
-               break;
-
-       case TX_E_TXQ_STOPPED:
-               /**
-                * This event is received due to flushing of mbox when
-                * device fails
-                */
-               /* No-op */
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_tx_sm_started_entry(struct bna_tx *tx)
-{
-       struct bna_txq *txq;
-       struct list_head                 *qe;
-
-       __bna_tx_start(tx);
-
-       /* Start IB */
-       list_for_each(qe, &tx->txq_q) {
-               txq = (struct bna_txq *)qe;
-               bna_ib_ack(&txq->ib->door_bell, 0);
-       }
-}
-
-static void
-bna_tx_sm_started(struct bna_tx *tx, enum bna_tx_event event)
-{
-       struct bna_txq *txq;
-       struct list_head                 *qe;
-
-       switch (event) {
-       case TX_E_STOP:
-               bfa_fsm_set_state(tx, bna_tx_sm_txq_stop_wait);
-               __bna_tx_stop(tx);
-               break;
-
-       case TX_E_FAIL:
-               list_for_each(qe, &tx->txq_q) {
-                       txq = (struct bna_txq *)qe;
-                       bna_ib_fail(txq->ib);
-                       (tx->tx_stall_cbfn)(tx->bna->bnad, txq->tcb);
-               }
-               bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-               break;
-
-       case TX_E_PRIO_CHANGE:
-               bfa_fsm_set_state(tx, bna_tx_sm_prio_stop_wait);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_tx_sm_txq_stop_wait_entry(struct bna_tx *tx)
-{
-}
-
-static void
-bna_tx_sm_txq_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
-{
-       struct bna_txq *txq;
-       struct list_head                 *qe;
-
-       switch (event) {
-       case TX_E_FAIL:
-               bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-               break;
-
-       case TX_E_TXQ_STOPPED:
-               list_for_each(qe, &tx->txq_q) {
-                       txq = (struct bna_txq *)qe;
-                       bna_ib_stop(txq->ib);
-               }
-               bfa_fsm_set_state(tx, bna_tx_sm_stat_clr_wait);
-               break;
-
-       case TX_E_PRIO_CHANGE:
-               /* No-op */
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_tx_sm_prio_stop_wait_entry(struct bna_tx *tx)
-{
-       __bna_tx_stop(tx);
-}
-
-static void
-bna_tx_sm_prio_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
-{
-       struct bna_txq *txq;
-       struct list_head                 *qe;
-
-       switch (event) {
-       case TX_E_STOP:
-               bfa_fsm_set_state(tx, bna_tx_sm_txq_stop_wait);
-               break;
-
-       case TX_E_FAIL:
-               call_tx_prio_change_cbfn(tx, BNA_CB_FAIL);
-               bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-               break;
-
-       case TX_E_TXQ_STOPPED:
-               list_for_each(qe, &tx->txq_q) {
-                       txq = (struct bna_txq *)qe;
-                       bna_ib_stop(txq->ib);
-                       (tx->tx_cleanup_cbfn)(tx->bna->bnad, txq->tcb);
-               }
-               call_tx_prio_change_cbfn(tx, BNA_CB_SUCCESS);
-               bfa_fsm_set_state(tx, bna_tx_sm_started);
-               break;
-
-       case TX_E_PRIO_CHANGE:
-               /* No-op */
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-bna_tx_sm_stat_clr_wait_entry(struct bna_tx *tx)
-{
-       __bna_txf_stat_clr(tx);
-}
-
-static void
-bna_tx_sm_stat_clr_wait(struct bna_tx *tx, enum bna_tx_event event)
-{
-       switch (event) {
-       case TX_E_FAIL:
-       case TX_E_STAT_CLEARED:
-               bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-               break;
-
-       default:
-               bfa_sm_fault(event);
-       }
-}
-
-static void
-__bna_txq_start(struct bna_tx *tx, struct bna_txq *txq)
-{
-       struct bna_rxtx_q_mem *q_mem;
-       struct bna_txq_mem txq_cfg;
-       struct bna_txq_mem *txq_mem;
-       struct bna_dma_addr cur_q_addr;
-       u32 pg_num;
-       void __iomem *base_addr;
-       unsigned long off;
-
-       /* Fill out structure, to be subsequently written to hardware */
-       txq_cfg.pg_tbl_addr_lo = txq->qpt.hw_qpt_ptr.lsb;
-       txq_cfg.pg_tbl_addr_hi = txq->qpt.hw_qpt_ptr.msb;
-       cur_q_addr = *((struct bna_dma_addr *)(txq->qpt.kv_qpt_ptr));
-       txq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
-       txq_cfg.cur_q_entry_hi = cur_q_addr.msb;
-
-       txq_cfg.pg_cnt_n_prd_ptr = (txq->qpt.page_count << 16) | 0x0;
-
-       txq_cfg.entry_n_pg_size = ((u32)(BFI_TXQ_WI_SIZE >> 2) << 16) |
-                       (txq->qpt.page_size >> 2);
-       txq_cfg.int_blk_n_cns_ptr = ((((u32)txq->ib_seg_offset) << 24) |
-                       ((u32)(txq->ib->ib_id & 0xff) << 16) | 0x0);
-
-       txq_cfg.cns_ptr2_n_q_state = BNA_Q_IDLE_STATE;
-       txq_cfg.nxt_qid_n_fid_n_pri = (((tx->txf.txf_id & 0x3f) << 3) |
-                       (txq->priority & 0x7));
-       txq_cfg.wvc_n_cquota_n_rquota =
-                       ((((u32)BFI_TX_MAX_WRR_QUOTA & 0xfff) << 12) |
-                       (BFI_TX_MAX_WRR_QUOTA & 0xfff));
-
-       /* Setup the page and write to H/W */
-
-       pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + tx->bna->port_num,
-                       HQM_RXTX_Q_RAM_BASE_OFFSET);
-       writel(pg_num, tx->bna->regs.page_addr);
-
-       base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
-                                       HQM_RXTX_Q_RAM_BASE_OFFSET);
-       q_mem = (struct bna_rxtx_q_mem *)0;
-       txq_mem = &q_mem[txq->txq_id].txq;
-
-       /*
-        * The following 4 lines, is a hack b'cos the H/W needs to read
-        * these DMA addresses as little endian
-        */
-
-       off = (unsigned long)&txq_mem->pg_tbl_addr_lo;
-       writel(htonl(txq_cfg.pg_tbl_addr_lo), base_addr + off);
-
-       off = (unsigned long)&txq_mem->pg_tbl_addr_hi;
-       writel(htonl(txq_cfg.pg_tbl_addr_hi), base_addr + off);
-
-       off = (unsigned long)&txq_mem->cur_q_entry_lo;
-       writel(htonl(txq_cfg.cur_q_entry_lo), base_addr + off);
-
-       off = (unsigned long)&txq_mem->cur_q_entry_hi;
-       writel(htonl(txq_cfg.cur_q_entry_hi), base_addr + off);
-
-       off = (unsigned long)&txq_mem->pg_cnt_n_prd_ptr;
-       writel(txq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
-
-       off = (unsigned long)&txq_mem->entry_n_pg_size;
-       writel(txq_cfg.entry_n_pg_size, base_addr + off);
-
-       off = (unsigned long)&txq_mem->int_blk_n_cns_ptr;
-       writel(txq_cfg.int_blk_n_cns_ptr, base_addr + off);
-
-       off = (unsigned long)&txq_mem->cns_ptr2_n_q_state;
-       writel(txq_cfg.cns_ptr2_n_q_state, base_addr + off);
-
-       off = (unsigned long)&txq_mem->nxt_qid_n_fid_n_pri;
-       writel(txq_cfg.nxt_qid_n_fid_n_pri, base_addr + off);
-
-       off = (unsigned long)&txq_mem->wvc_n_cquota_n_rquota;
-       writel(txq_cfg.wvc_n_cquota_n_rquota, base_addr + off);
-
-       txq->tcb->producer_index = 0;
-       txq->tcb->consumer_index = 0;
-       *(txq->tcb->hw_consumer_index) = 0;
-
-}
-
-static void
-__bna_txq_stop(struct bna_tx *tx, struct bna_txq *txq)
-{
-       struct bfi_ll_q_stop_req ll_req;
-       u32 bit_mask[2] = {0, 0};
-       if (txq->txq_id < 32)
-               bit_mask[0] = (u32)1 << txq->txq_id;
-       else
-               bit_mask[1] = (u32)1 << (txq->txq_id - 32);
-
-       memset(&ll_req, 0, sizeof(ll_req));
-       ll_req.mh.msg_class = BFI_MC_LL;
-       ll_req.mh.msg_id = BFI_LL_H2I_TXQ_STOP_REQ;
-       ll_req.mh.mtag.h2i.lpu_id = 0;
-       ll_req.q_id_mask[0] = htonl(bit_mask[0]);
-       ll_req.q_id_mask[1] = htonl(bit_mask[1]);
-
-       bna_mbox_qe_fill(&tx->mbox_qe, &ll_req, sizeof(ll_req),
-                       bna_tx_cb_txq_stopped, tx);
-
-       bna_mbox_send(tx->bna, &tx->mbox_qe);
-}
-
-static void
-__bna_txf_start(struct bna_tx *tx)
-{
-       struct bna_tx_fndb_ram *tx_fndb;
-       struct bna_txf *txf = &tx->txf;
-       void __iomem *base_addr;
-       unsigned long off;
-
-       writel(BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
-                       (tx->bna->port_num * 2), TX_FNDB_RAM_BASE_OFFSET),
-                       tx->bna->regs.page_addr);
-
-       base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
-                                       TX_FNDB_RAM_BASE_OFFSET);
-
-       tx_fndb = (struct bna_tx_fndb_ram *)0;
-       off = (unsigned long)&tx_fndb[txf->txf_id].vlan_n_ctrl_flags;
-
-       writel(((u32)txf->vlan << 16) | txf->ctrl_flags,
-                       base_addr + off);
-
-       if (tx->txf.txf_id < 32)
-               tx->bna->tx_mod.txf_bmap[0] |= ((u32)1 << tx->txf.txf_id);
-       else
-               tx->bna->tx_mod.txf_bmap[1] |= ((u32)
-                                                1 << (tx->txf.txf_id - 32));
-}
-
-static void
-__bna_txf_stop(struct bna_tx *tx)
-{
-       struct bna_tx_fndb_ram *tx_fndb;
-       u32 page_num;
-       u32 ctl_flags;
-       struct bna_txf *txf = &tx->txf;
-       void __iomem *base_addr;
-       unsigned long off;
-
-       /* retrieve the running txf_flags & turn off enable bit */
-       page_num = BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
-                       (tx->bna->port_num * 2), TX_FNDB_RAM_BASE_OFFSET);
-       writel(page_num, tx->bna->regs.page_addr);
-
-       base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
-                                       TX_FNDB_RAM_BASE_OFFSET);
-       tx_fndb = (struct bna_tx_fndb_ram *)0;
-       off = (unsigned long)&tx_fndb[txf->txf_id].vlan_n_ctrl_flags;
-
-       ctl_flags = readl(base_addr + off);
-       ctl_flags &= ~BFI_TXF_CF_ENABLE;
-
-       writel(ctl_flags, base_addr + off);
-
-       if (tx->txf.txf_id < 32)
-               tx->bna->tx_mod.txf_bmap[0] &= ~((u32)1 << tx->txf.txf_id);
-       else
-               tx->bna->tx_mod.txf_bmap[0] &= ~((u32)
-                                                1 << (tx->txf.txf_id - 32));
-}
-
-static void
-__bna_txf_stat_clr(struct bna_tx *tx)
-{
-       struct bfi_ll_stats_req ll_req;
-       u32 txf_bmap[2] = {0, 0};
-       if (tx->txf.txf_id < 32)
-               txf_bmap[0] = ((u32)1 << tx->txf.txf_id);
-       else
-               txf_bmap[1] = ((u32)1 << (tx->txf.txf_id - 32));
-       bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0);
-       ll_req.stats_mask = 0;
-       ll_req.rxf_id_mask[0] = 0;
-       ll_req.rxf_id_mask[1] = 0;
-       ll_req.txf_id_mask[0] = htonl(txf_bmap[0]);
-       ll_req.txf_id_mask[1] = htonl(txf_bmap[1]);
-
-       bna_mbox_qe_fill(&tx->mbox_qe, &ll_req, sizeof(ll_req),
-                       bna_tx_cb_stats_cleared, tx);
-       bna_mbox_send(tx->bna, &tx->mbox_qe);
-}
-
-static void
-__bna_tx_start(struct bna_tx *tx)
-{
-       struct bna_txq *txq;
-       struct list_head                 *qe;
-
-       list_for_each(qe, &tx->txq_q) {
-               txq = (struct bna_txq *)qe;
-               bna_ib_start(txq->ib);
-               __bna_txq_start(tx, txq);
-       }
-
-       __bna_txf_start(tx);
-
-       list_for_each(qe, &tx->txq_q) {
-               txq = (struct bna_txq *)qe;
-               txq->tcb->priority = txq->priority;
-               (tx->tx_resume_cbfn)(tx->bna->bnad, txq->tcb);
-       }
-}
-
-static void
-__bna_tx_stop(struct bna_tx *tx)
-{
-       struct bna_txq *txq;
-       struct list_head                 *qe;
-
-       list_for_each(qe, &tx->txq_q) {
-               txq = (struct bna_txq *)qe;
-               (tx->tx_stall_cbfn)(tx->bna->bnad, txq->tcb);
-       }
-
-       __bna_txf_stop(tx);
-
-       list_for_each(qe, &tx->txq_q) {
-               txq = (struct bna_txq *)qe;
-               bfa_wc_up(&tx->txq_stop_wc);
-       }
-
-       list_for_each(qe, &tx->txq_q) {
-               txq = (struct bna_txq *)qe;
-               __bna_txq_stop(tx, txq);
-       }
-}
-
-static void
-bna_txq_qpt_setup(struct bna_txq *txq, int page_count, int page_size,
-               struct bna_mem_descr *qpt_mem,
-               struct bna_mem_descr *swqpt_mem,
-               struct bna_mem_descr *page_mem)
-{
-       int i;
-
-       txq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
-       txq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
-       txq->qpt.kv_qpt_ptr = qpt_mem->kva;
-       txq->qpt.page_count = page_count;
-       txq->qpt.page_size = page_size;
-
-       txq->tcb->sw_qpt = (void **) swqpt_mem->kva;
-
-       for (i = 0; i < page_count; i++) {
-               txq->tcb->sw_qpt[i] = page_mem[i].kva;
-
-               ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].lsb =
-                       page_mem[i].dma.lsb;
-               ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].msb =
-                       page_mem[i].dma.msb;
-
-       }
-}
-
-static void
-bna_tx_free(struct bna_tx *tx)
-{
-       struct bna_tx_mod *tx_mod = &tx->bna->tx_mod;
-       struct bna_txq *txq;
-       struct bna_ib_mod *ib_mod = &tx->bna->ib_mod;
-       struct list_head *qe;
-
-       while (!list_empty(&tx->txq_q)) {
-               bfa_q_deq(&tx->txq_q, &txq);
-               bfa_q_qe_init(&txq->qe);
-               if (txq->ib) {
-                       if (txq->ib_seg_offset != -1)
-                               bna_ib_release_idx(txq->ib,
-                                               txq->ib_seg_offset);
-                       bna_ib_put(ib_mod, txq->ib);
-                       txq->ib = NULL;
-               }
-               txq->tcb = NULL;
-               txq->tx = NULL;
-               list_add_tail(&txq->qe, &tx_mod->txq_free_q);
-       }
-
-       list_for_each(qe, &tx_mod->tx_active_q) {
-               if (qe == &tx->qe) {
-                       list_del(&tx->qe);
-                       bfa_q_qe_init(&tx->qe);
-                       break;
-               }
-       }
-
-       tx->bna = NULL;
-       tx->priv = NULL;
-       list_add_tail(&tx->qe, &tx_mod->tx_free_q);
-}
-
-static void
-bna_tx_cb_txq_stopped(void *arg, int status)
-{
-       struct bna_tx *tx = (struct bna_tx *)arg;
-
-       bfa_q_qe_init(&tx->mbox_qe.qe);
-       bfa_wc_down(&tx->txq_stop_wc);
-}
-
-static void
-bna_tx_cb_txq_stopped_all(void *arg)
-{
-       struct bna_tx *tx = (struct bna_tx *)arg;
-
-       bfa_fsm_send_event(tx, TX_E_TXQ_STOPPED);
-}
-
-static void
-bna_tx_cb_stats_cleared(void *arg, int status)
-{
-       struct bna_tx *tx = (struct bna_tx *)arg;
-
-       bfa_q_qe_init(&tx->mbox_qe.qe);
-
-       bfa_fsm_send_event(tx, TX_E_STAT_CLEARED);
-}
-
-static void
-bna_tx_start(struct bna_tx *tx)
-{
-       tx->flags |= BNA_TX_F_PORT_STARTED;
-       if (tx->flags & BNA_TX_F_ENABLED)
-               bfa_fsm_send_event(tx, TX_E_START);
-}
-
-static void
-bna_tx_stop(struct bna_tx *tx)
-{
-       tx->stop_cbfn = bna_tx_mod_cb_tx_stopped;
-       tx->stop_cbarg = &tx->bna->tx_mod;
-
-       tx->flags &= ~BNA_TX_F_PORT_STARTED;
-       bfa_fsm_send_event(tx, TX_E_STOP);
-}
-
-static void
-bna_tx_fail(struct bna_tx *tx)
-{
-       tx->flags &= ~BNA_TX_F_PORT_STARTED;
-       bfa_fsm_send_event(tx, TX_E_FAIL);
-}
-
-static void
-bna_tx_prio_changed(struct bna_tx *tx, int prio)
-{
-       struct bna_txq *txq;
-       struct list_head                 *qe;
-
-       list_for_each(qe, &tx->txq_q) {
-               txq = (struct bna_txq *)qe;
-               txq->priority = prio;
-       }
-
-       bfa_fsm_send_event(tx, TX_E_PRIO_CHANGE);
-}
-
-static void
-bna_tx_cee_link_status(struct bna_tx *tx, int cee_link)
-{
-       if (cee_link)
-               tx->flags |= BNA_TX_F_PRIO_LOCK;
-       else
-               tx->flags &= ~BNA_TX_F_PRIO_LOCK;
-}
-
-static void
-bna_tx_mod_cb_tx_stopped(void *arg, struct bna_tx *tx,
-                       enum bna_cb_status status)
-{
-       struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
-
-       bfa_wc_down(&tx_mod->tx_stop_wc);
-}
-
-static void
-bna_tx_mod_cb_tx_stopped_all(void *arg)
-{
-       struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
-
-       if (tx_mod->stop_cbfn)
-               tx_mod->stop_cbfn(&tx_mod->bna->port, BNA_CB_SUCCESS);
-       tx_mod->stop_cbfn = NULL;
-}
-
-void
-bna_tx_res_req(int num_txq, int txq_depth, struct bna_res_info *res_info)
-{
-       u32 q_size;
-       u32 page_count;
-       struct bna_mem_info *mem_info;
-
-       res_info[BNA_TX_RES_MEM_T_TCB].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_KVA;
-       mem_info->len = sizeof(struct bna_tcb);
-       mem_info->num = num_txq;
-
-       q_size = txq_depth * BFI_TXQ_WI_SIZE;
-       q_size = ALIGN(q_size, PAGE_SIZE);
-       page_count = q_size >> PAGE_SHIFT;
-
-       res_info[BNA_TX_RES_MEM_T_QPT].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_DMA;
-       mem_info->len = page_count * sizeof(struct bna_dma_addr);
-       mem_info->num = num_txq;
-
-       res_info[BNA_TX_RES_MEM_T_SWQPT].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_KVA;
-       mem_info->len = page_count * sizeof(void *);
-       mem_info->num = num_txq;
-
-       res_info[BNA_TX_RES_MEM_T_PAGE].res_type = BNA_RES_T_MEM;
-       mem_info = &res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info;
-       mem_info->mem_type = BNA_MEM_T_DMA;
-       mem_info->len = PAGE_SIZE;
-       mem_info->num = num_txq * page_count;
-
-       res_info[BNA_TX_RES_INTR_T_TXCMPL].res_type = BNA_RES_T_INTR;
-       res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.intr_type =
-                       BNA_INTR_T_MSIX;
-       res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.num = num_txq;
-}
-
-struct bna_tx *
-bna_tx_create(struct bna *bna, struct bnad *bnad,
-               struct bna_tx_config *tx_cfg,
-               struct bna_tx_event_cbfn *tx_cbfn,
-               struct bna_res_info *res_info, void *priv)
-{
-       struct bna_intr_info *intr_info;
-       struct bna_tx_mod *tx_mod = &bna->tx_mod;
-       struct bna_tx *tx;
-       struct bna_txq *txq;
-       struct list_head *qe;
-       struct bna_ib_mod *ib_mod = &bna->ib_mod;
-       struct bna_doorbell_qset *qset;
-       struct bna_ib_config ib_config;
-       int page_count;
-       int page_size;
-       int page_idx;
-       int i;
-       unsigned long off;
-
-       intr_info = &res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info;
-       page_count = (res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.num) /
-                       tx_cfg->num_txq;
-       page_size = res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.len;
-
-       /**
-        * Get resources
-        */
-
-       if ((intr_info->num != 1) && (intr_info->num != tx_cfg->num_txq))
-               return NULL;
-
-       /* Tx */
-
-       if (list_empty(&tx_mod->tx_free_q))
-               return NULL;
-       bfa_q_deq(&tx_mod->tx_free_q, &tx);
-       bfa_q_qe_init(&tx->qe);
-
-       /* TxQs */
-
-       INIT_LIST_HEAD(&tx->txq_q);
-       for (i = 0; i < tx_cfg->num_txq; i++) {
-               if (list_empty(&tx_mod->txq_free_q))
-                       goto err_return;
-
-               bfa_q_deq(&tx_mod->txq_free_q, &txq);
-               bfa_q_qe_init(&txq->qe);
-               list_add_tail(&txq->qe, &tx->txq_q);
-               txq->ib = NULL;
-               txq->ib_seg_offset = -1;
-               txq->tx = tx;
-       }
-
-       /* IBs */
-       i = 0;
-       list_for_each(qe, &tx->txq_q) {
-               txq = (struct bna_txq *)qe;
-
-               if (intr_info->num == 1)
-                       txq->ib = bna_ib_get(ib_mod, intr_info->intr_type,
-                                               intr_info->idl[0].vector);
-               else
-                       txq->ib = bna_ib_get(ib_mod, intr_info->intr_type,
-                                               intr_info->idl[i].vector);
-
-               if (txq->ib == NULL)
-                       goto err_return;
-
-               txq->ib_seg_offset = bna_ib_reserve_idx(txq->ib);
-               if (txq->ib_seg_offset == -1)
-                       goto err_return;
-
-               i++;
-       }
-
-       /*
-        * Initialize
-        */
-
-       /* Tx */
-
-       tx->tcb_setup_cbfn = tx_cbfn->tcb_setup_cbfn;
-       tx->tcb_destroy_cbfn = tx_cbfn->tcb_destroy_cbfn;
-       /* Following callbacks are mandatory */
-       tx->tx_stall_cbfn = tx_cbfn->tx_stall_cbfn;
-       tx->tx_resume_cbfn = tx_cbfn->tx_resume_cbfn;
-       tx->tx_cleanup_cbfn = tx_cbfn->tx_cleanup_cbfn;
-
-       list_add_tail(&tx->qe, &tx_mod->tx_active_q);
-       tx->bna = bna;
-       tx->priv = priv;
-       tx->txq_stop_wc.wc_resume = bna_tx_cb_txq_stopped_all;
-       tx->txq_stop_wc.wc_cbarg = tx;
-       tx->txq_stop_wc.wc_count = 0;
-
-       tx->type = tx_cfg->tx_type;
-
-       tx->flags = 0;
-       if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_PORT_STARTED) {
-               switch (tx->type) {
-               case BNA_TX_T_REGULAR:
-                       if (!(tx->bna->tx_mod.flags &
-                               BNA_TX_MOD_F_PORT_LOOPBACK))
-                               tx->flags |= BNA_TX_F_PORT_STARTED;
-                       break;
-               case BNA_TX_T_LOOPBACK:
-                       if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_PORT_LOOPBACK)
-                               tx->flags |= BNA_TX_F_PORT_STARTED;
-                       break;
-               }
-       }
-       if (tx->bna->tx_mod.cee_link)
-               tx->flags |= BNA_TX_F_PRIO_LOCK;
-
-       /* TxQ */
-
-       i = 0;
-       page_idx = 0;
-       list_for_each(qe, &tx->txq_q) {
-               txq = (struct bna_txq *)qe;
-               txq->priority = tx_mod->priority;
-               txq->tcb = (struct bna_tcb *)
-                 res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info.mdl[i].kva;
-               txq->tx_packets = 0;
-               txq->tx_bytes = 0;
-
-               /* IB */
-
-               ib_config.coalescing_timeo = BFI_TX_COALESCING_TIMEO;
-               ib_config.interpkt_timeo = 0; /* Not used */
-               ib_config.interpkt_count = BFI_TX_INTERPKT_COUNT;
-               ib_config.ctrl_flags = (BFI_IB_CF_INTER_PKT_DMA |
-                                       BFI_IB_CF_INT_ENABLE |
-                                       BFI_IB_CF_COALESCING_MODE);
-               bna_ib_config(txq->ib, &ib_config);
-
-               /* TCB */
-
-               txq->tcb->producer_index = 0;
-               txq->tcb->consumer_index = 0;
-               txq->tcb->hw_consumer_index = (volatile u32 *)
-                       ((volatile u8 *)txq->ib->ib_seg_host_addr_kva +
-                        (txq->ib_seg_offset * BFI_IBIDX_SIZE));
-               *(txq->tcb->hw_consumer_index) = 0;
-               txq->tcb->q_depth = tx_cfg->txq_depth;
-               txq->tcb->unmap_q = (void *)
-               res_info[BNA_TX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[i].kva;
-               qset = (struct bna_doorbell_qset *)0;
-               off = (unsigned long)&qset[txq->txq_id].txq[0];
-               txq->tcb->q_dbell = off +
-                       BNA_GET_DOORBELL_BASE_ADDR(bna->pcidev.pci_bar_kva);
-               txq->tcb->i_dbell = &txq->ib->door_bell;
-               txq->tcb->intr_type = intr_info->intr_type;
-               txq->tcb->intr_vector = (intr_info->num == 1) ?
-                                       intr_info->idl[0].vector :
-                                       intr_info->idl[i].vector;
-               txq->tcb->txq = txq;
-               txq->tcb->bnad = bnad;
-               txq->tcb->id = i;
-
-               /* QPT, SWQPT, Pages */
-               bna_txq_qpt_setup(txq, page_count, page_size,
-                       &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info.mdl[i],
-                       &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info.mdl[i],
-                       &res_info[BNA_TX_RES_MEM_T_PAGE].
-                                 res_u.mem_info.mdl[page_idx]);
-               txq->tcb->page_idx = page_idx;
-               txq->tcb->page_count = page_count;
-               page_idx += page_count;
-
-               /* Callback to bnad for setting up TCB */
-               if (tx->tcb_setup_cbfn)
-                       (tx->tcb_setup_cbfn)(bna->bnad, txq->tcb);
-
-               i++;
-       }
-
-       /* TxF */
-
-       tx->txf.ctrl_flags = BFI_TXF_CF_ENABLE | BFI_TXF_CF_VLAN_WI_BASED;
-       tx->txf.vlan = 0;
-
-       /* Mbox element */
-       bfa_q_qe_init(&tx->mbox_qe.qe);
-
-       bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-
-       return tx;
-
-err_return:
-       bna_tx_free(tx);
-       return NULL;
-}
-
-void
-bna_tx_destroy(struct bna_tx *tx)
-{
-       /* Callback to bnad for destroying TCB */
-       if (tx->tcb_destroy_cbfn) {
-               struct bna_txq *txq;
-               struct list_head *qe;
-
-               list_for_each(qe, &tx->txq_q) {
-                       txq = (struct bna_txq *)qe;
-                       (tx->tcb_destroy_cbfn)(tx->bna->bnad, txq->tcb);
-               }
-       }
-
-       bna_tx_free(tx);
-}
-
-void
-bna_tx_enable(struct bna_tx *tx)
-{
-       if (tx->fsm != (bfa_sm_t)bna_tx_sm_stopped)
-               return;
-
-       tx->flags |= BNA_TX_F_ENABLED;
-
-       if (tx->flags & BNA_TX_F_PORT_STARTED)
-               bfa_fsm_send_event(tx, TX_E_START);
-}
-
-void
-bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type,
-               void (*cbfn)(void *, struct bna_tx *, enum bna_cb_status))
-{
-       if (type == BNA_SOFT_CLEANUP) {
-               (*cbfn)(tx->bna->bnad, tx, BNA_CB_SUCCESS);
-               return;
-       }
-
-       tx->stop_cbfn = cbfn;
-       tx->stop_cbarg = tx->bna->bnad;
-
-       tx->flags &= ~BNA_TX_F_ENABLED;
-
-       bfa_fsm_send_event(tx, TX_E_STOP);
-}
-
-int
-bna_tx_state_get(struct bna_tx *tx)
-{
-       return bfa_sm_to_state(tx_sm_table, tx->fsm);
-}
-
-void
-bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna,
-               struct bna_res_info *res_info)
-{
-       int i;
-
-       tx_mod->bna = bna;
-       tx_mod->flags = 0;
-
-       tx_mod->tx = (struct bna_tx *)
-               res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.mdl[0].kva;
-       tx_mod->txq = (struct bna_txq *)
-               res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mdl[0].kva;
-
-       INIT_LIST_HEAD(&tx_mod->tx_free_q);
-       INIT_LIST_HEAD(&tx_mod->tx_active_q);
-
-       INIT_LIST_HEAD(&tx_mod->txq_free_q);
-
-       for (i = 0; i < BFI_MAX_TXQ; i++) {
-               tx_mod->tx[i].txf.txf_id = i;
-               bfa_q_qe_init(&tx_mod->tx[i].qe);
-               list_add_tail(&tx_mod->tx[i].qe, &tx_mod->tx_free_q);
-
-               tx_mod->txq[i].txq_id = i;
-               bfa_q_qe_init(&tx_mod->txq[i].qe);
-               list_add_tail(&tx_mod->txq[i].qe, &tx_mod->txq_free_q);
-       }
-
-       tx_mod->tx_stop_wc.wc_resume = bna_tx_mod_cb_tx_stopped_all;
-       tx_mod->tx_stop_wc.wc_cbarg = tx_mod;
-       tx_mod->tx_stop_wc.wc_count = 0;
-}
-
-void
-bna_tx_mod_uninit(struct bna_tx_mod *tx_mod)
-{
-       struct list_head                *qe;
-       int i;
-
-       i = 0;
-       list_for_each(qe, &tx_mod->tx_free_q)
-               i++;
-
-       i = 0;
-       list_for_each(qe, &tx_mod->txq_free_q)
-               i++;
-
-       tx_mod->bna = NULL;
-}
-
-void
-bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
-{
-       struct bna_tx *tx;
-       struct list_head                *qe;
-
-       tx_mod->flags |= BNA_TX_MOD_F_PORT_STARTED;
-       if (type == BNA_TX_T_LOOPBACK)
-               tx_mod->flags |= BNA_TX_MOD_F_PORT_LOOPBACK;
-
-       list_for_each(qe, &tx_mod->tx_active_q) {
-               tx = (struct bna_tx *)qe;
-               if (tx->type == type)
-                       bna_tx_start(tx);
-       }
-}
-
-void
-bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
-{
-       struct bna_tx *tx;
-       struct list_head                *qe;
-
-       tx_mod->flags &= ~BNA_TX_MOD_F_PORT_STARTED;
-       tx_mod->flags &= ~BNA_TX_MOD_F_PORT_LOOPBACK;
-
-       tx_mod->stop_cbfn = bna_port_cb_tx_stopped;
-
-       /**
-        * Before calling bna_tx_stop(), increment tx_stop_wc as many times
-        * as we are going to call bna_tx_stop
-        */
-       list_for_each(qe, &tx_mod->tx_active_q) {
-               tx = (struct bna_tx *)qe;
-               if (tx->type == type)
-                       bfa_wc_up(&tx_mod->tx_stop_wc);
-       }
-
-       if (tx_mod->tx_stop_wc.wc_count == 0) {
-               tx_mod->stop_cbfn(&tx_mod->bna->port, BNA_CB_SUCCESS);
-               tx_mod->stop_cbfn = NULL;
-               return;
-       }
-
-       list_for_each(qe, &tx_mod->tx_active_q) {
-               tx = (struct bna_tx *)qe;
-               if (tx->type == type)
-                       bna_tx_stop(tx);
-       }
-}
-
-void
-bna_tx_mod_fail(struct bna_tx_mod *tx_mod)
-{
-       struct bna_tx *tx;
-       struct list_head                *qe;
-
-       tx_mod->flags &= ~BNA_TX_MOD_F_PORT_STARTED;
-       tx_mod->flags &= ~BNA_TX_MOD_F_PORT_LOOPBACK;
-
-       list_for_each(qe, &tx_mod->tx_active_q) {
-               tx = (struct bna_tx *)qe;
-               bna_tx_fail(tx);
-       }
-}
-
-void
-bna_tx_mod_prio_changed(struct bna_tx_mod *tx_mod, int prio)
-{
-       struct bna_tx *tx;
-       struct list_head                *qe;
-
-       if (prio != tx_mod->priority) {
-               tx_mod->priority = prio;
-
-               list_for_each(qe, &tx_mod->tx_active_q) {
-                       tx = (struct bna_tx *)qe;
-                       bna_tx_prio_changed(tx, prio);
-               }
-       }
-}
-
-void
-bna_tx_mod_cee_link_status(struct bna_tx_mod *tx_mod, int cee_link)
-{
-       struct bna_tx *tx;
-       struct list_head                *qe;
-
-       tx_mod->cee_link = cee_link;
-
-       list_for_each(qe, &tx_mod->tx_active_q) {
-               tx = (struct bna_tx *)qe;
-               bna_tx_cee_link_status(tx, cee_link);
-       }
-}
index 38a83ac..8cb75a6 100644 (file)
@@ -3419,9 +3419,27 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
 static int bond_open(struct net_device *bond_dev)
 {
        struct bonding *bond = netdev_priv(bond_dev);
+       struct slave *slave;
+       int i;
 
        bond->kill_timers = 0;
 
+       /* reset slave->backup and slave->inactive */
+       read_lock(&bond->lock);
+       if (bond->slave_cnt > 0) {
+               read_lock(&bond->curr_slave_lock);
+               bond_for_each_slave(bond, slave, i) {
+                       if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+                               && (slave != bond->curr_active_slave)) {
+                               bond_set_slave_inactive_flags(slave);
+                       } else {
+                               bond_set_slave_active_flags(slave);
+                       }
+               }
+               read_unlock(&bond->curr_slave_lock);
+       }
+       read_unlock(&bond->lock);
+
        INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed);
 
        if (bond_is_lb(bond)) {
@@ -3686,44 +3704,27 @@ static bool bond_addr_in_mc_list(unsigned char *addr,
        return false;
 }
 
-static void bond_set_multicast_list(struct net_device *bond_dev)
+static void bond_change_rx_flags(struct net_device *bond_dev, int change)
 {
        struct bonding *bond = netdev_priv(bond_dev);
-       struct netdev_hw_addr *ha;
-       bool found;
 
-       /*
-        * Do promisc before checking multicast_mode
-        */
-       if ((bond_dev->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC))
-               /*
-                * FIXME: Need to handle the error when one of the multi-slaves
-                * encounters error.
-                */
-               bond_set_promiscuity(bond, 1);
+       if (change & IFF_PROMISC)
+               bond_set_promiscuity(bond,
+                                    bond_dev->flags & IFF_PROMISC ? 1 : -1);
 
+       if (change & IFF_ALLMULTI)
+               bond_set_allmulti(bond,
+                                 bond_dev->flags & IFF_ALLMULTI ? 1 : -1);
+}
 
-       if (!(bond_dev->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC))
-               bond_set_promiscuity(bond, -1);
-
-
-       /* set allmulti flag to slaves */
-       if ((bond_dev->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI))
-               /*
-                * FIXME: Need to handle the error when one of the multi-slaves
-                * encounters error.
-                */
-               bond_set_allmulti(bond, 1);
-
-
-       if (!(bond_dev->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI))
-               bond_set_allmulti(bond, -1);
-
+static void bond_set_multicast_list(struct net_device *bond_dev)
+{
+       struct bonding *bond = netdev_priv(bond_dev);
+       struct netdev_hw_addr *ha;
+       bool found;
 
        read_lock(&bond->lock);
 
-       bond->flags = bond_dev->flags;
-
        /* looking for addresses to add to slaves' mc list */
        netdev_for_each_mc_addr(ha, bond_dev) {
                found = bond_addr_in_mc_list(ha->addr, &bond->mc_list,
@@ -4282,7 +4283,8 @@ static const struct net_device_ops bond_netdev_ops = {
        .ndo_select_queue       = bond_select_queue,
        .ndo_get_stats64        = bond_get_stats,
        .ndo_do_ioctl           = bond_do_ioctl,
-       .ndo_set_multicast_list = bond_set_multicast_list,
+       .ndo_change_rx_flags    = bond_change_rx_flags,
+       .ndo_set_rx_mode        = bond_set_multicast_list,
        .ndo_change_mtu         = bond_change_mtu,
        .ndo_set_mac_address    = bond_set_mac_address,
        .ndo_neigh_setup        = bond_neigh_setup,
@@ -4828,11 +4830,20 @@ static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
        return 0;
 }
 
+static int bond_get_tx_queues(struct net *net, struct nlattr *tb[],
+                             unsigned int *num_queues,
+                             unsigned int *real_num_queues)
+{
+       *num_queues = tx_queues;
+       return 0;
+}
+
 static struct rtnl_link_ops bond_link_ops __read_mostly = {
        .kind           = "bond",
        .priv_size      = sizeof(struct bonding),
        .setup          = bond_setup,
        .validate       = bond_validate,
+       .get_tx_queues  = bond_get_tx_queues,
 };
 
 /* Create a new bond based on the specified name and bonding parameters.
index 43526a2..e823366 100644 (file)
@@ -234,7 +234,6 @@ struct bonding {
        struct   netdev_hw_addr_list mc_list;
        int      (*xmit_hash_policy)(struct sk_buff *, int);
        __be32   master_ip;
-       u16      flags;
        u16      rr_tx_counter;
        struct   ad_bond_info ad_info;
        struct   alb_bond_info alb_info;
index b41c2fc..2fcabba 100644 (file)
@@ -937,11 +937,8 @@ int cfhsi_probe(struct platform_device *pdev)
        int res;
 
        ndev = alloc_netdev(sizeof(struct cfhsi), "cfhsi%d", cfhsi_setup);
-       if (!ndev) {
-               dev_err(&pdev->dev, "%s: alloc_netdev failed.\n",
-                       __func__);
+       if (!ndev)
                return -ENODEV;
-       }
 
        cfhsi = netdev_priv(ndev);
        cfhsi->ndev = ndev;
@@ -969,8 +966,6 @@ int cfhsi_probe(struct platform_device *pdev)
         */
        cfhsi->tx_buf = kzalloc(CFHSI_BUF_SZ_TX, GFP_KERNEL);
        if (!cfhsi->tx_buf) {
-               dev_err(&ndev->dev, "%s: Failed to allocate TX buffer.\n",
-                       __func__);
                res = -ENODEV;
                goto err_alloc_tx;
        }
@@ -981,8 +976,6 @@ int cfhsi_probe(struct platform_device *pdev)
         */
        cfhsi->rx_buf = kzalloc(CFHSI_BUF_SZ_RX, GFP_KERNEL);
        if (!cfhsi->rx_buf) {
-               dev_err(&ndev->dev, "%s: Failed to allocate RX buffer.\n",
-                       __func__);
                res = -ENODEV;
                goto err_alloc_rx;
        }
index 0f8defc..05e791f 100644 (file)
@@ -664,8 +664,6 @@ int cfspi_spi_probe(struct platform_device *pdev)
        /* Allocate DMA buffers. */
        cfspi->xfer.va_tx = dma_alloc(&cfspi->xfer.pa_tx);
        if (!cfspi->xfer.va_tx) {
-               printk(KERN_WARNING
-                      "CFSPI: failed to allocate dma TX buffer.\n");
                res = -ENODEV;
                goto err_dma_alloc_tx;
        }
@@ -673,8 +671,6 @@ int cfspi_spi_probe(struct platform_device *pdev)
        cfspi->xfer.va_rx = dma_alloc(&cfspi->xfer.pa_rx);
 
        if (!cfspi->xfer.va_rx) {
-               printk(KERN_WARNING
-                      "CFSPI: failed to allocate dma TX buffer.\n");
                res = -ENODEV;
                goto err_dma_alloc_rx;
        }
index 1767811..e023379 100644 (file)
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 
-#include <mach/clock.h>
-
 #define DRV_NAME                       "flexcan"
 
 /* 8 for RX fifo and 2 error handling */
@@ -191,6 +190,31 @@ static struct can_bittiming_const flexcan_bittiming_const = {
        .brp_inc = 1,
 };
 
+/*
+ * Abstract off the read/write for arm versus ppc.
+ */
+#if defined(__BIG_ENDIAN)
+static inline u32 flexcan_read(void __iomem *addr)
+{
+       return in_be32(addr);
+}
+
+static inline void flexcan_write(u32 val, void __iomem *addr)
+{
+       out_be32(addr, val);
+}
+#else
+static inline u32 flexcan_read(void __iomem *addr)
+{
+       return readl(addr);
+}
+
+static inline void flexcan_write(u32 val, void __iomem *addr)
+{
+       writel(val, addr);
+}
+#endif
+
 /*
  * Swtich transceiver on or off
  */
@@ -212,9 +236,9 @@ static inline void flexcan_chip_enable(struct flexcan_priv *priv)
        struct flexcan_regs __iomem *regs = priv->base;
        u32 reg;
 
-       reg = readl(&regs->mcr);
+       reg = flexcan_read(&regs->mcr);
        reg &= ~FLEXCAN_MCR_MDIS;
-       writel(reg, &regs->mcr);
+       flexcan_write(reg, &regs->mcr);
 
        udelay(10);
 }
@@ -224,9 +248,9 @@ static inline void flexcan_chip_disable(struct flexcan_priv *priv)
        struct flexcan_regs __iomem *regs = priv->base;
        u32 reg;
 
-       reg = readl(&regs->mcr);
+       reg = flexcan_read(&regs->mcr);
        reg |= FLEXCAN_MCR_MDIS;
-       writel(reg, &regs->mcr);
+       flexcan_write(reg, &regs->mcr);
 }
 
 static int flexcan_get_berr_counter(const struct net_device *dev,
@@ -234,7 +258,7 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
 {
        const struct flexcan_priv *priv = netdev_priv(dev);
        struct flexcan_regs __iomem *regs = priv->base;
-       u32 reg = readl(&regs->ecr);
+       u32 reg = flexcan_read(&regs->ecr);
 
        bec->txerr = (reg >> 0) & 0xff;
        bec->rxerr = (reg >> 8) & 0xff;
@@ -268,15 +292,15 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        if (cf->can_dlc > 0) {
                u32 data = be32_to_cpup((__be32 *)&cf->data[0]);
-               writel(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
+               flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
        }
        if (cf->can_dlc > 3) {
                u32 data = be32_to_cpup((__be32 *)&cf->data[4]);
-               writel(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
+               flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
        }
 
-       writel(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
-       writel(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+       flexcan_write(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
+       flexcan_write(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
 
        kfree_skb(skb);
 
@@ -464,8 +488,8 @@ static void flexcan_read_fifo(const struct net_device *dev,
        struct flexcan_mb __iomem *mb = &regs->cantxfg[0];
        u32 reg_ctrl, reg_id;
 
-       reg_ctrl = readl(&mb->can_ctrl);
-       reg_id = readl(&mb->can_id);
+       reg_ctrl = flexcan_read(&mb->can_ctrl);
+       reg_id = flexcan_read(&mb->can_id);
        if (reg_ctrl & FLEXCAN_MB_CNT_IDE)
                cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
        else
@@ -475,12 +499,12 @@ static void flexcan_read_fifo(const struct net_device *dev,
                cf->can_id |= CAN_RTR_FLAG;
        cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf);
 
-       *(__be32 *)(cf->data + 0) = cpu_to_be32(readl(&mb->data[0]));
-       *(__be32 *)(cf->data + 4) = cpu_to_be32(readl(&mb->data[1]));
+       *(__be32 *)(cf->data + 0) = cpu_to_be32(flexcan_read(&mb->data[0]));
+       *(__be32 *)(cf->data + 4) = cpu_to_be32(flexcan_read(&mb->data[1]));
 
        /* mark as read */
-       writel(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
-       readl(&regs->timer);
+       flexcan_write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
+       flexcan_read(&regs->timer);
 }
 
 static int flexcan_read_frame(struct net_device *dev)
@@ -516,17 +540,17 @@ static int flexcan_poll(struct napi_struct *napi, int quota)
         * The error bits are cleared on read,
         * use saved value from irq handler.
         */
-       reg_esr = readl(&regs->esr) | priv->reg_esr;
+       reg_esr = flexcan_read(&regs->esr) | priv->reg_esr;
 
        /* handle state changes */
        work_done += flexcan_poll_state(dev, reg_esr);
 
        /* handle RX-FIFO */
-       reg_iflag1 = readl(&regs->iflag1);
+       reg_iflag1 = flexcan_read(&regs->iflag1);
        while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE &&
               work_done < quota) {
                work_done += flexcan_read_frame(dev);
-               reg_iflag1 = readl(&regs->iflag1);
+               reg_iflag1 = flexcan_read(&regs->iflag1);
        }
 
        /* report bus errors */
@@ -536,8 +560,8 @@ static int flexcan_poll(struct napi_struct *napi, int quota)
        if (work_done < quota) {
                napi_complete(napi);
                /* enable IRQs */
-               writel(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
-               writel(priv->reg_ctrl_default, &regs->ctrl);
+               flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
+               flexcan_write(priv->reg_ctrl_default, &regs->ctrl);
        }
 
        return work_done;
@@ -551,9 +575,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
        struct flexcan_regs __iomem *regs = priv->base;
        u32 reg_iflag1, reg_esr;
 
-       reg_iflag1 = readl(&regs->iflag1);
-       reg_esr = readl(&regs->esr);
-       writel(FLEXCAN_ESR_ERR_INT, &regs->esr);        /* ACK err IRQ */
+       reg_iflag1 = flexcan_read(&regs->iflag1);
+       reg_esr = flexcan_read(&regs->esr);
+       flexcan_write(FLEXCAN_ESR_ERR_INT, &regs->esr); /* ACK err IRQ */
 
        /*
         * schedule NAPI in case of:
@@ -569,16 +593,16 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
                 * save them for later use.
                 */
                priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS;
-               writel(FLEXCAN_IFLAG_DEFAULT & ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE,
-                      &regs->imask1);
-               writel(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
+               flexcan_write(FLEXCAN_IFLAG_DEFAULT &
+                       ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->imask1);
+               flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
                       &regs->ctrl);
                napi_schedule(&priv->napi);
        }
 
        /* FIFO overflow */
        if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) {
-               writel(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, &regs->iflag1);
+               flexcan_write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, &regs->iflag1);
                dev->stats.rx_over_errors++;
                dev->stats.rx_errors++;
        }
@@ -587,7 +611,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
        if (reg_iflag1 & (1 << FLEXCAN_TX_BUF_ID)) {
                /* tx_bytes is incremented in flexcan_start_xmit */
                stats->tx_packets++;
-               writel((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
+               flexcan_write((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
                netif_wake_queue(dev);
        }
 
@@ -601,7 +625,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
        struct flexcan_regs __iomem *regs = priv->base;
        u32 reg;
 
-       reg = readl(&regs->ctrl);
+       reg = flexcan_read(&regs->ctrl);
        reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) |
                 FLEXCAN_CTRL_RJW(0x3) |
                 FLEXCAN_CTRL_PSEG1(0x7) |
@@ -625,11 +649,11 @@ static void flexcan_set_bittiming(struct net_device *dev)
                reg |= FLEXCAN_CTRL_SMP;
 
        dev_info(dev->dev.parent, "writing ctrl=0x%08x\n", reg);
-       writel(reg, &regs->ctrl);
+       flexcan_write(reg, &regs->ctrl);
 
        /* print chip status */
        dev_dbg(dev->dev.parent, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__,
-               readl(&regs->mcr), readl(&regs->ctrl));
+               flexcan_read(&regs->mcr), flexcan_read(&regs->ctrl));
 }
 
 /*
@@ -650,10 +674,10 @@ static int flexcan_chip_start(struct net_device *dev)
        flexcan_chip_enable(priv);
 
        /* soft reset */
-       writel(FLEXCAN_MCR_SOFTRST, &regs->mcr);
+       flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
        udelay(10);
 
-       reg_mcr = readl(&regs->mcr);
+       reg_mcr = flexcan_read(&regs->mcr);
        if (reg_mcr & FLEXCAN_MCR_SOFTRST) {
                dev_err(dev->dev.parent,
                        "Failed to softreset can module (mcr=0x%08x)\n",
@@ -675,12 +699,12 @@ static int flexcan_chip_start(struct net_device *dev)
         * choose format C
         *
         */
-       reg_mcr = readl(&regs->mcr);
+       reg_mcr = flexcan_read(&regs->mcr);
        reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
                FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
                FLEXCAN_MCR_IDAM_C;
        dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr);
-       writel(reg_mcr, &regs->mcr);
+       flexcan_write(reg_mcr, &regs->mcr);
 
        /*
         * CTRL
@@ -698,7 +722,7 @@ static int flexcan_chip_start(struct net_device *dev)
         * (FLEXCAN_CTRL_ERR_MSK), too. Otherwise we don't get any
         * warning or bus passive interrupts.
         */
-       reg_ctrl = readl(&regs->ctrl);
+       reg_ctrl = flexcan_read(&regs->ctrl);
        reg_ctrl &= ~FLEXCAN_CTRL_TSYN;
        reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
                FLEXCAN_CTRL_ERR_STATE | FLEXCAN_CTRL_ERR_MSK;
@@ -706,38 +730,39 @@ static int flexcan_chip_start(struct net_device *dev)
        /* save for later use */
        priv->reg_ctrl_default = reg_ctrl;
        dev_dbg(dev->dev.parent, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
-       writel(reg_ctrl, &regs->ctrl);
+       flexcan_write(reg_ctrl, &regs->ctrl);
 
        for (i = 0; i < ARRAY_SIZE(regs->cantxfg); i++) {
-               writel(0, &regs->cantxfg[i].can_ctrl);
-               writel(0, &regs->cantxfg[i].can_id);
-               writel(0, &regs->cantxfg[i].data[0]);
-               writel(0, &regs->cantxfg[i].data[1]);
+               flexcan_write(0, &regs->cantxfg[i].can_ctrl);
+               flexcan_write(0, &regs->cantxfg[i].can_id);
+               flexcan_write(0, &regs->cantxfg[i].data[0]);
+               flexcan_write(0, &regs->cantxfg[i].data[1]);
 
                /* put MB into rx queue */
-               writel(FLEXCAN_MB_CNT_CODE(0x4), &regs->cantxfg[i].can_ctrl);
+               flexcan_write(FLEXCAN_MB_CNT_CODE(0x4),
+                       &regs->cantxfg[i].can_ctrl);
        }
 
        /* acceptance mask/acceptance code (accept everything) */
-       writel(0x0, &regs->rxgmask);
-       writel(0x0, &regs->rx14mask);
-       writel(0x0, &regs->rx15mask);
+       flexcan_write(0x0, &regs->rxgmask);
+       flexcan_write(0x0, &regs->rx14mask);
+       flexcan_write(0x0, &regs->rx15mask);
 
        flexcan_transceiver_switch(priv, 1);
 
        /* synchronize with the can bus */
-       reg_mcr = readl(&regs->mcr);
+       reg_mcr = flexcan_read(&regs->mcr);
        reg_mcr &= ~FLEXCAN_MCR_HALT;
-       writel(reg_mcr, &regs->mcr);
+       flexcan_write(reg_mcr, &regs->mcr);
 
        priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
        /* enable FIFO interrupts */
-       writel(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
+       flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
 
        /* print chip status */
        dev_dbg(dev->dev.parent, "%s: reading mcr=0x%08x ctrl=0x%08x\n",
-               __func__, readl(&regs->mcr), readl(&regs->ctrl));
+               __func__, flexcan_read(&regs->mcr), flexcan_read(&regs->ctrl));
 
        return 0;
 
@@ -759,12 +784,12 @@ static void flexcan_chip_stop(struct net_device *dev)
        u32 reg;
 
        /* Disable all interrupts */
-       writel(0, &regs->imask1);
+       flexcan_write(0, &regs->imask1);
 
        /* Disable + halt module */
-       reg = readl(&regs->mcr);
+       reg = flexcan_read(&regs->mcr);
        reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT;
-       writel(reg, &regs->mcr);
+       flexcan_write(reg, &regs->mcr);
 
        flexcan_transceiver_switch(priv, 0);
        priv->can.state = CAN_STATE_STOPPED;
@@ -856,24 +881,24 @@ static int __devinit register_flexcandev(struct net_device *dev)
 
        /* select "bus clock", chip must be disabled */
        flexcan_chip_disable(priv);
-       reg = readl(&regs->ctrl);
+       reg = flexcan_read(&regs->ctrl);
        reg |= FLEXCAN_CTRL_CLK_SRC;
-       writel(reg, &regs->ctrl);
+       flexcan_write(reg, &regs->ctrl);
 
        flexcan_chip_enable(priv);
 
        /* set freeze, halt and activate FIFO, restrict register access */
-       reg = readl(&regs->mcr);
+       reg = flexcan_read(&regs->mcr);
        reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
                FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
-       writel(reg, &regs->mcr);
+       flexcan_write(reg, &regs->mcr);
 
        /*
         * Currently we only support newer versions of this core
         * featuring a RX FIFO. Older cores found on some Coldfire
         * derivates are not yet supported.
         */
-       reg = readl(&regs->mcr);
+       reg = flexcan_read(&regs->mcr);
        if (!(reg & FLEXCAN_MCR_FEN)) {
                dev_err(dev->dev.parent,
                        "Could not enable RX FIFO, unsupported core\n");
@@ -901,16 +926,29 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
        struct net_device *dev;
        struct flexcan_priv *priv;
        struct resource *mem;
-       struct clk *clk;
+       struct clk *clk = NULL;
        void __iomem *base;
        resource_size_t mem_size;
        int err, irq;
+       u32 clock_freq = 0;
+
+       if (pdev->dev.of_node) {
+               const u32 *clock_freq_p;
 
-       clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(clk)) {
-               dev_err(&pdev->dev, "no clock defined\n");
-               err = PTR_ERR(clk);
-               goto failed_clock;
+               clock_freq_p = of_get_property(pdev->dev.of_node,
+                                               "clock-frequency", NULL);
+               if (clock_freq_p)
+                       clock_freq = *clock_freq_p;
+       }
+
+       if (!clock_freq) {
+               clk = clk_get(&pdev->dev, NULL);
+               if (IS_ERR(clk)) {
+                       dev_err(&pdev->dev, "no clock defined\n");
+                       err = PTR_ERR(clk);
+                       goto failed_clock;
+               }
+               clock_freq = clk_get_rate(clk);
        }
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -943,7 +981,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
        dev->flags |= IFF_ECHO; /* we support local echo in hardware */
 
        priv = netdev_priv(dev);
-       priv->can.clock.freq = clk_get_rate(clk);
+       priv->can.clock.freq = clock_freq;
        priv->can.bittiming_const = &flexcan_bittiming_const;
        priv->can.do_set_mode = flexcan_set_mode;
        priv->can.do_get_berr_counter = flexcan_get_berr_counter;
@@ -978,7 +1016,8 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
  failed_map:
        release_mem_region(mem->start, mem_size);
  failed_get:
-       clk_put(clk);
+       if (clk)
+               clk_put(clk);
  failed_clock:
        return err;
 }
@@ -996,15 +1035,27 @@ static int __devexit flexcan_remove(struct platform_device *pdev)
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(mem->start, resource_size(mem));
 
-       clk_put(priv->clk);
+       if (priv->clk)
+               clk_put(priv->clk);
 
        free_candev(dev);
 
        return 0;
 }
 
+static struct of_device_id flexcan_of_match[] = {
+       {
+               .compatible = "fsl,p1010-flexcan",
+       },
+       {},
+};
+
 static struct platform_driver flexcan_driver = {
-       .driver.name = DRV_NAME,
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = flexcan_of_match,
+       },
        .probe = flexcan_probe,
        .remove = __devexit_p(flexcan_remove),
 };
index 92feac6..ac42f5d 100644 (file)
@@ -62,7 +62,7 @@ static enum can_state state_map[] = {
 static int mscan_set_mode(struct net_device *dev, u8 mode)
 {
        struct mscan_priv *priv = netdev_priv(dev);
-       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+       struct mscan_regs __iomem *regs = priv->reg_base;
        int ret = 0;
        int i;
        u8 canctl1;
@@ -138,7 +138,7 @@ static int mscan_set_mode(struct net_device *dev, u8 mode)
 static int mscan_start(struct net_device *dev)
 {
        struct mscan_priv *priv = netdev_priv(dev);
-       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+       struct mscan_regs __iomem *regs = priv->reg_base;
        u8 canrflg;
        int err;
 
@@ -178,7 +178,7 @@ static int mscan_restart(struct net_device *dev)
        struct mscan_priv *priv = netdev_priv(dev);
 
        if (priv->type == MSCAN_TYPE_MPC5121) {
-               struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+               struct mscan_regs __iomem *regs = priv->reg_base;
 
                priv->can.state = CAN_STATE_ERROR_ACTIVE;
                WARN(!(in_8(&regs->canmisc) & MSCAN_BOHOLD),
@@ -199,7 +199,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct can_frame *frame = (struct can_frame *)skb->data;
        struct mscan_priv *priv = netdev_priv(dev);
-       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+       struct mscan_regs __iomem *regs = priv->reg_base;
        int i, rtr, buf_id;
        u32 can_id;
 
@@ -305,7 +305,7 @@ static enum can_state check_set_state(struct net_device *dev, u8 canrflg)
 static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame)
 {
        struct mscan_priv *priv = netdev_priv(dev);
-       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+       struct mscan_regs __iomem *regs = priv->reg_base;
        u32 can_id;
        int i;
 
@@ -343,7 +343,7 @@ static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame,
                                u8 canrflg)
 {
        struct mscan_priv *priv = netdev_priv(dev);
-       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+       struct mscan_regs __iomem *regs = priv->reg_base;
        struct net_device_stats *stats = &dev->stats;
        enum can_state old_state;
 
@@ -406,7 +406,7 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
 {
        struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi);
        struct net_device *dev = napi->dev;
-       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+       struct mscan_regs __iomem *regs = priv->reg_base;
        struct net_device_stats *stats = &dev->stats;
        int npackets = 0;
        int ret = 1;
@@ -453,7 +453,7 @@ static irqreturn_t mscan_isr(int irq, void *dev_id)
 {
        struct net_device *dev = (struct net_device *)dev_id;
        struct mscan_priv *priv = netdev_priv(dev);
-       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+       struct mscan_regs __iomem *regs = priv->reg_base;
        struct net_device_stats *stats = &dev->stats;
        u8 cantier, cantflg, canrflg;
        irqreturn_t ret = IRQ_NONE;
@@ -537,7 +537,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
 static int mscan_do_set_bittiming(struct net_device *dev)
 {
        struct mscan_priv *priv = netdev_priv(dev);
-       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+       struct mscan_regs __iomem *regs = priv->reg_base;
        struct can_bittiming *bt = &priv->can.bittiming;
        u8 btr0, btr1;
 
@@ -559,7 +559,7 @@ static int mscan_open(struct net_device *dev)
 {
        int ret;
        struct mscan_priv *priv = netdev_priv(dev);
-       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+       struct mscan_regs __iomem *regs = priv->reg_base;
 
        /* common open */
        ret = open_candev(dev);
@@ -598,7 +598,7 @@ exit_napi_disable:
 static int mscan_close(struct net_device *dev)
 {
        struct mscan_priv *priv = netdev_priv(dev);
-       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+       struct mscan_regs __iomem *regs = priv->reg_base;
 
        netif_stop_queue(dev);
        napi_disable(&priv->napi);
@@ -622,7 +622,7 @@ static const struct net_device_ops mscan_netdev_ops = {
 int register_mscandev(struct net_device *dev, int mscan_clksrc)
 {
        struct mscan_priv *priv = netdev_priv(dev);
-       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+       struct mscan_regs __iomem *regs = priv->reg_base;
        u8 ctl1;
 
        ctl1 = in_8(&regs->canctl1);
@@ -659,7 +659,7 @@ int register_mscandev(struct net_device *dev, int mscan_clksrc)
 void unregister_mscandev(struct net_device *dev)
 {
        struct mscan_priv *priv = netdev_priv(dev);
-       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+       struct mscan_regs __iomem *regs = priv->reg_base;
        mscan_set_mode(dev, MSCAN_INIT_MODE);
        clrbits8(&regs->canctl1, MSCAN_CANE);
        unregister_candev(dev);
index 231385b..c7f3d4e 100644 (file)
@@ -408,7 +408,7 @@ static void plx_pci_del_card(struct pci_dev *pdev)
        struct sja1000_priv *priv;
        int i = 0;
 
-       for (i = 0; i < card->channels; i++) {
+       for (i = 0; i < PLX_PCI_MAX_CHAN; i++) {
                dev = card->net_dev[i];
                if (!dev)
                        continue;
@@ -536,7 +536,6 @@ static int __devinit plx_pci_add_card(struct pci_dev *pdev,
                        if (err) {
                                dev_err(&pdev->dev, "Registering device failed "
                                        "(err=%d)\n", err);
-                               free_sja1000dev(dev);
                                goto failure_cleanup;
                        }
 
@@ -549,6 +548,7 @@ static int __devinit plx_pci_add_card(struct pci_dev *pdev,
                        dev_err(&pdev->dev, "Channel #%d not detected\n",
                                i + 1);
                        free_sja1000dev(dev);
+                       card->net_dev[i] = NULL;
                }
        }
 
index f523f1c..4b70b7e 100644 (file)
@@ -197,7 +197,7 @@ static void slc_bump(struct slcan *sl)
        skb->ip_summed = CHECKSUM_UNNECESSARY;
        memcpy(skb_put(skb, sizeof(struct can_frame)),
               &cf, sizeof(struct can_frame));
-       netif_rx(skb);
+       netif_rx_ni(skb);
 
        sl->dev->stats.rx_packets++;
        sl->dev->stats.rx_bytes += cf.can_dlc;
index e66aceb..7cb2785 100644 (file)
@@ -261,7 +261,7 @@ static const struct net_device_ops e100_netdev_ops = {
        .ndo_start_xmit         = e100_send_packet,
        .ndo_tx_timeout         = e100_tx_timeout,
        .ndo_get_stats          = e100_get_stats,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_do_ioctl           = e100_ioctl,
        .ndo_set_mac_address    = e100_set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
index 39cf9b9..a7c5e88 100644 (file)
@@ -116,7 +116,7 @@ static const struct net_device_ops dummy_netdev_ops = {
        .ndo_init               = dummy_dev_init,
        .ndo_start_xmit         = dummy_xmit,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_set_mac_address    = dummy_set_address,
        .ndo_get_stats64        = dummy_get_stats64,
 };
similarity index 99%
rename from drivers/net/3c501.c
rename to drivers/net/ethernet/3com/3c501.c
index 5420f6d..68da81d 100644 (file)
@@ -201,7 +201,7 @@ static const struct net_device_ops el_netdev_ops = {
        .ndo_stop               = el1_close,
        .ndo_start_xmit         = el_start_xmit,
        .ndo_tx_timeout         = el_timeout,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/3c509.c
rename to drivers/net/ethernet/3com/3c509.c
index 44b28b2..92053e6 100644 (file)
@@ -545,7 +545,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_stop               = el3_close,
        .ndo_start_xmit         = el3_start_xmit,
        .ndo_get_stats          = el3_get_stats,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_tx_timeout         = el3_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/3c515.c
rename to drivers/net/ethernet/3com/3c515.c
index d2bb4b2..f67a5d3 100644 (file)
@@ -569,7 +569,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_start_xmit         = corkscrew_start_xmit,
        .ndo_tx_timeout         = corkscrew_timeout,
        .ndo_get_stats          = corkscrew_get_stats,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/pcmcia/3c574_cs.c
rename to drivers/net/ethernet/3com/3c574_cs.c
index 34c5e1c..9c01bc9 100644 (file)
@@ -255,7 +255,7 @@ static const struct net_device_ops el3_netdev_ops = {
        .ndo_tx_timeout         = el3_tx_timeout,
        .ndo_get_stats          = el3_get_stats,
        .ndo_do_ioctl           = el3_ioctl,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/pcmcia/3c589_cs.c
rename to drivers/net/ethernet/3com/3c589_cs.c
index 4a1a358..972f80e 100644 (file)
@@ -184,7 +184,7 @@ static const struct net_device_ops el3_netdev_ops = {
        .ndo_tx_timeout         = el3_tx_timeout,
        .ndo_set_config         = el3_config,
        .ndo_get_stats          = el3_get_stats,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/3c59x.c
rename to drivers/net/ethernet/3com/3c59x.c
index 8cc2256..6e1f595 100644 (file)
@@ -1055,7 +1055,7 @@ static const struct net_device_ops boomrang_netdev_ops = {
 #ifdef CONFIG_PCI
        .ndo_do_ioctl           = vortex_ioctl,
 #endif
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
@@ -1073,7 +1073,7 @@ static const struct net_device_ops vortex_netdev_ops = {
 #ifdef CONFIG_PCI
        .ndo_do_ioctl           = vortex_ioctl,
 #endif
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
diff --git a/drivers/net/ethernet/3com/Kconfig b/drivers/net/ethernet/3com/Kconfig
new file mode 100644 (file)
index 0000000..a439cbd
--- /dev/null
@@ -0,0 +1,121 @@
+#
+# 3Com Ethernet device configuration
+#
+
+config NET_VENDOR_3COM
+       bool "3Com devices"
+       default y
+       depends on ISA || EISA || MCA || PCI || PCMCIA
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about 3Com cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_3COM
+
+config EL1
+       tristate "3c501 \"EtherLink\" support"
+       depends on ISA
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.  Also, consider buying a
+         new card, since the 3c501 is slow, broken, and obsolete: you will
+         have problems.  Some people suggest to ping ("man ping") a nearby
+         machine every minute ("man cron") when using this card.
+
+         To compile this driver as a module, choose M here. The module
+         will be called 3c501.
+
+config EL3
+       tristate "3c509/3c529 (MCA)/3c579 \"EtherLink III\" support"
+       depends on (ISA || EISA || MCA)
+       ---help---
+         If you have a network (Ethernet) card belonging to the 3Com
+         EtherLinkIII series, say Y and read the Ethernet-HOWTO, available
+         from <http://www.tldp.org/docs.html#howto>.
+
+         If your card is not working you may need to use the DOS
+         setup disk to disable Plug & Play mode, and to select the default
+         media type.
+
+         To compile this driver as a module, choose M here. The module
+         will be called 3c509.
+
+config 3C515
+       tristate "3c515 ISA \"Fast EtherLink\""
+       depends on (ISA || EISA) && ISA_DMA_API
+       ---help---
+         If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet
+         network card, say Y and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called 3c515.
+
+config PCMCIA_3C574
+       tristate "3Com 3c574 PCMCIA support"
+       depends on PCMCIA
+       ---help---
+         Say Y here if you intend to attach a 3Com 3c574 or compatible PCMCIA
+         (PC-card) Fast Ethernet card to your computer.
+
+         To compile this driver as a module, choose M here: the module will be
+         called 3c574_cs.  If unsure, say N.
+
+config PCMCIA_3C589
+       tristate "3Com 3c589 PCMCIA support"
+       depends on PCMCIA
+       ---help---
+         Say Y here if you intend to attach a 3Com 3c589 or compatible PCMCIA
+         (PC-card) Ethernet card to your computer.
+
+         To compile this driver as a module, choose M here: the module will be
+         called 3c589_cs.  If unsure, say N.
+
+config VORTEX
+       tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support"
+       depends on (PCI || EISA)
+       select MII
+       ---help---
+         This option enables driver support for a large number of 10Mbps and
+         10/100Mbps EISA, PCI and PCMCIA 3Com network cards:
+
+         "Vortex"    (Fast EtherLink 3c590/3c592/3c595/3c597) EISA and PCI
+         "Boomerang" (EtherLink XL 3c900 or 3c905)            PCI
+         "Cyclone"   (3c540/3c900/3c905/3c980/3c575/3c656)    PCI and Cardbus
+         "Tornado"   (3c905)                                  PCI
+         "Hurricane" (3c555/3cSOHO)                           PCI
+
+         If you have such a card, say Y and read the Ethernet-HOWTO,
+         available from <http://www.tldp.org/docs.html#howto>. More
+         specific information is in
+         <file:Documentation/networking/vortex.txt> and in the comments at
+         the beginning of <file:drivers/net/3c59x.c>.
+
+         To compile this support as a module, choose M here.
+
+config TYPHOON
+       tristate "3cr990 series \"Typhoon\" support"
+       depends on PCI
+       select CRC32
+       ---help---
+         This option enables driver support for the 3cr990 series of cards:
+
+         3C990-TX, 3CR990-TX-95, 3CR990-TX-97, 3CR990-FX-95, 3CR990-FX-97,
+         3CR990SVR, 3CR990SVR95, 3CR990SVR97, 3CR990-FX-95 Server,
+         3CR990-FX-97 Server, 3C990B-TX-M, 3C990BSVR
+
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called typhoon.
+
+endif # NET_VENDOR_3COM
diff --git a/drivers/net/ethernet/3com/Makefile b/drivers/net/ethernet/3com/Makefile
new file mode 100644 (file)
index 0000000..1e5382a
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for the 3Com Ethernet device drivers
+#
+
+obj-$(CONFIG_EL1) += 3c501.o
+obj-$(CONFIG_EL3) += 3c509.o
+obj-$(CONFIG_3C515) += 3c515.o
+obj-$(CONFIG_PCMCIA_3C589) += 3c589_cs.o
+obj-$(CONFIG_PCMCIA_3C574) += 3c574_cs.o
+obj-$(CONFIG_VORTEX) += 3c59x.o
+obj-$(CONFIG_TYPHOON) += typhoon.o
similarity index 99%
rename from drivers/net/typhoon.c
rename to drivers/net/ethernet/3com/typhoon.c
index 1d5091a..f1dc9ac 100644 (file)
@@ -2266,7 +2266,7 @@ static const struct net_device_ops typhoon_netdev_ops = {
        .ndo_open               = typhoon_open,
        .ndo_stop               = typhoon_close,
        .ndo_start_xmit         = typhoon_start_tx,
-       .ndo_set_multicast_list = typhoon_set_rx_mode,
+       .ndo_set_rx_mode        = typhoon_set_rx_mode,
        .ndo_tx_timeout         = typhoon_tx_timeout,
        .ndo_get_stats          = typhoon_get_stats,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/3c503.c
rename to drivers/net/ethernet/8390/3c503.c
index 84e68f1..fbab136 100644 (file)
@@ -176,7 +176,7 @@ static const struct net_device_ops el2_netdev_ops = {
        .ndo_start_xmit         = eip_start_xmit,
        .ndo_tx_timeout         = eip_tx_timeout,
        .ndo_get_stats          = eip_get_stats,
-       .ndo_set_multicast_list = eip_set_multicast_list,
+       .ndo_set_rx_mode        = eip_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 97%
rename from drivers/net/8390.c
rename to drivers/net/ethernet/8390/8390.c
index 7c7518b..5db1f55 100644 (file)
@@ -61,7 +61,7 @@ const struct net_device_ops ei_netdev_ops = {
        .ndo_start_xmit         = ei_start_xmit,
        .ndo_tx_timeout         = ei_tx_timeout,
        .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 97%
rename from drivers/net/8390p.c
rename to drivers/net/ethernet/8390/8390p.c
index a2a64ea..e8fc2e8 100644 (file)
@@ -66,7 +66,7 @@ const struct net_device_ops eip_netdev_ops = {
        .ndo_start_xmit         = eip_start_xmit,
        .ndo_tx_timeout         = eip_tx_timeout,
        .ndo_get_stats          = eip_get_stats,
-       .ndo_set_multicast_list = eip_set_multicast_list,
+       .ndo_set_rx_mode        = eip_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig
new file mode 100644 (file)
index 0000000..e04ade4
--- /dev/null
@@ -0,0 +1,337 @@
+#
+# 8390 device configuration
+#
+
+config NET_VENDOR_8390
+       bool "National Semi-conductor 8390 devices"
+       default y
+       depends on NET_VENDOR_NATSEMI && (AMIGA_PCMCIA || PCI || SUPERH || \
+                  ISA || MCA || EISA || MAC || M32R || MACH_TX49XX || \
+                  MCA_LEGACY || H8300 || ARM || MIPS || ZORRO || PCMCIA || \
+                  EXPERIMENTAL)
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Western Digital cards. If you say Y, you will be
+         asked for your specific card in the following questions.
+
+if NET_VENDOR_8390
+
+config EL2
+       tristate "3c503 \"EtherLink II\" support"
+       depends on ISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called 3c503.
+
+config AC3200
+       tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)"
+       depends on PCI && (ISA || EISA) && EXPERIMENTAL
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ac3200.
+
+config PCMCIA_AXNET
+       tristate "Asix AX88190 PCMCIA support"
+       depends on PCMCIA
+       ---help---
+         Say Y here if you intend to attach an Asix AX88190-based PCMCIA
+         (PC-card) Fast Ethernet card to your computer.  These cards are
+         nearly NE2000 compatible but need a separate driver due to a few
+         misfeatures.
+
+         To compile this driver as a module, choose M here: the module will be
+         called axnet_cs.  If unsure, say N.
+
+config AX88796
+       tristate "ASIX AX88796 NE2000 clone support"
+       depends on (ARM || MIPS || SUPERH)
+       select PHYLIB
+       select MDIO_BITBANG
+       ---help---
+         AX88796 driver, using platform bus to provide
+         chip detection and resources
+
+config AX88796_93CX6
+       bool "ASIX AX88796 external 93CX6 eeprom support"
+       depends on AX88796
+       select EEPROM_93CX6
+       ---help---
+         Select this if your platform comes with an external 93CX6 eeprom.
+
+config E2100
+       tristate "Cabletron E21xx support"
+       depends on ISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called e2100.
+
+config ES3210
+       tristate "Racal-Interlan EISA ES3210 support (EXPERIMENTAL)"
+       depends on PCI && EISA && EXPERIMENTAL
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called es3210.
+
+config HPLAN_PLUS
+       tristate "HP PCLAN+ (27247B and 27252A) support"
+       depends on ISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called hp-plus.
+
+config HPLAN
+       tristate "HP PCLAN (27245 and other 27xxx series) support"
+       depends on ISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called hp.
+
+config HYDRA
+       tristate "Hydra support"
+       depends on ZORRO
+       select CRC32
+       ---help---
+         If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
+
+         To compile this driver as a module, choose M here: the module
+         will be called hydra.
+
+config ARM_ETHERH
+       tristate "I-cubed EtherH/ANT EtherM support"
+       depends on ARM && ARCH_ACORN
+       select CRC32
+       ---help---
+         If you have an Acorn system with one of these network cards, you
+         should say Y to this option if you wish to use it with Linux.
+
+config LNE390
+       tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
+       depends on PCI && EISA && EXPERIMENTAL
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called lne390.
+
+config MAC8390
+       bool "Macintosh NS 8390 based ethernet cards"
+       depends on MAC
+       select CRC32
+       ---help---
+         If you want to include a driver to support Nubus or LC-PDS
+         Ethernet cards using an NS8390 chipset or its equivalent, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+config NE2000
+       tristate "NE2000/NE1000 support"
+       depends on (ISA || (Q40 && m) || M32R || MACH_TX49XX)
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.  Many Ethernet cards
+         without a specific driver are compatible with NE2000.
+
+         If you have a PCI NE2000 card however, say N here and Y to "PCI
+         NE2000 and clone support" under "EISA, VLB, PCI and on board
+         controllers" below. If you have a NE2000 card and are running on
+         an MCA system (a bus system used on some IBM PS/2 computers and
+         laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
+         below.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ne.
+
+config NE2_MCA
+       tristate "NE/2 (ne2000 MCA version) support"
+       depends on MCA_LEGACY
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ne2.
+
+config NE2K_PCI
+       tristate "PCI NE2000 and clones support (see help)"
+       depends on PCI
+       select CRC32
+       ---help---
+         This driver is for NE2000 compatible PCI cards. It will not work
+         with ISA NE2000 cards (they have their own driver, "NE2000/NE1000
+         support" below). If you have a PCI NE2000 network (Ethernet) card,
+         say Y and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         This driver also works for the following NE2000 clone cards:
+         RealTek RTL-8029  Winbond 89C940  Compex RL2000  KTI ET32P2
+         NetVin NV5000SC   Via 86C926      SureCom NE34   Winbond
+         Holtek HT80232    Holtek HT80229
+
+         To compile this driver as a module, choose M here. The module
+         will be called ne2k-pci.
+
+config APNE
+       tristate "PCMCIA NE2000 support"
+       depends on AMIGA_PCMCIA
+       select CRC32
+       ---help---
+         If you have a PCMCIA NE2000 compatible adapter, say Y.  Otherwise,
+         say N.
+
+         To compile this driver as a module, choose M here: the module
+         will be called apne.
+
+config NE3210
+       tristate "Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)"
+       depends on PCI && EISA && EXPERIMENTAL
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.  Note that this driver
+         will NOT WORK for NE3200 cards as they are completely different.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ne3210.
+
+config PCMCIA_PCNET
+       tristate "NE2000 compatible PCMCIA support"
+       depends on PCMCIA
+       select CRC32
+       ---help---
+         Say Y here if you intend to attach an NE2000 compatible PCMCIA
+         (PC-card) Ethernet or Fast Ethernet card to your computer.
+
+         To compile this driver as a module, choose M here: the module will be
+         called pcnet_cs.  If unsure, say N.
+
+config NE_H8300
+       tristate "NE2000 compatible support for H8/300"
+       depends on H8300
+       ---help---
+         Say Y here if you want to use the NE2000 compatible
+         controller on the Renesas H8/300 processor.
+
+config STNIC
+       tristate "National DP83902AV  support"
+       depends on SUPERH
+       select CRC32
+       ---help---
+         Support for cards based on the National Semiconductor DP83902AV
+         ST-NIC Serial Network Interface Controller for Twisted Pair.  This
+         is a 10Mbit/sec Ethernet controller.  Product overview and specs at
+         <http://www.national.com/pf/DP/DP83902A.html>.
+
+         If unsure, say N.
+
+config ULTRAMCA
+       tristate "SMC Ultra MCA support"
+       depends on MCA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type and are running
+         an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
+         available from <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called smc-mca.
+
+config ULTRA
+       tristate "SMC Ultra support"
+       depends on ISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Important: There have been many reports that, with some motherboards
+         mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible,
+         such as some BusLogic models) causes corruption problems with many
+         operating systems. The Linux smc-ultra driver has a work-around for
+         this but keep it in mind if you have such a SCSI card and have
+         problems.
+
+         To compile this driver as a module, choose M here. The module
+         will be called smc-ultra.
+
+config ULTRA32
+       tristate "SMC Ultra32 EISA support"
+       depends on EISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called smc-ultra32.
+
+config WD80x3
+       tristate "WD80*3 support"
+       depends on ISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called wd.
+
+config ZORRO8390
+       tristate "Zorro NS8390-based Ethernet support"
+       depends on ZORRO
+       select CRC32
+       ---help---
+         This driver is for Zorro Ethernet cards using an NS8390-compatible
+         chipset, like the Village Tronic Ariadne II and the Individual
+         Computers X-Surf Ethernet cards. If you have such a card, say Y.
+         Otherwise, say N.
+
+         To compile this driver as a module, choose M here: the module
+         will be called zorro8390.
+
+endif # NET_VENDOR_8390
diff --git a/drivers/net/ethernet/8390/Makefile b/drivers/net/ethernet/8390/Makefile
new file mode 100644 (file)
index 0000000..3337d7f
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# Makefile for the 8390 network device drivers.
+#
+
+obj-$(CONFIG_MAC8390) += mac8390.o
+obj-$(CONFIG_AC3200) += ac3200.o 8390.o
+obj-$(CONFIG_APNE) += apne.o 8390.o
+obj-$(CONFIG_ARM_ETHERH) += etherh.o
+obj-$(CONFIG_AX88796) += ax88796.o
+obj-$(CONFIG_E2100) += e2100.o 8390.o
+obj-$(CONFIG_EL2) += 3c503.o 8390p.o
+obj-$(CONFIG_ES3210) += es3210.o 8390.o
+obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390p.o
+obj-$(CONFIG_HPLAN) += hp.o 8390p.o
+obj-$(CONFIG_HYDRA) += hydra.o 8390.o
+obj-$(CONFIG_LNE390) += lne390.o 8390.o
+obj-$(CONFIG_NE2000) += ne.o 8390p.o
+obj-$(CONFIG_NE2_MCA) += ne2.o 8390p.o
+obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
+obj-$(CONFIG_NE3210) += ne3210.o 8390.o
+obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
+obj-$(CONFIG_PCMCIA_AXNET) += axnet_cs.o 8390.o
+obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o 8390.o
+obj-$(CONFIG_STNIC) += stnic.o 8390.o
+obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
+obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
+obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
+obj-$(CONFIG_WD80x3) += wd.o 8390.o
+obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
similarity index 99%
rename from drivers/net/ac3200.c
rename to drivers/net/ethernet/8390/ac3200.c
index f07b2e9..5337dd0 100644 (file)
@@ -151,7 +151,7 @@ static const struct net_device_ops ac_netdev_ops = {
        .ndo_start_xmit         = ei_start_xmit,
        .ndo_tx_timeout         = ei_tx_timeout,
        .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/ax88796.c
rename to drivers/net/ethernet/8390/ax88796.c
index e7cb8c8..e9f8432 100644 (file)
@@ -543,7 +543,7 @@ static const struct net_device_ops ax_netdev_ops = {
        .ndo_start_xmit         = ax_ei_start_xmit,
        .ndo_tx_timeout         = ax_ei_tx_timeout,
        .ndo_get_stats          = ax_ei_get_stats,
-       .ndo_set_multicast_list = ax_ei_set_multicast_list,
+       .ndo_set_rx_mode        = ax_ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/pcmcia/axnet_cs.c
rename to drivers/net/ethernet/8390/axnet_cs.c
index 9953db7..bba51cd 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/etherdevice.h>
 #include <linux/crc32.h>
 #include <linux/mii.h>
-#include "../8390.h"
+#include "8390.h"
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
@@ -134,7 +134,7 @@ static const struct net_device_ops axnet_netdev_ops = {
        .ndo_start_xmit         = axnet_start_xmit,
        .ndo_tx_timeout         = axnet_tx_timeout,
        .ndo_get_stats          = get_stats,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/e2100.c
rename to drivers/net/ethernet/8390/e2100.c
index d50a999..d16dc53 100644 (file)
@@ -168,7 +168,7 @@ static const struct net_device_ops e21_netdev_ops = {
        .ndo_start_xmit         = ei_start_xmit,
        .ndo_tx_timeout         = ei_tx_timeout,
        .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/arm/etherh.c
rename to drivers/net/ethernet/8390/etherh.c
index 03e217a..48c4948 100644 (file)
@@ -65,7 +65,7 @@
 static char version[] __initdata =
        "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n";
 
-#include "../lib8390.c"
+#include "lib8390.c"
 
 static unsigned int net_debug = NET_DEBUG;
 
@@ -644,7 +644,7 @@ static const struct net_device_ops etherh_netdev_ops = {
        .ndo_start_xmit         = __ei_start_xmit,
        .ndo_tx_timeout         = __ei_tx_timeout,
        .ndo_get_stats          = __ei_get_stats,
-       .ndo_set_multicast_list = __ei_set_multicast_list,
+       .ndo_set_rx_mode        = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/hp-plus.c
rename to drivers/net/ethernet/8390/hp-plus.c
index 2991736..eeac843 100644 (file)
@@ -165,7 +165,7 @@ static const struct net_device_ops hpp_netdev_ops = {
        .ndo_start_xmit         = eip_start_xmit,
        .ndo_tx_timeout         = eip_tx_timeout,
        .ndo_get_stats          = eip_get_stats,
-       .ndo_set_multicast_list = eip_set_multicast_list,
+       .ndo_set_rx_mode        = eip_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/hydra.c
rename to drivers/net/ethernet/8390/hydra.c
index 1cd481c..3dac937 100644 (file)
@@ -101,7 +101,7 @@ static const struct net_device_ops hydra_netdev_ops = {
        .ndo_start_xmit         = __ei_start_xmit,
        .ndo_tx_timeout         = __ei_tx_timeout,
        .ndo_get_stats          = __ei_get_stats,
-       .ndo_set_multicast_list = __ei_set_multicast_list,
+       .ndo_set_rx_mode        = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/mac8390.c
rename to drivers/net/ethernet/8390/mac8390.c
index f84f5e6..af5d982 100644 (file)
@@ -494,7 +494,7 @@ static const struct net_device_ops mac8390_netdev_ops = {
        .ndo_start_xmit         = __ei_start_xmit,
        .ndo_tx_timeout         = __ei_tx_timeout,
        .ndo_get_stats          = __ei_get_stats,
-       .ndo_set_multicast_list = __ei_set_multicast_list,
+       .ndo_set_rx_mode        = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/ne-h8300.c
rename to drivers/net/ethernet/8390/ne-h8300.c
index 7298a34..cd36a6a 100644 (file)
@@ -200,7 +200,7 @@ static const struct net_device_ops ne_netdev_ops = {
        .ndo_start_xmit         = __ei_start_xmit,
        .ndo_tx_timeout         = __ei_tx_timeout,
        .ndo_get_stats          = __ei_get_stats,
-       .ndo_set_multicast_list = __ei_set_multicast_list,
+       .ndo_set_rx_mode        = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/ne2k-pci.c
rename to drivers/net/ethernet/8390/ne2k-pci.c
index 3c333cb..3992342 100644 (file)
@@ -207,7 +207,7 @@ static const struct net_device_ops ne2k_netdev_ops = {
        .ndo_start_xmit         = ei_start_xmit,
        .ndo_tx_timeout         = ei_tx_timeout,
        .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/pcmcia/pcnet_cs.c
rename to drivers/net/ethernet/8390/pcnet_cs.c
index b4fd7c3..053b255 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/log2.h>
 #include <linux/etherdevice.h>
 #include <linux/mii.h>
-#include "../8390.h"
+#include "8390.h"
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
@@ -227,7 +227,7 @@ static const struct net_device_ops pcnet_netdev_ops = {
        .ndo_start_xmit         = ei_start_xmit,
        .ndo_get_stats          = ei_get_stats,
        .ndo_do_ioctl           = ei_ioctl,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_tx_timeout         = ei_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/smc-mca.c
rename to drivers/net/ethernet/8390/smc-mca.c
index 34934fb..77efec4 100644 (file)
@@ -191,7 +191,7 @@ static const struct net_device_ops ultramca_netdev_ops = {
        .ndo_start_xmit         = ei_start_xmit,
        .ndo_tx_timeout         = ei_tx_timeout,
        .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/smc-ultra.c
rename to drivers/net/ethernet/8390/smc-ultra.c
index ba44ede..1cc306a 100644 (file)
@@ -192,7 +192,7 @@ static const struct net_device_ops ultra_netdev_ops = {
        .ndo_start_xmit         = ei_start_xmit,
        .ndo_tx_timeout         = ei_tx_timeout,
        .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/smc-ultra32.c
rename to drivers/net/ethernet/8390/smc-ultra32.c
index e459c3b..bb87053 100644 (file)
@@ -160,7 +160,7 @@ static const struct net_device_ops ultra32_netdev_ops = {
        .ndo_start_xmit         = ei_start_xmit,
        .ndo_tx_timeout         = ei_tx_timeout,
        .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/wd.c
rename to drivers/net/ethernet/8390/wd.c
index 8831a33..c175fad 100644 (file)
@@ -153,7 +153,7 @@ static const struct net_device_ops wd_netdev_ops = {
        .ndo_start_xmit         = ei_start_xmit,
        .ndo_tx_timeout         = ei_tx_timeout,
        .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/zorro8390.c
rename to drivers/net/ethernet/8390/zorro8390.c
index 15e7751..3aa9fe9 100644 (file)
@@ -278,7 +278,7 @@ static const struct net_device_ops zorro8390_netdev_ops = {
        .ndo_start_xmit         = __ei_start_xmit,
        .ndo_tx_timeout         = __ei_tx_timeout,
        .ndo_get_stats          = __ei_get_stats,
-       .ndo_set_multicast_list = __ei_set_multicast_list,
+       .ndo_set_rx_mode        = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
new file mode 100644 (file)
index 0000000..1f64747
--- /dev/null
@@ -0,0 +1,173 @@
+#
+# Ethernet LAN device configuration
+#
+
+menuconfig ETHERNET
+       bool "Ethernet driver support"
+       depends on NET
+       default y
+       ---help---
+         This section contains all the Ethernet device drivers.
+
+if ETHERNET
+
+config MDIO
+       tristate
+
+config SUNGEM_PHY
+       tristate
+
+source "drivers/net/ethernet/3com/Kconfig"
+source "drivers/net/ethernet/adaptec/Kconfig"
+source "drivers/net/ethernet/aeroflex/Kconfig"
+source "drivers/net/ethernet/alteon/Kconfig"
+source "drivers/net/ethernet/amd/Kconfig"
+source "drivers/net/ethernet/apple/Kconfig"
+source "drivers/net/ethernet/atheros/Kconfig"
+source "drivers/net/ethernet/cadence/Kconfig"
+source "drivers/net/ethernet/adi/Kconfig"
+source "drivers/net/ethernet/broadcom/Kconfig"
+source "drivers/net/ethernet/brocade/Kconfig"
+source "drivers/net/ethernet/chelsio/Kconfig"
+source "drivers/net/ethernet/cirrus/Kconfig"
+source "drivers/net/ethernet/cisco/Kconfig"
+source "drivers/net/ethernet/davicom/Kconfig"
+
+config DNET
+       tristate "Dave ethernet support (DNET)"
+       depends on HAS_IOMEM
+       select PHYLIB
+       ---help---
+         The Dave ethernet interface (DNET) is found on Qong Board FPGA.
+         Say Y to include support for the DNET chip.
+
+         To compile this driver as a module, choose M here: the module
+         will be called dnet.
+
+source "drivers/net/ethernet/dec/Kconfig"
+source "drivers/net/ethernet/dlink/Kconfig"
+source "drivers/net/ethernet/emulex/Kconfig"
+source "drivers/net/ethernet/neterion/Kconfig"
+source "drivers/net/ethernet/faraday/Kconfig"
+source "drivers/net/ethernet/freescale/Kconfig"
+source "drivers/net/ethernet/fujitsu/Kconfig"
+source "drivers/net/ethernet/hp/Kconfig"
+source "drivers/net/ethernet/ibm/Kconfig"
+source "drivers/net/ethernet/intel/Kconfig"
+source "drivers/net/ethernet/i825xx/Kconfig"
+source "drivers/net/ethernet/xscale/Kconfig"
+source "drivers/net/ethernet/icplus/Kconfig"
+
+config JME
+       tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         This driver supports the PCI-Express gigabit ethernet adapters
+         based on JMicron JMC250 chipset.
+
+         To compile this driver as a module, choose M here. The module
+         will be called jme.
+
+config KORINA
+       tristate "Korina (IDT RC32434) Ethernet support"
+       depends on MIKROTIK_RB532
+       ---help---
+         If you have a Mikrotik RouterBoard 500 or IDT RC32434
+         based system say Y. Otherwise say N.
+
+config LANTIQ_ETOP
+       tristate "Lantiq SoC ETOP driver"
+       depends on SOC_TYPE_XWAY
+       ---help---
+         Support for the MII0 inside the Lantiq SoC
+
+source "drivers/net/ethernet/marvell/Kconfig"
+source "drivers/net/ethernet/mellanox/Kconfig"
+source "drivers/net/ethernet/micrel/Kconfig"
+source "drivers/net/ethernet/microchip/Kconfig"
+
+config MIPS_SIM_NET
+       tristate "MIPS simulator Network device"
+       depends on MIPS_SIM
+       ---help---
+         The MIPSNET device is a simple Ethernet network device which is
+         emulated by the MIPS Simulator.
+         If you are not using a MIPSsim or are unsure, say N.
+
+source "drivers/net/ethernet/myricom/Kconfig"
+
+config FEALNX
+       tristate "Myson MTD-8xx PCI Ethernet support"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         Say Y here to support the Myson MTD-800 family of PCI-based Ethernet
+         cards. <http://www.myson.com.tw/>
+
+source "drivers/net/ethernet/natsemi/Kconfig"
+source "drivers/net/ethernet/8390/Kconfig"
+
+config NET_NETX
+       tristate "NetX Ethernet support"
+       select MII
+       depends on ARCH_NETX
+       ---help---
+         This is support for the Hilscher netX builtin Ethernet ports
+
+         To compile this driver as a module, choose M here. The module
+         will be called netx-eth.
+
+source "drivers/net/ethernet/nuvoton/Kconfig"
+source "drivers/net/ethernet/nvidia/Kconfig"
+source "drivers/net/ethernet/octeon/Kconfig"
+source "drivers/net/ethernet/oki-semi/Kconfig"
+
+config ETHOC
+       tristate "OpenCores 10/100 Mbps Ethernet MAC support"
+       depends on HAS_IOMEM && HAS_DMA
+       select MII
+       select PHYLIB
+       select CRC32
+       select BITREVERSE
+       ---help---
+         Say Y here if you want to use the OpenCores 10/100 Mbps Ethernet MAC.
+
+source "drivers/net/ethernet/packetengines/Kconfig"
+source "drivers/net/ethernet/pasemi/Kconfig"
+source "drivers/net/ethernet/qlogic/Kconfig"
+source "drivers/net/ethernet/racal/Kconfig"
+source "drivers/net/ethernet/realtek/Kconfig"
+source "drivers/net/ethernet/renesas/Kconfig"
+source "drivers/net/ethernet/rdc/Kconfig"
+
+config S6GMAC
+       tristate "S6105 GMAC ethernet support"
+       depends on XTENSA_VARIANT_S6000
+       select PHYLIB
+       ---help---
+         This driver supports the on chip ethernet device on the
+         S6105 xtensa processor.
+
+         To compile this driver as a module, choose M here. The module
+         will be called s6gmac.
+
+source "drivers/net/ethernet/seeq/Kconfig"
+source "drivers/net/ethernet/sis/Kconfig"
+source "drivers/net/ethernet/sfc/Kconfig"
+source "drivers/net/ethernet/sgi/Kconfig"
+source "drivers/net/ethernet/smsc/Kconfig"
+source "drivers/net/ethernet/stmicro/Kconfig"
+source "drivers/net/ethernet/sun/Kconfig"
+source "drivers/net/ethernet/tehuti/Kconfig"
+source "drivers/net/ethernet/ti/Kconfig"
+source "drivers/net/ethernet/tile/Kconfig"
+source "drivers/net/ethernet/toshiba/Kconfig"
+source "drivers/net/ethernet/tundra/Kconfig"
+source "drivers/net/ethernet/via/Kconfig"
+source "drivers/net/ethernet/xilinx/Kconfig"
+source "drivers/net/ethernet/xircom/Kconfig"
+
+endif # ETHERNET
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
new file mode 100644 (file)
index 0000000..c53ad3a
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# Makefile for the Linux network Ethernet device drivers.
+#
+
+obj-$(CONFIG_NET_VENDOR_3COM) += 3com/
+obj-$(CONFIG_NET_VENDOR_8390) += 8390/
+obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adaptec/
+obj-$(CONFIG_GRETH) += aeroflex/
+obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
+obj-$(CONFIG_NET_VENDOR_AMD) += amd/
+obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
+obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/
+obj-$(CONFIG_NET_ATMEL) += cadence/
+obj-$(CONFIG_NET_BFIN) += adi/
+obj-$(CONFIG_NET_VENDOR_BROADCOM) += broadcom/
+obj-$(CONFIG_NET_VENDOR_BROCADE) += brocade/
+obj-$(CONFIG_NET_VENDOR_CHELSIO) += chelsio/
+obj-$(CONFIG_NET_VENDOR_CIRRUS) += cirrus/
+obj-$(CONFIG_NET_VENDOR_CISCO) += cisco/
+obj-$(CONFIG_DM9000) += davicom/
+obj-$(CONFIG_DNET) += dnet.o
+obj-$(CONFIG_NET_VENDOR_DEC) += dec/
+obj-$(CONFIG_NET_VENDOR_DLINK) += dlink/
+obj-$(CONFIG_NET_VENDOR_EMULEX) += emulex/
+obj-$(CONFIG_NET_VENDOR_EXAR) += neterion/
+obj-$(CONFIG_NET_VENDOR_FARADAY) += faraday/
+obj-$(CONFIG_NET_VENDOR_FREESCALE) += freescale/
+obj-$(CONFIG_NET_VENDOR_FUJITSU) += fujitsu/
+obj-$(CONFIG_NET_VENDOR_HP) += hp/
+obj-$(CONFIG_NET_VENDOR_IBM) += ibm/
+obj-$(CONFIG_NET_VENDOR_INTEL) += intel/
+obj-$(CONFIG_NET_VENDOR_I825XX) += i825xx/
+obj-$(CONFIG_NET_VENDOR_XSCALE) += xscale/
+obj-$(CONFIG_IP1000) += icplus/
+obj-$(CONFIG_JME) += jme.o
+obj-$(CONFIG_KORINA) += korina.o
+obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
+obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/
+obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/
+obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/
+obj-$(CONFIG_NET_VENDOR_MICROCHIP) += microchip/
+obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
+obj-$(CONFIG_NET_VENDOR_MYRI) += myricom/
+obj-$(CONFIG_FEALNX) += fealnx.o
+obj-$(CONFIG_NET_VENDOR_NATSEMI) += natsemi/
+obj-$(CONFIG_NET_NETX) += netx-eth.o
+obj-$(CONFIG_NET_VENDOR_NUVOTON) += nuvoton/
+obj-$(CONFIG_NET_VENDOR_NVIDIA) += nvidia/
+obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
+obj-$(CONFIG_NET_VENDOR_OKI) += oki-semi/
+obj-$(CONFIG_ETHOC) += ethoc.o
+obj-$(CONFIG_NET_PACKET_ENGINE) += packetengines/
+obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/
+obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/
+obj-$(CONFIG_NET_VENDOR_RACAL) += racal/
+obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
+obj-$(CONFIG_SH_ETH) += renesas/
+obj-$(CONFIG_NET_VENDOR_RDC) += rdc/
+obj-$(CONFIG_S6GMAC) += s6gmac.o
+obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/
+obj-$(CONFIG_NET_VENDOR_SIS) += sis/
+obj-$(CONFIG_SFC) += sfc/
+obj-$(CONFIG_NET_VENDOR_SGI) += sgi/
+obj-$(CONFIG_NET_VENDOR_SMSC) += smsc/
+obj-$(CONFIG_NET_VENDOR_STMICRO) += stmicro/
+obj-$(CONFIG_NET_VENDOR_SUN) += sun/
+obj-$(CONFIG_NET_VENDOR_TEHUTI) += tehuti/
+obj-$(CONFIG_NET_VENDOR_TI) += ti/
+obj-$(CONFIG_TILE_NET) += tile/
+obj-$(CONFIG_NET_VENDOR_TOSHIBA) += toshiba/
+obj-$(CONFIG_NET_VENDOR_TUNDRA) += tundra/
+obj-$(CONFIG_NET_VENDOR_VIA) += via/
+obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
+obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
diff --git a/drivers/net/ethernet/adaptec/Kconfig b/drivers/net/ethernet/adaptec/Kconfig
new file mode 100644 (file)
index 0000000..5c804bb
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# Adaptec network device configuration
+#
+
+config NET_VENDOR_ADAPTEC
+       bool "Adaptec devices"
+       default y
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Adaptec cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_ADAPTEC
+
+config ADAPTEC_STARFIRE
+       tristate "Adaptec Starfire/DuraLAN support"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network
+         adapter. The DuraLAN chip is used on the 64 bit PCI boards from
+         Adaptec e.g. the ANA-6922A. The older 32 bit boards use the tulip
+         driver.
+
+         To compile this driver as a module, choose M here: the module
+         will be called starfire.  This is recommended.
+
+endif # NET_VENDOR_ADAPTEC
diff --git a/drivers/net/ethernet/adaptec/Makefile b/drivers/net/ethernet/adaptec/Makefile
new file mode 100644 (file)
index 0000000..6c07b75
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Adaptec network device drivers.
+#
+
+obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
similarity index 99%
rename from drivers/net/starfire.c
rename to drivers/net/ethernet/adaptec/starfire.c
index 7ae1f99..df51fdd 100644 (file)
@@ -639,7 +639,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_start_xmit         = start_tx,
        .ndo_tx_timeout         = tx_timeout,
        .ndo_get_stats          = get_stats,
-       .ndo_set_multicast_list = &set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_do_ioctl           = netdev_ioctl,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig
new file mode 100644 (file)
index 0000000..6de9851
--- /dev/null
@@ -0,0 +1,68 @@
+#
+# Blackfin device configuration
+#
+
+config NET_BFIN
+       bool "Blackfin devices"
+       depends on BF516 || BF518 || BF526 || BF527 || BF536 || BF537
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y.
+         Make sure you know the name of your card. Read the Ethernet-HOWTO,
+         available from <http://www.tldp.org/docs.html#howto>.
+
+         If unsure, say Y.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the remaining Blackfin card questions. If you say Y, you will be
+         asked for your specific card in the following questions.
+
+if NET_BFIN
+
+config BFIN_MAC
+       tristate "Blackfin on-chip MAC support"
+       depends on (BF516 || BF518 || BF526 || BF527 || BF536 || BF537)
+       select CRC32
+       select MII
+       select PHYLIB
+       select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE
+       ---help---
+         This is the driver for Blackfin on-chip mac device. Say Y if you want
+         it compiled into the kernel. This driver is also available as a
+         module ( = code which can be inserted in and removed from the running
+         kernel whenever you want). The module will be called bfin_mac.
+
+config BFIN_MAC_USE_L1
+       bool "Use L1 memory for rx/tx packets"
+       depends on BFIN_MAC && (BF527 || BF537)
+       default y
+       ---help---
+         To get maximum network performance, you should use L1 memory as rx/tx
+         buffers. Say N here if you want to reserve L1 memory for other uses.
+
+config BFIN_TX_DESC_NUM
+       int "Number of transmit buffer packets"
+       depends on BFIN_MAC
+       range 6 10 if BFIN_MAC_USE_L1
+       range 10 100
+       default "10"
+       ---help---
+         Set the number of buffer packets used in driver.
+
+config BFIN_RX_DESC_NUM
+       int "Number of receive buffer packets"
+       depends on BFIN_MAC
+       range 20 100 if BFIN_MAC_USE_L1
+       range 20 800
+       default "20"
+       ---help---
+         Set the number of buffer packets used in driver.
+
+config BFIN_MAC_USE_HWSTAMP
+       bool "Use IEEE 1588 hwstamp"
+       depends on BFIN_MAC && BF518
+       default y
+       ---help---
+         To support the IEEE 1588 Precision Time Protocol (PTP), select y here
+
+endif # NET_BFIN
diff --git a/drivers/net/ethernet/adi/Makefile b/drivers/net/ethernet/adi/Makefile
new file mode 100644 (file)
index 0000000..b1fbe19
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Blackfin device drivers.
+#
+
+obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
similarity index 99%
rename from drivers/net/bfin_mac.c
rename to drivers/net/ethernet/adi/bfin_mac.c
index 6c019e1..b6d69c9 100644 (file)
@@ -1449,7 +1449,7 @@ static const struct net_device_ops bfin_mac_netdev_ops = {
        .ndo_start_xmit         = bfin_mac_hard_start_xmit,
        .ndo_set_mac_address    = bfin_mac_set_mac_address,
        .ndo_tx_timeout         = bfin_mac_timeout,
-       .ndo_set_multicast_list = bfin_mac_set_multicast_list,
+       .ndo_set_rx_mode        = bfin_mac_set_multicast_list,
        .ndo_do_ioctl           = bfin_mac_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
diff --git a/drivers/net/ethernet/aeroflex/Kconfig b/drivers/net/ethernet/aeroflex/Kconfig
new file mode 100644 (file)
index 0000000..4f4a8d7
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Aeroflex Gaisler network device configuration
+#
+
+config GRETH
+       tristate "Aeroflex Gaisler GRETH Ethernet MAC support"
+       depends on SPARC
+       select PHYLIB
+       select CRC32
+       ---help---
+         Say Y here if you want to use the Aeroflex Gaisler GRETH Ethernet MAC.
diff --git a/drivers/net/ethernet/aeroflex/Makefile b/drivers/net/ethernet/aeroflex/Makefile
new file mode 100644 (file)
index 0000000..6e62a67
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Aeroflex Gaisler network device drivers.
+#
+
+obj-$(CONFIG_GRETH) += greth.o
similarity index 99%
rename from drivers/net/greth.c
rename to drivers/net/ethernet/aeroflex/greth.c
index 16ce45c..a5f6b07 100644 (file)
@@ -1539,7 +1539,7 @@ static int __devinit greth_of_probe(struct platform_device *ofdev)
        }
 
        if (greth->multicast) {
-               greth_netdev_ops.ndo_set_multicast_list = greth_set_multicast_list;
+               greth_netdev_ops.ndo_set_rx_mode = greth_set_multicast_list;
                dev->flags |= IFF_MULTICAST;
        } else {
                dev->flags &= ~IFF_MULTICAST;
diff --git a/drivers/net/ethernet/alteon/Kconfig b/drivers/net/ethernet/alteon/Kconfig
new file mode 100644 (file)
index 0000000..799a852
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Alteon network device configuration
+#
+
+config NET_VENDOR_ALTEON
+       bool "Alteon devices"
+       default y
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Alteon cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_ALTEON
+
+config ACENIC
+       tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
+       depends on PCI
+       ---help---
+         Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear
+         GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit Ethernet
+         adapter. The driver allows for using the Jumbo Frame option (9000
+         bytes/frame) however it requires that your switches can handle this
+         as well. To enable Jumbo Frames, add `mtu 9000' to your ifconfig
+         line.
+
+         To compile this driver as a module, choose M here: the
+         module will be called acenic.
+
+config ACENIC_OMIT_TIGON_I
+       bool "Omit support for old Tigon I based AceNICs"
+       depends on ACENIC
+       ---help---
+         Say Y here if you only have Tigon II based AceNICs and want to leave
+         out support for the older Tigon I based cards which are no longer
+         being sold (ie. the original Alteon AceNIC and 3Com 3C985 (non B
+         version)).  This will reduce the size of the driver object by
+         app. 100KB.  If you are not sure whether your card is a Tigon I or a
+         Tigon II, say N here.
+
+         The safe and default value for this is N.
+
+endif # NET_VENDOR_ALTEON
diff --git a/drivers/net/ethernet/alteon/Makefile b/drivers/net/ethernet/alteon/Makefile
new file mode 100644 (file)
index 0000000..a2ca173
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Alteon network device drivers.
+#
+
+obj-$(CONFIG_ACENIC) += acenic.o
similarity index 99%
rename from drivers/net/acenic.c
rename to drivers/net/ethernet/alteon/acenic.c
index 31798f5..1d6f2db 100644 (file)
@@ -449,7 +449,7 @@ static const struct net_device_ops ace_netdev_ops = {
        .ndo_tx_timeout         = ace_watchdog,
        .ndo_get_stats          = ace_get_stats,
        .ndo_start_xmit         = ace_start_xmit,
-       .ndo_set_multicast_list = ace_set_multicast_list,
+       .ndo_set_rx_mode        = ace_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ace_set_mac_addr,
        .ndo_change_mtu         = ace_change_mtu,
diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig
new file mode 100644 (file)
index 0000000..8af1c93
--- /dev/null
@@ -0,0 +1,193 @@
+#
+# AMD network device configuration
+#
+
+config NET_VENDOR_AMD
+       bool "AMD devices"
+       default y
+       depends on DIO || MACH_DECSTATION || MVME147 || ATARI || SUN3 || \
+                  SUN3X || SBUS || PCI || ZORRO || (ISA && ISA_DMA_API) || \
+                  (ARM && ARCH_EBSA110) || ISA || EISA || MCA || PCMCIA
+       ---help---
+         If you have a network (Ethernet) chipset belonging to this class,
+         say Y.
+
+         Note that the answer to this question does not directly affect
+         the kernel: saying N will just case the configurator to skip all
+         the questions regarding AMD chipsets. If you say Y, you will be asked
+         for your specific chipset/driver in the following questions.
+
+if NET_VENDOR_AMD
+
+config A2065
+       tristate "A2065 support"
+       depends on ZORRO
+       select CRC32
+       ---help---
+         If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
+         say N.
+
+         To compile this driver as a module, choose M here: the module
+         will be called a2065.
+
+config AMD8111_ETH
+       tristate "AMD 8111 (new PCI LANCE) support"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         If you have an AMD 8111-based PCI LANCE ethernet card,
+         answer Y here and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called amd8111e.
+
+config LANCE
+       tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
+       depends on ISA && ISA_DMA_API
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>. Some LinkSys cards are
+         of this type.
+
+         To compile this driver as a module, choose M here: the module
+         will be called lance.  This is recommended.
+
+config PCNET32
+       tristate "AMD PCnet32 PCI support"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         If you have a PCnet32 or PCnetPCI based network (Ethernet) card,
+         answer Y here and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called pcnet32.
+
+config ARIADNE
+       tristate "Ariadne support"
+       depends on ZORRO
+       ---help---
+         If you have a Village Tronic Ariadne Ethernet adapter, say Y.
+         Otherwise, say N.
+
+         To compile this driver as a module, choose M here: the module
+         will be called ariadne.
+
+config ARM_AM79C961A
+       bool "ARM EBSA110 AM79C961A support"
+       depends on ARM && ARCH_EBSA110
+       select CRC32
+       ---help---
+         If you wish to compile a kernel for the EBSA-110, then you should
+         always answer Y to this.
+
+config ATARILANCE
+       tristate "Atari LANCE support"
+       depends on ATARI
+       ---help---
+         Say Y to include support for several Atari Ethernet adapters based
+         on the AMD LANCE chipset: RieblCard (with or without battery), or
+         PAMCard VME (also the version by Rhotron, with different addresses).
+
+config DECLANCE
+       tristate "DEC LANCE ethernet controller support"
+       depends on MACH_DECSTATION
+       select CRC32
+       ---help---
+         This driver is for the series of Ethernet controllers produced by
+         DEC (now Compaq) based on the AMD LANCE chipset, including the
+         DEPCA series.  (This chipset is better known via the NE2100 cards.)
+
+config DEPCA
+       tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support"
+       depends on (ISA || EISA || MCA)
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto> as well as
+         <file:drivers/net/depca.c>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called depca.
+
+config HPLANCE
+       bool "HP on-board LANCE support"
+       depends on DIO
+       select CRC32
+       ---help---
+         If you want to use the builtin "LANCE" Ethernet controller on an
+         HP300 machine, say Y here.
+
+config MIPS_AU1X00_ENET
+       tristate "MIPS AU1000 Ethernet support"
+       depends on MIPS_ALCHEMY
+       select PHYLIB
+       select CRC32
+       ---help---
+         If you have an Alchemy Semi AU1X00 based system
+         say Y.  Otherwise, say N.
+
+config MVME147_NET
+       tristate "MVME147 (LANCE) Ethernet support"
+       depends on MVME147
+       select CRC32
+       ---help---
+         Support for the on-board Ethernet interface on the Motorola MVME147
+         single-board computer.  Say Y here to include the
+         driver for this chip in your kernel.
+         To compile this driver as a module, choose M here.
+
+config PCMCIA_NMCLAN
+       tristate "New Media PCMCIA support"
+       depends on PCMCIA
+       help
+         Say Y here if you intend to attach a New Media Ethernet or LiveWire
+         PCMCIA (PC-card) Ethernet card to your computer.
+
+         To compile this driver as a module, choose M here: the module will be
+         called nmclan_cs.  If unsure, say N.
+
+config NI65
+       tristate "NI6510 support"
+       depends on ISA && ISA_DMA_API
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ni65.
+
+config SUN3LANCE
+       tristate "Sun3/Sun3x on-board LANCE support"
+       depends on (SUN3 || SUN3X)
+       ---help---
+         Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
+         featured an AMD LANCE 10Mbit Ethernet controller on board; say Y
+         here to compile in the Linux driver for this and enable Ethernet.
+         General Linux information on the Sun 3 and 3x series (now
+         discontinued) is at
+         <http://www.angelfire.com/ca2/tech68k/sun3.html>.
+
+         If you're not building a kernel for a Sun 3, say N.
+
+config SUNLANCE
+       tristate "Sun LANCE support"
+       depends on SBUS
+       select CRC32
+       ---help---
+         This driver supports the "le" interface present on all 32-bit Sparc
+         systems, on some older Ultra systems and as an Sbus option.  These
+         cards are based on the AMD LANCE chipset, which is better known
+         via the NE2100 cards.
+
+         To compile this driver as a module, choose M here: the module
+         will be called sunlance.
+
+endif # NET_VENDOR_AMD
diff --git a/drivers/net/ethernet/amd/Makefile b/drivers/net/ethernet/amd/Makefile
new file mode 100644 (file)
index 0000000..175caa5
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Makefile for the AMD network device drivers.
+#
+
+obj-$(CONFIG_A2065) += a2065.o
+obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
+obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
+obj-$(CONFIG_ARIADNE) += ariadne.o
+obj-$(CONFIG_ATARILANCE) += atarilance.o
+obj-$(CONFIG_DECLANCE) += declance.o
+obj-$(CONFIG_DEPCA) += depca.o
+obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
+obj-$(CONFIG_LANCE) += lance.o
+obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
+obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
+obj-$(CONFIG_PCMCIA_NMCLAN) += nmclan_cs.o
+obj-$(CONFIG_NI65) += ni65.o
+obj-$(CONFIG_PCNET32) += pcnet32.o
+obj-$(CONFIG_SUN3LANCE) += sun3lance.o
+obj-$(CONFIG_SUNLANCE) += sunlance.o
similarity index 99%
rename from drivers/net/a2065.c
rename to drivers/net/ethernet/amd/a2065.c
index e1e1b07..825e5d4 100644 (file)
@@ -664,7 +664,7 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_stop               = lance_close,
        .ndo_start_xmit         = lance_start_xmit,
        .ndo_tx_timeout         = lance_tx_timeout,
-       .ndo_set_multicast_list = lance_set_multicast,
+       .ndo_set_rx_mode        = lance_set_multicast,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/arm/am79c961a.c
rename to drivers/net/ethernet/amd/am79c961a.c
index 52fe21e..c2b630c 100644 (file)
@@ -659,7 +659,7 @@ static const struct net_device_ops am79c961_netdev_ops = {
        .ndo_open               = am79c961_open,
        .ndo_stop               = am79c961_close,
        .ndo_start_xmit         = am79c961_sendpacket,
-       .ndo_set_multicast_list = am79c961_setmulticastlist,
+       .ndo_set_rx_mode        = am79c961_setmulticastlist,
        .ndo_tx_timeout         = am79c961_timeout,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/amd8111e.c
rename to drivers/net/ethernet/amd/amd8111e.c
index 78002ef..a9745f4 100644 (file)
@@ -1798,7 +1798,7 @@ static const struct net_device_ops amd8111e_netdev_ops = {
        .ndo_start_xmit         = amd8111e_start_xmit,
        .ndo_tx_timeout         = amd8111e_tx_timeout,
        .ndo_get_stats          = amd8111e_get_stats,
-       .ndo_set_multicast_list = amd8111e_set_multicast_list,
+       .ndo_set_rx_mode        = amd8111e_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = amd8111e_set_mac_address,
        .ndo_do_ioctl           = amd8111e_ioctl,
similarity index 99%
rename from drivers/net/ariadne.c
rename to drivers/net/ethernet/amd/ariadne.c
index 7ed78f4..eb18e1f 100644 (file)
@@ -704,7 +704,7 @@ static const struct net_device_ops ariadne_netdev_ops = {
        .ndo_start_xmit         = ariadne_start_xmit,
        .ndo_tx_timeout         = ariadne_tx_timeout,
        .ndo_get_stats          = ariadne_get_stats,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/atarilance.c
rename to drivers/net/ethernet/amd/atarilance.c
index 1264d78..15bfa28 100644 (file)
@@ -456,7 +456,7 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_open               = lance_open,
        .ndo_stop               = lance_close,
        .ndo_start_xmit         = lance_start_xmit,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_set_mac_address    = lance_set_mac_address,
        .ndo_tx_timeout         = lance_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/au1000_eth.c
rename to drivers/net/ethernet/amd/au1000_eth.c
index b9debcf..8238667 100644 (file)
@@ -1010,7 +1010,7 @@ static const struct net_device_ops au1000_netdev_ops = {
        .ndo_open               = au1000_open,
        .ndo_stop               = au1000_close,
        .ndo_start_xmit         = au1000_tx,
-       .ndo_set_multicast_list = au1000_multicast_list,
+       .ndo_set_rx_mode        = au1000_multicast_list,
        .ndo_do_ioctl           = au1000_ioctl,
        .ndo_tx_timeout         = au1000_tx_timeout,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/declance.c
rename to drivers/net/ethernet/amd/declance.c
index d5598f6..73f8d4f 100644 (file)
@@ -1015,7 +1015,7 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_stop               = lance_close,
        .ndo_start_xmit         = lance_start_xmit,
        .ndo_tx_timeout         = lance_tx_timeout,
-       .ndo_set_multicast_list = lance_set_multicast,
+       .ndo_set_rx_mode        = lance_set_multicast,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/depca.c
rename to drivers/net/ethernet/amd/depca.c
index f2015a8..681970c 100644 (file)
@@ -572,7 +572,7 @@ static const struct net_device_ops depca_netdev_ops = {
        .ndo_open               = depca_open,
        .ndo_start_xmit         = depca_start_xmit,
        .ndo_stop               = depca_close,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_do_ioctl           = depca_ioctl,
        .ndo_tx_timeout         = depca_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/hplance.c
rename to drivers/net/ethernet/amd/hplance.c
index a900d5b..86aa0d5 100644 (file)
@@ -74,7 +74,7 @@ static const struct net_device_ops hplance_netdev_ops = {
        .ndo_open               = hplance_open,
        .ndo_stop               = hplance_close,
        .ndo_start_xmit         = lance_start_xmit,
-       .ndo_set_multicast_list = lance_set_multicast,
+       .ndo_set_rx_mode        = lance_set_multicast,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/lance.c
rename to drivers/net/ethernet/amd/lance.c
index 02336ed..a6e2e84 100644 (file)
@@ -459,7 +459,7 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_start_xmit         = lance_start_xmit,
        .ndo_stop               = lance_close,
        .ndo_get_stats          = lance_get_stats,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_tx_timeout         = lance_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/mvme147.c
rename to drivers/net/ethernet/amd/mvme147.c
index 3a7ad84..56bc47a 100644 (file)
@@ -61,7 +61,7 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_open               = m147lance_open,
        .ndo_stop               = m147lance_close,
        .ndo_start_xmit         = lance_start_xmit,
-       .ndo_set_multicast_list = lance_set_multicast,
+       .ndo_set_rx_mode        = lance_set_multicast,
        .ndo_tx_timeout         = lance_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/ni65.c
rename to drivers/net/ethernet/amd/ni65.c
index c75ae85..6e6aa72 100644 (file)
@@ -406,7 +406,7 @@ static const struct net_device_ops ni65_netdev_ops = {
        .ndo_stop               = ni65_close,
        .ndo_start_xmit         = ni65_send_packet,
        .ndo_tx_timeout         = ni65_timeout,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/pcmcia/nmclan_cs.c
rename to drivers/net/ethernet/amd/nmclan_cs.c
index 9d70b65..3accd5d 100644 (file)
@@ -430,7 +430,7 @@ static const struct net_device_ops mace_netdev_ops = {
        .ndo_tx_timeout         = mace_tx_timeout,
        .ndo_set_config         = mace_config,
        .ndo_get_stats          = mace_get_stats,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/pcnet32.c
rename to drivers/net/ethernet/amd/pcnet32.c
index 8b3090d..c90fe91 100644 (file)
@@ -82,7 +82,7 @@ static int cards_found;
 /*
  * VLB I/O addresses
  */
-static unsigned int pcnet32_portlist[] __initdata =
+static unsigned int pcnet32_portlist[] =
     { 0x300, 0x320, 0x340, 0x360, 0 };
 
 static int pcnet32_debug;
@@ -1505,7 +1505,7 @@ static const struct net_device_ops pcnet32_netdev_ops = {
        .ndo_start_xmit         = pcnet32_start_xmit,
        .ndo_tx_timeout         = pcnet32_tx_timeout,
        .ndo_get_stats          = pcnet32_get_stats,
-       .ndo_set_multicast_list = pcnet32_set_multicast_list,
+       .ndo_set_rx_mode        = pcnet32_set_multicast_list,
        .ndo_do_ioctl           = pcnet32_ioctl,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/sun3lance.c
rename to drivers/net/ethernet/amd/sun3lance.c
index 7d9ec23..080b71f 100644 (file)
@@ -297,7 +297,7 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_open               = lance_open,
        .ndo_stop               = lance_close,
        .ndo_start_xmit         = lance_start_xmit,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_set_mac_address    = NULL,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/sunlance.c
rename to drivers/net/ethernet/amd/sunlance.c
index 06f2d43..8fda457 100644 (file)
@@ -1298,7 +1298,7 @@ static const struct net_device_ops sparc_lance_ops = {
        .ndo_open               = lance_open,
        .ndo_stop               = lance_close,
        .ndo_start_xmit         = lance_start_xmit,
-       .ndo_set_multicast_list = lance_set_multicast,
+       .ndo_set_rx_mode        = lance_set_multicast,
        .ndo_tx_timeout         = lance_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
diff --git a/drivers/net/ethernet/apple/Kconfig b/drivers/net/ethernet/apple/Kconfig
new file mode 100644 (file)
index 0000000..59d5c26
--- /dev/null
@@ -0,0 +1,97 @@
+#
+# Apple device configuration
+#
+
+config NET_VENDOR_APPLE
+       bool "Apple devices"
+       default y
+       depends on (PPC_PMAC && PPC32) || MAC || ISA || EISA || MACH_IXDP2351 \
+                  || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about IBM devices. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_APPLE
+
+config MACE
+       tristate "MACE (Power Mac ethernet) support"
+       depends on PPC_PMAC && PPC32
+       select CRC32
+       ---help---
+         Power Macintoshes and clones with Ethernet built-in on the
+         motherboard will usually use a MACE (Medium Access Control for
+         Ethernet) interface. Say Y to include support for the MACE chip.
+
+         To compile this driver as a module, choose M here: the module
+         will be called mace.
+
+config MACE_AAUI_PORT
+       bool "Use AAUI port instead of TP by default"
+       depends on MACE
+       ---help---
+         Some Apple machines (notably the Apple Network Server) which use the
+         MACE ethernet chip have an Apple AUI port (small 15-pin connector),
+         instead of an 8-pin RJ45 connector for twisted-pair ethernet.  Say
+         Y here if you have such a machine.  If unsure, say N.
+         The driver will default to AAUI on ANS anyway, and if you use it as
+         a module, you can provide the port_aaui=0|1 to force the driver.
+
+config BMAC
+       tristate "BMAC (G3 ethernet) support"
+       depends on PPC_PMAC && PPC32
+       select CRC32
+       ---help---
+         Say Y for support of BMAC Ethernet interfaces. These are used on G3
+         computers.
+
+         To compile this driver as a module, choose M here: the module
+         will be called bmac.
+
+config MAC89x0
+       tristate "Macintosh CS89x0 based ethernet cards"
+       depends on MAC
+       ---help---
+         Support for CS89x0 chipset based Ethernet cards.  If you have a
+         Nubus or LC-PDS network (Ethernet) card of this type, say Y and
+         read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. This module will
+         be called mac89x0.
+
+config MACMACE
+       bool "Macintosh (AV) onboard MACE ethernet"
+       depends on MAC
+       select CRC32
+       ---help---
+         Support for the onboard AMD 79C940 MACE Ethernet controller used in
+         the 660AV and 840AV Macintosh.  If you have one of these Macintoshes
+         say Y and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+config CS89x0
+       tristate "CS89x0 support"
+       depends on (ISA || EISA || MACH_IXDP2351 \
+               || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440)
+       ---help---
+         Support for CS89x0 chipset based Ethernet cards. If you have a
+         network (Ethernet) card of this type, say Y and read the
+         Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto> as well as
+         <file:Documentation/networking/cs89x0.txt>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called cs89x0.
+
+config CS89x0_NONISA_IRQ
+       def_bool y
+       depends on CS89x0 != n
+       depends on MACH_IXDP2351 || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440
+
+endif # NET_VENDOR_APPLE
diff --git a/drivers/net/ethernet/apple/Makefile b/drivers/net/ethernet/apple/Makefile
new file mode 100644 (file)
index 0000000..9d30086
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for the Apple network device drivers.
+#
+
+obj-$(CONFIG_MACE) += mace.o
+obj-$(CONFIG_BMAC) += bmac.o
+obj-$(CONFIG_MAC89x0) += mac89x0.o
+obj-$(CONFIG_CS89x0) += cs89x0.o
+obj-$(CONFIG_MACMACE) += macmace.o
similarity index 99%
rename from drivers/net/bmac.c
rename to drivers/net/ethernet/apple/bmac.c
index 45e45e8..d070b22 100644 (file)
@@ -1237,7 +1237,7 @@ static const struct net_device_ops bmac_netdev_ops = {
        .ndo_open               = bmac_open,
        .ndo_stop               = bmac_close,
        .ndo_start_xmit         = bmac_output,
-       .ndo_set_multicast_list = bmac_set_multicast,
+       .ndo_set_rx_mode        = bmac_set_multicast,
        .ndo_set_mac_address    = bmac_set_address,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/cs89x0.c
rename to drivers/net/ethernet/apple/cs89x0.c
index 537a4b2..f328da2 100644 (file)
@@ -488,7 +488,7 @@ static const struct net_device_ops net_ops = {
        .ndo_tx_timeout         = net_timeout,
        .ndo_start_xmit         = net_send_packet,
        .ndo_get_stats          = net_get_stats,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_set_mac_address    = set_mac_address,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = net_poll_controller,
similarity index 99%
rename from drivers/net/mac89x0.c
rename to drivers/net/ethernet/apple/mac89x0.c
index 669b317..83781f3 100644 (file)
@@ -170,7 +170,7 @@ static const struct net_device_ops mac89x0_netdev_ops = {
        .ndo_stop               = net_close,
        .ndo_start_xmit         = net_send_packet,
        .ndo_get_stats          = net_get_stats,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_set_mac_address    = set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/mace.c
rename to drivers/net/ethernet/apple/mace.c
index 2074e97..bec87bd 100644 (file)
@@ -100,7 +100,7 @@ static const struct net_device_ops mace_netdev_ops = {
        .ndo_open               = mace_open,
        .ndo_stop               = mace_close,
        .ndo_start_xmit         = mace_xmit_start,
-       .ndo_set_multicast_list = mace_set_multicast,
+       .ndo_set_rx_mode        = mace_set_multicast,
        .ndo_set_mac_address    = mace_set_address,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/macmace.c
rename to drivers/net/ethernet/apple/macmace.c
index 4286e67..6cd3f86 100644 (file)
@@ -185,7 +185,7 @@ static const struct net_device_ops mace_netdev_ops = {
        .ndo_stop               = mace_close,
        .ndo_start_xmit         = mace_xmit_start,
        .ndo_tx_timeout         = mace_tx_timeout,
-       .ndo_set_multicast_list = mace_set_multicast,
+       .ndo_set_rx_mode        = mace_set_multicast,
        .ndo_set_mac_address    = mace_set_address,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
diff --git a/drivers/net/ethernet/atheros/Kconfig b/drivers/net/ethernet/atheros/Kconfig
new file mode 100644 (file)
index 0000000..26ab8ca
--- /dev/null
@@ -0,0 +1,66 @@
+#
+# Atheros device configuration
+#
+
+config NET_VENDOR_ATHEROS
+       bool "Atheros devices"
+       default y
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Atheros devices. If you say Y, you will be asked
+         for your specific card in the following questions.
+
+if NET_VENDOR_ATHEROS
+
+config ATL2
+       tristate "Atheros L2 Fast Ethernet support"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         This driver supports the Atheros L2 fast ethernet adapter.
+
+         To compile this driver as a module, choose M here.  The module
+         will be called atl2.
+
+config ATL1
+       tristate "Atheros/Attansic L1 Gigabit Ethernet support"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         This driver supports the Atheros/Attansic L1 gigabit ethernet
+         adapter.
+
+         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.
+
+config ATL1C
+       tristate "Atheros L1C Gigabit Ethernet support (EXPERIMENTAL)"
+       depends on PCI && EXPERIMENTAL
+       select CRC32
+       select MII
+       ---help---
+         This driver supports the Atheros L1C gigabit ethernet adapter.
+
+         To compile this driver as a module, choose M here.  The module
+         will be called atl1c.
+
+endif # NET_VENDOR_ATHEROS
diff --git a/drivers/net/ethernet/atheros/Makefile b/drivers/net/ethernet/atheros/Makefile
new file mode 100644 (file)
index 0000000..e7e76fb
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for the Atheros network device drivers.
+#
+
+obj-$(CONFIG_ATL1) += atlx/
+obj-$(CONFIG_ATL2) += atlx/
+obj-$(CONFIG_ATL1E) += atl1e/
+obj-$(CONFIG_ATL1C) += atl1c/
similarity index 99%
rename from drivers/net/atl1c/atl1c_main.c
rename to drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 9722442..acb4c10 100644 (file)
@@ -2600,7 +2600,7 @@ static const struct net_device_ops atl1c_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_start_xmit         = atl1c_xmit_frame,
        .ndo_set_mac_address    = atl1c_set_mac_addr,
-       .ndo_set_multicast_list = atl1c_set_multi,
+       .ndo_set_rx_mode        = atl1c_set_multi,
        .ndo_change_mtu         = atl1c_change_mtu,
        .ndo_fix_features       = atl1c_fix_features,
        .ndo_set_features       = atl1c_set_features,
similarity index 99%
rename from drivers/net/atl1e/atl1e_main.c
rename to drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index d8d4119..1b5dc79 100644 (file)
@@ -2212,7 +2212,7 @@ static const struct net_device_ops atl1e_netdev_ops = {
        .ndo_stop               = atl1e_close,
        .ndo_start_xmit         = atl1e_xmit_frame,
        .ndo_get_stats          = atl1e_get_stats,
-       .ndo_set_multicast_list = atl1e_set_multi,
+       .ndo_set_rx_mode        = atl1e_set_multi,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = atl1e_set_mac_addr,
        .ndo_fix_features       = atl1e_fix_features,
similarity index 99%
rename from drivers/net/atlx/atl1.c
rename to drivers/net/ethernet/atheros/atlx/atl1.c
index 97e6954..c34e823 100644 (file)
@@ -2869,7 +2869,7 @@ static const struct net_device_ops atl1_netdev_ops = {
        .ndo_open               = atl1_open,
        .ndo_stop               = atl1_close,
        .ndo_start_xmit         = atl1_xmit_frame,
-       .ndo_set_multicast_list = atlx_set_multi,
+       .ndo_set_rx_mode        = atlx_set_multi,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = atl1_set_mac,
        .ndo_change_mtu         = atl1_change_mtu,
similarity index 99%
rename from drivers/net/atlx/atl2.c
rename to drivers/net/ethernet/atheros/atlx/atl2.c
index d4f7dda..1feae59 100644 (file)
@@ -1325,7 +1325,7 @@ static const struct net_device_ops atl2_netdev_ops = {
        .ndo_open               = atl2_open,
        .ndo_stop               = atl2_close,
        .ndo_start_xmit         = atl2_xmit_frame,
-       .ndo_set_multicast_list = atl2_set_multi,
+       .ndo_set_rx_mode        = atl2_set_multi,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = atl2_set_mac,
        .ndo_change_mtu         = atl2_change_mtu,
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
new file mode 100644 (file)
index 0000000..d82ad22
--- /dev/null
@@ -0,0 +1,120 @@
+#
+# Broadcom device configuration
+#
+
+config NET_VENDOR_BROADCOM
+       bool "Broadcom devices"
+       default y
+       depends on (SSB_POSSIBLE && HAS_DMA) || PCI || BCM63XX || \
+                  SIBYTE_SB1xxx_SOC
+       ---help---
+         If you have a network (Ethernet) chipset belonging to this class,
+         say Y.
+
+         Note that the answer to this question does not directly affect
+         the kernel: saying N will just case the configurator to skip all
+         the questions regarding AMD chipsets. If you say Y, you will be asked
+         for your specific chipset/driver in the following questions.
+
+if NET_VENDOR_BROADCOM
+
+config B44
+       tristate "Broadcom 440x/47xx ethernet support"
+       depends on SSB_POSSIBLE && HAS_DMA
+       select SSB
+       select MII
+       ---help---
+         If you have a network (Ethernet) controller of this type, say Y
+         or M and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called b44.
+
+# Auto-select SSB PCI-HOST support, if possible
+config B44_PCI_AUTOSELECT
+       bool
+       depends on B44 && SSB_PCIHOST_POSSIBLE
+       select SSB_PCIHOST
+       default y
+
+# Auto-select SSB PCICORE driver, if possible
+config B44_PCICORE_AUTOSELECT
+       bool
+       depends on B44 && SSB_DRIVER_PCICORE_POSSIBLE
+       select SSB_DRIVER_PCICORE
+       default y
+
+config B44_PCI
+       bool
+       depends on B44_PCI_AUTOSELECT && B44_PCICORE_AUTOSELECT
+       default y
+
+config BCM63XX_ENET
+       tristate "Broadcom 63xx internal mac support"
+       depends on BCM63XX
+       select MII
+       select PHYLIB
+       help
+         This driver supports the ethernet MACs in the Broadcom 63xx
+         MIPS chipset family (BCM63XX).
+
+config BNX2
+       tristate "Broadcom NetXtremeII support"
+       depends on PCI
+       select CRC32
+       select FW_LOADER
+       ---help---
+         This driver supports Broadcom NetXtremeII gigabit Ethernet cards.
+
+         To compile this driver as a module, choose M here: the module
+         will be called bnx2.  This is recommended.
+
+config CNIC
+       tristate "Broadcom CNIC support"
+       depends on PCI
+       select BNX2
+       select UIO
+       ---help---
+         This driver supports offload features of Broadcom NetXtremeII
+         gigabit Ethernet cards.
+
+         To compile this driver as a module, choose M here: the module
+         will be called cnic.  This is recommended.
+
+config SB1250_MAC
+       tristate "SB1250 Gigabit Ethernet support"
+       depends on SIBYTE_SB1xxx_SOC
+       select PHYLIB
+       ---help---
+         This driver supports Gigabit Ethernet interfaces based on the
+         Broadcom SiByte family of System-On-a-Chip parts.  They include
+         the BCM1120, BCM1125, BCM1125H, BCM1250, BCM1255, BCM1280, BCM1455
+         and BCM1480 chips.
+
+         To compile this driver as a module, choose M here: the module
+         will be called sb1250-mac.
+
+config TIGON3
+       tristate "Broadcom Tigon3 support"
+       depends on PCI
+       select PHYLIB
+       ---help---
+         This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
+
+         To compile this driver as a module, choose M here: the module
+         will be called tg3.  This is recommended.
+
+config BNX2X
+       tristate "Broadcom NetXtremeII 10Gb support"
+       depends on PCI
+       select FW_LOADER
+       select ZLIB_INFLATE
+       select LIBCRC32C
+       select MDIO
+       ---help---
+         This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards.
+         To compile this driver as a module, choose M here: the module
+         will be called bnx2x.  This is recommended.
+
+endif # NET_VENDOR_BROADCOM
diff --git a/drivers/net/ethernet/broadcom/Makefile b/drivers/net/ethernet/broadcom/Makefile
new file mode 100644 (file)
index 0000000..b789605
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for the Broadcom network device drivers.
+#
+
+obj-$(CONFIG_B44) += b44.o
+obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
+obj-$(CONFIG_BNX2) += bnx2.o
+obj-$(CONFIG_CNIC) += cnic.o
+obj-$(CONFIG_BNX2X) += bnx2x/
+obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
+obj-$(CONFIG_TIGON3) += tg3.o
similarity index 99%
rename from drivers/net/b44.c
rename to drivers/net/ethernet/broadcom/b44.c
index 41ea84e..4cf835d 100644 (file)
@@ -2114,7 +2114,7 @@ static const struct net_device_ops b44_netdev_ops = {
        .ndo_stop               = b44_close,
        .ndo_start_xmit         = b44_start_xmit,
        .ndo_get_stats          = b44_get_stats,
-       .ndo_set_multicast_list = b44_set_rx_mode,
+       .ndo_set_rx_mode        = b44_set_rx_mode,
        .ndo_set_mac_address    = b44_set_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = b44_ioctl,
similarity index 99%
rename from drivers/net/bcm63xx_enet.c
rename to drivers/net/ethernet/broadcom/bcm63xx_enet.c
index 1d9b985..05b0228 100644 (file)
@@ -1603,7 +1603,7 @@ static const struct net_device_ops bcm_enet_ops = {
        .ndo_stop               = bcm_enet_stop,
        .ndo_start_xmit         = bcm_enet_start_xmit,
        .ndo_set_mac_address    = bcm_enet_set_mac_address,
-       .ndo_set_multicast_list = bcm_enet_set_multicast_list,
+       .ndo_set_rx_mode        = bcm_enet_set_multicast_list,
        .ndo_do_ioctl           = bcm_enet_ioctl,
        .ndo_change_mtu         = bcm_enet_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
similarity index 99%
rename from drivers/net/bnx2.c
rename to drivers/net/ethernet/broadcom/bnx2.c
index 4b2b570..9afb653 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/time.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
+#include <linux/if.h>
 #include <linux/if_vlan.h>
 #include <net/ip.h>
 #include <net/tcp.h>
@@ -2929,8 +2930,8 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
 
                shinfo = skb_shinfo(skb);
                shinfo->nr_frags--;
-               page = shinfo->frags[shinfo->nr_frags].page;
-               shinfo->frags[shinfo->nr_frags].page = NULL;
+               page = skb_frag_page(&shinfo->frags[shinfo->nr_frags]);
+               __skb_frag_set_page(&shinfo->frags[shinfo->nr_frags], NULL);
 
                cons_rx_pg->page = page;
                dev_kfree_skb(skb);
@@ -6510,8 +6511,8 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
                txbd = &txr->tx_desc_ring[ring_prod];
 
                len = frag->size;
-               mapping = dma_map_page(&bp->pdev->dev, frag->page, frag->page_offset,
-                                      len, PCI_DMA_TODEVICE);
+               mapping = skb_frag_dma_map(&bp->pdev->dev, frag, 0, len,
+                                          PCI_DMA_TODEVICE);
                if (dma_mapping_error(&bp->pdev->dev, mapping))
                        goto dma_error;
                dma_unmap_addr_set(&txr->tx_buf_ring[ring_prod], mapping,
@@ -8370,6 +8371,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->vlan_features = dev->hw_features;
        dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
        dev->features |= dev->hw_features;
+       dev->priv_flags |= IFF_UNICAST_FLT;
 
        if ((rc = register_netdev(dev))) {
                dev_err(&pdev->dev, "Cannot register net device\n");
similarity index 98%
rename from drivers/net/bnx2x/bnx2x.h
rename to drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index c423504..f127768 100644 (file)
 #define BNX2X_MSG_SP                   0x100000 /* was: NETIF_MSG_INTR */
 #define BNX2X_MSG_FP                   0x200000 /* was: NETIF_MSG_INTR */
 
-#define DP_LEVEL                       KERN_NOTICE     /* was: KERN_DEBUG */
-
 /* regular debug print */
-#define DP(__mask, __fmt, __args...)                           \
+#define DP(__mask, fmt, ...)                                   \
 do {                                                           \
        if (bp->msg_enable & (__mask))                          \
-               printk(DP_LEVEL "[%s:%d(%s)]" __fmt,            \
-                      __func__, __LINE__,                      \
-                      bp->dev ? (bp->dev->name) : "?",         \
-                      ##__args);                               \
+               pr_notice("[%s:%d(%s)]" fmt,                    \
+                         __func__, __LINE__,                   \
+                         bp->dev ? (bp->dev->name) : "?",      \
+                         ##__VA_ARGS__);                       \
 } while (0)
 
-#define DP_CONT(__mask, __fmt, __args...)                      \
+#define DP_CONT(__mask, fmt, ...)                              \
 do {                                                           \
        if (bp->msg_enable & (__mask))                          \
-               pr_cont(__fmt, ##__args);                       \
+               pr_cont(fmt, ##__VA_ARGS__);                    \
 } while (0)
 
 /* errors debug print */
-#define BNX2X_DBG_ERR(__fmt, __args...)                                \
+#define BNX2X_DBG_ERR(fmt, ...)                                        \
 do {                                                           \
        if (netif_msg_probe(bp))                                \
-               pr_err("[%s:%d(%s)]" __fmt,                     \
+               pr_err("[%s:%d(%s)]" fmt,                       \
                       __func__, __LINE__,                      \
                       bp->dev ? (bp->dev->name) : "?",         \
-                      ##__args);                               \
+                      ##__VA_ARGS__);                          \
 } while (0)
 
 /* for errors (never masked) */
-#define BNX2X_ERR(__fmt, __args...)                            \
+#define BNX2X_ERR(fmt, ...)                                    \
 do {                                                           \
-       pr_err("[%s:%d(%s)]" __fmt,                             \
+       pr_err("[%s:%d(%s)]" fmt,                               \
               __func__, __LINE__,                              \
               bp->dev ? (bp->dev->name) : "?",                 \
-              ##__args);                                       \
-       } while (0)
+              ##__VA_ARGS__);                                  \
+} while (0)
 
-#define BNX2X_ERROR(__fmt, __args...) do { \
-       pr_err("[%s:%d]" __fmt, __func__, __LINE__, ##__args); \
-       } while (0)
+#define BNX2X_ERROR(fmt, ...)                                  \
+       pr_err("[%s:%d]" fmt, __func__, __LINE__, ##__VA_ARGS__)
 
 
 /* before we have a dev->name use dev_info() */
-#define BNX2X_DEV_INFO(__fmt, __args...)                        \
+#define BNX2X_DEV_INFO(fmt, ...)                                \
 do {                                                            \
        if (netif_msg_probe(bp))                                 \
-               dev_info(&bp->pdev->dev, __fmt, ##__args);       \
+               dev_info(&bp->pdev->dev, fmt, ##__VA_ARGS__);    \
 } while (0)
 
-#define BNX2X_MAC_FMT          "%pM"
-#define BNX2X_MAC_PRN_LIST(mac)        (mac)
-
-
 #ifdef BNX2X_STOP_ON_ERROR
 void bnx2x_int_disable(struct bnx2x *bp);
-#define bnx2x_panic() do { \
-               bp->panic = 1; \
-               BNX2X_ERR("driver assert\n"); \
-               bnx2x_int_disable(bp); \
-               bnx2x_panic_dump(bp); \
-       } while (0)
+#define bnx2x_panic()                          \
+do {                                           \
+       bp->panic = 1;                          \
+       BNX2X_ERR("driver assert\n");           \
+       bnx2x_int_disable(bp);                  \
+       bnx2x_panic_dump(bp);                   \
+} while (0)
 #else
-#define bnx2x_panic() do { \
-               bp->panic = 1; \
-               BNX2X_ERR("driver assert\n"); \
-               bnx2x_panic_dump(bp); \
-       } while (0)
+#define bnx2x_panic()                          \
+do {                                           \
+       bp->panic = 1;                          \
+       BNX2X_ERR("driver assert\n");           \
+       bnx2x_panic_dump(bp);                   \
+} while (0)
 #endif
 
 #define bnx2x_mc_addr(ha)      ((ha)->addr)
similarity index 97%
rename from drivers/net/bnx2x/bnx2x_cmn.c
rename to drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 5b0dba6..5c3eb17 100644 (file)
@@ -15,6 +15,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
 #include <linux/interrupt.h>
@@ -63,8 +65,9 @@ static inline void bnx2x_bz_fp(struct bnx2x *bp, int index)
        fp->disable_tpa = ((bp->flags & TPA_ENABLE_FLAG) == 0);
 
 #ifdef BCM_CNIC
-       /* We don't want TPA on FCoE, FWD and OOO L2 rings */
-       bnx2x_fcoe(bp, disable_tpa) = 1;
+       /* We don't want TPA on an FCoE L2 ring */
+       if (IS_FCOE_FP(fp))
+               fp->disable_tpa = 1;
 #endif
 }
 
@@ -953,15 +956,16 @@ void __bnx2x_link_report(struct bnx2x *bp)
                netdev_err(bp->dev, "NIC Link is Down\n");
                return;
        } else {
+               const char *duplex;
+               const char *flow;
+
                netif_carrier_on(bp->dev);
-               netdev_info(bp->dev, "NIC Link is Up, ");
-               pr_cont("%d Mbps ", cur_data.line_speed);
 
                if (test_and_clear_bit(BNX2X_LINK_REPORT_FD,
                                       &cur_data.link_report_flags))
-                       pr_cont("full duplex");
+                       duplex = "full";
                else
-                       pr_cont("half duplex");
+                       duplex = "half";
 
                /* Handle the FC at the end so that only these flags would be
                 * possibly set. This way we may easily check if there is no FC
@@ -970,16 +974,19 @@ void __bnx2x_link_report(struct bnx2x *bp)
                if (cur_data.link_report_flags) {
                        if (test_bit(BNX2X_LINK_REPORT_RX_FC_ON,
                                     &cur_data.link_report_flags)) {
-                               pr_cont(", receive ");
                                if (test_bit(BNX2X_LINK_REPORT_TX_FC_ON,
                                     &cur_data.link_report_flags))
-                                       pr_cont("& transmit ");
+                                       flow = "ON - receive & transmit";
+                               else
+                                       flow = "ON - receive";
                        } else {
-                               pr_cont(", transmit ");
+                               flow = "ON - transmit";
                        }
-                       pr_cont("flow control ON");
+               } else {
+                       flow = "none";
                }
-               pr_cont("\n");
+               netdev_info(bp->dev, "NIC Link is Up, %d Mbps %s duplex, Flow control: %s\n",
+                           cur_data.line_speed, duplex, flow);
        }
 }
 
@@ -1404,10 +1411,9 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
        struct bnx2x *bp = netdev_priv(dev);
+
 #ifdef BCM_CNIC
-       if (NO_FCOE(bp))
-               return skb_tx_hash(dev, skb);
-       else {
+       if (!NO_FCOE(bp)) {
                struct ethhdr *hdr = (struct ethhdr *)skb->data;
                u16 ether_type = ntohs(hdr->h_proto);
 
@@ -1424,8 +1430,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
                        return bnx2x_fcoe_tx(bp, txq_index);
        }
 #endif
-       /* Select a none-FCoE queue:  if FCoE is enabled, exclude FCoE L2 ring
-        */
+       /* select a non-FCoE queue */
        return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp));
 }
 
@@ -1448,6 +1453,28 @@ void bnx2x_set_num_queues(struct bnx2x *bp)
        bp->num_queues += NON_ETH_CONTEXT_USE;
 }
 
+/**
+ * bnx2x_set_real_num_queues - configure netdev->real_num_[tx,rx]_queues
+ *
+ * @bp:                Driver handle
+ *
+ * We currently support for at most 16 Tx queues for each CoS thus we will
+ * allocate a multiple of 16 for ETH L2 rings according to the value of the
+ * bp->max_cos.
+ *
+ * If there is an FCoE L2 queue the appropriate Tx queue will have the next
+ * index after all ETH L2 indices.
+ *
+ * If the actual number of Tx queues (for each CoS) is less than 16 then there
+ * will be the holes at the end of each group of 16 ETh L2 indices (0..15,
+ * 16..31,...) with indicies that are not coupled with any real Tx queue.
+ *
+ * The proper configuration of skb->queue_mapping is handled by
+ * bnx2x_select_queue() and __skb_tx_hash().
+ *
+ * bnx2x_setup_tc() takes care of the proper TC mappings so that __skb_tx_hash()
+ * will return a proper Tx index if TC is enabled (netdev->num_tc > 0).
+ */
 static inline int bnx2x_set_real_num_queues(struct bnx2x *bp)
 {
        int rc, tx, rx;
@@ -1989,14 +2016,20 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
                return -EINVAL;
        }
 
+       /*
+        * It's important to set the bp->state to the value different from
+        * BNX2X_STATE_OPEN and only then stop the Tx. Otherwise bnx2x_tx_int()
+        * may restart the Tx from the NAPI context (see bnx2x_tx_int()).
+        */
+       bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
+       smp_mb();
+
        /* Stop Tx */
        bnx2x_tx_disable(bp);
 
 #ifdef BCM_CNIC
        bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
 #endif
-       bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
-       smp_mb();
 
        bp->rx_mode = BNX2X_RX_MODE_NONE;
 
@@ -2578,7 +2611,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif
 
        /* enable this debug print to view the transmission queue being used
-       DP(BNX2X_MSG_FP, "indices: txq %d, fp %d, txdata %d",
+       DP(BNX2X_MSG_FP, "indices: txq %d, fp %d, txdata %d\n",
           txq_index, fp_index, txdata_index); */
 
        /* locate the fastpath and the txdata */
@@ -2587,7 +2620,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* enable this debug print to view the tranmission details
        DP(BNX2X_MSG_FP,"transmitting packet cid %d fp index %d txdata_index %d"
-                       " tx_data ptr %p fp pointer %p",
+                       " tx_data ptr %p fp pointer %p\n",
           txdata->cid, fp_index, txdata_index, txdata, fp); */
 
        if (unlikely(bnx2x_tx_avail(bp, txdata) <
@@ -2767,9 +2800,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
-               mapping = dma_map_page(&bp->pdev->dev, frag->page,
-                                      frag->page_offset, frag->size,
-                                      DMA_TO_DEVICE);
+               mapping = skb_frag_dma_map(&bp->pdev->dev, frag, 0, frag->size,
+                                          DMA_TO_DEVICE);
                if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
 
                        DP(NETIF_MSG_TX_QUEUED, "Unable to map page - "
@@ -2904,14 +2936,14 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
        /* requested to support too many traffic classes */
        if (num_tc > bp->max_cos) {
                DP(NETIF_MSG_TX_ERR, "support for too many traffic classes"
-                                    " requested: %d. max supported is %d",
+                                    " requested: %d. max supported is %d\n",
                                     num_tc, bp->max_cos);
                return -EINVAL;
        }
 
        /* declare amount of supported traffic classes */
        if (netdev_set_num_tc(dev, num_tc)) {
-               DP(NETIF_MSG_TX_ERR, "failed to declare %d traffic classes",
+               DP(NETIF_MSG_TX_ERR, "failed to declare %d traffic classes\n",
                                     num_tc);
                return -EINVAL;
        }
@@ -2919,7 +2951,7 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
        /* configure priority to traffic class mapping */
        for (prio = 0; prio < BNX2X_MAX_PRIORITY; prio++) {
                netdev_set_prio_tc_map(dev, prio, bp->prio_to_cos[prio]);
-               DP(BNX2X_MSG_SP, "mapping priority %d to tc %d",
+               DP(BNX2X_MSG_SP, "mapping priority %d to tc %d\n",
                   prio, bp->prio_to_cos[prio]);
        }
 
@@ -2928,10 +2960,10 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
           This can be used for ets or pfc, and save the effort of setting
           up a multio class queue disc or negotiating DCBX with a switch
        netdev_set_prio_tc_map(dev, 0, 0);
-       DP(BNX2X_MSG_SP, "mapping priority %d to tc %d", 0, 0);
+       DP(BNX2X_MSG_SP, "mapping priority %d to tc %d\n", 0, 0);
        for (prio = 1; prio < 16; prio++) {
                netdev_set_prio_tc_map(dev, prio, 1);
-               DP(BNX2X_MSG_SP, "mapping priority %d to tc %d", prio, 1);
+               DP(BNX2X_MSG_SP, "mapping priority %d to tc %d\n", prio, 1);
        } */
 
        /* configure traffic class to transmission queue mapping */
@@ -2939,7 +2971,7 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
                count = BNX2X_NUM_ETH_QUEUES(bp);
                offset = cos * MAX_TXQS_PER_COS;
                netdev_set_tc_queue(dev, cos, count, offset);
-               DP(BNX2X_MSG_SP, "mapping tc %d to offset %d count %d",
+               DP(BNX2X_MSG_SP, "mapping tc %d to offset %d count %d\n",
                   cos, offset, count);
        }
 
@@ -3027,7 +3059,7 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
                        struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
 
                        DP(BNX2X_MSG_SP,
-                          "freeing tx memory of fp %d cos %d cid %d",
+                          "freeing tx memory of fp %d cos %d cid %d\n",
                           fp_index, cos, txdata->cid);
 
                        BNX2X_FREE(txdata->tx_buf_ring);
@@ -3109,7 +3141,7 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
                        struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
 
                        DP(BNX2X_MSG_SP, "allocating tx memory of "
-                                        "fp %d cos %d",
+                                        "fp %d cos %d\n",
                           index, cos);
 
                        BNX2X_ALLOC(txdata->tx_buf_ring,
@@ -3359,7 +3391,7 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
        struct bnx2x *bp = netdev_priv(dev);
 
        if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
-               printk(KERN_ERR "Handling parity error recovery. Try again later\n");
+               pr_err("Handling parity error recovery. Try again later\n");
                return -EAGAIN;
        }
 
@@ -3485,7 +3517,7 @@ int bnx2x_resume(struct pci_dev *pdev)
        bp = netdev_priv(dev);
 
        if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
-               printk(KERN_ERR "Handling parity error recovery. Try again later\n");
+               pr_err("Handling parity error recovery. Try again later\n");
                return -EAGAIN;
        }
 
similarity index 99%
rename from drivers/net/bnx2x/bnx2x_cmn.h
rename to drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 223bfee..f290b23 100644 (file)
@@ -1289,7 +1289,7 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp,
        txdata->txq_index = txq_index;
        txdata->tx_cons_sb = tx_cons_sb;
 
-       DP(BNX2X_MSG_SP, "created tx data cid %d, txq %d",
+       DP(BNX2X_MSG_SP, "created tx data cid %d, txq %d\n",
           txdata->cid, txdata->txq_index);
 }
 
@@ -1333,7 +1333,7 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
        bnx2x_init_txdata(bp, &bnx2x_fcoe(bp, txdata[0]),
                          fp->cid, FCOE_TXQ_IDX(bp), BNX2X_FCOE_L2_TX_INDEX);
 
-       DP(BNX2X_MSG_SP, "created fcoe tx data (fp index %d)", fp->index);
+       DP(BNX2X_MSG_SP, "created fcoe tx data (fp index %d)\n", fp->index);
 
        /* qZone id equals to FW (per path) client id */
        bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fp_qzone_id(fp);
@@ -1481,8 +1481,8 @@ static inline u16 bnx2x_extract_max_cfg(struct bnx2x *bp, u32 mf_cfg)
        u16 max_cfg = (mf_cfg & FUNC_MF_CFG_MAX_BW_MASK) >>
                              FUNC_MF_CFG_MAX_BW_SHIFT;
        if (!max_cfg) {
-               BNX2X_ERR("Illegal configuration detected for Max BW - "
-                         "using 100 instead\n");
+               DP(NETIF_MSG_LINK,
+                  "Max BW configured to 0 - using 100 instead\n");
                max_cfg = 100;
        }
        return max_cfg;
similarity index 99%
rename from drivers/net/bnx2x/bnx2x_dcb.c
rename to drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
index a4ea35f..0b9bd55 100644 (file)
@@ -16,6 +16,9 @@
  * Written by: Dmitry Kravkov
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -350,7 +353,7 @@ static void bnx2x_dcbx_map_nw(struct bnx2x *bp)
                if (cos_params[i].pri_bitmask & nw_prio) {
                        /* extend the bitmask with unmapped */
                        DP(NETIF_MSG_LINK,
-                          "cos %d extended with 0x%08x", i, unmapped);
+                          "cos %d extended with 0x%08x\n", i, unmapped);
                        cos_params[i].pri_bitmask |= unmapped;
                        break;
                }
@@ -920,7 +923,7 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
 
 void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
 {
-       if (!CHIP_IS_E1x(bp)) {
+       if (!CHIP_IS_E1x(bp) && !CHIP_IS_E3(bp)) {
                bp->dcb_state = dcb_on;
                bp->dcbx_enabled = dcbx_enabled;
        } else {
similarity index 99%
rename from drivers/net/bnx2x/bnx2x_ethtool.c
rename to drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 2218630..767c229 100644 (file)
@@ -14,6 +14,9 @@
  * Statistics and Link management by Yitchak Gertner
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/ethtool.h>
 #include <linux/netdevice.h>
 #include <linux/types.h>
@@ -239,9 +242,9 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        cmd->maxrxpkt = 0;
 
        DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n"
-          DP_LEVEL "  supported 0x%x  advertising 0x%x  speed %u\n"
-          DP_LEVEL "  duplex %d  port %d  phy_address %d  transceiver %d\n"
-          DP_LEVEL "  autoneg %d  maxtxpkt %d  maxrxpkt %d\n",
+          "  supported 0x%x  advertising 0x%x  speed %u\n"
+          "  duplex %d  port %d  phy_address %d  transceiver %d\n"
+          "  autoneg %d  maxtxpkt %d  maxrxpkt %d\n",
           cmd->cmd, cmd->supported, cmd->advertising,
           ethtool_cmd_speed(cmd),
           cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
@@ -482,7 +485,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        }
 
        DP(NETIF_MSG_LINK, "req_line_speed %d\n"
-          DP_LEVEL "  req_duplex %d  advertising 0x%x\n",
+          "  req_duplex %d  advertising 0x%x\n",
           bp->link_params.req_line_speed[cfg_idx],
           bp->link_params.req_duplex[cfg_idx],
           bp->port.advertising[cfg_idx]);
@@ -1028,7 +1031,7 @@ static int bnx2x_get_eeprom(struct net_device *dev,
                return -EAGAIN;
 
        DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n"
-          DP_LEVEL "  magic 0x%x  offset 0x%x (%d)  len 0x%x (%d)\n",
+          "  magic 0x%x  offset 0x%x (%d)  len 0x%x (%d)\n",
           eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset,
           eeprom->len, eeprom->len);
 
@@ -1199,7 +1202,7 @@ static int bnx2x_set_eeprom(struct net_device *dev,
                return -EAGAIN;
 
        DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n"
-          DP_LEVEL "  magic 0x%x  offset 0x%x (%d)  len 0x%x (%d)\n",
+          "  magic 0x%x  offset 0x%x (%d)  len 0x%x (%d)\n",
           eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset,
           eeprom->len, eeprom->len);
 
@@ -1328,7 +1331,7 @@ static int bnx2x_set_ringparam(struct net_device *dev,
        struct bnx2x *bp = netdev_priv(dev);
 
        if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
-               printk(KERN_ERR "Handling parity error recovery. Try again later\n");
+               pr_err("Handling parity error recovery. Try again later\n");
                return -EAGAIN;
        }
 
@@ -1359,7 +1362,7 @@ static void bnx2x_get_pauseparam(struct net_device *dev,
                            BNX2X_FLOW_CTRL_TX);
 
        DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
-          DP_LEVEL "  autoneg %d  rx_pause %d  tx_pause %d\n",
+          "  autoneg %d  rx_pause %d  tx_pause %d\n",
           epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
 }
 
@@ -1372,7 +1375,7 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
                return 0;
 
        DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
-          DP_LEVEL "  autoneg %d  rx_pause %d  tx_pause %d\n",
+          "  autoneg %d  rx_pause %d  tx_pause %d\n",
           epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
 
        bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_AUTO;
@@ -1970,7 +1973,7 @@ static void bnx2x_self_test(struct net_device *dev,
        struct bnx2x *bp = netdev_priv(dev);
        u8 is_serdes;
        if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
-               printk(KERN_ERR "Handling parity error recovery. Try again later\n");
+               pr_err("Handling parity error recovery. Try again later\n");
                etest->flags |= ETH_TEST_FL_FAILED;
                return;
        }
similarity index 99%
rename from drivers/net/bnx2x/bnx2x_hsi.h
rename to drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
index 06727f3..e44b858 100644 (file)
@@ -704,6 +704,7 @@ struct port_hw_cfg {                    /* port 0: 0x12c  port 1: 0x2bc */
                #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833      0x00000d00
                #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54618SE    0x00000e00
                #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8722       0x00000f00
+               #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54616      0x00001000
                #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE       0x0000fd00
                #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN      0x0000ff00
 
@@ -759,6 +760,7 @@ struct port_hw_cfg {                    /* port 0: 0x12c  port 1: 0x2bc */
                #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833       0x00000d00
                #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE     0x00000e00
                #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722        0x00000f00
+               #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616       0x00001000
                #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT_WC      0x0000fc00
                #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE        0x0000fd00
                #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN       0x0000ff00
@@ -1204,6 +1206,8 @@ struct drv_port_mb {
 
        #define LINK_STATUS_PFC_ENABLED                         0x20000000
 
+       #define LINK_STATUS_PHYSICAL_LINK_FLAG                  0x40000000
+
        u32 port_stx;
 
        u32 stat_nig_timer;
similarity index 97%
rename from drivers/net/bnx2x/bnx2x_link.c
rename to drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index bcd8f00..8e9b87b 100644 (file)
@@ -694,8 +694,8 @@ static int bnx2x_ets_e3b0_disabled(const struct link_params *params,
        struct bnx2x *bp = params->bp;
 
        if (!CHIP_IS_E3B0(bp)) {
-               DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_disabled the chip isn't E3B0"
-                                  "\n");
+               DP(NETIF_MSG_LINK,
+                  "bnx2x_ets_e3b0_disabled the chip isn't E3B0\n");
                return -EINVAL;
        }
 
@@ -854,8 +854,8 @@ static int bnx2x_ets_e3b0_get_total_bw(
                if (bnx2x_cos_state_bw == ets_params->cos[cos_idx].state) {
 
                        if (0 == ets_params->cos[cos_idx].params.bw_params.bw) {
-                               DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config BW"
-                                                  "was set to 0\n");
+                               DP(NETIF_MSG_LINK,
+                                  "bnx2x_ets_E3B0_config BW was set to 0\n");
                        return -EINVAL;
                }
                *total_bw +=
@@ -866,12 +866,12 @@ static int bnx2x_ets_e3b0_get_total_bw(
        /*Check taotl BW is valid */
        if ((100 != *total_bw) || (0 == *total_bw)) {
                if (0 == *total_bw) {
-                       DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config toatl BW"
-                                          "shouldn't be 0\n");
+                       DP(NETIF_MSG_LINK,
+                          "bnx2x_ets_E3B0_config toatl BW shouldn't be 0\n");
                        return -EINVAL;
                }
-               DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config toatl BW should be"
-                                  "100\n");
+               DP(NETIF_MSG_LINK,
+                  "bnx2x_ets_E3B0_config toatl BW should be 100\n");
                /**
                *   We can handle a case whre the BW isn't 100 this can happen
                *   if the TC are joined.
@@ -908,13 +908,13 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
 
        if (DCBX_INVALID_COS != sp_pri_to_cos[pri]) {
                DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
-                                  "parameter There can't be two COS's with"
+                                  "parameter There can't be two COS's with "
                                   "the same strict pri\n");
                return -EINVAL;
        }
 
        if (pri > max_num_of_cos) {
-               DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid"
+               DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
                               "parameter Illegal strict priority\n");
            return -EINVAL;
        }
@@ -1090,8 +1090,8 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
        u8 cos_entry = 0;
 
        if (!CHIP_IS_E3B0(bp)) {
-               DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_disabled the chip isn't E3B0"
-                                  "\n");
+               DP(NETIF_MSG_LINK,
+                  "bnx2x_ets_e3b0_disabled the chip isn't E3B0\n");
                return -EINVAL;
        }
 
@@ -1108,8 +1108,8 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
        bnx2x_status = bnx2x_ets_e3b0_get_total_bw(params, ets_params,
                                                   &total_bw);
        if (0 != bnx2x_status) {
-               DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config get_total_bw failed "
-                                  "\n");
+               DP(NETIF_MSG_LINK,
+                  "bnx2x_ets_E3B0_config get_total_bw failed\n");
                return -EINVAL;
        }
 
@@ -1144,13 +1144,13 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
                                cos_entry);
 
                } else {
-                       DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_config cos state not"
-                                          " valid\n");
+                       DP(NETIF_MSG_LINK,
+                          "bnx2x_ets_e3b0_config cos state not valid\n");
                        return -EINVAL;
                }
                if (0 != bnx2x_status) {
-                       DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_config set cos bw "
-                                          "failed\n");
+                       DP(NETIF_MSG_LINK,
+                          "bnx2x_ets_e3b0_config set cos bw failed\n");
                        return bnx2x_status;
                }
        }
@@ -1160,8 +1160,8 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
                                                         sp_pri_to_cos);
 
        if (0 != bnx2x_status) {
-               DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config set_pri_cli_reg "
-                                  "failed\n");
+               DP(NETIF_MSG_LINK,
+                  "bnx2x_ets_E3B0_config set_pri_cli_reg failed\n");
                return bnx2x_status;
        }
 
@@ -1546,6 +1546,12 @@ static void bnx2x_umac_enable(struct link_params *params,
                               vars->line_speed);
                break;
        }
+       if (!(vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
+               val |= UMAC_COMMAND_CONFIG_REG_IGNORE_TX_PAUSE;
+
+       if (!(vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
+               val |= UMAC_COMMAND_CONFIG_REG_PAUSE_IGNORE;
+
        REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
        udelay(50);
 
@@ -1612,8 +1618,8 @@ static void bnx2x_xmac_init(struct bnx2x *bp, u32 max_speed)
 
        if (is_port4mode && (REG_RD(bp, MISC_REG_RESET_REG_2) &
             MISC_REGISTERS_RESET_REG_2_XMAC)) {
-               DP(NETIF_MSG_LINK, "XMAC already out of reset"
-                                  " in 4-port mode\n");
+               DP(NETIF_MSG_LINK,
+                  "XMAC already out of reset in 4-port mode\n");
                return;
        }
 
@@ -1636,13 +1642,13 @@ static void bnx2x_xmac_init(struct bnx2x *bp, u32 max_speed)
                /*  Set the number of ports on the system side to 1 */
                REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 0);
                if (max_speed == SPEED_10000) {
-                       DP(NETIF_MSG_LINK, "Init XMAC to 10G x 1"
-                                          " port per path\n");
+                       DP(NETIF_MSG_LINK,
+                          "Init XMAC to 10G x 1 port per path\n");
                        /* Set the number of ports on the Warp Core to 10G */
                        REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 3);
                } else {
-                       DP(NETIF_MSG_LINK, "Init XMAC to 20G x 2 ports"
-                                          " per path\n");
+                       DP(NETIF_MSG_LINK,
+                          "Init XMAC to 20G x 2 ports per path\n");
                        /* Set the number of ports on the Warp Core to 20G */
                        REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 1);
                }
@@ -1661,10 +1667,20 @@ static void bnx2x_xmac_disable(struct link_params *params)
 {
        u8 port = params->port;
        struct bnx2x *bp = params->bp;
-       u32 xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+       u32 pfc_ctrl, xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
 
        if (REG_RD(bp, MISC_REG_RESET_REG_2) &
            MISC_REGISTERS_RESET_REG_2_XMAC) {
+               /*
+                * Send an indication to change the state in the NIG back to XON
+                * Clearing this bit enables the next set of this bit to get
+                * rising edge
+                */
+               pfc_ctrl = REG_RD(bp, xmac_base + XMAC_REG_PFC_CTRL_HI);
+               REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI,
+                      (pfc_ctrl & ~(1<<1)));
+               REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI,
+                      (pfc_ctrl | (1<<1)));
                DP(NETIF_MSG_LINK, "Disable XMAC on port %x\n", port);
                REG_WR(bp, xmac_base + XMAC_REG_CTRL, 0);
                usleep_range(1000, 1000);
@@ -1729,6 +1745,10 @@ static int bnx2x_emac_enable(struct link_params *params,
 
        DP(NETIF_MSG_LINK, "enabling EMAC\n");
 
+       /* Disable BMAC */
+       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+              (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+
        /* enable emac and not bmac */
        REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
 
@@ -2583,12 +2603,6 @@ static int bnx2x_bmac1_enable(struct link_params *params,
        REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
                    wb_data, 2);
 
-       if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) {
-               REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LSS_STATUS,
-                           wb_data, 2);
-               if (wb_data[0] > 0)
-                       return -ESRCH;
-       }
        return 0;
 }
 
@@ -2654,16 +2668,6 @@ static int bnx2x_bmac2_enable(struct link_params *params,
        udelay(30);
        bnx2x_update_pfc_bmac2(params, vars, is_lb);
 
-       if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) {
-               REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LSS_STAT,
-                           wb_data, 2);
-               if (wb_data[0] > 0) {
-                       DP(NETIF_MSG_LINK, "Got bad LSS status 0x%x\n",
-                                      wb_data[0]);
-                       return -ESRCH;
-               }
-       }
-
        return 0;
 }
 
@@ -2949,7 +2953,9 @@ static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
        u32 val;
        u16 i;
        int rc = 0;
-
+       if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
+               bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
+                             EMAC_MDIO_STATUS_10MB);
        /* address */
        val = ((phy->addr << 21) | (devad << 16) | reg |
               EMAC_MDIO_COMM_COMMAND_ADDRESS |
@@ -3003,6 +3009,9 @@ static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
                }
        }
 
+       if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
+               bnx2x_bits_dis(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
+                              EMAC_MDIO_STATUS_10MB);
        return rc;
 }
 
@@ -3012,6 +3021,9 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
        u32 tmp;
        u8 i;
        int rc = 0;
+       if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
+               bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
+                             EMAC_MDIO_STATUS_10MB);
 
        /* address */
 
@@ -3065,7 +3077,9 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
                        bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val);
                }
        }
-
+       if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
+               bnx2x_bits_dis(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
+                              EMAC_MDIO_STATUS_10MB);
        return rc;
 }
 
@@ -3945,8 +3959,8 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
                        val16 |= 0x0040;
                        break;
                default:
-                       DP(NETIF_MSG_LINK, "Speed not supported: 0x%x"
-                                          "\n", phy->req_line_speed);
+                       DP(NETIF_MSG_LINK,
+                          "Speed not supported: 0x%x\n", phy->req_line_speed);
                        return;
                }
 
@@ -4078,9 +4092,9 @@ static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
                 */
                if ((cfg_pin < PIN_CFG_GPIO0_P0) ||
                    (cfg_pin > PIN_CFG_GPIO3_P1)) {
-                       DP(NETIF_MSG_LINK, "ERROR: Invalid cfg pin %x for "
-                                          "module detect indication\n",
-                                      cfg_pin);
+                       DP(NETIF_MSG_LINK,
+                          "ERROR: Invalid cfg pin %x for module detect indication\n",
+                          cfg_pin);
                        return -EINVAL;
                }
 
@@ -4208,8 +4222,9 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
                        break;
 
                default:
-                       DP(NETIF_MSG_LINK, "Unsupported Serdes Net Interface "
-                                          "0x%x\n", serdes_net_if);
+                       DP(NETIF_MSG_LINK,
+                          "Unsupported Serdes Net Interface 0x%x\n",
+                          serdes_net_if);
                        return;
                }
        }
@@ -4353,6 +4368,9 @@ void bnx2x_link_status_update(struct link_params *params,
 
        vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
        vars->phy_flags = PHY_XGXS_FLAG;
+       if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
+               vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
+
        if (vars->link_up) {
                DP(NETIF_MSG_LINK, "phy link up\n");
 
@@ -4444,6 +4462,8 @@ void bnx2x_link_status_update(struct link_params *params,
 
                /* indicate no mac active */
                vars->mac_type = MAC_TYPE_NONE;
+               if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
+                       vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
        }
 
        /* Sync media type */
@@ -5903,20 +5923,30 @@ int bnx2x_set_led(struct link_params *params,
                                tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
                                EMAC_WR(bp, EMAC_REG_EMAC_LED,
                                        (tmp | EMAC_LED_OVERRIDE));
-                               return rc;
+                               /*
+                                * return here without enabling traffic
+                                * LED blink andsetting rate in ON mode.
+                                * In oper mode, enabling LED blink
+                                * and setting rate is needed.
+                                */
+                               if (mode == LED_MODE_ON)
+                                       return rc;
                        }
-               } else if (SINGLE_MEDIA_DIRECT(params) &&
-                          (CHIP_IS_E1x(bp) ||
-                           CHIP_IS_E2(bp))) {
+               } else if (SINGLE_MEDIA_DIRECT(params)) {
                        /*
                         * This is a work-around for HW issue found when link
                         * is up in CL73
                         */
-                       REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
                        REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
-               } else {
+                       if (CHIP_IS_E1x(bp) ||
+                           CHIP_IS_E2(bp) ||
+                           (mode == LED_MODE_ON))
+                               REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
+                       else
+                               REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
+                                      hw_led_mode);
+               } else
                        REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
-               }
 
                REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + port*4, 0);
                /* Set blinking rate to ~15.9Hz */
@@ -6098,8 +6128,8 @@ static int bnx2x_link_initialize(struct link_params *params,
                        if (phy_index == EXT_PHY2 &&
                            (bnx2x_phy_selection(params) ==
                             PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) {
-                               DP(NETIF_MSG_LINK, "Not initializing"
-                                               " second phy\n");
+                               DP(NETIF_MSG_LINK,
+                                  "Not initializing second phy\n");
                                continue;
                        }
                        params->phy[phy_index].config_init(
@@ -6160,6 +6190,7 @@ static int bnx2x_update_link_down(struct link_params *params,
        /* update shared memory */
        vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
                               LINK_STATUS_LINK_UP |
+                              LINK_STATUS_PHYSICAL_LINK_FLAG |
                               LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
                               LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
                               LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
@@ -6197,7 +6228,8 @@ static int bnx2x_update_link_up(struct link_params *params,
        u8 port = params->port;
        int rc = 0;
 
-       vars->link_status |= LINK_STATUS_LINK_UP;
+       vars->link_status |= (LINK_STATUS_LINK_UP |
+                             LINK_STATUS_PHYSICAL_LINK_FLAG);
        vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
 
        if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
@@ -6416,8 +6448,8 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
                 */
                if (active_external_phy == EXT_PHY1) {
                        if (params->phy[EXT_PHY2].phy_specific_func) {
-                               DP(NETIF_MSG_LINK, "Disabling TX on"
-                                                  " EXT_PHY2\n");
+                               DP(NETIF_MSG_LINK,
+                                  "Disabling TX on EXT_PHY2\n");
                                params->phy[EXT_PHY2].phy_specific_func(
                                        &params->phy[EXT_PHY2],
                                        params, DISABLE_TX);
@@ -7310,8 +7342,8 @@ static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        u16 val = 0;
        u16 i;
        if (byte_cnt > 16) {
-               DP(NETIF_MSG_LINK, "Reading from eeprom is"
-                           " is limited to 0xf\n");
+               DP(NETIF_MSG_LINK,
+                  "Reading from eeprom is limited to 0xf\n");
                return -EINVAL;
        }
        /* Set the read command byte count */
@@ -7382,8 +7414,8 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
                                        " addr %d, cnt %d\n",
                                        addr, byte_cnt);*/
        if (byte_cnt > 16) {
-               DP(NETIF_MSG_LINK, "Reading from eeprom is"
-                           " is limited to 16 bytes\n");
+               DP(NETIF_MSG_LINK,
+                  "Reading from eeprom is limited to 16 bytes\n");
                return -EINVAL;
        }
 
@@ -7412,8 +7444,8 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        u16 val, i;
 
        if (byte_cnt > 16) {
-               DP(NETIF_MSG_LINK, "Reading from eeprom is"
-                           " is limited to 0xf\n");
+               DP(NETIF_MSG_LINK,
+                  "Reading from eeprom is limited to 0xf\n");
                return -EINVAL;
        }
 
@@ -7560,13 +7592,14 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                        check_limiting_mode = 1;
                } else if (copper_module_type &
                        SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
-                               DP(NETIF_MSG_LINK, "Passive Copper"
-                                           " cable detected\n");
+                               DP(NETIF_MSG_LINK,
+                                  "Passive Copper cable detected\n");
                                *edc_mode =
                                      EDC_MODE_PASSIVE_DAC;
                } else {
-                       DP(NETIF_MSG_LINK, "Unknown copper-cable-"
-                                    "type 0x%x !!!\n", copper_module_type);
+                       DP(NETIF_MSG_LINK,
+                          "Unknown copper-cable-type 0x%x !!!\n",
+                          copper_module_type);
                        return -EINVAL;
                }
                break;
@@ -7604,8 +7637,8 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                                                 SFP_EEPROM_OPTIONS_ADDR,
                                                 SFP_EEPROM_OPTIONS_SIZE,
                                                 options) != 0) {
-                       DP(NETIF_MSG_LINK, "Failed to read Option"
-                               " field from module EEPROM\n");
+                       DP(NETIF_MSG_LINK,
+                          "Failed to read Option field from module EEPROM\n");
                        return -EINVAL;
                }
                if ((options[0] & SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK))
@@ -7646,15 +7679,15 @@ static int bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
                   FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY) {
                /* Use first phy request only in case of non-dual media*/
                if (DUAL_MEDIA(params)) {
-                       DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
-                          "verification\n");
+                       DP(NETIF_MSG_LINK,
+                          "FW does not support OPT MDL verification\n");
                        return -EINVAL;
                }
                cmd = DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL;
        } else {
                /* No support in OPT MDL detection */
-               DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
-                         "verification\n");
+               DP(NETIF_MSG_LINK,
+                  "FW does not support OPT MDL verification\n");
                return -EINVAL;
        }
 
@@ -7705,8 +7738,9 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
        for (timeout = 0; timeout < 60; timeout++) {
                if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
                    == 0) {
-                       DP(NETIF_MSG_LINK, "SFP+ module initialization "
-                                    "took %d ms\n", timeout * 5);
+                       DP(NETIF_MSG_LINK,
+                          "SFP+ module initialization took %d ms\n",
+                          timeout * 5);
                        return 0;
                }
                msleep(5);
@@ -7998,6 +8032,9 @@ static void bnx2x_warpcore_set_limiting_mode(struct link_params *params,
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
                        MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
 
+       /* Restart microcode to re-read the new mode */
+       bnx2x_warpcore_reset_lane(bp, phy, 1);
+       bnx2x_warpcore_reset_lane(bp, phy, 0);
 
 }
 
@@ -8116,7 +8153,6 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
                                 offsetof(struct shmem_region, dev_info.
                                          port_feature_config[params->port].
                                          config));
-
                bnx2x_set_gpio_int(bp, gpio_num,
                                   MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
                                   gpio_port);
@@ -8125,8 +8161,9 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
                 * Disable transmit for this module
                 */
                phy->media_type = ETH_PHY_NOT_PRESENT;
-               if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-                   PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
+               if (((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+                    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) ||
+                   CHIP_IS_E3(bp))
                        bnx2x_sfp_set_transmitter(params, phy, 0);
        }
 }
@@ -8228,9 +8265,6 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
        u16 cnt, val, tmp1;
        struct bnx2x *bp = params->bp;
 
-       /* SPF+ PHY: Set flag to check for Tx error */
-       vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
-
        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
                       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
        /* HW reset */
@@ -8414,9 +8448,6 @@ static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
 
-       /* SPF+ PHY: Set flag to check for Tx error */
-       vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
-
        bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
        bnx2x_wait_reset_complete(bp, phy, params);
 
@@ -8478,8 +8509,8 @@ static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
        /* Set TX PreEmphasis if needed */
        if ((params->feature_config_flags &
             FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
-               DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
-                        "TX_CTRL2 0x%x\n",
+               DP(NETIF_MSG_LINK,
+                  "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
                         phy->tx_preemphasis[0],
                         phy->tx_preemphasis[1]);
                bnx2x_cl45_write(bp, phy,
@@ -8585,9 +8616,6 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
 
-       /* SPF+ PHY: Set flag to check for Tx error */
-       vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
-
        bnx2x_wait_reset_complete(bp, phy, params);
        rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
        /* Should be 0x6 to enable XS on Tx side. */
@@ -8763,8 +8791,8 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
        if (mod_abs & (1<<8)) {
 
                /* Module is absent */
-               DP(NETIF_MSG_LINK, "MOD_ABS indication "
-                           "show module is absent\n");
+               DP(NETIF_MSG_LINK,
+                  "MOD_ABS indication show module is absent\n");
                phy->media_type = ETH_PHY_NOT_PRESENT;
                /*
                 * 1. Set mod_abs to detect next module
@@ -8791,8 +8819,8 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
 
        } else {
                /* Module is present */
-               DP(NETIF_MSG_LINK, "MOD_ABS indication "
-                           "show module is present\n");
+               DP(NETIF_MSG_LINK,
+                  "MOD_ABS indication show module is present\n");
                /*
                 * First disable transmitter, and if the module is ok, the
                 * module_detection will enable it
@@ -8883,8 +8911,9 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
                if ((val1 & (1<<8)) == 0) {
                        if (!CHIP_IS_E1x(bp))
                                oc_port = BP_PATH(bp) + (params->port << 1);
-                       DP(NETIF_MSG_LINK, "8727 Power fault has been detected"
-                                      " on port %d\n", oc_port);
+                       DP(NETIF_MSG_LINK,
+                          "8727 Power fault has been detected on port %d\n",
+                          oc_port);
                        netdev_err(bp->dev, "Error:  Power fault on Port %d has"
                                            " been detected and the power to "
                                            "that SFP+ module has been removed"
@@ -9243,7 +9272,13 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
        if (phy->req_duplex == DUPLEX_FULL)
                autoneg_val |= (1<<8);
 
-       bnx2x_cl45_write(bp, phy,
+       /*
+        * Always write this if this is not 84833.
+        * For 84833, write it only when it's a forced speed.
+        */
+       if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+               ((autoneg_val & (1<<12)) == 0))
+               bnx2x_cl45_write(bp, phy,
                         MDIO_AN_DEVAD,
                         MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val);
 
@@ -9257,13 +9292,12 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
                        bnx2x_cl45_write(bp, phy,
                                 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
                                 0x3200);
-       } else if (phy->req_line_speed != SPEED_10 &&
-                  phy->req_line_speed != SPEED_100) {
+       } else
                bnx2x_cl45_write(bp, phy,
                                 MDIO_AN_DEVAD,
                                 MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
                                 1);
-       }
+
        /* Save spirom version */
        bnx2x_save_848xx_spirom_version(phy, params);
 
@@ -9660,8 +9694,8 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
                                MDIO_AN_REG_8481_EXPANSION_REG_RD_RW,
                                &legacy_status);
 
-               DP(NETIF_MSG_LINK, "Legacy speed status"
-                            " = 0x%x\n", legacy_status);
+               DP(NETIF_MSG_LINK, "Legacy speed status = 0x%x\n",
+                  legacy_status);
                link_up = ((legacy_status & (1<<11)) == (1<<11));
                if (link_up) {
                        legacy_speed = (legacy_status & (3<<9));
@@ -9679,9 +9713,10 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
                        else
                                vars->duplex = DUPLEX_HALF;
 
-                       DP(NETIF_MSG_LINK, "Link is up in %dMbps,"
-                                  " is_duplex_full= %d\n", vars->line_speed,
-                                  (vars->duplex == DUPLEX_FULL));
+                       DP(NETIF_MSG_LINK,
+                          "Link is up in %dMbps, is_duplex_full= %d\n",
+                          vars->line_speed,
+                          (vars->duplex == DUPLEX_FULL));
                        /* Check legacy speed AN resolution */
                        bnx2x_cl45_read(bp, phy,
                                        MDIO_AN_DEVAD,
@@ -9756,11 +9791,9 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
                bnx2x_cl45_read(bp, phy,
                                MDIO_CTL_DEVAD,
                                0x400f, &val16);
-               /* Put to low power mode on newer FW */
-               if ((val16 & 0x303f) > 0x1009)
-                       bnx2x_cl45_write(bp, phy,
-                                       MDIO_PMA_DEVAD,
-                                       MDIO_PMA_REG_CTRL, 0x800);
+               bnx2x_cl45_write(bp, phy,
+                               MDIO_PMA_DEVAD,
+                               MDIO_PMA_REG_CTRL, 0x800);
        }
 }
 
@@ -10191,8 +10224,15 @@ static void bnx2x_54618se_link_reset(struct bnx2x_phy *phy,
        u32 cfg_pin;
        u8 port;
 
-       /* This works with E3 only, no need to check the chip
-          before determining the port. */
+       /*
+        * In case of no EPIO routed to reset the GPHY, put it
+        * in low power mode.
+        */
+       bnx2x_cl22_write(bp, phy, MDIO_PMA_REG_CTRL, 0x800);
+       /*
+        * This works with E3 only, no need to check the chip
+        * before determining the port.
+        */
        port = params->port;
        cfg_pin = (REG_RD(bp, params->shmem_base +
                        offsetof(struct shmem_region,
@@ -10251,9 +10291,10 @@ static u8 bnx2x_54618se_read_status(struct bnx2x_phy *phy,
                } else /* Should not happen */
                        vars->line_speed = 0;
 
-               DP(NETIF_MSG_LINK, "Link is up in %dMbps,"
-                          " is_duplex_full= %d\n", vars->line_speed,
-                          (vars->duplex == DUPLEX_FULL));
+               DP(NETIF_MSG_LINK,
+                  "Link is up in %dMbps, is_duplex_full= %d\n",
+                  vars->line_speed,
+                  (vars->duplex == DUPLEX_FULL));
 
                /* Check legacy speed AN resolution */
                bnx2x_cl22_read(bp, phy,
@@ -10603,7 +10644,8 @@ static struct bnx2x_phy phy_warpcore = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
        .addr           = 0xff,
        .def_md_devad   = 0,
-       .flags          = FLAGS_HW_LOCK_REQUIRED,
+       .flags          = (FLAGS_HW_LOCK_REQUIRED |
+                          FLAGS_TX_ERROR_CHECK),
        .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .mdio_ctrl      = 0,
@@ -10729,7 +10771,8 @@ static struct bnx2x_phy phy_8706 = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
        .addr           = 0xff,
        .def_md_devad   = 0,
-       .flags          = FLAGS_INIT_XGXS_FIRST,
+       .flags          = (FLAGS_INIT_XGXS_FIRST |
+                          FLAGS_TX_ERROR_CHECK),
        .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .mdio_ctrl      = 0,
@@ -10760,7 +10803,8 @@ static struct bnx2x_phy phy_8726 = {
        .addr           = 0xff,
        .def_md_devad   = 0,
        .flags          = (FLAGS_HW_LOCK_REQUIRED |
-                          FLAGS_INIT_XGXS_FIRST),
+                          FLAGS_INIT_XGXS_FIRST |
+                          FLAGS_TX_ERROR_CHECK),
        .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .mdio_ctrl      = 0,
@@ -10791,7 +10835,8 @@ static struct bnx2x_phy phy_8727 = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
        .addr           = 0xff,
        .def_md_devad   = 0,
-       .flags          = FLAGS_FAN_FAILURE_DET_REQ,
+       .flags          = (FLAGS_FAN_FAILURE_DET_REQ |
+                          FLAGS_TX_ERROR_CHECK),
        .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .mdio_ctrl      = 0,
@@ -11112,6 +11157,8 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
                 */
                if (CHIP_REV(bp) == CHIP_REV_Ax)
                        phy->flags |= FLAGS_MDC_MDIO_WA;
+               else
+                       phy->flags |= FLAGS_MDC_MDIO_WA_B0;
        } else {
                switch (switch_cfg) {
                case SWITCH_CFG_1G:
@@ -11195,6 +11242,7 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
                *phy = phy_84833;
                break;
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616:
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE:
                *phy = phy_54618se;
                break;
@@ -11295,8 +11343,9 @@ static void bnx2x_phy_def_cfg(struct link_params *params,
                                                      dev_info.
                        port_hw_config[params->port].speed_capability_mask));
        }
-       DP(NETIF_MSG_LINK, "Default config phy idx %x cfg 0x%x speed_cap_mask"
-                      " 0x%x\n", phy_index, link_config, phy->speed_cap_mask);
+       DP(NETIF_MSG_LINK,
+          "Default config phy idx %x cfg 0x%x speed_cap_mask 0x%x\n",
+          phy_index, link_config, phy->speed_cap_mask);
 
        phy->req_duplex = DUPLEX_FULL;
        switch (link_config  & PORT_FEATURE_LINK_SPEED_MASK) {
@@ -11500,13 +11549,12 @@ void bnx2x_init_xmac_loopback(struct link_params *params,
         * Set WC to loopback mode since link is required to provide clock
         * to the XMAC in 20G mode
         */
-       if (vars->line_speed == SPEED_20000) {
-               bnx2x_set_aer_mmd(params, &params->phy[0]);
-               bnx2x_warpcore_reset_lane(bp, &params->phy[0], 0);
-               params->phy[INT_PHY].config_loopback(
+       bnx2x_set_aer_mmd(params, &params->phy[0]);
+       bnx2x_warpcore_reset_lane(bp, &params->phy[0], 0);
+       params->phy[INT_PHY].config_loopback(
                        &params->phy[INT_PHY],
                        params);
-       }
+
        bnx2x_xmac_enable(params, vars, 1);
        REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 }
@@ -11684,12 +11732,16 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
        bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
 
        if (reset_ext_phy) {
+               bnx2x_set_mdio_clk(bp, params->chip_id, port);
                for (phy_index = EXT_PHY1; phy_index < params->num_phys;
                      phy_index++) {
-                       if (params->phy[phy_index].link_reset)
+                       if (params->phy[phy_index].link_reset) {
+                               bnx2x_set_aer_mmd(params,
+                                                 &params->phy[phy_index]);
                                params->phy[phy_index].link_reset(
                                        &params->phy[phy_index],
                                        params);
+                       }
                        if (params->phy[phy_index].flags &
                            FLAGS_REARM_LATCH_SIGNAL)
                                clear_latch_ind = 1;
@@ -12178,10 +12230,6 @@ static void bnx2x_analyze_link_error(struct link_params *params,
        u8 led_mode;
        u32 half_open_conn = (vars->phy_flags & PHY_HALF_OPEN_CONN_FLAG) > 0;
 
-       /*DP(NETIF_MSG_LINK, "CHECK LINK: %x half_open:%x-> lss:%x\n",
-                      vars->link_up,
-                      half_open_conn, lss_status);*/
-
        if ((lss_status ^ half_open_conn) == 0)
                return;
 
@@ -12194,6 +12242,7 @@ static void bnx2x_analyze_link_error(struct link_params *params,
         * b. Update link_vars->link_up
         */
        if (lss_status) {
+               DP(NETIF_MSG_LINK, "Remote Fault detected !!!\n");
                vars->link_status &= ~LINK_STATUS_LINK_UP;
                vars->link_up = 0;
                vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
@@ -12203,6 +12252,7 @@ static void bnx2x_analyze_link_error(struct link_params *params,
                 */
                led_mode = LED_MODE_OFF;
        } else {
+               DP(NETIF_MSG_LINK, "Remote Fault cleared\n");
                vars->link_status |= LINK_STATUS_LINK_UP;
                vars->link_up = 1;
                vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
@@ -12219,6 +12269,15 @@ static void bnx2x_analyze_link_error(struct link_params *params,
        bnx2x_notify_link_changed(bp);
 }
 
+/******************************************************************************
+* Description:
+*      This function checks for half opened connection change indication.
+*      When such change occurs, it calls the bnx2x_analyze_link_error
+*      to check if Remote Fault is set or cleared. Reception of remote fault
+*      status message in the MAC indicates that the peer's MAC has detected
+*      a fault, for example, due to break in the TX side of fiber.
+*
+******************************************************************************/
 static void bnx2x_check_half_open_conn(struct link_params *params,
                                       struct link_vars *vars)
 {
@@ -12229,9 +12288,28 @@ static void bnx2x_check_half_open_conn(struct link_params *params,
        if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
                return;
 
-       if (!CHIP_IS_E3(bp) &&
+       if (CHIP_IS_E3(bp) &&
            (REG_RD(bp, MISC_REG_RESET_REG_2) &
-                  (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))) {
+             (MISC_REGISTERS_RESET_REG_2_XMAC))) {
+               /* Check E3 XMAC */
+               /*
+                * Note that link speed cannot be queried here, since it may be
+                * zero while link is down. In case UMAC is active, LSS will
+                * simply not be set
+                */
+               mac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+
+               /* Clear stick bits (Requires rising edge) */
+               REG_WR(bp, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0);
+               REG_WR(bp, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS,
+                      XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS |
+                      XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS);
+               if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS))
+                       lss_status = 1;
+
+               bnx2x_analyze_link_error(params, vars, lss_status);
+       } else if (REG_RD(bp, MISC_REG_RESET_REG_2) &
+                  (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) {
                /* Check E1X / E2 BMAC */
                u32 lss_status_reg;
                u32 wb_data[2];
@@ -12253,14 +12331,20 @@ static void bnx2x_check_half_open_conn(struct link_params *params,
 void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
+       u16 phy_idx;
        if (!params) {
-               DP(NETIF_MSG_LINK, "Ininitliazed params !\n");
+               DP(NETIF_MSG_LINK, "Uninitialized params !\n");
                return;
        }
-       /* DP(NETIF_MSG_LINK, "Periodic called vars->phy_flags 0x%x speed 0x%x
-        RESET_REG_2 0x%x\n", vars->phy_flags, vars->line_speed,
-         REG_RD(bp, MISC_REG_RESET_REG_2)); */
-       bnx2x_check_half_open_conn(params, vars);
+
+       for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
+               if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
+                       bnx2x_set_aer_mmd(params, &params->phy[phy_idx]);
+                       bnx2x_check_half_open_conn(params, vars);
+                       break;
+               }
+       }
+
        if (CHIP_IS_E3(bp))
                bnx2x_check_over_curr(params, vars);
 }
similarity index 99%
rename from drivers/net/bnx2x/bnx2x_link.h
rename to drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
index 6a7708d..c12db6d 100644 (file)
@@ -145,6 +145,8 @@ struct bnx2x_phy {
 #define FLAGS_SFP_NOT_APPROVED         (1<<7)
 #define FLAGS_MDC_MDIO_WA              (1<<8)
 #define FLAGS_DUMMY_READ               (1<<9)
+#define FLAGS_MDC_MDIO_WA_B0           (1<<10)
+#define FLAGS_TX_ERROR_CHECK           (1<<12)
 
        /* preemphasis values for the rx side */
        u16 rx_preemphasis[4];
@@ -276,7 +278,6 @@ struct link_vars {
 #define PHY_PHYSICAL_LINK_FLAG         (1<<2)
 #define PHY_HALF_OPEN_CONN_FLAG                (1<<3)
 #define PHY_OVER_CURRENT_FLAG          (1<<4)
-#define PHY_TX_ERROR_CHECK_FLAG                (1<<5)
 
        u8 mac_type;
 #define MAC_TYPE_NONE          0
similarity index 99%
rename from drivers/net/bnx2x/bnx2x_main.c
rename to drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 1507091..85dd294 100644 (file)
@@ -15,6 +15,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
@@ -37,6 +39,7 @@
 #include <linux/time.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
+#include <linux/if.h>
 #include <linux/if_vlan.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
@@ -350,17 +353,15 @@ static void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae,
        default:
                if (src_type == DMAE_CMD_SRC_PCI)
                        DP(msglvl, "DMAE: opcode 0x%08x\n"
-                          DP_LEVEL "src_addr [%x:%08x]  len [%d * 4]  "
-                                   "dst_addr [none]\n"
-                          DP_LEVEL "comp_addr [%x:%08x]  comp_val 0x%08x\n",
+                          "src_addr [%x:%08x]  len [%d * 4]  dst_addr [none]\n"
+                          "comp_addr [%x:%08x]  comp_val 0x%08x\n",
                           dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
                           dmae->len, dmae->comp_addr_hi, dmae->comp_addr_lo,
                           dmae->comp_val);
                else
                        DP(msglvl, "DMAE: opcode 0x%08x\n"
-                          DP_LEVEL "src_addr [%08x]  len [%d * 4]  "
-                                   "dst_addr [none]\n"
-                          DP_LEVEL "comp_addr [%x:%08x]  comp_val 0x%08x\n",
+                          "src_addr [%08x]  len [%d * 4]  dst_addr [none]\n"
+                          "comp_addr [%x:%08x]  comp_val 0x%08x\n",
                           dmae->opcode, dmae->src_addr_lo >> 2,
                           dmae->len, dmae->comp_addr_hi, dmae->comp_addr_lo,
                           dmae->comp_val);
@@ -789,18 +790,15 @@ void bnx2x_panic_dump(struct bnx2x *bp)
        BNX2X_ERR("     def (");
        for (i = 0; i < HC_SP_SB_MAX_INDICES; i++)
                pr_cont("0x%x%s",
-                      bp->def_status_blk->sp_sb.index_values[i],
-                      (i == HC_SP_SB_MAX_INDICES - 1) ? ")  " : " ");
+                       bp->def_status_blk->sp_sb.index_values[i],
+                       (i == HC_SP_SB_MAX_INDICES - 1) ? ")  " : " ");
 
        for (i = 0; i < sizeof(struct hc_sp_status_block_data)/sizeof(u32); i++)
                *((u32 *)&sp_sb_data + i) = REG_RD(bp, BAR_CSTRORM_INTMEM +
                        CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
                        i*sizeof(u32));
 
-       pr_cont("igu_sb_id(0x%x)  igu_seg_id(0x%x) "
-                        "pf_id(0x%x)  vnic_id(0x%x)  "
-                        "vf_id(0x%x)  vf_valid (0x%x) "
-                        "state(0x%x)\n",
+       pr_cont("igu_sb_id(0x%x)  igu_seg_id(0x%x) pf_id(0x%x)  vnic_id(0x%x)  vf_id(0x%x)  vf_valid (0x%x) state(0x%x)\n",
               sp_sb_data.igu_sb_id,
               sp_sb_data.igu_seg_id,
               sp_sb_data.p_func.pf_id,
@@ -3721,9 +3719,7 @@ static inline void bnx2x_clear_load_cnt(struct bnx2x *bp)
 
 static inline void _print_next_block(int idx, const char *blk)
 {
-       if (idx)
-               pr_cont(", ");
-       pr_cont("%s", blk);
+       pr_cont("%s%s", idx ? ", " : "", blk);
 }
 
 static inline int bnx2x_check_blocks_with_parity0(u32 sig, int par_num,
@@ -4388,7 +4384,7 @@ static inline void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
 static inline struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj(
        struct bnx2x *bp, u32 cid)
 {
-       DP(BNX2X_MSG_SP, "retrieving fp from cid %d", cid);
+       DP(BNX2X_MSG_SP, "retrieving fp from cid %d\n", cid);
 #ifdef BCM_CNIC
        if (cid == BNX2X_FCOE_ETH_CID)
                return &bnx2x_fcoe(bp, q_obj);
@@ -5798,6 +5794,12 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
 
        DP(BNX2X_MSG_MCP, "starting common init  func %d\n", BP_ABS_FUNC(bp));
 
+       /*
+        * take the UNDI lock to protect undi_unload flow from accessing
+        * registers while we're resetting the chip
+        */
+       bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
+
        bnx2x_reset_common(bp);
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff);
 
@@ -5808,6 +5810,8 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
        }
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, val);
 
+       bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
+
        bnx2x_init_block(bp, BLOCK_MISC, PHASE_COMMON);
 
        if (!CHIP_IS_E1x(bp)) {
@@ -7176,7 +7180,7 @@ static inline void bnx2x_pf_q_prep_init(struct bnx2x *bp,
        /* set maximum number of COSs supported by this queue */
        init_params->max_cos = fp->max_cos;
 
-       DP(BNX2X_MSG_SP, "fp: %d setting queue params max cos to: %d",
+       DP(BNX2X_MSG_SP, "fp: %d setting queue params max cos to: %d\n",
            fp->index, init_params->max_cos);
 
        /* set the context pointers queue object */
@@ -7209,7 +7213,7 @@ int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 
        DP(BNX2X_MSG_SP, "preparing to send tx-only ramrod for connection:"
                         "cos %d, primary cid %d, cid %d, "
-                        "client id %d, sp-client id %d, flags %lx",
+                        "client id %d, sp-client id %d, flags %lx\n",
           tx_index, q_params->q_obj->cids[FIRST_TX_COS_INDEX],
           q_params->q_obj->cids[tx_index], q_params->q_obj->cl_id,
           tx_only_params->gen_params.spcl_id, tx_only_params->flags);
@@ -7241,7 +7245,7 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
        int rc;
        u8 tx_index;
 
-       DP(BNX2X_MSG_SP, "setting up queue %d", fp->index);
+       DP(BNX2X_MSG_SP, "setting up queue %d\n", fp->index);
 
        /* reset IGU state skip FCoE L2 queue */
        if (!IS_FCOE_FP(fp))
@@ -7265,7 +7269,7 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                return rc;
        }
 
-       DP(BNX2X_MSG_SP, "init complete");
+       DP(BNX2X_MSG_SP, "init complete\n");
 
 
        /* Now move the Queue to the SETUP state... */
@@ -7319,7 +7323,7 @@ static int bnx2x_stop_queue(struct bnx2x *bp, int index)
        struct bnx2x_queue_state_params q_params = {0};
        int rc, tx_index;
 
-       DP(BNX2X_MSG_SP, "stopping queue %d cid %d", index, fp->cid);
+       DP(BNX2X_MSG_SP, "stopping queue %d cid %d\n", index, fp->cid);
 
        q_params.q_obj = &fp->q_obj;
        /* We want to wait for completion in this context */
@@ -7334,7 +7338,7 @@ static int bnx2x_stop_queue(struct bnx2x *bp, int index)
                /* ascertain this is a normal queue*/
                txdata = &fp->txdata[tx_index];
 
-               DP(BNX2X_MSG_SP, "stopping tx-only queue %d",
+               DP(BNX2X_MSG_SP, "stopping tx-only queue %d\n",
                                                        txdata->txq_index);
 
                /* send halt terminate on tx-only connection */
@@ -9315,9 +9319,8 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
                                val = MF_CFG_RD(bp, func_ext_config[func].
                                                    iscsi_mac_addr_lower);
                                bnx2x_set_mac_buf(iscsi_mac, val, val2);
-                               BNX2X_DEV_INFO("Read iSCSI MAC: "
-                                              BNX2X_MAC_FMT"\n",
-                                              BNX2X_MAC_PRN_LIST(iscsi_mac));
+                               BNX2X_DEV_INFO("Read iSCSI MAC: %pM\n",
+                                              iscsi_mac);
                        } else
                                bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
 
@@ -9327,9 +9330,8 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
                                val = MF_CFG_RD(bp, func_ext_config[func].
                                                    fcoe_mac_addr_lower);
                                bnx2x_set_mac_buf(fip_mac, val, val2);
-                               BNX2X_DEV_INFO("Read FCoE L2 MAC to "
-                                              BNX2X_MAC_FMT"\n",
-                                              BNX2X_MAC_PRN_LIST(fip_mac));
+                               BNX2X_DEV_INFO("Read FCoE L2 MAC to %pM\n",
+                                              fip_mac);
 
                        } else
                                bp->flags |= NO_FCOE_FLAG;
@@ -9384,9 +9386,9 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
        if (!is_valid_ether_addr(bp->dev->dev_addr))
                dev_err(&bp->pdev->dev,
                        "bad Ethernet MAC address configuration: "
-                       BNX2X_MAC_FMT", change it manually before bringing up "
+                       "%pM, change it manually before bringing up "
                        "the appropriate network interface\n",
-                       BNX2X_MAC_PRN_LIST(bp->dev->dev_addr));
+                       bp->dev->dev_addr);
 }
 
 static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
@@ -10251,10 +10253,17 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
        /* clean indirect addresses */
        pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS,
                               PCICFG_VENDOR_ID_OFFSET);
-       REG_WR(bp, PXP2_REG_PGL_ADDR_88_F0 + BP_PORT(bp)*16, 0);
-       REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F0 + BP_PORT(bp)*16, 0);
-       REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0 + BP_PORT(bp)*16, 0);
-       REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0 + BP_PORT(bp)*16, 0);
+       /* Clean the following indirect addresses for all functions since it
+        * is not used by the driver.
+        */
+       REG_WR(bp, PXP2_REG_PGL_ADDR_88_F0, 0);
+       REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F0, 0);
+       REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0, 0);
+       REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0, 0);
+       REG_WR(bp, PXP2_REG_PGL_ADDR_88_F1, 0);
+       REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F1, 0);
+       REG_WR(bp, PXP2_REG_PGL_ADDR_90_F1, 0);
+       REG_WR(bp, PXP2_REG_PGL_ADDR_94_F1, 0);
 
        /*
         * Enable internal target-read (in case we are probed after PF FLR).
@@ -10273,9 +10282,11 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
        dev->netdev_ops = &bnx2x_netdev_ops;
        bnx2x_set_ethtool_ops(dev);
 
+       dev->priv_flags |= IFF_UNICAST_FLT;
+
        dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-               NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
-               NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_HW_VLAN_TX;
+               NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_LRO |
+               NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_HW_VLAN_TX;
 
        dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA;
@@ -10706,7 +10717,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
                return rc;
        }
 
-       DP(NETIF_MSG_DRV, "max_non_def_sbs %d", max_non_def_sbs);
+       DP(NETIF_MSG_DRV, "max_non_def_sbs %d\n", max_non_def_sbs);
 
        rc = bnx2x_init_bp(bp);
        if (rc)
@@ -10761,15 +10772,14 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 
        bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
 
-       netdev_info(dev, "%s (%c%d) PCI-E x%d %s found at mem %lx,"
-              " IRQ %d, ", board_info[ent->driver_data].name,
-              (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
-              pcie_width,
-              ((!CHIP_IS_E2(bp) && pcie_speed == 2) ||
-                (CHIP_IS_E2(bp) && pcie_speed == 1)) ?
-                                               "5GHz (Gen2)" : "2.5GHz",
-              dev->base_addr, bp->pdev->irq);
-       pr_cont("node addr %pM\n", dev->dev_addr);
+       netdev_info(dev, "%s (%c%d) PCI-E x%d %s found at mem %lx, IRQ %d, node addr %pM\n",
+                   board_info[ent->driver_data].name,
+                   (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
+                   pcie_width,
+                   ((!CHIP_IS_E2(bp) && pcie_speed == 2) ||
+                    (CHIP_IS_E2(bp) && pcie_speed == 1)) ?
+                   "5GHz (Gen2)" : "2.5GHz",
+                   dev->base_addr, bp->pdev->irq, dev->dev_addr);
 
        return 0;
 
similarity index 99%
rename from drivers/net/bnx2x/bnx2x_reg.h
rename to drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index 02461fe..40266c1 100644 (file)
 /* [R 6] Debug only: Number of used entries in the data FIFO */
 #define PXP2_REG_HST_DATA_FIFO_STATUS                           0x12047c
 /* [R 7] Debug only: Number of used entries in the header FIFO */
-#define PXP2_REG_HST_HEADER_FIFO_STATUS                         0x120478
-#define PXP2_REG_PGL_ADDR_88_F0                                 0x120534
-#define PXP2_REG_PGL_ADDR_8C_F0                                 0x120538
-#define PXP2_REG_PGL_ADDR_90_F0                                 0x12053c
-#define PXP2_REG_PGL_ADDR_94_F0                                 0x120540
+#define PXP2_REG_HST_HEADER_FIFO_STATUS                                 0x120478
+#define PXP2_REG_PGL_ADDR_88_F0                                         0x120534
+/* [R 32] GRC address for configuration access to PCIE config address 0x88.
+ * any write to this PCIE address will cause a GRC write access to the
+ * address that's in t this register */
+#define PXP2_REG_PGL_ADDR_88_F1                                         0x120544
+#define PXP2_REG_PGL_ADDR_8C_F0                                         0x120538
+/* [R 32] GRC address for configuration access to PCIE config address 0x8c.
+ * any write to this PCIE address will cause a GRC write access to the
+ * address that's in t this register */
+#define PXP2_REG_PGL_ADDR_8C_F1                                         0x120548
+#define PXP2_REG_PGL_ADDR_90_F0                                         0x12053c
+/* [R 32] GRC address for configuration access to PCIE config address 0x90.
+ * any write to this PCIE address will cause a GRC write access to the
+ * address that's in t this register */
+#define PXP2_REG_PGL_ADDR_90_F1                                         0x12054c
+#define PXP2_REG_PGL_ADDR_94_F0                                         0x120540
+/* [R 32] GRC address for configuration access to PCIE config address 0x94.
+ * any write to this PCIE address will cause a GRC write access to the
+ * address that's in t this register */
+#define PXP2_REG_PGL_ADDR_94_F1                                         0x120550
 #define PXP2_REG_PGL_CONTROL0                                   0x120490
 #define PXP2_REG_PGL_CONTROL1                                   0x120514
 #define PXP2_REG_PGL_DEBUG                                      0x120520
    The fields are: [4:0] - tail pointer; 10:5] - Link List size; 15:11] -
    header pointer. */
 #define UCM_REG_XX_TABLE                                        0xe0300
+#define UMAC_COMMAND_CONFIG_REG_IGNORE_TX_PAUSE                         (0x1<<28)
 #define UMAC_COMMAND_CONFIG_REG_LOOP_ENA                        (0x1<<15)
 #define UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK                   (0x1<<24)
 #define UMAC_COMMAND_CONFIG_REG_PAD_EN                          (0x1<<5)
+#define UMAC_COMMAND_CONFIG_REG_PAUSE_IGNORE                    (0x1<<8)
 #define UMAC_COMMAND_CONFIG_REG_PROMIS_EN                       (0x1<<4)
 #define UMAC_COMMAND_CONFIG_REG_RX_ENA                          (0x1<<1)
 #define UMAC_COMMAND_CONFIG_REG_SW_RESET                        (0x1<<13)
 #define EMAC_MDIO_COMM_START_BUSY                               (1L<<29)
 #define EMAC_MDIO_MODE_AUTO_POLL                                (1L<<4)
 #define EMAC_MDIO_MODE_CLAUSE_45                                (1L<<31)
-#define EMAC_MDIO_MODE_CLOCK_CNT                                (0x3fL<<16)
+#define EMAC_MDIO_MODE_CLOCK_CNT                                (0x3ffL<<16)
 #define EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT                       16
+#define EMAC_MDIO_STATUS_10MB                                   (1L<<1)
 #define EMAC_MODE_25G_MODE                                      (1L<<5)
 #define EMAC_MODE_HALF_DUPLEX                                   (1L<<1)
 #define EMAC_MODE_PORT_GMII                                     (2L<<2)
 #define EMAC_REG_EMAC_MAC_MATCH                                 0x10
 #define EMAC_REG_EMAC_MDIO_COMM                                 0xac
 #define EMAC_REG_EMAC_MDIO_MODE                                 0xb4
+#define EMAC_REG_EMAC_MDIO_STATUS                               0xb0
 #define EMAC_REG_EMAC_MODE                                      0x0
 #define EMAC_REG_EMAC_RX_MODE                                   0xc8
 #define EMAC_REG_EMAC_RX_MTU_SIZE                               0x9c
similarity index 98%
rename from drivers/net/bnx2x/bnx2x_sp.c
rename to drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index df52f11..0440425 100644 (file)
@@ -16,6 +16,9 @@
  * Written by: Vladislav Zolotarov
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/crc32.h>
 #include <linux/netdevice.h>
@@ -707,9 +710,8 @@ static void bnx2x_set_one_mac_e2(struct bnx2x *bp,
        bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_MAC,
                                      &rule_entry->mac.header);
 
-       DP(BNX2X_MSG_SP, "About to %s MAC "BNX2X_MAC_FMT" for "
-                        "Queue %d\n", (add ? "add" : "delete"),
-                        BNX2X_MAC_PRN_LIST(mac), raw->cl_id);
+       DP(BNX2X_MSG_SP, "About to %s MAC %pM for Queue %d\n",
+                        add ? "add" : "delete", mac, raw->cl_id);
 
        /* Set a MAC itself */
        bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
@@ -801,9 +803,9 @@ static inline void bnx2x_vlan_mac_set_rdata_e1x(struct bnx2x *bp,
        bnx2x_vlan_mac_set_cfg_entry_e1x(bp, o, add, opcode, mac, vlan_id,
                                         cfg_entry);
 
-       DP(BNX2X_MSG_SP, "%s MAC "BNX2X_MAC_FMT" CLID %d CAM offset %d\n",
-                        (add ? "setting" : "clearing"),
-                        BNX2X_MAC_PRN_LIST(mac), raw->cl_id, cam_offset);
+       DP(BNX2X_MSG_SP, "%s MAC %pM CLID %d CAM offset %d\n",
+                        add ? "setting" : "clearing",
+                        mac, raw->cl_id, cam_offset);
 }
 
 /**
@@ -2579,9 +2581,8 @@ static inline void bnx2x_mcast_hdl_pending_add_e2(struct bnx2x *bp,
 
                cnt++;
 
-               DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
-                                " mcast MAC\n",
-                                BNX2X_MAC_PRN_LIST(pmac_pos->mac));
+               DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
+                                pmac_pos->mac);
 
                list_del(&pmac_pos->link);
 
@@ -2702,9 +2703,8 @@ static inline void bnx2x_mcast_hdl_add(struct bnx2x *bp,
 
                cnt++;
 
-               DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
-                                " mcast MAC\n",
-                                BNX2X_MAC_PRN_LIST(mlist_pos->mac));
+               DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
+                                mlist_pos->mac);
        }
 
        *line_idx = cnt;
@@ -2998,9 +2998,8 @@ static inline void bnx2x_mcast_hdl_add_e1h(struct bnx2x *bp,
                bit = bnx2x_mcast_bin_from_mac(mlist_pos->mac);
                BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
 
-               DP(BNX2X_MSG_SP, "About to configure "
-                                BNX2X_MAC_FMT" mcast MAC, bin %d\n",
-                                BNX2X_MAC_PRN_LIST(mlist_pos->mac), bit);
+               DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC, bin %d\n",
+                                mlist_pos->mac, bit);
 
                /* bookkeeping... */
                BIT_VEC64_SET_BIT(o->registry.aprox_match.vec,
@@ -3049,8 +3048,8 @@ static int bnx2x_mcast_setup_e1h(struct bnx2x *bp,
                        break;
 
                case BNX2X_MCAST_CMD_DEL:
-                       DP(BNX2X_MSG_SP, "Invalidating multicast "
-                                        "MACs configuration\n");
+                       DP(BNX2X_MSG_SP,
+                          "Invalidating multicast MACs configuration\n");
 
                        /* clear the registry */
                        memset(o->registry.aprox_match.vec, 0,
@@ -3233,9 +3232,8 @@ static inline int bnx2x_mcast_handle_restore_cmd_e1(
 
                i++;
 
-                 DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
-                                  " mcast MAC\n",
-                                  BNX2X_MAC_PRN_LIST(cfg_data.mac));
+                 DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
+                                  cfg_data.mac);
        }
 
        *rdata_idx = i;
@@ -3270,9 +3268,8 @@ static inline int bnx2x_mcast_handle_pending_cmds_e1(
 
                        cnt++;
 
-                       DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
-                                        " mcast MAC\n",
-                                        BNX2X_MAC_PRN_LIST(pmac_pos->mac));
+                       DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
+                                        pmac_pos->mac);
                }
                break;
 
@@ -3357,9 +3354,8 @@ static inline int bnx2x_mcast_refresh_registry_e1(struct bnx2x *bp,
                                &data->config_table[i].middle_mac_addr,
                                &data->config_table[i].lsb_mac_addr,
                                elem->mac);
-                       DP(BNX2X_MSG_SP, "Adding registry entry for ["
-                                        BNX2X_MAC_FMT"]\n",
-                                  BNX2X_MAC_PRN_LIST(elem->mac));
+                       DP(BNX2X_MSG_SP, "Adding registry entry for [%pM]\n",
+                                        elem->mac);
                        list_add_tail(&elem->link,
                                      &o->registry.exact_match.macs);
                }
@@ -4246,7 +4242,7 @@ static int bnx2x_queue_comp_cmd(struct bnx2x *bp,
                         o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_state);
 
        if (o->next_tx_only)  /* print num tx-only if any exist */
-               DP(BNX2X_MSG_SP, "primary cid %d: num tx-only cons %d",
+               DP(BNX2X_MSG_SP, "primary cid %d: num tx-only cons %d\n",
                           o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_tx_only);
 
        o->state = o->next_state;
@@ -4308,7 +4304,7 @@ static void bnx2x_q_fill_init_general_data(struct bnx2x *bp,
                test_bit(BNX2X_Q_FLG_FCOE, flags) ?
                LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
 
-       DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d",
+       DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d\n",
           gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg);
 }
 
@@ -4461,7 +4457,7 @@ static void bnx2x_q_fill_setup_tx_only(struct bnx2x *bp,
                                  &data->tx,
                                  &cmd_params->params.tx_only.flags);
 
-       DP(BNX2X_MSG_SP, "cid %d, tx bd page lo %x hi %x",cmd_params->q_obj->cids[0],
+       DP(BNX2X_MSG_SP, "cid %d, tx bd page lo %x hi %x\n",cmd_params->q_obj->cids[0],
           data->tx.tx_bd_page_base.lo, data->tx.tx_bd_page_base.hi);
 }
 
@@ -4508,9 +4504,9 @@ static inline int bnx2x_q_init(struct bnx2x *bp,
 
        /* Set CDU context validation values */
        for (cos = 0; cos < o->max_cos; cos++) {
-               DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d",
+               DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d\n",
                                 o->cids[cos], cos);
-               DP(BNX2X_MSG_SP, "context pointer %p", init->cxts[cos]);
+               DP(BNX2X_MSG_SP, "context pointer %p\n", init->cxts[cos]);
                bnx2x_set_ctx_validation(bp, init->cxts[cos], o->cids[cos]);
        }
 
@@ -4599,7 +4595,7 @@ static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
                return -EINVAL;
        }
 
-       DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d",
+       DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d\n",
                         tx_only_params->gen_params.cos,
                         tx_only_params->gen_params.spcl_id);
 
@@ -4610,7 +4606,7 @@ static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
        bnx2x_q_fill_setup_tx_only(bp, params, rdata);
 
        DP(BNX2X_MSG_SP, "sending tx-only ramrod: cid %d, client-id %d,"
-                        "sp-client id %d, cos %d",
+                        "sp-client id %d, cos %d\n",
                         o->cids[cid_index],
                         rdata->general.client_id,
                         rdata->general.sp_client_id, rdata->general.cos);
@@ -5167,8 +5163,9 @@ static inline int bnx2x_func_state_change_comp(struct bnx2x *bp,
                return -EINVAL;
        }
 
-       DP(BNX2X_MSG_SP, "Completing command %d for func %d, setting state to "
-                        "%d\n", cmd, BP_FUNC(bp), o->next_state);
+       DP(BNX2X_MSG_SP,
+          "Completing command %d for func %d, setting state to %d\n",
+          cmd, BP_FUNC(bp), o->next_state);
 
        o->state = o->next_state;
        o->next_state = BNX2X_F_STATE_MAX;
similarity index 98%
rename from drivers/net/bnx2x/bnx2x_stats.c
rename to drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
index 771f680..628f7b9 100644 (file)
@@ -14,6 +14,9 @@
  * Statistics and Link management by Yitchak Gertner
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "bnx2x_stats.h"
 #include "bnx2x_cmn.h"
 
@@ -1194,14 +1197,13 @@ static void bnx2x_stats_update(struct bnx2x *bp)
                        struct bnx2x_fastpath *fp = &bp->fp[i];
                        struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
 
-                       printk(KERN_DEBUG "%s: rx usage(%4u)  *rx_cons_sb(%u)"
-                                         "  rx pkt(%lu)  rx calls(%lu %lu)\n",
-                              fp->name, (le16_to_cpu(*fp->rx_cons_sb) -
-                              fp->rx_comp_cons),
-                              le16_to_cpu(*fp->rx_cons_sb),
-                              bnx2x_hilo(&qstats->
-                                         total_unicast_packets_received_hi),
-                              fp->rx_calls, fp->rx_pkt);
+                       pr_debug("%s: rx usage(%4u)  *rx_cons_sb(%u)  rx pkt(%lu)  rx calls(%lu %lu)\n",
+                                fp->name, (le16_to_cpu(*fp->rx_cons_sb) -
+                                           fp->rx_comp_cons),
+                                le16_to_cpu(*fp->rx_cons_sb),
+                                bnx2x_hilo(&qstats->
+                                           total_unicast_packets_received_hi),
+                                fp->rx_calls, fp->rx_pkt);
                }
 
                for_each_eth_queue(bp, i) {
@@ -1210,27 +1212,25 @@ static void bnx2x_stats_update(struct bnx2x *bp)
                        struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
                        struct netdev_queue *txq;
 
-                       printk(KERN_DEBUG "%s: tx pkt(%lu) (Xoff events %u)",
-                               fp->name, bnx2x_hilo(
-                               &qstats->total_unicast_packets_transmitted_hi),
-                               qstats->driver_xoff);
+                       pr_debug("%s: tx pkt(%lu) (Xoff events %u)",
+                                fp->name,
+                                bnx2x_hilo(
+                                        &qstats->total_unicast_packets_transmitted_hi),
+                                qstats->driver_xoff);
 
                        for_each_cos_in_tx_queue(fp, cos) {
                                txdata = &fp->txdata[cos];
                                txq = netdev_get_tx_queue(bp->dev,
                                                FP_COS_TO_TXQ(fp, cos));
 
-                               printk(KERN_DEBUG "%d: tx avail(%4u)"
-                                      "  *tx_cons_sb(%u)"
-                                      "  tx calls (%lu)"
-                                      "  %s\n",
-                                      cos,
-                                      bnx2x_tx_avail(bp, txdata),
-                                      le16_to_cpu(*txdata->tx_cons_sb),
-                                      txdata->tx_pkt,
-                                      (netif_tx_queue_stopped(txq) ?
-                                       "Xoff" : "Xon")
-                                      );
+                               pr_debug("%d: tx avail(%4u)  *tx_cons_sb(%u)  tx calls (%lu)  %s\n",
+                                        cos,
+                                        bnx2x_tx_avail(bp, txdata),
+                                        le16_to_cpu(*txdata->tx_cons_sb),
+                                        txdata->tx_pkt,
+                                        (netif_tx_queue_stopped(txq) ?
+                                         "Xoff" : "Xon")
+                                       );
                        }
                }
        }
similarity index 99%
rename from drivers/net/cnic.c
rename to drivers/net/ethernet/broadcom/cnic.c
index 94a2e54..6f10c69 100644 (file)
@@ -45,8 +45,8 @@
 #include "bnx2x/bnx2x_reg.h"
 #include "bnx2x/bnx2x_fw_defs.h"
 #include "bnx2x/bnx2x_hsi.h"
-#include "../scsi/bnx2i/57xx_iscsi_constants.h"
-#include "../scsi/bnx2i/57xx_iscsi_hsi.h"
+#include "../../../scsi/bnx2i/57xx_iscsi_constants.h"
+#include "../../../scsi/bnx2i/57xx_iscsi_hsi.h"
 #include "cnic.h"
 #include "cnic_defs.h"
 
@@ -1177,7 +1177,7 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
        cp->fcoe_start_cid = start_cid + MAX_ISCSI_TBL_SZ;
 
        if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
-               cp->max_cid_space += BNX2X_FCOE_NUM_CONNECTIONS;
+               cp->max_cid_space += dev->max_fcoe_conn;
                cp->fcoe_init_cid = ethdev->fcoe_init_cid;
                if (!cp->fcoe_init_cid)
                        cp->fcoe_init_cid = 0x10;
@@ -1875,12 +1875,12 @@ static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid)
                                  hw_cid, NONE_CONNECTION_TYPE, &l5_data);
 
        if (ret == 0) {
-               wait_event(ctx->waitq, ctx->wait_cond);
+               wait_event_timeout(ctx->waitq, ctx->wait_cond, CNIC_RAMROD_TMO);
                if (unlikely(test_bit(CTX_FL_CID_ERROR, &ctx->ctx_flags)))
                        return -EBUSY;
        }
 
-       return ret;
+       return 0;
 }
 
 static int cnic_bnx2x_iscsi_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
@@ -2280,7 +2280,7 @@ static int cnic_bnx2x_fcoe_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
        *work = 4;
 
        l5_cid = req1->fcoe_conn_id;
-       if (l5_cid >= BNX2X_FCOE_NUM_CONNECTIONS)
+       if (l5_cid >= dev->max_fcoe_conn)
                goto err_reply;
 
        l5_cid += BNX2X_FCOE_L5_CID_BASE;
@@ -2384,7 +2384,7 @@ static int cnic_bnx2x_fcoe_disable(struct cnic_dev *dev, struct kwqe *kwqe)
        req = (struct fcoe_kwqe_conn_enable_disable *) kwqe;
        cid = req->context_id;
        l5_cid = req->conn_id;
-       if (l5_cid >= BNX2X_FCOE_NUM_CONNECTIONS)
+       if (l5_cid >= dev->max_fcoe_conn)
                return -EINVAL;
 
        l5_cid += BNX2X_FCOE_L5_CID_BASE;
@@ -2418,7 +2418,7 @@ static int cnic_bnx2x_fcoe_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
        req = (struct fcoe_kwqe_conn_destroy *) kwqe;
        cid = req->context_id;
        l5_cid = req->conn_id;
-       if (l5_cid >= BNX2X_FCOE_NUM_CONNECTIONS)
+       if (l5_cid >= dev->max_fcoe_conn)
                return -EINVAL;
 
        l5_cid += BNX2X_FCOE_L5_CID_BASE;
@@ -2428,17 +2428,20 @@ static int cnic_bnx2x_fcoe_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
        init_waitqueue_head(&ctx->waitq);
        ctx->wait_cond = 0;
 
+       memset(&kcqe, 0, sizeof(kcqe));
+       kcqe.completion_status = FCOE_KCQE_COMPLETION_STATUS_ERROR;
        memset(&l5_data, 0, sizeof(l5_data));
        ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_TERMINATE_CONN, cid,
                                  FCOE_CONNECTION_TYPE, &l5_data);
        if (ret == 0) {
-               wait_event(ctx->waitq, ctx->wait_cond);
-               set_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags);
-               queue_delayed_work(cnic_wq, &cp->delete_task,
-                                  msecs_to_jiffies(2000));
+               wait_event_timeout(ctx->waitq, ctx->wait_cond, CNIC_RAMROD_TMO);
+               if (ctx->wait_cond)
+                       kcqe.completion_status = 0;
        }
 
-       memset(&kcqe, 0, sizeof(kcqe));
+       set_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags);
+       queue_delayed_work(cnic_wq, &cp->delete_task, msecs_to_jiffies(2000));
+
        kcqe.op_code = FCOE_KCQE_OPCODE_DESTROY_CONN;
        kcqe.fcoe_conn_id = req->conn_id;
        kcqe.fcoe_conn_context_id = cid;
@@ -4850,8 +4853,7 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
                return -ENOMEM;
 
        if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
-               ret = cnic_init_id_tbl(&cp->fcoe_cid_tbl,
-                                       BNX2X_FCOE_NUM_CONNECTIONS,
+               ret = cnic_init_id_tbl(&cp->fcoe_cid_tbl, dev->max_fcoe_conn,
                                        cp->fcoe_start_cid, 0);
 
                if (ret)
@@ -5292,6 +5294,9 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
            !(ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE))
                cdev->max_fcoe_conn = ethdev->max_fcoe_conn;
 
+       if (cdev->max_fcoe_conn > BNX2X_FCOE_NUM_CONNECTIONS)
+               cdev->max_fcoe_conn = BNX2X_FCOE_NUM_CONNECTIONS;
+
        memcpy(cdev->mac_addr, ethdev->iscsi_mac, 6);
 
        cp->cnic_ops = &cnic_bnx2x_ops;
similarity index 99%
rename from drivers/net/cnic.h
rename to drivers/net/ethernet/broadcom/cnic.h
index 7a2928f..3032809 100644 (file)
@@ -373,7 +373,7 @@ struct bnx2x_bd_chain_next {
 #define BNX2X_ISCSI_PBL_NOT_CACHED     0xff
 #define BNX2X_ISCSI_PDU_HEADER_NOT_CACHED      0xff
 
-#define BNX2X_FCOE_NUM_CONNECTIONS     128
+#define BNX2X_FCOE_NUM_CONNECTIONS     1024
 
 #define BNX2X_FCOE_L5_CID_BASE         MAX_ISCSI_TBL_SZ
 
@@ -474,5 +474,7 @@ struct bnx2x_bd_chain_next {
          MAX_STAT_COUNTER_ID_E1))
 #endif
 
+#define CNIC_RAMROD_TMO                        (HZ / 4)
+
 #endif
 
similarity index 99%
rename from drivers/net/cnic_defs.h
rename to drivers/net/ethernet/broadcom/cnic_defs.h
index e47d210..239de89 100644 (file)
@@ -67,6 +67,7 @@
 #define FCOE_KWQE_OPCODE_DESTROY               (10)
 #define FCOE_KWQE_OPCODE_STAT                  (11)
 
+#define FCOE_KCQE_COMPLETION_STATUS_ERROR      (0x1)
 #define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE  (0x3)
 
 /* KCQ (kernel completion queue) response op codes */
similarity index 99%
rename from drivers/net/sb1250-mac.c
rename to drivers/net/ethernet/broadcom/sb1250-mac.c
index ea65f7e..0a1d7f2 100644 (file)
@@ -2176,7 +2176,7 @@ static const struct net_device_ops sbmac_netdev_ops = {
        .ndo_open               = sbmac_open,
        .ndo_stop               = sbmac_close,
        .ndo_start_xmit         = sbmac_start_tx,
-       .ndo_set_multicast_list = sbmac_set_rx_mode,
+       .ndo_set_rx_mode        = sbmac_set_rx_mode,
        .ndo_tx_timeout         = sbmac_tx_timeout,
        .ndo_do_ioctl           = sbmac_mii_ioctl,
        .ndo_change_mtu         = sb1250_change_mtu,
similarity index 98%
rename from drivers/net/tg3.c
rename to drivers/net/ethernet/broadcom/tg3.c
index dc3fbf6..a7e28a2 100644 (file)
@@ -89,12 +89,11 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 
 #define DRV_MODULE_NAME                "tg3"
 #define TG3_MAJ_NUM                    3
-#define TG3_MIN_NUM                    119
+#define TG3_MIN_NUM                    120
 #define DRV_MODULE_VERSION     \
        __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE     "May 18, 2011"
+#define DRV_MODULE_RELDATE     "August 18, 2011"
 
-#define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
 #define TG3_DEF_TX_MODE                0
 #define TG3_DEF_MSG_ENABLE       \
@@ -391,12 +390,14 @@ static const struct {
 static const struct {
        const char string[ETH_GSTRING_LEN];
 } ethtool_test_keys[] = {
-       { "nvram test     (online) " },
-       { "link test      (online) " },
-       { "register test  (offline)" },
-       { "memory test    (offline)" },
-       { "loopback test  (offline)" },
-       { "interrupt test (offline)" },
+       { "nvram test        (online) " },
+       { "link test         (online) " },
+       { "register test     (offline)" },
+       { "memory test       (offline)" },
+       { "mac loopback test (offline)" },
+       { "phy loopback test (offline)" },
+       { "ext loopback test (offline)" },
+       { "interrupt test    (offline)" },
 };
 
 #define TG3_NUM_TEST   ARRAY_SIZE(ethtool_test_keys)
@@ -1680,6 +1681,36 @@ static void tg3_phy_fini(struct tg3 *tp)
        }
 }
 
+static int tg3_phy_set_extloopbk(struct tg3 *tp)
+{
+       int err;
+       u32 val;
+
+       if (tp->phy_flags & TG3_PHYFLG_IS_FET)
+               return 0;
+
+       if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
+               /* Cannot do read-modify-write on 5401 */
+               err = tg3_phy_auxctl_write(tp,
+                                          MII_TG3_AUXCTL_SHDWSEL_AUXCTL,
+                                          MII_TG3_AUXCTL_ACTL_EXTLOOPBK |
+                                          0x4c20);
+               goto done;
+       }
+
+       err = tg3_phy_auxctl_read(tp,
+                                 MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val);
+       if (err)
+               return err;
+
+       val |= MII_TG3_AUXCTL_ACTL_EXTLOOPBK;
+       err = tg3_phy_auxctl_write(tp,
+                                  MII_TG3_AUXCTL_SHDWSEL_AUXCTL, val);
+
+done:
+       return err;
+}
+
 static void tg3_phy_fet_toggle_apd(struct tg3 *tp, bool enable)
 {
        u32 phytest;
@@ -6280,10 +6311,8 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
                        len = frag->size;
-                       mapping = pci_map_page(tp->pdev,
-                                              frag->page,
-                                              frag->page_offset,
-                                              len, PCI_DMA_TODEVICE);
+                       mapping = skb_frag_dma_map(&tp->pdev->dev, frag, 0,
+                                                  len, PCI_DMA_TODEVICE);
 
                        tnapi->tx_buffers[entry].skb = NULL;
                        dma_unmap_addr_set(&tnapi->tx_buffers[entry], mapping,
@@ -6343,6 +6372,127 @@ dma_error:
        return NETDEV_TX_OK;
 }
 
+static void tg3_mac_loopback(struct tg3 *tp, bool enable)
+{
+       if (enable) {
+               tp->mac_mode &= ~(MAC_MODE_HALF_DUPLEX |
+                                 MAC_MODE_PORT_MODE_MASK);
+
+               tp->mac_mode |= MAC_MODE_PORT_INT_LPBACK;
+
+               if (!tg3_flag(tp, 5705_PLUS))
+                       tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+
+               if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
+                       tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
+               else
+                       tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+       } else {
+               tp->mac_mode &= ~MAC_MODE_PORT_INT_LPBACK;
+
+               if (tg3_flag(tp, 5705_PLUS) ||
+                   (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
+                       tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
+       }
+
+       tw32(MAC_MODE, tp->mac_mode);
+       udelay(40);
+}
+
+static int tg3_phy_lpbk_set(struct tg3 *tp, u32 speed, bool extlpbk)
+{
+       u32 val, bmcr, mac_mode, ptest = 0;
+
+       tg3_phy_toggle_apd(tp, false);
+       tg3_phy_toggle_automdix(tp, 0);
+
+       if (extlpbk && tg3_phy_set_extloopbk(tp))
+               return -EIO;
+
+       bmcr = BMCR_FULLDPLX;
+       switch (speed) {
+       case SPEED_10:
+               break;
+       case SPEED_100:
+               bmcr |= BMCR_SPEED100;
+               break;
+       case SPEED_1000:
+       default:
+               if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
+                       speed = SPEED_100;
+                       bmcr |= BMCR_SPEED100;
+               } else {
+                       speed = SPEED_1000;
+                       bmcr |= BMCR_SPEED1000;
+               }
+       }
+
+       if (extlpbk) {
+               if (!(tp->phy_flags & TG3_PHYFLG_IS_FET)) {
+                       tg3_readphy(tp, MII_CTRL1000, &val);
+                       val |= CTL1000_AS_MASTER |
+                              CTL1000_ENABLE_MASTER;
+                       tg3_writephy(tp, MII_CTRL1000, val);
+               } else {
+                       ptest = MII_TG3_FET_PTEST_TRIM_SEL |
+                               MII_TG3_FET_PTEST_TRIM_2;
+                       tg3_writephy(tp, MII_TG3_FET_PTEST, ptest);
+               }
+       } else
+               bmcr |= BMCR_LOOPBACK;
+
+       tg3_writephy(tp, MII_BMCR, bmcr);
+
+       /* The write needs to be flushed for the FETs */
+       if (tp->phy_flags & TG3_PHYFLG_IS_FET)
+               tg3_readphy(tp, MII_BMCR, &bmcr);
+
+       udelay(40);
+
+       if ((tp->phy_flags & TG3_PHYFLG_IS_FET) &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+               tg3_writephy(tp, MII_TG3_FET_PTEST, ptest |
+                            MII_TG3_FET_PTEST_FRC_TX_LINK |
+                            MII_TG3_FET_PTEST_FRC_TX_LOCK);
+
+               /* The write needs to be flushed for the AC131 */
+               tg3_readphy(tp, MII_TG3_FET_PTEST, &val);
+       }
+
+       /* Reset to prevent losing 1st rx packet intermittently */
+       if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) &&
+           tg3_flag(tp, 5780_CLASS)) {
+               tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+               udelay(10);
+               tw32_f(MAC_RX_MODE, tp->rx_mode);
+       }
+
+       mac_mode = tp->mac_mode &
+                  ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
+       if (speed == SPEED_1000)
+               mac_mode |= MAC_MODE_PORT_MODE_GMII;
+       else
+               mac_mode |= MAC_MODE_PORT_MODE_MII;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
+               u32 masked_phy_id = tp->phy_id & TG3_PHY_ID_MASK;
+
+               if (masked_phy_id == TG3_PHY_ID_BCM5401)
+                       mac_mode &= ~MAC_MODE_LINK_POLARITY;
+               else if (masked_phy_id == TG3_PHY_ID_BCM5411)
+                       mac_mode |= MAC_MODE_LINK_POLARITY;
+
+               tg3_writephy(tp, MII_TG3_EXT_CTRL,
+                            MII_TG3_EXT_CTRL_LNK3_LED_MODE);
+       }
+
+       tw32(MAC_MODE, mac_mode);
+       udelay(40);
+
+       return 0;
+}
+
 static void tg3_set_loopback(struct net_device *dev, u32 features)
 {
        struct tg3 *tp = netdev_priv(dev);
@@ -6351,16 +6501,8 @@ static void tg3_set_loopback(struct net_device *dev, u32 features)
                if (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK)
                        return;
 
-               /*
-                * Clear MAC_MODE_HALF_DUPLEX or you won't get packets back in
-                * loopback mode if Half-Duplex mode was negotiated earlier.
-                */
-               tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
-
-               /* Enable internal MAC loopback mode */
-               tp->mac_mode |= MAC_MODE_PORT_INT_LPBACK;
                spin_lock_bh(&tp->lock);
-               tw32(MAC_MODE, tp->mac_mode);
+               tg3_mac_loopback(tp, true);
                netif_carrier_on(tp->dev);
                spin_unlock_bh(&tp->lock);
                netdev_info(dev, "Internal MAC loopback mode enabled.\n");
@@ -6368,10 +6510,8 @@ static void tg3_set_loopback(struct net_device *dev, u32 features)
                if (!(tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
                        return;
 
-               /* Disable internal MAC loopback mode */
-               tp->mac_mode &= ~MAC_MODE_PORT_INT_LPBACK;
                spin_lock_bh(&tp->lock);
-               tw32(MAC_MODE, tp->mac_mode);
+               tg3_mac_loopback(tp, false);
                /* Force link status check */
                tg3_setup_phy(tp, 1);
                spin_unlock_bh(&tp->lock);
@@ -11219,10 +11359,6 @@ static int tg3_test_memory(struct tg3 *tp)
        return err;
 }
 
-#define TG3_MAC_LOOPBACK       0
-#define TG3_PHY_LOOPBACK       1
-#define TG3_TSO_LOOPBACK       2
-
 #define TG3_TSO_MSS            500
 
 #define TG3_TSO_IP_HDR_LEN     20
@@ -11246,9 +11382,9 @@ static const u8 tg3_tso_header[] = {
 0x11, 0x11, 0x11, 0x11,
 };
 
-static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
+static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback)
 {
-       u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key;
+       u32 rx_start_idx, rx_idx, tx_idx, opaque_key;
        u32 base_flags = 0, mss = 0, desc_idx, coal_now, data_off, val;
        u32 budget;
        struct sk_buff *skb, *rx_skb;
@@ -11269,76 +11405,6 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
        }
        coal_now = tnapi->coal_now | rnapi->coal_now;
 
-       if (loopback_mode == TG3_MAC_LOOPBACK) {
-               /* HW errata - mac loopback fails in some cases on 5780.
-                * Normal traffic and PHY loopback are not affected by
-                * errata.  Also, the MAC loopback test is deprecated for
-                * all newer ASIC revisions.
-                */
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
-                   tg3_flag(tp, CPMU_PRESENT))
-                       return 0;
-
-               mac_mode = tp->mac_mode &
-                          ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
-               mac_mode |= MAC_MODE_PORT_INT_LPBACK;
-               if (!tg3_flag(tp, 5705_PLUS))
-                       mac_mode |= MAC_MODE_LINK_POLARITY;
-               if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
-                       mac_mode |= MAC_MODE_PORT_MODE_MII;
-               else
-                       mac_mode |= MAC_MODE_PORT_MODE_GMII;
-               tw32(MAC_MODE, mac_mode);
-       } else {
-               if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
-                       tg3_phy_fet_toggle_apd(tp, false);
-                       val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100;
-               } else
-                       val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000;
-
-               tg3_phy_toggle_automdix(tp, 0);
-
-               tg3_writephy(tp, MII_BMCR, val);
-               udelay(40);
-
-               mac_mode = tp->mac_mode &
-                          ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
-               if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
-                       tg3_writephy(tp, MII_TG3_FET_PTEST,
-                                    MII_TG3_FET_PTEST_FRC_TX_LINK |
-                                    MII_TG3_FET_PTEST_FRC_TX_LOCK);
-                       /* The write needs to be flushed for the AC131 */
-                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
-                               tg3_readphy(tp, MII_TG3_FET_PTEST, &val);
-                       mac_mode |= MAC_MODE_PORT_MODE_MII;
-               } else
-                       mac_mode |= MAC_MODE_PORT_MODE_GMII;
-
-               /* reset to prevent losing 1st rx packet intermittently */
-               if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) {
-                       tw32_f(MAC_RX_MODE, RX_MODE_RESET);
-                       udelay(10);
-                       tw32_f(MAC_RX_MODE, tp->rx_mode);
-               }
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
-                       u32 masked_phy_id = tp->phy_id & TG3_PHY_ID_MASK;
-                       if (masked_phy_id == TG3_PHY_ID_BCM5401)
-                               mac_mode &= ~MAC_MODE_LINK_POLARITY;
-                       else if (masked_phy_id == TG3_PHY_ID_BCM5411)
-                               mac_mode |= MAC_MODE_LINK_POLARITY;
-                       tg3_writephy(tp, MII_TG3_EXT_CTRL,
-                                    MII_TG3_EXT_CTRL_LNK3_LED_MODE);
-               }
-               tw32(MAC_MODE, mac_mode);
-
-               /* Wait for link */
-               for (i = 0; i < 100; i++) {
-                       if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
-                               break;
-                       mdelay(1);
-               }
-       }
-
        err = -EIO;
 
        tx_len = pktsz;
@@ -11352,7 +11418,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
 
        tw32(MAC_RX_MTU_SIZE, tx_len + ETH_FCS_LEN);
 
-       if (loopback_mode == TG3_TSO_LOOPBACK) {
+       if (tso_loopback) {
                struct iphdr *iph = (struct iphdr *)&tx_data[ETH_HLEN];
 
                u32 hdr_len = TG3_TSO_IP_HDR_LEN + TG3_TSO_TCP_HDR_LEN +
@@ -11472,7 +11538,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
                rx_len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT)
                         - ETH_FCS_LEN;
 
-               if (loopback_mode != TG3_TSO_LOOPBACK) {
+               if (!tso_loopback) {
                        if (rx_len != tx_len)
                                goto out;
 
@@ -11519,25 +11585,33 @@ out:
 #define TG3_STD_LOOPBACK_FAILED                1
 #define TG3_JMB_LOOPBACK_FAILED                2
 #define TG3_TSO_LOOPBACK_FAILED                4
+#define TG3_LOOPBACK_FAILED \
+       (TG3_STD_LOOPBACK_FAILED | \
+        TG3_JMB_LOOPBACK_FAILED | \
+        TG3_TSO_LOOPBACK_FAILED)
 
-#define TG3_MAC_LOOPBACK_SHIFT         0
-#define TG3_PHY_LOOPBACK_SHIFT         4
-#define TG3_LOOPBACK_FAILED            0x00000077
-
-static int tg3_test_loopback(struct tg3 *tp)
+static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
 {
-       int err = 0;
-       u32 eee_cap, cpmuctrl = 0;
-
-       if (!netif_running(tp->dev))
-               return TG3_LOOPBACK_FAILED;
+       int err = -EIO;
+       u32 eee_cap;
 
        eee_cap = tp->phy_flags & TG3_PHYFLG_EEE_CAP;
        tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP;
 
+       if (!netif_running(tp->dev)) {
+               data[0] = TG3_LOOPBACK_FAILED;
+               data[1] = TG3_LOOPBACK_FAILED;
+               if (do_extlpbk)
+                       data[2] = TG3_LOOPBACK_FAILED;
+               goto done;
+       }
+
        err = tg3_reset_hw(tp, 1);
        if (err) {
-               err = TG3_LOOPBACK_FAILED;
+               data[0] = TG3_LOOPBACK_FAILED;
+               data[1] = TG3_LOOPBACK_FAILED;
+               if (do_extlpbk)
+                       data[2] = TG3_LOOPBACK_FAILED;
                goto done;
        }
 
@@ -11550,68 +11624,72 @@ static int tg3_test_loopback(struct tg3 *tp)
                        tw32(i, 0x0);
        }
 
-       /* Turn off gphy autopowerdown. */
-       if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD)
-               tg3_phy_toggle_apd(tp, false);
+       /* HW errata - mac loopback fails in some cases on 5780.
+        * Normal traffic and PHY loopback are not affected by
+        * errata.  Also, the MAC loopback test is deprecated for
+        * all newer ASIC revisions.
+        */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780 &&
+           !tg3_flag(tp, CPMU_PRESENT)) {
+               tg3_mac_loopback(tp, true);
 
-       if (tg3_flag(tp, CPMU_PRESENT)) {
+               if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
+                       data[0] |= TG3_STD_LOOPBACK_FAILED;
+
+               if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
+                   tg3_run_loopback(tp, 9000 + ETH_HLEN, false))
+                       data[0] |= TG3_JMB_LOOPBACK_FAILED;
+
+               tg3_mac_loopback(tp, false);
+       }
+
+       if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
+           !tg3_flag(tp, USE_PHYLIB)) {
                int i;
-               u32 status;
 
-               tw32(TG3_CPMU_MUTEX_REQ, CPMU_MUTEX_REQ_DRIVER);
+               tg3_phy_lpbk_set(tp, 0, false);
 
-               /* Wait for up to 40 microseconds to acquire lock. */
-               for (i = 0; i < 4; i++) {
-                       status = tr32(TG3_CPMU_MUTEX_GNT);
-                       if (status == CPMU_MUTEX_GNT_DRIVER)
+               /* Wait for link */
+               for (i = 0; i < 100; i++) {
+                       if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
                                break;
-                       udelay(10);
-               }
-
-               if (status != CPMU_MUTEX_GNT_DRIVER) {
-                       err = TG3_LOOPBACK_FAILED;
-                       goto done;
+                       mdelay(1);
                }
 
-               /* Turn off link-based power management. */
-               cpmuctrl = tr32(TG3_CPMU_CTRL);
-               tw32(TG3_CPMU_CTRL,
-                    cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE |
-                                 CPMU_CTRL_LINK_AWARE_MODE));
-       }
-
-       if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_MAC_LOOPBACK))
-               err |= TG3_STD_LOOPBACK_FAILED << TG3_MAC_LOOPBACK_SHIFT;
+               if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
+                       data[1] |= TG3_STD_LOOPBACK_FAILED;
+               if (tg3_flag(tp, TSO_CAPABLE) &&
+                   tg3_run_loopback(tp, ETH_FRAME_LEN, true))
+                       data[1] |= TG3_TSO_LOOPBACK_FAILED;
+               if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
+                   tg3_run_loopback(tp, 9000 + ETH_HLEN, false))
+                       data[1] |= TG3_JMB_LOOPBACK_FAILED;
 
-       if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
-           tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_MAC_LOOPBACK))
-               err |= TG3_JMB_LOOPBACK_FAILED << TG3_MAC_LOOPBACK_SHIFT;
+               if (do_extlpbk) {
+                       tg3_phy_lpbk_set(tp, 0, true);
 
-       if (tg3_flag(tp, CPMU_PRESENT)) {
-               tw32(TG3_CPMU_CTRL, cpmuctrl);
+                       /* All link indications report up, but the hardware
+                        * isn't really ready for about 20 msec.  Double it
+                        * to be sure.
+                        */
+                       mdelay(40);
 
-               /* Release the mutex */
-               tw32(TG3_CPMU_MUTEX_GNT, CPMU_MUTEX_GNT_DRIVER);
-       }
+                       if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
+                               data[2] |= TG3_STD_LOOPBACK_FAILED;
+                       if (tg3_flag(tp, TSO_CAPABLE) &&
+                           tg3_run_loopback(tp, ETH_FRAME_LEN, true))
+                               data[2] |= TG3_TSO_LOOPBACK_FAILED;
+                       if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
+                           tg3_run_loopback(tp, 9000 + ETH_HLEN, false))
+                               data[2] |= TG3_JMB_LOOPBACK_FAILED;
+               }
 
-       if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
-           !tg3_flag(tp, USE_PHYLIB)) {
-               if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_PHY_LOOPBACK))
-                       err |= TG3_STD_LOOPBACK_FAILED <<
-                              TG3_PHY_LOOPBACK_SHIFT;
-               if (tg3_flag(tp, TSO_CAPABLE) &&
-                   tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_TSO_LOOPBACK))
-                       err |= TG3_TSO_LOOPBACK_FAILED <<
-                              TG3_PHY_LOOPBACK_SHIFT;
-               if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
-                   tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_PHY_LOOPBACK))
-                       err |= TG3_JMB_LOOPBACK_FAILED <<
-                              TG3_PHY_LOOPBACK_SHIFT;
+               /* Re-enable gphy autopowerdown. */
+               if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD)
+                       tg3_phy_toggle_apd(tp, true);
        }
 
-       /* Re-enable gphy autopowerdown. */
-       if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD)
-               tg3_phy_toggle_apd(tp, true);
+       err = (data[0] | data[1] | data[2]) ? -EIO : 0;
 
 done:
        tp->phy_flags |= eee_cap;
@@ -11623,6 +11701,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
                          u64 *data)
 {
        struct tg3 *tp = netdev_priv(dev);
+       bool doextlpbk = etest->flags & ETH_TEST_FL_EXTERNAL_LB;
 
        if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) &&
            tg3_power_up(tp)) {
@@ -11637,7 +11716,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
                etest->flags |= ETH_TEST_FL_FAILED;
                data[0] = 1;
        }
-       if (tg3_test_link(tp) != 0) {
+       if (!doextlpbk && tg3_test_link(tp)) {
                etest->flags |= ETH_TEST_FL_FAILED;
                data[1] = 1;
        }
@@ -11667,18 +11746,23 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
                        etest->flags |= ETH_TEST_FL_FAILED;
                        data[2] = 1;
                }
+
                if (tg3_test_memory(tp) != 0) {
                        etest->flags |= ETH_TEST_FL_FAILED;
                        data[3] = 1;
                }
-               if ((data[4] = tg3_test_loopback(tp)) != 0)
+
+               if (doextlpbk)
+                       etest->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
+
+               if (tg3_test_loopback(tp, &data[4], doextlpbk))
                        etest->flags |= ETH_TEST_FL_FAILED;
 
                tg3_full_unlock(tp);
 
                if (tg3_test_interrupt(tp) != 0) {
                        etest->flags |= ETH_TEST_FL_FAILED;
-                       data[5] = 1;
+                       data[7] = 1;
                }
 
                tg3_full_lock(tp, 0);
@@ -14368,7 +14452,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (tg3_flag(tp, ENABLE_APE))
                tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
        else
-               tp->mac_mode = TG3_DEF_MAC_MODE;
+               tp->mac_mode = 0;
 
        /* these are limited to 10/100 only */
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
@@ -15177,7 +15261,7 @@ static const struct net_device_ops tg3_netdev_ops = {
        .ndo_start_xmit         = tg3_start_xmit,
        .ndo_get_stats64        = tg3_get_stats64,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = tg3_set_rx_mode,
+       .ndo_set_rx_mode        = tg3_set_rx_mode,
        .ndo_set_mac_address    = tg3_set_mac_addr,
        .ndo_do_ioctl           = tg3_ioctl,
        .ndo_tx_timeout         = tg3_tx_timeout,
similarity index 99%
rename from drivers/net/tg3.h
rename to drivers/net/ethernet/broadcom/tg3.h
index 2ea456d..d2976f3 100644 (file)
 #define MII_TG3_AUXCTL_ACTL_TX_6DB     0x0400
 #define MII_TG3_AUXCTL_ACTL_SMDSP_ENA  0x0800
 #define MII_TG3_AUXCTL_ACTL_EXTPKTLEN  0x4000
+#define MII_TG3_AUXCTL_ACTL_EXTLOOPBK  0x8000
 
 #define MII_TG3_AUXCTL_SHDWSEL_PWRCTL  0x0002
 #define MII_TG3_AUXCTL_PCTL_WOL_EN     0x0008
 
 /* Fast Ethernet Tranceiver definitions */
 #define MII_TG3_FET_PTEST              0x17
+#define  MII_TG3_FET_PTEST_TRIM_SEL    0x0010
+#define  MII_TG3_FET_PTEST_TRIM_2      0x0002
 #define  MII_TG3_FET_PTEST_FRC_TX_LINK 0x1000
 #define  MII_TG3_FET_PTEST_FRC_TX_LOCK 0x0800
 
diff --git a/drivers/net/ethernet/brocade/Kconfig b/drivers/net/ethernet/brocade/Kconfig
new file mode 100644 (file)
index 0000000..2641557
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# Brocade device configuration
+#
+
+config NET_VENDOR_BROCADE
+       bool "Brocade devices"
+       default y
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Brocade cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_BROCADE
+
+source "drivers/net/ethernet/brocade/bna/Kconfig"
+
+endif # NET_VENDOR_BROCADE
diff --git a/drivers/net/ethernet/brocade/Makefile b/drivers/net/ethernet/brocade/Makefile
new file mode 100644 (file)
index 0000000..b58238d
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Brocade device drivers.
+#
+
+obj-$(CONFIG_BNA) += bna/
diff --git a/drivers/net/ethernet/brocade/bna/Kconfig b/drivers/net/ethernet/brocade/bna/Kconfig
new file mode 100644 (file)
index 0000000..dc2eb52
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# Brocade network device configuration
+#
+
+config BNA
+       tristate "Brocade 1010/1020 10Gb Ethernet Driver support"
+       depends on PCI
+       ---help---
+         This driver supports Brocade 1010/1020 10Gb CEE capable Ethernet
+         cards.
+         To compile this driver as a module, choose M here: the module
+         will be called bna.
+
+         For general information and support, go to the Brocade support
+         website at:
+
+         <http://support.brocade.com>
similarity index 52%
rename from drivers/net/bna/Makefile
rename to drivers/net/ethernet/brocade/bna/Makefile
index a5d604d..74d3abc 100644 (file)
@@ -5,7 +5,8 @@
 
 obj-$(CONFIG_BNA) += bna.o
 
-bna-objs := bnad.o bnad_ethtool.o bna_ctrl.o bna_txrx.o
-bna-objs += bfa_ioc.o bfa_ioc_ct.o bfa_cee.o cna_fwimg.o
+bna-objs := bnad.o bnad_ethtool.o bna_enet.o bna_tx_rx.o
+bna-objs += bfa_msgq.o bfa_ioc.o bfa_ioc_ct.o bfa_cee.o
+bna-objs += cna_fwimg.o
 
 EXTRA_CFLAGS := -Idrivers/net/bna
similarity index 98%
rename from drivers/net/bna/bfa_cee.c
rename to drivers/net/ethernet/brocade/bna/bfa_cee.c
index 39e5ab9..b45b8eb 100644 (file)
@@ -22,9 +22,6 @@
 #include "bfi_cna.h"
 #include "bfa_ioc.h"
 
-#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
-#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
-
 static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg);
 static void bfa_cee_format_cee_cfg(void *buffer);
 
similarity index 92%
rename from drivers/net/bna/bfa_defs.h
rename to drivers/net/ethernet/brocade/bna/bfa_defs.h
index b080b36..205b92b 100644 (file)
@@ -124,6 +124,7 @@ enum bfa_ioc_state {
        BFA_IOC_DISABLED        = 10,   /*!< IOC is disabled */
        BFA_IOC_FWMISMATCH      = 11,   /*!< IOC f/w different from drivers */
        BFA_IOC_ENABLING        = 12,   /*!< IOC is being enabled */
+       BFA_IOC_HWFAIL          = 13,   /*!< PCI mapping doesn't exist */
 };
 
 /**
@@ -179,8 +180,19 @@ struct bfa_ioc_attr {
        struct bfa_adapter_attr adapter_attr;   /*!< HBA attributes */
        struct bfa_ioc_driver_attr driver_attr; /*!< driver attr    */
        struct bfa_ioc_pci_attr pci_attr;
-       u8                              port_id;        /*!< port number    */
-       u8                              rsvd[7];        /*!< 64bit align    */
+       u8                              port_id;        /*!< port number */
+       u8                              port_mode;      /*!< enum bfa_mode */
+       u8                              cap_bm;         /*!< capability */
+       u8                              port_mode_cfg;  /*!< enum bfa_mode */
+       u8                              rsvd[4];        /*!< 64bit align */
+};
+
+/**
+ * Adapter capability mask definition
+ */
+enum {
+       BFA_CM_HBA      =       0x01,
+       BFA_CM_CNA      =       0x02,
 };
 
 /**
@@ -228,7 +240,7 @@ struct bfa_mfg_block {
        mac_t           mfg_mac;        /*!< mac address */
        u8              num_mac;        /*!< number of mac addresses */
        u8              rsv2;
-       u32     mfg_type;       /*!< card type */
+       u32             card_type;      /*!< card type */
        u8              rsv3[108];
        u8              md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */
 };
@@ -242,5 +254,12 @@ struct bfa_mfg_block {
 #define bfa_asic_id_ct(devid)                  \
        ((devid) == PCI_DEVICE_ID_BROCADE_CT || \
        (devid) == PCI_DEVICE_ID_BROCADE_CT_FC)
+#define bfa_asic_id_ctc(devid) (bfa_asic_id_ct(devid))
+
+enum bfa_mode {
+       BFA_MODE_HBA            = 1,
+       BFA_MODE_CNA            = 2,
+       BFA_MODE_NIC            = 3
+};
 
 #endif /* __BFA_DEFS_H__ */
similarity index 89%
rename from drivers/net/bna/bfa_defs_mfg_comm.h
rename to drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h
index 885ef3a..7ddd16f 100644 (file)
 #define __BFA_DEFS_MFG_COMM_H__
 
 #include "cna.h"
+#include "bfa_defs.h"
 
 /**
  * Manufacturing block version
  */
-#define BFA_MFG_VERSION                                2
+#define BFA_MFG_VERSION                                3
 #define BFA_MFG_VERSION_UNINIT                 0xFF
 
 /**
@@ -65,14 +66,6 @@ enum {
 
 #pragma pack(1)
 
-/**
- * Check if 1-port card
- */
-#define bfa_mfg_is_1port(type) (( \
-       (type) == BFA_MFG_TYPE_FC8P1 || \
-       (type) == BFA_MFG_TYPE_FC4P1 || \
-       (type) == BFA_MFG_TYPE_CNA10P1))
-
 /**
  * Check if Mezz card
  */
@@ -95,27 +88,14 @@ enum {
        (type) == BFA_MFG_TYPE_CNA10P1 || \
        bfa_mfg_is_mezz(type)))
 
-#define bfa_mfg_adapter_prop_init_flash(card_type, prop)       \
+#define bfa_mfg_adapter_prop_init_flash_ct(mfgblk, prop)       \
 do {                                                           \
-       switch ((card_type)) {                                  \
-       case BFA_MFG_TYPE_FC8P2:                                \
+       switch ((mfgblk)->card_type) {                          \
        case BFA_MFG_TYPE_JAYHAWK:                              \
        case BFA_MFG_TYPE_ASTRA:                                \
                (prop) = BFI_ADAPTER_SETP(NPORTS, 2) |          \
                        BFI_ADAPTER_SETP(SPEED, 8);             \
                break;                                          \
-       case BFA_MFG_TYPE_FC8P1:                                \
-               (prop) = BFI_ADAPTER_SETP(NPORTS, 1) |          \
-                       BFI_ADAPTER_SETP(SPEED, 8);             \
-               break;                                          \
-       case BFA_MFG_TYPE_FC4P2:                                \
-               (prop) = BFI_ADAPTER_SETP(NPORTS, 2) |          \
-                       BFI_ADAPTER_SETP(SPEED, 4);             \
-               break;                                          \
-       case BFA_MFG_TYPE_FC4P1:                                \
-               (prop) = BFI_ADAPTER_SETP(NPORTS, 1) |          \
-                       BFI_ADAPTER_SETP(SPEED, 4);             \
-               break;                                          \
        case BFA_MFG_TYPE_CNA10P2:                              \
        case BFA_MFG_TYPE_WANCHESE:                             \
        case BFA_MFG_TYPE_LIGHTNING_P0:                         \
similarity index 87%
rename from drivers/net/bna/bfa_ioc.c
rename to drivers/net/ethernet/brocade/bna/bfa_ioc.c
index 126b0aa..029fb52 100644 (file)
@@ -19,7 +19,7 @@
 #include "bfa_ioc.h"
 #include "cna.h"
 #include "bfi.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
 #include "bfa_defs.h"
 
 /**
@@ -62,6 +62,7 @@ static void bfa_ioc_hw_sem_init(struct bfa_ioc *ioc);
 static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc);
 static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc);
 static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force);
+static void bfa_ioc_poll_fwinit(struct bfa_ioc *ioc);
 static void bfa_ioc_send_enable(struct bfa_ioc *ioc);
 static void bfa_ioc_send_disable(struct bfa_ioc *ioc);
 static void bfa_ioc_send_getattr(struct bfa_ioc *ioc);
@@ -78,8 +79,8 @@ static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
 static void bfa_ioc_fail_notify(struct bfa_ioc *ioc);
 static void bfa_ioc_pf_enabled(struct bfa_ioc *ioc);
 static void bfa_ioc_pf_disabled(struct bfa_ioc *ioc);
-static void bfa_ioc_pf_initfailed(struct bfa_ioc *ioc);
 static void bfa_ioc_pf_failed(struct bfa_ioc *ioc);
+static void bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc);
 static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc);
 static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type,
                         u32 boot_param);
@@ -108,11 +109,11 @@ enum ioc_event {
        IOC_E_ENABLED           = 5,    /*!< f/w enabled                */
        IOC_E_FWRSP_GETATTR     = 6,    /*!< IOC get attribute response */
        IOC_E_DISABLED          = 7,    /*!< f/w disabled               */
-       IOC_E_INITFAILED        = 8,    /*!< failure notice by iocpf sm */
-       IOC_E_PFFAILED          = 9,    /*!< failure notice by iocpf sm */
-       IOC_E_HBFAIL            = 10,   /*!< heartbeat failure          */
-       IOC_E_HWERROR           = 11,   /*!< hardware error interrupt   */
-       IOC_E_TIMEOUT           = 12,   /*!< timeout                    */
+       IOC_E_PFFAILED          = 8,    /*!< failure notice by iocpf sm */
+       IOC_E_HBFAIL            = 9,    /*!< heartbeat failure          */
+       IOC_E_HWERROR           = 10,   /*!< hardware error interrupt   */
+       IOC_E_TIMEOUT           = 11,   /*!< timeout                    */
+       IOC_E_HWFAILED          = 12,   /*!< PCI mapping failure notice */
 };
 
 bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event);
@@ -124,6 +125,7 @@ bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc, enum ioc_event);
 
 static struct bfa_sm_table ioc_sm_table[] = {
        {BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
@@ -135,6 +137,7 @@ static struct bfa_sm_table ioc_sm_table[] = {
        {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
        {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
        {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
+       {BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},
 };
 
 /**
@@ -166,6 +169,7 @@ enum iocpf_event {
        IOCPF_E_GETATTRFAIL     = 9,    /*!< init fail notice by ioc sm */
        IOCPF_E_SEMLOCKED       = 10,   /*!< h/w semaphore is locked    */
        IOCPF_E_TIMEOUT         = 11,   /*!< f/w response timeout       */
+       IOCPF_E_SEM_ERROR       = 12,   /*!< h/w sem mapping error      */
 };
 
 /**
@@ -300,11 +304,16 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
                /* !!! fall through !!! */
        case IOC_E_HWERROR:
                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
                if (event != IOC_E_PFFAILED)
                        bfa_iocpf_initfail(ioc);
                break;
 
+       case IOC_E_HWFAILED:
+               ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+               break;
+
        case IOC_E_DISABLE:
                bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
                break;
@@ -343,6 +352,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
        case IOC_E_FWRSP_GETATTR:
                del_timer(&ioc->ioc_timer);
                bfa_ioc_check_attr_wwns(ioc);
+               bfa_ioc_hb_monitor(ioc);
                bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
                break;
 
@@ -352,7 +362,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
                /* fall through */
        case IOC_E_TIMEOUT:
                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
                if (event != IOC_E_PFFAILED)
                        bfa_iocpf_getattrfail(ioc);
                break;
@@ -374,7 +384,7 @@ static void
 bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
 {
        ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
-       bfa_ioc_hb_monitor(ioc);
+       bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
 }
 
 static void
@@ -394,12 +404,13 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
                bfa_ioc_hb_stop(ioc);
                /* !!! fall through !!! */
        case IOC_E_HBFAIL:
-               bfa_ioc_fail_notify(ioc);
                if (ioc->iocpf.auto_recover)
                        bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
                else
                        bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 
+               bfa_ioc_fail_notify(ioc);
+
                if (event != IOC_E_PFFAILED)
                        bfa_iocpf_fail(ioc);
                break;
@@ -435,6 +446,11 @@ bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
                bfa_iocpf_fail(ioc);
                break;
 
+       case IOC_E_HWFAILED:
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+               bfa_ioc_disable_comp(ioc);
+               break;
+
        default:
                bfa_sm_fault(event);
        }
@@ -493,12 +509,14 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
                 * Initialization retry failed.
                 */
                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
                if (event != IOC_E_PFFAILED)
                        bfa_iocpf_initfail(ioc);
                break;
 
-       case IOC_E_INITFAILED:
-               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+       case IOC_E_HWFAILED:
+               ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
                break;
 
        case IOC_E_ENABLE:
@@ -552,6 +570,36 @@ bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
        }
 }
 
+static void
+bfa_ioc_sm_hwfail_entry(struct bfa_ioc *ioc)
+{
+}
+
+/**
+ * IOC failure.
+ */
+static void
+bfa_ioc_sm_hwfail(struct bfa_ioc *ioc, enum ioc_event event)
+{
+       switch (event) {
+
+       case IOC_E_ENABLE:
+               ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+               break;
+
+       case IOC_E_DISABLE:
+               ioc->cbfn->disable_cbfn(ioc->bfa);
+               break;
+
+       case IOC_E_DETACH:
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
 /**
  * IOCPF State Machine
  */
@@ -562,7 +610,7 @@ bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
 static void
 bfa_iocpf_sm_reset_entry(struct bfa_iocpf *iocpf)
 {
-       iocpf->retry_count = 0;
+       iocpf->fw_mismatch_notified = false;
        iocpf->auto_recover = bfa_nw_auto_recover;
 }
 
@@ -607,7 +655,6 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
        case IOCPF_E_SEMLOCKED:
                if (bfa_ioc_firmware_lock(ioc)) {
                        if (bfa_ioc_sync_start(ioc)) {
-                               iocpf->retry_count = 0;
                                bfa_ioc_sync_join(ioc);
                                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
                        } else {
@@ -622,6 +669,11 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
                }
                break;
 
+       case IOCPF_E_SEM_ERROR:
+               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+               bfa_ioc_pf_hwfailed(ioc);
+               break;
+
        case IOCPF_E_DISABLE:
                bfa_ioc_hw_sem_get_cancel(ioc);
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
@@ -645,10 +697,10 @@ static void
 bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf)
 {
        /* Call only the first time sm enters fwmismatch state. */
-       if (iocpf->retry_count == 0)
+       if (iocpf->fw_mismatch_notified == false)
                bfa_ioc_pf_fwmismatch(iocpf->ioc);
 
-       iocpf->retry_count++;
+       iocpf->fw_mismatch_notified = true;
        mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
                msecs_to_jiffies(BFA_IOC_TOV));
 }
@@ -711,6 +763,11 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
                }
                break;
 
+       case IOCPF_E_SEM_ERROR:
+               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+               bfa_ioc_pf_hwfailed(ioc);
+               break;
+
        case IOCPF_E_DISABLE:
                bfa_ioc_hw_sem_get_cancel(ioc);
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -724,8 +781,7 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf *iocpf)
 {
-       mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
-               msecs_to_jiffies(BFA_IOC_TOV));
+       iocpf->poll_time = 0;
        bfa_ioc_reset(iocpf->ioc, 0);
 }
 
@@ -740,19 +796,11 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)
 
        switch (event) {
        case IOCPF_E_FWREADY:
-               del_timer(&ioc->iocpf_timer);
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
                break;
 
-       case IOCPF_E_INITFAIL:
-               del_timer(&ioc->iocpf_timer);
-               /*
-                * !!! fall through !!!
-                */
-
        case IOCPF_E_TIMEOUT:
                bfa_nw_ioc_hw_sem_release(ioc);
-               if (event == IOCPF_E_TIMEOUT)
                        bfa_ioc_pf_failed(ioc);
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
                break;
@@ -774,6 +822,10 @@ bfa_iocpf_sm_enabling_entry(struct bfa_iocpf *iocpf)
 {
        mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
                msecs_to_jiffies(BFA_IOC_TOV));
+       /**
+        * Enable Interrupts before sending fw IOC ENABLE cmd.
+        */
+       iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);
        bfa_ioc_send_enable(iocpf->ioc);
 }
 
@@ -811,21 +863,11 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
                break;
 
-       case IOCPF_E_FWREADY:
-               bfa_ioc_send_enable(ioc);
-               break;
-
        default:
                bfa_sm_fault(event);
        }
 }
 
-static bool
-bfa_nw_ioc_is_operational(struct bfa_ioc *ioc)
-{
-       return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
-}
-
 static void
 bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf)
 {
@@ -835,8 +877,6 @@ bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf)
 static void
 bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
 {
-       struct bfa_ioc *ioc = iocpf->ioc;
-
        switch (event) {
        case IOCPF_E_DISABLE:
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
@@ -850,14 +890,6 @@ bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
                break;
 
-       case IOCPF_E_FWREADY:
-               bfa_ioc_pf_failed(ioc);
-               if (bfa_nw_ioc_is_operational(ioc))
-                       bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
-               else
-                       bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
-               break;
-
        default:
                bfa_sm_fault(event);
        }
@@ -881,7 +913,6 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
 
        switch (event) {
        case IOCPF_E_FWRSP_DISABLE:
-       case IOCPF_E_FWREADY:
                del_timer(&ioc->iocpf_timer);
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
                break;
@@ -926,6 +957,11 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
                break;
 
+       case IOCPF_E_SEM_ERROR:
+               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+               bfa_ioc_pf_hwfailed(ioc);
+               break;
+
        case IOCPF_E_FAIL:
                break;
 
@@ -951,7 +987,6 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event)
 
        switch (event) {
        case IOCPF_E_ENABLE:
-               iocpf->retry_count = 0;
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
                break;
 
@@ -982,20 +1017,15 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
        switch (event) {
        case IOCPF_E_SEMLOCKED:
                bfa_ioc_notify_fail(ioc);
-               bfa_ioc_sync_ack(ioc);
-               iocpf->retry_count++;
-               if (iocpf->retry_count >= BFA_IOC_HWINIT_MAX) {
-                       bfa_ioc_sync_leave(ioc);
-                       bfa_nw_ioc_hw_sem_release(ioc);
-                       bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
-               } else {
-                       if (bfa_ioc_sync_complete(ioc))
-                               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
-                       else {
-                               bfa_nw_ioc_hw_sem_release(ioc);
-                               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
-                       }
-               }
+               bfa_ioc_sync_leave(ioc);
+               writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+               bfa_nw_ioc_hw_sem_release(ioc);
+               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+               break;
+
+       case IOCPF_E_SEM_ERROR:
+               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+               bfa_ioc_pf_hwfailed(ioc);
                break;
 
        case IOCPF_E_DISABLE:
@@ -1020,7 +1050,6 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_initfail_entry(struct bfa_iocpf *iocpf)
 {
-       bfa_ioc_pf_initfailed(iocpf->ioc);
 }
 
 /**
@@ -1071,11 +1100,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 
        switch (event) {
        case IOCPF_E_SEMLOCKED:
-               iocpf->retry_count = 0;
                bfa_ioc_sync_ack(ioc);
                bfa_ioc_notify_fail(ioc);
                if (!iocpf->auto_recover) {
                        bfa_ioc_sync_leave(ioc);
+                       writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
                        bfa_nw_ioc_hw_sem_release(ioc);
                        bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
                } else {
@@ -1088,6 +1117,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
                }
                break;
 
+       case IOCPF_E_SEM_ERROR:
+               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+               bfa_ioc_pf_hwfailed(ioc);
+               break;
+
        case IOCPF_E_DISABLE:
                bfa_ioc_hw_sem_get_cancel(ioc);
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -1158,13 +1192,13 @@ bfa_nw_ioc_sem_get(void __iomem *sem_reg)
 
        r32 = readl(sem_reg);
 
-       while (r32 && (cnt < BFA_SEM_SPINCNT)) {
+       while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) {
                cnt++;
                udelay(2);
                r32 = readl(sem_reg);
        }
 
-       if (r32 == 0)
+       if (!(r32 & 1))
                return true;
 
        BUG_ON(!(cnt < BFA_SEM_SPINCNT));
@@ -1210,7 +1244,11 @@ bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
         * will return 1. Semaphore is released by writing 1 to the register
         */
        r32 = readl(ioc->ioc_regs.ioc_sem_reg);
-       if (r32 == 0) {
+       if (r32 == ~0) {
+               bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR);
+               return;
+       }
+       if (!(r32 & 1)) {
                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
                return;
        }
@@ -1331,7 +1369,7 @@ bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
        int i;
 
        drv_fwhdr = (struct bfi_ioc_image_hdr *)
-               bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+               bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
 
        for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
                if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i])
@@ -1352,12 +1390,12 @@ bfa_ioc_fwver_valid(struct bfa_ioc *ioc, u32 boot_env)
 
        bfa_nw_ioc_fwver_get(ioc, &fwhdr);
        drv_fwhdr = (struct bfi_ioc_image_hdr *)
-               bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+               bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
 
        if (fwhdr.signature != drv_fwhdr->signature)
                return false;
 
-       if (swab32(fwhdr.param) != boot_env)
+       if (swab32(fwhdr.bootenv) != boot_env)
                return false;
 
        return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr);
@@ -1388,11 +1426,11 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
 
        ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
 
-       boot_env = BFI_BOOT_LOADER_OS;
-
        if (force)
                ioc_fwstate = BFI_IOC_UNINIT;
 
+       boot_env = BFI_FWBOOT_ENV_OS;
+
        /**
         * check if firmware is valid
         */
@@ -1400,7 +1438,8 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
                false : bfa_ioc_fwver_valid(ioc, boot_env);
 
        if (!fwvalid) {
-               bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env);
+               bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env);
+               bfa_ioc_poll_fwinit(ioc);
                return;
        }
 
@@ -1409,7 +1448,7 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
         * just wait for an initialization completion interrupt.
         */
        if (ioc_fwstate == BFI_IOC_INITING) {
-               ioc->cbfn->reset_cbfn(ioc->bfa);
+               bfa_ioc_poll_fwinit(ioc);
                return;
        }
 
@@ -1423,7 +1462,6 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
                 * be flushed. Otherwise MSI-X interrupts are not delivered.
                 */
                bfa_ioc_msgflush(ioc);
-               ioc->cbfn->reset_cbfn(ioc->bfa);
                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
                return;
        }
@@ -1431,7 +1469,8 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
        /**
         * Initialize the h/w for any other states.
         */
-       bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env);
+       bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env);
+       bfa_ioc_poll_fwinit(ioc);
 }
 
 void
@@ -1475,7 +1514,7 @@ bfa_ioc_send_enable(struct bfa_ioc *ioc)
 
        bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
                    bfa_ioc_portid(ioc));
-       enable_req.ioc_class = ioc->ioc_mc;
+       enable_req.clscode = htons(ioc->clscode);
        do_gettimeofday(&tv);
        enable_req.tv_sec = ntohl(tv.tv_sec);
        bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req));
@@ -1548,22 +1587,23 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
        u32 loff = 0;
        u32 chunkno = 0;
        u32 i;
+       u32 asicmode;
 
        /**
         * Initialize LMEM first before code download
         */
        bfa_ioc_lmem_init(ioc);
 
-       fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
+       fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
 
        pgnum = bfa_ioc_smem_pgnum(ioc, loff);
 
        writel(pgnum, ioc->ioc_regs.host_page_num_fn);
 
-       for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
+       for (i = 0; i < bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); i++) {
                if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
                        chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
-                       fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
+                       fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),
                                        BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
                }
 
@@ -1590,12 +1630,16 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
                      ioc->ioc_regs.host_page_num_fn);
 
        /*
-        * Set boot type and boot param at the end.
+        * Set boot type, env and device mode at the end.
        */
+       asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
+                                       ioc->port0_mode, ioc->port1_mode);
+       writel(asicmode, ((ioc->ioc_regs.smem_page_start)
+                       + BFI_FWBOOT_DEVMODE_OFF));
        writel(boot_type, ((ioc->ioc_regs.smem_page_start)
-                       + (BFI_BOOT_TYPE_OFF)));
+                       + (BFI_FWBOOT_TYPE_OFF)));
        writel(boot_env, ((ioc->ioc_regs.smem_page_start)
-                       + (BFI_BOOT_LOADER_OFF)));
+                       + (BFI_FWBOOT_ENV_OFF)));
 }
 
 static void
@@ -1604,6 +1648,20 @@ bfa_ioc_reset(struct bfa_ioc *ioc, bool force)
        bfa_ioc_hwinit(ioc, force);
 }
 
+/**
+ * BFA ioc enable reply by firmware
+ */
+static void
+bfa_ioc_enable_reply(struct bfa_ioc *ioc, enum bfa_mode port_mode,
+                       u8 cap_bm)
+{
+       struct bfa_iocpf *iocpf = &ioc->iocpf;
+
+       ioc->port_mode = ioc->port_mode_cfg = port_mode;
+       ioc->ad_cap_bm = cap_bm;
+       bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
+}
+
 /**
  * @brief
  * Update BFA configuration from firmware configuration.
@@ -1644,7 +1702,9 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
 {
        struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
        struct bfa_mbox_cmd *cmd;
-       u32                     stat;
+       bfa_mbox_cmd_cbfn_t cbfn;
+       void *cbarg;
+       u32 stat;
 
        /**
         * If no command pending, do nothing
@@ -1664,6 +1724,16 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
         */
        bfa_q_deq(&mod->cmd_q, &cmd);
        bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+
+       /**
+        * Give a callback to the client, indicating that the command is sent
+        */
+       if (cmd->cbfn) {
+               cbfn = cmd->cbfn;
+               cbarg = cmd->cbarg;
+               cmd->cbfn = NULL;
+               cbfn(cbarg);
+       }
 }
 
 /**
@@ -1702,15 +1772,15 @@ bfa_ioc_pf_disabled(struct bfa_ioc *ioc)
 }
 
 static void
-bfa_ioc_pf_initfailed(struct bfa_ioc *ioc)
+bfa_ioc_pf_failed(struct bfa_ioc *ioc)
 {
-       bfa_fsm_send_event(ioc, IOC_E_INITFAILED);
+       bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
 }
 
 static void
-bfa_ioc_pf_failed(struct bfa_ioc *ioc)
+bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc)
 {
-       bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+       bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
 }
 
 static void
@@ -1749,10 +1819,9 @@ bfa_ioc_pll_init(struct bfa_ioc *ioc)
  * as the entry vector.
  */
 static void
-bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_env)
+bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
+               u32 boot_env)
 {
-       void __iomem *rb;
-
        bfa_ioc_stats(ioc, ioc_boots);
 
        if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
@@ -1761,22 +1830,16 @@ bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_env)
        /**
         * Initialize IOC state of all functions on a chip reset.
         */
-       rb = ioc->pcidev.pci_bar_kva;
-       if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
-               writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
-               writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
+       if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {
+               writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate);
+               writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate);
        } else {
-               writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG));
-               writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG));
+               writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate);
+               writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate);
        }
 
        bfa_ioc_msgflush(ioc);
        bfa_ioc_download_fw(ioc, boot_type, boot_env);
-
-       /**
-        * Enable interrupts just before starting LPU
-        */
-       ioc->cbfn->reset_cbfn(ioc->bfa);
        bfa_ioc_lpu_start(ioc);
 }
 
@@ -1789,13 +1852,17 @@ bfa_nw_ioc_auto_recover(bool auto_recover)
        bfa_nw_auto_recover = auto_recover;
 }
 
-static void
+static bool
 bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg)
 {
        u32     *msgp = mbmsg;
        u32     r32;
        int             i;
 
+       r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
+       if ((r32 & 1) == 0)
+               return false;
+
        /**
         * read the MBOX msg
         */
@@ -1811,6 +1878,8 @@ bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg)
         */
        writel(1, ioc->ioc_regs.lpu_mbox_cmd);
        readl(ioc->ioc_regs.lpu_mbox_cmd);
+
+       return true;
 }
 
 static void
@@ -1827,12 +1896,10 @@ bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
        case BFI_IOC_I2H_HBEAT:
                break;
 
-       case BFI_IOC_I2H_READY_EVENT:
-               bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
-               break;
-
        case BFI_IOC_I2H_ENABLE_REPLY:
-               bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
+               bfa_ioc_enable_reply(ioc,
+                       (enum bfa_mode)msg->fw_event.port_mode,
+                       msg->fw_event.cap_bm);
                break;
 
        case BFI_IOC_I2H_DISABLE_REPLY:
@@ -1878,6 +1945,9 @@ void
 bfa_nw_ioc_detach(struct bfa_ioc *ioc)
 {
        bfa_fsm_send_event(ioc, IOC_E_DETACH);
+
+       /* Done with detach, empty the notify_q. */
+       INIT_LIST_HEAD(&ioc->notify_q);
 }
 
 /**
@@ -1887,12 +1957,29 @@ bfa_nw_ioc_detach(struct bfa_ioc *ioc)
  */
 void
 bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
-                enum bfi_mclass mc)
+                enum bfi_pcifn_class clscode)
 {
-       ioc->ioc_mc     = mc;
+       ioc->clscode    = clscode;
        ioc->pcidev     = *pcidev;
-       ioc->ctdev      = bfa_asic_id_ct(ioc->pcidev.device_id);
-       ioc->cna        = ioc->ctdev && !ioc->fcmode;
+
+       /**
+        * Initialize IOC and device personality
+        */
+       ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_FC;
+       ioc->asic_mode  = BFI_ASIC_MODE_FC;
+
+       switch (pcidev->device_id) {
+       case PCI_DEVICE_ID_BROCADE_CT:
+               ioc->asic_gen = BFI_ASIC_GEN_CT;
+               ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
+               ioc->asic_mode  = BFI_ASIC_MODE_ETH;
+               ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_CNA;
+               ioc->ad_cap_bm = BFA_CM_CNA;
+               break;
+
+       default:
+               BUG_ON(1);
+       }
 
        bfa_nw_ioc_set_ct_hwif(ioc);
 
@@ -1968,18 +2055,22 @@ bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
  * @param[in]  ioc     IOC instance
  * @param[i]   cmd     Mailbox command
  */
-void
-bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
+bool
+bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd,
+                       bfa_mbox_cmd_cbfn_t cbfn, void *cbarg)
 {
        struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
        u32                     stat;
 
+       cmd->cbfn = cbfn;
+       cmd->cbarg = cbarg;
+
        /**
         * If a previous command is pending, queue new command
         */
        if (!list_empty(&mod->cmd_q)) {
                list_add_tail(&cmd->qe, &mod->cmd_q);
-               return;
+               return true;
        }
 
        /**
@@ -1988,7 +2079,7 @@ bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
        stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
        if (stat) {
                list_add_tail(&cmd->qe, &mod->cmd_q);
-               return;
+               return true;
        }
 
        /**
@@ -1996,7 +2087,7 @@ bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
         */
        bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
 
-       return;
+       return false;
 }
 
 /**
@@ -2009,21 +2100,28 @@ bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)
        struct bfi_mbmsg m;
        int                             mc;
 
-       bfa_ioc_msgget(ioc, &m);
+       if (bfa_ioc_msgget(ioc, &m)) {
+               /**
+                * Treat IOC message class as special.
+                */
+               mc = m.mh.msg_class;
+               if (mc == BFI_MC_IOC) {
+                       bfa_ioc_isr(ioc, &m);
+                       return;
+               }
 
-       /**
-        * Treat IOC message class as special.
-        */
-       mc = m.mh.msg_class;
-       if (mc == BFI_MC_IOC) {
-               bfa_ioc_isr(ioc, &m);
-               return;
+               if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
+                       return;
+
+               mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
        }
 
-       if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
-               return;
+       bfa_ioc_lpu_read_stat(ioc);
 
-       mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
+       /**
+        * Try to send pending mailbox commands
+        */
+       bfa_ioc_mbox_poll(ioc);
 }
 
 void
@@ -2095,24 +2193,18 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc,
        ad_attr->asic_rev = ioc_attr->asic_rev;
 
        bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
-
-       ad_attr->cna_capable = ioc->cna;
-       ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
 }
 
 static enum bfa_ioc_type
 bfa_ioc_get_type(struct bfa_ioc *ioc)
 {
-       if (!ioc->ctdev || ioc->fcmode)
-               return BFA_IOC_TYPE_FC;
-       else if (ioc->ioc_mc == BFI_MC_IOCFC)
-               return BFA_IOC_TYPE_FCoE;
-       else if (ioc->ioc_mc == BFI_MC_LL)
-               return BFA_IOC_TYPE_LL;
-       else {
-               BUG_ON(!(ioc->ioc_mc == BFI_MC_LL));
+       if (ioc->clscode == BFI_PCIFN_CLASS_ETH)
                return BFA_IOC_TYPE_LL;
-       }
+
+       BUG_ON(!(ioc->clscode == BFI_PCIFN_CLASS_FC));
+
+       return (ioc->attr->port_mode == BFI_PORT_MODE_FC)
+               ? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;
 }
 
 static void
@@ -2224,6 +2316,10 @@ bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr)
 
        ioc_attr->state = bfa_ioc_get_state(ioc);
        ioc_attr->port_id = ioc->port_id;
+       ioc_attr->port_mode = ioc->port_mode;
+
+       ioc_attr->port_mode_cfg = ioc->port_mode_cfg;
+       ioc_attr->cap_bm = ioc->ad_cap_bm;
 
        ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
 
@@ -2313,8 +2409,14 @@ void
 bfa_nw_iocpf_timeout(void *ioc_arg)
 {
        struct bfa_ioc  *ioc = (struct bfa_ioc *) ioc_arg;
+       enum bfa_iocpf_state iocpf_st;
+
+       iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
 
-       bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
+       if (iocpf_st == BFA_IOCPF_HWINIT)
+               bfa_ioc_poll_fwinit(ioc);
+       else
+               bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
 }
 
 void
@@ -2324,3 +2426,22 @@ bfa_nw_iocpf_sem_timeout(void *ioc_arg)
 
        bfa_ioc_hw_sem_get(ioc);
 }
+
+static void
+bfa_ioc_poll_fwinit(struct bfa_ioc *ioc)
+{
+       u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+       if (fwstate == BFI_IOC_DISABLED) {
+               bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
+               return;
+       }
+
+       if (ioc->iocpf.poll_time >= BFA_IOC_TOV) {
+               bfa_nw_iocpf_timeout(ioc);
+       } else {
+               ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
+               mod_timer(&ioc->iocpf_timer, jiffies +
+                       msecs_to_jiffies(BFA_IOC_POLL_TOV));
+       }
+}
similarity index 88%
rename from drivers/net/bna/bfa_ioc.h
rename to drivers/net/ethernet/brocade/bna/bfa_ioc.h
index bda866b..f5a3d4e 100644 (file)
@@ -26,7 +26,7 @@
 #define BFA_IOC_TOV            3000    /* msecs */
 #define BFA_IOC_HWSEM_TOV      500     /* msecs */
 #define BFA_IOC_HB_TOV         500     /* msecs */
-#define BFA_IOC_HWINIT_MAX     5
+#define BFA_IOC_POLL_TOV       200     /* msecs */
 
 /**
  * PCI device information required by IOC
@@ -169,8 +169,9 @@ struct bfa_ioc_hbfail_notify {
 struct bfa_iocpf {
        bfa_fsm_t               fsm;
        struct bfa_ioc          *ioc;
-       u32                     retry_count;
+       bool                    fw_mismatch_notified;
        bool                    auto_recover;
+       u32                     poll_time;
 };
 
 struct bfa_ioc {
@@ -186,12 +187,10 @@ struct bfa_ioc {
        void                    *dbg_fwsave;
        int                     dbg_fwsave_len;
        bool                    dbg_fwsave_once;
-       enum bfi_mclass         ioc_mc;
+       enum bfi_pcifn_class    clscode;
        struct bfa_ioc_regs     ioc_regs;
        struct bfa_ioc_drv_stats stats;
        bool                    fcmode;
-       bool                    ctdev;
-       bool                    cna;
        bool                    pllinit;
        bool                    stats_busy;     /*!< outstanding stats */
        u8                      port_id;
@@ -202,10 +201,18 @@ struct bfa_ioc {
        struct bfa_ioc_mbox_mod mbox_mod;
        struct bfa_ioc_hwif     *ioc_hwif;
        struct bfa_iocpf        iocpf;
+       enum bfi_asic_gen       asic_gen;
+       enum bfi_asic_mode      asic_mode;
+       enum bfi_port_mode      port0_mode;
+       enum bfi_port_mode      port1_mode;
+       enum bfa_mode           port_mode;
+       u8                      ad_cap_bm;      /*!< adapter cap bit mask */
+       u8                      port_mode_cfg;  /*!< config port mode */
 };
 
 struct bfa_ioc_hwif {
-       enum bfa_status (*ioc_pll_init) (void __iomem *rb, bool fcmode);
+       enum bfa_status (*ioc_pll_init) (void __iomem *rb,
+                                               enum bfi_asic_mode m);
        bool            (*ioc_firmware_lock)    (struct bfa_ioc *ioc);
        void            (*ioc_firmware_unlock)  (struct bfa_ioc *ioc);
        void            (*ioc_reg_init) (struct bfa_ioc *ioc);
@@ -219,12 +226,14 @@ struct bfa_ioc_hwif {
        void            (*ioc_sync_leave)       (struct bfa_ioc *ioc);
        void            (*ioc_sync_ack)         (struct bfa_ioc *ioc);
        bool            (*ioc_sync_complete)    (struct bfa_ioc *ioc);
+       bool            (*ioc_lpu_read_stat)    (struct bfa_ioc *ioc);
 };
 
 #define bfa_ioc_pcifn(__ioc)           ((__ioc)->pcidev.pci_func)
 #define bfa_ioc_devid(__ioc)           ((__ioc)->pcidev.device_id)
 #define bfa_ioc_bar0(__ioc)            ((__ioc)->pcidev.pci_bar_kva)
 #define bfa_ioc_portid(__ioc)          ((__ioc)->port_id)
+#define bfa_ioc_asic_gen(__ioc)                ((__ioc)->asic_gen)
 #define bfa_ioc_fetch_stats(__ioc, __stats) \
                (((__stats)->drv_stats) = (__ioc)->stats)
 #define bfa_ioc_clr_stats(__ioc)       \
@@ -240,12 +249,9 @@ struct bfa_ioc_hwif {
 #define bfa_ioc_stats_hb_count(_ioc, _hb_count)        \
        ((_ioc)->stats.hb_count = (_hb_count))
 #define BFA_IOC_FWIMG_MINSZ    (16 * 1024)
-#define BFA_IOC_FWIMG_TYPE(__ioc)                                      \
-       (((__ioc)->ctdev) ?                                             \
-        (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) :     \
-        BFI_IMAGE_CB_FC)
 #define BFA_IOC_FW_SMEM_SIZE(__ioc)                                    \
-       (((__ioc)->ctdev) ? BFI_SMEM_CT_SIZE : BFI_SMEM_CB_SIZE)
+       ((bfa_ioc_asic_gen(__ioc) == BFI_ASIC_GEN_CB)                   \
+       ? BFI_SMEM_CB_SIZE : BFI_SMEM_CT_SIZE)
 #define BFA_IOC_FLASH_CHUNK_NO(off)            (off / BFI_FLASH_CHUNK_SZ_WORDS)
 #define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off)     (off % BFI_FLASH_CHUNK_SZ_WORDS)
 #define BFA_IOC_FLASH_CHUNK_ADDR(chunkno)  (chunkno * BFI_FLASH_CHUNK_SZ_WORDS)
@@ -253,7 +259,9 @@ struct bfa_ioc_hwif {
 /**
  * IOC mailbox interface
  */
-void bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd);
+bool bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc,
+                       struct bfa_mbox_cmd *cmd,
+                       bfa_mbox_cmd_cbfn_t cbfn, void *cbarg);
 void bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc);
 void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
                bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg);
@@ -264,13 +272,18 @@ void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
 
 #define bfa_ioc_pll_init_asic(__ioc) \
        ((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \
-                          (__ioc)->fcmode))
+                          (__ioc)->asic_mode))
 
 #define        bfa_ioc_isr_mode_set(__ioc, __msix)                     \
                        ((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix))
 #define        bfa_ioc_ownership_reset(__ioc)                          \
                        ((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
 
+#define bfa_ioc_lpu_read_stat(__ioc) do {                              \
+               if ((__ioc)->ioc_hwif->ioc_lpu_read_stat)               \
+                       ((__ioc)->ioc_hwif->ioc_lpu_read_stat(__ioc));  \
+} while (0)
+
 void bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc);
 
 void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa,
@@ -278,7 +291,7 @@ void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa,
 void bfa_nw_ioc_auto_recover(bool auto_recover);
 void bfa_nw_ioc_detach(struct bfa_ioc *ioc);
 void bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
-               enum bfi_mclass mc);
+               enum bfi_pcifn_class clscode);
 u32 bfa_nw_ioc_meminfo(void);
 void bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc,  u8 *dm_kva, u64 dm_pa);
 void bfa_nw_ioc_enable(struct bfa_ioc *ioc);
@@ -309,7 +322,7 @@ void bfa_nw_iocpf_sem_timeout(void *ioc);
 /*
  * F/W Image Size & Chunk
  */
-u32 *bfa_cb_image_get_chunk(int type, u32 off);
-u32 bfa_cb_image_get_size(int type);
+u32 *bfa_cb_image_get_chunk(enum bfi_asic_gen asic_gen, u32 off);
+u32 bfa_cb_image_get_size(enum bfi_asic_gen asic_gen);
 
 #endif /* __BFA_IOC_H__ */
similarity index 76%
rename from drivers/net/bna/bfa_ioc_ct.c
rename to drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c
index 87aecdf..b4429bc 100644 (file)
@@ -19,7 +19,7 @@
 #include "bfa_ioc.h"
 #include "cna.h"
 #include "bfi.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
 #include "bfa_defs.h"
 
 #define bfa_ioc_ct_sync_pos(__ioc)     \
@@ -46,30 +46,37 @@ static void bfa_ioc_ct_sync_join(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc);
 static bool bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc);
-static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode);
+static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb,
+                               enum bfi_asic_mode asic_mode);
 
 static struct bfa_ioc_hwif nw_hwif_ct;
 
+static void
+bfa_ioc_set_ctx_hwif(struct bfa_ioc *ioc, struct bfa_ioc_hwif *hwif)
+{
+       hwif->ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
+       hwif->ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
+       hwif->ioc_notify_fail = bfa_ioc_ct_notify_fail;
+       hwif->ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+       hwif->ioc_sync_start = bfa_ioc_ct_sync_start;
+       hwif->ioc_sync_join = bfa_ioc_ct_sync_join;
+       hwif->ioc_sync_leave = bfa_ioc_ct_sync_leave;
+       hwif->ioc_sync_ack = bfa_ioc_ct_sync_ack;
+       hwif->ioc_sync_complete = bfa_ioc_ct_sync_complete;
+}
+
 /**
  * Called from bfa_ioc_attach() to map asic specific calls.
  */
 void
 bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc)
 {
+       bfa_ioc_set_ctx_hwif(ioc, &nw_hwif_ct);
+
        nw_hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
-       nw_hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
-       nw_hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
        nw_hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
        nw_hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
        nw_hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
-       nw_hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail;
-       nw_hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
-       nw_hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start;
-       nw_hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
-       nw_hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
-       nw_hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
-       nw_hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete;
-
        ioc->ioc_hwif = &nw_hwif_ct;
 }
 
@@ -83,16 +90,10 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc)
        u32 usecnt;
        struct bfi_ioc_image_hdr fwhdr;
 
-       /**
-        * Firmware match check is relevant only for CNA.
-        */
-       if (!ioc->cna)
-               return true;
-
        /**
         * If bios boot (flash based) -- do not increment usage count
         */
-       if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+       if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) <
                                                BFA_IOC_FWIMG_MINSZ)
                return true;
 
@@ -139,16 +140,10 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc)
 {
        u32 usecnt;
 
-       /**
-        * Firmware lock is relevant only for CNA.
-        */
-       if (!ioc->cna)
-               return;
-
        /**
         * If bios boot (flash based) -- do not decrement usage count
         */
-       if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+       if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) <
                                                BFA_IOC_FWIMG_MINSZ)
                return;
 
@@ -171,22 +166,17 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc)
 static void
 bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc)
 {
-       if (ioc->cna) {
-               writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
-               writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt);
-               /* Wait for halt to take effect */
-               readl(ioc->ioc_regs.ll_halt);
-               readl(ioc->ioc_regs.alt_ll_halt);
-       } else {
-               writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
-               readl(ioc->ioc_regs.err_set);
-       }
+       writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
+       writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt);
+       /* Wait for halt to take effect */
+       readl(ioc->ioc_regs.ll_halt);
+       readl(ioc->ioc_regs.alt_ll_halt);
 }
 
 /**
  * Host to LPU mailbox message addresses
  */
-static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
+static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } ct_fnreg[] = {
        { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
        { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
        { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 },
@@ -196,21 +186,21 @@ static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
 /**
  * Host <-> LPU mailbox command/status registers - port 0
  */
-static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = {
-       { HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT },
-       { HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT },
-       { HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT },
-       { HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT }
+static struct { u32 hfn, lpu; } ct_p0reg[] = {
+       { HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT },
+       { HOSTFN1_LPU0_CMD_STAT, LPU0_HOSTFN1_CMD_STAT },
+       { HOSTFN2_LPU0_CMD_STAT, LPU0_HOSTFN2_CMD_STAT },
+       { HOSTFN3_LPU0_CMD_STAT, LPU0_HOSTFN3_CMD_STAT }
 };
 
 /**
  * Host <-> LPU mailbox command/status registers - port 1
  */
-static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = {
-       { HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT },
-       { HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT },
-       { HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT },
-       { HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT }
+static struct { u32 hfn, lpu; } ct_p1reg[] = {
+       { HOSTFN0_LPU1_CMD_STAT, LPU1_HOSTFN0_CMD_STAT },
+       { HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT },
+       { HOSTFN2_LPU1_CMD_STAT, LPU1_HOSTFN2_CMD_STAT },
+       { HOSTFN3_LPU1_CMD_STAT, LPU1_HOSTFN3_CMD_STAT }
 };
 
 static void
@@ -221,24 +211,24 @@ bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
 
        rb = bfa_ioc_bar0(ioc);
 
-       ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
-       ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
-       ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
+       ioc->ioc_regs.hfn_mbox = rb + ct_fnreg[pcifn].hfn_mbox;
+       ioc->ioc_regs.lpu_mbox = rb + ct_fnreg[pcifn].lpu_mbox;
+       ioc->ioc_regs.host_page_num_fn = rb + ct_fnreg[pcifn].hfn_pgn;
 
        if (ioc->port_id == 0) {
                ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
                ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
                ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
-               ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
-               ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
+               ioc->ioc_regs.hfn_mbox_cmd = rb + ct_p0reg[pcifn].hfn;
+               ioc->ioc_regs.lpu_mbox_cmd = rb + ct_p0reg[pcifn].lpu;
                ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
                ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
        } else {
                ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
                ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
                ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG;
-               ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
-               ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
+               ioc->ioc_regs.hfn_mbox_cmd = rb + ct_p1reg[pcifn].hfn;
+               ioc->ioc_regs.lpu_mbox_cmd = rb + ct_p1reg[pcifn].lpu;
                ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
                ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
        }
@@ -248,8 +238,8 @@ bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
         */
        ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
        ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
-       ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG);
-       ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG);
+       ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_LCLK_CTL_REG);
+       ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_SCLK_CTL_REG);
 
        /*
         * IOC semaphore registers and serialization
@@ -309,7 +299,7 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix)
        /**
         * If already in desired mode, do not change anything
         */
-       if (!msix && mode)
+       if ((!msix && mode) || (msix && !mode))
                return;
 
        if (msix)
@@ -329,11 +319,9 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix)
 static void
 bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc)
 {
-       if (ioc->cna) {
-               bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
-               writel(0, ioc->ioc_regs.ioc_usage_reg);
-               bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
-       }
+       bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+       writel(0, ioc->ioc_regs.ioc_usage_reg);
+       bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
 
        /*
         * Read the hw sem reg to make sure that it is locked
@@ -442,18 +430,20 @@ bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc)
 }
 
 static enum bfa_status
-bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode)
+bfa_ioc_ct_pll_init(void __iomem *rb, enum bfi_asic_mode asic_mode)
 {
        u32     pll_sclk, pll_fclk, r32;
+       bool fcmode = (asic_mode == BFI_ASIC_MODE_FC);
+
+       pll_sclk = __APP_PLL_SCLK_LRESETN | __APP_PLL_SCLK_ENARST |
+               __APP_PLL_SCLK_RSEL200500 | __APP_PLL_SCLK_P0_1(3U) |
+               __APP_PLL_SCLK_JITLMT0_1(3U) |
+               __APP_PLL_SCLK_CNTLMT0_1(1U);
+       pll_fclk = __APP_PLL_LCLK_LRESETN | __APP_PLL_LCLK_ENARST |
+               __APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) |
+               __APP_PLL_LCLK_JITLMT0_1(3U) |
+               __APP_PLL_LCLK_CNTLMT0_1(1U);
 
-       pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
-               __APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
-               __APP_PLL_312_JITLMT0_1(3U) |
-               __APP_PLL_312_CNTLMT0_1(1U);
-       pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST |
-               __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
-               __APP_PLL_425_JITLMT0_1(3U) |
-               __APP_PLL_425_CNTLMT0_1(1U);
        if (fcmode) {
                writel(0, (rb + OP_MODE));
                writel(__APP_EMS_CMLCKSEL |
@@ -474,27 +464,28 @@ bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode)
        writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
        writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
        writel(pll_sclk |
-               __APP_PLL_312_LOGIC_SOFT_RESET,
-               rb + APP_PLL_312_CTL_REG);
+               __APP_PLL_SCLK_LOGIC_SOFT_RESET,
+               rb + APP_PLL_SCLK_CTL_REG);
        writel(pll_fclk |
-               __APP_PLL_425_LOGIC_SOFT_RESET,
-               rb + APP_PLL_425_CTL_REG);
+               __APP_PLL_LCLK_LOGIC_SOFT_RESET,
+               rb + APP_PLL_LCLK_CTL_REG);
        writel(pll_sclk |
-               __APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE,
-               rb + APP_PLL_312_CTL_REG);
+               __APP_PLL_SCLK_LOGIC_SOFT_RESET | __APP_PLL_SCLK_ENABLE,
+               rb + APP_PLL_SCLK_CTL_REG);
        writel(pll_fclk |
-               __APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE,
-               rb + APP_PLL_425_CTL_REG);
+               __APP_PLL_LCLK_LOGIC_SOFT_RESET | __APP_PLL_LCLK_ENABLE,
+               rb + APP_PLL_LCLK_CTL_REG);
        readl(rb + HOSTFN0_INT_MSK);
        udelay(2000);
        writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
        writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
        writel(pll_sclk |
-               __APP_PLL_312_ENABLE,
-               rb + APP_PLL_312_CTL_REG);
+               __APP_PLL_SCLK_ENABLE,
+               rb + APP_PLL_SCLK_CTL_REG);
        writel(pll_fclk |
-               __APP_PLL_425_ENABLE,
-               rb + APP_PLL_425_CTL_REG);
+               __APP_PLL_LCLK_ENABLE,
+               rb + APP_PLL_LCLK_CTL_REG);
+
        if (!fcmode) {
                writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0));
                writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1));
diff --git a/drivers/net/ethernet/brocade/bna/bfa_msgq.c b/drivers/net/ethernet/brocade/bna/bfa_msgq.c
new file mode 100644 (file)
index 0000000..dd36427
--- /dev/null
@@ -0,0 +1,669 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.
+ */
+/*
+ * Copyright (c) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/**
+ * @file bfa_msgq.c MSGQ module source file.
+ */
+
+#include "bfi.h"
+#include "bfa_msgq.h"
+#include "bfa_ioc.h"
+
+#define call_cmdq_ent_cbfn(_cmdq_ent, _status)                         \
+{                                                                      \
+       bfa_msgq_cmdcbfn_t cbfn;                                        \
+       void *cbarg;                                                    \
+       cbfn = (_cmdq_ent)->cbfn;                                       \
+       cbarg = (_cmdq_ent)->cbarg;                                     \
+       (_cmdq_ent)->cbfn = NULL;                                       \
+       (_cmdq_ent)->cbarg = NULL;                                      \
+       if (cbfn) {                                                     \
+               cbfn(cbarg, (_status));                                 \
+       }                                                               \
+}
+
+static void bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq *cmdq);
+static void bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq);
+
+enum cmdq_event {
+       CMDQ_E_START                    = 1,
+       CMDQ_E_STOP                     = 2,
+       CMDQ_E_FAIL                     = 3,
+       CMDQ_E_POST                     = 4,
+       CMDQ_E_INIT_RESP                = 5,
+       CMDQ_E_DB_READY                 = 6,
+};
+
+bfa_fsm_state_decl(cmdq, stopped, struct bfa_msgq_cmdq, enum cmdq_event);
+bfa_fsm_state_decl(cmdq, init_wait, struct bfa_msgq_cmdq, enum cmdq_event);
+bfa_fsm_state_decl(cmdq, ready, struct bfa_msgq_cmdq, enum cmdq_event);
+bfa_fsm_state_decl(cmdq, dbell_wait, struct bfa_msgq_cmdq,
+                       enum cmdq_event);
+
+static void
+cmdq_sm_stopped_entry(struct bfa_msgq_cmdq *cmdq)
+{
+       struct bfa_msgq_cmd_entry *cmdq_ent;
+
+       cmdq->producer_index = 0;
+       cmdq->consumer_index = 0;
+       cmdq->flags = 0;
+       cmdq->token = 0;
+       cmdq->offset = 0;
+       cmdq->bytes_to_copy = 0;
+       while (!list_empty(&cmdq->pending_q)) {
+               bfa_q_deq(&cmdq->pending_q, &cmdq_ent);
+               bfa_q_qe_init(&cmdq_ent->qe);
+               call_cmdq_ent_cbfn(cmdq_ent, BFA_STATUS_FAILED);
+       }
+}
+
+static void
+cmdq_sm_stopped(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
+{
+       switch (event) {
+       case CMDQ_E_START:
+               bfa_fsm_set_state(cmdq, cmdq_sm_init_wait);
+               break;
+
+       case CMDQ_E_STOP:
+       case CMDQ_E_FAIL:
+               /* No-op */
+               break;
+
+       case CMDQ_E_POST:
+               cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+cmdq_sm_init_wait_entry(struct bfa_msgq_cmdq *cmdq)
+{
+       bfa_wc_down(&cmdq->msgq->init_wc);
+}
+
+static void
+cmdq_sm_init_wait(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
+{
+       switch (event) {
+       case CMDQ_E_STOP:
+       case CMDQ_E_FAIL:
+               bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
+               break;
+
+       case CMDQ_E_POST:
+               cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
+               break;
+
+       case CMDQ_E_INIT_RESP:
+               if (cmdq->flags & BFA_MSGQ_CMDQ_F_DB_UPDATE) {
+                       cmdq->flags &= ~BFA_MSGQ_CMDQ_F_DB_UPDATE;
+                       bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
+               } else
+                       bfa_fsm_set_state(cmdq, cmdq_sm_ready);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+cmdq_sm_ready_entry(struct bfa_msgq_cmdq *cmdq)
+{
+}
+
+static void
+cmdq_sm_ready(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
+{
+       switch (event) {
+       case CMDQ_E_STOP:
+       case CMDQ_E_FAIL:
+               bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
+               break;
+
+       case CMDQ_E_POST:
+               bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+cmdq_sm_dbell_wait_entry(struct bfa_msgq_cmdq *cmdq)
+{
+       bfa_msgq_cmdq_dbell(cmdq);
+}
+
+static void
+cmdq_sm_dbell_wait(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
+{
+       switch (event) {
+       case CMDQ_E_STOP:
+       case CMDQ_E_FAIL:
+               bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
+               break;
+
+       case CMDQ_E_POST:
+               cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
+               break;
+
+       case CMDQ_E_DB_READY:
+               if (cmdq->flags & BFA_MSGQ_CMDQ_F_DB_UPDATE) {
+                       cmdq->flags &= ~BFA_MSGQ_CMDQ_F_DB_UPDATE;
+                       bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
+               } else
+                       bfa_fsm_set_state(cmdq, cmdq_sm_ready);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bfa_msgq_cmdq_dbell_ready(void *arg)
+{
+       struct bfa_msgq_cmdq *cmdq = (struct bfa_msgq_cmdq *)arg;
+       bfa_fsm_send_event(cmdq, CMDQ_E_DB_READY);
+}
+
+static void
+bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq *cmdq)
+{
+       struct bfi_msgq_h2i_db *dbell =
+               (struct bfi_msgq_h2i_db *)(&cmdq->dbell_mb.msg[0]);
+
+       memset(dbell, 0, sizeof(struct bfi_msgq_h2i_db));
+       bfi_h2i_set(dbell->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_DOORBELL_PI, 0);
+       dbell->mh.mtag.i2htok = 0;
+       dbell->idx.cmdq_pi = htons(cmdq->producer_index);
+
+       if (!bfa_nw_ioc_mbox_queue(cmdq->msgq->ioc, &cmdq->dbell_mb,
+                               bfa_msgq_cmdq_dbell_ready, cmdq)) {
+               bfa_msgq_cmdq_dbell_ready(cmdq);
+       }
+}
+
+static void
+__cmd_copy(struct bfa_msgq_cmdq *cmdq, struct bfa_msgq_cmd_entry *cmd)
+{
+       size_t len = cmd->msg_size;
+       int num_entries = 0;
+       size_t to_copy;
+       u8 *src, *dst;
+
+       src = (u8 *)cmd->msg_hdr;
+       dst = (u8 *)cmdq->addr.kva;
+       dst += (cmdq->producer_index * BFI_MSGQ_CMD_ENTRY_SIZE);
+
+       while (len) {
+               to_copy = (len < BFI_MSGQ_CMD_ENTRY_SIZE) ?
+                               len : BFI_MSGQ_CMD_ENTRY_SIZE;
+               memcpy(dst, src, to_copy);
+               len -= to_copy;
+               src += BFI_MSGQ_CMD_ENTRY_SIZE;
+               BFA_MSGQ_INDX_ADD(cmdq->producer_index, 1, cmdq->depth);
+               dst = (u8 *)cmdq->addr.kva;
+               dst += (cmdq->producer_index * BFI_MSGQ_CMD_ENTRY_SIZE);
+               num_entries++;
+       }
+
+}
+
+static void
+bfa_msgq_cmdq_ci_update(struct bfa_msgq_cmdq *cmdq, struct bfi_mbmsg *mb)
+{
+       struct bfi_msgq_i2h_db *dbell = (struct bfi_msgq_i2h_db *)mb;
+       struct bfa_msgq_cmd_entry *cmd;
+       int posted = 0;
+
+       cmdq->consumer_index = ntohs(dbell->idx.cmdq_ci);
+
+       /* Walk through pending list to see if the command can be posted */
+       while (!list_empty(&cmdq->pending_q)) {
+               cmd =
+               (struct bfa_msgq_cmd_entry *)bfa_q_first(&cmdq->pending_q);
+               if (ntohs(cmd->msg_hdr->num_entries) <=
+                       BFA_MSGQ_FREE_CNT(cmdq)) {
+                       list_del(&cmd->qe);
+                       __cmd_copy(cmdq, cmd);
+                       posted = 1;
+                       call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
+               } else {
+                       break;
+               }
+       }
+
+       if (posted)
+               bfa_fsm_send_event(cmdq, CMDQ_E_POST);
+}
+
+static void
+bfa_msgq_cmdq_copy_next(void *arg)
+{
+       struct bfa_msgq_cmdq *cmdq = (struct bfa_msgq_cmdq *)arg;
+
+       if (cmdq->bytes_to_copy)
+               bfa_msgq_cmdq_copy_rsp(cmdq);
+}
+
+static void
+bfa_msgq_cmdq_copy_req(struct bfa_msgq_cmdq *cmdq, struct bfi_mbmsg *mb)
+{
+       struct bfi_msgq_i2h_cmdq_copy_req *req =
+               (struct bfi_msgq_i2h_cmdq_copy_req *)mb;
+
+       cmdq->token = 0;
+       cmdq->offset = ntohs(req->offset);
+       cmdq->bytes_to_copy = ntohs(req->len);
+       bfa_msgq_cmdq_copy_rsp(cmdq);
+}
+
+static void
+bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq)
+{
+       struct bfi_msgq_h2i_cmdq_copy_rsp *rsp =
+               (struct bfi_msgq_h2i_cmdq_copy_rsp *)&cmdq->copy_mb.msg[0];
+       int copied;
+       u8 *addr = (u8 *)cmdq->addr.kva;
+
+       memset(rsp, 0, sizeof(struct bfi_msgq_h2i_cmdq_copy_rsp));
+       bfi_h2i_set(rsp->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_CMDQ_COPY_RSP, 0);
+       rsp->mh.mtag.i2htok = htons(cmdq->token);
+       copied = (cmdq->bytes_to_copy >= BFI_CMD_COPY_SZ) ? BFI_CMD_COPY_SZ :
+               cmdq->bytes_to_copy;
+       addr += cmdq->offset;
+       memcpy(rsp->data, addr, copied);
+
+       cmdq->token++;
+       cmdq->offset += copied;
+       cmdq->bytes_to_copy -= copied;
+
+       if (!bfa_nw_ioc_mbox_queue(cmdq->msgq->ioc, &cmdq->copy_mb,
+                               bfa_msgq_cmdq_copy_next, cmdq)) {
+               bfa_msgq_cmdq_copy_next(cmdq);
+       }
+}
+
+static void
+bfa_msgq_cmdq_attach(struct bfa_msgq_cmdq *cmdq, struct bfa_msgq *msgq)
+{
+       cmdq->depth = BFA_MSGQ_CMDQ_NUM_ENTRY;
+       INIT_LIST_HEAD(&cmdq->pending_q);
+       cmdq->msgq = msgq;
+       bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
+}
+
+static void bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq);
+
+enum rspq_event {
+       RSPQ_E_START                    = 1,
+       RSPQ_E_STOP                     = 2,
+       RSPQ_E_FAIL                     = 3,
+       RSPQ_E_RESP                     = 4,
+       RSPQ_E_INIT_RESP                = 5,
+       RSPQ_E_DB_READY                 = 6,
+};
+
+bfa_fsm_state_decl(rspq, stopped, struct bfa_msgq_rspq, enum rspq_event);
+bfa_fsm_state_decl(rspq, init_wait, struct bfa_msgq_rspq,
+                       enum rspq_event);
+bfa_fsm_state_decl(rspq, ready, struct bfa_msgq_rspq, enum rspq_event);
+bfa_fsm_state_decl(rspq, dbell_wait, struct bfa_msgq_rspq,
+                       enum rspq_event);
+
+static void
+rspq_sm_stopped_entry(struct bfa_msgq_rspq *rspq)
+{
+       rspq->producer_index = 0;
+       rspq->consumer_index = 0;
+       rspq->flags = 0;
+}
+
+static void
+rspq_sm_stopped(struct bfa_msgq_rspq *rspq, enum rspq_event event)
+{
+       switch (event) {
+       case RSPQ_E_START:
+               bfa_fsm_set_state(rspq, rspq_sm_init_wait);
+               break;
+
+       case RSPQ_E_STOP:
+       case RSPQ_E_FAIL:
+               /* No-op */
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+rspq_sm_init_wait_entry(struct bfa_msgq_rspq *rspq)
+{
+       bfa_wc_down(&rspq->msgq->init_wc);
+}
+
+static void
+rspq_sm_init_wait(struct bfa_msgq_rspq *rspq, enum rspq_event event)
+{
+       switch (event) {
+       case RSPQ_E_FAIL:
+       case RSPQ_E_STOP:
+               bfa_fsm_set_state(rspq, rspq_sm_stopped);
+               break;
+
+       case RSPQ_E_INIT_RESP:
+               bfa_fsm_set_state(rspq, rspq_sm_ready);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+rspq_sm_ready_entry(struct bfa_msgq_rspq *rspq)
+{
+}
+
+static void
+rspq_sm_ready(struct bfa_msgq_rspq *rspq, enum rspq_event event)
+{
+       switch (event) {
+       case RSPQ_E_STOP:
+       case RSPQ_E_FAIL:
+               bfa_fsm_set_state(rspq, rspq_sm_stopped);
+               break;
+
+       case RSPQ_E_RESP:
+               bfa_fsm_set_state(rspq, rspq_sm_dbell_wait);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+rspq_sm_dbell_wait_entry(struct bfa_msgq_rspq *rspq)
+{
+       if (!bfa_nw_ioc_is_disabled(rspq->msgq->ioc))
+               bfa_msgq_rspq_dbell(rspq);
+}
+
+static void
+rspq_sm_dbell_wait(struct bfa_msgq_rspq *rspq, enum rspq_event event)
+{
+       switch (event) {
+       case RSPQ_E_STOP:
+       case RSPQ_E_FAIL:
+               bfa_fsm_set_state(rspq, rspq_sm_stopped);
+               break;
+
+       case RSPQ_E_RESP:
+               rspq->flags |= BFA_MSGQ_RSPQ_F_DB_UPDATE;
+               break;
+
+       case RSPQ_E_DB_READY:
+               if (rspq->flags & BFA_MSGQ_RSPQ_F_DB_UPDATE) {
+                       rspq->flags &= ~BFA_MSGQ_RSPQ_F_DB_UPDATE;
+                       bfa_fsm_set_state(rspq, rspq_sm_dbell_wait);
+               } else
+                       bfa_fsm_set_state(rspq, rspq_sm_ready);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bfa_msgq_rspq_dbell_ready(void *arg)
+{
+       struct bfa_msgq_rspq *rspq = (struct bfa_msgq_rspq *)arg;
+       bfa_fsm_send_event(rspq, RSPQ_E_DB_READY);
+}
+
+static void
+bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq)
+{
+       struct bfi_msgq_h2i_db *dbell =
+               (struct bfi_msgq_h2i_db *)(&rspq->dbell_mb.msg[0]);
+
+       memset(dbell, 0, sizeof(struct bfi_msgq_h2i_db));
+       bfi_h2i_set(dbell->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_DOORBELL_CI, 0);
+       dbell->mh.mtag.i2htok = 0;
+       dbell->idx.rspq_ci = htons(rspq->consumer_index);
+
+       if (!bfa_nw_ioc_mbox_queue(rspq->msgq->ioc, &rspq->dbell_mb,
+                               bfa_msgq_rspq_dbell_ready, rspq)) {
+               bfa_msgq_rspq_dbell_ready(rspq);
+       }
+}
+
+static void
+bfa_msgq_rspq_pi_update(struct bfa_msgq_rspq *rspq, struct bfi_mbmsg *mb)
+{
+       struct bfi_msgq_i2h_db *dbell = (struct bfi_msgq_i2h_db *)mb;
+       struct bfi_msgq_mhdr *msghdr;
+       int num_entries;
+       int mc;
+       u8 *rspq_qe;
+
+       rspq->producer_index = ntohs(dbell->idx.rspq_pi);
+
+       while (rspq->consumer_index != rspq->producer_index) {
+               rspq_qe = (u8 *)rspq->addr.kva;
+               rspq_qe += (rspq->consumer_index * BFI_MSGQ_RSP_ENTRY_SIZE);
+               msghdr = (struct bfi_msgq_mhdr *)rspq_qe;
+
+               mc = msghdr->msg_class;
+               num_entries = ntohs(msghdr->num_entries);
+
+               if ((mc >= BFI_MC_MAX) || (rspq->rsphdlr[mc].cbfn == NULL))
+                       break;
+
+               (rspq->rsphdlr[mc].cbfn)(rspq->rsphdlr[mc].cbarg, msghdr);
+
+               BFA_MSGQ_INDX_ADD(rspq->consumer_index, num_entries,
+                               rspq->depth);
+       }
+
+       bfa_fsm_send_event(rspq, RSPQ_E_RESP);
+}
+
+static void
+bfa_msgq_rspq_attach(struct bfa_msgq_rspq *rspq, struct bfa_msgq *msgq)
+{
+       rspq->depth = BFA_MSGQ_RSPQ_NUM_ENTRY;
+       rspq->msgq = msgq;
+       bfa_fsm_set_state(rspq, rspq_sm_stopped);
+}
+
+static void
+bfa_msgq_init_rsp(struct bfa_msgq *msgq,
+                struct bfi_mbmsg *mb)
+{
+       bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_INIT_RESP);
+       bfa_fsm_send_event(&msgq->rspq, RSPQ_E_INIT_RESP);
+}
+
+static void
+bfa_msgq_init(void *arg)
+{
+       struct bfa_msgq *msgq = (struct bfa_msgq *)arg;
+       struct bfi_msgq_cfg_req *msgq_cfg =
+               (struct bfi_msgq_cfg_req *)&msgq->init_mb.msg[0];
+
+       memset(msgq_cfg, 0, sizeof(struct bfi_msgq_cfg_req));
+       bfi_h2i_set(msgq_cfg->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_INIT_REQ, 0);
+       msgq_cfg->mh.mtag.i2htok = 0;
+
+       bfa_dma_be_addr_set(msgq_cfg->cmdq.addr, msgq->cmdq.addr.pa);
+       msgq_cfg->cmdq.q_depth = htons(msgq->cmdq.depth);
+       bfa_dma_be_addr_set(msgq_cfg->rspq.addr, msgq->rspq.addr.pa);
+       msgq_cfg->rspq.q_depth = htons(msgq->rspq.depth);
+
+       bfa_nw_ioc_mbox_queue(msgq->ioc, &msgq->init_mb, NULL, NULL);
+}
+
+static void
+bfa_msgq_isr(void *cbarg, struct bfi_mbmsg *msg)
+{
+       struct bfa_msgq *msgq = (struct bfa_msgq *)cbarg;
+
+       switch (msg->mh.msg_id) {
+       case BFI_MSGQ_I2H_INIT_RSP:
+               bfa_msgq_init_rsp(msgq, msg);
+               break;
+
+       case BFI_MSGQ_I2H_DOORBELL_PI:
+               bfa_msgq_rspq_pi_update(&msgq->rspq, msg);
+               break;
+
+       case BFI_MSGQ_I2H_DOORBELL_CI:
+               bfa_msgq_cmdq_ci_update(&msgq->cmdq, msg);
+               break;
+
+       case BFI_MSGQ_I2H_CMDQ_COPY_REQ:
+               bfa_msgq_cmdq_copy_req(&msgq->cmdq, msg);
+               break;
+
+       default:
+               BUG_ON(1);
+       }
+}
+
+static void
+bfa_msgq_notify(void *cbarg, enum bfa_ioc_event event)
+{
+       struct bfa_msgq *msgq = (struct bfa_msgq *)cbarg;
+
+       switch (event) {
+       case BFA_IOC_E_ENABLED:
+               bfa_wc_init(&msgq->init_wc, bfa_msgq_init, msgq);
+               bfa_wc_up(&msgq->init_wc);
+               bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_START);
+               bfa_wc_up(&msgq->init_wc);
+               bfa_fsm_send_event(&msgq->rspq, RSPQ_E_START);
+               bfa_wc_wait(&msgq->init_wc);
+               break;
+
+       case BFA_IOC_E_DISABLED:
+               bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_STOP);
+               bfa_fsm_send_event(&msgq->rspq, RSPQ_E_STOP);
+               break;
+
+       case BFA_IOC_E_FAILED:
+               bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_FAIL);
+               bfa_fsm_send_event(&msgq->rspq, RSPQ_E_FAIL);
+               break;
+
+       default:
+               break;
+       }
+}
+
+u32
+bfa_msgq_meminfo(void)
+{
+       return roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ) +
+               roundup(BFA_MSGQ_RSPQ_SIZE, BFA_DMA_ALIGN_SZ);
+}
+
+void
+bfa_msgq_memclaim(struct bfa_msgq *msgq, u8 *kva, u64 pa)
+{
+       msgq->cmdq.addr.kva = kva;
+       msgq->cmdq.addr.pa  = pa;
+
+       kva += roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ);
+       pa += roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ);
+
+       msgq->rspq.addr.kva = kva;
+       msgq->rspq.addr.pa = pa;
+}
+
+void
+bfa_msgq_attach(struct bfa_msgq *msgq, struct bfa_ioc *ioc)
+{
+       msgq->ioc    = ioc;
+
+       bfa_msgq_cmdq_attach(&msgq->cmdq, msgq);
+       bfa_msgq_rspq_attach(&msgq->rspq, msgq);
+
+       bfa_nw_ioc_mbox_regisr(msgq->ioc, BFI_MC_MSGQ, bfa_msgq_isr, msgq);
+       bfa_q_qe_init(&msgq->ioc_notify);
+       bfa_ioc_notify_init(&msgq->ioc_notify, bfa_msgq_notify, msgq);
+       bfa_nw_ioc_notify_register(msgq->ioc, &msgq->ioc_notify);
+}
+
+void
+bfa_msgq_regisr(struct bfa_msgq *msgq, enum bfi_mclass mc,
+               bfa_msgq_mcfunc_t cbfn, void *cbarg)
+{
+       msgq->rspq.rsphdlr[mc].cbfn     = cbfn;
+       msgq->rspq.rsphdlr[mc].cbarg    = cbarg;
+}
+
+void
+bfa_msgq_cmd_post(struct bfa_msgq *msgq,  struct bfa_msgq_cmd_entry *cmd)
+{
+       if (ntohs(cmd->msg_hdr->num_entries) <=
+               BFA_MSGQ_FREE_CNT(&msgq->cmdq)) {
+               __cmd_copy(&msgq->cmdq, cmd);
+               call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
+               bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_POST);
+       } else {
+               list_add_tail(&cmd->qe, &msgq->cmdq.pending_q);
+       }
+}
+
+void
+bfa_msgq_rsp_copy(struct bfa_msgq *msgq, u8 *buf, size_t buf_len)
+{
+       struct bfa_msgq_rspq *rspq = &msgq->rspq;
+       size_t len = buf_len;
+       size_t to_copy;
+       int ci;
+       u8 *src, *dst;
+
+       ci = rspq->consumer_index;
+       src = (u8 *)rspq->addr.kva;
+       src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
+       dst = buf;
+
+       while (len) {
+               to_copy = (len < BFI_MSGQ_RSP_ENTRY_SIZE) ?
+                               len : BFI_MSGQ_RSP_ENTRY_SIZE;
+               memcpy(dst, src, to_copy);
+               len -= to_copy;
+               dst += BFI_MSGQ_RSP_ENTRY_SIZE;
+               BFA_MSGQ_INDX_ADD(ci, 1, rspq->depth);
+               src = (u8 *)rspq->addr.kva;
+               src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
+       }
+}
diff --git a/drivers/net/ethernet/brocade/bna/bfa_msgq.h b/drivers/net/ethernet/brocade/bna/bfa_msgq.h
new file mode 100644 (file)
index 0000000..a6a565a
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.
+ */
+/*
+ * Copyright (c) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __BFA_MSGQ_H__
+#define __BFA_MSGQ_H__
+
+#include "bfa_defs.h"
+#include "bfi.h"
+#include "bfa_ioc.h"
+#include "bfa_cs.h"
+
+#define BFA_MSGQ_FREE_CNT(_q)                                          \
+       (((_q)->consumer_index - (_q)->producer_index - 1) & ((_q)->depth - 1))
+
+#define BFA_MSGQ_INDX_ADD(_q_indx, _qe_num, _q_depth)                  \
+       ((_q_indx) = (((_q_indx) + (_qe_num)) & ((_q_depth) - 1)))
+
+#define BFA_MSGQ_CMDQ_NUM_ENTRY                128
+#define BFA_MSGQ_CMDQ_SIZE                                             \
+       (BFI_MSGQ_CMD_ENTRY_SIZE * BFA_MSGQ_CMDQ_NUM_ENTRY)
+
+#define BFA_MSGQ_RSPQ_NUM_ENTRY                128
+#define BFA_MSGQ_RSPQ_SIZE                                             \
+       (BFI_MSGQ_RSP_ENTRY_SIZE * BFA_MSGQ_RSPQ_NUM_ENTRY)
+
+#define bfa_msgq_cmd_set(_cmd, _cbfn, _cbarg, _msg_size, _msg_hdr)     \
+do {                                                                   \
+       (_cmd)->cbfn = (_cbfn);                                         \
+       (_cmd)->cbarg = (_cbarg);                                       \
+       (_cmd)->msg_size = (_msg_size);                                 \
+       (_cmd)->msg_hdr = (_msg_hdr);                                   \
+} while (0)
+
+struct bfa_msgq;
+
+typedef void (*bfa_msgq_cmdcbfn_t)(void *cbarg, enum bfa_status status);
+
+struct bfa_msgq_cmd_entry {
+       struct list_head                                qe;
+       bfa_msgq_cmdcbfn_t              cbfn;
+       void                            *cbarg;
+       size_t                          msg_size;
+       struct bfi_msgq_mhdr *msg_hdr;
+};
+
+enum bfa_msgq_cmdq_flags {
+       BFA_MSGQ_CMDQ_F_DB_UPDATE       = 1,
+};
+
+struct bfa_msgq_cmdq {
+       bfa_fsm_t                       fsm;
+       enum bfa_msgq_cmdq_flags flags;
+
+       u16                     producer_index;
+       u16                     consumer_index;
+       u16                     depth; /* FW Q depth is 16 bits */
+       struct bfa_dma addr;
+       struct bfa_mbox_cmd dbell_mb;
+
+       u16                     token;
+       int                             offset;
+       int                             bytes_to_copy;
+       struct bfa_mbox_cmd copy_mb;
+
+       struct list_head                pending_q; /* pending command queue */
+
+       struct bfa_msgq *msgq;
+};
+
+enum bfa_msgq_rspq_flags {
+       BFA_MSGQ_RSPQ_F_DB_UPDATE       = 1,
+};
+
+typedef void (*bfa_msgq_mcfunc_t)(void *cbarg, struct bfi_msgq_mhdr *mhdr);
+
+struct bfa_msgq_rspq {
+       bfa_fsm_t                       fsm;
+       enum bfa_msgq_rspq_flags flags;
+
+       u16                     producer_index;
+       u16                     consumer_index;
+       u16                     depth; /* FW Q depth is 16 bits */
+       struct bfa_dma addr;
+       struct bfa_mbox_cmd dbell_mb;
+
+       int                             nmclass;
+       struct {
+               bfa_msgq_mcfunc_t       cbfn;
+               void                    *cbarg;
+       } rsphdlr[BFI_MC_MAX];
+
+       struct bfa_msgq *msgq;
+};
+
+struct bfa_msgq {
+       struct bfa_msgq_cmdq cmdq;
+       struct bfa_msgq_rspq rspq;
+
+       struct bfa_wc                   init_wc;
+       struct bfa_mbox_cmd init_mb;
+
+       struct bfa_ioc_notify ioc_notify;
+       struct bfa_ioc *ioc;
+};
+
+u32 bfa_msgq_meminfo(void);
+void bfa_msgq_memclaim(struct bfa_msgq *msgq, u8 *kva, u64 pa);
+void bfa_msgq_attach(struct bfa_msgq *msgq, struct bfa_ioc *ioc);
+void bfa_msgq_regisr(struct bfa_msgq *msgq, enum bfi_mclass mc,
+                    bfa_msgq_mcfunc_t cbfn, void *cbarg);
+void bfa_msgq_cmd_post(struct bfa_msgq *msgq,
+                      struct bfa_msgq_cmd_entry *cmd);
+void bfa_msgq_rsp_copy(struct bfa_msgq *msgq, u8 *buf, size_t buf_len);
+
+#endif
similarity index 70%
rename from drivers/net/bna/bfi.h
rename to drivers/net/ethernet/brocade/bna/bfi.h
index 088211c..19654cc 100644 (file)
@@ -15,7 +15,6 @@
  * All rights reserved
  * www.brocade.com
  */
-
 #ifndef __BFI_H__
 #define __BFI_H__
 
  */
 #define        BFI_FLASH_CHUNK_SZ                      256     /*!< Flash chunk size */
 #define        BFI_FLASH_CHUNK_SZ_WORDS        (BFI_FLASH_CHUNK_SZ/sizeof(u32))
-enum {
-       BFI_IMAGE_CB_FC,
-       BFI_IMAGE_CT_FC,
-       BFI_IMAGE_CT_CNA,
-       BFI_IMAGE_MAX,
-};
 
 /**
  * Msg header common to all msgs
@@ -43,17 +36,21 @@ struct bfi_mhdr {
        u8              msg_id;         /*!< msg opcode with in the class   */
        union {
                struct {
-                       u8      rsvd;
-                       u8      lpu_id; /*!< msg destination                */
+                       u8      qid;
+                       u8      fn_lpu; /*!< msg destination                */
                } h2i;
                u16     i2htok; /*!< token in msgs to host          */
        } mtag;
 };
 
-#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {                \
+#define bfi_fn_lpu(__fn, __lpu)        ((__fn) << 1 | (__lpu))
+#define bfi_mhdr_2_fn(_mh)     ((_mh)->mtag.h2i.fn_lpu >> 1)
+#define bfi_mhdr_2_qid(_mh)    ((_mh)->mtag.h2i.qid)
+
+#define bfi_h2i_set(_mh, _mc, _op, _fn_lpu) do {               \
        (_mh).msg_class                 = (_mc);                \
        (_mh).msg_id                    = (_op);                \
-       (_mh).mtag.h2i.lpu_id   = (_lpuid);                     \
+       (_mh).mtag.h2i.fn_lpu   = (_fn_lpu);                    \
 } while (0)
 
 #define bfi_i2h_set(_mh, _mc, _op, _i2htok) do {               \
@@ -148,6 +145,14 @@ struct bfi_mbmsg {
        u32             pl[BFI_MBMSG_SZ];
 };
 
+/**
+ * Supported PCI function class codes (personality)
+ */
+enum bfi_pcifn_class {
+       BFI_PCIFN_CLASS_FC      = 0x0c04,
+       BFI_PCIFN_CLASS_ETH     = 0x0200,
+};
+
 /**
  * Message Classes
  */
@@ -183,14 +188,7 @@ enum bfi_mclass {
 #define BFI_IOC_MAX_CQS_ASIC   8
 #define BFI_IOC_MSGLEN_MAX     32      /* 32 bytes */
 
-#define BFI_BOOT_TYPE_OFF              8
-#define BFI_BOOT_LOADER_OFF            12
-
-#define BFI_BOOT_TYPE_NORMAL           0
-#define        BFI_BOOT_TYPE_FLASH             1
-#define        BFI_BOOT_TYPE_MEMTEST           2
-
-#define BFI_BOOT_LOADER_OS             0
+#define BFI_FWBOOT_ENV_OS              0
 
 #define BFI_BOOT_MEMTEST_RES_ADDR   0x900
 #define BFI_BOOT_MEMTEST_RES_SIG    0xA0A1A2A3
@@ -201,6 +199,21 @@ enum bfi_mclass {
  *----------------------------------------------------------------------
  */
 
+/**
+ * Different asic generations
+ */
+enum bfi_asic_gen {
+       BFI_ASIC_GEN_CB         = 1,
+       BFI_ASIC_GEN_CT         = 2,
+};
+
+enum bfi_asic_mode {
+       BFI_ASIC_MODE_FC        = 1,    /* FC upto 8G speed             */
+       BFI_ASIC_MODE_FC16      = 2,    /* FC upto 16G speed            */
+       BFI_ASIC_MODE_ETH       = 3,    /* Ethernet ports               */
+       BFI_ASIC_MODE_COMBO     = 4,    /* FC 16G and Ethernet 10G port */
+};
+
 enum bfi_ioc_h2i_msgs {
        BFI_IOC_H2I_ENABLE_REQ          = 1,
        BFI_IOC_H2I_DISABLE_REQ         = 2,
@@ -213,8 +226,7 @@ enum bfi_ioc_i2h_msgs {
        BFI_IOC_I2H_ENABLE_REPLY        = BFA_I2HM(1),
        BFI_IOC_I2H_DISABLE_REPLY       = BFA_I2HM(2),
        BFI_IOC_I2H_GETATTR_REPLY       = BFA_I2HM(3),
-       BFI_IOC_I2H_READY_EVENT         = BFA_I2HM(4),
-       BFI_IOC_I2H_HBEAT               = BFA_I2HM(5),
+       BFI_IOC_I2H_HBEAT               = BFA_I2HM(4),
 };
 
 /**
@@ -229,7 +241,8 @@ struct bfi_ioc_attr {
        u64             mfg_pwwn;       /*!< Mfg port wwn          */
        u64             mfg_nwwn;       /*!< Mfg node wwn          */
        mac_t           mfg_mac;        /*!< Mfg mac               */
-       u16     rsvd_a;
+       u8              port_mode;      /* enum bfi_port_mode      */
+       u8              rsvd_a;
        u64             pwwn;
        u64             nwwn;
        mac_t           mac;            /*!< PBC or Mfg mac        */
@@ -282,28 +295,39 @@ struct bfi_ioc_getattr_reply {
 #define BFI_IOC_MD5SUM_SZ      4
 struct bfi_ioc_image_hdr {
        u32     signature;      /*!< constant signature */
-       u32     rsvd_a;
+       u8      asic_gen;       /*!< asic generation */
+       u8      asic_mode;
+       u8      port0_mode;     /*!< device mode for port 0 */
+       u8      port1_mode;     /*!< device mode for port 1 */
        u32     exec;           /*!< exec vector        */
-       u32     param;          /*!< parameters         */
+       u32     bootenv;        /*!< firmware boot env */
        u32     rsvd_b[4];
        u32     md5sum[BFI_IOC_MD5SUM_SZ];
 };
 
+#define BFI_FWBOOT_DEVMODE_OFF         4
+#define BFI_FWBOOT_TYPE_OFF            8
+#define BFI_FWBOOT_ENV_OFF             12
+#define BFI_FWBOOT_DEVMODE(__asic_gen, __asic_mode, __p0_mode, __p1_mode) \
+       (((u32)(__asic_gen)) << 24 |    \
+        ((u32)(__asic_mode)) << 16 |   \
+        ((u32)(__p0_mode)) << 8 |      \
+        ((u32)(__p1_mode)))
+
 enum bfi_fwboot_type {
        BFI_FWBOOT_TYPE_NORMAL  = 0,
        BFI_FWBOOT_TYPE_FLASH   = 1,
        BFI_FWBOOT_TYPE_MEMTEST = 2,
 };
 
+enum bfi_port_mode {
+       BFI_PORT_MODE_FC        = 1,
+       BFI_PORT_MODE_ETH       = 2,
+};
+
 /**
  *  BFI_IOC_I2H_READY_EVENT message
  */
-struct bfi_ioc_rdy_event {
-       struct bfi_mhdr mh;             /*!< common msg header */
-       u8                      init_status;    /*!< init event status */
-       u8                      rsvd[3];
-};
-
 struct bfi_ioc_hbeat {
        struct bfi_mhdr mh;             /*!< common msg header          */
        u32        hb_count;    /*!< current heart beat count   */
@@ -360,8 +384,8 @@ enum {
  */
 struct bfi_ioc_ctrl_req {
        struct bfi_mhdr mh;
-       u8                      ioc_class;
-       u8                      rsvd[3];
+       u16                     clscode;
+       u16                     rsvd;
        u32             tv_sec;
 };
 
@@ -369,9 +393,11 @@ struct bfi_ioc_ctrl_req {
  * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
  */
 struct bfi_ioc_ctrl_reply {
-       struct bfi_mhdr mh;             /*!< Common msg header     */
+       struct bfi_mhdr mh;                     /*!< Common msg header     */
        u8                      status;         /*!< enable/disable status */
-       u8                      rsvd[3];
+       u8                      port_mode;      /*!< enum bfa_mode */
+       u8                      cap_bm;         /*!< capability bit mask */
+       u8                      rsvd;
 };
 
 #define BFI_IOC_MSGSZ   8
@@ -391,10 +417,109 @@ union bfi_ioc_h2i_msg_u {
  */
 union bfi_ioc_i2h_msg_u {
        struct bfi_mhdr mh;
-       struct bfi_ioc_rdy_event rdy_event;
+       struct bfi_ioc_ctrl_reply fw_event;
        u32                     mboxmsg[BFI_IOC_MSGSZ];
 };
 
+/**
+ *----------------------------------------------------------------------
+ *                             MSGQ
+ *----------------------------------------------------------------------
+ */
+
+enum bfi_msgq_h2i_msgs {
+       BFI_MSGQ_H2I_INIT_REQ      = 1,
+       BFI_MSGQ_H2I_DOORBELL_PI        = 2,
+       BFI_MSGQ_H2I_DOORBELL_CI        = 3,
+       BFI_MSGQ_H2I_CMDQ_COPY_RSP      = 4,
+};
+
+enum bfi_msgq_i2h_msgs {
+       BFI_MSGQ_I2H_INIT_RSP      = BFA_I2HM(BFI_MSGQ_H2I_INIT_REQ),
+       BFI_MSGQ_I2H_DOORBELL_PI        = BFA_I2HM(BFI_MSGQ_H2I_DOORBELL_PI),
+       BFI_MSGQ_I2H_DOORBELL_CI        = BFA_I2HM(BFI_MSGQ_H2I_DOORBELL_CI),
+       BFI_MSGQ_I2H_CMDQ_COPY_REQ      = BFA_I2HM(BFI_MSGQ_H2I_CMDQ_COPY_RSP),
+};
+
+/* Messages(commands/responsed/AENS will have the following header */
+struct bfi_msgq_mhdr {
+       u8      msg_class;
+       u8      msg_id;
+       u16     msg_token;
+       u16     num_entries;
+       u8      enet_id;
+       u8      rsvd[1];
+};
+
+#define bfi_msgq_mhdr_set(_mh, _mc, _mid, _tok, _enet_id) do { \
+       (_mh).msg_class  = (_mc);       \
+       (_mh).msg_id        = (_mid);       \
+       (_mh).msg_token  = (_tok);       \
+       (_mh).enet_id      = (_enet_id);   \
+} while (0)
+
+/*
+ * Mailbox  for messaging interface
+ */
+#define BFI_MSGQ_CMD_ENTRY_SIZE         (64)    /* TBD */
+#define BFI_MSGQ_RSP_ENTRY_SIZE         (64)    /* TBD */
+
+#define bfi_msgq_num_cmd_entries(_size)                                 \
+       (((_size) + BFI_MSGQ_CMD_ENTRY_SIZE - 1) / BFI_MSGQ_CMD_ENTRY_SIZE)
+
+struct bfi_msgq {
+       union bfi_addr_u addr;
+       u16 q_depth;     /* Total num of entries in the queue */
+       u8 rsvd[2];
+};
+
+/* BFI_ENET_MSGQ_CFG_REQ TBD init or cfg? */
+struct bfi_msgq_cfg_req {
+       struct bfi_mhdr mh;
+       struct bfi_msgq cmdq;
+       struct bfi_msgq rspq;
+};
+
+/* BFI_ENET_MSGQ_CFG_RSP */
+struct bfi_msgq_cfg_rsp {
+       struct bfi_mhdr mh;
+       u8 cmd_status;
+       u8 rsvd[3];
+};
+
+/* BFI_MSGQ_H2I_DOORBELL */
+struct bfi_msgq_h2i_db {
+       struct bfi_mhdr mh;
+       union {
+               u16 cmdq_pi;
+               u16 rspq_ci;
+       } idx;
+};
+
+/* BFI_MSGQ_I2H_DOORBELL */
+struct bfi_msgq_i2h_db {
+       struct bfi_mhdr mh;
+       union {
+               u16 rspq_pi;
+               u16 cmdq_ci;
+       } idx;
+};
+
+#define BFI_CMD_COPY_SZ 28
+
+/* BFI_MSGQ_H2I_CMD_COPY_RSP */
+struct bfi_msgq_h2i_cmdq_copy_rsp {
+       struct bfi_mhdr mh;
+       u8            data[BFI_CMD_COPY_SZ];
+};
+
+/* BFI_MSGQ_I2H_CMD_COPY_REQ */
+struct bfi_msgq_i2h_cmdq_copy_req {
+       struct bfi_mhdr mh;
+       u16     offset;
+       u16     len;
+};
+
 #pragma pack()
 
 #endif /* __BFI_H__ */
diff --git a/drivers/net/ethernet/brocade/bna/bfi_enet.h b/drivers/net/ethernet/brocade/bna/bfi_enet.h
new file mode 100644 (file)
index 0000000..a90f1cf
--- /dev/null
@@ -0,0 +1,901 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.
+ */
+/*
+ * Copyright (c) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/**
+ * @file bfi_enet.h BNA Hardware and Firmware Interface
+ */
+
+/**
+ * Skipping statistics collection to avoid clutter.
+ * Command is no longer needed:
+ *     MTU
+ *     TxQ Stop
+ *     RxQ Stop
+ *     RxF Enable/Disable
+ *
+ * HDS-off request is dynamic
+ * keep structures as multiple of 32-bit fields for alignment.
+ * All values must be written in big-endian.
+ */
+#ifndef __BFI_ENET_H__
+#define __BFI_ENET_H__
+
+#include "bfa_defs.h"
+#include "bfi.h"
+
+#pragma pack(1)
+
+#define BFI_ENET_CFG_MAX               32      /* Max resources per PF */
+
+#define BFI_ENET_TXQ_PRIO_MAX          8
+#define BFI_ENET_RX_QSET_MAX           16
+#define BFI_ENET_TXQ_WI_VECT_MAX       4
+
+#define BFI_ENET_VLAN_ID_MAX           4096
+#define BFI_ENET_VLAN_BLOCK_SIZE       512     /* in bits */
+#define BFI_ENET_VLAN_BLOCKS_MAX                                       \
+       (BFI_ENET_VLAN_ID_MAX / BFI_ENET_VLAN_BLOCK_SIZE)
+#define BFI_ENET_VLAN_WORD_SIZE                32      /* in bits */
+#define BFI_ENET_VLAN_WORDS_MAX                                                \
+       (BFI_ENET_VLAN_BLOCK_SIZE / BFI_ENET_VLAN_WORD_SIZE)
+
+#define BFI_ENET_RSS_RIT_MAX           64      /* entries */
+#define BFI_ENET_RSS_KEY_LEN           10      /* 32-bit words */
+
+union bfi_addr_be_u {
+       struct {
+               u32     addr_hi;        /* Most Significant 32-bits */
+               u32     addr_lo;        /* Least Significant 32-Bits */
+       } a32;
+};
+
+/**
+ *     T X   Q U E U E   D E F I N E S
+ */
+/* TxQ Vector (a.k.a. Tx-Buffer Descriptor) */
+/* TxQ Entry Opcodes */
+#define BFI_ENET_TXQ_WI_SEND           (0x402) /* Single Frame Transmission */
+#define BFI_ENET_TXQ_WI_SEND_LSO       (0x403) /* Multi-Frame Transmission */
+#define BFI_ENET_TXQ_WI_EXTENSION      (0x104) /* Extension WI */
+
+/* TxQ Entry Control Flags */
+#define BFI_ENET_TXQ_WI_CF_FCOE_CRC    (1 << 8)
+#define BFI_ENET_TXQ_WI_CF_IPID_MODE   (1 << 5)
+#define BFI_ENET_TXQ_WI_CF_INS_PRIO    (1 << 4)
+#define BFI_ENET_TXQ_WI_CF_INS_VLAN    (1 << 3)
+#define BFI_ENET_TXQ_WI_CF_UDP_CKSUM   (1 << 2)
+#define BFI_ENET_TXQ_WI_CF_TCP_CKSUM   (1 << 1)
+#define BFI_ENET_TXQ_WI_CF_IP_CKSUM    (1 << 0)
+
+struct bfi_enet_txq_wi_base {
+       u8                      reserved;
+       u8                      num_vectors;    /* number of vectors present */
+       u16                     opcode;
+                       /* BFI_ENET_TXQ_WI_SEND or BFI_ENET_TXQ_WI_SEND_LSO */
+       u16                     flags;          /* OR of all the flags */
+       u16                     l4_hdr_size_n_offset;
+       u16                     vlan_tag;
+       u16                     lso_mss;        /* Only 14 LSB are valid */
+       u32                     frame_length;   /* Only 24 LSB are valid */
+};
+
+struct bfi_enet_txq_wi_ext {
+       u16                     reserved;
+       u16                     opcode;         /* BFI_ENET_TXQ_WI_EXTENSION */
+       u32                     reserved2[3];
+};
+
+struct bfi_enet_txq_wi_vector {                        /* Tx Buffer Descriptor */
+       u16                     reserved;
+       u16                     length;         /* Only 14 LSB are valid */
+       union bfi_addr_be_u     addr;
+};
+
+/**
+ *  TxQ Entry Structure
+ *
+ */
+struct bfi_enet_txq_entry {
+       union {
+               struct bfi_enet_txq_wi_base     base;
+               struct bfi_enet_txq_wi_ext      ext;
+       } wi;
+       struct bfi_enet_txq_wi_vector vector[BFI_ENET_TXQ_WI_VECT_MAX];
+};
+
+#define wi_hdr         wi.base
+#define wi_ext_hdr     wi.ext
+
+#define BFI_ENET_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \
+               (((_hdr_size) << 10) | ((_offset) & 0x3FF))
+
+/**
+ *   R X   Q U E U E   D E F I N E S
+ */
+struct bfi_enet_rxq_entry {
+       union bfi_addr_be_u  rx_buffer;
+};
+
+/**
+ *   R X   C O M P L E T I O N   Q U E U E   D E F I N E S
+ */
+/* CQ Entry Flags */
+#define        BFI_ENET_CQ_EF_MAC_ERROR        (1 <<  0)
+#define        BFI_ENET_CQ_EF_FCS_ERROR        (1 <<  1)
+#define        BFI_ENET_CQ_EF_TOO_LONG         (1 <<  2)
+#define        BFI_ENET_CQ_EF_FC_CRC_OK        (1 <<  3)
+
+#define        BFI_ENET_CQ_EF_RSVD1            (1 <<  4)
+#define        BFI_ENET_CQ_EF_L4_CKSUM_OK      (1 <<  5)
+#define        BFI_ENET_CQ_EF_L3_CKSUM_OK      (1 <<  6)
+#define        BFI_ENET_CQ_EF_HDS_HEADER       (1 <<  7)
+
+#define        BFI_ENET_CQ_EF_UDP              (1 <<  8)
+#define        BFI_ENET_CQ_EF_TCP              (1 <<  9)
+#define        BFI_ENET_CQ_EF_IP_OPTIONS       (1 << 10)
+#define        BFI_ENET_CQ_EF_IPV6             (1 << 11)
+
+#define        BFI_ENET_CQ_EF_IPV4             (1 << 12)
+#define        BFI_ENET_CQ_EF_VLAN             (1 << 13)
+#define        BFI_ENET_CQ_EF_RSS              (1 << 14)
+#define        BFI_ENET_CQ_EF_RSVD2            (1 << 15)
+
+#define        BFI_ENET_CQ_EF_MCAST_MATCH      (1 << 16)
+#define        BFI_ENET_CQ_EF_MCAST            (1 << 17)
+#define BFI_ENET_CQ_EF_BCAST           (1 << 18)
+#define        BFI_ENET_CQ_EF_REMOTE           (1 << 19)
+
+#define        BFI_ENET_CQ_EF_LOCAL            (1 << 20)
+
+/* CQ Entry Structure */
+struct bfi_enet_cq_entry {
+       u32 flags;
+       u16     vlan_tag;
+       u16     length;
+       u32     rss_hash;
+       u8      valid;
+       u8      reserved1;
+       u8      reserved2;
+       u8      rxq_id;
+};
+
+/**
+ *   E N E T   C O N T R O L   P A T H   C O M M A N D S
+ */
+struct bfi_enet_q {
+       union bfi_addr_u        pg_tbl;
+       union bfi_addr_u        first_entry;
+       u16             pages;  /* # of pages */
+       u16             page_sz;
+};
+
+struct bfi_enet_txq {
+       struct bfi_enet_q       q;
+       u8                      priority;
+       u8                      rsvd[3];
+};
+
+struct bfi_enet_rxq {
+       struct bfi_enet_q       q;
+       u16             rx_buffer_size;
+       u16             rsvd;
+};
+
+struct bfi_enet_cq {
+       struct bfi_enet_q       q;
+};
+
+struct bfi_enet_ib_cfg {
+       u8              int_pkt_dma;
+       u8              int_enabled;
+       u8              int_pkt_enabled;
+       u8              continuous_coalescing;
+       u8              msix;
+       u8              rsvd[3];
+       u32     coalescing_timeout;
+       u32     inter_pkt_timeout;
+       u8              inter_pkt_count;
+       u8              rsvd1[3];
+};
+
+struct bfi_enet_ib {
+       union bfi_addr_u        index_addr;
+       union {
+               u16     msix_index;
+               u16     intx_bitmask;
+       } intr;
+       u16             rsvd;
+};
+
+/**
+ * ENET command messages
+ */
+enum bfi_enet_h2i_msgs {
+       /* Rx Commands */
+       BFI_ENET_H2I_RX_CFG_SET_REQ = 1,
+       BFI_ENET_H2I_RX_CFG_CLR_REQ = 2,
+
+       BFI_ENET_H2I_RIT_CFG_REQ = 3,
+       BFI_ENET_H2I_RSS_CFG_REQ = 4,
+       BFI_ENET_H2I_RSS_ENABLE_REQ = 5,
+       BFI_ENET_H2I_RX_PROMISCUOUS_REQ = 6,
+       BFI_ENET_H2I_RX_DEFAULT_REQ = 7,
+
+       BFI_ENET_H2I_MAC_UCAST_SET_REQ = 8,
+       BFI_ENET_H2I_MAC_UCAST_CLR_REQ = 9,
+       BFI_ENET_H2I_MAC_UCAST_ADD_REQ = 10,
+       BFI_ENET_H2I_MAC_UCAST_DEL_REQ = 11,
+
+       BFI_ENET_H2I_MAC_MCAST_ADD_REQ = 12,
+       BFI_ENET_H2I_MAC_MCAST_DEL_REQ = 13,
+       BFI_ENET_H2I_MAC_MCAST_FILTER_REQ = 14,
+
+       BFI_ENET_H2I_RX_VLAN_SET_REQ = 15,
+       BFI_ENET_H2I_RX_VLAN_STRIP_ENABLE_REQ = 16,
+
+       /* Tx Commands */
+       BFI_ENET_H2I_TX_CFG_SET_REQ = 17,
+       BFI_ENET_H2I_TX_CFG_CLR_REQ = 18,
+
+       /* Port Commands */
+       BFI_ENET_H2I_PORT_ADMIN_UP_REQ = 19,
+       BFI_ENET_H2I_SET_PAUSE_REQ = 20,
+       BFI_ENET_H2I_DIAG_LOOPBACK_REQ = 21,
+
+       /* Get Attributes Command */
+       BFI_ENET_H2I_GET_ATTR_REQ = 22,
+
+       /*  Statistics Commands */
+       BFI_ENET_H2I_STATS_GET_REQ = 23,
+       BFI_ENET_H2I_STATS_CLR_REQ = 24,
+
+       BFI_ENET_H2I_WOL_MAGIC_REQ = 25,
+       BFI_ENET_H2I_WOL_FRAME_REQ = 26,
+
+       BFI_ENET_H2I_MAX = 27,
+};
+
+enum bfi_enet_i2h_msgs {
+       /* Rx Responses */
+       BFI_ENET_I2H_RX_CFG_SET_RSP =
+               BFA_I2HM(BFI_ENET_H2I_RX_CFG_SET_REQ),
+       BFI_ENET_I2H_RX_CFG_CLR_RSP =
+               BFA_I2HM(BFI_ENET_H2I_RX_CFG_CLR_REQ),
+
+       BFI_ENET_I2H_RIT_CFG_RSP =
+               BFA_I2HM(BFI_ENET_H2I_RIT_CFG_REQ),
+       BFI_ENET_I2H_RSS_CFG_RSP =
+               BFA_I2HM(BFI_ENET_H2I_RSS_CFG_REQ),
+       BFI_ENET_I2H_RSS_ENABLE_RSP =
+               BFA_I2HM(BFI_ENET_H2I_RSS_ENABLE_REQ),
+       BFI_ENET_I2H_RX_PROMISCUOUS_RSP =
+               BFA_I2HM(BFI_ENET_H2I_RX_PROMISCUOUS_REQ),
+       BFI_ENET_I2H_RX_DEFAULT_RSP =
+               BFA_I2HM(BFI_ENET_H2I_RX_DEFAULT_REQ),
+
+       BFI_ENET_I2H_MAC_UCAST_SET_RSP =
+               BFA_I2HM(BFI_ENET_H2I_MAC_UCAST_SET_REQ),
+       BFI_ENET_I2H_MAC_UCAST_CLR_RSP =
+               BFA_I2HM(BFI_ENET_H2I_MAC_UCAST_CLR_REQ),
+       BFI_ENET_I2H_MAC_UCAST_ADD_RSP =
+               BFA_I2HM(BFI_ENET_H2I_MAC_UCAST_ADD_REQ),
+       BFI_ENET_I2H_MAC_UCAST_DEL_RSP =
+               BFA_I2HM(BFI_ENET_H2I_MAC_UCAST_DEL_REQ),
+
+       BFI_ENET_I2H_MAC_MCAST_ADD_RSP =
+               BFA_I2HM(BFI_ENET_H2I_MAC_MCAST_ADD_REQ),
+       BFI_ENET_I2H_MAC_MCAST_DEL_RSP =
+               BFA_I2HM(BFI_ENET_H2I_MAC_MCAST_DEL_REQ),
+       BFI_ENET_I2H_MAC_MCAST_FILTER_RSP =
+               BFA_I2HM(BFI_ENET_H2I_MAC_MCAST_FILTER_REQ),
+
+       BFI_ENET_I2H_RX_VLAN_SET_RSP =
+               BFA_I2HM(BFI_ENET_H2I_RX_VLAN_SET_REQ),
+
+       BFI_ENET_I2H_RX_VLAN_STRIP_ENABLE_RSP =
+               BFA_I2HM(BFI_ENET_H2I_RX_VLAN_STRIP_ENABLE_REQ),
+
+       /* Tx Responses */
+       BFI_ENET_I2H_TX_CFG_SET_RSP =
+               BFA_I2HM(BFI_ENET_H2I_TX_CFG_SET_REQ),
+       BFI_ENET_I2H_TX_CFG_CLR_RSP =
+               BFA_I2HM(BFI_ENET_H2I_TX_CFG_CLR_REQ),
+
+       /* Port Responses */
+       BFI_ENET_I2H_PORT_ADMIN_RSP =
+               BFA_I2HM(BFI_ENET_H2I_PORT_ADMIN_UP_REQ),
+
+       BFI_ENET_I2H_SET_PAUSE_RSP =
+               BFA_I2HM(BFI_ENET_H2I_SET_PAUSE_REQ),
+       BFI_ENET_I2H_DIAG_LOOPBACK_RSP =
+               BFA_I2HM(BFI_ENET_H2I_DIAG_LOOPBACK_REQ),
+
+       /*  Attributes Response */
+       BFI_ENET_I2H_GET_ATTR_RSP =
+               BFA_I2HM(BFI_ENET_H2I_GET_ATTR_REQ),
+
+       /* Statistics Responses */
+       BFI_ENET_I2H_STATS_GET_RSP =
+               BFA_I2HM(BFI_ENET_H2I_STATS_GET_REQ),
+       BFI_ENET_I2H_STATS_CLR_RSP =
+               BFA_I2HM(BFI_ENET_H2I_STATS_CLR_REQ),
+
+       BFI_ENET_I2H_WOL_MAGIC_RSP =
+               BFA_I2HM(BFI_ENET_H2I_WOL_MAGIC_REQ),
+       BFI_ENET_I2H_WOL_FRAME_RSP =
+               BFA_I2HM(BFI_ENET_H2I_WOL_FRAME_REQ),
+
+       /* AENs */
+       BFI_ENET_I2H_LINK_DOWN_AEN = BFA_I2HM(BFI_ENET_H2I_MAX),
+       BFI_ENET_I2H_LINK_UP_AEN = BFA_I2HM(BFI_ENET_H2I_MAX + 1),
+
+       BFI_ENET_I2H_PORT_ENABLE_AEN = BFA_I2HM(BFI_ENET_H2I_MAX + 2),
+       BFI_ENET_I2H_PORT_DISABLE_AEN = BFA_I2HM(BFI_ENET_H2I_MAX + 3),
+
+       BFI_ENET_I2H_BW_UPDATE_AEN = BFA_I2HM(BFI_ENET_H2I_MAX + 4),
+};
+
+/**
+ *  The following error codes can be returned by the enet commands
+ */
+enum bfi_enet_err {
+       BFI_ENET_CMD_OK         = 0,
+       BFI_ENET_CMD_FAIL       = 1,
+       BFI_ENET_CMD_DUP_ENTRY  = 2,    /* !< Duplicate entry in CAM */
+       BFI_ENET_CMD_CAM_FULL   = 3,    /* !< CAM is full */
+       BFI_ENET_CMD_NOT_OWNER  = 4,    /* !< Not permitted, b'cos not owner */
+       BFI_ENET_CMD_NOT_EXEC   = 5,    /* !< Was not sent to f/w at all */
+       BFI_ENET_CMD_WAITING    = 6,    /* !< Waiting for completion */
+       BFI_ENET_CMD_PORT_DISABLED = 7, /* !< port in disabled state */
+};
+
+/**
+ * Generic Request
+ *
+ * bfi_enet_req is used by:
+ *     BFI_ENET_H2I_RX_CFG_CLR_REQ
+ *     BFI_ENET_H2I_TX_CFG_CLR_REQ
+ */
+struct bfi_enet_req {
+       struct bfi_msgq_mhdr mh;
+};
+
+/**
+ * Enable/Disable Request
+ *
+ * bfi_enet_enable_req is used by:
+ *     BFI_ENET_H2I_RSS_ENABLE_REQ     (enet_id must be zero)
+ *     BFI_ENET_H2I_RX_PROMISCUOUS_REQ (enet_id must be zero)
+ *     BFI_ENET_H2I_RX_DEFAULT_REQ     (enet_id must be zero)
+ *     BFI_ENET_H2I_RX_MAC_MCAST_FILTER_REQ
+ *     BFI_ENET_H2I_PORT_ADMIN_UP_REQ  (enet_id must be zero)
+ */
+struct bfi_enet_enable_req {
+       struct          bfi_msgq_mhdr mh;
+       u8              enable;         /* 1 = enable;  0 = disable */
+       u8              rsvd[3];
+};
+
+/**
+ * Generic Response
+ */
+struct bfi_enet_rsp {
+       struct bfi_msgq_mhdr mh;
+       u8              error;          /*!< if error see cmd_offset */
+       u8              rsvd;
+       u16             cmd_offset;     /*!< offset to invalid parameter */
+};
+
+/**
+ * GLOBAL CONFIGURATION
+ */
+
+/**
+ * bfi_enet_attr_req is used by:
+ *     BFI_ENET_H2I_GET_ATTR_REQ
+ */
+struct bfi_enet_attr_req {
+       struct bfi_msgq_mhdr    mh;
+};
+
+/**
+ * bfi_enet_attr_rsp is used by:
+ *     BFI_ENET_I2H_GET_ATTR_RSP
+ */
+struct bfi_enet_attr_rsp {
+       struct bfi_msgq_mhdr mh;
+       u8              error;          /*!< if error see cmd_offset */
+       u8              rsvd;
+       u16             cmd_offset;     /*!< offset to invalid parameter */
+       u32             max_cfg;
+       u32             max_ucmac;
+       u32             rit_size;
+};
+
+/**
+ * Tx Configuration
+ *
+ * bfi_enet_tx_cfg is used by:
+ *     BFI_ENET_H2I_TX_CFG_SET_REQ
+ */
+enum bfi_enet_tx_vlan_mode {
+       BFI_ENET_TX_VLAN_NOP    = 0,
+       BFI_ENET_TX_VLAN_INS    = 1,
+       BFI_ENET_TX_VLAN_WI     = 2,
+};
+
+struct bfi_enet_tx_cfg {
+       u8              vlan_mode;      /*!< processing mode */
+       u8              rsvd;
+       u16             vlan_id;
+       u8              admit_tagged_frame;
+       u8              apply_vlan_filter;
+       u8              add_to_vswitch;
+       u8              rsvd1[1];
+};
+
+struct bfi_enet_tx_cfg_req {
+       struct bfi_msgq_mhdr mh;
+       u8                      num_queues;     /* # of Tx Queues */
+       u8                      rsvd[3];
+
+       struct {
+               struct bfi_enet_txq     q;
+               struct bfi_enet_ib      ib;
+       } q_cfg[BFI_ENET_TXQ_PRIO_MAX];
+
+       struct bfi_enet_ib_cfg  ib_cfg;
+
+       struct bfi_enet_tx_cfg  tx_cfg;
+};
+
+struct bfi_enet_tx_cfg_rsp {
+       struct          bfi_msgq_mhdr mh;
+       u8              error;
+       u8              hw_id;          /* For debugging */
+       u8              rsvd[2];
+       struct {
+               u32     q_dbell;        /* PCI base address offset */
+               u32     i_dbell;        /* PCI base address offset */
+               u8      hw_qid;         /* For debugging */
+               u8      rsvd[3];
+       } q_handles[BFI_ENET_TXQ_PRIO_MAX];
+};
+
+/**
+ * Rx Configuration
+ *
+ * bfi_enet_rx_cfg is used by:
+ *     BFI_ENET_H2I_RX_CFG_SET_REQ
+ */
+enum bfi_enet_rxq_type {
+       BFI_ENET_RXQ_SINGLE             = 1,
+       BFI_ENET_RXQ_LARGE_SMALL        = 2,
+       BFI_ENET_RXQ_HDS                = 3,
+       BFI_ENET_RXQ_HDS_OPT_BASED      = 4,
+};
+
+enum bfi_enet_hds_type {
+       BFI_ENET_HDS_FORCED     = 0x01,
+       BFI_ENET_HDS_IPV6_UDP   = 0x02,
+       BFI_ENET_HDS_IPV6_TCP   = 0x04,
+       BFI_ENET_HDS_IPV4_TCP   = 0x08,
+       BFI_ENET_HDS_IPV4_UDP   = 0x10,
+};
+
+struct bfi_enet_rx_cfg {
+       u8              rxq_type;
+       u8              rsvd[3];
+
+       struct {
+               u8                      max_header_size;
+               u8                      force_offset;
+               u8                      type;
+               u8                      rsvd1;
+       } hds;
+
+       u8              multi_buffer;
+       u8              strip_vlan;
+       u8              drop_untagged;
+       u8              rsvd2;
+};
+
+/*
+ * Multicast frames are received on the ql of q-set index zero.
+ * On the completion queue.  RxQ ID = even is for large/data buffer queues
+ * and RxQ ID = odd is for small/header buffer queues.
+ */
+struct bfi_enet_rx_cfg_req {
+       struct bfi_msgq_mhdr mh;
+       u8                      num_queue_sets; /* # of Rx Queue Sets */
+       u8                      rsvd[3];
+
+       struct {
+               struct bfi_enet_rxq     ql;     /* large/data/single buffers */
+               struct bfi_enet_rxq     qs;     /* small/header buffers */
+               struct bfi_enet_cq      cq;
+               struct bfi_enet_ib      ib;
+       } q_cfg[BFI_ENET_RX_QSET_MAX];
+
+       struct bfi_enet_ib_cfg  ib_cfg;
+
+       struct bfi_enet_rx_cfg  rx_cfg;
+};
+
+struct bfi_enet_rx_cfg_rsp {
+       struct bfi_msgq_mhdr mh;
+       u8              error;
+       u8              hw_id;   /* For debugging */
+       u8              rsvd[2];
+       struct {
+               u32     ql_dbell; /* PCI base address offset */
+               u32     qs_dbell; /* PCI base address offset */
+               u32     i_dbell;  /* PCI base address offset */
+               u8              hw_lqid;  /* For debugging */
+               u8              hw_sqid;  /* For debugging */
+               u8              hw_cqid;  /* For debugging */
+               u8              rsvd;
+       } q_handles[BFI_ENET_RX_QSET_MAX];
+};
+
+/**
+ * RIT
+ *
+ * bfi_enet_rit_req is used by:
+ *     BFI_ENET_H2I_RIT_CFG_REQ
+ */
+struct bfi_enet_rit_req {
+       struct  bfi_msgq_mhdr mh;
+       u16     size;                   /* number of table-entries used */
+       u8      rsvd[2];
+       u8      table[BFI_ENET_RSS_RIT_MAX];
+};
+
+/**
+ * RSS
+ *
+ * bfi_enet_rss_cfg_req is used by:
+ *     BFI_ENET_H2I_RSS_CFG_REQ
+ */
+enum bfi_enet_rss_type {
+       BFI_ENET_RSS_IPV6       = 0x01,
+       BFI_ENET_RSS_IPV6_TCP   = 0x02,
+       BFI_ENET_RSS_IPV4       = 0x04,
+       BFI_ENET_RSS_IPV4_TCP   = 0x08
+};
+
+struct bfi_enet_rss_cfg {
+       u8      type;
+       u8      mask;
+       u8      rsvd[2];
+       u32     key[BFI_ENET_RSS_KEY_LEN];
+};
+
+struct bfi_enet_rss_cfg_req {
+       struct bfi_msgq_mhdr    mh;
+       struct bfi_enet_rss_cfg cfg;
+};
+
+/**
+ * MAC Unicast
+ *
+ * bfi_enet_rx_vlan_req is used by:
+ *     BFI_ENET_H2I_MAC_UCAST_SET_REQ
+ *     BFI_ENET_H2I_MAC_UCAST_CLR_REQ
+ *     BFI_ENET_H2I_MAC_UCAST_ADD_REQ
+ *     BFI_ENET_H2I_MAC_UCAST_DEL_REQ
+ */
+struct bfi_enet_ucast_req {
+       struct bfi_msgq_mhdr    mh;
+       mac_t                   mac_addr;
+       u8                      rsvd[2];
+};
+
+/**
+ * MAC Unicast + VLAN
+ */
+struct bfi_enet_mac_n_vlan_req {
+       struct bfi_msgq_mhdr    mh;
+       u16                     vlan_id;
+       mac_t                   mac_addr;
+};
+
+/**
+ * MAC Multicast
+ *
+ * bfi_enet_mac_mfilter_add_req is used by:
+ *     BFI_ENET_H2I_MAC_MCAST_ADD_REQ
+ */
+struct bfi_enet_mcast_add_req {
+       struct bfi_msgq_mhdr    mh;
+       mac_t                   mac_addr;
+       u8                      rsvd[2];
+};
+
+/**
+ * bfi_enet_mac_mfilter_add_rsp is used by:
+ *     BFI_ENET_I2H_MAC_MCAST_ADD_RSP
+ */
+struct bfi_enet_mcast_add_rsp {
+       struct bfi_msgq_mhdr    mh;
+       u8                      error;
+       u8                      rsvd;
+       u16                     cmd_offset;
+       u16                     handle;
+       u8                      rsvd1[2];
+};
+
+/**
+ * bfi_enet_mac_mfilter_del_req is used by:
+ *     BFI_ENET_H2I_MAC_MCAST_DEL_REQ
+ */
+struct bfi_enet_mcast_del_req {
+       struct bfi_msgq_mhdr    mh;
+       u16                     handle;
+       u8                      rsvd[2];
+};
+
+/**
+ * VLAN
+ *
+ * bfi_enet_rx_vlan_req is used by:
+ *     BFI_ENET_H2I_RX_VLAN_SET_REQ
+ */
+struct bfi_enet_rx_vlan_req {
+       struct bfi_msgq_mhdr    mh;
+       u8                      block_idx;
+       u8                      rsvd[3];
+       u32                     bit_mask[BFI_ENET_VLAN_WORDS_MAX];
+};
+
+/**
+ * PAUSE
+ *
+ * bfi_enet_set_pause_req is used by:
+ *     BFI_ENET_H2I_SET_PAUSE_REQ
+ */
+struct bfi_enet_set_pause_req {
+       struct bfi_msgq_mhdr    mh;
+       u8                      rsvd[2];
+       u8                      tx_pause;       /* 1 = enable;  0 = disable */
+       u8                      rx_pause;       /* 1 = enable;  0 = disable */
+};
+
+/**
+ * DIAGNOSTICS
+ *
+ * bfi_enet_diag_lb_req is used by:
+ *      BFI_ENET_H2I_DIAG_LOOPBACK
+ */
+struct bfi_enet_diag_lb_req {
+       struct bfi_msgq_mhdr    mh;
+       u8                      rsvd[2];
+       u8                      mode;           /* cable or Serdes */
+       u8                      enable;         /* 1 = enable;  0 = disable */
+};
+
+/**
+ * enum for Loopback opmodes
+ */
+enum {
+       BFI_ENET_DIAG_LB_OPMODE_EXT = 0,
+       BFI_ENET_DIAG_LB_OPMODE_CBL = 1,
+};
+
+/**
+ * STATISTICS
+ *
+ * bfi_enet_stats_req is used by:
+ *    BFI_ENET_H2I_STATS_GET_REQ
+ *    BFI_ENET_I2H_STATS_CLR_REQ
+ */
+struct bfi_enet_stats_req {
+       struct bfi_msgq_mhdr    mh;
+       u16                     stats_mask;
+       u8                      rsvd[2];
+       u32                     rx_enet_mask;
+       u32                     tx_enet_mask;
+       union bfi_addr_u        host_buffer;
+};
+
+/**
+ * defines for "stats_mask" above.
+ */
+#define BFI_ENET_STATS_MAC    (1 << 0)    /* !< MAC Statistics */
+#define BFI_ENET_STATS_BPC    (1 << 1)    /* !< Pause Stats from BPC */
+#define BFI_ENET_STATS_RAD    (1 << 2)    /* !< Rx Admission Statistics */
+#define BFI_ENET_STATS_RX_FC  (1 << 3)    /* !< Rx FC Stats from RxA */
+#define BFI_ENET_STATS_TX_FC  (1 << 4)    /* !< Tx FC Stats from TxA */
+
+#define BFI_ENET_STATS_ALL    0x1f
+
+/* TxF Frame Statistics */
+struct bfi_enet_stats_txf {
+       u64 ucast_octets;
+       u64 ucast;
+       u64 ucast_vlan;
+
+       u64 mcast_octets;
+       u64 mcast;
+       u64 mcast_vlan;
+
+       u64 bcast_octets;
+       u64 bcast;
+       u64 bcast_vlan;
+
+       u64 errors;
+       u64 filter_vlan;      /* frames filtered due to VLAN */
+       u64 filter_mac_sa;    /* frames filtered due to SA check */
+};
+
+/* RxF Frame Statistics */
+struct bfi_enet_stats_rxf {
+       u64 ucast_octets;
+       u64 ucast;
+       u64 ucast_vlan;
+
+       u64 mcast_octets;
+       u64 mcast;
+       u64 mcast_vlan;
+
+       u64 bcast_octets;
+       u64 bcast;
+       u64 bcast_vlan;
+       u64 frame_drops;
+};
+
+/* FC Tx Frame Statistics */
+struct bfi_enet_stats_fc_tx {
+       u64 txf_ucast_octets;
+       u64 txf_ucast;
+       u64 txf_ucast_vlan;
+
+       u64 txf_mcast_octets;
+       u64 txf_mcast;
+       u64 txf_mcast_vlan;
+
+       u64 txf_bcast_octets;
+       u64 txf_bcast;
+       u64 txf_bcast_vlan;
+
+       u64 txf_parity_errors;
+       u64 txf_timeout;
+       u64 txf_fid_parity_errors;
+};
+
+/* FC Rx Frame Statistics */
+struct bfi_enet_stats_fc_rx {
+       u64 rxf_ucast_octets;
+       u64 rxf_ucast;
+       u64 rxf_ucast_vlan;
+
+       u64 rxf_mcast_octets;
+       u64 rxf_mcast;
+       u64 rxf_mcast_vlan;
+
+       u64 rxf_bcast_octets;
+       u64 rxf_bcast;
+       u64 rxf_bcast_vlan;
+};
+
+/* RAD Frame Statistics */
+struct bfi_enet_stats_rad {
+       u64 rx_frames;
+       u64 rx_octets;
+       u64 rx_vlan_frames;
+
+       u64 rx_ucast;
+       u64 rx_ucast_octets;
+       u64 rx_ucast_vlan;
+
+       u64 rx_mcast;
+       u64 rx_mcast_octets;
+       u64 rx_mcast_vlan;
+
+       u64 rx_bcast;
+       u64 rx_bcast_octets;
+       u64 rx_bcast_vlan;
+
+       u64 rx_drops;
+};
+
+/* BPC Tx Registers */
+struct bfi_enet_stats_bpc {
+       /* transmit stats */
+       u64 tx_pause[8];
+       u64 tx_zero_pause[8];   /*!< Pause cancellation */
+       /*!<Pause initiation rather than retention */
+       u64 tx_first_pause[8];
+
+       /* receive stats */
+       u64 rx_pause[8];
+       u64 rx_zero_pause[8];   /*!< Pause cancellation */
+       /*!<Pause initiation rather than retention */
+       u64 rx_first_pause[8];
+};
+
+/* MAC Rx Statistics */
+struct bfi_enet_stats_mac {
+       u64 frame_64;           /* both rx and tx counter */
+       u64 frame_65_127;               /* both rx and tx counter */
+       u64 frame_128_255;              /* both rx and tx counter */
+       u64 frame_256_511;              /* both rx and tx counter */
+       u64 frame_512_1023;     /* both rx and tx counter */
+       u64 frame_1024_1518;    /* both rx and tx counter */
+       u64 frame_1519_1522;    /* both rx and tx counter */
+
+       /* receive stats */
+       u64 rx_bytes;
+       u64 rx_packets;
+       u64 rx_fcs_error;
+       u64 rx_multicast;
+       u64 rx_broadcast;
+       u64 rx_control_frames;
+       u64 rx_pause;
+       u64 rx_unknown_opcode;
+       u64 rx_alignment_error;
+       u64 rx_frame_length_error;
+       u64 rx_code_error;
+       u64 rx_carrier_sense_error;
+       u64 rx_undersize;
+       u64 rx_oversize;
+       u64 rx_fragments;
+       u64 rx_jabber;
+       u64 rx_drop;
+
+       /* transmit stats */
+       u64 tx_bytes;
+       u64 tx_packets;
+       u64 tx_multicast;
+       u64 tx_broadcast;
+       u64 tx_pause;
+       u64 tx_deferral;
+       u64 tx_excessive_deferral;
+       u64 tx_single_collision;
+       u64 tx_muliple_collision;
+       u64 tx_late_collision;
+       u64 tx_excessive_collision;
+       u64 tx_total_collision;
+       u64 tx_pause_honored;
+       u64 tx_drop;
+       u64 tx_jabber;
+       u64 tx_fcs_error;
+       u64 tx_control_frame;
+       u64 tx_oversize;
+       u64 tx_undersize;
+       u64 tx_fragments;
+};
+
+/**
+ * Complete statistics, DMAed from fw to host followed by
+ * BFI_ENET_I2H_STATS_GET_RSP
+ */
+struct bfi_enet_stats {
+       struct bfi_enet_stats_mac       mac_stats;
+       struct bfi_enet_stats_bpc       bpc_stats;
+       struct bfi_enet_stats_rad       rad_stats;
+       struct bfi_enet_stats_rad       rlb_stats;
+       struct bfi_enet_stats_fc_rx     fc_rx_stats;
+       struct bfi_enet_stats_fc_tx     fc_tx_stats;
+       struct bfi_enet_stats_rxf       rxf_stats[BFI_ENET_CFG_MAX];
+       struct bfi_enet_stats_txf       txf_stats[BFI_ENET_CFG_MAX];
+};
+
+#pragma pack()
+
+#endif  /* __BFI_ENET_H__ */
diff --git a/drivers/net/ethernet/brocade/bna/bfi_reg.h b/drivers/net/ethernet/brocade/bna/bfi_reg.h
new file mode 100644 (file)
index 0000000..efacff3
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.
+ */
+/*
+ * Copyright (c) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/*
+ * bfi_reg.h ASIC register defines for all Brocade adapter ASICs
+ */
+
+#ifndef __BFI_REG_H__
+#define __BFI_REG_H__
+
+#define HOSTFN0_INT_STATUS             0x00014000      /* cb/ct        */
+#define HOSTFN1_INT_STATUS             0x00014100      /* cb/ct        */
+#define HOSTFN2_INT_STATUS             0x00014300      /* ct           */
+#define HOSTFN3_INT_STATUS             0x00014400      /* ct           */
+#define HOSTFN0_INT_MSK                        0x00014004      /* cb/ct        */
+#define HOSTFN1_INT_MSK                        0x00014104      /* cb/ct        */
+#define HOSTFN2_INT_MSK                        0x00014304      /* ct           */
+#define HOSTFN3_INT_MSK                        0x00014404      /* ct           */
+
+#define HOST_PAGE_NUM_FN0              0x00014008      /* cb/ct        */
+#define HOST_PAGE_NUM_FN1              0x00014108      /* cb/ct        */
+#define HOST_PAGE_NUM_FN2              0x00014308      /* ct           */
+#define HOST_PAGE_NUM_FN3              0x00014408      /* ct           */
+
+#define APP_PLL_LCLK_CTL_REG           0x00014204      /* cb/ct        */
+#define __P_LCLK_PLL_LOCK              0x80000000
+#define __APP_PLL_LCLK_SRAM_USE_100MHZ 0x00100000
+#define __APP_PLL_LCLK_RESET_TIMER_MK  0x000e0000
+#define __APP_PLL_LCLK_RESET_TIMER_SH  17
+#define __APP_PLL_LCLK_RESET_TIMER(_v) ((_v) << __APP_PLL_LCLK_RESET_TIMER_SH)
+#define __APP_PLL_LCLK_LOGIC_SOFT_RESET        0x00010000
+#define __APP_PLL_LCLK_CNTLMT0_1_MK    0x0000c000
+#define __APP_PLL_LCLK_CNTLMT0_1_SH    14
+#define __APP_PLL_LCLK_CNTLMT0_1(_v)   ((_v) << __APP_PLL_LCLK_CNTLMT0_1_SH)
+#define __APP_PLL_LCLK_JITLMT0_1_MK    0x00003000
+#define __APP_PLL_LCLK_JITLMT0_1_SH    12
+#define __APP_PLL_LCLK_JITLMT0_1(_v)   ((_v) << __APP_PLL_LCLK_JITLMT0_1_SH)
+#define __APP_PLL_LCLK_HREF            0x00000800
+#define __APP_PLL_LCLK_HDIV            0x00000400
+#define __APP_PLL_LCLK_P0_1_MK         0x00000300
+#define __APP_PLL_LCLK_P0_1_SH         8
+#define __APP_PLL_LCLK_P0_1(_v)                ((_v) << __APP_PLL_LCLK_P0_1_SH)
+#define __APP_PLL_LCLK_Z0_2_MK         0x000000e0
+#define __APP_PLL_LCLK_Z0_2_SH         5
+#define __APP_PLL_LCLK_Z0_2(_v)                ((_v) << __APP_PLL_LCLK_Z0_2_SH)
+#define __APP_PLL_LCLK_RSEL200500      0x00000010
+#define __APP_PLL_LCLK_ENARST          0x00000008
+#define __APP_PLL_LCLK_BYPASS          0x00000004
+#define __APP_PLL_LCLK_LRESETN         0x00000002
+#define __APP_PLL_LCLK_ENABLE          0x00000001
+#define APP_PLL_SCLK_CTL_REG           0x00014208      /* cb/ct        */
+#define __P_SCLK_PLL_LOCK              0x80000000
+#define __APP_PLL_SCLK_RESET_TIMER_MK  0x000e0000
+#define __APP_PLL_SCLK_RESET_TIMER_SH  17
+#define __APP_PLL_SCLK_RESET_TIMER(_v) ((_v) << __APP_PLL_SCLK_RESET_TIMER_SH)
+#define __APP_PLL_SCLK_LOGIC_SOFT_RESET        0x00010000
+#define __APP_PLL_SCLK_CNTLMT0_1_MK    0x0000c000
+#define __APP_PLL_SCLK_CNTLMT0_1_SH    14
+#define __APP_PLL_SCLK_CNTLMT0_1(_v)   ((_v) << __APP_PLL_SCLK_CNTLMT0_1_SH)
+#define __APP_PLL_SCLK_JITLMT0_1_MK    0x00003000
+#define __APP_PLL_SCLK_JITLMT0_1_SH    12
+#define __APP_PLL_SCLK_JITLMT0_1(_v)   ((_v) << __APP_PLL_SCLK_JITLMT0_1_SH)
+#define __APP_PLL_SCLK_HREF            0x00000800
+#define __APP_PLL_SCLK_HDIV            0x00000400
+#define __APP_PLL_SCLK_P0_1_MK         0x00000300
+#define __APP_PLL_SCLK_P0_1_SH         8
+#define __APP_PLL_SCLK_P0_1(_v)                ((_v) << __APP_PLL_SCLK_P0_1_SH)
+#define __APP_PLL_SCLK_Z0_2_MK         0x000000e0
+#define __APP_PLL_SCLK_Z0_2_SH         5
+#define __APP_PLL_SCLK_Z0_2(_v)                ((_v) << __APP_PLL_SCLK_Z0_2_SH)
+#define __APP_PLL_SCLK_RSEL200500      0x00000010
+#define __APP_PLL_SCLK_ENARST          0x00000008
+#define __APP_PLL_SCLK_BYPASS          0x00000004
+#define __APP_PLL_SCLK_LRESETN         0x00000002
+#define __APP_PLL_SCLK_ENABLE          0x00000001
+#define __ENABLE_MAC_AHB_1             0x00800000      /* ct           */
+#define __ENABLE_MAC_AHB_0             0x00400000      /* ct           */
+#define __ENABLE_MAC_1                 0x00200000      /* ct           */
+#define __ENABLE_MAC_0                 0x00100000      /* ct           */
+
+#define HOST_SEM0_REG                  0x00014230      /* cb/ct        */
+#define HOST_SEM1_REG                  0x00014234      /* cb/ct        */
+#define HOST_SEM2_REG                  0x00014238      /* cb/ct        */
+#define HOST_SEM3_REG                  0x0001423c      /* cb/ct        */
+#define HOST_SEM4_REG                  0x00014610      /* cb/ct        */
+#define HOST_SEM5_REG                  0x00014614      /* cb/ct        */
+#define HOST_SEM6_REG                  0x00014618      /* cb/ct        */
+#define HOST_SEM7_REG                  0x0001461c      /* cb/ct        */
+#define HOST_SEM0_INFO_REG             0x00014240      /* cb/ct        */
+#define HOST_SEM1_INFO_REG             0x00014244      /* cb/ct        */
+#define HOST_SEM2_INFO_REG             0x00014248      /* cb/ct        */
+#define HOST_SEM3_INFO_REG             0x0001424c      /* cb/ct        */
+#define HOST_SEM4_INFO_REG             0x00014620      /* cb/ct        */
+#define HOST_SEM5_INFO_REG             0x00014624      /* cb/ct        */
+#define HOST_SEM6_INFO_REG             0x00014628      /* cb/ct        */
+#define HOST_SEM7_INFO_REG             0x0001462c      /* cb/ct        */
+
+#define HOSTFN0_LPU0_CMD_STAT          0x00019000      /* cb/ct        */
+#define HOSTFN0_LPU1_CMD_STAT          0x00019004      /* cb/ct        */
+#define HOSTFN1_LPU0_CMD_STAT          0x00019010      /* cb/ct        */
+#define HOSTFN1_LPU1_CMD_STAT          0x00019014      /* cb/ct        */
+#define HOSTFN2_LPU0_CMD_STAT          0x00019150      /* ct           */
+#define HOSTFN2_LPU1_CMD_STAT          0x00019154      /* ct           */
+#define HOSTFN3_LPU0_CMD_STAT          0x00019160      /* ct           */
+#define HOSTFN3_LPU1_CMD_STAT          0x00019164      /* ct           */
+#define LPU0_HOSTFN0_CMD_STAT          0x00019008      /* cb/ct        */
+#define LPU1_HOSTFN0_CMD_STAT          0x0001900c      /* cb/ct        */
+#define LPU0_HOSTFN1_CMD_STAT          0x00019018      /* cb/ct        */
+#define LPU1_HOSTFN1_CMD_STAT          0x0001901c      /* cb/ct        */
+#define LPU0_HOSTFN2_CMD_STAT          0x00019158      /* ct           */
+#define LPU1_HOSTFN2_CMD_STAT          0x0001915c      /* ct           */
+#define LPU0_HOSTFN3_CMD_STAT          0x00019168      /* ct           */
+#define LPU1_HOSTFN3_CMD_STAT          0x0001916c      /* ct           */
+
+#define PSS_CTL_REG                    0x00018800      /* cb/ct        */
+#define __PSS_I2C_CLK_DIV_MK           0x007f0000
+#define __PSS_I2C_CLK_DIV_SH           16
+#define __PSS_I2C_CLK_DIV(_v)          ((_v) << __PSS_I2C_CLK_DIV_SH)
+#define __PSS_LMEM_INIT_DONE           0x00001000
+#define __PSS_LMEM_RESET               0x00000200
+#define __PSS_LMEM_INIT_EN             0x00000100
+#define __PSS_LPU1_RESET               0x00000002
+#define __PSS_LPU0_RESET               0x00000001
+#define PSS_ERR_STATUS_REG             0x00018810      /* cb/ct        */
+#define ERR_SET_REG                    0x00018818      /* cb/ct        */
+#define PSS_GPIO_OUT_REG               0x000188c0      /* cb/ct        */
+#define __PSS_GPIO_OUT_REG             0x00000fff
+#define PSS_GPIO_OE_REG                        0x000188c8      /* cb/ct        */
+#define __PSS_GPIO_OE_REG              0x000000ff
+
+#define HOSTFN0_LPU_MBOX0_0            0x00019200      /* cb/ct        */
+#define HOSTFN1_LPU_MBOX0_8            0x00019260      /* cb/ct        */
+#define LPU_HOSTFN0_MBOX0_0            0x00019280      /* cb/ct        */
+#define LPU_HOSTFN1_MBOX0_8            0x000192e0      /* cb/ct        */
+#define HOSTFN2_LPU_MBOX0_0            0x00019400      /* ct           */
+#define HOSTFN3_LPU_MBOX0_8            0x00019460      /* ct           */
+#define LPU_HOSTFN2_MBOX0_0            0x00019480      /* ct           */
+#define LPU_HOSTFN3_MBOX0_8            0x000194e0      /* ct           */
+
+#define HOST_MSIX_ERR_INDEX_FN0                0x0001400c      /* ct           */
+#define HOST_MSIX_ERR_INDEX_FN1                0x0001410c      /* ct           */
+#define HOST_MSIX_ERR_INDEX_FN2                0x0001430c      /* ct           */
+#define HOST_MSIX_ERR_INDEX_FN3                0x0001440c      /* ct           */
+
+#define MBIST_CTL_REG                  0x00014220      /* ct           */
+#define __EDRAM_BISTR_START            0x00000004
+#define MBIST_STAT_REG                 0x00014224      /* ct           */
+#define ETH_MAC_SER_REG                        0x00014288      /* ct           */
+#define __APP_EMS_CKBUFAMPIN           0x00000020
+#define __APP_EMS_REFCLKSEL            0x00000010
+#define __APP_EMS_CMLCKSEL             0x00000008
+#define __APP_EMS_REFCKBUFEN2          0x00000004
+#define __APP_EMS_REFCKBUFEN1          0x00000002
+#define __APP_EMS_CHANNEL_SEL          0x00000001
+#define FNC_PERS_REG                   0x00014604      /* ct           */
+#define __F3_FUNCTION_ACTIVE           0x80000000
+#define __F3_FUNCTION_MODE             0x40000000
+#define __F3_PORT_MAP_MK               0x30000000
+#define __F3_PORT_MAP_SH               28
+#define __F3_PORT_MAP(_v)              ((_v) << __F3_PORT_MAP_SH)
+#define __F3_VM_MODE                   0x08000000
+#define __F3_INTX_STATUS_MK            0x07000000
+#define __F3_INTX_STATUS_SH            24
+#define __F3_INTX_STATUS(_v)           ((_v) << __F3_INTX_STATUS_SH)
+#define __F2_FUNCTION_ACTIVE           0x00800000
+#define __F2_FUNCTION_MODE             0x00400000
+#define __F2_PORT_MAP_MK               0x00300000
+#define __F2_PORT_MAP_SH               20
+#define __F2_PORT_MAP(_v)              ((_v) << __F2_PORT_MAP_SH)
+#define __F2_VM_MODE                   0x00080000
+#define __F2_INTX_STATUS_MK            0x00070000
+#define __F2_INTX_STATUS_SH            16
+#define __F2_INTX_STATUS(_v)           ((_v) << __F2_INTX_STATUS_SH)
+#define __F1_FUNCTION_ACTIVE           0x00008000
+#define __F1_FUNCTION_MODE             0x00004000
+#define __F1_PORT_MAP_MK               0x00003000
+#define __F1_PORT_MAP_SH               12
+#define __F1_PORT_MAP(_v)              ((_v) << __F1_PORT_MAP_SH)
+#define __F1_VM_MODE                   0x00000800
+#define __F1_INTX_STATUS_MK            0x00000700
+#define __F1_INTX_STATUS_SH            8
+#define __F1_INTX_STATUS(_v)           ((_v) << __F1_INTX_STATUS_SH)
+#define __F0_FUNCTION_ACTIVE           0x00000080
+#define __F0_FUNCTION_MODE             0x00000040
+#define __F0_PORT_MAP_MK               0x00000030
+#define __F0_PORT_MAP_SH               4
+#define __F0_PORT_MAP(_v)              ((_v) << __F0_PORT_MAP_SH)
+#define __F0_VM_MODE                   0x00000008
+#define __F0_INTX_STATUS               0x00000007
+enum {
+       __F0_INTX_STATUS_MSIX = 0x0,
+       __F0_INTX_STATUS_INTA = 0x1,
+       __F0_INTX_STATUS_INTB = 0x2,
+       __F0_INTX_STATUS_INTC = 0x3,
+       __F0_INTX_STATUS_INTD = 0x4,
+};
+
+#define OP_MODE                                0x0001460c
+#define __APP_ETH_CLK_LOWSPEED         0x00000004
+#define __GLOBAL_CORECLK_HALFSPEED     0x00000002
+#define __GLOBAL_FCOE_MODE             0x00000001
+#define FW_INIT_HALT_P0                        0x000191ac
+#define __FW_INIT_HALT_P               0x00000001
+#define FW_INIT_HALT_P1                        0x000191bc
+#define PMM_1T_RESET_REG_P0            0x0002381c
+#define __PMM_1T_RESET_P               0x00000001
+#define PMM_1T_RESET_REG_P1            0x00023c1c
+
+/**
+ * Brocade 1860 Adapter specific defines
+ */
+#define CT2_PCI_CPQ_BASE               0x00030000
+#define CT2_PCI_APP_BASE               0x00030100
+#define CT2_PCI_ETH_BASE               0x00030400
+
+/*
+ * APP block registers
+ */
+#define CT2_HOSTFN_INT_STATUS          (CT2_PCI_APP_BASE + 0x00)
+#define CT2_HOSTFN_INTR_MASK           (CT2_PCI_APP_BASE + 0x04)
+#define CT2_HOSTFN_PERSONALITY0                (CT2_PCI_APP_BASE + 0x08)
+#define __PME_STATUS_                  0x00200000
+#define __PF_VF_BAR_SIZE_MODE__MK      0x00180000
+#define __PF_VF_BAR_SIZE_MODE__SH      19
+#define __PF_VF_BAR_SIZE_MODE_(_v)     ((_v) << __PF_VF_BAR_SIZE_MODE__SH)
+#define __FC_LL_PORT_MAP__MK           0x00060000
+#define __FC_LL_PORT_MAP__SH           17
+#define __FC_LL_PORT_MAP_(_v)          ((_v) << __FC_LL_PORT_MAP__SH)
+#define __PF_VF_ACTIVE_                        0x00010000
+#define __PF_VF_CFG_RDY_               0x00008000
+#define __PF_VF_ENABLE_                        0x00004000
+#define __PF_DRIVER_ACTIVE_            0x00002000
+#define __PF_PME_SEND_ENABLE_          0x00001000
+#define __PF_EXROM_OFFSET__MK          0x00000ff0
+#define __PF_EXROM_OFFSET__SH          4
+#define __PF_EXROM_OFFSET_(_v)         ((_v) << __PF_EXROM_OFFSET__SH)
+#define __FC_LL_MODE_                  0x00000008
+#define __PF_INTX_PIN_                 0x00000007
+#define CT2_HOSTFN_PERSONALITY1                (CT2_PCI_APP_BASE + 0x0C)
+#define __PF_NUM_QUEUES1__MK           0xff000000
+#define __PF_NUM_QUEUES1__SH           24
+#define __PF_NUM_QUEUES1_(_v)          ((_v) << __PF_NUM_QUEUES1__SH)
+#define __PF_VF_QUE_OFFSET1__MK                0x00ff0000
+#define __PF_VF_QUE_OFFSET1__SH                16
+#define __PF_VF_QUE_OFFSET1_(_v)       ((_v) << __PF_VF_QUE_OFFSET1__SH)
+#define __PF_VF_NUM_QUEUES__MK         0x0000ff00
+#define __PF_VF_NUM_QUEUES__SH         8
+#define __PF_VF_NUM_QUEUES_(_v)                ((_v) << __PF_VF_NUM_QUEUES__SH)
+#define __PF_VF_QUE_OFFSET_            0x000000ff
+#define CT2_HOSTFN_PAGE_NUM            (CT2_PCI_APP_BASE + 0x18)
+#define CT2_HOSTFN_MSIX_VT_INDEX_MBOX_ERR      (CT2_PCI_APP_BASE + 0x38)
+
+/*
+ * Brocade 1860 adapter CPQ block registers
+ */
+#define CT2_HOSTFN_LPU0_MBOX0          (CT2_PCI_CPQ_BASE + 0x00)
+#define CT2_HOSTFN_LPU1_MBOX0          (CT2_PCI_CPQ_BASE + 0x20)
+#define CT2_LPU0_HOSTFN_MBOX0          (CT2_PCI_CPQ_BASE + 0x40)
+#define CT2_LPU1_HOSTFN_MBOX0          (CT2_PCI_CPQ_BASE + 0x60)
+#define CT2_HOSTFN_LPU0_CMD_STAT       (CT2_PCI_CPQ_BASE + 0x80)
+#define CT2_HOSTFN_LPU1_CMD_STAT       (CT2_PCI_CPQ_BASE + 0x84)
+#define CT2_LPU0_HOSTFN_CMD_STAT       (CT2_PCI_CPQ_BASE + 0x88)
+#define CT2_LPU1_HOSTFN_CMD_STAT       (CT2_PCI_CPQ_BASE + 0x8c)
+#define CT2_HOSTFN_LPU0_READ_STAT      (CT2_PCI_CPQ_BASE + 0x90)
+#define CT2_HOSTFN_LPU1_READ_STAT      (CT2_PCI_CPQ_BASE + 0x94)
+#define CT2_LPU0_HOSTFN_MBOX0_MSK      (CT2_PCI_CPQ_BASE + 0x98)
+#define CT2_LPU1_HOSTFN_MBOX0_MSK      (CT2_PCI_CPQ_BASE + 0x9C)
+#define CT2_HOST_SEM0_REG              0x000148f0
+#define CT2_HOST_SEM1_REG              0x000148f4
+#define CT2_HOST_SEM2_REG              0x000148f8
+#define CT2_HOST_SEM3_REG              0x000148fc
+#define CT2_HOST_SEM4_REG              0x00014900
+#define CT2_HOST_SEM5_REG              0x00014904
+#define CT2_HOST_SEM6_REG              0x00014908
+#define CT2_HOST_SEM7_REG              0x0001490c
+#define CT2_HOST_SEM0_INFO_REG         0x000148b0
+#define CT2_HOST_SEM1_INFO_REG         0x000148b4
+#define CT2_HOST_SEM2_INFO_REG         0x000148b8
+#define CT2_HOST_SEM3_INFO_REG         0x000148bc
+#define CT2_HOST_SEM4_INFO_REG         0x000148c0
+#define CT2_HOST_SEM5_INFO_REG         0x000148c4
+#define CT2_HOST_SEM6_INFO_REG         0x000148c8
+#define CT2_HOST_SEM7_INFO_REG         0x000148cc
+
+#define CT2_APP_PLL_LCLK_CTL_REG       0x00014808
+#define __APP_LPUCLK_HALFSPEED         0x40000000
+#define __APP_PLL_LCLK_LOAD            0x20000000
+#define __APP_PLL_LCLK_FBCNT_MK                0x1fe00000
+#define __APP_PLL_LCLK_FBCNT_SH                21
+#define __APP_PLL_LCLK_FBCNT(_v)       ((_v) << __APP_PLL_SCLK_FBCNT_SH)
+enum {
+       __APP_PLL_LCLK_FBCNT_425_MHZ = 6,
+       __APP_PLL_LCLK_FBCNT_468_MHZ = 4,
+};
+#define __APP_PLL_LCLK_EXTFB           0x00000800
+#define __APP_PLL_LCLK_ENOUTS          0x00000400
+#define __APP_PLL_LCLK_RATE            0x00000010
+#define CT2_APP_PLL_SCLK_CTL_REG       0x0001480c
+#define __P_SCLK_PLL_LOCK              0x80000000
+#define __APP_PLL_SCLK_REFCLK_SEL      0x40000000
+#define __APP_PLL_SCLK_CLK_DIV2                0x20000000
+#define __APP_PLL_SCLK_LOAD            0x10000000
+#define __APP_PLL_SCLK_FBCNT_MK                0x0ff00000
+#define __APP_PLL_SCLK_FBCNT_SH                20
+#define __APP_PLL_SCLK_FBCNT(_v)       ((_v) << __APP_PLL_SCLK_FBCNT_SH)
+enum {
+       __APP_PLL_SCLK_FBCNT_NORM = 6,
+       __APP_PLL_SCLK_FBCNT_10G_FC = 10,
+};
+#define __APP_PLL_SCLK_EXTFB           0x00000800
+#define __APP_PLL_SCLK_ENOUTS          0x00000400
+#define __APP_PLL_SCLK_RATE            0x00000010
+#define CT2_PCIE_MISC_REG              0x00014804
+#define __ETH_CLK_ENABLE_PORT1         0x00000010
+#define CT2_CHIP_MISC_PRG              0x000148a4
+#define __ETH_CLK_ENABLE_PORT0         0x00004000
+#define __APP_LPU_SPEED                        0x00000002
+#define CT2_MBIST_STAT_REG             0x00014818
+#define CT2_MBIST_CTL_REG              0x0001481c
+#define CT2_PMM_1T_CONTROL_REG_P0      0x0002381c
+#define __PMM_1T_PNDB_P                        0x00000002
+#define CT2_PMM_1T_CONTROL_REG_P1      0x00023c1c
+#define CT2_WGN_STATUS                 0x00014990
+#define __A2T_AHB_LOAD                 0x00000800
+#define __WGN_READY                    0x00000400
+#define __GLBL_PF_VF_CFG_RDY           0x00000200
+#define CT2_NFC_CSR_SET_REG            0x00027424
+#define __HALT_NFC_CONTROLLER          0x00000002
+#define __NFC_CONTROLLER_HALTED                0x00001000
+
+#define CT2_CSI_MAC0_CONTROL_REG       0x000270d0
+#define __CSI_MAC_RESET                        0x00000010
+#define __CSI_MAC_AHB_RESET            0x00000008
+#define CT2_CSI_MAC1_CONTROL_REG       0x000270d4
+#define CT2_CSI_MAC_CONTROL_REG(__n) \
+       (CT2_CSI_MAC0_CONTROL_REG + \
+       (__n) * (CT2_CSI_MAC1_CONTROL_REG - CT2_CSI_MAC0_CONTROL_REG))
+
+/*
+ * Name semaphore registers based on usage
+ */
+#define BFA_IOC0_HBEAT_REG             HOST_SEM0_INFO_REG
+#define BFA_IOC0_STATE_REG             HOST_SEM1_INFO_REG
+#define BFA_IOC1_HBEAT_REG             HOST_SEM2_INFO_REG
+#define BFA_IOC1_STATE_REG             HOST_SEM3_INFO_REG
+#define BFA_FW_USE_COUNT               HOST_SEM4_INFO_REG
+#define BFA_IOC_FAIL_SYNC              HOST_SEM5_INFO_REG
+
+/*
+ * CT2 semaphore register locations changed
+ */
+#define CT2_BFA_IOC0_HBEAT_REG         CT2_HOST_SEM0_INFO_REG
+#define CT2_BFA_IOC0_STATE_REG         CT2_HOST_SEM1_INFO_REG
+#define CT2_BFA_IOC1_HBEAT_REG         CT2_HOST_SEM2_INFO_REG
+#define CT2_BFA_IOC1_STATE_REG         CT2_HOST_SEM3_INFO_REG
+#define CT2_BFA_FW_USE_COUNT           CT2_HOST_SEM4_INFO_REG
+#define CT2_BFA_IOC_FAIL_SYNC          CT2_HOST_SEM5_INFO_REG
+
+#define CPE_Q_NUM(__fn, __q)   (((__fn) << 2) + (__q))
+#define RME_Q_NUM(__fn, __q)   (((__fn) << 2) + (__q))
+
+/*
+ * And corresponding host interrupt status bit field defines
+ */
+#define __HFN_INT_CPE_Q0       0x00000001U
+#define __HFN_INT_CPE_Q1       0x00000002U
+#define __HFN_INT_CPE_Q2       0x00000004U
+#define __HFN_INT_CPE_Q3       0x00000008U
+#define __HFN_INT_CPE_Q4       0x00000010U
+#define __HFN_INT_CPE_Q5       0x00000020U
+#define __HFN_INT_CPE_Q6       0x00000040U
+#define __HFN_INT_CPE_Q7       0x00000080U
+#define __HFN_INT_RME_Q0       0x00000100U
+#define __HFN_INT_RME_Q1       0x00000200U
+#define __HFN_INT_RME_Q2       0x00000400U
+#define __HFN_INT_RME_Q3       0x00000800U
+#define __HFN_INT_RME_Q4       0x00001000U
+#define __HFN_INT_RME_Q5       0x00002000U
+#define __HFN_INT_RME_Q6       0x00004000U
+#define __HFN_INT_RME_Q7       0x00008000U
+#define __HFN_INT_ERR_EMC      0x00010000U
+#define __HFN_INT_ERR_LPU0     0x00020000U
+#define __HFN_INT_ERR_LPU1     0x00040000U
+#define __HFN_INT_ERR_PSS      0x00080000U
+#define __HFN_INT_MBOX_LPU0    0x00100000U
+#define __HFN_INT_MBOX_LPU1    0x00200000U
+#define __HFN_INT_MBOX1_LPU0   0x00400000U
+#define __HFN_INT_MBOX1_LPU1   0x00800000U
+#define __HFN_INT_LL_HALT      0x01000000U
+#define __HFN_INT_CPE_MASK     0x000000ffU
+#define __HFN_INT_RME_MASK     0x0000ff00U
+#define __HFN_INT_ERR_MASK     \
+       (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | __HFN_INT_ERR_LPU1 | \
+        __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT)
+#define __HFN_INT_FN0_MASK     \
+       (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | __HFN_INT_CPE_Q2 | \
+        __HFN_INT_CPE_Q3 | __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 | \
+        __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 | __HFN_INT_MBOX_LPU0)
+#define __HFN_INT_FN1_MASK     \
+       (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 | __HFN_INT_CPE_Q6 | \
+        __HFN_INT_CPE_Q7 | __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 | \
+        __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 | __HFN_INT_MBOX_LPU1)
+
+/*
+ * Host interrupt status defines for 1860
+ */
+#define __HFN_INT_MBOX_LPU0_CT2        0x00010000U
+#define __HFN_INT_MBOX_LPU1_CT2        0x00020000U
+#define __HFN_INT_ERR_PSS_CT2  0x00040000U
+#define __HFN_INT_ERR_LPU0_CT2 0x00080000U
+#define __HFN_INT_ERR_LPU1_CT2 0x00100000U
+#define __HFN_INT_CPQ_HALT_CT2 0x00200000U
+#define __HFN_INT_ERR_WGN_CT2  0x00400000U
+#define __HFN_INT_ERR_LEHRX_CT2        0x00800000U
+#define __HFN_INT_ERR_LEHTX_CT2        0x01000000U
+#define __HFN_INT_ERR_MASK_CT2 \
+       (__HFN_INT_ERR_PSS_CT2 | __HFN_INT_ERR_LPU0_CT2 | \
+        __HFN_INT_ERR_LPU1_CT2 | __HFN_INT_CPQ_HALT_CT2 | \
+        __HFN_INT_ERR_WGN_CT2 | __HFN_INT_ERR_LEHRX_CT2 | \
+        __HFN_INT_ERR_LEHTX_CT2)
+#define __HFN_INT_FN0_MASK_CT2 \
+       (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | __HFN_INT_CPE_Q2 | \
+        __HFN_INT_CPE_Q3 | __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 | \
+        __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 | __HFN_INT_MBOX_LPU0_CT2)
+#define __HFN_INT_FN1_MASK_CT2 \
+       (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 | __HFN_INT_CPE_Q6 | \
+        __HFN_INT_CPE_Q7 | __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 | \
+        __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 | __HFN_INT_MBOX_LPU1_CT2)
+
+/*
+ * asic memory map.
+ */
+#define PSS_SMEM_PAGE_START            0x8000
+#define PSS_SMEM_PGNUM(_pg0, _ma)      ((_pg0) + ((_ma) >> 15))
+#define PSS_SMEM_PGOFF(_ma)            ((_ma) & 0x7fff)
+
+#endif /* __BFI_REG_H__ */
similarity index 67%
rename from drivers/net/bna/bna.h
rename to drivers/net/ethernet/brocade/bna/bna.h
index 21e9155..2a587c5 100644 (file)
@@ -16,7 +16,6 @@
 #include "bfa_cs.h"
 #include "bfa_ioc.h"
 #include "cna.h"
-#include "bfi_ll.h"
 #include "bna_types.h"
 
 extern const u32 bna_napi_dim_vector[][BNA_BIAS_T_MAX];
@@ -32,15 +31,7 @@ extern const u32 bna_napi_dim_vector[][BNA_BIAS_T_MAX];
 /* Log string size */
 #define BNA_MESSAGE_SIZE               256
 
-/* MBOX API for PORT, TX, RX */
-#define bna_mbox_qe_fill(_qe, _cmd, _cmd_len, _cbfn, _cbarg)           \
-do {                                                                   \
-       memcpy(&((_qe)->cmd.msg[0]), (_cmd), (_cmd_len));       \
-       (_qe)->cbfn = (_cbfn);                                          \
-       (_qe)->cbarg = (_cbarg);                                        \
-} while (0)
-
-#define bna_is_small_rxq(rcb) ((rcb)->id == 1)
+#define bna_is_small_rxq(_id) ((_id) & 0x1)
 
 #define BNA_MAC_IS_EQUAL(_mac1, _mac2)                                 \
        (!memcmp((_mac1), (_mac2), sizeof(mac_t)))
@@ -177,32 +168,6 @@ do {                                                               \
 #define BNA_Q_IN_USE_COUNT(_q_ptr)                                     \
        (BNA_QE_IN_USE_CNT(&(_q_ptr)->q, (_q_ptr)->q.q_depth))
 
-/* These macros build the data portion of the TxQ/RxQ doorbell */
-#define BNA_DOORBELL_Q_PRD_IDX(_pi)    (0x80000000 | (_pi))
-#define BNA_DOORBELL_Q_STOP            (0x40000000)
-
-/* These macros build the data portion of the IB doorbell */
-#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
-       (0x80000000 | ((_timeout) << 16) | (_events))
-#define BNA_DOORBELL_IB_INT_DISABLE    (0x40000000)
-
-/* Set the coalescing timer for the given ib */
-#define bna_ib_coalescing_timer_set(_i_dbell, _cls_timer)              \
-       ((_i_dbell)->doorbell_ack = BNA_DOORBELL_IB_INT_ACK((_cls_timer), 0));
-
-/* Acks 'events' # of events for a given ib */
-#define bna_ib_ack(_i_dbell, _events)                                  \
-       (writel(((_i_dbell)->doorbell_ack | (_events)), \
-               (_i_dbell)->doorbell_addr));
-
-#define bna_txq_prod_indx_doorbell(_tcb)                               \
-       (writel(BNA_DOORBELL_Q_PRD_IDX((_tcb)->producer_index), \
-               (_tcb)->q_dbell));
-
-#define bna_rxq_prod_indx_doorbell(_rcb)                               \
-       (writel(BNA_DOORBELL_Q_PRD_IDX((_rcb)->producer_index), \
-               (_rcb)->q_dbell));
-
 #define BNA_LARGE_PKT_SIZE             1000
 
 #define BNA_UPDATE_PKT_CNT(_pkt, _len)                                 \
@@ -214,38 +179,59 @@ do {                                                                      \
        }                                                               \
 } while (0)
 
-#define        call_rxf_stop_cbfn(rxf, status)                                 \
+#define        call_rxf_stop_cbfn(rxf)                                         \
+do {                                                                   \
        if ((rxf)->stop_cbfn) {                                         \
-               (*(rxf)->stop_cbfn)((rxf)->stop_cbarg, (status));       \
+               void (*cbfn)(struct bna_rx *);                  \
+               struct bna_rx *cbarg;                                   \
+               cbfn = (rxf)->stop_cbfn;                                \
+               cbarg = (rxf)->stop_cbarg;                              \
                (rxf)->stop_cbfn = NULL;                                \
                (rxf)->stop_cbarg = NULL;                               \
-       }
+               cbfn(cbarg);                                            \
+       }                                                               \
+} while (0)
 
-#define        call_rxf_start_cbfn(rxf, status)                                \
+#define        call_rxf_start_cbfn(rxf)                                        \
+do {                                                                   \
        if ((rxf)->start_cbfn) {                                        \
-               (*(rxf)->start_cbfn)((rxf)->start_cbarg, (status));     \
+               void (*cbfn)(struct bna_rx *);                  \
+               struct bna_rx *cbarg;                                   \
+               cbfn = (rxf)->start_cbfn;                               \
+               cbarg = (rxf)->start_cbarg;                             \
                (rxf)->start_cbfn = NULL;                               \
                (rxf)->start_cbarg = NULL;                              \
-       }
+               cbfn(cbarg);                                            \
+       }                                                               \
+} while (0)
 
-#define        call_rxf_cam_fltr_cbfn(rxf, status)                             \
+#define        call_rxf_cam_fltr_cbfn(rxf)                                     \
+do {                                                                   \
        if ((rxf)->cam_fltr_cbfn) {                                     \
-               (*(rxf)->cam_fltr_cbfn)((rxf)->cam_fltr_cbarg, rxf->rx, \
-                                       (status));                      \
+               void (*cbfn)(struct bnad *, struct bna_rx *);   \
+               struct bnad *cbarg;                                     \
+               cbfn = (rxf)->cam_fltr_cbfn;                            \
+               cbarg = (rxf)->cam_fltr_cbarg;                          \
                (rxf)->cam_fltr_cbfn = NULL;                            \
                (rxf)->cam_fltr_cbarg = NULL;                           \
-       }
+               cbfn(cbarg, rxf->rx);                                   \
+       }                                                               \
+} while (0)
 
-#define        call_rxf_pause_cbfn(rxf, status)                                \
+#define        call_rxf_pause_cbfn(rxf)                                        \
+do {                                                                   \
        if ((rxf)->oper_state_cbfn) {                                   \
-               (*(rxf)->oper_state_cbfn)((rxf)->oper_state_cbarg, rxf->rx,\
-                                       (status));                      \
-               (rxf)->rxf_flags &= ~BNA_RXF_FL_OPERSTATE_CHANGED;      \
+               void (*cbfn)(struct bnad *, struct bna_rx *);   \
+               struct bnad *cbarg;                                     \
+               cbfn = (rxf)->oper_state_cbfn;                          \
+               cbarg = (rxf)->oper_state_cbarg;                        \
                (rxf)->oper_state_cbfn = NULL;                          \
                (rxf)->oper_state_cbarg = NULL;                         \
-       }
+               cbfn(cbarg, rxf->rx);                                   \
+       }                                                               \
+} while (0)
 
-#define        call_rxf_resume_cbfn(rxf, status) call_rxf_pause_cbfn(rxf, status)
+#define        call_rxf_resume_cbfn(rxf) call_rxf_pause_cbfn(rxf)
 
 #define is_xxx_enable(mode, bitmask, xxx) ((bitmask & xxx) && (mode & xxx))
 
@@ -331,6 +317,61 @@ do {                                                                       \
        }                                                               \
 } while (0)
 
+#define bna_tx_rid_mask(_bna) ((_bna)->tx_mod.rid_mask)
+
+#define bna_rx_rid_mask(_bna) ((_bna)->rx_mod.rid_mask)
+
+#define bna_tx_from_rid(_bna, _rid, _tx)                               \
+do {                                                               \
+       struct bna_tx_mod *__tx_mod = &(_bna)->tx_mod;    \
+       struct bna_tx *__tx;                                        \
+       struct list_head *qe;                                      \
+       _tx = NULL;                                                  \
+       list_for_each(qe, &__tx_mod->tx_active_q) {                  \
+               __tx = (struct bna_tx *)qe;                          \
+               if (__tx->rid == (_rid)) {                            \
+                       (_tx) = __tx;                              \
+                       break;                                    \
+               }                                                      \
+       }                                                              \
+} while (0)
+
+#define bna_rx_from_rid(_bna, _rid, _rx)                               \
+do {                                                                   \
+       struct bna_rx_mod *__rx_mod = &(_bna)->rx_mod;                  \
+       struct bna_rx *__rx;                                            \
+       struct list_head *qe;                                           \
+       _rx = NULL;                                                     \
+       list_for_each(qe, &__rx_mod->rx_active_q) {                     \
+               __rx = (struct bna_rx *)qe;                             \
+               if (__rx->rid == (_rid)) {                              \
+                       (_rx) = __rx;                                   \
+                       break;                                          \
+               }                                                       \
+       }                                                               \
+} while (0)
+
+/**
+ *
+ *  Inline functions
+ *
+ */
+
+static inline struct bna_mac *bna_mac_find(struct list_head *q, u8 *addr)
+{
+       struct bna_mac *mac = NULL;
+       struct list_head *qe;
+       list_for_each(qe, q) {
+               if (BNA_MAC_IS_EQUAL(((struct bna_mac *)qe)->addr, addr)) {
+                       mac = (struct bna_mac *)qe;
+                       break;
+               }
+       }
+       return mac;
+}
+
+#define bna_attr(_bna) (&(_bna)->ioceth.attr)
+
 /**
  *
  * Function prototypes
@@ -341,17 +382,24 @@ do {                                                                      \
  * BNA
  */
 
+/* FW response handlers */
+void bna_bfi_stats_clr_rsp(struct bna *bna, struct bfi_msgq_mhdr *msghdr);
+
 /* APIs for BNAD */
 void bna_res_req(struct bna_res_info *res_info);
+void bna_mod_res_req(struct bna *bna, struct bna_res_info *res_info);
 void bna_init(struct bna *bna, struct bnad *bnad,
                        struct bfa_pcidev *pcidev,
                        struct bna_res_info *res_info);
+void bna_mod_init(struct bna *bna, struct bna_res_info *res_info);
 void bna_uninit(struct bna *bna);
+int bna_num_txq_set(struct bna *bna, int num_txq);
+int bna_num_rxp_set(struct bna *bna, int num_rxp);
 void bna_stats_get(struct bna *bna);
 void bna_get_perm_mac(struct bna *bna, u8 *mac);
+void bna_hw_stats_get(struct bna *bna);
 
 /* APIs for Rx */
-int bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size);
 
 /* APIs for RxF */
 struct bna_mac *bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod);
@@ -360,79 +408,44 @@ void bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod,
 struct bna_mac *bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod);
 void bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod,
                          struct bna_mac *mac);
-struct bna_rit_segment *
-bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size);
-void bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod,
-                       struct bna_rit_segment *seg);
-
-/**
- * DEVICE
- */
-
-/* APIs for BNAD */
-void bna_device_enable(struct bna_device *device);
-void bna_device_disable(struct bna_device *device,
-                       enum bna_cleanup_type type);
+struct bna_mcam_handle *bna_mcam_mod_handle_get(struct bna_mcam_mod *mod);
+void bna_mcam_mod_handle_put(struct bna_mcam_mod *mcam_mod,
+                         struct bna_mcam_handle *handle);
 
 /**
  * MBOX
  */
 
-/* APIs for PORT, TX, RX */
-void bna_mbox_handler(struct bna *bna, u32 intr_status);
-void bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe);
-
-/**
- * PORT
- */
-
-/* API for RX */
-int bna_port_mtu_get(struct bna_port *port);
-void bna_llport_rx_started(struct bna_llport *llport);
-void bna_llport_rx_stopped(struct bna_llport *llport);
-
 /* API for BNAD */
-void bna_port_enable(struct bna_port *port);
-void bna_port_disable(struct bna_port *port, enum bna_cleanup_type type,
-                     void (*cbfn)(void *, enum bna_cb_status));
-void bna_port_pause_config(struct bna_port *port,
-                          struct bna_pause_config *pause_config,
-                          void (*cbfn)(struct bnad *, enum bna_cb_status));
-void bna_port_mtu_set(struct bna_port *port, int mtu,
-                     void (*cbfn)(struct bnad *, enum bna_cb_status));
-void bna_port_mac_get(struct bna_port *port, mac_t *mac);
-
-/* Callbacks for TX, RX */
-void bna_port_cb_tx_stopped(struct bna_port *port,
-                           enum bna_cb_status status);
-void bna_port_cb_rx_stopped(struct bna_port *port,
-                           enum bna_cb_status status);
+void bna_mbox_handler(struct bna *bna, u32 intr_status);
 
 /**
- * IB
+ * ETHPORT
  */
 
-/* APIs for BNA */
-void bna_ib_mod_init(struct bna_ib_mod *ib_mod, struct bna *bna,
-                    struct bna_res_info *res_info);
-void bna_ib_mod_uninit(struct bna_ib_mod *ib_mod);
+/* Callbacks for RX */
+void bna_ethport_cb_rx_started(struct bna_ethport *ethport);
+void bna_ethport_cb_rx_stopped(struct bna_ethport *ethport);
 
 /**
  * TX MODULE AND TX
  */
+/* FW response handelrs */
+void bna_bfi_tx_enet_start_rsp(struct bna_tx *tx,
+                              struct bfi_msgq_mhdr *msghdr);
+void bna_bfi_tx_enet_stop_rsp(struct bna_tx *tx,
+                             struct bfi_msgq_mhdr *msghdr);
+void bna_bfi_bw_update_aen(struct bna_tx_mod *tx_mod);
 
 /* APIs for BNA */
 void bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna,
                     struct bna_res_info *res_info);
 void bna_tx_mod_uninit(struct bna_tx_mod *tx_mod);
-int bna_tx_state_get(struct bna_tx *tx);
 
-/* APIs for PORT */
+/* APIs for ENET */
 void bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type);
 void bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type);
 void bna_tx_mod_fail(struct bna_tx_mod *tx_mod);
-void bna_tx_mod_prio_changed(struct bna_tx_mod *tx_mod, int prio);
-void bna_tx_mod_cee_link_status(struct bna_tx_mod *tx_mod, int cee_link);
 
 /* APIs for BNAD */
 void bna_tx_res_req(int num_txq, int txq_depth,
@@ -444,43 +457,29 @@ struct bna_tx *bna_tx_create(struct bna *bna, struct bnad *bnad,
 void bna_tx_destroy(struct bna_tx *tx);
 void bna_tx_enable(struct bna_tx *tx);
 void bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type,
-                   void (*cbfn)(void *, struct bna_tx *,
-                                enum bna_cb_status));
+                   void (*cbfn)(void *, struct bna_tx *));
+void bna_tx_cleanup_complete(struct bna_tx *tx);
 void bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo);
 
 /**
  * RX MODULE, RX, RXF
  */
 
-/* Internal APIs */
-void rxf_cb_cam_fltr_mbox_cmd(void *arg, int status);
-void rxf_cam_mbox_cmd(struct bna_rxf *rxf, u8 cmd,
-               const struct bna_mac *mac_addr);
-void __rxf_vlan_filter_set(struct bna_rxf *rxf, enum bna_status status);
-void bna_rxf_adv_init(struct bna_rxf *rxf,
-               struct bna_rx *rx,
-               struct bna_rx_config *q_config);
-int rxf_process_packet_filter_ucast(struct bna_rxf *rxf);
-int rxf_process_packet_filter_promisc(struct bna_rxf *rxf);
-int rxf_process_packet_filter_default(struct bna_rxf *rxf);
-int rxf_process_packet_filter_allmulti(struct bna_rxf *rxf);
-int rxf_clear_packet_filter_ucast(struct bna_rxf *rxf);
-int rxf_clear_packet_filter_promisc(struct bna_rxf *rxf);
-int rxf_clear_packet_filter_default(struct bna_rxf *rxf);
-int rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf);
-void rxf_reset_packet_filter_ucast(struct bna_rxf *rxf);
-void rxf_reset_packet_filter_promisc(struct bna_rxf *rxf);
-void rxf_reset_packet_filter_default(struct bna_rxf *rxf);
-void rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf);
+/* FW response handlers */
+void bna_bfi_rx_enet_start_rsp(struct bna_rx *rx,
+                              struct bfi_msgq_mhdr *msghdr);
+void bna_bfi_rx_enet_stop_rsp(struct bna_rx *rx,
+                             struct bfi_msgq_mhdr *msghdr);
+void bna_bfi_rxf_cfg_rsp(struct bna_rxf *rxf, struct bfi_msgq_mhdr *msghdr);
+void bna_bfi_rxf_mcast_add_rsp(struct bna_rxf *rxf,
+                              struct bfi_msgq_mhdr *msghdr);
 
 /* APIs for BNA */
 void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
                     struct bna_res_info *res_info);
 void bna_rx_mod_uninit(struct bna_rx_mod *rx_mod);
-int bna_rx_state_get(struct bna_rx *rx);
-int bna_rxf_state_get(struct bna_rxf *rxf);
 
-/* APIs for PORT */
+/* APIs for ENET */
 void bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type);
 void bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type);
 void bna_rx_mod_fail(struct bna_rx_mod *rx_mod);
@@ -495,54 +494,86 @@ struct bna_rx *bna_rx_create(struct bna *bna, struct bnad *bnad,
 void bna_rx_destroy(struct bna_rx *rx);
 void bna_rx_enable(struct bna_rx *rx);
 void bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type,
-                   void (*cbfn)(void *, struct bna_rx *,
-                                enum bna_cb_status));
+                   void (*cbfn)(void *, struct bna_rx *));
+void bna_rx_cleanup_complete(struct bna_rx *rx);
 void bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo);
 void bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX]);
 void bna_rx_dim_update(struct bna_ccb *ccb);
 enum bna_cb_status
 bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,
-                void (*cbfn)(struct bnad *, struct bna_rx *,
-                             enum bna_cb_status));
+                void (*cbfn)(struct bnad *, struct bna_rx *));
+enum bna_cb_status
+bna_rx_ucast_add(struct bna_rx *rx, u8* ucmac,
+                void (*cbfn)(struct bnad *, struct bna_rx *));
+enum bna_cb_status
+bna_rx_ucast_del(struct bna_rx *rx, u8 *ucmac,
+                void (*cbfn)(struct bnad *, struct bna_rx *));
 enum bna_cb_status
 bna_rx_mcast_add(struct bna_rx *rx, u8 *mcmac,
-                void (*cbfn)(struct bnad *, struct bna_rx *,
-                             enum bna_cb_status));
+                void (*cbfn)(struct bnad *, struct bna_rx *));
 enum bna_cb_status
 bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mcmac,
-                    void (*cbfn)(struct bnad *, struct bna_rx *,
-                                 enum bna_cb_status));
+                    void (*cbfn)(struct bnad *, struct bna_rx *));
 enum bna_cb_status
 bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode rxmode,
                enum bna_rxmode bitmask,
-               void (*cbfn)(struct bnad *, struct bna_rx *,
-                            enum bna_cb_status));
+               void (*cbfn)(struct bnad *, struct bna_rx *));
 void bna_rx_vlan_add(struct bna_rx *rx, int vlan_id);
 void bna_rx_vlan_del(struct bna_rx *rx, int vlan_id);
 void bna_rx_vlanfilter_enable(struct bna_rx *rx);
-void bna_rx_hds_enable(struct bna_rx *rx, struct bna_rxf_hds *hds_config,
-                      void (*cbfn)(struct bnad *, struct bna_rx *,
-                                   enum bna_cb_status));
+void bna_rx_hds_enable(struct bna_rx *rx, struct bna_hds_config *hds_config,
+                      void (*cbfn)(struct bnad *, struct bna_rx *));
 void bna_rx_hds_disable(struct bna_rx *rx,
-                       void (*cbfn)(struct bnad *, struct bna_rx *,
-                                    enum bna_cb_status));
+                       void (*cbfn)(struct bnad *, struct bna_rx *));
+
+/**
+ * ENET
+ */
+
+/* API for RX */
+int bna_enet_mtu_get(struct bna_enet *enet);
+
+/* Callbacks for TX, RX */
+void bna_enet_cb_tx_stopped(struct bna_enet *enet);
+void bna_enet_cb_rx_stopped(struct bna_enet *enet);
+
+/* API for BNAD */
+void bna_enet_enable(struct bna_enet *enet);
+void bna_enet_disable(struct bna_enet *enet, enum bna_cleanup_type type,
+                     void (*cbfn)(void *));
+void bna_enet_pause_config(struct bna_enet *enet,
+                          struct bna_pause_config *pause_config,
+                          void (*cbfn)(struct bnad *));
+void bna_enet_mtu_set(struct bna_enet *enet, int mtu,
+                     void (*cbfn)(struct bnad *));
+void bna_enet_perm_mac_get(struct bna_enet *enet, mac_t *mac);
+
+/**
+ * IOCETH
+ */
+
+/* APIs for BNAD */
+void bna_ioceth_enable(struct bna_ioceth *ioceth);
+void bna_ioceth_disable(struct bna_ioceth *ioceth,
+                       enum bna_cleanup_type type);
 
 /**
  * BNAD
  */
 
+/* Callbacks for ENET */
+void bnad_cb_ethport_link_status(struct bnad *bnad,
+                             enum bna_link_status status);
+
+/* Callbacks for IOCETH */
+void bnad_cb_ioceth_ready(struct bnad *bnad);
+void bnad_cb_ioceth_failed(struct bnad *bnad);
+void bnad_cb_ioceth_disabled(struct bnad *bnad);
+void bnad_cb_mbox_intr_enable(struct bnad *bnad);
+void bnad_cb_mbox_intr_disable(struct bnad *bnad);
+
 /* Callbacks for BNA */
 void bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status,
                       struct bna_stats *stats);
 
-/* Callbacks for DEVICE */
-void bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status);
-void bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status);
-void bnad_cb_device_enable_mbox_intr(struct bnad *bnad);
-void bnad_cb_device_disable_mbox_intr(struct bnad *bnad);
-
-/* Callbacks for port */
-void bnad_cb_port_link_status(struct bnad *bnad,
-                             enum bna_link_status status);
-
 #endif  /* __BNA_H__ */
diff --git a/drivers/net/ethernet/brocade/bna/bna_enet.c b/drivers/net/ethernet/brocade/bna/bna_enet.c
new file mode 100644 (file)
index 0000000..68a275d
--- /dev/null
@@ -0,0 +1,2129 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.
+ */
+/*
+ * Copyright (c) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#include "bna.h"
+
+static inline int
+ethport_can_be_up(struct bna_ethport *ethport)
+{
+       int ready = 0;
+       if (ethport->bna->enet.type == BNA_ENET_T_REGULAR)
+               ready = ((ethport->flags & BNA_ETHPORT_F_ADMIN_UP) &&
+                        (ethport->flags & BNA_ETHPORT_F_RX_STARTED) &&
+                        (ethport->flags & BNA_ETHPORT_F_PORT_ENABLED));
+       else
+               ready = ((ethport->flags & BNA_ETHPORT_F_ADMIN_UP) &&
+                        (ethport->flags & BNA_ETHPORT_F_RX_STARTED) &&
+                        !(ethport->flags & BNA_ETHPORT_F_PORT_ENABLED));
+       return ready;
+}
+
+#define ethport_is_up ethport_can_be_up
+
+enum bna_ethport_event {
+       ETHPORT_E_START                 = 1,
+       ETHPORT_E_STOP                  = 2,
+       ETHPORT_E_FAIL                  = 3,
+       ETHPORT_E_UP                    = 4,
+       ETHPORT_E_DOWN                  = 5,
+       ETHPORT_E_FWRESP_UP_OK          = 6,
+       ETHPORT_E_FWRESP_DOWN           = 7,
+       ETHPORT_E_FWRESP_UP_FAIL        = 8,
+};
+
+enum bna_enet_event {
+       ENET_E_START                    = 1,
+       ENET_E_STOP                     = 2,
+       ENET_E_FAIL                     = 3,
+       ENET_E_PAUSE_CFG                = 4,
+       ENET_E_MTU_CFG                  = 5,
+       ENET_E_FWRESP_PAUSE             = 6,
+       ENET_E_CHLD_STOPPED             = 7,
+};
+
+enum bna_ioceth_event {
+       IOCETH_E_ENABLE                 = 1,
+       IOCETH_E_DISABLE                = 2,
+       IOCETH_E_IOC_RESET              = 3,
+       IOCETH_E_IOC_FAILED             = 4,
+       IOCETH_E_IOC_READY              = 5,
+       IOCETH_E_ENET_ATTR_RESP         = 6,
+       IOCETH_E_ENET_STOPPED           = 7,
+       IOCETH_E_IOC_DISABLED           = 8,
+};
+
+#define bna_stats_copy(_name, _type)                                   \
+do {                                                                   \
+       count = sizeof(struct bfi_enet_stats_ ## _type) / sizeof(u64);  \
+       stats_src = (u64 *)&bna->stats.hw_stats_kva->_name ## _stats;   \
+       stats_dst = (u64 *)&bna->stats.hw_stats._name ## _stats;        \
+       for (i = 0; i < count; i++)                                     \
+               stats_dst[i] = be64_to_cpu(stats_src[i]);               \
+} while (0)                                                            \
+
+/*
+ * FW response handlers
+ */
+
+static void
+bna_bfi_ethport_enable_aen(struct bna_ethport *ethport,
+                               struct bfi_msgq_mhdr *msghdr)
+{
+       ethport->flags |= BNA_ETHPORT_F_PORT_ENABLED;
+
+       if (ethport_can_be_up(ethport))
+               bfa_fsm_send_event(ethport, ETHPORT_E_UP);
+}
+
+static void
+bna_bfi_ethport_disable_aen(struct bna_ethport *ethport,
+                               struct bfi_msgq_mhdr *msghdr)
+{
+       int ethport_up = ethport_is_up(ethport);
+
+       ethport->flags &= ~BNA_ETHPORT_F_PORT_ENABLED;
+
+       if (ethport_up)
+               bfa_fsm_send_event(ethport, ETHPORT_E_DOWN);
+}
+
+static void
+bna_bfi_ethport_admin_rsp(struct bna_ethport *ethport,
+                               struct bfi_msgq_mhdr *msghdr)
+{
+       struct bfi_enet_enable_req *admin_req =
+               &ethport->bfi_enet_cmd.admin_req;
+       struct bfi_enet_rsp *rsp = (struct bfi_enet_rsp *)msghdr;
+
+       switch (admin_req->enable) {
+       case BNA_STATUS_T_ENABLED:
+               if (rsp->error == BFI_ENET_CMD_OK)
+                       bfa_fsm_send_event(ethport, ETHPORT_E_FWRESP_UP_OK);
+               else {
+                       ethport->flags &= ~BNA_ETHPORT_F_PORT_ENABLED;
+                       bfa_fsm_send_event(ethport, ETHPORT_E_FWRESP_UP_FAIL);
+               }
+               break;
+
+       case BNA_STATUS_T_DISABLED:
+               bfa_fsm_send_event(ethport, ETHPORT_E_FWRESP_DOWN);
+               ethport->link_status = BNA_LINK_DOWN;
+               ethport->link_cbfn(ethport->bna->bnad, BNA_LINK_DOWN);
+               break;
+       }
+}
+
+static void
+bna_bfi_ethport_lpbk_rsp(struct bna_ethport *ethport,
+                               struct bfi_msgq_mhdr *msghdr)
+{
+       struct bfi_enet_diag_lb_req *diag_lb_req =
+               &ethport->bfi_enet_cmd.lpbk_req;
+       struct bfi_enet_rsp *rsp = (struct bfi_enet_rsp *)msghdr;
+
+       switch (diag_lb_req->enable) {
+       case BNA_STATUS_T_ENABLED:
+               if (rsp->error == BFI_ENET_CMD_OK)
+                       bfa_fsm_send_event(ethport, ETHPORT_E_FWRESP_UP_OK);
+               else {
+                       ethport->flags &= ~BNA_ETHPORT_F_ADMIN_UP;
+                       bfa_fsm_send_event(ethport, ETHPORT_E_FWRESP_UP_FAIL);
+               }
+               break;
+
+       case BNA_STATUS_T_DISABLED:
+               bfa_fsm_send_event(ethport, ETHPORT_E_FWRESP_DOWN);
+               break;
+       }
+}
+
+static void
+bna_bfi_pause_set_rsp(struct bna_enet *enet, struct bfi_msgq_mhdr *msghdr)
+{
+       bfa_fsm_send_event(enet, ENET_E_FWRESP_PAUSE);
+}
+
+static void
+bna_bfi_attr_get_rsp(struct bna_ioceth *ioceth,
+                       struct bfi_msgq_mhdr *msghdr)
+{
+       struct bfi_enet_attr_rsp *rsp = (struct bfi_enet_attr_rsp *)msghdr;
+
+       /**
+        * Store only if not set earlier, since BNAD can override the HW
+        * attributes
+        */
+       if (!ioceth->attr.num_txq)
+               ioceth->attr.num_txq = ntohl(rsp->max_cfg);
+       if (!ioceth->attr.num_rxp)
+               ioceth->attr.num_rxp = ntohl(rsp->max_cfg);
+       ioceth->attr.num_ucmac = ntohl(rsp->max_ucmac);
+       ioceth->attr.num_mcmac = BFI_ENET_MAX_MCAM;
+       ioceth->attr.max_rit_size = ntohl(rsp->rit_size);
+
+       bfa_fsm_send_event(ioceth, IOCETH_E_ENET_ATTR_RESP);
+}
+
+static void
+bna_bfi_stats_get_rsp(struct bna *bna, struct bfi_msgq_mhdr *msghdr)
+{
+       struct bfi_enet_stats_req *stats_req = &bna->stats_mod.stats_get;
+       u64 *stats_src;
+       u64 *stats_dst;
+       u32 tx_enet_mask = ntohl(stats_req->tx_enet_mask);
+       u32 rx_enet_mask = ntohl(stats_req->rx_enet_mask);
+       int count;
+       int i;
+
+       bna_stats_copy(mac, mac);
+       bna_stats_copy(bpc, bpc);
+       bna_stats_copy(rad, rad);
+       bna_stats_copy(rlb, rad);
+       bna_stats_copy(fc_rx, fc_rx);
+       bna_stats_copy(fc_tx, fc_tx);
+
+       stats_src = (u64 *)&(bna->stats.hw_stats_kva->rxf_stats[0]);
+
+       /* Copy Rxf stats to SW area, scatter them while copying */
+       for (i = 0; i < BFI_ENET_CFG_MAX; i++) {
+               stats_dst = (u64 *)&(bna->stats.hw_stats.rxf_stats[i]);
+               memset(stats_dst, 0, sizeof(struct bfi_enet_stats_rxf));
+               if (rx_enet_mask & ((u32)(1 << i))) {
+                       int k;
+                       count = sizeof(struct bfi_enet_stats_rxf) /
+                               sizeof(u64);
+                       for (k = 0; k < count; k++) {
+                               stats_dst[k] = be64_to_cpu(*stats_src);
+                               stats_src++;
+                       }
+               }
+       }
+
+       /* Copy Txf stats to SW area, scatter them while copying */
+       for (i = 0; i < BFI_ENET_CFG_MAX; i++) {
+               stats_dst = (u64 *)&(bna->stats.hw_stats.txf_stats[i]);
+               memset(stats_dst, 0, sizeof(struct bfi_enet_stats_txf));
+               if (tx_enet_mask & ((u32)(1 << i))) {
+                       int k;
+                       count = sizeof(struct bfi_enet_stats_txf) /
+                               sizeof(u64);
+                       for (k = 0; k < count; k++) {
+                               stats_dst[k] = be64_to_cpu(*stats_src);
+                               stats_src++;
+                       }
+               }
+       }
+
+       bna->stats_mod.stats_get_busy = false;
+       bnad_cb_stats_get(bna->bnad, BNA_CB_SUCCESS, &bna->stats);
+}
+
+static void
+bna_bfi_ethport_linkup_aen(struct bna_ethport *ethport,
+                       struct bfi_msgq_mhdr *msghdr)
+{
+       ethport->link_status = BNA_LINK_UP;
+
+       /* Dispatch events */
+       ethport->link_cbfn(ethport->bna->bnad, ethport->link_status);
+}
+
+static void
+bna_bfi_ethport_linkdown_aen(struct bna_ethport *ethport,
+                               struct bfi_msgq_mhdr *msghdr)
+{
+       ethport->link_status = BNA_LINK_DOWN;
+
+       /* Dispatch events */
+       ethport->link_cbfn(ethport->bna->bnad, BNA_LINK_DOWN);
+}
+
+static void
+bna_err_handler(struct bna *bna, u32 intr_status)
+{
+       if (BNA_IS_HALT_INTR(bna, intr_status))
+               bna_halt_clear(bna);
+
+       bfa_nw_ioc_error_isr(&bna->ioceth.ioc);
+}
+
+void
+bna_mbox_handler(struct bna *bna, u32 intr_status)
+{
+       if (BNA_IS_ERR_INTR(bna, intr_status)) {
+               bna_err_handler(bna, intr_status);
+               return;
+       }
+       if (BNA_IS_MBOX_INTR(bna, intr_status))
+               bfa_nw_ioc_mbox_isr(&bna->ioceth.ioc);
+}
+
+static void
+bna_msgq_rsp_handler(void *arg, struct bfi_msgq_mhdr *msghdr)
+{
+       struct bna *bna = (struct bna *)arg;
+       struct bna_tx *tx;
+       struct bna_rx *rx;
+
+       switch (msghdr->msg_id) {
+       case BFI_ENET_I2H_RX_CFG_SET_RSP:
+               bna_rx_from_rid(bna, msghdr->enet_id, rx);
+               if (rx)
+                       bna_bfi_rx_enet_start_rsp(rx, msghdr);
+               break;
+
+       case BFI_ENET_I2H_RX_CFG_CLR_RSP:
+               bna_rx_from_rid(bna, msghdr->enet_id, rx);
+               if (rx)
+                       bna_bfi_rx_enet_stop_rsp(rx, msghdr);
+               break;
+
+       case BFI_ENET_I2H_RIT_CFG_RSP:
+       case BFI_ENET_I2H_RSS_CFG_RSP:
+       case BFI_ENET_I2H_RSS_ENABLE_RSP:
+       case BFI_ENET_I2H_RX_PROMISCUOUS_RSP:
+       case BFI_ENET_I2H_RX_DEFAULT_RSP:
+       case BFI_ENET_I2H_MAC_UCAST_SET_RSP:
+       case BFI_ENET_I2H_MAC_UCAST_CLR_RSP:
+       case BFI_ENET_I2H_MAC_UCAST_ADD_RSP:
+       case BFI_ENET_I2H_MAC_UCAST_DEL_RSP:
+       case BFI_ENET_I2H_MAC_MCAST_DEL_RSP:
+       case BFI_ENET_I2H_MAC_MCAST_FILTER_RSP:
+       case BFI_ENET_I2H_RX_VLAN_SET_RSP:
+       case BFI_ENET_I2H_RX_VLAN_STRIP_ENABLE_RSP:
+               bna_rx_from_rid(bna, msghdr->enet_id, rx);
+               if (rx)
+                       bna_bfi_rxf_cfg_rsp(&rx->rxf, msghdr);
+               break;
+
+       case BFI_ENET_I2H_MAC_MCAST_ADD_RSP:
+               bna_rx_from_rid(bna, msghdr->enet_id, rx);
+               if (rx)
+                       bna_bfi_rxf_mcast_add_rsp(&rx->rxf, msghdr);
+               break;
+
+       case BFI_ENET_I2H_TX_CFG_SET_RSP:
+               bna_tx_from_rid(bna, msghdr->enet_id, tx);
+               if (tx)
+                       bna_bfi_tx_enet_start_rsp(tx, msghdr);
+               break;
+
+       case BFI_ENET_I2H_TX_CFG_CLR_RSP:
+               bna_tx_from_rid(bna, msghdr->enet_id, tx);
+               if (tx)
+                       bna_bfi_tx_enet_stop_rsp(tx, msghdr);
+               break;
+
+       case BFI_ENET_I2H_PORT_ADMIN_RSP:
+               bna_bfi_ethport_admin_rsp(&bna->ethport, msghdr);
+               break;
+
+       case BFI_ENET_I2H_DIAG_LOOPBACK_RSP:
+               bna_bfi_ethport_lpbk_rsp(&bna->ethport, msghdr);
+               break;
+
+       case BFI_ENET_I2H_SET_PAUSE_RSP:
+               bna_bfi_pause_set_rsp(&bna->enet, msghdr);
+               break;
+
+       case BFI_ENET_I2H_GET_ATTR_RSP:
+               bna_bfi_attr_get_rsp(&bna->ioceth, msghdr);
+               break;
+
+       case BFI_ENET_I2H_STATS_GET_RSP:
+               bna_bfi_stats_get_rsp(bna, msghdr);
+               break;
+
+       case BFI_ENET_I2H_STATS_CLR_RSP:
+               /* No-op */
+               break;
+
+       case BFI_ENET_I2H_LINK_UP_AEN:
+               bna_bfi_ethport_linkup_aen(&bna->ethport, msghdr);
+               break;
+
+       case BFI_ENET_I2H_LINK_DOWN_AEN:
+               bna_bfi_ethport_linkdown_aen(&bna->ethport, msghdr);
+               break;
+
+       case BFI_ENET_I2H_PORT_ENABLE_AEN:
+               bna_bfi_ethport_enable_aen(&bna->ethport, msghdr);
+               break;
+
+       case BFI_ENET_I2H_PORT_DISABLE_AEN:
+               bna_bfi_ethport_disable_aen(&bna->ethport, msghdr);
+               break;
+
+       case BFI_ENET_I2H_BW_UPDATE_AEN:
+               bna_bfi_bw_update_aen(&bna->tx_mod);
+               break;
+
+       default:
+               break;
+       }
+}
+
+/**
+ * ETHPORT
+ */
+#define call_ethport_stop_cbfn(_ethport)                               \
+do {                                                                   \
+       if ((_ethport)->stop_cbfn) {                                    \
+               void (*cbfn)(struct bna_enet *);                        \
+               cbfn = (_ethport)->stop_cbfn;                           \
+               (_ethport)->stop_cbfn = NULL;                           \
+               cbfn(&(_ethport)->bna->enet);                           \
+       }                                                               \
+} while (0)
+
+#define call_ethport_adminup_cbfn(ethport, status)                     \
+do {                                                                   \
+       if ((ethport)->adminup_cbfn) {                                  \
+               void (*cbfn)(struct bnad *, enum bna_cb_status);        \
+               cbfn = (ethport)->adminup_cbfn;                         \
+               (ethport)->adminup_cbfn = NULL;                         \
+               cbfn((ethport)->bna->bnad, status);                     \
+       }                                                               \
+} while (0)
+
+static void
+bna_bfi_ethport_admin_up(struct bna_ethport *ethport)
+{
+       struct bfi_enet_enable_req *admin_up_req =
+               &ethport->bfi_enet_cmd.admin_req;
+
+       bfi_msgq_mhdr_set(admin_up_req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_PORT_ADMIN_UP_REQ, 0, 0);
+       admin_up_req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_enable_req)));
+       admin_up_req->enable = BNA_STATUS_T_ENABLED;
+
+       bfa_msgq_cmd_set(&ethport->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_enable_req), &admin_up_req->mh);
+       bfa_msgq_cmd_post(&ethport->bna->msgq, &ethport->msgq_cmd);
+}
+
+static void
+bna_bfi_ethport_admin_down(struct bna_ethport *ethport)
+{
+       struct bfi_enet_enable_req *admin_down_req =
+               &ethport->bfi_enet_cmd.admin_req;
+
+       bfi_msgq_mhdr_set(admin_down_req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_PORT_ADMIN_UP_REQ, 0, 0);
+       admin_down_req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_enable_req)));
+       admin_down_req->enable = BNA_STATUS_T_DISABLED;
+
+       bfa_msgq_cmd_set(&ethport->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_enable_req), &admin_down_req->mh);
+       bfa_msgq_cmd_post(&ethport->bna->msgq, &ethport->msgq_cmd);
+}
+
+static void
+bna_bfi_ethport_lpbk_up(struct bna_ethport *ethport)
+{
+       struct bfi_enet_diag_lb_req *lpbk_up_req =
+               &ethport->bfi_enet_cmd.lpbk_req;
+
+       bfi_msgq_mhdr_set(lpbk_up_req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_DIAG_LOOPBACK_REQ, 0, 0);
+       lpbk_up_req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_diag_lb_req)));
+       lpbk_up_req->mode = (ethport->bna->enet.type ==
+                               BNA_ENET_T_LOOPBACK_INTERNAL) ?
+                               BFI_ENET_DIAG_LB_OPMODE_EXT :
+                               BFI_ENET_DIAG_LB_OPMODE_CBL;
+       lpbk_up_req->enable = BNA_STATUS_T_ENABLED;
+
+       bfa_msgq_cmd_set(&ethport->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_diag_lb_req), &lpbk_up_req->mh);
+       bfa_msgq_cmd_post(&ethport->bna->msgq, &ethport->msgq_cmd);
+}
+
+static void
+bna_bfi_ethport_lpbk_down(struct bna_ethport *ethport)
+{
+       struct bfi_enet_diag_lb_req *lpbk_down_req =
+               &ethport->bfi_enet_cmd.lpbk_req;
+
+       bfi_msgq_mhdr_set(lpbk_down_req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_DIAG_LOOPBACK_REQ, 0, 0);
+       lpbk_down_req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_diag_lb_req)));
+       lpbk_down_req->enable = BNA_STATUS_T_DISABLED;
+
+       bfa_msgq_cmd_set(&ethport->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_diag_lb_req), &lpbk_down_req->mh);
+       bfa_msgq_cmd_post(&ethport->bna->msgq, &ethport->msgq_cmd);
+}
+
+static void
+bna_bfi_ethport_up(struct bna_ethport *ethport)
+{
+       if (ethport->bna->enet.type == BNA_ENET_T_REGULAR)
+               bna_bfi_ethport_admin_up(ethport);
+       else
+               bna_bfi_ethport_lpbk_up(ethport);
+}
+
+static void
+bna_bfi_ethport_down(struct bna_ethport *ethport)
+{
+       if (ethport->bna->enet.type == BNA_ENET_T_REGULAR)
+               bna_bfi_ethport_admin_down(ethport);
+       else
+               bna_bfi_ethport_lpbk_down(ethport);
+}
+
+bfa_fsm_state_decl(bna_ethport, stopped, struct bna_ethport,
+                       enum bna_ethport_event);
+bfa_fsm_state_decl(bna_ethport, down, struct bna_ethport,
+                       enum bna_ethport_event);
+bfa_fsm_state_decl(bna_ethport, up_resp_wait, struct bna_ethport,
+                       enum bna_ethport_event);
+bfa_fsm_state_decl(bna_ethport, down_resp_wait, struct bna_ethport,
+                       enum bna_ethport_event);
+bfa_fsm_state_decl(bna_ethport, up, struct bna_ethport,
+                       enum bna_ethport_event);
+bfa_fsm_state_decl(bna_ethport, last_resp_wait, struct bna_ethport,
+                       enum bna_ethport_event);
+
+static void
+bna_ethport_sm_stopped_entry(struct bna_ethport *ethport)
+{
+       call_ethport_stop_cbfn(ethport);
+}
+
+static void
+bna_ethport_sm_stopped(struct bna_ethport *ethport,
+                       enum bna_ethport_event event)
+{
+       switch (event) {
+       case ETHPORT_E_START:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_down);
+               break;
+
+       case ETHPORT_E_STOP:
+               call_ethport_stop_cbfn(ethport);
+               break;
+
+       case ETHPORT_E_FAIL:
+               /* No-op */
+               break;
+
+       case ETHPORT_E_DOWN:
+               /* This event is received due to Rx objects failing */
+               /* No-op */
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ethport_sm_down_entry(struct bna_ethport *ethport)
+{
+}
+
+static void
+bna_ethport_sm_down(struct bna_ethport *ethport,
+                       enum bna_ethport_event event)
+{
+       switch (event) {
+       case ETHPORT_E_STOP:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+               break;
+
+       case ETHPORT_E_FAIL:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+               break;
+
+       case ETHPORT_E_UP:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_up_resp_wait);
+               bna_bfi_ethport_up(ethport);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ethport_sm_up_resp_wait_entry(struct bna_ethport *ethport)
+{
+}
+
+static void
+bna_ethport_sm_up_resp_wait(struct bna_ethport *ethport,
+                       enum bna_ethport_event event)
+{
+       switch (event) {
+       case ETHPORT_E_STOP:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_last_resp_wait);
+               break;
+
+       case ETHPORT_E_FAIL:
+               call_ethport_adminup_cbfn(ethport, BNA_CB_FAIL);
+               bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+               break;
+
+       case ETHPORT_E_DOWN:
+               call_ethport_adminup_cbfn(ethport, BNA_CB_INTERRUPT);
+               bfa_fsm_set_state(ethport, bna_ethport_sm_down_resp_wait);
+               break;
+
+       case ETHPORT_E_FWRESP_UP_OK:
+               call_ethport_adminup_cbfn(ethport, BNA_CB_SUCCESS);
+               bfa_fsm_set_state(ethport, bna_ethport_sm_up);
+               break;
+
+       case ETHPORT_E_FWRESP_UP_FAIL:
+               call_ethport_adminup_cbfn(ethport, BNA_CB_FAIL);
+               bfa_fsm_set_state(ethport, bna_ethport_sm_down);
+               break;
+
+       case ETHPORT_E_FWRESP_DOWN:
+               /* down_resp_wait -> up_resp_wait transition on ETHPORT_E_UP */
+               bna_bfi_ethport_up(ethport);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ethport_sm_down_resp_wait_entry(struct bna_ethport *ethport)
+{
+       /**
+        * NOTE: Do not call bna_bfi_ethport_down() here. That will over step
+        * mbox due to up_resp_wait -> down_resp_wait transition on event
+        * ETHPORT_E_DOWN
+        */
+}
+
+static void
+bna_ethport_sm_down_resp_wait(struct bna_ethport *ethport,
+                       enum bna_ethport_event event)
+{
+       switch (event) {
+       case ETHPORT_E_STOP:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_last_resp_wait);
+               break;
+
+       case ETHPORT_E_FAIL:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+               break;
+
+       case ETHPORT_E_UP:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_up_resp_wait);
+               break;
+
+       case ETHPORT_E_FWRESP_UP_OK:
+               /* up_resp_wait->down_resp_wait transition on ETHPORT_E_DOWN */
+               bna_bfi_ethport_down(ethport);
+               break;
+
+       case ETHPORT_E_FWRESP_UP_FAIL:
+       case ETHPORT_E_FWRESP_DOWN:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_down);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ethport_sm_up_entry(struct bna_ethport *ethport)
+{
+}
+
+static void
+bna_ethport_sm_up(struct bna_ethport *ethport,
+                       enum bna_ethport_event event)
+{
+       switch (event) {
+       case ETHPORT_E_STOP:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_last_resp_wait);
+               bna_bfi_ethport_down(ethport);
+               break;
+
+       case ETHPORT_E_FAIL:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+               break;
+
+       case ETHPORT_E_DOWN:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_down_resp_wait);
+               bna_bfi_ethport_down(ethport);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ethport_sm_last_resp_wait_entry(struct bna_ethport *ethport)
+{
+}
+
+static void
+bna_ethport_sm_last_resp_wait(struct bna_ethport *ethport,
+                       enum bna_ethport_event event)
+{
+       switch (event) {
+       case ETHPORT_E_FAIL:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+               break;
+
+       case ETHPORT_E_DOWN:
+               /**
+                * This event is received due to Rx objects stopping in
+                * parallel to ethport
+                */
+               /* No-op */
+               break;
+
+       case ETHPORT_E_FWRESP_UP_OK:
+               /* up_resp_wait->last_resp_wait transition on ETHPORT_T_STOP */
+               bna_bfi_ethport_down(ethport);
+               break;
+
+       case ETHPORT_E_FWRESP_UP_FAIL:
+       case ETHPORT_E_FWRESP_DOWN:
+               bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ethport_init(struct bna_ethport *ethport, struct bna *bna)
+{
+       ethport->flags |= (BNA_ETHPORT_F_ADMIN_UP | BNA_ETHPORT_F_PORT_ENABLED);
+       ethport->bna = bna;
+
+       ethport->link_status = BNA_LINK_DOWN;
+       ethport->link_cbfn = bnad_cb_ethport_link_status;
+
+       ethport->rx_started_count = 0;
+
+       ethport->stop_cbfn = NULL;
+       ethport->adminup_cbfn = NULL;
+
+       bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+}
+
+static void
+bna_ethport_uninit(struct bna_ethport *ethport)
+{
+       ethport->flags &= ~BNA_ETHPORT_F_ADMIN_UP;
+       ethport->flags &= ~BNA_ETHPORT_F_PORT_ENABLED;
+
+       ethport->bna = NULL;
+}
+
+static void
+bna_ethport_start(struct bna_ethport *ethport)
+{
+       bfa_fsm_send_event(ethport, ETHPORT_E_START);
+}
+
+static void
+bna_enet_cb_ethport_stopped(struct bna_enet *enet)
+{
+       bfa_wc_down(&enet->chld_stop_wc);
+}
+
+static void
+bna_ethport_stop(struct bna_ethport *ethport)
+{
+       ethport->stop_cbfn = bna_enet_cb_ethport_stopped;
+       bfa_fsm_send_event(ethport, ETHPORT_E_STOP);
+}
+
+static void
+bna_ethport_fail(struct bna_ethport *ethport)
+{
+       /* Reset the physical port status to enabled */
+       ethport->flags |= BNA_ETHPORT_F_PORT_ENABLED;
+
+       if (ethport->link_status != BNA_LINK_DOWN) {
+               ethport->link_status = BNA_LINK_DOWN;
+               ethport->link_cbfn(ethport->bna->bnad, BNA_LINK_DOWN);
+       }
+       bfa_fsm_send_event(ethport, ETHPORT_E_FAIL);
+}
+
+/* Should be called only when ethport is disabled */
+void
+bna_ethport_cb_rx_started(struct bna_ethport *ethport)
+{
+       ethport->rx_started_count++;
+
+       if (ethport->rx_started_count == 1) {
+               ethport->flags |= BNA_ETHPORT_F_RX_STARTED;
+
+               if (ethport_can_be_up(ethport))
+                       bfa_fsm_send_event(ethport, ETHPORT_E_UP);
+       }
+}
+
+void
+bna_ethport_cb_rx_stopped(struct bna_ethport *ethport)
+{
+       int ethport_up = ethport_is_up(ethport);
+
+       ethport->rx_started_count--;
+
+       if (ethport->rx_started_count == 0) {
+               ethport->flags &= ~BNA_ETHPORT_F_RX_STARTED;
+
+               if (ethport_up)
+                       bfa_fsm_send_event(ethport, ETHPORT_E_DOWN);
+       }
+}
+
+/**
+ * ENET
+ */
+#define bna_enet_chld_start(enet)                                      \
+do {                                                                   \
+       enum bna_tx_type tx_type =                                      \
+               ((enet)->type == BNA_ENET_T_REGULAR) ?                  \
+               BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;                   \
+       enum bna_rx_type rx_type =                                      \
+               ((enet)->type == BNA_ENET_T_REGULAR) ?                  \
+               BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;                   \
+       bna_ethport_start(&(enet)->bna->ethport);                       \
+       bna_tx_mod_start(&(enet)->bna->tx_mod, tx_type);                \
+       bna_rx_mod_start(&(enet)->bna->rx_mod, rx_type);                \
+} while (0)
+
+#define bna_enet_chld_stop(enet)                                       \
+do {                                                                   \
+       enum bna_tx_type tx_type =                                      \
+               ((enet)->type == BNA_ENET_T_REGULAR) ?                  \
+               BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;                   \
+       enum bna_rx_type rx_type =                                      \
+               ((enet)->type == BNA_ENET_T_REGULAR) ?                  \
+               BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;                   \
+       bfa_wc_init(&(enet)->chld_stop_wc, bna_enet_cb_chld_stopped, (enet));\
+       bfa_wc_up(&(enet)->chld_stop_wc);                               \
+       bna_ethport_stop(&(enet)->bna->ethport);                        \
+       bfa_wc_up(&(enet)->chld_stop_wc);                               \
+       bna_tx_mod_stop(&(enet)->bna->tx_mod, tx_type);                 \
+       bfa_wc_up(&(enet)->chld_stop_wc);                               \
+       bna_rx_mod_stop(&(enet)->bna->rx_mod, rx_type);                 \
+       bfa_wc_wait(&(enet)->chld_stop_wc);                             \
+} while (0)
+
+#define bna_enet_chld_fail(enet)                                       \
+do {                                                                   \
+       bna_ethport_fail(&(enet)->bna->ethport);                        \
+       bna_tx_mod_fail(&(enet)->bna->tx_mod);                          \
+       bna_rx_mod_fail(&(enet)->bna->rx_mod);                          \
+} while (0)
+
+#define bna_enet_rx_start(enet)                                                \
+do {                                                                   \
+       enum bna_rx_type rx_type =                                      \
+               ((enet)->type == BNA_ENET_T_REGULAR) ?                  \
+               BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;                   \
+       bna_rx_mod_start(&(enet)->bna->rx_mod, rx_type);                \
+} while (0)
+
+#define bna_enet_rx_stop(enet)                                         \
+do {                                                                   \
+       enum bna_rx_type rx_type =                                      \
+               ((enet)->type == BNA_ENET_T_REGULAR) ?                  \
+               BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;                   \
+       bfa_wc_init(&(enet)->chld_stop_wc, bna_enet_cb_chld_stopped, (enet));\
+       bfa_wc_up(&(enet)->chld_stop_wc);                               \
+       bna_rx_mod_stop(&(enet)->bna->rx_mod, rx_type);                 \
+       bfa_wc_wait(&(enet)->chld_stop_wc);                             \
+} while (0)
+
+#define call_enet_stop_cbfn(enet)                                      \
+do {                                                                   \
+       if ((enet)->stop_cbfn) {                                        \
+               void (*cbfn)(void *);                                   \
+               void *cbarg;                                            \
+               cbfn = (enet)->stop_cbfn;                               \
+               cbarg = (enet)->stop_cbarg;                             \
+               (enet)->stop_cbfn = NULL;                               \
+               (enet)->stop_cbarg = NULL;                              \
+               cbfn(cbarg);                                            \
+       }                                                               \
+} while (0)
+
+#define call_enet_pause_cbfn(enet)                                     \
+do {                                                                   \
+       if ((enet)->pause_cbfn) {                                       \
+               void (*cbfn)(struct bnad *);                            \
+               cbfn = (enet)->pause_cbfn;                              \
+               (enet)->pause_cbfn = NULL;                              \
+               cbfn((enet)->bna->bnad);                                \
+       }                                                               \
+} while (0)
+
+#define call_enet_mtu_cbfn(enet)                                       \
+do {                                                                   \
+       if ((enet)->mtu_cbfn) {                                         \
+               void (*cbfn)(struct bnad *);                            \
+               cbfn = (enet)->mtu_cbfn;                                \
+               (enet)->mtu_cbfn = NULL;                                \
+               cbfn((enet)->bna->bnad);                                \
+       }                                                               \
+} while (0)
+
+static void bna_enet_cb_chld_stopped(void *arg);
+static void bna_bfi_pause_set(struct bna_enet *enet);
+
+bfa_fsm_state_decl(bna_enet, stopped, struct bna_enet,
+                       enum bna_enet_event);
+bfa_fsm_state_decl(bna_enet, pause_init_wait, struct bna_enet,
+                       enum bna_enet_event);
+bfa_fsm_state_decl(bna_enet, last_resp_wait, struct bna_enet,
+                       enum bna_enet_event);
+bfa_fsm_state_decl(bna_enet, started, struct bna_enet,
+                       enum bna_enet_event);
+bfa_fsm_state_decl(bna_enet, cfg_wait, struct bna_enet,
+                       enum bna_enet_event);
+bfa_fsm_state_decl(bna_enet, cfg_stop_wait, struct bna_enet,
+                       enum bna_enet_event);
+bfa_fsm_state_decl(bna_enet, chld_stop_wait, struct bna_enet,
+                       enum bna_enet_event);
+
+static void
+bna_enet_sm_stopped_entry(struct bna_enet *enet)
+{
+       call_enet_pause_cbfn(enet);
+       call_enet_mtu_cbfn(enet);
+       call_enet_stop_cbfn(enet);
+}
+
+static void
+bna_enet_sm_stopped(struct bna_enet *enet, enum bna_enet_event event)
+{
+       switch (event) {
+       case ENET_E_START:
+               bfa_fsm_set_state(enet, bna_enet_sm_pause_init_wait);
+               break;
+
+       case ENET_E_STOP:
+               call_enet_stop_cbfn(enet);
+               break;
+
+       case ENET_E_FAIL:
+               /* No-op */
+               break;
+
+       case ENET_E_PAUSE_CFG:
+               call_enet_pause_cbfn(enet);
+               break;
+
+       case ENET_E_MTU_CFG:
+               call_enet_mtu_cbfn(enet);
+               break;
+
+       case ENET_E_CHLD_STOPPED:
+               /**
+                * This event is received due to Ethport, Tx and Rx objects
+                * failing
+                */
+               /* No-op */
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_enet_sm_pause_init_wait_entry(struct bna_enet *enet)
+{
+       bna_bfi_pause_set(enet);
+}
+
+static void
+bna_enet_sm_pause_init_wait(struct bna_enet *enet,
+                               enum bna_enet_event event)
+{
+       switch (event) {
+       case ENET_E_STOP:
+               enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+               bfa_fsm_set_state(enet, bna_enet_sm_last_resp_wait);
+               break;
+
+       case ENET_E_FAIL:
+               enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+               bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+               break;
+
+       case ENET_E_PAUSE_CFG:
+               enet->flags |= BNA_ENET_F_PAUSE_CHANGED;
+               break;
+
+       case ENET_E_MTU_CFG:
+               /* No-op */
+               break;
+
+       case ENET_E_FWRESP_PAUSE:
+               if (enet->flags & BNA_ENET_F_PAUSE_CHANGED) {
+                       enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+                       bna_bfi_pause_set(enet);
+               } else {
+                       bfa_fsm_set_state(enet, bna_enet_sm_started);
+                       bna_enet_chld_start(enet);
+               }
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_enet_sm_last_resp_wait_entry(struct bna_enet *enet)
+{
+       enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+}
+
+static void
+bna_enet_sm_last_resp_wait(struct bna_enet *enet,
+                               enum bna_enet_event event)
+{
+       switch (event) {
+       case ENET_E_FAIL:
+       case ENET_E_FWRESP_PAUSE:
+               bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_enet_sm_started_entry(struct bna_enet *enet)
+{
+       /**
+        * NOTE: Do not call bna_enet_chld_start() here, since it will be
+        * inadvertently called during cfg_wait->started transition as well
+        */
+       call_enet_pause_cbfn(enet);
+       call_enet_mtu_cbfn(enet);
+}
+
+static void
+bna_enet_sm_started(struct bna_enet *enet,
+                       enum bna_enet_event event)
+{
+       switch (event) {
+       case ENET_E_STOP:
+               bfa_fsm_set_state(enet, bna_enet_sm_chld_stop_wait);
+               break;
+
+       case ENET_E_FAIL:
+               bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+               bna_enet_chld_fail(enet);
+               break;
+
+       case ENET_E_PAUSE_CFG:
+               bfa_fsm_set_state(enet, bna_enet_sm_cfg_wait);
+               bna_bfi_pause_set(enet);
+               break;
+
+       case ENET_E_MTU_CFG:
+               bfa_fsm_set_state(enet, bna_enet_sm_cfg_wait);
+               bna_enet_rx_stop(enet);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_enet_sm_cfg_wait_entry(struct bna_enet *enet)
+{
+}
+
+static void
+bna_enet_sm_cfg_wait(struct bna_enet *enet,
+                       enum bna_enet_event event)
+{
+       switch (event) {
+       case ENET_E_STOP:
+               enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+               enet->flags &= ~BNA_ENET_F_MTU_CHANGED;
+               bfa_fsm_set_state(enet, bna_enet_sm_cfg_stop_wait);
+               break;
+
+       case ENET_E_FAIL:
+               enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+               enet->flags &= ~BNA_ENET_F_MTU_CHANGED;
+               bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+               bna_enet_chld_fail(enet);
+               break;
+
+       case ENET_E_PAUSE_CFG:
+               enet->flags |= BNA_ENET_F_PAUSE_CHANGED;
+               break;
+
+       case ENET_E_MTU_CFG:
+               enet->flags |= BNA_ENET_F_MTU_CHANGED;
+               break;
+
+       case ENET_E_CHLD_STOPPED:
+               bna_enet_rx_start(enet);
+               /* Fall through */
+       case ENET_E_FWRESP_PAUSE:
+               if (enet->flags & BNA_ENET_F_PAUSE_CHANGED) {
+                       enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+                       bna_bfi_pause_set(enet);
+               } else if (enet->flags & BNA_ENET_F_MTU_CHANGED) {
+                       enet->flags &= ~BNA_ENET_F_MTU_CHANGED;
+                       bna_enet_rx_stop(enet);
+               } else {
+                       bfa_fsm_set_state(enet, bna_enet_sm_started);
+               }
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_enet_sm_cfg_stop_wait_entry(struct bna_enet *enet)
+{
+       enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+       enet->flags &= ~BNA_ENET_F_MTU_CHANGED;
+}
+
+static void
+bna_enet_sm_cfg_stop_wait(struct bna_enet *enet,
+                               enum bna_enet_event event)
+{
+       switch (event) {
+       case ENET_E_FAIL:
+               bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+               bna_enet_chld_fail(enet);
+               break;
+
+       case ENET_E_FWRESP_PAUSE:
+       case ENET_E_CHLD_STOPPED:
+               bfa_fsm_set_state(enet, bna_enet_sm_chld_stop_wait);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_enet_sm_chld_stop_wait_entry(struct bna_enet *enet)
+{
+       bna_enet_chld_stop(enet);
+}
+
+static void
+bna_enet_sm_chld_stop_wait(struct bna_enet *enet,
+                               enum bna_enet_event event)
+{
+       switch (event) {
+       case ENET_E_FAIL:
+               bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+               bna_enet_chld_fail(enet);
+               break;
+
+       case ENET_E_CHLD_STOPPED:
+               bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_bfi_pause_set(struct bna_enet *enet)
+{
+       struct bfi_enet_set_pause_req *pause_req = &enet->pause_req;
+
+       bfi_msgq_mhdr_set(pause_req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_SET_PAUSE_REQ, 0, 0);
+       pause_req->mh.num_entries = htons(
+       bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_set_pause_req)));
+       pause_req->tx_pause = enet->pause_config.tx_pause;
+       pause_req->rx_pause = enet->pause_config.rx_pause;
+
+       bfa_msgq_cmd_set(&enet->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_set_pause_req), &pause_req->mh);
+       bfa_msgq_cmd_post(&enet->bna->msgq, &enet->msgq_cmd);
+}
+
+static void
+bna_enet_cb_chld_stopped(void *arg)
+{
+       struct bna_enet *enet = (struct bna_enet *)arg;
+
+       bfa_fsm_send_event(enet, ENET_E_CHLD_STOPPED);
+}
+
+static void
+bna_enet_init(struct bna_enet *enet, struct bna *bna)
+{
+       enet->bna = bna;
+       enet->flags = 0;
+       enet->mtu = 0;
+       enet->type = BNA_ENET_T_REGULAR;
+
+       enet->stop_cbfn = NULL;
+       enet->stop_cbarg = NULL;
+
+       enet->pause_cbfn = NULL;
+
+       enet->mtu_cbfn = NULL;
+
+       bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+}
+
+static void
+bna_enet_uninit(struct bna_enet *enet)
+{
+       enet->flags = 0;
+
+       enet->bna = NULL;
+}
+
+static void
+bna_enet_start(struct bna_enet *enet)
+{
+       enet->flags |= BNA_ENET_F_IOCETH_READY;
+       if (enet->flags & BNA_ENET_F_ENABLED)
+               bfa_fsm_send_event(enet, ENET_E_START);
+}
+
+static void
+bna_ioceth_cb_enet_stopped(void *arg)
+{
+       struct bna_ioceth *ioceth = (struct bna_ioceth *)arg;
+
+       bfa_fsm_send_event(ioceth, IOCETH_E_ENET_STOPPED);
+}
+
+static void
+bna_enet_stop(struct bna_enet *enet)
+{
+       enet->stop_cbfn = bna_ioceth_cb_enet_stopped;
+       enet->stop_cbarg = &enet->bna->ioceth;
+
+       enet->flags &= ~BNA_ENET_F_IOCETH_READY;
+       bfa_fsm_send_event(enet, ENET_E_STOP);
+}
+
+static void
+bna_enet_fail(struct bna_enet *enet)
+{
+       enet->flags &= ~BNA_ENET_F_IOCETH_READY;
+       bfa_fsm_send_event(enet, ENET_E_FAIL);
+}
+
+void
+bna_enet_cb_tx_stopped(struct bna_enet *enet)
+{
+       bfa_wc_down(&enet->chld_stop_wc);
+}
+
+void
+bna_enet_cb_rx_stopped(struct bna_enet *enet)
+{
+       bfa_wc_down(&enet->chld_stop_wc);
+}
+
+int
+bna_enet_mtu_get(struct bna_enet *enet)
+{
+       return enet->mtu;
+}
+
+void
+bna_enet_enable(struct bna_enet *enet)
+{
+       if (enet->fsm != (bfa_sm_t)bna_enet_sm_stopped)
+               return;
+
+       enet->flags |= BNA_ENET_F_ENABLED;
+
+       if (enet->flags & BNA_ENET_F_IOCETH_READY)
+               bfa_fsm_send_event(enet, ENET_E_START);
+}
+
+void
+bna_enet_disable(struct bna_enet *enet, enum bna_cleanup_type type,
+                void (*cbfn)(void *))
+{
+       if (type == BNA_SOFT_CLEANUP) {
+               (*cbfn)(enet->bna->bnad);
+               return;
+       }
+
+       enet->stop_cbfn = cbfn;
+       enet->stop_cbarg = enet->bna->bnad;
+
+       enet->flags &= ~BNA_ENET_F_ENABLED;
+
+       bfa_fsm_send_event(enet, ENET_E_STOP);
+}
+
+void
+bna_enet_pause_config(struct bna_enet *enet,
+                     struct bna_pause_config *pause_config,
+                     void (*cbfn)(struct bnad *))
+{
+       enet->pause_config = *pause_config;
+
+       enet->pause_cbfn = cbfn;
+
+       bfa_fsm_send_event(enet, ENET_E_PAUSE_CFG);
+}
+
+void
+bna_enet_mtu_set(struct bna_enet *enet, int mtu,
+                void (*cbfn)(struct bnad *))
+{
+       enet->mtu = mtu;
+
+       enet->mtu_cbfn = cbfn;
+
+       bfa_fsm_send_event(enet, ENET_E_MTU_CFG);
+}
+
+void
+bna_enet_perm_mac_get(struct bna_enet *enet, mac_t *mac)
+{
+       *mac = bfa_nw_ioc_get_mac(&enet->bna->ioceth.ioc);
+}
+
+/**
+ * IOCETH
+ */
+#define enable_mbox_intr(_ioceth)                                      \
+do {                                                                   \
+       u32 intr_status;                                                \
+       bna_intr_status_get((_ioceth)->bna, intr_status);               \
+       bnad_cb_mbox_intr_enable((_ioceth)->bna->bnad);                 \
+       bna_mbox_intr_enable((_ioceth)->bna);                           \
+} while (0)
+
+#define disable_mbox_intr(_ioceth)                                     \
+do {                                                                   \
+       bna_mbox_intr_disable((_ioceth)->bna);                          \
+       bnad_cb_mbox_intr_disable((_ioceth)->bna->bnad);                \
+} while (0)
+
+#define call_ioceth_stop_cbfn(_ioceth)                                 \
+do {                                                                   \
+       if ((_ioceth)->stop_cbfn) {                                     \
+               void (*cbfn)(struct bnad *);                            \
+               struct bnad *cbarg;                                     \
+               cbfn = (_ioceth)->stop_cbfn;                            \
+               cbarg = (_ioceth)->stop_cbarg;                          \
+               (_ioceth)->stop_cbfn = NULL;                            \
+               (_ioceth)->stop_cbarg = NULL;                           \
+               cbfn(cbarg);                                            \
+       }                                                               \
+} while (0)
+
+#define bna_stats_mod_uninit(_stats_mod)                               \
+do {                                                                   \
+} while (0)
+
+#define bna_stats_mod_start(_stats_mod)                                        \
+do {                                                                   \
+       (_stats_mod)->ioc_ready = true;                                 \
+} while (0)
+
+#define bna_stats_mod_stop(_stats_mod)                                 \
+do {                                                                   \
+       (_stats_mod)->ioc_ready = false;                                \
+} while (0)
+
+#define bna_stats_mod_fail(_stats_mod)                                 \
+do {                                                                   \
+       (_stats_mod)->ioc_ready = false;                                \
+       (_stats_mod)->stats_get_busy = false;                           \
+       (_stats_mod)->stats_clr_busy = false;                           \
+} while (0)
+
+static void bna_bfi_attr_get(struct bna_ioceth *ioceth);
+
+bfa_fsm_state_decl(bna_ioceth, stopped, struct bna_ioceth,
+                       enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, ioc_ready_wait, struct bna_ioceth,
+                       enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, enet_attr_wait, struct bna_ioceth,
+                       enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, ready, struct bna_ioceth,
+                       enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, last_resp_wait, struct bna_ioceth,
+                       enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, enet_stop_wait, struct bna_ioceth,
+                       enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, ioc_disable_wait, struct bna_ioceth,
+                       enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, failed, struct bna_ioceth,
+                       enum bna_ioceth_event);
+
+static void
+bna_ioceth_sm_stopped_entry(struct bna_ioceth *ioceth)
+{
+       call_ioceth_stop_cbfn(ioceth);
+}
+
+static void
+bna_ioceth_sm_stopped(struct bna_ioceth *ioceth,
+                       enum bna_ioceth_event event)
+{
+       switch (event) {
+       case IOCETH_E_ENABLE:
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_ready_wait);
+               bfa_nw_ioc_enable(&ioceth->ioc);
+               break;
+
+       case IOCETH_E_DISABLE:
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_stopped);
+               break;
+
+       case IOCETH_E_IOC_RESET:
+               enable_mbox_intr(ioceth);
+               break;
+
+       case IOCETH_E_IOC_FAILED:
+               disable_mbox_intr(ioceth);
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_failed);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ioceth_sm_ioc_ready_wait_entry(struct bna_ioceth *ioceth)
+{
+       /**
+        * Do not call bfa_nw_ioc_enable() here. It must be called in the
+        * previous state due to failed -> ioc_ready_wait transition.
+        */
+}
+
+static void
+bna_ioceth_sm_ioc_ready_wait(struct bna_ioceth *ioceth,
+                               enum bna_ioceth_event event)
+{
+       switch (event) {
+       case IOCETH_E_DISABLE:
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_disable_wait);
+               bfa_nw_ioc_disable(&ioceth->ioc);
+               break;
+
+       case IOCETH_E_IOC_RESET:
+               enable_mbox_intr(ioceth);
+               break;
+
+       case IOCETH_E_IOC_FAILED:
+               disable_mbox_intr(ioceth);
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_failed);
+               break;
+
+       case IOCETH_E_IOC_READY:
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_enet_attr_wait);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ioceth_sm_enet_attr_wait_entry(struct bna_ioceth *ioceth)
+{
+       bna_bfi_attr_get(ioceth);
+}
+
+static void
+bna_ioceth_sm_enet_attr_wait(struct bna_ioceth *ioceth,
+                               enum bna_ioceth_event event)
+{
+       switch (event) {
+       case IOCETH_E_DISABLE:
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_last_resp_wait);
+               break;
+
+       case IOCETH_E_IOC_FAILED:
+               disable_mbox_intr(ioceth);
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_failed);
+               break;
+
+       case IOCETH_E_ENET_ATTR_RESP:
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_ready);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ioceth_sm_ready_entry(struct bna_ioceth *ioceth)
+{
+       bna_enet_start(&ioceth->bna->enet);
+       bna_stats_mod_start(&ioceth->bna->stats_mod);
+       bnad_cb_ioceth_ready(ioceth->bna->bnad);
+}
+
+static void
+bna_ioceth_sm_ready(struct bna_ioceth *ioceth, enum bna_ioceth_event event)
+{
+       switch (event) {
+       case IOCETH_E_DISABLE:
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_enet_stop_wait);
+               break;
+
+       case IOCETH_E_IOC_FAILED:
+               disable_mbox_intr(ioceth);
+               bna_enet_fail(&ioceth->bna->enet);
+               bna_stats_mod_fail(&ioceth->bna->stats_mod);
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_failed);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ioceth_sm_last_resp_wait_entry(struct bna_ioceth *ioceth)
+{
+}
+
+static void
+bna_ioceth_sm_last_resp_wait(struct bna_ioceth *ioceth,
+                               enum bna_ioceth_event event)
+{
+       switch (event) {
+       case IOCETH_E_IOC_FAILED:
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_disable_wait);
+               disable_mbox_intr(ioceth);
+               bfa_nw_ioc_disable(&ioceth->ioc);
+               break;
+
+       case IOCETH_E_ENET_ATTR_RESP:
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_disable_wait);
+               bfa_nw_ioc_disable(&ioceth->ioc);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ioceth_sm_enet_stop_wait_entry(struct bna_ioceth *ioceth)
+{
+       bna_stats_mod_stop(&ioceth->bna->stats_mod);
+       bna_enet_stop(&ioceth->bna->enet);
+}
+
+static void
+bna_ioceth_sm_enet_stop_wait(struct bna_ioceth *ioceth,
+                               enum bna_ioceth_event event)
+{
+       switch (event) {
+       case IOCETH_E_IOC_FAILED:
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_disable_wait);
+               disable_mbox_intr(ioceth);
+               bna_enet_fail(&ioceth->bna->enet);
+               bna_stats_mod_fail(&ioceth->bna->stats_mod);
+               bfa_nw_ioc_disable(&ioceth->ioc);
+               break;
+
+       case IOCETH_E_ENET_STOPPED:
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_disable_wait);
+               bfa_nw_ioc_disable(&ioceth->ioc);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ioceth_sm_ioc_disable_wait_entry(struct bna_ioceth *ioceth)
+{
+}
+
+static void
+bna_ioceth_sm_ioc_disable_wait(struct bna_ioceth *ioceth,
+                               enum bna_ioceth_event event)
+{
+       switch (event) {
+       case IOCETH_E_IOC_DISABLED:
+               disable_mbox_intr(ioceth);
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_stopped);
+               break;
+
+       case IOCETH_E_ENET_STOPPED:
+               /* This event is received due to enet failing */
+               /* No-op */
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_ioceth_sm_failed_entry(struct bna_ioceth *ioceth)
+{
+       bnad_cb_ioceth_failed(ioceth->bna->bnad);
+}
+
+static void
+bna_ioceth_sm_failed(struct bna_ioceth *ioceth,
+                       enum bna_ioceth_event event)
+{
+       switch (event) {
+       case IOCETH_E_DISABLE:
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_disable_wait);
+               bfa_nw_ioc_disable(&ioceth->ioc);
+               break;
+
+       case IOCETH_E_IOC_RESET:
+               enable_mbox_intr(ioceth);
+               bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_ready_wait);
+               break;
+
+       case IOCETH_E_IOC_FAILED:
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_bfi_attr_get(struct bna_ioceth *ioceth)
+{
+       struct bfi_enet_attr_req *attr_req = &ioceth->attr_req;
+
+       bfi_msgq_mhdr_set(attr_req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_GET_ATTR_REQ, 0, 0);
+       attr_req->mh.num_entries = htons(
+       bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_attr_req)));
+       bfa_msgq_cmd_set(&ioceth->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_attr_req), &attr_req->mh);
+       bfa_msgq_cmd_post(&ioceth->bna->msgq, &ioceth->msgq_cmd);
+}
+
+/* IOC callback functions */
+
+static void
+bna_cb_ioceth_enable(void *arg, enum bfa_status error)
+{
+       struct bna_ioceth *ioceth = (struct bna_ioceth *)arg;
+
+       if (error)
+               bfa_fsm_send_event(ioceth, IOCETH_E_IOC_FAILED);
+       else
+               bfa_fsm_send_event(ioceth, IOCETH_E_IOC_READY);
+}
+
+static void
+bna_cb_ioceth_disable(void *arg)
+{
+       struct bna_ioceth *ioceth = (struct bna_ioceth *)arg;
+
+       bfa_fsm_send_event(ioceth, IOCETH_E_IOC_DISABLED);
+}
+
+static void
+bna_cb_ioceth_hbfail(void *arg)
+{
+       struct bna_ioceth *ioceth = (struct bna_ioceth *)arg;
+
+       bfa_fsm_send_event(ioceth, IOCETH_E_IOC_FAILED);
+}
+
+static void
+bna_cb_ioceth_reset(void *arg)
+{
+       struct bna_ioceth *ioceth = (struct bna_ioceth *)arg;
+
+       bfa_fsm_send_event(ioceth, IOCETH_E_IOC_RESET);
+}
+
+static struct bfa_ioc_cbfn bna_ioceth_cbfn = {
+       bna_cb_ioceth_enable,
+       bna_cb_ioceth_disable,
+       bna_cb_ioceth_hbfail,
+       bna_cb_ioceth_reset
+};
+
+static void
+bna_ioceth_init(struct bna_ioceth *ioceth, struct bna *bna,
+               struct bna_res_info *res_info)
+{
+       u64 dma;
+       u8 *kva;
+
+       ioceth->bna = bna;
+
+       /**
+        * Attach IOC and claim:
+        *      1. DMA memory for IOC attributes
+        *      2. Kernel memory for FW trace
+        */
+       bfa_nw_ioc_attach(&ioceth->ioc, ioceth, &bna_ioceth_cbfn);
+       bfa_nw_ioc_pci_init(&ioceth->ioc, &bna->pcidev, BFI_PCIFN_CLASS_ETH);
+
+       BNA_GET_DMA_ADDR(
+               &res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].dma, dma);
+       kva = res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].kva;
+       bfa_nw_ioc_mem_claim(&ioceth->ioc, kva, dma);
+
+       kva = res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mdl[0].kva;
+
+       /**
+        * Attach common modules (Diag, SFP, CEE, Port) and claim respective
+        * DMA memory.
+        */
+       BNA_GET_DMA_ADDR(
+               &res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].dma, dma);
+       kva = res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].kva;
+       bfa_nw_cee_attach(&bna->cee, &ioceth->ioc, bna);
+       bfa_nw_cee_mem_claim(&bna->cee, kva, dma);
+       kva += bfa_nw_cee_meminfo();
+       dma += bfa_nw_cee_meminfo();
+
+       bfa_msgq_attach(&bna->msgq, &ioceth->ioc);
+       bfa_msgq_memclaim(&bna->msgq, kva, dma);
+       bfa_msgq_regisr(&bna->msgq, BFI_MC_ENET, bna_msgq_rsp_handler, bna);
+       kva += bfa_msgq_meminfo();
+       dma += bfa_msgq_meminfo();
+
+       ioceth->stop_cbfn = NULL;
+       ioceth->stop_cbarg = NULL;
+
+       bfa_fsm_set_state(ioceth, bna_ioceth_sm_stopped);
+}
+
+static void
+bna_ioceth_uninit(struct bna_ioceth *ioceth)
+{
+       bfa_nw_ioc_detach(&ioceth->ioc);
+
+       ioceth->bna = NULL;
+}
+
+void
+bna_ioceth_enable(struct bna_ioceth *ioceth)
+{
+       if (ioceth->fsm == (bfa_fsm_t)bna_ioceth_sm_ready) {
+               bnad_cb_ioceth_ready(ioceth->bna->bnad);
+               return;
+       }
+
+       if (ioceth->fsm == (bfa_fsm_t)bna_ioceth_sm_stopped)
+               bfa_fsm_send_event(ioceth, IOCETH_E_ENABLE);
+}
+
+void
+bna_ioceth_disable(struct bna_ioceth *ioceth, enum bna_cleanup_type type)
+{
+       if (type == BNA_SOFT_CLEANUP) {
+               bnad_cb_ioceth_disabled(ioceth->bna->bnad);
+               return;
+       }
+
+       ioceth->stop_cbfn = bnad_cb_ioceth_disabled;
+       ioceth->stop_cbarg = ioceth->bna->bnad;
+
+       bfa_fsm_send_event(ioceth, IOCETH_E_DISABLE);
+}
+
+static void
+bna_ucam_mod_init(struct bna_ucam_mod *ucam_mod, struct bna *bna,
+                 struct bna_res_info *res_info)
+{
+       int i;
+
+       ucam_mod->ucmac = (struct bna_mac *)
+       res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
+
+       INIT_LIST_HEAD(&ucam_mod->free_q);
+       for (i = 0; i < bna->ioceth.attr.num_ucmac; i++) {
+               bfa_q_qe_init(&ucam_mod->ucmac[i].qe);
+               list_add_tail(&ucam_mod->ucmac[i].qe, &ucam_mod->free_q);
+       }
+
+       ucam_mod->bna = bna;
+}
+
+static void
+bna_ucam_mod_uninit(struct bna_ucam_mod *ucam_mod)
+{
+       struct list_head *qe;
+       int i = 0;
+
+       list_for_each(qe, &ucam_mod->free_q)
+               i++;
+
+       ucam_mod->bna = NULL;
+}
+
+static void
+bna_mcam_mod_init(struct bna_mcam_mod *mcam_mod, struct bna *bna,
+                 struct bna_res_info *res_info)
+{
+       int i;
+
+       mcam_mod->mcmac = (struct bna_mac *)
+       res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
+
+       INIT_LIST_HEAD(&mcam_mod->free_q);
+       for (i = 0; i < bna->ioceth.attr.num_mcmac; i++) {
+               bfa_q_qe_init(&mcam_mod->mcmac[i].qe);
+               list_add_tail(&mcam_mod->mcmac[i].qe, &mcam_mod->free_q);
+       }
+
+       mcam_mod->mchandle = (struct bna_mcam_handle *)
+       res_info[BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY].res_u.mem_info.mdl[0].kva;
+
+       INIT_LIST_HEAD(&mcam_mod->free_handle_q);
+       for (i = 0; i < bna->ioceth.attr.num_mcmac; i++) {
+               bfa_q_qe_init(&mcam_mod->mchandle[i].qe);
+               list_add_tail(&mcam_mod->mchandle[i].qe,
+                               &mcam_mod->free_handle_q);
+       }
+
+       mcam_mod->bna = bna;
+}
+
+static void
+bna_mcam_mod_uninit(struct bna_mcam_mod *mcam_mod)
+{
+       struct list_head *qe;
+       int i;
+
+       i = 0;
+       list_for_each(qe, &mcam_mod->free_q) i++;
+
+       i = 0;
+       list_for_each(qe, &mcam_mod->free_handle_q) i++;
+
+       mcam_mod->bna = NULL;
+}
+
+static void
+bna_bfi_stats_get(struct bna *bna)
+{
+       struct bfi_enet_stats_req *stats_req = &bna->stats_mod.stats_get;
+
+       bna->stats_mod.stats_get_busy = true;
+
+       bfi_msgq_mhdr_set(stats_req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_STATS_GET_REQ, 0, 0);
+       stats_req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_stats_req)));
+       stats_req->stats_mask = htons(BFI_ENET_STATS_ALL);
+       stats_req->tx_enet_mask = htonl(bna->tx_mod.rid_mask);
+       stats_req->rx_enet_mask = htonl(bna->rx_mod.rid_mask);
+       stats_req->host_buffer.a32.addr_hi = bna->stats.hw_stats_dma.msb;
+       stats_req->host_buffer.a32.addr_lo = bna->stats.hw_stats_dma.lsb;
+
+       bfa_msgq_cmd_set(&bna->stats_mod.stats_get_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_stats_req), &stats_req->mh);
+       bfa_msgq_cmd_post(&bna->msgq, &bna->stats_mod.stats_get_cmd);
+}
+
+void
+bna_res_req(struct bna_res_info *res_info)
+{
+       /* DMA memory for COMMON_MODULE */
+       res_info[BNA_RES_MEM_T_COM].res_type = BNA_RES_T_MEM;
+       res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+       res_info[BNA_RES_MEM_T_COM].res_u.mem_info.num = 1;
+       res_info[BNA_RES_MEM_T_COM].res_u.mem_info.len = ALIGN(
+                               (bfa_nw_cee_meminfo() +
+                               bfa_msgq_meminfo()), PAGE_SIZE);
+
+       /* DMA memory for retrieving IOC attributes */
+       res_info[BNA_RES_MEM_T_ATTR].res_type = BNA_RES_T_MEM;
+       res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+       res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.num = 1;
+       res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.len =
+                               ALIGN(bfa_nw_ioc_meminfo(), PAGE_SIZE);
+
+       /* Virtual memory for retreiving fw_trc */
+       res_info[BNA_RES_MEM_T_FWTRC].res_type = BNA_RES_T_MEM;
+       res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mem_type = BNA_MEM_T_KVA;
+       res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.num = 0;
+       res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.len = 0;
+
+       /* DMA memory for retreiving stats */
+       res_info[BNA_RES_MEM_T_STATS].res_type = BNA_RES_T_MEM;
+       res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+       res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.num = 1;
+       res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.len =
+                               ALIGN(sizeof(struct bfi_enet_stats),
+                                       PAGE_SIZE);
+}
+
+void
+bna_mod_res_req(struct bna *bna, struct bna_res_info *res_info)
+{
+       struct bna_attr *attr = &bna->ioceth.attr;
+
+       /* Virtual memory for Tx objects - stored by Tx module */
+       res_info[BNA_MOD_RES_MEM_T_TX_ARRAY].res_type = BNA_RES_T_MEM;
+       res_info[BNA_MOD_RES_MEM_T_TX_ARRAY].res_u.mem_info.mem_type =
+               BNA_MEM_T_KVA;
+       res_info[BNA_MOD_RES_MEM_T_TX_ARRAY].res_u.mem_info.num = 1;
+       res_info[BNA_MOD_RES_MEM_T_TX_ARRAY].res_u.mem_info.len =
+               attr->num_txq * sizeof(struct bna_tx);
+
+       /* Virtual memory for TxQ - stored by Tx module */
+       res_info[BNA_MOD_RES_MEM_T_TXQ_ARRAY].res_type = BNA_RES_T_MEM;
+       res_info[BNA_MOD_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mem_type =
+               BNA_MEM_T_KVA;
+       res_info[BNA_MOD_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.num = 1;
+       res_info[BNA_MOD_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.len =
+               attr->num_txq * sizeof(struct bna_txq);
+
+       /* Virtual memory for Rx objects - stored by Rx module */
+       res_info[BNA_MOD_RES_MEM_T_RX_ARRAY].res_type = BNA_RES_T_MEM;
+       res_info[BNA_MOD_RES_MEM_T_RX_ARRAY].res_u.mem_info.mem_type =
+               BNA_MEM_T_KVA;
+       res_info[BNA_MOD_RES_MEM_T_RX_ARRAY].res_u.mem_info.num = 1;
+       res_info[BNA_MOD_RES_MEM_T_RX_ARRAY].res_u.mem_info.len =
+               attr->num_rxp * sizeof(struct bna_rx);
+
+       /* Virtual memory for RxPath - stored by Rx module */
+       res_info[BNA_MOD_RES_MEM_T_RXP_ARRAY].res_type = BNA_RES_T_MEM;
+       res_info[BNA_MOD_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mem_type =
+               BNA_MEM_T_KVA;
+       res_info[BNA_MOD_RES_MEM_T_RXP_ARRAY].res_u.mem_info.num = 1;
+       res_info[BNA_MOD_RES_MEM_T_RXP_ARRAY].res_u.mem_info.len =
+               attr->num_rxp * sizeof(struct bna_rxp);
+
+       /* Virtual memory for RxQ - stored by Rx module */
+       res_info[BNA_MOD_RES_MEM_T_RXQ_ARRAY].res_type = BNA_RES_T_MEM;
+       res_info[BNA_MOD_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mem_type =
+               BNA_MEM_T_KVA;
+       res_info[BNA_MOD_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.num = 1;
+       res_info[BNA_MOD_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.len =
+               (attr->num_rxp * 2) * sizeof(struct bna_rxq);
+
+       /* Virtual memory for Unicast MAC address - stored by ucam module */
+       res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_type = BNA_RES_T_MEM;
+       res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mem_type =
+               BNA_MEM_T_KVA;
+       res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.num = 1;
+       res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.len =
+               attr->num_ucmac * sizeof(struct bna_mac);
+
+       /* Virtual memory for Multicast MAC address - stored by mcam module */
+       res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_type = BNA_RES_T_MEM;
+       res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mem_type =
+               BNA_MEM_T_KVA;
+       res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.num = 1;
+       res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.len =
+               attr->num_mcmac * sizeof(struct bna_mac);
+
+       /* Virtual memory for Multicast handle - stored by mcam module */
+       res_info[BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY].res_type = BNA_RES_T_MEM;
+       res_info[BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY].res_u.mem_info.mem_type =
+               BNA_MEM_T_KVA;
+       res_info[BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY].res_u.mem_info.num = 1;
+       res_info[BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY].res_u.mem_info.len =
+               attr->num_mcmac * sizeof(struct bna_mcam_handle);
+}
+
+void
+bna_init(struct bna *bna, struct bnad *bnad,
+               struct bfa_pcidev *pcidev, struct bna_res_info *res_info)
+{
+       bna->bnad = bnad;
+       bna->pcidev = *pcidev;
+
+       bna->stats.hw_stats_kva = (struct bfi_enet_stats *)
+               res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].kva;
+       bna->stats.hw_stats_dma.msb =
+               res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.msb;
+       bna->stats.hw_stats_dma.lsb =
+               res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.lsb;
+
+       bna_reg_addr_init(bna, &bna->pcidev);
+
+       /* Also initializes diag, cee, sfp, phy_port, msgq */
+       bna_ioceth_init(&bna->ioceth, bna, res_info);
+
+       bna_enet_init(&bna->enet, bna);
+       bna_ethport_init(&bna->ethport, bna);
+}
+
+void
+bna_mod_init(struct bna *bna, struct bna_res_info *res_info)
+{
+       bna_tx_mod_init(&bna->tx_mod, bna, res_info);
+
+       bna_rx_mod_init(&bna->rx_mod, bna, res_info);
+
+       bna_ucam_mod_init(&bna->ucam_mod, bna, res_info);
+
+       bna_mcam_mod_init(&bna->mcam_mod, bna, res_info);
+
+       bna->default_mode_rid = BFI_INVALID_RID;
+       bna->promisc_rid = BFI_INVALID_RID;
+
+       bna->mod_flags |= BNA_MOD_F_INIT_DONE;
+}
+
+void
+bna_uninit(struct bna *bna)
+{
+       if (bna->mod_flags & BNA_MOD_F_INIT_DONE) {
+               bna_mcam_mod_uninit(&bna->mcam_mod);
+               bna_ucam_mod_uninit(&bna->ucam_mod);
+               bna_rx_mod_uninit(&bna->rx_mod);
+               bna_tx_mod_uninit(&bna->tx_mod);
+               bna->mod_flags &= ~BNA_MOD_F_INIT_DONE;
+       }
+
+       bna_stats_mod_uninit(&bna->stats_mod);
+       bna_ethport_uninit(&bna->ethport);
+       bna_enet_uninit(&bna->enet);
+
+       bna_ioceth_uninit(&bna->ioceth);
+
+       bna->bnad = NULL;
+}
+
+int
+bna_num_txq_set(struct bna *bna, int num_txq)
+{
+       if (num_txq > 0 && (num_txq <= bna->ioceth.attr.num_txq)) {
+               bna->ioceth.attr.num_txq = num_txq;
+               return BNA_CB_SUCCESS;
+       }
+
+       return BNA_CB_FAIL;
+}
+
+int
+bna_num_rxp_set(struct bna *bna, int num_rxp)
+{
+       if (num_rxp > 0 && (num_rxp <= bna->ioceth.attr.num_rxp)) {
+               bna->ioceth.attr.num_rxp = num_rxp;
+               return BNA_CB_SUCCESS;
+       }
+
+       return BNA_CB_FAIL;
+}
+
+struct bna_mac *
+bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod)
+{
+       struct list_head *qe;
+
+       if (list_empty(&ucam_mod->free_q))
+               return NULL;
+
+       bfa_q_deq(&ucam_mod->free_q, &qe);
+
+       return (struct bna_mac *)qe;
+}
+
+void
+bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod, struct bna_mac *mac)
+{
+       list_add_tail(&mac->qe, &ucam_mod->free_q);
+}
+
+struct bna_mac *
+bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod)
+{
+       struct list_head *qe;
+
+       if (list_empty(&mcam_mod->free_q))
+               return NULL;
+
+       bfa_q_deq(&mcam_mod->free_q, &qe);
+
+       return (struct bna_mac *)qe;
+}
+
+void
+bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod, struct bna_mac *mac)
+{
+       list_add_tail(&mac->qe, &mcam_mod->free_q);
+}
+
+struct bna_mcam_handle *
+bna_mcam_mod_handle_get(struct bna_mcam_mod *mcam_mod)
+{
+       struct list_head *qe;
+
+       if (list_empty(&mcam_mod->free_handle_q))
+               return NULL;
+
+       bfa_q_deq(&mcam_mod->free_handle_q, &qe);
+
+       return (struct bna_mcam_handle *)qe;
+}
+
+void
+bna_mcam_mod_handle_put(struct bna_mcam_mod *mcam_mod,
+                       struct bna_mcam_handle *handle)
+{
+       list_add_tail(&handle->qe, &mcam_mod->free_handle_q);
+}
+
+void
+bna_hw_stats_get(struct bna *bna)
+{
+       if (!bna->stats_mod.ioc_ready) {
+               bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats);
+               return;
+       }
+       if (bna->stats_mod.stats_get_busy) {
+               bnad_cb_stats_get(bna->bnad, BNA_CB_BUSY, &bna->stats);
+               return;
+       }
+
+       bna_bfi_stats_get(bna);
+}
diff --git a/drivers/net/ethernet/brocade/bna/bna_hw_defs.h b/drivers/net/ethernet/brocade/bna/bna_hw_defs.h
new file mode 100644 (file)
index 0000000..07bb792
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.
+ */
+/*
+ * Copyright (c) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/**
+ * File for interrupt macros and functions
+ */
+
+#ifndef __BNA_HW_DEFS_H__
+#define __BNA_HW_DEFS_H__
+
+#include "bfi_reg.h"
+
+/**
+ *
+ * SW imposed limits
+ *
+ */
+
+#define BFI_ENET_MAX_MCAM              256
+
+#define BFI_INVALID_RID                        -1
+
+#define BFI_IBIDX_SIZE                 4
+
+#define BFI_VLAN_WORD_SHIFT            5       /* 32 bits */
+#define BFI_VLAN_WORD_MASK             0x1F
+#define BFI_VLAN_BLOCK_SHIFT           9       /* 512 bits */
+#define BFI_VLAN_BMASK_ALL             0xFF
+
+#define BFI_COALESCING_TIMER_UNIT      5       /* 5us */
+#define BFI_MAX_COALESCING_TIMEO       0xFF    /* in 5us units */
+#define BFI_MAX_INTERPKT_COUNT         0xFF
+#define BFI_MAX_INTERPKT_TIMEO         0xF     /* in 0.5us units */
+#define BFI_TX_COALESCING_TIMEO                20      /* 20 * 5 = 100us */
+#define BFI_TX_INTERPKT_COUNT          32
+#define        BFI_RX_COALESCING_TIMEO         12      /* 12 * 5 = 60us */
+#define        BFI_RX_INTERPKT_COUNT           6       /* Pkt Cnt = 6 */
+#define        BFI_RX_INTERPKT_TIMEO           3       /* 3 * 0.5 = 1.5us */
+
+#define BFI_TXQ_WI_SIZE                        64      /* bytes */
+#define BFI_RXQ_WI_SIZE                        8       /* bytes */
+#define BFI_CQ_WI_SIZE                 16      /* bytes */
+#define BFI_TX_MAX_WRR_QUOTA           0xFFF
+
+#define BFI_TX_MAX_VECTORS_PER_WI      4
+#define BFI_TX_MAX_VECTORS_PER_PKT     0xFF
+#define BFI_TX_MAX_DATA_PER_VECTOR     0xFFFF
+#define BFI_TX_MAX_DATA_PER_PKT                0xFFFFFF
+
+/* Small Q buffer size */
+#define BFI_SMALL_RXBUF_SIZE           128
+
+#define BFI_TX_MAX_PRIO                        8
+#define BFI_TX_PRIO_MAP_ALL            0xFF
+
+/*
+ *
+ * Register definitions and macros
+ *
+ */
+
+#define BNA_PCI_REG_CT_ADDRSZ          (0x40000)
+
+#define ct_reg_addr_init(_bna, _pcidev)                                        \
+{                                                                      \
+       struct bna_reg_offset reg_offset[] =                            \
+       {{HOSTFN0_INT_STATUS, HOSTFN0_INT_MSK},                         \
+        {HOSTFN1_INT_STATUS, HOSTFN1_INT_MSK},                         \
+        {HOSTFN2_INT_STATUS, HOSTFN2_INT_MSK},                         \
+        {HOSTFN3_INT_STATUS, HOSTFN3_INT_MSK} };                       \
+                                                                       \
+       (_bna)->regs.fn_int_status = (_pcidev)->pci_bar_kva +           \
+                               reg_offset[(_pcidev)->pci_func].fn_int_status;\
+       (_bna)->regs.fn_int_mask = (_pcidev)->pci_bar_kva +             \
+                               reg_offset[(_pcidev)->pci_func].fn_int_mask;\
+}
+
+#define ct_bit_defn_init(_bna, _pcidev)                                        \
+{                                                                      \
+       (_bna)->bits.mbox_status_bits = (__HFN_INT_MBOX_LPU0 |          \
+                                       __HFN_INT_MBOX_LPU1);           \
+       (_bna)->bits.mbox_mask_bits = (__HFN_INT_MBOX_LPU0 |            \
+                                       __HFN_INT_MBOX_LPU1);           \
+       (_bna)->bits.error_status_bits = (__HFN_INT_ERR_MASK);          \
+       (_bna)->bits.error_mask_bits = (__HFN_INT_ERR_MASK);            \
+       (_bna)->bits.halt_status_bits = __HFN_INT_LL_HALT;              \
+}
+
+#define ct2_reg_addr_init(_bna, _pcidev)                               \
+{                                                                      \
+       (_bna)->regs.fn_int_status = (_pcidev)->pci_bar_kva +           \
+                               CT2_HOSTFN_INT_STATUS;                  \
+       (_bna)->regs.fn_int_mask = (_pcidev)->pci_bar_kva +             \
+                               CT2_HOSTFN_INTR_MASK;                   \
+}
+
+#define ct2_bit_defn_init(_bna, _pcidev)                               \
+{                                                                      \
+       (_bna)->bits.mbox_status_bits = (__HFN_INT_MBOX_LPU0_CT2 |      \
+                                       __HFN_INT_MBOX_LPU1_CT2);       \
+       (_bna)->bits.mbox_mask_bits = (__HFN_INT_MBOX_LPU0_CT2 |        \
+                                       __HFN_INT_MBOX_LPU1_CT2);       \
+       (_bna)->bits.error_status_bits = (__HFN_INT_ERR_MASK_CT2);      \
+       (_bna)->bits.error_mask_bits = (__HFN_INT_ERR_MASK_CT2);        \
+       (_bna)->bits.halt_status_bits = __HFN_INT_CPQ_HALT_CT2;         \
+       (_bna)->bits.halt_mask_bits = __HFN_INT_CPQ_HALT_CT2;           \
+}
+
+#define bna_reg_addr_init(_bna, _pcidev)                               \
+{                                                                      \
+       switch ((_pcidev)->device_id) {                                 \
+       case PCI_DEVICE_ID_BROCADE_CT:                                  \
+               ct_reg_addr_init((_bna), (_pcidev));                    \
+               ct_bit_defn_init((_bna), (_pcidev));                    \
+               break;                                                  \
+       }                                                               \
+}
+
+#define bna_port_id_get(_bna) ((_bna)->ioceth.ioc.port_id)
+/**
+ *
+ *  Interrupt related bits, flags and macros
+ *
+ */
+
+#define IB_STATUS_BITS         0x0000ffff
+
+#define BNA_IS_MBOX_INTR(_bna, _intr_status)                           \
+       ((_intr_status) & (_bna)->bits.mbox_status_bits)
+
+#define BNA_IS_HALT_INTR(_bna, _intr_status)                           \
+       ((_intr_status) & (_bna)->bits.halt_status_bits)
+
+#define BNA_IS_ERR_INTR(_bna, _intr_status)    \
+       ((_intr_status) & (_bna)->bits.error_status_bits)
+
+#define BNA_IS_MBOX_ERR_INTR(_bna, _intr_status)       \
+       (BNA_IS_MBOX_INTR(_bna, _intr_status) |         \
+       BNA_IS_ERR_INTR(_bna, _intr_status))
+
+#define BNA_IS_INTX_DATA_INTR(_intr_status)            \
+               ((_intr_status) & IB_STATUS_BITS)
+
+#define bna_halt_clear(_bna)                                           \
+do {                                                                   \
+       u32 init_halt;                                          \
+       init_halt = readl((_bna)->ioceth.ioc.ioc_regs.ll_halt); \
+       init_halt &= ~__FW_INIT_HALT_P;                                 \
+       writel(init_halt, (_bna)->ioceth.ioc.ioc_regs.ll_halt); \
+       init_halt = readl((_bna)->ioceth.ioc.ioc_regs.ll_halt); \
+} while (0)
+
+#define bna_intx_disable(_bna, _cur_mask)                              \
+{                                                                      \
+       (_cur_mask) = readl((_bna)->regs.fn_int_mask);          \
+       writel(0xffffffff, (_bna)->regs.fn_int_mask);           \
+}
+
+#define bna_intx_enable(bna, new_mask)                                 \
+       writel((new_mask), (bna)->regs.fn_int_mask)
+#define bna_mbox_intr_disable(bna)                                     \
+do {                                                                   \
+       u32 mask;                                                       \
+       mask = readl((bna)->regs.fn_int_mask);                          \
+       writel((mask | (bna)->bits.mbox_mask_bits |                     \
+               (bna)->bits.error_mask_bits), (bna)->regs.fn_int_mask); \
+       mask = readl((bna)->regs.fn_int_mask);                          \
+} while (0)
+
+#define bna_mbox_intr_enable(bna)                                      \
+do {                                                                   \
+       u32 mask;                                                       \
+       mask = readl((bna)->regs.fn_int_mask);                          \
+       writel((mask & ~((bna)->bits.mbox_mask_bits |                   \
+               (bna)->bits.error_mask_bits)), (bna)->regs.fn_int_mask);\
+       mask = readl((bna)->regs.fn_int_mask);                          \
+} while (0)
+
+#define bna_intr_status_get(_bna, _status)                             \
+{                                                                      \
+       (_status) = readl((_bna)->regs.fn_int_status);                  \
+       if (_status) {                                                  \
+               writel(((_status) & ~(_bna)->bits.mbox_status_bits),    \
+                       (_bna)->regs.fn_int_status);                    \
+       }                                                               \
+}
+
+/*
+ * MAX ACK EVENTS : No. of acks that can be accumulated in driver,
+ * before acking to h/w. The no. of bits is 16 in the doorbell register,
+ * however we keep this limited to 15 bits.
+ * This is because around the edge of 64K boundary (16 bits), one
+ * single poll can make the accumulated ACK counter cross the 64K boundary,
+ * causing problems, when we try to ack with a value greater than 64K.
+ * 15 bits (32K) should  be large enough to accumulate, anyways, and the max.
+ * acked events to h/w can be (32K + max poll weight) (currently 64).
+ */
+#define        BNA_IB_MAX_ACK_EVENTS           (1 << 15)
+
+/* These macros build the data portion of the TxQ/RxQ doorbell */
+#define BNA_DOORBELL_Q_PRD_IDX(_pi)    (0x80000000 | (_pi))
+#define BNA_DOORBELL_Q_STOP            (0x40000000)
+
+/* These macros build the data portion of the IB doorbell */
+#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events)                     \
+       (0x80000000 | ((_timeout) << 16) | (_events))
+#define BNA_DOORBELL_IB_INT_DISABLE    (0x40000000)
+
+/* Set the coalescing timer for the given ib */
+#define bna_ib_coalescing_timer_set(_i_dbell, _cls_timer)              \
+       ((_i_dbell)->doorbell_ack = BNA_DOORBELL_IB_INT_ACK((_cls_timer), 0));
+
+/* Acks 'events' # of events for a given ib while disabling interrupts */
+#define bna_ib_ack_disable_irq(_i_dbell, _events)                      \
+       (writel(BNA_DOORBELL_IB_INT_ACK(0, (_events)), \
+               (_i_dbell)->doorbell_addr));
+
+/* Acks 'events' # of events for a given ib */
+#define bna_ib_ack(_i_dbell, _events)                                  \
+       (writel(((_i_dbell)->doorbell_ack | (_events)), \
+               (_i_dbell)->doorbell_addr));
+
+#define bna_ib_start(_bna, _ib, _is_regular)                           \
+{                                                                      \
+       u32 intx_mask;                                          \
+       struct bna_ib *ib = _ib;                                        \
+       if ((ib->intr_type == BNA_INTR_T_INTX)) {                       \
+               bna_intx_disable((_bna), intx_mask);                    \
+               intx_mask &= ~(ib->intr_vector);                        \
+               bna_intx_enable((_bna), intx_mask);                     \
+       }                                                               \
+       bna_ib_coalescing_timer_set(&ib->door_bell,                     \
+                       ib->coalescing_timeo);                          \
+       if (_is_regular)                                                \
+               bna_ib_ack(&ib->door_bell, 0);                          \
+}
+
+#define bna_ib_stop(_bna, _ib)                                         \
+{                                                                      \
+       u32 intx_mask;                                          \
+       struct bna_ib *ib = _ib;                                        \
+       writel(BNA_DOORBELL_IB_INT_DISABLE,                             \
+               ib->door_bell.doorbell_addr);                           \
+       if (ib->intr_type == BNA_INTR_T_INTX) {                         \
+               bna_intx_disable((_bna), intx_mask);                    \
+               intx_mask |= ib->intr_vector;                           \
+               bna_intx_enable((_bna), intx_mask);                     \
+       }                                                               \
+}
+
+#define bna_txq_prod_indx_doorbell(_tcb)                               \
+       (writel(BNA_DOORBELL_Q_PRD_IDX((_tcb)->producer_index), \
+               (_tcb)->q_dbell));
+
+#define bna_rxq_prod_indx_doorbell(_rcb)                               \
+       (writel(BNA_DOORBELL_Q_PRD_IDX((_rcb)->producer_index), \
+               (_rcb)->q_dbell));
+
+/**
+ *
+ * TxQ, RxQ, CQ related bits, offsets, macros
+ *
+ */
+
+/* TxQ Entry Opcodes */
+#define BNA_TXQ_WI_SEND                        (0x402) /* Single Frame Transmission */
+#define BNA_TXQ_WI_SEND_LSO            (0x403) /* Multi-Frame Transmission */
+#define BNA_TXQ_WI_EXTENSION           (0x104) /* Extension WI */
+
+/* TxQ Entry Control Flags */
+#define BNA_TXQ_WI_CF_FCOE_CRC         (1 << 8)
+#define BNA_TXQ_WI_CF_IPID_MODE                (1 << 5)
+#define BNA_TXQ_WI_CF_INS_PRIO         (1 << 4)
+#define BNA_TXQ_WI_CF_INS_VLAN         (1 << 3)
+#define BNA_TXQ_WI_CF_UDP_CKSUM                (1 << 2)
+#define BNA_TXQ_WI_CF_TCP_CKSUM                (1 << 1)
+#define BNA_TXQ_WI_CF_IP_CKSUM         (1 << 0)
+
+#define BNA_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \
+               (((_hdr_size) << 10) | ((_offset) & 0x3FF))
+
+/*
+ * Completion Q defines
+ */
+/* CQ Entry Flags */
+#define        BNA_CQ_EF_MAC_ERROR     (1 <<  0)
+#define        BNA_CQ_EF_FCS_ERROR     (1 <<  1)
+#define        BNA_CQ_EF_TOO_LONG      (1 <<  2)
+#define        BNA_CQ_EF_FC_CRC_OK     (1 <<  3)
+
+#define        BNA_CQ_EF_RSVD1         (1 <<  4)
+#define        BNA_CQ_EF_L4_CKSUM_OK   (1 <<  5)
+#define        BNA_CQ_EF_L3_CKSUM_OK   (1 <<  6)
+#define        BNA_CQ_EF_HDS_HEADER    (1 <<  7)
+
+#define        BNA_CQ_EF_UDP           (1 <<  8)
+#define        BNA_CQ_EF_TCP           (1 <<  9)
+#define        BNA_CQ_EF_IP_OPTIONS    (1 << 10)
+#define        BNA_CQ_EF_IPV6          (1 << 11)
+
+#define        BNA_CQ_EF_IPV4          (1 << 12)
+#define        BNA_CQ_EF_VLAN          (1 << 13)
+#define        BNA_CQ_EF_RSS           (1 << 14)
+#define        BNA_CQ_EF_RSVD2         (1 << 15)
+
+#define        BNA_CQ_EF_MCAST_MATCH   (1 << 16)
+#define        BNA_CQ_EF_MCAST         (1 << 17)
+#define BNA_CQ_EF_BCAST                (1 << 18)
+#define        BNA_CQ_EF_REMOTE        (1 << 19)
+
+#define        BNA_CQ_EF_LOCAL         (1 << 20)
+
+/**
+ *
+ * Data structures
+ *
+ */
+
+struct bna_reg_offset {
+       u32 fn_int_status;
+       u32 fn_int_mask;
+};
+
+struct bna_bit_defn {
+       u32 mbox_status_bits;
+       u32 mbox_mask_bits;
+       u32 error_status_bits;
+       u32 error_mask_bits;
+       u32 halt_status_bits;
+       u32 halt_mask_bits;
+};
+
+struct bna_reg {
+       void __iomem *fn_int_status;
+       void __iomem *fn_int_mask;
+};
+
+/* TxQ Vector (a.k.a. Tx-Buffer Descriptor) */
+struct bna_dma_addr {
+       u32             msb;
+       u32             lsb;
+};
+
+struct bna_txq_wi_vector {
+       u16             reserved;
+       u16             length;         /* Only 14 LSB are valid */
+       struct bna_dma_addr host_addr; /* Tx-Buf DMA addr */
+};
+
+/**
+ *  TxQ Entry Structure
+ *
+ *  BEWARE:  Load values into this structure with correct endianess.
+ */
+struct bna_txq_entry {
+       union {
+               struct {
+                       u8 reserved;
+                       u8 num_vectors; /* number of vectors present */
+                       u16 opcode; /* Either */
+                                                   /* BNA_TXQ_WI_SEND or */
+                                                   /* BNA_TXQ_WI_SEND_LSO */
+                       u16 flags; /* OR of all the flags */
+                       u16 l4_hdr_size_n_offset;
+                       u16 vlan_tag;
+                       u16 lso_mss;    /* Only 14 LSB are valid */
+                       u32 frame_length;       /* Only 24 LSB are valid */
+               } wi;
+
+               struct {
+                       u16 reserved;
+                       u16 opcode; /* Must be */
+                                                   /* BNA_TXQ_WI_EXTENSION */
+                       u32 reserved2[3];       /* Place holder for */
+                                               /* removed vector (12 bytes) */
+               } wi_ext;
+       } hdr;
+       struct bna_txq_wi_vector vector[4];
+};
+
+/* RxQ Entry Structure */
+struct bna_rxq_entry {         /* Rx-Buffer */
+       struct bna_dma_addr host_addr; /* Rx-Buffer DMA address */
+};
+
+/* CQ Entry Structure */
+struct bna_cq_entry {
+       u32 flags;
+       u16 vlan_tag;
+       u16 length;
+       u32 rss_hash;
+       u8 valid;
+       u8 reserved1;
+       u8 reserved2;
+       u8 rxq_id;
+};
+
+#endif /* __BNA_HW_DEFS_H__ */
diff --git a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c
new file mode 100644 (file)
index 0000000..9221413
--- /dev/null
@@ -0,0 +1,3787 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.
+  */
+/*
+ * Copyright (c) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#include "bna.h"
+#include "bfi.h"
+
+/**
+ * IB
+ */
+static void
+bna_ib_coalescing_timeo_set(struct bna_ib *ib, u8 coalescing_timeo)
+{
+       ib->coalescing_timeo = coalescing_timeo;
+       ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK(
+                               (u32)ib->coalescing_timeo, 0);
+}
+
+/**
+ * RXF
+ */
+
+#define bna_rxf_vlan_cfg_soft_reset(rxf)                               \
+do {                                                                   \
+       (rxf)->vlan_pending_bitmask = (u8)BFI_VLAN_BMASK_ALL;           \
+       (rxf)->vlan_strip_pending = true;                               \
+} while (0)
+
+#define bna_rxf_rss_cfg_soft_reset(rxf)                                        \
+do {                                                                   \
+       if ((rxf)->rss_status == BNA_STATUS_T_ENABLED)                  \
+               (rxf)->rss_pending = (BNA_RSS_F_RIT_PENDING |           \
+                               BNA_RSS_F_CFG_PENDING |                 \
+                               BNA_RSS_F_STATUS_PENDING);              \
+} while (0)
+
+static int bna_rxf_cfg_apply(struct bna_rxf *rxf);
+static void bna_rxf_cfg_reset(struct bna_rxf *rxf);
+static int bna_rxf_fltr_clear(struct bna_rxf *rxf);
+static int bna_rxf_ucast_cfg_apply(struct bna_rxf *rxf);
+static int bna_rxf_promisc_cfg_apply(struct bna_rxf *rxf);
+static int bna_rxf_allmulti_cfg_apply(struct bna_rxf *rxf);
+static int bna_rxf_vlan_strip_cfg_apply(struct bna_rxf *rxf);
+static int bna_rxf_ucast_cfg_reset(struct bna_rxf *rxf,
+                                       enum bna_cleanup_type cleanup);
+static int bna_rxf_promisc_cfg_reset(struct bna_rxf *rxf,
+                                       enum bna_cleanup_type cleanup);
+static int bna_rxf_allmulti_cfg_reset(struct bna_rxf *rxf,
+                                       enum bna_cleanup_type cleanup);
+
+bfa_fsm_state_decl(bna_rxf, stopped, struct bna_rxf,
+                       enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, paused, struct bna_rxf,
+                       enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, cfg_wait, struct bna_rxf,
+                       enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, started, struct bna_rxf,
+                       enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, fltr_clr_wait, struct bna_rxf,
+                       enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, last_resp_wait, struct bna_rxf,
+                       enum bna_rxf_event);
+
+static void
+bna_rxf_sm_stopped_entry(struct bna_rxf *rxf)
+{
+       call_rxf_stop_cbfn(rxf);
+}
+
+static void
+bna_rxf_sm_stopped(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+       switch (event) {
+       case RXF_E_START:
+               if (rxf->flags & BNA_RXF_F_PAUSED) {
+                       bfa_fsm_set_state(rxf, bna_rxf_sm_paused);
+                       call_rxf_start_cbfn(rxf);
+               } else
+                       bfa_fsm_set_state(rxf, bna_rxf_sm_cfg_wait);
+               break;
+
+       case RXF_E_STOP:
+               call_rxf_stop_cbfn(rxf);
+               break;
+
+       case RXF_E_FAIL:
+               /* No-op */
+               break;
+
+       case RXF_E_CONFIG:
+               call_rxf_cam_fltr_cbfn(rxf);
+               break;
+
+       case RXF_E_PAUSE:
+               rxf->flags |= BNA_RXF_F_PAUSED;
+               call_rxf_pause_cbfn(rxf);
+               break;
+
+       case RXF_E_RESUME:
+               rxf->flags &= ~BNA_RXF_F_PAUSED;
+               call_rxf_resume_cbfn(rxf);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_rxf_sm_paused_entry(struct bna_rxf *rxf)
+{
+       call_rxf_pause_cbfn(rxf);
+}
+
+static void
+bna_rxf_sm_paused(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+       switch (event) {
+       case RXF_E_STOP:
+       case RXF_E_FAIL:
+               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+               break;
+
+       case RXF_E_CONFIG:
+               call_rxf_cam_fltr_cbfn(rxf);
+               break;
+
+       case RXF_E_RESUME:
+               rxf->flags &= ~BNA_RXF_F_PAUSED;
+               bfa_fsm_set_state(rxf, bna_rxf_sm_cfg_wait);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_rxf_sm_cfg_wait_entry(struct bna_rxf *rxf)
+{
+       if (!bna_rxf_cfg_apply(rxf)) {
+               /* No more pending config updates */
+               bfa_fsm_set_state(rxf, bna_rxf_sm_started);
+       }
+}
+
+static void
+bna_rxf_sm_cfg_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+       switch (event) {
+       case RXF_E_STOP:
+               bfa_fsm_set_state(rxf, bna_rxf_sm_last_resp_wait);
+               break;
+
+       case RXF_E_FAIL:
+               bna_rxf_cfg_reset(rxf);
+               call_rxf_start_cbfn(rxf);
+               call_rxf_cam_fltr_cbfn(rxf);
+               call_rxf_resume_cbfn(rxf);
+               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+               break;
+
+       case RXF_E_CONFIG:
+               /* No-op */
+               break;
+
+       case RXF_E_PAUSE:
+               rxf->flags |= BNA_RXF_F_PAUSED;
+               call_rxf_start_cbfn(rxf);
+               bfa_fsm_set_state(rxf, bna_rxf_sm_fltr_clr_wait);
+               break;
+
+       case RXF_E_FW_RESP:
+               if (!bna_rxf_cfg_apply(rxf)) {
+                       /* No more pending config updates */
+                       bfa_fsm_set_state(rxf, bna_rxf_sm_started);
+               }
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_rxf_sm_started_entry(struct bna_rxf *rxf)
+{
+       call_rxf_start_cbfn(rxf);
+       call_rxf_cam_fltr_cbfn(rxf);
+       call_rxf_resume_cbfn(rxf);
+}
+
+static void
+bna_rxf_sm_started(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+       switch (event) {
+       case RXF_E_STOP:
+       case RXF_E_FAIL:
+               bna_rxf_cfg_reset(rxf);
+               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+               break;
+
+       case RXF_E_CONFIG:
+               bfa_fsm_set_state(rxf, bna_rxf_sm_cfg_wait);
+               break;
+
+       case RXF_E_PAUSE:
+               rxf->flags |= BNA_RXF_F_PAUSED;
+               if (!bna_rxf_fltr_clear(rxf))
+                       bfa_fsm_set_state(rxf, bna_rxf_sm_paused);
+               else
+                       bfa_fsm_set_state(rxf, bna_rxf_sm_fltr_clr_wait);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_rxf_sm_fltr_clr_wait_entry(struct bna_rxf *rxf)
+{
+}
+
+static void
+bna_rxf_sm_fltr_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+       switch (event) {
+       case RXF_E_FAIL:
+               bna_rxf_cfg_reset(rxf);
+               call_rxf_pause_cbfn(rxf);
+               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+               break;
+
+       case RXF_E_FW_RESP:
+               if (!bna_rxf_fltr_clear(rxf)) {
+                       /* No more pending CAM entries to clear */
+                       bfa_fsm_set_state(rxf, bna_rxf_sm_paused);
+               }
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_rxf_sm_last_resp_wait_entry(struct bna_rxf *rxf)
+{
+}
+
+static void
+bna_rxf_sm_last_resp_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+       switch (event) {
+       case RXF_E_FAIL:
+       case RXF_E_FW_RESP:
+               bna_rxf_cfg_reset(rxf);
+               bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_bfi_ucast_req(struct bna_rxf *rxf, struct bna_mac *mac,
+               enum bfi_enet_h2i_msgs req_type)
+{
+       struct bfi_enet_ucast_req *req = &rxf->bfi_enet_cmd.ucast_req;
+
+       bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET, req_type, 0, rxf->rx->rid);
+       req->mh.num_entries = htons(
+       bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_ucast_req)));
+       memcpy(&req->mac_addr, &mac->addr, sizeof(mac_t));
+       bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_ucast_req), &req->mh);
+       bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_mcast_add_req(struct bna_rxf *rxf, struct bna_mac *mac)
+{
+       struct bfi_enet_mcast_add_req *req =
+               &rxf->bfi_enet_cmd.mcast_add_req;
+
+       bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET, BFI_ENET_H2I_MAC_MCAST_ADD_REQ,
+               0, rxf->rx->rid);
+       req->mh.num_entries = htons(
+       bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_mcast_add_req)));
+       memcpy(&req->mac_addr, &mac->addr, sizeof(mac_t));
+       bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_mcast_add_req), &req->mh);
+       bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_mcast_del_req(struct bna_rxf *rxf, u16 handle)
+{
+       struct bfi_enet_mcast_del_req *req =
+               &rxf->bfi_enet_cmd.mcast_del_req;
+
+       bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET, BFI_ENET_H2I_MAC_MCAST_DEL_REQ,
+               0, rxf->rx->rid);
+       req->mh.num_entries = htons(
+       bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_mcast_del_req)));
+       req->handle = htons(handle);
+       bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_mcast_del_req), &req->mh);
+       bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_mcast_filter_req(struct bna_rxf *rxf, enum bna_status status)
+{
+       struct bfi_enet_enable_req *req = &rxf->bfi_enet_cmd.req;
+
+       bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_MAC_MCAST_FILTER_REQ, 0, rxf->rx->rid);
+       req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_enable_req)));
+       req->enable = status;
+       bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_enable_req), &req->mh);
+       bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_rx_promisc_req(struct bna_rxf *rxf, enum bna_status status)
+{
+       struct bfi_enet_enable_req *req = &rxf->bfi_enet_cmd.req;
+
+       bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_RX_PROMISCUOUS_REQ, 0, rxf->rx->rid);
+       req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_enable_req)));
+       req->enable = status;
+       bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_enable_req), &req->mh);
+       bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_rx_vlan_filter_set(struct bna_rxf *rxf, u8 block_idx)
+{
+       struct bfi_enet_rx_vlan_req *req = &rxf->bfi_enet_cmd.vlan_req;
+       int i;
+       int j;
+
+       bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_RX_VLAN_SET_REQ, 0, rxf->rx->rid);
+       req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_rx_vlan_req)));
+       req->block_idx = block_idx;
+       for (i = 0; i < (BFI_ENET_VLAN_BLOCK_SIZE / 32); i++) {
+               j = (block_idx * (BFI_ENET_VLAN_BLOCK_SIZE / 32)) + i;
+               if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED)
+                       req->bit_mask[i] =
+                               htonl(rxf->vlan_filter_table[j]);
+               else
+                       req->bit_mask[i] = 0xFFFFFFFF;
+       }
+       bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_rx_vlan_req), &req->mh);
+       bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_vlan_strip_enable(struct bna_rxf *rxf)
+{
+       struct bfi_enet_enable_req *req = &rxf->bfi_enet_cmd.req;
+
+       bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_RX_VLAN_STRIP_ENABLE_REQ, 0, rxf->rx->rid);
+       req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_enable_req)));
+       req->enable = rxf->vlan_strip_status;
+       bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_enable_req), &req->mh);
+       bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_rit_cfg(struct bna_rxf *rxf)
+{
+       struct bfi_enet_rit_req *req = &rxf->bfi_enet_cmd.rit_req;
+
+       bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_RIT_CFG_REQ, 0, rxf->rx->rid);
+       req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_rit_req)));
+       req->size = htons(rxf->rit_size);
+       memcpy(&req->table[0], rxf->rit, rxf->rit_size);
+       bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_rit_req), &req->mh);
+       bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_rss_cfg(struct bna_rxf *rxf)
+{
+       struct bfi_enet_rss_cfg_req *req = &rxf->bfi_enet_cmd.rss_req;
+       int i;
+
+       bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_RSS_CFG_REQ, 0, rxf->rx->rid);
+       req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_rss_cfg_req)));
+       req->cfg.type = rxf->rss_cfg.hash_type;
+       req->cfg.mask = rxf->rss_cfg.hash_mask;
+       for (i = 0; i < BFI_ENET_RSS_KEY_LEN; i++)
+               req->cfg.key[i] =
+                       htonl(rxf->rss_cfg.toeplitz_hash_key[i]);
+       bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_rss_cfg_req), &req->mh);
+       bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_rss_enable(struct bna_rxf *rxf)
+{
+       struct bfi_enet_enable_req *req = &rxf->bfi_enet_cmd.req;
+
+       bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_RSS_ENABLE_REQ, 0, rxf->rx->rid);
+       req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_enable_req)));
+       req->enable = rxf->rss_status;
+       bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_enable_req), &req->mh);
+       bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+/* This function gets the multicast MAC that has already been added to CAM */
+static struct bna_mac *
+bna_rxf_mcmac_get(struct bna_rxf *rxf, u8 *mac_addr)
+{
+       struct bna_mac *mac;
+       struct list_head *qe;
+
+       list_for_each(qe, &rxf->mcast_active_q) {
+               mac = (struct bna_mac *)qe;
+               if (BNA_MAC_IS_EQUAL(&mac->addr, mac_addr))
+                       return mac;
+       }
+
+       list_for_each(qe, &rxf->mcast_pending_del_q) {
+               mac = (struct bna_mac *)qe;
+               if (BNA_MAC_IS_EQUAL(&mac->addr, mac_addr))
+                       return mac;
+       }
+
+       return NULL;
+}
+
+static struct bna_mcam_handle *
+bna_rxf_mchandle_get(struct bna_rxf *rxf, int handle)
+{
+       struct bna_mcam_handle *mchandle;
+       struct list_head *qe;
+
+       list_for_each(qe, &rxf->mcast_handle_q) {
+               mchandle = (struct bna_mcam_handle *)qe;
+               if (mchandle->handle == handle)
+                       return mchandle;
+       }
+
+       return NULL;
+}
+
+static void
+bna_rxf_mchandle_attach(struct bna_rxf *rxf, u8 *mac_addr, int handle)
+{
+       struct bna_mac *mcmac;
+       struct bna_mcam_handle *mchandle;
+
+       mcmac = bna_rxf_mcmac_get(rxf, mac_addr);
+       mchandle = bna_rxf_mchandle_get(rxf, handle);
+       if (mchandle == NULL) {
+               mchandle = bna_mcam_mod_handle_get(&rxf->rx->bna->mcam_mod);
+               mchandle->handle = handle;
+               mchandle->refcnt = 0;
+               list_add_tail(&mchandle->qe, &rxf->mcast_handle_q);
+       }
+       mchandle->refcnt++;
+       mcmac->handle = mchandle;
+}
+
+static int
+bna_rxf_mcast_del(struct bna_rxf *rxf, struct bna_mac *mac,
+               enum bna_cleanup_type cleanup)
+{
+       struct bna_mcam_handle *mchandle;
+       int ret = 0;
+
+       mchandle = mac->handle;
+       if (mchandle == NULL)
+               return ret;
+
+       mchandle->refcnt--;
+       if (mchandle->refcnt == 0) {
+               if (cleanup == BNA_HARD_CLEANUP) {
+                       bna_bfi_mcast_del_req(rxf, mchandle->handle);
+                       ret = 1;
+               }
+               list_del(&mchandle->qe);
+               bfa_q_qe_init(&mchandle->qe);
+               bna_mcam_mod_handle_put(&rxf->rx->bna->mcam_mod, mchandle);
+       }
+       mac->handle = NULL;
+
+       return ret;
+}
+
+static int
+bna_rxf_mcast_cfg_apply(struct bna_rxf *rxf)
+{
+       struct bna_mac *mac = NULL;
+       struct list_head *qe;
+       int ret;
+
+       /* Delete multicast entries previousely added */
+       while (!list_empty(&rxf->mcast_pending_del_q)) {
+               bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
+               bfa_q_qe_init(qe);
+               mac = (struct bna_mac *)qe;
+               ret = bna_rxf_mcast_del(rxf, mac, BNA_HARD_CLEANUP);
+               bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+               if (ret)
+                       return ret;
+       }
+
+       /* Add multicast entries */
+       if (!list_empty(&rxf->mcast_pending_add_q)) {
+               bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
+               bfa_q_qe_init(qe);
+               mac = (struct bna_mac *)qe;
+               list_add_tail(&mac->qe, &rxf->mcast_active_q);
+               bna_bfi_mcast_add_req(rxf, mac);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int
+bna_rxf_vlan_cfg_apply(struct bna_rxf *rxf)
+{
+       u8 vlan_pending_bitmask;
+       int block_idx = 0;
+
+       if (rxf->vlan_pending_bitmask) {
+               vlan_pending_bitmask = rxf->vlan_pending_bitmask;
+               while (!(vlan_pending_bitmask & 0x1)) {
+                       block_idx++;
+                       vlan_pending_bitmask >>= 1;
+               }
+               rxf->vlan_pending_bitmask &= ~(1 << block_idx);
+               bna_bfi_rx_vlan_filter_set(rxf, block_idx);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int
+bna_rxf_mcast_cfg_reset(struct bna_rxf *rxf, enum bna_cleanup_type cleanup)
+{
+       struct list_head *qe;
+       struct bna_mac *mac;
+       int ret;
+
+       /* Throw away delete pending mcast entries */
+       while (!list_empty(&rxf->mcast_pending_del_q)) {
+               bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
+               bfa_q_qe_init(qe);
+               mac = (struct bna_mac *)qe;
+               ret = bna_rxf_mcast_del(rxf, mac, cleanup);
+               bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+               if (ret)
+                       return ret;
+       }
+
+       /* Move active mcast entries to pending_add_q */
+       while (!list_empty(&rxf->mcast_active_q)) {
+               bfa_q_deq(&rxf->mcast_active_q, &qe);
+               bfa_q_qe_init(qe);
+               list_add_tail(qe, &rxf->mcast_pending_add_q);
+               mac = (struct bna_mac *)qe;
+               if (bna_rxf_mcast_del(rxf, mac, cleanup))
+                       return 1;
+       }
+
+       return 0;
+}
+
+static int
+bna_rxf_rss_cfg_apply(struct bna_rxf *rxf)
+{
+       if (rxf->rss_pending) {
+               if (rxf->rss_pending & BNA_RSS_F_RIT_PENDING) {
+                       rxf->rss_pending &= ~BNA_RSS_F_RIT_PENDING;
+                       bna_bfi_rit_cfg(rxf);
+                       return 1;
+               }
+
+               if (rxf->rss_pending & BNA_RSS_F_CFG_PENDING) {
+                       rxf->rss_pending &= ~BNA_RSS_F_CFG_PENDING;
+                       bna_bfi_rss_cfg(rxf);
+                       return 1;
+               }
+
+               if (rxf->rss_pending & BNA_RSS_F_STATUS_PENDING) {
+                       rxf->rss_pending &= ~BNA_RSS_F_STATUS_PENDING;
+                       bna_bfi_rss_enable(rxf);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static int
+bna_rxf_cfg_apply(struct bna_rxf *rxf)
+{
+       if (bna_rxf_ucast_cfg_apply(rxf))
+               return 1;
+
+       if (bna_rxf_mcast_cfg_apply(rxf))
+               return 1;
+
+       if (bna_rxf_promisc_cfg_apply(rxf))
+               return 1;
+
+       if (bna_rxf_allmulti_cfg_apply(rxf))
+               return 1;
+
+       if (bna_rxf_vlan_cfg_apply(rxf))
+               return 1;
+
+       if (bna_rxf_vlan_strip_cfg_apply(rxf))
+               return 1;
+
+       if (bna_rxf_rss_cfg_apply(rxf))
+               return 1;
+
+       return 0;
+}
+
+/* Only software reset */
+static int
+bna_rxf_fltr_clear(struct bna_rxf *rxf)
+{
+       if (bna_rxf_ucast_cfg_reset(rxf, BNA_HARD_CLEANUP))
+               return 1;
+
+       if (bna_rxf_mcast_cfg_reset(rxf, BNA_HARD_CLEANUP))
+               return 1;
+
+       if (bna_rxf_promisc_cfg_reset(rxf, BNA_HARD_CLEANUP))
+               return 1;
+
+       if (bna_rxf_allmulti_cfg_reset(rxf, BNA_HARD_CLEANUP))
+               return 1;
+
+       return 0;
+}
+
+static void
+bna_rxf_cfg_reset(struct bna_rxf *rxf)
+{
+       bna_rxf_ucast_cfg_reset(rxf, BNA_SOFT_CLEANUP);
+       bna_rxf_mcast_cfg_reset(rxf, BNA_SOFT_CLEANUP);
+       bna_rxf_promisc_cfg_reset(rxf, BNA_SOFT_CLEANUP);
+       bna_rxf_allmulti_cfg_reset(rxf, BNA_SOFT_CLEANUP);
+       bna_rxf_vlan_cfg_soft_reset(rxf);
+       bna_rxf_rss_cfg_soft_reset(rxf);
+}
+
+static void
+bna_rit_init(struct bna_rxf *rxf, int rit_size)
+{
+       struct bna_rx *rx = rxf->rx;
+       struct bna_rxp *rxp;
+       struct list_head *qe;
+       int offset = 0;
+
+       rxf->rit_size = rit_size;
+       list_for_each(qe, &rx->rxp_q) {
+               rxp = (struct bna_rxp *)qe;
+               rxf->rit[offset] = rxp->cq.ccb->id;
+               offset++;
+       }
+
+}
+
+void
+bna_bfi_rxf_cfg_rsp(struct bna_rxf *rxf, struct bfi_msgq_mhdr *msghdr)
+{
+       bfa_fsm_send_event(rxf, RXF_E_FW_RESP);
+}
+
+void
+bna_bfi_rxf_mcast_add_rsp(struct bna_rxf *rxf,
+                       struct bfi_msgq_mhdr *msghdr)
+{
+       struct bfi_enet_mcast_add_req *req =
+               &rxf->bfi_enet_cmd.mcast_add_req;
+       struct bfi_enet_mcast_add_rsp *rsp =
+               (struct bfi_enet_mcast_add_rsp *)msghdr;
+
+       bna_rxf_mchandle_attach(rxf, (u8 *)&req->mac_addr,
+               ntohs(rsp->handle));
+       bfa_fsm_send_event(rxf, RXF_E_FW_RESP);
+}
+
+static void
+bna_rxf_init(struct bna_rxf *rxf,
+               struct bna_rx *rx,
+               struct bna_rx_config *q_config,
+               struct bna_res_info *res_info)
+{
+       rxf->rx = rx;
+
+       INIT_LIST_HEAD(&rxf->ucast_pending_add_q);
+       INIT_LIST_HEAD(&rxf->ucast_pending_del_q);
+       rxf->ucast_pending_set = 0;
+       rxf->ucast_active_set = 0;
+       INIT_LIST_HEAD(&rxf->ucast_active_q);
+       rxf->ucast_pending_mac = NULL;
+
+       INIT_LIST_HEAD(&rxf->mcast_pending_add_q);
+       INIT_LIST_HEAD(&rxf->mcast_pending_del_q);
+       INIT_LIST_HEAD(&rxf->mcast_active_q);
+       INIT_LIST_HEAD(&rxf->mcast_handle_q);
+
+       if (q_config->paused)
+               rxf->flags |= BNA_RXF_F_PAUSED;
+
+       rxf->rit = (u8 *)
+               res_info[BNA_RX_RES_MEM_T_RIT].res_u.mem_info.mdl[0].kva;
+       bna_rit_init(rxf, q_config->num_paths);
+
+       rxf->rss_status = q_config->rss_status;
+       if (rxf->rss_status == BNA_STATUS_T_ENABLED) {
+               rxf->rss_cfg = q_config->rss_config;
+               rxf->rss_pending |= BNA_RSS_F_CFG_PENDING;
+               rxf->rss_pending |= BNA_RSS_F_RIT_PENDING;
+               rxf->rss_pending |= BNA_RSS_F_STATUS_PENDING;
+       }
+
+       rxf->vlan_filter_status = BNA_STATUS_T_DISABLED;
+       memset(rxf->vlan_filter_table, 0,
+                       (sizeof(u32) * (BFI_ENET_VLAN_ID_MAX / 32)));
+       rxf->vlan_filter_table[0] |= 1; /* for pure priority tagged frames */
+       rxf->vlan_pending_bitmask = (u8)BFI_VLAN_BMASK_ALL;
+
+       rxf->vlan_strip_status = q_config->vlan_strip_status;
+
+       bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+}
+
+static void
+bna_rxf_uninit(struct bna_rxf *rxf)
+{
+       struct bna_mac *mac;
+
+       rxf->ucast_pending_set = 0;
+       rxf->ucast_active_set = 0;
+
+       while (!list_empty(&rxf->ucast_pending_add_q)) {
+               bfa_q_deq(&rxf->ucast_pending_add_q, &mac);
+               bfa_q_qe_init(&mac->qe);
+               bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+       }
+
+       if (rxf->ucast_pending_mac) {
+               bfa_q_qe_init(&rxf->ucast_pending_mac->qe);
+               bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod,
+                       rxf->ucast_pending_mac);
+               rxf->ucast_pending_mac = NULL;
+       }
+
+       while (!list_empty(&rxf->mcast_pending_add_q)) {
+               bfa_q_deq(&rxf->mcast_pending_add_q, &mac);
+               bfa_q_qe_init(&mac->qe);
+               bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+       }
+
+       rxf->rxmode_pending = 0;
+       rxf->rxmode_pending_bitmask = 0;
+       if (rxf->rx->bna->promisc_rid == rxf->rx->rid)
+               rxf->rx->bna->promisc_rid = BFI_INVALID_RID;
+       if (rxf->rx->bna->default_mode_rid == rxf->rx->rid)
+               rxf->rx->bna->default_mode_rid = BFI_INVALID_RID;
+
+       rxf->rss_pending = 0;
+       rxf->vlan_strip_pending = false;
+
+       rxf->flags = 0;
+
+       rxf->rx = NULL;
+}
+
+static void
+bna_rx_cb_rxf_started(struct bna_rx *rx)
+{
+       bfa_fsm_send_event(rx, RX_E_RXF_STARTED);
+}
+
+static void
+bna_rxf_start(struct bna_rxf *rxf)
+{
+       rxf->start_cbfn = bna_rx_cb_rxf_started;
+       rxf->start_cbarg = rxf->rx;
+       bfa_fsm_send_event(rxf, RXF_E_START);
+}
+
+static void
+bna_rx_cb_rxf_stopped(struct bna_rx *rx)
+{
+       bfa_fsm_send_event(rx, RX_E_RXF_STOPPED);
+}
+
+static void
+bna_rxf_stop(struct bna_rxf *rxf)
+{
+       rxf->stop_cbfn = bna_rx_cb_rxf_stopped;
+       rxf->stop_cbarg = rxf->rx;
+       bfa_fsm_send_event(rxf, RXF_E_STOP);
+}
+
+static void
+bna_rxf_fail(struct bna_rxf *rxf)
+{
+       bfa_fsm_send_event(rxf, RXF_E_FAIL);
+}
+
+enum bna_cb_status
+bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,
+                void (*cbfn)(struct bnad *, struct bna_rx *))
+{
+       struct bna_rxf *rxf = &rx->rxf;
+
+       if (rxf->ucast_pending_mac == NULL) {
+               rxf->ucast_pending_mac =
+                               bna_ucam_mod_mac_get(&rxf->rx->bna->ucam_mod);
+               if (rxf->ucast_pending_mac == NULL)
+                       return BNA_CB_UCAST_CAM_FULL;
+               bfa_q_qe_init(&rxf->ucast_pending_mac->qe);
+       }
+
+       memcpy(rxf->ucast_pending_mac->addr, ucmac, ETH_ALEN);
+       rxf->ucast_pending_set = 1;
+       rxf->cam_fltr_cbfn = cbfn;
+       rxf->cam_fltr_cbarg = rx->bna->bnad;
+
+       bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+
+       return BNA_CB_SUCCESS;
+}
+
+enum bna_cb_status
+bna_rx_mcast_add(struct bna_rx *rx, u8 *addr,
+                void (*cbfn)(struct bnad *, struct bna_rx *))
+{
+       struct bna_rxf *rxf = &rx->rxf;
+       struct bna_mac *mac;
+
+       /* Check if already added or pending addition */
+       if (bna_mac_find(&rxf->mcast_active_q, addr) ||
+               bna_mac_find(&rxf->mcast_pending_add_q, addr)) {
+               if (cbfn)
+                       cbfn(rx->bna->bnad, rx);
+               return BNA_CB_SUCCESS;
+       }
+
+       mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
+       if (mac == NULL)
+               return BNA_CB_MCAST_LIST_FULL;
+       bfa_q_qe_init(&mac->qe);
+       memcpy(mac->addr, addr, ETH_ALEN);
+       list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
+
+       rxf->cam_fltr_cbfn = cbfn;
+       rxf->cam_fltr_cbarg = rx->bna->bnad;
+
+       bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+
+       return BNA_CB_SUCCESS;
+}
+
+enum bna_cb_status
+bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist,
+                    void (*cbfn)(struct bnad *, struct bna_rx *))
+{
+       struct bna_rxf *rxf = &rx->rxf;
+       struct list_head list_head;
+       struct list_head *qe;
+       u8 *mcaddr;
+       struct bna_mac *mac;
+       int i;
+
+       /* Allocate nodes */
+       INIT_LIST_HEAD(&list_head);
+       for (i = 0, mcaddr = mclist; i < count; i++) {
+               mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
+               if (mac == NULL)
+                       goto err_return;
+               bfa_q_qe_init(&mac->qe);
+               memcpy(mac->addr, mcaddr, ETH_ALEN);
+               list_add_tail(&mac->qe, &list_head);
+
+               mcaddr += ETH_ALEN;
+       }
+
+       /* Purge the pending_add_q */
+       while (!list_empty(&rxf->mcast_pending_add_q)) {
+               bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
+               bfa_q_qe_init(qe);
+               mac = (struct bna_mac *)qe;
+               bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+       }
+
+       /* Schedule active_q entries for deletion */
+       while (!list_empty(&rxf->mcast_active_q)) {
+               bfa_q_deq(&rxf->mcast_active_q, &qe);
+               mac = (struct bna_mac *)qe;
+               bfa_q_qe_init(&mac->qe);
+               list_add_tail(&mac->qe, &rxf->mcast_pending_del_q);
+       }
+
+       /* Add the new entries */
+       while (!list_empty(&list_head)) {
+               bfa_q_deq(&list_head, &qe);
+               mac = (struct bna_mac *)qe;
+               bfa_q_qe_init(&mac->qe);
+               list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
+       }
+
+       rxf->cam_fltr_cbfn = cbfn;
+       rxf->cam_fltr_cbarg = rx->bna->bnad;
+       bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+
+       return BNA_CB_SUCCESS;
+
+err_return:
+       while (!list_empty(&list_head)) {
+               bfa_q_deq(&list_head, &qe);
+               mac = (struct bna_mac *)qe;
+               bfa_q_qe_init(&mac->qe);
+               bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+       }
+
+       return BNA_CB_MCAST_LIST_FULL;
+}
+
+void
+bna_rx_vlan_add(struct bna_rx *rx, int vlan_id)
+{
+       struct bna_rxf *rxf = &rx->rxf;
+       int index = (vlan_id >> BFI_VLAN_WORD_SHIFT);
+       int bit = (1 << (vlan_id & BFI_VLAN_WORD_MASK));
+       int group_id = (vlan_id >> BFI_VLAN_BLOCK_SHIFT);
+
+       rxf->vlan_filter_table[index] |= bit;
+       if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
+               rxf->vlan_pending_bitmask |= (1 << group_id);
+               bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+       }
+}
+
+void
+bna_rx_vlan_del(struct bna_rx *rx, int vlan_id)
+{
+       struct bna_rxf *rxf = &rx->rxf;
+       int index = (vlan_id >> BFI_VLAN_WORD_SHIFT);
+       int bit = (1 << (vlan_id & BFI_VLAN_WORD_MASK));
+       int group_id = (vlan_id >> BFI_VLAN_BLOCK_SHIFT);
+
+       rxf->vlan_filter_table[index] &= ~bit;
+       if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
+               rxf->vlan_pending_bitmask |= (1 << group_id);
+               bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+       }
+}
+
+static int
+bna_rxf_ucast_cfg_apply(struct bna_rxf *rxf)
+{
+       struct bna_mac *mac = NULL;
+       struct list_head *qe;
+
+       /* Delete MAC addresses previousely added */
+       if (!list_empty(&rxf->ucast_pending_del_q)) {
+               bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
+               bfa_q_qe_init(qe);
+               mac = (struct bna_mac *)qe;
+               bna_bfi_ucast_req(rxf, mac, BFI_ENET_H2I_MAC_UCAST_DEL_REQ);
+               bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+               return 1;
+       }
+
+       /* Set default unicast MAC */
+       if (rxf->ucast_pending_set) {
+               rxf->ucast_pending_set = 0;
+               memcpy(rxf->ucast_active_mac.addr,
+                       rxf->ucast_pending_mac->addr, ETH_ALEN);
+               rxf->ucast_active_set = 1;
+               bna_bfi_ucast_req(rxf, &rxf->ucast_active_mac,
+                       BFI_ENET_H2I_MAC_UCAST_SET_REQ);
+               return 1;
+       }
+
+       /* Add additional MAC entries */
+       if (!list_empty(&rxf->ucast_pending_add_q)) {
+               bfa_q_deq(&rxf->ucast_pending_add_q, &qe);
+               bfa_q_qe_init(qe);
+               mac = (struct bna_mac *)qe;
+               list_add_tail(&mac->qe, &rxf->ucast_active_q);
+               bna_bfi_ucast_req(rxf, mac, BFI_ENET_H2I_MAC_UCAST_ADD_REQ);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int
+bna_rxf_ucast_cfg_reset(struct bna_rxf *rxf, enum bna_cleanup_type cleanup)
+{
+       struct list_head *qe;
+       struct bna_mac *mac;
+
+       /* Throw away delete pending ucast entries */
+       while (!list_empty(&rxf->ucast_pending_del_q)) {
+               bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
+               bfa_q_qe_init(qe);
+               mac = (struct bna_mac *)qe;
+               if (cleanup == BNA_SOFT_CLEANUP)
+                       bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+               else {
+                       bna_bfi_ucast_req(rxf, mac,
+                               BFI_ENET_H2I_MAC_UCAST_DEL_REQ);
+                       bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+                       return 1;
+               }
+       }
+
+       /* Move active ucast entries to pending_add_q */
+       while (!list_empty(&rxf->ucast_active_q)) {
+               bfa_q_deq(&rxf->ucast_active_q, &qe);
+               bfa_q_qe_init(qe);
+               list_add_tail(qe, &rxf->ucast_pending_add_q);
+               if (cleanup == BNA_HARD_CLEANUP) {
+                       mac = (struct bna_mac *)qe;
+                       bna_bfi_ucast_req(rxf, mac,
+                               BFI_ENET_H2I_MAC_UCAST_DEL_REQ);
+                       return 1;
+               }
+       }
+
+       if (rxf->ucast_active_set) {
+               rxf->ucast_pending_set = 1;
+               rxf->ucast_active_set = 0;
+               if (cleanup == BNA_HARD_CLEANUP) {
+                       bna_bfi_ucast_req(rxf, &rxf->ucast_active_mac,
+                               BFI_ENET_H2I_MAC_UCAST_CLR_REQ);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static int
+bna_rxf_promisc_cfg_apply(struct bna_rxf *rxf)
+{
+       struct bna *bna = rxf->rx->bna;
+
+       /* Enable/disable promiscuous mode */
+       if (is_promisc_enable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask)) {
+               /* move promisc configuration from pending -> active */
+               promisc_inactive(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               rxf->rxmode_active |= BNA_RXMODE_PROMISC;
+               bna_bfi_rx_promisc_req(rxf, BNA_STATUS_T_ENABLED);
+               return 1;
+       } else if (is_promisc_disable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask)) {
+               /* move promisc configuration from pending -> active */
+               promisc_inactive(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+               bna->promisc_rid = BFI_INVALID_RID;
+               bna_bfi_rx_promisc_req(rxf, BNA_STATUS_T_DISABLED);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int
+bna_rxf_promisc_cfg_reset(struct bna_rxf *rxf, enum bna_cleanup_type cleanup)
+{
+       struct bna *bna = rxf->rx->bna;
+
+       /* Clear pending promisc mode disable */
+       if (is_promisc_disable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask)) {
+               promisc_inactive(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+               bna->promisc_rid = BFI_INVALID_RID;
+               if (cleanup == BNA_HARD_CLEANUP) {
+                       bna_bfi_rx_promisc_req(rxf, BNA_STATUS_T_DISABLED);
+                       return 1;
+               }
+       }
+
+       /* Move promisc mode config from active -> pending */
+       if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
+               promisc_enable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+               if (cleanup == BNA_HARD_CLEANUP) {
+                       bna_bfi_rx_promisc_req(rxf, BNA_STATUS_T_DISABLED);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static int
+bna_rxf_allmulti_cfg_apply(struct bna_rxf *rxf)
+{
+       /* Enable/disable allmulti mode */
+       if (is_allmulti_enable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask)) {
+               /* move allmulti configuration from pending -> active */
+               allmulti_inactive(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               rxf->rxmode_active |= BNA_RXMODE_ALLMULTI;
+               bna_bfi_mcast_filter_req(rxf, BNA_STATUS_T_DISABLED);
+               return 1;
+       } else if (is_allmulti_disable(rxf->rxmode_pending,
+                                       rxf->rxmode_pending_bitmask)) {
+               /* move allmulti configuration from pending -> active */
+               allmulti_inactive(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+               bna_bfi_mcast_filter_req(rxf, BNA_STATUS_T_ENABLED);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int
+bna_rxf_allmulti_cfg_reset(struct bna_rxf *rxf, enum bna_cleanup_type cleanup)
+{
+       /* Clear pending allmulti mode disable */
+       if (is_allmulti_disable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask)) {
+               allmulti_inactive(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+               if (cleanup == BNA_HARD_CLEANUP) {
+                       bna_bfi_mcast_filter_req(rxf, BNA_STATUS_T_ENABLED);
+                       return 1;
+               }
+       }
+
+       /* Move allmulti mode config from active -> pending */
+       if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
+               allmulti_enable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+               if (cleanup == BNA_HARD_CLEANUP) {
+                       bna_bfi_mcast_filter_req(rxf, BNA_STATUS_T_ENABLED);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static int
+bna_rxf_promisc_enable(struct bna_rxf *rxf)
+{
+       struct bna *bna = rxf->rx->bna;
+       int ret = 0;
+
+       if (is_promisc_enable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask) ||
+               (rxf->rxmode_active & BNA_RXMODE_PROMISC)) {
+               /* Do nothing if pending enable or already enabled */
+       } else if (is_promisc_disable(rxf->rxmode_pending,
+                                       rxf->rxmode_pending_bitmask)) {
+               /* Turn off pending disable command */
+               promisc_inactive(rxf->rxmode_pending,
+                       rxf->rxmode_pending_bitmask);
+       } else {
+               /* Schedule enable */
+               promisc_enable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               bna->promisc_rid = rxf->rx->rid;
+               ret = 1;
+       }
+
+       return ret;
+}
+
+static int
+bna_rxf_promisc_disable(struct bna_rxf *rxf)
+{
+       struct bna *bna = rxf->rx->bna;
+       int ret = 0;
+
+       if (is_promisc_disable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask) ||
+               (!(rxf->rxmode_active & BNA_RXMODE_PROMISC))) {
+               /* Do nothing if pending disable or already disabled */
+       } else if (is_promisc_enable(rxf->rxmode_pending,
+                                       rxf->rxmode_pending_bitmask)) {
+               /* Turn off pending enable command */
+               promisc_inactive(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               bna->promisc_rid = BFI_INVALID_RID;
+       } else if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
+               /* Schedule disable */
+               promisc_disable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               ret = 1;
+       }
+
+       return ret;
+}
+
+static int
+bna_rxf_allmulti_enable(struct bna_rxf *rxf)
+{
+       int ret = 0;
+
+       if (is_allmulti_enable(rxf->rxmode_pending,
+                       rxf->rxmode_pending_bitmask) ||
+                       (rxf->rxmode_active & BNA_RXMODE_ALLMULTI)) {
+               /* Do nothing if pending enable or already enabled */
+       } else if (is_allmulti_disable(rxf->rxmode_pending,
+                                       rxf->rxmode_pending_bitmask)) {
+               /* Turn off pending disable command */
+               allmulti_inactive(rxf->rxmode_pending,
+                       rxf->rxmode_pending_bitmask);
+       } else {
+               /* Schedule enable */
+               allmulti_enable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               ret = 1;
+       }
+
+       return ret;
+}
+
+static int
+bna_rxf_allmulti_disable(struct bna_rxf *rxf)
+{
+       int ret = 0;
+
+       if (is_allmulti_disable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask) ||
+               (!(rxf->rxmode_active & BNA_RXMODE_ALLMULTI))) {
+               /* Do nothing if pending disable or already disabled */
+       } else if (is_allmulti_enable(rxf->rxmode_pending,
+                                       rxf->rxmode_pending_bitmask)) {
+               /* Turn off pending enable command */
+               allmulti_inactive(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+       } else if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
+               /* Schedule disable */
+               allmulti_disable(rxf->rxmode_pending,
+                               rxf->rxmode_pending_bitmask);
+               ret = 1;
+       }
+
+       return ret;
+}
+
+static int
+bna_rxf_vlan_strip_cfg_apply(struct bna_rxf *rxf)
+{
+       if (rxf->vlan_strip_pending) {
+                       rxf->vlan_strip_pending = false;
+                       bna_bfi_vlan_strip_enable(rxf);
+                       return 1;
+       }
+
+       return 0;
+}
+
+/**
+ * RX
+ */
+
+#define        BNA_GET_RXQS(qcfg)      (((qcfg)->rxp_type == BNA_RXP_SINGLE) ? \
+       (qcfg)->num_paths : ((qcfg)->num_paths * 2))
+
+#define        SIZE_TO_PAGES(size)     (((size) >> PAGE_SHIFT) + ((((size) &\
+       (PAGE_SIZE - 1)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
+
+#define        call_rx_stop_cbfn(rx)                                           \
+do {                                                               \
+       if ((rx)->stop_cbfn) {                                          \
+               void (*cbfn)(void *, struct bna_rx *);    \
+               void *cbarg;                                        \
+               cbfn = (rx)->stop_cbfn;                          \
+               cbarg = (rx)->stop_cbarg;                              \
+               (rx)->stop_cbfn = NULL;                                 \
+               (rx)->stop_cbarg = NULL;                                \
+               cbfn(cbarg, rx);                                        \
+       }                                                              \
+} while (0)
+
+#define bfi_enet_datapath_q_init(bfi_q, bna_qpt)                       \
+do {                                                                   \
+       struct bna_dma_addr cur_q_addr =                                \
+               *((struct bna_dma_addr *)((bna_qpt)->kv_qpt_ptr));      \
+       (bfi_q)->pg_tbl.a32.addr_lo = (bna_qpt)->hw_qpt_ptr.lsb;        \
+       (bfi_q)->pg_tbl.a32.addr_hi = (bna_qpt)->hw_qpt_ptr.msb;        \
+       (bfi_q)->first_entry.a32.addr_lo = cur_q_addr.lsb;              \
+       (bfi_q)->first_entry.a32.addr_hi = cur_q_addr.msb;              \
+       (bfi_q)->pages = htons((u16)(bna_qpt)->page_count);     \
+       (bfi_q)->page_sz = htons((u16)(bna_qpt)->page_size);\
+} while (0)
+
+static void bna_bfi_rx_enet_start(struct bna_rx *rx);
+static void bna_rx_enet_stop(struct bna_rx *rx);
+static void bna_rx_mod_cb_rx_stopped(void *arg, struct bna_rx *rx);
+
+bfa_fsm_state_decl(bna_rx, stopped,
+       struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, start_wait,
+       struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, rxf_start_wait,
+       struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, started,
+       struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, rxf_stop_wait,
+       struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, stop_wait,
+       struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, cleanup_wait,
+       struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, failed,
+       struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, quiesce_wait,
+       struct bna_rx, enum bna_rx_event);
+
+static void bna_rx_sm_stopped_entry(struct bna_rx *rx)
+{
+       call_rx_stop_cbfn(rx);
+}
+
+static void bna_rx_sm_stopped(struct bna_rx *rx,
+                               enum bna_rx_event event)
+{
+       switch (event) {
+       case RX_E_START:
+               bfa_fsm_set_state(rx, bna_rx_sm_start_wait);
+               break;
+
+       case RX_E_STOP:
+               call_rx_stop_cbfn(rx);
+               break;
+
+       case RX_E_FAIL:
+               /* no-op */
+               break;
+
+       default:
+               bfa_sm_fault(event);
+               break;
+       }
+}
+
+static void bna_rx_sm_start_wait_entry(struct bna_rx *rx)
+{
+       bna_bfi_rx_enet_start(rx);
+}
+
+void
+bna_rx_sm_stop_wait_entry(struct bna_rx *rx)
+{
+}
+
+static void
+bna_rx_sm_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
+{
+       switch (event) {
+       case RX_E_FAIL:
+       case RX_E_STOPPED:
+               bfa_fsm_set_state(rx, bna_rx_sm_cleanup_wait);
+               rx->rx_cleanup_cbfn(rx->bna->bnad, rx);
+               break;
+
+       case RX_E_STARTED:
+               bna_rx_enet_stop(rx);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+               break;
+       }
+}
+
+static void bna_rx_sm_start_wait(struct bna_rx *rx,
+                               enum bna_rx_event event)
+{
+       switch (event) {
+       case RX_E_STOP:
+               bfa_fsm_set_state(rx, bna_rx_sm_stop_wait);
+               break;
+
+       case RX_E_FAIL:
+               bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+               break;
+
+       case RX_E_STARTED:
+               bfa_fsm_set_state(rx, bna_rx_sm_rxf_start_wait);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+               break;
+       }
+}
+
+static void bna_rx_sm_rxf_start_wait_entry(struct bna_rx *rx)
+{
+       rx->rx_post_cbfn(rx->bna->bnad, rx);
+       bna_rxf_start(&rx->rxf);
+}
+
+void
+bna_rx_sm_rxf_stop_wait_entry(struct bna_rx *rx)
+{
+}
+
+static void
+bna_rx_sm_rxf_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
+{
+       switch (event) {
+       case RX_E_FAIL:
+               bfa_fsm_set_state(rx, bna_rx_sm_cleanup_wait);
+               bna_rxf_fail(&rx->rxf);
+               rx->rx_cleanup_cbfn(rx->bna->bnad, rx);
+               break;
+
+       case RX_E_RXF_STARTED:
+               bna_rxf_stop(&rx->rxf);
+               break;
+
+       case RX_E_RXF_STOPPED:
+               bfa_fsm_set_state(rx, bna_rx_sm_stop_wait);
+               bna_rx_enet_stop(rx);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+               break;
+       }
+
+}
+
+void
+bna_rx_sm_started_entry(struct bna_rx *rx)
+{
+       struct bna_rxp *rxp;
+       struct list_head *qe_rxp;
+       int is_regular = (rx->type == BNA_RX_T_REGULAR);
+
+       /* Start IB */
+       list_for_each(qe_rxp, &rx->rxp_q) {
+               rxp = (struct bna_rxp *)qe_rxp;
+               bna_ib_start(rx->bna, &rxp->cq.ib, is_regular);
+       }
+
+       bna_ethport_cb_rx_started(&rx->bna->ethport);
+}
+
+static void
+bna_rx_sm_started(struct bna_rx *rx, enum bna_rx_event event)
+{
+       switch (event) {
+       case RX_E_STOP:
+               bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
+               bna_ethport_cb_rx_stopped(&rx->bna->ethport);
+               bna_rxf_stop(&rx->rxf);
+               break;
+
+       case RX_E_FAIL:
+               bfa_fsm_set_state(rx, bna_rx_sm_failed);
+               bna_ethport_cb_rx_stopped(&rx->bna->ethport);
+               bna_rxf_fail(&rx->rxf);
+               rx->rx_cleanup_cbfn(rx->bna->bnad, rx);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+               break;
+       }
+}
+
+static void bna_rx_sm_rxf_start_wait(struct bna_rx *rx,
+                               enum bna_rx_event event)
+{
+       switch (event) {
+       case RX_E_STOP:
+               bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
+               break;
+
+       case RX_E_FAIL:
+               bfa_fsm_set_state(rx, bna_rx_sm_failed);
+               bna_rxf_fail(&rx->rxf);
+               rx->rx_cleanup_cbfn(rx->bna->bnad, rx);
+               break;
+
+       case RX_E_RXF_STARTED:
+               bfa_fsm_set_state(rx, bna_rx_sm_started);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+               break;
+       }
+}
+
+void
+bna_rx_sm_cleanup_wait_entry(struct bna_rx *rx)
+{
+}
+
+void
+bna_rx_sm_cleanup_wait(struct bna_rx *rx, enum bna_rx_event event)
+{
+       switch (event) {
+       case RX_E_FAIL:
+       case RX_E_RXF_STOPPED:
+               /* No-op */
+               break;
+
+       case RX_E_CLEANUP_DONE:
+               bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+               break;
+       }
+}
+
+static void
+bna_rx_sm_failed_entry(struct bna_rx *rx)
+{
+}
+
+static void
+bna_rx_sm_failed(struct bna_rx *rx, enum bna_rx_event event)
+{
+       switch (event) {
+       case RX_E_START:
+               bfa_fsm_set_state(rx, bna_rx_sm_quiesce_wait);
+               break;
+
+       case RX_E_STOP:
+               bfa_fsm_set_state(rx, bna_rx_sm_cleanup_wait);
+               break;
+
+       case RX_E_FAIL:
+       case RX_E_RXF_STARTED:
+       case RX_E_RXF_STOPPED:
+               /* No-op */
+               break;
+
+       case RX_E_CLEANUP_DONE:
+               bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+               break;
+}      }
+
+static void
+bna_rx_sm_quiesce_wait_entry(struct bna_rx *rx)
+{
+}
+
+static void
+bna_rx_sm_quiesce_wait(struct bna_rx *rx, enum bna_rx_event event)
+{
+       switch (event) {
+       case RX_E_STOP:
+               bfa_fsm_set_state(rx, bna_rx_sm_cleanup_wait);
+               break;
+
+       case RX_E_FAIL:
+               bfa_fsm_set_state(rx, bna_rx_sm_failed);
+               break;
+
+       case RX_E_CLEANUP_DONE:
+               bfa_fsm_set_state(rx, bna_rx_sm_start_wait);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+               break;
+       }
+}
+
+static void
+bna_bfi_rx_enet_start(struct bna_rx *rx)
+{
+       struct bfi_enet_rx_cfg_req *cfg_req = &rx->bfi_enet_cmd.cfg_req;
+       struct bna_rxp *rxp = NULL;
+       struct bna_rxq *q0 = NULL, *q1 = NULL;
+       struct list_head *rxp_qe;
+       int i;
+
+       bfi_msgq_mhdr_set(cfg_req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_RX_CFG_SET_REQ, 0, rx->rid);
+       cfg_req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_rx_cfg_req)));
+
+       cfg_req->num_queue_sets = rx->num_paths;
+       for (i = 0, rxp_qe = bfa_q_first(&rx->rxp_q);
+               i < rx->num_paths;
+               i++, rxp_qe = bfa_q_next(rxp_qe)) {
+               rxp = (struct bna_rxp *)rxp_qe;
+
+               GET_RXQS(rxp, q0, q1);
+               switch (rxp->type) {
+               case BNA_RXP_SLR:
+               case BNA_RXP_HDS:
+                       /* Small RxQ */
+                       bfi_enet_datapath_q_init(&cfg_req->q_cfg[i].qs.q,
+                                               &q1->qpt);
+                       cfg_req->q_cfg[i].qs.rx_buffer_size =
+                               htons((u16)q1->buffer_size);
+                       /* Fall through */
+
+               case BNA_RXP_SINGLE:
+                       /* Large/Single RxQ */
+                       bfi_enet_datapath_q_init(&cfg_req->q_cfg[i].ql.q,
+                                               &q0->qpt);
+                       q0->buffer_size =
+                               bna_enet_mtu_get(&rx->bna->enet);
+                       cfg_req->q_cfg[i].ql.rx_buffer_size =
+                               htons((u16)q0->buffer_size);
+                       break;
+
+               default:
+                       BUG_ON(1);
+               }
+
+               bfi_enet_datapath_q_init(&cfg_req->q_cfg[i].cq.q,
+                                       &rxp->cq.qpt);
+
+               cfg_req->q_cfg[i].ib.index_addr.a32.addr_lo =
+                       rxp->cq.ib.ib_seg_host_addr.lsb;
+               cfg_req->q_cfg[i].ib.index_addr.a32.addr_hi =
+                       rxp->cq.ib.ib_seg_host_addr.msb;
+               cfg_req->q_cfg[i].ib.intr.msix_index =
+                       htons((u16)rxp->cq.ib.intr_vector);
+       }
+
+       cfg_req->ib_cfg.int_pkt_dma = BNA_STATUS_T_DISABLED;
+       cfg_req->ib_cfg.int_enabled = BNA_STATUS_T_ENABLED;
+       cfg_req->ib_cfg.int_pkt_enabled = BNA_STATUS_T_DISABLED;
+       cfg_req->ib_cfg.continuous_coalescing = BNA_STATUS_T_DISABLED;
+       cfg_req->ib_cfg.msix = (rxp->cq.ib.intr_type == BNA_INTR_T_MSIX)
+                               ? BNA_STATUS_T_ENABLED :
+                               BNA_STATUS_T_DISABLED;
+       cfg_req->ib_cfg.coalescing_timeout =
+                       htonl((u32)rxp->cq.ib.coalescing_timeo);
+       cfg_req->ib_cfg.inter_pkt_timeout =
+                       htonl((u32)rxp->cq.ib.interpkt_timeo);
+       cfg_req->ib_cfg.inter_pkt_count = (u8)rxp->cq.ib.interpkt_count;
+
+       switch (rxp->type) {
+       case BNA_RXP_SLR:
+               cfg_req->rx_cfg.rxq_type = BFI_ENET_RXQ_LARGE_SMALL;
+               break;
+
+       case BNA_RXP_HDS:
+               cfg_req->rx_cfg.rxq_type = BFI_ENET_RXQ_HDS;
+               cfg_req->rx_cfg.hds.type = rx->hds_cfg.hdr_type;
+               cfg_req->rx_cfg.hds.force_offset = rx->hds_cfg.forced_offset;
+               cfg_req->rx_cfg.hds.max_header_size = rx->hds_cfg.forced_offset;
+               break;
+
+       case BNA_RXP_SINGLE:
+               cfg_req->rx_cfg.rxq_type = BFI_ENET_RXQ_SINGLE;
+               break;
+
+       default:
+               BUG_ON(1);
+       }
+       cfg_req->rx_cfg.strip_vlan = rx->rxf.vlan_strip_status;
+
+       bfa_msgq_cmd_set(&rx->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_rx_cfg_req), &cfg_req->mh);
+       bfa_msgq_cmd_post(&rx->bna->msgq, &rx->msgq_cmd);
+}
+
+static void
+bna_bfi_rx_enet_stop(struct bna_rx *rx)
+{
+       struct bfi_enet_req *req = &rx->bfi_enet_cmd.req;
+
+       bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_RX_CFG_CLR_REQ, 0, rx->rid);
+       req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_req)));
+       bfa_msgq_cmd_set(&rx->msgq_cmd, NULL, NULL, sizeof(struct bfi_enet_req),
+               &req->mh);
+       bfa_msgq_cmd_post(&rx->bna->msgq, &rx->msgq_cmd);
+}
+
+static void
+bna_rx_enet_stop(struct bna_rx *rx)
+{
+       struct bna_rxp *rxp;
+       struct list_head                 *qe_rxp;
+
+       /* Stop IB */
+       list_for_each(qe_rxp, &rx->rxp_q) {
+               rxp = (struct bna_rxp *)qe_rxp;
+               bna_ib_stop(rx->bna, &rxp->cq.ib);
+       }
+
+       bna_bfi_rx_enet_stop(rx);
+}
+
+static int
+bna_rx_res_check(struct bna_rx_mod *rx_mod, struct bna_rx_config *rx_cfg)
+{
+       if ((rx_mod->rx_free_count == 0) ||
+               (rx_mod->rxp_free_count == 0) ||
+               (rx_mod->rxq_free_count == 0))
+               return 0;
+
+       if (rx_cfg->rxp_type == BNA_RXP_SINGLE) {
+               if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
+                       (rx_mod->rxq_free_count < rx_cfg->num_paths))
+                               return 0;
+       } else {
+               if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
+                       (rx_mod->rxq_free_count < (2 * rx_cfg->num_paths)))
+                       return 0;
+       }
+
+       return 1;
+}
+
+static struct bna_rxq *
+bna_rxq_get(struct bna_rx_mod *rx_mod)
+{
+       struct bna_rxq *rxq = NULL;
+       struct list_head        *qe = NULL;
+
+       bfa_q_deq(&rx_mod->rxq_free_q, &qe);
+       rx_mod->rxq_free_count--;
+       rxq = (struct bna_rxq *)qe;
+       bfa_q_qe_init(&rxq->qe);
+
+       return rxq;
+}
+
+static void
+bna_rxq_put(struct bna_rx_mod *rx_mod, struct bna_rxq *rxq)
+{
+       bfa_q_qe_init(&rxq->qe);
+       list_add_tail(&rxq->qe, &rx_mod->rxq_free_q);
+       rx_mod->rxq_free_count++;
+}
+
+static struct bna_rxp *
+bna_rxp_get(struct bna_rx_mod *rx_mod)
+{
+       struct list_head        *qe = NULL;
+       struct bna_rxp *rxp = NULL;
+
+       bfa_q_deq(&rx_mod->rxp_free_q, &qe);
+       rx_mod->rxp_free_count--;
+       rxp = (struct bna_rxp *)qe;
+       bfa_q_qe_init(&rxp->qe);
+
+       return rxp;
+}
+
+static void
+bna_rxp_put(struct bna_rx_mod *rx_mod, struct bna_rxp *rxp)
+{
+       bfa_q_qe_init(&rxp->qe);
+       list_add_tail(&rxp->qe, &rx_mod->rxp_free_q);
+       rx_mod->rxp_free_count++;
+}
+
+static struct bna_rx *
+bna_rx_get(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
+{
+       struct list_head        *qe = NULL;
+       struct bna_rx *rx = NULL;
+
+       if (type == BNA_RX_T_REGULAR) {
+               bfa_q_deq(&rx_mod->rx_free_q, &qe);
+       } else
+               bfa_q_deq_tail(&rx_mod->rx_free_q, &qe);
+
+       rx_mod->rx_free_count--;
+       rx = (struct bna_rx *)qe;
+       bfa_q_qe_init(&rx->qe);
+       list_add_tail(&rx->qe, &rx_mod->rx_active_q);
+       rx->type = type;
+
+       return rx;
+}
+
+static void
+bna_rx_put(struct bna_rx_mod *rx_mod, struct bna_rx *rx)
+{
+       struct list_head *prev_qe = NULL;
+       struct list_head *qe;
+
+       bfa_q_qe_init(&rx->qe);
+
+       list_for_each(qe, &rx_mod->rx_free_q) {
+               if (((struct bna_rx *)qe)->rid < rx->rid)
+                       prev_qe = qe;
+               else
+                       break;
+       }
+
+       if (prev_qe == NULL) {
+               /* This is the first entry */
+               bfa_q_enq_head(&rx_mod->rx_free_q, &rx->qe);
+       } else if (bfa_q_next(prev_qe) == &rx_mod->rx_free_q) {
+               /* This is the last entry */
+               list_add_tail(&rx->qe, &rx_mod->rx_free_q);
+       } else {
+               /* Somewhere in the middle */
+               bfa_q_next(&rx->qe) = bfa_q_next(prev_qe);
+               bfa_q_prev(&rx->qe) = prev_qe;
+               bfa_q_next(prev_qe) = &rx->qe;
+               bfa_q_prev(bfa_q_next(&rx->qe)) = &rx->qe;
+       }
+
+       rx_mod->rx_free_count++;
+}
+
+static void
+bna_rxp_add_rxqs(struct bna_rxp *rxp, struct bna_rxq *q0,
+               struct bna_rxq *q1)
+{
+       switch (rxp->type) {
+       case BNA_RXP_SINGLE:
+               rxp->rxq.single.only = q0;
+               rxp->rxq.single.reserved = NULL;
+               break;
+       case BNA_RXP_SLR:
+               rxp->rxq.slr.large = q0;
+               rxp->rxq.slr.small = q1;
+               break;
+       case BNA_RXP_HDS:
+               rxp->rxq.hds.data = q0;
+               rxp->rxq.hds.hdr = q1;
+               break;
+       default:
+               break;
+       }
+}
+
+static void
+bna_rxq_qpt_setup(struct bna_rxq *rxq,
+               struct bna_rxp *rxp,
+               u32 page_count,
+               u32 page_size,
+               struct bna_mem_descr *qpt_mem,
+               struct bna_mem_descr *swqpt_mem,
+               struct bna_mem_descr *page_mem)
+{
+       int     i;
+
+       rxq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
+       rxq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
+       rxq->qpt.kv_qpt_ptr = qpt_mem->kva;
+       rxq->qpt.page_count = page_count;
+       rxq->qpt.page_size = page_size;
+
+       rxq->rcb->sw_qpt = (void **) swqpt_mem->kva;
+
+       for (i = 0; i < rxq->qpt.page_count; i++) {
+               rxq->rcb->sw_qpt[i] = page_mem[i].kva;
+               ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].lsb =
+                       page_mem[i].dma.lsb;
+               ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].msb =
+                       page_mem[i].dma.msb;
+       }
+}
+
+static void
+bna_rxp_cqpt_setup(struct bna_rxp *rxp,
+               u32 page_count,
+               u32 page_size,
+               struct bna_mem_descr *qpt_mem,
+               struct bna_mem_descr *swqpt_mem,
+               struct bna_mem_descr *page_mem)
+{
+       int     i;
+
+       rxp->cq.qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
+       rxp->cq.qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
+       rxp->cq.qpt.kv_qpt_ptr = qpt_mem->kva;
+       rxp->cq.qpt.page_count = page_count;
+       rxp->cq.qpt.page_size = page_size;
+
+       rxp->cq.ccb->sw_qpt = (void **) swqpt_mem->kva;
+
+       for (i = 0; i < rxp->cq.qpt.page_count; i++) {
+               rxp->cq.ccb->sw_qpt[i] = page_mem[i].kva;
+
+               ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].lsb =
+                       page_mem[i].dma.lsb;
+               ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].msb =
+                       page_mem[i].dma.msb;
+       }
+}
+
+static void
+bna_rx_mod_cb_rx_stopped(void *arg, struct bna_rx *rx)
+{
+       struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
+
+       bfa_wc_down(&rx_mod->rx_stop_wc);
+}
+
+static void
+bna_rx_mod_cb_rx_stopped_all(void *arg)
+{
+       struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
+
+       if (rx_mod->stop_cbfn)
+               rx_mod->stop_cbfn(&rx_mod->bna->enet);
+       rx_mod->stop_cbfn = NULL;
+}
+
+static void
+bna_rx_start(struct bna_rx *rx)
+{
+       rx->rx_flags |= BNA_RX_F_ENET_STARTED;
+       if (rx->rx_flags & BNA_RX_F_ENABLED)
+               bfa_fsm_send_event(rx, RX_E_START);
+}
+
+static void
+bna_rx_stop(struct bna_rx *rx)
+{
+       rx->rx_flags &= ~BNA_RX_F_ENET_STARTED;
+       if (rx->fsm == (bfa_fsm_t) bna_rx_sm_stopped)
+               bna_rx_mod_cb_rx_stopped(&rx->bna->rx_mod, rx);
+       else {
+               rx->stop_cbfn = bna_rx_mod_cb_rx_stopped;
+               rx->stop_cbarg = &rx->bna->rx_mod;
+               bfa_fsm_send_event(rx, RX_E_STOP);
+       }
+}
+
+static void
+bna_rx_fail(struct bna_rx *rx)
+{
+       /* Indicate Enet is not enabled, and failed */
+       rx->rx_flags &= ~BNA_RX_F_ENET_STARTED;
+       bfa_fsm_send_event(rx, RX_E_FAIL);
+}
+
+void
+bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
+{
+       struct bna_rx *rx;
+       struct list_head *qe;
+
+       rx_mod->flags |= BNA_RX_MOD_F_ENET_STARTED;
+       if (type == BNA_RX_T_LOOPBACK)
+               rx_mod->flags |= BNA_RX_MOD_F_ENET_LOOPBACK;
+
+       list_for_each(qe, &rx_mod->rx_active_q) {
+               rx = (struct bna_rx *)qe;
+               if (rx->type == type)
+                       bna_rx_start(rx);
+       }
+}
+
+void
+bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
+{
+       struct bna_rx *rx;
+       struct list_head *qe;
+
+       rx_mod->flags &= ~BNA_RX_MOD_F_ENET_STARTED;
+       rx_mod->flags &= ~BNA_RX_MOD_F_ENET_LOOPBACK;
+
+       rx_mod->stop_cbfn = bna_enet_cb_rx_stopped;
+
+       bfa_wc_init(&rx_mod->rx_stop_wc, bna_rx_mod_cb_rx_stopped_all, rx_mod);
+
+       list_for_each(qe, &rx_mod->rx_active_q) {
+               rx = (struct bna_rx *)qe;
+               if (rx->type == type) {
+                       bfa_wc_up(&rx_mod->rx_stop_wc);
+                       bna_rx_stop(rx);
+               }
+       }
+
+       bfa_wc_wait(&rx_mod->rx_stop_wc);
+}
+
+void
+bna_rx_mod_fail(struct bna_rx_mod *rx_mod)
+{
+       struct bna_rx *rx;
+       struct list_head *qe;
+
+       rx_mod->flags &= ~BNA_RX_MOD_F_ENET_STARTED;
+       rx_mod->flags &= ~BNA_RX_MOD_F_ENET_LOOPBACK;
+
+       list_for_each(qe, &rx_mod->rx_active_q) {
+               rx = (struct bna_rx *)qe;
+               bna_rx_fail(rx);
+       }
+}
+
+void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
+                       struct bna_res_info *res_info)
+{
+       int     index;
+       struct bna_rx *rx_ptr;
+       struct bna_rxp *rxp_ptr;
+       struct bna_rxq *rxq_ptr;
+
+       rx_mod->bna = bna;
+       rx_mod->flags = 0;
+
+       rx_mod->rx = (struct bna_rx *)
+               res_info[BNA_MOD_RES_MEM_T_RX_ARRAY].res_u.mem_info.mdl[0].kva;
+       rx_mod->rxp = (struct bna_rxp *)
+               res_info[BNA_MOD_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mdl[0].kva;
+       rx_mod->rxq = (struct bna_rxq *)
+               res_info[BNA_MOD_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mdl[0].kva;
+
+       /* Initialize the queues */
+       INIT_LIST_HEAD(&rx_mod->rx_free_q);
+       rx_mod->rx_free_count = 0;
+       INIT_LIST_HEAD(&rx_mod->rxq_free_q);
+       rx_mod->rxq_free_count = 0;
+       INIT_LIST_HEAD(&rx_mod->rxp_free_q);
+       rx_mod->rxp_free_count = 0;
+       INIT_LIST_HEAD(&rx_mod->rx_active_q);
+
+       /* Build RX queues */
+       for (index = 0; index < bna->ioceth.attr.num_rxp; index++) {
+               rx_ptr = &rx_mod->rx[index];
+
+               bfa_q_qe_init(&rx_ptr->qe);
+               INIT_LIST_HEAD(&rx_ptr->rxp_q);
+               rx_ptr->bna = NULL;
+               rx_ptr->rid = index;
+               rx_ptr->stop_cbfn = NULL;
+               rx_ptr->stop_cbarg = NULL;
+
+               list_add_tail(&rx_ptr->qe, &rx_mod->rx_free_q);
+               rx_mod->rx_free_count++;
+       }
+
+       /* build RX-path queue */
+       for (index = 0; index < bna->ioceth.attr.num_rxp; index++) {
+               rxp_ptr = &rx_mod->rxp[index];
+               bfa_q_qe_init(&rxp_ptr->qe);
+               list_add_tail(&rxp_ptr->qe, &rx_mod->rxp_free_q);
+               rx_mod->rxp_free_count++;
+       }
+
+       /* build RXQ queue */
+       for (index = 0; index < (bna->ioceth.attr.num_rxp * 2); index++) {
+               rxq_ptr = &rx_mod->rxq[index];
+               bfa_q_qe_init(&rxq_ptr->qe);
+               list_add_tail(&rxq_ptr->qe, &rx_mod->rxq_free_q);
+               rx_mod->rxq_free_count++;
+       }
+}
+
+void
+bna_rx_mod_uninit(struct bna_rx_mod *rx_mod)
+{
+       struct list_head                *qe;
+       int i;
+
+       i = 0;
+       list_for_each(qe, &rx_mod->rx_free_q)
+               i++;
+
+       i = 0;
+       list_for_each(qe, &rx_mod->rxp_free_q)
+               i++;
+
+       i = 0;
+       list_for_each(qe, &rx_mod->rxq_free_q)
+               i++;
+
+       rx_mod->bna = NULL;
+}
+
+void
+bna_bfi_rx_enet_start_rsp(struct bna_rx *rx, struct bfi_msgq_mhdr *msghdr)
+{
+       struct bfi_enet_rx_cfg_rsp *cfg_rsp = &rx->bfi_enet_cmd.cfg_rsp;
+       struct bna_rxp *rxp = NULL;
+       struct bna_rxq *q0 = NULL, *q1 = NULL;
+       struct list_head *rxp_qe;
+       int i;
+
+       bfa_msgq_rsp_copy(&rx->bna->msgq, (u8 *)cfg_rsp,
+               sizeof(struct bfi_enet_rx_cfg_rsp));
+
+       rx->hw_id = cfg_rsp->hw_id;
+
+       for (i = 0, rxp_qe = bfa_q_first(&rx->rxp_q);
+               i < rx->num_paths;
+               i++, rxp_qe = bfa_q_next(rxp_qe)) {
+               rxp = (struct bna_rxp *)rxp_qe;
+               GET_RXQS(rxp, q0, q1);
+
+               /* Setup doorbells */
+               rxp->cq.ccb->i_dbell->doorbell_addr =
+                       rx->bna->pcidev.pci_bar_kva
+                       + ntohl(cfg_rsp->q_handles[i].i_dbell);
+               rxp->hw_id = cfg_rsp->q_handles[i].hw_cqid;
+               q0->rcb->q_dbell =
+                       rx->bna->pcidev.pci_bar_kva
+                       + ntohl(cfg_rsp->q_handles[i].ql_dbell);
+               q0->hw_id = cfg_rsp->q_handles[i].hw_lqid;
+               if (q1) {
+                       q1->rcb->q_dbell =
+                       rx->bna->pcidev.pci_bar_kva
+                       + ntohl(cfg_rsp->q_handles[i].qs_dbell);
+                       q1->hw_id = cfg_rsp->q_handles[i].hw_sqid;
+               }
+
+               /* Initialize producer/consumer indexes */
+               (*rxp->cq.ccb->hw_producer_index) = 0;
+               rxp->cq.ccb->producer_index = 0;
+               q0->rcb->producer_index = q0->rcb->consumer_index = 0;
+               if (q1)
+                       q1->rcb->producer_index = q1->rcb->consumer_index = 0;
+       }
+
+       bfa_fsm_send_event(rx, RX_E_STARTED);
+}
+
+void
+bna_bfi_rx_enet_stop_rsp(struct bna_rx *rx, struct bfi_msgq_mhdr *msghdr)
+{
+       bfa_fsm_send_event(rx, RX_E_STOPPED);
+}
+
+void
+bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info)
+{
+       u32 cq_size, hq_size, dq_size;
+       u32 cpage_count, hpage_count, dpage_count;
+       struct bna_mem_info *mem_info;
+       u32 cq_depth;
+       u32 hq_depth;
+       u32 dq_depth;
+
+       dq_depth = q_cfg->q_depth;
+       hq_depth = ((q_cfg->rxp_type == BNA_RXP_SINGLE) ? 0 : q_cfg->q_depth);
+       cq_depth = dq_depth + hq_depth;
+
+       BNA_TO_POWER_OF_2_HIGH(cq_depth);
+       cq_size = cq_depth * BFI_CQ_WI_SIZE;
+       cq_size = ALIGN(cq_size, PAGE_SIZE);
+       cpage_count = SIZE_TO_PAGES(cq_size);
+
+       BNA_TO_POWER_OF_2_HIGH(dq_depth);
+       dq_size = dq_depth * BFI_RXQ_WI_SIZE;
+       dq_size = ALIGN(dq_size, PAGE_SIZE);
+       dpage_count = SIZE_TO_PAGES(dq_size);
+
+       if (BNA_RXP_SINGLE != q_cfg->rxp_type) {
+               BNA_TO_POWER_OF_2_HIGH(hq_depth);
+               hq_size = hq_depth * BFI_RXQ_WI_SIZE;
+               hq_size = ALIGN(hq_size, PAGE_SIZE);
+               hpage_count = SIZE_TO_PAGES(hq_size);
+       } else
+               hpage_count = 0;
+
+       res_info[BNA_RX_RES_MEM_T_CCB].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_KVA;
+       mem_info->len = sizeof(struct bna_ccb);
+       mem_info->num = q_cfg->num_paths;
+
+       res_info[BNA_RX_RES_MEM_T_RCB].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_KVA;
+       mem_info->len = sizeof(struct bna_rcb);
+       mem_info->num = BNA_GET_RXQS(q_cfg);
+
+       res_info[BNA_RX_RES_MEM_T_CQPT].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_DMA;
+       mem_info->len = cpage_count * sizeof(struct bna_dma_addr);
+       mem_info->num = q_cfg->num_paths;
+
+       res_info[BNA_RX_RES_MEM_T_CSWQPT].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_KVA;
+       mem_info->len = cpage_count * sizeof(void *);
+       mem_info->num = q_cfg->num_paths;
+
+       res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_DMA;
+       mem_info->len = PAGE_SIZE;
+       mem_info->num = cpage_count * q_cfg->num_paths;
+
+       res_info[BNA_RX_RES_MEM_T_DQPT].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_DMA;
+       mem_info->len = dpage_count * sizeof(struct bna_dma_addr);
+       mem_info->num = q_cfg->num_paths;
+
+       res_info[BNA_RX_RES_MEM_T_DSWQPT].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_KVA;
+       mem_info->len = dpage_count * sizeof(void *);
+       mem_info->num = q_cfg->num_paths;
+
+       res_info[BNA_RX_RES_MEM_T_DPAGE].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_DMA;
+       mem_info->len = PAGE_SIZE;
+       mem_info->num = dpage_count * q_cfg->num_paths;
+
+       res_info[BNA_RX_RES_MEM_T_HQPT].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_DMA;
+       mem_info->len = hpage_count * sizeof(struct bna_dma_addr);
+       mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
+
+       res_info[BNA_RX_RES_MEM_T_HSWQPT].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_KVA;
+       mem_info->len = hpage_count * sizeof(void *);
+       mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
+
+       res_info[BNA_RX_RES_MEM_T_HPAGE].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_DMA;
+       mem_info->len = (hpage_count ? PAGE_SIZE : 0);
+       mem_info->num = (hpage_count ? (hpage_count * q_cfg->num_paths) : 0);
+
+       res_info[BNA_RX_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_IBIDX].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_DMA;
+       mem_info->len = BFI_IBIDX_SIZE;
+       mem_info->num = q_cfg->num_paths;
+
+       res_info[BNA_RX_RES_MEM_T_RIT].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_RX_RES_MEM_T_RIT].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_KVA;
+       mem_info->len = BFI_ENET_RSS_RIT_MAX;
+       mem_info->num = 1;
+
+       res_info[BNA_RX_RES_T_INTR].res_type = BNA_RES_T_INTR;
+       res_info[BNA_RX_RES_T_INTR].res_u.intr_info.intr_type = BNA_INTR_T_MSIX;
+       res_info[BNA_RX_RES_T_INTR].res_u.intr_info.num = q_cfg->num_paths;
+}
+
+struct bna_rx *
+bna_rx_create(struct bna *bna, struct bnad *bnad,
+               struct bna_rx_config *rx_cfg,
+               struct bna_rx_event_cbfn *rx_cbfn,
+               struct bna_res_info *res_info,
+               void *priv)
+{
+       struct bna_rx_mod *rx_mod = &bna->rx_mod;
+       struct bna_rx *rx;
+       struct bna_rxp *rxp;
+       struct bna_rxq *q0;
+       struct bna_rxq *q1;
+       struct bna_intr_info *intr_info;
+       u32 page_count;
+       struct bna_mem_descr *ccb_mem;
+       struct bna_mem_descr *rcb_mem;
+       struct bna_mem_descr *unmapq_mem;
+       struct bna_mem_descr *cqpt_mem;
+       struct bna_mem_descr *cswqpt_mem;
+       struct bna_mem_descr *cpage_mem;
+       struct bna_mem_descr *hqpt_mem;
+       struct bna_mem_descr *dqpt_mem;
+       struct bna_mem_descr *hsqpt_mem;
+       struct bna_mem_descr *dsqpt_mem;
+       struct bna_mem_descr *hpage_mem;
+       struct bna_mem_descr *dpage_mem;
+       int i, cpage_idx = 0, dpage_idx = 0, hpage_idx = 0;
+       int dpage_count, hpage_count, rcb_idx;
+
+       if (!bna_rx_res_check(rx_mod, rx_cfg))
+               return NULL;
+
+       intr_info = &res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
+       ccb_mem = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info.mdl[0];
+       rcb_mem = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info.mdl[0];
+       unmapq_mem = &res_info[BNA_RX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[0];
+       cqpt_mem = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info.mdl[0];
+       cswqpt_mem = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info.mdl[0];
+       cpage_mem = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.mdl[0];
+       hqpt_mem = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info.mdl[0];
+       dqpt_mem = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info.mdl[0];
+       hsqpt_mem = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info.mdl[0];
+       dsqpt_mem = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info.mdl[0];
+       hpage_mem = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.mdl[0];
+       dpage_mem = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.mdl[0];
+
+       page_count = res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.num /
+                       rx_cfg->num_paths;
+
+       dpage_count = res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.num /
+                       rx_cfg->num_paths;
+
+       hpage_count = res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.num /
+                       rx_cfg->num_paths;
+
+       rx = bna_rx_get(rx_mod, rx_cfg->rx_type);
+       rx->bna = bna;
+       rx->rx_flags = 0;
+       INIT_LIST_HEAD(&rx->rxp_q);
+       rx->stop_cbfn = NULL;
+       rx->stop_cbarg = NULL;
+       rx->priv = priv;
+
+       rx->rcb_setup_cbfn = rx_cbfn->rcb_setup_cbfn;
+       rx->rcb_destroy_cbfn = rx_cbfn->rcb_destroy_cbfn;
+       rx->ccb_setup_cbfn = rx_cbfn->ccb_setup_cbfn;
+       rx->ccb_destroy_cbfn = rx_cbfn->ccb_destroy_cbfn;
+       /* Following callbacks are mandatory */
+       rx->rx_cleanup_cbfn = rx_cbfn->rx_cleanup_cbfn;
+       rx->rx_post_cbfn = rx_cbfn->rx_post_cbfn;
+
+       if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_ENET_STARTED) {
+               switch (rx->type) {
+               case BNA_RX_T_REGULAR:
+                       if (!(rx->bna->rx_mod.flags &
+                               BNA_RX_MOD_F_ENET_LOOPBACK))
+                               rx->rx_flags |= BNA_RX_F_ENET_STARTED;
+                       break;
+               case BNA_RX_T_LOOPBACK:
+                       if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_ENET_LOOPBACK)
+                               rx->rx_flags |= BNA_RX_F_ENET_STARTED;
+                       break;
+               }
+       }
+
+       rx->num_paths = rx_cfg->num_paths;
+       for (i = 0, rcb_idx = 0; i < rx->num_paths; i++) {
+               rxp = bna_rxp_get(rx_mod);
+               list_add_tail(&rxp->qe, &rx->rxp_q);
+               rxp->type = rx_cfg->rxp_type;
+               rxp->rx = rx;
+               rxp->cq.rx = rx;
+
+               q0 = bna_rxq_get(rx_mod);
+               if (BNA_RXP_SINGLE == rx_cfg->rxp_type)
+                       q1 = NULL;
+               else
+                       q1 = bna_rxq_get(rx_mod);
+
+               if (1 == intr_info->num)
+                       rxp->vector = intr_info->idl[0].vector;
+               else
+                       rxp->vector = intr_info->idl[i].vector;
+
+               /* Setup IB */
+
+               rxp->cq.ib.ib_seg_host_addr.lsb =
+               res_info[BNA_RX_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.lsb;
+               rxp->cq.ib.ib_seg_host_addr.msb =
+               res_info[BNA_RX_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.msb;
+               rxp->cq.ib.ib_seg_host_addr_kva =
+               res_info[BNA_RX_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].kva;
+               rxp->cq.ib.intr_type = intr_info->intr_type;
+               if (intr_info->intr_type == BNA_INTR_T_MSIX)
+                       rxp->cq.ib.intr_vector = rxp->vector;
+               else
+                       rxp->cq.ib.intr_vector = (1 << rxp->vector);
+               rxp->cq.ib.coalescing_timeo = rx_cfg->coalescing_timeo;
+               rxp->cq.ib.interpkt_count = BFI_RX_INTERPKT_COUNT;
+               rxp->cq.ib.interpkt_timeo = BFI_RX_INTERPKT_TIMEO;
+
+               bna_rxp_add_rxqs(rxp, q0, q1);
+
+               /* Setup large Q */
+
+               q0->rx = rx;
+               q0->rxp = rxp;
+
+               q0->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
+               q0->rcb->unmap_q = (void *)unmapq_mem[rcb_idx].kva;
+               rcb_idx++;
+               q0->rcb->q_depth = rx_cfg->q_depth;
+               q0->rcb->rxq = q0;
+               q0->rcb->bnad = bna->bnad;
+               q0->rcb->id = 0;
+               q0->rx_packets = q0->rx_bytes = 0;
+               q0->rx_packets_with_error = q0->rxbuf_alloc_failed = 0;
+
+               bna_rxq_qpt_setup(q0, rxp, dpage_count, PAGE_SIZE,
+                       &dqpt_mem[i], &dsqpt_mem[i], &dpage_mem[dpage_idx]);
+               q0->rcb->page_idx = dpage_idx;
+               q0->rcb->page_count = dpage_count;
+               dpage_idx += dpage_count;
+
+               if (rx->rcb_setup_cbfn)
+                       rx->rcb_setup_cbfn(bnad, q0->rcb);
+
+               /* Setup small Q */
+
+               if (q1) {
+                       q1->rx = rx;
+                       q1->rxp = rxp;
+
+                       q1->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
+                       q1->rcb->unmap_q = (void *)unmapq_mem[rcb_idx].kva;
+                       rcb_idx++;
+                       q1->rcb->q_depth = rx_cfg->q_depth;
+                       q1->rcb->rxq = q1;
+                       q1->rcb->bnad = bna->bnad;
+                       q1->rcb->id = 1;
+                       q1->buffer_size = (rx_cfg->rxp_type == BNA_RXP_HDS) ?
+                                       rx_cfg->hds_config.forced_offset
+                                       : rx_cfg->small_buff_size;
+                       q1->rx_packets = q1->rx_bytes = 0;
+                       q1->rx_packets_with_error = q1->rxbuf_alloc_failed = 0;
+
+                       bna_rxq_qpt_setup(q1, rxp, hpage_count, PAGE_SIZE,
+                               &hqpt_mem[i], &hsqpt_mem[i],
+                               &hpage_mem[hpage_idx]);
+                       q1->rcb->page_idx = hpage_idx;
+                       q1->rcb->page_count = hpage_count;
+                       hpage_idx += hpage_count;
+
+                       if (rx->rcb_setup_cbfn)
+                               rx->rcb_setup_cbfn(bnad, q1->rcb);
+               }
+
+               /* Setup CQ */
+
+               rxp->cq.ccb = (struct bna_ccb *) ccb_mem[i].kva;
+               rxp->cq.ccb->q_depth =  rx_cfg->q_depth +
+                                       ((rx_cfg->rxp_type == BNA_RXP_SINGLE) ?
+                                       0 : rx_cfg->q_depth);
+               rxp->cq.ccb->cq = &rxp->cq;
+               rxp->cq.ccb->rcb[0] = q0->rcb;
+               q0->rcb->ccb = rxp->cq.ccb;
+               if (q1) {
+                       rxp->cq.ccb->rcb[1] = q1->rcb;
+                       q1->rcb->ccb = rxp->cq.ccb;
+               }
+               rxp->cq.ccb->hw_producer_index =
+                       (u32 *)rxp->cq.ib.ib_seg_host_addr_kva;
+               rxp->cq.ccb->i_dbell = &rxp->cq.ib.door_bell;
+               rxp->cq.ccb->intr_type = rxp->cq.ib.intr_type;
+               rxp->cq.ccb->intr_vector = rxp->cq.ib.intr_vector;
+               rxp->cq.ccb->rx_coalescing_timeo =
+                       rxp->cq.ib.coalescing_timeo;
+               rxp->cq.ccb->pkt_rate.small_pkt_cnt = 0;
+               rxp->cq.ccb->pkt_rate.large_pkt_cnt = 0;
+               rxp->cq.ccb->bnad = bna->bnad;
+               rxp->cq.ccb->id = i;
+
+               bna_rxp_cqpt_setup(rxp, page_count, PAGE_SIZE,
+                       &cqpt_mem[i], &cswqpt_mem[i], &cpage_mem[cpage_idx]);
+               rxp->cq.ccb->page_idx = cpage_idx;
+               rxp->cq.ccb->page_count = page_count;
+               cpage_idx += page_count;
+
+               if (rx->ccb_setup_cbfn)
+                       rx->ccb_setup_cbfn(bnad, rxp->cq.ccb);
+       }
+
+       rx->hds_cfg = rx_cfg->hds_config;
+
+       bna_rxf_init(&rx->rxf, rx, rx_cfg, res_info);
+
+       bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+
+       rx_mod->rid_mask |= (1 << rx->rid);
+
+       return rx;
+}
+
+void
+bna_rx_destroy(struct bna_rx *rx)
+{
+       struct bna_rx_mod *rx_mod = &rx->bna->rx_mod;
+       struct bna_rxq *q0 = NULL;
+       struct bna_rxq *q1 = NULL;
+       struct bna_rxp *rxp;
+       struct list_head *qe;
+
+       bna_rxf_uninit(&rx->rxf);
+
+       while (!list_empty(&rx->rxp_q)) {
+               bfa_q_deq(&rx->rxp_q, &rxp);
+               GET_RXQS(rxp, q0, q1);
+               if (rx->rcb_destroy_cbfn)
+                       rx->rcb_destroy_cbfn(rx->bna->bnad, q0->rcb);
+               q0->rcb = NULL;
+               q0->rxp = NULL;
+               q0->rx = NULL;
+               bna_rxq_put(rx_mod, q0);
+
+               if (q1) {
+                       if (rx->rcb_destroy_cbfn)
+                               rx->rcb_destroy_cbfn(rx->bna->bnad, q1->rcb);
+                       q1->rcb = NULL;
+                       q1->rxp = NULL;
+                       q1->rx = NULL;
+                       bna_rxq_put(rx_mod, q1);
+               }
+               rxp->rxq.slr.large = NULL;
+               rxp->rxq.slr.small = NULL;
+
+               if (rx->ccb_destroy_cbfn)
+                       rx->ccb_destroy_cbfn(rx->bna->bnad, rxp->cq.ccb);
+               rxp->cq.ccb = NULL;
+               rxp->rx = NULL;
+               bna_rxp_put(rx_mod, rxp);
+       }
+
+       list_for_each(qe, &rx_mod->rx_active_q) {
+               if (qe == &rx->qe) {
+                       list_del(&rx->qe);
+                       bfa_q_qe_init(&rx->qe);
+                       break;
+               }
+       }
+
+       rx_mod->rid_mask &= ~(1 << rx->rid);
+
+       rx->bna = NULL;
+       rx->priv = NULL;
+       bna_rx_put(rx_mod, rx);
+}
+
+void
+bna_rx_enable(struct bna_rx *rx)
+{
+       if (rx->fsm != (bfa_sm_t)bna_rx_sm_stopped)
+               return;
+
+       rx->rx_flags |= BNA_RX_F_ENABLED;
+       if (rx->rx_flags & BNA_RX_F_ENET_STARTED)
+               bfa_fsm_send_event(rx, RX_E_START);
+}
+
+void
+bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type,
+               void (*cbfn)(void *, struct bna_rx *))
+{
+       if (type == BNA_SOFT_CLEANUP) {
+               /* h/w should not be accessed. Treat we're stopped */
+               (*cbfn)(rx->bna->bnad, rx);
+       } else {
+               rx->stop_cbfn = cbfn;
+               rx->stop_cbarg = rx->bna->bnad;
+
+               rx->rx_flags &= ~BNA_RX_F_ENABLED;
+
+               bfa_fsm_send_event(rx, RX_E_STOP);
+       }
+}
+
+void
+bna_rx_cleanup_complete(struct bna_rx *rx)
+{
+       bfa_fsm_send_event(rx, RX_E_CLEANUP_DONE);
+}
+
+enum bna_cb_status
+bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode new_mode,
+               enum bna_rxmode bitmask,
+               void (*cbfn)(struct bnad *, struct bna_rx *))
+{
+       struct bna_rxf *rxf = &rx->rxf;
+       int need_hw_config = 0;
+
+       /* Error checks */
+
+       if (is_promisc_enable(new_mode, bitmask)) {
+               /* If promisc mode is already enabled elsewhere in the system */
+               if ((rx->bna->promisc_rid != BFI_INVALID_RID) &&
+                       (rx->bna->promisc_rid != rxf->rx->rid))
+                       goto err_return;
+
+               /* If default mode is already enabled in the system */
+               if (rx->bna->default_mode_rid != BFI_INVALID_RID)
+                       goto err_return;
+
+               /* Trying to enable promiscuous and default mode together */
+               if (is_default_enable(new_mode, bitmask))
+                       goto err_return;
+       }
+
+       if (is_default_enable(new_mode, bitmask)) {
+               /* If default mode is already enabled elsewhere in the system */
+               if ((rx->bna->default_mode_rid != BFI_INVALID_RID) &&
+                       (rx->bna->default_mode_rid != rxf->rx->rid)) {
+                               goto err_return;
+               }
+
+               /* If promiscuous mode is already enabled in the system */
+               if (rx->bna->promisc_rid != BFI_INVALID_RID)
+                       goto err_return;
+       }
+
+       /* Process the commands */
+
+       if (is_promisc_enable(new_mode, bitmask)) {
+               if (bna_rxf_promisc_enable(rxf))
+                       need_hw_config = 1;
+       } else if (is_promisc_disable(new_mode, bitmask)) {
+               if (bna_rxf_promisc_disable(rxf))
+                       need_hw_config = 1;
+       }
+
+       if (is_allmulti_enable(new_mode, bitmask)) {
+               if (bna_rxf_allmulti_enable(rxf))
+                       need_hw_config = 1;
+       } else if (is_allmulti_disable(new_mode, bitmask)) {
+               if (bna_rxf_allmulti_disable(rxf))
+                       need_hw_config = 1;
+       }
+
+       /* Trigger h/w if needed */
+
+       if (need_hw_config) {
+               rxf->cam_fltr_cbfn = cbfn;
+               rxf->cam_fltr_cbarg = rx->bna->bnad;
+               bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+       } else if (cbfn)
+               (*cbfn)(rx->bna->bnad, rx);
+
+       return BNA_CB_SUCCESS;
+
+err_return:
+       return BNA_CB_FAIL;
+}
+
+void
+bna_rx_vlanfilter_enable(struct bna_rx *rx)
+{
+       struct bna_rxf *rxf = &rx->rxf;
+
+       if (rxf->vlan_filter_status == BNA_STATUS_T_DISABLED) {
+               rxf->vlan_filter_status = BNA_STATUS_T_ENABLED;
+               rxf->vlan_pending_bitmask = (u8)BFI_VLAN_BMASK_ALL;
+               bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+       }
+}
+
+void
+bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo)
+{
+       struct bna_rxp *rxp;
+       struct list_head *qe;
+
+       list_for_each(qe, &rx->rxp_q) {
+               rxp = (struct bna_rxp *)qe;
+               rxp->cq.ccb->rx_coalescing_timeo = coalescing_timeo;
+               bna_ib_coalescing_timeo_set(&rxp->cq.ib, coalescing_timeo);
+       }
+}
+
+void
+bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX])
+{
+       int i, j;
+
+       for (i = 0; i < BNA_LOAD_T_MAX; i++)
+               for (j = 0; j < BNA_BIAS_T_MAX; j++)
+                       bna->rx_mod.dim_vector[i][j] = vector[i][j];
+}
+
+void
+bna_rx_dim_update(struct bna_ccb *ccb)
+{
+       struct bna *bna = ccb->cq->rx->bna;
+       u32 load, bias;
+       u32 pkt_rt, small_rt, large_rt;
+       u8 coalescing_timeo;
+
+       if ((ccb->pkt_rate.small_pkt_cnt == 0) &&
+               (ccb->pkt_rate.large_pkt_cnt == 0))
+               return;
+
+       /* Arrive at preconfigured coalescing timeo value based on pkt rate */
+
+       small_rt = ccb->pkt_rate.small_pkt_cnt;
+       large_rt = ccb->pkt_rate.large_pkt_cnt;
+
+       pkt_rt = small_rt + large_rt;
+
+       if (pkt_rt < BNA_PKT_RATE_10K)
+               load = BNA_LOAD_T_LOW_4;
+       else if (pkt_rt < BNA_PKT_RATE_20K)
+               load = BNA_LOAD_T_LOW_3;
+       else if (pkt_rt < BNA_PKT_RATE_30K)
+               load = BNA_LOAD_T_LOW_2;
+       else if (pkt_rt < BNA_PKT_RATE_40K)
+               load = BNA_LOAD_T_LOW_1;
+       else if (pkt_rt < BNA_PKT_RATE_50K)
+               load = BNA_LOAD_T_HIGH_1;
+       else if (pkt_rt < BNA_PKT_RATE_60K)
+               load = BNA_LOAD_T_HIGH_2;
+       else if (pkt_rt < BNA_PKT_RATE_80K)
+               load = BNA_LOAD_T_HIGH_3;
+       else
+               load = BNA_LOAD_T_HIGH_4;
+
+       if (small_rt > (large_rt << 1))
+               bias = 0;
+       else
+               bias = 1;
+
+       ccb->pkt_rate.small_pkt_cnt = 0;
+       ccb->pkt_rate.large_pkt_cnt = 0;
+
+       coalescing_timeo = bna->rx_mod.dim_vector[load][bias];
+       ccb->rx_coalescing_timeo = coalescing_timeo;
+
+       /* Set it to IB */
+       bna_ib_coalescing_timeo_set(&ccb->cq->ib, coalescing_timeo);
+}
+
+const u32 bna_napi_dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX] = {
+       {12, 12},
+       {6, 10},
+       {5, 10},
+       {4, 8},
+       {3, 6},
+       {3, 6},
+       {2, 4},
+       {1, 2},
+};
+
+/**
+ * TX
+ */
+#define call_tx_stop_cbfn(tx)                                          \
+do {                                                                   \
+       if ((tx)->stop_cbfn) {                                          \
+               void (*cbfn)(void *, struct bna_tx *);          \
+               void *cbarg;                                            \
+               cbfn = (tx)->stop_cbfn;                                 \
+               cbarg = (tx)->stop_cbarg;                               \
+               (tx)->stop_cbfn = NULL;                                 \
+               (tx)->stop_cbarg = NULL;                                \
+               cbfn(cbarg, (tx));                                      \
+       }                                                               \
+} while (0)
+
+#define call_tx_prio_change_cbfn(tx)                                   \
+do {                                                                   \
+       if ((tx)->prio_change_cbfn) {                                   \
+               void (*cbfn)(struct bnad *, struct bna_tx *);   \
+               cbfn = (tx)->prio_change_cbfn;                          \
+               (tx)->prio_change_cbfn = NULL;                          \
+               cbfn((tx)->bna->bnad, (tx));                            \
+       }                                                               \
+} while (0)
+
+static void bna_tx_mod_cb_tx_stopped(void *tx_mod, struct bna_tx *tx);
+static void bna_bfi_tx_enet_start(struct bna_tx *tx);
+static void bna_tx_enet_stop(struct bna_tx *tx);
+
+enum bna_tx_event {
+       TX_E_START                      = 1,
+       TX_E_STOP                       = 2,
+       TX_E_FAIL                       = 3,
+       TX_E_STARTED                    = 4,
+       TX_E_STOPPED                    = 5,
+       TX_E_PRIO_CHANGE                = 6,
+       TX_E_CLEANUP_DONE               = 7,
+       TX_E_BW_UPDATE                  = 8,
+};
+
+bfa_fsm_state_decl(bna_tx, stopped, struct bna_tx, enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, start_wait, struct bna_tx, enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, started, struct bna_tx, enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, stop_wait, struct bna_tx, enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, cleanup_wait, struct bna_tx,
+                       enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, prio_stop_wait, struct bna_tx,
+                       enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, prio_cleanup_wait, struct bna_tx,
+                       enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, failed, struct bna_tx, enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, quiesce_wait, struct bna_tx,
+                       enum bna_tx_event);
+
+static void
+bna_tx_sm_stopped_entry(struct bna_tx *tx)
+{
+       call_tx_stop_cbfn(tx);
+}
+
+static void
+bna_tx_sm_stopped(struct bna_tx *tx, enum bna_tx_event event)
+{
+       switch (event) {
+       case TX_E_START:
+               bfa_fsm_set_state(tx, bna_tx_sm_start_wait);
+               break;
+
+       case TX_E_STOP:
+               call_tx_stop_cbfn(tx);
+               break;
+
+       case TX_E_FAIL:
+               /* No-op */
+               break;
+
+       case TX_E_PRIO_CHANGE:
+               call_tx_prio_change_cbfn(tx);
+               break;
+
+       case TX_E_BW_UPDATE:
+               /* No-op */
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_tx_sm_start_wait_entry(struct bna_tx *tx)
+{
+       bna_bfi_tx_enet_start(tx);
+}
+
+static void
+bna_tx_sm_start_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+       switch (event) {
+       case TX_E_STOP:
+               tx->flags &= ~(BNA_TX_F_PRIO_CHANGED | BNA_TX_F_BW_UPDATED);
+               bfa_fsm_set_state(tx, bna_tx_sm_stop_wait);
+               break;
+
+       case TX_E_FAIL:
+               tx->flags &= ~(BNA_TX_F_PRIO_CHANGED | BNA_TX_F_BW_UPDATED);
+               bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+               break;
+
+       case TX_E_STARTED:
+               if (tx->flags & (BNA_TX_F_PRIO_CHANGED | BNA_TX_F_BW_UPDATED)) {
+                       tx->flags &= ~(BNA_TX_F_PRIO_CHANGED |
+                               BNA_TX_F_BW_UPDATED);
+                       bfa_fsm_set_state(tx, bna_tx_sm_prio_stop_wait);
+               } else
+                       bfa_fsm_set_state(tx, bna_tx_sm_started);
+               break;
+
+       case TX_E_PRIO_CHANGE:
+               tx->flags |=  BNA_TX_F_PRIO_CHANGED;
+               break;
+
+       case TX_E_BW_UPDATE:
+               tx->flags |= BNA_TX_F_BW_UPDATED;
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_tx_sm_started_entry(struct bna_tx *tx)
+{
+       struct bna_txq *txq;
+       struct list_head                 *qe;
+       int is_regular = (tx->type == BNA_TX_T_REGULAR);
+
+       list_for_each(qe, &tx->txq_q) {
+               txq = (struct bna_txq *)qe;
+               txq->tcb->priority = txq->priority;
+               /* Start IB */
+               bna_ib_start(tx->bna, &txq->ib, is_regular);
+       }
+       tx->tx_resume_cbfn(tx->bna->bnad, tx);
+}
+
+static void
+bna_tx_sm_started(struct bna_tx *tx, enum bna_tx_event event)
+{
+       switch (event) {
+       case TX_E_STOP:
+               bfa_fsm_set_state(tx, bna_tx_sm_stop_wait);
+               tx->tx_stall_cbfn(tx->bna->bnad, tx);
+               bna_tx_enet_stop(tx);
+               break;
+
+       case TX_E_FAIL:
+               bfa_fsm_set_state(tx, bna_tx_sm_failed);
+               tx->tx_stall_cbfn(tx->bna->bnad, tx);
+               tx->tx_cleanup_cbfn(tx->bna->bnad, tx);
+               break;
+
+       case TX_E_PRIO_CHANGE:
+       case TX_E_BW_UPDATE:
+               bfa_fsm_set_state(tx, bna_tx_sm_prio_stop_wait);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_tx_sm_stop_wait_entry(struct bna_tx *tx)
+{
+}
+
+static void
+bna_tx_sm_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+       switch (event) {
+       case TX_E_FAIL:
+       case TX_E_STOPPED:
+               bfa_fsm_set_state(tx, bna_tx_sm_cleanup_wait);
+               tx->tx_cleanup_cbfn(tx->bna->bnad, tx);
+               break;
+
+       case TX_E_STARTED:
+               /**
+                * We are here due to start_wait -> stop_wait transition on
+                * TX_E_STOP event
+                */
+               bna_tx_enet_stop(tx);
+               break;
+
+       case TX_E_PRIO_CHANGE:
+       case TX_E_BW_UPDATE:
+               /* No-op */
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_tx_sm_cleanup_wait_entry(struct bna_tx *tx)
+{
+}
+
+static void
+bna_tx_sm_cleanup_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+       switch (event) {
+       case TX_E_FAIL:
+       case TX_E_PRIO_CHANGE:
+       case TX_E_BW_UPDATE:
+               /* No-op */
+               break;
+
+       case TX_E_CLEANUP_DONE:
+               bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_tx_sm_prio_stop_wait_entry(struct bna_tx *tx)
+{
+       tx->tx_stall_cbfn(tx->bna->bnad, tx);
+       bna_tx_enet_stop(tx);
+}
+
+static void
+bna_tx_sm_prio_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+       switch (event) {
+       case TX_E_STOP:
+               bfa_fsm_set_state(tx, bna_tx_sm_stop_wait);
+               break;
+
+       case TX_E_FAIL:
+               bfa_fsm_set_state(tx, bna_tx_sm_failed);
+               call_tx_prio_change_cbfn(tx);
+               tx->tx_cleanup_cbfn(tx->bna->bnad, tx);
+               break;
+
+       case TX_E_STOPPED:
+               bfa_fsm_set_state(tx, bna_tx_sm_prio_cleanup_wait);
+               break;
+
+       case TX_E_PRIO_CHANGE:
+       case TX_E_BW_UPDATE:
+               /* No-op */
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_tx_sm_prio_cleanup_wait_entry(struct bna_tx *tx)
+{
+       call_tx_prio_change_cbfn(tx);
+       tx->tx_cleanup_cbfn(tx->bna->bnad, tx);
+}
+
+static void
+bna_tx_sm_prio_cleanup_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+       switch (event) {
+       case TX_E_STOP:
+               bfa_fsm_set_state(tx, bna_tx_sm_cleanup_wait);
+               break;
+
+       case TX_E_FAIL:
+               bfa_fsm_set_state(tx, bna_tx_sm_failed);
+               break;
+
+       case TX_E_PRIO_CHANGE:
+       case TX_E_BW_UPDATE:
+               /* No-op */
+               break;
+
+       case TX_E_CLEANUP_DONE:
+               bfa_fsm_set_state(tx, bna_tx_sm_start_wait);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_tx_sm_failed_entry(struct bna_tx *tx)
+{
+}
+
+static void
+bna_tx_sm_failed(struct bna_tx *tx, enum bna_tx_event event)
+{
+       switch (event) {
+       case TX_E_START:
+               bfa_fsm_set_state(tx, bna_tx_sm_quiesce_wait);
+               break;
+
+       case TX_E_STOP:
+               bfa_fsm_set_state(tx, bna_tx_sm_cleanup_wait);
+               break;
+
+       case TX_E_FAIL:
+               /* No-op */
+               break;
+
+       case TX_E_CLEANUP_DONE:
+               bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_tx_sm_quiesce_wait_entry(struct bna_tx *tx)
+{
+}
+
+static void
+bna_tx_sm_quiesce_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+       switch (event) {
+       case TX_E_STOP:
+               bfa_fsm_set_state(tx, bna_tx_sm_cleanup_wait);
+               break;
+
+       case TX_E_FAIL:
+               bfa_fsm_set_state(tx, bna_tx_sm_failed);
+               break;
+
+       case TX_E_CLEANUP_DONE:
+               bfa_fsm_set_state(tx, bna_tx_sm_start_wait);
+               break;
+
+       case TX_E_BW_UPDATE:
+               /* No-op */
+               break;
+
+       default:
+               bfa_sm_fault(event);
+       }
+}
+
+static void
+bna_bfi_tx_enet_start(struct bna_tx *tx)
+{
+       struct bfi_enet_tx_cfg_req *cfg_req = &tx->bfi_enet_cmd.cfg_req;
+       struct bna_txq *txq = NULL;
+       struct list_head *qe;
+       int i;
+
+       bfi_msgq_mhdr_set(cfg_req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_TX_CFG_SET_REQ, 0, tx->rid);
+       cfg_req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_tx_cfg_req)));
+
+       cfg_req->num_queues = tx->num_txq;
+       for (i = 0, qe = bfa_q_first(&tx->txq_q);
+               i < tx->num_txq;
+               i++, qe = bfa_q_next(qe)) {
+               txq = (struct bna_txq *)qe;
+
+               bfi_enet_datapath_q_init(&cfg_req->q_cfg[i].q.q, &txq->qpt);
+               cfg_req->q_cfg[i].q.priority = txq->priority;
+
+               cfg_req->q_cfg[i].ib.index_addr.a32.addr_lo =
+                       txq->ib.ib_seg_host_addr.lsb;
+               cfg_req->q_cfg[i].ib.index_addr.a32.addr_hi =
+                       txq->ib.ib_seg_host_addr.msb;
+               cfg_req->q_cfg[i].ib.intr.msix_index =
+                       htons((u16)txq->ib.intr_vector);
+       }
+
+       cfg_req->ib_cfg.int_pkt_dma = BNA_STATUS_T_ENABLED;
+       cfg_req->ib_cfg.int_enabled = BNA_STATUS_T_ENABLED;
+       cfg_req->ib_cfg.int_pkt_enabled = BNA_STATUS_T_DISABLED;
+       cfg_req->ib_cfg.continuous_coalescing = BNA_STATUS_T_ENABLED;
+       cfg_req->ib_cfg.msix = (txq->ib.intr_type == BNA_INTR_T_MSIX)
+                               ? BNA_STATUS_T_ENABLED : BNA_STATUS_T_DISABLED;
+       cfg_req->ib_cfg.coalescing_timeout =
+                       htonl((u32)txq->ib.coalescing_timeo);
+       cfg_req->ib_cfg.inter_pkt_timeout =
+                       htonl((u32)txq->ib.interpkt_timeo);
+       cfg_req->ib_cfg.inter_pkt_count = (u8)txq->ib.interpkt_count;
+
+       cfg_req->tx_cfg.vlan_mode = BFI_ENET_TX_VLAN_WI;
+       cfg_req->tx_cfg.vlan_id = htons((u16)tx->txf_vlan_id);
+       cfg_req->tx_cfg.admit_tagged_frame = BNA_STATUS_T_DISABLED;
+       cfg_req->tx_cfg.apply_vlan_filter = BNA_STATUS_T_DISABLED;
+
+       bfa_msgq_cmd_set(&tx->msgq_cmd, NULL, NULL,
+               sizeof(struct bfi_enet_tx_cfg_req), &cfg_req->mh);
+       bfa_msgq_cmd_post(&tx->bna->msgq, &tx->msgq_cmd);
+}
+
+static void
+bna_bfi_tx_enet_stop(struct bna_tx *tx)
+{
+       struct bfi_enet_req *req = &tx->bfi_enet_cmd.req;
+
+       bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+               BFI_ENET_H2I_TX_CFG_CLR_REQ, 0, tx->rid);
+       req->mh.num_entries = htons(
+               bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_req)));
+       bfa_msgq_cmd_set(&tx->msgq_cmd, NULL, NULL, sizeof(struct bfi_enet_req),
+               &req->mh);
+       bfa_msgq_cmd_post(&tx->bna->msgq, &tx->msgq_cmd);
+}
+
+static void
+bna_tx_enet_stop(struct bna_tx *tx)
+{
+       struct bna_txq *txq;
+       struct list_head                 *qe;
+
+       /* Stop IB */
+       list_for_each(qe, &tx->txq_q) {
+               txq = (struct bna_txq *)qe;
+               bna_ib_stop(tx->bna, &txq->ib);
+       }
+
+       bna_bfi_tx_enet_stop(tx);
+}
+
+static void
+bna_txq_qpt_setup(struct bna_txq *txq, int page_count, int page_size,
+               struct bna_mem_descr *qpt_mem,
+               struct bna_mem_descr *swqpt_mem,
+               struct bna_mem_descr *page_mem)
+{
+       int i;
+
+       txq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
+       txq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
+       txq->qpt.kv_qpt_ptr = qpt_mem->kva;
+       txq->qpt.page_count = page_count;
+       txq->qpt.page_size = page_size;
+
+       txq->tcb->sw_qpt = (void **) swqpt_mem->kva;
+
+       for (i = 0; i < page_count; i++) {
+               txq->tcb->sw_qpt[i] = page_mem[i].kva;
+
+               ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].lsb =
+                       page_mem[i].dma.lsb;
+               ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].msb =
+                       page_mem[i].dma.msb;
+       }
+}
+
+static struct bna_tx *
+bna_tx_get(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
+{
+       struct list_head        *qe = NULL;
+       struct bna_tx *tx = NULL;
+
+       if (list_empty(&tx_mod->tx_free_q))
+               return NULL;
+       if (type == BNA_TX_T_REGULAR) {
+               bfa_q_deq(&tx_mod->tx_free_q, &qe);
+       } else {
+               bfa_q_deq_tail(&tx_mod->tx_free_q, &qe);
+       }
+       tx = (struct bna_tx *)qe;
+       bfa_q_qe_init(&tx->qe);
+       tx->type = type;
+
+       return tx;
+}
+
+static void
+bna_tx_free(struct bna_tx *tx)
+{
+       struct bna_tx_mod *tx_mod = &tx->bna->tx_mod;
+       struct bna_txq *txq;
+       struct list_head *prev_qe;
+       struct list_head *qe;
+
+       while (!list_empty(&tx->txq_q)) {
+               bfa_q_deq(&tx->txq_q, &txq);
+               bfa_q_qe_init(&txq->qe);
+               txq->tcb = NULL;
+               txq->tx = NULL;
+               list_add_tail(&txq->qe, &tx_mod->txq_free_q);
+       }
+
+       list_for_each(qe, &tx_mod->tx_active_q) {
+               if (qe == &tx->qe) {
+                       list_del(&tx->qe);
+                       bfa_q_qe_init(&tx->qe);
+                       break;
+               }
+       }
+
+       tx->bna = NULL;
+       tx->priv = NULL;
+
+       prev_qe = NULL;
+       list_for_each(qe, &tx_mod->tx_free_q) {
+               if (((struct bna_tx *)qe)->rid < tx->rid)
+                       prev_qe = qe;
+               else {
+                       break;
+               }
+       }
+
+       if (prev_qe == NULL) {
+               /* This is the first entry */
+               bfa_q_enq_head(&tx_mod->tx_free_q, &tx->qe);
+       } else if (bfa_q_next(prev_qe) == &tx_mod->tx_free_q) {
+               /* This is the last entry */
+               list_add_tail(&tx->qe, &tx_mod->tx_free_q);
+       } else {
+               /* Somewhere in the middle */
+               bfa_q_next(&tx->qe) = bfa_q_next(prev_qe);
+               bfa_q_prev(&tx->qe) = prev_qe;
+               bfa_q_next(prev_qe) = &tx->qe;
+               bfa_q_prev(bfa_q_next(&tx->qe)) = &tx->qe;
+       }
+}
+
+static void
+bna_tx_start(struct bna_tx *tx)
+{
+       tx->flags |= BNA_TX_F_ENET_STARTED;
+       if (tx->flags & BNA_TX_F_ENABLED)
+               bfa_fsm_send_event(tx, TX_E_START);
+}
+
+static void
+bna_tx_stop(struct bna_tx *tx)
+{
+       tx->stop_cbfn = bna_tx_mod_cb_tx_stopped;
+       tx->stop_cbarg = &tx->bna->tx_mod;
+
+       tx->flags &= ~BNA_TX_F_ENET_STARTED;
+       bfa_fsm_send_event(tx, TX_E_STOP);
+}
+
+static void
+bna_tx_fail(struct bna_tx *tx)
+{
+       tx->flags &= ~BNA_TX_F_ENET_STARTED;
+       bfa_fsm_send_event(tx, TX_E_FAIL);
+}
+
+void
+bna_bfi_tx_enet_start_rsp(struct bna_tx *tx, struct bfi_msgq_mhdr *msghdr)
+{
+       struct bfi_enet_tx_cfg_rsp *cfg_rsp = &tx->bfi_enet_cmd.cfg_rsp;
+       struct bna_txq *txq = NULL;
+       struct list_head *qe;
+       int i;
+
+       bfa_msgq_rsp_copy(&tx->bna->msgq, (u8 *)cfg_rsp,
+               sizeof(struct bfi_enet_tx_cfg_rsp));
+
+       tx->hw_id = cfg_rsp->hw_id;
+
+       for (i = 0, qe = bfa_q_first(&tx->txq_q);
+               i < tx->num_txq; i++, qe = bfa_q_next(qe)) {
+               txq = (struct bna_txq *)qe;
+
+               /* Setup doorbells */
+               txq->tcb->i_dbell->doorbell_addr =
+                       tx->bna->pcidev.pci_bar_kva
+                       + ntohl(cfg_rsp->q_handles[i].i_dbell);
+               txq->tcb->q_dbell =
+                       tx->bna->pcidev.pci_bar_kva
+                       + ntohl(cfg_rsp->q_handles[i].q_dbell);
+               txq->hw_id = cfg_rsp->q_handles[i].hw_qid;
+
+               /* Initialize producer/consumer indexes */
+               (*txq->tcb->hw_consumer_index) = 0;
+               txq->tcb->producer_index = txq->tcb->consumer_index = 0;
+       }
+
+       bfa_fsm_send_event(tx, TX_E_STARTED);
+}
+
+void
+bna_bfi_tx_enet_stop_rsp(struct bna_tx *tx, struct bfi_msgq_mhdr *msghdr)
+{
+       bfa_fsm_send_event(tx, TX_E_STOPPED);
+}
+
+void
+bna_bfi_bw_update_aen(struct bna_tx_mod *tx_mod)
+{
+       struct bna_tx *tx;
+       struct list_head                *qe;
+
+       list_for_each(qe, &tx_mod->tx_active_q) {
+               tx = (struct bna_tx *)qe;
+               bfa_fsm_send_event(tx, TX_E_BW_UPDATE);
+       }
+}
+
+void
+bna_tx_res_req(int num_txq, int txq_depth, struct bna_res_info *res_info)
+{
+       u32 q_size;
+       u32 page_count;
+       struct bna_mem_info *mem_info;
+
+       res_info[BNA_TX_RES_MEM_T_TCB].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_KVA;
+       mem_info->len = sizeof(struct bna_tcb);
+       mem_info->num = num_txq;
+
+       q_size = txq_depth * BFI_TXQ_WI_SIZE;
+       q_size = ALIGN(q_size, PAGE_SIZE);
+       page_count = q_size >> PAGE_SHIFT;
+
+       res_info[BNA_TX_RES_MEM_T_QPT].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_DMA;
+       mem_info->len = page_count * sizeof(struct bna_dma_addr);
+       mem_info->num = num_txq;
+
+       res_info[BNA_TX_RES_MEM_T_SWQPT].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_KVA;
+       mem_info->len = page_count * sizeof(void *);
+       mem_info->num = num_txq;
+
+       res_info[BNA_TX_RES_MEM_T_PAGE].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_DMA;
+       mem_info->len = PAGE_SIZE;
+       mem_info->num = num_txq * page_count;
+
+       res_info[BNA_TX_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM;
+       mem_info = &res_info[BNA_TX_RES_MEM_T_IBIDX].res_u.mem_info;
+       mem_info->mem_type = BNA_MEM_T_DMA;
+       mem_info->len = BFI_IBIDX_SIZE;
+       mem_info->num = num_txq;
+
+       res_info[BNA_TX_RES_INTR_T_TXCMPL].res_type = BNA_RES_T_INTR;
+       res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.intr_type =
+                       BNA_INTR_T_MSIX;
+       res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.num = num_txq;
+}
+
+struct bna_tx *
+bna_tx_create(struct bna *bna, struct bnad *bnad,
+               struct bna_tx_config *tx_cfg,
+               struct bna_tx_event_cbfn *tx_cbfn,
+               struct bna_res_info *res_info, void *priv)
+{
+       struct bna_intr_info *intr_info;
+       struct bna_tx_mod *tx_mod = &bna->tx_mod;
+       struct bna_tx *tx;
+       struct bna_txq *txq;
+       struct list_head *qe;
+       int page_count;
+       int page_size;
+       int page_idx;
+       int i;
+
+       intr_info = &res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info;
+       page_count = (res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.num) /
+                       tx_cfg->num_txq;
+       page_size = res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.len;
+
+       /**
+        * Get resources
+        */
+
+       if ((intr_info->num != 1) && (intr_info->num != tx_cfg->num_txq))
+               return NULL;
+
+       /* Tx */
+
+       tx = bna_tx_get(tx_mod, tx_cfg->tx_type);
+       if (!tx)
+               return NULL;
+       tx->bna = bna;
+       tx->priv = priv;
+
+       /* TxQs */
+
+       INIT_LIST_HEAD(&tx->txq_q);
+       for (i = 0; i < tx_cfg->num_txq; i++) {
+               if (list_empty(&tx_mod->txq_free_q))
+                       goto err_return;
+
+               bfa_q_deq(&tx_mod->txq_free_q, &txq);
+               bfa_q_qe_init(&txq->qe);
+               list_add_tail(&txq->qe, &tx->txq_q);
+               txq->tx = tx;
+       }
+
+       /*
+        * Initialize
+        */
+
+       /* Tx */
+
+       tx->tcb_setup_cbfn = tx_cbfn->tcb_setup_cbfn;
+       tx->tcb_destroy_cbfn = tx_cbfn->tcb_destroy_cbfn;
+       /* Following callbacks are mandatory */
+       tx->tx_stall_cbfn = tx_cbfn->tx_stall_cbfn;
+       tx->tx_resume_cbfn = tx_cbfn->tx_resume_cbfn;
+       tx->tx_cleanup_cbfn = tx_cbfn->tx_cleanup_cbfn;
+
+       list_add_tail(&tx->qe, &tx_mod->tx_active_q);
+
+       tx->num_txq = tx_cfg->num_txq;
+
+       tx->flags = 0;
+       if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_ENET_STARTED) {
+               switch (tx->type) {
+               case BNA_TX_T_REGULAR:
+                       if (!(tx->bna->tx_mod.flags &
+                               BNA_TX_MOD_F_ENET_LOOPBACK))
+                               tx->flags |= BNA_TX_F_ENET_STARTED;
+                       break;
+               case BNA_TX_T_LOOPBACK:
+                       if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_ENET_LOOPBACK)
+                               tx->flags |= BNA_TX_F_ENET_STARTED;
+                       break;
+               }
+       }
+
+       /* TxQ */
+
+       i = 0;
+       page_idx = 0;
+       list_for_each(qe, &tx->txq_q) {
+               txq = (struct bna_txq *)qe;
+               txq->tcb = (struct bna_tcb *)
+               res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info.mdl[i].kva;
+               txq->tx_packets = 0;
+               txq->tx_bytes = 0;
+
+               /* IB */
+               txq->ib.ib_seg_host_addr.lsb =
+               res_info[BNA_TX_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.lsb;
+               txq->ib.ib_seg_host_addr.msb =
+               res_info[BNA_TX_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.msb;
+               txq->ib.ib_seg_host_addr_kva =
+               res_info[BNA_TX_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].kva;
+               txq->ib.intr_type = intr_info->intr_type;
+               txq->ib.intr_vector = (intr_info->num == 1) ?
+                                       intr_info->idl[0].vector :
+                                       intr_info->idl[i].vector;
+               if (intr_info->intr_type == BNA_INTR_T_INTX)
+                       txq->ib.intr_vector = (1 <<  txq->ib.intr_vector);
+               txq->ib.coalescing_timeo = tx_cfg->coalescing_timeo;
+               txq->ib.interpkt_timeo = 0; /* Not used */
+               txq->ib.interpkt_count = BFI_TX_INTERPKT_COUNT;
+
+               /* TCB */
+
+               txq->tcb->q_depth = tx_cfg->txq_depth;
+               txq->tcb->unmap_q = (void *)
+               res_info[BNA_TX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[i].kva;
+               txq->tcb->hw_consumer_index =
+                       (u32 *)txq->ib.ib_seg_host_addr_kva;
+               txq->tcb->i_dbell = &txq->ib.door_bell;
+               txq->tcb->intr_type = txq->ib.intr_type;
+               txq->tcb->intr_vector = txq->ib.intr_vector;
+               txq->tcb->txq = txq;
+               txq->tcb->bnad = bnad;
+               txq->tcb->id = i;
+
+               /* QPT, SWQPT, Pages */
+               bna_txq_qpt_setup(txq, page_count, page_size,
+                       &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info.mdl[i],
+                       &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info.mdl[i],
+                       &res_info[BNA_TX_RES_MEM_T_PAGE].
+                                 res_u.mem_info.mdl[page_idx]);
+               txq->tcb->page_idx = page_idx;
+               txq->tcb->page_count = page_count;
+               page_idx += page_count;
+
+               /* Callback to bnad for setting up TCB */
+               if (tx->tcb_setup_cbfn)
+                       (tx->tcb_setup_cbfn)(bna->bnad, txq->tcb);
+
+               if (tx_cfg->num_txq == BFI_TX_MAX_PRIO)
+                       txq->priority = txq->tcb->id;
+               else
+                       txq->priority = tx_mod->default_prio;
+
+               i++;
+       }
+
+       tx->txf_vlan_id = 0;
+
+       bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+
+       tx_mod->rid_mask |= (1 << tx->rid);
+
+       return tx;
+
+err_return:
+       bna_tx_free(tx);
+       return NULL;
+}
+
+void
+bna_tx_destroy(struct bna_tx *tx)
+{
+       struct bna_txq *txq;
+       struct list_head *qe;
+
+       list_for_each(qe, &tx->txq_q) {
+               txq = (struct bna_txq *)qe;
+               if (tx->tcb_destroy_cbfn)
+                       (tx->tcb_destroy_cbfn)(tx->bna->bnad, txq->tcb);
+       }
+
+       tx->bna->tx_mod.rid_mask &= ~(1 << tx->rid);
+       bna_tx_free(tx);
+}
+
+void
+bna_tx_enable(struct bna_tx *tx)
+{
+       if (tx->fsm != (bfa_sm_t)bna_tx_sm_stopped)
+               return;
+
+       tx->flags |= BNA_TX_F_ENABLED;
+
+       if (tx->flags & BNA_TX_F_ENET_STARTED)
+               bfa_fsm_send_event(tx, TX_E_START);
+}
+
+void
+bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type,
+               void (*cbfn)(void *, struct bna_tx *))
+{
+       if (type == BNA_SOFT_CLEANUP) {
+               (*cbfn)(tx->bna->bnad, tx);
+               return;
+       }
+
+       tx->stop_cbfn = cbfn;
+       tx->stop_cbarg = tx->bna->bnad;
+
+       tx->flags &= ~BNA_TX_F_ENABLED;
+
+       bfa_fsm_send_event(tx, TX_E_STOP);
+}
+
+void
+bna_tx_cleanup_complete(struct bna_tx *tx)
+{
+       bfa_fsm_send_event(tx, TX_E_CLEANUP_DONE);
+}
+
+static void
+bna_tx_mod_cb_tx_stopped(void *arg, struct bna_tx *tx)
+{
+       struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
+
+       bfa_wc_down(&tx_mod->tx_stop_wc);
+}
+
+static void
+bna_tx_mod_cb_tx_stopped_all(void *arg)
+{
+       struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
+
+       if (tx_mod->stop_cbfn)
+               tx_mod->stop_cbfn(&tx_mod->bna->enet);
+       tx_mod->stop_cbfn = NULL;
+}
+
+void
+bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna,
+               struct bna_res_info *res_info)
+{
+       int i;
+
+       tx_mod->bna = bna;
+       tx_mod->flags = 0;
+
+       tx_mod->tx = (struct bna_tx *)
+               res_info[BNA_MOD_RES_MEM_T_TX_ARRAY].res_u.mem_info.mdl[0].kva;
+       tx_mod->txq = (struct bna_txq *)
+               res_info[BNA_MOD_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mdl[0].kva;
+
+       INIT_LIST_HEAD(&tx_mod->tx_free_q);
+       INIT_LIST_HEAD(&tx_mod->tx_active_q);
+
+       INIT_LIST_HEAD(&tx_mod->txq_free_q);
+
+       for (i = 0; i < bna->ioceth.attr.num_txq; i++) {
+               tx_mod->tx[i].rid = i;
+               bfa_q_qe_init(&tx_mod->tx[i].qe);
+               list_add_tail(&tx_mod->tx[i].qe, &tx_mod->tx_free_q);
+               bfa_q_qe_init(&tx_mod->txq[i].qe);
+               list_add_tail(&tx_mod->txq[i].qe, &tx_mod->txq_free_q);
+       }
+
+       tx_mod->prio_map = BFI_TX_PRIO_MAP_ALL;
+       tx_mod->default_prio = 0;
+       tx_mod->iscsi_over_cee = BNA_STATUS_T_DISABLED;
+       tx_mod->iscsi_prio = -1;
+}
+
+void
+bna_tx_mod_uninit(struct bna_tx_mod *tx_mod)
+{
+       struct list_head                *qe;
+       int i;
+
+       i = 0;
+       list_for_each(qe, &tx_mod->tx_free_q)
+               i++;
+
+       i = 0;
+       list_for_each(qe, &tx_mod->txq_free_q)
+               i++;
+
+       tx_mod->bna = NULL;
+}
+
+void
+bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
+{
+       struct bna_tx *tx;
+       struct list_head                *qe;
+
+       tx_mod->flags |= BNA_TX_MOD_F_ENET_STARTED;
+       if (type == BNA_TX_T_LOOPBACK)
+               tx_mod->flags |= BNA_TX_MOD_F_ENET_LOOPBACK;
+
+       list_for_each(qe, &tx_mod->tx_active_q) {
+               tx = (struct bna_tx *)qe;
+               if (tx->type == type)
+                       bna_tx_start(tx);
+       }
+}
+
+void
+bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
+{
+       struct bna_tx *tx;
+       struct list_head                *qe;
+
+       tx_mod->flags &= ~BNA_TX_MOD_F_ENET_STARTED;
+       tx_mod->flags &= ~BNA_TX_MOD_F_ENET_LOOPBACK;
+
+       tx_mod->stop_cbfn = bna_enet_cb_tx_stopped;
+
+       bfa_wc_init(&tx_mod->tx_stop_wc, bna_tx_mod_cb_tx_stopped_all, tx_mod);
+
+       list_for_each(qe, &tx_mod->tx_active_q) {
+               tx = (struct bna_tx *)qe;
+               if (tx->type == type) {
+                       bfa_wc_up(&tx_mod->tx_stop_wc);
+                       bna_tx_stop(tx);
+               }
+       }
+
+       bfa_wc_wait(&tx_mod->tx_stop_wc);
+}
+
+void
+bna_tx_mod_fail(struct bna_tx_mod *tx_mod)
+{
+       struct bna_tx *tx;
+       struct list_head                *qe;
+
+       tx_mod->flags &= ~BNA_TX_MOD_F_ENET_STARTED;
+       tx_mod->flags &= ~BNA_TX_MOD_F_ENET_LOOPBACK;
+
+       list_for_each(qe, &tx_mod->tx_active_q) {
+               tx = (struct bna_tx *)qe;
+               bna_tx_fail(tx);
+       }
+}
+
+void
+bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo)
+{
+       struct bna_txq *txq;
+       struct list_head *qe;
+
+       list_for_each(qe, &tx->txq_q) {
+               txq = (struct bna_txq *)qe;
+               bna_ib_coalescing_timeo_set(&txq->ib, coalescing_timeo);
+       }
+}
similarity index 58%
rename from drivers/net/bna/bna_types.h
rename to drivers/net/ethernet/brocade/bna/bna_types.h
index 2f89cb2..8a6da0c 100644 (file)
 #define __BNA_TYPES_H__
 
 #include "cna.h"
-#include "bna_hw.h"
+#include "bna_hw_defs.h"
 #include "bfa_cee.h"
+#include "bfi_enet.h"
+#include "bfa_msgq.h"
 
 /**
  *
  *
  */
 
+struct bna_mcam_handle;
 struct bna_txq;
 struct bna_tx;
 struct bna_rxq;
 struct bna_cq;
 struct bna_rx;
 struct bna_rxf;
-struct bna_port;
+struct bna_enet;
 struct bna;
 struct bnad;
 
@@ -86,31 +89,29 @@ enum bna_res_req_type {
        BNA_RES_MEM_T_ATTR              = 1,
        BNA_RES_MEM_T_FWTRC             = 2,
        BNA_RES_MEM_T_STATS             = 3,
-       BNA_RES_MEM_T_SWSTATS           = 4,
-       BNA_RES_MEM_T_IBIDX             = 5,
-       BNA_RES_MEM_T_IB_ARRAY          = 6,
-       BNA_RES_MEM_T_INTR_ARRAY        = 7,
-       BNA_RES_MEM_T_IDXSEG_ARRAY      = 8,
-       BNA_RES_MEM_T_TX_ARRAY          = 9,
-       BNA_RES_MEM_T_TXQ_ARRAY         = 10,
-       BNA_RES_MEM_T_RX_ARRAY          = 11,
-       BNA_RES_MEM_T_RXP_ARRAY         = 12,
-       BNA_RES_MEM_T_RXQ_ARRAY         = 13,
-       BNA_RES_MEM_T_UCMAC_ARRAY       = 14,
-       BNA_RES_MEM_T_MCMAC_ARRAY       = 15,
-       BNA_RES_MEM_T_RIT_ENTRY         = 16,
-       BNA_RES_MEM_T_RIT_SEGMENT       = 17,
-       BNA_RES_INTR_T_MBOX             = 18,
        BNA_RES_T_MAX
 };
 
+enum bna_mod_res_req_type {
+       BNA_MOD_RES_MEM_T_TX_ARRAY      = 0,
+       BNA_MOD_RES_MEM_T_TXQ_ARRAY     = 1,
+       BNA_MOD_RES_MEM_T_RX_ARRAY      = 2,
+       BNA_MOD_RES_MEM_T_RXP_ARRAY     = 3,
+       BNA_MOD_RES_MEM_T_RXQ_ARRAY     = 4,
+       BNA_MOD_RES_MEM_T_UCMAC_ARRAY   = 5,
+       BNA_MOD_RES_MEM_T_MCMAC_ARRAY   = 6,
+       BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY = 7,
+       BNA_MOD_RES_T_MAX
+};
+
 enum bna_tx_res_req_type {
        BNA_TX_RES_MEM_T_TCB    = 0,
        BNA_TX_RES_MEM_T_UNMAPQ = 1,
        BNA_TX_RES_MEM_T_QPT    = 2,
        BNA_TX_RES_MEM_T_SWQPT  = 3,
        BNA_TX_RES_MEM_T_PAGE   = 4,
-       BNA_TX_RES_INTR_T_TXCMPL = 5,
+       BNA_TX_RES_MEM_T_IBIDX  = 5,
+       BNA_TX_RES_INTR_T_TXCMPL = 6,
        BNA_TX_RES_T_MAX,
 };
 
@@ -127,13 +128,10 @@ enum bna_rx_mem_type {
        BNA_RX_RES_MEM_T_DSWQPT         = 9,    /* RX s/w QPT */
        BNA_RX_RES_MEM_T_DPAGE          = 10,   /* RX s/w QPT */
        BNA_RX_RES_MEM_T_HPAGE          = 11,   /* RX s/w QPT */
-       BNA_RX_RES_T_INTR               = 12,   /* Rx interrupts */
-       BNA_RX_RES_T_MAX                = 13
-};
-
-enum bna_mbox_state {
-       BNA_MBOX_FREE           = 0,
-       BNA_MBOX_POSTED         = 1
+       BNA_RX_RES_MEM_T_IBIDX          = 12,
+       BNA_RX_RES_MEM_T_RIT            = 13,
+       BNA_RX_RES_T_INTR               = 14,   /* Rx interrupts */
+       BNA_RX_RES_T_MAX                = 15
 };
 
 enum bna_tx_type {
@@ -142,14 +140,15 @@ enum bna_tx_type {
 };
 
 enum bna_tx_flags {
-       BNA_TX_F_PORT_STARTED   = 1,
+       BNA_TX_F_ENET_STARTED   = 1,
        BNA_TX_F_ENABLED        = 2,
-       BNA_TX_F_PRIO_LOCK      = 4,
+       BNA_TX_F_PRIO_CHANGED   = 4,
+       BNA_TX_F_BW_UPDATED     = 8,
 };
 
 enum bna_tx_mod_flags {
-       BNA_TX_MOD_F_PORT_STARTED       = 1,
-       BNA_TX_MOD_F_PORT_LOOPBACK      = 2,
+       BNA_TX_MOD_F_ENET_STARTED       = 1,
+       BNA_TX_MOD_F_ENET_LOOPBACK      = 2,
 };
 
 enum bna_rx_type {
@@ -165,80 +164,49 @@ enum bna_rxp_type {
 
 enum bna_rxmode {
        BNA_RXMODE_PROMISC      = 1,
-       BNA_RXMODE_ALLMULTI     = 2
+       BNA_RXMODE_DEFAULT      = 2,
+       BNA_RXMODE_ALLMULTI     = 4
 };
 
 enum bna_rx_event {
        RX_E_START                      = 1,
        RX_E_STOP                       = 2,
        RX_E_FAIL                       = 3,
-       RX_E_RXF_STARTED                = 4,
-       RX_E_RXF_STOPPED                = 5,
-       RX_E_RXQ_STOPPED                = 6,
-};
-
-enum bna_rx_state {
-       BNA_RX_STOPPED                  = 1,
-       BNA_RX_RXF_START_WAIT           = 2,
-       BNA_RX_STARTED                  = 3,
-       BNA_RX_RXF_STOP_WAIT            = 4,
-       BNA_RX_RXQ_STOP_WAIT            = 5,
+       RX_E_STARTED                    = 4,
+       RX_E_STOPPED                    = 5,
+       RX_E_RXF_STARTED                = 6,
+       RX_E_RXF_STOPPED                = 7,
+       RX_E_CLEANUP_DONE               = 8,
 };
 
 enum bna_rx_flags {
-       BNA_RX_F_ENABLE         = 0x01,         /* bnad enabled rxf */
-       BNA_RX_F_PORT_ENABLED   = 0x02,         /* Port object is enabled */
-       BNA_RX_F_PORT_FAILED    = 0x04,         /* Port in failed state */
+       BNA_RX_F_ENET_STARTED   = 1,
+       BNA_RX_F_ENABLED        = 2,
 };
 
 enum bna_rx_mod_flags {
-       BNA_RX_MOD_F_PORT_STARTED       = 1,
-       BNA_RX_MOD_F_PORT_LOOPBACK      = 2,
-};
-
-enum bna_rxf_oper_state {
-       BNA_RXF_OPER_STATE_RUNNING      = 0x01, /* rxf operational */
-       BNA_RXF_OPER_STATE_PAUSED       = 0x02, /* rxf in PAUSED state */
+       BNA_RX_MOD_F_ENET_STARTED       = 1,
+       BNA_RX_MOD_F_ENET_LOOPBACK      = 2,
 };
 
 enum bna_rxf_flags {
-       BNA_RXF_FL_STOP_PENDING         = 0x01,
-       BNA_RXF_FL_FAILED               = 0x02,
-       BNA_RXF_FL_RSS_CONFIG_PENDING   = 0x04,
-       BNA_RXF_FL_OPERSTATE_CHANGED    = 0x08,
-       BNA_RXF_FL_RXF_ENABLED          = 0x10,
-       BNA_RXF_FL_VLAN_CONFIG_PENDING  = 0x20,
+       BNA_RXF_F_PAUSED                = 1,
 };
 
 enum bna_rxf_event {
        RXF_E_START                     = 1,
        RXF_E_STOP                      = 2,
        RXF_E_FAIL                      = 3,
-       RXF_E_CAM_FLTR_MOD              = 4,
-       RXF_E_STARTED                   = 5,
-       RXF_E_STOPPED                   = 6,
-       RXF_E_CAM_FLTR_RESP             = 7,
-       RXF_E_PAUSE                     = 8,
-       RXF_E_RESUME                    = 9,
-       RXF_E_STAT_CLEARED              = 10,
-};
-
-enum bna_rxf_state {
-       BNA_RXF_STOPPED                 = 1,
-       BNA_RXF_START_WAIT              = 2,
-       BNA_RXF_CAM_FLTR_MOD_WAIT       = 3,
-       BNA_RXF_STARTED                 = 4,
-       BNA_RXF_CAM_FLTR_CLR_WAIT       = 5,
-       BNA_RXF_STOP_WAIT               = 6,
-       BNA_RXF_PAUSE_WAIT              = 7,
-       BNA_RXF_RESUME_WAIT             = 8,
-       BNA_RXF_STAT_CLR_WAIT           = 9,
+       RXF_E_CONFIG                    = 4,
+       RXF_E_PAUSE                     = 5,
+       RXF_E_RESUME                    = 6,
+       RXF_E_FW_RESP                   = 7,
 };
 
-enum bna_port_type {
-       BNA_PORT_T_REGULAR              = 0,
-       BNA_PORT_T_LOOPBACK_INTERNAL    = 1,
-       BNA_PORT_T_LOOPBACK_EXTERNAL    = 2,
+enum bna_enet_type {
+       BNA_ENET_T_REGULAR              = 0,
+       BNA_ENET_T_LOOPBACK_INTERNAL    = 1,
+       BNA_ENET_T_LOOPBACK_EXTERNAL    = 2,
 };
 
 enum bna_link_status {
@@ -247,17 +215,27 @@ enum bna_link_status {
        BNA_CEE_UP              = 2
 };
 
-enum bna_llport_flags {
-       BNA_LLPORT_F_ADMIN_UP           = 1,
-       BNA_LLPORT_F_PORT_ENABLED       = 2,
-       BNA_LLPORT_F_RX_STARTED         = 4
+enum bna_ethport_flags {
+       BNA_ETHPORT_F_ADMIN_UP          = 1,
+       BNA_ETHPORT_F_PORT_ENABLED      = 2,
+       BNA_ETHPORT_F_RX_STARTED        = 4,
 };
 
-enum bna_port_flags {
-       BNA_PORT_F_DEVICE_READY = 1,
-       BNA_PORT_F_ENABLED      = 2,
-       BNA_PORT_F_PAUSE_CHANGED = 4,
-       BNA_PORT_F_MTU_CHANGED  = 8
+enum bna_enet_flags {
+       BNA_ENET_F_IOCETH_READY         = 1,
+       BNA_ENET_F_ENABLED              = 2,
+       BNA_ENET_F_PAUSE_CHANGED        = 4,
+       BNA_ENET_F_MTU_CHANGED          = 8
+};
+
+enum bna_rss_flags {
+       BNA_RSS_F_RIT_PENDING           = 1,
+       BNA_RSS_F_CFG_PENDING           = 2,
+       BNA_RSS_F_STATUS_PENDING        = 4,
+};
+
+enum bna_mod_flags {
+       BNA_MOD_F_INIT_DONE             = 1,
 };
 
 enum bna_pkt_rates {
@@ -289,10 +267,17 @@ enum bna_dim_bias_types {
        BNA_BIAS_T_MAX                  = 2
 };
 
+#define BNA_MAX_NAME_SIZE      64
+struct bna_ident {
+       int                     id;
+       char                    name[BNA_MAX_NAME_SIZE];
+};
+
 struct bna_mac {
        /* This should be the first one */
        struct list_head                        qe;
        u8                      addr[ETH_ALEN];
+       struct bna_mcam_handle *handle;
 };
 
 struct bna_mem_descr {
@@ -338,23 +323,29 @@ struct bna_qpt {
        u32             page_size;
 };
 
+struct bna_attr {
+       int                     num_txq;
+       int                     num_rxp;
+       int                     num_ucmac;
+       int                     num_mcmac;
+       int                     max_rit_size;
+};
+
 /**
  *
- * Device
+ * IOCEth
  *
  */
 
-struct bna_device {
+struct bna_ioceth {
        bfa_fsm_t               fsm;
        struct bfa_ioc ioc;
 
-       enum bna_intr_type intr_type;
-       int                     vector;
+       struct bna_attr attr;
+       struct bfa_msgq_cmd_entry msgq_cmd;
+       struct bfi_enet_attr_req attr_req;
 
-       void (*ready_cbfn)(struct bnad *bnad, enum bna_cb_status status);
-       struct bnad *ready_cbarg;
-
-       void (*stop_cbfn)(struct bnad *bnad, enum bna_cb_status status);
+       void (*stop_cbfn)(struct bnad *bnad);
        struct bnad *stop_cbarg;
 
        struct bna *bna;
@@ -362,32 +353,7 @@ struct bna_device {
 
 /**
  *
- * Mail box
- *
- */
-
-struct bna_mbox_qe {
-       /* This should be the first one */
-       struct list_head                        qe;
-
-       struct bfa_mbox_cmd cmd;
-       u32             cmd_len;
-       /* Callback for port, tx, rx, rxf */
-       void (*cbfn)(void *arg, int status);
-       void                    *cbarg;
-};
-
-struct bna_mbox_mod {
-       enum bna_mbox_state state;
-       struct list_head                        posted_q;
-       u32             msg_pending;
-       u32             msg_ctr;
-       struct bna *bna;
-};
-
-/**
- *
- * Port
+ * Enet
  *
  */
 
@@ -397,50 +363,58 @@ struct bna_pause_config {
        enum bna_status rx_pause;
 };
 
-struct bna_llport {
+struct bna_enet {
        bfa_fsm_t               fsm;
-       enum bna_llport_flags flags;
+       enum bna_enet_flags flags;
 
-       enum bna_port_type type;
+       enum bna_enet_type type;
 
-       enum bna_link_status link_status;
+       struct bna_pause_config pause_config;
+       int                     mtu;
 
-       int                     rx_started_count;
+       /* Callback for bna_enet_disable(), enet_stop() */
+       void (*stop_cbfn)(void *);
+       void                    *stop_cbarg;
+
+       /* Callback for bna_enet_pause_config() */
+       void (*pause_cbfn)(struct bnad *);
+
+       /* Callback for bna_enet_mtu_set() */
+       void (*mtu_cbfn)(struct bnad *);
 
-       void (*stop_cbfn)(struct bna_port *, enum bna_cb_status);
+       struct bfa_wc           chld_stop_wc;
 
-       struct bna_mbox_qe mbox_qe;
+       struct bfa_msgq_cmd_entry msgq_cmd;
+       struct bfi_enet_set_pause_req pause_req;
 
        struct bna *bna;
 };
 
-struct bna_port {
-       bfa_fsm_t               fsm;
-       enum bna_port_flags flags;
-
-       enum bna_port_type type;
+/**
+ *
+ * Ethport
+ *
+ */
 
-       struct bna_llport llport;
+struct bna_ethport {
+       bfa_fsm_t               fsm;
+       enum bna_ethport_flags flags;
 
-       struct bna_pause_config pause_config;
-       u8                      priority;
-       int                     mtu;
+       enum bna_link_status link_status;
 
-       /* Callback for bna_port_disable(), port_stop() */
-       void (*stop_cbfn)(void *, enum bna_cb_status);
-       void                    *stop_cbarg;
+       int                     rx_started_count;
 
-       /* Callback for bna_port_pause_config() */
-       void (*pause_cbfn)(struct bnad *, enum bna_cb_status);
+       void (*stop_cbfn)(struct bna_enet *);
 
-       /* Callback for bna_port_mtu_set() */
-       void (*mtu_cbfn)(struct bnad *, enum bna_cb_status);
+       void (*adminup_cbfn)(struct bnad *, enum bna_cb_status);
 
        void (*link_cbfn)(struct bnad *, enum bna_link_status);
 
-       struct bfa_wc           chld_stop_wc;
-
-       struct bna_mbox_qe mbox_qe;
+       struct bfa_msgq_cmd_entry msgq_cmd;
+       union {
+               struct bfi_enet_enable_req admin_req;
+               struct bfi_enet_diag_lb_req lpbk_req;
+       } bfi_enet_cmd;
 
        struct bna *bna;
 };
@@ -451,82 +425,26 @@ struct bna_port {
  *
  */
 
-/* IB index segment structure */
-struct bna_ibidx_seg {
-       /* This should be the first one */
-       struct list_head                        qe;
-
-       u8                      ib_seg_size;
-       u8                      ib_idx_tbl_offset;
-};
-
-/* Interrupt structure */
-struct bna_intr {
-       /* This should be the first one */
-       struct list_head                        qe;
-       int                     ref_count;
-
-       enum bna_intr_type intr_type;
-       int                     vector;
-
-       struct bna_ib *ib;
-};
-
 /* Doorbell structure */
 struct bna_ib_dbell {
        void *__iomem doorbell_addr;
        u32             doorbell_ack;
 };
 
-/* Interrupt timer configuration */
-struct bna_ib_config {
-       u8              coalescing_timeo;    /* Unit is 5usec. */
-
-       int                     interpkt_count;
-       int                     interpkt_timeo;
-
-       enum ib_flags ctrl_flags;
-};
-
 /* IB structure */
 struct bna_ib {
-       /* This should be the first one */
-       struct list_head                        qe;
-
-       int                     ib_id;
-
-       int                     ref_count;
-       int                     start_count;
-
        struct bna_dma_addr ib_seg_host_addr;
        void            *ib_seg_host_addr_kva;
-       u32             idx_mask; /* Size >= BNA_IBIDX_MAX_SEGSIZE */
-
-       struct bna_ibidx_seg *idx_seg;
 
        struct bna_ib_dbell door_bell;
 
-       struct bna_intr *intr;
-
-       struct bna_ib_config ib_config;
-
-       struct bna *bna;
-};
-
-/* IB module - keeps track of IBs and interrupts */
-struct bna_ib_mod {
-       struct bna_ib *ib;              /* BFI_MAX_IB entries */
-       struct bna_intr *intr;          /* BFI_MAX_IB entries */
-       struct bna_ibidx_seg *idx_seg;  /* BNA_IBIDX_TOTAL_SEGS */
-
-       struct list_head                        ib_free_q;
-
-       struct list_head                ibidx_seg_pool[BFI_IBIDX_TOTAL_POOLS];
+       enum bna_intr_type      intr_type;
+       int                     intr_vector;
 
-       struct list_head                        intr_free_q;
-       struct list_head                        intr_active_q;
+       u8                      coalescing_timeo;    /* Unit is 5usec. */
 
-       struct bna *bna;
+       int                     interpkt_count;
+       int                     interpkt_timeo;
 };
 
 /**
@@ -552,6 +470,7 @@ struct bna_tcb {
        /* Control path */
        struct bna_txq *txq;
        struct bnad *bnad;
+       void                    *priv; /* BNAD's cookie */
        enum bna_intr_type intr_type;
        int                     intr_vector;
        u8                      priority; /* Current priority */
@@ -565,68 +484,66 @@ struct bna_txq {
        /* This should be the first one */
        struct list_head                        qe;
 
-       int                     txq_id;
-
        u8                      priority;
 
        struct bna_qpt qpt;
        struct bna_tcb *tcb;
-       struct bna_ib *ib;
-       int                     ib_seg_offset;
+       struct bna_ib ib;
 
        struct bna_tx *tx;
 
+       int                     hw_id;
+
        u64             tx_packets;
        u64             tx_bytes;
 };
 
-/* TxF structure (hardware Tx Function) */
-struct bna_txf {
-       int                     txf_id;
-       enum txf_flags ctrl_flags;
-       u16             vlan;
-};
-
 /* Tx object */
 struct bna_tx {
        /* This should be the first one */
        struct list_head                        qe;
+       int                     rid;
+       int                     hw_id;
 
        bfa_fsm_t               fsm;
        enum bna_tx_flags flags;
 
        enum bna_tx_type type;
+       int                     num_txq;
 
        struct list_head                        txq_q;
-       struct bna_txf txf;
+       u16                     txf_vlan_id;
 
        /* Tx event handlers */
        void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *);
        void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *);
-       void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *);
-       void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *);
-       void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *);
+       void (*tx_stall_cbfn)(struct bnad *, struct bna_tx *);
+       void (*tx_resume_cbfn)(struct bnad *, struct bna_tx *);
+       void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tx *);
 
        /* callback for bna_tx_disable(), bna_tx_stop() */
-       void (*stop_cbfn)(void *arg, struct bna_tx *tx,
-                               enum bna_cb_status status);
+       void (*stop_cbfn)(void *arg, struct bna_tx *tx);
        void                    *stop_cbarg;
 
        /* callback for bna_tx_prio_set() */
-       void (*prio_change_cbfn)(struct bnad *bnad, struct bna_tx *tx,
-                               enum bna_cb_status status);
-
-       struct bfa_wc           txq_stop_wc;
+       void (*prio_change_cbfn)(struct bnad *bnad, struct bna_tx *tx);
 
-       struct bna_mbox_qe mbox_qe;
+       struct bfa_msgq_cmd_entry msgq_cmd;
+       union {
+               struct bfi_enet_tx_cfg_req      cfg_req;
+               struct bfi_enet_req             req;
+               struct bfi_enet_tx_cfg_rsp      cfg_rsp;
+       } bfi_enet_cmd;
 
        struct bna *bna;
        void                    *priv;  /* bnad's cookie */
 };
 
+/* Tx object configuration used during creation */
 struct bna_tx_config {
        int                     num_txq;
        int                     txq_depth;
+       int                     coalescing_timeo;
        enum bna_tx_type tx_type;
 };
 
@@ -635,9 +552,9 @@ struct bna_tx_event_cbfn {
        void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *);
        void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *);
        /* Mandatory */
-       void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *);
-       void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *);
-       void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *);
+       void (*tx_stall_cbfn)(struct bnad *, struct bna_tx *);
+       void (*tx_resume_cbfn)(struct bnad *, struct bna_tx *);
+       void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tx *);
 };
 
 /* Tx module - keeps track of free, active tx objects */
@@ -651,55 +568,23 @@ struct bna_tx_mod {
        struct list_head                        txq_free_q;
 
        /* callback for bna_tx_mod_stop() */
-       void (*stop_cbfn)(struct bna_port *port,
-                               enum bna_cb_status status);
+       void (*stop_cbfn)(struct bna_enet *enet);
 
        struct bfa_wc           tx_stop_wc;
 
        enum bna_tx_mod_flags flags;
 
-       int                     priority;
-       int                     cee_link;
+       u8                      prio_map;
+       int                     default_prio;
+       int                     iscsi_over_cee;
+       int                     iscsi_prio;
+       int                     prio_reconfigured;
 
-       u32             txf_bmap[2];
+       u32                     rid_mask;
 
        struct bna *bna;
 };
 
-/**
- *
- * Receive Indirection Table
- *
- */
-
-/* One row of RIT table */
-struct bna_rit_entry {
-       u8 large_rxq_id;        /* used for either large or data buffers */
-       u8 small_rxq_id;        /* used for either small or header buffers */
-};
-
-/* RIT segment */
-struct bna_rit_segment {
-       struct list_head                        qe;
-
-       u32             rit_offset;
-       u32             rit_size;
-       /**
-        * max_rit_size: Varies per RIT segment depending on how RIT is
-        * partitioned
-        */
-       u32             max_rit_size;
-
-       struct bna_rit_entry *rit;
-};
-
-struct bna_rit_mod {
-       struct bna_rit_entry *rit;
-       struct bna_rit_segment *rit_segment;
-
-       struct list_head                rit_seg_pool[BFI_RIT_SEG_TOTAL_POOLS];
-};
-
 /**
  *
  * Rx object
@@ -719,8 +604,9 @@ struct bna_rcb {
        int                     page_count;
        /* Control path */
        struct bna_rxq *rxq;
-       struct bna_cq *cq;
+       struct bna_ccb *ccb;
        struct bnad *bnad;
+       void                    *priv; /* BNAD's cookie */
        unsigned long           flags;
        int                     id;
 };
@@ -728,7 +614,6 @@ struct bna_rcb {
 /* RxQ structure - QPT, configuration */
 struct bna_rxq {
        struct list_head                        qe;
-       int                     rxq_id;
 
        int                     buffer_size;
        int                     q_depth;
@@ -739,6 +624,8 @@ struct bna_rxq {
        struct bna_rxp *rxp;
        struct bna_rx *rx;
 
+       int                     hw_id;
+
        u64             rx_packets;
        u64             rx_bytes;
        u64             rx_packets_with_error;
@@ -784,6 +671,7 @@ struct bna_ccb {
        /* Control path */
        struct bna_cq *cq;
        struct bnad *bnad;
+       void                    *priv; /* BNAD's cookie */
        enum bna_intr_type intr_type;
        int                     intr_vector;
        u8                      rx_coalescing_timeo; /* For NAPI */
@@ -793,46 +681,43 @@ struct bna_ccb {
 
 /* CQ QPT, configuration  */
 struct bna_cq {
-       int                     cq_id;
-
        struct bna_qpt qpt;
        struct bna_ccb *ccb;
 
-       struct bna_ib *ib;
-       u8                      ib_seg_offset;
+       struct bna_ib ib;
 
        struct bna_rx *rx;
 };
 
 struct bna_rss_config {
-       enum rss_hash_type hash_type;
+       enum bfi_enet_rss_type  hash_type;
        u8                      hash_mask;
-       u32             toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN];
+       u32             toeplitz_hash_key[BFI_ENET_RSS_KEY_LEN];
 };
 
 struct bna_hds_config {
-       enum hds_header_type hdr_type;
-       int                     header_size;
+       enum bfi_enet_hds_type  hdr_type;
+       int                     forced_offset;
 };
 
-/* This structure is used during RX creation */
+/* Rx object configuration used during creation */
 struct bna_rx_config {
        enum bna_rx_type rx_type;
        int                     num_paths;
        enum bna_rxp_type rxp_type;
        int                     paused;
        int                     q_depth;
+       int                     coalescing_timeo;
        /*
         * Small/Large (or Header/Data) buffer size to be configured
         * for SLR and HDS queue type. Large buffer size comes from
-        * port->mtu.
+        * enet->mtu.
         */
        int                     small_buff_size;
 
        enum bna_status rss_status;
        struct bna_rss_config rss_config;
 
-       enum bna_status hds_status;
        struct bna_hds_config hds_config;
 
        enum bna_status vlan_strip_status;
@@ -851,51 +736,35 @@ struct bna_rxp {
 
        /* MSI-x vector number for configuring RSS */
        int                     vector;
-
-       struct bna_mbox_qe mbox_qe;
-};
-
-/* HDS configuration structure */
-struct bna_rxf_hds {
-       enum hds_header_type hdr_type;
-       int                     header_size;
-};
-
-/* RSS configuration structure */
-struct bna_rxf_rss {
-       enum rss_hash_type hash_type;
-       u8                      hash_mask;
-       u32             toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN];
+       int                     hw_id;
 };
 
 /* RxF structure (hardware Rx Function) */
 struct bna_rxf {
        bfa_fsm_t               fsm;
-       int                     rxf_id;
-       enum rxf_flags ctrl_flags;
-       u16             default_vlan_tag;
-       enum bna_rxf_oper_state rxf_oper_state;
-       enum bna_status hds_status;
-       struct bna_rxf_hds hds_cfg;
-       enum bna_status rss_status;
-       struct bna_rxf_rss rss_cfg;
-       struct bna_rit_segment *rit_segment;
-       struct bna_rx *rx;
-       u32             forced_offset;
-       struct bna_mbox_qe mbox_qe;
-       int                     mcast_rxq_id;
+       enum bna_rxf_flags flags;
+
+       struct bfa_msgq_cmd_entry msgq_cmd;
+       union {
+               struct bfi_enet_enable_req req;
+               struct bfi_enet_rss_cfg_req rss_req;
+               struct bfi_enet_rit_req rit_req;
+               struct bfi_enet_rx_vlan_req vlan_req;
+               struct bfi_enet_mcast_add_req mcast_add_req;
+               struct bfi_enet_mcast_del_req mcast_del_req;
+               struct bfi_enet_ucast_req ucast_req;
+       } bfi_enet_cmd;
 
        /* callback for bna_rxf_start() */
-       void (*start_cbfn) (struct bna_rx *rx, enum bna_cb_status status);
+       void (*start_cbfn) (struct bna_rx *rx);
        struct bna_rx *start_cbarg;
 
        /* callback for bna_rxf_stop() */
-       void (*stop_cbfn) (struct bna_rx *rx, enum bna_cb_status status);
+       void (*stop_cbfn) (struct bna_rx *rx);
        struct bna_rx *stop_cbarg;
 
-       /* callback for bna_rxf_receive_enable() / bna_rxf_receive_disable() */
-       void (*oper_state_cbfn) (struct bnad *bnad, struct bna_rx *rx,
-                       enum bna_cb_status status);
+       /* callback for bna_rx_receive_pause() / bna_rx_receive_resume() */
+       void (*oper_state_cbfn) (struct bnad *bnad, struct bna_rx *rx);
        struct bnad *oper_state_cbarg;
 
        /**
@@ -905,25 +774,25 @@ struct bna_rxf {
         *      bna_rxf_{ucast/mcast}_del(),
         *      bna_rxf_mode_set()
         */
-       void (*cam_fltr_cbfn)(struct bnad *bnad, struct bna_rx *rx,
-                               enum bna_cb_status status);
+       void (*cam_fltr_cbfn)(struct bnad *bnad, struct bna_rx *rx);
        struct bnad *cam_fltr_cbarg;
 
-       enum bna_rxf_flags rxf_flags;
-
        /* List of unicast addresses yet to be applied to h/w */
        struct list_head                        ucast_pending_add_q;
        struct list_head                        ucast_pending_del_q;
+       struct bna_mac *ucast_pending_mac;
        int                     ucast_pending_set;
        /* ucast addresses applied to the h/w */
        struct list_head                        ucast_active_q;
-       struct bna_mac *ucast_active_mac;
+       struct bna_mac ucast_active_mac;
+       int                     ucast_active_set;
 
        /* List of multicast addresses yet to be applied to h/w */
        struct list_head                        mcast_pending_add_q;
        struct list_head                        mcast_pending_del_q;
        /* multicast addresses applied to the h/w */
        struct list_head                        mcast_active_q;
+       struct list_head                        mcast_handle_q;
 
        /* Rx modes yet to be applied to h/w */
        enum bna_rxmode rxmode_pending;
@@ -931,41 +800,58 @@ struct bna_rxf {
        /* Rx modes applied to h/w */
        enum bna_rxmode rxmode_active;
 
+       u8                      vlan_pending_bitmask;
        enum bna_status vlan_filter_status;
-       u32             vlan_filter_table[(BFI_MAX_VLAN + 1) / 32];
+       u32     vlan_filter_table[(BFI_ENET_VLAN_ID_MAX) / 32];
+       bool                    vlan_strip_pending;
+       enum bna_status         vlan_strip_status;
+
+       enum bna_rss_flags      rss_pending;
+       enum bna_status         rss_status;
+       struct bna_rss_config   rss_cfg;
+       u8                      *rit;
+       int                     rit_size;
+
+       struct bna_rx           *rx;
 };
 
 /* Rx object */
 struct bna_rx {
        /* This should be the first one */
        struct list_head                        qe;
+       int                     rid;
+       int                     hw_id;
 
        bfa_fsm_t               fsm;
 
        enum bna_rx_type type;
 
-       /* list-head for RX path objects */
+       int                     num_paths;
        struct list_head                        rxp_q;
 
+       struct bna_hds_config   hds_cfg;
+
        struct bna_rxf rxf;
 
        enum bna_rx_flags rx_flags;
 
-       struct bna_mbox_qe mbox_qe;
-
-       struct bfa_wc           rxq_stop_wc;
+       struct bfa_msgq_cmd_entry msgq_cmd;
+       union {
+               struct bfi_enet_rx_cfg_req      cfg_req;
+               struct bfi_enet_req             req;
+               struct bfi_enet_rx_cfg_rsp      cfg_rsp;
+       } bfi_enet_cmd;
 
        /* Rx event handlers */
        void (*rcb_setup_cbfn)(struct bnad *, struct bna_rcb *);
        void (*rcb_destroy_cbfn)(struct bnad *, struct bna_rcb *);
        void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *);
        void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *);
-       void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *);
-       void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *);
+       void (*rx_cleanup_cbfn)(struct bnad *, struct bna_rx *);
+       void (*rx_post_cbfn)(struct bnad *, struct bna_rx *);
 
        /* callback for bna_rx_disable(), bna_rx_stop() */
-       void (*stop_cbfn)(void *arg, struct bna_rx *rx,
-                               enum bna_cb_status status);
+       void (*stop_cbfn)(void *arg, struct bna_rx *rx);
        void                    *stop_cbarg;
 
        struct bna *bna;
@@ -979,8 +865,8 @@ struct bna_rx_event_cbfn {
        void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *);
        void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *);
        /* Mandatory */
-       void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *);
-       void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *);
+       void (*rx_cleanup_cbfn)(struct bnad *, struct bna_rx *);
+       void (*rx_post_cbfn)(struct bnad *, struct bna_rx *);
 };
 
 /* Rx module - keeps track of free, active rx objects */
@@ -1003,12 +889,11 @@ struct bna_rx_mod {
        enum bna_rx_mod_flags flags;
 
        /* callback for bna_rx_mod_stop() */
-       void (*stop_cbfn)(struct bna_port *port,
-                               enum bna_cb_status status);
+       void (*stop_cbfn)(struct bna_enet *enet);
 
        struct bfa_wc           rx_stop_wc;
        u32             dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX];
-       u32             rxf_bmap[2];
+       u32             rid_mask;
 };
 
 /**
@@ -1024,9 +909,18 @@ struct bna_ucam_mod {
        struct bna *bna;
 };
 
+struct bna_mcam_handle {
+       /* This should be the first one */
+       struct list_head                        qe;
+       int                     handle;
+       int                     refcnt;
+};
+
 struct bna_mcam_mod {
        struct bna_mac *mcmac;          /* BFI_MAX_MCMAC entries */
+       struct bna_mcam_handle *mchandle;       /* BFI_MAX_MCMAC entries */
        struct list_head                        free_q;
+       struct list_head                        free_handle_q;
 
        struct bna *bna;
 };
@@ -1037,50 +931,20 @@ struct bna_mcam_mod {
  *
  */
 
-struct bna_tx_stats {
-       int                     tx_state;
-       int                     tx_flags;
-       int                     num_txqs;
-       u32             txq_bmap[2];
-       int                     txf_id;
-};
-
-struct bna_rx_stats {
-       int                     rx_state;
-       int                     rx_flags;
-       int                     num_rxps;
-       int                     num_rxqs;
-       u32             rxq_bmap[2];
-       u32             cq_bmap[2];
-       int                     rxf_id;
-       int                     rxf_state;
-       int                     rxf_oper_state;
-       int                     num_active_ucast;
-       int                     num_active_mcast;
-       int                     rxmode_active;
-       int                     vlan_filter_status;
-       u32             vlan_filter_table[(BFI_MAX_VLAN + 1) / 32];
-       int                     rss_status;
-       int                     hds_status;
-};
-
-struct bna_sw_stats {
-       int                     device_state;
-       int                     port_state;
-       int                     port_flags;
-       int                     llport_state;
-       int                     priority;
-       int                     num_active_tx;
-       int                     num_active_rx;
-       struct bna_tx_stats tx_stats[BFI_MAX_TXQ];
-       struct bna_rx_stats rx_stats[BFI_MAX_RXQ];
+struct bna_stats {
+       struct bna_dma_addr     hw_stats_dma;
+       struct bfi_enet_stats   *hw_stats_kva;
+       struct bfi_enet_stats   hw_stats;
 };
 
-struct bna_stats {
-       u32             txf_bmap[2];
-       u32             rxf_bmap[2];
-       struct bfi_ll_stats     *hw_stats;
-       struct bna_sw_stats *sw_stats;
+struct bna_stats_mod {
+       bool            ioc_ready;
+       bool            stats_get_busy;
+       bool            stats_clr_busy;
+       struct bfa_msgq_cmd_entry stats_get_cmd;
+       struct bfa_msgq_cmd_entry stats_clr_cmd;
+       struct bfi_enet_stats_req stats_get;
+       struct bfi_enet_stats_req stats_clr;
 };
 
 /**
@@ -1090,38 +954,32 @@ struct bna_stats {
  */
 
 struct bna {
+       struct bna_ident ident;
        struct bfa_pcidev pcidev;
 
-       int                     port_num;
-
-       struct bna_chip_regs regs;
+       struct bna_reg regs;
+       struct bna_bit_defn bits;
 
-       struct bna_dma_addr hw_stats_dma;
        struct bna_stats stats;
 
-       struct bna_device device;
+       struct bna_ioceth ioceth;
        struct bfa_cee cee;
+       struct bfa_msgq msgq;
 
-       struct bna_mbox_mod mbox_mod;
-
-       struct bna_port port;
+       struct bna_ethport ethport;
+       struct bna_enet enet;
+       struct bna_stats_mod stats_mod;
 
        struct bna_tx_mod tx_mod;
-
        struct bna_rx_mod rx_mod;
-
-       struct bna_ib_mod ib_mod;
-
        struct bna_ucam_mod ucam_mod;
        struct bna_mcam_mod mcam_mod;
 
-       struct bna_rit_mod rit_mod;
+       enum bna_mod_flags mod_flags;
 
-       int                     rxf_promisc_id;
-
-       struct bna_mbox_qe mbox_qe;
+       int                     default_mode_rid;
+       int                     promisc_rid;
 
        struct bnad *bnad;
 };
-
 #endif /* __BNA_TYPES_H__ */
similarity index 85%
rename from drivers/net/bna/bnad.c
rename to drivers/net/ethernet/brocade/bna/bnad.c
index 8e35b25..6ad4b47 100644 (file)
@@ -441,11 +441,15 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
        struct bnad_skb_unmap *unmap_array;
        struct sk_buff *skb;
        u32 flags, unmap_cons;
-       u32 qid0 = ccb->rcb[0]->rxq->rxq_id;
        struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
+       struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
+
+       set_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
 
-       if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))
+       if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)) {
+               clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
                return 0;
+       }
 
        prefetch(bnad->netdev);
        BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl,
@@ -455,10 +459,10 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
                packets++;
                BNA_UPDATE_PKT_CNT(pkt_rt, ntohs(cmpl->length));
 
-               if (qid0 == cmpl->rxq_id)
-                       rcb = ccb->rcb[0];
-               else
+               if (bna_is_small_rxq(cmpl->rxq_id))
                        rcb = ccb->rcb[1];
+               else
+                       rcb = ccb->rcb[0];
 
                unmap_q = rcb->unmap_q;
                unmap_array = unmap_q->unmap_array;
@@ -518,12 +522,9 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
                if (flags & BNA_CQ_EF_VLAN)
                        __vlan_hwaccel_put_tag(skb, ntohs(cmpl->vlan_tag));
 
-               if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
-                       struct bnad_rx_ctrl *rx_ctrl;
-
-                       rx_ctrl = (struct bnad_rx_ctrl *) ccb->ctrl;
+               if (skb->ip_summed == CHECKSUM_UNNECESSARY)
                        napi_gro_receive(&rx_ctrl->napi, skb);
-               else {
+               else {
                        netif_receive_skb(skb);
                }
 
@@ -545,6 +546,8 @@ next:
                        bna_ib_ack(ccb->i_dbell, 0);
        }
 
+       clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
+
        return packets;
 }
 
@@ -611,7 +614,7 @@ bnad_msix_mbox_handler(int irq, void *data)
 
        bna_intr_status_get(&bnad->bna, intr_status);
 
-       if (BNA_IS_MBOX_ERR_INTR(intr_status))
+       if (BNA_IS_MBOX_ERR_INTR(&bnad->bna, intr_status))
                bna_mbox_handler(&bnad->bna, intr_status);
 
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -628,6 +631,7 @@ bnad_isr(int irq, void *data)
        struct bnad *bnad = (struct bnad *)data;
        struct bnad_rx_info *rx_info;
        struct bnad_rx_ctrl *rx_ctrl;
+       struct bna_tcb *tcb = NULL;
 
        if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
                return IRQ_NONE;
@@ -639,7 +643,7 @@ bnad_isr(int irq, void *data)
 
        spin_lock_irqsave(&bnad->bna_lock, flags);
 
-       if (BNA_IS_MBOX_ERR_INTR(intr_status))
+       if (BNA_IS_MBOX_ERR_INTR(&bnad->bna, intr_status))
                bna_mbox_handler(&bnad->bna, intr_status);
 
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -650,8 +654,11 @@ bnad_isr(int irq, void *data)
        /* Process data interrupts */
        /* Tx processing */
        for (i = 0; i < bnad->num_tx; i++) {
-               for (j = 0; j < bnad->num_txq_per_tx; j++)
-                       bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+               for (j = 0; j < bnad->num_txq_per_tx; j++) {
+                       tcb = bnad->tx_info[i].tcb[j];
+                       if (tcb && test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
+                               bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+               }
        }
        /* Rx processing */
        for (i = 0; i < bnad->num_rx; i++) {
@@ -706,43 +713,49 @@ bnad_set_netdev_perm_addr(struct bnad *bnad)
 
 /* Callbacks */
 void
-bnad_cb_device_enable_mbox_intr(struct bnad *bnad)
+bnad_cb_mbox_intr_enable(struct bnad *bnad)
 {
        bnad_enable_mbox_irq(bnad);
 }
 
 void
-bnad_cb_device_disable_mbox_intr(struct bnad *bnad)
+bnad_cb_mbox_intr_disable(struct bnad *bnad)
 {
        bnad_disable_mbox_irq(bnad);
 }
 
 void
-bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status)
+bnad_cb_ioceth_ready(struct bnad *bnad)
+{
+       bnad->bnad_completions.ioc_comp_status = BNA_CB_SUCCESS;
+       complete(&bnad->bnad_completions.ioc_comp);
+}
+
+void
+bnad_cb_ioceth_failed(struct bnad *bnad)
 {
+       bnad->bnad_completions.ioc_comp_status = BNA_CB_FAIL;
        complete(&bnad->bnad_completions.ioc_comp);
-       bnad->bnad_completions.ioc_comp_status = status;
 }
 
 void
-bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status)
+bnad_cb_ioceth_disabled(struct bnad *bnad)
 {
+       bnad->bnad_completions.ioc_comp_status = BNA_CB_SUCCESS;
        complete(&bnad->bnad_completions.ioc_comp);
-       bnad->bnad_completions.ioc_comp_status = status;
 }
 
 static void
-bnad_cb_port_disabled(void *arg, enum bna_cb_status status)
+bnad_cb_enet_disabled(void *arg)
 {
        struct bnad *bnad = (struct bnad *)arg;
 
-       complete(&bnad->bnad_completions.port_comp);
-
        netif_carrier_off(bnad->netdev);
+       complete(&bnad->bnad_completions.enet_comp);
 }
 
 void
-bnad_cb_port_link_status(struct bnad *bnad,
+bnad_cb_ethport_link_status(struct bnad *bnad,
                        enum bna_link_status link_status)
 {
        bool link_up = 0;
@@ -750,34 +763,60 @@ bnad_cb_port_link_status(struct bnad *bnad,
        link_up = (link_status == BNA_LINK_UP) || (link_status == BNA_CEE_UP);
 
        if (link_status == BNA_CEE_UP) {
+               if (!test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags))
+                       BNAD_UPDATE_CTR(bnad, cee_toggle);
                set_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags);
-               BNAD_UPDATE_CTR(bnad, cee_up);
-       } else
+       } else {
+               if (test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags))
+                       BNAD_UPDATE_CTR(bnad, cee_toggle);
                clear_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags);
+       }
 
        if (link_up) {
                if (!netif_carrier_ok(bnad->netdev)) {
-                       struct bna_tcb *tcb = bnad->tx_info[0].tcb[0];
-                       if (!tcb)
-                               return;
-                       pr_warn("bna: %s link up\n",
+                       uint tx_id, tcb_id;
+                       printk(KERN_WARNING "bna: %s link up\n",
                                bnad->netdev->name);
                        netif_carrier_on(bnad->netdev);
                        BNAD_UPDATE_CTR(bnad, link_toggle);
-                       if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) {
-                               /* Force an immediate Transmit Schedule */
-                               pr_info("bna: %s TX_STARTED\n",
-                                       bnad->netdev->name);
-                               netif_wake_queue(bnad->netdev);
-                               BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
-                       } else {
-                               netif_stop_queue(bnad->netdev);
-                               BNAD_UPDATE_CTR(bnad, netif_queue_stop);
+                       for (tx_id = 0; tx_id < bnad->num_tx; tx_id++) {
+                               for (tcb_id = 0; tcb_id < bnad->num_txq_per_tx;
+                                     tcb_id++) {
+                                       struct bna_tcb *tcb =
+                                       bnad->tx_info[tx_id].tcb[tcb_id];
+                                       u32 txq_id;
+                                       if (!tcb)
+                                               continue;
+
+                                       txq_id = tcb->id;
+
+                                       if (test_bit(BNAD_TXQ_TX_STARTED,
+                                                    &tcb->flags)) {
+                                               /*
+                                                * Force an immediate
+                                                * Transmit Schedule */
+                                               printk(KERN_INFO "bna: %s %d "
+                                                     "TXQ_STARTED\n",
+                                                      bnad->netdev->name,
+                                                      txq_id);
+                                               netif_wake_subqueue(
+                                                               bnad->netdev,
+                                                               txq_id);
+                                               BNAD_UPDATE_CTR(bnad,
+                                                       netif_queue_wakeup);
+                                       } else {
+                                               netif_stop_subqueue(
+                                                               bnad->netdev,
+                                                               txq_id);
+                                               BNAD_UPDATE_CTR(bnad,
+                                                       netif_queue_stop);
+                                       }
+                               }
                        }
                }
        } else {
                if (netif_carrier_ok(bnad->netdev)) {
-                       pr_warn("bna: %s link down\n",
+                       printk(KERN_WARNING "bna: %s link down\n",
                                bnad->netdev->name);
                        netif_carrier_off(bnad->netdev);
                        BNAD_UPDATE_CTR(bnad, link_toggle);
@@ -786,8 +825,7 @@ bnad_cb_port_link_status(struct bnad *bnad,
 }
 
 static void
-bnad_cb_tx_disabled(void *arg, struct bna_tx *tx,
-                       enum bna_cb_status status)
+bnad_cb_tx_disabled(void *arg, struct bna_tx *tx)
 {
        struct bnad *bnad = (struct bnad *)arg;
 
@@ -864,108 +902,166 @@ bnad_cb_ccb_destroy(struct bnad *bnad, struct bna_ccb *ccb)
 }
 
 static void
-bnad_cb_tx_stall(struct bnad *bnad, struct bna_tcb *tcb)
+bnad_cb_tx_stall(struct bnad *bnad, struct bna_tx *tx)
 {
        struct bnad_tx_info *tx_info =
-                       (struct bnad_tx_info *)tcb->txq->tx->priv;
-
-       if (tx_info != &bnad->tx_info[0])
-               return;
+                       (struct bnad_tx_info *)tx->priv;
+       struct bna_tcb *tcb;
+       u32 txq_id;
+       int i;
 
-       clear_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
-       netif_stop_queue(bnad->netdev);
-       pr_info("bna: %s TX_STOPPED\n", bnad->netdev->name);
+       for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) {
+               tcb = tx_info->tcb[i];
+               if (!tcb)
+                       continue;
+               txq_id = tcb->id;
+               clear_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
+               netif_stop_subqueue(bnad->netdev, txq_id);
+               printk(KERN_INFO "bna: %s %d TXQ_STOPPED\n",
+                       bnad->netdev->name, txq_id);
+       }
 }
 
 static void
-bnad_cb_tx_resume(struct bnad *bnad, struct bna_tcb *tcb)
+bnad_cb_tx_resume(struct bnad *bnad, struct bna_tx *tx)
 {
-       struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+       struct bnad_tx_info *tx_info = (struct bnad_tx_info *)tx->priv;
+       struct bna_tcb *tcb;
+       struct bnad_unmap_q *unmap_q;
+       u32 txq_id;
+       int i;
 
-       if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
-               return;
+       for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) {
+               tcb = tx_info->tcb[i];
+               if (!tcb)
+                       continue;
+               txq_id = tcb->id;
 
-       clear_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags);
+               unmap_q = tcb->unmap_q;
 
-       while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
-               cpu_relax();
+               if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
+                       continue;
 
-       bnad_free_all_txbufs(bnad, tcb);
+               while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
+                       cpu_relax();
 
-       unmap_q->producer_index = 0;
-       unmap_q->consumer_index = 0;
+               bnad_free_all_txbufs(bnad, tcb);
 
-       smp_mb__before_clear_bit();
-       clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+               unmap_q->producer_index = 0;
+               unmap_q->consumer_index = 0;
+
+               smp_mb__before_clear_bit();
+               clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+
+               set_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
+
+               if (netif_carrier_ok(bnad->netdev)) {
+                       printk(KERN_INFO "bna: %s %d TXQ_STARTED\n",
+                               bnad->netdev->name, txq_id);
+                       netif_wake_subqueue(bnad->netdev, txq_id);
+                       BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+               }
+       }
 
        /*
-        * Workaround for first device enable failure & we
+        * Workaround for first ioceth enable failure & we
         * get a 0 MAC address. We try to get the MAC address
         * again here.
         */
        if (is_zero_ether_addr(&bnad->perm_addr.mac[0])) {
-               bna_port_mac_get(&bnad->bna.port, &bnad->perm_addr);
+               bna_enet_perm_mac_get(&bnad->bna.enet, &bnad->perm_addr);
                bnad_set_netdev_perm_addr(bnad);
        }
-
-       set_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
-
-       if (netif_carrier_ok(bnad->netdev)) {
-               pr_info("bna: %s TX_STARTED\n", bnad->netdev->name);
-               netif_wake_queue(bnad->netdev);
-               BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
-       }
 }
 
 static void
-bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
+bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tx *tx)
 {
-       /* Delay only once for the whole Tx Path Shutdown */
-       if (!test_and_set_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags))
-               mdelay(BNAD_TXRX_SYNC_MDELAY);
+       struct bnad_tx_info *tx_info = (struct bnad_tx_info *)tx->priv;
+       struct bna_tcb *tcb;
+       int i;
+
+       for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) {
+               tcb = tx_info->tcb[i];
+               if (!tcb)
+                       continue;
+       }
+
+       mdelay(BNAD_TXRX_SYNC_MDELAY);
+       bna_tx_cleanup_complete(tx);
 }
 
 static void
-bnad_cb_rx_cleanup(struct bnad *bnad,
-                       struct bna_ccb *ccb)
+bnad_cb_rx_cleanup(struct bnad *bnad, struct bna_rx *rx)
 {
-       clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags);
+       struct bnad_rx_info *rx_info = (struct bnad_rx_info *)rx->priv;
+       struct bna_ccb *ccb;
+       struct bnad_rx_ctrl *rx_ctrl;
+       int i;
+
+       mdelay(BNAD_TXRX_SYNC_MDELAY);
+
+       for (i = 0; i < BNAD_MAX_RXPS_PER_RX; i++) {
+               rx_ctrl = &rx_info->rx_ctrl[i];
+               ccb = rx_ctrl->ccb;
+               if (!ccb)
+                       continue;
+
+               clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags);
 
-       if (ccb->rcb[1])
-               clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags);
+               if (ccb->rcb[1])
+                       clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags);
+
+               while (test_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags))
+                       cpu_relax();
+       }
 
-       if (!test_and_set_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags))
-               mdelay(BNAD_TXRX_SYNC_MDELAY);
+       bna_rx_cleanup_complete(rx);
 }
 
 static void
-bnad_cb_rx_post(struct bnad *bnad, struct bna_rcb *rcb)
+bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx)
 {
-       struct bnad_unmap_q *unmap_q = rcb->unmap_q;
-
-       clear_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags);
-
-       if (rcb == rcb->cq->ccb->rcb[0])
-               bnad_cq_cmpl_init(bnad, rcb->cq->ccb);
+       struct bnad_rx_info *rx_info = (struct bnad_rx_info *)rx->priv;
+       struct bna_ccb *ccb;
+       struct bna_rcb *rcb;
+       struct bnad_rx_ctrl *rx_ctrl;
+       struct bnad_unmap_q *unmap_q;
+       int i;
+       int j;
 
-       bnad_free_all_rxbufs(bnad, rcb);
+       for (i = 0; i < BNAD_MAX_RXPS_PER_RX; i++) {
+               rx_ctrl = &rx_info->rx_ctrl[i];
+               ccb = rx_ctrl->ccb;
+               if (!ccb)
+                       continue;
 
-       set_bit(BNAD_RXQ_STARTED, &rcb->flags);
+               bnad_cq_cmpl_init(bnad, ccb);
 
-       /* Now allocate & post buffers for this RCB */
-       /* !!Allocation in callback context */
-       if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
-               if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
-                        >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
-                       bnad_alloc_n_post_rxbufs(bnad, rcb);
-               smp_mb__before_clear_bit();
-               clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
+               for (j = 0; j < BNAD_MAX_RXQ_PER_RXP; j++) {
+                       rcb = ccb->rcb[j];
+                       if (!rcb)
+                               continue;
+                       bnad_free_all_rxbufs(bnad, rcb);
+
+                       set_bit(BNAD_RXQ_STARTED, &rcb->flags);
+                       unmap_q = rcb->unmap_q;
+
+                       /* Now allocate & post buffers for this RCB */
+                       /* !!Allocation in callback context */
+                       if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
+                               if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
+                                       >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
+                                       bnad_alloc_n_post_rxbufs(bnad, rcb);
+                                       smp_mb__before_clear_bit();
+                               clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
+                       }
+               }
        }
 }
 
 static void
-bnad_cb_rx_disabled(void *arg, struct bna_rx *rx,
-                       enum bna_cb_status status)
+bnad_cb_rx_disabled(void *arg, struct bna_rx *rx)
 {
        struct bnad *bnad = (struct bnad *)arg;
 
@@ -973,10 +1069,9 @@ bnad_cb_rx_disabled(void *arg, struct bna_rx *rx,
 }
 
 static void
-bnad_cb_rx_mcast_add(struct bnad *bnad, struct bna_rx *rx,
-                               enum bna_cb_status status)
+bnad_cb_rx_mcast_add(struct bnad *bnad, struct bna_rx *rx)
 {
-       bnad->bnad_completions.mcast_comp_status = status;
+       bnad->bnad_completions.mcast_comp_status = BNA_CB_SUCCESS;
        complete(&bnad->bnad_completions.mcast_comp);
 }
 
@@ -995,6 +1090,13 @@ bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status,
                  jiffies + msecs_to_jiffies(BNAD_STATS_TIMER_FREQ));
 }
 
+static void
+bnad_cb_enet_mtu_set(struct bnad *bnad)
+{
+       bnad->bnad_completions.mtu_comp_status = BNA_CB_SUCCESS;
+       complete(&bnad->bnad_completions.mtu_comp);
+}
+
 /* Resource allocation, free functions */
 
 static void
@@ -1073,23 +1175,17 @@ err_return:
 
 /* Free IRQ for Mailbox */
 static void
-bnad_mbox_irq_free(struct bnad *bnad,
-                  struct bna_intr_info *intr_info)
+bnad_mbox_irq_free(struct bnad *bnad)
 {
        int irq;
        unsigned long flags;
 
-       if (intr_info->idl == NULL)
-               return;
-
        spin_lock_irqsave(&bnad->bna_lock, flags);
        bnad_disable_mbox_irq(bnad);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
        irq = BNAD_GET_MBOX_IRQ(bnad);
        free_irq(irq, bnad);
-
-       kfree(intr_info->idl);
 }
 
 /*
@@ -1098,32 +1194,22 @@ bnad_mbox_irq_free(struct bnad *bnad,
  * from bna
  */
 static int
-bnad_mbox_irq_alloc(struct bnad *bnad,
-                   struct bna_intr_info *intr_info)
+bnad_mbox_irq_alloc(struct bnad *bnad)
 {
        int             err = 0;
        unsigned long   irq_flags, flags;
        u32     irq;
        irq_handler_t   irq_handler;
 
-       /* Mbox should use only 1 vector */
-
-       intr_info->idl = kzalloc(sizeof(*(intr_info->idl)), GFP_KERNEL);
-       if (!intr_info->idl)
-               return -ENOMEM;
-
        spin_lock_irqsave(&bnad->bna_lock, flags);
        if (bnad->cfg_flags & BNAD_CF_MSIX) {
                irq_handler = (irq_handler_t)bnad_msix_mbox_handler;
                irq = bnad->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector;
                irq_flags = 0;
-               intr_info->intr_type = BNA_INTR_T_MSIX;
-               intr_info->idl[0].vector = BNAD_MAILBOX_MSIX_INDEX;
        } else {
                irq_handler = (irq_handler_t)bnad_isr;
                irq = bnad->pcidev->irq;
                irq_flags = IRQF_SHARED;
-               intr_info->intr_type = BNA_INTR_T_INTX;
        }
 
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -1140,11 +1226,6 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
        err = request_irq(irq, irq_handler, irq_flags,
                          bnad->mbox_irq_name, bnad);
 
-       if (err) {
-               kfree(intr_info->idl);
-               intr_info->idl = NULL;
-       }
-
        return err;
 }
 
@@ -1158,7 +1239,7 @@ bnad_txrx_irq_free(struct bnad *bnad, struct bna_intr_info *intr_info)
 /* Allocates Interrupt Descriptor List for MSIX/INT-X vectors */
 static int
 bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
-                   uint txrx_id, struct bna_intr_info *intr_info)
+                   u32 txrx_id, struct bna_intr_info *intr_info)
 {
        int i, vector_start = 0;
        u32 cfg_flags;
@@ -1241,7 +1322,7 @@ bnad_tx_msix_unregister(struct bnad *bnad, struct bnad_tx_info *tx_info,
  */
 static int
 bnad_tx_msix_register(struct bnad *bnad, struct bnad_tx_info *tx_info,
-                       uint tx_id, int num_txqs)
+                       u32 tx_id, int num_txqs)
 {
        int i;
        int err;
@@ -1294,7 +1375,7 @@ bnad_rx_msix_unregister(struct bnad *bnad, struct bnad_rx_info *rx_info,
  */
 static int
 bnad_rx_msix_register(struct bnad *bnad, struct bnad_rx_info *rx_info,
-                       uint rx_id, int num_rxps)
+                       u32 rx_id, int num_rxps)
 {
        int i;
        int err;
@@ -1338,7 +1419,7 @@ bnad_tx_res_free(struct bnad *bnad, struct bna_res_info *res_info)
 /* Allocates memory and interrupt resources for Tx object */
 static int
 bnad_tx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
-                 uint tx_id)
+                 u32 tx_id)
 {
        int i, err = 0;
 
@@ -1407,7 +1488,7 @@ bnad_ioc_timeout(unsigned long data)
        unsigned long flags;
 
        spin_lock_irqsave(&bnad->bna_lock, flags);
-       bfa_nw_ioc_timeout((void *) &bnad->bna.device.ioc);
+       bfa_nw_ioc_timeout((void *) &bnad->bna.ioceth.ioc);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 }
 
@@ -1418,7 +1499,7 @@ bnad_ioc_hb_check(unsigned long data)
        unsigned long flags;
 
        spin_lock_irqsave(&bnad->bna_lock, flags);
-       bfa_nw_ioc_hb_check((void *) &bnad->bna.device.ioc);
+       bfa_nw_ioc_hb_check((void *) &bnad->bna.ioceth.ioc);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 }
 
@@ -1429,7 +1510,7 @@ bnad_iocpf_timeout(unsigned long data)
        unsigned long flags;
 
        spin_lock_irqsave(&bnad->bna_lock, flags);
-       bfa_nw_iocpf_timeout((void *) &bnad->bna.device.ioc);
+       bfa_nw_iocpf_timeout((void *) &bnad->bna.ioceth.ioc);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 }
 
@@ -1440,7 +1521,7 @@ bnad_iocpf_sem_timeout(unsigned long data)
        unsigned long flags;
 
        spin_lock_irqsave(&bnad->bna_lock, flags);
-       bfa_nw_iocpf_sem_timeout((void *) &bnad->bna.device.ioc);
+       bfa_nw_iocpf_sem_timeout((void *) &bnad->bna.ioceth.ioc);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 }
 
@@ -1499,7 +1580,7 @@ bnad_stats_timeout(unsigned long data)
                return;
 
        spin_lock_irqsave(&bnad->bna_lock, flags);
-       bna_stats_get(&bnad->bna);
+       bna_hw_stats_get(&bnad->bna);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 }
 
@@ -1632,7 +1713,7 @@ bnad_napi_disable(struct bnad *bnad, u32 rx_id)
 
 /* Should be held with conf_lock held */
 void
-bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
+bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
 {
        struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
        struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0];
@@ -1656,6 +1737,7 @@ bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
        tx_info->tx = NULL;
+       tx_info->tx_id = 0;
 
        if (0 == tx_id)
                tasklet_kill(&bnad->tx_free_tasklet);
@@ -1665,7 +1747,7 @@ bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
 
 /* Should be held with conf_lock held */
 int
-bnad_setup_tx(struct bnad *bnad, uint tx_id)
+bnad_setup_tx(struct bnad *bnad, u32 tx_id)
 {
        int err;
        struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
@@ -1677,10 +1759,13 @@ bnad_setup_tx(struct bnad *bnad, uint tx_id)
        struct bna_tx *tx;
        unsigned long flags;
 
+       tx_info->tx_id = tx_id;
+
        /* Initialize the Tx object configuration */
        tx_config->num_txq = bnad->num_txq_per_tx;
        tx_config->txq_depth = bnad->txq_depth;
        tx_config->tx_type = BNA_TX_T_REGULAR;
+       tx_config->coalescing_timeo = bnad->tx_coalescing_timeo;
 
        /* Initialize the tx event handlers */
        tx_cbfn.tcb_setup_cbfn = bnad_cb_tcb_setup;
@@ -1741,14 +1826,15 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
 {
        rx_config->rx_type = BNA_RX_T_REGULAR;
        rx_config->num_paths = bnad->num_rxp_per_rx;
+       rx_config->coalescing_timeo = bnad->rx_coalescing_timeo;
 
        if (bnad->num_rxp_per_rx > 1) {
                rx_config->rss_status = BNA_STATUS_T_ENABLED;
                rx_config->rss_config.hash_type =
-                               (BFI_RSS_T_V4_TCP |
-                                BFI_RSS_T_V6_TCP |
-                                BFI_RSS_T_V4_IP  |
-                                BFI_RSS_T_V6_IP);
+                               (BFI_ENET_RSS_IPV6 |
+                                BFI_ENET_RSS_IPV6_TCP |
+                                BFI_ENET_RSS_IPV4 |
+                                BFI_ENET_RSS_IPV4_TCP);
                rx_config->rss_config.hash_mask =
                                bnad->num_rxp_per_rx - 1;
                get_random_bytes(rx_config->rss_config.toeplitz_hash_key,
@@ -1768,7 +1854,7 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
 
 /* Called with mutex_lock(&bnad->conf_mutex) held */
 void
-bnad_cleanup_rx(struct bnad *bnad, uint rx_id)
+bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
 {
        struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
        struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
@@ -1811,7 +1897,7 @@ bnad_cleanup_rx(struct bnad *bnad, uint rx_id)
 
 /* Called with mutex_lock(&bnad->conf_mutex) held */
 int
-bnad_setup_rx(struct bnad *bnad, uint rx_id)
+bnad_setup_rx(struct bnad *bnad, u32 rx_id)
 {
        int err;
        struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
@@ -1823,6 +1909,8 @@ bnad_setup_rx(struct bnad *bnad, uint rx_id)
        struct bna_rx *rx;
        unsigned long flags;
 
+       rx_info->rx_id = rx_id;
+
        /* Initialize the Rx object configuration */
        bnad_init_rx_config(bnad, rx_config);
 
@@ -1978,7 +2066,7 @@ bnad_restore_vlans(struct bnad *bnad, u32 rx_id)
        u16 vid;
        unsigned long flags;
 
-       BUG_ON(!(VLAN_N_VID == (BFI_MAX_VLAN + 1)));
+       BUG_ON(!(VLAN_N_VID == BFI_ENET_VLAN_ID_MAX));
 
        for_each_set_bit(vid, bnad->active_vlans, VLAN_N_VID) {
                spin_lock_irqsave(&bnad->bna_lock, flags);
@@ -2031,11 +2119,11 @@ bnad_netdev_qstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
 void
 bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
 {
-       struct bfi_ll_stats_mac *mac_stats;
-       u64 bmap;
+       struct bfi_enet_stats_mac *mac_stats;
+       u32 bmap;
        int i;
 
-       mac_stats = &bnad->stats.bna_stats->hw_stats->mac_stats;
+       mac_stats = &bnad->stats.bna_stats->hw_stats.mac_stats;
        stats->rx_errors =
                mac_stats->rx_fcs_error + mac_stats->rx_alignment_error +
                mac_stats->rx_frame_length_error + mac_stats->rx_code_error +
@@ -2054,13 +2142,12 @@ bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
        stats->rx_crc_errors = mac_stats->rx_fcs_error;
        stats->rx_frame_errors = mac_stats->rx_alignment_error;
        /* recv'r fifo overrun */
-       bmap = (u64)bnad->stats.bna_stats->rxf_bmap[0] |
-               ((u64)bnad->stats.bna_stats->rxf_bmap[1] << 32);
-       for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+       bmap = bna_rx_rid_mask(&bnad->bna);
+       for (i = 0; bmap; i++) {
                if (bmap & 1) {
                        stats->rx_fifo_errors +=
                                bnad->stats.bna_stats->
-                                       hw_stats->rxf_stats[i].frame_drops;
+                                       hw_stats.rxf_stats[i].frame_drops;
                        break;
                }
                bmap >>= 1;
@@ -2158,7 +2245,7 @@ bnad_q_num_init(struct bnad *bnad)
  * Called with bnad->bna_lock held b'cos of cfg_flags access
  */
 static void
-bnad_q_num_adjust(struct bnad *bnad, int msix_vectors)
+bnad_q_num_adjust(struct bnad *bnad, int msix_vectors, int temp)
 {
        bnad->num_txq_per_tx = 1;
        if ((msix_vectors >= (bnad->num_tx * bnad->num_txq_per_tx)  +
@@ -2171,76 +2258,72 @@ bnad_q_num_adjust(struct bnad *bnad, int msix_vectors)
                bnad->num_rxp_per_rx = 1;
 }
 
-/* Enable / disable device */
-static void
-bnad_device_disable(struct bnad *bnad)
+/* Enable / disable ioceth */
+static int
+bnad_ioceth_disable(struct bnad *bnad)
 {
        unsigned long flags;
-
-       init_completion(&bnad->bnad_completions.ioc_comp);
+       int err = 0;
 
        spin_lock_irqsave(&bnad->bna_lock, flags);
-       bna_device_disable(&bnad->bna.device, BNA_HARD_CLEANUP);
+       init_completion(&bnad->bnad_completions.ioc_comp);
+       bna_ioceth_disable(&bnad->bna.ioceth, BNA_HARD_CLEANUP);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
-       wait_for_completion(&bnad->bnad_completions.ioc_comp);
+       wait_for_completion_timeout(&bnad->bnad_completions.ioc_comp,
+               msecs_to_jiffies(BNAD_IOCETH_TIMEOUT));
+
+       err = bnad->bnad_completions.ioc_comp_status;
+       return err;
 }
 
 static int
-bnad_device_enable(struct bnad *bnad)
+bnad_ioceth_enable(struct bnad *bnad)
 {
        int err = 0;
        unsigned long flags;
 
-       init_completion(&bnad->bnad_completions.ioc_comp);
-
        spin_lock_irqsave(&bnad->bna_lock, flags);
-       bna_device_enable(&bnad->bna.device);
+       init_completion(&bnad->bnad_completions.ioc_comp);
+       bnad->bnad_completions.ioc_comp_status = BNA_CB_WAITING;
+       bna_ioceth_enable(&bnad->bna.ioceth);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
-       wait_for_completion(&bnad->bnad_completions.ioc_comp);
+       wait_for_completion_timeout(&bnad->bnad_completions.ioc_comp,
+               msecs_to_jiffies(BNAD_IOCETH_TIMEOUT));
 
-       if (bnad->bnad_completions.ioc_comp_status)
-               err = bnad->bnad_completions.ioc_comp_status;
+       err = bnad->bnad_completions.ioc_comp_status;
 
        return err;
 }
 
 /* Free BNA resources */
 static void
-bnad_res_free(struct bnad *bnad)
+bnad_res_free(struct bnad *bnad, struct bna_res_info *res_info,
+               u32 res_val_max)
 {
        int i;
-       struct bna_res_info *res_info = &bnad->res_info[0];
 
-       for (i = 0; i < BNA_RES_T_MAX; i++) {
-               if (res_info[i].res_type == BNA_RES_T_MEM)
-                       bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
-               else
-                       bnad_mbox_irq_free(bnad, &res_info[i].res_u.intr_info);
-       }
+       for (i = 0; i < res_val_max; i++)
+               bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
 }
 
 /* Allocates memory and interrupt resources for BNA */
 static int
-bnad_res_alloc(struct bnad *bnad)
+bnad_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
+               u32 res_val_max)
 {
        int i, err;
-       struct bna_res_info *res_info = &bnad->res_info[0];
 
-       for (i = 0; i < BNA_RES_T_MAX; i++) {
-               if (res_info[i].res_type == BNA_RES_T_MEM)
-                       err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info);
-               else
-                       err = bnad_mbox_irq_alloc(bnad,
-                                                 &res_info[i].res_u.intr_info);
+       for (i = 0; i < res_val_max; i++) {
+               err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info);
                if (err)
                        goto err_return;
        }
        return 0;
 
 err_return:
-       bnad_res_free(bnad);
+       bnad_res_free(bnad, res_info, res_val_max);
        return err;
 }
 
@@ -2276,7 +2359,7 @@ bnad_enable_msix(struct bnad *bnad)
 
                spin_lock_irqsave(&bnad->bna_lock, flags);
                /* ret = #of vectors that we got */
-               bnad_q_num_adjust(bnad, ret);
+               bnad_q_num_adjust(bnad, ret, 0);
                spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
                bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx)
@@ -2284,6 +2367,9 @@ bnad_enable_msix(struct bnad *bnad)
                        * bnad->num_rxp_per_rx) +
                         BNAD_MAILBOX_MSIX_VECTORS;
 
+               if (bnad->msix_num > ret)
+                       goto intx_mode;
+
                /* Try once more with adjusted numbers */
                /* If this fails, fall back to INTx */
                ret = pci_enable_msix(bnad->pcidev, bnad->msix_table,
@@ -2293,6 +2379,9 @@ bnad_enable_msix(struct bnad *bnad)
 
        } else if (ret < 0)
                goto intx_mode;
+
+       pci_intx(bnad->pcidev, 0);
+
        return;
 
 intx_mode:
@@ -2351,12 +2440,12 @@ bnad_open(struct net_device *netdev)
        pause_config.tx_pause = 0;
        pause_config.rx_pause = 0;
 
-       mtu = ETH_HLEN + bnad->netdev->mtu + ETH_FCS_LEN;
+       mtu = ETH_HLEN + VLAN_HLEN + bnad->netdev->mtu + ETH_FCS_LEN;
 
        spin_lock_irqsave(&bnad->bna_lock, flags);
-       bna_port_mtu_set(&bnad->bna.port, mtu, NULL);
-       bna_port_pause_config(&bnad->bna.port, &pause_config, NULL);
-       bna_port_enable(&bnad->bna.port);
+       bna_enet_mtu_set(&bnad->bna.enet, mtu, NULL);
+       bna_enet_pause_config(&bnad->bna.enet, &pause_config, NULL);
+       bna_enet_enable(&bnad->bna.enet);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
        /* Enable broadcast */
@@ -2396,14 +2485,14 @@ bnad_stop(struct net_device *netdev)
        /* Stop the stats timer */
        bnad_stats_timer_stop(bnad);
 
-       init_completion(&bnad->bnad_completions.port_comp);
+       init_completion(&bnad->bnad_completions.enet_comp);
 
        spin_lock_irqsave(&bnad->bna_lock, flags);
-       bna_port_disable(&bnad->bna.port, BNA_HARD_CLEANUP,
-                       bnad_cb_port_disabled);
+       bna_enet_disable(&bnad->bna.enet, BNA_HARD_CLEANUP,
+                       bnad_cb_enet_disabled);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
-       wait_for_completion(&bnad->bnad_completions.port_comp);
+       wait_for_completion(&bnad->bnad_completions.enet_comp);
 
        bnad_cleanup_tx(bnad, 0);
        bnad_cleanup_rx(bnad, 0);
@@ -2425,19 +2514,18 @@ static netdev_tx_t
 bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
        struct bnad *bnad = netdev_priv(netdev);
+       u32 txq_id = 0;
+       struct bna_tcb *tcb = bnad->tx_info[0].tcb[txq_id];
 
        u16             txq_prod, vlan_tag = 0;
        u32             unmap_prod, wis, wis_used, wi_range;
        u32             vectors, vect_id, i, acked;
-       u32             tx_id;
        int                     err;
 
-       struct bnad_tx_info *tx_info;
-       struct bna_tcb *tcb;
-       struct bnad_unmap_q *unmap_q;
+       struct bnad_unmap_q *unmap_q = tcb->unmap_q;
        dma_addr_t              dma_addr;
        struct bna_txq_entry *txqent;
-       bna_txq_wi_ctrl_flag_t  flags;
+       u16     flags;
 
        if (unlikely
            (skb->len <= ETH_HLEN || skb->len > BFI_TX_MAX_DATA_PER_PKT)) {
@@ -2445,15 +2533,9 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
                return NETDEV_TX_OK;
        }
 
-       tx_id = 0;
-
-       tx_info = &bnad->tx_info[tx_id];
-       tcb = tx_info->tcb[tx_id];
-       unmap_q = tcb->unmap_q;
-
        /*
         * Takes care of the Tx that is scheduled between clearing the flag
-        * and the netif_stop_queue() call.
+        * and the netif_stop_all_queue() call.
         */
        if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) {
                dev_kfree_skb(skb);
@@ -2467,9 +2549,8 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
        }
        wis = BNA_TXQ_WI_NEEDED(vectors);       /* 4 vectors per work item */
        acked = 0;
-       if (unlikely
-           (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
-            vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
+       if (unlikely(wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
+                       vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
                if ((u16) (*tcb->hw_consumer_index) !=
                    tcb->consumer_index &&
                    !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
@@ -2602,7 +2683,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
-               u32             size = frag->size;
+               u16             size = frag->size;
 
                if (++vect_id == BFI_TX_MAX_VECTORS_PER_WI) {
                        vect_id = 0;
@@ -2760,11 +2841,25 @@ bnad_set_mac_address(struct net_device *netdev, void *mac_addr)
 }
 
 static int
-bnad_change_mtu(struct net_device *netdev, int new_mtu)
+bnad_mtu_set(struct bnad *bnad, int mtu)
 {
-       int mtu, err = 0;
        unsigned long flags;
 
+       init_completion(&bnad->bnad_completions.mtu_comp);
+
+       spin_lock_irqsave(&bnad->bna_lock, flags);
+       bna_enet_mtu_set(&bnad->bna.enet, mtu, bnad_cb_enet_mtu_set);
+       spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+       wait_for_completion(&bnad->bnad_completions.mtu_comp);
+
+       return bnad->bnad_completions.mtu_comp_status;
+}
+
+static int
+bnad_change_mtu(struct net_device *netdev, int new_mtu)
+{
+       int err, mtu = netdev->mtu;
        struct bnad *bnad = netdev_priv(netdev);
 
        if (new_mtu + ETH_HLEN < ETH_ZLEN || new_mtu > BNAD_JUMBO_MTU)
@@ -2774,11 +2869,10 @@ bnad_change_mtu(struct net_device *netdev, int new_mtu)
 
        netdev->mtu = new_mtu;
 
-       mtu = ETH_HLEN + new_mtu + ETH_FCS_LEN;
-
-       spin_lock_irqsave(&bnad->bna_lock, flags);
-       bna_port_mtu_set(&bnad->bna.port, mtu, NULL);
-       spin_unlock_irqrestore(&bnad->bna_lock, flags);
+       mtu = ETH_HLEN + VLAN_HLEN + new_mtu + ETH_FCS_LEN;
+       err = bnad_mtu_set(bnad, mtu);
+       if (err)
+               err = -EBUSY;
 
        mutex_unlock(&bnad->conf_mutex);
        return err;
@@ -2863,7 +2957,6 @@ static const struct net_device_ops bnad_netdev_ops = {
        .ndo_start_xmit         = bnad_start_xmit,
        .ndo_get_stats64                = bnad_get_stats64,
        .ndo_set_rx_mode        = bnad_set_rx_mode,
-       .ndo_set_multicast_list = bnad_set_rx_mode,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = bnad_set_mac_address,
        .ndo_change_mtu         = bnad_change_mtu,
@@ -2968,7 +3061,7 @@ bnad_uninit(struct bnad *bnad)
 
 /*
  * Initialize locks
-       a) Per device mutes used for serializing configuration
+       a) Per ioceth mutes used for serializing configuration
           changes from OS interface
        b) spin lock used to protect bna state machine
  */
@@ -3058,12 +3151,15 @@ bnad_pci_probe(struct pci_dev *pdev,
         */
        netdev = alloc_etherdev(sizeof(struct bnad));
        if (!netdev) {
-               dev_err(&pdev->dev, "alloc_etherdev failed\n");
+               dev_err(&pdev->dev, "netdev allocation failed\n");
                err = -ENOMEM;
                return err;
        }
        bnad = netdev_priv(netdev);
 
+       bnad_lock_init(bnad);
+
+       mutex_lock(&bnad->conf_mutex);
        /*
         * PCI initialization
         *      Output : using_dac = 1 for 64 bit DMA
@@ -3071,9 +3167,8 @@ bnad_pci_probe(struct pci_dev *pdev,
         */
        err = bnad_pci_init(bnad, pdev, &using_dac);
        if (err)
-               goto free_netdev;
+               goto unlock_mutex;
 
-       bnad_lock_init(bnad);
        /*
         * Initialize bnad structure
         * Setup relation between pci_dev & netdev
@@ -3082,21 +3177,22 @@ bnad_pci_probe(struct pci_dev *pdev,
        err = bnad_init(bnad, pdev, netdev);
        if (err)
                goto pci_uninit;
+
        /* Initialize netdev structure, set up ethtool ops */
        bnad_netdev_init(bnad, using_dac);
 
        /* Set link to down state */
        netif_carrier_off(netdev);
 
-       bnad_enable_msix(bnad);
-
        /* Get resource requirement form bna */
+       spin_lock_irqsave(&bnad->bna_lock, flags);
        bna_res_req(&bnad->res_info[0]);
+       spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
        /* Allocate resources from bna */
-       err = bnad_res_alloc(bnad);
+       err = bnad_res_alloc(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
        if (err)
-               goto free_netdev;
+               goto drv_uninit;
 
        bna = &bnad->bna;
 
@@ -3106,70 +3202,103 @@ bnad_pci_probe(struct pci_dev *pdev,
        pcidev_info.device_id = bnad->pcidev->device;
        pcidev_info.pci_bar_kva = bnad->bar0;
 
-       mutex_lock(&bnad->conf_mutex);
-
        spin_lock_irqsave(&bnad->bna_lock, flags);
        bna_init(bna, bnad, &pcidev_info, &bnad->res_info[0]);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
        bnad->stats.bna_stats = &bna->stats;
 
+       bnad_enable_msix(bnad);
+       err = bnad_mbox_irq_alloc(bnad);
+       if (err)
+               goto res_free;
+
+
        /* Set up timers */
-       setup_timer(&bnad->bna.device.ioc.ioc_timer, bnad_ioc_timeout,
+       setup_timer(&bnad->bna.ioceth.ioc.ioc_timer, bnad_ioc_timeout,
                                ((unsigned long)bnad));
-       setup_timer(&bnad->bna.device.ioc.hb_timer, bnad_ioc_hb_check,
+       setup_timer(&bnad->bna.ioceth.ioc.hb_timer, bnad_ioc_hb_check,
                                ((unsigned long)bnad));
-       setup_timer(&bnad->bna.device.ioc.iocpf_timer, bnad_iocpf_timeout,
+       setup_timer(&bnad->bna.ioceth.ioc.iocpf_timer, bnad_iocpf_timeout,
                                ((unsigned long)bnad));
-       setup_timer(&bnad->bna.device.ioc.sem_timer, bnad_iocpf_sem_timeout,
+       setup_timer(&bnad->bna.ioceth.ioc.sem_timer, bnad_iocpf_sem_timeout,
                                ((unsigned long)bnad));
 
        /* Now start the timer before calling IOC */
-       mod_timer(&bnad->bna.device.ioc.iocpf_timer,
+       mod_timer(&bnad->bna.ioceth.ioc.iocpf_timer,
                  jiffies + msecs_to_jiffies(BNA_IOC_TIMER_FREQ));
 
        /*
         * Start the chip
-        * Don't care even if err != 0, bna state machine will
-        * deal with it
+        * If the call back comes with error, we bail out.
+        * This is a catastrophic error.
         */
-       err = bnad_device_enable(bnad);
+       err = bnad_ioceth_enable(bnad);
+       if (err) {
+               pr_err("BNA: Initialization failed err=%d\n",
+                      err);
+               goto probe_success;
+       }
+
+       spin_lock_irqsave(&bnad->bna_lock, flags);
+       if (bna_num_txq_set(bna, BNAD_NUM_TXQ + 1) ||
+               bna_num_rxp_set(bna, BNAD_NUM_RXP + 1)) {
+               bnad_q_num_adjust(bnad, bna_attr(bna)->num_txq - 1,
+                       bna_attr(bna)->num_rxp - 1);
+               if (bna_num_txq_set(bna, BNAD_NUM_TXQ + 1) ||
+                       bna_num_rxp_set(bna, BNAD_NUM_RXP + 1))
+                       err = -EIO;
+       }
+       bna_mod_res_req(&bnad->bna, &bnad->mod_res_info[0]);
+       spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+       err = bnad_res_alloc(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+       if (err)
+               goto disable_ioceth;
+
+       spin_lock_irqsave(&bnad->bna_lock, flags);
+       bna_mod_init(&bnad->bna, &bnad->mod_res_info[0]);
+       spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
        /* Get the burnt-in mac */
        spin_lock_irqsave(&bnad->bna_lock, flags);
-       bna_port_mac_get(&bna->port, &bnad->perm_addr);
+       bna_enet_perm_mac_get(&bna->enet, &bnad->perm_addr);
        bnad_set_netdev_perm_addr(bnad);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
-       mutex_unlock(&bnad->conf_mutex);
-
        /* Finally, reguister with net_device layer */
        err = register_netdev(netdev);
        if (err) {
                pr_err("BNA : Registering with netdev failed\n");
-               goto disable_device;
+               goto probe_uninit;
        }
+       set_bit(BNAD_RF_NETDEV_REGISTERED, &bnad->run_flags);
 
+probe_success:
+       mutex_unlock(&bnad->conf_mutex);
        return 0;
 
-disable_device:
-       mutex_lock(&bnad->conf_mutex);
-       bnad_device_disable(bnad);
-       del_timer_sync(&bnad->bna.device.ioc.ioc_timer);
-       del_timer_sync(&bnad->bna.device.ioc.sem_timer);
-       del_timer_sync(&bnad->bna.device.ioc.hb_timer);
+probe_uninit:
+       bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+disable_ioceth:
+       bnad_ioceth_disable(bnad);
+       del_timer_sync(&bnad->bna.ioceth.ioc.ioc_timer);
+       del_timer_sync(&bnad->bna.ioceth.ioc.sem_timer);
+       del_timer_sync(&bnad->bna.ioceth.ioc.hb_timer);
        spin_lock_irqsave(&bnad->bna_lock, flags);
        bna_uninit(bna);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
-       mutex_unlock(&bnad->conf_mutex);
-
-       bnad_res_free(bnad);
+       bnad_mbox_irq_free(bnad);
        bnad_disable_msix(bnad);
+res_free:
+       bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
+drv_uninit:
+       bnad_uninit(bnad);
 pci_uninit:
        bnad_pci_uninit(pdev);
+unlock_mutex:
+       mutex_unlock(&bnad->conf_mutex);
        bnad_lock_uninit(bnad);
-       bnad_uninit(bnad);
-free_netdev:
        free_netdev(netdev);
        return err;
 }
@@ -3189,21 +3318,24 @@ bnad_pci_remove(struct pci_dev *pdev)
        bnad = netdev_priv(netdev);
        bna = &bnad->bna;
 
-       unregister_netdev(netdev);
+       if (test_and_clear_bit(BNAD_RF_NETDEV_REGISTERED, &bnad->run_flags))
+               unregister_netdev(netdev);
 
        mutex_lock(&bnad->conf_mutex);
-       bnad_device_disable(bnad);
-       del_timer_sync(&bnad->bna.device.ioc.ioc_timer);
-       del_timer_sync(&bnad->bna.device.ioc.sem_timer);
-       del_timer_sync(&bnad->bna.device.ioc.hb_timer);
+       bnad_ioceth_disable(bnad);
+       del_timer_sync(&bnad->bna.ioceth.ioc.ioc_timer);
+       del_timer_sync(&bnad->bna.ioceth.ioc.sem_timer);
+       del_timer_sync(&bnad->bna.ioceth.ioc.hb_timer);
        spin_lock_irqsave(&bnad->bna_lock, flags);
        bna_uninit(bna);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
-       mutex_unlock(&bnad->conf_mutex);
 
-       bnad_res_free(bnad);
+       bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+       bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
+       bnad_mbox_irq_free(bnad);
        bnad_disable_msix(bnad);
        bnad_pci_uninit(pdev);
+       mutex_unlock(&bnad->conf_mutex);
        bnad_lock_uninit(bnad);
        bnad_uninit(bnad);
        free_netdev(netdev);
similarity index 89%
rename from drivers/net/bna/bnad.h
rename to drivers/net/ethernet/brocade/bna/bnad.h
index 458eb30..5b5451e 100644 (file)
@@ -44,6 +44,7 @@
 
 #define BNAD_MAX_RXS           1
 #define BNAD_MAX_RXPS_PER_RX   16
+#define BNAD_MAX_RXQ_PER_RXP   2
 
 /*
  * Control structure pointed to ccb->ctrl, which
@@ -66,7 +67,7 @@ struct bnad_rx_ctrl {
 #define BNAD_NAME                      "bna"
 #define BNAD_NAME_LEN                  64
 
-#define BNAD_VERSION                   "2.3.2.3"
+#define BNAD_VERSION                   "3.0.2.0"
 
 #define BNAD_MAILBOX_MSIX_INDEX                0
 #define BNAD_MAILBOX_MSIX_VECTORS      1
@@ -76,6 +77,8 @@ struct bnad_rx_ctrl {
 #define BNAD_STATS_TIMER_FREQ          1000    /* in msecs */
 #define BNAD_DIM_TIMER_FREQ            1000    /* in msecs */
 
+#define BNAD_IOCETH_TIMEOUT         10000
+
 #define BNAD_MAX_Q_DEPTH               0x10000
 #define BNAD_MIN_Q_DEPTH               0x200
 
@@ -93,6 +96,10 @@ struct bnad_rx_ctrl {
 #define BNAD_RXQ_REFILL                        0
 #define BNAD_RXQ_STARTED               1
 
+/* Resource limits */
+#define BNAD_NUM_TXQ                   (bnad->num_tx * bnad->num_txq_per_tx)
+#define BNAD_NUM_RXP                   (bnad->num_rx * bnad->num_rxp_per_rx)
+
 /*
  * DATA STRUCTURES
  */
@@ -115,7 +122,8 @@ struct bnad_completion {
        struct completion       tx_comp;
        struct completion       rx_comp;
        struct completion       stats_comp;
-       struct completion       port_comp;
+       struct completion       enet_comp;
+       struct completion       mtu_comp;
 
        u8                      ioc_comp_status;
        u8                      ucast_comp_status;
@@ -124,6 +132,7 @@ struct bnad_completion {
        u8                      rx_comp_status;
        u8                      stats_comp_status;
        u8                      port_comp_status;
+       u8                      mtu_comp_status;
 };
 
 /* Tx Rx Control Stats */
@@ -145,6 +154,7 @@ struct bnad_drv_stats {
        u64             netif_rx_dropped;
 
        u64             link_toggle;
+       u64             cee_toggle;
        u64             cee_up;
 
        u64             rxp_info_alloc_failed;
@@ -174,12 +184,14 @@ struct bnad_rx_res_info {
 struct bnad_tx_info {
        struct bna_tx *tx; /* 1:1 between tx_info & tx */
        struct bna_tcb *tcb[BNAD_MAX_TXQ_PER_TX];
+       u32 tx_id;
 } ____cacheline_aligned;
 
 struct bnad_rx_info {
        struct bna_rx *rx; /* 1:1 between rx_info & rx */
 
        struct bnad_rx_ctrl rx_ctrl[BNAD_MAX_RXPS_PER_RX];
+       u32 rx_id;
 } ____cacheline_aligned;
 
 /* Unmap queues for Tx / Rx cleanup */
@@ -205,13 +217,18 @@ struct bnad_unmap_q {
 /* Defines for run_flags bit-mask */
 /* Set, tested & cleared using xxx_bit() functions */
 /* Values indicated bit positions */
-#define        BNAD_RF_CEE_RUNNING             1
+#define BNAD_RF_CEE_RUNNING            0
+#define BNAD_RF_MTU_SET                1
 #define BNAD_RF_MBOX_IRQ_DISABLED      2
-#define BNAD_RF_RX_STARTED             3
+#define BNAD_RF_NETDEV_REGISTERED      3
 #define BNAD_RF_DIM_TIMER_RUNNING      4
 #define BNAD_RF_STATS_TIMER_RUNNING    5
-#define BNAD_RF_TX_SHUTDOWN_DELAYED    6
-#define BNAD_RF_RX_SHUTDOWN_DELAYED    7
+#define BNAD_RF_TX_PRIO_SET            6
+
+
+/* Define for Fast Path flags */
+/* Defined as bit positions */
+#define BNAD_FP_IN_RX_PATH           0
 
 struct bnad {
        struct net_device       *netdev;
@@ -265,6 +282,7 @@ struct bnad {
 
        /* Control path resources, memory & irq */
        struct bna_res_info res_info[BNA_RES_T_MAX];
+       struct bna_res_info mod_res_info[BNA_MOD_RES_T_MAX];
        struct bnad_tx_res_info tx_res_info[BNAD_MAX_TXS];
        struct bnad_rx_res_info rx_res_info[BNAD_MAX_RXS];
 
@@ -302,10 +320,10 @@ extern void bnad_set_ethtool_ops(struct net_device *netdev);
 extern void bnad_tx_coalescing_timeo_set(struct bnad *bnad);
 extern void bnad_rx_coalescing_timeo_set(struct bnad *bnad);
 
-extern int bnad_setup_rx(struct bnad *bnad, uint rx_id);
-extern int bnad_setup_tx(struct bnad *bnad, uint tx_id);
-extern void bnad_cleanup_tx(struct bnad *bnad, uint tx_id);
-extern void bnad_cleanup_rx(struct bnad *bnad, uint rx_id);
+extern int bnad_setup_rx(struct bnad *bnad, u32 rx_id);
+extern int bnad_setup_tx(struct bnad *bnad, u32 tx_id);
+extern void bnad_cleanup_tx(struct bnad *bnad, u32 tx_id);
+extern void bnad_cleanup_rx(struct bnad *bnad, u32 rx_id);
 
 /* Timer start/stop protos */
 extern void bnad_dim_timer_start(struct bnad *bnad);
similarity index 67%
rename from drivers/net/bna/bnad_ethtool.c
rename to drivers/net/ethernet/brocade/bna/bnad_ethtool.c
index fea07f1..1c19dce 100644 (file)
 
 #define BNAD_NUM_TXF_COUNTERS 12
 #define BNAD_NUM_RXF_COUNTERS 10
-#define BNAD_NUM_CQ_COUNTERS 3
+#define BNAD_NUM_CQ_COUNTERS (3 + 5)
 #define BNAD_NUM_RXQ_COUNTERS 6
 #define BNAD_NUM_TXQ_COUNTERS 5
 
 #define BNAD_ETHTOOL_STATS_NUM                                         \
        (sizeof(struct rtnl_link_stats64) / sizeof(u64) +       \
        sizeof(struct bnad_drv_stats) / sizeof(u64) +           \
-       offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64))
+       offsetof(struct bfi_enet_stats, rxf_stats[0]) / sizeof(u64))
 
 static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
        "rx_packets",
@@ -277,7 +277,7 @@ bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
        ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL);
        if (ioc_attr) {
                spin_lock_irqsave(&bnad->bna_lock, flags);
-               bfa_nw_ioc_get_attr(&bnad->bna.device.ioc, ioc_attr);
+               bfa_nw_ioc_get_attr(&bnad->bna.ioceth.ioc, ioc_attr);
                spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
                strncpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver,
@@ -288,323 +288,6 @@ bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
        strncpy(drvinfo->bus_info, pci_name(bnad->pcidev), ETHTOOL_BUSINFO_LEN);
 }
 
-static int
-get_regs(struct bnad *bnad, u32 * regs)
-{
-       int num = 0, i;
-       u32 reg_addr;
-       unsigned long flags;
-
-#define BNAD_GET_REG(addr)                                     \
-do {                                                           \
-       if (regs)                                               \
-               regs[num++] = readl(bnad->bar0 + (addr));       \
-       else                                                    \
-               num++;                                          \
-} while (0)
-
-       spin_lock_irqsave(&bnad->bna_lock, flags);
-
-       /* DMA Block Internal Registers */
-       BNAD_GET_REG(DMA_CTRL_REG0);
-       BNAD_GET_REG(DMA_CTRL_REG1);
-       BNAD_GET_REG(DMA_ERR_INT_STATUS);
-       BNAD_GET_REG(DMA_ERR_INT_ENABLE);
-       BNAD_GET_REG(DMA_ERR_INT_STATUS_SET);
-
-       /* APP Block Register Address Offset from BAR0 */
-       BNAD_GET_REG(HOSTFN0_INT_STATUS);
-       BNAD_GET_REG(HOSTFN0_INT_MASK);
-       BNAD_GET_REG(HOST_PAGE_NUM_FN0);
-       BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN0);
-       BNAD_GET_REG(FN0_PCIE_ERR_REG);
-       BNAD_GET_REG(FN0_ERR_TYPE_STATUS_REG);
-       BNAD_GET_REG(FN0_ERR_TYPE_MSK_STATUS_REG);
-
-       BNAD_GET_REG(HOSTFN1_INT_STATUS);
-       BNAD_GET_REG(HOSTFN1_INT_MASK);
-       BNAD_GET_REG(HOST_PAGE_NUM_FN1);
-       BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN1);
-       BNAD_GET_REG(FN1_PCIE_ERR_REG);
-       BNAD_GET_REG(FN1_ERR_TYPE_STATUS_REG);
-       BNAD_GET_REG(FN1_ERR_TYPE_MSK_STATUS_REG);
-
-       BNAD_GET_REG(PCIE_MISC_REG);
-
-       BNAD_GET_REG(HOST_SEM0_INFO_REG);
-       BNAD_GET_REG(HOST_SEM1_INFO_REG);
-       BNAD_GET_REG(HOST_SEM2_INFO_REG);
-       BNAD_GET_REG(HOST_SEM3_INFO_REG);
-
-       BNAD_GET_REG(TEMPSENSE_CNTL_REG);
-       BNAD_GET_REG(TEMPSENSE_STAT_REG);
-
-       BNAD_GET_REG(APP_LOCAL_ERR_STAT);
-       BNAD_GET_REG(APP_LOCAL_ERR_MSK);
-
-       BNAD_GET_REG(PCIE_LNK_ERR_STAT);
-       BNAD_GET_REG(PCIE_LNK_ERR_MSK);
-
-       BNAD_GET_REG(FCOE_FIP_ETH_TYPE);
-       BNAD_GET_REG(RESV_ETH_TYPE);
-
-       BNAD_GET_REG(HOSTFN2_INT_STATUS);
-       BNAD_GET_REG(HOSTFN2_INT_MASK);
-       BNAD_GET_REG(HOST_PAGE_NUM_FN2);
-       BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN2);
-       BNAD_GET_REG(FN2_PCIE_ERR_REG);
-       BNAD_GET_REG(FN2_ERR_TYPE_STATUS_REG);
-       BNAD_GET_REG(FN2_ERR_TYPE_MSK_STATUS_REG);
-
-       BNAD_GET_REG(HOSTFN3_INT_STATUS);
-       BNAD_GET_REG(HOSTFN3_INT_MASK);
-       BNAD_GET_REG(HOST_PAGE_NUM_FN3);
-       BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN3);
-       BNAD_GET_REG(FN3_PCIE_ERR_REG);
-       BNAD_GET_REG(FN3_ERR_TYPE_STATUS_REG);
-       BNAD_GET_REG(FN3_ERR_TYPE_MSK_STATUS_REG);
-
-       /* Host Command Status Registers */
-       reg_addr = HOST_CMDSTS0_CLR_REG;
-       for (i = 0; i < 16; i++) {
-               BNAD_GET_REG(reg_addr);
-               BNAD_GET_REG(reg_addr + 4);
-               BNAD_GET_REG(reg_addr + 8);
-               reg_addr += 0x10;
-       }
-
-       /* Function ID register */
-       BNAD_GET_REG(FNC_ID_REG);
-
-       /* Function personality register */
-       BNAD_GET_REG(FNC_PERS_REG);
-
-       /* Operation mode register */
-       BNAD_GET_REG(OP_MODE);
-
-       /* LPU0 Registers */
-       BNAD_GET_REG(LPU0_MBOX_CTL_REG);
-       BNAD_GET_REG(LPU0_MBOX_CMD_REG);
-       BNAD_GET_REG(LPU0_MBOX_LINK_0REG);
-       BNAD_GET_REG(LPU1_MBOX_LINK_0REG);
-       BNAD_GET_REG(LPU0_MBOX_STATUS_0REG);
-       BNAD_GET_REG(LPU1_MBOX_STATUS_0REG);
-       BNAD_GET_REG(LPU0_ERR_STATUS_REG);
-       BNAD_GET_REG(LPU0_ERR_SET_REG);
-
-       /* LPU1 Registers */
-       BNAD_GET_REG(LPU1_MBOX_CTL_REG);
-       BNAD_GET_REG(LPU1_MBOX_CMD_REG);
-       BNAD_GET_REG(LPU0_MBOX_LINK_1REG);
-       BNAD_GET_REG(LPU1_MBOX_LINK_1REG);
-       BNAD_GET_REG(LPU0_MBOX_STATUS_1REG);
-       BNAD_GET_REG(LPU1_MBOX_STATUS_1REG);
-       BNAD_GET_REG(LPU1_ERR_STATUS_REG);
-       BNAD_GET_REG(LPU1_ERR_SET_REG);
-
-       /* PSS Registers */
-       BNAD_GET_REG(PSS_CTL_REG);
-       BNAD_GET_REG(PSS_ERR_STATUS_REG);
-       BNAD_GET_REG(ERR_STATUS_SET);
-       BNAD_GET_REG(PSS_RAM_ERR_STATUS_REG);
-
-       /* Catapult CPQ Registers */
-       BNAD_GET_REG(HOSTFN0_LPU0_MBOX0_CMD_STAT);
-       BNAD_GET_REG(HOSTFN0_LPU1_MBOX0_CMD_STAT);
-       BNAD_GET_REG(LPU0_HOSTFN0_MBOX0_CMD_STAT);
-       BNAD_GET_REG(LPU1_HOSTFN0_MBOX0_CMD_STAT);
-
-       BNAD_GET_REG(HOSTFN0_LPU0_MBOX1_CMD_STAT);
-       BNAD_GET_REG(HOSTFN0_LPU1_MBOX1_CMD_STAT);
-       BNAD_GET_REG(LPU0_HOSTFN0_MBOX1_CMD_STAT);
-       BNAD_GET_REG(LPU1_HOSTFN0_MBOX1_CMD_STAT);
-
-       BNAD_GET_REG(HOSTFN1_LPU0_MBOX0_CMD_STAT);
-       BNAD_GET_REG(HOSTFN1_LPU1_MBOX0_CMD_STAT);
-       BNAD_GET_REG(LPU0_HOSTFN1_MBOX0_CMD_STAT);
-       BNAD_GET_REG(LPU1_HOSTFN1_MBOX0_CMD_STAT);
-
-       BNAD_GET_REG(HOSTFN1_LPU0_MBOX1_CMD_STAT);
-       BNAD_GET_REG(HOSTFN1_LPU1_MBOX1_CMD_STAT);
-       BNAD_GET_REG(LPU0_HOSTFN1_MBOX1_CMD_STAT);
-       BNAD_GET_REG(LPU1_HOSTFN1_MBOX1_CMD_STAT);
-
-       BNAD_GET_REG(HOSTFN2_LPU0_MBOX0_CMD_STAT);
-       BNAD_GET_REG(HOSTFN2_LPU1_MBOX0_CMD_STAT);
-       BNAD_GET_REG(LPU0_HOSTFN2_MBOX0_CMD_STAT);
-       BNAD_GET_REG(LPU1_HOSTFN2_MBOX0_CMD_STAT);
-
-       BNAD_GET_REG(HOSTFN2_LPU0_MBOX1_CMD_STAT);
-       BNAD_GET_REG(HOSTFN2_LPU1_MBOX1_CMD_STAT);
-       BNAD_GET_REG(LPU0_HOSTFN2_MBOX1_CMD_STAT);
-       BNAD_GET_REG(LPU1_HOSTFN2_MBOX1_CMD_STAT);
-
-       BNAD_GET_REG(HOSTFN3_LPU0_MBOX0_CMD_STAT);
-       BNAD_GET_REG(HOSTFN3_LPU1_MBOX0_CMD_STAT);
-       BNAD_GET_REG(LPU0_HOSTFN3_MBOX0_CMD_STAT);
-       BNAD_GET_REG(LPU1_HOSTFN3_MBOX0_CMD_STAT);
-
-       BNAD_GET_REG(HOSTFN3_LPU0_MBOX1_CMD_STAT);
-       BNAD_GET_REG(HOSTFN3_LPU1_MBOX1_CMD_STAT);
-       BNAD_GET_REG(LPU0_HOSTFN3_MBOX1_CMD_STAT);
-       BNAD_GET_REG(LPU1_HOSTFN3_MBOX1_CMD_STAT);
-
-       /* Host Function Force Parity Error Registers */
-       BNAD_GET_REG(HOSTFN0_LPU_FORCE_PERR);
-       BNAD_GET_REG(HOSTFN1_LPU_FORCE_PERR);
-       BNAD_GET_REG(HOSTFN2_LPU_FORCE_PERR);
-       BNAD_GET_REG(HOSTFN3_LPU_FORCE_PERR);
-
-       /* LL Port[0|1] Halt Mask Registers */
-       BNAD_GET_REG(LL_HALT_MSK_P0);
-       BNAD_GET_REG(LL_HALT_MSK_P1);
-
-       /* LL Port[0|1] Error Mask Registers */
-       BNAD_GET_REG(LL_ERR_MSK_P0);
-       BNAD_GET_REG(LL_ERR_MSK_P1);
-
-       /* EMC FLI Registers */
-       BNAD_GET_REG(FLI_CMD_REG);
-       BNAD_GET_REG(FLI_ADDR_REG);
-       BNAD_GET_REG(FLI_CTL_REG);
-       BNAD_GET_REG(FLI_WRDATA_REG);
-       BNAD_GET_REG(FLI_RDDATA_REG);
-       BNAD_GET_REG(FLI_DEV_STATUS_REG);
-       BNAD_GET_REG(FLI_SIG_WD_REG);
-
-       BNAD_GET_REG(FLI_DEV_VENDOR_REG);
-       BNAD_GET_REG(FLI_ERR_STATUS_REG);
-
-       /* RxAdm 0 Registers */
-       BNAD_GET_REG(RAD0_CTL_REG);
-       BNAD_GET_REG(RAD0_PE_PARM_REG);
-       BNAD_GET_REG(RAD0_BCN_REG);
-       BNAD_GET_REG(RAD0_DEFAULT_REG);
-       BNAD_GET_REG(RAD0_PROMISC_REG);
-       BNAD_GET_REG(RAD0_BCNQ_REG);
-       BNAD_GET_REG(RAD0_DEFAULTQ_REG);
-
-       BNAD_GET_REG(RAD0_ERR_STS);
-       BNAD_GET_REG(RAD0_SET_ERR_STS);
-       BNAD_GET_REG(RAD0_ERR_INT_EN);
-       BNAD_GET_REG(RAD0_FIRST_ERR);
-       BNAD_GET_REG(RAD0_FORCE_ERR);
-
-       BNAD_GET_REG(RAD0_MAC_MAN_1H);
-       BNAD_GET_REG(RAD0_MAC_MAN_1L);
-       BNAD_GET_REG(RAD0_MAC_MAN_2H);
-       BNAD_GET_REG(RAD0_MAC_MAN_2L);
-       BNAD_GET_REG(RAD0_MAC_MAN_3H);
-       BNAD_GET_REG(RAD0_MAC_MAN_3L);
-       BNAD_GET_REG(RAD0_MAC_MAN_4H);
-       BNAD_GET_REG(RAD0_MAC_MAN_4L);
-
-       BNAD_GET_REG(RAD0_LAST4_IP);
-
-       /* RxAdm 1 Registers */
-       BNAD_GET_REG(RAD1_CTL_REG);
-       BNAD_GET_REG(RAD1_PE_PARM_REG);
-       BNAD_GET_REG(RAD1_BCN_REG);
-       BNAD_GET_REG(RAD1_DEFAULT_REG);
-       BNAD_GET_REG(RAD1_PROMISC_REG);
-       BNAD_GET_REG(RAD1_BCNQ_REG);
-       BNAD_GET_REG(RAD1_DEFAULTQ_REG);
-
-       BNAD_GET_REG(RAD1_ERR_STS);
-       BNAD_GET_REG(RAD1_SET_ERR_STS);
-       BNAD_GET_REG(RAD1_ERR_INT_EN);
-
-       /* TxA0 Registers */
-       BNAD_GET_REG(TXA0_CTRL_REG);
-       /* TxA0 TSO Sequence # Registers (RO) */
-       for (i = 0; i < 8; i++) {
-               BNAD_GET_REG(TXA0_TSO_TCP_SEQ_REG(i));
-               BNAD_GET_REG(TXA0_TSO_IP_INFO_REG(i));
-       }
-
-       /* TxA1 Registers */
-       BNAD_GET_REG(TXA1_CTRL_REG);
-       /* TxA1 TSO Sequence # Registers (RO) */
-       for (i = 0; i < 8; i++) {
-               BNAD_GET_REG(TXA1_TSO_TCP_SEQ_REG(i));
-               BNAD_GET_REG(TXA1_TSO_IP_INFO_REG(i));
-       }
-
-       /* RxA Registers */
-       BNAD_GET_REG(RXA0_CTL_REG);
-       BNAD_GET_REG(RXA1_CTL_REG);
-
-       /* PLB0 Registers */
-       BNAD_GET_REG(PLB0_ECM_TIMER_REG);
-       BNAD_GET_REG(PLB0_RL_CTL);
-       for (i = 0; i < 8; i++)
-               BNAD_GET_REG(PLB0_RL_MAX_BC(i));
-       BNAD_GET_REG(PLB0_RL_TU_PRIO);
-       for (i = 0; i < 8; i++)
-               BNAD_GET_REG(PLB0_RL_BYTE_CNT(i));
-       BNAD_GET_REG(PLB0_RL_MIN_REG);
-       BNAD_GET_REG(PLB0_RL_MAX_REG);
-       BNAD_GET_REG(PLB0_EMS_ADD_REG);
-
-       /* PLB1 Registers */
-       BNAD_GET_REG(PLB1_ECM_TIMER_REG);
-       BNAD_GET_REG(PLB1_RL_CTL);
-       for (i = 0; i < 8; i++)
-               BNAD_GET_REG(PLB1_RL_MAX_BC(i));
-       BNAD_GET_REG(PLB1_RL_TU_PRIO);
-       for (i = 0; i < 8; i++)
-               BNAD_GET_REG(PLB1_RL_BYTE_CNT(i));
-       BNAD_GET_REG(PLB1_RL_MIN_REG);
-       BNAD_GET_REG(PLB1_RL_MAX_REG);
-       BNAD_GET_REG(PLB1_EMS_ADD_REG);
-
-       /* HQM Control Register */
-       BNAD_GET_REG(HQM0_CTL_REG);
-       BNAD_GET_REG(HQM0_RXQ_STOP_SEM);
-       BNAD_GET_REG(HQM0_TXQ_STOP_SEM);
-       BNAD_GET_REG(HQM1_CTL_REG);
-       BNAD_GET_REG(HQM1_RXQ_STOP_SEM);
-       BNAD_GET_REG(HQM1_TXQ_STOP_SEM);
-
-       /* LUT Registers */
-       BNAD_GET_REG(LUT0_ERR_STS);
-       BNAD_GET_REG(LUT0_SET_ERR_STS);
-       BNAD_GET_REG(LUT1_ERR_STS);
-       BNAD_GET_REG(LUT1_SET_ERR_STS);
-
-       /* TRC Registers */
-       BNAD_GET_REG(TRC_CTL_REG);
-       BNAD_GET_REG(TRC_MODS_REG);
-       BNAD_GET_REG(TRC_TRGC_REG);
-       BNAD_GET_REG(TRC_CNT1_REG);
-       BNAD_GET_REG(TRC_CNT2_REG);
-       BNAD_GET_REG(TRC_NXTS_REG);
-       BNAD_GET_REG(TRC_DIRR_REG);
-       for (i = 0; i < 10; i++)
-               BNAD_GET_REG(TRC_TRGM_REG(i));
-       for (i = 0; i < 10; i++)
-               BNAD_GET_REG(TRC_NXTM_REG(i));
-       for (i = 0; i < 10; i++)
-               BNAD_GET_REG(TRC_STRM_REG(i));
-
-       spin_unlock_irqrestore(&bnad->bna_lock, flags);
-#undef BNAD_GET_REG
-       return num;
-}
-static int
-bnad_get_regs_len(struct net_device *netdev)
-{
-       int ret = get_regs(netdev_priv(netdev), NULL) * sizeof(u32);
-       return ret;
-}
-
-static void
-bnad_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
-{
-       memset(buf, 0, bnad_get_regs_len(netdev));
-       get_regs(netdev_priv(netdev), buf);
-}
-
 static void
 bnad_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wolinfo)
 {
@@ -779,8 +462,8 @@ bnad_get_pauseparam(struct net_device *netdev,
        struct bnad *bnad = netdev_priv(netdev);
 
        pauseparam->autoneg = 0;
-       pauseparam->rx_pause = bnad->bna.port.pause_config.rx_pause;
-       pauseparam->tx_pause = bnad->bna.port.pause_config.tx_pause;
+       pauseparam->rx_pause = bnad->bna.enet.pause_config.rx_pause;
+       pauseparam->tx_pause = bnad->bna.enet.pause_config.tx_pause;
 }
 
 static int
@@ -795,12 +478,12 @@ bnad_set_pauseparam(struct net_device *netdev,
                return -EINVAL;
 
        mutex_lock(&bnad->conf_mutex);
-       if (pauseparam->rx_pause != bnad->bna.port.pause_config.rx_pause ||
-           pauseparam->tx_pause != bnad->bna.port.pause_config.tx_pause) {
+       if (pauseparam->rx_pause != bnad->bna.enet.pause_config.rx_pause ||
+           pauseparam->tx_pause != bnad->bna.enet.pause_config.tx_pause) {
                pause_config.rx_pause = pauseparam->rx_pause;
                pause_config.tx_pause = pauseparam->tx_pause;
                spin_lock_irqsave(&bnad->bna_lock, flags);
-               bna_port_pause_config(&bnad->bna.port, &pause_config, NULL);
+               bna_enet_pause_config(&bnad->bna.enet, &pause_config, NULL);
                spin_unlock_irqrestore(&bnad->bna_lock, flags);
        }
        mutex_unlock(&bnad->conf_mutex);
@@ -812,7 +495,7 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
 {
        struct bnad *bnad = netdev_priv(netdev);
        int i, j, q_num;
-       u64 bmap;
+       u32 bmap;
 
        mutex_lock(&bnad->conf_mutex);
 
@@ -825,9 +508,8 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
                               ETH_GSTRING_LEN);
                        string += ETH_GSTRING_LEN;
                }
-               bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
-                       ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
-               for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
+               bmap = bna_tx_rid_mask(&bnad->bna);
+               for (i = 0; bmap; i++) {
                        if (bmap & 1) {
                                sprintf(string, "txf%d_ucast_octets", i);
                                string += ETH_GSTRING_LEN;
@@ -857,9 +539,8 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
                        bmap >>= 1;
                }
 
-               bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
-                       ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
-               for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+               bmap = bna_rx_rid_mask(&bnad->bna);
+               for (i = 0; bmap; i++) {
                        if (bmap & 1) {
                                sprintf(string, "rxf%d_ucast_octets", i);
                                string += ETH_GSTRING_LEN;
@@ -980,18 +661,16 @@ bnad_get_stats_count_locked(struct net_device *netdev)
 {
        struct bnad *bnad = netdev_priv(netdev);
        int i, j, count, rxf_active_num = 0, txf_active_num = 0;
-       u64 bmap;
+       u32 bmap;
 
-       bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
-                       ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
-       for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
+       bmap = bna_tx_rid_mask(&bnad->bna);
+       for (i = 0; bmap; i++) {
                if (bmap & 1)
                        txf_active_num++;
                bmap >>= 1;
        }
-       bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
-                       ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
-       for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+       bmap = bna_rx_rid_mask(&bnad->bna);
+       for (i = 0; bmap; i++) {
                if (bmap & 1)
                        rxf_active_num++;
                bmap >>= 1;
@@ -1104,7 +783,7 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,
        unsigned long flags;
        struct rtnl_link_stats64 *net_stats64;
        u64 *stats64;
-       u64 bmap;
+       u32 bmap;
 
        mutex_lock(&bnad->conf_mutex);
        if (bnad_get_stats_count_locked(netdev) != stats->n_stats) {
@@ -1135,20 +814,20 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,
                buf[bi++] = stats64[i];
 
        /* Fill hardware stats excluding the rxf/txf into ethtool bufs */
-       stats64 = (u64 *) bnad->stats.bna_stats->hw_stats;
+       stats64 = (u64 *) &bnad->stats.bna_stats->hw_stats;
        for (i = 0;
-            i < offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64);
+            i < offsetof(struct bfi_enet_stats, rxf_stats[0]) /
+               sizeof(u64);
             i++)
                buf[bi++] = stats64[i];
 
        /* Fill txf stats into ethtool buffers */
-       bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
-                       ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
-       for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
+       bmap = bna_tx_rid_mask(&bnad->bna);
+       for (i = 0; bmap; i++) {
                if (bmap & 1) {
                        stats64 = (u64 *)&bnad->stats.bna_stats->
-                                               hw_stats->txf_stats[i];
-                       for (j = 0; j < sizeof(struct bfi_ll_stats_txf) /
+                                               hw_stats.txf_stats[i];
+                       for (j = 0; j < sizeof(struct bfi_enet_stats_txf) /
                                        sizeof(u64); j++)
                                buf[bi++] = stats64[j];
                }
@@ -1156,13 +835,12 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,
        }
 
        /*  Fill rxf stats into ethtool buffers */
-       bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
-                       ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
-       for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+       bmap = bna_rx_rid_mask(&bnad->bna);
+       for (i = 0; bmap; i++) {
                if (bmap & 1) {
                        stats64 = (u64 *)&bnad->stats.bna_stats->
-                                               hw_stats->rxf_stats[i];
-                       for (j = 0; j < sizeof(struct bfi_ll_stats_rxf) /
+                                               hw_stats.rxf_stats[i];
+                       for (j = 0; j < sizeof(struct bfi_enet_stats_rxf) /
                                        sizeof(u64); j++)
                                buf[bi++] = stats64[j];
                }
@@ -1192,8 +870,6 @@ static struct ethtool_ops bnad_ethtool_ops = {
        .get_settings = bnad_get_settings,
        .set_settings = bnad_set_settings,
        .get_drvinfo = bnad_get_drvinfo,
-       .get_regs_len = bnad_get_regs_len,
-       .get_regs = bnad_get_regs,
        .get_wol = bnad_get_wol,
        .get_link = ethtool_op_get_link,
        .get_coalesce = bnad_get_coalesce,
similarity index 68%
rename from drivers/net/bna/cna.h
rename to drivers/net/ethernet/brocade/bna/cna.h
index a679e03..50fce15 100644 (file)
@@ -40,7 +40,7 @@
 
 extern char bfa_version[];
 
-#define        CNA_FW_FILE_CT  "ctfw_cna.bin"
+#define        CNA_FW_FILE_CT  "ctfw.bin"
 #define FC_SYMNAME_MAX 256     /*!< max name server symbolic name size */
 
 #pragma pack(1)
@@ -77,4 +77,33 @@ typedef struct mac { u8 mac[MAC_ADDRLEN]; } mac_t;
        }                                                               \
 }
 
+/*
+ * bfa_q_deq_tail - dequeue an element from tail of the queue
+ */
+#define bfa_q_deq_tail(_q, _qe) {                                      \
+       if (!list_empty(_q)) {                                          \
+               *((struct list_head **) (_qe)) = bfa_q_prev(_q);        \
+               bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) =  \
+                                               (struct list_head *) (_q); \
+               bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);\
+               bfa_q_qe_init(*((struct list_head **) _qe));            \
+       } else {                                                        \
+               *((struct list_head **) (_qe)) = (struct list_head *) NULL; \
+       }                                                               \
+}
+
+/*
+ * bfa_add_tail_head - enqueue an element at the head of queue
+ */
+#define bfa_q_enq_head(_q, _qe) {                                      \
+       if (!(bfa_q_next(_qe) == NULL) && (bfa_q_prev(_qe) == NULL))    \
+               pr_err("Assertion failure: %s:%d: %d",                  \
+                       __FILE__, __LINE__,                             \
+               (bfa_q_next(_qe) == NULL) && (bfa_q_prev(_qe) == NULL));\
+       bfa_q_next(_qe) = bfa_q_next(_q);                               \
+       bfa_q_prev(_qe) = (struct list_head *) (_q);                    \
+       bfa_q_prev(bfa_q_next(_q)) = (struct list_head *) (_qe);        \
+       bfa_q_next(_q) = (struct list_head *) (_qe);                    \
+}
+
 #endif /* __CNA_H__ */
diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
new file mode 100644 (file)
index 0000000..c00e706
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# Atmel device configuration
+#
+
+config HAVE_NET_MACB
+       bool
+
+config NET_ATMEL
+       bool "Atmel devices"
+       depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200)
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y.
+         Make sure you know the name of your card. Read the Ethernet-HOWTO,
+         available from <http://www.tldp.org/docs.html#howto>.
+
+         If unsure, say Y.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the remaining Atmel network card questions. If you say Y, you will be
+         asked for your specific card in the following questions.
+
+if NET_ATMEL
+
+config ARM_AT91_ETHER
+       tristate "AT91RM9200 Ethernet support"
+       depends on ARM && ARCH_AT91RM9200
+       select MII
+       ---help---
+         If you wish to compile a kernel for the AT91RM9200 and enable
+         ethernet support, then you should always answer Y to this.
+
+config MACB
+       tristate "Atmel MACB support"
+       depends on HAVE_NET_MACB
+       select PHYLIB
+       ---help---
+         The Atmel MACB ethernet interface is found on many AT32 and AT91
+         parts. Say Y to include support for the MACB chip.
+
+         To compile this driver as a module, choose M here: the module
+         will be called macb.
+
+endif # NET_ATMEL
diff --git a/drivers/net/ethernet/cadence/Makefile b/drivers/net/ethernet/cadence/Makefile
new file mode 100644 (file)
index 0000000..9068b83
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the Atmel network device drivers.
+#
+
+obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o
+obj-$(CONFIG_MACB) += macb.o
similarity index 99%
rename from drivers/net/arm/at91_ether.c
rename to drivers/net/ethernet/cadence/at91_ether.c
index 29dc435..1b0ba8c 100644 (file)
@@ -968,7 +968,7 @@ static const struct net_device_ops at91ether_netdev_ops = {
        .ndo_stop               = at91ether_close,
        .ndo_start_xmit         = at91ether_start_xmit,
        .ndo_get_stats          = at91ether_stats,
-       .ndo_set_multicast_list = at91ether_set_multicast_list,
+       .ndo_set_rx_mode        = at91ether_set_multicast_list,
        .ndo_set_mac_address    = set_mac_address,
        .ndo_do_ioctl           = at91ether_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/macb.c
rename to drivers/net/ethernet/cadence/macb.c
index 0fcdc25..a437b46 100644 (file)
@@ -322,6 +322,9 @@ static void macb_tx(struct macb *bp)
                for (i = 0; i < TX_RING_SIZE; i++)
                        bp->tx_ring[i].ctrl = MACB_BIT(TX_USED);
 
+               /* Add wrap bit */
+               bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+
                /* free transmit buffer in upper layer*/
                for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {
                        struct ring_info *rp = &bp->tx_skb[tail];
@@ -1103,7 +1106,7 @@ static const struct net_device_ops macb_netdev_ops = {
        .ndo_open               = macb_open,
        .ndo_stop               = macb_close,
        .ndo_start_xmit         = macb_start_xmit,
-       .ndo_set_multicast_list = macb_set_rx_mode,
+       .ndo_set_rx_mode        = macb_set_rx_mode,
        .ndo_get_stats          = macb_get_stats,
        .ndo_do_ioctl           = macb_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
diff --git a/drivers/net/ethernet/chelsio/Kconfig b/drivers/net/ethernet/chelsio/Kconfig
new file mode 100644 (file)
index 0000000..2de50f9
--- /dev/null
@@ -0,0 +1,107 @@
+#
+# Chelsio device configuration
+#
+
+config NET_VENDOR_CHELSIO
+       bool "Chelsio devices"
+       default y
+       depends on PCI || INET
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Chelsio devices. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_CHELSIO
+
+config CHELSIO_T1
+       tristate "Chelsio 10Gb Ethernet support"
+       depends on PCI
+       select CRC32
+       select MDIO
+       ---help---
+         This driver supports Chelsio gigabit and 10-gigabit
+         Ethernet cards. More information about adapter features and
+         performance tuning is in <file:Documentation/networking/cxgb.txt>.
+
+         For general information about Chelsio and our products, visit
+         our website at <http://www.chelsio.com>.
+
+         For customer support, please visit our customer support page at
+         <http://www.chelsio.com/support.html>.
+
+         Please send feedback to <linux-bugs@chelsio.com>.
+
+         To compile this driver as a module, choose M here: the module
+         will be called cxgb.
+
+config CHELSIO_T1_1G
+       bool "Chelsio gigabit Ethernet support"
+       depends on CHELSIO_T1
+       ---help---
+         Enables support for Chelsio's gigabit Ethernet PCI cards.  If you
+         are using only 10G cards say 'N' here.
+
+config CHELSIO_T3
+       tristate "Chelsio Communications T3 10Gb Ethernet support"
+       depends on PCI && INET
+       select FW_LOADER
+       select MDIO
+       ---help---
+         This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
+         adapters.
+
+         For general information about Chelsio and our products, visit
+         our website at <http://www.chelsio.com>.
+
+         For customer support, please visit our customer support page at
+         <http://www.chelsio.com/support.html>.
+
+         Please send feedback to <linux-bugs@chelsio.com>.
+
+         To compile this driver as a module, choose M here: the module
+         will be called cxgb3.
+
+config CHELSIO_T4
+       tristate "Chelsio Communications T4 Ethernet support"
+       depends on PCI
+       select FW_LOADER
+       select MDIO
+       ---help---
+         This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
+         adapters.
+
+         For general information about Chelsio and our products, visit
+         our website at <http://www.chelsio.com>.
+
+         For customer support, please visit our customer support page at
+         <http://www.chelsio.com/support.html>.
+
+         Please send feedback to <linux-bugs@chelsio.com>.
+
+         To compile this driver as a module choose M here; the module
+         will be called cxgb4.
+
+config CHELSIO_T4VF
+       tristate "Chelsio Communications T4 Virtual Function Ethernet support"
+       depends on PCI
+       ---help---
+         This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
+         adapters with PCI-E SR-IOV Virtual Functions.
+
+         For general information about Chelsio and our products, visit
+         our website at <http://www.chelsio.com>.
+
+         For customer support, please visit our customer support page at
+         <http://www.chelsio.com/support.html>.
+
+         Please send feedback to <linux-bugs@chelsio.com>.
+
+         To compile this driver as a module choose M here; the module
+         will be called cxgb4vf.
+
+endif # NET_VENDOR_CHELSIO
diff --git a/drivers/net/ethernet/chelsio/Makefile b/drivers/net/ethernet/chelsio/Makefile
new file mode 100644 (file)
index 0000000..390510b
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for the Chelsio network device drivers.
+#
+
+obj-$(CONFIG_CHELSIO_T1) += cxgb/
+obj-$(CONFIG_CHELSIO_T3) += cxgb3/
+obj-$(CONFIG_CHELSIO_T4) += cxgb4/
+obj-$(CONFIG_CHELSIO_T4VF) += cxgb4vf/
similarity index 99%
rename from drivers/net/chelsio/cxgb2.c
rename to drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 3edbbc4..9993f4f 100644 (file)
@@ -964,7 +964,7 @@ static const struct net_device_ops cxgb_netdev_ops = {
        .ndo_start_xmit         = t1_start_xmit,
        .ndo_get_stats          = t1_get_stats,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = t1_set_rxmode,
+       .ndo_set_rx_mode        = t1_set_rxmode,
        .ndo_do_ioctl           = t1_ioctl,
        .ndo_change_mtu         = t1_change_mtu,
        .ndo_set_mac_address    = t1_set_mac_addr,
similarity index 99%
rename from drivers/net/cxgb3/cxgb3_main.c
rename to drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 93b41a7..29e0e42 100644 (file)
@@ -3153,7 +3153,7 @@ static const struct net_device_ops cxgb_netdev_ops = {
        .ndo_start_xmit         = t3_eth_xmit,
        .ndo_get_stats          = cxgb_get_stats,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = cxgb_set_rxmode,
+       .ndo_set_rx_mode        = cxgb_set_rxmode,
        .ndo_do_ioctl           = cxgb_ioctl,
        .ndo_change_mtu         = cxgb_change_mtu,
        .ndo_set_mac_address    = cxgb_set_mac_addr,
similarity index 99%
rename from drivers/net/cxgb4/cxgb4_main.c
rename to drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index c9957b7..90b4921 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/err.h>
 #include <linux/etherdevice.h>
 #include <linux/firmware.h>
+#include <linux/if.h>
 #include <linux/if_vlan.h>
 #include <linux/init.h>
 #include <linux/log2.h>
@@ -3639,6 +3640,8 @@ static int __devinit init_one(struct pci_dev *pdev,
                netdev->features |= netdev->hw_features | highdma;
                netdev->vlan_features = netdev->features & VLAN_FEAT;
 
+               netdev->priv_flags |= IFF_UNICAST_FLT;
+
                netdev->netdev_ops = &cxgb4_netdev_ops;
                SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
        }
similarity index 99%
rename from drivers/net/cxgb4vf/cxgb4vf_main.c
rename to drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index ec79913..da9072b 100644 (file)
@@ -2625,6 +2625,8 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
                if (pci_using_dac)
                        netdev->features |= NETIF_F_HIGHDMA;
 
+               netdev->priv_flags |= IFF_UNICAST_FLT;
+
                netdev->netdev_ops = &cxgb4vf_netdev_ops;
                SET_ETHTOOL_OPS(netdev, &cxgb4vf_ethtool_ops);
 
diff --git a/drivers/net/ethernet/cirrus/Kconfig b/drivers/net/ethernet/cirrus/Kconfig
new file mode 100644 (file)
index 0000000..e0cacf6
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# Cirrus network device configuration
+#
+
+config NET_VENDOR_CIRRUS
+       bool "Cirrus devices"
+       default y
+       depends on ARM && ARCH_EP93XX
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Cirrus cards. If you say Y, you will be asked
+         for your specific card in the following questions.
+
+if NET_VENDOR_CIRRUS
+
+config EP93XX_ETH
+       tristate "EP93xx Ethernet support"
+       depends on ARM && ARCH_EP93XX
+       select MII
+       help
+         This is a driver for the ethernet hardware included in EP93xx CPUs.
+         Say Y if you are building a kernel for EP93xx based devices.
+
+endif # NET_VENDOR_CIRRUS
diff --git a/drivers/net/ethernet/cirrus/Makefile b/drivers/net/ethernet/cirrus/Makefile
new file mode 100644 (file)
index 0000000..9905ea2
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Cirrus network device drivers.
+#
+
+obj-$(CONFIG_EP93XX_ETH) += ep93xx_eth.o
diff --git a/drivers/net/ethernet/cisco/Kconfig b/drivers/net/ethernet/cisco/Kconfig
new file mode 100644 (file)
index 0000000..94606f7
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# Cisco device configuration
+#
+
+config NET_VENDOR_CISCO
+       bool "Cisco devices"
+       default y
+       depends on PCI && INET
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Cisco cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_CISCO
+
+source "drivers/net/ethernet/cisco/enic/Kconfig"
+
+endif # NET_VENDOR_CISCO
diff --git a/drivers/net/ethernet/cisco/Makefile b/drivers/net/ethernet/cisco/Makefile
new file mode 100644 (file)
index 0000000..6c7437b
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Cisco device drivers.
+#
+
+obj-$(CONFIG_ENIC) += enic/
diff --git a/drivers/net/ethernet/cisco/enic/Kconfig b/drivers/net/ethernet/cisco/enic/Kconfig
new file mode 100644 (file)
index 0000000..9cc706a
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Cisco device configuration
+#
+
+config ENIC
+       tristate "Cisco VIC Ethernet NIC Support"
+       depends on PCI && INET
+       ---help---
+         This enables the support for the Cisco VIC Ethernet card.
similarity index 99%
rename from drivers/net/enic/enic_main.c
rename to drivers/net/ethernet/cisco/enic/enic_main.c
index 67a27cd..c751c25 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/if_vlan.h>
 #include <linux/ethtool.h>
@@ -2103,7 +2104,6 @@ static const struct net_device_ops enic_netdev_dynamic_ops = {
        .ndo_get_stats64        = enic_get_stats,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_rx_mode        = enic_set_rx_mode,
-       .ndo_set_multicast_list = enic_set_rx_mode,
        .ndo_set_mac_address    = enic_set_mac_address_dynamic,
        .ndo_change_mtu         = enic_change_mtu,
        .ndo_vlan_rx_add_vid    = enic_vlan_rx_add_vid,
@@ -2125,7 +2125,6 @@ static const struct net_device_ops enic_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = enic_set_mac_address,
        .ndo_set_rx_mode        = enic_set_rx_mode,
-       .ndo_set_multicast_list = enic_set_rx_mode,
        .ndo_change_mtu         = enic_change_mtu,
        .ndo_vlan_rx_add_vid    = enic_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid   = enic_vlan_rx_kill_vid,
@@ -2442,6 +2441,8 @@ static int __devinit enic_probe(struct pci_dev *pdev,
        if (using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
 
+       netdev->priv_flags |= IFF_UNICAST_FLT;
+
        err = register_netdev(netdev);
        if (err) {
                dev_err(dev, "Cannot register net device, aborting\n");
diff --git a/drivers/net/ethernet/davicom/Kconfig b/drivers/net/ethernet/davicom/Kconfig
new file mode 100644 (file)
index 0000000..73c5d20
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# Davicom device configuration
+#
+
+config DM9000
+       tristate "DM9000 support"
+       depends on ARM || BLACKFIN || MIPS
+       select CRC32
+       select MII
+       ---help---
+         Support for DM9000 chipset.
+
+         To compile this driver as a module, choose M here.  The module
+         will be called dm9000.
+
+config DM9000_FORCE_SIMPLE_PHY_POLL
+       bool "Force simple NSR based PHY polling"
+       depends on DM9000
+       ---help---
+         This configuration forces the DM9000 to use the NSR's LinkStatus
+         bit to determine if the link is up or down instead of the more
+         costly MII PHY reads. Note, this will not work if the chip is
+         operating with an external PHY.
diff --git a/drivers/net/ethernet/davicom/Makefile b/drivers/net/ethernet/davicom/Makefile
new file mode 100644 (file)
index 0000000..74b31f0
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Davicom device drivers.
+#
+
+obj-$(CONFIG_DM9000) += dm9000.o
similarity index 99%
rename from drivers/net/dm9000.c
rename to drivers/net/ethernet/davicom/dm9000.c
index 8ef31dc..438f458 100644 (file)
@@ -56,6 +56,13 @@ static int watchdog = 5000;
 module_param(watchdog, int, 0400);
 MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
 
+/*
+ * Debug messages level
+ */
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "dm9000 debug level (0-4)");
+
 /* DM9000 register address locking.
  *
  * The DM9000 uses an address register to control where data written
@@ -103,7 +110,6 @@ typedef struct board_info {
        unsigned int    flags;
        unsigned int    in_suspend :1;
        unsigned int    wake_supported :1;
-       int             debug_level;
 
        enum dm9000_type type;
 
@@ -138,8 +144,7 @@ typedef struct board_info {
 /* debug code */
 
 #define dm9000_dbg(db, lev, msg...) do {               \
-       if ((lev) < CONFIG_DM9000_DEBUGLEVEL &&         \
-           (lev) < db->debug_level) {                  \
+       if ((lev) < debug) {                            \
                dev_dbg(db->dev, msg);                  \
        }                                               \
 } while (0)
@@ -1339,7 +1344,7 @@ static const struct net_device_ops dm9000_netdev_ops = {
        .ndo_stop               = dm9000_stop,
        .ndo_start_xmit         = dm9000_start_xmit,
        .ndo_tx_timeout         = dm9000_timeout,
-       .ndo_set_multicast_list = dm9000_hash_table,
+       .ndo_set_rx_mode        = dm9000_hash_table,
        .ndo_do_ioctl           = dm9000_ioctl,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_features       = dm9000_set_features,
diff --git a/drivers/net/ethernet/dec/Kconfig b/drivers/net/ethernet/dec/Kconfig
new file mode 100644 (file)
index 0000000..3794027
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# Digital Equipment Inc network device configuration
+#
+
+config NET_VENDOR_DEC
+       bool "Digital Equipment devices"
+       default y
+       depends on PCI || EISA || CARDBUS
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about DEC cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_DEC
+
+config EWRK3
+       tristate "EtherWORKS 3 (DE203, DE204, DE205) support"
+       depends on ISA
+       select CRC32
+       ---help---
+         This driver supports the DE203, DE204 and DE205 network (Ethernet)
+         cards. If this is for you, say Y and read
+         <file:Documentation/networking/ewrk3.txt> in the kernel source as
+         well as the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ewrk3.
+
+source "drivers/net/ethernet/dec/tulip/Kconfig"
+
+endif # NET_VENDOR_DEC
diff --git a/drivers/net/ethernet/dec/Makefile b/drivers/net/ethernet/dec/Makefile
new file mode 100644 (file)
index 0000000..1b01ed8
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the Digital Equipment Inc. network device drivers.
+#
+
+obj-$(CONFIG_EWRK3) += ewrk3.o
+obj-$(CONFIG_NET_TULIP) += tulip/
similarity index 99%
rename from drivers/net/ewrk3.c
rename to drivers/net/ethernet/dec/ewrk3.c
index 05a5f71..f9df5e4 100644 (file)
@@ -393,7 +393,7 @@ static const struct net_device_ops ewrk3_netdev_ops = {
        .ndo_open               = ewrk3_open,
        .ndo_start_xmit         = ewrk3_queue_pkt,
        .ndo_stop               = ewrk3_close,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_do_ioctl           = ewrk3_ioctl,
        .ndo_tx_timeout         = ewrk3_timeout,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 96%
rename from drivers/net/tulip/Kconfig
rename to drivers/net/ethernet/dec/tulip/Kconfig
index 1f8d4a8..f6af772 100644 (file)
@@ -2,10 +2,10 @@
 # Tulip family network device configuration
 #
 
-menuconfig NET_TULIP
-       bool "\"Tulip\" family network device support"
-       depends on PCI || EISA || CARDBUS
-       help
+config NET_TULIP
+       bool "DEC - Tulip devices"
+       depends on (PCI || EISA || CARDBUS)
+       ---help---
          This selects the "Tulip" family of EISA/PCI network cards.
 
 if NET_TULIP
@@ -32,7 +32,7 @@ config DE2104X_DSL
        depends on DE2104X
        range 0 31
        default 0
-       help
+       ---help---
          Setting this value allows to align ring buffer descriptors into their
          own cache lines. Value of 4 corresponds to the typical 32 byte line
          (the descriptor is 16 bytes). This is necessary on systems that lack
@@ -59,7 +59,7 @@ config TULIP
 config TULIP_MWI
        bool "New bus configuration (EXPERIMENTAL)"
        depends on TULIP && EXPERIMENTAL
-       help
+       ---help---
          This configures your Tulip card specifically for the card and
          system cache line size type you are using.
 
@@ -70,7 +70,7 @@ config TULIP_MWI
 config TULIP_MMIO
        bool "Use PCI shared mem for NIC registers"
        depends on TULIP
-       help
+       ---help---
          Use PCI shared memory for the NIC registers, rather than going through
          the Tulip's PIO (programmed I/O ports).  Faster, but could produce
          obscure bugs if your mainboard has memory controller timing issues.
@@ -79,7 +79,7 @@ config TULIP_MMIO
 config TULIP_NAPI
        bool "Use RX polling (NAPI)"
        depends on TULIP
-       help
+       ---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.
@@ -107,7 +107,7 @@ config TULIP_DM910X
 
 config DE4X5
        tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA"
-       depends on PCI || EISA
+       depends on (PCI || EISA)
        select CRC32
        ---help---
          This is support for the DIGITAL series of PCI/EISA Ethernet cards.
@@ -126,7 +126,7 @@ config WINBOND_840
        depends on PCI
        select CRC32
        select MII
-       help
+       ---help---
          This driver is for the Winbond W89c840 chip.  It also works with 
          the TX9882 chip on the Compex RL100-ATX board.
          More specific information and updates are available from
similarity index 99%
rename from drivers/net/tulip/de2104x.c
rename to drivers/net/ethernet/dec/tulip/de2104x.c
index ce90efc..1427739 100644 (file)
@@ -1956,7 +1956,7 @@ bad_srom:
 static const struct net_device_ops de_netdev_ops = {
        .ndo_open               = de_open,
        .ndo_stop               = de_close,
-       .ndo_set_multicast_list = de_set_rx_mode,
+       .ndo_set_rx_mode        = de_set_rx_mode,
        .ndo_start_xmit         = de_start_xmit,
        .ndo_get_stats          = de_get_stats,
        .ndo_tx_timeout         = de_tx_timeout,
similarity index 99%
rename from drivers/net/tulip/de4x5.c
rename to drivers/net/ethernet/dec/tulip/de4x5.c
index 959b410..871bcaa 100644 (file)
@@ -1084,7 +1084,7 @@ static const struct net_device_ops de4x5_netdev_ops = {
     .ndo_stop          = de4x5_close,
     .ndo_start_xmit    = de4x5_queue_pkt,
     .ndo_get_stats     = de4x5_get_stats,
-    .ndo_set_multicast_list = set_multicast_list,
+    .ndo_set_rx_mode   = set_multicast_list,
     .ndo_do_ioctl      = de4x5_ioctl,
     .ndo_change_mtu    = eth_change_mtu,
     .ndo_set_mac_address= eth_mac_addr,
similarity index 99%
rename from drivers/net/tulip/dmfe.c
rename to drivers/net/ethernet/dec/tulip/dmfe.c
index 9a21ca3..17b11ee 100644 (file)
@@ -356,7 +356,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_open               = dmfe_open,
        .ndo_stop               = dmfe_stop,
        .ndo_start_xmit         = dmfe_start_xmit,
-       .ndo_set_multicast_list = dmfe_set_filter_mode,
+       .ndo_set_rx_mode        = dmfe_set_filter_mode,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/tulip/tulip_core.c
rename to drivers/net/ethernet/dec/tulip/tulip_core.c
index 1246998..011f67c 100644 (file)
@@ -1291,7 +1291,7 @@ static const struct net_device_ops tulip_netdev_ops = {
        .ndo_stop               = tulip_close,
        .ndo_get_stats          = tulip_get_stats,
        .ndo_do_ioctl           = private_ioctl,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/tulip/uli526x.c
rename to drivers/net/ethernet/dec/tulip/uli526x.c
index 9e63f40..7a44a7a 100644 (file)
@@ -259,7 +259,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_open               = uli526x_open,
        .ndo_stop               = uli526x_stop,
        .ndo_start_xmit         = uli526x_start_xmit,
-       .ndo_set_multicast_list = uli526x_set_filter_mode,
+       .ndo_set_rx_mode        = uli526x_set_filter_mode,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/tulip/winbond-840.c
rename to drivers/net/ethernet/dec/tulip/winbond-840.c
index 862eadf..4d01219 100644 (file)
@@ -350,7 +350,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_stop               = netdev_close,
        .ndo_start_xmit         = start_tx,
        .ndo_get_stats          = get_stats,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_do_ioctl           = netdev_ioctl,
        .ndo_tx_timeout         = tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
diff --git a/drivers/net/ethernet/dlink/Kconfig b/drivers/net/ethernet/dlink/Kconfig
new file mode 100644 (file)
index 0000000..84a28a6
--- /dev/null
@@ -0,0 +1,85 @@
+#
+# D-Link device configuration
+#
+
+config NET_VENDOR_DLINK
+       bool "D-Link devices"
+       default y
+       depends on PCI || PARPORT
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about D-Link devices. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_DLINK
+
+config DE600
+       tristate "D-Link DE600 pocket adapter support"
+       depends on PARPORT
+       ---help---
+         This is a network (Ethernet) device which attaches to your parallel
+         port. Read <file:Documentation/networking/DLINK.txt> as well as the
+         Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>, if you want to use
+         this. It is possible to have several devices share a single parallel
+         port and it is safe to compile the corresponding drivers into the
+         kernel.
+
+         To compile this driver as a module, choose M here: the module
+         will be called de600.
+
+config DE620
+       tristate "D-Link DE620 pocket adapter support"
+       depends on PARPORT
+       ---help---
+         This is a network (Ethernet) device which attaches to your parallel
+         port. Read <file:Documentation/networking/DLINK.txt> as well as the
+         Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>, if you want to use
+         this. It is possible to have several devices share a single parallel
+         port and it is safe to compile the corresponding drivers into the
+         kernel.
+
+         To compile this driver as a module, choose M here: the module
+         will be called de620.
+
+config DL2K
+       tristate "DL2000/TC902x-based Gigabit Ethernet support"
+       depends on PCI
+       select CRC32
+       ---help---
+         This driver supports DL2000/TC902x-based Gigabit ethernet cards,
+         which includes
+         D-Link DGE-550T Gigabit Ethernet Adapter.
+         D-Link DL2000-based Gigabit Ethernet Adapter.
+         Sundance/Tamarack TC902x Gigabit Ethernet Adapter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called dl2k.
+
+config SUNDANCE
+       tristate "Sundance Alta support"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         This driver is for the Sundance "Alta" chip.
+         More specific information and updates are available from
+         <http://www.scyld.com/network/sundance.html>.
+
+config SUNDANCE_MMIO
+       bool "Use MMIO instead of PIO"
+       depends on SUNDANCE
+       ---help---
+         Enable memory-mapped I/O for interaction with Sundance NIC registers.
+         Do NOT enable this by default, PIO (enabled when MMIO is disabled)
+         is known to solve bugs on certain chips.
+
+         If unsure, say N.
+
+endif # NET_VENDOR_DLINK
diff --git a/drivers/net/ethernet/dlink/Makefile b/drivers/net/ethernet/dlink/Makefile
new file mode 100644 (file)
index 0000000..c705eaa
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for the D-Link network device drivers.
+#
+
+obj-$(CONFIG_DE600) += de600.o
+obj-$(CONFIG_DE620) += de620.o
+obj-$(CONFIG_DL2K) += dl2k.o
+obj-$(CONFIG_SUNDANCE) += sundance.o
similarity index 99%
rename from drivers/net/de620.c
rename to drivers/net/ethernet/dlink/de620.c
index 1c51a75..3b934ab 100644 (file)
@@ -767,7 +767,7 @@ static const struct net_device_ops de620_netdev_ops = {
        .ndo_stop               = de620_close,
        .ndo_start_xmit         = de620_start_xmit,
        .ndo_tx_timeout         = de620_timeout,
-       .ndo_set_multicast_list = de620_set_multicast_list,
+       .ndo_set_rx_mode        = de620_set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 95%
rename from drivers/net/dl2k.c
rename to drivers/net/ethernet/dlink/dl2k.c
index ed73e4a..b2dc2c8 100644 (file)
@@ -92,7 +92,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_get_stats          = get_stats,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_set_multicast_list = set_multicast,
+       .ndo_set_rx_mode        = set_multicast,
        .ndo_do_ioctl           = rio_ioctl,
        .ndo_tx_timeout         = rio_tx_timeout,
        .ndo_change_mtu         = change_mtu,
@@ -1428,7 +1428,7 @@ mii_wait_link (struct net_device *dev, int wait)
 
        do {
                bmsr = mii_read (dev, phy_addr, MII_BMSR);
-               if (bmsr & MII_BMSR_LINK_STATUS)
+               if (bmsr & BMSR_LSTATUS)
                        return 0;
                mdelay (1);
        } while (--wait > 0);
@@ -1449,60 +1449,60 @@ mii_get_media (struct net_device *dev)
 
        bmsr = mii_read (dev, phy_addr, MII_BMSR);
        if (np->an_enable) {
-               if (!(bmsr & MII_BMSR_AN_COMPLETE)) {
+               if (!(bmsr & BMSR_ANEGCOMPLETE)) {
                        /* Auto-Negotiation not completed */
                        return -1;
                }
-               negotiate = mii_read (dev, phy_addr, MII_ANAR) &
-                       mii_read (dev, phy_addr, MII_ANLPAR);
-               mscr = mii_read (dev, phy_addr, MII_MSCR);
-               mssr = mii_read (dev, phy_addr, MII_MSSR);
-               if (mscr & MII_MSCR_1000BT_FD && mssr & MII_MSSR_LP_1000BT_FD) {
+               negotiate = mii_read (dev, phy_addr, MII_ADVERTISE) &
+                       mii_read (dev, phy_addr, MII_LPA);
+               mscr = mii_read (dev, phy_addr, MII_CTRL1000);
+               mssr = mii_read (dev, phy_addr, MII_STAT1000);
+               if (mscr & ADVERTISE_1000FULL && mssr & LPA_1000FULL) {
                        np->speed = 1000;
                        np->full_duplex = 1;
                        printk (KERN_INFO "Auto 1000 Mbps, Full duplex\n");
-               } else if (mscr & MII_MSCR_1000BT_HD && mssr & MII_MSSR_LP_1000BT_HD) {
+               } else if (mscr & ADVERTISE_1000HALF && mssr & LPA_1000HALF) {
                        np->speed = 1000;
                        np->full_duplex = 0;
                        printk (KERN_INFO "Auto 1000 Mbps, Half duplex\n");
-               } else if (negotiate & MII_ANAR_100BX_FD) {
+               } else if (negotiate & ADVERTISE_100FULL) {
                        np->speed = 100;
                        np->full_duplex = 1;
                        printk (KERN_INFO "Auto 100 Mbps, Full duplex\n");
-               } else if (negotiate & MII_ANAR_100BX_HD) {
+               } else if (negotiate & ADVERTISE_100HALF) {
                        np->speed = 100;
                        np->full_duplex = 0;
                        printk (KERN_INFO "Auto 100 Mbps, Half duplex\n");
-               } else if (negotiate & MII_ANAR_10BT_FD) {
+               } else if (negotiate & ADVERTISE_10FULL) {
                        np->speed = 10;
                        np->full_duplex = 1;
                        printk (KERN_INFO "Auto 10 Mbps, Full duplex\n");
-               } else if (negotiate & MII_ANAR_10BT_HD) {
+               } else if (negotiate & ADVERTISE_10HALF) {
                        np->speed = 10;
                        np->full_duplex = 0;
                        printk (KERN_INFO "Auto 10 Mbps, Half duplex\n");
                }
-               if (negotiate & MII_ANAR_PAUSE) {
+               if (negotiate & ADVERTISE_PAUSE_CAP) {
                        np->tx_flow &= 1;
                        np->rx_flow &= 1;
-               } else if (negotiate & MII_ANAR_ASYMMETRIC) {
+               } else if (negotiate & ADVERTISE_PAUSE_ASYM) {
                        np->tx_flow = 0;
                        np->rx_flow &= 1;
                }
                /* else tx_flow, rx_flow = user select  */
        } else {
                __u16 bmcr = mii_read (dev, phy_addr, MII_BMCR);
-               switch (bmcr & (MII_BMCR_SPEED_100 | MII_BMCR_SPEED_1000)) {
-               case MII_BMCR_SPEED_1000:
+               switch (bmcr & (BMCR_SPEED100 | BMCR_SPEED1000)) {
+               case BMCR_SPEED1000:
                        printk (KERN_INFO "Operating at 1000 Mbps, ");
                        break;
-               case MII_BMCR_SPEED_100:
+               case BMCR_SPEED100:
                        printk (KERN_INFO "Operating at 100 Mbps, ");
                        break;
                case 0:
                        printk (KERN_INFO "Operating at 10 Mbps, ");
                }
-               if (bmcr & MII_BMCR_DUPLEX_MODE) {
+               if (bmcr & BMCR_FULLDPLX) {
                        printk (KERN_CONT "Full duplex\n");
                } else {
                        printk (KERN_CONT "Half duplex\n");
@@ -1536,24 +1536,22 @@ mii_set_media (struct net_device *dev)
        if (np->an_enable) {
                /* Advertise capabilities */
                bmsr = mii_read (dev, phy_addr, MII_BMSR);
-               anar = mii_read (dev, phy_addr, MII_ANAR) &
-                            ~MII_ANAR_100BX_FD &
-                            ~MII_ANAR_100BX_HD &
-                            ~MII_ANAR_100BT4 &
-                            ~MII_ANAR_10BT_FD &
-                            ~MII_ANAR_10BT_HD;
-               if (bmsr & MII_BMSR_100BX_FD)
-                       anar |= MII_ANAR_100BX_FD;
-               if (bmsr & MII_BMSR_100BX_HD)
-                       anar |= MII_ANAR_100BX_HD;
-               if (bmsr & MII_BMSR_100BT4)
-                       anar |= MII_ANAR_100BT4;
-               if (bmsr & MII_BMSR_10BT_FD)
-                       anar |= MII_ANAR_10BT_FD;
-               if (bmsr & MII_BMSR_10BT_HD)
-                       anar |= MII_ANAR_10BT_HD;
-               anar |= MII_ANAR_PAUSE | MII_ANAR_ASYMMETRIC;
-               mii_write (dev, phy_addr, MII_ANAR, anar);
+               anar = mii_read (dev, phy_addr, MII_ADVERTISE) &
+                       ~(ADVERTISE_100FULL | ADVERTISE_10FULL |
+                         ADVERTISE_100HALF | ADVERTISE_10HALF |
+                         ADVERTISE_100BASE4);
+               if (bmsr & BMSR_100FULL)
+                       anar |= ADVERTISE_100FULL;
+               if (bmsr & BMSR_100HALF)
+                       anar |= ADVERTISE_100HALF;
+               if (bmsr & BMSR_100BASE4)
+                       anar |= ADVERTISE_100BASE4;
+               if (bmsr & BMSR_10FULL)
+                       anar |= ADVERTISE_10FULL;
+               if (bmsr & BMSR_10HALF)
+                       anar |= ADVERTISE_10HALF;
+               anar |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+               mii_write (dev, phy_addr, MII_ADVERTISE, anar);
 
                /* Enable Auto crossover */
                pscr = mii_read (dev, phy_addr, MII_PHY_SCR);
@@ -1561,8 +1559,8 @@ mii_set_media (struct net_device *dev)
                mii_write (dev, phy_addr, MII_PHY_SCR, pscr);
 
                /* Soft reset PHY */
-               mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET);
-               bmcr = MII_BMCR_AN_ENABLE | MII_BMCR_RESTART_AN | MII_BMCR_RESET;
+               mii_write (dev, phy_addr, MII_BMCR, BMCR_RESET);
+               bmcr = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET;
                mii_write (dev, phy_addr, MII_BMCR, bmcr);
                mdelay(1);
        } else {
@@ -1574,7 +1572,7 @@ mii_set_media (struct net_device *dev)
 
                /* 2) PHY Reset */
                bmcr = mii_read (dev, phy_addr, MII_BMCR);
-               bmcr |= MII_BMCR_RESET;
+               bmcr |= BMCR_RESET;
                mii_write (dev, phy_addr, MII_BMCR, bmcr);
 
                /* 3) Power Down */
@@ -1583,25 +1581,25 @@ mii_set_media (struct net_device *dev)
                mdelay (100);   /* wait a certain time */
 
                /* 4) Advertise nothing */
-               mii_write (dev, phy_addr, MII_ANAR, 0);
+               mii_write (dev, phy_addr, MII_ADVERTISE, 0);
 
                /* 5) Set media and Power Up */
-               bmcr = MII_BMCR_POWER_DOWN;
+               bmcr = BMCR_PDOWN;
                if (np->speed == 100) {
-                       bmcr |= MII_BMCR_SPEED_100;
+                       bmcr |= BMCR_SPEED100;
                        printk (KERN_INFO "Manual 100 Mbps, ");
                } else if (np->speed == 10) {
                        printk (KERN_INFO "Manual 10 Mbps, ");
                }
                if (np->full_duplex) {
-                       bmcr |= MII_BMCR_DUPLEX_MODE;
+                       bmcr |= BMCR_FULLDPLX;
                        printk (KERN_CONT "Full duplex\n");
                } else {
                        printk (KERN_CONT "Half duplex\n");
                }
 #if 0
                /* Set 1000BaseT Master/Slave setting */
-               mscr = mii_read (dev, phy_addr, MII_MSCR);
+               mscr = mii_read (dev, phy_addr, MII_CTRL1000);
                mscr |= MII_MSCR_CFG_ENABLE;
                mscr &= ~MII_MSCR_CFG_VALUE = 0;
 #endif
@@ -1624,7 +1622,7 @@ mii_get_media_pcs (struct net_device *dev)
 
        bmsr = mii_read (dev, phy_addr, PCS_BMSR);
        if (np->an_enable) {
-               if (!(bmsr & MII_BMSR_AN_COMPLETE)) {
+               if (!(bmsr & BMSR_ANEGCOMPLETE)) {
                        /* Auto-Negotiation not completed */
                        return -1;
                }
@@ -1649,7 +1647,7 @@ mii_get_media_pcs (struct net_device *dev)
        } else {
                __u16 bmcr = mii_read (dev, phy_addr, PCS_BMCR);
                printk (KERN_INFO "Operating at 1000 Mbps, ");
-               if (bmcr & MII_BMCR_DUPLEX_MODE) {
+               if (bmcr & BMCR_FULLDPLX) {
                        printk (KERN_CONT "Full duplex\n");
                } else {
                        printk (KERN_CONT "Half duplex\n");
@@ -1682,7 +1680,7 @@ mii_set_media_pcs (struct net_device *dev)
        if (np->an_enable) {
                /* Advertise capabilities */
                esr = mii_read (dev, phy_addr, PCS_ESR);
-               anar = mii_read (dev, phy_addr, MII_ANAR) &
+               anar = mii_read (dev, phy_addr, MII_ADVERTISE) &
                        ~PCS_ANAR_HALF_DUPLEX &
                        ~PCS_ANAR_FULL_DUPLEX;
                if (esr & (MII_ESR_1000BT_HD | MII_ESR_1000BX_HD))
@@ -1690,22 +1688,21 @@ mii_set_media_pcs (struct net_device *dev)
                if (esr & (MII_ESR_1000BT_FD | MII_ESR_1000BX_FD))
                        anar |= PCS_ANAR_FULL_DUPLEX;
                anar |= PCS_ANAR_PAUSE | PCS_ANAR_ASYMMETRIC;
-               mii_write (dev, phy_addr, MII_ANAR, anar);
+               mii_write (dev, phy_addr, MII_ADVERTISE, anar);
 
                /* Soft reset PHY */
-               mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET);
-               bmcr = MII_BMCR_AN_ENABLE | MII_BMCR_RESTART_AN |
-                      MII_BMCR_RESET;
+               mii_write (dev, phy_addr, MII_BMCR, BMCR_RESET);
+               bmcr = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET;
                mii_write (dev, phy_addr, MII_BMCR, bmcr);
                mdelay(1);
        } else {
                /* Force speed setting */
                /* PHY Reset */
-               bmcr = MII_BMCR_RESET;
+               bmcr = BMCR_RESET;
                mii_write (dev, phy_addr, MII_BMCR, bmcr);
                mdelay(10);
                if (np->full_duplex) {
-                       bmcr = MII_BMCR_DUPLEX_MODE;
+                       bmcr = BMCR_FULLDPLX;
                        printk (KERN_INFO "Manual full duplex\n");
                } else {
                        bmcr = 0;
@@ -1715,7 +1712,7 @@ mii_set_media_pcs (struct net_device *dev)
                mdelay(10);
 
                /*  Advertise nothing */
-               mii_write (dev, phy_addr, MII_ANAR, 0);
+               mii_write (dev, phy_addr, MII_ADVERTISE, 0);
        }
        return 0;
 }
similarity index 81%
rename from drivers/net/dl2k.h
rename to drivers/net/ethernet/dlink/dl2k.h
index 7caab3d..ba0adca 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/crc32.h>
 #include <linux/ethtool.h>
+#include <linux/mii.h>
 #include <linux/bitops.h>
 #include <asm/processor.h>     /* Processor type for cache alignment. */
 #include <asm/io.h>
@@ -271,20 +272,9 @@ enum RFS_bits {
 #define MII_RESET_TIME_OUT             10000
 /* MII register */
 enum _mii_reg {
-       MII_BMCR = 0,
-       MII_BMSR = 1,
-       MII_PHY_ID1 = 2,
-       MII_PHY_ID2 = 3,
-       MII_ANAR = 4,
-       MII_ANLPAR = 5,
-       MII_ANER = 6,
-       MII_ANNPT = 7,
-       MII_ANLPRNP = 8,
-       MII_MSCR = 9,
-       MII_MSSR = 10,
-       MII_ESR = 15,
        MII_PHY_SCR = 16,
 };
+
 /* PCS register */
 enum _pcs_reg {
        PCS_BMCR = 0,
@@ -297,102 +287,6 @@ enum _pcs_reg {
        PCS_ESR = 15,
 };
 
-/* Basic Mode Control Register */
-enum _mii_bmcr {
-       MII_BMCR_RESET = 0x8000,
-       MII_BMCR_LOOP_BACK = 0x4000,
-       MII_BMCR_SPEED_LSB = 0x2000,
-       MII_BMCR_AN_ENABLE = 0x1000,
-       MII_BMCR_POWER_DOWN = 0x0800,
-       MII_BMCR_ISOLATE = 0x0400,
-       MII_BMCR_RESTART_AN = 0x0200,
-       MII_BMCR_DUPLEX_MODE = 0x0100,
-       MII_BMCR_COL_TEST = 0x0080,
-       MII_BMCR_SPEED_MSB = 0x0040,
-       MII_BMCR_SPEED_RESERVED = 0x003f,
-       MII_BMCR_SPEED_10 = 0,
-       MII_BMCR_SPEED_100 = MII_BMCR_SPEED_LSB,
-       MII_BMCR_SPEED_1000 = MII_BMCR_SPEED_MSB,
-};
-
-/* Basic Mode Status Register */
-enum _mii_bmsr {
-       MII_BMSR_100BT4 = 0x8000,
-       MII_BMSR_100BX_FD = 0x4000,
-       MII_BMSR_100BX_HD = 0x2000,
-       MII_BMSR_10BT_FD = 0x1000,
-       MII_BMSR_10BT_HD = 0x0800,
-       MII_BMSR_100BT2_FD = 0x0400,
-       MII_BMSR_100BT2_HD = 0x0200,
-       MII_BMSR_EXT_STATUS = 0x0100,
-       MII_BMSR_PREAMBLE_SUPP = 0x0040,
-       MII_BMSR_AN_COMPLETE = 0x0020,
-       MII_BMSR_REMOTE_FAULT = 0x0010,
-       MII_BMSR_AN_ABILITY = 0x0008,
-       MII_BMSR_LINK_STATUS = 0x0004,
-       MII_BMSR_JABBER_DETECT = 0x0002,
-       MII_BMSR_EXT_CAP = 0x0001,
-};
-
-/* ANAR */
-enum _mii_anar {
-       MII_ANAR_NEXT_PAGE = 0x8000,
-       MII_ANAR_REMOTE_FAULT = 0x4000,
-       MII_ANAR_ASYMMETRIC = 0x0800,
-       MII_ANAR_PAUSE = 0x0400,
-       MII_ANAR_100BT4 = 0x0200,
-       MII_ANAR_100BX_FD = 0x0100,
-       MII_ANAR_100BX_HD = 0x0080,
-       MII_ANAR_10BT_FD = 0x0020,
-       MII_ANAR_10BT_HD = 0x0010,
-       MII_ANAR_SELECTOR = 0x001f,
-       MII_IEEE8023_CSMACD = 0x0001,
-};
-
-/* ANLPAR */
-enum _mii_anlpar {
-       MII_ANLPAR_NEXT_PAGE = MII_ANAR_NEXT_PAGE,
-       MII_ANLPAR_REMOTE_FAULT = MII_ANAR_REMOTE_FAULT,
-       MII_ANLPAR_ASYMMETRIC = MII_ANAR_ASYMMETRIC,
-       MII_ANLPAR_PAUSE = MII_ANAR_PAUSE,
-       MII_ANLPAR_100BT4 = MII_ANAR_100BT4,
-       MII_ANLPAR_100BX_FD = MII_ANAR_100BX_FD,
-       MII_ANLPAR_100BX_HD = MII_ANAR_100BX_HD,
-       MII_ANLPAR_10BT_FD = MII_ANAR_10BT_FD,
-       MII_ANLPAR_10BT_HD = MII_ANAR_10BT_HD,
-       MII_ANLPAR_SELECTOR = MII_ANAR_SELECTOR,
-};
-
-/* Auto-Negotiation Expansion Register */
-enum _mii_aner {
-       MII_ANER_PAR_DETECT_FAULT = 0x0010,
-       MII_ANER_LP_NEXTPAGABLE = 0x0008,
-       MII_ANER_NETXTPAGABLE = 0x0004,
-       MII_ANER_PAGE_RECEIVED = 0x0002,
-       MII_ANER_LP_NEGOTIABLE = 0x0001,
-};
-
-/* MASTER-SLAVE Control Register */
-enum _mii_mscr {
-       MII_MSCR_TEST_MODE = 0xe000,
-       MII_MSCR_CFG_ENABLE = 0x1000,
-       MII_MSCR_CFG_VALUE = 0x0800,
-       MII_MSCR_PORT_VALUE = 0x0400,
-       MII_MSCR_1000BT_FD = 0x0200,
-       MII_MSCR_1000BT_HD = 0X0100,
-};
-
-/* MASTER-SLAVE Status Register */
-enum _mii_mssr {
-       MII_MSSR_CFG_FAULT = 0x8000,
-       MII_MSSR_CFG_RES = 0x4000,
-       MII_MSSR_LOCAL_RCV_STATUS = 0x2000,
-       MII_MSSR_REMOTE_RCVR = 0x1000,
-       MII_MSSR_LP_1000BT_FD = 0x0800,
-       MII_MSSR_LP_1000BT_HD = 0x0400,
-       MII_MSSR_IDLE_ERR_COUNT = 0x00ff,
-};
-
 /* IEEE Extened Status Register */
 enum _mii_esr {
        MII_ESR_1000BX_FD = 0x8000,
similarity index 99%
rename from drivers/net/sundance.c
rename to drivers/net/ethernet/dlink/sundance.c
index 4793df8..dcd7f7a 100644 (file)
@@ -464,7 +464,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_stop               = netdev_close,
        .ndo_start_xmit         = start_tx,
        .ndo_get_stats          = get_stats,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_do_ioctl           = netdev_ioctl,
        .ndo_tx_timeout         = tx_timeout,
        .ndo_change_mtu         = change_mtu,
diff --git a/drivers/net/ethernet/emulex/Kconfig b/drivers/net/ethernet/emulex/Kconfig
new file mode 100644 (file)
index 0000000..7a28a64
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# Emulex driver configuration
+#
+
+config NET_VENDOR_EMULEX
+       bool "Emulex devices"
+       default y
+       depends on PCI && INET
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Emulex cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_EMULEX
+
+source "drivers/net/ethernet/emulex/benet/Kconfig"
+
+endif # NET_VENDOR_EMULEX
diff --git a/drivers/net/ethernet/emulex/Makefile b/drivers/net/ethernet/emulex/Makefile
new file mode 100644 (file)
index 0000000..ea8ec57
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Emulex device drivers.
+#
+
+obj-$(CONFIG_BE2NET) += benet/
diff --git a/drivers/net/ethernet/emulex/benet/Kconfig b/drivers/net/ethernet/emulex/benet/Kconfig
new file mode 100644 (file)
index 0000000..804db04
--- /dev/null
@@ -0,0 +1,6 @@
+config BE2NET
+       tristate "ServerEngines' 10Gbps NIC - BladeEngine"
+       depends on PCI && INET
+       ---help---
+         This driver implements the NIC functionality for ServerEngines'
+         10Gbps network adapter - BladeEngine.
similarity index 84%
rename from drivers/net/benet/be.h
rename to drivers/net/ethernet/emulex/benet/be.h
index c85768c..c5f0516 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/interrupt.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/u64_stats_sync.h>
 
 #include "be_hw.h"
 
@@ -167,15 +168,15 @@ struct be_mcc_obj {
 };
 
 struct be_tx_stats {
-       u32 be_tx_reqs;         /* number of TX requests initiated */
-       u32 be_tx_stops;        /* number of times TX Q was stopped */
-       u32 be_tx_wrbs;         /* number of tx WRBs used */
-       u32 be_tx_compl;        /* number of tx completion entries processed */
-       ulong be_tx_jiffies;
-       u64 be_tx_bytes;
-       u64 be_tx_bytes_prev;
-       u64 be_tx_pkts;
-       u32 be_tx_rate;
+       u64 tx_bytes;
+       u64 tx_pkts;
+       u64 tx_reqs;
+       u64 tx_wrbs;
+       u64 tx_compl;
+       ulong tx_jiffies;
+       u32 tx_stops;
+       struct u64_stats_sync sync;
+       struct u64_stats_sync sync_compl;
 };
 
 struct be_tx_obj {
@@ -195,22 +196,20 @@ struct be_rx_page_info {
 };
 
 struct be_rx_stats {
-       u32 rx_post_fail;/* number of ethrx buffer alloc failures */
-       u32 rx_polls;   /* number of times NAPI called poll function */
-       u32 rx_events;  /* number of ucast rx completion events  */
-       u32 rx_compl;   /* number of rx completion entries processed */
-       ulong rx_dropped; /* number of skb allocation errors */
-       ulong rx_jiffies;
        u64 rx_bytes;
-       u64 rx_bytes_prev;
        u64 rx_pkts;
-       u32 rx_rate;
+       u64 rx_pkts_prev;
+       ulong rx_jiffies;
+       u32 rx_drops_no_skbs;   /* skb allocation errors */
+       u32 rx_drops_no_frags;  /* HW has no fetched frags */
+       u32 rx_post_fail;       /* page post alloc failures */
+       u32 rx_polls;           /* NAPI calls */
+       u32 rx_events;
+       u32 rx_compl;
        u32 rx_mcast_pkts;
-       u32 rxcp_err;   /* Num rx completion entries w/ err set. */
-       ulong rx_fps_jiffies;   /* jiffies at last FPS calc */
-       u32 rx_frags;
-       u32 prev_rx_frags;
-       u32 rx_fps;             /* Rx frags per second */
+       u32 rx_compl_err;       /* completions with err set */
+       u32 rx_pps;             /* pkts per second */
+       struct u64_stats_sync sync;
 };
 
 struct be_rx_compl_info {
@@ -218,7 +217,7 @@ struct be_rx_compl_info {
        u16 vlan_tag;
        u16 pkt_size;
        u16 rxq_idx;
-       u16 mac_id;
+       u16 port;
        u8 vlanf;
        u8 num_rcvd;
        u8 err;
@@ -247,43 +246,40 @@ struct be_rx_obj {
 
 struct be_drv_stats {
        u8 be_on_die_temperature;
-       u64 be_tx_events;
-       u64 eth_red_drops;
-       u64 rx_drops_no_pbuf;
-       u64 rx_drops_no_txpb;
-       u64 rx_drops_no_erx_descr;
-       u64 rx_drops_no_tpre_descr;
-       u64 rx_drops_too_many_frags;
-       u64 rx_drops_invalid_ring;
-       u64 forwarded_packets;
-       u64 rx_drops_mtu;
-       u64 rx_crc_errors;
-       u64 rx_alignment_symbol_errors;
-       u64 rx_pause_frames;
-       u64 rx_priority_pause_frames;
-       u64 rx_control_frames;
-       u64 rx_in_range_errors;
-       u64 rx_out_range_errors;
-       u64 rx_frame_too_long;
-       u64 rx_address_match_errors;
-       u64 rx_dropped_too_small;
-       u64 rx_dropped_too_short;
-       u64 rx_dropped_header_too_small;
-       u64 rx_dropped_tcp_length;
-       u64 rx_dropped_runt;
-       u64 rx_ip_checksum_errs;
-       u64 rx_tcp_checksum_errs;
-       u64 rx_udp_checksum_errs;
-       u64 rx_switched_unicast_packets;
-       u64 rx_switched_multicast_packets;
-       u64 rx_switched_broadcast_packets;
-       u64 tx_pauseframes;
-       u64 tx_priority_pauseframes;
-       u64 tx_controlframes;
-       u64 rxpp_fifo_overflow_drop;
-       u64 rx_input_fifo_overflow_drop;
-       u64 pmem_fifo_overflow_drop;
-       u64 jabber_events;
+       u32 tx_events;
+       u32 eth_red_drops;
+       u32 rx_drops_no_pbuf;
+       u32 rx_drops_no_txpb;
+       u32 rx_drops_no_erx_descr;
+       u32 rx_drops_no_tpre_descr;
+       u32 rx_drops_too_many_frags;
+       u32 rx_drops_invalid_ring;
+       u32 forwarded_packets;
+       u32 rx_drops_mtu;
+       u32 rx_crc_errors;
+       u32 rx_alignment_symbol_errors;
+       u32 rx_pause_frames;
+       u32 rx_priority_pause_frames;
+       u32 rx_control_frames;
+       u32 rx_in_range_errors;
+       u32 rx_out_range_errors;
+       u32 rx_frame_too_long;
+       u32 rx_address_match_errors;
+       u32 rx_dropped_too_small;
+       u32 rx_dropped_too_short;
+       u32 rx_dropped_header_too_small;
+       u32 rx_dropped_tcp_length;
+       u32 rx_dropped_runt;
+       u32 rx_ip_checksum_errs;
+       u32 rx_tcp_checksum_errs;
+       u32 rx_udp_checksum_errs;
+       u32 tx_pauseframes;
+       u32 tx_priority_pauseframes;
+       u32 tx_controlframes;
+       u32 rxpp_fifo_overflow_drop;
+       u32 rx_input_fifo_overflow_drop;
+       u32 pmem_fifo_overflow_drop;
+       u32 jabber_events;
 };
 
 struct be_vf_cfg {
@@ -302,7 +298,6 @@ struct be_adapter {
 
        u8 __iomem *csr;
        u8 __iomem *db;         /* Door Bell */
-       u8 __iomem *pcicfg;     /* PCI config space */
 
        struct mutex mbox_lock; /* For serializing mbox cmds to BE card */
        struct be_dma_mem mbox_mem;
@@ -338,7 +333,7 @@ struct be_adapter {
        u8 vlan_tag[VLAN_N_VID];
        u8 vlan_prio_bmap;      /* Available Priority BitMap */
        u16 recommended_prio;   /* Recommended Priority */
-       struct be_dma_mem mc_cmd_mem;
+       struct be_dma_mem rx_filter; /* Cmd DMA mem for rx-filter */
 
        struct be_dma_mem stats_cmd;
        /* Work queue used to perform periodic tasks like getting statistics */
@@ -352,7 +347,6 @@ struct be_adapter {
        u32 beacon_state;       /* for set_phys_id */
 
        bool eeh_err;
-       bool link_up;
        u32 port_num;
        bool promiscuous;
        bool wol;
@@ -385,6 +379,8 @@ struct be_adapter {
 #define BE_GEN2 2
 #define BE_GEN3 3
 
+#define ON                             1
+#define OFF                            0
 #define lancer_chip(adapter)   ((adapter->pdev->device == OC_DEVICE_ID3) || \
                                 (adapter->pdev->device == OC_DEVICE_ID4))
 
@@ -525,8 +521,7 @@ static inline bool be_multi_rxq(const struct be_adapter *adapter)
 
 extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
                u16 num_popped);
-extern void be_link_status_update(struct be_adapter *adapter, bool link_up);
-extern void netdev_stats_update(struct be_adapter *adapter);
+extern void be_link_status_update(struct be_adapter *adapter, u32 link_status);
 extern void be_parse_stats(struct be_adapter *adapter);
 extern int be_load_fw(struct be_adapter *adapter, u8 *func);
 #endif                         /* BE_H */
similarity index 94%
rename from drivers/net/benet/be_cmds.c
rename to drivers/net/ethernet/emulex/benet/be_cmds.c
index 054fa67..bebeee6 100644 (file)
@@ -82,28 +82,7 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
                if (((compl->tag0 == OPCODE_ETH_GET_STATISTICS) ||
                         (compl->tag0 == OPCODE_ETH_GET_PPORT_STATS)) &&
                        (compl->tag1 == CMD_SUBSYSTEM_ETH)) {
-                       if (adapter->generation == BE_GEN3) {
-                               if (lancer_chip(adapter)) {
-                                       struct lancer_cmd_resp_pport_stats
-                                               *resp = adapter->stats_cmd.va;
-                                       be_dws_le_to_cpu(&resp->pport_stats,
-                                               sizeof(resp->pport_stats));
-                               } else {
-                                       struct be_cmd_resp_get_stats_v1 *resp =
-                                                       adapter->stats_cmd.va;
-
-                               be_dws_le_to_cpu(&resp->hw_stats,
-                                                       sizeof(resp->hw_stats));
-                               }
-                       } else {
-                               struct be_cmd_resp_get_stats_v0 *resp =
-                                                       adapter->stats_cmd.va;
-
-                               be_dws_le_to_cpu(&resp->hw_stats,
-                                                       sizeof(resp->hw_stats));
-                       }
                        be_parse_stats(adapter);
-                       netdev_stats_update(adapter);
                        adapter->stats_cmd_sent = false;
                }
        } else {
@@ -131,8 +110,7 @@ done:
 static void be_async_link_state_process(struct be_adapter *adapter,
                struct be_async_event_link_state *evt)
 {
-       be_link_status_update(adapter,
-               evt->port_link_status == ASYNC_EVENT_LINK_UP);
+       be_link_status_update(adapter, evt->port_link_status);
 }
 
 /* Grp5 CoS Priority evt */
@@ -162,7 +140,7 @@ static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
                struct be_async_event_grp5_pvid_state *evt)
 {
        if (evt->enabled)
-               adapter->pvid = le16_to_cpu(evt->tag);
+               adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK;
        else
                adapter->pvid = 0;
 }
@@ -1282,8 +1260,8 @@ err:
 }
 
 /* Uses synchronous mcc */
-int be_cmd_link_status_query(struct be_adapter *adapter,
-                       bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom)
+int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
+                       u16 *link_speed, u32 dom)
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_req_link_status *req;
@@ -1298,8 +1276,6 @@ int be_cmd_link_status_query(struct be_adapter *adapter,
        }
        req = embedded_payload(wrb);
 
-       *link_up = false;
-
        be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
                        OPCODE_COMMON_NTWK_LINK_STATUS_QUERY);
 
@@ -1310,7 +1286,6 @@ int be_cmd_link_status_query(struct be_adapter *adapter,
        if (!status) {
                struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
                if (resp->mac_speed != PHY_LINK_SPEED_ZERO) {
-                       *link_up = true;
                        *link_speed = le16_to_cpu(resp->link_speed);
                        *mac_speed = resp->mac_speed;
                }
@@ -1573,70 +1548,11 @@ err:
        return status;
 }
 
-/* Uses MCC for this command as it may be called in BH context
- * Uses synchronous mcc
- */
-int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en)
-{
-       struct be_mcc_wrb *wrb;
-       struct be_cmd_req_rx_filter *req;
-       struct be_dma_mem promiscous_cmd;
-       struct be_sge *sge;
-       int status;
-
-       memset(&promiscous_cmd, 0, sizeof(struct be_dma_mem));
-       promiscous_cmd.size = sizeof(struct be_cmd_req_rx_filter);
-       promiscous_cmd.va = pci_alloc_consistent(adapter->pdev,
-                               promiscous_cmd.size, &promiscous_cmd.dma);
-       if (!promiscous_cmd.va) {
-               dev_err(&adapter->pdev->dev,
-                               "Memory allocation failure\n");
-               return -ENOMEM;
-       }
-
-       spin_lock_bh(&adapter->mcc_lock);
-
-       wrb = wrb_from_mccq(adapter);
-       if (!wrb) {
-               status = -EBUSY;
-               goto err;
-       }
-
-       req = promiscous_cmd.va;
-       sge = nonembedded_sgl(wrb);
-
-       be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
-                                       OPCODE_COMMON_NTWK_RX_FILTER);
-       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-                       OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req));
-
-       req->if_id = cpu_to_le32(adapter->if_handle);
-       req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS);
-       if (en)
-               req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS);
-
-       sge->pa_hi = cpu_to_le32(upper_32_bits(promiscous_cmd.dma));
-       sge->pa_lo = cpu_to_le32(promiscous_cmd.dma & 0xFFFFFFFF);
-       sge->len = cpu_to_le32(promiscous_cmd.size);
-
-       status = be_mcc_notify_wait(adapter);
-
-err:
-       spin_unlock_bh(&adapter->mcc_lock);
-       pci_free_consistent(adapter->pdev, promiscous_cmd.size,
-                       promiscous_cmd.va, promiscous_cmd.dma);
-       return status;
-}
-
-/*
- * Uses MCC for this command as it may be called in BH context
- * (mc == NULL) => multicast promiscuous
- */
-int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
-               struct net_device *netdev, struct be_dma_mem *mem)
+int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
 {
        struct be_mcc_wrb *wrb;
-       struct be_cmd_req_mcast_mac_config *req = mem->va;
+       struct be_dma_mem *mem = &adapter->rx_filter;
+       struct be_cmd_req_rx_filter *req = mem->va;
        struct be_sge *sge;
        int status;
 
@@ -1648,33 +1564,36 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
                goto err;
        }
        sge = nonembedded_sgl(wrb);
-       memset(req, 0, sizeof(*req));
-
-       be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
-                       OPCODE_COMMON_NTWK_MULTICAST_SET);
        sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma));
        sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF);
        sge->len = cpu_to_le32(mem->size);
+       be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
+                               OPCODE_COMMON_NTWK_RX_FILTER);
 
+       memset(req, 0, sizeof(*req));
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-               OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req));
+                               OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req));
 
-       req->interface_id = if_id;
-       if (netdev) {
-               int i;
+       req->if_id = cpu_to_le32(adapter->if_handle);
+       if (flags & IFF_PROMISC) {
+               req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS |
+                                       BE_IF_FLAGS_VLAN_PROMISCUOUS);
+               if (value == ON)
+                       req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS |
+                                       BE_IF_FLAGS_VLAN_PROMISCUOUS);
+       } else if (flags & IFF_ALLMULTI) {
+               req->if_flags_mask = req->if_flags =
+                       cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS);
+       } else {
                struct netdev_hw_addr *ha;
+               int i = 0;
 
-               req->num_mac = cpu_to_le16(netdev_mc_count(netdev));
-
-               i = 0;
-               netdev_for_each_mc_addr(ha, netdev)
-                       memcpy(req->mac[i++].byte, ha->addr, ETH_ALEN);
-       } else {
-               req->promiscuous = 1;
+               req->mcast_num = cpu_to_le16(netdev_mc_count(adapter->netdev));
+               netdev_for_each_mc_addr(ha, adapter->netdev)
+                       memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN);
        }
 
        status = be_mcc_notify_wait(adapter);
-
 err:
        spin_unlock_bh(&adapter->mcc_lock);
        return status;
@@ -2020,7 +1939,7 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
        spin_unlock_bh(&adapter->mcc_lock);
 
        if (!wait_for_completion_timeout(&adapter->flash_compl,
-                       msecs_to_jiffies(12000)))
+                       msecs_to_jiffies(40000)))
                status = -1;
        else
                status = adapter->flash_status;
@@ -2268,11 +2187,13 @@ err:
        return status;
 }
 
-int be_cmd_get_phy_info(struct be_adapter *adapter, struct be_dma_mem *cmd)
+int be_cmd_get_phy_info(struct be_adapter *adapter,
+                               struct be_phy_info *phy_info)
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_req_get_phy_info *req;
        struct be_sge *sge;
+       struct be_dma_mem cmd;
        int status;
 
        spin_lock_bh(&adapter->mcc_lock);
@@ -2282,8 +2203,16 @@ int be_cmd_get_phy_info(struct be_adapter *adapter, struct be_dma_mem *cmd)
                status = -EBUSY;
                goto err;
        }
+       cmd.size = sizeof(struct be_cmd_req_get_phy_info);
+       cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
+                                       &cmd.dma);
+       if (!cmd.va) {
+               dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+               status = -ENOMEM;
+               goto err;
+       }
 
-       req = cmd->va;
+       req = cmd.va;
        sge = nonembedded_sgl(wrb);
 
        be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
@@ -2293,11 +2222,20 @@ int be_cmd_get_phy_info(struct be_adapter *adapter, struct be_dma_mem *cmd)
                        OPCODE_COMMON_GET_PHY_DETAILS,
                        sizeof(*req));
 
-       sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma));
-       sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF);
-       sge->len = cpu_to_le32(cmd->size);
+       sge->pa_hi = cpu_to_le32(upper_32_bits(cmd.dma));
+       sge->pa_lo = cpu_to_le32(cmd.dma & 0xFFFFFFFF);
+       sge->len = cpu_to_le32(cmd.size);
 
        status = be_mcc_notify_wait(adapter);
+       if (!status) {
+               struct be_phy_info *resp_phy_info =
+                               cmd.va + sizeof(struct be_cmd_req_hdr);
+               phy_info->phy_type = le16_to_cpu(resp_phy_info->phy_type);
+               phy_info->interface_type =
+                       le16_to_cpu(resp_phy_info->interface_type);
+       }
+       pci_free_consistent(adapter->pdev, cmd.size,
+                               cmd.va, cmd.dma);
 err:
        spin_unlock_bh(&adapter->mcc_lock);
        return status;
similarity index 95%
rename from drivers/net/benet/be_cmds.h
rename to drivers/net/ethernet/emulex/benet/be_cmds.h
index 8e4d488..b61eac7 100644 (file)
@@ -89,9 +89,10 @@ struct be_async_event_trailer {
 };
 
 enum {
-       ASYNC_EVENT_LINK_DOWN   = 0x0,
-       ASYNC_EVENT_LINK_UP     = 0x1
+       LINK_DOWN       = 0x0,
+       LINK_UP         = 0x1
 };
+#define LINK_STATUS_MASK                       0x1
 
 /* When the event code of an async trailer is link-state, the mcc_compl
  * must be interpreted as follows
@@ -693,8 +694,7 @@ struct be_cmd_resp_get_stats_v0 {
        struct be_hw_stats_v0 hw_stats;
 };
 
-#define make_64bit_val(hi_32, lo_32)   (((u64)hi_32<<32) | lo_32)
-struct lancer_cmd_pport_stats {
+struct lancer_pport_stats {
        u32 tx_packets_lo;
        u32 tx_packets_hi;
        u32 tx_unicast_packets_lo;
@@ -871,16 +871,16 @@ struct lancer_cmd_req_pport_stats {
        struct be_cmd_req_hdr hdr;
        union {
                struct pport_stats_params params;
-               u8 rsvd[sizeof(struct lancer_cmd_pport_stats)];
+               u8 rsvd[sizeof(struct lancer_pport_stats)];
        } cmd_params;
 };
 
 struct lancer_cmd_resp_pport_stats {
        struct be_cmd_resp_hdr hdr;
-       struct lancer_cmd_pport_stats pport_stats;
+       struct lancer_pport_stats pport_stats;
 };
 
-static inline  struct lancer_cmd_pport_stats*
+static inline struct lancer_pport_stats*
        pport_stats_from_cmd(struct be_adapter *adapter)
 {
        struct lancer_cmd_resp_pport_stats *cmd = adapter->stats_cmd.va;
@@ -910,21 +910,12 @@ struct be_cmd_req_vlan_config {
        u16 normal_vlan[64];
 } __packed;
 
-/******************** Multicast MAC Config *******************/
+/******************* RX FILTER ******************************/
 #define BE_MAX_MC              64 /* set mcast promisc if > 64 */
 struct macaddr {
        u8 byte[ETH_ALEN];
 };
 
-struct be_cmd_req_mcast_mac_config {
-       struct be_cmd_req_hdr hdr;
-       u16 num_mac;
-       u8 promiscuous;
-       u8 interface_id;
-       struct macaddr mac[BE_MAX_MC];
-} __packed;
-
-/******************* RX FILTER ******************************/
 struct be_cmd_req_rx_filter {
        struct be_cmd_req_hdr hdr;
        u32 global_flags_mask;
@@ -932,11 +923,10 @@ struct be_cmd_req_rx_filter {
        u32 if_flags_mask;
        u32 if_flags;
        u32 if_id;
-       u32 multicast_num;
-       struct macaddr mac[BE_MAX_MC];
+       u32 mcast_num;
+       struct macaddr mcast_mac[BE_MAX_MC];
 };
 
-
 /******************** Link Status Query *******************/
 struct be_cmd_req_link_status {
        struct be_cmd_req_hdr hdr;
@@ -1254,14 +1244,19 @@ struct be_cmd_req_get_phy_info {
        struct be_cmd_req_hdr hdr;
        u8 rsvd0[24];
 };
-struct be_cmd_resp_get_phy_info {
-       struct be_cmd_req_hdr hdr;
+
+struct be_phy_info {
        u16 phy_type;
        u16 interface_type;
        u32 misc_params;
        u32 future_use[4];
 };
 
+struct be_cmd_resp_get_phy_info {
+       struct be_cmd_req_hdr hdr;
+       struct be_phy_info phy_info;
+};
+
 /*********************** Set QOS ***********************/
 
 #define BE_QOS_BITS_NIC                                1
@@ -1383,8 +1378,7 @@ struct be_cmd_resp_get_stats_v1 {
        struct be_hw_stats_v1 hw_stats;
 };
 
-static inline void *
-hw_stats_from_cmd(struct be_adapter *adapter)
+static inline void *hw_stats_from_cmd(struct be_adapter *adapter)
 {
        if (adapter->generation == BE_GEN3) {
                struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va;
@@ -1397,34 +1391,6 @@ hw_stats_from_cmd(struct be_adapter *adapter)
        }
 }
 
-static inline void *be_port_rxf_stats_from_cmd(struct be_adapter *adapter)
-{
-       if (adapter->generation == BE_GEN3) {
-               struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
-               struct be_rxf_stats_v1 *rxf_stats = &hw_stats->rxf;
-
-               return &rxf_stats->port[adapter->port_num];
-       } else {
-               struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
-               struct be_rxf_stats_v0 *rxf_stats = &hw_stats->rxf;
-
-               return &rxf_stats->port[adapter->port_num];
-       }
-}
-
-static inline void *be_rxf_stats_from_cmd(struct be_adapter *adapter)
-{
-       if (adapter->generation == BE_GEN3) {
-               struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
-
-               return &hw_stats->rxf;
-       } else {
-               struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
-
-               return &hw_stats->rxf;
-       }
-}
-
 static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter)
 {
        if (adapter->generation == BE_GEN3) {
@@ -1438,19 +1404,6 @@ static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter)
        }
 }
 
-static inline void *be_pmem_stats_from_cmd(struct be_adapter *adapter)
-{
-       if (adapter->generation == BE_GEN3) {
-               struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
-
-               return &hw_stats->pmem;
-       } else {
-               struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
-
-               return &hw_stats->pmem;
-       }
-}
-
 extern int be_pci_fnum_get(struct be_adapter *adapter);
 extern int be_cmd_POST(struct be_adapter *adapter);
 extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
@@ -1485,7 +1438,7 @@ extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
 extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
                        struct be_queue_info *q);
 extern int be_cmd_link_status_query(struct be_adapter *adapter,
-                       bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom);
+                       u8 *mac_speed, u16 *link_speed, u32 dom);
 extern int be_cmd_reset(struct be_adapter *adapter);
 extern int be_cmd_get_stats(struct be_adapter *adapter,
                        struct be_dma_mem *nonemb_cmd);
@@ -1497,9 +1450,7 @@ extern int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd);
 extern int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id,
                        u16 *vtag_array, u32 num, bool untagged,
                        bool promiscuous);
-extern int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en);
-extern int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
-                       struct net_device *netdev, struct be_dma_mem *mem);
+extern int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status);
 extern int be_cmd_set_flow_control(struct be_adapter *adapter,
                        u32 tx_fc, u32 rx_fc);
 extern int be_cmd_get_flow_control(struct be_adapter *adapter,
@@ -1540,7 +1491,7 @@ extern int be_cmd_get_seeprom_data(struct be_adapter *adapter,
 extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
                                u8 loopback_type, u8 enable);
 extern int be_cmd_get_phy_info(struct be_adapter *adapter,
-               struct be_dma_mem *cmd);
+                               struct be_phy_info *phy_info);
 extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
 extern void be_detect_dump_ue(struct be_adapter *adapter);
 extern int be_cmd_get_die_temperature(struct be_adapter *adapter);
similarity index 85%
rename from drivers/net/benet/be_ethtool.c
rename to drivers/net/ethernet/emulex/benet/be_ethtool.c
index 7fd8130..f144a6f 100644 (file)
@@ -26,33 +26,18 @@ struct be_ethtool_stat {
        int offset;
 };
 
-enum {NETSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT,
-                       DRVSTAT};
+enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT};
 #define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \
                                        offsetof(_struct, field)
-#define NETSTAT_INFO(field)    #field, NETSTAT,\
-                                       FIELDINFO(struct net_device_stats,\
-                                               field)
 #define DRVSTAT_TX_INFO(field) #field, DRVSTAT_TX,\
                                        FIELDINFO(struct be_tx_stats, field)
 #define DRVSTAT_RX_INFO(field) #field, DRVSTAT_RX,\
                                        FIELDINFO(struct be_rx_stats, field)
-#define ERXSTAT_INFO(field)    #field, ERXSTAT,\
-                                       FIELDINFO(struct be_erx_stats_v1, field)
 #define        DRVSTAT_INFO(field)     #field, DRVSTAT,\
-                                       FIELDINFO(struct be_drv_stats, \
-                                               field)
+                                       FIELDINFO(struct be_drv_stats, field)
 
 static const struct be_ethtool_stat et_stats[] = {
-       {NETSTAT_INFO(rx_packets)},
-       {NETSTAT_INFO(tx_packets)},
-       {NETSTAT_INFO(rx_bytes)},
-       {NETSTAT_INFO(tx_bytes)},
-       {NETSTAT_INFO(rx_errors)},
-       {NETSTAT_INFO(tx_errors)},
-       {NETSTAT_INFO(rx_dropped)},
-       {NETSTAT_INFO(tx_dropped)},
-       {DRVSTAT_INFO(be_tx_events)},
+       {DRVSTAT_INFO(tx_events)},
        {DRVSTAT_INFO(rx_crc_errors)},
        {DRVSTAT_INFO(rx_alignment_symbol_errors)},
        {DRVSTAT_INFO(rx_pause_frames)},
@@ -71,9 +56,6 @@ static const struct be_ethtool_stat et_stats[] = {
        {DRVSTAT_INFO(rx_ip_checksum_errs)},
        {DRVSTAT_INFO(rx_tcp_checksum_errs)},
        {DRVSTAT_INFO(rx_udp_checksum_errs)},
-       {DRVSTAT_INFO(rx_switched_unicast_packets)},
-       {DRVSTAT_INFO(rx_switched_multicast_packets)},
-       {DRVSTAT_INFO(rx_switched_broadcast_packets)},
        {DRVSTAT_INFO(tx_pauseframes)},
        {DRVSTAT_INFO(tx_controlframes)},
        {DRVSTAT_INFO(rx_priority_pause_frames)},
@@ -92,28 +74,33 @@ static const struct be_ethtool_stat et_stats[] = {
 };
 #define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)
 
-/* Stats related to multi RX queues */
+/* Stats related to multi RX queues: get_stats routine assumes bytes, pkts
+ * are first and second members respectively.
+ */
 static const struct be_ethtool_stat et_rx_stats[] = {
-       {DRVSTAT_RX_INFO(rx_bytes)},
-       {DRVSTAT_RX_INFO(rx_pkts)},
-       {DRVSTAT_RX_INFO(rx_rate)},
+       {DRVSTAT_RX_INFO(rx_bytes)},/* If moving this member see above note */
+       {DRVSTAT_RX_INFO(rx_pkts)}, /* If moving this member see above note */
        {DRVSTAT_RX_INFO(rx_polls)},
        {DRVSTAT_RX_INFO(rx_events)},
        {DRVSTAT_RX_INFO(rx_compl)},
        {DRVSTAT_RX_INFO(rx_mcast_pkts)},
        {DRVSTAT_RX_INFO(rx_post_fail)},
-       {DRVSTAT_RX_INFO(rx_dropped)},
-       {ERXSTAT_INFO(rx_drops_no_fragments)}
+       {DRVSTAT_RX_INFO(rx_drops_no_skbs)},
+       {DRVSTAT_RX_INFO(rx_drops_no_frags)}
 };
 #define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
 
-/* Stats related to multi TX queues */
+/* Stats related to multi TX queues: get_stats routine assumes compl is the
+ * first member
+ */
 static const struct be_ethtool_stat et_tx_stats[] = {
-       {DRVSTAT_TX_INFO(be_tx_rate)},
-       {DRVSTAT_TX_INFO(be_tx_reqs)},
-       {DRVSTAT_TX_INFO(be_tx_wrbs)},
-       {DRVSTAT_TX_INFO(be_tx_stops)},
-       {DRVSTAT_TX_INFO(be_tx_compl)}
+       {DRVSTAT_TX_INFO(tx_compl)}, /* If moving this member see above note */
+       {DRVSTAT_TX_INFO(tx_bytes)},
+       {DRVSTAT_TX_INFO(tx_pkts)},
+       {DRVSTAT_TX_INFO(tx_reqs)},
+       {DRVSTAT_TX_INFO(tx_wrbs)},
+       {DRVSTAT_TX_INFO(tx_compl)},
+       {DRVSTAT_TX_INFO(tx_stops)}
 };
 #define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats))
 
@@ -260,50 +247,49 @@ be_get_ethtool_stats(struct net_device *netdev,
        struct be_adapter *adapter = netdev_priv(netdev);
        struct be_rx_obj *rxo;
        struct be_tx_obj *txo;
-       void *p = NULL;
-       int i, j, base;
+       void *p;
+       unsigned int i, j, base = 0, start;
 
        for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
-               switch (et_stats[i].type) {
-               case NETSTAT:
-                       p = &netdev->stats;
-                       break;
-               case DRVSTAT:
-                       p = &adapter->drv_stats;
-                       break;
-               }
-
-               p = (u8 *)p + et_stats[i].offset;
-               data[i] = (et_stats[i].size == sizeof(u64)) ?
-                               *(u64 *)p: *(u32 *)p;
+               p = (u8 *)&adapter->drv_stats + et_stats[i].offset;
+               data[i] = *(u32 *)p;
        }
+       base += ETHTOOL_STATS_NUM;
 
-       base = ETHTOOL_STATS_NUM;
        for_all_rx_queues(adapter, rxo, j) {
-               for (i = 0; i < ETHTOOL_RXSTATS_NUM; i++) {
-                       switch (et_rx_stats[i].type) {
-                       case DRVSTAT_RX:
-                               p = (u8 *)&rxo->stats + et_rx_stats[i].offset;
-                               break;
-                       case ERXSTAT:
-                               p = (u32 *)be_erx_stats_from_cmd(adapter) +
-                                                               rxo->q.id;
-                               break;
-                       }
-                       data[base + j * ETHTOOL_RXSTATS_NUM + i] =
-                               (et_rx_stats[i].size == sizeof(u64)) ?
-                                       *(u64 *)p: *(u32 *)p;
+               struct be_rx_stats *stats = rx_stats(rxo);
+
+               do {
+                       start = u64_stats_fetch_begin_bh(&stats->sync);
+                       data[base] = stats->rx_bytes;
+                       data[base + 1] = stats->rx_pkts;
+               } while (u64_stats_fetch_retry_bh(&stats->sync, start));
+
+               for (i = 2; i < ETHTOOL_RXSTATS_NUM; i++) {
+                       p = (u8 *)stats + et_rx_stats[i].offset;
+                       data[base + i] = *(u32 *)p;
                }
+               base += ETHTOOL_RXSTATS_NUM;
        }
 
-       base = ETHTOOL_STATS_NUM + adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM;
        for_all_tx_queues(adapter, txo, j) {
-               for (i = 0; i < ETHTOOL_TXSTATS_NUM; i++) {
-                       p = (u8 *)&txo->stats + et_tx_stats[i].offset;
-                       data[base + j * ETHTOOL_TXSTATS_NUM + i] =
-                               (et_tx_stats[i].size == sizeof(u64)) ?
-                                       *(u64 *)p: *(u32 *)p;
-               }
+               struct be_tx_stats *stats = tx_stats(txo);
+
+               do {
+                       start = u64_stats_fetch_begin_bh(&stats->sync_compl);
+                       data[base] = stats->tx_compl;
+               } while (u64_stats_fetch_retry_bh(&stats->sync_compl, start));
+
+               do {
+                       start = u64_stats_fetch_begin_bh(&stats->sync);
+                       for (i = 1; i < ETHTOOL_TXSTATS_NUM; i++) {
+                               p = (u8 *)stats + et_tx_stats[i].offset;
+                               data[base + i] =
+                                       (et_tx_stats[i].size == sizeof(u64)) ?
+                                               *(u64 *)p : *(u32 *)p;
+                       }
+               } while (u64_stats_fetch_retry_bh(&stats->sync, start));
+               base += ETHTOOL_TXSTATS_NUM;
        }
 }
 
@@ -363,19 +349,15 @@ static int be_get_sset_count(struct net_device *netdev, int stringset)
 static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
-       struct be_dma_mem phy_cmd;
-       struct be_cmd_resp_get_phy_info *resp;
+       struct be_phy_info phy_info;
        u8 mac_speed = 0;
        u16 link_speed = 0;
-       bool link_up = false;
        int status;
-       u16 intf_type;
 
        if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) {
-               status = be_cmd_link_status_query(adapter, &link_up,
-                                               &mac_speed, &link_speed, 0);
+               status = be_cmd_link_status_query(adapter, &mac_speed,
+                                               &link_speed, 0);
 
-               be_link_status_update(adapter, link_up);
                /* link_speed is in units of 10 Mbps */
                if (link_speed) {
                        ethtool_cmd_speed_set(ecmd, link_speed*10);
@@ -399,20 +381,9 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
                        }
                }
 
-               phy_cmd.size = sizeof(struct be_cmd_req_get_phy_info);
-               phy_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
-                                               phy_cmd.size, &phy_cmd.dma,
-                                               GFP_KERNEL);
-               if (!phy_cmd.va) {
-                       dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
-                       return -ENOMEM;
-               }
-               status = be_cmd_get_phy_info(adapter, &phy_cmd);
+               status = be_cmd_get_phy_info(adapter, &phy_info);
                if (!status) {
-                       resp = phy_cmd.va;
-                       intf_type = le16_to_cpu(resp->interface_type);
-
-                       switch (intf_type) {
+                       switch (phy_info.interface_type) {
                        case PHY_TYPE_XFP_10GB:
                        case PHY_TYPE_SFP_1GB:
                        case PHY_TYPE_SFP_PLUS_10GB:
@@ -423,7 +394,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
                                break;
                        }
 
-                       switch (intf_type) {
+                       switch (phy_info.interface_type) {
                        case PHY_TYPE_KR_10GB:
                        case PHY_TYPE_KX4_10GB:
                                ecmd->autoneg = AUTONEG_ENABLE;
@@ -441,8 +412,6 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
                adapter->port_type = ecmd->port;
                adapter->transceiver = ecmd->transceiver;
                adapter->autoneg = ecmd->autoneg;
-               dma_free_coherent(&adapter->pdev->dev, phy_cmd.size, phy_cmd.va,
-                                 phy_cmd.dma);
        } else {
                ethtool_cmd_speed_set(ecmd, adapter->link_speed);
                ecmd->port = adapter->port_type;
@@ -631,7 +600,6 @@ static void
 be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
-       bool link_up;
        u8 mac_speed = 0;
        u16 qos_link_speed = 0;
 
@@ -657,7 +625,7 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
                test->flags |= ETH_TEST_FL_FAILED;
        }
 
-       if (be_cmd_link_status_query(adapter, &link_up, &mac_speed,
+       if (be_cmd_link_status_query(adapter, &mac_speed,
                                &qos_link_speed, 0) != 0) {
                test->flags |= ETH_TEST_FL_FAILED;
                data[4] = -1;
similarity index 94%
rename from drivers/net/benet/be_hw.h
rename to drivers/net/ethernet/emulex/benet/be_hw.h
index 53d658a..fbc8a91 100644 (file)
 #define IMG_TYPE_FCOE_FW_ACTIVE                10
 #define IMG_TYPE_FCOE_FW_BACKUP        11
 #define IMG_TYPE_NCSI_FW               13
+#define IMG_TYPE_PHY_FW                        99
+#define TN_8022                                13
 
+#define ILLEGAL_IOCTL_REQ              2
+#define FLASHROM_OPER_PHY_FLASH                9
+#define FLASHROM_OPER_PHY_SAVE         10
 #define FLASHROM_OPER_FLASH            1
 #define FLASHROM_OPER_SAVE             2
 #define FLASHROM_OPER_REPORT           4
 
-#define FLASH_IMAGE_MAX_SIZE_g2            (1310720) /* Max firmware image sz */
-#define FLASH_BIOS_IMAGE_MAX_SIZE_g2       (262144)  /* Max OPTION ROM img sz */
-#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g2          (262144)  /* Max Redboot image sz */
-#define FLASH_IMAGE_MAX_SIZE_g3            (2097152) /* Max fw image size */
-#define FLASH_BIOS_IMAGE_MAX_SIZE_g3       (524288)  /* Max OPTION ROM img sz */
-#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g3          (1048576)  /* Max Redboot image sz */
-#define FLASH_NCSI_IMAGE_MAX_SIZE_g3       (262144)  /* Max NSCI image sz */
+#define FLASH_IMAGE_MAX_SIZE_g2                (1310720) /* Max firmware image size */
+#define FLASH_BIOS_IMAGE_MAX_SIZE_g2   (262144)  /* Max OPTION ROM image sz */
+#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g2        (262144)  /* Max Redboot image sz    */
+#define FLASH_IMAGE_MAX_SIZE_g3                (2097152) /* Max firmware image size */
+#define FLASH_BIOS_IMAGE_MAX_SIZE_g3   (524288)  /* Max OPTION ROM image sz */
+#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g3        (1048576)  /* Max Redboot image sz    */
+#define FLASH_NCSI_IMAGE_MAX_SIZE_g3   (262144)
+#define FLASH_PHY_FW_IMAGE_MAX_SIZE_g3 262144
 
 #define FLASH_NCSI_MAGIC               (0x16032009)
 #define FLASH_NCSI_DISABLED            (0)
 #define FLASH_PXE_BIOS_START_g3            (13107200)
 #define FLASH_FCoE_BIOS_START_g3           (13631488)
 #define FLASH_REDBOOT_START_g3             (262144)
+#define FLASH_PHY_FW_START_g3             1310720
 
 /************* Rx Packet Type Encoding **************/
 #define BE_UNICAST_PACKET              0
similarity index 90%
rename from drivers/net/benet/be_main.c
rename to drivers/net/ethernet/emulex/benet/be_main.c
index c411bb1..3d55b47 100644 (file)
@@ -141,13 +141,15 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
 
 static void be_intr_set(struct be_adapter *adapter, bool enable)
 {
-       u8 __iomem *addr = adapter->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET;
-       u32 reg = ioread32(addr);
-       u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
+       u32 reg, enabled;
 
        if (adapter->eeh_err)
                return;
 
+       pci_read_config_dword(adapter->pdev, PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET,
+                               &reg);
+       enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
+
        if (!enabled && enable)
                reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
        else if (enabled && !enable)
@@ -155,7 +157,8 @@ static void be_intr_set(struct be_adapter *adapter, bool enable)
        else
                return;
 
-       iowrite32(reg, addr);
+       pci_write_config_dword(adapter->pdev,
+                       PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET, reg);
 }
 
 static void be_rxq_notify(struct be_adapter *adapter, u16 qid, u16 posted)
@@ -245,14 +248,14 @@ netdev_addr:
 
 static void populate_be2_stats(struct be_adapter *adapter)
 {
-
-       struct be_drv_stats *drvs = &adapter->drv_stats;
-       struct be_pmem_stats *pmem_sts = be_pmem_stats_from_cmd(adapter);
+       struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
+       struct be_pmem_stats *pmem_sts = &hw_stats->pmem;
+       struct be_rxf_stats_v0 *rxf_stats = &hw_stats->rxf;
        struct be_port_rxf_stats_v0 *port_stats =
-               be_port_rxf_stats_from_cmd(adapter);
-       struct be_rxf_stats_v0 *rxf_stats =
-               be_rxf_stats_from_cmd(adapter);
+                                       &rxf_stats->port[adapter->port_num];
+       struct be_drv_stats *drvs = &adapter->drv_stats;
 
+       be_dws_le_to_cpu(hw_stats, sizeof(*hw_stats));
        drvs->rx_pause_frames = port_stats->rx_pause_frames;
        drvs->rx_crc_errors = port_stats->rx_crc_errors;
        drvs->rx_control_frames = port_stats->rx_control_frames;
@@ -267,12 +270,10 @@ static void populate_be2_stats(struct be_adapter *adapter)
        drvs->rx_dropped_too_small = port_stats->rx_dropped_too_small;
        drvs->rx_dropped_too_short = port_stats->rx_dropped_too_short;
        drvs->rx_out_range_errors = port_stats->rx_out_range_errors;
-       drvs->rx_input_fifo_overflow_drop =
-               port_stats->rx_input_fifo_overflow;
+       drvs->rx_input_fifo_overflow_drop = port_stats->rx_input_fifo_overflow;
        drvs->rx_dropped_header_too_small =
                port_stats->rx_dropped_header_too_small;
-       drvs->rx_address_match_errors =
-               port_stats->rx_address_match_errors;
+       drvs->rx_address_match_errors = port_stats->rx_address_match_errors;
        drvs->rx_alignment_symbol_errors =
                port_stats->rx_alignment_symbol_errors;
 
@@ -280,36 +281,30 @@ static void populate_be2_stats(struct be_adapter *adapter)
        drvs->tx_controlframes = port_stats->tx_controlframes;
 
        if (adapter->port_num)
-               drvs->jabber_events =
-                       rxf_stats->port1_jabber_events;
+               drvs->jabber_events = rxf_stats->port1_jabber_events;
        else
-               drvs->jabber_events =
-                       rxf_stats->port0_jabber_events;
+               drvs->jabber_events = rxf_stats->port0_jabber_events;
        drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf;
        drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb;
        drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr;
        drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring;
        drvs->forwarded_packets = rxf_stats->forwarded_packets;
        drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu;
-       drvs->rx_drops_no_tpre_descr =
-               rxf_stats->rx_drops_no_tpre_descr;
-       drvs->rx_drops_too_many_frags =
-               rxf_stats->rx_drops_too_many_frags;
+       drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr;
+       drvs->rx_drops_too_many_frags = rxf_stats->rx_drops_too_many_frags;
        adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops;
 }
 
 static void populate_be3_stats(struct be_adapter *adapter)
 {
-       struct be_drv_stats *drvs = &adapter->drv_stats;
-       struct be_pmem_stats *pmem_sts = be_pmem_stats_from_cmd(adapter);
-
-       struct be_rxf_stats_v1 *rxf_stats =
-               be_rxf_stats_from_cmd(adapter);
+       struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
+       struct be_pmem_stats *pmem_sts = &hw_stats->pmem;
+       struct be_rxf_stats_v1 *rxf_stats = &hw_stats->rxf;
        struct be_port_rxf_stats_v1 *port_stats =
-               be_port_rxf_stats_from_cmd(adapter);
+                                       &rxf_stats->port[adapter->port_num];
+       struct be_drv_stats *drvs = &adapter->drv_stats;
 
-       drvs->rx_priority_pause_frames = 0;
-       drvs->pmem_fifo_overflow_drop = 0;
+       be_dws_le_to_cpu(hw_stats, sizeof(*hw_stats));
        drvs->rx_pause_frames = port_stats->rx_pause_frames;
        drvs->rx_crc_errors = port_stats->rx_crc_errors;
        drvs->rx_control_frames = port_stats->rx_control_frames;
@@ -327,12 +322,10 @@ static void populate_be3_stats(struct be_adapter *adapter)
                port_stats->rx_dropped_header_too_small;
        drvs->rx_input_fifo_overflow_drop =
                port_stats->rx_input_fifo_overflow_drop;
-       drvs->rx_address_match_errors =
-               port_stats->rx_address_match_errors;
+       drvs->rx_address_match_errors = port_stats->rx_address_match_errors;
        drvs->rx_alignment_symbol_errors =
                port_stats->rx_alignment_symbol_errors;
-       drvs->rxpp_fifo_overflow_drop =
-               port_stats->rxpp_fifo_overflow_drop;
+       drvs->rxpp_fifo_overflow_drop = port_stats->rxpp_fifo_overflow_drop;
        drvs->tx_pauseframes = port_stats->tx_pauseframes;
        drvs->tx_controlframes = port_stats->tx_controlframes;
        drvs->jabber_events = port_stats->jabber_events;
@@ -342,10 +335,8 @@ static void populate_be3_stats(struct be_adapter *adapter)
        drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring;
        drvs->forwarded_packets = rxf_stats->forwarded_packets;
        drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu;
-       drvs->rx_drops_no_tpre_descr =
-               rxf_stats->rx_drops_no_tpre_descr;
-       drvs->rx_drops_too_many_frags =
-               rxf_stats->rx_drops_too_many_frags;
+       drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr;
+       drvs->rx_drops_too_many_frags = rxf_stats->rx_drops_too_many_frags;
        adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops;
 }
 
@@ -353,22 +344,15 @@ static void populate_lancer_stats(struct be_adapter *adapter)
 {
 
        struct be_drv_stats *drvs = &adapter->drv_stats;
-       struct lancer_cmd_pport_stats *pport_stats = pport_stats_from_cmd
-                                               (adapter);
-       drvs->rx_priority_pause_frames = 0;
-       drvs->pmem_fifo_overflow_drop = 0;
-       drvs->rx_pause_frames =
-               make_64bit_val(pport_stats->rx_pause_frames_hi,
-                                pport_stats->rx_pause_frames_lo);
-       drvs->rx_crc_errors = make_64bit_val(pport_stats->rx_crc_errors_hi,
-                                               pport_stats->rx_crc_errors_lo);
-       drvs->rx_control_frames =
-                       make_64bit_val(pport_stats->rx_control_frames_hi,
-                       pport_stats->rx_control_frames_lo);
+       struct lancer_pport_stats *pport_stats =
+                                       pport_stats_from_cmd(adapter);
+
+       be_dws_le_to_cpu(pport_stats, sizeof(*pport_stats));
+       drvs->rx_pause_frames = pport_stats->rx_pause_frames_lo;
+       drvs->rx_crc_errors = pport_stats->rx_crc_errors_lo;
+       drvs->rx_control_frames = pport_stats->rx_control_frames_lo;
        drvs->rx_in_range_errors = pport_stats->rx_in_range_errors;
-       drvs->rx_frame_too_long =
-               make_64bit_val(pport_stats->rx_internal_mac_errors_hi,
-                                       pport_stats->rx_frames_too_long_lo);
+       drvs->rx_frame_too_long = pport_stats->rx_frames_too_long_lo;
        drvs->rx_dropped_runt = pport_stats->rx_dropped_runt;
        drvs->rx_ip_checksum_errs = pport_stats->rx_ip_checksum_errors;
        drvs->rx_tcp_checksum_errs = pport_stats->rx_tcp_checksum_errors;
@@ -382,32 +366,36 @@ static void populate_lancer_stats(struct be_adapter *adapter)
                                pport_stats->rx_dropped_header_too_small;
        drvs->rx_input_fifo_overflow_drop = pport_stats->rx_fifo_overflow;
        drvs->rx_address_match_errors = pport_stats->rx_address_match_errors;
-       drvs->rx_alignment_symbol_errors =
-               make_64bit_val(pport_stats->rx_symbol_errors_hi,
-                               pport_stats->rx_symbol_errors_lo);
+       drvs->rx_alignment_symbol_errors = pport_stats->rx_symbol_errors_lo;
        drvs->rxpp_fifo_overflow_drop = pport_stats->rx_fifo_overflow;
-       drvs->tx_pauseframes = make_64bit_val(pport_stats->tx_pause_frames_hi,
-                                       pport_stats->tx_pause_frames_lo);
-       drvs->tx_controlframes =
-               make_64bit_val(pport_stats->tx_control_frames_hi,
-                               pport_stats->tx_control_frames_lo);
+       drvs->tx_pauseframes = pport_stats->tx_pause_frames_lo;
+       drvs->tx_controlframes = pport_stats->tx_control_frames_lo;
        drvs->jabber_events = pport_stats->rx_jabbers;
-       drvs->rx_drops_no_pbuf = 0;
-       drvs->rx_drops_no_txpb = 0;
-       drvs->rx_drops_no_erx_descr = 0;
        drvs->rx_drops_invalid_ring = pport_stats->rx_drops_invalid_queue;
-       drvs->forwarded_packets = make_64bit_val(pport_stats->num_forwards_hi,
-                                               pport_stats->num_forwards_lo);
-       drvs->rx_drops_mtu = make_64bit_val(pport_stats->rx_drops_mtu_hi,
-                                               pport_stats->rx_drops_mtu_lo);
-       drvs->rx_drops_no_tpre_descr = 0;
+       drvs->forwarded_packets = pport_stats->num_forwards_lo;
+       drvs->rx_drops_mtu = pport_stats->rx_drops_mtu_lo;
        drvs->rx_drops_too_many_frags =
-               make_64bit_val(pport_stats->rx_drops_too_many_frags_hi,
-                               pport_stats->rx_drops_too_many_frags_lo);
+                               pport_stats->rx_drops_too_many_frags_lo;
+}
+
+static void accumulate_16bit_val(u32 *acc, u16 val)
+{
+#define lo(x)                  (x & 0xFFFF)
+#define hi(x)                  (x & 0xFFFF0000)
+       bool wrapped = val < lo(*acc);
+       u32 newacc = hi(*acc) + val;
+
+       if (wrapped)
+               newacc += 65536;
+       ACCESS_ONCE(*acc) = newacc;
 }
 
 void be_parse_stats(struct be_adapter *adapter)
 {
+       struct be_erx_stats_v1 *erx = be_erx_stats_from_cmd(adapter);
+       struct be_rx_obj *rxo;
+       int i;
+
        if (adapter->generation == BE_GEN3) {
                if (lancer_chip(adapter))
                        populate_lancer_stats(adapter);
@@ -416,50 +404,55 @@ void be_parse_stats(struct be_adapter *adapter)
        } else {
                populate_be2_stats(adapter);
        }
+
+       /* as erx_v1 is longer than v0, ok to use v1 defn for v0 access */
+       for_all_rx_queues(adapter, rxo, i) {
+               /* below erx HW counter can actually wrap around after
+                * 65535. Driver accumulates a 32-bit value
+                */
+               accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags,
+                               (u16)erx->rx_drops_no_fragments[rxo->q.id]);
+       }
 }
 
-void netdev_stats_update(struct be_adapter *adapter)
+static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
+                                       struct rtnl_link_stats64 *stats)
 {
+       struct be_adapter *adapter = netdev_priv(netdev);
        struct be_drv_stats *drvs = &adapter->drv_stats;
-       struct net_device_stats *dev_stats = &adapter->netdev->stats;
        struct be_rx_obj *rxo;
        struct be_tx_obj *txo;
-       unsigned long pkts = 0, bytes = 0, mcast = 0, drops = 0;
+       u64 pkts, bytes;
+       unsigned int start;
        int i;
 
        for_all_rx_queues(adapter, rxo, i) {
-               pkts += rx_stats(rxo)->rx_pkts;
-               bytes += rx_stats(rxo)->rx_bytes;
-               mcast += rx_stats(rxo)->rx_mcast_pkts;
-               drops += rx_stats(rxo)->rx_dropped;
-               /*  no space in linux buffers: best possible approximation */
-               if (adapter->generation == BE_GEN3) {
-                       if (!(lancer_chip(adapter))) {
-                               struct be_erx_stats_v1 *erx =
-                                       be_erx_stats_from_cmd(adapter);
-                               drops += erx->rx_drops_no_fragments[rxo->q.id];
-                       }
-               } else {
-                       struct be_erx_stats_v0 *erx =
-                                       be_erx_stats_from_cmd(adapter);
-                       drops += erx->rx_drops_no_fragments[rxo->q.id];
-               }
+               const struct be_rx_stats *rx_stats = rx_stats(rxo);
+               do {
+                       start = u64_stats_fetch_begin_bh(&rx_stats->sync);
+                       pkts = rx_stats(rxo)->rx_pkts;
+                       bytes = rx_stats(rxo)->rx_bytes;
+               } while (u64_stats_fetch_retry_bh(&rx_stats->sync, start));
+               stats->rx_packets += pkts;
+               stats->rx_bytes += bytes;
+               stats->multicast += rx_stats(rxo)->rx_mcast_pkts;
+               stats->rx_dropped += rx_stats(rxo)->rx_drops_no_skbs +
+                                       rx_stats(rxo)->rx_drops_no_frags;
        }
-       dev_stats->rx_packets = pkts;
-       dev_stats->rx_bytes = bytes;
-       dev_stats->multicast = mcast;
-       dev_stats->rx_dropped = drops;
 
-       pkts = bytes = 0;
        for_all_tx_queues(adapter, txo, i) {
-               pkts += tx_stats(txo)->be_tx_pkts;
-               bytes += tx_stats(txo)->be_tx_bytes;
+               const struct be_tx_stats *tx_stats = tx_stats(txo);
+               do {
+                       start = u64_stats_fetch_begin_bh(&tx_stats->sync);
+                       pkts = tx_stats(txo)->tx_pkts;
+                       bytes = tx_stats(txo)->tx_bytes;
+               } while (u64_stats_fetch_retry_bh(&tx_stats->sync, start));
+               stats->tx_packets += pkts;
+               stats->tx_bytes += bytes;
        }
-       dev_stats->tx_packets = pkts;
-       dev_stats->tx_bytes = bytes;
 
        /* bad pkts received */
-       dev_stats->rx_errors = drvs->rx_crc_errors +
+       stats->rx_errors = drvs->rx_crc_errors +
                drvs->rx_alignment_symbol_errors +
                drvs->rx_in_range_errors +
                drvs->rx_out_range_errors +
@@ -468,115 +461,38 @@ void netdev_stats_update(struct be_adapter *adapter)
                drvs->rx_dropped_too_short +
                drvs->rx_dropped_header_too_small +
                drvs->rx_dropped_tcp_length +
-               drvs->rx_dropped_runt +
-               drvs->rx_tcp_checksum_errs +
-               drvs->rx_ip_checksum_errs +
-               drvs->rx_udp_checksum_errs;
+               drvs->rx_dropped_runt;
 
        /* detailed rx errors */
-       dev_stats->rx_length_errors = drvs->rx_in_range_errors +
+       stats->rx_length_errors = drvs->rx_in_range_errors +
                drvs->rx_out_range_errors +
                drvs->rx_frame_too_long;
 
-       dev_stats->rx_crc_errors = drvs->rx_crc_errors;
+       stats->rx_crc_errors = drvs->rx_crc_errors;
 
        /* frame alignment errors */
-       dev_stats->rx_frame_errors = drvs->rx_alignment_symbol_errors;
+       stats->rx_frame_errors = drvs->rx_alignment_symbol_errors;
 
        /* receiver fifo overrun */
        /* drops_no_pbuf is no per i/f, it's per BE card */
-       dev_stats->rx_fifo_errors = drvs->rxpp_fifo_overflow_drop +
+       stats->rx_fifo_errors = drvs->rxpp_fifo_overflow_drop +
                                drvs->rx_input_fifo_overflow_drop +
                                drvs->rx_drops_no_pbuf;
+       return stats;
 }
 
-void be_link_status_update(struct be_adapter *adapter, bool link_up)
+void be_link_status_update(struct be_adapter *adapter, u32 link_status)
 {
        struct net_device *netdev = adapter->netdev;
 
-       /* If link came up or went down */
-       if (adapter->link_up != link_up) {
-               adapter->link_speed = -1;
-               if (link_up) {
-                       netif_carrier_on(netdev);
-                       printk(KERN_INFO "%s: Link up\n", netdev->name);
-               } else {
-                       netif_carrier_off(netdev);
-                       printk(KERN_INFO "%s: Link down\n", netdev->name);
-               }
-               adapter->link_up = link_up;
-       }
-}
-
-/* Update the EQ delay n BE based on the RX frags consumed / sec */
-static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo)
-{
-       struct be_eq_obj *rx_eq = &rxo->rx_eq;
-       struct be_rx_stats *stats = &rxo->stats;
-       ulong now = jiffies;
-       u32 eqd;
-
-       if (!rx_eq->enable_aic)
-               return;
-
-       /* Wrapped around */
-       if (time_before(now, stats->rx_fps_jiffies)) {
-               stats->rx_fps_jiffies = now;
-               return;
-       }
-
-       /* Update once a second */
-       if ((now - stats->rx_fps_jiffies) < HZ)
-               return;
-
-       stats->rx_fps = (stats->rx_frags - stats->prev_rx_frags) /
-                       ((now - stats->rx_fps_jiffies) / HZ);
-
-       stats->rx_fps_jiffies = now;
-       stats->prev_rx_frags = stats->rx_frags;
-       eqd = stats->rx_fps / 110000;
-       eqd = eqd << 3;
-       if (eqd > rx_eq->max_eqd)
-               eqd = rx_eq->max_eqd;
-       if (eqd < rx_eq->min_eqd)
-               eqd = rx_eq->min_eqd;
-       if (eqd < 10)
-               eqd = 0;
-       if (eqd != rx_eq->cur_eqd)
-               be_cmd_modify_eqd(adapter, rx_eq->q.id, eqd);
-
-       rx_eq->cur_eqd = eqd;
-}
-
-static u32 be_calc_rate(u64 bytes, unsigned long ticks)
-{
-       u64 rate = bytes;
-
-       do_div(rate, ticks / HZ);
-       rate <<= 3;                     /* bytes/sec -> bits/sec */
-       do_div(rate, 1000000ul);        /* MB/Sec */
-
-       return rate;
-}
-
-static void be_tx_rate_update(struct be_tx_obj *txo)
-{
-       struct be_tx_stats *stats = tx_stats(txo);
-       ulong now = jiffies;
-
-       /* Wrapped around? */
-       if (time_before(now, stats->be_tx_jiffies)) {
-               stats->be_tx_jiffies = now;
-               return;
-       }
-
-       /* Update tx rate once in two seconds */
-       if ((now - stats->be_tx_jiffies) > 2 * HZ) {
-               stats->be_tx_rate = be_calc_rate(stats->be_tx_bytes
-                                                 - stats->be_tx_bytes_prev,
-                                                now - stats->be_tx_jiffies);
-               stats->be_tx_jiffies = now;
-               stats->be_tx_bytes_prev = stats->be_tx_bytes;
+       /* when link status changes, link speed must be re-queried from card */
+       adapter->link_speed = -1;
+       if ((link_status & LINK_STATUS_MASK) == LINK_UP) {
+               netif_carrier_on(netdev);
+               dev_info(&adapter->pdev->dev, "%s: Link up\n", netdev->name);
+       } else {
+               netif_carrier_off(netdev);
+               dev_info(&adapter->pdev->dev, "%s: Link down\n", netdev->name);
        }
 }
 
@@ -585,12 +501,14 @@ static void be_tx_stats_update(struct be_tx_obj *txo,
 {
        struct be_tx_stats *stats = tx_stats(txo);
 
-       stats->be_tx_reqs++;
-       stats->be_tx_wrbs += wrb_cnt;
-       stats->be_tx_bytes += copied;
-       stats->be_tx_pkts += (gso_segs ? gso_segs : 1);
+       u64_stats_update_begin(&stats->sync);
+       stats->tx_reqs++;
+       stats->tx_wrbs += wrb_cnt;
+       stats->tx_bytes += copied;
+       stats->tx_pkts += (gso_segs ? gso_segs : 1);
        if (stopped)
-               stats->be_tx_stops++;
+               stats->tx_stops++;
+       u64_stats_update_end(&stats->sync);
 }
 
 /* Determine number of WRB entries needed to xmit data in an skb */
@@ -829,6 +747,10 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
                status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0);
        }
 
+       /* No need to further configure vids if in promiscuous mode */
+       if (adapter->promiscuous)
+               return 0;
+
        if (adapter->vlans_added <= adapter->max_vlans)  {
                /* Construct VLAN Table to give to HW */
                for (i = 0; i < VLAN_N_VID; i++) {
@@ -879,7 +801,7 @@ static void be_set_multicast_list(struct net_device *netdev)
        struct be_adapter *adapter = netdev_priv(netdev);
 
        if (netdev->flags & IFF_PROMISC) {
-               be_cmd_promiscuous_config(adapter, true);
+               be_cmd_rx_filter(adapter, IFF_PROMISC, ON);
                adapter->promiscuous = true;
                goto done;
        }
@@ -887,19 +809,20 @@ static void be_set_multicast_list(struct net_device *netdev)
        /* BE was previously in promiscuous mode; disable it */
        if (adapter->promiscuous) {
                adapter->promiscuous = false;
-               be_cmd_promiscuous_config(adapter, false);
+               be_cmd_rx_filter(adapter, IFF_PROMISC, OFF);
+
+               if (adapter->vlans_added)
+                       be_vid_config(adapter, false, 0);
        }
 
        /* Enable multicast promisc if num configured exceeds what we support */
        if (netdev->flags & IFF_ALLMULTI ||
-           netdev_mc_count(netdev) > BE_MAX_MC) {
-               be_cmd_multicast_set(adapter, adapter->if_handle, NULL,
-                               &adapter->mc_cmd_mem);
+                       netdev_mc_count(netdev) > BE_MAX_MC) {
+               be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
                goto done;
        }
 
-       be_cmd_multicast_set(adapter, adapter->if_handle, netdev,
-               &adapter->mc_cmd_mem);
+       be_cmd_rx_filter(adapter, IFF_MULTICAST, ON);
 done:
        return;
 }
@@ -1005,10 +928,17 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
        return status;
 }
 
-static void be_rx_rate_update(struct be_rx_obj *rxo)
+static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo)
 {
-       struct be_rx_stats *stats = &rxo->stats;
+       struct be_eq_obj *rx_eq = &rxo->rx_eq;
+       struct be_rx_stats *stats = rx_stats(rxo);
        ulong now = jiffies;
+       ulong delta = now - stats->rx_jiffies;
+       u64 pkts;
+       unsigned int start, eqd;
+
+       if (!rx_eq->enable_aic)
+               return;
 
        /* Wrapped around */
        if (time_before(now, stats->rx_jiffies)) {
@@ -1016,29 +946,46 @@ static void be_rx_rate_update(struct be_rx_obj *rxo)
                return;
        }
 
-       /* Update the rate once in two seconds */
-       if ((now - stats->rx_jiffies) < 2 * HZ)
+       /* Update once a second */
+       if (delta < HZ)
                return;
 
-       stats->rx_rate = be_calc_rate(stats->rx_bytes - stats->rx_bytes_prev,
-                               now - stats->rx_jiffies);
+       do {
+               start = u64_stats_fetch_begin_bh(&stats->sync);
+               pkts = stats->rx_pkts;
+       } while (u64_stats_fetch_retry_bh(&stats->sync, start));
+
+       stats->rx_pps = (unsigned long)(pkts - stats->rx_pkts_prev) / (delta / HZ);
+       stats->rx_pkts_prev = pkts;
        stats->rx_jiffies = now;
-       stats->rx_bytes_prev = stats->rx_bytes;
+       eqd = stats->rx_pps / 110000;
+       eqd = eqd << 3;
+       if (eqd > rx_eq->max_eqd)
+               eqd = rx_eq->max_eqd;
+       if (eqd < rx_eq->min_eqd)
+               eqd = rx_eq->min_eqd;
+       if (eqd < 10)
+               eqd = 0;
+       if (eqd != rx_eq->cur_eqd) {
+               be_cmd_modify_eqd(adapter, rx_eq->q.id, eqd);
+               rx_eq->cur_eqd = eqd;
+       }
 }
 
 static void be_rx_stats_update(struct be_rx_obj *rxo,
                struct be_rx_compl_info *rxcp)
 {
-       struct be_rx_stats *stats = &rxo->stats;
+       struct be_rx_stats *stats = rx_stats(rxo);
 
+       u64_stats_update_begin(&stats->sync);
        stats->rx_compl++;
-       stats->rx_frags += rxcp->num_rcvd;
        stats->rx_bytes += rxcp->pkt_size;
        stats->rx_pkts++;
        if (rxcp->pkt_type == BE_MULTICAST_PACKET)
                stats->rx_mcast_pkts++;
        if (rxcp->err)
-               stats->rxcp_err++;
+               stats->rx_compl_err++;
+       u64_stats_update_end(&stats->sync);
 }
 
 static inline bool csum_passed(struct be_rx_compl_info *rxcp)
@@ -1174,7 +1121,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,
 
        skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN);
        if (unlikely(!skb)) {
-               rxo->stats.rx_dropped++;
+               rx_stats(rxo)->rx_drops_no_skbs++;
                be_rx_compl_discard(adapter, rxo, rxcp);
                return;
        }
@@ -1192,7 +1139,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,
                skb->rxhash = rxcp->rss_hash;
 
 
-       if (unlikely(rxcp->vlanf))
+       if (rxcp->vlanf)
                __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag);
 
        netif_receive_skb(skb);
@@ -1249,7 +1196,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
        if (adapter->netdev->features & NETIF_F_RXHASH)
                skb->rxhash = rxcp->rss_hash;
 
-       if (unlikely(rxcp->vlanf))
+       if (rxcp->vlanf)
                __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag);
 
        napi_gro_frags(&eq_obj->napi);
@@ -1285,6 +1232,7 @@ static void be_parse_rx_compl_v1(struct be_adapter *adapter,
                rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag,
                                               compl);
        }
+       rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, port, compl);
 }
 
 static void be_parse_rx_compl_v0(struct be_adapter *adapter,
@@ -1317,6 +1265,7 @@ static void be_parse_rx_compl_v0(struct be_adapter *adapter,
                rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag,
                                               compl);
        }
+       rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, port, compl);
 }
 
 static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
@@ -1347,8 +1296,7 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
                if (!lancer_chip(adapter))
                        rxcp->vlan_tag = swab16(rxcp->vlan_tag);
 
-               if (((adapter->pvid & VLAN_VID_MASK) ==
-                    (rxcp->vlan_tag & VLAN_VID_MASK)) &&
+               if (adapter->pvid == (rxcp->vlan_tag & VLAN_VID_MASK) &&
                    !adapter->vlan_tag[rxcp->vlan_tag])
                        rxcp->vlanf = 0;
        }
@@ -1389,7 +1337,7 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp)
                if (!pagep) {
                        pagep = be_alloc_pages(adapter->big_page_size, gfp);
                        if (unlikely(!pagep)) {
-                               rxo->stats.rx_post_fail++;
+                               rx_stats(rxo)->rx_post_fail++;
                                break;
                        }
                        page_dmaaddr = dma_map_page(&adapter->pdev->dev, pagep,
@@ -1899,27 +1847,41 @@ static int be_poll_rx(struct napi_struct *napi, int budget)
        struct be_rx_compl_info *rxcp;
        u32 work_done;
 
-       rxo->stats.rx_polls++;
+       rx_stats(rxo)->rx_polls++;
        for (work_done = 0; work_done < budget; work_done++) {
                rxcp = be_rx_compl_get(rxo);
                if (!rxcp)
                        break;
 
-               /* Ignore flush completions */
-               if (rxcp->num_rcvd && rxcp->pkt_size) {
-                       if (do_gro(rxcp))
-                               be_rx_compl_process_gro(adapter, rxo, rxcp);
-                       else
-                               be_rx_compl_process(adapter, rxo, rxcp);
-               } else if (rxcp->pkt_size == 0) {
+               /* Is it a flush compl that has no data */
+               if (unlikely(rxcp->num_rcvd == 0))
+                       goto loop_continue;
+
+               /* Discard compl with partial DMA Lancer B0 */
+               if (unlikely(!rxcp->pkt_size)) {
+                       be_rx_compl_discard(adapter, rxo, rxcp);
+                       goto loop_continue;
+               }
+
+               /* On BE drop pkts that arrive due to imperfect filtering in
+                * promiscuous mode on some skews
+                */
+               if (unlikely(rxcp->port != adapter->port_num &&
+                               !lancer_chip(adapter))) {
                        be_rx_compl_discard(adapter, rxo, rxcp);
+                       goto loop_continue;
                }
 
+               if (do_gro(rxcp))
+                       be_rx_compl_process_gro(adapter, rxo, rxcp);
+               else
+                       be_rx_compl_process(adapter, rxo, rxcp);
+loop_continue:
                be_rx_stats_update(rxo, rxcp);
        }
 
        /* Refill the queue */
-       if (atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM)
+       if (work_done && atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM)
                be_post_rx_frags(rxo, GFP_ATOMIC);
 
        /* All consumed */
@@ -1968,8 +1930,9 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
                                netif_wake_subqueue(adapter->netdev, i);
                        }
 
-                       adapter->drv_stats.be_tx_events++;
-                       txo->stats.be_tx_compl += tx_compl;
+                       u64_stats_update_begin(&tx_stats(txo)->sync_compl);
+                       tx_stats(txo)->tx_compl += tx_compl;
+                       u64_stats_update_end(&tx_stats(txo)->sync_compl);
                }
        }
 
@@ -1983,6 +1946,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
        napi_complete(napi);
 
        be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
+       adapter->drv_stats.tx_events++;
        return 1;
 }
 
@@ -2031,7 +1995,6 @@ static void be_worker(struct work_struct *work)
        struct be_adapter *adapter =
                container_of(work, struct be_adapter, work.work);
        struct be_rx_obj *rxo;
-       struct be_tx_obj *txo;
        int i;
 
        if (!adapter->ue_detected && !lancer_chip(adapter))
@@ -2060,11 +2023,7 @@ static void be_worker(struct work_struct *work)
                        be_cmd_get_stats(adapter, &adapter->stats_cmd);
        }
 
-       for_all_tx_queues(adapter, txo, i)
-               be_tx_rate_update(txo);
-
        for_all_rx_queues(adapter, rxo, i) {
-               be_rx_rate_update(rxo);
                be_rx_eqd_update(adapter, rxo);
 
                if (rxo->rx_post_starved) {
@@ -2294,9 +2253,6 @@ static int be_close(struct net_device *netdev)
 
        be_async_mcc_disable(adapter);
 
-       netif_carrier_off(netdev);
-       adapter->link_up = false;
-
        if (!lancer_chip(adapter))
                be_intr_set(adapter, false);
 
@@ -2374,10 +2330,7 @@ static int be_open(struct net_device *netdev)
        struct be_adapter *adapter = netdev_priv(netdev);
        struct be_eq_obj *tx_eq = &adapter->tx_eq;
        struct be_rx_obj *rxo;
-       bool link_up;
        int status, i;
-       u8 mac_speed;
-       u16 link_speed;
 
        status = be_rx_queues_setup(adapter);
        if (status)
@@ -2400,12 +2353,6 @@ static int be_open(struct net_device *netdev)
        /* Now that interrupts are on we can process async mcc */
        be_async_mcc_enable(adapter);
 
-       status = be_cmd_link_status_query(adapter, &link_up, &mac_speed,
-                       &link_speed, 0);
-       if (status)
-               goto err;
-       be_link_status_update(adapter, link_up);
-
        if (be_physfn(adapter)) {
                status = be_vid_config(adapter, false, 0);
                if (status)
@@ -2656,6 +2603,21 @@ static bool be_flash_redboot(struct be_adapter *adapter,
                return true;
 }
 
+static bool phy_flashing_required(struct be_adapter *adapter)
+{
+       int status = 0;
+       struct be_phy_info phy_info;
+
+       status = be_cmd_get_phy_info(adapter, &phy_info);
+       if (status)
+               return false;
+       if ((phy_info.phy_type == TN_8022) &&
+               (phy_info.interface_type == PHY_TYPE_BASET_10GB)) {
+               return true;
+       }
+       return false;
+}
+
 static int be_flash_data(struct be_adapter *adapter,
                        const struct firmware *fw,
                        struct be_dma_mem *flash_cmd, int num_of_images)
@@ -2669,7 +2631,7 @@ static int be_flash_data(struct be_adapter *adapter,
        const struct flash_comp *pflashcomp;
        int num_comp;
 
-       static const struct flash_comp gen3_flash_types[9] = {
+       static const struct flash_comp gen3_flash_types[10] = {
                { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE,
                        FLASH_IMAGE_MAX_SIZE_g3},
                { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT,
@@ -2687,7 +2649,9 @@ static int be_flash_data(struct be_adapter *adapter,
                { FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP,
                        FLASH_IMAGE_MAX_SIZE_g3},
                { FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW,
-                       FLASH_NCSI_IMAGE_MAX_SIZE_g3}
+                       FLASH_NCSI_IMAGE_MAX_SIZE_g3},
+               { FLASH_PHY_FW_START_g3, IMG_TYPE_PHY_FW,
+                       FLASH_PHY_FW_IMAGE_MAX_SIZE_g3}
        };
        static const struct flash_comp gen2_flash_types[8] = {
                { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE,
@@ -2721,6 +2685,10 @@ static int be_flash_data(struct be_adapter *adapter,
                if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) &&
                                memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
                        continue;
+               if (pflashcomp[i].optype == IMG_TYPE_PHY_FW) {
+                       if (!phy_flashing_required(adapter))
+                               continue;
+               }
                if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) &&
                        (!be_flash_redboot(adapter, fw->data,
                        pflashcomp[i].offset, pflashcomp[i].size, filehdr_size +
@@ -2729,25 +2697,35 @@ static int be_flash_data(struct be_adapter *adapter,
                p = fw->data;
                p += filehdr_size + pflashcomp[i].offset
                        + (num_of_images * sizeof(struct image_hdr));
-       if (p + pflashcomp[i].size > fw->data + fw->size)
-               return -1;
-       total_bytes = pflashcomp[i].size;
+               if (p + pflashcomp[i].size > fw->data + fw->size)
+                       return -1;
+               total_bytes = pflashcomp[i].size;
                while (total_bytes) {
                        if (total_bytes > 32*1024)
                                num_bytes = 32*1024;
                        else
                                num_bytes = total_bytes;
                        total_bytes -= num_bytes;
-
-                       if (!total_bytes)
-                               flash_op = FLASHROM_OPER_FLASH;
-                       else
-                               flash_op = FLASHROM_OPER_SAVE;
+                       if (!total_bytes) {
+                               if (pflashcomp[i].optype == IMG_TYPE_PHY_FW)
+                                       flash_op = FLASHROM_OPER_PHY_FLASH;
+                               else
+                                       flash_op = FLASHROM_OPER_FLASH;
+                       } else {
+                               if (pflashcomp[i].optype == IMG_TYPE_PHY_FW)
+                                       flash_op = FLASHROM_OPER_PHY_SAVE;
+                               else
+                                       flash_op = FLASHROM_OPER_SAVE;
+                       }
                        memcpy(req->params.data_buf, p, num_bytes);
                        p += num_bytes;
                        status = be_cmd_write_flashrom(adapter, flash_cmd,
                                pflashcomp[i].optype, flash_op, num_bytes);
                        if (status) {
+                               if ((status == ILLEGAL_IOCTL_REQ) &&
+                                       (pflashcomp[i].optype ==
+                                               IMG_TYPE_PHY_FW))
+                                       break;
                                dev_err(&adapter->pdev->dev,
                                        "cmd to write to flash rom failed.\n");
                                return -1;
@@ -2938,6 +2916,7 @@ static struct net_device_ops be_netdev_ops = {
        .ndo_set_rx_mode        = be_set_multicast_list,
        .ndo_set_mac_address    = be_mac_addr_set,
        .ndo_change_mtu         = be_change_mtu,
+       .ndo_get_stats64        = be_get_stats64,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_vlan_rx_add_vid    = be_vlan_add_vid,
        .ndo_vlan_rx_kill_vid   = be_vlan_rem_vid,
@@ -2991,14 +2970,12 @@ static void be_unmap_pci_bars(struct be_adapter *adapter)
                iounmap(adapter->csr);
        if (adapter->db)
                iounmap(adapter->db);
-       if (adapter->pcicfg && be_physfn(adapter))
-               iounmap(adapter->pcicfg);
 }
 
 static int be_map_pci_bars(struct be_adapter *adapter)
 {
        u8 __iomem *addr;
-       int pcicfg_reg, db_reg;
+       int db_reg;
 
        if (lancer_chip(adapter)) {
                addr = ioremap_nocache(pci_resource_start(adapter->pdev, 0),
@@ -3018,10 +2995,8 @@ static int be_map_pci_bars(struct be_adapter *adapter)
        }
 
        if (adapter->generation == BE_GEN2) {
-               pcicfg_reg = 1;
                db_reg = 4;
        } else {
-               pcicfg_reg = 0;
                if (be_physfn(adapter))
                        db_reg = 4;
                else
@@ -3033,16 +3008,6 @@ static int be_map_pci_bars(struct be_adapter *adapter)
                goto pci_map_err;
        adapter->db = addr;
 
-       if (be_physfn(adapter)) {
-               addr = ioremap_nocache(
-                               pci_resource_start(adapter->pdev, pcicfg_reg),
-                               pci_resource_len(adapter->pdev, pcicfg_reg));
-               if (addr == NULL)
-                       goto pci_map_err;
-               adapter->pcicfg = addr;
-       } else
-               adapter->pcicfg = adapter->db + SRIOV_VF_PCICFG_OFFSET;
-
        return 0;
 pci_map_err:
        be_unmap_pci_bars(adapter);
@@ -3060,7 +3025,7 @@ static void be_ctrl_cleanup(struct be_adapter *adapter)
                dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
                                  mem->dma);
 
-       mem = &adapter->mc_cmd_mem;
+       mem = &adapter->rx_filter;
        if (mem->va)
                dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
                                  mem->dma);
@@ -3070,7 +3035,7 @@ static int be_ctrl_init(struct be_adapter *adapter)
 {
        struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced;
        struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem;
-       struct be_dma_mem *mc_cmd_mem = &adapter->mc_cmd_mem;
+       struct be_dma_mem *rx_filter = &adapter->rx_filter;
        int status;
 
        status = be_map_pci_bars(adapter);
@@ -3086,21 +3051,19 @@ static int be_ctrl_init(struct be_adapter *adapter)
                status = -ENOMEM;
                goto unmap_pci_bars;
        }
-
        mbox_mem_align->size = sizeof(struct be_mcc_mailbox);
        mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
        mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
        memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
 
-       mc_cmd_mem->size = sizeof(struct be_cmd_req_mcast_mac_config);
-       mc_cmd_mem->va = dma_alloc_coherent(&adapter->pdev->dev,
-                                           mc_cmd_mem->size, &mc_cmd_mem->dma,
-                                           GFP_KERNEL);
-       if (mc_cmd_mem->va == NULL) {
+       rx_filter->size = sizeof(struct be_cmd_req_rx_filter);
+       rx_filter->va = dma_alloc_coherent(&adapter->pdev->dev, rx_filter->size,
+                                       &rx_filter->dma, GFP_KERNEL);
+       if (rx_filter->va == NULL) {
                status = -ENOMEM;
                goto free_mbox;
        }
-       memset(mc_cmd_mem->va, 0, mc_cmd_mem->size);
+       memset(rx_filter->va, 0, rx_filter->size);
 
        mutex_init(&adapter->mbox_lock);
        spin_lock_init(&adapter->mcc_lock);
@@ -3421,11 +3384,9 @@ static int __devinit be_probe(struct pci_dev *pdev,
        status = register_netdev(netdev);
        if (status != 0)
                goto unsetup;
-       netif_carrier_off(netdev);
 
        if (be_physfn(adapter) && adapter->sriov_enabled) {
                u8 mac_speed;
-               bool link_up;
                u16 vf, lnk_speed;
 
                if (!lancer_chip(adapter)) {
@@ -3435,8 +3396,8 @@ static int __devinit be_probe(struct pci_dev *pdev,
                }
 
                for (vf = 0; vf < num_vfs; vf++) {
-                       status = be_cmd_link_status_query(adapter, &link_up,
-                                       &mac_speed, &lnk_speed, vf + 1);
+                       status = be_cmd_link_status_query(adapter, &mac_speed,
+                                               &lnk_speed, vf + 1);
                        if (!status)
                                adapter->vf_cfg[vf].vf_tx_rate = lnk_speed * 10;
                        else
similarity index 99%
rename from drivers/net/ethoc.c
rename to drivers/net/ethernet/ethoc.c
index 8abbe1d..bdb348a 100644 (file)
@@ -888,7 +888,7 @@ static const struct net_device_ops ethoc_netdev_ops = {
        .ndo_do_ioctl = ethoc_ioctl,
        .ndo_set_config = ethoc_config,
        .ndo_set_mac_address = ethoc_set_mac_address,
-       .ndo_set_multicast_list = ethoc_set_multicast_list,
+       .ndo_set_rx_mode = ethoc_set_multicast_list,
        .ndo_change_mtu = ethoc_change_mtu,
        .ndo_tx_timeout = ethoc_tx_timeout,
        .ndo_start_xmit = ethoc_start_xmit,
diff --git a/drivers/net/ethernet/faraday/Kconfig b/drivers/net/ethernet/faraday/Kconfig
new file mode 100644 (file)
index 0000000..5918c68
--- /dev/null
@@ -0,0 +1,39 @@
+#
+# Faraday device configuration
+#
+
+config NET_VENDOR_FARADAY
+       bool "Faraday devices"
+       default y
+       depends on ARM
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Faraday cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_FARADAY
+
+config FTMAC100
+       tristate "Faraday FTMAC100 10/100 Ethernet support"
+       depends on ARM
+       select MII
+       ---help---
+         This driver supports the FTMAC100 10/100 Ethernet controller
+         from Faraday. It is used on Faraday A320, Andes AG101 and some
+         other ARM/NDS32 SoC's.
+
+config FTGMAC100
+       tristate "Faraday FTGMAC100 Gigabit Ethernet support"
+       depends on ARM
+       select PHYLIB
+       ---help---
+         This driver supports the FTGMAC100 Gigabit Ethernet controller
+         from Faraday. It is used on Faraday A369, Andes AG102 and some
+         other ARM/NDS32 SoC's.
+
+endif # NET_VENDOR_FARADAY
diff --git a/drivers/net/ethernet/faraday/Makefile b/drivers/net/ethernet/faraday/Makefile
new file mode 100644 (file)
index 0000000..408b539
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the Faraday device drivers.
+#
+
+obj-$(CONFIG_FTGMAC100) += ftgmac100.o
+obj-$(CONFIG_FTMAC100) += ftmac100.o
similarity index 99%
rename from drivers/net/fealnx.c
rename to drivers/net/ethernet/fealnx.c
index fa8677c..61d2bdd 100644 (file)
@@ -469,7 +469,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_stop               = netdev_close,
        .ndo_start_xmit         = start_tx,
        .ndo_get_stats          = get_stats,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_do_ioctl           = mii_ioctl,
        .ndo_tx_timeout         = fealnx_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
new file mode 100644 (file)
index 0000000..4dbe41f
--- /dev/null
@@ -0,0 +1,89 @@
+#
+# Freescale device configuration
+#
+
+config NET_VENDOR_FREESCALE
+       bool "Freescale devices"
+       default y
+       depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \
+                  M523x || M527x || M5272 || M528x || M520x || M532x || \
+                  IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC || \
+                  (PPC_MPC52xx && PPC_BESTCOMM)
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about IBM devices. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_FREESCALE
+
+config FEC
+       bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
+       depends on (M523x || M527x || M5272 || M528x || M520x || M532x || \
+                   IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC)
+       default IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC if ARM
+       select PHYLIB
+       ---help---
+         Say Y here if you want to use the built-in 10/100 Fast ethernet
+         controller on some Motorola ColdFire and Freescale i.MX processors.
+
+config FEC_MPC52xx
+       tristate "FEC MPC52xx driver"
+       depends on PPC_MPC52xx && PPC_BESTCOMM
+       select CRC32
+       select PHYLIB
+       select PPC_BESTCOMM_FEC
+       ---help---
+         This option enables support for the MPC5200's on-chip
+         Fast Ethernet Controller
+         If compiled as module, it will be called fec_mpc52xx.
+
+config FEC_MPC52xx_MDIO
+       bool "FEC MPC52xx MDIO bus driver"
+       depends on FEC_MPC52xx
+       default y
+       ---help---
+         The MPC5200's FEC can connect to the Ethernet either with
+         an external MII PHY chip or 10 Mbps 7-wire interface
+         (Motorola? industry standard).
+         If your board uses an external PHY connected to FEC, enable this.
+         If not sure, enable.
+         If compiled as module, it will be called fec_mpc52xx_phy.
+
+source "drivers/net/ethernet/freescale/fs_enet/Kconfig"
+
+config FSL_PQ_MDIO
+       tristate "Freescale PQ MDIO"
+       depends on FSL_SOC
+       select PHYLIB
+       ---help---
+         This driver supports the MDIO bus used by the gianfar and UCC drivers.
+
+config UCC_GETH
+       tristate "Freescale QE Gigabit Ethernet"
+       depends on QUICC_ENGINE
+       select FSL_PQ_MDIO
+       select PHYLIB
+       ---help---
+         This driver supports the Gigabit Ethernet mode of the QUICC Engine,
+         which is available on some Freescale SOCs.
+
+config UGETH_TX_ON_DEMAND
+       bool "Transmit on Demand support"
+       depends on UCC_GETH
+
+config GIANFAR
+       tristate "Gianfar Ethernet"
+       depends on FSL_SOC
+       select FSL_PQ_MDIO
+       select PHYLIB
+       select CRC32
+       ---help---
+         This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
+         and MPC86xx family of chips, and the FEC on the 8540.
+
+endif # NET_VENDOR_FREESCALE
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
new file mode 100644 (file)
index 0000000..1752488
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Makefile for the Freescale network device drivers.
+#
+
+obj-$(CONFIG_FEC) += fec.o
+obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
+ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
+       obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
+endif
+obj-$(CONFIG_FS_ENET) += fs_enet/
+obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o
+obj-$(CONFIG_GIANFAR) += gianfar_driver.o
+obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o
+gianfar_driver-objs := gianfar.o \
+               gianfar_ethtool.o \
+               gianfar_sysfs.o
+obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
+ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
similarity index 93%
rename from drivers/net/fec.c
rename to drivers/net/ethernet/freescale/fec.c
index 5b631fe..158b82e 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/phy.h>
 #include <linux/fec.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_net.h>
 
 #include <asm/cacheflush.h>
 
 #define FEC_QUIRK_ENET_MAC             (1 << 0)
 /* Controller needs driver to swap frame */
 #define FEC_QUIRK_SWAP_FRAME           (1 << 1)
+/* Controller uses gasket */
+#define FEC_QUIRK_USE_GASKET           (1 << 2)
 
 static struct platform_device_id fec_devtype[] = {
        {
+               /* keep it for coldfire */
                .name = DRIVER_NAME,
                .driver_data = 0,
+       }, {
+               .name = "imx25-fec",
+               .driver_data = FEC_QUIRK_USE_GASKET,
+       }, {
+               .name = "imx27-fec",
+               .driver_data = 0,
        }, {
                .name = "imx28-fec",
                .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
-       },
-       { }
+       }, {
+               /* sentinel */
+       }
 };
+MODULE_DEVICE_TABLE(platform, fec_devtype);
+
+enum imx_fec_type {
+       IMX25_FEC = 1,  /* runs on i.mx25/50/53 */
+       IMX27_FEC,      /* runs on i.mx27/35/51 */
+       IMX28_FEC,
+};
+
+static const struct of_device_id fec_dt_ids[] = {
+       { .compatible = "fsl,imx25-fec", .data = &fec_devtype[IMX25_FEC], },
+       { .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], },
+       { .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fec_dt_ids);
 
 static unsigned char macaddr[ETH_ALEN];
 module_param_array(macaddr, byte, NULL, 0);
@@ -427,7 +456,7 @@ fec_restart(struct net_device *ndev, int duplex)
 
        } else {
 #ifdef FEC_MIIGSK_ENR
-               if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
+               if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) {
                        /* disable the gasket and wait */
                        writel(0, fep->hwp + FEC_MIIGSK_ENR);
                        while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
@@ -436,8 +465,11 @@ fec_restart(struct net_device *ndev, int duplex)
                        /*
                         * configure the gasket:
                         *   RMII, 50 MHz, no loopback, no echo
+                        *   MII, 25 MHz, no loopback, no echo
                         */
-                       writel(1, fep->hwp + FEC_MIIGSK_CFGR);
+                       writel((fep->phy_interface == PHY_INTERFACE_MODE_RMII) ?
+                                       1 : 0, fep->hwp + FEC_MIIGSK_CFGR);
+
 
                        /* re-enable the gasket */
                        writel(2, fep->hwp + FEC_MIIGSK_ENR);
@@ -734,8 +766,22 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
         */
        iap = macaddr;
 
+#ifdef CONFIG_OF
        /*
-        * 2) from flash or fuse (via platform data)
+        * 2) from device tree data
+        */
+       if (!is_valid_ether_addr(iap)) {
+               struct device_node *np = fep->pdev->dev.of_node;
+               if (np) {
+                       const char *mac = of_get_mac_address(np);
+                       if (mac)
+                               iap = (unsigned char *) mac;
+               }
+       }
+#endif
+
+       /*
+        * 3) from flash or fuse (via platform data)
         */
        if (!is_valid_ether_addr(iap)) {
 #ifdef CONFIG_M5272
@@ -748,7 +794,7 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
        }
 
        /*
-        * 3) FEC mac registers set by bootloader
+        * 4) FEC mac registers set by bootloader
         */
        if (!is_valid_ether_addr(iap)) {
                *((unsigned long *) &tmpaddr[0]) =
@@ -1279,7 +1325,7 @@ static const struct net_device_ops fec_netdev_ops = {
        .ndo_open               = fec_enet_open,
        .ndo_stop               = fec_enet_close,
        .ndo_start_xmit         = fec_enet_start_xmit,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = fec_timeout,
@@ -1354,6 +1400,52 @@ static int fec_enet_init(struct net_device *ndev)
        return 0;
 }
 
+#ifdef CONFIG_OF
+static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+
+       if (np)
+               return of_get_phy_mode(np);
+
+       return -ENODEV;
+}
+
+static int __devinit fec_reset_phy(struct platform_device *pdev)
+{
+       int err, phy_reset;
+       struct device_node *np = pdev->dev.of_node;
+
+       if (!np)
+               return -ENODEV;
+
+       phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
+       err = gpio_request_one(phy_reset, GPIOF_OUT_INIT_LOW, "phy-reset");
+       if (err) {
+               pr_warn("FEC: failed to get gpio phy-reset: %d\n", err);
+               return err;
+       }
+       msleep(1);
+       gpio_set_value(phy_reset, 1);
+
+       return 0;
+}
+#else /* CONFIG_OF */
+static inline int fec_get_phy_mode_dt(struct platform_device *pdev)
+{
+       return -ENODEV;
+}
+
+static inline int fec_reset_phy(struct platform_device *pdev)
+{
+       /*
+        * In case of platform probe, the reset has been done
+        * by machine code.
+        */
+       return 0;
+}
+#endif /* CONFIG_OF */
+
 static int __devinit
 fec_probe(struct platform_device *pdev)
 {
@@ -1362,6 +1454,11 @@ fec_probe(struct platform_device *pdev)
        struct net_device *ndev;
        int i, irq, ret = 0;
        struct resource *r;
+       const struct of_device_id *of_id;
+
+       of_id = of_match_device(fec_dt_ids, &pdev->dev);
+       if (of_id)
+               pdev->id_entry = of_id->data;
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!r)
@@ -1393,9 +1490,18 @@ fec_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, ndev);
 
-       pdata = pdev->dev.platform_data;
-       if (pdata)
-               fep->phy_interface = pdata->phy;
+       ret = fec_get_phy_mode_dt(pdev);
+       if (ret < 0) {
+               pdata = pdev->dev.platform_data;
+               if (pdata)
+                       fep->phy_interface = pdata->phy;
+               else
+                       fep->phy_interface = PHY_INTERFACE_MODE_MII;
+       } else {
+               fep->phy_interface = ret;
+       }
+
+       fec_reset_phy(pdev);
 
        /* This device has up to three irqs on some platforms */
        for (i = 0; i < 3; i++) {
@@ -1530,6 +1636,7 @@ static struct platform_driver fec_driver = {
 #ifdef CONFIG_PM
                .pm     = &fec_pm_ops,
 #endif
+               .of_match_table = fec_dt_ids,
        },
        .id_table = fec_devtype,
        .probe  = fec_probe,
similarity index 99%
rename from drivers/net/fec_mpc52xx.c
rename to drivers/net/ethernet/freescale/fec_mpc52xx.c
index cb4416e..30745b5 100644 (file)
@@ -828,7 +828,7 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = {
        .ndo_open = mpc52xx_fec_open,
        .ndo_stop = mpc52xx_fec_close,
        .ndo_start_xmit = mpc52xx_fec_start_xmit,
-       .ndo_set_multicast_list = mpc52xx_fec_set_multicast_list,
+       .ndo_set_rx_mode = mpc52xx_fec_set_multicast_list,
        .ndo_set_mac_address = mpc52xx_fec_set_mac_address,
        .ndo_validate_addr = eth_validate_addr,
        .ndo_do_ioctl = mpc52xx_fec_ioctl,
similarity index 91%
rename from drivers/net/fs_enet/Kconfig
rename to drivers/net/ethernet/freescale/fs_enet/Kconfig
index fc073b5..be92229 100644 (file)
@@ -1,6 +1,6 @@
 config FS_ENET
        tristate "Freescale Ethernet Driver"
-       depends on CPM1 || CPM2 || PPC_MPC512x
+       depends on NET_VENDOR_FREESCALE && (CPM1 || CPM2 || PPC_MPC512x)
        select MII
        select PHYLIB
 
similarity index 99%
rename from drivers/net/fs_enet/fs_enet-main.c
rename to drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 329ef23..5bf5471 100644 (file)
@@ -988,7 +988,7 @@ static const struct net_device_ops fs_enet_netdev_ops = {
        .ndo_get_stats          = fs_enet_get_stats,
        .ndo_start_xmit         = fs_enet_start_xmit,
        .ndo_tx_timeout         = fs_timeout,
-       .ndo_set_multicast_list = fs_set_multicast_list,
+       .ndo_set_rx_mode        = fs_set_multicast_list,
        .ndo_do_ioctl           = fs_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/gianfar.c
rename to drivers/net/ethernet/freescale/gianfar.c
index 2659daa..81d409d 100644 (file)
@@ -458,7 +458,7 @@ static const struct net_device_ops gfar_netdev_ops = {
        .ndo_stop = gfar_close,
        .ndo_change_mtu = gfar_change_mtu,
        .ndo_set_features = gfar_set_features,
-       .ndo_set_multicast_list = gfar_set_multi,
+       .ndo_set_rx_mode = gfar_set_multi,
        .ndo_tx_timeout = gfar_timeout,
        .ndo_do_ioctl = gfar_ioctl,
        .ndo_get_stats = gfar_get_stats,
@@ -2710,8 +2710,13 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
        /* Tell the skb what kind of packet this is */
        skb->protocol = eth_type_trans(skb, dev);
 
-       /* Set vlan tag */
-       if (fcb->flags & RXFCB_VLN)
+       /*
+        * There's need to check for NETIF_F_HW_VLAN_RX here.
+        * Even if vlan rx accel is disabled, on some chips
+        * RXFCB_VLN is pseudo randomly set.
+        */
+       if (dev->features & NETIF_F_HW_VLAN_RX &&
+           fcb->flags & RXFCB_VLN)
                __vlan_hwaccel_put_tag(skb, fcb->vlctl);
 
        /* Send the packet up the stack */
similarity index 99%
rename from drivers/net/gianfar_ethtool.c
rename to drivers/net/ethernet/freescale/gianfar_ethtool.c
index 6e35069..25a8c2a 100644 (file)
@@ -686,10 +686,21 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u
 {
        unsigned int last_rule_idx = priv->cur_filer_idx;
        unsigned int cmp_rqfpr;
-       unsigned int local_rqfpr[MAX_FILER_IDX + 1];
-       unsigned int local_rqfcr[MAX_FILER_IDX + 1];
+       unsigned int *local_rqfpr;
+       unsigned int *local_rqfcr;
        int i = 0x0, k = 0x0;
        int j = MAX_FILER_IDX, l = 0x0;
+       int ret = 1;
+
+       local_rqfpr = kmalloc(sizeof(unsigned int) * (MAX_FILER_IDX + 1),
+               GFP_KERNEL);
+       local_rqfcr = kmalloc(sizeof(unsigned int) * (MAX_FILER_IDX + 1),
+               GFP_KERNEL);
+       if (!local_rqfpr || !local_rqfcr) {
+               pr_err("Out of memory\n");
+               ret = 0;
+               goto err;
+       }
 
        switch (class) {
        case TCP_V4_FLOW:
@@ -706,7 +717,8 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u
                break;
        default:
                pr_err("Right now this class is not supported\n");
-               return 0;
+               ret = 0;
+               goto err;
        }
 
        for (i = 0; i < MAX_FILER_IDX + 1; i++) {
@@ -721,7 +733,8 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u
 
        if (i == MAX_FILER_IDX + 1) {
                pr_err("No parse rule found, can't create hash rules\n");
-               return 0;
+               ret = 0;
+               goto err;
        }
 
        /* If a match was found, then it begins the starting of a cluster rule
@@ -765,7 +778,10 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u
                priv->cur_filer_idx = priv->cur_filer_idx - 1;
        }
 
-       return 1;
+err:
+       kfree(local_rqfcr);
+       kfree(local_rqfpr);
+       return ret;
 }
 
 static int gfar_set_hash_opts(struct gfar_private *priv, struct ethtool_rxnfc *cmd)
similarity index 98%
rename from drivers/net/gianfar_ptp.c
rename to drivers/net/ethernet/freescale/gianfar_ptp.c
index 1c97861..f67b8ae 100644 (file)
@@ -193,14 +193,9 @@ static void set_alarm(struct etsects *etsects)
 /* Caller must hold etsects->lock. */
 static void set_fipers(struct etsects *etsects)
 {
-       u32 tmr_ctrl = gfar_read(&etsects->regs->tmr_ctrl);
-
-       gfar_write(&etsects->regs->tmr_ctrl,   tmr_ctrl & (~TE));
-       gfar_write(&etsects->regs->tmr_prsc,   etsects->tmr_prsc);
+       set_alarm(etsects);
        gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1);
        gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2);
-       set_alarm(etsects);
-       gfar_write(&etsects->regs->tmr_ctrl,   tmr_ctrl|TE);
 }
 
 /*
@@ -511,7 +506,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
        gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1);
        gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2);
        set_alarm(etsects);
-       gfar_write(&etsects->regs->tmr_ctrl,   tmr_ctrl|FS|RTPE|TE);
+       gfar_write(&etsects->regs->tmr_ctrl,   tmr_ctrl|FS|RTPE|TE|FRD);
 
        spin_unlock_irqrestore(&etsects->lock, flags);
 
similarity index 99%
rename from drivers/net/ucc_geth.c
rename to drivers/net/ethernet/freescale/ucc_geth.c
index d3465ab..46d690a 100644 (file)
@@ -1761,10 +1761,12 @@ static int init_phy(struct net_device *dev)
        if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII)
                uec_configure_serdes(dev);
 
-       phydev->supported &= (ADVERTISED_10baseT_Half |
-                                ADVERTISED_10baseT_Full |
-                                ADVERTISED_100baseT_Half |
-                                ADVERTISED_100baseT_Full);
+       phydev->supported &= (SUPPORTED_MII |
+                             SUPPORTED_Autoneg |
+                             ADVERTISED_10baseT_Half |
+                             ADVERTISED_10baseT_Full |
+                             ADVERTISED_100baseT_Half |
+                             ADVERTISED_100baseT_Full);
 
        if (priv->max_speed == SPEED_1000)
                phydev->supported |= ADVERTISED_1000baseT_Full;
@@ -3729,7 +3731,7 @@ static const struct net_device_ops ucc_geth_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ucc_geth_set_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
-       .ndo_set_multicast_list = ucc_geth_set_multi,
+       .ndo_set_rx_mode        = ucc_geth_set_multi,
        .ndo_tx_timeout         = ucc_geth_timeout,
        .ndo_do_ioctl           = ucc_geth_ioctl,
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/fujitsu/Kconfig b/drivers/net/ethernet/fujitsu/Kconfig
new file mode 100644 (file)
index 0000000..dffee9d
--- /dev/null
@@ -0,0 +1,54 @@
+#
+# Fujitsu Network device configuration
+#
+
+config NET_VENDOR_FUJITSU
+       bool "Fujitsu devices"
+       default y
+       depends on ISA || PCMCIA || ((ISA || MCA_LEGACY) && EXPERIMENTAL)
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         the questions about Fujitsu cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_FUJITSU
+
+config AT1700
+       tristate "AT1700/1720 support (EXPERIMENTAL)"
+       depends on (ISA || MCA_LEGACY) && EXPERIMENTAL
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called at1700.
+
+config PCMCIA_FMVJ18X
+       tristate "Fujitsu FMV-J18x PCMCIA support"
+       depends on PCMCIA
+       select CRC32
+       ---help---
+         Say Y here if you intend to attach a Fujitsu FMV-J18x or compatible
+         PCMCIA (PC-card) Ethernet card to your computer.
+
+         To compile this driver as a module, choose M here: the module will be
+         called fmvj18x_cs.  If unsure, say N.
+
+config ETH16I
+       tristate "ICL EtherTeam 16i/32 support"
+       depends on ISA
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called eth16i.
+
+endif # NET_VENDOR_FUJITSU
diff --git a/drivers/net/ethernet/fujitsu/Makefile b/drivers/net/ethernet/fujitsu/Makefile
new file mode 100644 (file)
index 0000000..2730ae6
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the Fujitsu network device drivers.
+#
+
+obj-$(CONFIG_AT1700) += at1700.o
+obj-$(CONFIG_ETH16I) += eth16i.o
+obj-$(CONFIG_PCMCIA_FMVJ18X) += fmvj18x_cs.o
similarity index 99%
rename from drivers/net/at1700.c
rename to drivers/net/ethernet/fujitsu/at1700.c
index 65a78f9..7c6c908 100644 (file)
@@ -253,7 +253,7 @@ static const struct net_device_ops at1700_netdev_ops = {
        .ndo_open               = net_open,
        .ndo_stop               = net_close,
        .ndo_start_xmit         = net_send_packet,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_tx_timeout         = net_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/eth16i.c
rename to drivers/net/ethernet/fujitsu/eth16i.c
index 12d28e9..b0e2313 100644 (file)
@@ -478,7 +478,7 @@ static const struct net_device_ops eth16i_netdev_ops = {
        .ndo_open               = eth16i_open,
        .ndo_stop               = eth16i_close,
        .ndo_start_xmit         = eth16i_tx,
-       .ndo_set_multicast_list = eth16i_multicast,
+       .ndo_set_rx_mode        = eth16i_multicast,
        .ndo_tx_timeout         = eth16i_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/pcmcia/fmvj18x_cs.c
rename to drivers/net/ethernet/fujitsu/fmvj18x_cs.c
index 723815e..1541675 100644 (file)
@@ -226,7 +226,7 @@ static const struct net_device_ops fjn_netdev_ops = {
        .ndo_start_xmit         = fjn_start_xmit,
        .ndo_tx_timeout         = fjn_tx_timeout,
        .ndo_set_config         = fjn_config,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
diff --git a/drivers/net/ethernet/hp/Kconfig b/drivers/net/ethernet/hp/Kconfig
new file mode 100644 (file)
index 0000000..a0b8ece
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# HP network device configuration
+#
+
+config NET_VENDOR_HP
+       bool "HP devices"
+       default y
+       depends on ISA || EISA || PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about HP cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_HP
+
+config HP100
+       tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support"
+       depends on (ISA || EISA || PCI)
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called hp100.
+
+endif # NET_VENDOR_HP
diff --git a/drivers/net/ethernet/hp/Makefile b/drivers/net/ethernet/hp/Makefile
new file mode 100644 (file)
index 0000000..20b6918
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the HP network device drivers.
+#
+
+obj-$(CONFIG_HP100) += hp100.o
similarity index 99%
rename from drivers/net/hp100.c
rename to drivers/net/ethernet/hp/hp100.c
index b6519c1..6a5ee07 100644 (file)
@@ -430,7 +430,7 @@ static const struct net_device_ops hp100_bm_netdev_ops = {
        .ndo_stop               = hp100_close,
        .ndo_start_xmit         = hp100_start_xmit_bm,
        .ndo_get_stats          = hp100_get_stats,
-       .ndo_set_multicast_list = hp100_set_multicast_list,
+       .ndo_set_rx_mode        = hp100_set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
@@ -441,7 +441,7 @@ static const struct net_device_ops hp100_netdev_ops = {
        .ndo_stop               = hp100_close,
        .ndo_start_xmit         = hp100_start_xmit,
        .ndo_get_stats          = hp100_get_stats,
-       .ndo_set_multicast_list = hp100_set_multicast_list,
+       .ndo_set_rx_mode        = hp100_set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/3c505.c
rename to drivers/net/ethernet/i825xx/3c505.c
index 88d766e..40e1a17 100644 (file)
@@ -1363,7 +1363,7 @@ static const struct net_device_ops elp_netdev_ops = {
        .ndo_get_stats          = elp_get_stats,
        .ndo_start_xmit         = elp_start_xmit,
        .ndo_tx_timeout         = elp_timeout,
-       .ndo_set_multicast_list = elp_set_mc_list,
+       .ndo_set_rx_mode        = elp_set_mc_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/3c523.c
rename to drivers/net/ethernet/i825xx/3c523.c
index bc0d1a1..d70d3df 100644 (file)
@@ -409,7 +409,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_start_xmit         = elmc_send_packet,
        .ndo_tx_timeout         = elmc_timeout,
 #ifdef ELMC_MULTICAST
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
 #endif
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/3c527.c
rename to drivers/net/ethernet/i825xx/3c527.c
index d9d056d..474b5e7 100644 (file)
@@ -292,7 +292,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_stop               = mc32_close,
        .ndo_start_xmit         = mc32_send_packet,
        .ndo_get_stats          = mc32_get_stats,
-       .ndo_set_multicast_list = mc32_set_multicast_list,
+       .ndo_set_rx_mode        = mc32_set_multicast_list,
        .ndo_tx_timeout         = mc32_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/82596.c
rename to drivers/net/ethernet/i825xx/82596.c
index be1f197..f2408a4 100644 (file)
@@ -1145,7 +1145,7 @@ static const struct net_device_ops i596_netdev_ops = {
        .ndo_open               = i596_open,
        .ndo_stop               = i596_close,
        .ndo_start_xmit         = i596_start_xmit,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_tx_timeout         = i596_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
diff --git a/drivers/net/ethernet/i825xx/Kconfig b/drivers/net/ethernet/i825xx/Kconfig
new file mode 100644 (file)
index 0000000..2be4698
--- /dev/null
@@ -0,0 +1,183 @@
+#
+# Intel 82596/82593/82596 network device configuration
+#
+
+config NET_VENDOR_I825XX
+       bool "Intel (82586/82593/82596) devices"
+       default y
+       depends on NET_VENDOR_INTEL && (ISA || ISA_DMA_API || ARM || \
+                  ARCH_ACORN || MCA || MCA_LEGACY || SNI_RM || SUN3 || \
+                  GSC || BVME6000 || MVME16x || EXPERIMENTAL)
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question does not directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about these devices. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_I825XX
+
+config ELPLUS
+       tristate "3c505 \"EtherLink Plus\" support"
+       depends on ISA && ISA_DMA_API
+       ---help---
+         Information about this network (Ethernet) card can be found in
+         <file:Documentation/networking/3c505.txt>.  If you have a card of
+         this type, say Y and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called 3c505.
+
+config EL16
+       tristate "3c507 \"EtherLink 16\" support (EXPERIMENTAL)"
+       depends on ISA && EXPERIMENTAL
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called 3c507.
+
+config ELMC
+       tristate "3c523 \"EtherLink/MC\" support"
+       depends on MCA_LEGACY
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called 3c523.
+
+config ELMC_II
+       tristate "3c527 \"EtherLink/MC 32\" support (EXPERIMENTAL)"
+       depends on MCA && MCA_LEGACY
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called 3c527.
+
+config ARM_ETHER1
+       tristate "Acorn Ether1 support"
+       depends on ARM && ARCH_ACORN
+       ---help---
+         If you have an Acorn system with one of these (AKA25) network cards,
+         you should say Y to this option if you wish to use it with Linux.
+
+config APRICOT
+       tristate "Apricot Xen-II on board Ethernet"
+       depends on ISA
+       ---help---
+         If you have a network (Ethernet) controller of this type, say Y and
+         read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called apricot.
+
+config BVME6000_NET
+       tristate "BVME6000 Ethernet support"
+       depends on BVME6000MVME16x
+       ---help---
+         This is the driver for the Ethernet interface on BVME4000 and
+         BVME6000 VME boards.  Say Y here to include the driver for this chip
+         in your kernel.
+         To compile this driver as a module, choose M here.
+
+config EEXPRESS
+       tristate "EtherExpress 16 support"
+       depends on ISA
+       ---help---
+         If you have an EtherExpress16 network (Ethernet) card, say Y and
+         read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.  Note that the Intel
+         EtherExpress16 card used to be regarded as a very poor choice
+         because the driver was very unreliable. We now have a new driver
+         that should do better.
+
+         To compile this driver as a module, choose M here. The module
+         will be called eexpress.
+
+config EEXPRESS_PRO
+       tristate "EtherExpressPro support/EtherExpress 10 (i82595) support"
+       depends on ISA
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y. This
+         driver supports Intel i82595{FX,TX} based boards. Note however
+         that the EtherExpress PRO/100 Ethernet card has its own separate
+         driver.  Please read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called eepro.
+
+config LASI_82596
+       tristate "Lasi ethernet"
+       depends on GSC
+       ---help---
+         Say Y here to support the builtin Intel 82596 ethernet controller
+         found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
+
+config LP486E
+       tristate "LP486E on board Ethernet"
+       depends on ISA
+       ---help---
+         Say Y here to support the 82596-based on-board Ethernet controller
+         for the Panther motherboard, which is one of the two shipped in the
+         Intel Professional Workstation.
+
+config MVME16x_NET
+       tristate "MVME16x Ethernet support"
+       depends on MVME16x
+       ---help---
+         This is the driver for the Ethernet interface on the Motorola
+         MVME162, 166, 167, 172 and 177 boards.  Say Y here to include the
+         driver for this chip in your kernel.
+         To compile this driver as a module, choose M here.
+
+config NI52
+       tristate "NI5210 support"
+       depends on ISA
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ni52.
+
+config SNI_82596
+       tristate "SNI RM ethernet"
+       depends on SNI_RM
+       ---help---
+         Say Y here to support the on-board Intel 82596 ethernet controller
+         built into SNI RM machines.
+
+config SUN3_82586
+       bool "Sun3 on-board Intel 82586 support"
+       depends on SUN3
+       ---help---
+         This driver enables support for the on-board Intel 82586 based
+         Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards.  Note
+         that this driver does not support 82586-based adapters on additional
+         VME boards.
+
+config ZNET
+       tristate "Zenith Z-Note support (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && ISA_DMA_API
+       ---help---
+         The Zenith Z-Note notebook computer has a built-in network
+         (Ethernet) card, and this is the Linux driver for it. Note that the
+         IBM Thinkpad 300 is compatible with the Z-Note and is also supported
+         by this driver. Read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+endif # NET_VENDOR_I825XX
diff --git a/drivers/net/ethernet/i825xx/Makefile b/drivers/net/ethernet/i825xx/Makefile
new file mode 100644 (file)
index 0000000..f68a369
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Makefile for the Intel 82586/82593/82596 chipset device drivers.
+#
+
+obj-$(CONFIG_ARM_ETHER1) += ether1.o
+obj-$(CONFIG_EEXPRESS) += eexpress.o
+obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
+obj-$(CONFIG_ELPLUS) += 3c505.o
+obj-$(CONFIG_EL16) += 3c507.o
+obj-$(CONFIG_ELMC) += 3c523.o
+obj-$(CONFIG_ELMC_II) += 3c527.o
+obj-$(CONFIG_LP486E) += lp486e.o
+obj-$(CONFIG_NI52) += ni52.o
+obj-$(CONFIG_SUN3_82586) += sun3_82586.o
+obj-$(CONFIG_ZNET) += znet.o
+obj-$(CONFIG_APRICOT) += 82596.o
+obj-$(CONFIG_LASI_82596) += lasi_82596.o
+obj-$(CONFIG_SNI_82596) += sni_82596.o
+obj-$(CONFIG_MVME16x_NET) += 82596.o
+obj-$(CONFIG_BVME6000_NET) += 82596.o
similarity index 99%
rename from drivers/net/eepro.c
rename to drivers/net/ethernet/i825xx/eepro.c
index dfeb006..067c460 100644 (file)
@@ -743,7 +743,7 @@ static const struct net_device_ops eepro_netdev_ops = {
        .ndo_open               = eepro_open,
        .ndo_stop               = eepro_close,
        .ndo_start_xmit         = eepro_send_packet,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_tx_timeout         = eepro_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/eexpress.c
rename to drivers/net/ethernet/i825xx/eexpress.c
index a192285..3a9580f 100644 (file)
@@ -1047,7 +1047,7 @@ static const struct net_device_ops eexp_netdev_ops = {
        .ndo_open               = eexp_open,
        .ndo_stop               = eexp_close,
        .ndo_start_xmit         = eexp_xmit,
-       .ndo_set_multicast_list = eexp_set_multicast,
+       .ndo_set_rx_mode        = eexp_set_multicast,
        .ndo_tx_timeout         = eexp_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/arm/ether1.c
rename to drivers/net/ethernet/i825xx/ether1.c
index b00781c..42e90a9 100644 (file)
@@ -985,7 +985,7 @@ static const struct net_device_ops ether1_netdev_ops = {
        .ndo_open               = ether1_open,
        .ndo_stop               = ether1_close,
        .ndo_start_xmit         = ether1_sendpacket,
-       .ndo_set_multicast_list = ether1_setmulticastlist,
+       .ndo_set_rx_mode        = ether1_setmulticastlist,
        .ndo_tx_timeout         = ether1_timeout,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/lib82596.c
rename to drivers/net/ethernet/i825xx/lib82596.c
index 9e04289..3efbd8d 100644 (file)
@@ -1038,7 +1038,7 @@ static const struct net_device_ops i596_netdev_ops = {
        .ndo_open               = i596_open,
        .ndo_stop               = i596_close,
        .ndo_start_xmit         = i596_start_xmit,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_tx_timeout         = i596_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/lp486e.c
rename to drivers/net/ethernet/i825xx/lp486e.c
index 385a953..414044b 100644 (file)
@@ -954,7 +954,7 @@ static const struct net_device_ops i596_netdev_ops = {
        .ndo_open               = i596_open,
        .ndo_stop               = i596_close,
        .ndo_start_xmit         = i596_start_xmit,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_tx_timeout         = i596_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/ni52.c
rename to drivers/net/ethernet/i825xx/ni52.c
index d973fc6..c089371 100644 (file)
@@ -445,7 +445,7 @@ static const struct net_device_ops ni52_netdev_ops = {
        .ndo_get_stats          = ni52_get_stats,
        .ndo_tx_timeout         = ni52_timeout,
        .ndo_start_xmit         = ni52_send_packet,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/sun3_82586.c
rename to drivers/net/ethernet/i825xx/sun3_82586.c
index b6ae53b..6ef5e11 100644 (file)
@@ -333,7 +333,7 @@ static const struct net_device_ops sun3_82586_netdev_ops = {
        .ndo_open               = sun3_82586_open,
        .ndo_stop               = sun3_82586_close,
        .ndo_start_xmit         = sun3_82586_send_packet,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_tx_timeout         = sun3_82586_timeout,
        .ndo_get_stats          = sun3_82586_get_stats,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/znet.c
rename to drivers/net/ethernet/i825xx/znet.c
index 8b88817..962b4c4 100644 (file)
@@ -356,7 +356,7 @@ static const struct net_device_ops znet_netdev_ops = {
        .ndo_open               = znet_open,
        .ndo_stop               = znet_close,
        .ndo_start_xmit         = znet_send_packet,
-       .ndo_set_multicast_list = znet_set_multicast_list,
+       .ndo_set_rx_mode        = znet_set_multicast_list,
        .ndo_tx_timeout         = znet_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
diff --git a/drivers/net/ethernet/ibm/Kconfig b/drivers/net/ethernet/ibm/Kconfig
new file mode 100644 (file)
index 0000000..9e16f3f
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# IBM device configuration.
+#
+
+config NET_VENDOR_IBM
+       bool "IBM devices"
+       default y
+       depends on MCA || PPC_PSERIES || PPC_PSERIES || PPC_DCR || \
+                  (IBMEBUS && INET && SPARSEMEM)
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about IBM devices. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_IBM
+
+config IBMVETH
+       tristate "IBM LAN Virtual Ethernet support"
+       depends on PPC_PSERIES
+       ---help---
+         This driver supports virtual ethernet adapters on newer IBM iSeries
+         and pSeries systems.
+
+         To compile this driver as a module, choose M here. The module will
+         be called ibmveth.
+
+config ISERIES_VETH
+       tristate "iSeries Virtual Ethernet driver support"
+       depends on PPC_ISERIES
+
+source "drivers/net/ethernet/ibm/emac/Kconfig"
+
+config EHEA
+       tristate "eHEA Ethernet support"
+       depends on IBMEBUS && INET && SPARSEMEM
+       select INET_LRO
+       ---help---
+         This driver supports the IBM pSeries eHEA ethernet adapter.
+
+         To compile the driver as a module, choose M here. The module
+         will be called ehea.
+
+endif # NET_VENDOR_IBM
diff --git a/drivers/net/ethernet/ibm/Makefile b/drivers/net/ethernet/ibm/Makefile
new file mode 100644 (file)
index 0000000..5a7d4e9
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for th IBM network device drivers.
+#
+
+obj-$(CONFIG_IBMVETH) += ibmveth.o
+obj-$(CONFIG_ISERIES_VETH) += iseries_veth.o
+obj-$(CONFIG_IBM_EMAC) += emac/
+obj-$(CONFIG_EHEA) += ehea/
similarity index 99%
rename from drivers/net/ehea/ehea_main.c
rename to drivers/net/ethernet/ibm/ehea/ehea_main.c
index be2cb4a..583bcd3 100644 (file)
@@ -3161,7 +3161,7 @@ static const struct net_device_ops ehea_netdev_ops = {
        .ndo_get_stats          = ehea_get_stats,
        .ndo_set_mac_address    = ehea_set_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = ehea_set_multicast_list,
+       .ndo_set_rx_mode        = ehea_set_multicast_list,
        .ndo_change_mtu         = ehea_change_mtu,
        .ndo_vlan_rx_add_vid    = ehea_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid   = ehea_vlan_rx_kill_vid,
similarity index 63%
rename from drivers/net/ibm_newemac/Kconfig
rename to drivers/net/ethernet/ibm/emac/Kconfig
index 78a1628..3f44a30 100644 (file)
@@ -1,4 +1,4 @@
-config IBM_NEW_EMAC
+config IBM_EMAC
        tristate "IBM EMAC Ethernet support"
        depends on PPC_DCR
        select CRC32
@@ -7,29 +7,29 @@ config IBM_NEW_EMAC
          typically found on 4xx embedded PowerPC chips, but also on the
          Axon southbridge for Cell.
 
-config IBM_NEW_EMAC_RXB
+config IBM_EMAC_RXB
        int "Number of receive buffers"
-       depends on IBM_NEW_EMAC
+       depends on IBM_EMAC
        default "128"
 
-config IBM_NEW_EMAC_TXB
+config IBM_EMAC_TXB
        int "Number of transmit buffers"
-       depends on IBM_NEW_EMAC
+       depends on IBM_EMAC
        default "64"
 
-config IBM_NEW_EMAC_POLL_WEIGHT
+config IBM_EMAC_POLL_WEIGHT
        int "MAL NAPI polling weight"
-       depends on IBM_NEW_EMAC
+       depends on IBM_EMAC
        default "32"
 
-config IBM_NEW_EMAC_RX_COPY_THRESHOLD
+config IBM_EMAC_RX_COPY_THRESHOLD
        int "RX skb copy threshold (bytes)"
-       depends on IBM_NEW_EMAC
+       depends on IBM_EMAC
        default "256"
 
-config IBM_NEW_EMAC_RX_SKB_HEADROOM
+config IBM_EMAC_RX_SKB_HEADROOM
        int "Additional RX skb headroom (bytes)"
-       depends on IBM_NEW_EMAC
+       depends on IBM_EMAC
        default "0"
        help
          Additional receive skb headroom. Note, that driver
@@ -39,38 +39,38 @@ config IBM_NEW_EMAC_RX_SKB_HEADROOM
 
          If unsure, set to 0.
 
-config IBM_NEW_EMAC_DEBUG
+config IBM_EMAC_DEBUG
        bool "Debugging"
-       depends on IBM_NEW_EMAC
+       depends on IBM_EMAC
        default n
 
 # The options below has to be select'ed by the respective
 # processor types or platforms
 
-config IBM_NEW_EMAC_ZMII
+config IBM_EMAC_ZMII
        bool
        default n
 
-config IBM_NEW_EMAC_RGMII
+config IBM_EMAC_RGMII
        bool
        default n
 
-config IBM_NEW_EMAC_TAH
+config IBM_EMAC_TAH
        bool
        default n
 
-config IBM_NEW_EMAC_EMAC4
+config IBM_EMAC_EMAC4
        bool
        default n
 
-config IBM_NEW_EMAC_NO_FLOW_CTRL
+config IBM_EMAC_NO_FLOW_CTRL
        bool
        default n
 
-config IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
+config IBM_EMAC_MAL_CLR_ICINTSTAT
        bool
        default n
 
-config IBM_NEW_EMAC_MAL_COMMON_ERR
+config IBM_EMAC_MAL_COMMON_ERR
        bool
        default n
diff --git a/drivers/net/ethernet/ibm/emac/Makefile b/drivers/net/ethernet/ibm/emac/Makefile
new file mode 100644 (file)
index 0000000..eba2183
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for the PowerPC 4xx on-chip ethernet driver
+#
+
+obj-$(CONFIG_IBM_EMAC) += ibm_emac.o
+
+ibm_emac-y := mal.o core.o phy.o
+ibm_emac-$(CONFIG_IBM_EMAC_ZMII) += zmii.o
+ibm_emac-$(CONFIG_IBM_EMAC_RGMII) += rgmii.o
+ibm_emac-$(CONFIG_IBM_EMAC_TAH) += tah.o
+ibm_emac-$(CONFIG_IBM_EMAC_DEBUG) += debug.o
similarity index 98%
rename from drivers/net/ibm_newemac/core.c
rename to drivers/net/ethernet/ibm/emac/core.c
index 725399e..a573df1 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/bitops.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
+#include <linux/of_net.h>
 #include <linux/slab.h>
 
 #include <asm/processor.h>
@@ -89,7 +90,7 @@ MODULE_LICENSE("GPL");
 /* If packet size is less than this number, we allocate small skb and copy packet
  * contents into it instead of just sending original big skb up
  */
-#define EMAC_RX_COPY_THRESH            CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD
+#define EMAC_RX_COPY_THRESH            CONFIG_IBM_EMAC_RX_COPY_THRESHOLD
 
 /* Since multiple EMACs share MDIO lines in various ways, we need
  * to avoid re-using the same PHY ID in cases where the arch didn't
@@ -1617,7 +1618,7 @@ static void emac_parse_rx_error(struct emac_instance *dev, u16 ctrl)
 static inline void emac_rx_csum(struct emac_instance *dev,
                                struct sk_buff *skb, u16 ctrl)
 {
-#ifdef CONFIG_IBM_NEW_EMAC_TAH
+#ifdef CONFIG_IBM_EMAC_TAH
        if (!ctrl && dev->tah_dev) {
                skb->ip_summed = CHECKSUM_UNNECESSARY;
                ++dev->stats.rx_packets_csum;
@@ -2506,18 +2507,6 @@ static int __devinit emac_init_config(struct emac_instance *dev)
 {
        struct device_node *np = dev->ofdev->dev.of_node;
        const void *p;
-       unsigned int plen;
-       const char *pm, *phy_modes[] = {
-               [PHY_MODE_NA] = "",
-               [PHY_MODE_MII] = "mii",
-               [PHY_MODE_RMII] = "rmii",
-               [PHY_MODE_SMII] = "smii",
-               [PHY_MODE_RGMII] = "rgmii",
-               [PHY_MODE_TBI] = "tbi",
-               [PHY_MODE_GMII] = "gmii",
-               [PHY_MODE_RTBI] = "rtbi",
-               [PHY_MODE_SGMII] = "sgmii",
-       };
 
        /* Read config from device-tree */
        if (emac_read_uint_prop(np, "mal-device", &dev->mal_ph, 1))
@@ -2566,23 +2555,9 @@ static int __devinit emac_init_config(struct emac_instance *dev)
                dev->mal_burst_size = 256;
 
        /* PHY mode needs some decoding */
-       dev->phy_mode = PHY_MODE_NA;
-       pm = of_get_property(np, "phy-mode", &plen);
-       if (pm != NULL) {
-               int i;
-               for (i = 0; i < ARRAY_SIZE(phy_modes); i++)
-                       if (!strcasecmp(pm, phy_modes[i])) {
-                               dev->phy_mode = i;
-                               break;
-                       }
-       }
-
-       /* Backward compat with non-final DT */
-       if (dev->phy_mode == PHY_MODE_NA && pm != NULL && plen == 4) {
-               u32 nmode = *(const u32 *)pm;
-               if (nmode > PHY_MODE_NA && nmode <= PHY_MODE_SGMII)
-                       dev->phy_mode = nmode;
-       }
+       dev->phy_mode = of_get_phy_mode(np);
+       if (dev->phy_mode < 0)
+               dev->phy_mode = PHY_MODE_NA;
 
        /* Check EMAC version */
        if (of_device_is_compatible(np, "ibm,emac4sync")) {
@@ -2602,7 +2577,7 @@ static int __devinit emac_init_config(struct emac_instance *dev)
                    of_device_is_compatible(np, "ibm,emac-440gr"))
                        dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
                if (of_device_is_compatible(np, "ibm,emac-405ez")) {
-#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL
+#ifdef CONFIG_IBM_EMAC_NO_FLOW_CTRL
                        dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x;
 #else
                        printk(KERN_ERR "%s: Flow control not disabled!\n",
@@ -2626,7 +2601,7 @@ static int __devinit emac_init_config(struct emac_instance *dev)
 
        /* Enable TAH/ZMII/RGMII features as found */
        if (dev->tah_ph != 0) {
-#ifdef CONFIG_IBM_NEW_EMAC_TAH
+#ifdef CONFIG_IBM_EMAC_TAH
                dev->features |= EMAC_FTR_HAS_TAH;
 #else
                printk(KERN_ERR "%s: TAH support not enabled !\n",
@@ -2636,7 +2611,7 @@ static int __devinit emac_init_config(struct emac_instance *dev)
        }
 
        if (dev->zmii_ph != 0) {
-#ifdef CONFIG_IBM_NEW_EMAC_ZMII
+#ifdef CONFIG_IBM_EMAC_ZMII
                dev->features |= EMAC_FTR_HAS_ZMII;
 #else
                printk(KERN_ERR "%s: ZMII support not enabled !\n",
@@ -2646,7 +2621,7 @@ static int __devinit emac_init_config(struct emac_instance *dev)
        }
 
        if (dev->rgmii_ph != 0) {
-#ifdef CONFIG_IBM_NEW_EMAC_RGMII
+#ifdef CONFIG_IBM_EMAC_RGMII
                dev->features |= EMAC_FTR_HAS_RGMII;
 #else
                printk(KERN_ERR "%s: RGMII support not enabled !\n",
@@ -2686,7 +2661,7 @@ static const struct net_device_ops emac_netdev_ops = {
        .ndo_open               = emac_open,
        .ndo_stop               = emac_close,
        .ndo_get_stats          = emac_stats,
-       .ndo_set_multicast_list = emac_set_multicast_list,
+       .ndo_set_rx_mode        = emac_set_multicast_list,
        .ndo_do_ioctl           = emac_ioctl,
        .ndo_tx_timeout         = emac_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
@@ -2699,7 +2674,7 @@ static const struct net_device_ops emac_gige_netdev_ops = {
        .ndo_open               = emac_open,
        .ndo_stop               = emac_close,
        .ndo_get_stats          = emac_stats,
-       .ndo_set_multicast_list = emac_set_multicast_list,
+       .ndo_set_rx_mode        = emac_set_multicast_list,
        .ndo_do_ioctl           = emac_ioctl,
        .ndo_tx_timeout         = emac_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 97%
rename from drivers/net/ibm_newemac/core.h
rename to drivers/net/ethernet/ibm/emac/core.h
index 4fec084..fa3ec57 100644 (file)
@@ -47,8 +47,8 @@
 #include "tah.h"
 #include "debug.h"
 
-#define NUM_TX_BUFF                    CONFIG_IBM_NEW_EMAC_TXB
-#define NUM_RX_BUFF                    CONFIG_IBM_NEW_EMAC_RXB
+#define NUM_TX_BUFF                    CONFIG_IBM_EMAC_TXB
+#define NUM_RX_BUFF                    CONFIG_IBM_EMAC_RXB
 
 /* Simple sanity check */
 #if NUM_TX_BUFF > 256 || NUM_RX_BUFF > 256
@@ -72,7 +72,7 @@ static inline int emac_rx_size(int mtu)
 #define EMAC_DMA_ALIGN(x)              ALIGN((x), dma_get_cache_alignment())
 
 #define EMAC_RX_SKB_HEADROOM           \
-       EMAC_DMA_ALIGN(CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM)
+       EMAC_DMA_ALIGN(CONFIG_IBM_EMAC_RX_SKB_HEADROOM)
 
 /* Size of RX skb for the given MTU */
 static inline int emac_rx_skb_size(int mtu)
@@ -335,21 +335,21 @@ enum {
        EMAC_FTRS_ALWAYS        = 0,
 
        EMAC_FTRS_POSSIBLE      =
-#ifdef CONFIG_IBM_NEW_EMAC_EMAC4
+#ifdef CONFIG_IBM_EMAC_EMAC4
            EMAC_FTR_EMAC4      | EMAC_FTR_EMAC4SYNC    |
            EMAC_FTR_HAS_NEW_STACR      |
            EMAC_FTR_STACR_OC_INVERT | EMAC_FTR_440GX_PHY_CLK_FIX |
 #endif
-#ifdef CONFIG_IBM_NEW_EMAC_TAH
+#ifdef CONFIG_IBM_EMAC_TAH
            EMAC_FTR_HAS_TAH    |
 #endif
-#ifdef CONFIG_IBM_NEW_EMAC_ZMII
+#ifdef CONFIG_IBM_EMAC_ZMII
            EMAC_FTR_HAS_ZMII   |
 #endif
-#ifdef CONFIG_IBM_NEW_EMAC_RGMII
+#ifdef CONFIG_IBM_EMAC_RGMII
            EMAC_FTR_HAS_RGMII  |
 #endif
-#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL
+#ifdef CONFIG_IBM_EMAC_NO_FLOW_CTRL
            EMAC_FTR_NO_FLOW_CONTROL_40x |
 #endif
        EMAC_FTR_460EX_PHY_CLK_FIX |
similarity index 98%
rename from drivers/net/ibm_newemac/debug.h
rename to drivers/net/ethernet/ibm/emac/debug.h
index e596c77..90477fe 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "core.h"
 
-#if defined(CONFIG_IBM_NEW_EMAC_DEBUG)
+#if defined(CONFIG_IBM_EMAC_DEBUG)
 
 struct emac_instance;
 struct mal_instance;
similarity index 95%
rename from drivers/net/ibm_newemac/emac.h
rename to drivers/net/ethernet/ibm/emac/emac.h
index 8a61b59..1568278 100644 (file)
@@ -26,6 +26,7 @@
 #define __IBM_NEWEMAC_H
 
 #include <linux/types.h>
+#include <linux/phy.h>
 
 /* EMAC registers                      Write Access rules */
 struct emac_regs {
@@ -106,15 +107,15 @@ struct emac_regs {
 /*
  * PHY mode settings (EMAC <-> ZMII/RGMII bridge <-> PHY)
  */
-#define PHY_MODE_NA    0
-#define PHY_MODE_MII   1
-#define PHY_MODE_RMII  2
-#define PHY_MODE_SMII  3
-#define PHY_MODE_RGMII 4
-#define PHY_MODE_TBI   5
-#define PHY_MODE_GMII  6
-#define PHY_MODE_RTBI  7
-#define PHY_MODE_SGMII 8
+#define PHY_MODE_NA    PHY_INTERFACE_MODE_NA
+#define PHY_MODE_MII   PHY_INTERFACE_MODE_MII
+#define PHY_MODE_RMII  PHY_INTERFACE_MODE_RMII
+#define PHY_MODE_SMII  PHY_INTERFACE_MODE_SMII
+#define PHY_MODE_RGMII PHY_INTERFACE_MODE_RGMII
+#define PHY_MODE_TBI   PHY_INTERFACE_MODE_TBI
+#define PHY_MODE_GMII  PHY_INTERFACE_MODE_GMII
+#define PHY_MODE_RTBI  PHY_INTERFACE_MODE_RTBI
+#define PHY_MODE_SGMII PHY_INTERFACE_MODE_SGMII
 
 /* EMACx_MR0 */
 #define EMAC_MR0_RXI                   0x80000000
similarity index 99%
rename from drivers/net/ibm_newemac/mal.c
rename to drivers/net/ethernet/ibm/emac/mal.c
index d268f40..f3c50b9 100644 (file)
@@ -577,8 +577,8 @@ static int __devinit mal_probe(struct platform_device *ofdev)
        }
 
        if (of_device_is_compatible(ofdev->dev.of_node, "ibm,mcmal-405ez")) {
-#if defined(CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT) && \
-               defined(CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR)
+#if defined(CONFIG_IBM_EMAC_MAL_CLR_ICINTSTAT) && \
+               defined(CONFIG_IBM_EMAC_MAL_COMMON_ERR)
                mal->features |= (MAL_FTR_CLEAR_ICINTSTAT |
                                MAL_FTR_COMMON_ERR_INT);
 #else
@@ -616,7 +616,7 @@ static int __devinit mal_probe(struct platform_device *ofdev)
        init_dummy_netdev(&mal->dummy_dev);
 
        netif_napi_add(&mal->dummy_dev, &mal->napi, mal_poll,
-                      CONFIG_IBM_NEW_EMAC_POLL_WEIGHT);
+                      CONFIG_IBM_EMAC_POLL_WEIGHT);
 
        /* Load power-on reset defaults */
        mal_reset(mal);
similarity index 99%
rename from drivers/net/ibm_newemac/mal.h
rename to drivers/net/ethernet/ibm/emac/mal.h
index 6608421..d06f985 100644 (file)
@@ -245,10 +245,10 @@ enum {
        MAL_FTRS_ALWAYS = 0,
 
        MAL_FTRS_POSSIBLE =
-#ifdef CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
+#ifdef CONFIG_IBM_EMAC_MAL_CLR_ICINTSTAT
                MAL_FTR_CLEAR_ICINTSTAT |
 #endif
-#ifdef CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR
+#ifdef CONFIG_IBM_EMAC_MAL_COMMON_ERR
                MAL_FTR_COMMON_ERR_INT |
 #endif
                0,
similarity index 98%
rename from drivers/net/ibm_newemac/phy.c
rename to drivers/net/ethernet/ibm/emac/phy.c
index ac9d964..ab4e596 100644 (file)
 #include "emac.h"
 #include "phy.h"
 
-static inline int phy_read(struct mii_phy *phy, int reg)
+#define phy_read _phy_read
+#define phy_write _phy_write
+
+static inline int _phy_read(struct mii_phy *phy, int reg)
 {
        return phy->mdio_read(phy->dev, phy->address, reg);
 }
 
-static inline void phy_write(struct mii_phy *phy, int reg, int val)
+static inline void _phy_write(struct mii_phy *phy, int reg, int val)
 {
        phy->mdio_write(phy->dev, phy->address, reg, val);
 }
similarity index 96%
rename from drivers/net/ibm_newemac/rgmii.h
rename to drivers/net/ethernet/ibm/emac/rgmii.h
index d697990..9296b6c 100644 (file)
@@ -54,7 +54,7 @@ struct rgmii_instance {
        struct platform_device          *ofdev;
 };
 
-#ifdef CONFIG_IBM_NEW_EMAC_RGMII
+#ifdef CONFIG_IBM_EMAC_RGMII
 
 extern int rgmii_init(void);
 extern void rgmii_exit(void);
@@ -77,6 +77,6 @@ extern void *rgmii_dump_regs(struct platform_device *ofdev, void *buf);
 # define rgmii_set_speed(x,y,z)        do { } while(0)
 # define rgmii_get_regs_len(x) 0
 # define rgmii_dump_regs(x,buf)        (buf)
-#endif                         /* !CONFIG_IBM_NEW_EMAC_RGMII */
+#endif                         /* !CONFIG_IBM_EMAC_RGMII */
 
 #endif /* __IBM_NEWEMAC_RGMII_H */
similarity index 97%
rename from drivers/net/ibm_newemac/tah.h
rename to drivers/net/ethernet/ibm/emac/tah.h
index 61dbeca..3437ab4 100644 (file)
@@ -70,7 +70,7 @@ struct tah_instance {
 #define TAH_MR_DTFP            0x00100000
 #define TAH_MR_DIG             0x00080000
 
-#ifdef CONFIG_IBM_NEW_EMAC_TAH
+#ifdef CONFIG_IBM_EMAC_TAH
 
 extern int tah_init(void);
 extern void tah_exit(void);
@@ -90,6 +90,6 @@ extern void *tah_dump_regs(struct platform_device *ofdev, void *buf);
 # define tah_get_regs_len(x)   0
 # define tah_dump_regs(x,buf)  (buf)
 
-#endif                         /* !CONFIG_IBM_NEW_EMAC_TAH */
+#endif                         /* !CONFIG_IBM_EMAC_TAH */
 
 #endif /* __IBM_NEWEMAC_TAH_H */
similarity index 96%
rename from drivers/net/ibm_newemac/zmii.h
rename to drivers/net/ethernet/ibm/emac/zmii.h
index 1333fa2..ceaed82 100644 (file)
@@ -51,7 +51,7 @@ struct zmii_instance {
        struct platform_device          *ofdev;
 };
 
-#ifdef CONFIG_IBM_NEW_EMAC_ZMII
+#ifdef CONFIG_IBM_EMAC_ZMII
 
 extern int zmii_init(void);
 extern void zmii_exit(void);
@@ -73,6 +73,6 @@ extern void *zmii_dump_regs(struct platform_device *ofdev, void *buf);
 # define zmii_set_speed(x,y,z) do { } while(0)
 # define zmii_get_regs_len(x)  0
 # define zmii_dump_regs(x,buf) (buf)
-#endif                         /* !CONFIG_IBM_NEW_EMAC_ZMII */
+#endif                         /* !CONFIG_IBM_EMAC_ZMII */
 
 #endif /* __IBM_NEWEMAC_ZMII_H */
similarity index 99%
rename from drivers/net/ibmveth.c
rename to drivers/net/ethernet/ibm/ibmveth.c
index ba99af0..bba1ffc 100644 (file)
@@ -1299,7 +1299,7 @@ static const struct net_device_ops ibmveth_netdev_ops = {
        .ndo_open               = ibmveth_open,
        .ndo_stop               = ibmveth_close,
        .ndo_start_xmit         = ibmveth_start_xmit,
-       .ndo_set_multicast_list = ibmveth_set_multicast_list,
+       .ndo_set_rx_mode        = ibmveth_set_multicast_list,
        .ndo_do_ioctl           = ibmveth_ioctl,
        .ndo_change_mtu         = ibmveth_change_mtu,
        .ndo_fix_features       = ibmveth_fix_features,
similarity index 99%
rename from drivers/net/iseries_veth.c
rename to drivers/net/ethernet/ibm/iseries_veth.c
index 53dd39e..4326681 100644 (file)
@@ -1009,7 +1009,7 @@ static const struct net_device_ops veth_netdev_ops = {
        .ndo_stop               = veth_close,
        .ndo_start_xmit         = veth_start_xmit,
        .ndo_change_mtu         = veth_change_mtu,
-       .ndo_set_multicast_list = veth_set_multicast_list,
+       .ndo_set_rx_mode        = veth_set_multicast_list,
        .ndo_set_mac_address    = NULL,
        .ndo_validate_addr      = eth_validate_addr,
 };
diff --git a/drivers/net/ethernet/icplus/Kconfig b/drivers/net/ethernet/icplus/Kconfig
new file mode 100644 (file)
index 0000000..e888222
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# IC Plus device configuration
+#
+
+config IP1000
+       tristate "IP1000 Gigabit Ethernet support"
+       depends on PCI && EXPERIMENTAL
+       select MII
+       ---help---
+         This driver supports IP1000 gigabit Ethernet cards.
+
+         To compile this driver as a module, choose M here: the module
+         will be called ipg.  This is recommended.
diff --git a/drivers/net/ethernet/icplus/Makefile b/drivers/net/ethernet/icplus/Makefile
new file mode 100644 (file)
index 0000000..5bc87c1
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the IC Plus device drivers
+#
+
+obj-$(CONFIG_IP1000) += ipg.o
similarity index 92%
rename from drivers/net/ipg.c
rename to drivers/net/ethernet/icplus/ipg.c
index d4aa40a..8fd80a0 100644 (file)
@@ -20,6 +20,9 @@
  *   http://www.icplus.com.tw
  *   jesse@icplus.com.tw
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/crc32.h>
 #include <linux/ethtool.h>
 #include <linux/interrupt.h>
@@ -67,7 +70,7 @@ MODULE_LICENSE("GPL");
  * Variable record -- index by leading revision/length
  * Revision/Length(=N*4), Address1, Data1, Address2, Data2,...,AddressN,DataN
  */
-static unsigned short DefaultPhyParam[] = {
+static const unsigned short DefaultPhyParam[] = {
        /* 11/12/03 IP1000A v1-3 rev=0x40 */
        /*--------------------------------------------------------------------------
        (0x4000|(15*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 22, 0x85bd, 24, 0xfff2,
@@ -85,7 +88,7 @@ static unsigned short DefaultPhyParam[] = {
        0x0000
 };
 
-static const char *ipg_brand_name[] = {
+static const char * const ipg_brand_name[] = {
        "IC PLUS IP1000 1000/100/10 based NIC",
        "Sundance Technology ST2021 based NIC",
        "Tamarack Microelectronics TC9020/9021 based NIC",
@@ -118,23 +121,23 @@ static void ipg_dump_rfdlist(struct net_device *dev)
 
        IPG_DEBUG_MSG("_dump_rfdlist\n");
 
-       printk(KERN_INFO "rx_current = %2.2x\n", sp->rx_current);
-       printk(KERN_INFO "rx_dirty   = %2.2x\n", sp->rx_dirty);
-       printk(KERN_INFO "RFDList start address = %16.16lx\n",
-              (unsigned long) sp->rxd_map);
-       printk(KERN_INFO "RFDListPtr register   = %8.8x%8.8x\n",
-              ipg_r32(IPG_RFDLISTPTR1), ipg_r32(IPG_RFDLISTPTR0));
+       netdev_info(dev, "rx_current = %02x\n", sp->rx_current);
+       netdev_info(dev, "rx_dirty   = %02x\n", sp->rx_dirty);
+       netdev_info(dev, "RFDList start address = %016lx\n",
+                   (unsigned long)sp->rxd_map);
+       netdev_info(dev, "RFDListPtr register   = %08x%08x\n",
+                   ipg_r32(IPG_RFDLISTPTR1), ipg_r32(IPG_RFDLISTPTR0));
 
        for (i = 0; i < IPG_RFDLIST_LENGTH; i++) {
                offset = (u32) &sp->rxd[i].next_desc - (u32) sp->rxd;
-               printk(KERN_INFO "%2.2x %4.4x RFDNextPtr = %16.16lx\n", i,
-                      offset, (unsigned long) sp->rxd[i].next_desc);
+               netdev_info(dev, "%02x %04x RFDNextPtr = %016lx\n",
+                           i, offset, (unsigned long)sp->rxd[i].next_desc);
                offset = (u32) &sp->rxd[i].rfs - (u32) sp->rxd;
-               printk(KERN_INFO "%2.2x %4.4x RFS        = %16.16lx\n", i,
-                      offset, (unsigned long) sp->rxd[i].rfs);
+               netdev_info(dev, "%02x %04x RFS        = %016lx\n",
+                           i, offset, (unsigned long)sp->rxd[i].rfs);
                offset = (u32) &sp->rxd[i].frag_info - (u32) sp->rxd;
-               printk(KERN_INFO "%2.2x %4.4x frag_info   = %16.16lx\n", i,
-                      offset, (unsigned long) sp->rxd[i].frag_info);
+               netdev_info(dev, "%02x %04x frag_info   = %016lx\n",
+                           i, offset, (unsigned long)sp->rxd[i].frag_info);
        }
 }
 
@@ -147,24 +150,24 @@ static void ipg_dump_tfdlist(struct net_device *dev)
 
        IPG_DEBUG_MSG("_dump_tfdlist\n");
 
-       printk(KERN_INFO "tx_current         = %2.2x\n", sp->tx_current);
-       printk(KERN_INFO "tx_dirty = %2.2x\n", sp->tx_dirty);
-       printk(KERN_INFO "TFDList start address = %16.16lx\n",
-              (unsigned long) sp->txd_map);
-       printk(KERN_INFO "TFDListPtr register   = %8.8x%8.8x\n",
-              ipg_r32(IPG_TFDLISTPTR1), ipg_r32(IPG_TFDLISTPTR0));
+       netdev_info(dev, "tx_current         = %02x\n", sp->tx_current);
+       netdev_info(dev, "tx_dirty = %02x\n", sp->tx_dirty);
+       netdev_info(dev, "TFDList start address = %016lx\n",
+                   (unsigned long) sp->txd_map);
+       netdev_info(dev, "TFDListPtr register   = %08x%08x\n",
+                   ipg_r32(IPG_TFDLISTPTR1), ipg_r32(IPG_TFDLISTPTR0));
 
        for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
                offset = (u32) &sp->txd[i].next_desc - (u32) sp->txd;
-               printk(KERN_INFO "%2.2x %4.4x TFDNextPtr = %16.16lx\n", i,
-                      offset, (unsigned long) sp->txd[i].next_desc);
+               netdev_info(dev, "%02x %04x TFDNextPtr = %016lx\n",
+                           i, offset, (unsigned long)sp->txd[i].next_desc);
 
                offset = (u32) &sp->txd[i].tfc - (u32) sp->txd;
-               printk(KERN_INFO "%2.2x %4.4x TFC        = %16.16lx\n", i,
-                      offset, (unsigned long) sp->txd[i].tfc);
+               netdev_info(dev, "%02x %04x TFC        = %016lx\n",
+                           i, offset, (unsigned long) sp->txd[i].tfc);
                offset = (u32) &sp->txd[i].frag_info - (u32) sp->txd;
-               printk(KERN_INFO "%2.2x %4.4x frag_info   = %16.16lx\n", i,
-                      offset, (unsigned long) sp->txd[i].frag_info);
+               netdev_info(dev, "%02x %04x frag_info   = %016lx\n",
+                           i, offset, (unsigned long) sp->txd[i].frag_info);
        }
 }
 #endif
@@ -480,6 +483,10 @@ static int ipg_config_autoneg(struct net_device *dev)
        u32 mac_ctrl_val;
        u32 asicctrl;
        u8 phyctrl;
+       const char *speed;
+       const char *duplex;
+       const char *tx_desc;
+       const char *rx_desc;
 
        IPG_DEBUG_MSG("_config_autoneg\n");
 
@@ -499,27 +506,27 @@ static int ipg_config_autoneg(struct net_device *dev)
         */
        sp->tenmbpsmode = 0;
 
-       printk(KERN_INFO "%s: Link speed = ", dev->name);
-
        /* Determine actual speed of operation. */
        switch (phyctrl & IPG_PC_LINK_SPEED) {
        case IPG_PC_LINK_SPEED_10MBPS:
-               printk("10Mbps.\n");
-               printk(KERN_INFO "%s: 10Mbps operational mode enabled.\n",
-                      dev->name);
+               speed = "10Mbps";
                sp->tenmbpsmode = 1;
                break;
        case IPG_PC_LINK_SPEED_100MBPS:
-               printk("100Mbps.\n");
+               speed = "100Mbps";
                break;
        case IPG_PC_LINK_SPEED_1000MBPS:
-               printk("1000Mbps.\n");
+               speed = "1000Mbps";
                break;
        default:
-               printk("undefined!\n");
+               speed = "undefined!";
                return 0;
        }
 
+       netdev_info(dev, "Link speed = %s\n", speed);
+       if (sp->tenmbpsmode == 1)
+               netdev_info(dev, "10Mbps operational mode enabled\n");
+
        if (phyctrl & IPG_PC_DUPLEX_STATUS) {
                fullduplex = 1;
                txflowcontrol = 1;
@@ -528,38 +535,41 @@ static int ipg_config_autoneg(struct net_device *dev)
 
        /* Configure full duplex, and flow control. */
        if (fullduplex == 1) {
+
                /* Configure IPG for full duplex operation. */
-               printk(KERN_INFO "%s: setting full duplex, ", dev->name);
+
+               duplex = "full";
 
                mac_ctrl_val |= IPG_MC_DUPLEX_SELECT_FD;
 
                if (txflowcontrol == 1) {
-                       printk("TX flow control");
+                       tx_desc  = "";
                        mac_ctrl_val |= IPG_MC_TX_FLOW_CONTROL_ENABLE;
                } else {
-                       printk("no TX flow control");
+                       tx_desc = "no ";
                        mac_ctrl_val &= ~IPG_MC_TX_FLOW_CONTROL_ENABLE;
                }
 
                if (rxflowcontrol == 1) {
-                       printk(", RX flow control.");
+                       rx_desc = "";
                        mac_ctrl_val |= IPG_MC_RX_FLOW_CONTROL_ENABLE;
                } else {
-                       printk(", no RX flow control.");
+                       rx_desc = "no ";
                        mac_ctrl_val &= ~IPG_MC_RX_FLOW_CONTROL_ENABLE;
                }
-
-               printk("\n");
        } else {
-               /* Configure IPG for half duplex operation. */
-               printk(KERN_INFO "%s: setting half duplex, "
-                      "no TX flow control, no RX flow control.\n", dev->name);
-
-               mac_ctrl_val &= ~IPG_MC_DUPLEX_SELECT_FD &
-                       ~IPG_MC_TX_FLOW_CONTROL_ENABLE &
-                       ~IPG_MC_RX_FLOW_CONTROL_ENABLE;
+               duplex = "half";
+               tx_desc = "no ";
+               rx_desc = "no ";
+               mac_ctrl_val &= (~IPG_MC_DUPLEX_SELECT_FD &
+                                ~IPG_MC_TX_FLOW_CONTROL_ENABLE &
+                                ~IPG_MC_RX_FLOW_CONTROL_ENABLE);
        }
+
+       netdev_info(dev, "setting %s duplex, %sTX, %sRX flow control\n",
+                   duplex, tx_desc, rx_desc);
        ipg_w32(mac_ctrl_val, MAC_CTRL);
+
        return 0;
 }
 
@@ -784,14 +794,13 @@ static int init_rfdlist(struct net_device *dev)
                         * A receive buffer was not ready, break the
                         * RFD list here.
                         */
-                       IPG_DEBUG_MSG("Cannot allocate Rx buffer.\n");
+                       IPG_DEBUG_MSG("Cannot allocate Rx buffer\n");
 
                        /* Just in case we cannot allocate a single RFD.
                         * Should not occur.
                         */
                        if (i == 0) {
-                               printk(KERN_ERR "%s: No memory available"
-                                       " for RFD list.\n", dev->name);
+                               netdev_err(dev, "No memory available for RFD list\n");
                                return -ENOMEM;
                        }
                }
@@ -838,7 +847,7 @@ static void init_tfdlist(struct net_device *dev)
        sp->tx_dirty = 0;
 
        /* Write the location of the TFDList to the IPG. */
-       IPG_DDEBUG_MSG("Starting TFDListPtr = %8.8x\n",
+       IPG_DDEBUG_MSG("Starting TFDListPtr = %08x\n",
                       (u32) sp->txd_map);
        ipg_w32((u32) sp->txd_map, TFD_LIST_PTR_0);
        ipg_w32(0x00000000, TFD_LIST_PTR_1);
@@ -864,7 +873,7 @@ static void ipg_nic_txfree(struct net_device *dev)
                struct sk_buff *skb = sp->tx_buff[dirty];
                struct ipg_tx *txfd = sp->txd + dirty;
 
-               IPG_DEBUG_MSG("TFC = %16.16lx\n", (unsigned long) txfd->tfc);
+               IPG_DEBUG_MSG("TFC = %016lx\n", (unsigned long) txfd->tfc);
 
                /* Look at each TFD's TFC field beginning
                 * at the last freed TFD up to the current TFD.
@@ -906,10 +915,8 @@ static void ipg_tx_timeout(struct net_device *dev)
        spin_lock_irq(&sp->lock);
 
        /* Re-configure after DMA reset. */
-       if (ipg_io_config(dev) < 0) {
-               printk(KERN_INFO "%s: Error during re-configuration.\n",
-                      dev->name);
-       }
+       if (ipg_io_config(dev) < 0)
+               netdev_info(dev, "Error during re-configuration\n");
 
        init_tfdlist(dev);
 
@@ -938,7 +945,7 @@ static void ipg_nic_txcleanup(struct net_device *dev)
                 */
                u32 txstatusdword = ipg_r32(TX_STATUS);
 
-               IPG_DEBUG_MSG("TxStatus = %8.8x\n", txstatusdword);
+               IPG_DEBUG_MSG("TxStatus = %08x\n", txstatusdword);
 
                /* Check for Transmit errors. Error bits only valid if
                 * TX_COMPLETE bit in the TXSTATUS register is a 1.
@@ -953,20 +960,20 @@ static void ipg_nic_txcleanup(struct net_device *dev)
 
                /* Transmit error, increment stat counters. */
                if (txstatusdword & IPG_TS_TX_ERROR) {
-                       IPG_DEBUG_MSG("Transmit error.\n");
+                       IPG_DEBUG_MSG("Transmit error\n");
                        sp->stats.tx_errors++;
                }
 
                /* Late collision, re-enable transmitter. */
                if (txstatusdword & IPG_TS_LATE_COLLISION) {
-                       IPG_DEBUG_MSG("Late collision on transmit.\n");
+                       IPG_DEBUG_MSG("Late collision on transmit\n");
                        ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) &
                                IPG_MC_RSVD_MASK, MAC_CTRL);
                }
 
                /* Maximum collisions, re-enable transmitter. */
                if (txstatusdword & IPG_TS_TX_MAX_COLL) {
-                       IPG_DEBUG_MSG("Maximum collisions on transmit.\n");
+                       IPG_DEBUG_MSG("Maximum collisions on transmit\n");
                        ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) &
                                IPG_MC_RSVD_MASK, MAC_CTRL);
                }
@@ -975,16 +982,14 @@ static void ipg_nic_txcleanup(struct net_device *dev)
                 * transmitter.
                 */
                if (txstatusdword & IPG_TS_TX_UNDERRUN) {
-                       IPG_DEBUG_MSG("Transmitter underrun.\n");
+                       IPG_DEBUG_MSG("Transmitter underrun\n");
                        sp->stats.tx_fifo_errors++;
                        ipg_reset(dev, IPG_AC_TX_RESET | IPG_AC_DMA |
                                  IPG_AC_NETWORK | IPG_AC_FIFO);
 
                        /* Re-configure after DMA reset. */
                        if (ipg_io_config(dev) < 0) {
-                               printk(KERN_INFO
-                                      "%s: Error during re-configuration.\n",
-                                      dev->name);
+                               netdev_info(dev, "Error during re-configuration\n");
                        }
                        init_tfdlist(dev);
 
@@ -1063,7 +1068,7 @@ static int ipg_nic_rxrestore(struct net_device *dev)
                 * Linux system).
                 */
                if (ipg_get_rxbuff(dev, entry) < 0) {
-                       IPG_DEBUG_MSG("Cannot allocate new Rx buffer.\n");
+                       IPG_DEBUG_MSG("Cannot allocate new Rx buffer\n");
 
                        break;
                }
@@ -1134,7 +1139,7 @@ static int ipg_nic_rx_check_error(struct net_device *dev)
             (IPG_RFS_RXFIFOOVERRUN | IPG_RFS_RXRUNTFRAME |
              IPG_RFS_RXALIGNMENTERROR | IPG_RFS_RXFCSERROR |
              IPG_RFS_RXOVERSIZEDFRAME | IPG_RFS_RXLENGTHERROR))) {
-               IPG_DEBUG_MSG("Rx error, RFS = %16.16lx\n",
+               IPG_DEBUG_MSG("Rx error, RFS = %016lx\n",
                              (unsigned long) rxfd->rfs);
 
                /* Increment general receive error statistic. */
@@ -1142,13 +1147,13 @@ static int ipg_nic_rx_check_error(struct net_device *dev)
 
                /* Increment detailed receive error statistics. */
                if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) {
-                       IPG_DEBUG_MSG("RX FIFO overrun occurred.\n");
+                       IPG_DEBUG_MSG("RX FIFO overrun occurred\n");
 
                        sp->stats.rx_fifo_errors++;
                }
 
                if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) {
-                       IPG_DEBUG_MSG("RX runt occurred.\n");
+                       IPG_DEBUG_MSG("RX runt occurred\n");
                        sp->stats.rx_length_errors++;
                }
 
@@ -1157,7 +1162,7 @@ static int ipg_nic_rx_check_error(struct net_device *dev)
                 */
 
                if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) {
-                       IPG_DEBUG_MSG("RX alignment error occurred.\n");
+                       IPG_DEBUG_MSG("RX alignment error occurred\n");
                        sp->stats.rx_frame_errors++;
                }
 
@@ -1404,7 +1409,7 @@ static int ipg_nic_rx(struct net_device *dev)
                 */
                if (framelen > sp->rxfrag_size) {
                        IPG_DEBUG_MSG
-                           ("RFS FrameLen > allocated fragment size.\n");
+                           ("RFS FrameLen > allocated fragment size\n");
 
                        framelen = sp->rxfrag_size;
                }
@@ -1414,7 +1419,7 @@ static int ipg_nic_rx(struct net_device *dev)
                        IPG_RFS_RXALIGNMENTERROR | IPG_RFS_RXFCSERROR |
                        IPG_RFS_RXOVERSIZEDFRAME | IPG_RFS_RXLENGTHERROR)))) {
 
-                       IPG_DEBUG_MSG("Rx error, RFS = %16.16lx\n",
+                       IPG_DEBUG_MSG("Rx error, RFS = %016lx\n",
                                      (unsigned long int) rxfd->rfs);
 
                        /* Increment general receive error statistic. */
@@ -1422,12 +1427,12 @@ static int ipg_nic_rx(struct net_device *dev)
 
                        /* Increment detailed receive error statistics. */
                        if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) {
-                               IPG_DEBUG_MSG("RX FIFO overrun occurred.\n");
+                               IPG_DEBUG_MSG("RX FIFO overrun occurred\n");
                                sp->stats.rx_fifo_errors++;
                        }
 
                        if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) {
-                               IPG_DEBUG_MSG("RX runt occurred.\n");
+                               IPG_DEBUG_MSG("RX runt occurred\n");
                                sp->stats.rx_length_errors++;
                        }
 
@@ -1437,7 +1442,7 @@ static int ipg_nic_rx(struct net_device *dev)
                         */
 
                        if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) {
-                               IPG_DEBUG_MSG("RX alignment error occurred.\n");
+                               IPG_DEBUG_MSG("RX alignment error occurred\n");
                                sp->stats.rx_frame_errors++;
                        }
 
@@ -1508,7 +1513,7 @@ static int ipg_nic_rx(struct net_device *dev)
 
                rxfd = sp->rxd + entry;
 
-               IPG_DEBUG_MSG("Frame requires multiple RFDs.\n");
+               IPG_DEBUG_MSG("Frame requires multiple RFDs\n");
 
                /* An unexpected event, additional code needed to handle
                 * properly. So for the time being, just disregard the
@@ -1557,8 +1562,7 @@ static void ipg_reset_after_host_error(struct work_struct *work)
        init_tfdlist(dev);
 
        if (ipg_io_config(dev) < 0) {
-               printk(KERN_INFO "%s: Cannot recover from PCI error.\n",
-                      dev->name);
+               netdev_info(dev, "Cannot recover from PCI error\n");
                schedule_delayed_work(&sp->task, HZ);
        }
 }
@@ -1586,7 +1590,7 @@ static irqreturn_t ipg_interrupt_handler(int irq, void *dev_inst)
         */
        status = ipg_r16(INT_STATUS_ACK);
 
-       IPG_DEBUG_MSG("IntStatusAck = %4.4x\n", status);
+       IPG_DEBUG_MSG("IntStatusAck = %04x\n", status);
 
        /* Shared IRQ of remove event. */
        if (!(status & IPG_IS_RSVD_MASK))
@@ -1599,7 +1603,7 @@ static irqreturn_t ipg_interrupt_handler(int irq, void *dev_inst)
 
        /* If RFDListEnd interrupt, restore all used RFDs. */
        if (status & IPG_IS_RFD_LIST_END) {
-               IPG_DEBUG_MSG("RFDListEnd Interrupt.\n");
+               IPG_DEBUG_MSG("RFDListEnd Interrupt\n");
 
                /* The RFD list end indicates an RFD was encountered
                 * with a 0 NextPtr, or with an RFDDone bit set to 1
@@ -1661,21 +1665,20 @@ static irqreturn_t ipg_interrupt_handler(int irq, void *dev_inst)
        /* If LinkEvent interrupt, resolve autonegotiation. */
        if (status & IPG_IS_LINK_EVENT) {
                if (ipg_config_autoneg(dev) < 0)
-                       printk(KERN_INFO "%s: Auto-negotiation error.\n",
-                              dev->name);
+                       netdev_info(dev, "Auto-negotiation error\n");
        }
 
        /* If MACCtrlFrame interrupt, do nothing. */
        if (status & IPG_IS_MAC_CTRL_FRAME)
-               IPG_DEBUG_MSG("MACCtrlFrame interrupt.\n");
+               IPG_DEBUG_MSG("MACCtrlFrame interrupt\n");
 
        /* If RxComplete interrupt, do nothing. */
        if (status & IPG_IS_RX_COMPLETE)
-               IPG_DEBUG_MSG("RxComplete interrupt.\n");
+               IPG_DEBUG_MSG("RxComplete interrupt\n");
 
        /* If RxEarly interrupt, do nothing. */
        if (status & IPG_IS_RX_EARLY)
-               IPG_DEBUG_MSG("RxEarly interrupt.\n");
+               IPG_DEBUG_MSG("RxEarly interrupt\n");
 
 out_enable:
        /* Re-enable IPG interrupts. */
@@ -1749,8 +1752,7 @@ static int ipg_nic_open(struct net_device *dev)
        rc = request_irq(pdev->irq, ipg_interrupt_handler, IRQF_SHARED,
                         dev->name, dev);
        if (rc < 0) {
-               printk(KERN_INFO "%s: Error when requesting interrupt.\n",
-                      dev->name);
+               netdev_info(dev, "Error when requesting interrupt\n");
                goto out;
        }
 
@@ -1770,8 +1772,7 @@ static int ipg_nic_open(struct net_device *dev)
 
        rc = init_rfdlist(dev);
        if (rc < 0) {
-               printk(KERN_INFO "%s: Error during configuration.\n",
-                      dev->name);
+               netdev_info(dev, "Error during configuration\n");
                goto err_free_tx_2;
        }
 
@@ -1779,14 +1780,13 @@ static int ipg_nic_open(struct net_device *dev)
 
        rc = ipg_io_config(dev);
        if (rc < 0) {
-               printk(KERN_INFO "%s: Error during configuration.\n",
-                      dev->name);
+               netdev_info(dev, "Error during configuration\n");
                goto err_release_tfdlist_3;
        }
 
        /* Resolve autonegotiation. */
        if (ipg_config_autoneg(dev) < 0)
-               printk(KERN_INFO "%s: Auto-negotiation error.\n", dev->name);
+               netdev_info(dev, "Auto-negotiation error\n");
 
        /* initialize JUMBO Frame control variable */
        sp->jumbo.found_start = 0;
@@ -1961,7 +1961,7 @@ static void ipg_set_phy_default_param(unsigned char rev,
 {
        unsigned short length;
        unsigned char revision;
-       unsigned short *phy_param;
+       const unsigned short *phy_param;
        unsigned short address, value;
 
        phy_param = &DefaultPhyParam[0];
@@ -2201,7 +2201,7 @@ static const struct net_device_ops ipg_netdev_ops = {
        .ndo_stop               = ipg_nic_stop,
        .ndo_start_xmit         = ipg_nic_hard_start_xmit,
        .ndo_get_stats          = ipg_nic_get_stats,
-       .ndo_set_multicast_list = ipg_nic_set_multicast_list,
+       .ndo_set_rx_mode        = ipg_nic_set_multicast_list,
        .ndo_do_ioctl           = ipg_ioctl,
        .ndo_tx_timeout         = ipg_tx_timeout,
        .ndo_change_mtu         = ipg_nic_change_mtu,
@@ -2222,7 +2222,7 @@ static int __devinit ipg_probe(struct pci_dev *pdev,
        if (rc < 0)
                goto out;
 
-       printk(KERN_INFO "%s: %s\n", pci_name(pdev), ipg_brand_name[i]);
+       pr_info("%s: %s\n", pci_name(pdev), ipg_brand_name[i]);
 
        pci_set_master(pdev);
 
@@ -2230,8 +2230,7 @@ static int __devinit ipg_probe(struct pci_dev *pdev,
        if (rc < 0) {
                rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
                if (rc < 0) {
-                       printk(KERN_ERR "%s: DMA config failed.\n",
-                              pci_name(pdev));
+                       pr_err("%s: DMA config failed\n", pci_name(pdev));
                        goto err_disable_0;
                }
        }
@@ -2241,7 +2240,7 @@ static int __devinit ipg_probe(struct pci_dev *pdev,
         */
        dev = alloc_etherdev(sizeof(struct ipg_nic_private));
        if (!dev) {
-               printk(KERN_ERR "%s: alloc_etherdev failed\n", pci_name(pdev));
+               pr_err("%s: alloc_etherdev failed\n", pci_name(pdev));
                rc = -ENOMEM;
                goto err_disable_0;
        }
@@ -2267,7 +2266,7 @@ static int __devinit ipg_probe(struct pci_dev *pdev,
 
        ioaddr = pci_iomap(pdev, 1, pci_resource_len(pdev, 1));
        if (!ioaddr) {
-               printk(KERN_ERR "%s cannot map MMIO\n", pci_name(pdev));
+               pr_err("%s: cannot map MMIO\n", pci_name(pdev));
                rc = -EIO;
                goto err_release_regions_2;
        }
@@ -2289,7 +2288,7 @@ static int __devinit ipg_probe(struct pci_dev *pdev,
        if (rc < 0)
                goto err_unmap_3;
 
-       printk(KERN_INFO "Ethernet device registered as: %s\n", dev->name);
+       netdev_info(dev, "Ethernet device registered\n");
 out:
        return rc;
 
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
new file mode 100644 (file)
index 0000000..4a98e83
--- /dev/null
@@ -0,0 +1,221 @@
+#
+# Intel network device configuration
+#
+
+config NET_VENDOR_INTEL
+       bool "Intel devices"
+       default y
+       depends on PCI || PCI_MSI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Intel cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_INTEL
+
+config E100
+       tristate "Intel(R) PRO/100+ support"
+       depends on PCI
+       select MII
+       ---help---
+         This driver supports Intel(R) PRO/100 family of adapters.
+         To verify that your adapter is supported, find the board ID number
+         on the adapter. Look for a label that has a barcode and a number
+         in the format 123456-001 (six digits hyphen three digits).
+
+         Use the above information and the Adapter & Driver ID Guide at:
+
+         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+         to identify the adapter.
+
+         For the latest Intel PRO/100 network driver for Linux, see:
+
+         <http://www.intel.com/p/en_US/support/highlights/network/pro100plus>
+
+         More specific information on configuring the driver is in
+         <file:Documentation/networking/e100.txt>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called e100.
+
+config E1000
+       tristate "Intel(R) PRO/1000 Gigabit Ethernet support"
+       depends on PCI
+       ---help---
+         This driver supports Intel(R) PRO/1000 gigabit ethernet family of
+         adapters.  For more information on how to identify your adapter, go
+         to the Adapter & Driver ID Guide at:
+
+         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+         For general information and support, go to the Intel support
+         website at:
+
+         <http://support.intel.com>
+
+         More specific information on configuring the driver is in
+         <file:Documentation/networking/e1000.txt>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called e1000.
+
+config E1000E
+       tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
+       depends on PCI && (!SPARC32 || BROKEN)
+       select CRC32
+       ---help---
+         This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
+         ethernet family of adapters. For PCI or PCI-X e1000 adapters,
+         use the regular e1000 driver For more information on how to
+         identify your adapter, go to the Adapter & Driver ID Guide at:
+
+         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+         For general information and support, go to the Intel support
+         website at:
+
+         <http://support.intel.com>
+
+         To compile this driver as a module, choose M here. The module
+         will be called e1000e.
+
+config IGB
+       tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
+       depends on PCI
+       ---help---
+         This driver supports Intel(R) 82575/82576 gigabit ethernet family of
+         adapters.  For more information on how to identify your adapter, go
+         to the Adapter & Driver ID Guide at:
+
+         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+         For general information and support, go to the Intel support
+         website at:
+
+         <http://support.intel.com>
+
+         More specific information on configuring the driver is in
+         <file:Documentation/networking/e1000.txt>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called igb.
+
+config IGB_DCA
+       bool "Direct Cache Access (DCA) Support"
+       default y
+       depends on IGB && DCA && !(IGB=y && DCA=m)
+       ---help---
+         Say Y here if you want to use Direct Cache Access (DCA) in the
+         driver.  DCA is a method for warming the CPU cache before data
+         is used, with the intent of lessening the impact of cache misses.
+
+config IGBVF
+       tristate "Intel(R) 82576 Virtual Function Ethernet support"
+       depends on PCI
+       ---help---
+         This driver supports Intel(R) 82576 virtual functions.  For more
+         information on how to identify your adapter, go to the Adapter &
+         Driver ID Guide at:
+
+         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+         For general information and support, go to the Intel support
+         website at:
+
+         <http://support.intel.com>
+
+         More specific information on configuring the driver is in
+         <file:Documentation/networking/e1000.txt>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called igbvf.
+
+config IXGB
+       tristate "Intel(R) PRO/10GbE support"
+       depends on PCI
+       ---help---
+         This driver supports Intel(R) PRO/10GbE family of adapters for
+         PCI-X type cards. For PCI-E type cards, use the "ixgbe" driver
+         instead. For more information on how to identify your adapter, go
+         to the Adapter & Driver ID Guide at:
+
+         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+         For general information and support, go to the Intel support
+         website at:
+
+         <http://support.intel.com>
+
+         More specific information on configuring the driver is in
+         <file:Documentation/networking/ixgb.txt>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ixgb.
+
+config IXGBE
+       tristate "Intel(R) 10GbE PCI Express adapters support"
+       depends on PCI && INET
+       select MDIO
+       ---help---
+         This driver supports Intel(R) 10GbE PCI Express family of
+         adapters.  For more information on how to identify your adapter, go
+         to the Adapter & Driver ID Guide at:
+
+         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+         For general information and support, go to the Intel support
+         website at:
+
+         <http://support.intel.com>
+
+         To compile this driver as a module, choose M here. The module
+         will be called ixgbe.
+
+config IXGBE_DCA
+       bool "Direct Cache Access (DCA) Support"
+       default y
+       depends on IXGBE && DCA && !(IXGBE=y && DCA=m)
+       ---help---
+         Say Y here if you want to use Direct Cache Access (DCA) in the
+         driver.  DCA is a method for warming the CPU cache before data
+         is used, with the intent of lessening the impact of cache misses.
+
+config IXGBE_DCB
+       bool "Data Center Bridging (DCB) Support"
+       default n
+       depends on IXGBE && DCB
+       ---help---
+         Say Y here if you want to use Data Center Bridging (DCB) in the
+         driver.
+
+         If unsure, say N.
+
+config IXGBEVF
+       tristate "Intel(R) 82599 Virtual Function Ethernet support"
+       depends on PCI_MSI
+       ---help---
+         This driver supports Intel(R) 82599 virtual functions.  For more
+         information on how to identify your adapter, go to the Adapter &
+         Driver ID Guide at:
+
+         <http://support.intel.com/support/network/sb/CS-008441.htm>
+
+         For general information and support, go to the Intel support
+         website at:
+
+         <http://support.intel.com>
+
+         More specific information on configuring the driver is in
+         <file:Documentation/networking/ixgbevf.txt>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ixgbevf.  MSI-X interrupt support is required
+         for this driver to work correctly.
+
+endif # NET_VENDOR_INTEL
diff --git a/drivers/net/ethernet/intel/Makefile b/drivers/net/ethernet/intel/Makefile
new file mode 100644 (file)
index 0000000..c8210e6
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Makefile for the Intel network device drivers.
+#
+
+obj-$(CONFIG_E100) += e100.o
+obj-$(CONFIG_E1000) += e1000/
+obj-$(CONFIG_E1000E) += e1000e/
+obj-$(CONFIG_IGB) += igb/
+obj-$(CONFIG_IGBVF) += igbvf/
+obj-$(CONFIG_IXGBE) += ixgbe/
+obj-$(CONFIG_IXGBEVF) += ixgbevf/
+obj-$(CONFIG_IXGB) += ixgb/
similarity index 99%
rename from drivers/net/e100.c
rename to drivers/net/ethernet/intel/e100.c
index c1352c6..fe87d3e 100644 (file)
@@ -2738,7 +2738,7 @@ static const struct net_device_ops e100_netdev_ops = {
        .ndo_stop               = e100_close,
        .ndo_start_xmit         = e100_xmit_frame,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = e100_set_multicast_list,
+       .ndo_set_rx_mode        = e100_set_multicast_list,
        .ndo_set_mac_address    = e100_set_mac_address,
        .ndo_change_mtu         = e100_change_mtu,
        .ndo_do_ioctl           = e100_do_ioctl,
similarity index 99%
rename from drivers/net/e1000/e1000.h
rename to drivers/net/ethernet/intel/e1000/e1000.h
index 24f41da..4ea87b1 100644 (file)
@@ -150,6 +150,8 @@ struct e1000_buffer {
        unsigned long time_stamp;
        u16 length;
        u16 next_to_watch;
+       unsigned int segs;
+       unsigned int bytecount;
        u16 mapped_as_page;
 };
 
similarity index 99%
rename from drivers/net/e1000/e1000_ethtool.c
rename to drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index c5f0f04..5548d46 100644 (file)
@@ -838,6 +838,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
 
        /* Disable all the interrupts */
        ew32(IMC, 0xFFFFFFFF);
+       E1000_WRITE_FLUSH();
        msleep(10);
 
        /* Test each interrupt */
@@ -856,6 +857,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
                        adapter->test_icr = 0;
                        ew32(IMC, mask);
                        ew32(ICS, mask);
+                       E1000_WRITE_FLUSH();
                        msleep(10);
 
                        if (adapter->test_icr & mask) {
@@ -873,6 +875,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
                adapter->test_icr = 0;
                ew32(IMS, mask);
                ew32(ICS, mask);
+               E1000_WRITE_FLUSH();
                msleep(10);
 
                if (!(adapter->test_icr & mask)) {
@@ -890,6 +893,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
                        adapter->test_icr = 0;
                        ew32(IMC, ~mask & 0x00007FFF);
                        ew32(ICS, ~mask & 0x00007FFF);
+                       E1000_WRITE_FLUSH();
                        msleep(10);
 
                        if (adapter->test_icr) {
@@ -901,6 +905,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
 
        /* Disable all the interrupts */
        ew32(IMC, 0xFFFFFFFF);
+       E1000_WRITE_FLUSH();
        msleep(10);
 
        /* Unhook test interrupt handler */
@@ -1394,6 +1399,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
                        if (unlikely(++k == txdr->count)) k = 0;
                }
                ew32(TDT, k);
+               E1000_WRITE_FLUSH();
                msleep(200);
                time = jiffies; /* set the start time for the receive */
                good_cnt = 0;
similarity index 99%
rename from drivers/net/e1000/e1000_hw.c
rename to drivers/net/ethernet/intel/e1000/e1000_hw.c
index 1698622..8545c7a 100644 (file)
@@ -446,6 +446,7 @@ s32 e1000_reset_hw(struct e1000_hw *hw)
        /* Must reset the PHY before resetting the MAC */
        if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
                ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST));
+               E1000_WRITE_FLUSH();
                msleep(5);
        }
 
@@ -3752,6 +3753,7 @@ static s32 e1000_acquire_eeprom(struct e1000_hw *hw)
                /* Clear SK and CS */
                eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
                ew32(EECD, eecd);
+               E1000_WRITE_FLUSH();
                udelay(1);
        }
 
@@ -3824,6 +3826,7 @@ static void e1000_release_eeprom(struct e1000_hw *hw)
                eecd &= ~E1000_EECD_SK; /* Lower SCK */
 
                ew32(EECD, eecd);
+               E1000_WRITE_FLUSH();
 
                udelay(hw->eeprom.delay_usec);
        } else if (hw->eeprom.type == e1000_eeprom_microwire) {
similarity index 99%
rename from drivers/net/e1000/e1000_main.c
rename to drivers/net/ethernet/intel/e1000/e1000_main.c
index f97afda..4a32c15 100644 (file)
@@ -1080,6 +1080,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        netdev->vlan_features |= NETIF_F_HW_CSUM;
        netdev->vlan_features |= NETIF_F_SG;
 
+       netdev->priv_flags |= IFF_UNICAST_FLT;
+
        adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
 
        /* initialize eeprom parameters */
@@ -2846,7 +2848,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
        struct e1000_buffer *buffer_info;
        unsigned int len = skb_headlen(skb);
        unsigned int offset = 0, size, count = 0, i;
-       unsigned int f;
+       unsigned int f, bytecount, segs;
 
        i = tx_ring->next_to_use;
 
@@ -2947,7 +2949,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
                }
        }
 
+       segs = skb_shinfo(skb)->gso_segs ?: 1;
+       /* multiply data chunks by size of headers */
+       bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len;
+
        tx_ring->buffer_info[i].skb = skb;
+       tx_ring->buffer_info[i].segs = segs;
+       tx_ring->buffer_info[i].bytecount = bytecount;
        tx_ring->buffer_info[first].next_to_watch = i;
 
        return count;
@@ -3621,14 +3629,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
                        cleaned = (i == eop);
 
                        if (cleaned) {
-                               struct sk_buff *skb = buffer_info->skb;
-                               unsigned int segs, bytecount;
-                               segs = skb_shinfo(skb)->gso_segs ?: 1;
-                               /* multiply data chunks by size of headers */
-                               bytecount = ((segs - 1) * skb_headlen(skb)) +
-                                           skb->len;
-                               total_tx_packets += segs;
-                               total_tx_bytes += bytecount;
+                               total_tx_packets += buffer_info->segs;
+                               total_tx_bytes += buffer_info->bytecount;
                        }
                        e1000_unmap_and_free_tx_resource(adapter, buffer_info);
                        tx_desc->upper.data = 0;
similarity index 99%
rename from drivers/net/e1000e/es2lan.c
rename to drivers/net/ethernet/intel/e1000e/80003es2lan.c
index c0ecb2d..b754433 100644 (file)
@@ -1313,6 +1313,7 @@ static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
        kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
                       E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
        ew32(KMRNCTRLSTA, kmrnctrlsta);
+       e1e_flush();
 
        udelay(2);
 
@@ -1347,6 +1348,7 @@ static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
        kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
                       E1000_KMRNCTRLSTA_OFFSET) | data;
        ew32(KMRNCTRLSTA, kmrnctrlsta);
+       e1e_flush();
 
        udelay(2);
 
@@ -1496,7 +1498,6 @@ struct e1000_info e1000_es2_info = {
                                  | FLAG_HAS_JUMBO_FRAMES
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
-                                 | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
                                  | FLAG_RX_NEEDS_RESTART /* errata */
                                  | FLAG_TARC_SET_BIT_ZERO /* errata */
similarity index 99%
rename from drivers/net/e1000e/82571.c
rename to drivers/net/ethernet/intel/e1000e/82571.c
index 480f259..2d4dc53 100644 (file)
@@ -2019,7 +2019,6 @@ struct e1000_info e1000_82571_info = {
                                  | FLAG_HAS_JUMBO_FRAMES
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
-                                 | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
                                  | FLAG_HAS_SMART_POWER_DOWN
                                  | FLAG_RESET_OVERWRITES_LAA /* errata */
@@ -2041,7 +2040,6 @@ struct e1000_info e1000_82572_info = {
                                  | FLAG_HAS_JUMBO_FRAMES
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
-                                 | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
                                  | FLAG_TARC_SPEED_MODE_BIT, /* errata */
        .flags2                 = FLAG2_DISABLE_ASPM_L1 /* errata 13 */
@@ -2059,7 +2057,6 @@ struct e1000_info e1000_82573_info = {
        .flags                  = FLAG_HAS_HW_VLAN_FILTER
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
-                                 | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_SMART_POWER_DOWN
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_SWSM_ON_LOAD,
@@ -2080,12 +2077,12 @@ struct e1000_info e1000_82574_info = {
                                  | FLAG_HAS_JUMBO_FRAMES
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
-                                 | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_SMART_POWER_DOWN
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_CTRLEXT_ON_LOAD,
        .flags2                   = FLAG2_CHECK_PHY_HANG
-                                 | FLAG2_DISABLE_ASPM_L0S,
+                                 | FLAG2_DISABLE_ASPM_L0S
+                                 | FLAG2_NO_DISABLE_RX,
        .pba                    = 32,
        .max_hw_frame_size      = DEFAULT_JUMBO,
        .get_variants           = e1000_get_variants_82571,
@@ -2099,12 +2096,12 @@ struct e1000_info e1000_82583_info = {
        .flags                  = FLAG_HAS_HW_VLAN_FILTER
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
-                                 | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_SMART_POWER_DOWN
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_JUMBO_FRAMES
                                  | FLAG_HAS_CTRLEXT_ON_LOAD,
-       .flags2                 = FLAG2_DISABLE_ASPM_L0S,
+       .flags2                 = FLAG2_DISABLE_ASPM_L0S
+                                 | FLAG2_NO_DISABLE_RX,
        .pba                    = 32,
        .max_hw_frame_size      = DEFAULT_JUMBO,
        .get_variants           = e1000_get_variants_82571,
similarity index 96%
rename from drivers/net/e1000e/Makefile
rename to drivers/net/ethernet/intel/e1000e/Makefile
index 28519ac..948c05d 100644 (file)
@@ -32,6 +32,6 @@
 
 obj-$(CONFIG_E1000E) += e1000e.o
 
-e1000e-objs := 82571.o ich8lan.o es2lan.o \
+e1000e-objs := 82571.o ich8lan.o 80003es2lan.o \
               lib.o phy.o param.o ethtool.o netdev.o
 
similarity index 98%
rename from drivers/net/e1000e/e1000.h
rename to drivers/net/ethernet/intel/e1000e/e1000.h
index 638d175..1b15d1f 100644 (file)
@@ -155,6 +155,9 @@ struct e1000_info;
 #define HV_M_STATUS_SPEED_1000            0x0200
 #define HV_M_STATUS_LINK_UP               0x0040
 
+#define E1000_ICH_FWSM_PCIM2PCI                0x01000000 /* ME PCIm-to-PCI active */
+#define E1000_ICH_FWSM_PCIM2PCI_COUNT  2000
+
 /* Time to wait before putting the device into D3 if there's no link (in ms). */
 #define LINK_TIMEOUT           100
 
@@ -437,12 +440,11 @@ struct e1000_info {
 #define FLAG_LSC_GIG_SPEED_DROP           (1 << 25)
 #define FLAG_SMART_POWER_DOWN             (1 << 26)
 #define FLAG_MSI_ENABLED                  (1 << 27)
-#define FLAG_RX_CSUM_ENABLED              (1 << 28)
+/* reserved (1 << 28) */
 #define FLAG_TSO_FORCE                    (1 << 29)
 #define FLAG_RX_RESTART_NOW               (1 << 30)
 #define FLAG_MSI_TEST_FAILED              (1 << 31)
 
-/* CRC Stripping defines */
 #define FLAG2_CRC_STRIPPING               (1 << 0)
 #define FLAG2_HAS_PHY_WAKEUP              (1 << 1)
 #define FLAG2_IS_DISCARDING               (1 << 2)
@@ -453,11 +455,14 @@ struct e1000_info {
 #define FLAG2_DISABLE_ASPM_L0S            (1 << 7)
 #define FLAG2_DISABLE_AIM                 (1 << 8)
 #define FLAG2_CHECK_PHY_HANG              (1 << 9)
+#define FLAG2_NO_DISABLE_RX               (1 << 10)
+#define FLAG2_PCIM2PCI_ARBITER_WA         (1 << 11)
 
 #define E1000_RX_DESC_PS(R, i)     \
        (&(((union e1000_rx_desc_packet_split *)((R).desc))[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)
 #define E1000_TX_DESC(R, i)            E1000_GET_DESC(R, i, e1000_tx_desc)
 #define E1000_CONTEXT_DESC(R, i)       E1000_GET_DESC(R, i, e1000_context_desc)
 
similarity index 96%
rename from drivers/net/e1000e/ethtool.c
rename to drivers/net/ethernet/intel/e1000e/ethtool.c
index cb1a362..d96d0b0 100644 (file)
@@ -28,8 +28,8 @@
 
 /* ethtool support for e1000 */
 
-#include <linux/interrupt.h>
 #include <linux/netdevice.h>
+#include <linux/interrupt.h>
 #include <linux/ethtool.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
@@ -367,59 +367,6 @@ out:
        return retval;
 }
 
-static u32 e1000_get_rx_csum(struct net_device *netdev)
-{
-       struct e1000_adapter *adapter = netdev_priv(netdev);
-       return adapter->flags & FLAG_RX_CSUM_ENABLED;
-}
-
-static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
-{
-       struct e1000_adapter *adapter = netdev_priv(netdev);
-
-       if (data)
-               adapter->flags |= FLAG_RX_CSUM_ENABLED;
-       else
-               adapter->flags &= ~FLAG_RX_CSUM_ENABLED;
-
-       if (netif_running(netdev))
-               e1000e_reinit_locked(adapter);
-       else
-               e1000e_reset(adapter);
-       return 0;
-}
-
-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)
-{
-       if (data)
-               netdev->features |= NETIF_F_HW_CSUM;
-       else
-               netdev->features &= ~NETIF_F_HW_CSUM;
-
-       return 0;
-}
-
-static int e1000_set_tso(struct net_device *netdev, u32 data)
-{
-       struct e1000_adapter *adapter = netdev_priv(netdev);
-
-       if (data) {
-               netdev->features |= NETIF_F_TSO;
-               netdev->features |= NETIF_F_TSO6;
-       } else {
-               netdev->features &= ~NETIF_F_TSO;
-               netdev->features &= ~NETIF_F_TSO6;
-       }
-
-       adapter->flags |= FLAG_TSO_FORCE;
-       return 0;
-}
-
 static u32 e1000_get_msglevel(struct net_device *netdev)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -964,6 +911,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
 
        /* Disable all the interrupts */
        ew32(IMC, 0xFFFFFFFF);
+       e1e_flush();
        usleep_range(10000, 20000);
 
        /* Test each interrupt */
@@ -996,6 +944,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
                        adapter->test_icr = 0;
                        ew32(IMC, mask);
                        ew32(ICS, mask);
+                       e1e_flush();
                        usleep_range(10000, 20000);
 
                        if (adapter->test_icr & mask) {
@@ -1014,6 +963,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
                adapter->test_icr = 0;
                ew32(IMS, mask);
                ew32(ICS, mask);
+               e1e_flush();
                usleep_range(10000, 20000);
 
                if (!(adapter->test_icr & mask)) {
@@ -1032,6 +982,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
                        adapter->test_icr = 0;
                        ew32(IMC, ~mask & 0x00007FFF);
                        ew32(ICS, ~mask & 0x00007FFF);
+                       e1e_flush();
                        usleep_range(10000, 20000);
 
                        if (adapter->test_icr) {
@@ -1043,6 +994,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
 
        /* Disable all the interrupts */
        ew32(IMC, 0xFFFFFFFF);
+       e1e_flush();
        usleep_range(10000, 20000);
 
        /* Unhook test interrupt handler */
@@ -1190,7 +1142,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
                goto err_nomem;
        }
 
-       rx_ring->size = rx_ring->count * sizeof(struct e1000_rx_desc);
+       rx_ring->size = rx_ring->count * sizeof(union e1000_rx_desc_extended);
        rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
                                           &rx_ring->dma, GFP_KERNEL);
        if (!rx_ring->desc) {
@@ -1201,7 +1153,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
        rx_ring->next_to_clean = 0;
 
        rctl = er32(RCTL);
-       ew32(RCTL, rctl & ~E1000_RCTL_EN);
+       if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX))
+               ew32(RCTL, rctl & ~E1000_RCTL_EN);
        ew32(RDBAL, ((u64) rx_ring->dma & 0xFFFFFFFF));
        ew32(RDBAH, ((u64) rx_ring->dma >> 32));
        ew32(RDLEN, rx_ring->size);
@@ -1215,7 +1168,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
        ew32(RCTL, rctl);
 
        for (i = 0; i < rx_ring->count; i++) {
-               struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i);
+               union e1000_rx_desc_extended *rx_desc;
                struct sk_buff *skb;
 
                skb = alloc_skb(2048 + NET_IP_ALIGN, GFP_KERNEL);
@@ -1233,8 +1186,9 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
                        ret_val = 8;
                        goto err_nomem;
                }
-               rx_desc->buffer_addr =
-                       cpu_to_le64(rx_ring->buffer_info[i].dma);
+               rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
+               rx_desc->read.buffer_addr =
+                   cpu_to_le64(rx_ring->buffer_info[i].dma);
                memset(skb->data, 0x00, skb->len);
        }
 
@@ -1276,6 +1230,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
                             E1000_CTRL_FD);     /* Force Duplex to FULL */
 
                ew32(CTRL, ctrl_reg);
+               e1e_flush();
                udelay(500);
 
                return 0;
@@ -1418,6 +1373,7 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
         */
 #define E1000_SERDES_LB_ON 0x410
        ew32(SCTL, E1000_SERDES_LB_ON);
+       e1e_flush();
        usleep_range(10000, 20000);
 
        return 0;
@@ -1513,6 +1469,7 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
                    hw->phy.media_type == e1000_media_type_internal_serdes) {
 #define E1000_SERDES_LB_OFF 0x400
                        ew32(SCTL, E1000_SERDES_LB_OFF);
+                       e1e_flush();
                        usleep_range(10000, 20000);
                        break;
                }
@@ -1592,6 +1549,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
                                k = 0;
                }
                ew32(TDT, k);
+               e1e_flush();
                msleep(200);
                time = jiffies; /* set the start time for the receive */
                good_cnt = 0;
@@ -2003,31 +1961,6 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset,
        }
 }
 
-static int e1000e_set_flags(struct net_device *netdev, u32 data)
-{
-       struct e1000_adapter *adapter = netdev_priv(netdev);
-       bool need_reset = false;
-       int rc;
-
-       need_reset = (data & ETH_FLAG_RXVLAN) !=
-                    (netdev->features & NETIF_F_HW_VLAN_RX);
-
-       rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_RXVLAN |
-                                 ETH_FLAG_TXVLAN);
-
-       if (rc)
-               return rc;
-
-       if (need_reset) {
-               if (netif_running(netdev))
-                       e1000e_reinit_locked(adapter);
-               else
-                       e1000e_reset(adapter);
-       }
-
-       return 0;
-}
-
 static const struct ethtool_ops e1000_ethtool_ops = {
        .get_settings           = e1000_get_settings,
        .set_settings           = e1000_set_settings,
@@ -2047,14 +1980,6 @@ static const struct ethtool_ops e1000_ethtool_ops = {
        .set_ringparam          = e1000_set_ringparam,
        .get_pauseparam         = e1000_get_pauseparam,
        .set_pauseparam         = e1000_set_pauseparam,
-       .get_rx_csum            = e1000_get_rx_csum,
-       .set_rx_csum            = e1000_set_rx_csum,
-       .get_tx_csum            = e1000_get_tx_csum,
-       .set_tx_csum            = e1000_set_tx_csum,
-       .get_sg                 = ethtool_op_get_sg,
-       .set_sg                 = ethtool_op_set_sg,
-       .get_tso                = ethtool_op_get_tso,
-       .set_tso                = e1000_set_tso,
        .self_test              = e1000_diag_test,
        .get_strings            = e1000_get_strings,
        .set_phys_id            = e1000_set_phys_id,
@@ -2062,8 +1987,6 @@ static const struct ethtool_ops e1000_ethtool_ops = {
        .get_sset_count         = e1000e_get_sset_count,
        .get_coalesce           = e1000_get_coalesce,
        .set_coalesce           = e1000_set_coalesce,
-       .get_flags              = ethtool_op_get_flags,
-       .set_flags              = e1000e_set_flags,
 };
 
 void e1000e_set_ethtool_ops(struct net_device *netdev)
similarity index 98%
rename from drivers/net/e1000e/ich8lan.c
rename to drivers/net/ethernet/intel/e1000e/ich8lan.c
index c175212..3fc3acc 100644 (file)
 #define HV_PM_CTRL             PHY_REG(770, 17)
 
 /* PHY Low Power Idle Control */
-#define I82579_LPI_CTRL                        PHY_REG(772, 20)
-#define I82579_LPI_CTRL_ENABLE_MASK    0x6000
+#define I82579_LPI_CTRL                                PHY_REG(772, 20)
+#define I82579_LPI_CTRL_ENABLE_MASK            0x6000
+#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT   0x80
 
 /* EMI Registers */
 #define I82579_EMI_ADDR         0x10
 #define HV_KMRN_MODE_CTRL      PHY_REG(769, 16)
 #define HV_KMRN_MDIO_SLOW      0x0400
 
+/* KMRN FIFO Control and Status */
+#define HV_KMRN_FIFO_CTRLSTA                  PHY_REG(770, 16)
+#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK    0x7000
+#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT   12
+
 /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
 /* Offset 04h HSFSTS */
 union ich8_hws_flash_status {
@@ -283,6 +289,7 @@ static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw)
        ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
        ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
        ew32(CTRL, ctrl);
+       e1e_flush();
        udelay(10);
        ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
        ew32(CTRL, ctrl);
@@ -656,6 +663,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
        struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val;
        bool link;
+       u16 phy_reg;
 
        /*
         * We only want to go out to the PHY registers to see if Auto-Neg
@@ -688,16 +696,35 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
 
        mac->get_link_status = false;
 
-       if (hw->phy.type == e1000_phy_82578) {
-               ret_val = e1000_link_stall_workaround_hv(hw);
-               if (ret_val)
-                       goto out;
-       }
-
-       if (hw->mac.type == e1000_pch2lan) {
+       switch (hw->mac.type) {
+       case e1000_pch2lan:
                ret_val = e1000_k1_workaround_lv(hw);
                if (ret_val)
                        goto out;
+               /* fall-thru */
+       case e1000_pchlan:
+               if (hw->phy.type == e1000_phy_82578) {
+                       ret_val = e1000_link_stall_workaround_hv(hw);
+                       if (ret_val)
+                               goto out;
+               }
+
+               /*
+                * Workaround for PCHx parts in half-duplex:
+                * Set the number of preambles removed from the packet
+                * when it is passed from the PHY to the MAC to prevent
+                * the MAC from misinterpreting the packet type.
+                */
+               e1e_rphy(hw, HV_KMRN_FIFO_CTRLSTA, &phy_reg);
+               phy_reg &= ~HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK;
+
+               if ((er32(STATUS) & E1000_STATUS_FD) != E1000_STATUS_FD)
+                       phy_reg |= (1 << HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT);
+
+               e1e_wphy(hw, HV_KMRN_FIFO_CTRLSTA, phy_reg);
+               break;
+       default:
+               break;
        }
 
        /*
@@ -787,6 +814,11 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
            (adapter->hw.phy.type == e1000_phy_igp_3))
                adapter->flags |= FLAG_LSC_GIG_SPEED_DROP;
 
+       /* Enable workaround for 82579 w/ ME enabled */
+       if ((adapter->hw.mac.type == e1000_pch2lan) &&
+           (er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
+               adapter->flags2 |= FLAG2_PCIM2PCI_ARBITER_WA;
+
        /* Disable EEE by default until IEEE802.3az spec is finalized */
        if (adapter->flags2 & FLAG2_HAS_EEE)
                adapter->hw.dev_spec.ich8lan.eee_disable = true;
@@ -1230,9 +1262,11 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
        ew32(CTRL, reg);
 
        ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS);
+       e1e_flush();
        udelay(20);
        ew32(CTRL, ctrl_reg);
        ew32(CTRL_EXT, ctrl_ext);
+       e1e_flush();
        udelay(20);
 
 out:
@@ -1352,7 +1386,7 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
                        return ret_val;
 
                /* Preamble tuning for SSC */
-               ret_val = e1e_wphy(hw, PHY_REG(770, 16), 0xA204);
+               ret_val = e1e_wphy(hw, HV_KMRN_FIFO_CTRLSTA, 0xA204);
                if (ret_val)
                        return ret_val;
        }
@@ -1642,6 +1676,7 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
        s32 ret_val = 0;
        u16 status_reg = 0;
        u32 mac_reg;
+       u16 phy_reg;
 
        if (hw->mac.type != e1000_pch2lan)
                goto out;
@@ -1656,12 +1691,19 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
                mac_reg = er32(FEXTNVM4);
                mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
 
-               if (status_reg & HV_M_STATUS_SPEED_1000)
+               ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg);
+               if (ret_val)
+                       goto out;
+
+               if (status_reg & HV_M_STATUS_SPEED_1000) {
                        mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
-               else
+                       phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
+               } else {
                        mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC;
-
+                       phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
+               }
                ew32(FEXTNVM4, mac_reg);
+               ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
        }
 
 out:
@@ -2134,8 +2176,7 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
 
        ret_val = 0;
        for (i = 0; i < words; i++) {
-               if ((dev_spec->shadow_ram) &&
-                   (dev_spec->shadow_ram[offset+i].modified)) {
+               if (dev_spec->shadow_ram[offset+i].modified) {
                        data[i] = dev_spec->shadow_ram[offset+i].value;
                } else {
                        ret_val = e1000_read_flash_word_ich8lan(hw,
@@ -3090,6 +3131,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
        ret_val = e1000_acquire_swflag_ich8lan(hw);
        e_dbg("Issuing a global reset to ich8lan\n");
        ew32(CTRL, (ctrl | E1000_CTRL_RST));
+       /* cannot issue a flush here because it hangs the hardware */
        msleep(20);
 
        if (!ret_val)
@@ -4016,7 +4058,6 @@ struct e1000_info e1000_ich8_info = {
        .mac                    = e1000_ich8lan,
        .flags                  = FLAG_HAS_WOL
                                  | FLAG_IS_ICH
-                                 | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_FLASH
@@ -4034,7 +4075,6 @@ struct e1000_info e1000_ich9_info = {
        .flags                  = FLAG_HAS_JUMBO_FRAMES
                                  | FLAG_IS_ICH
                                  | FLAG_HAS_WOL
-                                 | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_ERT
@@ -4053,7 +4093,6 @@ struct e1000_info e1000_ich10_info = {
        .flags                  = FLAG_HAS_JUMBO_FRAMES
                                  | FLAG_IS_ICH
                                  | FLAG_HAS_WOL
-                                 | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_ERT
@@ -4071,7 +4110,6 @@ struct e1000_info e1000_pch_info = {
        .mac                    = e1000_pchlan,
        .flags                  = FLAG_IS_ICH
                                  | FLAG_HAS_WOL
-                                 | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_FLASH
@@ -4091,7 +4129,6 @@ struct e1000_info e1000_pch2_info = {
        .mac                    = e1000_pch2lan,
        .flags                  = FLAG_IS_ICH
                                  | FLAG_HAS_WOL
-                                 | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_FLASH
similarity index 99%
rename from drivers/net/e1000e/lib.c
rename to drivers/net/ethernet/intel/e1000e/lib.c
index 65580b4..0893ab1 100644 (file)
@@ -190,7 +190,8 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
        /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */
        if (!((nvm_data & NVM_COMPAT_LOM) ||
              (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) ||
-             (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD)))
+             (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) ||
+             (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES)))
                goto out;
 
        ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
@@ -200,10 +201,10 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
                goto out;
        }
 
-       if (nvm_alt_mac_addr_offset == 0xFFFF) {
+       if ((nvm_alt_mac_addr_offset == 0xFFFF) ||
+           (nvm_alt_mac_addr_offset == 0x0000))
                /* There is no Alternate MAC Address */
                goto out;
-       }
 
        if (hw->bus.func == E1000_FUNC_1)
                nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
@@ -1986,6 +1987,7 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
                /* Clear SK and CS */
                eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
                ew32(EECD, eecd);
+               e1e_flush();
                udelay(1);
 
                /*
similarity index 95%
rename from drivers/net/e1000e/netdev.c
rename to drivers/net/ethernet/intel/e1000e/netdev.c
index 4353ad5..4f66999 100644 (file)
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
+#include <linux/interrupt.h>
 #include <linux/tcp.h>
 #include <linux/ipv6.h>
 #include <linux/slab.h>
@@ -56,7 +56,7 @@
 
 #define DRV_EXTRAVERSION "-k"
 
-#define DRV_VERSION "1.3.16" DRV_EXTRAVERSION
+#define DRV_VERSION "1.5.1" DRV_EXTRAVERSION
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 
@@ -192,7 +192,7 @@ static void e1000e_dump(struct e1000_adapter *adapter)
        struct e1000_buffer *buffer_info;
        struct e1000_ring *rx_ring = adapter->rx_ring;
        union e1000_rx_desc_packet_split *rx_desc_ps;
-       struct e1000_rx_desc *rx_desc;
+       union e1000_rx_desc_extended *rx_desc;
        struct my_u1 {
                u64 a;
                u64 b;
@@ -399,41 +399,70 @@ rx_ring_summary:
                break;
        default:
        case 0:
-               /* Legacy Receive Descriptor Format
+               /* Extended Receive Descriptor (Read) Format
+                *
+                *   +-----------------------------------------------------+
+                * 0 |                Buffer Address [63:0]                |
+                *   +-----------------------------------------------------+
+                * 8 |                      Reserved                       |
+                *   +-----------------------------------------------------+
+                */
+               printk(KERN_INFO "R  [desc]      [buf addr 63:0 ] "
+                      "[reserved 63:0 ] [bi->dma       ] "
+                      "[bi->skb] <-- Ext (Read) format\n");
+               /* Extended Receive Descriptor (Write-Back) Format
                 *
-                * +-----------------------------------------------------+
-                * |                Buffer Address [63:0]                |
-                * +-----------------------------------------------------+
-                * | VLAN Tag | Errors | Status 0 | Packet csum | Length |
-                * +-----------------------------------------------------+
-                * 63       48 47    40 39      32 31         16 15      0
+                *   63       48 47    32 31    24 23            4 3        0
+                *   +------------------------------------------------------+
+                *   |     RSS Hash      |        |               |         |
+                * 0 +-------------------+  Rsvd  |   Reserved    | MRQ RSS |
+                *   | Packet   | IP     |        |               |  Type   |
+                *   | Checksum | Ident  |        |               |         |
+                *   +------------------------------------------------------+
+                * 8 | VLAN Tag | Length | Extended Error | Extended Status |
+                *   +------------------------------------------------------+
+                *   63       48 47    32 31            20 19               0
                 */
-               printk(KERN_INFO "Rl[desc]     [address 63:0  ] "
-                      "[vl er S cks ln] [bi->dma       ] [bi->skb] "
-                      "<-- Legacy format\n");
-               for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
-                       rx_desc = E1000_RX_DESC(*rx_ring, i);
+               printk(KERN_INFO "RWB[desc]      [cs ipid    mrq] "
+                      "[vt   ln xe  xs] "
+                      "[bi->skb] <-- Ext (Write-Back) format\n");
+
+               for (i = 0; i < rx_ring->count; i++) {
                        buffer_info = &rx_ring->buffer_info[i];
-                       u0 = (struct my_u0 *)rx_desc;
-                       printk(KERN_INFO "Rl[0x%03X]    %016llX %016llX "
-                              "%016llX %p", i,
-                              (unsigned long long)le64_to_cpu(u0->a),
-                              (unsigned long long)le64_to_cpu(u0->b),
-                              (unsigned long long)buffer_info->dma,
-                              buffer_info->skb);
+                       rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
+                       u1 = (struct my_u1 *)rx_desc;
+                       staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+                       if (staterr & E1000_RXD_STAT_DD) {
+                               /* Descriptor Done */
+                               printk(KERN_INFO "RWB[0x%03X]     %016llX "
+                                      "%016llX ---------------- %p", i,
+                                      (unsigned long long)le64_to_cpu(u1->a),
+                                      (unsigned long long)le64_to_cpu(u1->b),
+                                      buffer_info->skb);
+                       } else {
+                               printk(KERN_INFO "R  [0x%03X]     %016llX "
+                                      "%016llX %016llX %p", i,
+                                      (unsigned long long)le64_to_cpu(u1->a),
+                                      (unsigned long long)le64_to_cpu(u1->b),
+                                      (unsigned long long)buffer_info->dma,
+                                      buffer_info->skb);
+
+                               if (netif_msg_pktdata(adapter))
+                                       print_hex_dump(KERN_INFO, "",
+                                                      DUMP_PREFIX_ADDRESS, 16,
+                                                      1,
+                                                      phys_to_virt
+                                                      (buffer_info->dma),
+                                                      adapter->rx_buffer_len,
+                                                      true);
+                       }
+
                        if (i == rx_ring->next_to_use)
                                printk(KERN_CONT " NTU\n");
                        else if (i == rx_ring->next_to_clean)
                                printk(KERN_CONT " NTC\n");
                        else
                                printk(KERN_CONT "\n");
-
-                       if (netif_msg_pktdata(adapter))
-                               print_hex_dump(KERN_INFO, "",
-                                              DUMP_PREFIX_ADDRESS,
-                                              16, 1,
-                                              phys_to_virt(buffer_info->dma),
-                                              adapter->rx_buffer_len, true);
                }
        }
 
@@ -519,7 +548,64 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
 }
 
 /**
- * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
+ * e1000e_update_tail_wa - helper function for e1000e_update_[rt]dt_wa()
+ * @hw: pointer to the HW structure
+ * @tail: address of tail descriptor register
+ * @i: value to write to tail descriptor register
+ *
+ * When updating the tail register, the ME could be accessing Host CSR
+ * registers at the same time.  Normally, this is handled in h/w by an
+ * arbiter but on some parts there is a bug that acknowledges Host accesses
+ * later than it should which could result in the descriptor register to
+ * have an incorrect value.  Workaround this by checking the FWSM register
+ * which has bit 24 set while ME is accessing Host CSR registers, wait
+ * if it is set and try again a number of times.
+ **/
+static inline s32 e1000e_update_tail_wa(struct e1000_hw *hw, u8 __iomem * tail,
+                                       unsigned int i)
+{
+       unsigned int j = 0;
+
+       while ((j++ < E1000_ICH_FWSM_PCIM2PCI_COUNT) &&
+              (er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI))
+               udelay(50);
+
+       writel(i, tail);
+
+       if ((j == E1000_ICH_FWSM_PCIM2PCI_COUNT) && (i != readl(tail)))
+               return E1000_ERR_SWFW_SYNC;
+
+       return 0;
+}
+
+static void e1000e_update_rdt_wa(struct e1000_adapter *adapter, unsigned int i)
+{
+       u8 __iomem *tail = (adapter->hw.hw_addr + adapter->rx_ring->tail);
+       struct e1000_hw *hw = &adapter->hw;
+
+       if (e1000e_update_tail_wa(hw, tail, i)) {
+               u32 rctl = er32(RCTL);
+               ew32(RCTL, rctl & ~E1000_RCTL_EN);
+               e_err("ME firmware caused invalid RDT - resetting\n");
+               schedule_work(&adapter->reset_task);
+       }
+}
+
+static void e1000e_update_tdt_wa(struct e1000_adapter *adapter, unsigned int i)
+{
+       u8 __iomem *tail = (adapter->hw.hw_addr + adapter->tx_ring->tail);
+       struct e1000_hw *hw = &adapter->hw;
+
+       if (e1000e_update_tail_wa(hw, tail, i)) {
+               u32 tctl = er32(TCTL);
+               ew32(TCTL, tctl & ~E1000_TCTL_EN);
+               e_err("ME firmware caused invalid TDT - resetting\n");
+               schedule_work(&adapter->reset_task);
+       }
+}
+
+/**
+ * e1000_alloc_rx_buffers - Replace used receive buffers
  * @adapter: address of board private structure
  **/
 static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
@@ -528,7 +614,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
        struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
        struct e1000_ring *rx_ring = adapter->rx_ring;
-       struct e1000_rx_desc *rx_desc;
+       union e1000_rx_desc_extended *rx_desc;
        struct e1000_buffer *buffer_info;
        struct sk_buff *skb;
        unsigned int i;
@@ -562,8 +648,8 @@ map_skb:
                        break;
                }
 
-               rx_desc = E1000_RX_DESC(*rx_ring, i);
-               rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+               rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
+               rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
 
                if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) {
                        /*
@@ -573,7 +659,10 @@ map_skb:
                         * such as IA-64).
                         */
                        wmb();
-                       writel(i, adapter->hw.hw_addr + rx_ring->tail);
+                       if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
+                               e1000e_update_rdt_wa(adapter, i);
+                       else
+                               writel(i, adapter->hw.hw_addr + rx_ring->tail);
                }
                i++;
                if (i == rx_ring->count)
@@ -673,7 +762,11 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
                         * such as IA-64).
                         */
                        wmb();
-                       writel(i << 1, adapter->hw.hw_addr + rx_ring->tail);
+                       if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
+                               e1000e_update_rdt_wa(adapter, i << 1);
+                       else
+                               writel(i << 1,
+                                      adapter->hw.hw_addr + rx_ring->tail);
                }
 
                i++;
@@ -697,7 +790,7 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
 {
        struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
-       struct e1000_rx_desc *rx_desc;
+       union e1000_rx_desc_extended *rx_desc;
        struct e1000_ring *rx_ring = adapter->rx_ring;
        struct e1000_buffer *buffer_info;
        struct sk_buff *skb;
@@ -738,8 +831,8 @@ check_page:
                                                        PAGE_SIZE,
                                                        DMA_FROM_DEVICE);
 
-               rx_desc = E1000_RX_DESC(*rx_ring, i);
-               rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+               rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
+               rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
 
                if (unlikely(++i == rx_ring->count))
                        i = 0;
@@ -756,7 +849,10 @@ check_page:
                 * applicable for weak-ordered memory model archs,
                 * such as IA-64). */
                wmb();
-               writel(i, adapter->hw.hw_addr + rx_ring->tail);
+               if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
+                       e1000e_update_rdt_wa(adapter, i);
+               else
+                       writel(i, adapter->hw.hw_addr + rx_ring->tail);
        }
 }
 
@@ -774,28 +870,27 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
        struct pci_dev *pdev = adapter->pdev;
        struct e1000_hw *hw = &adapter->hw;
        struct e1000_ring *rx_ring = adapter->rx_ring;
-       struct e1000_rx_desc *rx_desc, *next_rxd;
+       union e1000_rx_desc_extended *rx_desc, *next_rxd;
        struct e1000_buffer *buffer_info, *next_buffer;
-       u32 length;
+       u32 length, staterr;
        unsigned int i;
        int cleaned_count = 0;
        bool cleaned = 0;
        unsigned int total_rx_bytes = 0, total_rx_packets = 0;
 
        i = rx_ring->next_to_clean;
-       rx_desc = E1000_RX_DESC(*rx_ring, i);
+       rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
+       staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
        buffer_info = &rx_ring->buffer_info[i];
 
-       while (rx_desc->status & E1000_RXD_STAT_DD) {
+       while (staterr & E1000_RXD_STAT_DD) {
                struct sk_buff *skb;
-               u8 status;
 
                if (*work_done >= work_to_do)
                        break;
                (*work_done)++;
                rmb();  /* read descriptor and rx_buffer_info after status DD */
 
-               status = rx_desc->status;
                skb = buffer_info->skb;
                buffer_info->skb = NULL;
 
@@ -804,7 +899,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
                i++;
                if (i == rx_ring->count)
                        i = 0;
-               next_rxd = E1000_RX_DESC(*rx_ring, i);
+               next_rxd = E1000_RX_DESC_EXT(*rx_ring, i);
                prefetch(next_rxd);
 
                next_buffer = &rx_ring->buffer_info[i];
@@ -817,7 +912,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
                                 DMA_FROM_DEVICE);
                buffer_info->dma = 0;
 
-               length = le16_to_cpu(rx_desc->length);
+               length = le16_to_cpu(rx_desc->wb.upper.length);
 
                /*
                 * !EOP means multiple descriptors were used to store a single
@@ -826,7 +921,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
                 * next frame that _does_ have the EOP bit set, as it is by
                 * definition only a frame fragment
                 */
-               if (unlikely(!(status & E1000_RXD_STAT_EOP)))
+               if (unlikely(!(staterr & E1000_RXD_STAT_EOP)))
                        adapter->flags2 |= FLAG2_IS_DISCARDING;
 
                if (adapter->flags2 & FLAG2_IS_DISCARDING) {
@@ -834,12 +929,12 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
                        e_dbg("Receive packet consumed multiple buffers\n");
                        /* recycle */
                        buffer_info->skb = skb;
-                       if (status & E1000_RXD_STAT_EOP)
+                       if (staterr & E1000_RXD_STAT_EOP)
                                adapter->flags2 &= ~FLAG2_IS_DISCARDING;
                        goto next_desc;
                }
 
-               if (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
+               if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
                        /* recycle */
                        buffer_info->skb = skb;
                        goto next_desc;
@@ -877,15 +972,15 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
                skb_put(skb, length);
 
                /* Receive Checksum Offload */
-               e1000_rx_checksum(adapter,
-                                 (u32)(status) |
-                                 ((u32)(rx_desc->errors) << 24),
-                                 le16_to_cpu(rx_desc->csum), skb);
+               e1000_rx_checksum(adapter, staterr,
+                                 le16_to_cpu(rx_desc->wb.lower.hi_dword.
+                                             csum_ip.csum), skb);
 
-               e1000_receive_skb(adapter, netdev, skb,status,rx_desc->special);
+               e1000_receive_skb(adapter, netdev, skb, staterr,
+                                 rx_desc->wb.upper.vlan);
 
 next_desc:
-               rx_desc->status = 0;
+               rx_desc->wb.upper.status_error &= cpu_to_le32(~0xFF);
 
                /* return some buffers to hardware, one at a time is too slow */
                if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
@@ -897,6 +992,8 @@ next_desc:
                /* use prefetched values */
                rx_desc = next_rxd;
                buffer_info = next_buffer;
+
+               staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
        }
        rx_ring->next_to_clean = i;
 
@@ -1280,35 +1377,34 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
        struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
        struct e1000_ring *rx_ring = adapter->rx_ring;
-       struct e1000_rx_desc *rx_desc, *next_rxd;
+       union e1000_rx_desc_extended *rx_desc, *next_rxd;
        struct e1000_buffer *buffer_info, *next_buffer;
-       u32 length;
+       u32 length, staterr;
        unsigned int i;
        int cleaned_count = 0;
        bool cleaned = false;
        unsigned int total_rx_bytes=0, total_rx_packets=0;
 
        i = rx_ring->next_to_clean;
-       rx_desc = E1000_RX_DESC(*rx_ring, i);
+       rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
+       staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
        buffer_info = &rx_ring->buffer_info[i];
 
-       while (rx_desc->status & E1000_RXD_STAT_DD) {
+       while (staterr & E1000_RXD_STAT_DD) {
                struct sk_buff *skb;
-               u8 status;
 
                if (*work_done >= work_to_do)
                        break;
                (*work_done)++;
                rmb();  /* read descriptor and rx_buffer_info after status DD */
 
-               status = rx_desc->status;
                skb = buffer_info->skb;
                buffer_info->skb = NULL;
 
                ++i;
                if (i == rx_ring->count)
                        i = 0;
-               next_rxd = E1000_RX_DESC(*rx_ring, i);
+               next_rxd = E1000_RX_DESC_EXT(*rx_ring, i);
                prefetch(next_rxd);
 
                next_buffer = &rx_ring->buffer_info[i];
@@ -1319,23 +1415,22 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
                               DMA_FROM_DEVICE);
                buffer_info->dma = 0;
 
-               length = le16_to_cpu(rx_desc->length);
+               length = le16_to_cpu(rx_desc->wb.upper.length);
 
                /* errors is only valid for DD + EOP descriptors */
-               if (unlikely((status & E1000_RXD_STAT_EOP) &&
-                   (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) {
-                               /* recycle both page and skb */
-                               buffer_info->skb = skb;
-                               /* an error means any chain goes out the window
-                                * too */
-                               if (rx_ring->rx_skb_top)
-                                       dev_kfree_skb_irq(rx_ring->rx_skb_top);
-                               rx_ring->rx_skb_top = NULL;
-                               goto next_desc;
+               if (unlikely((staterr & E1000_RXD_STAT_EOP) &&
+                            (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK))) {
+                       /* recycle both page and skb */
+                       buffer_info->skb = skb;
+                       /* an error means any chain goes out the window too */
+                       if (rx_ring->rx_skb_top)
+                               dev_kfree_skb_irq(rx_ring->rx_skb_top);
+                       rx_ring->rx_skb_top = NULL;
+                       goto next_desc;
                }
 
 #define rxtop (rx_ring->rx_skb_top)
-               if (!(status & E1000_RXD_STAT_EOP)) {
+               if (!(staterr & E1000_RXD_STAT_EOP)) {
                        /* this descriptor is only the beginning (or middle) */
                        if (!rxtop) {
                                /* this is the beginning of a chain */
@@ -1390,10 +1485,9 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
                }
 
                /* Receive Checksum Offload XXX recompute due to CRC strip? */
-               e1000_rx_checksum(adapter,
-                                 (u32)(status) |
-                                 ((u32)(rx_desc->errors) << 24),
-                                 le16_to_cpu(rx_desc->csum), skb);
+               e1000_rx_checksum(adapter, staterr,
+                                 le16_to_cpu(rx_desc->wb.lower.hi_dword.
+                                             csum_ip.csum), skb);
 
                /* probably a little skewed due to removing CRC */
                total_rx_bytes += skb->len;
@@ -1406,11 +1500,11 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
                        goto next_desc;
                }
 
-               e1000_receive_skb(adapter, netdev, skb, status,
-                                 rx_desc->special);
+               e1000_receive_skb(adapter, netdev, skb, staterr,
+                                 rx_desc->wb.upper.vlan);
 
 next_desc:
-               rx_desc->status = 0;
+               rx_desc->wb.upper.status_error &= cpu_to_le32(~0xFF);
 
                /* return some buffers to hardware, one at a time is too slow */
                if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
@@ -1422,6 +1516,8 @@ next_desc:
                /* use prefetched values */
                rx_desc = next_rxd;
                buffer_info = next_buffer;
+
+               staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
        }
        rx_ring->next_to_clean = i;
 
@@ -2820,6 +2916,10 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
                break;
        }
 
+       /* Enable Extended Status in all Receive Descriptors */
+       rfctl = er32(RFCTL);
+       rfctl |= E1000_RFCTL_EXTEN;
+
        /*
         * 82571 and greater support packet-split where the protocol
         * header is placed in skb->data and the packet data is
@@ -2845,9 +2945,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
        if (adapter->rx_ps_pages) {
                u32 psrctl = 0;
 
-               /* Configure extra packet-split registers */
-               rfctl = er32(RFCTL);
-               rfctl |= E1000_RFCTL_EXTEN;
                /*
                 * disable packet split support for IPv6 extension headers,
                 * because some malformed IPv6 headers can hang the Rx
@@ -2855,8 +2952,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
                rfctl |= (E1000_RFCTL_IPV6_EX_DIS |
                          E1000_RFCTL_NEW_IPV6_EXT_DIS);
 
-               ew32(RFCTL, rfctl);
-
                /* Enable Packet split descriptors */
                rctl |= E1000_RCTL_DTYP_PS;
 
@@ -2879,6 +2974,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
                ew32(PSRCTL, psrctl);
        }
 
+       ew32(RFCTL, rfctl);
        ew32(RCTL, rctl);
        /* just started the receive unit, no need to restart */
        adapter->flags &= ~FLAG_RX_RESTART_NOW;
@@ -2904,18 +3000,19 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
                adapter->clean_rx = e1000_clean_rx_irq_ps;
                adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps;
        } else if (adapter->netdev->mtu > ETH_FRAME_LEN + ETH_FCS_LEN) {
-               rdlen = rx_ring->count * sizeof(struct e1000_rx_desc);
+               rdlen = rx_ring->count * sizeof(union e1000_rx_desc_extended);
                adapter->clean_rx = e1000_clean_jumbo_rx_irq;
                adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers;
        } else {
-               rdlen = rx_ring->count * sizeof(struct e1000_rx_desc);
+               rdlen = rx_ring->count * sizeof(union e1000_rx_desc_extended);
                adapter->clean_rx = e1000_clean_rx_irq;
                adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
        }
 
        /* disable receives while setting up the descriptors */
        rctl = er32(RCTL);
-       ew32(RCTL, rctl & ~E1000_RCTL_EN);
+       if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX))
+               ew32(RCTL, rctl & ~E1000_RCTL_EN);
        e1e_flush();
        usleep_range(10000, 20000);
 
@@ -2972,7 +3069,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
 
        /* Enable Receive Checksum Offload for TCP and UDP */
        rxcsum = er32(RXCSUM);
-       if (adapter->flags & FLAG_RX_CSUM_ENABLED) {
+       if (adapter->netdev->features & NETIF_F_RXCSUM) {
                rxcsum |= E1000_RXCSUM_TUOFL;
 
                /*
@@ -3394,7 +3491,8 @@ void e1000e_down(struct e1000_adapter *adapter)
 
        /* disable receives in the hardware */
        rctl = er32(RCTL);
-       ew32(RCTL, rctl & ~E1000_RCTL_EN);
+       if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX))
+               ew32(RCTL, rctl & ~E1000_RCTL_EN);
        /* flush and sleep below */
 
        netif_stop_queue(netdev);
@@ -3403,6 +3501,7 @@ void e1000e_down(struct e1000_adapter *adapter)
        tctl = er32(TCTL);
        tctl &= ~E1000_TCTL_EN;
        ew32(TCTL, tctl);
+
        /* flush both disables and wait for them to finish */
        e1e_flush();
        usleep_range(10000, 20000);
@@ -4686,7 +4785,12 @@ static void e1000_tx_queue(struct e1000_adapter *adapter,
        wmb();
 
        tx_ring->next_to_use = i;
-       writel(i, adapter->hw.hw_addr + tx_ring->tail);
+
+       if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
+               e1000e_update_tdt_wa(adapter, i);
+       else
+               writel(i, adapter->hw.hw_addr + tx_ring->tail);
+
        /*
         * we need this if more than one processor can write to our tail
         * at a time, it synchronizes IO on IA64/Altix systems
@@ -5756,12 +5860,32 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)
        }
 }
 
+static int e1000_set_features(struct net_device *netdev, u32 features)
+{
+       struct e1000_adapter *adapter = netdev_priv(netdev);
+       u32 changed = features ^ netdev->features;
+
+       if (changed & (NETIF_F_TSO | NETIF_F_TSO6))
+               adapter->flags |= FLAG_TSO_FORCE;
+
+       if (!(changed & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX |
+                        NETIF_F_RXCSUM)))
+               return 0;
+
+       if (netif_running(netdev))
+               e1000e_reinit_locked(adapter);
+       else
+               e1000e_reset(adapter);
+
+       return 0;
+}
+
 static const struct net_device_ops e1000e_netdev_ops = {
        .ndo_open               = e1000_open,
        .ndo_stop               = e1000_close,
        .ndo_start_xmit         = e1000_xmit_frame,
        .ndo_get_stats64        = e1000e_get_stats64,
-       .ndo_set_multicast_list = e1000_set_multi,
+       .ndo_set_rx_mode        = e1000_set_multi,
        .ndo_set_mac_address    = e1000_set_mac,
        .ndo_change_mtu         = e1000_change_mtu,
        .ndo_do_ioctl           = e1000_ioctl,
@@ -5773,6 +5897,7 @@ static const struct net_device_ops e1000e_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = e1000_netpoll,
 #endif
+       .ndo_set_features = e1000_set_features,
 };
 
 /**
@@ -5932,21 +6057,25 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        if (e1000_check_reset_block(&adapter->hw))
                e_info("PHY reset is blocked due to SOL/IDER session.\n");
 
-       netdev->features = NETIF_F_SG |
-                          NETIF_F_HW_CSUM |
-                          NETIF_F_HW_VLAN_TX |
-                          NETIF_F_HW_VLAN_RX;
+       /* Set initial default active device features */
+       netdev->features = (NETIF_F_SG |
+                           NETIF_F_HW_VLAN_RX |
+                           NETIF_F_HW_VLAN_TX |
+                           NETIF_F_TSO |
+                           NETIF_F_TSO6 |
+                           NETIF_F_RXCSUM |
+                           NETIF_F_HW_CSUM);
+
+       /* Set user-changeable features (subset of all device features) */
+       netdev->hw_features = netdev->features;
 
        if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER)
                netdev->features |= NETIF_F_HW_VLAN_FILTER;
 
-       netdev->features |= NETIF_F_TSO;
-       netdev->features |= NETIF_F_TSO6;
-
-       netdev->vlan_features |= NETIF_F_TSO;
-       netdev->vlan_features |= NETIF_F_TSO6;
-       netdev->vlan_features |= NETIF_F_HW_CSUM;
-       netdev->vlan_features |= NETIF_F_SG;
+       netdev->vlan_features |= (NETIF_F_SG |
+                                 NETIF_F_TSO |
+                                 NETIF_F_TSO6 |
+                                 NETIF_F_HW_CSUM);
 
        if (pci_using_dac) {
                netdev->features |= NETIF_F_HIGHDMA;
similarity index 99%
rename from drivers/net/e1000e/phy.c
rename to drivers/net/ethernet/intel/e1000e/phy.c
index 2a6ee13..8666476 100644 (file)
@@ -537,6 +537,7 @@ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
        kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
                       E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
        ew32(KMRNCTRLSTA, kmrnctrlsta);
+       e1e_flush();
 
        udelay(2);
 
@@ -609,6 +610,7 @@ static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
        kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
                       E1000_KMRNCTRLSTA_OFFSET) | data;
        ew32(KMRNCTRLSTA, kmrnctrlsta);
+       e1e_flush();
 
        udelay(2);
 
similarity index 99%
rename from drivers/net/igb/e1000_nvm.c
rename to drivers/net/ethernet/intel/igb/e1000_nvm.c
index 7dcd65c..4040712 100644 (file)
@@ -285,6 +285,7 @@ static s32 igb_ready_nvm_eeprom(struct e1000_hw *hw)
                /* Clear SK and CS */
                eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
                wr32(E1000_EECD, eecd);
+               wrfl();
                udelay(1);
                timeout = NVM_MAX_RETRY_SPI;
 
similarity index 99%
rename from drivers/net/igb/igb_ethtool.c
rename to drivers/net/ethernet/intel/igb/igb_ethtool.c
index ff244ce..414b022 100644 (file)
@@ -1225,6 +1225,7 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data)
 
        /* Disable all the interrupts */
        wr32(E1000_IMC, ~0);
+       wrfl();
        msleep(10);
 
        /* Define all writable bits for ICS */
@@ -1268,6 +1269,7 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data)
 
                        wr32(E1000_IMC, mask);
                        wr32(E1000_ICS, mask);
+                       wrfl();
                        msleep(10);
 
                        if (adapter->test_icr & mask) {
@@ -1289,6 +1291,7 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data)
 
                wr32(E1000_IMS, mask);
                wr32(E1000_ICS, mask);
+               wrfl();
                msleep(10);
 
                if (!(adapter->test_icr & mask)) {
@@ -1310,6 +1313,7 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data)
 
                        wr32(E1000_IMC, ~mask);
                        wr32(E1000_ICS, ~mask);
+                       wrfl();
                        msleep(10);
 
                        if (adapter->test_icr & mask) {
@@ -1321,6 +1325,7 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data)
 
        /* Disable all the interrupts */
        wr32(E1000_IMC, ~0);
+       wrfl();
        msleep(10);
 
        /* Unhook test interrupt handler */
similarity index 99%
rename from drivers/net/igb/igb_main.c
rename to drivers/net/ethernet/intel/igb/igb_main.c
index dc59905..8016084 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/net_tstamp.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/if.h>
 #include <linux/if_vlan.h>
 #include <linux/pci.h>
 #include <linux/pci-aspm.h>
@@ -1052,6 +1053,7 @@ msi_only:
                kfree(adapter->vf_data);
                adapter->vf_data = NULL;
                wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
+               wrfl();
                msleep(100);
                dev_info(&adapter->pdev->dev, "IOV Disabled\n");
        }
@@ -1788,7 +1790,6 @@ static const struct net_device_ops igb_netdev_ops = {
        .ndo_start_xmit         = igb_xmit_frame_adv,
        .ndo_get_stats64        = igb_get_stats64,
        .ndo_set_rx_mode        = igb_set_rx_mode,
-       .ndo_set_multicast_list = igb_set_rx_mode,
        .ndo_set_mac_address    = igb_set_mac,
        .ndo_change_mtu         = igb_change_mtu,
        .ndo_do_ioctl           = igb_ioctl,
@@ -1972,6 +1973,8 @@ static int __devinit igb_probe(struct pci_dev *pdev,
                netdev->features |= NETIF_F_SCTP_CSUM;
        }
 
+       netdev->priv_flags |= IFF_UNICAST_FLT;
+
        adapter->en_mng_pt = igb_enable_mng_pass_thru(hw);
 
        /* before reading the NVM, reset the controller to put the device in a
@@ -2022,7 +2025,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 
        if (hw->bus.func == 0)
                hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
-       else if (hw->mac.type == e1000_82580)
+       else if (hw->mac.type >= e1000_82580)
                hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
                                 NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
                                 &eeprom_data);
@@ -2198,6 +2201,7 @@ static void __devexit igb_remove(struct pci_dev *pdev)
                kfree(adapter->vf_data);
                adapter->vf_data = NULL;
                wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
+               wrfl();
                msleep(100);
                dev_info(&pdev->dev, "IOV Disabled\n");
        }
similarity index 99%
rename from drivers/net/igbvf/netdev.c
rename to drivers/net/ethernet/intel/igbvf/netdev.c
index 1330c8e..a6bdb3c 100644 (file)
@@ -1226,6 +1226,7 @@ static void igbvf_configure_tx(struct igbvf_adapter *adapter)
        /* disable transmits */
        txdctl = er32(TXDCTL(0));
        ew32(TXDCTL(0), txdctl & ~E1000_TXDCTL_QUEUE_ENABLE);
+       e1e_flush();
        msleep(10);
 
        /* Setup the HW Tx Head and Tail descriptor pointers */
@@ -1306,6 +1307,7 @@ static void igbvf_configure_rx(struct igbvf_adapter *adapter)
        /* disable receives */
        rxdctl = er32(RXDCTL(0));
        ew32(RXDCTL(0), rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE);
+       e1e_flush();
        msleep(10);
 
        rdlen = rx_ring->count * sizeof(union e1000_adv_rx_desc);
@@ -2536,7 +2538,7 @@ static const struct net_device_ops igbvf_netdev_ops = {
        .ndo_stop                       = igbvf_close,
        .ndo_start_xmit                 = igbvf_xmit_frame,
        .ndo_get_stats                  = igbvf_get_stats,
-       .ndo_set_multicast_list         = igbvf_set_multi,
+       .ndo_set_rx_mode                = igbvf_set_multi,
        .ndo_set_mac_address            = igbvf_set_mac,
        .ndo_change_mtu                 = igbvf_change_mtu,
        .ndo_do_ioctl                   = igbvf_ioctl,
similarity index 98%
rename from drivers/net/ixgb/ixgb_ee.c
rename to drivers/net/ethernet/intel/ixgb/ixgb_ee.c
index c982ab9..38b362b 100644 (file)
@@ -57,6 +57,7 @@ ixgb_raise_clock(struct ixgb_hw *hw,
         */
        *eecd_reg = *eecd_reg | IXGB_EECD_SK;
        IXGB_WRITE_REG(hw, EECD, *eecd_reg);
+       IXGB_WRITE_FLUSH(hw);
        udelay(50);
 }
 
@@ -75,6 +76,7 @@ ixgb_lower_clock(struct ixgb_hw *hw,
         */
        *eecd_reg = *eecd_reg & ~IXGB_EECD_SK;
        IXGB_WRITE_REG(hw, EECD, *eecd_reg);
+       IXGB_WRITE_FLUSH(hw);
        udelay(50);
 }
 
@@ -112,6 +114,7 @@ ixgb_shift_out_bits(struct ixgb_hw *hw,
                        eecd_reg |= IXGB_EECD_DI;
 
                IXGB_WRITE_REG(hw, EECD, eecd_reg);
+               IXGB_WRITE_FLUSH(hw);
 
                udelay(50);
 
@@ -206,21 +209,25 @@ ixgb_standby_eeprom(struct ixgb_hw *hw)
        /*  Deselect EEPROM  */
        eecd_reg &= ~(IXGB_EECD_CS | IXGB_EECD_SK);
        IXGB_WRITE_REG(hw, EECD, eecd_reg);
+       IXGB_WRITE_FLUSH(hw);
        udelay(50);
 
        /*  Clock high  */
        eecd_reg |= IXGB_EECD_SK;
        IXGB_WRITE_REG(hw, EECD, eecd_reg);
+       IXGB_WRITE_FLUSH(hw);
        udelay(50);
 
        /*  Select EEPROM  */
        eecd_reg |= IXGB_EECD_CS;
        IXGB_WRITE_REG(hw, EECD, eecd_reg);
+       IXGB_WRITE_FLUSH(hw);
        udelay(50);
 
        /*  Clock low  */
        eecd_reg &= ~IXGB_EECD_SK;
        IXGB_WRITE_REG(hw, EECD, eecd_reg);
+       IXGB_WRITE_FLUSH(hw);
        udelay(50);
 }
 
@@ -239,11 +246,13 @@ ixgb_clock_eeprom(struct ixgb_hw *hw)
        /*  Rising edge of clock  */
        eecd_reg |= IXGB_EECD_SK;
        IXGB_WRITE_REG(hw, EECD, eecd_reg);
+       IXGB_WRITE_FLUSH(hw);
        udelay(50);
 
        /*  Falling edge of clock  */
        eecd_reg &= ~IXGB_EECD_SK;
        IXGB_WRITE_REG(hw, EECD, eecd_reg);
+       IXGB_WRITE_FLUSH(hw);
        udelay(50);
 }
 
similarity index 99%
rename from drivers/net/ixgb/ixgb_hw.c
rename to drivers/net/ethernet/intel/ixgb/ixgb_hw.c
index 6cb2e42..3d61a9e 100644 (file)
@@ -149,6 +149,7 @@ ixgb_adapter_stop(struct ixgb_hw *hw)
         */
        IXGB_WRITE_REG(hw, RCTL, IXGB_READ_REG(hw, RCTL) & ~IXGB_RCTL_RXEN);
        IXGB_WRITE_REG(hw, TCTL, IXGB_READ_REG(hw, TCTL) & ~IXGB_TCTL_TXEN);
+       IXGB_WRITE_FLUSH(hw);
        msleep(IXGB_DELAY_BEFORE_RESET);
 
        /* Issue a global reset to the MAC.  This will reset the chip's
@@ -1220,6 +1221,7 @@ ixgb_optics_reset_bcm(struct ixgb_hw *hw)
        ctrl &= ~IXGB_CTRL0_SDP2;
        ctrl |= IXGB_CTRL0_SDP3;
        IXGB_WRITE_REG(hw, CTRL0, ctrl);
+       IXGB_WRITE_FLUSH(hw);
 
        /* SerDes needs extra delay */
        msleep(IXGB_SUN_PHY_RESET_DELAY);
similarity index 99%
rename from drivers/net/ixgb/ixgb_main.c
rename to drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 6a130eb..b8ef2c0 100644 (file)
@@ -330,7 +330,7 @@ static const struct net_device_ops ixgb_netdev_ops = {
        .ndo_stop               = ixgb_close,
        .ndo_start_xmit         = ixgb_xmit_frame,
        .ndo_get_stats          = ixgb_get_stats,
-       .ndo_set_multicast_list = ixgb_set_multi,
+       .ndo_set_rx_mode        = ixgb_set_multi,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ixgb_set_mac,
        .ndo_change_mtu         = ixgb_change_mtu,
similarity index 96%
rename from drivers/net/ixgbe/ixgbe.h
rename to drivers/net/ethernet/intel/ixgbe/ixgbe.h
index e04a8e4..58482fc 100644 (file)
 #define IXGBE_RX_BUFFER_WRITE  16      /* Must be power of 2 */
 
 #define IXGBE_TX_FLAGS_CSUM            (u32)(1)
-#define IXGBE_TX_FLAGS_VLAN            (u32)(1 << 1)
-#define IXGBE_TX_FLAGS_TSO             (u32)(1 << 2)
-#define IXGBE_TX_FLAGS_IPV4            (u32)(1 << 3)
-#define IXGBE_TX_FLAGS_FCOE            (u32)(1 << 4)
-#define IXGBE_TX_FLAGS_FSO             (u32)(1 << 5)
+#define IXGBE_TX_FLAGS_HW_VLAN         (u32)(1 << 1)
+#define IXGBE_TX_FLAGS_SW_VLAN         (u32)(1 << 2)
+#define IXGBE_TX_FLAGS_TSO             (u32)(1 << 3)
+#define IXGBE_TX_FLAGS_IPV4            (u32)(1 << 4)
+#define IXGBE_TX_FLAGS_FCOE            (u32)(1 << 5)
+#define IXGBE_TX_FLAGS_FSO             (u32)(1 << 6)
+#define IXGBE_TX_FLAGS_TXSW            (u32)(1 << 7)
+#define IXGBE_TX_FLAGS_MAPPED_AS_PAGE  (u32)(1 << 8)
 #define IXGBE_TX_FLAGS_VLAN_MASK       0xffff0000
-#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK   0x0000e000
+#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK  0xe0000000
+#define IXGBE_TX_FLAGS_VLAN_PRIO_SHIFT  29
 #define IXGBE_TX_FLAGS_VLAN_SHIFT      16
 
 #define IXGBE_MAX_RSC_INT_RATE          162760
@@ -141,14 +145,14 @@ struct vf_macvlans {
 /* wrapper around a pointer to a socket buffer,
  * so a DMA handle can be stored along with the buffer */
 struct ixgbe_tx_buffer {
-       struct sk_buff *skb;
-       dma_addr_t dma;
+       union ixgbe_adv_tx_desc *next_to_watch;
        unsigned long time_stamp;
-       u16 length;
-       u16 next_to_watch;
-       unsigned int bytecount;
+       dma_addr_t dma;
+       u32 length;
+       u32 tx_flags;
+       struct sk_buff *skb;
+       u32 bytecount;
        u16 gso_segs;
-       u8 mapped_as_page;
 };
 
 struct ixgbe_rx_buffer {
@@ -206,6 +210,7 @@ enum ixbge_ring_state_t {
 #define clear_ring_rsc_enabled(ring) \
        clear_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state)
 struct ixgbe_ring {
+       struct ixgbe_ring *next;        /* pointer to next ring in q_vector */
        void *desc;                     /* descriptor ring memory */
        struct device *dev;             /* device for DMA mapping */
        struct net_device *netdev;      /* netdev ring belongs to */
@@ -274,11 +279,7 @@ struct ixgbe_ring_feature {
 } ____cacheline_internodealigned_in_smp;
 
 struct ixgbe_ring_container {
-#if MAX_RX_QUEUES > MAX_TX_QUEUES
-       DECLARE_BITMAP(idx, MAX_RX_QUEUES);
-#else
-       DECLARE_BITMAP(idx, MAX_TX_QUEUES);
-#endif
+       struct ixgbe_ring *ring;        /* pointer to linked list of rings */
        unsigned int total_bytes;       /* total bytes processed this int */
        unsigned int total_packets;     /* total packets processed this int */
        u16 work_limit;                 /* total work allowed per interrupt */
similarity index 96%
rename from drivers/net/ixgbe/ixgbe_82599.c
rename to drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index 3b3dd4d..f193fc2 100644 (file)
@@ -213,6 +213,7 @@ static s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
        switch (hw->phy.type) {
        case ixgbe_phy_tn:
                phy->ops.check_link = &ixgbe_check_phy_link_tnx;
+               phy->ops.setup_link = &ixgbe_setup_phy_link_tnx;
                phy->ops.get_firmware_version =
                             &ixgbe_get_phy_firmware_version_tnx;
                break;
@@ -1106,79 +1107,6 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
        return 0;
 }
 
-/**
- *  ixgbe_set_fdir_rxpba_82599 - Initialize Flow Director Rx packet buffer
- *  @hw: pointer to hardware structure
- *  @pballoc: which mode to allocate filters with
- **/
-static s32 ixgbe_set_fdir_rxpba_82599(struct ixgbe_hw *hw, const u32 pballoc)
-{
-       u32 fdir_pbsize = hw->mac.rx_pb_size << IXGBE_RXPBSIZE_SHIFT;
-       u32 current_rxpbsize = 0;
-       int i;
-
-       /* reserve space for Flow Director filters */
-       switch (pballoc) {
-       case IXGBE_FDIR_PBALLOC_256K:
-               fdir_pbsize -= 256 << IXGBE_RXPBSIZE_SHIFT;
-               break;
-       case IXGBE_FDIR_PBALLOC_128K:
-               fdir_pbsize -= 128 << IXGBE_RXPBSIZE_SHIFT;
-               break;
-       case IXGBE_FDIR_PBALLOC_64K:
-               fdir_pbsize -= 64 << IXGBE_RXPBSIZE_SHIFT;
-               break;
-       case IXGBE_FDIR_PBALLOC_NONE:
-       default:
-               return IXGBE_ERR_PARAM;
-       }
-
-       /* determine current RX packet buffer size */
-       for (i = 0; i < 8; i++)
-               current_rxpbsize += IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
-
-       /* if there is already room for the filters do nothing */
-       if (current_rxpbsize <= fdir_pbsize)
-               return 0;
-
-       if (current_rxpbsize > hw->mac.rx_pb_size) {
-               /*
-                * if rxpbsize is greater than max then HW max the Rx buffer
-                * sizes are unconfigured or misconfigured since HW default is
-                * to give the full buffer to each traffic class resulting in
-                * the total size being buffer size 8x actual size
-                *
-                * This assumes no DCB since the RXPBSIZE registers appear to
-                * be unconfigured.
-                */
-               IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), fdir_pbsize);
-               for (i = 1; i < 8; i++)
-                       IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
-       } else {
-               /*
-                * Since the Rx packet buffer appears to have already been
-                * configured we need to shrink each packet buffer by enough
-                * to make room for the filters.  As such we take each rxpbsize
-                * value and multiply it by a fraction representing the size
-                * needed over the size we currently have.
-                *
-                * We need to reduce fdir_pbsize and current_rxpbsize to
-                * 1/1024 of their original values in order to avoid
-                * overflowing the u32 being used to store rxpbsize.
-                */
-               fdir_pbsize >>= IXGBE_RXPBSIZE_SHIFT;
-               current_rxpbsize >>= IXGBE_RXPBSIZE_SHIFT;
-               for (i = 0; i < 8; i++) {
-                       u32 rxpbsize = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
-                       rxpbsize *= fdir_pbsize;
-                       rxpbsize /= current_rxpbsize;
-                       IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpbsize);
-               }
-       }
-
-       return 0;
-}
-
 /**
  *  ixgbe_fdir_enable_82599 - Initialize Flow Director control registers
  *  @hw: pointer to hardware structure
@@ -1226,13 +1154,6 @@ static void ixgbe_fdir_enable_82599(struct ixgbe_hw *hw, u32 fdirctrl)
  **/
 s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
 {
-       s32 err;
-
-       /* Before enabling Flow Director, verify the Rx Packet Buffer size */
-       err = ixgbe_set_fdir_rxpba_82599(hw, fdirctrl);
-       if (err)
-               return err;
-
        /*
         * Continue setup of fdirctrl register bits:
         *  Move the flexible bytes to use the ethertype - shift 6 words
@@ -1257,13 +1178,6 @@ s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
  **/
 s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl)
 {
-       s32 err;
-
-       /* Before enabling Flow Director, verify the Rx Packet Buffer size */
-       err = ixgbe_set_fdir_rxpba_82599(hw, fdirctrl);
-       if (err)
-               return err;
-
        /*
         * Continue setup of fdirctrl register bits:
         *  Turn perfect match filtering on
similarity index 99%
rename from drivers/net/ixgbe/ixgbe_common.c
rename to drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 777051f..91986af 100644 (file)
@@ -225,8 +225,9 @@ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
        IXGBE_READ_REG(hw, IXGBE_GORCH);
        IXGBE_READ_REG(hw, IXGBE_GOTCL);
        IXGBE_READ_REG(hw, IXGBE_GOTCH);
-       for (i = 0; i < 8; i++)
-               IXGBE_READ_REG(hw, IXGBE_RNBC(i));
+       if (hw->mac.type == ixgbe_mac_82598EB)
+               for (i = 0; i < 8; i++)
+                       IXGBE_READ_REG(hw, IXGBE_RNBC(i));
        IXGBE_READ_REG(hw, IXGBE_RUC);
        IXGBE_READ_REG(hw, IXGBE_RFC);
        IXGBE_READ_REG(hw, IXGBE_ROC);
@@ -2121,8 +2122,8 @@ static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
         */
 
        linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
-       if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
-           ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+       if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+           (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
                ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
                goto out;
        }
@@ -2632,6 +2633,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
                autoc_reg |= IXGBE_AUTOC_AN_RESTART;
                autoc_reg |= IXGBE_AUTOC_FLU;
                IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+               IXGBE_WRITE_FLUSH(hw);
                usleep_range(10000, 20000);
        }
 
similarity index 99%
rename from drivers/net/ixgbe/ixgbe_dcb_82599.c
rename to drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
index ade9820..d64fb87 100644 (file)
@@ -252,8 +252,10 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en)
                reg &= ~IXGBE_MFLCN_RFCE;
                reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF;
 
-               if (hw->mac.type == ixgbe_mac_X540)
+               if (hw->mac.type == ixgbe_mac_X540) {
+                       reg &= ~IXGBE_MFLCN_RPFCE_MASK;
                        reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT;
+               }
 
                IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
 
similarity index 95%
rename from drivers/net/ixgbe/ixgbe_dcb_nl.c
rename to drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
index 0ace6ce..0422e35 100644 (file)
@@ -118,49 +118,11 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
        if (!!state != !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
                return err;
 
-       if (state > 0) {
-               /* Turn on DCB */
-               if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
-                       e_err(drv, "Enable failed, needs MSI-X\n");
-                       err = 1;
-                       goto out;
-               }
-
-               adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
-
-               switch (adapter->hw.mac.type) {
-               case ixgbe_mac_82598EB:
-                       adapter->last_lfc_mode = adapter->hw.fc.current_mode;
-                       adapter->hw.fc.requested_mode = ixgbe_fc_none;
-                       break;
-               case ixgbe_mac_82599EB:
-               case ixgbe_mac_X540:
-                       adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
-                       break;
-               default:
-                       break;
-               }
-
-               ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
-       } else {
-               /* Turn off DCB */
-               adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
-               adapter->temp_dcb_cfg.pfc_mode_enable = false;
-               adapter->dcb_cfg.pfc_mode_enable = false;
-               adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
-               switch (adapter->hw.mac.type) {
-               case ixgbe_mac_82599EB:
-               case ixgbe_mac_X540:
-                       if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
-                               adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
-                       break;
-               default:
-                       break;
-               }
-               ixgbe_setup_tc(netdev, 0);
-       }
+       if (state > 0)
+               err = ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
+       else
+               err = ixgbe_setup_tc(netdev, 0);
 
-out:
        return err;
 }
 
@@ -414,7 +376,7 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
                u8 prio_tc[MAX_TRAFFIC_CLASS] = {0, 1, 2, 3, 4, 5, 6, 7};
                int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
 
-#ifdef CONFIG_FCOE
+#ifdef IXGBE_FCOE
                if (adapter->netdev->features & NETIF_F_FCOE_MTU)
                        max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
 #endif
similarity index 99%
rename from drivers/net/ixgbe/ixgbe_ethtool.c
rename to drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index dc64955..9c12b35 100644 (file)
@@ -324,12 +324,16 @@ static int ixgbe_set_settings(struct net_device *netdev,
 
        if ((hw->phy.media_type == ixgbe_media_type_copper) ||
            (hw->phy.multispeed_fiber)) {
-               /* 10000/copper and 1000/copper must autoneg
-                * this function does not support any duplex forcing, but can
-                * limit the advertising of the adapter to only 10000 or 1000 */
+               /*
+                * this function does not support duplex forcing, but can
+                * limit the advertising of the adapter to the specified speed
+                */
                if (ecmd->autoneg == AUTONEG_DISABLE)
                        return -EINVAL;
 
+               if (ecmd->advertising & ~ecmd->supported)
+                       return -EINVAL;
+
                old = hw->phy.autoneg_advertised;
                advertised = 0;
                if (ecmd->advertising & ADVERTISED_10000baseT_Full)
@@ -1378,6 +1382,7 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data)
 
        /* Disable all the interrupts */
        IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF);
+       IXGBE_WRITE_FLUSH(&adapter->hw);
        usleep_range(10000, 20000);
 
        /* Test each interrupt */
@@ -1398,6 +1403,7 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data)
                                        ~mask & 0x00007FFF);
                        IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS,
                                        ~mask & 0x00007FFF);
+                       IXGBE_WRITE_FLUSH(&adapter->hw);
                        usleep_range(10000, 20000);
 
                        if (adapter->test_icr & mask) {
@@ -1415,6 +1421,7 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data)
                adapter->test_icr = 0;
                IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
                IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask);
+               IXGBE_WRITE_FLUSH(&adapter->hw);
                usleep_range(10000, 20000);
 
                if (!(adapter->test_icr &mask)) {
@@ -1435,6 +1442,7 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data)
                                        ~mask & 0x00007FFF);
                        IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS,
                                        ~mask & 0x00007FFF);
+                       IXGBE_WRITE_FLUSH(&adapter->hw);
                        usleep_range(10000, 20000);
 
                        if (adapter->test_icr) {
@@ -1446,6 +1454,7 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data)
 
        /* Disable all the interrupts */
        IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF);
+       IXGBE_WRITE_FLUSH(&adapter->hw);
        usleep_range(10000, 20000);
 
        /* Unhook test interrupt handler */
similarity index 99%
rename from drivers/net/ixgbe/ixgbe_fcoe.c
rename to drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index 824edae..e9b992f 100644 (file)
@@ -241,10 +241,12 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
         */
        if (lastsize == bufflen) {
                if (j >= IXGBE_BUFFCNT_MAX) {
-                       e_err(drv, "xid=%x:%d,%d,%d:addr=%llx "
-                               "not enough user buffers. We need an extra "
-                               "buffer because lastsize is bufflen.\n",
-                               xid, i, j, dmacount, (u64)addr);
+                       printk_once("Will NOT use DDP since there are not "
+                                   "enough user buffers. We need an  extra "
+                                   "buffer because lastsize is bufflen. "
+                                   "xid=%x:%d,%d,%d:addr=%llx\n",
+                                   xid, i, j, dmacount, (u64)addr);
+
                        goto out_noddp_free;
                }
 
similarity index 94%
rename from drivers/net/ixgbe/ixgbe_main.c
rename to drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 1be6175..a30f826 100644 (file)
@@ -42,6 +42,7 @@
 #include <net/checksum.h>
 #include <net/ip6_checksum.h>
 #include <linux/ethtool.h>
+#include <linux/if.h>
 #include <linux/if_vlan.h>
 #include <linux/prefetch.h>
 #include <scsi/fc/fc_fcoe.h>
@@ -184,6 +185,7 @@ static inline void ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
        vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
        vmdctl &= ~IXGBE_VT_CTL_POOL_MASK;
        IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl);
+       IXGBE_WRITE_FLUSH(hw);
 
        /* take a breather then clean up driver data */
        msleep(100);
@@ -383,7 +385,7 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
                tx_ring = adapter->tx_ring[n];
                tx_buffer_info =
                        &tx_ring->tx_buffer_info[tx_ring->next_to_clean];
-               pr_info(" %5d %5X %5X %016llX %04X %3X %016llX\n",
+               pr_info(" %5d %5X %5X %016llX %04X %p %016llX\n",
                           n, tx_ring->next_to_use, tx_ring->next_to_clean,
                           (u64)tx_buffer_info->dma,
                           tx_buffer_info->length,
@@ -422,7 +424,7 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
                        tx_buffer_info = &tx_ring->tx_buffer_info[i];
                        u0 = (struct my_u0 *)tx_desc;
                        pr_info("T [0x%03X]    %016llX %016llX %016llX"
-                               " %04X  %3X %016llX %p", i,
+                               " %04X  %p %016llX %p", i,
                                le64_to_cpu(u0->a),
                                le64_to_cpu(u0->b),
                                (u64)tx_buffer_info->dma,
@@ -641,27 +643,31 @@ static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter,
        }
 }
 
-void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *tx_ring,
-                                     struct ixgbe_tx_buffer *tx_buffer_info)
+static inline void ixgbe_unmap_tx_resource(struct ixgbe_ring *ring,
+                                          struct ixgbe_tx_buffer *tx_buffer)
 {
-       if (tx_buffer_info->dma) {
-               if (tx_buffer_info->mapped_as_page)
-                       dma_unmap_page(tx_ring->dev,
-                                      tx_buffer_info->dma,
-                                      tx_buffer_info->length,
-                                      DMA_TO_DEVICE);
+       if (tx_buffer->dma) {
+               if (tx_buffer->tx_flags & IXGBE_TX_FLAGS_MAPPED_AS_PAGE)
+                       dma_unmap_page(ring->dev,
+                                      tx_buffer->dma,
+                                      tx_buffer->length,
+                                      DMA_TO_DEVICE);
                else
-                       dma_unmap_single(tx_ring->dev,
-                                        tx_buffer_info->dma,
-                                        tx_buffer_info->length,
-                                        DMA_TO_DEVICE);
-               tx_buffer_info->dma = 0;
+                       dma_unmap_single(ring->dev,
+                                        tx_buffer->dma,
+                                        tx_buffer->length,
+                                        DMA_TO_DEVICE);
        }
-       if (tx_buffer_info->skb) {
+       tx_buffer->dma = 0;
+}
+
+void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *tx_ring,
+                                     struct ixgbe_tx_buffer *tx_buffer_info)
+{
+       ixgbe_unmap_tx_resource(tx_ring, tx_buffer_info);
+       if (tx_buffer_info->skb)
                dev_kfree_skb_any(tx_buffer_info->skb);
-               tx_buffer_info->skb = NULL;
-       }
-       tx_buffer_info->time_stamp = 0;
+       tx_buffer_info->skb = NULL;
        /* tx_buffer_info must be completely set up in the transmit path */
 }
 
@@ -795,56 +801,72 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
                               struct ixgbe_ring *tx_ring)
 {
        struct ixgbe_adapter *adapter = q_vector->adapter;
-       union ixgbe_adv_tx_desc *tx_desc, *eop_desc;
-       struct ixgbe_tx_buffer *tx_buffer_info;
+       struct ixgbe_tx_buffer *tx_buffer;
+       union ixgbe_adv_tx_desc *tx_desc;
        unsigned int total_bytes = 0, total_packets = 0;
-       u16 i, eop, count = 0;
+       u16 budget = q_vector->tx.work_limit;
+       u16 i = tx_ring->next_to_clean;
 
-       i = tx_ring->next_to_clean;
-       eop = tx_ring->tx_buffer_info[i].next_to_watch;
-       eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
+       tx_buffer = &tx_ring->tx_buffer_info[i];
+       tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
 
-       while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) &&
-              (count < q_vector->tx.work_limit)) {
-               bool cleaned = false;
-               rmb(); /* read buffer_info after eop_desc */
-               for ( ; !cleaned; count++) {
-                       tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
-                       tx_buffer_info = &tx_ring->tx_buffer_info[i];
+       for (; budget; budget--) {
+               union ixgbe_adv_tx_desc *eop_desc = tx_buffer->next_to_watch;
+
+               /* if next_to_watch is not set then there is no work pending */
+               if (!eop_desc)
+                       break;
+
+               /* if DD is not set pending work has not been completed */
+               if (!(eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)))
+                       break;
+
+               /* count the packet as being completed */
+               tx_ring->tx_stats.completed++;
+
+               /* clear next_to_watch to prevent false hangs */
+               tx_buffer->next_to_watch = NULL;
 
+               /* prevent any other reads prior to eop_desc being verified */
+               rmb();
+
+               do {
+                       ixgbe_unmap_tx_resource(tx_ring, tx_buffer);
                        tx_desc->wb.status = 0;
-                       cleaned = (i == eop);
+                       if (likely(tx_desc == eop_desc)) {
+                               eop_desc = NULL;
+                               dev_kfree_skb_any(tx_buffer->skb);
+                               tx_buffer->skb = NULL;
+
+                               total_bytes += tx_buffer->bytecount;
+                               total_packets += tx_buffer->gso_segs;
+                       }
 
+                       tx_buffer++;
+                       tx_desc++;
                        i++;
-                       if (i == tx_ring->count)
+                       if (unlikely(i == tx_ring->count)) {
                                i = 0;
 
-                       if (cleaned && tx_buffer_info->skb) {
-                               total_bytes += tx_buffer_info->bytecount;
-                               total_packets += tx_buffer_info->gso_segs;
+                               tx_buffer = tx_ring->tx_buffer_info;
+                               tx_desc = IXGBE_TX_DESC_ADV(tx_ring, 0);
                        }
 
-                       ixgbe_unmap_and_free_tx_resource(tx_ring,
-                                                        tx_buffer_info);
-               }
-
-               tx_ring->tx_stats.completed++;
-               eop = tx_ring->tx_buffer_info[i].next_to_watch;
-               eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
+               } while (eop_desc);
        }
 
        tx_ring->next_to_clean = i;
+       u64_stats_update_begin(&tx_ring->syncp);
        tx_ring->stats.bytes += total_bytes;
        tx_ring->stats.packets += total_packets;
-       u64_stats_update_begin(&tx_ring->syncp);
+       u64_stats_update_end(&tx_ring->syncp);
        q_vector->tx.total_bytes += total_bytes;
        q_vector->tx.total_packets += total_packets;
-       u64_stats_update_end(&tx_ring->syncp);
 
        if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) {
                /* schedule immediate reset if we believe we hung */
                struct ixgbe_hw *hw = &adapter->hw;
-               tx_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
+               tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
                e_err(drv, "Detected Tx Unit Hang\n"
                        "  Tx Queue             <%d>\n"
                        "  TDH, TDT             <%x>, <%x>\n"
@@ -856,8 +878,8 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
                        tx_ring->queue_index,
                        IXGBE_READ_REG(hw, IXGBE_TDH(tx_ring->reg_idx)),
                        IXGBE_READ_REG(hw, IXGBE_TDT(tx_ring->reg_idx)),
-                       tx_ring->next_to_use, eop,
-                       tx_ring->tx_buffer_info[eop].time_stamp, jiffies);
+                       tx_ring->next_to_use, i,
+                       tx_ring->tx_buffer_info[i].time_stamp, jiffies);
 
                netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
 
@@ -869,11 +891,11 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
                ixgbe_tx_timeout_reset(adapter);
 
                /* the adapter is about to reset, no point in enabling stuff */
-               return true;
+               return budget;
        }
 
 #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
-       if (unlikely(count && netif_carrier_ok(tx_ring->netdev) &&
+       if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) &&
                     (ixgbe_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD))) {
                /* Make sure that anybody stopping the queue after this
                 * sees the new next_to_clean.
@@ -886,7 +908,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
                }
        }
 
-       return count < q_vector->tx.work_limit;
+       return budget;
 }
 
 #ifdef CONFIG_IXGBE_DCA
@@ -952,26 +974,17 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
 static void ixgbe_update_dca(struct ixgbe_q_vector *q_vector)
 {
        struct ixgbe_adapter *adapter = q_vector->adapter;
+       struct ixgbe_ring *ring;
        int cpu = get_cpu();
-       long r_idx;
-       int i;
 
        if (q_vector->cpu == cpu)
                goto out_no_update;
 
-       r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
-       for (i = 0; i < q_vector->tx.count; i++) {
-               ixgbe_update_tx_dca(adapter, adapter->tx_ring[r_idx], cpu);
-               r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
-                                     r_idx + 1);
-       }
+       for (ring = q_vector->tx.ring; ring != NULL; ring = ring->next)
+               ixgbe_update_tx_dca(adapter, ring, cpu);
 
-       r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
-       for (i = 0; i < q_vector->rx.count; i++) {
-               ixgbe_update_rx_dca(adapter, adapter->rx_ring[r_idx], cpu);
-               r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
-                                     r_idx + 1);
-       }
+       for (ring = q_vector->rx.ring; ring != NULL; ring = ring->next)
+               ixgbe_update_rx_dca(adapter, ring, cpu);
 
        q_vector->cpu = cpu;
 out_no_update:
@@ -1005,7 +1018,7 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
        struct ixgbe_adapter *adapter = dev_get_drvdata(dev);
        unsigned long event = *(unsigned long *)data;
 
-       if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED))
+       if (!(adapter->flags & IXGBE_FLAG_DCA_CAPABLE))
                return 0;
 
        switch (event) {
@@ -1458,8 +1471,10 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                if (ixgbe_rx_is_fcoe(adapter, rx_desc)) {
                        ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb,
                                                   staterr);
-                       if (!ddp_bytes)
+                       if (!ddp_bytes) {
+                               dev_kfree_skb_any(skb);
                                goto next_desc;
+                       }
                }
 #endif /* IXGBE_FCOE */
                ixgbe_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc);
@@ -1522,7 +1537,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *, int);
 static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_q_vector *q_vector;
-       int i, q_vectors, v_idx, r_idx;
+       int q_vectors, v_idx;
        u32 mask;
 
        q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
@@ -1532,33 +1547,19 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
         * corresponding register.
         */
        for (v_idx = 0; v_idx < q_vectors; v_idx++) {
+               struct ixgbe_ring *ring;
                q_vector = adapter->q_vector[v_idx];
-               /* XXX for_each_set_bit(...) */
-               r_idx = find_first_bit(q_vector->rx.idx,
-                                      adapter->num_rx_queues);
-
-               for (i = 0; i < q_vector->rx.count; i++) {
-                       u8 reg_idx = adapter->rx_ring[r_idx]->reg_idx;
-                       ixgbe_set_ivar(adapter, 0, reg_idx, v_idx);
-                       r_idx = find_next_bit(q_vector->rx.idx,
-                                             adapter->num_rx_queues,
-                                             r_idx + 1);
-               }
-               r_idx = find_first_bit(q_vector->tx.idx,
-                                      adapter->num_tx_queues);
-
-               for (i = 0; i < q_vector->tx.count; i++) {
-                       u8 reg_idx = adapter->tx_ring[r_idx]->reg_idx;
-                       ixgbe_set_ivar(adapter, 1, reg_idx, v_idx);
-                       r_idx = find_next_bit(q_vector->tx.idx,
-                                             adapter->num_tx_queues,
-                                             r_idx + 1);
-               }
 
-               if (q_vector->tx.count && !q_vector->rx.count)
+               for (ring = q_vector->rx.ring; ring != NULL; ring = ring->next)
+                       ixgbe_set_ivar(adapter, 0, ring->reg_idx, v_idx);
+
+               for (ring = q_vector->tx.ring; ring != NULL; ring = ring->next)
+                       ixgbe_set_ivar(adapter, 1, ring->reg_idx, v_idx);
+
+               if (q_vector->tx.ring && !q_vector->rx.ring)
                        /* tx only */
                        q_vector->eitr = adapter->tx_eitr_param;
-               else if (q_vector->rx.count)
+               else if (q_vector->rx.ring)
                        /* rx or mixed */
                        q_vector->eitr = adapter->rx_eitr_param;
 
@@ -1982,20 +1983,10 @@ static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter,
 static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
 {
        struct ixgbe_q_vector *q_vector = data;
-       struct ixgbe_adapter  *adapter = q_vector->adapter;
-       struct ixgbe_ring     *tx_ring;
-       int i, r_idx;
 
        if (!q_vector->tx.count)
                return IRQ_HANDLED;
 
-       r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
-       for (i = 0; i < q_vector->tx.count; i++) {
-               tx_ring = adapter->tx_ring[r_idx];
-               r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
-                                     r_idx + 1);
-       }
-
        /* EIAM disabled interrupts (on this vector) for us */
        napi_schedule(&q_vector->napi);
 
@@ -2010,22 +2001,6 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
 static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
 {
        struct ixgbe_q_vector *q_vector = data;
-       struct ixgbe_adapter  *adapter = q_vector->adapter;
-       struct ixgbe_ring  *rx_ring;
-       int r_idx;
-       int i;
-
-#ifdef CONFIG_IXGBE_DCA
-       if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
-               ixgbe_update_dca(q_vector);
-#endif
-
-       r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
-       for (i = 0; i < q_vector->rx.count; i++) {
-               rx_ring = adapter->rx_ring[r_idx];
-               r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
-                                     r_idx + 1);
-       }
 
        if (!q_vector->rx.count)
                return IRQ_HANDLED;
@@ -2039,28 +2014,10 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
 static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
 {
        struct ixgbe_q_vector *q_vector = data;
-       struct ixgbe_adapter  *adapter = q_vector->adapter;
-       struct ixgbe_ring  *ring;
-       int r_idx;
-       int i;
 
        if (!q_vector->tx.count && !q_vector->rx.count)
                return IRQ_HANDLED;
 
-       r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
-       for (i = 0; i < q_vector->tx.count; i++) {
-               ring = adapter->tx_ring[r_idx];
-               r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
-                                     r_idx + 1);
-       }
-
-       r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
-       for (i = 0; i < q_vector->rx.count; i++) {
-               ring = adapter->rx_ring[r_idx];
-               r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
-                                     r_idx + 1);
-       }
-
        /* EIAM disabled interrupts (on this vector) for us */
        napi_schedule(&q_vector->napi);
 
@@ -2080,19 +2037,14 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
        struct ixgbe_q_vector *q_vector =
                               container_of(napi, struct ixgbe_q_vector, napi);
        struct ixgbe_adapter *adapter = q_vector->adapter;
-       struct ixgbe_ring *rx_ring = NULL;
        int work_done = 0;
-       long r_idx;
 
 #ifdef CONFIG_IXGBE_DCA
        if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
                ixgbe_update_dca(q_vector);
 #endif
 
-       r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
-       rx_ring = adapter->rx_ring[r_idx];
-
-       ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget);
+       ixgbe_clean_rx_irq(q_vector, q_vector->rx.ring, &work_done, budget);
 
        /* If all Rx work done, exit the polling mode */
        if (work_done < budget) {
@@ -2120,38 +2072,29 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
        struct ixgbe_q_vector *q_vector =
                               container_of(napi, struct ixgbe_q_vector, napi);
        struct ixgbe_adapter *adapter = q_vector->adapter;
-       struct ixgbe_ring *ring = NULL;
-       int work_done = 0, i;
-       long r_idx;
-       bool tx_clean_complete = true;
+       struct ixgbe_ring *ring;
+       int work_done = 0;
+       bool clean_complete = true;
 
 #ifdef CONFIG_IXGBE_DCA
        if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
                ixgbe_update_dca(q_vector);
 #endif
 
-       r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
-       for (i = 0; i < q_vector->tx.count; i++) {
-               ring = adapter->tx_ring[r_idx];
-               tx_clean_complete &= ixgbe_clean_tx_irq(q_vector, ring);
-               r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
-                                     r_idx + 1);
-       }
+       for (ring = q_vector->tx.ring; ring != NULL; ring = ring->next)
+               clean_complete &= ixgbe_clean_tx_irq(q_vector, ring);
 
        /* attempt to distribute budget to each queue fairly, but don't allow
         * the budget to go below 1 because we'll exit polling */
        budget /= (q_vector->rx.count ?: 1);
        budget = max(budget, 1);
-       r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
-       for (i = 0; i < q_vector->rx.count; i++) {
-               ring = adapter->rx_ring[r_idx];
+
+       for (ring = q_vector->rx.ring; ring != NULL; ring = ring->next)
                ixgbe_clean_rx_irq(q_vector, ring, &work_done, budget);
-               r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
-                                     r_idx + 1);
-       }
 
-       r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
-       ring = adapter->rx_ring[r_idx];
+       if (!clean_complete)
+               work_done = budget;
+
        /* If all Rx work done, exit the polling mode */
        if (work_done < budget) {
                napi_complete(napi);
@@ -2179,32 +2122,23 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
        struct ixgbe_q_vector *q_vector =
                               container_of(napi, struct ixgbe_q_vector, napi);
        struct ixgbe_adapter *adapter = q_vector->adapter;
-       struct ixgbe_ring *tx_ring = NULL;
-       int work_done = 0;
-       long r_idx;
 
 #ifdef CONFIG_IXGBE_DCA
        if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
                ixgbe_update_dca(q_vector);
 #endif
 
-       r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
-       tx_ring = adapter->tx_ring[r_idx];
-
-       if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
-               work_done = budget;
+       if (!ixgbe_clean_tx_irq(q_vector, q_vector->tx.ring))
+               return budget;
 
        /* If all Tx work done, exit the polling mode */
-       if (work_done < budget) {
-               napi_complete(napi);
-               if (adapter->tx_itr_setting & 1)
-                       ixgbe_set_itr(q_vector);
-               if (!test_bit(__IXGBE_DOWN, &adapter->state))
-                       ixgbe_irq_enable_queues(adapter,
-                                               ((u64)1 << q_vector->v_idx));
-       }
+       napi_complete(napi);
+       if (adapter->tx_itr_setting & 1)
+               ixgbe_set_itr(q_vector);
+       if (!test_bit(__IXGBE_DOWN, &adapter->state))
+               ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
 
-       return work_done;
+       return 0;
 }
 
 static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
@@ -2213,9 +2147,10 @@ static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
        struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
        struct ixgbe_ring *rx_ring = a->rx_ring[r_idx];
 
-       set_bit(r_idx, q_vector->rx.idx);
-       q_vector->rx.count++;
        rx_ring->q_vector = q_vector;
+       rx_ring->next = q_vector->rx.ring;
+       q_vector->rx.ring = rx_ring;
+       q_vector->rx.count++;
 }
 
 static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
@@ -2224,9 +2159,10 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
        struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
        struct ixgbe_ring *tx_ring = a->tx_ring[t_idx];
 
-       set_bit(t_idx, q_vector->tx.idx);
-       q_vector->tx.count++;
        tx_ring->q_vector = q_vector;
+       tx_ring->next = q_vector->tx.ring;
+       q_vector->tx.ring = tx_ring;
+       q_vector->tx.count++;
        q_vector->tx.work_limit = a->tx_work_limit;
 }
 
@@ -2484,14 +2420,26 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
 
 static inline void ixgbe_reset_q_vectors(struct ixgbe_adapter *adapter)
 {
-       int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+       int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+       int i;
+
+       /* legacy and MSI only use one vector */
+       if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
+               q_vectors = 1;
+
+       for (i = 0; i < adapter->num_rx_queues; i++) {
+               adapter->rx_ring[i]->q_vector = NULL;
+               adapter->rx_ring[i]->next = NULL;
+       }
+       for (i = 0; i < adapter->num_tx_queues; i++) {
+               adapter->tx_ring[i]->q_vector = NULL;
+               adapter->tx_ring[i]->next = NULL;
+       }
 
        for (i = 0; i < q_vectors; i++) {
                struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
-               bitmap_zero(q_vector->rx.idx, MAX_RX_QUEUES);
-               bitmap_zero(q_vector->tx.idx, MAX_TX_QUEUES);
-               q_vector->rx.count = 0;
-               q_vector->tx.count = 0;
+               memset(&q_vector->rx, 0, sizeof(struct ixgbe_ring_container));
+               memset(&q_vector->tx, 0, sizeof(struct ixgbe_ring_container));
        }
 }
 
@@ -3593,7 +3541,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
 
        /* reconfigure the hardware */
        if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE) {
-#ifdef CONFIG_FCOE
+#ifdef IXGBE_FCOE
                if (adapter->netdev->features & NETIF_F_FCOE_MTU)
                        max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
 #endif
@@ -4533,7 +4481,7 @@ static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
-               if (num_tcs == 8) {
+               if (num_tcs > 4) {
                        if (tc < 3) {
                                *tx = tc << 5;
                                *rx = tc << 4;
@@ -4544,7 +4492,7 @@ static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc,
                                *tx = ((tc + 8) << 3);
                                *rx = tc << 4;
                        }
-               } else if (num_tcs == 4) {
+               } else {
                        *rx =  tc << 5;
                        switch (tc) {
                        case 0:
@@ -5899,7 +5847,7 @@ static void ixgbe_check_hang_subtask(struct ixgbe_adapter *adapter)
                /* get one bit for every active tx/rx interrupt vector */
                for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
                        struct ixgbe_q_vector *qv = adapter->q_vector[i];
-                       if (qv->rx.count || qv->tx.count)
+                       if (qv->rx.ring || qv->tx.ring)
                                eics |= ((u64)1 << i);
                }
        }
@@ -6347,7 +6295,8 @@ static bool ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
        u32 type_tucmd = 0;
 
        if (skb->ip_summed != CHECKSUM_PARTIAL) {
-           if (!(tx_flags & IXGBE_TX_FLAGS_VLAN))
+           if (!(tx_flags & IXGBE_TX_FLAGS_HW_VLAN) &&
+               !(tx_flags & IXGBE_TX_FLAGS_TXSW))
                        return false;
        } else {
                u8 l4_hdr = 0;
@@ -6404,185 +6353,186 @@ static bool ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
        return (skb->ip_summed == CHECKSUM_PARTIAL);
 }
 
-static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
-                       struct ixgbe_ring *tx_ring,
-                       struct sk_buff *skb, u32 tx_flags,
-                       unsigned int first, const u8 hdr_len)
+static __le32 ixgbe_tx_cmd_type(u32 tx_flags)
 {
-       struct device *dev = tx_ring->dev;
-       struct ixgbe_tx_buffer *tx_buffer_info;
-       unsigned int len;
-       unsigned int total = skb->len;
-       unsigned int offset = 0, size, count = 0;
-       unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
-       unsigned int f;
-       unsigned int bytecount = skb->len;
-       u16 gso_segs = 1;
-       u16 i;
+       /* set type for advanced descriptor with frame checksum insertion */
+       __le32 cmd_type = cpu_to_le32(IXGBE_ADVTXD_DTYP_DATA |
+                                     IXGBE_ADVTXD_DCMD_IFCS |
+                                     IXGBE_ADVTXD_DCMD_DEXT);
 
-       i = tx_ring->next_to_use;
+       /* set HW vlan bit if vlan is present */
+       if (tx_flags & IXGBE_TX_FLAGS_HW_VLAN)
+               cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_VLE);
 
-       if (tx_flags & IXGBE_TX_FLAGS_FCOE)
-               /* excluding fcoe_crc_eof for FCoE */
-               total -= sizeof(struct fcoe_crc_eof);
+       /* set segmentation enable bits for TSO/FSO */
+#ifdef IXGBE_FCOE
+       if ((tx_flags & IXGBE_TX_FLAGS_TSO) || (tx_flags & IXGBE_TX_FLAGS_FSO))
+#else
+       if (tx_flags & IXGBE_TX_FLAGS_TSO)
+#endif
+               cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_TSE);
 
-       len = min(skb_headlen(skb), total);
-       while (len) {
-               tx_buffer_info = &tx_ring->tx_buffer_info[i];
-               size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD);
-
-               tx_buffer_info->length = size;
-               tx_buffer_info->mapped_as_page = false;
-               tx_buffer_info->dma = dma_map_single(dev,
-                                                    skb->data + offset,
-                                                    size, DMA_TO_DEVICE);
-               if (dma_mapping_error(dev, tx_buffer_info->dma))
-                       goto dma_error;
-               tx_buffer_info->time_stamp = jiffies;
-               tx_buffer_info->next_to_watch = i;
+       return cmd_type;
+}
 
-               len -= size;
-               total -= size;
-               offset += size;
-               count++;
+static __le32 ixgbe_tx_olinfo_status(u32 tx_flags, unsigned int paylen)
+{
+       __le32 olinfo_status =
+               cpu_to_le32(paylen << IXGBE_ADVTXD_PAYLEN_SHIFT);
 
-               if (len) {
-                       i++;
-                       if (i == tx_ring->count)
-                               i = 0;
-               }
+       if (tx_flags & IXGBE_TX_FLAGS_TSO) {
+               olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_POPTS_TXSM |
+                                           (1 << IXGBE_ADVTXD_IDX_SHIFT));
+               /* enble IPv4 checksum for TSO */
+               if (tx_flags & IXGBE_TX_FLAGS_IPV4)
+                       olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_POPTS_IXSM);
        }
 
-       for (f = 0; f < nr_frags; f++) {
-               struct skb_frag_struct *frag;
-
-               frag = &skb_shinfo(skb)->frags[f];
-               len = min((unsigned int)frag->size, total);
-               offset = frag->page_offset;
-
-               while (len) {
-                       i++;
-                       if (i == tx_ring->count)
-                               i = 0;
+       /* enable L4 checksum for TSO and TX checksum offload */
+       if (tx_flags & IXGBE_TX_FLAGS_CSUM)
+               olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_POPTS_TXSM);
 
-                       tx_buffer_info = &tx_ring->tx_buffer_info[i];
-                       size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD);
-
-                       tx_buffer_info->length = size;
-                       tx_buffer_info->dma = dma_map_page(dev,
-                                                          frag->page,
-                                                          offset, size,
-                                                          DMA_TO_DEVICE);
-                       tx_buffer_info->mapped_as_page = true;
-                       if (dma_mapping_error(dev, tx_buffer_info->dma))
-                               goto dma_error;
-                       tx_buffer_info->time_stamp = jiffies;
-                       tx_buffer_info->next_to_watch = i;
-
-                       len -= size;
-                       total -= size;
-                       offset += size;
-                       count++;
-               }
-               if (total == 0)
-                       break;
-       }
-
-       if (tx_flags & IXGBE_TX_FLAGS_TSO)
-               gso_segs = skb_shinfo(skb)->gso_segs;
 #ifdef IXGBE_FCOE
-       /* adjust for FCoE Sequence Offload */
-       else if (tx_flags & IXGBE_TX_FLAGS_FSO)
-               gso_segs = DIV_ROUND_UP(skb->len - hdr_len,
-                                       skb_shinfo(skb)->gso_size);
-#endif /* IXGBE_FCOE */
-       bytecount += (gso_segs - 1) * hdr_len;
+       /* use index 1 context for FCOE/FSO */
+       if (tx_flags & IXGBE_TX_FLAGS_FCOE)
+               olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_CC |
+                                           (1 << IXGBE_ADVTXD_IDX_SHIFT));
 
-       /* multiply data chunks by size of headers */
-       tx_ring->tx_buffer_info[i].bytecount = bytecount;
-       tx_ring->tx_buffer_info[i].gso_segs = gso_segs;
-       tx_ring->tx_buffer_info[i].skb = skb;
-       tx_ring->tx_buffer_info[first].next_to_watch = i;
+#endif
+       /*
+        * Check Context must be set if Tx switch is enabled, which it
+        * always is for case where virtual functions are running
+        */
+       if (tx_flags & IXGBE_TX_FLAGS_TXSW)
+               olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_CC);
 
-       return count;
+       return olinfo_status;
+}
 
-dma_error:
-       e_dev_err("TX DMA map failed\n");
+#define IXGBE_TXD_CMD (IXGBE_TXD_CMD_EOP | \
+                      IXGBE_TXD_CMD_RS)
 
-       /* clear timestamp and dma mappings for failed tx_buffer_info map */
-       tx_buffer_info->dma = 0;
-       tx_buffer_info->time_stamp = 0;
-       tx_buffer_info->next_to_watch = 0;
-       if (count)
-               count--;
+static void ixgbe_tx_map(struct ixgbe_ring *tx_ring,
+                        struct sk_buff *skb,
+                        struct ixgbe_tx_buffer *first,
+                        u32 tx_flags,
+                        const u8 hdr_len)
+{
+       struct device *dev = tx_ring->dev;
+       struct ixgbe_tx_buffer *tx_buffer_info;
+       union ixgbe_adv_tx_desc *tx_desc;
+       dma_addr_t dma;
+       __le32 cmd_type, olinfo_status;
+       struct skb_frag_struct *frag;
+       unsigned int f = 0;
+       unsigned int data_len = skb->data_len;
+       unsigned int size = skb_headlen(skb);
+       u32 offset = 0;
+       u32 paylen = skb->len - hdr_len;
+       u16 i = tx_ring->next_to_use;
+       u16 gso_segs;
 
-       /* clear timestamp and dma mappings for remaining portion of packet */
-       while (count--) {
-               if (i == 0)
-                       i += tx_ring->count;
-               i--;
-               tx_buffer_info = &tx_ring->tx_buffer_info[i];
-               ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
+#ifdef IXGBE_FCOE
+       if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
+               if (data_len >= sizeof(struct fcoe_crc_eof)) {
+                       data_len -= sizeof(struct fcoe_crc_eof);
+               } else {
+                       size -= sizeof(struct fcoe_crc_eof) - data_len;
+                       data_len = 0;
+               }
        }
 
-       return 0;
-}
+#endif
+       dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, dma))
+               goto dma_error;
 
-static void ixgbe_tx_queue(struct ixgbe_ring *tx_ring,
-                          int tx_flags, int count, u32 paylen, u8 hdr_len)
-{
-       union ixgbe_adv_tx_desc *tx_desc = NULL;
-       struct ixgbe_tx_buffer *tx_buffer_info;
-       u32 olinfo_status = 0, cmd_type_len = 0;
-       unsigned int i;
-       u32 txd_cmd = IXGBE_TXD_CMD_EOP | IXGBE_TXD_CMD_RS | IXGBE_TXD_CMD_IFCS;
+       cmd_type = ixgbe_tx_cmd_type(tx_flags);
+       olinfo_status = ixgbe_tx_olinfo_status(tx_flags, paylen);
 
-       cmd_type_len |= IXGBE_ADVTXD_DTYP_DATA;
+       tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
 
-       cmd_type_len |= IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT;
+       for (;;) {
+               while (size > IXGBE_MAX_DATA_PER_TXD) {
+                       tx_desc->read.buffer_addr = cpu_to_le64(dma + offset);
+                       tx_desc->read.cmd_type_len =
+                               cmd_type | cpu_to_le32(IXGBE_MAX_DATA_PER_TXD);
+                       tx_desc->read.olinfo_status = olinfo_status;
 
-       if (tx_flags & IXGBE_TX_FLAGS_VLAN)
-               cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE;
+                       offset += IXGBE_MAX_DATA_PER_TXD;
+                       size -= IXGBE_MAX_DATA_PER_TXD;
 
-       if (tx_flags & IXGBE_TX_FLAGS_TSO) {
-               cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
+                       tx_desc++;
+                       i++;
+                       if (i == tx_ring->count) {
+                               tx_desc = IXGBE_TX_DESC_ADV(tx_ring, 0);
+                               i = 0;
+                       }
+               }
 
-               olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
-                                IXGBE_ADVTXD_POPTS_SHIFT;
+               tx_buffer_info = &tx_ring->tx_buffer_info[i];
+               tx_buffer_info->length = offset + size;
+               tx_buffer_info->tx_flags = tx_flags;
+               tx_buffer_info->dma = dma;
 
-               /* use index 1 context for tso */
-               olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
-               if (tx_flags & IXGBE_TX_FLAGS_IPV4)
-                       olinfo_status |= IXGBE_TXD_POPTS_IXSM <<
-                                        IXGBE_ADVTXD_POPTS_SHIFT;
+               tx_desc->read.buffer_addr = cpu_to_le64(dma + offset);
+               tx_desc->read.cmd_type_len = cmd_type | cpu_to_le32(size);
+               tx_desc->read.olinfo_status = olinfo_status;
 
-       } else if (tx_flags & IXGBE_TX_FLAGS_CSUM)
-               olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
-                                IXGBE_ADVTXD_POPTS_SHIFT;
+               if (!data_len)
+                       break;
 
-       if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
-               olinfo_status |= IXGBE_ADVTXD_CC;
-               olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
-               if (tx_flags & IXGBE_TX_FLAGS_FSO)
-                       cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
-       }
+               frag = &skb_shinfo(skb)->frags[f];
+#ifdef IXGBE_FCOE
+               size = min_t(unsigned int, data_len, frag->size);
+#else
+               size = frag->size;
+#endif
+               data_len -= size;
+               f++;
 
-       olinfo_status |= ((paylen - hdr_len) << IXGBE_ADVTXD_PAYLEN_SHIFT);
+               offset = 0;
+               tx_flags |= IXGBE_TX_FLAGS_MAPPED_AS_PAGE;
 
-       i = tx_ring->next_to_use;
-       while (count--) {
-               tx_buffer_info = &tx_ring->tx_buffer_info[i];
-               tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
-               tx_desc->read.buffer_addr = cpu_to_le64(tx_buffer_info->dma);
-               tx_desc->read.cmd_type_len =
-                       cpu_to_le32(cmd_type_len | tx_buffer_info->length);
-               tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
+               dma = dma_map_page(dev, frag->page, frag->page_offset,
+                                  size, DMA_TO_DEVICE);
+               if (dma_mapping_error(dev, dma))
+                       goto dma_error;
+
+               tx_desc++;
                i++;
-               if (i == tx_ring->count)
+               if (i == tx_ring->count) {
+                       tx_desc = IXGBE_TX_DESC_ADV(tx_ring, 0);
                        i = 0;
+               }
        }
 
-       tx_desc->read.cmd_type_len |= cpu_to_le32(txd_cmd);
+       tx_desc->read.cmd_type_len |= cpu_to_le32(IXGBE_TXD_CMD);
+
+       i++;
+       if (i == tx_ring->count)
+               i = 0;
+
+       tx_ring->next_to_use = i;
+
+       if (tx_flags & IXGBE_TX_FLAGS_TSO)
+               gso_segs = skb_shinfo(skb)->gso_segs;
+#ifdef IXGBE_FCOE
+       /* adjust for FCoE Sequence Offload */
+       else if (tx_flags & IXGBE_TX_FLAGS_FSO)
+               gso_segs = DIV_ROUND_UP(skb->len - hdr_len,
+                                       skb_shinfo(skb)->gso_size);
+#endif /* IXGBE_FCOE */
+       else
+               gso_segs = 1;
+
+       /* multiply data chunks by size of headers */
+       tx_buffer_info->bytecount = paylen + (gso_segs * hdr_len);
+       tx_buffer_info->gso_segs = gso_segs;
+       tx_buffer_info->skb = skb;
+
+       /* set the timestamp */
+       first->time_stamp = jiffies;
 
        /*
         * Force memory writes to complete before letting h/w
@@ -6592,8 +6542,30 @@ static void ixgbe_tx_queue(struct ixgbe_ring *tx_ring,
         */
        wmb();
 
-       tx_ring->next_to_use = i;
+       /* set next_to_watch value indicating a packet is present */
+       first->next_to_watch = tx_desc;
+
+       /* notify HW of packet */
        writel(i, tx_ring->tail);
+
+       return;
+dma_error:
+       dev_err(dev, "TX DMA map failed\n");
+
+       /* clear dma mappings for failed tx_buffer_info map */
+       for (;;) {
+               tx_buffer_info = &tx_ring->tx_buffer_info[i];
+               ixgbe_unmap_tx_resource(tx_ring, tx_buffer_info);
+               if (tx_buffer_info == first)
+                       break;
+               if (i == 0)
+                       i = tx_ring->count;
+               i--;
+       }
+
+       dev_kfree_skb_any(skb);
+
+       tx_ring->next_to_use = i;
 }
 
 static void ixgbe_atr(struct ixgbe_ring *ring, struct sk_buff *skb,
@@ -6632,8 +6604,8 @@ static void ixgbe_atr(struct ixgbe_ring *ring, struct sk_buff *skb,
 
        th = tcp_hdr(skb);
 
-       /* skip this packet since the socket is closing */
-       if (th->fin)
+       /* skip this packet since it is invalid or the socket is closing */
+       if (!th || th->fin)
                return;
 
        /* sample on all syn packets or once every atr sample count */
@@ -6658,7 +6630,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring, struct sk_buff *skb,
         * since src port and flex bytes occupy the same word XOR them together
         * and write the value to source port portion of compressed dword
         */
-       if (vlan_id)
+       if (tx_flags & (IXGBE_TX_FLAGS_SW_VLAN | IXGBE_TX_FLAGS_HW_VLAN))
                common.port.src ^= th->dest ^ __constant_htons(ETH_P_8021Q);
        else
                common.port.src ^= th->dest ^ protocol;
@@ -6740,14 +6712,14 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
                          struct ixgbe_adapter *adapter,
                          struct ixgbe_ring *tx_ring)
 {
+       struct ixgbe_tx_buffer *first;
        int tso;
-       u32  tx_flags = 0;
+       u32 tx_flags = 0;
 #if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
        unsigned short f;
 #endif
-       u16 first;
        u16 count = TXD_USE_COUNT(skb_headlen(skb));
-       __be16 protocol;
+       __be16 protocol = skb->protocol;
        u8 hdr_len = 0;
 
        /*
@@ -6768,68 +6740,88 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
                return NETDEV_TX_BUSY;
        }
 
-       protocol = vlan_get_protocol(skb);
+#ifdef CONFIG_PCI_IOV
+       if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+               tx_flags |= IXGBE_TX_FLAGS_TXSW;
 
+#endif
+       /* if we have a HW VLAN tag being added default to the HW one */
        if (vlan_tx_tag_present(skb)) {
-               tx_flags |= vlan_tx_tag_get(skb);
-               if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-                       tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK;
-                       tx_flags |= tx_ring->dcb_tc << 13;
+               tx_flags |= vlan_tx_tag_get(skb) << IXGBE_TX_FLAGS_VLAN_SHIFT;
+               tx_flags |= IXGBE_TX_FLAGS_HW_VLAN;
+       /* else if it is a SW VLAN check the next protocol and store the tag */
+       } else if (protocol == __constant_htons(ETH_P_8021Q)) {
+               struct vlan_hdr *vhdr, _vhdr;
+               vhdr = skb_header_pointer(skb, ETH_HLEN, sizeof(_vhdr), &_vhdr);
+               if (!vhdr)
+                       goto out_drop;
+
+               protocol = vhdr->h_vlan_encapsulated_proto;
+               tx_flags |= ntohs(vhdr->h_vlan_TCI) << IXGBE_TX_FLAGS_VLAN_SHIFT;
+               tx_flags |= IXGBE_TX_FLAGS_SW_VLAN;
+       }
+
+       if ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
+           ((tx_flags & (IXGBE_TX_FLAGS_HW_VLAN | IXGBE_TX_FLAGS_SW_VLAN)) ||
+            (skb->priority != TC_PRIO_CONTROL))) {
+               tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK;
+               tx_flags |= tx_ring->dcb_tc <<
+                           IXGBE_TX_FLAGS_VLAN_PRIO_SHIFT;
+               if (tx_flags & IXGBE_TX_FLAGS_SW_VLAN) {
+                       struct vlan_ethhdr *vhdr;
+                       if (skb_header_cloned(skb) &&
+                           pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+                               goto out_drop;
+                       vhdr = (struct vlan_ethhdr *)skb->data;
+                       vhdr->h_vlan_TCI = htons(tx_flags >>
+                                                IXGBE_TX_FLAGS_VLAN_SHIFT);
+               } else {
+                       tx_flags |= IXGBE_TX_FLAGS_HW_VLAN;
                }
-               tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
-               tx_flags |= IXGBE_TX_FLAGS_VLAN;
-       } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED &&
-                  skb->priority != TC_PRIO_CONTROL) {
-               tx_flags |= tx_ring->dcb_tc << 13;
-               tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
-               tx_flags |= IXGBE_TX_FLAGS_VLAN;
        }
 
-#ifdef IXGBE_FCOE
-       /* for FCoE with DCB, we force the priority to what
-        * was specified by the switch */
-       if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED &&
-           (protocol == htons(ETH_P_FCOE)))
-               tx_flags |= IXGBE_TX_FLAGS_FCOE;
-
-#endif
        /* record the location of the first descriptor for this packet */
-       first = tx_ring->next_to_use;
+       first = &tx_ring->tx_buffer_info[tx_ring->next_to_use];
 
-       if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
 #ifdef IXGBE_FCOE
-               /* setup tx offload for FCoE */
+       /* setup tx offload for FCoE */
+       if ((protocol == __constant_htons(ETH_P_FCOE)) &&
+           (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) {
                tso = ixgbe_fso(tx_ring, skb, tx_flags, &hdr_len);
                if (tso < 0)
                        goto out_drop;
                else if (tso)
-                       tx_flags |= IXGBE_TX_FLAGS_FSO;
-#endif /* IXGBE_FCOE */
-       } else {
-               if (protocol == htons(ETH_P_IP))
-                       tx_flags |= IXGBE_TX_FLAGS_IPV4;
-               tso = ixgbe_tso(tx_ring, skb, tx_flags, protocol, &hdr_len);
-               if (tso < 0)
-                       goto out_drop;
-               else if (tso)
-                       tx_flags |= IXGBE_TX_FLAGS_TSO;
-               else if (ixgbe_tx_csum(tx_ring, skb, tx_flags, protocol))
-                       tx_flags |= IXGBE_TX_FLAGS_CSUM;
+                       tx_flags |= IXGBE_TX_FLAGS_FSO |
+                                   IXGBE_TX_FLAGS_FCOE;
+               else
+                       tx_flags |= IXGBE_TX_FLAGS_FCOE;
+
+               goto xmit_fcoe;
        }
 
-       count = ixgbe_tx_map(adapter, tx_ring, skb, tx_flags, first, hdr_len);
-       if (count) {
-               /* add the ATR filter if ATR is on */
-               if (test_bit(__IXGBE_TX_FDIR_INIT_DONE, &tx_ring->state))
-                       ixgbe_atr(tx_ring, skb, tx_flags, protocol);
-               ixgbe_tx_queue(tx_ring, tx_flags, count, skb->len, hdr_len);
-               ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED);
+#endif /* IXGBE_FCOE */
+       /* setup IPv4/IPv6 offloads */
+       if (protocol == __constant_htons(ETH_P_IP))
+               tx_flags |= IXGBE_TX_FLAGS_IPV4;
 
-       } else {
-               tx_ring->tx_buffer_info[first].time_stamp = 0;
-               tx_ring->next_to_use = first;
+       tso = ixgbe_tso(tx_ring, skb, tx_flags, protocol, &hdr_len);
+       if (tso < 0)
                goto out_drop;
-       }
+       else if (tso)
+               tx_flags |= IXGBE_TX_FLAGS_TSO;
+       else if (ixgbe_tx_csum(tx_ring, skb, tx_flags, protocol))
+               tx_flags |= IXGBE_TX_FLAGS_CSUM;
+
+       /* add the ATR filter if ATR is on */
+       if (test_bit(__IXGBE_TX_FDIR_INIT_DONE, &tx_ring->state))
+               ixgbe_atr(tx_ring, skb, tx_flags, protocol);
+
+#ifdef IXGBE_FCOE
+xmit_fcoe:
+#endif /* IXGBE_FCOE */
+       ixgbe_tx_map(tx_ring, skb, first, tx_flags, hdr_len);
+
+       ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED);
 
        return NETDEV_TX_OK;
 
@@ -7073,11 +7065,11 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
        struct ixgbe_adapter *adapter = netdev_priv(dev);
        struct ixgbe_hw *hw = &adapter->hw;
 
-       /* If DCB is anabled do not remove traffic classes, multiple
-        * traffic classes are required to implement DCB
-        */
-       if (!tc && (adapter->flags & IXGBE_FLAG_DCB_ENABLED))
-               return 0;
+       /* Multiple traffic classes requires multiple queues */
+       if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
+               e_err(drv, "Enable failed, needs MSI-X\n");
+               return -EINVAL;
+       }
 
        /* Hardware supports up to 8 traffic classes */
        if (tc > MAX_TRAFFIC_CLASS ||
@@ -7092,11 +7084,27 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
                ixgbe_close(dev);
        ixgbe_clear_interrupt_scheme(adapter);
 
-       if (tc)
+       if (tc) {
                netdev_set_num_tc(dev, tc);
-       else
+               adapter->last_lfc_mode = adapter->hw.fc.current_mode;
+
+               adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
+               adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
+
+               if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+                       adapter->hw.fc.requested_mode = ixgbe_fc_none;
+       } else {
                netdev_reset_tc(dev);
 
+               adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
+
+               adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
+               adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+
+               adapter->temp_dcb_cfg.pfc_mode_enable = false;
+               adapter->dcb_cfg.pfc_mode_enable = false;
+       }
+
        ixgbe_init_interrupt_scheme(adapter);
        ixgbe_validate_rtr(adapter, tc);
        if (netif_running(dev))
@@ -7203,7 +7211,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_start_xmit         = ixgbe_xmit_frame,
        .ndo_select_queue       = ixgbe_select_queue,
        .ndo_set_rx_mode        = ixgbe_set_rx_mode,
-       .ndo_set_multicast_list = ixgbe_set_rx_mode,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ixgbe_set_mac,
        .ndo_change_mtu         = ixgbe_change_mtu,
@@ -7503,7 +7510,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
                           NETIF_F_HW_VLAN_FILTER |
                           NETIF_F_TSO |
                           NETIF_F_TSO6 |
-                          NETIF_F_GRO |
                           NETIF_F_RXHASH |
                           NETIF_F_RXCSUM;
 
@@ -7526,6 +7532,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        netdev->vlan_features |= NETIF_F_IPV6_CSUM;
        netdev->vlan_features |= NETIF_F_SG;
 
+       netdev->priv_flags |= IFF_UNICAST_FLT;
+
        if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
                adapter->flags &= ~(IXGBE_FLAG_RSS_ENABLED |
                                    IXGBE_FLAG_DCB_ENABLED);
similarity index 99%
rename from drivers/net/ixgbe/ixgbe_phy.c
rename to drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index 735f686..f7ca351 100644 (file)
@@ -1585,6 +1585,7 @@ static s32 ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
        *i2cctl |= IXGBE_I2C_CLK_OUT;
 
        IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl);
+       IXGBE_WRITE_FLUSH(hw);
 
        /* SCL rise time (1000ns) */
        udelay(IXGBE_I2C_T_RISE);
@@ -1605,6 +1606,7 @@ static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
        *i2cctl &= ~IXGBE_I2C_CLK_OUT;
 
        IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl);
+       IXGBE_WRITE_FLUSH(hw);
 
        /* SCL fall time (300ns) */
        udelay(IXGBE_I2C_T_FALL);
@@ -1628,6 +1630,7 @@ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
                *i2cctl &= ~IXGBE_I2C_DATA_OUT;
 
        IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl);
+       IXGBE_WRITE_FLUSH(hw);
 
        /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
        udelay(IXGBE_I2C_T_RISE + IXGBE_I2C_T_FALL + IXGBE_I2C_T_SU_DATA);
similarity index 99%
rename from drivers/net/ixgbe/ixgbe_type.h
rename to drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index e0d970e..9f618ee 100644 (file)
@@ -1834,6 +1834,7 @@ enum {
 #define IXGBE_MFLCN_DPF         0x00000002 /* Discard Pause Frame */
 #define IXGBE_MFLCN_RPFCE       0x00000004 /* Receive Priority FC Enable */
 #define IXGBE_MFLCN_RFCE        0x00000008 /* Receive FC Enable */
+#define IXGBE_MFLCN_RPFCE_MASK 0x00000FE0 /* Receive FC Mask */
 
 #define IXGBE_MFLCN_RPFCE_SHIFT                 4
 
similarity index 99%
rename from drivers/net/ixgbe/ixgbe_x540.c
rename to drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index bec30ed..2696c78 100644 (file)
@@ -162,6 +162,7 @@ mac_reset_top:
        ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
        ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
        IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
+       IXGBE_WRITE_FLUSH(hw);
 
        msleep(50);
 
similarity index 94%
rename from drivers/net/ixgbevf/ethtool.c
rename to drivers/net/ethernet/intel/ixgbevf/ethtool.c
index deee375..e1d9e3b 100644 (file)
@@ -117,44 +117,6 @@ static int ixgbevf_get_settings(struct net_device *netdev,
        return 0;
 }
 
-static u32 ixgbevf_get_rx_csum(struct net_device *netdev)
-{
-       struct ixgbevf_adapter *adapter = netdev_priv(netdev);
-       return adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED;
-}
-
-static int ixgbevf_set_rx_csum(struct net_device *netdev, u32 data)
-{
-       struct ixgbevf_adapter *adapter = netdev_priv(netdev);
-       if (data)
-               adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
-       else
-               adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
-
-       if (netif_running(netdev)) {
-               if (!adapter->dev_closed)
-                       ixgbevf_reinit_locked(adapter);
-       } else {
-               ixgbevf_reset(adapter);
-       }
-
-       return 0;
-}
-
-static int ixgbevf_set_tso(struct net_device *netdev, u32 data)
-{
-       if (data) {
-               netdev->features |= NETIF_F_TSO;
-               netdev->features |= NETIF_F_TSO6;
-       } else {
-               netif_tx_stop_all_queues(netdev);
-               netdev->features &= ~NETIF_F_TSO;
-               netdev->features &= ~NETIF_F_TSO6;
-               netif_tx_start_all_queues(netdev);
-       }
-       return 0;
-}
-
 static u32 ixgbevf_get_msglevel(struct net_device *netdev)
 {
        struct ixgbevf_adapter *adapter = netdev_priv(netdev);
@@ -720,16 +682,8 @@ static struct ethtool_ops ixgbevf_ethtool_ops = {
        .get_link               = ethtool_op_get_link,
        .get_ringparam          = ixgbevf_get_ringparam,
        .set_ringparam          = ixgbevf_set_ringparam,
-       .get_rx_csum            = ixgbevf_get_rx_csum,
-       .set_rx_csum            = ixgbevf_set_rx_csum,
-       .get_tx_csum            = ethtool_op_get_tx_csum,
-       .set_tx_csum            = ethtool_op_set_tx_ipv6_csum,
-       .get_sg                 = ethtool_op_get_sg,
-       .set_sg                 = ethtool_op_set_sg,
        .get_msglevel           = ixgbevf_get_msglevel,
        .set_msglevel           = ixgbevf_set_msglevel,
-       .get_tso                = ethtool_op_get_tso,
-       .set_tso                = ixgbevf_set_tso,
        .self_test              = ixgbevf_diag_test,
        .get_sset_count         = ixgbevf_get_sset_count,
        .get_strings            = ixgbevf_get_strings,
similarity index 98%
rename from drivers/net/ixgbevf/ixgbevf.h
rename to drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index 8857df4..e6c9d1a 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/io.h>
 #include <linux/netdevice.h>
 #include <linux/if_vlan.h>
+#include <linux/u64_stats_sync.h>
 
 #include "vf.h"
 
@@ -71,12 +72,13 @@ struct ixgbevf_ring {
                struct ixgbevf_rx_buffer *rx_buffer_info;
        };
 
+       u64                     total_bytes;
+       u64                     total_packets;
+       struct u64_stats_sync   syncp;
+
        u16 head;
        u16 tail;
 
-       unsigned int total_bytes;
-       unsigned int total_packets;
-
        u16 reg_idx; /* holds the special value that gets the hardware register
                      * offset associated with this ring, which is different
                      * for DCB and RSS modes */
similarity index 98%
rename from drivers/net/ixgbevf/ixgbevf_main.c
rename to drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 3b880a2..9896397 100644 (file)
@@ -44,6 +44,7 @@
 #include <net/checksum.h>
 #include <net/ip6_checksum.h>
 #include <linux/ethtool.h>
+#include <linux/if.h>
 #include <linux/if_vlan.h>
 #include <linux/prefetch.h>
 
@@ -202,6 +203,9 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter,
               (count < tx_ring->work_limit)) {
                bool cleaned = false;
                rmb(); /* read buffer_info after eop_desc */
+               /* eop could change between read and DD-check */
+               if (unlikely(eop != tx_ring->tx_buffer_info[i].next_to_watch))
+                       goto cont_loop;
                for ( ; !cleaned; count++) {
                        struct sk_buff *skb;
                        tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
@@ -231,6 +235,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter,
                                i = 0;
                }
 
+cont_loop:
                eop = tx_ring->tx_buffer_info[i].next_to_watch;
                eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
        }
@@ -265,11 +270,10 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter,
                IXGBE_WRITE_REG(hw, IXGBE_VTEICS, tx_ring->v_idx);
        }
 
+       u64_stats_update_begin(&tx_ring->syncp);
        tx_ring->total_bytes += total_bytes;
        tx_ring->total_packets += total_packets;
-
-       netdev->stats.tx_bytes += total_bytes;
-       netdev->stats.tx_packets += total_packets;
+       u64_stats_update_end(&tx_ring->syncp);
 
        return count < tx_ring->work_limit;
 }
@@ -592,10 +596,10 @@ next_desc:
        if (cleaned_count)
                ixgbevf_alloc_rx_buffers(adapter, rx_ring, cleaned_count);
 
+       u64_stats_update_begin(&rx_ring->syncp);
        rx_ring->total_packets += total_rx_packets;
        rx_ring->total_bytes += total_rx_bytes;
-       adapter->netdev->stats.rx_bytes += total_rx_bytes;
-       adapter->netdev->stats.rx_packets += total_rx_packets;
+       u64_stats_update_end(&rx_ring->syncp);
 
        return cleaned;
 }
@@ -2255,10 +2259,6 @@ void ixgbevf_update_stats(struct ixgbevf_adapter *adapter)
                                adapter->stats.vfgotc);
        UPDATE_VF_COUNTER_32bit(IXGBE_VFMPRC, adapter->stats.last_vfmprc,
                                adapter->stats.vfmprc);
-
-       /* Fill out the OS statistics structure */
-       adapter->netdev->stats.multicast = adapter->stats.vfmprc -
-               adapter->stats.base_vfmprc;
 }
 
 /**
@@ -3215,18 +3215,69 @@ static void ixgbevf_shutdown(struct pci_dev *pdev)
        pci_disable_device(pdev);
 }
 
+static struct rtnl_link_stats64 *ixgbevf_get_stats(struct net_device *netdev,
+                                               struct rtnl_link_stats64 *stats)
+{
+       struct ixgbevf_adapter *adapter = netdev_priv(netdev);
+       unsigned int start;
+       u64 bytes, packets;
+       const struct ixgbevf_ring *ring;
+       int i;
+
+       ixgbevf_update_stats(adapter);
+
+       stats->multicast = adapter->stats.vfmprc - adapter->stats.base_vfmprc;
+
+       for (i = 0; i < adapter->num_rx_queues; i++) {
+               ring = &adapter->rx_ring[i];
+               do {
+                       start = u64_stats_fetch_begin_bh(&ring->syncp);
+                       bytes = ring->total_bytes;
+                       packets = ring->total_packets;
+               } while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+               stats->rx_bytes += bytes;
+               stats->rx_packets += packets;
+       }
+
+       for (i = 0; i < adapter->num_tx_queues; i++) {
+               ring = &adapter->tx_ring[i];
+               do {
+                       start = u64_stats_fetch_begin_bh(&ring->syncp);
+                       bytes = ring->total_bytes;
+                       packets = ring->total_packets;
+               } while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+               stats->tx_bytes += bytes;
+               stats->tx_packets += packets;
+       }
+
+       return stats;
+}
+
+static int ixgbevf_set_features(struct net_device *netdev, u32 features)
+{
+       struct ixgbevf_adapter *adapter = netdev_priv(netdev);
+
+       if (features & NETIF_F_RXCSUM)
+               adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
+       else
+               adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
+
+       return 0;
+}
+
 static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_open               = ixgbevf_open,
        .ndo_stop               = ixgbevf_close,
        .ndo_start_xmit         = ixgbevf_xmit_frame,
        .ndo_set_rx_mode        = ixgbevf_set_rx_mode,
-       .ndo_set_multicast_list = ixgbevf_set_rx_mode,
+       .ndo_get_stats64        = ixgbevf_get_stats,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ixgbevf_set_mac,
        .ndo_change_mtu         = ixgbevf_change_mtu,
        .ndo_tx_timeout         = ixgbevf_tx_timeout,
        .ndo_vlan_rx_add_vid    = ixgbevf_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid   = ixgbevf_vlan_rx_kill_vid,
+       .ndo_set_features       = ixgbevf_set_features,
 };
 
 static void ixgbevf_assign_netdev_ops(struct net_device *dev)
@@ -3339,16 +3390,18 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
        /* setup the private structure */
        err = ixgbevf_sw_init(adapter);
 
-       netdev->features = NETIF_F_SG |
+       netdev->hw_features = NETIF_F_SG |
                           NETIF_F_IP_CSUM |
+                          NETIF_F_IPV6_CSUM |
+                          NETIF_F_TSO |
+                          NETIF_F_TSO6 |
+                          NETIF_F_RXCSUM;
+
+       netdev->features = netdev->hw_features |
                           NETIF_F_HW_VLAN_TX |
                           NETIF_F_HW_VLAN_RX |
                           NETIF_F_HW_VLAN_FILTER;
 
-       netdev->features |= NETIF_F_IPV6_CSUM;
-       netdev->features |= NETIF_F_TSO;
-       netdev->features |= NETIF_F_TSO6;
-       netdev->features |= NETIF_F_GRO;
        netdev->vlan_features |= NETIF_F_TSO;
        netdev->vlan_features |= NETIF_F_TSO6;
        netdev->vlan_features |= NETIF_F_IP_CSUM;
@@ -3358,6 +3411,8 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
        if (pci_using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
 
+       netdev->priv_flags |= IFF_UNICAST_FLT;
+
        /* The HW MAC address was set and/or determined in sw_init */
        memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
        memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
similarity index 99%
rename from drivers/net/jme.c
rename to drivers/net/ethernet/jme.c
index 3ac262f..a869ee4 100644 (file)
@@ -2839,7 +2839,7 @@ static const struct net_device_ops jme_netdev_ops = {
        .ndo_do_ioctl           = jme_ioctl,
        .ndo_start_xmit         = jme_start_xmit,
        .ndo_set_mac_address    = jme_set_macaddr,
-       .ndo_set_multicast_list = jme_set_multi,
+       .ndo_set_rx_mode        = jme_set_multi,
        .ndo_change_mtu         = jme_change_mtu,
        .ndo_tx_timeout         = jme_tx_timeout,
        .ndo_fix_features       = jme_fix_features,
similarity index 100%
rename from drivers/net/jme.h
rename to drivers/net/ethernet/jme.h
similarity index 99%
rename from drivers/net/korina.c
rename to drivers/net/ethernet/korina.c
index 763844c..d8430f4 100644 (file)
@@ -58,7 +58,6 @@
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
-#include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
@@ -1089,7 +1088,7 @@ static const struct net_device_ops korina_netdev_ops = {
        .ndo_open               = korina_open,
        .ndo_stop               = korina_close,
        .ndo_start_xmit         = korina_send_packet,
-       .ndo_set_multicast_list = korina_multicast_list,
+       .ndo_set_rx_mode        = korina_multicast_list,
        .ndo_tx_timeout         = korina_tx_timeout,
        .ndo_do_ioctl           = korina_ioctl,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/lantiq_etop.c
rename to drivers/net/ethernet/lantiq_etop.c
index 45f252b..6bb2b95 100644 (file)
@@ -687,7 +687,7 @@ static const struct net_device_ops ltq_eth_netdev_ops = {
        .ndo_do_ioctl = ltq_etop_ioctl,
        .ndo_set_mac_address = ltq_etop_set_mac_address,
        .ndo_validate_addr = eth_validate_addr,
-       .ndo_set_multicast_list = ltq_etop_set_multicast_list,
+       .ndo_set_rx_mode = ltq_etop_set_multicast_list,
        .ndo_select_queue = ltq_etop_select_queue,
        .ndo_init = ltq_etop_init,
        .ndo_tx_timeout = ltq_etop_tx_timeout,
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
new file mode 100644 (file)
index 0000000..0029934
--- /dev/null
@@ -0,0 +1,111 @@
+#
+# Marvell device configuration
+#
+
+config NET_VENDOR_MARVELL
+       bool "Marvell devices"
+       default y
+       depends on PCI || CPU_PXA168 || MV64X60 || PPC32 || PLAT_ORION || INET
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Marvell devices. If you say Y, you will be
+         asked for your specific card in the following questions.
+
+if NET_VENDOR_MARVELL
+
+config MV643XX_ETH
+       tristate "Marvell Discovery (643XX) and Orion ethernet support"
+       depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
+       select INET_LRO
+       select PHYLIB
+       ---help---
+         This driver supports the gigabit ethernet MACs in the
+         Marvell Discovery PPC/MIPS chipset family (MV643XX) and
+         in the Marvell Orion ARM SoC family.
+
+         Some boards that use the Discovery chipset are the Momenco
+         Ocelot C and Jaguar ATX and Pegasos II.
+
+config PXA168_ETH
+       tristate "Marvell pxa168 ethernet support"
+       depends on CPU_PXA168
+       select PHYLIB
+       ---help---
+         This driver supports the pxa168 Ethernet ports.
+
+         To compile this driver as a module, choose M here. The module
+         will be called pxa168_eth.
+
+config SKGE
+       tristate "Marvell Yukon Gigabit Ethernet support"
+       depends on PCI
+       select CRC32
+       ---help---
+         This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
+         and related Gigabit Ethernet adapters. It is a new smaller driver
+         with better performance and more complete ethtool support.
+
+         It does not support the link failover and network management
+         features that "portable" vendor supplied sk98lin driver does.
+
+         This driver supports adapters based on the original Yukon chipset:
+         Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T,
+         Linksys EG1032/EG1064, 3Com 3C940/3C940B, SysKonnect SK-9871/9872.
+
+         It does not support the newer Yukon2 chipset: a separate driver,
+         sky2, is provided for these adapters.
+
+         To compile this driver as a module, choose M here: the module
+         will be called skge.  This is recommended.
+
+config SKGE_DEBUG
+       bool "Debugging interface"
+       depends on SKGE && DEBUG_FS
+       ---help---
+         This option adds the ability to dump driver state for debugging.
+         The file /sys/kernel/debug/skge/ethX displays the state of the internal
+         transmit and receive rings.
+
+         If unsure, say N.
+
+config SKGE_GENESIS
+       bool "Support for older SysKonnect Genesis boards"
+       depends on SKGE
+       ---help---
+        This enables support for the older and uncommon SysKonnect Genesis
+        chips, which support MII via an external transceiver, instead of
+        an internal one. Disabling this option will save some memory
+        by making code smaller. If unsure say Y.
+
+config SKY2
+       tristate "Marvell Yukon 2 support"
+       depends on PCI
+       select CRC32
+       ---help---
+         This driver supports Gigabit Ethernet adapters based on the
+         Marvell Yukon 2 chipset:
+         Marvell 88E8021/88E8022/88E8035/88E8036/88E8038/88E8050/88E8052/
+         88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21
+
+         There is companion driver for the older Marvell Yukon and
+         SysKonnect Genesis based adapters: skge.
+
+         To compile this driver as a module, choose M here: the module
+         will be called sky2.  This is recommended.
+
+config SKY2_DEBUG
+       bool "Debugging interface"
+       depends on SKY2 && DEBUG_FS
+       ---help---
+         This option adds the ability to dump driver state for debugging.
+         The file /sys/kernel/debug/sky2/ethX displays the state of the internal
+         transmit and receive rings.
+
+         If unsure, say N.
+
+endif # NET_VENDOR_MARVELL
diff --git a/drivers/net/ethernet/marvell/Makefile b/drivers/net/ethernet/marvell/Makefile
new file mode 100644 (file)
index 0000000..57e3234
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for the Marvell device drivers.
+#
+
+obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
+obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
+obj-$(CONFIG_SKGE) += skge.o
+obj-$(CONFIG_SKY2) += sky2.o
similarity index 99%
rename from drivers/net/mv643xx_eth.c
rename to drivers/net/ethernet/marvell/mv643xx_eth.c
index 2596999..1e2c9f0 100644 (file)
@@ -2923,6 +2923,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
        dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
        dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM;
 
+       dev->priv_flags |= IFF_UNICAST_FLT;
+
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        if (mp->shared->win_protect)
similarity index 99%
rename from drivers/net/skge.c
rename to drivers/net/ethernet/marvell/skge.c
index 98ec614..34622b0 100644 (file)
@@ -3762,7 +3762,7 @@ static const struct net_device_ops skge_netdev_ops = {
        .ndo_tx_timeout         = skge_tx_timeout,
        .ndo_change_mtu         = skge_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = skge_set_multicast,
+       .ndo_set_rx_mode        = skge_set_multicast,
        .ndo_set_mac_address    = skge_set_mac_address,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = skge_netpoll,
similarity index 99%
rename from drivers/net/sky2.c
rename to drivers/net/ethernet/marvell/sky2.c
index 57339da..3ff0a12 100644 (file)
@@ -4612,7 +4612,7 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
        .ndo_do_ioctl           = sky2_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = sky2_set_mac_address,
-       .ndo_set_multicast_list = sky2_set_multicast,
+       .ndo_set_rx_mode        = sky2_set_multicast,
        .ndo_change_mtu         = sky2_change_mtu,
        .ndo_fix_features       = sky2_fix_features,
        .ndo_set_features       = sky2_set_features,
@@ -4629,7 +4629,7 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
        .ndo_do_ioctl           = sky2_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = sky2_set_mac_address,
-       .ndo_set_multicast_list = sky2_set_multicast,
+       .ndo_set_rx_mode        = sky2_set_multicast,
        .ndo_change_mtu         = sky2_change_mtu,
        .ndo_fix_features       = sky2_fix_features,
        .ndo_set_features       = sky2_set_features,
diff --git a/drivers/net/ethernet/mellanox/Kconfig b/drivers/net/ethernet/mellanox/Kconfig
new file mode 100644 (file)
index 0000000..d8099a7
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# Mellanox driver configuration
+#
+
+config NET_VENDOR_MELLANOX
+       bool "Mellanox devices"
+       default y
+       depends on PCI && INET
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Mellanox cards. If you say Y, you will be asked
+         for your specific card in the following questions.
+
+if NET_VENDOR_MELLANOX
+
+source "drivers/net/ethernet/mellanox/mlx4/Kconfig"
+
+endif # NET_VENDOR_MELLANOX
diff --git a/drivers/net/ethernet/mellanox/Makefile b/drivers/net/ethernet/mellanox/Makefile
new file mode 100644 (file)
index 0000000..37afb96
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Mellanox device drivers.
+#
+
+obj-$(CONFIG_MLX4_CORE) += mlx4/
diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig
new file mode 100644 (file)
index 0000000..1bb9353
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# Mellanox driver configuration
+#
+
+config MLX4_EN
+       tristate "Mellanox Technologies 10Gbit Ethernet support"
+       depends on PCI && INET
+       select MLX4_CORE
+       select INET_LRO
+       ---help---
+         This driver supports Mellanox Technologies ConnectX Ethernet
+         devices.
+
+config MLX4_CORE
+       tristate
+       depends on PCI
+       default n
+
+config MLX4_DEBUG
+       bool "Verbose debugging output" if (MLX4_CORE && EXPERT)
+       depends on MLX4_CORE
+       default y
+       ---help---
+         This option causes debugging code to be compiled into the
+         mlx4_core driver.  The output can be turned on via the
+         debug_level module parameter (which can also be set after
+         the driver is loaded through sysfs).
similarity index 99%
rename from drivers/net/mlx4/en_netdev.c
rename to drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 4b0f32e..27789be 100644 (file)
@@ -1016,7 +1016,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
        .ndo_start_xmit         = mlx4_en_xmit,
        .ndo_select_queue       = mlx4_en_select_queue,
        .ndo_get_stats          = mlx4_en_get_stats,
-       .ndo_set_multicast_list = mlx4_en_set_multicast,
+       .ndo_set_rx_mode        = mlx4_en_set_multicast,
        .ndo_set_mac_address    = mlx4_en_set_mac,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = mlx4_en_change_mtu,
similarity index 99%
rename from drivers/net/mlx4/en_port.c
rename to drivers/net/ethernet/mellanox/mlx4/en_port.c
index 5e71091..5ada5b4 100644 (file)
@@ -128,7 +128,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
        memset(context, 0, sizeof *context);
 
        context->base_qpn = cpu_to_be32(base_qpn);
-       context->n_mac = 0x7;
+       context->n_mac = 0x2;
        context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT |
                                       base_qpn);
        context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT |
similarity index 99%
rename from drivers/net/mlx4/main.c
rename to drivers/net/ethernet/mellanox/mlx4/main.c
index c94b342..f0ee35d 100644 (file)
@@ -1117,6 +1117,8 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
        info->port = port;
        mlx4_init_mac_table(dev, &info->mac_table);
        mlx4_init_vlan_table(dev, &info->vlan_table);
+       info->base_qpn = dev->caps.reserved_qps_base[MLX4_QP_REGION_ETH_ADDR] +
+                       (port - 1) * (1 << log_num_mac);
 
        sprintf(info->dev_name, "mlx4_port%d", port);
        info->port_attr.attr.name = info->dev_name;
similarity index 98%
rename from drivers/net/mlx4/port.c
rename to drivers/net/ethernet/mellanox/mlx4/port.c
index 1f95afd..609e0ec 100644 (file)
@@ -258,9 +258,12 @@ void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn)
        if (validate_index(dev, table, index))
                goto out;
 
-       table->entries[index] = 0;
-       mlx4_set_port_mac_table(dev, port, table->entries);
-       --table->total;
+       /* Check whether this address has reference count */
+       if (!(--table->refs[index])) {
+               table->entries[index] = 0;
+               mlx4_set_port_mac_table(dev, port, table->entries);
+               --table->total;
+       }
 out:
        mutex_unlock(&table->mutex);
 }
diff --git a/drivers/net/ethernet/micrel/Kconfig b/drivers/net/ethernet/micrel/Kconfig
new file mode 100644 (file)
index 0000000..bd090db
--- /dev/null
@@ -0,0 +1,65 @@
+#
+# Micrel device configuration
+#
+
+config NET_VENDOR_MICREL
+       bool "Micrel devices"
+       default y
+       depends on (HAS_IOMEM && DMA_ENGINE) || SPI || PCI || HAS_IOMEM || \
+                  (ARM && ARCH_KS8695)
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Micrel devices. If you say Y, you will be asked
+         for your specific card in the following questions.
+
+if NET_VENDOR_MICREL
+
+config ARM_KS8695_ETHER
+       tristate "KS8695 Ethernet support"
+       depends on ARM && ARCH_KS8695
+       select MII
+       ---help---
+         If you wish to compile a kernel for the KS8695 and want to
+         use the internal ethernet then you should answer Y to this.
+
+config KS8842
+       tristate "Micrel KSZ8841/42 with generic bus interface"
+       depends on HAS_IOMEM && DMA_ENGINE
+       ---help---
+         This platform driver is for KSZ8841(1-port) / KS8842(2-port)
+         ethernet switch chip (managed, VLAN, QoS) from Micrel or
+         Timberdale(FPGA).
+
+config KS8851
+       tristate "Micrel KS8851 SPI"
+       depends on SPI
+       select MII
+       select CRC32
+       ---help---
+         SPI driver for Micrel KS8851 SPI attached network chip.
+
+config KS8851_MLL
+       tristate "Micrel KS8851 MLL"
+       depends on HAS_IOMEM
+       select MII
+       ---help---
+         This platform driver is for Micrel KS8851 Address/data bus
+         multiplexed network chip.
+
+config KSZ884X_PCI
+       tristate "Micrel KSZ8841/2 PCI"
+       depends on PCI
+       select MII
+       select CRC32
+       ---help---
+         This PCI driver is for Micrel KSZ8841/KSZ8842 PCI Ethernet chip.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ksz884x.
+
+endif # NET_VENDOR_MICREL
diff --git a/drivers/net/ethernet/micrel/Makefile b/drivers/net/ethernet/micrel/Makefile
new file mode 100644 (file)
index 0000000..c83e4bc
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for the Micrel network device drivers.
+#
+
+obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o
+obj-$(CONFIG_KS8842) += ks8842.o
+obj-$(CONFIG_KS8851) += ks8851.o
+obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
+obj-$(CONFIG_KSZ884X_PCI) += ksz884x.o
similarity index 99%
rename from drivers/net/arm/ks8695net.c
rename to drivers/net/ethernet/micrel/ks8695net.c
index c827a60..7078840 100644 (file)
@@ -1333,7 +1333,7 @@ static const struct net_device_ops ks8695_netdev_ops = {
        .ndo_tx_timeout         = ks8695_timeout,
        .ndo_set_mac_address    = ks8695_set_mac,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = ks8695_set_multicast,
+       .ndo_set_rx_mode        = ks8695_set_multicast,
 };
 
 /**
diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig
new file mode 100644 (file)
index 0000000..8163fd0
--- /dev/null
@@ -0,0 +1,38 @@
+#
+# Microchip network device configuration
+#
+
+config NET_VENDOR_MICROCHIP
+       bool "Microchip devices"
+       default y
+       depends on SPI && EXPERIMENTAL
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Microchip cards. If you say Y, you will be asked
+         for your specific card in the following questions.
+
+if NET_VENDOR_MICROCHIP
+
+config ENC28J60
+       tristate "ENC28J60 support"
+       depends on SPI && EXPERIMENTAL
+       select CRC32
+       ---help---
+         Support for the Microchip EN28J60 ethernet chip.
+
+         To compile this driver as a module, choose M here. The module will be
+         called enc28j60.
+
+config ENC28J60_WRITEVERIFY
+       bool "Enable write verify"
+       depends on ENC28J60
+       ---help---
+         Enable the verify after the buffer write useful for debugging purpose.
+         If unsure, say N.
+
+endif # NET_VENDOR_MICROCHIP
diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile
new file mode 100644 (file)
index 0000000..573d429
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Microchip network device drivers.
+#
+
+obj-$(CONFIG_ENC28J60) += enc28j60.o
similarity index 99%
rename from drivers/net/enc28j60.c
rename to drivers/net/ethernet/microchip/enc28j60.c
index 2837ce2..50055e0 100644 (file)
@@ -1534,7 +1534,7 @@ static const struct net_device_ops enc28j60_netdev_ops = {
        .ndo_open               = enc28j60_net_open,
        .ndo_stop               = enc28j60_net_close,
        .ndo_start_xmit         = enc28j60_send_packet,
-       .ndo_set_multicast_list = enc28j60_set_multicast_list,
+       .ndo_set_rx_mode        = enc28j60_set_multicast_list,
        .ndo_set_mac_address    = enc28j60_set_mac_address,
        .ndo_tx_timeout         = enc28j60_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/mipsnet.c
rename to drivers/net/ethernet/mipsnet.c
index 004e64a..d05b0c9 100644 (file)
@@ -242,7 +242,7 @@ static const struct net_device_ops mipsnet_netdev_ops = {
        .ndo_open               = mipsnet_open,
        .ndo_stop               = mipsnet_close,
        .ndo_start_xmit         = mipsnet_xmit,
-       .ndo_set_multicast_list = mipsnet_set_mclist,
+       .ndo_set_rx_mode        = mipsnet_set_mclist,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
diff --git a/drivers/net/ethernet/myricom/Kconfig b/drivers/net/ethernet/myricom/Kconfig
new file mode 100644 (file)
index 0000000..540f0c6
--- /dev/null
@@ -0,0 +1,47 @@
+#
+# Myricom device configuration
+#
+
+config NET_VENDOR_MYRI
+       bool "Myricom devices"
+       default y
+       depends on PCI && INET
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say
+         Y and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Myricom cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_MYRI
+
+config MYRI10GE
+       tristate "Myricom Myri-10G Ethernet support"
+       depends on PCI && INET
+       select FW_LOADER
+       select CRC32
+       select INET_LRO
+       ---help---
+         This driver supports Myricom Myri-10G Dual Protocol interface in
+         Ethernet mode. If the eeprom on your board is not recent enough,
+         you will need a newer firmware image.
+         You may get this image or more information, at:
+
+         <http://www.myri.com/scs/download-Myri10GE.html>
+
+         To compile this driver as a module, choose M here. The module
+         will be called myri10ge.
+
+config MYRI10GE_DCA
+       bool "Direct Cache Access (DCA) Support"
+       default y
+       depends on MYRI10GE && DCA && !(MYRI10GE=y && DCA=m)
+       ---help---
+         Say Y here if you want to use Direct Cache Access (DCA) in the
+         driver.  DCA is a method for warming the CPU cache before data
+         is used, with the intent of lessening the impact of cache misses.
+
+endif # NET_VENDOR_MYRI
diff --git a/drivers/net/ethernet/myricom/Makefile b/drivers/net/ethernet/myricom/Makefile
new file mode 100644 (file)
index 0000000..296c0a1
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Myricom network device drivers.
+#
+
+obj-$(CONFIG_MYRI10GE) += myri10ge/
similarity index 99%
rename from drivers/net/myri10ge/myri10ge.c
rename to drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 1d22475..81c1700 100644 (file)
@@ -3892,7 +3892,7 @@ static const struct net_device_ops myri10ge_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = myri10ge_change_mtu,
        .ndo_fix_features       = myri10ge_fix_features,
-       .ndo_set_multicast_list = myri10ge_set_multicast_list,
+       .ndo_set_rx_mode        = myri10ge_set_multicast_list,
        .ndo_set_mac_address    = myri10ge_set_mac_address,
 };
 
diff --git a/drivers/net/ethernet/natsemi/Kconfig b/drivers/net/ethernet/natsemi/Kconfig
new file mode 100644 (file)
index 0000000..4a6b9fd
--- /dev/null
@@ -0,0 +1,83 @@
+#
+# National Semi-conductor device configuration
+#
+
+config NET_VENDOR_NATSEMI
+       bool "National Semi-conductor devices"
+       default y
+       depends on MCA || MAC || MACH_JAZZ || PCI || XTENSA_PLATFORM_XT2000
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about National Semi-conductor devices. If you say Y,
+         you will be asked for your specific card in the following questions.
+
+if NET_VENDOR_NATSEMI
+
+config IBMLANA
+       tristate "IBM LAN Adapter/A support"
+       depends on MCA
+       ---help---
+         This is a Micro Channel Ethernet adapter.  You need to set
+         CONFIG_MCA to use this driver.  It is both available as an in-kernel
+         driver and as a module.
+
+         To compile this driver as a module, choose M here. The only
+         currently supported card is the IBM LAN Adapter/A for Ethernet.  It
+         will both support 16K and 32K memory windows, however a 32K window
+         gives a better security against packet losses.  Usage of multiple
+         boards with this driver should be possible, but has not been tested
+         up to now due to lack of hardware.
+
+config MACSONIC
+       tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)"
+       depends on MAC
+       ---help---
+         Support for NatSemi SONIC based Ethernet devices.  This includes
+         the onboard Ethernet in many Quadras as well as some LC-PDS,
+         a few Nubus and all known Comm Slot Ethernet cards.  If you have
+         one of these say Y and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. This module will
+         be called macsonic.
+
+config MIPS_JAZZ_SONIC
+       tristate "MIPS JAZZ onboard SONIC Ethernet support"
+       depends on MACH_JAZZ
+       ---help---
+         This is the driver for the onboard card of MIPS Magnum 4000,
+         Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
+
+config NATSEMI
+       tristate "National Semiconductor DP8381x series PCI Ethernet support"
+       depends on PCI
+       select CRC32
+       ---help---
+         This driver is for the National Semiconductor DP83810 series,
+         which is used in cards from PureData, NetGear, Linksys
+         and others, including the 83815 chip.
+         More specific information and updates are available from
+         <http://www.scyld.com/network/natsemi.html>.
+
+config NS83820
+       tristate "National Semiconductor DP83820 support"
+       depends on PCI
+       ---help---
+         This is a driver for the National Semiconductor DP83820 series
+         of gigabit ethernet MACs.  Cards using this chipset include
+         the D-Link DGE-500T, PureData's PDP8023Z-TG, SMC's SMC9462TX,
+         SOHO-GA2000T, SOHO-GA2500T.  The driver supports the use of
+         zero copy.
+
+config XTENSA_XT2000_SONIC
+       tristate "Xtensa XT2000 onboard SONIC Ethernet support"
+       depends on XTENSA_PLATFORM_XT2000
+       ---help---
+         This is the driver for the onboard card of the Xtensa XT2000 board.
+
+endif # NET_VENDOR_NATSEMI
diff --git a/drivers/net/ethernet/natsemi/Makefile b/drivers/net/ethernet/natsemi/Makefile
new file mode 100644 (file)
index 0000000..9aa5dea
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the National Semi-conductor Sonic devices.
+#
+
+obj-$(CONFIG_IBMLANA) += ibmlana.o
+obj-$(CONFIG_MACSONIC) += macsonic.o
+obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
+obj-$(CONFIG_NATSEMI) += natsemi.o
+obj-$(CONFIG_NS83820) += ns83820.o
+obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
similarity index 99%
rename from drivers/net/ibmlana.c
rename to drivers/net/ethernet/natsemi/ibmlana.c
index a7d6cad..999407f 100644 (file)
@@ -910,7 +910,7 @@ static const struct net_device_ops ibmlana_netdev_ops = {
        .ndo_open               = ibmlana_open,
        .ndo_stop               = ibmlana_close,
        .ndo_start_xmit         = ibmlana_tx,
-       .ndo_set_multicast_list = ibmlana_set_multicast_list,
+       .ndo_set_rx_mode        = ibmlana_set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/jazzsonic.c
rename to drivers/net/ethernet/natsemi/jazzsonic.c
index 949c1f9..fc7c6a9 100644 (file)
@@ -111,7 +111,7 @@ static const struct net_device_ops sonic_netdev_ops = {
        .ndo_stop               = jazzsonic_close,
        .ndo_start_xmit         = sonic_send_packet,
        .ndo_get_stats          = sonic_get_stats,
-       .ndo_set_multicast_list = sonic_multicast_list,
+       .ndo_set_rx_mode        = sonic_multicast_list,
        .ndo_tx_timeout         = sonic_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/macsonic.c
rename to drivers/net/ethernet/natsemi/macsonic.c
index c93679e..5c36948 100644 (file)
@@ -190,7 +190,7 @@ static const struct net_device_ops macsonic_netdev_ops = {
        .ndo_open               = macsonic_open,
        .ndo_stop               = macsonic_close,
        .ndo_start_xmit         = sonic_send_packet,
-       .ndo_set_multicast_list = sonic_multicast_list,
+       .ndo_set_rx_mode        = sonic_multicast_list,
        .ndo_tx_timeout         = sonic_tx_timeout,
        .ndo_get_stats          = sonic_get_stats,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/natsemi.c
rename to drivers/net/ethernet/natsemi/natsemi.c
index 2962cc6..6ca047a 100644 (file)
@@ -783,7 +783,7 @@ static const struct net_device_ops natsemi_netdev_ops = {
        .ndo_stop               = netdev_close,
        .ndo_start_xmit         = start_tx,
        .ndo_get_stats          = get_stats,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_change_mtu         = natsemi_change_mtu,
        .ndo_do_ioctl           = netdev_ioctl,
        .ndo_tx_timeout         = ns_tx_timeout,
similarity index 99%
rename from drivers/net/ns83820.c
rename to drivers/net/ethernet/natsemi/ns83820.c
index e736aec..1a1e20e 100644 (file)
@@ -1937,7 +1937,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_start_xmit         = ns83820_hard_start_xmit,
        .ndo_get_stats          = ns83820_get_stats,
        .ndo_change_mtu         = ns83820_change_mtu,
-       .ndo_set_multicast_list = ns83820_set_multicast,
+       .ndo_set_rx_mode        = ns83820_set_multicast,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_tx_timeout         = ns83820_tx_timeout,
similarity index 99%
rename from drivers/net/xtsonic.c
rename to drivers/net/ethernet/natsemi/xtsonic.c
index 9f12026..ccf61b9 100644 (file)
@@ -122,7 +122,7 @@ static const struct net_device_ops xtsonic_netdev_ops = {
        .ndo_stop               = xtsonic_close,
        .ndo_start_xmit         = sonic_send_packet,
        .ndo_get_stats          = sonic_get_stats,
-       .ndo_set_multicast_list = sonic_multicast_list,
+       .ndo_set_rx_mode        = sonic_multicast_list,
        .ndo_tx_timeout         = sonic_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
diff --git a/drivers/net/ethernet/neterion/Kconfig b/drivers/net/ethernet/neterion/Kconfig
new file mode 100644 (file)
index 0000000..ff26b54
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# Exar device configuration
+#
+
+config NET_VENDOR_EXAR
+       bool "Exar devices"
+       default y
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say
+         Y and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Exar cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_EXAR
+
+config S2IO
+       tristate "Exar Xframe 10Gb Ethernet Adapter"
+       depends on PCI
+       ---help---
+         This driver supports Exar Corp's Xframe Series 10Gb Ethernet Adapters.
+
+         More specific information on configuring the driver is in
+         <file:Documentation/networking/s2io.txt>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called s2io.
+
+config VXGE
+       tristate "Exar X3100 Series 10GbE PCIe Server Adapter"
+       depends on PCI && INET
+       ---help---
+         This driver supports Exar Corp's X3100 Series 10 GbE PCIe
+         I/O Virtualized Server Adapter.
+
+         More specific information on configuring the driver is in
+         <file:Documentation/networking/vxge.txt>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called vxge.
+
+config VXGE_DEBUG_TRACE_ALL
+       bool "Enabling All Debug trace statements in driver"
+       default n
+       depends on VXGE
+       ---help---
+         Say Y here if you want to enabling all the debug trace statements in
+         the vxge driver. By default only few debug trace statements are
+         enabled.
+
+endif # NET_VENDOR_EXAR
diff --git a/drivers/net/ethernet/neterion/Makefile b/drivers/net/ethernet/neterion/Makefile
new file mode 100644 (file)
index 0000000..70c8058
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the Exar network device drivers.
+#
+
+obj-$(CONFIG_S2IO) += s2io.o
+obj-$(CONFIG_VXGE) += vxge/
similarity index 99%
rename from drivers/net/s2io.c
rename to drivers/net/ethernet/neterion/s2io.c
index 277d48b..840cbb2 100644 (file)
@@ -7682,7 +7682,7 @@ static const struct net_device_ops s2io_netdev_ops = {
        .ndo_get_stats          = s2io_get_stats,
        .ndo_start_xmit         = s2io_xmit,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = s2io_set_multicast,
+       .ndo_set_rx_mode        = s2io_set_multicast,
        .ndo_do_ioctl           = s2io_ioctl,
        .ndo_set_mac_address    = s2io_set_mac_addr,
        .ndo_change_mtu         = s2io_change_mtu,
similarity index 99%
rename from drivers/net/vxge/vxge-main.c
rename to drivers/net/ethernet/neterion/vxge/vxge-main.c
index 178348a..1a53a24 100644 (file)
@@ -3354,7 +3354,7 @@ static const struct net_device_ops vxge_netdev_ops = {
        .ndo_get_stats64        = vxge_get_stats64,
        .ndo_start_xmit         = vxge_xmit,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = vxge_set_multicast,
+       .ndo_set_rx_mode        = vxge_set_multicast,
        .ndo_do_ioctl           = vxge_ioctl,
        .ndo_set_mac_address    = vxge_set_mac_addr,
        .ndo_change_mtu         = vxge_change_mtu,
similarity index 99%
rename from drivers/net/netx-eth.c
rename to drivers/net/ethernet/netx-eth.c
index 2dfee89..8d288af 100644 (file)
@@ -306,7 +306,7 @@ static const struct net_device_ops netx_eth_netdev_ops = {
        .ndo_stop               = netx_eth_close,
        .ndo_start_xmit         = netx_eth_hard_start_xmit,
        .ndo_tx_timeout         = netx_eth_timeout,
-       .ndo_set_multicast_list = netx_eth_set_multicast_list,
+       .ndo_set_rx_mode        = netx_eth_set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
diff --git a/drivers/net/ethernet/nuvoton/Kconfig b/drivers/net/ethernet/nuvoton/Kconfig
new file mode 100644 (file)
index 0000000..01182b5
--- /dev/null
@@ -0,0 +1,30 @@
+#
+# Nuvoton network device configuration
+#
+
+config NET_VENDOR_NUVOTON
+       bool "Nuvoton devices"
+       default y
+       depends on ARM && ARCH_W90X900
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Nuvoton cards. If you say Y, you will be asked
+         for your specific card in the following questions.
+
+if NET_VENDOR_NUVOTON
+
+config W90P910_ETH
+       tristate "Nuvoton w90p910 Ethernet support"
+       depends on ARM && ARCH_W90X900
+       select PHYLIB
+       select MII
+       ---help---
+         Say Y here if you want to use built-in Ethernet ports
+         on w90p910 processor.
+
+endif # NET_VENDOR_NUVOTON
diff --git a/drivers/net/ethernet/nuvoton/Makefile b/drivers/net/ethernet/nuvoton/Makefile
new file mode 100644 (file)
index 0000000..171aa04
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Nuvoton network device drivers.
+#
+
+obj-$(CONFIG_W90P910_ETH) += w90p910_ether.o
similarity index 99%
rename from drivers/net/arm/w90p910_ether.c
rename to drivers/net/ethernet/nuvoton/w90p910_ether.c
index bfea499..f1bfb8f 100644 (file)
@@ -919,7 +919,7 @@ static const struct net_device_ops w90p910_ether_netdev_ops = {
        .ndo_stop               = w90p910_ether_close,
        .ndo_start_xmit         = w90p910_ether_start_xmit,
        .ndo_get_stats          = w90p910_ether_stats,
-       .ndo_set_multicast_list = w90p910_ether_set_multicast_list,
+       .ndo_set_rx_mode        = w90p910_ether_set_multicast_list,
        .ndo_set_mac_address    = w90p910_set_mac_address,
        .ndo_do_ioctl           = w90p910_ether_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
diff --git a/drivers/net/ethernet/nvidia/Kconfig b/drivers/net/ethernet/nvidia/Kconfig
new file mode 100644 (file)
index 0000000..ace19e7
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# NVIDIA network device configuration
+#
+
+config NET_VENDOR_NVIDIA
+       bool "NVIDIA devices"
+       default y
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about NVIDIA cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_NVIDIA
+
+config FORCEDETH
+       tristate "nForce Ethernet support"
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) controller of this type, say Y and
+         read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called forcedeth.
+
+endif # NET_VENDOR_NVIDIA
diff --git a/drivers/net/ethernet/nvidia/Makefile b/drivers/net/ethernet/nvidia/Makefile
new file mode 100644 (file)
index 0000000..e079ae5
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the NVIDIA network device drivers.
+#
+
+obj-$(CONFIG_FORCEDETH) += forcedeth.o
similarity index 99%
rename from drivers/net/forcedeth.c
rename to drivers/net/ethernet/nvidia/forcedeth.c
index e55df30..98bb64b 100644 (file)
@@ -5208,7 +5208,7 @@ static const struct net_device_ops nv_netdev_ops = {
        .ndo_set_features       = nv_set_features,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = nv_set_mac_address,
-       .ndo_set_multicast_list = nv_set_multicast,
+       .ndo_set_rx_mode        = nv_set_multicast,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = nv_poll_controller,
 #endif
@@ -5225,7 +5225,7 @@ static const struct net_device_ops nv_netdev_ops_optimized = {
        .ndo_set_features       = nv_set_features,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = nv_set_mac_address,
-       .ndo_set_multicast_list = nv_set_multicast,
+       .ndo_set_rx_mode        = nv_set_multicast,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = nv_poll_controller,
 #endif
@@ -5615,7 +5615,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                goto out_error;
        }
 
-       nv_vlan_mode(dev, dev->features);
+       if (id->driver_data & DEV_HAS_VLAN)
+               nv_vlan_mode(dev, dev->features);
 
        netif_carrier_off(dev);
 
similarity index 85%
rename from drivers/net/octeon/Kconfig
rename to drivers/net/ethernet/octeon/Kconfig
index 1e56bbf..3de52ff 100644 (file)
@@ -1,10 +1,14 @@
+#
+# Cavium network device configuration
+#
+
 config OCTEON_MGMT_ETHERNET
        tristate "Octeon Management port ethernet driver (CN5XXX, CN6XXX)"
        depends on  CPU_CAVIUM_OCTEON
        select PHYLIB
        select MDIO_OCTEON
        default y
-       help
+       ---help---
          This option enables the ethernet driver for the management
          port on Cavium Networks' Octeon CN57XX, CN56XX, CN55XX,
          CN54XX, CN52XX, and CN6XXX chips.
diff --git a/drivers/net/ethernet/octeon/Makefile b/drivers/net/ethernet/octeon/Makefile
new file mode 100644 (file)
index 0000000..efa41c1
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Cavium network device drivers.
+#
+
+obj-$(CONFIG_OCTEON_MGMT_ETHERNET)     += octeon_mgmt.o
similarity index 99%
rename from drivers/net/octeon/octeon_mgmt.c
rename to drivers/net/ethernet/octeon/octeon_mgmt.c
index 429e08c..bc1d946 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/if.h>
 #include <linux/if_vlan.h>
 #include <linux/slab.h>
 #include <linux/phy.h>
@@ -1059,7 +1060,6 @@ static const struct net_device_ops octeon_mgmt_ops = {
        .ndo_stop =                     octeon_mgmt_stop,
        .ndo_start_xmit =               octeon_mgmt_xmit,
        .ndo_set_rx_mode =              octeon_mgmt_set_rx_filtering,
-       .ndo_set_multicast_list =       octeon_mgmt_set_rx_filtering,
        .ndo_set_mac_address =          octeon_mgmt_set_mac_address,
        .ndo_do_ioctl =                 octeon_mgmt_ioctl,
        .ndo_change_mtu =               octeon_mgmt_change_mtu,
@@ -1102,6 +1102,8 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
        tasklet_init(&p->tx_clean_tasklet,
                     octeon_mgmt_clean_tx_tasklet, (unsigned long)p);
 
+       netdev->priv_flags |= IFF_UNICAST_FLT;
+
        netdev->netdev_ops = &octeon_mgmt_ops;
        netdev->ethtool_ops = &octeon_mgmt_ethtool_ops;
 
diff --git a/drivers/net/ethernet/oki-semi/Kconfig b/drivers/net/ethernet/oki-semi/Kconfig
new file mode 100644 (file)
index 0000000..ecd45f9
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# OKI Semiconductor device configuration
+#
+
+config NET_VENDOR_OKI
+       bool "OKI Semiconductor devices"
+       default y
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about OKI Semiconductor cards. If you say Y, you will
+         be asked for your specific card in the following questions.
+
+if NET_VENDOR_OKI
+
+source "drivers/net/ethernet/oki-semi/pch_gbe/Kconfig"
+
+endif # NET_VENDOR_OKI
diff --git a/drivers/net/ethernet/oki-semi/Makefile b/drivers/net/ethernet/oki-semi/Makefile
new file mode 100644 (file)
index 0000000..b6780c8
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the OKI Semiconductor device drivers.
+#
+
+obj-$(CONFIG_PCH_GBE) += pch_gbe/
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
new file mode 100644 (file)
index 0000000..c85709d
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# OKI Semiconductor device configuration
+#
+
+config PCH_GBE
+       tristate "OKI SEMICONDUCTOR ML7223 IOH GbE (Intel EG20T PCH)"
+       depends on PCI
+       select MII
+       ---help---
+         This is a gigabit ethernet driver for EG20T PCH.
+         EG20T PCH is the platform controller hub that is used in Intel's
+         general embedded platform.  EG20T PCH has Gigabit Ethernet interface.
+         Using this interface, it is able to access system devices connected
+         to Gigabit Ethernet.  This driver enables Gigabit Ethernet function.
+
+         This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
+         Output Hub), ML7223.
+         ML7223 IOH is for MP(Media Phone) use.
+         ML7223 is companion chip for Intel Atom E6xx series.
+         ML7223 is completely compatible for Intel EG20T PCH.
similarity index 99%
rename from drivers/net/pch_gbe/pch_gbe_main.c
rename to drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index eac3c5c..72276fe 100644 (file)
@@ -2158,7 +2158,7 @@ static const struct net_device_ops pch_gbe_netdev_ops = {
        .ndo_change_mtu = pch_gbe_change_mtu,
        .ndo_set_features = pch_gbe_set_features,
        .ndo_do_ioctl = pch_gbe_ioctl,
-       .ndo_set_multicast_list = &pch_gbe_set_multi,
+       .ndo_set_rx_mode = pch_gbe_set_multi,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = pch_gbe_netpoll,
 #endif
diff --git a/drivers/net/ethernet/packetengines/Kconfig b/drivers/net/ethernet/packetengines/Kconfig
new file mode 100644 (file)
index 0000000..4add1db
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# Packet engine device configuration
+#
+
+config NET_PACKET_ENGINE
+       bool "Packet Engine devices"
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about packet engine devices. If you say Y, you will
+         be asked for your specific card in the following questions.
+
+if NET_PACKET_ENGINE
+
+config HAMACHI
+       tristate "Packet Engines Hamachi GNIC-II support"
+       depends on PCI
+       select MII
+       ---help---
+         If you have a Gigabit Ethernet card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module will be
+         called hamachi.
+
+config YELLOWFIN
+       tristate "Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)"
+       depends on PCI && EXPERIMENTAL
+       select CRC32
+       ---help---
+         Say Y here if you have a Packet Engines G-NIC PCI Gigabit Ethernet
+         adapter or the SYM53C885 Ethernet controller. The Gigabit adapter is
+         used by the Beowulf Linux cluster project.  See
+         <http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html> for more
+         information about this driver in particular and Beowulf in general.
+
+         To compile this driver as a module, choose M here: the module
+         will be called yellowfin.  This is recommended.
+
+endif # NET_PACKET_ENGINE
diff --git a/drivers/net/ethernet/packetengines/Makefile b/drivers/net/ethernet/packetengines/Makefile
new file mode 100644 (file)
index 0000000..995ccd0
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the Packet Engine network device drivers.
+#
+
+obj-$(CONFIG_HAMACHI) += hamachi.o
+obj-$(CONFIG_YELLOWFIN) += yellowfin.o
similarity index 99%
rename from drivers/net/hamachi.c
rename to drivers/net/ethernet/packetengines/hamachi.c
index c274b3d..3458df3 100644 (file)
@@ -567,7 +567,7 @@ static const struct net_device_ops hamachi_netdev_ops = {
        .ndo_stop               = hamachi_close,
        .ndo_start_xmit         = hamachi_start_xmit,
        .ndo_get_stats          = hamachi_get_stats,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/yellowfin.c
rename to drivers/net/ethernet/packetengines/yellowfin.c
index 3e5ac60..db44e9a 100644 (file)
@@ -359,7 +359,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_open               = yellowfin_open,
        .ndo_stop               = yellowfin_close,
        .ndo_start_xmit         = yellowfin_start_xmit,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
diff --git a/drivers/net/ethernet/pasemi/Kconfig b/drivers/net/ethernet/pasemi/Kconfig
new file mode 100644 (file)
index 0000000..01e6c32
--- /dev/null
@@ -0,0 +1,30 @@
+#
+# PA Semi network device configuration
+#
+
+config NET_VENDOR_PASEMI
+       bool "PA Semi devices"
+       default y
+       depends on PPC_PASEMI && PCI && INET
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about PA Semi cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_PASEMI
+
+config PASEMI_MAC
+       tristate "PA Semi 1/10Gbit MAC"
+       depends on PPC_PASEMI && PCI && INET
+       select PHYLIB
+       select INET_LRO
+       ---help---
+         This driver supports the on-chip 1/10Gbit Ethernet controller on
+         PA Semi's PWRficient line of chips.
+
+endif # NET_VENDOR_PASEMI
diff --git a/drivers/net/ethernet/pasemi/Makefile b/drivers/net/ethernet/pasemi/Makefile
new file mode 100644 (file)
index 0000000..05db543
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the A Semi network device drivers.
+#
+
+obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o pasemi_mac_ethtool.o
similarity index 99%
rename from drivers/net/pasemi_mac.c
rename to drivers/net/ethernet/pasemi/pasemi_mac.c
index 9ec112c..fad620d 100644 (file)
@@ -1719,7 +1719,7 @@ static const struct net_device_ops pasemi_netdev_ops = {
        .ndo_open               = pasemi_mac_open,
        .ndo_stop               = pasemi_mac_close,
        .ndo_start_xmit         = pasemi_mac_start_tx,
-       .ndo_set_multicast_list = pasemi_mac_set_rx_mode,
+       .ndo_set_rx_mode        = pasemi_mac_set_rx_mode,
        .ndo_set_mac_address    = pasemi_mac_set_mac_addr,
        .ndo_change_mtu         = pasemi_mac_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig
new file mode 100644 (file)
index 0000000..a8669ad
--- /dev/null
@@ -0,0 +1,54 @@
+#
+# QLogic network device configuration
+#
+
+config NET_VENDOR_QLOGIC
+       bool "QLogic devices"
+       default y
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about QLogic cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_QLOGIC
+
+config QLA3XXX
+       tristate "QLogic QLA3XXX Network Driver Support"
+       depends on PCI
+       ---help---
+         This driver supports QLogic ISP3XXX gigabit Ethernet cards.
+
+         To compile this driver as a module, choose M here: the module
+         will be called qla3xxx.
+
+config QLCNIC
+       tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support"
+       depends on PCI
+       select FW_LOADER
+       ---help---
+         This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet
+         devices.
+
+config QLGE
+       tristate "QLogic QLGE 10Gb Ethernet Driver Support"
+       depends on PCI
+       ---help---
+         This driver supports QLogic ISP8XXX 10Gb Ethernet cards.
+
+         To compile this driver as a module, choose M here: the module
+         will be called qlge.
+
+config NETXEN_NIC
+       tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
+       depends on PCI
+       select FW_LOADER
+       ---help---
+         This enables the support for NetXen's Gigabit Ethernet card.
+
+endif # NET_VENDOR_QLOGIC
diff --git a/drivers/net/ethernet/qlogic/Makefile b/drivers/net/ethernet/qlogic/Makefile
new file mode 100644 (file)
index 0000000..b2a283d
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for the QLogic network device drivers.
+#
+
+obj-$(CONFIG_QLA3XXX) += qla3xxx.o
+obj-$(CONFIG_QLCNIC) += qlcnic/
+obj-$(CONFIG_QLGE) += qlge/
+obj-$(CONFIG_NETXEN_NIC) += netxen/
similarity index 99%
rename from drivers/net/netxen/netxen_nic.h
rename to drivers/net/ethernet/qlogic/netxen/netxen_nic.h
index f744d29..196b660 100644 (file)
@@ -940,6 +940,11 @@ typedef struct nx_mac_list_s {
        uint8_t mac_addr[ETH_ALEN+2];
 } nx_mac_list_t;
 
+struct nx_vlan_ip_list {
+       struct list_head list;
+       u32 ip_addr;
+};
+
 /*
  * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is
  * adjusted based on configured MTU.
@@ -1165,6 +1170,7 @@ struct netxen_adapter {
        struct net_device *netdev;
        struct pci_dev *pdev;
        struct list_head mac_list;
+       struct list_head vlan_ip_list;
 
        spinlock_t tx_clean_lock;
 
similarity index 99%
rename from drivers/net/netxen/netxen_nic_init.c
rename to drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
index e8993a7..d6c6357 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/netdevice.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/if_vlan.h>
 #include "netxen_nic.h"
 #include "netxen_nic_hw.h"
 
@@ -1619,6 +1620,7 @@ netxen_process_lro(struct netxen_adapter *adapter,
        int index;
        u16 lro_length, length, data_offset;
        u32 seq_number;
+       u8 vhdr_len;
 
        if (unlikely(ring > adapter->max_rds_rings))
                return NULL;
@@ -1652,8 +1654,10 @@ netxen_process_lro(struct netxen_adapter *adapter,
        skb_pull(skb, l2_hdr_offset);
        skb->protocol = eth_type_trans(skb, netdev);
 
-       iph = (struct iphdr *)skb->data;
-       th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
+       if (skb->protocol == htons(ETH_P_8021Q))
+               vhdr_len = VLAN_HLEN;
+       iph = (struct iphdr *)(skb->data + vhdr_len);
+       th = (struct tcphdr *)((skb->data + vhdr_len) + (iph->ihl << 2));
 
        length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
        iph->tot_len = htons(length);
similarity index 96%
rename from drivers/net/netxen/netxen_nic_main.c
rename to drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index f574edf..de18e47 100644 (file)
@@ -91,7 +91,8 @@ static irqreturn_t netxen_intr(int irq, void *data);
 static irqreturn_t netxen_msi_intr(int irq, void *data);
 static irqreturn_t netxen_msix_intr(int irq, void *data);
 
-static void netxen_config_indev_addr(struct net_device *dev, unsigned long);
+static void netxen_free_vlan_ip_list(struct netxen_adapter *);
+static void netxen_restore_indev_addr(struct net_device *dev, unsigned long);
 static struct rtnl_link_stats64 *netxen_nic_get_stats(struct net_device *dev,
                                                      struct rtnl_link_stats64 *stats);
 static int netxen_nic_set_mac(struct net_device *netdev, void *p);
@@ -523,7 +524,7 @@ static const struct net_device_ops netxen_netdev_ops = {
        .ndo_start_xmit    = netxen_nic_xmit_frame,
        .ndo_get_stats64   = netxen_nic_get_stats,
        .ndo_validate_addr = eth_validate_addr,
-       .ndo_set_multicast_list = netxen_set_multicast_list,
+       .ndo_set_rx_mode   = netxen_set_multicast_list,
        .ndo_set_mac_address    = netxen_nic_set_mac,
        .ndo_change_mtu    = netxen_nic_change_mtu,
        .ndo_tx_timeout    = netxen_tx_timeout,
@@ -1359,6 +1360,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        spin_lock_init(&adapter->tx_clean_lock);
        INIT_LIST_HEAD(&adapter->mac_list);
+       INIT_LIST_HEAD(&adapter->vlan_ip_list);
 
        err = netxen_setup_pci_map(adapter);
        if (err)
@@ -1481,6 +1483,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
 
        cancel_work_sync(&adapter->tx_timeout_task);
 
+       netxen_free_vlan_ip_list(adapter);
        netxen_nic_detach(adapter);
 
        nx_decr_dev_ref_cnt(adapter);
@@ -1563,7 +1566,7 @@ static int netxen_nic_attach_func(struct pci_dev *pdev)
                if (err)
                        goto err_out_detach;
 
-               netxen_config_indev_addr(netdev, NETDEV_UP);
+               netxen_restore_indev_addr(netdev, NETDEV_UP);
        }
 
        netif_device_attach(netdev);
@@ -2374,7 +2377,7 @@ netxen_attach_work(struct work_struct *work)
                        goto done;
                }
 
-               netxen_config_indev_addr(netdev, NETDEV_UP);
+               netxen_restore_indev_addr(netdev, NETDEV_UP);
        }
 
        netif_device_attach(netdev);
@@ -2848,10 +2851,70 @@ netxen_destip_supported(struct netxen_adapter *adapter)
 }
 
 static void
-netxen_config_indev_addr(struct net_device *dev, unsigned long event)
+netxen_free_vlan_ip_list(struct netxen_adapter *adapter)
+{
+       struct nx_vlan_ip_list  *cur;
+       struct list_head *head = &adapter->vlan_ip_list;
+
+       while (!list_empty(head)) {
+               cur = list_entry(head->next, struct nx_vlan_ip_list, list);
+               netxen_config_ipaddr(adapter, cur->ip_addr, NX_IP_DOWN);
+               list_del(&cur->list);
+               kfree(cur);
+       }
+
+}
+static void
+netxen_list_config_vlan_ip(struct netxen_adapter *adapter,
+               struct in_ifaddr *ifa, unsigned long event)
+{
+       struct net_device *dev;
+       struct nx_vlan_ip_list *cur, *tmp_cur;
+       struct list_head *head;
+
+       dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
+
+       if (dev == NULL)
+               return;
+
+       if (!is_vlan_dev(dev))
+               return;
+
+       switch (event) {
+       case NX_IP_UP:
+               list_for_each(head, &adapter->vlan_ip_list) {
+                       cur = list_entry(head, struct nx_vlan_ip_list, list);
+
+                       if (cur->ip_addr == ifa->ifa_address)
+                               return;
+               }
+
+               cur = kzalloc(sizeof(struct nx_vlan_ip_list), GFP_ATOMIC);
+               if (cur == NULL) {
+                       printk(KERN_ERR "%s: failed to add vlan ip to list\n",
+                                       adapter->netdev->name);
+                       return;
+               }
+
+               cur->ip_addr = ifa->ifa_address;
+               list_add_tail(&cur->list, &adapter->vlan_ip_list);
+               break;
+       case NX_IP_DOWN:
+               list_for_each_entry_safe(cur, tmp_cur,
+                                       &adapter->vlan_ip_list, list) {
+                       if (cur->ip_addr == ifa->ifa_address) {
+                               list_del(&cur->list);
+                               kfree(cur);
+                               break;
+                       }
+               }
+       }
+}
+static void
+netxen_config_indev_addr(struct netxen_adapter *adapter,
+               struct net_device *dev, unsigned long event)
 {
        struct in_device *indev;
-       struct netxen_adapter *adapter = netdev_priv(dev);
 
        if (!netxen_destip_supported(adapter))
                return;
@@ -2865,10 +2928,12 @@ netxen_config_indev_addr(struct net_device *dev, unsigned long event)
                case NETDEV_UP:
                        netxen_config_ipaddr(adapter,
                                        ifa->ifa_address, NX_IP_UP);
+                       netxen_list_config_vlan_ip(adapter, ifa, NX_IP_UP);
                        break;
                case NETDEV_DOWN:
                        netxen_config_ipaddr(adapter,
                                        ifa->ifa_address, NX_IP_DOWN);
+                       netxen_list_config_vlan_ip(adapter, ifa, NX_IP_DOWN);
                        break;
                default:
                        break;
@@ -2878,11 +2943,28 @@ netxen_config_indev_addr(struct net_device *dev, unsigned long event)
        in_dev_put(indev);
 }
 
+static void
+netxen_restore_indev_addr(struct net_device *netdev, unsigned long event)
+
+{
+       struct netxen_adapter *adapter = netdev_priv(netdev);
+       struct nx_vlan_ip_list *pos, *tmp_pos;
+       unsigned long ip_event;
+
+       ip_event = (event == NETDEV_UP) ? NX_IP_UP : NX_IP_DOWN;
+       netxen_config_indev_addr(adapter, netdev, event);
+
+       list_for_each_entry_safe(pos, tmp_pos, &adapter->vlan_ip_list, list) {
+               netxen_config_ipaddr(adapter, pos->ip_addr, ip_event);
+       }
+}
+
 static int netxen_netdev_event(struct notifier_block *this,
                                 unsigned long event, void *ptr)
 {
        struct netxen_adapter *adapter;
        struct net_device *dev = (struct net_device *)ptr;
+       struct net_device *orig_dev = dev;
 
 recheck:
        if (dev == NULL)
@@ -2904,7 +2986,7 @@ recheck:
        if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
                goto done;
 
-       netxen_config_indev_addr(dev, event);
+       netxen_config_indev_addr(adapter, orig_dev, event);
 done:
        return NOTIFY_DONE;
 }
@@ -2921,7 +3003,7 @@ netxen_inetaddr_event(struct notifier_block *this,
        dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
 
 recheck:
-       if (dev == NULL || !netif_running(dev))
+       if (dev == NULL)
                goto done;
 
        if (dev->priv_flags & IFF_802_1Q_VLAN) {
@@ -2943,9 +3025,11 @@ recheck:
        switch (event) {
        case NETDEV_UP:
                netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP);
+               netxen_list_config_vlan_ip(adapter, ifa, NX_IP_UP);
                break;
        case NETDEV_DOWN:
                netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_DOWN);
+               netxen_list_config_vlan_ip(adapter, ifa, NX_IP_DOWN);
                break;
        default:
                break;
@@ -2964,7 +3048,10 @@ static struct notifier_block netxen_inetaddr_cb = {
 };
 #else
 static void
-netxen_config_indev_addr(struct net_device *dev, unsigned long event)
+netxen_restore_indev_addr(struct net_device *dev, unsigned long event)
+{ }
+static void
+netxen_free_vlan_ip_list(struct netxen_adapter *adapter)
 { }
 #endif
 
similarity index 99%
rename from drivers/net/qla3xxx.c
rename to drivers/net/ethernet/qlogic/qla3xxx.c
index 2f69140..8cab61c 100644 (file)
@@ -1650,7 +1650,7 @@ static int ql_mii_setup(struct ql3_adapter *qdev)
                                 SUPPORTED_1000baseT_Half |     \
                                 SUPPORTED_1000baseT_Full |     \
                                 SUPPORTED_Autoneg |            \
-                                SUPPORTED_TP);                 \
+                                SUPPORTED_TP)                  \
 
 static u32 ql_supported_modes(struct ql3_adapter *qdev)
 {
@@ -3762,7 +3762,6 @@ static const struct net_device_ops ql3xxx_netdev_ops = {
        .ndo_open               = ql3xxx_open,
        .ndo_start_xmit         = ql3xxx_send,
        .ndo_stop               = ql3xxx_close,
-       .ndo_set_multicast_list = NULL, /* not allowed on NIC side */
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ql3xxx_set_mac_address,
similarity index 99%
rename from drivers/net/qlcnic/qlcnic.h
rename to drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index baf646d..53c6e5d 100644 (file)
@@ -36,8 +36,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 21
-#define QLCNIC_LINUX_VERSIONID  "5.0.21"
+#define _QLCNIC_LINUX_SUBVERSION 22
+#define QLCNIC_LINUX_VERSIONID  "5.0.22"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
                 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -911,6 +911,7 @@ struct qlcnic_ipaddr {
 #define QLCNIC_PROMISC_DISABLED                0x800
 #define QLCNIC_NEED_FLR                        0x1000
 #define QLCNIC_FW_RESET_OWNER          0x2000
+#define QLCNIC_FW_HANG                 0x4000
 #define QLCNIC_IS_MSI_FAMILY(adapter) \
        ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
 
@@ -1344,6 +1345,7 @@ enum op_codes {
 #define QLCNIC_FORCE_FW_DUMP_KEY       0xdeadfeed
 #define QLCNIC_ENABLE_FW_DUMP          0xaddfeed
 #define QLCNIC_DISABLE_FW_DUMP         0xbadfeed
+#define QLCNIC_FORCE_FW_RESET          0xdeaddead
 
 struct qlcnic_dump_operations {
        enum op_codes opcode;
similarity index 98%
rename from drivers/net/qlcnic/qlcnic_ethtool.c
rename to drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 72a723d..7c64f2f 100644 (file)
@@ -1105,7 +1105,10 @@ qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
 
-       dump->len = fw_dump->tmpl_hdr->size + fw_dump->size;
+       if (fw_dump->clr)
+               dump->len = fw_dump->tmpl_hdr->size + fw_dump->size;
+       else
+               dump->len = 0;
        dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
        dump->version = adapter->fw_version;
        return 0;
@@ -1152,7 +1155,8 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
 
-       if (val->flag == QLCNIC_FORCE_FW_DUMP_KEY) {
+       switch (val->flag) {
+       case QLCNIC_FORCE_FW_DUMP_KEY:
                if (!fw_dump->enable) {
                        netdev_info(netdev, "FW dump not enabled\n");
                        return ret;
@@ -1164,17 +1168,25 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
                }
                netdev_info(netdev, "Forcing a FW dump\n");
                qlcnic_dev_request_reset(adapter);
-       } else if (val->flag == QLCNIC_DISABLE_FW_DUMP) {
+               break;
+       case QLCNIC_DISABLE_FW_DUMP:
                if (fw_dump->enable) {
                        netdev_info(netdev, "Disabling FW dump\n");
                        fw_dump->enable = 0;
                }
-       } else if (val->flag == QLCNIC_ENABLE_FW_DUMP) {
+               break;
+       case QLCNIC_ENABLE_FW_DUMP:
                if (!fw_dump->enable && fw_dump->tmpl_hdr) {
                        netdev_info(netdev, "Enabling FW dump\n");
                        fw_dump->enable = 1;
                }
-       } else {
+               break;
+       case QLCNIC_FORCE_FW_RESET:
+               netdev_info(netdev, "Forcing a FW reset\n");
+               qlcnic_dev_request_reset(adapter);
+               adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
+               break;
+       default:
                if (val->flag > QLCNIC_DUMP_MASK_MAX ||
                        val->flag < QLCNIC_DUMP_MASK_MIN) {
                                netdev_info(netdev,
similarity index 99%
rename from drivers/net/qlcnic/qlcnic_hw.c
rename to drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 4055c21..74e9d7b 100644 (file)
@@ -1773,8 +1773,8 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
                goto error;
        } else {
                fw_dump->clr = 1;
-               snprintf(mesg, sizeof(mesg), "FW dump for device: %d\n",
-                       adapter->pdev->devfn);
+               snprintf(mesg, sizeof(mesg), "FW_DUMP=%s",
+                       adapter->netdev->name);
                dev_info(&adapter->pdev->dev, "Dump data, %d bytes captured\n",
                        fw_dump->size);
                /* Send a udev event to notify availability of FW dump */
similarity index 99%
rename from drivers/net/qlcnic/qlcnic_init.c
rename to drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
index ee8a398..3b6741e 100644 (file)
@@ -1056,7 +1056,8 @@ qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter)
 int
 qlcnic_need_fw_reset(struct qlcnic_adapter *adapter)
 {
-       if (qlcnic_check_fw_hearbeat(adapter)) {
+       if ((adapter->flags & QLCNIC_FW_HANG) ||
+                       qlcnic_check_fw_hearbeat(adapter)) {
                qlcnic_rom_lock_recovery(adapter);
                return 1;
        }
similarity index 98%
rename from drivers/net/qlcnic/qlcnic_main.c
rename to drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 5ca1b56..b447cc5 100644 (file)
@@ -325,7 +325,7 @@ static const struct net_device_ops qlcnic_netdev_ops = {
        .ndo_start_xmit    = qlcnic_xmit_frame,
        .ndo_get_stats     = qlcnic_get_stats,
        .ndo_validate_addr = eth_validate_addr,
-       .ndo_set_multicast_list = qlcnic_set_multi,
+       .ndo_set_rx_mode   = qlcnic_set_multi,
        .ndo_set_mac_address    = qlcnic_set_mac,
        .ndo_change_mtu    = qlcnic_change_mtu,
        .ndo_fix_features  = qlcnic_fix_features,
@@ -643,8 +643,11 @@ static void get_brd_name(struct qlcnic_adapter *adapter, char *name)
 static void
 qlcnic_check_options(struct qlcnic_adapter *adapter)
 {
-       u32 fw_major, fw_minor, fw_build;
+       u32 fw_major, fw_minor, fw_build, prev_fw_version;
        struct pci_dev *pdev = adapter->pdev;
+       struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
+
+       prev_fw_version = adapter->fw_version;
 
        fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
        fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
@@ -652,6 +655,17 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
 
        adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
 
+       if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC) {
+               if (fw_dump->tmpl_hdr == NULL ||
+                               adapter->fw_version > prev_fw_version) {
+                       if (fw_dump->tmpl_hdr)
+                               vfree(fw_dump->tmpl_hdr);
+                       if (!qlcnic_fw_cmd_get_minidump_temp(adapter))
+                               dev_info(&pdev->dev,
+                                       "Supports FW dump capability\n");
+               }
+       }
+
        dev_info(&pdev->dev, "firmware v%d.%d.%d\n",
                        fw_major, fw_minor, fw_build);
        if (adapter->ahw->port_type == QLCNIC_XGBE) {
@@ -1610,12 +1624,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_out_decr_ref;
        }
 
-       /* Get FW dump template and store it */
-       if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC)
-               if (!qlcnic_fw_cmd_get_minidump_temp(adapter))
-                       dev_info(&pdev->dev,
-                               "Supports FW dump capability\n");
-
        if (qlcnic_read_mac_addr(adapter))
                dev_warn(&pdev->dev, "failed to read mac addr\n");
 
@@ -2682,6 +2690,7 @@ qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
        qlcnic_api_unlock(adapter);
 err:
        adapter->fw_fail_cnt = 0;
+       adapter->flags &= ~QLCNIC_FW_HANG;
        clear_bit(__QLCNIC_START_FW, &adapter->state);
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
 }
@@ -2859,6 +2868,7 @@ skip_ack_check:
                    (adapter->flags & QLCNIC_FW_RESET_OWNER)) {
                        QLCDB(adapter, DRV, "Take FW dump\n");
                        qlcnic_dump_fw(adapter);
+                       adapter->flags |= QLCNIC_FW_HANG;
                }
                rtnl_unlock();
 
@@ -3046,6 +3056,7 @@ attach:
 done:
        netif_device_attach(netdev);
        adapter->fw_fail_cnt = 0;
+       adapter->flags &= ~QLCNIC_FW_HANG;
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
 
        if (!qlcnic_clr_drv_state(adapter))
@@ -3090,13 +3101,26 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
        if (++adapter->fw_fail_cnt < FW_FAIL_THRESH)
                return 0;
 
+       adapter->flags |= QLCNIC_FW_HANG;
+
        qlcnic_dev_request_reset(adapter);
 
        if (auto_fw_reset)
                clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
 
        dev_info(&netdev->dev, "firmware hang detected\n");
-
+       dev_info(&adapter->pdev->dev, "Dumping hw/fw registers\n"
+                       "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n"
+                       "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n"
+                       "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n"
+                       "PEG_NET_4_PC: 0x%x\n",
+                       QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1),
+                       QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS2),
+                       QLCRD32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x3c),
+                       QLCRD32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x3c),
+                       QLCRD32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c),
+                       QLCRD32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c),
+                       QLCRD32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c));
 detach:
        adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state :
                QLCNIC_DEV_NEED_RESET;
similarity index 99%
rename from drivers/net/qlge/qlge_main.c
rename to drivers/net/ethernet/qlogic/qlge/qlge_main.c
index f07e96e..39360c4 100644 (file)
@@ -4676,7 +4676,7 @@ static const struct net_device_ops qlge_netdev_ops = {
        .ndo_start_xmit         = qlge_send,
        .ndo_change_mtu         = qlge_change_mtu,
        .ndo_get_stats          = qlge_get_stats,
-       .ndo_set_multicast_list = qlge_set_multicast_list,
+       .ndo_set_rx_mode        = qlge_set_multicast_list,
        .ndo_set_mac_address    = qlge_set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = qlge_tx_timeout,
diff --git a/drivers/net/ethernet/racal/Kconfig b/drivers/net/ethernet/racal/Kconfig
new file mode 100644 (file)
index 0000000..01969e0
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# Racal-Interlan device configuration
+#
+
+config NET_VENDOR_RACAL
+       bool "Racal-Interlan (Micom) NI devices"
+       default y
+       depends on ISA
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, such
+         as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
+         available from <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about NI cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_RACAL
+
+config NI5010
+       tristate "NI5010 support (EXPERIMENTAL)"
+       depends on ISA && EXPERIMENTAL && BROKEN_ON_SMP
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>. Note that this is still
+         experimental code.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ni5010.
+
+endif # NET_VENDOR_RACAL
diff --git a/drivers/net/ethernet/racal/Makefile b/drivers/net/ethernet/racal/Makefile
new file mode 100644 (file)
index 0000000..1e210ca
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Racal-Interlan network device drivers.
+#
+
+obj-$(CONFIG_NI5010) += ni5010.o
similarity index 99%
rename from drivers/net/ni5010.c
rename to drivers/net/ethernet/racal/ni5010.c
index 4d3f2e2..072810d 100644 (file)
@@ -192,7 +192,7 @@ static const struct net_device_ops ni5010_netdev_ops = {
        .ndo_open               = ni5010_open,
        .ndo_stop               = ni5010_close,
        .ndo_start_xmit         = ni5010_send_packet,
-       .ndo_set_multicast_list = ni5010_set_multicast_list,
+       .ndo_set_rx_mode        = ni5010_set_multicast_list,
        .ndo_tx_timeout         = ni5010_timeout,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
diff --git a/drivers/net/ethernet/rdc/Kconfig b/drivers/net/ethernet/rdc/Kconfig
new file mode 100644 (file)
index 0000000..2055f7e
--- /dev/null
@@ -0,0 +1,34 @@
+#
+# RDC network device configuration
+#
+
+config NET_VENDOR_RDC
+       bool "RDC devices"
+       default y
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about RDC cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_RDC
+
+config R6040
+       tristate "RDC R6040 Fast Ethernet Adapter support"
+       depends on PCI
+       select CRC32
+       select MII
+       select PHYLIB
+       ---help---
+         This is a driver for the R6040 Fast Ethernet MACs found in the
+         the RDC R-321x System-on-chips.
+
+         To compile this driver as a module, choose M here: the module
+         will be called r6040. This is recommended.
+
+endif # NET_VENDOR_RDC
diff --git a/drivers/net/ethernet/rdc/Makefile b/drivers/net/ethernet/rdc/Makefile
new file mode 100644 (file)
index 0000000..8d51fd2
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the RDC network device drivers.
+#
+
+obj-$(CONFIG_R6040) += r6040.o
similarity index 99%
rename from drivers/net/r6040.c
rename to drivers/net/ethernet/rdc/r6040.c
index b64fcee..2bbadc0 100644 (file)
@@ -982,7 +982,7 @@ static const struct net_device_ops r6040_netdev_ops = {
        .ndo_stop               = r6040_close,
        .ndo_start_xmit         = r6040_start_xmit,
        .ndo_get_stats          = r6040_get_stats,
-       .ndo_set_multicast_list = r6040_multicast_list,
+       .ndo_set_rx_mode        = r6040_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/8139cp.c
rename to drivers/net/ethernet/realtek/8139cp.c
index cc4c210..5d2d1b8 100644 (file)
@@ -1785,7 +1785,7 @@ static const struct net_device_ops cp_netdev_ops = {
        .ndo_stop               = cp_close,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = cp_set_mac_address,
-       .ndo_set_multicast_list = cp_set_rx_mode,
+       .ndo_set_rx_mode        = cp_set_rx_mode,
        .ndo_get_stats          = cp_get_stats,
        .ndo_do_ioctl           = cp_ioctl,
        .ndo_start_xmit         = cp_start_xmit,
similarity index 99%
rename from drivers/net/8139too.c
rename to drivers/net/ethernet/realtek/8139too.c
index c2672c6..4d6b254 100644 (file)
@@ -916,7 +916,7 @@ static const struct net_device_ops rtl8139_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = rtl8139_set_mac_address,
        .ndo_start_xmit         = rtl8139_start_xmit,
-       .ndo_set_multicast_list = rtl8139_set_rx_mode,
+       .ndo_set_rx_mode        = rtl8139_set_rx_mode,
        .ndo_do_ioctl           = netdev_ioctl,
        .ndo_tx_timeout         = rtl8139_tx_timeout,
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig
new file mode 100644 (file)
index 0000000..d8df67a
--- /dev/null
@@ -0,0 +1,127 @@
+#
+# Realtek device configuration
+#
+
+config NET_VENDOR_REALTEK
+       bool "Realtek devices"
+       default y
+       depends on PCI || (PARPORT && X86)
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Realtek devices. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_REALTEK
+
+config ATP
+       tristate "AT-LAN-TEC/RealTek pocket adapter support"
+       depends on PARPORT && X86
+       select CRC32
+       ---help---
+         This is a network (Ethernet) device which attaches to your parallel
+         port. Read <file:drivers/net/atp.c> as well as the Ethernet-HOWTO,
+         available from <http://www.tldp.org/docs.html#howto>, if you
+         want to use this.  If you intend to use this driver, you should have
+         said N to the "Parallel printer support", because the two drivers
+         don't like each other.
+
+         To compile this driver as a module, choose M here: the module
+         will be called atp.
+
+config 8139CP
+       tristate "RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL)"
+       depends on PCI && EXPERIMENTAL
+       select CRC32
+       select MII
+       ---help---
+         This is a driver for the Fast Ethernet PCI network cards based on
+         the RTL8139C+ chips. If you have one of those, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here: the module
+         will be called 8139cp.  This is recommended.
+
+config 8139TOO
+       tristate "RealTek RTL-8129/8130/8139 PCI Fast Ethernet Adapter support"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         This is a driver for the Fast Ethernet PCI network cards based on
+         the RTL 8129/8130/8139 chips. If you have one of those, say Y and
+         read the Ethernet-HOWTO <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here: the module
+         will be called 8139too.  This is recommended.
+
+config 8139TOO_PIO
+       bool "Use PIO instead of MMIO"
+       default y
+       depends on 8139TOO
+       ---help---
+         This instructs the driver to use programmed I/O ports (PIO) instead
+         of PCI shared memory (MMIO).  This can possibly solve some problems
+         in case your mainboard has memory consistency issues.  If unsure,
+         say N.
+
+config 8139TOO_TUNE_TWISTER
+       bool "Support for uncommon RTL-8139 rev. K (automatic channel equalization)"
+       depends on 8139TOO
+       ---help---
+         This implements a function which might come in handy in case you
+         are using low quality on long cabling. It is required for RealTek
+         RTL-8139 revision K boards, and totally unused otherwise.  It tries
+         to match the transceiver to the cable characteristics. This is
+         experimental since hardly documented by the manufacturer.
+         If unsure, say Y.
+
+config 8139TOO_8129
+       bool "Support for older RTL-8129/8130 boards"
+       depends on 8139TOO
+       ---help---
+         This enables support for the older and uncommon RTL-8129 and
+         RTL-8130 chips, which support MII via an external transceiver,
+         instead of an internal one.  Disabling this option will save some
+         memory by making the code size smaller.  If unsure, say Y.
+
+config 8139_OLD_RX_RESET
+       bool "Use older RX-reset method"
+       depends on 8139TOO
+       ---help---
+         The 8139too driver was recently updated to contain a more rapid
+         reset sequence, in the face of severe receive errors.  This "new"
+         RX-reset method should be adequate for all boards.  But if you
+         experience problems, you can enable this option to restore the
+         old RX-reset behavior.  If unsure, say N.
+
+config R8169
+       tristate "Realtek 8169 gigabit ethernet support"
+       depends on PCI
+       select FW_LOADER
+       select CRC32
+       select MII
+       ---help---
+         Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter.
+
+         To compile this driver as a module, choose M here: the module
+         will be called r8169.  This is recommended.
+
+config SC92031
+       tristate "Silan SC92031 PCI Fast Ethernet Adapter driver (EXPERIMENTAL)"
+       depends on PCI && EXPERIMENTAL
+       select CRC32
+       ---help---
+         This is a driver for the Fast Ethernet PCI network cards based on
+         the Silan SC92031 chip (sometimes also called Rsltek 8139D). If you
+         have one of these, say Y here.
+
+         To compile this driver as a module, choose M here: the module
+         will be called sc92031.  This is recommended.
+
+endif # NET_VENDOR_REALTEK
diff --git a/drivers/net/ethernet/realtek/Makefile b/drivers/net/ethernet/realtek/Makefile
new file mode 100644 (file)
index 0000000..e48cfb6
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for the Realtek network device drivers.
+#
+
+obj-$(CONFIG_8139CP) += 8139cp.o
+obj-$(CONFIG_8139TOO) += 8139too.o
+obj-$(CONFIG_ATP) += atp.o
+obj-$(CONFIG_R8169) += r8169.o
+obj-$(CONFIG_SC92031) += sc92031.o
similarity index 99%
rename from drivers/net/atp.c
rename to drivers/net/ethernet/realtek/atp.c
index f345979..e3f57fd 100644 (file)
@@ -245,7 +245,7 @@ static const struct net_device_ops atp_netdev_ops = {
        .ndo_open               = net_open,
        .ndo_stop               = net_close,
        .ndo_start_xmit         = atp_send_packet,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_tx_timeout         = tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/r8169.c
rename to drivers/net/ethernet/realtek/r8169.c
index 7d9c650..1cf8c3c 100644 (file)
@@ -239,6 +239,7 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
        { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8168), 0, 0, RTL_CFG_1 },
        { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8169), 0, 0, RTL_CFG_0 },
        { PCI_DEVICE(PCI_VENDOR_ID_DLINK,       0x4300), 0, 0, RTL_CFG_0 },
+       { PCI_DEVICE(PCI_VENDOR_ID_DLINK,       0x4302), 0, 0, RTL_CFG_0 },
        { PCI_DEVICE(PCI_VENDOR_ID_AT,          0xc107), 0, 0, RTL_CFG_0 },
        { PCI_DEVICE(0x16ec,                    0x0116), 0, 0, RTL_CFG_0 },
        { PCI_VENDOR_ID_LINKSYS,                0x1032,
@@ -1091,6 +1092,21 @@ rtl_w1w0_eri(void __iomem *ioaddr, int addr, u32 mask, u32 p, u32 m, int type)
        rtl_eri_write(ioaddr, addr, mask, (val & ~m) | p, type);
 }
 
+struct exgmac_reg {
+       u16 addr;
+       u16 mask;
+       u32 val;
+};
+
+static void rtl_write_exgmac_batch(void __iomem *ioaddr,
+                                  const struct exgmac_reg *r, int len)
+{
+       while (len-- > 0) {
+               rtl_eri_write(ioaddr, r->addr, r->mask, r->val, ERIAR_EXGMAC);
+               r++;
+       }
+}
+
 static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr)
 {
        u8 value = 0xff;
@@ -3116,6 +3132,18 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
        RTL_W32(MAC0, low);
        RTL_R32(MAC0);
 
+       if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
+               const struct exgmac_reg e[] = {
+                       { .addr = 0xe0, ERIAR_MASK_1111, .val = low },
+                       { .addr = 0xe4, ERIAR_MASK_1111, .val = high },
+                       { .addr = 0xf0, ERIAR_MASK_1111, .val = low << 16 },
+                       { .addr = 0xf4, ERIAR_MASK_1111, .val = high << 16 |
+                                                               low  >> 16 },
+               };
+
+               rtl_write_exgmac_batch(ioaddr, e, ARRAY_SIZE(e));
+       }
+
        RTL_W8(Cfg9346, Cfg9346_Lock);
 
        spin_unlock_irq(&tp->lock);
@@ -3249,7 +3277,7 @@ static const struct net_device_ops rtl8169_netdev_ops = {
        .ndo_set_features       = rtl8169_set_features,
        .ndo_set_mac_address    = rtl_set_mac_address,
        .ndo_do_ioctl           = rtl8169_ioctl,
-       .ndo_set_multicast_list = rtl_set_rx_mode,
+       .ndo_set_rx_mode        = rtl_set_rx_mode,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = rtl8169_netpoll,
 #endif
similarity index 99%
rename from drivers/net/sc92031.c
rename to drivers/net/ethernet/realtek/sc92031.c
index 9da4733..128f8eb 100644 (file)
@@ -1390,7 +1390,7 @@ static const struct net_device_ops sc92031_netdev_ops = {
        .ndo_start_xmit         = sc92031_start_xmit,
        .ndo_open               = sc92031_open,
        .ndo_stop               = sc92031_stop,
-       .ndo_set_multicast_list = sc92031_set_multicast_list,
+       .ndo_set_rx_mode        = sc92031_set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig
new file mode 100644 (file)
index 0000000..f57ae23
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Renesas device configuration
+#
+
+config SH_ETH
+       tristate "Renesas SuperH Ethernet support"
+       depends on SUPERH && \
+               (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
+                CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
+                CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7757)
+       select CRC32
+       select MII
+       select MDIO_BITBANG
+       select PHYLIB
+       ---help---
+         Renesas SuperH Ethernet device driver.
+         This driver supporting CPUs are:
+               - SH7710, SH7712, SH7763, SH7619, SH7724, and SH7757.
diff --git a/drivers/net/ethernet/renesas/Makefile b/drivers/net/ethernet/renesas/Makefile
new file mode 100644 (file)
index 0000000..1c278a8
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Renesas device drivers.
+#
+
+obj-$(CONFIG_SH_ETH) += sh_eth.o
similarity index 99%
rename from drivers/net/sh_eth.c
rename to drivers/net/ethernet/renesas/sh_eth.c
index ad35c21..bf2404a 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
@@ -1758,7 +1759,7 @@ static const struct net_device_ops sh_eth_netdev_ops = {
        .ndo_start_xmit         = sh_eth_start_xmit,
        .ndo_get_stats          = sh_eth_get_stats,
 #if defined(SH_ETH_HAS_TSU)
-       .ndo_set_multicast_list = sh_eth_set_multicast_list,
+       .ndo_set_rx_mode        = sh_eth_set_multicast_list,
 #endif
        .ndo_tx_timeout         = sh_eth_tx_timeout,
        .ndo_do_ioctl           = sh_eth_do_ioctl,
diff --git a/drivers/net/ethernet/seeq/Kconfig b/drivers/net/ethernet/seeq/Kconfig
new file mode 100644 (file)
index 0000000..49b6d5b
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# SEEQ device configuration
+#
+
+config NET_VENDOR_SEEQ
+       bool "SEEQ devices"
+       default y
+       depends on (ARM && ARCH_ACORN) || SGI_HAS_SEEQ || EXPERIMENTAL
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about SEEQ devices. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_SEEQ
+
+config ARM_ETHER3
+       tristate "Acorn/ANT Ether3 support"
+       depends on ARM && ARCH_ACORN
+       ---help---
+         If you have an Acorn system with one of these network cards, you
+         should say Y to this option if you wish to use it with Linux.
+
+config SEEQ8005
+       tristate "SEEQ8005 support (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       ---help---
+         This is a driver for the SEEQ 8005 network (Ethernet) card.  If this
+         is for you, read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called seeq8005.
+
+config SGISEEQ
+       tristate "SGI Seeq ethernet controller support"
+       depends on SGI_HAS_SEEQ
+       ---help---
+         Say Y here if you have an Seeq based Ethernet network card. This is
+         used in many Silicon Graphics machines.
+
+endif # NET_VENDOR_SEEQ
diff --git a/drivers/net/ethernet/seeq/Makefile b/drivers/net/ethernet/seeq/Makefile
new file mode 100644 (file)
index 0000000..3e258a5
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the SEEQ network device drivers
+#
+
+obj-$(CONFIG_ARM_ETHER3) += ether3.o
+obj-$(CONFIG_SEEQ8005) += seeq8005.o
+obj-$(CONFIG_SGISEEQ) += sgiseeq.o
similarity index 99%
rename from drivers/net/arm/ether3.c
rename to drivers/net/ethernet/seeq/ether3.c
index 44a8746..893c880 100644 (file)
@@ -761,7 +761,7 @@ static const struct net_device_ops ether3_netdev_ops = {
        .ndo_open               = ether3_open,
        .ndo_stop               = ether3_close,
        .ndo_start_xmit         = ether3_sendpacket,
-       .ndo_set_multicast_list = ether3_setmulticastlist,
+       .ndo_set_rx_mode        = ether3_setmulticastlist,
        .ndo_tx_timeout         = ether3_timeout,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/seeq8005.c
rename to drivers/net/ethernet/seeq/seeq8005.c
index d2fce98..6056145 100644 (file)
@@ -148,7 +148,7 @@ static const struct net_device_ops seeq8005_netdev_ops = {
        .ndo_stop               = seeq8005_close,
        .ndo_start_xmit         = seeq8005_send_packet,
        .ndo_tx_timeout         = seeq8005_timeout,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/sgiseeq.c
rename to drivers/net/ethernet/seeq/sgiseeq.c
index 52fb7ed..c3673f1 100644 (file)
@@ -715,7 +715,7 @@ static const struct net_device_ops sgiseeq_netdev_ops = {
        .ndo_stop               = sgiseeq_close,
        .ndo_start_xmit         = sgiseeq_start_xmit,
        .ndo_tx_timeout         = timeout,
-       .ndo_set_multicast_list = sgiseeq_set_multicast,
+       .ndo_set_rx_mode        = sgiseeq_set_multicast,
        .ndo_set_mac_address    = sgiseeq_set_mac_address,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 96%
rename from drivers/net/sfc/Kconfig
rename to drivers/net/ethernet/sfc/Kconfig
index a3d5bb9..5d18841 100644 (file)
@@ -5,7 +5,7 @@ config SFC
        select CRC32
        select I2C
        select I2C_ALGOBIT
-       help
+       ---help---
          This driver supports 10-gigabit Ethernet cards based on
          the Solarflare SFC4000 and SFC9000-family controllers.
 
@@ -15,7 +15,7 @@ config SFC_MTD
        bool "Solarflare SFC4000/SFC9000-family MTD support"
        depends on SFC && MTD && !(SFC=y && MTD=m)
        default y
-       help
+       ---help---
          This exposes the on-board flash memory as MTD devices (e.g.
          /dev/mtd1).  This makes it possible to upload new firmware
          to the NIC.
similarity index 99%
rename from drivers/net/sfc/efx.c
rename to drivers/net/ethernet/sfc/efx.c
index faca764..b6b0e71 100644 (file)
@@ -1903,7 +1903,7 @@ static const struct net_device_ops efx_netdev_ops = {
        .ndo_do_ioctl           = efx_ioctl,
        .ndo_change_mtu         = efx_change_mtu,
        .ndo_set_mac_address    = efx_set_mac_address,
-       .ndo_set_multicast_list = efx_set_multicast_list,
+       .ndo_set_rx_mode        = efx_set_multicast_list,
        .ndo_set_features       = efx_set_features,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = efx_netpoll,
diff --git a/drivers/net/ethernet/sgi/Kconfig b/drivers/net/ethernet/sgi/Kconfig
new file mode 100644 (file)
index 0000000..e832f46
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# SGI device configuration
+#
+
+config NET_VENDOR_SGI
+       bool "SGI devices"
+       default y
+       depends on (PCI && SGI_IP27) || SGI_IP32
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about SGI devices. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_SGI
+
+config SGI_IOC3_ETH
+       bool "SGI IOC3 Ethernet"
+       depends on PCI && SGI_IP27
+       select CRC32
+       select MII
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+config SGI_O2MACE_ETH
+       tristate "SGI O2 MACE Fast Ethernet support"
+       depends on SGI_IP32=y
+
+endif # NET_VENDOR_SGI
diff --git a/drivers/net/ethernet/sgi/Makefile b/drivers/net/ethernet/sgi/Makefile
new file mode 100644 (file)
index 0000000..e5bedd2
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the SGI device drivers.
+#
+
+obj-$(CONFIG_SGI_O2MACE_ETH) += meth.o
+obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
similarity index 99%
rename from drivers/net/ioc3-eth.c
rename to drivers/net/ethernet/sgi/ioc3-eth.c
index a234e45..ac149d9 100644 (file)
@@ -1220,7 +1220,7 @@ static const struct net_device_ops ioc3_netdev_ops = {
        .ndo_start_xmit         = ioc3_start_xmit,
        .ndo_tx_timeout         = ioc3_timeout,
        .ndo_get_stats          = ioc3_get_stats,
-       .ndo_set_multicast_list = ioc3_set_multicast_list,
+       .ndo_set_rx_mode        = ioc3_set_multicast_list,
        .ndo_do_ioctl           = ioc3_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ioc3_set_mac_address,
diff --git a/drivers/net/ethernet/sis/Kconfig b/drivers/net/ethernet/sis/Kconfig
new file mode 100644 (file)
index 0000000..68d052b
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Silicon Integrated Systems (SiS) device configuration
+#
+
+config NET_VENDOR_SIS
+       bool "Silicon Integrated Systems (SiS) devices"
+       default y
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about SiS devices. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_SIS
+
+config SIS900
+       tristate "SiS 900/7016 PCI Fast Ethernet Adapter support"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         This is a driver for the Fast Ethernet PCI network cards based on
+         the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in
+         SiS 630 and SiS 540 chipsets.
+
+         This driver also supports AMD 79C901 HomePNA so that you can use
+         your phone line as a network cable.
+
+         To compile this driver as a module, choose M here: the module
+         will be called sis900.  This is recommended.
+
+config SIS190
+       tristate "SiS190/SiS191 gigabit ethernet support"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or
+         a SiS 191 PCI Gigabit Ethernet adapter. Both are expected to
+         appear in lan on motherboard designs which are based on SiS 965
+         and SiS 966 south bridge.
+
+         To compile this driver as a module, choose M here: the module
+         will be called sis190.  This is recommended.
+
+endif # NET_VENDOR_SIS
diff --git a/drivers/net/ethernet/sis/Makefile b/drivers/net/ethernet/sis/Makefile
new file mode 100644 (file)
index 0000000..58d3ac1
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for Silicon Integrated Systems (SiS) network device drivers.
+#
+
+obj-$(CONFIG_SIS190) += sis190.o
+obj-$(CONFIG_SIS900) += sis900.o
similarity index 99%
rename from drivers/net/sis190.c
rename to drivers/net/ethernet/sis/sis190.c
index 8ad7bfb..1b4658c 100644 (file)
@@ -1825,15 +1825,25 @@ static int sis190_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                generic_mii_ioctl(&tp->mii_if, if_mii(ifr), cmd, NULL);
 }
 
+static int sis190_mac_addr(struct net_device  *dev, void *p)
+{
+       int rc;
+
+       rc = eth_mac_addr(dev, p);
+       if (!rc)
+               sis190_init_rxfilter(dev);
+       return rc;
+}
+
 static const struct net_device_ops sis190_netdev_ops = {
        .ndo_open               = sis190_open,
        .ndo_stop               = sis190_close,
        .ndo_do_ioctl           = sis190_ioctl,
        .ndo_start_xmit         = sis190_start_xmit,
        .ndo_tx_timeout         = sis190_tx_timeout,
-       .ndo_set_multicast_list = sis190_set_rx_mode,
+       .ndo_set_rx_mode        = sis190_set_rx_mode,
        .ndo_change_mtu         = eth_change_mtu,
-       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_set_mac_address    = sis190_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller     = sis190_netpoll,
similarity index 99%
rename from drivers/net/sis900.c
rename to drivers/net/ethernet/sis/sis900.c
index 658a192..a184abc 100644 (file)
@@ -403,7 +403,7 @@ static const struct net_device_ops sis900_netdev_ops = {
        .ndo_stop               = sis900_close,
        .ndo_start_xmit         = sis900_start_xmit,
        .ndo_set_config         = sis900_set_config,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
diff --git a/drivers/net/ethernet/smsc/Kconfig b/drivers/net/ethernet/smsc/Kconfig
new file mode 100644 (file)
index 0000000..f961928
--- /dev/null
@@ -0,0 +1,132 @@
+#
+# Western Digital/SMC network device configuration
+#
+
+config NET_VENDOR_SMSC
+       bool "SMC (SMSC)/Western Digital devices"
+       default y
+       depends on ARM || ISA || MAC || ARM || MIPS || M32R || SUPERH || \
+               BLACKFIN || MN10300 || COLDFIRE || PCI || PCMCIA
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about SMC/Western Digital cards. If you say Y, you will
+         be asked for your specific card in the following questions.
+
+if NET_VENDOR_SMSC
+
+config SMC9194
+       tristate "SMC 9194 support"
+       depends on (ISA || MAC && BROKEN)
+       select CRC32
+       ---help---
+         This is support for the SMC9xxx based Ethernet cards. Choose this
+         option if you have a DELL laptop with the docking station, or
+         another SMC9192/9194 based chipset.  Say Y if you want it compiled
+         into the kernel, and read the file
+         <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
+         available from <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called smc9194.
+
+config SMC91X
+       tristate "SMC 91C9x/91C1xxx support"
+       select CRC32
+       select MII
+       depends on (ARM || M32R || SUPERH || MIPS || BLACKFIN || \
+                   MN10300 || COLDFIRE)
+       ---help---
+         This is a driver for SMC's 91x series of Ethernet chipsets,
+         including the SMC91C94 and the SMC91C111. Say Y if you want it
+         compiled into the kernel, and read the file
+         <file:Documentation/networking/smc9.txt>  and the Ethernet-HOWTO,
+         available from  <http://www.tldp.org/docs.html#howto>.
+
+         This driver is also available as a module ( = code which can be
+         inserted in and removed from the running kernel whenever you want).
+         The module will be called smc91x.  If you want to compile it as a
+         module, say M here and read <file:Documentation/kbuild/modules.txt>.
+
+config PCMCIA_SMC91C92
+       tristate "SMC 91Cxx PCMCIA support"
+       depends on PCMCIA
+       select CRC32
+       select MII
+       ---help---
+         Say Y here if you intend to attach an SMC 91Cxx compatible PCMCIA
+         (PC-card) Ethernet or Fast Ethernet card to your computer.
+
+         To compile this driver as a module, choose M here: the module will be
+         called smc91c92_cs.  If unsure, say N.
+
+config EPIC100
+       tristate "SMC EtherPower II"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         This driver is for the SMC EtherPower II 9432 PCI Ethernet NIC,
+         which is based on the SMC83c17x (EPIC/100).
+         More specific information and updates are available from
+         <http://www.scyld.com/network/epic100.html>.
+
+config SMC911X
+       tristate "SMSC LAN911[5678] support"
+       select CRC32
+       select MII
+       depends on (ARM || SUPERH || MN10300)
+       ---help---
+         This is a driver for SMSC's LAN911x series of Ethernet chipsets
+         including the new LAN9115, LAN9116, LAN9117, and LAN9118.
+         Say Y if you want it compiled into the kernel,
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         This driver is also available as a module. The module will be
+         called smc911x.  If you want to compile it as a module, say M
+         here and read <file:Documentation/kbuild/modules.txt>
+
+config SMSC911X
+       tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
+       depends on (ARM || SUPERH || BLACKFIN || MIPS || MN10300)
+       select CRC32
+       select MII
+       select PHYLIB
+       ---help---
+         Say Y here if you want support for SMSC LAN911x and LAN921x families
+         of ethernet controllers.
+
+         To compile this driver as a module, choose M here and read
+         <file:Documentation/networking/net-modules.txt>. The module
+         will be called smsc911x.
+
+config SMSC911X_ARCH_HOOKS
+       def_bool n
+       depends on SMSC911X
+       ---help---
+         If the arch enables this, it allows the arch to implement various
+         hooks for more comprehensive interrupt control and also to override
+         the source of the MAC address.
+
+config SMSC9420
+       tristate "SMSC LAN9420 PCI ethernet adapter support"
+       depends on PCI
+       select CRC32
+       select PHYLIB
+       select SMSC_PHY
+       ---help---
+         This is a driver for SMSC's LAN9420 PCI ethernet adapter.
+         Say Y if you want it compiled into the kernel,
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         This driver is also available as a module. The module will be
+         called smsc9420.  If you want to compile it as a module, say M
+         here and read <file:Documentation/kbuild/modules.txt>
+
+endif # NET_VENDOR_SMSC
diff --git a/drivers/net/ethernet/smsc/Makefile b/drivers/net/ethernet/smsc/Makefile
new file mode 100644 (file)
index 0000000..f3438de
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for the SMSC network device drivers.
+#
+
+obj-$(CONFIG_SMC9194) += smc9194.o
+obj-$(CONFIG_SMC91X) += smc91x.o
+obj-$(CONFIG_PCMCIA_SMC91C92) += smc91c92_cs.o
+obj-$(CONFIG_EPIC100) += epic100.o
+obj-$(CONFIG_SMSC9420) += smsc9420.o
+obj-$(CONFIG_SMC911X) += smc911x.o
+obj-$(CONFIG_SMSC911X) += smsc911x.o
similarity index 99%
rename from drivers/net/epic100.c
rename to drivers/net/ethernet/smsc/epic100.c
index 814c187..0a5dfb8 100644 (file)
@@ -314,7 +314,7 @@ static const struct net_device_ops epic_netdev_ops = {
        .ndo_start_xmit         = epic_start_xmit,
        .ndo_tx_timeout         = epic_tx_timeout,
        .ndo_get_stats          = epic_get_stats,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_do_ioctl           = netdev_ioctl,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/smc911x.c
rename to drivers/net/ethernet/smsc/smc911x.c
index a91fe17..8f61fe9 100644 (file)
@@ -1768,7 +1768,7 @@ static const struct net_device_ops smc911x_netdev_ops = {
        .ndo_stop               = smc911x_close,
        .ndo_start_xmit         = smc911x_hard_start_xmit,
        .ndo_tx_timeout         = smc911x_timeout,
-       .ndo_set_multicast_list = smc911x_set_multicast_list,
+       .ndo_set_rx_mode        = smc911x_set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/smc9194.c
rename to drivers/net/ethernet/smsc/smc9194.c
index 5b65ac4..4e45094 100644 (file)
@@ -827,7 +827,7 @@ static const struct net_device_ops smc_netdev_ops = {
        .ndo_stop               = smc_close,
        .ndo_start_xmit         = smc_wait_to_send_packet,
        .ndo_tx_timeout         = smc_timeout,
-       .ndo_set_multicast_list = smc_set_multicast_list,
+       .ndo_set_rx_mode        = smc_set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/pcmcia/smc91c92_cs.c
rename to drivers/net/ethernet/smsc/smc91c92_cs.c
index 1cd9394..cbfa981 100644 (file)
@@ -294,7 +294,7 @@ static const struct net_device_ops smc_netdev_ops = {
        .ndo_start_xmit         = smc_start_xmit,
        .ndo_tx_timeout         = smc_tx_timeout,
        .ndo_set_config         = s9k_config,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_rx_mode        = set_rx_mode,
        .ndo_do_ioctl           = smc_ioctl,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
@@ -809,7 +809,7 @@ static int smc91c92_config(struct pcmcia_device *link)
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
     char *name;
-    int i, j, rev;
+    int i, rev, j = 0;
     unsigned int ioaddr;
     u_long mir;
 
similarity index 99%
rename from drivers/net/smc91x.c
rename to drivers/net/ethernet/smsc/smc91x.c
index 2b1d254..f47f81e 100644 (file)
@@ -1768,7 +1768,7 @@ static const struct net_device_ops smc_netdev_ops = {
        .ndo_stop               = smc_close,
        .ndo_start_xmit         = smc_hard_start_xmit,
        .ndo_tx_timeout         = smc_timeout,
-       .ndo_set_multicast_list = smc_set_multicast_list,
+       .ndo_set_rx_mode        = smc_set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 97%
rename from drivers/net/smsc911x.c
rename to drivers/net/ethernet/smsc/smsc911x.c
index b9016a3..788c4fd 100644 (file)
 #include <linux/phy.h>
 #include <linux/smsc911x.h>
 #include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_net.h>
 #include "smsc911x.h"
 
 #define SMSC_CHIPNAME          "smsc911x"
@@ -1902,7 +1906,7 @@ static const struct net_device_ops smsc911x_netdev_ops = {
        .ndo_stop               = smsc911x_stop,
        .ndo_start_xmit         = smsc911x_hard_start_xmit,
        .ndo_get_stats          = smsc911x_get_stats,
-       .ndo_set_multicast_list = smsc911x_set_multicast_list,
+       .ndo_set_rx_mode        = smsc911x_set_multicast_list,
        .ndo_do_ioctl           = smsc911x_do_ioctl,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
@@ -2095,8 +2099,58 @@ static const struct smsc911x_ops shifted_smsc911x_ops = {
        .tx_writefifo = smsc911x_tx_writefifo_shift,
 };
 
+#ifdef CONFIG_OF
+static int __devinit smsc911x_probe_config_dt(
+                               struct smsc911x_platform_config *config,
+                               struct device_node *np)
+{
+       const char *mac;
+       u32 width = 0;
+
+       if (!np)
+               return -ENODEV;
+
+       config->phy_interface = of_get_phy_mode(np);
+
+       mac = of_get_mac_address(np);
+       if (mac)
+               memcpy(config->mac, mac, ETH_ALEN);
+
+       of_property_read_u32(np, "reg-shift", &config->shift);
+
+       of_property_read_u32(np, "reg-io-width", &width);
+       if (width == 4)
+               config->flags |= SMSC911X_USE_32BIT;
+
+       if (of_get_property(np, "smsc,irq-active-high", NULL))
+               config->irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH;
+
+       if (of_get_property(np, "smsc,irq-push-pull", NULL))
+               config->irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL;
+
+       if (of_get_property(np, "smsc,force-internal-phy", NULL))
+               config->flags |= SMSC911X_FORCE_INTERNAL_PHY;
+
+       if (of_get_property(np, "smsc,force-external-phy", NULL))
+               config->flags |= SMSC911X_FORCE_EXTERNAL_PHY;
+
+       if (of_get_property(np, "smsc,save-mac-address", NULL))
+               config->flags |= SMSC911X_SAVE_MAC_ADDRESS;
+
+       return 0;
+}
+#else
+static inline int smsc911x_probe_config_dt(
+                               struct smsc911x_platform_config *config,
+                               struct device_node *np)
+{
+       return -ENODEV;
+}
+#endif /* CONFIG_OF */
+
 static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
 {
+       struct device_node *np = pdev->dev.of_node;
        struct net_device *dev;
        struct smsc911x_data *pdata;
        struct smsc911x_platform_config *config = pdev->dev.platform_data;
@@ -2107,13 +2161,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
 
        pr_info("Driver version %s\n", SMSC_DRV_VERSION);
 
-       /* platform data specifies irq & dynamic bus configuration */
-       if (!pdev->dev.platform_data) {
-               pr_warn("platform_data not provided\n");
-               retval = -ENODEV;
-               goto out_0;
-       }
-
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                                           "smsc911x-memory");
        if (!res)
@@ -2152,9 +2199,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
        irq_flags = irq_res->flags & IRQF_TRIGGER_MASK;
        pdata->ioaddr = ioremap_nocache(res->start, res_size);
 
-       /* copy config parameters across to pdata */
-       memcpy(&pdata->config, config, sizeof(pdata->config));
-
        pdata->dev = dev;
        pdata->msg_enable = ((1 << debug) - 1);
 
@@ -2164,10 +2208,22 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
                goto out_free_netdev_2;
        }
 
+       retval = smsc911x_probe_config_dt(&pdata->config, np);
+       if (retval && config) {
+               /* copy config parameters across to pdata */
+               memcpy(&pdata->config, config, sizeof(pdata->config));
+               retval = 0;
+       }
+
+       if (retval) {
+               SMSC_WARN(pdata, probe, "Error smsc911x config not found");
+               goto out_unmap_io_3;
+       }
+
        /* assume standard, non-shifted, access to HW registers */
        pdata->ops = &standard_smsc911x_ops;
        /* apply the right access if shifting is needed */
-       if (config->shift)
+       if (pdata->config.shift)
                pdata->ops = &shifted_smsc911x_ops;
 
        retval = smsc911x_init(dev);
@@ -2314,6 +2370,12 @@ static const struct dev_pm_ops smsc911x_pm_ops = {
 #define SMSC911X_PM_OPS NULL
 #endif
 
+static const struct of_device_id smsc911x_dt_ids[] = {
+       { .compatible = "smsc,lan9115", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, smsc911x_dt_ids);
+
 static struct platform_driver smsc911x_driver = {
        .probe = smsc911x_drv_probe,
        .remove = __devexit_p(smsc911x_drv_remove),
@@ -2321,6 +2383,7 @@ static struct platform_driver smsc911x_driver = {
                .name   = SMSC_CHIPNAME,
                .owner  = THIS_MODULE,
                .pm     = SMSC911X_PM_OPS,
+               .of_match_table = smsc911x_dt_ids,
        },
 };
 
similarity index 99%
rename from drivers/net/smsc9420.c
rename to drivers/net/ethernet/smsc/smsc9420.c
index 459726f..4f15680 100644 (file)
@@ -1566,7 +1566,7 @@ static const struct net_device_ops smsc9420_netdev_ops = {
        .ndo_stop               = smsc9420_stop,
        .ndo_start_xmit         = smsc9420_hard_start_xmit,
        .ndo_get_stats          = smsc9420_get_stats,
-       .ndo_set_multicast_list = smsc9420_set_multicast_list,
+       .ndo_set_rx_mode        = smsc9420_set_multicast_list,
        .ndo_do_ioctl           = smsc9420_do_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
diff --git a/drivers/net/ethernet/stmicro/Kconfig b/drivers/net/ethernet/stmicro/Kconfig
new file mode 100644 (file)
index 0000000..f4a80da
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# STMicroelectronics device configuration
+#
+
+config NET_VENDOR_STMICRO
+       bool "STMicroelectronics devices"
+       default y
+       depends on HAS_IOMEM
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about STMicroelectronics cards. If you say Y, you will
+         be asked for your specific card in the following questions.
+
+if NET_VENDOR_STMICRO
+
+source "drivers/net/ethernet/stmicro/stmmac/Kconfig"
+
+endif # NET_VENDOR_STMICRO
diff --git a/drivers/net/ethernet/stmicro/Makefile b/drivers/net/ethernet/stmicro/Makefile
new file mode 100644 (file)
index 0000000..9b3bfdd
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the STMicroelectronics device drivers.
+#
+
+obj-$(CONFIG_STMMAC_ETH) += stmmac/
similarity index 93%
rename from drivers/net/stmmac/Kconfig
rename to drivers/net/ethernet/stmicro/stmmac/Kconfig
index 7df7df4..cda61e3 100644 (file)
@@ -1,10 +1,10 @@
 config STMMAC_ETH
        tristate "STMicroelectronics 10/100/1000 Ethernet driver"
+       depends on HAS_IOMEM
        select MII
        select PHYLIB
        select CRC32
-       depends on NETDEVICES && HAS_IOMEM
-       help
+       ---help---
          This is the driver for the Ethernet IPs are built around a
          Synopsys IP Core and only tested on the STMicroelectronics
          platforms.
@@ -14,7 +14,7 @@ if STMMAC_ETH
 config STMMAC_DA
        bool "STMMAC DMA arbitration scheme"
        default n
-       help
+       ---help---
          Selecting this option, rx has priority over Tx (only for Giga
          Ethernet device).
          By default, the DMA arbitration scheme is based on Round-robin
@@ -24,7 +24,7 @@ config STMMAC_DUAL_MAC
        bool "STMMAC: dual mac support (EXPERIMENTAL)"
        default n
         depends on EXPERIMENTAL && STMMAC_ETH && !STMMAC_TIMER
-       help
+       ---help---
          Some ST SoCs (for example the stx7141 and stx7200c2) have two
          Ethernet Controllers. This option turns on the second Ethernet
          device on this kind of platforms.
@@ -33,7 +33,7 @@ config STMMAC_TIMER
        bool "STMMAC Timer optimisation"
        default n
        depends on RTC_HCTOSYS_DEVICE
-       help
+       ---help---
          Use an external timer for mitigating the number of network
          interrupts. Currently, for SH architectures, it is possible
          to use the TMU channel 2 and the SH-RTC device.
@@ -45,12 +45,12 @@ choice
 config STMMAC_TMU_TIMER
         bool "TMU channel 2"
         depends on CPU_SH4
-       help
+       ---help---
 
 config STMMAC_RTC_TIMER
         bool "Real time clock"
         depends on RTC_CLASS
-       help
+       ---help---
 
 endchoice
 
similarity index 99%
rename from drivers/net/stmmac/stmmac_main.c
rename to drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c6e567e..68fb5b0 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/crc32.h>
 #include <linux/mii.h>
 #include <linux/phy.h>
+#include <linux/if.h>
 #include <linux/if_vlan.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
@@ -1284,7 +1285,7 @@ static int stmmac_config(struct net_device *dev, struct ifmap *map)
 }
 
 /**
- *  stmmac_multicast_list - entry point for multicast addressing
+ *  stmmac_set_rx_mode - entry point for multicast addressing
  *  @dev : pointer to the device structure
  *  Description:
  *  This function is a driver entry point which gets called by the kernel
@@ -1292,7 +1293,7 @@ static int stmmac_config(struct net_device *dev, struct ifmap *map)
  *  Return value:
  *  void.
  */
-static void stmmac_multicast_list(struct net_device *dev)
+static void stmmac_set_rx_mode(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
 
@@ -1421,7 +1422,7 @@ static const struct net_device_ops stmmac_netdev_ops = {
        .ndo_stop = stmmac_release,
        .ndo_change_mtu = stmmac_change_mtu,
        .ndo_fix_features = stmmac_fix_features,
-       .ndo_set_multicast_list = stmmac_multicast_list,
+       .ndo_set_rx_mode = stmmac_set_rx_mode,
        .ndo_tx_timeout = stmmac_tx_timeout,
        .ndo_do_ioctl = stmmac_ioctl,
        .ndo_set_config = stmmac_config,
@@ -1498,10 +1499,12 @@ static int stmmac_mac_device_setup(struct net_device *dev)
 
        struct mac_device_info *device;
 
-       if (priv->plat->has_gmac)
+       if (priv->plat->has_gmac) {
+               dev->priv_flags |= IFF_UNICAST_FLT;
                device = dwmac1000_setup(priv->ioaddr);
-       else
+       } else {
                device = dwmac100_setup(priv->ioaddr);
+       }
 
        if (!device)
                return -ENOMEM;
diff --git a/drivers/net/ethernet/sun/Kconfig b/drivers/net/ethernet/sun/Kconfig
new file mode 100644 (file)
index 0000000..57bfd85
--- /dev/null
@@ -0,0 +1,88 @@
+#
+# Sun network device configuration
+#
+
+config NET_VENDOR_SUN
+       bool "Sun devices"
+       default y
+       depends on SUN3 || SBUS || PCI || SUN_LDOMS
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say
+         Y and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Sun network interfaces. If you say Y, you will be
+         asked for your specific card in the following questions.
+
+if NET_VENDOR_SUN
+
+config HAPPYMEAL
+       tristate "Sun Happy Meal 10/100baseT support"
+       depends on (SBUS || PCI)
+       select CRC32
+       ---help---
+         This driver supports the "hme" interface present on most Ultra
+         systems and as an option on older Sbus systems. This driver supports
+         both PCI and Sbus devices. This driver also supports the "qfe" quad
+         100baseT device available in both PCI and Sbus configurations.
+
+         To compile this driver as a module, choose M here: the module
+         will be called sunhme.
+
+config SUNBMAC
+       tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)"
+       depends on SBUS && EXPERIMENTAL
+       select CRC32
+       ---help---
+         This driver supports the "be" interface available as an Sbus option.
+         This is Sun's older 100baseT Ethernet device.
+
+         To compile this driver as a module, choose M here: the module
+         will be called sunbmac.
+
+config SUNQE
+       tristate "Sun QuadEthernet support"
+       depends on SBUS
+       select CRC32
+       ---help---
+         This driver supports the "qe" 10baseT Ethernet device, available as
+         an Sbus option. Note that this is not the same as Quad FastEthernet
+         "qfe" which is supported by the Happy Meal driver instead.
+
+         To compile this driver as a module, choose M here: the module
+         will be called sunqe.
+
+config SUNGEM
+       tristate "Sun GEM support"
+       depends on PCI
+       select CRC32
+       select SUNGEM_PHY
+       ---help---
+         Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0.  See also
+         <http://www.sun.com/products-n-solutions/hardware/docs/pdf/806-3985-10.pdf>.
+
+config CASSINI
+       tristate "Sun Cassini support"
+       depends on PCI
+       select CRC32
+       ---help---
+         Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
+         <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
+
+config SUNVNET
+       tristate "Sun Virtual Network support"
+       depends on SUN_LDOMS
+       ---help---
+         Support for virtual network devices under Sun Logical Domains.
+
+config NIU
+       tristate "Sun Neptune 10Gbit Ethernet support"
+       depends on PCI
+       select CRC32
+       ---help---
+         This enables support for cards based upon Sun's
+         Neptune chipset.
+
+endif # NET_VENDOR_SUN
diff --git a/drivers/net/ethernet/sun/Makefile b/drivers/net/ethernet/sun/Makefile
new file mode 100644 (file)
index 0000000..1e620ff
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for the Sun network device drivers.
+#
+
+obj-$(CONFIG_HAPPYMEAL) += sunhme.o
+obj-$(CONFIG_SUNQE) += sunqe.o
+obj-$(CONFIG_SUNBMAC) += sunbmac.o
+obj-$(CONFIG_SUNGEM) += sungem.o
+obj-$(CONFIG_CASSINI) += cassini.o
+obj-$(CONFIG_SUNVNET) += sunvnet.o
+obj-$(CONFIG_NIU) += niu.o
similarity index 99%
rename from drivers/net/cassini.c
rename to drivers/net/ethernet/sun/cassini.c
index 646c86b..1776a37 100644 (file)
@@ -4910,7 +4910,7 @@ static const struct net_device_ops cas_netdev_ops = {
        .ndo_stop               = cas_close,
        .ndo_start_xmit         = cas_start_xmit,
        .ndo_get_stats          = cas_get_stats,
-       .ndo_set_multicast_list = cas_set_multicast,
+       .ndo_set_rx_mode        = cas_set_multicast,
        .ndo_do_ioctl           = cas_ioctl,
        .ndo_tx_timeout         = cas_tx_timeout,
        .ndo_change_mtu         = cas_change_mtu,
similarity index 99%
rename from drivers/net/niu.c
rename to drivers/net/ethernet/sun/niu.c
index cd6c231..3c9ef1c 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/bitops.h>
 #include <linux/mii.h>
+#include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/if_vlan.h>
 #include <linux/ip.h>
@@ -9201,7 +9202,7 @@ static int __devinit niu_ldg_init(struct niu *np)
 
        first_chan = 0;
        for (i = 0; i < port; i++)
-               first_chan += parent->rxchan_per_port[port];
+               first_chan += parent->rxchan_per_port[i];
        num_chan = parent->rxchan_per_port[port];
 
        for (i = first_chan; i < (first_chan + num_chan); i++) {
@@ -9217,7 +9218,7 @@ static int __devinit niu_ldg_init(struct niu *np)
 
        first_chan = 0;
        for (i = 0; i < port; i++)
-               first_chan += parent->txchan_per_port[port];
+               first_chan += parent->txchan_per_port[i];
        num_chan = parent->txchan_per_port[port];
        for (i = first_chan; i < (first_chan + num_chan); i++) {
                err = niu_ldg_assign_ldn(np, parent,
@@ -9716,7 +9717,7 @@ static const struct net_device_ops niu_netdev_ops = {
        .ndo_stop               = niu_close,
        .ndo_start_xmit         = niu_start_xmit,
        .ndo_get_stats64        = niu_get_stats,
-       .ndo_set_multicast_list = niu_set_rx_mode,
+       .ndo_set_rx_mode        = niu_set_rx_mode,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = niu_set_mac_addr,
        .ndo_do_ioctl           = niu_ioctl,
@@ -9852,6 +9853,8 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
 
        niu_set_basic_features(dev);
 
+       dev->priv_flags |= IFF_UNICAST_FLT;
+
        np->regs = pci_ioremap_bar(pdev, 0);
        if (!np->regs) {
                dev_err(&pdev->dev, "Cannot map device registers, aborting\n");
similarity index 97%
rename from drivers/net/sunbmac.c
rename to drivers/net/ethernet/sun/sunbmac.c
index 297a424..0d8cfd9 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/crc32.h>
 #include <linux/errno.h>
 #include <linux/ethtool.h>
+#include <linux/mii.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -500,13 +501,13 @@ static int try_next_permutation(struct bigmac *bp, void __iomem *tregs)
 
                /* Reset the PHY. */
                bp->sw_bmcr     = (BMCR_ISOLATE | BMCR_PDOWN | BMCR_LOOPBACK);
-               bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
+               bigmac_tcvr_write(bp, tregs, MII_BMCR, bp->sw_bmcr);
                bp->sw_bmcr     = (BMCR_RESET);
-               bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
+               bigmac_tcvr_write(bp, tregs, MII_BMCR, bp->sw_bmcr);
 
                timeout = 64;
                while (--timeout) {
-                       bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
+                       bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, MII_BMCR);
                        if ((bp->sw_bmcr & BMCR_RESET) == 0)
                                break;
                        udelay(20);
@@ -514,11 +515,11 @@ static int try_next_permutation(struct bigmac *bp, void __iomem *tregs)
                if (timeout == 0)
                        printk(KERN_ERR "%s: PHY reset failed.\n", bp->dev->name);
 
-               bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
+               bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, MII_BMCR);
 
                /* Now we try 10baseT. */
                bp->sw_bmcr &= ~(BMCR_SPEED100);
-               bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
+               bigmac_tcvr_write(bp, tregs, MII_BMCR, bp->sw_bmcr);
                return 0;
        }
 
@@ -534,8 +535,8 @@ static void bigmac_timer(unsigned long data)
 
        bp->timer_ticks++;
        if (bp->timer_state == ltrywait) {
-               bp->sw_bmsr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMSR);
-               bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
+               bp->sw_bmsr = bigmac_tcvr_read(bp, tregs, MII_BMSR);
+               bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, MII_BMCR);
                if (bp->sw_bmsr & BMSR_LSTATUS) {
                        printk(KERN_INFO "%s: Link is now up at %s.\n",
                               bp->dev->name,
@@ -588,18 +589,18 @@ static void bigmac_begin_auto_negotiation(struct bigmac *bp)
        int timeout;
 
        /* Grab new software copies of PHY registers. */
-       bp->sw_bmsr     = bigmac_tcvr_read(bp, tregs, BIGMAC_BMSR);
-       bp->sw_bmcr     = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
+       bp->sw_bmsr     = bigmac_tcvr_read(bp, tregs, MII_BMSR);
+       bp->sw_bmcr     = bigmac_tcvr_read(bp, tregs, MII_BMCR);
 
        /* Reset the PHY. */
        bp->sw_bmcr     = (BMCR_ISOLATE | BMCR_PDOWN | BMCR_LOOPBACK);
-       bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
+       bigmac_tcvr_write(bp, tregs, MII_BMCR, bp->sw_bmcr);
        bp->sw_bmcr     = (BMCR_RESET);
-       bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
+       bigmac_tcvr_write(bp, tregs, MII_BMCR, bp->sw_bmcr);
 
        timeout = 64;
        while (--timeout) {
-               bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
+               bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, MII_BMCR);
                if ((bp->sw_bmcr & BMCR_RESET) == 0)
                        break;
                udelay(20);
@@ -607,11 +608,11 @@ static void bigmac_begin_auto_negotiation(struct bigmac *bp)
        if (timeout == 0)
                printk(KERN_ERR "%s: PHY reset failed.\n", bp->dev->name);
 
-       bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
+       bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, MII_BMCR);
 
        /* First we try 100baseT. */
        bp->sw_bmcr |= BMCR_SPEED100;
-       bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
+       bigmac_tcvr_write(bp, tregs, MII_BMCR, bp->sw_bmcr);
 
        bp->timer_state = ltrywait;
        bp->timer_ticks = 0;
@@ -1054,7 +1055,7 @@ static u32 bigmac_get_link(struct net_device *dev)
        struct bigmac *bp = netdev_priv(dev);
 
        spin_lock_irq(&bp->lock);
-       bp->sw_bmsr = bigmac_tcvr_read(bp, bp->tregs, BIGMAC_BMSR);
+       bp->sw_bmsr = bigmac_tcvr_read(bp, bp->tregs, MII_BMSR);
        spin_unlock_irq(&bp->lock);
 
        return (bp->sw_bmsr & BMSR_LSTATUS);
@@ -1070,7 +1071,7 @@ static const struct net_device_ops bigmac_ops = {
        .ndo_stop               = bigmac_close,
        .ndo_start_xmit         = bigmac_start_xmit,
        .ndo_get_stats          = bigmac_get_stats,
-       .ndo_set_multicast_list = bigmac_set_multicast,
+       .ndo_set_rx_mode        = bigmac_set_multicast,
        .ndo_tx_timeout         = bigmac_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 95%
rename from drivers/net/sunbmac.h
rename to drivers/net/ethernet/sun/sunbmac.h
index 4943e97..06dd217 100644 (file)
 #define BIGMAC_PHY_EXTERNAL   0 /* External transceiver */
 #define BIGMAC_PHY_INTERNAL   1 /* Internal transceiver */
 
-/* PHY registers */
-#define BIGMAC_BMCR           0x00 /* Basic mode control register      */
-#define BIGMAC_BMSR           0x01 /* Basic mode status register       */
-
-/* BMCR bits */
-#define BMCR_ISOLATE            0x0400  /* Disconnect DP83840 from MII */
-#define BMCR_PDOWN              0x0800  /* Powerdown the DP83840       */
-#define BMCR_ANENABLE           0x1000  /* Enable auto negotiation     */
-#define BMCR_SPEED100           0x2000  /* Select 100Mbps              */
-#define BMCR_LOOPBACK           0x4000  /* TXD loopback bits           */
-#define BMCR_RESET              0x8000  /* Reset the DP83840           */
-
-/* BMSR bits */
-#define BMSR_ERCAP              0x0001  /* Ext-reg capability          */
-#define BMSR_JCD                0x0002  /* Jabber detected             */
-#define BMSR_LSTATUS            0x0004  /* Link status                 */
-
 /* Ring descriptors and such, same as Quad Ethernet. */
 struct be_rxd {
        u32 rx_flags;
similarity index 99%
rename from drivers/net/sungem.c
rename to drivers/net/ethernet/sun/sungem.c
index be745ae..11fd299 100644 (file)
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
-#include <asm/prom.h>
 
 #ifdef CONFIG_SPARC
 #include <asm/idprom.h>
+#include <asm/prom.h>
 #endif
 
 #ifdef CONFIG_PPC_PMAC
 #include <asm/pci-bridge.h>
+#include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #endif
 
-#include "sungem_phy.h"
+#include <linux/sungem_phy.h>
 #include "sungem.h"
 
 /* Stripping FCS is causing problems, disabled for now */
@@ -1720,7 +1721,7 @@ static void gem_init_phy(struct gem *gp)
        if (gp->phy_type == phy_mii_mdio0 ||
            gp->phy_type == phy_mii_mdio1) {
                /* Reset and detect MII PHY */
-               mii_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
+               sungem_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
 
                /* Init PHY */
                if (gp->phy_mii.def && gp->phy_mii.def->ops->init)
@@ -2819,7 +2820,7 @@ static const struct net_device_ops gem_netdev_ops = {
        .ndo_stop               = gem_close,
        .ndo_start_xmit         = gem_start_xmit,
        .ndo_get_stats          = gem_get_stats,
-       .ndo_set_multicast_list = gem_set_multicast,
+       .ndo_set_rx_mode        = gem_set_multicast,
        .ndo_do_ioctl           = gem_ioctl,
        .ndo_tx_timeout         = gem_tx_timeout,
        .ndo_change_mtu         = gem_change_mtu,
similarity index 99%
rename from drivers/net/sunhme.c
rename to drivers/net/ethernet/sun/sunhme.c
index 856e05b..42f866e 100644 (file)
@@ -2619,7 +2619,7 @@ static const struct net_device_ops hme_netdev_ops = {
        .ndo_start_xmit         = happy_meal_start_xmit,
        .ndo_tx_timeout         = happy_meal_tx_timeout,
        .ndo_get_stats          = happy_meal_get_stats,
-       .ndo_set_multicast_list = happy_meal_set_multicast,
+       .ndo_set_rx_mode        = happy_meal_set_multicast,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
similarity index 99%
rename from drivers/net/sunqe.c
rename to drivers/net/ethernet/sun/sunqe.c
index 209c7f8..b28f743 100644 (file)
@@ -824,7 +824,7 @@ static const struct net_device_ops qec_ops = {
        .ndo_open               = qe_open,
        .ndo_stop               = qe_close,
        .ndo_start_xmit         = qe_start_xmit,
-       .ndo_set_multicast_list = qe_set_multicast,
+       .ndo_set_rx_mode        = qe_set_multicast,
        .ndo_tx_timeout         = qe_tx_timeout,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
similarity index 99%
rename from drivers/net/sunvnet.c
rename to drivers/net/ethernet/sun/sunvnet.c
index bf3c762..8c6c059 100644 (file)
@@ -1012,7 +1012,7 @@ static DEFINE_MUTEX(vnet_list_mutex);
 static const struct net_device_ops vnet_ops = {
        .ndo_open               = vnet_open,
        .ndo_stop               = vnet_close,
-       .ndo_set_multicast_list = vnet_set_rx_mode,
+       .ndo_set_rx_mode        = vnet_set_rx_mode,
        .ndo_set_mac_address    = vnet_set_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = vnet_tx_timeout,
diff --git a/drivers/net/ethernet/tehuti/Kconfig b/drivers/net/ethernet/tehuti/Kconfig
new file mode 100644 (file)
index 0000000..1fc027e
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# Tehuti network device configuration
+#
+
+config NET_VENDOR_TEHUTI
+       bool "Tehuti devices"
+       default y
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Tehuti cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_TEHUTI
+
+config TEHUTI
+       tristate "Tehuti Networks 10G Ethernet"
+       depends on PCI
+       ---help---
+         Tehuti Networks 10G Ethernet NIC
+
+endif # NET_VENDOR_TEHUTI
diff --git a/drivers/net/ethernet/tehuti/Makefile b/drivers/net/ethernet/tehuti/Makefile
new file mode 100644 (file)
index 0000000..f995421
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Tehuti network device drivers.
+#
+
+obj-$(CONFIG_TEHUTI) += tehuti.o
similarity index 99%
rename from drivers/net/tehuti.c
rename to drivers/net/ethernet/tehuti/tehuti.c
index 749bbf1..bc65aa8 100644 (file)
@@ -1860,7 +1860,7 @@ static const struct net_device_ops bdx_netdev_ops = {
        .ndo_start_xmit         = bdx_tx_transmit,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = bdx_ioctl,
-       .ndo_set_multicast_list = bdx_setmulti,
+       .ndo_set_rx_mode        = bdx_setmulti,
        .ndo_change_mtu         = bdx_change_mtu,
        .ndo_set_mac_address    = bdx_set_mac,
        .ndo_vlan_rx_add_vid    = bdx_vlan_rx_add_vid,
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
new file mode 100644 (file)
index 0000000..de76c70
--- /dev/null
@@ -0,0 +1,77 @@
+#
+# TI device configuration
+#
+
+config NET_VENDOR_TI
+       bool "Texas Instruments (TI) devices"
+       default y
+       depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3))
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about TI devices. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_TI
+
+config TI_DAVINCI_EMAC
+       tristate "TI DaVinci EMAC Support"
+       depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+       select TI_DAVINCI_MDIO
+       select TI_DAVINCI_CPDMA
+       select PHYLIB
+       ---help---
+         This driver supports TI's DaVinci Ethernet .
+
+         To compile this driver as a module, choose M here: the module
+         will be called davinci_emac_driver.  This is recommended.
+
+config TI_DAVINCI_MDIO
+       tristate "TI DaVinci MDIO Support"
+       depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+       select PHYLIB
+       ---help---
+         This driver supports TI's DaVinci MDIO module.
+
+         To compile this driver as a module, choose M here: the module
+         will be called davinci_mdio.  This is recommended.
+
+config TI_DAVINCI_CPDMA
+       tristate "TI DaVinci CPDMA Support"
+       depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+       ---help---
+         This driver supports TI's DaVinci CPDMA dma engine.
+
+         To compile this driver as a module, choose M here: the module
+         will be called davinci_cpdma.  This is recommended.
+
+config TLAN
+       tristate "TI ThunderLAN support"
+       depends on (PCI || EISA)
+       ---help---
+         If you have a PCI Ethernet network card based on the ThunderLAN chip
+         which is supported by this driver, say Y and read the
+         Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Devices currently supported by this driver are Compaq Netelligent,
+         Compaq NetFlex and Olicom cards.  Please read the file
+         <file:Documentation/networking/tlan.txt> for more details.
+
+         To compile this driver as a module, choose M here. The module
+         will be called tlan.
+
+         Please email feedback to <torben.mathiasen@compaq.com>.
+
+config CPMAC
+       tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && AR7
+       select PHYLIB
+       ---help---
+         TI AR7 CPMAC Ethernet support
+
+endif # NET_VENDOR_TI
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile
new file mode 100644 (file)
index 0000000..aedb3af
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for the TI network device drivers.
+#
+
+obj-$(CONFIG_TLAN) += tlan.o
+obj-$(CONFIG_CPMAC) += cpmac.o
+obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
+obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
+obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
similarity index 99%
rename from drivers/net/cpmac.c
rename to drivers/net/ethernet/ti/cpmac.c
index e0638cb..aaac0c7 100644 (file)
@@ -1100,7 +1100,7 @@ static const struct net_device_ops cpmac_netdev_ops = {
        .ndo_stop               = cpmac_stop,
        .ndo_start_xmit         = cpmac_start_xmit,
        .ndo_tx_timeout         = cpmac_tx_timeout,
-       .ndo_set_multicast_list = cpmac_set_multicast_list,
+       .ndo_set_rx_mode        = cpmac_set_multicast_list,
        .ndo_do_ioctl           = cpmac_ioctl,
        .ndo_set_config         = cpmac_config,
        .ndo_change_mtu         = eth_change_mtu,
similarity index 99%
rename from drivers/net/davinci_emac.c
rename to drivers/net/ethernet/ti/davinci_emac.c
index 3f451e4..815c797 100644 (file)
@@ -1741,7 +1741,7 @@ static const struct net_device_ops emac_netdev_ops = {
        .ndo_open               = emac_dev_open,
        .ndo_stop               = emac_dev_stop,
        .ndo_start_xmit         = emac_dev_xmit,
-       .ndo_set_multicast_list = emac_dev_mcast_set,
+       .ndo_set_rx_mode        = emac_dev_mcast_set,
        .ndo_set_mac_address    = emac_dev_setmac_addr,
        .ndo_do_ioctl           = emac_devioctl,
        .ndo_tx_timeout         = emac_dev_tx_timeout,
similarity index 99%
rename from drivers/net/tlan.c
rename to drivers/net/ethernet/ti/tlan.c
index 145871b..9c0dd6b 100644 (file)
@@ -774,7 +774,7 @@ static const struct net_device_ops tlan_netdev_ops = {
        .ndo_start_xmit         = tlan_start_tx,
        .ndo_tx_timeout         = tlan_tx_timeout,
        .ndo_get_stats          = tlan_get_stats,
-       .ndo_set_multicast_list = tlan_set_multicast_list,
+       .ndo_set_rx_mode        = tlan_set_multicast_list,
        .ndo_do_ioctl           = tlan_ioctl,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
diff --git a/drivers/net/ethernet/tile/Kconfig b/drivers/net/ethernet/tile/Kconfig
new file mode 100644 (file)
index 0000000..2d9218f
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# Tilera network device configuration
+#
+
+config TILE_NET
+       tristate "Tilera GBE/XGBE network driver support"
+       depends on TILE
+       default y
+       select CRC32
+       ---help---
+         This is a standard Linux network device driver for the
+         on-chip Tilera Gigabit Ethernet and XAUI interfaces.
+
+         To compile this driver as a module, choose M here: the module
+         will be called tile_net.
diff --git a/drivers/net/ethernet/toshiba/Kconfig b/drivers/net/ethernet/toshiba/Kconfig
new file mode 100644 (file)
index 0000000..0517647
--- /dev/null
@@ -0,0 +1,57 @@
+#
+# Toshiba network device configuration
+#
+
+config NET_VENDOR_TOSHIBA
+       bool "Toshiba devices"
+       default y
+       depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB) || PPC_PS3
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Toshiba cards. If you say Y, you will be asked
+         for your specific card in the following questions.
+
+if NET_VENDOR_TOSHIBA
+
+config GELIC_NET
+       tristate "PS3 Gigabit Ethernet driver"
+       depends on PPC_PS3
+       select PS3_SYS_MANAGER
+       ---help---
+         This driver supports the network device on the PS3 game
+         console.  This driver has built-in support for Ethernet.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ps3_gelic.
+
+config GELIC_WIRELESS
+       bool "PS3 Wireless support"
+       depends on GELIC_NET && WLAN
+       select WIRELESS_EXT
+       ---help---
+         This option adds the support for the wireless feature of PS3.
+         If you have the wireless-less model of PS3 or have no plan to
+         use wireless feature, disabling this option saves memory.  As
+         the driver automatically distinguishes the models, you can
+         safely enable this option even if you have a wireless-less model.
+
+config SPIDER_NET
+       tristate "Spider Gigabit Ethernet driver"
+       depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB)
+       select FW_LOADER
+       select SUNGEM_PHY
+       ---help---
+         This driver supports the Gigabit Ethernet chips present on the
+         Cell Processor-Based Blades from IBM.
+
+config TC35815
+       tristate "TOSHIBA TC35815 Ethernet support"
+       depends on PCI && MIPS
+       select PHYLIB
+
+endif # NET_VENDOR_TOSHIBA
diff --git a/drivers/net/ethernet/toshiba/Makefile b/drivers/net/ethernet/toshiba/Makefile
new file mode 100644 (file)
index 0000000..a506900
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the Toshiba network device drivers.
+#
+
+obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
+gelic_wireless-$(CONFIG_GELIC_WIRELESS) += ps3_gelic_wireless.o
+ps3_gelic-objs += ps3_gelic_net.o $(gelic_wireless-y)
+spidernet-y += spider_net.o spider_net_ethtool.o
+obj-$(CONFIG_SPIDER_NET) += spidernet.o
+obj-$(CONFIG_TC35815) += tc35815.o
similarity index 99%
rename from drivers/net/ps3_gelic_net.c
rename to drivers/net/ethernet/toshiba/ps3_gelic_net.c
index d82a82d..ddb33cf 100644 (file)
@@ -1452,7 +1452,7 @@ static const struct net_device_ops gelic_netdevice_ops = {
        .ndo_open = gelic_net_open,
        .ndo_stop = gelic_net_stop,
        .ndo_start_xmit = gelic_net_xmit,
-       .ndo_set_multicast_list = gelic_net_set_multi,
+       .ndo_set_rx_mode = gelic_net_set_multi,
        .ndo_change_mtu = gelic_net_change_mtu,
        .ndo_tx_timeout = gelic_net_tx_timeout,
        .ndo_set_mac_address = eth_mac_addr,
similarity index 99%
rename from drivers/net/ps3_gelic_wireless.c
rename to drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
index 2e62938..fd4ed7f 100644 (file)
@@ -2568,7 +2568,7 @@ static const struct net_device_ops gelic_wl_netdevice_ops = {
        .ndo_open = gelic_wl_open,
        .ndo_stop = gelic_wl_stop,
        .ndo_start_xmit = gelic_net_xmit,
-       .ndo_set_multicast_list = gelic_net_set_multi,
+       .ndo_set_rx_mode = gelic_net_set_multi,
        .ndo_change_mtu = gelic_net_change_mtu,
        .ndo_tx_timeout = gelic_net_tx_timeout,
        .ndo_set_mac_address = eth_mac_addr,
similarity index 99%
rename from drivers/net/spider_net.c
rename to drivers/net/ethernet/toshiba/spider_net.c
index 1ff3491..6199f6b 100644 (file)
@@ -196,7 +196,7 @@ spider_net_setup_aneg(struct spider_net_card *card)
        if ((bmsr & BMSR_ESTATEN) && (estat & ESTATUS_1000_THALF))
                advertise |= SUPPORTED_1000baseT_Half;
 
-       mii_phy_probe(phy, phy->mii_id);
+       sungem_phy_probe(phy, phy->mii_id);
        phy->def->ops->setup_aneg(phy, advertise);
 
 }
@@ -2120,7 +2120,7 @@ spider_net_setup_phy(struct spider_net_card *card)
                unsigned short id;
                id = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR);
                if (id != 0x0000 && id != 0xffff) {
-                       if (!mii_phy_probe(phy, phy->mii_id)) {
+                       if (!sungem_phy_probe(phy, phy->mii_id)) {
                                pr_info("Found %s.\n", phy->def->name);
                                break;
                        }
@@ -2259,7 +2259,7 @@ static const struct net_device_ops spider_net_ops = {
        .ndo_open               = spider_net_open,
        .ndo_stop               = spider_net_stop,
        .ndo_start_xmit         = spider_net_xmit,
-       .ndo_set_multicast_list = spider_net_set_multi,
+       .ndo_set_rx_mode        = spider_net_set_multi,
        .ndo_set_mac_address    = spider_net_set_mac,
        .ndo_change_mtu         = spider_net_change_mtu,
        .ndo_do_ioctl           = spider_net_do_ioctl,
similarity index 99%
rename from drivers/net/spider_net.h
rename to drivers/net/ethernet/toshiba/spider_net.h
index 020f64a..4ba2135 100644 (file)
@@ -27,7 +27,7 @@
 
 #define VERSION "2.0 B"
 
-#include "sungem_phy.h"
+#include <linux/sungem_phy.h>
 
 extern int spider_net_stop(struct net_device *netdev);
 extern int spider_net_open(struct net_device *netdev);
similarity index 99%
rename from drivers/net/tc35815.c
rename to drivers/net/ethernet/toshiba/tc35815.c
index 4a55a16..71b785c 100644 (file)
@@ -774,7 +774,7 @@ static const struct net_device_ops tc35815_netdev_ops = {
        .ndo_stop               = tc35815_close,
        .ndo_start_xmit         = tc35815_send_packet,
        .ndo_get_stats          = tc35815_get_stats,
-       .ndo_set_multicast_list = tc35815_set_multicast_list,
+       .ndo_set_rx_mode        = tc35815_set_multicast_list,
        .ndo_tx_timeout         = tc35815_tx_timeout,
        .ndo_do_ioctl           = tc35815_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
diff --git a/drivers/net/ethernet/tundra/Kconfig b/drivers/net/ethernet/tundra/Kconfig
new file mode 100644 (file)
index 0000000..cf7d69b
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# Tundra network device configuration
+#
+
+config NET_VENDOR_TUNDRA
+       bool "Tundra devices"
+       default y
+       depends on TSI108_BRIDGE
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Tundra cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_TUNDRA
+
+config TSI108_ETH
+       tristate "Tundra TSI108 gigabit Ethernet support"
+       depends on TSI108_BRIDGE
+       ---help---
+         This driver supports Tundra TSI108 gigabit Ethernet ports.
+         To compile this driver as a module, choose M here: the module
+         will be called tsi108_eth.
+
+endif # NET_VENDOR_TUNDRA
diff --git a/drivers/net/ethernet/tundra/Makefile b/drivers/net/ethernet/tundra/Makefile
new file mode 100644 (file)
index 0000000..439f693
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Tundra network device drivers.
+#
+
+obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
similarity index 99%
rename from drivers/net/tsi108_eth.c
rename to drivers/net/ethernet/tundra/tsi108_eth.c
index 64cb9ac..480a4ba 100644 (file)
@@ -1554,7 +1554,7 @@ static const struct net_device_ops tsi108_netdev_ops = {
        .ndo_open               = tsi108_open,
        .ndo_stop               = tsi108_close,
        .ndo_start_xmit         = tsi108_send_packet,
-       .ndo_set_multicast_list = tsi108_set_rx_mode,
+       .ndo_set_rx_mode        = tsi108_set_rx_mode,
        .ndo_get_stats          = tsi108_get_stats,
        .ndo_do_ioctl           = tsi108_do_ioctl,
        .ndo_set_mac_address    = tsi108_set_mac,
diff --git a/drivers/net/ethernet/via/Kconfig b/drivers/net/ethernet/via/Kconfig
new file mode 100644 (file)
index 0000000..e5d82a5
--- /dev/null
@@ -0,0 +1,57 @@
+#
+# VIA device configuration
+#
+
+config NET_VENDOR_VIA
+       bool "VIA devices"
+       default y
+       depends on PCI
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about VIA devices. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_VIA
+
+config VIA_RHINE
+       tristate "VIA Rhine support"
+       depends on PCI
+       select CRC32
+       select MII
+       ---help---
+         If you have a VIA "Rhine" based network card (Rhine-I (VT86C100A),
+         Rhine-II (VT6102), or Rhine-III (VT6105)), say Y here. Rhine-type
+         Ethernet functions can also be found integrated on South Bridges
+         (e.g. VT8235).
+
+         To compile this driver as a module, choose M here. The module
+         will be called via-rhine.
+
+config VIA_RHINE_MMIO
+       bool "Use MMIO instead of PIO"
+       depends on VIA_RHINE
+       ---help---
+         This instructs the driver to use PCI shared memory (MMIO) instead of
+         programmed I/O ports (PIO). Enabling this gives an improvement in
+         processing time in parts of the driver.
+
+         If unsure, say Y.
+
+config VIA_VELOCITY
+       tristate "VIA Velocity support"
+       depends on PCI
+       select CRC32
+       select CRC_CCITT
+       select MII
+       ---help---
+         If you have a VIA "Velocity" based network card say Y here.
+
+         To compile this driver as a module, choose M here. The module
+         will be called via-velocity.
+
+endif # NET_VENDOR_VIA
diff --git a/drivers/net/ethernet/via/Makefile b/drivers/net/ethernet/via/Makefile
new file mode 100644 (file)
index 0000000..46c5d4a
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the VIA device drivers.
+#
+
+obj-$(CONFIG_VIA_RHINE) += via-rhine.o
+obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
similarity index 99%
rename from drivers/net/via-rhine.c
rename to drivers/net/ethernet/via/via-rhine.c
index 7f23ab9..f34dd99 100644 (file)
@@ -697,7 +697,7 @@ static const struct net_device_ops rhine_netdev_ops = {
        .ndo_stop                = rhine_close,
        .ndo_start_xmit          = rhine_start_tx,
        .ndo_get_stats           = rhine_get_stats,
-       .ndo_set_multicast_list  = rhine_set_rx_mode,
+       .ndo_set_rx_mode         = rhine_set_rx_mode,
        .ndo_change_mtu          = eth_change_mtu,
        .ndo_validate_addr       = eth_validate_addr,
        .ndo_set_mac_address     = eth_mac_addr,
similarity index 97%
rename from drivers/net/via-velocity.c
rename to drivers/net/ethernet/via/via-velocity.c
index deb1eca..086463b 100644 (file)
@@ -42,7 +42,6 @@
  *
  */
 
-
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
@@ -112,7 +111,6 @@ static void mac_get_cam_mask(struct mac_regs __iomem *regs, u8 *mask)
        BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
 }
 
-
 /**
  *     mac_set_cam_mask        -       Set a CAM mask
  *     @regs: register block for this velocity
@@ -515,10 +513,6 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
        mac_set_cam_mask(regs, vptr->mCAMmask);
 
        /* Enable VCAMs */
-
-       if (test_bit(0, vptr->active_vlans))
-               WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
-
        for_each_set_bit(vid, vptr->active_vlans, VLAN_N_VID) {
                mac_set_vlan_cam(regs, i, (u8 *) &vid);
                vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
@@ -700,7 +694,6 @@ static int velocity_mii_read(struct mac_regs __iomem *regs, u8 index, u16 *data)
        return 0;
 }
 
-
 /**
  *     mii_check_media_mode    -       check media state
  *     @regs: velocity registers
@@ -866,8 +859,6 @@ static u32 check_connection_type(struct mac_regs __iomem *regs)
        return status;
 }
 
-
-
 /**
  *     velocity_set_media_mode         -       set media mode
  *     @mii_status: old MII link state
@@ -1262,6 +1253,7 @@ static void setup_queue_timers(struct velocity_info *vptr)
                writeb(rxqueue_timer, &vptr->mac_regs->RQETMR);
        }
 }
+
 /**
  * setup_adaptive_interrupts  -  Setup interrupt suppression
  *
@@ -1601,8 +1593,6 @@ static void velocity_free_rd_ring(struct velocity_info *vptr)
        vptr->rx.info = NULL;
 }
 
-
-
 /**
  *     velocity_init_rd_ring   -       set up receive ring
  *     @vptr: velocity to configure
@@ -1676,7 +1666,6 @@ static void velocity_free_dma_rings(struct velocity_info *vptr)
        pci_free_consistent(vptr->pdev, size, vptr->rx.ring, vptr->rx.pool_dma);
 }
 
-
 static int velocity_init_rings(struct velocity_info *vptr, int mtu)
 {
        int ret;
@@ -1739,7 +1728,6 @@ static void velocity_free_tx_buf(struct velocity_info *vptr,
        tdinfo->skb = NULL;
 }
 
-
 /*
  *     FIXME: could we merge this with velocity_free_tx_buf ?
  */
@@ -1787,7 +1775,6 @@ static void velocity_free_td_ring(struct velocity_info *vptr)
        }
 }
 
-
 static void velocity_free_rings(struct velocity_info *vptr)
 {
        velocity_free_td_ring(vptr);
@@ -2025,7 +2012,6 @@ static inline void velocity_iph_realign(struct velocity_info *vptr,
        }
 }
 
-
 /**
  *     velocity_receive_frame  -       received packet processor
  *     @vptr: velocity we are handling
@@ -2092,11 +2078,11 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
        netif_rx(skb);
 
        stats->rx_bytes += pkt_len;
+       stats->rx_packets++;
 
        return 0;
 }
 
-
 /**
  *     velocity_rx_srv         -       service RX interrupt
  *     @vptr: velocity
@@ -2404,7 +2390,6 @@ static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd
        return 0;
 }
 
-
 /**
  *     velocity_ioctl          -       ioctl entry point
  *     @dev: network device
@@ -2619,15 +2604,14 @@ out:
        return NETDEV_TX_OK;
 }
 
-
 static const struct net_device_ops velocity_netdev_ops = {
        .ndo_open               = velocity_open,
        .ndo_stop               = velocity_close,
        .ndo_start_xmit         = velocity_xmit,
        .ndo_get_stats          = velocity_get_stats,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_set_multicast_list = velocity_set_multi,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_set_rx_mode        = velocity_set_multi,
        .ndo_change_mtu         = velocity_change_mtu,
        .ndo_do_ioctl           = velocity_ioctl,
        .ndo_vlan_rx_add_vid    = velocity_vlan_rx_add_vid,
@@ -2717,7 +2701,6 @@ static u32 velocity_get_link(struct net_device *dev)
        return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0) ? 1 : 0;
 }
 
-
 /**
  *     velocity_found1         -       set up discovered velocity card
  *     @pdev: PCI device
@@ -2864,7 +2847,6 @@ err_free_dev:
        goto out;
 }
 
-
 #ifdef CONFIG_PM
 /**
  *     wol_calc_crc            -       WOL CRC
@@ -3035,7 +3017,7 @@ static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
 
        spin_lock_irqsave(&vptr->lock, flags);
        pci_save_state(pdev);
-#ifdef ETHTOOL_GWOL
+
        if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
                velocity_get_ip(vptr);
                velocity_save_context(vptr, &vptr->context);
@@ -3049,9 +3031,7 @@ static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
                pci_disable_device(pdev);
                pci_set_power_state(pdev, pci_choose_state(pdev, state));
        }
-#else
-       pci_set_power_state(pdev, pci_choose_state(pdev, state));
-#endif
+
        spin_unlock_irqrestore(&vptr->lock, flags);
        return 0;
 }
@@ -3132,13 +3112,13 @@ static int velocity_resume(struct pci_dev *pdev)
  *     uses this to handle all our card discover and plugging
  */
 static struct pci_driver velocity_driver = {
-      .name    = VELOCITY_NAME,
-      .id_table        = velocity_id_table,
-      .probe   = velocity_found1,
-      .remove  = __devexit_p(velocity_remove1),
+       .name           = VELOCITY_NAME,
+       .id_table       = velocity_id_table,
+       .probe          = velocity_found1,
+       .remove         = __devexit_p(velocity_remove1),
 #ifdef CONFIG_PM
-      .suspend = velocity_suspend,
-      .resume  = velocity_resume,
+       .suspend        = velocity_suspend,
+       .resume         = velocity_resume,
 #endif
 };
 
@@ -3448,26 +3428,99 @@ static int velocity_set_coalesce(struct net_device *dev,
        return 0;
 }
 
+static const char velocity_gstrings[][ETH_GSTRING_LEN] = {
+       "rx_all",
+       "rx_ok",
+       "tx_ok",
+       "rx_error",
+       "rx_runt_ok",
+       "rx_runt_err",
+       "rx_64",
+       "tx_64",
+       "rx_65_to_127",
+       "tx_65_to_127",
+       "rx_128_to_255",
+       "tx_128_to_255",
+       "rx_256_to_511",
+       "tx_256_to_511",
+       "rx_512_to_1023",
+       "tx_512_to_1023",
+       "rx_1024_to_1518",
+       "tx_1024_to_1518",
+       "tx_ether_collisions",
+       "rx_crc_errors",
+       "rx_jumbo",
+       "tx_jumbo",
+       "rx_mac_control_frames",
+       "tx_mac_control_frames",
+       "rx_frame_alignement_errors",
+       "rx_long_ok",
+       "rx_long_err",
+       "tx_sqe_errors",
+       "rx_no_buf",
+       "rx_symbol_errors",
+       "in_range_length_errors",
+       "late_collisions"
+};
+
+static void velocity_get_strings(struct net_device *dev, u32 sset, u8 *data)
+{
+       switch (sset) {
+       case ETH_SS_STATS:
+               memcpy(data, *velocity_gstrings, sizeof(velocity_gstrings));
+               break;
+       }
+}
+
+static int velocity_get_sset_count(struct net_device *dev, int sset)
+{
+       switch (sset) {
+       case ETH_SS_STATS:
+               return ARRAY_SIZE(velocity_gstrings);
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
+static void velocity_get_ethtool_stats(struct net_device *dev,
+                                      struct ethtool_stats *stats, u64 *data)
+{
+       if (netif_running(dev)) {
+               struct velocity_info *vptr = netdev_priv(dev);
+               u32 *p = vptr->mib_counter;
+               int i;
+
+               spin_lock_irq(&vptr->lock);
+               velocity_update_hw_mibs(vptr);
+               spin_unlock_irq(&vptr->lock);
+
+               for (i = 0; i < ARRAY_SIZE(velocity_gstrings); i++)
+                       *data++ = *p++;
+       }
+}
+
 static const struct ethtool_ops velocity_ethtool_ops = {
-       .get_settings   =       velocity_get_settings,
-       .set_settings   =       velocity_set_settings,
-       .get_drvinfo    =       velocity_get_drvinfo,
-       .get_wol        =       velocity_ethtool_get_wol,
-       .set_wol        =       velocity_ethtool_set_wol,
-       .get_msglevel   =       velocity_get_msglevel,
-       .set_msglevel   =       velocity_set_msglevel,
-       .get_link       =       velocity_get_link,
-       .get_coalesce   =       velocity_get_coalesce,
-       .set_coalesce   =       velocity_set_coalesce,
-       .begin          =       velocity_ethtool_up,
-       .complete       =       velocity_ethtool_down
+       .get_settings           = velocity_get_settings,
+       .set_settings           = velocity_set_settings,
+       .get_drvinfo            = velocity_get_drvinfo,
+       .get_wol                = velocity_ethtool_get_wol,
+       .set_wol                = velocity_ethtool_set_wol,
+       .get_msglevel           = velocity_get_msglevel,
+       .set_msglevel           = velocity_set_msglevel,
+       .get_link               = velocity_get_link,
+       .get_strings            = velocity_get_strings,
+       .get_sset_count         = velocity_get_sset_count,
+       .get_ethtool_stats      = velocity_get_ethtool_stats,
+       .get_coalesce           = velocity_get_coalesce,
+       .set_coalesce           = velocity_set_coalesce,
+       .begin                  = velocity_ethtool_up,
+       .complete               = velocity_ethtool_down
 };
 
-#ifdef CONFIG_PM
-#ifdef CONFIG_INET
+#if defined(CONFIG_PM) && defined(CONFIG_INET)
 static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
 {
-       struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
+       struct in_ifaddr *ifa = ptr;
        struct net_device *dev = ifa->ifa_dev->dev;
 
        if (dev_net(dev) == &init_net &&
@@ -3476,12 +3529,9 @@ static int velocity_netdev_event(struct notifier_block *nb, unsigned long notifi
 
        return NOTIFY_DONE;
 }
-#endif /* CONFIG_INET */
-#endif /* CONFIG_PM */
 
-#if defined(CONFIG_PM) && defined(CONFIG_INET)
 static struct notifier_block velocity_inetaddr_notifier = {
-      .notifier_call   = velocity_netdev_event,
+       .notifier_call  = velocity_netdev_event,
 };
 
 static void velocity_register_notifier(void)
diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig
new file mode 100644 (file)
index 0000000..d5a8260
--- /dev/null
@@ -0,0 +1,36 @@
+#
+# Xilink device configuration
+#
+
+config NET_VENDOR_XILINX
+       bool "Xilinx devices"
+       default y
+       depends on PPC || PPC32 || MICROBLAZE
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Xilinx devices. If you say Y, you will be asked
+         for your specific card in the following questions.
+
+if NET_VENDOR_XILINX
+
+config XILINX_EMACLITE
+       tristate "Xilinx 10/100 Ethernet Lite support"
+       depends on (PPC32 || MICROBLAZE)
+       select PHYLIB
+       ---help---
+         This driver supports the 10/100 Ethernet Lite from Xilinx.
+
+config XILINX_LL_TEMAC
+       tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
+       depends on (PPC || MICROBLAZE)
+       select PHYLIB
+       ---help---
+         This driver supports the Xilinx 10/100/1000 LocalLink TEMAC
+         core used in Xilinx Spartan and Virtex FPGAs
+
+endif # NET_VENDOR_XILINX
diff --git a/drivers/net/ethernet/xilinx/Makefile b/drivers/net/ethernet/xilinx/Makefile
new file mode 100644 (file)
index 0000000..5feac73
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the Xilink network device drivers.
+#
+
+ll_temac-objs := ll_temac_main.o ll_temac_mdio.o
+obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o
+obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
similarity index 99%
rename from drivers/net/ll_temac_main.c
rename to drivers/net/ethernet/xilinx/ll_temac_main.c
index 728fe41..570776e 100644 (file)
@@ -922,7 +922,6 @@ static const struct net_device_ops temac_netdev_ops = {
        .ndo_start_xmit = temac_start_xmit,
        .ndo_set_mac_address = netdev_set_mac_address,
        .ndo_validate_addr = eth_validate_addr,
-       //.ndo_set_multicast_list = temac_set_multicast_list,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = temac_poll_controller,
 #endif
diff --git a/drivers/net/ethernet/xircom/Kconfig b/drivers/net/ethernet/xircom/Kconfig
new file mode 100644 (file)
index 0000000..69f56a6
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# Xircom network device configuration
+#
+
+config NET_VENDOR_XIRCOM
+       bool "Xircom devices"
+       default y
+       depends on PCMCIA
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Xircom cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_XIRCOM
+
+config PCMCIA_XIRC2PS
+       tristate "Xircom 16-bit PCMCIA support"
+       depends on PCMCIA
+       ---help---
+         Say Y here if you intend to attach a Xircom 16-bit PCMCIA (PC-card)
+         Ethernet or Fast Ethernet card to your computer.
+
+         To compile this driver as a module, choose M here: the module will be
+         called xirc2ps_cs.  If unsure, say N.
+
+endif # NET_VENDOR_XIRCOM
diff --git a/drivers/net/ethernet/xircom/Makefile b/drivers/net/ethernet/xircom/Makefile
new file mode 100644 (file)
index 0000000..3b7aebd
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Xircom network device drivers.
+#
+
+obj-$(CONFIG_PCMCIA_XIRC2PS) += xirc2ps_cs.o
similarity index 99%
rename from drivers/net/pcmcia/xirc2ps_cs.c
rename to drivers/net/ethernet/xircom/xirc2ps_cs.c
index e33b190..bbe8b7d 100644 (file)
@@ -467,7 +467,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_tx_timeout         = xirc_tx_timeout,
        .ndo_set_config         = do_config,
        .ndo_do_ioctl           = do_ioctl,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
diff --git a/drivers/net/ethernet/xscale/Kconfig b/drivers/net/ethernet/xscale/Kconfig
new file mode 100644 (file)
index 0000000..cf67352
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# Intel XScale IXP device configuration
+#
+
+config NET_VENDOR_XSCALE
+       bool "Intel XScale IXP devices"
+       default y
+       depends on NET_VENDOR_INTEL && ((ARM && ARCH_IXP4XX && \
+                  IXP4XX_NPE && IXP4XX_QMGR) || ARCH_ENP2611)
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question does not directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about XSacle IXP devices. If you say Y, you will be
+         asked for your specific card in the following questions.
+
+if NET_VENDOR_XSCALE
+
+config IXP4XX_ETH
+       tristate "Intel IXP4xx Ethernet support"
+       depends on ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR
+       select PHYLIB
+       ---help---
+         Say Y here if you want to use built-in Ethernet ports
+         on IXP4xx processor.
+
+source "drivers/net/ethernet/xscale/ixp2000/Kconfig"
+
+endif # NET_VENDOR_XSCALE
diff --git a/drivers/net/ethernet/xscale/Makefile b/drivers/net/ethernet/xscale/Makefile
new file mode 100644 (file)
index 0000000..b195b9d
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the Intel XScale IXP device drivers.
+#
+
+obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/
+obj-$(CONFIG_IXP4XX_ETH) += ixp4xx_eth.o
similarity index 94%
rename from drivers/net/ixp2000/Kconfig
rename to drivers/net/ethernet/xscale/ixp2000/Kconfig
index 2fec241..58dbc5b 100644 (file)
@@ -1,6 +1,6 @@
 config ENP2611_MSF_NET
        tristate "Radisys ENP2611 MSF network interface support"
        depends on ARCH_ENP2611
-       help
+       ---help---
          This is a driver for the MSF network interface unit in
          the IXP2400 on the Radisys ENP2611 platform.
similarity index 99%
rename from drivers/net/arm/ixp4xx_eth.c
rename to drivers/net/ethernet/xscale/ixp4xx_eth.c
index de51e84..ec96d91 100644 (file)
@@ -1339,7 +1339,7 @@ static const struct net_device_ops ixp4xx_netdev_ops = {
        .ndo_open = eth_open,
        .ndo_stop = eth_close,
        .ndo_start_xmit = eth_xmit,
-       .ndo_set_multicast_list = eth_set_mcast_list,
+       .ndo_set_rx_mode = eth_set_mcast_list,
        .ndo_do_ioctl = eth_ioctl,
        .ndo_change_mtu = eth_change_mtu,
        .ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/fddi/Kconfig b/drivers/net/fddi/Kconfig
new file mode 100644 (file)
index 0000000..3a424c8
--- /dev/null
@@ -0,0 +1,77 @@
+#
+# FDDI network device configuration
+#
+
+config FDDI
+       tristate "FDDI driver support"
+       depends on PCI || EISA || TC
+       ---help---
+         Fiber Distributed Data Interface is a high speed local area network
+         design; essentially a replacement for high speed Ethernet. FDDI can
+         run over copper or fiber. If you are connected to such a network and
+         want a driver for the FDDI card in your computer, say Y here (and
+         then also Y to the driver for your FDDI card, below). Most people
+         will say N.
+
+if FDDI
+
+config DEFXX
+       tristate "Digital DEFTA/DEFEA/DEFPA adapter support"
+       depends on FDDI && (PCI || EISA || TC)
+       ---help---
+         This is support for the DIGITAL series of TURBOchannel (DEFTA),
+         EISA (DEFEA) and PCI (DEFPA) controllers which can connect you
+         to a local FDDI network.
+
+         To compile this driver as a module, choose M here: the module
+         will be called defxx.  If unsure, say N.
+
+config DEFXX_MMIO
+       bool
+       prompt "Use MMIO instead of PIO" if PCI || EISA
+       depends on DEFXX
+       default n if PCI || EISA
+       default y
+       ---help---
+         This instructs the driver to use EISA or PCI memory-mapped I/O
+         (MMIO) as appropriate instead of programmed I/O ports (PIO).
+         Enabling this gives an improvement in processing time in parts
+         of the driver, but it may cause problems with EISA (DEFEA)
+         adapters.  TURBOchannel does not have the concept of I/O ports,
+         so MMIO is always used for these (DEFTA) adapters.
+
+         If unsure, say N.
+
+config SKFP
+       tristate "SysKonnect FDDI PCI support"
+       depends on FDDI && PCI
+       select BITREVERSE
+       ---help---
+         Say Y here if you have a SysKonnect FDDI PCI adapter.
+         The following adapters are supported by this driver:
+         - SK-5521 (SK-NET FDDI-UP)
+         - SK-5522 (SK-NET FDDI-UP DAS)
+         - SK-5541 (SK-NET FDDI-FP)
+         - SK-5543 (SK-NET FDDI-LP)
+         - SK-5544 (SK-NET FDDI-LP DAS)
+         - SK-5821 (SK-NET FDDI-UP64)
+         - SK-5822 (SK-NET FDDI-UP64 DAS)
+         - SK-5841 (SK-NET FDDI-FP64)
+         - SK-5843 (SK-NET FDDI-LP64)
+         - SK-5844 (SK-NET FDDI-LP64 DAS)
+         - Netelligent 100 FDDI DAS Fibre SC
+         - Netelligent 100 FDDI SAS Fibre SC
+         - Netelligent 100 FDDI DAS UTP
+         - Netelligent 100 FDDI SAS UTP
+         - Netelligent 100 FDDI SAS Fibre MIC
+
+         Read <file:Documentation/networking/skfp.txt> for information about
+         the driver.
+
+         Questions concerning this driver can be addressed to:
+         <linux@syskonnect.de>
+
+         To compile this driver as a module, choose M here: the module
+         will be called skfp.  This is recommended.
+
+endif # FDDI
diff --git a/drivers/net/fddi/Makefile b/drivers/net/fddi/Makefile
new file mode 100644 (file)
index 0000000..36da19c
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the Linux FDDI network device drivers.
+#
+
+obj-$(CONFIG_DEFXX) += defxx.o
+obj-$(CONFIG_SKFP) += skfp/
similarity index 99%
rename from drivers/net/defxx.c
rename to drivers/net/fddi/defxx.c
index 417e143..4ad80f7 100644 (file)
@@ -483,7 +483,7 @@ static const struct net_device_ops dfx_netdev_ops = {
        .ndo_stop               = dfx_close,
        .ndo_start_xmit         = dfx_xmt_queue_pkt,
        .ndo_get_stats          = dfx_ctl_get_stats,
-       .ndo_set_multicast_list = dfx_ctl_set_multicast_list,
+       .ndo_set_rx_mode        = dfx_ctl_set_multicast_list,
        .ndo_set_mac_address    = dfx_ctl_set_mac_address,
 };
 
similarity index 100%
rename from drivers/net/defxx.h
rename to drivers/net/fddi/defxx.h
similarity index 99%
rename from drivers/net/skfp/h/cmtdef.h
rename to drivers/net/fddi/skfp/h/cmtdef.h
index 5a6c612..f5bc90f 100644 (file)
@@ -477,8 +477,8 @@ struct s_plc {
 /*
  * function prototypes
  */
-#include "h/mbuf.h"    /* Type definitions for MBUFs */
-#include "h/smtstate.h"        /* struct smt_state */
+#include "mbuf.h"      /* Type definitions for MBUFs */
+#include "smtstate.h"  /* struct smt_state */
 
 void hwt_restart(struct s_smc *smc);   /* hwt.c */
 SMbuf *smt_build_frame(struct s_smc *smc, int class, int type,
similarity index 99%
rename from drivers/net/skfp/h/hwmtm.h
rename to drivers/net/fddi/skfp/h/hwmtm.h
index e1a7e5f..5924d42 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef        _HWM_
 #define        _HWM_
 
-#include "h/mbuf.h"
+#include "mbuf.h"
 
 /*
  * MACRO for DMA synchronization:
similarity index 98%
rename from drivers/net/skfp/h/sba.h
rename to drivers/net/fddi/skfp/h/sba.h
index 638cf02..35ddb44 100644 (file)
@@ -19,8 +19,8 @@
 #ifndef _SBA_
 #define _SBA_
 
-#include "h/mbuf.h"
-#include "h/sba_def.h"
+#include "mbuf.h"
+#include "sba_def.h"
 
 #ifdef SBA
 
similarity index 99%
rename from drivers/net/skfp/h/skfbiinc.h
rename to drivers/net/fddi/skfp/h/skfbiinc.h
index ac2d719..ce72557 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef        _SKFBIINC_
 #define _SKFBIINC_
 
-#include "h/supern_2.h"
+#include "supern_2.h"
 
 /*
  * special defines for use into .asm files
similarity index 98%
rename from drivers/net/skfp/h/smc.h
rename to drivers/net/fddi/skfp/h/smc.h
index c774a95..3ca308b 100644 (file)
  *     fddi.h
  */
 #ifdef OSDEF
-#include "h/osdef1st.h"
+#include "osdef1st.h"
 #endif /* OSDEF */
 #ifdef OEM_CONCEPT
 #include "oemdef.h"
 #endif /* OEM_CONCEPT */
-#include "h/smt.h"
-#include "h/cmtdef.h"
-#include "h/fddimib.h"
-#include "h/targethw.h"                /* all target hw dependencies */
-#include "h/targetos.h"                /* all target os dependencies */
+#include "smt.h"
+#include "cmtdef.h"
+#include "fddimib.h"
+#include "targethw.h"          /* all target hw dependencies */
+#include "targetos.h"          /* all target os dependencies */
 #ifdef ESS
-#include "h/sba.h"
+#include "sba.h"
 #endif
 
 /*
similarity index 98%
rename from drivers/net/skfp/h/targethw.h
rename to drivers/net/fddi/skfp/h/targethw.h
index 626dc72..842a690 100644 (file)
 #define SK_ML_ID_2     0x30
 #endif
 
-#include       "h/skfbi.h"
+#include       "skfbi.h"
 #ifndef TAG_MODE       
-#include       "h/fplus.h"
+#include       "fplus.h"
 #else
-#include       "h/fplustm.h"
+#include       "fplustm.h"
 #endif
 
 #ifndef        HW_PTR
similarity index 99%
rename from drivers/net/skfp/h/targetos.h
rename to drivers/net/fddi/skfp/h/targetos.h
index 5d940e7..53bacc1 100644 (file)
@@ -58,7 +58,7 @@
 #define        ADDR(a) (((a)>>7) ? (outp(smc->hw.iop+B0_RAP,(a)>>7), (smc->hw.iop+( ((a)&0x7F) | ((a)>>7 ? 0x80:0)) )) : (smc->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0))))
 #endif
 
-#include "h/hwmtm.h"
+#include "hwmtm.h"
 
 #define TRUE  1
 #define FALSE 0
similarity index 99%
rename from drivers/net/skfp/skfddi.c
rename to drivers/net/fddi/skfp/skfddi.c
index 16c6265..3d9a459 100644 (file)
@@ -167,7 +167,7 @@ static const struct net_device_ops skfp_netdev_ops = {
        .ndo_start_xmit         = skfp_send_pkt,
        .ndo_get_stats          = skfp_ctl_get_stats,
        .ndo_change_mtu         = fddi_change_mtu,
-       .ndo_set_multicast_list = skfp_ctl_set_multicast_list,
+       .ndo_set_rx_mode        = skfp_ctl_set_multicast_list,
        .ndo_set_mac_address    = skfp_ctl_set_mac_address,
        .ndo_do_ioctl           = skfp_ioctl,
 };
diff --git a/drivers/net/hippi/Kconfig b/drivers/net/hippi/Kconfig
new file mode 100644 (file)
index 0000000..7393eb7
--- /dev/null
@@ -0,0 +1,39 @@
+#
+# HIPPI network device configuration
+#
+
+config HIPPI
+       bool "HIPPI driver support (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && INET && PCI
+       ---help---
+         HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and
+         1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI
+         can run over copper (25m) or fiber (300m on multi-mode or 10km on
+         single-mode). HIPPI networks are commonly used for clusters and to
+         connect to super computers. If you are connected to a HIPPI network
+         and have a HIPPI network card in your computer that you want to use
+         under Linux, say Y here (you must also remember to enable the driver
+         for your HIPPI card below). Most people will say N here.
+
+if HIPPI
+
+config ROADRUNNER
+       tristate "Essential RoadRunner HIPPI PCI adapter support (EXPERIMENTAL)"
+       depends on PCI
+       ---help---
+         Say Y here if this is your PCI HIPPI network card.
+
+         To compile this driver as a module, choose M here: the module
+         will be called rrunner.  If unsure, say N.
+
+config ROADRUNNER_LARGE_RINGS
+       bool "Use large TX/RX rings (EXPERIMENTAL)"
+       depends on ROADRUNNER
+       ---help---
+         If you say Y here, the RoadRunner driver will preallocate up to 2 MB
+         of additional memory to allow for fastest operation, both for
+         transmitting and receiving. This memory cannot be used by any other
+         kernel code or by user space programs. Say Y here only if you have
+         the memory.
+
+endif /* HIPPI */
diff --git a/drivers/net/hippi/Makefile b/drivers/net/hippi/Makefile
new file mode 100644 (file)
index 0000000..b95d629
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the HIPPI network device drivers.
+#
+
+obj-$(CONFIG_ROADRUNNER) += rrunner.o
diff --git a/drivers/net/ibm_newemac/Makefile b/drivers/net/ibm_newemac/Makefile
deleted file mode 100644 (file)
index 0b5c995..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the PowerPC 4xx on-chip ethernet driver
-#
-
-obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac.o
-
-ibm_newemac-y := mal.o core.o phy.o
-ibm_newemac-$(CONFIG_IBM_NEW_EMAC_ZMII) += zmii.o
-ibm_newemac-$(CONFIG_IBM_NEW_EMAC_RGMII) += rgmii.o
-ibm_newemac-$(CONFIG_IBM_NEW_EMAC_TAH) += tah.o
-ibm_newemac-$(CONFIG_IBM_NEW_EMAC_DEBUG) += debug.o
index 4488bd5..8266067 100644 (file)
@@ -22,6 +22,8 @@
  *  - DMA transfer support
  *  - FIFO mode support
  */
+#include <linux/io.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
index 52a7c86..ed7d7d6 100644 (file)
@@ -12,6 +12,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/io.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -511,7 +513,7 @@ static void sh_sir_tx(struct sh_sir_self *self, int phase)
 
 static int sh_sir_read_data(struct sh_sir_self *self)
 {
-       u16 val;
+       u16 val = 0;
        int timeout = 1024;
 
        while (timeout--) {
index 954f6e9..8b1c348 100644 (file)
@@ -2405,8 +2405,6 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
  * addresses making a subsystem device table necessary.
  */
 #ifdef CONFIG_PCI
-#define PCIID_VENDOR_INTEL 0x8086
-#define PCIID_VENDOR_ALI 0x10b9
 static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __initdata = {
        /*
         * Subsystems needing entries:
@@ -2416,7 +2414,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
         */
        {
                /* Guessed entry */
-               .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+               .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801DBM LPC bridge */
                .device = 0x24cc,
                .subvendor = 0x103c,
                .subdevice = 0x08bc,
@@ -2429,7 +2427,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
                .name = "HP nx5000 family",
        },
        {
-               .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+               .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801DBM LPC bridge */
                .device = 0x24cc,
                .subvendor = 0x103c,
                .subdevice = 0x088c,
@@ -2443,7 +2441,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
                .name = "HP nc8000 family",
        },
        {
-               .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+               .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801DBM LPC bridge */
                .device = 0x24cc,
                .subvendor = 0x103c,
                .subdevice = 0x0890,
@@ -2456,7 +2454,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
                .name = "HP nc6000 family",
        },
        {
-               .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+               .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801DBM LPC bridge */
                .device = 0x24cc,
                .subvendor = 0x0e11,
                .subdevice = 0x0860,
@@ -2471,7 +2469,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
        },
        {
                /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
-               .vendor = PCIID_VENDOR_INTEL,
+               .vendor = PCI_VENDOR_ID_INTEL,
                .device = 0x24c0,
                .subvendor = 0x1179,
                .subdevice = 0xffff, /* 0xffff is "any" */
@@ -2484,7 +2482,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
                .name = "Toshiba laptop with Intel 82801DB/DBL LPC bridge",
        },
        {
-               .vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */
+               .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801CAM ISA bridge */
                .device = 0x248c,
                .subvendor = 0x1179,
                .subdevice = 0xffff, /* 0xffff is "any" */
@@ -2498,7 +2496,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
        },
        {
                /* 82801DBM (ICH4-M) LPC Interface Bridge */
-               .vendor = PCIID_VENDOR_INTEL,
+               .vendor = PCI_VENDOR_ID_INTEL,
                .device = 0x24cc,
                .subvendor = 0x1179,
                .subdevice = 0xffff, /* 0xffff is "any" */
@@ -2512,7 +2510,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
        },
        {
                /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */
-               .vendor = PCIID_VENDOR_ALI,
+               .vendor = PCI_VENDOR_ID_AL,
                .device = 0x1533,
                .subvendor = 0x1179,
                .subdevice = 0xffff, /* 0xffff is "any" */
index 05172c3..836e13f 100644 (file)
@@ -561,7 +561,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
        .ndo_change_mtu         = macvlan_change_mtu,
        .ndo_change_rx_flags    = macvlan_change_rx_flags,
        .ndo_set_mac_address    = macvlan_set_mac_address,
-       .ndo_set_multicast_list = macvlan_set_multicast_list,
+       .ndo_set_rx_mode        = macvlan_set_multicast_list,
        .ndo_get_stats64        = macvlan_dev_get_stats64,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_vlan_rx_add_vid    = macvlan_vlan_rx_add_vid,
diff --git a/drivers/net/octeon/Makefile b/drivers/net/octeon/Makefile
deleted file mode 100644 (file)
index 906edec..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-
-obj-$(CONFIG_OCTEON_MGMT_ETHERNET)     += octeon_mgmt.o
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
deleted file mode 100644 (file)
index c0f2337..0000000
+++ /dev/null
@@ -1,1923 +0,0 @@
-/*
-
-       drivers/net/pci-skeleton.c
-
-       Maintained by Jeff Garzik <jgarzik@pobox.com>
-
-       Original code came from 8139too.c, which in turns was based
-       originally on Donald Becker's rtl8139.c driver, versions 1.11
-       and older.  This driver was originally based on rtl8139.c
-       version 1.07.  Header of rtl8139.c version 1.11:
-
-       -----<snip>-----
-
-               Written 1997-2000 by Donald Becker.
-               This software may be used and distributed according to the
-               terms of the GNU General Public License (GPL), incorporated
-               herein by reference.  Drivers based on or derived from this
-               code fall under the GPL and must retain the authorship,
-               copyright and license notice.  This file is not a complete
-               program and may only be used when the entire operating
-               system is licensed under the GPL.
-
-               This driver is for boards based on the RTL8129 and RTL8139
-               PCI ethernet chips.
-
-               The author may be reached as becker@scyld.com, or C/O Scyld
-               Computing Corporation 410 Severn Ave., Suite 210 Annapolis
-               MD 21403
-
-               Support and updates available at
-               http://www.scyld.com/network/rtl8139.html
-
-               Twister-tuning table provided by Kinston
-               <shangh@realtek.com.tw>.
-
-       -----<snip>-----
-
-       This software may be used and distributed according to the terms
-       of the GNU General Public License, incorporated herein by reference.
-
-
------------------------------------------------------------------------------
-
-                               Theory of Operation
-
-I. Board Compatibility
-
-This device driver is designed for the RealTek RTL8139 series, the RealTek
-Fast Ethernet controllers for PCI and CardBus.  This chip is used on many
-low-end boards, sometimes with its markings changed.
-
-
-II. Board-specific settings
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board.  The system BIOS will assign the
-PCI INTA signal to a (preferably otherwise unused) system IRQ line.
-
-III. Driver operation
-
-IIIa. Rx Ring buffers
-
-The receive unit uses a single linear ring buffer rather than the more
-common (and more efficient) descriptor-based architecture.  Incoming frames
-are sequentially stored into the Rx region, and the host copies them into
-skbuffs.
-
-Comment: While it is theoretically possible to process many frames in place,
-any delay in Rx processing would cause us to drop frames.  More importantly,
-the Linux protocol stack is not designed to operate in this manner.
-
-IIIb. Tx operation
-
-The RTL8139 uses a fixed set of four Tx descriptors in register space.
-In a stunningly bad design choice, Tx frames must be 32 bit aligned.  Linux
-aligns the IP header on word boundaries, and 14 byte ethernet header means
-that almost all frames will need to be copied to an alignment buffer.
-
-IVb. References
-
-http://www.realtek.com.tw/
-http://www.scyld.com/expert/NWay.html
-
-IVc. Errata
-
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#include <linux/crc32.h>
-#include <linux/io.h>
-
-#define NETDRV_VERSION         "1.0.1"
-#define MODNAME                        "netdrv"
-#define NETDRV_DRIVER_LOAD_MSG "MyVendor Fast Ethernet driver " NETDRV_VERSION " loaded"
-
-static char version[] __devinitdata =
-       KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n"
-       "  Support available from http://foo.com/bar/baz.html\n";
-
-/* define to 1 to enable PIO instead of MMIO */
-#undef USE_IO_OPS
-
-/* define to 1 to enable copious debugging info */
-#undef NETDRV_DEBUG
-
-/* define to 1 to disable lightweight runtime debugging checks */
-#undef NETDRV_NDEBUG
-
-
-#ifdef NETDRV_DEBUG
-/* note: prints function name for you */
-#define DPRINTK(fmt, args...)                                  \
-       printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
-#else
-#define DPRINTK(fmt, args...)                          \
-do {                                                   \
-       if (0)                                          \
-               printk(KERN_DEBUG fmt, ##args);         \
-} while (0)
-#endif
-
-#ifdef NETDRV_NDEBUG
-#define assert(expr) do {} while (0)
-#else
-#define assert(expr)                                           \
-       if (!(expr)) {                                          \
-               printk("Assertion failed! %s,%s,%s,line=%d\n",  \
-                      #expr, __FILE__, __func__, __LINE__);    \
-       }
-#endif
-
-
-/* A few user-configurable values. */
-/* media options */
-static int media[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
-
-/* 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;
-
-/* Size of the in-memory receive ring. */
-#define RX_BUF_LEN_IDX 2       /* 0==8K, 1==16K, 2==32K, 3==64K */
-#define RX_BUF_LEN     (8192 << RX_BUF_LEN_IDX)
-#define RX_BUF_PAD     16
-#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
-#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)
-
-/* Number of Tx descriptor registers. */
-#define NUM_TX_DESC    4
-
-/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/
-#define MAX_ETH_FRAME_SIZE     1536
-
-/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
-#define TX_BUF_SIZE    MAX_ETH_FRAME_SIZE
-#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC)
-
-/* PCI Tuning Parameters
-   Threshold is bytes transferred to chip before transmission starts. */
-#define TX_FIFO_THRESH 256     /* In bytes, rounded down to 32 byte units. */
-
-/* The following settings are log_2(bytes)-4:
-   0==16 bytes 1==32 2==64 3==128 4==256 5==512 6==1024 7==end of packet.
-*/
-#define RX_FIFO_THRESH 6       /* Rx buffer level before first PCI xfer.  */
-#define RX_DMA_BURST   6       /* Maximum PCI burst, '6' is 1024 */
-#define TX_DMA_BURST   6       /* Maximum PCI burst, '6' is 1024 */
-
-
-/* Operational parameters that usually are not changed. */
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT     (6 * HZ)
-
-enum {
-       HAS_CHIP_XCVR = 0x020000,
-       HAS_LNK_CHNG = 0x040000,
-};
-
-#define NETDRV_MIN_IO_SIZE 0x80
-#define RTL8139B_IO_SIZE 256
-
-#define NETDRV_CAPS    (HAS_CHIP_XCVR | HAS_LNK_CHNG)
-
-typedef enum {
-       RTL8139 = 0,
-       NETDRV_CB,
-       SMC1211TX,
-       /*MPX5030,*/
-       DELTA8139,
-       ADDTRON8139,
-} board_t;
-
-
-/* indexed by board_t, above */
-static struct {
-       const char *name;
-} board_info[] __devinitdata = {
-       { "RealTek RTL8139 Fast Ethernet" },
-       { "RealTek RTL8139B PCI/CardBus" },
-       { "SMC1211TX EZCard 10/100 (RealTek RTL8139)" },
-/*     { MPX5030, "Accton MPX5030 (RealTek RTL8139)" },*/
-       { "Delta Electronics 8139 10/100BaseTX" },
-       { "Addtron Technology 8139 10/100BaseTX" },
-};
-
-
-static DEFINE_PCI_DEVICE_TABLE(netdrv_pci_tbl) = {
-       {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-       {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NETDRV_CB },
-       {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMC1211TX },
-/*     {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MPX5030 },*/
-       {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DELTA8139 },
-       {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 },
-       {0,}
-};
-MODULE_DEVICE_TABLE(pci, netdrv_pci_tbl);
-
-
-/* The rest of these values should never change. */
-
-/* Symbolic offsets to registers. */
-enum NETDRV_registers {
-       MAC0 = 0,               /* Ethernet hardware address. */
-       MAR0 = 8,               /* Multicast filter. */
-       TxStatus0 = 0x10,       /* Transmit status (Four 32bit registers). */
-       TxAddr0 = 0x20,         /* Tx descriptors (also four 32bit). */
-       RxBuf = 0x30,
-       RxEarlyCnt = 0x34,
-       RxEarlyStatus = 0x36,
-       ChipCmd = 0x37,
-       RxBufPtr = 0x38,
-       RxBufAddr = 0x3A,
-       IntrMask = 0x3C,
-       IntrStatus = 0x3E,
-       TxConfig = 0x40,
-       ChipVersion = 0x43,
-       RxConfig = 0x44,
-       Timer = 0x48,           /* A general-purpose counter. */
-       RxMissed = 0x4C,        /* 24 bits valid, write clears. */
-       Cfg9346 = 0x50,
-       Config0 = 0x51,
-       Config1 = 0x52,
-       FlashReg = 0x54,
-       MediaStatus = 0x58,
-       Config3 = 0x59,
-       Config4 = 0x5A,         /* absent on RTL-8139A */
-       HltClk = 0x5B,
-       MultiIntr = 0x5C,
-       TxSummary = 0x60,
-       BasicModeCtrl = 0x62,
-       BasicModeStatus = 0x64,
-       NWayAdvert = 0x66,
-       NWayLPAR = 0x68,
-       NWayExpansion = 0x6A,
-       /* Undocumented registers, but required for proper operation. */
-       FIFOTMS = 0x70,         /* FIFO Control and test. */
-       CSCR = 0x74,            /* Chip Status and Configuration Register. */
-       PARA78 = 0x78,
-       PARA7c = 0x7c,          /* Magic transceiver parameter register. */
-       Config5 = 0xD8,         /* absent on RTL-8139A */
-};
-
-enum ClearBitMasks {
-       MultiIntrClear = 0xF000,
-       ChipCmdClear = 0xE2,
-       Config1Clear = (1 << 7) | (1 << 6) | (1 << 3) | (1 << 2) | (1 << 1),
-};
-
-enum ChipCmdBits {
-       CmdReset = 0x10,
-       CmdRxEnb = 0x08,
-       CmdTxEnb = 0x04,
-       RxBufEmpty = 0x01,
-};
-
-/* Interrupt register bits, using my own meaningful names. */
-enum IntrStatusBits {
-       PCIErr = 0x8000,
-       PCSTimeout = 0x4000,
-       RxFIFOOver = 0x40,
-       RxUnderrun = 0x20,
-       RxOverflow = 0x10,
-       TxErr = 0x08,
-       TxOK = 0x04,
-       RxErr = 0x02,
-       RxOK = 0x01,
-};
-enum TxStatusBits {
-       TxHostOwns = 0x2000,
-       TxUnderrun = 0x4000,
-       TxStatOK = 0x8000,
-       TxOutOfWindow = 0x20000000,
-       TxAborted = 0x40000000,
-       TxCarrierLost = 0x80000000,
-};
-enum RxStatusBits {
-       RxMulticast = 0x8000,
-       RxPhysical = 0x4000,
-       RxBroadcast = 0x2000,
-       RxBadSymbol = 0x0020,
-       RxRunt = 0x0010,
-       RxTooLong = 0x0008,
-       RxCRCErr = 0x0004,
-       RxBadAlign = 0x0002,
-       RxStatusOK = 0x0001,
-};
-
-/* Bits in RxConfig. */
-enum rx_mode_bits {
-       AcceptErr = 0x20,
-       AcceptRunt = 0x10,
-       AcceptBroadcast = 0x08,
-       AcceptMulticast = 0x04,
-       AcceptMyPhys = 0x02,
-       AcceptAllPhys = 0x01,
-};
-
-/* Bits in TxConfig. */
-enum tx_config_bits {
-       TxIFG1 = (1 << 25),     /* Interframe Gap Time */
-       TxIFG0 = (1 << 24),     /* Enabling these bits violates IEEE 802.3 */
-       TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
-       TxCRC = (1 << 16),      /* DISABLE appending CRC to end of Tx packets */
-       TxClearAbt = (1 << 0),  /* Clear abort (WO) */
-       TxDMAShift = 8,         /* DMA burst value(0-7) is shift this many bits */
-
-       TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
-};
-
-/* Bits in Config1 */
-enum Config1Bits {
-       Cfg1_PM_Enable = 0x01,
-       Cfg1_VPD_Enable = 0x02,
-       Cfg1_PIO = 0x04,
-       Cfg1_MMIO = 0x08,
-       Cfg1_LWAKE = 0x10,
-       Cfg1_Driver_Load = 0x20,
-       Cfg1_LED0 = 0x40,
-       Cfg1_LED1 = 0x80,
-};
-
-enum RxConfigBits {
-       /* Early Rx threshold, none or X/16 */
-       RxCfgEarlyRxNone = 0,
-       RxCfgEarlyRxShift = 24,
-
-       /* rx fifo threshold */
-       RxCfgFIFOShift = 13,
-       RxCfgFIFONone = (7 << RxCfgFIFOShift),
-
-       /* Max DMA burst */
-       RxCfgDMAShift = 8,
-       RxCfgDMAUnlimited = (7 << RxCfgDMAShift),
-
-       /* rx ring buffer length */
-       RxCfgRcv8K = 0,
-       RxCfgRcv16K = (1 << 11),
-       RxCfgRcv32K = (1 << 12),
-       RxCfgRcv64K = (1 << 11) | (1 << 12),
-
-       /* Disable packet wrap at end of Rx buffer */
-       RxNoWrap = (1 << 7),
-};
-
-
-/* Twister tuning parameters from RealTek.
-   Completely undocumented, but required to tune bad links. */
-enum CSCRBits {
-       CSCR_LinkOKBit = 0x0400,
-       CSCR_LinkChangeBit = 0x0800,
-       CSCR_LinkStatusBits = 0x0f000,
-       CSCR_LinkDownOffCmd = 0x003c0,
-       CSCR_LinkDownCmd = 0x0f3c0,
-};
-
-
-enum Cfg9346Bits {
-       Cfg9346_Lock = 0x00,
-       Cfg9346_Unlock = 0xC0,
-};
-
-
-#define PARA78_default 0x78fa8388
-#define PARA7c_default 0xcb38de43      /* param[0][3] */
-#define PARA7c_xxx             0xcb38de43
-static const unsigned long param[4][4] = {
-       {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43},
-       {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
-       {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
-       {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83}
-};
-
-struct ring_info {
-       struct sk_buff *skb;
-       dma_addr_t mapping;
-};
-
-
-typedef enum {
-       CH_8139 = 0,
-       CH_8139_K,
-       CH_8139A,
-       CH_8139B,
-       CH_8130,
-       CH_8139C,
-} chip_t;
-
-
-/* directly indexed by chip_t, above */
-static const struct {
-       const char *name;
-       u8 version; /* from RTL8139C docs */
-       u32 RxConfigMask; /* should clear the bits supported by this chip */
-} rtl_chip_info[] = {
-       { "RTL-8139",
-         0x40,
-         0xf0fe0040, /* XXX copied from RTL8139A, verify */
-       },
-
-       { "RTL-8139 rev K",
-         0x60,
-         0xf0fe0040,
-       },
-
-       { "RTL-8139A",
-         0x70,
-         0xf0fe0040,
-       },
-
-       { "RTL-8139B",
-         0x78,
-         0xf0fc0040
-       },
-
-       { "RTL-8130",
-         0x7C,
-         0xf0fe0040, /* XXX copied from RTL8139A, verify */
-       },
-
-       { "RTL-8139C",
-         0x74,
-         0xf0fc0040, /* XXX copied from RTL8139B, verify */
-       },
-
-};
-
-
-struct netdrv_private {
-       board_t board;
-       void *mmio_addr;
-       int drv_flags;
-       struct pci_dev *pci_dev;
-       struct timer_list timer;        /* Media selection timer. */
-       unsigned char *rx_ring;
-       unsigned int cur_rx;    /* Index into the Rx buffer of next Rx pkt. */
-       unsigned int tx_flag;
-       atomic_t cur_tx;
-       atomic_t dirty_tx;
-       /* The saved address of a sent-in-place packet/buffer, for skfree(). */
-       struct ring_info tx_info[NUM_TX_DESC];
-       unsigned char *tx_buf[NUM_TX_DESC];     /* Tx bounce buffers */
-       unsigned char *tx_bufs; /* Tx bounce buffer region. */
-       dma_addr_t rx_ring_dma;
-       dma_addr_t tx_bufs_dma;
-       char phys[4];           /* MII device addresses. */
-       char twistie, twist_row, twist_col;     /* Twister tune state. */
-       unsigned int full_duplex:1;     /* Full-duplex operation requested. */
-       unsigned int duplex_lock:1;
-       unsigned int default_port:4;    /* Last dev->if_port value. */
-       unsigned int media2:4;  /* Secondary monitored media port. */
-       unsigned int medialock:1;       /* Don't sense media type. */
-       unsigned int mediasense:1;      /* Media sensing in progress. */
-       spinlock_t lock;
-       chip_t chipset;
-};
-
-MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
-MODULE_DESCRIPTION("Skeleton for a PCI Fast Ethernet driver");
-MODULE_LICENSE("GPL");
-module_param(multicast_filter_limit, int, 0);
-module_param(max_interrupt_work, int, 0);
-module_param_array(media, int, NULL, 0);
-MODULE_PARM_DESC(multicast_filter_limit,
-                MODNAME " maximum number of filtered multicast addresses");
-MODULE_PARM_DESC(max_interrupt_work,
-                MODNAME " maximum events handled per interrupt");
-MODULE_PARM_DESC(media,
-                MODNAME " Bits 0-3: media type, bit 17: full duplex");
-
-static int read_eeprom(void *ioaddr, int location, int addr_len);
-static int netdrv_open(struct net_device *dev);
-static int mdio_read(struct net_device *dev, int phy_id, int location);
-static void mdio_write(struct net_device *dev, int phy_id, int location,
-                      int val);
-static void netdrv_timer(unsigned long data);
-static void netdrv_tx_timeout(struct net_device *dev);
-static void netdrv_init_ring(struct net_device *dev);
-static int netdrv_start_xmit(struct sk_buff *skb,
-                            struct net_device *dev);
-static irqreturn_t netdrv_interrupt(int irq, void *dev_instance);
-static int netdrv_close(struct net_device *dev);
-static int netdrv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void netdrv_set_rx_mode(struct net_device *dev);
-static void netdrv_hw_start(struct net_device *dev);
-
-
-#ifdef USE_IO_OPS
-
-#define NETDRV_R8(reg)         inb(((unsigned long)ioaddr) + (reg))
-#define NETDRV_R16(reg)                inw(((unsigned long)ioaddr) + (reg))
-#define NETDRV_R32(reg)                ((unsigned long)inl(((unsigned long)ioaddr) + (reg)))
-#define NETDRV_W8(reg, val8)   outb((val8), ((unsigned long)ioaddr) + (reg))
-#define NETDRV_W16(reg, val16) outw((val16), ((unsigned long)ioaddr) + (reg))
-#define NETDRV_W32(reg, val32) outl((val32), ((unsigned long)ioaddr) + (reg))
-#define NETDRV_W8_F            NETDRV_W8
-#define NETDRV_W16_F           NETDRV_W16
-#define NETDRV_W32_F           NETDRV_W32
-#undef readb
-#undef readw
-#undef readl
-#undef writeb
-#undef writew
-#undef writel
-#define readb(addr) inb((unsigned long)(addr))
-#define readw(addr) inw((unsigned long)(addr))
-#define readl(addr) inl((unsigned long)(addr))
-#define writeb(val, addr) outb((val), (unsigned long)(addr))
-#define writew(val, addr) outw((val), (unsigned long)(addr))
-#define writel(val, addr) outl((val), (unsigned long)(addr))
-
-#else
-
-/* write MMIO register, with flush */
-/* Flush avoids rtl8139 bug w/ posted MMIO writes */
-#define NETDRV_W8_F(reg, val8)                 \
-do {                                           \
-       writeb((val8), ioaddr + (reg));         \
-       readb(ioaddr + (reg));                  \
-} while (0)
-#define NETDRV_W16_F(reg, val16)               \
-do {                                           \
-       writew((val16), ioaddr + (reg));        \
-       readw(ioaddr + (reg));                  \
-} while (0)
-#define NETDRV_W32_F(reg, val32)               \
-do {                                           \
-       writel((val32), ioaddr + (reg));        \
-       readl(ioaddr + (reg));                  \
-} while (0)
-
-
-#ifdef MMIO_FLUSH_AUDIT_COMPLETE
-
-/* write MMIO register */
-#define NETDRV_W8(reg, val8)   writeb((val8), ioaddr + (reg))
-#define NETDRV_W16(reg, val16) writew((val16), ioaddr + (reg))
-#define NETDRV_W32(reg, val32) writel((val32), ioaddr + (reg))
-
-#else
-
-/* write MMIO register, then flush */
-#define NETDRV_W8              NETDRV_W8_F
-#define NETDRV_W16             NETDRV_W16_F
-#define NETDRV_W32             NETDRV_W32_F
-
-#endif /* MMIO_FLUSH_AUDIT_COMPLETE */
-
-/* read MMIO register */
-#define NETDRV_R8(reg)         readb(ioaddr + (reg))
-#define NETDRV_R16(reg)                readw(ioaddr + (reg))
-#define NETDRV_R32(reg)                ((unsigned long) readl(ioaddr + (reg)))
-
-#endif /* USE_IO_OPS */
-
-
-static const u16 netdrv_intr_mask =
-       PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver |
-       TxErr | TxOK | RxErr | RxOK;
-
-static const unsigned int netdrv_rx_config =
-       RxCfgEarlyRxNone | RxCfgRcv32K | RxNoWrap |
-       (RX_FIFO_THRESH << RxCfgFIFOShift) |
-       (RX_DMA_BURST << RxCfgDMAShift);
-
-
-static int __devinit netdrv_init_board(struct pci_dev *pdev,
-                                      struct net_device **dev_out,
-                                      void **ioaddr_out)
-{
-       void *ioaddr = NULL;
-       struct net_device *dev;
-       struct netdrv_private *tp;
-       int rc, i;
-       u32 pio_start, pio_end, pio_flags, pio_len;
-       unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
-       u32 tmp;
-
-       DPRINTK("ENTER\n");
-
-       assert(pdev != NULL);
-       assert(ioaddr_out != NULL);
-
-       *ioaddr_out = NULL;
-       *dev_out = NULL;
-
-       /* dev zeroed in alloc_etherdev */
-       dev = alloc_etherdev(sizeof(*tp));
-       if (dev == NULL) {
-               dev_err(&pdev->dev, "unable to alloc new ethernet\n");
-               DPRINTK("EXIT, returning -ENOMEM\n");
-               return -ENOMEM;
-       }
-       SET_NETDEV_DEV(dev, &pdev->dev);
-       tp = netdev_priv(dev);
-
-       /* enable device(incl. PCI PM wakeup), and bus-mastering */
-       rc = pci_enable_device(pdev);
-       if (rc)
-               goto err_out;
-
-       pio_start = pci_resource_start(pdev, 0);
-       pio_end = pci_resource_end(pdev, 0);
-       pio_flags = pci_resource_flags(pdev, 0);
-       pio_len = pci_resource_len(pdev, 0);
-
-       mmio_start = pci_resource_start(pdev, 1);
-       mmio_end = pci_resource_end(pdev, 1);
-       mmio_flags = pci_resource_flags(pdev, 1);
-       mmio_len = pci_resource_len(pdev, 1);
-
-       /* set this immediately, we need to know before
-        * we talk to the chip directly */
-       DPRINTK("PIO region size == %#02X\n", pio_len);
-       DPRINTK("MMIO region size == %#02lX\n", mmio_len);
-
-       /* 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;
-       }
-
-       /* 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;
-       }
-
-       /* check for weird/broken PCI region reporting */
-       if ((pio_len < NETDRV_MIN_IO_SIZE) ||
-           (mmio_len < NETDRV_MIN_IO_SIZE)) {
-               dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n");
-               rc = -ENODEV;
-               goto err_out;
-       }
-
-       rc = pci_request_regions(pdev, MODNAME);
-       if (rc)
-               goto err_out;
-
-       pci_set_master(pdev);
-
-#ifdef USE_IO_OPS
-       ioaddr = (void *)pio_start;
-#else
-       /* ioremap MMIO region */
-       ioaddr = ioremap(mmio_start, mmio_len);
-       if (ioaddr == NULL) {
-               dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
-               rc = -EIO;
-               goto err_out_free_res;
-       }
-#endif /* USE_IO_OPS */
-
-       /* Soft reset the chip. */
-       NETDRV_W8(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear) | CmdReset);
-
-       /* Check that the chip has finished the reset. */
-       for (i = 1000; i > 0; i--)
-               if ((NETDRV_R8(ChipCmd) & CmdReset) == 0)
-                       break;
-               else
-                       udelay(10);
-
-       /* Bring the chip out of low-power mode. */
-       /* <insert device-specific code here> */
-
-#ifndef USE_IO_OPS
-       /* sanity checks -- ensure PIO and MMIO registers agree */
-       assert(inb(pio_start+Config0) == readb(ioaddr+Config0));
-       assert(inb(pio_start+Config1) == readb(ioaddr+Config1));
-       assert(inb(pio_start+TxConfig) == readb(ioaddr+TxConfig));
-       assert(inb(pio_start+RxConfig) == readb(ioaddr+RxConfig));
-#endif /* !USE_IO_OPS */
-
-       /* identify chip attached to board */
-       tmp = NETDRV_R8(ChipVersion);
-       for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--)
-               if (tmp == rtl_chip_info[i].version) {
-                       tp->chipset = i;
-                       goto match;
-               }
-
-       /* if unknown chip, assume array element #0, original RTL-8139 in this case */
-       dev_printk(KERN_DEBUG, &pdev->dev,
-                  "unknown chip version, assuming RTL-8139\n");
-       dev_printk(KERN_DEBUG, &pdev->dev, "TxConfig = %#lx\n",
-                  NETDRV_R32(TxConfig));
-       tp->chipset = 0;
-
-match:
-       DPRINTK("chipset id(%d) == index %d, '%s'\n",
-               tmp, tp->chipset, rtl_chip_info[tp->chipset].name);
-
-       rc = register_netdev(dev);
-       if (rc)
-               goto err_out_unmap;
-
-       DPRINTK("EXIT, returning 0\n");
-       *ioaddr_out = ioaddr;
-       *dev_out = dev;
-       return 0;
-
-err_out_unmap:
-#ifndef USE_IO_OPS
-       iounmap(ioaddr);
-err_out_free_res:
-#endif
-       pci_release_regions(pdev);
-err_out:
-       free_netdev(dev);
-       DPRINTK("EXIT, returning %d\n", rc);
-       return rc;
-}
-
-static const struct net_device_ops netdrv_netdev_ops = {
-       .ndo_open               = netdrv_open,
-       .ndo_stop               = netdrv_close,
-       .ndo_start_xmit         = netdrv_start_xmit,
-       .ndo_set_multicast_list = netdrv_set_rx_mode,
-       .ndo_do_ioctl           = netdrv_ioctl,
-       .ndo_tx_timeout         = netdrv_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-};
-
-static int __devinit netdrv_init_one(struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
-{
-       struct net_device *dev = NULL;
-       struct netdrv_private *tp;
-       int i, addr_len, option;
-       void *ioaddr = NULL;
-       static int board_idx = -1;
-
-/* when built into the kernel, we only print version if device is found */
-#ifndef MODULE
-       static int printed_version;
-       if (!printed_version++)
-               printk(version);
-#endif
-
-       DPRINTK("ENTER\n");
-
-       assert(pdev != NULL);
-       assert(ent != NULL);
-
-       board_idx++;
-
-       i = netdrv_init_board(pdev, &dev, &ioaddr);
-       if (i < 0) {
-               DPRINTK("EXIT, returning %d\n", i);
-               return i;
-       }
-
-       tp = netdev_priv(dev);
-
-       assert(ioaddr != NULL);
-       assert(dev != NULL);
-       assert(tp != NULL);
-
-       addr_len = read_eeprom(ioaddr, 0, 8) == 0x8129 ? 8 : 6;
-       for (i = 0; i < 3; i++)
-               ((u16 *)(dev->dev_addr))[i] =
-                       le16_to_cpu(read_eeprom(ioaddr, i + 7, addr_len));
-
-       dev->netdev_ops = &netdrv_netdev_ops;
-       dev->watchdog_timeo = TX_TIMEOUT;
-
-       dev->irq = pdev->irq;
-       dev->base_addr = (unsigned long) ioaddr;
-
-       /* netdev_priv()/tp zeroed and aligned in alloc_etherdev */
-       tp = netdev_priv(dev);
-
-       /* note: tp->chipset set in netdrv_init_board */
-       tp->drv_flags = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
-               PCI_COMMAND_MASTER | NETDRV_CAPS;
-       tp->pci_dev = pdev;
-       tp->board = ent->driver_data;
-       tp->mmio_addr = ioaddr;
-       spin_lock_init(&tp->lock);
-
-       pci_set_drvdata(pdev, dev);
-
-       tp->phys[0] = 32;
-
-       netdev_info(dev, "%s at %#lx, %pM IRQ %d\n",
-                   board_info[ent->driver_data].name,
-                   dev->base_addr, dev->dev_addr, dev->irq);
-
-       netdev_printk(KERN_DEBUG, dev, "Identified 8139 chip type '%s'\n",
-                     rtl_chip_info[tp->chipset].name);
-
-       /* Put the chip into low-power mode. */
-       NETDRV_W8_F(Cfg9346, Cfg9346_Unlock);
-
-       /* The lower four bits are the media type. */
-       option = (board_idx > 7) ? 0 : media[board_idx];
-       if (option > 0) {
-               tp->full_duplex = (option & 0x200) ? 1 : 0;
-               tp->default_port = option & 15;
-               if (tp->default_port)
-                       tp->medialock = 1;
-       }
-
-       if (tp->full_duplex) {
-               netdev_info(dev, "Media type forced to Full Duplex\n");
-               mdio_write(dev, tp->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
-               tp->duplex_lock = 1;
-       }
-
-       DPRINTK("EXIT - returning 0\n");
-       return 0;
-}
-
-
-static void __devexit netdrv_remove_one(struct pci_dev *pdev)
-{
-       struct net_device *dev = pci_get_drvdata(pdev);
-       struct netdrv_private *np;
-
-       DPRINTK("ENTER\n");
-
-       assert(dev != NULL);
-
-       np = netdev_priv(dev);
-       assert(np != NULL);
-
-       unregister_netdev(dev);
-
-#ifndef USE_IO_OPS
-       iounmap(np->mmio_addr);
-#endif /* !USE_IO_OPS */
-
-       pci_release_regions(pdev);
-
-       free_netdev(dev);
-
-       pci_set_drvdata(pdev, NULL);
-
-       pci_disable_device(pdev);
-
-       DPRINTK("EXIT\n");
-}
-
-
-/* Serial EEPROM section. */
-
-/*  EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK   0x04    /* EEPROM shift clock. */
-#define EE_CS          0x08    /* EEPROM chip select. */
-#define EE_DATA_WRITE  0x02    /* EEPROM chip data in. */
-#define EE_WRITE_0     0x00
-#define EE_WRITE_1     0x02
-#define EE_DATA_READ   0x01    /* EEPROM chip data out. */
-#define EE_ENB         (0x80 | EE_CS)
-
-/* Delay between EEPROM clock transitions.
-   No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
-*/
-
-#define eeprom_delay() readl(ee_addr)
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD   (5)
-#define EE_READ_CMD    (6)
-#define EE_ERASE_CMD   (7)
-
-static int __devinit read_eeprom(void *ioaddr, int location, int addr_len)
-{
-       int i;
-       unsigned retval = 0;
-       void *ee_addr = ioaddr + Cfg9346;
-       int read_cmd = location | (EE_READ_CMD << addr_len);
-
-       DPRINTK("ENTER\n");
-
-       writeb(EE_ENB & ~EE_CS, ee_addr);
-       writeb(EE_ENB, ee_addr);
-       eeprom_delay();
-
-       /* Shift the read command bits out. */
-       for (i = 4 + addr_len; i >= 0; i--) {
-               int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-               writeb(EE_ENB | dataval, ee_addr);
-               eeprom_delay();
-               writeb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-               eeprom_delay();
-       }
-       writeb(EE_ENB, ee_addr);
-       eeprom_delay();
-
-       for (i = 16; i > 0; i--) {
-               writeb(EE_ENB | EE_SHIFT_CLK, ee_addr);
-               eeprom_delay();
-               retval =
-                       (retval << 1) | ((readb(ee_addr) & EE_DATA_READ) ? 1 :
-                                       0);
-               writeb(EE_ENB, ee_addr);
-               eeprom_delay();
-       }
-
-       /* Terminate the EEPROM access. */
-       writeb(~EE_CS, ee_addr);
-       eeprom_delay();
-
-       DPRINTK("EXIT - returning %d\n", retval);
-       return retval;
-}
-
-/* MII serial management: mostly bogus for now. */
-/* Read and write the MII management registers using software-generated
-   serial MDIO protocol.
-   The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
-   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
-   "overclocking" issues. */
-#define MDIO_DIR       0x80
-#define MDIO_DATA_OUT  0x04
-#define MDIO_DATA_IN   0x02
-#define MDIO_CLK       0x01
-#define MDIO_WRITE0    (MDIO_DIR)
-#define MDIO_WRITE1    (MDIO_DIR | MDIO_DATA_OUT)
-
-#define mdio_delay()   readb(mdio_addr)
-
-
-static char mii_2_8139_map[8] = {
-       BasicModeCtrl,
-       BasicModeStatus,
-       0,
-       0,
-       NWayAdvert,
-       NWayLPAR,
-       NWayExpansion,
-       0
-};
-
-
-/* Syncronize the MII management interface by shifting 32 one bits out. */
-static void mdio_sync(void *mdio_addr)
-{
-       int i;
-
-       DPRINTK("ENTER\n");
-
-       for (i = 32; i >= 0; i--) {
-               writeb(MDIO_WRITE1, mdio_addr);
-               mdio_delay();
-               writeb(MDIO_WRITE1 | MDIO_CLK, mdio_addr);
-               mdio_delay();
-       }
-
-       DPRINTK("EXIT\n");
-}
-
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-       struct netdrv_private *tp = netdev_priv(dev);
-       void *mdio_addr = tp->mmio_addr + Config4;
-       int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
-       int retval = 0;
-       int i;
-
-       DPRINTK("ENTER\n");
-
-       if (phy_id > 31) {      /* Really a 8139.  Use internal registers. */
-               DPRINTK("EXIT after directly using 8139 internal regs\n");
-               return location < 8 && mii_2_8139_map[location] ?
-                       readw(tp->mmio_addr + mii_2_8139_map[location]) : 0;
-       }
-       mdio_sync(mdio_addr);
-       /* Shift the read command bits out. */
-       for (i = 15; i >= 0; i--) {
-               int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
-
-               writeb(MDIO_DIR | dataval, mdio_addr);
-               mdio_delay();
-               writeb(MDIO_DIR | dataval | MDIO_CLK, mdio_addr);
-               mdio_delay();
-       }
-
-       /* Read the two transition, 16 data, and wire-idle bits. */
-       for (i = 19; i > 0; i--) {
-               writeb(0, mdio_addr);
-               mdio_delay();
-               retval = ((retval << 1) | ((readb(mdio_addr) & MDIO_DATA_IN))
-                         ? 1 : 0);
-               writeb(MDIO_CLK, mdio_addr);
-               mdio_delay();
-       }
-
-       DPRINTK("EXIT, returning %d\n", (retval >> 1) & 0xffff);
-       return (retval >> 1) & 0xffff;
-}
-
-
-static void mdio_write(struct net_device *dev, int phy_id, int location,
-                      int value)
-{
-       struct netdrv_private *tp = netdev_priv(dev);
-       void *mdio_addr = tp->mmio_addr + Config4;
-       int mii_cmd =
-               (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
-       int i;
-
-       DPRINTK("ENTER\n");
-
-       if (phy_id > 31) {      /* Really a 8139.  Use internal registers. */
-               if (location < 8 && mii_2_8139_map[location]) {
-                       writew(value,
-                              tp->mmio_addr + mii_2_8139_map[location]);
-                       readw(tp->mmio_addr + mii_2_8139_map[location]);
-               }
-               DPRINTK("EXIT after directly using 8139 internal regs\n");
-               return;
-       }
-       mdio_sync(mdio_addr);
-
-       /* Shift the command bits out. */
-       for (i = 31; i >= 0; i--) {
-               int dataval =
-                       (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
-               writeb(dataval, mdio_addr);
-               mdio_delay();
-               writeb(dataval | MDIO_CLK, mdio_addr);
-               mdio_delay();
-       }
-
-       /* Clear out extra bits. */
-       for (i = 2; i > 0; i--) {
-               writeb(0, mdio_addr);
-               mdio_delay();
-               writeb(MDIO_CLK, mdio_addr);
-               mdio_delay();
-       }
-
-       DPRINTK("EXIT\n");
-}
-
-
-static int netdrv_open(struct net_device *dev)
-{
-       struct netdrv_private *tp = netdev_priv(dev);
-       int retval;
-       void *ioaddr = tp->mmio_addr;
-
-       DPRINTK("ENTER\n");
-
-       retval = request_irq(dev->irq, netdrv_interrupt, IRQF_SHARED, dev->name, dev);
-       if (retval) {
-               DPRINTK("EXIT, returning %d\n", retval);
-               return retval;
-       }
-
-       tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
-                                          &tp->tx_bufs_dma);
-       tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
-                                          &tp->rx_ring_dma);
-       if (tp->tx_bufs == NULL || tp->rx_ring == NULL) {
-               free_irq(dev->irq, dev);
-
-               if (tp->tx_bufs)
-                       pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
-                                           tp->tx_bufs, tp->tx_bufs_dma);
-               if (tp->rx_ring)
-                       pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
-                                           tp->rx_ring, tp->rx_ring_dma);
-
-               DPRINTK("EXIT, returning -ENOMEM\n");
-               return -ENOMEM;
-
-       }
-
-       tp->full_duplex = tp->duplex_lock;
-       tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
-
-       netdrv_init_ring(dev);
-       netdrv_hw_start(dev);
-
-       netdev_dbg(dev, "ioaddr %#llx IRQ %d GP Pins %02x %s-duplex\n",
-                  (unsigned long long)pci_resource_start(tp->pci_dev, 1),
-                  dev->irq, NETDRV_R8(MediaStatus),
-                  tp->full_duplex ? "full" : "half");
-
-       /* Set the timer to switch to check for link beat and perhaps switch
-          to an alternate media type. */
-       init_timer(&tp->timer);
-       tp->timer.expires = jiffies + 3 * HZ;
-       tp->timer.data = (unsigned long) dev;
-       tp->timer.function = netdrv_timer;
-       add_timer(&tp->timer);
-
-       DPRINTK("EXIT, returning 0\n");
-       return 0;
-}
-
-
-/* Start the hardware at open or resume. */
-static void netdrv_hw_start(struct net_device *dev)
-{
-       struct netdrv_private *tp = netdev_priv(dev);
-       void *ioaddr = tp->mmio_addr;
-       u32 i;
-
-       DPRINTK("ENTER\n");
-
-       /* Soft reset the chip. */
-       NETDRV_W8(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear) | CmdReset);
-       udelay(100);
-
-       /* Check that the chip has finished the reset. */
-       for (i = 1000; i > 0; i--)
-               if ((NETDRV_R8(ChipCmd) & CmdReset) == 0)
-                       break;
-
-       /* Restore our idea of the MAC address. */
-       NETDRV_W32_F(MAC0 + 0, cpu_to_le32(*(u32 *)(dev->dev_addr + 0)));
-       NETDRV_W32_F(MAC0 + 4, cpu_to_le32(*(u32 *)(dev->dev_addr + 4)));
-
-       /* Must enable Tx/Rx before setting transfer thresholds! */
-       NETDRV_W8_F(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear) |
-                   CmdRxEnb | CmdTxEnb);
-
-       i = netdrv_rx_config |
-               (NETDRV_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
-       NETDRV_W32_F(RxConfig, i);
-
-       /* Check this value: the documentation for IFG contradicts ifself. */
-       NETDRV_W32(TxConfig, (TX_DMA_BURST << TxDMAShift));
-
-       /* unlock Config[01234] and BMCR register writes */
-       NETDRV_W8_F(Cfg9346, Cfg9346_Unlock);
-       udelay(10);
-
-       tp->cur_rx = 0;
-
-       /* Lock Config[01234] and BMCR register writes */
-       NETDRV_W8_F(Cfg9346, Cfg9346_Lock);
-       udelay(10);
-
-       /* init Rx ring buffer DMA address */
-       NETDRV_W32_F(RxBuf, tp->rx_ring_dma);
-
-       /* init Tx buffer DMA addresses */
-       for (i = 0; i < NUM_TX_DESC; i++)
-               NETDRV_W32_F(TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs));
-
-       NETDRV_W32_F(RxMissed, 0);
-
-       netdrv_set_rx_mode(dev);
-
-       /* no early-rx interrupts */
-       NETDRV_W16(MultiIntr, NETDRV_R16(MultiIntr) & MultiIntrClear);
-
-       /* make sure RxTx has started */
-       NETDRV_W8_F(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear) |
-                   CmdRxEnb | CmdTxEnb);
-
-       /* Enable all known interrupts by setting the interrupt mask. */
-       NETDRV_W16_F(IntrMask, netdrv_intr_mask);
-
-       netif_start_queue(dev);
-
-       DPRINTK("EXIT\n");
-}
-
-
-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void netdrv_init_ring(struct net_device *dev)
-{
-       struct netdrv_private *tp = netdev_priv(dev);
-       int i;
-
-       DPRINTK("ENTER\n");
-
-       tp->cur_rx = 0;
-       atomic_set(&tp->cur_tx, 0);
-       atomic_set(&tp->dirty_tx, 0);
-
-       for (i = 0; i < NUM_TX_DESC; i++) {
-               tp->tx_info[i].skb = NULL;
-               tp->tx_info[i].mapping = 0;
-               tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];
-       }
-
-       DPRINTK("EXIT\n");
-}
-
-
-static void netdrv_timer(unsigned long data)
-{
-       struct net_device *dev = (struct net_device *) data;
-       struct netdrv_private *tp = netdev_priv(dev);
-       void *ioaddr = tp->mmio_addr;
-       int next_tick = 60 * HZ;
-       int mii_lpa;
-
-       mii_lpa = mdio_read(dev, tp->phys[0], MII_LPA);
-
-       if (!tp->duplex_lock && mii_lpa != 0xffff) {
-               int duplex = ((mii_lpa & LPA_100FULL) ||
-                            (mii_lpa & 0x01C0) == 0x0040);
-               if (tp->full_duplex != duplex) {
-                       tp->full_duplex = duplex;
-                       netdev_info(dev, "Setting %s-duplex based on MII #%d link partner ability of %04x\n",
-                                   tp->full_duplex ? "full" : "half",
-                                   tp->phys[0], mii_lpa);
-                       NETDRV_W8(Cfg9346, Cfg9346_Unlock);
-                       NETDRV_W8(Config1, tp->full_duplex ? 0x60 : 0x20);
-                       NETDRV_W8(Cfg9346, Cfg9346_Lock);
-               }
-       }
-
-       netdev_dbg(dev, "Media selection tick, Link partner %04x\n",
-                  NETDRV_R16(NWayLPAR));
-       netdev_dbg(dev, "Other registers are IntMask %04x IntStatus %04x RxStatus %04lx\n",
-                  NETDRV_R16(IntrMask),
-                  NETDRV_R16(IntrStatus),
-                  NETDRV_R32(RxEarlyStatus));
-       netdev_dbg(dev, "Chip config %02x %02x\n",
-                  NETDRV_R8(Config0), NETDRV_R8(Config1));
-
-       tp->timer.expires = jiffies + next_tick;
-       add_timer(&tp->timer);
-}
-
-
-static void netdrv_tx_clear(struct net_device *dev)
-{
-       int i;
-       struct netdrv_private *tp = netdev_priv(dev);
-
-       atomic_set(&tp->cur_tx, 0);
-       atomic_set(&tp->dirty_tx, 0);
-
-       /* Dump the unsent Tx packets. */
-       for (i = 0; i < NUM_TX_DESC; i++) {
-               struct ring_info *rp = &tp->tx_info[i];
-               if (rp->mapping != 0) {
-                       pci_unmap_single(tp->pci_dev, rp->mapping,
-                                        rp->skb->len, PCI_DMA_TODEVICE);
-                       rp->mapping = 0;
-               }
-               if (rp->skb) {
-                       dev_kfree_skb(rp->skb);
-                       rp->skb = NULL;
-                       dev->stats.tx_dropped++;
-               }
-       }
-}
-
-
-static void netdrv_tx_timeout(struct net_device *dev)
-{
-       struct netdrv_private *tp = netdev_priv(dev);
-       void *ioaddr = tp->mmio_addr;
-       int i;
-       u8 tmp8;
-       unsigned long flags;
-
-       netdev_dbg(dev, "Transmit timeout, status %02x %04x media %02x\n",
-                  NETDRV_R8(ChipCmd),
-                  NETDRV_R16(IntrStatus),
-                  NETDRV_R8(MediaStatus));
-
-       /* disable Tx ASAP, if not already */
-       tmp8 = NETDRV_R8(ChipCmd);
-       if (tmp8 & CmdTxEnb)
-               NETDRV_W8(ChipCmd, tmp8 & ~CmdTxEnb);
-
-       /* Disable interrupts by clearing the interrupt mask. */
-       NETDRV_W16(IntrMask, 0x0000);
-
-       /* Emit info to figure out what went wrong. */
-       netdev_dbg(dev, "Tx queue start entry %d dirty entry %d\n",
-                  atomic_read(&tp->cur_tx),
-                  atomic_read(&tp->dirty_tx));
-       for (i = 0; i < NUM_TX_DESC; i++)
-               netdev_dbg(dev, "Tx descriptor %d is %08lx%s\n",
-                          i, NETDRV_R32(TxStatus0 + (i * 4)),
-                          i == atomic_read(&tp->dirty_tx) % NUM_TX_DESC ?
-                          "(queue head)" : "");
-
-       /* Stop a shared interrupt from scavenging while we are. */
-       spin_lock_irqsave(&tp->lock, flags);
-
-       netdrv_tx_clear(dev);
-
-       spin_unlock_irqrestore(&tp->lock, flags);
-
-       /* ...and finally, reset everything */
-       netdrv_hw_start(dev);
-
-       netif_wake_queue(dev);
-}
-
-
-
-static int netdrv_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-       struct netdrv_private *tp = netdev_priv(dev);
-       void *ioaddr = tp->mmio_addr;
-       int entry;
-
-       /* Calculate the next Tx descriptor entry. */
-       entry = atomic_read(&tp->cur_tx) % NUM_TX_DESC;
-
-       assert(tp->tx_info[entry].skb == NULL);
-       assert(tp->tx_info[entry].mapping == 0);
-
-       tp->tx_info[entry].skb = skb;
-       /* tp->tx_info[entry].mapping = 0; */
-       skb_copy_from_linear_data(skb, tp->tx_buf[entry], skb->len);
-
-       /* Note: the chip doesn't have auto-pad! */
-       NETDRV_W32(TxStatus0 + (entry * sizeof(u32)),
-                  tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
-
-       atomic_inc(&tp->cur_tx);
-       if ((atomic_read(&tp->cur_tx) - atomic_read(&tp->dirty_tx)) >= NUM_TX_DESC)
-               netif_stop_queue(dev);
-
-       netdev_dbg(dev, "Queued Tx packet at %p size %u to slot %d\n",
-                  skb->data, skb->len, entry);
-
-       return NETDEV_TX_OK;
-}
-
-
-static void netdrv_tx_interrupt(struct net_device *dev,
-                               struct netdrv_private *tp,
-                               void *ioaddr)
-{
-       int cur_tx, dirty_tx, tx_left;
-
-       assert(dev != NULL);
-       assert(tp != NULL);
-       assert(ioaddr != NULL);
-
-       dirty_tx = atomic_read(&tp->dirty_tx);
-
-       cur_tx = atomic_read(&tp->cur_tx);
-       tx_left = cur_tx - dirty_tx;
-       while (tx_left > 0) {
-               int entry = dirty_tx % NUM_TX_DESC;
-               int txstatus;
-
-               txstatus = NETDRV_R32(TxStatus0 + (entry * sizeof(u32)));
-
-               if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted)))
-                       break;  /* It still hasn't been Txed */
-
-               /* Note: TxCarrierLost is always asserted at 100mbps. */
-               if (txstatus & (TxOutOfWindow | TxAborted)) {
-                       /* There was an major error, log it. */
-                       netdev_dbg(dev, "Transmit error, Tx status %#08x\n",
-                                  txstatus);
-                       dev->stats.tx_errors++;
-                       if (txstatus & TxAborted) {
-                               dev->stats.tx_aborted_errors++;
-                               NETDRV_W32(TxConfig, TxClearAbt | (TX_DMA_BURST << TxDMAShift));
-                       }
-                       if (txstatus & TxCarrierLost)
-                               dev->stats.tx_carrier_errors++;
-                       if (txstatus & TxOutOfWindow)
-                               dev->stats.tx_window_errors++;
-               } else {
-                       if (txstatus & TxUnderrun) {
-                               /* Add 64 to the Tx FIFO threshold. */
-                               if (tp->tx_flag < 0x00300000)
-                                       tp->tx_flag += 0x00020000;
-                               dev->stats.tx_fifo_errors++;
-                       }
-                       dev->stats.collisions += (txstatus >> 24) & 15;
-                       dev->stats.tx_bytes += txstatus & 0x7ff;
-                       dev->stats.tx_packets++;
-               }
-
-               /* Free the original skb. */
-               if (tp->tx_info[entry].mapping != 0) {
-                       pci_unmap_single(tp->pci_dev,
-                                        tp->tx_info[entry].mapping,
-                                        tp->tx_info[entry].skb->len,
-                                        PCI_DMA_TODEVICE);
-                       tp->tx_info[entry].mapping = 0;
-               }
-               dev_kfree_skb_irq(tp->tx_info[entry].skb);
-               tp->tx_info[entry].skb = NULL;
-               dirty_tx++;
-               if (dirty_tx < 0) { /* handle signed int overflow */
-                       atomic_sub(cur_tx, &tp->cur_tx); /* XXX racy? */
-                       dirty_tx = cur_tx - tx_left + 1;
-               }
-               if (netif_queue_stopped(dev))
-                       netif_wake_queue(dev);
-
-               cur_tx = atomic_read(&tp->cur_tx);
-               tx_left = cur_tx - dirty_tx;
-
-       }
-
-#ifndef NETDRV_NDEBUG
-       if (atomic_read(&tp->cur_tx) - dirty_tx > NUM_TX_DESC) {
-               netdev_err(dev, "Out-of-sync dirty pointer, %d vs. %d\n",
-                          dirty_tx, atomic_read(&tp->cur_tx));
-               dirty_tx += NUM_TX_DESC;
-       }
-#endif /* NETDRV_NDEBUG */
-
-       atomic_set(&tp->dirty_tx, dirty_tx);
-}
-
-
-/* TODO: clean this up!  Rx reset need not be this intensive */
-static void netdrv_rx_err(u32 rx_status, struct net_device *dev,
-                         struct netdrv_private *tp, void *ioaddr)
-{
-       u8 tmp8;
-       int tmp_work = 1000;
-
-       netdev_dbg(dev, "Ethernet frame had errors, status %08x\n", rx_status);
-       if (rx_status & RxTooLong)
-               netdev_dbg(dev, "Oversized Ethernet frame, status %04x!\n",
-                          rx_status);
-               /* A.C.: The chip hangs here. */
-       dev->stats.rx_errors++;
-       if (rx_status & (RxBadSymbol | RxBadAlign))
-               dev->stats.rx_frame_errors++;
-       if (rx_status & (RxRunt | RxTooLong))
-               dev->stats.rx_length_errors++;
-       if (rx_status & RxCRCErr)
-               dev->stats.rx_crc_errors++;
-       /* Reset the receiver, based on RealTek recommendation.(Bug?) */
-       tp->cur_rx = 0;
-
-       /* disable receive */
-       tmp8 = NETDRV_R8(ChipCmd) & ChipCmdClear;
-       NETDRV_W8_F(ChipCmd, tmp8 | CmdTxEnb);
-
-       /* A.C.: Reset the multicast list. */
-       netdrv_set_rx_mode(dev);
-
-       /* XXX potentially temporary hack to
-        * restart hung receiver */
-       while (--tmp_work > 0) {
-               tmp8 = NETDRV_R8(ChipCmd);
-               if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb))
-                       break;
-               NETDRV_W8_F(ChipCmd,
-                           (tmp8 & ChipCmdClear) | CmdRxEnb | CmdTxEnb);
-       }
-
-       /* G.S.: Re-enable receiver */
-       /* XXX temporary hack to work around receiver hang */
-       netdrv_set_rx_mode(dev);
-
-       if (tmp_work <= 0)
-               netdev_warn(dev, "tx/rx enable wait too long\n");
-}
-
-
-/* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the
-   field alignments and semantics. */
-static void netdrv_rx_interrupt(struct net_device *dev,
-                               struct netdrv_private *tp, void *ioaddr)
-{
-       unsigned char *rx_ring;
-       u16 cur_rx;
-
-       assert(dev != NULL);
-       assert(tp != NULL);
-       assert(ioaddr != NULL);
-
-       rx_ring = tp->rx_ring;
-       cur_rx = tp->cur_rx;
-
-       netdev_dbg(dev, "In netdrv_rx(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n",
-                  cur_rx, NETDRV_R16(RxBufAddr),
-                  NETDRV_R16(RxBufPtr), NETDRV_R8(ChipCmd));
-
-       while ((NETDRV_R8(ChipCmd) & RxBufEmpty) == 0) {
-               int ring_offset = cur_rx % RX_BUF_LEN;
-               u32 rx_status;
-               unsigned int rx_size;
-               unsigned int pkt_size;
-               struct sk_buff *skb;
-
-               /* read size+status of next frame from DMA ring buffer */
-               rx_status = le32_to_cpu(*(u32 *)(rx_ring + ring_offset));
-               rx_size = rx_status >> 16;
-               pkt_size = rx_size - 4;
-
-               netdev_dbg(dev, "netdrv_rx() status %04x, size %04x, cur %04x\n",
-                          rx_status, rx_size, cur_rx);
-#if defined(NETDRV_DEBUG) && (NETDRV_DEBUG > 2)
-               print_hex_dump_bytes("Frame contents: ", HEX_DUMP_OFFSET,
-                                    &rx_ring[ring_offset], 70);
-#endif
-
-               /* If Rx err or invalid rx_size/rx_status received
-                *(which happens if we get lost in the ring),
-                * Rx process gets reset, so we abort any further
-                * Rx processing.
-                */
-               if ((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
-                   (!(rx_status & RxStatusOK))) {
-                       netdrv_rx_err(rx_status, dev, tp, ioaddr);
-                       return;
-               }
-
-               /* Malloc up new buffer, compatible with net-2e. */
-               /* Omit the four octet CRC from the length. */
-
-               /* TODO: consider allocating skb's outside of
-                * interrupt context, both to speed interrupt processing,
-                * and also to reduce the chances of having to
-                * drop packets here under memory pressure.
-                */
-
-               skb = dev_alloc_skb(pkt_size + 2);
-               if (skb) {
-                       skb_reserve(skb, 2);    /* 16 byte align the IP fields. */
-
-                       skb_copy_to_linear_data(skb, &rx_ring[ring_offset + 4], pkt_size);
-                       skb_put(skb, pkt_size);
-
-                       skb->protocol = eth_type_trans(skb, dev);
-                       netif_rx(skb);
-                       dev->stats.rx_bytes += pkt_size;
-                       dev->stats.rx_packets++;
-               } else {
-                       netdev_warn(dev, "Memory squeeze, dropping packet\n");
-                       dev->stats.rx_dropped++;
-               }
-
-               cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
-               NETDRV_W16_F(RxBufPtr, cur_rx - 16);
-       }
-
-       netdev_dbg(dev, "Done netdrv_rx(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n",
-                  cur_rx, NETDRV_R16(RxBufAddr),
-                  NETDRV_R16(RxBufPtr), NETDRV_R8(ChipCmd));
-
-       tp->cur_rx = cur_rx;
-}
-
-
-static void netdrv_weird_interrupt(struct net_device *dev,
-                                  struct netdrv_private *tp,
-                                  void *ioaddr,
-                                  int status, int link_changed)
-{
-       netdev_printk(KERN_DEBUG, dev, "Abnormal interrupt, status %08x\n",
-                     status);
-
-       assert(dev != NULL);
-       assert(tp != NULL);
-       assert(ioaddr != NULL);
-
-       /* Update the error count. */
-       dev->stats.rx_missed_errors += NETDRV_R32(RxMissed);
-       NETDRV_W32(RxMissed, 0);
-
-       if ((status & RxUnderrun) && link_changed &&
-           (tp->drv_flags & HAS_LNK_CHNG)) {
-               /* Really link-change on new chips. */
-               int lpar = NETDRV_R16(NWayLPAR);
-               int duplex = ((lpar & 0x0100) || (lpar & 0x01C0) == 0x0040 ||
-                            tp->duplex_lock);
-               if (tp->full_duplex != duplex) {
-                       tp->full_duplex = duplex;
-                       NETDRV_W8(Cfg9346, Cfg9346_Unlock);
-                       NETDRV_W8(Config1, tp->full_duplex ? 0x60 : 0x20);
-                       NETDRV_W8(Cfg9346, Cfg9346_Lock);
-               }
-               status &= ~RxUnderrun;
-       }
-
-       /* XXX along with netdrv_rx_err, are we double-counting errors? */
-       if (status & (RxUnderrun | RxOverflow | RxErr | RxFIFOOver))
-               dev->stats.rx_errors++;
-
-       if (status & (PCSTimeout))
-               dev->stats.rx_length_errors++;
-       if (status & (RxUnderrun | RxFIFOOver))
-               dev->stats.rx_fifo_errors++;
-       if (status & RxOverflow) {
-               dev->stats.rx_over_errors++;
-               tp->cur_rx = NETDRV_R16(RxBufAddr) % RX_BUF_LEN;
-               NETDRV_W16_F(RxBufPtr, tp->cur_rx - 16);
-       }
-       if (status & PCIErr) {
-               u16 pci_cmd_status;
-               pci_read_config_word(tp->pci_dev, PCI_STATUS, &pci_cmd_status);
-
-               netdev_err(dev, "PCI Bus error %04x\n", pci_cmd_status);
-       }
-}
-
-
-/* The interrupt handler does all of the Rx thread work and cleans up
-   after the Tx thread. */
-static irqreturn_t netdrv_interrupt(int irq, void *dev_instance)
-{
-       struct net_device *dev = (struct net_device *) dev_instance;
-       struct netdrv_private *tp = netdev_priv(dev);
-       int boguscnt = max_interrupt_work;
-       void *ioaddr = tp->mmio_addr;
-       int status = 0, link_changed = 0; /* avoid bogus "uninit" warning */
-       int handled = 0;
-
-       spin_lock(&tp->lock);
-
-       do {
-               status = NETDRV_R16(IntrStatus);
-
-               /* h/w no longer present(hotplug?) or major error, bail */
-               if (status == 0xFFFF)
-                       break;
-
-               handled = 1;
-               /* Acknowledge all of the current interrupt sources ASAP */
-               NETDRV_W16_F(IntrStatus, status);
-
-               netdev_dbg(dev, "interrupt  status=%#04x new intstat=%#04x\n",
-                          status, NETDRV_R16(IntrStatus));
-
-               if ((status &
-                    (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
-                     RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0)
-                       break;
-
-               /* Check uncommon events with one test. */
-               if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
-                            RxFIFOOver | TxErr | RxErr))
-                       netdrv_weird_interrupt(dev, tp, ioaddr,
-                                              status, link_changed);
-
-               if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver))     /* Rx interrupt */
-                       netdrv_rx_interrupt(dev, tp, ioaddr);
-
-               if (status & (TxOK | TxErr))
-                       netdrv_tx_interrupt(dev, tp, ioaddr);
-
-               boguscnt--;
-       } while (boguscnt > 0);
-
-       if (boguscnt <= 0) {
-               netdev_warn(dev, "Too much work at interrupt, IntrStatus=%#04x\n",
-                           status);
-
-               /* Clear all interrupt sources. */
-               NETDRV_W16(IntrStatus, 0xffff);
-       }
-
-       spin_unlock(&tp->lock);
-
-       netdev_dbg(dev, "exiting interrupt, intr_status=%#04x\n",
-                  NETDRV_R16(IntrStatus));
-       return IRQ_RETVAL(handled);
-}
-
-
-static int netdrv_close(struct net_device *dev)
-{
-       struct netdrv_private *tp = netdev_priv(dev);
-       void *ioaddr = tp->mmio_addr;
-       unsigned long flags;
-
-       DPRINTK("ENTER\n");
-
-       netif_stop_queue(dev);
-
-       netdev_dbg(dev, "Shutting down ethercard, status was %#04x\n",
-                  NETDRV_R16(IntrStatus));
-
-       del_timer_sync(&tp->timer);
-
-       spin_lock_irqsave(&tp->lock, flags);
-
-       /* Stop the chip's Tx and Rx DMA processes. */
-       NETDRV_W8(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear));
-
-       /* Disable interrupts by clearing the interrupt mask. */
-       NETDRV_W16(IntrMask, 0x0000);
-
-       /* Update the error counts. */
-       dev->stats.rx_missed_errors += NETDRV_R32(RxMissed);
-       NETDRV_W32(RxMissed, 0);
-
-       spin_unlock_irqrestore(&tp->lock, flags);
-
-       free_irq(dev->irq, dev);
-
-       netdrv_tx_clear(dev);
-
-       pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
-                           tp->rx_ring, tp->rx_ring_dma);
-       pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
-                           tp->tx_bufs, tp->tx_bufs_dma);
-       tp->rx_ring = NULL;
-       tp->tx_bufs = NULL;
-
-       /* Green! Put the chip in low-power mode. */
-       NETDRV_W8(Cfg9346, Cfg9346_Unlock);
-       NETDRV_W8(Config1, 0x03);
-       NETDRV_W8(Cfg9346, Cfg9346_Lock);
-
-       DPRINTK("EXIT\n");
-       return 0;
-}
-
-
-static int netdrv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-       struct netdrv_private *tp = netdev_priv(dev);
-       struct mii_ioctl_data *data = if_mii(rq);
-       unsigned long flags;
-       int rc = 0;
-
-       DPRINTK("ENTER\n");
-
-       switch (cmd) {
-       case SIOCGMIIPHY:               /* Get address of MII PHY in use. */
-               data->phy_id = tp->phys[0] & 0x3f;
-               /* Fall Through */
-
-       case SIOCGMIIREG:               /* Read MII PHY register. */
-               spin_lock_irqsave(&tp->lock, flags);
-               data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
-               spin_unlock_irqrestore(&tp->lock, flags);
-               break;
-
-       case SIOCSMIIREG:               /* Write MII PHY register. */
-               spin_lock_irqsave(&tp->lock, flags);
-               mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
-               spin_unlock_irqrestore(&tp->lock, flags);
-               break;
-
-       default:
-               rc = -EOPNOTSUPP;
-               break;
-       }
-
-       DPRINTK("EXIT, returning %d\n", rc);
-       return rc;
-}
-
-/* Set or clear the multicast filter for this adaptor.
-   This routine is not state sensitive and need not be SMP locked. */
-
-static void netdrv_set_rx_mode(struct net_device *dev)
-{
-       struct netdrv_private *tp = netdev_priv(dev);
-       void *ioaddr = tp->mmio_addr;
-       u32 mc_filter[2];       /* Multicast hash filter */
-       int rx_mode;
-       u32 tmp;
-
-       DPRINTK("ENTER\n");
-
-       netdev_dbg(dev, "%s(%04x) done -- Rx config %08lx\n",
-                  __func__, dev->flags, NETDRV_R32(RxConfig));
-
-       /* Note: do not reorder, GCC is clever about common statements. */
-       if (dev->flags & IFF_PROMISC) {
-               rx_mode =
-                       AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
-                       AcceptAllPhys;
-               mc_filter[1] = mc_filter[0] = 0xffffffff;
-       } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
-                  (dev->flags & IFF_ALLMULTI)) {
-               /* Too many to filter perfectly -- accept all multicasts. */
-               rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
-               mc_filter[1] = mc_filter[0] = 0xffffffff;
-       } else {
-               struct netdev_hw_addr *ha;
-
-               rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
-               mc_filter[1] = mc_filter[0] = 0;
-               netdev_for_each_mc_addr(ha, dev) {
-                       int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
-
-                       mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
-               }
-       }
-
-       /* if called from irq handler, lock already acquired */
-       if (!in_irq())
-               spin_lock_irq(&tp->lock);
-
-       /* We can safely update without stopping the chip. */
-       tmp = netdrv_rx_config | rx_mode |
-               (NETDRV_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
-       NETDRV_W32_F(RxConfig, tmp);
-       NETDRV_W32_F(MAR0 + 0, mc_filter[0]);
-       NETDRV_W32_F(MAR0 + 4, mc_filter[1]);
-
-       if (!in_irq())
-               spin_unlock_irq(&tp->lock);
-
-       DPRINTK("EXIT\n");
-}
-
-
-#ifdef CONFIG_PM
-
-static int netdrv_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       struct net_device *dev = pci_get_drvdata(pdev);
-       struct netdrv_private *tp = netdev_priv(dev);
-       void *ioaddr = tp->mmio_addr;
-       unsigned long flags;
-
-       if (!netif_running(dev))
-               return 0;
-       netif_device_detach(dev);
-
-       spin_lock_irqsave(&tp->lock, flags);
-
-       /* Disable interrupts, stop Tx and Rx. */
-       NETDRV_W16(IntrMask, 0x0000);
-       NETDRV_W8(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear));
-
-       /* Update the error counts. */
-       dev->stats.rx_missed_errors += NETDRV_R32(RxMissed);
-       NETDRV_W32(RxMissed, 0);
-
-       spin_unlock_irqrestore(&tp->lock, flags);
-
-       pci_save_state(pdev);
-       pci_set_power_state(pdev, PCI_D3hot);
-
-       return 0;
-}
-
-
-static int netdrv_resume(struct pci_dev *pdev)
-{
-       struct net_device *dev = pci_get_drvdata(pdev);
-       /*struct netdrv_private *tp = netdev_priv(dev);*/
-
-       if (!netif_running(dev))
-               return 0;
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       netif_device_attach(dev);
-       netdrv_hw_start(dev);
-
-       return 0;
-}
-
-#endif /* CONFIG_PM */
-
-
-static struct pci_driver netdrv_pci_driver = {
-       .name           = MODNAME,
-       .id_table       = netdrv_pci_tbl,
-       .probe          = netdrv_init_one,
-       .remove         = __devexit_p(netdrv_remove_one),
-#ifdef CONFIG_PM
-       .suspend        = netdrv_suspend,
-       .resume         = netdrv_resume,
-#endif /* CONFIG_PM */
-};
-
-
-static int __init netdrv_init_module(void)
-{
-/* when a module, this is printed whether or not devices are found in probe */
-#ifdef MODULE
-       printk(version);
-#endif
-       return pci_register_driver(&netdrv_pci_driver);
-}
-
-
-static void __exit netdrv_cleanup_module(void)
-{
-       pci_unregister_driver(&netdrv_pci_driver);
-}
-
-
-module_init(netdrv_init_module);
-module_exit(netdrv_cleanup_module);
diff --git a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig
deleted file mode 100644 (file)
index 9b8f793..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-#
-# PCMCIA Network device configuration
-#
-
-menuconfig NET_PCMCIA
-       bool "PCMCIA network device support"
-       depends on PCMCIA
-       ---help---
-         Say Y if you would like to include support for any PCMCIA or CardBus
-         network adapters, then say Y to the driver for your particular card
-         below.  PCMCIA- or PC-cards are credit-card size devices often used
-         with laptops computers; CardBus is the newer and faster version of
-         PCMCIA.
-
-         To use your PC-cards, you will need supporting software from David
-         Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
-         for location).  You also want to check out the PCMCIA-HOWTO,
-         available from <http://www.tldp.org/docs.html#howto>.
-
-         If unsure, say N.
-
-if NET_PCMCIA && PCMCIA
-
-config PCMCIA_3C589
-       tristate "3Com 3c589 PCMCIA support"
-       help
-         Say Y here if you intend to attach a 3Com 3c589 or compatible PCMCIA
-         (PC-card) Ethernet card to your computer.
-
-         To compile this driver as a module, choose M here: the module will be
-         called 3c589_cs.  If unsure, say N.
-
-config PCMCIA_3C574
-       tristate "3Com 3c574 PCMCIA support"
-       help
-         Say Y here if you intend to attach a 3Com 3c574 or compatible PCMCIA
-         (PC-card) Fast Ethernet card to your computer.
-
-         To compile this driver as a module, choose M here: the module will be
-         called 3c574_cs.  If unsure, say N.
-
-config PCMCIA_FMVJ18X
-       tristate "Fujitsu FMV-J18x PCMCIA support"
-       select CRC32
-       help
-         Say Y here if you intend to attach a Fujitsu FMV-J18x or compatible
-         PCMCIA (PC-card) Ethernet card to your computer.
-
-         To compile this driver as a module, choose M here: the module will be
-         called fmvj18x_cs.  If unsure, say N.
-
-config PCMCIA_PCNET
-       tristate "NE2000 compatible PCMCIA support"
-       select CRC32
-       help
-         Say Y here if you intend to attach an NE2000 compatible PCMCIA
-         (PC-card) Ethernet or Fast Ethernet card to your computer.
-
-         To compile this driver as a module, choose M here: the module will be
-         called pcnet_cs.  If unsure, say N.
-
-config PCMCIA_NMCLAN
-       tristate "New Media PCMCIA support"
-       help
-         Say Y here if you intend to attach a New Media Ethernet or LiveWire
-         PCMCIA (PC-card) Ethernet card to your computer.
-
-         To compile this driver as a module, choose M here: the module will be
-         called nmclan_cs.  If unsure, say N.
-
-config PCMCIA_SMC91C92
-       tristate "SMC 91Cxx PCMCIA support"
-       select CRC32
-       select MII
-       help
-         Say Y here if you intend to attach an SMC 91Cxx compatible PCMCIA
-         (PC-card) Ethernet or Fast Ethernet card to your computer.
-
-         To compile this driver as a module, choose M here: the module will be
-         called smc91c92_cs.  If unsure, say N.
-
-config PCMCIA_XIRC2PS
-       tristate "Xircom 16-bit PCMCIA support"
-       help
-         Say Y here if you intend to attach a Xircom 16-bit PCMCIA (PC-card)
-         Ethernet or Fast Ethernet card to your computer.
-
-         To compile this driver as a module, choose M here: the module will be
-         called xirc2ps_cs.  If unsure, say N.
-
-config PCMCIA_AXNET
-       tristate "Asix AX88190 PCMCIA support"
-       ---help---
-         Say Y here if you intend to attach an Asix AX88190-based PCMCIA
-         (PC-card) Fast Ethernet card to your computer.  These cards are
-         nearly NE2000 compatible but need a separate driver due to a few
-         misfeatures.
-
-         To compile this driver as a module, choose M here: the module will be
-         called axnet_cs.  If unsure, say N.
-
-config ARCNET_COM20020_CS
-       tristate "COM20020 ARCnet PCMCIA support"
-       depends on ARCNET_COM20020
-       help
-         Say Y here if you intend to attach this type of ARCnet PCMCIA card
-         to your computer.
-
-         To compile this driver as a module, choose M here: the module will be
-         called com20020_cs.  If unsure, say N.
-
-config PCMCIA_IBMTR
-       tristate "IBM PCMCIA tokenring adapter support"
-       depends on IBMTR!=y && TR
-       help
-         Say Y here if you intend to attach this type of Token Ring PCMCIA
-         card to your computer. You then also need to say Y to "Token Ring
-         driver support".
-
-         To compile this driver as a module, choose M here: the module will be
-         called ibmtr_cs.
-
-endif # NET_PCMCIA
diff --git a/drivers/net/pcmcia/Makefile b/drivers/net/pcmcia/Makefile
deleted file mode 100644 (file)
index 87d2d99..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# Makefile for the Linux PCMCIA network device drivers.
-#
-
-# 16-bit client drivers
-obj-$(CONFIG_PCMCIA_3C589)     += 3c589_cs.o
-obj-$(CONFIG_PCMCIA_3C574)     += 3c574_cs.o
-obj-$(CONFIG_PCMCIA_FMVJ18X)   += fmvj18x_cs.o
-obj-$(CONFIG_PCMCIA_NMCLAN)    += nmclan_cs.o
-obj-$(CONFIG_PCMCIA_PCNET)     += pcnet_cs.o
-obj-$(CONFIG_PCMCIA_SMC91C92)  += smc91c92_cs.o
-obj-$(CONFIG_PCMCIA_XIRC2PS)   += xirc2ps_cs.o
-obj-$(CONFIG_ARCNET_COM20020_CS)+= com20020_cs.o
-obj-$(CONFIG_PCMCIA_AXNET)     += axnet_cs.o
-
-obj-$(CONFIG_PCMCIA_IBMTR)     += ibmtr_cs.o
index a702443..bb88e12 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 menuconfig PHYLIB
-       tristate "PHY Device support and infrastructure"
+       bool "PHY Device support and infrastructure"
        depends on !S390
        depends on NETDEVICES
        help
index 2cd8dc5..cb6e0b4 100644 (file)
@@ -34,8 +34,7 @@
 #define PAGESEL                0x13
 #define LAYER4         0x02
 #define LAYER2         0x01
-#define MAX_RXTS       4
-#define MAX_TXTS       4
+#define MAX_RXTS       64
 #define N_EXT_TS       1
 #define PSF_PTPVER     2
 #define PSF_EVNT       0x4000
@@ -218,7 +217,7 @@ static void phy2rxts(struct phy_rxts *p, struct rxts *rxts)
        rxts->seqid = p->seqid;
        rxts->msgtype = (p->msgtype >> 12) & 0xf;
        rxts->hash = p->msgtype & 0x0fff;
-       rxts->tmo = jiffies + HZ;
+       rxts->tmo = jiffies + 2;
 }
 
 static u64 phy2txts(struct phy_txts *p)
diff --git a/drivers/net/plip/Kconfig b/drivers/net/plip/Kconfig
new file mode 100644 (file)
index 0000000..80c4a33
--- /dev/null
@@ -0,0 +1,38 @@
+#
+# Parallel Line Internet Protocol (PLIP) network device configuration
+#
+
+config PLIP
+       tristate "PLIP (parallel port) support"
+       depends on PARPORT
+       ---help---
+         PLIP (Parallel Line Internet Protocol) is used to create a
+         reasonably fast mini network consisting of two (or, rarely, more)
+         local machines.  A PLIP link from a Linux box is a popular means to
+         install a Linux distribution on a machine which doesn't have a
+         CD-ROM drive (a minimal system has to be transferred with floppies
+         first). The kernels on both machines need to have this PLIP option
+         enabled for this to work.
+
+         The PLIP driver has two modes, mode 0 and mode 1.  The parallel
+         ports (the connectors at the computers with 25 holes) are connected
+         with "null printer" or "Turbo Laplink" cables which can transmit 4
+         bits at a time (mode 0) or with special PLIP cables, to be used on
+         bidirectional parallel ports only, which can transmit 8 bits at a
+         time (mode 1); you can find the wiring of these cables in
+         <file:Documentation/networking/PLIP.txt>.  The cables can be up to
+         15m long.  Mode 0 works also if one of the machines runs DOS/Windows
+         and has some PLIP software installed, e.g. the Crynwr PLIP packet
+         driver (<http://oak.oakland.edu/simtel.net/msdos/pktdrvr-pre.html>)
+         and winsock or NCSA's telnet.
+
+         If you want to use PLIP, say Y and read the PLIP mini-HOWTO as well
+         as the NET-3-HOWTO, both available from
+         <http://www.tldp.org/docs.html#howto>.  Note that the PLIP
+         protocol has been changed and this PLIP driver won't work together
+         with the PLIP support in Linux versions 1.0.x.  This option enlarges
+         your kernel by about 8 KB.
+
+         To compile this driver as a module, choose M here. The module
+         will be called plip. If unsure, say Y or M, in case you buy
+         a laptop later.
diff --git a/drivers/net/plip/Makefile b/drivers/net/plip/Makefile
new file mode 100644 (file)
index 0000000..ed95879
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the PLIP network device drivers.
+#
+
+obj-$(CONFIG_PLIP) += plip.o
similarity index 100%
rename from drivers/net/plip.c
rename to drivers/net/plip/plip.c
diff --git a/drivers/net/ppp/Kconfig b/drivers/net/ppp/Kconfig
new file mode 100644 (file)
index 0000000..872df3e
--- /dev/null
@@ -0,0 +1,175 @@
+#
+# PPP network device configuration
+#
+
+config PPP
+       tristate "PPP (point-to-point protocol) support"
+       select SLHC
+       ---help---
+         PPP (Point to Point Protocol) is a newer and better SLIP.  It serves
+         the same purpose: sending Internet traffic over telephone (and other
+         serial) lines.  Ask your access provider if they support it, because
+         otherwise you can't use it; most Internet access providers these
+         days support PPP rather than SLIP.
+
+         To use PPP, you need an additional program called pppd as described
+         in the PPP-HOWTO, available at
+         <http://www.tldp.org/docs.html#howto>.  Make sure that you have
+         the version of pppd recommended in <file:Documentation/Changes>.
+         The PPP option enlarges your kernel by about 16 KB.
+
+         There are actually two versions of PPP: the traditional PPP for
+         asynchronous lines, such as regular analog phone lines, and
+         synchronous PPP which can be used over digital ISDN lines for
+         example.  If you want to use PPP over phone lines or other
+         asynchronous serial lines, you need to say Y (or M) here and also to
+         the next option, "PPP support for async serial ports".  For PPP over
+         synchronous lines, you should say Y (or M) here and to "Support
+         synchronous PPP", below.
+
+         If you said Y to "Version information on all symbols" above, then
+         you cannot compile the PPP driver into the kernel; you can then only
+         compile it as a module. To compile this driver as a module, choose M
+         here. The module will be called ppp_generic.
+
+if PPP
+
+config PPP_BSDCOMP
+       tristate "PPP BSD-Compress compression"
+       depends on PPP
+       ---help---
+         Support for the BSD-Compress compression method for PPP, which uses
+         the LZW compression method to compress each PPP packet before it is
+         sent over the wire. The machine at the other end of the PPP link
+         (usually your ISP) has to support the BSD-Compress compression
+         method as well for this to be useful. Even if they don't support it,
+         it is safe to say Y here.
+
+         The PPP Deflate compression method ("PPP Deflate compression",
+         above) is preferable to BSD-Compress, because it compresses better
+         and is patent-free.
+
+         Note that the BSD compression code will always be compiled as a
+         module; it is called bsd_comp and will show up in the directory
+         modules once you have said "make modules". If unsure, say N.
+
+config PPP_DEFLATE
+       tristate "PPP Deflate compression"
+       depends on PPP
+       select ZLIB_INFLATE
+       select ZLIB_DEFLATE
+       ---help---
+         Support for the Deflate compression method for PPP, which uses the
+         Deflate algorithm (the same algorithm that gzip uses) to compress
+         each PPP packet before it is sent over the wire.  The machine at the
+         other end of the PPP link (usually your ISP) has to support the
+         Deflate compression method as well for this to be useful.  Even if
+         they don't support it, it is safe to say Y here.
+
+         To compile this driver as a module, choose M here.
+
+config PPP_FILTER
+       bool "PPP filtering"
+       depends on PPP
+       ---help---
+         Say Y here if you want to be able to filter the packets passing over
+         PPP interfaces.  This allows you to control which packets count as
+         activity (i.e. which packets will reset the idle timer or bring up
+         a demand-dialed link) and which packets are to be dropped entirely.
+         You need to say Y here if you wish to use the pass-filter and
+         active-filter options to pppd.
+
+         If unsure, say N.
+
+config PPP_MPPE
+       tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)"
+       depends on PPP && EXPERIMENTAL
+       select CRYPTO
+       select CRYPTO_SHA1
+       select CRYPTO_ARC4
+       select CRYPTO_ECB
+       ---help---
+         Support for the MPPE Encryption protocol, as employed by the
+         Microsoft Point-to-Point Tunneling Protocol.
+
+         See http://pptpclient.sourceforge.net/ for information on
+         configuring PPTP clients and servers to utilize this method.
+
+config PPP_MULTILINK
+       bool "PPP multilink support (EXPERIMENTAL)"
+       depends on PPP && EXPERIMENTAL
+       ---help---
+         PPP multilink is a protocol (defined in RFC 1990) which allows you
+         to combine several (logical or physical) lines into one logical PPP
+         connection, so that you can utilize your full bandwidth.
+
+         This has to be supported at the other end as well and you need a
+         version of the pppd daemon which understands the multilink protocol.
+
+         If unsure, say N.
+
+config PPPOATM
+       tristate "PPP over ATM"
+       depends on ATM && PPP
+       ---help---
+         Support PPP (Point to Point Protocol) encapsulated in ATM frames.
+         This implementation does not yet comply with section 8 of RFC2364,
+         which can lead to bad results if the ATM peer loses state and
+         changes its encapsulation unilaterally.
+
+config PPPOE
+       tristate "PPP over Ethernet (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && PPP
+       ---help---
+         Support for PPP over Ethernet.
+
+         This driver requires the latest version of pppd from the CVS
+         repository at cvs.samba.org.  Alternatively, see the
+         RoaringPenguin package (<http://www.roaringpenguin.com/pppoe>)
+         which contains instruction on how to use this driver (under
+         the heading "Kernel mode PPPoE").
+
+config PPTP
+       tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX
+       ---help---
+         Support for PPP over IPv4.(Point-to-Point Tunneling Protocol)
+
+         This driver requires pppd plugin to work in client mode or
+         modified pptpd (poptop) to work in server mode.
+         See http://accel-pptp.sourceforge.net/ for information how to
+         utilize this module.
+
+config PPPOL2TP
+       tristate "PPP over L2TP (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && L2TP && PPP
+       ---help---
+         Support for PPP-over-L2TP socket family. L2TP is a protocol
+         used by ISPs and enterprises to tunnel PPP traffic over UDP
+         tunnels. L2TP is replacing PPTP for VPN uses.
+
+config PPP_ASYNC
+       tristate "PPP support for async serial ports"
+       depends on PPP
+       select CRC_CCITT
+       ---help---
+         Say Y (or M) here if you want to be able to use PPP over standard
+         asynchronous serial ports, such as COM1 or COM2 on a PC.  If you use
+         a modem (not a synchronous or ISDN modem) to contact your ISP, you
+         need this option.
+
+         To compile this driver as a module, choose M here.
+
+         If unsure, say Y.
+
+config PPP_SYNC_TTY
+       tristate "PPP support for sync tty ports"
+       depends on PPP
+       ---help---
+         Say Y (or M) here if you want to be able to use PPP over synchronous
+         (HDLC) tty devices, such as the SyncLink adapter. These devices
+         are often used for high-speed leased lines like T1/E1.
+
+         To compile this driver as a module, choose M here.
+
+endif # PPP
diff --git a/drivers/net/ppp/Makefile b/drivers/net/ppp/Makefile
new file mode 100644 (file)
index 0000000..a6b6297
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Makefile for the Linux PPP network device drivers.
+#
+
+obj-$(CONFIG_PPP) += ppp_generic.o
+obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
+obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
+obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
+obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
+obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
+obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
+obj-$(CONFIG_PPPOL2TP) += pppox.o
+obj-$(CONFIG_PPTP) += pppox.o pptp.o
similarity index 100%
rename from drivers/net/pppoe.c
rename to drivers/net/ppp/pppoe.c
similarity index 100%
rename from drivers/net/pppox.c
rename to drivers/net/ppp/pppox.c
similarity index 100%
rename from drivers/net/pptp.c
rename to drivers/net/ppp/pptp.c
diff --git a/drivers/net/slip/Kconfig b/drivers/net/slip/Kconfig
new file mode 100644 (file)
index 0000000..211b160
--- /dev/null
@@ -0,0 +1,79 @@
+#
+# SLIP network device configuration
+#
+
+config SLIP
+       tristate "SLIP (serial line) support"
+       ---help---
+         Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to
+         connect to your Internet service provider or to connect to some
+         other local Unix box or if you want to configure your Linux box as a
+         Slip/CSlip server for other people to dial in. SLIP (Serial Line
+         Internet Protocol) is a protocol used to send Internet traffic over
+         serial connections such as telephone lines or null modem cables;
+         nowadays, the protocol PPP is more commonly used for this same
+         purpose.
+
+         Normally, your access provider has to support SLIP in order for you
+         to be able to use it, but there is now a SLIP emulator called SLiRP
+         around (available from
+         <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
+         allows you to use SLIP over a regular dial up shell connection. If
+         you plan to use SLiRP, make sure to say Y to CSLIP, below. The
+         NET-3-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>, explains how to
+         configure SLIP. Note that you don't need this option if you just
+         want to run term (term is a program which gives you almost full
+         Internet connectivity if you have a regular dial up shell account on
+         some Internet connected Unix computer. Read
+         <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP
+         support will enlarge your kernel by about 4 KB. If unsure, say N.
+
+         To compile this driver as a module, choose M here. The module
+         will be called slip.
+
+config SLHC
+       tristate
+       ---help---
+         This option enables Van Jacobsen serial line header compression
+         routines.
+
+if SLIP
+
+config SLIP_COMPRESSED
+       bool "CSLIP compressed headers"
+       depends on SLIP
+       select SLHC
+       ---help---
+         This protocol is faster than SLIP because it uses compression on the
+         TCP/IP headers (not on the data itself), but it has to be supported
+         on both ends. Ask your access provider if you are not sure and
+         answer Y, just in case. You will still be able to use plain SLIP. If
+         you plan to use SLiRP, the SLIP emulator (available from
+         <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
+         allows you to use SLIP over a regular dial up shell connection, you
+         definitely want to say Y here. The NET-3-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>, explains how to configure
+         CSLIP. This won't enlarge your kernel.
+
+config SLIP_SMART
+       bool "Keepalive and linefill"
+       depends on SLIP
+       ---help---
+         Adds additional capabilities to the SLIP driver to support the
+         RELCOM line fill and keepalive monitoring. Ideal on poor quality
+         analogue lines.
+
+config SLIP_MODE_SLIP6
+       bool "Six bit SLIP encapsulation"
+       depends on SLIP
+       ---help---
+         Just occasionally you may need to run IP over hostile serial
+         networks that don't pass all control characters or are only seven
+         bit. Saying Y here adds an extra mode you can use with SLIP:
+         "slip6". In this mode, SLIP will only send normal ASCII symbols over
+         the serial device. Naturally, this has to be supported at the other
+         end of the link as well. It's good enough, for example, to run IP
+         over the async ports of a Camtec JNT Pad. If unsure, say N.
+
+endif # SLIP
diff --git a/drivers/net/slip/Makefile b/drivers/net/slip/Makefile
new file mode 100644 (file)
index 0000000..e3ebc59
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the SLIP network device drivers.
+#
+
+obj-$(CONFIG_SLIP) += slip.o
+obj-$(CONFIG_SLHC) += slhc.o
similarity index 100%
rename from drivers/net/slhc.c
rename to drivers/net/slip/slhc.c
similarity index 98%
rename from drivers/net/slip.c
rename to drivers/net/slip/slip.c
index f11b3f3..ba08341 100644 (file)
@@ -367,7 +367,7 @@ static void sl_bump(struct slip *sl)
        memcpy(skb_put(skb, count), sl->rbuff, count);
        skb_reset_mac_header(skb);
        skb->protocol = htons(ETH_P_IP);
-       netif_rx(skb);
+       netif_rx_ni(skb);
        dev->stats.rx_packets++;
 }
 
@@ -562,34 +562,33 @@ static struct rtnl_link_stats64 *
 sl_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
 {
        struct net_device_stats *devstats = &dev->stats;
-       unsigned long c_rx_dropped = 0;
 #ifdef SL_INCLUDE_CSLIP
-       unsigned long c_rx_fifo_errors = 0;
-       unsigned long c_tx_fifo_errors = 0;
-       unsigned long c_collisions = 0;
        struct slip *sl = netdev_priv(dev);
        struct slcompress *comp = sl->slcomp;
-
-       if (comp) {
-               c_rx_fifo_errors = comp->sls_i_compressed;
-               c_rx_dropped     = comp->sls_i_tossed;
-               c_tx_fifo_errors = comp->sls_o_compressed;
-               c_collisions     = comp->sls_o_misses;
-       }
-       stats->rx_fifo_errors = sl->rx_compressed + c_rx_fifo_errors;
-       stats->tx_fifo_errors = sl->tx_compressed + c_tx_fifo_errors;
-       stats->collisions     = sl->tx_misses + c_collisions;
 #endif
        stats->rx_packets     = devstats->rx_packets;
        stats->tx_packets     = devstats->tx_packets;
        stats->rx_bytes       = devstats->rx_bytes;
        stats->tx_bytes       = devstats->tx_bytes;
-       stats->rx_dropped     = devstats->rx_dropped + c_rx_dropped;
+       stats->rx_dropped     = devstats->rx_dropped;
        stats->tx_dropped     = devstats->tx_dropped;
        stats->tx_errors      = devstats->tx_errors;
        stats->rx_errors      = devstats->rx_errors;
        stats->rx_over_errors = devstats->rx_over_errors;
 
+#ifdef SL_INCLUDE_CSLIP
+       if (comp) {
+               /* Generic compressed statistics */
+               stats->rx_compressed   = comp->sls_i_compressed;
+               stats->tx_compressed   = comp->sls_o_compressed;
+
+               /* Are we really still needs this? */
+               stats->rx_fifo_errors += comp->sls_i_compressed;
+               stats->rx_dropped     += comp->sls_i_tossed;
+               stats->tx_fifo_errors += comp->sls_o_compressed;
+               stats->collisions     += comp->sls_o_misses;
+       }
+#endif
        return stats;
 }
 
similarity index 94%
rename from drivers/net/slip.h
rename to drivers/net/slip/slip.h
index aa0764c..67673cf 100644 (file)
@@ -65,15 +65,6 @@ struct slip {
   unsigned char                *xbuff;         /* transmitter buffer           */
   unsigned char         *xhead;         /* pointer to next byte to XMIT */
   int                   xleft;          /* bytes left in XMIT queue     */
-
-  /* SLIP interface statistics. */
-#ifdef SL_INCLUDE_CSLIP
-  unsigned long                tx_compressed;
-  unsigned long                rx_compressed;
-  unsigned long                tx_misses;
-#endif
-  /* Detailed SLIP statistics. */
-
   int                  mtu;            /* Our mtu (to spot changes!)   */
   int                   buffsize;       /* Max buffers sizes            */
 
index d16880d..58f13ad 100644 (file)
@@ -33,7 +33,7 @@
 #include <asm/prom.h>
 #endif
 
-#include "sungem_phy.h"
+#include <linux/sungem_phy.h>
 
 /* Link modes of the BCM5400 PHY */
 static const int phy_BCM5400_link_table[8][3] = {
@@ -1156,7 +1156,7 @@ static struct mii_phy_def* mii_phy_table[] = {
        NULL
 };
 
-int mii_phy_probe(struct mii_phy *phy, int mii_id)
+int sungem_phy_probe(struct mii_phy *phy, int mii_id)
 {
        int rc;
        u32 id;
@@ -1195,6 +1195,5 @@ fail:
        return -ENODEV;
 }
 
-EXPORT_SYMBOL(mii_phy_probe);
+EXPORT_SYMBOL(sungem_phy_probe);
 MODULE_LICENSE("GPL");
-
index b6162fe..ef9fdf3 100644 (file)
@@ -282,7 +282,7 @@ static const struct net_device_ops xl_netdev_ops = {
        .ndo_stop               = xl_close,
        .ndo_start_xmit         = xl_xmit,
        .ndo_change_mtu         = xl_change_mtu,
-       .ndo_set_multicast_list = xl_set_rx_mode,
+       .ndo_set_rx_mode        = xl_set_rx_mode,
        .ndo_set_mac_address    = xl_set_mac_address,
 };
  
index c4137b0..c7e0149 100644 (file)
@@ -4,9 +4,9 @@
 
 # So far, we only have PCI, ISA, and MCA token ring devices
 menuconfig TR
-       tristate "Token Ring driver support"
+       bool "Token Ring driver support"
        depends on NETDEVICES && !UML
-       depends on (PCI || ISA || MCA || CCW)
+       depends on (PCI || ISA || MCA || CCW || PCMCIA)
        select LLC
        help
          Token Ring is IBM's way of communication on a local network; the
@@ -20,6 +20,17 @@ menuconfig TR
 
 if TR
 
+config PCMCIA_IBMTR
+       tristate "IBM PCMCIA tokenring adapter support"
+       depends on IBMTR!=y && PCMCIA
+       ---help---
+         Say Y here if you intend to attach this type of Token Ring PCMCIA
+         card to your computer. You then also need to say Y to "Token Ring
+         driver support".
+
+         To compile this driver as a module, choose M here: the module will be
+         called ibmtr_cs.
+
 config IBMTR
        tristate "IBM Tropic chipset based adapter support"
        depends on ISA || MCA
index c88b0a5..f1be8d9 100644 (file)
@@ -2,14 +2,15 @@
 # Makefile for drivers/net/tokenring
 #
 
-obj-$(CONFIG_IBMTR)    += ibmtr.o
-obj-$(CONFIG_IBMOL)    += olympic.o
-obj-$(CONFIG_IBMLS)    += lanstreamer.o
-obj-$(CONFIG_TMS380TR)         += tms380tr.o
-obj-$(CONFIG_ABYSS)    += abyss.o
-obj-$(CONFIG_MADGEMC)  += madgemc.o
-obj-$(CONFIG_PROTEON)  += proteon.o
-obj-$(CONFIG_TMSPCI)   += tmspci.o
-obj-$(CONFIG_SKISA)    += skisa.o
-obj-$(CONFIG_SMCTR)    += smctr.o
+obj-$(CONFIG_PCMCIA_IBMTR)     += ibmtr_cs.o
+obj-$(CONFIG_IBMTR)    += ibmtr.o
+obj-$(CONFIG_IBMOL)    += olympic.o
+obj-$(CONFIG_IBMLS)    += lanstreamer.o
+obj-$(CONFIG_TMS380TR) += tms380tr.o
+obj-$(CONFIG_ABYSS)    += abyss.o
+obj-$(CONFIG_MADGEMC)  += madgemc.o
+obj-$(CONFIG_PROTEON)  += proteon.o
+obj-$(CONFIG_TMSPCI)   += tmspci.o
+obj-$(CONFIG_SKISA)    += skisa.o
+obj-$(CONFIG_SMCTR)    += smctr.o
 obj-$(CONFIG_3C359)    += 3c359.o
index e257a00..b5c8c18 100644 (file)
@@ -823,7 +823,7 @@ static const struct net_device_ops trdev_netdev_ops = {
        .ndo_open               = tok_open,
        .ndo_stop               = tok_close,
        .ndo_start_xmit         = tok_send_packet,
-       .ndo_set_multicast_list = tok_set_multicast_list,
+       .ndo_set_rx_mode        = tok_set_multicast_list,
        .ndo_change_mtu         = ibmtr_change_mtu,
 };
 
similarity index 99%
rename from drivers/net/pcmcia/ibmtr_cs.c
rename to drivers/net/tokenring/ibmtr_cs.c
index 6006d54..91b6846 100644 (file)
@@ -66,7 +66,7 @@
 #include <asm/system.h>
 
 #define PCMCIA
-#include "../tokenring/ibmtr.c"
+#include "ibmtr.c"
 
 
 /*====================================================================*/
index 9354ca9..8d71e0d 100644 (file)
@@ -231,7 +231,7 @@ static const struct net_device_ops streamer_netdev_ops = {
 #if STREAMER_IOCTL
        .ndo_do_ioctl           = streamer_ioctl,
 #endif
-       .ndo_set_multicast_list = streamer_set_rx_mode,
+       .ndo_set_rx_mode        = streamer_set_rx_mode,
        .ndo_set_mac_address    = streamer_set_mac_address,
 };
 
index e3855ae..fd8dce9 100644 (file)
@@ -201,7 +201,7 @@ static const struct net_device_ops olympic_netdev_ops = {
        .ndo_stop               = olympic_close,
        .ndo_start_xmit         = olympic_xmit,
        .ndo_change_mtu         = olympic_change_mtu,
-       .ndo_set_multicast_list = olympic_set_rx_mode,
+       .ndo_set_rx_mode        = olympic_set_rx_mode,
        .ndo_set_mac_address    = olympic_set_mac_address,
 };
 
index d9044ab..029846a 100644 (file)
@@ -3623,7 +3623,7 @@ static const struct net_device_ops smctr_netdev_ops = {
        .ndo_start_xmit    = smctr_send_packet,
        .ndo_tx_timeout    = smctr_timeout,
        .ndo_get_stats     = smctr_get_stats,
-       .ndo_set_multicast_list = smctr_set_multicast_list,
+       .ndo_set_rx_mode   = smctr_set_multicast_list,
 };
 
 static int __init smctr_probe1(struct net_device *dev, int ioaddr)
index 7930203..65e9cf3 100644 (file)
@@ -2289,7 +2289,7 @@ const struct net_device_ops tms380tr_netdev_ops = {
        .ndo_start_xmit         = tms380tr_send_packet,
        .ndo_tx_timeout         = tms380tr_timeout,
        .ndo_get_stats          = tms380tr_get_stats,
-       .ndo_set_multicast_list = tms380tr_set_multicast_list,
+       .ndo_set_rx_mode        = tms380tr_set_multicast_list,
        .ndo_set_mac_address    = tms380tr_set_mac_address,
 };
 EXPORT_SYMBOL(tms380tr_netdev_ops);
index 71f3d1a..7bea9c6 100644 (file)
@@ -496,7 +496,7 @@ static const struct net_device_ops tap_netdev_ops = {
        .ndo_start_xmit         = tun_net_xmit,
        .ndo_change_mtu         = tun_net_change_mtu,
        .ndo_fix_features       = tun_net_fix_features,
-       .ndo_set_multicast_list = tun_net_mclist,
+       .ndo_set_rx_mode        = tun_net_mclist,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index c5c4b4d..b843eed 100644 (file)
@@ -872,7 +872,7 @@ static const struct net_device_ops ax88172_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = asix_ioctl,
-       .ndo_set_multicast_list = ax88172_set_multicast,
+       .ndo_set_rx_mode        = ax88172_set_multicast,
 };
 
 static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
@@ -975,7 +975,7 @@ static const struct net_device_ops ax88772_netdev_ops = {
        .ndo_set_mac_address    = asix_set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = asix_ioctl,
-       .ndo_set_multicast_list = asix_set_multicast,
+       .ndo_set_rx_mode        = asix_set_multicast,
 };
 
 static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
@@ -1270,7 +1270,7 @@ static const struct net_device_ops ax88178_netdev_ops = {
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_set_mac_address    = asix_set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = asix_set_multicast,
+       .ndo_set_rx_mode        = asix_set_multicast,
        .ndo_do_ioctl           = asix_ioctl,
        .ndo_change_mtu         = ax88178_change_mtu,
 };
index 8056f8a..a68272c 100644 (file)
@@ -749,7 +749,7 @@ static const struct net_device_ops catc_netdev_ops = {
        .ndo_start_xmit         = catc_start_xmit,
 
        .ndo_tx_timeout         = catc_tx_timeout,
-       .ndo_set_multicast_list = catc_set_multicast_list,
+       .ndo_set_rx_mode        = catc_set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
index fd622a6..f06fb78 100644 (file)
@@ -53,7 +53,7 @@
 #include <linux/usb/usbnet.h>
 #include <linux/usb/cdc.h>
 
-#define        DRIVER_VERSION                          "01-June-2011"
+#define        DRIVER_VERSION                          "04-Aug-2011"
 
 /* CDC NCM subclass 3.2.1 */
 #define USB_CDC_NCM_NDP16_LENGTH_MIN           0x10
@@ -163,35 +163,8 @@ cdc_ncm_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
        usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info));
 }
 
-static int
-cdc_ncm_do_request(struct cdc_ncm_ctx *ctx, struct usb_cdc_notification *req,
-                  void *data, u16 flags, u16 *actlen, u16 timeout)
-{
-       int err;
-
-       err = usb_control_msg(ctx->udev, (req->bmRequestType & USB_DIR_IN) ?
-                               usb_rcvctrlpipe(ctx->udev, 0) :
-                               usb_sndctrlpipe(ctx->udev, 0),
-                               req->bNotificationType, req->bmRequestType,
-                               req->wValue,
-                               req->wIndex, data,
-                               req->wLength, timeout);
-
-       if (err < 0) {
-               if (actlen)
-                       *actlen = 0;
-               return err;
-       }
-
-       if (actlen)
-               *actlen = err;
-
-       return 0;
-}
-
 static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
 {
-       struct usb_cdc_notification req;
        u32 val;
        u8 flags;
        u8 iface_no;
@@ -200,14 +173,14 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
 
        iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber;
 
-       req.bmRequestType = USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE;
-       req.bNotificationType = USB_CDC_GET_NTB_PARAMETERS;
-       req.wValue = 0;
-       req.wIndex = cpu_to_le16(iface_no);
-       req.wLength = cpu_to_le16(sizeof(ctx->ncm_parm));
-
-       err = cdc_ncm_do_request(ctx, &req, &ctx->ncm_parm, 0, NULL, 1000);
-       if (err) {
+       err = usb_control_msg(ctx->udev,
+                               usb_rcvctrlpipe(ctx->udev, 0),
+                               USB_CDC_GET_NTB_PARAMETERS,
+                               USB_TYPE_CLASS | USB_DIR_IN
+                                | USB_RECIP_INTERFACE,
+                               0, iface_no, &ctx->ncm_parm,
+                               sizeof(ctx->ncm_parm), 10000);
+       if (err < 0) {
                pr_debug("failed GET_NTB_PARAMETERS\n");
                return 1;
        }
@@ -253,31 +226,43 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
 
        /* inform device about NTB input size changes */
        if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) {
-               req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT |
-                                                       USB_RECIP_INTERFACE;
-               req.bNotificationType = USB_CDC_SET_NTB_INPUT_SIZE;
-               req.wValue = 0;
-               req.wIndex = cpu_to_le16(iface_no);
 
                if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) {
-                       struct usb_cdc_ncm_ndp_input_size ndp_in_sz;
-
-                       req.wLength = 8;
-                       ndp_in_sz.dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
-                       ndp_in_sz.wNtbInMaxDatagrams =
-                                       cpu_to_le16(CDC_NCM_DPT_DATAGRAMS_MAX);
-                       ndp_in_sz.wReserved = 0;
-                       err = cdc_ncm_do_request(ctx, &req, &ndp_in_sz, 0, NULL,
-                                                                       1000);
-               } else {
-                       __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
+                       struct usb_cdc_ncm_ndp_input_size *ndp_in_sz;
 
-                       req.wLength = 4;
-                       err = cdc_ncm_do_request(ctx, &req, &dwNtbInMaxSize, 0,
-                                                               NULL, 1000);
-               }
+                       ndp_in_sz = kzalloc(sizeof(*ndp_in_sz), GFP_KERNEL);
+                       if (!ndp_in_sz) {
+                               err = -ENOMEM;
+                               goto size_err;
+                       }
 
-               if (err)
+                       err = usb_control_msg(ctx->udev,
+                                       usb_sndctrlpipe(ctx->udev, 0),
+                                       USB_CDC_SET_NTB_INPUT_SIZE,
+                                       USB_TYPE_CLASS | USB_DIR_OUT
+                                        | USB_RECIP_INTERFACE,
+                                       0, iface_no, ndp_in_sz, 8, 1000);
+                       kfree(ndp_in_sz);
+               } else {
+                       __le32 *dwNtbInMaxSize;
+                       dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize),
+                                       GFP_KERNEL);
+                       if (!dwNtbInMaxSize) {
+                               err = -ENOMEM;
+                               goto size_err;
+                       }
+                       *dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
+
+                       err = usb_control_msg(ctx->udev,
+                                       usb_sndctrlpipe(ctx->udev, 0),
+                                       USB_CDC_SET_NTB_INPUT_SIZE,
+                                       USB_TYPE_CLASS | USB_DIR_OUT
+                                        | USB_RECIP_INTERFACE,
+                                       0, iface_no, dwNtbInMaxSize, 4, 1000);
+                       kfree(dwNtbInMaxSize);
+               }
+size_err:
+               if (err < 0)
                        pr_debug("Setting NTB Input Size failed\n");
        }
 
@@ -332,29 +317,24 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
 
        /* set CRC Mode */
        if (flags & USB_CDC_NCM_NCAP_CRC_MODE) {
-               req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT |
-                                                       USB_RECIP_INTERFACE;
-               req.bNotificationType = USB_CDC_SET_CRC_MODE;
-               req.wValue = cpu_to_le16(USB_CDC_NCM_CRC_NOT_APPENDED);
-               req.wIndex = cpu_to_le16(iface_no);
-               req.wLength = 0;
-
-               err = cdc_ncm_do_request(ctx, &req, NULL, 0, NULL, 1000);
-               if (err)
+               err = usb_control_msg(ctx->udev, usb_sndctrlpipe(ctx->udev, 0),
+                               USB_CDC_SET_CRC_MODE,
+                               USB_TYPE_CLASS | USB_DIR_OUT
+                                | USB_RECIP_INTERFACE,
+                               USB_CDC_NCM_CRC_NOT_APPENDED,
+                               iface_no, NULL, 0, 1000);
+               if (err < 0)
                        pr_debug("Setting CRC mode off failed\n");
        }
 
        /* set NTB format, if both formats are supported */
        if (ntb_fmt_supported & USB_CDC_NCM_NTH32_SIGN) {
-               req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT |
-                                                       USB_RECIP_INTERFACE;
-               req.bNotificationType = USB_CDC_SET_NTB_FORMAT;
-               req.wValue = cpu_to_le16(USB_CDC_NCM_NTB16_FORMAT);
-               req.wIndex = cpu_to_le16(iface_no);
-               req.wLength = 0;
-
-               err = cdc_ncm_do_request(ctx, &req, NULL, 0, NULL, 1000);
-               if (err)
+               err = usb_control_msg(ctx->udev, usb_sndctrlpipe(ctx->udev, 0),
+                               USB_CDC_SET_NTB_FORMAT, USB_TYPE_CLASS
+                                | USB_DIR_OUT | USB_RECIP_INTERFACE,
+                               USB_CDC_NCM_NTB16_FORMAT,
+                               iface_no, NULL, 0, 1000);
+               if (err < 0)
                        pr_debug("Setting NTB format to 16-bit failed\n");
        }
 
@@ -362,23 +342,29 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
 
        /* set Max Datagram Size (MTU) */
        if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) {
-               __le16 max_datagram_size;
+               __le16 *max_datagram_size;
                u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
 
-               req.bmRequestType = USB_TYPE_CLASS | USB_DIR_IN |
-                                                       USB_RECIP_INTERFACE;
-               req.bNotificationType = USB_CDC_GET_MAX_DATAGRAM_SIZE;
-               req.wValue = 0;
-               req.wIndex = cpu_to_le16(iface_no);
-               req.wLength = cpu_to_le16(2);
+               max_datagram_size = kzalloc(sizeof(*max_datagram_size),
+                               GFP_KERNEL);
+               if (!max_datagram_size) {
+                       err = -ENOMEM;
+                       goto max_dgram_err;
+               }
 
-               err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, 0, NULL,
-                                                                       1000);
-               if (err) {
+               err = usb_control_msg(ctx->udev, usb_rcvctrlpipe(ctx->udev, 0),
+                               USB_CDC_GET_MAX_DATAGRAM_SIZE,
+                               USB_TYPE_CLASS | USB_DIR_IN
+                                | USB_RECIP_INTERFACE,
+                               0, iface_no, max_datagram_size,
+                               2, 1000);
+               if (err < 0) {
                        pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n",
                                                CDC_NCM_MIN_DATAGRAM_SIZE);
+                       kfree(max_datagram_size);
                } else {
-                       ctx->max_datagram_size = le16_to_cpu(max_datagram_size);
+                       ctx->max_datagram_size =
+                               le16_to_cpu(*max_datagram_size);
                        /* Check Eth descriptor value */
                        if (eth_max_sz < CDC_NCM_MAX_DATAGRAM_SIZE) {
                                if (ctx->max_datagram_size > eth_max_sz)
@@ -395,17 +381,17 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
                                        CDC_NCM_MIN_DATAGRAM_SIZE;
 
                        /* if value changed, update device */
-                       req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT |
-                                                       USB_RECIP_INTERFACE;
-                       req.bNotificationType = USB_CDC_SET_MAX_DATAGRAM_SIZE;
-                       req.wValue = 0;
-                       req.wIndex = cpu_to_le16(iface_no);
-                       req.wLength = 2;
-                       max_datagram_size = cpu_to_le16(ctx->max_datagram_size);
-
-                       err = cdc_ncm_do_request(ctx, &req, &max_datagram_size,
-                                                               0, NULL, 1000);
-                       if (err)
+                       err = usb_control_msg(ctx->udev,
+                                               usb_sndctrlpipe(ctx->udev, 0),
+                                               USB_CDC_SET_MAX_DATAGRAM_SIZE,
+                                               USB_TYPE_CLASS | USB_DIR_OUT
+                                                | USB_RECIP_INTERFACE,
+                                               0,
+                                               iface_no, max_datagram_size,
+                                               2, 1000);
+                       kfree(max_datagram_size);
+max_dgram_err:
+                       if (err < 0)
                                pr_debug("SET_MAX_DATAGRAM_SIZE failed\n");
                }
 
@@ -671,7 +657,7 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
        u32 rem;
        u32 offset;
        u32 last_offset;
-       u16 n = 0;
+       u16 n = 0, index;
        u8 ready2send = 0;
 
        /* if there is a remaining skb, it gets priority */
@@ -859,8 +845,8 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
                                        cpu_to_le16(sizeof(ctx->tx_ncm.nth16));
        ctx->tx_ncm.nth16.wSequence = cpu_to_le16(ctx->tx_seq);
        ctx->tx_ncm.nth16.wBlockLength = cpu_to_le16(last_offset);
-       ctx->tx_ncm.nth16.wNdpIndex = ALIGN(sizeof(struct usb_cdc_ncm_nth16),
-                                                       ctx->tx_ndp_modulus);
+       index = ALIGN(sizeof(struct usb_cdc_ncm_nth16), ctx->tx_ndp_modulus);
+       ctx->tx_ncm.nth16.wNdpIndex = cpu_to_le16(index);
 
        memcpy(skb_out->data, &(ctx->tx_ncm.nth16), sizeof(ctx->tx_ncm.nth16));
        ctx->tx_seq++;
@@ -873,12 +859,11 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
        ctx->tx_ncm.ndp16.wLength = cpu_to_le16(rem);
        ctx->tx_ncm.ndp16.wNextNdpIndex = 0; /* reserved */
 
-       memcpy(((u8 *)skb_out->data) + ctx->tx_ncm.nth16.wNdpIndex,
+       memcpy(((u8 *)skb_out->data) + index,
                                                &(ctx->tx_ncm.ndp16),
                                                sizeof(ctx->tx_ncm.ndp16));
 
-       memcpy(((u8 *)skb_out->data) + ctx->tx_ncm.nth16.wNdpIndex +
-                                       sizeof(ctx->tx_ncm.ndp16),
+       memcpy(((u8 *)skb_out->data) + index + sizeof(ctx->tx_ncm.ndp16),
                                        &(ctx->tx_ncm.dpe16),
                                        (ctx->tx_curr_frame_num + 1) *
                                        sizeof(struct usb_cdc_ncm_dpe16));
index 1d93133..fbc0e4d 100644 (file)
@@ -428,7 +428,7 @@ static const struct net_device_ops dm9601_netdev_ops = {
        .ndo_change_mtu         = usbnet_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = dm9601_ioctl,
-       .ndo_set_multicast_list = dm9601_set_multicast,
+       .ndo_set_rx_mode        = dm9601_set_multicast,
        .ndo_set_mac_address    = dm9601_set_mac_address,
 };
 
index be02a25..131ac6c 100644 (file)
@@ -193,7 +193,7 @@ static const struct net_device_ops int51x1_netdev_ops = {
        .ndo_change_mtu         = usbnet_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = int51x1_set_multicast,
+       .ndo_set_rx_mode        = int51x1_set_multicast,
 };
 
 static int int51x1_bind(struct usbnet *dev, struct usb_interface *intf)
index ad0298f..582ca2d 100644 (file)
@@ -985,7 +985,7 @@ static const struct net_device_ops kaweth_netdev_ops = {
        .ndo_stop =                     kaweth_close,
        .ndo_start_xmit =               kaweth_start_xmit,
        .ndo_tx_timeout =               kaweth_tx_timeout,
-       .ndo_set_multicast_list =       kaweth_set_rx_mode,
+       .ndo_set_rx_mode =              kaweth_set_rx_mode,
        .ndo_get_stats =                kaweth_netdev_stats,
        .ndo_change_mtu =               eth_change_mtu,
        .ndo_set_mac_address =          eth_mac_addr,
index 1d83ccf..1e72219 100644 (file)
@@ -89,6 +89,8 @@ static int vl600_bind(struct usbnet *dev, struct usb_interface *intf)
         * addresses have no meaning, the destination and the source of every
         * packet depend only on whether it is on the IN or OUT endpoint.  */
        dev->net->flags |= IFF_NOARP;
+       /* IPv6 NDP relies on multicast.  Enable it by default. */
+       dev->net->flags |= IFF_MULTICAST;
 
        return ret;
 }
@@ -200,6 +202,14 @@ static int vl600_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                } else {
                        memset(ethhdr->h_source, 0, ETH_ALEN);
                        memcpy(ethhdr->h_dest, dev->net->dev_addr, ETH_ALEN);
+
+                       /* Inbound IPv6 packets have an IPv4 ethertype (0x800)
+                        * for some reason.  Peek at the L3 header to check
+                        * for IPv6 packets, and set the ethertype to IPv6
+                        * (0x86dd) so Linux can understand it.
+                        */
+                       if ((buf->data[sizeof(*ethhdr)] & 0xf0) == 0x60)
+                               ethhdr->h_proto = __constant_htons(ETH_P_IPV6);
                }
 
                if (count) {
@@ -297,6 +307,15 @@ encapsulate:
        if (skb->len < full_len) /* Pad */
                skb_put(skb, full_len - skb->len);
 
+       /* The VL600 wants IPv6 packets to have an IPv4 ethertype
+        * Check if this is an IPv6 packet, and set the ethertype
+        * to 0x800
+        */
+       if ((skb->data[sizeof(struct vl600_pkt_hdr *) + 0x22] & 0xf0) == 0x60) {
+               skb->data[sizeof(struct vl600_pkt_hdr *) + 0x20] = 0x08;
+               skb->data[sizeof(struct vl600_pkt_hdr *) + 0x21] = 0;
+       }
+
        return skb;
 }
 
index 2b79139..db2cb74 100644 (file)
@@ -553,7 +553,7 @@ static const struct net_device_ops mcs7830_netdev_ops = {
        .ndo_change_mtu         = usbnet_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = mcs7830_ioctl,
-       .ndo_set_multicast_list = mcs7830_set_multicast,
+       .ndo_set_rx_mode        = mcs7830_set_multicast,
        .ndo_set_mac_address    = mcs7830_set_mac_address,
 };
 
index ef36676..769f509 100644 (file)
@@ -1476,7 +1476,7 @@ static const struct net_device_ops pegasus_netdev_ops = {
        .ndo_stop =                     pegasus_close,
        .ndo_do_ioctl =                 pegasus_ioctl,
        .ndo_start_xmit =               pegasus_start_xmit,
-       .ndo_set_multicast_list =       pegasus_set_multicast,
+       .ndo_set_rx_mode =              pegasus_set_multicast,
        .ndo_get_stats =                pegasus_netdev_stats,
        .ndo_tx_timeout =               pegasus_tx_timeout,
        .ndo_change_mtu =               eth_change_mtu,
index 041fb7d..b00d692 100644 (file)
@@ -899,7 +899,7 @@ static const struct net_device_ops rtl8150_netdev_ops = {
        .ndo_do_ioctl           = rtl8150_ioctl,
        .ndo_start_xmit         = rtl8150_start_xmit,
        .ndo_tx_timeout         = rtl8150_tx_timeout,
-       .ndo_set_multicast_list = rtl8150_set_multicast,
+       .ndo_set_rx_mode        = rtl8150_set_multicast,
        .ndo_set_mac_address    = rtl8150_set_mac_address,
 
        .ndo_change_mtu         = eth_change_mtu,
@@ -977,7 +977,6 @@ static void rtl8150_disconnect(struct usb_interface *intf)
        usb_set_intfdata(intf, NULL);
        if (dev) {
                set_bit(RTL8150_UNPLUG, &dev->flags);
-               tasklet_disable(&dev->tl);
                tasklet_kill(&dev->tl);
                unregister_netdev(dev->netdev);
                unlink_all_urbs(dev);
index 15b3d68..22a7cf9 100644 (file)
@@ -1000,7 +1000,7 @@ static const struct net_device_ops smsc75xx_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = smsc75xx_ioctl,
-       .ndo_set_multicast_list = smsc75xx_set_multicast,
+       .ndo_set_rx_mode        = smsc75xx_set_multicast,
        .ndo_set_features       = smsc75xx_set_features,
 };
 
index f74f3ce..eff6767 100644 (file)
@@ -972,7 +972,7 @@ static const struct net_device_ops smsc95xx_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = smsc95xx_ioctl,
-       .ndo_set_multicast_list = smsc95xx_set_multicast,
+       .ndo_set_rx_mode        = smsc95xx_set_multicast,
        .ndo_set_features       = smsc95xx_set_features,
 };
 
index 0c7321c..4f09f88 100644 (file)
@@ -949,6 +949,7 @@ static int virtnet_probe(struct virtio_device *vdev)
                return -ENOMEM;
 
        /* Set up network device as normal. */
+       dev->priv_flags |= IFF_UNICAST_FLT;
        dev->netdev_ops = &virtnet_netdev;
        dev->features = NETIF_F_HIGHDMA;
 
index 1cbacb3..759c1a4 100644 (file)
@@ -1929,14 +1929,17 @@ static void
 vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 {
        struct vmxnet3_adapter *adapter = netdev_priv(netdev);
-       u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
-       unsigned long flags;
 
-       VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
-       spin_lock_irqsave(&adapter->cmd_lock, flags);
-       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
-                              VMXNET3_CMD_UPDATE_VLAN_FILTERS);
-       spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+       if (!(netdev->flags & IFF_PROMISC)) {
+               u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+               unsigned long flags;
+
+               VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
+               spin_lock_irqsave(&adapter->cmd_lock, flags);
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                      VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+               spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+       }
 
        set_bit(vid, adapter->active_vlans);
 }
@@ -1946,14 +1949,17 @@ static void
 vmxnet3_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 {
        struct vmxnet3_adapter *adapter = netdev_priv(netdev);
-       u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
-       unsigned long flags;
 
-       VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid);
-       spin_lock_irqsave(&adapter->cmd_lock, flags);
-       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
-                              VMXNET3_CMD_UPDATE_VLAN_FILTERS);
-       spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+       if (!(netdev->flags & IFF_PROMISC)) {
+               u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+               unsigned long flags;
+
+               VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid);
+               spin_lock_irqsave(&adapter->cmd_lock, flags);
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                      VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+               spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+       }
 
        clear_bit(vid, adapter->active_vlans);
 }
@@ -2870,7 +2876,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
                .ndo_set_features = vmxnet3_set_features,
                .ndo_get_stats64 = vmxnet3_get_stats64,
                .ndo_tx_timeout = vmxnet3_tx_timeout,
-               .ndo_set_multicast_list = vmxnet3_set_mc,
+               .ndo_set_rx_mode = vmxnet3_set_mc,
                .ndo_vlan_rx_add_vid = vmxnet3_vlan_rx_add_vid,
                .ndo_vlan_rx_kill_vid = vmxnet3_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 055a918..0d76455 100644 (file)
@@ -515,37 +515,37 @@ static int ppp_rx(struct sk_buff *skb)
        switch (cp->code) {
        case CP_CONF_REQ:
                ppp_cp_parse_cr(dev, pid, cp->id, len, skb->data);
-               goto out;
+               break;
 
        case CP_CONF_ACK:
                if (cp->id == proto->cr_id)
                        ppp_cp_event(dev, pid, RCA, 0, 0, 0, NULL);
-               goto out;
+               break;
 
        case CP_CONF_REJ:
        case CP_CONF_NAK:
                if (cp->id == proto->cr_id)
                        ppp_cp_event(dev, pid, RCN, 0, 0, 0, NULL);
-               goto out;
+               break;
 
        case CP_TERM_REQ:
                ppp_cp_event(dev, pid, RTR, 0, cp->id, 0, NULL);
-               goto out;
+               break;
 
        case CP_TERM_ACK:
                ppp_cp_event(dev, pid, RTA, 0, 0, 0, NULL);
-               goto out;
+               break;
 
        case CP_CODE_REJ:
                ppp_cp_event(dev, pid, RXJ_BAD, 0, 0, 0, NULL);
-               goto out;
+               break;
 
        default:
                len += sizeof(struct cp_header);
                if (len > dev->mtu)
                        len = dev->mtu;
                ppp_cp_event(dev, pid, RUC, 0, 0, len, cp);
-               goto out;
+               break;
        }
        goto out;
 
index 86127bc..783168c 100644 (file)
@@ -212,7 +212,7 @@ static const struct net_device_ops sbni_netdev_ops = {
        .ndo_open               = sbni_open,
        .ndo_stop               = sbni_close,
        .ndo_start_xmit         = sbni_start_xmit,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_do_ioctl           = sbni_ioctl,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
index e1b3e3c..ac1176a 100644 (file)
@@ -2754,7 +2754,7 @@ static const struct net_device_ops airo_netdev_ops = {
        .ndo_stop               = airo_close,
        .ndo_start_xmit         = airo_start_xmit,
        .ndo_get_stats          = airo_get_stats,
-       .ndo_set_multicast_list = airo_set_multicast_list,
+       .ndo_set_rx_mode        = airo_set_multicast_list,
        .ndo_set_mac_address    = airo_set_mac_address,
        .ndo_do_ioctl           = airo_ioctl,
        .ndo_change_mtu         = airo_change_mtu,
@@ -2766,7 +2766,7 @@ static const struct net_device_ops mpi_netdev_ops = {
        .ndo_stop               = airo_close,
        .ndo_start_xmit         = mpi_start_xmit,
        .ndo_get_stats          = airo_get_stats,
-       .ndo_set_multicast_list = airo_set_multicast_list,
+       .ndo_set_rx_mode        = airo_set_multicast_list,
        .ndo_set_mac_address    = airo_set_mac_address,
        .ndo_do_ioctl           = airo_ioctl,
        .ndo_change_mtu         = airo_change_mtu,
index 108d55a..e9ea38d 100644 (file)
@@ -1729,6 +1729,8 @@ ath5k_beacon_setup(struct ath5k_hw *ah, struct ath5k_buf *bf)
 
        if (dma_mapping_error(ah->dev, bf->skbaddr)) {
                ATH5K_ERR(ah, "beacon DMA mapping failed\n");
+               dev_kfree_skb_any(skb);
+               bf->skb = NULL;
                return -EIO;
        }
 
@@ -1813,8 +1815,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        ath5k_txbuf_free_skb(ah, avf->bbuf);
        avf->bbuf->skb = skb;
        ret = ath5k_beacon_setup(ah, avf->bbuf);
-       if (ret)
-               avf->bbuf->skb = NULL;
 out:
        return ret;
 }
@@ -1834,6 +1834,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
        struct ath5k_vif *avf;
        struct ath5k_buf *bf;
        struct sk_buff *skb;
+       int err;
 
        ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "in beacon_send\n");
 
@@ -1882,11 +1883,6 @@ ath5k_beacon_send(struct ath5k_hw *ah)
 
        avf = (void *)vif->drv_priv;
        bf = avf->bbuf;
-       if (unlikely(bf->skb == NULL || ah->opmode == NL80211_IFTYPE_STATION ||
-                    ah->opmode == NL80211_IFTYPE_MONITOR)) {
-               ATH5K_WARN(ah, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
-               return;
-       }
 
        /*
         * Stop any current dma and put the new frame on the queue.
@@ -1900,8 +1896,17 @@ ath5k_beacon_send(struct ath5k_hw *ah)
 
        /* refresh the beacon for AP or MESH mode */
        if (ah->opmode == NL80211_IFTYPE_AP ||
-           ah->opmode == NL80211_IFTYPE_MESH_POINT)
-               ath5k_beacon_update(ah->hw, vif);
+           ah->opmode == NL80211_IFTYPE_MESH_POINT) {
+               err = ath5k_beacon_update(ah->hw, vif);
+               if (err)
+                       return;
+       }
+
+       if (unlikely(bf->skb == NULL || ah->opmode == NL80211_IFTYPE_STATION ||
+                    ah->opmode == NL80211_IFTYPE_MONITOR)) {
+               ATH5K_WARN(ah, "bf=%p bf_skb=%p\n", bf, bf->skb);
+               return;
+       }
 
        trace_ath5k_tx(ah, bf->skb, &ah->txqs[ah->bhalq]);
 
index 9084639..cb8bcc4 100644 (file)
@@ -307,7 +307,7 @@ static const struct ar9300_eeprom ar9300_default = {
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-                { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
@@ -884,7 +884,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-                { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
@@ -2040,7 +2040,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-               { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+               { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
@@ -3861,7 +3861,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
                                }
                        } else {
                                reg_pmu_set = (5 << 1) | (7 << 4) |
-                                             (1 << 8) | (2 << 14) |
+                                             (2 << 8) | (2 << 14) |
                                              (6 << 17) | (1 << 20) |
                                              (3 << 24) | (1 << 28);
                        }
index 3aca9fa..80397de 100644 (file)
 #define AR_PHY_TPC_11_B1         (AR_SM1_BASE + 0x220)
 #define AR_PHY_PDADC_TAB_1       (AR_SM1_BASE + 0x240)
 #define AR_PHY_TX_IQCAL_STATUS_B1   (AR_SM1_BASE + 0x48c)
-#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i)    (AR_SM_BASE + 0x450 + ((_i) << 2))
+#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i)    (AR_SM1_BASE + 0x450 + ((_i) << 2))
 
 /*
  * Channel 2 Register Map
index e76b40d..c5d890e 100644 (file)
@@ -816,9 +816,23 @@ static u64 supported_dma_mask(struct b43_wldev *dev)
        u32 tmp;
        u16 mmio_base;
 
-       tmp = b43_read32(dev, SSB_TMSHIGH);
-       if (tmp & SSB_TMSHIGH_DMA64)
-               return DMA_BIT_MASK(64);
+       switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+       case B43_BUS_BCMA:
+               tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST);
+               if (tmp & BCMA_IOST_DMA64)
+                       return DMA_BIT_MASK(64);
+               break;
+#endif
+#ifdef CONFIG_B43_SSB
+       case B43_BUS_SSB:
+               tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
+               if (tmp & SSB_TMSHIGH_DMA64)
+                       return DMA_BIT_MASK(64);
+               break;
+#endif
+       }
+
        mmio_base = b43_dmacontroller_base(0, 0);
        b43_write32(dev, mmio_base + B43_DMA32_TXCTL, B43_DMA32_TXADDREXT_MASK);
        tmp = b43_read32(dev, mmio_base + B43_DMA32_TXCTL);
index 89a116f..bfa0d54 100644 (file)
@@ -816,7 +816,7 @@ static const struct net_device_ops hostap_netdev_ops = {
        .ndo_stop               = prism2_close,
        .ndo_do_ioctl           = hostap_ioctl,
        .ndo_set_mac_address    = prism2_set_mac_address,
-       .ndo_set_multicast_list = hostap_set_multicast_list,
+       .ndo_set_rx_mode        = hostap_set_multicast_list,
        .ndo_change_mtu         = prism2_change_mtu,
        .ndo_tx_timeout         = prism2_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
@@ -829,7 +829,7 @@ static const struct net_device_ops hostap_mgmt_netdev_ops = {
        .ndo_stop               = prism2_close,
        .ndo_do_ioctl           = hostap_ioctl,
        .ndo_set_mac_address    = prism2_set_mac_address,
-       .ndo_set_multicast_list = hostap_set_multicast_list,
+       .ndo_set_rx_mode        = hostap_set_multicast_list,
        .ndo_change_mtu         = prism2_change_mtu,
        .ndo_tx_timeout         = prism2_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
@@ -842,7 +842,7 @@ static const struct net_device_ops hostap_master_ops = {
        .ndo_stop               = prism2_close,
        .ndo_do_ioctl           = hostap_ioctl,
        .ndo_set_mac_address    = prism2_set_mac_address,
-       .ndo_set_multicast_list = hostap_set_multicast_list,
+       .ndo_set_rx_mode        = hostap_set_multicast_list,
        .ndo_change_mtu         = prism2_change_mtu,
        .ndo_tx_timeout         = prism2_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
index 4395977..f303df4 100644 (file)
@@ -11702,7 +11702,7 @@ static const struct net_device_ops ipw_netdev_ops = {
        .ndo_init               = ipw_net_init,
        .ndo_open               = ipw_net_open,
        .ndo_stop               = ipw_net_stop,
-       .ndo_set_multicast_list = ipw_net_set_multicast_list,
+       .ndo_set_rx_mode        = ipw_net_set_multicast_list,
        .ndo_set_mac_address    = ipw_net_set_mac_address,
        .ndo_start_xmit         = libipw_xmit,
        .ndo_change_mtu         = libipw_change_mtu,
index d62d1fb..d1c1d52 100644 (file)
@@ -867,7 +867,7 @@ static const struct net_device_ops lbs_netdev_ops = {
        .ndo_stop               = lbs_eth_stop,
        .ndo_start_xmit         = lbs_hard_start_xmit,
        .ndo_set_mac_address    = lbs_set_mac_address,
-       .ndo_set_multicast_list = lbs_set_multicast_list,
+       .ndo_set_rx_mode        = lbs_set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 138699b..e87c031 100644 (file)
@@ -978,7 +978,7 @@ static const struct net_device_ops mesh_netdev_ops = {
        .ndo_stop               = lbs_mesh_stop,
        .ndo_start_xmit         = lbs_hard_start_xmit,
        .ndo_set_mac_address    = lbs_set_mac_address,
-       .ndo_set_multicast_list = lbs_set_multicast_list,
+       .ndo_set_rx_mode        = lbs_set_multicast_list,
 };
 
 /**
index 53579ad..48b4d95 100644 (file)
@@ -627,7 +627,7 @@ static const struct net_device_ops mwifiex_netdev_ops = {
        .ndo_set_mac_address = mwifiex_set_mac_address,
        .ndo_tx_timeout = mwifiex_tx_timeout,
        .ndo_get_stats = mwifiex_get_stats,
-       .ndo_set_multicast_list = mwifiex_set_multicast_list,
+       .ndo_set_rx_mode = mwifiex_set_multicast_list,
 };
 
 /*
index ef7efe8..b52acc4 100644 (file)
@@ -2135,7 +2135,7 @@ static const struct net_device_ops orinoco_netdev_ops = {
        .ndo_open               = orinoco_open,
        .ndo_stop               = orinoco_stop,
        .ndo_start_xmit         = orinoco_xmit,
-       .ndo_set_multicast_list = orinoco_set_multicast_list,
+       .ndo_set_rx_mode        = orinoco_set_multicast_list,
        .ndo_change_mtu         = orinoco_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
index 811e87f..0793e42 100644 (file)
@@ -1562,7 +1562,7 @@ static const struct net_device_ops ezusb_netdev_ops = {
        .ndo_open               = orinoco_open,
        .ndo_stop               = orinoco_stop,
        .ndo_start_xmit         = ezusb_xmit,
-       .ndo_set_multicast_list = orinoco_set_multicast_list,
+       .ndo_set_rx_mode        = orinoco_set_multicast_list,
        .ndo_change_mtu         = orinoco_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
index 2a06ebc..0021e49 100644 (file)
@@ -273,7 +273,7 @@ static const struct net_device_ops ray_netdev_ops = {
        .ndo_start_xmit         = ray_dev_start_xmit,
        .ndo_set_config         = ray_dev_config,
        .ndo_get_stats          = ray_get_stats,
-       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_set_rx_mode        = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
index 15464d5..0c13840 100644 (file)
@@ -3390,7 +3390,7 @@ static const struct net_device_ops rndis_wlan_netdev_ops = {
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = rndis_wlan_set_multicast_list,
+       .ndo_set_rx_mode        = rndis_wlan_set_multicast_list,
 };
 
 static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
index 5075593..9395631 100644 (file)
@@ -921,6 +921,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x07d1, 0x3c16) },
        /* Draytek */
        { USB_DEVICE(0x07fa, 0x7712) },
+       /* DVICO */
+       { USB_DEVICE(0x0fe9, 0xb307) },
        /* Edimax */
        { USB_DEVICE(0x7392, 0x7711) },
        { USB_DEVICE(0x7392, 0x7717) },
index 6a93939..0baeb89 100644 (file)
@@ -2420,6 +2420,7 @@ static struct usb_device_id rt73usb_device_table[] = {
        /* Buffalo */
        { USB_DEVICE(0x0411, 0x00d8) },
        { USB_DEVICE(0x0411, 0x00d9) },
+       { USB_DEVICE(0x0411, 0x00e6) },
        { USB_DEVICE(0x0411, 0x00f4) },
        { USB_DEVICE(0x0411, 0x0116) },
        { USB_DEVICE(0x0411, 0x0119) },
index 195666a..424b8a0 100644 (file)
@@ -281,6 +281,8 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817d, rtl92cu_hal_cfg)},
        /* 8188CE-VAU USB minCard (b/g mode only) */
        {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817e, rtl92cu_hal_cfg)},
+       /* 8188RU in Alfa AWUS036NHR */
+       {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)},
        /* 8188 Combo for BC4 */
        {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)},
 
@@ -303,20 +305,23 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
        /* HP - Lite-On ,8188CUS Slim Combo */
        {RTL_USB_DEVICE(0x103c, 0x1629, rtl92cu_hal_cfg)},
+       {RTL_USB_DEVICE(0x13d3, 0x3357, rtl92cu_hal_cfg)}, /* AzureWave */
        {RTL_USB_DEVICE(0x2001, 0x3308, rtl92cu_hal_cfg)}, /*D-Link - Alpha*/
        {RTL_USB_DEVICE(0x2019, 0xab2a, rtl92cu_hal_cfg)}, /*Planex - Abocom*/
        {RTL_USB_DEVICE(0x2019, 0xed17, rtl92cu_hal_cfg)}, /*PCI - Edimax*/
        {RTL_USB_DEVICE(0x20f4, 0x648b, rtl92cu_hal_cfg)}, /*TRENDnet - Cameo*/
        {RTL_USB_DEVICE(0x7392, 0x7811, rtl92cu_hal_cfg)}, /*Edimax - Edimax*/
-       {RTL_USB_DEVICE(0x3358, 0x13d3, rtl92cu_hal_cfg)}, /*Azwave 8188CE-VAU*/
+       {RTL_USB_DEVICE(0x13d3, 0x3358, rtl92cu_hal_cfg)}, /*Azwave 8188CE-VAU*/
        /* Russian customer -Azwave (8188CE-VAU  b/g mode only) */
-       {RTL_USB_DEVICE(0x3359, 0x13d3, rtl92cu_hal_cfg)},
+       {RTL_USB_DEVICE(0x13d3, 0x3359, rtl92cu_hal_cfg)},
+       {RTL_USB_DEVICE(0x4855, 0x0090, rtl92cu_hal_cfg)}, /* Feixun */
+       {RTL_USB_DEVICE(0x4855, 0x0091, rtl92cu_hal_cfg)}, /* NetweeN-Feixun */
+       {RTL_USB_DEVICE(0x9846, 0x9041, rtl92cu_hal_cfg)}, /* Netgear Cameo */
 
        /****** 8192CU ********/
        {RTL_USB_DEVICE(0x0586, 0x341f, rtl92cu_hal_cfg)}, /*Zyxel -Abocom*/
        {RTL_USB_DEVICE(0x07aa, 0x0056, rtl92cu_hal_cfg)}, /*ATKK-Gemtek*/
        {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/
-       {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Abocom -Abocom*/
        {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/
        {RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
        {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
index ef8370e..ad87a1a 100644 (file)
@@ -140,8 +140,6 @@ int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth)
        auth->sleep_auth = sleep_auth;
 
        ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
-       if (ret < 0)
-               return ret;
 
 out:
        kfree(auth);
@@ -681,10 +679,8 @@ int wl1251_acx_cca_threshold(struct wl1251 *wl)
 
        ret = wl1251_cmd_configure(wl, ACX_CCA_THRESHOLD,
                                   detection, sizeof(*detection));
-       if (ret < 0) {
+       if (ret < 0)
                wl1251_warning("failed to set cca threshold: %d", ret);
-               return ret;
-       }
 
 out:
        kfree(detection);
index 81f164b..d14d69d 100644 (file)
@@ -241,7 +241,7 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
        if (ret < 0) {
                wl1251_error("tx %s cmd for channel %d failed",
                             enable ? "start" : "stop", channel);
-               return ret;
+               goto out;
        }
 
        wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d",
index 415eec4..8efa2f2 100644 (file)
@@ -1722,7 +1722,7 @@ static const struct net_device_ops zd1201_netdev_ops = {
        .ndo_stop               = zd1201_net_stop,
        .ndo_start_xmit         = zd1201_hard_start_xmit,
        .ndo_tx_timeout         = zd1201_tx_timeout,
-       .ndo_set_multicast_list = zd1201_set_multicast,
+       .ndo_set_rx_mode        = zd1201_set_multicast,
        .ndo_set_mac_address    = zd1201_set_mac_address,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
index da1f4b9..72c33fb 100644 (file)
@@ -610,6 +610,6 @@ void __iomem *of_iomap(struct device_node *np, int index)
        if (of_address_to_resource(np, index, &res))
                return NULL;
 
-       return ioremap(res.start, 1 + res.end - res.start);
+       return ioremap(res.start, resource_size(&res));
 }
 EXPORT_SYMBOL(of_iomap);
index 02ed367..3ff22e3 100644 (file)
@@ -610,8 +610,9 @@ EXPORT_SYMBOL(of_find_node_by_phandle);
  *
  * The out_value is modified only if a valid u32 value can be decoded.
  */
-int of_property_read_u32_array(const struct device_node *np, char *propname,
-                              u32 *out_values, size_t sz)
+int of_property_read_u32_array(const struct device_node *np,
+                              const char *propname, u32 *out_values,
+                              size_t sz)
 {
        struct property *prop = of_find_property(np, propname, NULL);
        const __be32 *val;
@@ -645,7 +646,7 @@ EXPORT_SYMBOL_GPL(of_property_read_u32_array);
  *
  * The out_string pointer is modified only if a valid string can be decoded.
  */
-int of_property_read_string(struct device_node *np, char *propname,
+int of_property_read_string(struct device_node *np, const char *propname,
                                const char **out_string)
 {
        struct property *prop = of_find_property(np, propname, NULL);
index 3007662..ef0105f 100644 (file)
@@ -127,8 +127,8 @@ EXPORT_SYMBOL(of_gpio_count);
  * gpio chips. This function performs only one sanity check: whether gpio
  * is less than ngpios (that is specified in the gpio_chip).
  */
-static int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
-                               const void *gpio_spec, u32 *flags)
+int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
+                        const void *gpio_spec, u32 *flags)
 {
        const __be32 *gpio = gpio_spec;
        const u32 n = be32_to_cpup(gpio);
@@ -152,6 +152,7 @@ static int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
 
        return n;
 }
+EXPORT_SYMBOL(of_gpio_simple_xlate);
 
 /**
  * of_mm_gpiochip_add - Add memory mapped GPIO chip (bank)
index 86f334a..bb18471 100644 (file)
@@ -8,6 +8,51 @@
 #include <linux/etherdevice.h>
 #include <linux/kernel.h>
 #include <linux/of_net.h>
+#include <linux/phy.h>
+
+/**
+ * It maps 'enum phy_interface_t' found in include/linux/phy.h
+ * into the device tree binding of 'phy-mode', so that Ethernet
+ * device driver can get phy interface from device tree.
+ */
+static const char *phy_modes[] = {
+       [PHY_INTERFACE_MODE_NA]         = "",
+       [PHY_INTERFACE_MODE_MII]        = "mii",
+       [PHY_INTERFACE_MODE_GMII]       = "gmii",
+       [PHY_INTERFACE_MODE_SGMII]      = "sgmii",
+       [PHY_INTERFACE_MODE_TBI]        = "tbi",
+       [PHY_INTERFACE_MODE_RMII]       = "rmii",
+       [PHY_INTERFACE_MODE_RGMII]      = "rgmii",
+       [PHY_INTERFACE_MODE_RGMII_ID]   = "rgmii-id",
+       [PHY_INTERFACE_MODE_RGMII_RXID] = "rgmii-rxid",
+       [PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
+       [PHY_INTERFACE_MODE_RTBI]       = "rtbi",
+       [PHY_INTERFACE_MODE_SMII]       = "smii",
+};
+
+/**
+ * of_get_phy_mode - Get phy mode for given device_node
+ * @np:        Pointer to the given device_node
+ *
+ * The function gets phy interface string from property 'phy-mode',
+ * and return its index in phy_modes table, or errno in error case.
+ */
+const int of_get_phy_mode(struct device_node *np)
+{
+       const char *pm;
+       int err, i;
+
+       err = of_property_read_string(np, "phy-mode", &pm);
+       if (err < 0)
+               return err;
+
+       for (i = 0; i < ARRAY_SIZE(phy_modes); i++)
+               if (!strcasecmp(pm, phy_modes[i]))
+                       return i;
+
+       return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(of_get_phy_mode);
 
 /**
  * Search the device tree for the best MAC address to use.  'mac-address' is
index 8f3faf3..095f29e 100644 (file)
@@ -408,7 +408,7 @@ got_one:
 }
 EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware);
 
-static int is_ejectable(acpi_handle handle)
+static int pcihp_is_ejectable(acpi_handle handle)
 {
        acpi_status status;
        acpi_handle tmp;
@@ -442,7 +442,7 @@ int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle)
                return 0;
        if (bridge_handle != parent_handle)
                return 0;
-       return is_ejectable(handle);
+       return pcihp_is_ejectable(handle);
 }
 EXPORT_SYMBOL_GPL(acpi_pci_check_ejectable);
 
@@ -450,7 +450,7 @@ static acpi_status
 check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
        int *found = (int *)context;
-       if (is_ejectable(handle)) {
+       if (pcihp_is_ejectable(handle)) {
                *found = 1;
                return AE_CTRL_TERMINATE;
        }
index a70fa89..2202857 100644 (file)
@@ -110,7 +110,7 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
 }
 
 
-static struct acpi_dock_ops acpiphp_dock_ops = {
+static const struct acpi_dock_ops acpiphp_dock_ops = {
        .handler = handle_hotplug_event_func,
 };
 
index 4952c3b..f1ce99c 100644 (file)
@@ -840,8 +840,9 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* Need to read VID early b/c it's used to differentiate CPQ and INTC
         * discovery
         */
-       rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
-       if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
+       vendor_id = pdev->vendor;
+       if ((vendor_id != PCI_VENDOR_ID_COMPAQ) &&
+           (vendor_id != PCI_VENDOR_ID_INTEL)) {
                err(msg_HPC_non_compaq_or_intel);
                rc = -ENODEV;
                goto err_disable_device;
@@ -868,11 +869,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* TODO: This code can be made to support non-Compaq or Intel
         * subsystem IDs
         */
-       rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
-       if (rc) {
-               err("%s : pci_read_config_word failed\n", __func__);
-               goto err_disable_device;
-       }
+       subsystem_vid = pdev->subsystem_vendor;
        dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
        if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
                err(msg_HPC_non_compaq_or_intel);
@@ -887,11 +884,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_disable_device;
        }
 
-       rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
-       if (rc) {
-               err("%s : pci_read_config_word failed\n", __func__);
-               goto err_free_ctrl;
-       }
+       subsystem_deviceid = pdev->subsystem_device;
 
        info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid);
 
index 085dbb5..1e9c9aa 100644 (file)
@@ -213,6 +213,9 @@ static int board_added(struct slot *p_slot)
                goto err_exit;
        }
 
+       /* Wait for 1 second after checking link training status */
+       msleep(1000);
+
        /* Check for a power fault */
        if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
                ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
index 50a23da..96dc473 100644 (file)
@@ -275,16 +275,9 @@ int pciehp_check_link_status(struct controller *ctrl)
          * hot-plug capable downstream port. But old controller might
          * not implement it. In this case, we wait for 1000 ms.
          */
-        if (ctrl->link_active_reporting){
-                /* Wait for Data Link Layer Link Active bit to be set */
+        if (ctrl->link_active_reporting)
                 pcie_wait_link_active(ctrl);
-                /*
-                 * We must wait for 100 ms after the Data Link Layer
-                 * Link Active bit reads 1b before initiating a
-                 * configuration access to the hot added device.
-                 */
-                msleep(100);
-        } else
+        else
                 msleep(1000);
 
        retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
index 692671b..08a95b3 100644 (file)
@@ -1905,7 +1905,7 @@ void pci_enable_ari(struct pci_dev *dev)
 {
        int pos;
        u32 cap;
-       u16 ctrl;
+       u16 flags, ctrl;
        struct pci_dev *bridge;
 
        if (!pci_is_pcie(dev) || dev->devfn)
@@ -1923,6 +1923,11 @@ void pci_enable_ari(struct pci_dev *dev)
        if (!pos)
                return;
 
+       /* ARI is a PCIe v2 feature */
+       pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &flags);
+       if ((flags & PCI_EXP_FLAGS_VERS) < 2)
+               return;
+
        pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap);
        if (!(cap & PCI_EXP_DEVCAP2_ARI))
                return;
@@ -3186,7 +3191,7 @@ EXPORT_SYMBOL(pcie_get_readrq);
  * @rq: maximum memory read count in bytes
  *    valid values are 128, 256, 512, 1024, 2048, 4096
  *
- * If possible sets maximum read byte count
+ * If possible sets maximum memory read request in bytes
  */
 int pcie_set_readrq(struct pci_dev *dev, int rq)
 {
@@ -3209,7 +3214,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
        if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) {
                ctl &= ~PCI_EXP_DEVCTL_READRQ;
                ctl |= v;
-               err = pci_write_config_dword(dev, cap + PCI_EXP_DEVCTL, ctl);
+               err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl);
        }
 
 out:
index 43421fb..9674e9f 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/suspend.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/kfifo.h>
 #include "aerdrv.h"
 
 static int forceload;
@@ -445,8 +446,7 @@ static struct pcie_port_service_driver *find_aer_service(struct pci_dev *dev)
        return drv;
 }
 
-static pci_ers_result_t reset_link(struct pcie_device *aerdev,
-               struct pci_dev *dev)
+static pci_ers_result_t reset_link(struct pci_dev *dev)
 {
        struct pci_dev *udev;
        pci_ers_result_t status;
@@ -486,7 +486,6 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev,
 
 /**
  * do_recovery - handle nonfatal/fatal error recovery process
- * @aerdev: pointer to a pcie_device data structure of root port
  * @dev: pointer to a pci_dev data structure of agent detecting an error
  * @severity: error severity type
  *
@@ -494,8 +493,7 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev,
  * error detected message to all downstream drivers within a hierarchy in
  * question and return the returned code.
  */
-static void do_recovery(struct pcie_device *aerdev, struct pci_dev *dev,
-               int severity)
+static void do_recovery(struct pci_dev *dev, int severity)
 {
        pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED;
        enum pci_channel_state state;
@@ -511,7 +509,7 @@ static void do_recovery(struct pcie_device *aerdev, struct pci_dev *dev,
                        report_error_detected);
 
        if (severity == AER_FATAL) {
-               result = reset_link(aerdev, dev);
+               result = reset_link(dev);
                if (result != PCI_ERS_RESULT_RECOVERED)
                        goto failed;
        }
@@ -576,9 +574,73 @@ static void handle_error_source(struct pcie_device *aerdev,
                        pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
                                        info->status);
        } else
-               do_recovery(aerdev, dev, info->severity);
+               do_recovery(dev, info->severity);
 }
 
+#ifdef CONFIG_ACPI_APEI_PCIEAER
+static void aer_recover_work_func(struct work_struct *work);
+
+#define AER_RECOVER_RING_ORDER         4
+#define AER_RECOVER_RING_SIZE          (1 << AER_RECOVER_RING_ORDER)
+
+struct aer_recover_entry
+{
+       u8      bus;
+       u8      devfn;
+       u16     domain;
+       int     severity;
+};
+
+static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry,
+                   AER_RECOVER_RING_SIZE);
+/*
+ * Mutual exclusion for writers of aer_recover_ring, reader side don't
+ * need lock, because there is only one reader and lock is not needed
+ * between reader and writer.
+ */
+static DEFINE_SPINLOCK(aer_recover_ring_lock);
+static DECLARE_WORK(aer_recover_work, aer_recover_work_func);
+
+void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
+                      int severity)
+{
+       unsigned long flags;
+       struct aer_recover_entry entry = {
+               .bus            = bus,
+               .devfn          = devfn,
+               .domain         = domain,
+               .severity       = severity,
+       };
+
+       spin_lock_irqsave(&aer_recover_ring_lock, flags);
+       if (kfifo_put(&aer_recover_ring, &entry))
+               schedule_work(&aer_recover_work);
+       else
+               pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n",
+                      domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+       spin_unlock_irqrestore(&aer_recover_ring_lock, flags);
+}
+EXPORT_SYMBOL_GPL(aer_recover_queue);
+
+static void aer_recover_work_func(struct work_struct *work)
+{
+       struct aer_recover_entry entry;
+       struct pci_dev *pdev;
+
+       while (kfifo_get(&aer_recover_ring, &entry)) {
+               pdev = pci_get_domain_bus_and_slot(entry.domain, entry.bus,
+                                                  entry.devfn);
+               if (!pdev) {
+                       pr_err("AER recover: Can not find pci_dev for %04x:%02x:%02x:%x\n",
+                              entry.domain, entry.bus,
+                              PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn));
+                       continue;
+               }
+               do_recovery(pdev, entry.severity);
+       }
+}
+#endif
+
 /**
  * get_device_error_info - read error status from dev and store it to info
  * @dev: pointer to the device expected to have a error record
index b07a42e..3ea5173 100644 (file)
@@ -204,7 +204,7 @@ void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
 }
 
 #ifdef CONFIG_ACPI_APEI_PCIEAER
-static int cper_severity_to_aer(int cper_severity)
+int cper_severity_to_aer(int cper_severity)
 {
        switch (cper_severity) {
        case CPER_SEV_RECOVERABLE:
@@ -215,6 +215,7 @@ static int cper_severity_to_aer(int cper_severity)
                return AER_CORRECTABLE;
        }
 }
+EXPORT_SYMBOL_GPL(cper_severity_to_aer);
 
 void cper_print_aer(const char *prefix, int cper_severity,
                    struct aer_capability_regs *aer)
index 9ab492f..795c902 100644 (file)
@@ -68,21 +68,6 @@ static int __init pcibus_class_init(void)
 }
 postcore_initcall(pcibus_class_init);
 
-/*
- * Translate the low bits of the PCI base
- * to the resource type
- */
-static inline unsigned int pci_calc_resource_flags(unsigned int flags)
-{
-       if (flags & PCI_BASE_ADDRESS_SPACE_IO)
-               return IORESOURCE_IO;
-
-       if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH)
-               return IORESOURCE_MEM | IORESOURCE_PREFETCH;
-
-       return IORESOURCE_MEM;
-}
-
 static u64 pci_size(u64 base, u64 maxbase, u64 mask)
 {
        u64 size = mask & maxbase;      /* Find the significant bits */
@@ -101,18 +86,39 @@ static u64 pci_size(u64 base, u64 maxbase, u64 mask)
        return size;
 }
 
-static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)
+static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)
 {
+       u32 mem_type;
+       unsigned long flags;
+
        if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
-               res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK;
-               return pci_bar_io;
+               flags = bar & ~PCI_BASE_ADDRESS_IO_MASK;
+               flags |= IORESOURCE_IO;
+               return flags;
        }
 
-       res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK;
+       flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK;
+       flags |= IORESOURCE_MEM;
+       if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH)
+               flags |= IORESOURCE_PREFETCH;
 
-       if (res->flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
-               return pci_bar_mem64;
-       return pci_bar_mem32;
+       mem_type = bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+       switch (mem_type) {
+       case PCI_BASE_ADDRESS_MEM_TYPE_32:
+               break;
+       case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+               dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n");
+               break;
+       case PCI_BASE_ADDRESS_MEM_TYPE_64:
+               flags |= IORESOURCE_MEM_64;
+               break;
+       default:
+               dev_warn(&dev->dev,
+                        "mem unknown type %x treated as 32-bit BAR\n",
+                        mem_type);
+               break;
+       }
+       return flags;
 }
 
 /**
@@ -165,9 +171,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                l = 0;
 
        if (type == pci_bar_unknown) {
-               type = decode_bar(res, l);
-               res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
-               if (type == pci_bar_io) {
+               res->flags = decode_bar(dev, l);
+               res->flags |= IORESOURCE_SIZEALIGN;
+               if (res->flags & IORESOURCE_IO) {
                        l &= PCI_BASE_ADDRESS_IO_MASK;
                        mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT;
                } else {
@@ -180,7 +186,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                mask = (u32)PCI_ROM_ADDRESS_MASK;
        }
 
-       if (type == pci_bar_mem64) {
+       if (res->flags & IORESOURCE_MEM_64) {
                u64 l64 = l;
                u64 sz64 = sz;
                u64 mask64 = mask | (u64)~0 << 32;
@@ -204,7 +210,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        goto fail;
                }
 
-               res->flags |= IORESOURCE_MEM_64;
                if ((sizeof(resource_size_t) < 8) && l) {
                        /* Address above 32-bit boundary; disable the BAR */
                        pci_write_config_dword(dev, pos, 0);
@@ -230,7 +235,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
        }
 
  out:
-       return (type == pci_bar_mem64) ? 1 : 0;
+       return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
  fail:
        res->flags = 0;
        goto out;
@@ -284,10 +289,6 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
                if (!res->end)
                        res->end = limit + 0xfff;
                dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);
-       } else {
-               dev_printk(KERN_DEBUG, &dev->dev,
-                        "  bridge window [io  %#06lx-%#06lx] (disabled)\n",
-                                base, limit);
        }
 }
 
@@ -308,10 +309,6 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
                res->start = base;
                res->end = limit + 0xfffff;
                dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);
-       } else {
-               dev_printk(KERN_DEBUG, &dev->dev,
-                       "  bridge window [mem %#010lx-%#010lx] (disabled)\n",
-                                        base, limit + 0xfffff);
        }
 }
 
@@ -359,10 +356,6 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
                res->start = base;
                res->end = limit + 0xfffff;
                dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);
-       } else {
-               dev_printk(KERN_DEBUG, &dev->dev,
-                    "  bridge window [mem %#010lx-%#010lx pref] (disabled)\n",
-                                        base, limit + 0xfffff);
        }
 }
 
@@ -725,12 +718,14 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
                pci_write_config_word(dev, PCI_STATUS, 0xffff);
 
                /* Prevent assigning a bus number that already exists.
-                * This can happen when a bridge is hot-plugged */
-               if (pci_find_bus(pci_domain_nr(bus), max+1))
-                       goto out;
-               child = pci_add_new_bus(bus, dev, ++max);
-               if (!child)
-                       goto out;
+                * This can happen when a bridge is hot-plugged, so in
+                * this case we only re-scan this bus. */
+               child = pci_find_bus(pci_domain_nr(bus), max+1);
+               if (!child) {
+                       child = pci_add_new_bus(bus, dev, ++max);
+                       if (!child)
+                               goto out;
+               }
                buses = (buses & 0xff000000)
                      | ((unsigned int)(child->primary)     <<  0)
                      | ((unsigned int)(child->secondary)   <<  8)
index 9995842..8a1d3c7 100644 (file)
@@ -336,7 +336,6 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
                /* Clear upper 16 bits of I/O base/limit. */
                io_upper16 = 0;
                l = 0x00f0;
-               dev_info(&bridge->dev, "  bridge window [io  disabled]\n");
        }
        /* Temporarily disable the I/O range before updating PCI_IO_BASE. */
        pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
@@ -362,7 +361,6 @@ static void pci_setup_bridge_mmio(struct pci_bus *bus)
                dev_info(&bridge->dev, "  bridge window %pR\n", res);
        } else {
                l = 0x0000fff0;
-               dev_info(&bridge->dev, "  bridge window [mem disabled]\n");
        }
        pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
 }
@@ -393,7 +391,6 @@ static void pci_setup_bridge_mmio_pref(struct pci_bus *bus)
                dev_info(&bridge->dev, "  bridge window %pR\n", res);
        } else {
                l = 0x0000fff0;
-               dev_info(&bridge->dev, "  bridge window [mem pref disabled]\n");
        }
        pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
 
index eec9738..eb219a1 100644 (file)
@@ -21,7 +21,7 @@
 static void __init
 pdev_fixup_irq(struct pci_dev *dev,
               u8 (*swizzle)(struct pci_dev *, u8 *),
-              int (*map_irq)(struct pci_dev *, u8, u8))
+              int (*map_irq)(const struct pci_dev *, u8, u8))
 {
        u8 pin, slot;
        int irq = 0;
@@ -56,7 +56,7 @@ pdev_fixup_irq(struct pci_dev *dev,
 
 void __init
 pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
-              int (*map_irq)(struct pci_dev *, u8, u8))
+              int (*map_irq)(const struct pci_dev *, u8, u8))
 {
        struct pci_dev *dev = NULL;
        for_each_pci_dev(dev)
index bc0e6ee..319f359 100644 (file)
@@ -74,8 +74,7 @@ void pci_update_resource(struct pci_dev *dev, int resno)
                        resno, new, check);
        }
 
-       if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
-           (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+       if (res->flags & IORESOURCE_MEM_64) {
                new = region.start >> 16 >> 16;
                pci_write_config_dword(dev, reg + 4, new);
                pci_read_config_dword(dev, reg + 4, &check);
index 4c3e94c..f56d7de 100644 (file)
@@ -103,22 +103,12 @@ static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
        return 0;
 }
 
-static void balloon3_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void balloon3_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
 static struct pcmcia_low_level balloon3_pcmcia_ops = {
        .owner                  = THIS_MODULE,
        .hw_init                = balloon3_pcmcia_hw_init,
        .hw_shutdown            = balloon3_pcmcia_hw_shutdown,
        .socket_state           = balloon3_pcmcia_socket_state,
        .configure_socket       = balloon3_pcmcia_configure_socket,
-       .socket_init            = balloon3_pcmcia_socket_init,
-       .socket_suspend         = balloon3_pcmcia_socket_suspend,
        .first                  = 0,
        .nr                     = 1,
 };
index 05913d0..63f4d52 100644 (file)
@@ -102,23 +102,12 @@ static int cmx255_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
        return 0;
 }
 
-static void cmx255_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void cmx255_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
-
 static struct pcmcia_low_level cmx255_pcmcia_ops __initdata = {
        .owner                  = THIS_MODULE,
        .hw_init                = cmx255_pcmcia_hw_init,
        .hw_shutdown            = cmx255_pcmcia_shutdown,
        .socket_state           = cmx255_pcmcia_socket_state,
        .configure_socket       = cmx255_pcmcia_configure_socket,
-       .socket_init            = cmx255_pcmcia_socket_init,
-       .socket_suspend         = cmx255_pcmcia_socket_suspend,
        .nr                     = 1,
 };
 
index 5662646..6ee42b4 100644 (file)
@@ -82,23 +82,12 @@ static int cmx270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
        return 0;
 }
 
-static void cmx270_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void cmx270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
-
 static struct pcmcia_low_level cmx270_pcmcia_ops __initdata = {
        .owner                  = THIS_MODULE,
        .hw_init                = cmx270_pcmcia_hw_init,
        .hw_shutdown            = cmx270_pcmcia_shutdown,
        .socket_state           = cmx270_pcmcia_socket_state,
        .configure_socket       = cmx270_pcmcia_configure_socket,
-       .socket_init            = cmx270_pcmcia_socket_init,
-       .socket_suspend         = cmx270_pcmcia_socket_suspend,
        .nr                     = 1,
 };
 
index 443cb7f..c6dec57 100644 (file)
@@ -116,14 +116,6 @@ colibri_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
        return 0;
 }
 
-static void colibri_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void colibri_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
 static struct pcmcia_low_level colibri_pcmcia_ops = {
        .owner                  = THIS_MODULE,
 
@@ -135,9 +127,6 @@ static struct pcmcia_low_level colibri_pcmcia_ops = {
 
        .socket_state           = colibri_pcmcia_socket_state,
        .configure_socket       = colibri_pcmcia_configure_socket,
-
-       .socket_init            = colibri_pcmcia_socket_init,
-       .socket_suspend         = colibri_pcmcia_socket_suspend,
 };
 
 static struct platform_device *colibri_pcmcia_device;
index 92016fe..aded706 100644 (file)
@@ -128,22 +128,12 @@ static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
        return ret;
 }
 
-static void mst_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void mst_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
 static struct pcmcia_low_level mst_pcmcia_ops __initdata = {
        .owner                  = THIS_MODULE,
        .hw_init                = mst_pcmcia_hw_init,
        .hw_shutdown            = mst_pcmcia_hw_shutdown,
        .socket_state           = mst_pcmcia_socket_state,
        .configure_socket       = mst_pcmcia_configure_socket,
-       .socket_init            = mst_pcmcia_socket_init,
-       .socket_suspend         = mst_pcmcia_socket_suspend,
        .nr                     = 2,
 };
 
index 69f7367..d589ad1 100644 (file)
@@ -65,14 +65,6 @@ static int palmld_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
        return 0;
 }
 
-static void palmld_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void palmld_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
 static struct pcmcia_low_level palmld_pcmcia_ops = {
        .owner                  = THIS_MODULE,
 
@@ -84,9 +76,6 @@ static struct pcmcia_low_level palmld_pcmcia_ops = {
 
        .socket_state           = palmld_pcmcia_socket_state,
        .configure_socket       = palmld_pcmcia_configure_socket,
-
-       .socket_init            = palmld_pcmcia_socket_init,
-       .socket_suspend         = palmld_pcmcia_socket_suspend,
 };
 
 static struct platform_device *palmld_pcmcia_device;
index d0ad6a7..9c6a04b 100644 (file)
@@ -117,14 +117,6 @@ static int palmtc_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
        return ret;
 }
 
-static void palmtc_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void palmtc_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
 static struct pcmcia_low_level palmtc_pcmcia_ops = {
        .owner                  = THIS_MODULE,
 
@@ -136,9 +128,6 @@ static struct pcmcia_low_level palmtc_pcmcia_ops = {
 
        .socket_state           = palmtc_pcmcia_socket_state,
        .configure_socket       = palmtc_pcmcia_configure_socket,
-
-       .socket_init            = palmtc_pcmcia_socket_init,
-       .socket_suspend         = palmtc_pcmcia_socket_suspend,
 };
 
 static struct platform_device *palmtc_pcmcia_device;
index 1a25804..80645a6 100644 (file)
@@ -67,14 +67,6 @@ palmtx_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
        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,
 
@@ -86,9 +78,6 @@ static struct pcmcia_low_level palmtx_pcmcia_ops = {
 
        .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;
index d08802f..9396222 100644 (file)
@@ -28,7 +28,6 @@
 
 #include "soc_common.h"
 
-#define SG2_S0_BUFF_CTL                120
 #define SG2_S0_POWER_CTL       108
 #define SG2_S0_GPIO_RESET      82
 #define SG2_S0_GPIO_DETECT     53
@@ -38,6 +37,11 @@ static struct pcmcia_irqs irqs[] = {
        { 0, IRQ_GPIO(SG2_S0_GPIO_DETECT), "PCMCIA0 CD" },
 };
 
+static struct gpio sg2_pcmcia_gpios[] = {
+       { SG2_S0_GPIO_RESET, GPIOF_OUT_INIT_HIGH, "PCMCIA Reset" },
+       { SG2_S0_POWER_CTL, GPIOF_OUT_INIT_HIGH, "PCMCIA Power Ctrl" },
+};
+
 static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
        skt->socket.pci_irq = IRQ_GPIO(SG2_S0_GPIO_READY);
@@ -122,37 +126,23 @@ static int __init sg2_pcmcia_init(void)
        if (!sg2_pcmcia_device)
                return -ENOMEM;
 
-       ret = gpio_request(SG2_S0_BUFF_CTL, "SG2 CF buff ctl");
+       ret = gpio_request_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios));
        if (ret)
                goto error_put_platform_device;
-       ret = gpio_request(SG2_S0_POWER_CTL, "SG2 CF power ctl");
-       if (ret)
-               goto error_free_gpio_buff_ctl;
-       ret = gpio_request(SG2_S0_GPIO_RESET, "SG2 CF reset");
-       if (ret)
-               goto error_free_gpio_power_ctl;
-       /* Set gpio directions */
-       gpio_direction_output(SG2_S0_BUFF_CTL, 0);
-       gpio_direction_output(SG2_S0_POWER_CTL, 1);
-       gpio_direction_output(SG2_S0_GPIO_RESET, 1);
 
        ret = platform_device_add_data(sg2_pcmcia_device,
                                       &sg2_pcmcia_ops,
                                       sizeof(sg2_pcmcia_ops));
        if (ret)
-               goto error_free_gpio_reset;
+               goto error_free_gpios;
 
        ret = platform_device_add(sg2_pcmcia_device);
        if (ret)
-               goto error_free_gpio_reset;
+               goto error_free_gpios;
 
        return 0;
-error_free_gpio_reset:
-       gpio_free(SG2_S0_GPIO_RESET);
-error_free_gpio_power_ctl:
-       gpio_free(SG2_S0_POWER_CTL);
-error_free_gpio_buff_ctl:
-       gpio_free(SG2_S0_BUFF_CTL);
+error_free_gpios:
+       gpio_free_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios));
 error_put_platform_device:
        platform_device_put(sg2_pcmcia_device);
 
@@ -162,9 +152,7 @@ error_put_platform_device:
 static void __exit sg2_pcmcia_exit(void)
 {
        platform_device_unregister(sg2_pcmcia_device);
-       gpio_free(SG2_S0_BUFF_CTL);
-       gpio_free(SG2_S0_POWER_CTL);
-       gpio_free(SG2_S0_GPIO_RESET);
+       gpio_free_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios));
 }
 
 fs_initcall(sg2_pcmcia_init);
index a51f207..1064b1c 100644 (file)
@@ -136,22 +136,12 @@ static int viper_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
        return 0;
 }
 
-static void viper_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void viper_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
 static struct pcmcia_low_level viper_pcmcia_ops = {
        .owner                  = THIS_MODULE,
        .hw_init                = viper_pcmcia_hw_init,
        .hw_shutdown            = viper_pcmcia_hw_shutdown,
        .socket_state           = viper_pcmcia_socket_state,
        .configure_socket       = viper_pcmcia_configure_socket,
-       .socket_init            = viper_pcmcia_socket_init,
-       .socket_suspend         = viper_pcmcia_socket_suspend,
        .nr                     = 1,
 };
 
index 768f957..a0a9c2a 100644 (file)
@@ -186,8 +186,8 @@ static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock)
        struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
 
        debug(skt, 2, "initializing socket\n");
-
-       skt->ops->socket_init(skt);
+       if (skt->ops->socket_init)
+               skt->ops->socket_init(skt);
        return 0;
 }
 
@@ -207,7 +207,8 @@ static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock)
 
        debug(skt, 2, "suspending socket\n");
 
-       skt->ops->socket_suspend(skt);
+       if (skt->ops->socket_suspend)
+               skt->ops->socket_suspend(skt);
 
        return 0;
 }
index 45e0191..1e88d47 100644 (file)
@@ -769,4 +769,12 @@ config INTEL_OAKTRAIL
          enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y
          here; it will only load on supported platforms.
 
+config SAMSUNG_Q10
+       tristate "Samsung Q10 Extras"
+       depends on SERIO_I8042
+       select BACKLIGHT_CLASS_DEVICE
+       ---help---
+         This driver provides support for backlight control on Samsung Q10
+         and related laptops, including Dell Latitude X200.
+
 endif # X86_PLATFORM_DEVICES
index afc1f83..293a320 100644 (file)
@@ -44,3 +44,4 @@ obj-$(CONFIG_SAMSUNG_LAPTOP)  += samsung-laptop.o
 obj-$(CONFIG_MXM_WMI)          += mxm-wmi.o
 obj-$(CONFIG_INTEL_MID_POWER_BUTTON)   += intel_mid_powerbtn.o
 obj-$(CONFIG_INTEL_OAKTRAIL)   += intel_oaktrail.o
+obj-$(CONFIG_SAMSUNG_Q10)      += samsung-q10.o
index e1c4938..af2bb20 100644 (file)
@@ -99,6 +99,7 @@ enum acer_wmi_event_ids {
 static const struct key_entry acer_wmi_keymap[] = {
        {KE_KEY, 0x01, {KEY_WLAN} },     /* WiFi */
        {KE_KEY, 0x03, {KEY_WLAN} },     /* WiFi */
+       {KE_KEY, 0x04, {KEY_WLAN} },     /* WiFi */
        {KE_KEY, 0x12, {KEY_BLUETOOTH} },       /* BT */
        {KE_KEY, 0x21, {KEY_PROG1} },    /* Backup */
        {KE_KEY, 0x22, {KEY_PROG2} },    /* Arcade */
@@ -304,6 +305,10 @@ static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
        .wireless = 2,
 };
 
+static struct quirk_entry quirk_lenovo_ideapad_s205 = {
+       .wireless = 3,
+};
+
 /* The Aspire One has a dummy ACPI-WMI interface - disable it */
 static struct dmi_system_id __devinitdata acer_blacklist[] = {
        {
@@ -450,6 +455,15 @@ static struct dmi_system_id acer_quirks[] = {
                },
                .driver_data = &quirk_medion_md_98300,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "Lenovo Ideapad S205",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "10382LG"),
+               },
+               .driver_data = &quirk_lenovo_ideapad_s205,
+       },
        {}
 };
 
@@ -542,6 +556,12 @@ struct wmi_interface *iface)
                                return AE_ERROR;
                        *value = result & 0x1;
                        return AE_OK;
+               case 3:
+                       err = ec_read(0x78, &result);
+                       if (err)
+                               return AE_ERROR;
+                       *value = result & 0x1;
+                       return AE_OK;
                default:
                        err = ec_read(0xA, &result);
                        if (err)
@@ -1266,8 +1286,13 @@ static void acer_rfkill_update(struct work_struct *ignored)
        acpi_status status;
 
        status = get_u32(&state, ACER_CAP_WIRELESS);
-       if (ACPI_SUCCESS(status))
-               rfkill_set_sw_state(wireless_rfkill, !state);
+       if (ACPI_SUCCESS(status)) {
+               if (quirks->wireless == 3) {
+                       rfkill_set_hw_state(wireless_rfkill, !state);
+               } else {
+                       rfkill_set_sw_state(wireless_rfkill, !state);
+               }
+       }
 
        if (has_cap(ACER_CAP_BLUETOOTH)) {
                status = get_u32(&state, ACER_CAP_BLUETOOTH);
@@ -1400,6 +1425,9 @@ static ssize_t show_bool_threeg(struct device *dev,
 {
        u32 result; \
        acpi_status status;
+
+       pr_info("This threeg sysfs will be removed in 2012"
+               " - used by: %s\n", current->comm);
        if (wmi_has_guid(WMID_GUID3))
                status = wmid3_get_device_status(&result,
                                ACER_WMID3_GDS_THREEG);
@@ -1415,8 +1443,10 @@ static ssize_t set_bool_threeg(struct device *dev,
 {
        u32 tmp = simple_strtoul(buf, NULL, 10);
        acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
-               if (ACPI_FAILURE(status))
-                       return -EINVAL;
+       pr_info("This threeg sysfs will be removed in 2012"
+               " - used by: %s\n", current->comm);
+       if (ACPI_FAILURE(status))
+               return -EINVAL;
        return count;
 }
 static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
@@ -1425,6 +1455,8 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
 static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
        char *buf)
 {
+       pr_info("This interface sysfs will be removed in 2012"
+               " - used by: %s\n", current->comm);
        switch (interface->type) {
        case ACER_AMW0:
                return sprintf(buf, "AMW0\n");
index fca3489..760c6d7 100644 (file)
@@ -182,6 +182,7 @@ static const struct bios_settings_t bios_tbl[] = {
        {"Acer", "Aspire 1810T",  "v1.3308", 0x55, 0x58, {0x9e, 0x00} },
        {"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
        {"Acer", "Aspire 1810T",  "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
+       {"Acer", "Aspire 1810TZ", "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
        /* Acer 531 */
        {"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} },
        /* Gateway */
@@ -703,15 +704,15 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Peter Feuerer");
 MODULE_DESCRIPTION("Aspire One temperature and fan driver");
 MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
-MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1410*:");
-MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1810*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1410*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1810*:");
 MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:");
 MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
 MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMU*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMA*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnAOA*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOA*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMU*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMA*:");
 
 module_init(acerhdf_init);
 module_exit(acerhdf_exit);
index d65df92..fa6d7ec 100644 (file)
@@ -70,11 +70,10 @@ MODULE_LICENSE("GPL");
  * WAPF defines the behavior of the Fn+Fx wlan key
  * The significance of values is yet to be found, but
  * most of the time:
- * 0x0 will do nothing
- * 0x1 will allow to control the device with Fn+Fx key.
- * 0x4 will send an ACPI event (0x88) while pressing the Fn+Fx key
- * 0x5 like 0x1 or 0x4
- * So, if something doesn't work as you want, just try other values =)
+ * Bit | Bluetooth | WLAN
+ *  0  | Hardware  | Hardware
+ *  1  | Hardware  | Software
+ *  4  | Software  | Software
  */
 static uint wapf = 1;
 module_param(wapf, uint, 0444);
index 0580d99..b0859d4 100644 (file)
@@ -38,6 +38,24 @@ MODULE_LICENSE("GPL");
 
 MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID);
 
+/*
+ * WAPF defines the behavior of the Fn+Fx wlan key
+ * The significance of values is yet to be found, but
+ * most of the time:
+ * Bit | Bluetooth | WLAN
+ *  0  | Hardware  | Hardware
+ *  1  | Hardware  | Software
+ *  4  | Software  | Software
+ */
+static uint wapf;
+module_param(wapf, uint, 0444);
+MODULE_PARM_DESC(wapf, "WAPF value");
+
+static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
+{
+       driver->wapf = wapf;
+}
+
 static const struct key_entry asus_nb_wmi_keymap[] = {
        { KE_KEY, 0x30, { KEY_VOLUMEUP } },
        { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
@@ -53,16 +71,16 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
        { KE_KEY, 0x51, { KEY_WWW } },
        { KE_KEY, 0x55, { KEY_CALC } },
        { KE_KEY, 0x5C, { KEY_F15 } },  /* Power Gear key */
-       { KE_KEY, 0x5D, { KEY_WLAN } },
-       { KE_KEY, 0x5E, { KEY_WLAN } },
-       { KE_KEY, 0x5F, { KEY_WLAN } },
+       { KE_KEY, 0x5D, { KEY_WLAN } }, /* Wireless console Toggle */
+       { KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */
+       { KE_KEY, 0x5F, { KEY_WLAN } }, /* Wireless console Disable */
        { KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
        { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
        { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
        { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
        { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } },
-       { KE_KEY, 0x7E, { KEY_BLUETOOTH } },
        { KE_KEY, 0x7D, { KEY_BLUETOOTH } },
+       { KE_KEY, 0x7E, { KEY_BLUETOOTH } },
        { KE_KEY, 0x82, { KEY_CAMERA } },
        { KE_KEY, 0x88, { KEY_RFKILL  } },
        { KE_KEY, 0x8A, { KEY_PROG1 } },
@@ -81,6 +99,7 @@ static struct asus_wmi_driver asus_nb_wmi_driver = {
        .keymap = asus_nb_wmi_keymap,
        .input_name = "Asus WMI hotkeys",
        .input_phys = ASUS_NB_WMI_FILE "/input0",
+       .quirks = asus_nb_wmi_quirks,
 };
 
 
index 65b66aa..95cba9e 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/platform_device.h>
+#include <linux/thermal.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -66,6 +67,8 @@ MODULE_LICENSE("GPL");
 #define NOTIFY_BRNUP_MAX               0x1f
 #define NOTIFY_BRNDOWN_MIN             0x20
 #define NOTIFY_BRNDOWN_MAX             0x2e
+#define NOTIFY_KBD_BRTUP               0xc4
+#define NOTIFY_KBD_BRTDWN              0xc5
 
 /* WMI Methods */
 #define ASUS_WMI_METHODID_SPEC         0x43455053 /* BIOS SPECification */
@@ -93,6 +96,7 @@ MODULE_LICENSE("GPL");
 /* Wireless */
 #define ASUS_WMI_DEVID_HW_SWITCH       0x00010001
 #define ASUS_WMI_DEVID_WIRELESS_LED    0x00010002
+#define ASUS_WMI_DEVID_CWAP            0x00010003
 #define ASUS_WMI_DEVID_WLAN            0x00010011
 #define ASUS_WMI_DEVID_BLUETOOTH       0x00010013
 #define ASUS_WMI_DEVID_GPS             0x00010015
@@ -102,6 +106,12 @@ MODULE_LICENSE("GPL");
 
 /* Leds */
 /* 0x000200XX and 0x000400XX */
+#define ASUS_WMI_DEVID_LED1            0x00020011
+#define ASUS_WMI_DEVID_LED2            0x00020012
+#define ASUS_WMI_DEVID_LED3            0x00020013
+#define ASUS_WMI_DEVID_LED4            0x00020014
+#define ASUS_WMI_DEVID_LED5            0x00020015
+#define ASUS_WMI_DEVID_LED6            0x00020016
 
 /* Backlight and Brightness */
 #define ASUS_WMI_DEVID_BACKLIGHT       0x00050011
@@ -174,13 +184,18 @@ struct asus_wmi {
 
        struct led_classdev tpd_led;
        int tpd_led_wk;
+       struct led_classdev kbd_led;
+       int kbd_led_wk;
        struct workqueue_struct *led_workqueue;
        struct work_struct tpd_led_work;
+       struct work_struct kbd_led_work;
 
        struct asus_rfkill wlan;
        struct asus_rfkill bluetooth;
        struct asus_rfkill wimax;
        struct asus_rfkill wwan3g;
+       struct asus_rfkill gps;
+       struct asus_rfkill uwb;
 
        struct hotplug_slot *hotplug_slot;
        struct mutex hotplug_lock;
@@ -205,6 +220,7 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
        asus->inputdev->phys = asus->driver->input_phys;
        asus->inputdev->id.bustype = BUS_HOST;
        asus->inputdev->dev.parent = &asus->platform_device->dev;
+       set_bit(EV_REP, asus->inputdev->evbit);
 
        err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL);
        if (err)
@@ -359,30 +375,80 @@ static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
        return read_tpd_led_state(asus);
 }
 
-static int asus_wmi_led_init(struct asus_wmi *asus)
+static void kbd_led_update(struct work_struct *work)
 {
-       int rv;
+       int ctrl_param = 0;
+       struct asus_wmi *asus;
 
-       if (read_tpd_led_state(asus) < 0)
-               return 0;
+       asus = container_of(work, struct asus_wmi, kbd_led_work);
 
-       asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
-       if (!asus->led_workqueue)
-               return -ENOMEM;
-       INIT_WORK(&asus->tpd_led_work, tpd_led_update);
+       /*
+        * bits 0-2: level
+        * bit 7: light on/off
+        */
+       if (asus->kbd_led_wk > 0)
+               ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
 
-       asus->tpd_led.name = "asus::touchpad";
-       asus->tpd_led.brightness_set = tpd_led_set;
-       asus->tpd_led.brightness_get = tpd_led_get;
-       asus->tpd_led.max_brightness = 1;
+       asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
+}
 
-       rv = led_classdev_register(&asus->platform_device->dev, &asus->tpd_led);
-       if (rv) {
-               destroy_workqueue(asus->led_workqueue);
-               return rv;
+static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
+{
+       int retval;
+
+       /*
+        * bits 0-2: level
+        * bit 7: light on/off
+        * bit 8-10: environment (0: dark, 1: normal, 2: light)
+        * bit 17: status unknown
+        */
+       retval = asus_wmi_get_devstate_bits(asus, ASUS_WMI_DEVID_KBD_BACKLIGHT,
+                                           0xFFFF);
+
+       /* Unknown status is considered as off */
+       if (retval == 0x8000)
+               retval = 0;
+
+       if (retval >= 0) {
+               if (level)
+                       *level = retval & 0x80 ? retval & 0x7F : 0;
+               if (env)
+                       *env = (retval >> 8) & 0x7F;
+               retval = 0;
        }
 
-       return 0;
+       return retval;
+}
+
+static void kbd_led_set(struct led_classdev *led_cdev,
+                       enum led_brightness value)
+{
+       struct asus_wmi *asus;
+
+       asus = container_of(led_cdev, struct asus_wmi, kbd_led);
+
+       if (value > asus->kbd_led.max_brightness)
+               value = asus->kbd_led.max_brightness;
+       else if (value < 0)
+               value = 0;
+
+       asus->kbd_led_wk = value;
+       queue_work(asus->led_workqueue, &asus->kbd_led_work);
+}
+
+static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
+{
+       struct asus_wmi *asus;
+       int retval, value;
+
+       asus = container_of(led_cdev, struct asus_wmi, kbd_led);
+
+       retval = kbd_led_read(asus, &value, NULL);
+
+       if (retval < 0)
+               return retval;
+
+       return value;
 }
 
 static void asus_wmi_led_exit(struct asus_wmi *asus)
@@ -393,6 +459,48 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
                destroy_workqueue(asus->led_workqueue);
 }
 
+static int asus_wmi_led_init(struct asus_wmi *asus)
+{
+       int rv = 0;
+
+       asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
+       if (!asus->led_workqueue)
+               return -ENOMEM;
+
+       if (read_tpd_led_state(asus) >= 0) {
+               INIT_WORK(&asus->tpd_led_work, tpd_led_update);
+
+               asus->tpd_led.name = "asus::touchpad";
+               asus->tpd_led.brightness_set = tpd_led_set;
+               asus->tpd_led.brightness_get = tpd_led_get;
+               asus->tpd_led.max_brightness = 1;
+
+               rv = led_classdev_register(&asus->platform_device->dev,
+                                          &asus->tpd_led);
+               if (rv)
+                       goto error;
+       }
+
+       if (kbd_led_read(asus, NULL, NULL) >= 0) {
+               INIT_WORK(&asus->kbd_led_work, kbd_led_update);
+
+               asus->kbd_led.name = "asus::kbd_backlight";
+               asus->kbd_led.brightness_set = kbd_led_set;
+               asus->kbd_led.brightness_get = kbd_led_get;
+               asus->kbd_led.max_brightness = 3;
+
+               rv = led_classdev_register(&asus->platform_device->dev,
+                                          &asus->kbd_led);
+       }
+
+error:
+       if (rv)
+               asus_wmi_led_exit(asus);
+
+       return rv;
+}
+
+
 /*
  * PCI hotplug (for wlan rfkill)
  */
@@ -729,6 +837,16 @@ static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
                rfkill_destroy(asus->wwan3g.rfkill);
                asus->wwan3g.rfkill = NULL;
        }
+       if (asus->gps.rfkill) {
+               rfkill_unregister(asus->gps.rfkill);
+               rfkill_destroy(asus->gps.rfkill);
+               asus->gps.rfkill = NULL;
+       }
+       if (asus->uwb.rfkill) {
+               rfkill_unregister(asus->uwb.rfkill);
+               rfkill_destroy(asus->uwb.rfkill);
+               asus->uwb.rfkill = NULL;
+       }
 }
 
 static int asus_wmi_rfkill_init(struct asus_wmi *asus)
@@ -763,6 +881,18 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus)
        if (result && result != -ENODEV)
                goto exit;
 
+       result = asus_new_rfkill(asus, &asus->gps, "asus-gps",
+                                RFKILL_TYPE_GPS, ASUS_WMI_DEVID_GPS);
+
+       if (result && result != -ENODEV)
+               goto exit;
+
+       result = asus_new_rfkill(asus, &asus->uwb, "asus-uwb",
+                                RFKILL_TYPE_UWB, ASUS_WMI_DEVID_UWB);
+
+       if (result && result != -ENODEV)
+               goto exit;
+
        if (!asus->driver->hotplug_wireless)
                goto exit;
 
@@ -797,8 +927,8 @@ exit:
  * Hwmon device
  */
 static ssize_t asus_hwmon_pwm1(struct device *dev,
-                           struct device_attribute *attr,
-                           char *buf)
+                              struct device_attribute *attr,
+                              char *buf)
 {
        struct asus_wmi *asus = dev_get_drvdata(dev);
        u32 value;
@@ -809,7 +939,7 @@ static ssize_t asus_hwmon_pwm1(struct device *dev,
        if (err < 0)
                return err;
 
-       value |= 0xFF;
+       value &= 0xFF;
 
        if (value == 1) /* Low Speed */
                value = 85;
@@ -825,7 +955,26 @@ static ssize_t asus_hwmon_pwm1(struct device *dev,
        return sprintf(buf, "%d\n", value);
 }
 
+static ssize_t asus_hwmon_temp1(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct asus_wmi *asus = dev_get_drvdata(dev);
+       u32 value;
+       int err;
+
+       err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_THERMAL_CTRL, &value);
+
+       if (err < 0)
+               return err;
+
+       value = KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000;
+
+       return sprintf(buf, "%d\n", value);
+}
+
 static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL, 0);
 
 static ssize_t
 show_name(struct device *dev, struct device_attribute *attr, char *buf)
@@ -836,12 +985,13 @@ static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
 
 static struct attribute *hwmon_attributes[] = {
        &sensor_dev_attr_pwm1.dev_attr.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_name.dev_attr.attr,
        NULL
 };
 
 static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
-                                   struct attribute *attr, int idx)
+                                         struct attribute *attr, int idx)
 {
        struct device *dev = container_of(kobj, struct device, kobj);
        struct platform_device *pdev = to_platform_device(dev->parent);
@@ -852,6 +1002,8 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
 
        if (attr == &sensor_dev_attr_pwm1.dev_attr.attr)
                dev_id = ASUS_WMI_DEVID_FAN_CTRL;
+       else if (attr == &sensor_dev_attr_temp1_input.dev_attr.attr)
+               dev_id = ASUS_WMI_DEVID_THERMAL_CTRL;
 
        if (dev_id != -1) {
                int err = asus_wmi_get_devstate(asus, dev_id, &value);
@@ -869,9 +1021,13 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
                 * - reverved bits are non-zero
                 * - sfun and presence bit are not set
                 */
-               if (value != ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
+               if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
                    || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
                        ok = false;
+       } else if (dev_id == ASUS_WMI_DEVID_THERMAL_CTRL) {
+               /* If value is zero, something is clearly wrong */
+               if (value == 0)
+                       ok = false;
        }
 
        return ok ? attr->mode : 0;
@@ -904,6 +1060,7 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus)
                pr_err("Could not register asus hwmon device\n");
                return PTR_ERR(hwmon);
        }
+       dev_set_drvdata(hwmon, asus);
        asus->hwmon_device = hwmon;
        result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group);
        if (result)
@@ -1060,6 +1217,8 @@ static void asus_wmi_notify(u32 value, void *context)
        acpi_status status;
        int code;
        int orig_code;
+       unsigned int key_value = 1;
+       bool autorelease = 1;
 
        status = wmi_get_event_data(value, &response);
        if (status != AE_OK) {
@@ -1075,6 +1234,13 @@ static void asus_wmi_notify(u32 value, void *context)
        code = obj->integer.value;
        orig_code = code;
 
+       if (asus->driver->key_filter) {
+               asus->driver->key_filter(asus->driver, &code, &key_value,
+                                        &autorelease);
+               if (code == ASUS_WMI_KEY_IGNORE)
+                       goto exit;
+       }
+
        if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
                code = NOTIFY_BRNUP_MIN;
        else if (code >= NOTIFY_BRNDOWN_MIN &&
@@ -1084,7 +1250,8 @@ static void asus_wmi_notify(u32 value, void *context)
        if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
                if (!acpi_video_backlight_support())
                        asus_wmi_backlight_notify(asus, orig_code);
-       } else if (!sparse_keymap_report_event(asus->inputdev, code, 1, true))
+       } else if (!sparse_keymap_report_event(asus->inputdev, code,
+                                              key_value, autorelease))
                pr_info("Unknown key %x pressed\n", code);
 
 exit:
@@ -1164,14 +1331,18 @@ ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
 static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
                           const char *buf, size_t count)
 {
-       int value;
+       int value, rv;
 
        if (!count || sscanf(buf, "%i", &value) != 1)
                return -EINVAL;
        if (value < 0 || value > 2)
                return -EINVAL;
 
-       return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
+       rv = asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
+       if (rv < 0)
+               return rv;
+
+       return count;
 }
 
 static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
@@ -1234,7 +1405,7 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
 
        /* We don't know yet what to do with this version... */
        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {
-               pr_info("BIOS WMI version: %d.%d", rv >> 8, rv & 0xFF);
+               pr_info("BIOS WMI version: %d.%d", rv >> 16, rv & 0xFF);
                asus->spec = rv;
        }
 
@@ -1266,6 +1437,12 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
                return -ENODEV;
        }
 
+       /* CWAP allow to define the behavior of the Fn+F2 key,
+        * this method doesn't seems to be present on Eee PCs */
+       if (asus->driver->wapf >= 0)
+               asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
+                                     asus->driver->wapf, NULL);
+
        return asus_wmi_sysfs_init(asus->platform_device);
 }
 
@@ -1568,6 +1745,14 @@ static int asus_hotk_restore(struct device *device)
                bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
                rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
        }
+       if (asus->gps.rfkill) {
+               bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPS);
+               rfkill_set_sw_state(asus->gps.rfkill, bl);
+       }
+       if (asus->uwb.rfkill) {
+               bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_UWB);
+               rfkill_set_sw_state(asus->uwb.rfkill, bl);
+       }
 
        return 0;
 }
@@ -1604,7 +1789,7 @@ static int asus_wmi_probe(struct platform_device *pdev)
 
 static bool used;
 
-int asus_wmi_register_driver(struct asus_wmi_driver *driver)
+int __init_or_module asus_wmi_register_driver(struct asus_wmi_driver *driver)
 {
        struct platform_driver *platform_driver;
        struct platform_device *platform_device;
index c044522..8147c10 100644 (file)
 
 #include <linux/platform_device.h>
 
+#define ASUS_WMI_KEY_IGNORE (-1)
+
 struct module;
 struct key_entry;
 struct asus_wmi;
 
 struct asus_wmi_driver {
        bool                    hotplug_wireless;
+       int                     wapf;
 
        const char              *name;
        struct module           *owner;
@@ -44,6 +47,10 @@ struct asus_wmi_driver {
        const struct key_entry  *keymap;
        const char              *input_name;
        const char              *input_phys;
+       /* Returns new code, value, and autorelease values in arguments.
+        * Return ASUS_WMI_KEY_IGNORE in code if event should be ignored. */
+       void (*key_filter) (struct asus_wmi_driver *driver, int *code,
+                           unsigned int *value, bool *autorelease);
 
        int (*probe) (struct platform_device *device);
        void (*quirks) (struct asus_wmi_driver *driver);
index e39ab1d..f31fa4e 100644 (file)
@@ -612,7 +612,6 @@ static int __init dell_init(void)
        if (!bufferpage)
                goto fail_buffer;
        buffer = page_address(bufferpage);
-       mutex_init(&buffer_mutex);
 
        ret = dell_setup_rfkill();
 
index ce79082..fa9a217 100644 (file)
@@ -54,6 +54,8 @@ MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
  */
 
 static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
+       { KE_IGNORE, 0x003a, { KEY_CAPSLOCK } },
+
        { KE_KEY, 0xe045, { KEY_PROG1 } },
        { KE_KEY, 0xe009, { KEY_EJECTCD } },
 
@@ -85,6 +87,11 @@ static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
        { KE_IGNORE, 0xe013, { KEY_RESERVED } },
 
        { KE_IGNORE, 0xe020, { KEY_MUTE } },
+
+       /* Shortcut and audio panel keys */
+       { KE_IGNORE, 0xe025, { KEY_RESERVED } },
+       { KE_IGNORE, 0xe026, { KEY_RESERVED } },
+
        { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
        { KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
        { KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
@@ -92,6 +99,9 @@ static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
        { KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
        { KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
        { KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
+       { KE_IGNORE, 0xe0f7, { KEY_MUTE } },
+       { KE_IGNORE, 0xe0f8, { KEY_VOLUMEDOWN } },
+       { KE_IGNORE, 0xe0f9, { KEY_VOLUMEUP } },
        { KE_END, 0 }
 };
 
index 4aa867a..9f6e643 100644 (file)
@@ -56,6 +56,11 @@ MODULE_PARM_DESC(hotplug_wireless,
                 "If your laptop needs that, please report to "
                 "acpi4asus-user@lists.sourceforge.net.");
 
+/* Values for T101MT "Home" key */
+#define HOME_PRESS     0xe4
+#define HOME_HOLD      0xea
+#define HOME_RELEASE   0xe5
+
 static const struct key_entry eeepc_wmi_keymap[] = {
        /* Sleep already handled via generic ACPI code */
        { KE_KEY, 0x30, { KEY_VOLUMEUP } },
@@ -71,6 +76,7 @@ static const struct key_entry eeepc_wmi_keymap[] = {
        { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
        { KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */
        { KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */
+       { KE_KEY, HOME_PRESS, { KEY_CONFIG } }, /* Home/Express gate key */
        { KE_KEY, 0xe8, { KEY_SCREENLOCK } },
        { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } },
        { KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } },
@@ -81,6 +87,25 @@ static const struct key_entry eeepc_wmi_keymap[] = {
        { KE_END, 0},
 };
 
+static void eeepc_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
+                                unsigned int *value, bool *autorelease)
+{
+       switch (*code) {
+       case HOME_PRESS:
+               *value = 1;
+               *autorelease = 0;
+               break;
+       case HOME_HOLD:
+               *code = ASUS_WMI_KEY_IGNORE;
+               break;
+       case HOME_RELEASE:
+               *code = HOME_PRESS;
+               *value = 0;
+               *autorelease = 0;
+               break;
+       }
+}
+
 static acpi_status eeepc_wmi_parse_device(acpi_handle handle, u32 level,
                                                 void *context, void **retval)
 {
@@ -141,6 +166,7 @@ static void eeepc_dmi_check(struct asus_wmi_driver *driver)
 static void eeepc_wmi_quirks(struct asus_wmi_driver *driver)
 {
        driver->hotplug_wireless = hotplug_wireless;
+       driver->wapf = -1;
        eeepc_dmi_check(driver);
 }
 
@@ -151,6 +177,7 @@ static struct asus_wmi_driver asus_wmi_driver = {
        .keymap = eeepc_wmi_keymap,
        .input_name = "Eee PC WMI hotkeys",
        .input_phys = EEEPC_WMI_FILE "/input0",
+       .key_filter = eeepc_wmi_key_filter,
        .probe = eeepc_wmi_probe,
        .quirks = eeepc_wmi_quirks,
 };
index bfdda33..0c59541 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
 
 #define IDEAPAD_RFKILL_DEV_NUM (3)
 
+#define CFG_BT_BIT     (16)
+#define CFG_3G_BIT     (17)
+#define CFG_WIFI_BIT   (18)
+#define CFG_CAMERA_BIT (19)
+
 struct ideapad_private {
        struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
        struct platform_device *platform_device;
        struct input_dev *inputdev;
+       struct backlight_device *blightdev;
+       unsigned long cfg;
 };
 
 static acpi_handle ideapad_handle;
@@ -155,7 +164,7 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
 }
 
 /*
- * camera power
+ * sysfs
  */
 static ssize_t show_ideapad_cam(struct device *dev,
                                struct device_attribute *attr,
@@ -186,6 +195,44 @@ static ssize_t store_ideapad_cam(struct device *dev,
 
 static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
 
+static ssize_t show_ideapad_cfg(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct ideapad_private *priv = dev_get_drvdata(dev);
+
+       return sprintf(buf, "0x%.8lX\n", priv->cfg);
+}
+
+static DEVICE_ATTR(cfg, 0444, show_ideapad_cfg, NULL);
+
+static struct attribute *ideapad_attributes[] = {
+       &dev_attr_camera_power.attr,
+       &dev_attr_cfg.attr,
+       NULL
+};
+
+static mode_t ideapad_is_visible(struct kobject *kobj,
+                                struct attribute *attr,
+                                int idx)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct ideapad_private *priv = dev_get_drvdata(dev);
+       bool supported;
+
+       if (attr == &dev_attr_camera_power.attr)
+               supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
+       else
+               supported = true;
+
+       return supported ? attr->mode : 0;
+}
+
+static struct attribute_group ideapad_attribute_group = {
+       .is_visible = ideapad_is_visible,
+       .attrs = ideapad_attributes
+};
+
 /*
  * Rfkill
  */
@@ -197,9 +244,9 @@ struct ideapad_rfk_data {
 };
 
 const struct ideapad_rfk_data ideapad_rfk_data[] = {
-       { "ideapad_wlan",       18, 0x15, RFKILL_TYPE_WLAN },
-       { "ideapad_bluetooth",  16, 0x17, RFKILL_TYPE_BLUETOOTH },
-       { "ideapad_3g",         17, 0x20, RFKILL_TYPE_WWAN },
+       { "ideapad_wlan",      CFG_WIFI_BIT, 0x15, RFKILL_TYPE_WLAN },
+       { "ideapad_bluetooth", CFG_BT_BIT,   0x17, RFKILL_TYPE_BLUETOOTH },
+       { "ideapad_3g",        CFG_3G_BIT,   0x20, RFKILL_TYPE_WWAN },
 };
 
 static int ideapad_rfk_set(void *data, bool blocked)
@@ -265,8 +312,7 @@ static int __devinit ideapad_register_rfkill(struct acpi_device *adevice,
        return 0;
 }
 
-static void __devexit ideapad_unregister_rfkill(struct acpi_device *adevice,
-                                               int dev)
+static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
 {
        struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
 
@@ -280,15 +326,6 @@ static void __devexit ideapad_unregister_rfkill(struct acpi_device *adevice,
 /*
  * Platform device
  */
-static struct attribute *ideapad_attributes[] = {
-       &dev_attr_camera_power.attr,
-       NULL
-};
-
-static struct attribute_group ideapad_attribute_group = {
-       .attrs = ideapad_attributes
-};
-
 static int __devinit ideapad_platform_init(struct ideapad_private *priv)
 {
        int result;
@@ -369,7 +406,7 @@ err_free_dev:
        return error;
 }
 
-static void __devexit ideapad_input_exit(struct ideapad_private *priv)
+static void ideapad_input_exit(struct ideapad_private *priv)
 {
        sparse_keymap_free(priv->inputdev);
        input_unregister_device(priv->inputdev);
@@ -382,6 +419,98 @@ static void ideapad_input_report(struct ideapad_private *priv,
        sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
 }
 
+/*
+ * backlight
+ */
+static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
+{
+       unsigned long now;
+
+       if (read_ec_data(ideapad_handle, 0x12, &now))
+               return -EIO;
+       return now;
+}
+
+static int ideapad_backlight_update_status(struct backlight_device *blightdev)
+{
+       if (write_ec_cmd(ideapad_handle, 0x13, blightdev->props.brightness))
+               return -EIO;
+       if (write_ec_cmd(ideapad_handle, 0x33,
+                        blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
+               return -EIO;
+
+       return 0;
+}
+
+static const struct backlight_ops ideapad_backlight_ops = {
+       .get_brightness = ideapad_backlight_get_brightness,
+       .update_status = ideapad_backlight_update_status,
+};
+
+static int ideapad_backlight_init(struct ideapad_private *priv)
+{
+       struct backlight_device *blightdev;
+       struct backlight_properties props;
+       unsigned long max, now, power;
+
+       if (read_ec_data(ideapad_handle, 0x11, &max))
+               return -EIO;
+       if (read_ec_data(ideapad_handle, 0x12, &now))
+               return -EIO;
+       if (read_ec_data(ideapad_handle, 0x18, &power))
+               return -EIO;
+
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.max_brightness = max;
+       props.type = BACKLIGHT_PLATFORM;
+       blightdev = backlight_device_register("ideapad",
+                                             &priv->platform_device->dev,
+                                             priv,
+                                             &ideapad_backlight_ops,
+                                             &props);
+       if (IS_ERR(blightdev)) {
+               pr_err("Could not register backlight device\n");
+               return PTR_ERR(blightdev);
+       }
+
+       priv->blightdev = blightdev;
+       blightdev->props.brightness = now;
+       blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+       backlight_update_status(blightdev);
+
+       return 0;
+}
+
+static void ideapad_backlight_exit(struct ideapad_private *priv)
+{
+       if (priv->blightdev)
+               backlight_device_unregister(priv->blightdev);
+       priv->blightdev = NULL;
+}
+
+static void ideapad_backlight_notify_power(struct ideapad_private *priv)
+{
+       unsigned long power;
+       struct backlight_device *blightdev = priv->blightdev;
+
+       if (read_ec_data(ideapad_handle, 0x18, &power))
+               return;
+       blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+}
+
+static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
+{
+       unsigned long now;
+
+       /* if we control brightness via acpi video driver */
+       if (priv->blightdev == NULL) {
+               read_ec_data(ideapad_handle, 0x12, &now);
+               return;
+       }
+
+       backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);
+}
+
 /*
  * module init/exit
  */
@@ -393,10 +522,11 @@ MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
 
 static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
 {
-       int ret, i, cfg;
+       int ret, i;
+       unsigned long cfg;
        struct ideapad_private *priv;
 
-       if (read_method_int(adevice->handle, "_CFG", &cfg))
+       if (read_method_int(adevice->handle, "_CFG", (int *)&cfg))
                return -ENODEV;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -404,6 +534,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
                return -ENOMEM;
        dev_set_drvdata(&adevice->dev, priv);
        ideapad_handle = adevice->handle;
+       priv->cfg = cfg;
 
        ret = ideapad_platform_init(priv);
        if (ret)
@@ -414,15 +545,25 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
                goto input_failed;
 
        for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
-               if (test_bit(ideapad_rfk_data[i].cfgbit, (unsigned long *)&cfg))
+               if (test_bit(ideapad_rfk_data[i].cfgbit, &cfg))
                        ideapad_register_rfkill(adevice, i);
                else
                        priv->rfk[i] = NULL;
        }
        ideapad_sync_rfk_state(adevice);
 
+       if (!acpi_video_backlight_support()) {
+               ret = ideapad_backlight_init(priv);
+               if (ret && ret != -ENODEV)
+                       goto backlight_failed;
+       }
+
        return 0;
 
+backlight_failed:
+       for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
+               ideapad_unregister_rfkill(adevice, i);
+       ideapad_input_exit(priv);
 input_failed:
        ideapad_platform_exit(priv);
 platform_failed:
@@ -435,6 +576,7 @@ static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type)
        struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
        int i;
 
+       ideapad_backlight_exit(priv);
        for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
                ideapad_unregister_rfkill(adevice, i);
        ideapad_input_exit(priv);
@@ -459,12 +601,19 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
        vpc1 = (vpc2 << 8) | vpc1;
        for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
                if (test_bit(vpc_bit, &vpc1)) {
-                       if (vpc_bit == 9)
+                       switch (vpc_bit) {
+                       case 9:
                                ideapad_sync_rfk_state(adevice);
-                       else if (vpc_bit == 4)
-                               read_ec_data(handle, 0x12, &vpc2);
-                       else
+                               break;
+                       case 4:
+                               ideapad_backlight_notify_brightness(priv);
+                               break;
+                       case 2:
+                               ideapad_backlight_notify_power(priv);
+                               break;
+                       default:
                                ideapad_input_report(priv, vpc_bit);
+                       }
                }
        }
 }
index 5ffe7c3..809a3ae 100644 (file)
@@ -403,7 +403,7 @@ static void ips_cpu_raise(struct ips_driver *ips)
 
        thm_writew(THM_MPCPC, (new_tdp_limit * 10) / 8);
 
-       turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN;
+       turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDP_OVR_EN;
        wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
 
        turbo_override &= ~TURBO_TDP_MASK;
@@ -438,7 +438,7 @@ static void ips_cpu_lower(struct ips_driver *ips)
 
        thm_writew(THM_MPCPC, (new_limit * 10) / 8);
 
-       turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN;
+       turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDP_OVR_EN;
        wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
 
        turbo_override &= ~TURBO_TDP_MASK;
index 809adea..abddc83 100644 (file)
@@ -477,6 +477,8 @@ static acpi_status intel_menlow_register_sensor(acpi_handle handle, u32 lvl,
                return AE_ERROR;
        }
 
+       return AE_OK;
+
  aux1_not_found:
        if (status == AE_NOT_FOUND)
                return AE_OK;
index 3a57832..ccd7b1f 100644 (file)
@@ -493,20 +493,30 @@ static int mid_thermal_probe(struct platform_device *pdev)
 
        /* Register each sensor with the generic thermal framework*/
        for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
+               struct thermal_device_info *td_info = initialize_sensor(i);
+
+               if (!td_info) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
                pinfo->tzd[i] = thermal_zone_device_register(name[i],
-                               0, initialize_sensor(i), &tzd_ops, 0, 0, 0, 0);
-               if (IS_ERR(pinfo->tzd[i]))
-                       goto reg_fail;
+                               0, td_info, &tzd_ops, 0, 0, 0, 0);
+               if (IS_ERR(pinfo->tzd[i])) {
+                       kfree(td_info);
+                       ret = PTR_ERR(pinfo->tzd[i]);
+                       goto err;
+               }
        }
 
        pinfo->pdev = pdev;
        platform_set_drvdata(pdev, pinfo);
        return 0;
 
-reg_fail:
-       ret = PTR_ERR(pinfo->tzd[i]);
-       while (--i >= 0)
+err:
+       while (--i >= 0) {
+               kfree(pinfo->tzd[i]->devdata);
                thermal_zone_device_unregister(pinfo->tzd[i]);
+       }
        configure_adc(0);
        kfree(pinfo);
        return ret;
@@ -524,8 +534,10 @@ static int mid_thermal_remove(struct platform_device *pdev)
        int i;
        struct platform_info *pinfo = platform_get_drvdata(pdev);
 
-       for (i = 0; i < MSIC_THERMAL_SENSORS; i++)
+       for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
+               kfree(pinfo->tzd[i]->devdata);
                thermal_zone_device_unregister(pinfo->tzd[i]);
+       }
 
        kfree(pinfo);
        platform_set_drvdata(pdev, NULL);
index bde47e9..c8a6aed 100644 (file)
@@ -637,15 +637,13 @@ end_function:
        return error;
 }
 
-const struct pci_device_id rar_pci_id_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(rar_pci_id_tbl) = {
        { PCI_VDEVICE(INTEL, 0x4110) },
        { 0 }
 };
 
 MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl);
 
-const struct pci_device_id *my_id_table = rar_pci_id_tbl;
-
 /* field for registering driver to PCI device */
 static struct pci_driver rar_pci_driver = {
        .name = "rar_register_driver",
index 940accb..c866653 100644 (file)
@@ -725,7 +725,7 @@ static void ipc_remove(struct pci_dev *pdev)
        intel_scu_devices_destroy();
 }
 
-static const struct pci_device_id pci_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080e)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)},
        { 0,}
index 3ff629d..f204643 100644 (file)
@@ -538,6 +538,15 @@ static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = {
                },
                .callback = dmi_check_cb
        },
+       {
+               .ident = "MSI U270",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                               "Micro-Star International Co., Ltd."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "U270 series"),
+               },
+               .callback = dmi_check_cb
+       },
        { }
 };
 
@@ -996,3 +1005,4 @@ MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N034:*");
 MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N051:*");
 MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N014:*");
 MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnCR620:*");
+MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnU270series:*");
index c832e33..6f40bf2 100644 (file)
@@ -272,6 +272,7 @@ static int __init msi_wmi_init(void)
 err_free_backlight:
        backlight_device_unregister(backlight);
 err_free_input:
+       sparse_keymap_free(msi_wmi_input_dev);
        input_unregister_device(msi_wmi_input_dev);
 err_uninstall_notifier:
        wmi_remove_notify_handler(MSIWMI_EVENT_GUID);
index d347116..3591630 100644 (file)
@@ -520,6 +520,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
                },
                .callback = dmi_check_cb,
        },
+       {
+               .ident = "N510",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N510"),
+                       DMI_MATCH(DMI_BOARD_NAME, "N510"),
+               },
+               .callback = dmi_check_cb,
+       },
        {
                .ident = "X125",
                .matches = {
@@ -600,6 +610,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
                },
                .callback = dmi_check_cb,
        },
+       {
+               .ident = "N150/N210/N220",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
+                       DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
+               },
+               .callback = dmi_check_cb,
+       },
        {
                .ident = "N150/N210/N220/N230",
                .matches = {
diff --git a/drivers/platform/x86/samsung-q10.c b/drivers/platform/x86/samsung-q10.c
new file mode 100644 (file)
index 0000000..1e54ae7
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ *  Driver for Samsung Q10 and related laptops: controls the backlight
+ *
+ *  Copyright (c) 2011 Frederick van der Wyck <fvanderwyck@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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/backlight.h>
+#include <linux/i8042.h>
+#include <linux/dmi.h>
+
+#define SAMSUNGQ10_BL_MAX_INTENSITY      255
+#define SAMSUNGQ10_BL_DEFAULT_INTENSITY  185
+
+#define SAMSUNGQ10_BL_8042_CMD           0xbe
+#define SAMSUNGQ10_BL_8042_DATA          { 0x89, 0x91 }
+
+static int samsungq10_bl_brightness;
+
+static bool force;
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force,
+               "Disable the DMI check and force the driver to be loaded");
+
+static int samsungq10_bl_set_intensity(struct backlight_device *bd)
+{
+
+       int brightness = bd->props.brightness;
+       unsigned char c[3] = SAMSUNGQ10_BL_8042_DATA;
+
+       c[2] = (unsigned char)brightness;
+       i8042_lock_chip();
+       i8042_command(c, (0x30 << 8) | SAMSUNGQ10_BL_8042_CMD);
+       i8042_unlock_chip();
+       samsungq10_bl_brightness = brightness;
+
+       return 0;
+}
+
+static int samsungq10_bl_get_intensity(struct backlight_device *bd)
+{
+       return samsungq10_bl_brightness;
+}
+
+static const struct backlight_ops samsungq10_bl_ops = {
+       .get_brightness = samsungq10_bl_get_intensity,
+       .update_status  = samsungq10_bl_set_intensity,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int samsungq10_suspend(struct device *dev)
+{
+       return 0;
+}
+
+static int samsungq10_resume(struct device *dev)
+{
+
+       struct backlight_device *bd = dev_get_drvdata(dev);
+
+       samsungq10_bl_set_intensity(bd);
+       return 0;
+}
+#else
+#define samsungq10_suspend NULL
+#define samsungq10_resume  NULL
+#endif
+
+static SIMPLE_DEV_PM_OPS(samsungq10_pm_ops,
+                         samsungq10_suspend, samsungq10_resume);
+
+static int __devinit samsungq10_probe(struct platform_device *pdev)
+{
+
+       struct backlight_properties props;
+       struct backlight_device *bd;
+
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
+       props.max_brightness = SAMSUNGQ10_BL_MAX_INTENSITY;
+       bd = backlight_device_register("samsung", &pdev->dev, NULL,
+                                      &samsungq10_bl_ops, &props);
+       if (IS_ERR(bd))
+               return PTR_ERR(bd);
+
+       platform_set_drvdata(pdev, bd);
+
+       bd->props.brightness = SAMSUNGQ10_BL_DEFAULT_INTENSITY;
+       samsungq10_bl_set_intensity(bd);
+
+       return 0;
+}
+
+static int __devexit samsungq10_remove(struct platform_device *pdev)
+{
+
+       struct backlight_device *bd = platform_get_drvdata(pdev);
+
+       bd->props.brightness = SAMSUNGQ10_BL_DEFAULT_INTENSITY;
+       samsungq10_bl_set_intensity(bd);
+
+       backlight_device_unregister(bd);
+
+       return 0;
+}
+
+static struct platform_driver samsungq10_driver = {
+       .driver         = {
+               .name   = KBUILD_MODNAME,
+               .owner  = THIS_MODULE,
+               .pm     = &samsungq10_pm_ops,
+       },
+       .probe          = samsungq10_probe,
+       .remove         = __devexit_p(samsungq10_remove),
+};
+
+static struct platform_device *samsungq10_device;
+
+static int __init dmi_check_callback(const struct dmi_system_id *id)
+{
+       printk(KERN_INFO KBUILD_MODNAME ": found model '%s'\n", id->ident);
+       return 1;
+}
+
+static struct dmi_system_id __initdata samsungq10_dmi_table[] = {
+       {
+               .ident = "Samsung Q10",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Samsung"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SQ10"),
+               },
+               .callback = dmi_check_callback,
+       },
+       {
+               .ident = "Samsung Q20",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG Electronics"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SENS Q20"),
+               },
+               .callback = dmi_check_callback,
+       },
+       {
+               .ident = "Samsung Q25",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG Electronics"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "NQ25"),
+               },
+               .callback = dmi_check_callback,
+       },
+       {
+               .ident = "Dell Latitude X200",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X200"),
+               },
+               .callback = dmi_check_callback,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(dmi, samsungq10_dmi_table);
+
+static int __init samsungq10_init(void)
+{
+       if (!force && !dmi_check_system(samsungq10_dmi_table))
+               return -ENODEV;
+
+       samsungq10_device = platform_create_bundle(&samsungq10_driver,
+                                                  samsungq10_probe,
+                                                  NULL, 0, NULL, 0);
+
+       if (IS_ERR(samsungq10_device))
+               return PTR_ERR(samsungq10_device);
+
+       return 0;
+}
+
+static void __exit samsungq10_exit(void)
+{
+       platform_device_unregister(samsungq10_device);
+       platform_driver_unregister(&samsungq10_driver);
+}
+
+module_init(samsungq10_init);
+module_exit(samsungq10_exit);
+
+MODULE_AUTHOR("Frederick van der Wyck <fvanderwyck@gmail.com>");
+MODULE_DESCRIPTION("Samsung Q10 Driver");
+MODULE_LICENSE("GPL");
index 26c5b11..7bd829f 100644 (file)
@@ -3185,9 +3185,18 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 
                KEY_VENDOR,     /* 0x17: Thinkpad/AccessIBM/Lenovo */
 
+               /* (assignments unknown, please report if found) */
+               KEY_UNKNOWN, KEY_UNKNOWN,
+
+               /*
+                * The mic mute button only sends 0x1a.  It does not
+                * automatically mute the mic or change the mute light.
+                */
+               KEY_MICMUTE,    /* 0x1a: Mic mute (since ?400 or so) */
+
                /* (assignments unknown, please report if found) */
                KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
-               KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
+               KEY_UNKNOWN,
                },
        };
 
index e57b50b..57de051 100644 (file)
@@ -235,4 +235,18 @@ config CHARGER_GPIO
          This driver can be build as a module. If so, the module will be
          called gpio-charger.
 
+config CHARGER_MAX8997
+       tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver"
+       depends on MFD_MAX8997 && REGULATOR_MAX8997
+       help
+         Say Y to enable support for the battery charger control sysfs and
+         platform data of MAX8997/LP3974 PMICs.
+
+config CHARGER_MAX8998
+       tristate "Maxim MAX8998/LP3974 PMIC battery charger driver"
+       depends on MFD_MAX8998 && REGULATOR_MAX8998
+       help
+         Say Y to enable support for the battery charger control sysfs and
+         platform data of MAX8998/LP3974 PMICs.
+
 endif # POWER_SUPPLY
index 009a90f..b4af13d 100644 (file)
@@ -36,3 +36,5 @@ obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
 obj-$(CONFIG_CHARGER_MAX8903)  += max8903_charger.o
 obj-$(CONFIG_CHARGER_TWL4030)  += twl4030_charger.o
 obj-$(CONFIG_CHARGER_GPIO)     += gpio-charger.o
+obj-$(CONFIG_CHARGER_MAX8997)  += max8997_charger.o
+obj-$(CONFIG_CHARGER_MAX8998)  += max8998_charger.o
index dc628cb..8a612de 100644 (file)
 #include <linux/apm-emulation.h>
 
 
-#define PSY_PROP(psy, prop, val) psy->get_property(psy, \
-                        POWER_SUPPLY_PROP_##prop, val)
+#define PSY_PROP(psy, prop, val) (psy->get_property(psy, \
+                        POWER_SUPPLY_PROP_##prop, val))
 
-#define _MPSY_PROP(prop, val) main_battery->get_property(main_battery, \
-                                                        prop, val)
+#define _MPSY_PROP(prop, val) (main_battery->get_property(main_battery, \
+                                                        prop, val))
 
 #define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val)
 
index 506585e..9c5e5be 100644 (file)
@@ -152,6 +152,10 @@ struct bq20z75_info {
        bool                            gpio_detect;
        bool                            enable_detection;
        int                             irq;
+       int                             last_state;
+       int                             poll_time;
+       struct delayed_work             work;
+       int                             ignore_changes;
 };
 
 static int bq20z75_read_word_data(struct i2c_client *client, u8 address)
@@ -279,6 +283,7 @@ static int bq20z75_get_battery_property(struct i2c_client *client,
        int reg_offset, enum power_supply_property psp,
        union power_supply_propval *val)
 {
+       struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
        s32 ret;
 
        ret = bq20z75_read_word_data(client,
@@ -293,15 +298,24 @@ static int bq20z75_get_battery_property(struct i2c_client *client,
        if (ret >= bq20z75_data[reg_offset].min_value &&
            ret <= bq20z75_data[reg_offset].max_value) {
                val->intval = ret;
-               if (psp == POWER_SUPPLY_PROP_STATUS) {
-                       if (ret & BATTERY_FULL_CHARGED)
-                               val->intval = POWER_SUPPLY_STATUS_FULL;
-                       else if (ret & BATTERY_FULL_DISCHARGED)
-                               val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
-                       else if (ret & BATTERY_DISCHARGING)
-                               val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
-                       else
-                               val->intval = POWER_SUPPLY_STATUS_CHARGING;
+               if (psp != POWER_SUPPLY_PROP_STATUS)
+                       return 0;
+
+               if (ret & BATTERY_FULL_CHARGED)
+                       val->intval = POWER_SUPPLY_STATUS_FULL;
+               else if (ret & BATTERY_FULL_DISCHARGED)
+                       val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               else if (ret & BATTERY_DISCHARGING)
+                       val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+               else
+                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
+
+               if (bq20z75_device->poll_time == 0)
+                       bq20z75_device->last_state = val->intval;
+               else if (bq20z75_device->last_state != val->intval) {
+                       cancel_delayed_work_sync(&bq20z75_device->work);
+                       power_supply_changed(&bq20z75_device->power_supply);
+                       bq20z75_device->poll_time = 0;
                }
        } else {
                if (psp == POWER_SUPPLY_PROP_STATUS)
@@ -545,6 +559,60 @@ static irqreturn_t bq20z75_irq(int irq, void *devid)
        return IRQ_HANDLED;
 }
 
+static void bq20z75_external_power_changed(struct power_supply *psy)
+{
+       struct bq20z75_info *bq20z75_device;
+
+       bq20z75_device = container_of(psy, struct bq20z75_info, power_supply);
+
+       if (bq20z75_device->ignore_changes > 0) {
+               bq20z75_device->ignore_changes--;
+               return;
+       }
+
+       /* cancel outstanding work */
+       cancel_delayed_work_sync(&bq20z75_device->work);
+
+       schedule_delayed_work(&bq20z75_device->work, HZ);
+       bq20z75_device->poll_time = bq20z75_device->pdata->poll_retry_count;
+}
+
+static void bq20z75_delayed_work(struct work_struct *work)
+{
+       struct bq20z75_info *bq20z75_device;
+       s32 ret;
+
+       bq20z75_device = container_of(work, struct bq20z75_info, work.work);
+
+       ret = bq20z75_read_word_data(bq20z75_device->client,
+                                    bq20z75_data[REG_STATUS].addr);
+       /* if the read failed, give up on this work */
+       if (ret < 0) {
+               bq20z75_device->poll_time = 0;
+               return;
+       }
+
+       if (ret & BATTERY_FULL_CHARGED)
+               ret = POWER_SUPPLY_STATUS_FULL;
+       else if (ret & BATTERY_FULL_DISCHARGED)
+               ret = POWER_SUPPLY_STATUS_NOT_CHARGING;
+       else if (ret & BATTERY_DISCHARGING)
+               ret = POWER_SUPPLY_STATUS_DISCHARGING;
+       else
+               ret = POWER_SUPPLY_STATUS_CHARGING;
+
+       if (bq20z75_device->last_state != ret) {
+               bq20z75_device->poll_time = 0;
+               power_supply_changed(&bq20z75_device->power_supply);
+               return;
+       }
+       if (bq20z75_device->poll_time > 0) {
+               schedule_delayed_work(&bq20z75_device->work, HZ);
+               bq20z75_device->poll_time--;
+               return;
+       }
+}
+
 static int __devinit bq20z75_probe(struct i2c_client *client,
        const struct i2c_device_id *id)
 {
@@ -566,6 +634,13 @@ static int __devinit bq20z75_probe(struct i2c_client *client,
        bq20z75_device->power_supply.num_properties =
                ARRAY_SIZE(bq20z75_properties);
        bq20z75_device->power_supply.get_property = bq20z75_get_property;
+       /* ignore first notification of external change, it is generated
+        * from the power_supply_register call back
+        */
+       bq20z75_device->ignore_changes = 1;
+       bq20z75_device->last_state = POWER_SUPPLY_STATUS_UNKNOWN;
+       bq20z75_device->power_supply.external_power_changed =
+               bq20z75_external_power_changed;
 
        if (pdata) {
                bq20z75_device->gpio_detect =
@@ -625,6 +700,10 @@ skip_gpio:
        dev_info(&client->dev,
                "%s: battery gas gauge device registered\n", client->name);
 
+       INIT_DELAYED_WORK(&bq20z75_device->work, bq20z75_delayed_work);
+
+       bq20z75_device->enable_detection = true;
+
        return 0;
 
 exit_psupply:
@@ -648,6 +727,9 @@ static int __devexit bq20z75_remove(struct i2c_client *client)
                gpio_free(bq20z75_device->pdata->battery_detect);
 
        power_supply_unregister(&bq20z75_device->power_supply);
+
+       cancel_delayed_work_sync(&bq20z75_device->work);
+
        kfree(bq20z75_device);
        bq20z75_device = NULL;
 
@@ -661,6 +743,9 @@ static int bq20z75_suspend(struct i2c_client *client,
        struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
        s32 ret;
 
+       if (bq20z75_device->poll_time > 0)
+               cancel_delayed_work_sync(&bq20z75_device->work);
+
        /* write to manufacturer access with sleep command */
        ret = bq20z75_write_word_data(client,
                bq20z75_data[REG_MANUFACTURER_DATA].addr,
index 718f2c5..a64b885 100644 (file)
@@ -127,7 +127,7 @@ static int __devinit gpio_charger_probe(struct platform_device *pdev)
                ret = request_any_context_irq(irq, gpio_charger_irq,
                                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
                                dev_name(&pdev->dev), charger);
-               if (ret)
+               if (ret < 0)
                        dev_warn(&pdev->dev, "Failed to request irq: %d\n", ret);
                else
                        gpio_charger->irq = irq;
index c5c8805..98bfab3 100644 (file)
 #include <linux/power_supply.h>
 #include <linux/power/max17042_battery.h>
 
-enum max17042_register {
-       MAX17042_STATUS         = 0x00,
-       MAX17042_VALRT_Th       = 0x01,
-       MAX17042_TALRT_Th       = 0x02,
-       MAX17042_SALRT_Th       = 0x03,
-       MAX17042_AtRate         = 0x04,
-       MAX17042_RepCap         = 0x05,
-       MAX17042_RepSOC         = 0x06,
-       MAX17042_Age            = 0x07,
-       MAX17042_TEMP           = 0x08,
-       MAX17042_VCELL          = 0x09,
-       MAX17042_Current        = 0x0A,
-       MAX17042_AvgCurrent     = 0x0B,
-       MAX17042_Qresidual      = 0x0C,
-       MAX17042_SOC            = 0x0D,
-       MAX17042_AvSOC          = 0x0E,
-       MAX17042_RemCap         = 0x0F,
-       MAX17402_FullCAP        = 0x10,
-       MAX17042_TTE            = 0x11,
-       MAX17042_V_empty        = 0x12,
-
-       MAX17042_RSLOW          = 0x14,
-
-       MAX17042_AvgTA          = 0x16,
-       MAX17042_Cycles         = 0x17,
-       MAX17042_DesignCap      = 0x18,
-       MAX17042_AvgVCELL       = 0x19,
-       MAX17042_MinMaxTemp     = 0x1A,
-       MAX17042_MinMaxVolt     = 0x1B,
-       MAX17042_MinMaxCurr     = 0x1C,
-       MAX17042_CONFIG         = 0x1D,
-       MAX17042_ICHGTerm       = 0x1E,
-       MAX17042_AvCap          = 0x1F,
-       MAX17042_ManName        = 0x20,
-       MAX17042_DevName        = 0x21,
-       MAX17042_DevChem        = 0x22,
-
-       MAX17042_TempNom        = 0x24,
-       MAX17042_TempCold       = 0x25,
-       MAX17042_TempHot        = 0x26,
-       MAX17042_AIN            = 0x27,
-       MAX17042_LearnCFG       = 0x28,
-       MAX17042_SHFTCFG        = 0x29,
-       MAX17042_RelaxCFG       = 0x2A,
-       MAX17042_MiscCFG        = 0x2B,
-       MAX17042_TGAIN          = 0x2C,
-       MAx17042_TOFF           = 0x2D,
-       MAX17042_CGAIN          = 0x2E,
-       MAX17042_COFF           = 0x2F,
-
-       MAX17042_Q_empty        = 0x33,
-       MAX17042_T_empty        = 0x34,
-
-       MAX17042_RCOMP0         = 0x38,
-       MAX17042_TempCo         = 0x39,
-       MAX17042_Rx             = 0x3A,
-       MAX17042_T_empty0       = 0x3B,
-       MAX17042_TaskPeriod     = 0x3C,
-       MAX17042_FSTAT          = 0x3D,
-
-       MAX17042_SHDNTIMER      = 0x3F,
-
-       MAX17042_VFRemCap       = 0x4A,
-
-       MAX17042_QH             = 0x4D,
-       MAX17042_QL             = 0x4E,
-};
-
 struct max17042_chip {
        struct i2c_client *client;
        struct power_supply battery;
@@ -123,10 +55,27 @@ static int max17042_read_reg(struct i2c_client *client, u8 reg)
        return ret;
 }
 
+static void max17042_set_reg(struct i2c_client *client,
+                            struct max17042_reg_data *data, int size)
+{
+       int i;
+
+       for (i = 0; i < size; i++)
+               max17042_write_reg(client, data[i].addr, data[i].data);
+}
+
 static enum power_supply_property max17042_battery_props[] = {
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_CYCLE_COUNT,
+       POWER_SUPPLY_PROP_VOLTAGE_MAX,
+       POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
        POWER_SUPPLY_PROP_VOLTAGE_AVG,
        POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_CHARGE_FULL,
+       POWER_SUPPLY_PROP_TEMP,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_CURRENT_AVG,
 };
 
 static int max17042_get_property(struct power_supply *psy,
@@ -137,6 +86,30 @@ static int max17042_get_property(struct power_supply *psy,
                                struct max17042_chip, battery);
 
        switch (psp) {
+       case POWER_SUPPLY_PROP_PRESENT:
+               val->intval = max17042_read_reg(chip->client,
+                               MAX17042_STATUS);
+               if (val->intval & MAX17042_STATUS_BattAbsent)
+                       val->intval = 0;
+               else
+                       val->intval = 1;
+               break;
+       case POWER_SUPPLY_PROP_CYCLE_COUNT:
+               val->intval = max17042_read_reg(chip->client,
+                               MAX17042_Cycles);
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+               val->intval = max17042_read_reg(chip->client,
+                               MAX17042_MinMaxVolt);
+               val->intval >>= 8;
+               val->intval *= 20000; /* Units of LSB = 20mV */
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+               val->intval = max17042_read_reg(chip->client,
+                               MAX17042_V_empty);
+               val->intval >>= 7;
+               val->intval *= 10000; /* Units of LSB = 10mV */
+               break;
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
                val->intval = max17042_read_reg(chip->client,
                                MAX17042_VCELL) * 83; /* 1000 / 12 = 83 */
@@ -149,6 +122,57 @@ static int max17042_get_property(struct power_supply *psy,
                val->intval = max17042_read_reg(chip->client,
                                MAX17042_SOC) / 256;
                break;
+       case POWER_SUPPLY_PROP_CHARGE_FULL:
+               val->intval = max17042_read_reg(chip->client,
+                               MAX17042_RepSOC);
+               if ((val->intval / 256) >= MAX17042_BATTERY_FULL)
+                       val->intval = 1;
+               else if (val->intval >= 0)
+                       val->intval = 0;
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+               val->intval = max17042_read_reg(chip->client,
+                               MAX17042_TEMP);
+               /* The value is signed. */
+               if (val->intval & 0x8000) {
+                       val->intval = (0x7fff & ~val->intval) + 1;
+                       val->intval *= -1;
+               }
+               /* The value is converted into deci-centigrade scale */
+               /* Units of LSB = 1 / 256 degree Celsius */
+               val->intval = val->intval * 10 / 256;
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               if (chip->pdata->enable_current_sense) {
+                       val->intval = max17042_read_reg(chip->client,
+                                       MAX17042_Current);
+                       if (val->intval & 0x8000) {
+                               /* Negative */
+                               val->intval = ~val->intval & 0x7fff;
+                               val->intval++;
+                               val->intval *= -1;
+                       }
+                       val->intval >>= 4;
+                       val->intval *= 1000000 * 25 / chip->pdata->r_sns;
+               } else {
+                       return -EINVAL;
+               }
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_AVG:
+               if (chip->pdata->enable_current_sense) {
+                       val->intval = max17042_read_reg(chip->client,
+                                       MAX17042_AvgCurrent);
+                       if (val->intval & 0x8000) {
+                               /* Negative */
+                               val->intval = ~val->intval & 0x7fff;
+                               val->intval++;
+                               val->intval *= -1;
+                       }
+                       val->intval *= 1562500 / chip->pdata->r_sns;
+               } else {
+                       return -EINVAL;
+               }
+               break;
        default:
                return -EINVAL;
        }
@@ -180,18 +204,30 @@ static int __devinit max17042_probe(struct i2c_client *client,
        chip->battery.properties        = max17042_battery_props;
        chip->battery.num_properties    = ARRAY_SIZE(max17042_battery_props);
 
+       /* When current is not measured,
+        * CURRENT_NOW and CURRENT_AVG properties should be invisible. */
+       if (!chip->pdata->enable_current_sense)
+               chip->battery.num_properties -= 2;
+
        ret = power_supply_register(&client->dev, &chip->battery);
        if (ret) {
                dev_err(&client->dev, "failed: power supply register\n");
-               i2c_set_clientdata(client, NULL);
                kfree(chip);
                return ret;
        }
 
+       /* Initialize registers according to values from the platform data */
+       if (chip->pdata->init_data)
+               max17042_set_reg(client, chip->pdata->init_data,
+                                chip->pdata->num_init_data);
+
        if (!chip->pdata->enable_current_sense) {
                max17042_write_reg(client, MAX17042_CGAIN, 0x0000);
                max17042_write_reg(client, MAX17042_MiscCFG, 0x0003);
                max17042_write_reg(client, MAX17042_LearnCFG, 0x0007);
+       } else {
+               if (chip->pdata->r_sns == 0)
+                       chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
        }
 
        return 0;
@@ -202,7 +238,6 @@ static int __devexit max17042_remove(struct i2c_client *client)
        struct max17042_chip *chip = i2c_get_clientdata(client);
 
        power_supply_unregister(&chip->battery);
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return 0;
 }
index 33ff0e3..a9b0209 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/power/max8903_charger.h>
 
 struct max8903_data {
-       struct max8903_pdata *pdata;
+       struct max8903_pdata pdata;
        struct device *dev;
        struct power_supply psy;
        bool fault;
@@ -52,8 +52,8 @@ static int max8903_get_property(struct power_supply *psy,
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
                val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
-               if (data->pdata->chg) {
-                       if (gpio_get_value(data->pdata->chg) == 0)
+               if (data->pdata.chg) {
+                       if (gpio_get_value(data->pdata.chg) == 0)
                                val->intval = POWER_SUPPLY_STATUS_CHARGING;
                        else if (data->usb_in || data->ta_in)
                                val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
@@ -80,7 +80,7 @@ static int max8903_get_property(struct power_supply *psy,
 static irqreturn_t max8903_dcin(int irq, void *_data)
 {
        struct max8903_data *data = _data;
-       struct max8903_pdata *pdata = data->pdata;
+       struct max8903_pdata *pdata = &data->pdata;
        bool ta_in;
        enum power_supply_type old_type;
 
@@ -121,7 +121,7 @@ static irqreturn_t max8903_dcin(int irq, void *_data)
 static irqreturn_t max8903_usbin(int irq, void *_data)
 {
        struct max8903_data *data = _data;
-       struct max8903_pdata *pdata = data->pdata;
+       struct max8903_pdata *pdata = &data->pdata;
        bool usb_in;
        enum power_supply_type old_type;
 
@@ -160,7 +160,7 @@ static irqreturn_t max8903_usbin(int irq, void *_data)
 static irqreturn_t max8903_fault(int irq, void *_data)
 {
        struct max8903_data *data = _data;
-       struct max8903_pdata *pdata = data->pdata;
+       struct max8903_pdata *pdata = &data->pdata;
        bool fault;
 
        fault = gpio_get_value(pdata->flt) ? false : true;
@@ -193,7 +193,7 @@ static __devinit int max8903_probe(struct platform_device *pdev)
                dev_err(dev, "Cannot allocate memory.\n");
                return -ENOMEM;
        }
-       data->pdata = pdata;
+       memcpy(&data->pdata, pdata, sizeof(struct max8903_pdata));
        data->dev = dev;
        platform_set_drvdata(pdev, data);
 
@@ -349,7 +349,7 @@ static __devexit int max8903_remove(struct platform_device *pdev)
        struct max8903_data *data = platform_get_drvdata(pdev);
 
        if (data) {
-               struct max8903_pdata *pdata = data->pdata;
+               struct max8903_pdata *pdata = &data->pdata;
 
                if (pdata->flt)
                        free_irq(gpio_to_irq(pdata->flt), data);
diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
new file mode 100644 (file)
index 0000000..7106b49
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * max8997_charger.c - Power supply consumer driver for the Maxim 8997/8966
+ *
+ *  Copyright (C) 2011 Samsung Electronics
+ *  MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mfd/max8997-private.h>
+
+struct charger_data {
+       struct device *dev;
+       struct max8997_dev *iodev;
+       struct power_supply battery;
+};
+
+static enum power_supply_property max8997_battery_props[] = {
+       POWER_SUPPLY_PROP_STATUS, /* "FULL" or "NOT FULL" only. */
+       POWER_SUPPLY_PROP_PRESENT, /* the presence of battery */
+       POWER_SUPPLY_PROP_ONLINE, /* charger is active or not */
+};
+
+/* Note that the charger control is done by a current regulator "CHARGER" */
+static int max8997_battery_get_property(struct power_supply *psy,
+               enum power_supply_property psp,
+               union power_supply_propval *val)
+{
+       struct charger_data *charger = container_of(psy,
+                       struct charger_data, battery);
+       struct i2c_client *i2c = charger->iodev->i2c;
+       int ret;
+       u8 reg;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               val->intval = 0;
+               ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
+               if (ret)
+                       return ret;
+               if ((reg & (1 << 0)) == 0x1)
+                       val->intval = POWER_SUPPLY_STATUS_FULL;
+
+               break;
+       case POWER_SUPPLY_PROP_PRESENT:
+               val->intval = 0;
+               ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
+               if (ret)
+                       return ret;
+               if ((reg & (1 << 2)) == 0x0)
+                       val->intval = 1;
+
+               break;
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = 0;
+               ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
+               if (ret)
+                       return ret;
+               /* DCINOK */
+               if (reg & (1 << 1))
+                       val->intval = 1;
+
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static __devinit int max8997_battery_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct charger_data *charger;
+       struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+       struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+
+       if (!pdata)
+               return -EINVAL;
+
+       if (pdata->eoc_mA) {
+               u8 val = (pdata->eoc_mA - 50) / 10;
+               if (val < 0)
+                       val = 0;
+               if (val > 0xf)
+                       val = 0xf;
+
+               ret = max8997_update_reg(iodev->i2c,
+                               MAX8997_REG_MBCCTRL5, val, 0xf);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "Cannot use i2c bus.\n");
+                       return ret;
+               }
+       }
+
+       switch (pdata->timeout) {
+       case 5:
+               ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
+                               0x2 << 4, 0x7 << 4);
+               break;
+       case 6:
+               ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
+                               0x3 << 4, 0x7 << 4);
+               break;
+       case 7:
+               ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
+                               0x4 << 4, 0x7 << 4);
+               break;
+       case 0:
+               ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
+                               0x7 << 4, 0x7 << 4);
+               break;
+       default:
+               dev_err(&pdev->dev, "incorrect timeout value (%d)\n",
+                               pdata->timeout);
+               return -EINVAL;
+       }
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Cannot use i2c bus.\n");
+               return ret;
+       }
+
+       charger = kzalloc(sizeof(struct charger_data), GFP_KERNEL);
+       if (charger == NULL) {
+               dev_err(&pdev->dev, "Cannot allocate memory.\n");
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(pdev, charger);
+
+       charger->battery.name = "max8997_pmic";
+       charger->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+       charger->battery.get_property = max8997_battery_get_property;
+       charger->battery.properties = max8997_battery_props;
+       charger->battery.num_properties = ARRAY_SIZE(max8997_battery_props);
+
+       charger->dev = &pdev->dev;
+       charger->iodev = iodev;
+
+       ret = power_supply_register(&pdev->dev, &charger->battery);
+       if (ret) {
+               dev_err(&pdev->dev, "failed: power supply register\n");
+               goto err;
+       }
+
+       return 0;
+err:
+       kfree(charger);
+       return ret;
+}
+
+static int __devexit max8997_battery_remove(struct platform_device *pdev)
+{
+       struct charger_data *charger = platform_get_drvdata(pdev);
+
+       power_supply_unregister(&charger->battery);
+       kfree(charger);
+       return 0;
+}
+
+static const struct platform_device_id max8997_battery_id[] = {
+       { "max8997-battery", 0 },
+};
+
+static struct platform_driver max8997_battery_driver = {
+       .driver = {
+               .name = "max8997-battery",
+               .owner = THIS_MODULE,
+       },
+       .probe = max8997_battery_probe,
+       .remove = __devexit_p(max8997_battery_remove),
+       .id_table = max8997_battery_id,
+};
+
+static int __init max8997_battery_init(void)
+{
+       return platform_driver_register(&max8997_battery_driver);
+}
+subsys_initcall(max8997_battery_init);
+
+static void __exit max8997_battery_cleanup(void)
+{
+       platform_driver_unregister(&max8997_battery_driver);
+}
+module_exit(max8997_battery_cleanup);
+
+MODULE_DESCRIPTION("MAXIM 8997/8966 battery control driver");
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c
new file mode 100644 (file)
index 0000000..cc21fa2
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * max8998_charger.c - Power supply consumer driver for the Maxim 8998/LP3974
+ *
+ *  Copyright (C) 2009-2010 Samsung Electronics
+ *  MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/max8998.h>
+#include <linux/mfd/max8998-private.h>
+
+struct max8998_battery_data {
+       struct device *dev;
+       struct max8998_dev *iodev;
+       struct power_supply battery;
+};
+
+static enum power_supply_property max8998_battery_props[] = {
+       POWER_SUPPLY_PROP_PRESENT, /* the presence of battery */
+       POWER_SUPPLY_PROP_ONLINE, /* charger is active or not */
+};
+
+/* Note that the charger control is done by a current regulator "CHARGER" */
+static int max8998_battery_get_property(struct power_supply *psy,
+               enum power_supply_property psp,
+               union power_supply_propval *val)
+{
+       struct max8998_battery_data *max8998 = container_of(psy,
+                       struct max8998_battery_data, battery);
+       struct i2c_client *i2c = max8998->iodev->i2c;
+       int ret;
+       u8 reg;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_PRESENT:
+               ret = max8998_read_reg(i2c, MAX8998_REG_STATUS2, &reg);
+               if (ret)
+                       return ret;
+               if (reg & (1 << 4))
+                       val->intval = 0;
+               else
+                       val->intval = 1;
+               break;
+       case POWER_SUPPLY_PROP_ONLINE:
+               ret = max8998_read_reg(i2c, MAX8998_REG_STATUS2, &reg);
+               if (ret)
+                       return ret;
+               if (reg & (1 << 3))
+                       val->intval = 0;
+               else
+                       val->intval = 1;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static __devinit int max8998_battery_probe(struct platform_device *pdev)
+{
+       struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+       struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
+       struct max8998_battery_data *max8998;
+       struct i2c_client *i2c;
+       int ret = 0;
+
+       if (!pdata) {
+               dev_err(pdev->dev.parent, "No platform init data supplied\n");
+               return -ENODEV;
+       }
+
+       max8998 = kzalloc(sizeof(struct max8998_battery_data), GFP_KERNEL);
+       if (!max8998)
+               return -ENOMEM;
+
+       max8998->dev = &pdev->dev;
+       max8998->iodev = iodev;
+       platform_set_drvdata(pdev, max8998);
+       i2c = max8998->iodev->i2c;
+
+       /* Setup "End of Charge" */
+       /* If EOC value equals 0,
+        * remain value set from bootloader or default value */
+       if (pdata->eoc >= 10 && pdata->eoc <= 45) {
+               max8998_update_reg(i2c, MAX8998_REG_CHGR1,
+                               (pdata->eoc / 5 - 2) << 5, 0x7 << 5);
+       } else if (pdata->eoc == 0) {
+               dev_dbg(max8998->dev,
+                       "EOC value not set: leave it unchanged.\n");
+       } else {
+               dev_err(max8998->dev, "Invalid EOC value\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* Setup Charge Restart Level */
+       switch (pdata->restart) {
+       case 100:
+               max8998_update_reg(i2c, MAX8998_REG_CHGR1, 0x1 << 3, 0x3 << 3);
+               break;
+       case 150:
+               max8998_update_reg(i2c, MAX8998_REG_CHGR1, 0x0 << 3, 0x3 << 3);
+               break;
+       case 200:
+               max8998_update_reg(i2c, MAX8998_REG_CHGR1, 0x2 << 3, 0x3 << 3);
+               break;
+       case -1:
+               max8998_update_reg(i2c, MAX8998_REG_CHGR1, 0x3 << 3, 0x3 << 3);
+               break;
+       case 0:
+               dev_dbg(max8998->dev,
+                       "Restart Level not set: leave it unchanged.\n");
+               break;
+       default:
+               dev_err(max8998->dev, "Invalid Restart Level\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* Setup Charge Full Timeout */
+       switch (pdata->timeout) {
+       case 5:
+               max8998_update_reg(i2c, MAX8998_REG_CHGR2, 0x0 << 4, 0x3 << 4);
+               break;
+       case 6:
+               max8998_update_reg(i2c, MAX8998_REG_CHGR2, 0x1 << 4, 0x3 << 4);
+               break;
+       case 7:
+               max8998_update_reg(i2c, MAX8998_REG_CHGR2, 0x2 << 4, 0x3 << 4);
+               break;
+       case -1:
+               max8998_update_reg(i2c, MAX8998_REG_CHGR2, 0x3 << 4, 0x3 << 4);
+               break;
+       case 0:
+               dev_dbg(max8998->dev,
+                       "Full Timeout not set: leave it unchanged.\n");
+       default:
+               dev_err(max8998->dev, "Invalid Full Timeout value\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       max8998->battery.name = "max8998_pmic";
+       max8998->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+       max8998->battery.get_property = max8998_battery_get_property;
+       max8998->battery.properties = max8998_battery_props;
+       max8998->battery.num_properties = ARRAY_SIZE(max8998_battery_props);
+
+       ret = power_supply_register(max8998->dev, &max8998->battery);
+       if (ret) {
+               dev_err(max8998->dev, "failed: power supply register\n");
+               goto err;
+       }
+
+       return 0;
+err:
+       kfree(max8998);
+       return ret;
+}
+
+static int __devexit max8998_battery_remove(struct platform_device *pdev)
+{
+       struct max8998_battery_data *max8998 = platform_get_drvdata(pdev);
+
+       power_supply_unregister(&max8998->battery);
+       kfree(max8998);
+
+       return 0;
+}
+
+static const struct platform_device_id max8998_battery_id[] = {
+       { "max8998-battery", TYPE_MAX8998 },
+};
+
+static struct platform_driver max8998_battery_driver = {
+       .driver = {
+               .name = "max8998-battery",
+               .owner = THIS_MODULE,
+       },
+       .probe = max8998_battery_probe,
+       .remove = __devexit_p(max8998_battery_remove),
+       .id_table = max8998_battery_id,
+};
+
+static int __init max8998_battery_init(void)
+{
+       return platform_driver_register(&max8998_battery_driver);
+}
+module_init(max8998_battery_init);
+
+static void __exit max8998_battery_cleanup(void)
+{
+       platform_driver_unregister(&max8998_battery_driver);
+}
+module_exit(max8998_battery_cleanup);
+
+MODULE_DESCRIPTION("MAXIM 8998 battery control driver");
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:max8998-battery");
index d36c289..a675e31 100644 (file)
@@ -266,7 +266,7 @@ static irqreturn_t s3c_adc_bat_charged(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __init s3c_adc_bat_probe(struct platform_device *pdev)
+static int __devinit s3c_adc_bat_probe(struct platform_device *pdev)
 {
        struct s3c_adc_client   *client;
        struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data;
index 92c16e1..54b9198 100644 (file)
@@ -62,7 +62,7 @@
 #define TWL4030_MSTATEC_COMPLETE4      0x0e
 
 static bool allow_usb;
-module_param(allow_usb, bool, 1);
+module_param(allow_usb, bool, 0644);
 MODULE_PARM_DESC(allow_usb, "Allow USB charge drawing default current");
 
 struct twl4030_bci {
@@ -425,7 +425,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 {
        struct twl4030_bci *bci;
        int ret;
-       int reg;
+       u32 reg;
 
        bci = kzalloc(sizeof(*bci), GFP_KERNEL);
        if (bci == NULL)
@@ -486,7 +486,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
        }
 
        /* Enable interrupts now. */
-       reg = ~(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 |
+       reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 |
                TWL4030_TBATOR1 | TWL4030_BATSTS);
        ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
                               TWL4030_INTERRUPTS_BCIIMR1A);
@@ -495,7 +495,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
                goto fail_unmask_interrupts;
        }
 
-       reg = ~(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
+       reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
        ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
                               TWL4030_INTERRUPTS_BCIIMR2A);
        if (ret < 0)
@@ -572,7 +572,7 @@ static void __exit twl4030_bci_exit(void)
 }
 module_exit(twl4030_bci_exit);
 
-MODULE_AUTHOR("Gražydas Ignotas");
+MODULE_AUTHOR("Gražvydas Ignotas");
 MODULE_DESCRIPTION("TWL4030 Battery Charger Interface driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:twl4030_bci");
index 0fd130d..e648cbe 100644 (file)
@@ -22,6 +22,7 @@
 struct wm831x_backup {
        struct wm831x *wm831x;
        struct power_supply backup;
+       char name[20];
 };
 
 static int wm831x_backup_read_voltage(struct wm831x *wm831x,
@@ -163,6 +164,7 @@ static enum power_supply_property wm831x_backup_props[] = {
 static __devinit int wm831x_backup_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+       struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
        struct wm831x_backup *devdata;
        struct power_supply *backup;
        int ret;
@@ -182,7 +184,14 @@ static __devinit int wm831x_backup_probe(struct platform_device *pdev)
         */
        wm831x_config_backup(wm831x);
 
-       backup->name = "wm831x-backup";
+       if (wm831x_pdata && wm831x_pdata->wm831x_num)
+               snprintf(devdata->name, sizeof(devdata->name),
+                        "wm831x-backup.%d", wm831x_pdata->wm831x_num);
+       else
+               snprintf(devdata->name, sizeof(devdata->name),
+                        "wm831x-backup");
+
+       backup->name = devdata->name;
        backup->type = POWER_SUPPLY_TYPE_BATTERY;
        backup->properties = wm831x_backup_props;
        backup->num_properties = ARRAY_SIZE(wm831x_backup_props);
@@ -203,6 +212,7 @@ static __devexit int wm831x_backup_remove(struct platform_device *pdev)
        struct wm831x_backup *devdata = platform_get_drvdata(pdev);
 
        power_supply_unregister(&devdata->backup);
+       kfree(devdata->backup.name);
        kfree(devdata);
 
        return 0;
index ddf8cf5..6cc2ca6 100644 (file)
@@ -24,6 +24,9 @@ struct wm831x_power {
        struct power_supply wall;
        struct power_supply usb;
        struct power_supply battery;
+       char wall_name[20];
+       char usb_name[20];
+       char battery_name[20];
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -486,6 +489,7 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
 static __devinit int wm831x_power_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+       struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
        struct wm831x_power *power;
        struct power_supply *usb;
        struct power_supply *battery;
@@ -503,12 +507,28 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
        battery = &power->battery;
        wall = &power->wall;
 
+       if (wm831x_pdata && wm831x_pdata->wm831x_num) {
+               snprintf(power->wall_name, sizeof(power->wall_name),
+                        "wm831x-wall.%d", wm831x_pdata->wm831x_num);
+               snprintf(power->battery_name, sizeof(power->wall_name),
+                        "wm831x-battery.%d", wm831x_pdata->wm831x_num);
+               snprintf(power->usb_name, sizeof(power->wall_name),
+                        "wm831x-usb.%d", wm831x_pdata->wm831x_num);
+       } else {
+               snprintf(power->wall_name, sizeof(power->wall_name),
+                        "wm831x-wall");
+               snprintf(power->battery_name, sizeof(power->wall_name),
+                        "wm831x-battery");
+               snprintf(power->usb_name, sizeof(power->wall_name),
+                        "wm831x-usb");
+       }
+
        /* We ignore configuration failures since we can still read back
         * the status without enabling the charger.
         */
        wm831x_config_battery(wm831x);
 
-       wall->name = "wm831x-wall";
+       wall->name = power->wall_name;
        wall->type = POWER_SUPPLY_TYPE_MAINS;
        wall->properties = wm831x_wall_props;
        wall->num_properties = ARRAY_SIZE(wm831x_wall_props);
@@ -517,7 +537,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
        if (ret)
                goto err_kmalloc;
 
-       battery->name = "wm831x-battery";
+       battery->name = power->battery_name;
        battery->properties = wm831x_bat_props;
        battery->num_properties = ARRAY_SIZE(wm831x_bat_props);
        battery->get_property = wm831x_bat_get_prop;
@@ -526,7 +546,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
        if (ret)
                goto err_wall;
 
-       usb->name = "wm831x-usb",
+       usb->name = power->usb_name,
        usb->type = POWER_SUPPLY_TYPE_USB;
        usb->properties = wm831x_usb_props;
        usb->num_properties = ARRAY_SIZE(wm831x_usb_props);
index 118eb21..c7fd2c0 100644 (file)
@@ -249,6 +249,12 @@ config REGULATOR_TPS6507X
          three step-down converters and two general-purpose LDO voltage regulators.
          It supports TI's software based Class-2 SmartReflex implementation.
 
+config REGULATOR_TPS65912
+       tristate "TI TPS65912 Power regulator"
+       depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
+       help
+           This driver supports TPS65912 voltage regulator chip.
+
 config REGULATOR_88PM8607
        bool "Marvell 88PM8607 Power regulators"
        depends on MFD_88PM860X=y
@@ -304,5 +310,12 @@ config REGULATOR_TPS65910
        help
          This driver supports TPS65910 voltage regulator chips.
 
+config REGULATOR_AAT2870
+       tristate "AnalogicTech AAT2870 Regulators"
+       depends on MFD_AAT2870_CORE
+       help
+         If you have a AnalogicTech AAT2870 say Y to enable the
+         regulator driver.
+
 endif
 
index 3932d2e..040d5aa 100644 (file)
@@ -38,10 +38,12 @@ obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
+obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
 obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
 obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
 obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
+obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
 
 ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c
new file mode 100644 (file)
index 0000000..cd41045
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * linux/drivers/regulator/aat2870-regulator.c
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ * Author: Jin Park <jinyoungp@nvidia.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/aat2870.h>
+
+struct aat2870_regulator {
+       struct platform_device *pdev;
+       struct regulator_desc desc;
+
+       const int *voltages; /* uV */
+
+       int min_uV;
+       int max_uV;
+
+       u8 enable_addr;
+       u8 enable_shift;
+       u8 enable_mask;
+
+       u8 voltage_addr;
+       u8 voltage_shift;
+       u8 voltage_mask;
+};
+
+static int aat2870_ldo_list_voltage(struct regulator_dev *rdev,
+                                   unsigned selector)
+{
+       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
+
+       return ri->voltages[selector];
+}
+
+static int aat2870_ldo_set_voltage_sel(struct regulator_dev *rdev,
+                                      unsigned selector)
+{
+       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
+       struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent);
+
+       return aat2870->update(aat2870, ri->voltage_addr, ri->voltage_mask,
+                       (selector << ri->voltage_shift) & ri->voltage_mask);
+}
+
+static int aat2870_ldo_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
+       struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent);
+       u8 val;
+       int ret;
+
+       ret = aat2870->read(aat2870, ri->voltage_addr, &val);
+       if (ret)
+               return ret;
+
+       return (val & ri->voltage_mask) >> ri->voltage_shift;
+}
+
+static int aat2870_ldo_enable(struct regulator_dev *rdev)
+{
+       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
+       struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent);
+
+       return aat2870->update(aat2870, ri->enable_addr, ri->enable_mask,
+                              ri->enable_mask);
+}
+
+static int aat2870_ldo_disable(struct regulator_dev *rdev)
+{
+       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
+       struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent);
+
+       return aat2870->update(aat2870, ri->enable_addr, ri->enable_mask, 0);
+}
+
+static int aat2870_ldo_is_enabled(struct regulator_dev *rdev)
+{
+       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
+       struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent);
+       u8 val;
+       int ret;
+
+       ret = aat2870->read(aat2870, ri->enable_addr, &val);
+       if (ret)
+               return ret;
+
+       return val & ri->enable_mask ? 1 : 0;
+}
+
+static struct regulator_ops aat2870_ldo_ops = {
+       .list_voltage = aat2870_ldo_list_voltage,
+       .set_voltage_sel = aat2870_ldo_set_voltage_sel,
+       .get_voltage_sel = aat2870_ldo_get_voltage_sel,
+       .enable = aat2870_ldo_enable,
+       .disable = aat2870_ldo_disable,
+       .is_enabled = aat2870_ldo_is_enabled,
+};
+
+static const int aat2870_ldo_voltages[] = {
+       1200000, 1300000, 1500000, 1600000,
+       1800000, 2000000, 2200000, 2500000,
+       2600000, 2700000, 2800000, 2900000,
+       3000000, 3100000, 3200000, 3300000,
+};
+
+#define AAT2870_LDO(ids)                               \
+       {                                               \
+               .desc = {                               \
+                       .name = #ids,                   \
+                       .id = AAT2870_ID_##ids,         \
+                       .n_voltages = ARRAY_SIZE(aat2870_ldo_voltages), \
+                       .ops = &aat2870_ldo_ops,        \
+                       .type = REGULATOR_VOLTAGE,      \
+                       .owner = THIS_MODULE,           \
+               },                                      \
+               .voltages = aat2870_ldo_voltages,       \
+               .min_uV = 1200000,                      \
+               .max_uV = 3300000,                      \
+       }
+
+static struct aat2870_regulator aat2870_regulators[] = {
+       AAT2870_LDO(LDOA),
+       AAT2870_LDO(LDOB),
+       AAT2870_LDO(LDOC),
+       AAT2870_LDO(LDOD),
+};
+
+static struct aat2870_regulator *aat2870_get_regulator(int id)
+{
+       struct aat2870_regulator *ri = NULL;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(aat2870_regulators); i++) {
+               ri = &aat2870_regulators[i];
+               if (ri->desc.id == id)
+                       break;
+       }
+
+       if (!ri)
+               return NULL;
+
+       ri->enable_addr = AAT2870_LDO_EN;
+       ri->enable_shift = id - AAT2870_ID_LDOA;
+       ri->enable_mask = 0x1 << ri->enable_shift;
+
+       ri->voltage_addr = (id - AAT2870_ID_LDOA) / 2 ?
+                          AAT2870_LDO_CD : AAT2870_LDO_AB;
+       ri->voltage_shift = (id - AAT2870_ID_LDOA) % 2 ? 0 : 4;
+       ri->voltage_mask = 0xF << ri->voltage_shift;
+
+       return ri;
+}
+
+static int aat2870_regulator_probe(struct platform_device *pdev)
+{
+       struct aat2870_regulator *ri;
+       struct regulator_dev *rdev;
+
+       ri = aat2870_get_regulator(pdev->id);
+       if (!ri) {
+               dev_err(&pdev->dev, "Invalid device ID, %d\n", pdev->id);
+               return -EINVAL;
+       }
+       ri->pdev = pdev;
+
+       rdev = regulator_register(&ri->desc, &pdev->dev,
+                                 pdev->dev.platform_data, ri);
+       if (IS_ERR(rdev)) {
+               dev_err(&pdev->dev, "Failed to register regulator %s\n",
+                       ri->desc.name);
+               return PTR_ERR(rdev);
+       }
+       platform_set_drvdata(pdev, rdev);
+
+       return 0;
+}
+
+static int __devexit aat2870_regulator_remove(struct platform_device *pdev)
+{
+       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+       regulator_unregister(rdev);
+       return 0;
+}
+
+static struct platform_driver aat2870_regulator_driver = {
+       .driver = {
+               .name   = "aat2870-regulator",
+               .owner  = THIS_MODULE,
+       },
+       .probe  = aat2870_regulator_probe,
+       .remove = __devexit_p(aat2870_regulator_remove),
+};
+
+static int __init aat2870_regulator_init(void)
+{
+       return platform_driver_register(&aat2870_regulator_driver);
+}
+subsys_initcall(aat2870_regulator_init);
+
+static void __exit aat2870_regulator_exit(void)
+{
+       platform_driver_unregister(&aat2870_regulator_driver);
+}
+module_exit(aat2870_regulator_exit);
+
+MODULE_DESCRIPTION("AnalogicTech AAT2870 Regulator");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");
index d3e3879..d8e6a42 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/debugfs.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <linux/async.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/suspend.h>
@@ -33,6 +34,8 @@
 
 #include "dummy.h"
 
+#define rdev_crit(rdev, fmt, ...)                                      \
+       pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
 #define rdev_err(rdev, fmt, ...)                                       \
        pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
 #define rdev_warn(rdev, fmt, ...)                                      \
@@ -78,11 +81,13 @@ struct regulator {
        char *supply_name;
        struct device_attribute dev_attr;
        struct regulator_dev *rdev;
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *debugfs;
+#endif
 };
 
 static int _regulator_is_enabled(struct regulator_dev *rdev);
-static int _regulator_disable(struct regulator_dev *rdev,
-               struct regulator_dev **supply_rdev_ptr);
+static int _regulator_disable(struct regulator_dev *rdev);
 static int _regulator_get_voltage(struct regulator_dev *rdev);
 static int _regulator_get_current_limit(struct regulator_dev *rdev);
 static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
@@ -90,6 +95,9 @@ static void _notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data);
 static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                                     int min_uV, int max_uV);
+static struct regulator *create_regulator(struct regulator_dev *rdev,
+                                         struct device *dev,
+                                         const char *supply_name);
 
 static const char *rdev_get_name(struct regulator_dev *rdev)
 {
@@ -143,8 +151,11 @@ static int regulator_check_voltage(struct regulator_dev *rdev,
        if (*min_uV < rdev->constraints->min_uV)
                *min_uV = rdev->constraints->min_uV;
 
-       if (*min_uV > *max_uV)
+       if (*min_uV > *max_uV) {
+               rdev_err(rdev, "unsupportable voltage range: %d-%duV\n",
+                        *min_uV, *max_uV);
                return -EINVAL;
+       }
 
        return 0;
 }
@@ -197,8 +208,11 @@ static int regulator_check_current_limit(struct regulator_dev *rdev,
        if (*min_uA < rdev->constraints->min_uA)
                *min_uA = rdev->constraints->min_uA;
 
-       if (*min_uA > *max_uA)
+       if (*min_uA > *max_uA) {
+               rdev_err(rdev, "unsupportable current range: %d-%duA\n",
+                        *min_uA, *max_uA);
                return -EINVAL;
+       }
 
        return 0;
 }
@@ -213,6 +227,7 @@ static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode)
        case REGULATOR_MODE_STANDBY:
                break;
        default:
+               rdev_err(rdev, "invalid mode %x specified\n", *mode);
                return -EINVAL;
        }
 
@@ -779,7 +794,6 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
                if (ret < 0) {
                        rdev_err(rdev, "failed to apply %duV constraint\n",
                                 rdev->constraints->min_uV);
-                       rdev->constraints = NULL;
                        return ret;
                }
        }
@@ -882,7 +896,6 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                ret = suspend_prepare(rdev, rdev->constraints->initial_state);
                if (ret < 0) {
                        rdev_err(rdev, "failed to set suspend state\n");
-                       rdev->constraints = NULL;
                        goto out;
                }
        }
@@ -909,13 +922,15 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                ret = ops->enable(rdev);
                if (ret < 0) {
                        rdev_err(rdev, "failed to enable\n");
-                       rdev->constraints = NULL;
                        goto out;
                }
        }
 
        print_constraints(rdev);
+       return 0;
 out:
+       kfree(rdev->constraints);
+       rdev->constraints = NULL;
        return ret;
 }
 
@@ -929,21 +944,20 @@ out:
  * core if it's child is enabled.
  */
 static int set_supply(struct regulator_dev *rdev,
-       struct regulator_dev *supply_rdev)
+                     struct regulator_dev *supply_rdev)
 {
        int err;
 
-       err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj,
-                               "supply");
-       if (err) {
-               rdev_err(rdev, "could not add device link %s err %d\n",
-                        supply_rdev->dev.kobj.name, err);
-                      goto out;
+       rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
+
+       rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
+       if (IS_ERR(rdev->supply)) {
+               err = PTR_ERR(rdev->supply);
+               rdev->supply = NULL;
+               return err;
        }
-       rdev->supply = supply_rdev;
-       list_add(&rdev->slist, &supply_rdev->supply_list);
-out:
-       return err;
+
+       return 0;
 }
 
 /**
@@ -1032,7 +1046,7 @@ static void unset_regulator_supplies(struct regulator_dev *rdev)
        }
 }
 
-#define REG_STR_SIZE   32
+#define REG_STR_SIZE   64
 
 static struct regulator *create_regulator(struct regulator_dev *rdev,
                                          struct device *dev,
@@ -1052,8 +1066,9 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
 
        if (dev) {
                /* create a 'requested_microamps_name' sysfs entry */
-               size = scnprintf(buf, REG_STR_SIZE, "microamps_requested_%s",
-                       supply_name);
+               size = scnprintf(buf, REG_STR_SIZE,
+                                "microamps_requested_%s-%s",
+                                dev_name(dev), supply_name);
                if (size >= REG_STR_SIZE)
                        goto overflow_err;
 
@@ -1088,7 +1103,28 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
                                  dev->kobj.name, err);
                        goto link_name_err;
                }
+       } else {
+               regulator->supply_name = kstrdup(supply_name, GFP_KERNEL);
+               if (regulator->supply_name == NULL)
+                       goto attr_err;
+       }
+
+#ifdef CONFIG_DEBUG_FS
+       regulator->debugfs = debugfs_create_dir(regulator->supply_name,
+                                               rdev->debugfs);
+       if (IS_ERR_OR_NULL(regulator->debugfs)) {
+               rdev_warn(rdev, "Failed to create debugfs directory\n");
+               regulator->debugfs = NULL;
+       } else {
+               debugfs_create_u32("uA_load", 0444, regulator->debugfs,
+                                  &regulator->uA_load);
+               debugfs_create_u32("min_uV", 0444, regulator->debugfs,
+                                  &regulator->min_uV);
+               debugfs_create_u32("max_uV", 0444, regulator->debugfs,
+                                  &regulator->max_uV);
        }
+#endif
+
        mutex_unlock(&rdev->mutex);
        return regulator;
 link_name_err:
@@ -1267,13 +1303,17 @@ void regulator_put(struct regulator *regulator)
        mutex_lock(&regulator_list_mutex);
        rdev = regulator->rdev;
 
+#ifdef CONFIG_DEBUG_FS
+       debugfs_remove_recursive(regulator->debugfs);
+#endif
+
        /* remove any sysfs entries */
        if (regulator->dev) {
                sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
-               kfree(regulator->supply_name);
                device_remove_file(regulator->dev, &regulator->dev_attr);
                kfree(regulator->dev_attr.attr.name);
        }
+       kfree(regulator->supply_name);
        list_del(&regulator->list);
        kfree(regulator);
 
@@ -1301,19 +1341,6 @@ static int _regulator_enable(struct regulator_dev *rdev)
 {
        int ret, delay;
 
-       if (rdev->use_count == 0) {
-               /* do we need to enable the supply regulator first */
-               if (rdev->supply) {
-                       mutex_lock(&rdev->supply->mutex);
-                       ret = _regulator_enable(rdev->supply);
-                       mutex_unlock(&rdev->supply->mutex);
-                       if (ret < 0) {
-                               rdev_err(rdev, "failed to enable: %d\n", ret);
-                               return ret;
-                       }
-               }
-       }
-
        /* check voltage and requested load before enabling */
        if (rdev->constraints &&
            (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS))
@@ -1388,19 +1415,27 @@ int regulator_enable(struct regulator *regulator)
        struct regulator_dev *rdev = regulator->rdev;
        int ret = 0;
 
+       if (rdev->supply) {
+               ret = regulator_enable(rdev->supply);
+               if (ret != 0)
+                       return ret;
+       }
+
        mutex_lock(&rdev->mutex);
        ret = _regulator_enable(rdev);
        mutex_unlock(&rdev->mutex);
+
+       if (ret != 0)
+               regulator_disable(rdev->supply);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_enable);
 
 /* locks held by regulator_disable() */
-static int _regulator_disable(struct regulator_dev *rdev,
-               struct regulator_dev **supply_rdev_ptr)
+static int _regulator_disable(struct regulator_dev *rdev)
 {
        int ret = 0;
-       *supply_rdev_ptr = NULL;
 
        if (WARN(rdev->use_count <= 0,
                 "unbalanced disables for %s\n", rdev_get_name(rdev)))
@@ -1427,9 +1462,6 @@ static int _regulator_disable(struct regulator_dev *rdev,
                                             NULL);
                }
 
-               /* decrease our supplies ref count and disable if required */
-               *supply_rdev_ptr = rdev->supply;
-
                rdev->use_count = 0;
        } else if (rdev->use_count > 1) {
 
@@ -1440,6 +1472,7 @@ static int _regulator_disable(struct regulator_dev *rdev,
 
                rdev->use_count--;
        }
+
        return ret;
 }
 
@@ -1458,29 +1491,21 @@ static int _regulator_disable(struct regulator_dev *rdev,
 int regulator_disable(struct regulator *regulator)
 {
        struct regulator_dev *rdev = regulator->rdev;
-       struct regulator_dev *supply_rdev = NULL;
        int ret = 0;
 
        mutex_lock(&rdev->mutex);
-       ret = _regulator_disable(rdev, &supply_rdev);
+       ret = _regulator_disable(rdev);
        mutex_unlock(&rdev->mutex);
 
-       /* decrease our supplies ref count and disable if required */
-       while (supply_rdev != NULL) {
-               rdev = supply_rdev;
-
-               mutex_lock(&rdev->mutex);
-               _regulator_disable(rdev, &supply_rdev);
-               mutex_unlock(&rdev->mutex);
-       }
+       if (ret == 0 && rdev->supply)
+               regulator_disable(rdev->supply);
 
        return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_disable);
 
 /* locks held by regulator_force_disable() */
-static int _regulator_force_disable(struct regulator_dev *rdev,
-               struct regulator_dev **supply_rdev_ptr)
+static int _regulator_force_disable(struct regulator_dev *rdev)
 {
        int ret = 0;
 
@@ -1497,10 +1522,6 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
                        REGULATOR_EVENT_DISABLE, NULL);
        }
 
-       /* decrease our supplies ref count and disable if required */
-       *supply_rdev_ptr = rdev->supply;
-
-       rdev->use_count = 0;
        return ret;
 }
 
@@ -1516,16 +1537,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
 int regulator_force_disable(struct regulator *regulator)
 {
        struct regulator_dev *rdev = regulator->rdev;
-       struct regulator_dev *supply_rdev = NULL;
        int ret;
 
        mutex_lock(&rdev->mutex);
        regulator->uA_load = 0;
-       ret = _regulator_force_disable(rdev, &supply_rdev);
+       ret = _regulator_force_disable(regulator->rdev);
        mutex_unlock(&rdev->mutex);
 
-       if (supply_rdev)
-               regulator_disable(get_device_regulator(rdev_get_dev(supply_rdev)));
+       if (rdev->supply)
+               while (rdev->open_count--)
+                       regulator_disable(rdev->supply);
 
        return ret;
 }
@@ -2136,7 +2157,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
        /* get input voltage */
        input_uV = 0;
        if (rdev->supply)
-               input_uV = _regulator_get_voltage(rdev->supply);
+               input_uV = regulator_get_voltage(rdev->supply);
        if (input_uV <= 0)
                input_uV = rdev->constraints->input_uV;
        if (input_uV <= 0) {
@@ -2206,17 +2227,8 @@ EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
 static void _notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data)
 {
-       struct regulator_dev *_rdev;
-
        /* call rdev chain first */
        blocking_notifier_call_chain(&rdev->notifier, event, NULL);
-
-       /* now notify regulator we supply */
-       list_for_each_entry(_rdev, &rdev->supply_list, slist) {
-               mutex_lock(&_rdev->mutex);
-               _notifier_call_chain(_rdev, event, data);
-               mutex_unlock(&_rdev->mutex);
-       }
 }
 
 /**
@@ -2264,6 +2276,13 @@ err:
 }
 EXPORT_SYMBOL_GPL(regulator_bulk_get);
 
+static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
+{
+       struct regulator_bulk_data *bulk = data;
+
+       bulk->ret = regulator_enable(bulk->consumer);
+}
+
 /**
  * regulator_bulk_enable - enable multiple regulator consumers
  *
@@ -2279,21 +2298,33 @@ EXPORT_SYMBOL_GPL(regulator_bulk_get);
 int regulator_bulk_enable(int num_consumers,
                          struct regulator_bulk_data *consumers)
 {
+       LIST_HEAD(async_domain);
        int i;
-       int ret;
+       int ret = 0;
+
+       for (i = 0; i < num_consumers; i++)
+               async_schedule_domain(regulator_bulk_enable_async,
+                                     &consumers[i], &async_domain);
+
+       async_synchronize_full_domain(&async_domain);
 
+       /* If any consumer failed we need to unwind any that succeeded */
        for (i = 0; i < num_consumers; i++) {
-               ret = regulator_enable(consumers[i].consumer);
-               if (ret != 0)
+               if (consumers[i].ret != 0) {
+                       ret = consumers[i].ret;
                        goto err;
+               }
        }
 
        return 0;
 
 err:
-       pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret);
-       for (--i; i >= 0; --i)
-               regulator_disable(consumers[i].consumer);
+       for (i = 0; i < num_consumers; i++)
+               if (consumers[i].ret == 0)
+                       regulator_disable(consumers[i].consumer);
+               else
+                       pr_err("Failed to enable %s: %d\n",
+                              consumers[i].supply, consumers[i].ret);
 
        return ret;
 }
@@ -2589,9 +2620,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
        rdev->owner = regulator_desc->owner;
        rdev->desc = regulator_desc;
        INIT_LIST_HEAD(&rdev->consumer_list);
-       INIT_LIST_HEAD(&rdev->supply_list);
        INIT_LIST_HEAD(&rdev->list);
-       INIT_LIST_HEAD(&rdev->slist);
        BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
 
        /* preform any regulator specific init */
@@ -2672,6 +2701,7 @@ unset_supplies:
        unset_regulator_supplies(rdev);
 
 scrub:
+       kfree(rdev->constraints);
        device_unregister(&rdev->dev);
        /* device core frees rdev */
        rdev = ERR_PTR(ret);
@@ -2703,7 +2733,7 @@ void regulator_unregister(struct regulator_dev *rdev)
        unset_regulator_supplies(rdev);
        list_del(&rdev->list);
        if (rdev->supply)
-               sysfs_remove_link(&rdev->dev.kobj, "supply");
+               regulator_put(rdev->supply);
        device_unregister(&rdev->dev);
        kfree(rdev->constraints);
        mutex_unlock(&regulator_list_mutex);
index c7410bd..f6ef669 100644 (file)
@@ -36,6 +36,29 @@ static struct regulator_desc dummy_desc = {
        .ops = &dummy_ops,
 };
 
+static int __devinit dummy_regulator_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       dummy_regulator_rdev = regulator_register(&dummy_desc, NULL,
+                                                 &dummy_initdata, NULL);
+       if (IS_ERR(dummy_regulator_rdev)) {
+               ret = PTR_ERR(dummy_regulator_rdev);
+               pr_err("Failed to register regulator: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static struct platform_driver dummy_regulator_driver = {
+       .probe          = dummy_regulator_probe,
+       .driver         = {
+               .name           = "reg-dummy",
+               .owner          = THIS_MODULE,
+       },
+};
+
 static struct platform_device *dummy_pdev;
 
 void __init regulator_dummy_init(void)
@@ -55,12 +78,9 @@ void __init regulator_dummy_init(void)
                return;
        }
 
-       dummy_regulator_rdev = regulator_register(&dummy_desc, NULL,
-                                                 &dummy_initdata, NULL);
-       if (IS_ERR(dummy_regulator_rdev)) {
-               ret = PTR_ERR(dummy_regulator_rdev);
-               pr_err("Failed to register regulator: %d\n", ret);
+       ret = platform_driver_register(&dummy_regulator_driver);
+       if (ret != 0) {
+               pr_err("Failed to register dummy regulator driver: %d\n", ret);
                platform_device_unregister(dummy_pdev);
-               return;
        }
 }
index 55dd4e6..66d2d60 100644 (file)
@@ -49,7 +49,6 @@
 #define TPS65911_REG_LDO7              11
 #define TPS65911_REG_LDO8              12
 
-#define TPS65910_NUM_REGULATOR         13
 #define TPS65910_SUPPLY_STATE_ENABLED  0x1
 
 /* supported VIO voltages in milivolts */
@@ -264,11 +263,12 @@ static struct tps_info tps65911_regs[] = {
 };
 
 struct tps65910_reg {
-       struct regulator_desc desc[TPS65910_NUM_REGULATOR];
+       struct regulator_desc *desc;
        struct tps65910 *mfd;
-       struct regulator_dev *rdev[TPS65910_NUM_REGULATOR];
-       struct tps_info *info[TPS65910_NUM_REGULATOR];
+       struct regulator_dev **rdev;
+       struct tps_info **info;
        struct mutex mutex;
+       int num_regulators;
        int mode;
        int  (*get_ctrl_reg)(int);
 };
@@ -759,8 +759,13 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev,
                mult = (selector / VDD1_2_NUM_VOLTS) + 1;
                volt = VDD1_2_MIN_VOLT +
                                (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET;
+               break;
        case TPS65911_REG_VDDCTRL:
                volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET);
+               break;
+       default:
+               BUG();
+               return -EINVAL;
        }
 
        return  volt * 100 * mult;
@@ -897,16 +902,42 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
        switch(tps65910_chip_id(tps65910)) {
        case TPS65910:
                pmic->get_ctrl_reg = &tps65910_get_ctrl_register;
+               pmic->num_regulators = ARRAY_SIZE(tps65910_regs);
                info = tps65910_regs;
+               break;
        case TPS65911:
                pmic->get_ctrl_reg = &tps65911_get_ctrl_register;
+               pmic->num_regulators = ARRAY_SIZE(tps65911_regs);
                info = tps65911_regs;
+               break;
        default:
                pr_err("Invalid tps chip version\n");
+               kfree(pmic);
                return -ENODEV;
        }
 
-       for (i = 0; i < TPS65910_NUM_REGULATOR; i++, info++, reg_data++) {
+       pmic->desc = kcalloc(pmic->num_regulators,
+                       sizeof(struct regulator_desc), GFP_KERNEL);
+       if (!pmic->desc) {
+               err = -ENOMEM;
+               goto err_free_pmic;
+       }
+
+       pmic->info = kcalloc(pmic->num_regulators,
+                       sizeof(struct tps_info *), GFP_KERNEL);
+       if (!pmic->info) {
+               err = -ENOMEM;
+               goto err_free_desc;
+       }
+
+       pmic->rdev = kcalloc(pmic->num_regulators,
+                       sizeof(struct regulator_dev *), GFP_KERNEL);
+       if (!pmic->rdev) {
+               err = -ENOMEM;
+               goto err_free_info;
+       }
+
+       for (i = 0; i < pmic->num_regulators; i++, info++, reg_data++) {
                /* Register the regulators */
                pmic->info[i] = info;
 
@@ -938,7 +969,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
                                "failed to register %s regulator\n",
                                pdev->name);
                        err = PTR_ERR(rdev);
-                       goto err;
+                       goto err_unregister_regulator;
                }
 
                /* Save regulator for cleanup */
@@ -946,23 +977,31 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
        }
        return 0;
 
-err:
+err_unregister_regulator:
        while (--i >= 0)
                regulator_unregister(pmic->rdev[i]);
-
+       kfree(pmic->rdev);
+err_free_info:
+       kfree(pmic->info);
+err_free_desc:
+       kfree(pmic->desc);
+err_free_pmic:
        kfree(pmic);
        return err;
 }
 
 static int __devexit tps65910_remove(struct platform_device *pdev)
 {
-       struct tps65910_reg *tps65910_reg = platform_get_drvdata(pdev);
+       struct tps65910_reg *pmic = platform_get_drvdata(pdev);
        int i;
 
-       for (i = 0; i < TPS65910_NUM_REGULATOR; i++)
-               regulator_unregister(tps65910_reg->rdev[i]);
+       for (i = 0; i < pmic->num_regulators; i++)
+               regulator_unregister(pmic->rdev[i]);
 
-       kfree(tps65910_reg);
+       kfree(pmic->rdev);
+       kfree(pmic->info);
+       kfree(pmic->desc);
+       kfree(pmic);
        return 0;
 }
 
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
new file mode 100644 (file)
index 0000000..3a9313e
--- /dev/null
@@ -0,0 +1,800 @@
+/*
+ * tps65912.c  --  TI tps65912
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk>
+ *
+ *  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 driver is based on wm8350 implementation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/mfd/tps65912.h>
+
+/* DCDC's */
+#define TPS65912_REG_DCDC1     0
+#define TPS65912_REG_DCDC2     1
+#define TPS65912_REG_DCDC3     2
+#define TPS65912_REG_DCDC4     3
+
+/* LDOs */
+#define TPS65912_REG_LDO1      4
+#define TPS65912_REG_LDO2      5
+#define TPS65912_REG_LDO3      6
+#define TPS65912_REG_LDO4      7
+#define TPS65912_REG_LDO5      8
+#define TPS65912_REG_LDO6      9
+#define TPS65912_REG_LDO7      10
+#define TPS65912_REG_LDO8      11
+#define TPS65912_REG_LDO9      12
+#define TPS65912_REG_LDO10     13
+
+#define TPS65912_MAX_REG_ID    TPS65912_REG_LDO_10
+
+/* Number of step-down converters available */
+#define TPS65912_NUM_DCDC      4
+
+/* Number of LDO voltage regulators  available */
+#define TPS65912_NUM_LDO       10
+
+/* Number of total regulators available */
+#define TPS65912_NUM_REGULATOR         (TPS65912_NUM_DCDC + TPS65912_NUM_LDO)
+
+#define TPS65912_REG_ENABLED   0x80
+#define OP_SELREG_MASK         0x40
+#define OP_SELREG_SHIFT                6
+
+struct tps_info {
+       const char *name;
+};
+
+static struct tps_info tps65912_regs[] = {
+       {
+               .name = "DCDC1",
+       },
+       {
+               .name = "DCDC2",
+       },
+       {
+               .name = "DCDC3",
+       },
+       {
+               .name = "DCDC4",
+       },
+       {
+               .name = "LDO1",
+       },
+       {
+               .name = "LDO2",
+       },
+       {
+               .name = "LDO3",
+       },
+       {
+               .name = "LDO4",
+       },
+       {
+               .name = "LDO5",
+       },
+       {
+               .name = "LDO6",
+       },
+       {
+               .name = "LDO7",
+       },
+       {
+               .name = "LDO8",
+       },
+       {
+               .name = "LDO9",
+       },
+       {
+               .name = "LDO10",
+       },
+};
+
+struct tps65912_reg {
+       struct regulator_desc desc[TPS65912_NUM_REGULATOR];
+       struct tps65912 *mfd;
+       struct regulator_dev *rdev[TPS65912_NUM_REGULATOR];
+       struct tps_info *info[TPS65912_NUM_REGULATOR];
+       /* for read/write access */
+       struct mutex io_lock;
+       int mode;
+       int (*get_ctrl_reg)(int);
+       int dcdc1_range;
+       int dcdc2_range;
+       int dcdc3_range;
+       int dcdc4_range;
+       int pwm_mode_reg;
+       int eco_reg;
+};
+
+static int tps65912_get_range(struct tps65912_reg *pmic, int id)
+{
+       struct tps65912 *mfd = pmic->mfd;
+
+       if (id > TPS65912_REG_DCDC4)
+               return 0;
+
+       switch (id) {
+       case TPS65912_REG_DCDC1:
+               pmic->dcdc1_range = tps65912_reg_read(mfd,
+                                                       TPS65912_DCDC1_LIMIT);
+               if (pmic->dcdc1_range < 0)
+                       return pmic->dcdc1_range;
+               pmic->dcdc1_range = (pmic->dcdc1_range &
+                       DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT;
+               return pmic->dcdc1_range;
+       case TPS65912_REG_DCDC2:
+               pmic->dcdc2_range = tps65912_reg_read(mfd,
+                                                       TPS65912_DCDC2_LIMIT);
+               if (pmic->dcdc2_range < 0)
+                       return pmic->dcdc2_range;
+               pmic->dcdc2_range = (pmic->dcdc2_range &
+                       DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT;
+               return pmic->dcdc2_range;
+       case TPS65912_REG_DCDC3:
+               pmic->dcdc3_range = tps65912_reg_read(mfd,
+                                                       TPS65912_DCDC3_LIMIT);
+               if (pmic->dcdc3_range < 0)
+                       return pmic->dcdc3_range;
+               pmic->dcdc3_range = (pmic->dcdc3_range &
+                       DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT;
+               return pmic->dcdc3_range;
+       case TPS65912_REG_DCDC4:
+               pmic->dcdc4_range = tps65912_reg_read(mfd,
+                                                       TPS65912_DCDC4_LIMIT);
+               if (pmic->dcdc4_range < 0)
+                       return pmic->dcdc4_range;
+               pmic->dcdc4_range = (pmic->dcdc4_range &
+                       DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT;
+               return pmic->dcdc4_range;
+       default:
+               return 0;
+       }
+}
+
+static unsigned long tps65912_vsel_to_uv_range0(u8 vsel)
+{
+       unsigned long uv;
+
+       uv = ((vsel * 12500) + 500000);
+       return uv;
+}
+
+static unsigned long tps65912_vsel_to_uv_range1(u8 vsel)
+{
+       unsigned long uv;
+
+        uv = ((vsel * 12500) + 700000);
+       return uv;
+}
+
+static unsigned long tps65912_vsel_to_uv_range2(u8 vsel)
+{
+       unsigned long uv;
+
+       uv = ((vsel * 25000) + 500000);
+       return uv;
+}
+
+static unsigned long tps65912_vsel_to_uv_range3(u8 vsel)
+{
+       unsigned long uv;
+
+       if (vsel == 0x3f)
+               uv = 3800000;
+       else
+               uv = ((vsel * 50000) + 500000);
+
+       return uv;
+}
+
+static unsigned long tps65912_vsel_to_uv_ldo(u8 vsel)
+{
+       unsigned long uv = 0;
+
+       if (vsel <= 32)
+               uv = ((vsel * 25000) + 800000);
+       else if (vsel > 32 && vsel <= 60)
+               uv = (((vsel - 32) * 50000) + 1600000);
+       else if (vsel > 60)
+               uv = (((vsel - 60) * 100000) + 3000000);
+
+       return uv;
+}
+
+static int tps65912_get_ctrl_register(int id)
+{
+       switch (id) {
+       case TPS65912_REG_DCDC1:
+               return TPS65912_DCDC1_AVS;
+       case TPS65912_REG_DCDC2:
+               return TPS65912_DCDC2_AVS;
+       case TPS65912_REG_DCDC3:
+               return TPS65912_DCDC3_AVS;
+       case TPS65912_REG_DCDC4:
+               return TPS65912_DCDC4_AVS;
+       case TPS65912_REG_LDO1:
+               return TPS65912_LDO1_AVS;
+       case TPS65912_REG_LDO2:
+               return TPS65912_LDO2_AVS;
+       case TPS65912_REG_LDO3:
+               return TPS65912_LDO3_AVS;
+       case TPS65912_REG_LDO4:
+               return TPS65912_LDO4_AVS;
+       case TPS65912_REG_LDO5:
+               return TPS65912_LDO5;
+       case TPS65912_REG_LDO6:
+               return TPS65912_LDO6;
+       case TPS65912_REG_LDO7:
+               return TPS65912_LDO7;
+       case TPS65912_REG_LDO8:
+               return TPS65912_LDO8;
+       case TPS65912_REG_LDO9:
+               return TPS65912_LDO9;
+       case TPS65912_REG_LDO10:
+               return TPS65912_LDO10;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int tps65912_get_dcdc_sel_register(struct tps65912_reg *pmic, int id)
+{
+       struct tps65912 *mfd = pmic->mfd;
+       int opvsel = 0, sr = 0;
+       u8 reg = 0;
+
+       if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_DCDC4)
+               return -EINVAL;
+
+       switch (id) {
+       case TPS65912_REG_DCDC1:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC1_OP);
+               sr = ((opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT);
+               if (sr)
+                       reg = TPS65912_DCDC1_AVS;
+               else
+                       reg = TPS65912_DCDC1_OP;
+               break;
+       case TPS65912_REG_DCDC2:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC2_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_DCDC2_AVS;
+               else
+                       reg = TPS65912_DCDC2_OP;
+               break;
+       case TPS65912_REG_DCDC3:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC3_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_DCDC3_AVS;
+               else
+                       reg = TPS65912_DCDC3_OP;
+               break;
+       case TPS65912_REG_DCDC4:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC4_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_DCDC4_AVS;
+               else
+                       reg = TPS65912_DCDC4_OP;
+               break;
+       }
+       return reg;
+}
+
+static int tps65912_get_ldo_sel_register(struct tps65912_reg *pmic, int id)
+{
+       struct tps65912 *mfd = pmic->mfd;
+       int opvsel = 0, sr = 0;
+       u8 reg = 0;
+
+       if (id < TPS65912_REG_LDO1 || id > TPS65912_REG_LDO10)
+               return -EINVAL;
+
+       switch (id) {
+       case TPS65912_REG_LDO1:
+               opvsel = tps65912_reg_read(mfd, TPS65912_LDO1_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_LDO1_AVS;
+               else
+                       reg = TPS65912_LDO1_OP;
+               break;
+       case TPS65912_REG_LDO2:
+               opvsel = tps65912_reg_read(mfd, TPS65912_LDO2_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_LDO2_AVS;
+               else
+                       reg = TPS65912_LDO2_OP;
+               break;
+       case TPS65912_REG_LDO3:
+               opvsel = tps65912_reg_read(mfd, TPS65912_LDO3_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_LDO3_AVS;
+               else
+                       reg = TPS65912_LDO3_OP;
+               break;
+       case TPS65912_REG_LDO4:
+               opvsel = tps65912_reg_read(mfd, TPS65912_LDO4_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_LDO4_AVS;
+               else
+                       reg = TPS65912_LDO4_OP;
+               break;
+       case TPS65912_REG_LDO5:
+               reg = TPS65912_LDO5;
+               break;
+       case TPS65912_REG_LDO6:
+               reg = TPS65912_LDO6;
+               break;
+       case TPS65912_REG_LDO7:
+               reg = TPS65912_LDO7;
+               break;
+       case TPS65912_REG_LDO8:
+               reg = TPS65912_LDO8;
+               break;
+       case TPS65912_REG_LDO9:
+               reg = TPS65912_LDO9;
+               break;
+       case TPS65912_REG_LDO10:
+               reg = TPS65912_LDO10;
+               break;
+       }
+
+       return reg;
+}
+
+static int tps65912_get_mode_regiters(struct tps65912_reg *pmic, int id)
+{
+       switch (id) {
+       case TPS65912_REG_DCDC1:
+               pmic->pwm_mode_reg = TPS65912_DCDC1_CTRL;
+               pmic->eco_reg = TPS65912_DCDC1_AVS;
+               break;
+       case TPS65912_REG_DCDC2:
+               pmic->pwm_mode_reg = TPS65912_DCDC2_CTRL;
+               pmic->eco_reg = TPS65912_DCDC2_AVS;
+               break;
+       case TPS65912_REG_DCDC3:
+               pmic->pwm_mode_reg = TPS65912_DCDC3_CTRL;
+               pmic->eco_reg = TPS65912_DCDC3_AVS;
+               break;
+       case TPS65912_REG_DCDC4:
+               pmic->pwm_mode_reg = TPS65912_DCDC4_CTRL;
+               pmic->eco_reg = TPS65912_DCDC4_AVS;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int tps65912_reg_is_enabled(struct regulator_dev *dev)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int reg, value, id = rdev_get_id(dev);
+
+       if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10)
+               return -EINVAL;
+
+       reg = pmic->get_ctrl_reg(id);
+       if (reg < 0)
+               return reg;
+
+       value = tps65912_reg_read(mfd, reg);
+       if (value < 0)
+               return value;
+
+       return value & TPS65912_REG_ENABLED;
+}
+
+static int tps65912_reg_enable(struct regulator_dev *dev)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev);
+       int reg;
+
+       if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10)
+               return -EINVAL;
+
+       reg = pmic->get_ctrl_reg(id);
+       if (reg < 0)
+               return reg;
+
+       return tps65912_set_bits(mfd, reg, TPS65912_REG_ENABLED);
+}
+
+static int tps65912_reg_disable(struct regulator_dev *dev)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev), reg;
+
+       reg = pmic->get_ctrl_reg(id);
+       if (reg < 0)
+               return reg;
+
+       return tps65912_clear_bits(mfd, reg, TPS65912_REG_ENABLED);
+}
+
+static int tps65912_set_mode(struct regulator_dev *dev, unsigned int mode)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int pwm_mode, eco, id = rdev_get_id(dev);
+
+       tps65912_get_mode_regiters(pmic, id);
+
+       pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg);
+       eco = tps65912_reg_read(mfd, pmic->eco_reg);
+
+       pwm_mode &= DCDCCTRL_DCDC_MODE_MASK;
+       eco &= DCDC_AVS_ECO_MASK;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               /* Verify if mode alredy set */
+               if (pwm_mode && !eco)
+                       break;
+               tps65912_set_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
+               tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
+               break;
+       case REGULATOR_MODE_NORMAL:
+       case REGULATOR_MODE_IDLE:
+               if (!pwm_mode && !eco)
+                       break;
+               tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
+               tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
+               break;
+       case REGULATOR_MODE_STANDBY:
+               if (!pwm_mode && eco)
+                       break;
+               tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
+               tps65912_set_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static unsigned int tps65912_get_mode(struct regulator_dev *dev)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int pwm_mode, eco, mode = 0, id = rdev_get_id(dev);
+
+       tps65912_get_mode_regiters(pmic, id);
+
+       pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg);
+       eco = tps65912_reg_read(mfd, pmic->eco_reg);
+
+       pwm_mode &= DCDCCTRL_DCDC_MODE_MASK;
+       eco &= DCDC_AVS_ECO_MASK;
+
+       if (pwm_mode && !eco)
+               mode = REGULATOR_MODE_FAST;
+       else if (!pwm_mode && !eco)
+               mode = REGULATOR_MODE_NORMAL;
+       else if (!pwm_mode && eco)
+               mode = REGULATOR_MODE_STANDBY;
+
+       return mode;
+}
+
+static int tps65912_get_voltage_dcdc(struct regulator_dev *dev)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev), voltage = 0, range;
+       int opvsel = 0, avsel = 0, sr, vsel;
+
+       switch (id) {
+       case TPS65912_REG_DCDC1:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC1_OP);
+               avsel = tps65912_reg_read(mfd, TPS65912_DCDC1_AVS);
+               range = pmic->dcdc1_range;
+               break;
+       case TPS65912_REG_DCDC2:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC2_OP);
+               avsel = tps65912_reg_read(mfd, TPS65912_DCDC2_AVS);
+               range = pmic->dcdc2_range;
+               break;
+       case TPS65912_REG_DCDC3:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC3_OP);
+               avsel = tps65912_reg_read(mfd, TPS65912_DCDC3_AVS);
+               range = pmic->dcdc3_range;
+               break;
+       case TPS65912_REG_DCDC4:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC4_OP);
+               avsel = tps65912_reg_read(mfd, TPS65912_DCDC4_AVS);
+               range = pmic->dcdc4_range;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+       if (sr)
+               vsel = avsel;
+       else
+               vsel = opvsel;
+       vsel &= 0x3F;
+
+       switch (range) {
+       case 0:
+               /* 0.5 - 1.2875V in 12.5mV steps */
+               voltage = tps65912_vsel_to_uv_range0(vsel);
+               break;
+       case 1:
+               /* 0.7 - 1.4875V in 12.5mV steps */
+               voltage = tps65912_vsel_to_uv_range1(vsel);
+               break;
+       case 2:
+               /* 0.5 - 2.075V in 25mV steps */
+               voltage = tps65912_vsel_to_uv_range2(vsel);
+               break;
+       case 3:
+               /* 0.5 - 3.8V in 50mV steps */
+               voltage = tps65912_vsel_to_uv_range3(vsel);
+               break;
+       }
+       return voltage;
+}
+
+static int tps65912_set_voltage_dcdc(struct regulator_dev *dev,
+                                               unsigned selector)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev);
+       int value;
+       u8 reg;
+
+       reg = tps65912_get_dcdc_sel_register(pmic, id);
+       value = tps65912_reg_read(mfd, reg);
+       value &= 0xC0;
+       return tps65912_reg_write(mfd, reg, selector | value);
+}
+
+static int tps65912_get_voltage_ldo(struct regulator_dev *dev)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev);
+       int vsel = 0;
+       u8 reg;
+
+       reg = tps65912_get_ldo_sel_register(pmic, id);
+       vsel = tps65912_reg_read(mfd, reg);
+       vsel &= 0x3F;
+
+       return tps65912_vsel_to_uv_ldo(vsel);
+}
+
+static int tps65912_set_voltage_ldo(struct regulator_dev *dev,
+                                               unsigned selector)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev), reg, value;
+
+       reg = tps65912_get_ldo_sel_register(pmic, id);
+       value = tps65912_reg_read(mfd, reg);
+       value &= 0xC0;
+       return tps65912_reg_write(mfd, reg, selector | value);
+}
+
+static int tps65912_list_voltage_dcdc(struct regulator_dev *dev,
+                                       unsigned selector)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       int range, voltage = 0, id = rdev_get_id(dev);
+
+       switch (id) {
+       case TPS65912_REG_DCDC1:
+               range = pmic->dcdc1_range;
+               break;
+       case TPS65912_REG_DCDC2:
+               range = pmic->dcdc2_range;
+               break;
+       case TPS65912_REG_DCDC3:
+               range = pmic->dcdc3_range;
+               break;
+       case TPS65912_REG_DCDC4:
+               range = pmic->dcdc4_range;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (range) {
+       case 0:
+               /* 0.5 - 1.2875V in 12.5mV steps */
+               voltage = tps65912_vsel_to_uv_range0(selector);
+               break;
+       case 1:
+               /* 0.7 - 1.4875V in 12.5mV steps */
+               voltage = tps65912_vsel_to_uv_range1(selector);
+               break;
+       case 2:
+               /* 0.5 - 2.075V in 25mV steps */
+               voltage = tps65912_vsel_to_uv_range2(selector);
+               break;
+       case 3:
+               /* 0.5 - 3.8V in 50mV steps */
+               voltage = tps65912_vsel_to_uv_range3(selector);
+               break;
+       }
+       return voltage;
+}
+
+static int tps65912_list_voltage_ldo(struct regulator_dev *dev,
+                                       unsigned selector)
+{
+       int ldo = rdev_get_id(dev);
+
+       if (ldo < TPS65912_REG_LDO1 || ldo > TPS65912_REG_LDO10)
+               return -EINVAL;
+
+       return tps65912_vsel_to_uv_ldo(selector);
+}
+
+/* Operations permitted on DCDCx */
+static struct regulator_ops tps65912_ops_dcdc = {
+       .is_enabled = tps65912_reg_is_enabled,
+       .enable = tps65912_reg_enable,
+       .disable = tps65912_reg_disable,
+       .set_mode = tps65912_set_mode,
+       .get_mode = tps65912_get_mode,
+       .get_voltage = tps65912_get_voltage_dcdc,
+       .set_voltage_sel = tps65912_set_voltage_dcdc,
+       .list_voltage = tps65912_list_voltage_dcdc,
+};
+
+/* Operations permitted on LDOx */
+static struct regulator_ops tps65912_ops_ldo = {
+       .is_enabled = tps65912_reg_is_enabled,
+       .enable = tps65912_reg_enable,
+       .disable = tps65912_reg_disable,
+       .get_voltage = tps65912_get_voltage_ldo,
+       .set_voltage_sel = tps65912_set_voltage_ldo,
+       .list_voltage = tps65912_list_voltage_ldo,
+};
+
+static __devinit int tps65912_probe(struct platform_device *pdev)
+{
+       struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
+       struct tps_info *info;
+       struct regulator_init_data *reg_data;
+       struct regulator_dev *rdev;
+       struct tps65912_reg *pmic;
+       struct tps65912_board *pmic_plat_data;
+       int i, err;
+
+       pmic_plat_data = dev_get_platdata(tps65912->dev);
+       if (!pmic_plat_data)
+               return -EINVAL;
+
+       reg_data = pmic_plat_data->tps65912_pmic_init_data;
+
+       pmic = kzalloc(sizeof(*pmic), GFP_KERNEL);
+       if (!pmic)
+               return -ENOMEM;
+
+       mutex_init(&pmic->io_lock);
+       pmic->mfd = tps65912;
+       platform_set_drvdata(pdev, pmic);
+
+       pmic->get_ctrl_reg = &tps65912_get_ctrl_register;
+       info = tps65912_regs;
+
+       for (i = 0; i < TPS65912_NUM_REGULATOR; i++, info++, reg_data++) {
+               int range = 0;
+               /* Register the regulators */
+               pmic->info[i] = info;
+
+               pmic->desc[i].name = info->name;
+               pmic->desc[i].id = i;
+               pmic->desc[i].n_voltages = 64;
+               pmic->desc[i].ops = (i > TPS65912_REG_DCDC4 ?
+                       &tps65912_ops_ldo : &tps65912_ops_dcdc);
+               pmic->desc[i].type = REGULATOR_VOLTAGE;
+               pmic->desc[i].owner = THIS_MODULE;
+               range = tps65912_get_range(pmic, i);
+               rdev = regulator_register(&pmic->desc[i],
+                                       tps65912->dev, reg_data, pmic);
+               if (IS_ERR(rdev)) {
+                       dev_err(tps65912->dev,
+                               "failed to register %s regulator\n",
+                               pdev->name);
+                       err = PTR_ERR(rdev);
+                       goto err;
+               }
+
+               /* Save regulator for cleanup */
+               pmic->rdev[i] = rdev;
+       }
+       return 0;
+
+err:
+       while (--i >= 0)
+               regulator_unregister(pmic->rdev[i]);
+
+       kfree(pmic);
+       return err;
+}
+
+static int __devexit tps65912_remove(struct platform_device *pdev)
+{
+       struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < TPS65912_NUM_REGULATOR; i++)
+               regulator_unregister(tps65912_reg->rdev[i]);
+
+       kfree(tps65912_reg);
+       return 0;
+}
+
+static struct platform_driver tps65912_driver = {
+       .driver = {
+               .name = "tps65912-pmic",
+               .owner = THIS_MODULE,
+       },
+       .probe = tps65912_probe,
+       .remove = __devexit_p(tps65912_remove),
+};
+
+/**
+ * tps65912_init
+ *
+ * Module init function
+ */
+static int __init tps65912_init(void)
+{
+       return platform_driver_register(&tps65912_driver);
+}
+subsys_initcall(tps65912_init);
+
+/**
+ * tps65912_cleanup
+ *
+ * Module exit function
+ */
+static void __exit tps65912_cleanup(void)
+{
+       platform_driver_unregister(&tps65912_driver);
+}
+module_exit(tps65912_cleanup);
+
+MODULE_AUTHOR("Margarita Olaya Cabrera <magi@slimlogic.co.uk>");
+MODULE_DESCRIPTION("TPS65912 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tps65912-pmic");
index 87fe0f7..ee8747f 100644 (file)
@@ -835,8 +835,8 @@ static struct regulator_ops twlsmps_ops = {
                        remap_conf) \
                TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
                        remap_conf, TWL4030, twl4030fixed_ops)
-#define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay) \
-               TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
+#define TWL6030_FIXED_LDO(label, offset, mVolts, turnon_delay) \
+               TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \
                        0x0, TWL6030, twl6030fixed_ops)
 
 #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) { \
@@ -856,24 +856,22 @@ static struct regulator_ops twlsmps_ops = {
                }, \
        }
 
-#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \
+#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \
        .base = offset, \
-       .id = num, \
        .min_mV = min_mVolts, \
        .max_mV = max_mVolts, \
        .desc = { \
                .name = #label, \
                .id = TWL6030_REG_##label, \
-               .n_voltages = (max_mVolts - min_mVolts)/100, \
+               .n_voltages = (max_mVolts - min_mVolts)/100 + 1, \
                .ops = &twl6030ldo_ops, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
                }, \
        }
 
-#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \
+#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \
        .base = offset, \
-       .id = num, \
        .min_mV = min_mVolts, \
        .max_mV = max_mVolts, \
        .desc = { \
@@ -903,9 +901,8 @@ static struct regulator_ops twlsmps_ops = {
                }, \
        }
 
-#define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay) { \
+#define TWL6030_FIXED_RESOURCE(label, offset, turnon_delay) { \
        .base = offset, \
-       .id = num, \
        .delay = turnon_delay, \
        .desc = { \
                .name = #label, \
@@ -916,9 +913,8 @@ static struct regulator_ops twlsmps_ops = {
                }, \
        }
 
-#define TWL6025_ADJUSTABLE_SMPS(label, offset, num) { \
+#define TWL6025_ADJUSTABLE_SMPS(label, offset) { \
        .base = offset, \
-       .id = num, \
        .min_mV = 600, \
        .max_mV = 2100, \
        .desc = { \
@@ -961,32 +957,32 @@ static struct twlreg_info twl_regs[] = {
        /* 6030 REG with base as PMC Slave Misc : 0x0030 */
        /* Turnon-delay and remap configuration values for 6030 are not
           verified since the specification is not public */
-       TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1),
-       TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2),
-       TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3),
-       TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4),
-       TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5),
-       TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7),
-       TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0),
-       TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0),
-       TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0),
-       TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0),
-       TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0),
+       TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300),
+       TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300),
+       TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300),
+       TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300),
+       TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300),
+       TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300),
+       TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0),
+       TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0),
+       TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0),
+       TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0),
+       TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0),
 
        /* 6025 are renamed compared to 6030 versions */
-       TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300, 1),
-       TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300, 2),
-       TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300, 3),
-       TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300, 4),
-       TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300, 5),
-       TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300, 7),
-       TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300, 16),
-       TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300, 17),
-       TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300, 18),
-
-       TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34, 1),
-       TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10, 2),
-       TWL6025_ADJUSTABLE_SMPS(VIO, 0x16, 3),
+       TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300),
+
+       TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34),
+       TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10),
+       TWL6025_ADJUSTABLE_SMPS(VIO, 0x16),
 };
 
 static u8 twl_get_smps_offset(void)
index a0982e8..bd3531d 100644 (file)
@@ -267,23 +267,6 @@ static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev,
        return vsel;
 }
 
-static int wm831x_buckv_select_max_voltage(struct regulator_dev *rdev,
-                                          int min_uV, int max_uV)
-{
-       u16 vsel;
-
-       if (max_uV < 600000 || max_uV > 1800000)
-               return -EINVAL;
-
-       vsel = ((max_uV - 600000) / 12500) + 8;
-
-       if (wm831x_buckv_list_voltage(rdev, vsel) < min_uV ||
-           wm831x_buckv_list_voltage(rdev, vsel) < max_uV)
-               return -EINVAL;
-
-       return vsel;
-}
-
 static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
 {
        struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
@@ -338,28 +321,23 @@ static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
        if (ret < 0)
                return ret;
 
-       /* Set the high voltage as the DVS voltage.  This is optimised
-        * for CPUfreq usage, most processors will keep the maximum
-        * voltage constant and lower the minimum with the frequency. */
-       vsel = wm831x_buckv_select_max_voltage(rdev, min_uV, max_uV);
-       if (vsel < 0) {
-               /* This should never happen - at worst the same vsel
-                * should be chosen */
-               WARN_ON(vsel < 0);
-               return 0;
+       /*
+        * If this VSEL is higher than the last one we've seen then
+        * remember it as the DVS VSEL.  This is optimised for CPUfreq
+        * usage where we want to get to the highest voltage very
+        * quickly.
+        */
+       if (vsel > dcdc->dvs_vsel) {
+               ret = wm831x_set_bits(wm831x, dvs_reg,
+                                     WM831X_DC1_DVS_VSEL_MASK,
+                                     dcdc->dvs_vsel);
+               if (ret == 0)
+                       dcdc->dvs_vsel = vsel;
+               else
+                       dev_warn(wm831x->dev,
+                                "Failed to set DCDC DVS VSEL: %d\n", ret);
        }
 
-       /* Don't bother if it's the same VSEL we're already using */
-       if (vsel == dcdc->on_vsel)
-               return 0;
-
-       ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, vsel);
-       if (ret == 0)
-               dcdc->dvs_vsel = vsel;
-       else
-               dev_warn(wm831x->dev, "Failed to set DCDC DVS VSEL: %d\n",
-                        ret);
-
        return 0;
 }
 
@@ -456,27 +434,6 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
        if (!pdata || !pdata->dvs_gpio)
                return;
 
-       switch (pdata->dvs_control_src) {
-       case 1:
-               ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT;
-               break;
-       case 2:
-               ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT;
-               break;
-       default:
-               dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n",
-                       pdata->dvs_control_src, dcdc->name);
-               return;
-       }
-
-       ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL,
-                             WM831X_DC1_DVS_SRC_MASK, ctrl);
-       if (ret < 0) {
-               dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n",
-                       dcdc->name, ret);
-               return;
-       }
-
        ret = gpio_request(pdata->dvs_gpio, "DCDC DVS");
        if (ret < 0) {
                dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n",
@@ -498,17 +455,57 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
        }
 
        dcdc->dvs_gpio = pdata->dvs_gpio;
+
+       switch (pdata->dvs_control_src) {
+       case 1:
+               ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT;
+               break;
+       case 2:
+               ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT;
+               break;
+       default:
+               dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n",
+                       pdata->dvs_control_src, dcdc->name);
+               return;
+       }
+
+       /* If DVS_VSEL is set to the minimum value then raise it to ON_VSEL
+        * to make bootstrapping a bit smoother.
+        */
+       if (!dcdc->dvs_vsel) {
+               ret = wm831x_set_bits(wm831x,
+                                     dcdc->base + WM831X_DCDC_DVS_CONTROL,
+                                     WM831X_DC1_DVS_VSEL_MASK, dcdc->on_vsel);
+               if (ret == 0)
+                       dcdc->dvs_vsel = dcdc->on_vsel;
+               else
+                       dev_warn(wm831x->dev, "Failed to set DVS_VSEL: %d\n",
+                                ret);
+       }
+
+       ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL,
+                             WM831X_DC1_DVS_SRC_MASK, ctrl);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n",
+                       dcdc->name, ret);
+       }
 }
 
 static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-       int id = pdev->id % ARRAY_SIZE(pdata->dcdc);
+       int id;
        struct wm831x_dcdc *dcdc;
        struct resource *res;
        int ret, irq;
 
+       if (pdata && pdata->wm831x_num)
+               id = (pdata->wm831x_num * 10) + 1;
+       else
+               id = 0;
+       id = pdev->id - id;
+
        dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);
 
        if (pdata == NULL || pdata->dcdc[id] == NULL)
@@ -545,7 +542,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
        }
        dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK;
 
-       ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG);
+       ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL);
        if (ret < 0) {
                dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret);
                goto err;
@@ -709,11 +706,17 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-       int id = pdev->id % ARRAY_SIZE(pdata->dcdc);
+       int id;
        struct wm831x_dcdc *dcdc;
        struct resource *res;
        int ret, irq;
 
+       if (pdata && pdata->wm831x_num)
+               id = (pdata->wm831x_num * 10) + 1;
+       else
+               id = 0;
+       id = pdev->id - id;
+
        dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);
 
        if (pdata == NULL || pdata->dcdc[id] == NULL)
@@ -1046,3 +1049,4 @@ MODULE_DESCRIPTION("WM831x DC-DC convertor driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:wm831x-buckv");
 MODULE_ALIAS("platform:wm831x-buckp");
+MODULE_ALIAS("platform:wm831x-epe");
index 2220cf8..6709710 100644 (file)
@@ -310,11 +310,17 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-       int id = pdev->id % ARRAY_SIZE(pdata->ldo);
+       int id;
        struct wm831x_ldo *ldo;
        struct resource *res;
        int ret, irq;
 
+       if (pdata && pdata->wm831x_num)
+               id = (pdata->wm831x_num * 10) + 1;
+       else
+               id = 0;
+       id = pdev->id - id;
+
        dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
 
        if (pdata == NULL || pdata->ldo[id] == NULL)
@@ -574,11 +580,17 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-       int id = pdev->id % ARRAY_SIZE(pdata->ldo);
+       int id;
        struct wm831x_ldo *ldo;
        struct resource *res;
        int ret, irq;
 
+       if (pdata && pdata->wm831x_num)
+               id = (pdata->wm831x_num * 10) + 1;
+       else
+               id = 0;
+       id = pdev->id - id;
+
        dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
 
        if (pdata == NULL || pdata->ldo[id] == NULL)
@@ -764,11 +776,18 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-       int id = pdev->id % ARRAY_SIZE(pdata->ldo);
+       int id;
        struct wm831x_ldo *ldo;
        struct resource *res;
        int ret;
 
+       if (pdata && pdata->wm831x_num)
+               id = (pdata->wm831x_num * 10) + 1;
+       else
+               id = 0;
+       id = pdev->id - id;
+
+
        dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
 
        if (pdata == NULL || pdata->ldo[id] == NULL)
index 35b2958..1a6a690 100644 (file)
@@ -43,7 +43,7 @@ static int wm8994_ldo_enable(struct regulator_dev *rdev)
        if (!ldo->enable)
                return 0;
 
-       gpio_set_value(ldo->enable, 1);
+       gpio_set_value_cansleep(ldo->enable, 1);
        ldo->is_enabled = true;
 
        return 0;
@@ -57,7 +57,7 @@ static int wm8994_ldo_disable(struct regulator_dev *rdev)
        if (!ldo->enable)
                return -EINVAL;
 
-       gpio_set_value(ldo->enable, 0);
+       gpio_set_value_cansleep(ldo->enable, 0);
        ldo->is_enabled = false;
 
        return 0;
index bcae8dd..7789002 100644 (file)
@@ -368,7 +368,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
                pr_info("%s: already running\n", pdev->name);
 
        /* force to 24 hour mode */
-       new_ctrl = reg & ~(OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP);
+       new_ctrl = reg & (OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP);
        new_ctrl |= OMAP_RTC_CTRL_STOP;
 
        /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE:
index 432444a..a1d3ddb 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/mutex.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/vmalloc.h>
 
 #include <asm/ccwdev.h>
 #include <asm/ebcdic.h>
@@ -888,11 +889,11 @@ char *dasd_get_user_string(const char __user *user_buf, size_t user_len)
 {
        char *buffer;
 
-       buffer = kmalloc(user_len + 1, GFP_KERNEL);
+       buffer = vmalloc(user_len + 1);
        if (buffer == NULL)
                return ERR_PTR(-ENOMEM);
        if (copy_from_user(buffer, user_buf, user_len) != 0) {
-               kfree(buffer);
+               vfree(buffer);
                return ERR_PTR(-EFAULT);
        }
        /* got the string, now strip linefeed. */
@@ -930,7 +931,7 @@ static ssize_t dasd_stats_write(struct file *file,
                dasd_profile_off(prof);
        } else
                rc = -EINVAL;
-       kfree(buffer);
+       vfree(buffer);
        return rc;
 }
 
@@ -1042,7 +1043,7 @@ static ssize_t dasd_stats_global_write(struct file *file,
                dasd_global_profile_level = DASD_PROFILE_OFF;
        } else
                rc = -EINVAL;
-       kfree(buffer);
+       vfree(buffer);
        return rc;
 }
 
index 30fb979..6e835c9 100644 (file)
@@ -1461,6 +1461,15 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
                                "Read device characteristic failed, rc=%d", rc);
                goto out_err3;
        }
+
+       if ((device->features & DASD_FEATURE_USERAW) &&
+           !(private->rdc_data.facilities.RT_in_LR)) {
+               dev_err(&device->cdev->dev, "The storage server does not "
+                       "support raw-track access\n");
+               rc = -EINVAL;
+               goto out_err3;
+       }
+
        /* find the valid cylinder size */
        if (private->rdc_data.no_cyl == LV_COMPAT_CYL &&
            private->rdc_data.long_no_cyl)
index 6c3c536..e12989f 100644 (file)
@@ -312,14 +312,14 @@ static ssize_t dasd_stats_proc_write(struct file *file,
                pr_info("The statistics have been reset\n");
        } else
                goto out_parse_error;
-       kfree(buffer);
+       vfree(buffer);
        return user_len;
 out_parse_error:
        rc = -EINVAL;
        pr_warning("%s is not a supported value for /proc/dasd/statistics\n",
                str);
 out_error:
-       kfree(buffer);
+       vfree(buffer);
        return rc;
 #else
        pr_warning("/proc/dasd/statistics: is not activated in this kernel\n");
index 7ad30e7..5f9f929 100644 (file)
@@ -82,12 +82,9 @@ static int proc_handler_callhome(struct ctl_table *ctl, int write,
                        return -EFAULT;
        } else {
                len = *count;
-               rc = copy_from_user(buf, buffer, sizeof(buf));
-               if (rc != 0)
-                       return -EFAULT;
-               buf[sizeof(buf) - 1] = '\0';
-               if (strict_strtoul(buf, 0, &val) != 0)
-                       return -EINVAL;
+               rc = kstrtoul_from_user(buffer, len, 0, &val);
+               if (rc)
+                       return rc;
                if (val != 0 && val != 1)
                        return -EINVAL;
                callhome_enabled = val;
index 7bc643f..3dd8644 100644 (file)
@@ -14,6 +14,8 @@
 #include "chsc.h"
 
 #define QDIO_BUSY_BIT_PATIENCE         (100 << 12)     /* 100 microseconds */
+#define QDIO_BUSY_BIT_RETRY_DELAY      10              /* 10 milliseconds */
+#define QDIO_BUSY_BIT_RETRIES          1000            /* = 10s retry time */
 #define QDIO_INPUT_THRESHOLD           (500 << 12)     /* 500 microseconds */
 
 /*
@@ -42,6 +44,7 @@ enum qdio_irq_states {
 #define SLSB_STATE_NOT_INIT    0x0
 #define SLSB_STATE_EMPTY       0x1
 #define SLSB_STATE_PRIMED      0x2
+#define SLSB_STATE_PENDING     0x3
 #define SLSB_STATE_HALTED      0xe
 #define SLSB_STATE_ERROR       0xf
 #define SLSB_TYPE_INPUT                0x0
@@ -65,6 +68,8 @@ enum qdio_irq_states {
        (SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_NOT_INIT) /* 0xa0 */
 #define SLSB_P_OUTPUT_EMPTY    \
        (SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_EMPTY)    /* 0xa1 */
+#define SLSB_P_OUTPUT_PENDING \
+       (SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_PENDING)  /* 0xa3 */
 #define SLSB_CU_OUTPUT_PRIMED  \
        (SLSB_OWNER_CU | SLSB_TYPE_OUTPUT | SLSB_STATE_PRIMED)     /* 0x62 */
 #define SLSB_P_OUTPUT_HALTED   \
@@ -82,19 +87,11 @@ enum qdio_irq_states {
 #define CHSC_FLAG_QDIO_CAPABILITY      0x80
 #define CHSC_FLAG_VALIDITY             0x40
 
-/* qdio adapter-characteristics-1 flag */
-#define AC1_SIGA_INPUT_NEEDED          0x40    /* process input queues */
-#define AC1_SIGA_OUTPUT_NEEDED         0x20    /* process output queues */
-#define AC1_SIGA_SYNC_NEEDED           0x10    /* ask hypervisor to sync */
-#define AC1_AUTOMATIC_SYNC_ON_THININT  0x08    /* set by hypervisor */
-#define AC1_AUTOMATIC_SYNC_ON_OUT_PCI  0x04    /* set by hypervisor */
-#define AC1_SC_QEBSM_AVAILABLE         0x02    /* available for subchannel */
-#define AC1_SC_QEBSM_ENABLED           0x01    /* enabled for subchannel */
-
 /* SIGA flags */
 #define QDIO_SIGA_WRITE                0x00
 #define QDIO_SIGA_READ         0x01
 #define QDIO_SIGA_SYNC         0x02
+#define QDIO_SIGA_WRITEQ       0x04
 #define QDIO_SIGA_QEBSM_FLAG   0x80
 
 #ifdef CONFIG_64BIT
@@ -251,6 +248,12 @@ struct qdio_input_q {
 struct qdio_output_q {
        /* PCIs are enabled for the queue */
        int pci_out_enabled;
+       /* cq: use asynchronous output buffers */
+       int use_cq;
+       /* cq: aobs used for particual SBAL */
+       struct qaob **aobs;
+       /* cq: sbal state related to asynchronous operation */
+       struct qdio_outbuf_state *sbal_state;
        /* timer to check for more outbound work */
        struct timer_list timer;
        /* used SBALs before tasklet schedule */
@@ -430,9 +433,20 @@ struct indicator_t {
 
 extern struct indicator_t *q_indicators;
 
-static inline int shared_ind(u32 *dsci)
+static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq)
+{
+       return irq->nr_input_qs > 1;
+}
+
+static inline int references_shared_dsci(struct qdio_irq *irq)
 {
-       return dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
+       return irq->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
+}
+
+static inline int shared_ind(struct qdio_q *q)
+{
+       struct qdio_irq *i = q->irq_ptr;
+       return references_shared_dsci(i) || has_multiple_inq_on_dsci(i);
 }
 
 /* prototypes for thin interrupt */
@@ -447,6 +461,7 @@ void tiqdio_free_memory(void);
 int tiqdio_register_thinints(void);
 void tiqdio_unregister_thinints(void);
 
+
 /* prototypes for setup */
 void qdio_inbound_processing(unsigned long data);
 void qdio_outbound_processing(unsigned long data);
@@ -467,6 +482,9 @@ int qdio_setup_create_sysfs(struct ccw_device *cdev);
 void qdio_setup_destroy_sysfs(struct ccw_device *cdev);
 int qdio_setup_init(void);
 void qdio_setup_exit(void);
+int qdio_enable_async_operation(struct qdio_output_q *q);
+void qdio_disable_async_operation(struct qdio_output_q *q);
+struct qaob *qdio_allocate_aob(void);
 
 int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
                        unsigned char *state);
index f8b03a6..aaf7f93 100644 (file)
@@ -76,6 +76,9 @@ static int qstat_show(struct seq_file *m, void *v)
                case SLSB_P_OUTPUT_NOT_INIT:
                        seq_printf(m, "N");
                        break;
+               case SLSB_P_OUTPUT_PENDING:
+                       seq_printf(m, "P");
+                       break;
                case SLSB_P_INPUT_PRIMED:
                case SLSB_CU_OUTPUT_PRIMED:
                        seq_printf(m, "+");
@@ -188,19 +191,13 @@ static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
        struct qdio_irq *irq_ptr = seq->private;
        struct qdio_q *q;
        unsigned long val;
-       char buf[8];
        int ret, i;
 
        if (!irq_ptr)
                return 0;
-       if (count >= sizeof(buf))
-               return -EINVAL;
-       if (copy_from_user(&buf, ubuf, count))
-               return -EFAULT;
-       buf[count] = 0;
-
-       ret = strict_strtoul(buf, 10, &val);
-       if (ret < 0)
+
+       ret = kstrtoul_from_user(ubuf, count, 10, &val);
+       if (ret)
                return ret;
 
        switch (val) {
index e58169c..9a12228 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
+#include <linux/io.h>
 #include <linux/kernel_stat.h>
 #include <linux/atomic.h>
 #include <asm/debug.h>
@@ -77,11 +78,13 @@ static inline int do_siga_input(unsigned long schid, unsigned int mask,
  * Note: For IQDC unicast queues only the highest priority queue is processed.
  */
 static inline int do_siga_output(unsigned long schid, unsigned long mask,
-                                unsigned int *bb, unsigned int fc)
+                                unsigned int *bb, unsigned int fc,
+                                unsigned long aob)
 {
        register unsigned long __fc asm("0") = fc;
        register unsigned long __schid asm("1") = schid;
        register unsigned long __mask asm("2") = mask;
+       register unsigned long __aob asm("3") = aob;
        int cc = QDIO_ERROR_SIGA_ACCESS_EXCEPTION;
 
        asm volatile(
@@ -90,7 +93,8 @@ static inline int do_siga_output(unsigned long schid, unsigned long mask,
                "       srl     %0,28\n"
                "1:\n"
                EX_TABLE(0b, 1b)
-               : "+d" (cc), "+d" (__fc), "+d" (__schid), "+d" (__mask)
+               : "+d" (cc), "+d" (__fc), "+d" (__schid), "+d" (__mask),
+                 "+d" (__aob)
                : : "cc", "memory");
        *bb = ((unsigned int) __fc) >> 31;
        return cc;
@@ -212,7 +216,7 @@ again:
 /* returns number of examined buffers and their common state in *state */
 static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr,
                                 unsigned char *state, unsigned int count,
-                                int auto_ack)
+                                int auto_ack, int merge_pending)
 {
        unsigned char __state = 0;
        int i;
@@ -224,9 +228,14 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr,
                return qdio_do_eqbs(q, state, bufnr, count, auto_ack);
 
        for (i = 0; i < count; i++) {
-               if (!__state)
+               if (!__state) {
                        __state = q->slsb.val[bufnr];
-               else if (q->slsb.val[bufnr] != __state)
+                       if (merge_pending && __state == SLSB_P_OUTPUT_PENDING)
+                               __state = SLSB_P_OUTPUT_EMPTY;
+               } else if (merge_pending) {
+                       if ((q->slsb.val[bufnr] & __state) != __state)
+                               break;
+               } else if (q->slsb.val[bufnr] != __state)
                        break;
                bufnr = next_buf(bufnr);
        }
@@ -237,7 +246,7 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr,
 static inline int get_buf_state(struct qdio_q *q, unsigned int bufnr,
                                unsigned char *state, int auto_ack)
 {
-       return get_buf_states(q, bufnr, state, 1, auto_ack);
+       return get_buf_states(q, bufnr, state, 1, auto_ack, 0);
 }
 
 /* wrap-around safe setting of slsb states, returns number of changed buffers */
@@ -308,23 +317,33 @@ static inline int qdio_siga_sync_q(struct qdio_q *q)
                return qdio_siga_sync(q, q->mask, 0);
 }
 
-static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit)
+static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit,
+       unsigned long aob)
 {
        unsigned long schid = *((u32 *) &q->irq_ptr->schid);
        unsigned int fc = QDIO_SIGA_WRITE;
        u64 start_time = 0;
-       int cc;
+       int retries = 0, cc;
+       unsigned long laob = 0;
+
+       if (q->u.out.use_cq && aob != 0) {
+               fc = QDIO_SIGA_WRITEQ;
+               laob = aob;
+       }
 
        if (is_qebsm(q)) {
                schid = q->irq_ptr->sch_token;
                fc |= QDIO_SIGA_QEBSM_FLAG;
        }
 again:
-       cc = do_siga_output(schid, q->mask, busy_bit, fc);
+       WARN_ON_ONCE((aob && queue_type(q) != QDIO_IQDIO_QFMT) ||
+               (aob && fc != QDIO_SIGA_WRITEQ));
+       cc = do_siga_output(schid, q->mask, busy_bit, fc, laob);
 
        /* hipersocket busy condition */
        if (unlikely(*busy_bit)) {
                WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2);
+               retries++;
 
                if (!start_time) {
                        start_time = get_clock();
@@ -333,6 +352,11 @@ again:
                if ((get_clock() - start_time) < QDIO_BUSY_BIT_PATIENCE)
                        goto again;
        }
+       if (retries) {
+               DBF_DEV_EVENT(DBF_WARN, q->irq_ptr,
+                             "%4x cc2 BB1:%1d", SCH_NO(q), q->nr);
+               DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "count:%u", retries);
+       }
        return cc;
 }
 
@@ -373,7 +397,7 @@ int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
 {
        if (need_siga_sync(q))
                qdio_siga_sync_q(q);
-       return get_buf_states(q, bufnr, state, 1, 0);
+       return get_buf_states(q, bufnr, state, 1, 0, 0);
 }
 
 static inline void qdio_stop_polling(struct qdio_q *q)
@@ -501,7 +525,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
         * No siga sync here, as a PCI or we after a thin interrupt
         * already sync'ed the queues.
         */
-       count = get_buf_states(q, q->first_to_check, &state, count, 1);
+       count = get_buf_states(q, q->first_to_check, &state, count, 1, 0);
        if (!count)
                goto out;
 
@@ -584,6 +608,107 @@ static inline int qdio_inbound_q_done(struct qdio_q *q)
                return 0;
 }
 
+static inline int contains_aobs(struct qdio_q *q)
+{
+       return !q->is_input_q && q->u.out.use_cq;
+}
+
+static inline void qdio_trace_aob(struct qdio_irq *irq, struct qdio_q *q,
+                               int i, struct qaob *aob)
+{
+       int tmp;
+
+       DBF_DEV_EVENT(DBF_INFO, irq, "AOB%d:%lx", i,
+                       (unsigned long) virt_to_phys(aob));
+       DBF_DEV_EVENT(DBF_INFO, irq, "RES00:%lx",
+                       (unsigned long) aob->res0[0]);
+       DBF_DEV_EVENT(DBF_INFO, irq, "RES01:%lx",
+                       (unsigned long) aob->res0[1]);
+       DBF_DEV_EVENT(DBF_INFO, irq, "RES02:%lx",
+                       (unsigned long) aob->res0[2]);
+       DBF_DEV_EVENT(DBF_INFO, irq, "RES03:%lx",
+                       (unsigned long) aob->res0[3]);
+       DBF_DEV_EVENT(DBF_INFO, irq, "RES04:%lx",
+                       (unsigned long) aob->res0[4]);
+       DBF_DEV_EVENT(DBF_INFO, irq, "RES05:%lx",
+                       (unsigned long) aob->res0[5]);
+       DBF_DEV_EVENT(DBF_INFO, irq, "RES1:%x", aob->res1);
+       DBF_DEV_EVENT(DBF_INFO, irq, "RES2:%x", aob->res2);
+       DBF_DEV_EVENT(DBF_INFO, irq, "RES3:%x", aob->res3);
+       DBF_DEV_EVENT(DBF_INFO, irq, "AORC:%u", aob->aorc);
+       DBF_DEV_EVENT(DBF_INFO, irq, "FLAGS:%u", aob->flags);
+       DBF_DEV_EVENT(DBF_INFO, irq, "CBTBS:%u", aob->cbtbs);
+       DBF_DEV_EVENT(DBF_INFO, irq, "SBC:%u", aob->sb_count);
+       for (tmp = 0; tmp < QDIO_MAX_ELEMENTS_PER_BUFFER; ++tmp) {
+               DBF_DEV_EVENT(DBF_INFO, irq, "SBA%d:%lx", tmp,
+                               (unsigned long) aob->sba[tmp]);
+               DBF_DEV_EVENT(DBF_INFO, irq, "rSBA%d:%lx", tmp,
+                               (unsigned long) q->sbal[i]->element[tmp].addr);
+               DBF_DEV_EVENT(DBF_INFO, irq, "DC%d:%u", tmp, aob->dcount[tmp]);
+               DBF_DEV_EVENT(DBF_INFO, irq, "rDC%d:%u", tmp,
+                               q->sbal[i]->element[tmp].length);
+       }
+       DBF_DEV_EVENT(DBF_INFO, irq, "USER0:%lx", (unsigned long) aob->user0);
+       for (tmp = 0; tmp < 2; ++tmp) {
+               DBF_DEV_EVENT(DBF_INFO, irq, "RES4%d:%lx", tmp,
+                       (unsigned long) aob->res4[tmp]);
+       }
+       DBF_DEV_EVENT(DBF_INFO, irq, "USER1:%lx", (unsigned long) aob->user1);
+       DBF_DEV_EVENT(DBF_INFO, irq, "USER2:%lx", (unsigned long) aob->user2);
+}
+
+static inline void qdio_handle_aobs(struct qdio_q *q, int start, int count)
+{
+       unsigned char state = 0;
+       int j, b = start;
+
+       if (!contains_aobs(q))
+               return;
+
+       for (j = 0; j < count; ++j) {
+               get_buf_state(q, b, &state, 0);
+               if (state == SLSB_P_OUTPUT_PENDING) {
+                       struct qaob *aob = q->u.out.aobs[b];
+                       if (aob == NULL)
+                               continue;
+
+                       BUG_ON(q->u.out.sbal_state == NULL);
+                       q->u.out.sbal_state[b].flags |=
+                               QDIO_OUTBUF_STATE_FLAG_PENDING;
+                       q->u.out.aobs[b] = NULL;
+               } else if (state == SLSB_P_OUTPUT_EMPTY) {
+                       BUG_ON(q->u.out.sbal_state == NULL);
+                       q->u.out.sbal_state[b].aob = NULL;
+               }
+               b = next_buf(b);
+       }
+}
+
+static inline unsigned long qdio_aob_for_buffer(struct qdio_output_q *q,
+                                       int bufnr)
+{
+       unsigned long phys_aob = 0;
+
+       if (!q->use_cq)
+               goto out;
+
+       if (!q->aobs[bufnr]) {
+               struct qaob *aob = qdio_allocate_aob();
+               q->aobs[bufnr] = aob;
+       }
+       if (q->aobs[bufnr]) {
+               BUG_ON(q->sbal_state == NULL);
+               q->sbal_state[bufnr].flags = QDIO_OUTBUF_STATE_FLAG_NONE;
+               q->sbal_state[bufnr].aob = q->aobs[bufnr];
+               q->aobs[bufnr]->user1 = (u64) q->sbal_state[bufnr].user;
+               phys_aob = virt_to_phys(q->aobs[bufnr]);
+               BUG_ON(phys_aob & 0xFF);
+       }
+
+out:
+       return phys_aob;
+}
+
 static void qdio_kick_handler(struct qdio_q *q)
 {
        int start = q->first_to_kick;
@@ -604,6 +729,8 @@ static void qdio_kick_handler(struct qdio_q *q)
                              start, count);
        }
 
+       qdio_handle_aobs(q, start, count);
+
        q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count,
                   q->irq_ptr->int_parm);
 
@@ -666,23 +793,26 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
         */
        count = min(atomic_read(&q->nr_buf_used), QDIO_MAX_BUFFERS_MASK);
        stop = add_buf(q->first_to_check, count);
-
        if (q->first_to_check == stop)
-               return q->first_to_check;
+               goto out;
 
-       count = get_buf_states(q, q->first_to_check, &state, count, 0);
+       count = get_buf_states(q, q->first_to_check, &state, count, 0, 1);
        if (!count)
-               return q->first_to_check;
+               goto out;
 
        switch (state) {
+       case SLSB_P_OUTPUT_PENDING:
+               BUG();
        case SLSB_P_OUTPUT_EMPTY:
                /* the adapter got it */
-               DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out empty:%1d %02x", q->nr, count);
+               DBF_DEV_EVENT(DBF_INFO, q->irq_ptr,
+                       "out empty:%1d %02x", q->nr, count);
 
                atomic_sub(count, &q->nr_buf_used);
                q->first_to_check = add_buf(q->first_to_check, count);
                if (q->irq_ptr->perf_stat_enabled)
                        account_sbals(q, count);
+
                break;
        case SLSB_P_OUTPUT_ERROR:
                process_buffer_error(q, count);
@@ -695,7 +825,8 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
                /* the adapter has not fetched the output yet */
                if (q->irq_ptr->perf_stat_enabled)
                        q->q_stats.nr_sbal_nop++;
-               DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out primed:%1d", q->nr);
+               DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out primed:%1d",
+                             q->nr);
                break;
        case SLSB_P_OUTPUT_NOT_INIT:
        case SLSB_P_OUTPUT_HALTED:
@@ -703,6 +834,8 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
        default:
                BUG();
        }
+
+out:
        return q->first_to_check;
 }
 
@@ -726,24 +859,29 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q)
                return 0;
 }
 
-static int qdio_kick_outbound_q(struct qdio_q *q)
+static int qdio_kick_outbound_q(struct qdio_q *q, unsigned long aob)
 {
+       int retries = 0, cc;
        unsigned int busy_bit;
-       int cc;
 
        if (!need_siga_out(q))
                return 0;
 
        DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr);
+retry:
        qperf_inc(q, siga_write);
 
-       cc = qdio_siga_output(q, &busy_bit);
+       cc = qdio_siga_output(q, &busy_bit, aob);
        switch (cc) {
        case 0:
                break;
        case 2:
                if (busy_bit) {
-                       DBF_ERROR("%4x cc2 REP:%1d", SCH_NO(q), q->nr);
+                       while (++retries < QDIO_BUSY_BIT_RETRIES) {
+                               mdelay(QDIO_BUSY_BIT_RETRY_DELAY);
+                               goto retry;
+                       }
+                       DBF_ERROR("%4x cc2 BBC:%1d", SCH_NO(q), q->nr);
                        cc |= QDIO_ERROR_SIGA_BUSY;
                } else
                        DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", q->nr);
@@ -753,6 +891,10 @@ static int qdio_kick_outbound_q(struct qdio_q *q)
                DBF_ERROR("%4x SIGA-W:%1d", SCH_NO(q), cc);
                break;
        }
+       if (retries) {
+               DBF_ERROR("%4x cc2 BB2:%1d", SCH_NO(q), q->nr);
+               DBF_ERROR("count:%u", retries);
+       }
        return cc;
 }
 
@@ -906,8 +1048,9 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
                        }
                        q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
                                                 q->irq_ptr->int_parm);
-               } else
+               } else {
                        tasklet_schedule(&q->tasklet);
+               }
        }
 
        if (!pci_out_supported(q))
@@ -1221,6 +1364,26 @@ out_err:
 }
 EXPORT_SYMBOL_GPL(qdio_allocate);
 
+static void qdio_detect_hsicq(struct qdio_irq *irq_ptr)
+{
+       struct qdio_q *q = irq_ptr->input_qs[0];
+       int i, use_cq = 0;
+
+       if (irq_ptr->nr_input_qs > 1 && queue_type(q) == QDIO_IQDIO_QFMT)
+               use_cq = 1;
+
+       for_each_output_queue(irq_ptr, q, i) {
+               if (use_cq) {
+                       if (qdio_enable_async_operation(&q->u.out) < 0) {
+                               use_cq = 0;
+                               continue;
+                       }
+               } else
+                       qdio_disable_async_operation(&q->u.out);
+       }
+       DBF_EVENT("use_cq:%d", use_cq);
+}
+
 /**
  * qdio_establish - establish queues on a qdio subchannel
  * @init_data: initialization data
@@ -1286,6 +1449,8 @@ int qdio_establish(struct qdio_initialize *init_data)
        qdio_setup_ssqd_info(irq_ptr);
        DBF_EVENT("qib ac:%4x", irq_ptr->qib.ac);
 
+       qdio_detect_hsicq(irq_ptr);
+
        /* qebsm is now setup if available, initialize buffer states */
        qdio_init_buf_states(irq_ptr);
 
@@ -1427,12 +1592,9 @@ set:
        used = atomic_add_return(count, &q->nr_buf_used) - count;
        BUG_ON(used + count > QDIO_MAX_BUFFERS_PER_Q);
 
-       /* no need to signal as long as the adapter had free buffers */
-       if (used)
-               return 0;
-
        if (need_siga_in(q))
                return qdio_siga_input(q);
+
        return 0;
 }
 
@@ -1465,17 +1627,21 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
                q->u.out.pci_out_enabled = 0;
 
        if (queue_type(q) == QDIO_IQDIO_QFMT) {
-               /* One SIGA-W per buffer required for unicast HiperSockets. */
+               unsigned long phys_aob = 0;
+
+               /* One SIGA-W per buffer required for unicast HSI */
                WARN_ON_ONCE(count > 1 && !multicast_outbound(q));
 
-               rc = qdio_kick_outbound_q(q);
+               phys_aob = qdio_aob_for_buffer(&q->u.out, bufnr);
+
+               rc = qdio_kick_outbound_q(q, phys_aob);
        } else if (need_siga_sync(q)) {
                rc = qdio_siga_sync_q(q);
        } else {
                /* try to fast requeue buffers */
                get_buf_state(q, prev_buf(bufnr), &state, 0);
                if (state != SLSB_CU_OUTPUT_PRIMED)
-                       rc = qdio_kick_outbound_q(q);
+                       rc = qdio_kick_outbound_q(q, 0);
                else
                        qperf_inc(q, fast_requeue);
        }
@@ -1503,6 +1669,7 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
 {
        struct qdio_irq *irq_ptr;
 
+
        if (bufnr >= QDIO_MAX_BUFFERS_PER_Q || count > QDIO_MAX_BUFFERS_PER_Q)
                return -EINVAL;
 
@@ -1547,7 +1714,7 @@ int qdio_start_irq(struct ccw_device *cdev, int nr)
 
        WARN_ON(queue_irqs_enabled(q));
 
-       if (!shared_ind(q->irq_ptr->dsci))
+       if (!shared_ind(q))
                xchg(q->irq_ptr->dsci, 0);
 
        qdio_stop_polling(q);
@@ -1557,7 +1724,7 @@ int qdio_start_irq(struct ccw_device *cdev, int nr)
         * We need to check again to not lose initiative after
         * resetting the ACK state.
         */
-       if (!shared_ind(q->irq_ptr->dsci) && *q->irq_ptr->dsci)
+       if (!shared_ind(q) && *q->irq_ptr->dsci)
                goto rescan;
        if (!qdio_inbound_q_done(q))
                goto rescan;
index 89107d0..dd8bd67 100644 (file)
 #include "qdio_debug.h"
 
 static struct kmem_cache *qdio_q_cache;
+static struct kmem_cache *qdio_aob_cache;
+
+struct qaob *qdio_allocate_aob()
+{
+       struct qaob *aob;
+
+       aob = kmem_cache_zalloc(qdio_aob_cache, GFP_ATOMIC);
+       return aob;
+}
+EXPORT_SYMBOL_GPL(qdio_allocate_aob);
+
+void qdio_release_aob(struct qaob *aob)
+{
+       kmem_cache_free(qdio_aob_cache, aob);
+}
+EXPORT_SYMBOL_GPL(qdio_release_aob);
 
 /*
  * qebsm is only available under 64bit but the adapter sets the feature
@@ -154,29 +170,36 @@ static void setup_queues(struct qdio_irq *irq_ptr,
        struct qdio_q *q;
        void **input_sbal_array = qdio_init->input_sbal_addr_array;
        void **output_sbal_array = qdio_init->output_sbal_addr_array;
+       struct qdio_outbuf_state *output_sbal_state_array =
+                                 qdio_init->output_sbal_state_array;
        int i;
 
        for_each_input_queue(irq_ptr, q, i) {
-               DBF_EVENT("in-q:%1d", i);
+               DBF_EVENT("inq:%1d", i);
                setup_queues_misc(q, irq_ptr, qdio_init->input_handler, i);
 
                q->is_input_q = 1;
-               q->u.in.queue_start_poll = qdio_init->queue_start_poll;
+               q->u.in.queue_start_poll = qdio_init->queue_start_poll[i];
+
                setup_storage_lists(q, irq_ptr, input_sbal_array, i);
                input_sbal_array += QDIO_MAX_BUFFERS_PER_Q;
 
-               if (is_thinint_irq(irq_ptr))
+               if (is_thinint_irq(irq_ptr)) {
                        tasklet_init(&q->tasklet, tiqdio_inbound_processing,
                                     (unsigned long) q);
-               else
+               } else {
                        tasklet_init(&q->tasklet, qdio_inbound_processing,
                                     (unsigned long) q);
+               }
        }
 
        for_each_output_queue(irq_ptr, q, i) {
                DBF_EVENT("outq:%1d", i);
                setup_queues_misc(q, irq_ptr, qdio_init->output_handler, i);
 
+               q->u.out.sbal_state = output_sbal_state_array;
+               output_sbal_state_array += QDIO_MAX_BUFFERS_PER_Q;
+
                q->is_input_q = 0;
                q->u.out.scan_threshold = qdio_init->scan_threshold;
                setup_storage_lists(q, irq_ptr, output_sbal_array, i);
@@ -311,6 +334,19 @@ void qdio_release_memory(struct qdio_irq *irq_ptr)
        for (i = 0; i < QDIO_MAX_QUEUES_PER_IRQ; i++) {
                q = irq_ptr->output_qs[i];
                if (q) {
+                       if (q->u.out.use_cq) {
+                               int n;
+
+                               for (n = 0; n < QDIO_MAX_BUFFERS_PER_Q; ++n) {
+                                       struct qaob *aob = q->u.out.aobs[n];
+                                       if (aob) {
+                                               qdio_release_aob(aob);
+                                               q->u.out.aobs[n] = NULL;
+                                       }
+                               }
+
+                               qdio_disable_async_operation(&q->u.out);
+                       }
                        free_page((unsigned long) q->slib);
                        kmem_cache_free(qdio_q_cache, q);
                }
@@ -465,23 +501,60 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
        printk(KERN_INFO "%s", s);
 }
 
+int qdio_enable_async_operation(struct qdio_output_q *outq)
+{
+       outq->aobs = kzalloc(sizeof(struct qaob *) * QDIO_MAX_BUFFERS_PER_Q,
+                            GFP_ATOMIC);
+       if (!outq->aobs) {
+               outq->use_cq = 0;
+               return -ENOMEM;
+       }
+       outq->use_cq = 1;
+       return 0;
+}
+
+void qdio_disable_async_operation(struct qdio_output_q *q)
+{
+       kfree(q->aobs);
+       q->aobs = NULL;
+       q->use_cq = 0;
+}
+
 int __init qdio_setup_init(void)
 {
+       int rc;
+
        qdio_q_cache = kmem_cache_create("qdio_q", sizeof(struct qdio_q),
                                         256, 0, NULL);
        if (!qdio_q_cache)
                return -ENOMEM;
 
+       qdio_aob_cache = kmem_cache_create("qdio_aob",
+                                       sizeof(struct qaob),
+                                       sizeof(struct qaob),
+                                       0,
+                                       NULL);
+       if (!qdio_aob_cache) {
+               rc = -ENOMEM;
+               goto free_qdio_q_cache;
+       }
+
        /* Check for OSA/FCP thin interrupts (bit 67). */
        DBF_EVENT("thinint:%1d",
                  (css_general_characteristics.aif_osa) ? 1 : 0);
 
        /* Check for QEBSM support in general (bit 58). */
        DBF_EVENT("cssQEBSM:%1d", (qebsm_possible()) ? 1 : 0);
-       return 0;
+       rc = 0;
+out:
+       return rc;
+free_qdio_q_cache:
+       kmem_cache_destroy(qdio_q_cache);
+       goto out;
 }
 
 void qdio_setup_exit(void)
 {
+       kmem_cache_destroy(qdio_aob_cache);
        kmem_cache_destroy(qdio_q_cache);
 }
index 2a1d4df..a3e3949 100644 (file)
@@ -67,12 +67,9 @@ static void put_indicator(u32 *addr)
 
 void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)
 {
-       struct qdio_q *q;
-       int i;
-
        mutex_lock(&tiq_list_lock);
-       for_each_input_queue(irq_ptr, q, i)
-               list_add_rcu(&q->entry, &tiq_list);
+       BUG_ON(irq_ptr->nr_input_qs < 1);
+       list_add_rcu(&irq_ptr->input_qs[0]->entry, &tiq_list);
        mutex_unlock(&tiq_list_lock);
        xchg(irq_ptr->dsci, 1 << 7);
 }
@@ -80,19 +77,17 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)
 void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
 {
        struct qdio_q *q;
-       int i;
 
-       for (i = 0; i < irq_ptr->nr_input_qs; i++) {
-               q = irq_ptr->input_qs[i];
-               /* if establish triggered an error */
-               if (!q || !q->entry.prev || !q->entry.next)
-                       continue;
+       BUG_ON(irq_ptr->nr_input_qs < 1);
+       q = irq_ptr->input_qs[0];
+       /* if establish triggered an error */
+       if (!q || !q->entry.prev || !q->entry.next)
+               return;
 
-               mutex_lock(&tiq_list_lock);
-               list_del_rcu(&q->entry);
-               mutex_unlock(&tiq_list_lock);
-               synchronize_rcu();
-       }
+       mutex_lock(&tiq_list_lock);
+       list_del_rcu(&q->entry);
+       mutex_unlock(&tiq_list_lock);
+       synchronize_rcu();
 }
 
 static inline u32 clear_shared_ind(void)
@@ -102,6 +97,40 @@ static inline u32 clear_shared_ind(void)
        return xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
 }
 
+static inline void tiqdio_call_inq_handlers(struct qdio_irq *irq)
+{
+       struct qdio_q *q;
+       int i;
+
+       for_each_input_queue(irq, q, i) {
+               if (!references_shared_dsci(irq) &&
+                   has_multiple_inq_on_dsci(irq))
+                       xchg(q->irq_ptr->dsci, 0);
+
+               if (q->u.in.queue_start_poll) {
+                       /* skip if polling is enabled or already in work */
+                       if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
+                                            &q->u.in.queue_irq_state)) {
+                               qperf_inc(q, int_discarded);
+                               continue;
+                       }
+
+                       /* avoid dsci clear here, done after processing */
+                       q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
+                                                q->irq_ptr->int_parm);
+               } else {
+                       if (!shared_ind(q))
+                               xchg(q->irq_ptr->dsci, 0);
+
+                       /*
+                        * Call inbound processing but not directly
+                        * since that could starve other thinint queues.
+                        */
+                       tasklet_schedule(&q->tasklet);
+               }
+       }
+}
+
 /**
  * tiqdio_thinint_handler - thin interrupt handler for qdio
  * @alsi: pointer to adapter local summary indicator
@@ -120,35 +149,18 @@ static void tiqdio_thinint_handler(void *alsi, void *data)
 
        /* check for work on all inbound thinint queues */
        list_for_each_entry_rcu(q, &tiq_list, entry) {
+               struct qdio_irq *irq;
 
                /* only process queues from changed sets */
-               if (unlikely(shared_ind(q->irq_ptr->dsci))) {
+               irq = q->irq_ptr;
+               if (unlikely(references_shared_dsci(irq))) {
                        if (!si_used)
                                continue;
-               } else if (!*q->irq_ptr->dsci)
+               } else if (!*irq->dsci)
                        continue;
 
-               if (q->u.in.queue_start_poll) {
-                       /* skip if polling is enabled or already in work */
-                       if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
-                                            &q->u.in.queue_irq_state)) {
-                               qperf_inc(q, int_discarded);
-                               continue;
-                       }
+               tiqdio_call_inq_handlers(irq);
 
-                       /* avoid dsci clear here, done after processing */
-                       q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
-                                                q->irq_ptr->int_parm);
-               } else {
-                       /* only clear it if the indicator is non-shared */
-                       if (!shared_ind(q->irq_ptr->dsci))
-                               xchg(q->irq_ptr->dsci, 0);
-                       /*
-                        * Call inbound processing but not directly
-                        * since that could starve other thinint queues.
-                        */
-                       tasklet_schedule(&q->tasklet);
-               }
                qperf_inc(q, adapter_int);
        }
        rcu_read_unlock();
index c3b8064..fb246b9 100644 (file)
@@ -2122,7 +2122,7 @@ static const struct net_device_ops lcs_mc_netdev_ops = {
        .ndo_stop               = lcs_stop_device,
        .ndo_get_stats          = lcs_getstats,
        .ndo_start_xmit         = lcs_start_xmit,
-       .ndo_set_multicast_list = lcs_set_multicast_list,
+       .ndo_set_rx_mode        = lcs_set_multicast_list,
 };
 
 static int
index 26a4110..b77c65e 100644 (file)
@@ -110,6 +110,10 @@ struct qeth_perf_stats {
 
        unsigned int sc_dp_p;
        unsigned int sc_p_dp;
+       /* qdio_cq_handler: number of times called, time spent in */
+       __u64 cq_start_time;
+       unsigned int cq_cnt;
+       unsigned int cq_time;
        /* qdio_input_handler: number of times called, time spent in */
        __u64 inbound_start_time;
        unsigned int inbound_cnt;
@@ -213,6 +217,7 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
  */
 #define QETH_TX_TIMEOUT                100 * HZ
 #define QETH_RCD_TIMEOUT       60 * HZ
+#define QETH_RECLAIM_WORK_TIME HZ
 #define QETH_HEADER_SIZE       32
 #define QETH_MAX_PORTNO                15
 
@@ -231,7 +236,8 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
 #define QETH_IN_BUF_COUNT_MAX 128
 #define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
 #define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \
-               ((card)->qdio.in_buf_pool.buf_count / 2)
+               ((card)->ssqd.qdioac1 & AC1_SIGA_INPUT_NEEDED ? 1 : \
+                ((card)->qdio.in_buf_pool.buf_count / 2))
 
 /* buffers we have to be behind before we get a PCI */
 #define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1)
@@ -260,6 +266,7 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
 
 /* large receive scatter gather copy break */
 #define QETH_RX_SG_CB (PAGE_SIZE >> 1)
+#define QETH_RX_PULL_LEN 256
 
 struct qeth_hdr_layer3 {
        __u8  id;
@@ -375,6 +382,21 @@ enum qeth_qdio_buffer_states {
         * outbound: filled by driver; owned by hardware in order to be sent
         */
        QETH_QDIO_BUF_PRIMED,
+       /*
+        * inbound: not applicable
+        * outbound: identified to be pending in TPQ
+        */
+       QETH_QDIO_BUF_PENDING,
+       /*
+        * inbound: not applicable
+        * outbound: found in completion queue
+        */
+       QETH_QDIO_BUF_IN_CQ,
+       /*
+        * inbound: not applicable
+        * outbound: handled via transfer pending / completion queue
+        */
+       QETH_QDIO_BUF_HANDLED_DELAYED,
 };
 
 enum qeth_qdio_info_states {
@@ -399,6 +421,7 @@ struct qeth_qdio_buffer {
        struct qdio_buffer *buffer;
        /* the buffer pool entry currently associated to this buffer */
        struct qeth_buffer_pool_entry *pool_entry;
+       struct sk_buff *rx_skb;
 };
 
 struct qeth_qdio_q {
@@ -412,8 +435,11 @@ struct qeth_qdio_out_buffer {
        atomic_t state;
        int next_element_to_fill;
        struct sk_buff_head skb_list;
-       struct list_head ctx_list;
        int is_header[16];
+
+       struct qaob *aob;
+       struct qeth_qdio_out_q *q;
+       struct qeth_qdio_out_buffer *next_pending;
 };
 
 struct qeth_card;
@@ -426,7 +452,8 @@ enum qeth_out_q_states {
 
 struct qeth_qdio_out_q {
        struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
-       struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
+       struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q];
+       struct qdio_outbuf_state *bufstates; /* convenience pointer */
        int queue_no;
        struct qeth_card *card;
        atomic_t state;
@@ -447,7 +474,9 @@ struct qeth_qdio_out_q {
 struct qeth_qdio_info {
        atomic_t state;
        /* input */
+       int no_in_queues;
        struct qeth_qdio_q *in_q;
+       struct qeth_qdio_q *c_q;
        struct qeth_qdio_buffer_pool in_buf_pool;
        struct qeth_qdio_buffer_pool init_pool;
        int in_buf_size;
@@ -455,6 +484,7 @@ struct qeth_qdio_info {
        /* output */
        int no_out_queues;
        struct qeth_qdio_out_q **out_qs;
+       struct qdio_outbuf_state *out_bufstates;
 
        /* priority queueing */
        int do_prio_queueing;
@@ -526,6 +556,12 @@ enum qeth_cmd_buffer_state {
        BUF_STATE_PROCESSED,
 };
 
+enum qeth_cq {
+       QETH_CQ_DISABLED = 0,
+       QETH_CQ_ENABLED = 1,
+       QETH_CQ_NOTAVAILABLE = 2,
+};
+
 struct qeth_ipato {
        int enabled;
        int invert4;
@@ -650,6 +686,8 @@ struct qeth_card_options {
        int rx_sg_cb;
        enum qeth_ipa_isolation_modes isolation;
        int sniffer;
+       enum qeth_cq cq;
+       char hsuid[9];
 };
 
 /*
@@ -747,6 +785,8 @@ struct qeth_card {
        struct mutex discipline_mutex;
        struct napi_struct napi;
        struct qeth_rx rx;
+       struct delayed_work buffer_reclaim_work;
+       int reclaim_index;
 };
 
 struct qeth_card_list_struct {
@@ -812,6 +852,7 @@ int qeth_core_create_device_attributes(struct device *);
 void qeth_core_remove_device_attributes(struct device *);
 int qeth_core_create_osn_attributes(struct device *);
 void qeth_core_remove_osn_attributes(struct device *);
+void qeth_buffer_reclaim_work(struct work_struct *);
 
 /* exports for qeth discipline device drivers */
 extern struct qeth_card_list_struct qeth_core_card_list;
@@ -840,7 +881,7 @@ int qeth_check_qdio_errors(struct qeth_card *, struct qdio_buffer *,
                unsigned int, const char *);
 void qeth_queue_input_buffer(struct qeth_card *, int);
 struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
-               struct qdio_buffer *, struct qdio_buffer_element **, int *,
+               struct qeth_qdio_buffer *, struct qdio_buffer_element **, int *,
                struct qeth_hdr **);
 void qeth_schedule_recovery(struct qeth_card *);
 void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long);
@@ -887,6 +928,7 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
 int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *);
 int qeth_set_access_ctrl_online(struct qeth_card *card);
 int qeth_hdr_chk_and_bounce(struct sk_buff *, int);
+int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
 int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
 int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot);
 
index 4550573..97172f8 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/mii.h>
 #include <linux/kthread.h>
 #include <linux/slab.h>
+#include <net/iucv/af_iucv.h>
 
 #include <asm/ebcdic.h>
 #include <asm/io.h>
@@ -44,6 +45,7 @@ struct qeth_card_list_struct qeth_core_card_list;
 EXPORT_SYMBOL_GPL(qeth_core_card_list);
 struct kmem_cache *qeth_core_header_cache;
 EXPORT_SYMBOL_GPL(qeth_core_header_cache);
+static struct kmem_cache *qeth_qdio_outbuf_cache;
 
 static struct device *qeth_core_root_dev;
 static unsigned int known_devices[][6] = QETH_MODELLIST_ARRAY;
@@ -56,6 +58,14 @@ static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *);
 static void qeth_setup_ccw(struct qeth_channel *, unsigned char *, __u32);
 static void qeth_free_buffer_pool(struct qeth_card *);
 static int qeth_qdio_establish(struct qeth_card *);
+static void qeth_free_qdio_buffers(struct qeth_card *);
+static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
+               struct qeth_qdio_out_buffer *buf,
+               enum iucv_tx_notify notification);
+static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf);
+static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
+               struct qeth_qdio_out_buffer *buf,
+               enum qeth_qdio_buffer_states newbufstate);
 
 
 static inline const char *qeth_get_cardname(struct qeth_card *card)
@@ -199,7 +209,7 @@ static int qeth_alloc_buffer_pool(struct qeth_card *card)
 
        QETH_CARD_TEXT(card, 5, "alocpool");
        for (i = 0; i < card->qdio.init_pool.buf_count; ++i) {
-               pool_entry = kmalloc(sizeof(*pool_entry), GFP_KERNEL);
+               pool_entry = kzalloc(sizeof(*pool_entry), GFP_KERNEL);
                if (!pool_entry) {
                        qeth_free_buffer_pool(card);
                        return -ENOMEM;
@@ -239,6 +249,196 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
 }
 EXPORT_SYMBOL_GPL(qeth_realloc_buffer_pool);
 
+static inline int qeth_cq_init(struct qeth_card *card)
+{
+       int rc;
+
+       if (card->options.cq == QETH_CQ_ENABLED) {
+               QETH_DBF_TEXT(SETUP, 2, "cqinit");
+               memset(card->qdio.c_q->qdio_bufs, 0,
+                      QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+               card->qdio.c_q->next_buf_to_init = 127;
+               rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT,
+                            card->qdio.no_in_queues - 1, 0,
+                            127);
+               if (rc) {
+                       QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
+                       goto out;
+               }
+       }
+       rc = 0;
+out:
+       return rc;
+}
+
+static inline int qeth_alloc_cq(struct qeth_card *card)
+{
+       int rc;
+
+       if (card->options.cq == QETH_CQ_ENABLED) {
+               int i;
+               struct qdio_outbuf_state *outbuf_states;
+
+               QETH_DBF_TEXT(SETUP, 2, "cqon");
+               card->qdio.c_q = kzalloc(sizeof(struct qeth_qdio_q),
+                                        GFP_KERNEL);
+               if (!card->qdio.c_q) {
+                       rc = -1;
+                       goto kmsg_out;
+               }
+               QETH_DBF_HEX(SETUP, 2, &card->qdio.c_q, sizeof(void *));
+
+               for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
+                       card->qdio.c_q->bufs[i].buffer =
+                               &card->qdio.c_q->qdio_bufs[i];
+               }
+
+               card->qdio.no_in_queues = 2;
+
+               card->qdio.out_bufstates = (struct qdio_outbuf_state *)
+                       kzalloc(card->qdio.no_out_queues *
+                               QDIO_MAX_BUFFERS_PER_Q *
+                               sizeof(struct qdio_outbuf_state), GFP_KERNEL);
+               outbuf_states = card->qdio.out_bufstates;
+               if (outbuf_states == NULL) {
+                       rc = -1;
+                       goto free_cq_out;
+               }
+               for (i = 0; i < card->qdio.no_out_queues; ++i) {
+                       card->qdio.out_qs[i]->bufstates = outbuf_states;
+                       outbuf_states += QDIO_MAX_BUFFERS_PER_Q;
+               }
+       } else {
+               QETH_DBF_TEXT(SETUP, 2, "nocq");
+               card->qdio.c_q = NULL;
+               card->qdio.no_in_queues = 1;
+       }
+       QETH_DBF_TEXT_(SETUP, 2, "iqc%d", card->qdio.no_in_queues);
+       rc = 0;
+out:
+       return rc;
+free_cq_out:
+       kfree(card->qdio.c_q);
+       card->qdio.c_q = NULL;
+kmsg_out:
+       dev_err(&card->gdev->dev, "Failed to create completion queue\n");
+       goto out;
+}
+
+static inline void qeth_free_cq(struct qeth_card *card)
+{
+       if (card->qdio.c_q) {
+               --card->qdio.no_in_queues;
+               kfree(card->qdio.c_q);
+               card->qdio.c_q = NULL;
+       }
+       kfree(card->qdio.out_bufstates);
+       card->qdio.out_bufstates = NULL;
+}
+
+static inline enum iucv_tx_notify qeth_compute_cq_notification(int sbalf15,
+       int delayed) {
+       enum iucv_tx_notify n;
+
+       switch (sbalf15) {
+       case 0:
+               n = delayed ? TX_NOTIFY_DELAYED_OK : TX_NOTIFY_OK;
+               break;
+       case 4:
+       case 16:
+       case 17:
+       case 18:
+               n = delayed ? TX_NOTIFY_DELAYED_UNREACHABLE :
+                       TX_NOTIFY_UNREACHABLE;
+               break;
+       default:
+               n = delayed ? TX_NOTIFY_DELAYED_GENERALERROR :
+                       TX_NOTIFY_GENERALERROR;
+               break;
+       }
+
+       return n;
+}
+
+static inline void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q,
+       int bidx, int forced_cleanup)
+{
+       if (q->bufs[bidx]->next_pending != NULL) {
+               struct qeth_qdio_out_buffer *head = q->bufs[bidx];
+               struct qeth_qdio_out_buffer *c = q->bufs[bidx]->next_pending;
+
+               while (c) {
+                       if (forced_cleanup ||
+                           atomic_read(&c->state) ==
+                             QETH_QDIO_BUF_HANDLED_DELAYED) {
+                               struct qeth_qdio_out_buffer *f = c;
+                               QETH_CARD_TEXT(f->q->card, 5, "fp");
+                               QETH_CARD_TEXT_(f->q->card, 5, "%lx", (long) f);
+                               /* release here to avoid interleaving between
+                                  outbound tasklet and inbound tasklet
+                                  regarding notifications and lifecycle */
+                               qeth_release_skbs(c);
+
+                               c = f->next_pending;
+                               BUG_ON(head->next_pending != f);
+                               head->next_pending = c;
+                               kmem_cache_free(qeth_qdio_outbuf_cache, f);
+                       } else {
+                               head = c;
+                               c = c->next_pending;
+                       }
+
+               }
+       }
+}
+
+
+static inline void qeth_qdio_handle_aob(struct qeth_card *card,
+               unsigned long phys_aob_addr) {
+       struct qaob *aob;
+       struct qeth_qdio_out_buffer *buffer;
+       enum iucv_tx_notify notification;
+
+       aob = (struct qaob *) phys_to_virt(phys_aob_addr);
+       QETH_CARD_TEXT(card, 5, "haob");
+       QETH_CARD_TEXT_(card, 5, "%lx", phys_aob_addr);
+       buffer = (struct qeth_qdio_out_buffer *) aob->user1;
+       QETH_CARD_TEXT_(card, 5, "%lx", aob->user1);
+
+       BUG_ON(buffer == NULL);
+
+       if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED,
+                          QETH_QDIO_BUF_IN_CQ) == QETH_QDIO_BUF_PRIMED) {
+               notification = TX_NOTIFY_OK;
+       } else {
+               BUG_ON(atomic_read(&buffer->state) != QETH_QDIO_BUF_PENDING);
+
+               atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ);
+               notification = TX_NOTIFY_DELAYED_OK;
+       }
+
+       if (aob->aorc != 0)  {
+               QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc);
+               notification = qeth_compute_cq_notification(aob->aorc, 1);
+       }
+       qeth_notify_skbs(buffer->q, buffer, notification);
+
+       buffer->aob = NULL;
+       qeth_clear_output_buffer(buffer->q, buffer,
+                               QETH_QDIO_BUF_HANDLED_DELAYED);
+       /* from here on: do not touch buffer anymore */
+       qdio_release_aob(aob);
+}
+
+static inline int qeth_is_cq(struct qeth_card *card, unsigned int queue)
+{
+       return card->options.cq == QETH_CQ_ENABLED &&
+           card->qdio.c_q != NULL &&
+           queue != 0 &&
+           queue == card->qdio.no_in_queues - 1;
+}
+
+
 static int qeth_issue_next_read(struct qeth_card *card)
 {
        int rc;
@@ -589,7 +789,7 @@ static int qeth_setup_channel(struct qeth_channel *channel)
        QETH_DBF_TEXT(SETUP, 2, "setupch");
        for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
                channel->iob[cnt].data =
-                       kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
+                       kzalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
                if (channel->iob[cnt].data == NULL)
                        break;
                channel->iob[cnt].state = BUF_STATE_FREE;
@@ -681,6 +881,7 @@ EXPORT_SYMBOL_GPL(qeth_do_run_thread);
 void qeth_schedule_recovery(struct qeth_card *card)
 {
        QETH_CARD_TEXT(card, 2, "startrec");
+       WARN_ON(1);
        if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)
                schedule_work(&card->kernel_thread_starter);
 }
@@ -883,22 +1084,60 @@ out:
        return;
 }
 
-static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
-               struct qeth_qdio_out_buffer *buf)
+static void qeth_notify_skbs(struct qeth_qdio_out_q *q,
+               struct qeth_qdio_out_buffer *buf,
+               enum iucv_tx_notify notification)
 {
-       int i;
        struct sk_buff *skb;
 
-       /* is PCI flag set on buffer? */
-       if (buf->buffer->element[0].sflags & SBAL_SFLAGS0_PCI_REQ)
-               atomic_dec(&queue->set_pci_flags_count);
+       if (skb_queue_empty(&buf->skb_list))
+               goto out;
+       skb = skb_peek(&buf->skb_list);
+       while (skb) {
+               QETH_CARD_TEXT_(q->card, 5, "skbn%d", notification);
+               QETH_CARD_TEXT_(q->card, 5, "%lx", (long) skb);
+               if (skb->protocol == ETH_P_AF_IUCV) {
+                       if (skb->sk) {
+                               struct iucv_sock *iucv = iucv_sk(skb->sk);
+                               iucv->sk_txnotify(skb, notification);
+                       }
+               }
+               if (skb_queue_is_last(&buf->skb_list, skb))
+                       skb = NULL;
+               else
+                       skb = skb_queue_next(&buf->skb_list, skb);
+       }
+out:
+       return;
+}
+
+static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
+{
+       struct sk_buff *skb;
 
        skb = skb_dequeue(&buf->skb_list);
        while (skb) {
+               QETH_CARD_TEXT(buf->q->card, 5, "skbr");
+               QETH_CARD_TEXT_(buf->q->card, 5, "%lx", (long) skb);
                atomic_dec(&skb->users);
                dev_kfree_skb_any(skb);
                skb = skb_dequeue(&buf->skb_list);
        }
+}
+
+static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
+               struct qeth_qdio_out_buffer *buf,
+               enum qeth_qdio_buffer_states newbufstate)
+{
+       int i;
+
+       /* is PCI flag set on buffer? */
+       if (buf->buffer->element[0].sflags & SBAL_SFLAGS0_PCI_REQ)
+               atomic_dec(&queue->set_pci_flags_count);
+
+       if (newbufstate == QETH_QDIO_BUF_EMPTY) {
+               qeth_release_skbs(buf);
+       }
        for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) {
                if (buf->buffer->element[i].addr && buf->is_header[i])
                        kmem_cache_free(qeth_core_header_cache,
@@ -912,21 +1151,36 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
        buf->buffer->element[15].eflags = 0;
        buf->buffer->element[15].sflags = 0;
        buf->next_element_to_fill = 0;
-       atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
+       atomic_set(&buf->state, newbufstate);
+}
+
+static void qeth_clear_outq_buffers(struct qeth_qdio_out_q *q, int free)
+{
+       int j;
+
+       for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
+               if (!q->bufs[j])
+                       continue;
+               qeth_cleanup_handled_pending(q, j, free);
+               qeth_clear_output_buffer(q, q->bufs[j], QETH_QDIO_BUF_EMPTY);
+               if (free) {
+                       kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[j]);
+                       q->bufs[j] = NULL;
+               }
+       }
 }
 
 void qeth_clear_qdio_buffers(struct qeth_card *card)
 {
-       int i, j;
+       int i;
 
        QETH_CARD_TEXT(card, 2, "clearqdbf");
        /* clear outbound buffers to free skbs */
-       for (i = 0; i < card->qdio.no_out_queues; ++i)
+       for (i = 0; i < card->qdio.no_out_queues; ++i) {
                if (card->qdio.out_qs[i]) {
-                       for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
-                               qeth_clear_output_buffer(card->qdio.out_qs[i],
-                                               &card->qdio.out_qs[i]->bufs[j]);
+                       qeth_clear_outq_buffers(card->qdio.out_qs[i], 0);
                }
+       }
 }
 EXPORT_SYMBOL_GPL(qeth_clear_qdio_buffers);
 
@@ -950,6 +1204,11 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
        if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
                QETH_QDIO_UNINITIALIZED)
                return;
+
+       qeth_free_cq(card);
+       cancel_delayed_work_sync(&card->buffer_reclaim_work);
+       for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+               kfree_skb(card->qdio.in_q->bufs[j].rx_skb);
        kfree(card->qdio.in_q);
        card->qdio.in_q = NULL;
        /* inbound buffer pool */
@@ -957,9 +1216,7 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
        /* free outbound qdio_qs */
        if (card->qdio.out_qs) {
                for (i = 0; i < card->qdio.no_out_queues; ++i) {
-                       for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
-                               qeth_clear_output_buffer(card->qdio.out_qs[i],
-                                               &card->qdio.out_qs[i]->bufs[j]);
+                       qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
                        kfree(card->qdio.out_qs[i]);
                }
                kfree(card->qdio.out_qs);
@@ -995,27 +1252,29 @@ static void qeth_get_channel_path_desc(struct qeth_card *card)
        ccwdev = card->data.ccwdev;
        chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
        if (chp_dsc != NULL) {
-               /* CHPP field bit 6 == 1 -> single queue */
-               if ((chp_dsc->chpp & 0x02) == 0x02) {
-                       if ((atomic_read(&card->qdio.state) !=
-                               QETH_QDIO_UNINITIALIZED) &&
-                           (card->qdio.no_out_queues == 4))
-                               /* change from 4 to 1 outbound queues */
-                               qeth_free_qdio_buffers(card);
-                       card->qdio.no_out_queues = 1;
-                       if (card->qdio.default_out_queue != 0)
-                               dev_info(&card->gdev->dev,
+               if (card->info.type != QETH_CARD_TYPE_IQD) {
+                       /* CHPP field bit 6 == 1 -> single queue */
+                       if ((chp_dsc->chpp & 0x02) == 0x02) {
+                               if ((atomic_read(&card->qdio.state) !=
+                                       QETH_QDIO_UNINITIALIZED) &&
+                                   (card->qdio.no_out_queues == 4))
+                                       /* change from 4 to 1 outbound queues */
+                                       qeth_free_qdio_buffers(card);
+                               card->qdio.no_out_queues = 1;
+                               if (card->qdio.default_out_queue != 0)
+                                       dev_info(&card->gdev->dev,
                                        "Priority Queueing not supported\n");
-                       card->qdio.default_out_queue = 0;
-               } else {
-                       if ((atomic_read(&card->qdio.state) !=
-                               QETH_QDIO_UNINITIALIZED) &&
-                           (card->qdio.no_out_queues == 1)) {
-                               /* change from 1 to 4 outbound queues */
-                               qeth_free_qdio_buffers(card);
-                               card->qdio.default_out_queue = 2;
+                               card->qdio.default_out_queue = 0;
+                       } else {
+                               if ((atomic_read(&card->qdio.state) !=
+                                       QETH_QDIO_UNINITIALIZED) &&
+                                   (card->qdio.no_out_queues == 1)) {
+                                       /* change from 1 to 4 outbound queues */
+                                       qeth_free_qdio_buffers(card);
+                                       card->qdio.default_out_queue = 2;
+                               }
+                               card->qdio.no_out_queues = 4;
                        }
-                       card->qdio.no_out_queues = 4;
                }
                card->info.func_level = 0x4100 + chp_dsc->desc;
                kfree(chp_dsc);
@@ -1051,6 +1310,7 @@ static void qeth_set_intial_options(struct qeth_card *card)
        card->options.performance_stats = 0;
        card->options.rx_sg_cb = QETH_RX_SG_CB;
        card->options.isolation = ISOLATION_MODE_NONE;
+       card->options.cq = QETH_CQ_DISABLED;
 }
 
 static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread)
@@ -1119,6 +1379,7 @@ static int qeth_setup_card(struct qeth_card *card)
        card->ipato.invert6 = 0;
        /* init QDIO stuff */
        qeth_init_qdio_info(card);
+       INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work);
        return 0;
 }
 
@@ -1140,7 +1401,7 @@ static struct qeth_card *qeth_alloc_card(void)
        if (!card)
                goto out;
        QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
-       card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+       card->ip_tbd_list = kzalloc(sizeof(struct list_head), GFP_KERNEL);
        if (!card->ip_tbd_list) {
                QETH_DBF_TEXT(SETUP, 0, "iptbdnom");
                goto out_card;
@@ -1180,6 +1441,7 @@ static int qeth_determine_card_type(struct qeth_card *card)
                        card->info.type = known_devices[i][QETH_DEV_MODEL_IND];
                        card->qdio.no_out_queues =
                                known_devices[i][QETH_QUEUE_NO_IND];
+                       card->qdio.no_in_queues = 1;
                        card->info.is_multicast_different =
                                known_devices[i][QETH_MULTICAST_IND];
                        qeth_get_channel_path_desc(card);
@@ -2027,6 +2289,37 @@ static int qeth_ulp_setup(struct qeth_card *card)
        return rc;
 }
 
+static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
+{
+       int rc;
+       struct qeth_qdio_out_buffer *newbuf;
+
+       rc = 0;
+       newbuf = kmem_cache_zalloc(qeth_qdio_outbuf_cache, GFP_ATOMIC);
+       if (!newbuf) {
+               rc = -ENOMEM;
+               goto out;
+       }
+       newbuf->buffer = &q->qdio_bufs[bidx];
+       skb_queue_head_init(&newbuf->skb_list);
+       lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key);
+       newbuf->q = q;
+       newbuf->aob = NULL;
+       newbuf->next_pending = q->bufs[bidx];
+       atomic_set(&newbuf->state, QETH_QDIO_BUF_EMPTY);
+       q->bufs[bidx] = newbuf;
+       if (q->bufstates) {
+               q->bufstates[bidx].user = newbuf;
+               QETH_CARD_TEXT_(q->card, 2, "nbs%d", bidx);
+               QETH_CARD_TEXT_(q->card, 2, "%lx", (long) newbuf);
+               QETH_CARD_TEXT_(q->card, 2, "%lx",
+                               (long) newbuf->next_pending);
+       }
+out:
+       return rc;
+}
+
+
 static int qeth_alloc_qdio_buffers(struct qeth_card *card)
 {
        int i, j;
@@ -2037,52 +2330,63 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
                QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
                return 0;
 
-       card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
-                                 GFP_KERNEL);
+       card->qdio.in_q = kzalloc(sizeof(struct qeth_qdio_q),
+                                  GFP_KERNEL);
        if (!card->qdio.in_q)
                goto out_nomem;
        QETH_DBF_TEXT(SETUP, 2, "inq");
        QETH_DBF_HEX(SETUP, 2, &card->qdio.in_q, sizeof(void *));
        memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q));
        /* give inbound qeth_qdio_buffers their qdio_buffers */
-       for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+       for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
                card->qdio.in_q->bufs[i].buffer =
                        &card->qdio.in_q->qdio_bufs[i];
+               card->qdio.in_q->bufs[i].rx_skb = NULL;
+       }
        /* inbound buffer pool */
        if (qeth_alloc_buffer_pool(card))
                goto out_freeinq;
+
        /* outbound */
        card->qdio.out_qs =
-               kmalloc(card->qdio.no_out_queues *
+               kzalloc(card->qdio.no_out_queues *
                        sizeof(struct qeth_qdio_out_q *), GFP_KERNEL);
        if (!card->qdio.out_qs)
                goto out_freepool;
        for (i = 0; i < card->qdio.no_out_queues; ++i) {
-               card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q),
+               card->qdio.out_qs[i] = kzalloc(sizeof(struct qeth_qdio_out_q),
                                               GFP_KERNEL);
                if (!card->qdio.out_qs[i])
                        goto out_freeoutq;
                QETH_DBF_TEXT_(SETUP, 2, "outq %i", i);
                QETH_DBF_HEX(SETUP, 2, &card->qdio.out_qs[i], sizeof(void *));
-               memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q));
                card->qdio.out_qs[i]->queue_no = i;
                /* give outbound qeth_qdio_buffers their qdio_buffers */
                for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
-                       card->qdio.out_qs[i]->bufs[j].buffer =
-                               &card->qdio.out_qs[i]->qdio_bufs[j];
-                       skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j].
-                                           skb_list);
-                       lockdep_set_class(
-                               &card->qdio.out_qs[i]->bufs[j].skb_list.lock,
-                               &qdio_out_skb_queue_key);
-                       INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list);
+                       BUG_ON(card->qdio.out_qs[i]->bufs[j] != NULL);
+                       if (qeth_init_qdio_out_buf(card->qdio.out_qs[i], j))
+                               goto out_freeoutqbufs;
                }
        }
+
+       /* completion */
+       if (qeth_alloc_cq(card))
+               goto out_freeoutq;
+
        return 0;
 
+out_freeoutqbufs:
+       while (j > 0) {
+               --j;
+               kmem_cache_free(qeth_qdio_outbuf_cache,
+                               card->qdio.out_qs[i]->bufs[j]);
+               card->qdio.out_qs[i]->bufs[j] = NULL;
+       }
 out_freeoutq:
-       while (i > 0)
+       while (i > 0) {
                kfree(card->qdio.out_qs[--i]);
+               qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
+       }
        kfree(card->qdio.out_qs);
        card->qdio.out_qs = NULL;
 out_freepool:
@@ -2353,6 +2657,12 @@ static int qeth_init_input_buffer(struct qeth_card *card,
        struct qeth_buffer_pool_entry *pool_entry;
        int i;
 
+       if ((card->options.cq == QETH_CQ_ENABLED) && (!buf->rx_skb)) {
+               buf->rx_skb = dev_alloc_skb(QETH_RX_PULL_LEN + ETH_HLEN);
+               if (!buf->rx_skb)
+                       return 1;
+       }
+
        pool_entry = qeth_find_free_buffer_pool_entry(card);
        if (!pool_entry)
                return 1;
@@ -2399,13 +2709,21 @@ int qeth_init_qdio_queues(struct qeth_card *card)
                QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
                return rc;
        }
+
+       /* completion */
+       rc = qeth_cq_init(card);
+       if (rc) {
+               return rc;
+       }
+
        /* outbound queue */
        for (i = 0; i < card->qdio.no_out_queues; ++i) {
                memset(card->qdio.out_qs[i]->qdio_bufs, 0,
                       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
                for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
                        qeth_clear_output_buffer(card->qdio.out_qs[i],
-                                       &card->qdio.out_qs[i]->bufs[j]);
+                                       card->qdio.out_qs[i]->bufs[j],
+                                       QETH_QDIO_BUF_EMPTY);
                }
                card->qdio.out_qs[i]->card = card;
                card->qdio.out_qs[i]->next_buf_to_fill = 0;
@@ -2734,9 +3052,19 @@ int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf,
 }
 EXPORT_SYMBOL_GPL(qeth_check_qdio_errors);
 
+void qeth_buffer_reclaim_work(struct work_struct *work)
+{
+       struct qeth_card *card = container_of(work, struct qeth_card,
+               buffer_reclaim_work.work);
+
+       QETH_CARD_TEXT_(card, 2, "brw:%x", card->reclaim_index);
+       qeth_queue_input_buffer(card, card->reclaim_index);
+}
+
 void qeth_queue_input_buffer(struct qeth_card *card, int index)
 {
        struct qeth_qdio_q *queue = card->qdio.in_q;
+       struct list_head *lh;
        int count;
        int i;
        int rc;
@@ -2768,6 +3096,20 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index)
                        atomic_add_unless(&card->force_alloc_skb, -1, 0);
                }
 
+               if (!count) {
+                       i = 0;
+                       list_for_each(lh, &card->qdio.in_buf_pool.entry_list)
+                               i++;
+                       if (i == card->qdio.in_buf_pool.buf_count) {
+                               QETH_CARD_TEXT(card, 2, "qsarbw");
+                               card->reclaim_index = index;
+                               schedule_delayed_work(
+                                       &card->buffer_reclaim_work,
+                                       QETH_RECLAIM_WORK_TIME);
+                       }
+                       return;
+               }
+
                /*
                 * according to old code it should be avoided to requeue all
                 * 128 buffers in order to benefit from PCI avoidance.
@@ -2787,8 +3129,6 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index)
                                qeth_get_micros() -
                                card->perf_stats.inbound_do_qdio_start_time;
                if (rc) {
-                       dev_warn(&card->gdev->dev,
-                               "QDIO reported an error, rc=%i\n", rc);
                        QETH_CARD_TEXT(card, 2, "qinberr");
                }
                queue->next_buf_to_init = (queue->next_buf_to_init + count) %
@@ -2862,12 +3202,12 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
                                queue->card->perf_stats.sc_p_dp++;
                        queue->do_pack = 0;
                        /* flush packing buffers */
-                       buffer = &queue->bufs[queue->next_buf_to_fill];
+                       buffer = queue->bufs[queue->next_buf_to_fill];
                        if ((atomic_read(&buffer->state) ==
                                                QETH_QDIO_BUF_EMPTY) &&
                            (buffer->next_element_to_fill > 0)) {
                                atomic_set(&buffer->state,
-                                               QETH_QDIO_BUF_PRIMED);
+                                          QETH_QDIO_BUF_PRIMED);
                                flush_count++;
                                queue->next_buf_to_fill =
                                        (queue->next_buf_to_fill + 1) %
@@ -2878,6 +3218,7 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
        return flush_count;
 }
 
+
 /*
  * Called to flush a packing buffer if no more pci flags are on the queue.
  * Checks if there is a packing buffer and prepares it to be flushed.
@@ -2887,7 +3228,7 @@ static int qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
 {
        struct qeth_qdio_out_buffer *buffer;
 
-       buffer = &queue->bufs[queue->next_buf_to_fill];
+       buffer = queue->bufs[queue->next_buf_to_fill];
        if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
           (buffer->next_element_to_fill > 0)) {
                /* it's a packing buffer */
@@ -2908,10 +3249,14 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
        unsigned int qdio_flags;
 
        for (i = index; i < index + count; ++i) {
-               buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+               int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
+               buf = queue->bufs[bidx];
                buf->buffer->element[buf->next_element_to_fill - 1].eflags |=
                                SBAL_EFLAGS_LAST_ENTRY;
 
+               if (queue->bufstates)
+                       queue->bufstates[bidx].user = buf;
+
                if (queue->card->info.type == QETH_CARD_TYPE_IQD)
                        continue;
 
@@ -2963,6 +3308,9 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
                if (rc == QDIO_ERROR_SIGA_TARGET)
                        return;
                QETH_CARD_TEXT(queue->card, 2, "flushbuf");
+               QETH_CARD_TEXT_(queue->card, 2, " q%d", queue->queue_no);
+               QETH_CARD_TEXT_(queue->card, 2, " idx%d", index);
+               QETH_CARD_TEXT_(queue->card, 2, " c%d", count);
                QETH_CARD_TEXT_(queue->card, 2, " err%d", rc);
 
                /* this must not happen under normal circumstances. if it
@@ -3024,14 +3372,120 @@ void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue,
 }
 EXPORT_SYMBOL_GPL(qeth_qdio_start_poll);
 
+int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq)
+{
+       int rc;
+
+       if (card->options.cq ==  QETH_CQ_NOTAVAILABLE) {
+               rc = -1;
+               goto out;
+       } else {
+               if (card->options.cq == cq) {
+                       rc = 0;
+                       goto out;
+               }
+
+               if (card->state != CARD_STATE_DOWN &&
+                   card->state != CARD_STATE_RECOVER) {
+                       rc = -1;
+                       goto out;
+               }
+
+               qeth_free_qdio_buffers(card);
+               card->options.cq = cq;
+               rc = 0;
+       }
+out:
+       return rc;
+
+}
+EXPORT_SYMBOL_GPL(qeth_configure_cq);
+
+
+static void qeth_qdio_cq_handler(struct qeth_card *card,
+               unsigned int qdio_err,
+               unsigned int queue, int first_element, int count) {
+       struct qeth_qdio_q *cq = card->qdio.c_q;
+       int i;
+       int rc;
+
+       if (!qeth_is_cq(card, queue))
+               goto out;
+
+       QETH_CARD_TEXT_(card, 5, "qcqhe%d", first_element);
+       QETH_CARD_TEXT_(card, 5, "qcqhc%d", count);
+       QETH_CARD_TEXT_(card, 5, "qcqherr%d", qdio_err);
+
+       if (qdio_err) {
+               netif_stop_queue(card->dev);
+               qeth_schedule_recovery(card);
+               goto out;
+       }
+
+       if (card->options.performance_stats) {
+               card->perf_stats.cq_cnt++;
+               card->perf_stats.cq_start_time = qeth_get_micros();
+       }
+
+       for (i = first_element; i < first_element + count; ++i) {
+               int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
+               struct qdio_buffer *buffer = &cq->qdio_bufs[bidx];
+               int e;
+
+               e = 0;
+               while (buffer->element[e].addr) {
+                       unsigned long phys_aob_addr;
+
+                       phys_aob_addr = (unsigned long) buffer->element[e].addr;
+                       qeth_qdio_handle_aob(card, phys_aob_addr);
+                       buffer->element[e].addr = NULL;
+                       buffer->element[e].eflags = 0;
+                       buffer->element[e].sflags = 0;
+                       buffer->element[e].length = 0;
+
+                       ++e;
+               }
+
+               buffer->element[15].eflags = 0;
+               buffer->element[15].sflags = 0;
+       }
+       rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, queue,
+                   card->qdio.c_q->next_buf_to_init,
+                   count);
+       if (rc) {
+               dev_warn(&card->gdev->dev,
+                       "QDIO reported an error, rc=%i\n", rc);
+               QETH_CARD_TEXT(card, 2, "qcqherr");
+       }
+       card->qdio.c_q->next_buf_to_init = (card->qdio.c_q->next_buf_to_init
+                                  + count) % QDIO_MAX_BUFFERS_PER_Q;
+
+       netif_wake_queue(card->dev);
+
+       if (card->options.performance_stats) {
+               int delta_t = qeth_get_micros();
+               delta_t -= card->perf_stats.cq_start_time;
+               card->perf_stats.cq_time += delta_t;
+       }
+out:
+       return;
+}
+
 void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err,
-               unsigned int queue, int first_element, int count,
+               unsigned int queue, int first_elem, int count,
                unsigned long card_ptr)
 {
        struct qeth_card *card = (struct qeth_card *)card_ptr;
 
-       if (qdio_err)
+       QETH_CARD_TEXT_(card, 2, "qihq%d", queue);
+       QETH_CARD_TEXT_(card, 2, "qiec%d", qdio_err);
+
+       if (qeth_is_cq(card, queue))
+               qeth_qdio_cq_handler(card, qdio_err, queue, first_elem, count);
+       else if (qdio_err)
                qeth_schedule_recovery(card);
+
+
 }
 EXPORT_SYMBOL_GPL(qeth_qdio_input_handler);
 
@@ -3057,9 +3511,45 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
                        qeth_get_micros();
        }
        for (i = first_element; i < (first_element + count); ++i) {
-               buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+               int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
+               buffer = queue->bufs[bidx];
                qeth_handle_send_error(card, buffer, qdio_error);
-               qeth_clear_output_buffer(queue, buffer);
+
+               if (queue->bufstates &&
+                   (queue->bufstates[bidx].flags &
+                    QDIO_OUTBUF_STATE_FLAG_PENDING) != 0) {
+                       BUG_ON(card->options.cq != QETH_CQ_ENABLED);
+
+                       if (atomic_cmpxchg(&buffer->state,
+                                          QETH_QDIO_BUF_PRIMED,
+                                          QETH_QDIO_BUF_PENDING) ==
+                               QETH_QDIO_BUF_PRIMED) {
+                               qeth_notify_skbs(queue, buffer,
+                                                TX_NOTIFY_PENDING);
+                       }
+                       buffer->aob = queue->bufstates[bidx].aob;
+                       QETH_CARD_TEXT_(queue->card, 5, "pel%d", bidx);
+                       QETH_CARD_TEXT(queue->card, 5, "aob");
+                       QETH_CARD_TEXT_(queue->card, 5, "%lx",
+                                       virt_to_phys(buffer->aob));
+                       BUG_ON(bidx < 0 || bidx >= QDIO_MAX_BUFFERS_PER_Q);
+                       if (qeth_init_qdio_out_buf(queue, bidx)) {
+                               QETH_CARD_TEXT(card, 2, "outofbuf");
+                               qeth_schedule_recovery(card);
+                       }
+               } else {
+                       if (card->options.cq == QETH_CQ_ENABLED) {
+                               enum iucv_tx_notify n;
+
+                               n = qeth_compute_cq_notification(
+                                       buffer->buffer->element[15].sflags, 0);
+                               qeth_notify_skbs(queue, buffer, n);
+                       }
+
+                       qeth_clear_output_buffer(queue, buffer,
+                                               QETH_QDIO_BUF_EMPTY);
+               }
+               qeth_cleanup_handled_pending(queue, bidx, 0);
        }
        atomic_sub(count, &queue->used_buffers);
        /* check if we need to do something on this outbound queue */
@@ -3291,7 +3781,7 @@ int qeth_do_send_packet_fast(struct qeth_card *card,
                              QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
        /* ... now we've got the queue */
        index = queue->next_buf_to_fill;
-       buffer = &queue->bufs[queue->next_buf_to_fill];
+       buffer = queue->bufs[queue->next_buf_to_fill];
        /*
         * check if buffer is empty to make sure that we do not 'overtake'
         * ourselves and try to fill a buffer that is already primed
@@ -3325,7 +3815,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
        while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
                              QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
        start_index = queue->next_buf_to_fill;
-       buffer = &queue->bufs[queue->next_buf_to_fill];
+       buffer = queue->bufs[queue->next_buf_to_fill];
        /*
         * check if buffer is empty to make sure that we do not 'overtake'
         * ourselves and try to fill a buffer that is already primed
@@ -3347,7 +3837,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
                        queue->next_buf_to_fill =
                                (queue->next_buf_to_fill + 1) %
                                QDIO_MAX_BUFFERS_PER_Q;
-                       buffer = &queue->bufs[queue->next_buf_to_fill];
+                       buffer = queue->bufs[queue->next_buf_to_fill];
                        /* we did a step forward, so check buffer state
                         * again */
                        if (atomic_read(&buffer->state) !=
@@ -3925,6 +4415,20 @@ static void qeth_determine_capabilities(struct qeth_card *card)
        if (rc)
                QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
 
+       QETH_DBF_TEXT_(SETUP, 2, "qfmt%d", card->ssqd.qfmt);
+       QETH_DBF_TEXT_(SETUP, 2, "%d", card->ssqd.qdioac1);
+       QETH_DBF_TEXT_(SETUP, 2, "%d", card->ssqd.qdioac3);
+       QETH_DBF_TEXT_(SETUP, 2, "icnt%d", card->ssqd.icnt);
+       if (!((card->ssqd.qfmt != QDIO_IQDIO_QFMT) ||
+           ((card->ssqd.qdioac1 & CHSC_AC1_INITIATE_INPUTQ) == 0) ||
+           ((card->ssqd.qdioac3 & CHSC_AC3_FORMAT2_CQ_AVAILABLE) == 0))) {
+               dev_info(&card->gdev->dev,
+                       "Completion Queueing supported\n");
+       } else {
+               card->options.cq = QETH_CQ_NOTAVAILABLE;
+       }
+
+
 out_offline:
        if (ddev_offline == 1)
                ccw_device_set_offline(ddev);
@@ -3932,11 +4436,30 @@ out:
        return;
 }
 
+static inline void qeth_qdio_establish_cq(struct qeth_card *card,
+       struct qdio_buffer **in_sbal_ptrs,
+       void (**queue_start_poll) (struct ccw_device *, int, unsigned long)) {
+       int i;
+
+       if (card->options.cq == QETH_CQ_ENABLED) {
+               int offset = QDIO_MAX_BUFFERS_PER_Q *
+                            (card->qdio.no_in_queues - 1);
+               i = QDIO_MAX_BUFFERS_PER_Q * (card->qdio.no_in_queues - 1);
+               for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
+                       in_sbal_ptrs[offset + i] = (struct qdio_buffer *)
+                               virt_to_phys(card->qdio.c_q->bufs[i].buffer);
+               }
+
+               queue_start_poll[card->qdio.no_in_queues - 1] = NULL;
+       }
+}
+
 static int qeth_qdio_establish(struct qeth_card *card)
 {
        struct qdio_initialize init_data;
        char *qib_param_field;
        struct qdio_buffer **in_sbal_ptrs;
+       void (**queue_start_poll) (struct ccw_device *, int, unsigned long);
        struct qdio_buffer **out_sbal_ptrs;
        int i, j, k;
        int rc = 0;
@@ -3945,34 +4468,48 @@ static int qeth_qdio_establish(struct qeth_card *card)
 
        qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
                              GFP_KERNEL);
-       if (!qib_param_field)
-               return -ENOMEM;
+       if (!qib_param_field) {
+               rc =  -ENOMEM;
+               goto out_free_nothing;
+       }
 
        qeth_create_qib_param_field(card, qib_param_field);
        qeth_create_qib_param_field_blkt(card, qib_param_field);
 
-       in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
+       in_sbal_ptrs = kzalloc(card->qdio.no_in_queues *
+                              QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
                               GFP_KERNEL);
        if (!in_sbal_ptrs) {
-               kfree(qib_param_field);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto out_free_qib_param;
        }
-       for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+       for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
                in_sbal_ptrs[i] = (struct qdio_buffer *)
                        virt_to_phys(card->qdio.in_q->bufs[i].buffer);
+       }
+
+       queue_start_poll = kzalloc(sizeof(void *) * card->qdio.no_in_queues,
+                                  GFP_KERNEL);
+       if (!queue_start_poll) {
+               rc = -ENOMEM;
+               goto out_free_in_sbals;
+       }
+       for (i = 0; i < card->qdio.no_in_queues; ++i)
+               queue_start_poll[i] = card->discipline.start_poll;
+
+       qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll);
 
        out_sbal_ptrs =
-               kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
+               kzalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
                        sizeof(void *), GFP_KERNEL);
        if (!out_sbal_ptrs) {
-               kfree(in_sbal_ptrs);
-               kfree(qib_param_field);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto out_free_queue_start_poll;
        }
        for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
                for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) {
                        out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys(
-                               card->qdio.out_qs[i]->bufs[j].buffer);
+                               card->qdio.out_qs[i]->bufs[j]->buffer);
                }
 
        memset(&init_data, 0, sizeof(struct qdio_initialize));
@@ -3980,14 +4517,15 @@ static int qeth_qdio_establish(struct qeth_card *card)
        init_data.q_format               = qeth_get_qdio_q_format(card);
        init_data.qib_param_field_format = 0;
        init_data.qib_param_field        = qib_param_field;
-       init_data.no_input_qs            = 1;
+       init_data.no_input_qs            = card->qdio.no_in_queues;
        init_data.no_output_qs           = card->qdio.no_out_queues;
        init_data.input_handler          = card->discipline.input_handler;
        init_data.output_handler         = card->discipline.output_handler;
-       init_data.queue_start_poll       = card->discipline.start_poll;
+       init_data.queue_start_poll       = queue_start_poll;
        init_data.int_parm               = (unsigned long) card;
        init_data.input_sbal_addr_array  = (void **) in_sbal_ptrs;
        init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
+       init_data.output_sbal_state_array = card->qdio.out_bufstates;
        init_data.scan_threshold =
                (card->info.type == QETH_CARD_TYPE_IQD) ? 8 : 32;
 
@@ -4004,10 +4542,26 @@ static int qeth_qdio_establish(struct qeth_card *card)
                        qdio_free(CARD_DDEV(card));
                }
        }
+
+       switch (card->options.cq) {
+       case QETH_CQ_ENABLED:
+               dev_info(&card->gdev->dev, "Completion Queue support enabled");
+               break;
+       case QETH_CQ_DISABLED:
+               dev_info(&card->gdev->dev, "Completion Queue support disabled");
+               break;
+       default:
+               break;
+       }
 out:
        kfree(out_sbal_ptrs);
+out_free_queue_start_poll:
+       kfree(queue_start_poll);
+out_free_in_sbals:
        kfree(in_sbal_ptrs);
+out_free_qib_param:
        kfree(qib_param_field);
+out_free_nothing:
        return rc;
 }
 
@@ -4144,29 +4698,36 @@ out:
 }
 EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card);
 
-static inline int qeth_create_skb_frag(struct qdio_buffer_element *element,
+static inline int qeth_create_skb_frag(struct qeth_qdio_buffer *qethbuffer,
+               struct qdio_buffer_element *element,
                struct sk_buff **pskb, int offset, int *pfrag, int data_len)
 {
        struct page *page = virt_to_page(element->addr);
        if (*pskb == NULL) {
-               /* the upper protocol layers assume that there is data in the
-                * skb itself. Copy a small amount (64 bytes) to make them
-                * happy. */
-               *pskb = dev_alloc_skb(64 + ETH_HLEN);
-               if (!(*pskb))
-                       return -ENOMEM;
+               if (qethbuffer->rx_skb) {
+                       /* only if qeth_card.options.cq == QETH_CQ_ENABLED */
+                       *pskb = qethbuffer->rx_skb;
+                       qethbuffer->rx_skb = NULL;
+               } else {
+                       *pskb = dev_alloc_skb(QETH_RX_PULL_LEN + ETH_HLEN);
+                       if (!(*pskb))
+                               return -ENOMEM;
+               }
+
                skb_reserve(*pskb, ETH_HLEN);
-               if (data_len <= 64) {
+               if (data_len <= QETH_RX_PULL_LEN) {
                        memcpy(skb_put(*pskb, data_len), element->addr + offset,
                                data_len);
                } else {
                        get_page(page);
-                       memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
-                       skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
-                               data_len - 64);
-                       (*pskb)->data_len += data_len - 64;
-                       (*pskb)->len      += data_len - 64;
-                       (*pskb)->truesize += data_len - 64;
+                       memcpy(skb_put(*pskb, QETH_RX_PULL_LEN),
+                              element->addr + offset, QETH_RX_PULL_LEN);
+                       skb_fill_page_desc(*pskb, *pfrag, page,
+                               offset + QETH_RX_PULL_LEN,
+                               data_len - QETH_RX_PULL_LEN);
+                       (*pskb)->data_len += data_len - QETH_RX_PULL_LEN;
+                       (*pskb)->len      += data_len - QETH_RX_PULL_LEN;
+                       (*pskb)->truesize += data_len - QETH_RX_PULL_LEN;
                        (*pfrag)++;
                }
        } else {
@@ -4177,15 +4738,18 @@ static inline int qeth_create_skb_frag(struct qdio_buffer_element *element,
                (*pskb)->truesize += data_len;
                (*pfrag)++;
        }
+
+
        return 0;
 }
 
 struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
-               struct qdio_buffer *buffer,
+               struct qeth_qdio_buffer *qethbuffer,
                struct qdio_buffer_element **__element, int *__offset,
                struct qeth_hdr **hdr)
 {
        struct qdio_buffer_element *element = *__element;
+       struct qdio_buffer *buffer = qethbuffer->buffer;
        int offset = *__offset;
        struct sk_buff *skb = NULL;
        int skb_len = 0;
@@ -4230,9 +4794,10 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
        if (!skb_len)
                return NULL;
 
-       if ((skb_len >= card->options.rx_sg_cb) &&
-           (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
-           (!atomic_read(&card->force_alloc_skb))) {
+       if (((skb_len >= card->options.rx_sg_cb) &&
+            (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
+            (!atomic_read(&card->force_alloc_skb))) ||
+           (card->options.cq == QETH_CQ_ENABLED)) {
                use_rx_sg = 1;
        } else {
                skb = dev_alloc_skb(skb_len + headroom);
@@ -4247,8 +4812,8 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
                data_len = min(skb_len, (int)(element->length - offset));
                if (data_len) {
                        if (use_rx_sg) {
-                               if (qeth_create_skb_frag(element, &skb, offset,
-                                   &frag, data_len))
+                               if (qeth_create_skb_frag(qethbuffer, element,
+                                   &skb, offset, &frag, data_len))
                                        goto no_mem;
                        } else {
                                memcpy(skb_put(skb, data_len), data_ptr,
@@ -4650,6 +5215,8 @@ static struct {
        {"tx do_QDIO count"},
        {"tx csum"},
        {"tx lin"},
+       {"cq handler count"},
+       {"cq handler time"}
 };
 
 int qeth_core_get_sset_count(struct net_device *dev, int stringset)
@@ -4708,6 +5275,8 @@ void qeth_core_get_ethtool_stats(struct net_device *dev,
        data[32] = card->perf_stats.outbound_do_qdio_cnt;
        data[33] = card->perf_stats.tx_csum;
        data[34] = card->perf_stats.tx_lin;
+       data[35] = card->perf_stats.cq_cnt;
+       data[36] = card->perf_stats.cq_time;
 }
 EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats);
 
@@ -4866,7 +5435,16 @@ static int __init qeth_core_init(void)
                goto slab_err;
        }
 
+       qeth_qdio_outbuf_cache = kmem_cache_create("qeth_buf",
+                       sizeof(struct qeth_qdio_out_buffer), 0, 0, NULL);
+       if (!qeth_qdio_outbuf_cache) {
+               rc = -ENOMEM;
+               goto cqslab_err;
+       }
+
        return 0;
+cqslab_err:
+       kmem_cache_destroy(qeth_core_header_cache);
 slab_err:
        root_device_unregister(qeth_core_root_dev);
 register_err:
@@ -4891,6 +5469,7 @@ static void __exit qeth_core_exit(void)
                           &driver_attr_group);
        ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
        ccw_driver_unregister(&qeth_ccw_driver);
+       kmem_cache_destroy(qeth_qdio_outbuf_cache);
        kmem_cache_destroy(qeth_core_header_cache);
        qeth_unregister_dbf_views();
        pr_info("core functions removed\n");
index b70b47f..a21ae3d 100644 (file)
@@ -409,7 +409,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
        BUG_ON(!budget);
        while (budget) {
                skb = qeth_core_get_next_skb(card,
-                       card->qdio.in_q->bufs[card->rx.b_index].buffer,
+                       &card->qdio.in_q->bufs[card->rx.b_index],
                        &card->rx.b_element, &card->rx.e_offset, &hdr);
                if (!skb) {
                        *done = 1;
@@ -925,7 +925,7 @@ static const struct net_device_ops qeth_l2_netdev_ops = {
        .ndo_get_stats          = qeth_get_stats,
        .ndo_start_xmit         = qeth_l2_hard_start_xmit,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = qeth_l2_set_multicast_list,
+       .ndo_set_rx_mode        = qeth_l2_set_multicast_list,
        .ndo_do_ioctl           = qeth_l2_do_ioctl,
        .ndo_set_mac_address    = qeth_l2_set_mac_address,
        .ndo_change_mtu         = qeth_change_mtu,
index 14a43ae..e367315 100644 (file)
@@ -63,5 +63,9 @@ int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
 void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions,
                        const u8 *);
 int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *);
+struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions);
+int qeth_l3_add_ip(struct qeth_card *, struct qeth_ipaddr *);
+int qeth_l3_delete_ip(struct qeth_card *, struct qeth_ipaddr *);
+void qeth_l3_set_ip_addr_list(struct qeth_card *);
 
 #endif /* __QETH_L3_H__ */
index fafb8c2..ce73520 100644 (file)
@@ -29,6 +29,7 @@
 #include <net/ip.h>
 #include <net/arp.h>
 #include <net/ip6_checksum.h>
+#include <net/iucv/af_iucv.h>
 
 #include "qeth_l3.h"
 
@@ -267,7 +268,7 @@ static int __qeth_l3_insert_ip_todo(struct qeth_card *card,
        }
 }
 
-static int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
 {
        unsigned long flags;
        int rc = 0;
@@ -286,7 +287,7 @@ static int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
        return rc;
 }
 
-static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
 {
        unsigned long flags;
        int rc = 0;
@@ -305,7 +306,7 @@ static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
 }
 
 
-static struct qeth_ipaddr *qeth_l3_get_addr_buffer(
+struct qeth_ipaddr *qeth_l3_get_addr_buffer(
                                enum qeth_prot_versions prot)
 {
        struct qeth_ipaddr *addr;
@@ -421,7 +422,7 @@ again:
        list_splice(&fail_list, &card->ip_list);
 }
 
-static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
+void qeth_l3_set_ip_addr_list(struct qeth_card *card)
 {
        struct list_head *tbd_list;
        struct qeth_ipaddr *todo, *addr;
@@ -438,7 +439,7 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
 
        spin_lock_irqsave(&card->ip_lock, flags);
        tbd_list = card->ip_tbd_list;
-       card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
+       card->ip_tbd_list = kzalloc(sizeof(struct list_head), GFP_ATOMIC);
        if (!card->ip_tbd_list) {
                QETH_CARD_TEXT(card, 0, "silnomem");
                card->ip_tbd_list = tbd_list;
@@ -1993,12 +1994,13 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
        __u16 vlan_tag = 0;
        int is_vlan;
        unsigned int len;
+       __u16 magic;
 
        *done = 0;
        BUG_ON(!budget);
        while (budget) {
                skb = qeth_core_get_next_skb(card,
-                       card->qdio.in_q->bufs[card->rx.b_index].buffer,
+                       &card->qdio.in_q->bufs[card->rx.b_index],
                        &card->rx.b_element, &card->rx.e_offset, &hdr);
                if (!skb) {
                        *done = 1;
@@ -2007,12 +2009,26 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
                skb->dev = card->dev;
                switch (hdr->hdr.l3.id) {
                case QETH_HEADER_TYPE_LAYER3:
-                       is_vlan = qeth_l3_rebuild_skb(card, skb, hdr,
+                       magic = *(__u16 *)skb->data;
+                       if ((card->info.type == QETH_CARD_TYPE_IQD) &&
+                           (magic == ETH_P_AF_IUCV)) {
+                               skb->protocol = ETH_P_AF_IUCV;
+                               skb->pkt_type = PACKET_HOST;
+                               skb->mac_header = NET_SKB_PAD;
+                               skb->dev = card->dev;
+                               len = skb->len;
+                               card->dev->header_ops->create(skb, card->dev, 0,
+                                       card->dev->dev_addr, "FAKELL",
+                                       card->dev->addr_len);
+                               netif_receive_skb(skb);
+                       } else {
+                               is_vlan = qeth_l3_rebuild_skb(card, skb, hdr,
                                                      &vlan_tag);
-                       len = skb->len;
-                       if (is_vlan && !card->options.sniffer)
-                               __vlan_hwaccel_put_tag(skb, vlan_tag);
-                       napi_gro_receive(&card->napi, skb);
+                               len = skb->len;
+                               if (is_vlan && !card->options.sniffer)
+                                       __vlan_hwaccel_put_tag(skb, vlan_tag);
+                               napi_gro_receive(&card->napi, skb);
+                       }
                        break;
                case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
                        skb->pkt_type = PACKET_HOST;
@@ -2784,6 +2800,30 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
        return cast_type;
 }
 
+static void qeth_l3_fill_af_iucv_hdr(struct qeth_card *card,
+               struct qeth_hdr *hdr, struct sk_buff *skb)
+{
+       char daddr[16];
+       struct af_iucv_trans_hdr *iucv_hdr;
+
+       skb_pull(skb, 14);
+       card->dev->header_ops->create(skb, card->dev, 0,
+                                     card->dev->dev_addr, card->dev->dev_addr,
+                                     card->dev->addr_len);
+       skb_pull(skb, 14);
+       iucv_hdr = (struct af_iucv_trans_hdr *)skb->data;
+       memset(hdr, 0, sizeof(struct qeth_hdr));
+       hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
+       hdr->hdr.l3.ext_flags = 0;
+       hdr->hdr.l3.length = skb->len;
+       hdr->hdr.l3.flags = QETH_HDR_IPV6 | QETH_CAST_UNICAST;
+       memset(daddr, 0, sizeof(daddr));
+       daddr[0] = 0xfe;
+       daddr[1] = 0x80;
+       memcpy(&daddr[8], iucv_hdr->destUserID, 8);
+       memcpy(hdr->hdr.l3.dest_addr, daddr, 16);
+}
+
 static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
                struct sk_buff *skb, int ipv, int cast_type)
 {
@@ -2936,8 +2976,11 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        int data_offset = -1;
        int nr_frags;
 
-       if (((card->info.type == QETH_CARD_TYPE_IQD) && (!ipv)) ||
-            card->options.sniffer)
+       if (((card->info.type == QETH_CARD_TYPE_IQD) &&
+            (((card->options.cq != QETH_CQ_ENABLED) && !ipv) ||
+             ((card->options.cq == QETH_CQ_ENABLED) &&
+              (skb->protocol != ETH_P_AF_IUCV)))) ||
+           card->options.sniffer)
                        goto tx_drop;
 
        if ((card->state != CARD_STATE_UP) || !card->lan_online) {
@@ -2959,7 +3002,10 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) &&
            (skb_shinfo(skb)->nr_frags == 0)) {
                new_skb = skb;
-               data_offset = ETH_HLEN;
+               if (new_skb->protocol == ETH_P_AF_IUCV)
+                       data_offset = 0;
+               else
+                       data_offset = ETH_HLEN;
                hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
                if (!hdr)
                        goto tx_drop;
@@ -2993,7 +3039,6 @@ 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));
-                       new_skb->vlan_tci = 0;
                }
        }
 
@@ -3025,9 +3070,13 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        qeth_l3_fill_header(card, hdr, new_skb, ipv,
                                                cast_type);
                } else {
-                       qeth_l3_fill_header(card, hdr, new_skb, ipv,
-                                               cast_type);
-                       hdr->hdr.l3.length = new_skb->len - data_offset;
+                       if (new_skb->protocol == ETH_P_AF_IUCV)
+                               qeth_l3_fill_af_iucv_hdr(card, hdr, new_skb);
+                       else {
+                               qeth_l3_fill_header(card, hdr, new_skb, ipv,
+                                                       cast_type);
+                               hdr->hdr.l3.length = new_skb->len - data_offset;
+                       }
                }
 
                if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -3226,7 +3275,7 @@ static const struct net_device_ops qeth_l3_netdev_ops = {
        .ndo_get_stats          = qeth_get_stats,
        .ndo_start_xmit         = qeth_l3_hard_start_xmit,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = qeth_l3_set_multicast_list,
+       .ndo_set_rx_mode        = qeth_l3_set_multicast_list,
        .ndo_do_ioctl           = qeth_l3_do_ioctl,
        .ndo_change_mtu         = qeth_change_mtu,
        .ndo_fix_features       = qeth_l3_fix_features,
@@ -3242,7 +3291,7 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = {
        .ndo_get_stats          = qeth_get_stats,
        .ndo_start_xmit         = qeth_l3_hard_start_xmit,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = qeth_l3_set_multicast_list,
+       .ndo_set_rx_mode        = qeth_l3_set_multicast_list,
        .ndo_do_ioctl           = qeth_l3_do_ioctl,
        .ndo_change_mtu         = qeth_change_mtu,
        .ndo_fix_features       = qeth_l3_fix_features,
@@ -3290,6 +3339,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
                card->dev->flags |= IFF_NOARP;
                card->dev->netdev_ops = &qeth_l3_netdev_ops;
                qeth_l3_iqd_read_initial_mac(card);
+               if (card->options.hsuid[0])
+                       memcpy(card->dev->perm_addr, card->options.hsuid, 9);
        } else
                return -ENODEV;
 
@@ -3660,7 +3711,6 @@ static int qeth_l3_ip6_event(struct notifier_block *this,
        struct qeth_ipaddr *addr;
        struct qeth_card *card;
 
-
        card = qeth_l3_get_card_from_dev(dev);
        if (!card)
                return NOTIFY_DONE;
index cd99210..0ea2fbf 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #include <linux/slab.h>
-
+#include <asm/ebcdic.h>
 #include "qeth_l3.h"
 
 #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
@@ -308,6 +308,8 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
 
        if (card->info.type != QETH_CARD_TYPE_IQD)
                return -EPERM;
+       if (card->options.cq == QETH_CQ_ENABLED)
+               return -EPERM;
 
        mutex_lock(&card->conf_mutex);
        if ((card->state != CARD_STATE_DOWN) &&
@@ -347,6 +349,111 @@ out:
 static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show,
                qeth_l3_dev_sniffer_store);
 
+
+static ssize_t qeth_l3_dev_hsuid_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct qeth_card *card = dev_get_drvdata(dev);
+       char tmp_hsuid[9];
+
+       if (!card)
+               return -EINVAL;
+
+       if (card->info.type != QETH_CARD_TYPE_IQD)
+               return -EPERM;
+
+       if (card->state == CARD_STATE_DOWN)
+               return -EPERM;
+
+       memcpy(tmp_hsuid, card->options.hsuid, sizeof(tmp_hsuid));
+       EBCASC(tmp_hsuid, 8);
+       return sprintf(buf, "%s\n", tmp_hsuid);
+}
+
+static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct qeth_card *card = dev_get_drvdata(dev);
+       struct qeth_ipaddr *addr;
+       char *tmp;
+       int i;
+
+       if (!card)
+               return -EINVAL;
+
+       if (card->info.type != QETH_CARD_TYPE_IQD)
+               return -EPERM;
+       if (card->state != CARD_STATE_DOWN &&
+           card->state != CARD_STATE_RECOVER)
+               return -EPERM;
+       if (card->options.sniffer)
+               return -EPERM;
+       if (card->options.cq == QETH_CQ_NOTAVAILABLE)
+               return -EPERM;
+
+       tmp = strsep((char **)&buf, "\n");
+       if (strlen(tmp) > 8)
+               return -EINVAL;
+
+       if (card->options.hsuid[0]) {
+               /* delete old ip address */
+               addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
+               if (addr != NULL) {
+                       addr->u.a6.addr.s6_addr32[0] = 0xfe800000;
+                       addr->u.a6.addr.s6_addr32[1] = 0x00000000;
+                       for (i = 8; i < 16; i++)
+                               addr->u.a6.addr.s6_addr[i] =
+                                       card->options.hsuid[i - 8];
+                       addr->u.a6.pfxlen = 0;
+                       addr->type = QETH_IP_TYPE_NORMAL;
+               } else
+                       return -ENOMEM;
+               if (!qeth_l3_delete_ip(card, addr))
+                       kfree(addr);
+               qeth_l3_set_ip_addr_list(card);
+       }
+
+       if (strlen(tmp) == 0) {
+               /* delete ip address only */
+               card->options.hsuid[0] = '\0';
+               if (card->dev)
+                       memcpy(card->dev->perm_addr, card->options.hsuid, 9);
+               qeth_configure_cq(card, QETH_CQ_DISABLED);
+               return count;
+       }
+
+       if (qeth_configure_cq(card, QETH_CQ_ENABLED))
+               return -EPERM;
+
+       for (i = 0; i < 8; i++)
+               card->options.hsuid[i] = ' ';
+       card->options.hsuid[8] = '\0';
+       strncpy(card->options.hsuid, tmp, strlen(tmp));
+       ASCEBC(card->options.hsuid, 8);
+       if (card->dev)
+               memcpy(card->dev->perm_addr, card->options.hsuid, 9);
+
+       addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
+       if (addr != NULL) {
+               addr->u.a6.addr.s6_addr32[0] = 0xfe800000;
+               addr->u.a6.addr.s6_addr32[1] = 0x00000000;
+               for (i = 8; i < 16; i++)
+                       addr->u.a6.addr.s6_addr[i] = card->options.hsuid[i - 8];
+               addr->u.a6.pfxlen = 0;
+               addr->type = QETH_IP_TYPE_NORMAL;
+       } else
+               return -ENOMEM;
+       if (!qeth_l3_add_ip(card, addr))
+               kfree(addr);
+       qeth_l3_set_ip_addr_list(card);
+
+       return count;
+}
+
+static DEVICE_ATTR(hsuid, 0644, qeth_l3_dev_hsuid_show,
+                  qeth_l3_dev_hsuid_store);
+
+
 static struct attribute *qeth_l3_device_attrs[] = {
        &dev_attr_route4.attr,
        &dev_attr_route6.attr,
@@ -354,6 +461,7 @@ static struct attribute *qeth_l3_device_attrs[] = {
        &dev_attr_broadcast_mode.attr,
        &dev_attr_canonical_macaddr.attr,
        &dev_attr_sniffer.attr,
+       &dev_attr_hsuid.attr,
        NULL,
 };
 
index 3b0af11..a796de9 100644 (file)
@@ -27,6 +27,7 @@
 struct bfa_s;
 
 typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
+typedef void (*bfa_cb_cbfn_status_t) (void *cbarg, bfa_status_t status);
 
 /*
  * Interrupt message handlers
@@ -121,6 +122,7 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
 #define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do {    \
                (__hcb_qe)->cbfn  = (__cbfn);      \
                (__hcb_qe)->cbarg = (__cbarg);      \
+               (__hcb_qe)->pre_rmv = BFA_FALSE;                \
                list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q);      \
        } while (0)
 
@@ -135,6 +137,11 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
                }                                                       \
        } while (0)
 
+#define bfa_cb_queue_status(__bfa, __hcb_qe, __status) do {            \
+               (__hcb_qe)->fw_status = (__status);                     \
+               list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q);       \
+} while (0)
+
 #define bfa_cb_queue_done(__hcb_qe) do {       \
                (__hcb_qe)->once = BFA_FALSE;   \
        } while (0)
@@ -177,7 +184,7 @@ struct bfa_msix_s {
 struct bfa_hwif_s {
        void (*hw_reginit)(struct bfa_s *bfa);
        void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq);
-       void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
+       void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq, u32 ci);
        void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
        void (*hw_msix_ctrl_install)(struct bfa_s *bfa);
        void (*hw_msix_queue_install)(struct bfa_s *bfa);
@@ -268,10 +275,8 @@ struct bfa_iocfc_s {
        ((__bfa)->iocfc.hwif.hw_msix_queue_install(__bfa))
 #define bfa_msix_uninstall(__bfa)                                      \
        ((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
-#define bfa_isr_rspq_ack(__bfa, __queue) do {                          \
-       if ((__bfa)->iocfc.hwif.hw_rspq_ack)                            \
-               (__bfa)->iocfc.hwif.hw_rspq_ack(__bfa, __queue);        \
-} while (0)
+#define bfa_isr_rspq_ack(__bfa, __queue, __ci)                         \
+       ((__bfa)->iocfc.hwif.hw_rspq_ack(__bfa, __queue, __ci))
 #define bfa_isr_reqq_ack(__bfa, __queue) do {                          \
        if ((__bfa)->iocfc.hwif.hw_reqq_ack)                            \
                (__bfa)->iocfc.hwif.hw_reqq_ack(__bfa, __queue);        \
@@ -311,7 +316,7 @@ void bfa_msix_rspq(struct bfa_s *bfa, int vec);
 void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
 
 void bfa_hwcb_reginit(struct bfa_s *bfa);
-void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci);
 void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
 void bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa);
 void bfa_hwcb_msix_queue_install(struct bfa_s *bfa);
@@ -324,7 +329,8 @@ void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
 void bfa_hwct_reginit(struct bfa_s *bfa);
 void bfa_hwct2_reginit(struct bfa_s *bfa);
 void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci);
+void bfa_hwct2_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci);
 void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
 void bfa_hwct_msix_ctrl_install(struct bfa_s *bfa);
 void bfa_hwct_msix_queue_install(struct bfa_s *bfa);
@@ -376,6 +382,22 @@ int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa,
 #define bfa_get_fw_clock_res(__bfa)            \
        ((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res)
 
+/*
+ * lun mask macros return NULL when min cfg is enabled and there is
+ * no memory allocated for lunmask.
+ */
+#define bfa_get_lun_mask(__bfa)                                        \
+       ((&(__bfa)->modules.dconf_mod)->min_cfg) ? NULL :       \
+        (&(BFA_DCONF_MOD(__bfa)->dconf->lun_mask))
+
+#define bfa_get_lun_mask_list(_bfa)                            \
+       ((&(_bfa)->modules.dconf_mod)->min_cfg) ? NULL :        \
+        (bfa_get_lun_mask(_bfa)->lun_list)
+
+#define bfa_get_lun_mask_status(_bfa)                          \
+       (((&(_bfa)->modules.dconf_mod)->min_cfg)                \
+        ? BFA_LUNMASK_MINCFG : ((bfa_get_lun_mask(_bfa))->status))
+
 void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);
 void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);
 void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);
@@ -406,7 +428,22 @@ bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa,
 
 void bfa_iocfc_enable(struct bfa_s *bfa);
 void bfa_iocfc_disable(struct bfa_s *bfa);
+void bfa_iocfc_cb_dconf_modinit(struct bfa_s *bfa, bfa_status_t status);
 #define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout)                \
        bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
 
+struct bfa_cb_pending_q_s {
+       struct bfa_cb_qe_s      hcb_qe;
+       void                    *data;  /* Driver buffer */
+};
+
+/* Common macros to operate on pending stats/attr apis */
+#define bfa_pending_q_init(__qe, __cbfn, __cbarg, __data) do { \
+       bfa_q_qe_init(&((__qe)->hcb_qe.qe));                    \
+       (__qe)->hcb_qe.cbfn = (__cbfn);                         \
+       (__qe)->hcb_qe.cbarg = (__cbarg);                       \
+       (__qe)->hcb_qe.pre_rmv = BFA_TRUE;                      \
+       (__qe)->data = (__data);                                \
+} while (0)
+
 #endif /* __BFA_H__ */
index c38e589..4bd546b 100644 (file)
@@ -33,6 +33,7 @@ static struct bfa_module_s *hal_mods[] = {
        &hal_mod_uf,
        &hal_mod_rport,
        &hal_mod_fcp,
+       &hal_mod_dconf,
        NULL
 };
 
@@ -237,8 +238,6 @@ bfa_isr_rspq(struct bfa_s *bfa, int qid)
        u32     pi, ci;
        struct list_head *waitq;
 
-       bfa_isr_rspq_ack(bfa, qid);
-
        ci = bfa_rspq_ci(bfa, qid);
        pi = bfa_rspq_pi(bfa, qid);
 
@@ -251,11 +250,9 @@ bfa_isr_rspq(struct bfa_s *bfa, int qid)
        }
 
        /*
-        * update CI
+        * acknowledge RME completions and update CI
         */
-       bfa_rspq_ci(bfa, qid) = pi;
-       writel(pi, bfa->iocfc.bfa_regs.rme_q_ci[qid]);
-       mmiowb();
+       bfa_isr_rspq_ack(bfa, qid, ci);
 
        /*
         * Resume any pending requests in the corresponding reqq.
@@ -325,23 +322,19 @@ bfa_intx(struct bfa_s *bfa)
        int queue;
 
        intr = readl(bfa->iocfc.bfa_regs.intr_status);
-       if (!intr)
-               return BFA_FALSE;
 
        qintr = intr & (__HFN_INT_RME_MASK | __HFN_INT_CPE_MASK);
        if (qintr)
                writel(qintr, bfa->iocfc.bfa_regs.intr_status);
 
        /*
-        * RME completion queue interrupt
+        * Unconditional RME completion queue interrupt
         */
-       qintr = intr & __HFN_INT_RME_MASK;
-       if (qintr && bfa->queue_process) {
+       if (bfa->queue_process) {
                for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
                        bfa_isr_rspq(bfa, queue);
        }
 
-       intr &= ~qintr;
        if (!intr)
                return BFA_TRUE;
 
@@ -432,7 +425,8 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
                                   __HFN_INT_MBOX_LPU1_CT2);
                intr    &= __HFN_INT_ERR_MASK_CT2;
        } else {
-               halt_isr = intr & __HFN_INT_LL_HALT;
+               halt_isr = bfa_asic_id_ct(bfa->ioc.pcidev.device_id) ?
+                                         (intr & __HFN_INT_LL_HALT) : 0;
                pss_isr  = intr & __HFN_INT_ERR_PSS;
                lpu_isr  = intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1);
                intr    &= __HFN_INT_ERR_MASK;
@@ -578,7 +572,7 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
        } else {
                iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
                iocfc->hwif.hw_reqq_ack = NULL;
-               iocfc->hwif.hw_rspq_ack = NULL;
+               iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
                iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
                iocfc->hwif.hw_msix_ctrl_install = bfa_hwcb_msix_ctrl_install;
                iocfc->hwif.hw_msix_queue_install = bfa_hwcb_msix_queue_install;
@@ -595,7 +589,7 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
        if (bfa_asic_id_ct2(bfa_ioc_devid(&bfa->ioc))) {
                iocfc->hwif.hw_reginit = bfa_hwct2_reginit;
                iocfc->hwif.hw_isr_mode_set = NULL;
-               iocfc->hwif.hw_rspq_ack = NULL;
+               iocfc->hwif.hw_rspq_ack = bfa_hwct2_rspq_ack;
        }
 
        iocfc->hwif.hw_reginit(bfa);
@@ -685,7 +679,7 @@ bfa_iocfc_start_submod(struct bfa_s *bfa)
 
        bfa->queue_process = BFA_TRUE;
        for (i = 0; i < BFI_IOC_MAX_CQS; i++)
-               bfa_isr_rspq_ack(bfa, i);
+               bfa_isr_rspq_ack(bfa, i, bfa_rspq_ci(bfa, i));
 
        for (i = 0; hal_mods[i]; i++)
                hal_mods[i]->start(bfa);
@@ -709,7 +703,7 @@ bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete)
        struct bfa_s    *bfa = bfa_arg;
 
        if (complete) {
-               if (bfa->iocfc.cfgdone)
+               if (bfa->iocfc.cfgdone && BFA_DCONF_MOD(bfa)->flashdone)
                        bfa_cb_init(bfa->bfad, BFA_STATUS_OK);
                else
                        bfa_cb_init(bfa->bfad, BFA_STATUS_FAILED);
@@ -822,9 +816,11 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa)
         */
        bfa_fcport_init(bfa);
 
-       if (iocfc->action == BFA_IOCFC_ACT_INIT)
-               bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa);
-       else {
+       if (iocfc->action == BFA_IOCFC_ACT_INIT) {
+               if (BFA_DCONF_MOD(bfa)->flashdone == BFA_TRUE)
+                       bfa_cb_queue(bfa, &iocfc->init_hcb_qe,
+                               bfa_iocfc_init_cb, bfa);
+       } else {
                if (bfa->iocfc.action == BFA_IOCFC_ACT_ENABLE)
                        bfa_cb_queue(bfa, &bfa->iocfc.en_hcb_qe,
                                        bfa_iocfc_enable_cb, bfa);
@@ -1045,6 +1041,7 @@ bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
        }
 
        bfa_iocfc_send_cfg(bfa);
+       bfa_dconf_modinit(bfa);
 }
 
 /*
@@ -1207,7 +1204,9 @@ bfa_iocfc_stop(struct bfa_s *bfa)
        bfa->iocfc.action = BFA_IOCFC_ACT_STOP;
 
        bfa->queue_process = BFA_FALSE;
-       bfa_ioc_disable(&bfa->ioc);
+       bfa_dconf_modexit(bfa);
+       if (BFA_DCONF_MOD(bfa)->flashdone == BFA_TRUE)
+               bfa_ioc_disable(&bfa->ioc);
 }
 
 void
@@ -1540,10 +1539,17 @@ bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q)
        struct list_head                *qe;
        struct list_head                *qen;
        struct bfa_cb_qe_s      *hcb_qe;
+       bfa_cb_cbfn_status_t    cbfn;
 
        list_for_each_safe(qe, qen, comp_q) {
                hcb_qe = (struct bfa_cb_qe_s *) qe;
-               hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE);
+               if (hcb_qe->pre_rmv) {
+                       /* qe is invalid after return, dequeue before cbfn() */
+                       list_del(qe);
+                       cbfn = (bfa_cb_cbfn_status_t)(hcb_qe->cbfn);
+                       cbfn(hcb_qe->cbarg, hcb_qe->fw_status);
+               } else
+                       hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE);
        }
 }
 
@@ -1556,10 +1562,20 @@ bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q)
        while (!list_empty(comp_q)) {
                bfa_q_deq(comp_q, &qe);
                hcb_qe = (struct bfa_cb_qe_s *) qe;
+               WARN_ON(hcb_qe->pre_rmv);
                hcb_qe->cbfn(hcb_qe->cbarg, BFA_FALSE);
        }
 }
 
+void
+bfa_iocfc_cb_dconf_modinit(struct bfa_s *bfa, bfa_status_t status)
+{
+       if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT) {
+               if (bfa->iocfc.cfgdone == BFA_TRUE)
+                       bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
+                               bfa_iocfc_init_cb, bfa);
+       }
+}
 
 /*
  * Return the list of PCI vendor/device id lists supported by this
index ed8d31b..7b3d235 100644 (file)
@@ -144,6 +144,7 @@ enum bfa_status {
        BFA_STATUS_INVLD_DFSZ   = 24,   /*  Invalid Max data field size */
        BFA_STATUS_CMD_NOTSUPP  = 26,   /*  Command/API not supported */
        BFA_STATUS_FABRIC_RJT   = 29,   /*  Reject from attached fabric */
+       BFA_STATUS_UNKNOWN_VWWN = 30,   /*  VPORT PWWN not found */
        BFA_STATUS_PORT_OFFLINE = 34,   /*  Port is not online */
        BFA_STATUS_VPORT_WWN_BP = 46,   /*  WWN is same as base port's WWN */
        BFA_STATUS_PORT_NOT_DISABLED = 47, /* Port not disabled disable port */
@@ -164,6 +165,8 @@ enum bfa_status {
        BFA_STATUS_INVALID_MAC  = 134, /*  Invalid MAC address */
        BFA_STATUS_PBC          = 154, /*  Operation not allowed for pre-boot
                                        *  configuration */
+       BFA_STATUS_BAD_FWCFG = 156,     /* Bad firmware configuration */
+       BFA_STATUS_INVALID_VENDOR = 158, /* Invalid switch vendor */
        BFA_STATUS_SFP_NOT_READY = 159, /* SFP info is not ready. Retry */
        BFA_STATUS_TRUNK_ENABLED = 164, /* Trunk is already enabled on
                                         * this adapter */
@@ -172,11 +175,15 @@ enum bfa_status {
        BFA_STATUS_IOPROFILE_OFF = 175, /* IO profile OFF */
        BFA_STATUS_PHY_NOT_PRESENT = 183, /* PHY module not present */
        BFA_STATUS_FEATURE_NOT_SUPPORTED = 192, /* Feature not supported */
+       BFA_STATUS_ENTRY_EXISTS = 193,  /* Entry already exists */
+       BFA_STATUS_ENTRY_NOT_EXISTS = 194, /* Entry does not exist */
+       BFA_STATUS_NO_CHANGE = 195,     /* Feature already in that state */
        BFA_STATUS_FAA_ENABLED = 197,   /* FAA is already enabled */
        BFA_STATUS_FAA_DISABLED = 198,  /* FAA is already disabled */
        BFA_STATUS_FAA_ACQUIRED = 199,  /* FAA is already acquired */
        BFA_STATUS_FAA_ACQ_ADDR = 200,  /* Acquiring addr */
        BFA_STATUS_ERROR_TRUNK_ENABLED = 203,   /* Trunk enabled on adapter */
+       BFA_STATUS_MAX_ENTRY_REACHED = 212,     /* MAX entry reached */
        BFA_STATUS_MAX_VAL              /* Unknown error code */
 };
 #define bfa_status_t enum bfa_status
@@ -358,6 +365,139 @@ struct bfa_ioc_attr_s {
        u8                              rsvd[4];        /*  64bit align */
 };
 
+/*
+ *                     AEN related definitions
+ */
+enum bfa_aen_category {
+       BFA_AEN_CAT_ADAPTER     = 1,
+       BFA_AEN_CAT_PORT        = 2,
+       BFA_AEN_CAT_LPORT       = 3,
+       BFA_AEN_CAT_RPORT       = 4,
+       BFA_AEN_CAT_ITNIM       = 5,
+       BFA_AEN_CAT_AUDIT       = 8,
+       BFA_AEN_CAT_IOC         = 9,
+};
+
+/* BFA adapter level events */
+enum bfa_adapter_aen_event {
+       BFA_ADAPTER_AEN_ADD     = 1,    /* New Adapter found event */
+       BFA_ADAPTER_AEN_REMOVE  = 2,    /* Adapter removed event */
+};
+
+struct bfa_adapter_aen_data_s {
+       char    serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+       u32     nports; /* Number of NPorts */
+       wwn_t   pwwn;   /* WWN of one of its physical port */
+};
+
+/* BFA physical port Level events */
+enum bfa_port_aen_event {
+       BFA_PORT_AEN_ONLINE     = 1,    /* Physical Port online event */
+       BFA_PORT_AEN_OFFLINE    = 2,    /* Physical Port offline event */
+       BFA_PORT_AEN_RLIR       = 3,    /* RLIR event, not supported */
+       BFA_PORT_AEN_SFP_INSERT = 4,    /* SFP inserted event */
+       BFA_PORT_AEN_SFP_REMOVE = 5,    /* SFP removed event */
+       BFA_PORT_AEN_SFP_POM    = 6,    /* SFP POM event */
+       BFA_PORT_AEN_ENABLE     = 7,    /* Physical Port enable event */
+       BFA_PORT_AEN_DISABLE    = 8,    /* Physical Port disable event */
+       BFA_PORT_AEN_AUTH_ON    = 9,    /* Physical Port auth success event */
+       BFA_PORT_AEN_AUTH_OFF   = 10,   /* Physical Port auth fail event */
+       BFA_PORT_AEN_DISCONNECT = 11,   /* Physical Port disconnect event */
+       BFA_PORT_AEN_QOS_NEG    = 12,   /* Base Port QOS negotiation event */
+       BFA_PORT_AEN_FABRIC_NAME_CHANGE = 13, /* Fabric Name/WWN change */
+       BFA_PORT_AEN_SFP_ACCESS_ERROR   = 14, /* SFP read error event */
+       BFA_PORT_AEN_SFP_UNSUPPORT      = 15, /* Unsupported SFP event */
+};
+
+enum bfa_port_aen_sfp_pom {
+       BFA_PORT_AEN_SFP_POM_GREEN = 1, /* Normal */
+       BFA_PORT_AEN_SFP_POM_AMBER = 2, /* Warning */
+       BFA_PORT_AEN_SFP_POM_RED   = 3, /* Critical */
+       BFA_PORT_AEN_SFP_POM_MAX   = BFA_PORT_AEN_SFP_POM_RED
+};
+
+struct bfa_port_aen_data_s {
+       wwn_t           pwwn;           /* WWN of the physical port */
+       wwn_t           fwwn;           /* WWN of the fabric port */
+       u32             phy_port_num;   /* For SFP related events */
+       u16             ioc_type;
+       u16             level;          /* Only transitions will be informed */
+       mac_t           mac;            /* MAC address of the ethernet port */
+       u16             rsvd;
+};
+
+/* BFA AEN logical port events */
+enum bfa_lport_aen_event {
+       BFA_LPORT_AEN_NEW       = 1,            /* LPort created event */
+       BFA_LPORT_AEN_DELETE    = 2,            /* LPort deleted event */
+       BFA_LPORT_AEN_ONLINE    = 3,            /* LPort online event */
+       BFA_LPORT_AEN_OFFLINE   = 4,            /* LPort offline event */
+       BFA_LPORT_AEN_DISCONNECT = 5,           /* LPort disconnect event */
+       BFA_LPORT_AEN_NEW_PROP  = 6,            /* VPort created event */
+       BFA_LPORT_AEN_DELETE_PROP = 7,          /* VPort deleted event */
+       BFA_LPORT_AEN_NEW_STANDARD = 8,         /* VPort created event */
+       BFA_LPORT_AEN_DELETE_STANDARD = 9,      /* VPort deleted event */
+       BFA_LPORT_AEN_NPIV_DUP_WWN = 10,        /* VPort with duplicate WWN */
+       BFA_LPORT_AEN_NPIV_FABRIC_MAX = 11,     /* Max NPIV in fabric/fport */
+       BFA_LPORT_AEN_NPIV_UNKNOWN = 12,        /* Unknown NPIV Error code */
+};
+
+struct bfa_lport_aen_data_s {
+       u16     vf_id;  /* vf_id of this logical port */
+       u16     roles;  /* Logical port mode,IM/TM/IP etc */
+       u32     rsvd;
+       wwn_t   ppwwn;  /* WWN of its physical port */
+       wwn_t   lpwwn;  /* WWN of this logical port */
+};
+
+/* BFA ITNIM events */
+enum bfa_itnim_aen_event {
+       BFA_ITNIM_AEN_ONLINE     = 1,   /* Target online */
+       BFA_ITNIM_AEN_OFFLINE    = 2,   /* Target offline */
+       BFA_ITNIM_AEN_DISCONNECT = 3,   /* Target disconnected */
+};
+
+struct bfa_itnim_aen_data_s {
+       u16             vf_id;          /* vf_id of the IT nexus */
+       u16             rsvd[3];
+       wwn_t           ppwwn;          /* WWN of its physical port */
+       wwn_t           lpwwn;          /* WWN of logical port */
+       wwn_t           rpwwn;          /* WWN of remote(target) port */
+};
+
+/* BFA audit events */
+enum bfa_audit_aen_event {
+       BFA_AUDIT_AEN_AUTH_ENABLE       = 1,
+       BFA_AUDIT_AEN_AUTH_DISABLE      = 2,
+       BFA_AUDIT_AEN_FLASH_ERASE       = 3,
+       BFA_AUDIT_AEN_FLASH_UPDATE      = 4,
+};
+
+struct bfa_audit_aen_data_s {
+       wwn_t   pwwn;
+       int     partition_inst;
+       int     partition_type;
+};
+
+/* BFA IOC level events */
+enum bfa_ioc_aen_event {
+       BFA_IOC_AEN_HBGOOD  = 1,        /* Heart Beat restore event     */
+       BFA_IOC_AEN_HBFAIL  = 2,        /* Heart Beat failure event     */
+       BFA_IOC_AEN_ENABLE  = 3,        /* IOC enabled event            */
+       BFA_IOC_AEN_DISABLE = 4,        /* IOC disabled event           */
+       BFA_IOC_AEN_FWMISMATCH  = 5,    /* IOC firmware mismatch        */
+       BFA_IOC_AEN_FWCFG_ERROR = 6,    /* IOC firmware config error    */
+       BFA_IOC_AEN_INVALID_VENDOR = 7,
+       BFA_IOC_AEN_INVALID_NWWN = 8,   /* Zero NWWN                    */
+       BFA_IOC_AEN_INVALID_PWWN = 9    /* Zero PWWN                    */
+};
+
+struct bfa_ioc_aen_data_s {
+       wwn_t   pwwn;
+       u16     ioc_type;
+       mac_t   mac;
+};
+
 /*
  * ---------------------- mfg definitions ------------
  */
@@ -520,6 +660,20 @@ struct bfa_boot_bootlun_s {
 /*
  * BOOT boot configuraton
  */
+struct bfa_boot_cfg_s {
+       u8              version;
+       u8              rsvd1;
+       u16             chksum;
+       u8              enable;         /* enable/disable SAN boot */
+       u8              speed;          /* boot speed settings */
+       u8              topology;       /* boot topology setting */
+       u8              bootopt;        /* bfa_boot_bootopt_t */
+       u32             nbluns;         /* number of boot luns */
+       u32             rsvd2;
+       struct bfa_boot_bootlun_s blun[BFA_BOOT_BOOTLUN_MAX];
+       struct bfa_boot_bootlun_s blun_disc[BFA_BOOT_BOOTLUN_MAX];
+};
+
 struct bfa_boot_pbc_s {
        u8              enable;         /*  enable/disable SAN boot */
        u8              speed;          /*  boot speed settings */
@@ -529,6 +683,15 @@ struct bfa_boot_pbc_s {
        struct bfa_boot_bootlun_s pblun[BFA_PREBOOT_BOOTLUN_MAX];
 };
 
+struct bfa_ethboot_cfg_s {
+       u8              version;
+       u8              rsvd1;
+       u16             chksum;
+       u8              enable; /* enable/disable Eth/PXE boot */
+       u8              rsvd2;
+       u16             vlan;
+};
+
 /*
  * ASIC block configuration related structures
  */
@@ -587,6 +750,14 @@ struct bfa_ablk_cfg_s {
  */
 #define SFP_DIAGMON_SIZE       10 /* num bytes of diag monitor data */
 
+/* SFP state change notification event */
+#define BFA_SFP_SCN_REMOVED    0
+#define BFA_SFP_SCN_INSERTED   1
+#define BFA_SFP_SCN_POM                2
+#define BFA_SFP_SCN_FAILED     3
+#define BFA_SFP_SCN_UNSUPPORT  4
+#define BFA_SFP_SCN_VALID      5
+
 enum bfa_defs_sfp_media_e {
        BFA_SFP_MEDIA_UNKNOWN   = 0x00,
        BFA_SFP_MEDIA_CU        = 0x01,
index 0b97525..863c6ba 100644 (file)
@@ -268,6 +268,7 @@ struct bfa_fw_port_snsm_stats_s {
     u32    error_resets;       /*  error resets initiated by upsm      */
     u32    sync_lost;          /*  Sync loss count                     */
     u32    sig_lost;           /*  Signal loss count                   */
+       u32     asn8g_attempts; /* SNSM HWSM at 8Gbps attempts */
 };
 
 struct bfa_fw_port_physm_stats_s {
@@ -468,6 +469,7 @@ struct bfa_fw_stats_s {
  * QoS states
  */
 enum bfa_qos_state {
+       BFA_QOS_DISABLED = 0,           /* QoS is disabled */
        BFA_QOS_ONLINE = 1,             /*  QoS is online */
        BFA_QOS_OFFLINE = 2,            /*  QoS is offline */
 };
@@ -670,6 +672,12 @@ struct bfa_itnim_iostats_s {
        u32     tm_iocdowns;            /*  TM cleaned-up due to IOC down   */
        u32     tm_cleanups;            /*  TM cleanup requests */
        u32     tm_cleanup_comps;       /*  TM cleanup completions      */
+       u32     lm_lun_across_sg;       /*  LM lun is across sg data buf */
+       u32     lm_lun_not_sup;         /*  LM lun not supported */
+       u32     lm_rpl_data_changed;    /*  LM report-lun data changed */
+       u32     lm_wire_residue_changed; /* LM report-lun rsp residue changed */
+       u32     lm_small_buf_addresidue; /* LM buf smaller than reported cnt */
+       u32     lm_lun_not_rdy;         /* LM lun not ready */
 };
 
 /* Modify char* port_stt[] in bfal_port.c if a new state was added */
@@ -785,7 +793,50 @@ enum bfa_port_linkstate_rsn {
        CEE_ISCSI_PRI_PFC_OFF                   = 42,
        CEE_ISCSI_PRI_OVERLAP_FCOE_PRI          = 43
 };
+
+#define MAX_LUN_MASK_CFG 16
+
+/*
+ * Initially flash content may be fff. On making LUN mask enable and disable
+ * state chnage.  when report lun command is being processed it goes from
+ * BFA_LUN_MASK_ACTIVE to BFA_LUN_MASK_FETCH and comes back to
+ * BFA_LUN_MASK_ACTIVE.
+ */
+enum bfa_ioim_lun_mask_state_s {
+       BFA_IOIM_LUN_MASK_INACTIVE = 0,
+       BFA_IOIM_LUN_MASK_ACTIVE = 1,
+       BFA_IOIM_LUN_MASK_FETCHED = 2,
+};
+
+enum bfa_lunmask_state_s {
+       BFA_LUNMASK_DISABLED = 0x00,
+       BFA_LUNMASK_ENABLED = 0x01,
+       BFA_LUNMASK_MINCFG = 0x02,
+       BFA_LUNMASK_UNINITIALIZED = 0xff,
+};
+
 #pragma pack(1)
+/*
+ * LUN mask configuration
+ */
+struct bfa_lun_mask_s {
+       wwn_t           lp_wwn;
+       wwn_t           rp_wwn;
+       struct scsi_lun lun;
+       u8              ua;
+       u8              rsvd[3];
+       u16             rp_tag;
+       u8              lp_tag;
+       u8              state;
+};
+
+#define MAX_LUN_MASK_CFG 16
+struct bfa_lunmask_cfg_s {
+       u32     status;
+       u32     rsvd;
+       struct bfa_lun_mask_s   lun_list[MAX_LUN_MASK_CFG];
+};
+
 /*
  *      Physical port configuration
  */
@@ -1228,4 +1279,52 @@ struct bfa_cee_stats_s {
 
 #pragma pack()
 
+/*
+ *                     AEN related definitions
+ */
+#define BFAD_NL_VENDOR_ID (((u64)0x01 << SCSI_NL_VID_TYPE_SHIFT) \
+                          | BFA_PCI_VENDOR_ID_BROCADE)
+
+/* BFA remote port events */
+enum bfa_rport_aen_event {
+       BFA_RPORT_AEN_ONLINE     = 1,   /* RPort online event */
+       BFA_RPORT_AEN_OFFLINE    = 2,   /* RPort offline event */
+       BFA_RPORT_AEN_DISCONNECT = 3,   /* RPort disconnect event */
+       BFA_RPORT_AEN_QOS_PRIO   = 4,   /* QOS priority change event */
+       BFA_RPORT_AEN_QOS_FLOWID = 5,   /* QOS flow Id change event */
+};
+
+struct bfa_rport_aen_data_s {
+       u16             vf_id;  /* vf_id of this logical port */
+       u16             rsvd[3];
+       wwn_t           ppwwn;  /* WWN of its physical port */
+       wwn_t           lpwwn;  /* WWN of this logical port */
+       wwn_t           rpwwn;  /* WWN of this remote port */
+       union {
+               struct bfa_rport_qos_attr_s qos;
+       } priv;
+};
+
+union bfa_aen_data_u {
+       struct bfa_adapter_aen_data_s   adapter;
+       struct bfa_port_aen_data_s      port;
+       struct bfa_lport_aen_data_s     lport;
+       struct bfa_rport_aen_data_s     rport;
+       struct bfa_itnim_aen_data_s     itnim;
+       struct bfa_audit_aen_data_s     audit;
+       struct bfa_ioc_aen_data_s       ioc;
+};
+
+#define BFA_AEN_MAX_ENTRY      512
+
+struct bfa_aen_entry_s {
+       struct list_head        qe;
+       enum bfa_aen_category   aen_category;
+       u32                     aen_type;
+       union bfa_aen_data_u    aen_data;
+       struct timeval          aen_tv;
+       u32                     seq_num;
+       u32                     bfad_num;
+};
+
 #endif /* __BFA_DEFS_SVC_H__ */
index 8d0b88f..50b6a1c 100644 (file)
@@ -56,6 +56,161 @@ struct scsi_cdb_s {
 
 #define SCSI_MAX_ALLOC_LEN      0xFF    /* maximum allocarion length */
 
+#define SCSI_SENSE_CUR_ERR     0x70
+#define SCSI_SENSE_DEF_ERR     0x71
+
+/*
+ * SCSI additional sense codes
+ */
+#define SCSI_ASC_LUN_NOT_READY         0x04
+#define SCSI_ASC_LUN_NOT_SUPPORTED     0x25
+#define SCSI_ASC_TOCC                  0x3F
+
+/*
+ * SCSI additional sense code qualifiers
+ */
+#define SCSI_ASCQ_MAN_INTR_REQ         0x03    /* manual intervention req */
+#define SCSI_ASCQ_RL_DATA_CHANGED      0x0E    /* report luns data changed */
+
+/*
+ * Methods of reporting informational exceptions
+ */
+#define SCSI_MP_IEC_UNIT_ATTN          0x2     /* generate unit attention */
+
+struct scsi_report_luns_data_s {
+       u32             lun_list_length;        /* length of LUN list length */
+       u32             reserved;
+       struct scsi_lun lun[1];                 /* first LUN in lun list */
+};
+
+struct scsi_inquiry_vendor_s {
+       u8      vendor_id[8];
+};
+
+struct scsi_inquiry_prodid_s {
+       u8      product_id[16];
+};
+
+struct scsi_inquiry_prodrev_s {
+       u8      product_rev[4];
+};
+
+struct scsi_inquiry_data_s {
+#ifdef __BIG_ENDIAN
+       u8              peripheral_qual:3;      /* peripheral qualifier */
+       u8              device_type:5;          /* peripheral device type */
+       u8              rmb:1;                  /* removable medium bit */
+       u8              device_type_mod:7;      /* device type modifier */
+       u8              version;
+       u8              aenc:1;         /* async evt notification capability */
+       u8              trm_iop:1;      /* terminate I/O process */
+       u8              norm_aca:1;     /* normal ACA supported */
+       u8              hi_support:1;   /* SCSI-3: supports REPORT LUNS */
+       u8              rsp_data_format:4;
+       u8              additional_len;
+       u8              sccs:1;
+       u8              reserved1:7;
+       u8              reserved2:1;
+       u8              enc_serv:1;     /* enclosure service component */
+       u8              reserved3:1;
+       u8              multi_port:1;   /* multi-port device */
+       u8              m_chngr:1;      /* device in medium transport element */
+       u8              ack_req_q:1;    /* SIP specific bit */
+       u8              addr32:1;       /* SIP specific bit */
+       u8              addr16:1;       /* SIP specific bit */
+       u8              rel_adr:1;      /* relative address */
+       u8              w_bus32:1;
+       u8              w_bus16:1;
+       u8              synchronous:1;
+       u8              linked_commands:1;
+       u8              trans_dis:1;
+       u8              cmd_queue:1;    /* command queueing supported */
+       u8              soft_reset:1;   /* soft reset alternative (VS) */
+#else
+       u8              device_type:5;  /* peripheral device type */
+       u8              peripheral_qual:3; /* peripheral qualifier */
+       u8              device_type_mod:7; /* device type modifier */
+       u8              rmb:1;          /* removable medium bit */
+       u8              version;
+       u8              rsp_data_format:4;
+       u8              hi_support:1;   /* SCSI-3: supports REPORT LUNS */
+       u8              norm_aca:1;     /* normal ACA supported */
+       u8              terminate_iop:1;/* terminate I/O process */
+       u8              aenc:1;         /* async evt notification capability */
+       u8              additional_len;
+       u8              reserved1:7;
+       u8              sccs:1;
+       u8              addr16:1;       /* SIP specific bit */
+       u8              addr32:1;       /* SIP specific bit */
+       u8              ack_req_q:1;    /* SIP specific bit */
+       u8              m_chngr:1;      /* device in medium transport element */
+       u8              multi_port:1;   /* multi-port device */
+       u8              reserved3:1;    /* TBD - Vendor Specific */
+       u8              enc_serv:1;     /* enclosure service component */
+       u8              reserved2:1;
+       u8              soft_seset:1;   /* soft reset alternative (VS) */
+       u8              cmd_queue:1;    /* command queueing supported */
+       u8              trans_dis:1;
+       u8              linked_commands:1;
+       u8              synchronous:1;
+       u8              w_bus16:1;
+       u8              w_bus32:1;
+       u8              rel_adr:1;      /* relative address */
+#endif
+       struct scsi_inquiry_vendor_s    vendor_id;
+       struct scsi_inquiry_prodid_s    product_id;
+       struct scsi_inquiry_prodrev_s   product_rev;
+       u8              vendor_specific[20];
+       u8              reserved4[40];
+};
+
+/*
+ *     SCSI sense data format
+ */
+struct scsi_sense_s {
+#ifdef __BIG_ENDIAN
+       u8              valid:1;
+       u8              rsp_code:7;
+#else
+       u8              rsp_code:7;
+       u8              valid:1;
+#endif
+       u8              seg_num;
+#ifdef __BIG_ENDIAN
+       u8              file_mark:1;
+       u8              eom:1;          /* end of media */
+       u8              ili:1;          /* incorrect length indicator */
+       u8              reserved:1;
+       u8              sense_key:4;
+#else
+       u8              sense_key:4;
+       u8              reserved:1;
+       u8              ili:1;          /* incorrect length indicator */
+       u8              eom:1;          /* end of media */
+       u8              file_mark:1;
+#endif
+       u8              information[4]; /* device-type or cmd specific info */
+       u8              add_sense_length; /* additional sense length */
+       u8              command_info[4];/* command specific information */
+       u8              asc;            /* additional sense code */
+       u8              ascq;           /* additional sense code qualifier */
+       u8              fru_code;       /* field replaceable unit code */
+#ifdef __BIG_ENDIAN
+       u8              sksv:1;         /* sense key specific valid */
+       u8              c_d:1;          /* command/data bit */
+       u8              res1:2;
+       u8              bpv:1;          /* bit pointer valid */
+       u8              bpointer:3;     /* bit pointer */
+#else
+       u8              bpointer:3;     /* bit pointer */
+       u8              bpv:1;          /* bit pointer valid */
+       u8              res1:2;
+       u8              c_d:1;          /* command/data bit */
+       u8              sksv:1;         /* sense key specific valid */
+#endif
+       u8              fpointer[2];    /* field pointer */
+};
+
 /*
  * Fibre Channel Header Structure (FCHS) definition
  */
index a4e7951..e07bd47 100644 (file)
@@ -24,6 +24,9 @@ BFA_TRC_FILE(HAL, FCPIM);
  *  BFA ITNIM Related definitions
  */
 static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
+static bfa_boolean_t bfa_ioim_lm_proc_rpl_data(struct bfa_ioim_s *ioim);
+static bfa_boolean_t bfa_ioim_lm_proc_inq_data(struct bfa_ioim_s *ioim);
+static void bfa_ioim_lm_init(struct bfa_s *bfa);
 
 #define BFA_ITNIM_FROM_TAG(_fcpim, _tag)                                \
        (((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1))))
@@ -57,6 +60,14 @@ static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
        }                                                               \
 } while (0)
 
+#define bfa_ioim_rp_wwn(__ioim)                                                \
+       (((struct bfa_fcs_rport_s *)                                    \
+        (__ioim)->itnim->rport->rport_drv)->pwwn)
+
+#define bfa_ioim_lp_wwn(__ioim)                                                \
+       ((BFA_LPS_FROM_TAG(BFA_LPS_MOD((__ioim)->bfa),                  \
+       (__ioim)->itnim->rport->rport_info.lp_tag))->pwwn)              \
+
 #define bfa_itnim_sler_cb(__itnim) do {                                        \
        if ((__itnim)->bfa->fcs)                                        \
                bfa_cb_itnim_sler((__itnim)->ditn);      \
@@ -66,6 +77,18 @@ static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
        }                                                               \
 } while (0)
 
+enum bfa_ioim_lm_status {
+       BFA_IOIM_LM_PRESENT = 1,
+       BFA_IOIM_LM_LUN_NOT_SUP = 2,
+       BFA_IOIM_LM_RPL_DATA_CHANGED = 3,
+       BFA_IOIM_LM_LUN_NOT_RDY = 4,
+};
+
+enum bfa_ioim_lm_ua_status {
+       BFA_IOIM_LM_UA_RESET = 0,
+       BFA_IOIM_LM_UA_SET = 1,
+};
+
 /*
  *  itnim state machine event
  */
@@ -122,6 +145,9 @@ enum bfa_ioim_event {
        BFA_IOIM_SM_TMDONE      = 16,   /*  IO cleanup from tskim */
        BFA_IOIM_SM_HWFAIL      = 17,   /*  IOC h/w failure event */
        BFA_IOIM_SM_IOTOV       = 18,   /*  ITN offline TOV */
+       BFA_IOIM_SM_LM_LUN_NOT_SUP = 19,/*  lunmask lun not supported */
+       BFA_IOIM_SM_LM_RPL_DC = 20,     /*  lunmask report-lun data changed */
+       BFA_IOIM_SM_LM_LUN_NOT_RDY = 21,/*  lunmask lun not ready */
 };
 
 
@@ -219,6 +245,9 @@ static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
 static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
 static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
 static bfa_boolean_t    bfa_ioim_is_abortable(struct bfa_ioim_s *ioim);
+static void __bfa_cb_ioim_lm_lun_not_sup(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_lm_rpl_dc(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_lm_lun_not_rdy(void *cbarg, bfa_boolean_t complete);
 
 /*
  * forward declaration of BFA IO state machine
@@ -416,6 +445,12 @@ bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
        bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
        bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
        bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
+       bfa_fcpim_add_iostats(lstats, rstats, lm_lun_across_sg);
+       bfa_fcpim_add_iostats(lstats, rstats, lm_lun_not_sup);
+       bfa_fcpim_add_iostats(lstats, rstats, lm_rpl_data_changed);
+       bfa_fcpim_add_iostats(lstats, rstats, lm_wire_residue_changed);
+       bfa_fcpim_add_iostats(lstats, rstats, lm_small_buf_addresidue);
+       bfa_fcpim_add_iostats(lstats, rstats, lm_lun_not_rdy);
 }
 
 bfa_status_t
@@ -437,6 +472,59 @@ bfa_fcpim_port_iostats(struct bfa_s *bfa,
        return BFA_STATUS_OK;
 }
 
+void
+bfa_ioim_profile_comp(struct bfa_ioim_s *ioim)
+{
+       struct bfa_itnim_latency_s *io_lat =
+                       &(ioim->itnim->ioprofile.io_latency);
+       u32 val, idx;
+
+       val = (u32)(jiffies - ioim->start_time);
+       idx = bfa_ioim_get_index(scsi_bufflen((struct scsi_cmnd *)ioim->dio));
+       bfa_itnim_ioprofile_update(ioim->itnim, idx);
+
+       io_lat->count[idx]++;
+       io_lat->min[idx] = (io_lat->min[idx] < val) ? io_lat->min[idx] : val;
+       io_lat->max[idx] = (io_lat->max[idx] > val) ? io_lat->max[idx] : val;
+       io_lat->avg[idx] += val;
+}
+
+void
+bfa_ioim_profile_start(struct bfa_ioim_s *ioim)
+{
+       ioim->start_time = jiffies;
+}
+
+bfa_status_t
+bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time)
+{
+       struct bfa_itnim_s *itnim;
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
+       struct list_head *qe, *qen;
+
+       /* accumulate IO stats from itnim */
+       list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+               itnim = (struct bfa_itnim_s *) qe;
+               bfa_itnim_clear_stats(itnim);
+       }
+       fcpim->io_profile = BFA_TRUE;
+       fcpim->io_profile_start_time = time;
+       fcpim->profile_comp = bfa_ioim_profile_comp;
+       fcpim->profile_start = bfa_ioim_profile_start;
+       return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcpim_profile_off(struct bfa_s *bfa)
+{
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
+       fcpim->io_profile = BFA_FALSE;
+       fcpim->io_profile_start_time = 0;
+       fcpim->profile_comp = NULL;
+       fcpim->profile_start = NULL;
+       return BFA_STATUS_OK;
+}
+
 u16
 bfa_fcpim_qdepth_get(struct bfa_s *bfa)
 {
@@ -1401,6 +1489,26 @@ bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
                 bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable));
 }
 
+#define bfa_io_lat_clock_res_div       HZ
+#define bfa_io_lat_clock_res_mul       1000
+bfa_status_t
+bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
+                       struct bfa_itnim_ioprofile_s *ioprofile)
+{
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(itnim->bfa);
+       if (!fcpim->io_profile)
+               return BFA_STATUS_IOPROFILE_OFF;
+
+       itnim->ioprofile.index = BFA_IOBUCKET_MAX;
+       itnim->ioprofile.io_profile_start_time =
+                               bfa_io_profile_start_time(itnim->bfa);
+       itnim->ioprofile.clock_res_mul = bfa_io_lat_clock_res_mul;
+       itnim->ioprofile.clock_res_div = bfa_io_lat_clock_res_div;
+       *ioprofile = itnim->ioprofile;
+
+       return BFA_STATUS_OK;
+}
+
 void
 bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
 {
@@ -1469,7 +1577,28 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
                bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
                WARN_ON(!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
                bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
-                               __bfa_cb_ioim_abort, ioim);
+                       __bfa_cb_ioim_abort, ioim);
+               break;
+
+       case BFA_IOIM_SM_LM_LUN_NOT_SUP:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_ioim_move_to_comp_q(ioim);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+                       __bfa_cb_ioim_lm_lun_not_sup, ioim);
+               break;
+
+       case BFA_IOIM_SM_LM_RPL_DC:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_ioim_move_to_comp_q(ioim);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+                               __bfa_cb_ioim_lm_rpl_dc, ioim);
+               break;
+
+       case BFA_IOIM_SM_LM_LUN_NOT_RDY:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_ioim_move_to_comp_q(ioim);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+                       __bfa_cb_ioim_lm_lun_not_rdy, ioim);
                break;
 
        default:
@@ -2009,6 +2138,264 @@ bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
        }
 }
 
+/*
+ * This is called from bfa_fcpim_start after the bfa_init() with flash read
+ * is complete by driver. now invalidate the stale content of lun mask
+ * like unit attention, rp tag and lp tag.
+ */
+static void
+bfa_ioim_lm_init(struct bfa_s *bfa)
+{
+       struct bfa_lun_mask_s *lunm_list;
+       int     i;
+
+       if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
+               return;
+
+       lunm_list = bfa_get_lun_mask_list(bfa);
+       for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
+               lunm_list[i].ua = BFA_IOIM_LM_UA_RESET;
+               lunm_list[i].lp_tag = BFA_LP_TAG_INVALID;
+               lunm_list[i].rp_tag = BFA_RPORT_TAG_INVALID;
+       }
+}
+
+/*
+ * Validate LUN for LUN masking
+ */
+static enum bfa_ioim_lm_status
+bfa_ioim_lm_check(struct bfa_ioim_s *ioim, struct bfa_lps_s *lps,
+               struct bfa_rport_s *rp, struct scsi_lun lun)
+{
+       u8 i;
+       struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa);
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
+       struct scsi_cdb_s *cdb = (struct scsi_cdb_s *)cmnd->cmnd;
+
+       if ((cdb->scsi_cdb[0] == REPORT_LUNS) &&
+           (scsilun_to_int((struct scsi_lun *)&lun) == 0)) {
+               ioim->proc_rsp_data = bfa_ioim_lm_proc_rpl_data;
+               return BFA_IOIM_LM_PRESENT;
+       }
+
+       for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
+
+               if (lun_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)
+                       continue;
+
+               if ((scsilun_to_int((struct scsi_lun *)&lun_list[i].lun) ==
+                   scsilun_to_int((struct scsi_lun *)&lun))
+                   && (rp->rport_tag == lun_list[i].rp_tag)
+                   && ((u8)ioim->itnim->rport->rport_info.lp_tag ==
+                                               lun_list[i].lp_tag)) {
+                       bfa_trc(ioim->bfa, lun_list[i].rp_tag);
+                       bfa_trc(ioim->bfa, lun_list[i].lp_tag);
+                       bfa_trc(ioim->bfa, scsilun_to_int(
+                               (struct scsi_lun *)&lun_list[i].lun));
+
+                       if ((lun_list[i].ua == BFA_IOIM_LM_UA_SET) &&
+                           ((cdb->scsi_cdb[0] != INQUIRY) ||
+                           (cdb->scsi_cdb[0] != REPORT_LUNS))) {
+                               lun_list[i].ua = BFA_IOIM_LM_UA_RESET;
+                               return BFA_IOIM_LM_RPL_DATA_CHANGED;
+                       }
+
+                       if (cdb->scsi_cdb[0] == REPORT_LUNS)
+                               ioim->proc_rsp_data = bfa_ioim_lm_proc_rpl_data;
+
+                       return BFA_IOIM_LM_PRESENT;
+               }
+       }
+
+       if ((cdb->scsi_cdb[0] == INQUIRY) &&
+           (scsilun_to_int((struct scsi_lun *)&lun) == 0)) {
+               ioim->proc_rsp_data = bfa_ioim_lm_proc_inq_data;
+               return BFA_IOIM_LM_PRESENT;
+       }
+
+       if (cdb->scsi_cdb[0] == TEST_UNIT_READY)
+               return BFA_IOIM_LM_LUN_NOT_RDY;
+
+       return BFA_IOIM_LM_LUN_NOT_SUP;
+}
+
+static bfa_boolean_t
+bfa_ioim_lm_proc_rsp_data_dummy(struct bfa_ioim_s *ioim)
+{
+       return BFA_TRUE;
+}
+
+static void
+bfa_ioim_lm_fetch_lun(struct bfa_ioim_s *ioim, u8 *rl_data, int offset,
+               int buf_lun_cnt)
+{
+       struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa);
+       struct scsi_lun *lun_data = (struct scsi_lun *)(rl_data + offset);
+       struct scsi_lun lun;
+       int i, j;
+
+       bfa_trc(ioim->bfa, buf_lun_cnt);
+       for (j = 0; j < buf_lun_cnt; j++) {
+               lun = *((struct scsi_lun *)(lun_data + j));
+               for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
+                       if (lun_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)
+                               continue;
+                       if ((lun_list[i].rp_wwn == bfa_ioim_rp_wwn(ioim)) &&
+                           (lun_list[i].lp_wwn == bfa_ioim_lp_wwn(ioim)) &&
+                           (scsilun_to_int((struct scsi_lun *)&lun_list[i].lun)
+                               == scsilun_to_int((struct scsi_lun *)&lun))) {
+                               lun_list[i].state = BFA_IOIM_LUN_MASK_FETCHED;
+                               break;
+                       }
+               } /* next lun in mask DB */
+       } /* next lun in buf */
+}
+
+static int
+bfa_ioim_lm_update_lun_sg(struct bfa_ioim_s *ioim, u32 *pgdlen,
+               struct scsi_report_luns_data_s *rl)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
+       struct scatterlist *sg = scsi_sglist(cmnd);
+       struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa);
+       struct scsi_lun *prev_rl_data = NULL, *base_rl_data;
+       int i, j, sgeid, lun_fetched_cnt = 0, prev_sg_len = 0, base_count;
+       int lun_across_sg_bytes, bytes_from_next_buf;
+       u64     last_lun, temp_last_lun;
+
+       /* fetch luns from the first sg element */
+       bfa_ioim_lm_fetch_lun(ioim, (u8 *)(rl->lun), 0,
+                       (sg_dma_len(sg) / sizeof(struct scsi_lun)) - 1);
+
+       /* fetch luns from multiple sg elements */
+       scsi_for_each_sg(cmnd, sg, scsi_sg_count(cmnd), sgeid) {
+               if (sgeid == 0) {
+                       prev_sg_len = sg_dma_len(sg);
+                       prev_rl_data = (struct scsi_lun *)
+                                       phys_to_virt(sg_dma_address(sg));
+                       continue;
+               }
+
+               /* if the buf is having more data */
+               lun_across_sg_bytes = prev_sg_len % sizeof(struct scsi_lun);
+               if (lun_across_sg_bytes) {
+                       bfa_trc(ioim->bfa, lun_across_sg_bytes);
+                       bfa_stats(ioim->itnim, lm_lun_across_sg);
+                       bytes_from_next_buf = sizeof(struct scsi_lun) -
+                                             lun_across_sg_bytes;
+
+                       /* from next buf take higher bytes */
+                       temp_last_lun = *((u64 *)
+                                         phys_to_virt(sg_dma_address(sg)));
+                       last_lun |= temp_last_lun >>
+                                   (lun_across_sg_bytes * BITS_PER_BYTE);
+
+                       /* from prev buf take higher bytes */
+                       temp_last_lun = *((u64 *)(prev_rl_data +
+                                         (prev_sg_len - lun_across_sg_bytes)));
+                       temp_last_lun >>= bytes_from_next_buf * BITS_PER_BYTE;
+                       last_lun = last_lun | (temp_last_lun <<
+                                  (bytes_from_next_buf * BITS_PER_BYTE));
+
+                       bfa_ioim_lm_fetch_lun(ioim, (u8 *)&last_lun, 0, 1);
+               } else
+                       bytes_from_next_buf = 0;
+
+               *pgdlen += sg_dma_len(sg);
+               prev_sg_len = sg_dma_len(sg);
+               prev_rl_data = (struct scsi_lun *)
+                               phys_to_virt(sg_dma_address(sg));
+               bfa_ioim_lm_fetch_lun(ioim, (u8 *)prev_rl_data,
+                               bytes_from_next_buf,
+                               sg_dma_len(sg) / sizeof(struct scsi_lun));
+       }
+
+       /* update the report luns data - based on fetched luns */
+       sg = scsi_sglist(cmnd);
+       base_rl_data = (struct scsi_lun *)rl->lun;
+       base_count = (sg_dma_len(sg) / sizeof(struct scsi_lun)) - 1;
+       for (i = 0, j = 0; i < MAX_LUN_MASK_CFG; i++) {
+               if (lun_list[i].state == BFA_IOIM_LUN_MASK_FETCHED) {
+                       base_rl_data[j] = lun_list[i].lun;
+                       lun_list[i].state = BFA_IOIM_LUN_MASK_ACTIVE;
+                       j++;
+                       lun_fetched_cnt++;
+               }
+
+               if (j > base_count) {
+                       j = 0;
+                       sg = sg_next(sg);
+                       base_rl_data = (struct scsi_lun *)
+                                       phys_to_virt(sg_dma_address(sg));
+                       base_count = sg_dma_len(sg) / sizeof(struct scsi_lun);
+               }
+       }
+
+       bfa_trc(ioim->bfa, lun_fetched_cnt);
+       return lun_fetched_cnt;
+}
+
+static bfa_boolean_t
+bfa_ioim_lm_proc_inq_data(struct bfa_ioim_s *ioim)
+{
+       struct scsi_inquiry_data_s *inq;
+       struct scatterlist *sg = scsi_sglist((struct scsi_cmnd *)ioim->dio);
+
+       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
+       inq = (struct scsi_inquiry_data_s *)phys_to_virt(sg_dma_address(sg));
+
+       bfa_trc(ioim->bfa, inq->device_type);
+       inq->peripheral_qual = SCSI_INQ_PQ_NOT_CON;
+       return 0;
+}
+
+static bfa_boolean_t
+bfa_ioim_lm_proc_rpl_data(struct bfa_ioim_s *ioim)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
+       struct scatterlist *sg = scsi_sglist(cmnd);
+       struct bfi_ioim_rsp_s *m;
+       struct scsi_report_luns_data_s *rl = NULL;
+       int lun_count = 0, lun_fetched_cnt = 0;
+       u32 residue, pgdlen = 0;
+
+       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
+       if (bfa_get_lun_mask_status(ioim->bfa) != BFA_LUNMASK_ENABLED)
+               return BFA_TRUE;
+
+       m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
+       if (m->scsi_status == SCSI_STATUS_CHECK_CONDITION)
+               return BFA_TRUE;
+
+       pgdlen = sg_dma_len(sg);
+       bfa_trc(ioim->bfa, pgdlen);
+       rl = (struct scsi_report_luns_data_s *)phys_to_virt(sg_dma_address(sg));
+       lun_count = cpu_to_be32(rl->lun_list_length) / sizeof(struct scsi_lun);
+       lun_fetched_cnt = bfa_ioim_lm_update_lun_sg(ioim, &pgdlen, rl);
+
+       if (lun_count == lun_fetched_cnt)
+               return BFA_TRUE;
+
+       bfa_trc(ioim->bfa, lun_count);
+       bfa_trc(ioim->bfa, lun_fetched_cnt);
+       bfa_trc(ioim->bfa, be32_to_cpu(rl->lun_list_length));
+
+       if (be32_to_cpu(rl->lun_list_length) <= pgdlen)
+               rl->lun_list_length = be32_to_cpu(lun_fetched_cnt) *
+                                     sizeof(struct scsi_lun);
+       else
+               bfa_stats(ioim->itnim, lm_small_buf_addresidue);
+
+       bfa_trc(ioim->bfa, be32_to_cpu(rl->lun_list_length));
+       bfa_trc(ioim->bfa, be32_to_cpu(m->residue));
+
+       residue = be32_to_cpu(m->residue);
+       residue += (lun_count - lun_fetched_cnt) * sizeof(struct scsi_lun);
+       bfa_stats(ioim->itnim, lm_wire_residue_changed);
+       m->residue = be32_to_cpu(residue);
+       bfa_trc(ioim->bfa, ioim->nsges);
+       return BFA_FALSE;
+}
 
 static void
 __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
@@ -2067,6 +2454,299 @@ __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
                          m->scsi_status, sns_len, snsinfo, residue);
 }
 
+static void
+__bfa_cb_ioim_lm_lun_not_sup(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_ioim_s *ioim = cbarg;
+       int sns_len = 0xD;
+       u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio);
+       struct scsi_sense_s *snsinfo;
+
+       if (!complete) {
+               bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+               return;
+       }
+
+       snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(
+                                       ioim->fcpim->fcp, ioim->iotag);
+       snsinfo->rsp_code = SCSI_SENSE_CUR_ERR;
+       snsinfo->add_sense_length = 0xa;
+       snsinfo->asc = SCSI_ASC_LUN_NOT_SUPPORTED;
+       snsinfo->sense_key = ILLEGAL_REQUEST;
+       bfa_trc(ioim->bfa, residue);
+       bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK,
+                       SCSI_STATUS_CHECK_CONDITION, sns_len,
+                       (u8 *)snsinfo, residue);
+}
+
+static void
+__bfa_cb_ioim_lm_rpl_dc(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_ioim_s *ioim = cbarg;
+       int sns_len = 0xD;
+       u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio);
+       struct scsi_sense_s *snsinfo;
+
+       if (!complete) {
+               bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+               return;
+       }
+
+       snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(ioim->fcpim->fcp,
+                                                      ioim->iotag);
+       snsinfo->rsp_code = SCSI_SENSE_CUR_ERR;
+       snsinfo->sense_key = SCSI_MP_IEC_UNIT_ATTN;
+       snsinfo->asc = SCSI_ASC_TOCC;
+       snsinfo->add_sense_length = 0x6;
+       snsinfo->ascq = SCSI_ASCQ_RL_DATA_CHANGED;
+       bfa_trc(ioim->bfa, residue);
+       bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK,
+                       SCSI_STATUS_CHECK_CONDITION, sns_len,
+                       (u8 *)snsinfo, residue);
+}
+
+static void
+__bfa_cb_ioim_lm_lun_not_rdy(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_ioim_s *ioim = cbarg;
+       int sns_len = 0xD;
+       u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio);
+       struct scsi_sense_s *snsinfo;
+
+       if (!complete) {
+               bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+               return;
+       }
+
+       snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(
+                                       ioim->fcpim->fcp, ioim->iotag);
+       snsinfo->rsp_code = SCSI_SENSE_CUR_ERR;
+       snsinfo->add_sense_length = 0xa;
+       snsinfo->sense_key = NOT_READY;
+       snsinfo->asc = SCSI_ASC_LUN_NOT_READY;
+       snsinfo->ascq = SCSI_ASCQ_MAN_INTR_REQ;
+       bfa_trc(ioim->bfa, residue);
+       bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK,
+                       SCSI_STATUS_CHECK_CONDITION, sns_len,
+                       (u8 *)snsinfo, residue);
+}
+
+void
+bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, wwn_t rp_wwn,
+                       u16 rp_tag, u8 lp_tag)
+{
+       struct bfa_lun_mask_s *lun_list;
+       u8      i;
+
+       if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
+               return;
+
+       lun_list = bfa_get_lun_mask_list(bfa);
+       for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
+               if (lun_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE) {
+                       if ((lun_list[i].lp_wwn == lp_wwn) &&
+                           (lun_list[i].rp_wwn == rp_wwn)) {
+                               lun_list[i].rp_tag = rp_tag;
+                               lun_list[i].lp_tag = lp_tag;
+                       }
+               }
+       }
+}
+
+/*
+ * set UA for all active luns in LM DB
+ */
+static void
+bfa_ioim_lm_set_ua(struct bfa_s *bfa)
+{
+       struct bfa_lun_mask_s   *lunm_list;
+       int     i;
+
+       lunm_list = bfa_get_lun_mask_list(bfa);
+       for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
+               if (lunm_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)
+                       continue;
+               lunm_list[i].ua = BFA_IOIM_LM_UA_SET;
+       }
+}
+
+bfa_status_t
+bfa_fcpim_lunmask_update(struct bfa_s *bfa, u32 update)
+{
+       struct bfa_lunmask_cfg_s        *lun_mask;
+
+       bfa_trc(bfa, bfa_get_lun_mask_status(bfa));
+       if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
+               return BFA_STATUS_FAILED;
+
+       if (bfa_get_lun_mask_status(bfa) == update)
+               return BFA_STATUS_NO_CHANGE;
+
+       lun_mask = bfa_get_lun_mask(bfa);
+       lun_mask->status = update;
+
+       if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED)
+               bfa_ioim_lm_set_ua(bfa);
+
+       return  bfa_dconf_update(bfa);
+}
+
+bfa_status_t
+bfa_fcpim_lunmask_clear(struct bfa_s *bfa)
+{
+       int i;
+       struct bfa_lun_mask_s   *lunm_list;
+
+       bfa_trc(bfa, bfa_get_lun_mask_status(bfa));
+       if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
+               return BFA_STATUS_FAILED;
+
+       lunm_list = bfa_get_lun_mask_list(bfa);
+       for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
+               if (lunm_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE) {
+                       if (lunm_list[i].rp_tag != BFA_RPORT_TAG_INVALID)
+                               bfa_rport_unset_lunmask(bfa,
+                                 BFA_RPORT_FROM_TAG(bfa, lunm_list[i].rp_tag));
+               }
+       }
+
+       memset(lunm_list, 0, sizeof(struct bfa_lun_mask_s) * MAX_LUN_MASK_CFG);
+       return bfa_dconf_update(bfa);
+}
+
+bfa_status_t
+bfa_fcpim_lunmask_query(struct bfa_s *bfa, void *buf)
+{
+       struct bfa_lunmask_cfg_s *lun_mask;
+
+       bfa_trc(bfa, bfa_get_lun_mask_status(bfa));
+       if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
+               return BFA_STATUS_FAILED;
+
+       lun_mask = bfa_get_lun_mask(bfa);
+       memcpy(buf, lun_mask, sizeof(struct bfa_lunmask_cfg_s));
+       return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn,
+                     wwn_t rpwwn, struct scsi_lun lun)
+{
+       struct bfa_lun_mask_s *lunm_list;
+       struct bfa_rport_s *rp = NULL;
+       int i, free_index = MAX_LUN_MASK_CFG + 1;
+       struct bfa_fcs_lport_s *port = NULL;
+       struct bfa_fcs_rport_s *rp_fcs;
+
+       bfa_trc(bfa, bfa_get_lun_mask_status(bfa));
+       if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
+               return BFA_STATUS_FAILED;
+
+       port = bfa_fcs_lookup_port(&((struct bfad_s *)bfa->bfad)->bfa_fcs,
+                                  vf_id, *pwwn);
+       if (port) {
+               *pwwn = port->port_cfg.pwwn;
+               rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
+               rp = rp_fcs->bfa_rport;
+       }
+
+       lunm_list = bfa_get_lun_mask_list(bfa);
+       /* if entry exists */
+       for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
+               if (lunm_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)
+                       free_index = i;
+               if ((lunm_list[i].lp_wwn == *pwwn) &&
+                   (lunm_list[i].rp_wwn == rpwwn) &&
+                   (scsilun_to_int((struct scsi_lun *)&lunm_list[i].lun) ==
+                    scsilun_to_int((struct scsi_lun *)&lun)))
+                       return  BFA_STATUS_ENTRY_EXISTS;
+       }
+
+       if (free_index > MAX_LUN_MASK_CFG)
+               return BFA_STATUS_MAX_ENTRY_REACHED;
+
+       if (rp) {
+               lunm_list[free_index].lp_tag = bfa_lps_get_tag_from_pid(bfa,
+                                                  rp->rport_info.local_pid);
+               lunm_list[free_index].rp_tag = rp->rport_tag;
+       } else {
+               lunm_list[free_index].lp_tag = BFA_LP_TAG_INVALID;
+               lunm_list[free_index].rp_tag = BFA_RPORT_TAG_INVALID;
+       }
+
+       lunm_list[free_index].lp_wwn = *pwwn;
+       lunm_list[free_index].rp_wwn = rpwwn;
+       lunm_list[free_index].lun = lun;
+       lunm_list[free_index].state = BFA_IOIM_LUN_MASK_ACTIVE;
+
+       /* set for all luns in this rp */
+       for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
+               if ((lunm_list[i].lp_wwn == *pwwn) &&
+                   (lunm_list[i].rp_wwn == rpwwn))
+                       lunm_list[i].ua = BFA_IOIM_LM_UA_SET;
+       }
+
+       return bfa_dconf_update(bfa);
+}
+
+bfa_status_t
+bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn,
+                        wwn_t rpwwn, struct scsi_lun lun)
+{
+       struct bfa_lun_mask_s   *lunm_list;
+       struct bfa_rport_s      *rp = NULL;
+       struct bfa_fcs_lport_s *port = NULL;
+       struct bfa_fcs_rport_s *rp_fcs;
+       int     i;
+
+       /* in min cfg lunm_list could be NULL but  no commands should run. */
+       if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG)
+               return BFA_STATUS_FAILED;
+
+       bfa_trc(bfa, bfa_get_lun_mask_status(bfa));
+       bfa_trc(bfa, *pwwn);
+       bfa_trc(bfa, rpwwn);
+       bfa_trc(bfa, scsilun_to_int((struct scsi_lun *)&lun));
+
+       if (*pwwn == 0) {
+               port = bfa_fcs_lookup_port(
+                               &((struct bfad_s *)bfa->bfad)->bfa_fcs,
+                               vf_id, *pwwn);
+               if (port) {
+                       *pwwn = port->port_cfg.pwwn;
+                       rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
+                       rp = rp_fcs->bfa_rport;
+               }
+       }
+
+       lunm_list = bfa_get_lun_mask_list(bfa);
+       for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
+               if ((lunm_list[i].lp_wwn == *pwwn) &&
+                   (lunm_list[i].rp_wwn == rpwwn) &&
+                   (scsilun_to_int((struct scsi_lun *)&lunm_list[i].lun) ==
+                    scsilun_to_int((struct scsi_lun *)&lun))) {
+                       lunm_list[i].lp_wwn = 0;
+                       lunm_list[i].rp_wwn = 0;
+                       int_to_scsilun(0, &lunm_list[i].lun);
+                       lunm_list[i].state = BFA_IOIM_LUN_MASK_INACTIVE;
+                       if (lunm_list[i].rp_tag != BFA_RPORT_TAG_INVALID) {
+                               lunm_list[i].rp_tag = BFA_RPORT_TAG_INVALID;
+                               lunm_list[i].lp_tag = BFA_LP_TAG_INVALID;
+                       }
+                       return bfa_dconf_update(bfa);
+               }
+       }
+
+       /* set for all luns in this rp */
+       for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
+               if ((lunm_list[i].lp_wwn == *pwwn) &&
+                   (lunm_list[i].rp_wwn == rpwwn))
+                       lunm_list[i].ua = BFA_IOIM_LM_UA_SET;
+       }
+
+       return BFA_STATUS_ENTRY_NOT_EXISTS;
+}
+
 static void
 __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
 {
@@ -2077,6 +2757,7 @@ __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
                return;
        }
 
+       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
        bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
                          0, 0, NULL, 0);
 }
@@ -2092,6 +2773,7 @@ __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
                return;
        }
 
+       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
        bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
                          0, 0, NULL, 0);
 }
@@ -2106,6 +2788,7 @@ __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
                return;
        }
 
+       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
        bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
 }
 
@@ -2449,6 +3132,7 @@ bfa_ioim_attach(struct bfa_fcpim_s *fcpim)
                ioim->bfa     = fcpim->bfa;
                ioim->fcpim   = fcpim;
                ioim->iosp    = iosp;
+               ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
                INIT_LIST_HEAD(&ioim->sgpg_q);
                bfa_reqq_winit(&ioim->iosp->reqq_wait,
                                   bfa_ioim_qresume, ioim);
@@ -2486,6 +3170,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
                        evt = BFA_IOIM_SM_DONE;
                else
                        evt = BFA_IOIM_SM_COMP;
+               ioim->proc_rsp_data(ioim);
                break;
 
        case BFI_IOIM_STS_TIMEDOUT:
@@ -2521,6 +3206,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
                if (rsp->abort_tag != ioim->abort_tag) {
                        bfa_trc(ioim->bfa, rsp->abort_tag);
                        bfa_trc(ioim->bfa, ioim->abort_tag);
+                       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
                        return;
                }
 
@@ -2539,6 +3225,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
                WARN_ON(1);
        }
 
+       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
        bfa_sm_send_event(ioim, evt);
 }
 
@@ -2556,7 +3243,16 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
        WARN_ON(BFA_IOIM_TAG_2_ID(ioim->iotag) != iotag);
 
        bfa_ioim_cb_profile_comp(fcpim, ioim);
-       bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
+
+       if (bfa_get_lun_mask_status(bfa) != BFA_LUNMASK_ENABLED)  {
+               bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
+               return;
+       }
+
+       if (ioim->proc_rsp_data(ioim) == BFA_TRUE)
+               bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
+       else
+               bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP);
 }
 
 /*
@@ -2668,6 +3364,35 @@ bfa_ioim_free(struct bfa_ioim_s *ioim)
 void
 bfa_ioim_start(struct bfa_ioim_s *ioim)
 {
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
+       struct bfa_lps_s        *lps;
+       enum bfa_ioim_lm_status status;
+       struct scsi_lun scsilun;
+
+       if (bfa_get_lun_mask_status(ioim->bfa) == BFA_LUNMASK_ENABLED) {
+               lps = BFA_IOIM_TO_LPS(ioim);
+               int_to_scsilun(cmnd->device->lun, &scsilun);
+               status = bfa_ioim_lm_check(ioim, lps,
+                               ioim->itnim->rport, scsilun);
+               if (status == BFA_IOIM_LM_LUN_NOT_RDY) {
+                       bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_LUN_NOT_RDY);
+                       bfa_stats(ioim->itnim, lm_lun_not_rdy);
+                       return;
+               }
+
+               if (status == BFA_IOIM_LM_LUN_NOT_SUP) {
+                       bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_LUN_NOT_SUP);
+                       bfa_stats(ioim->itnim, lm_lun_not_sup);
+                       return;
+               }
+
+               if (status == BFA_IOIM_LM_RPL_DATA_CHANGED) {
+                       bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_RPL_DC);
+                       bfa_stats(ioim->itnim, lm_rpl_data_changed);
+                       return;
+               }
+       }
+
        bfa_ioim_cb_profile_start(ioim->fcpim, ioim);
 
        /*
@@ -3411,6 +4136,13 @@ bfa_fcp_detach(struct bfa_s *bfa)
 static void
 bfa_fcp_start(struct bfa_s *bfa)
 {
+       struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+
+       /*
+        * bfa_init() with flash read is complete. now invalidate the stale
+        * content of lun mask like unit attention, rp tag and lp tag.
+        */
+       bfa_ioim_lm_init(fcp->bfa);
 }
 
 static void
index 57b695a..1080bcb 100644 (file)
@@ -79,14 +79,22 @@ bfa_ioim_get_index(u32 n) {
        if (n >= (1UL)<<22)
                return BFA_IOBUCKET_MAX - 1;
        n >>= 8;
-       if (n >= (1UL)<<16)
-               n >>= 16; pos += 16;
-       if (n >= 1 << 8)
-               n >>= 8; pos += 8;
-       if (n >= 1 << 4)
-               n >>= 4; pos += 4;
-       if (n >= 1 << 2)
-               n >>= 2; pos += 2;
+       if (n >= (1UL)<<16) {
+               n >>= 16;
+               pos += 16;
+       }
+       if (n >= 1 << 8) {
+               n >>= 8;
+               pos += 8;
+       }
+       if (n >= 1 << 4) {
+               n >>= 4;
+               pos += 4;
+       }
+       if (n >= 1 << 2) {
+               n >>= 2;
+               pos += 2;
+       }
        if (n >= 1 << 1)
                pos += 1;
 
@@ -102,6 +110,7 @@ struct bfad_ioim_s;
 struct bfad_tskim_s;
 
 typedef void    (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim);
+typedef bfa_boolean_t (*bfa_ioim_lm_proc_rsp_data_t) (struct bfa_ioim_s *ioim);
 
 struct bfa_fcpim_s {
        struct bfa_s            *bfa;
@@ -115,7 +124,7 @@ struct bfa_fcpim_s {
        u32                     path_tov;
        u16                     q_depth;
        u8                      reqq;           /*  Request queue to be used */
-       u8                      rsvd;
+       u8                      lun_masking_pending;
        struct list_head        itnim_q;        /*  queue of active itnim */
        struct list_head        ioim_resfree_q; /*  IOs waiting for f/w */
        struct list_head        ioim_comp_q;    /*  IO global comp Q    */
@@ -170,7 +179,9 @@ struct bfa_ioim_s {
        bfa_cb_cbfn_t           io_cbfn;        /*  IO completion handler */
        struct bfa_ioim_sp_s    *iosp;          /*  slow-path IO handling */
        u8                      reqq;           /*  Request queue for I/O */
+       u8                      mode;           /*  IO is passthrough or not */
        u64                     start_time;     /*  IO's Profile start val */
+       bfa_ioim_lm_proc_rsp_data_t proc_rsp_data; /* RSP data adjust */
 };
 
 struct bfa_ioim_sp_s {
@@ -250,6 +261,10 @@ struct bfa_itnim_s {
        (__ioim)->iotag |= k << BFA_IOIM_RETRY_TAG_OFFSET;              \
 } while (0)
 
+#define BFA_IOIM_TO_LPS(__ioim)                \
+       BFA_LPS_FROM_TAG(BFA_LPS_MOD(__ioim->bfa),      \
+               __ioim->itnim->rport->rport_info.lp_tag)
+
 static inline bfa_boolean_t
 bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim)
 {
@@ -297,6 +312,8 @@ bfa_status_t bfa_fcpim_port_iostats(struct bfa_s *bfa,
                        struct bfa_itnim_iostats_s *stats, u8 lp_tag);
 void bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *fcpim_stats,
                        struct bfa_itnim_iostats_s *itnim_stats);
+bfa_status_t bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time);
+bfa_status_t bfa_fcpim_profile_off(struct bfa_s *bfa);
 
 #define bfa_fcpim_ioredirect_enabled(__bfa)                            \
        (((struct bfa_fcpim_s *)(BFA_FCPIM(__bfa)))->ioredirect)
@@ -397,4 +414,14 @@ void bfa_tskim_start(struct bfa_tskim_s *tskim,
 void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
                        enum bfi_tskim_status tsk_status);
 
+void   bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn,
+                       wwn_t rp_wwn, u16 rp_tag, u8 lp_tag);
+bfa_status_t   bfa_fcpim_lunmask_update(struct bfa_s *bfa, u32 on_off);
+bfa_status_t   bfa_fcpim_lunmask_query(struct bfa_s *bfa, void *buf);
+bfa_status_t   bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id,
+                               wwn_t *pwwn, wwn_t rpwwn, struct scsi_lun lun);
+bfa_status_t   bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id,
+                               wwn_t *pwwn, wwn_t rpwwn, struct scsi_lun lun);
+bfa_status_t   bfa_fcpim_lunmask_clear(struct bfa_s *bfa);
+
 #endif /* __BFA_FCPIM_H__ */
index a9b22bc..eaac57e 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include "bfad_drv.h"
+#include "bfad_im.h"
 #include "bfa_fcs.h"
 #include "bfa_fcbuild.h"
 
@@ -1327,6 +1328,29 @@ bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
        bfa_trc(fabric->fcs, status);
 }
 
+
+/*
+ * Send AEN notification
+ */
+static void
+bfa_fcs_fabric_aen_post(struct bfa_fcs_lport_s *port,
+                       enum bfa_port_aen_event event)
+{
+       struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;
+       struct bfa_aen_entry_s  *aen_entry;
+
+       bfad_get_aen_entry(bfad, aen_entry);
+       if (!aen_entry)
+               return;
+
+       aen_entry->aen_data.port.pwwn = bfa_fcs_lport_get_pwwn(port);
+       aen_entry->aen_data.port.fwwn = bfa_fcs_lport_get_fabric_name(port);
+
+       /* Send the AEN notification */
+       bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
+                                 BFA_AEN_CAT_PORT, event);
+}
+
 /*
  *
  * @param[in] fabric - fabric
@@ -1358,6 +1382,8 @@ bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
                BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
                        "Base port WWN = %s Fabric WWN = %s\n",
                        pwwn_ptr, fwwn_ptr);
+               bfa_fcs_fabric_aen_post(&fabric->bport,
+                               BFA_PORT_AEN_FABRIC_NAME_CHANGE);
        }
 }
 
index a5f1faf..e75e07d 100644 (file)
@@ -675,6 +675,7 @@ struct bfa_fcs_s {
        struct bfa_fcs_fabric_s fabric; /*  base fabric state machine */
        struct bfa_fcs_stats_s  stats;  /*  FCS statistics */
        struct bfa_wc_s         wc;     /*  waiting counter */
+       int                     fcs_aen_seq;
 };
 
 /*
index 29b4108..9272840 100644 (file)
@@ -37,6 +37,8 @@ static void   bfa_fcs_itnim_prli_response(void *fcsarg,
                         struct bfa_fcxp_s *fcxp, void *cbarg,
                            bfa_status_t req_status, u32 rsp_len,
                            u32 resid_len, struct fchs_s *rsp_fchs);
+static void    bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
+                       enum bfa_itnim_aen_event event);
 
 /*
  *  fcs_itnim_sm FCS itnim state machine events
@@ -269,6 +271,7 @@ bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "Target (WWN = %s) is online for initiator (WWN = %s)\n",
                rpwwn_buf, lpwwn_buf);
+               bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE);
                break;
 
        case BFA_FCS_ITNIM_SM_OFFLINE:
@@ -305,14 +308,17 @@ bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
                bfa_itnim_offline(itnim->bfa_itnim);
                wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
                wwn2str(rpwwn_buf, itnim->rport->pwwn);
-               if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE)
+               if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE) {
                        BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                        "Target (WWN = %s) connectivity lost for "
                        "initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);
-               else
+                       bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT);
+               } else {
                        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Target (WWN = %s) offlined by initiator (WWN = %s)\n",
                        rpwwn_buf, lpwwn_buf);
+                       bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE);
+               }
                break;
 
        case BFA_FCS_ITNIM_SM_DELETE:
@@ -381,6 +387,33 @@ bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
        }
 }
 
+static void
+bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
+                       enum bfa_itnim_aen_event event)
+{
+       struct bfa_fcs_rport_s *rport = itnim->rport;
+       struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
+       struct bfa_aen_entry_s  *aen_entry;
+
+       /* Don't post events for well known addresses */
+       if (BFA_FCS_PID_IS_WKA(rport->pid))
+               return;
+
+       bfad_get_aen_entry(bfad, aen_entry);
+       if (!aen_entry)
+               return;
+
+       aen_entry->aen_data.itnim.vf_id = rport->port->fabric->vf_id;
+       aen_entry->aen_data.itnim.ppwwn = bfa_fcs_lport_get_pwwn(
+                                       bfa_fcs_get_base_port(itnim->fcs));
+       aen_entry->aen_data.itnim.lpwwn = bfa_fcs_lport_get_pwwn(rport->port);
+       aen_entry->aen_data.itnim.rpwwn = rport->pwwn;
+
+       /* Send the AEN notification */
+       bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq,
+                                 BFA_AEN_CAT_ITNIM, event);
+}
+
 static void
 bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 {
index f8251a9..d4f951f 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "bfad_drv.h"
+#include "bfad_im.h"
 #include "bfa_fcs.h"
 #include "bfa_fcbuild.h"
 #include "bfa_fc.h"
@@ -299,6 +300,31 @@ bfa_fcs_lport_sm_deleting(
  *  fcs_port_pvt
  */
 
+/*
+ * Send AEN notification
+ */
+static void
+bfa_fcs_lport_aen_post(struct bfa_fcs_lport_s *port,
+                       enum bfa_lport_aen_event event)
+{
+       struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;
+       struct bfa_aen_entry_s  *aen_entry;
+
+       bfad_get_aen_entry(bfad, aen_entry);
+       if (!aen_entry)
+               return;
+
+       aen_entry->aen_data.lport.vf_id = port->fabric->vf_id;
+       aen_entry->aen_data.lport.roles = port->port_cfg.roles;
+       aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn(
+                                       bfa_fcs_get_base_port(port->fcs));
+       aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port);
+
+       /* Send the AEN notification */
+       bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
+                                 BFA_AEN_CAT_LPORT, event);
+}
+
 /*
  * Send a LS reject
  */
@@ -593,6 +619,7 @@ bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "Logical port online: WWN = %s Role = %s\n",
                lpwwn_buf, "Initiator");
+       bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_ONLINE);
 
        bfad->bfad_flags |= BFAD_PORT_ONLINE;
 }
@@ -611,14 +638,17 @@ bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
 
        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
        if (bfa_sm_cmp_state(port->fabric,
-                       bfa_fcs_fabric_sm_online) == BFA_TRUE)
+                       bfa_fcs_fabric_sm_online) == BFA_TRUE) {
                BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                "Logical port lost fabric connectivity: WWN = %s Role = %s\n",
                lpwwn_buf, "Initiator");
-       else
+               bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
+       } else {
                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "Logical port taken offline: WWN = %s Role = %s\n",
                lpwwn_buf, "Initiator");
+               bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_OFFLINE);
+       }
 
        list_for_each_safe(qe, qen, &port->rport_q) {
                rport = (struct bfa_fcs_rport_s *) qe;
@@ -676,6 +706,7 @@ bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "Logical port deleted: WWN = %s Role = %s\n",
                lpwwn_buf, "Initiator");
+       bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DELETE);
 
        /* Base port will be deleted by the OS driver */
        if (port->vport) {
@@ -973,6 +1004,7 @@ bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "New logical port created: WWN = %s Role = %s\n",
                lpwwn_buf, "Initiator");
+       bfa_fcs_lport_aen_post(lport, BFA_LPORT_AEN_NEW);
 
        bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
        bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
@@ -5558,6 +5590,31 @@ bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
 /*
  *  fcs_vport_private FCS virtual port private functions
  */
+/*
+ * Send AEN notification
+ */
+static void
+bfa_fcs_vport_aen_post(struct bfa_fcs_lport_s *port,
+                      enum bfa_lport_aen_event event)
+{
+       struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;
+       struct bfa_aen_entry_s  *aen_entry;
+
+       bfad_get_aen_entry(bfad, aen_entry);
+       if (!aen_entry)
+               return;
+
+       aen_entry->aen_data.lport.vf_id = port->fabric->vf_id;
+       aen_entry->aen_data.lport.roles = port->port_cfg.roles;
+       aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn(
+                                       bfa_fcs_get_base_port(port->fcs));
+       aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port);
+
+       /* Send the AEN notification */
+       bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
+                                 BFA_AEN_CAT_LPORT, event);
+}
+
 /*
  * This routine will be called to send a FDISC command.
  */
@@ -5585,8 +5642,11 @@ bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
        case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
                if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
                        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-               else
+               else {
+                       bfa_fcs_vport_aen_post(&vport->lport,
+                                       BFA_LPORT_AEN_NPIV_DUP_WWN);
                        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
+               }
                break;
 
        case FC_LS_RJT_EXP_INSUFF_RES:
@@ -5596,11 +5656,17 @@ bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
                 */
                if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
                        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-               else
+               else {
+                       bfa_fcs_vport_aen_post(&vport->lport,
+                                       BFA_LPORT_AEN_NPIV_FABRIC_MAX);
                        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
+               }
                break;
 
        default:
+               if (vport->fdisc_retries == 0)
+                       bfa_fcs_vport_aen_post(&vport->lport,
+                                       BFA_LPORT_AEN_NPIV_UNKNOWN);
                bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
        }
 }
index 2c51445..52628d5 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include "bfad_drv.h"
+#include "bfad_im.h"
 #include "bfa_fcs.h"
 #include "bfa_fcbuild.h"
 
@@ -2040,6 +2041,35 @@ bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
        kfree(rport->rp_drv);
 }
 
+static void
+bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
+                       enum bfa_rport_aen_event event,
+                       struct bfa_rport_aen_data_s *data)
+{
+       struct bfa_fcs_lport_s *port = rport->port;
+       struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+       struct bfa_aen_entry_s  *aen_entry;
+
+       bfad_get_aen_entry(bfad, aen_entry);
+       if (!aen_entry)
+               return;
+
+       if (event == BFA_RPORT_AEN_QOS_PRIO)
+               aen_entry->aen_data.rport.priv.qos = data->priv.qos;
+       else if (event == BFA_RPORT_AEN_QOS_FLOWID)
+               aen_entry->aen_data.rport.priv.qos = data->priv.qos;
+
+       aen_entry->aen_data.rport.vf_id = rport->port->fabric->vf_id;
+       aen_entry->aen_data.rport.ppwwn = bfa_fcs_lport_get_pwwn(
+                                       bfa_fcs_get_base_port(rport->fcs));
+       aen_entry->aen_data.rport.lpwwn = bfa_fcs_lport_get_pwwn(rport->port);
+       aen_entry->aen_data.rport.rpwwn = rport->pwwn;
+
+       /* Send the AEN notification */
+       bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq,
+                                 BFA_AEN_CAT_RPORT, event);
+}
+
 static void
 bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
 {
@@ -2063,10 +2093,12 @@ bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
 
        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
        wwn2str(rpwwn_buf, rport->pwwn);
-       if (!BFA_FCS_PID_IS_WKA(rport->pid))
+       if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "Remote port (WWN = %s) online for logical port (WWN = %s)\n",
                rpwwn_buf, lpwwn_buf);
+               bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
+       }
 }
 
 static void
@@ -2083,16 +2115,21 @@ bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
        wwn2str(rpwwn_buf, rport->pwwn);
        if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
-               if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE)
+               if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE) {
                        BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                                "Remote port (WWN = %s) connectivity lost for "
                                "logical port (WWN = %s)\n",
                                rpwwn_buf, lpwwn_buf);
-               else
+                       bfa_fcs_rport_aen_post(rport,
+                               BFA_RPORT_AEN_DISCONNECT, NULL);
+               } else {
                        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                                "Remote port (WWN = %s) offlined by "
                                "logical port (WWN = %s)\n",
                                rpwwn_buf, lpwwn_buf);
+                       bfa_fcs_rport_aen_post(rport,
+                               BFA_RPORT_AEN_OFFLINE, NULL);
+               }
        }
 
        if (bfa_fcs_lport_is_initiator(port)) {
@@ -2366,8 +2403,11 @@ bfa_cb_rport_qos_scn_flowid(void *cbarg,
                struct bfa_rport_qos_attr_s new_qos_attr)
 {
        struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+       struct bfa_rport_aen_data_s aen_data;
 
        bfa_trc(rport->fcs, rport->pwwn);
+       aen_data.priv.qos = new_qos_attr;
+       bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
 }
 
 /*
@@ -2390,8 +2430,11 @@ bfa_cb_rport_qos_scn_prio(void *cbarg,
                struct bfa_rport_qos_attr_s new_qos_attr)
 {
        struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+       struct bfa_rport_aen_data_s aen_data;
 
        bfa_trc(rport->fcs, rport->pwwn);
+       aen_data.priv.qos = new_qos_attr;
+       bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
 }
 
 /*
index e7ffd82..ea24d4c 100644 (file)
@@ -42,11 +42,36 @@ bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq)
                        bfa->iocfc.bfa_regs.intr_status);
 }
 
+/*
+ * Actions to respond RME Interrupt for Crossbow ASIC:
+ * - Write 1 to Interrupt Status register
+ *              INTX - done in bfa_intx()
+ *              MSIX - done in bfa_hwcb_rspq_ack_msix()
+ * - Update CI (only if new CI)
+ */
 static void
-bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq)
+bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq, u32 ci)
 {
        writel(__HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq),
-                       bfa->iocfc.bfa_regs.intr_status);
+               bfa->iocfc.bfa_regs.intr_status);
+
+       if (bfa_rspq_ci(bfa, rspq) == ci)
+               return;
+
+       bfa_rspq_ci(bfa, rspq) = ci;
+       writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]);
+       mmiowb();
+}
+
+void
+bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci)
+{
+       if (bfa_rspq_ci(bfa, rspq) == ci)
+               return;
+
+       bfa_rspq_ci(bfa, rspq) = ci;
+       writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]);
+       mmiowb();
 }
 
 void
@@ -149,8 +174,13 @@ bfa_hwcb_msix_uninstall(struct bfa_s *bfa)
 void
 bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
 {
-       bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix;
-       bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix;
+       if (msix) {
+               bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix;
+               bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix;
+       } else {
+               bfa->iocfc.hwif.hw_reqq_ack = NULL;
+               bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
+       }
 }
 
 void
index 989bbce..637527f 100644 (file)
@@ -64,13 +64,36 @@ bfa_hwct_reqq_ack(struct bfa_s *bfa, int reqq)
        writel(r32, bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq]);
 }
 
+/*
+ * Actions to respond RME Interrupt for Catapult ASIC:
+ * - Write 1 to Interrupt Status register (INTx only - done in bfa_intx())
+ * - Acknowledge by writing to RME Queue Control register
+ * - Update CI
+ */
 void
-bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq)
+bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci)
 {
        u32     r32;
 
        r32 = readl(bfa->iocfc.bfa_regs.rme_q_ctrl[rspq]);
        writel(r32, bfa->iocfc.bfa_regs.rme_q_ctrl[rspq]);
+
+       bfa_rspq_ci(bfa, rspq) = ci;
+       writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]);
+       mmiowb();
+}
+
+/*
+ * Actions to respond RME Interrupt for Catapult2 ASIC:
+ * - Write 1 to Interrupt Status register (INTx only - done in bfa_intx())
+ * - Update CI
+ */
+void
+bfa_hwct2_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci)
+{
+       bfa_rspq_ci(bfa, rspq) = ci;
+       writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]);
+       mmiowb();
 }
 
 void
index d6c2bf3..1ac5aec 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "bfad_drv.h"
+#include "bfad_im.h"
 #include "bfa_ioc.h"
 #include "bfi_reg.h"
 #include "bfa_defs.h"
@@ -458,6 +459,7 @@ bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
        ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
        bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
        BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");
+       bfa_ioc_aen_post(ioc, BFA_IOC_AEN_ENABLE);
 }
 
 static void
@@ -502,6 +504,7 @@ bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
        struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
        bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
        BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n");
+       bfa_ioc_aen_post(ioc, BFA_IOC_AEN_DISABLE);
 }
 
 /*
@@ -1966,6 +1969,7 @@ bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)
 
        BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
                "Heart Beat of IOC has failed\n");
+       bfa_ioc_aen_post(ioc, BFA_IOC_AEN_HBFAIL);
 
 }
 
@@ -1980,6 +1984,7 @@ bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
        BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
                "Running firmware version is incompatible "
                "with the driver version\n");
+       bfa_ioc_aen_post(ioc, BFA_IOC_AEN_FWMISMATCH);
 }
 
 bfa_status_t
@@ -2678,6 +2683,43 @@ bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
        return m;
 }
 
+/*
+ * Send AEN notification
+ */
+void
+bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event)
+{
+       struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
+       struct bfa_aen_entry_s  *aen_entry;
+       enum bfa_ioc_type_e ioc_type;
+
+       bfad_get_aen_entry(bfad, aen_entry);
+       if (!aen_entry)
+               return;
+
+       ioc_type = bfa_ioc_get_type(ioc);
+       switch (ioc_type) {
+       case BFA_IOC_TYPE_FC:
+               aen_entry->aen_data.ioc.pwwn = ioc->attr->pwwn;
+               break;
+       case BFA_IOC_TYPE_FCoE:
+               aen_entry->aen_data.ioc.pwwn = ioc->attr->pwwn;
+               aen_entry->aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
+               break;
+       case BFA_IOC_TYPE_LL:
+               aen_entry->aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
+               break;
+       default:
+               WARN_ON(ioc_type != BFA_IOC_TYPE_FC);
+               break;
+       }
+
+       /* Send the AEN notification */
+       aen_entry->aen_data.ioc.ioc_type = ioc_type;
+       bfad_im_post_vendor_event(aen_entry, bfad, ++ioc->ioc_aen_seq,
+                                 BFA_AEN_CAT_IOC, event);
+}
+
 /*
  * Retrieve saved firmware trace from a prior IOC failure.
  */
@@ -2879,6 +2921,10 @@ bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc)
 {
        if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
                return;
+       if (ioc->attr->nwwn == 0)
+               bfa_ioc_aen_post(ioc, BFA_IOC_AEN_INVALID_NWWN);
+       if (ioc->attr->pwwn == 0)
+               bfa_ioc_aen_post(ioc, BFA_IOC_AEN_INVALID_PWWN);
 }
 
 /*
@@ -3442,6 +3488,54 @@ bfa_sfp_notify(void *sfp_arg, enum bfa_ioc_event_e event)
        }
 }
 
+/*
+ * SFP's State Change Notification post to AEN
+ */
+static void
+bfa_sfp_scn_aen_post(struct bfa_sfp_s *sfp, struct bfi_sfp_scn_s *rsp)
+{
+       struct bfad_s *bfad = (struct bfad_s *)sfp->ioc->bfa->bfad;
+       struct bfa_aen_entry_s  *aen_entry;
+       enum bfa_port_aen_event aen_evt = 0;
+
+       bfa_trc(sfp, (((u64)rsp->pomlvl) << 16) | (((u64)rsp->sfpid) << 8) |
+                     ((u64)rsp->event));
+
+       bfad_get_aen_entry(bfad, aen_entry);
+       if (!aen_entry)
+               return;
+
+       aen_entry->aen_data.port.ioc_type = bfa_ioc_get_type(sfp->ioc);
+       aen_entry->aen_data.port.pwwn = sfp->ioc->attr->pwwn;
+       aen_entry->aen_data.port.mac = bfa_ioc_get_mac(sfp->ioc);
+
+       switch (rsp->event) {
+       case BFA_SFP_SCN_INSERTED:
+               aen_evt = BFA_PORT_AEN_SFP_INSERT;
+               break;
+       case BFA_SFP_SCN_REMOVED:
+               aen_evt = BFA_PORT_AEN_SFP_REMOVE;
+               break;
+       case BFA_SFP_SCN_FAILED:
+               aen_evt = BFA_PORT_AEN_SFP_ACCESS_ERROR;
+               break;
+       case BFA_SFP_SCN_UNSUPPORT:
+               aen_evt = BFA_PORT_AEN_SFP_UNSUPPORT;
+               break;
+       case BFA_SFP_SCN_POM:
+               aen_evt = BFA_PORT_AEN_SFP_POM;
+               aen_entry->aen_data.port.level = rsp->pomlvl;
+               break;
+       default:
+               bfa_trc(sfp, rsp->event);
+               WARN_ON(1);
+       }
+
+       /* Send the AEN notification */
+       bfad_im_post_vendor_event(aen_entry, bfad, ++sfp->ioc->ioc_aen_seq,
+                                 BFA_AEN_CAT_PORT, aen_evt);
+}
+
 /*
  *     SFP get data send
  */
@@ -3481,6 +3575,50 @@ bfa_sfp_getdata(struct bfa_sfp_s *sfp, enum bfi_sfp_mem_e memtype)
        bfa_sfp_getdata_send(sfp);
 }
 
+/*
+ *     SFP scn handler
+ */
+static void
+bfa_sfp_scn(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg)
+{
+       struct bfi_sfp_scn_s *rsp = (struct bfi_sfp_scn_s *) msg;
+
+       switch (rsp->event) {
+       case BFA_SFP_SCN_INSERTED:
+               sfp->state = BFA_SFP_STATE_INSERTED;
+               sfp->data_valid = 0;
+               bfa_sfp_scn_aen_post(sfp, rsp);
+               break;
+       case BFA_SFP_SCN_REMOVED:
+               sfp->state = BFA_SFP_STATE_REMOVED;
+               sfp->data_valid = 0;
+               bfa_sfp_scn_aen_post(sfp, rsp);
+                break;
+       case BFA_SFP_SCN_FAILED:
+               sfp->state = BFA_SFP_STATE_FAILED;
+               sfp->data_valid = 0;
+               bfa_sfp_scn_aen_post(sfp, rsp);
+               break;
+       case BFA_SFP_SCN_UNSUPPORT:
+               sfp->state = BFA_SFP_STATE_UNSUPPORT;
+               bfa_sfp_scn_aen_post(sfp, rsp);
+               if (!sfp->lock)
+                       bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);
+               break;
+       case BFA_SFP_SCN_POM:
+               bfa_sfp_scn_aen_post(sfp, rsp);
+               break;
+       case BFA_SFP_SCN_VALID:
+               sfp->state = BFA_SFP_STATE_VALID;
+               if (!sfp->lock)
+                       bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);
+               break;
+       default:
+               bfa_trc(sfp, rsp->event);
+               WARN_ON(1);
+       }
+}
+
 /*
  * SFP show complete
  */
@@ -3645,7 +3783,7 @@ bfa_sfp_intr(void *sfparg, struct bfi_mbmsg_s *msg)
                break;
 
        case BFI_SFP_I2H_SCN:
-               bfa_trc(sfp, msg->mh.msg_id);
+               bfa_sfp_scn(sfp, msg);
                break;
 
        default:
@@ -3837,6 +3975,26 @@ bfa_sfp_speed(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed,
 #define BFA_FLASH_DMA_BUF_SZ   \
        BFA_ROUNDUP(0x010000 + sizeof(struct bfa_mfg_block_s), BFA_FLASH_SEG_SZ)
 
+static void
+bfa_flash_aen_audit_post(struct bfa_ioc_s *ioc, enum bfa_audit_aen_event event,
+                       int inst, int type)
+{
+       struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
+       struct bfa_aen_entry_s  *aen_entry;
+
+       bfad_get_aen_entry(bfad, aen_entry);
+       if (!aen_entry)
+               return;
+
+       aen_entry->aen_data.audit.pwwn = ioc->attr->pwwn;
+       aen_entry->aen_data.audit.partition_inst = inst;
+       aen_entry->aen_data.audit.partition_type = type;
+
+       /* Send the AEN notification */
+       bfad_im_post_vendor_event(aen_entry, bfad, ++ioc->ioc_aen_seq,
+                                 BFA_AEN_CAT_AUDIT, event);
+}
+
 static void
 bfa_flash_cb(struct bfa_flash_s *flash)
 {
@@ -3978,6 +4136,7 @@ bfa_flash_intr(void *flasharg, struct bfi_mbmsg_s *msg)
                struct bfi_flash_erase_rsp_s *erase;
                struct bfi_flash_write_rsp_s *write;
                struct bfi_flash_read_rsp_s *read;
+               struct bfi_flash_event_s *event;
                struct bfi_mbmsg_s   *msg;
        } m;
 
@@ -4061,8 +4220,19 @@ bfa_flash_intr(void *flasharg, struct bfi_mbmsg_s *msg)
                }
                break;
        case BFI_FLASH_I2H_BOOT_VER_RSP:
+               break;
        case BFI_FLASH_I2H_EVENT:
-               bfa_trc(flash, msg->mh.msg_id);
+               status = be32_to_cpu(m.event->status);
+               bfa_trc(flash, status);
+               if (status == BFA_STATUS_BAD_FWCFG)
+                       bfa_ioc_aen_post(flash->ioc, BFA_IOC_AEN_FWCFG_ERROR);
+               else if (status == BFA_STATUS_INVALID_VENDOR) {
+                       u32 param;
+                       param = be32_to_cpu(m.event->param);
+                       bfa_trc(flash, param);
+                       bfa_ioc_aen_post(flash->ioc,
+                               BFA_IOC_AEN_INVALID_VENDOR);
+               }
                break;
 
        default:
@@ -4204,6 +4374,8 @@ bfa_flash_erase_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
        flash->instance = instance;
 
        bfa_flash_erase_send(flash);
+       bfa_flash_aen_audit_post(flash->ioc, BFA_AUDIT_AEN_FLASH_ERASE,
+                               instance, type);
        return BFA_STATUS_OK;
 }
 
@@ -5416,3 +5588,396 @@ bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg)
                WARN_ON(1);
        }
 }
+
+/*
+ *     DCONF module specific
+ */
+
+BFA_MODULE(dconf);
+
+/*
+ * DCONF state machine events
+ */
+enum bfa_dconf_event {
+       BFA_DCONF_SM_INIT               = 1,    /* dconf Init */
+       BFA_DCONF_SM_FLASH_COMP         = 2,    /* read/write to flash */
+       BFA_DCONF_SM_WR                 = 3,    /* binding change, map */
+       BFA_DCONF_SM_TIMEOUT            = 4,    /* Start timer */
+       BFA_DCONF_SM_EXIT               = 5,    /* exit dconf module */
+       BFA_DCONF_SM_IOCDISABLE         = 6,    /* IOC disable event */
+};
+
+/* forward declaration of DCONF state machine */
+static void bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf,
+                               enum bfa_dconf_event event);
+static void bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf,
+                               enum bfa_dconf_event event);
+static void bfa_dconf_sm_ready(struct bfa_dconf_mod_s *dconf,
+                               enum bfa_dconf_event event);
+static void bfa_dconf_sm_dirty(struct bfa_dconf_mod_s *dconf,
+                               enum bfa_dconf_event event);
+static void bfa_dconf_sm_sync(struct bfa_dconf_mod_s *dconf,
+                               enum bfa_dconf_event event);
+static void bfa_dconf_sm_final_sync(struct bfa_dconf_mod_s *dconf,
+                               enum bfa_dconf_event event);
+static void bfa_dconf_sm_iocdown_dirty(struct bfa_dconf_mod_s *dconf,
+                               enum bfa_dconf_event event);
+
+static void bfa_dconf_cbfn(void *dconf, bfa_status_t status);
+static void bfa_dconf_timer(void *cbarg);
+static bfa_status_t bfa_dconf_flash_write(struct bfa_dconf_mod_s *dconf);
+static void bfa_dconf_init_cb(void *arg, bfa_status_t status);
+
+/*
+ * Begining state of dconf module. Waiting for an event to start.
+ */
+static void
+bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
+{
+       bfa_status_t bfa_status;
+       bfa_trc(dconf->bfa, event);
+
+       switch (event) {
+       case BFA_DCONF_SM_INIT:
+               if (dconf->min_cfg) {
+                       bfa_trc(dconf->bfa, dconf->min_cfg);
+                       return;
+               }
+               bfa_sm_set_state(dconf, bfa_dconf_sm_flash_read);
+               dconf->flashdone = BFA_FALSE;
+               bfa_trc(dconf->bfa, dconf->flashdone);
+               bfa_status = bfa_flash_read_part(BFA_FLASH(dconf->bfa),
+                                       BFA_FLASH_PART_DRV, dconf->instance,
+                                       dconf->dconf,
+                                       sizeof(struct bfa_dconf_s), 0,
+                                       bfa_dconf_init_cb, dconf->bfa);
+               if (bfa_status != BFA_STATUS_OK) {
+                       bfa_dconf_init_cb(dconf->bfa, BFA_STATUS_FAILED);
+                       bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
+                       return;
+               }
+               break;
+       case BFA_DCONF_SM_EXIT:
+               dconf->flashdone = BFA_TRUE;
+       case BFA_DCONF_SM_IOCDISABLE:
+       case BFA_DCONF_SM_WR:
+       case BFA_DCONF_SM_FLASH_COMP:
+               break;
+       default:
+               bfa_sm_fault(dconf->bfa, event);
+       }
+}
+
+/*
+ * Read flash for dconf entries and make a call back to the driver once done.
+ */
+static void
+bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf,
+                       enum bfa_dconf_event event)
+{
+       bfa_trc(dconf->bfa, event);
+
+       switch (event) {
+       case BFA_DCONF_SM_FLASH_COMP:
+               bfa_sm_set_state(dconf, bfa_dconf_sm_ready);
+               break;
+       case BFA_DCONF_SM_TIMEOUT:
+               bfa_sm_set_state(dconf, bfa_dconf_sm_ready);
+               break;
+       case BFA_DCONF_SM_EXIT:
+               dconf->flashdone = BFA_TRUE;
+               bfa_trc(dconf->bfa, dconf->flashdone);
+       case BFA_DCONF_SM_IOCDISABLE:
+               bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
+               break;
+       default:
+               bfa_sm_fault(dconf->bfa, event);
+       }
+}
+
+/*
+ * DCONF Module is in ready state. Has completed the initialization.
+ */
+static void
+bfa_dconf_sm_ready(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
+{
+       bfa_trc(dconf->bfa, event);
+
+       switch (event) {
+       case BFA_DCONF_SM_WR:
+               bfa_timer_start(dconf->bfa, &dconf->timer,
+                       bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
+               bfa_sm_set_state(dconf, bfa_dconf_sm_dirty);
+               break;
+       case BFA_DCONF_SM_EXIT:
+               dconf->flashdone = BFA_TRUE;
+               bfa_trc(dconf->bfa, dconf->flashdone);
+               bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
+               break;
+       case BFA_DCONF_SM_INIT:
+       case BFA_DCONF_SM_IOCDISABLE:
+               break;
+       default:
+               bfa_sm_fault(dconf->bfa, event);
+       }
+}
+
+/*
+ * entries are dirty, write back to the flash.
+ */
+
+static void
+bfa_dconf_sm_dirty(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
+{
+       bfa_trc(dconf->bfa, event);
+
+       switch (event) {
+       case BFA_DCONF_SM_TIMEOUT:
+               bfa_sm_set_state(dconf, bfa_dconf_sm_sync);
+               bfa_dconf_flash_write(dconf);
+               break;
+       case BFA_DCONF_SM_WR:
+               bfa_timer_stop(&dconf->timer);
+               bfa_timer_start(dconf->bfa, &dconf->timer,
+                       bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
+               break;
+       case BFA_DCONF_SM_EXIT:
+               bfa_timer_stop(&dconf->timer);
+               bfa_timer_start(dconf->bfa, &dconf->timer,
+                       bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
+               bfa_sm_set_state(dconf, bfa_dconf_sm_final_sync);
+               bfa_dconf_flash_write(dconf);
+               break;
+       case BFA_DCONF_SM_FLASH_COMP:
+               break;
+       case BFA_DCONF_SM_IOCDISABLE:
+               bfa_timer_stop(&dconf->timer);
+               bfa_sm_set_state(dconf, bfa_dconf_sm_iocdown_dirty);
+               break;
+       default:
+               bfa_sm_fault(dconf->bfa, event);
+       }
+}
+
+/*
+ * Sync the dconf entries to the flash.
+ */
+static void
+bfa_dconf_sm_final_sync(struct bfa_dconf_mod_s *dconf,
+                       enum bfa_dconf_event event)
+{
+       bfa_trc(dconf->bfa, event);
+
+       switch (event) {
+       case BFA_DCONF_SM_IOCDISABLE:
+       case BFA_DCONF_SM_FLASH_COMP:
+               bfa_timer_stop(&dconf->timer);
+       case BFA_DCONF_SM_TIMEOUT:
+               bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
+               dconf->flashdone = BFA_TRUE;
+               bfa_trc(dconf->bfa, dconf->flashdone);
+               bfa_ioc_disable(&dconf->bfa->ioc);
+               break;
+       default:
+               bfa_sm_fault(dconf->bfa, event);
+       }
+}
+
+static void
+bfa_dconf_sm_sync(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
+{
+       bfa_trc(dconf->bfa, event);
+
+       switch (event) {
+       case BFA_DCONF_SM_FLASH_COMP:
+               bfa_sm_set_state(dconf, bfa_dconf_sm_ready);
+               break;
+       case BFA_DCONF_SM_WR:
+               bfa_timer_start(dconf->bfa, &dconf->timer,
+                       bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
+               bfa_sm_set_state(dconf, bfa_dconf_sm_dirty);
+               break;
+       case BFA_DCONF_SM_EXIT:
+               bfa_timer_start(dconf->bfa, &dconf->timer,
+                       bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
+               bfa_sm_set_state(dconf, bfa_dconf_sm_final_sync);
+               break;
+       case BFA_DCONF_SM_IOCDISABLE:
+               bfa_sm_set_state(dconf, bfa_dconf_sm_iocdown_dirty);
+               break;
+       default:
+               bfa_sm_fault(dconf->bfa, event);
+       }
+}
+
+static void
+bfa_dconf_sm_iocdown_dirty(struct bfa_dconf_mod_s *dconf,
+                       enum bfa_dconf_event event)
+{
+       bfa_trc(dconf->bfa, event);
+
+       switch (event) {
+       case BFA_DCONF_SM_INIT:
+               bfa_timer_start(dconf->bfa, &dconf->timer,
+                       bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
+               bfa_sm_set_state(dconf, bfa_dconf_sm_dirty);
+               break;
+       case BFA_DCONF_SM_EXIT:
+               dconf->flashdone = BFA_TRUE;
+               bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
+               break;
+       case BFA_DCONF_SM_IOCDISABLE:
+               break;
+       default:
+               bfa_sm_fault(dconf->bfa, event);
+       }
+}
+
+/*
+ * Compute and return memory needed by DRV_CFG module.
+ */
+static void
+bfa_dconf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
+                 struct bfa_s *bfa)
+{
+       struct bfa_mem_kva_s *dconf_kva = BFA_MEM_DCONF_KVA(bfa);
+
+       if (cfg->drvcfg.min_cfg)
+               bfa_mem_kva_setup(meminfo, dconf_kva,
+                               sizeof(struct bfa_dconf_hdr_s));
+       else
+               bfa_mem_kva_setup(meminfo, dconf_kva,
+                               sizeof(struct bfa_dconf_s));
+}
+
+static void
+bfa_dconf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+               struct bfa_pcidev_s *pcidev)
+{
+       struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
+
+       dconf->bfad = bfad;
+       dconf->bfa = bfa;
+       dconf->instance = bfa->ioc.port_id;
+       bfa_trc(bfa, dconf->instance);
+
+       dconf->dconf = (struct bfa_dconf_s *) bfa_mem_kva_curp(dconf);
+       if (cfg->drvcfg.min_cfg) {
+               bfa_mem_kva_curp(dconf) += sizeof(struct bfa_dconf_hdr_s);
+               dconf->min_cfg = BFA_TRUE;
+               /*
+                * Set the flashdone flag to TRUE explicitly as no flash
+                * write will happen in min_cfg mode.
+                */
+               dconf->flashdone = BFA_TRUE;
+       } else {
+               dconf->min_cfg = BFA_FALSE;
+               bfa_mem_kva_curp(dconf) += sizeof(struct bfa_dconf_s);
+       }
+
+       bfa_dconf_read_data_valid(bfa) = BFA_FALSE;
+       bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
+}
+
+static void
+bfa_dconf_init_cb(void *arg, bfa_status_t status)
+{
+       struct bfa_s *bfa = arg;
+       struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
+
+       dconf->flashdone = BFA_TRUE;
+       bfa_trc(bfa, dconf->flashdone);
+       bfa_iocfc_cb_dconf_modinit(bfa, status);
+       if (status == BFA_STATUS_OK) {
+               bfa_dconf_read_data_valid(bfa) = BFA_TRUE;
+               if (dconf->dconf->hdr.signature != BFI_DCONF_SIGNATURE)
+                       dconf->dconf->hdr.signature = BFI_DCONF_SIGNATURE;
+               if (dconf->dconf->hdr.version != BFI_DCONF_VERSION)
+                       dconf->dconf->hdr.version = BFI_DCONF_VERSION;
+       }
+       bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);
+}
+
+void
+bfa_dconf_modinit(struct bfa_s *bfa)
+{
+       struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
+       bfa_sm_send_event(dconf, BFA_DCONF_SM_INIT);
+}
+static void
+bfa_dconf_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_dconf_stop(struct bfa_s *bfa)
+{
+}
+
+static void bfa_dconf_timer(void *cbarg)
+{
+       struct bfa_dconf_mod_s *dconf = cbarg;
+       bfa_sm_send_event(dconf, BFA_DCONF_SM_TIMEOUT);
+}
+static void
+bfa_dconf_iocdisable(struct bfa_s *bfa)
+{
+       struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
+       bfa_sm_send_event(dconf, BFA_DCONF_SM_IOCDISABLE);
+}
+
+static void
+bfa_dconf_detach(struct bfa_s *bfa)
+{
+}
+
+static bfa_status_t
+bfa_dconf_flash_write(struct bfa_dconf_mod_s *dconf)
+{
+       bfa_status_t bfa_status;
+       bfa_trc(dconf->bfa, 0);
+
+       bfa_status = bfa_flash_update_part(BFA_FLASH(dconf->bfa),
+                               BFA_FLASH_PART_DRV, dconf->instance,
+                               dconf->dconf,  sizeof(struct bfa_dconf_s), 0,
+                               bfa_dconf_cbfn, dconf);
+       if (bfa_status != BFA_STATUS_OK)
+               WARN_ON(bfa_status);
+       bfa_trc(dconf->bfa, bfa_status);
+
+       return bfa_status;
+}
+
+bfa_status_t
+bfa_dconf_update(struct bfa_s *bfa)
+{
+       struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
+       bfa_trc(dconf->bfa, 0);
+       if (bfa_sm_cmp_state(dconf, bfa_dconf_sm_iocdown_dirty))
+               return BFA_STATUS_FAILED;
+
+       if (dconf->min_cfg) {
+               bfa_trc(dconf->bfa, dconf->min_cfg);
+               return BFA_STATUS_FAILED;
+       }
+
+       bfa_sm_send_event(dconf, BFA_DCONF_SM_WR);
+       return BFA_STATUS_OK;
+}
+
+static void
+bfa_dconf_cbfn(void *arg, bfa_status_t status)
+{
+       struct bfa_dconf_mod_s *dconf = arg;
+       WARN_ON(status);
+       bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);
+}
+
+void
+bfa_dconf_modexit(struct bfa_s *bfa)
+{
+       struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
+       BFA_DCONF_MOD(bfa)->flashdone = BFA_FALSE;
+       bfa_trc(bfa, BFA_DCONF_MOD(bfa)->flashdone);
+       bfa_sm_send_event(dconf, BFA_DCONF_SM_EXIT);
+}
index c5ecd2e..546d46b 100644 (file)
@@ -327,6 +327,7 @@ struct bfa_ioc_s {
        enum bfa_mode_s         port_mode;
        u8                      ad_cap_bm;      /* adapter cap bit mask */
        u8                      port_mode_cfg;  /* config port mode */
+       int                     ioc_aen_seq;
 };
 
 struct bfa_ioc_hwif_s {
@@ -366,6 +367,8 @@ struct bfa_cb_qe_s {
        struct list_head        qe;
        bfa_cb_cbfn_t   cbfn;
        bfa_boolean_t   once;
+       bfa_boolean_t   pre_rmv;        /* set for stack based qe(s) */
+       bfa_status_t    fw_status;      /* to access fw status in comp proc */
        void            *cbarg;
 };
 
@@ -658,7 +661,6 @@ struct bfa_phy_s {
        struct bfa_ioc_notify_s ioc_notify; /* ioc event notify */
        struct bfa_mem_dma_s    phy_dma;
 };
-
 #define BFA_PHY(__bfa) (&(__bfa)->modules.phy)
 #define BFA_MEM_PHY_DMA(__bfa) (&(BFA_PHY(__bfa)->phy_dma))
 
@@ -683,6 +685,49 @@ void bfa_phy_memclaim(struct bfa_phy_s *phy,
                u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);
 void bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg);
 
+/*
+ * Driver Config( dconf) specific
+ */
+#define BFI_DCONF_SIGNATURE    0xabcdabcd
+#define BFI_DCONF_VERSION      1
+
+#pragma pack(1)
+struct bfa_dconf_hdr_s {
+       u32     signature;
+       u32     version;
+};
+
+struct bfa_dconf_s {
+       struct bfa_dconf_hdr_s          hdr;
+       struct bfa_lunmask_cfg_s        lun_mask;
+};
+#pragma pack()
+
+struct bfa_dconf_mod_s {
+       bfa_sm_t                sm;
+       u8                      instance;
+       bfa_boolean_t           flashdone;
+       bfa_boolean_t           read_data_valid;
+       bfa_boolean_t           min_cfg;
+       struct bfa_timer_s      timer;
+       struct bfa_s            *bfa;
+       void                    *bfad;
+       void                    *trcmod;
+       struct bfa_dconf_s      *dconf;
+       struct bfa_mem_kva_s    kva_seg;
+};
+
+#define BFA_DCONF_MOD(__bfa)   \
+       (&(__bfa)->modules.dconf_mod)
+#define BFA_MEM_DCONF_KVA(__bfa)       (&(BFA_DCONF_MOD(__bfa)->kva_seg))
+#define bfa_dconf_read_data_valid(__bfa)       \
+       (BFA_DCONF_MOD(__bfa)->read_data_valid)
+#define BFA_DCONF_UPDATE_TOV   5000    /* memtest timeout in msec */
+
+void   bfa_dconf_modinit(struct bfa_s *bfa);
+void   bfa_dconf_modexit(struct bfa_s *bfa);
+bfa_status_t   bfa_dconf_update(struct bfa_s *bfa);
+
 /*
  *     IOC specfic macros
  */
@@ -803,6 +848,7 @@ void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc,
                        struct bfi_ioc_image_hdr_s *fwhdr);
 bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc,
                        struct bfi_ioc_image_hdr_s *fwhdr);
+void bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event);
 bfa_status_t bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats);
 bfa_status_t bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc);
 
index 1c6efd4..2d36e48 100644 (file)
@@ -44,6 +44,7 @@ struct bfa_modules_s {
        struct bfa_flash_s      flash;          /*  flash module */
        struct bfa_diag_s       diag_mod;       /*  diagnostics module  */
        struct bfa_phy_s        phy;            /*  phy module          */
+       struct bfa_dconf_mod_s  dconf_mod;      /*  DCONF common module */
 };
 
 /*
@@ -119,6 +120,7 @@ struct bfa_s {
        struct list_head        reqq_waitq[BFI_IOC_MAX_CQS];
        bfa_boolean_t           fcs;            /*  FCS is attached to BFA */
        struct bfa_msix_s       msix;
+       int                     bfa_aen_seq;
 };
 
 extern bfa_boolean_t bfa_auto_recover;
@@ -130,5 +132,6 @@ extern struct bfa_module_s hal_mod_lps;
 extern struct bfa_module_s hal_mod_uf;
 extern struct bfa_module_s hal_mod_rport;
 extern struct bfa_module_s hal_mod_fcp;
+extern struct bfa_module_s hal_mod_dconf;
 
 #endif /* __BFA_MODULES_H__ */
index 21caaef..aa8a0ea 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "bfad_drv.h"
+#include "bfad_im.h"
 #include "bfa_plog.h"
 #include "bfa_cs.h"
 #include "bfa_modules.h"
@@ -2007,6 +2008,24 @@ bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
        }
 }
 
+static void
+bfa_fcport_aen_post(struct bfa_fcport_s *fcport, enum bfa_port_aen_event event)
+{
+       struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+       struct bfa_aen_entry_s  *aen_entry;
+
+       bfad_get_aen_entry(bfad, aen_entry);
+       if (!aen_entry)
+               return;
+
+       aen_entry->aen_data.port.ioc_type = bfa_get_type(fcport->bfa);
+       aen_entry->aen_data.port.pwwn = fcport->pwwn;
+
+       /* Send the AEN notification */
+       bfad_im_post_vendor_event(aen_entry, bfad, ++fcport->bfa->bfa_aen_seq,
+                                 BFA_AEN_CAT_PORT, event);
+}
+
 /*
  * FC PORT state machine functions
  */
@@ -2095,6 +2114,7 @@ bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
                wwn2str(pwwn_buf, fcport->pwwn);
                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port disabled: WWN = %s\n", pwwn_buf);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
                break;
 
        case BFA_FCPORT_SM_LINKUP:
@@ -2155,6 +2175,7 @@ bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
                wwn2str(pwwn_buf, fcport->pwwn);
                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port disabled: WWN = %s\n", pwwn_buf);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
                break;
 
        case BFA_FCPORT_SM_STOP:
@@ -2208,6 +2229,12 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
                wwn2str(pwwn_buf, fcport->pwwn);
                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port online: WWN = %s\n", pwwn_buf);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ONLINE);
+
+               /* If QoS is enabled and it is not online, send AEN */
+               if (fcport->cfg.qos_enabled &&
+                   fcport->qos_attr.state != BFA_QOS_ONLINE)
+                       bfa_fcport_aen_post(fcport, BFA_PORT_AEN_QOS_NEG);
                break;
 
        case BFA_FCPORT_SM_LINKDOWN:
@@ -2234,6 +2261,7 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
                wwn2str(pwwn_buf, fcport->pwwn);
                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port disabled: WWN = %s\n", pwwn_buf);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
                break;
 
        case BFA_FCPORT_SM_STOP:
@@ -2279,8 +2307,10 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
                wwn2str(pwwn_buf, fcport->pwwn);
                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port offline: WWN = %s\n", pwwn_buf);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port disabled: WWN = %s\n", pwwn_buf);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
                break;
 
        case BFA_FCPORT_SM_LINKDOWN:
@@ -2290,26 +2320,32 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
                                BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
                wwn2str(pwwn_buf, fcport->pwwn);
-               if (BFA_PORT_IS_DISABLED(fcport->bfa))
+               if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
                        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                                "Base port offline: WWN = %s\n", pwwn_buf);
-               else
+                       bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
+               } else {
                        BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                                "Base port (WWN = %s) "
                                "lost fabric connectivity\n", pwwn_buf);
+                       bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+               }
                break;
 
        case BFA_FCPORT_SM_STOP:
                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
                bfa_fcport_reset_linkinfo(fcport);
                wwn2str(pwwn_buf, fcport->pwwn);
-               if (BFA_PORT_IS_DISABLED(fcport->bfa))
+               if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
                        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                                "Base port offline: WWN = %s\n", pwwn_buf);
-               else
+                       bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
+               } else {
                        BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                                "Base port (WWN = %s) "
                                "lost fabric connectivity\n", pwwn_buf);
+                       bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+               }
                break;
 
        case BFA_FCPORT_SM_HWFAIL:
@@ -2317,13 +2353,16 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
                bfa_fcport_reset_linkinfo(fcport);
                bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
                wwn2str(pwwn_buf, fcport->pwwn);
-               if (BFA_PORT_IS_DISABLED(fcport->bfa))
+               if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
                        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                                "Base port offline: WWN = %s\n", pwwn_buf);
-               else
+                       bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
+               } else {
                        BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                                "Base port (WWN = %s) "
                                "lost fabric connectivity\n", pwwn_buf);
+                       bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+               }
                break;
 
        default:
@@ -2454,6 +2493,7 @@ bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
                wwn2str(pwwn_buf, fcport->pwwn);
                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port enabled: WWN = %s\n", pwwn_buf);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
                break;
 
        case BFA_FCPORT_SM_STOP:
@@ -2508,6 +2548,7 @@ bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
                wwn2str(pwwn_buf, fcport->pwwn);
                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port enabled: WWN = %s\n", pwwn_buf);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
                break;
 
        case BFA_FCPORT_SM_DISABLE:
@@ -2874,6 +2915,9 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 
        port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
 
+       INIT_LIST_HEAD(&fcport->stats_pending_q);
+       INIT_LIST_HEAD(&fcport->statsclr_pending_q);
+
        bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
 }
 
@@ -3102,30 +3146,38 @@ bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
 static void
 __bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
 {
-       struct bfa_fcport_s *fcport = cbarg;
+       struct bfa_fcport_s *fcport = (struct bfa_fcport_s *)cbarg;
+       struct bfa_cb_pending_q_s *cb;
+       struct list_head *qe, *qen;
+       union bfa_fcport_stats_u *ret;
 
        if (complete) {
-               if (fcport->stats_status == BFA_STATUS_OK) {
-                       struct timeval tv;
-
-                       /* Swap FC QoS or FCoE stats */
-                       if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
-                               bfa_fcport_qos_stats_swap(
-                                       &fcport->stats_ret->fcqos,
-                                       &fcport->stats->fcqos);
-                       } else {
-                               bfa_fcport_fcoe_stats_swap(
-                                       &fcport->stats_ret->fcoe,
-                                       &fcport->stats->fcoe);
-
-                               do_gettimeofday(&tv);
-                               fcport->stats_ret->fcoe.secs_reset =
+               struct timeval tv;
+               if (fcport->stats_status == BFA_STATUS_OK)
+                       do_gettimeofday(&tv);
+
+               list_for_each_safe(qe, qen, &fcport->stats_pending_q) {
+                       bfa_q_deq(&fcport->stats_pending_q, &qe);
+                       cb = (struct bfa_cb_pending_q_s *)qe;
+                       if (fcport->stats_status == BFA_STATUS_OK) {
+                               ret = (union bfa_fcport_stats_u *)cb->data;
+                               /* Swap FC QoS or FCoE stats */
+                               if (bfa_ioc_get_fcmode(&fcport->bfa->ioc))
+                                       bfa_fcport_qos_stats_swap(&ret->fcqos,
+                                                       &fcport->stats->fcqos);
+                               else {
+                                       bfa_fcport_fcoe_stats_swap(&ret->fcoe,
+                                                       &fcport->stats->fcoe);
+                                       ret->fcoe.secs_reset =
                                        tv.tv_sec - fcport->stats_reset_time;
+                               }
                        }
+                       bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
+                                       fcport->stats_status);
                }
-               fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
+               fcport->stats_status = BFA_STATUS_OK;
        } else {
-               fcport->stats_busy = BFA_FALSE;
+               INIT_LIST_HEAD(&fcport->stats_pending_q);
                fcport->stats_status = BFA_STATUS_OK;
        }
 }
@@ -3143,8 +3195,7 @@ bfa_fcport_stats_get_timeout(void *cbarg)
        }
 
        fcport->stats_status = BFA_STATUS_ETIMER;
-       bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get,
-               fcport);
+       __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
 }
 
 static void
@@ -3174,7 +3225,9 @@ bfa_fcport_send_stats_get(void *cbarg)
 static void
 __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
 {
-       struct bfa_fcport_s *fcport = cbarg;
+       struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+       struct bfa_cb_pending_q_s *cb;
+       struct list_head *qe, *qen;
 
        if (complete) {
                struct timeval tv;
@@ -3184,10 +3237,15 @@ __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
                 */
                do_gettimeofday(&tv);
                fcport->stats_reset_time = tv.tv_sec;
-
-               fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
+               list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) {
+                       bfa_q_deq(&fcport->statsclr_pending_q, &qe);
+                       cb = (struct bfa_cb_pending_q_s *)qe;
+                       bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
+                                               fcport->stats_status);
+               }
+               fcport->stats_status = BFA_STATUS_OK;
        } else {
-               fcport->stats_busy = BFA_FALSE;
+               INIT_LIST_HEAD(&fcport->statsclr_pending_q);
                fcport->stats_status = BFA_STATUS_OK;
        }
 }
@@ -3205,8 +3263,7 @@ bfa_fcport_stats_clr_timeout(void *cbarg)
        }
 
        fcport->stats_status = BFA_STATUS_ETIMER;
-       bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
-                       __bfa_cb_fcport_stats_clr, fcport);
+       __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
 }
 
 static void
@@ -3402,6 +3459,11 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
                                fcport->use_flash_cfg = BFA_FALSE;
                        }
 
+                       if (fcport->cfg.qos_enabled)
+                               fcport->qos_attr.state = BFA_QOS_OFFLINE;
+                       else
+                               fcport->qos_attr.state = BFA_QOS_DISABLED;
+
                        bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
                }
                break;
@@ -3426,28 +3488,26 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
                /*
                 * check for timer pop before processing the rsp
                 */
-               if (fcport->stats_busy == BFA_FALSE ||
-                   fcport->stats_status == BFA_STATUS_ETIMER)
+               if (list_empty(&fcport->stats_pending_q) ||
+                   (fcport->stats_status == BFA_STATUS_ETIMER))
                        break;
 
                bfa_timer_stop(&fcport->timer);
                fcport->stats_status = i2hmsg.pstatsget_rsp->status;
-               bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
-                               __bfa_cb_fcport_stats_get, fcport);
+               __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
                break;
 
        case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
                /*
                 * check for timer pop before processing the rsp
                 */
-               if (fcport->stats_busy == BFA_FALSE ||
-                   fcport->stats_status == BFA_STATUS_ETIMER)
+               if (list_empty(&fcport->statsclr_pending_q) ||
+                   (fcport->stats_status == BFA_STATUS_ETIMER))
                        break;
 
                bfa_timer_stop(&fcport->timer);
                fcport->stats_status = BFA_STATUS_OK;
-               bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
-                               __bfa_cb_fcport_stats_clr, fcport);
+               __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
                break;
 
        case BFI_FCPORT_I2H_ENABLE_AEN:
@@ -3779,25 +3839,25 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
  * Fetch port statistics (FCQoS or FCoE).
  */
 bfa_status_t
-bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
-       bfa_cb_port_t cbfn, void *cbarg)
+bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
 {
        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
 
-       if (fcport->stats_busy) {
-               bfa_trc(bfa, fcport->stats_busy);
-               return BFA_STATUS_DEVBUSY;
-       }
+       if (bfa_ioc_is_disabled(&bfa->ioc))
+               return BFA_STATUS_IOC_DISABLED;
 
-       fcport->stats_busy  = BFA_TRUE;
-       fcport->stats_ret   = stats;
-       fcport->stats_cbfn  = cbfn;
-       fcport->stats_cbarg = cbarg;
+       if (!list_empty(&fcport->statsclr_pending_q))
+               return BFA_STATUS_DEVBUSY;
 
-       bfa_fcport_send_stats_get(fcport);
+       if (list_empty(&fcport->stats_pending_q)) {
+               list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
+               bfa_fcport_send_stats_get(fcport);
+               bfa_timer_start(bfa, &fcport->timer,
+                               bfa_fcport_stats_get_timeout,
+                               fcport, BFA_FCPORT_STATS_TOV);
+       } else
+               list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
 
-       bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_get_timeout,
-                       fcport, BFA_FCPORT_STATS_TOV);
        return BFA_STATUS_OK;
 }
 
@@ -3805,27 +3865,25 @@ bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
  * Reset port statistics (FCQoS or FCoE).
  */
 bfa_status_t
-bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
+bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
 {
        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
 
-       if (fcport->stats_busy) {
-               bfa_trc(bfa, fcport->stats_busy);
+       if (!list_empty(&fcport->stats_pending_q))
                return BFA_STATUS_DEVBUSY;
-       }
-
-       fcport->stats_busy  = BFA_TRUE;
-       fcport->stats_cbfn  = cbfn;
-       fcport->stats_cbarg = cbarg;
 
-       bfa_fcport_send_stats_clear(fcport);
+       if (list_empty(&fcport->statsclr_pending_q)) {
+               list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
+               bfa_fcport_send_stats_clear(fcport);
+               bfa_timer_start(bfa, &fcport->timer,
+                               bfa_fcport_stats_clr_timeout,
+                               fcport, BFA_FCPORT_STATS_TOV);
+       } else
+               list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
 
-       bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout,
-                       fcport, BFA_FCPORT_STATS_TOV);
        return BFA_STATUS_OK;
 }
 
-
 /*
  * Fetch port attributes.
  */
@@ -4619,6 +4677,7 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
                rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
                rp->fw_handle = msg.create_rsp->fw_handle;
                rp->qos_attr = msg.create_rsp->qos_attr;
+               bfa_rport_set_lunmask(bfa, rp);
                WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
                bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
                break;
@@ -4626,6 +4685,7 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
        case BFI_RPORT_I2H_DELETE_RSP:
                rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
                WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
+               bfa_rport_unset_lunmask(bfa, rp);
                bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
                break;
 
@@ -4706,6 +4766,37 @@ bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
        bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
 }
 
+/* Set Rport LUN Mask */
+void
+bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
+{
+       struct bfa_lps_mod_s    *lps_mod = BFA_LPS_MOD(bfa);
+       wwn_t   lp_wwn, rp_wwn;
+       u8 lp_tag = (u8)rp->rport_info.lp_tag;
+
+       rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;
+       lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;
+
+       BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =
+                                       rp->lun_mask = BFA_TRUE;
+       bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn, rp->rport_tag, lp_tag);
+}
+
+/* Unset Rport LUN mask */
+void
+bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
+{
+       struct bfa_lps_mod_s    *lps_mod = BFA_LPS_MOD(bfa);
+       wwn_t   lp_wwn, rp_wwn;
+
+       rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;
+       lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;
+
+       BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =
+                               rp->lun_mask = BFA_FALSE;
+       bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn,
+                       BFA_RPORT_TAG_INVALID, BFA_LP_TAG_INVALID);
+}
 
 /*
  * SGPG related functions
@@ -5517,11 +5608,29 @@ bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
                return BFA_STATUS_PORT_NOT_DISABLED;
        }
 
-       /* Check if the speed is supported */
-       bfa_fcport_get_attr(bfa, &attr);
-       bfa_trc(fcdiag, attr.speed_supported);
-       if (speed > attr.speed_supported)
-               return BFA_STATUS_UNSUPP_SPEED;
+       /*
+        * Check if input speed is supported by the port mode
+        */
+       if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
+               if (!(speed == BFA_PORT_SPEED_1GBPS ||
+                     speed == BFA_PORT_SPEED_2GBPS ||
+                     speed == BFA_PORT_SPEED_4GBPS ||
+                     speed == BFA_PORT_SPEED_8GBPS ||
+                     speed == BFA_PORT_SPEED_16GBPS ||
+                     speed == BFA_PORT_SPEED_AUTO)) {
+                       bfa_trc(fcdiag, speed);
+                       return BFA_STATUS_UNSUPP_SPEED;
+               }
+               bfa_fcport_get_attr(bfa, &attr);
+               bfa_trc(fcdiag, attr.speed_supported);
+               if (speed > attr.speed_supported)
+                       return BFA_STATUS_UNSUPP_SPEED;
+       } else {
+               if (speed != BFA_PORT_SPEED_10GBPS) {
+                       bfa_trc(fcdiag, speed);
+                       return BFA_STATUS_UNSUPP_SPEED;
+               }
+       }
 
        /* For Mezz card, port speed entered needs to be checked */
        if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {
index fbe513a..95adb86 100644 (file)
@@ -297,6 +297,7 @@ struct bfa_rport_s {
        void            *rport_drv;     /*  fcs/driver rport object         */
        u16     fw_handle;      /*  firmware rport handle           */
        u16     rport_tag;      /*  BFA rport tag                   */
+       u8      lun_mask;       /*  LUN mask flag                   */
        struct bfa_rport_info_s rport_info; /*  rport info from fcs/driver */
        struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq     */
        struct bfa_cb_qe_s hcb_qe;      /*  BFA callback qelem              */
@@ -404,6 +405,7 @@ struct bfa_lps_s {
        u8              bb_scn;         /*  local BB_SCN                */
        u8              lsrjt_rsn;      /*  LSRJT reason                */
        u8              lsrjt_expl;     /*  LSRJT explanation           */
+       u8              lun_mask;       /*  LUN mask flag               */
        wwn_t           pwwn;           /*  port wwn of lport           */
        wwn_t           nwwn;           /*  node wwn of lport           */
        wwn_t           pr_pwwn;        /*  port wwn of lport peer      */
@@ -441,7 +443,6 @@ void        bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
  */
 
 #define BFA_FCPORT(_bfa)       (&((_bfa)->modules.port))
-typedef void (*bfa_cb_port_t) (void *cbarg, enum bfa_status status);
 
 /*
  * Link notification data structure
@@ -495,13 +496,11 @@ struct bfa_fcport_s {
        u8                      *stats_kva;
        u64             stats_pa;
        union bfa_fcport_stats_u *stats;
-       union bfa_fcport_stats_u *stats_ret; /*  driver stats location */
        bfa_status_t            stats_status; /*  stats/statsclr status */
-       bfa_boolean_t           stats_busy; /*  outstanding stats/statsclr */
+       struct list_head        stats_pending_q;
+       struct list_head        statsclr_pending_q;
        bfa_boolean_t           stats_qfull;
        u32             stats_reset_time; /*  stats reset time stamp */
-       bfa_cb_port_t           stats_cbfn; /*  driver callback function */
-       void                    *stats_cbarg; /* *!< user callback arg */
        bfa_boolean_t           diag_busy; /*  diag busy status */
        bfa_boolean_t           beacon; /*  port beacon status */
        bfa_boolean_t           link_e2e_beacon; /*  link beacon status */
@@ -552,10 +551,9 @@ void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
                        bfa_boolean_t link_e2e_beacon);
 bfa_boolean_t  bfa_fcport_is_linkup(struct bfa_s *bfa);
 bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
-                                 union bfa_fcport_stats_u *stats,
-                                 bfa_cb_port_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
-                                   void *cbarg);
+                       struct bfa_cb_pending_q_s *cb);
+bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa,
+                       struct bfa_cb_pending_q_s *cb);
 bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
 bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa);
 bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa);
@@ -577,6 +575,19 @@ void bfa_cb_rport_qos_scn_prio(void *rport,
                               struct bfa_rport_qos_attr_s old_qos_attr,
                               struct bfa_rport_qos_attr_s new_qos_attr);
 
+/*
+ *     Rport LUN masking related
+ */
+#define BFA_RPORT_TAG_INVALID  0xffff
+#define BFA_LP_TAG_INVALID     0xff
+void   bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp);
+void   bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp);
+bfa_boolean_t  bfa_rport_lunmask_active(struct bfa_rport_s *rp);
+wwn_t  bfa_rport_get_pwwn(struct bfa_s *bfa, struct bfa_rport_s *rp);
+struct bfa_rport_s *bfa_rport_get_by_wwn(struct bfa_s *bfa, u16 vf_id,
+                                        wwn_t *lpwwn, wwn_t rpwwn);
+void *bfa_cb_get_rp_by_wwn(void *arg, u16 vf_id, wwn_t *lpwwn, wwn_t rpwwn);
+
 /*
  * bfa fcxp API functions
  */
index beb30a7..66fb725 100644 (file)
@@ -1348,7 +1348,7 @@ int
 bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
        struct bfad_s   *bfad;
-       int             error = -ENODEV, retval;
+       int             error = -ENODEV, retval, i;
 
        /* For single port cards - only claim function 0 */
        if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P) &&
@@ -1372,6 +1372,12 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
        bfa_trc_init(bfad->trcmod);
        bfa_trc(bfad, bfad_inst);
 
+       /* AEN INIT */
+       INIT_LIST_HEAD(&bfad->free_aen_q);
+       INIT_LIST_HEAD(&bfad->active_aen_q);
+       for (i = 0; i < BFA_AEN_MAX_ENTRY; i++)
+               list_add_tail(&bfad->aen_list[i].qe, &bfad->free_aen_q);
+
        if (!(bfad_load_fwimg(pdev))) {
                kfree(bfad->trcmod);
                goto out_alloc_trace_failure;
index 89f863e..06fc00c 100644 (file)
@@ -56,7 +56,7 @@ bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd)
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        if (bfad->disable_active) {
                spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-               return EBUSY;
+               return -EBUSY;
        }
 
        bfad->disable_active = BFA_TRUE;
@@ -90,6 +90,7 @@ bfad_iocmd_ioc_get_info(struct bfad_s *bfad, void *cmd)
        bfa_get_adapter_serial_num(&bfad->bfa, iocmd->serialnum);
        iocmd->factorynwwn = pattr.factorynwwn;
        iocmd->factorypwwn = pattr.factorypwwn;
+       iocmd->bfad_num = bfad->inst_no;
        im_port = bfad->pport.im_port;
        iocmd->host = im_port->shost->host_no;
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -177,6 +178,38 @@ out:
        return 0;
 }
 
+int
+bfad_iocmd_ioc_reset_stats(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
+{
+       struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+       unsigned long   flags;
+
+       if (v_cmd == IOCMD_IOC_RESET_STATS) {
+               bfa_ioc_clear_stats(&bfad->bfa);
+               iocmd->status = BFA_STATUS_OK;
+       } else if (v_cmd == IOCMD_IOC_RESET_FWSTATS) {
+               spin_lock_irqsave(&bfad->bfad_lock, flags);
+               iocmd->status = bfa_ioc_fw_stats_clear(&bfad->bfa.ioc);
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       }
+
+       return 0;
+}
+
+int
+bfad_iocmd_ioc_set_name(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
+{
+       struct bfa_bsg_ioc_name_s *iocmd = (struct bfa_bsg_ioc_name_s *) cmd;
+
+       if (v_cmd == IOCMD_IOC_SET_ADAPTER_NAME)
+               strcpy(bfad->adapter_name, iocmd->name);
+       else if (v_cmd == IOCMD_IOC_SET_PORT_NAME)
+               strcpy(bfad->port_name, iocmd->name);
+
+       iocmd->status = BFA_STATUS_OK;
+       return 0;
+}
+
 int
 bfad_iocmd_iocfc_get_attr(struct bfad_s *bfad, void *cmd)
 {
@@ -306,6 +339,81 @@ out:
        return 0;
 }
 
+int
+bfad_iocmd_port_reset_stats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long   flags;
+
+       init_completion(&fcomp.comp);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_port_clear_stats(&bfad->bfa.modules.port,
+                                       bfad_hcb_comp, &fcomp);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status != BFA_STATUS_OK) {
+               bfa_trc(bfad, iocmd->status);
+               return 0;
+       }
+       wait_for_completion(&fcomp.comp);
+       iocmd->status = fcomp.status;
+       return 0;
+}
+
+int
+bfad_iocmd_set_port_cfg(struct bfad_s *bfad, void *iocmd, unsigned int v_cmd)
+{
+       struct bfa_bsg_port_cfg_s *cmd = (struct bfa_bsg_port_cfg_s *)iocmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       if (v_cmd == IOCMD_PORT_CFG_TOPO)
+               cmd->status = bfa_fcport_cfg_topology(&bfad->bfa, cmd->param);
+       else if (v_cmd == IOCMD_PORT_CFG_SPEED)
+               cmd->status = bfa_fcport_cfg_speed(&bfad->bfa, cmd->param);
+       else if (v_cmd == IOCMD_PORT_CFG_ALPA)
+               cmd->status = bfa_fcport_cfg_hardalpa(&bfad->bfa, cmd->param);
+       else if (v_cmd == IOCMD_PORT_CLR_ALPA)
+               cmd->status = bfa_fcport_clr_hardalpa(&bfad->bfa);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
+int
+bfad_iocmd_port_cfg_maxfrsize(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_port_cfg_maxfrsize_s *iocmd =
+                               (struct bfa_bsg_port_cfg_maxfrsize_s *)cmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_fcport_cfg_maxfrsize(&bfad->bfa, iocmd->maxfrsize);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
+int
+bfad_iocmd_port_cfg_bbsc(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
+{
+       struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       if (bfa_ioc_get_type(&bfad->bfa.ioc) == BFA_IOC_TYPE_FC) {
+               if (v_cmd == IOCMD_PORT_BBSC_ENABLE)
+                       fcport->cfg.bb_scn_state = BFA_TRUE;
+               else if (v_cmd == IOCMD_PORT_BBSC_DISABLE)
+                       fcport->cfg.bb_scn_state = BFA_FALSE;
+       }
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       iocmd->status = BFA_STATUS_OK;
+       return 0;
+}
+
 static int
 bfad_iocmd_lport_get_attr(struct bfad_s *bfad, void *cmd)
 {
@@ -353,6 +461,40 @@ out:
        return 0;
 }
 
+int
+bfad_iocmd_lport_reset_stats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_fcs_lport_s *fcs_port;
+       struct bfa_bsg_reset_stats_s *iocmd =
+                       (struct bfa_bsg_reset_stats_s *)cmd;
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa);
+       struct list_head *qe, *qen;
+       struct bfa_itnim_s *itnim;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+                               iocmd->vf_id, iocmd->vpwwn);
+       if (fcs_port == NULL) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+               goto out;
+       }
+
+       bfa_fcs_lport_clear_stats(fcs_port);
+       /* clear IO stats from all active itnims */
+       list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+               itnim = (struct bfa_itnim_s *) qe;
+               if (itnim->rport->rport_info.lp_tag != fcs_port->lp_tag)
+                       continue;
+               bfa_itnim_clear_stats(itnim);
+       }
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       iocmd->status = BFA_STATUS_OK;
+out:
+       return 0;
+}
+
 int
 bfad_iocmd_lport_get_iostats(struct bfad_s *bfad, void *cmd)
 {
@@ -389,7 +531,7 @@ bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd,
        void    *iocmd_bufptr;
 
        if (iocmd->nrports == 0)
-               return EINVAL;
+               return -EINVAL;
 
        if (bfad_chk_iocmd_sz(payload_len,
                        sizeof(struct bfa_bsg_lport_get_rports_s),
@@ -539,6 +681,152 @@ out:
        return 0;
 }
 
+int
+bfad_iocmd_rport_clr_stats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_rport_reset_stats_s *iocmd =
+                               (struct bfa_bsg_rport_reset_stats_s *)cmd;
+       struct bfa_fcs_lport_s *fcs_port;
+       struct bfa_fcs_rport_s *fcs_rport;
+       struct bfa_rport_s *rport;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+                               iocmd->vf_id, iocmd->pwwn);
+       if (fcs_port == NULL) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+               goto out;
+       }
+
+       fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
+       if (fcs_rport == NULL) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+               goto out;
+       }
+
+       memset((char *)&fcs_rport->stats, 0, sizeof(struct bfa_rport_stats_s));
+       rport = bfa_fcs_rport_get_halrport(fcs_rport);
+       memset(&rport->stats, 0, sizeof(rport->stats));
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       iocmd->status = BFA_STATUS_OK;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_rport_set_speed(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_rport_set_speed_s *iocmd =
+                               (struct bfa_bsg_rport_set_speed_s *)cmd;
+       struct bfa_fcs_lport_s *fcs_port;
+       struct bfa_fcs_rport_s *fcs_rport;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+                               iocmd->vf_id, iocmd->pwwn);
+       if (fcs_port == NULL) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+               goto out;
+       }
+
+       fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
+       if (fcs_rport == NULL) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+               goto out;
+       }
+
+       fcs_rport->rpf.assigned_speed  = iocmd->speed;
+       /* Set this speed in f/w only if the RPSC speed is not available */
+       if (fcs_rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN)
+               bfa_rport_speed(fcs_rport->bfa_rport, iocmd->speed);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       iocmd->status = BFA_STATUS_OK;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_vport_get_attr(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_fcs_vport_s *fcs_vport;
+       struct bfa_bsg_vport_attr_s *iocmd = (struct bfa_bsg_vport_attr_s *)cmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs,
+                               iocmd->vf_id, iocmd->vpwwn);
+       if (fcs_vport == NULL) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               iocmd->status = BFA_STATUS_UNKNOWN_VWWN;
+               goto out;
+       }
+
+       bfa_fcs_vport_get_attr(fcs_vport, &iocmd->vport_attr);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       iocmd->status = BFA_STATUS_OK;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_vport_get_stats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_fcs_vport_s *fcs_vport;
+       struct bfa_bsg_vport_stats_s *iocmd =
+                               (struct bfa_bsg_vport_stats_s *)cmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs,
+                               iocmd->vf_id, iocmd->vpwwn);
+       if (fcs_vport == NULL) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               iocmd->status = BFA_STATUS_UNKNOWN_VWWN;
+               goto out;
+       }
+
+       memcpy((void *)&iocmd->vport_stats, (void *)&fcs_vport->vport_stats,
+               sizeof(struct bfa_vport_stats_s));
+       memcpy((void *)&iocmd->vport_stats.port_stats,
+              (void *)&fcs_vport->lport.stats,
+               sizeof(struct bfa_lport_stats_s));
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       iocmd->status = BFA_STATUS_OK;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_vport_clr_stats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_fcs_vport_s *fcs_vport;
+       struct bfa_bsg_reset_stats_s *iocmd =
+                               (struct bfa_bsg_reset_stats_s *)cmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs,
+                               iocmd->vf_id, iocmd->vpwwn);
+       if (fcs_vport == NULL) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               iocmd->status = BFA_STATUS_UNKNOWN_VWWN;
+               goto out;
+       }
+
+       memset(&fcs_vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s));
+       memset(&fcs_vport->lport.stats, 0, sizeof(struct bfa_lport_stats_s));
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       iocmd->status = BFA_STATUS_OK;
+out:
+       return 0;
+}
+
 static int
 bfad_iocmd_fabric_get_lports(struct bfad_s *bfad, void *cmd,
                        unsigned int payload_len)
@@ -581,6 +869,66 @@ out:
        return 0;
 }
 
+int
+bfad_iocmd_ratelim(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
+{
+       struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+       if (cmd == IOCMD_RATELIM_ENABLE)
+               fcport->cfg.ratelimit = BFA_TRUE;
+       else if (cmd == IOCMD_RATELIM_DISABLE)
+               fcport->cfg.ratelimit = BFA_FALSE;
+
+       if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
+               fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;
+
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       iocmd->status = BFA_STATUS_OK;
+
+       return 0;
+}
+
+int
+bfad_iocmd_ratelim_speed(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
+{
+       struct bfa_bsg_trl_speed_s *iocmd = (struct bfa_bsg_trl_speed_s *)pcmd;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+       /* Auto and speeds greater than the supported speed, are invalid */
+       if ((iocmd->speed == BFA_PORT_SPEED_AUTO) ||
+           (iocmd->speed > fcport->speed_sup)) {
+               iocmd->status = BFA_STATUS_UNSUPP_SPEED;
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               return 0;
+       }
+
+       fcport->cfg.trl_def_speed = iocmd->speed;
+       iocmd->status = BFA_STATUS_OK;
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
+int
+bfad_iocmd_cfg_fcpim(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_fcpim_s *iocmd = (struct bfa_bsg_fcpim_s *)cmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       bfa_fcpim_path_tov_set(&bfad->bfa, iocmd->param);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       iocmd->status = BFA_STATUS_OK;
+       return 0;
+}
+
 int
 bfad_iocmd_fcpim_get_modstats(struct bfad_s *bfad, void *cmd)
 {
@@ -603,6 +951,28 @@ bfad_iocmd_fcpim_get_modstats(struct bfad_s *bfad, void *cmd)
        return 0;
 }
 
+int
+bfad_iocmd_fcpim_clr_modstats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_fcpim_modstatsclr_s *iocmd =
+                               (struct bfa_bsg_fcpim_modstatsclr_s *)cmd;
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa);
+       struct list_head *qe, *qen;
+       struct bfa_itnim_s *itnim;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+               itnim = (struct bfa_itnim_s *) qe;
+               bfa_itnim_clear_stats(itnim);
+       }
+       memset(&fcpim->del_itn_stats, 0,
+               sizeof(struct bfa_fcpim_del_itn_stats_s));
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       iocmd->status = BFA_STATUS_OK;
+       return 0;
+}
+
 int
 bfad_iocmd_fcpim_get_del_itn_stats(struct bfad_s *bfad, void *cmd)
 {
@@ -670,7 +1040,36 @@ bfad_iocmd_itnim_get_iostats(struct bfad_s *bfad, void *cmd)
 }
 
 static int
-bfad_iocmd_itnim_get_itnstats(struct bfad_s *bfad, void *cmd)
+bfad_iocmd_itnim_reset_stats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_rport_reset_stats_s *iocmd =
+                       (struct bfa_bsg_rport_reset_stats_s *)cmd;
+       struct bfa_fcs_lport_s  *fcs_port;
+       struct bfa_fcs_itnim_s  *itnim;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+                               iocmd->vf_id, iocmd->pwwn);
+       if (!fcs_port)
+               iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+       else {
+               itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
+               if (itnim == NULL)
+                       iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+               else {
+                       iocmd->status = BFA_STATUS_OK;
+                       bfa_fcs_itnim_stats_clear(fcs_port, iocmd->rpwwn);
+                       bfa_itnim_clear_stats(bfa_fcs_itnim_get_halitn(itnim));
+               }
+       }
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
+static int
+bfad_iocmd_itnim_get_itnstats(struct bfad_s *bfad, void *cmd)
 {
        struct bfa_bsg_itnim_itnstats_s *iocmd =
                        (struct bfa_bsg_itnim_itnstats_s *)cmd;
@@ -1511,11 +1910,545 @@ out:
        return 0;
 }
 
+#define BFA_DEBUG_FW_CORE_CHUNK_SZ     0x4000U /* 16K chunks for FW dump */
+int
+bfad_iocmd_debug_fw_core(struct bfad_s *bfad, void *cmd,
+                       unsigned int payload_len)
+{
+       struct bfa_bsg_debug_s *iocmd = (struct bfa_bsg_debug_s *)cmd;
+       void    *iocmd_bufptr;
+       unsigned long   flags;
+
+       if (bfad_chk_iocmd_sz(payload_len, sizeof(struct bfa_bsg_debug_s),
+                       BFA_DEBUG_FW_CORE_CHUNK_SZ) != BFA_STATUS_OK) {
+               iocmd->status = BFA_STATUS_VERSION_FAIL;
+               return 0;
+       }
+
+       if (iocmd->bufsz < BFA_DEBUG_FW_CORE_CHUNK_SZ ||
+                       !IS_ALIGNED(iocmd->bufsz, sizeof(u16)) ||
+                       !IS_ALIGNED(iocmd->offset, sizeof(u32))) {
+               bfa_trc(bfad, BFA_DEBUG_FW_CORE_CHUNK_SZ);
+               iocmd->status = BFA_STATUS_EINVAL;
+               goto out;
+       }
+
+       iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_debug_s);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_ioc_debug_fwcore(&bfad->bfa.ioc, iocmd_bufptr,
+                               (u32 *)&iocmd->offset, &iocmd->bufsz);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_debug_ctl(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
+{
+       struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+       unsigned long   flags;
+
+       if (v_cmd == IOCMD_DEBUG_FW_STATE_CLR) {
+               spin_lock_irqsave(&bfad->bfad_lock, flags);
+               bfad->bfa.ioc.dbg_fwsave_once = BFA_TRUE;
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       } else if (v_cmd == IOCMD_DEBUG_PORTLOG_CLR)
+               bfad->plog_buf.head = bfad->plog_buf.tail = 0;
+       else if (v_cmd == IOCMD_DEBUG_START_DTRC)
+               bfa_trc_init(bfad->trcmod);
+       else if (v_cmd == IOCMD_DEBUG_STOP_DTRC)
+               bfa_trc_stop(bfad->trcmod);
+
+       iocmd->status = BFA_STATUS_OK;
+       return 0;
+}
+
+int
+bfad_iocmd_porglog_ctl(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_portlogctl_s *iocmd = (struct bfa_bsg_portlogctl_s *)cmd;
+
+       if (iocmd->ctl == BFA_TRUE)
+               bfad->plog_buf.plog_enabled = 1;
+       else
+               bfad->plog_buf.plog_enabled = 0;
+
+       iocmd->status = BFA_STATUS_OK;
+       return 0;
+}
+
+int
+bfad_iocmd_fcpim_cfg_profile(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
+{
+       struct bfa_bsg_fcpim_profile_s *iocmd =
+                               (struct bfa_bsg_fcpim_profile_s *)cmd;
+       struct timeval  tv;
+       unsigned long   flags;
+
+       do_gettimeofday(&tv);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       if (v_cmd == IOCMD_FCPIM_PROFILE_ON)
+               iocmd->status = bfa_fcpim_profile_on(&bfad->bfa, tv.tv_sec);
+       else if (v_cmd == IOCMD_FCPIM_PROFILE_OFF)
+               iocmd->status = bfa_fcpim_profile_off(&bfad->bfa);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
+static int
+bfad_iocmd_itnim_get_ioprofile(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_itnim_ioprofile_s *iocmd =
+                               (struct bfa_bsg_itnim_ioprofile_s *)cmd;
+       struct bfa_fcs_lport_s *fcs_port;
+       struct bfa_fcs_itnim_s *itnim;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+                               iocmd->vf_id, iocmd->lpwwn);
+       if (!fcs_port)
+               iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+       else {
+               itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
+               if (itnim == NULL)
+                       iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+               else
+                       iocmd->status = bfa_itnim_get_ioprofile(
+                                               bfa_fcs_itnim_get_halitn(itnim),
+                                               &iocmd->ioprofile);
+       }
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       return 0;
+}
+
+int
+bfad_iocmd_fcport_get_stats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_fcport_stats_s *iocmd =
+                               (struct bfa_bsg_fcport_stats_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long   flags;
+       struct bfa_cb_pending_q_s cb_qe;
+
+       init_completion(&fcomp.comp);
+       bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
+                          &fcomp, &iocmd->stats);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status != BFA_STATUS_OK) {
+               bfa_trc(bfad, iocmd->status);
+               goto out;
+       }
+       wait_for_completion(&fcomp.comp);
+       iocmd->status = fcomp.status;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_fcport_reset_stats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long   flags;
+       struct bfa_cb_pending_q_s cb_qe;
+
+       init_completion(&fcomp.comp);
+       bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp, &fcomp, NULL);
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status != BFA_STATUS_OK) {
+               bfa_trc(bfad, iocmd->status);
+               goto out;
+       }
+       wait_for_completion(&fcomp.comp);
+       iocmd->status = fcomp.status;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_boot_cfg(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_boot_s *iocmd = (struct bfa_bsg_boot_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long   flags;
+
+       init_completion(&fcomp.comp);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_flash_update_part(BFA_FLASH(&bfad->bfa),
+                       BFA_FLASH_PART_BOOT, PCI_FUNC(bfad->pcidev->devfn),
+                       &iocmd->cfg, sizeof(struct bfa_boot_cfg_s), 0,
+                       bfad_hcb_comp, &fcomp);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status != BFA_STATUS_OK)
+               goto out;
+       wait_for_completion(&fcomp.comp);
+       iocmd->status = fcomp.status;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_boot_query(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_boot_s *iocmd = (struct bfa_bsg_boot_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long   flags;
+
+       init_completion(&fcomp.comp);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_flash_read_part(BFA_FLASH(&bfad->bfa),
+                       BFA_FLASH_PART_BOOT, PCI_FUNC(bfad->pcidev->devfn),
+                       &iocmd->cfg, sizeof(struct bfa_boot_cfg_s), 0,
+                       bfad_hcb_comp, &fcomp);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status != BFA_STATUS_OK)
+               goto out;
+       wait_for_completion(&fcomp.comp);
+       iocmd->status = fcomp.status;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_preboot_query(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_preboot_s *iocmd = (struct bfa_bsg_preboot_s *)cmd;
+       struct bfi_iocfc_cfgrsp_s *cfgrsp = bfad->bfa.iocfc.cfgrsp;
+       struct bfa_boot_pbc_s *pbcfg = &iocmd->cfg;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled;
+       pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns;
+       pbcfg->speed = cfgrsp->pbc_cfg.port_speed;
+       memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun));
+       iocmd->status = BFA_STATUS_OK;
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
+int
+bfad_iocmd_ethboot_cfg(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_ethboot_s *iocmd = (struct bfa_bsg_ethboot_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long   flags;
+
+       init_completion(&fcomp.comp);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_flash_update_part(BFA_FLASH(&bfad->bfa),
+                               BFA_FLASH_PART_PXECFG,
+                               bfad->bfa.ioc.port_id, &iocmd->cfg,
+                               sizeof(struct bfa_ethboot_cfg_s), 0,
+                               bfad_hcb_comp, &fcomp);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status != BFA_STATUS_OK)
+               goto out;
+       wait_for_completion(&fcomp.comp);
+       iocmd->status = fcomp.status;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_ethboot_query(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_ethboot_s *iocmd = (struct bfa_bsg_ethboot_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long   flags;
+
+       init_completion(&fcomp.comp);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_flash_read_part(BFA_FLASH(&bfad->bfa),
+                               BFA_FLASH_PART_PXECFG,
+                               bfad->bfa.ioc.port_id, &iocmd->cfg,
+                               sizeof(struct bfa_ethboot_cfg_s), 0,
+                               bfad_hcb_comp, &fcomp);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status != BFA_STATUS_OK)
+               goto out;
+       wait_for_completion(&fcomp.comp);
+       iocmd->status = fcomp.status;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_cfg_trunk(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
+{
+       struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
+       struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+       if (v_cmd == IOCMD_TRUNK_ENABLE) {
+               trunk->attr.state = BFA_TRUNK_OFFLINE;
+               bfa_fcport_disable(&bfad->bfa);
+               fcport->cfg.trunked = BFA_TRUE;
+       } else if (v_cmd == IOCMD_TRUNK_DISABLE) {
+               trunk->attr.state = BFA_TRUNK_DISABLED;
+               bfa_fcport_disable(&bfad->bfa);
+               fcport->cfg.trunked = BFA_FALSE;
+       }
+
+       if (!bfa_fcport_is_disabled(&bfad->bfa))
+               bfa_fcport_enable(&bfad->bfa);
+
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       iocmd->status = BFA_STATUS_OK;
+       return 0;
+}
+
+int
+bfad_iocmd_trunk_get_attr(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_trunk_attr_s *iocmd = (struct bfa_bsg_trunk_attr_s *)cmd;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
+       struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       memcpy((void *)&iocmd->attr, (void *)&trunk->attr,
+               sizeof(struct bfa_trunk_attr_s));
+       iocmd->attr.port_id = bfa_lps_get_base_pid(&bfad->bfa);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       iocmd->status = BFA_STATUS_OK;
+       return 0;
+}
+
+int
+bfad_iocmd_qos(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
+{
+       struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       if (bfa_ioc_get_type(&bfad->bfa.ioc) == BFA_IOC_TYPE_FC) {
+               if (v_cmd == IOCMD_QOS_ENABLE)
+                       fcport->cfg.qos_enabled = BFA_TRUE;
+               else if (v_cmd == IOCMD_QOS_DISABLE)
+                       fcport->cfg.qos_enabled = BFA_FALSE;
+       }
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       iocmd->status = BFA_STATUS_OK;
+       return 0;
+}
+
+int
+bfad_iocmd_qos_get_attr(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_qos_attr_s *iocmd = (struct bfa_bsg_qos_attr_s *)cmd;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->attr.state = fcport->qos_attr.state;
+       iocmd->attr.total_bb_cr = be32_to_cpu(fcport->qos_attr.total_bb_cr);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       iocmd->status = BFA_STATUS_OK;
+       return 0;
+}
+
+int
+bfad_iocmd_qos_get_vc_attr(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_qos_vc_attr_s *iocmd =
+                               (struct bfa_bsg_qos_vc_attr_s *)cmd;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
+       struct bfa_qos_vc_attr_s *bfa_vc_attr = &fcport->qos_vc_attr;
+       unsigned long   flags;
+       u32     i = 0;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->attr.total_vc_count = be16_to_cpu(bfa_vc_attr->total_vc_count);
+       iocmd->attr.shared_credit  = be16_to_cpu(bfa_vc_attr->shared_credit);
+       iocmd->attr.elp_opmode_flags  =
+                               be32_to_cpu(bfa_vc_attr->elp_opmode_flags);
+
+       /* Individual VC info */
+       while (i < iocmd->attr.total_vc_count) {
+               iocmd->attr.vc_info[i].vc_credit =
+                               bfa_vc_attr->vc_info[i].vc_credit;
+               iocmd->attr.vc_info[i].borrow_credit =
+                               bfa_vc_attr->vc_info[i].borrow_credit;
+               iocmd->attr.vc_info[i].priority =
+                               bfa_vc_attr->vc_info[i].priority;
+               i++;
+       }
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       iocmd->status = BFA_STATUS_OK;
+       return 0;
+}
+
+int
+bfad_iocmd_qos_get_stats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_fcport_stats_s *iocmd =
+                               (struct bfa_bsg_fcport_stats_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long   flags;
+       struct bfa_cb_pending_q_s cb_qe;
+
+       init_completion(&fcomp.comp);
+       bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
+                          &fcomp, &iocmd->stats);
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
+       iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status != BFA_STATUS_OK) {
+               bfa_trc(bfad, iocmd->status);
+               goto out;
+       }
+       wait_for_completion(&fcomp.comp);
+       iocmd->status = fcomp.status;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_qos_reset_stats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long   flags;
+       struct bfa_cb_pending_q_s cb_qe;
+
+       init_completion(&fcomp.comp);
+       bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
+                          &fcomp, NULL);
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
+       iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status != BFA_STATUS_OK) {
+               bfa_trc(bfad, iocmd->status);
+               goto out;
+       }
+       wait_for_completion(&fcomp.comp);
+       iocmd->status = fcomp.status;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_vf_get_stats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_vf_stats_s *iocmd =
+                       (struct bfa_bsg_vf_stats_s *)cmd;
+       struct bfa_fcs_fabric_s *fcs_vf;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       fcs_vf = bfa_fcs_vf_lookup(&bfad->bfa_fcs, iocmd->vf_id);
+       if (fcs_vf == NULL) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               iocmd->status = BFA_STATUS_UNKNOWN_VFID;
+               goto out;
+       }
+       memcpy((void *)&iocmd->stats, (void *)&fcs_vf->stats,
+               sizeof(struct bfa_vf_stats_s));
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       iocmd->status = BFA_STATUS_OK;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_vf_clr_stats(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_vf_reset_stats_s *iocmd =
+                       (struct bfa_bsg_vf_reset_stats_s *)cmd;
+       struct bfa_fcs_fabric_s *fcs_vf;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       fcs_vf = bfa_fcs_vf_lookup(&bfad->bfa_fcs, iocmd->vf_id);
+       if (fcs_vf == NULL) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               iocmd->status = BFA_STATUS_UNKNOWN_VFID;
+               goto out;
+       }
+       memset((void *)&fcs_vf->stats, 0, sizeof(struct bfa_vf_stats_s));
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       iocmd->status = BFA_STATUS_OK;
+out:
+       return 0;
+}
+
+int
+bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd)
+{
+       struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE)
+               iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_TRUE);
+       else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE)
+               iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_FALSE);
+       else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR)
+               iocmd->status = bfa_fcpim_lunmask_clear(&bfad->bfa);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       return 0;
+}
+
+int
+bfad_iocmd_fcpim_lunmask_query(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_fcpim_lunmask_query_s *iocmd =
+                       (struct bfa_bsg_fcpim_lunmask_query_s *)cmd;
+       struct bfa_lunmask_cfg_s *lun_mask = &iocmd->lun_mask;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_fcpim_lunmask_query(&bfad->bfa, lun_mask);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       return 0;
+}
+
+int
+bfad_iocmd_fcpim_cfg_lunmask(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
+{
+       struct bfa_bsg_fcpim_lunmask_s *iocmd =
+                               (struct bfa_bsg_fcpim_lunmask_s *)cmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       if (v_cmd == IOCMD_FCPIM_LUNMASK_ADD)
+               iocmd->status = bfa_fcpim_lunmask_add(&bfad->bfa, iocmd->vf_id,
+                                       &iocmd->pwwn, iocmd->rpwwn, iocmd->lun);
+       else if (v_cmd == IOCMD_FCPIM_LUNMASK_DELETE)
+               iocmd->status = bfa_fcpim_lunmask_delete(&bfad->bfa,
+                                       iocmd->vf_id, &iocmd->pwwn,
+                                       iocmd->rpwwn, iocmd->lun);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       return 0;
+}
+
 static int
 bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
                unsigned int payload_len)
 {
-       int rc = EINVAL;
+       int rc = -EINVAL;
 
        switch (cmd) {
        case IOCMD_IOC_ENABLE:
@@ -1536,6 +2469,14 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
        case IOCMD_IOC_GET_FWSTATS:
                rc = bfad_iocmd_ioc_get_fwstats(bfad, iocmd, payload_len);
                break;
+       case IOCMD_IOC_RESET_STATS:
+       case IOCMD_IOC_RESET_FWSTATS:
+               rc = bfad_iocmd_ioc_reset_stats(bfad, iocmd, cmd);
+               break;
+       case IOCMD_IOC_SET_ADAPTER_NAME:
+       case IOCMD_IOC_SET_PORT_NAME:
+               rc = bfad_iocmd_ioc_set_name(bfad, iocmd, cmd);
+               break;
        case IOCMD_IOCFC_GET_ATTR:
                rc = bfad_iocmd_iocfc_get_attr(bfad, iocmd);
                break;
@@ -1554,12 +2495,31 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
        case IOCMD_PORT_GET_STATS:
                rc = bfad_iocmd_port_get_stats(bfad, iocmd, payload_len);
                break;
+       case IOCMD_PORT_RESET_STATS:
+               rc = bfad_iocmd_port_reset_stats(bfad, iocmd);
+               break;
+       case IOCMD_PORT_CFG_TOPO:
+       case IOCMD_PORT_CFG_SPEED:
+       case IOCMD_PORT_CFG_ALPA:
+       case IOCMD_PORT_CLR_ALPA:
+               rc = bfad_iocmd_set_port_cfg(bfad, iocmd, cmd);
+               break;
+       case IOCMD_PORT_CFG_MAXFRSZ:
+               rc = bfad_iocmd_port_cfg_maxfrsize(bfad, iocmd);
+               break;
+       case IOCMD_PORT_BBSC_ENABLE:
+       case IOCMD_PORT_BBSC_DISABLE:
+               rc = bfad_iocmd_port_cfg_bbsc(bfad, iocmd, cmd);
+               break;
        case IOCMD_LPORT_GET_ATTR:
                rc = bfad_iocmd_lport_get_attr(bfad, iocmd);
                break;
        case IOCMD_LPORT_GET_STATS:
                rc = bfad_iocmd_lport_get_stats(bfad, iocmd);
                break;
+       case IOCMD_LPORT_RESET_STATS:
+               rc = bfad_iocmd_lport_reset_stats(bfad, iocmd);
+               break;
        case IOCMD_LPORT_GET_IOSTATS:
                rc = bfad_iocmd_lport_get_iostats(bfad, iocmd);
                break;
@@ -1575,12 +2535,40 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
        case IOCMD_RPORT_GET_STATS:
                rc = bfad_iocmd_rport_get_stats(bfad, iocmd);
                break;
+       case IOCMD_RPORT_RESET_STATS:
+               rc = bfad_iocmd_rport_clr_stats(bfad, iocmd);
+               break;
+       case IOCMD_RPORT_SET_SPEED:
+               rc = bfad_iocmd_rport_set_speed(bfad, iocmd);
+               break;
+       case IOCMD_VPORT_GET_ATTR:
+               rc = bfad_iocmd_vport_get_attr(bfad, iocmd);
+               break;
+       case IOCMD_VPORT_GET_STATS:
+               rc = bfad_iocmd_vport_get_stats(bfad, iocmd);
+               break;
+       case IOCMD_VPORT_RESET_STATS:
+               rc = bfad_iocmd_vport_clr_stats(bfad, iocmd);
+               break;
        case IOCMD_FABRIC_GET_LPORTS:
                rc = bfad_iocmd_fabric_get_lports(bfad, iocmd, payload_len);
                break;
+       case IOCMD_RATELIM_ENABLE:
+       case IOCMD_RATELIM_DISABLE:
+               rc = bfad_iocmd_ratelim(bfad, cmd, iocmd);
+               break;
+       case IOCMD_RATELIM_DEF_SPEED:
+               rc = bfad_iocmd_ratelim_speed(bfad, cmd, iocmd);
+               break;
+       case IOCMD_FCPIM_FAILOVER:
+               rc = bfad_iocmd_cfg_fcpim(bfad, iocmd);
+               break;
        case IOCMD_FCPIM_MODSTATS:
                rc = bfad_iocmd_fcpim_get_modstats(bfad, iocmd);
                break;
+       case IOCMD_FCPIM_MODSTATSCLR:
+               rc = bfad_iocmd_fcpim_clr_modstats(bfad, iocmd);
+               break;
        case IOCMD_FCPIM_DEL_ITN_STATS:
                rc = bfad_iocmd_fcpim_get_del_itn_stats(bfad, iocmd);
                break;
@@ -1590,6 +2578,9 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
        case IOCMD_ITNIM_GET_IOSTATS:
                rc = bfad_iocmd_itnim_get_iostats(bfad, iocmd);
                break;
+       case IOCMD_ITNIM_RESET_STATS:
+               rc = bfad_iocmd_itnim_reset_stats(bfad, iocmd);
+               break;
        case IOCMD_ITNIM_GET_ITNSTATS:
                rc = bfad_iocmd_itnim_get_itnstats(bfad, iocmd);
                break;
@@ -1702,11 +2693,92 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
        case IOCMD_DEBUG_PORTLOG:
                rc = bfad_iocmd_porglog_get(bfad, iocmd);
                break;
+       case IOCMD_DEBUG_FW_CORE:
+               rc = bfad_iocmd_debug_fw_core(bfad, iocmd, payload_len);
+               break;
+       case IOCMD_DEBUG_FW_STATE_CLR:
+       case IOCMD_DEBUG_PORTLOG_CLR:
+       case IOCMD_DEBUG_START_DTRC:
+       case IOCMD_DEBUG_STOP_DTRC:
+               rc = bfad_iocmd_debug_ctl(bfad, iocmd, cmd);
+               break;
+       case IOCMD_DEBUG_PORTLOG_CTL:
+               rc = bfad_iocmd_porglog_ctl(bfad, iocmd);
+               break;
+       case IOCMD_FCPIM_PROFILE_ON:
+       case IOCMD_FCPIM_PROFILE_OFF:
+               rc = bfad_iocmd_fcpim_cfg_profile(bfad, iocmd, cmd);
+               break;
+       case IOCMD_ITNIM_GET_IOPROFILE:
+               rc = bfad_iocmd_itnim_get_ioprofile(bfad, iocmd);
+               break;
+       case IOCMD_FCPORT_GET_STATS:
+               rc = bfad_iocmd_fcport_get_stats(bfad, iocmd);
+               break;
+       case IOCMD_FCPORT_RESET_STATS:
+               rc = bfad_iocmd_fcport_reset_stats(bfad, iocmd);
+               break;
+       case IOCMD_BOOT_CFG:
+               rc = bfad_iocmd_boot_cfg(bfad, iocmd);
+               break;
+       case IOCMD_BOOT_QUERY:
+               rc = bfad_iocmd_boot_query(bfad, iocmd);
+               break;
+       case IOCMD_PREBOOT_QUERY:
+               rc = bfad_iocmd_preboot_query(bfad, iocmd);
+               break;
+       case IOCMD_ETHBOOT_CFG:
+               rc = bfad_iocmd_ethboot_cfg(bfad, iocmd);
+               break;
+       case IOCMD_ETHBOOT_QUERY:
+               rc = bfad_iocmd_ethboot_query(bfad, iocmd);
+               break;
+       case IOCMD_TRUNK_ENABLE:
+       case IOCMD_TRUNK_DISABLE:
+               rc = bfad_iocmd_cfg_trunk(bfad, iocmd, cmd);
+               break;
+       case IOCMD_TRUNK_GET_ATTR:
+               rc = bfad_iocmd_trunk_get_attr(bfad, iocmd);
+               break;
+       case IOCMD_QOS_ENABLE:
+       case IOCMD_QOS_DISABLE:
+               rc = bfad_iocmd_qos(bfad, iocmd, cmd);
+               break;
+       case IOCMD_QOS_GET_ATTR:
+               rc = bfad_iocmd_qos_get_attr(bfad, iocmd);
+               break;
+       case IOCMD_QOS_GET_VC_ATTR:
+               rc = bfad_iocmd_qos_get_vc_attr(bfad, iocmd);
+               break;
+       case IOCMD_QOS_GET_STATS:
+               rc = bfad_iocmd_qos_get_stats(bfad, iocmd);
+               break;
+       case IOCMD_QOS_RESET_STATS:
+               rc = bfad_iocmd_qos_reset_stats(bfad, iocmd);
+               break;
+       case IOCMD_VF_GET_STATS:
+               rc = bfad_iocmd_vf_get_stats(bfad, iocmd);
+               break;
+       case IOCMD_VF_RESET_STATS:
+               rc = bfad_iocmd_vf_clr_stats(bfad, iocmd);
+               break;
+       case IOCMD_FCPIM_LUNMASK_ENABLE:
+       case IOCMD_FCPIM_LUNMASK_DISABLE:
+       case IOCMD_FCPIM_LUNMASK_CLEAR:
+               rc = bfad_iocmd_lunmask(bfad, iocmd, cmd);
+               break;
+       case IOCMD_FCPIM_LUNMASK_QUERY:
+               rc = bfad_iocmd_fcpim_lunmask_query(bfad, iocmd);
+               break;
+       case IOCMD_FCPIM_LUNMASK_ADD:
+       case IOCMD_FCPIM_LUNMASK_DELETE:
+               rc = bfad_iocmd_fcpim_cfg_lunmask(bfad, iocmd, cmd);
+               break;
        default:
-               rc = EINVAL;
+               rc = -EINVAL;
                break;
        }
-       return -rc;
+       return rc;
 }
 
 static int
index 99b0e8a..e859adb 100644 (file)
@@ -30,24 +30,48 @@ enum {
        IOCMD_IOC_GET_INFO,
        IOCMD_IOC_GET_STATS,
        IOCMD_IOC_GET_FWSTATS,
+       IOCMD_IOC_RESET_STATS,
+       IOCMD_IOC_RESET_FWSTATS,
+       IOCMD_IOC_SET_ADAPTER_NAME,
+       IOCMD_IOC_SET_PORT_NAME,
        IOCMD_IOCFC_GET_ATTR,
        IOCMD_IOCFC_SET_INTR,
        IOCMD_PORT_ENABLE,
        IOCMD_PORT_DISABLE,
        IOCMD_PORT_GET_ATTR,
        IOCMD_PORT_GET_STATS,
+       IOCMD_PORT_RESET_STATS,
+       IOCMD_PORT_CFG_TOPO,
+       IOCMD_PORT_CFG_SPEED,
+       IOCMD_PORT_CFG_ALPA,
+       IOCMD_PORT_CFG_MAXFRSZ,
+       IOCMD_PORT_CLR_ALPA,
+       IOCMD_PORT_BBSC_ENABLE,
+       IOCMD_PORT_BBSC_DISABLE,
        IOCMD_LPORT_GET_ATTR,
        IOCMD_LPORT_GET_RPORTS,
        IOCMD_LPORT_GET_STATS,
+       IOCMD_LPORT_RESET_STATS,
        IOCMD_LPORT_GET_IOSTATS,
        IOCMD_RPORT_GET_ATTR,
        IOCMD_RPORT_GET_ADDR,
        IOCMD_RPORT_GET_STATS,
+       IOCMD_RPORT_RESET_STATS,
+       IOCMD_RPORT_SET_SPEED,
+       IOCMD_VPORT_GET_ATTR,
+       IOCMD_VPORT_GET_STATS,
+       IOCMD_VPORT_RESET_STATS,
        IOCMD_FABRIC_GET_LPORTS,
+       IOCMD_RATELIM_ENABLE,
+       IOCMD_RATELIM_DISABLE,
+       IOCMD_RATELIM_DEF_SPEED,
+       IOCMD_FCPIM_FAILOVER,
        IOCMD_FCPIM_MODSTATS,
+       IOCMD_FCPIM_MODSTATSCLR,
        IOCMD_FCPIM_DEL_ITN_STATS,
        IOCMD_ITNIM_GET_ATTR,
        IOCMD_ITNIM_GET_IOSTATS,
+       IOCMD_ITNIM_RESET_STATS,
        IOCMD_ITNIM_GET_ITNSTATS,
        IOCMD_IOC_PCIFN_CFG,
        IOCMD_FCPORT_ENABLE,
@@ -86,6 +110,39 @@ enum {
        IOCMD_PHY_READ_FW,
        IOCMD_VHBA_QUERY,
        IOCMD_DEBUG_PORTLOG,
+       IOCMD_DEBUG_FW_CORE,
+       IOCMD_DEBUG_FW_STATE_CLR,
+       IOCMD_DEBUG_PORTLOG_CLR,
+       IOCMD_DEBUG_START_DTRC,
+       IOCMD_DEBUG_STOP_DTRC,
+       IOCMD_DEBUG_PORTLOG_CTL,
+       IOCMD_FCPIM_PROFILE_ON,
+       IOCMD_FCPIM_PROFILE_OFF,
+       IOCMD_ITNIM_GET_IOPROFILE,
+       IOCMD_FCPORT_GET_STATS,
+       IOCMD_FCPORT_RESET_STATS,
+       IOCMD_BOOT_CFG,
+       IOCMD_BOOT_QUERY,
+       IOCMD_PREBOOT_QUERY,
+       IOCMD_ETHBOOT_CFG,
+       IOCMD_ETHBOOT_QUERY,
+       IOCMD_TRUNK_ENABLE,
+       IOCMD_TRUNK_DISABLE,
+       IOCMD_TRUNK_GET_ATTR,
+       IOCMD_QOS_ENABLE,
+       IOCMD_QOS_DISABLE,
+       IOCMD_QOS_GET_ATTR,
+       IOCMD_QOS_GET_VC_ATTR,
+       IOCMD_QOS_GET_STATS,
+       IOCMD_QOS_RESET_STATS,
+       IOCMD_VF_GET_STATS,
+       IOCMD_VF_RESET_STATS,
+       IOCMD_FCPIM_LUNMASK_ENABLE,
+       IOCMD_FCPIM_LUNMASK_DISABLE,
+       IOCMD_FCPIM_LUNMASK_CLEAR,
+       IOCMD_FCPIM_LUNMASK_QUERY,
+       IOCMD_FCPIM_LUNMASK_ADD,
+       IOCMD_FCPIM_LUNMASK_DELETE,
 };
 
 struct bfa_bsg_gen_s {
@@ -94,6 +151,43 @@ struct bfa_bsg_gen_s {
        u16             rsvd;
 };
 
+struct bfa_bsg_portlogctl_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       bfa_boolean_t   ctl;
+       int             inst_no;
+};
+
+struct bfa_bsg_fcpim_profile_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+};
+
+struct bfa_bsg_itnim_ioprofile_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             vf_id;
+       wwn_t           lpwwn;
+       wwn_t           rpwwn;
+       struct bfa_itnim_ioprofile_s ioprofile;
+};
+
+struct bfa_bsg_fcport_stats_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       union bfa_fcport_stats_u stats;
+};
+
+struct bfa_bsg_ioc_name_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       char            name[BFA_ADAPTER_SYM_NAME_LEN];
+};
+
 struct bfa_bsg_ioc_info_s {
        bfa_status_t    status;
        u16             bfad_num;
@@ -164,6 +258,20 @@ struct bfa_bsg_port_attr_s {
        struct bfa_port_attr_s  attr;
 };
 
+struct bfa_bsg_port_cfg_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       u32             param;
+       u32             rsvd1;
+};
+
+struct bfa_bsg_port_cfg_maxfrsize_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             maxfrsize;
+};
+
 struct bfa_bsg_port_stats_s {
        bfa_status_t    status;
        u16             bfad_num;
@@ -237,6 +345,47 @@ struct bfa_bsg_rport_scsi_addr_s {
        u32             lun;
 };
 
+struct bfa_bsg_rport_reset_stats_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             vf_id;
+       wwn_t           pwwn;
+       wwn_t           rpwwn;
+};
+
+struct bfa_bsg_rport_set_speed_s {
+       bfa_status_t            status;
+       u16                     bfad_num;
+       u16                     vf_id;
+       enum bfa_port_speed     speed;
+       u32                     rsvd;
+       wwn_t                   pwwn;
+       wwn_t                   rpwwn;
+};
+
+struct bfa_bsg_vport_attr_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             vf_id;
+       wwn_t           vpwwn;
+       struct bfa_vport_attr_s vport_attr;
+};
+
+struct bfa_bsg_vport_stats_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             vf_id;
+       wwn_t           vpwwn;
+       struct bfa_vport_stats_s vport_stats;
+};
+
+struct bfa_bsg_reset_stats_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             vf_id;
+       wwn_t           vpwwn;
+};
+
 struct bfa_bsg_fabric_get_lports_s {
        bfa_status_t    status;
        u16             bfad_num;
@@ -246,6 +395,19 @@ struct bfa_bsg_fabric_get_lports_s {
        u32             rsvd;
 };
 
+struct bfa_bsg_trl_speed_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       enum bfa_port_speed speed;
+};
+
+struct bfa_bsg_fcpim_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             param;
+};
+
 struct bfa_bsg_fcpim_modstats_s {
        bfa_status_t    status;
        u16             bfad_num;
@@ -258,6 +420,11 @@ struct bfa_bsg_fcpim_del_itn_stats_s {
        struct bfa_fcpim_del_itn_stats_s modstats;
 };
 
+struct bfa_bsg_fcpim_modstatsclr_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+};
+
 struct bfa_bsg_itnim_attr_s {
        bfa_status_t    status;
        u16             bfad_num;
@@ -485,6 +652,76 @@ struct bfa_bsg_vhba_attr_s {
        struct bfa_vhba_attr_s  attr;
 };
 
+struct bfa_bsg_boot_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       struct bfa_boot_cfg_s   cfg;
+};
+
+struct bfa_bsg_preboot_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       struct bfa_boot_pbc_s   cfg;
+};
+
+struct bfa_bsg_ethboot_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       struct  bfa_ethboot_cfg_s  cfg;
+};
+
+struct bfa_bsg_trunk_attr_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       struct bfa_trunk_attr_s attr;
+};
+
+struct bfa_bsg_qos_attr_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       struct bfa_qos_attr_s   attr;
+};
+
+struct bfa_bsg_qos_vc_attr_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       struct bfa_qos_vc_attr_s attr;
+};
+
+struct bfa_bsg_vf_stats_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             vf_id;
+       struct bfa_vf_stats_s   stats;
+};
+
+struct bfa_bsg_vf_reset_stats_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             vf_id;
+};
+
+struct bfa_bsg_fcpim_lunmask_query_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       struct bfa_lunmask_cfg_s lun_mask;
+};
+
+struct bfa_bsg_fcpim_lunmask_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             vf_id;
+       wwn_t           pwwn;
+       wwn_t           rpwwn;
+       struct scsi_lun lun;
+};
+
 struct bfa_bsg_fcpt_s {
        bfa_status_t    status;
        u16             vf_id;
index 48661a2..bda999a 100644 (file)
@@ -56,7 +56,7 @@
 #ifdef BFA_DRIVER_VERSION
 #define BFAD_DRIVER_VERSION    BFA_DRIVER_VERSION
 #else
-#define BFAD_DRIVER_VERSION    "3.0.2.1"
+#define BFAD_DRIVER_VERSION    "3.0.2.2"
 #endif
 
 #define BFAD_PROTO_NAME FCPI_NAME
@@ -224,6 +224,10 @@ struct bfad_s {
        char *regdata;
        u32 reglen;
        struct dentry *bfad_dentry_files[5];
+       struct list_head        free_aen_q;
+       struct list_head        active_aen_q;
+       struct bfa_aen_entry_s  aen_list[BFA_AEN_MAX_ENTRY];
+       spinlock_t              bfad_aen_spinlock;
 };
 
 /* BFAD state machine events */
index f2bf812..0131238 100644 (file)
@@ -656,6 +656,31 @@ bfad_im_port_clean(struct bfad_im_port_s *im_port)
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 }
 
+static void bfad_aen_im_notify_handler(struct work_struct *work)
+{
+       struct bfad_im_s *im =
+               container_of(work, struct bfad_im_s, aen_im_notify_work);
+       struct bfa_aen_entry_s *aen_entry;
+       struct bfad_s *bfad = im->bfad;
+       struct Scsi_Host *shost = bfad->pport.im_port->shost;
+       void *event_data;
+       unsigned long flags;
+
+       while (!list_empty(&bfad->active_aen_q)) {
+               spin_lock_irqsave(&bfad->bfad_aen_spinlock, flags);
+               bfa_q_deq(&bfad->active_aen_q, &aen_entry);
+               spin_unlock_irqrestore(&bfad->bfad_aen_spinlock, flags);
+               event_data = (char *)aen_entry + sizeof(struct list_head);
+               fc_host_post_vendor_event(shost, fc_get_event_number(),
+                               sizeof(struct bfa_aen_entry_s) -
+                               sizeof(struct list_head),
+                               (char *)event_data, BFAD_NL_VENDOR_ID);
+               spin_lock_irqsave(&bfad->bfad_aen_spinlock, flags);
+               list_add_tail(&aen_entry->qe, &bfad->free_aen_q);
+               spin_unlock_irqrestore(&bfad->bfad_aen_spinlock, flags);
+       }
+}
+
 bfa_status_t
 bfad_im_probe(struct bfad_s *bfad)
 {
@@ -676,6 +701,7 @@ bfad_im_probe(struct bfad_s *bfad)
                rc = BFA_STATUS_FAILED;
        }
 
+       INIT_WORK(&im->aen_im_notify_work, bfad_aen_im_notify_handler);
 ext:
        return rc;
 }
index 4fe34d5..004b6cf 100644 (file)
@@ -115,8 +115,30 @@ struct bfad_im_s {
        struct bfad_s         *bfad;
        struct workqueue_struct *drv_workq;
        char            drv_workq_name[KOBJ_NAME_LEN];
+       struct work_struct      aen_im_notify_work;
 };
 
+#define bfad_get_aen_entry(_drv, _entry) do {                          \
+       unsigned long   _flags;                                         \
+       spin_lock_irqsave(&(_drv)->bfad_aen_spinlock, _flags);          \
+       bfa_q_deq(&(_drv)->free_aen_q, &(_entry));                      \
+       if (_entry)                                                     \
+               list_add_tail(&(_entry)->qe, &(_drv)->active_aen_q);    \
+       spin_unlock_irqrestore(&(_drv)->bfad_aen_spinlock, _flags);     \
+} while (0)
+
+/* post fc_host vendor event */
+#define bfad_im_post_vendor_event(_entry, _drv, _cnt, _cat, _evt) do {       \
+       do_gettimeofday(&(_entry)->aen_tv);                                   \
+       (_entry)->bfad_num = (_drv)->inst_no;                                 \
+       (_entry)->seq_num = (_cnt);                                           \
+       (_entry)->aen_category = (_cat);                                      \
+       (_entry)->aen_type = (_evt);                                          \
+       if ((_drv)->bfad_flags & BFAD_FC4_PROBE_DONE)                         \
+               queue_work((_drv)->im->drv_workq,                             \
+                          &(_drv)->im->aen_im_notify_work);                  \
+} while (0)
+
 struct Scsi_Host *bfad_scsi_host_alloc(struct bfad_im_port_s *im_port,
                                struct bfad_s *);
 bfa_status_t bfad_thread_workq(struct bfad_s *bfad);
index 1e258d5..b2ba0b2 100644 (file)
@@ -783,6 +783,17 @@ enum bfi_sfp_i2h_e {
        BFI_SFP_I2H_SCN  = BFA_I2HM(BFI_SFP_H2I_SCN),
 };
 
+/*
+ *     SFP state change notification
+ */
+struct bfi_sfp_scn_s {
+       struct bfi_mhdr_s mhr;  /* host msg header        */
+       u8      event;
+       u8      sfpid;
+       u8      pomlvl; /* pom level: normal/warning/alarm */
+       u8      is_elb; /* e-loopback */
+};
+
 /*
  *     SFP state
  */
@@ -925,6 +936,15 @@ struct bfi_flash_erase_rsp_s {
        u32     status;
 };
 
+/*
+ * Flash event notification
+ */
+struct bfi_flash_event_s {
+       struct bfi_mhdr_s       mh;     /* Common msg header */
+       bfa_status_t            status;
+       u32                     param;
+};
+
 /*
  *----------------------------------------------------------------------
  *                             DIAG
index 6a38080..cfcad8b 100644 (file)
@@ -2,7 +2,8 @@ config SCSI_BNX2X_FCOE
        tristate "Broadcom NetXtreme II FCoE support"
        depends on PCI
        select NETDEVICES
-       select NETDEV_1000
+       select ETHERNET
+       select NET_VENDOR_BROADCOM
        select LIBFC
        select LIBFCOE
        select CNIC
index d924236..dd335a2 100644 (file)
@@ -2,7 +2,7 @@
 #define _BNX2FC_H_
 /* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver.
  *
- * Copyright (c) 2008 - 2010 Broadcom Corporation
+ * Copyright (c) 2008 - 2011 Broadcom 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
 
 #include "57xx_hsi_bnx2fc.h"
 #include "bnx2fc_debug.h"
-#include "../../net/cnic_if.h"
+#include "../../net/ethernet/broadcom/cnic_if.h"
 #include "bnx2fc_constants.h"
 
 #define BNX2FC_NAME            "bnx2fc"
-#define BNX2FC_VERSION         "1.0.3"
+#define BNX2FC_VERSION         "1.0.4"
 
 #define PFX                    "bnx2fc: "
 
@@ -81,7 +81,7 @@
 #define BNX2FC_RQ_WQES_MAX     16
 #define BNX2FC_CQ_WQES_MAX     (BNX2FC_SQ_WQES_MAX + BNX2FC_RQ_WQES_MAX)
 
-#define BNX2FC_NUM_MAX_SESS    128
+#define BNX2FC_NUM_MAX_SESS    1024
 #define BNX2FC_NUM_MAX_SESS_LOG        (ilog2(BNX2FC_NUM_MAX_SESS))
 
 #define BNX2FC_MAX_OUTSTANDING_CMNDS   2048
 
 #define BNX2FC_RNID_HBA                        0x7
 
+#define SRR_RETRY_COUNT                        5
+#define REC_RETRY_COUNT                        1
+#define BNX2FC_NUM_ERR_BITS            63
+
 /* bnx2fc driver uses only one instance of fcoe_percpu_s */
 extern struct fcoe_percpu_s bnx2fc_global;
 
@@ -153,18 +157,13 @@ struct bnx2fc_percpu_s {
 };
 
 struct bnx2fc_hba {
-       struct list_head link;
+       struct list_head list;
        struct cnic_dev *cnic;
        struct pci_dev *pcidev;
-       struct net_device *netdev;
        struct net_device *phys_dev;
        unsigned long reg_with_cnic;
                #define BNX2FC_CNIC_REGISTERED           1
-       struct packet_type fcoe_packet_type;
-       struct packet_type fip_packet_type;
        struct bnx2fc_cmd_mgr *cmd_mgr;
-       struct workqueue_struct *timer_work_queue;
-       struct kref kref;
        spinlock_t hba_lock;
        struct mutex hba_mutex;
        unsigned long adapter_state;
@@ -172,15 +171,9 @@ struct bnx2fc_hba {
                #define ADAPTER_STATE_GOING_DOWN        1
                #define ADAPTER_STATE_LINK_DOWN         2
                #define ADAPTER_STATE_READY             3
-       u32 flags;
-       unsigned long init_done;
-               #define BNX2FC_FW_INIT_DONE             0
-               #define BNX2FC_CTLR_INIT_DONE           1
-               #define BNX2FC_CREATE_DONE              2
-       struct fcoe_ctlr ctlr;
-       struct list_head vports;
-       u8 vlan_enabled;
-       int vlan_id;
+       unsigned long flags;
+               #define BNX2FC_FLAG_FW_INIT_DONE        0
+               #define BNX2FC_FLAG_DESTROY_CMPL        1
        u32 next_conn_id;
        struct fcoe_task_ctx_entry **task_ctx;
        dma_addr_t *task_ctx_dma;
@@ -199,38 +192,41 @@ struct bnx2fc_hba {
        char *dummy_buffer;
        dma_addr_t dummy_buf_dma;
 
+       /* Active list of offloaded sessions */
+       struct bnx2fc_rport **tgt_ofld_list;
+
+       /* statistics */
        struct fcoe_statistics_params *stats_buffer;
        dma_addr_t stats_buf_dma;
-
-       /*
-        * PCI related info.
-        */
-       u16 pci_did;
-       u16 pci_vid;
-       u16 pci_sdid;
-       u16 pci_svid;
-       u16 pci_func;
-       u16 pci_devno;
-
-       struct task_struct *l2_thread;
-
-       /* linkdown handling */
-       wait_queue_head_t shutdown_wait;
-       int wait_for_link_down;
+       struct completion stat_req_done;
 
        /*destroy handling */
        struct timer_list destroy_timer;
        wait_queue_head_t destroy_wait;
 
-       /* Active list of offloaded sessions */
-       struct bnx2fc_rport *tgt_ofld_list[BNX2FC_NUM_MAX_SESS];
+       /* linkdown handling */
+       wait_queue_head_t shutdown_wait;
+       int wait_for_link_down;
        int num_ofld_sess;
+       struct list_head vports;
+};
 
-       /* statistics */
-       struct completion stat_req_done;
+struct bnx2fc_interface {
+       struct list_head list;
+       unsigned long if_flags;
+               #define BNX2FC_CTLR_INIT_DONE           0
+       struct bnx2fc_hba *hba;
+       struct net_device *netdev;
+       struct packet_type fcoe_packet_type;
+       struct packet_type fip_packet_type;
+       struct workqueue_struct *timer_work_queue;
+       struct kref kref;
+       struct fcoe_ctlr ctlr;
+       u8 vlan_enabled;
+       int vlan_id;
 };
 
-#define bnx2fc_from_ctlr(fip) container_of(fip, struct bnx2fc_hba, ctlr)
+#define bnx2fc_from_ctlr(fip) container_of(fip, struct bnx2fc_interface, ctlr)
 
 struct bnx2fc_lport {
        struct list_head list;
@@ -252,9 +248,11 @@ struct bnx2fc_rport {
        struct fc_rport_priv *rdata;
        void __iomem *ctx_base;
 #define DPM_TRIGER_TYPE                0x40
+       u32 io_timeout;
        u32 fcoe_conn_id;
        u32 context_id;
        u32 sid;
+       int dev_type;
 
        unsigned long flags;
 #define BNX2FC_FLAG_SESSION_READY      0x1
@@ -262,10 +260,9 @@ struct bnx2fc_rport {
 #define BNX2FC_FLAG_DISABLED           0x3
 #define BNX2FC_FLAG_DESTROYED          0x4
 #define BNX2FC_FLAG_OFLD_REQ_CMPL      0x5
-#define BNX2FC_FLAG_DESTROY_CMPL       0x6
-#define BNX2FC_FLAG_CTX_ALLOC_FAILURE  0x7
-#define BNX2FC_FLAG_UPLD_REQ_COMPL     0x8
-#define BNX2FC_FLAG_EXPL_LOGO          0x9
+#define BNX2FC_FLAG_CTX_ALLOC_FAILURE  0x6
+#define BNX2FC_FLAG_UPLD_REQ_COMPL     0x7
+#define BNX2FC_FLAG_EXPL_LOGO          0x8
 
        u8 src_addr[ETH_ALEN];
        u32 max_sqes;
@@ -327,12 +324,9 @@ struct bnx2fc_rport {
        spinlock_t cq_lock;
        atomic_t num_active_ios;
        u32 flush_in_prog;
-       unsigned long work_time_slice;
        unsigned long timestamp;
        struct list_head free_task_list;
        struct bnx2fc_cmd *pending_queue[BNX2FC_SQ_WQES_MAX+1];
-       atomic_t pi;
-       atomic_t ci;
        struct list_head active_cmd_queue;
        struct list_head els_queue;
        struct list_head io_retire_queue;
@@ -367,6 +361,8 @@ struct bnx2fc_els_cb_arg {
        struct bnx2fc_cmd *aborted_io_req;
        struct bnx2fc_cmd *io_req;
        u16 l2_oxid;
+       u32 offset;
+       enum fc_rctl r_ctl;
 };
 
 /* bnx2fc command structure */
@@ -380,6 +376,7 @@ struct bnx2fc_cmd {
 #define BNX2FC_ABTS                    3
 #define BNX2FC_ELS                     4
 #define BNX2FC_CLEANUP                 5
+#define BNX2FC_SEQ_CLEANUP             6
        u8 io_req_flags;
        struct kref refcount;
        struct fcoe_port *port;
@@ -393,6 +390,7 @@ struct bnx2fc_cmd {
        struct completion tm_done;
        int wait_for_comp;
        u16 xid;
+       struct fcoe_err_report_entry err_entry;
        struct fcoe_task_ctx_entry *task;
        struct io_bdt *bd_tbl;
        struct fcp_rsp *rsp;
@@ -409,6 +407,12 @@ struct bnx2fc_cmd {
 #define BNX2FC_FLAG_IO_COMPL           0x9
 #define BNX2FC_FLAG_ELS_DONE           0xa
 #define BNX2FC_FLAG_ELS_TIMEOUT                0xb
+#define BNX2FC_FLAG_CMD_LOST           0xc
+#define BNX2FC_FLAG_SRR_SENT           0xd
+       u8 rec_retry;
+       u8 srr_retry;
+       u32 srr_offset;
+       u8 srr_rctl;
        u32 fcp_resid;
        u32 fcp_rsp_len;
        u32 fcp_sns_len;
@@ -439,6 +443,7 @@ struct bnx2fc_unsol_els {
 
 
 
+struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt);
 struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type);
 void bnx2fc_cmd_release(struct kref *ref);
 int bnx2fc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd);
@@ -476,6 +481,10 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req);
 void bnx2fc_init_cleanup_task(struct bnx2fc_cmd *io_req,
                              struct fcoe_task_ctx_entry *task,
                              u16 orig_xid);
+void bnx2fc_init_seq_cleanup_task(struct bnx2fc_cmd *seq_clnup_req,
+                                 struct fcoe_task_ctx_entry *task,
+                                 struct bnx2fc_cmd *orig_io_req,
+                                 u32 offset);
 void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
                         struct fcoe_task_ctx_entry *task);
 void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
@@ -525,5 +534,13 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
                                   unsigned char *buf,
                                   u32 frame_len, u16 l2_oxid);
 int bnx2fc_send_stat_req(struct bnx2fc_hba *hba);
+int bnx2fc_post_io_req(struct bnx2fc_rport *tgt, struct bnx2fc_cmd *io_req);
+int bnx2fc_send_rec(struct bnx2fc_cmd *orig_io_req);
+int bnx2fc_send_srr(struct bnx2fc_cmd *orig_io_req, u32 offset, u8 r_ctl);
+void bnx2fc_process_seq_cleanup_compl(struct bnx2fc_cmd *seq_clnup_req,
+                                     struct fcoe_task_ctx_entry *task,
+                                     u8 rx_state);
+int bnx2fc_initiate_seq_cleanup(struct bnx2fc_cmd *orig_io_req, u32 offset,
+                               enum fc_rctl r_ctl);
 
 #endif
index 7f6aff6..3416d9a 100644 (file)
@@ -21,21 +21,21 @@ extern unsigned int bnx2fc_debug_level;
 
 #define BNX2FC_ELS_DBG(fmt, arg...)                                    \
        BNX2FC_CHK_LOGGING(LOG_ELS,                                     \
-                          printk(KERN_ALERT PFX fmt, ##arg))
+                          printk(KERN_INFO PFX fmt, ##arg))
 
 #define BNX2FC_MISC_DBG(fmt, arg...)                                   \
        BNX2FC_CHK_LOGGING(LOG_MISC,                                    \
-                          printk(KERN_ALERT PFX fmt, ##arg))
+                          printk(KERN_INFO PFX fmt, ##arg))
 
 #define BNX2FC_IO_DBG(io_req, fmt, arg...)                             \
        do {                                                            \
                if (!io_req || !io_req->port || !io_req->port->lport || \
                    !io_req->port->lport->host)                         \
                        BNX2FC_CHK_LOGGING(LOG_IO,                      \
-                          printk(KERN_ALERT PFX "NULL " fmt, ##arg));  \
+                          printk(KERN_INFO PFX "NULL " fmt, ##arg));   \
                else                                                    \
                        BNX2FC_CHK_LOGGING(LOG_IO,                      \
-                          shost_printk(KERN_ALERT,                     \
+                          shost_printk(KERN_INFO,                      \
                                   (io_req)->port->lport->host,         \
                                   PFX "xid:0x%x " fmt,                 \
                                   (io_req)->xid, ##arg));              \
@@ -46,10 +46,10 @@ extern unsigned int bnx2fc_debug_level;
                if (!tgt || !tgt->port || !tgt->port->lport ||          \
                    !tgt->port->lport->host || !tgt->rport)             \
                        BNX2FC_CHK_LOGGING(LOG_TGT,                     \
-                          printk(KERN_ALERT PFX "NULL " fmt, ##arg));  \
+                          printk(KERN_INFO PFX "NULL " fmt, ##arg));   \
                else                                                    \
                        BNX2FC_CHK_LOGGING(LOG_TGT,                     \
-                          shost_printk(KERN_ALERT,                     \
+                          shost_printk(KERN_INFO,                      \
                                   (tgt)->port->lport->host,            \
                                   PFX "port:%x " fmt,                  \
                                   (tgt)->rport->port_id, ##arg));      \
@@ -60,10 +60,10 @@ extern unsigned int bnx2fc_debug_level;
        do {                                                            \
                if (!lport || !lport->host)                             \
                        BNX2FC_CHK_LOGGING(LOG_HBA,                     \
-                          printk(KERN_ALERT PFX "NULL " fmt, ##arg));  \
+                          printk(KERN_INFO PFX "NULL " fmt, ##arg));   \
                else                                                    \
                        BNX2FC_CHK_LOGGING(LOG_HBA,                     \
-                          shost_printk(KERN_ALERT, lport->host,        \
+                          shost_printk(KERN_INFO, lport->host, \
                                   PFX fmt, ##arg));                    \
        } while (0)
 
index 7e89143..d66dcbd 100644 (file)
@@ -3,7 +3,7 @@
  * This file contains helper routines that handle ELS requests
  * and responses.
  *
- * Copyright (c) 2008 - 2010 Broadcom Corporation
+ * Copyright (c) 2008 - 2011 Broadcom 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
@@ -253,13 +253,417 @@ int bnx2fc_send_rls(struct bnx2fc_rport *tgt, struct fc_frame *fp)
        return rc;
 }
 
+void bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg)
+{
+       struct bnx2fc_mp_req *mp_req;
+       struct fc_frame_header *fc_hdr, *fh;
+       struct bnx2fc_cmd *srr_req;
+       struct bnx2fc_cmd *orig_io_req;
+       struct fc_frame *fp;
+       unsigned char *buf;
+       void *resp_buf;
+       u32 resp_len, hdr_len;
+       u8 opcode;
+       int rc = 0;
+
+       orig_io_req = cb_arg->aborted_io_req;
+       srr_req = cb_arg->io_req;
+       if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags)) {
+               BNX2FC_IO_DBG(srr_req, "srr_compl: xid - 0x%x completed",
+                       orig_io_req->xid);
+               goto srr_compl_done;
+       }
+       if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
+               BNX2FC_IO_DBG(srr_req, "rec abts in prog "
+                      "orig_io - 0x%x\n",
+                       orig_io_req->xid);
+               goto srr_compl_done;
+       }
+       if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &srr_req->req_flags)) {
+               /* SRR timedout */
+               BNX2FC_IO_DBG(srr_req, "srr timed out, abort "
+                      "orig_io - 0x%x\n",
+                       orig_io_req->xid);
+               rc = bnx2fc_initiate_abts(srr_req);
+               if (rc != SUCCESS) {
+                       BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts "
+                               "failed. issue cleanup\n");
+                       bnx2fc_initiate_cleanup(srr_req);
+               }
+               orig_io_req->srr_retry++;
+               if (orig_io_req->srr_retry <= SRR_RETRY_COUNT) {
+                       struct bnx2fc_rport *tgt = orig_io_req->tgt;
+                       spin_unlock_bh(&tgt->tgt_lock);
+                       rc = bnx2fc_send_srr(orig_io_req,
+                                            orig_io_req->srr_offset,
+                                            orig_io_req->srr_rctl);
+                       spin_lock_bh(&tgt->tgt_lock);
+                       if (!rc)
+                               goto srr_compl_done;
+               }
+
+               rc = bnx2fc_initiate_abts(orig_io_req);
+               if (rc != SUCCESS) {
+                       BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts "
+                               "failed xid = 0x%x. issue cleanup\n",
+                               orig_io_req->xid);
+                       bnx2fc_initiate_cleanup(orig_io_req);
+               }
+               goto srr_compl_done;
+       }
+       mp_req = &(srr_req->mp_req);
+       fc_hdr = &(mp_req->resp_fc_hdr);
+       resp_len = mp_req->resp_len;
+       resp_buf = mp_req->resp_buf;
+
+       hdr_len = sizeof(*fc_hdr);
+       buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+       if (!buf) {
+               printk(KERN_ERR PFX "srr buf: mem alloc failure\n");
+               goto srr_compl_done;
+       }
+       memcpy(buf, fc_hdr, hdr_len);
+       memcpy(buf + hdr_len, resp_buf, resp_len);
+
+       fp = fc_frame_alloc(NULL, resp_len);
+       if (!fp) {
+               printk(KERN_ERR PFX "fc_frame_alloc failure\n");
+               goto free_buf;
+       }
+
+       fh = (struct fc_frame_header *) fc_frame_header_get(fp);
+       /* Copy FC Frame header and payload into the frame */
+       memcpy(fh, buf, hdr_len + resp_len);
+
+       opcode = fc_frame_payload_op(fp);
+       switch (opcode) {
+       case ELS_LS_ACC:
+               BNX2FC_IO_DBG(srr_req, "SRR success\n");
+               break;
+       case ELS_LS_RJT:
+               BNX2FC_IO_DBG(srr_req, "SRR rejected\n");
+               rc = bnx2fc_initiate_abts(orig_io_req);
+               if (rc != SUCCESS) {
+                       BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts "
+                               "failed xid = 0x%x. issue cleanup\n",
+                               orig_io_req->xid);
+                       bnx2fc_initiate_cleanup(orig_io_req);
+               }
+               break;
+       default:
+               BNX2FC_IO_DBG(srr_req, "srr compl - invalid opcode = %d\n",
+                       opcode);
+               break;
+       }
+       fc_frame_free(fp);
+free_buf:
+       kfree(buf);
+srr_compl_done:
+       kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
+}
+
+void bnx2fc_rec_compl(struct bnx2fc_els_cb_arg *cb_arg)
+{
+       struct bnx2fc_cmd *orig_io_req, *new_io_req;
+       struct bnx2fc_cmd *rec_req;
+       struct bnx2fc_mp_req *mp_req;
+       struct fc_frame_header *fc_hdr, *fh;
+       struct fc_els_ls_rjt *rjt;
+       struct fc_els_rec_acc *acc;
+       struct bnx2fc_rport *tgt;
+       struct fcoe_err_report_entry *err_entry;
+       struct scsi_cmnd *sc_cmd;
+       enum fc_rctl r_ctl;
+       unsigned char *buf;
+       void *resp_buf;
+       struct fc_frame *fp;
+       u8 opcode;
+       u32 offset;
+       u32 e_stat;
+       u32 resp_len, hdr_len;
+       int rc = 0;
+       bool send_seq_clnp = false;
+       bool abort_io = false;
+
+       BNX2FC_MISC_DBG("Entered rec_compl callback\n");
+       rec_req = cb_arg->io_req;
+       orig_io_req = cb_arg->aborted_io_req;
+       BNX2FC_IO_DBG(rec_req, "rec_compl: orig xid = 0x%x", orig_io_req->xid);
+       tgt = orig_io_req->tgt;
+
+       if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags)) {
+               BNX2FC_IO_DBG(rec_req, "completed"
+                      "orig_io - 0x%x\n",
+                       orig_io_req->xid);
+               goto rec_compl_done;
+       }
+       if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
+               BNX2FC_IO_DBG(rec_req, "abts in prog "
+                      "orig_io - 0x%x\n",
+                       orig_io_req->xid);
+               goto rec_compl_done;
+       }
+       /* Handle REC timeout case */
+       if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &rec_req->req_flags)) {
+               BNX2FC_IO_DBG(rec_req, "timed out, abort "
+                      "orig_io - 0x%x\n",
+                       orig_io_req->xid);
+               /* els req is timed out. send abts for els */
+               rc = bnx2fc_initiate_abts(rec_req);
+               if (rc != SUCCESS) {
+                       BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts "
+                               "failed. issue cleanup\n");
+                       bnx2fc_initiate_cleanup(rec_req);
+               }
+               orig_io_req->rec_retry++;
+               /* REC timedout. send ABTS to the orig IO req */
+               if (orig_io_req->rec_retry <= REC_RETRY_COUNT) {
+                       spin_unlock_bh(&tgt->tgt_lock);
+                       rc = bnx2fc_send_rec(orig_io_req);
+                       spin_lock_bh(&tgt->tgt_lock);
+                       if (!rc)
+                               goto rec_compl_done;
+               }
+               rc = bnx2fc_initiate_abts(orig_io_req);
+               if (rc != SUCCESS) {
+                       BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts "
+                               "failed xid = 0x%x. issue cleanup\n",
+                               orig_io_req->xid);
+                       bnx2fc_initiate_cleanup(orig_io_req);
+               }
+               goto rec_compl_done;
+       }
+       mp_req = &(rec_req->mp_req);
+       fc_hdr = &(mp_req->resp_fc_hdr);
+       resp_len = mp_req->resp_len;
+       acc = resp_buf = mp_req->resp_buf;
+
+       hdr_len = sizeof(*fc_hdr);
+
+       buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+       if (!buf) {
+               printk(KERN_ERR PFX "rec buf: mem alloc failure\n");
+               goto rec_compl_done;
+       }
+       memcpy(buf, fc_hdr, hdr_len);
+       memcpy(buf + hdr_len, resp_buf, resp_len);
+
+       fp = fc_frame_alloc(NULL, resp_len);
+       if (!fp) {
+               printk(KERN_ERR PFX "fc_frame_alloc failure\n");
+               goto free_buf;
+       }
+
+       fh = (struct fc_frame_header *) fc_frame_header_get(fp);
+       /* Copy FC Frame header and payload into the frame */
+       memcpy(fh, buf, hdr_len + resp_len);
+
+       opcode = fc_frame_payload_op(fp);
+       if (opcode == ELS_LS_RJT) {
+               BNX2FC_IO_DBG(rec_req, "opcode is RJT\n");
+               rjt = fc_frame_payload_get(fp, sizeof(*rjt));
+               if ((rjt->er_reason == ELS_RJT_LOGIC ||
+                   rjt->er_reason == ELS_RJT_UNAB) &&
+                   rjt->er_explan == ELS_EXPL_OXID_RXID) {
+                       BNX2FC_IO_DBG(rec_req, "handle CMD LOST case\n");
+                       new_io_req = bnx2fc_cmd_alloc(tgt);
+                       if (!new_io_req)
+                               goto abort_io;
+                       new_io_req->sc_cmd = orig_io_req->sc_cmd;
+                       /* cleanup orig_io_req that is with the FW */
+                       set_bit(BNX2FC_FLAG_CMD_LOST,
+                               &orig_io_req->req_flags);
+                       bnx2fc_initiate_cleanup(orig_io_req);
+                       /* Post a new IO req with the same sc_cmd */
+                       BNX2FC_IO_DBG(rec_req, "Post IO request again\n");
+                       spin_unlock_bh(&tgt->tgt_lock);
+                       rc = bnx2fc_post_io_req(tgt, new_io_req);
+                       spin_lock_bh(&tgt->tgt_lock);
+                       if (!rc)
+                               goto free_frame;
+                       BNX2FC_IO_DBG(rec_req, "REC: io post err\n");
+               }
+abort_io:
+               rc = bnx2fc_initiate_abts(orig_io_req);
+               if (rc != SUCCESS) {
+                       BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts "
+                               "failed. issue cleanup\n");
+                       bnx2fc_initiate_cleanup(orig_io_req);
+               }
+       } else if (opcode == ELS_LS_ACC) {
+               /* REVISIT: Check if the exchange is already aborted */
+               offset = ntohl(acc->reca_fc4value);
+               e_stat = ntohl(acc->reca_e_stat);
+               if (e_stat & ESB_ST_SEQ_INIT)  {
+                       BNX2FC_IO_DBG(rec_req, "target has the seq init\n");
+                       goto free_frame;
+               }
+               BNX2FC_IO_DBG(rec_req, "e_stat = 0x%x, offset = 0x%x\n",
+                       e_stat, offset);
+               /* Seq initiative is with us */
+               err_entry = (struct fcoe_err_report_entry *)
+                            &orig_io_req->err_entry;
+               sc_cmd = orig_io_req->sc_cmd;
+               if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) {
+                       /* SCSI WRITE command */
+                       if (offset == orig_io_req->data_xfer_len) {
+                               BNX2FC_IO_DBG(rec_req, "WRITE - resp lost\n");
+                               /* FCP_RSP lost */
+                               r_ctl = FC_RCTL_DD_CMD_STATUS;
+                               offset = 0;
+                       } else  {
+                               /* start transmitting from offset */
+                               BNX2FC_IO_DBG(rec_req, "XFER_RDY/DATA lost\n");
+                               send_seq_clnp = true;
+                               r_ctl = FC_RCTL_DD_DATA_DESC;
+                               if (bnx2fc_initiate_seq_cleanup(orig_io_req,
+                                                               offset, r_ctl))
+                                       abort_io = true;
+                               /* XFER_RDY */
+                       }
+               } else {
+                       /* SCSI READ command */
+                       if (err_entry->data.rx_buf_off ==
+                                       orig_io_req->data_xfer_len) {
+                               /* FCP_RSP lost */
+                               BNX2FC_IO_DBG(rec_req, "READ - resp lost\n");
+                               r_ctl = FC_RCTL_DD_CMD_STATUS;
+                               offset = 0;
+                       } else  {
+                               /* request retransmission from this offset */
+                               send_seq_clnp = true;
+                               offset = err_entry->data.rx_buf_off;
+                               BNX2FC_IO_DBG(rec_req, "RD DATA lost\n");
+                               /* FCP_DATA lost */
+                               r_ctl = FC_RCTL_DD_SOL_DATA;
+                               if (bnx2fc_initiate_seq_cleanup(orig_io_req,
+                                                               offset, r_ctl))
+                                       abort_io = true;
+                       }
+               }
+               if (abort_io) {
+                       rc = bnx2fc_initiate_abts(orig_io_req);
+                       if (rc != SUCCESS) {
+                               BNX2FC_IO_DBG(rec_req, "rec_compl:initiate_abts"
+                                             " failed. issue cleanup\n");
+                               bnx2fc_initiate_cleanup(orig_io_req);
+                       }
+               } else if (!send_seq_clnp) {
+                       BNX2FC_IO_DBG(rec_req, "Send SRR - FCP_RSP\n");
+                       spin_unlock_bh(&tgt->tgt_lock);
+                       rc = bnx2fc_send_srr(orig_io_req, offset, r_ctl);
+                       spin_lock_bh(&tgt->tgt_lock);
+
+                       if (rc) {
+                               BNX2FC_IO_DBG(rec_req, "Unable to send SRR"
+                                       " IO will abort\n");
+                       }
+               }
+       }
+free_frame:
+       fc_frame_free(fp);
+free_buf:
+       kfree(buf);
+rec_compl_done:
+       kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
+       kfree(cb_arg);
+}
+
+int bnx2fc_send_rec(struct bnx2fc_cmd *orig_io_req)
+{
+       struct fc_els_rec rec;
+       struct bnx2fc_rport *tgt = orig_io_req->tgt;
+       struct fc_lport *lport = tgt->rdata->local_port;
+       struct bnx2fc_els_cb_arg *cb_arg = NULL;
+       u32 sid = tgt->sid;
+       u32 r_a_tov = lport->r_a_tov;
+       int rc;
+
+       BNX2FC_IO_DBG(orig_io_req, "Sending REC\n");
+       memset(&rec, 0, sizeof(rec));
+
+       cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
+       if (!cb_arg) {
+               printk(KERN_ERR PFX "Unable to allocate cb_arg for REC\n");
+               rc = -ENOMEM;
+               goto rec_err;
+       }
+       kref_get(&orig_io_req->refcount);
+
+       cb_arg->aborted_io_req = orig_io_req;
+
+       rec.rec_cmd = ELS_REC;
+       hton24(rec.rec_s_id, sid);
+       rec.rec_ox_id = htons(orig_io_req->xid);
+       rec.rec_rx_id = htons(orig_io_req->task->rxwr_txrd.var_ctx.rx_id);
+
+       rc = bnx2fc_initiate_els(tgt, ELS_REC, &rec, sizeof(rec),
+                                bnx2fc_rec_compl, cb_arg,
+                                r_a_tov);
+rec_err:
+       if (rc) {
+               BNX2FC_IO_DBG(orig_io_req, "REC failed - release\n");
+               spin_lock_bh(&tgt->tgt_lock);
+               kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
+               spin_unlock_bh(&tgt->tgt_lock);
+               kfree(cb_arg);
+       }
+       return rc;
+}
+
+int bnx2fc_send_srr(struct bnx2fc_cmd *orig_io_req, u32 offset, u8 r_ctl)
+{
+       struct fcp_srr srr;
+       struct bnx2fc_rport *tgt = orig_io_req->tgt;
+       struct fc_lport *lport = tgt->rdata->local_port;
+       struct bnx2fc_els_cb_arg *cb_arg = NULL;
+       u32 r_a_tov = lport->r_a_tov;
+       int rc;
+
+       BNX2FC_IO_DBG(orig_io_req, "Sending SRR\n");
+       memset(&srr, 0, sizeof(srr));
+
+       cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
+       if (!cb_arg) {
+               printk(KERN_ERR PFX "Unable to allocate cb_arg for SRR\n");
+               rc = -ENOMEM;
+               goto srr_err;
+       }
+       kref_get(&orig_io_req->refcount);
+
+       cb_arg->aborted_io_req = orig_io_req;
+
+       srr.srr_op = ELS_SRR;
+       srr.srr_ox_id = htons(orig_io_req->xid);
+       srr.srr_rx_id = htons(orig_io_req->task->rxwr_txrd.var_ctx.rx_id);
+       srr.srr_rel_off = htonl(offset);
+       srr.srr_r_ctl = r_ctl;
+       orig_io_req->srr_offset = offset;
+       orig_io_req->srr_rctl = r_ctl;
+
+       rc = bnx2fc_initiate_els(tgt, ELS_SRR, &srr, sizeof(srr),
+                                bnx2fc_srr_compl, cb_arg,
+                                r_a_tov);
+srr_err:
+       if (rc) {
+               BNX2FC_IO_DBG(orig_io_req, "SRR failed - release\n");
+               spin_lock_bh(&tgt->tgt_lock);
+               kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
+               spin_unlock_bh(&tgt->tgt_lock);
+               kfree(cb_arg);
+       } else
+               set_bit(BNX2FC_FLAG_SRR_SENT, &orig_io_req->req_flags);
+
+       return rc;
+}
+
 static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
                        void *data, u32 data_len,
                        void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
                        struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec)
 {
        struct fcoe_port *port = tgt->port;
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
        struct fc_rport *rport = tgt->rport;
        struct fc_lport *lport = port->lport;
        struct bnx2fc_cmd *els_req;
@@ -274,12 +678,12 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
 
        rc = fc_remote_port_chkready(rport);
        if (rc) {
-               printk(KERN_ALERT PFX "els 0x%x: rport not ready\n", op);
+               printk(KERN_ERR PFX "els 0x%x: rport not ready\n", op);
                rc = -EINVAL;
                goto els_err;
        }
        if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
-               printk(KERN_ALERT PFX "els 0x%x: link is not ready\n", op);
+               printk(KERN_ERR PFX "els 0x%x: link is not ready\n", op);
                rc = -EINVAL;
                goto els_err;
        }
@@ -305,7 +709,7 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
        mp_req = (struct bnx2fc_mp_req *)&(els_req->mp_req);
        rc = bnx2fc_init_mp_req(els_req);
        if (rc == FAILED) {
-               printk(KERN_ALERT PFX "ELS MP request init failed\n");
+               printk(KERN_ERR PFX "ELS MP request init failed\n");
                spin_lock_bh(&tgt->tgt_lock);
                kref_put(&els_req->refcount, bnx2fc_cmd_release);
                spin_unlock_bh(&tgt->tgt_lock);
@@ -324,7 +728,7 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
        if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS)) {
                memcpy(mp_req->req_buf, data, data_len);
        } else {
-               printk(KERN_ALERT PFX "Invalid ELS op 0x%x\n", op);
+               printk(KERN_ERR PFX "Invalid ELS op 0x%x\n", op);
                els_req->cb_func = NULL;
                els_req->cb_arg = NULL;
                spin_lock_bh(&tgt->tgt_lock);
@@ -342,9 +746,14 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
        did = tgt->rport->port_id;
        sid = tgt->sid;
 
-       __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid,
-                          FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
-                          FC_FC_SEQ_INIT, 0);
+       if (op == ELS_SRR)
+               __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS4_REQ, did, sid,
+                                  FC_TYPE_FCP, FC_FC_FIRST_SEQ |
+                                  FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
+       else
+               __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid,
+                                  FC_TYPE_ELS, FC_FC_FIRST_SEQ |
+                                  FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
 
        /* Obtain exchange id */
        xid = els_req->xid;
@@ -352,7 +761,8 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
        index = xid % BNX2FC_TASKS_PER_PAGE;
 
        /* Initialize task context for this IO request */
-       task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+       task_page = (struct fcoe_task_ctx_entry *)
+                       interface->hba->task_ctx[task_idx];
        task = &(task_page[index]);
        bnx2fc_init_mp_task(els_req, task);
 
@@ -496,8 +906,8 @@ struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
                                      void *arg, u32 timeout)
 {
        struct fcoe_port *port = lport_priv(lport);
-       struct bnx2fc_hba *hba = port->priv;
-       struct fcoe_ctlr *fip = &hba->ctlr;
+       struct bnx2fc_interface *interface = port->priv;
+       struct fcoe_ctlr *fip = &interface->ctlr;
        struct fc_frame_header *fh = fc_frame_header_get(fp);
 
        switch (op) {
index a97aff3..2c780a7 100644 (file)
@@ -3,7 +3,7 @@
  * cnic modules to create FCoE instances, send/receive non-offloaded
  * FIP/FCoE packets, listen to link events etc.
  *
- * Copyright (c) 2008 - 2010 Broadcom Corporation
+ * Copyright (c) 2008 - 2011 Broadcom 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
 #include "bnx2fc.h"
 
 static struct list_head adapter_list;
+static struct list_head if_list;
 static u32 adapter_count;
 static DEFINE_MUTEX(bnx2fc_dev_lock);
 DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
 
 #define DRV_MODULE_NAME                "bnx2fc"
 #define DRV_MODULE_VERSION     BNX2FC_VERSION
-#define DRV_MODULE_RELDATE     "Jun 10, 2011"
+#define DRV_MODULE_RELDATE     "Jun 23, 2011"
 
 
 static char version[] __devinitdata =
@@ -61,7 +62,7 @@ static int bnx2fc_disable(struct net_device *netdev);
 
 static void bnx2fc_recv_frame(struct sk_buff *skb);
 
-static void bnx2fc_start_disc(struct bnx2fc_hba *hba);
+static void bnx2fc_start_disc(struct bnx2fc_interface *interface);
 static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev);
 static int bnx2fc_net_config(struct fc_lport *lp);
 static int bnx2fc_lport_config(struct fc_lport *lport);
@@ -70,18 +71,20 @@ static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba);
 static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba);
 static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba);
 static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba);
-static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
+static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
                                  struct device *parent, int npiv);
 static void bnx2fc_destroy_work(struct work_struct *work);
 
 static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev);
+static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device
+                                                       *phys_dev);
 static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic);
 
 static int bnx2fc_fw_init(struct bnx2fc_hba *hba);
 static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba);
 
 static void bnx2fc_port_shutdown(struct fc_lport *lport);
-static void bnx2fc_stop(struct bnx2fc_hba *hba);
+static void bnx2fc_stop(struct bnx2fc_interface *interface);
 static int __init bnx2fc_mod_init(void);
 static void __exit bnx2fc_mod_exit(void);
 
@@ -142,7 +145,8 @@ static void bnx2fc_abort_io(struct fc_lport *lport)
 static void bnx2fc_cleanup(struct fc_lport *lport)
 {
        struct fcoe_port *port = lport_priv(lport);
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        struct bnx2fc_rport *tgt;
        int i;
 
@@ -219,7 +223,8 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
        struct fcoe_crc_eof     *cp;
        struct sk_buff          *skb;
        struct fc_frame_header  *fh;
-       struct bnx2fc_hba       *hba;
+       struct bnx2fc_interface *interface;
+       struct bnx2fc_hba *hba;
        struct fcoe_port        *port;
        struct fcoe_hdr         *hp;
        struct bnx2fc_rport     *tgt;
@@ -230,7 +235,8 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
        int                     wlen, rc = 0;
 
        port = (struct fcoe_port *)lport_priv(lport);
-       hba = port->priv;
+       interface = port->priv;
+       hba = interface->hba;
 
        fh = fc_frame_header_get(fp);
 
@@ -242,12 +248,12 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
        }
 
        if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ)) {
-               if (!hba->ctlr.sel_fcf) {
+               if (!interface->ctlr.sel_fcf) {
                        BNX2FC_HBA_DBG(lport, "FCF not selected yet!\n");
                        kfree_skb(skb);
                        return -EINVAL;
                }
-               if (fcoe_ctlr_els_send(&hba->ctlr, lport, skb))
+               if (fcoe_ctlr_els_send(&interface->ctlr, lport, skb))
                        return 0;
        }
 
@@ -296,7 +302,7 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
                        return -ENOMEM;
                }
                frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
-               cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
+               cp = kmap_atomic(skb_frag_page(frag), KM_SKB_DATA_SOFTIRQ)
                                + frag->page_offset;
        } else {
                cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
@@ -316,19 +322,19 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
        skb_reset_network_header(skb);
        skb->mac_len = elen;
        skb->protocol = htons(ETH_P_FCOE);
-       skb->dev = hba->netdev;
+       skb->dev = interface->netdev;
 
        /* fill up mac and fcoe headers */
        eh = eth_hdr(skb);
        eh->h_proto = htons(ETH_P_FCOE);
-       if (hba->ctlr.map_dest)
+       if (interface->ctlr.map_dest)
                fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id);
        else
                /* insert GW address */
-               memcpy(eh->h_dest, hba->ctlr.dest_addr, ETH_ALEN);
+               memcpy(eh->h_dest, interface->ctlr.dest_addr, ETH_ALEN);
 
-       if (unlikely(hba->ctlr.flogi_oxid != FC_XID_UNKNOWN))
-               memcpy(eh->h_source, hba->ctlr.ctl_src_addr, ETH_ALEN);
+       if (unlikely(interface->ctlr.flogi_oxid != FC_XID_UNKNOWN))
+               memcpy(eh->h_source, interface->ctlr.ctl_src_addr, ETH_ALEN);
        else
                memcpy(eh->h_source, port->data_src_addr, ETH_ALEN);
 
@@ -377,22 +383,23 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev,
                struct packet_type *ptype, struct net_device *olddev)
 {
        struct fc_lport *lport;
-       struct bnx2fc_hba *hba;
+       struct bnx2fc_interface *interface;
        struct fc_frame_header *fh;
        struct fcoe_rcv_info *fr;
        struct fcoe_percpu_s *bg;
        unsigned short oxid;
 
-       hba = container_of(ptype, struct bnx2fc_hba, fcoe_packet_type);
-       lport = hba->ctlr.lp;
+       interface = container_of(ptype, struct bnx2fc_interface,
+                                fcoe_packet_type);
+       lport = interface->ctlr.lp;
 
        if (unlikely(lport == NULL)) {
-               printk(KERN_ALERT PFX "bnx2fc_rcv: lport is NULL\n");
+               printk(KERN_ERR PFX "bnx2fc_rcv: lport is NULL\n");
                goto err;
        }
 
        if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
-               printk(KERN_ALERT PFX "bnx2fc_rcv: Wrong FC type frame\n");
+               printk(KERN_ERR PFX "bnx2fc_rcv: Wrong FC type frame\n");
                goto err;
        }
 
@@ -411,7 +418,6 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev,
 
        fr = fcoe_dev_from_skb(skb);
        fr->fr_dev = lport;
-       fr->ptype = ptype;
 
        bg = &bnx2fc_global;
        spin_lock_bh(&bg->fcoe_rx_list.lock);
@@ -469,7 +475,7 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
        fr = fcoe_dev_from_skb(skb);
        lport = fr->fr_dev;
        if (unlikely(lport == NULL)) {
-               printk(KERN_ALERT PFX "Invalid lport struct\n");
+               printk(KERN_ERR PFX "Invalid lport struct\n");
                kfree_skb(skb);
                return;
        }
@@ -594,7 +600,8 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
        struct fc_host_statistics *bnx2fc_stats;
        struct fc_lport *lport = shost_priv(shost);
        struct fcoe_port *port = lport_priv(lport);
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        struct fcoe_statistics_params *fw_stats;
        int rc = 0;
 
@@ -631,7 +638,7 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
 static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
 {
        struct fcoe_port *port = lport_priv(lport);
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
        struct Scsi_Host *shost = lport->host;
        int rc = 0;
 
@@ -654,7 +661,7 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
                fc_host_max_npiv_vports(lport->host) = USHRT_MAX;
        sprintf(fc_host_symbolic_name(lport->host), "%s v%s over %s",
                BNX2FC_NAME, BNX2FC_VERSION,
-               hba->netdev->name);
+               interface->netdev->name);
 
        return 0;
 }
@@ -662,8 +669,8 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
 static void bnx2fc_link_speed_update(struct fc_lport *lport)
 {
        struct fcoe_port *port = lport_priv(lport);
-       struct bnx2fc_hba *hba = port->priv;
-       struct net_device *netdev = hba->netdev;
+       struct bnx2fc_interface *interface = port->priv;
+       struct net_device *netdev = interface->netdev;
        struct ethtool_cmd ecmd;
 
        if (!dev_ethtool_get_settings(netdev, &ecmd)) {
@@ -691,7 +698,8 @@ static void bnx2fc_link_speed_update(struct fc_lport *lport)
 static int bnx2fc_link_ok(struct fc_lport *lport)
 {
        struct fcoe_port *port = lport_priv(lport);
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        struct net_device *dev = hba->phys_dev;
        int rc = 0;
 
@@ -713,7 +721,7 @@ static int bnx2fc_link_ok(struct fc_lport *lport)
  */
 void bnx2fc_get_link_state(struct bnx2fc_hba *hba)
 {
-       if (test_bit(__LINK_STATE_NOCARRIER, &hba->netdev->state))
+       if (test_bit(__LINK_STATE_NOCARRIER, &hba->phys_dev->state))
                set_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
        else
                clear_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
@@ -722,11 +730,13 @@ void bnx2fc_get_link_state(struct bnx2fc_hba *hba)
 static int bnx2fc_net_config(struct fc_lport *lport)
 {
        struct bnx2fc_hba *hba;
+       struct bnx2fc_interface *interface;
        struct fcoe_port *port;
        u64 wwnn, wwpn;
 
        port = lport_priv(lport);
-       hba = port->priv;
+       interface = port->priv;
+       hba = interface->hba;
 
        /* require support for get_pauseparam ethtool op. */
        if (!hba->phys_dev->ethtool_ops ||
@@ -743,11 +753,11 @@ static int bnx2fc_net_config(struct fc_lport *lport)
        bnx2fc_link_speed_update(lport);
 
        if (!lport->vport) {
-               wwnn = fcoe_wwn_from_mac(hba->ctlr.ctl_src_addr, 1, 0);
+               wwnn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr, 1, 0);
                BNX2FC_HBA_DBG(lport, "WWNN = 0x%llx\n", wwnn);
                fc_set_wwnn(lport, wwnn);
 
-               wwpn = fcoe_wwn_from_mac(hba->ctlr.ctl_src_addr, 2, 0);
+               wwpn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr, 2, 0);
                BNX2FC_HBA_DBG(lport, "WWPN = 0x%llx\n", wwpn);
                fc_set_wwpn(lport, wwpn);
        }
@@ -759,9 +769,9 @@ static void bnx2fc_destroy_timer(unsigned long data)
 {
        struct bnx2fc_hba *hba = (struct bnx2fc_hba *)data;
 
-       BNX2FC_HBA_DBG(hba->ctlr.lp, "ERROR:bnx2fc_destroy_timer - "
+       BNX2FC_MISC_DBG("ERROR:bnx2fc_destroy_timer - "
                   "Destroy compl not received!!\n");
-       hba->flags |= BNX2FC_FLAG_DESTROY_CMPL;
+       set_bit(BNX2FC_FLAG_DESTROY_CMPL, &hba->flags);
        wake_up_interruptible(&hba->destroy_wait);
 }
 
@@ -779,54 +789,35 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
                                     u16 vlan_id)
 {
        struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context;
-       struct fc_lport *lport = hba->ctlr.lp;
+       struct fc_lport *lport;
        struct fc_lport *vport;
+       struct bnx2fc_interface *interface;
+       int wait_for_upload = 0;
        u32 link_possible = 1;
 
        /* Ignore vlans for now */
        if (vlan_id != 0)
                return;
 
-       if (!test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
-               BNX2FC_MISC_DBG("driver not ready. event=%s %ld\n",
-                          hba->netdev->name, event);
-               return;
-       }
-
-       /*
-        * ASSUMPTION:
-        * indicate_netevent cannot be called from cnic unless bnx2fc
-        * does register_device
-        */
-       BUG_ON(!lport);
-
-       BNX2FC_HBA_DBG(lport, "enter netevent handler - event=%s %ld\n",
-                               hba->netdev->name, event);
-
        switch (event) {
        case NETDEV_UP:
-               BNX2FC_HBA_DBG(lport, "Port up, adapter_state = %ld\n",
-                       hba->adapter_state);
                if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
                        printk(KERN_ERR "indicate_netevent: "\
-                                       "adapter is not UP!!\n");
+                                       "hba is not UP!!\n");
                break;
 
        case NETDEV_DOWN:
-               BNX2FC_HBA_DBG(lport, "Port down\n");
                clear_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
                clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
                link_possible = 0;
                break;
 
        case NETDEV_GOING_DOWN:
-               BNX2FC_HBA_DBG(lport, "Port going down\n");
                set_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
                link_possible = 0;
                break;
 
        case NETDEV_CHANGE:
-               BNX2FC_HBA_DBG(lport, "NETDEV_CHANGE\n");
                break;
 
        default:
@@ -834,15 +825,22 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
                return;
        }
 
-       bnx2fc_link_speed_update(lport);
+       mutex_lock(&bnx2fc_dev_lock);
+       list_for_each_entry(interface, &if_list, list) {
 
-       if (link_possible && !bnx2fc_link_ok(lport)) {
-               printk(KERN_ERR "indicate_netevent: call ctlr_link_up\n");
-               fcoe_ctlr_link_up(&hba->ctlr);
-       } else {
-               printk(KERN_ERR "indicate_netevent: call ctlr_link_down\n");
-               if (fcoe_ctlr_link_down(&hba->ctlr)) {
-                       clear_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+               if (interface->hba != hba)
+                       continue;
+
+               lport = interface->ctlr.lp;
+               BNX2FC_HBA_DBG(lport, "netevent handler - event=%s %ld\n",
+                               interface->netdev->name, event);
+
+               bnx2fc_link_speed_update(lport);
+
+               if (link_possible && !bnx2fc_link_ok(lport)) {
+                       printk(KERN_ERR "indicate_netevent: ctlr_link_up\n");
+                       fcoe_ctlr_link_up(&interface->ctlr);
+               } else if (fcoe_ctlr_link_down(&interface->ctlr)) {
                        mutex_lock(&lport->lp_mutex);
                        list_for_each_entry(vport, &lport->vports, list)
                                fc_host_port_type(vport->host) =
@@ -853,24 +851,26 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
                                    get_cpu())->LinkFailureCount++;
                        put_cpu();
                        fcoe_clean_pending_queue(lport);
+                       wait_for_upload = 1;
+               }
+       }
+       mutex_unlock(&bnx2fc_dev_lock);
 
-                       init_waitqueue_head(&hba->shutdown_wait);
-                       BNX2FC_HBA_DBG(lport, "indicate_netevent "
-                                            "num_ofld_sess = %d\n",
-                                  hba->num_ofld_sess);
-                       hba->wait_for_link_down = 1;
-                       BNX2FC_HBA_DBG(lport, "waiting for uploads to "
-                                            "compl proc = %s\n",
-                                  current->comm);
-                       wait_event_interruptible(hba->shutdown_wait,
-                                                (hba->num_ofld_sess == 0));
-                       BNX2FC_HBA_DBG(lport, "wakeup - num_ofld_sess = %d\n",
+       if (wait_for_upload) {
+               clear_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+               init_waitqueue_head(&hba->shutdown_wait);
+               BNX2FC_MISC_DBG("indicate_netevent "
+                               "num_ofld_sess = %d\n",
+                               hba->num_ofld_sess);
+               hba->wait_for_link_down = 1;
+               wait_event_interruptible(hba->shutdown_wait,
+                                        (hba->num_ofld_sess == 0));
+               BNX2FC_MISC_DBG("wakeup - num_ofld_sess = %d\n",
                                hba->num_ofld_sess);
-                       hba->wait_for_link_down = 0;
+               hba->wait_for_link_down = 0;
 
-                       if (signal_pending(current))
-                               flush_signals(current);
-               }
+               if (signal_pending(current))
+                       flush_signals(current);
        }
 }
 
@@ -889,23 +889,12 @@ static int bnx2fc_libfc_config(struct fc_lport *lport)
 
 static int bnx2fc_em_config(struct fc_lport *lport)
 {
-       struct fcoe_port *port = lport_priv(lport);
-       struct bnx2fc_hba *hba = port->priv;
-
        if (!fc_exch_mgr_alloc(lport, FC_CLASS_3, FCOE_MIN_XID,
                                FCOE_MAX_XID, NULL)) {
                printk(KERN_ERR PFX "em_config:fc_exch_mgr_alloc failed\n");
                return -ENOMEM;
        }
 
-       hba->cmd_mgr = bnx2fc_cmd_mgr_alloc(hba, BNX2FC_MIN_XID,
-                                           BNX2FC_MAX_XID);
-
-       if (!hba->cmd_mgr) {
-               printk(KERN_ERR PFX "em_config:bnx2fc_cmd_mgr_alloc failed\n");
-               fc_exch_mgr_free(lport);
-               return -ENOMEM;
-       }
        return 0;
 }
 
@@ -918,11 +907,8 @@ static int bnx2fc_lport_config(struct fc_lport *lport)
        lport->e_d_tov = 2 * 1000;
        lport->r_a_tov = 10 * 1000;
 
-       /* REVISIT: enable when supporting tape devices
        lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
                                FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
-       */
-       lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS);
        lport->does_npiv = 1;
 
        memset(&lport->rnid_gen, 0, sizeof(struct fc_els_rnid_gen));
@@ -952,9 +938,10 @@ static int bnx2fc_fip_recv(struct sk_buff *skb, struct net_device *dev,
                           struct packet_type *ptype,
                           struct net_device *orig_dev)
 {
-       struct bnx2fc_hba *hba;
-       hba = container_of(ptype, struct bnx2fc_hba, fip_packet_type);
-       fcoe_ctlr_recv(&hba->ctlr, skb);
+       struct bnx2fc_interface *interface;
+       interface = container_of(ptype, struct bnx2fc_interface,
+                                fip_packet_type);
+       fcoe_ctlr_recv(&interface->ctlr, skb);
        return 0;
 }
 
@@ -1005,17 +992,17 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled)
        struct Scsi_Host *shost = vport_to_shost(vport);
        struct fc_lport *n_port = shost_priv(shost);
        struct fcoe_port *port = lport_priv(n_port);
-       struct bnx2fc_hba *hba = port->priv;
-       struct net_device *netdev = hba->netdev;
+       struct bnx2fc_interface *interface = port->priv;
+       struct net_device *netdev = interface->netdev;
        struct fc_lport *vn_port;
 
-       if (!test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+       if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags)) {
                printk(KERN_ERR PFX "vn ports cannot be created on"
-                       "this hba\n");
+                       "this interface\n");
                return -EIO;
        }
        mutex_lock(&bnx2fc_dev_lock);
-       vn_port = bnx2fc_if_create(hba, &vport->dev, 1);
+       vn_port = bnx2fc_if_create(interface, &vport->dev, 1);
        mutex_unlock(&bnx2fc_dev_lock);
 
        if (IS_ERR(vn_port)) {
@@ -1065,10 +1052,10 @@ static int bnx2fc_vport_disable(struct fc_vport *vport, bool disable)
 }
 
 
-static int bnx2fc_netdev_setup(struct bnx2fc_hba *hba)
+static int bnx2fc_netdev_setup(struct bnx2fc_interface *interface)
 {
-       struct net_device *netdev = hba->netdev;
-       struct net_device *physdev = hba->phys_dev;
+       struct net_device *netdev = interface->netdev;
+       struct net_device *physdev = interface->hba->phys_dev;
        struct netdev_hw_addr *ha;
        int sel_san_mac = 0;
 
@@ -1083,7 +1070,8 @@ static int bnx2fc_netdev_setup(struct bnx2fc_hba *hba)
 
                if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
                    (is_valid_ether_addr(ha->addr))) {
-                       memcpy(hba->ctlr.ctl_src_addr, ha->addr, ETH_ALEN);
+                       memcpy(interface->ctlr.ctl_src_addr, ha->addr,
+                              ETH_ALEN);
                        sel_san_mac = 1;
                        BNX2FC_MISC_DBG("Found SAN MAC\n");
                }
@@ -1093,15 +1081,15 @@ static int bnx2fc_netdev_setup(struct bnx2fc_hba *hba)
        if (!sel_san_mac)
                return -ENODEV;
 
-       hba->fip_packet_type.func = bnx2fc_fip_recv;
-       hba->fip_packet_type.type = htons(ETH_P_FIP);
-       hba->fip_packet_type.dev = netdev;
-       dev_add_pack(&hba->fip_packet_type);
+       interface->fip_packet_type.func = bnx2fc_fip_recv;
+       interface->fip_packet_type.type = htons(ETH_P_FIP);
+       interface->fip_packet_type.dev = netdev;
+       dev_add_pack(&interface->fip_packet_type);
 
-       hba->fcoe_packet_type.func = bnx2fc_rcv;
-       hba->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
-       hba->fcoe_packet_type.dev = netdev;
-       dev_add_pack(&hba->fcoe_packet_type);
+       interface->fcoe_packet_type.func = bnx2fc_rcv;
+       interface->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
+       interface->fcoe_packet_type.dev = netdev;
+       dev_add_pack(&interface->fcoe_packet_type);
 
        return 0;
 }
@@ -1137,53 +1125,54 @@ static void bnx2fc_release_transport(void)
 
 static void bnx2fc_interface_release(struct kref *kref)
 {
-       struct bnx2fc_hba *hba;
+       struct bnx2fc_interface *interface;
        struct net_device *netdev;
-       struct net_device *phys_dev;
 
-       hba = container_of(kref, struct bnx2fc_hba, kref);
+       interface = container_of(kref, struct bnx2fc_interface, kref);
        BNX2FC_MISC_DBG("Interface is being released\n");
 
-       netdev = hba->netdev;
-       phys_dev = hba->phys_dev;
+       netdev = interface->netdev;
 
        /* tear-down FIP controller */
-       if (test_and_clear_bit(BNX2FC_CTLR_INIT_DONE, &hba->init_done))
-               fcoe_ctlr_destroy(&hba->ctlr);
+       if (test_and_clear_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags))
+               fcoe_ctlr_destroy(&interface->ctlr);
+
+       kfree(interface);
 
-       /* Free the command manager */
-       if (hba->cmd_mgr) {
-               bnx2fc_cmd_mgr_free(hba->cmd_mgr);
-               hba->cmd_mgr = NULL;
-       }
        dev_put(netdev);
        module_put(THIS_MODULE);
 }
 
-static inline void bnx2fc_interface_get(struct bnx2fc_hba *hba)
+static inline void bnx2fc_interface_get(struct bnx2fc_interface *interface)
 {
-       kref_get(&hba->kref);
+       kref_get(&interface->kref);
 }
 
-static inline void bnx2fc_interface_put(struct bnx2fc_hba *hba)
+static inline void bnx2fc_interface_put(struct bnx2fc_interface *interface)
 {
-       kref_put(&hba->kref, bnx2fc_interface_release);
+       kref_put(&interface->kref, bnx2fc_interface_release);
 }
-static void bnx2fc_interface_destroy(struct bnx2fc_hba *hba)
+static void bnx2fc_hba_destroy(struct bnx2fc_hba *hba)
 {
+       /* Free the command manager */
+       if (hba->cmd_mgr) {
+               bnx2fc_cmd_mgr_free(hba->cmd_mgr);
+               hba->cmd_mgr = NULL;
+       }
+       kfree(hba->tgt_ofld_list);
        bnx2fc_unbind_pcidev(hba);
        kfree(hba);
 }
 
 /**
- * bnx2fc_interface_create - create a new fcoe instance
+ * bnx2fc_hba_create - create a new bnx2fc hba
  *
  * @cnic:      pointer to cnic device
  *
- * Creates a new FCoE instance on the given device which include allocating
- *     hba structure, scsi_host and lport structures.
+ * Creates a new FCoE hba on the given device.
+ *
  */
-static struct bnx2fc_hba *bnx2fc_interface_create(struct cnic_dev *cnic)
+static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic)
 {
        struct bnx2fc_hba *hba;
        int rc;
@@ -1198,65 +1187,83 @@ static struct bnx2fc_hba *bnx2fc_interface_create(struct cnic_dev *cnic)
 
        hba->cnic = cnic;
        rc = bnx2fc_bind_pcidev(hba);
-       if (rc)
+       if (rc) {
+               printk(KERN_ERR PFX "create_adapter:  bind error\n");
                goto bind_err;
+       }
        hba->phys_dev = cnic->netdev;
-       /* will get overwritten after we do vlan discovery */
-       hba->netdev = hba->phys_dev;
+       hba->next_conn_id = 0;
+
+       hba->tgt_ofld_list =
+               kzalloc(sizeof(struct bnx2fc_rport *) * BNX2FC_NUM_MAX_SESS,
+                       GFP_KERNEL);
+       if (!hba->tgt_ofld_list) {
+               printk(KERN_ERR PFX "Unable to allocate tgt offload list\n");
+               goto tgtofld_err;
+       }
+
+       hba->num_ofld_sess = 0;
+
+       hba->cmd_mgr = bnx2fc_cmd_mgr_alloc(hba, BNX2FC_MIN_XID,
+                                               BNX2FC_MAX_XID);
+       if (!hba->cmd_mgr) {
+               printk(KERN_ERR PFX "em_config:bnx2fc_cmd_mgr_alloc failed\n");
+               goto cmgr_err;
+       }
 
        init_waitqueue_head(&hba->shutdown_wait);
        init_waitqueue_head(&hba->destroy_wait);
+       INIT_LIST_HEAD(&hba->vports);
 
        return hba;
+
+cmgr_err:
+       kfree(hba->tgt_ofld_list);
+tgtofld_err:
+       bnx2fc_unbind_pcidev(hba);
 bind_err:
-       printk(KERN_ERR PFX "create_interface: bind error\n");
        kfree(hba);
        return NULL;
 }
 
-static int bnx2fc_interface_setup(struct bnx2fc_hba *hba,
-                                 enum fip_state fip_mode)
+struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba,
+                                     struct net_device *netdev,
+                                     enum fip_state fip_mode)
 {
+       struct bnx2fc_interface *interface;
        int rc = 0;
-       struct net_device *netdev = hba->netdev;
-       struct fcoe_ctlr *fip = &hba->ctlr;
 
+       interface = kzalloc(sizeof(*interface), GFP_KERNEL);
+       if (!interface) {
+               printk(KERN_ERR PFX "Unable to allocate interface structure\n");
+               return NULL;
+       }
        dev_hold(netdev);
-       kref_init(&hba->kref);
-
-       hba->flags = 0;
+       kref_init(&interface->kref);
+       interface->hba = hba;
+       interface->netdev = netdev;
 
        /* Initialize FIP */
-       memset(fip, 0, sizeof(*fip));
-       fcoe_ctlr_init(fip, fip_mode);
-       hba->ctlr.send = bnx2fc_fip_send;
-       hba->ctlr.update_mac = bnx2fc_update_src_mac;
-       hba->ctlr.get_src_addr = bnx2fc_get_src_mac;
-       set_bit(BNX2FC_CTLR_INIT_DONE, &hba->init_done);
-
-       INIT_LIST_HEAD(&hba->vports);
-       rc = bnx2fc_netdev_setup(hba);
-       if (rc)
-               goto setup_err;
+       fcoe_ctlr_init(&interface->ctlr, fip_mode);
+       interface->ctlr.send = bnx2fc_fip_send;
+       interface->ctlr.update_mac = bnx2fc_update_src_mac;
+       interface->ctlr.get_src_addr = bnx2fc_get_src_mac;
+       set_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags);
 
-       hba->next_conn_id = 0;
+       rc = bnx2fc_netdev_setup(interface);
+       if (!rc)
+               return interface;
 
-       memset(hba->tgt_ofld_list, 0, sizeof(hba->tgt_ofld_list));
-       hba->num_ofld_sess = 0;
-
-       return 0;
-
-setup_err:
-       fcoe_ctlr_destroy(&hba->ctlr);
+       fcoe_ctlr_destroy(&interface->ctlr);
        dev_put(netdev);
-       bnx2fc_interface_put(hba);
-       return rc;
+       kfree(interface);
+       return NULL;
 }
 
 /**
  * bnx2fc_if_create - Create FCoE instance on a given interface
  *
- * @hba:       FCoE interface to create a local port on
+ * @interface: FCoE interface to create a local port on
  * @parent:    Device pointer to be the parent in sysfs for the SCSI host
  * @npiv:      Indicates if the port is vport or not
  *
@@ -1264,7 +1271,7 @@ setup_err:
  *
  * Returns:    Allocated fc_lport or an error pointer
  */
-static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
+static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
                                  struct device *parent, int npiv)
 {
        struct fc_lport         *lport, *n_port;
@@ -1272,11 +1279,12 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
        struct Scsi_Host        *shost;
        struct fc_vport         *vport = dev_to_vport(parent);
        struct bnx2fc_lport     *blport;
+       struct bnx2fc_hba       *hba;
        int                     rc = 0;
 
        blport = kzalloc(sizeof(struct bnx2fc_lport), GFP_KERNEL);
        if (!blport) {
-               BNX2FC_HBA_DBG(hba->ctlr.lp, "Unable to alloc bnx2fc_lport\n");
+               BNX2FC_HBA_DBG(interface->ctlr.lp, "Unable to alloc blport\n");
                return NULL;
        }
 
@@ -1293,7 +1301,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
        shost = lport->host;
        port = lport_priv(lport);
        port->lport = lport;
-       port->priv = hba;
+       port->priv = interface;
        INIT_WORK(&port->destroy_work, bnx2fc_destroy_work);
 
        /* Configure fcoe_port */
@@ -1317,7 +1325,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
        rc = bnx2fc_shost_config(lport, parent);
        if (rc) {
                printk(KERN_ERR PFX "Couldnt configure shost for %s\n",
-                       hba->netdev->name);
+                       interface->netdev->name);
                goto lp_config_err;
        }
 
@@ -1343,8 +1351,9 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
                goto shost_err;
        }
 
-       bnx2fc_interface_get(hba);
+       bnx2fc_interface_get(interface);
 
+       hba = interface->hba;
        spin_lock_bh(&hba->hba_lock);
        blport->lport = lport;
        list_add_tail(&blport->list, &hba->vports);
@@ -1361,21 +1370,19 @@ free_blport:
        return NULL;
 }
 
-static void bnx2fc_netdev_cleanup(struct bnx2fc_hba *hba)
+static void bnx2fc_netdev_cleanup(struct bnx2fc_interface *interface)
 {
        /* Dont listen for Ethernet packets anymore */
-       __dev_remove_pack(&hba->fcoe_packet_type);
-       __dev_remove_pack(&hba->fip_packet_type);
+       __dev_remove_pack(&interface->fcoe_packet_type);
+       __dev_remove_pack(&interface->fip_packet_type);
        synchronize_net();
 }
 
-static void bnx2fc_if_destroy(struct fc_lport *lport)
+static void bnx2fc_if_destroy(struct fc_lport *lport, struct bnx2fc_hba *hba)
 {
        struct fcoe_port *port = lport_priv(lport);
-       struct bnx2fc_hba *hba = port->priv;
        struct bnx2fc_lport *blport, *tmp;
 
-       BNX2FC_HBA_DBG(hba->ctlr.lp, "ENTERED bnx2fc_if_destroy\n");
        /* Stop the transmit retry timer */
        del_timer_sync(&port->timer);
 
@@ -1409,8 +1416,6 @@ static void bnx2fc_if_destroy(struct fc_lport *lport)
 
        /* Release Scsi_Host */
        scsi_host_put(lport->host);
-
-       bnx2fc_interface_put(hba);
 }
 
 /**
@@ -1425,46 +1430,31 @@ static void bnx2fc_if_destroy(struct fc_lport *lport)
  */
 static int bnx2fc_destroy(struct net_device *netdev)
 {
-       struct bnx2fc_hba *hba = NULL;
-       struct net_device *phys_dev;
+       struct bnx2fc_interface *interface = NULL;
+       struct bnx2fc_hba *hba;
+       struct fc_lport *lport;
        int rc = 0;
 
        rtnl_lock();
-
        mutex_lock(&bnx2fc_dev_lock);
-       /* obtain physical netdev */
-       if (netdev->priv_flags & IFF_802_1Q_VLAN)
-               phys_dev = vlan_dev_real_dev(netdev);
-       else {
-               printk(KERN_ERR PFX "Not a vlan device\n");
-               rc = -ENODEV;
-               goto netdev_err;
-       }
 
-       hba = bnx2fc_hba_lookup(phys_dev);
-       if (!hba || !hba->ctlr.lp) {
+       interface = bnx2fc_interface_lookup(netdev);
+       if (!interface || !interface->ctlr.lp) {
                rc = -ENODEV;
-               printk(KERN_ERR PFX "bnx2fc_destroy: hba or lport not found\n");
-               goto netdev_err;
-       }
-
-       if (!test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
-               printk(KERN_ERR PFX "bnx2fc_destroy: Create not called\n");
+               printk(KERN_ERR PFX "bnx2fc_destroy: interface or lport not found\n");
                goto netdev_err;
        }
 
-       bnx2fc_netdev_cleanup(hba);
-
-       bnx2fc_stop(hba);
-
-       bnx2fc_if_destroy(hba->ctlr.lp);
+       hba = interface->hba;
 
-       destroy_workqueue(hba->timer_work_queue);
+       bnx2fc_netdev_cleanup(interface);
+       lport = interface->ctlr.lp;
+       bnx2fc_stop(interface);
+       list_del(&interface->list);
+       destroy_workqueue(interface->timer_work_queue);
+       bnx2fc_interface_put(interface);
+       bnx2fc_if_destroy(lport, hba);
 
-       if (test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done))
-               bnx2fc_fw_destroy(hba);
-
-       clear_bit(BNX2FC_CREATE_DONE, &hba->init_done);
 netdev_err:
        mutex_unlock(&bnx2fc_dev_lock);
        rtnl_unlock();
@@ -1475,16 +1465,20 @@ static void bnx2fc_destroy_work(struct work_struct *work)
 {
        struct fcoe_port *port;
        struct fc_lport *lport;
+       struct bnx2fc_interface *interface;
+       struct bnx2fc_hba *hba;
 
        port = container_of(work, struct fcoe_port, destroy_work);
        lport = port->lport;
+       interface = port->priv;
+       hba = interface->hba;
 
        BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n");
 
        bnx2fc_port_shutdown(lport);
        rtnl_lock();
        mutex_lock(&bnx2fc_dev_lock);
-       bnx2fc_if_destroy(lport);
+       bnx2fc_if_destroy(lport, hba);
        mutex_unlock(&bnx2fc_dev_lock);
        rtnl_unlock();
 }
@@ -1556,28 +1550,27 @@ static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba)
 static void bnx2fc_ulp_start(void *handle)
 {
        struct bnx2fc_hba *hba = handle;
-       struct fc_lport *lport = hba->ctlr.lp;
+       struct bnx2fc_interface *interface;
+       struct fc_lport *lport;
 
-       BNX2FC_MISC_DBG("Entered %s\n", __func__);
        mutex_lock(&bnx2fc_dev_lock);
 
-       if (test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done))
-               goto start_disc;
-
-       if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done))
+       if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &hba->flags))
                bnx2fc_fw_init(hba);
 
-start_disc:
-       mutex_unlock(&bnx2fc_dev_lock);
-
        BNX2FC_MISC_DBG("bnx2fc started.\n");
 
-       /* Kick off Fabric discovery*/
-       if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
-               printk(KERN_ERR PFX "ulp_init: start discovery\n");
-               lport->tt.frame_send = bnx2fc_xmit;
-               bnx2fc_start_disc(hba);
+       list_for_each_entry(interface, &if_list, list) {
+               if (interface->hba == hba) {
+                       lport = interface->ctlr.lp;
+                       /* Kick off Fabric discovery*/
+                       printk(KERN_ERR PFX "ulp_init: start discovery\n");
+                       lport->tt.frame_send = bnx2fc_xmit;
+                       bnx2fc_start_disc(interface);
+               }
        }
+
+       mutex_unlock(&bnx2fc_dev_lock);
 }
 
 static void bnx2fc_port_shutdown(struct fc_lport *lport)
@@ -1587,37 +1580,25 @@ static void bnx2fc_port_shutdown(struct fc_lport *lport)
        fc_lport_destroy(lport);
 }
 
-static void bnx2fc_stop(struct bnx2fc_hba *hba)
+static void bnx2fc_stop(struct bnx2fc_interface *interface)
 {
        struct fc_lport *lport;
        struct fc_lport *vport;
 
-       BNX2FC_MISC_DBG("ENTERED %s - init_done = %ld\n", __func__,
-                  hba->init_done);
-       if (test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done) &&
-           test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
-               lport = hba->ctlr.lp;
-               bnx2fc_port_shutdown(lport);
-               BNX2FC_HBA_DBG(lport, "bnx2fc_stop: waiting for %d "
-                               "offloaded sessions\n",
-                               hba->num_ofld_sess);
-               wait_event_interruptible(hba->shutdown_wait,
-                                        (hba->num_ofld_sess == 0));
-               mutex_lock(&lport->lp_mutex);
-               list_for_each_entry(vport, &lport->vports, list)
-                       fc_host_port_type(vport->host) = FC_PORTTYPE_UNKNOWN;
-               mutex_unlock(&lport->lp_mutex);
-               fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
-               fcoe_ctlr_link_down(&hba->ctlr);
-               fcoe_clean_pending_queue(lport);
-
-               mutex_lock(&hba->hba_mutex);
-               clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
-               clear_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
+       if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags))
+               return;
 
-               clear_bit(ADAPTER_STATE_READY, &hba->adapter_state);
-               mutex_unlock(&hba->hba_mutex);
-       }
+       lport = interface->ctlr.lp;
+       bnx2fc_port_shutdown(lport);
+
+       mutex_lock(&lport->lp_mutex);
+       list_for_each_entry(vport, &lport->vports, list)
+               fc_host_port_type(vport->host) =
+                                       FC_PORTTYPE_UNKNOWN;
+       mutex_unlock(&lport->lp_mutex);
+       fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
+       fcoe_ctlr_link_down(&interface->ctlr);
+       fcoe_clean_pending_queue(lport);
 }
 
 static int bnx2fc_fw_init(struct bnx2fc_hba *hba)
@@ -1656,8 +1637,7 @@ static int bnx2fc_fw_init(struct bnx2fc_hba *hba)
        }
 
 
-       /* Mark HBA to indicate that the FW INIT is done */
-       set_bit(BNX2FC_FW_INIT_DONE, &hba->init_done);
+       set_bit(BNX2FC_FLAG_FW_INIT_DONE, &hba->flags);
        return 0;
 
 err_unbind:
@@ -1668,7 +1648,7 @@ err_out:
 
 static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba)
 {
-       if (test_and_clear_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+       if (test_and_clear_bit(BNX2FC_FLAG_FW_INIT_DONE, &hba->flags)) {
                if (bnx2fc_send_fw_fcoe_destroy_msg(hba) == 0) {
                        init_timer(&hba->destroy_timer);
                        hba->destroy_timer.expires = BNX2FC_FW_TIMEOUT +
@@ -1677,8 +1657,8 @@ static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba)
                        hba->destroy_timer.data = (unsigned long)hba;
                        add_timer(&hba->destroy_timer);
                        wait_event_interruptible(hba->destroy_wait,
-                                                (hba->flags &
-                                                 BNX2FC_FLAG_DESTROY_CMPL));
+                                       test_bit(BNX2FC_FLAG_DESTROY_CMPL,
+                                                &hba->flags));
                        /* This should never happen */
                        if (signal_pending(current))
                                flush_signals(current);
@@ -1699,40 +1679,57 @@ static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba)
  */
 static void bnx2fc_ulp_stop(void *handle)
 {
-       struct bnx2fc_hba *hba = (struct bnx2fc_hba *)handle;
+       struct bnx2fc_hba *hba = handle;
+       struct bnx2fc_interface *interface;
 
        printk(KERN_ERR "ULP_STOP\n");
 
        mutex_lock(&bnx2fc_dev_lock);
-       bnx2fc_stop(hba);
+       if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &hba->flags))
+               goto exit;
+       list_for_each_entry(interface, &if_list, list) {
+               if (interface->hba == hba)
+                       bnx2fc_stop(interface);
+       }
+       BUG_ON(hba->num_ofld_sess != 0);
+
+       mutex_lock(&hba->hba_mutex);
+       clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
+       clear_bit(ADAPTER_STATE_GOING_DOWN,
+                 &hba->adapter_state);
+
+       clear_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+       mutex_unlock(&hba->hba_mutex);
+
        bnx2fc_fw_destroy(hba);
+exit:
        mutex_unlock(&bnx2fc_dev_lock);
 }
 
-static void bnx2fc_start_disc(struct bnx2fc_hba *hba)
+static void bnx2fc_start_disc(struct bnx2fc_interface *interface)
 {
        struct fc_lport *lport;
        int wait_cnt = 0;
 
        BNX2FC_MISC_DBG("Entered %s\n", __func__);
        /* Kick off FIP/FLOGI */
-       if (!test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+       if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags)) {
                printk(KERN_ERR PFX "Init not done yet\n");
                return;
        }
 
-       lport = hba->ctlr.lp;
+       lport = interface->ctlr.lp;
        BNX2FC_HBA_DBG(lport, "calling fc_fabric_login\n");
 
        if (!bnx2fc_link_ok(lport)) {
                BNX2FC_HBA_DBG(lport, "ctlr_link_up\n");
-               fcoe_ctlr_link_up(&hba->ctlr);
+               fcoe_ctlr_link_up(&interface->ctlr);
                fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
-               set_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+               set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state);
        }
 
        /* wait for the FCF to be selected before issuing FLOGI */
-       while (!hba->ctlr.sel_fcf) {
+       while (!interface->ctlr.sel_fcf) {
                msleep(250);
                /* give up after 3 secs */
                if (++wait_cnt > 12)
@@ -1758,15 +1755,15 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev)
 
        BNX2FC_MISC_DBG("Entered %s\n", __func__);
        /* bnx2fc works only when bnx2x is loaded */
-       if (!test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
+       if (!test_bit(CNIC_F_BNX2X_CLASS, &dev->flags) ||
+           (dev->max_fcoe_conn == 0)) {
                printk(KERN_ERR PFX "bnx2fc FCoE not supported on %s,"
-                                   " flags: %lx\n",
-                       dev->netdev->name, dev->flags);
+                                   " flags: %lx fcoe_conn: %d\n",
+                       dev->netdev->name, dev->flags, dev->max_fcoe_conn);
                return;
        }
 
-       /* Configure FCoE interface */
-       hba = bnx2fc_interface_create(dev);
+       hba = bnx2fc_hba_create(dev);
        if (!hba) {
                printk(KERN_ERR PFX "hba initialization failed\n");
                return;
@@ -1774,7 +1771,7 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev)
 
        /* Add HBA to the adapter list */
        mutex_lock(&bnx2fc_dev_lock);
-       list_add_tail(&hba->link, &adapter_list);
+       list_add_tail(&hba->list, &adapter_list);
        adapter_count++;
        mutex_unlock(&bnx2fc_dev_lock);
 
@@ -1782,7 +1779,7 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev)
        rc = dev->register_device(dev, CNIC_ULP_FCOE,
                                                (void *) hba);
        if (rc)
-               printk(KERN_ALERT PFX "register_device failed, rc = %d\n", rc);
+               printk(KERN_ERR PFX "register_device failed, rc = %d\n", rc);
        else
                set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic);
 }
@@ -1790,52 +1787,21 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev)
 
 static int bnx2fc_disable(struct net_device *netdev)
 {
-       struct bnx2fc_hba *hba;
-       struct net_device *phys_dev;
-       struct ethtool_drvinfo drvinfo;
+       struct bnx2fc_interface *interface;
        int rc = 0;
 
        rtnl_lock();
-
        mutex_lock(&bnx2fc_dev_lock);
 
-       /* obtain physical netdev */
-       if (netdev->priv_flags & IFF_802_1Q_VLAN)
-               phys_dev = vlan_dev_real_dev(netdev);
-       else {
-               printk(KERN_ERR PFX "Not a vlan device\n");
-               rc = -ENODEV;
-               goto nodev;
-       }
-
-       /* verify if the physical device is a netxtreme2 device */
-       if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) {
-               memset(&drvinfo, 0, sizeof(drvinfo));
-               phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo);
-               if (strcmp(drvinfo.driver, "bnx2x")) {
-                       printk(KERN_ERR PFX "Not a netxtreme2 device\n");
-                       rc = -ENODEV;
-                       goto nodev;
-               }
-       } else {
-               printk(KERN_ERR PFX "unable to obtain drv_info\n");
-               rc = -ENODEV;
-               goto nodev;
-       }
-
-       printk(KERN_ERR PFX "phys_dev is netxtreme2 device\n");
-
-       /* obtain hba and initialize rest of the structure */
-       hba = bnx2fc_hba_lookup(phys_dev);
-       if (!hba || !hba->ctlr.lp) {
+       interface = bnx2fc_interface_lookup(netdev);
+       if (!interface || !interface->ctlr.lp) {
                rc = -ENODEV;
-               printk(KERN_ERR PFX "bnx2fc_disable: hba or lport not found\n");
+               printk(KERN_ERR PFX "bnx2fc_disable: interface or lport not found\n");
        } else {
-               fcoe_ctlr_link_down(&hba->ctlr);
-               fcoe_clean_pending_queue(hba->ctlr.lp);
+               fcoe_ctlr_link_down(&interface->ctlr);
+               fcoe_clean_pending_queue(interface->ctlr.lp);
        }
 
-nodev:
        mutex_unlock(&bnx2fc_dev_lock);
        rtnl_unlock();
        return rc;
@@ -1844,48 +1810,19 @@ nodev:
 
 static int bnx2fc_enable(struct net_device *netdev)
 {
-       struct bnx2fc_hba *hba;
-       struct net_device *phys_dev;
-       struct ethtool_drvinfo drvinfo;
+       struct bnx2fc_interface *interface;
        int rc = 0;
 
        rtnl_lock();
-
-       BNX2FC_MISC_DBG("Entered %s\n", __func__);
        mutex_lock(&bnx2fc_dev_lock);
 
-       /* obtain physical netdev */
-       if (netdev->priv_flags & IFF_802_1Q_VLAN)
-               phys_dev = vlan_dev_real_dev(netdev);
-       else {
-               printk(KERN_ERR PFX "Not a vlan device\n");
-               rc = -ENODEV;
-               goto nodev;
-       }
-       /* verify if the physical device is a netxtreme2 device */
-       if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) {
-               memset(&drvinfo, 0, sizeof(drvinfo));
-               phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo);
-               if (strcmp(drvinfo.driver, "bnx2x")) {
-                       printk(KERN_ERR PFX "Not a netxtreme2 device\n");
-                       rc = -ENODEV;
-                       goto nodev;
-               }
-       } else {
-               printk(KERN_ERR PFX "unable to obtain drv_info\n");
+       interface = bnx2fc_interface_lookup(netdev);
+       if (!interface || !interface->ctlr.lp) {
                rc = -ENODEV;
-               goto nodev;
-       }
-
-       /* obtain hba and initialize rest of the structure */
-       hba = bnx2fc_hba_lookup(phys_dev);
-       if (!hba || !hba->ctlr.lp) {
-               rc = -ENODEV;
-               printk(KERN_ERR PFX "bnx2fc_enable: hba or lport not found\n");
-       } else if (!bnx2fc_link_ok(hba->ctlr.lp))
-               fcoe_ctlr_link_up(&hba->ctlr);
+               printk(KERN_ERR PFX "bnx2fc_enable: interface or lport not found\n");
+       } else if (!bnx2fc_link_ok(interface->ctlr.lp))
+               fcoe_ctlr_link_up(&interface->ctlr);
 
-nodev:
        mutex_unlock(&bnx2fc_dev_lock);
        rtnl_unlock();
        return rc;
@@ -1903,6 +1840,7 @@ nodev:
  */
 static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
 {
+       struct bnx2fc_interface *interface;
        struct bnx2fc_hba *hba;
        struct net_device *phys_dev;
        struct fc_lport *lport;
@@ -1938,7 +1876,7 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
        if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) {
                memset(&drvinfo, 0, sizeof(drvinfo));
                phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo);
-               if (strcmp(drvinfo.driver, "bnx2x")) {
+               if (strncmp(drvinfo.driver, "bnx2x", strlen("bnx2x"))) {
                        printk(KERN_ERR PFX "Not a netxtreme2 device\n");
                        rc = -EINVAL;
                        goto netdev_err;
@@ -1949,7 +1887,7 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
                goto netdev_err;
        }
 
-       /* obtain hba and initialize rest of the structure */
+       /* obtain interface and initialize rest of the structure */
        hba = bnx2fc_hba_lookup(phys_dev);
        if (!hba) {
                rc = -ENODEV;
@@ -1957,67 +1895,61 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
                goto netdev_err;
        }
 
-       if (!test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
-               rc = bnx2fc_fw_init(hba);
-               if (rc)
-                       goto netdev_err;
-       }
-
-       if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+       if (bnx2fc_interface_lookup(netdev)) {
                rc = -EEXIST;
                goto netdev_err;
        }
 
-       /* update netdev with vlan netdev */
-       hba->netdev = netdev;
-       hba->vlan_id = vlan_id;
-       hba->vlan_enabled = 1;
-
-       rc = bnx2fc_interface_setup(hba, fip_mode);
-       if (rc) {
-               printk(KERN_ERR PFX "bnx2fc_interface_setup failed\n");
+       interface = bnx2fc_interface_create(hba, netdev, fip_mode);
+       if (!interface) {
+               printk(KERN_ERR PFX "bnx2fc_interface_create failed\n");
                goto ifput_err;
        }
 
-       hba->timer_work_queue =
+       interface->vlan_id = vlan_id;
+       interface->vlan_enabled = 1;
+
+       interface->timer_work_queue =
                        create_singlethread_workqueue("bnx2fc_timer_wq");
-       if (!hba->timer_work_queue) {
+       if (!interface->timer_work_queue) {
                printk(KERN_ERR PFX "ulp_init could not create timer_wq\n");
                rc = -EINVAL;
                goto ifput_err;
        }
 
-       lport = bnx2fc_if_create(hba, &hba->pcidev->dev, 0);
+       lport = bnx2fc_if_create(interface, &interface->hba->pcidev->dev, 0);
        if (!lport) {
                printk(KERN_ERR PFX "Failed to create interface (%s)\n",
                        netdev->name);
-               bnx2fc_netdev_cleanup(hba);
+               bnx2fc_netdev_cleanup(interface);
                rc = -EINVAL;
                goto if_create_err;
        }
 
+       /* Add interface to if_list */
+       list_add_tail(&interface->list, &if_list);
+
        lport->boot_time = jiffies;
 
        /* Make this master N_port */
-       hba->ctlr.lp = lport;
+       interface->ctlr.lp = lport;
 
-       set_bit(BNX2FC_CREATE_DONE, &hba->init_done);
-       printk(KERN_ERR PFX "create: START DISC\n");
-       bnx2fc_start_disc(hba);
+       BNX2FC_HBA_DBG(lport, "create: START DISC\n");
+       bnx2fc_start_disc(interface);
        /*
         * Release from kref_init in bnx2fc_interface_setup, on success
         * lport should be holding a reference taken in bnx2fc_if_create
         */
-       bnx2fc_interface_put(hba);
+       bnx2fc_interface_put(interface);
        /* put netdev that was held while calling dev_get_by_name */
        mutex_unlock(&bnx2fc_dev_lock);
        rtnl_unlock();
        return 0;
 
 if_create_err:
-       destroy_workqueue(hba->timer_work_queue);
+       destroy_workqueue(interface->timer_work_queue);
 ifput_err:
-       bnx2fc_interface_put(hba);
+       bnx2fc_interface_put(interface);
 netdev_err:
        module_put(THIS_MODULE);
 mod_err:
@@ -2027,7 +1959,7 @@ mod_err:
 }
 
 /**
- * bnx2fc_find_hba_for_cnic - maps cnic instance to bnx2fc adapter instance
+ * bnx2fc_find_hba_for_cnic - maps cnic instance to bnx2fc hba instance
  *
  * @cnic:      Pointer to cnic device instance
  *
@@ -2047,19 +1979,30 @@ static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic)
        return NULL;
 }
 
-static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev)
+static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device
+                                                       *netdev)
+{
+       struct bnx2fc_interface *interface;
+
+       /* Called with bnx2fc_dev_lock held */
+       list_for_each_entry(interface, &if_list, list) {
+               if (interface->netdev == netdev)
+                       return interface;
+       }
+       return NULL;
+}
+
+static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device
+                                                     *phys_dev)
 {
-       struct list_head *list;
-       struct list_head *temp;
        struct bnx2fc_hba *hba;
 
        /* Called with bnx2fc_dev_lock held */
-       list_for_each_safe(list, temp, &adapter_list) {
-               hba = (struct bnx2fc_hba *)list;
+       list_for_each_entry(hba, &adapter_list, list) {
                if (hba->phys_dev == phys_dev)
                        return hba;
        }
-       printk(KERN_ERR PFX "hba_lookup: hba NULL\n");
+       printk(KERN_ERR PFX "adapter_lookup: hba NULL\n");
        return NULL;
 }
 
@@ -2071,6 +2014,8 @@ static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev)
 static void bnx2fc_ulp_exit(struct cnic_dev *dev)
 {
        struct bnx2fc_hba *hba;
+       struct bnx2fc_interface *interface, *tmp;
+       struct fc_lport *lport;
 
        BNX2FC_MISC_DBG("Entered bnx2fc_ulp_exit\n");
 
@@ -2089,13 +2034,20 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev)
                return;
        }
 
-       list_del_init(&hba->link);
+       list_del_init(&hba->list);
        adapter_count--;
 
-       if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+       list_for_each_entry_safe(interface, tmp, &if_list, list) {
                /* destroy not called yet, move to quiesced list */
-               bnx2fc_netdev_cleanup(hba);
-               bnx2fc_if_destroy(hba->ctlr.lp);
+               if (interface->hba == hba) {
+                       bnx2fc_netdev_cleanup(interface);
+                       bnx2fc_stop(interface);
+
+                       list_del(&interface->list);
+                       lport = interface->ctlr.lp;
+                       bnx2fc_interface_put(interface);
+                       bnx2fc_if_destroy(lport, hba);
+               }
        }
        mutex_unlock(&bnx2fc_dev_lock);
 
@@ -2103,7 +2055,7 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev)
        /* unregister cnic device */
        if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic))
                hba->cnic->unregister_device(hba->cnic, CNIC_ULP_FCOE);
-       bnx2fc_interface_destroy(hba);
+       bnx2fc_hba_destroy(hba);
 }
 
 /**
@@ -2259,6 +2211,7 @@ static int __init bnx2fc_mod_init(void)
        }
 
        INIT_LIST_HEAD(&adapter_list);
+       INIT_LIST_HEAD(&if_list);
        mutex_init(&bnx2fc_dev_lock);
        adapter_count = 0;
 
@@ -2336,16 +2289,17 @@ static void __exit bnx2fc_mod_exit(void)
        mutex_unlock(&bnx2fc_dev_lock);
 
        /* Unregister with cnic */
-       list_for_each_entry_safe(hba, next, &to_be_deleted, link) {
-               list_del_init(&hba->link);
-               printk(KERN_ERR PFX "MOD_EXIT:destroy hba = 0x%p, kref = %d\n",
-                       hba, atomic_read(&hba->kref.refcount));
+       list_for_each_entry_safe(hba, next, &to_be_deleted, list) {
+               list_del_init(&hba->list);
+               printk(KERN_ERR PFX "MOD_EXIT:destroy hba = 0x%p\n",
+                      hba);
                bnx2fc_ulp_stop(hba);
                /* unregister cnic device */
                if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED,
                                       &hba->reg_with_cnic))
-                       hba->cnic->unregister_device(hba->cnic, CNIC_ULP_FCOE);
-               bnx2fc_interface_destroy(hba);
+                       hba->cnic->unregister_device(hba->cnic,
+                                                        CNIC_ULP_FCOE);
+               bnx2fc_hba_destroy(hba);
        }
        cnic_unregister_driver(CNIC_ULP_FCOE);
 
index 09bdd9b..72cfb14 100644 (file)
@@ -2,7 +2,7 @@
  * This file contains the code that low level functions that interact
  * with 57712 FCoE firmware.
  *
- * Copyright (c) 2008 - 2010 Broadcom Corporation
+ * Copyright (c) 2008 - 2011 Broadcom 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,7 +23,7 @@ static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
                                                struct fcoe_kcqe *ofld_kcqe);
 static void bnx2fc_init_failure(struct bnx2fc_hba *hba, u32 err_code);
 static void bnx2fc_process_conn_destroy_cmpl(struct bnx2fc_hba *hba,
-                                       struct fcoe_kcqe *conn_destroy);
+                                       struct fcoe_kcqe *destroy_kcqe);
 
 int bnx2fc_send_stat_req(struct bnx2fc_hba *hba)
 {
@@ -67,7 +67,7 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
        int rc = 0;
 
        if (!hba->cnic) {
-               printk(KERN_ALERT PFX "hba->cnic NULL during fcoe fw init\n");
+               printk(KERN_ERR PFX "hba->cnic NULL during fcoe fw init\n");
                return -ENODEV;
        }
 
@@ -103,6 +103,7 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
        fcoe_init2.hsi_major_version = FCOE_HSI_MAJOR_VERSION;
        fcoe_init2.hsi_minor_version = FCOE_HSI_MINOR_VERSION;
 
+
        fcoe_init2.hash_tbl_pbl_addr_lo = (u32) hba->hash_tbl_pbl_dma;
        fcoe_init2.hash_tbl_pbl_addr_hi = (u32)
                                           ((u64) hba->hash_tbl_pbl_dma >> 32);
@@ -165,7 +166,8 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
                                        struct bnx2fc_rport *tgt)
 {
        struct fc_lport *lport = port->lport;
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        struct kwqe *kwqe_arr[4];
        struct fcoe_kwqe_conn_offload1 ofld_req1;
        struct fcoe_kwqe_conn_offload2 ofld_req2;
@@ -227,7 +229,7 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
        ofld_req3.hdr.flags =
                (FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
 
-       ofld_req3.vlan_tag = hba->vlan_id <<
+       ofld_req3.vlan_tag = interface->vlan_id <<
                                FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT;
        ofld_req3.vlan_tag |= 3 << FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT;
 
@@ -277,8 +279,20 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
        ofld_req3.flags |= (((rdata->sp_features & FC_SP_FT_SEQC) ? 1 : 0) <<
                             FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT);
 
+       /*
+        * Info from PRLI response, this info is used for sequence level error
+        * recovery support
+        */
+       if (tgt->dev_type == TYPE_TAPE) {
+               ofld_req3.flags |= 1 <<
+                                   FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT;
+               ofld_req3.flags |= (((rdata->flags & FC_RP_FLAGS_REC_SUPPORTED)
+                                   ? 1 : 0) <<
+                                   FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT);
+       }
+
        /* vlan flag */
-       ofld_req3.flags |= (hba->vlan_enabled <<
+       ofld_req3.flags |= (interface->vlan_enabled <<
                            FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT);
 
        /* C2_VALID and ACK flags are not set as they are not suppported */
@@ -300,12 +314,13 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
        ofld_req4.src_mac_addr_mid[1] =  port->data_src_addr[2];
        ofld_req4.src_mac_addr_hi[0] =  port->data_src_addr[1];
        ofld_req4.src_mac_addr_hi[1] =  port->data_src_addr[0];
-       ofld_req4.dst_mac_addr_lo[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
-       ofld_req4.dst_mac_addr_lo[1] =  hba->ctlr.dest_addr[4];
-       ofld_req4.dst_mac_addr_mid[0] =  hba->ctlr.dest_addr[3];
-       ofld_req4.dst_mac_addr_mid[1] =  hba->ctlr.dest_addr[2];
-       ofld_req4.dst_mac_addr_hi[0] =  hba->ctlr.dest_addr[1];
-       ofld_req4.dst_mac_addr_hi[1] =  hba->ctlr.dest_addr[0];
+       ofld_req4.dst_mac_addr_lo[0] =  interface->ctlr.dest_addr[5];
+                                                       /* fcf mac */
+       ofld_req4.dst_mac_addr_lo[1] =  interface->ctlr.dest_addr[4];
+       ofld_req4.dst_mac_addr_mid[0] =  interface->ctlr.dest_addr[3];
+       ofld_req4.dst_mac_addr_mid[1] =  interface->ctlr.dest_addr[2];
+       ofld_req4.dst_mac_addr_hi[0] =  interface->ctlr.dest_addr[1];
+       ofld_req4.dst_mac_addr_hi[1] =  interface->ctlr.dest_addr[0];
 
        ofld_req4.lcq_addr_lo = (u32) tgt->lcq_dma;
        ofld_req4.lcq_addr_hi = (u32)((u64) tgt->lcq_dma >> 32);
@@ -335,7 +350,8 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
                                        struct bnx2fc_rport *tgt)
 {
        struct kwqe *kwqe_arr[2];
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        struct fcoe_kwqe_conn_enable_disable enbl_req;
        struct fc_lport *lport = port->lport;
        struct fc_rport *rport = tgt->rport;
@@ -358,12 +374,12 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
        enbl_req.src_mac_addr_hi[1] =  port->data_src_addr[0];
        memcpy(tgt->src_addr, port->data_src_addr, ETH_ALEN);
 
-       enbl_req.dst_mac_addr_lo[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
-       enbl_req.dst_mac_addr_lo[1] =  hba->ctlr.dest_addr[4];
-       enbl_req.dst_mac_addr_mid[0] =  hba->ctlr.dest_addr[3];
-       enbl_req.dst_mac_addr_mid[1] =  hba->ctlr.dest_addr[2];
-       enbl_req.dst_mac_addr_hi[0] =  hba->ctlr.dest_addr[1];
-       enbl_req.dst_mac_addr_hi[1] =  hba->ctlr.dest_addr[0];
+       enbl_req.dst_mac_addr_lo[0] =  interface->ctlr.dest_addr[5];
+       enbl_req.dst_mac_addr_lo[1] =  interface->ctlr.dest_addr[4];
+       enbl_req.dst_mac_addr_mid[0] =  interface->ctlr.dest_addr[3];
+       enbl_req.dst_mac_addr_mid[1] =  interface->ctlr.dest_addr[2];
+       enbl_req.dst_mac_addr_hi[0] =  interface->ctlr.dest_addr[1];
+       enbl_req.dst_mac_addr_hi[1] =  interface->ctlr.dest_addr[0];
 
        port_id = fc_host_port_id(lport->host);
        if (port_id != tgt->sid) {
@@ -379,10 +395,10 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
        enbl_req.d_id[0] = (port_id & 0x000000FF);
        enbl_req.d_id[1] = (port_id & 0x0000FF00) >> 8;
        enbl_req.d_id[2] = (port_id & 0x00FF0000) >> 16;
-       enbl_req.vlan_tag = hba->vlan_id <<
+       enbl_req.vlan_tag = interface->vlan_id <<
                                FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT;
        enbl_req.vlan_tag |= 3 << FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT;
-       enbl_req.vlan_flag = hba->vlan_enabled;
+       enbl_req.vlan_flag = interface->vlan_enabled;
        enbl_req.context_id = tgt->context_id;
        enbl_req.conn_id = tgt->fcoe_conn_id;
 
@@ -402,7 +418,8 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
 int bnx2fc_send_session_disable_req(struct fcoe_port *port,
                                    struct bnx2fc_rport *tgt)
 {
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        struct fcoe_kwqe_conn_enable_disable disable_req;
        struct kwqe *kwqe_arr[2];
        struct fc_rport *rport = tgt->rport;
@@ -423,12 +440,12 @@ int bnx2fc_send_session_disable_req(struct fcoe_port *port,
        disable_req.src_mac_addr_hi[0] =  tgt->src_addr[1];
        disable_req.src_mac_addr_hi[1] =  tgt->src_addr[0];
 
-       disable_req.dst_mac_addr_lo[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
-       disable_req.dst_mac_addr_lo[1] =  hba->ctlr.dest_addr[4];
-       disable_req.dst_mac_addr_mid[0] =  hba->ctlr.dest_addr[3];
-       disable_req.dst_mac_addr_mid[1] =  hba->ctlr.dest_addr[2];
-       disable_req.dst_mac_addr_hi[0] =  hba->ctlr.dest_addr[1];
-       disable_req.dst_mac_addr_hi[1] =  hba->ctlr.dest_addr[0];
+       disable_req.dst_mac_addr_lo[0] =  interface->ctlr.dest_addr[5];
+       disable_req.dst_mac_addr_lo[1] =  interface->ctlr.dest_addr[4];
+       disable_req.dst_mac_addr_mid[0] =  interface->ctlr.dest_addr[3];
+       disable_req.dst_mac_addr_mid[1] =  interface->ctlr.dest_addr[2];
+       disable_req.dst_mac_addr_hi[0] =  interface->ctlr.dest_addr[1];
+       disable_req.dst_mac_addr_hi[1] =  interface->ctlr.dest_addr[0];
 
        port_id = tgt->sid;
        disable_req.s_id[0] = (port_id & 0x000000FF);
@@ -442,11 +459,11 @@ int bnx2fc_send_session_disable_req(struct fcoe_port *port,
        disable_req.d_id[2] = (port_id & 0x00FF0000) >> 16;
        disable_req.context_id = tgt->context_id;
        disable_req.conn_id = tgt->fcoe_conn_id;
-       disable_req.vlan_tag = hba->vlan_id <<
+       disable_req.vlan_tag = interface->vlan_id <<
                                FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT;
        disable_req.vlan_tag |=
                        3 << FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT;
-       disable_req.vlan_flag = hba->vlan_enabled;
+       disable_req.vlan_flag = interface->vlan_enabled;
 
        kwqe_arr[0] = (struct kwqe *) &disable_req;
 
@@ -525,7 +542,7 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
 {
        struct fcoe_port *port = tgt->port;
        struct fc_lport *lport = port->lport;
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
        struct bnx2fc_unsol_els *unsol_els;
        struct fc_frame_header *fh;
        struct fc_frame *fp;
@@ -586,7 +603,7 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
                fr_eof(fp) = FC_EOF_T;
                fr_crc(fp) = cpu_to_le32(~crc);
                unsol_els->lport = lport;
-               unsol_els->hba = hba;
+               unsol_els->hba = interface->hba;
                unsol_els->fp = fp;
                INIT_WORK(&unsol_els->unsol_els_work, bnx2fc_unsol_els_work);
                queue_work(bnx2fc_wq, &unsol_els->unsol_els_work);
@@ -608,9 +625,12 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
        u32 frame_len, len;
        struct bnx2fc_cmd *io_req = NULL;
        struct fcoe_task_ctx_entry *task, *task_page;
-       struct bnx2fc_hba *hba = tgt->port->priv;
+       struct bnx2fc_interface *interface = tgt->port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        int task_idx, index;
        int rc = 0;
+       u64 err_warn_bit_map;
+       u8 err_warn = 0xff;
 
 
        BNX2FC_TGT_DBG(tgt, "Entered UNSOL COMPLETION wqe = 0x%x\n", wqe);
@@ -673,39 +693,43 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
                BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x\n",
                        err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
 
-               bnx2fc_return_rqe(tgt, 1);
 
                if (xid > BNX2FC_MAX_XID) {
                        BNX2FC_TGT_DBG(tgt, "xid(0x%x) out of FW range\n",
                                   xid);
-                       spin_unlock_bh(&tgt->tgt_lock);
-                       break;
+                       goto ret_err_rqe;
                }
 
                task_idx = xid / BNX2FC_TASKS_PER_PAGE;
                index = xid % BNX2FC_TASKS_PER_PAGE;
                task_page = (struct fcoe_task_ctx_entry *)
-                                               hba->task_ctx[task_idx];
+                                       hba->task_ctx[task_idx];
                task = &(task_page[index]);
 
                io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
-               if (!io_req) {
-                       spin_unlock_bh(&tgt->tgt_lock);
-                       break;
-               }
+               if (!io_req)
+                       goto ret_err_rqe;
 
                if (io_req->cmd_type != BNX2FC_SCSI_CMD) {
                        printk(KERN_ERR PFX "err_warn: Not a SCSI cmd\n");
-                       spin_unlock_bh(&tgt->tgt_lock);
-                       break;
+                       goto ret_err_rqe;
                }
 
                if (test_and_clear_bit(BNX2FC_FLAG_IO_CLEANUP,
                                       &io_req->req_flags)) {
                        BNX2FC_IO_DBG(io_req, "unsol_err: cleanup in "
                                            "progress.. ignore unsol err\n");
-                       spin_unlock_bh(&tgt->tgt_lock);
-                       break;
+                       goto ret_err_rqe;
+               }
+
+               err_warn_bit_map = (u64)
+                       ((u64)err_entry->data.err_warn_bitmap_hi << 32) |
+                       (u64)err_entry->data.err_warn_bitmap_lo;
+               for (i = 0; i < BNX2FC_NUM_ERR_BITS; i++) {
+                       if (err_warn_bit_map & (u64)((u64)1 << i)) {
+                               err_warn = i;
+                               break;
+                       }
                }
 
                /*
@@ -715,26 +739,61 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
                 * logging out the target, when the ABTS eventually
                 * times out.
                 */
-               if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS,
-                                     &io_req->req_flags)) {
-                       /*
-                        * Cancel the timeout_work, as we received IO
-                        * completion with FW error.
-                        */
-                       if (cancel_delayed_work(&io_req->timeout_work))
-                               kref_put(&io_req->refcount,
-                                        bnx2fc_cmd_release); /* timer hold */
-
-                       rc = bnx2fc_initiate_abts(io_req);
-                       if (rc != SUCCESS) {
-                               BNX2FC_IO_DBG(io_req, "err_warn: initiate_abts "
-                                       "failed. issue cleanup\n");
-                               rc = bnx2fc_initiate_cleanup(io_req);
-                               BUG_ON(rc);
-                       }
-               } else
+               if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) {
                        printk(KERN_ERR PFX "err_warn: io_req (0x%x) already "
                                            "in ABTS processing\n", xid);
+                       goto ret_err_rqe;
+               }
+               BNX2FC_TGT_DBG(tgt, "err = 0x%x\n", err_warn);
+               if (tgt->dev_type != TYPE_TAPE)
+                       goto skip_rec;
+               switch (err_warn) {
+               case FCOE_ERROR_CODE_REC_TOV_TIMER_EXPIRATION:
+               case FCOE_ERROR_CODE_DATA_OOO_RO:
+               case FCOE_ERROR_CODE_COMMON_INCORRECT_SEQ_CNT:
+               case FCOE_ERROR_CODE_DATA_SOFI3_SEQ_ACTIVE_SET:
+               case FCOE_ERROR_CODE_FCP_RSP_OPENED_SEQ:
+               case FCOE_ERROR_CODE_DATA_SOFN_SEQ_ACTIVE_RESET:
+                       BNX2FC_TGT_DBG(tgt, "REC TOV popped for xid - 0x%x\n",
+                                  xid);
+                       memset(&io_req->err_entry, 0,
+                              sizeof(struct fcoe_err_report_entry));
+                       memcpy(&io_req->err_entry, err_entry,
+                              sizeof(struct fcoe_err_report_entry));
+                       if (!test_bit(BNX2FC_FLAG_SRR_SENT,
+                                     &io_req->req_flags)) {
+                               spin_unlock_bh(&tgt->tgt_lock);
+                               rc = bnx2fc_send_rec(io_req);
+                               spin_lock_bh(&tgt->tgt_lock);
+
+                               if (rc)
+                                       goto skip_rec;
+                       } else
+                               printk(KERN_ERR PFX "SRR in progress\n");
+                       goto ret_err_rqe;
+                       break;
+               default:
+                       break;
+               }
+
+skip_rec:
+               set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags);
+               /*
+                * Cancel the timeout_work, as we received IO
+                * completion with FW error.
+                */
+               if (cancel_delayed_work(&io_req->timeout_work))
+                       kref_put(&io_req->refcount, bnx2fc_cmd_release);
+
+               rc = bnx2fc_initiate_abts(io_req);
+               if (rc != SUCCESS) {
+                       printk(KERN_ERR PFX "err_warn: initiate_abts "
+                               "failed xid = 0x%x. issue cleanup\n",
+                               io_req->xid);
+                       bnx2fc_initiate_cleanup(io_req);
+               }
+ret_err_rqe:
+               bnx2fc_return_rqe(tgt, 1);
                spin_unlock_bh(&tgt->tgt_lock);
                break;
 
@@ -755,6 +814,47 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
                BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x",
                        err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
 
+               if (xid > BNX2FC_MAX_XID) {
+                       BNX2FC_TGT_DBG(tgt, "xid(0x%x) out of FW range\n", xid);
+                       goto ret_warn_rqe;
+               }
+
+               err_warn_bit_map = (u64)
+                       ((u64)err_entry->data.err_warn_bitmap_hi << 32) |
+                       (u64)err_entry->data.err_warn_bitmap_lo;
+               for (i = 0; i < BNX2FC_NUM_ERR_BITS; i++) {
+                       if (err_warn_bit_map & (u64) (1 << i)) {
+                               err_warn = i;
+                               break;
+                       }
+               }
+               BNX2FC_TGT_DBG(tgt, "warn = 0x%x\n", err_warn);
+
+               task_idx = xid / BNX2FC_TASKS_PER_PAGE;
+               index = xid % BNX2FC_TASKS_PER_PAGE;
+               task_page = (struct fcoe_task_ctx_entry *)
+                            interface->hba->task_ctx[task_idx];
+               task = &(task_page[index]);
+               io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
+               if (!io_req)
+                       goto ret_warn_rqe;
+
+               if (io_req->cmd_type != BNX2FC_SCSI_CMD) {
+                       printk(KERN_ERR PFX "err_warn: Not a SCSI cmd\n");
+                       goto ret_warn_rqe;
+               }
+
+               memset(&io_req->err_entry, 0,
+                      sizeof(struct fcoe_err_report_entry));
+               memcpy(&io_req->err_entry, err_entry,
+                      sizeof(struct fcoe_err_report_entry));
+
+               if (err_warn == FCOE_ERROR_CODE_REC_TOV_TIMER_EXPIRATION)
+                       /* REC_TOV is not a warning code */
+                       BUG_ON(1);
+               else
+                       BNX2FC_TGT_DBG(tgt, "Unsolicited warning\n");
+ret_warn_rqe:
                bnx2fc_return_rqe(tgt, 1);
                spin_unlock_bh(&tgt->tgt_lock);
                break;
@@ -770,7 +870,8 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
        struct fcoe_task_ctx_entry *task;
        struct fcoe_task_ctx_entry *task_page;
        struct fcoe_port *port = tgt->port;
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        struct bnx2fc_cmd *io_req;
        int task_idx, index;
        u16 xid;
@@ -781,7 +882,7 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
        spin_lock_bh(&tgt->tgt_lock);
        xid = wqe & FCOE_PEND_WQ_CQE_TASK_ID;
        if (xid >= BNX2FC_MAX_TASKS) {
-               printk(KERN_ALERT PFX "ERROR:xid out of range\n");
+               printk(KERN_ERR PFX "ERROR:xid out of range\n");
                spin_unlock_bh(&tgt->tgt_lock);
                return;
        }
@@ -861,6 +962,13 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
                kref_put(&io_req->refcount, bnx2fc_cmd_release);
                break;
 
+       case BNX2FC_SEQ_CLEANUP:
+               BNX2FC_IO_DBG(io_req, "cq_compl(0x%x) - seq cleanup resp\n",
+                             io_req->xid);
+               bnx2fc_process_seq_cleanup_compl(io_req, task, rx_state);
+               kref_put(&io_req->refcount, bnx2fc_cmd_release);
+               break;
+
        default:
                printk(KERN_ERR PFX "Invalid cmd_type %d\n", cmd_type);
                break;
@@ -962,8 +1070,10 @@ unlock:
                                1 - tgt->cq_curr_toggle_bit;
                }
        }
-       bnx2fc_arm_cq(tgt);
-       atomic_add(num_free_sqes, &tgt->free_sqes);
+       if (num_free_sqes) {
+               bnx2fc_arm_cq(tgt);
+               atomic_add(num_free_sqes, &tgt->free_sqes);
+       }
        spin_unlock_bh(&tgt->cq_lock);
        return 0;
 }
@@ -983,7 +1093,7 @@ static void bnx2fc_fastpath_notification(struct bnx2fc_hba *hba,
        struct bnx2fc_rport *tgt = hba->tgt_ofld_list[conn_id];
 
        if (!tgt) {
-               printk(KERN_ALERT PFX "conn_id 0x%x not valid\n", conn_id);
+               printk(KERN_ERR PFX "conn_id 0x%x not valid\n", conn_id);
                return;
        }
 
@@ -1004,6 +1114,7 @@ static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
 {
        struct bnx2fc_rport             *tgt;
        struct fcoe_port                *port;
+       struct bnx2fc_interface         *interface;
        u32                             conn_id;
        u32                             context_id;
        int                             rc;
@@ -1018,8 +1129,9 @@ static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
        BNX2FC_TGT_DBG(tgt, "Entered ofld compl - context_id = 0x%x\n",
                ofld_kcqe->fcoe_conn_context_id);
        port = tgt->port;
-       if (hba != tgt->port->priv) {
-               printk(KERN_ALERT PFX "ERROR:ofld_cmpl: HBA mis-match\n");
+       interface = tgt->port->priv;
+       if (hba != interface->hba) {
+               printk(KERN_ERR PFX "ERROR:ofld_cmpl: HBA mis-match\n");
                goto ofld_cmpl_err;
        }
        /*
@@ -1040,7 +1152,7 @@ static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
                /* now enable the session */
                rc = bnx2fc_send_session_enable_req(port, tgt);
                if (rc) {
-                       printk(KERN_ALERT PFX "enable session failed\n");
+                       printk(KERN_ERR PFX "enable session failed\n");
                        goto ofld_cmpl_err;
                }
        }
@@ -1063,6 +1175,7 @@ static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
                                                struct fcoe_kcqe *ofld_kcqe)
 {
        struct bnx2fc_rport             *tgt;
+       struct bnx2fc_interface         *interface;
        u32                             conn_id;
        u32                             context_id;
 
@@ -1070,7 +1183,7 @@ static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
        conn_id = ofld_kcqe->fcoe_conn_id;
        tgt = hba->tgt_ofld_list[conn_id];
        if (!tgt) {
-               printk(KERN_ALERT PFX "ERROR:enbl_cmpl: No pending ofld req\n");
+               printk(KERN_ERR PFX "ERROR:enbl_cmpl: No pending ofld req\n");
                return;
        }
 
@@ -1082,16 +1195,17 @@ static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
         * and enable
         */
        if (tgt->context_id != context_id) {
-               printk(KERN_ALERT PFX "context id mis-match\n");
+               printk(KERN_ERR PFX "context id mis-match\n");
                return;
        }
-       if (hba != tgt->port->priv) {
-               printk(KERN_ALERT PFX "bnx2fc-enbl_cmpl: HBA mis-match\n");
+       interface = tgt->port->priv;
+       if (hba != interface->hba) {
+               printk(KERN_ERR PFX "bnx2fc-enbl_cmpl: HBA mis-match\n");
                goto enbl_cmpl_err;
        }
-       if (ofld_kcqe->completion_status) {
+       if (ofld_kcqe->completion_status)
                goto enbl_cmpl_err;
-       else {
+       else {
                /* enable successful - rport ready for issuing IOs */
                set_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
                set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
@@ -1114,14 +1228,14 @@ static void bnx2fc_process_conn_disable_cmpl(struct bnx2fc_hba *hba,
        conn_id = disable_kcqe->fcoe_conn_id;
        tgt = hba->tgt_ofld_list[conn_id];
        if (!tgt) {
-               printk(KERN_ALERT PFX "ERROR: disable_cmpl: No disable req\n");
+               printk(KERN_ERR PFX "ERROR: disable_cmpl: No disable req\n");
                return;
        }
 
        BNX2FC_TGT_DBG(tgt, PFX "disable_cmpl: conn_id %d\n", conn_id);
 
        if (disable_kcqe->completion_status) {
-               printk(KERN_ALERT PFX "ERROR: Disable failed with cmpl status %d\n",
+               printk(KERN_ERR PFX "Disable failed with cmpl status %d\n",
                        disable_kcqe->completion_status);
                return;
        } else {
@@ -1143,14 +1257,14 @@ static void bnx2fc_process_conn_destroy_cmpl(struct bnx2fc_hba *hba,
        conn_id = destroy_kcqe->fcoe_conn_id;
        tgt = hba->tgt_ofld_list[conn_id];
        if (!tgt) {
-               printk(KERN_ALERT PFX "destroy_cmpl: No destroy req\n");
+               printk(KERN_ERR PFX "destroy_cmpl: No destroy req\n");
                return;
        }
 
        BNX2FC_TGT_DBG(tgt, "destroy_cmpl: conn_id %d\n", conn_id);
 
        if (destroy_kcqe->completion_status) {
-               printk(KERN_ALERT PFX "Destroy conn failed, cmpl status %d\n",
+               printk(KERN_ERR PFX "Destroy conn failed, cmpl status %d\n",
                        destroy_kcqe->completion_status);
                return;
        } else {
@@ -1182,6 +1296,7 @@ static void bnx2fc_init_failure(struct bnx2fc_hba *hba, u32 err_code)
                break;
        case FCOE_KCQE_COMPLETION_STATUS_WRONG_HSI_VERSION:
                printk(KERN_ERR PFX "init failure due to HSI mismatch\n");
+               break;
        default:
                printk(KERN_ERR PFX "Unknown Error code %d\n", err_code);
        }
@@ -1240,7 +1355,7 @@ void bnx2fc_indicate_kcqe(void *context, struct kcqe *kcq[],
                        } else {
                                printk(KERN_ERR PFX "DESTROY success\n");
                        }
-                       hba->flags |= BNX2FC_FLAG_DESTROY_CMPL;
+                       set_bit(BNX2FC_FLAG_DESTROY_CMPL, &hba->flags);
                        wake_up_interruptible(&hba->destroy_wait);
                        break;
 
@@ -1262,7 +1377,7 @@ void bnx2fc_indicate_kcqe(void *context, struct kcqe *kcq[],
                case FCOE_KCQE_OPCODE_FCOE_ERROR:
                        /* fall thru */
                default:
-                       printk(KERN_ALERT PFX "unknown opcode 0x%x\n",
+                       printk(KERN_ERR PFX "unknown opcode 0x%x\n",
                                                                kcqe->op_code);
                }
        }
@@ -1305,7 +1420,8 @@ int bnx2fc_map_doorbell(struct bnx2fc_rport *tgt)
        struct fcoe_port *port = tgt->port;
        u32 reg_off;
        resource_size_t reg_base;
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
 
        reg_base = pci_resource_start(hba->pcidev,
                                        BNX2X_DOORBELL_PCI_BAR);
@@ -1344,6 +1460,96 @@ void bnx2fc_return_rqe(struct bnx2fc_rport *tgt, u8 num_items)
        tgt->conn_db->rq_prod = tgt->rq_prod_idx;
 }
 
+void bnx2fc_init_seq_cleanup_task(struct bnx2fc_cmd *seq_clnp_req,
+                                 struct fcoe_task_ctx_entry *task,
+                                 struct bnx2fc_cmd *orig_io_req,
+                                 u32 offset)
+{
+       struct scsi_cmnd *sc_cmd = orig_io_req->sc_cmd;
+       struct bnx2fc_rport *tgt = seq_clnp_req->tgt;
+       struct bnx2fc_interface *interface = tgt->port->priv;
+       struct fcoe_bd_ctx *bd = orig_io_req->bd_tbl->bd_tbl;
+       struct fcoe_task_ctx_entry *orig_task;
+       struct fcoe_task_ctx_entry *task_page;
+       struct fcoe_ext_mul_sges_ctx *sgl;
+       u8 task_type = FCOE_TASK_TYPE_SEQUENCE_CLEANUP;
+       u8 orig_task_type;
+       u16 orig_xid = orig_io_req->xid;
+       u32 context_id = tgt->context_id;
+       u64 phys_addr = (u64)orig_io_req->bd_tbl->bd_tbl_dma;
+       u32 orig_offset = offset;
+       int bd_count;
+       int orig_task_idx, index;
+       int i;
+
+       memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
+
+       if (sc_cmd->sc_data_direction == DMA_TO_DEVICE)
+               orig_task_type = FCOE_TASK_TYPE_WRITE;
+       else
+               orig_task_type = FCOE_TASK_TYPE_READ;
+
+       /* Tx flags */
+       task->txwr_rxrd.const_ctx.tx_flags =
+                               FCOE_TASK_TX_STATE_SEQUENCE_CLEANUP <<
+                               FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
+       /* init flags */
+       task->txwr_rxrd.const_ctx.init_flags = task_type <<
+                               FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+       task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+                               FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+       task->rxwr_txrd.const_ctx.init_flags = context_id <<
+                               FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+       task->rxwr_txrd.const_ctx.init_flags = context_id <<
+                               FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+
+       task->txwr_rxrd.union_ctx.cleanup.ctx.cleaned_task_id = orig_xid;
+
+       task->txwr_rxrd.union_ctx.cleanup.ctx.rolled_tx_seq_cnt = 0;
+       task->txwr_rxrd.union_ctx.cleanup.ctx.rolled_tx_data_offset = offset;
+
+       bd_count = orig_io_req->bd_tbl->bd_valid;
+
+       /* obtain the appropriate bd entry from relative offset */
+       for (i = 0; i < bd_count; i++) {
+               if (offset < bd[i].buf_len)
+                       break;
+               offset -= bd[i].buf_len;
+       }
+       phys_addr += (i * sizeof(struct fcoe_bd_ctx));
+
+       if (orig_task_type == FCOE_TASK_TYPE_WRITE) {
+               task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.lo =
+                               (u32)phys_addr;
+               task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.hi =
+                               (u32)((u64)phys_addr >> 32);
+               task->txwr_only.sgl_ctx.sgl.mul_sgl.sgl_size =
+                               bd_count;
+               task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_off =
+                               offset; /* adjusted offset */
+               task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_idx = i;
+       } else {
+               orig_task_idx = orig_xid / BNX2FC_TASKS_PER_PAGE;
+               index = orig_xid % BNX2FC_TASKS_PER_PAGE;
+
+               task_page = (struct fcoe_task_ctx_entry *)
+                            interface->hba->task_ctx[orig_task_idx];
+               orig_task = &(task_page[index]);
+
+               /* Multiple SGEs were used for this IO */
+               sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl;
+               sgl->mul_sgl.cur_sge_addr.lo = (u32)phys_addr;
+               sgl->mul_sgl.cur_sge_addr.hi = (u32)((u64)phys_addr >> 32);
+               sgl->mul_sgl.sgl_size = bd_count;
+               sgl->mul_sgl.cur_sge_off = offset; /*adjusted offset */
+               sgl->mul_sgl.cur_sge_idx = i;
+
+               memset(&task->rxwr_only.rx_seq_ctx, 0,
+                      sizeof(struct fcoe_rx_seq_ctx));
+               task->rxwr_only.rx_seq_ctx.low_exp_ro = orig_offset;
+               task->rxwr_only.rx_seq_ctx.high_exp_ro = orig_offset;
+       }
+}
 void bnx2fc_init_cleanup_task(struct bnx2fc_cmd *io_req,
                              struct fcoe_task_ctx_entry *task,
                              u16 orig_xid)
@@ -1360,7 +1566,12 @@ void bnx2fc_init_cleanup_task(struct bnx2fc_cmd *io_req,
                                FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
        task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
                                FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
-       task->txwr_rxrd.const_ctx.init_flags |=
+       if (tgt->dev_type == TYPE_TAPE)
+               task->txwr_rxrd.const_ctx.init_flags |=
+                               FCOE_TASK_DEV_TYPE_TAPE <<
+                               FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+       else
+               task->txwr_rxrd.const_ctx.init_flags |=
                                FCOE_TASK_DEV_TYPE_DISK <<
                                FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
        task->txwr_rxrd.union_ctx.cleanup.ctx.cleaned_task_id = orig_xid;
@@ -1420,7 +1631,12 @@ void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
        /* init flags */
        task->txwr_rxrd.const_ctx.init_flags = task_type <<
                                FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
-       task->txwr_rxrd.const_ctx.init_flags |=
+       if (tgt->dev_type == TYPE_TAPE)
+               task->txwr_rxrd.const_ctx.init_flags |=
+                               FCOE_TASK_DEV_TYPE_TAPE <<
+                               FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+       else
+               task->txwr_rxrd.const_ctx.init_flags |=
                                FCOE_TASK_DEV_TYPE_DISK <<
                                FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
        task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
@@ -1477,6 +1693,7 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
        struct bnx2fc_rport *tgt = io_req->tgt;
        struct fcoe_cached_sge_ctx *cached_sge;
        struct fcoe_ext_mul_sges_ctx *sgl;
+       int dev_type = tgt->dev_type;
        u64 *fcp_cmnd;
        u64 tmp_fcp_cmnd[4];
        u32 context_id;
@@ -1494,20 +1711,40 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
                task_type = FCOE_TASK_TYPE_READ;
 
        /* Tx only */
+       bd_count = bd_tbl->bd_valid;
        if (task_type == FCOE_TASK_TYPE_WRITE) {
-               task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.lo =
-                               (u32)bd_tbl->bd_tbl_dma;
-               task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.hi =
-                               (u32)((u64)bd_tbl->bd_tbl_dma >> 32);
-               task->txwr_only.sgl_ctx.sgl.mul_sgl.sgl_size =
-                               bd_tbl->bd_valid;
+               if ((dev_type == TYPE_DISK) && (bd_count == 1)) {
+                       struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
+
+                       task->txwr_only.sgl_ctx.cached_sge.cur_buf_addr.lo =
+                                       fcoe_bd_tbl->buf_addr_lo;
+                       task->txwr_only.sgl_ctx.cached_sge.cur_buf_addr.hi =
+                                       fcoe_bd_tbl->buf_addr_hi;
+                       task->txwr_only.sgl_ctx.cached_sge.cur_buf_rem =
+                                       fcoe_bd_tbl->buf_len;
+
+                       task->txwr_rxrd.const_ctx.init_flags |= 1 <<
+                               FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT;
+               } else {
+                       task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.lo =
+                                       (u32)bd_tbl->bd_tbl_dma;
+                       task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.hi =
+                                       (u32)((u64)bd_tbl->bd_tbl_dma >> 32);
+                       task->txwr_only.sgl_ctx.sgl.mul_sgl.sgl_size =
+                                       bd_tbl->bd_valid;
+               }
        }
 
        /*Tx Write Rx Read */
        /* Init state to NORMAL */
-       task->txwr_rxrd.const_ctx.init_flags = task_type <<
+       task->txwr_rxrd.const_ctx.init_flags |= task_type <<
                                FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
-       task->txwr_rxrd.const_ctx.init_flags |=
+       if (dev_type == TYPE_TAPE)
+               task->txwr_rxrd.const_ctx.init_flags |=
+                               FCOE_TASK_DEV_TYPE_TAPE <<
+                               FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+       else
+               task->txwr_rxrd.const_ctx.init_flags |=
                                FCOE_TASK_DEV_TYPE_DISK <<
                                FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
        task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
@@ -1550,7 +1787,8 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
        cached_sge = &task->rxwr_only.union_ctx.read_info.sgl_ctx.cached_sge;
        sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl;
        bd_count = bd_tbl->bd_valid;
-       if (task_type == FCOE_TASK_TYPE_READ) {
+       if (task_type == FCOE_TASK_TYPE_READ &&
+           dev_type == TYPE_DISK) {
                if (bd_count == 1) {
 
                        struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
@@ -1582,6 +1820,11 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
                                        (u32)((u64)bd_tbl->bd_tbl_dma >> 32);
                        sgl->mul_sgl.sgl_size = bd_count;
                }
+       } else {
+               sgl->mul_sgl.cur_sge_addr.lo = (u32)bd_tbl->bd_tbl_dma;
+               sgl->mul_sgl.cur_sge_addr.hi =
+                               (u32)((u64)bd_tbl->bd_tbl_dma >> 32);
+               sgl->mul_sgl.sgl_size = bd_count;
        }
 }
 
index 45eba6d..6cc3789 100644 (file)
@@ -1,7 +1,7 @@
 /* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver.
  * IO manager and SCSI IO processing.
  *
- * Copyright (c) 2008 - 2010 Broadcom Corporation
+ * Copyright (c) 2008 - 2011 Broadcom 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
@@ -18,8 +18,6 @@ static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, u64 addr, int sg_len,
                           int bd_index);
 static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req);
 static void bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req);
-static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
-                              struct bnx2fc_cmd *io_req);
 static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req);
 static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req);
 static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
@@ -29,10 +27,11 @@ static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
 void bnx2fc_cmd_timer_set(struct bnx2fc_cmd *io_req,
                          unsigned int timer_msec)
 {
-       struct bnx2fc_hba *hba = io_req->port->priv;
+       struct bnx2fc_interface *interface = io_req->port->priv;
 
-       if (queue_delayed_work(hba->timer_work_queue, &io_req->timeout_work,
-                                 msecs_to_jiffies(timer_msec)))
+       if (queue_delayed_work(interface->timer_work_queue,
+                              &io_req->timeout_work,
+                              msecs_to_jiffies(timer_msec)))
                kref_get(&io_req->refcount);
 }
 
@@ -217,6 +216,11 @@ static void bnx2fc_scsi_done(struct bnx2fc_cmd *io_req, int err_code)
                return;
 
        BNX2FC_IO_DBG(io_req, "scsi_done. err_code = 0x%x\n", err_code);
+       if (test_bit(BNX2FC_FLAG_CMD_LOST, &io_req->req_flags)) {
+               /* Do not call scsi done for this IO */
+               return;
+       }
+
        bnx2fc_unmap_sg_list(io_req);
        io_req->sc_cmd = NULL;
        if (!sc_cmd) {
@@ -419,8 +423,8 @@ free_cmgr:
 struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
 {
        struct fcoe_port *port = tgt->port;
-       struct bnx2fc_hba *hba = port->priv;
-       struct bnx2fc_cmd_mgr *cmd_mgr = hba->cmd_mgr;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_cmd_mgr *cmd_mgr = interface->hba->cmd_mgr;
        struct bnx2fc_cmd *io_req;
        struct list_head *listp;
        struct io_bdt *bd_tbl;
@@ -485,11 +489,12 @@ struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
        kref_init(&io_req->refcount);
        return io_req;
 }
-static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
+
+struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
 {
        struct fcoe_port *port = tgt->port;
-       struct bnx2fc_hba *hba = port->priv;
-       struct bnx2fc_cmd_mgr *cmd_mgr = hba->cmd_mgr;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_cmd_mgr *cmd_mgr = interface->hba->cmd_mgr;
        struct bnx2fc_cmd *io_req;
        struct list_head *listp;
        struct io_bdt *bd_tbl;
@@ -570,7 +575,8 @@ void bnx2fc_cmd_release(struct kref *ref)
 static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req)
 {
        struct bnx2fc_mp_req *mp_req = &(io_req->mp_req);
-       struct bnx2fc_hba *hba = io_req->port->priv;
+       struct bnx2fc_interface *interface = io_req->port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        size_t sz = sizeof(struct fcoe_bd_ctx);
 
        /* clear tm flags */
@@ -606,7 +612,8 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
        struct bnx2fc_mp_req *mp_req;
        struct fcoe_bd_ctx *mp_req_bd;
        struct fcoe_bd_ctx *mp_resp_bd;
-       struct bnx2fc_hba *hba = io_req->port->priv;
+       struct bnx2fc_interface *interface = io_req->port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        dma_addr_t addr;
        size_t sz;
 
@@ -682,7 +689,7 @@ static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
        struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
        struct fc_rport_libfc_priv *rp = rport->dd_data;
        struct fcoe_port *port;
-       struct bnx2fc_hba *hba;
+       struct bnx2fc_interface *interface;
        struct bnx2fc_rport *tgt;
        struct bnx2fc_cmd *io_req;
        struct bnx2fc_mp_req *tm_req;
@@ -699,10 +706,10 @@ static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
 
        lport = shost_priv(host);
        port = lport_priv(lport);
-       hba = port->priv;
+       interface = port->priv;
 
        if (rport == NULL) {
-               printk(KERN_ALERT PFX "device_reset: rport is NULL\n");
+               printk(KERN_ERR PFX "device_reset: rport is NULL\n");
                rc = FAILED;
                goto tmf_err;
        }
@@ -745,7 +752,9 @@ retry_tmf:
        rc = bnx2fc_init_mp_req(io_req);
        if (rc == FAILED) {
                printk(KERN_ERR PFX "Task mgmt MP request init failed\n");
+               spin_lock_bh(&tgt->tgt_lock);
                kref_put(&io_req->refcount, bnx2fc_cmd_release);
+               spin_unlock_bh(&tgt->tgt_lock);
                goto tmf_err;
        }
 
@@ -774,7 +783,8 @@ retry_tmf:
        index = xid % BNX2FC_TASKS_PER_PAGE;
 
        /* Initialize task context for this IO request */
-       task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+       task_page = (struct fcoe_task_ctx_entry *)
+                       interface->hba->task_ctx[task_idx];
        task = &(task_page[index]);
        bnx2fc_init_mp_task(io_req, task);
 
@@ -806,10 +816,10 @@ retry_tmf:
        spin_unlock_bh(&tgt->tgt_lock);
 
        if (!rc) {
-               printk(KERN_ERR PFX "task mgmt command failed...\n");
+               BNX2FC_TGT_DBG(tgt, "task mgmt command failed...\n");
                rc = FAILED;
        } else {
-               printk(KERN_ERR PFX "task mgmt command success...\n");
+               BNX2FC_TGT_DBG(tgt, "task mgmt command success...\n");
                rc = SUCCESS;
        }
 tmf_err:
@@ -822,7 +832,7 @@ int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
        struct bnx2fc_rport *tgt = io_req->tgt;
        struct fc_rport *rport = tgt->rport;
        struct fc_rport_priv *rdata = tgt->rdata;
-       struct bnx2fc_hba *hba;
+       struct bnx2fc_interface *interface;
        struct fcoe_port *port;
        struct bnx2fc_cmd *abts_io_req;
        struct fcoe_task_ctx_entry *task;
@@ -839,7 +849,7 @@ int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
        BNX2FC_IO_DBG(io_req, "Entered bnx2fc_initiate_abts\n");
 
        port = io_req->port;
-       hba = port->priv;
+       interface = port->priv;
        lport = port->lport;
 
        if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
@@ -849,7 +859,7 @@ int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
        }
 
        if (rport == NULL) {
-               printk(KERN_ALERT PFX "initiate_abts: rport is NULL\n");
+               printk(KERN_ERR PFX "initiate_abts: rport is NULL\n");
                rc = FAILED;
                goto abts_err;
        }
@@ -896,7 +906,8 @@ int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
        index = xid % BNX2FC_TASKS_PER_PAGE;
 
        /* Initialize task context for this IO request */
-       task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+       task_page = (struct fcoe_task_ctx_entry *)
+                       interface->hba->task_ctx[task_idx];
        task = &(task_page[index]);
        bnx2fc_init_mp_task(abts_io_req, task);
 
@@ -924,11 +935,81 @@ abts_err:
        return rc;
 }
 
+int bnx2fc_initiate_seq_cleanup(struct bnx2fc_cmd *orig_io_req, u32 offset,
+                               enum fc_rctl r_ctl)
+{
+       struct fc_lport *lport;
+       struct bnx2fc_rport *tgt = orig_io_req->tgt;
+       struct bnx2fc_interface *interface;
+       struct fcoe_port *port;
+       struct bnx2fc_cmd *seq_clnp_req;
+       struct fcoe_task_ctx_entry *task;
+       struct fcoe_task_ctx_entry *task_page;
+       struct bnx2fc_els_cb_arg *cb_arg = NULL;
+       int task_idx, index;
+       u16 xid;
+       int rc = 0;
+
+       BNX2FC_IO_DBG(orig_io_req, "bnx2fc_initiate_seq_cleanup xid = 0x%x\n",
+                  orig_io_req->xid);
+       kref_get(&orig_io_req->refcount);
+
+       port = orig_io_req->port;
+       interface = port->priv;
+       lport = port->lport;
+
+       cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
+       if (!cb_arg) {
+               printk(KERN_ERR PFX "Unable to alloc cb_arg for seq clnup\n");
+               rc = -ENOMEM;
+               goto cleanup_err;
+       }
+
+       seq_clnp_req = bnx2fc_elstm_alloc(tgt, BNX2FC_SEQ_CLEANUP);
+       if (!seq_clnp_req) {
+               printk(KERN_ERR PFX "cleanup: couldnt allocate cmd\n");
+               rc = -ENOMEM;
+               kfree(cb_arg);
+               goto cleanup_err;
+       }
+       /* Initialize rest of io_req fields */
+       seq_clnp_req->sc_cmd = NULL;
+       seq_clnp_req->port = port;
+       seq_clnp_req->tgt = tgt;
+       seq_clnp_req->data_xfer_len = 0; /* No data transfer for cleanup */
+
+       xid = seq_clnp_req->xid;
+
+       task_idx = xid/BNX2FC_TASKS_PER_PAGE;
+       index = xid % BNX2FC_TASKS_PER_PAGE;
+
+       /* Initialize task context for this IO request */
+       task_page = (struct fcoe_task_ctx_entry *)
+                    interface->hba->task_ctx[task_idx];
+       task = &(task_page[index]);
+       cb_arg->aborted_io_req = orig_io_req;
+       cb_arg->io_req = seq_clnp_req;
+       cb_arg->r_ctl = r_ctl;
+       cb_arg->offset = offset;
+       seq_clnp_req->cb_arg = cb_arg;
+
+       printk(KERN_ERR PFX "call init_seq_cleanup_task\n");
+       bnx2fc_init_seq_cleanup_task(seq_clnp_req, task, orig_io_req, offset);
+
+       /* Obtain free SQ entry */
+       bnx2fc_add_2_sq(tgt, xid);
+
+       /* Ring doorbell */
+       bnx2fc_ring_doorbell(tgt);
+cleanup_err:
+       return rc;
+}
+
 int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req)
 {
        struct fc_lport *lport;
        struct bnx2fc_rport *tgt = io_req->tgt;
-       struct bnx2fc_hba *hba;
+       struct bnx2fc_interface *interface;
        struct fcoe_port *port;
        struct bnx2fc_cmd *cleanup_io_req;
        struct fcoe_task_ctx_entry *task;
@@ -941,7 +1022,7 @@ int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req)
        BNX2FC_IO_DBG(io_req, "Entered bnx2fc_initiate_cleanup\n");
 
        port = io_req->port;
-       hba = port->priv;
+       interface = port->priv;
        lport = port->lport;
 
        cleanup_io_req = bnx2fc_elstm_alloc(tgt, BNX2FC_CLEANUP);
@@ -963,7 +1044,8 @@ int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req)
        index = xid % BNX2FC_TASKS_PER_PAGE;
 
        /* Initialize task context for this IO request */
-       task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+       task_page = (struct fcoe_task_ctx_entry *)
+                       interface->hba->task_ctx[task_idx];
        task = &(task_page[index]);
        orig_xid = io_req->xid;
 
@@ -1031,7 +1113,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
 
        lport = shost_priv(sc_cmd->device->host);
        if ((lport->state != LPORT_ST_READY) || !(lport->link_up)) {
-               printk(KERN_ALERT PFX "eh_abort: link not ready\n");
+               printk(KERN_ERR PFX "eh_abort: link not ready\n");
                return rc;
        }
 
@@ -1062,7 +1144,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
         * io_req is no longer in the active_q.
         */
        if (tgt->flush_in_prog) {
-               printk(KERN_ALERT PFX "eh_abort: io_req (xid = 0x%x) "
+               printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) "
                        "flush in progress\n", io_req->xid);
                kref_put(&io_req->refcount, bnx2fc_cmd_release);
                spin_unlock_bh(&tgt->tgt_lock);
@@ -1070,7 +1152,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
        }
 
        if (io_req->on_active_queue == 0) {
-               printk(KERN_ALERT PFX "eh_abort: io_req (xid = 0x%x) "
+               printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) "
                                "not on active_q\n", io_req->xid);
                /*
                 * This condition can happen only due to the FW bug,
@@ -1108,7 +1190,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
                set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags);
                rc = bnx2fc_initiate_abts(io_req);
        } else {
-               printk(KERN_ALERT PFX "eh_abort: io_req (xid = 0x%x) "
+               printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) "
                                "already in abts processing\n", io_req->xid);
                kref_put(&io_req->refcount, bnx2fc_cmd_release);
                spin_unlock_bh(&tgt->tgt_lock);
@@ -1149,6 +1231,42 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
        return rc;
 }
 
+void bnx2fc_process_seq_cleanup_compl(struct bnx2fc_cmd *seq_clnp_req,
+                                     struct fcoe_task_ctx_entry *task,
+                                     u8 rx_state)
+{
+       struct bnx2fc_els_cb_arg *cb_arg = seq_clnp_req->cb_arg;
+       struct bnx2fc_cmd *orig_io_req = cb_arg->aborted_io_req;
+       u32 offset = cb_arg->offset;
+       enum fc_rctl r_ctl = cb_arg->r_ctl;
+       int rc = 0;
+       struct bnx2fc_rport *tgt = orig_io_req->tgt;
+
+       BNX2FC_IO_DBG(orig_io_req, "Entered process_cleanup_compl xid = 0x%x"
+                             "cmd_type = %d\n",
+                  seq_clnp_req->xid, seq_clnp_req->cmd_type);
+
+       if (rx_state == FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP) {
+               printk(KERN_ERR PFX "seq cleanup ignored - xid = 0x%x\n",
+                       seq_clnp_req->xid);
+               goto free_cb_arg;
+       }
+       kref_get(&orig_io_req->refcount);
+
+       spin_unlock_bh(&tgt->tgt_lock);
+       rc = bnx2fc_send_srr(orig_io_req, offset, r_ctl);
+       spin_lock_bh(&tgt->tgt_lock);
+
+       if (rc)
+               printk(KERN_ERR PFX "clnup_compl: Unable to send SRR"
+                       " IO will abort\n");
+       seq_clnp_req->cb_arg = NULL;
+       kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
+free_cb_arg:
+       kfree(cb_arg);
+       return;
+}
+
 void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req,
                                  struct fcoe_task_ctx_entry *task,
                                  u8 num_rq)
@@ -1378,7 +1496,7 @@ void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
                        fc_hdr->fh_r_ctl);
        }
        if (!sc_cmd->SCp.ptr) {
-               printk(KERN_ALERT PFX "tm_compl: SCp.ptr is NULL\n");
+               printk(KERN_ERR PFX "tm_compl: SCp.ptr is NULL\n");
                return;
        }
        switch (io_req->fcp_status) {
@@ -1410,7 +1528,7 @@ void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
                io_req->on_tmf_queue = 0;
        } else {
 
-               printk(KERN_ALERT PFX "Command not on active_cmd_queue!\n");
+               printk(KERN_ERR PFX "Command not on active_cmd_queue!\n");
                return;
        }
 
@@ -1597,7 +1715,7 @@ static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
 
                if (rq_buff_len > num_rq * BNX2FC_RQ_BUF_SZ) {
                        /* Invalid sense sense length. */
-                       printk(KERN_ALERT PFX "invalid sns length %d\n",
+                       printk(KERN_ERR PFX "invalid sns length %d\n",
                                rq_buff_len);
                        /* reset rq_buff_len */
                        rq_buff_len =  num_rq * BNX2FC_RQ_BUF_SZ;
@@ -1780,7 +1898,7 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
                        scsi_set_resid(sc_cmd, io_req->fcp_resid);
                break;
        default:
-               printk(KERN_ALERT PFX "scsi_cmd_compl: fcp_status = %d\n",
+               printk(KERN_ERR PFX "scsi_cmd_compl: fcp_status = %d\n",
                        io_req->fcp_status);
                break;
        }
@@ -1789,14 +1907,15 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
        kref_put(&io_req->refcount, bnx2fc_cmd_release);
 }
 
-static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
+int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
                               struct bnx2fc_cmd *io_req)
 {
        struct fcoe_task_ctx_entry *task;
        struct fcoe_task_ctx_entry *task_page;
        struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
        struct fcoe_port *port = tgt->port;
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        struct fc_lport *lport = port->lport;
        struct fcoe_dev_stats *stats;
        int task_idx, index;
@@ -1854,7 +1973,8 @@ static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
        }
 
        /* Time IO req */
-       bnx2fc_cmd_timer_set(io_req, BNX2FC_IO_TIMEOUT);
+       if (tgt->io_timeout)
+               bnx2fc_cmd_timer_set(io_req, BNX2FC_IO_TIMEOUT);
        /* Obtain free SQ entry */
        bnx2fc_add_2_sq(tgt, xid);
 
index 3e892bd..d5311b5 100644 (file)
@@ -2,7 +2,7 @@
  * Handles operations such as session offload/upload etc, and manages
  * session resources such as connection id and qp resources.
  *
- * Copyright (c) 2008 - 2010 Broadcom Corporation
+ * Copyright (c) 2008 - 2011 Broadcom 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
@@ -65,7 +65,8 @@ static void bnx2fc_offload_session(struct fcoe_port *port,
 {
        struct fc_lport *lport = rdata->local_port;
        struct fc_rport *rport = rdata->rport;
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        int rval;
        int i = 0;
 
@@ -237,7 +238,8 @@ void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt)
 static void bnx2fc_upload_session(struct fcoe_port *port,
                                        struct bnx2fc_rport *tgt)
 {
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
 
        BNX2FC_TGT_DBG(tgt, "upload_session: active_ios = %d\n",
                tgt->num_active_ios.counter);
@@ -316,7 +318,8 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
 {
 
        struct fc_rport *rport = rdata->rport;
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        struct b577xx_doorbell_set_prod *sq_db = &tgt->sq_db;
        struct b577xx_fcoe_rx_doorbell *rx_db = &tgt->rx_db;
 
@@ -350,6 +353,14 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
        tgt->rq_cons_idx = 0;
        atomic_set(&tgt->num_active_ios, 0);
 
+       if (rdata->flags & FC_RP_FLAGS_RETRY) {
+               tgt->dev_type = TYPE_TAPE;
+               tgt->io_timeout = 0; /* use default ULP timeout */
+       } else {
+               tgt->dev_type = TYPE_DISK;
+               tgt->io_timeout = BNX2FC_IO_TIMEOUT;
+       }
+
        /* initialize sq doorbell */
        sq_db->header.header = B577XX_DOORBELL_HDR_DB_TYPE;
        sq_db->header.header |= B577XX_FCOE_CONNECTION_TYPE <<
@@ -392,7 +403,8 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
                                enum fc_rport_event event)
 {
        struct fcoe_port *port = lport_priv(lport);
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        struct fc_rport *rport = rdata->rport;
        struct fc_rport_libfc_priv *rp;
        struct bnx2fc_rport *tgt;
@@ -403,7 +415,7 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
        switch (event) {
        case RPORT_EV_READY:
                if (!rport) {
-                       printk(KERN_ALERT PFX "rport is NULL: ERROR!\n");
+                       printk(KERN_ERR PFX "rport is NULL: ERROR!\n");
                        break;
                }
 
@@ -415,7 +427,7 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
                         * We should not come here, as lport will
                         * take care of fabric login
                         */
-                       printk(KERN_ALERT PFX "%x - rport_event_handler ERROR\n",
+                       printk(KERN_ERR PFX "%x - rport_event_handler ERROR\n",
                                rdata->ids.port_id);
                        break;
                }
@@ -483,7 +495,7 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
                        break;
 
                if (!rport) {
-                       printk(KERN_ALERT PFX "%x - rport not created Yet!!\n",
+                       printk(KERN_INFO PFX "%x - rport not created Yet!!\n",
                                port_id);
                        break;
                }
@@ -537,7 +549,8 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
 struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
                                             u32 port_id)
 {
-       struct bnx2fc_hba *hba = port->priv;
+       struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        struct bnx2fc_rport *tgt;
        struct fc_rport_priv *rdata;
        int i;
@@ -552,7 +565,7 @@ struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
                                                "obtained\n");
                                        return tgt;
                                } else {
-                                       printk(KERN_ERR PFX "rport 0x%x "
+                                       BNX2FC_TGT_DBG(tgt, "rport 0x%x "
                                                "is in DELETED state\n",
                                                rdata->ids.port_id);
                                        return NULL;
@@ -633,7 +646,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->sq = dma_alloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
                                     &tgt->sq_dma, GFP_KERNEL);
        if (!tgt->sq) {
-               printk(KERN_ALERT PFX "unable to allocate SQ memory %d\n",
+               printk(KERN_ERR PFX "unable to allocate SQ memory %d\n",
                        tgt->sq_mem_size);
                goto mem_alloc_failure;
        }
@@ -646,7 +659,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->cq = dma_alloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
                                     &tgt->cq_dma, GFP_KERNEL);
        if (!tgt->cq) {
-               printk(KERN_ALERT PFX "unable to allocate CQ memory %d\n",
+               printk(KERN_ERR PFX "unable to allocate CQ memory %d\n",
                        tgt->cq_mem_size);
                goto mem_alloc_failure;
        }
@@ -659,7 +672,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->rq = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
                                        &tgt->rq_dma, GFP_KERNEL);
        if (!tgt->rq) {
-               printk(KERN_ALERT PFX "unable to allocate RQ memory %d\n",
+               printk(KERN_ERR PFX "unable to allocate RQ memory %d\n",
                        tgt->rq_mem_size);
                goto mem_alloc_failure;
        }
@@ -671,7 +684,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->rq_pbl = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
                                         &tgt->rq_pbl_dma, GFP_KERNEL);
        if (!tgt->rq_pbl) {
-               printk(KERN_ALERT PFX "unable to allocate RQ PBL %d\n",
+               printk(KERN_ERR PFX "unable to allocate RQ PBL %d\n",
                        tgt->rq_pbl_size);
                goto mem_alloc_failure;
        }
@@ -697,7 +710,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->xferq = dma_alloc_coherent(&hba->pcidev->dev, tgt->xferq_mem_size,
                                        &tgt->xferq_dma, GFP_KERNEL);
        if (!tgt->xferq) {
-               printk(KERN_ALERT PFX "unable to allocate XFERQ %d\n",
+               printk(KERN_ERR PFX "unable to allocate XFERQ %d\n",
                        tgt->xferq_mem_size);
                goto mem_alloc_failure;
        }
@@ -711,7 +724,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->confq = dma_alloc_coherent(&hba->pcidev->dev, tgt->confq_mem_size,
                                        &tgt->confq_dma, GFP_KERNEL);
        if (!tgt->confq) {
-               printk(KERN_ALERT PFX "unable to allocate CONFQ %d\n",
+               printk(KERN_ERR PFX "unable to allocate CONFQ %d\n",
                        tgt->confq_mem_size);
                goto mem_alloc_failure;
        }
@@ -726,7 +739,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
                                            tgt->confq_pbl_size,
                                            &tgt->confq_pbl_dma, GFP_KERNEL);
        if (!tgt->confq_pbl) {
-               printk(KERN_ALERT PFX "unable to allocate CONFQ PBL %d\n",
+               printk(KERN_ERR PFX "unable to allocate CONFQ PBL %d\n",
                        tgt->confq_pbl_size);
                goto mem_alloc_failure;
        }
@@ -751,7 +764,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
                                          tgt->conn_db_mem_size,
                                          &tgt->conn_db_dma, GFP_KERNEL);
        if (!tgt->conn_db) {
-               printk(KERN_ALERT PFX "unable to allocate conn_db %d\n",
+               printk(KERN_ERR PFX "unable to allocate conn_db %d\n",
                                                tgt->conn_db_mem_size);
                goto mem_alloc_failure;
        }
@@ -767,7 +780,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
                                      &tgt->lcq_dma, GFP_KERNEL);
 
        if (!tgt->lcq) {
-               printk(KERN_ALERT PFX "unable to allocate lcq %d\n",
+               printk(KERN_ERR PFX "unable to allocate lcq %d\n",
                       tgt->lcq_mem_size);
                goto mem_alloc_failure;
        }
index 45a6154..01cff18 100644 (file)
@@ -4,7 +4,8 @@ config SCSI_BNX2_ISCSI
        depends on PCI
        select SCSI_ISCSI_ATTRS
        select NETDEVICES
-       select NETDEV_1000
+       select ETHERNET
+       select NET_VENDOR_BROADCOM
        select CNIC
        ---help---
        This driver supports iSCSI offload for the Broadcom NetXtreme II
index dc57007..0bd70e8 100644 (file)
@@ -40,7 +40,7 @@
 #include <scsi/libiscsi.h>
 #include <scsi/scsi_transport_iscsi.h>
 
-#include "../../net/cnic_if.h"
+#include "../../net/ethernet/broadcom/cnic_if.h"
 #include "57xx_iscsi_hsi.h"
 #include "57xx_iscsi_constants.h"
 
index 09dbf9e..6f095e2 100644 (file)
@@ -1,3 +1,3 @@
-EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb3
 
 obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o
index 11dff23..6bbc36f 100644 (file)
@@ -2,7 +2,8 @@ config SCSI_CXGB3_ISCSI
        tristate "Chelsio T3 iSCSI support"
        depends on PCI && INET
        select NETDEVICES
-       select NETDEV_10000
+       select ETHERNET
+       select NET_VENDOR_CHELSIO
        select CHELSIO_T3
        select SCSI_ISCSI_ATTRS
        ---help---
index b9f4af7..8290cda 100644 (file)
@@ -1,3 +1,3 @@
-EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb4
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb4
 
 obj-$(CONFIG_SCSI_CXGB4_ISCSI) += cxgb4i.o
index d5302c2..16b2c7d 100644 (file)
@@ -2,7 +2,8 @@ config SCSI_CXGB4_ISCSI
        tristate "Chelsio T4 iSCSI support"
        depends on PCI && INET
        select NETDEVICES
-       select NETDEV_10000
+       select ETHERNET
+       select NET_VENDOR_CHELSIO
        select CHELSIO_T4
        select SCSI_ISCSI_ATTRS
        ---help---
index 2e7c136..27c9d65 100644 (file)
@@ -128,25 +128,7 @@ struct c4_inquiry {
        u8      reserved[2];
 };
 
-struct rdac_controller {
-       u8                      subsys_id[SUBSYS_ID_LEN];
-       u8                      slot_id[SLOT_ID_LEN];
-       int                     use_ms10;
-       struct kref             kref;
-       struct list_head        node; /* list of all controllers */
-       union                   {
-               struct rdac_pg_legacy legacy;
-               struct rdac_pg_expanded expanded;
-       } mode_select;
-       u8      index;
-       u8      array_name[ARRAY_LABEL_LEN];
-       spinlock_t              ms_lock;
-       int                     ms_queued;
-       struct work_struct      ms_work;
-       struct scsi_device      *ms_sdev;
-       struct list_head        ms_head;
-};
-
+#define UNIQUE_ID_LEN 16
 struct c8_inquiry {
        u8      peripheral_info;
        u8      page_code; /* 0xC8 */
@@ -159,12 +141,31 @@ struct c8_inquiry {
        u8      vol_user_label_len;
        u8      vol_user_label[60];
        u8      array_uniq_id_len;
-       u8      array_unique_id[16];
+       u8      array_unique_id[UNIQUE_ID_LEN];
        u8      array_user_label_len;
        u8      array_user_label[60];
        u8      lun[8];
 };
 
+struct rdac_controller {
+       u8                      array_id[UNIQUE_ID_LEN];
+       int                     use_ms10;
+       struct kref             kref;
+       struct list_head        node; /* list of all controllers */
+       union                   {
+               struct rdac_pg_legacy legacy;
+               struct rdac_pg_expanded expanded;
+       } mode_select;
+       u8      index;
+       u8      array_name[ARRAY_LABEL_LEN];
+       struct Scsi_Host        *host;
+       spinlock_t              ms_lock;
+       int                     ms_queued;
+       struct work_struct      ms_work;
+       struct scsi_device      *ms_sdev;
+       struct list_head        ms_head;
+};
+
 struct c2_inquiry {
        u8      peripheral_info;
        u8      page_code;      /* 0xC2 */
@@ -369,16 +370,17 @@ static void release_controller(struct kref *kref)
        kfree(ctlr);
 }
 
-static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id,
-                                               char *array_name)
+static struct rdac_controller *get_controller(int index, char *array_name,
+                       u8 *array_id, struct scsi_device *sdev)
 {
        struct rdac_controller *ctlr, *tmp;
 
        spin_lock(&list_lock);
 
        list_for_each_entry(tmp, &ctlr_list, node) {
-               if ((memcmp(tmp->subsys_id, subsys_id, SUBSYS_ID_LEN) == 0) &&
-                         (memcmp(tmp->slot_id, slot_id, SLOT_ID_LEN) == 0)) {
+               if ((memcmp(tmp->array_id, array_id, UNIQUE_ID_LEN) == 0) &&
+                         (tmp->index == index) &&
+                         (tmp->host == sdev->host)) {
                        kref_get(&tmp->kref);
                        spin_unlock(&list_lock);
                        return tmp;
@@ -389,16 +391,11 @@ static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id,
                goto done;
 
        /* initialize fields of controller */
-       memcpy(ctlr->subsys_id, subsys_id, SUBSYS_ID_LEN);
-       memcpy(ctlr->slot_id, slot_id, SLOT_ID_LEN);
+       memcpy(ctlr->array_id, array_id, UNIQUE_ID_LEN);
+       ctlr->index = index;
+       ctlr->host = sdev->host;
        memcpy(ctlr->array_name, array_name, ARRAY_LABEL_LEN);
 
-       /* update the controller index */
-       if (slot_id[1] == 0x31)
-               ctlr->index = 0;
-       else
-               ctlr->index = 1;
-
        kref_init(&ctlr->kref);
        ctlr->use_ms10 = -1;
        ctlr->ms_queued = 0;
@@ -444,7 +441,7 @@ done:
 }
 
 static int get_lun_info(struct scsi_device *sdev, struct rdac_dh_data *h,
-                       char *array_name)
+                       char *array_name, u8 *array_id)
 {
        int err, i;
        struct c8_inquiry *inqp;
@@ -463,6 +460,8 @@ static int get_lun_info(struct scsi_device *sdev, struct rdac_dh_data *h,
                        *(array_name+i) = inqp->array_user_label[(2*i)+1];
 
                *(array_name+ARRAY_LABEL_LEN-1) = '\0';
+               memset(array_id, 0, UNIQUE_ID_LEN);
+               memcpy(array_id, inqp->array_unique_id, inqp->array_uniq_id_len);
        }
        return err;
 }
@@ -504,16 +503,20 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
 }
 
 static int initialize_controller(struct scsi_device *sdev,
-                                struct rdac_dh_data *h, char *array_name)
+               struct rdac_dh_data *h, char *array_name, u8 *array_id)
 {
-       int err;
+       int err, index;
        struct c4_inquiry *inqp;
 
        err = submit_inquiry(sdev, 0xC4, sizeof(struct c4_inquiry), h);
        if (err == SCSI_DH_OK) {
                inqp = &h->inq.c4;
-               h->ctlr = get_controller(inqp->subsys_id, inqp->slot_id,
-                                       array_name);
+               /* get the controller index */
+               if (inqp->slot_id[1] == 0x31)
+                       index = 0;
+               else
+                       index = 1;
+               h->ctlr = get_controller(index, array_name, array_id, sdev);
                if (!h->ctlr)
                        err = SCSI_DH_RES_TEMP_UNAVAIL;
        }
@@ -835,6 +838,7 @@ static int rdac_bus_attach(struct scsi_device *sdev)
        unsigned long flags;
        int err;
        char array_name[ARRAY_LABEL_LEN];
+       char array_id[UNIQUE_ID_LEN];
 
        scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
                               + sizeof(*h) , GFP_KERNEL);
@@ -849,11 +853,11 @@ static int rdac_bus_attach(struct scsi_device *sdev)
        h->lun = UNINITIALIZED_LUN;
        h->state = RDAC_STATE_ACTIVE;
 
-       err = get_lun_info(sdev, h, array_name);
+       err = get_lun_info(sdev, h, array_name, array_id);
        if (err != SCSI_DH_OK)
                goto failed;
 
-       err = initialize_controller(sdev, h, array_name);
+       err = initialize_controller(sdev, h, array_name, array_id);
        if (err != SCSI_DH_OK)
                goto failed;
 
index 204fa8d..3416ab6 100644 (file)
@@ -486,6 +486,19 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *netdev,
        return 0;
 }
 
+/**
+ * fcoe_port_send() - Send an Ethernet-encapsulated FIP/FCoE frame
+ * @port: The FCoE port
+ * @skb: The FIP/FCoE packet to be sent
+ */
+static void fcoe_port_send(struct fcoe_port *port, struct sk_buff *skb)
+{
+       if (port->fcoe_pending_queue.qlen)
+               fcoe_check_wait_queue(port->lport, skb);
+       else if (fcoe_start_io(skb))
+               fcoe_check_wait_queue(port->lport, skb);
+}
+
 /**
  * fcoe_fip_send() - Send an Ethernet-encapsulated FIP frame
  * @fip: The FCoE controller
@@ -494,7 +507,7 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *netdev,
 static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
 {
        skb->dev = fcoe_from_ctlr(fip)->netdev;
-       dev_queue_xmit(skb);
+       fcoe_port_send(lport_priv(fip->lp), skb);
 }
 
 /**
@@ -1257,30 +1270,20 @@ static int fcoe_cpu_callback(struct notifier_block *nfb,
 /**
  * fcoe_select_cpu() - Selects CPU to handle post-processing of incoming
  *                     command.
- * @curr_cpu:   CPU which received request
  *
- * This routine selects next CPU based on cpumask.
+ * This routine selects next CPU based on cpumask to distribute
+ * incoming requests in round robin.
  *
- * Returns: int (CPU number). Caller to verify if returned CPU is online or not.
+ * Returns: int CPU number
  */
-static unsigned int fcoe_select_cpu(unsigned int curr_cpu)
+static inline unsigned int fcoe_select_cpu(void)
 {
        static unsigned int selected_cpu;
 
-       if (num_online_cpus() == 1)
-               return curr_cpu;
-       /*
-        * Doing following check, to skip "curr_cpu (smp_processor_id)"
-        * from selection of CPU is intentional. This is to avoid same CPU
-        * doing post-processing of command. "curr_cpu" to just receive
-        * incoming request in case where rx_id is UNKNOWN and all other
-        * CPU to actually process the command(s)
-        */
-       do {
-               selected_cpu = cpumask_next(selected_cpu, cpu_online_mask);
-               if (selected_cpu >= nr_cpu_ids)
-                       selected_cpu = cpumask_first(cpu_online_mask);
-       } while (selected_cpu == curr_cpu);
+       selected_cpu = cpumask_next(selected_cpu, cpu_online_mask);
+       if (selected_cpu >= nr_cpu_ids)
+               selected_cpu = cpumask_first(cpu_online_mask);
+
        return selected_cpu;
 }
 
@@ -1350,30 +1353,26 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
 
        fr = fcoe_dev_from_skb(skb);
        fr->fr_dev = lport;
-       fr->ptype = ptype;
 
        /*
         * In case the incoming frame's exchange is originated from
         * the initiator, then received frame's exchange id is ANDed
         * with fc_cpu_mask bits to get the same cpu on which exchange
-        * was originated, otherwise just use the current cpu.
+        * was originated, otherwise select cpu using rx exchange id
+        * or fcoe_select_cpu().
         */
        if (ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX)
                cpu = ntohs(fh->fh_ox_id) & fc_cpu_mask;
        else {
-               cpu = smp_processor_id();
-
-               if ((fh->fh_type == FC_TYPE_FCP) &&
-                   (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN)) {
-                       do {
-                               cpu = fcoe_select_cpu(cpu);
-                       } while (!cpu_online(cpu));
-               } else  if ((fh->fh_type == FC_TYPE_FCP) &&
-                           (ntohs(fh->fh_rx_id) != FC_XID_UNKNOWN)) {
+               if (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN)
+                       cpu = fcoe_select_cpu();
+               else
                        cpu = ntohs(fh->fh_rx_id) & fc_cpu_mask;
-               } else
-                       cpu = smp_processor_id();
        }
+
+       if (cpu >= nr_cpu_ids)
+               goto err;
+
        fps = &per_cpu(fcoe_percpu, cpu);
        spin_lock_bh(&fps->fcoe_rx_list.lock);
        if (unlikely(!fps->thread)) {
@@ -1515,7 +1514,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
                        return -ENOMEM;
                }
                frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
-               cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
+               cp = kmap_atomic(skb_frag_page(frag), KM_SKB_DATA_SOFTIRQ)
                        + frag->page_offset;
        } else {
                cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
@@ -1572,11 +1571,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
 
        /* send down to lld */
        fr_dev(fp) = lport;
-       if (port->fcoe_pending_queue.qlen)
-               fcoe_check_wait_queue(lport, skb);
-       else if (fcoe_start_io(skb))
-               fcoe_check_wait_queue(lport, skb);
-
+       fcoe_port_send(port, skb);
        return 0;
 }
 
index 41068e8..f6613f9 100644 (file)
@@ -108,8 +108,9 @@ u32 fcoe_fc_crc(struct fc_frame *fp)
                len = frag->size;
                while (len > 0) {
                        clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
-                       data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
-                                          KM_SKB_DATA_SOFTIRQ);
+                       data = kmap_atomic(
+                               skb_frag_page(frag) + (off >> PAGE_SHIFT),
+                               KM_SKB_DATA_SOFTIRQ);
                        crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
                        kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
                        off += clen;
index c6f99b1..ec61bdb 100644 (file)
@@ -1219,8 +1219,8 @@ static void complete_scsi_command(struct CommandList *cp)
                dev_warn(&h->pdev->dev, "cp %p reports abort failed\n", cp);
                break;
        case CMD_UNSOLICITED_ABORT:
-               cmd->result = DID_RESET << 16;
-               dev_warn(&h->pdev->dev, "cp %p aborted do to an unsolicited "
+               cmd->result = DID_SOFT_ERROR << 16; /* retry the command */
+               dev_warn(&h->pdev->dev, "cp %p aborted due to an unsolicited "
                        "abort\n", cp);
                break;
        case CMD_TIMEOUT:
index 6d8dcd4..7f53cea 100644 (file)
@@ -214,7 +214,7 @@ static void SA5_submit_command(struct ctlr_info *h,
        dev_dbg(&h->pdev->dev, "Sending %x, tag = %x\n", c->busaddr,
                c->Header.Tag.lower);
        writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
-       (void) readl(h->vaddr + SA5_REQUEST_PORT_OFFSET);
+       (void) readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
        h->commands_outstanding++;
        if (h->commands_outstanding > h->max_outstanding)
                h->max_outstanding = h->commands_outstanding;
index 888086c..8d63630 100644 (file)
@@ -8778,14 +8778,14 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        if (rc != PCIBIOS_SUCCESSFUL) {
                dev_err(&pdev->dev, "Failed to save PCI config space\n");
                rc = -EIO;
-               goto cleanup_nomem;
+               goto out_msi_disable;
        }
 
        if ((rc = ipr_save_pcix_cmd_reg(ioa_cfg)))
-               goto cleanup_nomem;
+               goto out_msi_disable;
 
        if ((rc = ipr_set_pcix_cmd_reg(ioa_cfg)))
-               goto cleanup_nomem;
+               goto out_msi_disable;
 
        if (ioa_cfg->sis64)
                ioa_cfg->cfg_table_size = (sizeof(struct ipr_config_table_hdr64)
@@ -8800,7 +8800,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        if (rc < 0) {
                dev_err(&pdev->dev,
                        "Couldn't allocate enough memory for device driver!\n");
-               goto cleanup_nomem;
+               goto out_msi_disable;
        }
 
        /*
@@ -8845,10 +8845,10 @@ out:
 
 cleanup_nolog:
        ipr_free_mem(ioa_cfg);
-cleanup_nomem:
-       iounmap(ipr_regs);
 out_msi_disable:
        pci_disable_msi(pdev);
+cleanup_nomem:
+       iounmap(ipr_regs);
 out_release_regions:
        pci_release_regions(pdev);
 out_scsi_host_put:
index f5a0665..01ff082 100644 (file)
@@ -802,10 +802,8 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
                pool = per_cpu_ptr(mp->pool, xid & fc_cpu_mask);
                spin_lock_bh(&pool->lock);
                ep = fc_exch_ptr_get(pool, (xid - mp->min_xid) >> fc_cpu_order);
-               if (ep) {
+               if (ep && ep->xid == xid)
                        fc_exch_hold(ep);
-                       WARN_ON(ep->xid != xid);
-               }
                spin_unlock_bh(&pool->lock);
        }
        return ep;
@@ -2465,8 +2463,11 @@ int fc_setup_exch_mgr(void)
 
        fc_exch_workqueue = create_singlethread_workqueue("fc_exch_workqueue");
        if (!fc_exch_workqueue)
-               return -ENOMEM;
+               goto err;
        return 0;
+err:
+       kmem_cache_destroy(fc_em_cachep);
+       return -ENOMEM;
 }
 
 /**
index 9cd2149..afb63c8 100644 (file)
@@ -498,7 +498,7 @@ crc_err:
                        stats = per_cpu_ptr(lport->dev_stats, get_cpu());
                        stats->ErrorFrames++;
                        /* per cpu count, not total count, but OK for limit */
-                       if (stats->InvalidCRCCount++ < 5)
+                       if (stats->InvalidCRCCount++ < FC_MAX_ERROR_CNT)
                                printk(KERN_WARNING "libfc: CRC error on data "
                                       "frame for port (%6.6x)\n",
                                       lport->port_id);
@@ -690,7 +690,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
 }
 
 /**
- * fc_fcp_abts_resp() - Send an ABTS response
+ * fc_fcp_abts_resp() - Receive an ABTS response
  * @fsp: The FCP packet that is being aborted
  * @fp:         The response frame
  */
@@ -730,7 +730,7 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 }
 
 /**
- * fc_fcp_recv() - Reveive an FCP frame
+ * fc_fcp_recv() - Receive an FCP frame
  * @seq: The sequence the frame is on
  * @fp:         The received frame
  * @arg: The related FCP packet
@@ -1084,6 +1084,7 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
        rc = lport->tt.fcp_cmd_send(lport, fsp, fc_fcp_recv);
        if (unlikely(rc)) {
                spin_lock_irqsave(&si->scsi_queue_lock, flags);
+               fsp->cmd->SCp.ptr = NULL;
                list_del(&fsp->list);
                spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
        }
@@ -1645,12 +1646,10 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
        struct fc_seq *seq;
        struct fcp_srr *srr;
        struct fc_frame *fp;
-       u8 cdb_op;
        unsigned int rec_tov;
 
        rport = fsp->rport;
        rpriv = rport->dd_data;
-       cdb_op = fsp->cdb_cmd.fc_cdb[0];
 
        if (!(rpriv->flags & FC_RP_FLAGS_RETRY) ||
            rpriv->rp_state != RPORT_ST_READY)
index e008b16..e55ed9c 100644 (file)
@@ -1352,7 +1352,6 @@ static void fc_lport_timeout(struct work_struct *work)
                WARN_ON(1);
                break;
        case LPORT_ST_READY:
-               WARN_ON(1);
                break;
        case LPORT_ST_RESET:
                break;
index 874e29d..f84084b 100644 (file)
@@ -849,6 +849,9 @@ static struct domain_device *sas_ex_discover_expander(
 
        res = sas_discover_expander(child);
        if (res) {
+               spin_lock_irq(&parent->port->dev_list_lock);
+               list_del(&child->dev_list_node);
+               spin_unlock_irq(&parent->port->dev_list_lock);
                kfree(child);
                return NULL;
        }
index 8ec2c86..c088a36 100644 (file)
  *******************************************************************/
 
 #include <scsi/scsi_host.h>
+
+#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_SCSI_LPFC_DEBUG_FS)
+#define CONFIG_SCSI_LPFC_DEBUG_FS
+#endif
+
 struct lpfc_sli2_slim;
 
 #define LPFC_PCI_DEV_LP                0x1
@@ -465,9 +470,10 @@ enum intr_type_t {
 struct unsol_rcv_ct_ctx {
        uint32_t ctxt_id;
        uint32_t SID;
-       uint32_t oxid;
        uint32_t flags;
 #define UNSOL_VALID    0x00000001
+       uint16_t oxid;
+       uint16_t rxid;
 };
 
 #define LPFC_USER_LINK_SPEED_AUTO      0       /* auto select (default)*/
@@ -674,6 +680,9 @@ struct lpfc_hba {
        uint32_t cfg_enable_rrq;
        uint32_t cfg_topology;
        uint32_t cfg_link_speed;
+#define LPFC_FCF_FOV 1         /* Fast fcf failover */
+#define LPFC_FCF_PRIORITY 2    /* Priority fcf failover */
+       uint32_t cfg_fcf_failover_policy;
        uint32_t cfg_cr_delay;
        uint32_t cfg_cr_count;
        uint32_t cfg_multi_ring_support;
@@ -845,9 +854,13 @@ struct lpfc_hba {
        /* iDiag debugfs sub-directory */
        struct dentry *idiag_root;
        struct dentry *idiag_pci_cfg;
+       struct dentry *idiag_bar_acc;
        struct dentry *idiag_que_info;
        struct dentry *idiag_que_acc;
        struct dentry *idiag_drb_acc;
+       struct dentry *idiag_ctl_acc;
+       struct dentry *idiag_mbx_acc;
+       struct dentry *idiag_ext_acc;
 #endif
 
        /* Used for deferred freeing of ELS data buffers */
index 135a53b..2542f1f 100644 (file)
@@ -754,6 +754,47 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
                return status;
 }
 
+/**
+ * lpfc_sli4_pdev_status_reg_wait - Wait for pdev status register for readyness
+ * @phba: lpfc_hba pointer.
+ *
+ * Description:
+ * SLI4 interface type-2 device to wait on the sliport status register for
+ * the readyness after performing a firmware reset.
+ *
+ * Returns:
+ * zero for success
+ **/
+static int
+lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba)
+{
+       struct lpfc_register portstat_reg;
+       int i;
+
+
+       lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
+                  &portstat_reg.word0);
+
+       /* wait for the SLI port firmware ready after firmware reset */
+       for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) {
+               msleep(10);
+               lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
+                          &portstat_reg.word0);
+               if (!bf_get(lpfc_sliport_status_err, &portstat_reg))
+                       continue;
+               if (!bf_get(lpfc_sliport_status_rn, &portstat_reg))
+                       continue;
+               if (!bf_get(lpfc_sliport_status_rdy, &portstat_reg))
+                       continue;
+               break;
+       }
+
+       if (i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT)
+               return 0;
+       else
+               return -EIO;
+}
+
 /**
  * lpfc_sli4_pdev_reg_request - Request physical dev to perform a register acc
  * @phba: lpfc_hba pointer.
@@ -769,6 +810,7 @@ static ssize_t
 lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
 {
        struct completion online_compl;
+       struct pci_dev *pdev = phba->pcidev;
        uint32_t reg_val;
        int status = 0;
        int rc;
@@ -781,6 +823,14 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
             LPFC_SLI_INTF_IF_TYPE_2))
                return -EPERM;
 
+       if (!pdev->is_physfn)
+               return -EPERM;
+
+       /* Disable SR-IOV virtual functions if enabled */
+       if (phba->cfg_sriov_nr_virtfn) {
+               pci_disable_sriov(pdev);
+               phba->cfg_sriov_nr_virtfn = 0;
+       }
        status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
 
        if (status != 0)
@@ -805,7 +855,10 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
        readl(phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET);
 
        /* delay driver action following IF_TYPE_2 reset */
-       msleep(100);
+       rc = lpfc_sli4_pdev_status_reg_wait(phba);
+
+       if (rc)
+               return -EIO;
 
        init_completion(&online_compl);
        rc = lpfc_workq_post_event(phba, &status, &online_compl,
@@ -895,6 +948,10 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
 
        if (!phba->cfg_enable_hba_reset)
                return -EACCES;
+
+       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+               "3050 lpfc_board_mode set to %s\n", buf);
+
        init_completion(&online_compl);
 
        if(strncmp(buf, "online", sizeof("online") - 1) == 0) {
@@ -1290,6 +1347,10 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr,
        if (phba->sli_rev == LPFC_SLI_REV4)
                val = 0;
 
+       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+               "3051 lpfc_poll changed from %d to %d\n",
+               phba->cfg_poll, val);
+
        spin_lock_irq(&phba->hbalock);
 
        old_val = phba->cfg_poll;
@@ -1414,80 +1475,10 @@ lpfc_sriov_hw_max_virtfn_show(struct device *dev,
        struct Scsi_Host *shost = class_to_shost(dev);
        struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
        struct lpfc_hba *phba = vport->phba;
-       struct pci_dev *pdev = phba->pcidev;
-       union  lpfc_sli4_cfg_shdr *shdr;
-       uint32_t shdr_status, shdr_add_status;
-       LPFC_MBOXQ_t *mboxq;
-       struct lpfc_mbx_get_prof_cfg *get_prof_cfg;
-       struct lpfc_rsrc_desc_pcie *desc;
-       uint32_t max_nr_virtfn;
-       uint32_t desc_count;
-       int length, rc, i;
-
-       if ((phba->sli_rev < LPFC_SLI_REV4) ||
-           (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
-            LPFC_SLI_INTF_IF_TYPE_2))
-               return -EPERM;
-
-       if (!pdev->is_physfn)
-               return snprintf(buf, PAGE_SIZE, "%d\n", 0);
-
-       mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-       if (!mboxq)
-               return -ENOMEM;
-
-       /* get the maximum number of virtfn support by physfn */
-       length = (sizeof(struct lpfc_mbx_get_prof_cfg) -
-                 sizeof(struct lpfc_sli4_cfg_mhdr));
-       lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
-                        LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG,
-                        length, LPFC_SLI4_MBX_EMBED);
-       shdr = (union lpfc_sli4_cfg_shdr *)
-               &mboxq->u.mqe.un.sli4_config.header.cfg_shdr;
-       bf_set(lpfc_mbox_hdr_pf_num, &shdr->request,
-              phba->sli4_hba.iov.pf_number + 1);
-
-       get_prof_cfg = &mboxq->u.mqe.un.get_prof_cfg;
-       bf_set(lpfc_mbx_get_prof_cfg_prof_tp, &get_prof_cfg->u.request,
-              LPFC_CFG_TYPE_CURRENT_ACTIVE);
-
-       rc = lpfc_sli_issue_mbox_wait(phba, mboxq,
-                               lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG));
-
-       if (rc != MBX_TIMEOUT) {
-               /* check return status */
-               shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
-               shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
-                                        &shdr->response);
-               if (shdr_status || shdr_add_status || rc)
-                       goto error_out;
-
-       } else
-               goto error_out;
-
-       desc_count = get_prof_cfg->u.response.prof_cfg.rsrc_desc_count;
-
-       for (i = 0; i < LPFC_RSRC_DESC_MAX_NUM; i++) {
-               desc = (struct lpfc_rsrc_desc_pcie *)
-                       &get_prof_cfg->u.response.prof_cfg.desc[i];
-               if (LPFC_RSRC_DESC_TYPE_PCIE ==
-                   bf_get(lpfc_rsrc_desc_pcie_type, desc)) {
-                       max_nr_virtfn = bf_get(lpfc_rsrc_desc_pcie_nr_virtfn,
-                                              desc);
-                       break;
-               }
-       }
-
-       if (i < LPFC_RSRC_DESC_MAX_NUM) {
-               if (rc != MBX_TIMEOUT)
-                       mempool_free(mboxq, phba->mbox_mem_pool);
-               return snprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn);
-       }
+       uint16_t max_nr_virtfn;
 
-error_out:
-       if (rc != MBX_TIMEOUT)
-               mempool_free(mboxq, phba->mbox_mem_pool);
-       return -EIO;
+       max_nr_virtfn = lpfc_sli_sriov_nr_virtfn_get(phba);
+       return snprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn);
 }
 
 /**
@@ -1605,6 +1596,9 @@ static int \
 lpfc_##attr##_set(struct lpfc_hba *phba, uint val) \
 { \
        if (val >= minval && val <= maxval) {\
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \
+                       "3052 lpfc_" #attr " changed from %d to %d\n", \
+                       phba->cfg_##attr, val); \
                phba->cfg_##attr = val;\
                return 0;\
        }\
@@ -1762,6 +1756,9 @@ static int \
 lpfc_##attr##_set(struct lpfc_vport *vport, uint val) \
 { \
        if (val >= minval && val <= maxval) {\
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \
+                       "3053 lpfc_" #attr " changed from %d to %d\n", \
+                       vport->cfg_##attr, val); \
                vport->cfg_##attr = val;\
                return 0;\
        }\
@@ -2196,6 +2193,9 @@ lpfc_param_show(enable_npiv);
 lpfc_param_init(enable_npiv, 1, 0, 1);
 static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL);
 
+LPFC_ATTR_R(fcf_failover_policy, 1, 1, 2,
+       "FCF Fast failover=1 Priority failover=2");
+
 int lpfc_enable_rrq;
 module_param(lpfc_enable_rrq, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality");
@@ -2678,6 +2678,9 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,
                if (nolip)
                        return strlen(buf);
 
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                       "3054 lpfc_topology changed from %d to %d\n",
+                       prev_val, val);
                err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));
                if (err) {
                        phba->cfg_topology = prev_val;
@@ -3101,6 +3104,10 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
        if (sscanf(val_buf, "%i", &val) != 1)
                return -EINVAL;
 
+       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+               "3055 lpfc_link_speed changed from %d to %d %s\n",
+               phba->cfg_link_speed, val, nolip ? "(nolip)" : "(lip)");
+
        if (((val == LPFC_USER_LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) ||
            ((val == LPFC_USER_LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) ||
            ((val == LPFC_USER_LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) ||
@@ -3678,7 +3685,9 @@ LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support");
 #      - Default will result in registering capabilities for all profiles.
 #
 */
-unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION;
+unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION |
+                             SHOST_DIX_TYPE0_PROTECTION |
+                             SHOST_DIX_TYPE1_PROTECTION;
 
 module_param(lpfc_prot_mask, uint, S_IRUGO);
 MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask");
@@ -3769,6 +3778,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_lpfc_fdmi_on,
        &dev_attr_lpfc_max_luns,
        &dev_attr_lpfc_enable_npiv,
+       &dev_attr_lpfc_fcf_failover_policy,
        &dev_attr_lpfc_enable_rrq,
        &dev_attr_nport_evt_cnt,
        &dev_attr_board_mode,
@@ -4989,6 +4999,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
        lpfc_link_speed_init(phba, lpfc_link_speed);
        lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
        lpfc_enable_npiv_init(phba, lpfc_enable_npiv);
+       lpfc_fcf_failover_policy_init(phba, lpfc_fcf_failover_policy);
        lpfc_enable_rrq_init(phba, lpfc_enable_rrq);
        lpfc_use_msi_init(phba, lpfc_use_msi);
        lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
index 7fb0ba4..6760c69 100644 (file)
@@ -42,6 +42,7 @@
 #include "lpfc.h"
 #include "lpfc_logmsg.h"
 #include "lpfc_crtn.h"
+#include "lpfc_debugfs.h"
 #include "lpfc_vport.h"
 #include "lpfc_version.h"
 
@@ -960,8 +961,10 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                                                    evt_dat->immed_dat].oxid,
                                                phba->ct_ctx[
                                                    evt_dat->immed_dat].SID);
+                       phba->ct_ctx[evt_dat->immed_dat].rxid =
+                               piocbq->iocb.ulpContext;
                        phba->ct_ctx[evt_dat->immed_dat].oxid =
-                                               piocbq->iocb.ulpContext;
+                               piocbq->iocb.unsli3.rcvsli3.ox_id;
                        phba->ct_ctx[evt_dat->immed_dat].SID =
                                piocbq->iocb.un.rcvels.remoteID;
                        phba->ct_ctx[evt_dat->immed_dat].flags = UNSOL_VALID;
@@ -1312,7 +1315,8 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
                        rc = IOCB_ERROR;
                        goto issue_ct_rsp_exit;
                }
-               icmd->ulpContext = phba->ct_ctx[tag].oxid;
+               icmd->ulpContext = phba->ct_ctx[tag].rxid;
+               icmd->unsli3.rcvsli3.ox_id = phba->ct_ctx[tag].oxid;
                ndlp = lpfc_findnode_did(phba->pport, phba->ct_ctx[tag].SID);
                if (!ndlp) {
                        lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
@@ -1337,9 +1341,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
                        goto issue_ct_rsp_exit;
                }
 
-               icmd->un.ulpWord[3] = ndlp->nlp_rpi;
-               if (phba->sli_rev == LPFC_SLI_REV4)
-                       icmd->ulpContext =
+               icmd->un.ulpWord[3] =
                                phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
 
                /* The exchange is done, mark the entry as invalid */
@@ -1351,8 +1353,8 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
 
        /* Xmit CT response on exchange <xid> */
        lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "2722 Xmit CT response on exchange x%x Data: x%x x%x\n",
-                       icmd->ulpContext, icmd->ulpIoTag, phba->link_state);
+               "2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n",
+               icmd->ulpContext, icmd->ulpIoTag, tag, phba->link_state);
 
        ctiocb->iocb_cmpl = NULL;
        ctiocb->iocb_flag |= LPFC_IO_LIBDFC;
@@ -1471,13 +1473,12 @@ send_mgmt_rsp_exit:
 /**
  * lpfc_bsg_diag_mode_enter - process preparing into device diag loopback mode
  * @phba: Pointer to HBA context object.
- * @job: LPFC_BSG_VENDOR_DIAG_MODE
  *
  * This function is responsible for preparing driver for diag loopback
  * on device.
  */
 static int
-lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba, struct fc_bsg_job *job)
+lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba)
 {
        struct lpfc_vport **vports;
        struct Scsi_Host *shost;
@@ -1521,7 +1522,6 @@ lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba, struct fc_bsg_job *job)
 /**
  * lpfc_bsg_diag_mode_exit - exit process from device diag loopback mode
  * @phba: Pointer to HBA context object.
- * @job: LPFC_BSG_VENDOR_DIAG_MODE
  *
  * This function is responsible for driver exit processing of setting up
  * diag loopback mode on device.
@@ -1567,7 +1567,7 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
        uint32_t link_flags;
        uint32_t timeout;
        LPFC_MBOXQ_t *pmboxq;
-       int mbxstatus;
+       int mbxstatus = MBX_SUCCESS;
        int i = 0;
        int rc = 0;
 
@@ -1586,7 +1586,7 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
                goto job_error;
        }
 
-       rc = lpfc_bsg_diag_mode_enter(phba, job);
+       rc = lpfc_bsg_diag_mode_enter(phba);
        if (rc)
                goto job_error;
 
@@ -1741,7 +1741,7 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
        uint32_t link_flags, timeout, req_len, alloc_len;
        struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback;
        LPFC_MBOXQ_t *pmboxq = NULL;
-       int mbxstatus, i, rc = 0;
+       int mbxstatus = MBX_SUCCESS, i, rc = 0;
 
        /* no data to return just the return code */
        job->reply->reply_payload_rcv_len = 0;
@@ -1758,7 +1758,7 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
                goto job_error;
        }
 
-       rc = lpfc_bsg_diag_mode_enter(phba, job);
+       rc = lpfc_bsg_diag_mode_enter(phba);
        if (rc)
                goto job_error;
 
@@ -1982,7 +1982,7 @@ lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job)
                goto job_error;
        }
 
-       rc = lpfc_bsg_diag_mode_enter(phba, job);
+       rc = lpfc_bsg_diag_mode_enter(phba);
        if (rc)
                goto job_error;
 
@@ -3178,6 +3178,11 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
                                "(x%x/x%x) complete bsg job done, bsize:%d\n",
                                phba->mbox_ext_buf_ctx.nembType,
                                phba->mbox_ext_buf_ctx.mboxType, size);
+               lpfc_idiag_mbxacc_dump_bsg_mbox(phba,
+                                       phba->mbox_ext_buf_ctx.nembType,
+                                       phba->mbox_ext_buf_ctx.mboxType,
+                                       dma_ebuf, sta_pos_addr,
+                                       phba->mbox_ext_buf_ctx.mbx_dmabuf, 0);
        } else
                spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 
@@ -3430,6 +3435,10 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                                "ext_buf_cnt:%d\n", ext_buf_cnt);
        }
 
+       /* before dma descriptor setup */
+       lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_rd, dma_mbox,
+                                       sta_pre_addr, dmabuf, ext_buf_cnt);
+
        /* reject non-embedded mailbox command with none external buffer */
        if (ext_buf_cnt == 0) {
                rc = -EPERM;
@@ -3477,6 +3486,10 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                }
        }
 
+       /* after dma descriptor setup */
+       lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_rd, dma_mbox,
+                                       sta_pos_addr, dmabuf, ext_buf_cnt);
+
        /* construct base driver mbox command */
        pmb = &pmboxq->u.mb;
        pmbx = (uint8_t *)dmabuf->virt;
@@ -3511,7 +3524,7 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
                                "2947 Issued SLI_CONFIG ext-buffer "
                                "maibox command, rc:x%x\n", rc);
-               return 1;
+               return SLI_CONFIG_HANDLED;
        }
        lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
                        "2948 Failed to issue SLI_CONFIG ext-buffer "
@@ -3549,7 +3562,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
        LPFC_MBOXQ_t *pmboxq = NULL;
        MAILBOX_t *pmb;
        uint8_t *mbx;
-       int rc = 0, i;
+       int rc = SLI_CONFIG_NOT_HANDLED, i;
 
        mbox_req =
           (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd;
@@ -3591,12 +3604,20 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                                "ext_buf_cnt:%d\n", ext_buf_cnt);
        }
 
+       /* before dma buffer descriptor setup */
+       lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_wr, dma_mbox,
+                                       sta_pre_addr, dmabuf, ext_buf_cnt);
+
        if (ext_buf_cnt == 0)
                return -EPERM;
 
        /* for the first external buffer */
        lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf);
 
+       /* after dma descriptor setup */
+       lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_wr, dma_mbox,
+                                       sta_pos_addr, dmabuf, ext_buf_cnt);
+
        /* log for looking forward */
        for (i = 1; i < ext_buf_cnt; i++) {
                if (nemb_tp == nemb_mse)
@@ -3660,7 +3681,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                        lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
                                        "2955 Issued SLI_CONFIG ext-buffer "
                                        "maibox command, rc:x%x\n", rc);
-                       return 1;
+                       return SLI_CONFIG_HANDLED;
                }
                lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
                                "2956 Failed to issue SLI_CONFIG ext-buffer "
@@ -3668,6 +3689,11 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                rc = -EPIPE;
        }
 
+       /* wait for additoinal external buffers */
+       job->reply->result = 0;
+       job->job_done(job);
+       return SLI_CONFIG_HANDLED;
+
 job_error:
        if (pmboxq)
                mempool_free(pmboxq, phba->mbox_mem_pool);
@@ -3840,6 +3866,12 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job)
        dmabuf = list_first_entry(&phba->mbox_ext_buf_ctx.ext_dmabuf_list,
                                  struct lpfc_dmabuf, list);
        list_del_init(&dmabuf->list);
+
+       /* after dma buffer descriptor setup */
+       lpfc_idiag_mbxacc_dump_bsg_mbox(phba, phba->mbox_ext_buf_ctx.nembType,
+                                       mbox_rd, dma_ebuf, sta_pos_addr,
+                                       dmabuf, index);
+
        pbuf = (uint8_t *)dmabuf->virt;
        job->reply->reply_payload_rcv_len =
                sg_copy_from_buffer(job->reply_payload.sg_list,
@@ -3922,6 +3954,11 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job,
                                        dmabuf);
        list_add_tail(&dmabuf->list, &phba->mbox_ext_buf_ctx.ext_dmabuf_list);
 
+       /* after write dma buffer */
+       lpfc_idiag_mbxacc_dump_bsg_mbox(phba, phba->mbox_ext_buf_ctx.nembType,
+                                       mbox_wr, dma_ebuf, sta_pos_addr,
+                                       dmabuf, index);
+
        if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) {
                lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
                                "2968 SLI_CONFIG ext-buffer wr all %d "
@@ -3959,7 +3996,7 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job,
                        lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
                                        "2969 Issued SLI_CONFIG ext-buffer "
                                        "maibox command, rc:x%x\n", rc);
-                       return 1;
+                       return SLI_CONFIG_HANDLED;
                }
                lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
                                "2970 Failed to issue SLI_CONFIG ext-buffer "
@@ -4039,14 +4076,14 @@ lpfc_bsg_handle_sli_cfg_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                            struct lpfc_dmabuf *dmabuf)
 {
        struct dfc_mbox_req *mbox_req;
-       int rc;
+       int rc = SLI_CONFIG_NOT_HANDLED;
 
        mbox_req =
           (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd;
 
        /* mbox command with/without single external buffer */
        if (mbox_req->extMboxTag == 0 && mbox_req->extSeqNum == 0)
-               return SLI_CONFIG_NOT_HANDLED;
+               return rc;
 
        /* mbox command and first external buffer */
        if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_IDLE) {
@@ -4249,7 +4286,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
                 * mailbox extension size
                 */
                if ((transmit_length > receive_length) ||
-                       (transmit_length > MAILBOX_EXT_SIZE)) {
+                       (transmit_length > BSG_MBOX_SIZE - sizeof(MAILBOX_t))) {
                        rc = -ERANGE;
                        goto job_done;
                }
@@ -4272,7 +4309,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
                /* receive length cannot be greater than mailbox
                 * extension size
                 */
-               if (receive_length > MAILBOX_EXT_SIZE) {
+               if (receive_length > BSG_MBOX_SIZE - sizeof(MAILBOX_t)) {
                        rc = -ERANGE;
                        goto job_done;
                }
@@ -4306,7 +4343,8 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
                        bde = (struct ulp_bde64 *)&pmb->un.varWords[4];
 
                        /* bde size cannot be greater than mailbox ext size */
-                       if (bde->tus.f.bdeSize > MAILBOX_EXT_SIZE) {
+                       if (bde->tus.f.bdeSize >
+                           BSG_MBOX_SIZE - sizeof(MAILBOX_t)) {
                                rc = -ERANGE;
                                goto job_done;
                        }
@@ -4332,7 +4370,8 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
                                 * mailbox extension size
                                 */
                                if ((receive_length == 0) ||
-                                   (receive_length > MAILBOX_EXT_SIZE)) {
+                                   (receive_length >
+                                    BSG_MBOX_SIZE - sizeof(MAILBOX_t))) {
                                        rc = -ERANGE;
                                        goto job_done;
                                }
index fc20c24..a6db6ae 100644 (file)
@@ -235,9 +235,11 @@ int lpfc_sli4_redisc_fcf_table(struct lpfc_hba *);
 void lpfc_fcf_redisc_wait_start_timer(struct lpfc_hba *);
 void lpfc_sli4_fcf_dead_failthrough(struct lpfc_hba *);
 uint16_t lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *);
+void lpfc_sli4_set_fcf_flogi_fail(struct lpfc_hba *, uint16_t);
 int lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *, uint16_t);
 void lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *, uint16_t);
 int lpfc_sli4_fcf_rr_next_proc(struct lpfc_vport *, uint16_t);
+void lpfc_sli4_clear_fcf_rr_bmask(struct lpfc_hba *);
 
 int lpfc_mem_alloc(struct lpfc_hba *, int align);
 void lpfc_mem_free(struct lpfc_hba *);
@@ -371,6 +373,10 @@ extern struct lpfc_hbq_init *lpfc_hbq_defs[];
 /* SLI4 if_type 2 externs. */
 int lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *);
 int lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *);
+int lpfc_sli4_get_allocated_extnts(struct lpfc_hba *, uint16_t,
+                                  uint16_t *, uint16_t *);
+int lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *, uint16_t,
+                                         uint16_t *, uint16_t *);
 
 /* externs BlockGuard */
 extern char *_dump_buf_data;
@@ -432,10 +438,16 @@ void lpfc_handle_rrq_active(struct lpfc_hba *);
 int lpfc_send_rrq(struct lpfc_hba *, struct lpfc_node_rrq *);
 int lpfc_set_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *,
        uint16_t, uint16_t, uint16_t);
+uint16_t lpfc_sli4_xri_inrange(struct lpfc_hba *, uint16_t);
 void lpfc_cleanup_wt_rrqs(struct lpfc_hba *);
 void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *);
 struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t,
        uint32_t);
+void lpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *, enum nemb_type,
+       enum mbox_type, enum dma_type, enum sta_type,
+       struct lpfc_dmabuf *, uint32_t);
+void lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *, MAILBOX_t *);
 int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *);
 /* functions to support SR-IOV */
 int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int);
+uint16_t lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *);
index 30b25c5..a0424dd 100644 (file)
@@ -48,6 +48,7 @@
 #include "lpfc_version.h"
 #include "lpfc_compat.h"
 #include "lpfc_debugfs.h"
+#include "lpfc_bsg.h"
 
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
 /*
@@ -135,7 +136,11 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
        int i, index, len, enable;
        uint32_t ms;
        struct lpfc_debugfs_trc *dtp;
-       char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE];
+       char *buffer;
+
+       buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL);
+       if (!buffer)
+               return 0;
 
        enable = lpfc_debugfs_enable;
        lpfc_debugfs_enable = 0;
@@ -167,6 +172,8 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
        }
 
        lpfc_debugfs_enable = enable;
+       kfree(buffer);
+
        return len;
 }
 
@@ -195,8 +202,11 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
        int i, index, len, enable;
        uint32_t ms;
        struct lpfc_debugfs_trc *dtp;
-       char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE];
+       char *buffer;
 
+       buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL);
+       if (!buffer)
+               return 0;
 
        enable = lpfc_debugfs_enable;
        lpfc_debugfs_enable = 0;
@@ -228,6 +238,8 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
        }
 
        lpfc_debugfs_enable = enable;
+       kfree(buffer);
+
        return len;
 }
 
@@ -378,7 +390,11 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
        int len = 0;
        int i, off;
        uint32_t *ptr;
-       char buffer[1024];
+       char *buffer;
+
+       buffer = kmalloc(1024, GFP_KERNEL);
+       if (!buffer)
+               return 0;
 
        off = 0;
        spin_lock_irq(&phba->hbalock);
@@ -407,6 +423,8 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
        }
 
        spin_unlock_irq(&phba->hbalock);
+       kfree(buffer);
+
        return len;
 }
 
@@ -1327,8 +1345,8 @@ lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes,
                return 0;
 
        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
-               where = idiag.cmd.data[0];
-               count = idiag.cmd.data[1];
+               where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
+               count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
        } else
                return 0;
 
@@ -1373,6 +1391,11 @@ pcicfg_browse:
                len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
                                "%08x ", u32val);
                offset += sizeof(uint32_t);
+               if (offset >= LPFC_PCI_CFG_SIZE) {
+                       len += snprintf(pbuffer+len,
+                                       LPFC_PCI_CFG_SIZE-len, "\n");
+                       break;
+               }
                index -= sizeof(uint32_t);
                if (!index)
                        len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
@@ -1385,8 +1408,11 @@ pcicfg_browse:
        }
 
        /* Set up the offset for next portion of pci cfg read */
-       idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE;
-       if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE)
+       if (index == 0) {
+               idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE;
+               if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE)
+                       idiag.offset.last_rd = 0;
+       } else
                idiag.offset.last_rd = 0;
 
        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
@@ -1439,8 +1465,8 @@ lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
                if (rc != LPFC_PCI_CFG_RD_CMD_ARG)
                        goto error_out;
                /* Read command from PCI config space, set up command fields */
-               where = idiag.cmd.data[0];
-               count = idiag.cmd.data[1];
+               where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
+               count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
                if (count == LPFC_PCI_CFG_BROWSE) {
                        if (where % sizeof(uint32_t))
                                goto error_out;
@@ -1475,9 +1501,9 @@ lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
                if (rc != LPFC_PCI_CFG_WR_CMD_ARG)
                        goto error_out;
                /* Write command to PCI config space, read-modify-write */
-               where = idiag.cmd.data[0];
-               count = idiag.cmd.data[1];
-               value = idiag.cmd.data[2];
+               where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
+               count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
+               value = idiag.cmd.data[IDIAG_PCICFG_VALUE_INDX];
                /* Sanity checks */
                if ((count != sizeof(uint8_t)) &&
                    (count != sizeof(uint16_t)) &&
@@ -1569,6 +1595,292 @@ error_out:
        return -EINVAL;
 }
 
+/**
+ * lpfc_idiag_baracc_read - idiag debugfs pci bar access read
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba pci bar memory mapped space
+ * according to the idiag command, and copies to user @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_baracc_read(struct file *file, char __user *buf, size_t nbytes,
+                      loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+       int offset_label, offset, offset_run, len = 0, index;
+       int bar_num, acc_range, bar_size;
+       char *pbuffer;
+       void __iomem *mem_mapped_bar;
+       uint32_t if_type;
+       struct pci_dev *pdev;
+       uint32_t u32val;
+
+       pdev = phba->pcidev;
+       if (!pdev)
+               return 0;
+
+       /* This is a user read operation */
+       debug->op = LPFC_IDIAG_OP_RD;
+
+       if (!debug->buffer)
+               debug->buffer = kmalloc(LPFC_PCI_BAR_RD_BUF_SIZE, GFP_KERNEL);
+       if (!debug->buffer)
+               return 0;
+       pbuffer = debug->buffer;
+
+       if (*ppos)
+               return 0;
+
+       if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) {
+               bar_num   = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX];
+               offset    = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX];
+               acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX];
+               bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX];
+       } else
+               return 0;
+
+       if (acc_range == 0)
+               return 0;
+
+       if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+       if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
+               if (bar_num == IDIAG_BARACC_BAR_0)
+                       mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
+               else if (bar_num == IDIAG_BARACC_BAR_1)
+                       mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p;
+               else if (bar_num == IDIAG_BARACC_BAR_2)
+                       mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p;
+               else
+                       return 0;
+       } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+               if (bar_num == IDIAG_BARACC_BAR_0)
+                       mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
+               else
+                       return 0;
+       } else
+               return 0;
+
+       /* Read single PCI bar space register */
+       if (acc_range == SINGLE_WORD) {
+               offset_run = offset;
+               u32val = readl(mem_mapped_bar + offset_run);
+               len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
+                               "%05x: %08x\n", offset_run, u32val);
+       } else
+               goto baracc_browse;
+
+       return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+
+baracc_browse:
+
+       /* Browse all PCI bar space registers */
+       offset_label = idiag.offset.last_rd;
+       offset_run = offset_label;
+
+       /* Read PCI bar memory mapped space */
+       len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
+                       "%05x: ", offset_label);
+       index = LPFC_PCI_BAR_RD_SIZE;
+       while (index > 0) {
+               u32val = readl(mem_mapped_bar + offset_run);
+               len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
+                               "%08x ", u32val);
+               offset_run += sizeof(uint32_t);
+               if (acc_range == LPFC_PCI_BAR_BROWSE) {
+                       if (offset_run >= bar_size) {
+                               len += snprintf(pbuffer+len,
+                                       LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
+                               break;
+                       }
+               } else {
+                       if (offset_run >= offset +
+                           (acc_range * sizeof(uint32_t))) {
+                               len += snprintf(pbuffer+len,
+                                       LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
+                               break;
+                       }
+               }
+               index -= sizeof(uint32_t);
+               if (!index)
+                       len += snprintf(pbuffer+len,
+                                       LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
+               else if (!(index % (8 * sizeof(uint32_t)))) {
+                       offset_label += (8 * sizeof(uint32_t));
+                       len += snprintf(pbuffer+len,
+                                       LPFC_PCI_BAR_RD_BUF_SIZE-len,
+                                       "\n%05x: ", offset_label);
+               }
+       }
+
+       /* Set up the offset for next portion of pci bar read */
+       if (index == 0) {
+               idiag.offset.last_rd += LPFC_PCI_BAR_RD_SIZE;
+               if (acc_range == LPFC_PCI_BAR_BROWSE) {
+                       if (idiag.offset.last_rd >= bar_size)
+                               idiag.offset.last_rd = 0;
+               } else {
+                       if (offset_run >= offset +
+                           (acc_range * sizeof(uint32_t)))
+                               idiag.offset.last_rd = offset;
+               }
+       } else {
+               if (acc_range == LPFC_PCI_BAR_BROWSE)
+                       idiag.offset.last_rd = 0;
+               else
+                       idiag.offset.last_rd = offset;
+       }
+
+       return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+/**
+ * lpfc_idiag_baracc_write - Syntax check and set up idiag bar access commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and
+ * then perform the syntax check for PCI bar memory mapped space read or
+ * write command accordingly. In the case of PCI bar memory mapped space
+ * read command, it sets up the command in the idiag command struct for
+ * the debugfs read operation. In the case of PCI bar memorpy mapped space
+ * write operation, it executes the write operation into the PCI bar memory
+ * mapped space accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ */
+static ssize_t
+lpfc_idiag_baracc_write(struct file *file, const char __user *buf,
+                       size_t nbytes, loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+       uint32_t bar_num, bar_size, offset, value, acc_range;
+       struct pci_dev *pdev;
+       void __iomem *mem_mapped_bar;
+       uint32_t if_type;
+       uint32_t u32val;
+       int rc;
+
+       pdev = phba->pcidev;
+       if (!pdev)
+               return -EFAULT;
+
+       /* This is a user write operation */
+       debug->op = LPFC_IDIAG_OP_WR;
+
+       rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+       if (rc < 0)
+               return rc;
+
+       if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+       bar_num = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX];
+
+       if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
+               if ((bar_num != IDIAG_BARACC_BAR_0) &&
+                   (bar_num != IDIAG_BARACC_BAR_1) &&
+                   (bar_num != IDIAG_BARACC_BAR_2))
+                       goto error_out;
+       } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+               if (bar_num != IDIAG_BARACC_BAR_0)
+                       goto error_out;
+       } else
+               goto error_out;
+
+       if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
+               if (bar_num == IDIAG_BARACC_BAR_0) {
+                       idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
+                               LPFC_PCI_IF0_BAR0_SIZE;
+                       mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
+               } else if (bar_num == IDIAG_BARACC_BAR_1) {
+                       idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
+                               LPFC_PCI_IF0_BAR1_SIZE;
+                       mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p;
+               } else if (bar_num == IDIAG_BARACC_BAR_2) {
+                       idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
+                               LPFC_PCI_IF0_BAR2_SIZE;
+                       mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p;
+               } else
+                       goto error_out;
+       } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+               if (bar_num == IDIAG_BARACC_BAR_0) {
+                       idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
+                               LPFC_PCI_IF2_BAR0_SIZE;
+                       mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
+               } else
+                       goto error_out;
+       } else
+               goto error_out;
+
+       offset = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX];
+       if (offset % sizeof(uint32_t))
+               goto error_out;
+
+       bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX];
+       if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) {
+               /* Sanity check on PCI config read command line arguments */
+               if (rc != LPFC_PCI_BAR_RD_CMD_ARG)
+                       goto error_out;
+               acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX];
+               if (acc_range == LPFC_PCI_BAR_BROWSE) {
+                       if (offset > bar_size - sizeof(uint32_t))
+                               goto error_out;
+                       /* Starting offset to browse */
+                       idiag.offset.last_rd = offset;
+               } else if (acc_range > SINGLE_WORD) {
+                       if (offset + acc_range * sizeof(uint32_t) > bar_size)
+                               goto error_out;
+                       /* Starting offset to browse */
+                       idiag.offset.last_rd = offset;
+               } else if (acc_range != SINGLE_WORD)
+                       goto error_out;
+       } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR ||
+                  idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST ||
+                  idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) {
+               /* Sanity check on PCI bar write command line arguments */
+               if (rc != LPFC_PCI_BAR_WR_CMD_ARG)
+                       goto error_out;
+               /* Write command to PCI bar space, read-modify-write */
+               acc_range = SINGLE_WORD;
+               value = idiag.cmd.data[IDIAG_BARACC_REG_VAL_INDX];
+               if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR) {
+                       writel(value, mem_mapped_bar + offset);
+                       readl(mem_mapped_bar + offset);
+               }
+               if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST) {
+                       u32val = readl(mem_mapped_bar + offset);
+                       u32val |= value;
+                       writel(u32val, mem_mapped_bar + offset);
+                       readl(mem_mapped_bar + offset);
+               }
+               if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) {
+                       u32val = readl(mem_mapped_bar + offset);
+                       u32val &= ~value;
+                       writel(u32val, mem_mapped_bar + offset);
+                       readl(mem_mapped_bar + offset);
+               }
+       } else
+               /* All other opecodes are illegal for now */
+               goto error_out;
+
+       return nbytes;
+error_out:
+       memset(&idiag, 0, sizeof(idiag));
+       return -EINVAL;
+}
+
 /**
  * lpfc_idiag_queinfo_read - idiag debugfs read queue information
  * @file: The file pointer to read from.
@@ -1871,8 +2183,8 @@ lpfc_idiag_queacc_read(struct file *file, char __user *buf, size_t nbytes,
                return 0;
 
        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
-               index = idiag.cmd.data[2];
-               count = idiag.cmd.data[3];
+               index = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX];
+               count = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX];
                pque = (struct lpfc_queue *)idiag.ptr_private;
        } else
                return 0;
@@ -1944,12 +2256,12 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
                return rc;
 
        /* Get and sanity check on command feilds */
-       quetp  = idiag.cmd.data[0];
-       queid  = idiag.cmd.data[1];
-       index  = idiag.cmd.data[2];
-       count  = idiag.cmd.data[3];
-       offset = idiag.cmd.data[4];
-       value  = idiag.cmd.data[5];
+       quetp  = idiag.cmd.data[IDIAG_QUEACC_QUETP_INDX];
+       queid  = idiag.cmd.data[IDIAG_QUEACC_QUEID_INDX];
+       index  = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX];
+       count  = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX];
+       offset = idiag.cmd.data[IDIAG_QUEACC_OFFST_INDX];
+       value  = idiag.cmd.data[IDIAG_QUEACC_VALUE_INDX];
 
        /* Sanity check on command line arguments */
        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR ||
@@ -2218,7 +2530,7 @@ lpfc_idiag_drbacc_read(struct file *file, char __user *buf, size_t nbytes,
                return 0;
 
        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD)
-               drb_reg_id = idiag.cmd.data[0];
+               drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX];
        else
                return 0;
 
@@ -2257,7 +2569,7 @@ lpfc_idiag_drbacc_write(struct file *file, const char __user *buf,
 {
        struct lpfc_debug *debug = file->private_data;
        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
-       uint32_t drb_reg_id, value, reg_val;
+       uint32_t drb_reg_id, value, reg_val = 0;
        void __iomem *drb_reg;
        int rc;
 
@@ -2269,8 +2581,8 @@ lpfc_idiag_drbacc_write(struct file *file, const char __user *buf,
                return rc;
 
        /* Sanity check on command line arguments */
-       drb_reg_id = idiag.cmd.data[0];
-       value = idiag.cmd.data[1];
+       drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX];
+       value = idiag.cmd.data[IDIAG_DRBACC_VALUE_INDX];
 
        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR ||
            idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
@@ -2330,63 +2642,736 @@ error_out:
        return -EINVAL;
 }
 
-#undef lpfc_debugfs_op_disc_trc
-static const struct file_operations lpfc_debugfs_op_disc_trc = {
-       .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_disc_trc_open,
-       .llseek =       lpfc_debugfs_lseek,
-       .read =         lpfc_debugfs_read,
-       .release =      lpfc_debugfs_release,
-};
+/**
+ * lpfc_idiag_ctlacc_read_reg - idiag debugfs read a control registers
+ * @phba: The pointer to hba structure.
+ * @pbuffer: The pointer to the buffer to copy the data to.
+ * @len: The lenght of bytes to copied.
+ * @drbregid: The id to doorbell registers.
+ *
+ * Description:
+ * This routine reads a control register and copies its content to the
+ * user buffer pointed to by @pbuffer.
+ *
+ * Returns:
+ * This function returns the amount of data that was copied into @pbuffer.
+ **/
+static int
+lpfc_idiag_ctlacc_read_reg(struct lpfc_hba *phba, char *pbuffer,
+                          int len, uint32_t ctlregid)
+{
 
-#undef lpfc_debugfs_op_nodelist
-static const struct file_operations lpfc_debugfs_op_nodelist = {
-       .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_nodelist_open,
-       .llseek =       lpfc_debugfs_lseek,
-       .read =         lpfc_debugfs_read,
-       .release =      lpfc_debugfs_release,
-};
+       if (!pbuffer)
+               return 0;
 
-#undef lpfc_debugfs_op_hbqinfo
-static const struct file_operations lpfc_debugfs_op_hbqinfo = {
-       .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_hbqinfo_open,
-       .llseek =       lpfc_debugfs_lseek,
-       .read =         lpfc_debugfs_read,
-       .release =      lpfc_debugfs_release,
-};
+       switch (ctlregid) {
+       case LPFC_CTL_PORT_SEM:
+               len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+                               "Port SemReg:   0x%08x\n",
+                               readl(phba->sli4_hba.conf_regs_memmap_p +
+                                     LPFC_CTL_PORT_SEM_OFFSET));
+               break;
+       case LPFC_CTL_PORT_STA:
+               len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+                               "Port StaReg:   0x%08x\n",
+                               readl(phba->sli4_hba.conf_regs_memmap_p +
+                                     LPFC_CTL_PORT_STA_OFFSET));
+               break;
+       case LPFC_CTL_PORT_CTL:
+               len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+                               "Port CtlReg:   0x%08x\n",
+                               readl(phba->sli4_hba.conf_regs_memmap_p +
+                                     LPFC_CTL_PORT_CTL_OFFSET));
+               break;
+       case LPFC_CTL_PORT_ER1:
+               len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+                               "Port Er1Reg:   0x%08x\n",
+                               readl(phba->sli4_hba.conf_regs_memmap_p +
+                                     LPFC_CTL_PORT_ER1_OFFSET));
+               break;
+       case LPFC_CTL_PORT_ER2:
+               len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+                               "Port Er2Reg:   0x%08x\n",
+                               readl(phba->sli4_hba.conf_regs_memmap_p +
+                                     LPFC_CTL_PORT_ER2_OFFSET));
+               break;
+       case LPFC_CTL_PDEV_CTL:
+               len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+                               "PDev CtlReg:   0x%08x\n",
+                               readl(phba->sli4_hba.conf_regs_memmap_p +
+                                     LPFC_CTL_PDEV_CTL_OFFSET));
+               break;
+       default:
+               break;
+       }
+       return len;
+}
 
-#undef lpfc_debugfs_op_dumpHBASlim
-static const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
-       .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_dumpHBASlim_open,
-       .llseek =       lpfc_debugfs_lseek,
-       .read =         lpfc_debugfs_read,
-       .release =      lpfc_debugfs_release,
-};
+/**
+ * lpfc_idiag_ctlacc_read - idiag debugfs read port and device control register
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba port and device registers according
+ * to the idiag command, and copies to user @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_ctlacc_read(struct file *file, char __user *buf, size_t nbytes,
+                      loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+       uint32_t ctl_reg_id, i;
+       char *pbuffer;
+       int len = 0;
 
-#undef lpfc_debugfs_op_dumpHostSlim
-static const struct file_operations lpfc_debugfs_op_dumpHostSlim = {
-       .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_dumpHostSlim_open,
-       .llseek =       lpfc_debugfs_lseek,
-       .read =         lpfc_debugfs_read,
-       .release =      lpfc_debugfs_release,
-};
+       /* This is a user read operation */
+       debug->op = LPFC_IDIAG_OP_RD;
 
-#undef lpfc_debugfs_op_dumpData
-static const struct file_operations lpfc_debugfs_op_dumpData = {
-       .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_dumpData_open,
-       .llseek =       lpfc_debugfs_lseek,
-       .read =         lpfc_debugfs_read,
-       .write =        lpfc_debugfs_dumpDataDif_write,
-       .release =      lpfc_debugfs_dumpDataDif_release,
-};
+       if (!debug->buffer)
+               debug->buffer = kmalloc(LPFC_CTL_ACC_BUF_SIZE, GFP_KERNEL);
+       if (!debug->buffer)
+               return 0;
+       pbuffer = debug->buffer;
 
-#undef lpfc_debugfs_op_dumpDif
-static const struct file_operations lpfc_debugfs_op_dumpDif = {
+       if (*ppos)
+               return 0;
+
+       if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD)
+               ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX];
+       else
+               return 0;
+
+       if (ctl_reg_id == LPFC_CTL_ACC_ALL)
+               for (i = 1; i <= LPFC_CTL_MAX; i++)
+                       len = lpfc_idiag_ctlacc_read_reg(phba,
+                                                        pbuffer, len, i);
+       else
+               len = lpfc_idiag_ctlacc_read_reg(phba,
+                                                pbuffer, len, ctl_reg_id);
+
+       return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+/**
+ * lpfc_idiag_ctlacc_write - Syntax check and set up idiag ctlacc commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and then
+ * perform the syntax check for port and device control register read (dump)
+ * or write (set) command accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ **/
+static ssize_t
+lpfc_idiag_ctlacc_write(struct file *file, const char __user *buf,
+                       size_t nbytes, loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+       uint32_t ctl_reg_id, value, reg_val = 0;
+       void __iomem *ctl_reg;
+       int rc;
+
+       /* This is a user write operation */
+       debug->op = LPFC_IDIAG_OP_WR;
+
+       rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+       if (rc < 0)
+               return rc;
+
+       /* Sanity check on command line arguments */
+       ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX];
+       value = idiag.cmd.data[IDIAG_CTLACC_VALUE_INDX];
+
+       if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR ||
+           idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST ||
+           idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
+               if (rc != LPFC_CTL_ACC_WR_CMD_ARG)
+                       goto error_out;
+               if (ctl_reg_id > LPFC_CTL_MAX)
+                       goto error_out;
+       } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD) {
+               if (rc != LPFC_CTL_ACC_RD_CMD_ARG)
+                       goto error_out;
+               if ((ctl_reg_id > LPFC_CTL_MAX) &&
+                   (ctl_reg_id != LPFC_CTL_ACC_ALL))
+                       goto error_out;
+       } else
+               goto error_out;
+
+       /* Perform the write access operation */
+       if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR ||
+           idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST ||
+           idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
+               switch (ctl_reg_id) {
+               case LPFC_CTL_PORT_SEM:
+                       ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_CTL_PORT_SEM_OFFSET;
+                       break;
+               case LPFC_CTL_PORT_STA:
+                       ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_CTL_PORT_STA_OFFSET;
+                       break;
+               case LPFC_CTL_PORT_CTL:
+                       ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_CTL_PORT_CTL_OFFSET;
+                       break;
+               case LPFC_CTL_PORT_ER1:
+                       ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_CTL_PORT_ER1_OFFSET;
+                       break;
+               case LPFC_CTL_PORT_ER2:
+                       ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_CTL_PORT_ER2_OFFSET;
+                       break;
+               case LPFC_CTL_PDEV_CTL:
+                       ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_CTL_PDEV_CTL_OFFSET;
+                       break;
+               default:
+                       goto error_out;
+               }
+
+               if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR)
+                       reg_val = value;
+               if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST) {
+                       reg_val = readl(ctl_reg);
+                       reg_val |= value;
+               }
+               if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
+                       reg_val = readl(ctl_reg);
+                       reg_val &= ~value;
+               }
+               writel(reg_val, ctl_reg);
+               readl(ctl_reg); /* flush */
+       }
+       return nbytes;
+
+error_out:
+       /* Clean out command structure on command error out */
+       memset(&idiag, 0, sizeof(idiag));
+       return -EINVAL;
+}
+
+/**
+ * lpfc_idiag_mbxacc_get_setup - idiag debugfs get mailbox access setup
+ * @phba: Pointer to HBA context object.
+ * @pbuffer: Pointer to data buffer.
+ *
+ * Description:
+ * This routine gets the driver mailbox access debugfs setup information.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static int
+lpfc_idiag_mbxacc_get_setup(struct lpfc_hba *phba, char *pbuffer)
+{
+       uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd;
+       int len = 0;
+
+       mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
+       mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
+       mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
+       mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
+
+       len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
+                       "mbx_dump_map: 0x%08x\n", mbx_dump_map);
+       len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
+                       "mbx_dump_cnt: %04d\n", mbx_dump_cnt);
+       len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
+                       "mbx_word_cnt: %04d\n", mbx_word_cnt);
+       len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
+                       "mbx_mbox_cmd: 0x%02x\n", mbx_mbox_cmd);
+
+       return len;
+}
+
+/**
+ * lpfc_idiag_mbxacc_read - idiag debugfs read on mailbox access
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba driver mailbox access debugfs setup
+ * information.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_mbxacc_read(struct file *file, char __user *buf, size_t nbytes,
+                      loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+       char *pbuffer;
+       int len = 0;
+
+       /* This is a user read operation */
+       debug->op = LPFC_IDIAG_OP_RD;
+
+       if (!debug->buffer)
+               debug->buffer = kmalloc(LPFC_MBX_ACC_BUF_SIZE, GFP_KERNEL);
+       if (!debug->buffer)
+               return 0;
+       pbuffer = debug->buffer;
+
+       if (*ppos)
+               return 0;
+
+       if ((idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP) &&
+           (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP))
+               return 0;
+
+       len = lpfc_idiag_mbxacc_get_setup(phba, pbuffer);
+
+       return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+/**
+ * lpfc_idiag_mbxacc_write - Syntax check and set up idiag mbxacc commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and then
+ * perform the syntax check for driver mailbox command (dump) and sets up the
+ * necessary states in the idiag command struct accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ **/
+static ssize_t
+lpfc_idiag_mbxacc_write(struct file *file, const char __user *buf,
+                       size_t nbytes, loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd;
+       int rc;
+
+       /* This is a user write operation */
+       debug->op = LPFC_IDIAG_OP_WR;
+
+       rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+       if (rc < 0)
+               return rc;
+
+       /* Sanity check on command line arguments */
+       mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
+       mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
+       mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
+       mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
+
+       if (idiag.cmd.opcode == LPFC_IDIAG_CMD_MBXACC_DP) {
+               if (!(mbx_dump_map & LPFC_MBX_DMP_MBX_ALL))
+                       goto error_out;
+               if ((mbx_dump_map & ~LPFC_MBX_DMP_MBX_ALL) &&
+                   (mbx_dump_map != LPFC_MBX_DMP_ALL))
+                       goto error_out;
+               if (mbx_word_cnt > sizeof(MAILBOX_t))
+                       goto error_out;
+       } else if (idiag.cmd.opcode == LPFC_IDIAG_BSG_MBXACC_DP) {
+               if (!(mbx_dump_map & LPFC_BSG_DMP_MBX_ALL))
+                       goto error_out;
+               if ((mbx_dump_map & ~LPFC_BSG_DMP_MBX_ALL) &&
+                   (mbx_dump_map != LPFC_MBX_DMP_ALL))
+                       goto error_out;
+               if (mbx_word_cnt > (BSG_MBOX_SIZE)/4)
+                       goto error_out;
+               if (mbx_mbox_cmd != 0x9b)
+                       goto error_out;
+       } else
+               goto error_out;
+
+       if (mbx_word_cnt == 0)
+               goto error_out;
+       if (rc != LPFC_MBX_DMP_ARG)
+               goto error_out;
+       if (mbx_mbox_cmd & ~0xff)
+               goto error_out;
+
+       /* condition for stop mailbox dump */
+       if (mbx_dump_cnt == 0)
+               goto reset_out;
+
+       return nbytes;
+
+reset_out:
+       /* Clean out command structure on command error out */
+       memset(&idiag, 0, sizeof(idiag));
+       return nbytes;
+
+error_out:
+       /* Clean out command structure on command error out */
+       memset(&idiag, 0, sizeof(idiag));
+       return -EINVAL;
+}
+
+/**
+ * lpfc_idiag_extacc_avail_get - get the available extents information
+ * @phba: pointer to lpfc hba data structure.
+ * @pbuffer: pointer to internal buffer.
+ * @len: length into the internal buffer data has been copied.
+ *
+ * Description:
+ * This routine is to get the available extent information.
+ *
+ * Returns:
+ * overall lenth of the data read into the internal buffer.
+ **/
+static int
+lpfc_idiag_extacc_avail_get(struct lpfc_hba *phba, char *pbuffer, int len)
+{
+       uint16_t ext_cnt, ext_size;
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\nAvailable Extents Information:\n");
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tPort Available VPI extents: ");
+       lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VPI,
+                                      &ext_cnt, &ext_size);
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "Count %3d, Size %3d\n", ext_cnt, ext_size);
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tPort Available VFI extents: ");
+       lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VFI,
+                                      &ext_cnt, &ext_size);
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "Count %3d, Size %3d\n", ext_cnt, ext_size);
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tPort Available RPI extents: ");
+       lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_RPI,
+                                      &ext_cnt, &ext_size);
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "Count %3d, Size %3d\n", ext_cnt, ext_size);
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tPort Available XRI extents: ");
+       lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_XRI,
+                                      &ext_cnt, &ext_size);
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "Count %3d, Size %3d\n", ext_cnt, ext_size);
+
+       return len;
+}
+
+/**
+ * lpfc_idiag_extacc_alloc_get - get the allocated extents information
+ * @phba: pointer to lpfc hba data structure.
+ * @pbuffer: pointer to internal buffer.
+ * @len: length into the internal buffer data has been copied.
+ *
+ * Description:
+ * This routine is to get the allocated extent information.
+ *
+ * Returns:
+ * overall lenth of the data read into the internal buffer.
+ **/
+static int
+lpfc_idiag_extacc_alloc_get(struct lpfc_hba *phba, char *pbuffer, int len)
+{
+       uint16_t ext_cnt, ext_size;
+       int rc;
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\nAllocated Extents Information:\n");
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tHost Allocated VPI extents: ");
+       rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VPI,
+                                           &ext_cnt, &ext_size);
+       if (!rc)
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "Port %d Extent %3d, Size %3d\n",
+                               phba->brd_no, ext_cnt, ext_size);
+       else
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "N/A\n");
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tHost Allocated VFI extents: ");
+       rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VFI,
+                                           &ext_cnt, &ext_size);
+       if (!rc)
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "Port %d Extent %3d, Size %3d\n",
+                               phba->brd_no, ext_cnt, ext_size);
+       else
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "N/A\n");
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tHost Allocated RPI extents: ");
+       rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_RPI,
+                                           &ext_cnt, &ext_size);
+       if (!rc)
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "Port %d Extent %3d, Size %3d\n",
+                               phba->brd_no, ext_cnt, ext_size);
+       else
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "N/A\n");
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tHost Allocated XRI extents: ");
+       rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_XRI,
+                                           &ext_cnt, &ext_size);
+       if (!rc)
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "Port %d Extent %3d, Size %3d\n",
+                               phba->brd_no, ext_cnt, ext_size);
+       else
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "N/A\n");
+
+       return len;
+}
+
+/**
+ * lpfc_idiag_extacc_drivr_get - get driver extent information
+ * @phba: pointer to lpfc hba data structure.
+ * @pbuffer: pointer to internal buffer.
+ * @len: length into the internal buffer data has been copied.
+ *
+ * Description:
+ * This routine is to get the driver extent information.
+ *
+ * Returns:
+ * overall lenth of the data read into the internal buffer.
+ **/
+static int
+lpfc_idiag_extacc_drivr_get(struct lpfc_hba *phba, char *pbuffer, int len)
+{
+       struct lpfc_rsrc_blks *rsrc_blks;
+       int index;
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\nDriver Extents Information:\n");
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tVPI extents:\n");
+       index = 0;
+       list_for_each_entry(rsrc_blks, &phba->lpfc_vpi_blk_list, list) {
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "\t\tBlock %3d: Start %4d, Count %4d\n",
+                               index, rsrc_blks->rsrc_start,
+                               rsrc_blks->rsrc_size);
+               index++;
+       }
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tVFI extents:\n");
+       index = 0;
+       list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_vfi_blk_list,
+                           list) {
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "\t\tBlock %3d: Start %4d, Count %4d\n",
+                               index, rsrc_blks->rsrc_start,
+                               rsrc_blks->rsrc_size);
+               index++;
+       }
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tRPI extents:\n");
+       index = 0;
+       list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_rpi_blk_list,
+                           list) {
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "\t\tBlock %3d: Start %4d, Count %4d\n",
+                               index, rsrc_blks->rsrc_start,
+                               rsrc_blks->rsrc_size);
+               index++;
+       }
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tXRI extents:\n");
+       index = 0;
+       list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_xri_blk_list,
+                           list) {
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "\t\tBlock %3d: Start %4d, Count %4d\n",
+                               index, rsrc_blks->rsrc_start,
+                               rsrc_blks->rsrc_size);
+               index++;
+       }
+
+       return len;
+}
+
+/**
+ * lpfc_idiag_extacc_write - Syntax check and set up idiag extacc commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and then
+ * perform the syntax check for extent information access commands and sets
+ * up the necessary states in the idiag command struct accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ **/
+static ssize_t
+lpfc_idiag_extacc_write(struct file *file, const char __user *buf,
+                       size_t nbytes, loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       uint32_t ext_map;
+       int rc;
+
+       /* This is a user write operation */
+       debug->op = LPFC_IDIAG_OP_WR;
+
+       rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+       if (rc < 0)
+               return rc;
+
+       ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX];
+
+       if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD)
+               goto error_out;
+       if (rc != LPFC_EXT_ACC_CMD_ARG)
+               goto error_out;
+       if (!(ext_map & LPFC_EXT_ACC_ALL))
+               goto error_out;
+
+       return nbytes;
+error_out:
+       /* Clean out command structure on command error out */
+       memset(&idiag, 0, sizeof(idiag));
+       return -EINVAL;
+}
+
+/**
+ * lpfc_idiag_extacc_read - idiag debugfs read access to extent information
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the proper extent information according to
+ * the idiag command, and copies to user @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_extacc_read(struct file *file, char __user *buf, size_t nbytes,
+                      loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+       char *pbuffer;
+       uint32_t ext_map;
+       int len = 0;
+
+       /* This is a user read operation */
+       debug->op = LPFC_IDIAG_OP_RD;
+
+       if (!debug->buffer)
+               debug->buffer = kmalloc(LPFC_EXT_ACC_BUF_SIZE, GFP_KERNEL);
+       if (!debug->buffer)
+               return 0;
+       pbuffer = debug->buffer;
+       if (*ppos)
+               return 0;
+       if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD)
+               return 0;
+
+       ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX];
+       if (ext_map & LPFC_EXT_ACC_AVAIL)
+               len = lpfc_idiag_extacc_avail_get(phba, pbuffer, len);
+       if (ext_map & LPFC_EXT_ACC_ALLOC)
+               len = lpfc_idiag_extacc_alloc_get(phba, pbuffer, len);
+       if (ext_map & LPFC_EXT_ACC_DRIVR)
+               len = lpfc_idiag_extacc_drivr_get(phba, pbuffer, len);
+
+       return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+#undef lpfc_debugfs_op_disc_trc
+static const struct file_operations lpfc_debugfs_op_disc_trc = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_disc_trc_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_read,
+       .release =      lpfc_debugfs_release,
+};
+
+#undef lpfc_debugfs_op_nodelist
+static const struct file_operations lpfc_debugfs_op_nodelist = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_nodelist_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_read,
+       .release =      lpfc_debugfs_release,
+};
+
+#undef lpfc_debugfs_op_hbqinfo
+static const struct file_operations lpfc_debugfs_op_hbqinfo = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_hbqinfo_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_read,
+       .release =      lpfc_debugfs_release,
+};
+
+#undef lpfc_debugfs_op_dumpHBASlim
+static const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_dumpHBASlim_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_read,
+       .release =      lpfc_debugfs_release,
+};
+
+#undef lpfc_debugfs_op_dumpHostSlim
+static const struct file_operations lpfc_debugfs_op_dumpHostSlim = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_dumpHostSlim_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_read,
+       .release =      lpfc_debugfs_release,
+};
+
+#undef lpfc_debugfs_op_dumpData
+static const struct file_operations lpfc_debugfs_op_dumpData = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_dumpData_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_read,
+       .write =        lpfc_debugfs_dumpDataDif_write,
+       .release =      lpfc_debugfs_dumpDataDif_release,
+};
+
+#undef lpfc_debugfs_op_dumpDif
+static const struct file_operations lpfc_debugfs_op_dumpDif = {
        .owner =        THIS_MODULE,
        .open =         lpfc_debugfs_dumpDif_open,
        .llseek =       lpfc_debugfs_lseek,
@@ -2420,6 +3405,16 @@ static const struct file_operations lpfc_idiag_op_pciCfg = {
        .release =      lpfc_idiag_cmd_release,
 };
 
+#undef lpfc_idiag_op_barAcc
+static const struct file_operations lpfc_idiag_op_barAcc = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_idiag_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_idiag_baracc_read,
+       .write =        lpfc_idiag_baracc_write,
+       .release =      lpfc_idiag_cmd_release,
+};
+
 #undef lpfc_idiag_op_queInfo
 static const struct file_operations lpfc_idiag_op_queInfo = {
        .owner =        THIS_MODULE,
@@ -2428,7 +3423,7 @@ static const struct file_operations lpfc_idiag_op_queInfo = {
        .release =      lpfc_idiag_release,
 };
 
-#undef lpfc_idiag_op_queacc
+#undef lpfc_idiag_op_queAcc
 static const struct file_operations lpfc_idiag_op_queAcc = {
        .owner =        THIS_MODULE,
        .open =         lpfc_idiag_open,
@@ -2438,7 +3433,7 @@ static const struct file_operations lpfc_idiag_op_queAcc = {
        .release =      lpfc_idiag_cmd_release,
 };
 
-#undef lpfc_idiag_op_drbacc
+#undef lpfc_idiag_op_drbAcc
 static const struct file_operations lpfc_idiag_op_drbAcc = {
        .owner =        THIS_MODULE,
        .open =         lpfc_idiag_open,
@@ -2448,8 +3443,234 @@ static const struct file_operations lpfc_idiag_op_drbAcc = {
        .release =      lpfc_idiag_cmd_release,
 };
 
+#undef lpfc_idiag_op_ctlAcc
+static const struct file_operations lpfc_idiag_op_ctlAcc = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_idiag_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_idiag_ctlacc_read,
+       .write =        lpfc_idiag_ctlacc_write,
+       .release =      lpfc_idiag_cmd_release,
+};
+
+#undef lpfc_idiag_op_mbxAcc
+static const struct file_operations lpfc_idiag_op_mbxAcc = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_idiag_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_idiag_mbxacc_read,
+       .write =        lpfc_idiag_mbxacc_write,
+       .release =      lpfc_idiag_cmd_release,
+};
+
+#undef lpfc_idiag_op_extAcc
+static const struct file_operations lpfc_idiag_op_extAcc = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_idiag_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_idiag_extacc_read,
+       .write =        lpfc_idiag_extacc_write,
+       .release =      lpfc_idiag_cmd_release,
+};
+
 #endif
 
+/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
+ * @phba: Pointer to HBA context object.
+ * @dmabuf: Pointer to a DMA buffer descriptor.
+ *
+ * Description:
+ * This routine dump a bsg pass-through non-embedded mailbox command with
+ * external buffer.
+ **/
+void
+lpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *phba, enum nemb_type nemb_tp,
+                               enum mbox_type mbox_tp, enum dma_type dma_tp,
+                               enum sta_type sta_tp,
+                               struct lpfc_dmabuf *dmabuf, uint32_t ext_buf)
+{
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+       uint32_t *mbx_mbox_cmd, *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt;
+       char line_buf[LPFC_MBX_ACC_LBUF_SZ];
+       int len = 0;
+       uint32_t do_dump = 0;
+       uint32_t *pword;
+       uint32_t i;
+
+       if (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP)
+               return;
+
+       mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
+       mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
+       mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
+       mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
+
+       if (!(*mbx_dump_map & LPFC_MBX_DMP_ALL) ||
+           (*mbx_dump_cnt == 0) ||
+           (*mbx_word_cnt == 0))
+               return;
+
+       if (*mbx_mbox_cmd != 0x9B)
+               return;
+
+       if ((mbox_tp == mbox_rd) && (dma_tp == dma_mbox)) {
+               if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_MBX) {
+                       do_dump |= LPFC_BSG_DMP_MBX_RD_MBX;
+                       printk(KERN_ERR "\nRead mbox command (x%x), "
+                              "nemb:0x%x, extbuf_cnt:%d:\n",
+                              sta_tp, nemb_tp, ext_buf);
+               }
+       }
+       if ((mbox_tp == mbox_rd) && (dma_tp == dma_ebuf)) {
+               if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_BUF) {
+                       do_dump |= LPFC_BSG_DMP_MBX_RD_BUF;
+                       printk(KERN_ERR "\nRead mbox buffer (x%x), "
+                              "nemb:0x%x, extbuf_seq:%d:\n",
+                              sta_tp, nemb_tp, ext_buf);
+               }
+       }
+       if ((mbox_tp == mbox_wr) && (dma_tp == dma_mbox)) {
+               if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_MBX) {
+                       do_dump |= LPFC_BSG_DMP_MBX_WR_MBX;
+                       printk(KERN_ERR "\nWrite mbox command (x%x), "
+                              "nemb:0x%x, extbuf_cnt:%d:\n",
+                              sta_tp, nemb_tp, ext_buf);
+               }
+       }
+       if ((mbox_tp == mbox_wr) && (dma_tp == dma_ebuf)) {
+               if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_BUF) {
+                       do_dump |= LPFC_BSG_DMP_MBX_WR_BUF;
+                       printk(KERN_ERR "\nWrite mbox buffer (x%x), "
+                              "nemb:0x%x, extbuf_seq:%d:\n",
+                              sta_tp, nemb_tp, ext_buf);
+               }
+       }
+
+       /* dump buffer content */
+       if (do_dump) {
+               pword = (uint32_t *)dmabuf->virt;
+               for (i = 0; i < *mbx_word_cnt; i++) {
+                       if (!(i % 8)) {
+                               if (i != 0)
+                                       printk(KERN_ERR "%s\n", line_buf);
+                               len = 0;
+                               len += snprintf(line_buf+len,
+                                               LPFC_MBX_ACC_LBUF_SZ-len,
+                                               "%03d: ", i);
+                       }
+                       len += snprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len,
+                                       "%08x ", (uint32_t)*pword);
+                       pword++;
+               }
+               if ((i - 1) % 8)
+                       printk(KERN_ERR "%s\n", line_buf);
+               (*mbx_dump_cnt)--;
+       }
+
+       /* Clean out command structure on reaching dump count */
+       if (*mbx_dump_cnt == 0)
+               memset(&idiag, 0, sizeof(idiag));
+       return;
+#endif
+}
+
+/* lpfc_idiag_mbxacc_dump_issue_mbox - idiag debugfs dump issue mailbox command
+ * @phba: Pointer to HBA context object.
+ * @dmabuf: Pointer to a DMA buffer descriptor.
+ *
+ * Description:
+ * This routine dump a pass-through non-embedded mailbox command from issue
+ * mailbox command.
+ **/
+void
+lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *phba, MAILBOX_t *pmbox)
+{
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+       uint32_t *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt, *mbx_mbox_cmd;
+       char line_buf[LPFC_MBX_ACC_LBUF_SZ];
+       int len = 0;
+       uint32_t *pword;
+       uint8_t *pbyte;
+       uint32_t i, j;
+
+       if (idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP)
+               return;
+
+       mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
+       mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
+       mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
+       mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
+
+       if (!(*mbx_dump_map & LPFC_MBX_DMP_MBX_ALL) ||
+           (*mbx_dump_cnt == 0) ||
+           (*mbx_word_cnt == 0))
+               return;
+
+       if ((*mbx_mbox_cmd != LPFC_MBX_ALL_CMD) &&
+           (*mbx_mbox_cmd != pmbox->mbxCommand))
+               return;
+
+       /* dump buffer content */
+       if (*mbx_dump_map & LPFC_MBX_DMP_MBX_WORD) {
+               printk(KERN_ERR "Mailbox command:0x%x dump by word:\n",
+                      pmbox->mbxCommand);
+               pword = (uint32_t *)pmbox;
+               for (i = 0; i < *mbx_word_cnt; i++) {
+                       if (!(i % 8)) {
+                               if (i != 0)
+                                       printk(KERN_ERR "%s\n", line_buf);
+                               len = 0;
+                               memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ);
+                               len += snprintf(line_buf+len,
+                                               LPFC_MBX_ACC_LBUF_SZ-len,
+                                               "%03d: ", i);
+                       }
+                       len += snprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len,
+                                       "%08x ",
+                                       ((uint32_t)*pword) & 0xffffffff);
+                       pword++;
+               }
+               if ((i - 1) % 8)
+                       printk(KERN_ERR "%s\n", line_buf);
+               printk(KERN_ERR "\n");
+       }
+       if (*mbx_dump_map & LPFC_MBX_DMP_MBX_BYTE) {
+               printk(KERN_ERR "Mailbox command:0x%x dump by byte:\n",
+                      pmbox->mbxCommand);
+               pbyte = (uint8_t *)pmbox;
+               for (i = 0; i < *mbx_word_cnt; i++) {
+                       if (!(i % 8)) {
+                               if (i != 0)
+                                       printk(KERN_ERR "%s\n", line_buf);
+                               len = 0;
+                               memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ);
+                               len += snprintf(line_buf+len,
+                                               LPFC_MBX_ACC_LBUF_SZ-len,
+                                               "%03d: ", i);
+                       }
+                       for (j = 0; j < 4; j++) {
+                               len += snprintf(line_buf+len,
+                                               LPFC_MBX_ACC_LBUF_SZ-len,
+                                               "%02x",
+                                               ((uint8_t)*pbyte) & 0xff);
+                               pbyte++;
+                       }
+                       len += snprintf(line_buf+len,
+                                       LPFC_MBX_ACC_LBUF_SZ-len, " ");
+               }
+               if ((i - 1) % 8)
+                       printk(KERN_ERR "%s\n", line_buf);
+               printk(KERN_ERR "\n");
+       }
+       (*mbx_dump_cnt)--;
+
+       /* Clean out command structure on reaching dump count */
+       if (*mbx_dump_cnt == 0)
+               memset(&idiag, 0, sizeof(idiag));
+       return;
+#endif
+}
+
 /**
  * lpfc_debugfs_initialize - Initialize debugfs for a vport
  * @vport: The vport pointer to initialize.
@@ -2673,7 +3894,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                                 vport, &lpfc_debugfs_op_nodelist);
        if (!vport->debug_nodelist) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-                                "0409 Can't create debugfs nodelist\n");
+                                "2985 Can't create debugfs nodelist\n");
                goto debug_failed;
        }
 
@@ -2710,6 +3931,20 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                idiag.offset.last_rd = 0;
        }
 
+       /* iDiag PCI BAR access */
+       snprintf(name, sizeof(name), "barAcc");
+       if (!phba->idiag_bar_acc) {
+               phba->idiag_bar_acc =
+                       debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+                               phba->idiag_root, phba, &lpfc_idiag_op_barAcc);
+               if (!phba->idiag_bar_acc) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                       "3056 Can't create idiag debugfs\n");
+                       goto debug_failed;
+               }
+               idiag.offset.last_rd = 0;
+       }
+
        /* iDiag get PCI function queue information */
        snprintf(name, sizeof(name), "queInfo");
        if (!phba->idiag_que_info) {
@@ -2749,6 +3984,50 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                }
        }
 
+       /* iDiag access PCI function control registers */
+       snprintf(name, sizeof(name), "ctlAcc");
+       if (!phba->idiag_ctl_acc) {
+               phba->idiag_ctl_acc =
+                       debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+                               phba->idiag_root, phba, &lpfc_idiag_op_ctlAcc);
+               if (!phba->idiag_ctl_acc) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                        "2981 Can't create idiag debugfs\n");
+                       goto debug_failed;
+               }
+       }
+
+       /* iDiag access mbox commands */
+       snprintf(name, sizeof(name), "mbxAcc");
+       if (!phba->idiag_mbx_acc) {
+               phba->idiag_mbx_acc =
+                       debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+                               phba->idiag_root, phba, &lpfc_idiag_op_mbxAcc);
+               if (!phba->idiag_mbx_acc) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                       "2980 Can't create idiag debugfs\n");
+                       goto debug_failed;
+               }
+       }
+
+       /* iDiag extents access commands */
+       if (phba->sli4_hba.extents_in_use) {
+               snprintf(name, sizeof(name), "extAcc");
+               if (!phba->idiag_ext_acc) {
+                       phba->idiag_ext_acc =
+                               debugfs_create_file(name,
+                                                   S_IFREG|S_IRUGO|S_IWUSR,
+                                                   phba->idiag_root, phba,
+                                                   &lpfc_idiag_op_extAcc);
+                       if (!phba->idiag_ext_acc) {
+                               lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                               "2986 Cant create "
+                                               "idiag debugfs\n");
+                               goto debug_failed;
+                       }
+               }
+       }
+
 debug_failed:
        return;
 #endif
@@ -2783,7 +4062,6 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
                debugfs_remove(vport->debug_nodelist); /* nodelist */
                vport->debug_nodelist = NULL;
        }
-
        if (vport->vport_debugfs_root) {
                debugfs_remove(vport->vport_debugfs_root); /* vportX */
                vport->vport_debugfs_root = NULL;
@@ -2827,6 +4105,21 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
                 * iDiag release
                 */
                if (phba->sli_rev == LPFC_SLI_REV4) {
+                       if (phba->idiag_ext_acc) {
+                               /* iDiag extAcc */
+                               debugfs_remove(phba->idiag_ext_acc);
+                               phba->idiag_ext_acc = NULL;
+                       }
+                       if (phba->idiag_mbx_acc) {
+                               /* iDiag mbxAcc */
+                               debugfs_remove(phba->idiag_mbx_acc);
+                               phba->idiag_mbx_acc = NULL;
+                       }
+                       if (phba->idiag_ctl_acc) {
+                               /* iDiag ctlAcc */
+                               debugfs_remove(phba->idiag_ctl_acc);
+                               phba->idiag_ctl_acc = NULL;
+                       }
                        if (phba->idiag_drb_acc) {
                                /* iDiag drbAcc */
                                debugfs_remove(phba->idiag_drb_acc);
@@ -2842,6 +4135,11 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
                                debugfs_remove(phba->idiag_que_info);
                                phba->idiag_que_info = NULL;
                        }
+                       if (phba->idiag_bar_acc) {
+                               /* iDiag barAcc */
+                               debugfs_remove(phba->idiag_bar_acc);
+                               phba->idiag_bar_acc = NULL;
+                       }
                        if (phba->idiag_pci_cfg) {
                                /* iDiag pciCfg */
                                debugfs_remove(phba->idiag_pci_cfg);
index 6525a5e..f83bd94 100644 (file)
 /* hbqinfo output buffer size */
 #define LPFC_HBQINFO_SIZE 8192
 
+/*
+ * For SLI4 iDiag debugfs diagnostics tool
+ */
+
 /* pciConf */
 #define LPFC_PCI_CFG_BROWSE 0xffff
 #define LPFC_PCI_CFG_RD_CMD_ARG 2
 #define LPFC_PCI_CFG_WR_CMD_ARG 3
 #define LPFC_PCI_CFG_SIZE 4096
-#define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2)
 #define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4)
 
+#define IDIAG_PCICFG_WHERE_INDX 0
+#define IDIAG_PCICFG_COUNT_INDX 1
+#define IDIAG_PCICFG_VALUE_INDX 2
+
+/* barAcc */
+#define LPFC_PCI_BAR_BROWSE 0xffff
+#define LPFC_PCI_BAR_RD_CMD_ARG 3
+#define LPFC_PCI_BAR_WR_CMD_ARG 3
+
+#define LPFC_PCI_IF0_BAR0_SIZE (1024 *  16)
+#define LPFC_PCI_IF0_BAR1_SIZE (1024 * 128)
+#define LPFC_PCI_IF0_BAR2_SIZE (1024 * 128)
+#define LPFC_PCI_IF2_BAR0_SIZE (1024 *  32)
+
+#define LPFC_PCI_BAR_RD_BUF_SIZE 4096
+#define LPFC_PCI_BAR_RD_SIZE (LPFC_PCI_BAR_RD_BUF_SIZE/4)
+
+#define LPFC_PCI_IF0_BAR0_RD_SIZE (LPFC_PCI_IF0_BAR0_SIZE/4)
+#define LPFC_PCI_IF0_BAR1_RD_SIZE (LPFC_PCI_IF0_BAR1_SIZE/4)
+#define LPFC_PCI_IF0_BAR2_RD_SIZE (LPFC_PCI_IF0_BAR2_SIZE/4)
+#define LPFC_PCI_IF2_BAR0_RD_SIZE (LPFC_PCI_IF2_BAR0_SIZE/4)
+
+#define IDIAG_BARACC_BAR_NUM_INDX 0
+#define IDIAG_BARACC_OFF_SET_INDX 1
+#define IDIAG_BARACC_ACC_MOD_INDX 2
+#define IDIAG_BARACC_REG_VAL_INDX 2
+#define IDIAG_BARACC_BAR_SZE_INDX 3
+
+#define IDIAG_BARACC_BAR_0 0
+#define IDIAG_BARACC_BAR_1 1
+#define IDIAG_BARACC_BAR_2 2
+
+#define SINGLE_WORD 1
+
 /* queue info */
 #define LPFC_QUE_INFO_GET_BUF_SIZE 4096
 
 #define LPFC_IDIAG_WQ 4
 #define LPFC_IDIAG_RQ 5
 
-/* doorbell acc */
+#define IDIAG_QUEACC_QUETP_INDX 0
+#define IDIAG_QUEACC_QUEID_INDX 1
+#define IDIAG_QUEACC_INDEX_INDX 2
+#define IDIAG_QUEACC_COUNT_INDX 3
+#define IDIAG_QUEACC_OFFST_INDX 4
+#define IDIAG_QUEACC_VALUE_INDX 5
+
+/* doorbell register acc */
 #define LPFC_DRB_ACC_ALL 0xffff
 #define LPFC_DRB_ACC_RD_CMD_ARG 1
 #define LPFC_DRB_ACC_WR_CMD_ARG 2
 
 #define LPFC_DRB_MAX  4
 
+#define IDIAG_DRBACC_REGID_INDX 0
+#define IDIAG_DRBACC_VALUE_INDX 1
+
+/* control register acc */
+#define LPFC_CTL_ACC_ALL 0xffff
+#define LPFC_CTL_ACC_RD_CMD_ARG 1
+#define LPFC_CTL_ACC_WR_CMD_ARG 2
+#define LPFC_CTL_ACC_BUF_SIZE 256
+
+#define LPFC_CTL_PORT_SEM  1
+#define LPFC_CTL_PORT_STA  2
+#define LPFC_CTL_PORT_CTL  3
+#define LPFC_CTL_PORT_ER1  4
+#define LPFC_CTL_PORT_ER2  5
+#define LPFC_CTL_PDEV_CTL  6
+
+#define LPFC_CTL_MAX  6
+
+#define IDIAG_CTLACC_REGID_INDX 0
+#define IDIAG_CTLACC_VALUE_INDX 1
+
+/* mailbox access */
+#define LPFC_MBX_DMP_ARG 4
+
+#define LPFC_MBX_ACC_BUF_SIZE 512
+#define LPFC_MBX_ACC_LBUF_SZ 128
+
+#define LPFC_MBX_DMP_MBX_WORD 0x00000001
+#define LPFC_MBX_DMP_MBX_BYTE 0x00000002
+#define LPFC_MBX_DMP_MBX_ALL (LPFC_MBX_DMP_MBX_WORD | LPFC_MBX_DMP_MBX_BYTE)
+
+#define LPFC_BSG_DMP_MBX_RD_MBX 0x00000001
+#define LPFC_BSG_DMP_MBX_RD_BUF 0x00000002
+#define LPFC_BSG_DMP_MBX_WR_MBX 0x00000004
+#define LPFC_BSG_DMP_MBX_WR_BUF 0x00000008
+#define LPFC_BSG_DMP_MBX_ALL (LPFC_BSG_DMP_MBX_RD_MBX | \
+                             LPFC_BSG_DMP_MBX_RD_BUF | \
+                             LPFC_BSG_DMP_MBX_WR_MBX | \
+                             LPFC_BSG_DMP_MBX_WR_BUF)
+
+#define LPFC_MBX_DMP_ALL 0xffff
+#define LPFC_MBX_ALL_CMD 0xff
+
+#define IDIAG_MBXACC_MBCMD_INDX 0
+#define IDIAG_MBXACC_DPMAP_INDX 1
+#define IDIAG_MBXACC_DPCNT_INDX 2
+#define IDIAG_MBXACC_WDCNT_INDX 3
+
+/* extents access */
+#define LPFC_EXT_ACC_CMD_ARG 1
+#define LPFC_EXT_ACC_BUF_SIZE 4096
+
+#define LPFC_EXT_ACC_AVAIL 0x1
+#define LPFC_EXT_ACC_ALLOC 0x2
+#define LPFC_EXT_ACC_DRIVR 0x4
+#define LPFC_EXT_ACC_ALL   (LPFC_EXT_ACC_DRIVR | \
+                           LPFC_EXT_ACC_AVAIL | \
+                           LPFC_EXT_ACC_ALLOC)
+
+#define IDIAG_EXTACC_EXMAP_INDX 0
+
 #define SIZE_U8  sizeof(uint8_t)
 #define SIZE_U16 sizeof(uint16_t)
 #define SIZE_U32 sizeof(uint32_t)
@@ -110,6 +215,11 @@ struct lpfc_idiag_cmd {
 #define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003
 #define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004
 
+#define LPFC_IDIAG_CMD_BARACC_RD 0x00000008
+#define LPFC_IDIAG_CMD_BARACC_WR 0x00000009
+#define LPFC_IDIAG_CMD_BARACC_ST 0x0000000a
+#define LPFC_IDIAG_CMD_BARACC_CL 0x0000000b
+
 #define LPFC_IDIAG_CMD_QUEACC_RD 0x00000011
 #define LPFC_IDIAG_CMD_QUEACC_WR 0x00000012
 #define LPFC_IDIAG_CMD_QUEACC_ST 0x00000013
@@ -119,6 +229,17 @@ struct lpfc_idiag_cmd {
 #define LPFC_IDIAG_CMD_DRBACC_WR 0x00000022
 #define LPFC_IDIAG_CMD_DRBACC_ST 0x00000023
 #define LPFC_IDIAG_CMD_DRBACC_CL 0x00000024
+
+#define LPFC_IDIAG_CMD_CTLACC_RD 0x00000031
+#define LPFC_IDIAG_CMD_CTLACC_WR 0x00000032
+#define LPFC_IDIAG_CMD_CTLACC_ST 0x00000033
+#define LPFC_IDIAG_CMD_CTLACC_CL 0x00000034
+
+#define LPFC_IDIAG_CMD_MBXACC_DP 0x00000041
+#define LPFC_IDIAG_BSG_MBXACC_DP 0x00000042
+
+#define LPFC_IDIAG_CMD_EXTACC_RD 0x00000051
+
        uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE];
 };
 
index 32a0845..023da0e 100644 (file)
@@ -647,21 +647,15 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                }
                lpfc_cleanup_pending_mbox(vport);
 
-               if (phba->sli_rev == LPFC_SLI_REV4)
+               if (phba->sli_rev == LPFC_SLI_REV4) {
                        lpfc_sli4_unreg_all_rpis(vport);
-
-               if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
                        lpfc_mbx_unreg_vpi(vport);
                        spin_lock_irq(shost->host_lock);
                        vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
-                       spin_unlock_irq(shost->host_lock);
-               }
-               /*
-                * If VPI is unreged, driver need to do INIT_VPI
-                * before re-registering
-                */
-               if (phba->sli_rev == LPFC_SLI_REV4) {
-                       spin_lock_irq(shost->host_lock);
+                       /*
+                       * If VPI is unreged, driver need to do INIT_VPI
+                       * before re-registering
+                       */
                        vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
                        spin_unlock_irq(shost->host_lock);
                }
@@ -880,6 +874,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                                        phba->fcf.current_rec.fcf_indx,
                                        irsp->ulpStatus, irsp->un.ulpWord[4],
                                        irsp->ulpTimeout);
+                       lpfc_sli4_set_fcf_flogi_fail(phba,
+                                       phba->fcf.current_rec.fcf_indx);
                        fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba);
                        rc = lpfc_sli4_fcf_rr_next_proc(vport, fcf_index);
                        if (rc)
@@ -1096,11 +1092,14 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                        /* Set the fcfi to the fcfi we registered with */
                        elsiocb->iocb.ulpContext = phba->fcf.fcfi;
                }
-       } else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
-               sp->cmn.request_multiple_Nport = 1;
-               /* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */
-               icmd->ulpCt_h = 1;
-               icmd->ulpCt_l = 0;
+       } else {
+               if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+                       sp->cmn.request_multiple_Nport = 1;
+                       /* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */
+                       icmd->ulpCt_h = 1;
+                       icmd->ulpCt_l = 0;
+               } else
+                       sp->cmn.request_multiple_Nport = 0;
        }
 
        if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) {
@@ -3656,7 +3655,8 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
                }
 
                icmd = &elsiocb->iocb;
-               icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
+               icmd->ulpContext = oldcmd->ulpContext;  /* Xri / rx_id */
+               icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id;
                pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
                *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
                pcmd += sizeof(uint32_t);
@@ -3673,7 +3673,8 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
                        return 1;
 
                icmd = &elsiocb->iocb;
-               icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
+               icmd->ulpContext = oldcmd->ulpContext;  /* Xri / rx_id */
+               icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id;
                pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
                if (mbox)
@@ -3695,7 +3696,8 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
                        return 1;
 
                icmd = &elsiocb->iocb;
-               icmd->ulpContext = oldcmd->ulpContext; /* Xri */
+               icmd->ulpContext = oldcmd->ulpContext;  /* Xri / rx_id */
+               icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id;
                pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
                memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
@@ -3781,7 +3783,8 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
 
        icmd = &elsiocb->iocb;
        oldcmd = &oldiocb->iocb;
-       icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
+       icmd->ulpContext = oldcmd->ulpContext;  /* Xri / rx_id */
+       icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id;
        pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
        *((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT;
@@ -3853,7 +3856,8 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
 
        icmd = &elsiocb->iocb;
        oldcmd = &oldiocb->iocb;
-       icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
+       icmd->ulpContext = oldcmd->ulpContext;  /* Xri / rx_id */
+       icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id;
 
        /* Xmit ADISC ACC response tag <ulpIoTag> */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
@@ -3931,7 +3935,9 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
 
        icmd = &elsiocb->iocb;
        oldcmd = &oldiocb->iocb;
-       icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
+       icmd->ulpContext = oldcmd->ulpContext;  /* Xri / rx_id */
+       icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id;
+
        /* Xmit PRLI ACC response tag <ulpIoTag> */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                         "0131 Xmit PRLI ACC response tag x%x xri x%x, "
@@ -4035,7 +4041,9 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
 
        icmd = &elsiocb->iocb;
        oldcmd = &oldiocb->iocb;
-       icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
+       icmd->ulpContext = oldcmd->ulpContext;  /* Xri / rx_id */
+       icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id;
+
        /* Xmit RNID ACC response tag <ulpIoTag> */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                         "0132 Xmit RNID ACC response tag x%x xri x%x\n",
@@ -4163,7 +4171,9 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data,
        if (!elsiocb)
                return 1;
 
-       elsiocb->iocb.ulpContext = oldiocb->iocb.ulpContext;    /* Xri */
+       elsiocb->iocb.ulpContext = oldiocb->iocb.ulpContext;  /* Xri / rx_id */
+       elsiocb->iocb.unsli3.rcvsli3.ox_id = oldiocb->iocb.unsli3.rcvsli3.ox_id;
+
        /* Xmit ECHO ACC response tag <ulpIoTag> */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                         "2876 Xmit ECHO ACC response tag x%x xri x%x\n",
@@ -5054,13 +5064,15 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        uint8_t *pcmd;
        struct lpfc_iocbq *elsiocb;
        struct lpfc_nodelist *ndlp;
-       uint16_t xri;
+       uint16_t oxid;
+       uint16_t rxid;
        uint32_t cmdsize;
 
        mb = &pmb->u.mb;
 
        ndlp = (struct lpfc_nodelist *) pmb->context2;
-       xri = (uint16_t) ((unsigned long)(pmb->context1));
+       rxid = (uint16_t) ((unsigned long)(pmb->context1) & 0xffff);
+       oxid = (uint16_t) (((unsigned long)(pmb->context1) >> 16) & 0xffff);
        pmb->context1 = NULL;
        pmb->context2 = NULL;
 
@@ -5082,7 +5094,8 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                return;
 
        icmd = &elsiocb->iocb;
-       icmd->ulpContext = xri;
+       icmd->ulpContext = rxid;
+       icmd->unsli3.rcvsli3.ox_id = oxid;
 
        pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
        *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
@@ -5137,13 +5150,16 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        uint8_t *pcmd;
        struct lpfc_iocbq *elsiocb;
        struct lpfc_nodelist *ndlp;
-       uint16_t xri, status;
+       uint16_t status;
+       uint16_t oxid;
+       uint16_t rxid;
        uint32_t cmdsize;
 
        mb = &pmb->u.mb;
 
        ndlp = (struct lpfc_nodelist *) pmb->context2;
-       xri = (uint16_t) ((unsigned long)(pmb->context1));
+       rxid = (uint16_t) ((unsigned long)(pmb->context1) & 0xffff);
+       oxid = (uint16_t) (((unsigned long)(pmb->context1) >> 16) & 0xffff);
        pmb->context1 = NULL;
        pmb->context2 = NULL;
 
@@ -5165,7 +5181,8 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                return;
 
        icmd = &elsiocb->iocb;
-       icmd->ulpContext = xri;
+       icmd->ulpContext = rxid;
+       icmd->unsli3.rcvsli3.ox_id = oxid;
 
        pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
        *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
@@ -5238,8 +5255,9 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
        mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC);
        if (mbox) {
                lpfc_read_lnk_stat(phba, mbox);
-               mbox->context1 =
-                   (void *)((unsigned long) cmdiocb->iocb.ulpContext);
+               mbox->context1 = (void *)((unsigned long)
+                       ((cmdiocb->iocb.unsli3.rcvsli3.ox_id << 16) |
+                       cmdiocb->iocb.ulpContext)); /* rx_id */
                mbox->context2 = lpfc_nlp_get(ndlp);
                mbox->vport = vport;
                mbox->mbox_cmpl = lpfc_els_rsp_rls_acc;
@@ -5314,7 +5332,8 @@ lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
        pcmd += sizeof(uint32_t); /* Skip past command */
 
        /* use the command's xri in the response */
-       elsiocb->iocb.ulpContext = cmdiocb->iocb.ulpContext;
+       elsiocb->iocb.ulpContext = cmdiocb->iocb.ulpContext;  /* Xri / rx_id */
+       elsiocb->iocb.unsli3.rcvsli3.ox_id = cmdiocb->iocb.unsli3.rcvsli3.ox_id;
 
        rtv_rsp = (struct RTV_RSP *)pcmd;
 
@@ -5399,8 +5418,9 @@ lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC);
                if (mbox) {
                        lpfc_read_lnk_stat(phba, mbox);
-                       mbox->context1 =
-                           (void *)((unsigned long) cmdiocb->iocb.ulpContext);
+                       mbox->context1 = (void *)((unsigned long)
+                               ((cmdiocb->iocb.unsli3.rcvsli3.ox_id << 16) |
+                               cmdiocb->iocb.ulpContext)); /* rx_id */
                        mbox->context2 = lpfc_nlp_get(ndlp);
                        mbox->vport = vport;
                        mbox->mbox_cmpl = lpfc_els_rsp_rps_acc;
@@ -5554,7 +5574,8 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
 
        icmd = &elsiocb->iocb;
        oldcmd = &oldiocb->iocb;
-       icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
+       icmd->ulpContext = oldcmd->ulpContext;  /* Xri / rx_id */
+       icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id;
 
        pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
        *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
@@ -6586,7 +6607,7 @@ lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
 {
        struct lpfc_vport *vport;
        unsigned long flags;
-       int i;
+       int i = 0;
 
        /* The physical ports are always vpi 0 - translate is unnecessary. */
        if (vpi > 0) {
@@ -6609,7 +6630,7 @@ lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
 
        spin_lock_irqsave(&phba->hbalock, flags);
        list_for_each_entry(vport, &phba->port_list, listentry) {
-               if (vport->vpi == vpi) {
+               if (vport->vpi == i) {
                        spin_unlock_irqrestore(&phba->hbalock, flags);
                        return vport;
                }
@@ -7787,6 +7808,7 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba,
 {
        uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);
        uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
+       uint16_t lxri = 0;
 
        struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
        unsigned long iflag = 0;
@@ -7815,7 +7837,12 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba,
                }
        }
        spin_unlock(&phba->sli4_hba.abts_sgl_list_lock);
-       sglq_entry = __lpfc_get_active_sglq(phba, xri);
+       lxri = lpfc_sli4_xri_inrange(phba, xri);
+       if (lxri == NO_XRI) {
+               spin_unlock_irqrestore(&phba->hbalock, iflag);
+               return;
+       }
+       sglq_entry = __lpfc_get_active_sglq(phba, lxri);
        if (!sglq_entry || (sglq_entry->sli4_xritag != xri)) {
                spin_unlock_irqrestore(&phba->hbalock, iflag);
                return;
index 18d0dbf..0b47adf 100644 (file)
@@ -1109,6 +1109,28 @@ out:
        return;
 }
 
+/**
+ * lpfc_sli4_clear_fcf_rr_bmask
+ * @phba pointer to the struct lpfc_hba for this port.
+ * This fucnction resets the round robin bit mask and clears the
+ * fcf priority list. The list deletions are done while holding the
+ * hbalock. The ON_LIST flag and the FLOGI_FAILED flags are cleared
+ * from the lpfc_fcf_pri record.
+ **/
+void
+lpfc_sli4_clear_fcf_rr_bmask(struct lpfc_hba *phba)
+{
+       struct lpfc_fcf_pri *fcf_pri;
+       struct lpfc_fcf_pri *next_fcf_pri;
+       memset(phba->fcf.fcf_rr_bmask, 0, sizeof(*phba->fcf.fcf_rr_bmask));
+       spin_lock_irq(&phba->hbalock);
+       list_for_each_entry_safe(fcf_pri, next_fcf_pri,
+                               &phba->fcf.fcf_pri_list, list) {
+               list_del_init(&fcf_pri->list);
+               fcf_pri->fcf_rec.flag = 0;
+       }
+       spin_unlock_irq(&phba->hbalock);
+}
 static void
 lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 {
@@ -1130,7 +1152,8 @@ lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        spin_unlock_irq(&phba->hbalock);
 
        /* If there is a pending FCoE event, restart FCF table scan. */
-       if (lpfc_check_pending_fcoe_event(phba, LPFC_UNREG_FCF))
+       if ((!(phba->hba_flag & FCF_RR_INPROG)) &&
+               lpfc_check_pending_fcoe_event(phba, LPFC_UNREG_FCF))
                goto fail_out;
 
        /* Mark successful completion of FCF table scan */
@@ -1249,6 +1272,30 @@ lpfc_vlan_id_match(uint16_t curr_vlan_id, uint16_t new_vlan_id)
        return (curr_vlan_id == new_vlan_id);
 }
 
+/**
+ * lpfc_update_fcf_record - Update driver fcf record
+ * __lpfc_update_fcf_record_pri - update the lpfc_fcf_pri record.
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_index: Index for the lpfc_fcf_record.
+ * @new_fcf_record: pointer to hba fcf record.
+ *
+ * This routine updates the driver FCF priority record from the new HBA FCF
+ * record. This routine is called with the host lock held.
+ **/
+static void
+__lpfc_update_fcf_record_pri(struct lpfc_hba *phba, uint16_t fcf_index,
+                                struct fcf_record *new_fcf_record
+                                )
+{
+       struct lpfc_fcf_pri *fcf_pri;
+
+       fcf_pri = &phba->fcf.fcf_pri[fcf_index];
+       fcf_pri->fcf_rec.fcf_index = fcf_index;
+       /* FCF record priority */
+       fcf_pri->fcf_rec.priority = new_fcf_record->fip_priority;
+
+}
+
 /**
  * lpfc_copy_fcf_record - Copy fcf information to lpfc_hba.
  * @fcf: pointer to driver fcf record.
@@ -1332,6 +1379,9 @@ __lpfc_update_fcf_record(struct lpfc_hba *phba, struct lpfc_fcf_rec *fcf_rec,
        fcf_rec->addr_mode = addr_mode;
        fcf_rec->vlan_id = vlan_id;
        fcf_rec->flag |= (flag | RECORD_VALID);
+       __lpfc_update_fcf_record_pri(phba,
+               bf_get(lpfc_fcf_record_fcf_index, new_fcf_record),
+                                new_fcf_record);
 }
 
 /**
@@ -1834,6 +1884,8 @@ lpfc_sli4_fcf_record_match(struct lpfc_hba *phba,
                return false;
        if (!lpfc_fab_name_match(fcf_rec->fabric_name, new_fcf_record))
                return false;
+       if (fcf_rec->priority != new_fcf_record->fip_priority)
+               return false;
        return true;
 }
 
@@ -1896,6 +1948,152 @@ stop_flogi_current_fcf:
        return 1;
 }
 
+/**
+ * lpfc_sli4_fcf_pri_list_del
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_index the index of the fcf record to delete
+ * This routine checks the on list flag of the fcf_index to be deleted.
+ * If it is one the list then it is removed from the list, and the flag
+ * is cleared. This routine grab the hbalock before removing the fcf
+ * record from the list.
+ **/
+static void lpfc_sli4_fcf_pri_list_del(struct lpfc_hba *phba,
+                       uint16_t fcf_index)
+{
+       struct lpfc_fcf_pri *new_fcf_pri;
+
+       new_fcf_pri = &phba->fcf.fcf_pri[fcf_index];
+       lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+               "3058 deleting idx x%x pri x%x flg x%x\n",
+               fcf_index, new_fcf_pri->fcf_rec.priority,
+                new_fcf_pri->fcf_rec.flag);
+       spin_lock_irq(&phba->hbalock);
+       if (new_fcf_pri->fcf_rec.flag & LPFC_FCF_ON_PRI_LIST) {
+               if (phba->fcf.current_rec.priority ==
+                               new_fcf_pri->fcf_rec.priority)
+                       phba->fcf.eligible_fcf_cnt--;
+               list_del_init(&new_fcf_pri->list);
+               new_fcf_pri->fcf_rec.flag &= ~LPFC_FCF_ON_PRI_LIST;
+       }
+       spin_unlock_irq(&phba->hbalock);
+}
+
+/**
+ * lpfc_sli4_set_fcf_flogi_fail
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_index the index of the fcf record to update
+ * This routine acquires the hbalock and then set the LPFC_FCF_FLOGI_FAILED
+ * flag so the the round robin slection for the particular priority level
+ * will try a different fcf record that does not have this bit set.
+ * If the fcf record is re-read for any reason this flag is cleared brfore
+ * adding it to the priority list.
+ **/
+void
+lpfc_sli4_set_fcf_flogi_fail(struct lpfc_hba *phba, uint16_t fcf_index)
+{
+       struct lpfc_fcf_pri *new_fcf_pri;
+       new_fcf_pri = &phba->fcf.fcf_pri[fcf_index];
+       spin_lock_irq(&phba->hbalock);
+       new_fcf_pri->fcf_rec.flag |= LPFC_FCF_FLOGI_FAILED;
+       spin_unlock_irq(&phba->hbalock);
+}
+
+/**
+ * lpfc_sli4_fcf_pri_list_add
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_index the index of the fcf record to add
+ * This routine checks the priority of the fcf_index to be added.
+ * If it is a lower priority than the current head of the fcf_pri list
+ * then it is added to the list in the right order.
+ * If it is the same priority as the current head of the list then it
+ * is added to the head of the list and its bit in the rr_bmask is set.
+ * If the fcf_index to be added is of a higher priority than the current
+ * head of the list then the rr_bmask is cleared, its bit is set in the
+ * rr_bmask and it is added to the head of the list.
+ * returns:
+ * 0=success 1=failure
+ **/
+int lpfc_sli4_fcf_pri_list_add(struct lpfc_hba *phba, uint16_t fcf_index,
+       struct fcf_record *new_fcf_record)
+{
+       uint16_t current_fcf_pri;
+       uint16_t last_index;
+       struct lpfc_fcf_pri *fcf_pri;
+       struct lpfc_fcf_pri *next_fcf_pri;
+       struct lpfc_fcf_pri *new_fcf_pri;
+       int ret;
+
+       new_fcf_pri = &phba->fcf.fcf_pri[fcf_index];
+       lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+               "3059 adding idx x%x pri x%x flg x%x\n",
+               fcf_index, new_fcf_record->fip_priority,
+                new_fcf_pri->fcf_rec.flag);
+       spin_lock_irq(&phba->hbalock);
+       if (new_fcf_pri->fcf_rec.flag & LPFC_FCF_ON_PRI_LIST)
+               list_del_init(&new_fcf_pri->list);
+       new_fcf_pri->fcf_rec.fcf_index = fcf_index;
+       new_fcf_pri->fcf_rec.priority = new_fcf_record->fip_priority;
+       if (list_empty(&phba->fcf.fcf_pri_list)) {
+               list_add(&new_fcf_pri->list, &phba->fcf.fcf_pri_list);
+               ret = lpfc_sli4_fcf_rr_index_set(phba,
+                               new_fcf_pri->fcf_rec.fcf_index);
+               goto out;
+       }
+
+       last_index = find_first_bit(phba->fcf.fcf_rr_bmask,
+                               LPFC_SLI4_FCF_TBL_INDX_MAX);
+       if (last_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
+               ret = 0; /* Empty rr list */
+               goto out;
+       }
+       current_fcf_pri = phba->fcf.fcf_pri[last_index].fcf_rec.priority;
+       if (new_fcf_pri->fcf_rec.priority <=  current_fcf_pri) {
+               list_add(&new_fcf_pri->list, &phba->fcf.fcf_pri_list);
+               if (new_fcf_pri->fcf_rec.priority <  current_fcf_pri) {
+                       memset(phba->fcf.fcf_rr_bmask, 0,
+                               sizeof(*phba->fcf.fcf_rr_bmask));
+                       /* fcfs_at_this_priority_level = 1; */
+                       phba->fcf.eligible_fcf_cnt = 1;
+               } else
+                       /* fcfs_at_this_priority_level++; */
+                       phba->fcf.eligible_fcf_cnt++;
+               ret = lpfc_sli4_fcf_rr_index_set(phba,
+                               new_fcf_pri->fcf_rec.fcf_index);
+               goto out;
+       }
+
+       list_for_each_entry_safe(fcf_pri, next_fcf_pri,
+                               &phba->fcf.fcf_pri_list, list) {
+               if (new_fcf_pri->fcf_rec.priority <=
+                               fcf_pri->fcf_rec.priority) {
+                       if (fcf_pri->list.prev == &phba->fcf.fcf_pri_list)
+                               list_add(&new_fcf_pri->list,
+                                               &phba->fcf.fcf_pri_list);
+                       else
+                               list_add(&new_fcf_pri->list,
+                                        &((struct lpfc_fcf_pri *)
+                                       fcf_pri->list.prev)->list);
+                       ret = 0;
+                       goto out;
+               } else if (fcf_pri->list.next == &phba->fcf.fcf_pri_list
+                       || new_fcf_pri->fcf_rec.priority <
+                               next_fcf_pri->fcf_rec.priority) {
+                       list_add(&new_fcf_pri->list, &fcf_pri->list);
+                       ret = 0;
+                       goto out;
+               }
+               if (new_fcf_pri->fcf_rec.priority > fcf_pri->fcf_rec.priority)
+                       continue;
+
+       }
+       ret = 1;
+out:
+       /* we use = instead of |= to clear the FLOGI_FAILED flag. */
+       new_fcf_pri->fcf_rec.flag = LPFC_FCF_ON_PRI_LIST;
+       spin_unlock_irq(&phba->hbalock);
+       return ret;
+}
+
 /**
  * lpfc_mbx_cmpl_fcf_scan_read_fcf_rec - fcf scan read_fcf mbox cmpl handler.
  * @phba: pointer to lpfc hba data structure.
@@ -1958,6 +2156,9 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
         * record for roundrobin FCF failover.
         */
        if (!rc) {
+               lpfc_sli4_fcf_pri_list_del(phba,
+                                       bf_get(lpfc_fcf_record_fcf_index,
+                                              new_fcf_record));
                lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
                                "2781 FCF (x%x) failed connection "
                                "list check: (x%x/x%x)\n",
@@ -2005,7 +2206,8 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                goto read_next_fcf;
        } else {
                fcf_index = bf_get(lpfc_fcf_record_fcf_index, new_fcf_record);
-               rc = lpfc_sli4_fcf_rr_index_set(phba, fcf_index);
+               rc = lpfc_sli4_fcf_pri_list_add(phba, fcf_index,
+                                                       new_fcf_record);
                if (rc)
                        goto read_next_fcf;
        }
@@ -2018,7 +2220,8 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
         */
        spin_lock_irq(&phba->hbalock);
        if (phba->fcf.fcf_flag & FCF_IN_USE) {
-               if (lpfc_sli4_fcf_record_match(phba, &phba->fcf.current_rec,
+               if (phba->cfg_fcf_failover_policy == LPFC_FCF_FOV &&
+                       lpfc_sli4_fcf_record_match(phba, &phba->fcf.current_rec,
                    new_fcf_record, vlan_id)) {
                        if (bf_get(lpfc_fcf_record_fcf_index, new_fcf_record) ==
                            phba->fcf.current_rec.fcf_indx) {
@@ -2232,7 +2435,8 @@ read_next_fcf:
                            (phba->fcf.fcf_flag & FCF_REDISC_PEND))
                                return;
 
-                       if (phba->fcf.fcf_flag & FCF_IN_USE) {
+                       if (phba->cfg_fcf_failover_policy == LPFC_FCF_FOV &&
+                               phba->fcf.fcf_flag & FCF_IN_USE) {
                                /*
                                 * In case the current in-use FCF record no
                                 * longer existed during FCF discovery that
@@ -2247,7 +2451,6 @@ read_next_fcf:
                                spin_lock_irq(&phba->hbalock);
                                phba->fcf.fcf_flag |= FCF_REDISC_FOV;
                                spin_unlock_irq(&phba->hbalock);
-                               lpfc_sli4_mbox_cmd_free(phba, mboxq);
                                lpfc_sli4_fcf_scan_read_fcf_rec(phba,
                                                LPFC_FCOE_FCF_GET_FIRST);
                                return;
@@ -2424,7 +2627,8 @@ lpfc_mbx_cmpl_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 
        /* Update the eligible FCF record index bmask */
        fcf_index = bf_get(lpfc_fcf_record_fcf_index, new_fcf_record);
-       rc = lpfc_sli4_fcf_rr_index_set(phba, fcf_index);
+
+       rc = lpfc_sli4_fcf_pri_list_add(phba, fcf_index, new_fcf_record);
 
 out:
        lpfc_sli4_mbox_cmd_free(phba, mboxq);
@@ -2645,6 +2849,7 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        vport->vpi_state |= LPFC_VPI_REGISTERED;
        vport->fc_flag |= FC_VFI_REGISTERED;
        vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+       vport->fc_flag &= ~FC_VPORT_NEEDS_INIT_VPI;
        spin_unlock_irq(shost->host_lock);
 
        if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
@@ -2893,8 +3098,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
                        goto out;
                }
                /* Reset FCF roundrobin bmask for new discovery */
-               memset(phba->fcf.fcf_rr_bmask, 0,
-                      sizeof(*phba->fcf.fcf_rr_bmask));
+               lpfc_sli4_clear_fcf_rr_bmask(phba);
        }
 
        return;
@@ -5592,7 +5796,7 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba)
        spin_unlock_irq(&phba->hbalock);
 
        /* Reset FCF roundrobin bmask for new discovery */
-       memset(phba->fcf.fcf_rr_bmask, 0, sizeof(*phba->fcf.fcf_rr_bmask));
+       lpfc_sli4_clear_fcf_rr_bmask(phba);
 
        rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST);
 
index ab4c4d6..046edc4 100644 (file)
@@ -3470,11 +3470,16 @@ typedef struct {
    or CMD_IOCB_RCV_SEQ64_CX (0xB5) */
 
 struct rcv_sli3 {
-       uint32_t word8Rsvd;
 #ifdef __BIG_ENDIAN_BITFIELD
+       uint16_t ox_id;
+       uint16_t seq_cnt;
+
        uint16_t vpi;
        uint16_t word9Rsvd;
 #else  /*  __LITTLE_ENDIAN */
+       uint16_t seq_cnt;
+       uint16_t ox_id;
+
        uint16_t word9Rsvd;
        uint16_t vpi;
 #endif
index 11e26a2..7f8003b 100644 (file)
@@ -170,15 +170,8 @@ struct lpfc_sli_intf {
 #define LPFC_PCI_FUNC3         3
 #define LPFC_PCI_FUNC4         4
 
-/* SLI4 interface type-2 control register offsets */
-#define LPFC_CTL_PORT_SEM_OFFSET       0x400
-#define LPFC_CTL_PORT_STA_OFFSET       0x404
-#define LPFC_CTL_PORT_CTL_OFFSET       0x408
-#define LPFC_CTL_PORT_ER1_OFFSET       0x40C
-#define LPFC_CTL_PORT_ER2_OFFSET       0x410
+/* SLI4 interface type-2 PDEV_CTL register */
 #define LPFC_CTL_PDEV_CTL_OFFSET       0x414
-
-/* Some SLI4 interface type-2 PDEV_CTL register bits */
 #define LPFC_CTL_PDEV_CTL_DRST         0x00000001
 #define LPFC_CTL_PDEV_CTL_FRST         0x00000002
 #define LPFC_CTL_PDEV_CTL_DD           0x00000004
@@ -337,6 +330,7 @@ struct lpfc_cqe {
 #define CQE_CODE_RELEASE_WQE           0x2
 #define CQE_CODE_RECEIVE               0x4
 #define CQE_CODE_XRI_ABORTED           0x5
+#define CQE_CODE_RECEIVE_V1            0x9
 
 /* completion queue entry for wqe completions */
 struct lpfc_wcqe_complete {
@@ -440,7 +434,10 @@ struct lpfc_rcqe {
 #define FC_STATUS_RQ_BUF_LEN_EXCEEDED  0x11 /* payload truncated */
 #define FC_STATUS_INSUFF_BUF_NEED_BUF  0x12 /* Insufficient buffers */
 #define FC_STATUS_INSUFF_BUF_FRM_DISC  0x13 /* Frame Discard */
-       uint32_t reserved1;
+       uint32_t word1;
+#define lpfc_rcqe_fcf_id_v1_SHIFT      0
+#define lpfc_rcqe_fcf_id_v1_MASK       0x0000003F
+#define lpfc_rcqe_fcf_id_v1_WORD       word1
        uint32_t word2;
 #define lpfc_rcqe_length_SHIFT         16
 #define lpfc_rcqe_length_MASK          0x0000FFFF
@@ -451,6 +448,9 @@ struct lpfc_rcqe {
 #define lpfc_rcqe_fcf_id_SHIFT         0
 #define lpfc_rcqe_fcf_id_MASK          0x0000003F
 #define lpfc_rcqe_fcf_id_WORD          word2
+#define lpfc_rcqe_rq_id_v1_SHIFT       0
+#define lpfc_rcqe_rq_id_v1_MASK                0x0000FFFF
+#define lpfc_rcqe_rq_id_v1_WORD                word2
        uint32_t word3;
 #define lpfc_rcqe_valid_SHIFT          lpfc_cqe_valid_SHIFT
 #define lpfc_rcqe_valid_MASK           lpfc_cqe_valid_MASK
@@ -515,7 +515,7 @@ struct lpfc_register {
 /* The following BAR0 register sets are defined for if_type 0 and 2 UCNAs. */
 #define LPFC_SLI_INTF                  0x0058
 
-#define LPFC_SLIPORT_IF2_SMPHR         0x0400
+#define LPFC_CTL_PORT_SEM_OFFSET       0x400
 #define lpfc_port_smphr_perr_SHIFT     31
 #define lpfc_port_smphr_perr_MASK      0x1
 #define lpfc_port_smphr_perr_WORD      word0
@@ -575,7 +575,7 @@ struct lpfc_register {
 #define LPFC_POST_STAGE_PORT_READY                     0xC000
 #define LPFC_POST_STAGE_PORT_UE                        0xF000
 
-#define LPFC_SLIPORT_STATUS            0x0404
+#define LPFC_CTL_PORT_STA_OFFSET       0x404
 #define lpfc_sliport_status_err_SHIFT  31
 #define lpfc_sliport_status_err_MASK   0x1
 #define lpfc_sliport_status_err_WORD   word0
@@ -593,7 +593,7 @@ struct lpfc_register {
 #define lpfc_sliport_status_rdy_WORD   word0
 #define MAX_IF_TYPE_2_RESETS   1000
 
-#define LPFC_SLIPORT_CNTRL             0x0408
+#define LPFC_CTL_PORT_CTL_OFFSET       0x408
 #define lpfc_sliport_ctrl_end_SHIFT    30
 #define lpfc_sliport_ctrl_end_MASK     0x1
 #define lpfc_sliport_ctrl_end_WORD     word0
@@ -604,8 +604,8 @@ struct lpfc_register {
 #define lpfc_sliport_ctrl_ip_WORD      word0
 #define LPFC_SLIPORT_INIT_PORT 1
 
-#define LPFC_SLIPORT_ERR_1             0x040C
-#define LPFC_SLIPORT_ERR_2             0x0410
+#define LPFC_CTL_PORT_ER1_OFFSET       0x40C
+#define LPFC_CTL_PORT_ER2_OFFSET       0x410
 
 /* The following Registers apply to SLI4 if_type 0 UCNAs. They typically
  * reside in BAR 2.
@@ -3198,6 +3198,8 @@ struct lpfc_grp_hdr {
 #define lpfc_grp_hdr_id_MASK           0x000000FF
 #define lpfc_grp_hdr_id_WORD           word2
        uint8_t rev_name[128];
+       uint8_t date[12];
+       uint8_t revision[32];
 };
 
 #define FCP_COMMAND 0x0
index 148b98d..a3c8200 100644 (file)
@@ -2927,6 +2927,8 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
                                 sizeof fc_host_symbolic_name(shost));
 
        fc_host_supported_speeds(shost) = 0;
+       if (phba->lmt & LMT_16Gb)
+               fc_host_supported_speeds(shost) |= FC_PORTSPEED_16GBIT;
        if (phba->lmt & LMT_10Gb)
                fc_host_supported_speeds(shost) |= FC_PORTSPEED_10GBIT;
        if (phba->lmt & LMT_8Gb)
@@ -3632,8 +3634,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
                        lpfc_sli4_fcf_dead_failthrough(phba);
                } else {
                        /* Reset FCF roundrobin bmask for new discovery */
-                       memset(phba->fcf.fcf_rr_bmask, 0,
-                              sizeof(*phba->fcf.fcf_rr_bmask));
+                       lpfc_sli4_clear_fcf_rr_bmask(phba);
                        /*
                         * Handling fast FCF failover to a DEAD FCF event is
                         * considered equalivant to receiving CVL to all vports.
@@ -3647,7 +3648,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
                        " tag 0x%x\n", acqe_fip->index, acqe_fip->event_tag);
 
                vport = lpfc_find_vport_by_vpid(phba,
-                               acqe_fip->index - phba->vpi_base);
+                                               acqe_fip->index);
                ndlp = lpfc_sli4_perform_vport_cvl(vport);
                if (!ndlp)
                        break;
@@ -3719,8 +3720,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
                                 * Reset FCF roundrobin bmask for new
                                 * discovery.
                                 */
-                               memset(phba->fcf.fcf_rr_bmask, 0,
-                                      sizeof(*phba->fcf.fcf_rr_bmask));
+                               lpfc_sli4_clear_fcf_rr_bmask(phba);
                }
                break;
        default:
@@ -4034,6 +4034,34 @@ lpfc_reset_hba(struct lpfc_hba *phba)
        lpfc_unblock_mgmt_io(phba);
 }
 
+/**
+ * lpfc_sli_sriov_nr_virtfn_get - Get the number of sr-iov virtual functions
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This function enables the PCI SR-IOV virtual functions to a physical
+ * function. It invokes the PCI SR-IOV api with the @nr_vfn provided to
+ * enable the number of virtual functions to the physical function. As
+ * not all devices support SR-IOV, the return code from the pci_enable_sriov()
+ * API call does not considered as an error condition for most of the device.
+ **/
+uint16_t
+lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *phba)
+{
+       struct pci_dev *pdev = phba->pcidev;
+       uint16_t nr_virtfn;
+       int pos;
+
+       if (!pdev->is_physfn)
+               return 0;
+
+       pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
+       if (pos == 0)
+               return 0;
+
+       pci_read_config_word(pdev, pos + PCI_SRIOV_TOTAL_VF, &nr_virtfn);
+       return nr_virtfn;
+}
+
 /**
  * lpfc_sli_probe_sriov_nr_virtfn - Enable a number of sr-iov virtual functions
  * @phba: pointer to lpfc hba data structure.
@@ -4049,8 +4077,17 @@ int
 lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *phba, int nr_vfn)
 {
        struct pci_dev *pdev = phba->pcidev;
+       uint16_t max_nr_vfn;
        int rc;
 
+       max_nr_vfn = lpfc_sli_sriov_nr_virtfn_get(phba);
+       if (nr_vfn > max_nr_vfn) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3057 Requested vfs (%d) greater than "
+                               "supported vfs (%d)", nr_vfn, max_nr_vfn);
+               return -EINVAL;
+       }
+
        rc = pci_enable_sriov(pdev, nr_vfn);
        if (rc) {
                lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
@@ -4516,7 +4553,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                }
        }
 
-       return rc;
+       return 0;
 
 out_free_fcp_eq_hdl:
        kfree(phba->sli4_hba.fcp_eq_hdl);
@@ -4966,17 +5003,14 @@ out_free_mem:
  * @phba: pointer to lpfc hba data structure.
  *
  * This routine is invoked to post rpi header templates to the
- * HBA consistent with the SLI-4 interface spec.  This routine
+ * port for those SLI4 ports that do not support extents.  This routine
  * posts a PAGE_SIZE memory region to the port to hold up to
- * PAGE_SIZE modulo 64 rpi context headers.
- * No locks are held here because this is an initialization routine
- * called only from probe or lpfc_online when interrupts are not
- * enabled and the driver is reinitializing the device.
+ * PAGE_SIZE modulo 64 rpi context headers.  This is an initialization routine
+ * and should be called only when interrupts are disabled.
  *
  * Return codes
  *     0 - successful
- *     -ENOMEM - No available memory
- *      -EIO - The mailbox failed to complete successfully.
+ *     -ERROR - otherwise.
  **/
 int
 lpfc_sli4_init_rpi_hdrs(struct lpfc_hba *phba)
@@ -5687,17 +5721,22 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type)
                break;
        case LPFC_SLI_INTF_IF_TYPE_2:
                phba->sli4_hba.u.if_type2.ERR1regaddr =
-                       phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_ERR_1;
+                       phba->sli4_hba.conf_regs_memmap_p +
+                                               LPFC_CTL_PORT_ER1_OFFSET;
                phba->sli4_hba.u.if_type2.ERR2regaddr =
-                       phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_ERR_2;
+                       phba->sli4_hba.conf_regs_memmap_p +
+                                               LPFC_CTL_PORT_ER2_OFFSET;
                phba->sli4_hba.u.if_type2.CTRLregaddr =
-                       phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_CNTRL;
+                       phba->sli4_hba.conf_regs_memmap_p +
+                                               LPFC_CTL_PORT_CTL_OFFSET;
                phba->sli4_hba.u.if_type2.STATUSregaddr =
-                       phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_STATUS;
+                       phba->sli4_hba.conf_regs_memmap_p +
+                                               LPFC_CTL_PORT_STA_OFFSET;
                phba->sli4_hba.SLIINTFregaddr =
                        phba->sli4_hba.conf_regs_memmap_p + LPFC_SLI_INTF;
                phba->sli4_hba.PSMPHRregaddr =
-                    phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_IF2_SMPHR;
+                       phba->sli4_hba.conf_regs_memmap_p +
+                                               LPFC_CTL_PORT_SEM_OFFSET;
                phba->sli4_hba.RQDBregaddr =
                        phba->sli4_hba.conf_regs_memmap_p + LPFC_RQ_DOORBELL;
                phba->sli4_hba.WQDBregaddr =
@@ -8859,11 +8898,11 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
                return -EINVAL;
        }
        lpfc_decode_firmware_rev(phba, fwrev, 1);
-       if (strncmp(fwrev, image->rev_name, strnlen(fwrev, 16))) {
+       if (strncmp(fwrev, image->revision, strnlen(image->revision, 16))) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "3023 Updating Firmware. Current Version:%s "
                                "New Version:%s\n",
-                               fwrev, image->rev_name);
+                               fwrev, image->revision);
                for (i = 0; i < LPFC_MBX_WR_CONFIG_MAX_BDE; i++) {
                        dmabuf = kzalloc(sizeof(struct lpfc_dmabuf),
                                         GFP_KERNEL);
@@ -8892,9 +8931,9 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
                                               fw->size - offset);
                                        break;
                                }
-                               temp_offset += SLI4_PAGE_SIZE;
                                memcpy(dmabuf->virt, fw->data + temp_offset,
                                       SLI4_PAGE_SIZE);
+                               temp_offset += SLI4_PAGE_SIZE;
                        }
                        rc = lpfc_wr_object(phba, &dma_buffer_list,
                                    (fw->size - offset), &offset);
@@ -9005,6 +9044,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        }
 
        INIT_LIST_HEAD(&phba->active_rrq_list);
+       INIT_LIST_HEAD(&phba->fcf.fcf_pri_list);
 
        /* Set up common device driver resources */
        error = lpfc_setup_driver_resource_phase2(phba);
@@ -9112,7 +9152,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
 
        /* Check if there are static vports to be created. */
        lpfc_create_static_vport(phba);
-
        return 0;
 
 out_disable_intr:
@@ -9483,6 +9522,13 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)
        }
 
        pci_restore_state(pdev);
+
+       /*
+        * As the new kernel behavior of pci_restore_state() API call clears
+        * device saved_state flag, need to save the restored state again.
+        */
+       pci_save_state(pdev);
+
        if (pdev->is_busmaster)
                pci_set_master(pdev);
 
index 5567670..83450cc 100644 (file)
@@ -2031,7 +2031,7 @@ lpfc_init_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport)
        bf_set(lpfc_init_vfi_vp, init_vfi, 1);
        bf_set(lpfc_init_vfi_vfi, init_vfi,
               vport->phba->sli4_hba.vfi_ids[vport->vfi]);
-       bf_set(lpfc_init_vpi_vpi, init_vfi,
+       bf_set(lpfc_init_vfi_vpi, init_vfi,
               vport->phba->vpi_ids[vport->vpi]);
        bf_set(lpfc_init_vfi_fcfi, init_vfi,
               vport->phba->fcf.fcfi);
index 3ccc974..eadd241 100644 (file)
@@ -1302,13 +1302,13 @@ lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc,
                case SCSI_PROT_NORMAL:
                default:
                        lpfc_printf_log(phba, KERN_ERR, LOG_BG,
-                               "9063 BLKGRD: Bad op/guard:%d/%d combination\n",
-                                       scsi_get_prot_op(sc), guard_type);
+                               "9063 BLKGRD: Bad op/guard:%d/IP combination\n",
+                                       scsi_get_prot_op(sc));
                        ret = 1;
                        break;
 
                }
-       } else if (guard_type == SHOST_DIX_GUARD_CRC) {
+       } else {
                switch (scsi_get_prot_op(sc)) {
                case SCSI_PROT_READ_STRIP:
                case SCSI_PROT_WRITE_INSERT:
@@ -1324,17 +1324,18 @@ lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc,
 
                case SCSI_PROT_READ_INSERT:
                case SCSI_PROT_WRITE_STRIP:
+                       *txop = BG_OP_IN_CRC_OUT_NODIF;
+                       *rxop = BG_OP_IN_NODIF_OUT_CRC;
+                       break;
+
                case SCSI_PROT_NORMAL:
                default:
                        lpfc_printf_log(phba, KERN_ERR, LOG_BG,
-                               "9075 BLKGRD: Bad op/guard:%d/%d combination\n",
-                                       scsi_get_prot_op(sc), guard_type);
+                               "9075 BLKGRD: Bad op/guard:%d/CRC combination\n",
+                                       scsi_get_prot_op(sc));
                        ret = 1;
                        break;
                }
-       } else {
-               /* unsupported format */
-               BUG();
        }
 
        return ret;
@@ -1352,45 +1353,6 @@ lpfc_cmd_blksize(struct scsi_cmnd *sc)
        return sc->device->sector_size;
 }
 
-/**
- * lpfc_get_cmd_dif_parms - Extract DIF parameters from SCSI command
- * @sc:             in: SCSI command
- * @apptagmask:     out: app tag mask
- * @apptagval:      out: app tag value
- * @reftag:         out: ref tag (reference tag)
- *
- * Description:
- *   Extract DIF parameters from the command if possible.  Otherwise,
- *   use default parameters.
- *
- **/
-static inline void
-lpfc_get_cmd_dif_parms(struct scsi_cmnd *sc, uint16_t *apptagmask,
-               uint16_t *apptagval, uint32_t *reftag)
-{
-       struct  scsi_dif_tuple *spt;
-       unsigned char op = scsi_get_prot_op(sc);
-       unsigned int protcnt = scsi_prot_sg_count(sc);
-       static int cnt;
-
-       if (protcnt && (op == SCSI_PROT_WRITE_STRIP ||
-                               op == SCSI_PROT_WRITE_PASS)) {
-
-               cnt++;
-               spt = page_address(sg_page(scsi_prot_sglist(sc))) +
-                       scsi_prot_sglist(sc)[0].offset;
-               *apptagmask = 0;
-               *apptagval = 0;
-               *reftag = cpu_to_be32(spt->ref_tag);
-
-       } else {
-               /* SBC defines ref tag to be lower 32bits of LBA */
-               *reftag = (uint32_t) (0xffffffff & scsi_get_lba(sc));
-               *apptagmask = 0;
-               *apptagval = 0;
-       }
-}
-
 /*
  * This function sets up buffer list for protection groups of
  * type LPFC_PG_TYPE_NO_DIF
@@ -1427,9 +1389,8 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        dma_addr_t physaddr;
        int i = 0, num_bde = 0, status;
        int datadir = sc->sc_data_direction;
-       unsigned blksize;
        uint32_t reftag;
-       uint16_t apptagmask, apptagval;
+       unsigned blksize;
        uint8_t txop, rxop;
 
        status  = lpfc_sc_to_bg_opcodes(phba, sc, &txop, &rxop);
@@ -1438,17 +1399,16 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
 
        /* extract some info from the scsi command for pde*/
        blksize = lpfc_cmd_blksize(sc);
-       lpfc_get_cmd_dif_parms(sc, &apptagmask, &apptagval, &reftag);
+       reftag = scsi_get_lba(sc) & 0xffffffff;
 
        /* setup PDE5 with what we have */
        pde5 = (struct lpfc_pde5 *) bpl;
        memset(pde5, 0, sizeof(struct lpfc_pde5));
        bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR);
-       pde5->reftag = reftag;
 
        /* Endianness conversion if necessary for PDE5 */
        pde5->word0 = cpu_to_le32(pde5->word0);
-       pde5->reftag = cpu_to_le32(pde5->reftag);
+       pde5->reftag = cpu_to_le32(reftag);
 
        /* advance bpl and increment bde count */
        num_bde++;
@@ -1463,10 +1423,10 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        if (datadir == DMA_FROM_DEVICE) {
                bf_set(pde6_ce, pde6, 1);
                bf_set(pde6_re, pde6, 1);
-               bf_set(pde6_ae, pde6, 1);
        }
        bf_set(pde6_ai, pde6, 1);
-       bf_set(pde6_apptagval, pde6, apptagval);
+       bf_set(pde6_ae, pde6, 0);
+       bf_set(pde6_apptagval, pde6, 0);
 
        /* Endianness conversion if necessary for PDE6 */
        pde6->word0 = cpu_to_le32(pde6->word0);
@@ -1551,7 +1511,6 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        unsigned char pgdone = 0, alldone = 0;
        unsigned blksize;
        uint32_t reftag;
-       uint16_t apptagmask, apptagval;
        uint8_t txop, rxop;
        int num_bde = 0;
 
@@ -1571,7 +1530,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
 
        /* extract some info from the scsi command */
        blksize = lpfc_cmd_blksize(sc);
-       lpfc_get_cmd_dif_parms(sc, &apptagmask, &apptagval, &reftag);
+       reftag = scsi_get_lba(sc) & 0xffffffff;
 
        split_offset = 0;
        do {
@@ -1579,11 +1538,10 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
                pde5 = (struct lpfc_pde5 *) bpl;
                memset(pde5, 0, sizeof(struct lpfc_pde5));
                bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR);
-               pde5->reftag = reftag;
 
                /* Endianness conversion if necessary for PDE5 */
                pde5->word0 = cpu_to_le32(pde5->word0);
-               pde5->reftag = cpu_to_le32(pde5->reftag);
+               pde5->reftag = cpu_to_le32(reftag);
 
                /* advance bpl and increment bde count */
                num_bde++;
@@ -1597,9 +1555,9 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
                bf_set(pde6_oprx, pde6, rxop);
                bf_set(pde6_ce, pde6, 1);
                bf_set(pde6_re, pde6, 1);
-               bf_set(pde6_ae, pde6, 1);
                bf_set(pde6_ai, pde6, 1);
-               bf_set(pde6_apptagval, pde6, apptagval);
+               bf_set(pde6_ae, pde6, 0);
+               bf_set(pde6_apptagval, pde6, 0);
 
                /* Endianness conversion if necessary for PDE6 */
                pde6->word0 = cpu_to_le32(pde6->word0);
@@ -1621,8 +1579,8 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
                memset(pde7, 0, sizeof(struct lpfc_pde7));
                bf_set(pde7_type, pde7, LPFC_PDE7_DESCRIPTOR);
 
-               pde7->addrHigh = le32_to_cpu(putPaddrLow(protphysaddr));
-               pde7->addrLow = le32_to_cpu(putPaddrHigh(protphysaddr));
+               pde7->addrHigh = le32_to_cpu(putPaddrHigh(protphysaddr));
+               pde7->addrLow = le32_to_cpu(putPaddrLow(protphysaddr));
 
                protgrp_blks = protgroup_len / 8;
                protgrp_bytes = protgrp_blks * blksize;
@@ -1632,7 +1590,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
                        protgroup_remainder = 0x1000 - (pde7->addrLow & 0xfff);
                        protgroup_offset += protgroup_remainder;
                        protgrp_blks = protgroup_remainder / 8;
-                       protgrp_bytes = protgroup_remainder * blksize;
+                       protgrp_bytes = protgrp_blks * blksize;
                } else {
                        protgroup_offset = 0;
                        curr_prot++;
@@ -2006,16 +1964,21 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
        if (lpfc_bgs_get_hi_water_mark_present(bgstat)) {
                /*
                 * setup sense data descriptor 0 per SPC-4 as an information
-                * field, and put the failing LBA in it
+                * field, and put the failing LBA in it.
+                * This code assumes there was also a guard/app/ref tag error
+                * indication.
                 */
-               cmd->sense_buffer[8] = 0;     /* Information */
-               cmd->sense_buffer[9] = 0xa;   /* Add. length */
+               cmd->sense_buffer[7] = 0xc;   /* Additional sense length */
+               cmd->sense_buffer[8] = 0;     /* Information descriptor type */
+               cmd->sense_buffer[9] = 0xa;   /* Additional descriptor length */
+               cmd->sense_buffer[10] = 0x80; /* Validity bit */
                bghm /= cmd->device->sector_size;
 
                failing_sector = scsi_get_lba(cmd);
                failing_sector += bghm;
 
-               put_unaligned_be64(failing_sector, &cmd->sense_buffer[10]);
+               /* Descriptor Information */
+               put_unaligned_be64(failing_sector, &cmd->sense_buffer[12]);
        }
 
        if (!ret) {
index 98999bb..8b799f0 100644 (file)
@@ -560,7 +560,7 @@ __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
        rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL);
        if (rrq) {
                rrq->send_rrq = send_rrq;
-               rrq->xritag = phba->sli4_hba.xri_ids[xritag];
+               rrq->xritag = xritag;
                rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1);
                rrq->ndlp = ndlp;
                rrq->nlp_DID = ndlp->nlp_DID;
@@ -2452,7 +2452,8 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 
                /* search continue save q for same XRI */
                list_for_each_entry(iocbq, &pring->iocb_continue_saveq, clist) {
-                       if (iocbq->iocb.ulpContext == saveq->iocb.ulpContext) {
+                       if (iocbq->iocb.unsli3.rcvsli3.ox_id ==
+                               saveq->iocb.unsli3.rcvsli3.ox_id) {
                                list_add_tail(&saveq->list, &iocbq->list);
                                found = 1;
                                break;
@@ -3355,6 +3356,7 @@ lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba *phba,
                                                           irspiocbq);
                        break;
                case CQE_CODE_RECEIVE:
+               case CQE_CODE_RECEIVE_V1:
                        dmabuf = container_of(cq_event, struct hbq_dmabuf,
                                              cq_event);
                        lpfc_sli4_handle_received_buffer(phba, dmabuf);
@@ -4712,10 +4714,15 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba)
  * lpfc_sli4_get_avail_extnt_rsrc - Get available resource extent count.
  * @phba: Pointer to HBA context object.
  * @type: The resource extent type.
+ * @extnt_count: buffer to hold port available extent count.
+ * @extnt_size: buffer to hold element count per extent.
  *
- * This function allocates all SLI4 resource identifiers.
+ * This function calls the port and retrievs the number of available
+ * extents and their size for a particular extent type.
+ *
+ * Returns: 0 if successful.  Nonzero otherwise.
  **/
-static int
+int
 lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type,
                               uint16_t *extnt_count, uint16_t *extnt_size)
 {
@@ -4892,7 +4899,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
                                     req_len, *emb);
        if (alloc_len < req_len) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                       "9000 Allocated DMA memory size (x%x) is "
+                       "2982 Allocated DMA memory size (x%x) is "
                        "less than the requested DMA memory "
                        "size (x%x)\n", alloc_len, req_len);
                return -ENOMEM;
@@ -5505,6 +5512,154 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba)
        return 0;
 }
 
+/**
+ * lpfc_sli4_get_allocated_extnts - Get the port's allocated extents.
+ * @phba: Pointer to HBA context object.
+ * @type: The resource extent type.
+ * @extnt_count: buffer to hold port extent count response
+ * @extnt_size: buffer to hold port extent size response.
+ *
+ * This function calls the port to read the host allocated extents
+ * for a particular type.
+ **/
+int
+lpfc_sli4_get_allocated_extnts(struct lpfc_hba *phba, uint16_t type,
+                              uint16_t *extnt_cnt, uint16_t *extnt_size)
+{
+       bool emb;
+       int rc = 0;
+       uint16_t curr_blks = 0;
+       uint32_t req_len, emb_len;
+       uint32_t alloc_len, mbox_tmo;
+       struct list_head *blk_list_head;
+       struct lpfc_rsrc_blks *rsrc_blk;
+       LPFC_MBOXQ_t *mbox;
+       void *virtaddr = NULL;
+       struct lpfc_mbx_nembed_rsrc_extent *n_rsrc;
+       struct lpfc_mbx_alloc_rsrc_extents *rsrc_ext;
+       union  lpfc_sli4_cfg_shdr *shdr;
+
+       switch (type) {
+       case LPFC_RSC_TYPE_FCOE_VPI:
+               blk_list_head = &phba->lpfc_vpi_blk_list;
+               break;
+       case LPFC_RSC_TYPE_FCOE_XRI:
+               blk_list_head = &phba->sli4_hba.lpfc_xri_blk_list;
+               break;
+       case LPFC_RSC_TYPE_FCOE_VFI:
+               blk_list_head = &phba->sli4_hba.lpfc_vfi_blk_list;
+               break;
+       case LPFC_RSC_TYPE_FCOE_RPI:
+               blk_list_head = &phba->sli4_hba.lpfc_rpi_blk_list;
+               break;
+       default:
+               return -EIO;
+       }
+
+       /* Count the number of extents currently allocatd for this type. */
+       list_for_each_entry(rsrc_blk, blk_list_head, list) {
+               if (curr_blks == 0) {
+                       /*
+                        * The GET_ALLOCATED mailbox does not return the size,
+                        * just the count.  The size should be just the size
+                        * stored in the current allocated block and all sizes
+                        * for an extent type are the same so set the return
+                        * value now.
+                        */
+                       *extnt_size = rsrc_blk->rsrc_size;
+               }
+               curr_blks++;
+       }
+
+       /* Calculate the total requested length of the dma memory. */
+       req_len = curr_blks * sizeof(uint16_t);
+
+       /*
+        * Calculate the size of an embedded mailbox.  The uint32_t
+        * accounts for extents-specific word.
+        */
+       emb_len = sizeof(MAILBOX_t) - sizeof(struct mbox_header) -
+               sizeof(uint32_t);
+
+       /*
+        * Presume the allocation and response will fit into an embedded
+        * mailbox.  If not true, reconfigure to a non-embedded mailbox.
+        */
+       emb = LPFC_SLI4_MBX_EMBED;
+       req_len = emb_len;
+       if (req_len > emb_len) {
+               req_len = curr_blks * sizeof(uint16_t) +
+                       sizeof(union lpfc_sli4_cfg_shdr) +
+                       sizeof(uint32_t);
+               emb = LPFC_SLI4_MBX_NEMBED;
+       }
+
+       mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!mbox)
+               return -ENOMEM;
+       memset(mbox, 0, sizeof(LPFC_MBOXQ_t));
+
+       alloc_len = lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
+                                    LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT,
+                                    req_len, emb);
+       if (alloc_len < req_len) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "2983 Allocated DMA memory size (x%x) is "
+                       "less than the requested DMA memory "
+                       "size (x%x)\n", alloc_len, req_len);
+               rc = -ENOMEM;
+               goto err_exit;
+       }
+       rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, curr_blks, type, emb);
+       if (unlikely(rc)) {
+               rc = -EIO;
+               goto err_exit;
+       }
+
+       if (!phba->sli4_hba.intr_enable)
+               rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
+       else {
+               mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+               rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
+       }
+
+       if (unlikely(rc)) {
+               rc = -EIO;
+               goto err_exit;
+       }
+
+       /*
+        * Figure out where the response is located.  Then get local pointers
+        * to the response data.  The port does not guarantee to respond to
+        * all extents counts request so update the local variable with the
+        * allocated count from the port.
+        */
+       if (emb == LPFC_SLI4_MBX_EMBED) {
+               rsrc_ext = &mbox->u.mqe.un.alloc_rsrc_extents;
+               shdr = &rsrc_ext->header.cfg_shdr;
+               *extnt_cnt = bf_get(lpfc_mbx_rsrc_cnt, &rsrc_ext->u.rsp);
+       } else {
+               virtaddr = mbox->sge_array->addr[0];
+               n_rsrc = (struct lpfc_mbx_nembed_rsrc_extent *) virtaddr;
+               shdr = &n_rsrc->cfg_shdr;
+               *extnt_cnt = bf_get(lpfc_mbx_rsrc_cnt, n_rsrc);
+       }
+
+       if (bf_get(lpfc_mbox_hdr_status, &shdr->response)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT,
+                       "2984 Failed to read allocated resources "
+                       "for type %d - Status 0x%x Add'l Status 0x%x.\n",
+                       type,
+                       bf_get(lpfc_mbox_hdr_status, &shdr->response),
+                       bf_get(lpfc_mbox_hdr_add_status, &shdr->response));
+               rc = -EIO;
+               goto err_exit;
+       }
+ err_exit:
+       lpfc_sli4_mbox_cmd_free(phba, mbox);
+       return rc;
+}
+
 /**
  * lpfc_sli4_hba_setup - SLI4 device intialization PCI function
  * @phba: Pointer to HBA context object.
@@ -5837,6 +5992,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
                                        "Advanced Error Reporting (AER)\n");
                        phba->cfg_aer_support = 0;
                }
+               rc = 0;
        }
 
        if (!(phba->hba_flag & HBA_FCOE_MODE)) {
@@ -6634,6 +6790,9 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
        unsigned long iflags;
        int rc;
 
+       /* dump from issue mailbox command if setup */
+       lpfc_idiag_mbxacc_dump_issue_mbox(phba, &mboxq->u.mb);
+
        rc = lpfc_mbox_dev_check(phba);
        if (unlikely(rc)) {
                lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
@@ -7318,12 +7477,12 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                bf_set(wqe_qosd, &wqe->els_req.wqe_com, 1);
                bf_set(wqe_lenloc, &wqe->els_req.wqe_com, LPFC_WQE_LENLOC_NONE);
                bf_set(wqe_ebde_cnt, &wqe->els_req.wqe_com, 0);
-       break;
+               break;
        case CMD_XMIT_SEQUENCE64_CX:
                bf_set(wqe_ctxt_tag, &wqe->xmit_sequence.wqe_com,
                       iocbq->iocb.un.ulpWord[3]);
                bf_set(wqe_rcvoxid, &wqe->xmit_sequence.wqe_com,
-                      iocbq->iocb.ulpContext);
+                      iocbq->iocb.unsli3.rcvsli3.ox_id);
                /* The entire sequence is transmitted for this IOCB */
                xmit_len = total_len;
                cmnd = CMD_XMIT_SEQUENCE64_CR;
@@ -7341,7 +7500,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                bf_set(wqe_ebde_cnt, &wqe->xmit_sequence.wqe_com, 0);
                wqe->xmit_sequence.xmit_len = xmit_len;
                command_type = OTHER_COMMAND;
-       break;
+               break;
        case CMD_XMIT_BCAST64_CN:
                /* word3 iocb=iotag32 wqe=seq_payload_len */
                wqe->xmit_bcast64.seq_payload_len = xmit_len;
@@ -7355,7 +7514,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                bf_set(wqe_lenloc, &wqe->xmit_bcast64.wqe_com,
                       LPFC_WQE_LENLOC_WORD3);
                bf_set(wqe_ebde_cnt, &wqe->xmit_bcast64.wqe_com, 0);
-       break;
+               break;
        case CMD_FCP_IWRITE64_CR:
                command_type = FCP_COMMAND_DATA_OUT;
                /* word3 iocb=iotag wqe=payload_offset_len */
@@ -7375,7 +7534,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                       LPFC_WQE_LENLOC_WORD4);
                bf_set(wqe_ebde_cnt, &wqe->fcp_iwrite.wqe_com, 0);
                bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpPU);
-       break;
+               break;
        case CMD_FCP_IREAD64_CR:
                /* word3 iocb=iotag wqe=payload_offset_len */
                /* Add the FCP_CMD and FCP_RSP sizes to get the offset */
@@ -7394,7 +7553,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                       LPFC_WQE_LENLOC_WORD4);
                bf_set(wqe_ebde_cnt, &wqe->fcp_iread.wqe_com, 0);
                bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpPU);
-       break;
+               break;
        case CMD_FCP_ICMND64_CR:
                /* word3 iocb=IO_TAG wqe=reserved */
                wqe->fcp_icmd.rsrvd3 = 0;
@@ -7407,7 +7566,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com,
                       LPFC_WQE_LENLOC_NONE);
                bf_set(wqe_ebde_cnt, &wqe->fcp_icmd.wqe_com, 0);
-       break;
+               break;
        case CMD_GEN_REQUEST64_CR:
                /* For this command calculate the xmit length of the
                 * request bde.
@@ -7442,7 +7601,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                bf_set(wqe_lenloc, &wqe->gen_req.wqe_com, LPFC_WQE_LENLOC_NONE);
                bf_set(wqe_ebde_cnt, &wqe->gen_req.wqe_com, 0);
                command_type = OTHER_COMMAND;
-       break;
+               break;
        case CMD_XMIT_ELS_RSP64_CX:
                ndlp = (struct lpfc_nodelist *)iocbq->context1;
                /* words0-2 BDE memcpy */
@@ -7457,7 +7616,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                       ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l));
                bf_set(wqe_pu, &wqe->xmit_els_rsp.wqe_com, iocbq->iocb.ulpPU);
                bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com,
-                      iocbq->iocb.ulpContext);
+                      iocbq->iocb.unsli3.rcvsli3.ox_id);
                if (!iocbq->iocb.ulpCt_h && iocbq->iocb.ulpCt_l)
                        bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com,
                               phba->vpi_ids[iocbq->vport->vpi]);
@@ -7470,7 +7629,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp,
                       phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
                command_type = OTHER_COMMAND;
-       break;
+               break;
        case CMD_CLOSE_XRI_CN:
        case CMD_ABORT_XRI_CN:
        case CMD_ABORT_XRI_CX:
@@ -7509,7 +7668,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                cmnd = CMD_ABORT_XRI_CX;
                command_type = OTHER_COMMAND;
                xritag = 0;
-       break;
+               break;
        case CMD_XMIT_BLS_RSP64_CX:
                /* As BLS ABTS RSP WQE is very different from other WQEs,
                 * we re-construct this WQE here based on information in
@@ -7553,7 +7712,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                               bf_get(lpfc_rsn_code, &iocbq->iocb.un.bls_rsp));
                }
 
-       break;
+               break;
        case CMD_XRI_ABORTED_CX:
        case CMD_CREATE_XRI_CR: /* Do we expect to use this? */
        case CMD_IOCB_FCP_IBIDIR64_CR: /* bidirectional xfer */
@@ -7565,7 +7724,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                                "2014 Invalid command 0x%x\n",
                                iocbq->iocb.ulpCommand);
                return IOCB_ERROR;
-       break;
+               break;
        }
 
        bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag);
@@ -10481,10 +10640,14 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
        struct lpfc_queue *hrq = phba->sli4_hba.hdr_rq;
        struct lpfc_queue *drq = phba->sli4_hba.dat_rq;
        struct hbq_dmabuf *dma_buf;
-       uint32_t status;
+       uint32_t status, rq_id;
        unsigned long iflags;
 
-       if (bf_get(lpfc_rcqe_rq_id, rcqe) != hrq->queue_id)
+       if (bf_get(lpfc_cqe_code, rcqe) == CQE_CODE_RECEIVE_V1)
+               rq_id = bf_get(lpfc_rcqe_rq_id_v1, rcqe);
+       else
+               rq_id = bf_get(lpfc_rcqe_rq_id, rcqe);
+       if (rq_id != hrq->queue_id)
                goto out;
 
        status = bf_get(lpfc_rcqe_status, rcqe);
@@ -10563,6 +10726,7 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
                                (struct sli4_wcqe_xri_aborted *)&cqevt);
                break;
        case CQE_CODE_RECEIVE:
+       case CQE_CODE_RECEIVE_V1:
                /* Process the RQ event */
                phba->last_completion_time = jiffies;
                workposted = lpfc_sli4_sp_handle_rcqe(phba,
@@ -12345,19 +12509,18 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba,
 }
 
 /**
- * lpfc_sli4_init_rpi_hdrs - Post the rpi header memory region to the port
+ * lpfc_sli4_alloc_xri - Get an available rpi in the device's range
  * @phba: pointer to lpfc hba data structure.
  *
  * This routine is invoked to post rpi header templates to the
- * port for those SLI4 ports that do not support extents.  This routine
- * posts a PAGE_SIZE memory region to the port to hold up to
- * PAGE_SIZE modulo 64 rpi context headers.  This is an initialization routine
- * and should be called only when interrupts are disabled.
+ * HBA consistent with the SLI-4 interface spec.  This routine
+ * posts a SLI4_PAGE_SIZE memory region to the port to hold up to
+ * SLI4_PAGE_SIZE modulo 64 rpi context headers.
  *
- * Return codes
- *     0 - successful
- *     -ERROR - otherwise.
- */
+ * Returns
+ *     A nonzero rpi defined as rpi_base <= rpi < max_rpi if successful
+ *     LPFC_RPI_ALLOC_ERROR if no rpis are available.
+ **/
 uint16_t
 lpfc_sli4_alloc_xri(struct lpfc_hba *phba)
 {
@@ -13406,7 +13569,7 @@ lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba,
  * This function validates the xri maps to the known range of XRIs allocated an
  * used by the driver.
  **/
-static uint16_t
+uint16_t
 lpfc_sli4_xri_inrange(struct lpfc_hba *phba,
                      uint16_t xri)
 {
@@ -13643,10 +13806,12 @@ lpfc_seq_complete(struct hbq_dmabuf *dmabuf)
 static struct lpfc_iocbq *
 lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
 {
+       struct hbq_dmabuf *hbq_buf;
        struct lpfc_dmabuf *d_buf, *n_buf;
        struct lpfc_iocbq *first_iocbq, *iocbq;
        struct fc_frame_header *fc_hdr;
        uint32_t sid;
+       uint32_t len, tot_len;
        struct ulp_bde64 *pbde;
 
        fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
@@ -13655,6 +13820,7 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
        lpfc_update_rcv_time_stamp(vport);
        /* get the Remote Port's SID */
        sid = sli4_sid_from_fc_hdr(fc_hdr);
+       tot_len = 0;
        /* Get an iocbq struct to fill in. */
        first_iocbq = lpfc_sli_get_iocbq(vport->phba);
        if (first_iocbq) {
@@ -13662,9 +13828,12 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
                first_iocbq->iocb.unsli3.rcvsli3.acc_len = 0;
                first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS;
                first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX;
-               first_iocbq->iocb.ulpContext = be16_to_cpu(fc_hdr->fh_ox_id);
-               /* iocbq is prepped for internal consumption.  Logical vpi. */
-               first_iocbq->iocb.unsli3.rcvsli3.vpi = vport->vpi;
+               first_iocbq->iocb.ulpContext = NO_XRI;
+               first_iocbq->iocb.unsli3.rcvsli3.ox_id =
+                       be16_to_cpu(fc_hdr->fh_ox_id);
+               /* iocbq is prepped for internal consumption.  Physical vpi. */
+               first_iocbq->iocb.unsli3.rcvsli3.vpi =
+                       vport->phba->vpi_ids[vport->vpi];
                /* put the first buffer into the first IOCBq */
                first_iocbq->context2 = &seq_dmabuf->dbuf;
                first_iocbq->context3 = NULL;
@@ -13672,9 +13841,9 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
                first_iocbq->iocb.un.cont64[0].tus.f.bdeSize =
                                                        LPFC_DATA_BUF_SIZE;
                first_iocbq->iocb.un.rcvels.remoteID = sid;
-               first_iocbq->iocb.unsli3.rcvsli3.acc_len +=
-                               bf_get(lpfc_rcqe_length,
+               tot_len = bf_get(lpfc_rcqe_length,
                                       &seq_dmabuf->cq_event.cqe.rcqe_cmpl);
+               first_iocbq->iocb.unsli3.rcvsli3.acc_len = tot_len;
        }
        iocbq = first_iocbq;
        /*
@@ -13692,9 +13861,13 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
                        pbde = (struct ulp_bde64 *)
                                        &iocbq->iocb.unsli3.sli3Words[4];
                        pbde->tus.f.bdeSize = LPFC_DATA_BUF_SIZE;
-                       first_iocbq->iocb.unsli3.rcvsli3.acc_len +=
-                               bf_get(lpfc_rcqe_length,
-                                      &seq_dmabuf->cq_event.cqe.rcqe_cmpl);
+
+                       /* We need to get the size out of the right CQE */
+                       hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
+                       len = bf_get(lpfc_rcqe_length,
+                                      &hbq_buf->cq_event.cqe.rcqe_cmpl);
+                       iocbq->iocb.unsli3.rcvsli3.acc_len += len;
+                       tot_len += len;
                } else {
                        iocbq = lpfc_sli_get_iocbq(vport->phba);
                        if (!iocbq) {
@@ -13712,9 +13885,14 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
                        iocbq->iocb.ulpBdeCount = 1;
                        iocbq->iocb.un.cont64[0].tus.f.bdeSize =
                                                        LPFC_DATA_BUF_SIZE;
-                       first_iocbq->iocb.unsli3.rcvsli3.acc_len +=
-                               bf_get(lpfc_rcqe_length,
-                                      &seq_dmabuf->cq_event.cqe.rcqe_cmpl);
+
+                       /* We need to get the size out of the right CQE */
+                       hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
+                       len = bf_get(lpfc_rcqe_length,
+                                      &hbq_buf->cq_event.cqe.rcqe_cmpl);
+                       tot_len += len;
+                       iocbq->iocb.unsli3.rcvsli3.acc_len = tot_len;
+
                        iocbq->iocb.un.rcvels.remoteID = sid;
                        list_add_tail(&iocbq->list, &first_iocbq->list);
                }
@@ -13787,7 +13965,13 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
                lpfc_in_buf_free(phba, &dmabuf->dbuf);
                return;
        }
-       fcfi = bf_get(lpfc_rcqe_fcf_id, &dmabuf->cq_event.cqe.rcqe_cmpl);
+       if ((bf_get(lpfc_cqe_code,
+                   &dmabuf->cq_event.cqe.rcqe_cmpl) == CQE_CODE_RECEIVE_V1))
+               fcfi = bf_get(lpfc_rcqe_fcf_id_v1,
+                             &dmabuf->cq_event.cqe.rcqe_cmpl);
+       else
+               fcfi = bf_get(lpfc_rcqe_fcf_id,
+                             &dmabuf->cq_event.cqe.rcqe_cmpl);
        vport = lpfc_fc_frame_to_vport(phba, fc_hdr, fcfi);
        if (!vport || !(vport->vpi_state & LPFC_VPI_REGISTERED)) {
                /* throw out the frame */
@@ -14450,6 +14634,92 @@ fail_fcf_read:
        return error;
 }
 
+/**
+ * lpfc_check_next_fcf_pri
+ * phba pointer to the lpfc_hba struct for this port.
+ * This routine is called from the lpfc_sli4_fcf_rr_next_index_get
+ * routine when the rr_bmask is empty. The FCF indecies are put into the
+ * rr_bmask based on their priority level. Starting from the highest priority
+ * to the lowest. The most likely FCF candidate will be in the highest
+ * priority group. When this routine is called it searches the fcf_pri list for
+ * next lowest priority group and repopulates the rr_bmask with only those
+ * fcf_indexes.
+ * returns:
+ * 1=success 0=failure
+ **/
+int
+lpfc_check_next_fcf_pri_level(struct lpfc_hba *phba)
+{
+       uint16_t next_fcf_pri;
+       uint16_t last_index;
+       struct lpfc_fcf_pri *fcf_pri;
+       int rc;
+       int ret = 0;
+
+       last_index = find_first_bit(phba->fcf.fcf_rr_bmask,
+                       LPFC_SLI4_FCF_TBL_INDX_MAX);
+       lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+                       "3060 Last IDX %d\n", last_index);
+       if (list_empty(&phba->fcf.fcf_pri_list)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
+                       "3061 Last IDX %d\n", last_index);
+               return 0; /* Empty rr list */
+       }
+       next_fcf_pri = 0;
+       /*
+        * Clear the rr_bmask and set all of the bits that are at this
+        * priority.
+        */
+       memset(phba->fcf.fcf_rr_bmask, 0,
+                       sizeof(*phba->fcf.fcf_rr_bmask));
+       spin_lock_irq(&phba->hbalock);
+       list_for_each_entry(fcf_pri, &phba->fcf.fcf_pri_list, list) {
+               if (fcf_pri->fcf_rec.flag & LPFC_FCF_FLOGI_FAILED)
+                       continue;
+               /*
+                * the 1st priority that has not FLOGI failed
+                * will be the highest.
+                */
+               if (!next_fcf_pri)
+                       next_fcf_pri = fcf_pri->fcf_rec.priority;
+               spin_unlock_irq(&phba->hbalock);
+               if (fcf_pri->fcf_rec.priority == next_fcf_pri) {
+                       rc = lpfc_sli4_fcf_rr_index_set(phba,
+                                               fcf_pri->fcf_rec.fcf_index);
+                       if (rc)
+                               return 0;
+               }
+               spin_lock_irq(&phba->hbalock);
+       }
+       /*
+        * if next_fcf_pri was not set above and the list is not empty then
+        * we have failed flogis on all of them. So reset flogi failed
+        * and start at the begining.
+        */
+       if (!next_fcf_pri && !list_empty(&phba->fcf.fcf_pri_list)) {
+               list_for_each_entry(fcf_pri, &phba->fcf.fcf_pri_list, list) {
+                       fcf_pri->fcf_rec.flag &= ~LPFC_FCF_FLOGI_FAILED;
+                       /*
+                        * the 1st priority that has not FLOGI failed
+                        * will be the highest.
+                        */
+                       if (!next_fcf_pri)
+                               next_fcf_pri = fcf_pri->fcf_rec.priority;
+                       spin_unlock_irq(&phba->hbalock);
+                       if (fcf_pri->fcf_rec.priority == next_fcf_pri) {
+                               rc = lpfc_sli4_fcf_rr_index_set(phba,
+                                               fcf_pri->fcf_rec.fcf_index);
+                               if (rc)
+                                       return 0;
+                       }
+                       spin_lock_irq(&phba->hbalock);
+               }
+       } else
+               ret = 1;
+       spin_unlock_irq(&phba->hbalock);
+
+       return ret;
+}
 /**
  * lpfc_sli4_fcf_rr_next_index_get - Get next eligible fcf record index
  * @phba: pointer to lpfc hba data structure.
@@ -14466,6 +14736,7 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba)
        uint16_t next_fcf_index;
 
        /* Search start from next bit of currently registered FCF index */
+next_priority:
        next_fcf_index = (phba->fcf.current_rec.fcf_indx + 1) %
                                        LPFC_SLI4_FCF_TBL_INDX_MAX;
        next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask,
@@ -14473,17 +14744,46 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba)
                                       next_fcf_index);
 
        /* Wrap around condition on phba->fcf.fcf_rr_bmask */
-       if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX)
+       if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
+               /*
+                * If we have wrapped then we need to clear the bits that
+                * have been tested so that we can detect when we should
+                * change the priority level.
+                */
                next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask,
                                               LPFC_SLI4_FCF_TBL_INDX_MAX, 0);
+       }
+
 
        /* Check roundrobin failover list empty condition */
-       if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
+       if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX ||
+               next_fcf_index == phba->fcf.current_rec.fcf_indx) {
+               /*
+                * If next fcf index is not found check if there are lower
+                * Priority level fcf's in the fcf_priority list.
+                * Set up the rr_bmask with all of the avaiable fcf bits
+                * at that level and continue the selection process.
+                */
+               if (lpfc_check_next_fcf_pri_level(phba))
+                       goto next_priority;
                lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
                                "2844 No roundrobin failover FCF available\n");
-               return LPFC_FCOE_FCF_NEXT_NONE;
+               if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX)
+                       return LPFC_FCOE_FCF_NEXT_NONE;
+               else {
+                       lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
+                               "3063 Only FCF available idx %d, flag %x\n",
+                               next_fcf_index,
+                       phba->fcf.fcf_pri[next_fcf_index].fcf_rec.flag);
+                       return next_fcf_index;
+               }
        }
 
+       if (next_fcf_index < LPFC_SLI4_FCF_TBL_INDX_MAX &&
+               phba->fcf.fcf_pri[next_fcf_index].fcf_rec.flag &
+               LPFC_FCF_FLOGI_FAILED)
+               goto next_priority;
+
        lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
                        "2845 Get next roundrobin failover FCF (x%x)\n",
                        next_fcf_index);
@@ -14535,6 +14835,7 @@ lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *phba, uint16_t fcf_index)
 void
 lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index)
 {
+       struct lpfc_fcf_pri *fcf_pri;
        if (fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
                lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
                                "2762 FCF (x%x) reached driver's book "
@@ -14543,6 +14844,14 @@ lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index)
                return;
        }
        /* Clear the eligible FCF record index bmask */
+       spin_lock_irq(&phba->hbalock);
+       list_for_each_entry(fcf_pri, &phba->fcf.fcf_pri_list, list) {
+               if (fcf_pri->fcf_rec.fcf_index == fcf_index) {
+                       list_del_init(&fcf_pri->list);
+                       break;
+               }
+       }
+       spin_unlock_irq(&phba->hbalock);
        clear_bit(fcf_index, phba->fcf.fcf_rr_bmask);
 
        lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
index 4b17035..19bb87a 100644 (file)
@@ -81,6 +81,8 @@
         (fc_hdr)->fh_f_ctl[1] <<  8 | \
         (fc_hdr)->fh_f_ctl[2])
 
+#define LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT 12000
+
 enum lpfc_sli4_queue_type {
        LPFC_EQ,
        LPFC_GCQ,
@@ -157,6 +159,25 @@ struct lpfc_fcf_rec {
 #define RECORD_VALID   0x02
 };
 
+struct lpfc_fcf_pri_rec {
+       uint16_t fcf_index;
+#define LPFC_FCF_ON_PRI_LIST 0x0001
+#define LPFC_FCF_FLOGI_FAILED 0x0002
+       uint16_t flag;
+       uint32_t priority;
+};
+
+struct lpfc_fcf_pri {
+       struct list_head list;
+       struct lpfc_fcf_pri_rec fcf_rec;
+};
+
+/*
+ * Maximum FCF table index, it is for driver internal book keeping, it
+ * just needs to be no less than the supported HBA's FCF table size.
+ */
+#define LPFC_SLI4_FCF_TBL_INDX_MAX     32
+
 struct lpfc_fcf {
        uint16_t fcfi;
        uint32_t fcf_flag;
@@ -176,15 +197,13 @@ struct lpfc_fcf {
        uint32_t eligible_fcf_cnt;
        struct lpfc_fcf_rec current_rec;
        struct lpfc_fcf_rec failover_rec;
+       struct list_head fcf_pri_list;
+       struct lpfc_fcf_pri fcf_pri[LPFC_SLI4_FCF_TBL_INDX_MAX];
+       uint32_t current_fcf_scan_pri;
        struct timer_list redisc_wait;
        unsigned long *fcf_rr_bmask; /* Eligible FCF indexes for RR failover */
 };
 
-/*
- * Maximum FCF table index, it is for driver internal book keeping, it
- * just needs to be no less than the supported HBA's FCF table size.
- */
-#define LPFC_SLI4_FCF_TBL_INDX_MAX     32
 
 #define LPFC_REGION23_SIGNATURE "RG23"
 #define LPFC_REGION23_VERSION  1
index c03921b..c1e0ae9 100644 (file)
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.3.23"
+#define LPFC_DRIVER_VERSION "8.3.25"
 #define LPFC_DRIVER_NAME               "lpfc"
 #define LPFC_SP_DRIVER_HANDLER_NAME    "lpfc:sp"
 #define LPFC_FP_DRIVER_HANDLER_NAME    "lpfc:fp"
index 7370c08..3948a00 100644 (file)
@@ -33,9 +33,9 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION                                "00.00.05.38-rc1"
-#define MEGASAS_RELDATE                                "May. 11, 2011"
-#define MEGASAS_EXT_VERSION                    "Wed. May. 11 17:00:00 PDT 2011"
+#define MEGASAS_VERSION                                "00.00.05.40-rc1"
+#define MEGASAS_RELDATE                                "Jul. 26, 2011"
+#define MEGASAS_EXT_VERSION                    "Tue. Jul. 26 17:00:00 PDT 2011"
 
 /*
  * Device IDs
index 2d8cdce..776d019 100644 (file)
@@ -18,7 +18,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  *  FILE: megaraid_sas_base.c
- *  Version : v00.00.05.38-rc1
+ *  Version : v00.00.05.40-rc1
  *
  *  Authors: LSI Corporation
  *           Sreenivas Bagalkote
@@ -54,6 +54,7 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
 #include "megaraid_sas_fusion.h"
 #include "megaraid_sas.h"
 
@@ -2057,6 +2058,20 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
        }
 }
 
+static int megasas_change_queue_depth(struct scsi_device *sdev,
+                                     int queue_depth, int reason)
+{
+       if (reason != SCSI_QDEPTH_DEFAULT)
+               return -EOPNOTSUPP;
+
+       if (queue_depth > sdev->host->can_queue)
+               queue_depth = sdev->host->can_queue;
+       scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev),
+                               queue_depth);
+
+       return queue_depth;
+}
+
 /*
  * Scsi host template for megaraid_sas driver
  */
@@ -2074,6 +2089,7 @@ static struct scsi_host_template megasas_template = {
        .eh_timed_out = megasas_reset_timer,
        .bios_param = megasas_bios_param,
        .use_clustering = ENABLE_CLUSTERING,
+       .change_queue_depth = megasas_change_queue_depth,
 };
 
 /**
index 8fe3a45..5a5af1f 100644 (file)
@@ -288,7 +288,6 @@ u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock,
                                /* Get dev handle from Pd */
                                *pDevHandle = MR_PdDevHandleGet(pd, map);
                }
-               retval = FALSE;
        }
 
        *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk;
index 939f283..6abd2fc 100644 (file)
@@ -4258,6 +4258,7 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
        u32 log_info;
        struct MPT2SAS_DEVICE *sas_device_priv_data;
        u32 response_code = 0;
+       unsigned long flags;
 
        mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
        scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
@@ -4282,6 +4283,9 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
         * the failed direct I/O should be redirected to volume
         */
        if (_scsih_scsi_direct_io_get(ioc, smid)) {
+               spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+               ioc->scsi_lookup[smid - 1].scmd = scmd;
+               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
                _scsih_scsi_direct_io_set(ioc, smid, 0);
                memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
                mpi_request->DevHandle =
index c82b012..78f7e20 100644 (file)
@@ -3,7 +3,7 @@
 #
 # Copyright 2007 Red Hat, Inc.
 # Copyright 2008 Marvell. <kewei@marvell.com>
-# Copyright 2009-20011 Marvell. <yuxiangl@marvell.com>
+# Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
 #
 # This file is licensed under GPLv2.
 #
@@ -41,3 +41,10 @@ config SCSI_MVSAS_DEBUG
        help
                Compiles the 88SE64XX/88SE94XX driver in debug mode.  In debug mode,
                the driver prints some messages to the console.
+config SCSI_MVSAS_TASKLET
+       bool "Support for interrupt tasklet"
+       default n
+       depends on SCSI_MVSAS
+       help
+               Compiles the 88SE64xx/88SE94xx driver in interrupt tasklet mode.In this mode,
+               the interrupt will schedule a tasklet.
index 13c9604..8ba4722 100644 (file)
@@ -33,7 +33,6 @@ static void mvs_64xx_detect_porttype(struct mvs_info *mvi, int i)
        u32 reg;
        struct mvs_phy *phy = &mvi->phy[i];
 
-       /* TODO check & save device type */
        reg = mr32(MVS_GBL_PORT_TYPE);
        phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
        if (reg & MODE_SAS_SATA & (1 << i))
@@ -48,7 +47,7 @@ static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
        u32 tmp;
 
        tmp = mr32(MVS_PCS);
-       if (mvi->chip->n_phy <= 4)
+       if (mvi->chip->n_phy <= MVS_SOC_PORTS)
                tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT);
        else
                tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT2);
@@ -58,24 +57,16 @@ static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
 static void __devinit mvs_64xx_phy_hacks(struct mvs_info *mvi)
 {
        void __iomem *regs = mvi->regs;
+       int i;
 
        mvs_phy_hacks(mvi);
 
        if (!(mvi->flags & MVF_FLAG_SOC)) {
-               /* TEST - for phy decoding error, adjust voltage levels */
-               mw32(MVS_P0_VSR_ADDR + 0, 0x8);
-               mw32(MVS_P0_VSR_DATA + 0, 0x2F0);
-
-               mw32(MVS_P0_VSR_ADDR + 8, 0x8);
-               mw32(MVS_P0_VSR_DATA + 8, 0x2F0);
-
-               mw32(MVS_P0_VSR_ADDR + 16, 0x8);
-               mw32(MVS_P0_VSR_DATA + 16, 0x2F0);
-
-               mw32(MVS_P0_VSR_ADDR + 24, 0x8);
-               mw32(MVS_P0_VSR_DATA + 24, 0x2F0);
+               for (i = 0; i < MVS_SOC_PORTS; i++) {
+                       mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE8);
+                       mvs_write_port_vsr_data(mvi, i, 0x2F0);
+               }
        } else {
-               int i;
                /* disable auto port detection */
                mw32(MVS_GBL_PORT_TYPE, 0);
                for (i = 0; i < mvi->chip->n_phy; i++) {
@@ -95,7 +86,7 @@ static void mvs_64xx_stp_reset(struct mvs_info *mvi, u32 phy_id)
        u32 reg, tmp;
 
        if (!(mvi->flags & MVF_FLAG_SOC)) {
-               if (phy_id < 4)
+               if (phy_id < MVS_SOC_PORTS)
                        pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &reg);
                else
                        pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &reg);
@@ -104,13 +95,13 @@ static void mvs_64xx_stp_reset(struct mvs_info *mvi, u32 phy_id)
                reg = mr32(MVS_PHY_CTL);
 
        tmp = reg;
-       if (phy_id < 4)
+       if (phy_id < MVS_SOC_PORTS)
                tmp |= (1U << phy_id) << PCTL_LINK_OFFS;
        else
-               tmp |= (1U << (phy_id - 4)) << PCTL_LINK_OFFS;
+               tmp |= (1U << (phy_id - MVS_SOC_PORTS)) << PCTL_LINK_OFFS;
 
        if (!(mvi->flags & MVF_FLAG_SOC)) {
-               if (phy_id < 4) {
+               if (phy_id < MVS_SOC_PORTS) {
                        pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp);
                        mdelay(10);
                        pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, reg);
@@ -133,9 +124,9 @@ static void mvs_64xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
        tmp &= ~PHYEV_RDY_CH;
        mvs_write_port_irq_stat(mvi, phy_id, tmp);
        tmp = mvs_read_phy_ctl(mvi, phy_id);
-       if (hard == 1)
+       if (hard == MVS_HARD_RESET)
                tmp |= PHY_RST_HARD;
-       else if (hard == 0)
+       else if (hard == MVS_SOFT_RESET)
                tmp |= PHY_RST;
        mvs_write_phy_ctl(mvi, phy_id, tmp);
        if (hard) {
@@ -321,6 +312,11 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
        /* init phys */
        mvs_64xx_phy_hacks(mvi);
 
+       tmp = mvs_cr32(mvi, CMD_PHY_MODE_21);
+       tmp &= 0x0000ffff;
+       tmp |= 0x00fa0000;
+       mvs_cw32(mvi, CMD_PHY_MODE_21, tmp);
+
        /* enable auto port detection */
        mw32(MVS_GBL_PORT_TYPE, MODE_AUTO_DET_EN);
 
@@ -346,7 +342,7 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
 
                mvs_64xx_enable_xmt(mvi, i);
 
-               mvs_64xx_phy_reset(mvi, i, 1);
+               mvs_64xx_phy_reset(mvi, i, MVS_HARD_RESET);
                msleep(500);
                mvs_64xx_detect_porttype(mvi, i);
        }
@@ -377,13 +373,7 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
                mvs_update_phyinfo(mvi, i, 1);
        }
 
-       /* FIXME: update wide port bitmaps */
-
        /* little endian for open address and command table, etc. */
-       /*
-        * it seems that ( from the spec ) turning on big-endian won't
-        * do us any good on big-endian machines, need further confirmation
-        */
        cctl = mr32(MVS_CTL);
        cctl |= CCTL_ENDIAN_CMD;
        cctl |= CCTL_ENDIAN_DATA;
@@ -394,15 +384,19 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
        /* reset CMD queue */
        tmp = mr32(MVS_PCS);
        tmp |= PCS_CMD_RST;
+       tmp &= ~PCS_SELF_CLEAR;
        mw32(MVS_PCS, tmp);
-       /* interrupt coalescing may cause missing HW interrput in some case,
-        * and the max count is 0x1ff, while our max slot is 0x200,
+       /*
+        * the max count is 0x1ff, while our max slot is 0x200,
         * it will make count 0.
         */
        tmp = 0;
-       mw32(MVS_INT_COAL, tmp);
+       if (MVS_CHIP_SLOT_SZ > 0x1ff)
+               mw32(MVS_INT_COAL, 0x1ff | COAL_EN);
+       else
+               mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ | COAL_EN);
 
-       tmp = 0x100;
+       tmp = 0x10000 | interrupt_coalescing;
        mw32(MVS_INT_COAL_TMOUT, tmp);
 
        /* ladies and gentlemen, start your engines */
@@ -477,13 +471,11 @@ static irqreturn_t mvs_64xx_isr(struct mvs_info *mvi, int irq, u32 stat)
 
        /* clear CMD_CMPLT ASAP */
        mw32_f(MVS_INT_STAT, CINT_DONE);
-#ifndef MVS_USE_TASKLET
+
        spin_lock(&mvi->lock);
-#endif
        mvs_int_full(mvi);
-#ifndef MVS_USE_TASKLET
        spin_unlock(&mvi->lock);
-#endif
+
        return IRQ_HANDLED;
 }
 
@@ -630,7 +622,6 @@ static void mvs_64xx_phy_work_around(struct mvs_info *mvi, int i)
 {
        u32 tmp;
        struct mvs_phy *phy = &mvi->phy[i];
-       /* workaround for HW phy decoding error on 1.5g disk drive */
        mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE6);
        tmp = mvs_read_port_vsr_data(mvi, i);
        if (((phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >>
@@ -661,7 +652,7 @@ void mvs_64xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
                tmp |= lrmax;
        }
        mvs_write_phy_ctl(mvi, phy_id, tmp);
-       mvs_64xx_phy_reset(mvi, phy_id, 1);
+       mvs_64xx_phy_reset(mvi, phy_id, MVS_HARD_RESET);
 }
 
 static void mvs_64xx_clear_active_cmds(struct mvs_info *mvi)
@@ -744,11 +735,13 @@ int mvs_64xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
        return -1;
 }
 
-#ifndef DISABLE_HOTPLUG_DMA_FIX
-void mvs_64xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd)
+void mvs_64xx_fix_dma(struct mvs_info *mvi, u32 phy_mask,
+                               int buf_len, int from, void *prd)
 {
        int i;
        struct mvs_prd *buf_prd = prd;
+       dma_addr_t buf_dma = mvi->bulk_buffer_dma;
+
        buf_prd += from;
        for (i = 0; i < MAX_SG_ENTRY - from; i++) {
                buf_prd->addr = cpu_to_le64(buf_dma);
@@ -756,7 +749,28 @@ void mvs_64xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd)
                ++buf_prd;
        }
 }
-#endif
+
+static void mvs_64xx_tune_interrupt(struct mvs_info *mvi, u32 time)
+{
+       void __iomem *regs = mvi->regs;
+       u32 tmp = 0;
+       /*
+        * the max count is 0x1ff, while our max slot is 0x200,
+        * it will make count 0.
+        */
+       if (time == 0) {
+               mw32(MVS_INT_COAL, 0);
+               mw32(MVS_INT_COAL_TMOUT, 0x10000);
+       } else {
+               if (MVS_CHIP_SLOT_SZ > 0x1ff)
+                       mw32(MVS_INT_COAL, 0x1ff|COAL_EN);
+               else
+                       mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ|COAL_EN);
+
+               tmp = 0x10000 | time;
+               mw32(MVS_INT_COAL_TMOUT, tmp);
+       }
+}
 
 const struct mvs_dispatch mvs_64xx_dispatch = {
        "mv64xx",
@@ -780,7 +794,6 @@ const struct mvs_dispatch mvs_64xx_dispatch = {
        mvs_write_port_irq_stat,
        mvs_read_port_irq_mask,
        mvs_write_port_irq_mask,
-       mvs_get_sas_addr,
        mvs_64xx_command_active,
        mvs_64xx_clear_srs_irq,
        mvs_64xx_issue_stop,
@@ -808,8 +821,8 @@ const struct mvs_dispatch mvs_64xx_dispatch = {
        mvs_64xx_spi_buildcmd,
        mvs_64xx_spi_issuecmd,
        mvs_64xx_spi_waitdataready,
-#ifndef DISABLE_HOTPLUG_DMA_FIX
        mvs_64xx_fix_dma,
-#endif
+       mvs_64xx_tune_interrupt,
+       NULL,
 };
 
index 78162c3..3501291 100644 (file)
@@ -48,6 +48,216 @@ static void mvs_94xx_detect_porttype(struct mvs_info *mvi, int i)
        }
 }
 
+void set_phy_tuning(struct mvs_info *mvi, int phy_id,
+                       struct phy_tuning phy_tuning)
+{
+       u32 tmp, setting_0 = 0, setting_1 = 0;
+       u8 i;
+
+       /* Remap information for B0 chip:
+       *
+       * R0Ch -> R118h[15:0] (Adapted DFE F3 - F5 coefficient)
+       * R0Dh -> R118h[31:16] (Generation 1 Setting 0)
+       * R0Eh -> R11Ch[15:0]  (Generation 1 Setting 1)
+       * R0Fh -> R11Ch[31:16] (Generation 2 Setting 0)
+       * R10h -> R120h[15:0]  (Generation 2 Setting 1)
+       * R11h -> R120h[31:16] (Generation 3 Setting 0)
+       * R12h -> R124h[15:0]  (Generation 3 Setting 1)
+       * R13h -> R124h[31:16] (Generation 4 Setting 0 (Reserved))
+       */
+
+       /* A0 has a different set of registers */
+       if (mvi->pdev->revision == VANIR_A0_REV)
+               return;
+
+       for (i = 0; i < 3; i++) {
+               /* loop 3 times, set Gen 1, Gen 2, Gen 3 */
+               switch (i) {
+               case 0:
+                       setting_0 = GENERATION_1_SETTING;
+                       setting_1 = GENERATION_1_2_SETTING;
+                       break;
+               case 1:
+                       setting_0 = GENERATION_1_2_SETTING;
+                       setting_1 = GENERATION_2_3_SETTING;
+                       break;
+               case 2:
+                       setting_0 = GENERATION_2_3_SETTING;
+                       setting_1 = GENERATION_3_4_SETTING;
+                       break;
+               }
+
+               /* Set:
+               *
+               * Transmitter Emphasis Enable
+               * Transmitter Emphasis Amplitude
+               * Transmitter Amplitude
+               */
+               mvs_write_port_vsr_addr(mvi, phy_id, setting_0);
+               tmp = mvs_read_port_vsr_data(mvi, phy_id);
+               tmp &= ~(0xFBE << 16);
+               tmp |= (((phy_tuning.trans_emp_en << 11) |
+                       (phy_tuning.trans_emp_amp << 7) |
+                       (phy_tuning.trans_amp << 1)) << 16);
+               mvs_write_port_vsr_data(mvi, phy_id, tmp);
+
+               /* Set Transmitter Amplitude Adjust */
+               mvs_write_port_vsr_addr(mvi, phy_id, setting_1);
+               tmp = mvs_read_port_vsr_data(mvi, phy_id);
+               tmp &= ~(0xC000);
+               tmp |= (phy_tuning.trans_amp_adj << 14);
+               mvs_write_port_vsr_data(mvi, phy_id, tmp);
+       }
+}
+
+void set_phy_ffe_tuning(struct mvs_info *mvi, int phy_id,
+                               struct ffe_control ffe)
+{
+       u32 tmp;
+
+       /* Don't run this if A0/B0 */
+       if ((mvi->pdev->revision == VANIR_A0_REV)
+               || (mvi->pdev->revision == VANIR_B0_REV))
+               return;
+
+       /* FFE Resistor and Capacitor */
+       /* R10Ch DFE Resolution Control/Squelch and FFE Setting
+        *
+        * FFE_FORCE            [7]
+        * FFE_RES_SEL          [6:4]
+        * FFE_CAP_SEL          [3:0]
+        */
+       mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_FFE_CONTROL);
+       tmp = mvs_read_port_vsr_data(mvi, phy_id);
+       tmp &= ~0xFF;
+
+       /* Read from HBA_Info_Page */
+       tmp |= ((0x1 << 7) |
+               (ffe.ffe_rss_sel << 4) |
+               (ffe.ffe_cap_sel << 0));
+
+       mvs_write_port_vsr_data(mvi, phy_id, tmp);
+
+       /* R064h PHY Mode Register 1
+        *
+        * DFE_DIS              18
+        */
+       mvs_write_port_vsr_addr(mvi, phy_id, VSR_REF_CLOCK_CRTL);
+       tmp = mvs_read_port_vsr_data(mvi, phy_id);
+       tmp &= ~0x40001;
+       /* Hard coding */
+       /* No defines in HBA_Info_Page */
+       tmp |= (0 << 18);
+       mvs_write_port_vsr_data(mvi, phy_id, tmp);
+
+       /* R110h DFE F0-F1 Coefficient Control/DFE Update Control
+        *
+        * DFE_UPDATE_EN        [11:6]
+        * DFE_FX_FORCE         [5:0]
+        */
+       mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_DFE_UPDATE_CRTL);
+       tmp = mvs_read_port_vsr_data(mvi, phy_id);
+       tmp &= ~0xFFF;
+       /* Hard coding */
+       /* No defines in HBA_Info_Page */
+       tmp |= ((0x3F << 6) | (0x0 << 0));
+       mvs_write_port_vsr_data(mvi, phy_id, tmp);
+
+       /* R1A0h Interface and Digital Reference Clock Control/Reserved_50h
+        *
+        * FFE_TRAIN_EN         3
+        */
+       mvs_write_port_vsr_addr(mvi, phy_id, VSR_REF_CLOCK_CRTL);
+       tmp = mvs_read_port_vsr_data(mvi, phy_id);
+       tmp &= ~0x8;
+       /* Hard coding */
+       /* No defines in HBA_Info_Page */
+       tmp |= (0 << 3);
+       mvs_write_port_vsr_data(mvi, phy_id, tmp);
+}
+
+/*Notice: this function must be called when phy is disabled*/
+void set_phy_rate(struct mvs_info *mvi, int phy_id, u8 rate)
+{
+       union reg_phy_cfg phy_cfg, phy_cfg_tmp;
+       mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2);
+       phy_cfg_tmp.v = mvs_read_port_vsr_data(mvi, phy_id);
+       phy_cfg.v = 0;
+       phy_cfg.u.disable_phy = phy_cfg_tmp.u.disable_phy;
+       phy_cfg.u.sas_support = 1;
+       phy_cfg.u.sata_support = 1;
+       phy_cfg.u.sata_host_mode = 1;
+
+       switch (rate) {
+       case 0x0:
+               /* support 1.5 Gbps */
+               phy_cfg.u.speed_support = 1;
+               phy_cfg.u.snw_3_support = 0;
+               phy_cfg.u.tx_lnk_parity = 1;
+               phy_cfg.u.tx_spt_phs_lnk_rate = 0x30;
+               break;
+       case 0x1:
+
+               /* support 1.5, 3.0 Gbps */
+               phy_cfg.u.speed_support = 3;
+               phy_cfg.u.tx_spt_phs_lnk_rate = 0x3c;
+               phy_cfg.u.tx_lgcl_lnk_rate = 0x08;
+               break;
+       case 0x2:
+       default:
+               /* support 1.5, 3.0, 6.0 Gbps */
+               phy_cfg.u.speed_support = 7;
+               phy_cfg.u.snw_3_support = 1;
+               phy_cfg.u.tx_lnk_parity = 1;
+               phy_cfg.u.tx_spt_phs_lnk_rate = 0x3f;
+               phy_cfg.u.tx_lgcl_lnk_rate = 0x09;
+               break;
+       }
+       mvs_write_port_vsr_data(mvi, phy_id, phy_cfg.v);
+}
+
+static void __devinit
+mvs_94xx_config_reg_from_hba(struct mvs_info *mvi, int phy_id)
+{
+       u32 temp;
+       temp = (u32)(*(u32 *)&mvi->hba_info_param.phy_tuning[phy_id]);
+       if (temp == 0xFFFFFFFFL) {
+               mvi->hba_info_param.phy_tuning[phy_id].trans_emp_amp = 0x6;
+               mvi->hba_info_param.phy_tuning[phy_id].trans_amp = 0x1A;
+               mvi->hba_info_param.phy_tuning[phy_id].trans_amp_adj = 0x3;
+       }
+
+       temp = (u8)(*(u8 *)&mvi->hba_info_param.ffe_ctl[phy_id]);
+       if (temp == 0xFFL) {
+               switch (mvi->pdev->revision) {
+               case VANIR_A0_REV:
+               case VANIR_B0_REV:
+                       mvi->hba_info_param.ffe_ctl[phy_id].ffe_rss_sel = 0x7;
+                       mvi->hba_info_param.ffe_ctl[phy_id].ffe_cap_sel = 0x7;
+                       break;
+               case VANIR_C0_REV:
+               case VANIR_C1_REV:
+               case VANIR_C2_REV:
+               default:
+                       mvi->hba_info_param.ffe_ctl[phy_id].ffe_rss_sel = 0x7;
+                       mvi->hba_info_param.ffe_ctl[phy_id].ffe_cap_sel = 0xC;
+                       break;
+               }
+       }
+
+       temp = (u8)(*(u8 *)&mvi->hba_info_param.phy_rate[phy_id]);
+       if (temp == 0xFFL)
+               /*set default phy_rate = 6Gbps*/
+               mvi->hba_info_param.phy_rate[phy_id] = 0x2;
+
+       set_phy_tuning(mvi, phy_id,
+               mvi->hba_info_param.phy_tuning[phy_id]);
+       set_phy_ffe_tuning(mvi, phy_id,
+               mvi->hba_info_param.ffe_ctl[phy_id]);
+       set_phy_rate(mvi, phy_id,
+               mvi->hba_info_param.phy_rate[phy_id]);
+}
+
 static void __devinit mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id)
 {
        void __iomem *regs = mvi->regs;
@@ -61,7 +271,14 @@ static void __devinit mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id)
 static void mvs_94xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
 {
        u32 tmp;
-
+       u32 delay = 5000;
+       if (hard == MVS_PHY_TUNE) {
+               mvs_write_port_cfg_addr(mvi, phy_id, PHYR_SATA_CTL);
+               tmp = mvs_read_port_cfg_data(mvi, phy_id);
+               mvs_write_port_cfg_data(mvi, phy_id, tmp|0x20000000);
+               mvs_write_port_cfg_data(mvi, phy_id, tmp|0x100000);
+               return;
+       }
        tmp = mvs_read_port_irq_stat(mvi, phy_id);
        tmp &= ~PHYEV_RDY_CH;
        mvs_write_port_irq_stat(mvi, phy_id, tmp);
@@ -71,12 +288,15 @@ static void mvs_94xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
                mvs_write_phy_ctl(mvi, phy_id, tmp);
                do {
                        tmp = mvs_read_phy_ctl(mvi, phy_id);
-               } while (tmp & PHY_RST_HARD);
+                       udelay(10);
+                       delay--;
+               } while ((tmp & PHY_RST_HARD) && delay);
+               if (!delay)
+                       mv_dprintk("phy hard reset failed.\n");
        } else {
-               mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_STAT);
-               tmp = mvs_read_port_vsr_data(mvi, phy_id);
+               tmp = mvs_read_phy_ctl(mvi, phy_id);
                tmp |= PHY_RST;
-               mvs_write_port_vsr_data(mvi, phy_id, tmp);
+               mvs_write_phy_ctl(mvi, phy_id, tmp);
        }
 }
 
@@ -90,12 +310,25 @@ static void mvs_94xx_phy_disable(struct mvs_info *mvi, u32 phy_id)
 
 static void mvs_94xx_phy_enable(struct mvs_info *mvi, u32 phy_id)
 {
-       mvs_write_port_vsr_addr(mvi, phy_id, 0x1B4);
-       mvs_write_port_vsr_data(mvi, phy_id, 0x8300ffc1);
-       mvs_write_port_vsr_addr(mvi, phy_id, 0x104);
-       mvs_write_port_vsr_data(mvi, phy_id, 0x00018080);
+       u32 tmp;
+       u8 revision = 0;
+
+       revision = mvi->pdev->revision;
+       if (revision == VANIR_A0_REV) {
+               mvs_write_port_vsr_addr(mvi, phy_id, CMD_HOST_RD_DATA);
+               mvs_write_port_vsr_data(mvi, phy_id, 0x8300ffc1);
+       }
+       if (revision == VANIR_B0_REV) {
+               mvs_write_port_vsr_addr(mvi, phy_id, CMD_APP_MEM_CTL);
+               mvs_write_port_vsr_data(mvi, phy_id, 0x08001006);
+               mvs_write_port_vsr_addr(mvi, phy_id, CMD_HOST_RD_DATA);
+               mvs_write_port_vsr_data(mvi, phy_id, 0x0000705f);
+       }
+
        mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2);
-       mvs_write_port_vsr_data(mvi, phy_id, 0x00207fff);
+       tmp = mvs_read_port_vsr_data(mvi, phy_id);
+       tmp |= bit(0);
+       mvs_write_port_vsr_data(mvi, phy_id, tmp & 0xfd7fffff);
 }
 
 static int __devinit mvs_94xx_init(struct mvs_info *mvi)
@@ -103,7 +336,9 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
        void __iomem *regs = mvi->regs;
        int i;
        u32 tmp, cctl;
+       u8 revision;
 
+       revision = mvi->pdev->revision;
        mvs_show_pcie_usage(mvi);
        if (mvi->flags & MVF_FLAG_SOC) {
                tmp = mr32(MVS_PHY_CTL);
@@ -133,6 +368,28 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
                msleep(100);
        }
 
+       /* disable Multiplexing, enable phy implemented */
+       mw32(MVS_PORTS_IMP, 0xFF);
+
+       if (revision == VANIR_A0_REV) {
+               mw32(MVS_PA_VSR_ADDR, CMD_CMWK_OOB_DET);
+               mw32(MVS_PA_VSR_PORT, 0x00018080);
+       }
+       mw32(MVS_PA_VSR_ADDR, VSR_PHY_MODE2);
+       if (revision == VANIR_A0_REV || revision == VANIR_B0_REV)
+               /* set 6G/3G/1.5G, multiplexing, without SSC */
+               mw32(MVS_PA_VSR_PORT, 0x0084d4fe);
+       else
+               /* set 6G/3G/1.5G, multiplexing, with and without SSC */
+               mw32(MVS_PA_VSR_PORT, 0x0084fffe);
+
+       if (revision == VANIR_B0_REV) {
+               mw32(MVS_PA_VSR_ADDR, CMD_APP_MEM_CTL);
+               mw32(MVS_PA_VSR_PORT, 0x08001006);
+               mw32(MVS_PA_VSR_ADDR, CMD_HOST_RD_DATA);
+               mw32(MVS_PA_VSR_PORT, 0x0000705f);
+       }
+
        /* reset control */
        mw32(MVS_PCS, 0);               /* MVS_PCS */
        mw32(MVS_STP_REG_SET_0, 0);
@@ -141,17 +398,8 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
        /* init phys */
        mvs_phy_hacks(mvi);
 
-       /* disable Multiplexing, enable phy implemented */
-       mw32(MVS_PORTS_IMP, 0xFF);
-
-
-       mw32(MVS_PA_VSR_ADDR, 0x00000104);
-       mw32(MVS_PA_VSR_PORT, 0x00018080);
-       mw32(MVS_PA_VSR_ADDR, VSR_PHY_MODE8);
-       mw32(MVS_PA_VSR_PORT, 0x0084ffff);
-
        /* set LED blink when IO*/
-       mw32(MVS_PA_VSR_ADDR, 0x00000030);
+       mw32(MVS_PA_VSR_ADDR, VSR_PHY_ACT_LED);
        tmp = mr32(MVS_PA_VSR_PORT);
        tmp &= 0xFFFF00FF;
        tmp |= 0x00003300;
@@ -175,12 +423,13 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
                mvs_94xx_phy_disable(mvi, i);
                /* set phy local SAS address */
                mvs_set_sas_addr(mvi, i, CONFIG_ID_FRAME3, CONFIG_ID_FRAME4,
-                                               (mvi->phy[i].dev_sas_addr));
+                                               cpu_to_le64(mvi->phy[i].dev_sas_addr));
 
                mvs_94xx_enable_xmt(mvi, i);
+               mvs_94xx_config_reg_from_hba(mvi, i);
                mvs_94xx_phy_enable(mvi, i);
 
-               mvs_94xx_phy_reset(mvi, i, 1);
+               mvs_94xx_phy_reset(mvi, i, PHY_RST_HARD);
                msleep(500);
                mvs_94xx_detect_porttype(mvi, i);
        }
@@ -211,16 +460,9 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
                mvs_update_phyinfo(mvi, i, 1);
        }
 
-       /* FIXME: update wide port bitmaps */
-
        /* little endian for open address and command table, etc. */
-       /*
-        * it seems that ( from the spec ) turning on big-endian won't
-        * do us any good on big-endian machines, need further confirmation
-        */
        cctl = mr32(MVS_CTL);
        cctl |= CCTL_ENDIAN_CMD;
-       cctl |= CCTL_ENDIAN_DATA;
        cctl &= ~CCTL_ENDIAN_OPEN;
        cctl |= CCTL_ENDIAN_RSP;
        mw32_f(MVS_CTL, cctl);
@@ -228,15 +470,20 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
        /* reset CMD queue */
        tmp = mr32(MVS_PCS);
        tmp |= PCS_CMD_RST;
+       tmp &= ~PCS_SELF_CLEAR;
        mw32(MVS_PCS, tmp);
-       /* interrupt coalescing may cause missing HW interrput in some case,
-        * and the max count is 0x1ff, while our max slot is 0x200,
+       /*
+        * the max count is 0x1ff, while our max slot is 0x200,
         * it will make count 0.
         */
        tmp = 0;
-       mw32(MVS_INT_COAL, tmp);
+       if (MVS_CHIP_SLOT_SZ > 0x1ff)
+               mw32(MVS_INT_COAL, 0x1ff | COAL_EN);
+       else
+               mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ | COAL_EN);
 
-       tmp = 0x100;
+       /* default interrupt coalescing time is 128us */
+       tmp = 0x10000 | interrupt_coalescing;
        mw32(MVS_INT_COAL_TMOUT, tmp);
 
        /* ladies and gentlemen, start your engines */
@@ -249,7 +496,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
 
        /* enable completion queue interrupt */
        tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS | CINT_CI_STOP |
-               CINT_DMA_PCIE);
+               CINT_DMA_PCIE | CINT_NON_SPEC_NCQ_ERROR);
        tmp |= CINT_PHY_MASK;
        mw32(MVS_INT_MASK, tmp);
 
@@ -332,13 +579,10 @@ static irqreturn_t mvs_94xx_isr(struct mvs_info *mvi, int irq, u32 stat)
        if (((stat & IRQ_SAS_A) && mvi->id == 0) ||
                        ((stat & IRQ_SAS_B) && mvi->id == 1)) {
                mw32_f(MVS_INT_STAT, CINT_DONE);
-       #ifndef MVS_USE_TASKLET
+
                spin_lock(&mvi->lock);
-       #endif
                mvs_int_full(mvi);
-       #ifndef MVS_USE_TASKLET
                spin_unlock(&mvi->lock);
-       #endif
        }
        return IRQ_HANDLED;
 }
@@ -346,10 +590,48 @@ static irqreturn_t mvs_94xx_isr(struct mvs_info *mvi, int irq, u32 stat)
 static void mvs_94xx_command_active(struct mvs_info *mvi, u32 slot_idx)
 {
        u32 tmp;
-       mvs_cw32(mvi, 0x300 + (slot_idx >> 3), 1 << (slot_idx % 32));
-       do {
-               tmp = mvs_cr32(mvi, 0x300 + (slot_idx >> 3));
-       } while (tmp & 1 << (slot_idx % 32));
+       tmp = mvs_cr32(mvi, MVS_COMMAND_ACTIVE+(slot_idx >> 3));
+       if (tmp && 1 << (slot_idx % 32)) {
+               mv_printk("command active %08X,  slot [%x].\n", tmp, slot_idx);
+               mvs_cw32(mvi, MVS_COMMAND_ACTIVE + (slot_idx >> 3),
+                       1 << (slot_idx % 32));
+               do {
+                       tmp = mvs_cr32(mvi,
+                               MVS_COMMAND_ACTIVE + (slot_idx >> 3));
+               } while (tmp & 1 << (slot_idx % 32));
+       }
+}
+
+void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all)
+{
+       void __iomem *regs = mvi->regs;
+       u32 tmp;
+
+       if (clear_all) {
+               tmp = mr32(MVS_INT_STAT_SRS_0);
+               if (tmp) {
+                       mv_dprintk("check SRS 0 %08X.\n", tmp);
+                       mw32(MVS_INT_STAT_SRS_0, tmp);
+               }
+               tmp = mr32(MVS_INT_STAT_SRS_1);
+               if (tmp) {
+                       mv_dprintk("check SRS 1 %08X.\n", tmp);
+                       mw32(MVS_INT_STAT_SRS_1, tmp);
+               }
+       } else {
+               if (reg_set > 31)
+                       tmp = mr32(MVS_INT_STAT_SRS_1);
+               else
+                       tmp = mr32(MVS_INT_STAT_SRS_0);
+
+               if (tmp & (1 << (reg_set % 32))) {
+                       mv_dprintk("register set 0x%x was stopped.\n", reg_set);
+                       if (reg_set > 31)
+                               mw32(MVS_INT_STAT_SRS_1, 1 << (reg_set % 32));
+                       else
+                               mw32(MVS_INT_STAT_SRS_0, 1 << (reg_set % 32));
+               }
+       }
 }
 
 static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type,
@@ -357,37 +639,56 @@ static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type,
 {
        void __iomem *regs = mvi->regs;
        u32 tmp;
+       mvs_94xx_clear_srs_irq(mvi, 0, 1);
 
-       if (type == PORT_TYPE_SATA) {
-               tmp = mr32(MVS_INT_STAT_SRS_0) | (1U << tfs);
-               mw32(MVS_INT_STAT_SRS_0, tmp);
-       }
-       mw32(MVS_INT_STAT, CINT_CI_STOP);
+       tmp = mr32(MVS_INT_STAT);
+       mw32(MVS_INT_STAT, tmp | CINT_CI_STOP);
        tmp = mr32(MVS_PCS) | 0xFF00;
        mw32(MVS_PCS, tmp);
 }
 
+static void mvs_94xx_non_spec_ncq_error(struct mvs_info *mvi)
+{
+       void __iomem *regs = mvi->regs;
+       u32 err_0, err_1;
+       u8 i;
+       struct mvs_device *device;
+
+       err_0 = mr32(MVS_NON_NCQ_ERR_0);
+       err_1 = mr32(MVS_NON_NCQ_ERR_1);
+
+       mv_dprintk("non specific ncq error err_0:%x,err_1:%x.\n",
+                       err_0, err_1);
+       for (i = 0; i < 32; i++) {
+               if (err_0 & bit(i)) {
+                       device = mvs_find_dev_by_reg_set(mvi, i);
+                       if (device)
+                               mvs_release_task(mvi, device->sas_device);
+               }
+               if (err_1 & bit(i)) {
+                       device = mvs_find_dev_by_reg_set(mvi, i+32);
+                       if (device)
+                               mvs_release_task(mvi, device->sas_device);
+               }
+       }
+
+       mw32(MVS_NON_NCQ_ERR_0, err_0);
+       mw32(MVS_NON_NCQ_ERR_1, err_1);
+}
+
 static void mvs_94xx_free_reg_set(struct mvs_info *mvi, u8 *tfs)
 {
        void __iomem *regs = mvi->regs;
-       u32 tmp;
        u8 reg_set = *tfs;
 
        if (*tfs == MVS_ID_NOT_MAPPED)
                return;
 
        mvi->sata_reg_set &= ~bit(reg_set);
-       if (reg_set < 32) {
+       if (reg_set < 32)
                w_reg_set_enable(reg_set, (u32)mvi->sata_reg_set);
-               tmp = mr32(MVS_INT_STAT_SRS_0) & (u32)mvi->sata_reg_set;
-               if (tmp)
-                       mw32(MVS_INT_STAT_SRS_0, tmp);
-       } else {
-               w_reg_set_enable(reg_set, mvi->sata_reg_set);
-               tmp = mr32(MVS_INT_STAT_SRS_1) & mvi->sata_reg_set;
-               if (tmp)
-                       mw32(MVS_INT_STAT_SRS_1, tmp);
-       }
+       else
+               w_reg_set_enable(reg_set, (u32)(mvi->sata_reg_set >> 32));
 
        *tfs = MVS_ID_NOT_MAPPED;
 
@@ -403,7 +704,7 @@ static u8 mvs_94xx_assign_reg_set(struct mvs_info *mvi, u8 *tfs)
                return 0;
 
        i = mv_ffc64(mvi->sata_reg_set);
-       if (i > 32) {
+       if (i >= 32) {
                mvi->sata_reg_set |= bit(i);
                w_reg_set_enable(i, (u32)(mvi->sata_reg_set >> 32));
                *tfs = i;
@@ -422,9 +723,12 @@ static void mvs_94xx_make_prd(struct scatterlist *scatter, int nr, void *prd)
        int i;
        struct scatterlist *sg;
        struct mvs_prd *buf_prd = prd;
+       struct mvs_prd_imt im_len;
+       *(u32 *)&im_len = 0;
        for_each_sg(scatter, sg, nr, i) {
                buf_prd->addr = cpu_to_le64(sg_dma_address(sg));
-               buf_prd->im_len.len = cpu_to_le32(sg_dma_len(sg));
+               im_len.len = sg_dma_len(sg);
+               buf_prd->im_len = cpu_to_le32(*(u32 *)&im_len);
                buf_prd++;
        }
 }
@@ -433,7 +737,7 @@ static int mvs_94xx_oob_done(struct mvs_info *mvi, int i)
 {
        u32 phy_st;
        phy_st = mvs_read_phy_ctl(mvi, i);
-       if (phy_st & PHY_READY_MASK)    /* phy ready */
+       if (phy_st & PHY_READY_MASK)
                return 1;
        return 0;
 }
@@ -447,7 +751,7 @@ static void mvs_94xx_get_dev_identify_frame(struct mvs_info *mvi, int port_id,
        for (i = 0; i < 7; i++) {
                mvs_write_port_cfg_addr(mvi, port_id,
                                        CONFIG_ID_FRAME0 + i * 4);
-               id_frame[i] = mvs_read_port_cfg_data(mvi, port_id);
+               id_frame[i] = cpu_to_le32(mvs_read_port_cfg_data(mvi, port_id));
        }
        memcpy(id, id_frame, 28);
 }
@@ -458,15 +762,13 @@ static void mvs_94xx_get_att_identify_frame(struct mvs_info *mvi, int port_id,
        int i;
        u32 id_frame[7];
 
-       /* mvs_hexdump(28, (u8 *)id_frame, 0); */
        for (i = 0; i < 7; i++) {
                mvs_write_port_cfg_addr(mvi, port_id,
                                        CONFIG_ATT_ID_FRAME0 + i * 4);
-               id_frame[i] = mvs_read_port_cfg_data(mvi, port_id);
+               id_frame[i] = cpu_to_le32(mvs_read_port_cfg_data(mvi, port_id));
                mv_dprintk("94xx phy %d atta frame %d %x.\n",
                        port_id + mvi->id * mvi->chip->n_phy, i, id_frame[i]);
        }
-       /* mvs_hexdump(28, (u8 *)id_frame, 0); */
        memcpy(id, id_frame, 28);
 }
 
@@ -526,7 +828,18 @@ static void mvs_94xx_fix_phy_info(struct mvs_info *mvi, int i,
 void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
                        struct sas_phy_linkrates *rates)
 {
-       /* TODO */
+       u32 lrmax = 0;
+       u32 tmp;
+
+       tmp = mvs_read_phy_ctl(mvi, phy_id);
+       lrmax = (rates->maximum_linkrate - SAS_LINK_RATE_1_5_GBPS) << 12;
+
+       if (lrmax) {
+               tmp &= ~(0x3 << 12);
+               tmp |= lrmax;
+       }
+       mvs_write_phy_ctl(mvi, phy_id, tmp);
+       mvs_94xx_phy_reset(mvi, phy_id, PHY_RST_HARD);
 }
 
 static void mvs_94xx_clear_active_cmds(struct mvs_info *mvi)
@@ -603,27 +916,59 @@ int mvs_94xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
        return -1;
 }
 
-#ifndef DISABLE_HOTPLUG_DMA_FIX
-void mvs_94xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd)
+void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask,
+                               int buf_len, int from, void *prd)
 {
        int i;
        struct mvs_prd *buf_prd = prd;
+       dma_addr_t buf_dma;
+       struct mvs_prd_imt im_len;
+
+       *(u32 *)&im_len = 0;
        buf_prd += from;
-       for (i = 0; i < MAX_SG_ENTRY - from; i++) {
-               buf_prd->addr = cpu_to_le64(buf_dma);
-               buf_prd->im_len.len = cpu_to_le32(buf_len);
-               ++buf_prd;
+
+#define PRD_CHAINED_ENTRY 0x01
+       if ((mvi->pdev->revision == VANIR_A0_REV) ||
+                       (mvi->pdev->revision == VANIR_B0_REV))
+               buf_dma = (phy_mask <= 0x08) ?
+                               mvi->bulk_buffer_dma : mvi->bulk_buffer_dma1;
+       else
+               return;
+
+       for (i = from; i < MAX_SG_ENTRY; i++, ++buf_prd) {
+               if (i == MAX_SG_ENTRY - 1) {
+                       buf_prd->addr = cpu_to_le64(virt_to_phys(buf_prd - 1));
+                       im_len.len = 2;
+                       im_len.misc_ctl = PRD_CHAINED_ENTRY;
+               } else {
+                       buf_prd->addr = cpu_to_le64(buf_dma);
+                       im_len.len = buf_len;
+               }
+               buf_prd->im_len = cpu_to_le32(*(u32 *)&im_len);
        }
 }
-#endif
 
-/*
- * FIXME JEJB: temporary nop clear_srs_irq to make 94xx still work
- * with 64xx fixes
- */
-static void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set,
-                                  u8 clear_all)
+static void mvs_94xx_tune_interrupt(struct mvs_info *mvi, u32 time)
 {
+       void __iomem *regs = mvi->regs;
+       u32 tmp = 0;
+       /*
+        * the max count is 0x1ff, while our max slot is 0x200,
+        * it will make count 0.
+        */
+       if (time == 0) {
+               mw32(MVS_INT_COAL, 0);
+               mw32(MVS_INT_COAL_TMOUT, 0x10000);
+       } else {
+               if (MVS_CHIP_SLOT_SZ > 0x1ff)
+                       mw32(MVS_INT_COAL, 0x1ff|COAL_EN);
+               else
+                       mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ|COAL_EN);
+
+               tmp = 0x10000 | time;
+               mw32(MVS_INT_COAL_TMOUT, tmp);
+       }
+
 }
 
 const struct mvs_dispatch mvs_94xx_dispatch = {
@@ -648,7 +993,6 @@ const struct mvs_dispatch mvs_94xx_dispatch = {
        mvs_write_port_irq_stat,
        mvs_read_port_irq_mask,
        mvs_write_port_irq_mask,
-       mvs_get_sas_addr,
        mvs_94xx_command_active,
        mvs_94xx_clear_srs_irq,
        mvs_94xx_issue_stop,
@@ -676,8 +1020,8 @@ const struct mvs_dispatch mvs_94xx_dispatch = {
        mvs_94xx_spi_buildcmd,
        mvs_94xx_spi_issuecmd,
        mvs_94xx_spi_waitdataready,
-#ifndef DISABLE_HOTPLUG_DMA_FIX
        mvs_94xx_fix_dma,
-#endif
+       mvs_94xx_tune_interrupt,
+       mvs_94xx_non_spec_ncq_error,
 };
 
index 8835bef..8f7eb4f 100644 (file)
 
 #define MAX_LINK_RATE          SAS_LINK_RATE_6_0_GBPS
 
+enum VANIR_REVISION_ID {
+       VANIR_A0_REV            = 0xA0,
+       VANIR_B0_REV            = 0x01,
+       VANIR_C0_REV            = 0x02,
+       VANIR_C1_REV            = 0x03,
+       VANIR_C2_REV            = 0xC2,
+};
+
 enum hw_registers {
        MVS_GBL_CTL             = 0x04,  /* global control */
        MVS_GBL_INT_STAT        = 0x00,  /* global irq status */
@@ -101,6 +109,7 @@ enum hw_registers {
        MVS_P4_VSR_DATA         = 0x254, /* phy4 VSR data */
        MVS_PA_VSR_ADDR         = 0x290, /* All port VSR addr */
        MVS_PA_VSR_PORT         = 0x294, /* All port VSR data */
+       MVS_COMMAND_ACTIVE      = 0x300,
 };
 
 enum pci_cfg_registers {
@@ -112,26 +121,29 @@ enum pci_cfg_registers {
 
 /*  SAS/SATA Vendor Specific Port Registers */
 enum sas_sata_vsp_regs {
-       VSR_PHY_STAT            = 0x00 * 4, /* Phy Status */
-       VSR_PHY_MODE1           = 0x01 * 4, /* phy tx */
-       VSR_PHY_MODE2           = 0x02 * 4, /* tx scc */
-       VSR_PHY_MODE3           = 0x03 * 4, /* pll */
-       VSR_PHY_MODE4           = 0x04 * 4, /* VCO */
-       VSR_PHY_MODE5           = 0x05 * 4, /* Rx */
-       VSR_PHY_MODE6           = 0x06 * 4, /* CDR */
-       VSR_PHY_MODE7           = 0x07 * 4, /* Impedance */
-       VSR_PHY_MODE8           = 0x08 * 4, /* Voltage */
-       VSR_PHY_MODE9           = 0x09 * 4, /* Test */
-       VSR_PHY_MODE10          = 0x0A * 4, /* Power */
-       VSR_PHY_MODE11          = 0x0B * 4, /* Phy Mode */
-       VSR_PHY_VS0             = 0x0C * 4, /* Vednor Specific 0 */
-       VSR_PHY_VS1             = 0x0D * 4, /* Vednor Specific 1 */
+       VSR_PHY_STAT            = 0x00 * 4, /* Phy Interrupt Status */
+       VSR_PHY_MODE1           = 0x01 * 4, /* phy Interrupt Enable */
+       VSR_PHY_MODE2           = 0x02 * 4, /* Phy Configuration */
+       VSR_PHY_MODE3           = 0x03 * 4, /* Phy Status */
+       VSR_PHY_MODE4           = 0x04 * 4, /* Phy Counter 0 */
+       VSR_PHY_MODE5           = 0x05 * 4, /* Phy Counter 1 */
+       VSR_PHY_MODE6           = 0x06 * 4, /* Event Counter Control */
+       VSR_PHY_MODE7           = 0x07 * 4, /* Event Counter Select */
+       VSR_PHY_MODE8           = 0x08 * 4, /* Event Counter 0 */
+       VSR_PHY_MODE9           = 0x09 * 4, /* Event Counter 1 */
+       VSR_PHY_MODE10          = 0x0A * 4, /* Event Counter 2 */
+       VSR_PHY_MODE11          = 0x0B * 4, /* Event Counter 3 */
+       VSR_PHY_ACT_LED         = 0x0C * 4, /* Activity LED control */
+
+       VSR_PHY_FFE_CONTROL     = 0x10C,
+       VSR_PHY_DFE_UPDATE_CRTL = 0x110,
+       VSR_REF_CLOCK_CRTL      = 0x1A0,
 };
 
 enum chip_register_bits {
        PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0x7 << 8),
-       PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0x7 << 8),
-       PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (12),
+       PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0x7 << 12),
+       PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (16),
        PHY_NEG_SPP_PHYS_LINK_RATE_MASK =
                        (0x3 << PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET),
 };
@@ -169,22 +181,75 @@ enum pci_interrupt_cause {
        IRQ_PCIE_ERR                   = (1 << 31),
 };
 
+union reg_phy_cfg {
+       u32 v;
+       struct {
+               u32 phy_reset:1;
+               u32 sas_support:1;
+               u32 sata_support:1;
+               u32 sata_host_mode:1;
+               /*
+                * bit 2: 6Gbps support
+                * bit 1: 3Gbps support
+                * bit 0: 1.5Gbps support
+                */
+               u32 speed_support:3;
+               u32 snw_3_support:1;
+               u32 tx_lnk_parity:1;
+               /*
+                * bit 5: G1 (1.5Gbps) Without SSC
+                * bit 4: G1 (1.5Gbps) with SSC
+                * bit 3: G2 (3.0Gbps) Without SSC
+                * bit 2: G2 (3.0Gbps) with SSC
+                * bit 1: G3 (6.0Gbps) without SSC
+                * bit 0: G3 (6.0Gbps) with SSC
+                */
+               u32 tx_spt_phs_lnk_rate:6;
+               /* 8h: 1.5Gbps 9h: 3Gbps Ah: 6Gbps */
+               u32 tx_lgcl_lnk_rate:4;
+               u32 tx_ssc_type:1;
+               u32 sata_spin_up_spt:1;
+               u32 sata_spin_up_en:1;
+               u32 bypass_oob:1;
+               u32 disable_phy:1;
+               u32 rsvd:8;
+       } u;
+};
+
 #define MAX_SG_ENTRY           255
 
 struct mvs_prd_imt {
+#ifndef __BIG_ENDIAN
        __le32                  len:22;
        u8                      _r_a:2;
        u8                      misc_ctl:4;
        u8                      inter_sel:4;
+#else
+       u32                     inter_sel:4;
+       u32                     misc_ctl:4;
+       u32                     _r_a:2;
+       u32                     len:22;
+#endif
 };
 
 struct mvs_prd {
        /* 64-bit buffer address */
        __le64                  addr;
        /* 22-bit length */
-       struct mvs_prd_imt      im_len;
+       __le32                  im_len;
 } __attribute__ ((packed));
 
+/*
+ * these registers are accessed through port vendor
+ * specific address/data registers
+ */
+enum sas_sata_phy_regs {
+       GENERATION_1_SETTING            = 0x118,
+       GENERATION_1_2_SETTING          = 0x11C,
+       GENERATION_2_3_SETTING          = 0x120,
+       GENERATION_3_4_SETTING          = 0x124,
+};
+
 #define SPI_CTRL_REG_94XX              0xc800
 #define SPI_ADDR_REG_94XX              0xc804
 #define SPI_WR_DATA_REG_94XX         0xc808
index 1753a6f..bcc4080 100644 (file)
@@ -164,7 +164,6 @@ static inline void __devinit mvs_phy_hacks(struct mvs_info *mvi)
 {
        u32 tmp;
 
-       /* workaround for SATA R-ERR, to ignore phy glitch */
        tmp = mvs_cr32(mvi, CMD_PHY_TIMER);
        tmp &= ~(1 << 9);
        tmp |= (1 << 10);
@@ -179,23 +178,10 @@ static inline void __devinit mvs_phy_hacks(struct mvs_info *mvi)
        tmp |= 0x3fff;
        mvs_cw32(mvi, CMD_SAS_CTL0, tmp);
 
-       /* workaround for WDTIMEOUT , set to 550 ms */
        mvs_cw32(mvi, CMD_WD_TIMER, 0x7a0000);
 
        /* not to halt for different port op during wideport link change */
        mvs_cw32(mvi, CMD_APP_ERR_CONFIG, 0xffefbf7d);
-
-       /* workaround for Seagate disk not-found OOB sequence, recv
-        * COMINIT before sending out COMWAKE */
-       tmp = mvs_cr32(mvi, CMD_PHY_MODE_21);
-       tmp &= 0x0000ffff;
-       tmp |= 0x00fa0000;
-       mvs_cw32(mvi, CMD_PHY_MODE_21, tmp);
-
-       tmp = mvs_cr32(mvi, CMD_PHY_TIMER);
-       tmp &= 0x1fffffff;
-       tmp |= (2U << 29);      /* 8 ms retry */
-       mvs_cw32(mvi, CMD_PHY_TIMER, tmp);
 }
 
 static inline void mvs_int_sata(struct mvs_info *mvi)
@@ -223,6 +209,9 @@ static inline void mvs_int_full(struct mvs_info *mvi)
                        mvs_int_port(mvi, i, tmp);
        }
 
+       if (stat & CINT_NON_SPEC_NCQ_ERROR)
+               MVS_CHIP_DISP->non_spec_ncq_error(mvi);
+
        if (stat & CINT_SRS)
                mvs_int_sata(mvi);
 
index bc00c94..dec7cad 100644 (file)
@@ -43,7 +43,6 @@ enum chip_flavors {
 
 /* driver compile-time configuration */
 enum driver_configuration {
-       MVS_SLOTS               = 512,  /* command slots */
        MVS_TX_RING_SZ          = 1024, /* TX ring size (12-bit) */
        MVS_RX_RING_SZ          = 1024, /* RX ring size (12-bit) */
                                        /* software requires power-of-2
@@ -56,8 +55,7 @@ enum driver_configuration {
        MVS_SSP_CMD_SZ          = 64,   /* SSP command table buffer size */
        MVS_ATA_CMD_SZ          = 96,   /* SATA command table buffer size */
        MVS_OAF_SZ              = 64,   /* Open address frame buffer size */
-       MVS_QUEUE_SIZE  = 32,   /* Support Queue depth */
-       MVS_CAN_QUEUE           = MVS_SLOTS - 2,        /* SCSI Queue depth */
+       MVS_QUEUE_SIZE          = 64,   /* Support Queue depth */
        MVS_SOC_CAN_QUEUE       = MVS_SOC_SLOTS - 2,
 };
 
@@ -144,6 +142,7 @@ enum hw_register_bits {
        CINT_DMA_PCIE           = (1U << 27),   /* DMA to PCIE timeout */
        CINT_MEM                = (1U << 26),   /* int mem parity err */
        CINT_I2C_SLAVE          = (1U << 25),   /* slave I2C event */
+       CINT_NON_SPEC_NCQ_ERROR = (1U << 25),   /* Non specific NCQ error */
        CINT_SRS                = (1U << 3),    /* SRS event */
        CINT_CI_STOP            = (1U << 1),    /* cmd issue stopped */
        CINT_DONE               = (1U << 0),    /* cmd completion */
@@ -161,7 +160,7 @@ enum hw_register_bits {
        TXQ_CMD_SSP             = 1,            /* SSP protocol */
        TXQ_CMD_SMP             = 2,            /* SMP protocol */
        TXQ_CMD_STP             = 3,            /* STP/SATA protocol */
-       TXQ_CMD_SSP_FREE_LIST   = 4,            /* add to SSP targ free list */
+       TXQ_CMD_SSP_FREE_LIST   = 4,            /* add to SSP target free list */
        TXQ_CMD_SLOT_RESET      = 7,            /* reset command slot */
        TXQ_MODE_I              = (1U << 28),   /* mode: 0=target,1=initiator */
        TXQ_MODE_TARGET         = 0,
@@ -391,15 +390,15 @@ enum sas_cmd_port_registers {
 };
 
 enum mvs_info_flags {
-       MVF_MSI         = (1U << 0),    /* MSI is enabled */
        MVF_PHY_PWR_FIX = (1U << 1),    /* bug workaround */
        MVF_FLAG_SOC            = (1U << 2),    /* SoC integrated controllers */
 };
 
 enum mvs_event_flags {
-       PHY_PLUG_EVENT  = (3U),
+       PHY_PLUG_EVENT          = (3U),
        PHY_PLUG_IN             = (1U << 0),    /* phy plug in */
        PHY_PLUG_OUT            = (1U << 1),    /* phy plug out */
+       EXP_BRCT_CHG            = (1U << 2),    /* broadcast change */
 };
 
 enum mvs_port_type {
index 90b6366..4e9af66 100644 (file)
@@ -34,22 +34,25 @@ MODULE_PARM_DESC(collector, "\n"
        "\tThe mvsas SAS LLDD supports both modes.\n"
        "\tDefault: 1 (Direct Mode).\n");
 
+int interrupt_coalescing = 0x80;
+
 static struct scsi_transport_template *mvs_stt;
 struct kmem_cache *mvs_task_list_cache;
 static const struct mvs_chip_info mvs_chips[] = {
-       [chip_6320] =   { 1, 2, 0x400, 17, 16,  9, &mvs_64xx_dispatch, },
-       [chip_6440] =   { 1, 4, 0x400, 17, 16,  9, &mvs_64xx_dispatch, },
-       [chip_6485] =   { 1, 8, 0x800, 33, 32, 10, &mvs_64xx_dispatch, },
-       [chip_9180] =   { 2, 4, 0x800, 17, 64,  9, &mvs_94xx_dispatch, },
-       [chip_9480] =   { 2, 4, 0x800, 17, 64,  9, &mvs_94xx_dispatch, },
-       [chip_9445] =   { 1, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, },
-       [chip_9485] =   { 2, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, },
-       [chip_1300] =   { 1, 4, 0x400, 17, 16,  9, &mvs_64xx_dispatch, },
-       [chip_1320] =   { 2, 4, 0x800, 17, 64,  9, &mvs_94xx_dispatch, },
+       [chip_6320] =   { 1, 2, 0x400, 17, 16, 6,  9, &mvs_64xx_dispatch, },
+       [chip_6440] =   { 1, 4, 0x400, 17, 16, 6,  9, &mvs_64xx_dispatch, },
+       [chip_6485] =   { 1, 8, 0x800, 33, 32, 6, 10, &mvs_64xx_dispatch, },
+       [chip_9180] =   { 2, 4, 0x800, 17, 64, 8,  9, &mvs_94xx_dispatch, },
+       [chip_9480] =   { 2, 4, 0x800, 17, 64, 8,  9, &mvs_94xx_dispatch, },
+       [chip_9445] =   { 1, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, },
+       [chip_9485] =   { 2, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, },
+       [chip_1300] =   { 1, 4, 0x400, 17, 16, 6,  9, &mvs_64xx_dispatch, },
+       [chip_1320] =   { 2, 4, 0x800, 17, 64, 8,  9, &mvs_94xx_dispatch, },
 };
 
+struct device_attribute *mvst_host_attrs[];
+
 #define SOC_SAS_NUM 2
-#define SG_MX 64
 
 static struct scsi_host_template mvs_sht = {
        .module                 = THIS_MODULE,
@@ -66,7 +69,7 @@ static struct scsi_host_template mvs_sht = {
        .can_queue              = 1,
        .cmd_per_lun            = 1,
        .this_id                = -1,
-       .sg_tablesize           = SG_MX,
+       .sg_tablesize           = SG_ALL,
        .max_sectors            = SCSI_DEFAULT_MAX_SECTORS,
        .use_clustering         = ENABLE_CLUSTERING,
        .eh_device_reset_handler = sas_eh_device_reset_handler,
@@ -74,6 +77,7 @@ static struct scsi_host_template mvs_sht = {
        .slave_alloc            = mvs_slave_alloc,
        .target_destroy         = sas_target_destroy,
        .ioctl                  = sas_ioctl,
+       .shost_attrs            = mvst_host_attrs,
 };
 
 static struct sas_domain_function_template mvs_transport_ops = {
@@ -100,6 +104,7 @@ static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id)
        struct asd_sas_phy *sas_phy = &phy->sas_phy;
 
        phy->mvi = mvi;
+       phy->port = NULL;
        init_timer(&phy->timer);
        sas_phy->enabled = (phy_id < mvi->chip->n_phy) ? 1 : 0;
        sas_phy->class = SAS;
@@ -128,7 +133,7 @@ static void mvs_free(struct mvs_info *mvi)
        if (mvi->flags & MVF_FLAG_SOC)
                slot_nr = MVS_SOC_SLOTS;
        else
-               slot_nr = MVS_SLOTS;
+               slot_nr = MVS_CHIP_SLOT_SZ;
 
        if (mvi->dma_pool)
                pci_pool_destroy(mvi->dma_pool);
@@ -148,25 +153,26 @@ static void mvs_free(struct mvs_info *mvi)
                dma_free_coherent(mvi->dev,
                                  sizeof(*mvi->slot) * slot_nr,
                                  mvi->slot, mvi->slot_dma);
-#ifndef DISABLE_HOTPLUG_DMA_FIX
+
        if (mvi->bulk_buffer)
                dma_free_coherent(mvi->dev, TRASH_BUCKET_SIZE,
                                  mvi->bulk_buffer, mvi->bulk_buffer_dma);
-#endif
+       if (mvi->bulk_buffer1)
+               dma_free_coherent(mvi->dev, TRASH_BUCKET_SIZE,
+                                 mvi->bulk_buffer1, mvi->bulk_buffer_dma1);
 
        MVS_CHIP_DISP->chip_iounmap(mvi);
        if (mvi->shost)
                scsi_host_put(mvi->shost);
        list_for_each_entry(mwq, &mvi->wq_list, entry)
                cancel_delayed_work(&mwq->work_q);
+       kfree(mvi->tags);
        kfree(mvi);
 }
 
-#ifdef MVS_USE_TASKLET
-struct tasklet_struct  mv_tasklet;
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
 static void mvs_tasklet(unsigned long opaque)
 {
-       unsigned long flags;
        u32 stat;
        u16 core_nr, i = 0;
 
@@ -179,35 +185,49 @@ static void mvs_tasklet(unsigned long opaque)
        if (unlikely(!mvi))
                BUG_ON(1);
 
+       stat = MVS_CHIP_DISP->isr_status(mvi, mvi->pdev->irq);
+       if (!stat)
+               goto out;
+
        for (i = 0; i < core_nr; i++) {
                mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
-               stat = MVS_CHIP_DISP->isr_status(mvi, mvi->irq);
-               if (stat)
-                       MVS_CHIP_DISP->isr(mvi, mvi->irq, stat);
+               MVS_CHIP_DISP->isr(mvi, mvi->pdev->irq, stat);
        }
+out:
+       MVS_CHIP_DISP->interrupt_enable(mvi);
 
 }
 #endif
 
 static irqreturn_t mvs_interrupt(int irq, void *opaque)
 {
-       u32 core_nr, i = 0;
+       u32 core_nr;
        u32 stat;
        struct mvs_info *mvi;
        struct sas_ha_struct *sha = opaque;
+#ifndef CONFIG_SCSI_MVSAS_TASKLET
+       u32 i;
+#endif
 
        core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
        mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
 
        if (unlikely(!mvi))
                return IRQ_NONE;
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+       MVS_CHIP_DISP->interrupt_disable(mvi);
+#endif
 
        stat = MVS_CHIP_DISP->isr_status(mvi, irq);
-       if (!stat)
+       if (!stat) {
+       #ifdef CONFIG_SCSI_MVSAS_TASKLET
+               MVS_CHIP_DISP->interrupt_enable(mvi);
+       #endif
                return IRQ_NONE;
+       }
 
-#ifdef MVS_USE_TASKLET
-       tasklet_schedule(&mv_tasklet);
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+       tasklet_schedule(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
 #else
        for (i = 0; i < core_nr; i++) {
                mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
@@ -225,7 +245,7 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
        if (mvi->flags & MVF_FLAG_SOC)
                slot_nr = MVS_SOC_SLOTS;
        else
-               slot_nr = MVS_SLOTS;
+               slot_nr = MVS_CHIP_SLOT_SZ;
 
        spin_lock_init(&mvi->lock);
        for (i = 0; i < mvi->chip->n_phy; i++) {
@@ -273,13 +293,18 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
                goto err_out;
        memset(mvi->slot, 0, sizeof(*mvi->slot) * slot_nr);
 
-#ifndef DISABLE_HOTPLUG_DMA_FIX
        mvi->bulk_buffer = dma_alloc_coherent(mvi->dev,
                                       TRASH_BUCKET_SIZE,
                                       &mvi->bulk_buffer_dma, GFP_KERNEL);
        if (!mvi->bulk_buffer)
                goto err_out;
-#endif
+
+       mvi->bulk_buffer1 = dma_alloc_coherent(mvi->dev,
+                                      TRASH_BUCKET_SIZE,
+                                      &mvi->bulk_buffer_dma1, GFP_KERNEL);
+       if (!mvi->bulk_buffer1)
+               goto err_out;
+
        sprintf(pool_name, "%s%d", "mvs_dma_pool", mvi->id);
        mvi->dma_pool = pci_pool_create(pool_name, mvi->pdev, MVS_SLOT_BUF_SZ, 16, 0);
        if (!mvi->dma_pool) {
@@ -354,11 +379,12 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
                                const struct pci_device_id *ent,
                                struct Scsi_Host *shost, unsigned int id)
 {
-       struct mvs_info *mvi;
+       struct mvs_info *mvi = NULL;
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
 
-       mvi = kzalloc(sizeof(*mvi) + MVS_SLOTS * sizeof(struct mvs_slot_info),
-                       GFP_KERNEL);
+       mvi = kzalloc(sizeof(*mvi) +
+               (1L << mvs_chips[ent->driver_data].slot_width) *
+               sizeof(struct mvs_slot_info), GFP_KERNEL);
        if (!mvi)
                return NULL;
 
@@ -367,7 +393,6 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
        mvi->chip_id = ent->driver_data;
        mvi->chip = &mvs_chips[mvi->chip_id];
        INIT_LIST_HEAD(&mvi->wq_list);
-       mvi->irq = pdev->irq;
 
        ((struct mvs_prv_info *)sha->lldd_ha)->mvi[id] = mvi;
        ((struct mvs_prv_info *)sha->lldd_ha)->n_phy = mvi->chip->n_phy;
@@ -375,9 +400,10 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
        mvi->id = id;
        mvi->sas = sha;
        mvi->shost = shost;
-#ifdef MVS_USE_TASKLET
-       tasklet_init(&mv_tasklet, mvs_tasklet, (unsigned long)sha);
-#endif
+
+       mvi->tags = kzalloc(MVS_CHIP_SLOT_SZ>>3, GFP_KERNEL);
+       if (!mvi->tags)
+               goto err_out;
 
        if (MVS_CHIP_DISP->chip_ioremap(mvi))
                goto err_out;
@@ -388,7 +414,6 @@ err_out:
        return NULL;
 }
 
-/* move to PCI layer or libata core? */
 static int pci_go_64(struct pci_dev *pdev)
 {
        int rc;
@@ -450,7 +475,7 @@ static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost,
        ((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr;
 
        shost->transportt = mvs_stt;
-       shost->max_id = 128;
+       shost->max_id = MVS_MAX_DEVICES;
        shost->max_lun = ~0;
        shost->max_channel = 1;
        shost->max_cmd_len = 16;
@@ -493,11 +518,12 @@ static void  __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost,
        if (mvi->flags & MVF_FLAG_SOC)
                can_queue = MVS_SOC_CAN_QUEUE;
        else
-               can_queue = MVS_CAN_QUEUE;
+               can_queue = MVS_CHIP_SLOT_SZ;
 
        sha->lldd_queue_size = can_queue;
+       shost->sg_tablesize = min_t(u16, SG_ALL, MVS_MAX_SG);
        shost->can_queue = can_queue;
-       mvi->shost->cmd_per_lun = MVS_SLOTS/sha->num_phys;
+       mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE;
        sha->core.shost = mvi->shost;
 }
 
@@ -518,6 +544,7 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev,
 {
        unsigned int rc, nhost = 0;
        struct mvs_info *mvi;
+       struct mvs_prv_info *mpi;
        irq_handler_t irq_handler = mvs_interrupt;
        struct Scsi_Host *shost = NULL;
        const struct mvs_chip_info *chip;
@@ -569,6 +596,9 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev,
                        goto err_out_regions;
                }
 
+               memset(&mvi->hba_info_param, 0xFF,
+                       sizeof(struct hba_info_page));
+
                mvs_init_sas_add(mvi);
 
                mvi->instance = nhost;
@@ -579,8 +609,9 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev,
                }
                nhost++;
        } while (nhost < chip->n_host);
-#ifdef MVS_USE_TASKLET
-       tasklet_init(&mv_tasklet, mvs_tasklet,
+       mpi = (struct mvs_prv_info *)(SHOST_TO_SAS_HA(shost)->lldd_ha);
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+       tasklet_init(&(mpi->mv_tasklet), mvs_tasklet,
                     (unsigned long)SHOST_TO_SAS_HA(shost));
 #endif
 
@@ -625,8 +656,8 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev)
        core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
        mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
 
-#ifdef MVS_USE_TASKLET
-       tasklet_kill(&mv_tasklet);
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+       tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
 #endif
 
        pci_set_drvdata(pdev, NULL);
@@ -635,7 +666,7 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev)
        scsi_remove_host(mvi->shost);
 
        MVS_CHIP_DISP->interrupt_disable(mvi);
-       free_irq(mvi->irq, sha);
+       free_irq(mvi->pdev->irq, sha);
        for (i = 0; i < core_nr; i++) {
                mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
                mvs_free(mvi);
@@ -703,6 +734,70 @@ static struct pci_driver mvs_pci_driver = {
        .remove         = __devexit_p(mvs_pci_remove),
 };
 
+static ssize_t
+mvs_show_driver_version(struct device *cdev,
+               struct device_attribute *attr,  char *buffer)
+{
+       return snprintf(buffer, PAGE_SIZE, "%s\n", DRV_VERSION);
+}
+
+static DEVICE_ATTR(driver_version,
+                        S_IRUGO,
+                        mvs_show_driver_version,
+                        NULL);
+
+static ssize_t
+mvs_store_interrupt_coalescing(struct device *cdev,
+                       struct device_attribute *attr,
+                       const char *buffer, size_t size)
+{
+       int val = 0;
+       struct mvs_info *mvi = NULL;
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+       u8 i, core_nr;
+       if (buffer == NULL)
+               return size;
+
+       if (sscanf(buffer, "%d", &val) != 1)
+               return -EINVAL;
+
+       if (val >= 0x10000) {
+               mv_dprintk("interrupt coalescing timer %d us is"
+                       "too long\n", val);
+               return strlen(buffer);
+       }
+
+       interrupt_coalescing = val;
+
+       core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
+       mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
+
+       if (unlikely(!mvi))
+               return -EINVAL;
+
+       for (i = 0; i < core_nr; i++) {
+               mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
+               if (MVS_CHIP_DISP->tune_interrupt)
+                       MVS_CHIP_DISP->tune_interrupt(mvi,
+                               interrupt_coalescing);
+       }
+       mv_dprintk("set interrupt coalescing time to %d us\n",
+               interrupt_coalescing);
+       return strlen(buffer);
+}
+
+static ssize_t mvs_show_interrupt_coalescing(struct device *cdev,
+                       struct device_attribute *attr, char *buffer)
+{
+       return snprintf(buffer, PAGE_SIZE, "%d\n", interrupt_coalescing);
+}
+
+static DEVICE_ATTR(interrupt_coalescing,
+                        S_IRUGO|S_IWUSR,
+                        mvs_show_interrupt_coalescing,
+                        mvs_store_interrupt_coalescing);
+
 /* task handler */
 struct task_struct *mvs_th;
 static int __init mvs_init(void)
@@ -739,6 +834,12 @@ static void __exit mvs_exit(void)
        kmem_cache_destroy(mvs_task_list_cache);
 }
 
+struct device_attribute *mvst_host_attrs[] = {
+       &dev_attr_driver_version,
+       &dev_attr_interrupt_coalescing,
+       NULL,
+};
+
 module_init(mvs_init);
 module_exit(mvs_exit);
 
index 0ef2742..4958fef 100644 (file)
@@ -38,7 +38,7 @@ static int mvs_find_tag(struct mvs_info *mvi, struct sas_task *task, u32 *tag)
 
 void mvs_tag_clear(struct mvs_info *mvi, u32 tag)
 {
-       void *bitmap = &mvi->tags;
+       void *bitmap = mvi->tags;
        clear_bit(tag, bitmap);
 }
 
@@ -49,14 +49,14 @@ void mvs_tag_free(struct mvs_info *mvi, u32 tag)
 
 void mvs_tag_set(struct mvs_info *mvi, unsigned int tag)
 {
-       void *bitmap = &mvi->tags;
+       void *bitmap = mvi->tags;
        set_bit(tag, bitmap);
 }
 
 inline int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out)
 {
        unsigned int index, tag;
-       void *bitmap = &mvi->tags;
+       void *bitmap = mvi->tags;
 
        index = find_first_zero_bit(bitmap, mvi->tags_num);
        tag = index;
@@ -74,126 +74,6 @@ void mvs_tag_init(struct mvs_info *mvi)
                mvs_tag_clear(mvi, i);
 }
 
-void mvs_hexdump(u32 size, u8 *data, u32 baseaddr)
-{
-       u32 i;
-       u32 run;
-       u32 offset;
-
-       offset = 0;
-       while (size) {
-               printk(KERN_DEBUG"%08X : ", baseaddr + offset);
-               if (size >= 16)
-                       run = 16;
-               else
-                       run = size;
-               size -= run;
-               for (i = 0; i < 16; i++) {
-                       if (i < run)
-                               printk(KERN_DEBUG"%02X ", (u32)data[i]);
-                       else
-                               printk(KERN_DEBUG"   ");
-               }
-               printk(KERN_DEBUG": ");
-               for (i = 0; i < run; i++)
-                       printk(KERN_DEBUG"%c",
-                               isalnum(data[i]) ? data[i] : '.');
-               printk(KERN_DEBUG"\n");
-               data = &data[16];
-               offset += run;
-       }
-       printk(KERN_DEBUG"\n");
-}
-
-#if (_MV_DUMP > 1)
-static void mvs_hba_sb_dump(struct mvs_info *mvi, u32 tag,
-                                  enum sas_protocol proto)
-{
-       u32 offset;
-       struct mvs_slot_info *slot = &mvi->slot_info[tag];
-
-       offset = slot->cmd_size + MVS_OAF_SZ +
-           MVS_CHIP_DISP->prd_size() * slot->n_elem;
-       dev_printk(KERN_DEBUG, mvi->dev, "+---->Status buffer[%d] :\n",
-                       tag);
-       mvs_hexdump(32, (u8 *) slot->response,
-                   (u32) slot->buf_dma + offset);
-}
-#endif
-
-static void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag,
-                               enum sas_protocol proto)
-{
-#if (_MV_DUMP > 1)
-       u32 sz, w_ptr;
-       u64 addr;
-       struct mvs_slot_info *slot = &mvi->slot_info[tag];
-
-       /*Delivery Queue */
-       sz = MVS_CHIP_SLOT_SZ;
-       w_ptr = slot->tx;
-       addr = mvi->tx_dma;
-       dev_printk(KERN_DEBUG, mvi->dev,
-               "Delivery Queue Size=%04d , WRT_PTR=%04X\n", sz, w_ptr);
-       dev_printk(KERN_DEBUG, mvi->dev,
-               "Delivery Queue Base Address=0x%llX (PA)"
-               "(tx_dma=0x%llX), Entry=%04d\n",
-               addr, (unsigned long long)mvi->tx_dma, w_ptr);
-       mvs_hexdump(sizeof(u32), (u8 *)(&mvi->tx[mvi->tx_prod]),
-                       (u32) mvi->tx_dma + sizeof(u32) * w_ptr);
-       /*Command List */
-       addr = mvi->slot_dma;
-       dev_printk(KERN_DEBUG, mvi->dev,
-               "Command List Base Address=0x%llX (PA)"
-               "(slot_dma=0x%llX), Header=%03d\n",
-               addr, (unsigned long long)slot->buf_dma, tag);
-       dev_printk(KERN_DEBUG, mvi->dev, "Command Header[%03d]:\n", tag);
-       /*mvs_cmd_hdr */
-       mvs_hexdump(sizeof(struct mvs_cmd_hdr), (u8 *)(&mvi->slot[tag]),
-               (u32) mvi->slot_dma + tag * sizeof(struct mvs_cmd_hdr));
-       /*1.command table area */
-       dev_printk(KERN_DEBUG, mvi->dev, "+---->Command Table :\n");
-       mvs_hexdump(slot->cmd_size, (u8 *) slot->buf, (u32) slot->buf_dma);
-       /*2.open address frame area */
-       dev_printk(KERN_DEBUG, mvi->dev, "+---->Open Address Frame :\n");
-       mvs_hexdump(MVS_OAF_SZ, (u8 *) slot->buf + slot->cmd_size,
-                               (u32) slot->buf_dma + slot->cmd_size);
-       /*3.status buffer */
-       mvs_hba_sb_dump(mvi, tag, proto);
-       /*4.PRD table */
-       dev_printk(KERN_DEBUG, mvi->dev, "+---->PRD table :\n");
-       mvs_hexdump(MVS_CHIP_DISP->prd_size() * slot->n_elem,
-               (u8 *) slot->buf + slot->cmd_size + MVS_OAF_SZ,
-               (u32) slot->buf_dma + slot->cmd_size + MVS_OAF_SZ);
-#endif
-}
-
-static void mvs_hba_cq_dump(struct mvs_info *mvi)
-{
-#if (_MV_DUMP > 2)
-       u64 addr;
-       void __iomem *regs = mvi->regs;
-       u32 entry = mvi->rx_cons + 1;
-       u32 rx_desc = le32_to_cpu(mvi->rx[entry]);
-
-       /*Completion Queue */
-       addr = mr32(RX_HI) << 16 << 16 | mr32(RX_LO);
-       dev_printk(KERN_DEBUG, mvi->dev, "Completion Task = 0x%p\n",
-                  mvi->slot_info[rx_desc & RXQ_SLOT_MASK].task);
-       dev_printk(KERN_DEBUG, mvi->dev,
-               "Completion List Base Address=0x%llX (PA), "
-               "CQ_Entry=%04d, CQ_WP=0x%08X\n",
-               addr, entry - 1, mvi->rx[0]);
-       mvs_hexdump(sizeof(u32), (u8 *)(&rx_desc),
-                   mvi->rx_dma + sizeof(u32) * entry);
-#endif
-}
-
-void mvs_get_sas_addr(void *buf, u32 buflen)
-{
-       /*memcpy(buf, "\x50\x05\x04\x30\x11\xab\x64\x40", 8);*/
-}
-
 struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev)
 {
        unsigned long i = 0, j = 0, hi = 0;
@@ -222,7 +102,6 @@ struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev)
 
 }
 
-/* FIXME */
 int mvs_find_dev_phyno(struct domain_device *dev, int *phyno)
 {
        unsigned long i = 0, j = 0, n = 0, num = 0;
@@ -253,6 +132,20 @@ int mvs_find_dev_phyno(struct domain_device *dev, int *phyno)
        return num;
 }
 
+struct mvs_device *mvs_find_dev_by_reg_set(struct mvs_info *mvi,
+                                               u8 reg_set)
+{
+       u32 dev_no;
+       for (dev_no = 0; dev_no < MVS_MAX_DEVICES; dev_no++) {
+               if (mvi->devices[dev_no].taskfileset == MVS_ID_NOT_MAPPED)
+                       continue;
+
+               if (mvi->devices[dev_no].taskfileset == reg_set)
+                       return &mvi->devices[dev_no];
+       }
+       return NULL;
+}
+
 static inline void mvs_free_reg_set(struct mvs_info *mvi,
                                struct mvs_device *dev)
 {
@@ -283,7 +176,6 @@ void mvs_phys_reset(struct mvs_info *mvi, u32 phy_mask, int hard)
        }
 }
 
-/* FIXME: locking? */
 int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
                        void *funcdata)
 {
@@ -309,12 +201,12 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
                tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id);
                if (tmp & PHY_RST_HARD)
                        break;
-               MVS_CHIP_DISP->phy_reset(mvi, phy_id, 1);
+               MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_HARD_RESET);
                break;
 
        case PHY_FUNC_LINK_RESET:
                MVS_CHIP_DISP->phy_enable(mvi, phy_id);
-               MVS_CHIP_DISP->phy_reset(mvi, phy_id, 0);
+               MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_SOFT_RESET);
                break;
 
        case PHY_FUNC_DISABLE:
@@ -406,14 +298,10 @@ int mvs_slave_configure(struct scsi_device *sdev)
 
        if (ret)
                return ret;
-       if (dev_is_sata(dev)) {
-               /* may set PIO mode */
-       #if MV_DISABLE_NCQ
-               struct ata_port *ap = dev->sata_dev.ap;
-               struct ata_device *adev = ap->link.device;
-               adev->flags |= ATA_DFLAG_NCQ_OFF;
-               scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, 1);
-       #endif
+       if (!dev_is_sata(dev)) {
+               sas_change_queue_depth(sdev,
+                       MVS_QUEUE_SIZE,
+                       SCSI_QDEPTH_DEFAULT);
        }
        return 0;
 }
@@ -424,6 +312,7 @@ void mvs_scan_start(struct Scsi_Host *shost)
        unsigned short core_nr;
        struct mvs_info *mvi;
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+       struct mvs_prv_info *mvs_prv = sha->lldd_ha;
 
        core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
 
@@ -432,15 +321,17 @@ void mvs_scan_start(struct Scsi_Host *shost)
                for (i = 0; i < mvi->chip->n_phy; ++i)
                        mvs_bytes_dmaed(mvi, i);
        }
+       mvs_prv->scan_finished = 1;
 }
 
 int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time)
 {
-       /* give the phy enabling interrupt event time to come in (1s
-        * is empirically about all it takes) */
-       if (time < HZ)
+       struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+       struct mvs_prv_info *mvs_prv = sha->lldd_ha;
+
+       if (mvs_prv->scan_finished == 0)
                return 0;
-       /* Wait for discovery to finish */
+
        scsi_flush_work(shost);
        return 1;
 }
@@ -461,10 +352,7 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,
        void *buf_prd;
        struct mvs_slot_info *slot = &mvi->slot_info[tag];
        u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT);
-#if _MV_DUMP
-       u8 *buf_cmd;
-       void *from;
-#endif
+
        /*
         * DMA-map SMP request, response buffers
         */
@@ -496,15 +384,7 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,
        buf_tmp = slot->buf;
        buf_tmp_dma = slot->buf_dma;
 
-#if _MV_DUMP
-       buf_cmd = buf_tmp;
-       hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma);
-       buf_tmp += req_len;
-       buf_tmp_dma += req_len;
-       slot->cmd_size = req_len;
-#else
        hdr->cmd_tbl = cpu_to_le64(sg_dma_address(sg_req));
-#endif
 
        /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
        buf_oaf = buf_tmp;
@@ -553,12 +433,6 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,
        /* fill in PRD (scatter/gather) table, if any */
        MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd);
 
-#if _MV_DUMP
-       /* copy cmd table */
-       from = kmap_atomic(sg_page(sg_req), KM_IRQ0);
-       memcpy(buf_cmd, from + sg_req->offset, req_len);
-       kunmap_atomic(from, KM_IRQ0);
-#endif
        return 0;
 
 err_out_2:
@@ -616,14 +490,11 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
                (mvi_dev->taskfileset << TXQ_SRS_SHIFT);
        mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q);
 
-#ifndef DISABLE_HOTPLUG_DMA_FIX
        if (task->data_dir == DMA_FROM_DEVICE)
                flags = (MVS_CHIP_DISP->prd_count() << MCH_PRD_LEN_SHIFT);
        else
                flags = (tei->n_elem << MCH_PRD_LEN_SHIFT);
-#else
-       flags = (tei->n_elem << MCH_PRD_LEN_SHIFT);
-#endif
+
        if (task->ata_task.use_ncq)
                flags |= MCH_FPDMA;
        if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) {
@@ -631,11 +502,8 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
                        flags |= MCH_ATAPI;
        }
 
-       /* FIXME: fill in port multiplier number */
-
        hdr->flags = cpu_to_le32(flags);
 
-       /* FIXME: the low order order 5 bits for the TAG if enable NCQ */
        if (task->ata_task.use_ncq && mvs_get_ncq_tag(task, &hdr_tag))
                task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
        else
@@ -657,9 +525,6 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
 
        buf_tmp += MVS_ATA_CMD_SZ;
        buf_tmp_dma += MVS_ATA_CMD_SZ;
-#if _MV_DUMP
-       slot->cmd_size = MVS_ATA_CMD_SZ;
-#endif
 
        /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
        /* used for STP.  unused for SATA? */
@@ -682,9 +547,6 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
        buf_tmp_dma += i;
 
        /* region 4: status buffer (larger the PRD, smaller this buf) ****** */
-       /* FIXME: probably unused, for SATA.  kept here just in case
-        * we get a STP/SATA error information record
-        */
        slot->response = buf_tmp;
        hdr->status_buf = cpu_to_le64(buf_tmp_dma);
        if (mvi->flags & MVF_FLAG_SOC)
@@ -715,11 +577,11 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
 
        /* fill in PRD (scatter/gather) table, if any */
        MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd);
-#ifndef DISABLE_HOTPLUG_DMA_FIX
+
        if (task->data_dir == DMA_FROM_DEVICE)
-               MVS_CHIP_DISP->dma_fix(mvi->bulk_buffer_dma,
+               MVS_CHIP_DISP->dma_fix(mvi, sas_port->phy_mask,
                                TRASH_BUCKET_SIZE, tei->n_elem, buf_prd);
-#endif
+
        return 0;
 }
 
@@ -761,6 +623,9 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
        }
        if (is_tmf)
                flags |= (MCH_SSP_FR_TASK << MCH_SSP_FR_TYPE_SHIFT);
+       else
+               flags |= (MCH_SSP_FR_CMD << MCH_SSP_FR_TYPE_SHIFT);
+
        hdr->flags = cpu_to_le32(flags | (tei->n_elem << MCH_PRD_LEN_SHIFT));
        hdr->tags = cpu_to_le32(tag);
        hdr->data_len = cpu_to_le32(task->total_xfer_len);
@@ -777,9 +642,6 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
 
        buf_tmp += MVS_SSP_CMD_SZ;
        buf_tmp_dma += MVS_SSP_CMD_SZ;
-#if _MV_DUMP
-       slot->cmd_size = MVS_SSP_CMD_SZ;
-#endif
 
        /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
        buf_oaf = buf_tmp;
@@ -986,7 +848,6 @@ static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf
        task->task_state_flags |= SAS_TASK_AT_INITIATOR;
        spin_unlock(&task->task_state_lock);
 
-       mvs_hba_memory_dump(mvi, tag, task->task_proto);
        mvi_dev->running_req++;
        ++(*pass);
        mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
@@ -1189,9 +1050,9 @@ static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task,
        mvs_slot_free(mvi, slot_idx);
 }
 
-static void mvs_update_wideport(struct mvs_info *mvi, int i)
+static void mvs_update_wideport(struct mvs_info *mvi, int phy_no)
 {
-       struct mvs_phy *phy = &mvi->phy[i];
+       struct mvs_phy *phy = &mvi->phy[phy_no];
        struct mvs_port *port = phy->port;
        int j, no;
 
@@ -1246,18 +1107,17 @@ static void *mvs_get_d2h_reg(struct mvs_info *mvi, int i, void *buf)
                return NULL;
 
        MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG3);
-       s[3] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
+       s[3] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
 
        MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG2);
-       s[2] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
+       s[2] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
 
        MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG1);
-       s[1] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
+       s[1] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
 
        MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG0);
-       s[0] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
+       s[0] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
 
-       /* Workaround: take some ATAPI devices for ATA */
        if (((s[1] & 0x00FFFFFF) == 0x00EB1401) && (*(u8 *)&s[3] == 0x01))
                s[1] = 0x00EB1401 | (*((u8 *)&s[1] + 3) & 0x10);
 
@@ -1269,6 +1129,13 @@ static u32 mvs_is_sig_fis_received(u32 irq_status)
        return irq_status & PHYEV_SIG_FIS;
 }
 
+static void mvs_sig_remove_timer(struct mvs_phy *phy)
+{
+       if (phy->timer.function)
+               del_timer(&phy->timer);
+       phy->timer.function = NULL;
+}
+
 void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
 {
        struct mvs_phy *phy = &mvi->phy[i];
@@ -1291,6 +1158,7 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
                if (phy->phy_type & PORT_TYPE_SATA) {
                        phy->identify.target_port_protocols = SAS_PROTOCOL_STP;
                        if (mvs_is_sig_fis_received(phy->irq_status)) {
+                               mvs_sig_remove_timer(phy);
                                phy->phy_attached = 1;
                                phy->att_dev_sas_addr =
                                        i + mvi->id * mvi->chip->n_phy;
@@ -1308,7 +1176,6 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
                                                tmp | PHYEV_SIG_FIS);
                                phy->phy_attached = 0;
                                phy->phy_type &= ~PORT_TYPE_SATA;
-                               MVS_CHIP_DISP->phy_reset(mvi, i, 0);
                                goto out_done;
                        }
                }       else if (phy->phy_type & PORT_TYPE_SAS
@@ -1334,9 +1201,9 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
                if (MVS_CHIP_DISP->phy_work_around)
                        MVS_CHIP_DISP->phy_work_around(mvi, i);
        }
-       mv_dprintk("port %d attach dev info is %x\n",
+       mv_dprintk("phy %d attach dev info is %x\n",
                i + mvi->id * mvi->chip->n_phy, phy->att_dev_info);
-       mv_dprintk("port %d attach sas addr is %llx\n",
+       mv_dprintk("phy %d attach sas addr is %llx\n",
                i + mvi->id * mvi->chip->n_phy, phy->att_dev_sas_addr);
 out_done:
        if (get_st)
@@ -1361,10 +1228,10 @@ static void mvs_port_notify_formed(struct asd_sas_phy *sas_phy, int lock)
        }
        hi = i/((struct mvs_prv_info *)sas_ha->lldd_ha)->n_phy;
        mvi = ((struct mvs_prv_info *)sas_ha->lldd_ha)->mvi[hi];
-       if (sas_port->id >= mvi->chip->n_phy)
-               port = &mvi->port[sas_port->id - mvi->chip->n_phy];
+       if (i >= mvi->chip->n_phy)
+               port = &mvi->port[i - mvi->chip->n_phy];
        else
-               port = &mvi->port[sas_port->id];
+               port = &mvi->port[i];
        if (lock)
                spin_lock_irqsave(&mvi->lock, flags);
        port->port_attached = 1;
@@ -1393,7 +1260,7 @@ static void mvs_port_notify_deformed(struct asd_sas_phy *sas_phy, int lock)
                        return;
        }
        list_for_each_entry(dev, &port->dev_list, dev_list_node)
-               mvs_do_release_task(phy->mvi, phy_no, NULL);
+               mvs_do_release_task(phy->mvi, phy_no, dev);
 
 }
 
@@ -1457,6 +1324,7 @@ int mvs_dev_found_notify(struct domain_device *dev, int lock)
        mvi_device->dev_status = MVS_DEV_NORMAL;
        mvi_device->dev_type = dev->dev_type;
        mvi_device->mvi_info = mvi;
+       mvi_device->sas_device = dev;
        if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) {
                int phy_id;
                u8 phy_num = parent_dev->ex_dev.num_phys;
@@ -1508,6 +1376,7 @@ void mvs_dev_gone_notify(struct domain_device *dev)
                mv_dprintk("found dev has gone.\n");
        }
        dev->lldd_dev = NULL;
+       mvi_dev->sas_device = NULL;
 
        spin_unlock_irqrestore(&mvi->lock, flags);
 }
@@ -1555,7 +1424,6 @@ static void mvs_tmf_timedout(unsigned long data)
        complete(&task->completion);
 }
 
-/* XXX */
 #define MVS_TASK_TIMEOUT 20
 static int mvs_exec_internal_tmf_task(struct domain_device *dev,
                        void *parameter, u32 para_len, struct mvs_tmf_task *tmf)
@@ -1588,7 +1456,7 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
                }
 
                wait_for_completion(&task->completion);
-               res = -TMF_RESP_FUNC_FAILED;
+               res = TMF_RESP_FUNC_FAILED;
                /* Even TMF timed out, return direct. */
                if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
                        if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
@@ -1638,11 +1506,10 @@ static int mvs_debug_issue_ssp_tmf(struct domain_device *dev,
                                u8 *lun, struct mvs_tmf_task *tmf)
 {
        struct sas_ssp_task ssp_task;
-       DECLARE_COMPLETION_ONSTACK(completion);
        if (!(dev->tproto & SAS_PROTOCOL_SSP))
                return TMF_RESP_FUNC_ESUPP;
 
-       strncpy((u8 *)&ssp_task.LUN, lun, 8);
+       memcpy(ssp_task.LUN, lun, 8);
 
        return mvs_exec_internal_tmf_task(dev, &ssp_task,
                                sizeof(ssp_task), tmf);
@@ -1666,7 +1533,7 @@ static int mvs_debug_I_T_nexus_reset(struct domain_device *dev)
 int mvs_lu_reset(struct domain_device *dev, u8 *lun)
 {
        unsigned long flags;
-       int i, phyno[WIDE_PORT_MAX_PHY], num , rc = TMF_RESP_FUNC_FAILED;
+       int rc = TMF_RESP_FUNC_FAILED;
        struct mvs_tmf_task tmf_task;
        struct mvs_device * mvi_dev = dev->lldd_dev;
        struct mvs_info *mvi = mvi_dev->mvi_info;
@@ -1675,10 +1542,8 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun)
        mvi_dev->dev_status = MVS_DEV_EH;
        rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task);
        if (rc == TMF_RESP_FUNC_COMPLETE) {
-               num = mvs_find_dev_phyno(dev, phyno);
                spin_lock_irqsave(&mvi->lock, flags);
-               for (i = 0; i < num; i++)
-                       mvs_release_task(mvi, dev);
+               mvs_release_task(mvi, dev);
                spin_unlock_irqrestore(&mvi->lock, flags);
        }
        /* If failed, fall-through I_T_Nexus reset */
@@ -1696,11 +1561,12 @@ int mvs_I_T_nexus_reset(struct domain_device *dev)
 
        if (mvi_dev->dev_status != MVS_DEV_EH)
                return TMF_RESP_FUNC_COMPLETE;
+       else
+               mvi_dev->dev_status = MVS_DEV_NORMAL;
        rc = mvs_debug_I_T_nexus_reset(dev);
        mv_printk("%s for device[%x]:rc= %d\n",
                __func__, mvi_dev->device_id, rc);
 
-       /* housekeeper */
        spin_lock_irqsave(&mvi->lock, flags);
        mvs_release_task(mvi, dev);
        spin_unlock_irqrestore(&mvi->lock, flags);
@@ -1739,9 +1605,6 @@ int mvs_query_task(struct sas_task *task)
                case TMF_RESP_FUNC_FAILED:
                case TMF_RESP_FUNC_COMPLETE:
                        break;
-               default:
-                       rc = TMF_RESP_FUNC_COMPLETE;
-                       break;
                }
        }
        mv_printk("%s:rc= %d\n", __func__, rc);
@@ -1761,8 +1624,8 @@ int mvs_abort_task(struct sas_task *task)
        u32 tag;
 
        if (!mvi_dev) {
-               mv_printk("%s:%d TMF_RESP_FUNC_FAILED\n", __func__, __LINE__);
-               rc = TMF_RESP_FUNC_FAILED;
+               mv_printk("Device has removed\n");
+               return TMF_RESP_FUNC_FAILED;
        }
 
        mvi = mvi_dev->mvi_info;
@@ -1807,25 +1670,17 @@ int mvs_abort_task(struct sas_task *task)
 
        } else if (task->task_proto & SAS_PROTOCOL_SATA ||
                task->task_proto & SAS_PROTOCOL_STP) {
-               /* to do free register_set */
                if (SATA_DEV == dev->dev_type) {
                        struct mvs_slot_info *slot = task->lldd_task;
-                       struct task_status_struct *tstat;
                        u32 slot_idx = (u32)(slot - mvi->slot_info);
-                       tstat = &task->task_status;
-                       mv_dprintk(KERN_DEBUG "mv_abort_task() mvi=%p task=%p "
+                       mv_dprintk("mvs_abort_task() mvi=%p task=%p "
                                   "slot=%p slot_idx=x%x\n",
                                   mvi, task, slot, slot_idx);
-                       tstat->stat = SAS_ABORTED_TASK;
-                       if (mvi_dev && mvi_dev->running_req)
-                               mvi_dev->running_req--;
-                       if (sas_protocol_ata(task->task_proto))
-                               mvs_free_reg_set(mvi, mvi_dev);
+                       mvs_tmf_timedout((unsigned long)task);
                        mvs_slot_task_free(mvi, task, slot, slot_idx);
-                       return -1;
+                       rc = TMF_RESP_FUNC_COMPLETE;
+                       goto out;
                }
-       } else {
-               /* SMP */
 
        }
 out:
@@ -1891,12 +1746,63 @@ static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task,
        return stat;
 }
 
+void mvs_set_sense(u8 *buffer, int len, int d_sense,
+               int key, int asc, int ascq)
+{
+       memset(buffer, 0, len);
+
+       if (d_sense) {
+               /* Descriptor format */
+               if (len < 4) {
+                       mv_printk("Length %d of sense buffer too small to "
+                               "fit sense %x:%x:%x", len, key, asc, ascq);
+               }
+
+               buffer[0] = 0x72;               /* Response Code        */
+               if (len > 1)
+                       buffer[1] = key;        /* Sense Key */
+               if (len > 2)
+                       buffer[2] = asc;        /* ASC  */
+               if (len > 3)
+                       buffer[3] = ascq;       /* ASCQ */
+       } else {
+               if (len < 14) {
+                       mv_printk("Length %d of sense buffer too small to "
+                               "fit sense %x:%x:%x", len, key, asc, ascq);
+               }
+
+               buffer[0] = 0x70;               /* Response Code        */
+               if (len > 2)
+                       buffer[2] = key;        /* Sense Key */
+               if (len > 7)
+                       buffer[7] = 0x0a;       /* Additional Sense Length */
+               if (len > 12)
+                       buffer[12] = asc;       /* ASC */
+               if (len > 13)
+                       buffer[13] = ascq; /* ASCQ */
+       }
+
+       return;
+}
+
+void mvs_fill_ssp_resp_iu(struct ssp_response_iu *iu,
+                               u8 key, u8 asc, u8 asc_q)
+{
+       iu->datapres = 2;
+       iu->response_data_len = 0;
+       iu->sense_data_len = 17;
+       iu->status = 02;
+       mvs_set_sense(iu->sense_data, 17, 0,
+                       key, asc, asc_q);
+}
+
 static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
                         u32 slot_idx)
 {
        struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
        int stat;
-       u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response));
+       u32 err_dw0 = le32_to_cpu(*(u32 *)slot->response);
+       u32 err_dw1 = le32_to_cpu(*((u32 *)slot->response + 1));
        u32 tfs = 0;
        enum mvs_port_type type = PORT_TYPE_SAS;
 
@@ -1908,8 +1814,19 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
        stat = SAM_STAT_CHECK_CONDITION;
        switch (task->task_proto) {
        case SAS_PROTOCOL_SSP:
+       {
                stat = SAS_ABORTED_TASK;
+               if ((err_dw0 & NO_DEST) || err_dw1 & bit(31)) {
+                       struct ssp_response_iu *iu = slot->response +
+                               sizeof(struct mvs_err_info);
+                       mvs_fill_ssp_resp_iu(iu, NOT_READY, 0x04, 01);
+                       sas_ssp_task_response(mvi->dev, task, iu);
+                       stat = SAM_STAT_CHECK_CONDITION;
+               }
+               if (err_dw1 & bit(31))
+                       mv_printk("reuse same slot, retry command.\n");
                break;
+       }
        case SAS_PROTOCOL_SMP:
                stat = SAM_STAT_CHECK_CONDITION;
                break;
@@ -1918,10 +1835,8 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
        case SAS_PROTOCOL_STP:
        case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
        {
-               if (err_dw0 == 0x80400002)
-                       mv_printk("find reserved error, why?\n");
-
                task->ata_task.use_ncq = 0;
+               stat = SAS_PROTO_RESPONSE;
                mvs_sata_done(mvi, task, slot_idx, err_dw0);
        }
                break;
@@ -1945,8 +1860,6 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
        void *to;
        enum exec_status sts;
 
-       if (mvi->exp_req)
-               mvi->exp_req--;
        if (unlikely(!task || !task->lldd_task || !task->dev))
                return -1;
 
@@ -1954,8 +1867,6 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
        dev = task->dev;
        mvi_dev = dev->lldd_dev;
 
-       mvs_hba_cq_dump(mvi);
-
        spin_lock(&task->task_state_lock);
        task->task_state_flags &=
                ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
@@ -1978,6 +1889,7 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
                return -1;
        }
 
+       /* when no device attaching, go ahead and complete by error handling*/
        if (unlikely(!mvi_dev || flags)) {
                if (!mvi_dev)
                        mv_dprintk("port has not device.\n");
@@ -1987,6 +1899,9 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
 
        /* error info record present */
        if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) {
+               mv_dprintk("port %d slot %d rx_desc %X has error info"
+                       "%016llX.\n", slot->port->sas_port.id, slot_idx,
+                        rx_desc, (u64)(*(u64 *)slot->response));
                tstat->stat = mvs_slot_err(mvi, task, slot_idx);
                tstat->resp = SAS_TASK_COMPLETE;
                goto out;
@@ -2048,8 +1963,7 @@ out:
        spin_unlock(&mvi->lock);
        if (task->task_done)
                task->task_done(task);
-       else
-               mv_dprintk("why has not task_done.\n");
+
        spin_lock(&mvi->lock);
 
        return sts;
@@ -2092,7 +2006,6 @@ void mvs_release_task(struct mvs_info *mvi,
                      struct domain_device *dev)
 {
        int i, phyno[WIDE_PORT_MAX_PHY], num;
-       /* housekeeper */
        num = mvs_find_dev_phyno(dev, phyno);
        for (i = 0; i < num; i++)
                mvs_do_release_task(mvi, phyno[i], dev);
@@ -2111,13 +2024,13 @@ static void mvs_work_queue(struct work_struct *work)
        struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q);
        struct mvs_info *mvi = mwq->mvi;
        unsigned long flags;
+       u32 phy_no = (unsigned long) mwq->data;
+       struct sas_ha_struct *sas_ha = mvi->sas;
+       struct mvs_phy *phy = &mvi->phy[phy_no];
+       struct asd_sas_phy *sas_phy = &phy->sas_phy;
 
        spin_lock_irqsave(&mvi->lock, flags);
        if (mwq->handler & PHY_PLUG_EVENT) {
-               u32 phy_no = (unsigned long) mwq->data;
-               struct sas_ha_struct *sas_ha = mvi->sas;
-               struct mvs_phy *phy = &mvi->phy[phy_no];
-               struct asd_sas_phy *sas_phy = &phy->sas_phy;
 
                if (phy->phy_event & PHY_PLUG_OUT) {
                        u32 tmp;
@@ -2139,6 +2052,11 @@ static void mvs_work_queue(struct work_struct *work)
                                mv_dprintk("phy%d Attached Device\n", phy_no);
                        }
                }
+       } else if (mwq->handler & EXP_BRCT_CHG) {
+               phy->phy_event &= ~EXP_BRCT_CHG;
+               sas_ha->notify_port_event(sas_phy,
+                               PORTE_BROADCAST_RCVD);
+               mv_dprintk("phy%d Got Broadcast Change\n", phy_no);
        }
        list_del(&mwq->entry);
        spin_unlock_irqrestore(&mvi->lock, flags);
@@ -2174,29 +2092,21 @@ static void mvs_sig_time_out(unsigned long tphy)
                if (&mvi->phy[phy_no] == phy) {
                        mv_dprintk("Get signature time out, reset phy %d\n",
                                phy_no+mvi->id*mvi->chip->n_phy);
-                       MVS_CHIP_DISP->phy_reset(mvi, phy_no, 1);
+                       MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_HARD_RESET);
                }
        }
 }
 
-static void mvs_sig_remove_timer(struct mvs_phy *phy)
-{
-       if (phy->timer.function)
-               del_timer(&phy->timer);
-       phy->timer.function = NULL;
-}
-
 void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
 {
        u32 tmp;
-       struct sas_ha_struct *sas_ha = mvi->sas;
        struct mvs_phy *phy = &mvi->phy[phy_no];
-       struct asd_sas_phy *sas_phy = &phy->sas_phy;
 
        phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no);
-       mv_dprintk("port %d ctrl sts=0x%X.\n", phy_no+mvi->id*mvi->chip->n_phy,
+       MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status);
+       mv_dprintk("phy %d ctrl sts=0x%08X.\n", phy_no+mvi->id*mvi->chip->n_phy,
                MVS_CHIP_DISP->read_phy_ctl(mvi, phy_no));
-       mv_dprintk("Port %d irq sts = 0x%X\n", phy_no+mvi->id*mvi->chip->n_phy,
+       mv_dprintk("phy %d irq sts = 0x%08X\n", phy_no+mvi->id*mvi->chip->n_phy,
                phy->irq_status);
 
        /*
@@ -2205,11 +2115,12 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
        */
 
        if (phy->irq_status & PHYEV_DCDR_ERR) {
-               mv_dprintk("port %d STP decoding error.\n",
+               mv_dprintk("phy %d STP decoding error.\n",
                phy_no + mvi->id*mvi->chip->n_phy);
        }
 
        if (phy->irq_status & PHYEV_POOF) {
+               mdelay(500);
                if (!(phy->phy_event & PHY_PLUG_OUT)) {
                        int dev_sata = phy->phy_type & PORT_TYPE_SATA;
                        int ready;
@@ -2220,17 +2131,13 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
                                (void *)(unsigned long)phy_no,
                                PHY_PLUG_EVENT);
                        ready = mvs_is_phy_ready(mvi, phy_no);
-                       if (!ready)
-                               mv_dprintk("phy%d Unplug Notice\n",
-                                       phy_no +
-                                       mvi->id * mvi->chip->n_phy);
                        if (ready || dev_sata) {
                                if (MVS_CHIP_DISP->stp_reset)
                                        MVS_CHIP_DISP->stp_reset(mvi,
                                                        phy_no);
                                else
                                        MVS_CHIP_DISP->phy_reset(mvi,
-                                                       phy_no, 0);
+                                                       phy_no, MVS_SOFT_RESET);
                                return;
                        }
                }
@@ -2243,13 +2150,12 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
                if (phy->timer.function == NULL) {
                        phy->timer.data = (unsigned long)phy;
                        phy->timer.function = mvs_sig_time_out;
-                       phy->timer.expires = jiffies + 10*HZ;
+                       phy->timer.expires = jiffies + 5*HZ;
                        add_timer(&phy->timer);
                }
        }
        if (phy->irq_status & (PHYEV_SIG_FIS | PHYEV_ID_DONE)) {
                phy->phy_status = mvs_is_phy_ready(mvi, phy_no);
-               mvs_sig_remove_timer(phy);
                mv_dprintk("notify plug in on phy[%d]\n", phy_no);
                if (phy->phy_status) {
                        mdelay(10);
@@ -2263,14 +2169,14 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
                        }
                        mvs_update_phyinfo(mvi, phy_no, 0);
                        if (phy->phy_type & PORT_TYPE_SAS) {
-                               MVS_CHIP_DISP->phy_reset(mvi, phy_no, 2);
+                               MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_PHY_TUNE);
                                mdelay(10);
                        }
 
                        mvs_bytes_dmaed(mvi, phy_no);
                        /* whether driver is going to handle hot plug */
                        if (phy->phy_event & PHY_PLUG_OUT) {
-                               mvs_port_notify_formed(sas_phy, 0);
+                               mvs_port_notify_formed(&phy->sas_phy, 0);
                                phy->phy_event &= ~PHY_PLUG_OUT;
                        }
                } else {
@@ -2278,13 +2184,11 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
                                phy_no + mvi->id*mvi->chip->n_phy);
                }
        } else if (phy->irq_status & PHYEV_BROAD_CH) {
-               mv_dprintk("port %d broadcast change.\n",
+               mv_dprintk("phy %d broadcast change.\n",
                        phy_no + mvi->id*mvi->chip->n_phy);
-               /* exception for Samsung disk drive*/
-               mdelay(1000);
-               sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+               mvs_handle_event(mvi, (void *)(unsigned long)phy_no,
+                               EXP_BRCT_CHG);
        }
-       MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status);
 }
 
 int mvs_int_rx(struct mvs_info *mvi, bool self_clear)
index 1367d8b..44d7885 100644 (file)
 
 #define DRV_NAME               "mvsas"
 #define DRV_VERSION            "0.8.2"
-#define _MV_DUMP               0
 #define MVS_ID_NOT_MAPPED      0x7f
-/* #define DISABLE_HOTPLUG_DMA_FIX */
-// #define MAX_EXP_RUNNING_REQ 2
 #define WIDE_PORT_MAX_PHY              4
-#define        MV_DISABLE_NCQ  0
 #define mv_printk(fmt, arg ...)        \
        printk(KERN_DEBUG"%s %d:" fmt, __FILE__, __LINE__, ## arg)
 #ifdef MV_DEBUG
@@ -64,6 +60,7 @@
 #endif
 #define MV_MAX_U32                     0xffffffff
 
+extern int interrupt_coalescing;
 extern struct mvs_tgt_initiator mvs_tgt;
 extern struct mvs_info *tgt_mvi;
 extern const struct mvs_dispatch mvs_64xx_dispatch;
@@ -99,6 +96,11 @@ enum dev_status {
        MVS_DEV_EH      = 0x1,
 };
 
+enum dev_reset {
+       MVS_SOFT_RESET  = 0,
+       MVS_HARD_RESET  = 1,
+       MVS_PHY_TUNE    = 2,
+};
 
 struct mvs_info;
 
@@ -130,7 +132,6 @@ struct mvs_dispatch {
        u32 (*read_port_irq_mask)(struct mvs_info *mvi, u32 port);
        void (*write_port_irq_mask)(struct mvs_info *mvi, u32 port, u32 val);
 
-       void (*get_sas_addr)(void *buf, u32 buflen);
        void (*command_active)(struct mvs_info *mvi, u32 slot_idx);
        void (*clear_srs_irq)(struct mvs_info *mvi, u8 reg_set, u8 clear_all);
        void (*issue_stop)(struct mvs_info *mvi, enum mvs_port_type type,
@@ -167,9 +168,10 @@ struct mvs_dispatch {
                                                );
        int (*spi_issuecmd)(struct mvs_info *mvi, u32 cmd);
        int (*spi_waitdataready)(struct mvs_info *mvi, u32 timeout);
-#ifndef DISABLE_HOTPLUG_DMA_FIX
-       void (*dma_fix)(dma_addr_t buf_dma, int buf_len, int from, void *prd);
-#endif
+       void (*dma_fix)(struct mvs_info *mvi, u32 phy_mask,
+                               int buf_len, int from, void *prd);
+       void (*tune_interrupt)(struct mvs_info *mvi, u32 time);
+       void (*non_spec_ncq_error)(struct mvs_info *mvi);
 
 };
 
@@ -179,9 +181,11 @@ struct mvs_chip_info {
        u32             fis_offs;
        u32             fis_count;
        u32             srs_sz;
+       u32             sg_width;
        u32             slot_width;
        const struct mvs_dispatch *dispatch;
 };
+#define MVS_MAX_SG             (1U << mvi->chip->sg_width)
 #define MVS_CHIP_SLOT_SZ       (1U << mvi->chip->slot_width)
 #define MVS_RX_FISL_SZ         \
        (mvi->chip->fis_offs + (mvi->chip->fis_count * 0x100))
@@ -249,6 +253,73 @@ struct mvs_device {
        u16 reserved;
 };
 
+/* Generate  PHY tunning parameters */
+struct phy_tuning {
+       /* 1 bit,  transmitter emphasis enable  */
+       u8      trans_emp_en:1;
+       /* 4 bits, transmitter emphasis amplitude */
+       u8      trans_emp_amp:4;
+       /* 3 bits, reserved space */
+       u8      Reserved_2bit_1:3;
+       /* 5 bits, transmitter amplitude */
+       u8      trans_amp:5;
+       /* 2 bits, transmitter amplitude adjust */
+       u8      trans_amp_adj:2;
+       /* 1 bit, reserved space */
+       u8      resv_2bit_2:1;
+       /* 2 bytes, reserved space */
+       u8      reserved[2];
+};
+
+struct ffe_control {
+       /* 4 bits,  FFE Capacitor Select  (value range 0~F)  */
+       u8 ffe_cap_sel:4;
+       /* 3 bits,  FFE Resistor Select (value range 0~7) */
+       u8 ffe_rss_sel:3;
+       /* 1 bit reserve*/
+       u8 reserved:1;
+};
+
+/*
+ * HBA_Info_Page is saved in Flash/NVRAM, total 256 bytes.
+ * The data area is valid only Signature="MRVL".
+ * If any member fills with 0xFF, the member is invalid.
+ */
+struct hba_info_page {
+       /* Dword 0 */
+       /* 4 bytes, structure signature,should be "MRVL" at first initial */
+       u8 signature[4];
+
+       /* Dword 1-13 */
+       u32 reserved1[13];
+
+       /* Dword 14-29 */
+       /* 64 bytes, SAS address for each port */
+       u64 sas_addr[8];
+
+       /* Dword 30-31 */
+       /* 8 bytes for vanir 8 port PHY FFE seeting
+        * BIT 0~3 : FFE Capacitor select(value range 0~F)
+        * BIT 4~6 : FFE Resistor select(value range 0~7)
+        * BIT 7: reserve.
+        */
+
+       struct ffe_control  ffe_ctl[8];
+       /* Dword 32 -43 */
+       u32 reserved2[12];
+
+       /* Dword 44-45 */
+       /* 8 bytes,  0:  1.5G, 1: 3.0G, should be 0x01 at first initial */
+       u8 phy_rate[8];
+
+       /* Dword 46-53 */
+       /* 32 bytes, PHY tuning parameters for each PHY*/
+       struct phy_tuning   phy_tuning[8];
+
+       /* Dword 54-63 */
+       u32 reserved3[10];
+};     /* total 256 bytes */
+
 struct mvs_slot_info {
        struct list_head entry;
        union {
@@ -264,9 +335,6 @@ struct mvs_slot_info {
         */
        void *buf;
        dma_addr_t buf_dma;
-#if _MV_DUMP
-       u32 cmd_size;
-#endif
        void *response;
        struct mvs_port *port;
        struct mvs_device       *device;
@@ -320,12 +388,10 @@ struct mvs_info {
        const struct mvs_chip_info *chip;
 
        int tags_num;
-       DECLARE_BITMAP(tags, MVS_SLOTS);
+       unsigned long *tags;
        /* further per-slot information */
        struct mvs_phy phy[MVS_MAX_PHYS];
        struct mvs_port port[MVS_MAX_PHYS];
-       u32 irq;
-       u32 exp_req;
        u32 id;
        u64 sata_reg_set;
        struct list_head *hba_list;
@@ -337,12 +403,13 @@ struct mvs_info {
        u32 flashsectSize;
 
        void *addon;
+       struct hba_info_page hba_info_param;
        struct mvs_device       devices[MVS_MAX_DEVICES];
-#ifndef DISABLE_HOTPLUG_DMA_FIX
        void *bulk_buffer;
        dma_addr_t bulk_buffer_dma;
+       void *bulk_buffer1;
+       dma_addr_t bulk_buffer_dma1;
 #define TRASH_BUCKET_SIZE      0x20000
-#endif
        void *dma_pool;
        struct mvs_slot_info slot_info[0];
 };
@@ -350,8 +417,10 @@ struct mvs_info {
 struct mvs_prv_info{
        u8 n_host;
        u8 n_phy;
-       u16 reserve;
+       u8 scan_finished;
+       u8 reserve;
        struct mvs_info *mvi[2];
+       struct tasklet_struct mv_tasklet;
 };
 
 struct mvs_wq {
@@ -415,6 +484,6 @@ void mvs_do_release_task(struct mvs_info *mvi, int phy_no,
 void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events);
 void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st);
 int mvs_int_rx(struct mvs_info *mvi, bool self_clear);
-void mvs_hexdump(u32 size, u8 *data, u32 baseaddr);
+struct mvs_device *mvs_find_dev_by_reg_set(struct mvs_info *mvi, u8 reg_set);
 #endif
 
index fca6a89..d079f9a 100644 (file)
@@ -3871,6 +3871,9 @@ static long pmcraid_ioctl_passthrough(
                        pmcraid_err("couldn't build passthrough ioadls\n");
                        goto out_free_buffer;
                }
+       } else if (request_size < 0) {
+               rc = -EINVAL;
+               goto out_free_buffer;
        }
 
        /* If data is being written into the device, copy the data from user
index 532313e..7836eb0 100644 (file)
@@ -42,8 +42,8 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
        int reading;
 
        if (IS_QLA82XX(ha)) {
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                       "Firmware dump not supported for ISP82xx\n"));
+               ql_dbg(ql_dbg_user, vha, 0x705b,
+                   "Firmware dump not supported for ISP82xx\n");
                return count;
        }
 
@@ -56,7 +56,7 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
                if (!ha->fw_dump_reading)
                        break;
 
-               qla_printk(KERN_INFO, ha,
+               ql_log(ql_log_info, vha, 0x705d,
                    "Firmware dump cleared on (%ld).\n", vha->host_no);
 
                ha->fw_dump_reading = 0;
@@ -66,7 +66,7 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
                if (ha->fw_dumped && !ha->fw_dump_reading) {
                        ha->fw_dump_reading = 1;
 
-                       qla_printk(KERN_INFO, ha,
+                       ql_log(ql_log_info, vha, 0x705e,
                            "Raw firmware dump ready for read on (%ld).\n",
                            vha->host_no);
                }
@@ -148,7 +148,7 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj,
        }
 
        if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x705f,
                    "HBA not online, failing NVRAM update.\n");
                return -EAGAIN;
        }
@@ -158,6 +158,8 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj,
        ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base,
            count);
 
+       ql_dbg(ql_dbg_user, vha, 0x7060,
+           "Setting ISP_ABORT_NEEDED\n");
        /* NVRAM settings take effect immediately. */
        set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
        qla2xxx_wake_dpc(vha);
@@ -255,9 +257,9 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
 
                ha->optrom_state = QLA_SWAITING;
 
-               DEBUG2(qla_printk(KERN_INFO, ha,
+               ql_dbg(ql_dbg_user, vha, 0x7061,
                    "Freeing flash region allocation -- 0x%x bytes.\n",
-                   ha->optrom_region_size));
+                   ha->optrom_region_size);
 
                vfree(ha->optrom_buffer);
                ha->optrom_buffer = NULL;
@@ -273,7 +275,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
                ha->optrom_state = QLA_SREADING;
                ha->optrom_buffer = vmalloc(ha->optrom_region_size);
                if (ha->optrom_buffer == NULL) {
-                       qla_printk(KERN_WARNING, ha,
+                       ql_log(ql_log_warn, vha, 0x7062,
                            "Unable to allocate memory for optrom retrieval "
                            "(%x).\n", ha->optrom_region_size);
 
@@ -282,14 +284,14 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
                }
 
                if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
-                       qla_printk(KERN_WARNING, ha,
-                               "HBA not online, failing NVRAM update.\n");
+                       ql_log(ql_log_warn, vha, 0x7063,
+                           "HBA not online, failing NVRAM update.\n");
                        return -EAGAIN;
                }
 
-               DEBUG2(qla_printk(KERN_INFO, ha,
+               ql_dbg(ql_dbg_user, vha, 0x7064,
                    "Reading flash region -- 0x%x/0x%x.\n",
-                   ha->optrom_region_start, ha->optrom_region_size));
+                   ha->optrom_region_start, ha->optrom_region_size);
 
                memset(ha->optrom_buffer, 0, ha->optrom_region_size);
                ha->isp_ops->read_optrom(vha, ha->optrom_buffer,
@@ -328,7 +330,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
                else if (IS_QLA25XX(ha) || IS_QLA8XXX_TYPE(ha))
                        valid = 1;
                if (!valid) {
-                       qla_printk(KERN_WARNING, ha,
+                       ql_log(ql_log_warn, vha, 0x7065,
                            "Invalid start region 0x%x/0x%x.\n", start, size);
                        return -EINVAL;
                }
@@ -340,17 +342,17 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
                ha->optrom_state = QLA_SWRITING;
                ha->optrom_buffer = vmalloc(ha->optrom_region_size);
                if (ha->optrom_buffer == NULL) {
-                       qla_printk(KERN_WARNING, ha,
+                       ql_log(ql_log_warn, vha, 0x7066,
                            "Unable to allocate memory for optrom update "
-                           "(%x).\n", ha->optrom_region_size);
+                           "(%x)\n", ha->optrom_region_size);
 
                        ha->optrom_state = QLA_SWAITING;
                        return count;
                }
 
-               DEBUG2(qla_printk(KERN_INFO, ha,
+               ql_dbg(ql_dbg_user, vha, 0x7067,
                    "Staging flash region write -- 0x%x/0x%x.\n",
-                   ha->optrom_region_start, ha->optrom_region_size));
+                   ha->optrom_region_start, ha->optrom_region_size);
 
                memset(ha->optrom_buffer, 0, ha->optrom_region_size);
                break;
@@ -359,14 +361,14 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
                        break;
 
                if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
-                       qla_printk(KERN_WARNING, ha,
+                       ql_log(ql_log_warn, vha, 0x7068,
                            "HBA not online, failing flash update.\n");
                        return -EAGAIN;
                }
 
-               DEBUG2(qla_printk(KERN_INFO, ha,
+               ql_dbg(ql_dbg_user, vha, 0x7069,
                    "Writing flash region -- 0x%x/0x%x.\n",
-                   ha->optrom_region_start, ha->optrom_region_size));
+                   ha->optrom_region_start, ha->optrom_region_size);
 
                ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
                    ha->optrom_region_start, ha->optrom_region_size);
@@ -425,7 +427,7 @@ qla2x00_sysfs_write_vpd(struct file *filp, struct kobject *kobj,
                return 0;
 
        if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x706a,
                    "HBA not online, failing VPD update.\n");
                return -EAGAIN;
        }
@@ -440,7 +442,7 @@ qla2x00_sysfs_write_vpd(struct file *filp, struct kobject *kobj,
 
        tmp_data = vmalloc(256);
        if (!tmp_data) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x706b,
                    "Unable to allocate memory for VPD information update.\n");
                goto done;
        }
@@ -480,7 +482,7 @@ qla2x00_sysfs_read_sfp(struct file *filp, struct kobject *kobj,
        ha->sfp_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
            &ha->sfp_data_dma);
        if (!ha->sfp_data) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x706c,
                    "Unable to allocate memory for SFP read-data.\n");
                return 0;
        }
@@ -499,9 +501,10 @@ do_read:
                rval = qla2x00_read_sfp(vha, ha->sfp_data_dma, ha->sfp_data,
                    addr, offset, SFP_BLOCK_SIZE, 0);
                if (rval != QLA_SUCCESS) {
-                       qla_printk(KERN_WARNING, ha,
+                       ql_log(ql_log_warn, vha, 0x706d,
                            "Unable to read SFP data (%x/%x/%x).\n", rval,
                            addr, offset);
+
                        count = 0;
                        break;
                }
@@ -538,8 +541,8 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
        type = simple_strtol(buf, NULL, 10);
        switch (type) {
        case 0x2025c:
-               qla_printk(KERN_INFO, ha,
-                   "Issuing ISP reset on (%ld).\n", vha->host_no);
+               ql_log(ql_log_info, vha, 0x706e,
+                   "Issuing ISP reset.\n");
 
                scsi_block_requests(vha->host);
                set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
@@ -551,8 +554,8 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
                if (!IS_QLA81XX(ha))
                        break;
 
-               qla_printk(KERN_INFO, ha,
-                   "Issuing MPI reset on (%ld).\n", vha->host_no);
+               ql_log(ql_log_info, vha, 0x706f,
+                   "Issuing MPI reset.\n");
 
                /* Make sure FC side is not in reset */
                qla2x00_wait_for_hba_online(vha);
@@ -560,20 +563,19 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
                /* Issue MPI reset */
                scsi_block_requests(vha->host);
                if (qla81xx_restart_mpi_firmware(vha) != QLA_SUCCESS)
-                       qla_printk(KERN_WARNING, ha,
-                           "MPI reset failed on (%ld).\n", vha->host_no);
+                       ql_log(ql_log_warn, vha, 0x7070,
+                           "MPI reset failed.\n");
                scsi_unblock_requests(vha->host);
                break;
        case 0x2025e:
                if (!IS_QLA82XX(ha) || vha != base_vha) {
-                       qla_printk(KERN_INFO, ha,
-                           "FCoE ctx reset not supported for host%ld.\n",
-                           vha->host_no);
+                       ql_log(ql_log_info, vha, 0x7071,
+                           "FCoE ctx reset no supported.\n");
                        return count;
                }
 
-               qla_printk(KERN_INFO, ha,
-                   "Issuing FCoE CTX reset on host%ld.\n", vha->host_no);
+               ql_log(ql_log_info, vha, 0x7072,
+                   "Issuing FCoE ctx reset.\n");
                set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
                qla2xxx_wake_dpc(vha);
                qla2x00_wait_for_fcoe_ctx_reset(vha);
@@ -611,8 +613,8 @@ qla2x00_sysfs_write_edc(struct file *filp, struct kobject *kobj,
                ha->edc_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
                    &ha->edc_data_dma);
                if (!ha->edc_data) {
-                       DEBUG2(qla_printk(KERN_INFO, ha,
-                           "Unable to allocate memory for EDC write.\n"));
+                       ql_log(ql_log_warn, vha, 0x7073,
+                           "Unable to allocate memory for EDC write.\n");
                        return 0;
                }
        }
@@ -631,9 +633,9 @@ qla2x00_sysfs_write_edc(struct file *filp, struct kobject *kobj,
        rval = qla2x00_write_sfp(vha, ha->edc_data_dma, ha->edc_data,
            dev, adr, len, opt);
        if (rval != QLA_SUCCESS) {
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                   "Unable to write EDC (%x) %02x:%02x:%04x:%02x:%02x.\n",
-                   rval, dev, adr, opt, len, buf[8]));
+               ql_log(ql_log_warn, vha, 0x7074,
+                   "Unable to write EDC (%x) %02x:%04x:%02x:%02x\n",
+                   rval, dev, adr, opt, len, buf[8]);
                return 0;
        }
 
@@ -669,8 +671,8 @@ qla2x00_sysfs_write_edc_status(struct file *filp, struct kobject *kobj,
                ha->edc_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
                    &ha->edc_data_dma);
                if (!ha->edc_data) {
-                       DEBUG2(qla_printk(KERN_INFO, ha,
-                           "Unable to allocate memory for EDC status.\n"));
+                       ql_log(ql_log_warn, vha, 0x708c,
+                           "Unable to allocate memory for EDC status.\n");
                        return 0;
                }
        }
@@ -688,9 +690,9 @@ qla2x00_sysfs_write_edc_status(struct file *filp, struct kobject *kobj,
        rval = qla2x00_read_sfp(vha, ha->edc_data_dma, ha->edc_data,
                        dev, adr, len, opt);
        if (rval != QLA_SUCCESS) {
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                   "Unable to write EDC status (%x) %02x:%02x:%04x:%02x.\n",
-                   rval, dev, adr, opt, len));
+               ql_log(ql_log_info, vha, 0x7075,
+                   "Unable to write EDC status (%x) %02x:%04x:%02x.\n",
+                   rval, dev, adr, opt, len);
                return 0;
        }
 
@@ -749,7 +751,7 @@ qla2x00_sysfs_read_xgmac_stats(struct file *filp, struct kobject *kobj,
        ha->xgmac_data = dma_alloc_coherent(&ha->pdev->dev, XGMAC_DATA_SIZE,
            &ha->xgmac_data_dma, GFP_KERNEL);
        if (!ha->xgmac_data) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x7076,
                    "Unable to allocate memory for XGMAC read-data.\n");
                return 0;
        }
@@ -761,7 +763,7 @@ do_read:
        rval = qla2x00_get_xgmac_stats(vha, ha->xgmac_data_dma,
            XGMAC_DATA_SIZE, &actual_size);
        if (rval != QLA_SUCCESS) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x7077,
                    "Unable to read XGMAC data (%x).\n", rval);
                count = 0;
        }
@@ -801,7 +803,7 @@ qla2x00_sysfs_read_dcbx_tlv(struct file *filp, struct kobject *kobj,
        ha->dcbx_tlv = dma_alloc_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE,
            &ha->dcbx_tlv_dma, GFP_KERNEL);
        if (!ha->dcbx_tlv) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x7078,
                    "Unable to allocate memory for DCBX TLV read-data.\n");
                return 0;
        }
@@ -813,8 +815,8 @@ do_read:
        rval = qla2x00_get_dcbx_params(vha, ha->dcbx_tlv_dma,
            DCBX_TLV_DATA_SIZE);
        if (rval != QLA_SUCCESS) {
-               qla_printk(KERN_WARNING, ha,
-                   "Unable to read DCBX TLV data (%x).\n", rval);
+               ql_log(ql_log_warn, vha, 0x7079,
+                   "Unable to read DCBX TLV (%x).\n", rval);
                count = 0;
        }
 
@@ -869,9 +871,13 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha)
                ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
                    iter->attr);
                if (ret)
-                       qla_printk(KERN_INFO, vha->hw,
-                           "Unable to create sysfs %s binary attribute "
-                           "(%d).\n", iter->name, ret);
+                       ql_log(ql_log_warn, vha, 0x00f3,
+                           "Unable to create sysfs %s binary attribute (%d).\n",
+                           iter->name, ret);
+               else
+                       ql_dbg(ql_dbg_init, vha, 0x00f4,
+                           "Successfully created sysfs %s binary attribure.\n",
+                           iter->name);
        }
 }
 
@@ -1126,7 +1132,7 @@ qla2x00_beacon_store(struct device *dev, struct device_attribute *attr,
                return -EPERM;
 
        if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x707a,
                    "Abort ISP active -- ignoring beacon request.\n");
                return -EBUSY;
        }
@@ -1322,9 +1328,8 @@ qla2x00_thermal_temp_show(struct device *dev,
        temp = frac = 0;
        if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
            test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
-               DEBUG2_3_11(printk(KERN_WARNING
-                   "%s(%ld): isp reset in progress.\n",
-                   __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x707b,
+                   "ISP reset active.\n");
        else if (!vha->hw->flags.eeh_busy)
                rval = qla2x00_get_thermal_temp(vha, &temp, &frac);
        if (rval != QLA_SUCCESS)
@@ -1343,8 +1348,8 @@ qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr,
 
        if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
                test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
-               DEBUG2_3_11(printk("%s(%ld): isp reset in progress.\n",
-                       __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x707c,
+                   "ISP reset active.\n");
        else if (!vha->hw->flags.eeh_busy)
                rval = qla2x00_get_firmware_state(vha, state);
        if (rval != QLA_SUCCESS)
@@ -1645,8 +1650,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
 
        stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma);
        if (stats == NULL) {
-               DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
-                   __func__, base_vha->host_no));
+               ql_log(ql_log_warn, vha, 0x707d,
+                   "Failed to allocate memory for stats.\n");
                goto done;
        }
        memset(stats, 0, DMA_POOL_SIZE);
@@ -1746,15 +1751,14 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
 
        ret = qla24xx_vport_create_req_sanity_check(fc_vport);
        if (ret) {
-               DEBUG15(printk("qla24xx_vport_create_req_sanity_check failed, "
-                   "status %x\n", ret));
+               ql_log(ql_log_warn, vha, 0x707e,
+                   "Vport sanity check failed, status %x\n", ret);
                return (ret);
        }
 
        vha = qla24xx_create_vhost(fc_vport);
        if (vha == NULL) {
-               DEBUG15(printk ("qla24xx_create_vhost failed, vha = %p\n",
-                   vha));
+               ql_log(ql_log_warn, vha, 0x707f, "Vport create host failed.\n");
                return FC_VPORT_FAILED;
        }
        if (disable) {
@@ -1764,8 +1768,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
                atomic_set(&vha->vp_state, VP_FAILED);
 
        /* ready to create vport */
-       qla_printk(KERN_INFO, vha->hw, "VP entry id %d assigned.\n",
-                                                       vha->vp_idx);
+       ql_log(ql_log_info, vha, 0x7080,
+           "VP entry id %d assigned.\n", vha->vp_idx);
 
        /* initialized vport states */
        atomic_set(&vha->loop_state, LOOP_DOWN);
@@ -1775,8 +1779,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
        if (atomic_read(&base_vha->loop_state) == LOOP_DOWN ||
            atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
                /* Don't retry or attempt login of this virtual port */
-               DEBUG15(printk ("scsi(%ld): pport loop_state is not UP.\n",
-                   base_vha->host_no));
+               ql_dbg(ql_dbg_user, vha, 0x7081,
+                   "Vport loop state is not UP.\n");
                atomic_set(&vha->loop_state, LOOP_DEAD);
                if (!disable)
                        fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
@@ -1785,9 +1789,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
        if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) {
                if (ha->fw_attributes & BIT_4) {
                        vha->flags.difdix_supported = 1;
-                       DEBUG18(qla_printk(KERN_INFO, ha,
-                           "Registering for DIF/DIX type 1 and 3"
-                           " protection.\n"));
+                       ql_dbg(ql_dbg_user, vha, 0x7082,
+                           "Registered for DIF/DIX type 1 and 3 protection.\n");
                        scsi_host_set_prot(vha->host,
                            SHOST_DIF_TYPE1_PROTECTION
                            | SHOST_DIF_TYPE2_PROTECTION
@@ -1802,8 +1805,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
 
        if (scsi_add_host_with_dma(vha->host, &fc_vport->dev,
                                   &ha->pdev->dev)) {
-               DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
-                       vha->host_no, vha->vp_idx));
+               ql_dbg(ql_dbg_user, vha, 0x7083,
+                   "scsi_add_host failure for VP[%d].\n", vha->vp_idx);
                goto vport_create_failed_2;
        }
 
@@ -1820,6 +1823,10 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
 
        if (ha->flags.cpu_affinity_enabled) {
                req = ha->req_q_map[1];
+               ql_dbg(ql_dbg_multiq, vha, 0xc000,
+                   "Request queue %p attached with "
+                   "VP[%d], cpu affinity =%d\n",
+                   req, vha->vp_idx, ha->flags.cpu_affinity_enabled);
                goto vport_queue;
        } else if (ql2xmaxqueues == 1 || !ha->npiv_info)
                goto vport_queue;
@@ -1836,13 +1843,16 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
                ret = qla25xx_create_req_que(ha, options, vha->vp_idx, 0, 0,
                        qos);
                if (!ret)
-                       qla_printk(KERN_WARNING, ha,
-                       "Can't create request queue for vp_idx:%d\n",
-                       vha->vp_idx);
+                       ql_log(ql_log_warn, vha, 0x7084,
+                           "Can't create request queue for VP[%d]\n",
+                           vha->vp_idx);
                else {
-                       DEBUG2(qla_printk(KERN_INFO, ha,
-                       "Request Que:%d (QoS: %d) created for vp_idx:%d\n",
-                       ret, qos, vha->vp_idx));
+                       ql_dbg(ql_dbg_multiq, vha, 0xc001,
+                           "Request Que:%d Q0s: %d) created for VP[%d]\n",
+                           ret, qos, vha->vp_idx);
+                       ql_dbg(ql_dbg_user, vha, 0x7085,
+                           "Request Que:%d Q0s: %d) created for VP[%d]\n",
+                           ret, qos, vha->vp_idx);
                        req = ha->req_q_map[ret];
                }
        }
@@ -1882,12 +1892,13 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
 
        if (vha->timer_active) {
                qla2x00_vp_stop_timer(vha);
-               DEBUG15(printk(KERN_INFO "scsi(%ld): timer for the vport[%d]"
-               " = %p has stopped\n", vha->host_no, vha->vp_idx, vha));
+               ql_dbg(ql_dbg_user, vha, 0x7086,
+                   "Timer for the VP[%d] has stopped\n", vha->vp_idx);
        }
 
        /* No pending activities shall be there on the vha now */
-       DEBUG(msleep(random32()%10));  /* Just to see if something falls on
+       if (ql2xextended_error_logging & ql_dbg_user)
+               msleep(random32()%10);  /* Just to see if something falls on
                                        * the net we have placed below */
 
        BUG_ON(atomic_read(&vha->vref_count));
@@ -1901,12 +1912,12 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
 
        if (vha->req->id && !ha->flags.cpu_affinity_enabled) {
                if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS)
-                       qla_printk(KERN_WARNING, ha,
-                               "Queue delete failed.\n");
+                       ql_log(ql_log_warn, vha, 0x7087,
+                           "Queue delete failed.\n");
        }
 
        scsi_host_put(vha->host);
-       qla_printk(KERN_INFO, ha, "vport %d deleted\n", id);
+       ql_log(ql_log_info, vha, 0x7088, "VP[%d] deleted.\n", id);
        return 0;
 }
 
index 8c10e2c..07d1767 100644 (file)
@@ -36,7 +36,8 @@ done:
 }
 
 int
-qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
+qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *vha,
+       struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
 {
        int i, ret, num_valid;
        uint8_t *bcode;
@@ -51,18 +52,17 @@ qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
 
        if (bcode_val == 0xFFFFFFFF) {
                /* No FCP Priority config data in flash */
-               DEBUG2(printk(KERN_INFO
-                   "%s: No FCP priority config data.\n",
-                   __func__));
+               ql_dbg(ql_dbg_user, vha, 0x7051,
+                   "No FCP Priority config data.\n");
                return 0;
        }
 
        if (bcode[0] != 'H' || bcode[1] != 'Q' || bcode[2] != 'O' ||
                        bcode[3] != 'S') {
                /* Invalid FCP priority data header*/
-               DEBUG2(printk(KERN_ERR
-                   "%s: Invalid FCP Priority data header. bcode=0x%x\n",
-                   __func__, bcode_val));
+               ql_dbg(ql_dbg_user, vha, 0x7052,
+                   "Invalid FCP Priority data header. bcode=0x%x.\n",
+                   bcode_val);
                return 0;
        }
        if (flag != 1)
@@ -77,15 +77,14 @@ qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
 
        if (num_valid == 0) {
                /* No valid FCP priority data entries */
-               DEBUG2(printk(KERN_ERR
-                   "%s: No valid FCP Priority data entries.\n",
-                   __func__));
+               ql_dbg(ql_dbg_user, vha, 0x7053,
+                   "No valid FCP Priority data entries.\n");
                ret = 0;
        } else {
                /* FCP priority data is valid */
-               DEBUG2(printk(KERN_INFO
-                   "%s: Valid FCP priority data. num entries = %d\n",
-                   __func__, num_valid));
+               ql_dbg(ql_dbg_user, vha, 0x7054,
+                   "Valid FCP priority data. num entries = %d.\n",
+                   num_valid);
        }
 
        return ret;
@@ -182,10 +181,9 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
                if (!ha->fcp_prio_cfg) {
                        ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
                        if (!ha->fcp_prio_cfg) {
-                               qla_printk(KERN_WARNING, ha,
-                                       "Unable to allocate memory "
-                                       "for fcp prio config data (%x).\n",
-                                       FCP_PRIO_CFG_SIZE);
+                               ql_log(ql_log_warn, vha, 0x7050,
+                                   "Unable to allocate memory for fcp prio "
+                                   "config data (%x).\n", FCP_PRIO_CFG_SIZE);
                                bsg_job->reply->result = (DID_ERROR << 16);
                                ret = -ENOMEM;
                                goto exit_fcp_prio_cfg;
@@ -198,9 +196,9 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
                        FCP_PRIO_CFG_SIZE);
 
                /* validate fcp priority data */
-               if (!qla24xx_fcp_prio_cfg_valid(
-                       (struct qla_fcp_prio_cfg *)
-                       ha->fcp_prio_cfg, 1)) {
+
+               if (!qla24xx_fcp_prio_cfg_valid(vha,
+                   (struct qla_fcp_prio_cfg *) ha->fcp_prio_cfg, 1)) {
                        bsg_job->reply->result = (DID_ERROR << 16);
                        ret = -EINVAL;
                        /* If buffer was invalidatic int
@@ -256,9 +254,8 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
 
        /* pass through is supported only for ISP 4Gb or higher */
        if (!IS_FWI2_CAPABLE(ha)) {
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                   "scsi(%ld):ELS passthru not supported for ISP23xx based "
-                   "adapters\n", vha->host_no));
+               ql_dbg(ql_dbg_user, vha, 0x7001,
+                   "ELS passthru not supported for ISP23xx based adapters.\n");
                rval = -EPERM;
                goto done;
        }
@@ -266,11 +263,11 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
        /*  Multiple SG's are not supported for ELS requests */
        if (bsg_job->request_payload.sg_cnt > 1 ||
                bsg_job->reply_payload.sg_cnt > 1) {
-               DEBUG2(printk(KERN_INFO
-                       "multiple SG's are not supported for ELS requests"
-                       " [request_sg_cnt: %x reply_sg_cnt: %x]\n",
-                       bsg_job->request_payload.sg_cnt,
-                       bsg_job->reply_payload.sg_cnt));
+               ql_dbg(ql_dbg_user, vha, 0x7002,
+                   "Multiple SG's are not suppored for ELS requests, "
+                   "request_sg_cnt=%x reply_sg_cnt=%x.\n",
+                   bsg_job->request_payload.sg_cnt,
+                   bsg_job->reply_payload.sg_cnt);
                rval = -EPERM;
                goto done;
        }
@@ -281,9 +278,9 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
                 * if not perform fabric login
                 */
                if (qla2x00_fabric_login(vha, fcport, &nextlid)) {
-                       DEBUG2(qla_printk(KERN_WARNING, ha,
-                       "failed to login port %06X for ELS passthru\n",
-                       fcport->d_id.b24));
+                       ql_dbg(ql_dbg_user, vha, 0x7003,
+                           "Failed to login port %06X for ELS passthru.\n",
+                           fcport->d_id.b24);
                        rval = -EIO;
                        goto done;
                }
@@ -314,8 +311,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
        }
 
        if (!vha->flags.online) {
-               DEBUG2(qla_printk(KERN_WARNING, ha,
-               "host not online\n"));
+               ql_log(ql_log_warn, vha, 0x7005, "Host not online.\n");
                rval = -EIO;
                goto done;
        }
@@ -337,12 +333,11 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
 
        if ((req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
                (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
-               DEBUG2(printk(KERN_INFO
-                       "dma mapping resulted in different sg counts \
-                       [request_sg_cnt: %x dma_request_sg_cnt: %x\
-                       reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
-                       bsg_job->request_payload.sg_cnt, req_sg_cnt,
-                       bsg_job->reply_payload.sg_cnt, rsp_sg_cnt));
+               ql_log(ql_log_warn, vha, 0x7008,
+                   "dma mapping resulted in different sg counts, "
+                   "request_sg_cnt: %x dma_request_sg_cnt:%x reply_sg_cnt:%x "
+                   "dma_reply_sg_cnt:%x.\n", bsg_job->request_payload.sg_cnt,
+                   req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
                rval = -EAGAIN;
                goto done_unmap_sg;
        }
@@ -363,15 +358,16 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
                "bsg_els_rpt" : "bsg_els_hst");
        els->u.bsg_job = bsg_job;
 
-       DEBUG2(qla_printk(KERN_INFO, ha,
-               "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
-               "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type,
-               bsg_job->request->rqst_data.h_els.command_code,
-               fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
-               fcport->d_id.b.al_pa));
+       ql_dbg(ql_dbg_user, vha, 0x700a,
+           "bsg rqst type: %s els type: %x - loop-id=%x "
+           "portid=%-2x%02x%02x.\n", type,
+           bsg_job->request->rqst_data.h_els.command_code, fcport->loop_id,
+           fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa);
 
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS) {
+               ql_log(ql_log_warn, vha, 0x700e,
+                   "qla2x00_start_sp failed = %d\n", rval);
                kfree(sp->ctx);
                mempool_free(sp, ha->srb_mempool);
                rval = -EIO;
@@ -411,6 +407,8 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
                dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
                        bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
        if (!req_sg_cnt) {
+               ql_log(ql_log_warn, vha, 0x700f,
+                   "dma_map_sg return %d for request\n", req_sg_cnt);
                rval = -ENOMEM;
                goto done;
        }
@@ -418,24 +416,25 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
        rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
                bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
        if (!rsp_sg_cnt) {
+               ql_log(ql_log_warn, vha, 0x7010,
+                   "dma_map_sg return %d for reply\n", rsp_sg_cnt);
                rval = -ENOMEM;
                goto done;
        }
 
        if ((req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
            (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
-               DEBUG2(qla_printk(KERN_WARNING, ha,
-                   "[request_sg_cnt: %x dma_request_sg_cnt: %x\
-                   reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
-                   bsg_job->request_payload.sg_cnt, req_sg_cnt,
-                   bsg_job->reply_payload.sg_cnt, rsp_sg_cnt));
+               ql_log(ql_log_warn, vha, 0x7011,
+                   "request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt:%x "
+                   "dma_reply_sg_cnt: %x\n", bsg_job->request_payload.sg_cnt,
+                   req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
                rval = -EAGAIN;
                goto done_unmap_sg;
        }
 
        if (!vha->flags.online) {
-               DEBUG2(qla_printk(KERN_WARNING, ha,
-                       "host not online\n"));
+               ql_log(ql_log_warn, vha, 0x7012,
+                   "Host is not online.\n");
                rval = -EIO;
                goto done_unmap_sg;
        }
@@ -451,8 +450,8 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
                loop_id = vha->mgmt_svr_loop_id;
                break;
        default:
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                   "Unknown loop id: %x\n", loop_id));
+               ql_dbg(ql_dbg_user, vha, 0x7013,
+                   "Unknown loop id: %x.\n", loop_id);
                rval = -EINVAL;
                goto done_unmap_sg;
        }
@@ -464,6 +463,8 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
         */
        fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
        if (!fcport) {
+               ql_log(ql_log_warn, vha, 0x7014,
+                   "Failed to allocate fcport.\n");
                rval = -ENOMEM;
                goto done_unmap_sg;
        }
@@ -479,6 +480,8 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
        /* Alloc SRB structure */
        sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
        if (!sp) {
+               ql_log(ql_log_warn, vha, 0x7015,
+                   "qla2x00_get_ctx_bsg_sp failed.\n");
                rval = -ENOMEM;
                goto done_free_fcport;
        }
@@ -488,15 +491,17 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
        ct->name = "bsg_ct";
        ct->u.bsg_job = bsg_job;
 
-       DEBUG2(qla_printk(KERN_INFO, ha,
-               "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
-               "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type,
-               (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16),
-               fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
-               fcport->d_id.b.al_pa));
+       ql_dbg(ql_dbg_user, vha, 0x7016,
+           "bsg rqst type: %s else type: %x - "
+           "loop-id=%x portid=%02x%02x%02x.\n", type,
+           (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16),
+           fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
+           fcport->d_id.b.al_pa);
 
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS) {
+               ql_log(ql_log_warn, vha, 0x7017,
+                   "qla2x00_start_sp failed=%d.\n", rval);
                kfree(sp->ctx);
                mempool_free(sp, ha->srb_mempool);
                rval = -EIO;
@@ -535,9 +540,8 @@ qla81xx_set_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
        ha->notify_dcbx_comp = 1;
        ret = qla81xx_set_port_config(vha, new_config);
        if (ret != QLA_SUCCESS) {
-               DEBUG2(printk(KERN_ERR
-                   "%s(%lu): Set port config failed\n",
-                   __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x7021,
+                   "set port config failed.\n");
                ha->notify_dcbx_comp = 0;
                rval = -EINVAL;
                goto done_set_internal;
@@ -545,11 +549,11 @@ qla81xx_set_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
 
        /* Wait for DCBX complete event */
        if (!wait_for_completion_timeout(&ha->dcbx_comp, (20 * HZ))) {
-               DEBUG2(qla_printk(KERN_WARNING, ha,
-                   "State change notificaition not received.\n"));
+               ql_dbg(ql_dbg_user, vha, 0x7022,
+                   "State change notification not received.\n");
        } else
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                   "State change RECEIVED\n"));
+               ql_dbg(ql_dbg_user, vha, 0x7023,
+                   "State change received.\n");
 
        ha->notify_dcbx_comp = 0;
 
@@ -581,9 +585,8 @@ qla81xx_reset_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
                ha->notify_dcbx_comp = wait;
                ret = qla81xx_set_port_config(vha, new_config);
                if (ret != QLA_SUCCESS) {
-                       DEBUG2(printk(KERN_ERR
-                           "%s(%lu): Set port config failed\n",
-                            __func__, vha->host_no));
+                       ql_log(ql_log_warn, vha, 0x7025,
+                           "Set port config failed.\n");
                        ha->notify_dcbx_comp = 0;
                        rval = -EINVAL;
                        goto done_reset_internal;
@@ -592,14 +595,14 @@ qla81xx_reset_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
                /* Wait for DCBX complete event */
                if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
                        (20 * HZ))) {
-                       DEBUG2(qla_printk(KERN_WARNING, ha,
-                           "State change notificaition not received.\n"));
+                       ql_dbg(ql_dbg_user, vha, 0x7026,
+                           "State change notification not received.\n");
                        ha->notify_dcbx_comp = 0;
                        rval = -EINVAL;
                        goto done_reset_internal;
                } else
-                       DEBUG2(qla_printk(KERN_INFO, ha,
-                           "State change RECEIVED\n"));
+                       ql_dbg(ql_dbg_user, vha, 0x7027,
+                           "State change received.\n");
 
                ha->notify_dcbx_comp = 0;
        }
@@ -629,11 +632,13 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 
        if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
                test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
-               test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
+               test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+               ql_log(ql_log_warn, vha, 0x7018, "Abort active or needed.\n");
                return -EBUSY;
+       }
 
        if (!vha->flags.online) {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "host not online\n"));
+               ql_log(ql_log_warn, vha, 0x7019, "Host is not online.\n");
                return -EIO;
        }
 
@@ -641,26 +646,31 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt,
                DMA_TO_DEVICE);
 
-       if (!elreq.req_sg_cnt)
+       if (!elreq.req_sg_cnt) {
+               ql_log(ql_log_warn, vha, 0x701a,
+                   "dma_map_sg returned %d for request.\n", elreq.req_sg_cnt);
                return -ENOMEM;
+       }
 
        elreq.rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
                bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt,
                DMA_FROM_DEVICE);
 
        if (!elreq.rsp_sg_cnt) {
+               ql_log(ql_log_warn, vha, 0x701b,
+                   "dma_map_sg returned %d for reply.\n", elreq.rsp_sg_cnt);
                rval = -ENOMEM;
                goto done_unmap_req_sg;
        }
 
        if ((elreq.req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
                (elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
-               DEBUG2(printk(KERN_INFO
-                       "dma mapping resulted in different sg counts "
-                       "[request_sg_cnt: %x dma_request_sg_cnt: %x "
-                       "reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
-                       bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt,
-                       bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt));
+               ql_log(ql_log_warn, vha, 0x701c,
+                   "dma mapping resulted in different sg counts, "
+                   "request_sg_cnt: %x dma_request_sg_cnt: %x "
+                   "reply_sg_cnt: %x dma_reply_sg_cnt: %x.\n",
+                   bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt,
+                   bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt);
                rval = -EAGAIN;
                goto done_unmap_sg;
        }
@@ -668,8 +678,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
        req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len,
                &req_data_dma, GFP_KERNEL);
        if (!req_data) {
-               DEBUG2(printk(KERN_ERR "%s: dma alloc for req_data "
-                       "failed for host=%lu\n", __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x701d,
+                   "dma alloc failed for req_data.\n");
                rval = -ENOMEM;
                goto done_unmap_sg;
        }
@@ -677,8 +687,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
        rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len,
                &rsp_data_dma, GFP_KERNEL);
        if (!rsp_data) {
-               DEBUG2(printk(KERN_ERR "%s: dma alloc for rsp_data "
-                       "failed for host=%lu\n", __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x7004,
+                   "dma alloc failed for rsp_data.\n");
                rval = -ENOMEM;
                goto done_free_dma_req;
        }
@@ -699,8 +709,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
            && req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
                elreq.options == EXTERNAL_LOOPBACK) {
                type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                       "scsi(%ld) bsg rqst type: %s\n", vha->host_no, type));
+               ql_dbg(ql_dbg_user, vha, 0x701e,
+                   "BSG request type: %s.\n", type);
                command_sent = INT_DEF_LB_ECHO_CMD;
                rval = qla2x00_echo_test(vha, &elreq, response);
        } else {
@@ -708,9 +718,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                        memset(config, 0, sizeof(config));
                        memset(new_config, 0, sizeof(new_config));
                        if (qla81xx_get_port_config(vha, config)) {
-                               DEBUG2(printk(KERN_ERR
-                                       "%s(%lu): Get port config failed\n",
-                                       __func__, vha->host_no));
+                               ql_log(ql_log_warn, vha, 0x701f,
+                                   "Get port config failed.\n");
                                bsg_job->reply->reply_payload_rcv_len = 0;
                                bsg_job->reply->result = (DID_ERROR << 16);
                                rval = -EPERM;
@@ -718,11 +727,13 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                        }
 
                        if (elreq.options != EXTERNAL_LOOPBACK) {
-                               DEBUG2(qla_printk(KERN_INFO, ha,
-                                       "Internal: current port config = %x\n",
-                                       config[0]));
+                               ql_dbg(ql_dbg_user, vha, 0x7020,
+                                   "Internal: curent port config = %x\n",
+                                   config[0]);
                                if (qla81xx_set_internal_loopback(vha, config,
                                        new_config)) {
+                                       ql_log(ql_log_warn, vha, 0x7024,
+                                           "Internal loopback failed.\n");
                                        bsg_job->reply->reply_payload_rcv_len =
                                                0;
                                        bsg_job->reply->result =
@@ -746,9 +757,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                        }
 
                        type = "FC_BSG_HST_VENDOR_LOOPBACK";
-                       DEBUG2(qla_printk(KERN_INFO, ha,
-                               "scsi(%ld) bsg rqst type: %s\n",
-                               vha->host_no, type));
+                       ql_dbg(ql_dbg_user, vha, 0x7028,
+                           "BSG request type: %s.\n", type);
 
                        command_sent = INT_DEF_LB_LOOPBACK_CMD;
                        rval = qla2x00_loopback_test(vha, &elreq, response);
@@ -763,17 +773,16 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 
                        if (response[0] == MBS_COMMAND_ERROR &&
                                        response[1] == MBS_LB_RESET) {
-                               DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing "
-                                       "ISP\n", __func__, vha->host_no));
+                               ql_log(ql_log_warn, vha, 0x7029,
+                                   "MBX command error, Aborting ISP.\n");
                                set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
                                qla2xxx_wake_dpc(vha);
                                qla2x00_wait_for_chip_reset(vha);
                                /* Also reset the MPI */
                                if (qla81xx_restart_mpi_firmware(vha) !=
                                    QLA_SUCCESS) {
-                                       qla_printk(KERN_INFO, ha,
-                                           "MPI reset failed for host%ld.\n",
-                                           vha->host_no);
+                                       ql_log(ql_log_warn, vha, 0x702a,
+                                           "MPI reset failed.\n");
                                }
 
                                bsg_job->reply->reply_payload_rcv_len = 0;
@@ -783,17 +792,16 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                        }
                } else {
                        type = "FC_BSG_HST_VENDOR_LOOPBACK";
-                       DEBUG2(qla_printk(KERN_INFO, ha,
-                               "scsi(%ld) bsg rqst type: %s\n",
-                               vha->host_no, type));
+                       ql_dbg(ql_dbg_user, vha, 0x702b,
+                           "BSG request type: %s.\n", type);
                        command_sent = INT_DEF_LB_LOOPBACK_CMD;
                        rval = qla2x00_loopback_test(vha, &elreq, response);
                }
        }
 
        if (rval) {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
-                   "request %s failed\n", vha->host_no, type));
+               ql_log(ql_log_warn, vha, 0x702c,
+                   "Vendor request %s failed.\n", type);
 
                fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
                    sizeof(struct fc_bsg_reply);
@@ -805,8 +813,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                bsg_job->reply->reply_payload_rcv_len = 0;
                bsg_job->reply->result = (DID_ERROR << 16);
        } else {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
-                       "request %s completed\n", vha->host_no, type));
+               ql_dbg(ql_dbg_user, vha, 0x702d,
+                   "Vendor request %s completed.\n", type);
 
                bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
                        sizeof(response) + sizeof(uint8_t);
@@ -851,12 +859,13 @@ qla84xx_reset(struct fc_bsg_job *bsg_job)
 
        if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
            test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
-           test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
+           test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+               ql_log(ql_log_warn, vha, 0x702e, "Abort active or needed.\n");
                return -EBUSY;
+       }
 
        if (!IS_QLA84XX(ha)) {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, "
-                  "exiting.\n", vha->host_no));
+               ql_dbg(ql_dbg_user, vha, 0x702f, "Not 84xx, exiting.\n");
                return -EINVAL;
        }
 
@@ -865,14 +874,14 @@ qla84xx_reset(struct fc_bsg_job *bsg_job)
        rval = qla84xx_reset_chip(vha, flag == A84_ISSUE_RESET_DIAG_FW);
 
        if (rval) {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
-                   "request 84xx reset failed\n", vha->host_no));
+               ql_log(ql_log_warn, vha, 0x7030,
+                   "Vendor request 84xx reset failed.\n");
                rval = bsg_job->reply->reply_payload_rcv_len = 0;
                bsg_job->reply->result = (DID_ERROR << 16);
 
        } else {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
-                   "request 84xx reset completed\n", vha->host_no));
+               ql_dbg(ql_dbg_user, vha, 0x7031,
+                   "Vendor request 84xx reset completed.\n");
                bsg_job->reply->result = DID_OK;
        }
 
@@ -902,21 +911,24 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
                return -EBUSY;
 
        if (!IS_QLA84XX(ha)) {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, "
-                       "exiting.\n", vha->host_no));
+               ql_dbg(ql_dbg_user, vha, 0x7032,
+                   "Not 84xx, exiting.\n");
                return -EINVAL;
        }
 
        sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
                bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
-       if (!sg_cnt)
+       if (!sg_cnt) {
+               ql_log(ql_log_warn, vha, 0x7033,
+                   "dma_map_sg returned %d for request.\n", sg_cnt);
                return -ENOMEM;
+       }
 
        if (sg_cnt != bsg_job->request_payload.sg_cnt) {
-               DEBUG2(printk(KERN_INFO
-                       "dma mapping resulted in different sg counts "
-                       "request_sg_cnt: %x dma_request_sg_cnt: %x ",
-                       bsg_job->request_payload.sg_cnt, sg_cnt));
+               ql_log(ql_log_warn, vha, 0x7034,
+                   "DMA mapping resulted in different sg counts, "
+                   "request_sg_cnt: %x dma_request_sg_cnt: %x.\n",
+                   bsg_job->request_payload.sg_cnt, sg_cnt);
                rval = -EAGAIN;
                goto done_unmap_sg;
        }
@@ -925,8 +937,8 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
        fw_buf = dma_alloc_coherent(&ha->pdev->dev, data_len,
                &fw_dma, GFP_KERNEL);
        if (!fw_buf) {
-               DEBUG2(printk(KERN_ERR "%s: dma alloc for fw_buf "
-                       "failed for host=%lu\n", __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x7035,
+                   "DMA alloc failed for fw_buf.\n");
                rval = -ENOMEM;
                goto done_unmap_sg;
        }
@@ -936,8 +948,8 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
 
        mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
        if (!mn) {
-               DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer "
-                       "failed for host=%lu\n", __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x7036,
+                   "DMA alloc failed for fw buffer.\n");
                rval = -ENOMEM;
                goto done_free_fw_buf;
        }
@@ -965,15 +977,15 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
        rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
 
        if (rval) {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
-                       "request 84xx updatefw failed\n", vha->host_no));
+               ql_log(ql_log_warn, vha, 0x7037,
+                   "Vendor request 84xx updatefw failed.\n");
 
                rval = bsg_job->reply->reply_payload_rcv_len = 0;
                bsg_job->reply->result = (DID_ERROR << 16);
 
        } else {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
-                       "request 84xx updatefw completed\n", vha->host_no));
+               ql_dbg(ql_dbg_user, vha, 0x7038,
+                   "Vendor request 84xx updatefw completed.\n");
 
                bsg_job->reply_len = sizeof(struct fc_bsg_reply);
                bsg_job->reply->result = DID_OK;
@@ -1009,27 +1021,30 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
 
        if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
                test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
-               test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
+               test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+               ql_log(ql_log_warn, vha, 0x7039,
+                   "Abort active or needed.\n");
                return -EBUSY;
+       }
 
        if (!IS_QLA84XX(ha)) {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, "
-                       "exiting.\n", vha->host_no));
+               ql_log(ql_log_warn, vha, 0x703a,
+                   "Not 84xx, exiting.\n");
                return -EINVAL;
        }
 
        ql84_mgmt = (struct qla_bsg_a84_mgmt *)((char *)bsg_job->request +
                sizeof(struct fc_bsg_request));
        if (!ql84_mgmt) {
-               DEBUG2(printk("%s(%ld): mgmt header not provided, exiting.\n",
-                       __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x703b,
+                   "MGMT header not provided, exiting.\n");
                return -EINVAL;
        }
 
        mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
        if (!mn) {
-               DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer "
-                       "failed for host=%lu\n", __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x703c,
+                   "DMA alloc failed for fw buffer.\n");
                return -ENOMEM;
        }
 
@@ -1044,6 +1059,8 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
                        bsg_job->reply_payload.sg_list,
                        bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
                if (!sg_cnt) {
+                       ql_log(ql_log_warn, vha, 0x703d,
+                           "dma_map_sg returned %d for reply.\n", sg_cnt);
                        rval = -ENOMEM;
                        goto exit_mgmt;
                }
@@ -1051,10 +1068,10 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
                dma_direction = DMA_FROM_DEVICE;
 
                if (sg_cnt != bsg_job->reply_payload.sg_cnt) {
-                       DEBUG2(printk(KERN_INFO
-                               "dma mapping resulted in different sg counts "
-                               "reply_sg_cnt: %x dma_reply_sg_cnt: %x\n",
-                               bsg_job->reply_payload.sg_cnt, sg_cnt));
+                       ql_log(ql_log_warn, vha, 0x703e,
+                           "DMA mapping resulted in different sg counts, "
+                           "reply_sg_cnt: %x dma_reply_sg_cnt: %x.\n",
+                           bsg_job->reply_payload.sg_cnt, sg_cnt);
                        rval = -EAGAIN;
                        goto done_unmap_sg;
                }
@@ -1064,9 +1081,8 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
                mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
                    &mgmt_dma, GFP_KERNEL);
                if (!mgmt_b) {
-                       DEBUG2(printk(KERN_ERR "%s: dma alloc for mgmt_b "
-                               "failed for host=%lu\n",
-                               __func__, vha->host_no));
+                       ql_log(ql_log_warn, vha, 0x703f,
+                           "DMA alloc failed for mgmt_b.\n");
                        rval = -ENOMEM;
                        goto done_unmap_sg;
                }
@@ -1094,6 +1110,8 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
                        bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 
                if (!sg_cnt) {
+                       ql_log(ql_log_warn, vha, 0x7040,
+                           "dma_map_sg returned %d.\n", sg_cnt);
                        rval = -ENOMEM;
                        goto exit_mgmt;
                }
@@ -1101,10 +1119,10 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
                dma_direction = DMA_TO_DEVICE;
 
                if (sg_cnt != bsg_job->request_payload.sg_cnt) {
-                       DEBUG2(printk(KERN_INFO
-                               "dma mapping resulted in different sg counts "
-                               "request_sg_cnt: %x dma_request_sg_cnt: %x ",
-                               bsg_job->request_payload.sg_cnt, sg_cnt));
+                       ql_log(ql_log_warn, vha, 0x7041,
+                           "DMA mapping resulted in different sg counts, "
+                           "request_sg_cnt: %x dma_request_sg_cnt: %x.\n",
+                           bsg_job->request_payload.sg_cnt, sg_cnt);
                        rval = -EAGAIN;
                        goto done_unmap_sg;
                }
@@ -1113,9 +1131,8 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
                mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
                        &mgmt_dma, GFP_KERNEL);
                if (!mgmt_b) {
-                       DEBUG2(printk(KERN_ERR "%s: dma alloc for mgmt_b "
-                               "failed for host=%lu\n",
-                               __func__, vha->host_no));
+                       ql_log(ql_log_warn, vha, 0x7042,
+                           "DMA alloc failed for mgmt_b.\n");
                        rval = -ENOMEM;
                        goto done_unmap_sg;
                }
@@ -1156,15 +1173,15 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
        rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0);
 
        if (rval) {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
-                       "request 84xx mgmt failed\n", vha->host_no));
+               ql_log(ql_log_warn, vha, 0x7043,
+                   "Vendor request 84xx mgmt failed.\n");
 
                rval = bsg_job->reply->reply_payload_rcv_len = 0;
                bsg_job->reply->result = (DID_ERROR << 16);
 
        } else {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
-                       "request 84xx mgmt completed\n", vha->host_no));
+               ql_dbg(ql_dbg_user, vha, 0x7044,
+                   "Vendor request 84xx mgmt completed.\n");
 
                bsg_job->reply_len = sizeof(struct fc_bsg_reply);
                bsg_job->reply->result = DID_OK;
@@ -1204,7 +1221,6 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
 {
        struct Scsi_Host *host = bsg_job->shost;
        scsi_qla_host_t *vha = shost_priv(host);
-       struct qla_hw_data *ha = vha->hw;
        int rval = 0;
        struct qla_port_param *port_param = NULL;
        fc_port_t *fcport = NULL;
@@ -1215,26 +1231,27 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
 
        if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
                test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
-               test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
+               test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+               ql_log(ql_log_warn, vha, 0x7045, "abort active or needed.\n");
                return -EBUSY;
+       }
 
        if (!IS_IIDMA_CAPABLE(vha->hw)) {
-               DEBUG2(qla_printk(KERN_WARNING, ha, "%s(%lu): iiDMA not "
-                       "supported\n",  __func__, vha->host_no));
+               ql_log(ql_log_info, vha, 0x7046, "iiDMA not supported.\n");
                return -EINVAL;
        }
 
        port_param = (struct qla_port_param *)((char *)bsg_job->request +
                sizeof(struct fc_bsg_request));
        if (!port_param) {
-               DEBUG2(printk("%s(%ld): port_param header not provided, "
-                       "exiting.\n", __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x7047,
+                   "port_param header not provided.\n");
                return -EINVAL;
        }
 
        if (port_param->fc_scsi_addr.dest_type != EXT_DEF_TYPE_WWPN) {
-               DEBUG2(printk(KERN_ERR "%s(%ld): Invalid destination type\n",
-                       __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x7048,
+                   "Invalid destination type.\n");
                return -EINVAL;
        }
 
@@ -1249,21 +1266,20 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
        }
 
        if (!fcport) {
-               DEBUG2(printk(KERN_ERR "%s(%ld): Failed to find port\n",
-                       __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x7049,
+                   "Failed to find port.\n");
                return -EINVAL;
        }
 
        if (atomic_read(&fcport->state) != FCS_ONLINE) {
-               DEBUG2(printk(KERN_ERR "%s(%ld): Port not online\n",
-                       __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x704a,
+                   "Port is not online.\n");
                return -EINVAL;
        }
 
        if (fcport->flags & FCF_LOGIN_NEEDED) {
-               DEBUG2(printk(KERN_ERR "%s(%ld): Remote port not logged in, "
-                   "flags = 0x%x\n",
-                   __func__, vha->host_no, fcport->flags));
+               ql_log(ql_log_warn, vha, 0x704b,
+                   "Remote port not logged in flags = 0x%x.\n", fcport->flags);
                return -EINVAL;
        }
 
@@ -1275,15 +1291,13 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
                        &port_param->speed, mb);
 
        if (rval) {
-               DEBUG16(printk(KERN_ERR "scsi(%ld): iIDMA cmd failed for "
-                       "%02x%02x%02x%02x%02x%02x%02x%02x -- "
-                       "%04x %x %04x %04x.\n",
-                       vha->host_no, fcport->port_name[0],
-                       fcport->port_name[1],
-                       fcport->port_name[2], fcport->port_name[3],
-                       fcport->port_name[4], fcport->port_name[5],
-                       fcport->port_name[6], fcport->port_name[7], rval,
-                       fcport->fp_speed, mb[0], mb[1]));
+               ql_log(ql_log_warn, vha, 0x704c,
+                   "iIDMA cmd failed for %02x%02x%02x%02x%02x%02x%02x%02x -- "
+                   "%04x %x %04x %04x.\n", fcport->port_name[0],
+                   fcport->port_name[1], fcport->port_name[2],
+                   fcport->port_name[3], fcport->port_name[4],
+                   fcport->port_name[5], fcport->port_name[6],
+                   fcport->port_name[7], rval, fcport->fp_speed, mb[0], mb[1]);
                rval = 0;
                bsg_job->reply->result = (DID_ERROR << 16);
 
@@ -1307,11 +1321,12 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
 }
 
 static int
-qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha,
+qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, scsi_qla_host_t *vha,
        uint8_t is_update)
 {
        uint32_t start = 0;
        int valid = 0;
+       struct qla_hw_data *ha = vha->hw;
 
        bsg_job->reply->reply_payload_rcv_len = 0;
 
@@ -1319,14 +1334,20 @@ qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha,
                return -EINVAL;
 
        start = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
-       if (start > ha->optrom_size)
+       if (start > ha->optrom_size) {
+               ql_log(ql_log_warn, vha, 0x7055,
+                   "start %d > optrom_size %d.\n", start, ha->optrom_size);
                return -EINVAL;
+       }
 
-       if (ha->optrom_state != QLA_SWAITING)
+       if (ha->optrom_state != QLA_SWAITING) {
+               ql_log(ql_log_info, vha, 0x7056,
+                   "optrom_state %d.\n", ha->optrom_state);
                return -EBUSY;
+       }
 
        ha->optrom_region_start = start;
-
+       ql_dbg(ql_dbg_user, vha, 0x7057, "is_update=%d.\n", is_update);
        if (is_update) {
                if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
                        valid = 1;
@@ -1337,9 +1358,9 @@ qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha,
                    IS_QLA8XXX_TYPE(ha))
                        valid = 1;
                if (!valid) {
-                       qla_printk(KERN_WARNING, ha,
-                           "Invalid start region 0x%x/0x%x.\n",
-                           start, bsg_job->request_payload.payload_len);
+                       ql_log(ql_log_warn, vha, 0x7058,
+                           "Invalid start region 0x%x/0x%x.\n", start,
+                           bsg_job->request_payload.payload_len);
                        return -EINVAL;
                }
 
@@ -1358,9 +1379,9 @@ qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha,
 
        ha->optrom_buffer = vmalloc(ha->optrom_region_size);
        if (!ha->optrom_buffer) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x7059,
                    "Read: Unable to allocate memory for optrom retrieval "
-                   "(%x).\n", ha->optrom_region_size);
+                   "(%x)\n", ha->optrom_region_size);
 
                ha->optrom_state = QLA_SWAITING;
                return -ENOMEM;
@@ -1378,7 +1399,7 @@ qla2x00_read_optrom(struct fc_bsg_job *bsg_job)
        struct qla_hw_data *ha = vha->hw;
        int rval = 0;
 
-       rval = qla2x00_optrom_setup(bsg_job, ha, 0);
+       rval = qla2x00_optrom_setup(bsg_job, vha, 0);
        if (rval)
                return rval;
 
@@ -1406,7 +1427,7 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job)
        struct qla_hw_data *ha = vha->hw;
        int rval = 0;
 
-       rval = qla2x00_optrom_setup(bsg_job, ha, 1);
+       rval = qla2x00_optrom_setup(bsg_job, vha, 1);
        if (rval)
                return rval;
 
@@ -1464,6 +1485,23 @@ int
 qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
 {
        int ret = -EINVAL;
+       struct fc_rport *rport;
+       fc_port_t *fcport = NULL;
+       struct Scsi_Host *host;
+       scsi_qla_host_t *vha;
+
+       if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
+               rport = bsg_job->rport;
+               fcport = *(fc_port_t **) rport->dd_data;
+               host = rport_to_shost(rport);
+               vha = shost_priv(host);
+       } else {
+               host = bsg_job->shost;
+               vha = shost_priv(host);
+       }
+
+       ql_dbg(ql_dbg_user, vha, 0x7000,
+           "Entered %s msgcode=%d.\n", __func__, bsg_job->request->msgcode);
 
        switch (bsg_job->request->msgcode) {
        case FC_BSG_RPT_ELS:
@@ -1480,7 +1518,7 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
        case FC_BSG_HST_DEL_RPORT:
        case FC_BSG_RPT_CT:
        default:
-               DEBUG2(printk("qla2xxx: unsupported BSG request\n"));
+               ql_log(ql_log_warn, vha, 0x705a, "Unsupported BSG request.\n");
                break;
        }
        return ret;
@@ -1514,17 +1552,15 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
                                        && (sp_bsg->u.bsg_job == bsg_job)) {
                                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
                                        if (ha->isp_ops->abort_command(sp)) {
-                                               DEBUG2(qla_printk(KERN_INFO, ha,
-                                                   "scsi(%ld): mbx "
-                                                   "abort_command failed\n",
-                                                   vha->host_no));
+                                               ql_log(ql_log_warn, vha, 0x7089,
+                                                   "mbx abort_command "
+                                                   "failed.\n");
                                                bsg_job->req->errors =
                                                bsg_job->reply->result = -EIO;
                                        } else {
-                                               DEBUG2(qla_printk(KERN_INFO, ha,
-                                                   "scsi(%ld): mbx "
-                                                   "abort_command success\n",
-                                                   vha->host_no));
+                                               ql_dbg(ql_dbg_user, vha, 0x708a,
+                                                   "mbx abort_command "
+                                                   "success.\n");
                                                bsg_job->req->errors =
                                                bsg_job->reply->result = 0;
                                        }
@@ -1535,8 +1571,7 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
                }
        }
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
-       DEBUG2(qla_printk(KERN_INFO, ha,
-               "scsi(%ld) SRB not found to abort\n", vha->host_no));
+       ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n");
        bsg_job->req->errors = bsg_job->reply->result = -ENXIO;
        return 0;
 
index c53719a..2155071 100644 (file)
@@ -4,10 +4,36 @@
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
+
+/*
+ * Table for showing the current message id in use for particular level
+ * Change this table for addition of log/debug messages.
+ * -----------------------------------------------------
+ * |             Level            |   Last Value Used  |
+ * -----------------------------------------------------
+ * | Module Init and Probe        |       0x0116       |
+ * | Mailbox commands             |       0x111e       |
+ * | Device Discovery             |       0x2083       |
+ * | Queue Command and IO tracing |       0x302e       |
+ * | DPC Thread                   |       0x401c       |
+ * | Async Events                 |       0x5059       |
+ * | Timer Routines               |       0x600d       |
+ * | User Space Interactions      |       0x709c       |
+ * | Task Management              |       0x8043       |
+ * | AER/EEH                      |       0x900f       |
+ * | Virtual Port                 |       0xa007       |
+ * | ISP82XX Specific             |       0xb027       |
+ * | MultiQ                       |       0xc00b       |
+ * | Misc                         |       0xd00b       |
+ * -----------------------------------------------------
+ */
+
 #include "qla_def.h"
 
 #include <linux/delay.h>
 
+static uint32_t ql_dbg_offset = 0x800;
+
 static inline void
 qla2xxx_prep_dump(struct qla_hw_data *ha, struct qla2xxx_fw_dump *fw_dump)
 {
@@ -383,11 +409,11 @@ qla2xxx_dump_post_process(scsi_qla_host_t *vha, int rval)
        struct qla_hw_data *ha = vha->hw;
 
        if (rval != QLA_SUCCESS) {
-               qla_printk(KERN_WARNING, ha,
-                   "Failed to dump firmware (%x)!!!\n", rval);
+               ql_log(ql_log_warn, vha, 0xd000,
+                   "Failed to dump firmware (%x).\n", rval);
                ha->fw_dumped = 0;
        } else {
-               qla_printk(KERN_INFO, ha,
+               ql_log(ql_log_info, vha, 0xd001,
                    "Firmware dump saved to temp buffer (%ld/%p).\n",
                    vha->host_no, ha->fw_dump);
                ha->fw_dumped = 1;
@@ -419,15 +445,16 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
                spin_lock_irqsave(&ha->hardware_lock, flags);
 
        if (!ha->fw_dump) {
-               qla_printk(KERN_WARNING, ha,
-                   "No buffer available for dump!!!\n");
+               ql_log(ql_log_warn, vha, 0xd002,
+                   "No buffer available for dump.\n");
                goto qla2300_fw_dump_failed;
        }
 
        if (ha->fw_dumped) {
-               qla_printk(KERN_WARNING, ha,
-                   "Firmware has been previously dumped (%p) -- ignoring "
-                   "request...\n", ha->fw_dump);
+               ql_log(ql_log_warn, vha, 0xd003,
+                   "Firmware has been previously dumped (%p) "
+                   "-- ignoring request.\n",
+                   ha->fw_dump);
                goto qla2300_fw_dump_failed;
        }
        fw = &ha->fw_dump->isp.isp23;
@@ -582,15 +609,16 @@ qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
                spin_lock_irqsave(&ha->hardware_lock, flags);
 
        if (!ha->fw_dump) {
-               qla_printk(KERN_WARNING, ha,
-                   "No buffer available for dump!!!\n");
+               ql_log(ql_log_warn, vha, 0xd004,
+                   "No buffer available for dump.\n");
                goto qla2100_fw_dump_failed;
        }
 
        if (ha->fw_dumped) {
-               qla_printk(KERN_WARNING, ha,
-                   "Firmware has been previously dumped (%p) -- ignoring "
-                   "request...\n", ha->fw_dump);
+               ql_log(ql_log_warn, vha, 0xd005,
+                   "Firmware has been previously dumped (%p) "
+                   "-- ignoring request.\n",
+                   ha->fw_dump);
                goto qla2100_fw_dump_failed;
        }
        fw = &ha->fw_dump->isp.isp21;
@@ -779,15 +807,16 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
                spin_lock_irqsave(&ha->hardware_lock, flags);
 
        if (!ha->fw_dump) {
-               qla_printk(KERN_WARNING, ha,
-                   "No buffer available for dump!!!\n");
+               ql_log(ql_log_warn, vha, 0xd006,
+                   "No buffer available for dump.\n");
                goto qla24xx_fw_dump_failed;
        }
 
        if (ha->fw_dumped) {
-               qla_printk(KERN_WARNING, ha,
-                   "Firmware has been previously dumped (%p) -- ignoring "
-                   "request...\n", ha->fw_dump);
+               ql_log(ql_log_warn, vha, 0xd007,
+                   "Firmware has been previously dumped (%p) "
+                   "-- ignoring request.\n",
+                   ha->fw_dump);
                goto qla24xx_fw_dump_failed;
        }
        fw = &ha->fw_dump->isp.isp24;
@@ -1017,15 +1046,16 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
                spin_lock_irqsave(&ha->hardware_lock, flags);
 
        if (!ha->fw_dump) {
-               qla_printk(KERN_WARNING, ha,
-                   "No buffer available for dump!!!\n");
+               ql_log(ql_log_warn, vha, 0xd008,
+                   "No buffer available for dump.\n");
                goto qla25xx_fw_dump_failed;
        }
 
        if (ha->fw_dumped) {
-               qla_printk(KERN_WARNING, ha,
-                   "Firmware has been previously dumped (%p) -- ignoring "
-                   "request...\n", ha->fw_dump);
+               ql_log(ql_log_warn, vha, 0xd009,
+                   "Firmware has been previously dumped (%p) "
+                   "-- ignoring request.\n",
+                   ha->fw_dump);
                goto qla25xx_fw_dump_failed;
        }
        fw = &ha->fw_dump->isp.isp25;
@@ -1328,15 +1358,16 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
                spin_lock_irqsave(&ha->hardware_lock, flags);
 
        if (!ha->fw_dump) {
-               qla_printk(KERN_WARNING, ha,
-                   "No buffer available for dump!!!\n");
+               ql_log(ql_log_warn, vha, 0xd00a,
+                   "No buffer available for dump.\n");
                goto qla81xx_fw_dump_failed;
        }
 
        if (ha->fw_dumped) {
-               qla_printk(KERN_WARNING, ha,
-                   "Firmware has been previously dumped (%p) -- ignoring "
-                   "request...\n", ha->fw_dump);
+               ql_log(ql_log_warn, vha, 0xd00b,
+                   "Firmware has been previously dumped (%p) "
+                   "-- ignoring request.\n",
+                   ha->fw_dump);
                goto qla81xx_fw_dump_failed;
        }
        fw = &ha->fw_dump->isp.isp81;
@@ -1619,106 +1650,255 @@ qla81xx_fw_dump_failed:
 /****************************************************************************/
 /*                         Driver Debug Functions.                          */
 /****************************************************************************/
-
+/*
+ * This function is for formatting and logging debug information.
+ * It is to be used when vha is available. It formats the message
+ * and logs it to the messages file.
+ * parameters:
+ * level: The level of the debug messages to be printed.
+ *        If ql2xextended_error_logging value is correctly set,
+ *        this message will appear in the messages file.
+ * vha:   Pointer to the scsi_qla_host_t.
+ * id:    This is a unique identifier for the level. It identifies the
+ *        part of the code from where the message originated.
+ * msg:   The message to be displayed.
+ */
 void
-qla2x00_dump_regs(scsi_qla_host_t *vha)
-{
-       int i;
-       struct qla_hw_data *ha = vha->hw;
-       struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
-       struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
-       uint16_t __iomem *mbx_reg;
+ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, char *msg, ...) {
+
+       char pbuf[QL_DBG_BUF_LEN];
+       va_list ap;
+       uint32_t len;
+       struct pci_dev *pdev = NULL;
+
+       memset(pbuf, 0, QL_DBG_BUF_LEN);
+
+       va_start(ap, msg);
+
+       if ((level & ql2xextended_error_logging) == level) {
+               if (vha != NULL) {
+                       pdev = vha->hw->pdev;
+                       /* <module-name> <pci-name> <msg-id>:<host> Message */
+                       sprintf(pbuf, "%s [%s]-%04x:%ld: ", QL_MSGHDR,
+                           dev_name(&(pdev->dev)), id + ql_dbg_offset,
+                           vha->host_no);
+               } else
+                       sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR,
+                           "0000:00:00.0", id + ql_dbg_offset);
+
+               len = strlen(pbuf);
+               vsprintf(pbuf+len, msg, ap);
+               pr_warning("%s", pbuf);
+       }
 
-       mbx_reg = IS_FWI2_CAPABLE(ha) ? &reg24->mailbox0:
-           MAILBOX_REG(ha, reg, 0);
+       va_end(ap);
 
-       printk("Mailbox registers:\n");
-       for (i = 0; i < 6; i++)
-               printk("scsi(%ld): mbox %d 0x%04x \n", vha->host_no, i,
-                   RD_REG_WORD(mbx_reg++));
 }
 
-
+/*
+ * This function is for formatting and logging debug information.
+ * It is to be used when vha is not available and pci is availble,
+ * i.e., before host allocation. It formats the message and logs it
+ * to the messages file.
+ * parameters:
+ * level: The level of the debug messages to be printed.
+ *        If ql2xextended_error_logging value is correctly set,
+ *        this message will appear in the messages file.
+ * pdev:  Pointer to the struct pci_dev.
+ * id:    This is a unique id for the level. It identifies the part
+ *        of the code from where the message originated.
+ * msg:   The message to be displayed.
+ */
 void
-qla2x00_dump_buffer(uint8_t * b, uint32_t size)
-{
-       uint32_t cnt;
-       uint8_t c;
+ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id, char *msg, ...) {
 
-       printk(" 0   1   2   3   4   5   6   7   8   9  "
-           "Ah  Bh  Ch  Dh  Eh  Fh\n");
-       printk("----------------------------------------"
-           "----------------------\n");
-
-       for (cnt = 0; cnt < size;) {
-               c = *b++;
-               printk("%02x",(uint32_t) c);
-               cnt++;
-               if (!(cnt % 16))
-                       printk("\n");
-               else
-                       printk("  ");
+       char pbuf[QL_DBG_BUF_LEN];
+       va_list ap;
+       uint32_t len;
+
+       if (pdev == NULL)
+               return;
+
+       memset(pbuf, 0, QL_DBG_BUF_LEN);
+
+       va_start(ap, msg);
+
+       if ((level & ql2xextended_error_logging) == level) {
+               /* <module-name> <dev-name>:<msg-id> Message */
+               sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR,
+                   dev_name(&(pdev->dev)), id + ql_dbg_offset);
+
+               len = strlen(pbuf);
+               vsprintf(pbuf+len, msg, ap);
+               pr_warning("%s", pbuf);
        }
-       if (cnt % 16)
-               printk("\n");
+
+       va_end(ap);
+
 }
 
+/*
+ * This function is for formatting and logging log messages.
+ * It is to be used when vha is available. It formats the message
+ * and logs it to the messages file. All the messages will be logged
+ * irrespective of value of ql2xextended_error_logging.
+ * parameters:
+ * level: The level of the log messages to be printed in the
+ *        messages file.
+ * vha:   Pointer to the scsi_qla_host_t
+ * id:    This is a unique id for the level. It identifies the
+ *        part of the code from where the message originated.
+ * msg:   The message to be displayed.
+ */
 void
-qla2x00_dump_buffer_zipped(uint8_t *b, uint32_t size)
-{
-       uint32_t cnt;
-       uint8_t c;
-       uint8_t  last16[16], cur16[16];
-       uint32_t lc = 0, num_same16 = 0, j;
+ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, char *msg, ...) {
 
-       printk(KERN_DEBUG " 0   1   2   3   4   5   6   7   8   9  "
-           "Ah  Bh  Ch  Dh  Eh  Fh\n");
-       printk(KERN_DEBUG "----------------------------------------"
-           "----------------------\n");
+       char pbuf[QL_DBG_BUF_LEN];
+       va_list ap;
+       uint32_t len;
+       struct pci_dev *pdev = NULL;
 
-       for (cnt = 0; cnt < size;) {
-               c = *b++;
+       memset(pbuf, 0, QL_DBG_BUF_LEN);
 
-               cur16[lc++] = c;
+       va_start(ap, msg);
 
-               cnt++;
-               if (cnt % 16)
-                       continue;
-
-               /* We have 16 now */
-               lc = 0;
-               if (num_same16 == 0) {
-                       memcpy(last16, cur16, 16);
-                       num_same16++;
-                       continue;
+       if (level <= ql_errlev) {
+               if (vha != NULL) {
+                       pdev = vha->hw->pdev;
+                       /* <module-name> <msg-id>:<host> Message */
+                       sprintf(pbuf, "%s [%s]-%04x:%ld: ", QL_MSGHDR,
+                           dev_name(&(pdev->dev)), id, vha->host_no);
+               } else
+                       sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR,
+                           "0000:00:00.0", id);
+
+               len = strlen(pbuf);
+                       vsprintf(pbuf+len, msg, ap);
+
+               switch (level) {
+               case 0: /* FATAL LOG */
+                       pr_crit("%s", pbuf);
+                       break;
+               case 1:
+                       pr_err("%s", pbuf);
+                       break;
+               case 2:
+                       pr_warn("%s", pbuf);
+                       break;
+               default:
+                       pr_info("%s", pbuf);
+                       break;
                }
-               if (memcmp(cur16, last16, 16) == 0) {
-                       num_same16++;
-                       continue;
+       }
+
+       va_end(ap);
+}
+
+/*
+ * This function is for formatting and logging log messages.
+ * It is to be used when vha is not available and pci is availble,
+ * i.e., before host allocation. It formats the message and logs
+ * it to the messages file. All the messages are logged irrespective
+ * of the value of ql2xextended_error_logging.
+ * parameters:
+ * level: The level of the log messages to be printed in the
+ *        messages file.
+ * pdev:  Pointer to the struct pci_dev.
+ * id:    This is a unique id for the level. It identifies the
+ *        part of the code from where the message originated.
+ * msg:   The message to be displayed.
+ */
+void
+ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id, char *msg, ...) {
+
+       char pbuf[QL_DBG_BUF_LEN];
+       va_list ap;
+       uint32_t len;
+
+       if (pdev == NULL)
+               return;
+
+       memset(pbuf, 0, QL_DBG_BUF_LEN);
+
+       va_start(ap, msg);
+
+       if (level <= ql_errlev) {
+               /* <module-name> <dev-name>:<msg-id> Message */
+               sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR,
+                   dev_name(&(pdev->dev)), id);
+
+               len = strlen(pbuf);
+               vsprintf(pbuf+len, msg, ap);
+               switch (level) {
+               case 0: /* FATAL LOG */
+                       pr_crit("%s", pbuf);
+                       break;
+               case 1:
+                       pr_err("%s", pbuf);
+                       break;
+               case 2:
+                       pr_warn("%s", pbuf);
+                       break;
+               default:
+                       pr_info("%s", pbuf);
+                       break;
                }
-               for (j = 0; j < 16; j++)
-                       printk(KERN_DEBUG "%02x  ", (uint32_t)last16[j]);
-               printk(KERN_DEBUG "\n");
-
-               if (num_same16 > 1)
-                       printk(KERN_DEBUG "> prev pattern repeats (%u)"
-                           "more times\n", num_same16-1);
-               memcpy(last16, cur16, 16);
-               num_same16 = 1;
        }
 
-       if (num_same16) {
-               for (j = 0; j < 16; j++)
-                       printk(KERN_DEBUG "%02x  ", (uint32_t)last16[j]);
-               printk(KERN_DEBUG "\n");
+       va_end(ap);
+}
 
-               if (num_same16 > 1)
-                       printk(KERN_DEBUG "> prev pattern repeats (%u)"
-                           "more times\n", num_same16-1);
+void
+ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id)
+{
+       int i;
+       struct qla_hw_data *ha = vha->hw;
+       struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+       struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
+       struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
+       uint16_t __iomem *mbx_reg;
+
+       if ((level & ql2xextended_error_logging) == level) {
+
+               if (IS_QLA82XX(ha))
+                       mbx_reg = &reg82->mailbox_in[0];
+               else if (IS_FWI2_CAPABLE(ha))
+                       mbx_reg = &reg24->mailbox0;
+               else
+                       mbx_reg = MAILBOX_REG(ha, reg, 0);
+
+               ql_dbg(level, vha, id, "Mailbox registers:\n");
+               for (i = 0; i < 6; i++)
+                       ql_dbg(level, vha, id,
+                           "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg++));
        }
-       if (lc) {
-               for (j = 0; j < lc; j++)
-                       printk(KERN_DEBUG "%02x  ", (uint32_t)cur16[j]);
-               printk(KERN_DEBUG "\n");
+}
+
+
+void
+ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id,
+       uint8_t *b, uint32_t size)
+{
+       uint32_t cnt;
+       uint8_t c;
+       if ((level & ql2xextended_error_logging) == level) {
+
+               ql_dbg(level, vha, id, " 0   1   2   3   4   5   6   7   8   "
+                   "9  Ah  Bh  Ch  Dh  Eh  Fh\n");
+               ql_dbg(level, vha, id, "----------------------------------"
+                   "----------------------------\n");
+
+               ql_dbg(level, vha, id, "");
+               for (cnt = 0; cnt < size;) {
+                       c = *b++;
+                       printk("%02x", (uint32_t) c);
+                       cnt++;
+                       if (!(cnt % 16))
+                               printk("\n");
+                       else
+                               printk("  ");
+               }
+               if (cnt % 16)
+                       ql_dbg(level, vha, id, "\n");
        }
 }
index 9304145..98a377b 100644 (file)
@@ -7,146 +7,6 @@
 
 #include "qla_def.h"
 
-/*
- * Driver debug definitions.
- */
-/* #define QL_DEBUG_LEVEL_1  */ /* Output register accesses to COM1 */
-/* #define QL_DEBUG_LEVEL_2  */ /* Output error msgs to COM1 */
-/* #define QL_DEBUG_LEVEL_3  */ /* Output function trace msgs to COM1 */
-/* #define QL_DEBUG_LEVEL_4  */ /* Output NVRAM trace msgs to COM1 */
-/* #define QL_DEBUG_LEVEL_5  */ /* Output ring trace msgs to COM1 */
-/* #define QL_DEBUG_LEVEL_6  */ /* Output WATCHDOG timer trace to COM1 */
-/* #define QL_DEBUG_LEVEL_7  */ /* Output RISC load trace msgs to COM1 */
-/* #define QL_DEBUG_LEVEL_8  */ /* Output ring saturation msgs to COM1 */
-/* #define QL_DEBUG_LEVEL_9  */ /* Output IOCTL trace msgs */
-/* #define QL_DEBUG_LEVEL_10 */ /* Output IOCTL error msgs */
-/* #define QL_DEBUG_LEVEL_11 */ /* Output Mbx Cmd trace msgs */
-/* #define QL_DEBUG_LEVEL_12 */ /* Output IP trace msgs */
-/* #define QL_DEBUG_LEVEL_13 */ /* Output fdmi function trace msgs */
-/* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */
-/* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
-/* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */
-/* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */
-/* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */
-
-/*
-* Macros use for debugging the driver.
-*/
-
-#define DEBUG(x)       do { if (ql2xextended_error_logging) { x; } } while (0)
-
-#if defined(QL_DEBUG_LEVEL_1)
-#define DEBUG1(x)      do {x;} while (0)
-#else
-#define DEBUG1(x)      do {} while (0)
-#endif
-
-#define DEBUG2(x)      do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_3(x)    do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_3_11(x) do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_9_10(x) do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_11(x)   do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_13(x)   do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_16(x)   do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_17(x)   do { if (ql2xextended_error_logging) { x; } } while (0)
-
-#if defined(QL_DEBUG_LEVEL_3)
-#define DEBUG3(x)      do {x;} while (0)
-#define DEBUG3_11(x)   do {x;} while (0)
-#else
-#define DEBUG3(x)      do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_4)
-#define DEBUG4(x)      do {x;} while (0)
-#else
-#define DEBUG4(x)      do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_5)
-#define DEBUG5(x)          do {x;} while (0)
-#else
-#define DEBUG5(x)      do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_7)
-#define DEBUG7(x)          do {x;} while (0)
-#else
-#define DEBUG7(x)         do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_9)
-#define DEBUG9(x)       do {x;} while (0)
-#define DEBUG9_10(x)    do {x;} while (0)
-#else
-#define DEBUG9(x)      do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_10)
-#define DEBUG10(x)      do {x;} while (0)
-#define DEBUG9_10(x)   do {x;} while (0)
-#else
-#define DEBUG10(x)     do {} while (0)
-  #if !defined(DEBUG9_10)
-  #define DEBUG9_10(x) do {} while (0)
-  #endif
-#endif
-
-#if defined(QL_DEBUG_LEVEL_11)
-#define DEBUG11(x)      do{x;} while(0)
-#if !defined(DEBUG3_11)
-#define DEBUG3_11(x)    do{x;} while(0)
-#endif
-#else
-#define DEBUG11(x)     do{} while(0)
-  #if !defined(QL_DEBUG_LEVEL_3)
-  #define DEBUG3_11(x) do{} while(0)
-  #endif
-#endif
-
-#if defined(QL_DEBUG_LEVEL_12)
-#define DEBUG12(x)      do {x;} while (0)
-#else
-#define DEBUG12(x)     do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_13)
-#define DEBUG13(x)      do {x;} while (0)
-#else
-#define DEBUG13(x)     do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_14)
-#define DEBUG14(x)      do {x;} while (0)
-#else
-#define DEBUG14(x)     do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_15)
-#define DEBUG15(x)      do {x;} while (0)
-#else
-#define DEBUG15(x)     do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_16)
-#define DEBUG16(x)     do {x;} while (0)
-#else
-#define DEBUG16(x)     do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_17)
-#define DEBUG17(x)     do {x;} while (0)
-#else
-#define DEBUG17(x)     do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_18)
-#define DEBUG18(x)     do {if (ql2xextended_error_logging) x; } while (0)
-#else
-#define DEBUG18(x)     do {} while (0)
-#endif
-
-
 /*
  * Firmware Dump structure definition
  */
@@ -370,3 +230,50 @@ struct qla2xxx_fw_dump {
                struct qla81xx_fw_dump isp81;
        } isp;
 };
+
+#define QL_MSGHDR "qla2xxx"
+
+#define ql_log_fatal           0 /* display fatal errors */
+#define ql_log_warn            1 /* display critical errors */
+#define ql_log_info            2 /* display all recovered errors */
+#define ql_log_all             3 /* This value is only used by ql_errlev.
+                                  * No messages will use this value.
+                                  * This should be always highest value
+                                  * as compared to other log levels.
+                                  */
+
+extern int ql_errlev;
+
+void
+ql_dbg(uint32_t, scsi_qla_host_t *vha, int32_t, char *, ...);
+void
+ql_dbg_pci(uint32_t, struct pci_dev *pdev, int32_t, char *, ...);
+
+void
+ql_log(uint32_t, scsi_qla_host_t *vha, int32_t, char *, ...);
+void
+ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, char *, ...);
+
+/* Debug Levels */
+/* The 0x40000000 is the max value any debug level can have
+ * as ql2xextended_error_logging is of type signed int
+ */
+#define ql_dbg_init    0x40000000 /* Init Debug */
+#define ql_dbg_mbx     0x20000000 /* MBX Debug */
+#define ql_dbg_disc    0x10000000 /* Device Discovery Debug */
+#define ql_dbg_io      0x08000000 /* IO Tracing Debug */
+#define ql_dbg_dpc     0x04000000 /* DPC Thead Debug */
+#define ql_dbg_async   0x02000000 /* Async events Debug */
+#define ql_dbg_timer   0x01000000 /* Timer Debug */
+#define ql_dbg_user    0x00800000 /* User Space Interations Debug */
+#define ql_dbg_taskm   0x00400000 /* Task Management Debug */
+#define ql_dbg_aer     0x00200000 /* AER/EEH Debug */
+#define ql_dbg_multiq  0x00100000 /* MultiQ Debug */
+#define ql_dbg_p3p     0x00080000 /* P3P specific Debug */
+#define ql_dbg_vport   0x00040000 /* Virtual Port Debug */
+#define ql_dbg_buffer  0x00020000 /* For dumping the buffer/regs */
+#define ql_dbg_misc    0x00010000 /* For dumping everything that is not
+                                   * not covered by upper categories
+                                   */
+
+#define QL_DBG_BUF_LEN 512
index a5a4e12..0b4c2b7 100644 (file)
@@ -64,7 +64,7 @@ qla2x00_dfs_fce_open(struct inode *inode, struct file *file)
        /* Pause tracing to flush FCE buffers. */
        rval = qla2x00_disable_fce_trace(vha, &ha->fce_wr, &ha->fce_rd);
        if (rval)
-               qla_printk(KERN_WARNING, ha,
+               ql_dbg(ql_dbg_user, vha, 0x705c,
                    "DebugFS: Unable to disable FCE (%d).\n", rval);
 
        ha->flags.fce_enabled = 0;
@@ -92,7 +92,7 @@ qla2x00_dfs_fce_release(struct inode *inode, struct file *file)
        rval = qla2x00_enable_fce_trace(vha, ha->fce_dma, ha->fce_bufs,
            ha->fce_mb, &ha->fce_bufs);
        if (rval) {
-               qla_printk(KERN_WARNING, ha,
+               ql_dbg(ql_dbg_user, vha, 0x700d,
                    "DebugFS: Unable to reinitialize FCE (%d).\n", rval);
                ha->flags.fce_enabled = 0;
        }
@@ -125,8 +125,8 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha)
        atomic_set(&qla2x00_dfs_root_count, 0);
        qla2x00_dfs_root = debugfs_create_dir(QLA2XXX_DRIVER_NAME, NULL);
        if (!qla2x00_dfs_root) {
-               qla_printk(KERN_NOTICE, ha,
-                   "DebugFS: Unable to create root directory.\n");
+               ql_log(ql_log_warn, vha, 0x00f7,
+                   "Unable to create debugfs root directory.\n");
                goto out;
        }
 
@@ -137,8 +137,8 @@ create_dir:
        mutex_init(&ha->fce_mutex);
        ha->dfs_dir = debugfs_create_dir(vha->host_str, qla2x00_dfs_root);
        if (!ha->dfs_dir) {
-               qla_printk(KERN_NOTICE, ha,
-                   "DebugFS: Unable to create ha directory.\n");
+               ql_log(ql_log_warn, vha, 0x00f8,
+                   "Unable to create debugfs ha directory.\n");
                goto out;
        }
 
@@ -148,8 +148,8 @@ create_nodes:
        ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, vha,
            &dfs_fce_ops);
        if (!ha->dfs_fce) {
-               qla_printk(KERN_NOTICE, ha,
-                   "DebugFS: Unable to fce node.\n");
+               ql_log(ql_log_warn, vha, 0x00f9,
+                   "Unable to create debugfs fce node.\n");
                goto out;
        }
 out:
index 0b38122..29b1a3e 100644 (file)
@@ -185,7 +185,7 @@ extern int qla24xx_start_scsi(srb_t *sp);
 int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *,
                                                uint16_t, uint16_t, uint8_t);
 extern int qla2x00_start_sp(srb_t *);
-extern uint16_t qla24xx_calc_iocbs(uint16_t);
+extern uint16_t qla24xx_calc_iocbs(scsi_qla_host_t *, uint16_t);
 extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t);
 extern int qla24xx_dif_start_scsi(srb_t *);
 
@@ -439,6 +439,9 @@ extern void qla81xx_fw_dump(scsi_qla_host_t *, int);
 extern void qla2x00_dump_regs(scsi_qla_host_t *);
 extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
 extern void qla2x00_dump_buffer_zipped(uint8_t *, uint32_t);
+extern void ql_dump_regs(uint32_t, scsi_qla_host_t *, int32_t);
+extern void ql_dump_buffer(uint32_t, scsi_qla_host_t *, int32_t,
+       uint8_t *, uint32_t);
 
 /*
  * Global Function Prototypes in qla_gs.c source file.
@@ -478,7 +481,8 @@ extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16
 extern int qla2x00_echo_test(scsi_qla_host_t *,
        struct msg_echo_lb *, uint16_t *);
 extern int qla24xx_update_all_fcp_prio(scsi_qla_host_t *);
-extern int qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *, uint8_t);
+extern int qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *,
+       struct qla_fcp_prio_cfg *, uint8_t);
 
 /*
  * Global Function Prototypes in qla_dfs.c source file.
index 8cd9066..37937aa 100644 (file)
@@ -121,11 +121,10 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
 
        rval = QLA_FUNCTION_FAILED;
        if (ms_pkt->entry_status != 0) {
-               DEBUG2_3(printk(KERN_WARNING "scsi(%ld): %s failed, error status "
-                   "(%x) on port_id: %02x%02x%02x.\n",
-                   vha->host_no, routine, ms_pkt->entry_status,
-                   vha->d_id.b.domain, vha->d_id.b.area,
-                   vha->d_id.b.al_pa));
+               ql_dbg(ql_dbg_disc, vha, 0x2031,
+                   "%s failed, error status (%x) on port_id: %02x%02x%02x.\n",
+                   routine, ms_pkt->entry_status, vha->d_id.b.domain,
+                   vha->d_id.b.area, vha->d_id.b.al_pa);
        } else {
                if (IS_FWI2_CAPABLE(ha))
                        comp_status = le16_to_cpu(
@@ -138,24 +137,24 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
                case CS_DATA_OVERRUN:           /* Overrun? */
                        if (ct_rsp->header.response !=
                            __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
-                               DEBUG2_3(printk("scsi(%ld): %s failed, "
-                                   "rejected request on port_id: %02x%02x%02x\n",
-                                   vha->host_no, routine,
+                               ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077,
+                                   "%s failed rejected request on port_id: "
+                                   "%02x%02x%02x.\n", routine,
                                    vha->d_id.b.domain, vha->d_id.b.area,
-                                   vha->d_id.b.al_pa));
-                               DEBUG2_3(qla2x00_dump_buffer(
-                                   (uint8_t *)&ct_rsp->header,
-                                   sizeof(struct ct_rsp_hdr)));
+                                   vha->d_id.b.al_pa);
+                               ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha,
+                                   0x2078, (uint8_t *)&ct_rsp->header,
+                                   sizeof(struct ct_rsp_hdr));
                                rval = QLA_INVALID_COMMAND;
                        } else
                                rval = QLA_SUCCESS;
                        break;
                default:
-                       DEBUG2_3(printk("scsi(%ld): %s failed, completion "
-                           "status (%x) on port_id: %02x%02x%02x.\n",
-                           vha->host_no, routine, comp_status,
+                       ql_dbg(ql_dbg_disc, vha, 0x2033,
+                           "%s failed, completion status (%x) on port_id: "
+                           "%02x%02x%02x.\n", routine, comp_status,
                            vha->d_id.b.domain, vha->d_id.b.area,
-                           vha->d_id.b.al_pa));
+                           vha->d_id.b.al_pa);
                        break;
                }
        }
@@ -202,8 +201,8 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
            sizeof(ms_iocb_entry_t));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): GA_NXT issue IOCB failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x2062,
+                   "GA_NXT issue IOCB failed (%d).\n", rval);
        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GA_NXT") !=
            QLA_SUCCESS) {
                rval = QLA_FUNCTION_FAILED;
@@ -222,11 +221,10 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
                    ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
                        fcport->d_id.b.domain = 0xf0;
 
-               DEBUG2_3(printk("scsi(%ld): GA_NXT entry - "
-                   "nn %02x%02x%02x%02x%02x%02x%02x%02x "
+               ql_dbg(ql_dbg_disc, vha, 0x2063,
+                   "GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
                    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
-                   "portid=%02x%02x%02x.\n",
-                   vha->host_no,
+                   "port_id=%02x%02x%02x.\n",
                    fcport->node_name[0], fcport->node_name[1],
                    fcport->node_name[2], fcport->node_name[3],
                    fcport->node_name[4], fcport->node_name[5],
@@ -236,7 +234,7 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
                    fcport->port_name[4], fcport->port_name[5],
                    fcport->port_name[6], fcport->port_name[7],
                    fcport->d_id.b.domain, fcport->d_id.b.area,
-                   fcport->d_id.b.al_pa));
+                   fcport->d_id.b.al_pa);
        }
 
        return (rval);
@@ -287,8 +285,8 @@ qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
            sizeof(ms_iocb_entry_t));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): GID_PT issue IOCB failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x2055,
+                   "GID_PT issue IOCB failed (%d).\n", rval);
        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GID_PT") !=
            QLA_SUCCESS) {
                rval = QLA_FUNCTION_FAILED;
@@ -364,8 +362,8 @@ qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
                    sizeof(ms_iocb_entry_t));
                if (rval != QLA_SUCCESS) {
                        /*EMPTY*/
-                       DEBUG2_3(printk("scsi(%ld): GPN_ID issue IOCB failed "
-                           "(%d).\n", vha->host_no, rval));
+                       ql_dbg(ql_dbg_disc, vha, 0x2056,
+                           "GPN_ID issue IOCB failed (%d).\n", rval);
                } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
                    "GPN_ID") != QLA_SUCCESS) {
                        rval = QLA_FUNCTION_FAILED;
@@ -424,8 +422,8 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
                    sizeof(ms_iocb_entry_t));
                if (rval != QLA_SUCCESS) {
                        /*EMPTY*/
-                       DEBUG2_3(printk("scsi(%ld): GNN_ID issue IOCB failed "
-                           "(%d).\n", vha->host_no, rval));
+                       ql_dbg(ql_dbg_disc, vha, 0x2057,
+                           "GNN_ID issue IOCB failed (%d).\n", rval);
                } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
                    "GNN_ID") != QLA_SUCCESS) {
                        rval = QLA_FUNCTION_FAILED;
@@ -434,11 +432,10 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
                        memcpy(list[i].node_name,
                            ct_rsp->rsp.gnn_id.node_name, WWN_SIZE);
 
-                       DEBUG2_3(printk("scsi(%ld): GID_PT entry - "
-                           "nn %02x%02x%02x%02x%02x%02x%02x%02x "
-                           "pn %02x%02x%02x%02x%02x%02x%02x%02x "
+                       ql_dbg(ql_dbg_disc, vha, 0x2058,
+                           "GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02X%02x "
+                           "pn %02x%02x%02x%02x%02x%02x%02X%02x "
                            "portid=%02x%02x%02x.\n",
-                           vha->host_no,
                            list[i].node_name[0], list[i].node_name[1],
                            list[i].node_name[2], list[i].node_name[3],
                            list[i].node_name[4], list[i].node_name[5],
@@ -448,7 +445,7 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
                            list[i].port_name[4], list[i].port_name[5],
                            list[i].port_name[6], list[i].port_name[7],
                            list[i].d_id.b.domain, list[i].d_id.b.area,
-                           list[i].d_id.b.al_pa));
+                           list[i].d_id.b.al_pa);
                }
 
                /* Last device exit. */
@@ -499,14 +496,14 @@ qla2x00_rft_id(scsi_qla_host_t *vha)
            sizeof(ms_iocb_entry_t));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): RFT_ID issue IOCB failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x2043,
+                   "RFT_ID issue IOCB failed (%d).\n", rval);
        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFT_ID") !=
            QLA_SUCCESS) {
                rval = QLA_FUNCTION_FAILED;
        } else {
-               DEBUG2(printk("scsi(%ld): RFT_ID exiting normally.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x2044,
+                   "RFT_ID exiting normally.\n");
        }
 
        return (rval);
@@ -528,8 +525,8 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
        struct ct_sns_rsp       *ct_rsp;
 
        if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
-               DEBUG2(printk("scsi(%ld): RFF_ID call unsupported on "
-                   "ISP2100/ISP2200.\n", vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x2046,
+                   "RFF_ID call not supported on ISP2100/ISP2200.\n");
                return (QLA_SUCCESS);
        }
 
@@ -556,14 +553,14 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
            sizeof(ms_iocb_entry_t));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): RFF_ID issue IOCB failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x2047,
+                   "RFF_ID issue IOCB failed (%d).\n", rval);
        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFF_ID") !=
            QLA_SUCCESS) {
                rval = QLA_FUNCTION_FAILED;
        } else {
-               DEBUG2(printk("scsi(%ld): RFF_ID exiting normally.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x2048,
+                   "RFF_ID exiting normally.\n");
        }
 
        return (rval);
@@ -609,14 +606,14 @@ qla2x00_rnn_id(scsi_qla_host_t *vha)
            sizeof(ms_iocb_entry_t));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): RNN_ID issue IOCB failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x204d,
+                   "RNN_ID issue IOCB failed (%d).\n", rval);
        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RNN_ID") !=
            QLA_SUCCESS) {
                rval = QLA_FUNCTION_FAILED;
        } else {
-               DEBUG2(printk("scsi(%ld): RNN_ID exiting normally.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x204e,
+                   "RNN_ID exiting normally.\n");
        }
 
        return (rval);
@@ -647,8 +644,8 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
        struct ct_sns_rsp       *ct_rsp;
 
        if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
-               DEBUG2(printk("scsi(%ld): RSNN_ID call unsupported on "
-                   "ISP2100/ISP2200.\n", vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x2050,
+                   "RSNN_ID call unsupported on ISP2100/ISP2200.\n");
                return (QLA_SUCCESS);
        }
 
@@ -682,14 +679,14 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
            sizeof(ms_iocb_entry_t));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): RSNN_NN issue IOCB failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x2051,
+                   "RSNN_NN issue IOCB failed (%d).\n", rval);
        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RSNN_NN") !=
            QLA_SUCCESS) {
                rval = QLA_FUNCTION_FAILED;
        } else {
-               DEBUG2(printk("scsi(%ld): RSNN_NN exiting normally.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x2052,
+                   "RSNN_NN exiting normally.\n");
        }
 
        return (rval);
@@ -757,13 +754,14 @@ qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
            sizeof(struct sns_cmd_pkt));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): GA_NXT Send SNS failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x205f,
+                   "GA_NXT Send SNS failed (%d).\n", rval);
        } else if (sns_cmd->p.gan_data[8] != 0x80 ||
            sns_cmd->p.gan_data[9] != 0x02) {
-               DEBUG2_3(printk("scsi(%ld): GA_NXT failed, rejected request, "
-                   "ga_nxt_rsp:\n", vha->host_no));
-               DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gan_data, 16));
+               ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207d,
+                   "GA_NXT failed, rejected request ga_nxt_rsp:\n");
+               ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074,
+                   sns_cmd->p.gan_data, 16);
                rval = QLA_FUNCTION_FAILED;
        } else {
                /* Populate fc_port_t entry. */
@@ -778,11 +776,10 @@ qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
                    sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
                        fcport->d_id.b.domain = 0xf0;
 
-               DEBUG2_3(printk("scsi(%ld): GA_NXT entry - "
-                   "nn %02x%02x%02x%02x%02x%02x%02x%02x "
+               ql_dbg(ql_dbg_disc, vha, 0x2061,
+                   "GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
                    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
-                   "portid=%02x%02x%02x.\n",
-                   vha->host_no,
+                   "port_id=%02x%02x%02x.\n",
                    fcport->node_name[0], fcport->node_name[1],
                    fcport->node_name[2], fcport->node_name[3],
                    fcport->node_name[4], fcport->node_name[5],
@@ -792,7 +789,7 @@ qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
                    fcport->port_name[4], fcport->port_name[5],
                    fcport->port_name[6], fcport->port_name[7],
                    fcport->d_id.b.domain, fcport->d_id.b.area,
-                   fcport->d_id.b.al_pa));
+                   fcport->d_id.b.al_pa);
        }
 
        return (rval);
@@ -831,13 +828,14 @@ qla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
            sizeof(struct sns_cmd_pkt));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): GID_PT Send SNS failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x206d,
+                   "GID_PT Send SNS failed (%d).\n", rval);
        } else if (sns_cmd->p.gid_data[8] != 0x80 ||
            sns_cmd->p.gid_data[9] != 0x02) {
-               DEBUG2_3(printk("scsi(%ld): GID_PT failed, rejected request, "
-                   "gid_rsp:\n", vha->host_no));
-               DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gid_data, 16));
+               ql_dbg(ql_dbg_disc, vha, 0x202f,
+                   "GID_PT failed, rejected request, gid_rsp:\n");
+               ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2081,
+                   sns_cmd->p.gid_data, 16);
                rval = QLA_FUNCTION_FAILED;
        } else {
                /* Set port IDs in switch info list. */
@@ -900,13 +898,14 @@ qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
                    GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
                if (rval != QLA_SUCCESS) {
                        /*EMPTY*/
-                       DEBUG2_3(printk("scsi(%ld): GPN_ID Send SNS failed "
-                           "(%d).\n", vha->host_no, rval));
+                       ql_dbg(ql_dbg_disc, vha, 0x2032,
+                           "GPN_ID Send SNS failed (%d).\n", rval);
                } else if (sns_cmd->p.gpn_data[8] != 0x80 ||
                    sns_cmd->p.gpn_data[9] != 0x02) {
-                       DEBUG2_3(printk("scsi(%ld): GPN_ID failed, rejected "
-                           "request, gpn_rsp:\n", vha->host_no));
-                       DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gpn_data, 16));
+                       ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,
+                           "GPN_ID failed, rejected request, gpn_rsp:\n");
+                       ql_dump_buffer(ql_dbg_disc, vha, 0x207f,
+                           sns_cmd->p.gpn_data, 16);
                        rval = QLA_FUNCTION_FAILED;
                } else {
                        /* Save portname */
@@ -955,24 +954,24 @@ qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
                    GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
                if (rval != QLA_SUCCESS) {
                        /*EMPTY*/
-                       DEBUG2_3(printk("scsi(%ld): GNN_ID Send SNS failed "
-                           "(%d).\n", vha->host_no, rval));
+                       ql_dbg(ql_dbg_disc, vha, 0x203f,
+                           "GNN_ID Send SNS failed (%d).\n", rval);
                } else if (sns_cmd->p.gnn_data[8] != 0x80 ||
                    sns_cmd->p.gnn_data[9] != 0x02) {
-                       DEBUG2_3(printk("scsi(%ld): GNN_ID failed, rejected "
-                           "request, gnn_rsp:\n", vha->host_no));
-                       DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gnn_data, 16));
+                       ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2082,
+                           "GNN_ID failed, rejected request, gnn_rsp:\n");
+                       ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207a,
+                           sns_cmd->p.gnn_data, 16);
                        rval = QLA_FUNCTION_FAILED;
                } else {
                        /* Save nodename */
                        memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
                            WWN_SIZE);
 
-                       DEBUG2_3(printk("scsi(%ld): GID_PT entry - "
-                           "nn %02x%02x%02x%02x%02x%02x%02x%02x "
+                       ql_dbg(ql_dbg_disc, vha, 0x206e,
+                           "GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
                            "pn %02x%02x%02x%02x%02x%02x%02x%02x "
-                           "portid=%02x%02x%02x.\n",
-                           vha->host_no,
+                           "port_id=%02x%02x%02x.\n",
                            list[i].node_name[0], list[i].node_name[1],
                            list[i].node_name[2], list[i].node_name[3],
                            list[i].node_name[4], list[i].node_name[5],
@@ -982,7 +981,7 @@ qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
                            list[i].port_name[4], list[i].port_name[5],
                            list[i].port_name[6], list[i].port_name[7],
                            list[i].d_id.b.domain, list[i].d_id.b.area,
-                           list[i].d_id.b.al_pa));
+                           list[i].d_id.b.al_pa);
                }
 
                /* Last device exit. */
@@ -1025,17 +1024,18 @@ qla2x00_sns_rft_id(scsi_qla_host_t *vha)
            sizeof(struct sns_cmd_pkt));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): RFT_ID Send SNS failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x2060,
+                   "RFT_ID Send SNS failed (%d).\n", rval);
        } else if (sns_cmd->p.rft_data[8] != 0x80 ||
            sns_cmd->p.rft_data[9] != 0x02) {
-               DEBUG2_3(printk("scsi(%ld): RFT_ID failed, rejected request, "
-                   "rft_rsp:\n", vha->host_no));
-               DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.rft_data, 16));
+               ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2083,
+                   "RFT_ID failed, rejected request rft_rsp:\n");
+               ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2080,
+                   sns_cmd->p.rft_data, 16);
                rval = QLA_FUNCTION_FAILED;
        } else {
-               DEBUG2(printk("scsi(%ld): RFT_ID exiting normally.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x2073,
+                   "RFT_ID exiting normally.\n");
        }
 
        return (rval);
@@ -1081,17 +1081,18 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
            sizeof(struct sns_cmd_pkt));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): RNN_ID Send SNS failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x204a,
+                   "RNN_ID Send SNS failed (%d).\n", rval);
        } else if (sns_cmd->p.rnn_data[8] != 0x80 ||
            sns_cmd->p.rnn_data[9] != 0x02) {
-               DEBUG2_3(printk("scsi(%ld): RNN_ID failed, rejected request, "
-                   "rnn_rsp:\n", vha->host_no));
-               DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.rnn_data, 16));
+               ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207b,
+                   "RNN_ID failed, rejected request, rnn_rsp:\n");
+               ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207c,
+                   sns_cmd->p.rnn_data, 16);
                rval = QLA_FUNCTION_FAILED;
        } else {
-               DEBUG2(printk("scsi(%ld): RNN_ID exiting normally.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x204c,
+                   "RNN_ID exiting normally.\n");
        }
 
        return (rval);
@@ -1116,10 +1117,10 @@ qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
        ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa,
            mb, BIT_1|BIT_0);
        if (mb[0] != MBS_COMMAND_COMPLETE) {
-               DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: "
-                   "loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x\n",
-                   __func__, vha->host_no, vha->mgmt_svr_loop_id, mb[0], mb[1],
-                   mb[2], mb[6], mb[7]));
+               ql_dbg(ql_dbg_disc, vha, 0x2024,
+                   "Failed management_server login: loopid=%x mb[0]=%x "
+                   "mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x.\n",
+                   vha->mgmt_svr_loop_id, mb[0], mb[1], mb[2], mb[6], mb[7]);
                ret = QLA_FUNCTION_FAILED;
        } else
                vha->flags.management_server_logged_in = 1;
@@ -1292,11 +1293,12 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
        memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
        size += 4 + WWN_SIZE;
 
-       DEBUG13(printk("%s(%ld): NODENAME=%02x%02x%02x%02x%02x%02x%02x%02x.\n",
-           __func__, vha->host_no,
-           eiter->a.node_name[0], eiter->a.node_name[1], eiter->a.node_name[2],
-           eiter->a.node_name[3], eiter->a.node_name[4], eiter->a.node_name[5],
-           eiter->a.node_name[6], eiter->a.node_name[7]));
+       ql_dbg(ql_dbg_disc, vha, 0x2025,
+           "NodeName = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
+           eiter->a.node_name[0], eiter->a.node_name[1],
+           eiter->a.node_name[2], eiter->a.node_name[3],
+           eiter->a.node_name[4], eiter->a.node_name[5],
+           eiter->a.node_name[6], eiter->a.node_name[7]);
 
        /* Manufacturer. */
        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1307,8 +1309,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
-       DEBUG13(printk("%s(%ld): MANUFACTURER=%s.\n", __func__, vha->host_no,
-           eiter->a.manufacturer));
+       ql_dbg(ql_dbg_disc, vha, 0x2026,
+           "Manufacturer = %s.\n", eiter->a.manufacturer);
 
        /* Serial number. */
        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1320,8 +1322,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
-       DEBUG13(printk("%s(%ld): SERIALNO=%s.\n", __func__, vha->host_no,
-           eiter->a.serial_num));
+       ql_dbg(ql_dbg_disc, vha, 0x2027,
+           "Serial no. = %s.\n", eiter->a.serial_num);
 
        /* Model name. */
        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1332,8 +1334,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
-       DEBUG13(printk("%s(%ld): MODEL_NAME=%s.\n", __func__, vha->host_no,
-           eiter->a.model));
+       ql_dbg(ql_dbg_disc, vha, 0x2028,
+           "Model Name = %s.\n", eiter->a.model);
 
        /* Model description. */
        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1345,8 +1347,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
-       DEBUG13(printk("%s(%ld): MODEL_DESC=%s.\n", __func__, vha->host_no,
-           eiter->a.model_desc));
+       ql_dbg(ql_dbg_disc, vha, 0x2029,
+           "Model Desc = %s.\n", eiter->a.model_desc);
 
        /* Hardware version. */
        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1357,8 +1359,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
-       DEBUG13(printk("%s(%ld): HARDWAREVER=%s.\n", __func__, vha->host_no,
-           eiter->a.hw_version));
+       ql_dbg(ql_dbg_disc, vha, 0x202a,
+           "Hardware ver = %s.\n", eiter->a.hw_version);
 
        /* Driver version. */
        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1369,8 +1371,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
-       DEBUG13(printk("%s(%ld): DRIVERVER=%s.\n", __func__, vha->host_no,
-           eiter->a.driver_version));
+       ql_dbg(ql_dbg_disc, vha, 0x202b,
+           "Driver ver = %s.\n", eiter->a.driver_version);
 
        /* Option ROM version. */
        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1381,8 +1383,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
-       DEBUG13(printk("%s(%ld): OPTROMVER=%s.\n", __func__, vha->host_no,
-           eiter->a.orom_version));
+       ql_dbg(ql_dbg_disc, vha , 0x202c,
+           "Optrom vers = %s.\n", eiter->a.orom_version);
 
        /* Firmware version */
        eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1393,44 +1395,46 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
-       DEBUG13(printk("%s(%ld): FIRMWAREVER=%s.\n", __func__, vha->host_no,
-           eiter->a.fw_version));
+       ql_dbg(ql_dbg_disc, vha, 0x202d,
+           "Firmware vers = %s.\n", eiter->a.fw_version);
 
        /* Update MS request size. */
        qla2x00_update_ms_fdmi_iocb(vha, size + 16);
 
-       DEBUG13(printk("%s(%ld): RHBA identifier="
-           "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__,
-           vha->host_no, ct_req->req.rhba.hba_identifier[0],
+       ql_dbg(ql_dbg_disc, vha, 0x202e,
+           "RHBA identifier = "
+           "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n",
+           ct_req->req.rhba.hba_identifier[0],
            ct_req->req.rhba.hba_identifier[1],
            ct_req->req.rhba.hba_identifier[2],
            ct_req->req.rhba.hba_identifier[3],
            ct_req->req.rhba.hba_identifier[4],
            ct_req->req.rhba.hba_identifier[5],
            ct_req->req.rhba.hba_identifier[6],
-           ct_req->req.rhba.hba_identifier[7], size));
-       DEBUG13(qla2x00_dump_buffer(entries, size));
+           ct_req->req.rhba.hba_identifier[7], size);
+       ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076,
+           entries, size);
 
        /* Execute MS IOCB */
        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
            sizeof(ms_iocb_entry_t));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): RHBA issue IOCB failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x2030,
+                   "RHBA issue IOCB failed (%d).\n", rval);
        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
            QLA_SUCCESS) {
                rval = QLA_FUNCTION_FAILED;
                if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
                    ct_rsp->header.explanation_code ==
                    CT_EXPL_ALREADY_REGISTERED) {
-                       DEBUG2_13(printk("%s(%ld): HBA already registered.\n",
-                           __func__, vha->host_no));
+                       ql_dbg(ql_dbg_disc, vha, 0x2034,
+                           "HBA already registered.\n");
                        rval = QLA_ALREADY_REGISTERED;
                }
        } else {
-               DEBUG2(printk("scsi(%ld): RHBA exiting normally.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x2035,
+                   "RHBA exiting normally.\n");
        }
 
        return rval;
@@ -1464,26 +1468,26 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
        /* Prepare FDMI command arguments -- portname. */
        memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE);
 
-       DEBUG13(printk("%s(%ld): DHBA portname="
-           "%02x%02x%02x%02x%02x%02x%02x%02x.\n", __func__, vha->host_no,
+       ql_dbg(ql_dbg_disc, vha, 0x2036,
+           "DHBA portname = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
            ct_req->req.dhba.port_name[0], ct_req->req.dhba.port_name[1],
            ct_req->req.dhba.port_name[2], ct_req->req.dhba.port_name[3],
            ct_req->req.dhba.port_name[4], ct_req->req.dhba.port_name[5],
-           ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7]));
+           ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7]);
 
        /* Execute MS IOCB */
        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
            sizeof(ms_iocb_entry_t));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): DHBA issue IOCB failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x2037,
+                   "DHBA issue IOCB failed (%d).\n", rval);
        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "DHBA") !=
            QLA_SUCCESS) {
                rval = QLA_FUNCTION_FAILED;
        } else {
-               DEBUG2(printk("scsi(%ld): DHBA exiting normally.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x2038,
+                   "DHBA exiting normally.\n");
        }
 
        return rval;
@@ -1534,9 +1538,10 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
        eiter->a.fc4_types[2] = 0x01;
        size += 4 + 32;
 
-       DEBUG13(printk("%s(%ld): FC4_TYPES=%02x %02x.\n", __func__,
-               vha->host_no, eiter->a.fc4_types[2],
-               eiter->a.fc4_types[1]));
+       ql_dbg(ql_dbg_disc, vha, 0x2039,
+           "FC4_TYPES=%02x %02x.\n",
+           eiter->a.fc4_types[2],
+           eiter->a.fc4_types[1]);
 
        /* Supported speed. */
        eiter = (struct ct_fdmi_port_attr *) (entries + size);
@@ -1561,8 +1566,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
                    FDMI_PORT_SPEED_1GB);
        size += 4 + 4;
 
-       DEBUG13(printk("%s(%ld): SUPPORTED_SPEED=%x.\n", __func__, vha->host_no,
-           eiter->a.sup_speed));
+       ql_dbg(ql_dbg_disc, vha, 0x203a,
+           "Supported_Speed=%x.\n", eiter->a.sup_speed);
 
        /* Current speed. */
        eiter = (struct ct_fdmi_port_attr *) (entries + size);
@@ -1596,8 +1601,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
        }
        size += 4 + 4;
 
-       DEBUG13(printk("%s(%ld): CURRENT_SPEED=%x.\n", __func__, vha->host_no,
-           eiter->a.cur_speed));
+       ql_dbg(ql_dbg_disc, vha, 0x203b,
+           "Current_Speed=%x.\n", eiter->a.cur_speed);
 
        /* Max frame size. */
        eiter = (struct ct_fdmi_port_attr *) (entries + size);
@@ -1609,8 +1614,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
        eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
        size += 4 + 4;
 
-       DEBUG13(printk("%s(%ld): MAX_FRAME_SIZE=%x.\n", __func__, vha->host_no,
-           eiter->a.max_frame_size));
+       ql_dbg(ql_dbg_disc, vha, 0x203c,
+           "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
 
        /* OS device name. */
        eiter = (struct ct_fdmi_port_attr *) (entries + size);
@@ -1621,8 +1626,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
 
-       DEBUG13(printk("%s(%ld): OS_DEVICE_NAME=%s.\n", __func__, vha->host_no,
-           eiter->a.os_dev_name));
+       ql_dbg(ql_dbg_disc, vha, 0x204b,
+           "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
 
        /* Hostname. */
        if (strlen(fc_host_system_hostname(vha->host))) {
@@ -1637,35 +1642,36 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
                eiter->len = cpu_to_be16(4 + alen);
                size += 4 + alen;
 
-               DEBUG13(printk("%s(%ld): HOSTNAME=%s.\n", __func__,
-                   vha->host_no, eiter->a.host_name));
+               ql_dbg(ql_dbg_disc, vha, 0x203d,
+                   "HostName=%s.\n", eiter->a.host_name);
        }
 
        /* Update MS request size. */
        qla2x00_update_ms_fdmi_iocb(vha, size + 16);
 
-       DEBUG13(printk("%s(%ld): RPA portname="
-           "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__,
-           vha->host_no, ct_req->req.rpa.port_name[0],
-           ct_req->req.rpa.port_name[1], ct_req->req.rpa.port_name[2],
-           ct_req->req.rpa.port_name[3], ct_req->req.rpa.port_name[4],
-           ct_req->req.rpa.port_name[5], ct_req->req.rpa.port_name[6],
-           ct_req->req.rpa.port_name[7], size));
-       DEBUG13(qla2x00_dump_buffer(entries, size));
+       ql_dbg(ql_dbg_disc, vha, 0x203e,
+           "RPA portname= %02x%02x%02x%02x%02X%02x%02x%02x size=%d.\n",
+           ct_req->req.rpa.port_name[0], ct_req->req.rpa.port_name[1],
+           ct_req->req.rpa.port_name[2], ct_req->req.rpa.port_name[3],
+           ct_req->req.rpa.port_name[4], ct_req->req.rpa.port_name[5],
+           ct_req->req.rpa.port_name[6], ct_req->req.rpa.port_name[7],
+           size);
+       ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
+           entries, size);
 
        /* Execute MS IOCB */
        rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
            sizeof(ms_iocb_entry_t));
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3(printk("scsi(%ld): RPA issue IOCB failed (%d).\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x2040,
+                   "RPA issue IOCB failed (%d).\n", rval);
        } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
            QLA_SUCCESS) {
                rval = QLA_FUNCTION_FAILED;
        } else {
-               DEBUG2(printk("scsi(%ld): RPA exiting normally.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x2041,
+                   "RPA exiting nornally.\n");
        }
 
        return rval;
@@ -1749,8 +1755,8 @@ qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
                    sizeof(ms_iocb_entry_t));
                if (rval != QLA_SUCCESS) {
                        /*EMPTY*/
-                       DEBUG2_3(printk("scsi(%ld): GFPN_ID issue IOCB "
-                           "failed (%d).\n", vha->host_no, rval));
+                       ql_dbg(ql_dbg_disc, vha, 0x2023,
+                           "GFPN_ID issue IOCB failed (%d).\n", rval);
                } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
                    "GFPN_ID") != QLA_SUCCESS) {
                        rval = QLA_FUNCTION_FAILED;
@@ -1860,8 +1866,8 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
                    sizeof(ms_iocb_entry_t));
                if (rval != QLA_SUCCESS) {
                        /*EMPTY*/
-                       DEBUG2_3(printk("scsi(%ld): GPSC issue IOCB "
-                           "failed (%d).\n", vha->host_no, rval));
+                       ql_dbg(ql_dbg_disc, vha, 0x2059,
+                           "GPSC issue IOCB failed (%d).\n", rval);
                } else if ((rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
                    "GPSC")) != QLA_SUCCESS) {
                        /* FM command unsupported? */
@@ -1870,9 +1876,9 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
                                CT_REASON_INVALID_COMMAND_CODE ||
                             ct_rsp->header.reason_code ==
                                CT_REASON_COMMAND_UNSUPPORTED)) {
-                               DEBUG2(printk("scsi(%ld): GPSC command "
-                                   "unsupported, disabling query...\n",
-                                   vha->host_no));
+                               ql_dbg(ql_dbg_disc, vha, 0x205a,
+                                   "GPSC command unsupported, disabling "
+                                   "query.\n");
                                ha->flags.gpsc_supported = 0;
                                rval = QLA_FUNCTION_FAILED;
                                break;
@@ -1898,9 +1904,10 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
                                break;
                        }
 
-                       DEBUG2_3(printk("scsi(%ld): GPSC ext entry - "
-                           "fpn %02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x "
-                           "speed=%04x.\n", vha->host_no,
+                       ql_dbg(ql_dbg_disc, vha, 0x205b,
+                           "GPSC ext entry - fpn "
+                           "%02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x "
+                           "speed=%04x.\n",
                            list[i].fabric_port_name[0],
                            list[i].fabric_port_name[1],
                            list[i].fabric_port_name[2],
@@ -1910,7 +1917,7 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
                            list[i].fabric_port_name[6],
                            list[i].fabric_port_name[7],
                            be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
-                           be16_to_cpu(ct_rsp->rsp.gpsc.speed)));
+                           be16_to_cpu(ct_rsp->rsp.gpsc.speed));
                }
 
                /* Last device exit. */
@@ -1968,14 +1975,12 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
                   sizeof(ms_iocb_entry_t));
 
                if (rval != QLA_SUCCESS) {
-                       DEBUG2_3(printk(KERN_INFO
-                           "scsi(%ld): GFF_ID issue IOCB failed "
-                           "(%d).\n", vha->host_no, rval));
+                       ql_dbg(ql_dbg_disc, vha, 0x205c,
+                           "GFF_ID issue IOCB failed (%d).\n", rval);
                } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
                               "GFF_ID") != QLA_SUCCESS) {
-                       DEBUG2_3(printk(KERN_INFO
-                           "scsi(%ld): GFF_ID IOCB status had a "
-                           "failure status code\n", vha->host_no));
+                       ql_dbg(ql_dbg_disc, vha, 0x205d,
+                           "GFF_ID IOCB status had a failure status code.\n");
                } else {
                        fcp_scsi_features =
                           ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
index 920b76b..def6942 100644 (file)
@@ -153,11 +153,10 @@ qla2x00_async_iocb_timeout(srb_t *sp)
        fc_port_t *fcport = sp->fcport;
        struct srb_ctx *ctx = sp->ctx;
 
-       DEBUG2(printk(KERN_WARNING
-               "scsi(%ld:%x): Async-%s timeout - portid=%02x%02x%02x.\n",
-               fcport->vha->host_no, sp->handle,
-               ctx->name, fcport->d_id.b.domain,
-               fcport->d_id.b.area, fcport->d_id.b.al_pa));
+       ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
+           "Async-%s timeout - portid=%02x%02x%02x.\n",
+           ctx->name, fcport->d_id.b.domain, fcport->d_id.b.area,
+           fcport->d_id.b.al_pa);
 
        fcport->flags &= ~FCF_ASYNC_SENT;
        if (ctx->type == SRB_LOGIN_CMD) {
@@ -211,11 +210,10 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
        if (rval != QLA_SUCCESS)
                goto done_free_sp;
 
-       DEBUG2(printk(KERN_DEBUG
-           "scsi(%ld:%x): Async-login - loop-id=%x portid=%02x%02x%02x "
-           "retries=%d.\n", fcport->vha->host_no, sp->handle, fcport->loop_id,
-           fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
-           fcport->login_retry));
+       ql_dbg(ql_dbg_disc, vha, 0x2072,
+           "Async-login - loopid=%x portid=%02x%02x%02x retries=%d.\n",
+           fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
+           fcport->d_id.b.al_pa, fcport->login_retry);
        return rval;
 
 done_free_sp:
@@ -259,10 +257,10 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
        if (rval != QLA_SUCCESS)
                goto done_free_sp;
 
-       DEBUG2(printk(KERN_DEBUG
-           "scsi(%ld:%x): Async-logout - loop-id=%x portid=%02x%02x%02x.\n",
-           fcport->vha->host_no, sp->handle, fcport->loop_id,
-           fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa));
+       ql_dbg(ql_dbg_disc, vha, 0x2070,
+           "Async-logout - loop-id=%x portid=%02x%02x%02x.\n",
+           fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
+           fcport->d_id.b.al_pa);
        return rval;
 
 done_free_sp:
@@ -309,11 +307,10 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
        if (rval != QLA_SUCCESS)
                goto done_free_sp;
 
-       DEBUG2(printk(KERN_DEBUG
-           "scsi(%ld:%x): Async-adisc - loop-id=%x portid=%02x%02x%02x.\n",
-           fcport->vha->host_no, sp->handle, fcport->loop_id,
-           fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa));
-
+       ql_dbg(ql_dbg_disc, vha, 0x206f,
+           "Async-adisc - loopid=%x portid=%02x%02x%02x.\n",
+           fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
+           fcport->d_id.b.al_pa);
        return rval;
 
 done_free_sp:
@@ -362,11 +359,10 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
        if (rval != QLA_SUCCESS)
                goto done_free_sp;
 
-       DEBUG2(printk(KERN_DEBUG
-           "scsi(%ld:%x): Async-tmf - loop-id=%x portid=%02x%02x%02x.\n",
-           fcport->vha->host_no, sp->handle, fcport->loop_id,
-           fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa));
-
+       ql_dbg(ql_dbg_taskm, vha, 0x802f,
+           "Async-tmf loop-id=%x portid=%02x%02x%02x.\n",
+           fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
+           fcport->d_id.b.al_pa);
        return rval;
 
 done_free_sp:
@@ -471,9 +467,8 @@ qla2x00_async_tm_cmd_done(struct scsi_qla_host *vha, fc_port_t *fcport,
                flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
 
        if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) {
-               DEBUG2_3_11(printk(KERN_WARNING
-                       "%s(%ld): TM IOCB failed (%x).\n",
-                       __func__, vha->host_no, rval));
+               ql_dbg(ql_dbg_taskm, vha, 0x8030,
+                   "TM IOCB failed (%x).\n", rval);
        }
 
        return;
@@ -519,11 +514,12 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
        set_bit(0, ha->req_qid_map);
        set_bit(0, ha->rsp_qid_map);
 
-       qla_printk(KERN_INFO, ha, "Configuring PCI space...\n");
+       ql_log(ql_log_info, vha, 0x0040,
+           "Configuring PCI space...\n");
        rval = ha->isp_ops->pci_config(vha);
        if (rval) {
-               DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n",
-                   vha->host_no));
+               ql_log(ql_log_warn, vha, 0x0044,
+                   "Unable to configure PCI space.\n");
                return (rval);
        }
 
@@ -531,20 +527,21 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
 
        rval = qla2xxx_get_flash_info(vha);
        if (rval) {
-               DEBUG2(printk("scsi(%ld): Unable to validate FLASH data.\n",
-                   vha->host_no));
+               ql_log(ql_log_fatal, vha, 0x004f,
+                   "Unable to validate FLASH data.\n");
                return (rval);
        }
 
        ha->isp_ops->get_flash_version(vha, req->ring);
-
-       qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n");
+       ql_log(ql_log_info, vha, 0x0061,
+           "Configure NVRAM parameters...\n");
 
        ha->isp_ops->nvram_config(vha);
 
        if (ha->flags.disable_serdes) {
                /* Mask HBA via NVRAM settings? */
-               qla_printk(KERN_INFO, ha, "Masking HBA WWPN "
+               ql_log(ql_log_info, vha, 0x0077,
+                   "Masking HBA WWPN "
                    "%02x%02x%02x%02x%02x%02x%02x%02x (via NVRAM).\n",
                    vha->port_name[0], vha->port_name[1],
                    vha->port_name[2], vha->port_name[3],
@@ -553,7 +550,8 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
                return QLA_FUNCTION_FAILED;
        }
 
-       qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n");
+       ql_log(ql_log_info, vha, 0x0078,
+           "Verifying loaded RISC code...\n");
 
        if (qla2x00_isp_firmware(vha) != QLA_SUCCESS) {
                rval = ha->isp_ops->chip_diag(vha);
@@ -567,7 +565,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
        if (IS_QLA84XX(ha)) {
                ha->cs84xx = qla84xx_get_chip(vha);
                if (!ha->cs84xx) {
-                       qla_printk(KERN_ERR, ha,
+                       ql_log(ql_log_warn, vha, 0x00d0,
                            "Unable to configure ISP84XX.\n");
                        return QLA_FUNCTION_FAILED;
                }
@@ -579,8 +577,8 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
                /* Issue verify 84xx FW IOCB to complete 84xx initialization */
                rval = qla84xx_init_chip(vha);
                if (rval != QLA_SUCCESS) {
-                       qla_printk(KERN_ERR, ha,
-                               "Unable to initialize ISP84XX.\n");
+                       ql_log(ql_log_warn, vha, 0x00d4,
+                           "Unable to initialize ISP84XX.\n");
                qla84xx_put_chip(vha);
                }
        }
@@ -797,9 +795,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *vha)
        rval = QLA_FUNCTION_FAILED;
 
        if (ha->flags.disable_risc_code_load) {
-               DEBUG2(printk("scsi(%ld): RISC CODE NOT loaded\n",
-                   vha->host_no));
-               qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n");
+               ql_log(ql_log_info, vha, 0x0079, "RISC CODE NOT loaded.\n");
 
                /* Verify checksum of loaded RISC code. */
                rval = qla2x00_verify_checksum(vha, ha->fw_srisc_address);
@@ -810,10 +806,9 @@ qla2x00_isp_firmware(scsi_qla_host_t *vha)
                }
        }
 
-       if (rval) {
-               DEBUG2_3(printk("scsi(%ld): **** Load RISC code ****\n",
-                   vha->host_no));
-       }
+       if (rval)
+               ql_dbg(ql_dbg_init, vha, 0x007a,
+                   "**** Load RISC code ****.\n");
 
        return (rval);
 }
@@ -1105,8 +1100,8 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
        /* Assume a failed state */
        rval = QLA_FUNCTION_FAILED;
 
-       DEBUG3(printk("scsi(%ld): Testing device at %lx.\n",
-           vha->host_no, (u_long)&reg->flash_address));
+       ql_dbg(ql_dbg_init, vha, 0x007b,
+           "Testing device at %lx.\n", (u_long)&reg->flash_address);
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
 
@@ -1128,8 +1123,8 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
        if (!cnt)
                goto chip_diag_failed;
 
-       DEBUG3(printk("scsi(%ld): Reset register cleared by chip reset\n",
-           vha->host_no));
+       ql_dbg(ql_dbg_init, vha, 0x007c,
+           "Reset register cleared by chip reset.\n");
 
        /* Reset RISC processor. */
        WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
@@ -1150,7 +1145,7 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
                goto chip_diag_failed;
 
        /* Check product ID of chip */
-       DEBUG3(printk("scsi(%ld): Checking product ID of chip\n", vha->host_no));
+       ql_dbg(ql_dbg_init, vha, 0x007d, "Checking product Id of chip.\n");
 
        mb[1] = RD_MAILBOX_REG(ha, reg, 1);
        mb[2] = RD_MAILBOX_REG(ha, reg, 2);
@@ -1158,8 +1153,9 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
        mb[4] = qla2x00_debounce_register(MAILBOX_REG(ha, reg, 4));
        if (mb[1] != PROD_ID_1 || (mb[2] != PROD_ID_2 && mb[2] != PROD_ID_2a) ||
            mb[3] != PROD_ID_3) {
-               qla_printk(KERN_WARNING, ha,
-                   "Wrong product ID = 0x%x,0x%x,0x%x\n", mb[1], mb[2], mb[3]);
+               ql_log(ql_log_warn, vha, 0x0062,
+                   "Wrong product ID = 0x%x,0x%x,0x%x.\n",
+                   mb[1], mb[2], mb[3]);
 
                goto chip_diag_failed;
        }
@@ -1178,8 +1174,7 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
        if (IS_QLA2200(ha) &&
            RD_MAILBOX_REG(ha, reg, 7) == QLA2200A_RISC_ROM_VER) {
                /* Limit firmware transfer size with a 2200A */
-               DEBUG3(printk("scsi(%ld): Found QLA2200A chip.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_init, vha, 0x007e, "Found QLA2200A Chip.\n");
 
                ha->device_type |= DT_ISP2200A;
                ha->fw_transfer_size = 128;
@@ -1188,24 +1183,20 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
        /* Wrap Incoming Mailboxes Test. */
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-       DEBUG3(printk("scsi(%ld): Checking mailboxes.\n", vha->host_no));
+       ql_dbg(ql_dbg_init, vha, 0x007f, "Checking mailboxes.\n");
        rval = qla2x00_mbx_reg_test(vha);
-       if (rval) {
-               DEBUG(printk("scsi(%ld): Failed mailbox send register test\n",
-                   vha->host_no));
-               qla_printk(KERN_WARNING, ha,
-                   "Failed mailbox send register test\n");
-       }
-       else {
+       if (rval)
+               ql_log(ql_log_warn, vha, 0x0080,
+                   "Failed mailbox send register test.\n");
+       else
                /* Flag a successful rval */
                rval = QLA_SUCCESS;
-       }
        spin_lock_irqsave(&ha->hardware_lock, flags);
 
 chip_diag_failed:
        if (rval)
-               DEBUG2_3(printk("scsi(%ld): Chip diagnostics **** FAILED "
-                   "****\n", vha->host_no));
+               ql_log(ql_log_info, vha, 0x0081,
+                   "Chip diagnostics **** FAILED ****.\n");
 
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
@@ -1232,10 +1223,8 @@ qla24xx_chip_diag(scsi_qla_host_t *vha)
 
        rval = qla2x00_mbx_reg_test(vha);
        if (rval) {
-               DEBUG(printk("scsi(%ld): Failed mailbox send register test\n",
-                   vha->host_no));
-               qla_printk(KERN_WARNING, ha,
-                   "Failed mailbox send register test\n");
+               ql_log(ql_log_warn, vha, 0x0082,
+                   "Failed mailbox send register test.\n");
        } else {
                /* Flag a successful rval */
                rval = QLA_SUCCESS;
@@ -1257,8 +1246,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
        struct rsp_que *rsp = ha->rsp_q_map[0];
 
        if (ha->fw_dump) {
-               qla_printk(KERN_WARNING, ha,
-                   "Firmware dump previously allocated.\n");
+               ql_dbg(ql_dbg_init, vha, 0x00bd,
+                   "Firmware dump already allocated.\n");
                return;
        }
 
@@ -1288,8 +1277,9 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
                tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
                    GFP_KERNEL);
                if (!tc) {
-                       qla_printk(KERN_WARNING, ha, "Unable to allocate "
-                           "(%d KB) for FCE.\n", FCE_SIZE / 1024);
+                       ql_log(ql_log_warn, vha, 0x00be,
+                           "Unable to allocate (%d KB) for FCE.\n",
+                           FCE_SIZE / 1024);
                        goto try_eft;
                }
 
@@ -1297,16 +1287,15 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
                rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
                    ha->fce_mb, &ha->fce_bufs);
                if (rval) {
-                       qla_printk(KERN_WARNING, ha, "Unable to initialize "
-                           "FCE (%d).\n", rval);
+                       ql_log(ql_log_warn, vha, 0x00bf,
+                           "Unable to initialize FCE (%d).\n", rval);
                        dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc,
                            tc_dma);
                        ha->flags.fce_enabled = 0;
                        goto try_eft;
                }
-
-               qla_printk(KERN_INFO, ha, "Allocated (%d KB) for FCE...\n",
-                   FCE_SIZE / 1024);
+               ql_log(ql_log_info, vha, 0x00c0,
+                   "Allocate (%d KB) for FCE...\n", FCE_SIZE / 1024);
 
                fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
                ha->flags.fce_enabled = 1;
@@ -1317,23 +1306,23 @@ try_eft:
                tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
                    GFP_KERNEL);
                if (!tc) {
-                       qla_printk(KERN_WARNING, ha, "Unable to allocate "
-                           "(%d KB) for EFT.\n", EFT_SIZE / 1024);
+                       ql_log(ql_log_warn, vha, 0x00c1,
+                           "Unable to allocate (%d KB) for EFT.\n",
+                           EFT_SIZE / 1024);
                        goto cont_alloc;
                }
 
                memset(tc, 0, EFT_SIZE);
                rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
                if (rval) {
-                       qla_printk(KERN_WARNING, ha, "Unable to initialize "
-                           "EFT (%d).\n", rval);
+                       ql_log(ql_log_warn, vha, 0x00c2,
+                           "Unable to initialize EFT (%d).\n", rval);
                        dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
                            tc_dma);
                        goto cont_alloc;
                }
-
-               qla_printk(KERN_INFO, ha, "Allocated (%d KB) for EFT...\n",
-                   EFT_SIZE / 1024);
+               ql_log(ql_log_info, vha, 0x00c3,
+                   "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
 
                eft_size = EFT_SIZE;
                ha->eft_dma = tc_dma;
@@ -1350,8 +1339,9 @@ cont_alloc:
 
        ha->fw_dump = vmalloc(dump_size);
        if (!ha->fw_dump) {
-               qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for "
-                   "firmware dump!!!\n", dump_size / 1024);
+               ql_log(ql_log_warn, vha, 0x00c4,
+                   "Unable to allocate (%d KB) for firmware dump.\n",
+                   dump_size / 1024);
 
                if (ha->fce) {
                        dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
@@ -1368,8 +1358,8 @@ cont_alloc:
                }
                return;
        }
-       qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware dump...\n",
-           dump_size / 1024);
+       ql_log(ql_log_info, vha, 0x00c5,
+           "Allocated (%d KB) for firmware dump.\n", dump_size / 1024);
 
        ha->fw_dump_len = dump_size;
        ha->fw_dump->signature[0] = 'Q';
@@ -1398,23 +1388,21 @@ qla81xx_mpi_sync(scsi_qla_host_t *vha)
        int rval;
        uint16_t dc;
        uint32_t dw;
-       struct qla_hw_data *ha = vha->hw;
 
        if (!IS_QLA81XX(vha->hw))
                return QLA_SUCCESS;
 
        rval = qla2x00_write_ram_word(vha, 0x7c00, 1);
        if (rval != QLA_SUCCESS) {
-               DEBUG2(qla_printk(KERN_WARNING, ha,
-                   "Sync-MPI: Unable to acquire semaphore.\n"));
+               ql_log(ql_log_warn, vha, 0x0105,
+                   "Unable to acquire semaphore.\n");
                goto done;
        }
 
        pci_read_config_word(vha->hw->pdev, 0x54, &dc);
        rval = qla2x00_read_ram_word(vha, 0x7a15, &dw);
        if (rval != QLA_SUCCESS) {
-               DEBUG2(qla_printk(KERN_WARNING, ha,
-                   "Sync-MPI: Unable to read sync.\n"));
+               ql_log(ql_log_warn, vha, 0x0067, "Unable to read sync.\n");
                goto done_release;
        }
 
@@ -1426,15 +1414,14 @@ qla81xx_mpi_sync(scsi_qla_host_t *vha)
        dw |= dc;
        rval = qla2x00_write_ram_word(vha, 0x7a15, dw);
        if (rval != QLA_SUCCESS) {
-               DEBUG2(qla_printk(KERN_WARNING, ha,
-                   "Sync-MPI: Unable to gain sync.\n"));
+               ql_log(ql_log_warn, vha, 0x0114, "Unable to gain sync.\n");
        }
 
 done_release:
        rval = qla2x00_write_ram_word(vha, 0x7c00, 0);
        if (rval != QLA_SUCCESS) {
-               DEBUG2(qla_printk(KERN_WARNING, ha,
-                   "Sync-MPI: Unable to release semaphore.\n"));
+               ql_log(ql_log_warn, vha, 0x006d,
+                   "Unable to release semaphore.\n");
        }
 
 done:
@@ -1479,14 +1466,14 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
        /* Load firmware sequences */
        rval = ha->isp_ops->load_risc(vha, &srisc_address);
        if (rval == QLA_SUCCESS) {
-               DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC "
-                   "code.\n", vha->host_no));
+               ql_dbg(ql_dbg_init, vha, 0x00c9,
+                   "Verifying Checksum of loaded RISC code.\n");
 
                rval = qla2x00_verify_checksum(vha, srisc_address);
                if (rval == QLA_SUCCESS) {
                        /* Start firmware execution. */
-                       DEBUG(printk("scsi(%ld): Checksum OK, start "
-                           "firmware.\n", vha->host_no));
+                       ql_dbg(ql_dbg_init, vha, 0x00ca,
+                           "Starting firmware.\n");
 
                        rval = qla2x00_execute_fw(vha, srisc_address);
                        /* Retrieve firmware information. */
@@ -1522,9 +1509,9 @@ enable_82xx_npiv:
                                }
                        }
                } else {
-                       DEBUG2(printk(KERN_INFO
-                           "scsi(%ld): ISP Firmware failed checksum.\n",
-                           vha->host_no));
+                       ql_log(ql_log_fatal, vha, 0x00cd,
+                           "ISP Firmware failed checksum.\n");
+                       goto failed;
                }
        }
 
@@ -1549,7 +1536,7 @@ enable_82xx_npiv:
                        ha->flags.fac_supported = 1;
                        ha->fdt_block_size = size << 2;
                } else {
-                       qla_printk(KERN_ERR, ha,
+                       ql_log(ql_log_warn, vha, 0x00ce,
                            "Unsupported FAC firmware (%d.%02d.%02d).\n",
                            ha->fw_major_version, ha->fw_minor_version,
                            ha->fw_subminor_version);
@@ -1557,8 +1544,8 @@ enable_82xx_npiv:
        }
 failed:
        if (rval) {
-               DEBUG2_3(printk("scsi(%ld): Setup chip **** FAILED ****.\n",
-                   vha->host_no));
+               ql_log(ql_log_fatal, vha, 0x00cf,
+                   "Setup chip ****FAILED****.\n");
        }
 
        return (rval);
@@ -1608,10 +1595,11 @@ qla2x00_update_fw_options(scsi_qla_host_t *vha)
                return;
 
        /* Serial Link options. */
-       DEBUG3(printk("scsi(%ld): Serial link options:\n",
-           vha->host_no));
-       DEBUG3(qla2x00_dump_buffer((uint8_t *)&ha->fw_seriallink_options,
-           sizeof(ha->fw_seriallink_options)));
+       ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0115,
+           "Serial link options.\n");
+       ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0109,
+           (uint8_t *)&ha->fw_seriallink_options,
+           sizeof(ha->fw_seriallink_options));
 
        ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
        if (ha->fw_seriallink_options[3] & BIT_2) {
@@ -1688,7 +1676,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
            le16_to_cpu(ha->fw_seriallink_options24[2]),
            le16_to_cpu(ha->fw_seriallink_options24[3]));
        if (rval != QLA_SUCCESS) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x0104,
                    "Unable to update Serial Link options (%x).\n", rval);
        }
 }
@@ -1746,8 +1734,9 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
                icb->rid = __constant_cpu_to_le16(rid);
                if (ha->flags.msix_enabled) {
                        msix = &ha->msix_entries[1];
-                       DEBUG2_17(printk(KERN_INFO
-                       "Registering vector 0x%x for base que\n", msix->entry));
+                       ql_dbg(ql_dbg_init, vha, 0x00fd,
+                           "Registering vector 0x%x for base que.\n",
+                           msix->entry);
                        icb->msix = cpu_to_le16(msix->entry);
                }
                /* Use alternate PCI bus number */
@@ -1764,8 +1753,8 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
                        icb->firmware_options_2 &=
                                __constant_cpu_to_le32(~BIT_22);
                        ha->flags.disable_msix_handshake = 1;
-                       qla_printk(KERN_INFO, ha,
-                               "MSIX Handshake Disable Mode turned on\n");
+                       ql_dbg(ql_dbg_init, vha, 0x00fe,
+                           "MSIX Handshake Disable Mode turned on.\n");
                } else {
                        icb->firmware_options_2 |=
                                __constant_cpu_to_le32(BIT_22);
@@ -1850,7 +1839,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
        /* Update any ISP specific firmware options before initialization. */
        ha->isp_ops->update_fw_options(vha);
 
-       DEBUG(printk("scsi(%ld): Issue init firmware.\n", vha->host_no));
+       ql_dbg(ql_dbg_init, vha, 0x00d1, "Issue init firmware.\n");
 
        if (ha->flags.npiv_supported) {
                if (ha->operating_mode == LOOP)
@@ -1866,11 +1855,11 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
 
        rval = qla2x00_init_firmware(vha, ha->init_cb_size);
        if (rval) {
-               DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n",
-                   vha->host_no));
+               ql_log(ql_log_fatal, vha, 0x00d2,
+                   "Init Firmware **** FAILED ****.\n");
        } else {
-               DEBUG3(printk("scsi(%ld): Init firmware -- success.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_init, vha, 0x00d3,
+                   "Init Firmware -- success.\n");
        }
 
        return (rval);
@@ -1913,10 +1902,8 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
 
        /* Wait for ISP to finish LIP */
        if (!vha->flags.init_done)
-               qla_printk(KERN_INFO, ha, "Waiting for LIP to complete...\n");
-
-       DEBUG3(printk("scsi(%ld): Waiting for LIP to complete...\n",
-           vha->host_no));
+               ql_log(ql_log_info, vha, 0x801e,
+                   "Waiting for LIP to complete.\n");
 
        do {
                rval = qla2x00_get_firmware_state(vha, state);
@@ -1925,30 +1912,35 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
                                vha->device_flags &= ~DFLG_NO_CABLE;
                        }
                        if (IS_QLA84XX(ha) && state[0] != FSTATE_READY) {
-                               DEBUG16(printk("scsi(%ld): fw_state=%x "
-                                   "84xx=%x.\n", vha->host_no, state[0],
-                                   state[2]));
+                               ql_dbg(ql_dbg_taskm, vha, 0x801f,
+                                   "fw_state=%x 84xx=%x.\n", state[0],
+                                   state[2]);
                                if ((state[2] & FSTATE_LOGGED_IN) &&
                                     (state[2] & FSTATE_WAITING_FOR_VERIFY)) {
-                                       DEBUG16(printk("scsi(%ld): Sending "
-                                           "verify iocb.\n", vha->host_no));
+                                       ql_dbg(ql_dbg_taskm, vha, 0x8028,
+                                           "Sending verify iocb.\n");
 
                                        cs84xx_time = jiffies;
                                        rval = qla84xx_init_chip(vha);
-                                       if (rval != QLA_SUCCESS)
+                                       if (rval != QLA_SUCCESS) {
+                                               ql_log(ql_log_warn,
+                                                   vha, 0x8043,
+                                                   "Init chip failed.\n");
                                                break;
+                                       }
 
                                        /* Add time taken to initialize. */
                                        cs84xx_time = jiffies - cs84xx_time;
                                        wtime += cs84xx_time;
                                        mtime += cs84xx_time;
-                                       DEBUG16(printk("scsi(%ld): Increasing "
-                                           "wait time by %ld. New time %ld\n",
-                                           vha->host_no, cs84xx_time, wtime));
+                                       ql_dbg(ql_dbg_taskm, vha, 0x8042,
+                                           "Increasing wait time by %ld. "
+                                           "New time %ld.\n", cs84xx_time,
+                                           wtime);
                                }
                        } else if (state[0] == FSTATE_READY) {
-                               DEBUG(printk("scsi(%ld): F/W Ready - OK \n",
-                                   vha->host_no));
+                               ql_dbg(ql_dbg_taskm, vha, 0x8037,
+                                   "F/W Ready - OK.\n");
 
                                qla2x00_get_retry_cnt(vha, &ha->retry_count,
                                    &ha->login_timeout, &ha->r_a_tov);
@@ -1965,7 +1957,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
                                 * other than Wait for Login.
                                 */
                                if (time_after_eq(jiffies, mtime)) {
-                                       qla_printk(KERN_INFO, ha,
+                                       ql_log(ql_log_info, vha, 0x8038,
                                            "Cable is unplugged...\n");
 
                                        vha->device_flags |= DFLG_NO_CABLE;
@@ -1985,17 +1977,17 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
                /* Delay for a while */
                msleep(500);
 
-               DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
-                   vha->host_no, state[0], jiffies));
+               ql_dbg(ql_dbg_taskm, vha, 0x8039,
+                   "fw_state=%x curr time=%lx.\n", state[0], jiffies);
        } while (1);
 
-       DEBUG(printk("scsi(%ld): fw_state=%x (%x, %x, %x, %x) curr time=%lx.\n",
-           vha->host_no, state[0], state[1], state[2], state[3], state[4],
-           jiffies));
+       ql_dbg(ql_dbg_taskm, vha, 0x803a,
+           "fw_state=%x (%x, %x, %x, %x) " "curr time=%lx.\n", state[0],
+           state[1], state[2], state[3], state[4], jiffies);
 
        if (rval) {
-               DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n",
-                   vha->host_no));
+               ql_log(ql_log_warn, vha, 0x803b,
+                   "Firmware ready **** FAILED ****.\n");
        }
 
        return (rval);
@@ -2034,19 +2026,19 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
                if (LOOP_TRANSITION(vha) || atomic_read(&ha->loop_down_timer) ||
                    IS_QLA8XXX_TYPE(ha) ||
                    (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {
-                       DEBUG2(printk("%s(%ld) Loop is in a transition state\n",
-                           __func__, vha->host_no));
+                       ql_dbg(ql_dbg_disc, vha, 0x2008,
+                           "Loop is in a transition state.\n");
                } else {
-                       qla_printk(KERN_WARNING, ha,
-                           "ERROR -- Unable to get host loop ID.\n");
+                       ql_log(ql_log_warn, vha, 0x2009,
+                           "Unable to get host loop ID.\n");
                        set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
                }
                return (rval);
        }
 
        if (topo == 4) {
-               qla_printk(KERN_INFO, ha,
-                       "Cannot get topology - retrying.\n");
+               ql_log(ql_log_info, vha, 0x200a,
+                   "Cannot get topology - retrying.\n");
                return (QLA_FUNCTION_FAILED);
        }
 
@@ -2059,31 +2051,27 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
 
        switch (topo) {
        case 0:
-               DEBUG3(printk("scsi(%ld): HBA in NL topology.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x200b, "HBA in NL topology.\n");
                ha->current_topology = ISP_CFG_NL;
                strcpy(connect_type, "(Loop)");
                break;
 
        case 1:
-               DEBUG3(printk("scsi(%ld): HBA in FL topology.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x200c, "HBA in FL topology.\n");
                ha->switch_cap = sw_cap;
                ha->current_topology = ISP_CFG_FL;
                strcpy(connect_type, "(FL_Port)");
                break;
 
        case 2:
-               DEBUG3(printk("scsi(%ld): HBA in N P2P topology.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x200d, "HBA in N P2P topology.\n");
                ha->operating_mode = P2P;
                ha->current_topology = ISP_CFG_N;
                strcpy(connect_type, "(N_Port-to-N_Port)");
                break;
 
        case 3:
-               DEBUG3(printk("scsi(%ld): HBA in F P2P topology.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x200e, "HBA in F P2P topology.\n");
                ha->switch_cap = sw_cap;
                ha->operating_mode = P2P;
                ha->current_topology = ISP_CFG_F;
@@ -2091,9 +2079,8 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
                break;
 
        default:
-               DEBUG3(printk("scsi(%ld): HBA in unknown topology %x. "
-                   "Using NL.\n",
-                   vha->host_no, topo));
+               ql_dbg(ql_dbg_disc, vha, 0x200f,
+                   "HBA in unknown topology %x, using NL.\n", topo);
                ha->current_topology = ISP_CFG_NL;
                strcpy(connect_type, "(Loop)");
                break;
@@ -2106,14 +2093,16 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
        vha->d_id.b.al_pa = al_pa;
 
        if (!vha->flags.init_done)
-               qla_printk(KERN_INFO, ha,
-                   "Topology - %s, Host Loop address 0x%x\n",
+               ql_log(ql_log_info, vha, 0x2010,
+                   "Topology - %s, Host Loop address 0x%x.\n",
                    connect_type, vha->loop_id);
 
        if (rval) {
-               DEBUG2_3(printk("scsi(%ld): FAILED.\n", vha->host_no));
+               ql_log(ql_log_warn, vha, 0x2011,
+                   "%s FAILED\n", __func__);
        } else {
-               DEBUG3(printk("scsi(%ld): exiting normally.\n", vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x2012,
+                   "%s success\n", __func__);
        }
 
        return(rval);
@@ -2227,18 +2216,22 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
        for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++)
                chksum += *ptr++;
 
-       DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", vha->host_no));
-       DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));
+       ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x010f,
+           "Contents of NVRAM.\n");
+       ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0110,
+           (uint8_t *)nv, ha->nvram_size);
 
        /* Bad NVRAM data, set defaults parameters. */
        if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
            nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) {
                /* Reset NVRAM data. */
-               qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
-                   "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
-                   nv->nvram_version);
-               qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
-                   "invalid -- WWPN) defaults.\n");
+               ql_log(ql_log_warn, vha, 0x0064,
+                   "Inconisistent NVRAM "
+                   "detected: checksum=0x%x id=%c version=0x%x.\n",
+                   chksum, nv->id[0], nv->nvram_version);
+               ql_log(ql_log_warn, vha, 0x0065,
+                   "Falling back to "
+                   "functioning (yet invalid -- WWPN) defaults.\n");
 
                /*
                 * Set default initialization control block.
@@ -2382,8 +2375,13 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
        /*
         * Set host adapter parameters.
         */
+
+       /*
+        * BIT_7 in the host-parameters section allows for modification to
+        * internal driver logging.
+        */
        if (nv->host_p[0] & BIT_7)
-               ql2xextended_error_logging = 1;
+               ql2xextended_error_logging = 0x7fffffff;
        ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0);
        /* Always load RISC code on non ISP2[12]00 chips. */
        if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
@@ -2488,10 +2486,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
                if (ha->zio_mode != QLA_ZIO_DISABLED) {
                        ha->zio_mode = QLA_ZIO_MODE_6;
 
-                       DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer "
-                           "delay (%d us).\n", vha->host_no, ha->zio_mode,
-                           ha->zio_timer * 100));
-                       qla_printk(KERN_INFO, ha,
+                       ql_log(ql_log_info, vha, 0x0068,
                            "ZIO mode %d enabled; timer delay (%d us).\n",
                            ha->zio_mode, ha->zio_timer * 100);
 
@@ -2502,8 +2497,8 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
        }
 
        if (rval) {
-               DEBUG2_3(printk(KERN_WARNING
-                   "scsi(%ld): NVRAM configuration failed!\n", vha->host_no));
+               ql_log(ql_log_warn, vha, 0x0069,
+                   "NVRAM configuration failed.\n");
        }
        return (rval);
 }
@@ -2574,15 +2569,15 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
        if (test_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags)) {
                rval = qla2x00_configure_hba(vha);
                if (rval != QLA_SUCCESS) {
-                       DEBUG(printk("scsi(%ld): Unable to configure HBA.\n",
-                           vha->host_no));
+                       ql_dbg(ql_dbg_disc, vha, 0x2013,
+                           "Unable to configure HBA.\n");
                        return (rval);
                }
        }
 
        save_flags = flags = vha->dpc_flags;
-       DEBUG(printk("scsi(%ld): Configure loop -- dpc flags =0x%lx\n",
-           vha->host_no, flags));
+       ql_dbg(ql_dbg_disc, vha, 0x2014,
+           "Configure loop -- dpc flags = 0x%lx.\n", flags);
 
        /*
         * If we have both an RSCN and PORT UPDATE pending then handle them
@@ -2619,15 +2614,21 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
        }
 
        if (test_bit(LOCAL_LOOP_UPDATE, &flags)) {
-               if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+               if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
+                       ql_dbg(ql_dbg_disc, vha, 0x2015,
+                           "Loop resync needed, failing.\n");
                        rval = QLA_FUNCTION_FAILED;
+               }
                else
                        rval = qla2x00_configure_local_loop(vha);
        }
 
        if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) {
-               if (LOOP_TRANSITION(vha))
+               if (LOOP_TRANSITION(vha)) {
+                       ql_dbg(ql_dbg_disc, vha, 0x201e,
+                           "Needs RSCN update and loop transition.\n");
                        rval = QLA_FUNCTION_FAILED;
+               }
                else
                        rval = qla2x00_configure_fabric(vha);
        }
@@ -2638,16 +2639,17 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
                        rval = QLA_FUNCTION_FAILED;
                } else {
                        atomic_set(&vha->loop_state, LOOP_READY);
-
-                       DEBUG(printk("scsi(%ld): LOOP READY\n", vha->host_no));
+                       ql_dbg(ql_dbg_disc, vha, 0x2069,
+                           "LOOP READY.\n");
                }
        }
 
        if (rval) {
-               DEBUG2_3(printk("%s(%ld): *** FAILED ***\n",
-                   __func__, vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x206a,
+                   "%s *** FAILED ***.\n", __func__);
        } else {
-               DEBUG3(printk("%s: exiting normally\n", __func__));
+               ql_dbg(ql_dbg_disc, vha, 0x206b,
+                   "%s: exiting normally.\n", __func__);
        }
 
        /* Restore state if a resync event occurred during processing */
@@ -2695,8 +2697,10 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
        new_fcport = NULL;
        entries = MAX_FIBRE_DEVICES;
 
-       DEBUG3(printk("scsi(%ld): Getting FCAL position map\n", vha->host_no));
-       DEBUG3(qla2x00_get_fcal_position_map(vha, NULL));
+       ql_dbg(ql_dbg_disc, vha, 0x2016,
+           "Getting FCAL position map.\n");
+       if (ql2xextended_error_logging & ql_dbg_disc)
+               qla2x00_get_fcal_position_map(vha, NULL);
 
        /* Get list of logged in devices. */
        memset(ha->gid_list, 0, GID_LIST_SIZE);
@@ -2705,14 +2709,17 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
        if (rval != QLA_SUCCESS)
                goto cleanup_allocation;
 
-       DEBUG3(printk("scsi(%ld): Entries in ID list (%d)\n",
-           vha->host_no, entries));
-       DEBUG3(qla2x00_dump_buffer((uint8_t *)ha->gid_list,
-           entries * sizeof(struct gid_list_info)));
+       ql_dbg(ql_dbg_disc, vha, 0x2017,
+           "Entries in ID list (%d).\n", entries);
+       ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2075,
+           (uint8_t *)ha->gid_list,
+           entries * sizeof(struct gid_list_info));
 
        /* Allocate temporary fcport for any new fcports discovered. */
        new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
        if (new_fcport == NULL) {
+               ql_log(ql_log_warn, vha, 0x2018,
+                   "Memory allocation failed for fcport.\n");
                rval = QLA_MEMORY_ALLOC_FAILED;
                goto cleanup_allocation;
        }
@@ -2726,9 +2733,9 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
                    fcport->port_type != FCT_BROADCAST &&
                    (fcport->flags & FCF_FABRIC_DEVICE) == 0) {
 
-                       DEBUG(printk("scsi(%ld): Marking port lost, "
-                           "loop_id=0x%04x\n",
-                           vha->host_no, fcport->loop_id));
+                       ql_dbg(ql_dbg_disc, vha, 0x2019,
+                           "Marking port lost loop_id=0x%04x.\n",
+                           fcport->loop_id);
 
                        qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
                }
@@ -2769,12 +2776,12 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
                new_fcport->vp_idx = vha->vp_idx;
                rval2 = qla2x00_get_port_database(vha, new_fcport, 0);
                if (rval2 != QLA_SUCCESS) {
-                       DEBUG2(printk("scsi(%ld): Failed to retrieve fcport "
-                           "information -- get_port_database=%x, "
-                           "loop_id=0x%04x\n",
-                           vha->host_no, rval2, new_fcport->loop_id));
-                       DEBUG2(printk("scsi(%ld): Scheduling resync...\n",
-                           vha->host_no));
+                       ql_dbg(ql_dbg_disc, vha, 0x201a,
+                           "Failed to retrieve fcport information "
+                           "-- get_port_database=%x, loop_id=0x%04x.\n",
+                           rval2, new_fcport->loop_id);
+                       ql_dbg(ql_dbg_disc, vha, 0x201b,
+                           "Scheduling resync.\n");
                        set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
                        continue;
                }
@@ -2810,6 +2817,8 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
                        fcport = new_fcport;
                        new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
                        if (new_fcport == NULL) {
+                               ql_log(ql_log_warn, vha, 0x201c,
+                                   "Failed to allocate memory for fcport.\n");
                                rval = QLA_MEMORY_ALLOC_FAILED;
                                goto cleanup_allocation;
                        }
@@ -2828,8 +2837,8 @@ cleanup_allocation:
        kfree(new_fcport);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2(printk("scsi(%ld): Configure local loop error exit: "
-                   "rval=%x\n", vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x201d,
+                   "Configure local loop error exit: rval=%x.\n", rval);
        }
 
        return (rval);
@@ -2858,27 +2867,27 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
        rval = qla2x00_set_idma_speed(vha, fcport->loop_id, fcport->fp_speed,
            mb);
        if (rval != QLA_SUCCESS) {
-               DEBUG2(printk("scsi(%ld): Unable to adjust iIDMA "
-                   "%02x%02x%02x%02x%02x%02x%02x%02x -- %04x %x %04x %04x.\n",
-                   vha->host_no, fcport->port_name[0], fcport->port_name[1],
+               ql_dbg(ql_dbg_disc, vha, 0x2004,
+                   "Unable to adjust iIDMA "
+                   "%02x%02x%02x%02x%02x%02x%02x%02x -- %04x %x %04x "
+                   "%04x.\n", fcport->port_name[0], fcport->port_name[1],
                    fcport->port_name[2], fcport->port_name[3],
                    fcport->port_name[4], fcport->port_name[5],
                    fcport->port_name[6], fcport->port_name[7], rval,
-                   fcport->fp_speed, mb[0], mb[1]));
+                   fcport->fp_speed, mb[0], mb[1]);
        } else {
                link_speed = link_speeds[LS_UNKNOWN];
                if (fcport->fp_speed < 5)
                        link_speed = link_speeds[fcport->fp_speed];
                else if (fcport->fp_speed == 0x13)
                        link_speed = link_speeds[5];
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                   "iIDMA adjusted to %s GB/s on "
-                   "%02x%02x%02x%02x%02x%02x%02x%02x.\n",
-                   link_speed, fcport->port_name[0],
-                   fcport->port_name[1], fcport->port_name[2],
-                   fcport->port_name[3], fcport->port_name[4],
-                   fcport->port_name[5], fcport->port_name[6],
-                   fcport->port_name[7]));
+               ql_dbg(ql_dbg_disc, vha, 0x2005,
+                   "iIDMA adjusted to %s GB/s "
+                   "on %02x%02x%02x%02x%02x%02x%02x%02x.\n", link_speed,
+                   fcport->port_name[0], fcport->port_name[1],
+                   fcport->port_name[2], fcport->port_name[3],
+                   fcport->port_name[4], fcport->port_name[5],
+                   fcport->port_name[6], fcport->port_name[7]);
        }
 }
 
@@ -2887,7 +2896,6 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
 {
        struct fc_rport_identifiers rport_ids;
        struct fc_rport *rport;
-       struct qla_hw_data *ha = vha->hw;
        unsigned long flags;
 
        qla2x00_rport_del(fcport);
@@ -2899,8 +2907,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
        rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
        fcport->rport = rport = fc_remote_port_add(vha->host, 0, &rport_ids);
        if (!rport) {
-               qla_printk(KERN_WARNING, ha,
-                   "Unable to allocate fc remote port!\n");
+               ql_log(ql_log_warn, vha, 0x2006,
+                   "Unable to allocate fc remote port.\n");
                return;
        }
        spin_lock_irqsave(fcport->vha->host->host_lock, flags);
@@ -2975,8 +2983,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
                loop_id = SNS_FL_PORT;
        rval = qla2x00_get_port_name(vha, loop_id, vha->fabric_node_name, 1);
        if (rval != QLA_SUCCESS) {
-               DEBUG2(printk("scsi(%ld): MBC_GET_PORT_NAME Failed, No FL "
-                   "Port\n", vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x201f,
+                   "MBX_GET_PORT_NAME failed, No FL Port.\n");
 
                vha->device_flags &= ~SWITCH_FOUND;
                return (QLA_SUCCESS);
@@ -3003,32 +3011,32 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
                ha->isp_ops->fabric_login(vha, loop_id, 0xff, 0xff,
                    0xfc, mb, BIT_1 | BIT_0);
                if (mb[0] != MBS_COMMAND_COMPLETE) {
-                       DEBUG2(qla_printk(KERN_INFO, ha,
-                           "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x "
-                           "mb[2]=%x mb[6]=%x mb[7]=%x\n", loop_id,
-                           mb[0], mb[1], mb[2], mb[6], mb[7]));
+                       ql_dbg(ql_dbg_disc, vha, 0x2042,
+                           "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x "
+                           "mb[6]=%x mb[7]=%x.\n", loop_id, mb[0], mb[1],
+                           mb[2], mb[6], mb[7]);
                        return (QLA_SUCCESS);
                }
 
                if (test_and_clear_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags)) {
                        if (qla2x00_rft_id(vha)) {
                                /* EMPTY */
-                               DEBUG2(printk("scsi(%ld): Register FC-4 "
-                                   "TYPE failed.\n", vha->host_no));
+                               ql_dbg(ql_dbg_disc, vha, 0x2045,
+                                   "Register FC-4 TYPE failed.\n");
                        }
                        if (qla2x00_rff_id(vha)) {
                                /* EMPTY */
-                               DEBUG2(printk("scsi(%ld): Register FC-4 "
-                                   "Features failed.\n", vha->host_no));
+                               ql_dbg(ql_dbg_disc, vha, 0x2049,
+                                   "Register FC-4 Features failed.\n");
                        }
                        if (qla2x00_rnn_id(vha)) {
                                /* EMPTY */
-                               DEBUG2(printk("scsi(%ld): Register Node Name "
-                                   "failed.\n", vha->host_no));
+                               ql_dbg(ql_dbg_disc, vha, 0x204f,
+                                   "Register Node Name failed.\n");
                        } else if (qla2x00_rsnn_nn(vha)) {
                                /* EMPTY */
-                               DEBUG2(printk("scsi(%ld): Register Symbolic "
-                                   "Node Name failed.\n", vha->host_no));
+                               ql_dbg(ql_dbg_disc, vha, 0x2053,
+                                   "Register Symobilic Node Name failed.\n");
                        }
                }
 
@@ -3132,8 +3140,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
        }
 
        if (rval) {
-               DEBUG2(printk("scsi(%ld): Configure fabric error exit: "
-                   "rval=%d\n", vha->host_no, rval));
+               ql_dbg(ql_dbg_disc, vha, 0x2068,
+                   "Configure fabric error exit rval=%d.\n", rval);
        }
 
        return (rval);
@@ -3175,8 +3183,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
        swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_KERNEL);
        if (!swl) {
                /*EMPTY*/
-               DEBUG2(printk("scsi(%ld): GID_PT allocations failed, fallback "
-                   "on GA_NXT\n", vha->host_no));
+               ql_dbg(ql_dbg_disc, vha, 0x2054,
+                   "GID_PT allocations failed, fallback on GA_NXT.\n");
        } else {
                if (qla2x00_gid_pt(vha, swl) != QLA_SUCCESS) {
                        kfree(swl);
@@ -3201,6 +3209,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
        /* Allocate temporary fcport for any new fcports discovered. */
        new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
        if (new_fcport == NULL) {
+               ql_log(ql_log_warn, vha, 0x205e,
+                   "Failed to allocate memory for fcport.\n");
                kfree(swl);
                return (QLA_MEMORY_ALLOC_FAILED);
        }
@@ -3247,9 +3257,9 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
                        /* Send GA_NXT to the switch */
                        rval = qla2x00_ga_nxt(vha, new_fcport);
                        if (rval != QLA_SUCCESS) {
-                               qla_printk(KERN_WARNING, ha,
-                                   "SNS scan failed -- assuming zero-entry "
-                                   "result...\n");
+                               ql_log(ql_log_warn, vha, 0x2064,
+                                   "SNS scan failed -- assuming "
+                                   "zero-entry result.\n");
                                list_for_each_entry_safe(fcport, fcptemp,
                                    new_fcports, list) {
                                        list_del(&fcport->list);
@@ -3265,9 +3275,11 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
                        wrap.b24 = new_fcport->d_id.b24;
                        first_dev = 0;
                } else if (new_fcport->d_id.b24 == wrap.b24) {
-                       DEBUG2(printk("scsi(%ld): device wrap (%02x%02x%02x)\n",
-                           vha->host_no, new_fcport->d_id.b.domain,
-                           new_fcport->d_id.b.area, new_fcport->d_id.b.al_pa));
+                       ql_dbg(ql_dbg_disc, vha, 0x2065,
+                           "Device wrap (%02x%02x%02x).\n",
+                           new_fcport->d_id.b.domain,
+                           new_fcport->d_id.b.area,
+                           new_fcport->d_id.b.al_pa);
                        break;
                }
 
@@ -3372,6 +3384,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
                nxt_d_id.b24 = new_fcport->d_id.b24;
                new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
                if (new_fcport == NULL) {
+                       ql_log(ql_log_warn, vha, 0x2066,
+                           "Memory allocation failed for fcport.\n");
                        kfree(swl);
                        return (QLA_MEMORY_ALLOC_FAILED);
                }
@@ -3501,10 +3515,10 @@ qla2x00_device_resync(scsi_qla_host_t *vha)
                d_id.b.area = MSB(LSW(rscn_entry));
                d_id.b.al_pa = LSB(LSW(rscn_entry));
 
-               DEBUG(printk("scsi(%ld): RSCN queue entry[%d] = "
-                   "[%02x/%02x%02x%02x].\n",
-                   vha->host_no, vha->rscn_out_ptr, format, d_id.b.domain,
-                   d_id.b.area, d_id.b.al_pa));
+               ql_dbg(ql_dbg_disc, vha, 0x2020,
+                   "RSCN queue entry[%d] = [%02x/%02x%02x%02x].\n",
+                   vha->rscn_out_ptr, format, d_id.b.domain, d_id.b.area,
+                   d_id.b.al_pa);
 
                vha->rscn_out_ptr++;
                if (vha->rscn_out_ptr == MAX_RSCN_COUNT)
@@ -3520,17 +3534,17 @@ qla2x00_device_resync(scsi_qla_host_t *vha)
                        if (rscn_entry != vha->rscn_queue[rscn_out_iter])
                                break;
 
-                       DEBUG(printk("scsi(%ld): Skipping duplicate RSCN queue "
-                           "entry found at [%d].\n", vha->host_no,
-                           rscn_out_iter));
+                       ql_dbg(ql_dbg_disc, vha, 0x2021,
+                           "Skipping duplicate RSCN queue entry found at "
+                           "[%d].\n", rscn_out_iter);
 
                        vha->rscn_out_ptr = rscn_out_iter;
                }
 
                /* Queue overflow, set switch default case. */
                if (vha->flags.rscn_queue_overflow) {
-                       DEBUG(printk("scsi(%ld): device_resync: rscn "
-                           "overflow.\n", vha->host_no));
+                       ql_dbg(ql_dbg_disc, vha, 0x2022,
+                           "device_resync: rscn overflow.\n");
 
                        format = 3;
                        vha->flags.rscn_queue_overflow = 0;
@@ -3659,10 +3673,11 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
        tmp_loopid = 0;
 
        for (;;) {
-               DEBUG(printk("scsi(%ld): Trying Fabric Login w/loop id 0x%04x "
-                   "for port %02x%02x%02x.\n",
-                   vha->host_no, fcport->loop_id, fcport->d_id.b.domain,
-                   fcport->d_id.b.area, fcport->d_id.b.al_pa));
+               ql_dbg(ql_dbg_disc, vha, 0x2000,
+                   "Trying Fabric Login w/loop id 0x%04x for port "
+                   "%02x%02x%02x.\n",
+                   fcport->loop_id, fcport->d_id.b.domain,
+                   fcport->d_id.b.area, fcport->d_id.b.al_pa);
 
                /* Login fcport on switch. */
                ha->isp_ops->fabric_login(vha, fcport->loop_id,
@@ -3680,10 +3695,11 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
                        tmp_loopid = fcport->loop_id;
                        fcport->loop_id = mb[1];
 
-                       DEBUG(printk("Fabric Login: port in use - next "
-                           "loop id=0x%04x, port Id=%02x%02x%02x.\n",
+                       ql_dbg(ql_dbg_disc, vha, 0x2001,
+                           "Fabric Login: port in use - next loop "
+                           "id=0x%04x, port id= %02x%02x%02x.\n",
                            fcport->loop_id, fcport->d_id.b.domain,
-                           fcport->d_id.b.area, fcport->d_id.b.al_pa));
+                           fcport->d_id.b.area, fcport->d_id.b.al_pa);
 
                } else if (mb[0] == MBS_COMMAND_COMPLETE) {
                        /*
@@ -3744,11 +3760,11 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
                        /*
                         * unrecoverable / not handled error
                         */
-                       DEBUG2(printk("%s(%ld): failed=%x port_id=%02x%02x%02x "
-                           "loop_id=%x jiffies=%lx.\n",
-                           __func__, vha->host_no, mb[0],
-                           fcport->d_id.b.domain, fcport->d_id.b.area,
-                           fcport->d_id.b.al_pa, fcport->loop_id, jiffies));
+                       ql_dbg(ql_dbg_disc, vha, 0x2002,
+                           "Failed=%x port_id=%02x%02x%02x loop_id=%x "
+                           "jiffies=%lx.\n", mb[0], fcport->d_id.b.domain,
+                           fcport->d_id.b.area, fcport->d_id.b.al_pa,
+                           fcport->loop_id, jiffies);
 
                        *next_loopid = fcport->loop_id;
                        ha->isp_ops->fabric_logout(vha, fcport->loop_id,
@@ -3852,7 +3868,8 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
                return (QLA_FUNCTION_FAILED);
 
        if (rval)
-               DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__));
+               ql_dbg(ql_dbg_disc, vha, 0x206c,
+                   "%s *** FAILED ***.\n", __func__);
 
        return (rval);
 }
@@ -3929,8 +3946,8 @@ qla82xx_quiescent_state_cleanup(scsi_qla_host_t *vha)
        struct qla_hw_data *ha = vha->hw;
        struct scsi_qla_host *vp;
 
-       qla_printk(KERN_INFO, ha,
-                       "Performing ISP error recovery - ha= %p.\n", ha);
+       ql_dbg(ql_dbg_p3p, vha, 0xb002,
+           "Performing ISP error recovery - ha=%p.\n", ha);
 
        atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
        if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
@@ -3964,8 +3981,8 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
        clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
        ha->qla_stats.total_isp_aborts++;
 
-       qla_printk(KERN_INFO, ha,
-           "Performing ISP error recovery - ha= %p.\n", ha);
+       ql_log(ql_log_info, vha, 0x00af,
+           "Performing ISP error recovery - ha=%p.\n", ha);
 
        /* For ISP82XX, reset_chip is just disabling interrupts.
         * Driver waits for the completion of the commands.
@@ -4016,6 +4033,8 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
                /* Make sure for ISP 82XX IO DMA is complete */
                if (IS_QLA82XX(ha)) {
                        qla82xx_chip_reset_cleanup(vha);
+                       ql_log(ql_log_info, vha, 0x00b4,
+                           "Done chip reset cleanup.\n");
 
                        /* Done waiting for pending commands.
                         * Reset the online flag.
@@ -4097,7 +4116,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
                                    ha->fce_dma, ha->fce_bufs, ha->fce_mb,
                                    &ha->fce_bufs);
                                if (rval) {
-                                       qla_printk(KERN_WARNING, ha,
+                                       ql_log(ql_log_warn, vha, 0x8033,
                                            "Unable to reinitialize FCE "
                                            "(%d).\n", rval);
                                        ha->flags.fce_enabled = 0;
@@ -4109,7 +4128,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
                                rval = qla2x00_enable_eft_trace(vha,
                                    ha->eft_dma, EFT_NUM_BUFFERS);
                                if (rval) {
-                                       qla_printk(KERN_WARNING, ha,
+                                       ql_log(ql_log_warn, vha, 0x8034,
                                            "Unable to reinitialize EFT "
                                            "(%d).\n", rval);
                                }
@@ -4118,9 +4137,9 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
                        vha->flags.online = 1;
                        if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
                                if (ha->isp_abort_cnt == 0) {
-                                       qla_printk(KERN_WARNING, ha,
-                                           "ISP error recovery failed - "
-                                           "board disabled\n");
+                                       ql_log(ql_log_fatal, vha, 0x8035,
+                                           "ISP error recover failed - "
+                                           "board disabled.\n");
                                        /*
                                         * The next call disables the board
                                         * completely.
@@ -4132,16 +4151,16 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
                                        status = 0;
                                } else { /* schedule another ISP abort */
                                        ha->isp_abort_cnt--;
-                                       DEBUG(printk("qla%ld: ISP abort - "
-                                           "retry remaining %d\n",
-                                           vha->host_no, ha->isp_abort_cnt));
+                                       ql_dbg(ql_dbg_taskm, vha, 0x8020,
+                                           "ISP abort - retry remaining %d.\n",
+                                           ha->isp_abort_cnt);
                                        status = 1;
                                }
                        } else {
                                ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT;
-                               DEBUG(printk("qla2x00(%ld): ISP error recovery "
-                                   "- retrying (%d) more times\n",
-                                   vha->host_no, ha->isp_abort_cnt));
+                               ql_dbg(ql_dbg_taskm, vha, 0x8021,
+                                   "ISP error recovery - retrying (%d) "
+                                   "more times.\n", ha->isp_abort_cnt);
                                set_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
                                status = 1;
                        }
@@ -4150,9 +4169,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
        }
 
        if (!status) {
-               DEBUG(printk(KERN_INFO
-                               "qla2x00_abort_isp(%ld): succeeded.\n",
-                               vha->host_no));
+               ql_dbg(ql_dbg_taskm, vha, 0x8022, "%s succeeded.\n", __func__);
 
                spin_lock_irqsave(&ha->vport_slock, flags);
                list_for_each_entry(vp, &ha->vp_list, list) {
@@ -4169,8 +4186,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
                spin_unlock_irqrestore(&ha->vport_slock, flags);
 
        } else {
-               qla_printk(KERN_INFO, ha,
-                       "qla2x00_abort_isp: **** FAILED ****\n");
+               ql_log(ql_log_warn, vha, 0x8023, "%s **** FAILED ****.\n");
        }
 
        return(status);
@@ -4211,8 +4227,8 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
 
                status = qla2x00_fw_ready(vha);
                if (!status) {
-                       DEBUG(printk("%s(): Start configure loop, "
-                           "status = %d\n", __func__, status));
+                       ql_dbg(ql_dbg_taskm, vha, 0x8031,
+                           "Start configure loop status = %d.\n", status);
 
                        /* Issue a marker after FW becomes ready. */
                        qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
@@ -4234,9 +4250,8 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
                if ((vha->device_flags & DFLG_NO_CABLE))
                        status = 0;
 
-               DEBUG(printk("%s(): Configure loop done, status = 0x%x\n",
-                               __func__,
-                               status));
+               ql_dbg(ql_dbg_taskm, vha, 0x8032,
+                   "Configure loop done, status = 0x%x.\n", status);
        }
        return (status);
 }
@@ -4256,13 +4271,13 @@ qla25xx_init_queues(struct qla_hw_data *ha)
                        rsp->options &= ~BIT_0;
                        ret = qla25xx_init_rsp_que(base_vha, rsp);
                        if (ret != QLA_SUCCESS)
-                               DEBUG2_17(printk(KERN_WARNING
-                                       "%s Rsp que:%d init failed\n", __func__,
-                                               rsp->id));
+                               ql_dbg(ql_dbg_init, base_vha, 0x00ff,
+                                   "%s Rsp que: %d init failed.\n",
+                                   __func__, rsp->id);
                        else
-                               DEBUG2_17(printk(KERN_INFO
-                                       "%s Rsp que:%d inited\n", __func__,
-                                               rsp->id));
+                               ql_dbg(ql_dbg_init, base_vha, 0x0100,
+                                   "%s Rsp que: %d inited.\n",
+                                   __func__, rsp->id);
                }
        }
        for (i = 1; i < ha->max_req_queues; i++) {
@@ -4272,13 +4287,13 @@ qla25xx_init_queues(struct qla_hw_data *ha)
                        req->options &= ~BIT_0;
                        ret = qla25xx_init_req_que(base_vha, req);
                        if (ret != QLA_SUCCESS)
-                               DEBUG2_17(printk(KERN_WARNING
-                                       "%s Req que:%d init failed\n", __func__,
-                                               req->id));
+                               ql_dbg(ql_dbg_init, base_vha, 0x0101,
+                                   "%s Req que: %d init failed.\n",
+                                   __func__, req->id);
                        else
-                               DEBUG2_17(printk(KERN_WARNING
-                                       "%s Req que:%d inited\n", __func__,
-                                               req->id));
+                               ql_dbg(ql_dbg_init, base_vha, 0x0102,
+                                   "%s Req que: %d inited.\n",
+                                   __func__, req->id);
                }
        }
        return ret;
@@ -4397,19 +4412,22 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
        for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)
                chksum += le32_to_cpu(*dptr++);
 
-       DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", vha->host_no));
-       DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));
+       ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x006a,
+           "Contents of NVRAM\n");
+       ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010d,
+           (uint8_t *)nv, ha->nvram_size);
 
        /* Bad NVRAM data, set defaults parameters. */
        if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
            || nv->id[3] != ' ' ||
            nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) {
                /* Reset NVRAM data. */
-               qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
-                   "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
-                   le16_to_cpu(nv->nvram_version));
-               qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
-                   "invalid -- WWPN) defaults.\n");
+               ql_log(ql_log_warn, vha, 0x006b,
+                   "Inconisistent NVRAM detected: checksum=0x%x id=%c "
+                   "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version);
+               ql_log(ql_log_warn, vha, 0x006c,
+                   "Falling back to functioning (yet invalid -- WWPN) "
+                   "defaults.\n");
 
                /*
                 * Set default initialization control block.
@@ -4587,10 +4605,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
        if (ha->zio_mode != QLA_ZIO_DISABLED) {
                ha->zio_mode = QLA_ZIO_MODE_6;
 
-               DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay "
-                   "(%d us).\n", vha->host_no, ha->zio_mode,
-                   ha->zio_timer * 100));
-               qla_printk(KERN_INFO, ha,
+               ql_log(ql_log_info, vha, 0x006f,
                    "ZIO mode %d enabled; timer delay (%d us).\n",
                    ha->zio_mode, ha->zio_timer * 100);
 
@@ -4601,8 +4616,8 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
        }
 
        if (rval) {
-               DEBUG2_3(printk(KERN_WARNING
-                   "scsi(%ld): NVRAM configuration failed!\n", vha->host_no));
+               ql_log(ql_log_warn, vha, 0x0070,
+                   "NVRAM configuration failed.\n");
        }
        return (rval);
 }
@@ -4620,8 +4635,8 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
        struct qla_hw_data *ha = vha->hw;
        struct req_que *req = ha->req_q_map[0];
 
-       qla_printk(KERN_INFO, ha,
-           "FW: Loading from flash (%x)...\n", faddr);
+       ql_dbg(ql_dbg_init, vha, 0x008b,
+           "Loading firmware from flash (%x).\n", faddr);
 
        rval = QLA_SUCCESS;
 
@@ -4637,11 +4652,12 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
            dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
            (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
                dcode[3] == 0)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Unable to verify integrity of flash firmware image!\n");
-               qla_printk(KERN_WARNING, ha,
-                   "Firmware data: %08x %08x %08x %08x!\n", dcode[0],
-                   dcode[1], dcode[2], dcode[3]);
+               ql_log(ql_log_fatal, vha, 0x008c,
+                   "Unable to verify the integrity of flash firmware "
+                   "image.\n");
+               ql_log(ql_log_fatal, vha, 0x008d,
+                   "Firmware data: %08x %08x %08x %08x.\n",
+                   dcode[0], dcode[1], dcode[2], dcode[3]);
 
                return QLA_FUNCTION_FAILED;
        }
@@ -4660,9 +4676,10 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
                        if (dlen > risc_size)
                                dlen = risc_size;
 
-                       DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
-                           "addr %x, number of dwords 0x%x, offset 0x%x.\n",
-                           vha->host_no, risc_addr, dlen, faddr));
+                       ql_dbg(ql_dbg_init, vha, 0x008e,
+                           "Loading risc segment@ risc addr %x "
+                           "number of dwords 0x%x offset 0x%x.\n",
+                           risc_addr, dlen, faddr);
 
                        qla24xx_read_flash_data(vha, dcode, faddr, dlen);
                        for (i = 0; i < dlen; i++)
@@ -4671,12 +4688,9 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
                        rval = qla2x00_load_ram(vha, req->dma, risc_addr,
                            dlen);
                        if (rval) {
-                               DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
-                                   "segment %d of firmware\n", vha->host_no,
-                                   fragment));
-                               qla_printk(KERN_WARNING, ha,
-                                   "[ERROR] Failed to load segment %d of "
-                                   "firmware\n", fragment);
+                               ql_log(ql_log_fatal, vha, 0x008f,
+                                   "Failed to load segment %d of firmware.\n",
+                                   fragment);
                                break;
                        }
 
@@ -4709,9 +4723,10 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
        /* Load firmware blob. */
        blob = qla2x00_request_firmware(vha);
        if (!blob) {
-               qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
-               qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
-                   "from: " QLA_FW_URL ".\n");
+               ql_log(ql_log_info, vha, 0x0083,
+                   "Fimware image unavailable.\n");
+               ql_log(ql_log_info, vha, 0x0084,
+                   "Firmware images can be retrieved from: "QLA_FW_URL ".\n");
                return QLA_FUNCTION_FAILED;
        }
 
@@ -4724,8 +4739,8 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
 
        /* Validate firmware image by checking version. */
        if (blob->fw->size < 8 * sizeof(uint16_t)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Unable to verify integrity of firmware image (%Zd)!\n",
+               ql_log(ql_log_fatal, vha, 0x0085,
+                   "Unable to verify integrity of firmware image (%Zd).\n",
                    blob->fw->size);
                goto fail_fw_integrity;
        }
@@ -4734,11 +4749,11 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
        if ((wcode[0] == 0xffff && wcode[1] == 0xffff && wcode[2] == 0xffff &&
            wcode[3] == 0xffff) || (wcode[0] == 0 && wcode[1] == 0 &&
                wcode[2] == 0 && wcode[3] == 0)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Unable to verify integrity of firmware image!\n");
-               qla_printk(KERN_WARNING, ha,
-                   "Firmware data: %04x %04x %04x %04x!\n", wcode[0],
-                   wcode[1], wcode[2], wcode[3]);
+               ql_log(ql_log_fatal, vha, 0x0086,
+                   "Unable to verify integrity of firmware image.\n");
+               ql_log(ql_log_fatal, vha, 0x0087,
+                   "Firmware data: %04x %04x %04x %04x.\n",
+                   wcode[0], wcode[1], wcode[2], wcode[3]);
                goto fail_fw_integrity;
        }
 
@@ -4751,9 +4766,9 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
                /* Validate firmware image size. */
                fwclen += risc_size * sizeof(uint16_t);
                if (blob->fw->size < fwclen) {
-                       qla_printk(KERN_WARNING, ha,
+                       ql_log(ql_log_fatal, vha, 0x0088,
                            "Unable to verify integrity of firmware image "
-                           "(%Zd)!\n", blob->fw->size);
+                           "(%Zd).\n", blob->fw->size);
                        goto fail_fw_integrity;
                }
 
@@ -4762,10 +4777,9 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
                        wlen = (uint16_t)(ha->fw_transfer_size >> 1);
                        if (wlen > risc_size)
                                wlen = risc_size;
-
-                       DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
-                           "addr %x, number of words 0x%x.\n", vha->host_no,
-                           risc_addr, wlen));
+                       ql_dbg(ql_dbg_init, vha, 0x0089,
+                           "Loading risc segment@ risc addr %x number of "
+                           "words 0x%x.\n", risc_addr, wlen);
 
                        for (i = 0; i < wlen; i++)
                                wcode[i] = swab16(fwcode[i]);
@@ -4773,12 +4787,9 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
                        rval = qla2x00_load_ram(vha, req->dma, risc_addr,
                            wlen);
                        if (rval) {
-                               DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
-                                   "segment %d of firmware\n", vha->host_no,
-                                   fragment));
-                               qla_printk(KERN_WARNING, ha,
-                                   "[ERROR] Failed to load segment %d of "
-                                   "firmware\n", fragment);
+                               ql_log(ql_log_fatal, vha, 0x008a,
+                                   "Failed to load segment %d of firmware.\n",
+                                   fragment);
                                break;
                        }
 
@@ -4814,15 +4825,17 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
        /* Load firmware blob. */
        blob = qla2x00_request_firmware(vha);
        if (!blob) {
-               qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
-               qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
-                   "from: " QLA_FW_URL ".\n");
+               ql_log(ql_log_warn, vha, 0x0090,
+                   "Fimware image unavailable.\n");
+               ql_log(ql_log_warn, vha, 0x0091,
+                   "Firmware images can be retrieved from: "
+                   QLA_FW_URL ".\n");
 
                return QLA_FUNCTION_FAILED;
        }
 
-       qla_printk(KERN_INFO, ha,
-           "FW: Loading via request-firmware...\n");
+       ql_log(ql_log_info, vha, 0x0092,
+           "Loading via request-firmware.\n");
 
        rval = QLA_SUCCESS;
 
@@ -4834,8 +4847,8 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
 
        /* Validate firmware image by checking version. */
        if (blob->fw->size < 8 * sizeof(uint32_t)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Unable to verify integrity of firmware image (%Zd)!\n",
+               ql_log(ql_log_fatal, vha, 0x0093,
+                   "Unable to verify integrity of firmware image (%Zd).\n",
                    blob->fw->size);
                goto fail_fw_integrity;
        }
@@ -4845,11 +4858,12 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
            dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
            (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
                dcode[3] == 0)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Unable to verify integrity of firmware image!\n");
-               qla_printk(KERN_WARNING, ha,
-                   "Firmware data: %08x %08x %08x %08x!\n", dcode[0],
-                   dcode[1], dcode[2], dcode[3]);
+               ql_log(ql_log_fatal, vha, 0x0094,
+                   "Unable to verify integrity of firmware image (%Zd).\n",
+                   blob->fw->size);
+               ql_log(ql_log_fatal, vha, 0x0095,
+                   "Firmware data: %08x %08x %08x %08x.\n",
+                   dcode[0], dcode[1], dcode[2], dcode[3]);
                goto fail_fw_integrity;
        }
 
@@ -4861,9 +4875,9 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
                /* Validate firmware image size. */
                fwclen += risc_size * sizeof(uint32_t);
                if (blob->fw->size < fwclen) {
-                       qla_printk(KERN_WARNING, ha,
+                       ql_log(ql_log_fatal, vha, 0x0096,
                            "Unable to verify integrity of firmware image "
-                           "(%Zd)!\n", blob->fw->size);
+                           "(%Zd).\n", blob->fw->size);
 
                        goto fail_fw_integrity;
                }
@@ -4874,9 +4888,9 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
                        if (dlen > risc_size)
                                dlen = risc_size;
 
-                       DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
-                           "addr %x, number of dwords 0x%x.\n", vha->host_no,
-                           risc_addr, dlen));
+                       ql_dbg(ql_dbg_init, vha, 0x0097,
+                           "Loading risc segment@ risc addr %x "
+                           "number of dwords 0x%x.\n", risc_addr, dlen);
 
                        for (i = 0; i < dlen; i++)
                                dcode[i] = swab32(fwcode[i]);
@@ -4884,12 +4898,9 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
                        rval = qla2x00_load_ram(vha, req->dma, risc_addr,
                            dlen);
                        if (rval) {
-                               DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
-                                   "segment %d of firmware\n", vha->host_no,
-                                   fragment));
-                               qla_printk(KERN_WARNING, ha,
-                                   "[ERROR] Failed to load segment %d of "
-                                   "firmware\n", fragment);
+                               ql_log(ql_log_fatal, vha, 0x0098,
+                                   "Failed to load segment %d of firmware.\n",
+                                   fragment);
                                break;
                        }
 
@@ -4953,14 +4964,13 @@ try_blob_fw:
        if (rval == QLA_SUCCESS || !ha->flt_region_gold_fw)
                return rval;
 
-       qla_printk(KERN_ERR, ha,
-           "FW: Attempting to fallback to golden firmware...\n");
+       ql_log(ql_log_info, vha, 0x0099,
+           "Attempting to fallback to golden firmware.\n");
        rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_gold_fw);
        if (rval != QLA_SUCCESS)
                return rval;
 
-       qla_printk(KERN_ERR, ha,
-           "FW: Please update operational firmware...\n");
+       ql_log(ql_log_info, vha, 0x009a, "Update operational firmware.\n");
        ha->flags.running_gold_fw = 1;
 
        return rval;
@@ -4987,8 +4997,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
                        continue;
                if (qla2x00_setup_chip(vha) != QLA_SUCCESS)
                        continue;
-               qla_printk(KERN_INFO, ha,
-                   "Attempting retry of stop-firmware command...\n");
+               ql_log(ql_log_info, vha, 0x8015,
+                   "Attempting retry of stop-firmware command.\n");
                ret = qla2x00_stop_firmware(vha);
        }
 }
@@ -5023,10 +5033,10 @@ qla24xx_configure_vhba(scsi_qla_host_t *vha)
        /* Login to SNS first */
        ha->isp_ops->fabric_login(vha, NPH_SNS, 0xff, 0xff, 0xfc, mb, BIT_1);
        if (mb[0] != MBS_COMMAND_COMPLETE) {
-               DEBUG15(qla_printk(KERN_INFO, ha,
-                   "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x "
-                   "mb[2]=%x mb[6]=%x mb[7]=%x\n", NPH_SNS,
-                   mb[0], mb[1], mb[2], mb[6], mb[7]));
+               ql_dbg(ql_dbg_init, vha, 0x0103,
+                   "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x "
+                   "mb[6]=%x mb[7]=%x.\n",
+                   NPH_SNS, mb[0], mb[1], mb[2], mb[6], mb[7]);
                return (QLA_FUNCTION_FAILED);
        }
 
@@ -5146,19 +5156,23 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
        for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)
                chksum += le32_to_cpu(*dptr++);
 
-       DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", vha->host_no));
-       DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));
+       ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0111,
+           "Contents of NVRAM:\n");
+       ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0112,
+           (uint8_t *)nv, ha->nvram_size);
 
        /* Bad NVRAM data, set defaults parameters. */
        if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
            || nv->id[3] != ' ' ||
            nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) {
                /* Reset NVRAM data. */
-               qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
-                   "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
+               ql_log(ql_log_info, vha, 0x0073,
+                   "Inconisistent NVRAM detected: checksum=0x%x id=%c "
+                   "version=0x%x.\n", chksum, nv->id[0],
                    le16_to_cpu(nv->nvram_version));
-               qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
-                   "invalid -- WWPN) defaults.\n");
+               ql_log(ql_log_info, vha, 0x0074,
+                   "Falling back to functioning (yet invalid -- WWPN) "
+                   "defaults.\n");
 
                /*
                 * Set default initialization control block.
@@ -5350,12 +5364,10 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
        if (ha->zio_mode != QLA_ZIO_DISABLED) {
                ha->zio_mode = QLA_ZIO_MODE_6;
 
-               DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay "
-                   "(%d us).\n", vha->host_no, ha->zio_mode,
-                   ha->zio_timer * 100));
-               qla_printk(KERN_INFO, ha,
+               ql_log(ql_log_info, vha, 0x0075,
                    "ZIO mode %d enabled; timer delay (%d us).\n",
-                   ha->zio_mode, ha->zio_timer * 100);
+                   ha->zio_mode,
+                   ha->zio_timer * 100);
 
                icb->firmware_options_2 |= cpu_to_le32(
                    (uint32_t)ha->zio_mode);
@@ -5364,8 +5376,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
        }
 
        if (rval) {
-               DEBUG2_3(printk(KERN_WARNING
-                   "scsi(%ld): NVRAM configuration failed!\n", vha->host_no));
+               ql_log(ql_log_warn, vha, 0x0076,
+                   "NVRAM configuration failed.\n");
        }
        return (rval);
 }
@@ -5388,9 +5400,8 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
 
                status = qla2x00_fw_ready(vha);
                if (!status) {
-                       qla_printk(KERN_INFO, ha,
-                       "%s(): Start configure loop, "
-                       "status = %d\n", __func__, status);
+                       ql_log(ql_log_info, vha, 0x803c,
+                           "Start configure loop, status =%d.\n", status);
 
                        /* Issue a marker after FW becomes ready. */
                        qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
@@ -5412,9 +5423,8 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
                if ((vha->device_flags & DFLG_NO_CABLE))
                        status = 0;
 
-               qla_printk(KERN_INFO, ha,
-                       "%s(): Configure loop done, status = 0x%x\n",
-                       __func__, status);
+               ql_log(ql_log_info, vha, 0x803d,
+                   "Configure loop done, status = 0x%x.\n", status);
        }
 
        if (!status) {
@@ -5450,9 +5460,9 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
                            ha->fce_dma, ha->fce_bufs, ha->fce_mb,
                            &ha->fce_bufs);
                        if (rval) {
-                               qla_printk(KERN_WARNING, ha,
-                                   "Unable to reinitialize FCE "
-                                   "(%d).\n", rval);
+                               ql_log(ql_log_warn, vha, 0x803e,
+                                   "Unable to reinitialize FCE (%d).\n",
+                                   rval);
                                ha->flags.fce_enabled = 0;
                        }
                }
@@ -5462,17 +5472,16 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
                        rval = qla2x00_enable_eft_trace(vha,
                            ha->eft_dma, EFT_NUM_BUFFERS);
                        if (rval) {
-                               qla_printk(KERN_WARNING, ha,
-                                   "Unable to reinitialize EFT "
-                                   "(%d).\n", rval);
+                               ql_log(ql_log_warn, vha, 0x803f,
+                                   "Unable to reinitialize EFT (%d).\n",
+                                   rval);
                        }
                }
        }
 
        if (!status) {
-               DEBUG(printk(KERN_INFO
-                       "qla82xx_restart_isp(%ld): succeeded.\n",
-                       vha->host_no));
+               ql_dbg(ql_dbg_taskm, vha, 0x8040,
+                   "qla82xx_restart_isp succeeded.\n");
 
                spin_lock_irqsave(&ha->vport_slock, flags);
                list_for_each_entry(vp, &ha->vp_list, list) {
@@ -5489,8 +5498,8 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
                spin_unlock_irqrestore(&ha->vport_slock, flags);
 
        } else {
-               qla_printk(KERN_INFO, ha,
-                       "qla82xx_restart_isp: **** FAILED ****\n");
+               ql_log(ql_log_warn, vha, 0x8041,
+                   "qla82xx_restart_isp **** FAILED ****.\n");
        }
 
        return status;
@@ -5640,9 +5649,8 @@ qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
        if (ret == QLA_SUCCESS)
                fcport->fcp_prio = priority;
        else
-               DEBUG2(printk(KERN_WARNING
-                       "scsi(%ld): Unable to activate fcp priority, "
-                       " ret=0x%x\n", vha->host_no, ret));
+               ql_dbg(ql_dbg_user, vha, 0x704f,
+                   "Unable to activate fcp priority, ret=0x%x.\n", ret);
 
        return  ret;
 }
index 4c8167e..d2e904b 100644 (file)
@@ -94,11 +94,11 @@ qla2x00_set_fcport_state(fc_port_t *fcport, int state)
 
        /* Don't print state transitions during initial allocation of fcport */
        if (old_state && old_state != state) {
-               DEBUG(qla_printk(KERN_WARNING, fcport->vha->hw,
-                   "scsi(%ld): FCPort state transitioned from %s to %s - "
-                   "portid=%02x%02x%02x.\n", fcport->vha->host_no,
+               ql_dbg(ql_dbg_disc, fcport->vha, 0x207d,
+                   "FCPort state transitioned from %s to %s - "
+                   "portid=%02x%02x%02x.\n",
                    port_state_str[old_state], port_state_str[state],
                    fcport->d_id.b.domain, fcport->d_id.b.area,
-                   fcport->d_id.b.al_pa));
+                   fcport->d_id.b.al_pa);
        }
 }
index 7bac3cd..49d6906 100644 (file)
@@ -150,7 +150,8 @@ qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts)
 
        /* We only support T10 DIF right now */
        if (guard != SHOST_DIX_GUARD_CRC) {
-               DEBUG2(printk(KERN_ERR "Unsupported guard: %d\n", guard));
+               ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3007,
+                   "Unsupported guard: %d for cmd=%p.\n", guard, sp->cmd);
                return 0;
        }
 
@@ -343,9 +344,10 @@ qla2x00_start_scsi(srb_t *sp)
 
        /* Send marker if required */
        if (vha->marker_needed != 0) {
-               if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL)
-                                                       != QLA_SUCCESS)
+               if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+                   QLA_SUCCESS) {
                        return (QLA_FUNCTION_FAILED);
+               }
                vha->marker_needed = 0;
        }
 
@@ -490,8 +492,8 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
        mrk24 = NULL;
        mrk = (mrk_entry_t *)qla2x00_alloc_iocbs(vha, 0);
        if (mrk == NULL) {
-               DEBUG2_3(printk("%s(%ld): failed to allocate Marker IOCB.\n",
-                   __func__, base_vha->host_no));
+               ql_log(ql_log_warn, base_vha, 0x3026,
+                   "Failed to allocate Marker IOCB.\n");
 
                return (QLA_FUNCTION_FAILED);
        }
@@ -547,9 +549,10 @@ qla2x00_isp_cmd(struct scsi_qla_host *vha, struct req_que *req)
        device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id);
        struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp;
 
-       DEBUG5(printk("%s(): IOCB data:\n", __func__));
-       DEBUG5(qla2x00_dump_buffer(
-           (uint8_t *)req->ring_ptr, REQUEST_ENTRY_SIZE));
+       ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x302d,
+           "IOCB data:\n");
+       ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302e,
+           (uint8_t *)req->ring_ptr, REQUEST_ENTRY_SIZE);
 
        /* Adjust ring index. */
        req->ring_index++;
@@ -604,7 +607,7 @@ qla2x00_isp_cmd(struct scsi_qla_host *vha, struct req_que *req)
  * Returns the number of IOCB entries needed to store @dsds.
  */
 inline uint16_t
-qla24xx_calc_iocbs(uint16_t dsds)
+qla24xx_calc_iocbs(scsi_qla_host_t *vha, uint16_t dsds)
 {
        uint16_t iocbs;
 
@@ -614,8 +617,6 @@ qla24xx_calc_iocbs(uint16_t dsds)
                if ((dsds - 1) % 5)
                        iocbs++;
        }
-       DEBUG3(printk(KERN_DEBUG "%s(): Required PKT(s) = %d\n",
-           __func__, iocbs));
        return iocbs;
 }
 
@@ -712,6 +713,7 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt,
     unsigned int protcnt)
 {
        struct sd_dif_tuple *spt;
+       scsi_qla_host_t *vha = shost_priv(cmd->device->host);
        unsigned char op = scsi_get_prot_op(cmd);
 
        switch (scsi_get_prot_type(cmd)) {
@@ -768,9 +770,9 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt,
                    op == SCSI_PROT_WRITE_PASS)) {
                        spt = page_address(sg_page(scsi_prot_sglist(cmd))) +
                            scsi_prot_sglist(cmd)[0].offset;
-                       DEBUG18(printk(KERN_DEBUG
-                           "%s(): LBA from user %p, lba = 0x%x\n",
-                           __func__, spt, (int)spt->ref_tag));
+                       ql_dbg(ql_dbg_io, vha, 0x3008,
+                           "LBA from user %p, lba = 0x%x for cmd=%p.\n",
+                           spt, (int)spt->ref_tag, cmd);
                        pkt->ref_tag = swab32(spt->ref_tag);
                        pkt->app_tag_mask[0] = 0x0;
                        pkt->app_tag_mask[1] = 0x0;
@@ -789,11 +791,11 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt,
                break;
        }
 
-       DEBUG18(printk(KERN_DEBUG
-           "%s(): Setting protection Tags: (BIG) ref tag = 0x%x,"
-           " app tag = 0x%x, prot SG count %d , cmd lba 0x%x,"
-           " prot_type=%u\n", __func__, pkt->ref_tag, pkt->app_tag, protcnt,
-           (int)scsi_get_lba(cmd), scsi_get_prot_type(cmd)));
+       ql_dbg(ql_dbg_io, vha, 0x3009,
+           "Setting protection Tags: (BIG) ref tag = 0x%x, app tag = 0x%x, "
+           "prot SG count %d, cmd lba 0x%x, prot_type=%u cmd=%p.\n",
+           pkt->ref_tag, pkt->app_tag, protcnt, (int)scsi_get_lba(cmd),
+           scsi_get_prot_type(cmd), cmd);
 }
 
 
@@ -809,6 +811,7 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
        uint32_t *cur_dsd = dsd;
        int     i;
        uint16_t        used_dsds = tot_dsds;
+       scsi_qla_host_t *vha = shost_priv(sp->cmd->device->host);
 
        uint8_t         *cp;
 
@@ -853,9 +856,10 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
                        cur_dsd = (uint32_t *)next_dsd;
                }
                sle_dma = sg_dma_address(sg);
-               DEBUG18(printk("%s(): %p, sg entry %d - addr =0x%x 0x%x,"
-                   " len =%d\n", __func__ , cur_dsd, i, LSD(sle_dma),
-                   MSD(sle_dma), sg_dma_len(sg)));
+               ql_dbg(ql_dbg_io, vha, 0x300a,
+                   "sg entry %d - addr=0x%x 0x%x, " "len=%d for cmd=%p.\n",
+                   cur_dsd, i, LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg),
+                   sp->cmd);
                *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
                *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
                *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
@@ -863,8 +867,8 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
 
                if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) {
                        cp = page_address(sg_page(sg)) + sg->offset;
-                       DEBUG18(printk("%s(): User Data buffer= %p:\n",
-                           __func__ , cp));
+                       ql_dbg(ql_dbg_io, vha, 0x300b,
+                           "User data buffer=%p for cmd=%p.\n", cp, sp->cmd);
                }
        }
        /* Null termination */
@@ -888,7 +892,7 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
        struct scsi_cmnd *cmd;
        uint32_t *cur_dsd = dsd;
        uint16_t        used_dsds = tot_dsds;
-
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
        uint8_t         *cp;
 
 
@@ -935,10 +939,11 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
                }
                sle_dma = sg_dma_address(sg);
                if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) {
-                       DEBUG18(printk(KERN_DEBUG
-                           "%s(): %p, sg entry %d - addr =0x%x"
-                           "0x%x, len =%d\n", __func__ , cur_dsd, i,
-                           LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg)));
+                       ql_dbg(ql_dbg_io, vha, 0x3027,
+                           "%s(): %p, sg_entry %d - "
+                           "addr=0x%x0x%x, len=%d.\n",
+                           __func__, cur_dsd, i,
+                           LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg));
                }
                *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
                *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
@@ -946,8 +951,9 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
 
                if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) {
                        cp = page_address(sg_page(sg)) + sg->offset;
-                       DEBUG18(printk("%s(): Protection Data buffer = %p:\n",
-                           __func__ , cp));
+                       ql_dbg(ql_dbg_io, vha, 0x3028,
+                           "%s(): Protection Data buffer = %p.\n", __func__,
+                           cp);
                }
                avail_dsds--;
        }
@@ -996,22 +1002,16 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
        *((uint32_t *)(&cmd_pkt->entry_type)) =
            __constant_cpu_to_le32(COMMAND_TYPE_CRC_2);
 
+       vha = sp->fcport->vha;
+       ha = vha->hw;
+
        /* No data transfer */
        data_bytes = scsi_bufflen(cmd);
        if (!data_bytes || cmd->sc_data_direction == DMA_NONE) {
-               DEBUG18(printk(KERN_INFO "%s: Zero data bytes or DMA-NONE %d\n",
-                   __func__, data_bytes));
                cmd_pkt->byte_count = __constant_cpu_to_le32(0);
                return QLA_SUCCESS;
        }
 
-       vha = sp->fcport->vha;
-       ha = vha->hw;
-
-       DEBUG18(printk(KERN_DEBUG
-           "%s(%ld): Executing cmd sp %p, prot_op=%u.\n", __func__,
-           vha->host_no, sp, scsi_get_prot_op(sp->cmd)));
-
        cmd_pkt->vp_index = sp->fcport->vp_idx;
 
        /* Set transfer direction */
@@ -1056,8 +1056,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
 
        /* Determine SCSI command length -- align to 4 byte boundary */
        if (cmd->cmd_len > 16) {
-               DEBUG18(printk(KERN_INFO "%s(): **** SCSI CMD > 16\n",
-                   __func__));
                additional_fcpcdb_len = cmd->cmd_len - 16;
                if ((cmd->cmd_len % 4) != 0) {
                        /* SCSI cmd > 16 bytes must be multiple of 4 */
@@ -1108,11 +1106,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
 
        cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */
 
-       DEBUG18(printk(KERN_INFO "%s(%ld): Total SG(s) Entries %d, Data"
-           "entries %d, data bytes %d, Protection entries %d\n",
-           __func__, vha->host_no, tot_dsds, (tot_dsds-tot_prot_dsds),
-           data_bytes, tot_prot_dsds));
-
        /* Compute dif len and adjust data len to incude protection */
        total_bytes = data_bytes;
        dif_bytes = 0;
@@ -1150,14 +1143,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
            additional_fcpcdb_len);
        *fcp_dl = htonl(total_bytes);
 
-       DEBUG18(printk(KERN_INFO "%s(%ld): dif bytes = 0x%x (%d), total bytes"
-           " = 0x%x (%d), dat block size =0x%x (%d)\n", __func__,
-           vha->host_no, dif_bytes, dif_bytes, total_bytes, total_bytes,
-           crc_ctx_pkt->blk_size, crc_ctx_pkt->blk_size));
-
        if (!data_bytes || cmd->sc_data_direction == DMA_NONE) {
-               DEBUG18(printk(KERN_INFO "%s: Zero data bytes or DMA-NONE %d\n",
-                   __func__, data_bytes));
                cmd_pkt->byte_count = __constant_cpu_to_le32(0);
                return QLA_SUCCESS;
        }
@@ -1182,8 +1168,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
        return QLA_SUCCESS;
 
 crc_queuing_error:
-       DEBUG18(qla_printk(KERN_INFO, ha,
-           "CMD sent FAILED crc_q error:sp = %p\n", sp));
        /* Cleanup will be performed by the caller */
 
        return QLA_FUNCTION_FAILED;
@@ -1225,8 +1209,8 @@ qla24xx_start_scsi(srb_t *sp)
 
        /* Send marker if required */
        if (vha->marker_needed != 0) {
-               if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL)
-                                                       != QLA_SUCCESS)
+               if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+                   QLA_SUCCESS)
                        return QLA_FUNCTION_FAILED;
                vha->marker_needed = 0;
        }
@@ -1243,8 +1227,9 @@ qla24xx_start_scsi(srb_t *sp)
                if (!req->outstanding_cmds[handle])
                        break;
        }
-       if (index == MAX_OUTSTANDING_COMMANDS)
+       if (index == MAX_OUTSTANDING_COMMANDS) {
                goto queuing_error;
+       }
 
        /* Map the sg table so we have an accurate count of sg entries needed */
        if (scsi_sg_count(cmd)) {
@@ -1256,8 +1241,7 @@ qla24xx_start_scsi(srb_t *sp)
                nseg = 0;
 
        tot_dsds = nseg;
-
-       req_cnt = qla24xx_calc_iocbs(tot_dsds);
+       req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
        if (req->cnt < (req_cnt + 2)) {
                cnt = RD_REG_DWORD_RELAXED(req->req_q_out);
 
@@ -1322,7 +1306,6 @@ qla24xx_start_scsi(srb_t *sp)
        /* Specify response queue number where completion should happen */
        cmd_pkt->entry_status = (uint8_t) rsp->id;
        wmb();
-
        /* Adjust ring index. */
        req->ring_index++;
        if (req->ring_index == req->length) {
@@ -1534,9 +1517,6 @@ queuing_error:
        /* Cleanup will be performed by the caller (queuecommand) */
 
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-       DEBUG18(qla_printk(KERN_INFO, ha,
-           "CMD sent FAILED SCSI prot_op:%02x\n", scsi_get_prot_op(cmd)));
        return QLA_FUNCTION_FAILED;
 }
 
@@ -1581,8 +1561,11 @@ qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp)
                if (!req->outstanding_cmds[handle])
                        break;
        }
-       if (index == MAX_OUTSTANDING_COMMANDS)
+       if (index == MAX_OUTSTANDING_COMMANDS) {
+               ql_log(ql_log_warn, vha, 0x700b,
+                   "No room on oustanding cmd array.\n");
                goto queuing_error;
+       }
 
        /* Prep command array. */
        req->current_outstanding_cmd = handle;
@@ -1999,8 +1982,11 @@ qla2x00_start_sp(srb_t *sp)
        rval = QLA_FUNCTION_FAILED;
        spin_lock_irqsave(&ha->hardware_lock, flags);
        pkt = qla2x00_alloc_iocbs(sp->fcport->vha, sp);
-       if (!pkt)
+       if (!pkt) {
+               ql_log(ql_log_warn, sp->fcport->vha, 0x700c,
+                   "qla2x00_alloc_iocbs failed.\n");
                goto done;
+       }
 
        rval = QLA_SUCCESS;
        switch (ctx->type) {
index ae8e298..b16b772 100644 (file)
@@ -45,7 +45,7 @@ qla2100_intr_handler(int irq, void *dev_id)
        rsp = (struct rsp_que *) dev_id;
        if (!rsp) {
                printk(KERN_INFO
-                   "%s(): NULL response queue pointer\n", __func__);
+                   "%s(): NULL response queue pointer.\n", __func__);
                return (IRQ_NONE);
        }
 
@@ -91,9 +91,9 @@ qla2100_intr_handler(int irq, void *dev_id)
                                qla2x00_async_event(vha, rsp, mb);
                        } else {
                                /*EMPTY*/
-                               DEBUG2(printk("scsi(%ld): Unrecognized "
-                                   "interrupt type (%d).\n",
-                                   vha->host_no, mb[0]));
+                               ql_dbg(ql_dbg_async, vha, 0x5025,
+                                   "Unrecognized interrupt type (%d).\n",
+                                   mb[0]);
                        }
                        /* Release mailbox registers. */
                        WRT_REG_WORD(&reg->semaphore, 0);
@@ -142,7 +142,7 @@ qla2300_intr_handler(int irq, void *dev_id)
        rsp = (struct rsp_que *) dev_id;
        if (!rsp) {
                printk(KERN_INFO
-                   "%s(): NULL response queue pointer\n", __func__);
+                   "%s(): NULL response queue pointer.\n", __func__);
                return (IRQ_NONE);
        }
 
@@ -160,11 +160,13 @@ qla2300_intr_handler(int irq, void *dev_id)
 
                        hccr = RD_REG_WORD(&reg->hccr);
                        if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))
-                               qla_printk(KERN_INFO, ha, "Parity error -- "
-                                   "HCCR=%x, Dumping firmware!\n", hccr);
+                               ql_log(ql_log_warn, vha, 0x5026,
+                                   "Parity error -- HCCR=%x, Dumping "
+                                   "firmware.\n", hccr);
                        else
-                               qla_printk(KERN_INFO, ha, "RISC paused -- "
-                                   "HCCR=%x, Dumping firmware!\n", hccr);
+                               ql_log(ql_log_warn, vha, 0x5027,
+                                   "RISC paused -- HCCR=%x, Dumping "
+                                   "firmware.\n", hccr);
 
                        /*
                         * Issue a "HARD" reset in order for the RISC
@@ -213,9 +215,8 @@ qla2300_intr_handler(int irq, void *dev_id)
                        qla2x00_async_event(vha, rsp, mb);
                        break;
                default:
-                       DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
-                           "(%d).\n",
-                           vha->host_no, stat & 0xff));
+                       ql_dbg(ql_dbg_async, vha, 0x5028,
+                           "Unrecognized interrupt type (%d).\n", stat & 0xff);
                        break;
                }
                WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
@@ -262,11 +263,11 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
        }
 
        if (ha->mcp) {
-               DEBUG3(printk("%s(%ld): Got mailbox completion. cmd=%x.\n",
-                   __func__, vha->host_no, ha->mcp->mb[0]));
+               ql_dbg(ql_dbg_async, vha, 0x5000,
+                   "Got mbx completion. cmd=%x.\n", ha->mcp->mb[0]);
        } else {
-               DEBUG2_3(printk("%s(%ld): MBX pointer ERROR!\n",
-                   __func__, vha->host_no));
+               ql_dbg(ql_dbg_async, vha, 0x5001,
+                   "MBX pointer ERROR.\n");
        }
 }
 
@@ -285,22 +286,24 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr)
        for (cnt = 0; cnt < QLA_IDC_ACK_REGS; cnt++, wptr++)
                mb[cnt] = RD_REG_WORD(wptr);
 
-       DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
-           "%04x %04x %04x %04x %04x %04x %04x.\n", vha->host_no,
-           event[aen & 0xff],
-           mb[0], mb[1], mb[2], mb[3], mb[4], mb[5], mb[6]));
+       ql_dbg(ql_dbg_async, vha, 0x5021,
+           "Inter-Driver Commucation %s -- "
+           "%04x %04x %04x %04x %04x %04x %04x.\n",
+           event[aen & 0xff], mb[0], mb[1], mb[2], mb[3],
+           mb[4], mb[5], mb[6]);
 
        /* Acknowledgement needed? [Notify && non-zero timeout]. */
        timeout = (descr >> 8) & 0xf;
        if (aen != MBA_IDC_NOTIFY || !timeout)
                return;
 
-       DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
-           "ACK timeout=%d.\n", vha->host_no, event[aen & 0xff], timeout));
+       ql_dbg(ql_dbg_async, vha, 0x5022,
+           "Inter-Driver Commucation %s -- ACK timeout=%d.\n",
+           vha->host_no, event[aen & 0xff], timeout);
 
        rval = qla2x00_post_idc_ack_work(vha, mb);
        if (rval != QLA_SUCCESS)
-               qla_printk(KERN_WARNING, vha->hw,
+               ql_log(ql_log_warn, vha, 0x5023,
                    "IDC failed to post ACK.\n");
 }
 
@@ -393,15 +396,15 @@ skip_rio:
                break;
 
        case MBA_RESET:                 /* Reset */
-               DEBUG2(printk("scsi(%ld): Asynchronous RESET.\n",
-                       vha->host_no));
+               ql_dbg(ql_dbg_async, vha, 0x5002,
+                   "Asynchronous RESET.\n");
 
                set_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
                break;
 
        case MBA_SYSTEM_ERR:            /* System Error */
                mbx = IS_QLA81XX(ha) ? RD_REG_WORD(&reg24->mailbox7) : 0;
-               qla_printk(KERN_INFO, ha,
+               ql_log(ql_log_warn, vha, 0x5003,
                    "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh "
                    "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx);
 
@@ -409,7 +412,7 @@ skip_rio:
 
                if (IS_FWI2_CAPABLE(ha)) {
                        if (mb[1] == 0 && mb[2] == 0) {
-                               qla_printk(KERN_ERR, ha,
+                               ql_log(ql_log_fatal, vha, 0x5004,
                                    "Unrecoverable Hardware Error: adapter "
                                    "marked OFFLINE!\n");
                                vha->flags.online = 0;
@@ -422,7 +425,7 @@ skip_rio:
                                set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
                        }
                } else if (mb[1] == 0) {
-                       qla_printk(KERN_INFO, ha,
+                       ql_log(ql_log_fatal, vha, 0x5005,
                            "Unrecoverable Hardware Error: adapter marked "
                            "OFFLINE!\n");
                        vha->flags.online = 0;
@@ -431,31 +434,27 @@ skip_rio:
                break;
 
        case MBA_REQ_TRANSFER_ERR:      /* Request Transfer Error */
-               DEBUG2(printk("scsi(%ld): ISP Request Transfer Error (%x).\n",
-                   vha->host_no, mb[1]));
-               qla_printk(KERN_WARNING, ha,
-                   "ISP Request Transfer Error (%x).\n", mb[1]);
+               ql_log(ql_log_warn, vha, 0x5006,
+                   "ISP Request Transfer Error (%x).\n",  mb[1]);
 
                set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
                break;
 
        case MBA_RSP_TRANSFER_ERR:      /* Response Transfer Error */
-               DEBUG2(printk("scsi(%ld): ISP Response Transfer Error.\n",
-                   vha->host_no));
-               qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n");
+               ql_log(ql_log_warn, vha, 0x5007,
+                   "ISP Response Transfer Error.\n");
 
                set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
                break;
 
        case MBA_WAKEUP_THRES:          /* Request Queue Wake-up */
-               DEBUG2(printk("scsi(%ld): Asynchronous WAKEUP_THRES.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_async, vha, 0x5008,
+                   "Asynchronous WAKEUP_THRES.\n");
                break;
 
        case MBA_LIP_OCCURRED:          /* Loop Initialization Procedure */
-               DEBUG2(printk("scsi(%ld): LIP occurred (%x).\n", vha->host_no,
-                   mb[1]));
-               qla_printk(KERN_INFO, ha, "LIP occurred (%x).\n", mb[1]);
+               ql_log(ql_log_info, vha, 0x5009,
+                   "LIP occurred (%x).\n", mb[1]);
 
                if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
                        atomic_set(&vha->loop_state, LOOP_DOWN);
@@ -488,10 +487,8 @@ skip_rio:
                        ha->link_data_rate = mb[1];
                }
 
-               DEBUG2(printk("scsi(%ld): Asynchronous LOOP UP (%s Gbps).\n",
-                   vha->host_no, link_speed));
-               qla_printk(KERN_INFO, ha, "LOOP UP detected (%s Gbps).\n",
-                   link_speed);
+               ql_log(ql_log_info, vha, 0x500a,
+                   "LOOP UP detected (%s Gbps).\n", link_speed);
 
                vha->flags.management_server_logged_in = 0;
                qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate);
@@ -500,12 +497,9 @@ skip_rio:
        case MBA_LOOP_DOWN:             /* Loop Down Event */
                mbx = IS_QLA81XX(ha) ? RD_REG_WORD(&reg24->mailbox4) : 0;
                mbx = IS_QLA82XX(ha) ? RD_REG_WORD(&reg82->mailbox_out[4]) : mbx;
-               DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN "
-                   "(%x %x %x %x).\n", vha->host_no, mb[1], mb[2], mb[3],
-                   mbx));
-               qla_printk(KERN_INFO, ha,
-                   "LOOP DOWN detected (%x %x %x %x).\n", mb[1], mb[2], mb[3],
-                   mbx);
+               ql_log(ql_log_info, vha, 0x500b,
+                   "LOOP DOWN detected (%x %x %x %x).\n",
+                   mb[1], mb[2], mb[3], mbx);
 
                if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
                        atomic_set(&vha->loop_state, LOOP_DOWN);
@@ -525,9 +519,7 @@ skip_rio:
                break;
 
        case MBA_LIP_RESET:             /* LIP reset occurred */
-               DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n",
-                   vha->host_no, mb[1]));
-               qla_printk(KERN_INFO, ha,
+               ql_log(ql_log_info, vha, 0x500c,
                    "LIP reset occurred (%x).\n", mb[1]);
 
                if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
@@ -554,14 +546,15 @@ skip_rio:
                        break;
 
                if (IS_QLA8XXX_TYPE(ha)) {
-                       DEBUG2(printk("scsi(%ld): DCBX Completed -- %04x %04x "
-                           "%04x\n", vha->host_no, mb[1], mb[2], mb[3]));
+                       ql_dbg(ql_dbg_async, vha, 0x500d,
+                           "DCBX Completed -- %04x %04x %04x.\n",
+                           mb[1], mb[2], mb[3]);
                        if (ha->notify_dcbx_comp)
                                complete(&ha->dcbx_comp);
 
                } else
-                       DEBUG2(printk("scsi(%ld): Asynchronous P2P MODE "
-                           "received.\n", vha->host_no));
+                       ql_dbg(ql_dbg_async, vha, 0x500e,
+                           "Asynchronous P2P MODE received.\n");
 
                /*
                 * Until there's a transition from loop down to loop up, treat
@@ -594,10 +587,7 @@ skip_rio:
                if (IS_QLA2100(ha))
                        break;
 
-               DEBUG2(printk("scsi(%ld): Asynchronous Change In Connection "
-                   "received.\n",
-                   vha->host_no));
-               qla_printk(KERN_INFO, ha,
+               ql_log(ql_log_info, vha, 0x500f,
                    "Configuration change detected: value=%x.\n", mb[1]);
 
                if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
@@ -640,11 +630,9 @@ skip_rio:
 
                /* Global event -- port logout or port unavailable. */
                if (mb[1] == 0xffff && mb[2] == 0x7) {
-                       DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n",
-                           vha->host_no));
-                       DEBUG(printk(KERN_INFO
-                           "scsi(%ld): Port unavailable %04x %04x %04x.\n",
-                           vha->host_no, mb[1], mb[2], mb[3]));
+                       ql_dbg(ql_dbg_async, vha, 0x5010,
+                           "Port unavailable %04x %04x %04x.\n",
+                           mb[1], mb[2], mb[3]);
 
                        if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
                                atomic_set(&vha->loop_state, LOOP_DOWN);
@@ -674,17 +662,15 @@ skip_rio:
                atomic_set(&vha->loop_down_timer, 0);
                if (atomic_read(&vha->loop_state) != LOOP_DOWN &&
                    atomic_read(&vha->loop_state) != LOOP_DEAD) {
-                       DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE "
-                           "ignored %04x/%04x/%04x.\n", vha->host_no, mb[1],
-                           mb[2], mb[3]));
+                       ql_dbg(ql_dbg_async, vha, 0x5011,
+                           "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n",
+                           mb[1], mb[2], mb[3]);
                        break;
                }
 
-               DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n",
-                   vha->host_no));
-               DEBUG(printk(KERN_INFO
-                   "scsi(%ld): Port database changed %04x %04x %04x.\n",
-                   vha->host_no, mb[1], mb[2], mb[3]));
+               ql_dbg(ql_dbg_async, vha, 0x5012,
+                   "Port database changed %04x %04x %04x.\n",
+                   mb[1], mb[2], mb[3]);
 
                /*
                 * Mark all devices as missing so we will login again.
@@ -707,20 +693,17 @@ skip_rio:
                if (ha->flags.npiv_supported && vha->vp_idx != (mb[3] & 0xff))
                        break;
 
-               DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
-                   vha->host_no));
-               DEBUG(printk(KERN_INFO
-                   "scsi(%ld): RSCN database changed -- %04x %04x %04x.\n",
-                   vha->host_no, mb[1], mb[2], mb[3]));
+               ql_dbg(ql_dbg_async, vha, 0x5013,
+                   "RSCN database changed -- %04x %04x %04x.\n",
+                   mb[1], mb[2], mb[3]);
 
                rscn_entry = ((mb[1] & 0xff) << 16) | mb[2];
                host_pid = (vha->d_id.b.domain << 16) | (vha->d_id.b.area << 8)
                                | vha->d_id.b.al_pa;
                if (rscn_entry == host_pid) {
-                       DEBUG(printk(KERN_INFO
-                           "scsi(%ld): Ignoring RSCN update to local host "
-                           "port ID (%06x)\n",
-                           vha->host_no, host_pid));
+                       ql_dbg(ql_dbg_async, vha, 0x5014,
+                           "Ignoring RSCN update to local host "
+                           "port ID (%06x).\n", host_pid);
                        break;
                }
 
@@ -747,8 +730,8 @@ skip_rio:
 
        /* case MBA_RIO_RESPONSE: */
        case MBA_ZIO_RESPONSE:
-               DEBUG3(printk("scsi(%ld): [R|Z]IO update completion.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_async, vha, 0x5015,
+                   "[R|Z]IO update completion.\n");
 
                if (IS_FWI2_CAPABLE(ha))
                        qla24xx_process_response_queue(vha, rsp);
@@ -757,61 +740,68 @@ skip_rio:
                break;
 
        case MBA_DISCARD_RND_FRAME:
-               DEBUG2(printk("scsi(%ld): Discard RND Frame -- %04x %04x "
-                   "%04x.\n", vha->host_no, mb[1], mb[2], mb[3]));
+               ql_dbg(ql_dbg_async, vha, 0x5016,
+                   "Discard RND Frame -- %04x %04x %04x.\n",
+                   mb[1], mb[2], mb[3]);
                break;
 
        case MBA_TRACE_NOTIFICATION:
-               DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n",
-               vha->host_no, mb[1], mb[2]));
+               ql_dbg(ql_dbg_async, vha, 0x5017,
+                   "Trace Notification -- %04x %04x.\n", mb[1], mb[2]);
                break;
 
        case MBA_ISP84XX_ALERT:
-               DEBUG2(printk("scsi(%ld): ISP84XX Alert Notification -- "
-                   "%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
+               ql_dbg(ql_dbg_async, vha, 0x5018,
+                   "ISP84XX Alert Notification -- %04x %04x %04x.\n",
+                   mb[1], mb[2], mb[3]);
 
                spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
                switch (mb[1]) {
                case A84_PANIC_RECOVERY:
-                       qla_printk(KERN_INFO, ha, "Alert 84XX: panic recovery "
-                           "%04x %04x\n", mb[2], mb[3]);
+                       ql_log(ql_log_info, vha, 0x5019,
+                           "Alert 84XX: panic recovery %04x %04x.\n",
+                           mb[2], mb[3]);
                        break;
                case A84_OP_LOGIN_COMPLETE:
                        ha->cs84xx->op_fw_version = mb[3] << 16 | mb[2];
-                       DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
-                           "firmware version %x\n", ha->cs84xx->op_fw_version));
+                       ql_log(ql_log_info, vha, 0x501a,
+                           "Alert 84XX: firmware version %x.\n",
+                           ha->cs84xx->op_fw_version);
                        break;
                case A84_DIAG_LOGIN_COMPLETE:
                        ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
-                       DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
-                           "diagnostic firmware version %x\n",
-                           ha->cs84xx->diag_fw_version));
+                       ql_log(ql_log_info, vha, 0x501b,
+                           "Alert 84XX: diagnostic firmware version %x.\n",
+                           ha->cs84xx->diag_fw_version);
                        break;
                case A84_GOLD_LOGIN_COMPLETE:
                        ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
                        ha->cs84xx->fw_update = 1;
-                       DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX: gold "
-                           "firmware version %x\n",
-                           ha->cs84xx->gold_fw_version));
+                       ql_log(ql_log_info, vha, 0x501c,
+                           "Alert 84XX: gold firmware version %x.\n",
+                           ha->cs84xx->gold_fw_version);
                        break;
                default:
-                       qla_printk(KERN_ERR, ha,
-                           "Alert 84xx: Invalid Alert %04x %04x %04x\n",
+                       ql_log(ql_log_warn, vha, 0x501d,
+                           "Alert 84xx: Invalid Alert %04x %04x %04x.\n",
                            mb[1], mb[2], mb[3]);
                }
                spin_unlock_irqrestore(&ha->cs84xx->access_lock, flags);
                break;
        case MBA_DCBX_START:
-               DEBUG2(printk("scsi(%ld): DCBX Started -- %04x %04x %04x\n",
-                   vha->host_no, mb[1], mb[2], mb[3]));
+               ql_dbg(ql_dbg_async, vha, 0x501e,
+                   "DCBX Started -- %04x %04x %04x.\n",
+                   mb[1], mb[2], mb[3]);
                break;
        case MBA_DCBX_PARAM_UPDATE:
-               DEBUG2(printk("scsi(%ld): DCBX Parameters Updated -- "
-                   "%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
+               ql_dbg(ql_dbg_async, vha, 0x501f,
+                   "DCBX Parameters Updated -- %04x %04x %04x.\n",
+                   mb[1], mb[2], mb[3]);
                break;
        case MBA_FCF_CONF_ERR:
-               DEBUG2(printk("scsi(%ld): FCF Configuration Error -- "
-                   "%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
+               ql_dbg(ql_dbg_async, vha, 0x5020,
+                   "FCF Configuration Error -- %04x %04x %04x.\n",
+                   mb[1], mb[2], mb[3]);
                break;
        case MBA_IDC_COMPLETE:
        case MBA_IDC_NOTIFY:
@@ -838,10 +828,8 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
 
        /* Validate handle. */
        if (index >= MAX_OUTSTANDING_COMMANDS) {
-               DEBUG2(printk("scsi(%ld): Invalid SCSI completion handle %d.\n",
-                   vha->host_no, index));
-               qla_printk(KERN_WARNING, ha,
-                   "Invalid SCSI completion handle %d.\n", index);
+               ql_log(ql_log_warn, vha, 0x3014,
+                   "Invalid SCSI command index (%x).\n", index);
 
                if (IS_QLA82XX(ha))
                        set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
@@ -859,10 +847,7 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
                sp->cmd->result = DID_OK << 16;
                qla2x00_sp_compl(ha, sp);
        } else {
-               DEBUG2(printk("scsi(%ld) Req:%d: Invalid ISP SCSI completion"
-                       " handle(0x%x)\n", vha->host_no, req->id, index));
-               qla_printk(KERN_WARNING, ha,
-                   "Invalid ISP SCSI completion handle\n");
+               ql_log(ql_log_warn, vha, 0x3016, "Invalid SCSI SRB.\n");
 
                if (IS_QLA82XX(ha))
                        set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
@@ -882,8 +867,8 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
 
        index = LSW(pkt->handle);
        if (index >= MAX_OUTSTANDING_COMMANDS) {
-               qla_printk(KERN_WARNING, ha,
-                   "%s: Invalid completion handle (%x).\n", func, index);
+               ql_log(ql_log_warn, vha, 0x5031,
+                   "Invalid command index (%x).\n", index);
                if (IS_QLA82XX(ha))
                        set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
                else
@@ -892,15 +877,13 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
        }
        sp = req->outstanding_cmds[index];
        if (!sp) {
-               qla_printk(KERN_WARNING, ha,
-                   "%s: Invalid completion handle (%x) -- timed-out.\n", func,
-                   index);
+               ql_log(ql_log_warn, vha, 0x5032,
+                   "Invalid completion handle (%x) -- timed-out.\n", index);
                return sp;
        }
        if (sp->handle != index) {
-               qla_printk(KERN_WARNING, ha,
-                   "%s: SRB handle (%x) mismatch %x.\n", func, sp->handle,
-                   index);
+               ql_log(ql_log_warn, vha, 0x5033,
+                   "SRB handle (%x) mismatch %x.\n", sp->handle, index);
                return NULL;
        }
 
@@ -937,17 +920,17 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
        data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
            QLA_LOGIO_LOGIN_RETRIED : 0;
        if (mbx->entry_status) {
-               DEBUG2(printk(KERN_WARNING
-                   "scsi(%ld:%x): Async-%s error entry - portid=%02x%02x%02x "
+               ql_dbg(ql_dbg_async, vha, 0x5043,
+                   "Async-%s error entry - portid=%02x%02x%02x "
                    "entry-status=%x status=%x state-flag=%x "
                    "status-flags=%x.\n",
-                   fcport->vha->host_no, sp->handle, type,
-                   fcport->d_id.b.domain, fcport->d_id.b.area,
+                   type, fcport->d_id.b.domain, fcport->d_id.b.area,
                    fcport->d_id.b.al_pa, mbx->entry_status,
                    le16_to_cpu(mbx->status), le16_to_cpu(mbx->state_flags),
-                   le16_to_cpu(mbx->status_flags)));
+                   le16_to_cpu(mbx->status_flags));
 
-               DEBUG2(qla2x00_dump_buffer((uint8_t *)mbx, sizeof(*mbx)));
+               ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5057,
+                   (uint8_t *)mbx, sizeof(*mbx));
 
                goto logio_done;
        }
@@ -957,12 +940,10 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
            le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE)
                status = 0;
        if (!status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) {
-               DEBUG2(printk(KERN_DEBUG
-                   "scsi(%ld:%x): Async-%s complete - portid=%02x%02x%02x "
-                   "mbx1=%x.\n",
-                   fcport->vha->host_no, sp->handle, type,
-                   fcport->d_id.b.domain, fcport->d_id.b.area,
-                   fcport->d_id.b.al_pa, le16_to_cpu(mbx->mb1)));
+               ql_dbg(ql_dbg_async, vha, 0x5045,
+                   "Async-%s complete - portid=%02x%02x%02x mbx1=%x.\n",
+                   type, fcport->d_id.b.domain, fcport->d_id.b.area,
+                   fcport->d_id.b.al_pa, le16_to_cpu(mbx->mb1));
 
                data[0] = MBS_COMMAND_COMPLETE;
                if (ctx->type == SRB_LOGIN_CMD) {
@@ -987,14 +968,14 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
                break;
        }
 
-       DEBUG2(printk(KERN_WARNING
-           "scsi(%ld:%x): Async-%s failed - portid=%02x%02x%02x status=%x "
+       ql_log(ql_log_warn, vha, 0x5046,
+           "Async-%s failed - portid=%02x%02x%02x status=%x "
            "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n",
-           fcport->vha->host_no, sp->handle, type, fcport->d_id.b.domain,
+           type, fcport->d_id.b.domain,
            fcport->d_id.b.area, fcport->d_id.b.al_pa, status,
            le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1),
            le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6),
-           le16_to_cpu(mbx->mb7)));
+           le16_to_cpu(mbx->mb7));
 
 logio_done:
        lio->done(sp);
@@ -1025,9 +1006,8 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
                type = "ct pass-through";
                break;
        default:
-               qla_printk(KERN_WARNING, ha,
-                   "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp,
-                   sp_bsg->type);
+               ql_log(ql_log_warn, vha, 0x5047,
+                   "Unrecognized SRB: (%p) type=%d.\n", sp, sp_bsg->type);
                return;
        }
 
@@ -1045,20 +1025,20 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
                        bsg_job->reply->reply_payload_rcv_len =
                            le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
 
-                       DEBUG2(qla_printk(KERN_WARNING, ha,
-                           "scsi(%ld): CT pass-through-%s error "
+                       ql_log(ql_log_warn, vha, 0x5048,
+                           "CT pass-through-%s error "
                            "comp_status-status=0x%x total_byte = 0x%x.\n",
-                           vha->host_no, type, comp_status,
-                           bsg_job->reply->reply_payload_rcv_len));
+                           type, comp_status,
+                           bsg_job->reply->reply_payload_rcv_len);
                } else {
-                       DEBUG2(qla_printk(KERN_WARNING, ha,
-                           "scsi(%ld): CT pass-through-%s error "
-                           "comp_status-status=0x%x.\n",
-                           vha->host_no, type, comp_status));
+                       ql_log(ql_log_warn, vha, 0x5049,
+                           "CT pass-through-%s error "
+                           "comp_status-status=0x%x.\n", type, comp_status);
                        bsg_job->reply->result = DID_ERROR << 16;
                        bsg_job->reply->reply_payload_rcv_len = 0;
                }
-               DEBUG2(qla2x00_dump_buffer((uint8_t *)pkt, sizeof(*pkt)));
+               ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5058,
+                   (uint8_t *)pkt, sizeof(*pkt));
        } else {
                bsg_job->reply->result =  DID_OK << 16;
                bsg_job->reply->reply_payload_rcv_len =
@@ -1110,9 +1090,8 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
                type = "ct pass-through";
                break;
        default:
-               qla_printk(KERN_WARNING, ha,
-                   "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp,
-                   sp_bsg->type);
+               ql_log(ql_log_warn, vha, 0x503e,
+                   "Unrecognized SRB: (%p) type=%d.\n", sp, sp_bsg->type);
                return;
        }
 
@@ -1132,27 +1111,31 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
                        bsg_job->reply->reply_payload_rcv_len =
                                le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->total_byte_count);
 
-                       DEBUG2(qla_printk(KERN_WARNING, ha,
-                           "scsi(%ld:0x%x): ELS-CT pass-through-%s error comp_status-status=0x%x "
+                       ql_log(ql_log_info, vha, 0x503f,
+                           "ELS-CT pass-through-%s error comp_status-status=0x%x "
                            "error subcode 1=0x%x error subcode 2=0x%x total_byte = 0x%x.\n",
-                               vha->host_no, sp->handle, type, comp_status, fw_status[1], fw_status[2],
-                               le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->total_byte_count)));
+                           type, comp_status, fw_status[1], fw_status[2],
+                           le16_to_cpu(((struct els_sts_entry_24xx *)
+                               pkt)->total_byte_count));
                        fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
                        memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
                }
                else {
-                       DEBUG2(qla_printk(KERN_WARNING, ha,
-                           "scsi(%ld:0x%x): ELS-CT pass-through-%s error comp_status-status=0x%x "
+                       ql_log(ql_log_info, vha, 0x5040,
+                           "ELS-CT pass-through-%s error comp_status-status=0x%x "
                            "error subcode 1=0x%x error subcode 2=0x%x.\n",
-                               vha->host_no, sp->handle, type, comp_status,
-                               le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1),
-                               le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2)));
+                           type, comp_status,
+                           le16_to_cpu(((struct els_sts_entry_24xx *)
+                               pkt)->error_subcode_1),
+                           le16_to_cpu(((struct els_sts_entry_24xx *)
+                                   pkt)->error_subcode_2));
                        bsg_job->reply->result = DID_ERROR << 16;
                        bsg_job->reply->reply_payload_rcv_len = 0;
                        fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
                        memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
                }
-               DEBUG2(qla2x00_dump_buffer((uint8_t *)pkt, sizeof(*pkt)));
+               ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5056,
+                               (uint8_t *)pkt, sizeof(*pkt));
        }
        else {
                bsg_job->reply->result =  DID_OK << 16;
@@ -1201,25 +1184,24 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
        data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
                QLA_LOGIO_LOGIN_RETRIED : 0;
        if (logio->entry_status) {
-               DEBUG2(printk(KERN_WARNING
-                   "scsi(%ld:%x): Async-%s error entry - "
+               ql_log(ql_log_warn, vha, 0x5034,
+                   "Async-%s error entry - "
                    "portid=%02x%02x%02x entry-status=%x.\n",
-                   fcport->vha->host_no, sp->handle, type,
-                   fcport->d_id.b.domain, fcport->d_id.b.area,
-                   fcport->d_id.b.al_pa, logio->entry_status));
-               DEBUG2(qla2x00_dump_buffer((uint8_t *)logio, sizeof(*logio)));
+                   type, fcport->d_id.b.domain, fcport->d_id.b.area,
+                   fcport->d_id.b.al_pa, logio->entry_status);
+               ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5059,
+                   (uint8_t *)logio, sizeof(*logio));
 
                goto logio_done;
        }
 
        if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) {
-               DEBUG2(printk(KERN_DEBUG
-                   "scsi(%ld:%x): Async-%s complete - portid=%02x%02x%02x "
+               ql_dbg(ql_dbg_async, vha, 0x5036,
+                   "Async-%s complete - portid=%02x%02x%02x "
                    "iop0=%x.\n",
-                   fcport->vha->host_no, sp->handle, type,
-                   fcport->d_id.b.domain, fcport->d_id.b.area,
+                   type, fcport->d_id.b.domain, fcport->d_id.b.area,
                    fcport->d_id.b.al_pa,
-                   le32_to_cpu(logio->io_parameter[0])));
+                   le32_to_cpu(logio->io_parameter[0]));
 
                data[0] = MBS_COMMAND_COMPLETE;
                if (ctx->type != SRB_LOGIN_CMD)
@@ -1256,14 +1238,14 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
                break;
        }
 
-       DEBUG2(printk(KERN_WARNING
-           "scsi(%ld:%x): Async-%s failed - portid=%02x%02x%02x comp=%x "
+       ql_dbg(ql_dbg_async, vha, 0x5037,
+           "Async-%s failed - portid=%02x%02x%02x comp=%x "
            "iop0=%x iop1=%x.\n",
-           fcport->vha->host_no, sp->handle, type, fcport->d_id.b.domain,
+           type, fcport->d_id.b.domain,
            fcport->d_id.b.area, fcport->d_id.b.al_pa,
            le16_to_cpu(logio->comp_status),
            le32_to_cpu(logio->io_parameter[0]),
-           le32_to_cpu(logio->io_parameter[1])));
+           le32_to_cpu(logio->io_parameter[1]));
 
 logio_done:
        lio->done(sp);
@@ -1292,38 +1274,34 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
        fcport = sp->fcport;
 
        if (sts->entry_status) {
-               DEBUG2(printk(KERN_WARNING
-                   "scsi(%ld:%x): Async-%s error - entry-status(%x).\n",
-                   fcport->vha->host_no, sp->handle, type,
-                   sts->entry_status));
+               ql_log(ql_log_warn, vha, 0x5038,
+                   "Async-%s error - entry-status(%x).\n",
+                   type, sts->entry_status);
        } else if (sts->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
-               DEBUG2(printk(KERN_WARNING
-                   "scsi(%ld:%x): Async-%s error - completion status(%x).\n",
-                   fcport->vha->host_no, sp->handle, type,
-                   sts->comp_status));
+               ql_log(ql_log_warn, vha, 0x5039,
+                   "Async-%s error - completion status(%x).\n",
+                   type, sts->comp_status);
        } else if (!(le16_to_cpu(sts->scsi_status) &
            SS_RESPONSE_INFO_LEN_VALID)) {
-               DEBUG2(printk(KERN_WARNING
-                   "scsi(%ld:%x): Async-%s error - no response info(%x).\n",
-                   fcport->vha->host_no, sp->handle, type,
-                   sts->scsi_status));
+               ql_log(ql_log_warn, vha, 0x503a,
+                   "Async-%s error - no response info(%x).\n",
+                   type, sts->scsi_status);
        } else if (le32_to_cpu(sts->rsp_data_len) < 4) {
-               DEBUG2(printk(KERN_WARNING
-                   "scsi(%ld:%x): Async-%s error - not enough response(%d).\n",
-                   fcport->vha->host_no, sp->handle, type,
-                   sts->rsp_data_len));
+               ql_log(ql_log_warn, vha, 0x503b,
+                   "Async-%s error - not enough response(%d).\n",
+                   type, sts->rsp_data_len);
        } else if (sts->data[3]) {
-               DEBUG2(printk(KERN_WARNING
-                   "scsi(%ld:%x): Async-%s error - response(%x).\n",
-                   fcport->vha->host_no, sp->handle, type,
-                   sts->data[3]));
+               ql_log(ql_log_warn, vha, 0x503c,
+                   "Async-%s error - response(%x).\n",
+                   type, sts->data[3]);
        } else {
                error = 0;
        }
 
        if (error) {
                iocb->u.tmf.data = error;
-               DEBUG2(qla2x00_dump_buffer((uint8_t *)sts, sizeof(*sts)));
+               ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055,
+                   (uint8_t *)sts, sizeof(*sts));
        }
 
        iocb->done(sp);
@@ -1360,8 +1338,8 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
                }
 
                if (pkt->entry_status != 0) {
-                       DEBUG3(printk(KERN_INFO
-                           "scsi(%ld): Process error entry.\n", vha->host_no));
+                       ql_log(ql_log_warn, vha, 0x5035,
+                           "Process error entry.\n");
 
                        qla2x00_error_entry(vha, rsp, pkt);
                        ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
@@ -1399,10 +1377,10 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
                        break;
                default:
                        /* Type Not Supported. */
-                       DEBUG4(printk(KERN_WARNING
-                           "scsi(%ld): Received unknown response pkt type %x "
+                       ql_log(ql_log_warn, vha, 0x504a,
+                           "Received unknown response pkt type %x "
                            "entry status=%x.\n",
-                           vha->host_no, pkt->entry_type, pkt->entry_status));
+                           pkt->entry_type, pkt->entry_status);
                        break;
                }
                ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
@@ -1418,6 +1396,7 @@ static inline void
 qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
     uint32_t sense_len, struct rsp_que *rsp)
 {
+       struct scsi_qla_host *vha = sp->fcport->vha;
        struct scsi_cmnd *cp = sp->cmd;
 
        if (sense_len >= SCSI_SENSE_BUFFERSIZE)
@@ -1435,11 +1414,13 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
        if (sp->request_sense_length != 0)
                rsp->status_srb = sp;
 
-       DEBUG5(printk("%s(): Check condition Sense data, scsi(%ld:%d:%d:%d) "
-           "cmd=%p\n", __func__, sp->fcport->vha->host_no,
-           cp->device->channel, cp->device->id, cp->device->lun, cp));
+       ql_dbg(ql_dbg_io, vha, 0x301c,
+           "Check condition Sense data, scsi(%ld:%d:%d:%d) cmd=%p.\n",
+           sp->fcport->vha->host_no, cp->device->channel, cp->device->id,
+           cp->device->lun, cp);
        if (sense_len)
-               DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len));
+               ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302b,
+                   cp->sense_buffer, sense_len);
 }
 
 struct scsi_dif_tuple {
@@ -1457,6 +1438,7 @@ struct scsi_dif_tuple {
 static inline void
 qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
 {
+       struct scsi_qla_host *vha = sp->fcport->vha;
        struct scsi_cmnd *cmd = sp->cmd;
        struct scsi_dif_tuple   *ep =
                        (struct scsi_dif_tuple *)&sts24->data[20];
@@ -1473,15 +1455,15 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
        e_guard = be16_to_cpu(ep->guard);
        a_guard = be16_to_cpu(ap->guard);
 
-       DEBUG18(printk(KERN_DEBUG
-           "%s(): iocb(s) %p Returned STATUS\n", __func__, sts24));
+       ql_dbg(ql_dbg_io, vha, 0x3023,
+           "iocb(s) %p Returned STATUS.\n", sts24);
 
-       DEBUG18(printk(KERN_ERR "DIF ERROR in cmd 0x%x lba 0x%llx act ref"
+       ql_dbg(ql_dbg_io, vha, 0x3024,
+           "DIF ERROR in cmd 0x%x lba 0x%llx act ref"
            " tag=0x%x, exp ref_tag=0x%x, act app tag=0x%x, exp app"
-           " tag=0x%x, act guard=0x%x, exp guard=0x%x\n",
+           " tag=0x%x, act guard=0x%x, exp guard=0x%x.\n",
            cmd->cmnd[0], (u64)scsi_get_lba(cmd), a_ref_tag, e_ref_tag,
-           a_app_tag, e_app_tag, a_guard, e_guard));
-
+           a_app_tag, e_app_tag, a_guard, e_guard);
 
        /* check guard */
        if (e_guard != a_guard) {
@@ -1569,9 +1551,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                sp = NULL;
 
        if (sp == NULL) {
-               qla_printk(KERN_WARNING, ha,
-                   "scsi(%ld): Invalid status handle (0x%x).\n", vha->host_no,
-                   sts->handle);
+               ql_log(ql_log_warn, vha, 0x3017,
+                   "Invalid status handle (0x%x).\n", sts->handle);
 
                if (IS_QLA82XX(ha))
                        set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
@@ -1582,9 +1563,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
        }
        cp = sp->cmd;
        if (cp == NULL) {
-               qla_printk(KERN_WARNING, ha,
-                   "scsi(%ld): Command already returned (0x%x/%p).\n",
-                   vha->host_no, sts->handle, sp);
+               ql_log(ql_log_warn, vha, 0x3018,
+                   "Command already returned (0x%x/%p).\n",
+                   sts->handle, sp);
 
                return;
        }
@@ -1629,10 +1610,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                        par_sense_len -= rsp_info_len;
                }
                if (rsp_info_len > 3 && rsp_info[3]) {
-                       DEBUG2(qla_printk(KERN_INFO, ha,
-                           "scsi(%ld:%d:%d): FCP I/O protocol failure "
-                           "(0x%x/0x%x).\n", vha->host_no, cp->device->id,
-                           cp->device->lun, rsp_info_len, rsp_info[3]));
+                       ql_log(ql_log_warn, vha, 0x3019,
+                           "FCP I/O protocol failure (0x%x/0x%x).\n",
+                           rsp_info_len, rsp_info[3]);
 
                        cp->result = DID_BUS_BUSY << 16;
                        goto out;
@@ -1661,11 +1641,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                        if (!lscsi_status &&
                            ((unsigned)(scsi_bufflen(cp) - resid) <
                             cp->underflow)) {
-                               qla_printk(KERN_INFO, ha,
-                                   "scsi(%ld:%d:%d): Mid-layer underflow "
+                               ql_log(ql_log_warn, vha, 0x301a,
+                                   "Mid-layer underflow "
                                    "detected (0x%x of 0x%x bytes).\n",
-                                   vha->host_no, cp->device->id,
-                                   cp->device->lun, resid, scsi_bufflen(cp));
+                                   resid, scsi_bufflen(cp));
 
                                cp->result = DID_ERROR << 16;
                                break;
@@ -1674,9 +1653,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                cp->result = DID_OK << 16 | lscsi_status;
 
                if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
-                       DEBUG2(qla_printk(KERN_INFO, ha,
-                           "scsi(%ld:%d:%d) QUEUE FULL detected.\n",
-                           vha->host_no, cp->device->id, cp->device->lun));
+                       ql_log(ql_log_warn, vha, 0x301b,
+                           "QUEUE FULL detected.\n");
                        break;
                }
                logit = 0;
@@ -1697,11 +1675,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                scsi_set_resid(cp, resid);
                if (scsi_status & SS_RESIDUAL_UNDER) {
                        if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) {
-                               DEBUG2(qla_printk(KERN_INFO, ha,
-                                   "scsi(%ld:%d:%d) Dropped frame(s) detected "
-                                   "(0x%x of 0x%x bytes).\n", vha->host_no,
-                                   cp->device->id, cp->device->lun, resid,
-                                   scsi_bufflen(cp)));
+                               ql_log(ql_log_warn, vha, 0x301d,
+                                   "Dropped frame(s) detected "
+                                   "(0x%x of 0x%x bytes).\n",
+                                   resid, scsi_bufflen(cp));
 
                                cp->result = DID_ERROR << 16 | lscsi_status;
                                break;
@@ -1710,20 +1687,18 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                        if (!lscsi_status &&
                            ((unsigned)(scsi_bufflen(cp) - resid) <
                            cp->underflow)) {
-                               qla_printk(KERN_INFO, ha,
-                                   "scsi(%ld:%d:%d): Mid-layer underflow "
+                               ql_log(ql_log_warn, vha, 0x301e,
+                                   "Mid-layer underflow "
                                    "detected (0x%x of 0x%x bytes).\n",
-                                   vha->host_no, cp->device->id,
-                                   cp->device->lun, resid, scsi_bufflen(cp));
+                                   resid, scsi_bufflen(cp));
 
                                cp->result = DID_ERROR << 16;
                                break;
                        }
                } else {
-                       DEBUG2(qla_printk(KERN_INFO, ha,
-                           "scsi(%ld:%d:%d) Dropped frame(s) detected (0x%x "
-                           "of 0x%x bytes).\n", vha->host_no, cp->device->id,
-                           cp->device->lun, resid, scsi_bufflen(cp)));
+                       ql_log(ql_log_warn, vha, 0x301f,
+                           "Dropped frame(s) detected (0x%x "
+                           "of 0x%x bytes).\n", resid, scsi_bufflen(cp));
 
                        cp->result = DID_ERROR << 16 | lscsi_status;
                        goto check_scsi_status;
@@ -1739,10 +1714,8 @@ check_scsi_status:
                 */
                if (lscsi_status != 0) {
                        if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
-                               DEBUG2(qla_printk(KERN_INFO, ha,
-                                   "scsi(%ld:%d:%d) QUEUE FULL detected.\n",
-                                   vha->host_no, cp->device->id,
-                                   cp->device->lun));
+                               ql_log(ql_log_warn, vha, 0x3020,
+                                   "QUEUE FULL detected.\n");
                                logit = 1;
                                break;
                        }
@@ -1781,10 +1754,9 @@ check_scsi_status:
                                break;
                }
 
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                       "scsi(%ld:%d:%d) Port down status: port-state=0x%x\n",
-                       vha->host_no, cp->device->id, cp->device->lun,
-                       atomic_read(&fcport->state)));
+               ql_dbg(ql_dbg_io, vha, 0x3021,
+                   "Port down status: port-state=0x%x.\n",
+                   atomic_read(&fcport->state));
 
                if (atomic_read(&fcport->state) == FCS_ONLINE)
                        qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
@@ -1804,15 +1776,13 @@ check_scsi_status:
 
 out:
        if (logit)
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                   "scsi(%ld:%d:%d) FCP command status: 0x%x-0x%x (0x%x) "
-                   "portid=%02x%02x%02x oxid=0x%x cdb=%02x%02x%02x len=0x%x "
-                   "rsp_info=0x%x resid=0x%x fw_resid=0x%x\n", vha->host_no,
-                   cp->device->id, cp->device->lun, comp_status, scsi_status,
-                   cp->result, fcport->d_id.b.domain, fcport->d_id.b.area,
-                   fcport->d_id.b.al_pa, ox_id, cp->cmnd[0], cp->cmnd[1],
-                   cp->cmnd[2], scsi_bufflen(cp), rsp_info_len, resid_len,
-                   fw_resid_len));
+               ql_dbg(ql_dbg_io, vha, 0x3022,
+                   "FCP command status: 0x%x-0x%x (0x%x) "
+                   "oxid=0x%x cdb=%02x%02x%02x len=0x%x "
+                   "rsp_info=0x%x resid=0x%x fw_resid=0x%x.\n",
+                   comp_status, scsi_status, cp->result, ox_id, cp->cmnd[0],
+                   cp->cmnd[1], cp->cmnd[2], scsi_bufflen(cp), rsp_info_len,
+                   resid_len, fw_resid_len);
 
        if (rsp->status_srb == NULL)
                qla2x00_sp_compl(ha, sp);
@@ -1830,16 +1800,15 @@ qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
 {
        uint8_t         sense_sz = 0;
        struct qla_hw_data *ha = rsp->hw;
+       struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev);
        srb_t           *sp = rsp->status_srb;
        struct scsi_cmnd *cp;
 
        if (sp != NULL && sp->request_sense_length != 0) {
                cp = sp->cmd;
                if (cp == NULL) {
-                       DEBUG2(printk("%s(): Cmd already returned back to OS "
-                           "sp=%p.\n", __func__, sp));
-                       qla_printk(KERN_INFO, ha,
-                           "cmd is NULL: already returned to OS (sp=%p)\n",
+                       ql_log(ql_log_warn, vha, 0x3025,
+                           "cmd is NULL: already returned to OS (sp=%p).\n",
                            sp);
 
                        rsp->status_srb = NULL;
@@ -1856,7 +1825,8 @@ qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
                if (IS_FWI2_CAPABLE(ha))
                        host_to_fcp_swap(pkt->data, sizeof(pkt->data));
                memcpy(sp->request_sense_ptr, pkt->data, sense_sz);
-               DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz));
+               ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302c,
+                       sp->request_sense_ptr, sense_sz);
 
                sp->request_sense_ptr += sense_sz;
                sp->request_sense_length -= sense_sz;
@@ -1882,21 +1852,25 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
        uint32_t handle = LSW(pkt->handle);
        uint16_t que = MSW(pkt->handle);
        struct req_que *req = ha->req_q_map[que];
-#if defined(QL_DEBUG_LEVEL_2)
+
        if (pkt->entry_status & RF_INV_E_ORDER)
-               qla_printk(KERN_ERR, ha, "%s: Invalid Entry Order\n", __func__);
+               ql_dbg(ql_dbg_async, vha, 0x502a,
+                   "Invalid Entry Order.\n");
        else if (pkt->entry_status & RF_INV_E_COUNT)
-               qla_printk(KERN_ERR, ha, "%s: Invalid Entry Count\n", __func__);
+               ql_dbg(ql_dbg_async, vha, 0x502b,
+                   "Invalid Entry Count.\n");
        else if (pkt->entry_status & RF_INV_E_PARAM)
-               qla_printk(KERN_ERR, ha,
-                   "%s: Invalid Entry Parameter\n", __func__);
+               ql_dbg(ql_dbg_async, vha, 0x502c,
+                   "Invalid Entry Parameter.\n");
        else if (pkt->entry_status & RF_INV_E_TYPE)
-               qla_printk(KERN_ERR, ha, "%s: Invalid Entry Type\n", __func__);
+               ql_dbg(ql_dbg_async, vha, 0x502d,
+                   "Invalid Entry Type.\n");
        else if (pkt->entry_status & RF_BUSY)
-               qla_printk(KERN_ERR, ha, "%s: Busy\n", __func__);
+               ql_dbg(ql_dbg_async, vha, 0x502e,
+                   "Busy.\n");
        else
-               qla_printk(KERN_ERR, ha, "%s: UNKNOWN flag error\n", __func__);
-#endif
+               ql_dbg(ql_dbg_async, vha, 0x502f,
+                   "UNKNOWN flag error.\n");
 
        /* Validate handle. */
        if (handle < MAX_OUTSTANDING_COMMANDS)
@@ -1923,10 +1897,8 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
        } else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type ==
                COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7
                || pkt->entry_type == COMMAND_TYPE_6) {
-               DEBUG2(printk("scsi(%ld): Error entry - invalid handle\n",
-                       vha->host_no));
-               qla_printk(KERN_WARNING, ha,
-                       "Error entry - invalid handle\n");
+               ql_log(ql_log_warn, vha, 0x5030,
+                   "Error entry - invalid handle.\n");
 
                if (IS_QLA82XX(ha))
                        set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
@@ -1960,11 +1932,11 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
        }
 
        if (ha->mcp) {
-               DEBUG3(printk("%s(%ld): Got mailbox completion. cmd=%x.\n",
-                   __func__, vha->host_no, ha->mcp->mb[0]));
+               ql_dbg(ql_dbg_async, vha, 0x504d,
+                   "Got mailbox completion. cmd=%x.\n", ha->mcp->mb[0]);
        } else {
-               DEBUG2_3(printk("%s(%ld): MBX pointer ERROR!\n",
-                   __func__, vha->host_no));
+               ql_dbg(ql_dbg_async, vha, 0x504e,
+                   "MBX pointer ERROR.\n");
        }
 }
 
@@ -1993,8 +1965,8 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
                }
 
                if (pkt->entry_status != 0) {
-                       DEBUG3(printk(KERN_INFO
-                           "scsi(%ld): Process error entry.\n", vha->host_no));
+                       ql_dbg(ql_dbg_async, vha, 0x5029,
+                           "Process error entry.\n");
 
                        qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt);
                        ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
@@ -2030,10 +2002,10 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
                        break;
                default:
                        /* Type Not Supported. */
-                       DEBUG4(printk(KERN_WARNING
-                           "scsi(%ld): Received unknown response pkt type %x "
+                       ql_dbg(ql_dbg_async, vha, 0x5042,
+                           "Received unknown response pkt type %x "
                            "entry status=%x.\n",
-                           vha->host_no, pkt->entry_type, pkt->entry_status));
+                           pkt->entry_type, pkt->entry_status);
                        break;
                }
                ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
@@ -2088,7 +2060,8 @@ qla2xxx_check_risc_status(scsi_qla_host_t *vha)
 
 next_test:
        if (RD_REG_DWORD(&reg->iobase_c8) & BIT_3)
-               qla_printk(KERN_INFO, ha, "Additional code -- 0x55AA.\n");
+               ql_log(ql_log_info, vha, 0x504c,
+                   "Additional code -- 0x55AA.\n");
 
 done:
        WRT_REG_DWORD(&reg->iobase_window, 0x0000);
@@ -2121,7 +2094,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
        rsp = (struct rsp_que *) dev_id;
        if (!rsp) {
                printk(KERN_INFO
-                   "%s(): NULL response queue pointer\n", __func__);
+                   "%s(): NULL response queue pointer.\n", __func__);
                return IRQ_NONE;
        }
 
@@ -2142,8 +2115,9 @@ qla24xx_intr_handler(int irq, void *dev_id)
 
                        hccr = RD_REG_DWORD(&reg->hccr);
 
-                       qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
-                           "Dumping firmware!\n", hccr);
+                       ql_log(ql_log_warn, vha, 0x504b,
+                           "RISC paused -- HCCR=%x, Dumping firmware.\n",
+                           hccr);
 
                        qla2xxx_check_risc_status(vha);
 
@@ -2174,9 +2148,8 @@ qla24xx_intr_handler(int irq, void *dev_id)
                        qla24xx_process_response_queue(vha, rsp);
                        break;
                default:
-                       DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
-                           "(%d).\n",
-                           vha->host_no, stat & 0xff));
+                       ql_dbg(ql_dbg_async, vha, 0x504f,
+                           "Unrecognized interrupt type (%d).\n", stat * 0xff);
                        break;
                }
                WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
@@ -2205,7 +2178,7 @@ qla24xx_msix_rsp_q(int irq, void *dev_id)
        rsp = (struct rsp_que *) dev_id;
        if (!rsp) {
                printk(KERN_INFO
-               "%s(): NULL response queue pointer\n", __func__);
+               "%s(): NULL response queue pointer.\n", __func__);
                return IRQ_NONE;
        }
        ha = rsp->hw;
@@ -2235,7 +2208,7 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
        rsp = (struct rsp_que *) dev_id;
        if (!rsp) {
                printk(KERN_INFO
-                       "%s(): NULL response queue pointer\n", __func__);
+                       "%s(): NULL response queue pointer.\n", __func__);
                return IRQ_NONE;
        }
        ha = rsp->hw;
@@ -2268,8 +2241,8 @@ qla24xx_msix_default(int irq, void *dev_id)
 
        rsp = (struct rsp_que *) dev_id;
        if (!rsp) {
-               DEBUG(printk(
-               "%s(): NULL response queue pointer\n", __func__));
+               printk(KERN_INFO
+                       "%s(): NULL response queue pointer.\n", __func__);
                return IRQ_NONE;
        }
        ha = rsp->hw;
@@ -2286,8 +2259,9 @@ qla24xx_msix_default(int irq, void *dev_id)
 
                        hccr = RD_REG_DWORD(&reg->hccr);
 
-                       qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
-                           "Dumping firmware!\n", hccr);
+                       ql_log(ql_log_info, vha, 0x5050,
+                           "RISC paused -- HCCR=%x, Dumping firmware.\n",
+                           hccr);
 
                        qla2xxx_check_risc_status(vha);
 
@@ -2318,9 +2292,8 @@ qla24xx_msix_default(int irq, void *dev_id)
                        qla24xx_process_response_queue(vha, rsp);
                        break;
                default:
-                       DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
-                           "(%d).\n",
-                           vha->host_no, stat & 0xff));
+                       ql_dbg(ql_dbg_async, vha, 0x5051,
+                           "Unrecognized interrupt type (%d).\n", stat & 0xff);
                        break;
                }
                WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
@@ -2358,6 +2331,7 @@ qla24xx_disable_msix(struct qla_hw_data *ha)
 {
        int i;
        struct qla_msix_entry *qentry;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        for (i = 0; i < ha->msix_count; i++) {
                qentry = &ha->msix_entries[i];
@@ -2368,6 +2342,8 @@ qla24xx_disable_msix(struct qla_hw_data *ha)
        kfree(ha->msix_entries);
        ha->msix_entries = NULL;
        ha->flags.msix_enabled = 0;
+       ql_dbg(ql_dbg_init, vha, 0x0042,
+           "Disabled the MSI.\n");
 }
 
 static int
@@ -2377,11 +2353,15 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
        int i, ret;
        struct msix_entry *entries;
        struct qla_msix_entry *qentry;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        entries = kzalloc(sizeof(struct msix_entry) * ha->msix_count,
                        GFP_KERNEL);
-       if (!entries)
+       if (!entries) {
+               ql_log(ql_log_warn, vha, 0x00bc,
+                   "Failed to allocate memory for msix_entry.\n");
                return -ENOMEM;
+       }
 
        for (i = 0; i < ha->msix_count; i++)
                entries[i].entry = i;
@@ -2391,16 +2371,18 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
                if (ret < MIN_MSIX_COUNT)
                        goto msix_failed;
 
-               qla_printk(KERN_WARNING, ha,
-                       "MSI-X: Failed to enable support -- %d/%d\n"
-                       " Retry with %d vectors\n", ha->msix_count, ret, ret);
+               ql_log(ql_log_warn, vha, 0x00c6,
+                   "MSI-X: Failed to enable support "
+                   "-- %d/%d\n Retry with %d vectors.\n",
+                   ha->msix_count, ret, ret);
                ha->msix_count = ret;
                ret = pci_enable_msix(ha->pdev, entries, ha->msix_count);
                if (ret) {
 msix_failed:
-                       qla_printk(KERN_WARNING, ha, "MSI-X: Failed to enable"
-                               " support, giving up -- %d/%d\n",
-                               ha->msix_count, ret);
+                       ql_log(ql_log_fatal, vha, 0x00c7,
+                           "MSI-X: Failed to enable support, "
+                           "giving   up -- %d/%d.\n",
+                           ha->msix_count, ret);
                        goto msix_out;
                }
                ha->max_rsp_queues = ha->msix_count - 1;
@@ -2408,6 +2390,8 @@ msix_failed:
        ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) *
                                ha->msix_count, GFP_KERNEL);
        if (!ha->msix_entries) {
+               ql_log(ql_log_fatal, vha, 0x00c8,
+                   "Failed to allocate memory for ha->msix_entries.\n");
                ret = -ENOMEM;
                goto msix_out;
        }
@@ -2434,9 +2418,9 @@ msix_failed:
                                0, msix_entries[i].name, rsp);
                }
                if (ret) {
-                       qla_printk(KERN_WARNING, ha,
-                       "MSI-X: Unable to register handler -- %x/%d.\n",
-                       qentry->vector, ret);
+                       ql_log(ql_log_fatal, vha, 0x00cb,
+                           "MSI-X: unable to register handler -- %x/%d.\n",
+                           qentry->vector, ret);
                        qla24xx_disable_msix(ha);
                        ha->mqenable = 0;
                        goto msix_out;
@@ -2449,6 +2433,12 @@ msix_failed:
        /* Enable MSI-X vector for response queue update for queue 0 */
        if (ha->mqiobase &&  (ha->max_rsp_queues > 1 || ha->max_req_queues > 1))
                ha->mqenable = 1;
+       ql_dbg(ql_dbg_multiq, vha, 0xc005,
+           "mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n",
+           ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues);
+       ql_dbg(ql_dbg_init, vha, 0x0055,
+           "mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n",
+           ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues);
 
 msix_out:
        kfree(entries);
@@ -2460,6 +2450,7 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
 {
        int ret;
        device_reg_t __iomem *reg = ha->iobase;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        /* If possible, enable MSI-X. */
        if (!IS_QLA2432(ha) && !IS_QLA2532(ha) &&
@@ -2470,30 +2461,30 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
                (ha->pdev->subsystem_device == 0x7040 ||
                ha->pdev->subsystem_device == 0x7041 ||
                ha->pdev->subsystem_device == 0x1705)) {
-               DEBUG2(qla_printk(KERN_WARNING, ha,
-                       "MSI-X: Unsupported ISP2432 SSVID/SSDID (0x%X,0x%X).\n",
+               ql_log(ql_log_warn, vha, 0x0034,
+                   "MSI-X: Unsupported ISP 2432 SSVID/SSDID (0x%X,0x%X).\n",
                        ha->pdev->subsystem_vendor,
-                       ha->pdev->subsystem_device));
+                       ha->pdev->subsystem_device);
                goto skip_msi;
        }
 
        if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX ||
                !QLA_MSIX_FW_MODE_1(ha->fw_attributes))) {
-               DEBUG2(qla_printk(KERN_WARNING, ha,
-               "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n",
-                       ha->pdev->revision, ha->fw_attributes));
+               ql_log(ql_log_warn, vha, 0x0035,
+                   "MSI-X; Unsupported ISP2432 (0x%X, 0x%X).\n",
+                   ha->pdev->revision, ha->fw_attributes);
                goto skip_msix;
        }
 
        ret = qla24xx_enable_msix(ha, rsp);
        if (!ret) {
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                   "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision,
-                   ha->fw_attributes));
+               ql_dbg(ql_dbg_init, vha, 0x0036,
+                   "MSI-X: Enabled (0x%X, 0x%X).\n",
+                   ha->chip_revision, ha->fw_attributes);
                goto clear_risc_ints;
        }
-       qla_printk(KERN_WARNING, ha,
-           "MSI-X: Falling back-to MSI mode -- %d.\n", ret);
+       ql_log(ql_log_info, vha, 0x0037,
+           "MSI-X Falling back-to MSI mode -%d.\n", ret);
 skip_msix:
 
        if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
@@ -2502,18 +2493,19 @@ skip_msix:
 
        ret = pci_enable_msi(ha->pdev);
        if (!ret) {
-               DEBUG2(qla_printk(KERN_INFO, ha, "MSI: Enabled.\n"));
+               ql_dbg(ql_dbg_init, vha, 0x0038,
+                   "MSI: Enabled.\n");
                ha->flags.msi_enabled = 1;
        } else
-               qla_printk(KERN_WARNING, ha,
-                   "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
+               ql_log(ql_log_warn, vha, 0x0039,
+                   "MSI-X; Falling back-to INTa mode -- %d.\n", ret);
 skip_msi:
 
        ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
            ha->flags.msi_enabled ? 0 : IRQF_SHARED,
            QLA2XXX_DRIVER_NAME, rsp);
        if (ret) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x003a,
                    "Failed to reserve interrupt %d already in use.\n",
                    ha->pdev->irq);
                goto fail;
@@ -2563,13 +2555,14 @@ int qla25xx_request_irq(struct rsp_que *rsp)
        struct qla_hw_data *ha = rsp->hw;
        struct qla_init_msix_entry *intr = &msix_entries[2];
        struct qla_msix_entry *msix = rsp->msix;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
        int ret;
 
        ret = request_irq(msix->vector, intr->handler, 0, intr->name, rsp);
        if (ret) {
-               qla_printk(KERN_WARNING, ha,
-                       "MSI-X: Unable to register handler -- %x/%d.\n",
-                       msix->vector, ret);
+               ql_log(ql_log_fatal, vha, 0x00e6,
+                   "MSI-X: Unable to register handler -- %x/%d.\n",
+                   msix->vector, ret);
                return ret;
        }
        msix->have_irq = 1;
index c26f0ac..f7604ea 100644 (file)
@@ -46,14 +46,18 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        struct qla_hw_data *ha = vha->hw;
        scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
 
-       if (ha->pdev->error_state > pci_channel_io_frozen)
+       ql_dbg(ql_dbg_mbx, base_vha, 0x1000, "Entered %s.\n", __func__);
+
+       if (ha->pdev->error_state > pci_channel_io_frozen) {
+               ql_log(ql_log_warn, base_vha, 0x1001,
+                   "error_state is greater than pci_channel_io_frozen, "
+                   "exiting.\n");
                return QLA_FUNCTION_TIMEOUT;
+       }
 
        if (vha->device_flags & DFLG_DEV_FAILED) {
-               DEBUG2_3_11(qla_printk(KERN_WARNING, ha,
-                       "%s(%ld): Device in failed state, "
-                       "timeout MBX Exiting.\n",
-                       __func__, base_vha->host_no));
+               ql_log(ql_log_warn, base_vha, 0x1002,
+                   "Device in failed state, exiting.\n");
                return QLA_FUNCTION_TIMEOUT;
        }
 
@@ -63,17 +67,18 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        rval = QLA_SUCCESS;
        abort_active = test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, base_vha->host_no));
 
        if (ha->flags.pci_channel_io_perm_failure) {
-               DEBUG(printk("%s(%ld): Perm failure on EEH, timeout MBX "
-                            "Exiting.\n", __func__, vha->host_no));
+               ql_log(ql_log_warn, base_vha, 0x1003,
+                   "Perm failure on EEH timeout MBX, exiting.\n");
                return QLA_FUNCTION_TIMEOUT;
        }
 
        if (ha->flags.isp82xx_fw_hung) {
                /* Setting Link-Down error */
                mcp->mb[0] = MBS_LINK_DOWN_ERROR;
+               ql_log(ql_log_warn, base_vha, 0x1004,
+                   "FW hung = %d.\n", ha->flags.isp82xx_fw_hung);
                rval = QLA_FUNCTION_FAILED;
                goto premature_exit;
        }
@@ -85,8 +90,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
         */
        if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, mcp->tov * HZ)) {
                /* Timeout occurred. Return error. */
-               DEBUG2_3_11(printk("%s(%ld): cmd access timeout. "
-                   "Exiting.\n", __func__, base_vha->host_no));
+               ql_log(ql_log_warn, base_vha, 0x1005,
+                   "Cmd access timeout, Exiting.\n");
                return QLA_FUNCTION_TIMEOUT;
        }
 
@@ -94,8 +99,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        /* Save mailbox command for debug */
        ha->mcp = mcp;
 
-       DEBUG11(printk("scsi(%ld): prepare to issue mbox cmd=0x%x.\n",
-           base_vha->host_no, mcp->mb[0]));
+       ql_dbg(ql_dbg_mbx, base_vha, 0x1006,
+           "Prepare to issue mbox cmd=0x%x.\n", mcp->mb[0]);
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
 
@@ -123,27 +128,30 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                iptr++;
        }
 
-#if defined(QL_DEBUG_LEVEL_1)
-       printk("%s(%ld): Loaded MBX registers (displayed in bytes) = \n",
-           __func__, base_vha->host_no);
-       qla2x00_dump_buffer((uint8_t *)mcp->mb, 16);
-       printk("\n");
-       qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x10), 16);
-       printk("\n");
-       qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x20), 8);
-       printk("\n");
-       printk("%s(%ld): I/O address = %p.\n", __func__, base_vha->host_no,
-               optr);
-       qla2x00_dump_regs(base_vha);
-#endif
+       ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1111,
+           "Loaded MBX registers (displayed in bytes) =.\n");
+       ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1112,
+           (uint8_t *)mcp->mb, 16);
+       ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1113,
+           ".\n");
+       ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1114,
+           ((uint8_t *)mcp->mb + 0x10), 16);
+       ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1115,
+           ".\n");
+       ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1116,
+           ((uint8_t *)mcp->mb + 0x20), 8);
+       ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1117,
+           "I/O Address = %p.\n", optr);
+       ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x100e);
 
        /* Issue set host interrupt command to send cmd out. */
        ha->flags.mbox_int = 0;
        clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 
        /* Unlock mbx registers and wait for interrupt */
-       DEBUG11(printk("%s(%ld): going to unlock irq & waiting for interrupt. "
-           "jiffies=%lx.\n", __func__, base_vha->host_no, jiffies));
+       ql_dbg(ql_dbg_mbx, base_vha, 0x100f,
+           "Going to unlock irq & waiting for interrupts. "
+           "jiffies=%lx.\n", jiffies);
 
        /* Wait for mbx cmd completion until timeout */
 
@@ -155,9 +163,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                                HINT_MBX_INT_PENDING) {
                                spin_unlock_irqrestore(&ha->hardware_lock,
                                        flags);
-                               DEBUG2_3_11(printk(KERN_INFO
-                                   "%s(%ld): Pending Mailbox timeout. "
-                                   "Exiting.\n", __func__, base_vha->host_no));
+                               ql_dbg(ql_dbg_mbx, base_vha, 0x1010,
+                                   "Pending mailbox timeout, exiting.\n");
                                rval = QLA_FUNCTION_TIMEOUT;
                                goto premature_exit;
                        }
@@ -173,17 +180,16 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
 
        } else {
-               DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__,
-                   base_vha->host_no, command));
+               ql_dbg(ql_dbg_mbx, base_vha, 0x1011,
+                   "Cmd=%x Polling Mode.\n", command);
 
                if (IS_QLA82XX(ha)) {
                        if (RD_REG_DWORD(&reg->isp82.hint) &
                                HINT_MBX_INT_PENDING) {
                                spin_unlock_irqrestore(&ha->hardware_lock,
                                        flags);
-                               DEBUG2_3_11(printk(KERN_INFO
-                                   "%s(%ld): Pending Mailbox timeout. "
-                                   "Exiting.\n", __func__, base_vha->host_no));
+                               ql_dbg(ql_dbg_mbx, base_vha, 0x1012,
+                                   "Pending mailbox timeout, exiting.\n");
                                rval = QLA_FUNCTION_TIMEOUT;
                                goto premature_exit;
                        }
@@ -207,17 +213,17 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                            command == MBC_LOAD_RISC_RAM_EXTENDED))
                                msleep(10);
                } /* while */
-               DEBUG17(qla_printk(KERN_WARNING, ha,
-                       "Waited %d sec\n",
-                       (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ)));
+               ql_dbg(ql_dbg_mbx, base_vha, 0x1013,
+                   "Waited %d sec.\n",
+                   (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ));
        }
 
        /* Check whether we timed out */
        if (ha->flags.mbox_int) {
                uint16_t *iptr2;
 
-               DEBUG3_11(printk("%s(%ld): cmd %x completed.\n", __func__,
-                   base_vha->host_no, command));
+               ql_dbg(ql_dbg_mbx, base_vha, 0x1014,
+                   "Cmd=%x completed.\n", command);
 
                /* Got interrupt. Clear the flag. */
                ha->flags.mbox_int = 0;
@@ -229,6 +235,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                        mcp->mb[0] = MBS_LINK_DOWN_ERROR;
                        ha->mcp = NULL;
                        rval = QLA_FUNCTION_FAILED;
+                       ql_log(ql_log_warn, base_vha, 0x1015,
+                           "FW hung = %d.\n", ha->flags.isp82xx_fw_hung);
                        goto premature_exit;
                }
 
@@ -249,8 +257,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                }
        } else {
 
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) || \
-               defined(QL_DEBUG_LEVEL_11)
                uint16_t mb0;
                uint32_t ictrl;
 
@@ -261,14 +267,13 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                        mb0 = RD_MAILBOX_REG(ha, &reg->isp, 0);
                        ictrl = RD_REG_WORD(&reg->isp.ictrl);
                }
-               printk("%s(%ld): **** MB Command Timeout for cmd %x ****\n",
-                   __func__, base_vha->host_no, command);
-               printk("%s(%ld): icontrol=%x jiffies=%lx\n", __func__,
-                   base_vha->host_no, ictrl, jiffies);
-               printk("%s(%ld): *** mailbox[0] = 0x%x ***\n", __func__,
-                   base_vha->host_no, mb0);
-               qla2x00_dump_regs(base_vha);
-#endif
+               ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1119,
+                   "MBX Command timeout for cmd %x.\n", command);
+               ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x111a,
+                   "iocontrol=%x jiffies=%lx.\n", ictrl, jiffies);
+               ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x111b,
+                   "mb[0] = 0x%x.\n", mb0);
+               ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1019);
 
                rval = QLA_FUNCTION_TIMEOUT;
        }
@@ -279,8 +284,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        ha->mcp = NULL;
 
        if ((abort_active || !io_lock_on) && !IS_NOPOLLING_TYPE(ha)) {
-               DEBUG11(printk("%s(%ld): checking for additional resp "
-                   "interrupt.\n", __func__, base_vha->host_no));
+               ql_dbg(ql_dbg_mbx, base_vha, 0x101a,
+                   "Checking for additional resp interrupt.\n");
 
                /* polling mode for non isp_abort commands. */
                qla2x00_poll(ha->rsp_q_map[0]);
@@ -291,38 +296,32 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                if (!io_lock_on || (mcp->flags & IOCTL_CMD) ||
                    ha->flags.eeh_busy) {
                        /* not in dpc. schedule it for dpc to take over. */
-                       DEBUG(printk("%s(%ld): timeout schedule "
-                       "isp_abort_needed.\n", __func__,
-                       base_vha->host_no));
-                       DEBUG2_3_11(printk("%s(%ld): timeout schedule "
-                       "isp_abort_needed.\n", __func__,
-                       base_vha->host_no));
+                       ql_dbg(ql_dbg_mbx, base_vha, 0x101b,
+                           "Timeout, schedule isp_abort_needed.\n");
 
                        if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
                            !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
                            !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
 
-                               qla_printk(KERN_WARNING, ha,
-                                   "Mailbox command timeout occurred. "
-                                   "Scheduling ISP " "abort. eeh_busy: 0x%x\n",
-                                   ha->flags.eeh_busy);
+                               ql_log(ql_log_info, base_vha, 0x101c,
+                                   "Mailbox cmd timeout occured. "
+                                   "Scheduling ISP abort eeh_busy=0x%x.\n",
+                                       ha->flags.eeh_busy);
                                set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
                                qla2xxx_wake_dpc(vha);
                        }
                } else if (!abort_active) {
                        /* call abort directly since we are in the DPC thread */
-                       DEBUG(printk("%s(%ld): timeout calling abort_isp\n",
-                           __func__, base_vha->host_no));
-                       DEBUG2_3_11(printk("%s(%ld): timeout calling "
-                           "abort_isp\n", __func__, base_vha->host_no));
+                       ql_dbg(ql_dbg_mbx, base_vha, 0x101d,
+                           "Timeout, calling abort_isp.\n");
 
                        if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
                            !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
                            !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
 
-                               qla_printk(KERN_WARNING, ha,
-                                   "Mailbox command timeout occurred. "
-                                   "Issuing ISP abort.\n");
+                               ql_log(ql_log_info, base_vha, 0x101e,
+                                   "Mailbox cmd timeout occured. "
+                                   "Scheduling ISP abort.\n");
 
                                set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
                                clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
@@ -332,11 +331,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                                            &vha->dpc_flags);
                                }
                                clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
-                               DEBUG(printk("%s(%ld): finished abort_isp\n",
-                                   __func__, vha->host_no));
-                               DEBUG2_3_11(printk(
-                                   "%s(%ld): finished abort_isp\n",
-                                   __func__, vha->host_no));
+                               ql_dbg(ql_dbg_mbx, base_vha, 0x101f,
+                                   "Finished abort_isp.\n");
                        }
                }
        }
@@ -346,12 +342,11 @@ premature_exit:
        complete(&ha->mbx_cmd_comp);
 
        if (rval) {
-               DEBUG2_3_11(printk("%s(%ld): **** FAILED. mbx0=%x, mbx1=%x, "
-                   "mbx2=%x, cmd=%x ****\n", __func__, base_vha->host_no,
-                   mcp->mb[0], mcp->mb[1], mcp->mb[2], command));
+               ql_dbg(ql_dbg_mbx, base_vha, 0x1020,
+                   "**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, cmd=%x ****.\n",
+                   mcp->mb[0], mcp->mb[1], mcp->mb[2], command);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__,
-               base_vha->host_no));
+               ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -366,7 +361,7 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1022, "Entered %s.\n", __func__);
 
        if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha)) {
                mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
@@ -397,10 +392,10 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
-                   vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1023,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1024, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -430,7 +425,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1025, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_EXECUTE_FIRMWARE;
        mcp->out_mb = MBX_0;
@@ -461,15 +456,14 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
-                   vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1026,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
                if (IS_FWI2_CAPABLE(ha)) {
-                       DEBUG11(printk("%s(%ld): done exchanges=%x.\n",
-                           __func__, vha->host_no, mcp->mb[1]));
+                       ql_dbg(ql_dbg_mbx, vha, 0x1027,
+                           "Done exchanges=%x.\n", mcp->mb[1]);
                } else {
-                       DEBUG11(printk("%s(%ld): done.\n", __func__,
-                           vha->host_no));
+                       ql_dbg(ql_dbg_mbx, vha, 0x1028, "Done %s.\n", __func__);
                }
        }
 
@@ -501,7 +495,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
        mbx_cmd_t       mc;
        mbx_cmd_t       *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1029, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_GET_FIRMWARE_VERSION;
        mcp->out_mb = MBX_0;
@@ -535,11 +529,10 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
 failed:
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x102a, "Failed=%x.\n", rval);
        } else {
                /*EMPTY*/
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x102b, "Done %s.\n", __func__);
        }
        return rval;
 }
@@ -565,7 +558,7 @@ qla2x00_get_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x102c, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_GET_FIRMWARE_OPTION;
        mcp->out_mb = MBX_0;
@@ -576,15 +569,14 @@ qla2x00_get_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x102d, "Failed=%x.\n", rval);
        } else {
                fwopts[0] = mcp->mb[0];
                fwopts[1] = mcp->mb[1];
                fwopts[2] = mcp->mb[2];
                fwopts[3] = mcp->mb[3];
 
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x102e, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -612,7 +604,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x102f, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_SET_FIRMWARE_OPTION;
        mcp->mb[1] = fwopts[1];
@@ -636,11 +628,11 @@ qla2x00_set_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("%s(%ld): failed=%x (%x/%x).\n", __func__,
-                   vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1030,
+                   "Failed=%x (%x/%x).\n", rval, mcp->mb[0], mcp->mb[1]);
        } else {
                /*EMPTY*/
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1031, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -668,7 +660,7 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("qla2x00_mbx_reg_test(%ld): entered.\n", vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1032, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST;
        mcp->mb[1] = 0xAAAA;
@@ -695,12 +687,10 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha)
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("qla2x00_mbx_reg_test(%ld): failed=%x.\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x1033, "Failed=%x.\n", rval);
        } else {
                /*EMPTY*/
-               DEBUG11(printk("qla2x00_mbx_reg_test(%ld): done.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1034, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -728,7 +718,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1035, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_VERIFY_CHECKSUM;
        mcp->out_mb = MBX_0;
@@ -749,11 +739,11 @@ qla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__,
-                   vha->host_no, rval, IS_FWI2_CAPABLE(vha->hw) ?
-                   (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1036,
+                   "Failed=%x chm sum=%x.\n", rval, IS_FWI2_CAPABLE(vha->hw) ?
+                   (mcp->mb[2] << 16) | mcp->mb[1] : mcp->mb[1]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1037, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -785,6 +775,8 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer,
        mbx_cmd_t       mc;
        mbx_cmd_t       *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x1038, "Entered %s.\n", __func__);
+
        mcp->mb[0] = MBC_IOCB_COMMAND_A64;
        mcp->mb[1] = 0;
        mcp->mb[2] = MSW(phys_addr);
@@ -799,14 +791,14 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer,
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x1039, "Failed=%x.\n", rval);
        } else {
                sts_entry_t *sts_entry = (sts_entry_t *) buffer;
 
                /* Mask reserved bits. */
                sts_entry->entry_status &=
                    IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK;
+               ql_dbg(ql_dbg_mbx, vha, 0x103a, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -847,7 +839,7 @@ qla2x00_abort_command(srb_t *sp)
        struct qla_hw_data *ha = vha->hw;
        struct req_que *req = vha->req;
 
-       DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x103b, "Entered %s.\n", __func__);
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
        for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
@@ -876,11 +868,9 @@ qla2x00_abort_command(srb_t *sp)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("qla2x00_abort_command(%ld): failed=%x.\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x103c, "Failed=%x.\n", rval);
        } else {
-               DEBUG11(printk("qla2x00_abort_command(%ld): done.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x103d, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -896,10 +886,11 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag)
        struct req_que *req;
        struct rsp_que *rsp;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no));
-
        l = l;
        vha = fcport->vha;
+
+       ql_dbg(ql_dbg_mbx, vha, 0x103e, "Entered %s.\n", __func__);
+
        req = vha->hw->req_q_map[0];
        rsp = req->rsp;
        mcp->mb[0] = MBC_ABORT_TARGET;
@@ -919,18 +910,17 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag)
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(vha, mcp);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x103f, "Failed=%x.\n", rval);
        }
 
        /* Issue marker IOCB. */
        rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, 0,
                                                        MK_SYNC_ID);
        if (rval2 != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
-                   "(%x).\n", __func__, vha->host_no, rval2));
+               ql_dbg(ql_dbg_mbx, vha, 0x1040,
+                   "Failed to issue marker IOCB (%x).\n", rval2);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1041, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -946,9 +936,10 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
        struct req_que *req;
        struct rsp_que *rsp;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no));
-
        vha = fcport->vha;
+
+       ql_dbg(ql_dbg_mbx, vha, 0x1042, "Entered %s.\n", __func__);
+
        req = vha->hw->req_q_map[0];
        rsp = req->rsp;
        mcp->mb[0] = MBC_LUN_RESET;
@@ -966,18 +957,17 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(vha, mcp);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x1043, "Failed=%x.\n", rval);
        }
 
        /* Issue marker IOCB. */
        rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, l,
                                                                MK_SYNC_ID_LUN);
        if (rval2 != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
-                   "(%x).\n", __func__, vha->host_no, rval2));
+               ql_dbg(ql_dbg_mbx, vha, 0x1044,
+                   "Failed to issue marker IOCB (%x).\n", rval2);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1045, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -1011,8 +1001,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("qla2x00_get_adapter_id(%ld): entered.\n",
-           vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1046, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID;
        mcp->mb[9] = vha->vp_idx;
@@ -1038,11 +1027,9 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("qla2x00_get_adapter_id(%ld): failed=%x.\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x1047, "Failed=%x.\n", rval);
        } else {
-               DEBUG11(printk("qla2x00_get_adapter_id(%ld): done.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1048, "Done %s.\n", __func__);
 
                if (IS_QLA8XXX_TYPE(vha->hw)) {
                        vha->fcoe_vlan_id = mcp->mb[9] & 0xfff;
@@ -1083,8 +1070,7 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("qla2x00_get_retry_cnt(%ld): entered.\n",
-                       vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1049, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_GET_RETRY_COUNT;
        mcp->out_mb = MBX_0;
@@ -1095,8 +1081,8 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov,
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("qla2x00_get_retry_cnt(%ld): failed = %x.\n",
-                   vha->host_no, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x104a,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
                /* Convert returned data and check our values. */
                *r_a_tov = mcp->mb[3] / 2;
@@ -1107,8 +1093,8 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov,
                        *tov = ratov;
                }
 
-               DEBUG11(printk("qla2x00_get_retry_cnt(%ld): done. mb3=%d "
-                   "ratov=%d.\n", vha->host_no, mcp->mb[3], ratov));
+               ql_dbg(ql_dbg_mbx, vha, 0x104b,
+                   "Done %s mb3=%d ratov=%d.\n", __func__, mcp->mb[3], ratov);
        }
 
        return rval;
@@ -1139,8 +1125,7 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
        mbx_cmd_t *mcp = &mc;
        struct qla_hw_data *ha = vha->hw;
 
-       DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n",
-           vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x104c, "Entered %s.\n", __func__);
 
        if (IS_QLA82XX(ha) && ql2xdbwr)
                qla82xx_wr_32(ha, ha->nxdb_wr_ptr,
@@ -1174,13 +1159,11 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("qla2x00_init_firmware(%ld): failed=%x "
-                   "mb0=%x.\n",
-                   vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x104d,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
                /*EMPTY*/
-               DEBUG11(printk("qla2x00_init_firmware(%ld): done.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x104e, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -1213,13 +1196,13 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
        dma_addr_t pd_dma;
        struct qla_hw_data *ha = vha->hw;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x104f, "Entered %s.\n", __func__);
 
        pd24 = NULL;
        pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
        if (pd  == NULL) {
-               DEBUG2_3(printk("%s(%ld): failed to allocate Port Database "
-                   "structure.\n", __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x1050,
+                   "Failed to allocate port database structure.\n");
                return QLA_MEMORY_ALLOC_FAILED;
        }
        memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
@@ -1261,12 +1244,10 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
                /* Check for logged in state. */
                if (pd24->current_login_state != PDS_PRLI_COMPLETE &&
                    pd24->last_login_state != PDS_PRLI_COMPLETE) {
-                       DEBUG2(qla_printk(KERN_WARNING, ha,
-                          "scsi(%ld): Unable to verify login-state (%x/%x) "
-                          " - portid=%02x%02x%02x.\n", vha->host_no,
-                          pd24->current_login_state, pd24->last_login_state,
-                          fcport->d_id.b.domain, fcport->d_id.b.area,
-                          fcport->d_id.b.al_pa));
+                       ql_dbg(ql_dbg_mbx, vha, 0x1051,
+                           "Unable to verify login-state (%x/%x) for "
+                           "loop_id %x.\n", pd24->current_login_state,
+                           pd24->last_login_state, fcport->loop_id);
                        rval = QLA_FUNCTION_FAILED;
                        goto gpd_error_out;
                }
@@ -1290,12 +1271,11 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
                /* Check for logged in state. */
                if (pd->master_state != PD_STATE_PORT_LOGGED_IN &&
                    pd->slave_state != PD_STATE_PORT_LOGGED_IN) {
-                       DEBUG2(qla_printk(KERN_WARNING, ha,
-                          "scsi(%ld): Unable to verify login-state (%x/%x) "
-                          " - portid=%02x%02x%02x.\n", vha->host_no,
-                          pd->master_state, pd->slave_state,
-                          fcport->d_id.b.domain, fcport->d_id.b.area,
-                          fcport->d_id.b.al_pa));
+                       ql_dbg(ql_dbg_mbx, vha, 0x100a,
+                           "Unable to verify login-state (%x/%x) - "
+                           "portid=%02x%02x%02x.\n", pd->master_state,
+                           pd->slave_state, fcport->d_id.b.domain,
+                           fcport->d_id.b.area, fcport->d_id.b.al_pa);
                        rval = QLA_FUNCTION_FAILED;
                        goto gpd_error_out;
                }
@@ -1325,10 +1305,11 @@ gpd_error_out:
        dma_pool_free(ha->s_dma_pool, pd, pd_dma);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
-                   __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1052,
+                   "Failed=%x mb[0]=%x mb[1]=%x.\n", rval,
+                   mcp->mb[0], mcp->mb[1]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1053, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -1357,8 +1338,7 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("qla2x00_get_firmware_state(%ld): entered.\n",
-           vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1054, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
        mcp->out_mb = MBX_0;
@@ -1381,12 +1361,10 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("qla2x00_get_firmware_state(%ld): "
-                   "failed=%x.\n", vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval);
        } else {
                /*EMPTY*/
-               DEBUG11(printk("qla2x00_get_firmware_state(%ld): done.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1056, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -1418,8 +1396,7 @@ qla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("qla2x00_get_port_name(%ld): entered.\n",
-           vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1057, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_GET_PORT_NAME;
        mcp->mb[9] = vha->vp_idx;
@@ -1439,8 +1416,7 @@ qla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name,
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("qla2x00_get_port_name(%ld): failed=%x.\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x1058, "Failed=%x.\n", rval);
        } else {
                if (name != NULL) {
                        /* This function returns name in big endian. */
@@ -1454,8 +1430,7 @@ qla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name,
                        name[7] = LSB(mcp->mb[7]);
                }
 
-               DEBUG11(printk("qla2x00_get_port_name(%ld): done.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1059, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -1483,7 +1458,7 @@ qla2x00_lip_reset(scsi_qla_host_t *vha)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x105a, "Entered %s.\n", __func__);
 
        if (IS_QLA8XXX_TYPE(vha->hw)) {
                /* Logout across all FCFs. */
@@ -1517,11 +1492,10 @@ qla2x00_lip_reset(scsi_qla_host_t *vha)
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n",
-                   __func__, vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x105b, "Failed=%x.\n", rval);
        } else {
                /*EMPTY*/
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x105c, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -1553,12 +1527,11 @@ qla2x00_send_sns(scsi_qla_host_t *vha, dma_addr_t sns_phys_address,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("qla2x00_send_sns(%ld): entered.\n",
-           vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x105d, "Entered %s.\n", __func__);
 
-       DEBUG11(printk("qla2x00_send_sns: retry cnt=%d ratov=%d total "
-               "tov=%d.\n", vha->hw->retry_count, vha->hw->login_timeout,
-               mcp->tov));
+       ql_dbg(ql_dbg_mbx, vha, 0x105e,
+           "Retry cnt=%d ratov=%d total tov=%d.\n",
+           vha->hw->retry_count, vha->hw->login_timeout, mcp->tov);
 
        mcp->mb[0] = MBC_SEND_SNS_COMMAND;
        mcp->mb[1] = cmd_size;
@@ -1575,13 +1548,12 @@ qla2x00_send_sns(scsi_qla_host_t *vha, dma_addr_t sns_phys_address,
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x "
-                   "mb[1]=%x.\n", vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
-               DEBUG2_3_11(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x "
-                   "mb[1]=%x.\n", vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x105f,
+                   "Failed=%x mb[0]=%x mb[1]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1]);
        } else {
                /*EMPTY*/
-               DEBUG11(printk("qla2x00_send_sns(%ld): done.\n", vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1060, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -1600,7 +1572,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
        struct req_que *req;
        struct rsp_que *rsp;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1061, "Entered %s.\n", __func__);
 
        if (ha->flags.cpu_affinity_enabled)
                req = ha->req_q_map[0];
@@ -1610,8 +1582,8 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
 
        lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
        if (lg == NULL) {
-               DEBUG2_3(printk("%s(%ld): failed to allocate Login IOCB.\n",
-                   __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x1062,
+                   "Failed to allocate login IOCB.\n");
                return QLA_MEMORY_ALLOC_FAILED;
        }
        memset(lg, 0, sizeof(struct logio_entry_24xx));
@@ -1631,21 +1603,21 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
        lg->vp_index = vha->vp_idx;
        rval = qla2x00_issue_iocb(vha, lg, lg_dma, 0);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB "
-                   "(%x).\n", __func__, vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x1063,
+                   "Failed to issue login IOCB (%x).\n", rval);
        } else if (lg->entry_status != 0) {
-               DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-                   "-- error status (%x).\n", __func__, vha->host_no,
-                   lg->entry_status));
+               ql_dbg(ql_dbg_mbx, vha, 0x1064,
+                   "Failed to complete IOCB -- error status (%x).\n",
+                   lg->entry_status);
                rval = QLA_FUNCTION_FAILED;
        } else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
                iop[0] = le32_to_cpu(lg->io_parameter[0]);
                iop[1] = le32_to_cpu(lg->io_parameter[1]);
 
-               DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-                   "-- completion status (%x)  ioparam=%x/%x.\n", __func__,
-                   vha->host_no, le16_to_cpu(lg->comp_status), iop[0],
-                   iop[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1065,
+                   "Failed to complete IOCB -- completion  status (%x) "
+                   "ioparam=%x/%x.\n", le16_to_cpu(lg->comp_status),
+                   iop[0], iop[1]);
 
                switch (iop[0]) {
                case LSC_SCODE_PORTID_USED:
@@ -1673,7 +1645,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
                        break;
                }
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1066, "Done %s.\n", __func__);
 
                iop[0] = le32_to_cpu(lg->io_parameter[0]);
 
@@ -1728,7 +1700,7 @@ qla2x00_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
        mbx_cmd_t *mcp = &mc;
        struct qla_hw_data *ha = vha->hw;
 
-       DEBUG11(printk("qla2x00_login_fabric(%ld): entered.\n", vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1067, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_LOGIN_FABRIC_PORT;
        mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
@@ -1771,13 +1743,12 @@ qla2x00_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
                        rval = QLA_SUCCESS;
 
                /*EMPTY*/
-               DEBUG2_3_11(printk("qla2x00_login_fabric(%ld): failed=%x "
-                   "mb[0]=%x mb[1]=%x mb[2]=%x.\n", vha->host_no, rval,
-                   mcp->mb[0], mcp->mb[1], mcp->mb[2]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1068,
+                   "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
        } else {
                /*EMPTY*/
-               DEBUG11(printk("qla2x00_login_fabric(%ld): done.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1069, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -1808,13 +1779,13 @@ qla2x00_login_local_device(scsi_qla_host_t *vha, fc_port_t *fcport,
        mbx_cmd_t *mcp = &mc;
        struct qla_hw_data *ha = vha->hw;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x106a, "Entered %s.\n", __func__);
+
        if (IS_FWI2_CAPABLE(ha))
                return qla24xx_login_fabric(vha, fcport->loop_id,
                    fcport->d_id.b.domain, fcport->d_id.b.area,
                    fcport->d_id.b.al_pa, mb_ret, opt);
 
-       DEBUG3(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_LOGIN_LOOP_PORT;
        if (HAS_EXTENDED_IDS(ha))
                mcp->mb[1] = fcport->loop_id;
@@ -1845,15 +1816,12 @@ qla2x00_login_local_device(scsi_qla_host_t *vha, fc_port_t *fcport,
                if (mcp->mb[0] == 0x4005 || mcp->mb[0] == 0x4006)
                        rval = QLA_SUCCESS;
 
-               DEBUG(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
-                   "mb[6]=%x mb[7]=%x.\n", __func__, vha->host_no, rval,
-                   mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]));
-               DEBUG2_3(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
-                   "mb[6]=%x mb[7]=%x.\n", __func__, vha->host_no, rval,
-                   mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]));
+               ql_dbg(ql_dbg_mbx, vha, 0x106b,
+                   "Failed=%x mb[0]=%x mb[1]=%x mb[6]=%x mb[7]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]);
        } else {
                /*EMPTY*/
-               DEBUG3(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x106c, "Done %s.\n", __func__);
        }
 
        return (rval);
@@ -1870,12 +1838,12 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
        struct req_que *req;
        struct rsp_que *rsp;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x106d, "Entered %s.\n", __func__);
 
        lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
        if (lg == NULL) {
-               DEBUG2_3(printk("%s(%ld): failed to allocate Logout IOCB.\n",
-                   __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x106e,
+                   "Failed to allocate logout IOCB.\n");
                return QLA_MEMORY_ALLOC_FAILED;
        }
        memset(lg, 0, sizeof(struct logio_entry_24xx));
@@ -1899,22 +1867,22 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
 
        rval = qla2x00_issue_iocb(vha, lg, lg_dma, 0);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB "
-                   "(%x).\n", __func__, vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x106f,
+                   "Failed to issue logout IOCB (%x).\n", rval);
        } else if (lg->entry_status != 0) {
-               DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-                   "-- error status (%x).\n", __func__, vha->host_no,
-                   lg->entry_status));
+               ql_dbg(ql_dbg_mbx, vha, 0x1070,
+                   "Failed to complete IOCB -- error status (%x).\n",
+                   lg->entry_status);
                rval = QLA_FUNCTION_FAILED;
        } else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
-               DEBUG2_3_11(printk("%s(%ld %d): failed to complete IOCB "
-                   "-- completion status (%x)  ioparam=%x/%x.\n", __func__,
-                   vha->host_no, vha->vp_idx, le16_to_cpu(lg->comp_status),
+               ql_dbg(ql_dbg_mbx, vha, 0x1071,
+                   "Failed to complete IOCB -- completion status (%x) "
+                   "ioparam=%x/%x.\n", le16_to_cpu(lg->comp_status),
                    le32_to_cpu(lg->io_parameter[0]),
-                   le32_to_cpu(lg->io_parameter[1])));
+                   le32_to_cpu(lg->io_parameter[1]));
        } else {
                /*EMPTY*/
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1072, "Done %s.\n", __func__);
        }
 
        dma_pool_free(ha->s_dma_pool, lg, lg_dma);
@@ -1946,8 +1914,7 @@ qla2x00_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("qla2x00_fabric_logout(%ld): entered.\n",
-           vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1073, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT;
        mcp->out_mb = MBX_1|MBX_0;
@@ -1966,12 +1933,11 @@ qla2x00_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("qla2x00_fabric_logout(%ld): failed=%x "
-                   "mbx1=%x.\n", vha->host_no, rval, mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1074,
+                   "Failed=%x mb[1]=%x.\n", rval, mcp->mb[1]);
        } else {
                /*EMPTY*/
-               DEBUG11(printk("qla2x00_fabric_logout(%ld): done.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1075, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -1999,8 +1965,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *vha)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("qla2x00_full_login_lip(%ld): entered.\n",
-           vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1076, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_LIP_FULL_LOGIN;
        mcp->mb[1] = IS_FWI2_CAPABLE(vha->hw) ? BIT_3 : 0;
@@ -2014,12 +1979,10 @@ qla2x00_full_login_lip(scsi_qla_host_t *vha)
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("qla2x00_full_login_lip(%ld): failed=%x.\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x1077, "Failed=%x.\n", rval);
        } else {
                /*EMPTY*/
-               DEBUG11(printk("qla2x00_full_login_lip(%ld): done.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1078, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -2045,8 +2008,7 @@ qla2x00_get_id_list(scsi_qla_host_t *vha, void *id_list, dma_addr_t id_list_dma,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("qla2x00_get_id_list(%ld): entered.\n",
-           vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1079, "Entered %s.\n", __func__);
 
        if (id_list == NULL)
                return QLA_FUNCTION_FAILED;
@@ -2075,12 +2037,10 @@ qla2x00_get_id_list(scsi_qla_host_t *vha, void *id_list, dma_addr_t id_list_dma,
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("qla2x00_get_id_list(%ld): failed=%x.\n",
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x107a, "Failed=%x.\n", rval);
        } else {
                *entries = mcp->mb[1];
-               DEBUG11(printk("qla2x00_get_id_list(%ld): done.\n",
-                   vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x107b, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -2108,7 +2068,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x107c, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
        mcp->out_mb = MBX_0;
@@ -2121,14 +2081,14 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt,
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("%s(%ld): failed = %x.\n", __func__,
-                   vha->host_no, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x107d,
+                   "Failed mb[0]=%x.\n", mcp->mb[0]);
        } else {
-               DEBUG11(printk("%s(%ld): done. mb1=%x mb2=%x mb3=%x mb6=%x "
-                   "mb7=%x mb10=%x mb11=%x mb12=%x.\n", __func__,
-                   vha->host_no, mcp->mb[1], mcp->mb[2], mcp->mb[3],
-                   mcp->mb[6], mcp->mb[7], mcp->mb[10], mcp->mb[11],
-                   mcp->mb[12]));
+               ql_dbg(ql_dbg_mbx, vha, 0x107e,
+                   "Done %s mb1=%x mb2=%x mb3=%x mb6=%x mb7=%x mb10=%x "
+                   "mb11=%x mb12=%x.\n", __func__, mcp->mb[1], mcp->mb[2],
+                   mcp->mb[3], mcp->mb[6], mcp->mb[7], mcp->mb[10],
+                   mcp->mb[11], mcp->mb[12]);
 
                if (cur_xchg_cnt)
                        *cur_xchg_cnt = mcp->mb[3];
@@ -2147,7 +2107,6 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt,
        return (rval);
 }
 
-#if defined(QL_DEBUG_LEVEL_3)
 /*
  * qla2x00_get_fcal_position_map
  *     Get FCAL (LILP) position map using mailbox command
@@ -2172,10 +2131,12 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
        dma_addr_t pmap_dma;
        struct qla_hw_data *ha = vha->hw;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x107f, "Entered %s.\n", __func__);
+
        pmap = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma);
        if (pmap  == NULL) {
-               DEBUG2_3_11(printk("%s(%ld): **** Mem Alloc Failed ****",
-                   __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x1080,
+                   "Memory alloc failed.\n");
                return QLA_MEMORY_ALLOC_FAILED;
        }
        memset(pmap, 0, FCAL_MAP_SIZE);
@@ -2193,10 +2154,11 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval == QLA_SUCCESS) {
-               DEBUG11(printk("%s(%ld): (mb0=%x/mb1=%x) FC/AL Position Map "
-                   "size (%x)\n", __func__, vha->host_no, mcp->mb[0],
-                   mcp->mb[1], (unsigned)pmap[0]));
-               DEBUG11(qla2x00_dump_buffer(pmap, pmap[0] + 1));
+               ql_dbg(ql_dbg_mbx, vha, 0x1081,
+                   "mb0/mb1=%x/%X FC/AL position map size (%x).\n",
+                   mcp->mb[0], mcp->mb[1], (unsigned)pmap[0]);
+               ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111d,
+                   pmap, pmap[0] + 1);
 
                if (pos_map)
                        memcpy(pos_map, pmap, FCAL_MAP_SIZE);
@@ -2204,15 +2166,13 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
        dma_pool_free(ha->s_dma_pool, pmap, pmap_dma);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x1082, "Failed=%x.\n", rval);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1083, "Done %s.\n", __func__);
        }
 
        return rval;
 }
-#endif
 
 /*
  * qla2x00_get_link_status
@@ -2237,7 +2197,7 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
        uint32_t *siter, *diter, dwords;
        struct qla_hw_data *ha = vha->hw;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1084, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_GET_LINK_STATUS;
        mcp->mb[2] = MSW(stats_dma);
@@ -2266,11 +2226,12 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
 
        if (rval == QLA_SUCCESS) {
                if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
-                       DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
-                           __func__, vha->host_no, mcp->mb[0]));
+                       ql_dbg(ql_dbg_mbx, vha, 0x1085,
+                           "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
                        rval = QLA_FUNCTION_FAILED;
                } else {
                        /* Copy over data -- firmware data is LE. */
+                       ql_dbg(ql_dbg_mbx, vha, 0x1086, "Done %s.\n", __func__);
                        dwords = offsetof(struct link_statistics, unused1) / 4;
                        siter = diter = &stats->link_fail_cnt;
                        while (dwords--)
@@ -2278,8 +2239,7 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
                }
        } else {
                /* Failed. */
-               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x1087, "Failed=%x.\n", rval);
        }
 
        return rval;
@@ -2294,7 +2254,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
        mbx_cmd_t *mcp = &mc;
        uint32_t *siter, *diter, dwords;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1088, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_GET_LINK_PRIV_STATS;
        mcp->mb[2] = MSW(stats_dma);
@@ -2312,10 +2272,11 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
 
        if (rval == QLA_SUCCESS) {
                if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
-                       DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
-                           __func__, vha->host_no, mcp->mb[0]));
+                       ql_dbg(ql_dbg_mbx, vha, 0x1089,
+                           "Failed mb[0]=%x.\n", mcp->mb[0]);
                        rval = QLA_FUNCTION_FAILED;
                } else {
+                       ql_dbg(ql_dbg_mbx, vha, 0x108a, "Done %s.\n", __func__);
                        /* Copy over data -- firmware data is LE. */
                        dwords = sizeof(struct link_statistics) / 4;
                        siter = diter = &stats->link_fail_cnt;
@@ -2324,8 +2285,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
                }
        } else {
                /* Failed. */
-               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x108b, "Failed=%x.\n", rval);
        }
 
        return rval;
@@ -2345,7 +2305,7 @@ qla24xx_abort_command(srb_t *sp)
        struct qla_hw_data *ha = vha->hw;
        struct req_que *req = vha->req;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x108c, "Entered %s.\n", __func__);
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
        for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
@@ -2360,8 +2320,8 @@ qla24xx_abort_command(srb_t *sp)
 
        abt = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma);
        if (abt == NULL) {
-               DEBUG2_3(printk("%s(%ld): failed to allocate Abort IOCB.\n",
-                   __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x108d,
+                   "Failed to allocate abort IOCB.\n");
                return QLA_MEMORY_ALLOC_FAILED;
        }
        memset(abt, 0, sizeof(struct abort_entry_24xx));
@@ -2380,20 +2340,20 @@ qla24xx_abort_command(srb_t *sp)
 
        rval = qla2x00_issue_iocb(vha, abt, abt_dma, 0);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n",
-                   __func__, vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x108e,
+                   "Failed to issue IOCB (%x).\n", rval);
        } else if (abt->entry_status != 0) {
-               DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-                   "-- error status (%x).\n", __func__, vha->host_no,
-                   abt->entry_status));
+               ql_dbg(ql_dbg_mbx, vha, 0x108f,
+                   "Failed to complete IOCB -- error status (%x).\n",
+                   abt->entry_status);
                rval = QLA_FUNCTION_FAILED;
        } else if (abt->nport_handle != __constant_cpu_to_le16(0)) {
-               DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-                   "-- completion status (%x).\n", __func__, vha->host_no,
-                   le16_to_cpu(abt->nport_handle)));
+               ql_dbg(ql_dbg_mbx, vha, 0x1090,
+                   "Failed to complete IOCB -- completion status (%x).\n",
+                   le16_to_cpu(abt->nport_handle));
                rval = QLA_FUNCTION_FAILED;
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1091, "Done %s.\n", __func__);
        }
 
        dma_pool_free(ha->s_dma_pool, abt, abt_dma);
@@ -2421,19 +2381,20 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
        struct req_que *req;
        struct rsp_que *rsp;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no));
-
        vha = fcport->vha;
        ha = vha->hw;
        req = vha->req;
+
+       ql_dbg(ql_dbg_mbx, vha, 0x1092, "Entered %s.\n", __func__);
+
        if (ha->flags.cpu_affinity_enabled)
                rsp = ha->rsp_q_map[tag + 1];
        else
                rsp = req->rsp;
        tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
        if (tsk == NULL) {
-               DEBUG2_3(printk("%s(%ld): failed to allocate Task Management "
-                   "IOCB.\n", __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x1093,
+                   "Failed to allocate task management IOCB.\n");
                return QLA_MEMORY_ALLOC_FAILED;
        }
        memset(tsk, 0, sizeof(struct tsk_mgmt_cmd));
@@ -2457,30 +2418,30 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
        sts = &tsk->p.sts;
        rval = qla2x00_issue_iocb(vha, tsk, tsk_dma, 0);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed to issue %s Reset IOCB "
-                   "(%x).\n", __func__, vha->host_no, name, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x1094,
+                   "Failed to issue %s reset IOCB (%x).\n", name, rval);
        } else if (sts->entry_status != 0) {
-               DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-                   "-- error status (%x).\n", __func__, vha->host_no,
-                   sts->entry_status));
+               ql_dbg(ql_dbg_mbx, vha, 0x1095,
+                   "Failed to complete IOCB -- error status (%x).\n",
+                   sts->entry_status);
                rval = QLA_FUNCTION_FAILED;
        } else if (sts->comp_status !=
            __constant_cpu_to_le16(CS_COMPLETE)) {
-               DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-                   "-- completion status (%x).\n", __func__,
-                   vha->host_no, le16_to_cpu(sts->comp_status)));
+               ql_dbg(ql_dbg_mbx, vha, 0x1096,
+                   "Failed to complete IOCB -- completion status (%x).\n",
+                   le16_to_cpu(sts->comp_status));
                rval = QLA_FUNCTION_FAILED;
        } else if (le16_to_cpu(sts->scsi_status) &
            SS_RESPONSE_INFO_LEN_VALID) {
                if (le32_to_cpu(sts->rsp_data_len) < 4) {
-                       DEBUG2_3_11(printk("%s(%ld): ignoring inconsistent "
-                           "data length -- not enough response info (%d).\n",
-                           __func__, vha->host_no,
-                           le32_to_cpu(sts->rsp_data_len)));
+                       ql_dbg(ql_dbg_mbx, vha, 0x1097,
+                           "Ignoring inconsistent data length -- not enough "
+                           "response info (%d).\n",
+                           le32_to_cpu(sts->rsp_data_len));
                } else if (sts->data[3]) {
-                       DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-                           "-- response (%x).\n", __func__,
-                           vha->host_no, sts->data[3]));
+                       ql_dbg(ql_dbg_mbx, vha, 0x1098,
+                           "Failed to complete IOCB -- response (%x).\n",
+                           sts->data[3]);
                        rval = QLA_FUNCTION_FAILED;
                }
        }
@@ -2489,10 +2450,10 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
        rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, l,
            type == TCF_LUN_RESET ? MK_SYNC_ID_LUN: MK_SYNC_ID);
        if (rval2 != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
-                   "(%x).\n", __func__, vha->host_no, rval2));
+               ql_dbg(ql_dbg_mbx, vha, 0x1099,
+                   "Failed to issue marker IOCB (%x).\n", rval2);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x109a, "Done %s.\n", __func__);
        }
 
        dma_pool_free(ha->s_dma_pool, tsk, tsk_dma);
@@ -2533,7 +2494,7 @@ qla2x00_system_error(scsi_qla_host_t *vha)
        if (!IS_QLA23XX(ha) && !IS_FWI2_CAPABLE(ha))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x109b, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_GEN_SYSTEM_ERROR;
        mcp->out_mb = MBX_0;
@@ -2543,10 +2504,9 @@ qla2x00_system_error(scsi_qla_host_t *vha)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x109c, "Failed=%x.\n", rval);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x109d, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -2566,7 +2526,7 @@ qla2x00_set_serdes_params(scsi_qla_host_t *vha, uint16_t sw_em_1g,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x109e, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_SERDES_PARAMS;
        mcp->mb[1] = BIT_0;
@@ -2581,11 +2541,11 @@ qla2x00_set_serdes_params(scsi_qla_host_t *vha, uint16_t sw_em_1g,
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
-               DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
-                   vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x109f,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
                /*EMPTY*/
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10a0, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -2601,7 +2561,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *vha)
        if (!IS_FWI2_CAPABLE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x10a1, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_STOP_FIRMWARE;
        mcp->out_mb = MBX_0;
@@ -2611,12 +2571,11 @@ qla2x00_stop_firmware(scsi_qla_host_t *vha)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x10a2, "Failed=%x.\n", rval);
                if (mcp->mb[0] == MBS_INVALID_COMMAND)
                        rval = QLA_INVALID_COMMAND;
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10a3, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -2630,14 +2589,14 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10a4, "Entered %s.\n", __func__);
+
        if (!IS_FWI2_CAPABLE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        if (unlikely(pci_channel_offline(vha->hw->pdev)))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_TRACE_CONTROL;
        mcp->mb[1] = TC_EFT_ENABLE;
        mcp->mb[2] = LSW(eft_dma);
@@ -2652,10 +2611,11 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma,
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(vha, mcp);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
-                   __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10a5,
+                   "Failed=%x mb[0]=%x mb[1]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10a6, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -2668,14 +2628,14 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *vha)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10a7, "Entered %s.\n", __func__);
+
        if (!IS_FWI2_CAPABLE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        if (unlikely(pci_channel_offline(vha->hw->pdev)))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_TRACE_CONTROL;
        mcp->mb[1] = TC_EFT_DISABLE;
        mcp->out_mb = MBX_1|MBX_0;
@@ -2684,10 +2644,11 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *vha)
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(vha, mcp);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
-                   __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10a8,
+                   "Failed=%x mb[0]=%x mb[1]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10a9, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -2701,14 +2662,14 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10aa, "Entered %s.\n", __func__);
+
        if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        if (unlikely(pci_channel_offline(vha->hw->pdev)))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_TRACE_CONTROL;
        mcp->mb[1] = TC_FCE_ENABLE;
        mcp->mb[2] = LSW(fce_dma);
@@ -2727,10 +2688,11 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma,
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(vha, mcp);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
-                   __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10ab,
+                   "Failed=%x mb[0]=%x mb[1]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10ac, "Done %s.\n", __func__);
 
                if (mb)
                        memcpy(mb, mcp->mb, 8 * sizeof(*mb));
@@ -2748,14 +2710,14 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10ad, "Entered %s.\n", __func__);
+
        if (!IS_FWI2_CAPABLE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        if (unlikely(pci_channel_offline(vha->hw->pdev)))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_TRACE_CONTROL;
        mcp->mb[1] = TC_FCE_DISABLE;
        mcp->mb[2] = TC_FCE_DISABLE_TRACE;
@@ -2766,10 +2728,11 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd)
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(vha, mcp);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
-                   __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10ae,
+                   "Failed=%x mb[0]=%x mb[1]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10af, "Done %s.\n", __func__);
 
                if (wr)
                        *wr = (uint64_t) mcp->mb[5] << 48 |
@@ -2794,11 +2757,11 @@ qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10b0, "Entered %s.\n", __func__);
+
        if (!IS_IIDMA_CAPABLE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_PORT_PARAMS;
        mcp->mb[1] = loop_id;
        mcp->mb[2] = mcp->mb[3] = 0;
@@ -2817,10 +2780,9 @@ qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
        }
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x10b1, "Failed=%x.\n", rval);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10b2, "Done %s.\n", __func__);
                if (port_speed)
                        *port_speed = mcp->mb[3];
        }
@@ -2836,11 +2798,11 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10b3, "Entered %s.\n", __func__);
+
        if (!IS_IIDMA_CAPABLE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_PORT_PARAMS;
        mcp->mb[1] = loop_id;
        mcp->mb[2] = BIT_0;
@@ -2863,10 +2825,9 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
        }
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x10b4, "Failed=%x.\n", rval);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10b5, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -2882,33 +2843,36 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
        scsi_qla_host_t *vp;
        unsigned long   flags;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10b6, "Entered %s.\n", __func__);
+
        if (rptid_entry->entry_status != 0)
                return;
 
        if (rptid_entry->format == 0) {
-               DEBUG15(printk("%s:format 0 : scsi(%ld) number of VPs setup %d,"
-                       " number of VPs acquired %d\n", __func__, vha->host_no,
-                       MSB(le16_to_cpu(rptid_entry->vp_count)),
-                       LSB(le16_to_cpu(rptid_entry->vp_count))));
-               DEBUG15(printk("%s primary port id %02x%02x%02x\n", __func__,
-                       rptid_entry->port_id[2], rptid_entry->port_id[1],
-                       rptid_entry->port_id[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10b7,
+                   "Format 0 : Number of VPs setup %d, number of "
+                   "VPs acquired %d.\n",
+                   MSB(le16_to_cpu(rptid_entry->vp_count)),
+                   LSB(le16_to_cpu(rptid_entry->vp_count)));
+               ql_dbg(ql_dbg_mbx, vha, 0x10b8,
+                   "Primary port id %02x%02x%02x.\n",
+                   rptid_entry->port_id[2], rptid_entry->port_id[1],
+                   rptid_entry->port_id[0]);
        } else if (rptid_entry->format == 1) {
                vp_idx = LSB(stat);
-               DEBUG15(printk("%s:format 1: scsi(%ld): VP[%d] enabled "
-                   "- status %d - "
-                   "with port id %02x%02x%02x\n", __func__, vha->host_no,
-                   vp_idx, MSB(stat),
+               ql_dbg(ql_dbg_mbx, vha, 0x10b9,
+                   "Format 1: VP[%d] enabled - status %d - with "
+                   "port id %02x%02x%02x.\n", vp_idx, MSB(stat),
                    rptid_entry->port_id[2], rptid_entry->port_id[1],
-                   rptid_entry->port_id[0]));
+                   rptid_entry->port_id[0]);
 
                vp = vha;
                if (vp_idx == 0 && (MSB(stat) != 1))
                        goto reg_needed;
 
                if (MSB(stat) == 1) {
-                       DEBUG2(printk("scsi(%ld): Could not acquire ID for "
-                           "VP[%d].\n", vha->host_no, vp_idx));
+                       ql_dbg(ql_dbg_mbx, vha, 0x10ba,
+                           "Could not acquire ID for VP[%d].\n", vp_idx);
                        return;
                }
 
@@ -2963,10 +2927,12 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha)
 
        /* This can be called by the parent */
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10bb, "Entered %s.\n", __func__);
+
        vpmod = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vpmod_dma);
        if (!vpmod) {
-               DEBUG2_3(printk("%s(%ld): failed to allocate Modify VP "
-                   "IOCB.\n", __func__, vha->host_no));
+               ql_log(ql_log_warn, vha, 0x10bc,
+                   "Failed to allocate modify VP IOCB.\n");
                return QLA_MEMORY_ALLOC_FAILED;
        }
 
@@ -2983,22 +2949,21 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha)
 
        rval = qla2x00_issue_iocb(base_vha, vpmod, vpmod_dma, 0);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed to issue VP config IOCB"
-                       "(%x).\n", __func__, base_vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x10bd,
+                   "Failed to issue VP config IOCB (%x).\n", rval);
        } else if (vpmod->comp_status != 0) {
-               DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-                       "-- error status (%x).\n", __func__, base_vha->host_no,
-                       vpmod->comp_status));
+               ql_dbg(ql_dbg_mbx, vha, 0x10be,
+                   "Failed to complete IOCB -- error status (%x).\n",
+                   vpmod->comp_status);
                rval = QLA_FUNCTION_FAILED;
        } else if (vpmod->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
-               DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-                   "-- completion status (%x).\n", __func__, base_vha->host_no,
-                   le16_to_cpu(vpmod->comp_status)));
+               ql_dbg(ql_dbg_mbx, vha, 0x10bf,
+                   "Failed to complete IOCB -- completion status (%x).\n",
+                   le16_to_cpu(vpmod->comp_status));
                rval = QLA_FUNCTION_FAILED;
        } else {
                /* EMPTY */
-               DEBUG11(printk("%s(%ld): done.\n", __func__,
-                                                       base_vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10c0, "Done %s.\n", __func__);
                fc_vport_set_state(vha->fc_vport, FC_VPORT_INITIALIZING);
        }
        dma_pool_free(ha->s_dma_pool, vpmod, vpmod_dma);
@@ -3032,17 +2997,16 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
        int     vp_index = vha->vp_idx;
        struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
 
-       DEBUG11(printk("%s(%ld): entered. Enabling index %d\n", __func__,
-           vha->host_no, vp_index));
+       ql_dbg(ql_dbg_mbx, vha, 0x10c1,
+           "Entered %s enabling index %d.\n", __func__, vp_index);
 
        if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
                return QLA_PARAMETER_ERROR;
 
        vce = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vce_dma);
        if (!vce) {
-               DEBUG2_3(printk("%s(%ld): "
-                   "failed to allocate VP Control IOCB.\n", __func__,
-                   base_vha->host_no));
+               ql_log(ql_log_warn, vha, 0x10c2,
+                   "Failed to allocate VP control IOCB.\n");
                return QLA_MEMORY_ALLOC_FAILED;
        }
        memset(vce, 0, sizeof(struct vp_ctrl_entry_24xx));
@@ -3063,28 +3027,20 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
 
        rval = qla2x00_issue_iocb(base_vha, vce, vce_dma, 0);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed to issue VP control IOCB"
-                   "(%x).\n", __func__, base_vha->host_no, rval));
-               printk("%s(%ld): failed to issue VP control IOCB"
-                   "(%x).\n", __func__, base_vha->host_no, rval);
+               ql_dbg(ql_dbg_mbx, vha, 0x10c3,
+                   "Failed to issue VP control IOCB (%x).\n", rval);
        } else if (vce->entry_status != 0) {
-               DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-                   "-- error status (%x).\n", __func__, base_vha->host_no,
-                   vce->entry_status));
-               printk("%s(%ld): failed to complete IOCB "
-                   "-- error status (%x).\n", __func__, base_vha->host_no,
+               ql_dbg(ql_dbg_mbx, vha, 0x10c4,
+                   "Failed to complete IOCB -- error status (%x).\n",
                    vce->entry_status);
                rval = QLA_FUNCTION_FAILED;
        } else if (vce->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
-               DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-                   "-- completion status (%x).\n", __func__, base_vha->host_no,
-                   le16_to_cpu(vce->comp_status)));
-               printk("%s(%ld): failed to complete IOCB "
-                   "-- completion status (%x).\n", __func__, base_vha->host_no,
+               ql_dbg(ql_dbg_mbx, vha, 0x10c5,
+                   "Failed to complet IOCB -- completion status (%x).\n",
                    le16_to_cpu(vce->comp_status));
                rval = QLA_FUNCTION_FAILED;
        } else {
-               DEBUG2(printk("%s(%ld): done.\n", __func__, base_vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10c6, "Done %s.\n", __func__);
        }
 
        dma_pool_free(ha->s_dma_pool, vce, vce_dma);
@@ -3121,6 +3077,8 @@ qla2x00_send_change_request(scsi_qla_host_t *vha, uint16_t format,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10c7, "Entered %s.\n", __func__);
+
        /*
         * This command is implicitly executed by firmware during login for the
         * physical hosts
@@ -3155,7 +3113,7 @@ qla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1009, "Entered %s.\n", __func__);
 
        if (MSW(addr) || IS_FWI2_CAPABLE(vha->hw)) {
                mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED;
@@ -3186,10 +3144,10 @@ qla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
-                   vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1008,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1007, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -3214,12 +3172,10 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status)
        unsigned long flags;
        struct qla_hw_data *ha = vha->hw;
 
-       DEBUG16(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x10c8, "Entered %s.\n", __func__);
 
        mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
        if (mn == NULL) {
-               DEBUG2_3(printk("%s(%ld): failed to allocate Verify ISP84XX "
-                   "IOCB.\n", __func__, vha->host_no));
                return QLA_MEMORY_ALLOC_FAILED;
        }
 
@@ -3237,43 +3193,43 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status)
                mn->p.req.entry_count = 1;
                mn->p.req.options = cpu_to_le16(options);
 
-               DEBUG16(printk("%s(%ld): Dump of Verify Request.\n", __func__,
-                   vha->host_no));
-               DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
-                   sizeof(*mn)));
+               ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111c,
+                   "Dump of Verify Request.\n");
+               ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111e,
+                   (uint8_t *)mn, sizeof(*mn));
 
                rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
                if (rval != QLA_SUCCESS) {
-                       DEBUG2_16(printk("%s(%ld): failed to issue Verify "
-                           "IOCB (%x).\n", __func__, vha->host_no, rval));
+                       ql_dbg(ql_dbg_mbx, vha, 0x10cb,
+                           "Failed to issue verify IOCB (%x).\n", rval);
                        goto verify_done;
                }
 
-               DEBUG16(printk("%s(%ld): Dump of Verify Response.\n", __func__,
-                   vha->host_no));
-               DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
-                   sizeof(*mn)));
+               ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1110,
+                   "Dump of Verify Response.\n");
+               ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1118,
+                   (uint8_t *)mn, sizeof(*mn));
 
                status[0] = le16_to_cpu(mn->p.rsp.comp_status);
                status[1] = status[0] == CS_VCS_CHIP_FAILURE ?
                    le16_to_cpu(mn->p.rsp.failure_code) : 0;
-               DEBUG2_16(printk("%s(%ld): cs=%x fc=%x\n", __func__,
-                   vha->host_no, status[0], status[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10ce,
+                   "cs=%x fc=%x.\n", status[0], status[1]);
 
                if (status[0] != CS_COMPLETE) {
                        rval = QLA_FUNCTION_FAILED;
                        if (!(options & VCO_DONT_UPDATE_FW)) {
-                               DEBUG2_16(printk("%s(%ld): Firmware update "
-                                   "failed. Retrying without update "
-                                   "firmware.\n", __func__, vha->host_no));
+                               ql_dbg(ql_dbg_mbx, vha, 0x10cf,
+                                   "Firmware update failed. Retrying "
+                                   "without update firmware.\n");
                                options |= VCO_DONT_UPDATE_FW;
                                options &= ~VCO_FORCE_UPDATE;
                                retry = 1;
                        }
                } else {
-                       DEBUG2_16(printk("%s(%ld): firmware updated to %x.\n",
-                           __func__, vha->host_no,
-                           le32_to_cpu(mn->p.rsp.fw_ver)));
+                       ql_dbg(ql_dbg_mbx, vha, 0x10d0,
+                           "Firmware updated to %x.\n",
+                           le32_to_cpu(mn->p.rsp.fw_ver));
 
                        /* NOTE: we only update OP firmware. */
                        spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
@@ -3288,10 +3244,9 @@ verify_done:
        dma_pool_free(ha->s_dma_pool, mn, mn_dma);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_16(printk("%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x10d1, "Failed=%x.\n", rval);
        } else {
-               DEBUG16(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10d2, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -3307,6 +3262,8 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
        struct device_reg_25xxmq __iomem *reg;
        struct qla_hw_data *ha = vha->hw;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10d3, "Entered %s.\n", __func__);
+
        mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
        mcp->mb[1] = req->options;
        mcp->mb[2] = MSW(LSD(req->dma));
@@ -3344,9 +3301,13 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        rval = qla2x00_mailbox_command(vha, mcp);
-       if (rval != QLA_SUCCESS)
-               DEBUG2_3_11(printk(KERN_WARNING "%s(%ld): failed=%x mb0=%x.\n",
-                       __func__, vha->host_no, rval, mcp->mb[0]));
+       if (rval != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_mbx, vha, 0x10d4,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+       } else {
+               ql_dbg(ql_dbg_mbx, vha, 0x10d5, "Done %s.\n", __func__);
+       }
+
        return rval;
 }
 
@@ -3360,6 +3321,8 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
        struct device_reg_25xxmq __iomem *reg;
        struct qla_hw_data *ha = vha->hw;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10d6, "Entered %s.\n", __func__);
+
        mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
        mcp->mb[1] = rsp->options;
        mcp->mb[2] = MSW(LSD(rsp->dma));
@@ -3393,10 +3356,13 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        rval = qla2x00_mailbox_command(vha, mcp);
-       if (rval != QLA_SUCCESS)
-               DEBUG2_3_11(printk(KERN_WARNING "%s(%ld): failed=%x "
-                       "mb0=%x.\n", __func__,
-                       vha->host_no, rval, mcp->mb[0]));
+       if (rval != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_mbx, vha, 0x10d7,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+       } else {
+               ql_dbg(ql_dbg_mbx, vha, 0x10d8, "Done %s.\n", __func__);
+       }
+
        return rval;
 }
 
@@ -3407,7 +3373,7 @@ qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x10d9, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_IDC_ACK;
        memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
@@ -3418,10 +3384,10 @@ qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
-                   vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10da,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10db, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -3434,11 +3400,11 @@ qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10dc, "Entered %s.\n", __func__);
+
        if (!IS_QLA81XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
        mcp->mb[1] = FAC_OPT_CMD_GET_SECTOR_SIZE;
        mcp->out_mb = MBX_1|MBX_0;
@@ -3448,10 +3414,11 @@ qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
-                   __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10dd,
+                   "Failed=%x mb[0]=%x mb[1]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10de, "Done %s.\n", __func__);
                *sector_size = mcp->mb[1];
        }
 
@@ -3468,7 +3435,7 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable)
        if (!IS_QLA81XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x10df, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
        mcp->mb[1] = enable ? FAC_OPT_CMD_WRITE_ENABLE :
@@ -3480,10 +3447,11 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
-                   __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10e0,
+                   "Failed=%x mb[0]=%x mb[1]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10e1, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -3499,7 +3467,7 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
        if (!IS_QLA81XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x10e2, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
        mcp->mb[1] = FAC_OPT_CMD_ERASE_SECTOR;
@@ -3514,11 +3482,11 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
-                   "mb[2]=%x.\n", __func__, vha->host_no, rval, mcp->mb[0],
-                   mcp->mb[1], mcp->mb[2]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10e3,
+                   "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10e4, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -3531,7 +3499,7 @@ qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x10e5, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_RESTART_MPI_FW;
        mcp->out_mb = MBX_0;
@@ -3541,10 +3509,11 @@ qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=0x%x mb[1]=0x%x.\n",
-                   __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10e6,
+                   "Failed=%x mb[0]=%x mb[1]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10e7, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -3559,11 +3528,11 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
        mbx_cmd_t *mcp = &mc;
        struct qla_hw_data *ha = vha->hw;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10e8, "Entered %s.\n", __func__);
+
        if (!IS_FWI2_CAPABLE(ha))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        if (len == 1)
                opt |= BIT_0;
 
@@ -3586,10 +3555,10 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
                *sfp = mcp->mb[1];
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
-                   vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10e9,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10ea, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -3604,11 +3573,11 @@ qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
        mbx_cmd_t *mcp = &mc;
        struct qla_hw_data *ha = vha->hw;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10eb, "Entered %s.\n", __func__);
+
        if (!IS_FWI2_CAPABLE(ha))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        if (len == 1)
                opt |= BIT_0;
 
@@ -3631,10 +3600,10 @@ qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
-                   vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10ec,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10ed, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -3648,11 +3617,11 @@ qla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10ee, "Entered %s.\n", __func__);
+
        if (!IS_QLA8XXX_TYPE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_GET_XGMAC_STATS;
        mcp->mb[2] = MSW(stats_dma);
        mcp->mb[3] = LSW(stats_dma);
@@ -3666,11 +3635,12 @@ qla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma,
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=0x%x "
-                   "mb[1]=0x%x mb[2]=0x%x.\n", __func__, vha->host_no, rval,
-                   mcp->mb[0], mcp->mb[1], mcp->mb[2]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10ef,
+                   "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10f0, "Done %s.\n", __func__);
+
 
                *actual_size = mcp->mb[2] << 2;
        }
@@ -3686,11 +3656,11 @@ qla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10f1, "Entered %s.\n", __func__);
+
        if (!IS_QLA8XXX_TYPE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_GET_DCBX_PARAMS;
        mcp->mb[1] = 0;
        mcp->mb[2] = MSW(tlv_dma);
@@ -3705,11 +3675,11 @@ qla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma,
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=0x%x "
-                   "mb[1]=0x%x mb[2]=0x%x.\n", __func__, vha->host_no, rval,
-                   mcp->mb[0], mcp->mb[1], mcp->mb[2]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10f2,
+                   "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10f3, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -3722,11 +3692,11 @@ qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x10f4, "Entered %s.\n", __func__);
+
        if (!IS_FWI2_CAPABLE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_READ_RAM_EXTENDED;
        mcp->mb[1] = LSW(risc_addr);
        mcp->mb[8] = MSW(risc_addr);
@@ -3736,10 +3706,10 @@ qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data)
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(vha, mcp);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
-                   vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10f5,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10f6, "Done %s.\n", __func__);
                *data = mcp->mb[3] << 16 | mcp->mb[2];
        }
 
@@ -3755,7 +3725,7 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
        mbx_cmd_t *mcp = &mc;
        uint32_t iter_cnt = 0x1;
 
-       DEBUG11(printk("scsi(%ld): entered.\n", vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x10f7, "Entered %s.\n", __func__);
 
        memset(mcp->mb, 0 , sizeof(mcp->mb));
        mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
@@ -3794,15 +3764,12 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2(printk(KERN_WARNING
-                       "(%ld): failed=%x mb[0]=0x%x "
-                       "mb[1]=0x%x mb[2]=0x%x mb[3]=0x%x mb[18]=0x%x "
-                       "mb[19]=0x%x.\n",
-                       vha->host_no, rval, mcp->mb[0], mcp->mb[1], mcp->mb[2],
-                       mcp->mb[3], mcp->mb[18], mcp->mb[19]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10f8,
+                   "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[3]=%x mb[18]=%x "
+                   "mb[19]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2],
+                   mcp->mb[3], mcp->mb[18], mcp->mb[19]);
        } else {
-               DEBUG2(printk(KERN_WARNING
-                   "scsi(%ld): done.\n", vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10f9, "Done %s.\n", __func__);
        }
 
        /* Copy mailbox information */
@@ -3819,7 +3786,7 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
        mbx_cmd_t *mcp = &mc;
        struct qla_hw_data *ha = vha->hw;
 
-       DEBUG11(printk("scsi(%ld): entered.\n", vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x10fa, "Entered %s.\n", __func__);
 
        memset(mcp->mb, 0 , sizeof(mcp->mb));
        mcp->mb[0] = MBC_DIAGNOSTIC_ECHO;
@@ -3858,12 +3825,11 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2(printk(KERN_WARNING
-                   "(%ld): failed=%x mb[0]=0x%x mb[1]=0x%x.\n",
-                   vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+               ql_dbg(ql_dbg_mbx, vha, 0x10fb,
+                   "Failed=%x mb[0]=%x mb[1]=%x.\n",
+                   rval, mcp->mb[0], mcp->mb[1]);
        } else {
-               DEBUG2(printk(KERN_WARNING
-                   "scsi(%ld): done.\n", vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10fc, "Done %s.\n", __func__);
        }
 
        /* Copy mailbox information */
@@ -3872,14 +3838,14 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
 }
 
 int
-qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic)
+qla84xx_reset_chip(scsi_qla_host_t *vha, uint16_t enable_diagnostic)
 {
        int rval;
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG16(printk("%s(%ld): enable_diag=%d entered.\n", __func__,
-               ha->host_no, enable_diagnostic));
+       ql_dbg(ql_dbg_mbx, vha, 0x10fd,
+           "Entered %s enable_diag=%d.\n", __func__, enable_diagnostic);
 
        mcp->mb[0] = MBC_ISP84XX_RESET;
        mcp->mb[1] = enable_diagnostic;
@@ -3887,13 +3853,12 @@ qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic)
        mcp->in_mb = MBX_1|MBX_0;
        mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
-       rval = qla2x00_mailbox_command(ha, mcp);
+       rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS)
-               DEBUG16(printk("%s(%ld): failed=%x.\n", __func__, ha->host_no,
-                       rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x10fe, "Failed=%x.\n", rval);
        else
-               DEBUG16(printk("%s(%ld): done.\n", __func__, ha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10ff, "Done %s.\n", __func__);
 
        return rval;
 }
@@ -3905,11 +3870,11 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x1100, "Entered %s.\n", __func__);
+
        if (!IS_FWI2_CAPABLE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_WRITE_RAM_WORD_EXTENDED;
        mcp->mb[1] = LSW(risc_addr);
        mcp->mb[2] = LSW(data);
@@ -3921,10 +3886,10 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data)
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(vha, mcp);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
-                   vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1101,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1102, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -3941,8 +3906,7 @@ qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb)
 
        rval = QLA_SUCCESS;
 
-       DEBUG11(qla_printk(KERN_INFO, ha,
-           "%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1103, "Entered %s.\n", __func__);
 
        clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 
@@ -3982,11 +3946,10 @@ qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb)
                rval = QLA_FUNCTION_FAILED;
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk(KERN_INFO "%s(%ld): failed=%x mb[0]=%x.\n",
-                   __func__, vha->host_no, rval, mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1104,
+                   "Failed=%x mb[0]=%x.\n", rval, mb[0]);
        } else {
-               DEBUG11(printk(KERN_INFO
-                   "%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1105, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -3999,12 +3962,11 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
        mbx_cmd_t *mcp = &mc;
        struct qla_hw_data *ha = vha->hw;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x1106, "Entered %s.\n", __func__);
+
        if (!IS_FWI2_CAPABLE(ha))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(qla_printk(KERN_INFO, ha,
-               "%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_DATA_RATE;
        mcp->mb[1] = 0;
        mcp->out_mb = MBX_1|MBX_0;
@@ -4013,11 +3975,10 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(vha, mcp);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk(KERN_INFO "%s(%ld): failed=%x mb[0]=%x.\n",
-                   __func__, vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1107,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
-               DEBUG11(printk(KERN_INFO
-                   "%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x1108, "Done %s.\n", __func__);
                if (mcp->mb[1] != 0x7)
                        ha->link_data_rate = mcp->mb[1];
        }
@@ -4033,8 +3994,7 @@ qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb)
        mbx_cmd_t *mcp = &mc;
        struct qla_hw_data *ha = vha->hw;
 
-       DEBUG11(printk(KERN_INFO
-           "%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1109, "Entered %s.\n", __func__);
 
        if (!IS_QLA81XX(ha))
                return QLA_FUNCTION_FAILED;
@@ -4047,15 +4007,13 @@ qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk(KERN_WARNING
-                   "%s(%ld): failed=%x (%x).\n", __func__,
-                   vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x110a,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
                /* Copy all bits to preserve original value */
                memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4);
 
-               DEBUG11(printk(KERN_INFO
-                   "%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x110b, "Done %s.\n", __func__);
        }
        return rval;
 }
@@ -4067,8 +4025,7 @@ qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk(KERN_INFO
-           "%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x110c, "Entered %s.\n", __func__);
 
        mcp->mb[0] = MBC_SET_PORT_CONFIG;
        /* Copy all bits to preserve original setting */
@@ -4080,12 +4037,10 @@ qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb)
        rval = qla2x00_mailbox_command(vha, mcp);
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk(KERN_WARNING
-                   "%s(%ld): failed=%x (%x).\n", __func__,
-                   vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x110d,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else
-               DEBUG11(printk(KERN_INFO
-                   "%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x110e, "Done %s.\n", __func__);
 
        return rval;
 }
@@ -4100,12 +4055,11 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
        mbx_cmd_t *mcp = &mc;
        struct qla_hw_data *ha = vha->hw;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x110f, "Entered %s.\n", __func__);
+
        if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk(KERN_INFO
-           "%s(%ld): entered.\n", __func__, vha->host_no));
-
        mcp->mb[0] = MBC_PORT_PARAMS;
        mcp->mb[1] = loop_id;
        if (ha->flags.fcp_prio_enabled)
@@ -4127,12 +4081,9 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
        }
 
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk(KERN_WARNING
-                   "%s(%ld): failed=%x.\n", __func__,
-                   vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x10cd, "Failed=%x.\n", rval);
        } else {
-               DEBUG11(printk(KERN_INFO
-                   "%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x10cc, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -4145,13 +4096,12 @@ qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac)
        uint8_t byte;
        struct qla_hw_data *ha = vha->hw;
 
-       DEBUG11(printk(KERN_INFO "%s(%ld): entered.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x10ca, "Entered %s.\n", __func__);
 
        /* Integer part */
        rval = qla2x00_read_sfp(vha, 0, &byte, 0x98, 0x01, 1, BIT_13|BIT_0);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk(KERN_WARNING
-                   "%s(%ld): failed=%x.\n", __func__, vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x10c9, "Failed=%x.\n", rval);
                ha->flags.thermal_supported = 0;
                goto fail;
        }
@@ -4160,14 +4110,13 @@ qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac)
        /* Fraction part */
        rval = qla2x00_read_sfp(vha, 0, &byte, 0x98, 0x10, 1, BIT_13|BIT_0);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk(KERN_WARNING
-                   "%s(%ld): failed=%x.\n", __func__, vha->host_no, rval));
+               ql_dbg(ql_dbg_mbx, vha, 0x1019, "Failed=%x.\n", rval);
                ha->flags.thermal_supported = 0;
                goto fail;
        }
        *frac = (byte >> 6) * 25;
 
-       DEBUG11(printk(KERN_INFO "%s(%ld): done.\n", __func__, vha->host_no));
+       ql_dbg(ql_dbg_mbx, vha, 0x1018, "Done %s.\n", __func__);
 fail:
        return rval;
 }
@@ -4180,12 +4129,11 @@ qla82xx_mbx_intr_enable(scsi_qla_host_t *vha)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x1017, "Entered %s.\n", __func__);
+
        if (!IS_FWI2_CAPABLE(ha))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(qla_printk(KERN_INFO, ha,
-               "%s(%ld): entered.\n", __func__, vha->host_no));
-
        memset(mcp, 0, sizeof(mbx_cmd_t));
        mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
        mcp->mb[1] = 1;
@@ -4197,12 +4145,10 @@ qla82xx_mbx_intr_enable(scsi_qla_host_t *vha)
 
        rval = qla2x00_mailbox_command(vha, mcp);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(qla_printk(KERN_WARNING, ha,
-                       "%s(%ld): failed=%x mb[0]=%x.\n", __func__,
-                       vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x1016,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
-               DEBUG11(qla_printk(KERN_INFO, ha,
-                       "%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x100e, "Done %s.\n", __func__);
        }
 
        return rval;
@@ -4216,12 +4162,11 @@ qla82xx_mbx_intr_disable(scsi_qla_host_t *vha)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       ql_dbg(ql_dbg_mbx, vha, 0x100d, "Entered %s.\n", __func__);
+
        if (!IS_QLA82XX(ha))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(qla_printk(KERN_INFO, ha,
-               "%s(%ld): entered.\n", __func__, vha->host_no));
-
        memset(mcp, 0, sizeof(mbx_cmd_t));
        mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
        mcp->mb[1] = 0;
@@ -4233,12 +4178,10 @@ qla82xx_mbx_intr_disable(scsi_qla_host_t *vha)
 
        rval = qla2x00_mailbox_command(vha, mcp);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(qla_printk(KERN_WARNING, ha,
-                       "%s(%ld): failed=%x mb[0]=%x.\n", __func__,
-                       vha->host_no, rval, mcp->mb[0]));
+               ql_dbg(ql_dbg_mbx, vha, 0x100c,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
-               DEBUG11(qla_printk(KERN_INFO, ha,
-                       "%s(%ld): done.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_mbx, vha, 0x100b, "Done %s.\n", __func__);
        }
 
        return rval;
index 5e34391..c706ed3 100644 (file)
@@ -36,8 +36,9 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
        mutex_lock(&ha->vport_lock);
        vp_id = find_first_zero_bit(ha->vp_idx_map, ha->max_npiv_vports + 1);
        if (vp_id > ha->max_npiv_vports) {
-               DEBUG15(printk ("vp_id %d is bigger than max-supported %d.\n",
-                   vp_id, ha->max_npiv_vports));
+               ql_dbg(ql_dbg_vport, vha, 0xa000,
+                   "vp_id %d is bigger than max-supported %d.\n",
+                   vp_id, ha->max_npiv_vports);
                mutex_unlock(&ha->vport_lock);
                return vp_id;
        }
@@ -131,9 +132,9 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
        fc_port_t *fcport;
 
        list_for_each_entry(fcport, &vha->vp_fcports, list) {
-               DEBUG15(printk("scsi(%ld): Marking port dead, "
-                   "loop_id=0x%04x :%x\n",
-                   vha->host_no, fcport->loop_id, fcport->vp_idx));
+               ql_dbg(ql_dbg_vport, vha, 0xa001,
+                   "Marking port dead, loop_id=0x%04x : %x.\n",
+                   fcport->loop_id, fcport->vp_idx);
 
                qla2x00_mark_device_lost(vha, fcport, 0, 0);
                qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
@@ -187,13 +188,13 @@ qla24xx_enable_vp(scsi_qla_host_t *vha)
                goto enable_failed;
        }
 
-       DEBUG15(qla_printk(KERN_INFO, ha,
-           "Virtual port with id: %d - Enabled\n", vha->vp_idx));
+       ql_dbg(ql_dbg_taskm, vha, 0x801a,
+           "Virtual port with id: %d - Enabled.\n", vha->vp_idx);
        return 0;
 
 enable_failed:
-       DEBUG15(qla_printk(KERN_INFO, ha,
-           "Virtual port with id: %d - Disabled\n", vha->vp_idx));
+       ql_dbg(ql_dbg_taskm, vha, 0x801b,
+           "Virtual port with id: %d - Disabled.\n", vha->vp_idx);
        return 1;
 }
 
@@ -205,12 +206,12 @@ qla24xx_configure_vp(scsi_qla_host_t *vha)
 
        fc_vport = vha->fc_vport;
 
-       DEBUG15(printk("scsi(%ld): %s: change request #3 for this host.\n",
-           vha->host_no, __func__));
+       ql_dbg(ql_dbg_vport, vha, 0xa002,
+           "%s: change request #3.\n", __func__);
        ret = qla2x00_send_change_request(vha, 0x3, vha->vp_idx);
        if (ret != QLA_SUCCESS) {
-               DEBUG15(qla_printk(KERN_ERR, vha->hw, "Failed to enable "
-                   "receiving of RSCN requests: 0x%x\n", ret));
+               ql_dbg(ql_dbg_vport, vha, 0xa003, "Failed to enable "
+                   "receiving of RSCN requests: 0x%x.\n", ret);
                return;
        } else {
                /* Corresponds to SCR enabled */
@@ -248,9 +249,9 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
                        case MBA_CHG_IN_CONNECTION:
                        case MBA_PORT_UPDATE:
                        case MBA_RSCN_UPDATE:
-                               DEBUG15(printk("scsi(%ld)%s: Async_event for"
-                               " VP[%d], mb = 0x%x, vha=%p\n",
-                               vha->host_no, __func__, i, *mb, vha));
+                               ql_dbg(ql_dbg_async, vha, 0x5024,
+                                   "Async_event for VP[%d], mb=0x%x vha=%p.\n",
+                                   i, *mb, vha);
                                qla2x00_async_event(vha, rsp, mb);
                                break;
                        }
@@ -286,37 +287,49 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
        if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
                qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
 
-       DEBUG15(printk("scsi(%ld): Scheduling enable of Vport %d...\n",
-           vha->host_no, vha->vp_idx));
+       ql_dbg(ql_dbg_taskm, vha, 0x801d,
+           "Scheduling enable of Vport %d.\n", vha->vp_idx);
        return qla24xx_enable_vp(vha);
 }
 
 static int
 qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
 {
+       ql_dbg(ql_dbg_dpc, vha, 0x4012,
+           "Entering %s.\n", __func__);
+       ql_dbg(ql_dbg_dpc, vha, 0x4013,
+           "vp_flags: 0x%lx.\n", vha->vp_flags);
+
        qla2x00_do_work(vha);
 
        if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) {
                /* VP acquired. complete port configuration */
+               ql_dbg(ql_dbg_dpc, vha, 0x4014,
+                   "Configure VP scheduled.\n");
                qla24xx_configure_vp(vha);
+               ql_dbg(ql_dbg_dpc, vha, 0x4015,
+                   "Configure VP end.\n");
                return 0;
        }
 
        if (test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags)) {
+               ql_dbg(ql_dbg_dpc, vha, 0x4016,
+                   "FCPort update scheduled.\n");
                qla2x00_update_fcports(vha);
                clear_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags);
+               ql_dbg(ql_dbg_dpc, vha, 0x4017,
+                   "FCPort update end.\n");
        }
 
        if ((test_and_clear_bit(RELOGIN_NEEDED, &vha->dpc_flags)) &&
                !test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) &&
                atomic_read(&vha->loop_state) != LOOP_DOWN) {
 
-               DEBUG(printk("scsi(%ld): qla2x00_port_login()\n",
-                                               vha->host_no));
+               ql_dbg(ql_dbg_dpc, vha, 0x4018,
+                   "Relogin needed scheduled.\n");
                qla2x00_relogin(vha);
-
-               DEBUG(printk("scsi(%ld): qla2x00_port_login - end\n",
-                                                       vha->host_no));
+               ql_dbg(ql_dbg_dpc, vha, 0x4019,
+                   "Relogin needed end.\n");
        }
 
        if (test_and_clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) &&
@@ -326,11 +339,17 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
 
        if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
                if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))) {
+                       ql_dbg(ql_dbg_dpc, vha, 0x401a,
+                           "Loop resync scheduled.\n");
                        qla2x00_loop_resync(vha);
                        clear_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags);
+                       ql_dbg(ql_dbg_dpc, vha, 0x401b,
+                           "Loop resync end.\n");
                }
        }
 
+       ql_dbg(ql_dbg_dpc, vha, 0x401c,
+           "Exiting %s.\n", __func__);
        return 0;
 }
 
@@ -396,9 +415,10 @@ qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport)
 
        /* Check up max-npiv-supports */
        if (ha->num_vhosts > ha->max_npiv_vports) {
-               DEBUG15(printk("scsi(%ld): num_vhosts %ud is bigger than "
-                   "max_npv_vports %ud.\n", base_vha->host_no,
-                   ha->num_vhosts, ha->max_npiv_vports));
+               ql_dbg(ql_dbg_vport, vha, 0xa004,
+                   "num_vhosts %ud is bigger "
+                   "than max_npiv_vports %ud.\n",
+                   ha->num_vhosts, ha->max_npiv_vports);
                return VPCERR_UNSUPPORTED;
        }
        return 0;
@@ -415,7 +435,8 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
 
        vha = qla2x00_create_host(sht, ha);
        if (!vha) {
-               DEBUG(printk("qla2xxx: scsi_host_alloc() failed for vport\n"));
+               ql_log(ql_log_warn, vha, 0xa005,
+                   "scsi_host_alloc() failed for vport.\n");
                return(NULL);
        }
 
@@ -429,8 +450,8 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
        vha->device_flags = 0;
        vha->vp_idx = qla24xx_allocate_vp_id(vha);
        if (vha->vp_idx > ha->max_npiv_vports) {
-               DEBUG15(printk("scsi(%ld): Couldn't allocate vp_id.\n",
-                       vha->host_no));
+               ql_dbg(ql_dbg_vport, vha, 0xa006,
+                   "Couldn't allocate vp_id.\n");
                goto create_vhost_failed;
        }
        vha->mgmt_svr_loop_id = 10 + vha->vp_idx;
@@ -461,8 +482,9 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
        host->max_id = MAX_TARGETS_2200;
        host->transportt = qla2xxx_transport_vport_template;
 
-       DEBUG15(printk("DEBUG: detect vport hba %ld at address = %p\n",
-           vha->host_no, vha));
+       ql_dbg(ql_dbg_vport, vha, 0xa007,
+           "Detect vport hba %ld at address = %p.\n",
+           vha->host_no, vha);
 
        vha->flags.init_done = 1;
 
@@ -567,9 +589,9 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
                if (req) {
                        ret = qla25xx_delete_req_que(vha, req);
                        if (ret != QLA_SUCCESS) {
-                               qla_printk(KERN_WARNING, ha,
-                               "Couldn't delete req que %d\n",
-                               req->id);
+                               ql_log(ql_log_warn, vha, 0x00ea,
+                                   "Couldn't delete req que %d.\n",
+                                   req->id);
                                return ret;
                        }
                }
@@ -581,9 +603,9 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
                if (rsp) {
                        ret = qla25xx_delete_rsp_que(vha, rsp);
                        if (ret != QLA_SUCCESS) {
-                               qla_printk(KERN_WARNING, ha,
-                               "Couldn't delete rsp que %d\n",
-                               rsp->id);
+                               ql_log(ql_log_warn, vha, 0x00eb,
+                                   "Couldn't delete rsp que %d.\n",
+                                   rsp->id);
                                return ret;
                        }
                }
@@ -604,8 +626,8 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
 
        req = kzalloc(sizeof(struct req_que), GFP_KERNEL);
        if (req == NULL) {
-               qla_printk(KERN_WARNING, ha, "could not allocate memory"
-                       "for request que\n");
+               ql_log(ql_log_fatal, base_vha, 0x00d9,
+                   "Failed to allocate memory for request queue.\n");
                goto failed;
        }
 
@@ -614,8 +636,8 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
                        (req->length + 1) * sizeof(request_t),
                        &req->dma, GFP_KERNEL);
        if (req->ring == NULL) {
-               qla_printk(KERN_WARNING, ha,
-               "Memory Allocation failed - request_ring\n");
+               ql_log(ql_log_fatal, base_vha, 0x00da,
+                   "Failed to allocte memory for request_ring.\n");
                goto que_failed;
        }
 
@@ -623,8 +645,8 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
        que_id = find_first_zero_bit(ha->req_qid_map, ha->max_req_queues);
        if (que_id >= ha->max_req_queues) {
                mutex_unlock(&ha->vport_lock);
-               qla_printk(KERN_INFO, ha, "No resources to create "
-                        "additional request queue\n");
+               ql_log(ql_log_warn, base_vha, 0x00db,
+                   "No resources to create additional request queue.\n");
                goto que_failed;
        }
        set_bit(que_id, ha->req_qid_map);
@@ -633,6 +655,12 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
        req->vp_idx = vp_idx;
        req->qos = qos;
 
+       ql_dbg(ql_dbg_multiq, base_vha, 0xc002,
+           "queue_id=%d rid=%d vp_idx=%d qos=%d.\n",
+           que_id, req->rid, req->vp_idx, req->qos);
+       ql_dbg(ql_dbg_init, base_vha, 0x00dc,
+           "queue_id=%d rid=%d vp_idx=%d qos=%d.\n",
+           que_id, req->rid, req->vp_idx, req->qos);
        if (rsp_que < 0)
                req->rsp = NULL;
        else
@@ -645,6 +673,10 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
                options |= BIT_5;
        req->options = options;
 
+       ql_dbg(ql_dbg_multiq, base_vha, 0xc003,
+           "options=0x%x.\n", req->options);
+       ql_dbg(ql_dbg_init, base_vha, 0x00dd,
+           "options=0x%x.\n", req->options);
        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
                req->outstanding_cmds[cnt] = NULL;
        req->current_outstanding_cmd = 1;
@@ -656,10 +688,21 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
        reg = ISP_QUE_REG(ha, que_id);
        req->max_q_depth = ha->req_q_map[0]->max_q_depth;
        mutex_unlock(&ha->vport_lock);
+       ql_dbg(ql_dbg_multiq, base_vha, 0xc004,
+           "ring_ptr=%p ring_index=%d, "
+           "cnt=%d id=%d max_q_depth=%d.\n",
+           req->ring_ptr, req->ring_index,
+           req->cnt, req->id, req->max_q_depth);
+       ql_dbg(ql_dbg_init, base_vha, 0x00de,
+           "ring_ptr=%p ring_index=%d, "
+           "cnt=%d id=%d max_q_depth=%d.\n",
+           req->ring_ptr, req->ring_index, req->cnt,
+           req->id, req->max_q_depth);
 
        ret = qla25xx_init_req_que(base_vha, req);
        if (ret != QLA_SUCCESS) {
-               qla_printk(KERN_WARNING, ha, "%s failed\n", __func__);
+               ql_log(ql_log_fatal, base_vha, 0x00df,
+                   "%s failed.\n", __func__);
                mutex_lock(&ha->vport_lock);
                clear_bit(que_id, ha->req_qid_map);
                mutex_unlock(&ha->vport_lock);
@@ -700,8 +743,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
 
        rsp = kzalloc(sizeof(struct rsp_que), GFP_KERNEL);
        if (rsp == NULL) {
-               qla_printk(KERN_WARNING, ha, "could not allocate memory for"
-                               " response que\n");
+               ql_log(ql_log_warn, base_vha, 0x0066,
+                   "Failed to allocate memory for response queue.\n");
                goto failed;
        }
 
@@ -710,8 +753,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
                        (rsp->length + 1) * sizeof(response_t),
                        &rsp->dma, GFP_KERNEL);
        if (rsp->ring == NULL) {
-               qla_printk(KERN_WARNING, ha,
-               "Memory Allocation failed - response_ring\n");
+               ql_log(ql_log_warn, base_vha, 0x00e1,
+                   "Failed to allocate memory for response ring.\n");
                goto que_failed;
        }
 
@@ -719,8 +762,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
        que_id = find_first_zero_bit(ha->rsp_qid_map, ha->max_rsp_queues);
        if (que_id >= ha->max_rsp_queues) {
                mutex_unlock(&ha->vport_lock);
-               qla_printk(KERN_INFO, ha, "No resources to create "
-                        "additional response queue\n");
+               ql_log(ql_log_warn, base_vha, 0x00e2,
+                   "No resources to create additional request queue.\n");
                goto que_failed;
        }
        set_bit(que_id, ha->rsp_qid_map);
@@ -728,12 +771,16 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
        if (ha->flags.msix_enabled)
                rsp->msix = &ha->msix_entries[que_id + 1];
        else
-               qla_printk(KERN_WARNING, ha, "msix not enabled\n");
+               ql_log(ql_log_warn, base_vha, 0x00e3,
+                   "MSIX not enalbled.\n");
 
        ha->rsp_q_map[que_id] = rsp;
        rsp->rid = rid;
        rsp->vp_idx = vp_idx;
        rsp->hw = ha;
+       ql_dbg(ql_dbg_init, base_vha, 0x00e4,
+           "queue_id=%d rid=%d vp_idx=%d hw=%p.\n",
+           que_id, rsp->rid, rsp->vp_idx, rsp->hw);
        /* Use alternate PCI bus number */
        if (MSB(rsp->rid))
                options |= BIT_4;
@@ -750,6 +797,14 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
        rsp->rsp_q_in = &reg->isp25mq.rsp_q_in;
        rsp->rsp_q_out = &reg->isp25mq.rsp_q_out;
        mutex_unlock(&ha->vport_lock);
+       ql_dbg(ql_dbg_multiq, base_vha, 0xc00b,
+           "options=%x id=%d rsp_q_in=%p rsp_q_out=%p",
+           rsp->options, rsp->id, rsp->rsp_q_in,
+           rsp->rsp_q_out);
+       ql_dbg(ql_dbg_init, base_vha, 0x00e5,
+           "options=%x id=%d rsp_q_in=%p rsp_q_out=%p",
+           rsp->options, rsp->id, rsp->rsp_q_in,
+           rsp->rsp_q_out);
 
        ret = qla25xx_request_irq(rsp);
        if (ret)
@@ -757,7 +812,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
 
        ret = qla25xx_init_rsp_que(base_vha, rsp);
        if (ret != QLA_SUCCESS) {
-               qla_printk(KERN_WARNING, ha, "%s failed\n", __func__);
+               ql_log(ql_log_fatal, base_vha, 0x00e7,
+                   "%s failed.\n", __func__);
                mutex_lock(&ha->vport_lock);
                clear_bit(que_id, ha->rsp_qid_map);
                mutex_unlock(&ha->vport_lock);
index e1138bc..5cbf33a 100644 (file)
@@ -348,6 +348,7 @@ static void
 qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off)
 {
        u32 win_read;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        ha->crb_win = CRB_HI(*off);
        writel(ha->crb_win,
@@ -358,9 +359,10 @@ qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off)
         */
        win_read = RD_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase));
        if (win_read != ha->crb_win) {
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                   "%s: Written crbwin (0x%x) != Read crbwin (0x%x), "
-                   "off=0x%lx\n", __func__, ha->crb_win, win_read, *off));
+               ql_dbg(ql_dbg_p3p, vha, 0xb000,
+                   "%s: Written crbwin (0x%x) "
+                   "!= Read crbwin (0x%x), off=0x%lx.\n",
+                   ha->crb_win, win_read, *off);
        }
        *off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase;
 }
@@ -368,6 +370,7 @@ qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off)
 static inline unsigned long
 qla82xx_pci_set_crbwindow(struct qla_hw_data *ha, u64 off)
 {
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
        /* See if we are currently pointing to the region we want to use next */
        if ((off >= QLA82XX_CRB_PCIX_HOST) && (off < QLA82XX_CRB_DDR_NET)) {
                /* No need to change window. PCIX and PCIEregs are in both
@@ -398,9 +401,10 @@ qla82xx_pci_set_crbwindow(struct qla_hw_data *ha, u64 off)
                        return off;
        }
        /* strange address given */
-       qla_printk(KERN_WARNING, ha,
-               "%s: Warning: unm_nic_pci_set_crbwindow called with"
-               " an unknown address(%llx)\n", QLA2XXX_DRIVER_NAME, off);
+       ql_dbg(ql_dbg_p3p, vha, 0xb001,
+           "%x: Warning: unm_nic_pci_set_crbwindow "
+           "called with an unknown address(%llx).\n",
+           QLA2XXX_DRIVER_NAME, off);
        return off;
 }
 
@@ -563,6 +567,7 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
 {
        int window;
        u32 win_read;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET,
                QLA82XX_ADDR_DDR_NET_MAX)) {
@@ -574,8 +579,8 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
                win_read = qla82xx_rd_32(ha,
                        ha->mn_win_crb | QLA82XX_PCI_CRBSPACE);
                if ((win_read << 17) != window) {
-                       qla_printk(KERN_WARNING, ha,
-                           "%s: Written MNwin (0x%x) != Read MNwin (0x%x)\n",
+                       ql_dbg(ql_dbg_p3p, vha, 0xb003,
+                           "%s: Written MNwin (0x%x) != Read MNwin (0x%x).\n",
                            __func__, window, win_read);
                }
                addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_DDR_NET;
@@ -583,7 +588,7 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
                QLA82XX_ADDR_OCM0_MAX)) {
                unsigned int temp1;
                if ((addr & 0x00ff800) == 0xff800) {
-                       qla_printk(KERN_WARNING, ha,
+                       ql_log(ql_log_warn, vha, 0xb004,
                            "%s: QM access not handled.\n", __func__);
                        addr = -1UL;
                }
@@ -596,8 +601,8 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
                temp1 = ((window & 0x1FF) << 7) |
                    ((window & 0x0FFFE0000) >> 17);
                if (win_read != temp1) {
-                       qla_printk(KERN_WARNING, ha,
-                           "%s: Written OCMwin (0x%x) != Read OCMwin (0x%x)\n",
+                       ql_log(ql_log_warn, vha, 0xb005,
+                           "%s: Written OCMwin (0x%x) != Read OCMwin (0x%x).\n",
                            __func__, temp1, win_read);
                }
                addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_OCM0_2M;
@@ -612,8 +617,8 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
                win_read = qla82xx_rd_32(ha,
                        ha->ms_win_crb | QLA82XX_PCI_CRBSPACE);
                if (win_read != window) {
-                       qla_printk(KERN_WARNING, ha,
-                           "%s: Written MSwin (0x%x) != Read MSwin (0x%x)\n",
+                       ql_log(ql_log_warn, vha, 0xb006,
+                           "%s: Written MSwin (0x%x) != Read MSwin (0x%x).\n",
                            __func__, window, win_read);
                }
                addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_QDR_NET;
@@ -624,9 +629,9 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
                 */
                if ((qla82xx_pci_set_window_warning_count++ < 8) ||
                    (qla82xx_pci_set_window_warning_count%64 == 0)) {
-                       qla_printk(KERN_WARNING, ha,
-                           "%s: Warning:%s Unknown address range!\n", __func__,
-                           QLA2XXX_DRIVER_NAME);
+                       ql_log(ql_log_warn, vha, 0xb007,
+                           "%s: Warning:%s Unknown address range!.\n",
+                           __func__, QLA2XXX_DRIVER_NAME);
                }
                addr = -1UL;
        }
@@ -671,6 +676,7 @@ static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha,
        uint8_t         *mem_ptr = NULL;
        unsigned long   mem_base;
        unsigned long   mem_page;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        write_lock_irqsave(&ha->hw_lock, flags);
 
@@ -682,9 +688,10 @@ static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha,
        if ((start == -1UL) ||
                (qla82xx_pci_is_same_window(ha, off + size - 1) == 0)) {
                write_unlock_irqrestore(&ha->hw_lock, flags);
-               qla_printk(KERN_ERR, ha,
-                       "%s out of bound pci memory access. "
-                       "offset is 0x%llx\n", QLA2XXX_DRIVER_NAME, off);
+               ql_log(ql_log_fatal, vha, 0xb008,
+                   "%s out of bound pci memory "
+                   "access, offset is 0x%llx.\n",
+                   QLA2XXX_DRIVER_NAME, off);
                return -1;
        }
 
@@ -741,6 +748,7 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha,
        uint8_t         *mem_ptr = NULL;
        unsigned long   mem_base;
        unsigned long   mem_page;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        write_lock_irqsave(&ha->hw_lock, flags);
 
@@ -752,9 +760,10 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha,
        if ((start == -1UL) ||
                (qla82xx_pci_is_same_window(ha, off + size - 1) == 0)) {
                write_unlock_irqrestore(&ha->hw_lock, flags);
-               qla_printk(KERN_ERR, ha,
-                       "%s out of bound pci memory access. "
-                       "offset is 0x%llx\n", QLA2XXX_DRIVER_NAME, off);
+               ql_log(ql_log_fatal, vha, 0xb009,
+                   "%s out of bount memory "
+                   "access, offset is 0x%llx.\n",
+                   QLA2XXX_DRIVER_NAME, off);
                return -1;
        }
 
@@ -855,15 +864,16 @@ qla82xx_wait_rom_busy(struct qla_hw_data *ha)
 {
        long timeout = 0;
        long done = 0 ;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        while (done == 0) {
                done = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_STATUS);
                done &= 4;
                timeout++;
                if (timeout >= rom_max_timeout) {
-                       DEBUG(qla_printk(KERN_INFO, ha,
-                               "%s: Timeout reached waiting for rom busy",
-                               QLA2XXX_DRIVER_NAME));
+                       ql_dbg(ql_dbg_p3p, vha, 0xb00a,
+                           "%s: Timeout reached waiting for rom busy.\n",
+                           QLA2XXX_DRIVER_NAME);
                        return -1;
                }
        }
@@ -875,15 +885,16 @@ qla82xx_wait_rom_done(struct qla_hw_data *ha)
 {
        long timeout = 0;
        long done = 0 ;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        while (done == 0) {
                done = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_STATUS);
                done &= 2;
                timeout++;
                if (timeout >= rom_max_timeout) {
-                       DEBUG(qla_printk(KERN_INFO, ha,
-                               "%s: Timeout reached  waiting for rom done",
-                               QLA2XXX_DRIVER_NAME));
+                       ql_dbg(ql_dbg_p3p, vha, 0xb00b,
+                           "%s: Timeout reached waiting for rom done.\n",
+                           QLA2XXX_DRIVER_NAME);
                        return -1;
                }
        }
@@ -893,15 +904,16 @@ qla82xx_wait_rom_done(struct qla_hw_data *ha)
 static int
 qla82xx_do_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
 {
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
+
        qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr);
        qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
        qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 3);
        qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, 0xb);
        qla82xx_wait_rom_busy(ha);
        if (qla82xx_wait_rom_done(ha)) {
-               qla_printk(KERN_WARNING, ha,
-                       "%s: Error waiting for rom done\n",
-                       QLA2XXX_DRIVER_NAME);
+               ql_log(ql_log_fatal, vha, 0x00ba,
+                   "Error waiting for rom done.\n");
                return -1;
        }
        /* Reset abyte_cnt and dummy_byte_cnt */
@@ -917,6 +929,7 @@ static int
 qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
 {
        int ret, loops = 0;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        while ((qla82xx_rom_lock(ha) != 0) && (loops < 50000)) {
                udelay(100);
@@ -924,9 +937,8 @@ qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
                loops++;
        }
        if (loops >= 50000) {
-               qla_printk(KERN_INFO, ha,
-                       "%s: qla82xx_rom_lock failed\n",
-                       QLA2XXX_DRIVER_NAME);
+               ql_log(ql_log_fatal, vha, 0x00b9,
+                   "Failed to aquire SEM2 lock.\n");
                return -1;
        }
        ret = qla82xx_do_rom_fast_read(ha, addr, valp);
@@ -937,11 +949,12 @@ qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
 static int
 qla82xx_read_status_reg(struct qla_hw_data *ha, uint32_t *val)
 {
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
        qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_RDSR);
        qla82xx_wait_rom_busy(ha);
        if (qla82xx_wait_rom_done(ha)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Error waiting for rom done\n");
+               ql_log(ql_log_warn, vha, 0xb00c,
+                   "Error waiting for rom done.\n");
                return -1;
        }
        *val = qla82xx_rd_32(ha, QLA82XX_ROMUSB_ROM_RDATA);
@@ -955,6 +968,7 @@ qla82xx_flash_wait_write_finish(struct qla_hw_data *ha)
        uint32_t done = 1 ;
        uint32_t val;
        int ret = 0;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0);
        while ((done != 0) && (ret == 0)) {
@@ -964,8 +978,8 @@ qla82xx_flash_wait_write_finish(struct qla_hw_data *ha)
                udelay(10);
                cond_resched();
                if (timeout >= 50000) {
-                       qla_printk(KERN_WARNING, ha,
-                           "Timeout reached  waiting for write finish");
+                       ql_log(ql_log_warn, vha, 0xb00d,
+                           "Timeout reached waiting for write finish.\n");
                        return -1;
                }
        }
@@ -992,13 +1006,14 @@ qla82xx_flash_set_write_enable(struct qla_hw_data *ha)
 static int
 qla82xx_write_status_reg(struct qla_hw_data *ha, uint32_t val)
 {
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
        if (qla82xx_flash_set_write_enable(ha))
                return -1;
        qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_WDATA, val);
        qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, 0x1);
        if (qla82xx_wait_rom_done(ha)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Error waiting for rom done\n");
+               ql_log(ql_log_warn, vha, 0xb00e,
+                   "Error waiting for rom done.\n");
                return -1;
        }
        return qla82xx_flash_wait_write_finish(ha);
@@ -1007,10 +1022,11 @@ qla82xx_write_status_reg(struct qla_hw_data *ha, uint32_t val)
 static int
 qla82xx_write_disable_flash(struct qla_hw_data *ha)
 {
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
        qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WRDI);
        if (qla82xx_wait_rom_done(ha)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Error waiting for rom done\n");
+               ql_log(ql_log_warn, vha, 0xb00f,
+                   "Error waiting for rom done.\n");
                return -1;
        }
        return 0;
@@ -1020,13 +1036,16 @@ static int
 ql82xx_rom_lock_d(struct qla_hw_data *ha)
 {
        int loops = 0;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
+
        while ((qla82xx_rom_lock(ha) != 0) && (loops < 50000)) {
                udelay(100);
                cond_resched();
                loops++;
        }
        if (loops >= 50000) {
-               qla_printk(KERN_WARNING, ha, "ROM lock failed\n");
+               ql_log(ql_log_warn, vha, 0xb010,
+                   "ROM lock failed.\n");
                return -1;
        }
        return 0;;
@@ -1037,10 +1056,12 @@ qla82xx_write_flash_dword(struct qla_hw_data *ha, uint32_t flashaddr,
        uint32_t data)
 {
        int ret = 0;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        ret = ql82xx_rom_lock_d(ha);
        if (ret < 0) {
-               qla_printk(KERN_WARNING, ha, "ROM Lock failed\n");
+               ql_log(ql_log_warn, vha, 0xb011,
+                   "ROM lock failed.\n");
                return ret;
        }
 
@@ -1053,8 +1074,8 @@ qla82xx_write_flash_dword(struct qla_hw_data *ha, uint32_t flashaddr,
        qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_PP);
        qla82xx_wait_rom_busy(ha);
        if (qla82xx_wait_rom_done(ha)) {
-               qla_printk(KERN_WARNING, ha,
-                       "Error waiting for rom done\n");
+               ql_log(ql_log_warn, vha, 0xb012,
+                   "Error waiting for rom done.\n");
                ret = -1;
                goto done_write;
        }
@@ -1159,8 +1180,8 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
         */
        if (qla82xx_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafeUL ||
            qla82xx_rom_fast_read(ha, 4, &n) != 0) {
-               qla_printk(KERN_WARNING, ha,
-                   "[ERROR] Reading crb_init area: n: %08x\n", n);
+               ql_log(ql_log_fatal, vha, 0x006e,
+                   "Error Reading crb_init area: n: %08x.\n", n);
                return -1;
        }
 
@@ -1172,20 +1193,18 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
 
        /* number of addr/value pair should not exceed 1024 enteries */
        if (n  >= 1024) {
-               qla_printk(KERN_WARNING, ha,
-                   "%s: %s:n=0x%x [ERROR] Card flash not initialized.\n",
-                   QLA2XXX_DRIVER_NAME, __func__, n);
+               ql_log(ql_log_fatal, vha, 0x0071,
+                   "Card flash not initialized:n=0x%x.\n", n);
                return -1;
        }
 
-       qla_printk(KERN_INFO, ha,
-           "%s: %d CRB init values found in ROM.\n", QLA2XXX_DRIVER_NAME, n);
+       ql_log(ql_log_info, vha, 0x0072,
+           "%d CRB init values found in ROM.\n", n);
 
        buf = kmalloc(n * sizeof(struct crb_addr_pair), GFP_KERNEL);
        if (buf == NULL) {
-               qla_printk(KERN_WARNING, ha,
-                   "%s: [ERROR] Unable to malloc memory.\n",
-                   QLA2XXX_DRIVER_NAME);
+               ql_log(ql_log_fatal, vha, 0x010c,
+                   "Unable to allocate memory.\n");
                return -1;
        }
 
@@ -1236,9 +1255,8 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
                        continue;
 
                if (off == ADDR_ERROR) {
-                       qla_printk(KERN_WARNING, ha,
-                           "%s: [ERROR] Unknown addr: 0x%08lx\n",
-                           QLA2XXX_DRIVER_NAME, buf[i].addr);
+                       ql_log(ql_log_fatal, vha, 0x0116,
+                           "Unknow addr: 0x%08lx.\n", buf[i].addr);
                        continue;
                }
 
@@ -1370,7 +1388,7 @@ qla82xx_pci_mem_write_2M(struct qla_hw_data *ha,
                if (j >= MAX_CTL_CHECK) {
                        if (printk_ratelimit())
                                dev_err(&ha->pdev->dev,
-                                   "failed to write through agent\n");
+                                   "failed to write through agent.\n");
                        ret = -1;
                        break;
                }
@@ -1460,7 +1478,7 @@ qla82xx_pci_mem_read_2M(struct qla_hw_data *ha,
                if (j >= MAX_CTL_CHECK) {
                        if (printk_ratelimit())
                                dev_err(&ha->pdev->dev,
-                                   "failed to read through agent\n");
+                                   "failed to read through agent.\n");
                        break;
                }
 
@@ -1633,17 +1651,15 @@ qla82xx_iospace_config(struct qla_hw_data *ha)
        uint32_t len = 0;
 
        if (pci_request_regions(ha->pdev, QLA2XXX_DRIVER_NAME)) {
-               qla_printk(KERN_WARNING, ha,
-                       "Failed to reserve selected regions (%s)\n",
-                       pci_name(ha->pdev));
+               ql_log_pci(ql_log_fatal, ha->pdev, 0x000c,
+                   "Failed to reserver selected regions.\n");
                goto iospace_error_exit;
        }
 
        /* Use MMIO operations for all accesses. */
        if (!(pci_resource_flags(ha->pdev, 0) & IORESOURCE_MEM)) {
-               qla_printk(KERN_ERR, ha,
-                       "region #0 not an MMIO resource (%s), aborting\n",
-                       pci_name(ha->pdev));
+               ql_log_pci(ql_log_fatal, ha->pdev, 0x000d,
+                   "Region #0 not an MMIO resource, aborting.\n");
                goto iospace_error_exit;
        }
 
@@ -1651,9 +1667,8 @@ qla82xx_iospace_config(struct qla_hw_data *ha)
        ha->nx_pcibase =
            (unsigned long)ioremap(pci_resource_start(ha->pdev, 0), len);
        if (!ha->nx_pcibase) {
-               qla_printk(KERN_ERR, ha,
-                   "cannot remap pcibase MMIO (%s), aborting\n",
-                   pci_name(ha->pdev));
+               ql_log_pci(ql_log_fatal, ha->pdev, 0x000e,
+                   "Cannot remap pcibase MMIO, aborting.\n");
                pci_release_regions(ha->pdev);
                goto iospace_error_exit;
        }
@@ -1667,9 +1682,8 @@ qla82xx_iospace_config(struct qla_hw_data *ha)
                    (unsigned long)ioremap((pci_resource_start(ha->pdev, 4) +
                    (ha->pdev->devfn << 12)), 4);
                if (!ha->nxdb_wr_ptr) {
-                       qla_printk(KERN_ERR, ha,
-                           "cannot remap MMIO (%s), aborting\n",
-                           pci_name(ha->pdev));
+                       ql_log_pci(ql_log_fatal, ha->pdev, 0x000f,
+                           "Cannot remap MMIO, aborting.\n");
                        pci_release_regions(ha->pdev);
                        goto iospace_error_exit;
                }
@@ -1687,6 +1701,16 @@ qla82xx_iospace_config(struct qla_hw_data *ha)
 
        ha->max_req_queues = ha->max_rsp_queues = 1;
        ha->msix_count = ha->max_rsp_queues + 1;
+       ql_dbg_pci(ql_dbg_multiq, ha->pdev, 0xc006,
+           "nx_pci_base=%p iobase=%p "
+           "max_req_queues=%d msix_count=%d.\n",
+           ha->nx_pcibase, ha->iobase,
+           ha->max_req_queues, ha->msix_count);
+       ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0010,
+           "nx_pci_base=%p iobase=%p "
+           "max_req_queues=%d msix_count=%d.\n",
+           ha->nx_pcibase, ha->iobase,
+           ha->max_req_queues, ha->msix_count);
        return 0;
 
 iospace_error_exit:
@@ -1712,6 +1736,9 @@ qla82xx_pci_config(scsi_qla_host_t *vha)
        pci_set_master(ha->pdev);
        ret = pci_set_mwi(ha->pdev);
        ha->chip_revision = ha->pdev->revision;
+       ql_dbg(ql_dbg_init, vha, 0x0043,
+           "Chip revision:%ld.\n",
+           ha->chip_revision);
        return 0;
 }
 
@@ -1877,6 +1904,7 @@ qla82xx_check_cmdpeg_state(struct qla_hw_data *ha)
 {
        u32 val = 0;
        int retries = 60;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        do {
                read_lock(&ha->hw_lock);
@@ -1892,15 +1920,15 @@ qla82xx_check_cmdpeg_state(struct qla_hw_data *ha)
                default:
                        break;
                }
-               qla_printk(KERN_WARNING, ha,
-                       "CRB_CMDPEG_STATE: 0x%x and retries: 0x%x\n",
-                       val, retries);
+               ql_log(ql_log_info, vha, 0x00a8,
+                   "CRB_CMDPEG_STATE: 0x%x and retries:0x%x.\n",
+                   val, retries);
 
                msleep(500);
 
        } while (--retries);
 
-       qla_printk(KERN_INFO, ha,
+       ql_log(ql_log_fatal, vha, 0x00a9,
            "Cmd Peg initialization failed: 0x%x.\n", val);
 
        val = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_PEGTUNE_DONE);
@@ -1915,6 +1943,7 @@ qla82xx_check_rcvpeg_state(struct qla_hw_data *ha)
 {
        u32 val = 0;
        int retries = 60;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        do {
                read_lock(&ha->hw_lock);
@@ -1930,17 +1959,16 @@ qla82xx_check_rcvpeg_state(struct qla_hw_data *ha)
                default:
                        break;
                }
-
-               qla_printk(KERN_WARNING, ha,
-                       "CRB_RCVPEG_STATE: 0x%x and retries: 0x%x\n",
-                       val, retries);
+               ql_log(ql_log_info, vha, 0x00ab,
+                   "CRB_RCVPEG_STATE: 0x%x and retries: 0x%x.\n",
+                   val, retries);
 
                msleep(500);
 
        } while (--retries);
 
-       qla_printk(KERN_INFO, ha,
-               "Rcv Peg initialization failed: 0x%x.\n", val);
+       ql_log(ql_log_fatal, vha, 0x00ac,
+           "Rcv Peg initializatin failed: 0x%x.\n", val);
        read_lock(&ha->hw_lock);
        qla82xx_wr_32(ha, CRB_RCVPEG_STATE, PHAN_INITIALIZE_FAILED);
        read_unlock(&ha->hw_lock);
@@ -1989,13 +2017,11 @@ qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
        }
 
        if (ha->mcp) {
-               DEBUG3_11(printk(KERN_INFO "%s(%ld): "
-                       "Got mailbox completion. cmd=%x.\n",
-                       __func__, vha->host_no, ha->mcp->mb[0]));
+               ql_dbg(ql_dbg_async, vha, 0x5052,
+                   "Got mailbox completion. cmd=%x.\n", ha->mcp->mb[0]);
        } else {
-               qla_printk(KERN_INFO, ha,
-                       "%s(%ld): MBX pointer ERROR!\n",
-                       __func__, vha->host_no);
+               ql_dbg(ql_dbg_async, vha, 0x5053,
+                   "MBX pointer ERROR.\n");
        }
 }
 
@@ -2019,13 +2045,13 @@ qla82xx_intr_handler(int irq, void *dev_id)
        int status = 0, status1 = 0;
        unsigned long   flags;
        unsigned long   iter;
-       uint32_t        stat;
+       uint32_t        stat = 0;
        uint16_t        mb[4];
 
        rsp = (struct rsp_que *) dev_id;
        if (!rsp) {
                printk(KERN_INFO
-                       "%s(): NULL response queue pointer\n", __func__);
+                       "%s(): NULL response queue pointer.\n", __func__);
                return IRQ_NONE;
        }
        ha = rsp->hw;
@@ -2075,9 +2101,9 @@ qla82xx_intr_handler(int irq, void *dev_id)
                                qla24xx_process_response_queue(vha, rsp);
                                break;
                        default:
-                               DEBUG2(printk("scsi(%ld): "
-                                       " Unrecognized interrupt type (%d).\n",
-                                       vha->host_no, stat & 0xff));
+                               ql_dbg(ql_dbg_async, vha, 0x5054,
+                                   "Unrecognized interrupt type (%d).\n",
+                                   stat & 0xff);
                                break;
                        }
                }
@@ -2089,8 +2115,8 @@ qla82xx_intr_handler(int irq, void *dev_id)
 
 #ifdef QL_DEBUG_LEVEL_17
        if (!irq && ha->flags.eeh_busy)
-               qla_printk(KERN_WARNING, ha,
-                   "isr: status %x, cmd_flags %lx, mbox_int %x, stat %x\n",
+               ql_log(ql_log_warn, vha, 0x503d,
+                   "isr:status %x, cmd_flags %lx, mbox_int %x, stat %x.\n",
                    status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat);
 #endif
 
@@ -2111,13 +2137,13 @@ qla82xx_msix_default(int irq, void *dev_id)
        struct device_reg_82xx __iomem *reg;
        int status = 0;
        unsigned long flags;
-       uint32_t stat;
+       uint32_t stat = 0;
        uint16_t mb[4];
 
        rsp = (struct rsp_que *) dev_id;
        if (!rsp) {
                printk(KERN_INFO
-                       "%s(): NULL response queue pointer\n", __func__);
+                       "%s(): NULL response queue pointer.\n", __func__);
                return IRQ_NONE;
        }
        ha = rsp->hw;
@@ -2149,9 +2175,9 @@ qla82xx_msix_default(int irq, void *dev_id)
                                qla24xx_process_response_queue(vha, rsp);
                                break;
                        default:
-                               DEBUG2(printk("scsi(%ld): "
-                                       " Unrecognized interrupt type (%d).\n",
-                                       vha->host_no, stat & 0xff));
+                               ql_dbg(ql_dbg_async, vha, 0x5041,
+                                   "Unrecognized interrupt type (%d).\n",
+                                   stat & 0xff);
                                break;
                        }
                }
@@ -2162,9 +2188,9 @@ qla82xx_msix_default(int irq, void *dev_id)
 
 #ifdef QL_DEBUG_LEVEL_17
        if (!irq && ha->flags.eeh_busy)
-               qla_printk(KERN_WARNING, ha,
-                       "isr: status %x, cmd_flags %lx, mbox_int %x, stat %x\n",
-                       status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat);
+               ql_log(ql_log_warn, vha, 0x5044,
+                   "isr:status %x, cmd_flags %lx, mbox_int %x, stat %x.\n",
+                   status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat);
 #endif
 
        if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
@@ -2186,7 +2212,7 @@ qla82xx_msix_rsp_q(int irq, void *dev_id)
        rsp = (struct rsp_que *) dev_id;
        if (!rsp) {
                printk(KERN_INFO
-                       "%s(): NULL response queue pointer\n", __func__);
+                       "%s(): NULL response queue pointer.\n", __func__);
                return IRQ_NONE;
        }
 
@@ -2215,7 +2241,7 @@ qla82xx_poll(int irq, void *dev_id)
        rsp = (struct rsp_que *) dev_id;
        if (!rsp) {
                printk(KERN_INFO
-                       "%s(): NULL response queue pointer\n", __func__);
+                       "%s(): NULL response queue pointer.\n", __func__);
                return;
        }
        ha = rsp->hw;
@@ -2245,9 +2271,9 @@ qla82xx_poll(int irq, void *dev_id)
                        qla24xx_process_response_queue(vha, rsp);
                        break;
                default:
-                       DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
-                               "(%d).\n",
-                               vha->host_no, stat & 0xff));
+                       ql_dbg(ql_dbg_p3p, vha, 0xb013,
+                           "Unrecognized interrupt type (%d).\n",
+                           stat * 0xff);
                        break;
                }
        }
@@ -2347,9 +2373,8 @@ qla82xx_set_rst_ready(struct qla_hw_data *ha)
                drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
        }
        drv_state |= (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
-       qla_printk(KERN_INFO, ha,
-               "%s(%ld):drv_state = 0x%x\n",
-               __func__, vha->host_no, drv_state);
+       ql_log(ql_log_info, vha, 0x00bb,
+           "drv_state = 0x%x.\n", drv_state);
        qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state);
 }
 
@@ -2392,8 +2417,8 @@ qla82xx_load_fw(scsi_qla_host_t *vha)
        struct qla_hw_data *ha = vha->hw;
 
        if (qla82xx_pinit_from_rom(vha) != QLA_SUCCESS) {
-               qla_printk(KERN_ERR, ha,
-                       "%s: Error during CRB Initialization\n", __func__);
+               ql_log(ql_log_fatal, vha, 0x009f,
+                   "Error during CRB initialization.\n");
                return QLA_FUNCTION_FAILED;
        }
        udelay(500);
@@ -2411,27 +2436,27 @@ qla82xx_load_fw(scsi_qla_host_t *vha)
        if (ql2xfwloadbin == 2)
                goto try_blob_fw;
 
-       qla_printk(KERN_INFO, ha,
-               "Attempting to load firmware from flash\n");
+       ql_log(ql_log_info, vha, 0x00a0,
+           "Attempting to load firmware from flash.\n");
 
        if (qla82xx_fw_load_from_flash(ha) == QLA_SUCCESS) {
-               qla_printk(KERN_ERR, ha,
-                   "Firmware loaded successfully from flash\n");
+               ql_log(ql_log_info, vha, 0x00a1,
+                   "Firmware loaded successully from flash.\n");
                return QLA_SUCCESS;
        } else {
-               qla_printk(KERN_ERR, ha,
-                   "Firmware load from flash failed\n");
+               ql_log(ql_log_warn, vha, 0x0108,
+                   "Firmware load from flash failed.\n");
        }
 
 try_blob_fw:
-       qla_printk(KERN_INFO, ha,
-           "Attempting to load firmware from blob\n");
+       ql_log(ql_log_info, vha, 0x00a2,
+           "Attempting to load firmware from blob.\n");
 
        /* Load firmware blob. */
        blob = ha->hablob = qla2x00_request_firmware(vha);
        if (!blob) {
-               qla_printk(KERN_ERR, ha,
-                       "Firmware image not present.\n");
+               ql_log(ql_log_fatal, vha, 0x00a3,
+                   "Firmware image not preset.\n");
                goto fw_load_failed;
        }
 
@@ -2441,20 +2466,19 @@ try_blob_fw:
                /* Fallback to URI format */
                if (qla82xx_validate_firmware_blob(vha,
                        QLA82XX_UNIFIED_ROMIMAGE)) {
-                       qla_printk(KERN_ERR, ha,
-                               "No valid firmware image found!!!");
+                       ql_log(ql_log_fatal, vha, 0x00a4,
+                           "No valid firmware image found.\n");
                        return QLA_FUNCTION_FAILED;
                }
        }
 
        if (qla82xx_fw_load_from_blob(ha) == QLA_SUCCESS) {
-               qla_printk(KERN_ERR, ha,
-                       "%s: Firmware loaded successfully "
-                       " from binary blob\n", __func__);
+               ql_log(ql_log_info, vha, 0x00a5,
+                   "Firmware loaded successfully from binary blob.\n");
                return QLA_SUCCESS;
        } else {
-               qla_printk(KERN_ERR, ha,
-                   "Firmware load failed from binary blob\n");
+               ql_log(ql_log_fatal, vha, 0x00a6,
+                   "Firmware load failed for binary blob.\n");
                blob->fw = NULL;
                blob = NULL;
                goto fw_load_failed;
@@ -2486,15 +2510,15 @@ qla82xx_start_firmware(scsi_qla_host_t *vha)
        qla82xx_wr_32(ha, QLA82XX_PEG_HALT_STATUS2, 0);
 
        if (qla82xx_load_fw(vha) != QLA_SUCCESS) {
-               qla_printk(KERN_INFO, ha,
-                       "%s: Error trying to start fw!\n", __func__);
+               ql_log(ql_log_fatal, vha, 0x00a7,
+                   "Error trying to start fw.\n");
                return QLA_FUNCTION_FAILED;
        }
 
        /* Handshake with the card before we register the devices. */
        if (qla82xx_check_cmdpeg_state(ha) != QLA_SUCCESS) {
-               qla_printk(KERN_INFO, ha,
-                       "%s: Error during card handshake!\n", __func__);
+               ql_log(ql_log_fatal, vha, 0x00aa,
+                   "Error during card handshake.\n");
                return QLA_FUNCTION_FAILED;
        }
 
@@ -2663,8 +2687,11 @@ qla82xx_start_scsi(srb_t *sp)
        /* Send marker if required */
        if (vha->marker_needed != 0) {
                if (qla2x00_marker(vha, req,
-                       rsp, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS)
+                       rsp, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS) {
+                       ql_log(ql_log_warn, vha, 0x300c,
+                           "qla2x00_marker failed for cmd=%p.\n", cmd);
                        return QLA_FUNCTION_FAILED;
+               }
                vha->marker_needed = 0;
        }
 
@@ -2701,8 +2728,13 @@ qla82xx_start_scsi(srb_t *sp)
                uint16_t i;
 
                more_dsd_lists = qla82xx_calc_dsd_lists(tot_dsds);
-               if ((more_dsd_lists + ha->gbl_dsd_inuse) >= NUM_DSD_CHAIN)
+               if ((more_dsd_lists + ha->gbl_dsd_inuse) >= NUM_DSD_CHAIN) {
+                       ql_dbg(ql_dbg_io, vha, 0x300d,
+                           "Num of DSD list %d is than %d for cmd=%p.\n",
+                           more_dsd_lists + ha->gbl_dsd_inuse, NUM_DSD_CHAIN,
+                           cmd);
                        goto queuing_error;
+               }
 
                if (more_dsd_lists <= ha->gbl_dsd_avail)
                        goto sufficient_dsds;
@@ -2711,13 +2743,20 @@ qla82xx_start_scsi(srb_t *sp)
 
                for (i = 0; i < more_dsd_lists; i++) {
                        dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC);
-                       if (!dsd_ptr)
+                       if (!dsd_ptr) {
+                               ql_log(ql_log_fatal, vha, 0x300e,
+                                   "Failed to allocate memory for dsd_dma "
+                                   "for cmd=%p.\n", cmd);
                                goto queuing_error;
+                       }
 
                        dsd_ptr->dsd_addr = dma_pool_alloc(ha->dl_dma_pool,
                                GFP_ATOMIC, &dsd_ptr->dsd_list_dma);
                        if (!dsd_ptr->dsd_addr) {
                                kfree(dsd_ptr);
+                               ql_log(ql_log_fatal, vha, 0x300f,
+                                   "Failed to allocate memory for dsd_addr "
+                                   "for cmd=%p.\n", cmd);
                                goto queuing_error;
                        }
                        list_add_tail(&dsd_ptr->list, &ha->gbl_dsd_list);
@@ -2742,17 +2781,16 @@ sufficient_dsds:
 
                ctx = sp->ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC);
                if (!sp->ctx) {
-                       DEBUG(printk(KERN_INFO
-                               "%s(%ld): failed to allocate"
-                               " ctx.\n", __func__, vha->host_no));
+                       ql_log(ql_log_fatal, vha, 0x3010,
+                           "Failed to allocate ctx for cmd=%p.\n", cmd);
                        goto queuing_error;
                }
                memset(ctx, 0, sizeof(struct ct6_dsd));
                ctx->fcp_cmnd = dma_pool_alloc(ha->fcp_cmnd_dma_pool,
                        GFP_ATOMIC, &ctx->fcp_cmnd_dma);
                if (!ctx->fcp_cmnd) {
-                       DEBUG2_3(printk("%s(%ld): failed to allocate"
-                               " fcp_cmnd.\n", __func__, vha->host_no));
+                       ql_log(ql_log_fatal, vha, 0x3011,
+                           "Failed to allocate fcp_cmnd for cmd=%p.\n", cmd);
                        goto queuing_error_fcp_cmnd;
                }
 
@@ -2766,6 +2804,9 @@ sufficient_dsds:
                                /* SCSI command bigger than 16 bytes must be
                                 * multiple of 4
                                 */
+                               ql_log(ql_log_warn, vha, 0x3012,
+                                   "scsi cmd len %d not multiple of 4 "
+                                   "for cmd=%p.\n", cmd->cmd_len, cmd);
                                goto queuing_error_fcp_cmnd;
                        }
                        ctx->fcp_cmnd_len = 12 + cmd->cmd_len + 4;
@@ -2845,7 +2886,7 @@ sufficient_dsds:
                cmd_pkt->entry_status = (uint8_t) rsp->id;
        } else {
                struct cmd_type_7 *cmd_pkt;
-               req_cnt = qla24xx_calc_iocbs(tot_dsds);
+               req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
                if (req->cnt < (req_cnt + 2)) {
                        cnt = (uint16_t)RD_REG_DWORD_RELAXED(
                            &reg->req_q_out[0]);
@@ -2979,8 +3020,8 @@ qla82xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
        /* Dword reads to flash. */
        for (i = 0; i < length/4; i++, faddr += 4) {
                if (qla82xx_rom_fast_read(ha, faddr, &val)) {
-                       qla_printk(KERN_WARNING, ha,
-                           "Do ROM fast read failed\n");
+                       ql_log(ql_log_warn, vha, 0x0106,
+                           "Do ROM fast read failed.\n");
                        goto done_read;
                }
                dwptr[i] = __constant_cpu_to_le32(val);
@@ -2994,10 +3035,12 @@ qla82xx_unprotect_flash(struct qla_hw_data *ha)
 {
        int ret;
        uint32_t val;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        ret = ql82xx_rom_lock_d(ha);
        if (ret < 0) {
-               qla_printk(KERN_WARNING, ha, "ROM Lock failed\n");
+               ql_log(ql_log_warn, vha, 0xb014,
+                   "ROM Lock failed.\n");
                return ret;
        }
 
@@ -3013,7 +3056,8 @@ qla82xx_unprotect_flash(struct qla_hw_data *ha)
        }
 
        if (qla82xx_write_disable_flash(ha) != 0)
-               qla_printk(KERN_WARNING, ha, "Write disable failed\n");
+               ql_log(ql_log_warn, vha, 0xb015,
+                   "Write disable failed.\n");
 
 done_unprotect:
        qla82xx_rom_unlock(ha);
@@ -3025,10 +3069,12 @@ qla82xx_protect_flash(struct qla_hw_data *ha)
 {
        int ret;
        uint32_t val;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        ret = ql82xx_rom_lock_d(ha);
        if (ret < 0) {
-               qla_printk(KERN_WARNING, ha, "ROM Lock failed\n");
+               ql_log(ql_log_warn, vha, 0xb016,
+                   "ROM Lock failed.\n");
                return ret;
        }
 
@@ -3040,10 +3086,12 @@ qla82xx_protect_flash(struct qla_hw_data *ha)
        /* LOCK all sectors */
        ret = qla82xx_write_status_reg(ha, val);
        if (ret < 0)
-               qla_printk(KERN_WARNING, ha, "Write status register failed\n");
+               ql_log(ql_log_warn, vha, 0xb017,
+                   "Write status register failed.\n");
 
        if (qla82xx_write_disable_flash(ha) != 0)
-               qla_printk(KERN_WARNING, ha, "Write disable failed\n");
+               ql_log(ql_log_warn, vha, 0xb018,
+                   "Write disable failed.\n");
 done_protect:
        qla82xx_rom_unlock(ha);
        return ret;
@@ -3053,10 +3101,12 @@ static int
 qla82xx_erase_sector(struct qla_hw_data *ha, int addr)
 {
        int ret = 0;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        ret = ql82xx_rom_lock_d(ha);
        if (ret < 0) {
-               qla_printk(KERN_WARNING, ha, "ROM Lock failed\n");
+               ql_log(ql_log_warn, vha, 0xb019,
+                   "ROM Lock failed.\n");
                return ret;
        }
 
@@ -3066,8 +3116,8 @@ qla82xx_erase_sector(struct qla_hw_data *ha, int addr)
        qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_SE);
 
        if (qla82xx_wait_rom_done(ha)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Error waiting for rom done\n");
+               ql_log(ql_log_warn, vha, 0xb01a,
+                   "Error waiting for rom done.\n");
                ret = -1;
                goto done;
        }
@@ -3110,10 +3160,10 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr,
                optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
                    &optrom_dma, GFP_KERNEL);
                if (!optrom) {
-                       qla_printk(KERN_DEBUG, ha,
-                               "Unable to allocate memory for optrom "
-                               "burst write (%x KB).\n",
-                               OPTROM_BURST_SIZE / 1024);
+                       ql_log(ql_log_warn, vha, 0xb01b,
+                           "Unable to allocate memory "
+                           "for optron burst write (%x KB).\n",
+                           OPTROM_BURST_SIZE / 1024);
                }
        }
 
@@ -3122,8 +3172,8 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr,
 
        ret = qla82xx_unprotect_flash(ha);
        if (ret) {
-               qla_printk(KERN_WARNING, ha,
-                       "Unable to unprotect flash for update.\n");
+               ql_log(ql_log_warn, vha, 0xb01c,
+                   "Unable to unprotect flash for update.\n");
                goto write_done;
        }
 
@@ -3133,9 +3183,9 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr,
 
                        ret = qla82xx_erase_sector(ha, faddr);
                        if (ret) {
-                               DEBUG9(qla_printk(KERN_ERR, ha,
-                                   "Unable to erase sector: "
-                                   "address=%x.\n", faddr));
+                               ql_log(ql_log_warn, vha, 0xb01d,
+                                   "Unable to erase sector: address=%x.\n",
+                                   faddr);
                                break;
                        }
                }
@@ -3149,12 +3199,12 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr,
                            (ha->flash_data_off | faddr),
                            OPTROM_BURST_DWORDS);
                        if (ret != QLA_SUCCESS) {
-                               qla_printk(KERN_WARNING, ha,
+                               ql_log(ql_log_warn, vha, 0xb01e,
                                    "Unable to burst-write optrom segment "
                                    "(%x/%x/%llx).\n", ret,
                                    (ha->flash_data_off | faddr),
                                    (unsigned long long)optrom_dma);
-                               qla_printk(KERN_WARNING, ha,
+                               ql_log(ql_log_warn, vha, 0xb01f,
                                    "Reverting to slow-write.\n");
 
                                dma_free_coherent(&ha->pdev->dev,
@@ -3171,16 +3221,16 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr,
                ret = qla82xx_write_flash_dword(ha, faddr,
                    cpu_to_le32(*dwptr));
                if (ret) {
-                       DEBUG9(printk(KERN_DEBUG "%s(%ld) Unable to program"
-                           "flash address=%x data=%x.\n", __func__,
-                           ha->host_no, faddr, *dwptr));
+                       ql_dbg(ql_dbg_p3p, vha, 0xb020,
+                           "Unable to program flash address=%x data=%x.\n",
+                           faddr, *dwptr);
                        break;
                }
        }
 
        ret = qla82xx_protect_flash(ha);
        if (ret)
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0xb021,
                    "Unable to protect flash after update.\n");
 write_done:
        if (optrom)
@@ -3244,9 +3294,12 @@ qla82xx_start_iocbs(srb_t *sp)
 
 void qla82xx_rom_lock_recovery(struct qla_hw_data *ha)
 {
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
+
        if (qla82xx_rom_lock(ha))
                /* Someone else is holding the lock. */
-               qla_printk(KERN_INFO, ha, "Resetting rom_lock\n");
+               ql_log(ql_log_info, vha, 0xb022,
+                   "Resetting rom_lock.\n");
 
        /*
         * Either we got the lock, or someone
@@ -3313,7 +3366,8 @@ qla82xx_device_bootstrap(scsi_qla_host_t *vha)
 
 dev_initialize:
        /* set to DEV_INITIALIZING */
-       qla_printk(KERN_INFO, ha, "HW State: INITIALIZING\n");
+       ql_log(ql_log_info, vha, 0x009e,
+           "HW State: INITIALIZING.\n");
        qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_INITIALIZING);
 
        /* Driver that sets device state to initializating sets IDC version */
@@ -3324,14 +3378,16 @@ dev_initialize:
        qla82xx_idc_lock(ha);
 
        if (rval != QLA_SUCCESS) {
-               qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
+               ql_log(ql_log_fatal, vha, 0x00ad,
+                   "HW State: FAILED.\n");
                qla82xx_clear_drv_active(ha);
                qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_FAILED);
                return rval;
        }
 
 dev_ready:
-       qla_printk(KERN_INFO, ha, "HW State: READY\n");
+       ql_log(ql_log_info, vha, 0x00ae,
+           "HW State: READY.\n");
        qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_READY);
 
        return QLA_SUCCESS;
@@ -3376,15 +3432,15 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha)
                        /* quiescence timeout, other functions didn't ack
                         * changing the state to DEV_READY
                         */
-                       qla_printk(KERN_INFO, ha,
-                           "%s: QUIESCENT TIMEOUT\n", QLA2XXX_DRIVER_NAME);
-                       qla_printk(KERN_INFO, ha,
-                           "DRV_ACTIVE:%d DRV_STATE:%d\n", drv_active,
-                           drv_state);
+                       ql_log(ql_log_info, vha, 0xb023,
+                           "%s : QUIESCENT TIMEOUT.\n", QLA2XXX_DRIVER_NAME);
+                       ql_log(ql_log_info, vha, 0xb024,
+                           "DRV_ACTIVE:%d DRV_STATE:%d.\n",
+                           drv_active, drv_state);
                        qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
-                                               QLA82XX_DEV_READY);
-                       qla_printk(KERN_INFO, ha,
-                           "HW State: DEV_READY\n");
+                           QLA82XX_DEV_READY);
+                       ql_log(ql_log_info, vha, 0xb025,
+                           "HW State: DEV_READY.\n");
                        qla82xx_idc_unlock(ha);
                        qla2x00_perform_loop_resync(vha);
                        qla82xx_idc_lock(ha);
@@ -3404,7 +3460,8 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha)
        dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
        /* everyone acked so set the state to DEV_QUIESCENCE */
        if (dev_state == QLA82XX_DEV_NEED_QUIESCENT) {
-               qla_printk(KERN_INFO, ha, "HW State: DEV_QUIESCENT\n");
+               ql_log(ql_log_info, vha, 0xb026,
+                   "HW State: DEV_QUIESCENT.\n");
                qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_QUIESCENT);
        }
 }
@@ -3441,7 +3498,8 @@ qla82xx_dev_failed_handler(scsi_qla_host_t *vha)
        struct qla_hw_data *ha = vha->hw;
 
        /* Disable the board */
-       qla_printk(KERN_INFO, ha, "Disabling the board\n");
+       ql_log(ql_log_fatal, vha, 0x00b8,
+           "Disabling the board.\n");
 
        qla82xx_idc_lock(ha);
        qla82xx_clear_drv_active(ha);
@@ -3492,8 +3550,8 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
 
        while (drv_state != drv_active) {
                if (time_after_eq(jiffies, reset_timeout)) {
-                       qla_printk(KERN_INFO, ha,
-                               "%s: RESET TIMEOUT!\n", QLA2XXX_DRIVER_NAME);
+                       ql_log(ql_log_warn, vha, 0x00b5,
+                           "Reset timeout.\n");
                        break;
                }
                qla82xx_idc_unlock(ha);
@@ -3504,12 +3562,15 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
        }
 
        dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
-       qla_printk(KERN_INFO, ha, "3:Device state is 0x%x = %s\n", dev_state,
-               dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
+       ql_log(ql_log_info, vha, 0x00b6,
+           "Device state is 0x%x = %s.\n",
+           dev_state,
+           dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
 
        /* Force to DEV_COLD unless someone else is starting a reset */
        if (dev_state != QLA82XX_DEV_INITIALIZING) {
-               qla_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n");
+               ql_log(ql_log_info, vha, 0x00b7,
+                   "HW State: COLD/RE-INIT.\n");
                qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD);
        }
 }
@@ -3523,8 +3584,12 @@ qla82xx_check_fw_alive(scsi_qla_host_t *vha)
        fw_heartbeat_counter = qla82xx_rd_32(vha->hw,
                QLA82XX_PEG_ALIVE_COUNTER);
        /* all 0xff, assume AER/EEH in progress, ignore */
-       if (fw_heartbeat_counter == 0xffffffff)
+       if (fw_heartbeat_counter == 0xffffffff) {
+               ql_dbg(ql_dbg_timer, vha, 0x6003,
+                   "FW heartbeat counter is 0xffffffff, "
+                   "returning status=%d.\n", status);
                return status;
+       }
        if (vha->fw_heartbeat_counter == fw_heartbeat_counter) {
                vha->seconds_since_last_heartbeat++;
                /* FW not alive after 2 seconds */
@@ -3535,6 +3600,9 @@ qla82xx_check_fw_alive(scsi_qla_host_t *vha)
        } else
                vha->seconds_since_last_heartbeat = 0;
        vha->fw_heartbeat_counter = fw_heartbeat_counter;
+       if (status)
+               ql_dbg(ql_dbg_timer, vha, 0x6004,
+                   "Returning status=%d.\n", status);
        return status;
 }
 
@@ -3565,8 +3633,10 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
 
        dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
        old_dev_state = dev_state;
-       qla_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state,
-               dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
+       ql_log(ql_log_info, vha, 0x009b,
+           "Device state is 0x%x = %s.\n",
+           dev_state,
+           dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
 
        /* wait for 30 seconds for device to go ready */
        dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ);
@@ -3574,9 +3644,8 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
        while (1) {
 
                if (time_after_eq(jiffies, dev_init_timeout)) {
-                       DEBUG(qla_printk(KERN_INFO, ha,
-                               "%s: device init failed!\n",
-                               QLA2XXX_DRIVER_NAME));
+                       ql_log(ql_log_fatal, vha, 0x009c,
+                           "Device init failed.\n");
                        rval = QLA_FUNCTION_FAILED;
                        break;
                }
@@ -3586,10 +3655,11 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
                        old_dev_state = dev_state;
                }
                if (loopcount < 5) {
-                       qla_printk(KERN_INFO, ha,
-                           "2:Device state is 0x%x = %s\n", dev_state,
-                           dev_state < MAX_STATES ?
-                           qdev_state[dev_state] : "Unknown");
+                       ql_log(ql_log_info, vha, 0x009d,
+                           "Device state is 0x%x = %s.\n",
+                           dev_state,
+                           dev_state < MAX_STATES ? qdev_state[dev_state] :
+                           "Unknown");
                }
 
                switch (dev_state) {
@@ -3656,29 +3726,26 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
                dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
                if (dev_state == QLA82XX_DEV_NEED_RESET &&
                    !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) {
-                       qla_printk(KERN_WARNING, ha,
-                           "scsi(%ld) %s: Adapter reset needed!\n",
-                               vha->host_no, __func__);
+                       ql_log(ql_log_warn, vha, 0x6001,
+                           "Adapter reset needed.\n");
                        set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
                        qla2xxx_wake_dpc(vha);
                } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
                        !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) {
-                       DEBUG(qla_printk(KERN_INFO, ha,
-                               "scsi(%ld) %s - detected quiescence needed\n",
-                               vha->host_no, __func__));
+                       ql_log(ql_log_warn, vha, 0x6002,
+                           "Quiescent needed.\n");
                        set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
                        qla2xxx_wake_dpc(vha);
                } else {
                        if (qla82xx_check_fw_alive(vha)) {
                                halt_status = qla82xx_rd_32(ha,
                                    QLA82XX_PEG_HALT_STATUS1);
-                               qla_printk(KERN_INFO, ha,
-                                   "scsi(%ld): %s, Dumping hw/fw registers:\n "
-                                   " PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n "
-                                   " PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n "
-                                   " PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n "
-                                   " PEG_NET_4_PC: 0x%x\n",
-                                   vha->host_no, __func__, halt_status,
+                               ql_dbg(ql_dbg_timer, vha, 0x6005,
+                                   "dumping hw/fw registers:.\n "
+                                   " PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,.\n "
+                                   " PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,.\n "
+                                   " PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,.\n "
+                                   " PEG_NET_4_PC: 0x%x.\n", halt_status,
                                    qla82xx_rd_32(ha, QLA82XX_PEG_HALT_STATUS2),
                                    qla82xx_rd_32(ha,
                                            QLA82XX_CRB_PEG_NET_0 + 0x3c),
@@ -3694,9 +3761,8 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
                                        set_bit(ISP_UNRECOVERABLE,
                                            &vha->dpc_flags);
                                } else {
-                                       qla_printk(KERN_INFO, ha,
-                                           "scsi(%ld): %s - detect abort needed\n",
-                                           vha->host_no, __func__);
+                                       ql_log(ql_log_info, vha, 0x6006,
+                                           "Detect abort  needed.\n");
                                        set_bit(ISP_ABORT_NEEDED,
                                            &vha->dpc_flags);
                                }
@@ -3704,10 +3770,10 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
                                ha->flags.isp82xx_fw_hung = 1;
                                if (ha->flags.mbox_busy) {
                                        ha->flags.mbox_int = 1;
-                                       DEBUG2(qla_printk(KERN_ERR, ha,
-                                           "scsi(%ld) Due to fw hung, doing "
+                                       ql_log(ql_log_warn, vha, 0x6007,
+                                           "Due to FW hung, doing "
                                            "premature completion of mbx "
-                                           "command\n", vha->host_no));
+                                           "command.\n");
                                        if (test_bit(MBX_INTR_WAIT,
                                            &ha->mbx_cmd_flags))
                                                complete(&ha->mbx_intr_comp);
@@ -3742,9 +3808,8 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
        uint32_t dev_state;
 
        if (vha->device_flags & DFLG_DEV_FAILED) {
-               qla_printk(KERN_WARNING, ha,
-                       "%s(%ld): Device in failed state, "
-                       "Exiting.\n", __func__, vha->host_no);
+               ql_log(ql_log_warn, vha, 0x8024,
+                   "Device in failed state, exiting.\n");
                return QLA_SUCCESS;
        }
        ha->flags.isp82xx_reset_hdlr_active = 1;
@@ -3752,13 +3817,14 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
        qla82xx_idc_lock(ha);
        dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
        if (dev_state == QLA82XX_DEV_READY) {
-               qla_printk(KERN_INFO, ha, "HW State: NEED RESET\n");
+               ql_log(ql_log_info, vha, 0x8025,
+                   "HW State: NEED RESET.\n");
                qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
                        QLA82XX_DEV_NEED_RESET);
        } else
-               qla_printk(KERN_INFO, ha, "HW State: %s\n",
-                       dev_state < MAX_STATES ?
-                       qdev_state[dev_state] : "Unknown");
+               ql_log(ql_log_info, vha, 0x8026,
+                   "Hw State: %s.\n", dev_state < MAX_STATES ?
+                   qdev_state[dev_state] : "Unknown");
        qla82xx_idc_unlock(ha);
 
        rval = qla82xx_device_state_handler(vha);
@@ -3777,9 +3843,9 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
                vha->flags.online = 1;
                if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
                        if (ha->isp_abort_cnt == 0) {
-                               qla_printk(KERN_WARNING, ha,
-                                   "ISP error recovery failed - "
-                                   "board disabled\n");
+                               ql_log(ql_log_warn, vha, 0x8027,
+                                   "ISP error recover failed - board "
+                                   "disabled.\n");
                                /*
                                 * The next call disables the board
                                 * completely.
@@ -3791,16 +3857,16 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
                                rval = QLA_SUCCESS;
                        } else { /* schedule another ISP abort */
                                ha->isp_abort_cnt--;
-                               DEBUG(qla_printk(KERN_INFO, ha,
-                                   "qla%ld: ISP abort - retry remaining %d\n",
-                                   vha->host_no, ha->isp_abort_cnt));
+                               ql_log(ql_log_warn, vha, 0x8036,
+                                   "ISP abort - retry remaining %d.\n",
+                                   ha->isp_abort_cnt);
                                rval = QLA_FUNCTION_FAILED;
                        }
                } else {
                        ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT;
-                       DEBUG(qla_printk(KERN_INFO, ha,
-                           "(%ld): ISP error recovery - retrying (%d) "
-                           "more times\n", vha->host_no, ha->isp_abort_cnt));
+                       ql_dbg(ql_dbg_taskm, vha, 0x8029,
+                           "ISP error recovery - retrying (%d) more times.\n",
+                           ha->isp_abort_cnt);
                        set_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
                        rval = QLA_FUNCTION_FAILED;
                }
@@ -3872,8 +3938,8 @@ int qla2x00_wait_for_fcoe_ctx_reset(scsi_qla_host_t *vha)
                        break;
                }
        }
-       DEBUG2(printk(KERN_INFO
-           "%s status=%d\n", __func__, status));
+       ql_dbg(ql_dbg_p3p, vha, 0xb027,
+           "%s status=%d.\n", status);
 
        return status;
 }
@@ -3902,6 +3968,9 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
                        }
                }
        }
+       ql_dbg(ql_dbg_init, vha, 0x00b0,
+           "Entered %s fw_hung=%d.\n",
+           __func__, ha->flags.isp82xx_fw_hung);
 
        /* Abort all commands gracefully if fw NOT hung */
        if (!ha->flags.isp82xx_fw_hung) {
@@ -3922,13 +3991,13 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
                                                spin_unlock_irqrestore(
                                                    &ha->hardware_lock, flags);
                                                if (ha->isp_ops->abort_command(sp)) {
-                                                       qla_printk(KERN_INFO, ha,
-                                                           "scsi(%ld): mbx abort command failed in %s\n",
-                                                           vha->host_no, __func__);
+                                                       ql_log(ql_log_info, vha,
+                                                           0x00b1,
+                                                           "mbx abort failed.\n");
                                                } else {
-                                                       qla_printk(KERN_INFO, ha,
-                                                           "scsi(%ld): mbx abort command success in %s\n",
-                                                           vha->host_no, __func__);
+                                                       ql_log(ql_log_info, vha,
+                                                           0x00b2,
+                                                           "mbx abort success.\n");
                                                }
                                                spin_lock_irqsave(&ha->hardware_lock, flags);
                                        }
@@ -3940,8 +4009,9 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
                /* Wait for pending cmds (physical and virtual) to complete */
                if (!qla2x00_eh_wait_for_pending_commands(vha, 0, 0,
                    WAIT_HOST) == QLA_SUCCESS) {
-                       DEBUG2(qla_printk(KERN_INFO, ha,
-                           "Done wait for pending commands\n"));
+                       ql_dbg(ql_dbg_init, vha, 0x00b3,
+                           "Done wait for "
+                           "pending commands.\n");
                }
        }
 }
index f461925..e02df27 100644 (file)
@@ -35,6 +35,10 @@ static struct kmem_cache *srb_cachep;
  * CT6 CTX allocation cache
  */
 static struct kmem_cache *ctx_cachep;
+/*
+ * error level for logging
+ */
+int ql_errlev = ql_log_all;
 
 int ql2xlogintimeout = 20;
 module_param(ql2xlogintimeout, int, S_IRUGO);
@@ -69,8 +73,17 @@ MODULE_PARM_DESC(ql2xallocfwdump,
 int ql2xextended_error_logging;
 module_param(ql2xextended_error_logging, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(ql2xextended_error_logging,
-               "Option to enable extended error logging, "
-               "Default is 0 - no logging. 1 - log errors.");
+               "Option to enable extended error logging,\n"
+               "\t\tDefault is 0 - no logging.  0x40000000 - Module Init & Probe.\n"
+               "\t\t0x20000000 - Mailbox Cmnds. 0x10000000 - Device Discovery.\n"
+               "\t\t0x08000000 - IO tracing.    0x04000000 - DPC Thread.\n"
+               "\t\t0x02000000 - Async events.  0x01000000 - Timer routines.\n"
+               "\t\t0x00800000 - User space.    0x00400000 - Task Management.\n"
+               "\t\t0x00200000 - AER/EEH.       0x00100000 - Multi Q.\n"
+               "\t\t0x00080000 - P3P Specific.  0x00040000 - Virtual Port.\n"
+               "\t\t0x00020000 - Buffer Dump.   0x00010000 - Misc.\n"
+               "\t\t0x7fffffff - For enabling all logs, can be too many logs.\n"
+               "\t\tDo LOGICAL OR of the value to enable more than one level");
 
 int ql2xshiftctondsd = 6;
 module_param(ql2xshiftctondsd, int, S_IRUGO);
@@ -128,8 +141,8 @@ MODULE_PARM_DESC(ql2xmultique_tag,
 int ql2xfwloadbin;
 module_param(ql2xfwloadbin, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xfwloadbin,
-               "Option to specify location from which to load ISP firmware:\n"
-               " 2 -- load firmware via the request_firmware() (hotplug)\n"
+               "Option to specify location from which to load ISP firmware:.\n"
+               " 2 -- load firmware via the request_firmware() (hotplug).\n"
                "      interface.\n"
                " 1 -- load firmware from flash.\n"
                " 0 -- use default semantics.\n");
@@ -143,7 +156,7 @@ MODULE_PARM_DESC(ql2xetsenable,
 int ql2xdbwr = 1;
 module_param(ql2xdbwr, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xdbwr,
-       "Option to specify scheme for request queue posting\n"
+       "Option to specify scheme for request queue posting.\n"
        " 0 -- Regular doorbell.\n"
        " 1 -- CAMRAM doorbell (faster).\n");
 
@@ -168,7 +181,7 @@ MODULE_PARM_DESC(ql2xasynctmfenable,
 int ql2xdontresethba;
 module_param(ql2xdontresethba, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xdontresethba,
-       "Option to specify reset behaviour\n"
+       "Option to specify reset behaviour.\n"
        " 0 (Default) -- Reset on failure.\n"
        " 1 -- Do not reset on failure.\n");
 
@@ -247,8 +260,11 @@ static inline void
 qla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval)
 {
        /* Currently used for 82XX only. */
-       if (vha->device_flags & DFLG_DEV_FAILED)
+       if (vha->device_flags & DFLG_DEV_FAILED) {
+               ql_dbg(ql_dbg_timer, vha, 0x600d,
+                   "Device in a failed state, returning.\n");
                return;
+       }
 
        mod_timer(&vha->timer, jiffies + interval * HZ);
 }
@@ -273,19 +289,20 @@ static void qla2x00_sp_free_dma(srb_t *);
 /* -------------------------------------------------------------------------- */
 static int qla2x00_alloc_queues(struct qla_hw_data *ha)
 {
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
        ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues,
                                GFP_KERNEL);
        if (!ha->req_q_map) {
-               qla_printk(KERN_WARNING, ha,
-                       "Unable to allocate memory for request queue ptrs\n");
+               ql_log(ql_log_fatal, vha, 0x003b,
+                   "Unable to allocate memory for request queue ptrs.\n");
                goto fail_req_map;
        }
 
        ha->rsp_q_map = kzalloc(sizeof(struct rsp_que *) * ha->max_rsp_queues,
                                GFP_KERNEL);
        if (!ha->rsp_q_map) {
-               qla_printk(KERN_WARNING, ha,
-                       "Unable to allocate memory for response queue ptrs\n");
+               ql_log(ql_log_fatal, vha, 0x003c,
+                   "Unable to allocate memory for response queue ptrs.\n");
                goto fail_rsp_map;
        }
        set_bit(0, ha->rsp_qid_map);
@@ -349,8 +366,8 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha)
        struct qla_hw_data *ha = vha->hw;
 
        if (!(ha->fw_attributes & BIT_6)) {
-               qla_printk(KERN_INFO, ha,
-                       "Firmware is not multi-queue capable\n");
+               ql_log(ql_log_warn, vha, 0x00d8,
+                   "Firmware is not multi-queue capable.\n");
                goto fail;
        }
        if (ql2xmultique_tag) {
@@ -359,8 +376,8 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha)
                req = qla25xx_create_req_que(ha, options, 0, 0, -1,
                        QLA_DEFAULT_QUE_QOS);
                if (!req) {
-                       qla_printk(KERN_WARNING, ha,
-                               "Can't create request queue\n");
+                       ql_log(ql_log_warn, vha, 0x00e0,
+                           "Failed to create request queue.\n");
                        goto fail;
                }
                ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1);
@@ -369,17 +386,20 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha)
                for (ques = 1; ques < ha->max_rsp_queues; ques++) {
                        ret = qla25xx_create_rsp_que(ha, options, 0, 0, req);
                        if (!ret) {
-                               qla_printk(KERN_WARNING, ha,
-                                       "Response Queue create failed\n");
+                               ql_log(ql_log_warn, vha, 0x00e8,
+                                   "Failed to create response queue.\n");
                                goto fail2;
                        }
                }
                ha->flags.cpu_affinity_enabled = 1;
-
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                       "CPU affinity mode enabled, no. of response"
-                       " queues:%d, no. of request queues:%d\n",
-                       ha->max_rsp_queues, ha->max_req_queues));
+               ql_dbg(ql_dbg_multiq, vha, 0xc007,
+                   "CPU affinity mode enalbed, "
+                   "no. of response queues:%d no. of request queues:%d.\n",
+                   ha->max_rsp_queues, ha->max_req_queues);
+               ql_dbg(ql_dbg_init, vha, 0x00e9,
+                   "CPU affinity mode enalbed, "
+                   "no. of response queues:%d no. of request queues:%d.\n",
+                   ha->max_rsp_queues, ha->max_req_queues);
        }
        return 0;
 fail2:
@@ -526,8 +546,11 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
        struct qla_hw_data *ha = vha->hw;
 
        sp = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);
-       if (!sp)
+       if (!sp) {
+               ql_log(ql_log_warn, vha, 0x3006,
+                   "Memory allocation failed for sp.\n");
                return sp;
+       }
 
        atomic_set(&sp->ref_count, 1);
        sp->fcport = fcport;
@@ -551,30 +574,43 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
        int rval;
 
        if (ha->flags.eeh_busy) {
-               if (ha->flags.pci_channel_io_perm_failure)
+               if (ha->flags.pci_channel_io_perm_failure) {
+                       ql_dbg(ql_dbg_io, vha, 0x3001,
+                           "PCI Channel IO permanent failure, exiting "
+                           "cmd=%p.\n", cmd);
                        cmd->result = DID_NO_CONNECT << 16;
-               else
+               } else {
+                       ql_dbg(ql_dbg_io, vha, 0x3002,
+                           "EEH_Busy, Requeuing the cmd=%p.\n", cmd);
                        cmd->result = DID_REQUEUE << 16;
+               }
                goto qc24_fail_command;
        }
 
        rval = fc_remote_port_chkready(rport);
        if (rval) {
                cmd->result = rval;
+               ql_dbg(ql_dbg_io, vha, 0x3003,
+                   "fc_remote_port_chkready failed for cmd=%p, rval=0x%x.\n",
+                   cmd, rval);
                goto qc24_fail_command;
        }
 
        if (!vha->flags.difdix_supported &&
                scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) {
-                       DEBUG2(qla_printk(KERN_ERR, ha,
-                           "DIF Cap Not Reg, fail DIF capable cmd's:%x\n",
-                           cmd->cmnd[0]));
+                       ql_dbg(ql_dbg_io, vha, 0x3004,
+                           "DIF Cap not reg, fail DIF capable cmd's:%p.\n",
+                           cmd);
                        cmd->result = DID_NO_CONNECT << 16;
                        goto qc24_fail_command;
        }
        if (atomic_read(&fcport->state) != FCS_ONLINE) {
                if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
                        atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
+                       ql_dbg(ql_dbg_io, vha, 0x3005,
+                           "Returning DNC, fcport_state=%d loop_state=%d.\n",
+                           atomic_read(&fcport->state),
+                           atomic_read(&base_vha->loop_state));
                        cmd->result = DID_NO_CONNECT << 16;
                        goto qc24_fail_command;
                }
@@ -586,8 +622,11 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
                goto qc24_host_busy;
 
        rval = ha->isp_ops->start_scsi(sp);
-       if (rval != QLA_SUCCESS)
+       if (rval != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_io, vha, 0x3013,
+                   "Start scsi failed rval=%d for cmd=%p.\n", rval, cmd);
                goto qc24_host_busy_free_sp;
+       }
 
        return 0;
 
@@ -630,7 +669,8 @@ qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
        int ret = QLA_SUCCESS;
 
        if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) {
-               DEBUG17(qla_printk(KERN_WARNING, ha, "return:eh_wait\n"));
+               ql_dbg(ql_dbg_taskm, vha, 0x8005,
+                   "Return:eh_wait.\n");
                return ret;
        }
 
@@ -723,7 +763,8 @@ qla2x00_wait_for_reset_ready(scsi_qla_host_t *vha)
        else
                return_status = QLA_FUNCTION_FAILED;
 
-       DEBUG2(printk("%s return_status=%d\n", __func__, return_status));
+       ql_dbg(ql_dbg_taskm, vha, 0x8019,
+           "%s return status=%d.\n", __func__, return_status);
 
        return return_status;
 }
@@ -831,10 +872,14 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
        int wait = 0;
        struct qla_hw_data *ha = vha->hw;
 
+       ql_dbg(ql_dbg_taskm, vha, 0x8000,
+           "Entered %s for cmd=%p.\n", __func__, cmd);
        if (!CMD_SP(cmd))
                return SUCCESS;
 
        ret = fc_block_scsi_eh(cmd);
+       ql_dbg(ql_dbg_taskm, vha, 0x8001,
+           "Return value of fc_block_scsi_eh=%d.\n", ret);
        if (ret != 0)
                return ret;
        ret = SUCCESS;
@@ -849,20 +894,19 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
                return SUCCESS;
        }
 
-       DEBUG2(printk("%s(%ld): aborting sp %p from RISC.",
-           __func__, vha->host_no, sp));
+       ql_dbg(ql_dbg_taskm, vha, 0x8002,
+           "Aborting sp=%p cmd=%p from RISC ", sp, cmd);
 
        /* Get a reference to the sp and drop the lock.*/
        sp_get(sp);
 
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
        if (ha->isp_ops->abort_command(sp)) {
-               DEBUG2(printk("%s(%ld): abort_command "
-               "mbx failed.\n", __func__, vha->host_no));
-               ret = FAILED;
+               ql_dbg(ql_dbg_taskm, vha, 0x8003,
+                   "Abort command mbx failed for cmd=%p.\n", cmd);
        } else {
-               DEBUG3(printk("%s(%ld): abort_command "
-               "mbx success.\n", __func__, vha->host_no));
+               ql_dbg(ql_dbg_taskm, vha, 0x8004,
+                   "Abort command mbx success.\n");
                wait = 1;
        }
        qla2x00_sp_compl(ha, sp);
@@ -870,16 +914,14 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
        /* Wait for the command to be returned. */
        if (wait) {
                if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) {
-                       qla_printk(KERN_ERR, ha,
-                           "scsi(%ld:%d:%d): Abort handler timed out -- %x.\n",
-                           vha->host_no, id, lun, ret);
+                       ql_log(ql_log_warn, vha, 0x8006,
+                           "Abort handler timed out for cmd=%p.\n", cmd);
                        ret = FAILED;
                }
        }
 
-       qla_printk(KERN_INFO, ha,
-           "scsi(%ld:%d:%d): Abort command issued -- %d %x.\n",
-           vha->host_no, id, lun, wait, ret);
+       ql_log(ql_log_info, vha, 0x801c,
+           "Abort command issued --  %d %x.\n", wait, ret);
 
        return ret;
 }
@@ -947,40 +989,59 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
        int err;
 
-       if (!fcport)
+       if (!fcport) {
+               ql_log(ql_log_warn, vha, 0x8007,
+                   "fcport is NULL.\n");
                return FAILED;
+       }
 
        err = fc_block_scsi_eh(cmd);
+       ql_dbg(ql_dbg_taskm, vha, 0x8008,
+           "fc_block_scsi_eh ret=%d.\n", err);
        if (err != 0)
                return err;
 
-       qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET ISSUED.\n",
-           vha->host_no, cmd->device->id, cmd->device->lun, name);
+       ql_log(ql_log_info, vha, 0x8009,
+           "%s RESET ISSUED for id %d lun %d cmd=%p.\n", name,
+           cmd->device->id, cmd->device->lun, cmd);
 
        err = 0;
-       if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
+       if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
+               ql_log(ql_log_warn, vha, 0x800a,
+                   "Wait for hba online failed for cmd=%p.\n", cmd);
                goto eh_reset_failed;
+       }
        err = 1;
-       if (qla2x00_wait_for_loop_ready(vha) != QLA_SUCCESS)
+       if (qla2x00_wait_for_loop_ready(vha) != QLA_SUCCESS) {
+               ql_log(ql_log_warn, vha, 0x800b,
+                   "Wait for loop ready failed for cmd=%p.\n", cmd);
                goto eh_reset_failed;
+       }
        err = 2;
        if (do_reset(fcport, cmd->device->lun, cmd->request->cpu + 1)
-               != QLA_SUCCESS)
+               != QLA_SUCCESS) {
+               ql_log(ql_log_warn, vha, 0x800c,
+                   "do_reset failed for cmd=%p.\n", cmd);
                goto eh_reset_failed;
+       }
        err = 3;
        if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id,
-           cmd->device->lun, type) != QLA_SUCCESS)
+           cmd->device->lun, type) != QLA_SUCCESS) {
+               ql_log(ql_log_warn, vha, 0x800d,
+                   "wait for peding cmds failed for cmd=%p.\n", cmd);
                goto eh_reset_failed;
+       }
 
-       qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
-           vha->host_no, cmd->device->id, cmd->device->lun, name);
+       ql_log(ql_log_info, vha, 0x800e,
+           "%s RESET SUCCEEDED for id %d lun %d cmd=%p.\n", name,
+           cmd->device->id, cmd->device->lun, cmd);
 
        return SUCCESS;
 
 eh_reset_failed:
-       qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET FAILED: %s.\n"
-           , vha->host_no, cmd->device->id, cmd->device->lun, name,
-           reset_errors[err]);
+       ql_log(ql_log_info, vha, 0x800f,
+           "%s RESET FAILED: %s for id %d lun %d cmd=%p.\n", name,
+           reset_errors[err], cmd->device->id, cmd->device->lun);
        return FAILED;
 }
 
@@ -1030,19 +1091,25 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
        id = cmd->device->id;
        lun = cmd->device->lun;
 
-       if (!fcport)
+       if (!fcport) {
+               ql_log(ql_log_warn, vha, 0x8010,
+                   "fcport is NULL.\n");
                return ret;
+       }
 
        ret = fc_block_scsi_eh(cmd);
+       ql_dbg(ql_dbg_taskm, vha, 0x8011,
+           "fc_block_scsi_eh ret=%d.\n", ret);
        if (ret != 0)
                return ret;
        ret = FAILED;
 
-       qla_printk(KERN_INFO, vha->hw,
-           "scsi(%ld:%d:%d): BUS RESET ISSUED.\n", vha->host_no, id, lun);
+       ql_log(ql_log_info, vha, 0x8012,
+           "BUS RESET ISSUED for id %d lun %d.\n", id, lun);
 
        if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
-               DEBUG2(printk("%s failed:board disabled\n",__func__));
+               ql_log(ql_log_fatal, vha, 0x8013,
+                   "Wait for hba online failed board disabled.\n");
                goto eh_bus_reset_done;
        }
 
@@ -1055,12 +1122,15 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
 
        /* Flush outstanding commands. */
        if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) !=
-           QLA_SUCCESS)
+           QLA_SUCCESS) {
+               ql_log(ql_log_warn, vha, 0x8014,
+                   "Wait for pending commands failed.\n");
                ret = FAILED;
+       }
 
 eh_bus_reset_done:
-       qla_printk(KERN_INFO, vha->hw, "%s: reset %s\n", __func__,
-           (ret == FAILED) ? "failed" : "succeeded");
+       ql_log(ql_log_warn, vha, 0x802b,
+           "BUS RESET %s.\n", (ret == FAILED) ? "FAILED" : "SUCCEDED");
 
        return ret;
 }
@@ -1093,16 +1163,21 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
        id = cmd->device->id;
        lun = cmd->device->lun;
 
-       if (!fcport)
+       if (!fcport) {
+               ql_log(ql_log_warn, vha, 0x8016,
+                   "fcport is NULL.\n");
                return ret;
+       }
 
        ret = fc_block_scsi_eh(cmd);
+       ql_dbg(ql_dbg_taskm, vha, 0x8017,
+           "fc_block_scsi_eh ret=%d.\n", ret);
        if (ret != 0)
                return ret;
        ret = FAILED;
 
-       qla_printk(KERN_INFO, ha,
-           "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun);
+       ql_log(ql_log_info, vha, 0x8018,
+           "ADAPTER RESET ISSUED for id %d lun %d.\n", id, lun);
 
        if (qla2x00_wait_for_reset_ready(vha) != QLA_SUCCESS)
                goto eh_host_reset_lock;
@@ -1137,8 +1212,11 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
                        /* failed. schedule dpc to try */
                        set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
 
-                       if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
+                       if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
+                               ql_log(ql_log_warn, vha, 0x802a,
+                                   "wait for hba online failed.\n");
                                goto eh_host_reset_lock;
+                       }
                }
                clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
        }
@@ -1149,7 +1227,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
                ret = SUCCESS;
 
 eh_host_reset_lock:
-       qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
+       qla_printk(KERN_INFO, ha, "%s: reset %s.\n", __func__,
            (ret == FAILED) ? "failed" : "succeeded");
 
        return ret;
@@ -1179,9 +1257,9 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
 
                        ret = ha->isp_ops->target_reset(fcport, 0, 0);
                        if (ret != QLA_SUCCESS) {
-                               DEBUG2_3(printk("%s(%ld): bus_reset failed: "
-                                   "target_reset=%d d_id=%x.\n", __func__,
-                                   vha->host_no, ret, fcport->d_id.b24));
+                               ql_dbg(ql_dbg_taskm, vha, 0x802c,
+                                   "Bus Reset failed: Target Reset=%d "
+                                   "d_id=%x.\n", ret, fcport->d_id.b24);
                        }
                }
        }
@@ -1189,9 +1267,8 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
        if (ha->flags.enable_lip_full_login && !IS_QLA8XXX_TYPE(ha)) {
                ret = qla2x00_full_login_lip(vha);
                if (ret != QLA_SUCCESS) {
-                       DEBUG2_3(printk("%s(%ld): failed: "
-                           "full_login_lip=%d.\n", __func__, vha->host_no,
-                           ret));
+                       ql_dbg(ql_dbg_taskm, vha, 0x802d,
+                           "full_login_lip=%d.\n", ret);
                }
                atomic_set(&vha->loop_state, LOOP_DOWN);
                atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
@@ -1202,8 +1279,8 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
        if (ha->flags.enable_lip_reset) {
                ret = qla2x00_lip_reset(vha);
                if (ret != QLA_SUCCESS) {
-                       DEBUG2_3(printk("%s(%ld): failed: "
-                           "lip_reset=%d.\n", __func__, vha->host_no, ret));
+                       ql_dbg(ql_dbg_taskm, vha, 0x802e,
+                           "lip_reset failed (%d).\n", ret);
                } else
                        qla2x00_wait_for_loop_ready(vha);
        }
@@ -1302,17 +1379,17 @@ static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth)
        if (!scsi_track_queue_full(sdev, qdepth))
                return;
 
-       DEBUG2(qla_printk(KERN_INFO, fcport->vha->hw,
-               "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n",
-               fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
-               sdev->queue_depth));
+       ql_dbg(ql_dbg_io, fcport->vha, 0x3029,
+           "Queue depth adjusted-down "
+           "to %d for scsi(%ld:%d:%d:%d).\n",
+           sdev->queue_depth, fcport->vha->host_no,
+           sdev->channel, sdev->id, sdev->lun);
 }
 
 static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth)
 {
        fc_port_t *fcport = sdev->hostdata;
        struct scsi_qla_host *vha = fcport->vha;
-       struct qla_hw_data *ha = vha->hw;
        struct req_que *req = NULL;
 
        req = vha->req;
@@ -1327,10 +1404,11 @@ static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth)
        else
                scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, qdepth);
 
-       DEBUG2(qla_printk(KERN_INFO, ha,
-              "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n",
-              fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
-              sdev->queue_depth));
+       ql_dbg(ql_dbg_io, vha, 0x302a,
+           "Queue depth adjusted-up to %d for "
+           "scsi(%ld:%d:%d:%d).\n",
+           sdev->queue_depth, fcport->vha->host_no,
+           sdev->channel, sdev->id, sdev->lun);
 }
 
 static int
@@ -1776,6 +1854,9 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
                ha->flags.port0 = 1;
        else
                ha->flags.port0 = 0;
+       ql_dbg_pci(ql_dbg_init, ha->pdev, 0x000b,
+           "device_type=0x%x port=%d fw_srisc_address=%p.\n",
+           ha->device_type, ha->flags.port0, ha->fw_srisc_address);
 }
 
 static int
@@ -1790,10 +1871,9 @@ qla2x00_iospace_config(struct qla_hw_data *ha)
 
        if (pci_request_selected_regions(ha->pdev, ha->bars,
            QLA2XXX_DRIVER_NAME)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Failed to reserve PIO/MMIO regions (%s)\n",
+               ql_log_pci(ql_log_fatal, ha->pdev, 0x0011,
+                   "Failed to reserve PIO/MMIO regions (%s), aborting.\n",
                    pci_name(ha->pdev));
-
                goto iospace_error_exit;
        }
        if (!(ha->bars & 1))
@@ -1803,39 +1883,42 @@ qla2x00_iospace_config(struct qla_hw_data *ha)
        pio = pci_resource_start(ha->pdev, 0);
        if (pci_resource_flags(ha->pdev, 0) & IORESOURCE_IO) {
                if (pci_resource_len(ha->pdev, 0) < MIN_IOBASE_LEN) {
-                       qla_printk(KERN_WARNING, ha,
-                           "Invalid PCI I/O region size (%s)...\n",
-                               pci_name(ha->pdev));
+                       ql_log_pci(ql_log_warn, ha->pdev, 0x0012,
+                           "Invalid pci I/O region size (%s).\n",
+                           pci_name(ha->pdev));
                        pio = 0;
                }
        } else {
-               qla_printk(KERN_WARNING, ha,
-                   "region #0 not a PIO resource (%s)...\n",
+               ql_log_pci(ql_log_warn, ha->pdev, 0x0013,
+                   "Region #0 no a PIO resource (%s).\n",
                    pci_name(ha->pdev));
                pio = 0;
        }
        ha->pio_address = pio;
+       ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0014,
+           "PIO address=%p.\n",
+           ha->pio_address);
 
 skip_pio:
        /* Use MMIO operations for all accesses. */
        if (!(pci_resource_flags(ha->pdev, 1) & IORESOURCE_MEM)) {
-               qla_printk(KERN_ERR, ha,
-                   "region #1 not an MMIO resource (%s), aborting\n",
+               ql_log_pci(ql_log_fatal, ha->pdev, 0x0015,
+                   "Region #1 not an MMIO resource (%s), aborting.\n",
                    pci_name(ha->pdev));
                goto iospace_error_exit;
        }
        if (pci_resource_len(ha->pdev, 1) < MIN_IOBASE_LEN) {
-               qla_printk(KERN_ERR, ha,
-                   "Invalid PCI mem region size (%s), aborting\n",
-                       pci_name(ha->pdev));
+               ql_log_pci(ql_log_fatal, ha->pdev, 0x0016,
+                   "Invalid PCI mem region size (%s), aborting.\n",
+                   pci_name(ha->pdev));
                goto iospace_error_exit;
        }
 
        ha->iobase = ioremap(pci_resource_start(ha->pdev, 1), MIN_IOBASE_LEN);
        if (!ha->iobase) {
-               qla_printk(KERN_ERR, ha,
-                   "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));
-
+               ql_log_pci(ql_log_fatal, ha->pdev, 0x0017,
+                   "Cannot remap MMIO (%s), aborting.\n",
+                   pci_name(ha->pdev));
                goto iospace_error_exit;
        }
 
@@ -1849,6 +1932,8 @@ skip_pio:
        ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3),
                        pci_resource_len(ha->pdev, 3));
        if (ha->mqiobase) {
+               ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0018,
+                   "MQIO Base=%p.\n", ha->mqiobase);
                /* Read MSIX vector size of the board */
                pci_read_config_word(ha->pdev, QLA_PCI_MSIX_CONTROL, &msix);
                ha->msix_count = msix;
@@ -1861,17 +1946,24 @@ skip_pio:
                        ha->max_req_queues = 2;
                } else if (ql2xmaxqueues > 1) {
                        ha->max_req_queues = ql2xmaxqueues > QLA_MQ_SIZE ?
-                                               QLA_MQ_SIZE : ql2xmaxqueues;
-                       DEBUG2(qla_printk(KERN_INFO, ha, "QoS mode set, max no"
-                       " of request queues:%d\n", ha->max_req_queues));
+                           QLA_MQ_SIZE : ql2xmaxqueues;
+                       ql_dbg_pci(ql_dbg_multiq, ha->pdev, 0xc008,
+                           "QoS mode set, max no of request queues:%d.\n",
+                           ha->max_req_queues);
+                       ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0019,
+                           "QoS mode set, max no of request queues:%d.\n",
+                           ha->max_req_queues);
                }
-               qla_printk(KERN_INFO, ha,
-                       "MSI-X vector count: %d\n", msix);
+               ql_log_pci(ql_log_info, ha->pdev, 0x001a,
+                   "MSI-X vector count: %d.\n", msix);
        } else
-               qla_printk(KERN_INFO, ha, "BAR 3 not enabled\n");
+               ql_log_pci(ql_log_info, ha->pdev, 0x001b,
+                   "BAR 3 not enabled.\n");
 
 mqiobase_exit:
        ha->msix_count = ha->max_rsp_queues + 1;
+       ql_dbg_pci(ql_dbg_init, ha->pdev, 0x001c,
+           "MSIX Count:%d.\n", ha->msix_count);
        return (0);
 
 iospace_error_exit:
@@ -1935,7 +2027,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8021) {
                bars = pci_select_bars(pdev, IORESOURCE_MEM);
                mem_only = 1;
+               ql_dbg_pci(ql_dbg_init, pdev, 0x0007,
+                   "Mem only adapter.\n");
        }
+       ql_dbg_pci(ql_dbg_init, pdev, 0x0008,
+           "Bars=%d.\n", bars);
 
        if (mem_only) {
                if (pci_enable_device_mem(pdev))
@@ -1950,9 +2046,12 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL);
        if (!ha) {
-               DEBUG(printk("Unable to allocate memory for ha\n"));
+               ql_log_pci(ql_log_fatal, pdev, 0x0009,
+                   "Unable to allocate memory for ha.\n");
                goto probe_out;
        }
+       ql_dbg_pci(ql_dbg_init, pdev, 0x000a,
+           "Memory allocated for ha=%p.\n", ha);
        ha->pdev = pdev;
 
        /* Clear our data area */
@@ -1974,10 +2073,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        if (ret)
                goto probe_hw_failed;
 
-       qla_printk(KERN_INFO, ha,
-           "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq,
-           ha->iobase);
-
+       ql_log_pci(ql_log_info, pdev, 0x001d,
+           "Found an ISP%04X irq %d iobase 0x%p.\n",
+           pdev->device, pdev->irq, ha->iobase);
        ha->prev_topology = 0;
        ha->init_cb_size = sizeof(init_cb_t);
        ha->link_data_rate = PORT_SPEED_UNKNOWN;
@@ -2078,7 +2176,18 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF;
                ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA;
        }
-
+       ql_dbg_pci(ql_dbg_init, pdev, 0x001e,
+           "mbx_count=%d, req_length=%d, "
+           "rsp_length=%d, max_loop_id=%d, init_cb_size=%d, "
+           "gid_list_info_size=%d, optrom_size=%d, nvram_npiv_size=%d, .\n",
+           ha->mbx_count, req_length, rsp_length, ha->max_loop_id,
+           ha->init_cb_size, ha->gid_list_info_size, ha->optrom_size,
+           ha->nvram_npiv_size);
+       ql_dbg_pci(ql_dbg_init, pdev, 0x001f,
+           "isp_ops=%p, flash_conf_off=%d, "
+           "flash_data_off=%d, nvram_conf_off=%d, nvram_data_off=%d.\n",
+           ha->isp_ops, ha->flash_conf_off, ha->flash_data_off,
+           ha->nvram_conf_off, ha->nvram_data_off);
        mutex_init(&ha->vport_lock);
        init_completion(&ha->mbx_cmd_comp);
        complete(&ha->mbx_cmd_comp);
@@ -2088,10 +2197,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        set_bit(0, (unsigned long *) ha->vp_idx_map);
 
        qla2x00_config_dma_addressing(ha);
+       ql_dbg_pci(ql_dbg_init, pdev, 0x0020,
+           "64 Bit addressing is %s.\n",
+           ha->flags.enable_64bit_addressing ? "enable" :
+           "disable");
        ret = qla2x00_mem_alloc(ha, req_length, rsp_length, &req, &rsp);
        if (!ret) {
-               qla_printk(KERN_WARNING, ha,
-                   "[ERROR] Failed to allocate memory for adapter\n");
+               ql_log_pci(ql_log_fatal, pdev, 0x0031,
+                   "Failed to allocate memory for adapter, aborting.\n");
 
                goto probe_hw_failed;
        }
@@ -2103,9 +2216,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        base_vha = qla2x00_create_host(sht, ha);
        if (!base_vha) {
-               qla_printk(KERN_WARNING, ha,
-                   "[ERROR] Failed to allocate memory for scsi_host\n");
-
                ret = -ENOMEM;
                qla2x00_mem_free(ha);
                qla2x00_free_req_que(ha, req);
@@ -2132,7 +2242,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                if (!IS_QLA82XX(ha))
                        host->sg_tablesize = QLA_SG_ALL;
        }
-
+       ql_dbg(ql_dbg_init, base_vha, 0x0032,
+           "can_queue=%d, req=%p, "
+           "mgmt_svr_loop_id=%d, sg_tablesize=%d.\n",
+           host->can_queue, base_vha->req,
+           base_vha->mgmt_svr_loop_id, host->sg_tablesize);
        host->max_id = max_id;
        host->this_id = 255;
        host->cmd_per_lun = 3;
@@ -2146,6 +2260,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        host->transportt = qla2xxx_transport_template;
        sht->vendor_id = (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC);
 
+       ql_dbg(ql_dbg_init, base_vha, 0x0033,
+           "max_id=%d this_id=%d "
+           "cmd_per_len=%d unique_id=%d max_cmd_len=%d max_channel=%d "
+           "max_lun=%d transportt=%p, vendor_id=%d.\n", host->max_id,
+           host->this_id, host->cmd_per_lun, host->unique_id,
+           host->max_cmd_len, host->max_channel, host->max_lun,
+           host->transportt, sht->vendor_id);
+
        /* Set up the irqs */
        ret = qla2x00_request_irqs(ha, rsp);
        if (ret)
@@ -2156,9 +2278,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        /* Alloc arrays of request and response ring ptrs */
 que_init:
        if (!qla2x00_alloc_queues(ha)) {
-               qla_printk(KERN_WARNING, ha,
-               "[ERROR] Failed to allocate memory for queue"
-               " pointers\n");
+               ql_log(ql_log_fatal, base_vha, 0x003d,
+                   "Failed to allocate memory for queue pointers.. aborting.\n");
                goto probe_init_failed;
        }
 
@@ -2186,20 +2307,33 @@ que_init:
                rsp->rsp_q_out = &ha->iobase->isp82.rsp_q_out[0];
        }
 
-       if (qla2x00_initialize_adapter(base_vha)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Failed to initialize adapter\n");
+       ql_dbg(ql_dbg_multiq, base_vha, 0xc009,
+           "rsp_q_map=%p req_q_map=%p rsp->req=%p req->rsp=%p.\n",
+           ha->rsp_q_map, ha->req_q_map, rsp->req, req->rsp);
+       ql_dbg(ql_dbg_multiq, base_vha, 0xc00a,
+           "req->req_q_in=%p req->req_q_out=%p "
+           "rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n",
+           req->req_q_in, req->req_q_out,
+           rsp->rsp_q_in, rsp->rsp_q_out);
+       ql_dbg(ql_dbg_init, base_vha, 0x003e,
+           "rsp_q_map=%p req_q_map=%p rsp->req=%p req->rsp=%p.\n",
+           ha->rsp_q_map, ha->req_q_map, rsp->req, req->rsp);
+       ql_dbg(ql_dbg_init, base_vha, 0x003f,
+           "req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n",
+           req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out);
 
-               DEBUG2(printk("scsi(%ld): Failed to initialize adapter - "
-                   "Adapter flags %x.\n",
-                   base_vha->host_no, base_vha->device_flags));
+       if (qla2x00_initialize_adapter(base_vha)) {
+               ql_log(ql_log_fatal, base_vha, 0x00d6,
+                   "Failed to initialize adapter - Adapter flags %x.\n",
+                   base_vha->device_flags);
 
                if (IS_QLA82XX(ha)) {
                        qla82xx_idc_lock(ha);
                        qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
                                QLA82XX_DEV_FAILED);
                        qla82xx_idc_unlock(ha);
-                       qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
+                       ql_log(ql_log_fatal, base_vha, 0x00d7,
+                           "HW State: FAILED.\n");
                }
 
                ret = -ENODEV;
@@ -2208,9 +2342,8 @@ que_init:
 
        if (ha->mqenable) {
                if (qla25xx_setup_mode(base_vha)) {
-                       qla_printk(KERN_WARNING, ha,
-                               "Can't create queues, falling back to single"
-                               " queue mode\n");
+                       ql_log(ql_log_warn, base_vha, 0x00ec,
+                           "Failed to create queues, falling back to single queue mode.\n");
                        goto que_init;
                }
        }
@@ -2222,13 +2355,15 @@ que_init:
         * Startup the kernel thread for this host adapter
         */
        ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha,
-                       "%s_dpc", base_vha->host_str);
+           "%s_dpc", base_vha->host_str);
        if (IS_ERR(ha->dpc_thread)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Unable to start DPC thread!\n");
+               ql_log(ql_log_fatal, base_vha, 0x00ed,
+                   "Failed to start DPC thread.\n");
                ret = PTR_ERR(ha->dpc_thread);
                goto probe_failed;
        }
+       ql_dbg(ql_dbg_init, base_vha, 0x00ee,
+           "DPC thread started successfully.\n");
 
 skip_dpc:
        list_add_tail(&base_vha->list, &ha->vp_list);
@@ -2236,16 +2371,18 @@ skip_dpc:
 
        /* Initialized the timer */
        qla2x00_start_timer(base_vha, qla2x00_timer, WATCH_INTERVAL);
-
-       DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
-           base_vha->host_no, ha));
+       ql_dbg(ql_dbg_init, base_vha, 0x00ef,
+           "Started qla2x00_timer with "
+           "interval=%d.\n", WATCH_INTERVAL);
+       ql_dbg(ql_dbg_init, base_vha, 0x00f0,
+           "Detected hba at address=%p.\n",
+           ha);
 
        if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) {
                if (ha->fw_attributes & BIT_4) {
                        base_vha->flags.difdix_supported = 1;
-                       DEBUG18(qla_printk(KERN_INFO, ha,
-                           "Registering for DIF/DIX type 1 and 3"
-                           " protection.\n"));
+                       ql_dbg(ql_dbg_init, base_vha, 0x00f1,
+                           "Registering for DIF/DIX type 1 and 3 protection.\n");
                        scsi_host_set_prot(host,
                            SHOST_DIF_TYPE1_PROTECTION
                            | SHOST_DIF_TYPE2_PROTECTION
@@ -2267,6 +2404,9 @@ skip_dpc:
        base_vha->flags.init_done = 1;
        base_vha->flags.online = 1;
 
+       ql_dbg(ql_dbg_init, base_vha, 0x00f2,
+           "Init done and hba is online.\n");
+
        scsi_scan_host(host);
 
        qla2x00_alloc_sysfs_attr(base_vha);
@@ -2275,14 +2415,17 @@ skip_dpc:
 
        qla2x00_dfs_setup(base_vha);
 
-       qla_printk(KERN_INFO, ha, "\n"
-           " QLogic Fibre Channel HBA Driver: %s\n"
-           "  QLogic %s - %s\n"
-           "  ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n",
-           qla2x00_version_str, ha->model_number,
-           ha->model_desc ? ha->model_desc : "", pdev->device,
-           ha->isp_ops->pci_info_str(base_vha, pci_info), pci_name(pdev),
-           ha->flags.enable_64bit_addressing ? '+' : '-', base_vha->host_no,
+       ql_log(ql_log_info, base_vha, 0x00fa,
+           "QLogic Fibre Channed HBA Driver: %s.\n",
+           qla2x00_version_str);
+       ql_log(ql_log_info, base_vha, 0x00fb,
+           "QLogic %s - %s.\n",
+           ha->model_number, ha->model_desc ? ha->model_desc : "");
+       ql_log(ql_log_info, base_vha, 0x00fc,
+           "ISP%04X: %s @ %s hdma%c host#=%ld fw=%s.\n",
+           pdev->device, ha->isp_ops->pci_info_str(base_vha, pci_info),
+           pci_name(pdev), ha->flags.enable_64bit_addressing ? '+' : '-',
+           base_vha->host_no,
            ha->isp_ops->fw_version_str(base_vha, fw_str));
 
        return 0;
@@ -2580,20 +2723,15 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
                fcport->login_retry = vha->hw->login_retry_count;
                set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 
-               DEBUG(printk("scsi(%ld): Port login retry: "
+               ql_dbg(ql_dbg_disc, vha, 0x2067,
+                   "Port login retry "
                    "%02x%02x%02x%02x%02x%02x%02x%02x, "
-                   "id = 0x%04x retry cnt=%d\n",
-                   vha->host_no,
-                   fcport->port_name[0],
-                   fcport->port_name[1],
-                   fcport->port_name[2],
-                   fcport->port_name[3],
-                   fcport->port_name[4],
-                   fcport->port_name[5],
-                   fcport->port_name[6],
-                   fcport->port_name[7],
-                   fcport->loop_id,
-                   fcport->login_retry));
+                   "id = 0x%04x retry cnt=%d.\n",
+                   fcport->port_name[0], fcport->port_name[1],
+                   fcport->port_name[2], fcport->port_name[3],
+                   fcport->port_name[4], fcport->port_name[5],
+                   fcport->port_name[6], fcport->port_name[7],
+                   fcport->loop_id, fcport->login_retry);
        }
 }
 
@@ -2676,6 +2814,9 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
                        ctx_cachep);
                if (!ha->ctx_mempool)
                        goto fail_free_srb_mempool;
+               ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0021,
+                   "ctx_cachep=%p ctx_mempool=%p.\n",
+                   ctx_cachep, ha->ctx_mempool);
        }
 
        /* Get memory for cached NVRAM */
@@ -2690,22 +2831,29 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
        if (!ha->s_dma_pool)
                goto fail_free_nvram;
 
+       ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0022,
+           "init_cb=%p gid_list=%p, srb_mempool=%p s_dma_pool=%p.\n",
+           ha->init_cb, ha->gid_list, ha->srb_mempool, ha->s_dma_pool);
+
        if (IS_QLA82XX(ha) || ql2xenabledif) {
                ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev,
                        DSD_LIST_DMA_POOL_SIZE, 8, 0);
                if (!ha->dl_dma_pool) {
-                       qla_printk(KERN_WARNING, ha,
-                           "Memory Allocation failed - dl_dma_pool\n");
+                       ql_log_pci(ql_log_fatal, ha->pdev, 0x0023,
+                           "Failed to allocate memory for dl_dma_pool.\n");
                        goto fail_s_dma_pool;
                }
 
                ha->fcp_cmnd_dma_pool = dma_pool_create(name, &ha->pdev->dev,
                        FCP_CMND_DMA_POOL_SIZE, 8, 0);
                if (!ha->fcp_cmnd_dma_pool) {
-                       qla_printk(KERN_WARNING, ha,
-                           "Memory Allocation failed - fcp_cmnd_dma_pool\n");
+                       ql_log_pci(ql_log_fatal, ha->pdev, 0x0024,
+                           "Failed to allocate memory for fcp_cmnd_dma_pool.\n");
                        goto fail_dl_dma_pool;
                }
+               ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0025,
+                   "dl_dma_pool=%p fcp_cmnd_dma_pool=%p.\n",
+                   ha->dl_dma_pool, ha->fcp_cmnd_dma_pool);
        }
 
        /* Allocate memory for SNS commands */
@@ -2715,6 +2863,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
                sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, GFP_KERNEL);
                if (!ha->sns_cmd)
                        goto fail_dma_pool;
+               ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0026,
+                   "sns_cmd.\n", ha->sns_cmd);
        } else {
        /* Get consistent memory allocated for MS IOCB */
                ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
@@ -2726,12 +2876,16 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
                        sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, GFP_KERNEL);
                if (!ha->ct_sns)
                        goto fail_free_ms_iocb;
+               ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0027,
+                   "ms_iocb=%p ct_sns=%p.\n",
+                   ha->ms_iocb, ha->ct_sns);
        }
 
        /* Allocate memory for request ring */
        *req = kzalloc(sizeof(struct req_que), GFP_KERNEL);
        if (!*req) {
-               DEBUG(printk("Unable to allocate memory for req\n"));
+               ql_log_pci(ql_log_fatal, ha->pdev, 0x0028,
+                   "Failed to allocate memory for req.\n");
                goto fail_req;
        }
        (*req)->length = req_len;
@@ -2739,14 +2893,15 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
                ((*req)->length + 1) * sizeof(request_t),
                &(*req)->dma, GFP_KERNEL);
        if (!(*req)->ring) {
-               DEBUG(printk("Unable to allocate memory for req_ring\n"));
+               ql_log_pci(ql_log_fatal, ha->pdev, 0x0029,
+                   "Failed to allocate memory for req_ring.\n");
                goto fail_req_ring;
        }
        /* Allocate memory for response ring */
        *rsp = kzalloc(sizeof(struct rsp_que), GFP_KERNEL);
        if (!*rsp) {
-               qla_printk(KERN_WARNING, ha,
-                       "Unable to allocate memory for rsp\n");
+               ql_log_pci(ql_log_fatal, ha->pdev, 0x002a,
+                   "Failed to allocate memory for rsp.\n");
                goto fail_rsp;
        }
        (*rsp)->hw = ha;
@@ -2755,19 +2910,24 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
                ((*rsp)->length + 1) * sizeof(response_t),
                &(*rsp)->dma, GFP_KERNEL);
        if (!(*rsp)->ring) {
-               qla_printk(KERN_WARNING, ha,
-                       "Unable to allocate memory for rsp_ring\n");
+               ql_log_pci(ql_log_fatal, ha->pdev, 0x002b,
+                   "Failed to allocate memory for rsp_ring.\n");
                goto fail_rsp_ring;
        }
        (*req)->rsp = *rsp;
        (*rsp)->req = *req;
+       ql_dbg_pci(ql_dbg_init, ha->pdev, 0x002c,
+           "req=%p req->length=%d req->ring=%p rsp=%p "
+           "rsp->length=%d rsp->ring=%p.\n",
+           *req, (*req)->length, (*req)->ring, *rsp, (*rsp)->length,
+           (*rsp)->ring);
        /* Allocate memory for NVRAM data for vports */
        if (ha->nvram_npiv_size) {
                ha->npiv_info = kzalloc(sizeof(struct qla_npiv_entry) *
-                                       ha->nvram_npiv_size, GFP_KERNEL);
+                   ha->nvram_npiv_size, GFP_KERNEL);
                if (!ha->npiv_info) {
-                       qla_printk(KERN_WARNING, ha,
-                               "Unable to allocate memory for npiv info\n");
+                       ql_log_pci(ql_log_fatal, ha->pdev, 0x002d,
+                           "Failed to allocate memory for npiv_info.\n");
                        goto fail_npiv_info;
                }
        } else
@@ -2779,6 +2939,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
                    &ha->ex_init_cb_dma);
                if (!ha->ex_init_cb)
                        goto fail_ex_init_cb;
+               ql_dbg_pci(ql_dbg_init, ha->pdev, 0x002e,
+                   "ex_init_cb=%p.\n", ha->ex_init_cb);
        }
 
        INIT_LIST_HEAD(&ha->gbl_dsd_list);
@@ -2789,6 +2951,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
                        &ha->async_pd_dma);
                if (!ha->async_pd)
                        goto fail_async_pd;
+               ql_dbg_pci(ql_dbg_init, ha->pdev, 0x002f,
+                   "async_pd=%p.\n", ha->async_pd);
        }
 
        INIT_LIST_HEAD(&ha->vp_list);
@@ -2854,7 +3018,8 @@ fail_free_init_cb:
        ha->init_cb = NULL;
        ha->init_cb_dma = 0;
 fail:
-       DEBUG(printk("%s: Memory allocation failure\n", __func__));
+       ql_log(ql_log_fatal, NULL, 0x0030,
+           "Memory allocation failure.\n");
        return -ENOMEM;
 }
 
@@ -3003,8 +3168,8 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
 
        host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
        if (host == NULL) {
-               printk(KERN_WARNING
-               "qla2xxx: Couldn't allocate host from scsi layer!\n");
+               ql_log_pci(ql_log_fatal, ha->pdev, 0x0107,
+                   "Failed to allocate host from the scsi layer, aborting.\n");
                goto fail;
        }
 
@@ -3023,6 +3188,11 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
        spin_lock_init(&vha->work_lock);
 
        sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
+       ql_dbg(ql_dbg_init, vha, 0x0041,
+           "Allocated the host=%p hw=%p vha=%p dev_name=%s",
+           vha->host, vha->hw, vha,
+           dev_name(&(ha->pdev->dev)));
+
        return vha;
 
 fail:
@@ -3264,18 +3434,18 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
                        if (status == QLA_SUCCESS) {
                                fcport->old_loop_id = fcport->loop_id;
 
-                               DEBUG(printk("scsi(%ld): port login OK: logged "
-                               "in ID 0x%x\n", vha->host_no, fcport->loop_id));
+                               ql_dbg(ql_dbg_disc, vha, 0x2003,
+                                   "Port login OK: logged in ID 0x%x.\n",
+                                   fcport->loop_id);
 
                                qla2x00_update_fcport(vha, fcport);
 
                        } else if (status == 1) {
                                set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
                                /* retry the login again */
-                               DEBUG(printk("scsi(%ld): Retrying"
-                               " %d login again loop_id 0x%x\n",
-                               vha->host_no, fcport->login_retry,
-                                               fcport->loop_id));
+                               ql_dbg(ql_dbg_disc, vha, 0x2007,
+                                   "Retrying %d login again loop_id 0x%x.\n",
+                                   fcport->login_retry, fcport->loop_id);
                        } else {
                                fcport->login_retry = 0;
                        }
@@ -3315,26 +3485,27 @@ qla2x00_do_dpc(void *data)
 
        set_current_state(TASK_INTERRUPTIBLE);
        while (!kthread_should_stop()) {
-               DEBUG3(printk("qla2x00: DPC handler sleeping\n"));
+               ql_dbg(ql_dbg_dpc, base_vha, 0x4000,
+                   "DPC handler sleeping.\n");
 
                schedule();
                __set_current_state(TASK_RUNNING);
 
-               DEBUG3(printk("qla2x00: DPC handler waking up\n"));
+               ql_dbg(ql_dbg_dpc, base_vha, 0x4001,
+                   "DPC handler waking up.\n");
+               ql_dbg(ql_dbg_dpc, base_vha, 0x4002,
+                   "dpc_flags=0x%lx.\n", base_vha->dpc_flags);
 
                /* Initialization not yet finished. Don't do anything yet. */
                if (!base_vha->flags.init_done)
                        continue;
 
                if (ha->flags.eeh_busy) {
-                       DEBUG17(qla_printk(KERN_WARNING, ha,
-                           "qla2x00_do_dpc: dpc_flags: %lx\n",
-                           base_vha->dpc_flags));
+                       ql_dbg(ql_dbg_dpc, base_vha, 0x4003,
+                           "eeh_busy=%d.\n", ha->flags.eeh_busy);
                        continue;
                }
 
-               DEBUG3(printk("scsi(%ld): DPC handler\n", base_vha->host_no));
-
                ha->dpc_active = 1;
 
                if (ha->flags.mbox_busy) {
@@ -3351,8 +3522,8 @@ qla2x00_do_dpc(void *data)
                                qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
                                        QLA82XX_DEV_FAILED);
                                qla82xx_idc_unlock(ha);
-                               qla_printk(KERN_INFO, ha,
-                                       "HW State: FAILED\n");
+                               ql_log(ql_log_info, base_vha, 0x4004,
+                                   "HW State: FAILED.\n");
                                qla82xx_device_state_handler(base_vha);
                                continue;
                        }
@@ -3360,10 +3531,8 @@ qla2x00_do_dpc(void *data)
                        if (test_and_clear_bit(FCOE_CTX_RESET_NEEDED,
                                &base_vha->dpc_flags)) {
 
-                               DEBUG(printk(KERN_INFO
-                                       "scsi(%ld): dpc: sched "
-                                       "qla82xx_fcoe_ctx_reset ha = %p\n",
-                                       base_vha->host_no, ha));
+                               ql_dbg(ql_dbg_dpc, base_vha, 0x4005,
+                                   "FCoE context reset scheduled.\n");
                                if (!(test_and_set_bit(ABORT_ISP_ACTIVE,
                                        &base_vha->dpc_flags))) {
                                        if (qla82xx_fcoe_ctx_reset(base_vha)) {
@@ -3377,18 +3546,16 @@ qla2x00_do_dpc(void *data)
                                                &base_vha->dpc_flags);
                                }
 
-                               DEBUG(printk("scsi(%ld): dpc:"
-                                       " qla82xx_fcoe_ctx_reset end\n",
-                                       base_vha->host_no));
+                               ql_dbg(ql_dbg_dpc, base_vha, 0x4006,
+                                   "FCoE context reset end.\n");
                        }
                }
 
                if (test_and_clear_bit(ISP_ABORT_NEEDED,
                                                &base_vha->dpc_flags)) {
 
-                       DEBUG(printk("scsi(%ld): dpc: sched "
-                           "qla2x00_abort_isp ha = %p\n",
-                           base_vha->host_no, ha));
+                       ql_dbg(ql_dbg_dpc, base_vha, 0x4007,
+                           "ISP abort scheduled.\n");
                        if (!(test_and_set_bit(ABORT_ISP_ACTIVE,
                            &base_vha->dpc_flags))) {
 
@@ -3401,8 +3568,8 @@ qla2x00_do_dpc(void *data)
                                                &base_vha->dpc_flags);
                        }
 
-                       DEBUG(printk("scsi(%ld): dpc: qla2x00_abort_isp end\n",
-                           base_vha->host_no));
+                       ql_dbg(ql_dbg_dpc, base_vha, 0x4008,
+                           "ISP abort end.\n");
                }
 
                if (test_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) {
@@ -3411,9 +3578,8 @@ qla2x00_do_dpc(void *data)
                }
 
                if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {
-                       DEBUG(printk(KERN_INFO "scsi(%ld): dpc: sched "
-                           "qla2x00_quiesce_needed ha = %p\n",
-                           base_vha->host_no, ha));
+                       ql_dbg(ql_dbg_dpc, base_vha, 0x4009,
+                           "Quiescence mode scheduled.\n");
                        qla82xx_device_state_handler(base_vha);
                        clear_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags);
                        if (!ha->flags.quiesce_owner) {
@@ -3423,17 +3589,20 @@ qla2x00_do_dpc(void *data)
                                qla82xx_clear_qsnt_ready(base_vha);
                                qla82xx_idc_unlock(ha);
                        }
+                       ql_dbg(ql_dbg_dpc, base_vha, 0x400a,
+                           "Quiescence mode end.\n");
                }
 
                if (test_and_clear_bit(RESET_MARKER_NEEDED,
                                                        &base_vha->dpc_flags) &&
                    (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) {
 
-                       DEBUG(printk("scsi(%ld): qla2x00_reset_marker()\n",
-                           base_vha->host_no));
-
+                       ql_dbg(ql_dbg_dpc, base_vha, 0x400b,
+                           "Reset marker scheduled.\n");
                        qla2x00_rst_aen(base_vha);
                        clear_bit(RESET_ACTIVE, &base_vha->dpc_flags);
+                       ql_dbg(ql_dbg_dpc, base_vha, 0x400c,
+                           "Reset marker end.\n");
                }
 
                /* Retry each device up to login retry count */
@@ -3442,19 +3611,18 @@ qla2x00_do_dpc(void *data)
                    !test_bit(LOOP_RESYNC_NEEDED, &base_vha->dpc_flags) &&
                    atomic_read(&base_vha->loop_state) != LOOP_DOWN) {
 
-                       DEBUG(printk("scsi(%ld): qla2x00_port_login()\n",
-                                       base_vha->host_no));
+                       ql_dbg(ql_dbg_dpc, base_vha, 0x400d,
+                           "Relogin scheduled.\n");
                        qla2x00_relogin(base_vha);
-
-                       DEBUG(printk("scsi(%ld): qla2x00_port_login - end\n",
-                           base_vha->host_no));
+                       ql_dbg(ql_dbg_dpc, base_vha, 0x400e,
+                           "Relogin end.\n");
                }
 
                if (test_and_clear_bit(LOOP_RESYNC_NEEDED,
                                                        &base_vha->dpc_flags)) {
 
-                       DEBUG(printk("scsi(%ld): qla2x00_loop_resync()\n",
-                               base_vha->host_no));
+                       ql_dbg(ql_dbg_dpc, base_vha, 0x400f,
+                           "Loop resync scheduled.\n");
 
                        if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE,
                            &base_vha->dpc_flags))) {
@@ -3465,8 +3633,8 @@ qla2x00_do_dpc(void *data)
                                                &base_vha->dpc_flags);
                        }
 
-                       DEBUG(printk("scsi(%ld): qla2x00_loop_resync - end\n",
-                           base_vha->host_no));
+                       ql_dbg(ql_dbg_dpc, base_vha, 0x4010,
+                           "Loop resync end.\n");
                }
 
                if (test_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags) &&
@@ -3489,7 +3657,8 @@ qla2x00_do_dpc(void *data)
        } /* End of while(1) */
        __set_current_state(TASK_RUNNING);
 
-       DEBUG(printk("scsi(%ld): DPC handler exiting\n", base_vha->host_no));
+       ql_dbg(ql_dbg_dpc, base_vha, 0x4011,
+           "DPC handler exiting.\n");
 
        /*
         * Make sure that nobody tries to wake us up again.
@@ -3596,9 +3765,11 @@ void
 qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp)
 {
        if (atomic_read(&sp->ref_count) == 0) {
-               DEBUG2(qla_printk(KERN_WARNING, ha,
-                   "SP reference-count to ZERO -- sp=%p\n", sp));
-               DEBUG2(BUG());
+               ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3015,
+                   "SP reference-count to ZERO -- sp=%p cmd=%p.\n",
+                   sp, sp->cmd);
+               if (ql2xextended_error_logging & ql_dbg_io)
+                       BUG();
                return;
        }
        if (!atomic_dec_and_test(&sp->ref_count))
@@ -3626,6 +3797,9 @@ qla2x00_timer(scsi_qla_host_t *vha)
        struct req_que *req;
 
        if (ha->flags.eeh_busy) {
+               ql_dbg(ql_dbg_timer, vha, 0x6000,
+                   "EEH = %d, restarting timer.\n",
+                   ha->flags.eeh_busy);
                qla2x00_restart_timer(vha, WATCH_INTERVAL);
                return;
        }
@@ -3650,9 +3824,8 @@ qla2x00_timer(scsi_qla_host_t *vha)
                if (atomic_read(&vha->loop_down_timer) ==
                    vha->loop_down_abort_time) {
 
-                       DEBUG(printk("scsi(%ld): Loop Down - aborting the "
-                           "queues before time expire\n",
-                           vha->host_no));
+                       ql_log(ql_log_info, vha, 0x6008,
+                           "Loop down - aborting the queues before time expires.\n");
 
                        if (!IS_QLA2100(ha) && vha->link_down_timeout)
                                atomic_set(&vha->loop_state, LOOP_DEAD);
@@ -3697,10 +3870,7 @@ qla2x00_timer(scsi_qla_host_t *vha)
                /* if the loop has been down for 4 minutes, reinit adapter */
                if (atomic_dec_and_test(&vha->loop_down_timer) != 0) {
                        if (!(vha->device_flags & DFLG_NO_CABLE)) {
-                               DEBUG(printk("scsi(%ld): Loop down - "
-                                   "aborting ISP.\n",
-                                   vha->host_no));
-                               qla_printk(KERN_WARNING, ha,
+                               ql_log(ql_log_warn, vha, 0x6009,
                                    "Loop down - aborting ISP.\n");
 
                                if (IS_QLA82XX(ha))
@@ -3711,9 +3881,9 @@ qla2x00_timer(scsi_qla_host_t *vha)
                                                &vha->dpc_flags);
                        }
                }
-               DEBUG3(printk("scsi(%ld): Loop Down - seconds remaining %d\n",
-                   vha->host_no,
-                   atomic_read(&vha->loop_down_timer)));
+               ql_dbg(ql_dbg_timer, vha, 0x600a,
+                   "Loop down - seconds remaining %d.\n",
+                   atomic_read(&vha->loop_down_timer));
        }
 
        /* Check if beacon LED needs to be blinked for physical host only */
@@ -3736,8 +3906,27 @@ qla2x00_timer(scsi_qla_host_t *vha)
            test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) ||
            test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) ||
            test_bit(VP_DPC_NEEDED, &vha->dpc_flags) ||
-           test_bit(RELOGIN_NEEDED, &vha->dpc_flags)))
+           test_bit(RELOGIN_NEEDED, &vha->dpc_flags))) {
+               ql_dbg(ql_dbg_timer, vha, 0x600b,
+                   "isp_abort_needed=%d loop_resync_needed=%d "
+                   "fcport_update_needed=%d start_dpc=%d "
+                   "reset_marker_needed=%d",
+                   test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags),
+                   test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags),
+                   test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags),
+                   start_dpc,
+                   test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags));
+               ql_dbg(ql_dbg_timer, vha, 0x600c,
+                   "beacon_blink_needed=%d isp_unrecoverable=%d "
+                   "fcoe_ctx_reset_needed=%d vp_dpc_needed=%d "
+                   "relogin_needed=%d.\n",
+                   test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags),
+                   test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags),
+                   test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags),
+                   test_bit(VP_DPC_NEEDED, &vha->dpc_flags),
+                   test_bit(RELOGIN_NEEDED, &vha->dpc_flags));
                qla2xxx_wake_dpc(vha);
+       }
 
        qla2x00_restart_timer(vha, WATCH_INTERVAL);
 }
@@ -3806,8 +3995,8 @@ qla2x00_request_firmware(scsi_qla_host_t *vha)
                goto out;
 
        if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
-               DEBUG2(printk("scsi(%ld): Failed to load firmware image "
-                   "(%s).\n", vha->host_no, blob->name));
+               ql_log(ql_log_warn, vha, 0x0063,
+                   "Failed to load firmware image (%s).\n", blob->name);
                blob->fw = NULL;
                blob = NULL;
                goto out;
@@ -3836,8 +4025,8 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
        scsi_qla_host_t *vha = pci_get_drvdata(pdev);
        struct qla_hw_data *ha = vha->hw;
 
-       DEBUG2(qla_printk(KERN_WARNING, ha, "error_detected:state %x\n",
-           state));
+       ql_dbg(ql_dbg_aer, vha, 0x9000,
+           "PCI error detected, state %x.\n", state);
 
        switch (state) {
        case pci_channel_io_normal:
@@ -3850,9 +4039,9 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
                        ha->flags.isp82xx_fw_hung = 1;
                        if (ha->flags.mbox_busy) {
                                ha->flags.mbox_int = 1;
-                               DEBUG2(qla_printk(KERN_ERR, ha,
-                                       "Due to pci channel io frozen, doing premature "
-                                       "completion of mbx command\n"));
+                               ql_dbg(ql_dbg_aer, vha, 0x9001,
+                                   "Due to pci channel io frozen, doing premature "
+                                   "completion of mbx command.\n");
                                complete(&ha->mbx_intr_comp);
                        }
                }
@@ -3900,8 +4089,8 @@ qla2xxx_pci_mmio_enabled(struct pci_dev *pdev)
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        if (risc_paused) {
-               qla_printk(KERN_INFO, ha, "RISC paused -- mmio_enabled, "
-                   "Dumping firmware!\n");
+               ql_log(ql_log_info, base_vha, 0x9003,
+                   "RISC paused -- mmio_enabled, Dumping firmware.\n");
                ha->isp_ops->fw_dump(base_vha, 0);
 
                return PCI_ERS_RESULT_NEED_RESET;
@@ -3917,8 +4106,8 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
        int fn;
        struct pci_dev *other_pdev = NULL;
 
-       DEBUG17(qla_printk(KERN_INFO, ha,
-           "scsi(%ld): In qla82xx_error_recovery\n", base_vha->host_no));
+       ql_dbg(ql_dbg_aer, base_vha, 0x9006,
+           "Entered %s.\n", __func__);
 
        set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
 
@@ -3932,8 +4121,8 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
        fn = PCI_FUNC(ha->pdev->devfn);
        while (fn > 0) {
                fn--;
-               DEBUG17(qla_printk(KERN_INFO, ha,
-                   "Finding pci device at function = 0x%x\n", fn));
+               ql_dbg(ql_dbg_aer, base_vha, 0x9007,
+                   "Finding pci device at function = 0x%x.\n", fn);
                other_pdev =
                    pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
                    ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
@@ -3942,9 +4131,9 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
                if (!other_pdev)
                        continue;
                if (atomic_read(&other_pdev->enable_cnt)) {
-                       DEBUG17(qla_printk(KERN_INFO, ha,
-                           "Found PCI func available and enabled at 0x%x\n",
-                           fn));
+                       ql_dbg(ql_dbg_aer, base_vha, 0x9008,
+                           "Found PCI func available and enable at 0x%x.\n",
+                           fn);
                        pci_dev_put(other_pdev);
                        break;
                }
@@ -3953,8 +4142,9 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
 
        if (!fn) {
                /* Reset owner */
-               DEBUG17(qla_printk(KERN_INFO, ha,
-                   "This devfn is reset owner = 0x%x\n", ha->pdev->devfn));
+               ql_dbg(ql_dbg_aer, base_vha, 0x9009,
+                   "This devfn is reset owner = 0x%x.\n",
+                   ha->pdev->devfn);
                qla82xx_idc_lock(ha);
 
                qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
@@ -3964,8 +4154,8 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
                    QLA82XX_IDC_VERSION);
 
                drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
-               DEBUG17(qla_printk(KERN_INFO, ha,
-                   "drv_active = 0x%x\n", drv_active));
+               ql_dbg(ql_dbg_aer, base_vha, 0x900a,
+                   "drv_active = 0x%x.\n", drv_active);
 
                qla82xx_idc_unlock(ha);
                /* Reset if device is not already reset
@@ -3978,12 +4168,14 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
                qla82xx_idc_lock(ha);
 
                if (rval != QLA_SUCCESS) {
-                       qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
+                       ql_log(ql_log_info, base_vha, 0x900b,
+                           "HW State: FAILED.\n");
                        qla82xx_clear_drv_active(ha);
                        qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
                            QLA82XX_DEV_FAILED);
                } else {
-                       qla_printk(KERN_INFO, ha, "HW State: READY\n");
+                       ql_log(ql_log_info, base_vha, 0x900c,
+                           "HW State: READY.\n");
                        qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
                            QLA82XX_DEV_READY);
                        qla82xx_idc_unlock(ha);
@@ -3996,8 +4188,9 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
                }
                qla82xx_idc_unlock(ha);
        } else {
-               DEBUG17(qla_printk(KERN_INFO, ha,
-                   "This devfn is not reset owner = 0x%x\n", ha->pdev->devfn));
+               ql_dbg(ql_dbg_aer, base_vha, 0x900d,
+                   "This devfn is not reset owner = 0x%x.\n",
+                   ha->pdev->devfn);
                if ((qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
                    QLA82XX_DEV_READY)) {
                        ha->flags.isp82xx_fw_hung = 0;
@@ -4021,7 +4214,8 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
        struct rsp_que *rsp;
        int rc, retries = 10;
 
-       DEBUG17(qla_printk(KERN_WARNING, ha, "slot_reset\n"));
+       ql_dbg(ql_dbg_aer, base_vha, 0x9004,
+           "Slot Reset.\n");
 
        /* Workaround: qla2xxx driver which access hardware earlier
         * needs error state to be pci_channel_io_online.
@@ -4042,7 +4236,7 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
                rc = pci_enable_device(pdev);
 
        if (rc) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, base_vha, 0x9005,
                    "Can't re-enable PCI device after reset.\n");
                goto exit_slot_reset;
        }
@@ -4072,8 +4266,8 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
 
 
 exit_slot_reset:
-       DEBUG17(qla_printk(KERN_WARNING, ha,
-           "slot_reset-return:ret=%x\n", ret));
+       ql_dbg(ql_dbg_aer, base_vha, 0x900e,
+           "slot_reset return %x.\n", ret);
 
        return ret;
 }
@@ -4085,13 +4279,13 @@ qla2xxx_pci_resume(struct pci_dev *pdev)
        struct qla_hw_data *ha = base_vha->hw;
        int ret;
 
-       DEBUG17(qla_printk(KERN_WARNING, ha, "pci_resume\n"));
+       ql_dbg(ql_dbg_aer, base_vha, 0x900f,
+           "pci_resume.\n");
 
        ret = qla2x00_wait_for_hba_online(base_vha);
        if (ret != QLA_SUCCESS) {
-               qla_printk(KERN_ERR, ha,
-                   "the device failed to resume I/O "
-                   "from slot/link_reset");
+               ql_log(ql_log_fatal, base_vha, 0x9002,
+                   "The device failed to resume I/O from slot/link_reset.\n");
        }
 
        pci_cleanup_aer_uncorrect_error_status(pdev);
@@ -4155,8 +4349,8 @@ qla2x00_module_init(void)
        srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
            SLAB_HWCACHE_ALIGN, NULL);
        if (srb_cachep == NULL) {
-               printk(KERN_ERR
-                   "qla2xxx: Unable to allocate SRB cache...Failing load!\n");
+               ql_log(ql_log_fatal, NULL, 0x0001,
+                   "Unable to allocate SRB cache...Failing load!.\n");
                return -ENOMEM;
        }
 
@@ -4169,13 +4363,15 @@ qla2x00_module_init(void)
            fc_attach_transport(&qla2xxx_transport_functions);
        if (!qla2xxx_transport_template) {
                kmem_cache_destroy(srb_cachep);
+               ql_log(ql_log_fatal, NULL, 0x0002,
+                   "fc_attach_transport failed...Failing load!.\n");
                return -ENODEV;
        }
 
        apidev_major = register_chrdev(0, QLA2XXX_APIDEV, &apidev_fops);
        if (apidev_major < 0) {
-               printk(KERN_WARNING "qla2xxx: Unable to register char device "
-                   "%s\n", QLA2XXX_APIDEV);
+               ql_log(ql_log_fatal, NULL, 0x0003,
+                   "Unable to register char device %s.\n", QLA2XXX_APIDEV);
        }
 
        qla2xxx_transport_vport_template =
@@ -4183,16 +4379,21 @@ qla2x00_module_init(void)
        if (!qla2xxx_transport_vport_template) {
                kmem_cache_destroy(srb_cachep);
                fc_release_transport(qla2xxx_transport_template);
+               ql_log(ql_log_fatal, NULL, 0x0004,
+                   "fc_attach_transport vport failed...Failing load!.\n");
                return -ENODEV;
        }
-
-       printk(KERN_INFO "QLogic Fibre Channel HBA Driver: %s\n",
+       ql_log(ql_log_info, NULL, 0x0005,
+           "QLogic Fibre Channel HBA Driver: %s.\n",
            qla2x00_version_str);
        ret = pci_register_driver(&qla2xxx_pci_driver);
        if (ret) {
                kmem_cache_destroy(srb_cachep);
                fc_release_transport(qla2xxx_transport_template);
                fc_release_transport(qla2xxx_transport_vport_template);
+               ql_log(ql_log_fatal, NULL, 0x0006,
+                   "pci_register_driver failed...ret=%d Failing load!.\n",
+                   ret);
        }
        return ret;
 }
index 6936476..eff1356 100644 (file)
@@ -189,6 +189,7 @@ qla2x00_write_nvram_word(struct qla_hw_data *ha, uint32_t addr, uint16_t data)
        uint16_t word;
        uint32_t nv_cmd, wait_cnt;
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        qla2x00_nv_write(ha, NVR_DATA_OUT);
        qla2x00_nv_write(ha, 0);
@@ -220,8 +221,8 @@ qla2x00_write_nvram_word(struct qla_hw_data *ha, uint32_t addr, uint16_t data)
        wait_cnt = NVR_WAIT_CNT;
        do {
                if (!--wait_cnt) {
-                       DEBUG9_10(qla_printk(KERN_WARNING, ha,
-                           "NVRAM didn't go ready...\n"));
+                       ql_dbg(ql_dbg_user, vha, 0x708d,
+                           "NVRAM didn't go ready...\n");
                        break;
                }
                NVRAM_DELAY();
@@ -308,6 +309,7 @@ qla2x00_clear_nvram_protection(struct qla_hw_data *ha)
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
        uint32_t word, wait_cnt;
        uint16_t wprot, wprot_old;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        /* Clear NVRAM write protection. */
        ret = QLA_FUNCTION_FAILED;
@@ -350,8 +352,8 @@ qla2x00_clear_nvram_protection(struct qla_hw_data *ha)
                wait_cnt = NVR_WAIT_CNT;
                do {
                        if (!--wait_cnt) {
-                               DEBUG9_10(qla_printk(KERN_WARNING, ha,
-                                   "NVRAM didn't go ready...\n"));
+                               ql_dbg(ql_dbg_user, vha, 0x708e,
+                                   "NVRAM didn't go ready...\n");
                                break;
                        }
                        NVRAM_DELAY();
@@ -371,6 +373,7 @@ qla2x00_set_nvram_protection(struct qla_hw_data *ha, int stat)
 {
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
        uint32_t word, wait_cnt;
+       scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
        if (stat != QLA_SUCCESS)
                return;
@@ -409,8 +412,8 @@ qla2x00_set_nvram_protection(struct qla_hw_data *ha, int stat)
        wait_cnt = NVR_WAIT_CNT;
        do {
                if (!--wait_cnt) {
-                       DEBUG9_10(qla_printk(KERN_WARNING, ha,
-                           "NVRAM didn't go ready...\n"));
+                       ql_dbg(ql_dbg_user, vha, 0x708f,
+                           "NVRAM didn't go ready...\n");
                        break;
                }
                NVRAM_DELAY();
@@ -607,9 +610,10 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
        for (chksum = 0; cnt; cnt--)
                chksum += le16_to_cpu(*wptr++);
        if (chksum) {
-               qla_printk(KERN_ERR, ha,
+               ql_log(ql_log_fatal, vha, 0x0045,
                    "Inconsistent FLTL detected: checksum=0x%x.\n", chksum);
-               qla2x00_dump_buffer(buf, sizeof(struct qla_flt_location));
+               ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010e,
+                   buf, sizeof(struct qla_flt_location));
                return QLA_FUNCTION_FAILED;
        }
 
@@ -618,7 +622,9 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
        *start = (le16_to_cpu(fltl->start_hi) << 16 |
            le16_to_cpu(fltl->start_lo)) >> 2;
 end:
-       DEBUG2(qla_printk(KERN_DEBUG, ha, "FLTL[%s] = 0x%x.\n", loc, *start));
+       ql_dbg(ql_dbg_init, vha, 0x0046,
+           "FLTL[%s] = 0x%x.\n",
+           loc, *start);
        return QLA_SUCCESS;
 }
 
@@ -685,10 +691,10 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
        if (*wptr == __constant_cpu_to_le16(0xffff))
                goto no_flash_data;
        if (flt->version != __constant_cpu_to_le16(1)) {
-               DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported FLT detected: "
-                   "version=0x%x length=0x%x checksum=0x%x.\n",
+               ql_log(ql_log_warn, vha, 0x0047,
+                   "Unsupported FLT detected: version=0x%x length=0x%x checksum=0x%x.\n",
                    le16_to_cpu(flt->version), le16_to_cpu(flt->length),
-                   le16_to_cpu(flt->checksum)));
+                   le16_to_cpu(flt->checksum));
                goto no_flash_data;
        }
 
@@ -696,10 +702,10 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
        for (chksum = 0; cnt; cnt--)
                chksum += le16_to_cpu(*wptr++);
        if (chksum) {
-               DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent FLT detected: "
-                   "version=0x%x length=0x%x checksum=0x%x.\n",
+               ql_log(ql_log_fatal, vha, 0x0048,
+                   "Inconsistent FLT detected: version=0x%x length=0x%x checksum=0x%x.\n",
                    le16_to_cpu(flt->version), le16_to_cpu(flt->length),
-                   chksum));
+                   le16_to_cpu(flt->checksum));
                goto no_flash_data;
        }
 
@@ -708,10 +714,11 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
        for ( ; cnt; cnt--, region++) {
                /* Store addresses as DWORD offsets. */
                start = le32_to_cpu(region->start) >> 2;
-
-               DEBUG3(qla_printk(KERN_DEBUG, ha, "FLT[%02x]: start=0x%x "
-                   "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start,
-                   le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size)));
+               ql_dbg(ql_dbg_init, vha, 0x0049,
+                   "FLT[%02x]: start=0x%x "
+                   "end=0x%x size=0x%x.\n", le32_to_cpu(region->code),
+                   start, le32_to_cpu(region->end) >> 2,
+                   le32_to_cpu(region->size));
 
                switch (le32_to_cpu(region->code) & 0xff) {
                case FLT_REG_FW:
@@ -796,12 +803,16 @@ no_flash_data:
        ha->flt_region_npiv_conf = ha->flags.port0 ?
            def_npiv_conf0[def] : def_npiv_conf1[def];
 done:
-       DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x "
-           "vpd_nvram=0x%x vpd=0x%x nvram=0x%x fdt=0x%x flt=0x%x "
-           "npiv=0x%x. fcp_prio_cfg=0x%x\n", loc, ha->flt_region_boot,
-           ha->flt_region_fw, ha->flt_region_vpd_nvram, ha->flt_region_vpd,
-           ha->flt_region_nvram, ha->flt_region_fdt, ha->flt_region_flt,
-           ha->flt_region_npiv_conf, ha->flt_region_fcp_prio));
+       ql_dbg(ql_dbg_init, vha, 0x004a,
+           "FLT[%s]: boot=0x%x fw=0x%x vpd_nvram=0x%x vpd=0x%x.\n",
+           loc, ha->flt_region_boot,
+           ha->flt_region_fw, ha->flt_region_vpd_nvram,
+           ha->flt_region_vpd);
+       ql_dbg(ql_dbg_init, vha, 0x004b,
+           "nvram=0x%x fdt=0x%x flt=0x%x npiv=0x%x fcp_prif_cfg=0x%x.\n",
+           ha->flt_region_nvram,
+           ha->flt_region_fdt, ha->flt_region_flt,
+           ha->flt_region_npiv_conf, ha->flt_region_fcp_prio);
 }
 
 static void
@@ -833,10 +844,12 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha)
            cnt++)
                chksum += le16_to_cpu(*wptr++);
        if (chksum) {
-               DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent FDT detected: "
-                   "checksum=0x%x id=%c version=0x%x.\n", chksum, fdt->sig[0],
-                   le16_to_cpu(fdt->version)));
-               DEBUG9(qla2x00_dump_buffer((uint8_t *)fdt, sizeof(*fdt)));
+               ql_dbg(ql_dbg_init, vha, 0x004c,
+                   "Inconsistent FDT detected:"
+                   " checksum=0x%x id=%c version0x%x.\n", chksum,
+                   fdt->sig[0], le16_to_cpu(fdt->version));
+               ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0113,
+                   (uint8_t *)fdt, sizeof(*fdt));
                goto no_flash_data;
        }
 
@@ -890,11 +903,12 @@ no_flash_data:
                break;
        }
 done:
-       DEBUG2(qla_printk(KERN_DEBUG, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x "
-           "pro=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid,
+       ql_dbg(ql_dbg_init, vha, 0x004d,
+           "FDT[%x]: (0x%x/0x%x) erase=0x%x "
+           "pr=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid,
            ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd,
-           ha->fdt_unprotect_sec_cmd, ha->fdt_wrt_disable,
-           ha->fdt_block_size));
+           ha->fdt_wrt_disable, ha->fdt_block_size);
+
 }
 
 static void
@@ -919,6 +933,10 @@ qla2xxx_get_idc_param(scsi_qla_host_t *vha)
                ha->nx_dev_init_timeout = le32_to_cpu(*wptr++);
                ha->nx_reset_timeout = le32_to_cpu(*wptr);
        }
+       ql_dbg(ql_dbg_init, vha, 0x004e,
+           "nx_dev_init_timeout=%d "
+           "nx_reset_timeout=%d.\n", ha->nx_dev_init_timeout,
+           ha->nx_reset_timeout);
        return;
 }
 
@@ -963,17 +981,18 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
        if (hdr.version == __constant_cpu_to_le16(0xffff))
                return;
        if (hdr.version != __constant_cpu_to_le16(1)) {
-               DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported NPIV-Config "
+               ql_dbg(ql_dbg_user, vha, 0x7090,
+                   "Unsupported NPIV-Config "
                    "detected: version=0x%x entries=0x%x checksum=0x%x.\n",
                    le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries),
-                   le16_to_cpu(hdr.checksum)));
+                   le16_to_cpu(hdr.checksum));
                return;
        }
 
        data = kmalloc(NPIV_CONFIG_SIZE, GFP_KERNEL);
        if (!data) {
-               DEBUG2(qla_printk(KERN_INFO, ha, "NPIV-Config: Unable to "
-                   "allocate memory.\n"));
+               ql_log(ql_log_warn, vha, 0x7091,
+                   "Unable to allocate memory for data.\n");
                return;
        }
 
@@ -985,10 +1004,11 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
        for (wptr = data, chksum = 0; cnt; cnt--)
                chksum += le16_to_cpu(*wptr++);
        if (chksum) {
-               DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent NPIV-Config "
+               ql_dbg(ql_dbg_user, vha, 0x7092,
+                   "Inconsistent NPIV-Config "
                    "detected: version=0x%x entries=0x%x checksum=0x%x.\n",
                    le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries),
-                   chksum));
+                   le16_to_cpu(hdr.checksum));
                goto done;
        }
 
@@ -1014,21 +1034,22 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
                vid.port_name = wwn_to_u64(entry->port_name);
                vid.node_name = wwn_to_u64(entry->node_name);
 
-               DEBUG2(qla_printk(KERN_INFO, ha, "NPIV[%02x]: wwpn=%llx "
-                       "wwnn=%llx vf_id=0x%x Q_qos=0x%x F_qos=0x%x.\n", cnt,
-                       (unsigned long long)vid.port_name,
-                       (unsigned long long)vid.node_name,
-                       le16_to_cpu(entry->vf_id),
-                       entry->q_qos, entry->f_qos));
+               ql_dbg(ql_dbg_user, vha, 0x7093,
+                   "NPIV[%02x]: wwpn=%llx "
+                   "wwnn=%llx vf_id=0x%x Q_qos=0x%x F_qos=0x%x.\n", cnt,
+                   (unsigned long long)vid.port_name,
+                   (unsigned long long)vid.node_name,
+                   le16_to_cpu(entry->vf_id),
+                   entry->q_qos, entry->f_qos);
 
                if (i < QLA_PRECONFIG_VPORTS) {
                        vport = fc_vport_create(vha->host, 0, &vid);
                        if (!vport)
-                               qla_printk(KERN_INFO, ha,
-                               "NPIV-Config: Failed to create vport [%02x]: "
-                               "wwpn=%llx wwnn=%llx.\n", cnt,
-                               (unsigned long long)vid.port_name,
-                               (unsigned long long)vid.node_name);
+                               ql_log(ql_log_warn, vha, 0x7094,
+                                   "NPIV-Config Failed to create vport [%02x]: "
+                                   "wwpn=%llx wwnn=%llx.\n", cnt,
+                                   (unsigned long long)vid.port_name,
+                                   (unsigned long long)vid.node_name);
                }
        }
 done:
@@ -1127,9 +1148,10 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
                optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
                    &optrom_dma, GFP_KERNEL);
                if (!optrom) {
-                       qla_printk(KERN_DEBUG, ha,
-                           "Unable to allocate memory for optrom burst write "
-                           "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
+                       ql_log(ql_log_warn, vha, 0x7095,
+                           "Unable to allocate "
+                           "memory for optrom burst write (%x KB).\n",
+                           OPTROM_BURST_SIZE / 1024);
                }
        }
 
@@ -1138,7 +1160,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
 
        ret = qla24xx_unprotect_flash(vha);
        if (ret != QLA_SUCCESS) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x7096,
                    "Unable to unprotect flash for update.\n");
                goto done;
        }
@@ -1156,9 +1178,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
                                    0xff0000) | ((fdata >> 16) & 0xff));
                        ret = qla24xx_erase_sector(vha, fdata);
                        if (ret != QLA_SUCCESS) {
-                               DEBUG9(qla_printk(KERN_WARNING, ha,
-                                   "Unable to erase sector: address=%x.\n",
-                                   faddr));
+                               ql_dbg(ql_dbg_user, vha, 0x7007,
+                                   "Unable to erase erase sector: address=%x.\n",
+                                   faddr);
                                break;
                        }
                }
@@ -1172,12 +1194,12 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
                            flash_data_addr(ha, faddr),
                            OPTROM_BURST_DWORDS);
                        if (ret != QLA_SUCCESS) {
-                               qla_printk(KERN_WARNING, ha,
+                               ql_log(ql_log_warn, vha, 0x7097,
                                    "Unable to burst-write optrom segment "
                                    "(%x/%x/%llx).\n", ret,
                                    flash_data_addr(ha, faddr),
                                    (unsigned long long)optrom_dma);
-                               qla_printk(KERN_WARNING, ha,
+                               ql_log(ql_log_warn, vha, 0x7098,
                                    "Reverting to slow-write.\n");
 
                                dma_free_coherent(&ha->pdev->dev,
@@ -1194,9 +1216,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
                ret = qla24xx_write_flash_dword(ha,
                    flash_data_addr(ha, faddr), cpu_to_le32(*dwptr));
                if (ret != QLA_SUCCESS) {
-                       DEBUG9(printk("%s(%ld) Unable to program flash "
-                           "address=%x data=%x.\n", __func__,
-                           vha->host_no, faddr, *dwptr));
+                       ql_dbg(ql_dbg_user, vha, 0x7006,
+                           "Unable to program flash address=%x data=%x.\n",
+                           faddr, *dwptr);
                        break;
                }
 
@@ -1211,7 +1233,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
 
        ret = qla24xx_protect_flash(vha);
        if (ret != QLA_SUCCESS)
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x7099,
                    "Unable to protect flash after update.\n");
 done:
        if (optrom)
@@ -1324,9 +1346,9 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
                ret = qla24xx_write_flash_dword(ha,
                    nvram_data_addr(ha, naddr), cpu_to_le32(*dwptr));
                if (ret != QLA_SUCCESS) {
-                       DEBUG9(qla_printk(KERN_WARNING, ha,
+                       ql_dbg(ql_dbg_user, vha, 0x709a,
                            "Unable to program nvram address=%x data=%x.\n",
-                           naddr, *dwptr));
+                           naddr, *dwptr);
                        break;
                }
        }
@@ -1476,7 +1498,7 @@ qla2x00_beacon_on(struct scsi_qla_host *vha)
        ha->fw_options[1] |= FO1_DISABLE_GPIO6_7;
 
        if (qla2x00_set_fw_options(vha, ha->fw_options) != QLA_SUCCESS) {
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x709b,
                    "Unable to update fw options (beacon on).\n");
                return QLA_FUNCTION_FAILED;
        }
@@ -1541,7 +1563,7 @@ qla2x00_beacon_off(struct scsi_qla_host *vha)
 
        rval = qla2x00_set_fw_options(vha, ha->fw_options);
        if (rval != QLA_SUCCESS)
-               qla_printk(KERN_WARNING, ha,
+               ql_log(ql_log_warn, vha, 0x709c,
                    "Unable to update fw options (beacon off).\n");
        return rval;
 }
@@ -1616,7 +1638,7 @@ qla24xx_beacon_on(struct scsi_qla_host *vha)
 
                if (qla2x00_get_fw_options(vha, ha->fw_options) !=
                    QLA_SUCCESS) {
-                       qla_printk(KERN_WARNING, ha,
+                       ql_log(ql_log_warn, vha, 0x7009,
                            "Unable to update fw options (beacon on).\n");
                        return QLA_FUNCTION_FAILED;
                }
@@ -1670,14 +1692,14 @@ qla24xx_beacon_off(struct scsi_qla_host *vha)
        ha->fw_options[1] &= ~ADD_FO1_DISABLE_GPIO_LED_CTRL;
 
        if (qla2x00_set_fw_options(vha, ha->fw_options) != QLA_SUCCESS) {
-               qla_printk(KERN_WARNING, ha,
-                   "Unable to update fw options (beacon off).\n");
+               ql_log(ql_log_warn, vha, 0x704d,
+                   "Unable to update fw options (beacon on).\n");
                return QLA_FUNCTION_FAILED;
        }
 
        if (qla2x00_get_fw_options(vha, ha->fw_options) != QLA_SUCCESS) {
-               qla_printk(KERN_WARNING, ha,
-                   "Unable to get fw options (beacon off).\n");
+               ql_log(ql_log_warn, vha, 0x704e,
+                   "Unable to update fw options (beacon on).\n");
                return QLA_FUNCTION_FAILED;
        }
 
@@ -2389,10 +2411,9 @@ try_fast:
        optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
            &optrom_dma, GFP_KERNEL);
        if (!optrom) {
-               qla_printk(KERN_DEBUG, ha,
-                   "Unable to allocate memory for optrom burst read "
-                   "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
-
+               ql_log(ql_log_warn, vha, 0x00cc,
+                   "Unable to allocate memory for optrom burst read (%x KB).\n",
+                   OPTROM_BURST_SIZE / 1024);
                goto slow_read;
        }
 
@@ -2407,12 +2428,11 @@ try_fast:
                rval = qla2x00_dump_ram(vha, optrom_dma,
                    flash_data_addr(ha, faddr), burst);
                if (rval) {
-                       qla_printk(KERN_WARNING, ha,
-                           "Unable to burst-read optrom segment "
-                           "(%x/%x/%llx).\n", rval,
-                           flash_data_addr(ha, faddr),
+                       ql_log(ql_log_warn, vha, 0x00f5,
+                           "Unable to burst-read optrom segment (%x/%x/%llx).\n",
+                           rval, flash_data_addr(ha, faddr),
                            (unsigned long long)optrom_dma);
-                       qla_printk(KERN_WARNING, ha,
+                       ql_log(ql_log_warn, vha, 0x00f6,
                            "Reverting to slow-read.\n");
 
                        dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
@@ -2556,8 +2576,8 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
                if (qla2x00_read_flash_byte(ha, pcihdr) != 0x55 ||
                    qla2x00_read_flash_byte(ha, pcihdr + 0x01) != 0xaa) {
                        /* No signature */
-                       DEBUG2(qla_printk(KERN_DEBUG, ha, "No matching ROM "
-                           "signature.\n"));
+                       ql_log(ql_log_fatal, vha, 0x0050,
+                           "No matching ROM signature.\n");
                        ret = QLA_FUNCTION_FAILED;
                        break;
                }
@@ -2573,8 +2593,8 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
                    qla2x00_read_flash_byte(ha, pcids + 0x2) != 'I' ||
                    qla2x00_read_flash_byte(ha, pcids + 0x3) != 'R') {
                        /* Incorrect header. */
-                       DEBUG2(qla_printk(KERN_INFO, ha, "PCI data struct not "
-                           "found pcir_adr=%x.\n", pcids));
+                       ql_log(ql_log_fatal, vha, 0x0051,
+                           "PCI data struct not found pcir_adr=%x.\n", pcids);
                        ret = QLA_FUNCTION_FAILED;
                        break;
                }
@@ -2588,8 +2608,9 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
                            qla2x00_read_flash_byte(ha, pcids + 0x12);
                        ha->bios_revision[1] =
                            qla2x00_read_flash_byte(ha, pcids + 0x13);
-                       DEBUG3(qla_printk(KERN_DEBUG, ha, "read BIOS %d.%d.\n",
-                           ha->bios_revision[1], ha->bios_revision[0]));
+                       ql_dbg(ql_dbg_init, vha, 0x0052,
+                           "Read BIOS %d.%d.\n",
+                           ha->bios_revision[1], ha->bios_revision[0]);
                        break;
                case ROM_CODE_TYPE_FCODE:
                        /* Open Firmware standard for PCI (FCode). */
@@ -2602,12 +2623,14 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
                            qla2x00_read_flash_byte(ha, pcids + 0x12);
                        ha->efi_revision[1] =
                            qla2x00_read_flash_byte(ha, pcids + 0x13);
-                       DEBUG3(qla_printk(KERN_DEBUG, ha, "read EFI %d.%d.\n",
-                           ha->efi_revision[1], ha->efi_revision[0]));
+                       ql_dbg(ql_dbg_init, vha, 0x0053,
+                           "Read EFI %d.%d.\n",
+                           ha->efi_revision[1], ha->efi_revision[0]);
                        break;
                default:
-                       DEBUG2(qla_printk(KERN_INFO, ha, "Unrecognized code "
-                           "type %x at pcids %x.\n", code_type, pcids));
+                       ql_log(ql_log_warn, vha, 0x0054,
+                           "Unrecognized code type %x at pcids %x.\n",
+                           code_type, pcids);
                        break;
                }
 
@@ -2627,21 +2650,28 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
 
                qla2x00_read_flash_data(ha, dbyte, ha->flt_region_fw * 4 + 10,
                    8);
-               DEBUG3(qla_printk(KERN_DEBUG, ha, "dumping fw ver from "
-                   "flash:\n"));
-               DEBUG3(qla2x00_dump_buffer((uint8_t *)dbyte, 8));
+               ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x010a,
+                   "Dumping fw "
+                   "ver from flash:.\n");
+               ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010b,
+                   (uint8_t *)dbyte, 8);
 
                if ((dcode[0] == 0xffff && dcode[1] == 0xffff &&
                    dcode[2] == 0xffff && dcode[3] == 0xffff) ||
                    (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
                    dcode[3] == 0)) {
-                       DEBUG2(qla_printk(KERN_INFO, ha, "Unrecognized fw "
-                           "revision at %x.\n", ha->flt_region_fw * 4));
+                       ql_log(ql_log_warn, vha, 0x0057,
+                           "Unrecognized fw revision at %x.\n",
+                           ha->flt_region_fw * 4);
                } else {
                        /* values are in big endian */
                        ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1];
                        ha->fw_revision[1] = dbyte[2] << 16 | dbyte[3];
                        ha->fw_revision[2] = dbyte[4] << 16 | dbyte[5];
+                       ql_dbg(ql_dbg_init, vha, 0x0058,
+                           "FW Version: "
+                           "%d.%d.%d.\n", ha->fw_revision[0],
+                           ha->fw_revision[1], ha->fw_revision[2]);
                }
        }
 
@@ -2683,8 +2713,8 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
                bcode = mbuf + (pcihdr % 4);
                if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) {
                        /* No signature */
-                       DEBUG2(qla_printk(KERN_DEBUG, ha, "No matching ROM "
-                           "signature.\n"));
+                       ql_log(ql_log_fatal, vha, 0x0059,
+                           "No matching ROM signature.\n");
                        ret = QLA_FUNCTION_FAILED;
                        break;
                }
@@ -2699,8 +2729,8 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
                if (bcode[0x0] != 'P' || bcode[0x1] != 'C' ||
                    bcode[0x2] != 'I' || bcode[0x3] != 'R') {
                        /* Incorrect header. */
-                       DEBUG2(qla_printk(KERN_INFO, ha, "PCI data struct not "
-                           "found pcir_adr=%x.\n", pcids));
+                       ql_log(ql_log_fatal, vha, 0x005a,
+                           "PCI data struct not found pcir_adr=%x.\n", pcids);
                        ret = QLA_FUNCTION_FAILED;
                        break;
                }
@@ -2712,26 +2742,30 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
                        /* Intel x86, PC-AT compatible. */
                        ha->bios_revision[0] = bcode[0x12];
                        ha->bios_revision[1] = bcode[0x13];
-                       DEBUG3(qla_printk(KERN_DEBUG, ha, "read BIOS %d.%d.\n",
-                           ha->bios_revision[1], ha->bios_revision[0]));
+                       ql_dbg(ql_dbg_init, vha, 0x005b,
+                           "Read BIOS %d.%d.\n",
+                           ha->bios_revision[1], ha->bios_revision[0]);
                        break;
                case ROM_CODE_TYPE_FCODE:
                        /* Open Firmware standard for PCI (FCode). */
                        ha->fcode_revision[0] = bcode[0x12];
                        ha->fcode_revision[1] = bcode[0x13];
-                       DEBUG3(qla_printk(KERN_DEBUG, ha, "read FCODE %d.%d.\n",
-                           ha->fcode_revision[1], ha->fcode_revision[0]));
+                       ql_dbg(ql_dbg_init, vha, 0x005c,
+                           "Read FCODE %d.%d.\n",
+                           ha->fcode_revision[1], ha->fcode_revision[0]);
                        break;
                case ROM_CODE_TYPE_EFI:
                        /* Extensible Firmware Interface (EFI). */
                        ha->efi_revision[0] = bcode[0x12];
                        ha->efi_revision[1] = bcode[0x13];
-                       DEBUG3(qla_printk(KERN_DEBUG, ha, "read EFI %d.%d.\n",
-                           ha->efi_revision[1], ha->efi_revision[0]));
+                       ql_dbg(ql_dbg_init, vha, 0x005d,
+                           "Read EFI %d.%d.\n",
+                           ha->efi_revision[1], ha->efi_revision[0]);
                        break;
                default:
-                       DEBUG2(qla_printk(KERN_INFO, ha, "Unrecognized code "
-                           "type %x at pcids %x.\n", code_type, pcids));
+                       ql_log(ql_log_warn, vha, 0x005e,
+                           "Unrecognized code type %x at pcids %x.\n",
+                           code_type, pcids);
                        break;
                }
 
@@ -2753,13 +2787,18 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
            dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
            (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
            dcode[3] == 0)) {
-               DEBUG2(qla_printk(KERN_INFO, ha, "Unrecognized fw "
-                   "revision at %x.\n", ha->flt_region_fw * 4));
+               ql_log(ql_log_warn, vha, 0x005f,
+                   "Unrecognized fw revision at %x.\n",
+                   ha->flt_region_fw * 4);
        } else {
                ha->fw_revision[0] = dcode[0];
                ha->fw_revision[1] = dcode[1];
                ha->fw_revision[2] = dcode[2];
                ha->fw_revision[3] = dcode[3];
+               ql_dbg(ql_dbg_init, vha, 0x0060,
+                   "Firmware revision %d.%d.%d.%d.\n",
+                   ha->fw_revision[0], ha->fw_revision[1],
+                   ha->fw_revision[2], ha->fw_revision[3]);
        }
 
        /* Check for golden firmware and get version if available */
@@ -2775,9 +2814,9 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
 
        if (dcode[4] == 0xFFFFFFFF && dcode[5] == 0xFFFFFFFF &&
            dcode[6] == 0xFFFFFFFF && dcode[7] == 0xFFFFFFFF) {
-               DEBUG2(qla_printk(KERN_INFO, ha,
-                   "%s(%ld): Unrecognized golden fw at 0x%x.\n",
-                   __func__, vha->host_no, ha->flt_region_gold_fw * 4));
+               ql_log(ql_log_warn, vha, 0x0056,
+                   "Unrecognized golden fw at 0x%x.\n",
+                   ha->flt_region_gold_fw * 4);
                return ret;
        }
 
@@ -2843,9 +2882,9 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha)
        if (!ha->fcp_prio_cfg) {
                ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
                if (!ha->fcp_prio_cfg) {
-                       qla_printk(KERN_WARNING, ha,
-                       "Unable to allocate memory for fcp priority data "
-                                       "(%x).\n", FCP_PRIO_CFG_SIZE);
+                       ql_log(ql_log_warn, vha, 0x00d5,
+                           "Unable to allocate memory for fcp priorty data (%x).\n",
+                           FCP_PRIO_CFG_SIZE);
                        return QLA_FUNCTION_FAILED;
                }
        }
@@ -2857,7 +2896,7 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha)
        ha->isp_ops->read_optrom(vha, (uint8_t *)ha->fcp_prio_cfg,
                        fcp_prio_addr << 2, FCP_PRIO_CFG_HDR_SIZE);
 
-       if (!qla24xx_fcp_prio_cfg_valid(ha->fcp_prio_cfg, 0))
+       if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 0))
                goto fail;
 
        /* read remaining FCP CMD config data from flash */
@@ -2869,7 +2908,7 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha)
                        fcp_prio_addr << 2, (len < max_len ? len : max_len));
 
        /* revalidate the entire FCP priority config data, including entries */
-       if (!qla24xx_fcp_prio_cfg_valid(ha->fcp_prio_cfg, 1))
+       if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 1))
                goto fail;
 
        ha->flags.fcp_prio_enabled = 1;
index 28d9c9d..fc3f168 100644 (file)
@@ -137,6 +137,7 @@ static int __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy)
                host->host_blocked = host->max_host_blocked;
                break;
        case SCSI_MLQUEUE_DEVICE_BUSY:
+       case SCSI_MLQUEUE_EH_RETRY:
                device->device_blocked = device->max_device_blocked;
                break;
        case SCSI_MLQUEUE_TARGET_BUSY:
index 8a172d4..5fbeadd 100644 (file)
@@ -597,6 +597,28 @@ static DEVICE_ATTR(signalling, S_IRUGO,
                   show_spi_host_signalling,
                   store_spi_host_signalling);
 
+static ssize_t show_spi_host_width(struct device *cdev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct Scsi_Host *shost = transport_class_to_shost(cdev);
+
+       return sprintf(buf, "%s\n", shost->max_id == 16 ? "wide" : "narrow");
+}
+static DEVICE_ATTR(host_width, S_IRUGO,
+                  show_spi_host_width, NULL);
+
+static ssize_t show_spi_host_hba_id(struct device *cdev,
+                                   struct device_attribute *attr,
+                                   char *buf)
+{
+       struct Scsi_Host *shost = transport_class_to_shost(cdev);
+
+       return sprintf(buf, "%d\n", shost->this_id);
+}
+static DEVICE_ATTR(hba_id, S_IRUGO,
+                  show_spi_host_hba_id, NULL);
+
 #define DV_SET(x, y)                   \
        if(i->f->set_##x)               \
                i->f->set_##x(sdev->sdev_target, y)
@@ -1380,6 +1402,8 @@ static DECLARE_ANON_TRANSPORT_CLASS(spi_device_class,
 
 static struct attribute *host_attributes[] = {
        &dev_attr_signalling.attr,
+       &dev_attr_host_width.attr,
+       &dev_attr_hba_id.attr,
        NULL
 };
 
index d6702e5..dc8d022 100644 (file)
@@ -34,6 +34,9 @@ static LIST_HEAD(clock_list);
 static DEFINE_SPINLOCK(clock_lock);
 static DEFINE_MUTEX(clock_list_sem);
 
+/* clock disable operations are not passed on to hardware during boot */
+static int allow_disable;
+
 void clk_rate_table_build(struct clk *clk,
                          struct cpufreq_frequency_table *freq_table,
                          int nr_freqs,
@@ -228,7 +231,7 @@ static void __clk_disable(struct clk *clk)
                return;
 
        if (!(--clk->usecount)) {
-               if (likely(clk->ops && clk->ops->disable))
+               if (likely(allow_disable && clk->ops && clk->ops->disable))
                        clk->ops->disable(clk);
                if (likely(clk->parent))
                        __clk_disable(clk->parent);
@@ -393,7 +396,7 @@ int clk_register(struct clk *clk)
 {
        int ret;
 
-       if (clk == NULL || IS_ERR(clk))
+       if (IS_ERR_OR_NULL(clk))
                return -EINVAL;
 
        /*
@@ -744,3 +747,25 @@ err_out:
        return err;
 }
 late_initcall(clk_debugfs_init);
+
+static int __init clk_late_init(void)
+{
+       unsigned long flags;
+       struct clk *clk;
+
+       /* disable all clocks with zero use count */
+       mutex_lock(&clock_list_sem);
+       spin_lock_irqsave(&clock_lock, flags);
+
+       list_for_each_entry(clk, &clock_list, node)
+               if (!clk->usecount && clk->ops && clk->ops->disable)
+                       clk->ops->disable(clk);
+
+       /* from now on allow clock disable operations */
+       allow_disable = 1;
+
+       spin_unlock_irqrestore(&clock_lock, flags);
+       mutex_unlock(&clock_list_sem);
+       return 0;
+}
+late_initcall(clk_late_init);
index eba88c7..730b4a3 100644 (file)
@@ -2267,17 +2267,13 @@ static int __devexit
 pl022_remove(struct amba_device *adev)
 {
        struct pl022 *pl022 = amba_get_drvdata(adev);
-       int status = 0;
+
        if (!pl022)
                return 0;
 
        /* Remove the queue */
-       status = destroy_queue(pl022);
-       if (status != 0) {
-               dev_err(&adev->dev,
-                       "queue remove failed (%d)\n", status);
-               return status;
-       }
+       if (destroy_queue(pl022) != 0)
+               dev_err(&adev->dev, "queue remove failed\n");
        load_ssp_default_config(pl022);
        pl022_dma_remove(pl022);
        free_irq(adev->irq[0], pl022);
@@ -2289,7 +2285,6 @@ pl022_remove(struct amba_device *adev)
        spi_unregister_master(pl022->master);
        spi_master_put(pl022->master);
        amba_set_drvdata(adev, NULL);
-       dev_dbg(&adev->dev, "remove succeeded\n");
        return 0;
 }
 
index 05dada9..b129401 100644 (file)
@@ -1437,7 +1437,7 @@ static struct net_device_ops brcmf_netdev_ops_pri = {
        .ndo_do_ioctl = brcmf_netdev_ioctl_entry,
        .ndo_start_xmit = brcmf_netdev_start_xmit,
        .ndo_set_mac_address = brcmf_netdev_set_mac_address,
-       .ndo_set_multicast_list = brcmf_netdev_set_multicast_list
+       .ndo_set_rx_mode = brcmf_netdev_set_multicast_list,
 };
 
 int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
index 9d638c3..b48aefd 100644 (file)
@@ -1,9 +1,10 @@
 config DVB_CXD2099
-        tristate "CXD2099AR Common Interface driver"
-        depends on DVB_CORE && PCI && I2C && DVB_NGENE
-        ---help---
-          Support for the CI module found on cineS2 DVB-S2, supported by
-         the Micronas PCIe device driver (ngene).
+       tristate "CXD2099AR Common Interface driver"
+       depends on DVB_CORE && PCI && I2C
+       ---help---
+         Support for the CI module found on cards based on
+         - Micronas ngene PCIe bridge: cineS2 etc.
+         - Digital Devices PCIe bridge: Octopus series
 
          For now, data is passed through '/dev/dvb/adapterX/sec0':
            - Encrypted data must be written to 'sec0'.
index 55b1c4a..1c04185 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * cxd2099.c: Driver for the CXD2099AR Common Interface Controller
  *
- * Copyright (C) 2010 DigitalDevices UG
+ * Copyright (C) 2010-2011 Digital Devices GmbH
  *
  *
  * This program is free software; you can redistribute it and/or
@@ -41,13 +41,13 @@ struct cxd {
        struct dvb_ca_en50221 en;
 
        struct i2c_adapter *i2c;
-       u8     adr;
+       struct cxd2099_cfg cfg;
+
        u8     regs[0x23];
        u8     lastaddress;
        u8     clk_reg_f;
        u8     clk_reg_b;
        int    mode;
-       u32    bitrate;
        int    ready;
        int    dr;
        int    slot_stat;
@@ -89,9 +89,9 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr,
                        u8 reg, u8 *val)
 {
        struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
-                                  .buf = &reg, .len = 1 },
+                                  .buf = &reg, .len = 1},
                                  {.addr = adr, .flags = I2C_M_RD,
-                                  .buf = val, .len = 1 } };
+                                  .buf = val, .len = 1} };
 
        if (i2c_transfer(adapter, msgs, 2) != 2) {
                printk(KERN_ERR "error in i2c_read_reg\n");
@@ -104,9 +104,9 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr,
                    u8 reg, u8 *data, u8 n)
 {
        struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
-                                  .buf = &reg, .len = 1 },
-                                 {.addr = adr, .flags = I2C_M_RD,
-                                  .buf = data, .len = n } };
+                                .buf = &reg, .len = 1},
+                               {.addr = adr, .flags = I2C_M_RD,
+                                .buf = data, .len = n} };
 
        if (i2c_transfer(adapter, msgs, 2) != 2) {
                printk(KERN_ERR "error in i2c_read\n");
@@ -119,10 +119,10 @@ static int read_block(struct cxd *ci, u8 adr, u8 *data, u8 n)
 {
        int status;
 
-       status = i2c_write_reg(ci->i2c, ci->adr, 0, adr);
+       status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
        if (!status) {
                ci->lastaddress = adr;
-               status = i2c_read(ci->i2c, ci->adr, 1, data, n);
+               status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, n);
        }
        return status;
 }
@@ -136,24 +136,24 @@ static int read_reg(struct cxd *ci, u8 reg, u8 *val)
 static int read_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
 {
        int status;
-       u8 addr[3] = { 2, address&0xff, address>>8 };
+       u8 addr[3] = {2, address & 0xff, address >> 8};
 
-       status = i2c_write(ci->i2c, ci->adr, addr, 3);
+       status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
        if (!status)
-               status = i2c_read(ci->i2c, ci->adr, 3, data, n);
+               status = i2c_read(ci->i2c, ci->cfg.adr, 3, data, n);
        return status;
 }
 
 static int write_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
 {
        int status;
-       u8 addr[3] = { 2, address&0xff, address>>8 };
+       u8 addr[3] = {2, address & 0xff, address >> 8};
 
-       status = i2c_write(ci->i2c, ci->adr, addr, 3);
+       status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
        if (!status) {
                u8 buf[256] = {3};
                memcpy(buf+1, data, n);
-               status = i2c_write(ci->i2c, ci->adr, buf, n+1);
+               status = i2c_write(ci->i2c, ci->cfg.adr, buf, n+1);
        }
        return status;
 }
@@ -161,39 +161,64 @@ static int write_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
 static int read_io(struct cxd *ci, u16 address, u8 *val)
 {
        int status;
-       u8 addr[3] = { 2, address&0xff, address>>8 };
+       u8 addr[3] = {2, address & 0xff, address >> 8};
 
-       status = i2c_write(ci->i2c, ci->adr, addr, 3);
+       status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
        if (!status)
-               status = i2c_read(ci->i2c, ci->adr, 3, val, 1);
+               status = i2c_read(ci->i2c, ci->cfg.adr, 3, val, 1);
        return status;
 }
 
 static int write_io(struct cxd *ci, u16 address, u8 val)
 {
        int status;
-       u8 addr[3] = { 2, address&0xff, address>>8 };
-       u8 buf[2] = { 3, val };
+       u8 addr[3] = {2, address & 0xff, address >> 8};
+       u8 buf[2] = {3, val};
 
-       status = i2c_write(ci->i2c, ci->adr, addr, 3);
+       status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
        if (!status)
-               status = i2c_write(ci->i2c, ci->adr, buf, 2);
-
+               status = i2c_write(ci->i2c, ci->cfg.adr, buf, 2);
        return status;
 }
 
+#if 0
+static int read_io_data(struct cxd *ci, u8 *data, u8 n)
+{
+       int status;
+       u8 addr[3] = { 2, 0, 0 };
+
+       status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
+       if (!status)
+               status = i2c_read(ci->i2c, ci->cfg.adr, 3, data, n);
+       return 0;
+}
+
+static int write_io_data(struct cxd *ci, u8 *data, u8 n)
+{
+       int status;
+       u8 addr[3] = {2, 0, 0};
+
+       status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
+       if (!status) {
+               u8 buf[256] = {3};
+               memcpy(buf+1, data, n);
+               status = i2c_write(ci->i2c, ci->cfg.adr, buf, n + 1);
+       }
+       return 0;
+}
+#endif
 
 static int write_regm(struct cxd *ci, u8 reg, u8 val, u8 mask)
 {
        int status;
 
-       status = i2c_write_reg(ci->i2c, ci->adr, 0, reg);
+       status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, reg);
        if (!status && reg >= 6 && reg <= 8 && mask != 0xff)
-               status = i2c_read_reg(ci->i2c, ci->adr, 1, &ci->regs[reg]);
-       ci->regs[reg] = (ci->regs[reg]&(~mask))|val;
+               status = i2c_read_reg(ci->i2c, ci->cfg.adr, 1, &ci->regs[reg]);
+       ci->regs[reg] = (ci->regs[reg] & (~mask)) | val;
        if (!status) {
                ci->lastaddress = reg;
-               status = i2c_write_reg(ci->i2c, ci->adr, 1, ci->regs[reg]);
+               status = i2c_write_reg(ci->i2c, ci->cfg.adr, 1, ci->regs[reg]);
        }
        if (reg == 0x20)
                ci->regs[reg] &= 0x7f;
@@ -211,11 +236,11 @@ static int write_block(struct cxd *ci, u8 adr, u8 *data, int n)
        int status;
        u8 buf[256] = {1};
 
-       status = i2c_write_reg(ci->i2c, ci->adr, 0, adr);
+       status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
        if (!status) {
                ci->lastaddress = adr;
-               memcpy(buf+1, data, n);
-               status = i2c_write(ci->i2c, ci->adr, buf, n+1);
+               memcpy(buf + 1, data, n);
+               status = i2c_write(ci->i2c, ci->cfg.adr, buf, n + 1);
        }
        return status;
 }
@@ -249,12 +274,16 @@ static void cam_mode(struct cxd *ci, int mode)
                write_regm(ci, 0x20, 0x80, 0x80);
                break;
        case 0x01:
+#ifdef BUFFER_MODE
+               if (!ci->en.read_data)
+                       return;
                printk(KERN_INFO "enable cam buffer mode\n");
                /* write_reg(ci, 0x0d, 0x00); */
                /* write_reg(ci, 0x0e, 0x01); */
                write_regm(ci, 0x08, 0x40, 0x40);
                /* read_reg(ci, 0x12, &dummy); */
                write_regm(ci, 0x08, 0x80, 0x80);
+#endif
                break;
        default:
                break;
@@ -264,8 +293,6 @@ static void cam_mode(struct cxd *ci, int mode)
 
 
 
-#define CHK_ERROR(s) if ((status = s)) break
-
 static int init(struct cxd *ci)
 {
        int status;
@@ -273,63 +300,160 @@ static int init(struct cxd *ci)
        mutex_lock(&ci->lock);
        ci->mode = -1;
        do {
-               CHK_ERROR(write_reg(ci, 0x00, 0x00));
-               CHK_ERROR(write_reg(ci, 0x01, 0x00));
-               CHK_ERROR(write_reg(ci, 0x02, 0x10));
-               CHK_ERROR(write_reg(ci, 0x03, 0x00));
-               CHK_ERROR(write_reg(ci, 0x05, 0xFF));
-               CHK_ERROR(write_reg(ci, 0x06, 0x1F));
-               CHK_ERROR(write_reg(ci, 0x07, 0x1F));
-               CHK_ERROR(write_reg(ci, 0x08, 0x28));
-               CHK_ERROR(write_reg(ci, 0x14, 0x20));
-
-               CHK_ERROR(write_reg(ci, 0x09, 0x4D)); /* Input Mode C, BYPass Serial, TIVAL = low, MSB */
-               CHK_ERROR(write_reg(ci, 0x0A, 0xA7)); /* TOSTRT = 8, Mode B (gated clock), falling Edge, Serial, POL=HIGH, MSB */
-
-               /* Sync detector */
-               CHK_ERROR(write_reg(ci, 0x0B, 0x33));
-               CHK_ERROR(write_reg(ci, 0x0C, 0x33));
-
-               CHK_ERROR(write_regm(ci, 0x14, 0x00, 0x0F));
-               CHK_ERROR(write_reg(ci, 0x15, ci->clk_reg_b));
-               CHK_ERROR(write_regm(ci, 0x16, 0x00, 0x0F));
-               CHK_ERROR(write_reg(ci, 0x17, ci->clk_reg_f));
-
-               CHK_ERROR(write_reg(ci, 0x20, 0x28)); /* Integer Divider, Falling Edge, Internal Sync, */
-               CHK_ERROR(write_reg(ci, 0x21, 0x00)); /* MCLKI = TICLK/8 */
-               CHK_ERROR(write_reg(ci, 0x22, 0x07)); /* MCLKI = TICLK/8 */
-
-
-               CHK_ERROR(write_regm(ci, 0x20, 0x80, 0x80)); /* Reset CAM state machine */
-
-               CHK_ERROR(write_regm(ci, 0x03, 0x02, 02));  /* Enable IREQA Interrupt */
-               CHK_ERROR(write_reg(ci, 0x01, 0x04));  /* Enable CD Interrupt */
-               CHK_ERROR(write_reg(ci, 0x00, 0x31));  /* Enable TS1,Hot Swap,Slot A */
-               CHK_ERROR(write_regm(ci, 0x09, 0x08, 0x08));  /* Put TS in bypass */
+               status = write_reg(ci, 0x00, 0x00);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x01, 0x00);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x02, 0x10);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x03, 0x00);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x05, 0xFF);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x06, 0x1F);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x07, 0x1F);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x08, 0x28);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x14, 0x20);
+               if (status < 0)
+                       break;
+
+#if 0
+               status = write_reg(ci, 0x09, 0x4D); /* Input Mode C, BYPass Serial, TIVAL = low, MSB */
+               if (status < 0)
+                       break;
+#endif
+               status = write_reg(ci, 0x0A, 0xA7); /* TOSTRT = 8, Mode B (gated clock), falling Edge, Serial, POL=HIGH, MSB */
+               if (status < 0)
+                       break;
+
+               status = write_reg(ci, 0x0B, 0x33);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x0C, 0x33);
+               if (status < 0)
+                       break;
+
+               status = write_regm(ci, 0x14, 0x00, 0x0F);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x15, ci->clk_reg_b);
+               if (status < 0)
+                       break;
+               status = write_regm(ci, 0x16, 0x00, 0x0F);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x17, ci->clk_reg_f);
+               if (status < 0)
+                       break;
+
+               if (ci->cfg.clock_mode) {
+                       if (ci->cfg.polarity) {
+                               status = write_reg(ci, 0x09, 0x6f);
+                               if (status < 0)
+                                       break;
+                       } else {
+                               status = write_reg(ci, 0x09, 0x6d);
+                               if (status < 0)
+                                       break;
+                       }
+                       status = write_reg(ci, 0x20, 0x68);
+                       if (status < 0)
+                               break;
+                       status = write_reg(ci, 0x21, 0x00);
+                       if (status < 0)
+                               break;
+                       status = write_reg(ci, 0x22, 0x02);
+                       if (status < 0)
+                               break;
+               } else {
+                       if (ci->cfg.polarity) {
+                               status = write_reg(ci, 0x09, 0x4f);
+                               if (status < 0)
+                                       break;
+                       } else {
+                               status = write_reg(ci, 0x09, 0x4d);
+                               if (status < 0)
+                                       break;
+                       }
+
+                       status = write_reg(ci, 0x20, 0x28);
+                       if (status < 0)
+                               break;
+                       status = write_reg(ci, 0x21, 0x00);
+                       if (status < 0)
+                               break;
+                       status = write_reg(ci, 0x22, 0x07);
+                       if (status < 0)
+                               break;
+               }
+
+               status = write_regm(ci, 0x20, 0x80, 0x80);
+               if (status < 0)
+                       break;
+               status = write_regm(ci, 0x03, 0x02, 0x02);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x01, 0x04);
+               if (status < 0)
+                       break;
+               status = write_reg(ci, 0x00, 0x31);
+               if (status < 0)
+                       break;
+
+               /* Put TS in bypass */
+               status = write_regm(ci, 0x09, 0x08, 0x08);
+               if (status < 0)
+                       break;
                ci->cammode = -1;
-#ifdef BUFFER_MODE
                cam_mode(ci, 0);
-#endif
        } while (0);
        mutex_unlock(&ci->lock);
 
        return 0;
 }
 
-
 static int read_attribute_mem(struct dvb_ca_en50221 *ca,
                              int slot, int address)
 {
        struct cxd *ci = ca->data;
+#if 0
+       if (ci->amem_read) {
+               if (address <= 0 || address > 1024)
+                       return -EIO;
+               return ci->amem[address];
+       }
+
+       mutex_lock(&ci->lock);
+       write_regm(ci, 0x06, 0x00, 0x05);
+       read_pccard(ci, 0, &ci->amem[0], 128);
+       read_pccard(ci, 128, &ci->amem[0], 128);
+       read_pccard(ci, 256, &ci->amem[0], 128);
+       read_pccard(ci, 384, &ci->amem[0], 128);
+       write_regm(ci, 0x06, 0x05, 0x05);
+       mutex_unlock(&ci->lock);
+       return ci->amem[address];
+#else
        u8 val;
        mutex_lock(&ci->lock);
        set_mode(ci, 1);
        read_pccard(ci, address, &val, 1);
        mutex_unlock(&ci->lock);
+       /* printk(KERN_INFO "%02x:%02x\n", address,val); */
        return val;
+#endif
 }
 
-
 static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
                               int address, u8 value)
 {
@@ -372,6 +496,15 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
        struct cxd *ci = ca->data;
 
        mutex_lock(&ci->lock);
+#if 0
+       write_reg(ci, 0x00, 0x21);
+       write_reg(ci, 0x06, 0x1F);
+       write_reg(ci, 0x00, 0x31);
+#else
+#if 0
+       write_reg(ci, 0x06, 0x1F);
+       write_reg(ci, 0x06, 0x2F);
+#else
        cam_mode(ci, 0);
        write_reg(ci, 0x00, 0x21);
        write_reg(ci, 0x06, 0x1F);
@@ -379,13 +512,25 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
        write_regm(ci, 0x20, 0x80, 0x80);
        write_reg(ci, 0x03, 0x02);
        ci->ready = 0;
+#endif
+#endif
        ci->mode = -1;
        {
                int i;
+#if 0
+               u8 val;
+#endif
                for (i = 0; i < 100; i++) {
                        msleep(10);
+#if 0
+                       read_reg(ci, 0x06, &val);
+                       printk(KERN_INFO "%d:%02x\n", i, val);
+                       if (!(val&0x10))
+                               break;
+#else
                        if (ci->ready)
                                break;
+#endif
                }
        }
        mutex_unlock(&ci->lock);
@@ -399,12 +544,12 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
 
        printk(KERN_INFO "slot_shutdown\n");
        mutex_lock(&ci->lock);
-       /* write_regm(ci, 0x09, 0x08, 0x08); */
-       write_regm(ci, 0x20, 0x80, 0x80);
-       write_regm(ci, 0x06, 0x07, 0x07);
+       write_regm(ci, 0x09, 0x08, 0x08);
+       write_regm(ci, 0x20, 0x80, 0x80); /* Reset CAM Mode */
+       write_regm(ci, 0x06, 0x07, 0x07); /* Clear IO Mode */
        ci->mode = -1;
        mutex_unlock(&ci->lock);
-       return 0; /* shutdown(ci); */
+       return 0;
 }
 
 static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
@@ -459,7 +604,6 @@ static int campoll(struct cxd *ci)
                if (istat&8 && ci->slot_stat == DVB_CA_EN50221_POLL_CAM_PRESENT) {
                        ci->ready = 1;
                        ci->slot_stat |= DVB_CA_EN50221_POLL_CAM_READY;
-                       printk(KERN_INFO "READY\n");
                }
        }
        return 0;
@@ -510,7 +654,7 @@ static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
        struct cxd *ci = ca->data;
 
        mutex_lock(&ci->lock);
-       printk(KERN_INFO "write_data %d\n", ecount);
+       printk(kern_INFO "write_data %d\n", ecount);
        write_reg(ci, 0x0d, ecount>>8);
        write_reg(ci, 0x0e, ecount&0xff);
        write_block(ci, 0x11, ebuf, ecount);
@@ -535,15 +679,15 @@ static struct dvb_ca_en50221 en_templ = {
 
 };
 
-struct dvb_ca_en50221 *cxd2099_attach(u8 adr, void *priv,
+struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
+                                     void *priv,
                                      struct i2c_adapter *i2c)
 {
        struct cxd *ci = 0;
-       u32 bitrate = 62000000;
        u8 val;
 
-       if (i2c_read_reg(i2c, adr, 0, &val) < 0) {
-               printk(KERN_ERR "No CXD2099 detected at %02x\n", adr);
+       if (i2c_read_reg(i2c, cfg->adr, 0, &val) < 0) {
+               printk(KERN_INFO "No CXD2099 detected at %02x\n", cfg->adr);
                return 0;
        }
 
@@ -553,21 +697,20 @@ struct dvb_ca_en50221 *cxd2099_attach(u8 adr, void *priv,
        memset(ci, 0, sizeof(*ci));
 
        mutex_init(&ci->lock);
+       memcpy(&ci->cfg, cfg, sizeof(struct cxd2099_cfg));
        ci->i2c = i2c;
-       ci->adr = adr;
        ci->lastaddress = 0xff;
        ci->clk_reg_b = 0x4a;
        ci->clk_reg_f = 0x1b;
-       ci->bitrate = bitrate;
 
        memcpy(&ci->en, &en_templ, sizeof(en_templ));
        ci->en.data = ci;
        init(ci);
-       printk(KERN_INFO "Attached CXD2099AR at %02x\n", ci->adr);
+       printk(KERN_INFO "Attached CXD2099AR at %02x\n", ci->cfg.adr);
        return &ci->en;
 }
 EXPORT_SYMBOL(cxd2099_attach);
 
 MODULE_DESCRIPTION("cxd2099");
-MODULE_AUTHOR("Ralph Metzler <rjkm@metzlerbros.de>");
+MODULE_AUTHOR("Ralph Metzler");
 MODULE_LICENSE("GPL");
index bed54ff..19c588a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * cxd2099.h: Driver for the CXD2099AR Common Interface Controller
  *
- * Copyright (C) 2010 DigitalDevices UG
+ * Copyright (C) 2010-2011 Digital Devices GmbH
  *
  *
  * This program is free software; you can redistribute it and/or
 
 #include <dvb_ca_en50221.h>
 
+struct cxd2099_cfg {
+       u32 bitrate;
+       u8  adr;
+       u8  polarity:1;
+       u8  clock_mode:1;
+};
+
 #if defined(CONFIG_DVB_CXD2099) || \
-        (defined(CONFIG_DVB_CXD2099_MODULE) && defined(MODULE))
-struct dvb_ca_en50221 *cxd2099_attach(u8 adr, void *priv, struct i2c_adapter *i2c);
+       (defined(CONFIG_DVB_CXD2099_MODULE) && defined(MODULE))
+struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
+                                     void *priv, struct i2c_adapter *i2c);
 #else
-static inline struct dvb_ca_en50221 *cxd2099_attach(u8 adr, void *priv, struct i2c_adapter *i2c)
+
+static inline struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
+                                       void *priv, struct i2c_adapter *i2c)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
index fe02d22..05aa41c 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/stringify.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
+#include <linux/slab.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
 #include <media/videobuf2-dma-contig.h>
index 5f25bba..4406630 100644 (file)
@@ -638,7 +638,7 @@ static const struct net_device_ops et131x_netdev_ops = {
        .ndo_open               = et131x_open,
        .ndo_stop               = et131x_close,
        .ndo_start_xmit         = et131x_tx,
-       .ndo_set_multicast_list = et131x_multicast,
+       .ndo_set_rx_mode        = et131x_multicast,
        .ndo_tx_timeout         = et131x_tx_timeout,
        .ndo_change_mtu         = et131x_change_mtu,
        .ndo_set_mac_address    = et131x_set_mac_addr,
index 627a98b..9e728b3 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/string.h>
 #include <linux/vmalloc.h>
 #include <linux/netdevice.h>
+#include <asm/io.h>
 #include <asm/uaccess.h>
 #include "ft1000.h"
 
index 779ac1a..daac121 100644 (file)
 #include <drm/drmP.h>
 #include <drm/drm.h>
 
-/**
- * Initialize an already allocated GEM object of the specified size with
- * no GEM provided backing store. Instead the caller is responsible for
- * backing the object and handling it.
- */
-int drm_gem_private_object_init(struct drm_device *dev,
-                       struct drm_gem_object *obj, size_t size)
-{
-       BUG_ON((size & (PAGE_SIZE - 1)) != 0);
-
-       obj->dev = dev;
-       obj->filp = NULL;
-
-       kref_init(&obj->refcount);
-       atomic_set(&obj->handle_count, 0);
-       obj->size = size;
-
-       return 0;
-}
-
 void drm_gem_object_release_wrap(struct drm_gem_object *obj)
 {
        /* Remove the list map if one is present */
@@ -51,8 +31,7 @@ void drm_gem_object_release_wrap(struct drm_gem_object *obj)
                kfree(list->map);
                list->map = NULL;
        }
-       if (obj->filp)
-               drm_gem_object_release(obj);
+       drm_gem_object_release(obj);
 }
 
 /**
index a0f2bc4..ce5ce30 100644 (file)
@@ -1,4 +1,2 @@
 extern void drm_gem_object_release_wrap(struct drm_gem_object *obj);
-extern int drm_gem_private_object_init(struct drm_device *dev,
-                       struct drm_gem_object *obj, size_t size);
 extern int gem_create_mmap_offset(struct drm_gem_object *obj);
index 3612574..d286b22 100644 (file)
@@ -325,7 +325,7 @@ static int blkvsc_do_operation(struct block_device_context *blkdev,
 
        page_buf = alloc_page(GFP_KERNEL);
        if (!page_buf) {
-               kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
+               kmem_cache_free(blkdev->request_pool, blkvsc_req);
                return -ENOMEM;
        }
 
@@ -422,7 +422,7 @@ cleanup:
 
        __free_page(page_buf);
 
-       kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
+       kmem_cache_free(blkdev->request_pool, blkvsc_req);
 
        return ret;
 }
index 61989f0..bfd4c81 100644 (file)
@@ -307,7 +307,7 @@ static const struct net_device_ops device_ops = {
        .ndo_open =                     netvsc_open,
        .ndo_stop =                     netvsc_close,
        .ndo_start_xmit =               netvsc_start_xmit,
-       .ndo_set_multicast_list =       netvsc_set_multicast_list,
+       .ndo_set_rx_mode =              netvsc_set_multicast_list,
        .ndo_change_mtu =               eth_change_mtu,
        .ndo_validate_addr =            eth_validate_addr,
        .ndo_set_mac_address =          eth_mac_addr,
index bf19888..cf5d15d 100644 (file)
@@ -311,13 +311,17 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
                mutex_lock(&indio_dev->mlock);
                addr = adis16203_addresses[chan->address][0];
                ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16);
-               if (ret)
+               if (ret) {
+                       mutex_unlock(&indio_dev->mlock);
                        return ret;
+               }
 
                if (val16 & ADIS16203_ERROR_ACTIVE) {
                        ret = adis16203_check_status(indio_dev);
-                       if (ret)
+                       if (ret) {
+                               mutex_unlock(&indio_dev->mlock);
                                return ret;
+                       }
                }
                val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
                if (chan->scan_type.sign == 's')
index cfd09b3..3e2b626 100644 (file)
@@ -341,13 +341,17 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
                mutex_lock(&indio_dev->mlock);
                addr = adis16204_addresses[chan->address][0];
                ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
-               if (ret)
+               if (ret) {
+                       mutex_unlock(&indio_dev->mlock);
                        return ret;
+               }
 
                if (val16 & ADIS16204_ERROR_ACTIVE) {
                        ret = adis16204_check_status(indio_dev);
-                       if (ret)
+                       if (ret) {
+                               mutex_unlock(&indio_dev->mlock);
                                return ret;
+                       }
                }
                val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
                if (chan->scan_type.sign == 's')
index 55f3a7b..bec1fa8 100644 (file)
@@ -337,13 +337,17 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
                mutex_lock(&indio_dev->mlock);
                addr = adis16209_addresses[chan->address][0];
                ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16);
-               if (ret)
+               if (ret) {
+                       mutex_unlock(&indio_dev->mlock);
                        return ret;
+               }
 
                if (val16 & ADIS16209_ERROR_ACTIVE) {
                        ret = adis16209_check_status(indio_dev);
-                       if (ret)
+                       if (ret) {
+                               mutex_unlock(&indio_dev->mlock);
                                return ret;
+                       }
                }
                val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
                if (chan->scan_type.sign == 's')
index 4a4eafc..aee8b69 100644 (file)
@@ -370,13 +370,17 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
                mutex_lock(&indio_dev->mlock);
                addr = adis16240_addresses[chan->address][0];
                ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
-               if (ret)
+               if (ret) {
+                       mutex_unlock(&indio_dev->mlock);
                        return ret;
+               }
 
                if (val16 & ADIS16240_ERROR_ACTIVE) {
                        ret = adis16240_check_status(indio_dev);
-                       if (ret)
+                       if (ret) {
+                               mutex_unlock(&indio_dev->mlock);
                                return ret;
+                       }
                }
                val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
                if (chan->scan_type.sign == 's')
index 05797f4..f2d43cf 100644 (file)
@@ -446,13 +446,17 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
                mutex_lock(&indio_dev->mlock);
                addr = adis16260_addresses[chan->address][0];
                ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
-               if (ret)
+               if (ret) {
+                       mutex_unlock(&indio_dev->mlock);
                        return ret;
+               }
 
                if (val16 & ADIS16260_ERROR_ACTIVE) {
                        ret = adis16260_check_status(indio_dev);
-                       if (ret)
+                       if (ret) {
+                               mutex_unlock(&indio_dev->mlock);
                                return ret;
+                       }
                }
                val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
                if (chan->scan_type.sign == 's')
index 77b47f7..649d6b7 100644 (file)
@@ -4,5 +4,7 @@ ToDo list (incomplete, unordered)
        - add compile as module support
        - move nvec devices to mfd cells?
        - adjust to kernel style
-
-
+       - fix clk usage
+         should not be using clk_get_sys(), but clk_get(&pdev->dev, conn)
+         where conn is either NULL if the device only has one clock, or
+         the device specific name if it has multiple clocks.
index a8f780e..076f866 100644 (file)
@@ -512,7 +512,7 @@ static const struct net_device_ops cvm_oct_npi_netdev_ops = {
        .ndo_init               = cvm_oct_common_init,
        .ndo_uninit             = cvm_oct_common_uninit,
        .ndo_start_xmit         = cvm_oct_xmit,
-       .ndo_set_multicast_list = cvm_oct_common_set_multicast_list,
+       .ndo_set_rx_mode        = cvm_oct_common_set_multicast_list,
        .ndo_set_mac_address    = cvm_oct_common_set_mac_address,
        .ndo_do_ioctl           = cvm_oct_ioctl,
        .ndo_change_mtu         = cvm_oct_common_change_mtu,
@@ -527,7 +527,7 @@ static const struct net_device_ops cvm_oct_xaui_netdev_ops = {
        .ndo_open               = cvm_oct_xaui_open,
        .ndo_stop               = cvm_oct_xaui_stop,
        .ndo_start_xmit         = cvm_oct_xmit,
-       .ndo_set_multicast_list = cvm_oct_common_set_multicast_list,
+       .ndo_set_rx_mode        = cvm_oct_common_set_multicast_list,
        .ndo_set_mac_address    = cvm_oct_common_set_mac_address,
        .ndo_do_ioctl           = cvm_oct_ioctl,
        .ndo_change_mtu         = cvm_oct_common_change_mtu,
@@ -542,7 +542,7 @@ static const struct net_device_ops cvm_oct_sgmii_netdev_ops = {
        .ndo_open               = cvm_oct_sgmii_open,
        .ndo_stop               = cvm_oct_sgmii_stop,
        .ndo_start_xmit         = cvm_oct_xmit,
-       .ndo_set_multicast_list = cvm_oct_common_set_multicast_list,
+       .ndo_set_rx_mode        = cvm_oct_common_set_multicast_list,
        .ndo_set_mac_address    = cvm_oct_common_set_mac_address,
        .ndo_do_ioctl           = cvm_oct_ioctl,
        .ndo_change_mtu         = cvm_oct_common_change_mtu,
@@ -555,7 +555,7 @@ static const struct net_device_ops cvm_oct_spi_netdev_ops = {
        .ndo_init               = cvm_oct_spi_init,
        .ndo_uninit             = cvm_oct_spi_uninit,
        .ndo_start_xmit         = cvm_oct_xmit,
-       .ndo_set_multicast_list = cvm_oct_common_set_multicast_list,
+       .ndo_set_rx_mode        = cvm_oct_common_set_multicast_list,
        .ndo_set_mac_address    = cvm_oct_common_set_mac_address,
        .ndo_do_ioctl           = cvm_oct_ioctl,
        .ndo_change_mtu         = cvm_oct_common_change_mtu,
@@ -570,7 +570,7 @@ static const struct net_device_ops cvm_oct_rgmii_netdev_ops = {
        .ndo_open               = cvm_oct_rgmii_open,
        .ndo_stop               = cvm_oct_rgmii_stop,
        .ndo_start_xmit         = cvm_oct_xmit,
-       .ndo_set_multicast_list = cvm_oct_common_set_multicast_list,
+       .ndo_set_rx_mode        = cvm_oct_common_set_multicast_list,
        .ndo_set_mac_address    = cvm_oct_common_set_mac_address,
        .ndo_do_ioctl           = cvm_oct_ioctl,
        .ndo_change_mtu         = cvm_oct_common_change_mtu,
@@ -582,7 +582,7 @@ static const struct net_device_ops cvm_oct_rgmii_netdev_ops = {
 static const struct net_device_ops cvm_oct_pow_netdev_ops = {
        .ndo_init               = cvm_oct_common_init,
        .ndo_start_xmit         = cvm_oct_xmit_pow,
-       .ndo_set_multicast_list = cvm_oct_common_set_multicast_list,
+       .ndo_set_rx_mode        = cvm_oct_common_set_multicast_list,
        .ndo_set_mac_address    = cvm_oct_common_set_mac_address,
        .ndo_do_ioctl           = cvm_oct_ioctl,
        .ndo_change_mtu         = cvm_oct_common_change_mtu,
index 4c6651a..04c2391 100644 (file)
@@ -3534,7 +3534,7 @@ static const struct net_device_ops rtl8180_netdev_ops = {
        .ndo_get_stats          = rtl8180_stats,
        .ndo_tx_timeout         = rtl8180_restart,
        .ndo_do_ioctl           = rtl8180_ioctl,
-       .ndo_set_multicast_list = r8180_set_multicast,
+       .ndo_set_rx_mode        = r8180_set_multicast,
        .ndo_set_mac_address    = r8180_set_mac_adr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
index 94d9c8d..b418fed 100644 (file)
@@ -4519,7 +4519,7 @@ static const struct net_device_ops rtl8192_netdev_ops = {
        .ndo_stop =                     rtl8192_close,
        .ndo_tx_timeout =               tx_timeout,
        .ndo_do_ioctl =                 rtl8192_ioctl,
-       .ndo_set_multicast_list =       r8192_set_multicast,
+       .ndo_set_rx_mode =              r8192_set_multicast,
        .ndo_set_mac_address =          r8192_set_mac_adr,
        .ndo_start_xmit =               ieee80211_rtl_xmit,
 };
index ee86fe8..c09be0a 100644 (file)
@@ -5739,7 +5739,7 @@ static const struct net_device_ops rtl8192_netdev_ops = {
        .ndo_get_stats          = rtl8192_stats,
        .ndo_tx_timeout         = tx_timeout,
        .ndo_do_ioctl           = rtl8192_ioctl,
-       .ndo_set_multicast_list = r8192_set_multicast,
+       .ndo_set_rx_mode        = r8192_set_multicast,
        .ndo_set_mac_address    = r8192_set_mac_adr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
index 6766f46..4bb5fff 100644 (file)
@@ -399,10 +399,7 @@ download_firmware_fail:
 
 }
 
-
-
-
-
-
-
+MODULE_FIRMWARE("RTL8192U/boot.img");
+MODULE_FIRMWARE("RTL8192U/main.img");
+MODULE_FIRMWARE("RTL8192U/data.img");
 
index 5ff59f2..16c73fb 100644 (file)
@@ -66,12 +66,6 @@ static int msi_en;
 module_param(msi_en, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(msi_en, "enable msi");
 
-/* These are used to make sure the module doesn't unload before all the
- * threads have exited.
- */
-static atomic_t total_threads = ATOMIC_INIT(0);
-static DECLARE_COMPLETION(threads_gone);
-
 static irqreturn_t rtsx_interrupt(int irq, void *dev_id);
 
 /***********************************************************************
@@ -192,7 +186,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
        /* enqueue the command and wake up the control thread */
        srb->scsi_done = done;
        chip->srb = srb;
-       up(&(dev->sema));
+       complete(&dev->cmnd_ready);
 
        return 0;
 }
@@ -475,7 +469,7 @@ static int rtsx_control_thread(void *__dev)
        current->flags |= PF_NOFREEZE;
 
        for (;;) {
-               if (down_interruptible(&dev->sema))
+               if (wait_for_completion_interruptible(&dev->cmnd_ready))
                        break;
 
                /* lock the device pointers */
@@ -557,8 +551,6 @@ SkipForAbort:
                mutex_unlock(&dev->dev_mutex);
        } /* for (;;) */
 
-       scsi_host_put(host);
-
        /* notify the exit routine that we're actually exiting now
         *
         * complete()/wait_for_completion() is similar to up()/down(),
@@ -573,7 +565,7 @@ SkipForAbort:
         * This is important in preemption kernels, which transfer the flow
         * of execution immediately upon a complete().
         */
-       complete_and_exit(&threads_gone, 0);
+       complete_and_exit(&dev->control_exit, 0);
 }
 
 
@@ -581,7 +573,6 @@ static int rtsx_polling_thread(void *__dev)
 {
        struct rtsx_dev *dev = (struct rtsx_dev *)__dev;
        struct rtsx_chip *chip = dev->chip;
-       struct Scsi_Host *host = rtsx_to_host(dev);
        struct sd_info *sd_card = &(chip->sd_card);
        struct xd_info *xd_card = &(chip->xd_card);
        struct ms_info *ms_card = &(chip->ms_card);
@@ -621,8 +612,7 @@ static int rtsx_polling_thread(void *__dev)
                mutex_unlock(&dev->dev_mutex);
        }
 
-       scsi_host_put(host);
-       complete_and_exit(&threads_gone, 0);
+       complete_and_exit(&dev->polling_exit, 0);
 }
 
 /*
@@ -699,29 +689,38 @@ static void rtsx_release_resources(struct rtsx_dev *dev)
 {
        printk(KERN_INFO "-- %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.
+        */
+       printk(KERN_INFO "-- sending exit command to thread\n");
+       complete(&dev->cmnd_ready);
+       if (dev->ctl_thread)
+               wait_for_completion(&dev->control_exit);
+       if (dev->polling_thread)
+               wait_for_completion(&dev->polling_exit);
+
+       wait_timeout(200);
+
        if (dev->rtsx_resv_buf) {
-               dma_free_coherent(&(dev->pci->dev), HOST_CMDS_BUF_LEN,
+               dma_free_coherent(&(dev->pci->dev), RTSX_RESV_BUF_LEN,
                                dev->rtsx_resv_buf, dev->rtsx_resv_buf_addr);
                dev->chip->host_cmds_ptr = NULL;
                dev->chip->host_sg_tbl_ptr = NULL;
        }
 
-       pci_disable_device(dev->pci);
-       pci_release_regions(dev->pci);
-
-       if (dev->irq > 0) {
+       if (dev->irq > 0)
                free_irq(dev->irq, (void *)dev);
-       }
-       if (dev->chip->msi_en) {
+       if (dev->chip->msi_en)
                pci_disable_msi(dev->pci);
-       }
+       if (dev->remap_addr)
+               iounmap(dev->remap_addr);
 
-       /* Tell the control thread to exit.  The SCSI host must
-        * already have been removed so it won't try to queue
-        * any more commands.
-        */
-       printk(KERN_INFO "-- sending exit command to thread\n");
-       up(&dev->sema);
+       pci_disable_device(dev->pci);
+       pci_release_regions(dev->pci);
+
+       rtsx_release_chip(dev->chip);
+       kfree(dev->chip);
 }
 
 /* First stage of disconnect processing: stop all commands and remove
@@ -739,6 +738,7 @@ static void quiesce_and_remove_host(struct rtsx_dev *dev)
        scsi_unlock(host);
        mutex_unlock(&dev->dev_mutex);
        wake_up(&dev->delay_wait);
+       wait_for_completion(&dev->scanning_done);
 
        /* Wait some time to let other threads exist */
        wait_timeout(100);
@@ -793,8 +793,7 @@ static int rtsx_scan_thread(void *__dev)
                /* Should we unbind if no devices were detected? */
        }
 
-       scsi_host_put(rtsx_to_host(dev));
-       complete_and_exit(&threads_gone, 0);
+       complete_and_exit(&dev->scanning_done, 0);
 }
 
 static void rtsx_init_options(struct rtsx_chip *chip)
@@ -941,8 +940,11 @@ static int __devinit rtsx_probe(struct pci_dev *pci, const struct pci_device_id
 
        spin_lock_init(&dev->reg_lock);
        mutex_init(&(dev->dev_mutex));
-       sema_init(&(dev->sema), 0);
+       init_completion(&dev->cmnd_ready);
+       init_completion(&dev->control_exit);
+       init_completion(&dev->polling_exit);
        init_completion(&(dev->notify));
+       init_completion(&dev->scanning_done);
        init_waitqueue_head(&dev->delay_wait);
 
        dev->pci = pci;
@@ -992,28 +994,22 @@ static int __devinit rtsx_probe(struct pci_dev *pci, const struct pci_device_id
        pci_set_master(pci);
        synchronize_irq(dev->irq);
 
-       err = scsi_add_host(host, &pci->dev);
-       if (err) {
-               printk(KERN_ERR "Unable to add the scsi host\n");
-               goto errout;
-       }
-
        rtsx_init_chip(dev->chip);
 
        /* Start up our control thread */
-       th = kthread_create(rtsx_control_thread, dev, CR_DRIVER_NAME);
+       th = kthread_run(rtsx_control_thread, dev, CR_DRIVER_NAME);
        if (IS_ERR(th)) {
                printk(KERN_ERR "Unable to start control thread\n");
                err = PTR_ERR(th);
                goto errout;
        }
+       dev->ctl_thread = th;
 
-       /* Take a reference to the host for the control thread and
-        * count it among all the threads we have launched.  Then
-        * start it up. */
-       scsi_host_get(rtsx_to_host(dev));
-       atomic_inc(&total_threads);
-       wake_up_process(th);
+       err = scsi_add_host(host, &pci->dev);
+       if (err) {
+               printk(KERN_ERR "Unable to add the scsi host\n");
+               goto errout;
+       }
 
        /* Start up the thread for delayed SCSI-device scanning */
        th = kthread_create(rtsx_scan_thread, dev, "rtsx-scan");
@@ -1024,28 +1020,17 @@ static int __devinit rtsx_probe(struct pci_dev *pci, const struct pci_device_id
                goto errout;
        }
 
-       /* Take a reference to the host for the scanning thread and
-        * count it among all the threads we have launched.  Then
-        * start it up. */
-       scsi_host_get(rtsx_to_host(dev));
-       atomic_inc(&total_threads);
        wake_up_process(th);
 
        /* Start up the thread for polling thread */
-       th = kthread_create(rtsx_polling_thread, dev, "rtsx-polling");
+       th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling");
        if (IS_ERR(th)) {
                printk(KERN_ERR "Unable to start the device-polling thread\n");
                quiesce_and_remove_host(dev);
                err = PTR_ERR(th);
                goto errout;
        }
-
-       /* Take a reference to the host for the polling thread and
-        * count it among all the threads we have launched.  Then
-        * start it up. */
-       scsi_host_get(rtsx_to_host(dev));
-       atomic_inc(&total_threads);
-       wake_up_process(th);
+       dev->polling_thread = th;
 
        pci_set_drvdata(pci, dev);
 
@@ -1108,16 +1093,6 @@ static void __exit rtsx_exit(void)
 
        pci_unregister_driver(&driver);
 
-       /* Don't return until all of our control and scanning threads
-        * have exited.  Since each thread signals threads_gone as its
-        * last act, we have to call wait_for_completion the right number
-        * of times.
-        */
-       while (atomic_read(&total_threads) > 0) {
-               wait_for_completion(&threads_gone);
-               atomic_dec(&total_threads);
-       }
-
        printk(KERN_INFO "%s module exit\n", CR_DRIVER_NAME);
 }
 
index 247615b..86e47c2 100644 (file)
@@ -112,9 +112,16 @@ struct rtsx_dev {
        /* locks */
        spinlock_t              reg_lock;
 
+       struct task_struct      *ctl_thread;     /* the control thread   */
+       struct task_struct      *polling_thread; /* the polling thread   */
+
        /* mutual exclusion and synchronization structures */
-       struct semaphore        sema;            /* to sleep thread on      */
+       struct completion       cmnd_ready;      /* to sleep thread on      */
+       struct completion       control_exit;    /* control thread exit     */
+       struct completion       polling_exit;    /* polling thread exit     */
        struct completion       notify;          /* thread begin/end        */
+       struct completion       scanning_done;   /* wait for scan thread    */
+
        wait_queue_head_t       delay_wait;      /* wait during scan, reset */
        struct mutex            dev_mutex;
 
index 18f1103..77a0751 100644 (file)
@@ -3724,7 +3724,7 @@ static const struct net_device_ops slic_netdev_ops = {
        .ndo_do_ioctl           = slic_ioctl,
        .ndo_set_mac_address    = slic_mac_set_address,
        .ndo_get_stats          = slic_get_stats,
-       .ndo_set_multicast_list = slic_mcast_set_list,
+       .ndo_set_rx_mode        = slic_mcast_set_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
 };
index 7677994..f974f64 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/slab.h>
 #include <linux/videodev2.h>
 #include "solo6x10.h"
 #include "tw28.h"
index 285f7f3..de50259 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include "solo6x10.h"
 #include "osd-font.h"
 
index bd8eb92..59274bf 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/mempool.h>
 #include <linux/poll.h>
 #include <linux/kthread.h>
+#include <linux/slab.h>
 #include <linux/freezer.h>
 #include <sound/core.h>
 #include <sound/initval.h>
index 5717eab..56210f0 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/scatterlist.h>
 #include "solo6x10.h"
 
index 17c06bd..abee721 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/list.h>
 #include <linux/wait.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
 #include <linux/videodev2.h>
index 39dc586..940769e 100644 (file)
@@ -18,13 +18,14 @@ static ssize_t speakup_file_write(struct file *fp, const char *buffer,
 {
        size_t count = nbytes;
        const char *ptr = buffer;
-       int bytes;
+       size_t bytes;
        unsigned long flags;
        u_char buf[256];
+
        if (synth == NULL)
                return -ENODEV;
        while (count > 0) {
-               bytes = min_t(size_t, count, sizeof(buf));
+               bytes = min(count, sizeof(buf));
                if (copy_from_user(buf, ptr, bytes))
                        return -EFAULT;
                count -= bytes;
index ddfd7c3..bd5fa89 100644 (file)
@@ -84,7 +84,6 @@ static int _tm6000_start_audio_dma(struct snd_tm6000_card *chip)
 
        tm6000_set_audio_bitrate(core, 48000);
 
-
        return 0;
 }
 
@@ -123,6 +122,7 @@ static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size)
        if (substream->runtime->dma_area) {
                if (substream->runtime->dma_bytes > size)
                        return 0;
+
                dsp_buffer_free(substream);
        }
 
@@ -152,9 +152,9 @@ static struct snd_pcm_hardware snd_tm6000_digital_hw = {
                SNDRV_PCM_INFO_MMAP_VALID,
        .formats = SNDRV_PCM_FMTBIT_S16_LE,
 
-       .rates =                SNDRV_PCM_RATE_CONTINUOUS,
-       .rate_min =             48000,
-       .rate_max =             48000,
+       .rates = SNDRV_PCM_RATE_CONTINUOUS,
+       .rate_min = 48000,
+       .rate_max = 48000,
        .channels_min = 2,
        .channels_max = 2,
        .period_bytes_min = 64,
@@ -254,9 +254,7 @@ static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size)
                memcpy(runtime->dma_area + buf_pos * stride, buf,
                        length * stride);
 
-#ifndef NO_PCM_LOCK
        snd_pcm_stream_lock(substream);
-#endif
 
        chip->buf_pos += length;
        if (chip->buf_pos >= runtime->buffer_size)
@@ -268,9 +266,7 @@ static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size)
                period_elapsed = 1;
        }
 
-#ifndef NO_PCM_LOCK
        snd_pcm_stream_unlock(substream);
-#endif
 
        if (period_elapsed)
                snd_pcm_period_elapsed(substream);
index 3d2a9ba..8cb9116 100644 (file)
@@ -911,7 +911,7 @@ static const struct net_device_ops device_netdev_ops = {
     .ndo_do_ioctl           = device_ioctl,
     .ndo_get_stats          = device_get_stats,
     .ndo_start_xmit         = device_xmit,
-    .ndo_set_multicast_list = device_set_multi,
+    .ndo_set_rx_mode       = device_set_multi,
 };
 
 
index e18efd4..1ff3940 100644 (file)
@@ -753,7 +753,7 @@ static const struct net_device_ops device_netdev_ops = {
     .ndo_do_ioctl           = device_ioctl,
     .ndo_get_stats          = device_get_stats,
     .ndo_start_xmit         = device_xmit,
-    .ndo_set_multicast_list = device_set_multi,
+    .ndo_set_rx_mode       = device_set_multi,
 };
 
 static int __devinit
index cf917e6..b21515f 100644 (file)
@@ -1179,7 +1179,7 @@ static const struct net_device_ops wl_netdev_ops =
 
     .ndo_set_config         = &wl_config,
     .ndo_get_stats          = &wl_stats,
-    .ndo_set_multicast_list = &wl_multicast,
+    .ndo_set_rx_mode        = &wl_multicast,
 
     .ndo_init               = &wl_insert,
     .ndo_open               = &wl_adapter_open,
index b0af292..14bfeb2 100644 (file)
@@ -715,7 +715,7 @@ static const struct net_device_ops p80211_netdev_ops = {
        .ndo_stop = p80211knetdev_stop,
        .ndo_get_stats = p80211knetdev_get_stats,
        .ndo_start_xmit = p80211knetdev_hard_start_xmit,
-       .ndo_set_multicast_list = p80211knetdev_set_multicast_list,
+       .ndo_set_rx_mode = p80211knetdev_set_multicast_list,
        .ndo_do_ioctl = p80211knetdev_do_ioctl,
        .ndo_set_mac_address = p80211knetdev_set_mac_address,
        .ndo_tx_timeout = p80211knetdev_tx_timeout,
index f5ec64f..60daa27 100644 (file)
@@ -1,3 +1,3 @@
-zcache-y       :=      tmem.o
+zcache-y       :=      zcache-main.o tmem.o
 
 obj-$(CONFIG_ZCACHE)   +=      zcache.o
similarity index 99%
rename from drivers/staging/zcache/zcache.c
rename to drivers/staging/zcache/zcache-main.c
index 65a81a0..855a5bb 100644 (file)
@@ -19,6 +19,7 @@
  *   http://marc.info/?l=linux-mm&m=127811271605009
  */
 
+#include <linux/module.h>
 #include <linux/cpu.h>
 #include <linux/highmem.h>
 #include <linux/list.h>
@@ -27,6 +28,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/atomic.h>
+#include <linux/math64.h>
 #include "tmem.h"
 
 #include "../zram/xvmalloc.h" /* if built in drivers/staging */
@@ -53,6 +55,9 @@
 
 #define MAX_CLIENTS 16
 #define LOCAL_CLIENT ((uint16_t)-1)
+
+MODULE_LICENSE("GPL");
+
 struct zcache_client {
        struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT];
        struct xv_pool *xvpool;
@@ -1158,6 +1163,7 @@ static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph,
        uint16_t client_id = get_client_id_from_client(cli);
        unsigned long zv_mean_zsize;
        unsigned long curr_pers_pampd_count;
+       u64 total_zsize;
 
        if (eph) {
                ret = zcache_compress(page, &cdata, &clen);
@@ -1190,8 +1196,9 @@ static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph,
                }
                /* reject if mean compression is too poor */
                if ((clen > zv_max_mean_zsize) && (curr_pers_pampd_count > 0)) {
-                       zv_mean_zsize = xv_get_total_size_bytes(cli->xvpool) /
-                                               curr_pers_pampd_count;
+                       total_zsize = xv_get_total_size_bytes(cli->xvpool);
+                       zv_mean_zsize = div_u64(total_zsize,
+                                               curr_pers_pampd_count);
                        if (zv_mean_zsize > zv_max_mean_zsize) {
                                zcache_mean_compress_poor++;
                                goto out;
@@ -1929,9 +1936,9 @@ __setup("nofrontswap", no_frontswap);
 
 static int __init zcache_init(void)
 {
-#ifdef CONFIG_SYSFS
        int ret = 0;
 
+#ifdef CONFIG_SYSFS
        ret = sysfs_create_group(mm_kobj, &zcache_attr_group);
        if (ret) {
                pr_err("zcache: can't create sysfs\n");
index 564ff4e..8345fb4 100644 (file)
@@ -1,5 +1,6 @@
 config ISCSI_TARGET
        tristate "Linux-iSCSI.org iSCSI Target Mode Stack"
+       depends on NET
        select CRYPTO
        select CRYPTO_CRC32C
        select CRYPTO_CRC32C_INTEL if X86
index 14c81c4..c24fb10 100644 (file)
@@ -120,7 +120,7 @@ struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *buf)
        struct iscsi_tiqn *tiqn = NULL;
        int ret;
 
-       if (strlen(buf) > ISCSI_IQN_LEN) {
+       if (strlen(buf) >= ISCSI_IQN_LEN) {
                pr_err("Target IQN exceeds %d bytes\n",
                                ISCSI_IQN_LEN);
                return ERR_PTR(-EINVAL);
@@ -1857,7 +1857,7 @@ static int iscsit_handle_text_cmd(
        char *text_ptr, *text_in;
        int cmdsn_ret, niov = 0, rx_got, rx_size;
        u32 checksum = 0, data_crc = 0, payload_length;
-       u32 padding = 0, text_length = 0;
+       u32 padding = 0, pad_bytes = 0, text_length = 0;
        struct iscsi_cmd *cmd;
        struct kvec iov[3];
        struct iscsi_text *hdr;
@@ -1896,7 +1896,7 @@ static int iscsit_handle_text_cmd(
 
                padding = ((-payload_length) & 3);
                if (padding != 0) {
-                       iov[niov].iov_base = cmd->pad_bytes;
+                       iov[niov].iov_base = &pad_bytes;
                        iov[niov++].iov_len  = padding;
                        rx_size += padding;
                        pr_debug("Receiving %u additional bytes"
@@ -1917,7 +1917,7 @@ static int iscsit_handle_text_cmd(
                if (conn->conn_ops->DataDigest) {
                        iscsit_do_crypto_hash_buf(&conn->conn_rx_hash,
                                        text_in, text_length,
-                                       padding, cmd->pad_bytes,
+                                       padding, (u8 *)&pad_bytes,
                                        (u8 *)&data_crc);
 
                        if (checksum != data_crc) {
@@ -3468,7 +3468,12 @@ static inline void iscsit_thread_check_cpumask(
 }
 
 #else
-#define iscsit_thread_get_cpumask(X) ({})
+
+void iscsit_thread_get_cpumask(struct iscsi_conn *conn)
+{
+       return;
+}
+
 #define iscsit_thread_check_cpumask(X, Y, Z) ({})
 #endif /* CONFIG_SMP */
 
index 32bb92c..f095e65 100644 (file)
@@ -181,7 +181,7 @@ struct se_tpg_np *lio_target_call_addnptotpg(
                return ERR_PTR(-EOVERFLOW);
        }
        memset(buf, 0, MAX_PORTAL_LEN + 1);
-       snprintf(buf, MAX_PORTAL_LEN, "%s", name);
+       snprintf(buf, MAX_PORTAL_LEN + 1, "%s", name);
 
        memset(&sockaddr, 0, sizeof(struct __kernel_sockaddr_storage));
 
index 713a4d2..4d087ac 100644 (file)
@@ -978,7 +978,7 @@ struct iscsi_login *iscsi_target_init_negotiation(
                pr_err("Unable to allocate memory for struct iscsi_login.\n");
                iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
                                ISCSI_LOGIN_STATUS_NO_RESOURCES);
-               goto out;
+               return NULL;
        }
 
        login->req = kzalloc(ISCSI_HDR_LEN, GFP_KERNEL);
index c75a01a..8976032 100644 (file)
@@ -1747,6 +1747,8 @@ int transport_generic_handle_cdb(
 }
 EXPORT_SYMBOL(transport_generic_handle_cdb);
 
+static void transport_generic_request_failure(struct se_cmd *,
+                       struct se_device *, int, int);
 /*
  * Used by fabric module frontends to queue tasks directly.
  * Many only be used from process context only
@@ -1754,6 +1756,8 @@ EXPORT_SYMBOL(transport_generic_handle_cdb);
 int transport_handle_cdb_direct(
        struct se_cmd *cmd)
 {
+       int ret;
+
        if (!cmd->se_lun) {
                dump_stack();
                pr_err("cmd->se_lun is NULL\n");
@@ -1765,8 +1769,31 @@ int transport_handle_cdb_direct(
                                " from interrupt context\n");
                return -EINVAL;
        }
-
-       return transport_generic_new_cmd(cmd);
+       /*
+        * Set TRANSPORT_NEW_CMD state and cmd->t_transport_active=1 following
+        * transport_generic_handle_cdb*() -> transport_add_cmd_to_queue()
+        * in existing usage to ensure that outstanding descriptors are handled
+        * correctly during shutdown via transport_generic_wait_for_tasks()
+        *
+        * Also, we don't take cmd->t_state_lock here as we only expect
+        * this to be called for initial descriptor submission.
+        */
+       cmd->t_state = TRANSPORT_NEW_CMD;
+       atomic_set(&cmd->t_transport_active, 1);
+       /*
+        * transport_generic_new_cmd() is already handling QUEUE_FULL,
+        * so follow TRANSPORT_NEW_CMD processing thread context usage
+        * and call transport_generic_request_failure() if necessary..
+        */
+       ret = transport_generic_new_cmd(cmd);
+       if (ret == -EAGAIN)
+               return 0;
+       else if (ret < 0) {
+               cmd->transport_error_status = ret;
+               transport_generic_request_failure(cmd, NULL, 0,
+                               (cmd->data_direction != DMA_TO_DEVICE));
+       }
+       return 0;
 }
 EXPORT_SYMBOL(transport_handle_cdb_direct);
 
@@ -3324,7 +3351,7 @@ static int transport_generic_cmd_sequencer(
                        goto out_invalid_cdb_field;
                }
 
-               cmd->t_task_lba = get_unaligned_be16(&cdb[2]);
+               cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
                passthrough = (dev->transport->transport_type ==
                                TRANSPORT_PLUGIN_PHBA_PDEV);
                /*
index f7fff7e..bd4fe21 100644 (file)
@@ -187,4 +187,9 @@ void ft_dump_cmd(struct ft_cmd *, const char *caller);
 
 ssize_t ft_format_wwn(char *, size_t, u64);
 
+/*
+ * Underlying HW specific helper function
+ */
+void ft_invl_hw_context(struct ft_cmd *);
+
 #endif /* __TCM_FC_H__ */
index 09df38b..5654dc2 100644 (file)
@@ -320,6 +320,7 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
        default:
                pr_debug("%s: unhandled frame r_ctl %x\n",
                       __func__, fh->fh_r_ctl);
+               ft_invl_hw_context(cmd);
                fc_frame_free(fp);
                transport_generic_free_cmd(&cmd->se_cmd, 0, 0);
                break;
index 8e2a46d..c37f4cd 100644 (file)
@@ -213,62 +213,49 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
        if (!(ntoh24(fh->fh_f_ctl) & FC_FC_REL_OFF))
                goto drop;
 
+       f_ctl = ntoh24(fh->fh_f_ctl);
+       ep = fc_seq_exch(seq);
+       lport = ep->lp;
+       if (cmd->was_ddp_setup) {
+               BUG_ON(!ep);
+               BUG_ON(!lport);
+       }
+
        /*
-        * Doesn't expect even single byte of payload. Payload
+        * Doesn't expect payload if DDP is setup. Payload
         * is expected to be copied directly to user buffers
-        * due to DDP (Large Rx offload) feature, hence
-        * BUG_ON if BUF is non-NULL
+        * due to DDP (Large Rx offload),
         */
        buf = fc_frame_payload_get(fp, 1);
-       if (cmd->was_ddp_setup && buf) {
-               pr_debug("%s: When DDP was setup, not expected to"
-                                "receive frame with payload, Payload shall be"
-                                "copied directly to buffer instead of coming "
-                                "via. legacy receive queues\n", __func__);
-               BUG_ON(buf);
-       }
+       if (buf)
+               pr_err("%s: xid 0x%x, f_ctl 0x%x, cmd->sg %p, "
+                               "cmd->sg_cnt 0x%x. DDP was setup"
+                               " hence not expected to receive frame with "
+                               "payload, Frame will be dropped if "
+                               "'Sequence Initiative' bit in f_ctl is "
+                               "not set\n", __func__, ep->xid, f_ctl,
+                               cmd->sg, cmd->sg_cnt);
+       /*
+        * Invalidate HW DDP context if it was setup for respective
+        * command. Invalidation of HW DDP context is requited in both
+        * situation (success and error). 
+        */
+       ft_invl_hw_context(cmd);
 
        /*
-        * If ft_cmd indicated 'ddp_setup', in that case only the last frame
-        * should come with 'TSI bit being set'. If 'TSI bit is not set and if
-        * data frame appears here, means error condition. In both the cases
-        * release the DDP context (ddp_put) and in error case, as well
-        * initiate error recovery mechanism.
+        * If "Sequence Initiative (TSI)" bit set in f_ctl, means last
+        * write data frame is received successfully where payload is
+        * posted directly to user buffer and only the last frame's
+        * header is posted in receive queue.
+        *
+        * If "Sequence Initiative (TSI)" bit is not set, means error
+        * condition w.r.t. DDP, hence drop the packet and let explict
+        * ABORTS from other end of exchange timer trigger the recovery.
         */
-       ep = fc_seq_exch(seq);
-       if (cmd->was_ddp_setup) {
-               BUG_ON(!ep);
-               lport = ep->lp;
-               BUG_ON(!lport);
-       }
-       if (cmd->was_ddp_setup && ep->xid != FC_XID_UNKNOWN) {
-               f_ctl = ntoh24(fh->fh_f_ctl);
-               /*
-                * If TSI bit set in f_ctl, means last write data frame is
-                * received successfully where payload is posted directly
-                * to user buffer and only the last frame's header is posted
-                * in legacy receive queue
-                */
-               if (f_ctl & FC_FC_SEQ_INIT) { /* TSI bit set in FC frame */
-                       cmd->write_data_len = lport->tt.ddp_done(lport,
-                                                               ep->xid);
-                       goto last_frame;
-               } else {
-                       /*
-                        * Updating the write_data_len may be meaningless at
-                        * this point, but just in case if required in future
-                        * for debugging or any other purpose
-                        */
-                       pr_err("%s: Received frame with TSI bit not"
-                                       " being SET, dropping the frame, "
-                                       "cmd->sg <%p>, cmd->sg_cnt <0x%x>\n",
-                                       __func__, cmd->sg, cmd->sg_cnt);
-                       cmd->write_data_len = lport->tt.ddp_done(lport,
-                                                             ep->xid);
-                       lport->tt.seq_exch_abort(cmd->seq, 0);
-                       goto drop;
-               }
-       }
+       if (f_ctl & FC_FC_SEQ_INIT)
+               goto last_frame;
+       else
+               goto drop;
 
        rel_off = ntohl(fh->fh_parm_offset);
        frame_len = fr_len(fp);
@@ -331,3 +318,39 @@ last_frame:
 drop:
        fc_frame_free(fp);
 }
+
+/*
+ * Handle and cleanup any HW specific resources if
+ * received ABORTS, errors, timeouts.
+ */
+void ft_invl_hw_context(struct ft_cmd *cmd)
+{
+       struct fc_seq *seq = cmd->seq;
+       struct fc_exch *ep = NULL;
+       struct fc_lport *lport = NULL;
+
+       BUG_ON(!cmd);
+
+       /* Cleanup the DDP context in HW if DDP was setup */
+       if (cmd->was_ddp_setup && seq) {
+               ep = fc_seq_exch(seq);
+               if (ep) {
+                       lport = ep->lp;
+                       if (lport && (ep->xid <= lport->lro_xid))
+                               /*
+                                * "ddp_done" trigger invalidation of HW
+                                * specific DDP context
+                                */
+                               cmd->write_data_len = lport->tt.ddp_done(lport,
+                                                                     ep->xid);
+
+                               /*
+                                * Resetting same variable to indicate HW's
+                                * DDP context has been invalidated to avoid
+                                * re_invalidation of same context (context is
+                                * identified using ep->xid)
+                                */
+                               cmd->was_ddp_setup = 0;
+               }
+       }
+}
index bf7c687..f7f71b2 100644 (file)
@@ -14,11 +14,7 @@ menuconfig THERMAL
          If you want this support, you should say Y or M here.
 
 config THERMAL_HWMON
-       bool "Hardware monitoring support"
+       bool
        depends on THERMAL
        depends on HWMON=y || HWMON=THERMAL
-       help
-         The generic thermal sysfs driver's hardware monitoring support
-         requires a 2.10.7/3.0.2 or later lm-sensors userspace.
-
-         Say Y if your user-space is new enough.
+       default y
index 0b1c82a..708f8e9 100644 (file)
@@ -420,6 +420,29 @@ thermal_cooling_device_trip_point_show(struct device *dev,
 
 /* hwmon sys I/F */
 #include <linux/hwmon.h>
+
+/* thermal zone devices with the same type share one hwmon device */
+struct thermal_hwmon_device {
+       char type[THERMAL_NAME_LENGTH];
+       struct device *device;
+       int count;
+       struct list_head tz_list;
+       struct list_head node;
+};
+
+struct thermal_hwmon_attr {
+       struct device_attribute attr;
+       char name[16];
+};
+
+/* one temperature input for each thermal zone */
+struct thermal_hwmon_temp {
+       struct list_head hwmon_node;
+       struct thermal_zone_device *tz;
+       struct thermal_hwmon_attr temp_input;   /* hwmon sys attr */
+       struct thermal_hwmon_attr temp_crit;    /* hwmon sys attr */
+};
+
 static LIST_HEAD(thermal_hwmon_list);
 
 static ssize_t
@@ -437,9 +460,10 @@ temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
        int ret;
        struct thermal_hwmon_attr *hwmon_attr
                        = container_of(attr, struct thermal_hwmon_attr, attr);
-       struct thermal_zone_device *tz
-                       = container_of(hwmon_attr, struct thermal_zone_device,
+       struct thermal_hwmon_temp *temp
+                       = container_of(hwmon_attr, struct thermal_hwmon_temp,
                                       temp_input);
+       struct thermal_zone_device *tz = temp->tz;
 
        ret = tz->ops->get_temp(tz, &temperature);
 
@@ -455,9 +479,10 @@ temp_crit_show(struct device *dev, struct device_attribute *attr,
 {
        struct thermal_hwmon_attr *hwmon_attr
                        = container_of(attr, struct thermal_hwmon_attr, attr);
-       struct thermal_zone_device *tz
-                       = container_of(hwmon_attr, struct thermal_zone_device,
+       struct thermal_hwmon_temp *temp
+                       = container_of(hwmon_attr, struct thermal_hwmon_temp,
                                       temp_crit);
+       struct thermal_zone_device *tz = temp->tz;
        long temperature;
        int ret;
 
@@ -469,22 +494,54 @@ temp_crit_show(struct device *dev, struct device_attribute *attr,
 }
 
 
-static int
-thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
+static struct thermal_hwmon_device *
+thermal_hwmon_lookup_by_type(const struct thermal_zone_device *tz)
 {
        struct thermal_hwmon_device *hwmon;
-       int new_hwmon_device = 1;
-       int result;
 
        mutex_lock(&thermal_list_lock);
        list_for_each_entry(hwmon, &thermal_hwmon_list, node)
                if (!strcmp(hwmon->type, tz->type)) {
-                       new_hwmon_device = 0;
                        mutex_unlock(&thermal_list_lock);
-                       goto register_sys_interface;
+                       return hwmon;
+               }
+       mutex_unlock(&thermal_list_lock);
+
+       return NULL;
+}
+
+/* Find the temperature input matching a given thermal zone */
+static struct thermal_hwmon_temp *
+thermal_hwmon_lookup_temp(const struct thermal_hwmon_device *hwmon,
+                         const struct thermal_zone_device *tz)
+{
+       struct thermal_hwmon_temp *temp;
+
+       mutex_lock(&thermal_list_lock);
+       list_for_each_entry(temp, &hwmon->tz_list, hwmon_node)
+               if (temp->tz == tz) {
+                       mutex_unlock(&thermal_list_lock);
+                       return temp;
                }
        mutex_unlock(&thermal_list_lock);
 
+       return NULL;
+}
+
+static int
+thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
+{
+       struct thermal_hwmon_device *hwmon;
+       struct thermal_hwmon_temp *temp;
+       int new_hwmon_device = 1;
+       int result;
+
+       hwmon = thermal_hwmon_lookup_by_type(tz);
+       if (hwmon) {
+               new_hwmon_device = 0;
+               goto register_sys_interface;
+       }
+
        hwmon = kzalloc(sizeof(struct thermal_hwmon_device), GFP_KERNEL);
        if (!hwmon)
                return -ENOMEM;
@@ -502,30 +559,36 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
                goto free_mem;
 
  register_sys_interface:
-       tz->hwmon = hwmon;
+       temp = kzalloc(sizeof(struct thermal_hwmon_temp), GFP_KERNEL);
+       if (!temp) {
+               result = -ENOMEM;
+               goto unregister_name;
+       }
+
+       temp->tz = tz;
        hwmon->count++;
 
-       snprintf(tz->temp_input.name, THERMAL_NAME_LENGTH,
+       snprintf(temp->temp_input.name, THERMAL_NAME_LENGTH,
                 "temp%d_input", hwmon->count);
-       tz->temp_input.attr.attr.name = tz->temp_input.name;
-       tz->temp_input.attr.attr.mode = 0444;
-       tz->temp_input.attr.show = temp_input_show;
-       sysfs_attr_init(&tz->temp_input.attr.attr);
-       result = device_create_file(hwmon->device, &tz->temp_input.attr);
+       temp->temp_input.attr.attr.name = temp->temp_input.name;
+       temp->temp_input.attr.attr.mode = 0444;
+       temp->temp_input.attr.show = temp_input_show;
+       sysfs_attr_init(&temp->temp_input.attr.attr);
+       result = device_create_file(hwmon->device, &temp->temp_input.attr);
        if (result)
-               goto unregister_name;
+               goto free_temp_mem;
 
        if (tz->ops->get_crit_temp) {
                unsigned long temperature;
                if (!tz->ops->get_crit_temp(tz, &temperature)) {
-                       snprintf(tz->temp_crit.name, THERMAL_NAME_LENGTH,
+                       snprintf(temp->temp_crit.name, THERMAL_NAME_LENGTH,
                                "temp%d_crit", hwmon->count);
-                       tz->temp_crit.attr.attr.name = tz->temp_crit.name;
-                       tz->temp_crit.attr.attr.mode = 0444;
-                       tz->temp_crit.attr.show = temp_crit_show;
-                       sysfs_attr_init(&tz->temp_crit.attr.attr);
+                       temp->temp_crit.attr.attr.name = temp->temp_crit.name;
+                       temp->temp_crit.attr.attr.mode = 0444;
+                       temp->temp_crit.attr.show = temp_crit_show;
+                       sysfs_attr_init(&temp->temp_crit.attr.attr);
                        result = device_create_file(hwmon->device,
-                                                   &tz->temp_crit.attr);
+                                                   &temp->temp_crit.attr);
                        if (result)
                                goto unregister_input;
                }
@@ -534,13 +597,15 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
        mutex_lock(&thermal_list_lock);
        if (new_hwmon_device)
                list_add_tail(&hwmon->node, &thermal_hwmon_list);
-       list_add_tail(&tz->hwmon_node, &hwmon->tz_list);
+       list_add_tail(&temp->hwmon_node, &hwmon->tz_list);
        mutex_unlock(&thermal_list_lock);
 
        return 0;
 
  unregister_input:
-       device_remove_file(hwmon->device, &tz->temp_input.attr);
+       device_remove_file(hwmon->device, &temp->temp_input.attr);
+ free_temp_mem:
+       kfree(temp);
  unregister_name:
        if (new_hwmon_device) {
                device_remove_file(hwmon->device, &dev_attr_name);
@@ -556,15 +621,30 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
 static void
 thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
 {
-       struct thermal_hwmon_device *hwmon = tz->hwmon;
+       struct thermal_hwmon_device *hwmon;
+       struct thermal_hwmon_temp *temp;
+
+       hwmon = thermal_hwmon_lookup_by_type(tz);
+       if (unlikely(!hwmon)) {
+               /* Should never happen... */
+               dev_dbg(&tz->device, "hwmon device lookup failed!\n");
+               return;
+       }
+
+       temp = thermal_hwmon_lookup_temp(hwmon, tz);
+       if (unlikely(!temp)) {
+               /* Should never happen... */
+               dev_dbg(&tz->device, "temperature input lookup failed!\n");
+               return;
+       }
 
-       tz->hwmon = NULL;
-       device_remove_file(hwmon->device, &tz->temp_input.attr);
+       device_remove_file(hwmon->device, &temp->temp_input.attr);
        if (tz->ops->get_crit_temp)
-               device_remove_file(hwmon->device, &tz->temp_crit.attr);
+               device_remove_file(hwmon->device, &temp->temp_crit.attr);
 
        mutex_lock(&thermal_list_lock);
-       list_del(&tz->hwmon_node);
+       list_del(&temp->hwmon_node);
+       kfree(temp);
        if (!list_empty(&hwmon->tz_list)) {
                mutex_unlock(&thermal_list_lock);
                return;
index cb40b82..4dcb37b 100644 (file)
@@ -959,7 +959,7 @@ config SERIAL_IP22_ZILOG_CONSOLE
 
 config SERIAL_SH_SCI
        tristate "SuperH SCI(F) serial port support"
-       depends on HAVE_CLK && (SUPERH || H8300 || ARCH_SHMOBILE)
+       depends on HAVE_CLK && (SUPERH || ARCH_SHMOBILE)
        select SERIAL_CORE
 
 config SERIAL_SH_SCI_NR_UARTS
index 22fe801..7e91b3d 100644 (file)
 #include <linux/delay.h>
 #include <linux/rational.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <mach/hardware.h>
 #include <mach/imx-uart.h>
 
 /* Register definitions */
@@ -66,8 +67,9 @@
 #define UBIR  0xa4 /* BRM Incremental Register */
 #define UBMR  0xa8 /* BRM Modulator Register */
 #define UBRC  0xac /* Baud Rate Count Register */
-#define MX2_ONEMS 0xb0 /* One Millisecond register */
-#define UTS (cpu_is_mx1() ? 0xd0 : 0xb4) /* UART Test Register */
+#define IMX21_ONEMS 0xb0 /* One Millisecond register */
+#define IMX1_UTS 0xd0 /* UART Test Register on i.mx1 */
+#define IMX21_UTS 0xb4 /* UART Test Register on all other i.mx*/
 
 /* UART Control Register Bit Fields.*/
 #define  URXD_CHARRDY    (1<<15)
@@ -87,7 +89,7 @@
 #define  UCR1_RTSDEN     (1<<5)         /* RTS delta interrupt enable */
 #define  UCR1_SNDBRK     (1<<4)         /* Send break */
 #define  UCR1_TDMAEN     (1<<3)         /* Transmitter ready DMA enable */
-#define  MX1_UCR1_UARTCLKEN  (1<<2)     /* UART clock enabled, mx1 only */
+#define  IMX1_UCR1_UARTCLKEN  (1<<2)  /* UART clock enabled, i.mx1 only */
 #define  UCR1_DOZE       (1<<1)         /* Doze */
 #define  UCR1_UARTEN     (1<<0)         /* UART enabled */
 #define  UCR2_ESCI              (1<<15) /* Escape seq interrupt enable */
 #define  UCR3_RXDSEN    (1<<6)  /* Receive status interrupt enable */
 #define  UCR3_AIRINTEN   (1<<5)  /* Async IR wake interrupt enable */
 #define  UCR3_AWAKEN    (1<<4)  /* Async wake interrupt enable */
-#define  MX1_UCR3_REF25         (1<<3)  /* Ref freq 25 MHz, only on mx1 */
-#define  MX1_UCR3_REF30         (1<<2)  /* Ref Freq 30 MHz, only on mx1 */
-#define  MX2_UCR3_RXDMUXSEL     (1<<2)  /* RXD Muxed Input Select, on mx2/mx3 */
+#define  IMX21_UCR3_RXDMUXSEL   (1<<2)  /* RXD Muxed Input Select */
 #define  UCR3_INVT      (1<<1)  /* Inverted Infrared transmission */
 #define  UCR3_BPEN      (1<<0)  /* Preset registers enable */
 #define  UCR4_CTSTL_SHF  10      /* CTS trigger level shift */
 
 #define UART_NR 8
 
+/* i.mx21 type uart runs on all i.mx except i.mx1 */
+enum imx_uart_type {
+       IMX1_UART,
+       IMX21_UART,
+};
+
+/* device type dependent stuff */
+struct imx_uart_data {
+       unsigned uts_reg;
+       enum imx_uart_type devtype;
+};
+
 struct imx_port {
        struct uart_port        port;
        struct timer_list       timer;
@@ -192,6 +204,7 @@ struct imx_port {
        unsigned int            irda_inv_tx:1;
        unsigned short          trcv_delay; /* transceiver delay */
        struct clk              *clk;
+       struct imx_uart_data    *devdata;
 };
 
 #ifdef CONFIG_IRDA
@@ -200,6 +213,52 @@ struct imx_port {
 #define USE_IRDA(sport)        (0)
 #endif
 
+static struct imx_uart_data imx_uart_devdata[] = {
+       [IMX1_UART] = {
+               .uts_reg = IMX1_UTS,
+               .devtype = IMX1_UART,
+       },
+       [IMX21_UART] = {
+               .uts_reg = IMX21_UTS,
+               .devtype = IMX21_UART,
+       },
+};
+
+static struct platform_device_id imx_uart_devtype[] = {
+       {
+               .name = "imx1-uart",
+               .driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX1_UART],
+       }, {
+               .name = "imx21-uart",
+               .driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX21_UART],
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
+
+static struct of_device_id imx_uart_dt_ids[] = {
+       { .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
+       { .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_UART], },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_uart_dt_ids);
+
+static inline unsigned uts_reg(struct imx_port *sport)
+{
+       return sport->devdata->uts_reg;
+}
+
+static inline int is_imx1_uart(struct imx_port *sport)
+{
+       return sport->devdata->devtype == IMX1_UART;
+}
+
+static inline int is_imx21_uart(struct imx_port *sport)
+{
+       return sport->devdata->devtype == IMX21_UART;
+}
+
 /*
  * Handle any change of modem status signal since we were last called.
  */
@@ -326,7 +385,8 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
        struct circ_buf *xmit = &sport->port.state->xmit;
 
        while (!uart_circ_empty(xmit) &&
-                       !(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
+                       !(readl(sport->port.membase + uts_reg(sport))
+                               & UTS_TXFULL)) {
                /* send xmit->buf[xmit->tail]
                 * out the port here */
                writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
@@ -373,7 +433,7 @@ static void imx_start_tx(struct uart_port *port)
                writel(temp, sport->port.membase + UCR4);
        }
 
-       if (readl(sport->port.membase + UTS) & UTS_TXEMPTY)
+       if (readl(sport->port.membase + uts_reg(sport)) & UTS_TXEMPTY)
                imx_transmit_buffer(sport);
 }
 
@@ -689,9 +749,9 @@ static int imx_startup(struct uart_port *port)
                }
        }
 
-       if (!cpu_is_mx1()) {
+       if (is_imx21_uart(sport)) {
                temp = readl(sport->port.membase + UCR3);
-               temp |= MX2_UCR3_RXDMUXSEL;
+               temp |= IMX21_UCR3_RXDMUXSEL;
                writel(temp, sport->port.membase + UCR3);
        }
 
@@ -923,9 +983,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        writel(num, sport->port.membase + UBIR);
        writel(denom, sport->port.membase + UBMR);
 
-       if (!cpu_is_mx1())
+       if (is_imx21_uart(sport))
                writel(sport->port.uartclk / div / 1000,
-                               sport->port.membase + MX2_ONEMS);
+                               sport->port.membase + IMX21_ONEMS);
 
        writel(old_ucr1, sport->port.membase + UCR1);
 
@@ -1041,7 +1101,7 @@ static void imx_console_putchar(struct uart_port *port, int ch)
 {
        struct imx_port *sport = (struct imx_port *)port;
 
-       while (readl(sport->port.membase + UTS) & UTS_TXFULL)
+       while (readl(sport->port.membase + uts_reg(sport)) & UTS_TXFULL)
                barrier();
 
        writel(ch, sport->port.membase + URTX0);
@@ -1062,8 +1122,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
        ucr1 = old_ucr1 = readl(sport->port.membase + UCR1);
        old_ucr2 = readl(sport->port.membase + UCR2);
 
-       if (cpu_is_mx1())
-               ucr1 |= MX1_UCR1_UARTCLKEN;
+       if (is_imx1_uart(sport))
+               ucr1 |= IMX1_UCR1_UARTCLKEN;
        ucr1 |= UCR1_UARTEN;
        ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
 
@@ -1222,6 +1282,58 @@ static int serial_imx_resume(struct platform_device *dev)
        return 0;
 }
 
+#ifdef CONFIG_OF
+static int serial_imx_probe_dt(struct imx_port *sport,
+               struct platform_device *pdev)
+{
+       static int portnum = 0;
+       struct device_node *np = pdev->dev.of_node;
+       const struct of_device_id *of_id =
+                       of_match_device(imx_uart_dt_ids, &pdev->dev);
+
+       if (!np)
+               return -ENODEV;
+
+       sport->port.line = portnum++;
+       if (sport->port.line >= UART_NR)
+               return -EINVAL;
+
+       if (of_get_property(np, "fsl,uart-has-rtscts", NULL))
+               sport->have_rtscts = 1;
+
+       if (of_get_property(np, "fsl,irda-mode", NULL))
+               sport->use_irda = 1;
+
+       sport->devdata = of_id->data;
+
+       return 0;
+}
+#else
+static inline int serial_imx_probe_dt(struct imx_port *sport,
+               struct platform_device *pdev)
+{
+       return -ENODEV;
+}
+#endif
+
+static void serial_imx_probe_pdata(struct imx_port *sport,
+               struct platform_device *pdev)
+{
+       struct imxuart_platform_data *pdata = pdev->dev.platform_data;
+
+       sport->port.line = pdev->id;
+       sport->devdata = (struct imx_uart_data  *) pdev->id_entry->driver_data;
+
+       if (!pdata)
+               return;
+
+       if (pdata->flags & IMXUART_HAVE_RTSCTS)
+               sport->have_rtscts = 1;
+
+       if (pdata->flags & IMXUART_IRDA)
+               sport->use_irda = 1;
+}
+
 static int serial_imx_probe(struct platform_device *pdev)
 {
        struct imx_port *sport;
@@ -1234,6 +1346,10 @@ static int serial_imx_probe(struct platform_device *pdev)
        if (!sport)
                return -ENOMEM;
 
+       ret = serial_imx_probe_dt(sport, pdev);
+       if (ret == -ENODEV)
+               serial_imx_probe_pdata(sport, pdev);
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                ret = -ENODEV;
@@ -1258,7 +1374,6 @@ static int serial_imx_probe(struct platform_device *pdev)
        sport->port.fifosize = 32;
        sport->port.ops = &imx_pops;
        sport->port.flags = UPF_BOOT_AUTOCONF;
-       sport->port.line = pdev->id;
        init_timer(&sport->timer);
        sport->timer.function = imx_timeout;
        sport->timer.data     = (unsigned long)sport;
@@ -1272,17 +1387,9 @@ static int serial_imx_probe(struct platform_device *pdev)
 
        sport->port.uartclk = clk_get_rate(sport->clk);
 
-       imx_ports[pdev->id] = sport;
+       imx_ports[sport->port.line] = sport;
 
        pdata = pdev->dev.platform_data;
-       if (pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
-               sport->have_rtscts = 1;
-
-#ifdef CONFIG_IRDA
-       if (pdata && (pdata->flags & IMXUART_IRDA))
-               sport->use_irda = 1;
-#endif
-
        if (pdata && pdata->init) {
                ret = pdata->init(pdev);
                if (ret)
@@ -1340,9 +1447,11 @@ static struct platform_driver serial_imx_driver = {
 
        .suspend        = serial_imx_suspend,
        .resume         = serial_imx_resume,
+       .id_table       = imx_uart_devtype,
        .driver         = {
                .name   = "imx-uart",
                .owner  = THIS_MODULE,
+               .of_match_table = imx_uart_dt_ids,
        },
 };
 
index ebd8629..2ec57b2 100644 (file)
 #include <asm/sh_bios.h>
 #endif
 
-#ifdef CONFIG_H8300
-#include <asm/gpio.h>
-#endif
-
 #include "sh-sci.h"
 
 struct sci_port {
@@ -66,12 +62,6 @@ struct sci_port {
        /* Platform configuration */
        struct plat_sci_port    *cfg;
 
-       /* Port enable callback */
-       void                    (*enable)(struct uart_port *port);
-
-       /* Port disable callback */
-       void                    (*disable)(struct uart_port *port);
-
        /* Break timer */
        struct timer_list       break_timer;
        int                     break_flag;
@@ -81,6 +71,8 @@ struct sci_port {
        /* Function clock */
        struct clk              *fclk;
 
+       char                    *irqstr[SCIx_NR_IRQS];
+
        struct dma_chan                 *chan_tx;
        struct dma_chan                 *chan_rx;
 
@@ -121,6 +113,278 @@ to_sci_port(struct uart_port *uart)
        return container_of(uart, struct sci_port, port);
 }
 
+struct plat_sci_reg {
+       u8 offset, size;
+};
+
+/* Helper for invalidating specific entries of an inherited map. */
+#define sci_reg_invalid        { .offset = 0, .size = 0 }
+
+static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
+       [SCIx_PROBE_REGTYPE] = {
+               [0 ... SCIx_NR_REGS - 1] = sci_reg_invalid,
+       },
+
+       /*
+        * Common SCI definitions, dependent on the port's regshift
+        * value.
+        */
+       [SCIx_SCI_REGTYPE] = {
+               [SCSMR]         = { 0x00,  8 },
+               [SCBRR]         = { 0x01,  8 },
+               [SCSCR]         = { 0x02,  8 },
+               [SCxTDR]        = { 0x03,  8 },
+               [SCxSR]         = { 0x04,  8 },
+               [SCxRDR]        = { 0x05,  8 },
+               [SCFCR]         = sci_reg_invalid,
+               [SCFDR]         = sci_reg_invalid,
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = sci_reg_invalid,
+       },
+
+       /*
+        * Common definitions for legacy IrDA ports, dependent on
+        * regshift value.
+        */
+       [SCIx_IRDA_REGTYPE] = {
+               [SCSMR]         = { 0x00,  8 },
+               [SCBRR]         = { 0x01,  8 },
+               [SCSCR]         = { 0x02,  8 },
+               [SCxTDR]        = { 0x03,  8 },
+               [SCxSR]         = { 0x04,  8 },
+               [SCxRDR]        = { 0x05,  8 },
+               [SCFCR]         = { 0x06,  8 },
+               [SCFDR]         = { 0x07, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = sci_reg_invalid,
+       },
+
+       /*
+        * Common SCIFA definitions.
+        */
+       [SCIx_SCIFA_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x20,  8 },
+               [SCxSR]         = { 0x14, 16 },
+               [SCxRDR]        = { 0x24,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = sci_reg_invalid,
+       },
+
+       /*
+        * Common SCIFB definitions.
+        */
+       [SCIx_SCIFB_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x40,  8 },
+               [SCxSR]         = { 0x14, 16 },
+               [SCxRDR]        = { 0x60,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = sci_reg_invalid,
+       },
+
+       /*
+        * Common SH-3 SCIF definitions.
+        */
+       [SCIx_SH3_SCIF_REGTYPE] = {
+               [SCSMR]         = { 0x00,  8 },
+               [SCBRR]         = { 0x02,  8 },
+               [SCSCR]         = { 0x04,  8 },
+               [SCxTDR]        = { 0x06,  8 },
+               [SCxSR]         = { 0x08, 16 },
+               [SCxRDR]        = { 0x0a,  8 },
+               [SCFCR]         = { 0x0c,  8 },
+               [SCFDR]         = { 0x0e, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = sci_reg_invalid,
+       },
+
+       /*
+        * Common SH-4(A) SCIF(B) definitions.
+        */
+       [SCIx_SH4_SCIF_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x0c,  8 },
+               [SCxSR]         = { 0x10, 16 },
+               [SCxRDR]        = { 0x14,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = { 0x20, 16 },
+               [SCLSR]         = { 0x24, 16 },
+       },
+
+       /*
+        * Common SH-4(A) SCIF(B) definitions for ports without an SCSPTR
+        * register.
+        */
+       [SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x0c,  8 },
+               [SCxSR]         = { 0x10, 16 },
+               [SCxRDR]        = { 0x14,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = { 0x24, 16 },
+       },
+
+       /*
+        * Common SH-4(A) SCIF(B) definitions for ports with FIFO data
+        * count registers.
+        */
+       [SCIx_SH4_SCIF_FIFODATA_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x0c,  8 },
+               [SCxSR]         = { 0x10, 16 },
+               [SCxRDR]        = { 0x14,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = { 0x1c, 16 }, /* aliased to SCFDR */
+               [SCRFDR]        = { 0x20, 16 },
+               [SCSPTR]        = { 0x24, 16 },
+               [SCLSR]         = { 0x28, 16 },
+       },
+
+       /*
+        * SH7705-style SCIF(B) ports, lacking both SCSPTR and SCLSR
+        * registers.
+        */
+       [SCIx_SH7705_SCIF_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x20,  8 },
+               [SCxSR]         = { 0x14, 16 },
+               [SCxRDR]        = { 0x24,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = sci_reg_invalid,
+       },
+};
+
+#define sci_getreg(up, offset)         (sci_regmap[to_sci_port(up)->cfg->regtype] + offset)
+
+/*
+ * The "offset" here is rather misleading, in that it refers to an enum
+ * value relative to the port mapping rather than the fixed offset
+ * itself, which needs to be manually retrieved from the platform's
+ * register map for the given port.
+ */
+static unsigned int sci_serial_in(struct uart_port *p, int offset)
+{
+       struct plat_sci_reg *reg = sci_getreg(p, offset);
+
+       if (reg->size == 8)
+               return ioread8(p->membase + (reg->offset << p->regshift));
+       else if (reg->size == 16)
+               return ioread16(p->membase + (reg->offset << p->regshift));
+       else
+               WARN(1, "Invalid register access\n");
+
+       return 0;
+}
+
+static void sci_serial_out(struct uart_port *p, int offset, int value)
+{
+       struct plat_sci_reg *reg = sci_getreg(p, offset);
+
+       if (reg->size == 8)
+               iowrite8(value, p->membase + (reg->offset << p->regshift));
+       else if (reg->size == 16)
+               iowrite16(value, p->membase + (reg->offset << p->regshift));
+       else
+               WARN(1, "Invalid register access\n");
+}
+
+#define sci_in(up, offset)             (up->serial_in(up, offset))
+#define sci_out(up, offset, value)     (up->serial_out(up, offset, value))
+
+static int sci_probe_regmap(struct plat_sci_port *cfg)
+{
+       switch (cfg->type) {
+       case PORT_SCI:
+               cfg->regtype = SCIx_SCI_REGTYPE;
+               break;
+       case PORT_IRDA:
+               cfg->regtype = SCIx_IRDA_REGTYPE;
+               break;
+       case PORT_SCIFA:
+               cfg->regtype = SCIx_SCIFA_REGTYPE;
+               break;
+       case PORT_SCIFB:
+               cfg->regtype = SCIx_SCIFB_REGTYPE;
+               break;
+       case PORT_SCIF:
+               /*
+                * The SH-4 is a bit of a misnomer here, although that's
+                * where this particular port layout originated. This
+                * configuration (or some slight variation thereof)
+                * remains the dominant model for all SCIFs.
+                */
+               cfg->regtype = SCIx_SH4_SCIF_REGTYPE;
+               break;
+       default:
+               printk(KERN_ERR "Can't probe register map for given port\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void sci_port_enable(struct sci_port *sci_port)
+{
+       if (!sci_port->port.dev)
+               return;
+
+       pm_runtime_get_sync(sci_port->port.dev);
+
+       clk_enable(sci_port->iclk);
+       sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
+       clk_enable(sci_port->fclk);
+}
+
+static void sci_port_disable(struct sci_port *sci_port)
+{
+       if (!sci_port->port.dev)
+               return;
+
+       clk_disable(sci_port->fclk);
+       clk_disable(sci_port->iclk);
+
+       pm_runtime_put_sync(sci_port->port.dev);
+}
+
 #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
 
 #ifdef CONFIG_CONSOLE_POLL
@@ -164,223 +428,76 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c)
 }
 #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */
 
-#if defined(__H8300H__) || defined(__H8300S__)
 static void sci_init_pins(struct uart_port *port, unsigned int cflag)
 {
-       int ch = (port->mapbase - SMR0) >> 3;
-
-       /* set DDR regs */
-       H8300_GPIO_DDR(h8300_sci_pins[ch].port,
-                      h8300_sci_pins[ch].rx,
-                      H8300_GPIO_INPUT);
-       H8300_GPIO_DDR(h8300_sci_pins[ch].port,
-                      h8300_sci_pins[ch].tx,
-                      H8300_GPIO_OUTPUT);
-
-       /* tx mark output*/
-       H8300_SCI_DR(ch) |= h8300_sci_pins[ch].tx;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
-       if (port->mapbase == 0xA4400000) {
-               __raw_writew(__raw_readw(PACR) & 0xffc0, PACR);
-               __raw_writew(__raw_readw(PBCR) & 0x0fff, PBCR);
-       } else if (port->mapbase == 0xA4410000)
-               __raw_writew(__raw_readw(PBCR) & 0xf003, PBCR);
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || defined(CONFIG_CPU_SUBTYPE_SH7721)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
-       unsigned short data;
-
-       if (cflag & CRTSCTS) {
-               /* enable RTS/CTS */
-               if (port->mapbase == 0xa4430000) { /* SCIF0 */
-                       /* Clear PTCR bit 9-2; enable all scif pins but sck */
-                       data = __raw_readw(PORT_PTCR);
-                       __raw_writew((data & 0xfc03), PORT_PTCR);
-               } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
-                       /* Clear PVCR bit 9-2 */
-                       data = __raw_readw(PORT_PVCR);
-                       __raw_writew((data & 0xfc03), PORT_PVCR);
-               }
-       } else {
-               if (port->mapbase == 0xa4430000) { /* SCIF0 */
-                       /* Clear PTCR bit 5-2; enable only tx and rx  */
-                       data = __raw_readw(PORT_PTCR);
-                       __raw_writew((data & 0xffc3), PORT_PTCR);
-               } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
-                       /* Clear PVCR bit 5-2 */
-                       data = __raw_readw(PORT_PVCR);
-                       __raw_writew((data & 0xffc3), PORT_PVCR);
-               }
-       }
-}
-#elif defined(CONFIG_CPU_SH3)
-/* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
-       unsigned short data;
-
-       /* We need to set SCPCR to enable RTS/CTS */
-       data = __raw_readw(SCPCR);
-       /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
-       __raw_writew(data & 0x0fcf, SCPCR);
-
-       if (!(cflag & CRTSCTS)) {
-               /* We need to set SCPCR to enable RTS/CTS */
-               data = __raw_readw(SCPCR);
-               /* Clear out SCP7MD1,0, SCP4MD1,0,
-                  Set SCP6MD1,0 = {01} (output)  */
-               __raw_writew((data & 0x0fcf) | 0x1000, SCPCR);
+       struct sci_port *s = to_sci_port(port);
+       struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
 
-               data = __raw_readb(SCPDR);
-               /* Set /RTS2 (bit6) = 0 */
-               __raw_writeb(data & 0xbf, SCPDR);
+       /*
+        * Use port-specific handler if provided.
+        */
+       if (s->cfg->ops && s->cfg->ops->init_pins) {
+               s->cfg->ops->init_pins(port, cflag);
+               return;
        }
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
-       unsigned short data;
 
-       if (port->mapbase == 0xffe00000) {
-               data = __raw_readw(PSCR);
-               data &= ~0x03cf;
-               if (!(cflag & CRTSCTS))
-                       data |= 0x0340;
+       /*
+        * For the generic path SCSPTR is necessary. Bail out if that's
+        * unavailable, too.
+        */
+       if (!reg->size)
+               return;
 
-               __raw_writew(data, PSCR);
-       }
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7757) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7763) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7785) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7786) || \
-      defined(CONFIG_CPU_SUBTYPE_SHX3)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
        if (!(cflag & CRTSCTS))
-               __raw_writew(0x0080, SCSPTR0); /* Set RTS = 1 */
+               sci_out(port, SCSPTR, 0x0080); /* Set RTS = 1 */
 }
-#elif defined(CONFIG_CPU_SH4) && !defined(CONFIG_CPU_SH4A)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
-       if (!(cflag & CRTSCTS))
-               __raw_writew(0x0080, SCSPTR2); /* Set RTS = 1 */
-}
-#else
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
-       /* Nothing to do */
-}
-#endif
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7785) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7786)
-static int scif_txfill(struct uart_port *port)
-{
-       return sci_in(port, SCTFDR) & 0xff;
-}
-
-static int scif_txroom(struct uart_port *port)
+static int sci_txfill(struct uart_port *port)
 {
-       return SCIF_TXROOM_MAX - scif_txfill(port);
-}
+       struct plat_sci_reg *reg;
 
-static int scif_rxfill(struct uart_port *port)
-{
-       return sci_in(port, SCRFDR) & 0xff;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-static int scif_txfill(struct uart_port *port)
-{
-       if (port->mapbase == 0xffe00000 ||
-           port->mapbase == 0xffe08000)
-               /* SCIF0/1*/
+       reg = sci_getreg(port, SCTFDR);
+       if (reg->size)
                return sci_in(port, SCTFDR) & 0xff;
-       else
-               /* SCIF2 */
+
+       reg = sci_getreg(port, SCFDR);
+       if (reg->size)
                return sci_in(port, SCFDR) >> 8;
-}
 
-static int scif_txroom(struct uart_port *port)
-{
-       if (port->mapbase == 0xffe00000 ||
-           port->mapbase == 0xffe08000)
-               /* SCIF0/1*/
-               return SCIF_TXROOM_MAX - scif_txfill(port);
-       else
-               /* SCIF2 */
-               return SCIF2_TXROOM_MAX - scif_txfill(port);
+       return !(sci_in(port, SCxSR) & SCI_TDRE);
 }
 
-static int scif_rxfill(struct uart_port *port)
-{
-       if ((port->mapbase == 0xffe00000) ||
-           (port->mapbase == 0xffe08000)) {
-               /* SCIF0/1*/
-               return sci_in(port, SCRFDR) & 0xff;
-       } else {
-               /* SCIF2 */
-               return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
-       }
-}
-#elif defined(CONFIG_ARCH_SH7372)
-static int scif_txfill(struct uart_port *port)
+static int sci_txroom(struct uart_port *port)
 {
-       if (port->type == PORT_SCIFA)
-               return sci_in(port, SCFDR) >> 8;
-       else
-               return sci_in(port, SCTFDR);
+       return port->fifosize - sci_txfill(port);
 }
 
-static int scif_txroom(struct uart_port *port)
+static int sci_rxfill(struct uart_port *port)
 {
-       return port->fifosize - scif_txfill(port);
-}
+       struct plat_sci_reg *reg;
 
-static int scif_rxfill(struct uart_port *port)
-{
-       if (port->type == PORT_SCIFA)
-               return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
-       else
-               return sci_in(port, SCRFDR);
-}
-#else
-static int scif_txfill(struct uart_port *port)
-{
-       return sci_in(port, SCFDR) >> 8;
-}
+       reg = sci_getreg(port, SCRFDR);
+       if (reg->size)
+               return sci_in(port, SCRFDR) & 0xff;
 
-static int scif_txroom(struct uart_port *port)
-{
-       return SCIF_TXROOM_MAX - scif_txfill(port);
-}
+       reg = sci_getreg(port, SCFDR);
+       if (reg->size)
+               return sci_in(port, SCFDR) & ((port->fifosize << 1) - 1);
 
-static int scif_rxfill(struct uart_port *port)
-{
-       return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
+       return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
 }
-#endif
 
-static int sci_txfill(struct uart_port *port)
+/*
+ * SCI helper for checking the state of the muxed port/RXD pins.
+ */
+static inline int sci_rxd_in(struct uart_port *port)
 {
-       return !(sci_in(port, SCxSR) & SCI_TDRE);
-}
+       struct sci_port *s = to_sci_port(port);
 
-static int sci_txroom(struct uart_port *port)
-{
-       return !sci_txfill(port);
-}
+       if (s->cfg->port_reg <= 0)
+               return 1;
 
-static int sci_rxfill(struct uart_port *port)
-{
-       return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
+       return !!__raw_readb(s->cfg->port_reg);
 }
 
 /* ********************************************************************** *
@@ -406,10 +523,7 @@ static void sci_transmit_chars(struct uart_port *port)
                return;
        }
 
-       if (port->type == PORT_SCI)
-               count = sci_txroom(port);
-       else
-               count = scif_txroom(port);
+       count = sci_txroom(port);
 
        do {
                unsigned char c;
@@ -464,13 +578,8 @@ static void sci_receive_chars(struct uart_port *port)
                return;
 
        while (1) {
-               if (port->type == PORT_SCI)
-                       count = sci_rxfill(port);
-               else
-                       count = scif_rxfill(port);
-
                /* Don't copy more bytes than there is room for in the buffer */
-               count = tty_buffer_request_room(tty, count);
+               count = tty_buffer_request_room(tty, sci_rxfill(port));
 
                /* If for any reason we can't copy more data, we're done! */
                if (count == 0)
@@ -561,8 +670,7 @@ static void sci_break_timer(unsigned long data)
 {
        struct sci_port *port = (struct sci_port *)data;
 
-       if (port->enable)
-               port->enable(&port->port);
+       sci_port_enable(port);
 
        if (sci_rxd_in(&port->port) == 0) {
                port->break_flag = 1;
@@ -574,8 +682,7 @@ static void sci_break_timer(unsigned long data)
        } else
                port->break_flag = 0;
 
-       if (port->disable)
-               port->disable(&port->port);
+       sci_port_disable(port);
 }
 
 static int sci_handle_errors(struct uart_port *port)
@@ -583,13 +690,19 @@ static int sci_handle_errors(struct uart_port *port)
        int copied = 0;
        unsigned short status = sci_in(port, SCxSR);
        struct tty_struct *tty = port->state->port.tty;
+       struct sci_port *s = to_sci_port(port);
 
-       if (status & SCxSR_ORER(port)) {
-               /* overrun error */
-               if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
-                       copied++;
+       /*
+        * Handle overruns, if supported.
+        */
+       if (s->cfg->overrun_bit != SCIx_NOT_SUPPORTED) {
+               if (status & (1 << s->cfg->overrun_bit)) {
+                       /* overrun error */
+                       if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
+                               copied++;
 
-               dev_notice(port->dev, "overrun error");
+                       dev_notice(port->dev, "overrun error");
+               }
        }
 
        if (status & SCxSR_FER(port)) {
@@ -637,12 +750,15 @@ static int sci_handle_errors(struct uart_port *port)
 static int sci_handle_fifo_overrun(struct uart_port *port)
 {
        struct tty_struct *tty = port->state->port.tty;
+       struct sci_port *s = to_sci_port(port);
+       struct plat_sci_reg *reg;
        int copied = 0;
 
-       if (port->type != PORT_SCIF)
+       reg = sci_getreg(port, SCLSR);
+       if (!reg->size)
                return 0;
 
-       if ((sci_in(port, SCLSR) & SCIF_ORER) != 0) {
+       if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) {
                sci_out(port, SCLSR, 0);
 
                tty_insert_flip_char(tty, 0, TTY_OVERRUN);
@@ -840,74 +956,102 @@ static int sci_notifier(struct notifier_block *self,
        return NOTIFY_OK;
 }
 
-static void sci_clk_enable(struct uart_port *port)
-{
-       struct sci_port *sci_port = to_sci_port(port);
-
-       pm_runtime_get_sync(port->dev);
+static struct sci_irq_desc {
+       const char      *desc;
+       irq_handler_t   handler;
+} sci_irq_desc[] = {
+       /*
+        * Split out handlers, the default case.
+        */
+       [SCIx_ERI_IRQ] = {
+               .desc = "rx err",
+               .handler = sci_er_interrupt,
+       },
 
-       clk_enable(sci_port->iclk);
-       sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
-       clk_enable(sci_port->fclk);
-}
+       [SCIx_RXI_IRQ] = {
+               .desc = "rx full",
+               .handler = sci_rx_interrupt,
+       },
 
-static void sci_clk_disable(struct uart_port *port)
-{
-       struct sci_port *sci_port = to_sci_port(port);
+       [SCIx_TXI_IRQ] = {
+               .desc = "tx empty",
+               .handler = sci_tx_interrupt,
+       },
 
-       clk_disable(sci_port->fclk);
-       clk_disable(sci_port->iclk);
+       [SCIx_BRI_IRQ] = {
+               .desc = "break",
+               .handler = sci_br_interrupt,
+       },
 
-       pm_runtime_put_sync(port->dev);
-}
+       /*
+        * Special muxed handler.
+        */
+       [SCIx_MUX_IRQ] = {
+               .desc = "mux",
+               .handler = sci_mpxed_interrupt,
+       },
+};
 
 static int sci_request_irq(struct sci_port *port)
 {
-       int i;
-       irqreturn_t (*handlers[4])(int irq, void *ptr) = {
-               sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt,
-               sci_br_interrupt,
-       };
-       const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full",
-                              "SCI Transmit Data Empty", "SCI Break" };
-
-       if (port->cfg->irqs[0] == port->cfg->irqs[1]) {
-               if (unlikely(!port->cfg->irqs[0]))
-                       return -ENODEV;
-
-               if (request_irq(port->cfg->irqs[0], sci_mpxed_interrupt,
-                               IRQF_DISABLED, "sci", port)) {
-                       dev_err(port->port.dev, "Can't allocate IRQ\n");
-                       return -ENODEV;
+       struct uart_port *up = &port->port;
+       int i, j, ret = 0;
+
+       for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) {
+               struct sci_irq_desc *desc;
+               unsigned int irq;
+
+               if (SCIx_IRQ_IS_MUXED(port)) {
+                       i = SCIx_MUX_IRQ;
+                       irq = up->irq;
+               } else
+                       irq = port->cfg->irqs[i];
+
+               desc = sci_irq_desc + i;
+               port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
+                                           dev_name(up->dev), desc->desc);
+               if (!port->irqstr[j]) {
+                       dev_err(up->dev, "Failed to allocate %s IRQ string\n",
+                               desc->desc);
+                       goto out_nomem;
                }
-       } else {
-               for (i = 0; i < ARRAY_SIZE(handlers); i++) {
-                       if (unlikely(!port->cfg->irqs[i]))
-                               continue;
-
-                       if (request_irq(port->cfg->irqs[i], handlers[i],
-                                       IRQF_DISABLED, desc[i], port)) {
-                               dev_err(port->port.dev, "Can't allocate IRQ\n");
-                               return -ENODEV;
-                       }
+
+               ret = request_irq(irq, desc->handler, up->irqflags,
+                                 port->irqstr[j], port);
+               if (unlikely(ret)) {
+                       dev_err(up->dev, "Can't allocate %s IRQ\n", desc->desc);
+                       goto out_noirq;
                }
        }
 
        return 0;
+
+out_noirq:
+       while (--i >= 0)
+               free_irq(port->cfg->irqs[i], port);
+
+out_nomem:
+       while (--j >= 0)
+               kfree(port->irqstr[j]);
+
+       return ret;
 }
 
 static void sci_free_irq(struct sci_port *port)
 {
        int i;
 
-       if (port->cfg->irqs[0] == port->cfg->irqs[1])
-               free_irq(port->cfg->irqs[0], port);
-       else {
-               for (i = 0; i < ARRAY_SIZE(port->cfg->irqs); i++) {
-                       if (!port->cfg->irqs[i])
-                               continue;
+       /*
+        * Intentionally in reverse order so we iterate over the muxed
+        * IRQ first.
+        */
+       for (i = 0; i < SCIx_NR_IRQS; i++) {
+               free_irq(port->cfg->irqs[i], port);
+               kfree(port->irqstr[i]);
 
-                       free_irq(port->cfg->irqs[i], port);
+               if (SCIx_IRQ_IS_MUXED(port)) {
+                       /* If there's only one IRQ, we're done. */
+                       return;
                }
        }
 }
@@ -915,7 +1059,7 @@ static void sci_free_irq(struct sci_port *port)
 static unsigned int sci_tx_empty(struct uart_port *port)
 {
        unsigned short status = sci_in(port, SCxSR);
-       unsigned short in_tx_fifo = scif_txfill(port);
+       unsigned short in_tx_fifo = sci_txfill(port);
 
        return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
 }
@@ -1438,8 +1582,7 @@ static int sci_startup(struct uart_port *port)
 
        dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
 
-       if (s->enable)
-               s->enable(port);
+       sci_port_enable(s);
 
        ret = sci_request_irq(s);
        if (unlikely(ret < 0))
@@ -1465,8 +1608,7 @@ static void sci_shutdown(struct uart_port *port)
        sci_free_dma(port);
        sci_free_irq(s);
 
-       if (s->disable)
-               s->disable(port);
+       sci_port_disable(s);
 }
 
 static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
@@ -1513,8 +1655,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
        if (likely(baud && port->uartclk))
                t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, port->uartclk);
 
-       if (s->enable)
-               s->enable(port);
+       sci_port_enable(s);
 
        do {
                status = sci_in(port, SCxSR);
@@ -1584,8 +1725,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
        if ((termios->c_cflag & CREAD) != 0)
                sci_start_rx(port);
 
-       if (s->disable)
-               s->disable(port);
+       sci_port_disable(s);
 }
 
 static const char *sci_type(struct uart_port *port)
@@ -1726,6 +1866,7 @@ static int __devinit sci_init_single(struct platform_device *dev,
                                     struct plat_sci_port *p)
 {
        struct uart_port *port = &sci_port->port;
+       int ret;
 
        port->ops       = &sci_uart_ops;
        port->iotype    = UPIO_MEM;
@@ -1746,6 +1887,12 @@ static int __devinit sci_init_single(struct platform_device *dev,
                break;
        }
 
+       if (p->regtype == SCIx_PROBE_REGTYPE) {
+               ret = sci_probe_regmap(p);
+               if (unlikely(ret))
+                       return ret;
+       }
+
        if (dev) {
                sci_port->iclk = clk_get(&dev->dev, "sci_ick");
                if (IS_ERR(sci_port->iclk)) {
@@ -1764,8 +1911,6 @@ static int __devinit sci_init_single(struct platform_device *dev,
                if (IS_ERR(sci_port->fclk))
                        sci_port->fclk = NULL;
 
-               sci_port->enable = sci_clk_enable;
-               sci_port->disable = sci_clk_disable;
                port->dev = &dev->dev;
 
                pm_runtime_enable(&dev->dev);
@@ -1775,20 +1920,51 @@ static int __devinit sci_init_single(struct platform_device *dev,
        sci_port->break_timer.function = sci_break_timer;
        init_timer(&sci_port->break_timer);
 
+       /*
+        * Establish some sensible defaults for the error detection.
+        */
+       if (!p->error_mask)
+               p->error_mask = (p->type == PORT_SCI) ?
+                       SCI_DEFAULT_ERROR_MASK : SCIF_DEFAULT_ERROR_MASK;
+
+       /*
+        * Establish sensible defaults for the overrun detection, unless
+        * the part has explicitly disabled support for it.
+        */
+       if (p->overrun_bit != SCIx_NOT_SUPPORTED) {
+               if (p->type == PORT_SCI)
+                       p->overrun_bit = 5;
+               else if (p->scbrr_algo_id == SCBRR_ALGO_4)
+                       p->overrun_bit = 9;
+               else
+                       p->overrun_bit = 0;
+
+               /*
+                * Make the error mask inclusive of overrun detection, if
+                * supported.
+                */
+               p->error_mask |= (1 << p->overrun_bit);
+       }
+
        sci_port->cfg           = p;
 
        port->mapbase           = p->mapbase;
        port->type              = p->type;
        port->flags             = p->flags;
+       port->regshift          = p->regshift;
 
        /*
-        * The UART port needs an IRQ value, so we peg this to the TX IRQ
+        * The UART port needs an IRQ value, so we peg this to the RX IRQ
         * for the multi-IRQ ports, which is where we are primarily
         * concerned with the shutdown path synchronization.
         *
         * For the muxed case there's nothing more to do.
         */
        port->irq               = p->irqs[SCIx_RXI_IRQ];
+       port->irqflags          = IRQF_DISABLED;
+
+       port->serial_in         = sci_serial_in;
+       port->serial_out        = sci_serial_out;
 
        if (p->dma_dev)
                dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n",
@@ -1814,8 +1990,7 @@ static void serial_console_write(struct console *co, const char *s,
        struct uart_port *port = &sci_port->port;
        unsigned short bits;
 
-       if (sci_port->enable)
-               sci_port->enable(port);
+       sci_port_enable(sci_port);
 
        uart_console_write(port, s, count, serial_console_putchar);
 
@@ -1824,8 +1999,7 @@ static void serial_console_write(struct console *co, const char *s,
        while ((sci_in(port, SCxSR) & bits) != bits)
                cpu_relax();
 
-       if (sci_port->disable)
-               sci_port->disable(port);
+       sci_port_disable(sci_port);
 }
 
 static int __devinit serial_console_setup(struct console *co, char *options)
@@ -1857,20 +2031,13 @@ static int __devinit serial_console_setup(struct console *co, char *options)
        if (unlikely(ret != 0))
                return ret;
 
-       if (sci_port->enable)
-               sci_port->enable(port);
+       sci_port_enable(sci_port);
 
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
 
-       ret = uart_set_options(port, co, baud, parity, bits, flow);
-#if defined(__H8300H__) || defined(__H8300S__)
-       /* disable rx interrupt */
-       if (ret == 0)
-               sci_stop_rx(port);
-#endif
        /* TODO: disable clock */
-       return ret;
+       return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
 static struct console serial_console = {
@@ -2081,3 +2248,5 @@ module_exit(sci_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:sh-sci");
+MODULE_AUTHOR("Paul Mundt");
+MODULE_DESCRIPTION("SuperH SCI(F) serial driver");
index b04d937..e9bed03 100644 (file)
 #include <linux/io.h>
 #include <linux/gpio.h>
 
-#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
-#include <asm/regs306x.h>
-#endif
-#if defined(CONFIG_H8S2678)
-#include <asm/regs267x.h>
-#endif
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7707) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7708) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7709)
-# define SCPCR  0xA4000116 /* 16 bit SCI and SCIF */
-# define SCPDR  0xA4000136 /* 8  bit SCI and SCIF */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
-# define SCIF0         0xA4400000
-# define SCIF2         0xA4410000
-# define SCPCR 0xA4000116
-# define SCPDR 0xA4000136
-#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-      defined(CONFIG_ARCH_SH73A0) || \
-      defined(CONFIG_ARCH_SH7367) || \
-      defined(CONFIG_ARCH_SH7377) || \
-      defined(CONFIG_ARCH_SH7372)
-# define PORT_PTCR        0xA405011EUL
-# define PORT_PVCR        0xA4050122UL
-# define SCIF_ORER        0x0200   /* overrun error bit */
-#elif defined(CONFIG_SH_RTS7751R2D)
-# define SCSPTR1 0xFFE0001C /* 8 bit SCIF */
-# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001   /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750)  || \
-      defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7091)  || \
-      defined(CONFIG_CPU_SUBTYPE_SH7751)  || \
-      defined(CONFIG_CPU_SUBTYPE_SH7751R)
-# define SCSPTR1 0xffe0001c /* 8  bit SCI */
-# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001   /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-# define SCSPTR0 0xfe600024 /* 16 bit SCIF */
-# define SCSPTR1 0xfe610024 /* 16 bit SCIF */
-# define SCSPTR2 0xfe620024 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
-# define SCSPTR0 0xA4400000      /* 16 bit SCIF */
-# define SCIF_ORER 0x0001   /* overrun error bit */
-# define PACR 0xa4050100
-# define PBCR 0xa4050102
-#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
-# define SCSPTR0 0xffe00010    /* 16 bit SCIF */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
-# define PADR                  0xA4050120
-# define PSDR                  0xA405013e
-# define PWDR                  0xA4050166
-# define PSCR                  0xA405011E
-# define SCIF_ORER             0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7366)
-# define SCPDR0                        0xA405013E      /* 16 bit SCIF0 PSDR */
-# define SCSPTR0               SCPDR0
-# define SCIF_ORER             0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
-# define SCSPTR0                0xa4050160
-# define SCIF_ORER              0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
-# define SCIF_ORER              0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
-# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001   /* overrun error bit */
-#elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
-# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
-#elif defined(CONFIG_H8S2678)
-# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
-# define SCSPTR0 0xfe4b0020
-# define SCIF_ORER 0x0001
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-# define SCSPTR0 0xffe00024 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
-# define SCSPTR0 0xff923020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-# define SCSPTR0       0xffe00024      /* 16 bit SCIF */
-# define SCIF_ORER     0x0001          /* Overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7786)
-# define SCSPTR0       0xffea0024      /* 16 bit SCIF */
-# define SCIF_ORER     0x0001          /* Overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7203) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7206) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7263)
-# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
-# define SCSPTR0 0xf8400020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
-# define SCSPTR0 0xffc30020            /* 16 bit SCIF */
-# define SCIF_ORER 0x0001              /* Overrun error bit */
-#else
-# error CPU subtype not defined
-#endif
-
-/* SCxSR SCI */
-#define SCI_TDRE  0x80 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_RDRF  0x40 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_ORER  0x20 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_FER   0x10 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_PER   0x08 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_TEND  0x04 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-/*      SCI_MPB   0x02  * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-/*      SCI_MPBT  0x01  * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-
-#define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER)
-
-/* SCxSR SCIF */
-#define SCIF_ER    0x0080 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_TEND  0x0040 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_TDFE  0x0020 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_BRK   0x0010 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_FER   0x0008 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_PER   0x0004 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_RDF   0x0002 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_DR    0x0001 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-    defined(CONFIG_ARCH_SH73A0) || \
-    defined(CONFIG_ARCH_SH7367) || \
-    defined(CONFIG_ARCH_SH7377) || \
-    defined(CONFIG_ARCH_SH7372)
-# define SCIF_ORER    0x0200
-# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER)
-# define SCIF_RFDC_MASK 0x007f
-# define SCIF_TXROOM_MAX 64
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK )
-# define SCIF_RFDC_MASK 0x007f
-# define SCIF_TXROOM_MAX 64
-/* SH7763 SCIF2 support */
-# define SCIF2_RFDC_MASK 0x001f
-# define SCIF2_TXROOM_MAX 16
-#else
-# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
-# define SCIF_RFDC_MASK 0x001f
-# define SCIF_TXROOM_MAX 16
-#endif
-
-#ifndef SCIF_ORER
-#define SCIF_ORER      0x0000
-#endif
-
 #define SCxSR_TEND(port)       (((port)->type == PORT_SCI) ? SCI_TEND   : SCIF_TEND)
-#define SCxSR_ERRORS(port)     (((port)->type == PORT_SCI) ? SCI_ERRORS : SCIF_ERRORS)
 #define SCxSR_RDxF(port)       (((port)->type == PORT_SCI) ? SCI_RDRF   : SCIF_RDF)
 #define SCxSR_TDxE(port)       (((port)->type == PORT_SCI) ? SCI_TDRE   : SCIF_TDFE)
 #define SCxSR_FER(port)                (((port)->type == PORT_SCI) ? SCI_FER    : SCIF_FER)
 #define SCxSR_PER(port)                (((port)->type == PORT_SCI) ? SCI_PER    : SCIF_PER)
 #define SCxSR_BRK(port)                (((port)->type == PORT_SCI) ? 0x00       : SCIF_BRK)
-#define SCxSR_ORER(port)       (((port)->type == PORT_SCI) ? SCI_ORER   : SCIF_ORER)
+
+#define SCxSR_ERRORS(port)     (to_sci_port(port)->cfg->error_mask)
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
 
 #define SCI_MAJOR              204
 #define SCI_MINOR_START                8
-
-#define SCI_IN(size, offset)                                   \
-  if ((size) == 8) {                                           \
-    return ioread8(port->membase + (offset));                  \
-  } else {                                                     \
-    return ioread16(port->membase + (offset));                 \
-  }
-#define SCI_OUT(size, offset, value)                           \
-  if ((size) == 8) {                                           \
-    iowrite8(value, port->membase + (offset));                 \
-  } else if ((size) == 16) {                                   \
-    iowrite16(value, port->membase + (offset));                        \
-  }
-
-#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
-  static inline unsigned int sci_##name##_in(struct uart_port *port)   \
-  {                                                                    \
-    if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {         \
-      SCI_IN(scif_size, scif_offset)                                   \
-    } else {   /* PORT_SCI or PORT_SCIFA */                            \
-      SCI_IN(sci_size, sci_offset);                                    \
-    }                                                                  \
-  }                                                                    \
-  static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
-  {                                                                    \
-    if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {         \
-      SCI_OUT(scif_size, scif_offset, value)                           \
-    } else {   /* PORT_SCI or PORT_SCIFA */                            \
-      SCI_OUT(sci_size, sci_offset, value);                            \
-    }                                                                  \
-  }
-
-#ifdef CONFIG_H8300
-/* h8300 don't have SCIF */
-#define CPU_SCIF_FNS(name)                                             \
-  static inline unsigned int sci_##name##_in(struct uart_port *port)   \
-  {                                                                    \
-    return 0;                                                          \
-  }                                                                    \
-  static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
-  {                                                                    \
-  }
-#else
-#define CPU_SCIF_FNS(name, scif_offset, scif_size)                     \
-  static inline unsigned int sci_##name##_in(struct uart_port *port)   \
-  {                                                                    \
-    SCI_IN(scif_size, scif_offset);                                    \
-  }                                                                    \
-  static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
-  {                                                                    \
-    SCI_OUT(scif_size, scif_offset, value);                            \
-  }
-#endif
-
-#define CPU_SCI_FNS(name, sci_offset, sci_size)                                \
-  static inline unsigned int sci_##name##_in(struct uart_port* port)   \
-  {                                                                    \
-    SCI_IN(sci_size, sci_offset);                                      \
-  }                                                                    \
-  static inline void sci_##name##_out(struct uart_port* port, unsigned int value) \
-  {                                                                    \
-    SCI_OUT(sci_size, sci_offset, value);                              \
-  }
-
-#if defined(CONFIG_CPU_SH3) || \
-    defined(CONFIG_ARCH_SH73A0) || \
-    defined(CONFIG_ARCH_SH7367) || \
-    defined(CONFIG_ARCH_SH7377) || \
-    defined(CONFIG_ARCH_SH7372)
-#if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
-#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
-                               sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
-                                h8_sci_offset, h8_sci_size) \
-  CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
-         CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-      defined(CONFIG_ARCH_SH7367)
-#define SCIF_FNS(name, scif_offset, scif_size) \
-  CPU_SCIF_FNS(name, scif_offset, scif_size)
-#elif defined(CONFIG_ARCH_SH7377) || \
-      defined(CONFIG_ARCH_SH7372) || \
-      defined(CONFIG_ARCH_SH73A0)
-#define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) \
-  CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size)
-#define SCIF_FNS(name, scif_offset, scif_size) \
-  CPU_SCIF_FNS(name, scif_offset, scif_size)
-#else
-#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
-                sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
-                 h8_sci_offset, h8_sci_size) \
-  CPU_SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh3_scif_offset, sh3_scif_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
-  CPU_SCIF_FNS(name, sh3_scif_offset, sh3_scif_size)
-#endif
-#elif defined(__H8300H__) || defined(__H8300S__)
-#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
-                sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
-                 h8_sci_offset, h8_sci_size) \
-  CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
-  CPU_SCIF_FNS(name)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
-      defined(CONFIG_CPU_SUBTYPE_SH7724)
-        #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \
-                CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size)
-        #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \
-                CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
-#else
-#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
-                sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
-                h8_sci_offset, h8_sci_size) \
-  CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
-  CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
-#endif
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-    defined(CONFIG_ARCH_SH7367)
-
-SCIF_FNS(SCSMR,  0x00, 16)
-SCIF_FNS(SCBRR,  0x04,  8)
-SCIF_FNS(SCSCR,  0x08, 16)
-SCIF_FNS(SCxSR,  0x14, 16)
-SCIF_FNS(SCFCR,  0x18, 16)
-SCIF_FNS(SCFDR,  0x1c, 16)
-SCIF_FNS(SCxTDR, 0x20,  8)
-SCIF_FNS(SCxRDR, 0x24,  8)
-SCIF_FNS(SCLSR,  0x00,  0)
-#elif defined(CONFIG_ARCH_SH7377) || \
-      defined(CONFIG_ARCH_SH7372) || \
-      defined(CONFIG_ARCH_SH73A0)
-SCIF_FNS(SCSMR,  0x00, 16)
-SCIF_FNS(SCBRR,  0x04,  8)
-SCIF_FNS(SCSCR,  0x08, 16)
-SCIF_FNS(SCTDSR, 0x0c, 16)
-SCIF_FNS(SCFER,  0x10, 16)
-SCIF_FNS(SCxSR,  0x14, 16)
-SCIF_FNS(SCFCR,  0x18, 16)
-SCIF_FNS(SCFDR,  0x1c, 16)
-SCIF_FNS(SCTFDR, 0x38, 16)
-SCIF_FNS(SCRFDR, 0x3c, 16)
-SCIx_FNS(SCxTDR, 0x20,  8, 0x40,  8)
-SCIx_FNS(SCxRDR, 0x24,  8, 0x60,  8)
-SCIF_FNS(SCLSR,  0x00,  0)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
-      defined(CONFIG_CPU_SUBTYPE_SH7724)
-SCIx_FNS(SCSMR,  0x00, 16, 0x00, 16)
-SCIx_FNS(SCBRR,  0x04,  8, 0x04,  8)
-SCIx_FNS(SCSCR,  0x08, 16, 0x08, 16)
-SCIx_FNS(SCxTDR, 0x20,  8, 0x0c,  8)
-SCIx_FNS(SCxSR,  0x14, 16, 0x10, 16)
-SCIx_FNS(SCxRDR, 0x24,  8, 0x14,  8)
-SCIx_FNS(SCSPTR, 0,     0,    0,  0)
-SCIF_FNS(SCFCR,  0x18, 16)
-SCIF_FNS(SCFDR,  0x1c, 16)
-SCIF_FNS(SCLSR,  0x24, 16)
-#else
-/*      reg      SCI/SH3   SCI/SH4  SCIF/SH3   SCIF/SH4  SCI/H8*/
-/*      name     off  sz   off  sz   off  sz   off  sz   off  sz*/
-SCIx_FNS(SCSMR,  0x00,  8, 0x00,  8, 0x00,  8, 0x00, 16, 0x00,  8)
-SCIx_FNS(SCBRR,  0x02,  8, 0x04,  8, 0x02,  8, 0x04,  8, 0x01,  8)
-SCIx_FNS(SCSCR,  0x04,  8, 0x08,  8, 0x04,  8, 0x08, 16, 0x02,  8)
-SCIx_FNS(SCxTDR, 0x06,  8, 0x0c,  8, 0x06,  8, 0x0C,  8, 0x03,  8)
-SCIx_FNS(SCxSR,  0x08,  8, 0x10,  8, 0x08, 16, 0x10, 16, 0x04,  8)
-SCIx_FNS(SCxRDR, 0x0a,  8, 0x14,  8, 0x0A,  8, 0x14,  8, 0x05,  8)
-SCIF_FNS(SCFCR,                      0x0c,  8, 0x18, 16)
-#if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7785) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7786)
-SCIF_FNS(SCFDR,                             0x0e, 16, 0x1C, 16)
-SCIF_FNS(SCTFDR,                    0x0e, 16, 0x1C, 16)
-SCIF_FNS(SCRFDR,                    0x0e, 16, 0x20, 16)
-SCIF_FNS(SCSPTR,                       0,  0, 0x24, 16)
-SCIF_FNS(SCLSR,                                0,  0, 0x28, 16)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-SCIF_FNS(SCFDR,                                0,  0, 0x1C, 16)
-SCIF_FNS(SCTFDR,                    0x0e, 16, 0x1C, 16)
-SCIF_FNS(SCRFDR,                    0x0e, 16, 0x20, 16)
-SCIF_FNS(SCSPTR,                       0,  0, 0x24, 16)
-SCIF_FNS(SCLSR,                                0,  0, 0x28, 16)
-#else
-SCIF_FNS(SCFDR,                      0x0e, 16, 0x1C, 16)
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
-SCIF_FNS(SCSPTR,                        0,  0, 0, 0)
-#else
-SCIF_FNS(SCSPTR,                        0,  0, 0x20, 16)
-#endif
-SCIF_FNS(SCLSR,                         0,  0, 0x24, 16)
-#endif
-#endif
-#define sci_in(port, reg) sci_##reg##_in(port)
-#define sci_out(port, reg, value) sci_##reg##_out(port, value)
-
-/* H8/300 series SCI pins assignment */
-#if defined(__H8300H__) || defined(__H8300S__)
-static const struct __attribute__((packed)) {
-       int port;             /* GPIO port no */
-       unsigned short rx,tx; /* GPIO bit no */
-} h8300_sci_pins[] = {
-#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
-       {    /* SCI0 */
-               .port = H8300_GPIO_P9,
-               .rx   = H8300_GPIO_B2,
-               .tx   = H8300_GPIO_B0,
-       },
-       {    /* SCI1 */
-               .port = H8300_GPIO_P9,
-               .rx   = H8300_GPIO_B3,
-               .tx   = H8300_GPIO_B1,
-       },
-       {    /* SCI2 */
-               .port = H8300_GPIO_PB,
-               .rx   = H8300_GPIO_B7,
-               .tx   = H8300_GPIO_B6,
-       }
-#elif defined(CONFIG_H8S2678)
-       {    /* SCI0 */
-               .port = H8300_GPIO_P3,
-               .rx   = H8300_GPIO_B2,
-               .tx   = H8300_GPIO_B0,
-       },
-       {    /* SCI1 */
-               .port = H8300_GPIO_P3,
-               .rx   = H8300_GPIO_B3,
-               .tx   = H8300_GPIO_B1,
-       },
-       {    /* SCI2 */
-               .port = H8300_GPIO_P5,
-               .rx   = H8300_GPIO_B1,
-               .tx   = H8300_GPIO_B0,
-       }
-#endif
-};
-#endif
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7707) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7708) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7709)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-       if (port->mapbase == 0xfffffe80)
-               return __raw_readb(SCPDR)&0x01 ? 1 : 0; /* SCI */
-       return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750)  || \
-      defined(CONFIG_CPU_SUBTYPE_SH7751)  || \
-      defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7091)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-       if (port->mapbase == 0xffe00000)
-               return __raw_readb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */
-       return 1;
-}
-#elif defined(__H8300H__) || defined(__H8300S__)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-       int ch = (port->mapbase - SMR0) >> 3;
-       return (H8300_SCI_DR(ch) & h8300_sci_pins[ch].rx) ? 1 : 0;
-}
-#else /* default case for non-SCI processors */
-static inline int sci_rxd_in(struct uart_port *port)
-{
-       return 1;
-}
-#endif
index 385acb8..3f94ac3 100644 (file)
@@ -268,7 +268,7 @@ usbtmc_abort_bulk_in_status:
                                dev_err(dev, "usb_bulk_msg returned %d\n", rv);
                                goto exit;
                        }
-               } while ((actual = max_size) &&
+               } while ((actual == max_size) &&
                         (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
 
        if (actual == max_size) {
index c962608..26678ca 100644 (file)
@@ -123,10 +123,11 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
        }
 
        if (usb_endpoint_xfer_isoc(&ep->desc))
-               max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1) *
-                       (desc->bmAttributes + 1);
+               max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) *
+                       le16_to_cpu(ep->desc.wMaxPacketSize);
        else if (usb_endpoint_xfer_int(&ep->desc))
-               max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1);
+               max_tx = le16_to_cpu(ep->desc.wMaxPacketSize) *
+                       (desc->bMaxBurst + 1);
        else
                max_tx = 999999;
        if (le16_to_cpu(desc->wBytesPerInterval) > max_tx) {
@@ -134,10 +135,10 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
                                "config %d interface %d altsetting %d ep %d: "
                                "setting to %d\n",
                                usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int",
-                               desc->wBytesPerInterval,
+                               le16_to_cpu(desc->wBytesPerInterval),
                                cfgno, inum, asnum, ep->desc.bEndpointAddress,
                                max_tx);
-               ep->ss_ep_comp.wBytesPerInterval = max_tx;
+               ep->ss_ep_comp.wBytesPerInterval = cpu_to_le16(max_tx);
        }
 }
 
index 44b6b40..5a084b9 100644 (file)
@@ -310,7 +310,7 @@ config USB_PXA_U2O
 # musb builds in ../musb along with host support
 config USB_GADGET_MUSB_HDRC
        tristate "Inventra HDRC USB Peripheral (TI, ADI, ...)"
-       depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
+       depends on USB_MUSB_HDRC
        select USB_GADGET_DUALSPEED
        help
          This OTG-capable silicon IP is used in dual designs including
index 98cbc06..ddb118a 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/list.h>
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
+#include <linux/prefetch.h>
 #include <linux/clk.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
index 5ef8779..aef4741 100644 (file)
@@ -1079,10 +1079,12 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                        cdev->desc.bMaxPacketSize0 =
                                cdev->gadget->ep0->maxpacket;
                        if (gadget_is_superspeed(gadget)) {
-                               if (gadget->speed >= USB_SPEED_SUPER)
+                               if (gadget->speed >= USB_SPEED_SUPER) {
                                        cdev->desc.bcdUSB = cpu_to_le16(0x0300);
-                               else
+                                       cdev->desc.bMaxPacketSize0 = 9;
+                               } else {
                                        cdev->desc.bcdUSB = cpu_to_le16(0x0210);
+                               }
                        }
 
                        value = min(w_length, (u16) sizeof cdev->desc);
index 403a48b..83a266b 100644 (file)
@@ -367,6 +367,13 @@ static int hidg_setup(struct usb_function *f,
        case ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8
                  | USB_REQ_GET_DESCRIPTOR):
                switch (value >> 8) {
+               case HID_DT_HID:
+                       VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: HID\n");
+                       length = min_t(unsigned short, length,
+                                                  hidg_desc.bLength);
+                       memcpy(req->buf, &hidg_desc, length);
+                       goto respond;
+                       break;
                case HID_DT_REPORT:
                        VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: REPORT\n");
                        length = min_t(unsigned short, length,
index 24a9243..4ec888f 100644 (file)
@@ -609,107 +609,6 @@ void fusb300_rdcxf(struct fusb300 *fusb300,
        }
 }
 
-#if 0
-static void fusb300_dbg_fifo(struct fusb300_ep *ep,
-                               u8 entry, u16 length)
-{
-       u32 reg;
-       u32 i = 0;
-       u32 j = 0;
-
-       reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_GTM);
-       reg &= ~(FUSB300_GTM_TST_EP_ENTRY(0xF) |
-               FUSB300_GTM_TST_EP_NUM(0xF) | FUSB300_GTM_TST_FIFO_DEG);
-       reg |= (FUSB300_GTM_TST_EP_ENTRY(entry) |
-               FUSB300_GTM_TST_EP_NUM(ep->epnum) | FUSB300_GTM_TST_FIFO_DEG);
-       iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_GTM);
-
-       for (i = 0; i < (length >> 2); i++) {
-               if (i * 4 == 1024)
-                       break;
-               reg = ioread32(ep->fusb300->reg +
-                       FUSB300_OFFSET_BUFDBG_START + i * 4);
-               printk(KERN_DEBUG"  0x%-8x", reg);
-               j++;
-               if ((j % 4)  == 0)
-                       printk(KERN_DEBUG "\n");
-       }
-
-       if (length % 4) {
-               reg = ioread32(ep->fusb300->reg +
-                       FUSB300_OFFSET_BUFDBG_START + i * 4);
-               printk(KERN_DEBUG "  0x%x\n", reg);
-       }
-
-       if ((j % 4)  != 0)
-               printk(KERN_DEBUG "\n");
-
-       fusb300_disable_bit(ep->fusb300, FUSB300_OFFSET_GTM,
-               FUSB300_GTM_TST_FIFO_DEG);
-}
-
-static void fusb300_cmp_dbg_fifo(struct fusb300_ep *ep,
-                               u8 entry, u16 length, u8 *golden)
-{
-       u32 reg;
-       u32 i = 0;
-       u32 golden_value;
-       u8 *tmp;
-
-       tmp = golden;
-
-       printk(KERN_DEBUG "fusb300_cmp_dbg_fifo (entry %d) : start\n", entry);
-
-       reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_GTM);
-       reg &= ~(FUSB300_GTM_TST_EP_ENTRY(0xF) |
-               FUSB300_GTM_TST_EP_NUM(0xF) | FUSB300_GTM_TST_FIFO_DEG);
-       reg |= (FUSB300_GTM_TST_EP_ENTRY(entry) |
-               FUSB300_GTM_TST_EP_NUM(ep->epnum) | FUSB300_GTM_TST_FIFO_DEG);
-       iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_GTM);
-
-       for (i = 0; i < (length >> 2); i++) {
-               if (i * 4 == 1024)
-                       break;
-               golden_value = *tmp | *(tmp + 1) << 8 |
-                               *(tmp + 2) << 16 | *(tmp + 3) << 24;
-
-               reg = ioread32(ep->fusb300->reg +
-                       FUSB300_OFFSET_BUFDBG_START + i*4);
-
-               if (reg != golden_value) {
-                       printk(KERN_DEBUG "0x%x  :  ", (u32)(ep->fusb300->reg +
-                               FUSB300_OFFSET_BUFDBG_START + i*4));
-                       printk(KERN_DEBUG "    golden = 0x%x, reg = 0x%x\n",
-                               golden_value, reg);
-               }
-               tmp += 4;
-       }
-
-       switch (length % 4) {
-       case 1:
-               golden_value = *tmp;
-       case 2:
-               golden_value = *tmp | *(tmp + 1) << 8;
-       case 3:
-               golden_value = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16;
-       default:
-               break;
-
-       reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_BUFDBG_START + i*4);
-       if (reg != golden_value) {
-               printk(KERN_DEBUG "0x%x:", (u32)(ep->fusb300->reg +
-                       FUSB300_OFFSET_BUFDBG_START + i*4));
-               printk(KERN_DEBUG "  golden = 0x%x, reg = 0x%x\n",
-                       golden_value, reg);
-       }
-       }
-
-       printk(KERN_DEBUG "fusb300_cmp_dbg_fifo : end\n");
-       fusb300_disable_bit(ep->fusb300, FUSB300_OFFSET_GTM,
-               FUSB300_GTM_TST_FIFO_DEG);
-}
-#endif
-
 static void fusb300_rdfifo(struct fusb300_ep *ep,
                          struct fusb300_request *req,
                          u32 length)
index 7c7b0e1..ab98ea9 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
-#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
+#include <linux/prefetch.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
index 85c1b0d..8d31848 100644 (file)
@@ -2060,6 +2060,7 @@ static int s3c2410_udc_resume(struct platform_device *pdev)
 static const struct platform_device_id s3c_udc_ids[] = {
        { "s3c2410-usbgadget", },
        { "s3c2440-usbgadget", },
+       { }
 };
 MODULE_DEVICE_TABLE(platform, s3c_udc_ids);
 
index 5e807f0..52f8f9e 100644 (file)
@@ -124,24 +124,12 @@ uvc_v4l2_open(struct file *file)
        struct video_device *vdev = video_devdata(file);
        struct uvc_device *uvc = video_get_drvdata(vdev);
        struct uvc_file_handle *handle;
-       int ret;
 
        handle = kzalloc(sizeof(*handle), GFP_KERNEL);
        if (handle == NULL)
                return -ENOMEM;
 
-       ret = v4l2_fh_init(&handle->vfh, vdev);
-       if (ret < 0)
-               goto error;
-
-       ret = v4l2_event_init(&handle->vfh);
-       if (ret < 0)
-               goto error;
-
-       ret = v4l2_event_alloc(&handle->vfh, 8);
-       if (ret < 0)
-               goto error;
-
+       v4l2_fh_init(&handle->vfh, vdev);
        v4l2_fh_add(&handle->vfh);
 
        handle->device = &uvc->video;
@@ -149,10 +137,6 @@ uvc_v4l2_open(struct file *file)
 
        uvc_function_connect(uvc);
        return 0;
-
-error:
-       v4l2_fh_exit(&handle->vfh);
-       return ret;
 }
 
 static int
@@ -314,7 +298,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST)
                        return -EINVAL;
 
-               return v4l2_event_subscribe(&handle->vfh, arg);
+               return v4l2_event_subscribe(&handle->vfh, arg, 2);
        }
 
        case VIDIOC_UNSUBSCRIBE_EVENT:
@@ -354,7 +338,7 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)
        struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
        unsigned int mask = 0;
 
-       poll_wait(file, &handle->vfh.events->wait, wait);
+       poll_wait(file, &handle->vfh.wait, wait);
        if (v4l2_event_pending(&handle->vfh))
                mask |= POLLPRI;
 
index bf2c8f6..e051b30 100644 (file)
@@ -1046,7 +1046,19 @@ static int ehci_hub_control (
                        if (!selector || selector > 5)
                                goto error;
                        ehci_quiesce(ehci);
+
+                       /* Put all enabled ports into suspend */
+                       while (ports--) {
+                               u32 __iomem *sreg =
+                                               &ehci->regs->port_status[ports];
+
+                               temp = ehci_readl(ehci, sreg) & ~PORT_RWC_BITS;
+                               if (temp & PORT_PE)
+                                       ehci_writel(ehci, temp | PORT_SUSPEND,
+                                                       sreg);
+                       }
                        ehci_halt(ehci);
+                       temp = ehci_readl(ehci, status_reg);
                        temp |= selector << 16;
                        ehci_writel(ehci, temp, status_reg);
                        break;
index 0c058be..555a73c 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/usb/ulpi.h>
 #include <linux/slab.h>
 
+#include <mach/hardware.h>
 #include <mach/mxc_ehci.h>
 
 #include <asm/mach-types.h>
index 55a57c2..4524032 100644 (file)
@@ -98,6 +98,18 @@ static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port)
        }
 }
 
+static void disable_put_regulator(
+               struct ehci_hcd_omap_platform_data *pdata)
+{
+       int i;
+
+       for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
+               if (pdata->regulator[i]) {
+                       regulator_disable(pdata->regulator[i]);
+                       regulator_put(pdata->regulator[i]);
+               }
+       }
+}
 
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
@@ -231,9 +243,11 @@ err_add_hcd:
        omap_usbhs_disable(dev);
 
 err_enable:
+       disable_put_regulator(pdata);
        usb_put_hcd(hcd);
 
 err_io:
+       iounmap(regs);
        return ret;
 }
 
@@ -253,6 +267,8 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
 
        usb_remove_hcd(hcd);
        omap_usbhs_disable(dev);
+       disable_put_regulator(dev->platform_data);
+       iounmap(hcd->regs);
        usb_put_hcd(hcd);
        return 0;
 }
index 55d3d58..840beda 100644 (file)
@@ -1583,6 +1583,9 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
        int retval = 0;
 
        spin_lock_irqsave(&priv->lock, spinflags);
+       retval = usb_hcd_check_unlink_urb(hcd, urb, status);
+       if (retval)
+               goto out;
 
        qh = urb->ep->hcpriv;
        if (!qh) {
index a9d3159..629a968 100644 (file)
@@ -535,7 +535,7 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
        iounmap(base);
 }
 
-static const struct dmi_system_id __initconst ehci_dmi_nohandoff_table[] = {
+static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
        {
                /*  Pegatron Lucid (ExoPC) */
                .matches = {
@@ -817,7 +817,7 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
 
        /* If the BIOS owns the HC, signal that the OS wants it, and wait */
        if (val & XHCI_HC_BIOS_OWNED) {
-               writel(val & XHCI_HC_OS_OWNED, base + ext_cap_offset);
+               writel(val | XHCI_HC_OS_OWNED, base + ext_cap_offset);
 
                /* Wait for 5 seconds with 10 microsecond polling interval */
                timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED,
index 763f484..1c4432d 100644 (file)
@@ -345,7 +345,8 @@ static void xhci_event_ring_work(unsigned long arg)
        spin_lock_irqsave(&xhci->lock, flags);
        temp = xhci_readl(xhci, &xhci->op_regs->status);
        xhci_dbg(xhci, "op reg status = 0x%x\n", temp);
-       if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING)) {
+       if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) ||
+                       (xhci->xhc_state & XHCI_STATE_HALTED)) {
                xhci_dbg(xhci, "HW died, polling stopped.\n");
                spin_unlock_irqrestore(&xhci->lock, flags);
                return;
@@ -939,8 +940,11 @@ static int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
                return 0;
        }
 
+       xhci = hcd_to_xhci(hcd);
+       if (xhci->xhc_state & XHCI_STATE_HALTED)
+               return -ENODEV;
+
        if (check_virt_dev) {
-               xhci = hcd_to_xhci(hcd);
                if (!udev->slot_id || !xhci->devs
                        || !xhci->devs[udev->slot_id]) {
                        printk(KERN_DEBUG "xHCI %s called with unaddressed "
@@ -1242,7 +1246,8 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                xhci_urb_free_priv(xhci, urb_priv);
                return ret;
        }
-       if (xhci->xhc_state & XHCI_STATE_DYING) {
+       if ((xhci->xhc_state & XHCI_STATE_DYING) ||
+                       (xhci->xhc_state & XHCI_STATE_HALTED)) {
                xhci_dbg(xhci, "Ep 0x%x: URB %p to be canceled on "
                                "non-responsive xHCI host.\n",
                                urb->ep->desc.bEndpointAddress, urb);
@@ -2665,7 +2670,10 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
        int i, ret;
 
        ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
-       if (ret <= 0)
+       /* If the host is halted due to driver unload, we still need to free the
+        * device.
+        */
+       if (ret <= 0 && ret != -ENODEV)
                return;
 
        virt_dev = xhci->devs[udev->slot_id];
@@ -2679,7 +2687,8 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
        spin_lock_irqsave(&xhci->lock, flags);
        /* Don't disable the slot if the host controller is dead. */
        state = xhci_readl(xhci, &xhci->op_regs->status);
-       if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING)) {
+       if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) ||
+                       (xhci->xhc_state & XHCI_STATE_HALTED)) {
                xhci_free_virt_device(xhci, udev->slot_id);
                spin_unlock_irqrestore(&xhci->lock, flags);
                return;
index 6192b45..fc34b8b 100644 (file)
@@ -3,9 +3,6 @@
 # for silicon based on Mentor Graphics INVENTRA designs
 #
 
-comment "Enable Host or Gadget support to see Inventra options"
-       depends on !USB && USB_GADGET=n
-
 # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
 config USB_MUSB_HDRC
        depends on USB && USB_GADGET
index b67a062..8c41a2e 100644 (file)
@@ -1698,6 +1698,8 @@ static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
 
        is_on = !!is_on;
 
+       pm_runtime_get_sync(musb->controller);
+
        /* NOTE: this assumes we are sensing vbus; we'd rather
         * not pullup unless the B-session is active.
         */
@@ -1707,6 +1709,9 @@ static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
                musb_pullup(musb, is_on);
        }
        spin_unlock_irqrestore(&musb->lock, flags);
+
+       pm_runtime_put(musb->controller);
+
        return 0;
 }
 
index c784e6c..07c8a73 100644 (file)
@@ -89,7 +89,7 @@ static inline int tusb_omap_use_shared_dmareq(struct tusb_omap_dma_ch *chdat)
        u32             reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
 
        if (reg != 0) {
-               dev_dbg(musb->controller, "ep%i dmareq0 is busy for ep%i\n",
+               dev_dbg(chdat->musb->controller, "ep%i dmareq0 is busy for ep%i\n",
                        chdat->epnum, reg & 0xf);
                return -EAGAIN;
        }
index ba79dbf..cb2d451 100644 (file)
@@ -14,6 +14,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
+#include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -76,7 +77,7 @@ struct usbhsg_recip_handle {
                struct usbhsg_gpriv, mod)
 
 #define __usbhsg_for_each_uep(start, pos, g, i)        \
-       for (i = start, pos = (g)->uep;         \
+       for (i = start, pos = (g)->uep + i;     \
             i < (g)->uep_size;                 \
             i++, pos = (g)->uep + i)
 
index 2e06b90..78a2cf9 100644 (file)
@@ -151,6 +151,7 @@ static struct ftdi_sio_quirk ftdi_stmclite_quirk = {
  * /sys/bus/usb/ftdi_sio/new_id, then send patch/report!
  */
 static struct usb_device_id id_table_combined [] = {
+       { USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
@@ -1171,7 +1172,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
        case FT2232H: /* FT2232H chip */
        case FT4232H: /* FT4232H chip */
        case FT232H:  /* FT232H chip */
-               if ((baud <= 12000000) & (baud >= 1200)) {
+               if ((baud <= 12000000) && (baud >= 1200)) {
                        div_value = ftdi_2232h_baud_to_divisor(baud);
                } else if (baud < 1200) {
                        div_value = ftdi_232bm_baud_to_divisor(baud);
@@ -1205,7 +1206,10 @@ static int change_speed(struct tty_struct *tty, struct usb_serial_port *port)
        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 */
+       if ((priv->chip_type == FT2232C) || (priv->chip_type == FT2232H) ||
+               (priv->chip_type == FT4232H) || (priv->chip_type == FT232H)) {
+               /* Probably the BM type needs the MSB of the encoded fractional
+                * divider also moved like for the chips above. Any infos? */
                urb_index = (__u16)((urb_index << 8) | priv->interface);
        }
 
index 19156d1..bf5227a 100644 (file)
 /* USB-Nano-485*/
 #define FTDI_CTI_NANO_PID      0xF60B
 
-
+/*
+ * ZeitControl cardsystems GmbH rfid-readers http://zeitconrol.de
+ */
+/* TagTracer MIFARE*/
+#define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID   0xF7C0
index 60b25d8..8156561 100644 (file)
@@ -148,6 +148,10 @@ static void option_instat_callback(struct urb *urb);
 #define HUAWEI_PRODUCT_K4505                   0x1464
 #define HUAWEI_PRODUCT_K3765                   0x1465
 #define HUAWEI_PRODUCT_E14AC                   0x14AC
+#define HUAWEI_PRODUCT_K3770                   0x14C9
+#define HUAWEI_PRODUCT_K3771                   0x14CA
+#define HUAWEI_PRODUCT_K4510                   0x14CB
+#define HUAWEI_PRODUCT_K4511                   0x14CC
 #define HUAWEI_PRODUCT_ETS1220                 0x1803
 #define HUAWEI_PRODUCT_E353                    0x1506
 
@@ -547,6 +551,14 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x32) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x31) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x32) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },
index 54a9dab..aeccc7f 100644 (file)
@@ -45,6 +45,7 @@ static const struct usb_device_id id_table[] = {
        {USB_DEVICE(0x05c6, 0x9203)},   /* Generic Gobi Modem device */
        {USB_DEVICE(0x05c6, 0x9222)},   /* Generic Gobi Modem device */
        {USB_DEVICE(0x05c6, 0x9008)},   /* Generic Gobi QDL device */
+       {USB_DEVICE(0x05c6, 0x9009)},   /* Generic Gobi Modem device */
        {USB_DEVICE(0x05c6, 0x9201)},   /* Generic Gobi QDL device */
        {USB_DEVICE(0x05c6, 0x9221)},   /* Generic Gobi QDL device */
        {USB_DEVICE(0x05c6, 0x9231)},   /* Generic Gobi QDL device */
@@ -78,6 +79,7 @@ static const struct usb_device_id id_table[] = {
        {USB_DEVICE(0x1199, 0x9008)},   /* Sierra Wireless Gobi 2000 Modem device (VT773) */
        {USB_DEVICE(0x1199, 0x9009)},   /* Sierra Wireless Gobi 2000 Modem device (VT773) */
        {USB_DEVICE(0x1199, 0x900a)},   /* Sierra Wireless Gobi 2000 Modem device (VT773) */
+       {USB_DEVICE(0x1199, 0x9011)},   /* Sierra Wireless Gobi 2000 Modem device (MC8305) */
        {USB_DEVICE(0x16d8, 0x8001)},   /* CMDTech Gobi 2000 QDL device (VU922) */
        {USB_DEVICE(0x16d8, 0x8002)},   /* CMDTech Gobi 2000 Modem device (VU922) */
        {USB_DEVICE(0x05c6, 0x9204)},   /* Gobi 2000 QDL device */
index ccff348..3041a97 100644 (file)
@@ -1988,6 +1988,16 @@ UNUSUAL_DEV(  0x4146, 0xba01, 0x0100, 0x0100,
                "Micro Mini 1GB",
                USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
 
+/*
+ * Nick Bowler <nbowler@elliptictech.com>
+ * SCSI stack spams (otherwise harmless) error messages.
+ */
+UNUSUAL_DEV(  0xc251, 0x4003, 0x0100, 0x0100,
+               "Keil Software, Inc.",
+               "V2M MotherBoard",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NOT_LOCKABLE),
+
 /* Reported by Andrew Simmons <andrew.simmons@gmail.com> */
 UNUSUAL_DEV(  0xed06, 0x4500, 0x0001, 0x0001,
                "DataStor",
index 1e54b8b..278aeaa 100644 (file)
@@ -335,6 +335,13 @@ config BACKLIGHT_PCF50633
          If you have a backlight driven by a NXP PCF50633 MFD, say Y here to
          enable its driver.
 
+config BACKLIGHT_AAT2870
+       tristate "AnalogicTech AAT2870 Backlight"
+       depends on BACKLIGHT_CLASS_DEVICE && MFD_AAT2870_CORE
+       help
+         If you have a AnalogicTech AAT2870 say Y to enable the
+         backlight driver.
+
 endif # BACKLIGHT_CLASS_DEVICE
 
 endif # BACKLIGHT_LCD_SUPPORT
index bf1dd92..fdd1fc4 100644 (file)
@@ -38,4 +38,5 @@ obj-$(CONFIG_BACKLIGHT_ADP8860)       += adp8860_bl.o
 obj-$(CONFIG_BACKLIGHT_ADP8870)        += adp8870_bl.o
 obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)       += pcf50633-backlight.o
+obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
 
diff --git a/drivers/video/backlight/aat2870_bl.c b/drivers/video/backlight/aat2870_bl.c
new file mode 100644 (file)
index 0000000..331f1ef
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * linux/drivers/video/backlight/aat2870_bl.c
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ * Author: Jin Park <jinyoungp@nvidia.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/mfd/aat2870.h>
+
+struct aat2870_bl_driver_data {
+       struct platform_device *pdev;
+       struct backlight_device *bd;
+
+       int channels;
+       int max_current;
+       int brightness; /* current brightness */
+};
+
+static inline int aat2870_brightness(struct aat2870_bl_driver_data *aat2870_bl,
+                                    int brightness)
+{
+       struct backlight_device *bd = aat2870_bl->bd;
+       int val;
+
+       val = brightness * (aat2870_bl->max_current - 1);
+       val /= bd->props.max_brightness;
+
+       return val;
+}
+
+static inline int aat2870_bl_enable(struct aat2870_bl_driver_data *aat2870_bl)
+{
+       struct aat2870_data *aat2870
+                       = dev_get_drvdata(aat2870_bl->pdev->dev.parent);
+
+       return aat2870->write(aat2870, AAT2870_BL_CH_EN,
+                             (u8)aat2870_bl->channels);
+}
+
+static inline int aat2870_bl_disable(struct aat2870_bl_driver_data *aat2870_bl)
+{
+       struct aat2870_data *aat2870
+                       = dev_get_drvdata(aat2870_bl->pdev->dev.parent);
+
+       return aat2870->write(aat2870, AAT2870_BL_CH_EN, 0x0);
+}
+
+static int aat2870_bl_get_brightness(struct backlight_device *bd)
+{
+       return bd->props.brightness;
+}
+
+static int aat2870_bl_update_status(struct backlight_device *bd)
+{
+       struct aat2870_bl_driver_data *aat2870_bl = dev_get_drvdata(&bd->dev);
+       struct aat2870_data *aat2870 =
+                       dev_get_drvdata(aat2870_bl->pdev->dev.parent);
+       int brightness = bd->props.brightness;
+       int ret;
+
+       if ((brightness < 0) || (bd->props.max_brightness < brightness)) {
+               dev_err(&bd->dev, "invalid brightness, %d\n", brightness);
+               return -EINVAL;
+       }
+
+       dev_dbg(&bd->dev, "brightness=%d, power=%d, state=%d\n",
+                bd->props.brightness, bd->props.power, bd->props.state);
+
+       if ((bd->props.power != FB_BLANK_UNBLANK) ||
+                       (bd->props.state & BL_CORE_FBBLANK) ||
+                       (bd->props.state & BL_CORE_SUSPENDED))
+               brightness = 0;
+
+       ret = aat2870->write(aat2870, AAT2870_BLM,
+                            (u8)aat2870_brightness(aat2870_bl, brightness));
+       if (ret < 0)
+               return ret;
+
+       if (brightness == 0) {
+               ret = aat2870_bl_disable(aat2870_bl);
+               if (ret < 0)
+                       return ret;
+       } else if (aat2870_bl->brightness == 0) {
+               ret = aat2870_bl_enable(aat2870_bl);
+               if (ret < 0)
+                       return ret;
+       }
+
+       aat2870_bl->brightness = brightness;
+
+       return 0;
+}
+
+static int aat2870_bl_check_fb(struct backlight_device *bd, struct fb_info *fi)
+{
+       return 1;
+}
+
+static const struct backlight_ops aat2870_bl_ops = {
+       .options = BL_CORE_SUSPENDRESUME,
+       .get_brightness = aat2870_bl_get_brightness,
+       .update_status = aat2870_bl_update_status,
+       .check_fb = aat2870_bl_check_fb,
+};
+
+static int aat2870_bl_probe(struct platform_device *pdev)
+{
+       struct aat2870_bl_platform_data *pdata = pdev->dev.platform_data;
+       struct aat2870_bl_driver_data *aat2870_bl;
+       struct backlight_device *bd;
+       struct backlight_properties props;
+       int ret = 0;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "No platform data\n");
+               ret = -ENXIO;
+               goto out;
+       }
+
+       if (pdev->id != AAT2870_ID_BL) {
+               dev_err(&pdev->dev, "Invalid device ID, %d\n", pdev->id);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       aat2870_bl = kzalloc(sizeof(struct aat2870_bl_driver_data), GFP_KERNEL);
+       if (!aat2870_bl) {
+               dev_err(&pdev->dev,
+                       "Failed to allocate memory for aat2870 backlight\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       memset(&props, 0, sizeof(struct backlight_properties));
+
+       props.type = BACKLIGHT_RAW;
+       bd = backlight_device_register("aat2870-backlight", &pdev->dev,
+                                      aat2870_bl, &aat2870_bl_ops, &props);
+       if (IS_ERR(bd)) {
+               dev_err(&pdev->dev,
+                       "Failed allocate memory for backlight device\n");
+               ret = PTR_ERR(bd);
+               goto out_kfree;
+       }
+
+       aat2870_bl->pdev = pdev;
+       platform_set_drvdata(pdev, aat2870_bl);
+
+       aat2870_bl->bd = bd;
+
+       if (pdata->channels > 0)
+               aat2870_bl->channels = pdata->channels;
+       else
+               aat2870_bl->channels = AAT2870_BL_CH_ALL;
+
+       if (pdata->max_current > 0)
+               aat2870_bl->max_current = pdata->max_current;
+       else
+               aat2870_bl->max_current = AAT2870_CURRENT_27_9;
+
+       if (pdata->max_brightness > 0)
+               bd->props.max_brightness = pdata->max_brightness;
+       else
+               bd->props.max_brightness = 255;
+
+       aat2870_bl->brightness = 0;
+       bd->props.power = FB_BLANK_UNBLANK;
+       bd->props.brightness = bd->props.max_brightness;
+
+       ret = aat2870_bl_update_status(bd);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to initialize\n");
+               goto out_bl_dev_unregister;
+       }
+
+       return 0;
+
+out_bl_dev_unregister:
+       backlight_device_unregister(bd);
+out_kfree:
+       kfree(aat2870_bl);
+out:
+       return ret;
+}
+
+static int aat2870_bl_remove(struct platform_device *pdev)
+{
+       struct aat2870_bl_driver_data *aat2870_bl = platform_get_drvdata(pdev);
+       struct backlight_device *bd = aat2870_bl->bd;
+
+       bd->props.power = FB_BLANK_POWERDOWN;
+       bd->props.brightness = 0;
+       backlight_update_status(bd);
+
+       backlight_device_unregister(bd);
+       kfree(aat2870_bl);
+
+       return 0;
+}
+
+static struct platform_driver aat2870_bl_driver = {
+       .driver = {
+               .name   = "aat2870-backlight",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = aat2870_bl_probe,
+       .remove         = aat2870_bl_remove,
+};
+
+static int __init aat2870_bl_init(void)
+{
+       return platform_driver_register(&aat2870_bl_driver);
+}
+subsys_initcall(aat2870_bl_init);
+
+static void __exit aat2870_bl_exit(void)
+{
+       platform_driver_unregister(&aat2870_bl_driver);
+}
+module_exit(aat2870_bl_exit);
+
+MODULE_DESCRIPTION("AnalogicTech AAT2870 Backlight");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");
index fdd5d4a..4e888ac 100644 (file)
@@ -504,14 +504,18 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
                return 0;
 
        r = omapdss_dsi_display_enable(dssdev);
-       if (r)
-               goto err;
+       if (r) {
+               dev_err(&dssdev->dev, "failed to enable DSI\n");
+               goto err1;
+       }
 
        omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
 
        r = _taal_enable_te(dssdev, true);
-       if (r)
-               goto err;
+       if (r) {
+               dev_err(&dssdev->dev, "failed to re-enable TE");
+               goto err2;
+       }
 
        enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
 
@@ -521,13 +525,15 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
 
        return 0;
 
-err:
-       dev_err(&dssdev->dev, "exit ULPS failed");
-       r = taal_panel_reset(dssdev);
-
-       enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
-       td->ulps_enabled = false;
+err2:
+       dev_err(&dssdev->dev, "failed to exit ULPS");
 
+       r = taal_panel_reset(dssdev);
+       if (!r) {
+               enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+               td->ulps_enabled = false;
+       }
+err1:
        taal_queue_ulps_work(dssdev);
 
        return r;
@@ -1241,11 +1247,8 @@ static void taal_power_off(struct omap_dss_device *dssdev)
        int r;
 
        r = taal_dcs_write_0(td, DCS_DISPLAY_OFF);
-       if (!r) {
+       if (!r)
                r = taal_sleep_in(td);
-               /* HACK: wait a bit so that the message goes through */
-               msleep(10);
-       }
 
        if (r) {
                dev_err(&dssdev->dev,
@@ -1317,8 +1320,11 @@ static void taal_disable(struct omap_dss_device *dssdev)
        dsi_bus_lock(dssdev);
 
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-               taal_wake_up(dssdev);
-               taal_power_off(dssdev);
+               int r;
+
+               r = taal_wake_up(dssdev);
+               if (!r)
+                       taal_power_off(dssdev);
        }
 
        dsi_bus_unlock(dssdev);
@@ -1897,20 +1903,6 @@ err:
        mutex_unlock(&td->lock);
 }
 
-static int taal_set_update_mode(struct omap_dss_device *dssdev,
-               enum omap_dss_update_mode mode)
-{
-       if (mode != OMAP_DSS_UPDATE_MANUAL)
-               return -EINVAL;
-       return 0;
-}
-
-static enum omap_dss_update_mode taal_get_update_mode(
-               struct omap_dss_device *dssdev)
-{
-       return OMAP_DSS_UPDATE_MANUAL;
-}
-
 static struct omap_dss_driver taal_driver = {
        .probe          = taal_probe,
        .remove         = __exit_p(taal_remove),
@@ -1920,9 +1912,6 @@ static struct omap_dss_driver taal_driver = {
        .suspend        = taal_suspend,
        .resume         = taal_resume,
 
-       .set_update_mode = taal_set_update_mode,
-       .get_update_mode = taal_get_update_mode,
-
        .update         = taal_update,
        .sync           = taal_sync,
 
index 6b3e2da..0d12524 100644 (file)
@@ -117,18 +117,6 @@ config OMAP2_DSS_MIN_FCK_PER_PCK
          Max FCK is 173MHz, so this doesn't work if your PCK
          is very high.
 
-config OMAP2_DSS_SLEEP_BEFORE_RESET
-       bool "Sleep 50ms before DSS reset"
-       default y
-       help
-         For some unknown reason we may get SYNC_LOST errors from the display
-         subsystem at initialization time if we don't sleep before resetting
-         the DSS. See the source (dss.c) for more comments.
-
-         However, 50ms is quite long time to sleep, and with some
-         configurations the SYNC_LOST may never happen, so the sleep can
-         be disabled here.
-
 config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
        bool "Sleep 20ms after VENC reset"
        default y
index 3da4267..76821fe 100644 (file)
@@ -183,8 +183,11 @@ static int omap_dss_probe(struct platform_device *pdev)
                goto err_dss;
        }
 
-       /* keep clocks enabled to prevent context saves/restores during init */
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       r = dispc_init_platform_driver();
+       if (r) {
+               DSSERR("Failed to initialize dispc platform driver\n");
+               goto err_dispc;
+       }
 
        r = rfbi_init_platform_driver();
        if (r) {
@@ -192,12 +195,6 @@ static int omap_dss_probe(struct platform_device *pdev)
                goto err_rfbi;
        }
 
-       r = dispc_init_platform_driver();
-       if (r) {
-               DSSERR("Failed to initialize dispc platform driver\n");
-               goto err_dispc;
-       }
-
        r = venc_init_platform_driver();
        if (r) {
                DSSERR("Failed to initialize venc platform driver\n");
@@ -238,8 +235,6 @@ static int omap_dss_probe(struct platform_device *pdev)
                        pdata->default_device = dssdev;
        }
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
-
        return 0;
 
 err_register:
@@ -268,11 +263,11 @@ static int omap_dss_remove(struct platform_device *pdev)
 
        dss_uninitialize_debugfs();
 
+       hdmi_uninit_platform_driver();
+       dsi_uninit_platform_driver();
        venc_uninit_platform_driver();
-       dispc_uninit_platform_driver();
        rfbi_uninit_platform_driver();
-       dsi_uninit_platform_driver();
-       hdmi_uninit_platform_driver();
+       dispc_uninit_platform_driver();
        dss_uninit_platform_driver();
 
        dss_uninit_overlays(pdev);
index 7a9a2e7..0f3961a 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/workqueue.h>
 #include <linux/hardirq.h>
 #include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 #include <plat/sram.h>
 #include <plat/clock.h>
@@ -77,6 +79,12 @@ struct dispc_v_coef {
        s8 vc00;
 };
 
+enum omap_burst_size {
+       BURST_SIZE_X2 = 0,
+       BURST_SIZE_X4 = 1,
+       BURST_SIZE_X8 = 2,
+};
+
 #define REG_GET(idx, start, end) \
        FLD_GET(dispc_read_reg(idx), start, end)
 
@@ -92,7 +100,11 @@ struct dispc_irq_stats {
 static struct {
        struct platform_device *pdev;
        void __iomem    *base;
+
+       int             ctx_loss_cnt;
+
        int irq;
+       struct clk *dss_clk;
 
        u32     fifo_size[3];
 
@@ -102,6 +114,7 @@ static struct {
        u32 error_irqs;
        struct work_struct error_work;
 
+       bool            ctx_valid;
        u32             ctx[DISPC_SZ_REGS / sizeof(u32)];
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -134,18 +147,34 @@ static inline u32 dispc_read_reg(const u16 idx)
        return __raw_readl(dispc.base + idx);
 }
 
+static int dispc_get_ctx_loss_count(void)
+{
+       struct device *dev = &dispc.pdev->dev;
+       struct omap_display_platform_data *pdata = dev->platform_data;
+       struct omap_dss_board_info *board_data = pdata->board_data;
+       int cnt;
+
+       if (!board_data->get_context_loss_count)
+               return -ENOENT;
+
+       cnt = board_data->get_context_loss_count(dev);
+
+       WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
+
+       return cnt;
+}
+
 #define SR(reg) \
        dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
 #define RR(reg) \
        dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
 
-void dispc_save_context(void)
+static void dispc_save_context(void)
 {
        int i;
-       if (cpu_is_omap24xx())
-               return;
 
-       SR(SYSCONFIG);
+       DSSDBG("dispc_save_context\n");
+
        SR(IRQENABLE);
        SR(CONTROL);
        SR(CONFIG);
@@ -158,7 +187,8 @@ void dispc_save_context(void)
        SR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
        SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
        SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
-       SR(GLOBAL_ALPHA);
+       if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+               SR(GLOBAL_ALPHA);
        SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
        SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
        if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -188,20 +218,25 @@ void dispc_save_context(void)
        SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
        SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 
-       SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-       SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-       SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+       if (dss_has_feature(FEAT_CPR)) {
+               SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+               SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+               SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+       }
        if (dss_has_feature(FEAT_MGR_LCD2)) {
-               SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
-               SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-               SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+               if (dss_has_feature(FEAT_CPR)) {
+                       SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+                       SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+                       SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+               }
 
                SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
                SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
                SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
        }
 
-       SR(OVL_PRELOAD(OMAP_DSS_GFX));
+       if (dss_has_feature(FEAT_PRELOAD))
+               SR(OVL_PRELOAD(OMAP_DSS_GFX));
 
        /* VID1 */
        SR(OVL_BA0(OMAP_DSS_VIDEO1));
@@ -226,8 +261,10 @@ void dispc_save_context(void)
        for (i = 0; i < 5; i++)
                SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
 
-       for (i = 0; i < 8; i++)
-               SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+       if (dss_has_feature(FEAT_FIR_COEF_V)) {
+               for (i = 0; i < 8; i++)
+                       SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+       }
 
        if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
                SR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -248,7 +285,8 @@ void dispc_save_context(void)
        if (dss_has_feature(FEAT_ATTR2))
                SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
 
-       SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
+       if (dss_has_feature(FEAT_PRELOAD))
+               SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
 
        /* VID2 */
        SR(OVL_BA0(OMAP_DSS_VIDEO2));
@@ -273,8 +311,10 @@ void dispc_save_context(void)
        for (i = 0; i < 5; i++)
                SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
 
-       for (i = 0; i < 8; i++)
-               SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+       if (dss_has_feature(FEAT_FIR_COEF_V)) {
+               for (i = 0; i < 8; i++)
+                       SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+       }
 
        if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
                SR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -295,16 +335,35 @@ void dispc_save_context(void)
        if (dss_has_feature(FEAT_ATTR2))
                SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 
-       SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
+       if (dss_has_feature(FEAT_PRELOAD))
+               SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
 
        if (dss_has_feature(FEAT_CORE_CLK_DIV))
                SR(DIVISOR);
+
+       dispc.ctx_loss_cnt = dispc_get_ctx_loss_count();
+       dispc.ctx_valid = true;
+
+       DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
 }
 
-void dispc_restore_context(void)
+static void dispc_restore_context(void)
 {
-       int i;
-       RR(SYSCONFIG);
+       int i, ctx;
+
+       DSSDBG("dispc_restore_context\n");
+
+       if (!dispc.ctx_valid)
+               return;
+
+       ctx = dispc_get_ctx_loss_count();
+
+       if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
+               return;
+
+       DSSDBG("ctx_loss_count: saved %d, current %d\n",
+                       dispc.ctx_loss_cnt, ctx);
+
        /*RR(IRQENABLE);*/
        /*RR(CONTROL);*/
        RR(CONFIG);
@@ -317,7 +376,8 @@ void dispc_restore_context(void)
        RR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
        RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
        RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
-       RR(GLOBAL_ALPHA);
+       if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+               RR(GLOBAL_ALPHA);
        RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
        RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
        if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -347,20 +407,25 @@ void dispc_restore_context(void)
        RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
        RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 
-       RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-       RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-       RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+       if (dss_has_feature(FEAT_CPR)) {
+               RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+               RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+               RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+       }
        if (dss_has_feature(FEAT_MGR_LCD2)) {
                RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
                RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
                RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
 
-               RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
-               RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-               RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+               if (dss_has_feature(FEAT_CPR)) {
+                       RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+                       RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+                       RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+               }
        }
 
-       RR(OVL_PRELOAD(OMAP_DSS_GFX));
+       if (dss_has_feature(FEAT_PRELOAD))
+               RR(OVL_PRELOAD(OMAP_DSS_GFX));
 
        /* VID1 */
        RR(OVL_BA0(OMAP_DSS_VIDEO1));
@@ -385,8 +450,10 @@ void dispc_restore_context(void)
        for (i = 0; i < 5; i++)
                RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
 
-       for (i = 0; i < 8; i++)
-               RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+       if (dss_has_feature(FEAT_FIR_COEF_V)) {
+               for (i = 0; i < 8; i++)
+                       RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+       }
 
        if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
                RR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -407,7 +474,8 @@ void dispc_restore_context(void)
        if (dss_has_feature(FEAT_ATTR2))
                RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
 
-       RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
+       if (dss_has_feature(FEAT_PRELOAD))
+               RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
 
        /* VID2 */
        RR(OVL_BA0(OMAP_DSS_VIDEO2));
@@ -432,8 +500,10 @@ void dispc_restore_context(void)
        for (i = 0; i < 5; i++)
                RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
 
-       for (i = 0; i < 8; i++)
-               RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+       if (dss_has_feature(FEAT_FIR_COEF_V)) {
+               for (i = 0; i < 8; i++)
+                       RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+       }
 
        if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
                RR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -454,7 +524,8 @@ void dispc_restore_context(void)
        if (dss_has_feature(FEAT_ATTR2))
                RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 
-       RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
+       if (dss_has_feature(FEAT_PRELOAD))
+               RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
 
        if (dss_has_feature(FEAT_CORE_CLK_DIV))
                RR(DIVISOR);
@@ -471,19 +542,35 @@ void dispc_restore_context(void)
         * the context is fully restored
         */
        RR(IRQENABLE);
+
+       DSSDBG("context restored\n");
 }
 
 #undef SR
 #undef RR
 
-static inline void enable_clocks(bool enable)
+int dispc_runtime_get(void)
 {
-       if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-       else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       int r;
+
+       DSSDBG("dispc_runtime_get\n");
+
+       r = pm_runtime_get_sync(&dispc.pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
 }
 
+void dispc_runtime_put(void)
+{
+       int r;
+
+       DSSDBG("dispc_runtime_put\n");
+
+       r = pm_runtime_put(&dispc.pdev->dev);
+       WARN_ON(r < 0);
+}
+
+
 bool dispc_go_busy(enum omap_channel channel)
 {
        int bit;
@@ -505,8 +592,6 @@ void dispc_go(enum omap_channel channel)
        int bit;
        bool enable_bit, go_bit;
 
-       enable_clocks(1);
-
        if (channel == OMAP_DSS_CHANNEL_LCD ||
                        channel == OMAP_DSS_CHANNEL_LCD2)
                bit = 0; /* LCDENABLE */
@@ -520,7 +605,7 @@ void dispc_go(enum omap_channel channel)
                enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
 
        if (!enable_bit)
-               goto end;
+               return;
 
        if (channel == OMAP_DSS_CHANNEL_LCD ||
                        channel == OMAP_DSS_CHANNEL_LCD2)
@@ -535,7 +620,7 @@ void dispc_go(enum omap_channel channel)
 
        if (go_bit) {
                DSSERR("GO bit not down for channel %d\n", channel);
-               goto end;
+               return;
        }
 
        DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" :
@@ -545,8 +630,6 @@ void dispc_go(enum omap_channel channel)
                REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit);
        else
                REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
-end:
-       enable_clocks(0);
 }
 
 static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
@@ -920,7 +1003,7 @@ static void _dispc_set_color_mode(enum omap_plane plane,
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
 }
 
-static void _dispc_set_channel_out(enum omap_plane plane,
+void dispc_set_channel_out(enum omap_plane plane,
                enum omap_channel channel)
 {
        int shift;
@@ -967,13 +1050,10 @@ static void _dispc_set_channel_out(enum omap_plane plane,
        dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
 }
 
-void dispc_set_burst_size(enum omap_plane plane,
+static void dispc_set_burst_size(enum omap_plane plane,
                enum omap_burst_size burst_size)
 {
        int shift;
-       u32 val;
-
-       enable_clocks(1);
 
        switch (plane) {
        case OMAP_DSS_GFX:
@@ -988,11 +1068,24 @@ void dispc_set_burst_size(enum omap_plane plane,
                return;
        }
 
-       val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
-       val = FLD_MOD(val, burst_size, shift+1, shift);
-       dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
+       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);
+}
 
-       enable_clocks(0);
+static void dispc_configure_burst_sizes(void)
+{
+       int i;
+       const int burst_size = BURST_SIZE_X8;
+
+       /* Configure burst size always to maximum size */
+       for (i = 0; i < omap_dss_get_num_overlays(); ++i)
+               dispc_set_burst_size(i, burst_size);
+}
+
+u32 dispc_get_burst_size(enum omap_plane plane)
+{
+       unsigned unit = dss_feat_get_burst_size_unit();
+       /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
+       return unit * 8;
 }
 
 void dispc_enable_gamma_table(bool enable)
@@ -1009,6 +1102,40 @@ void dispc_enable_gamma_table(bool enable)
        REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
 }
 
+void dispc_enable_cpr(enum omap_channel channel, bool enable)
+{
+       u16 reg;
+
+       if (channel == OMAP_DSS_CHANNEL_LCD)
+               reg = DISPC_CONFIG;
+       else if (channel == OMAP_DSS_CHANNEL_LCD2)
+               reg = DISPC_CONFIG2;
+       else
+               return;
+
+       REG_FLD_MOD(reg, enable, 15, 15);
+}
+
+void dispc_set_cpr_coef(enum omap_channel channel,
+               struct omap_dss_cpr_coefs *coefs)
+{
+       u32 coef_r, coef_g, coef_b;
+
+       if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2)
+               return;
+
+       coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) |
+               FLD_VAL(coefs->rb, 9, 0);
+       coef_g = FLD_VAL(coefs->gr, 31, 22) | FLD_VAL(coefs->gg, 20, 11) |
+               FLD_VAL(coefs->gb, 9, 0);
+       coef_b = FLD_VAL(coefs->br, 31, 22) | FLD_VAL(coefs->bg, 20, 11) |
+               FLD_VAL(coefs->bb, 9, 0);
+
+       dispc_write_reg(DISPC_CPR_COEF_R(channel), coef_r);
+       dispc_write_reg(DISPC_CPR_COEF_G(channel), coef_g);
+       dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b);
+}
+
 static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
 {
        u32 val;
@@ -1029,9 +1156,7 @@ void dispc_enable_replication(enum omap_plane plane, bool enable)
        else
                bit = 10;
 
-       enable_clocks(1);
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
-       enable_clocks(0);
 }
 
 void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
@@ -1039,9 +1164,7 @@ void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
        u32 val;
        BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
        val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-       enable_clocks(1);
        dispc_write_reg(DISPC_SIZE_MGR(channel), val);
-       enable_clocks(0);
 }
 
 void dispc_set_digit_size(u16 width, u16 height)
@@ -1049,9 +1172,7 @@ void dispc_set_digit_size(u16 width, u16 height)
        u32 val;
        BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
        val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-       enable_clocks(1);
        dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
-       enable_clocks(0);
 }
 
 static void dispc_read_plane_fifo_sizes(void)
@@ -1059,18 +1180,17 @@ static void dispc_read_plane_fifo_sizes(void)
        u32 size;
        int plane;
        u8 start, end;
+       u32 unit;
 
-       enable_clocks(1);
+       unit = dss_feat_get_buffer_size_unit();
 
        dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
 
        for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
-               size = FLD_GET(dispc_read_reg(DISPC_OVL_FIFO_SIZE_STATUS(plane)),
-                       start, end);
+               size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end);
+               size *= unit;
                dispc.fifo_size[plane] = size;
        }
-
-       enable_clocks(0);
 }
 
 u32 dispc_get_plane_fifo_size(enum omap_plane plane)
@@ -1078,15 +1198,22 @@ u32 dispc_get_plane_fifo_size(enum omap_plane plane)
        return dispc.fifo_size[plane];
 }
 
-void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
+void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
 {
        u8 hi_start, hi_end, lo_start, lo_end;
+       u32 unit;
+
+       unit = dss_feat_get_buffer_size_unit();
+
+       WARN_ON(low % unit != 0);
+       WARN_ON(high % unit != 0);
+
+       low /= unit;
+       high /= unit;
 
        dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
        dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
 
-       enable_clocks(1);
-
        DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
                        plane,
                        REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
@@ -1098,18 +1225,12 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
        dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
                        FLD_VAL(high, hi_start, hi_end) |
                        FLD_VAL(low, lo_start, lo_end));
-
-       enable_clocks(0);
 }
 
 void dispc_enable_fifomerge(bool enable)
 {
-       enable_clocks(1);
-
        DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
        REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
-
-       enable_clocks(0);
 }
 
 static void _dispc_set_fir(enum omap_plane plane,
@@ -1729,14 +1850,7 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
        return dispc_pclk_rate(channel) * vf * hf;
 }
 
-void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
-{
-       enable_clocks(1);
-       _dispc_set_channel_out(plane, channel_out);
-       enable_clocks(0);
-}
-
-static int _dispc_setup_plane(enum omap_plane plane,
+int dispc_setup_plane(enum omap_plane plane,
                u32 paddr, u16 screen_width,
                u16 pos_x, u16 pos_y,
                u16 width, u16 height,
@@ -1744,7 +1858,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
                enum omap_color_mode color_mode,
                bool ilace,
                enum omap_dss_rotation_type rotation_type,
-               u8 rotation, int mirror,
+               u8 rotation, bool mirror,
                u8 global_alpha, u8 pre_mult_alpha,
                enum omap_channel channel, u32 puv_addr)
 {
@@ -1758,6 +1872,14 @@ static int _dispc_setup_plane(enum omap_plane plane,
        u16 frame_height = height;
        unsigned int field_offset = 0;
 
+       DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
+              "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
+              plane, paddr, screen_width, pos_x, pos_y,
+              width, height,
+              out_width, out_height,
+              ilace, color_mode,
+              rotation, mirror, channel);
+
        if (paddr == 0)
                return -EINVAL;
 
@@ -1903,9 +2025,13 @@ static int _dispc_setup_plane(enum omap_plane plane,
        return 0;
 }
 
-static void _dispc_enable_plane(enum omap_plane plane, bool enable)
+int dispc_enable_plane(enum omap_plane plane, bool enable)
 {
+       DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
+
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
+
+       return 0;
 }
 
 static void dispc_disable_isr(void *data, u32 mask)
@@ -1929,8 +2055,6 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
        int r;
        u32 irq;
 
-       enable_clocks(1);
-
        /* When we disable LCD output, we need to wait until frame is done.
         * Otherwise the DSS is still working, and turning off the clocks
         * prevents DSS from going to OFF mode */
@@ -1964,8 +2088,6 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
                if (r)
                        DSSERR("failed to unregister FRAMEDONE isr\n");
        }
-
-       enable_clocks(0);
 }
 
 static void _enable_digit_out(bool enable)
@@ -1978,12 +2100,8 @@ static void dispc_enable_digit_out(bool enable)
        struct completion frame_done_completion;
        int r;
 
-       enable_clocks(1);
-
-       if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
-               enable_clocks(0);
+       if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
                return;
-       }
 
        if (enable) {
                unsigned long flags;
@@ -2035,8 +2153,6 @@ static void dispc_enable_digit_out(bool enable)
                _omap_dispc_set_irqs();
                spin_unlock_irqrestore(&dispc.irq_lock, flags);
        }
-
-       enable_clocks(0);
 }
 
 bool dispc_is_channel_enabled(enum omap_channel channel)
@@ -2067,9 +2183,7 @@ void dispc_lcd_enable_signal_polarity(bool act_high)
        if (!dss_has_feature(FEAT_LCDENABLEPOL))
                return;
 
-       enable_clocks(1);
        REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
-       enable_clocks(0);
 }
 
 void dispc_lcd_enable_signal(bool enable)
@@ -2077,9 +2191,7 @@ void dispc_lcd_enable_signal(bool enable)
        if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
                return;
 
-       enable_clocks(1);
        REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
-       enable_clocks(0);
 }
 
 void dispc_pck_free_enable(bool enable)
@@ -2087,19 +2199,15 @@ void dispc_pck_free_enable(bool enable)
        if (!dss_has_feature(FEAT_PCKFREEENABLE))
                return;
 
-       enable_clocks(1);
        REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
-       enable_clocks(0);
 }
 
 void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
 {
-       enable_clocks(1);
        if (channel == OMAP_DSS_CHANNEL_LCD2)
                REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
        else
                REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
-       enable_clocks(0);
 }
 
 
@@ -2122,27 +2230,21 @@ void dispc_set_lcd_display_type(enum omap_channel channel,
                return;
        }
 
-       enable_clocks(1);
        if (channel == OMAP_DSS_CHANNEL_LCD2)
                REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
        else
                REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
-       enable_clocks(0);
 }
 
 void dispc_set_loadmode(enum omap_dss_load_mode mode)
 {
-       enable_clocks(1);
        REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
-       enable_clocks(0);
 }
 
 
 void dispc_set_default_color(enum omap_channel channel, u32 color)
 {
-       enable_clocks(1);
        dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
-       enable_clocks(0);
 }
 
 u32 dispc_get_default_color(enum omap_channel channel)
@@ -2153,9 +2255,7 @@ u32 dispc_get_default_color(enum omap_channel channel)
                channel != OMAP_DSS_CHANNEL_LCD &&
                channel != OMAP_DSS_CHANNEL_LCD2);
 
-       enable_clocks(1);
        l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
-       enable_clocks(0);
 
        return l;
 }
@@ -2164,7 +2264,6 @@ void dispc_set_trans_key(enum omap_channel ch,
                enum omap_dss_trans_key_type type,
                u32 trans_key)
 {
-       enable_clocks(1);
        if (ch == OMAP_DSS_CHANNEL_LCD)
                REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
        else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2173,14 +2272,12 @@ void dispc_set_trans_key(enum omap_channel ch,
                REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
 
        dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
-       enable_clocks(0);
 }
 
 void dispc_get_trans_key(enum omap_channel ch,
                enum omap_dss_trans_key_type *type,
                u32 *trans_key)
 {
-       enable_clocks(1);
        if (type) {
                if (ch == OMAP_DSS_CHANNEL_LCD)
                        *type = REG_GET(DISPC_CONFIG, 11, 11);
@@ -2194,33 +2291,28 @@ void dispc_get_trans_key(enum omap_channel ch,
 
        if (trans_key)
                *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
-       enable_clocks(0);
 }
 
 void dispc_enable_trans_key(enum omap_channel ch, bool enable)
 {
-       enable_clocks(1);
        if (ch == OMAP_DSS_CHANNEL_LCD)
                REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
        else if (ch == OMAP_DSS_CHANNEL_DIGIT)
                REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
        else /* OMAP_DSS_CHANNEL_LCD2 */
                REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
-       enable_clocks(0);
 }
 void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
 {
        if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
                return;
 
-       enable_clocks(1);
        if (ch == OMAP_DSS_CHANNEL_LCD)
                REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
        else if (ch == OMAP_DSS_CHANNEL_DIGIT)
                REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
        else /* OMAP_DSS_CHANNEL_LCD2 */
                REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
-       enable_clocks(0);
 }
 bool dispc_alpha_blending_enabled(enum omap_channel ch)
 {
@@ -2229,7 +2321,6 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
        if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
                return false;
 
-       enable_clocks(1);
        if (ch == OMAP_DSS_CHANNEL_LCD)
                enabled = REG_GET(DISPC_CONFIG, 18, 18);
        else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2238,7 +2329,6 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
                enabled = REG_GET(DISPC_CONFIG2, 18, 18);
        else
                BUG();
-       enable_clocks(0);
 
        return enabled;
 }
@@ -2248,7 +2338,6 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
 {
        bool enabled;
 
-       enable_clocks(1);
        if (ch == OMAP_DSS_CHANNEL_LCD)
                enabled = REG_GET(DISPC_CONFIG, 10, 10);
        else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2257,7 +2346,6 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
                enabled = REG_GET(DISPC_CONFIG2, 10, 10);
        else
                BUG();
-       enable_clocks(0);
 
        return enabled;
 }
@@ -2285,12 +2373,10 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
                return;
        }
 
-       enable_clocks(1);
        if (channel == OMAP_DSS_CHANNEL_LCD2)
                REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
        else
                REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
-       enable_clocks(0);
 }
 
 void dispc_set_parallel_interface_mode(enum omap_channel channel,
@@ -2322,8 +2408,6 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
                return;
        }
 
-       enable_clocks(1);
-
        if (channel == OMAP_DSS_CHANNEL_LCD2) {
                l = dispc_read_reg(DISPC_CONTROL2);
                l = FLD_MOD(l, stallmode, 11, 11);
@@ -2335,8 +2419,6 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
                l = FLD_MOD(l, gpout1, 16, 16);
                dispc_write_reg(DISPC_CONTROL, l);
        }
-
-       enable_clocks(0);
 }
 
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -2389,10 +2471,8 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
                        FLD_VAL(vbp, 31, 20);
        }
 
-       enable_clocks(1);
        dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
        dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
-       enable_clocks(0);
 }
 
 /* change name to mode? */
@@ -2435,10 +2515,8 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
        BUG_ON(lck_div < 1);
        BUG_ON(pck_div < 2);
 
-       enable_clocks(1);
        dispc_write_reg(DISPC_DIVISORo(channel),
                        FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
-       enable_clocks(0);
 }
 
 static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -2457,7 +2535,7 @@ unsigned long dispc_fclk_rate(void)
 
        switch (dss_get_dispc_clk_source()) {
        case OMAP_DSS_CLK_SRC_FCK:
-               r = dss_clk_get_rate(DSS_CLK_FCK);
+               r = clk_get_rate(dispc.dss_clk);
                break;
        case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
                dsidev = dsi_get_dsidev_from_id(0);
@@ -2487,7 +2565,7 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)
 
        switch (dss_get_lcd_clk_source(channel)) {
        case OMAP_DSS_CLK_SRC_FCK:
-               r = dss_clk_get_rate(DSS_CLK_FCK);
+               r = clk_get_rate(dispc.dss_clk);
                break;
        case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
                dsidev = dsi_get_dsidev_from_id(0);
@@ -2526,7 +2604,8 @@ void dispc_dump_clocks(struct seq_file *s)
        enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
        enum omap_dss_clk_source lcd_clk_src;
 
-       enable_clocks(1);
+       if (dispc_runtime_get())
+               return;
 
        seq_printf(s, "- DISPC -\n");
 
@@ -2574,7 +2653,8 @@ void dispc_dump_clocks(struct seq_file *s)
                seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
                                dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
        }
-       enable_clocks(0);
+
+       dispc_runtime_put();
 }
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -2629,7 +2709,8 @@ void dispc_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       if (dispc_runtime_get())
+               return;
 
        DUMPREG(DISPC_REVISION);
        DUMPREG(DISPC_SYSCONFIG);
@@ -2649,7 +2730,8 @@ void dispc_dump_regs(struct seq_file *s)
        DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD));
        DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD));
        DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_GLOBAL_ALPHA);
+       if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+               DUMPREG(DISPC_GLOBAL_ALPHA);
        DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
        DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
        if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -2680,20 +2762,25 @@ void dispc_dump_regs(struct seq_file *s)
        DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
        DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 
-       DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+       if (dss_has_feature(FEAT_CPR)) {
+               DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+               DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+               DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+       }
        if (dss_has_feature(FEAT_MGR_LCD2)) {
                DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
                DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
                DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
 
-               DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
-               DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-               DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+               if (dss_has_feature(FEAT_CPR)) {
+                       DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+                       DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+                       DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+               }
        }
 
-       DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
+       if (dss_has_feature(FEAT_PRELOAD))
+               DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
 
        DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1));
        DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1));
@@ -2744,14 +2831,16 @@ void dispc_dump_regs(struct seq_file *s)
        DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
        DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
        DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
+       if (dss_has_feature(FEAT_FIR_COEF_V)) {
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
+       }
 
        if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
                DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -2812,14 +2901,17 @@ void dispc_dump_regs(struct seq_file *s)
        DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
        DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
        DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
+
+       if (dss_has_feature(FEAT_FIR_COEF_V)) {
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
+       }
 
        if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
                DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -2858,10 +2950,12 @@ void dispc_dump_regs(struct seq_file *s)
        if (dss_has_feature(FEAT_ATTR2))
                DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 
-       DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
+       if (dss_has_feature(FEAT_PRELOAD)) {
+               DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
+               DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
+       }
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       dispc_runtime_put();
 #undef DUMPREG
 }
 
@@ -2882,9 +2976,7 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
        l |= FLD_VAL(acbi, 11, 8);
        l |= FLD_VAL(acb, 7, 0);
 
-       enable_clocks(1);
        dispc_write_reg(DISPC_POL_FREQ(channel), l);
-       enable_clocks(0);
 }
 
 void dispc_set_pol_freq(enum omap_channel channel,
@@ -3005,15 +3097,11 @@ static void _omap_dispc_set_irqs(void)
                mask |= isr_data->mask;
        }
 
-       enable_clocks(1);
-
        old_mask = dispc_read_reg(DISPC_IRQENABLE);
        /* clear the irqstatus for newly enabled irqs */
        dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
 
        dispc_write_reg(DISPC_IRQENABLE, mask);
-
-       enable_clocks(0);
 }
 
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
@@ -3522,13 +3610,6 @@ static void _omap_dispc_initial_config(void)
 {
        u32 l;
 
-       l = dispc_read_reg(DISPC_SYSCONFIG);
-       l = FLD_MOD(l, 2, 13, 12);      /* MIDLEMODE: smart standby */
-       l = FLD_MOD(l, 2, 4, 3);        /* SIDLEMODE: smart idle */
-       l = FLD_MOD(l, 1, 2, 2);        /* ENWAKEUP */
-       l = FLD_MOD(l, 1, 0, 0);        /* AUTOIDLE */
-       dispc_write_reg(DISPC_SYSCONFIG, l);
-
        /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
        if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
                l = dispc_read_reg(DISPC_DIVISOR);
@@ -3552,58 +3633,8 @@ static void _omap_dispc_initial_config(void)
        dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
 
        dispc_read_plane_fifo_sizes();
-}
 
-int dispc_enable_plane(enum omap_plane plane, bool enable)
-{
-       DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
-
-       enable_clocks(1);
-       _dispc_enable_plane(plane, enable);
-       enable_clocks(0);
-
-       return 0;
-}
-
-int dispc_setup_plane(enum omap_plane plane,
-                      u32 paddr, u16 screen_width,
-                      u16 pos_x, u16 pos_y,
-                      u16 width, u16 height,
-                      u16 out_width, u16 out_height,
-                      enum omap_color_mode color_mode,
-                      bool ilace,
-                      enum omap_dss_rotation_type rotation_type,
-                      u8 rotation, bool mirror, u8 global_alpha,
-                      u8 pre_mult_alpha, enum omap_channel channel,
-                      u32 puv_addr)
-{
-       int r = 0;
-
-       DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d, %d, %dx%d -> "
-              "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
-              plane, paddr, screen_width, pos_x, pos_y,
-              width, height,
-              out_width, out_height,
-              ilace, color_mode,
-              rotation, mirror, channel);
-
-       enable_clocks(1);
-
-       r = _dispc_setup_plane(plane,
-                          paddr, screen_width,
-                          pos_x, pos_y,
-                          width, height,
-                          out_width, out_height,
-                          color_mode, ilace,
-                          rotation_type,
-                          rotation, mirror,
-                          global_alpha,
-                          pre_mult_alpha,
-                          channel, puv_addr);
-
-       enable_clocks(0);
-
-       return r;
+       dispc_configure_burst_sizes();
 }
 
 /* DISPC HW IP initialisation */
@@ -3612,9 +3643,19 @@ static int omap_dispchw_probe(struct platform_device *pdev)
        u32 rev;
        int r = 0;
        struct resource *dispc_mem;
+       struct clk *clk;
 
        dispc.pdev = pdev;
 
+       clk = clk_get(&pdev->dev, "fck");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get fck\n");
+               r = PTR_ERR(clk);
+               goto err_get_clk;
+       }
+
+       dispc.dss_clk = clk;
+
        spin_lock_init(&dispc.irq_lock);
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -3628,62 +3669,103 @@ static int omap_dispchw_probe(struct platform_device *pdev)
        if (!dispc_mem) {
                DSSERR("can't get IORESOURCE_MEM DISPC\n");
                r = -EINVAL;
-               goto fail0;
+               goto err_ioremap;
        }
        dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
        if (!dispc.base) {
                DSSERR("can't ioremap DISPC\n");
                r = -ENOMEM;
-               goto fail0;
+               goto err_ioremap;
        }
        dispc.irq = platform_get_irq(dispc.pdev, 0);
        if (dispc.irq < 0) {
                DSSERR("platform_get_irq failed\n");
                r = -ENODEV;
-               goto fail1;
+               goto err_irq;
        }
 
        r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
                "OMAP DISPC", dispc.pdev);
        if (r < 0) {
                DSSERR("request_irq failed\n");
-               goto fail1;
+               goto err_irq;
        }
 
-       enable_clocks(1);
+       pm_runtime_enable(&pdev->dev);
+
+       r = dispc_runtime_get();
+       if (r)
+               goto err_runtime_get;
 
        _omap_dispc_initial_config();
 
        _omap_dispc_initialize_irq();
 
-       dispc_save_context();
-
        rev = dispc_read_reg(DISPC_REVISION);
        dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
               FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
-       enable_clocks(0);
+       dispc_runtime_put();
 
        return 0;
-fail1:
+
+err_runtime_get:
+       pm_runtime_disable(&pdev->dev);
+       free_irq(dispc.irq, dispc.pdev);
+err_irq:
        iounmap(dispc.base);
-fail0:
+err_ioremap:
+       clk_put(dispc.dss_clk);
+err_get_clk:
        return r;
 }
 
 static int omap_dispchw_remove(struct platform_device *pdev)
 {
+       pm_runtime_disable(&pdev->dev);
+
+       clk_put(dispc.dss_clk);
+
        free_irq(dispc.irq, dispc.pdev);
        iounmap(dispc.base);
        return 0;
 }
 
+static int dispc_runtime_suspend(struct device *dev)
+{
+       dispc_save_context();
+       clk_disable(dispc.dss_clk);
+       dss_runtime_put();
+
+       return 0;
+}
+
+static int dispc_runtime_resume(struct device *dev)
+{
+       int r;
+
+       r = dss_runtime_get();
+       if (r < 0)
+               return r;
+
+       clk_enable(dispc.dss_clk);
+       dispc_restore_context();
+
+       return 0;
+}
+
+static const struct dev_pm_ops dispc_pm_ops = {
+       .runtime_suspend = dispc_runtime_suspend,
+       .runtime_resume = dispc_runtime_resume,
+};
+
 static struct platform_driver omap_dispchw_driver = {
        .probe          = omap_dispchw_probe,
        .remove         = omap_dispchw_remove,
        .driver         = {
                .name   = "omapdss_dispc",
                .owner  = THIS_MODULE,
+               .pm     = &dispc_pm_ops,
        },
 };
 
index c2dfc8c..94495e4 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <video/omapdss.h>
 #include "dss.h"
+#include "dss_features.h"
 
 static ssize_t display_enabled_show(struct device *dev,
                struct device_attribute *attr, char *buf)
@@ -65,48 +66,6 @@ static ssize_t display_enabled_store(struct device *dev,
        return size;
 }
 
-static ssize_t display_upd_mode_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
-       if (dssdev->driver->get_update_mode)
-               mode = dssdev->driver->get_update_mode(dssdev);
-       return snprintf(buf, PAGE_SIZE, "%d\n", mode);
-}
-
-static ssize_t display_upd_mode_store(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf, size_t size)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       int val, r;
-       enum omap_dss_update_mode mode;
-
-       if (!dssdev->driver->set_update_mode)
-               return -EINVAL;
-
-       r = kstrtoint(buf, 0, &val);
-       if (r)
-               return r;
-
-       switch (val) {
-       case OMAP_DSS_UPDATE_DISABLED:
-       case OMAP_DSS_UPDATE_AUTO:
-       case OMAP_DSS_UPDATE_MANUAL:
-               mode = (enum omap_dss_update_mode)val;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       r = dssdev->driver->set_update_mode(dssdev, mode);
-       if (r)
-               return r;
-
-       return size;
-}
-
 static ssize_t display_tear_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -294,8 +253,6 @@ static ssize_t display_wss_store(struct device *dev,
 
 static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
                display_enabled_show, display_enabled_store);
-static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
-               display_upd_mode_show, display_upd_mode_store);
 static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
                display_tear_show, display_tear_store);
 static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
@@ -309,7 +266,6 @@ static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
 
 static struct device_attribute *display_sysfs_attrs[] = {
        &dev_attr_enabled,
-       &dev_attr_update_mode,
        &dev_attr_tear_elim,
        &dev_attr_timings,
        &dev_attr_rotate,
@@ -327,16 +283,13 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
 EXPORT_SYMBOL(omapdss_default_get_resolution);
 
 void default_get_overlay_fifo_thresholds(enum omap_plane plane,
-               u32 fifo_size, enum omap_burst_size *burst_size,
+               u32 fifo_size, u32 burst_size,
                u32 *fifo_low, u32 *fifo_high)
 {
-       unsigned burst_size_bytes;
-
-       *burst_size = OMAP_DSS_BURST_16x32;
-       burst_size_bytes = 16 * 32 / 8;
+       unsigned buf_unit = dss_feat_get_buffer_size_unit();
 
-       *fifo_high = fifo_size - 1;
-       *fifo_low = fifo_size - burst_size_bytes;
+       *fifo_high = fifo_size - buf_unit;
+       *fifo_low = fifo_size - burst_size;
 }
 
 int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
index ff6bd30..f053b18 100644 (file)
@@ -23,7 +23,6 @@
 #define DSS_SUBSYS_NAME "DPI"
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/errno.h>
@@ -130,8 +129,6 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
        bool is_tft;
        int r = 0;
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-
        dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
                        dssdev->panel.acbi, dssdev->panel.acb);
 
@@ -144,7 +141,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
                r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000,
                                &fck, &lck_div, &pck_div);
        if (r)
-               goto err0;
+               return r;
 
        pck = fck / lck_div / pck_div / 1000;
 
@@ -158,12 +155,10 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
 
        dispc_set_lcd_timings(dssdev->manager->id, t);
 
-err0:
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
-       return r;
+       return 0;
 }
 
-static int dpi_basic_init(struct omap_dss_device *dssdev)
+static void dpi_basic_init(struct omap_dss_device *dssdev)
 {
        bool is_tft;
 
@@ -175,8 +170,6 @@ static int dpi_basic_init(struct omap_dss_device *dssdev)
                        OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
        dispc_set_tft_data_lines(dssdev->manager->id,
                        dssdev->phy.dpi.data_lines);
-
-       return 0;
 }
 
 int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
@@ -186,31 +179,38 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
-               goto err0;
+               goto err_start_dev;
        }
 
        if (cpu_is_omap34xx()) {
                r = regulator_enable(dpi.vdds_dsi_reg);
                if (r)
-                       goto err1;
+                       goto err_reg_enable;
        }
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       r = dss_runtime_get();
+       if (r)
+               goto err_get_dss;
 
-       r = dpi_basic_init(dssdev);
+       r = dispc_runtime_get();
        if (r)
-               goto err2;
+               goto err_get_dispc;
+
+       dpi_basic_init(dssdev);
 
        if (dpi_use_dsi_pll(dssdev)) {
-               dss_clk_enable(DSS_CLK_SYSCK);
+               r = dsi_runtime_get(dpi.dsidev);
+               if (r)
+                       goto err_get_dsi;
+
                r = dsi_pll_init(dpi.dsidev, 0, 1);
                if (r)
-                       goto err3;
+                       goto err_dsi_pll_init;
        }
 
        r = dpi_set_mode(dssdev);
        if (r)
-               goto err4;
+               goto err_set_mode;
 
        mdelay(2);
 
@@ -218,19 +218,22 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 
        return 0;
 
-err4:
+err_set_mode:
        if (dpi_use_dsi_pll(dssdev))
                dsi_pll_uninit(dpi.dsidev, true);
-err3:
+err_dsi_pll_init:
        if (dpi_use_dsi_pll(dssdev))
-               dss_clk_disable(DSS_CLK_SYSCK);
-err2:
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+               dsi_runtime_put(dpi.dsidev);
+err_get_dsi:
+       dispc_runtime_put();
+err_get_dispc:
+       dss_runtime_put();
+err_get_dss:
        if (cpu_is_omap34xx())
                regulator_disable(dpi.vdds_dsi_reg);
-err1:
+err_reg_enable:
        omap_dss_stop_device(dssdev);
-err0:
+err_start_dev:
        return r;
 }
 EXPORT_SYMBOL(omapdss_dpi_display_enable);
@@ -242,10 +245,11 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
        if (dpi_use_dsi_pll(dssdev)) {
                dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
                dsi_pll_uninit(dpi.dsidev, true);
-               dss_clk_disable(DSS_CLK_SYSCK);
+               dsi_runtime_put(dpi.dsidev);
        }
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       dispc_runtime_put();
+       dss_runtime_put();
 
        if (cpu_is_omap34xx())
                regulator_disable(dpi.vdds_dsi_reg);
@@ -257,11 +261,26 @@ EXPORT_SYMBOL(omapdss_dpi_display_disable);
 void dpi_set_timings(struct omap_dss_device *dssdev,
                        struct omap_video_timings *timings)
 {
+       int r;
+
        DSSDBG("dpi_set_timings\n");
        dssdev->panel.timings = *timings;
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+               r = dss_runtime_get();
+               if (r)
+                       return;
+
+               r = dispc_runtime_get();
+               if (r) {
+                       dss_runtime_put();
+                       return;
+               }
+
                dpi_set_mode(dssdev);
                dispc_go(dssdev->manager->id);
+
+               dispc_runtime_put();
+               dss_runtime_put();
        }
 }
 EXPORT_SYMBOL(dpi_set_timings);
index 345757c..7adbbeb 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include <plat/clock.h>
@@ -267,8 +268,12 @@ struct dsi_isr_tables {
 struct dsi_data {
        struct platform_device *pdev;
        void __iomem    *base;
+
        int irq;
 
+       struct clk *dss_clk;
+       struct clk *sys_clk;
+
        void (*dsi_mux_pads)(bool enable);
 
        struct dsi_clock_info current_cinfo;
@@ -389,15 +394,6 @@ static inline u32 dsi_read_reg(struct platform_device *dsidev,
        return __raw_readl(dsi->base + idx.idx);
 }
 
-
-void dsi_save_context(void)
-{
-}
-
-void dsi_restore_context(void)
-{
-}
-
 void dsi_bus_lock(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -493,9 +489,18 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
                        total_bytes * 1000 / total_us);
 }
 #else
-#define dsi_perf_mark_setup(x)
-#define dsi_perf_mark_start(x)
-#define dsi_perf_show(x, y)
+static inline void dsi_perf_mark_setup(struct platform_device *dsidev)
+{
+}
+
+static inline void dsi_perf_mark_start(struct platform_device *dsidev)
+{
+}
+
+static inline void dsi_perf_show(struct platform_device *dsidev,
+               const char *name)
+{
+}
 #endif
 
 static void print_irq_status(u32 status)
@@ -1039,13 +1044,27 @@ static u32 dsi_get_errors(struct platform_device *dsidev)
        return e;
 }
 
-/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */
-static inline void enable_clocks(bool enable)
+int dsi_runtime_get(struct platform_device *dsidev)
 {
-       if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-       else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       int r;
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       DSSDBG("dsi_runtime_get\n");
+
+       r = pm_runtime_get_sync(&dsi->pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
+}
+
+void dsi_runtime_put(struct platform_device *dsidev)
+{
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       int r;
+
+       DSSDBG("dsi_runtime_put\n");
+
+       r = pm_runtime_put(&dsi->pdev->dev);
+       WARN_ON(r < 0);
 }
 
 /* source clock for DSI PLL. this could also be PCLKFREE */
@@ -1055,9 +1074,9 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
        if (enable)
-               dss_clk_enable(DSS_CLK_SYSCK);
+               clk_enable(dsi->sys_clk);
        else
-               dss_clk_disable(DSS_CLK_SYSCK);
+               clk_disable(dsi->sys_clk);
 
        if (enable && dsi->pll_locked) {
                if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
@@ -1150,10 +1169,11 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
 {
        unsigned long r;
        int dsi_module = dsi_get_dsidev_id(dsidev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
        if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) {
                /* DSI FCLK source is DSS_CLK_FCK */
-               r = dss_clk_get_rate(DSS_CLK_FCK);
+               r = clk_get_rate(dsi->dss_clk);
        } else {
                /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
                r = dsi_get_pll_hsdiv_dsi_rate(dsidev);
@@ -1262,7 +1282,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
                return -EINVAL;
 
        if (cinfo->use_sys_clk) {
-               cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK);
+               cinfo->clkin = clk_get_rate(dsi->sys_clk);
                /* XXX it is unclear if highfreq should be used
                 * with DSS_SYS_CLK source also */
                cinfo->highfreq = 0;
@@ -1311,7 +1331,7 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
        int match = 0;
        unsigned long dss_sys_clk, max_dss_fck;
 
-       dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK);
+       dss_sys_clk = clk_get_rate(dsi->sys_clk);
 
        max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
 
@@ -1601,7 +1621,6 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
                dsi->vdds_dsi_reg = vdds_dsi;
        }
 
-       enable_clocks(1);
        dsi_enable_pll_clock(dsidev, 1);
        /*
         * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
@@ -1653,7 +1672,6 @@ err1:
        }
 err0:
        dsi_disable_scp_clk(dsidev);
-       enable_clocks(0);
        dsi_enable_pll_clock(dsidev, 0);
        return r;
 }
@@ -1671,7 +1689,6 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
        }
 
        dsi_disable_scp_clk(dsidev);
-       enable_clocks(0);
        dsi_enable_pll_clock(dsidev, 0);
 
        DSSDBG("PLL uninit done\n");
@@ -1688,7 +1705,8 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
        dispc_clk_src = dss_get_dispc_clk_source();
        dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
 
-       enable_clocks(1);
+       if (dsi_runtime_get(dsidev))
+               return;
 
        seq_printf(s,   "- DSI%d PLL -\n", dsi_module + 1);
 
@@ -1731,7 +1749,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
 
        seq_printf(s,   "LP_CLK\t\t%lu\n", cinfo->lp_clk);
 
-       enable_clocks(0);
+       dsi_runtime_put(dsidev);
 }
 
 void dsi_dump_clocks(struct seq_file *s)
@@ -1873,7 +1891,8 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r))
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       if (dsi_runtime_get(dsidev))
+               return;
        dsi_enable_scp_clk(dsidev);
 
        DUMPREG(DSI_REVISION);
@@ -1947,7 +1966,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
        DUMPREG(DSI_PLL_CONFIGURATION2);
 
        dsi_disable_scp_clk(dsidev);
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       dsi_runtime_put(dsidev);
 #undef DUMPREG
 }
 
@@ -2463,28 +2482,6 @@ static void dsi_cio_uninit(struct platform_device *dsidev)
                dsi->dsi_mux_pads(false);
 }
 
-static int _dsi_wait_reset(struct platform_device *dsidev)
-{
-       int t = 0;
-
-       while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) == 0) {
-               if (++t > 5) {
-                       DSSERR("soft reset failed\n");
-                       return -ENODEV;
-               }
-               udelay(1);
-       }
-
-       return 0;
-}
-
-static int _dsi_reset(struct platform_device *dsidev)
-{
-       /* Soft reset */
-       REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1);
-       return _dsi_wait_reset(dsidev);
-}
-
 static void dsi_config_tx_fifo(struct platform_device *dsidev,
                enum fifo_size size1, enum fifo_size size2,
                enum fifo_size size3, enum fifo_size size4)
@@ -3386,6 +3383,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
        dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
                        DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
 
+       /* Reset LANEx_ULPS_SIG2 */
+       REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2),
+               7, 5);
+
        dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
 
        dsi_if_enable(dsidev, false);
@@ -4198,22 +4199,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
        dsi_pll_uninit(dsidev, disconnect_lanes);
 }
 
-static int dsi_core_init(struct platform_device *dsidev)
-{
-       /* Autoidle */
-       REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0);
-
-       /* ENWAKEUP */
-       REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2);
-
-       /* SIDLEMODE smart-idle */
-       REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3);
-
-       _dsi_initialize_irq(dsidev);
-
-       return 0;
-}
-
 int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4229,37 +4214,37 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
-               goto err0;
+               goto err_start_dev;
        }
 
-       enable_clocks(1);
-       dsi_enable_pll_clock(dsidev, 1);
-
-       r = _dsi_reset(dsidev);
+       r = dsi_runtime_get(dsidev);
        if (r)
-               goto err1;
+               goto err_get_dsi;
 
-       dsi_core_init(dsidev);
+       dsi_enable_pll_clock(dsidev, 1);
+
+       _dsi_initialize_irq(dsidev);
 
        r = dsi_display_init_dispc(dssdev);
        if (r)
-               goto err1;
+               goto err_init_dispc;
 
        r = dsi_display_init_dsi(dssdev);
        if (r)
-               goto err2;
+               goto err_init_dsi;
 
        mutex_unlock(&dsi->lock);
 
        return 0;
 
-err2:
+err_init_dsi:
        dsi_display_uninit_dispc(dssdev);
-err1:
-       enable_clocks(0);
+err_init_dispc:
        dsi_enable_pll_clock(dsidev, 0);
+       dsi_runtime_put(dsidev);
+err_get_dsi:
        omap_dss_stop_device(dssdev);
-err0:
+err_start_dev:
        mutex_unlock(&dsi->lock);
        DSSDBG("dsi_display_enable FAILED\n");
        return r;
@@ -4278,11 +4263,16 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
 
        mutex_lock(&dsi->lock);
 
+       dsi_sync_vc(dsidev, 0);
+       dsi_sync_vc(dsidev, 1);
+       dsi_sync_vc(dsidev, 2);
+       dsi_sync_vc(dsidev, 3);
+
        dsi_display_uninit_dispc(dssdev);
 
        dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps);
 
-       enable_clocks(0);
+       dsi_runtime_put(dsidev);
        dsi_enable_pll_clock(dsidev, 0);
 
        omap_dss_stop_device(dssdev);
@@ -4302,16 +4292,11 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
 EXPORT_SYMBOL(omapdss_dsi_enable_te);
 
 void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
-               u32 fifo_size, enum omap_burst_size *burst_size,
+               u32 fifo_size, u32 burst_size,
                u32 *fifo_low, u32 *fifo_high)
 {
-       unsigned burst_size_bytes;
-
-       *burst_size = OMAP_DSS_BURST_16x32;
-       burst_size_bytes = 16 * 32 / 8;
-
-       *fifo_high = fifo_size - burst_size_bytes;
-       *fifo_low = fifo_size - burst_size_bytes * 2;
+       *fifo_high = fifo_size - burst_size;
+       *fifo_low = fifo_size - burst_size * 2;
 }
 
 int dsi_init_display(struct omap_dss_device *dssdev)
@@ -4437,7 +4422,47 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
        dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
 }
 
-static int dsi_init(struct platform_device *dsidev)
+static int dsi_get_clocks(struct platform_device *dsidev)
+{
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct clk *clk;
+
+       clk = clk_get(&dsidev->dev, "fck");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get fck\n");
+               return PTR_ERR(clk);
+       }
+
+       dsi->dss_clk = clk;
+
+       if (cpu_is_omap34xx() || cpu_is_omap3630())
+               clk = clk_get(&dsidev->dev, "dss2_alwon_fck");
+       else
+               clk = clk_get(&dsidev->dev, "sys_clk");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get sys_clk\n");
+               clk_put(dsi->dss_clk);
+               dsi->dss_clk = NULL;
+               return PTR_ERR(clk);
+       }
+
+       dsi->sys_clk = clk;
+
+       return 0;
+}
+
+static void dsi_put_clocks(struct platform_device *dsidev)
+{
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       if (dsi->dss_clk)
+               clk_put(dsi->dss_clk);
+       if (dsi->sys_clk)
+               clk_put(dsi->sys_clk);
+}
+
+/* DSI1 HW IP initialisation */
+static int omap_dsi1hw_probe(struct platform_device *dsidev)
 {
        struct omap_display_platform_data *dss_plat_data;
        struct omap_dss_board_info *board_info;
@@ -4449,7 +4474,7 @@ static int dsi_init(struct platform_device *dsidev)
        dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
        if (!dsi) {
                r = -ENOMEM;
-               goto err0;
+               goto err_alloc;
        }
 
        dsi->pdev = dsidev;
@@ -4472,6 +4497,12 @@ static int dsi_init(struct platform_device *dsidev)
        mutex_init(&dsi->lock);
        sema_init(&dsi->bus_lock, 1);
 
+       r = dsi_get_clocks(dsidev);
+       if (r)
+               goto err_get_clk;
+
+       pm_runtime_enable(&dsidev->dev);
+
        INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work,
                        dsi_framedone_timeout_work_callback);
 
@@ -4484,26 +4515,26 @@ static int dsi_init(struct platform_device *dsidev)
        if (!dsi_mem) {
                DSSERR("can't get IORESOURCE_MEM DSI\n");
                r = -EINVAL;
-               goto err1;
+               goto err_ioremap;
        }
        dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem));
        if (!dsi->base) {
                DSSERR("can't ioremap DSI\n");
                r = -ENOMEM;
-               goto err1;
+               goto err_ioremap;
        }
        dsi->irq = platform_get_irq(dsi->pdev, 0);
        if (dsi->irq < 0) {
                DSSERR("platform_get_irq failed\n");
                r = -ENODEV;
-               goto err2;
+               goto err_get_irq;
        }
 
        r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED,
                dev_name(&dsidev->dev), dsi->pdev);
        if (r < 0) {
                DSSERR("request_irq failed\n");
-               goto err2;
+               goto err_get_irq;
        }
 
        /* DSI VCs initialization */
@@ -4515,7 +4546,9 @@ static int dsi_init(struct platform_device *dsidev)
 
        dsi_calc_clock_param_ranges(dsidev);
 
-       enable_clocks(1);
+       r = dsi_runtime_get(dsidev);
+       if (r)
+               goto err_get_dsi;
 
        rev = dsi_read_reg(dsidev, DSI_REVISION);
        dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
@@ -4523,21 +4556,32 @@ static int dsi_init(struct platform_device *dsidev)
 
        dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev);
 
-       enable_clocks(0);
+       dsi_runtime_put(dsidev);
 
        return 0;
-err2:
+
+err_get_dsi:
+       free_irq(dsi->irq, dsi->pdev);
+err_get_irq:
        iounmap(dsi->base);
-err1:
+err_ioremap:
+       pm_runtime_disable(&dsidev->dev);
+err_get_clk:
        kfree(dsi);
-err0:
+err_alloc:
        return r;
 }
 
-static void dsi_exit(struct platform_device *dsidev)
+static int omap_dsi1hw_remove(struct platform_device *dsidev)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
+       WARN_ON(dsi->scp_clk_refcount > 0);
+
+       pm_runtime_disable(&dsidev->dev);
+
+       dsi_put_clocks(dsidev);
+
        if (dsi->vdds_dsi_reg != NULL) {
                if (dsi->vdds_dsi_enabled) {
                        regulator_disable(dsi->vdds_dsi_reg);
@@ -4553,38 +4597,56 @@ static void dsi_exit(struct platform_device *dsidev)
 
        kfree(dsi);
 
-       DSSDBG("omap_dsi_exit\n");
+       return 0;
 }
 
-/* DSI1 HW IP initialisation */
-static int omap_dsi1hw_probe(struct platform_device *dsidev)
+static int dsi_runtime_suspend(struct device *dev)
 {
-       int r;
+       struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
 
-       r = dsi_init(dsidev);
-       if (r) {
-               DSSERR("Failed to initialize DSI\n");
-               goto err_dsi;
-       }
-err_dsi:
-       return r;
+       clk_disable(dsi->dss_clk);
+
+       dispc_runtime_put();
+       dss_runtime_put();
+
+       return 0;
 }
 
-static int omap_dsi1hw_remove(struct platform_device *dsidev)
+static int dsi_runtime_resume(struct device *dev)
 {
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
+       int r;
+
+       r = dss_runtime_get();
+       if (r)
+               goto err_get_dss;
+
+       r = dispc_runtime_get();
+       if (r)
+               goto err_get_dispc;
+
+       clk_enable(dsi->dss_clk);
 
-       dsi_exit(dsidev);
-       WARN_ON(dsi->scp_clk_refcount > 0);
        return 0;
+
+err_get_dispc:
+       dss_runtime_put();
+err_get_dss:
+       return r;
 }
 
+static const struct dev_pm_ops dsi_pm_ops = {
+       .runtime_suspend = dsi_runtime_suspend,
+       .runtime_resume = dsi_runtime_resume,
+};
+
 static struct platform_driver omap_dsi1hw_driver = {
        .probe          = omap_dsi1hw_probe,
        .remove         = omap_dsi1hw_remove,
        .driver         = {
                .name   = "omapdss_dsi1",
                .owner  = THIS_MODULE,
+               .pm     = &dsi_pm_ops,
        },
 };
 
index d9489d5..0f9c3a6 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include <plat/clock.h>
@@ -59,15 +61,9 @@ struct dss_reg {
 static struct {
        struct platform_device *pdev;
        void __iomem    *base;
-       int             ctx_id;
 
        struct clk      *dpll4_m4_ck;
-       struct clk      *dss_ick;
-       struct clk      *dss_fck;
-       struct clk      *dss_sys_clk;
-       struct clk      *dss_tv_fck;
-       struct clk      *dss_video_fck;
-       unsigned        num_clks_enabled;
+       struct clk      *dss_clk;
 
        unsigned long   cache_req_pck;
        unsigned long   cache_prate;
@@ -78,6 +74,7 @@ static struct {
        enum omap_dss_clk_source dispc_clk_source;
        enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
 
+       bool            ctx_valid;
        u32             ctx[DSS_SZ_REGS / sizeof(u32)];
 } dss;
 
@@ -87,13 +84,6 @@ static const char * const dss_generic_clk_source_names[] = {
        [OMAP_DSS_CLK_SRC_FCK]                  = "DSS_FCK",
 };
 
-static void dss_clk_enable_all_no_ctx(void);
-static void dss_clk_disable_all_no_ctx(void);
-static void dss_clk_enable_no_ctx(enum dss_clock clks);
-static void dss_clk_disable_no_ctx(enum dss_clock clks);
-
-static int _omap_dss_wait_reset(void);
-
 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
 {
        __raw_writel(val, dss.base + idx.idx);
@@ -109,12 +99,10 @@ static inline u32 dss_read_reg(const struct dss_reg idx)
 #define RR(reg) \
        dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
 
-void dss_save_context(void)
+static void dss_save_context(void)
 {
-       if (cpu_is_omap24xx())
-               return;
+       DSSDBG("dss_save_context\n");
 
-       SR(SYSCONFIG);
        SR(CONTROL);
 
        if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -122,14 +110,19 @@ void dss_save_context(void)
                SR(SDI_CONTROL);
                SR(PLL_CONTROL);
        }
+
+       dss.ctx_valid = true;
+
+       DSSDBG("context saved\n");
 }
 
-void dss_restore_context(void)
+static void dss_restore_context(void)
 {
-       if (_omap_dss_wait_reset())
-               DSSERR("DSS not coming out of reset after sleep\n");
+       DSSDBG("dss_restore_context\n");
+
+       if (!dss.ctx_valid)
+               return;
 
-       RR(SYSCONFIG);
        RR(CONTROL);
 
        if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -137,6 +130,8 @@ void dss_restore_context(void)
                RR(SDI_CONTROL);
                RR(PLL_CONTROL);
        }
+
+       DSSDBG("context restored\n");
 }
 
 #undef SR
@@ -234,6 +229,7 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
        return dss_generic_clk_source_names[clk_src];
 }
 
+
 void dss_dump_clocks(struct seq_file *s)
 {
        unsigned long dpll4_ck_rate;
@@ -241,13 +237,14 @@ void dss_dump_clocks(struct seq_file *s)
        const char *fclk_name, *fclk_real_name;
        unsigned long fclk_rate;
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       if (dss_runtime_get())
+               return;
 
        seq_printf(s, "- DSS -\n");
 
        fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
        fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
-       fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
+       fclk_rate = clk_get_rate(dss.dss_clk);
 
        if (dss.dpll4_m4_ck) {
                dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
@@ -273,14 +270,15 @@ void dss_dump_clocks(struct seq_file *s)
                                fclk_rate);
        }
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       dss_runtime_put();
 }
 
 void dss_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       if (dss_runtime_get())
+               return;
 
        DUMPREG(DSS_REVISION);
        DUMPREG(DSS_SYSCONFIG);
@@ -294,7 +292,7 @@ void dss_dump_regs(struct seq_file *s)
                DUMPREG(DSS_SDI_STATUS);
        }
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       dss_runtime_put();
 #undef DUMPREG
 }
 
@@ -437,7 +435,7 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
        } else {
                if (cinfo->fck_div != 0)
                        return -EINVAL;
-               cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
+               cinfo->fck = clk_get_rate(dss.dss_clk);
        }
 
        return 0;
@@ -467,7 +465,7 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
 
 int dss_get_clock_div(struct dss_clock_info *cinfo)
 {
-       cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
+       cinfo->fck = clk_get_rate(dss.dss_clk);
 
        if (dss.dpll4_m4_ck) {
                unsigned long prate;
@@ -512,7 +510,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
 
        max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
 
-       fck = dss_clk_get_rate(DSS_CLK_FCK);
+       fck = clk_get_rate(dss.dss_clk);
        if (req_pck == dss.cache_req_pck &&
                        ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
                         dss.cache_dss_cinfo.fck == fck)) {
@@ -539,7 +537,7 @@ retry:
        if (dss.dpll4_m4_ck == NULL) {
                struct dispc_clock_info cur_dispc;
                /* XXX can we change the clock on omap2? */
-               fck = dss_clk_get_rate(DSS_CLK_FCK);
+               fck = clk_get_rate(dss.dss_clk);
                fck_div = 1;
 
                dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
@@ -616,28 +614,6 @@ found:
        return 0;
 }
 
-static int _omap_dss_wait_reset(void)
-{
-       int t = 0;
-
-       while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
-               if (++t > 1000) {
-                       DSSERR("soft reset failed\n");
-                       return -ENODEV;
-               }
-               udelay(1);
-       }
-
-       return 0;
-}
-
-static int _omap_dss_reset(void)
-{
-       /* Soft reset */
-       REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
-       return _omap_dss_wait_reset();
-}
-
 void dss_set_venc_output(enum omap_dss_venc_type type)
 {
        int l = 0;
@@ -663,424 +639,88 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
        REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
 }
 
-static int dss_init(void)
+static int dss_get_clocks(void)
 {
+       struct clk *clk;
        int r;
-       u32 rev;
-       struct resource *dss_mem;
-       struct clk *dpll4_m4_ck;
 
-       dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
-       if (!dss_mem) {
-               DSSERR("can't get IORESOURCE_MEM DSS\n");
-               r = -EINVAL;
-               goto fail0;
-       }
-       dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
-       if (!dss.base) {
-               DSSERR("can't ioremap DSS\n");
-               r = -ENOMEM;
-               goto fail0;
+       clk = clk_get(&dss.pdev->dev, "fck");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get clock fck\n");
+               r = PTR_ERR(clk);
+               goto err;
        }
 
-       /* disable LCD and DIGIT output. This seems to fix the synclost
-        * problem that we get, if the bootloader starts the DSS and
-        * the kernel resets it */
-       omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
-
-#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
-       /* We need to wait here a bit, otherwise we sometimes start to
-        * get synclost errors, and after that only power cycle will
-        * restore DSS functionality. I have no idea why this happens.
-        * And we have to wait _before_ resetting the DSS, but after
-        * enabling clocks.
-        *
-        * This bug was at least present on OMAP3430. It's unknown
-        * if it happens on OMAP2 or OMAP3630.
-        */
-       msleep(50);
-#endif
-
-       _omap_dss_reset();
+       dss.dss_clk = clk;
 
-       /* autoidle */
-       REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
-
-       /* Select DPLL */
-       REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
-
-#ifdef CONFIG_OMAP2_DSS_VENC
-       REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);      /* venc dac demen */
-       REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);      /* venc clock 4x enable */
-       REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);      /* venc clock mode = normal */
-#endif
        if (cpu_is_omap34xx()) {
-               dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
-               if (IS_ERR(dpll4_m4_ck)) {
+               clk = clk_get(NULL, "dpll4_m4_ck");
+               if (IS_ERR(clk)) {
                        DSSERR("Failed to get dpll4_m4_ck\n");
-                       r = PTR_ERR(dpll4_m4_ck);
-                       goto fail1;
+                       r = PTR_ERR(clk);
+                       goto err;
                }
        } else if (cpu_is_omap44xx()) {
-               dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
-               if (IS_ERR(dpll4_m4_ck)) {
-                       DSSERR("Failed to get dpll4_m4_ck\n");
-                       r = PTR_ERR(dpll4_m4_ck);
-                       goto fail1;
+               clk = clk_get(NULL, "dpll_per_m5x2_ck");
+               if (IS_ERR(clk)) {
+                       DSSERR("Failed to get dpll_per_m5x2_ck\n");
+                       r = PTR_ERR(clk);
+                       goto err;
                }
        } else { /* omap24xx */
-               dpll4_m4_ck = NULL;
+               clk = NULL;
        }
 
-       dss.dpll4_m4_ck = dpll4_m4_ck;
-
-       dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
-       dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
-       dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
-       dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
-       dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
-
-       dss_save_context();
-
-       rev = dss_read_reg(DSS_REVISION);
-       printk(KERN_INFO "OMAP DSS rev %d.%d\n",
-                       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+       dss.dpll4_m4_ck = clk;
 
        return 0;
 
-fail1:
-       iounmap(dss.base);
-fail0:
-       return r;
-}
-
-static void dss_exit(void)
-{
+err:
+       if (dss.dss_clk)
+               clk_put(dss.dss_clk);
        if (dss.dpll4_m4_ck)
                clk_put(dss.dpll4_m4_ck);
 
-       iounmap(dss.base);
-}
-
-/* CONTEXT */
-static int dss_get_ctx_id(void)
-{
-       struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
-       int r;
-
-       if (!pdata->board_data->get_last_off_on_transaction_id)
-               return 0;
-       r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
-       if (r < 0) {
-               dev_err(&dss.pdev->dev, "getting transaction ID failed, "
-                               "will force context restore\n");
-               r = -1;
-       }
-       return r;
-}
-
-int dss_need_ctx_restore(void)
-{
-       int id = dss_get_ctx_id();
-
-       if (id < 0 || id != dss.ctx_id) {
-               DSSDBG("ctx id %d -> id %d\n",
-                               dss.ctx_id, id);
-               dss.ctx_id = id;
-               return 1;
-       } else {
-               return 0;
-       }
-}
-
-static void save_all_ctx(void)
-{
-       DSSDBG("save context\n");
-
-       dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
-
-       dss_save_context();
-       dispc_save_context();
-#ifdef CONFIG_OMAP2_DSS_DSI
-       dsi_save_context();
-#endif
-
-       dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
-}
-
-static void restore_all_ctx(void)
-{
-       DSSDBG("restore context\n");
-
-       dss_clk_enable_all_no_ctx();
-
-       dss_restore_context();
-       dispc_restore_context();
-#ifdef CONFIG_OMAP2_DSS_DSI
-       dsi_restore_context();
-#endif
-
-       dss_clk_disable_all_no_ctx();
-}
-
-static int dss_get_clock(struct clk **clock, const char *clk_name)
-{
-       struct clk *clk;
-
-       clk = clk_get(&dss.pdev->dev, clk_name);
-
-       if (IS_ERR(clk)) {
-               DSSERR("can't get clock %s", clk_name);
-               return PTR_ERR(clk);
-       }
-
-       *clock = clk;
-
-       DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
-
-       return 0;
-}
-
-static int dss_get_clocks(void)
-{
-       int r;
-       struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
-
-       dss.dss_ick = NULL;
-       dss.dss_fck = NULL;
-       dss.dss_sys_clk = NULL;
-       dss.dss_tv_fck = NULL;
-       dss.dss_video_fck = NULL;
-
-       r = dss_get_clock(&dss.dss_ick, "ick");
-       if (r)
-               goto err;
-
-       r = dss_get_clock(&dss.dss_fck, "fck");
-       if (r)
-               goto err;
-
-       if (!pdata->opt_clock_available) {
-               r = -ENODEV;
-               goto err;
-       }
-
-       if (pdata->opt_clock_available("sys_clk")) {
-               r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
-               if (r)
-                       goto err;
-       }
-
-       if (pdata->opt_clock_available("tv_clk")) {
-               r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
-               if (r)
-                       goto err;
-       }
-
-       if (pdata->opt_clock_available("video_clk")) {
-               r = dss_get_clock(&dss.dss_video_fck, "video_clk");
-               if (r)
-                       goto err;
-       }
-
-       return 0;
-
-err:
-       if (dss.dss_ick)
-               clk_put(dss.dss_ick);
-       if (dss.dss_fck)
-               clk_put(dss.dss_fck);
-       if (dss.dss_sys_clk)
-               clk_put(dss.dss_sys_clk);
-       if (dss.dss_tv_fck)
-               clk_put(dss.dss_tv_fck);
-       if (dss.dss_video_fck)
-               clk_put(dss.dss_video_fck);
-
        return r;
 }
 
 static void dss_put_clocks(void)
 {
-       if (dss.dss_video_fck)
-               clk_put(dss.dss_video_fck);
-       if (dss.dss_tv_fck)
-               clk_put(dss.dss_tv_fck);
-       if (dss.dss_sys_clk)
-               clk_put(dss.dss_sys_clk);
-       clk_put(dss.dss_fck);
-       clk_put(dss.dss_ick);
-}
-
-unsigned long dss_clk_get_rate(enum dss_clock clk)
-{
-       switch (clk) {
-       case DSS_CLK_ICK:
-               return clk_get_rate(dss.dss_ick);
-       case DSS_CLK_FCK:
-               return clk_get_rate(dss.dss_fck);
-       case DSS_CLK_SYSCK:
-               return clk_get_rate(dss.dss_sys_clk);
-       case DSS_CLK_TVFCK:
-               return clk_get_rate(dss.dss_tv_fck);
-       case DSS_CLK_VIDFCK:
-               return clk_get_rate(dss.dss_video_fck);
-       }
-
-       BUG();
-       return 0;
-}
-
-static unsigned count_clk_bits(enum dss_clock clks)
-{
-       unsigned num_clks = 0;
-
-       if (clks & DSS_CLK_ICK)
-               ++num_clks;
-       if (clks & DSS_CLK_FCK)
-               ++num_clks;
-       if (clks & DSS_CLK_SYSCK)
-               ++num_clks;
-       if (clks & DSS_CLK_TVFCK)
-               ++num_clks;
-       if (clks & DSS_CLK_VIDFCK)
-               ++num_clks;
-
-       return num_clks;
-}
-
-static void dss_clk_enable_no_ctx(enum dss_clock clks)
-{
-       unsigned num_clks = count_clk_bits(clks);
-
-       if (clks & DSS_CLK_ICK)
-               clk_enable(dss.dss_ick);
-       if (clks & DSS_CLK_FCK)
-               clk_enable(dss.dss_fck);
-       if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
-               clk_enable(dss.dss_sys_clk);
-       if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
-               clk_enable(dss.dss_tv_fck);
-       if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
-               clk_enable(dss.dss_video_fck);
-
-       dss.num_clks_enabled += num_clks;
-}
-
-void dss_clk_enable(enum dss_clock clks)
-{
-       bool check_ctx = dss.num_clks_enabled == 0;
-
-       dss_clk_enable_no_ctx(clks);
-
-       /*
-        * HACK: On omap4 the registers may not be accessible right after
-        * enabling the clocks. At some point this will be handled by
-        * pm_runtime, but for the time begin this should make things work.
-        */
-       if (cpu_is_omap44xx() && check_ctx)
-               udelay(10);
-
-       if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
-               restore_all_ctx();
+       if (dss.dpll4_m4_ck)
+               clk_put(dss.dpll4_m4_ck);
+       clk_put(dss.dss_clk);
 }
 
-static void dss_clk_disable_no_ctx(enum dss_clock clks)
+struct clk *dss_get_ick(void)
 {
-       unsigned num_clks = count_clk_bits(clks);
-
-       if (clks & DSS_CLK_ICK)
-               clk_disable(dss.dss_ick);
-       if (clks & DSS_CLK_FCK)
-               clk_disable(dss.dss_fck);
-       if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
-               clk_disable(dss.dss_sys_clk);
-       if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
-               clk_disable(dss.dss_tv_fck);
-       if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
-               clk_disable(dss.dss_video_fck);
-
-       dss.num_clks_enabled -= num_clks;
+       return clk_get(&dss.pdev->dev, "ick");
 }
 
-void dss_clk_disable(enum dss_clock clks)
+int dss_runtime_get(void)
 {
-       if (cpu_is_omap34xx()) {
-               unsigned num_clks = count_clk_bits(clks);
-
-               BUG_ON(dss.num_clks_enabled < num_clks);
+       int r;
 
-               if (dss.num_clks_enabled == num_clks)
-                       save_all_ctx();
-       }
+       DSSDBG("dss_runtime_get\n");
 
-       dss_clk_disable_no_ctx(clks);
+       r = pm_runtime_get_sync(&dss.pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
 }
 
-static void dss_clk_enable_all_no_ctx(void)
+void dss_runtime_put(void)
 {
-       enum dss_clock clks;
-
-       clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
-       if (cpu_is_omap34xx())
-               clks |= DSS_CLK_VIDFCK;
-       dss_clk_enable_no_ctx(clks);
-}
-
-static void dss_clk_disable_all_no_ctx(void)
-{
-       enum dss_clock clks;
+       int r;
 
-       clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
-       if (cpu_is_omap34xx())
-               clks |= DSS_CLK_VIDFCK;
-       dss_clk_disable_no_ctx(clks);
-}
+       DSSDBG("dss_runtime_put\n");
 
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
-/* CLOCKS */
-static void core_dump_clocks(struct seq_file *s)
-{
-       int i;
-       struct clk *clocks[5] = {
-               dss.dss_ick,
-               dss.dss_fck,
-               dss.dss_sys_clk,
-               dss.dss_tv_fck,
-               dss.dss_video_fck
-       };
-
-       const char *names[5] = {
-               "ick",
-               "fck",
-               "sys_clk",
-               "tv_fck",
-               "video_fck"
-       };
-
-       seq_printf(s, "- CORE -\n");
-
-       seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
-
-       for (i = 0; i < 5; i++) {
-               if (!clocks[i])
-                       continue;
-               seq_printf(s, "%s (%s)%*s\t%lu\t%d\n",
-                               names[i],
-                               clocks[i]->name,
-                               24 - strlen(names[i]) - strlen(clocks[i]->name),
-                               "",
-                               clk_get_rate(clocks[i]),
-                               clocks[i]->usecount);
-       }
+       r = pm_runtime_put(&dss.pdev->dev);
+       WARN_ON(r < 0);
 }
-#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
 
 /* DEBUGFS */
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
 void dss_debug_dump_clocks(struct seq_file *s)
 {
-       core_dump_clocks(s);
        dss_dump_clocks(s);
        dispc_dump_clocks(s);
 #ifdef CONFIG_OMAP2_DSS_DSI
@@ -1089,28 +729,51 @@ void dss_debug_dump_clocks(struct seq_file *s)
 }
 #endif
 
-
 /* DSS HW IP initialisation */
 static int omap_dsshw_probe(struct platform_device *pdev)
 {
+       struct resource *dss_mem;
+       u32 rev;
        int r;
 
        dss.pdev = pdev;
 
+       dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
+       if (!dss_mem) {
+               DSSERR("can't get IORESOURCE_MEM DSS\n");
+               r = -EINVAL;
+               goto err_ioremap;
+       }
+       dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
+       if (!dss.base) {
+               DSSERR("can't ioremap DSS\n");
+               r = -ENOMEM;
+               goto err_ioremap;
+       }
+
        r = dss_get_clocks();
        if (r)
                goto err_clocks;
 
-       dss_clk_enable_all_no_ctx();
+       pm_runtime_enable(&pdev->dev);
 
-       dss.ctx_id = dss_get_ctx_id();
-       DSSDBG("initial ctx id %u\n", dss.ctx_id);
+       r = dss_runtime_get();
+       if (r)
+               goto err_runtime_get;
 
-       r = dss_init();
-       if (r) {
-               DSSERR("Failed to initialize DSS\n");
-               goto err_dss;
-       }
+       /* Select DPLL */
+       REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+       REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);      /* venc dac demen */
+       REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);      /* venc clock 4x enable */
+       REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);      /* venc clock mode = normal */
+#endif
+       dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+       dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
+       dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
+       dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+       dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
 
        r = dpi_init();
        if (r) {
@@ -1124,42 +787,66 @@ static int omap_dsshw_probe(struct platform_device *pdev)
                goto err_sdi;
        }
 
-       dss_clk_disable_all_no_ctx();
+       rev = dss_read_reg(DSS_REVISION);
+       printk(KERN_INFO "OMAP DSS rev %d.%d\n",
+                       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+       dss_runtime_put();
+
        return 0;
 err_sdi:
        dpi_exit();
 err_dpi:
-       dss_exit();
-err_dss:
-       dss_clk_disable_all_no_ctx();
+       dss_runtime_put();
+err_runtime_get:
+       pm_runtime_disable(&pdev->dev);
        dss_put_clocks();
 err_clocks:
+       iounmap(dss.base);
+err_ioremap:
        return r;
 }
 
 static int omap_dsshw_remove(struct platform_device *pdev)
 {
+       dpi_exit();
+       sdi_exit();
 
-       dss_exit();
+       iounmap(dss.base);
 
-       /*
-        * As part of hwmod changes, DSS is not the only controller of dss
-        * clocks; hwmod framework itself will also enable clocks during hwmod
-        * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
-        * need to disable clocks if their usecounts > 1.
-        */
-       WARN_ON(dss.num_clks_enabled > 0);
+       pm_runtime_disable(&pdev->dev);
 
        dss_put_clocks();
+
+       return 0;
+}
+
+static int dss_runtime_suspend(struct device *dev)
+{
+       dss_save_context();
+       clk_disable(dss.dss_clk);
        return 0;
 }
 
+static int dss_runtime_resume(struct device *dev)
+{
+       clk_enable(dss.dss_clk);
+       dss_restore_context();
+       return 0;
+}
+
+static const struct dev_pm_ops dss_pm_ops = {
+       .runtime_suspend = dss_runtime_suspend,
+       .runtime_resume = dss_runtime_resume,
+};
+
 static struct platform_driver omap_dsshw_driver = {
        .probe          = omap_dsshw_probe,
        .remove         = omap_dsshw_remove,
        .driver         = {
                .name   = "omapdss_dss",
                .owner  = THIS_MODULE,
+               .pm     = &dss_pm_ops,
        },
 };
 
index 8ab6d43..9c94b11 100644 (file)
@@ -97,26 +97,12 @@ extern unsigned int dss_debug;
 #define FLD_MOD(orig, val, start, end) \
        (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
 
-enum omap_burst_size {
-       OMAP_DSS_BURST_4x32 = 0,
-       OMAP_DSS_BURST_8x32 = 1,
-       OMAP_DSS_BURST_16x32 = 2,
-};
-
 enum omap_parallel_interface_mode {
        OMAP_DSS_PARALLELMODE_BYPASS,           /* MIPI DPI */
        OMAP_DSS_PARALLELMODE_RFBI,             /* MIPI DBI */
        OMAP_DSS_PARALLELMODE_DSI,
 };
 
-enum dss_clock {
-       DSS_CLK_ICK     = 1 << 0,       /* DSS_L3_ICLK and DSS_L4_ICLK */
-       DSS_CLK_FCK     = 1 << 1,       /* DSS1_ALWON_FCLK */
-       DSS_CLK_SYSCK   = 1 << 2,       /* DSS2_ALWON_FCLK */
-       DSS_CLK_TVFCK   = 1 << 3,       /* DSS_TV_FCLK */
-       DSS_CLK_VIDFCK  = 1 << 4,       /* DSS_96M_FCLK*/
-};
-
 enum dss_hdmi_venc_clk_source_select {
        DSS_VENC_TV_CLK = 0,
        DSS_HDMI_M_PCLK = 1,
@@ -194,7 +180,7 @@ void dss_uninit_device(struct platform_device *pdev,
 bool dss_use_replication(struct omap_dss_device *dssdev,
                enum omap_color_mode mode);
 void default_get_overlay_fifo_thresholds(enum omap_plane plane,
-               u32 fifo_size, enum omap_burst_size *burst_size,
+               u32 fifo_size, u32 burst_size,
                u32 *fifo_low, u32 *fifo_high);
 
 /* manager */
@@ -220,13 +206,12 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
 int dss_init_platform_driver(void);
 void dss_uninit_platform_driver(void);
 
+int dss_runtime_get(void);
+void dss_runtime_put(void);
+
+struct clk *dss_get_ick(void);
+
 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
-void dss_save_context(void);
-void dss_restore_context(void);
-void dss_clk_enable(enum dss_clock clks);
-void dss_clk_disable(enum dss_clock clks);
-unsigned long dss_clk_get_rate(enum dss_clock clk);
-int dss_need_ctx_restore(void);
 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
 void dss_dump_clocks(struct seq_file *s);
 
@@ -283,15 +268,15 @@ struct file_operations;
 int dsi_init_platform_driver(void);
 void dsi_uninit_platform_driver(void);
 
+int dsi_runtime_get(struct platform_device *dsidev);
+void dsi_runtime_put(struct platform_device *dsidev);
+
 void dsi_dump_clocks(struct seq_file *s);
 void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
                const struct file_operations *debug_fops);
 void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
                const struct file_operations *debug_fops);
 
-void dsi_save_context(void);
-void dsi_restore_context(void);
-
 int dsi_init_display(struct omap_dss_device *display);
 void dsi_irq_handler(void);
 unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
@@ -304,7 +289,7 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
                bool enable_hsdiv);
 void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
 void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
-               u32 fifo_size, enum omap_burst_size *burst_size,
+               u32 fifo_size, u32 burst_size,
                u32 *fifo_low, u32 *fifo_high);
 void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
 void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
@@ -317,6 +302,13 @@ static inline int dsi_init_platform_driver(void)
 static inline void dsi_uninit_platform_driver(void)
 {
 }
+static inline int dsi_runtime_get(struct platform_device *dsidev)
+{
+       return 0;
+}
+static inline void dsi_runtime_put(struct platform_device *dsidev)
+{
+}
 static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
 {
        WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
@@ -384,8 +376,8 @@ void dispc_dump_regs(struct seq_file *s);
 void dispc_irq_handler(void);
 void dispc_fake_vsync_irq(void);
 
-void dispc_save_context(void);
-void dispc_restore_context(void);
+int dispc_runtime_get(void);
+void dispc_runtime_put(void);
 
 void dispc_enable_sidle(void);
 void dispc_disable_sidle(void);
@@ -398,10 +390,12 @@ void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable);
 void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
 void dispc_set_digit_size(u16 width, u16 height);
 u32 dispc_get_plane_fifo_size(enum omap_plane plane);
-void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
+void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
 void dispc_enable_fifomerge(bool enable);
-void dispc_set_burst_size(enum omap_plane plane,
-               enum omap_burst_size burst_size);
+u32 dispc_get_burst_size(enum omap_plane plane);
+void dispc_enable_cpr(enum omap_channel channel, bool enable);
+void dispc_set_cpr_coef(enum omap_channel channel,
+               struct omap_dss_cpr_coefs *coefs);
 
 void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
 void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
index 1c18888..b415c4e 100644 (file)
@@ -49,6 +49,9 @@ struct omap_dss_features {
        const enum omap_color_mode *supported_color_modes;
        const char * const *clksrc_names;
        const struct dss_param_range *dss_params;
+
+       const u32 buffer_size_unit;
+       const u32 burst_size_unit;
 };
 
 /* This struct is assigned to one of the below during initialization */
@@ -274,6 +277,8 @@ static const struct omap_dss_features omap2_dss_features = {
        .supported_color_modes = omap2_dss_supported_color_modes,
        .clksrc_names = omap2_dss_clk_source_names,
        .dss_params = omap2_dss_param_range,
+       .buffer_size_unit = 1,
+       .burst_size_unit = 8,
 };
 
 /* OMAP3 DSS Features */
@@ -286,7 +291,9 @@ static const struct omap_dss_features omap3430_dss_features = {
                FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
                FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
                FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
-               FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC,
+               FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
+               FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
+               FEAT_FIR_COEF_V,
 
        .num_mgrs = 2,
        .num_ovls = 3,
@@ -294,6 +301,8 @@ static const struct omap_dss_features omap3430_dss_features = {
        .supported_color_modes = omap3_dss_supported_color_modes,
        .clksrc_names = omap3_dss_clk_source_names,
        .dss_params = omap3_dss_param_range,
+       .buffer_size_unit = 1,
+       .burst_size_unit = 8,
 };
 
 static const struct omap_dss_features omap3630_dss_features = {
@@ -306,7 +315,8 @@ static const struct omap_dss_features omap3630_dss_features = {
                FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
                FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
                FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
-               FEAT_DSI_PLL_FREQSEL,
+               FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
+               FEAT_FIR_COEF_V,
 
        .num_mgrs = 2,
        .num_ovls = 3,
@@ -314,6 +324,8 @@ static const struct omap_dss_features omap3630_dss_features = {
        .supported_color_modes = omap3_dss_supported_color_modes,
        .clksrc_names = omap3_dss_clk_source_names,
        .dss_params = omap3_dss_param_range,
+       .buffer_size_unit = 1,
+       .burst_size_unit = 8,
 };
 
 /* OMAP4 DSS Features */
@@ -327,7 +339,8 @@ static const struct omap_dss_features omap4430_es1_0_dss_features  = {
                FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
                FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
                FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
-               FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
+               FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
+               FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V,
 
        .num_mgrs = 3,
        .num_ovls = 3,
@@ -335,6 +348,8 @@ static const struct omap_dss_features omap4430_es1_0_dss_features  = {
        .supported_color_modes = omap4_dss_supported_color_modes,
        .clksrc_names = omap4_dss_clk_source_names,
        .dss_params = omap4_dss_param_range,
+       .buffer_size_unit = 16,
+       .burst_size_unit = 16,
 };
 
 /* For all the other OMAP4 versions */
@@ -348,7 +363,8 @@ static const struct omap_dss_features omap4_dss_features = {
                FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
                FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
                FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
-               FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
+               FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
+               FEAT_PRELOAD | FEAT_FIR_COEF_V,
 
        .num_mgrs = 3,
        .num_ovls = 3,
@@ -356,6 +372,8 @@ static const struct omap_dss_features omap4_dss_features = {
        .supported_color_modes = omap4_dss_supported_color_modes,
        .clksrc_names = omap4_dss_clk_source_names,
        .dss_params = omap4_dss_param_range,
+       .buffer_size_unit = 16,
+       .burst_size_unit = 16,
 };
 
 /* Functions returning values related to a DSS feature */
@@ -401,6 +419,16 @@ const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id)
        return omap_current_dss_features->clksrc_names[id];
 }
 
+u32 dss_feat_get_buffer_size_unit(void)
+{
+       return omap_current_dss_features->buffer_size_unit;
+}
+
+u32 dss_feat_get_burst_size_unit(void)
+{
+       return omap_current_dss_features->burst_size_unit;
+}
+
 /* DSS has_feature check */
 bool dss_has_feature(enum dss_feat_id id)
 {
index 07b346f..b7398cb 100644 (file)
@@ -51,6 +51,10 @@ enum dss_feat_id {
        FEAT_HDMI_CTS_SWMODE            = 1 << 19,
        FEAT_HANDLE_UV_SEPARATE         = 1 << 20,
        FEAT_ATTR2                      = 1 << 21,
+       FEAT_VENC_REQUIRES_TV_DAC_CLK   = 1 << 22,
+       FEAT_CPR                        = 1 << 23,
+       FEAT_PRELOAD                    = 1 << 24,
+       FEAT_FIR_COEF_V                 = 1 << 25,
 };
 
 /* DSS register field id */
@@ -90,6 +94,9 @@ bool dss_feat_color_mode_supported(enum omap_plane plane,
                enum omap_color_mode color_mode);
 const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
 
+u32 dss_feat_get_buffer_size_unit(void);       /* in bytes */
+u32 dss_feat_get_burst_size_unit(void);                /* in bytes */
+
 bool dss_has_feature(enum dss_feat_id id);
 void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
 void dss_features_init(void);
index b0555f4..256f27a 100644 (file)
@@ -29,6 +29,9 @@
 #include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
 #include <video/omapdss.h>
 #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
        defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
@@ -51,6 +54,9 @@ static struct {
        u8 edid_set;
        bool custom_set;
        struct hdmi_config cfg;
+
+       struct clk *sys_clk;
+       struct clk *hdmi_clk;
 } hdmi;
 
 /*
@@ -162,6 +168,27 @@ static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
        return val;
 }
 
+static int hdmi_runtime_get(void)
+{
+       int r;
+
+       DSSDBG("hdmi_runtime_get\n");
+
+       r = pm_runtime_get_sync(&hdmi.pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
+}
+
+static void hdmi_runtime_put(void)
+{
+       int r;
+
+       DSSDBG("hdmi_runtime_put\n");
+
+       r = pm_runtime_put(&hdmi.pdev->dev);
+       WARN_ON(r < 0);
+}
+
 int hdmi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("init_display\n");
@@ -311,30 +338,11 @@ static int hdmi_phy_init(void)
        return 0;
 }
 
-static int hdmi_wait_softreset(void)
-{
-       /* reset W1 */
-       REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0);
-
-       /* wait till SOFTRESET == 0 */
-       if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) {
-               DSSERR("sysconfig reset failed\n");
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
 static int hdmi_pll_program(struct hdmi_pll_info *fmt)
 {
        u16 r = 0;
        enum hdmi_clk_refsel refsel;
 
-       /* wait for wrapper reset */
-       r = hdmi_wait_softreset();
-       if (r)
-               return r;
-
        r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
        if (r)
                return r;
@@ -1064,7 +1072,7 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
        unsigned long clkin, refclk;
        u32 mf;
 
-       clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000;
+       clkin = clk_get_rate(hdmi.sys_clk) / 10000;
        /*
         * Input clock is predivided by N + 1
         * out put of which is reference clk
@@ -1098,16 +1106,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
        DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
 }
 
-static void hdmi_enable_clocks(int enable)
-{
-       if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK |
-                               DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
-       else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK |
-                               DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
-}
-
 static int hdmi_power_on(struct omap_dss_device *dssdev)
 {
        int r, code = 0;
@@ -1115,7 +1113,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
        struct omap_video_timings *p;
        unsigned long phy;
 
-       hdmi_enable_clocks(1);
+       r = hdmi_runtime_get();
+       if (r)
+               return r;
 
        dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
 
@@ -1180,7 +1180,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 
        return 0;
 err:
-       hdmi_enable_clocks(0);
+       hdmi_runtime_put();
        return -EIO;
 }
 
@@ -1191,7 +1191,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
        hdmi_wp_video_start(0);
        hdmi_phy_off();
        hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
-       hdmi_enable_clocks(0);
+       hdmi_runtime_put();
 
        hdmi.edid_set = 0;
 }
@@ -1686,14 +1686,43 @@ static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
 };
 #endif
 
+static int hdmi_get_clocks(struct platform_device *pdev)
+{
+       struct clk *clk;
+
+       clk = clk_get(&pdev->dev, "sys_clk");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get sys_clk\n");
+               return PTR_ERR(clk);
+       }
+
+       hdmi.sys_clk = clk;
+
+       clk = clk_get(&pdev->dev, "dss_48mhz_clk");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get hdmi_clk\n");
+               clk_put(hdmi.sys_clk);
+               return PTR_ERR(clk);
+       }
+
+       hdmi.hdmi_clk = clk;
+
+       return 0;
+}
+
+static void hdmi_put_clocks(void)
+{
+       if (hdmi.sys_clk)
+               clk_put(hdmi.sys_clk);
+       if (hdmi.hdmi_clk)
+               clk_put(hdmi.hdmi_clk);
+}
+
 /* HDMI HW IP initialisation */
 static int omapdss_hdmihw_probe(struct platform_device *pdev)
 {
        struct resource *hdmi_mem;
-#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
-       defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
-       int ret;
-#endif
+       int r;
 
        hdmi.pdata = pdev->dev.platform_data;
        hdmi.pdev = pdev;
@@ -1713,17 +1742,25 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
+       r = hdmi_get_clocks(pdev);
+       if (r) {
+               iounmap(hdmi.base_wp);
+               return r;
+       }
+
+       pm_runtime_enable(&pdev->dev);
+
        hdmi_panel_init();
 
 #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
        defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
 
        /* Register ASoC codec DAI */
-       ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
+       r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
                                        &hdmi_codec_dai_drv, 1);
-       if (ret) {
+       if (r) {
                DSSERR("can't register ASoC HDMI audio codec\n");
-               return ret;
+               return r;
        }
 #endif
        return 0;
@@ -1738,17 +1775,62 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
        snd_soc_unregister_codec(&pdev->dev);
 #endif
 
+       pm_runtime_disable(&pdev->dev);
+
+       hdmi_put_clocks();
+
        iounmap(hdmi.base_wp);
 
        return 0;
 }
 
+static int hdmi_runtime_suspend(struct device *dev)
+{
+       clk_disable(hdmi.hdmi_clk);
+       clk_disable(hdmi.sys_clk);
+
+       dispc_runtime_put();
+       dss_runtime_put();
+
+       return 0;
+}
+
+static int hdmi_runtime_resume(struct device *dev)
+{
+       int r;
+
+       r = dss_runtime_get();
+       if (r < 0)
+               goto err_get_dss;
+
+       r = dispc_runtime_get();
+       if (r < 0)
+               goto err_get_dispc;
+
+
+       clk_enable(hdmi.sys_clk);
+       clk_enable(hdmi.hdmi_clk);
+
+       return 0;
+
+err_get_dispc:
+       dss_runtime_put();
+err_get_dss:
+       return r;
+}
+
+static const struct dev_pm_ops hdmi_pm_ops = {
+       .runtime_suspend = hdmi_runtime_suspend,
+       .runtime_resume = hdmi_runtime_resume,
+};
+
 static struct platform_driver omapdss_hdmihw_driver = {
        .probe          = omapdss_hdmihw_probe,
        .remove         = omapdss_hdmihw_remove,
        .driver         = {
                .name   = "omapdss_hdmi",
                .owner  = THIS_MODULE,
+               .pm     = &hdmi_pm_ops,
        },
 };
 
index 9aeea50..13d72d5 100644 (file)
@@ -275,6 +275,108 @@ static ssize_t manager_alpha_blending_enabled_store(
        return size;
 }
 
+static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
+               char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.cpr_enable);
+}
+
+static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
+               const char *buf, size_t size)
+{
+       struct omap_overlay_manager_info info;
+       int v;
+       int r;
+       bool enable;
+
+       if (!dss_has_feature(FEAT_CPR))
+               return -ENODEV;
+
+       r = kstrtoint(buf, 0, &v);
+       if (r)
+               return r;
+
+       enable = !!v;
+
+       mgr->get_manager_info(mgr, &info);
+
+       if (info.cpr_enable == enable)
+               return size;
+
+       info.cpr_enable = enable;
+
+       r = mgr->set_manager_info(mgr, &info);
+       if (r)
+               return r;
+
+       r = mgr->apply(mgr);
+       if (r)
+               return r;
+
+       return size;
+}
+
+static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
+               char *buf)
+{
+       struct omap_overlay_manager_info info;
+
+       mgr->get_manager_info(mgr, &info);
+
+       return snprintf(buf, PAGE_SIZE,
+                       "%d %d %d %d %d %d %d %d %d\n",
+                       info.cpr_coefs.rr,
+                       info.cpr_coefs.rg,
+                       info.cpr_coefs.rb,
+                       info.cpr_coefs.gr,
+                       info.cpr_coefs.gg,
+                       info.cpr_coefs.gb,
+                       info.cpr_coefs.br,
+                       info.cpr_coefs.bg,
+                       info.cpr_coefs.bb);
+}
+
+static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
+               const char *buf, size_t size)
+{
+       struct omap_overlay_manager_info info;
+       struct omap_dss_cpr_coefs coefs;
+       int r, i;
+       s16 *arr;
+
+       if (!dss_has_feature(FEAT_CPR))
+               return -ENODEV;
+
+       if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
+                               &coefs.rr, &coefs.rg, &coefs.rb,
+                               &coefs.gr, &coefs.gg, &coefs.gb,
+                               &coefs.br, &coefs.bg, &coefs.bb) != 9)
+               return -EINVAL;
+
+       arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
+               coefs.gr, coefs.gg, coefs.gb,
+               coefs.br, coefs.bg, coefs.bb };
+
+       for (i = 0; i < 9; ++i) {
+               if (arr[i] < -512 || arr[i] > 511)
+                       return -EINVAL;
+       }
+
+       mgr->get_manager_info(mgr, &info);
+
+       info.cpr_coefs = coefs;
+
+       r = mgr->set_manager_info(mgr, &info);
+       if (r)
+               return r;
+
+       r = mgr->apply(mgr);
+       if (r)
+               return r;
+
+       return size;
+}
+
 struct manager_attribute {
        struct attribute attr;
        ssize_t (*show)(struct omap_overlay_manager *, char *);
@@ -300,6 +402,12 @@ static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
 static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
                manager_alpha_blending_enabled_show,
                manager_alpha_blending_enabled_store);
+static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
+               manager_cpr_enable_show,
+               manager_cpr_enable_store);
+static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
+               manager_cpr_coef_show,
+               manager_cpr_coef_store);
 
 
 static struct attribute *manager_sysfs_attrs[] = {
@@ -310,6 +418,8 @@ static struct attribute *manager_sysfs_attrs[] = {
        &manager_attr_trans_key_value.attr,
        &manager_attr_trans_key_enabled.attr,
        &manager_attr_alpha_blending_enabled.attr,
+       &manager_attr_cpr_enable.attr,
+       &manager_attr_cpr_coef.attr,
        NULL
 };
 
@@ -391,33 +501,14 @@ struct overlay_cache_data {
 
        bool enabled;
 
-       u32 paddr;
-       void __iomem *vaddr;
-       u32 p_uv_addr; /* relevant for NV12 format only */
-       u16 screen_width;
-       u16 width;
-       u16 height;
-       enum omap_color_mode color_mode;
-       u8 rotation;
-       enum omap_dss_rotation_type rotation_type;
-       bool mirror;
-
-       u16 pos_x;
-       u16 pos_y;
-       u16 out_width;  /* if 0, out_width == width */
-       u16 out_height; /* if 0, out_height == height */
-       u8 global_alpha;
-       u8 pre_mult_alpha;
+       struct omap_overlay_info info;
 
        enum omap_channel channel;
        bool replication;
        bool ilace;
 
-       enum omap_burst_size burst_size;
        u32 fifo_low;
        u32 fifo_high;
-
-       bool manual_update;
 };
 
 struct manager_cache_data {
@@ -429,15 +520,8 @@ struct manager_cache_data {
         * VSYNC/EVSYNC */
        bool shadow_dirty;
 
-       u32 default_color;
-
-       enum omap_dss_trans_key_type trans_key_type;
-       u32 trans_key;
-       bool trans_enabled;
-
-       bool alpha_enabled;
+       struct omap_overlay_manager_info info;
 
-       bool manual_upd_display;
        bool manual_update;
        bool do_manual_update;
 
@@ -539,24 +623,15 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
        if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
+               return 0;
+
        if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
                        || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
                irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
        } else {
-               if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
-                       enum omap_dss_update_mode mode;
-                       mode = dssdev->driver->get_update_mode(dssdev);
-                       if (mode != OMAP_DSS_UPDATE_AUTO)
-                               return 0;
-
-                       irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
-                               DISPC_IRQ_FRAMEDONE
-                               : DISPC_IRQ_FRAMEDONE2;
-               } else {
-                       irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
-                               DISPC_IRQ_VSYNC
-                               : DISPC_IRQ_VSYNC2;
-               }
+               irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
+                       DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
        }
 
        mc = &dss_cache.manager_cache[mgr->id];
@@ -617,24 +692,15 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
        if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
+               return 0;
+
        if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
                        || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
                irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
        } else {
-               if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
-                       enum omap_dss_update_mode mode;
-                       mode = dssdev->driver->get_update_mode(dssdev);
-                       if (mode != OMAP_DSS_UPDATE_AUTO)
-                               return 0;
-
-                       irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
-                               DISPC_IRQ_FRAMEDONE
-                               : DISPC_IRQ_FRAMEDONE2;
-               } else {
-                       irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
-                               DISPC_IRQ_VSYNC
-                               : DISPC_IRQ_VSYNC2;
-               }
+               irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
+                       DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
        }
 
        oc = &dss_cache.overlay_cache[ovl->id];
@@ -720,10 +786,12 @@ static bool rectangle_intersects(int x1, int y1, int w1, int h1,
 
 static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
 {
-       if (oc->out_width != 0 && oc->width != oc->out_width)
+       struct omap_overlay_info *oi = &oc->info;
+
+       if (oi->out_width != 0 && oi->width != oi->out_width)
                return true;
 
-       if (oc->out_height != 0 && oc->height != oc->out_height)
+       if (oi->out_height != 0 && oi->height != oi->out_height)
                return true;
 
        return false;
@@ -733,6 +801,8 @@ static int configure_overlay(enum omap_plane plane)
 {
        struct overlay_cache_data *c;
        struct manager_cache_data *mc;
+       struct omap_overlay_info *oi;
+       struct omap_overlay_manager_info *mi;
        u16 outw, outh;
        u16 x, y, w, h;
        u32 paddr;
@@ -742,6 +812,7 @@ static int configure_overlay(enum omap_plane plane)
        DSSDBGF("%d", plane);
 
        c = &dss_cache.overlay_cache[plane];
+       oi = &c->info;
 
        if (!c->enabled) {
                dispc_enable_plane(plane, 0);
@@ -749,21 +820,22 @@ static int configure_overlay(enum omap_plane plane)
        }
 
        mc = &dss_cache.manager_cache[c->channel];
+       mi = &mc->info;
 
-       x = c->pos_x;
-       y = c->pos_y;
-       w = c->width;
-       h = c->height;
-       outw = c->out_width == 0 ? c->width : c->out_width;
-       outh = c->out_height == 0 ? c->height : c->out_height;
-       paddr = c->paddr;
+       x = oi->pos_x;
+       y = oi->pos_y;
+       w = oi->width;
+       h = oi->height;
+       outw = oi->out_width == 0 ? oi->width : oi->out_width;
+       outh = oi->out_height == 0 ? oi->height : oi->out_height;
+       paddr = oi->paddr;
 
        orig_w = w;
        orig_h = h;
        orig_outw = outw;
        orig_outh = outh;
 
-       if (c->manual_update && mc->do_manual_update) {
+       if (mc->manual_update && mc->do_manual_update) {
                unsigned bpp;
                unsigned scale_x_m = w, scale_x_d = outw;
                unsigned scale_y_m = h, scale_y_d = outh;
@@ -775,7 +847,7 @@ static int configure_overlay(enum omap_plane plane)
                        return 0;
                }
 
-               switch (c->color_mode) {
+               switch (oi->color_mode) {
                case OMAP_DSS_COLOR_NV12:
                        bpp = 8;
                        break;
@@ -805,23 +877,23 @@ static int configure_overlay(enum omap_plane plane)
                        BUG();
                }
 
-               if (mc->x > c->pos_x) {
+               if (mc->x > oi->pos_x) {
                        x = 0;
-                       outw -= (mc->x - c->pos_x);
-                       paddr += (mc->x - c->pos_x) *
+                       outw -= (mc->x - oi->pos_x);
+                       paddr += (mc->x - oi->pos_x) *
                                scale_x_m / scale_x_d * bpp / 8;
                } else {
-                       x = c->pos_x - mc->x;
+                       x = oi->pos_x - mc->x;
                }
 
-               if (mc->y > c->pos_y) {
+               if (mc->y > oi->pos_y) {
                        y = 0;
-                       outh -= (mc->y - c->pos_y);
-                       paddr += (mc->y - c->pos_y) *
+                       outh -= (mc->y - oi->pos_y);
+                       paddr += (mc->y - oi->pos_y) *
                                scale_y_m / scale_y_d *
-                               c->screen_width * bpp / 8;
+                               oi->screen_width * bpp / 8;
                } else {
-                       y = c->pos_y - mc->y;
+                       y = oi->pos_y - mc->y;
                }
 
                if (mc->w < (x + outw))
@@ -840,8 +912,8 @@ static int configure_overlay(enum omap_plane plane)
                 * the width if the original width was bigger.
                 */
                if ((w & 1) &&
-                               (c->color_mode == OMAP_DSS_COLOR_YUV2 ||
-                                c->color_mode == OMAP_DSS_COLOR_UYVY)) {
+                               (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
+                                oi->color_mode == OMAP_DSS_COLOR_UYVY)) {
                        if (orig_w > w)
                                w += 1;
                        else
@@ -851,19 +923,19 @@ static int configure_overlay(enum omap_plane plane)
 
        r = dispc_setup_plane(plane,
                        paddr,
-                       c->screen_width,
+                       oi->screen_width,
                        x, y,
                        w, h,
                        outw, outh,
-                       c->color_mode,
+                       oi->color_mode,
                        c->ilace,
-                       c->rotation_type,
-                       c->rotation,
-                       c->mirror,
-                       c->global_alpha,
-                       c->pre_mult_alpha,
+                       oi->rotation_type,
+                       oi->rotation,
+                       oi->mirror,
+                       oi->global_alpha,
+                       oi->pre_mult_alpha,
                        c->channel,
-                       c->p_uv_addr);
+                       oi->p_uv_addr);
 
        if (r) {
                /* this shouldn't happen */
@@ -874,8 +946,7 @@ static int configure_overlay(enum omap_plane plane)
 
        dispc_enable_replication(plane, c->replication);
 
-       dispc_set_burst_size(plane, c->burst_size);
-       dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high);
+       dispc_set_fifo_threshold(plane, c->fifo_low, c->fifo_high);
 
        dispc_enable_plane(plane, 1);
 
@@ -884,16 +955,21 @@ static int configure_overlay(enum omap_plane plane)
 
 static void configure_manager(enum omap_channel channel)
 {
-       struct manager_cache_data *c;
+       struct omap_overlay_manager_info *mi;
 
        DSSDBGF("%d", channel);
 
-       c = &dss_cache.manager_cache[channel];
+       /* picking info from the cache */
+       mi = &dss_cache.manager_cache[channel].info;
 
-       dispc_set_default_color(channel, c->default_color);
-       dispc_set_trans_key(channel, c->trans_key_type, c->trans_key);
-       dispc_enable_trans_key(channel, c->trans_enabled);
-       dispc_enable_alpha_blending(channel, c->alpha_enabled);
+       dispc_set_default_color(channel, mi->default_color);
+       dispc_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
+       dispc_enable_trans_key(channel, mi->trans_enabled);
+       dispc_enable_alpha_blending(channel, mi->alpha_enabled);
+       if (dss_has_feature(FEAT_CPR)) {
+               dispc_enable_cpr(channel, mi->cpr_enable);
+               dispc_set_cpr_coef(channel, &mi->cpr_coefs);
+       }
 }
 
 /* configure_dispc() tries to write values from cache to shadow registers.
@@ -928,7 +1004,7 @@ static int configure_dispc(void)
                if (!oc->dirty)
                        continue;
 
-               if (oc->manual_update && !mc->do_manual_update)
+               if (mc->manual_update && !mc->do_manual_update)
                        continue;
 
                if (mgr_busy[oc->channel]) {
@@ -976,7 +1052,7 @@ static int configure_dispc(void)
                /* We don't need GO with manual update display. LCD iface will
                 * always be turned off after frame, and new settings will be
                 * taken in to use at next update */
-               if (!mc->manual_upd_display)
+               if (!mc->manual_update)
                        dispc_go(i);
        }
 
@@ -1011,6 +1087,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
 {
        struct overlay_cache_data *oc;
        struct manager_cache_data *mc;
+       struct omap_overlay_info *oi;
        const int num_ovls = dss_feat_get_num_ovls();
        struct omap_overlay_manager *mgr;
        int i;
@@ -1053,6 +1130,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
                        unsigned outw, outh;
 
                        oc = &dss_cache.overlay_cache[i];
+                       oi = &oc->info;
 
                        if (oc->channel != mgr->id)
                                continue;
@@ -1068,39 +1146,39 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
                        if (!dispc_is_overlay_scaled(oc))
                                continue;
 
-                       outw = oc->out_width == 0 ?
-                               oc->width : oc->out_width;
-                       outh = oc->out_height == 0 ?
-                               oc->height : oc->out_height;
+                       outw = oi->out_width == 0 ?
+                               oi->width : oi->out_width;
+                       outh = oi->out_height == 0 ?
+                               oi->height : oi->out_height;
 
                        /* is the overlay outside the update region? */
                        if (!rectangle_intersects(x, y, w, h,
-                                               oc->pos_x, oc->pos_y,
+                                               oi->pos_x, oi->pos_y,
                                                outw, outh))
                                continue;
 
                        /* if the overlay totally inside the update region? */
-                       if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
+                       if (rectangle_subset(oi->pos_x, oi->pos_y, outw, outh,
                                                x, y, w, h))
                                continue;
 
-                       if (x > oc->pos_x)
-                               x1 = oc->pos_x;
+                       if (x > oi->pos_x)
+                               x1 = oi->pos_x;
                        else
                                x1 = x;
 
-                       if (y > oc->pos_y)
-                               y1 = oc->pos_y;
+                       if (y > oi->pos_y)
+                               y1 = oi->pos_y;
                        else
                                y1 = y;
 
-                       if ((x + w) < (oc->pos_x + outw))
-                               x2 = oc->pos_x + outw;
+                       if ((x + w) < (oi->pos_x + outw))
+                               x2 = oi->pos_x + outw;
                        else
                                x2 = x + w;
 
-                       if ((y + h) < (oc->pos_y + outh))
-                               y2 = oc->pos_y + outh;
+                       if ((y + h) < (oi->pos_y + outh))
+                               y2 = oi->pos_y + outh;
                        else
                                y2 = y + h;
 
@@ -1236,6 +1314,10 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
        DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
 
+       r = dispc_runtime_get();
+       if (r)
+               return r;
+
        spin_lock_irqsave(&dss_cache.lock, flags);
 
        /* Configure overlays */
@@ -1275,23 +1357,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
                ovl->info_dirty = false;
                oc->dirty = true;
-
-               oc->paddr = ovl->info.paddr;
-               oc->vaddr = ovl->info.vaddr;
-               oc->p_uv_addr = ovl->info.p_uv_addr;
-               oc->screen_width = ovl->info.screen_width;
-               oc->width = ovl->info.width;
-               oc->height = ovl->info.height;
-               oc->color_mode = ovl->info.color_mode;
-               oc->rotation = ovl->info.rotation;
-               oc->rotation_type = ovl->info.rotation_type;
-               oc->mirror = ovl->info.mirror;
-               oc->pos_x = ovl->info.pos_x;
-               oc->pos_y = ovl->info.pos_y;
-               oc->out_width = ovl->info.out_width;
-               oc->out_height = ovl->info.out_height;
-               oc->global_alpha = ovl->info.global_alpha;
-               oc->pre_mult_alpha = ovl->info.pre_mult_alpha;
+               oc->info = ovl->info;
 
                oc->replication =
                        dss_use_replication(dssdev, ovl->info.color_mode);
@@ -1302,11 +1368,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
                oc->enabled = true;
 
-               oc->manual_update =
-                       dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
-                       dssdev->driver->get_update_mode(dssdev) !=
-                               OMAP_DSS_UPDATE_AUTO;
-
                ++num_planes_enabled;
        }
 
@@ -1334,20 +1395,10 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
                mgr->info_dirty = false;
                mc->dirty = true;
-
-               mc->default_color = mgr->info.default_color;
-               mc->trans_key_type = mgr->info.trans_key_type;
-               mc->trans_key = mgr->info.trans_key;
-               mc->trans_enabled = mgr->info.trans_enabled;
-               mc->alpha_enabled = mgr->info.alpha_enabled;
-
-               mc->manual_upd_display =
-                       dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+               mc->info = mgr->info;
 
                mc->manual_update =
-                       dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
-                       dssdev->driver->get_update_mode(dssdev) !=
-                               OMAP_DSS_UPDATE_AUTO;
+                       dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
        }
 
        /* XXX TODO: Try to get fifomerge working. The problem is that it
@@ -1368,7 +1419,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
        /* Configure overlay fifos */
        for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
                struct omap_dss_device *dssdev;
-               u32 size;
+               u32 size, burst_size;
 
                ovl = omap_dss_get_overlay(i);
 
@@ -1386,6 +1437,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
                if (use_fifomerge)
                        size *= 3;
 
+               burst_size = dispc_get_burst_size(ovl->id);
+
                switch (dssdev->type) {
                case OMAP_DISPLAY_TYPE_DPI:
                case OMAP_DISPLAY_TYPE_DBI:
@@ -1393,13 +1446,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
                case OMAP_DISPLAY_TYPE_VENC:
                case OMAP_DISPLAY_TYPE_HDMI:
                        default_get_overlay_fifo_thresholds(ovl->id, size,
-                                       &oc->burst_size, &oc->fifo_low,
+                                       burst_size, &oc->fifo_low,
                                        &oc->fifo_high);
                        break;
 #ifdef CONFIG_OMAP2_DSS_DSI
                case OMAP_DISPLAY_TYPE_DSI:
                        dsi_get_overlay_fifo_thresholds(ovl->id, size,
-                                       &oc->burst_size, &oc->fifo_low,
+                                       burst_size, &oc->fifo_low,
                                        &oc->fifo_high);
                        break;
 #endif
@@ -1409,7 +1462,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
        }
 
        r = 0;
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
        if (!dss_cache.irq_enabled) {
                u32 mask;
 
@@ -1422,10 +1474,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
                dss_cache.irq_enabled = true;
        }
        configure_dispc();
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        spin_unlock_irqrestore(&dss_cache.lock, flags);
 
+       dispc_runtime_put();
+
        return r;
 }
 
index 0f08025..c84380c 100644 (file)
@@ -84,32 +84,42 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
 
        old_mgr = ovl->manager;
 
+       r = dispc_runtime_get();
+       if (r)
+               return r;
+
        /* detach old manager */
        if (old_mgr) {
                r = ovl->unset_manager(ovl);
                if (r) {
                        DSSERR("detach failed\n");
-                       return r;
+                       goto err;
                }
 
                r = old_mgr->apply(old_mgr);
                if (r)
-                       return r;
+                       goto err;
        }
 
        if (mgr) {
                r = ovl->set_manager(ovl, mgr);
                if (r) {
                        DSSERR("Failed to attach overlay\n");
-                       return r;
+                       goto err;
                }
 
                r = mgr->apply(mgr);
                if (r)
-                       return r;
+                       goto err;
        }
 
+       dispc_runtime_put();
+
        return size;
+
+err:
+       dispc_runtime_put();
+       return r;
 }
 
 static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
@@ -238,6 +248,9 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
        u8 alpha;
        struct omap_overlay_info info;
 
+       if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+               return -ENODEV;
+
        r = kstrtou8(buf, 0, &alpha);
        if (r)
                return r;
@@ -504,7 +517,6 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
 
        ovl->manager = mgr;
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
        /* XXX: When there is an overlay on a DSI manual update display, and
         * the overlay is first disabled, then moved to tv, and enabled, we
         * seem to get SYNC_LOST_DIGIT error.
@@ -518,7 +530,6 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
         * the overlay, but before moving the overlay to TV.
         */
        dispc_set_channel_out(ovl->id, mgr->id);
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        return 0;
 }
@@ -719,6 +730,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
        }
 
        if (mgr) {
+               dispc_runtime_get();
+
                for (i = 0; i < dss_feat_get_num_ovls(); i++) {
                        struct omap_overlay *ovl;
                        ovl = omap_dss_get_overlay(i);
@@ -728,6 +741,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
                                omap_dss_set_manager(ovl, mgr);
                        }
                }
+
+               dispc_runtime_put();
        }
 }
 
index c06fbe0..39f4c59 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/hrtimer.h>
 #include <linux/seq_file.h>
 #include <linux/semaphore.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include "dss.h"
@@ -120,12 +122,25 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
        return __raw_readl(rfbi.base + idx.idx);
 }
 
-static void rfbi_enable_clocks(bool enable)
+static int rfbi_runtime_get(void)
 {
-       if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-       else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       int r;
+
+       DSSDBG("rfbi_runtime_get\n");
+
+       r = pm_runtime_get_sync(&rfbi.pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
+}
+
+static void rfbi_runtime_put(void)
+{
+       int r;
+
+       DSSDBG("rfbi_runtime_put\n");
+
+       r = pm_runtime_put(&rfbi.pdev->dev);
+       WARN_ON(r < 0);
 }
 
 void rfbi_bus_lock(void)
@@ -805,7 +820,8 @@ void rfbi_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       if (rfbi_runtime_get())
+               return;
 
        DUMPREG(RFBI_REVISION);
        DUMPREG(RFBI_SYSCONFIG);
@@ -836,7 +852,7 @@ void rfbi_dump_regs(struct seq_file *s)
        DUMPREG(RFBI_VSYNC_WIDTH);
        DUMPREG(RFBI_HSYNC_WIDTH);
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       rfbi_runtime_put();
 #undef DUMPREG
 }
 
@@ -844,7 +860,9 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 {
        int r;
 
-       rfbi_enable_clocks(1);
+       r = rfbi_runtime_get();
+       if (r)
+               return r;
 
        r = omap_dss_start_device(dssdev);
        if (r) {
@@ -879,6 +897,7 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 err1:
        omap_dss_stop_device(dssdev);
 err0:
+       rfbi_runtime_put();
        return r;
 }
 EXPORT_SYMBOL(omapdss_rfbi_display_enable);
@@ -889,7 +908,7 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
                        DISPC_IRQ_FRAMEDONE);
        omap_dss_stop_device(dssdev);
 
-       rfbi_enable_clocks(0);
+       rfbi_runtime_put();
 }
 EXPORT_SYMBOL(omapdss_rfbi_display_disable);
 
@@ -904,8 +923,9 @@ int rfbi_init_display(struct omap_dss_device *dssdev)
 static int omap_rfbihw_probe(struct platform_device *pdev)
 {
        u32 rev;
-       u32 l;
        struct resource *rfbi_mem;
+       struct clk *clk;
+       int r;
 
        rfbi.pdev = pdev;
 
@@ -914,46 +934,102 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
        rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
        if (!rfbi_mem) {
                DSSERR("can't get IORESOURCE_MEM RFBI\n");
-               return -EINVAL;
+               r = -EINVAL;
+               goto err_ioremap;
        }
        rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
        if (!rfbi.base) {
                DSSERR("can't ioremap RFBI\n");
-               return -ENOMEM;
+               r = -ENOMEM;
+               goto err_ioremap;
        }
 
-       rfbi_enable_clocks(1);
+       pm_runtime_enable(&pdev->dev);
+
+       r = rfbi_runtime_get();
+       if (r)
+               goto err_get_rfbi;
 
        msleep(10);
 
-       rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
+       if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630())
+               clk = dss_get_ick();
+       else
+               clk = clk_get(&pdev->dev, "ick");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get ick\n");
+               r = PTR_ERR(clk);
+               goto err_get_ick;
+       }
+
+       rfbi.l4_khz = clk_get_rate(clk) / 1000;
 
-       /* Enable autoidle and smart-idle */
-       l = rfbi_read_reg(RFBI_SYSCONFIG);
-       l |= (1 << 0) | (2 << 3);
-       rfbi_write_reg(RFBI_SYSCONFIG, l);
+       clk_put(clk);
 
        rev = rfbi_read_reg(RFBI_REVISION);
        dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
               FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
-       rfbi_enable_clocks(0);
+       rfbi_runtime_put();
 
        return 0;
+
+err_get_ick:
+       rfbi_runtime_put();
+err_get_rfbi:
+       pm_runtime_disable(&pdev->dev);
+       iounmap(rfbi.base);
+err_ioremap:
+       return r;
 }
 
 static int omap_rfbihw_remove(struct platform_device *pdev)
 {
+       pm_runtime_disable(&pdev->dev);
        iounmap(rfbi.base);
        return 0;
 }
 
+static int rfbi_runtime_suspend(struct device *dev)
+{
+       dispc_runtime_put();
+       dss_runtime_put();
+
+       return 0;
+}
+
+static int rfbi_runtime_resume(struct device *dev)
+{
+       int r;
+
+       r = dss_runtime_get();
+       if (r < 0)
+               goto err_get_dss;
+
+       r = dispc_runtime_get();
+       if (r < 0)
+               goto err_get_dispc;
+
+       return 0;
+
+err_get_dispc:
+       dss_runtime_put();
+err_get_dss:
+       return r;
+}
+
+static const struct dev_pm_ops rfbi_pm_ops = {
+       .runtime_suspend = rfbi_runtime_suspend,
+       .runtime_resume = rfbi_runtime_resume,
+};
+
 static struct platform_driver omap_rfbihw_driver = {
        .probe          = omap_rfbihw_probe,
        .remove         = omap_rfbihw_remove,
        .driver         = {
                .name   = "omapdss_rfbi",
                .owner  = THIS_MODULE,
+               .pm     = &rfbi_pm_ops,
        },
 };
 
index 0bd4b03..3a688c8 100644 (file)
 #define DSS_SUBSYS_NAME "SDI"
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
 
 #include <video/omapdss.h>
-#include <plat/cpu.h>
 #include "dss.h"
 
 static struct {
@@ -60,14 +58,20 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
-               goto err0;
+               goto err_start_dev;
        }
 
        r = regulator_enable(sdi.vdds_sdi_reg);
        if (r)
-               goto err1;
+               goto err_reg_enable;
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       r = dss_runtime_get();
+       if (r)
+               goto err_get_dss;
+
+       r = dispc_runtime_get();
+       if (r)
+               goto err_get_dispc;
 
        sdi_basic_init(dssdev);
 
@@ -80,7 +84,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        r = dss_calc_clock_div(1, t->pixel_clock * 1000,
                        &dss_cinfo, &dispc_cinfo);
        if (r)
-               goto err2;
+               goto err_calc_clock_div;
 
        fck = dss_cinfo.fck;
        lck_div = dispc_cinfo.lck_div;
@@ -101,27 +105,34 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 
        r = dss_set_clock_div(&dss_cinfo);
        if (r)
-               goto err2;
+               goto err_set_dss_clock_div;
 
        r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
        if (r)
-               goto err2;
+               goto err_set_dispc_clock_div;
 
        dss_sdi_init(dssdev->phy.sdi.datapairs);
        r = dss_sdi_enable();
        if (r)
-               goto err1;
+               goto err_sdi_enable;
        mdelay(2);
 
        dssdev->manager->enable(dssdev->manager);
 
        return 0;
-err2:
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+
+err_sdi_enable:
+err_set_dispc_clock_div:
+err_set_dss_clock_div:
+err_calc_clock_div:
+       dispc_runtime_put();
+err_get_dispc:
+       dss_runtime_put();
+err_get_dss:
        regulator_disable(sdi.vdds_sdi_reg);
-err1:
+err_reg_enable:
        omap_dss_stop_device(dssdev);
-err0:
+err_start_dev:
        return r;
 }
 EXPORT_SYMBOL(omapdss_sdi_display_enable);
@@ -132,7 +143,8 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
 
        dss_sdi_disable();
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       dispc_runtime_put();
+       dss_runtime_put();
 
        regulator_disable(sdi.vdds_sdi_reg);
 
index 980f919..173c664 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include <plat/cpu.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 /* Venc registers */
 #define VENC_REV_ID                            0x00
@@ -292,6 +294,9 @@ static struct {
        struct mutex venc_lock;
        u32 wss_data;
        struct regulator *vdda_dac_reg;
+
+       struct clk      *tv_clk;
+       struct clk      *tv_dac_clk;
 } venc;
 
 static inline void venc_write_reg(int idx, u32 val)
@@ -380,14 +385,25 @@ static void venc_reset(void)
 #endif
 }
 
-static void venc_enable_clocks(int enable)
+static int venc_runtime_get(void)
+{
+       int r;
+
+       DSSDBG("venc_runtime_get\n");
+
+       r = pm_runtime_get_sync(&venc.pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
+}
+
+static void venc_runtime_put(void)
 {
-       if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
-                               DSS_CLK_VIDFCK);
-       else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
-                               DSS_CLK_VIDFCK);
+       int r;
+
+       DSSDBG("venc_runtime_put\n");
+
+       r = pm_runtime_put(&venc.pdev->dev);
+       WARN_ON(r < 0);
 }
 
 static const struct venc_config *venc_timings_to_config(
@@ -406,8 +422,6 @@ static void venc_power_on(struct omap_dss_device *dssdev)
 {
        u32 l;
 
-       venc_enable_clocks(1);
-
        venc_reset();
        venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
 
@@ -448,8 +462,6 @@ static void venc_power_off(struct omap_dss_device *dssdev)
                dssdev->platform_disable(dssdev);
 
        regulator_disable(venc.vdda_dac_reg);
-
-       venc_enable_clocks(0);
 }
 
 
@@ -487,6 +499,10 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
                goto err1;
        }
 
+       r = venc_runtime_get();
+       if (r)
+               goto err1;
+
        venc_power_on(dssdev);
 
        venc.wss_data = 0;
@@ -520,6 +536,8 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
 
        venc_power_off(dssdev);
 
+       venc_runtime_put();
+
        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 
        omap_dss_stop_device(dssdev);
@@ -538,20 +556,6 @@ static int venc_panel_resume(struct omap_dss_device *dssdev)
        return venc_panel_enable(dssdev);
 }
 
-static enum omap_dss_update_mode venc_get_update_mode(
-               struct omap_dss_device *dssdev)
-{
-       return OMAP_DSS_UPDATE_AUTO;
-}
-
-static int venc_set_update_mode(struct omap_dss_device *dssdev,
-               enum omap_dss_update_mode mode)
-{
-       if (mode != OMAP_DSS_UPDATE_AUTO)
-               return -EINVAL;
-       return 0;
-}
-
 static void venc_get_timings(struct omap_dss_device *dssdev,
                        struct omap_video_timings *timings)
 {
@@ -598,6 +602,7 @@ static u32 venc_get_wss(struct omap_dss_device *dssdev)
 static int venc_set_wss(struct omap_dss_device *dssdev,        u32 wss)
 {
        const struct venc_config *config;
+       int r;
 
        DSSDBG("venc_set_wss\n");
 
@@ -608,16 +613,19 @@ static int venc_set_wss(struct omap_dss_device *dssdev,   u32 wss)
        /* Invert due to VENC_L21_WC_CTL:INV=1 */
        venc.wss_data = (wss ^ 0xfffff) << 8;
 
-       venc_enable_clocks(1);
+       r = venc_runtime_get();
+       if (r)
+               goto err;
 
        venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
                        venc.wss_data);
 
-       venc_enable_clocks(0);
+       venc_runtime_put();
 
+err:
        mutex_unlock(&venc.venc_lock);
 
-       return 0;
+       return r;
 }
 
 static struct omap_dss_driver venc_driver = {
@@ -632,9 +640,6 @@ static struct omap_dss_driver venc_driver = {
        .get_resolution = omapdss_default_get_resolution,
        .get_recommended_bpp = omapdss_default_get_recommended_bpp,
 
-       .set_update_mode = venc_set_update_mode,
-       .get_update_mode = venc_get_update_mode,
-
        .get_timings    = venc_get_timings,
        .set_timings    = venc_set_timings,
        .check_timings  = venc_check_timings,
@@ -673,7 +678,8 @@ void venc_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
 
-       venc_enable_clocks(1);
+       if (venc_runtime_get())
+               return;
 
        DUMPREG(VENC_F_CONTROL);
        DUMPREG(VENC_VIDOUT_CTRL);
@@ -717,16 +723,56 @@ void venc_dump_regs(struct seq_file *s)
        DUMPREG(VENC_OUTPUT_CONTROL);
        DUMPREG(VENC_OUTPUT_TEST);
 
-       venc_enable_clocks(0);
+       venc_runtime_put();
 
 #undef DUMPREG
 }
 
+static int venc_get_clocks(struct platform_device *pdev)
+{
+       struct clk *clk;
+
+       clk = clk_get(&pdev->dev, "fck");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get fck\n");
+               return PTR_ERR(clk);
+       }
+
+       venc.tv_clk = clk;
+
+       if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
+               if (cpu_is_omap34xx() || cpu_is_omap3630())
+                       clk = clk_get(&pdev->dev, "dss_96m_fck");
+               else
+                       clk = clk_get(&pdev->dev, "tv_dac_clk");
+               if (IS_ERR(clk)) {
+                       DSSERR("can't get tv_dac_clk\n");
+                       clk_put(venc.tv_clk);
+                       return PTR_ERR(clk);
+               }
+       } else {
+               clk = NULL;
+       }
+
+       venc.tv_dac_clk = clk;
+
+       return 0;
+}
+
+static void venc_put_clocks(void)
+{
+       if (venc.tv_clk)
+               clk_put(venc.tv_clk);
+       if (venc.tv_dac_clk)
+               clk_put(venc.tv_dac_clk);
+}
+
 /* VENC HW IP initialisation */
 static int omap_venchw_probe(struct platform_device *pdev)
 {
        u8 rev_id;
        struct resource *venc_mem;
+       int r;
 
        venc.pdev = pdev;
 
@@ -737,22 +783,40 @@ static int omap_venchw_probe(struct platform_device *pdev)
        venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
        if (!venc_mem) {
                DSSERR("can't get IORESOURCE_MEM VENC\n");
-               return -EINVAL;
+               r = -EINVAL;
+               goto err_ioremap;
        }
        venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
        if (!venc.base) {
                DSSERR("can't ioremap VENC\n");
-               return -ENOMEM;
+               r = -ENOMEM;
+               goto err_ioremap;
        }
 
-       venc_enable_clocks(1);
+       r = venc_get_clocks(pdev);
+       if (r)
+               goto err_get_clk;
+
+       pm_runtime_enable(&pdev->dev);
+
+       r = venc_runtime_get();
+       if (r)
+               goto err_get_venc;
 
        rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
        dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
 
-       venc_enable_clocks(0);
+       venc_runtime_put();
 
        return omap_dss_register_driver(&venc_driver);
+
+err_get_venc:
+       pm_runtime_disable(&pdev->dev);
+       venc_put_clocks();
+err_get_clk:
+       iounmap(venc.base);
+err_ioremap:
+       return r;
 }
 
 static int omap_venchw_remove(struct platform_device *pdev)
@@ -763,16 +827,61 @@ static int omap_venchw_remove(struct platform_device *pdev)
        }
        omap_dss_unregister_driver(&venc_driver);
 
+       pm_runtime_disable(&pdev->dev);
+       venc_put_clocks();
+
        iounmap(venc.base);
        return 0;
 }
 
+static int venc_runtime_suspend(struct device *dev)
+{
+       if (venc.tv_dac_clk)
+               clk_disable(venc.tv_dac_clk);
+       clk_disable(venc.tv_clk);
+
+       dispc_runtime_put();
+       dss_runtime_put();
+
+       return 0;
+}
+
+static int venc_runtime_resume(struct device *dev)
+{
+       int r;
+
+       r = dss_runtime_get();
+       if (r < 0)
+               goto err_get_dss;
+
+       r = dispc_runtime_get();
+       if (r < 0)
+               goto err_get_dispc;
+
+       clk_enable(venc.tv_clk);
+       if (venc.tv_dac_clk)
+               clk_enable(venc.tv_dac_clk);
+
+       return 0;
+
+err_get_dispc:
+       dss_runtime_put();
+err_get_dss:
+       return r;
+}
+
+static const struct dev_pm_ops venc_pm_ops = {
+       .runtime_suspend = venc_runtime_suspend,
+       .runtime_resume = venc_runtime_resume,
+};
+
 static struct platform_driver omap_venchw_driver = {
        .probe          = omap_venchw_probe,
        .remove         = omap_venchw_remove,
        .driver         = {
                .name   = "omapdss_venc",
                .owner  = THIS_MODULE,
+               .pm     = &venc_pm_ops,
        },
 };
 
index cff4503..6b1ac23 100644 (file)
@@ -316,67 +316,67 @@ int omapfb_update_window(struct fb_info *fbi,
 }
 EXPORT_SYMBOL(omapfb_update_window);
 
-static int omapfb_set_update_mode(struct fb_info *fbi,
+int omapfb_set_update_mode(struct fb_info *fbi,
                                   enum omapfb_update_mode mode)
 {
        struct omap_dss_device *display = fb2display(fbi);
-       enum omap_dss_update_mode um;
+       struct omapfb_info *ofbi = FB2OFB(fbi);
+       struct omapfb2_device *fbdev = ofbi->fbdev;
+       struct omapfb_display_data *d;
        int r;
 
-       if (!display || !display->driver->set_update_mode)
+       if (!display)
                return -EINVAL;
 
-       switch (mode) {
-       case OMAPFB_UPDATE_DISABLED:
-               um = OMAP_DSS_UPDATE_DISABLED;
-               break;
+       if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE)
+               return -EINVAL;
 
-       case OMAPFB_AUTO_UPDATE:
-               um = OMAP_DSS_UPDATE_AUTO;
-               break;
+       omapfb_lock(fbdev);
 
-       case OMAPFB_MANUAL_UPDATE:
-               um = OMAP_DSS_UPDATE_MANUAL;
-               break;
+       d = get_display_data(fbdev, display);
 
-       default:
-               return -EINVAL;
+       if (d->update_mode == mode) {
+               omapfb_unlock(fbdev);
+               return 0;
        }
 
-       r = display->driver->set_update_mode(display, um);
+       r = 0;
+
+       if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+               if (mode == OMAPFB_AUTO_UPDATE)
+                       omapfb_start_auto_update(fbdev, display);
+               else /* MANUAL_UPDATE */
+                       omapfb_stop_auto_update(fbdev, display);
+
+               d->update_mode = mode;
+       } else { /* AUTO_UPDATE */
+               if (mode == OMAPFB_MANUAL_UPDATE)
+                       r = -EINVAL;
+       }
+
+       omapfb_unlock(fbdev);
 
        return r;
 }
 
-static int omapfb_get_update_mode(struct fb_info *fbi,
+int omapfb_get_update_mode(struct fb_info *fbi,
                enum omapfb_update_mode *mode)
 {
        struct omap_dss_device *display = fb2display(fbi);
-       enum omap_dss_update_mode m;
+       struct omapfb_info *ofbi = FB2OFB(fbi);
+       struct omapfb2_device *fbdev = ofbi->fbdev;
+       struct omapfb_display_data *d;
 
        if (!display)
                return -EINVAL;
 
-       if (!display->driver->get_update_mode) {
-               *mode = OMAPFB_AUTO_UPDATE;
-               return 0;
-       }
+       omapfb_lock(fbdev);
 
-       m = display->driver->get_update_mode(display);
+       d = get_display_data(fbdev, display);
 
-       switch (m) {
-       case OMAP_DSS_UPDATE_DISABLED:
-               *mode = OMAPFB_UPDATE_DISABLED;
-               break;
-       case OMAP_DSS_UPDATE_AUTO:
-               *mode = OMAPFB_AUTO_UPDATE;
-               break;
-       case OMAP_DSS_UPDATE_MANUAL:
-               *mode = OMAPFB_MANUAL_UPDATE;
-               break;
-       default:
-               BUG();
-       }
+       *mode = d->update_mode;
+
+       omapfb_unlock(fbdev);
 
        return 0;
 }
index 505bc12..602b71a 100644 (file)
@@ -46,6 +46,10 @@ static char *def_vram;
 static int def_vrfb;
 static int def_rotate;
 static int def_mirror;
+static bool auto_update;
+static unsigned int auto_update_freq;
+module_param(auto_update, bool, 0);
+module_param(auto_update_freq, uint, 0644);
 
 #ifdef DEBUG
 unsigned int omapfb_debug;
@@ -1242,6 +1246,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
        struct omapfb_info *ofbi = FB2OFB(fbi);
        struct omapfb2_device *fbdev = ofbi->fbdev;
        struct omap_dss_device *display = fb2display(fbi);
+       struct omapfb_display_data *d;
        int r = 0;
 
        if (!display)
@@ -1249,6 +1254,8 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
 
        omapfb_lock(fbdev);
 
+       d = get_display_data(fbdev, display);
+
        switch (blank) {
        case FB_BLANK_UNBLANK:
                if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
@@ -1257,6 +1264,11 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
                if (display->driver->resume)
                        r = display->driver->resume(display);
 
+               if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
+                               d->update_mode == OMAPFB_AUTO_UPDATE &&
+                               !d->auto_update_work_enabled)
+                       omapfb_start_auto_update(fbdev, display);
+
                break;
 
        case FB_BLANK_NORMAL:
@@ -1268,6 +1280,9 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
                if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
                        goto exit;
 
+               if (d->auto_update_work_enabled)
+                       omapfb_stop_auto_update(fbdev, display);
+
                if (display->driver->suspend)
                        r = display->driver->suspend(display);
 
@@ -1724,6 +1739,78 @@ err:
        return r;
 }
 
+static void omapfb_auto_update_work(struct work_struct *work)
+{
+       struct omap_dss_device *dssdev;
+       struct omap_dss_driver *dssdrv;
+       struct omapfb_display_data *d;
+       u16 w, h;
+       unsigned int freq;
+       struct omapfb2_device *fbdev;
+
+       d = container_of(work, struct omapfb_display_data,
+                       auto_update_work.work);
+
+       dssdev = d->dssdev;
+       dssdrv = dssdev->driver;
+       fbdev = d->fbdev;
+
+       if (!dssdrv || !dssdrv->update)
+               return;
+
+       if (dssdrv->sync)
+               dssdrv->sync(dssdev);
+
+       dssdrv->get_resolution(dssdev, &w, &h);
+       dssdrv->update(dssdev, 0, 0, w, h);
+
+       freq = auto_update_freq;
+       if (freq == 0)
+               freq = 20;
+       queue_delayed_work(fbdev->auto_update_wq,
+                       &d->auto_update_work, HZ / freq);
+}
+
+void omapfb_start_auto_update(struct omapfb2_device *fbdev,
+               struct omap_dss_device *display)
+{
+       struct omapfb_display_data *d;
+
+       if (fbdev->auto_update_wq == NULL) {
+               struct workqueue_struct *wq;
+
+               wq = create_singlethread_workqueue("omapfb_auto_update");
+
+               if (wq == NULL) {
+                       dev_err(fbdev->dev, "Failed to create workqueue for "
+                                       "auto-update\n");
+                       return;
+               }
+
+               fbdev->auto_update_wq = wq;
+       }
+
+       d = get_display_data(fbdev, display);
+
+       INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
+
+       d->auto_update_work_enabled = true;
+
+       omapfb_auto_update_work(&d->auto_update_work.work);
+}
+
+void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
+               struct omap_dss_device *display)
+{
+       struct omapfb_display_data *d;
+
+       d = get_display_data(fbdev, display);
+
+       cancel_delayed_work_sync(&d->auto_update_work);
+
+       d->auto_update_work_enabled = false;
+}
+
 /* initialize fb_info, var, fix to something sane based on the display */
 static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
 {
@@ -1858,10 +1945,21 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
        }
 
        for (i = 0; i < fbdev->num_displays; i++) {
-               if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
-                       fbdev->displays[i]->driver->disable(fbdev->displays[i]);
+               struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
+
+               if (fbdev->displays[i].auto_update_work_enabled)
+                       omapfb_stop_auto_update(fbdev, dssdev);
+
+               if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
+                       dssdev->driver->disable(dssdev);
+
+               omap_dss_put_device(dssdev);
+       }
 
-               omap_dss_put_device(fbdev->displays[i]);
+       if (fbdev->auto_update_wq != NULL) {
+               flush_workqueue(fbdev->auto_update_wq);
+               destroy_workqueue(fbdev->auto_update_wq);
+               fbdev->auto_update_wq = NULL;
        }
 
        dev_set_drvdata(fbdev->dev, NULL);
@@ -2084,14 +2182,14 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
        int r;
        u8 bpp;
        struct omap_video_timings timings, temp_timings;
+       struct omapfb_display_data *d;
 
        r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
        if (r)
                return r;
 
-       fbdev->bpp_overrides[fbdev->num_bpp_overrides].dssdev = display;
-       fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp;
-       ++fbdev->num_bpp_overrides;
+       d = get_display_data(fbdev, display);
+       d->bpp_override = bpp;
 
        if (display->driver->check_timings) {
                r = display->driver->check_timings(display, &timings);
@@ -2117,14 +2215,14 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
 static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
                struct omap_dss_device *dssdev)
 {
-       int i;
+       struct omapfb_display_data *d;
 
        BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
 
-       for (i = 0; i < fbdev->num_bpp_overrides; ++i) {
-               if (dssdev == fbdev->bpp_overrides[i].dssdev)
-                       return fbdev->bpp_overrides[i].bpp;
-       }
+       d = get_display_data(fbdev, dssdev);
+
+       if (d->bpp_override != 0)
+               return d->bpp_override;
 
        return dssdev->driver->get_recommended_bpp(dssdev);
 }
@@ -2156,9 +2254,9 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
 
                display = NULL;
                for (i = 0; i < fbdev->num_displays; ++i) {
-                       if (strcmp(fbdev->displays[i]->name,
+                       if (strcmp(fbdev->displays[i].dssdev->name,
                                                display_str) == 0) {
-                               display = fbdev->displays[i];
+                               display = fbdev->displays[i].dssdev;
                                break;
                        }
                }
@@ -2182,6 +2280,7 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
                struct omap_dss_device *dssdev)
 {
        struct omap_dss_driver *dssdrv = dssdev->driver;
+       struct omapfb_display_data *d;
        int r;
 
        r = dssdrv->enable(dssdev);
@@ -2191,8 +2290,20 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
                return r;
        }
 
+       d = get_display_data(fbdev, dssdev);
+
+       d->fbdev = fbdev;
+
        if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
                u16 w, h;
+
+               if (auto_update) {
+                       omapfb_start_auto_update(fbdev, dssdev);
+                       d->update_mode = OMAPFB_AUTO_UPDATE;
+               } else {
+                       d->update_mode = OMAPFB_MANUAL_UPDATE;
+               }
+
                if (dssdrv->enable_te) {
                        r = dssdrv->enable_te(dssdev, 1);
                        if (r) {
@@ -2201,16 +2312,6 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
                        }
                }
 
-               if (dssdrv->set_update_mode) {
-                       r = dssdrv->set_update_mode(dssdev,
-                                       OMAP_DSS_UPDATE_MANUAL);
-                       if (r) {
-                               dev_err(fbdev->dev,
-                                               "Failed to set update mode\n");
-                               return r;
-                       }
-               }
-
                dssdrv->get_resolution(dssdev, &w, &h);
                r = dssdrv->update(dssdev, 0, 0, w, h);
                if (r) {
@@ -2219,15 +2320,7 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
                        return r;
                }
        } else {
-               if (dssdrv->set_update_mode) {
-                       r = dssdrv->set_update_mode(dssdev,
-                                       OMAP_DSS_UPDATE_AUTO);
-                       if (r) {
-                               dev_err(fbdev->dev,
-                                               "Failed to set update mode\n");
-                               return r;
-                       }
-               }
+               d->update_mode = OMAPFB_AUTO_UPDATE;
        }
 
        return 0;
@@ -2275,6 +2368,8 @@ static int omapfb_probe(struct platform_device *pdev)
        fbdev->num_displays = 0;
        dssdev = NULL;
        for_each_dss_dev(dssdev) {
+               struct omapfb_display_data *d;
+
                omap_dss_get_device(dssdev);
 
                if (!dssdev->driver) {
@@ -2282,7 +2377,12 @@ static int omapfb_probe(struct platform_device *pdev)
                        r = -ENODEV;
                }
 
-               fbdev->displays[fbdev->num_displays++] = dssdev;
+               d = &fbdev->displays[fbdev->num_displays++];
+               d->dssdev = dssdev;
+               if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
+                       d->update_mode = OMAPFB_MANUAL_UPDATE;
+               else
+                       d->update_mode = OMAPFB_AUTO_UPDATE;
        }
 
        if (r)
index 2f5e817..153bf1a 100644 (file)
@@ -518,6 +518,39 @@ static ssize_t show_virt(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
 }
 
+static ssize_t show_upd_mode(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct fb_info *fbi = dev_get_drvdata(dev);
+       enum omapfb_update_mode mode;
+       int r;
+
+       r = omapfb_get_update_mode(fbi, &mode);
+
+       if (r)
+               return r;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode);
+}
+
+static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct fb_info *fbi = dev_get_drvdata(dev);
+       unsigned mode;
+       int r;
+
+       r = kstrtouint(buf, 0, &mode);
+       if (r)
+               return r;
+
+       r = omapfb_set_update_mode(fbi, mode);
+       if (r)
+               return r;
+
+       return count;
+}
+
 static struct device_attribute omapfb_attrs[] = {
        __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
                        store_rotate_type),
@@ -528,6 +561,7 @@ static struct device_attribute omapfb_attrs[] = {
                        store_overlays_rotate),
        __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
        __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
+       __ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode),
 };
 
 int omapfb_create_sysfs(struct omapfb2_device *fbdev)
index aa1b1d9..fdf0ede 100644 (file)
@@ -73,6 +73,15 @@ struct omapfb_info {
        bool mirror;
 };
 
+struct omapfb_display_data {
+       struct omapfb2_device *fbdev;
+       struct omap_dss_device *dssdev;
+       u8 bpp_override;
+       enum omapfb_update_mode update_mode;
+       bool auto_update_work_enabled;
+       struct delayed_work auto_update_work;
+};
+
 struct omapfb2_device {
        struct device *dev;
        struct mutex  mtx;
@@ -86,17 +95,13 @@ struct omapfb2_device {
        struct omapfb2_mem_region regions[10];
 
        unsigned num_displays;
-       struct omap_dss_device *displays[10];
+       struct omapfb_display_data displays[10];
        unsigned num_overlays;
        struct omap_overlay *overlays[10];
        unsigned num_managers;
        struct omap_overlay_manager *managers[10];
 
-       unsigned num_bpp_overrides;
-       struct {
-               struct omap_dss_device *dssdev;
-               u8 bpp;
-       } bpp_overrides[10];
+       struct workqueue_struct *auto_update_wq;
 };
 
 struct omapfb_colormode {
@@ -128,6 +133,13 @@ int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
 int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
                u16 posx, u16 posy, u16 outw, u16 outh);
 
+void omapfb_start_auto_update(struct omapfb2_device *fbdev,
+               struct omap_dss_device *display);
+void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
+               struct omap_dss_device *display);
+int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode);
+int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
+
 /* find the display connected to this fb, if any */
 static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
 {
@@ -143,6 +155,19 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
        return NULL;
 }
 
+static inline struct omapfb_display_data *get_display_data(
+               struct omapfb2_device *fbdev, struct omap_dss_device *dssdev)
+{
+       int i;
+
+       for (i = 0; i < fbdev->num_displays; ++i)
+               if (fbdev->displays[i].dssdev == dssdev)
+                       return &fbdev->displays[i];
+
+       /* This should never happen */
+       BUG();
+}
+
 static inline void omapfb_lock(struct omapfb2_device *fbdev)
 {
        mutex_lock(&fbdev->mtx);
index 32549d1..dcaab90 100644 (file)
@@ -55,7 +55,7 @@
 
 #define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
 
-#define S3_SAVAGE4_SERIES(chip)   ((chip>=S3_SAVAGE4) || (chip<=S3_PROSAVAGEDDR))
+#define S3_SAVAGE4_SERIES(chip)   ((chip>=S3_SAVAGE4) && (chip<=S3_PROSAVAGEDDR))
 
 #define S3_SAVAGE_MOBILE_SERIES(chip)  ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
 
index 21d816e..86b0735 100644 (file)
@@ -28,6 +28,14 @@ menuconfig WATCHDOG
 
 if WATCHDOG
 
+config WATCHDOG_CORE
+       bool "WatchDog Timer Driver Core"
+       ---help---
+         Say Y here if you want to use the new watchdog timer driver core.
+         This driver provides a framework for all watchdog timer drivers
+         and gives them the /dev/watchdog interface (and later also the
+         sysfs interface).
+
 config WATCHDOG_NOWAYOUT
        bool "Disable watchdog shutdown on close"
        help
@@ -186,6 +194,15 @@ config SA1100_WATCHDOG
          To compile this driver as a module, choose M here: the
          module will be called sa1100_wdt.
 
+config DW_WATCHDOG
+       tristate "Synopsys DesignWare watchdog"
+       depends on ARM && HAVE_CLK
+       help
+         Say Y here if to include support for the Synopsys DesignWare
+         watchdog timer found in many ARM chips.
+         To compile this driver as a module, choose M here: the
+         module will be called dw_wdt.
+
 config MPCORE_WATCHDOG
        tristate "MPcore watchdog"
        depends on HAVE_ARM_TWD
@@ -321,7 +338,7 @@ config MAX63XX_WATCHDOG
 
 config IMX2_WDT
        tristate "IMX2+ Watchdog"
-       depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 || ARCH_MX5
+       depends on IMX_HAVE_PLATFORM_IMX2_WDT
        help
          This is the driver for the hardware watchdog
          on the Freescale IMX2 and later processors.
@@ -879,6 +896,20 @@ config M54xx_WATCHDOG
          To compile this driver as a module, choose M here: the
          module will be called m54xx_wdt.
 
+# MicroBlaze Architecture
+
+config XILINX_WATCHDOG
+       tristate "Xilinx Watchdog timer"
+       depends on MICROBLAZE
+       ---help---
+         Watchdog driver for the xps_timebase_wdt ip core.
+
+         IMPORTANT: The xps_timebase_wdt parent must have the property
+         "clock-frequency" at device tree.
+
+         To compile this driver as a module, choose M here: the
+         module will be called of_xilinx_wdt.
+
 # MIPS Architecture
 
 config ATH79_WDT
index ed26f70..55bd574 100644 (file)
@@ -2,6 +2,10 @@
 # Makefile for the WatchDog device drivers.
 #
 
+# The WatchDog Timer Driver Core.
+watchdog-objs  += watchdog_core.o watchdog_dev.o
+obj-$(CONFIG_WATCHDOG_CORE)    += watchdog.o
+
 # Only one watchdog can succeed. We probe the ISA/PCI/USB based
 # watchdog-cards first, then the architecture specific watchdog
 # drivers and then the architecture independent "softdog" driver.
@@ -37,6 +41,7 @@ obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
 obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o
 obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
 obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
+obj-$(CONFIG_DW_WATCHDOG) += dw_wdt.o
 obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
 obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
 obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
@@ -109,6 +114,9 @@ obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o
 # M68K Architecture
 obj-$(CONFIG_M54xx_WATCHDOG) += m54xx_wdt.o
 
+# MicroBlaze Architecture
+obj-$(CONFIG_XILINX_WATCHDOG) += of_xilinx_wdt.o
+
 # MIPS Architecture
 obj-$(CONFIG_ATH79_WDT) += ath79_wdt.o
 obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o
index eac2602..87445b2 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/bitops.h>
 #include <linux/uaccess.h>
 
-#include <mach/at91_wdt.h>
+#include "at91sam9_wdt.h"
 
 #define DRV_NAME "AT91SAM9 Watchdog"
 
@@ -284,27 +284,8 @@ static int __exit at91wdt_remove(struct platform_device *pdev)
        return res;
 }
 
-#ifdef CONFIG_PM
-
-static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message)
-{
-       return 0;
-}
-
-static int at91wdt_resume(struct platform_device *pdev)
-{
-       return 0;
-}
-
-#else
-#define at91wdt_suspend        NULL
-#define at91wdt_resume NULL
-#endif
-
 static struct platform_driver at91wdt_driver = {
        .remove         = __exit_p(at91wdt_remove),
-       .suspend        = at91wdt_suspend,
-       .resume         = at91wdt_resume,
        .driver         = {
                .name   = "at91_wdt",
                .owner  = THIS_MODULE,
similarity index 96%
rename from arch/arm/mach-at91/include/mach/at91_wdt.h
rename to drivers/watchdog/at91sam9_wdt.h
index fecc2e9..757f9ca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-at91/include/mach/at91_wdt.h
+ * drivers/watchdog/at91sam9_wdt.h
  *
  * Copyright (C) 2007 Andrew Victor
  * Copyright (C) 2007 Atmel Corporation.
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
new file mode 100644 (file)
index 0000000..f10f8c0
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * Copyright 2010-2011 Picochip Ltd., Jamie Iles
+ * http://www.picochip.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This file implements a driver for the Synopsys DesignWare watchdog device
+ * in the many ARM subsystems. The watchdog has 16 different timeout periods
+ * and these are a function of the input clock frequency.
+ *
+ * The DesignWare watchdog cannot be stopped once it has been started so we
+ * use a software timer to implement a ping that will keep the watchdog alive.
+ * If we receive an expected close for the watchdog then we keep the timer
+ * running, otherwise the timer is stopped and the watchdog will expire.
+ */
+#define pr_fmt(fmt) "dw_wdt: " fmt
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/uaccess.h>
+#include <linux/watchdog.h>
+
+#define WDOG_CONTROL_REG_OFFSET                    0x00
+#define WDOG_CONTROL_REG_WDT_EN_MASK       0x01
+#define WDOG_TIMEOUT_RANGE_REG_OFFSET      0x04
+#define WDOG_CURRENT_COUNT_REG_OFFSET      0x08
+#define WDOG_COUNTER_RESTART_REG_OFFSET     0x0c
+#define WDOG_COUNTER_RESTART_KICK_VALUE            0x76
+
+/* The maximum TOP (timeout period) value that can be set in the watchdog. */
+#define DW_WDT_MAX_TOP         15
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
+                "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+#define WDT_TIMEOUT            (HZ / 2)
+
+static struct {
+       spinlock_t              lock;
+       void __iomem            *regs;
+       struct clk              *clk;
+       unsigned long           in_use;
+       unsigned long           next_heartbeat;
+       struct timer_list       timer;
+       int                     expect_close;
+} dw_wdt;
+
+static inline int dw_wdt_is_enabled(void)
+{
+       return readl(dw_wdt.regs + WDOG_CONTROL_REG_OFFSET) &
+               WDOG_CONTROL_REG_WDT_EN_MASK;
+}
+
+static inline int dw_wdt_top_in_seconds(unsigned top)
+{
+       /*
+        * There are 16 possible timeout values in 0..15 where the number of
+        * cycles is 2 ^ (16 + i) and the watchdog counts down.
+        */
+       return (1 << (16 + top)) / clk_get_rate(dw_wdt.clk);
+}
+
+static int dw_wdt_get_top(void)
+{
+       int top = readl(dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET) & 0xF;
+
+       return dw_wdt_top_in_seconds(top);
+}
+
+static inline void dw_wdt_set_next_heartbeat(void)
+{
+       dw_wdt.next_heartbeat = jiffies + dw_wdt_get_top() * HZ;
+}
+
+static int dw_wdt_set_top(unsigned top_s)
+{
+       int i, top_val = DW_WDT_MAX_TOP;
+
+       /*
+        * Iterate over the timeout values until we find the closest match. We
+        * always look for >=.
+        */
+       for (i = 0; i <= DW_WDT_MAX_TOP; ++i)
+               if (dw_wdt_top_in_seconds(i) >= top_s) {
+                       top_val = i;
+                       break;
+               }
+
+       /* Set the new value in the watchdog. */
+       writel(top_val, dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
+
+       dw_wdt_set_next_heartbeat();
+
+       return dw_wdt_top_in_seconds(top_val);
+}
+
+static void dw_wdt_keepalive(void)
+{
+       writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs +
+              WDOG_COUNTER_RESTART_REG_OFFSET);
+}
+
+static void dw_wdt_ping(unsigned long data)
+{
+       if (time_before(jiffies, dw_wdt.next_heartbeat) ||
+           (!nowayout && !dw_wdt.in_use)) {
+               dw_wdt_keepalive();
+               mod_timer(&dw_wdt.timer, jiffies + WDT_TIMEOUT);
+       } else
+               pr_crit("keepalive missed, machine will reset\n");
+}
+
+static int dw_wdt_open(struct inode *inode, struct file *filp)
+{
+       if (test_and_set_bit(0, &dw_wdt.in_use))
+               return -EBUSY;
+
+       /* Make sure we don't get unloaded. */
+       __module_get(THIS_MODULE);
+
+       spin_lock(&dw_wdt.lock);
+       if (!dw_wdt_is_enabled()) {
+               /*
+                * The watchdog is not currently enabled. Set the timeout to
+                * the maximum and then start it.
+                */
+               dw_wdt_set_top(DW_WDT_MAX_TOP);
+               writel(WDOG_CONTROL_REG_WDT_EN_MASK,
+                      dw_wdt.regs + WDOG_CONTROL_REG_OFFSET);
+       }
+
+       dw_wdt_set_next_heartbeat();
+
+       spin_unlock(&dw_wdt.lock);
+
+       return nonseekable_open(inode, filp);
+}
+
+ssize_t dw_wdt_write(struct file *filp, const char __user *buf, size_t len,
+                    loff_t *offset)
+{
+       if (!len)
+               return 0;
+
+       if (!nowayout) {
+               size_t i;
+
+               dw_wdt.expect_close = 0;
+
+               for (i = 0; i < len; ++i) {
+                       char c;
+
+                       if (get_user(c, buf + i))
+                               return -EFAULT;
+
+                       if (c == 'V') {
+                               dw_wdt.expect_close = 1;
+                               break;
+                       }
+               }
+       }
+
+       dw_wdt_set_next_heartbeat();
+       mod_timer(&dw_wdt.timer, jiffies + WDT_TIMEOUT);
+
+       return len;
+}
+
+static u32 dw_wdt_time_left(void)
+{
+       return readl(dw_wdt.regs + WDOG_CURRENT_COUNT_REG_OFFSET) /
+               clk_get_rate(dw_wdt.clk);
+}
+
+static const struct watchdog_info dw_wdt_ident = {
+       .options        = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
+                         WDIOF_MAGICCLOSE,
+       .identity       = "Synopsys DesignWare Watchdog",
+};
+
+static long dw_wdt_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       unsigned long val;
+       int timeout;
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               return copy_to_user((struct watchdog_info *)arg, &dw_wdt_ident,
+                                   sizeof(dw_wdt_ident)) ? -EFAULT : 0;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               return put_user(0, (int *)arg);
+
+       case WDIOC_KEEPALIVE:
+               dw_wdt_set_next_heartbeat();
+               return 0;
+
+       case WDIOC_SETTIMEOUT:
+               if (get_user(val, (int __user *)arg))
+                       return -EFAULT;
+               timeout = dw_wdt_set_top(val);
+               return put_user(timeout , (int __user *)arg);
+
+       case WDIOC_GETTIMEOUT:
+               return put_user(dw_wdt_get_top(), (int __user *)arg);
+
+       case WDIOC_GETTIMELEFT:
+               /* Get the time left until expiry. */
+               if (get_user(val, (int __user *)arg))
+                       return -EFAULT;
+               return put_user(dw_wdt_time_left(), (int __user *)arg);
+
+       default:
+               return -ENOTTY;
+       }
+}
+
+static int dw_wdt_release(struct inode *inode, struct file *filp)
+{
+       clear_bit(0, &dw_wdt.in_use);
+
+       if (!dw_wdt.expect_close) {
+               del_timer(&dw_wdt.timer);
+
+               if (!nowayout)
+                       pr_crit("unexpected close, system will reboot soon\n");
+               else
+                       pr_crit("watchdog cannot be disabled, system will reboot soon\n");
+       }
+
+       dw_wdt.expect_close = 0;
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int dw_wdt_suspend(struct device *dev)
+{
+       clk_disable(dw_wdt.clk);
+
+       return 0;
+}
+
+static int dw_wdt_resume(struct device *dev)
+{
+       int err = clk_enable(dw_wdt.clk);
+
+       if (err)
+               return err;
+
+       dw_wdt_keepalive();
+
+       return 0;
+}
+
+static const struct dev_pm_ops dw_wdt_pm_ops = {
+       .suspend        = dw_wdt_suspend,
+       .resume         = dw_wdt_resume,
+};
+#endif /* CONFIG_PM */
+
+static const struct file_operations wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .open           = dw_wdt_open,
+       .write          = dw_wdt_write,
+       .unlocked_ioctl = dw_wdt_ioctl,
+       .release        = dw_wdt_release
+};
+
+static struct miscdevice dw_wdt_miscdev = {
+       .fops           = &wdt_fops,
+       .name           = "watchdog",
+       .minor          = WATCHDOG_MINOR,
+};
+
+static int __devinit dw_wdt_drv_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       if (!mem)
+               return -EINVAL;
+
+       if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
+                                    "dw_wdt"))
+               return -ENOMEM;
+
+       dw_wdt.regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+       if (!dw_wdt.regs)
+               return -ENOMEM;
+
+       dw_wdt.clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(dw_wdt.clk))
+               return PTR_ERR(dw_wdt.clk);
+
+       ret = clk_enable(dw_wdt.clk);
+       if (ret)
+               goto out_put_clk;
+
+       spin_lock_init(&dw_wdt.lock);
+
+       ret = misc_register(&dw_wdt_miscdev);
+       if (ret)
+               goto out_disable_clk;
+
+       dw_wdt_set_next_heartbeat();
+       setup_timer(&dw_wdt.timer, dw_wdt_ping, 0);
+       mod_timer(&dw_wdt.timer, jiffies + WDT_TIMEOUT);
+
+       return 0;
+
+out_disable_clk:
+       clk_disable(dw_wdt.clk);
+out_put_clk:
+       clk_put(dw_wdt.clk);
+
+       return ret;
+}
+
+static int __devexit dw_wdt_drv_remove(struct platform_device *pdev)
+{
+       misc_deregister(&dw_wdt_miscdev);
+
+       clk_disable(dw_wdt.clk);
+       clk_put(dw_wdt.clk);
+
+       return 0;
+}
+
+static struct platform_driver dw_wdt_driver = {
+       .probe          = dw_wdt_drv_probe,
+       .remove         = __devexit_p(dw_wdt_drv_remove),
+       .driver         = {
+               .name   = "dw_wdt",
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm     = &dw_wdt_pm_ops,
+#endif /* CONFIG_PM */
+       },
+};
+
+static int __init dw_wdt_watchdog_init(void)
+{
+       return platform_driver_register(&dw_wdt_driver);
+}
+module_init(dw_wdt_watchdog_init);
+
+static void __exit dw_wdt_watchdog_exit(void)
+{
+       platform_driver_unregister(&dw_wdt_driver);
+}
+module_exit(dw_wdt_watchdog_exit);
+
+MODULE_AUTHOR("Jamie Iles");
+MODULE_DESCRIPTION("Synopsys DesignWare Watchdog Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
index 8cb2685..410fba4 100644 (file)
@@ -36,7 +36,7 @@
 #include <asm/cacheflush.h>
 #endif /* CONFIG_HPWDT_NMI_DECODING */
 
-#define HPWDT_VERSION                  "1.2.0"
+#define HPWDT_VERSION                  "1.3.0"
 #define SECS_TO_TICKS(secs)            ((secs) * 1000 / 128)
 #define TICKS_TO_SECS(ticks)           ((ticks) * 128 / 1000)
 #define HPWDT_MAX_TIMER                        TICKS_TO_SECS(65535)
@@ -87,6 +87,19 @@ struct smbios_cru64_info {
 };
 #define SMBIOS_CRU64_INFORMATION       212
 
+/* type 219 */
+struct smbios_proliant_info {
+       u8 type;
+       u8 byte_length;
+       u16 handle;
+       u32 power_features;
+       u32 omega_features;
+       u32 reserved;
+       u32 misc_features;
+};
+#define SMBIOS_ICRU_INFORMATION                219
+
+
 struct cmn_registers {
        union {
                struct {
@@ -132,6 +145,7 @@ struct cmn_registers {
 static unsigned int hpwdt_nmi_decoding;
 static unsigned int allow_kdump;
 static unsigned int priority;          /* hpwdt at end of die_notify list */
+static unsigned int is_icru;
 static DEFINE_SPINLOCK(rom_lock);
 static void *cru_rom_addr;
 static struct cmn_registers cmn_regs;
@@ -476,19 +490,22 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason,
                goto out;
 
        spin_lock_irqsave(&rom_lock, rom_pl);
-       if (!die_nmi_called)
+       if (!die_nmi_called && !is_icru)
                asminline_call(&cmn_regs, cru_rom_addr);
        die_nmi_called = 1;
        spin_unlock_irqrestore(&rom_lock, rom_pl);
-       if (cmn_regs.u1.ral == 0) {
-               printk(KERN_WARNING "hpwdt: An NMI occurred, "
-                       "but unable to determine source.\n");
-       } else {
-               if (allow_kdump)
-                       hpwdt_stop();
-               panic("An NMI occurred, please see the Integrated "
-                       "Management Log for details.\n");
+       if (!is_icru) {
+               if (cmn_regs.u1.ral == 0) {
+                       printk(KERN_WARNING "hpwdt: An NMI occurred, "
+                               "but unable to determine source.\n");
+               }
        }
+
+       if (allow_kdump)
+               hpwdt_stop();
+       panic("An NMI occurred, please see the Integrated "
+               "Management Log for details.\n");
+
 out:
        return NOTIFY_OK;
 }
@@ -659,30 +676,63 @@ static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
 }
 #endif /* CONFIG_X86_LOCAL_APIC */
 
+/*
+ *     dmi_find_icru
+ *
+ *     Routine Description:
+ *     This function checks whether or not we are on an iCRU-based server.
+ *     This check is independent of architecture and needs to be made for
+ *     any ProLiant system.
+ */
+static void __devinit dmi_find_icru(const struct dmi_header *dm, void *dummy)
+{
+       struct smbios_proliant_info *smbios_proliant_ptr;
+
+       if (dm->type == SMBIOS_ICRU_INFORMATION) {
+               smbios_proliant_ptr = (struct smbios_proliant_info *) dm;
+               if (smbios_proliant_ptr->misc_features & 0x01)
+                       is_icru = 1;
+       }
+}
+
 static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
 {
        int retval;
 
        /*
-        * We need to map the ROM to get the CRU service.
-        * For 32 bit Operating Systems we need to go through the 32 Bit
-        * BIOS Service Directory
-        * For 64 bit Operating Systems we get that service through SMBIOS.
+        * On typical CRU-based systems we need to map that service in
+        * the BIOS. For 32 bit Operating Systems we need to go through
+        * the 32 Bit BIOS Service Directory. For 64 bit Operating
+        * Systems we get that service through SMBIOS.
+        *
+        * On systems that support the new iCRU service all we need to
+        * do is call dmi_walk to get the supported flag value and skip
+        * the old cru detect code.
         */
-       retval = detect_cru_service();
-       if (retval < 0) {
-               dev_warn(&dev->dev,
-                       "Unable to detect the %d Bit CRU Service.\n",
-                       HPWDT_ARCH);
-               return retval;
-       }
+       dmi_walk(dmi_find_icru, NULL);
+       if (!is_icru) {
+
+               /*
+               * We need to map the ROM to get the CRU service.
+               * For 32 bit Operating Systems we need to go through the 32 Bit
+               * BIOS Service Directory
+               * For 64 bit Operating Systems we get that service through SMBIOS.
+               */
+               retval = detect_cru_service();
+               if (retval < 0) {
+                       dev_warn(&dev->dev,
+                               "Unable to detect the %d Bit CRU Service.\n",
+                               HPWDT_ARCH);
+                       return retval;
+               }
 
-       /*
-        * We know this is the only CRU call we need to make so lets keep as
-        * few instructions as possible once the NMI comes in.
-        */
-       cmn_regs.u1.rah = 0x0D;
-       cmn_regs.u1.ral = 0x02;
+               /*
+               * We know this is the only CRU call we need to make so lets keep as
+               * few instructions as possible once the NMI comes in.
+               */
+               cmn_regs.u1.rah = 0x0D;
+               cmn_regs.u1.ral = 0x02;
+       }
 
        /*
         * If the priority is set to 1, then we will be put first on the
index 5fd020d..751a591 100644 (file)
@@ -120,72 +120,12 @@ enum iTCO_chipsets {
        TCO_3420,       /* 3420 */
        TCO_3450,       /* 3450 */
        TCO_EP80579,    /* EP80579 */
-       TCO_CPT1,       /* Cougar Point */
-       TCO_CPT2,       /* Cougar Point Desktop */
-       TCO_CPT3,       /* Cougar Point Mobile */
-       TCO_CPT4,       /* Cougar Point */
-       TCO_CPT5,       /* Cougar Point */
-       TCO_CPT6,       /* Cougar Point */
-       TCO_CPT7,       /* Cougar Point */
-       TCO_CPT8,       /* Cougar Point */
-       TCO_CPT9,       /* Cougar Point */
-       TCO_CPT10,      /* Cougar Point */
-       TCO_CPT11,      /* Cougar Point */
-       TCO_CPT12,      /* Cougar Point */
-       TCO_CPT13,      /* Cougar Point */
-       TCO_CPT14,      /* Cougar Point */
-       TCO_CPT15,      /* Cougar Point */
-       TCO_CPT16,      /* Cougar Point */
-       TCO_CPT17,      /* Cougar Point */
-       TCO_CPT18,      /* Cougar Point */
-       TCO_CPT19,      /* Cougar Point */
-       TCO_CPT20,      /* Cougar Point */
-       TCO_CPT21,      /* Cougar Point */
-       TCO_CPT22,      /* Cougar Point */
-       TCO_CPT23,      /* Cougar Point */
-       TCO_CPT24,      /* Cougar Point */
-       TCO_CPT25,      /* Cougar Point */
-       TCO_CPT26,      /* Cougar Point */
-       TCO_CPT27,      /* Cougar Point */
-       TCO_CPT28,      /* Cougar Point */
-       TCO_CPT29,      /* Cougar Point */
-       TCO_CPT30,      /* Cougar Point */
-       TCO_CPT31,      /* Cougar Point */
-       TCO_PBG1,       /* Patsburg */
-       TCO_PBG2,       /* Patsburg */
+       TCO_CPT,        /* Cougar Point */
+       TCO_CPTD,       /* Cougar Point Desktop */
+       TCO_CPTM,       /* Cougar Point Mobile */
+       TCO_PBG,        /* Patsburg */
        TCO_DH89XXCC,   /* DH89xxCC */
-       TCO_PPT0,       /* Panther Point */
-       TCO_PPT1,       /* Panther Point */
-       TCO_PPT2,       /* Panther Point */
-       TCO_PPT3,       /* Panther Point */
-       TCO_PPT4,       /* Panther Point */
-       TCO_PPT5,       /* Panther Point */
-       TCO_PPT6,       /* Panther Point */
-       TCO_PPT7,       /* Panther Point */
-       TCO_PPT8,       /* Panther Point */
-       TCO_PPT9,       /* Panther Point */
-       TCO_PPT10,      /* Panther Point */
-       TCO_PPT11,      /* Panther Point */
-       TCO_PPT12,      /* Panther Point */
-       TCO_PPT13,      /* Panther Point */
-       TCO_PPT14,      /* Panther Point */
-       TCO_PPT15,      /* Panther Point */
-       TCO_PPT16,      /* Panther Point */
-       TCO_PPT17,      /* Panther Point */
-       TCO_PPT18,      /* Panther Point */
-       TCO_PPT19,      /* Panther Point */
-       TCO_PPT20,      /* Panther Point */
-       TCO_PPT21,      /* Panther Point */
-       TCO_PPT22,      /* Panther Point */
-       TCO_PPT23,      /* Panther Point */
-       TCO_PPT24,      /* Panther Point */
-       TCO_PPT25,      /* Panther Point */
-       TCO_PPT26,      /* Panther Point */
-       TCO_PPT27,      /* Panther Point */
-       TCO_PPT28,      /* Panther Point */
-       TCO_PPT29,      /* Panther Point */
-       TCO_PPT30,      /* Panther Point */
-       TCO_PPT31,      /* Panther Point */
+       TCO_PPT,        /* Panther Point */
 };
 
 static struct {
@@ -244,83 +184,14 @@ static struct {
        {"3450", 2},
        {"EP80579", 2},
        {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Cougar Point", 2},
-       {"Patsburg", 2},
+       {"Cougar Point Desktop", 2},
+       {"Cougar Point Mobile", 2},
        {"Patsburg", 2},
        {"DH89xxCC", 2},
        {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
-       {"Panther Point", 2},
        {NULL, 0}
 };
 
-#define ITCO_PCI_DEVICE(dev, data) \
-       .vendor = PCI_VENDOR_ID_INTEL,  \
-       .device = dev,                  \
-       .subvendor = PCI_ANY_ID,        \
-       .subdevice = PCI_ANY_ID,        \
-       .class = 0,                     \
-       .class_mask = 0,                \
-       .driver_data = data
-
 /*
  * This data only exists for exporting the supported PCI ids
  * via MODULE_DEVICE_TABLE.  We do not actually register a
@@ -328,138 +199,138 @@ static struct {
  * functions that probably will be registered by other drivers.
  */
 static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = {
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0,        TCO_ICH)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0,        TCO_ICH0)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0,        TCO_ICH2)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_10,       TCO_ICH2M)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_0,        TCO_ICH3)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_12,       TCO_ICH3M)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_0,        TCO_ICH4)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_12,       TCO_ICH4M)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801E_0,         TCO_CICH)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801EB_0,        TCO_ICH5)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB_1,            TCO_6300ESB)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_0,           TCO_ICH6)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_1,           TCO_ICH6M)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_2,           TCO_ICH6W)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0,           TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x2671,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x2672,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x2673,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x2674,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x2675,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x2676,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x2677,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x2678,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x2679,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x267a,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x267b,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x267c,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x267d,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x267e,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(0x267f,                               TCO_631XESB)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0,           TCO_ICH7)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30,          TCO_ICH7DH)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1,           TCO_ICH7M)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31,          TCO_ICH7MDH)},
-       { ITCO_PCI_DEVICE(0x27bc,                               TCO_NM10)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0,           TCO_ICH8)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2,           TCO_ICH8DH)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3,           TCO_ICH8DO)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4,           TCO_ICH8M)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1,           TCO_ICH8ME)},
-       { ITCO_PCI_DEVICE(0x2918,                               TCO_ICH9)},
-       { ITCO_PCI_DEVICE(0x2916,                               TCO_ICH9R)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2,           TCO_ICH9DH)},
-       { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4,           TCO_ICH9DO)},
-       { ITCO_PCI_DEVICE(0x2919,                               TCO_ICH9M)},
-       { ITCO_PCI_DEVICE(0x2917,                               TCO_ICH9ME)},
-       { ITCO_PCI_DEVICE(0x3a18,                               TCO_ICH10)},
-       { ITCO_PCI_DEVICE(0x3a16,                               TCO_ICH10R)},
-       { ITCO_PCI_DEVICE(0x3a1a,                               TCO_ICH10D)},
-       { ITCO_PCI_DEVICE(0x3a14,                               TCO_ICH10DO)},
-       { ITCO_PCI_DEVICE(0x3b00,                               TCO_PCH)},
-       { ITCO_PCI_DEVICE(0x3b01,                               TCO_PCHM)},
-       { ITCO_PCI_DEVICE(0x3b02,                               TCO_P55)},
-       { ITCO_PCI_DEVICE(0x3b03,                               TCO_PM55)},
-       { ITCO_PCI_DEVICE(0x3b06,                               TCO_H55)},
-       { ITCO_PCI_DEVICE(0x3b07,                               TCO_QM57)},
-       { ITCO_PCI_DEVICE(0x3b08,                               TCO_H57)},
-       { ITCO_PCI_DEVICE(0x3b09,                               TCO_HM55)},
-       { ITCO_PCI_DEVICE(0x3b0a,                               TCO_Q57)},
-       { ITCO_PCI_DEVICE(0x3b0b,                               TCO_HM57)},
-       { ITCO_PCI_DEVICE(0x3b0d,                               TCO_PCHMSFF)},
-       { ITCO_PCI_DEVICE(0x3b0f,                               TCO_QS57)},
-       { ITCO_PCI_DEVICE(0x3b12,                               TCO_3400)},
-       { ITCO_PCI_DEVICE(0x3b14,                               TCO_3420)},
-       { ITCO_PCI_DEVICE(0x3b16,                               TCO_3450)},
-       { ITCO_PCI_DEVICE(0x5031,                               TCO_EP80579)},
-       { ITCO_PCI_DEVICE(0x1c41,                               TCO_CPT1)},
-       { ITCO_PCI_DEVICE(0x1c42,                               TCO_CPT2)},
-       { ITCO_PCI_DEVICE(0x1c43,                               TCO_CPT3)},
-       { ITCO_PCI_DEVICE(0x1c44,                               TCO_CPT4)},
-       { ITCO_PCI_DEVICE(0x1c45,                               TCO_CPT5)},
-       { ITCO_PCI_DEVICE(0x1c46,                               TCO_CPT6)},
-       { ITCO_PCI_DEVICE(0x1c47,                               TCO_CPT7)},
-       { ITCO_PCI_DEVICE(0x1c48,                               TCO_CPT8)},
-       { ITCO_PCI_DEVICE(0x1c49,                               TCO_CPT9)},
-       { ITCO_PCI_DEVICE(0x1c4a,                               TCO_CPT10)},
-       { ITCO_PCI_DEVICE(0x1c4b,                               TCO_CPT11)},
-       { ITCO_PCI_DEVICE(0x1c4c,                               TCO_CPT12)},
-       { ITCO_PCI_DEVICE(0x1c4d,                               TCO_CPT13)},
-       { ITCO_PCI_DEVICE(0x1c4e,                               TCO_CPT14)},
-       { ITCO_PCI_DEVICE(0x1c4f,                               TCO_CPT15)},
-       { ITCO_PCI_DEVICE(0x1c50,                               TCO_CPT16)},
-       { ITCO_PCI_DEVICE(0x1c51,                               TCO_CPT17)},
-       { ITCO_PCI_DEVICE(0x1c52,                               TCO_CPT18)},
-       { ITCO_PCI_DEVICE(0x1c53,                               TCO_CPT19)},
-       { ITCO_PCI_DEVICE(0x1c54,                               TCO_CPT20)},
-       { ITCO_PCI_DEVICE(0x1c55,                               TCO_CPT21)},
-       { ITCO_PCI_DEVICE(0x1c56,                               TCO_CPT22)},
-       { ITCO_PCI_DEVICE(0x1c57,                               TCO_CPT23)},
-       { ITCO_PCI_DEVICE(0x1c58,                               TCO_CPT24)},
-       { ITCO_PCI_DEVICE(0x1c59,                               TCO_CPT25)},
-       { ITCO_PCI_DEVICE(0x1c5a,                               TCO_CPT26)},
-       { ITCO_PCI_DEVICE(0x1c5b,                               TCO_CPT27)},
-       { ITCO_PCI_DEVICE(0x1c5c,                               TCO_CPT28)},
-       { ITCO_PCI_DEVICE(0x1c5d,                               TCO_CPT29)},
-       { ITCO_PCI_DEVICE(0x1c5e,                               TCO_CPT30)},
-       { ITCO_PCI_DEVICE(0x1c5f,                               TCO_CPT31)},
-       { ITCO_PCI_DEVICE(0x1d40,                               TCO_PBG1)},
-       { ITCO_PCI_DEVICE(0x1d41,                               TCO_PBG2)},
-       { ITCO_PCI_DEVICE(0x2310,                               TCO_DH89XXCC)},
-       { ITCO_PCI_DEVICE(0x1e40,                               TCO_PPT0)},
-       { ITCO_PCI_DEVICE(0x1e41,                               TCO_PPT1)},
-       { ITCO_PCI_DEVICE(0x1e42,                               TCO_PPT2)},
-       { ITCO_PCI_DEVICE(0x1e43,                               TCO_PPT3)},
-       { ITCO_PCI_DEVICE(0x1e44,                               TCO_PPT4)},
-       { ITCO_PCI_DEVICE(0x1e45,                               TCO_PPT5)},
-       { ITCO_PCI_DEVICE(0x1e46,                               TCO_PPT6)},
-       { ITCO_PCI_DEVICE(0x1e47,                               TCO_PPT7)},
-       { ITCO_PCI_DEVICE(0x1e48,                               TCO_PPT8)},
-       { ITCO_PCI_DEVICE(0x1e49,                               TCO_PPT9)},
-       { ITCO_PCI_DEVICE(0x1e4a,                               TCO_PPT10)},
-       { ITCO_PCI_DEVICE(0x1e4b,                               TCO_PPT11)},
-       { ITCO_PCI_DEVICE(0x1e4c,                               TCO_PPT12)},
-       { ITCO_PCI_DEVICE(0x1e4d,                               TCO_PPT13)},
-       { ITCO_PCI_DEVICE(0x1e4e,                               TCO_PPT14)},
-       { ITCO_PCI_DEVICE(0x1e4f,                               TCO_PPT15)},
-       { ITCO_PCI_DEVICE(0x1e50,                               TCO_PPT16)},
-       { ITCO_PCI_DEVICE(0x1e51,                               TCO_PPT17)},
-       { ITCO_PCI_DEVICE(0x1e52,                               TCO_PPT18)},
-       { ITCO_PCI_DEVICE(0x1e53,                               TCO_PPT19)},
-       { ITCO_PCI_DEVICE(0x1e54,                               TCO_PPT20)},
-       { ITCO_PCI_DEVICE(0x1e55,                               TCO_PPT21)},
-       { ITCO_PCI_DEVICE(0x1e56,                               TCO_PPT22)},
-       { ITCO_PCI_DEVICE(0x1e57,                               TCO_PPT23)},
-       { ITCO_PCI_DEVICE(0x1e58,                               TCO_PPT24)},
-       { ITCO_PCI_DEVICE(0x1e59,                               TCO_PPT25)},
-       { ITCO_PCI_DEVICE(0x1e5a,                               TCO_PPT26)},
-       { ITCO_PCI_DEVICE(0x1e5b,                               TCO_PPT27)},
-       { ITCO_PCI_DEVICE(0x1e5c,                               TCO_PPT28)},
-       { ITCO_PCI_DEVICE(0x1e5d,                               TCO_PPT29)},
-       { ITCO_PCI_DEVICE(0x1e5e,                               TCO_PPT30)},
-       { ITCO_PCI_DEVICE(0x1e5f,                               TCO_PPT31)},
+       { PCI_VDEVICE(INTEL, 0x2410), TCO_ICH},
+       { PCI_VDEVICE(INTEL, 0x2420), TCO_ICH0},
+       { PCI_VDEVICE(INTEL, 0x2440), TCO_ICH2},
+       { PCI_VDEVICE(INTEL, 0x244c), TCO_ICH2M},
+       { PCI_VDEVICE(INTEL, 0x2480), TCO_ICH3},
+       { PCI_VDEVICE(INTEL, 0x248c), TCO_ICH3M},
+       { PCI_VDEVICE(INTEL, 0x24c0), TCO_ICH4},
+       { PCI_VDEVICE(INTEL, 0x24cc), TCO_ICH4M},
+       { PCI_VDEVICE(INTEL, 0x2450), TCO_CICH},
+       { PCI_VDEVICE(INTEL, 0x24d0), TCO_ICH5},
+       { PCI_VDEVICE(INTEL, 0x25a1), TCO_6300ESB},
+       { PCI_VDEVICE(INTEL, 0x2640), TCO_ICH6},
+       { PCI_VDEVICE(INTEL, 0x2641), TCO_ICH6M},
+       { PCI_VDEVICE(INTEL, 0x2642), TCO_ICH6W},
+       { PCI_VDEVICE(INTEL, 0x2670), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2671), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2672), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2673), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2674), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2675), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2676), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2677), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2678), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2679), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x267a), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x267b), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x267c), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x267d), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x267e), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x267f), TCO_631XESB},
+       { PCI_VDEVICE(INTEL, 0x27b8), TCO_ICH7},
+       { PCI_VDEVICE(INTEL, 0x27b0), TCO_ICH7DH},
+       { PCI_VDEVICE(INTEL, 0x27b9), TCO_ICH7M},
+       { PCI_VDEVICE(INTEL, 0x27bd), TCO_ICH7MDH},
+       { PCI_VDEVICE(INTEL, 0x27bc), TCO_NM10},
+       { PCI_VDEVICE(INTEL, 0x2810), TCO_ICH8},
+       { PCI_VDEVICE(INTEL, 0x2812), TCO_ICH8DH},
+       { PCI_VDEVICE(INTEL, 0x2814), TCO_ICH8DO},
+       { PCI_VDEVICE(INTEL, 0x2815), TCO_ICH8M},
+       { PCI_VDEVICE(INTEL, 0x2811), TCO_ICH8ME},
+       { PCI_VDEVICE(INTEL, 0x2918), TCO_ICH9},
+       { PCI_VDEVICE(INTEL, 0x2916), TCO_ICH9R},
+       { PCI_VDEVICE(INTEL, 0x2912), TCO_ICH9DH},
+       { PCI_VDEVICE(INTEL, 0x2914), TCO_ICH9DO},
+       { PCI_VDEVICE(INTEL, 0x2919), TCO_ICH9M},
+       { PCI_VDEVICE(INTEL, 0x2917), TCO_ICH9ME},
+       { PCI_VDEVICE(INTEL, 0x3a18), TCO_ICH10},
+       { PCI_VDEVICE(INTEL, 0x3a16), TCO_ICH10R},
+       { PCI_VDEVICE(INTEL, 0x3a1a), TCO_ICH10D},
+       { PCI_VDEVICE(INTEL, 0x3a14), TCO_ICH10DO},
+       { PCI_VDEVICE(INTEL, 0x3b00), TCO_PCH},
+       { PCI_VDEVICE(INTEL, 0x3b01), TCO_PCHM},
+       { PCI_VDEVICE(INTEL, 0x3b02), TCO_P55},
+       { PCI_VDEVICE(INTEL, 0x3b03), TCO_PM55},
+       { PCI_VDEVICE(INTEL, 0x3b06), TCO_H55},
+       { PCI_VDEVICE(INTEL, 0x3b07), TCO_QM57},
+       { PCI_VDEVICE(INTEL, 0x3b08), TCO_H57},
+       { PCI_VDEVICE(INTEL, 0x3b09), TCO_HM55},
+       { PCI_VDEVICE(INTEL, 0x3b0a), TCO_Q57},
+       { PCI_VDEVICE(INTEL, 0x3b0b), TCO_HM57},
+       { PCI_VDEVICE(INTEL, 0x3b0d), TCO_PCHMSFF},
+       { PCI_VDEVICE(INTEL, 0x3b0f), TCO_QS57},
+       { PCI_VDEVICE(INTEL, 0x3b12), TCO_3400},
+       { PCI_VDEVICE(INTEL, 0x3b14), TCO_3420},
+       { PCI_VDEVICE(INTEL, 0x3b16), TCO_3450},
+       { PCI_VDEVICE(INTEL, 0x5031), TCO_EP80579},
+       { PCI_VDEVICE(INTEL, 0x1c41), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c42), TCO_CPTD},
+       { PCI_VDEVICE(INTEL, 0x1c43), TCO_CPTM},
+       { PCI_VDEVICE(INTEL, 0x1c44), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c45), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c46), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c47), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c48), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c49), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c4a), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c4b), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c4c), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c4d), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c4e), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c4f), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c50), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c51), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c52), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c53), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c54), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c55), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c56), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c57), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c58), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c59), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c5a), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c5b), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c5c), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c5d), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c5e), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1c5f), TCO_CPT},
+       { PCI_VDEVICE(INTEL, 0x1d40), TCO_PBG},
+       { PCI_VDEVICE(INTEL, 0x1d41), TCO_PBG},
+       { PCI_VDEVICE(INTEL, 0x2310), TCO_DH89XXCC},
+       { PCI_VDEVICE(INTEL, 0x1e40), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e41), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e42), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e43), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e44), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e45), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e46), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e47), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e48), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e49), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e4a), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e4b), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e4c), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e4d), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e4e), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e4f), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e50), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e51), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e52), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e53), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e54), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e55), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e56), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e57), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e58), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e59), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e5a), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e5b), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e5c), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e5d), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e5e), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x1e5f), TCO_PPT},
        { 0, },                 /* End of list */
 };
 MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
@@ -1052,15 +923,10 @@ static void iTCO_wdt_shutdown(struct platform_device *dev)
        iTCO_wdt_stop();
 }
 
-#define iTCO_wdt_suspend NULL
-#define iTCO_wdt_resume  NULL
-
 static struct platform_driver iTCO_wdt_driver = {
        .probe          = iTCO_wdt_probe,
        .remove         = __devexit_p(iTCO_wdt_remove),
        .shutdown       = iTCO_wdt_shutdown,
-       .suspend        = iTCO_wdt_suspend,
-       .resume         = iTCO_wdt_resume,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = DRV_NAME,
index 86f7cac..b8ef2c6 100644 (file)
@@ -329,12 +329,18 @@ static void imx2_wdt_shutdown(struct platform_device *pdev)
        }
 }
 
+static const struct of_device_id imx2_wdt_dt_ids[] = {
+       { .compatible = "fsl,imx21-wdt", },
+       { /* sentinel */ }
+};
+
 static struct platform_driver imx2_wdt_driver = {
        .remove         = __exit_p(imx2_wdt_remove),
        .shutdown       = imx2_wdt_shutdown,
        .driver         = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = imx2_wdt_dt_ids,
        },
 };
 
index 6143f52..8d2d850 100644 (file)
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/fs.h>
-#include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
+#include <linux/ioport.h>
 
 #define NAME "it8712f_wdt"
 
@@ -51,7 +51,6 @@ MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
 
 static unsigned long wdt_open;
 static unsigned expect_close;
-static spinlock_t io_lock;
 static unsigned char revision;
 
 /* Dog Food address - We use the game port address */
@@ -121,20 +120,26 @@ static inline void superio_select(int ldn)
        outb(ldn, VAL);
 }
 
-static inline void superio_enter(void)
+static inline int superio_enter(void)
 {
-       spin_lock(&io_lock);
+       /*
+        * Try to reserve REG and REG + 1 for exclusive access.
+        */
+       if (!request_muxed_region(REG, 2, NAME))
+               return -EBUSY;
+
        outb(0x87, REG);
        outb(0x01, REG);
        outb(0x55, REG);
        outb(0x55, REG);
+       return 0;
 }
 
 static inline void superio_exit(void)
 {
        outb(0x02, REG);
        outb(0x02, VAL);
-       spin_unlock(&io_lock);
+       release_region(REG, 2);
 }
 
 static inline void it8712f_wdt_ping(void)
@@ -173,10 +178,13 @@ static int it8712f_wdt_get_status(void)
                return 0;
 }
 
-static void it8712f_wdt_enable(void)
+static int it8712f_wdt_enable(void)
 {
+       int ret = superio_enter();
+       if (ret)
+               return ret;
+
        printk(KERN_DEBUG NAME ": enabling watchdog timer\n");
-       superio_enter();
        superio_select(LDN_GPIO);
 
        superio_outb(wdt_control_reg, WDT_CONTROL);
@@ -186,13 +194,17 @@ static void it8712f_wdt_enable(void)
        superio_exit();
 
        it8712f_wdt_ping();
+
+       return 0;
 }
 
-static void it8712f_wdt_disable(void)
+static int it8712f_wdt_disable(void)
 {
-       printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
+       int ret = superio_enter();
+       if (ret)
+               return ret;
 
-       superio_enter();
+       printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
        superio_select(LDN_GPIO);
 
        superio_outb(0, WDT_CONFIG);
@@ -202,6 +214,7 @@ static void it8712f_wdt_disable(void)
        superio_outb(0, WDT_TIMEOUT);
 
        superio_exit();
+       return 0;
 }
 
 static int it8712f_wdt_notify(struct notifier_block *this,
@@ -252,6 +265,7 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
                                                WDIOF_MAGICCLOSE,
        };
        int value;
+       int ret;
 
        switch (cmd) {
        case WDIOC_GETSUPPORT:
@@ -259,7 +273,9 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
                        return -EFAULT;
                return 0;
        case WDIOC_GETSTATUS:
-               superio_enter();
+               ret = superio_enter();
+               if (ret)
+                       return ret;
                superio_select(LDN_GPIO);
 
                value = it8712f_wdt_get_status();
@@ -280,7 +296,9 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
                if (value > (max_units * 60))
                        return -EINVAL;
                margin = value;
-               superio_enter();
+               ret = superio_enter();
+               if (ret)
+                       return ret;
                superio_select(LDN_GPIO);
 
                it8712f_wdt_update_margin();
@@ -299,10 +317,14 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
 
 static int it8712f_wdt_open(struct inode *inode, struct file *file)
 {
+       int ret;
        /* only allow one at a time */
        if (test_and_set_bit(0, &wdt_open))
                return -EBUSY;
-       it8712f_wdt_enable();
+
+       ret = it8712f_wdt_enable();
+       if (ret)
+               return ret;
        return nonseekable_open(inode, file);
 }
 
@@ -313,7 +335,8 @@ static int it8712f_wdt_release(struct inode *inode, struct file *file)
                        ": watchdog device closed unexpectedly, will not"
                        " disable the watchdog timer\n");
        } else if (!nowayout) {
-               it8712f_wdt_disable();
+               if (it8712f_wdt_disable())
+                       printk(KERN_WARNING NAME "Watchdog disable failed\n");
        }
        expect_close = 0;
        clear_bit(0, &wdt_open);
@@ -340,8 +363,10 @@ static int __init it8712f_wdt_find(unsigned short *address)
 {
        int err = -ENODEV;
        int chip_type;
+       int ret = superio_enter();
+       if (ret)
+               return ret;
 
-       superio_enter();
        chip_type = superio_inw(DEVID);
        if (chip_type != IT8712F_DEVID)
                goto exit;
@@ -382,8 +407,6 @@ static int __init it8712f_wdt_init(void)
 {
        int err = 0;
 
-       spin_lock_init(&io_lock);
-
        if (it8712f_wdt_find(&address))
                return -ENODEV;
 
@@ -392,7 +415,11 @@ static int __init it8712f_wdt_init(void)
                return -EBUSY;
        }
 
-       it8712f_wdt_disable();
+       err = it8712f_wdt_disable();
+       if (err) {
+               printk(KERN_ERR NAME ": unable to disable watchdog timer.\n");
+               goto out;
+       }
 
        err = register_reboot_notifier(&it8712f_wdt_notifier);
        if (err) {
index b1bc72f..a2d9a12 100644 (file)
 
 static unsigned int base, gpact, ciract, max_units, chip_type;
 static unsigned long wdt_status;
-static DEFINE_SPINLOCK(spinlock);
 
 static int nogameport = DEFAULT_NOGAMEPORT;
 static int exclusive  = DEFAULT_EXCLUSIVE;
@@ -163,18 +162,26 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default="
 
 /* Superio Chip */
 
-static inline void superio_enter(void)
+static inline int superio_enter(void)
 {
+       /*
+        * Try to reserve REG and REG + 1 for exclusive access.
+        */
+       if (!request_muxed_region(REG, 2, WATCHDOG_NAME))
+               return -EBUSY;
+
        outb(0x87, REG);
        outb(0x01, REG);
        outb(0x55, REG);
        outb(0x55, REG);
+       return 0;
 }
 
 static inline void superio_exit(void)
 {
        outb(0x02, REG);
        outb(0x02, VAL);
+       release_region(REG, 2);
 }
 
 static inline void superio_select(int ldn)
@@ -255,12 +262,11 @@ static void wdt_keepalive(void)
        set_bit(WDTS_KEEPALIVE, &wdt_status);
 }
 
-static void wdt_start(void)
+static int wdt_start(void)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&spinlock, flags);
-       superio_enter();
+       int ret = superio_enter();
+       if (ret)
+               return ret;
 
        superio_select(GPIO);
        if (test_bit(WDTS_USE_GP, &wdt_status))
@@ -270,15 +276,15 @@ static void wdt_start(void)
        wdt_update_timeout();
 
        superio_exit();
-       spin_unlock_irqrestore(&spinlock, flags);
+
+       return 0;
 }
 
-static void wdt_stop(void)
+static int wdt_stop(void)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&spinlock, flags);
-       superio_enter();
+       int ret = superio_enter();
+       if (ret)
+               return ret;
 
        superio_select(GPIO);
        superio_outb(0x00, WDTCTRL);
@@ -288,7 +294,7 @@ static void wdt_stop(void)
                superio_outb(0x00, WDTVALMSB);
 
        superio_exit();
-       spin_unlock_irqrestore(&spinlock, flags);
+       return 0;
 }
 
 /**
@@ -303,8 +309,6 @@ static void wdt_stop(void)
 
 static int wdt_set_timeout(int t)
 {
-       unsigned long flags;
-
        if (t < 1 || t > max_units * 60)
                return -EINVAL;
 
@@ -313,14 +317,15 @@ static int wdt_set_timeout(int t)
        else
                timeout = t;
 
-       spin_lock_irqsave(&spinlock, flags);
        if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
-               superio_enter();
+               int ret = superio_enter();
+               if (ret)
+                       return ret;
+
                superio_select(GPIO);
                wdt_update_timeout();
                superio_exit();
        }
-       spin_unlock_irqrestore(&spinlock, flags);
        return 0;
 }
 
@@ -339,12 +344,12 @@ static int wdt_set_timeout(int t)
 
 static int wdt_get_status(int *status)
 {
-       unsigned long flags;
-
        *status = 0;
        if (testmode) {
-               spin_lock_irqsave(&spinlock, flags);
-               superio_enter();
+               int ret = superio_enter();
+               if (ret)
+                       return ret;
+
                superio_select(GPIO);
                if (superio_inb(WDTCTRL) & WDT_ZERO) {
                        superio_outb(0x00, WDTCTRL);
@@ -353,7 +358,6 @@ static int wdt_get_status(int *status)
                }
 
                superio_exit();
-               spin_unlock_irqrestore(&spinlock, flags);
        }
        if (test_and_clear_bit(WDTS_KEEPALIVE, &wdt_status))
                *status |= WDIOF_KEEPALIVEPING;
@@ -379,9 +383,17 @@ static int wdt_open(struct inode *inode, struct file *file)
        if (exclusive && test_and_set_bit(WDTS_DEV_OPEN, &wdt_status))
                return -EBUSY;
        if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) {
+               int ret;
                if (nowayout && !test_and_set_bit(WDTS_LOCKED, &wdt_status))
                        __module_get(THIS_MODULE);
-               wdt_start();
+
+               ret = wdt_start();
+               if (ret) {
+                       clear_bit(WDTS_LOCKED, &wdt_status);
+                       clear_bit(WDTS_TIMER_RUN, &wdt_status);
+                       clear_bit(WDTS_DEV_OPEN, &wdt_status);
+                       return ret;
+               }
        }
        return nonseekable_open(inode, file);
 }
@@ -403,7 +415,16 @@ static int wdt_release(struct inode *inode, struct file *file)
 {
        if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
                if (test_and_clear_bit(WDTS_EXPECTED, &wdt_status)) {
-                       wdt_stop();
+                       int ret = wdt_stop();
+                       if (ret) {
+                               /*
+                                * Stop failed. Just keep the watchdog alive
+                                * and hope nothing bad happens.
+                                */
+                               set_bit(WDTS_EXPECTED, &wdt_status);
+                               wdt_keepalive();
+                               return ret;
+                       }
                        clear_bit(WDTS_TIMER_RUN, &wdt_status);
                } else {
                        wdt_keepalive();
@@ -484,7 +505,9 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                                    &ident, sizeof(ident)) ? -EFAULT : 0;
 
        case WDIOC_GETSTATUS:
-               wdt_get_status(&status);
+               rc = wdt_get_status(&status);
+               if (rc)
+                       return rc;
                return put_user(status, uarg.i);
 
        case WDIOC_GETBOOTSTATUS:
@@ -500,14 +523,22 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
                switch (new_options) {
                case WDIOS_DISABLECARD:
-                       if (test_bit(WDTS_TIMER_RUN, &wdt_status))
-                               wdt_stop();
+                       if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
+                               rc = wdt_stop();
+                               if (rc)
+                                       return rc;
+                       }
                        clear_bit(WDTS_TIMER_RUN, &wdt_status);
                        return 0;
 
                case WDIOS_ENABLECARD:
-                       if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status))
-                               wdt_start();
+                       if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) {
+                               rc = wdt_start();
+                               if (rc) {
+                                       clear_bit(WDTS_TIMER_RUN, &wdt_status);
+                                       return rc;
+                               }
+                       }
                        return 0;
 
                default:
@@ -560,16 +591,17 @@ static int __init it87_wdt_init(void)
        int rc = 0;
        int try_gameport = !nogameport;
        u8  chip_rev;
-       unsigned long flags;
+       int gp_rreq_fail = 0;
 
        wdt_status = 0;
 
-       spin_lock_irqsave(&spinlock, flags);
-       superio_enter();
+       rc = superio_enter();
+       if (rc)
+               return rc;
+
        chip_type = superio_inw(CHIPID);
        chip_rev  = superio_inb(CHIPREV) & 0x0f;
        superio_exit();
-       spin_unlock_irqrestore(&spinlock, flags);
 
        switch (chip_type) {
        case IT8702_ID:
@@ -603,8 +635,9 @@ static int __init it87_wdt_init(void)
                return -ENODEV;
        }
 
-       spin_lock_irqsave(&spinlock, flags);
-       superio_enter();
+       rc = superio_enter();
+       if (rc)
+               return rc;
 
        superio_select(GPIO);
        superio_outb(WDT_TOV1, WDTCFG);
@@ -620,21 +653,16 @@ static int __init it87_wdt_init(void)
                }
                gpact = superio_inb(ACTREG);
                superio_outb(0x01, ACTREG);
-               superio_exit();
-               spin_unlock_irqrestore(&spinlock, flags);
                if (request_region(base, 1, WATCHDOG_NAME))
                        set_bit(WDTS_USE_GP, &wdt_status);
                else
-                       rc = -EIO;
-       } else {
-               superio_exit();
-               spin_unlock_irqrestore(&spinlock, flags);
+                       gp_rreq_fail = 1;
        }
 
        /* If we haven't Gameport support, try to get CIR support */
        if (!test_bit(WDTS_USE_GP, &wdt_status)) {
                if (!request_region(CIR_BASE, 8, WATCHDOG_NAME)) {
-                       if (rc == -EIO)
+                       if (gp_rreq_fail)
                                printk(KERN_ERR PFX
                                        "I/O Address 0x%04x and 0x%04x"
                                        " already in use\n", base, CIR_BASE);
@@ -646,21 +674,16 @@ static int __init it87_wdt_init(void)
                        goto err_out;
                }
                base = CIR_BASE;
-               spin_lock_irqsave(&spinlock, flags);
-               superio_enter();
 
                superio_select(CIR);
                superio_outw(base, BASEREG);
                superio_outb(0x00, CIR_ILS);
                ciract = superio_inb(ACTREG);
                superio_outb(0x01, ACTREG);
-               if (rc == -EIO) {
+               if (gp_rreq_fail) {
                        superio_select(GAMEPORT);
                        superio_outb(gpact, ACTREG);
                }
-
-               superio_exit();
-               spin_unlock_irqrestore(&spinlock, flags);
        }
 
        if (timeout < 1 || timeout > max_units * 60) {
@@ -704,6 +727,7 @@ static int __init it87_wdt_init(void)
                "nogameport=%d)\n", chip_type, chip_rev, timeout,
                nowayout, testmode, exclusive, nogameport);
 
+       superio_exit();
        return 0;
 
 err_out_reboot:
@@ -711,49 +735,37 @@ err_out_reboot:
 err_out_region:
        release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8);
        if (!test_bit(WDTS_USE_GP, &wdt_status)) {
-               spin_lock_irqsave(&spinlock, flags);
-               superio_enter();
                superio_select(CIR);
                superio_outb(ciract, ACTREG);
-               superio_exit();
-               spin_unlock_irqrestore(&spinlock, flags);
        }
 err_out:
        if (try_gameport) {
-               spin_lock_irqsave(&spinlock, flags);
-               superio_enter();
                superio_select(GAMEPORT);
                superio_outb(gpact, ACTREG);
-               superio_exit();
-               spin_unlock_irqrestore(&spinlock, flags);
        }
 
+       superio_exit();
        return rc;
 }
 
 static void __exit it87_wdt_exit(void)
 {
-       unsigned long flags;
-       int nolock;
-
-       nolock = !spin_trylock_irqsave(&spinlock, flags);
-       superio_enter();
-       superio_select(GPIO);
-       superio_outb(0x00, WDTCTRL);
-       superio_outb(0x00, WDTCFG);
-       superio_outb(0x00, WDTVALLSB);
-       if (max_units > 255)
-               superio_outb(0x00, WDTVALMSB);
-       if (test_bit(WDTS_USE_GP, &wdt_status)) {
-               superio_select(GAMEPORT);
-               superio_outb(gpact, ACTREG);
-       } else {
-               superio_select(CIR);
-               superio_outb(ciract, ACTREG);
+       if (superio_enter() == 0) {
+               superio_select(GPIO);
+               superio_outb(0x00, WDTCTRL);
+               superio_outb(0x00, WDTCFG);
+               superio_outb(0x00, WDTVALLSB);
+               if (max_units > 255)
+                       superio_outb(0x00, WDTVALMSB);
+               if (test_bit(WDTS_USE_GP, &wdt_status)) {
+                       superio_select(GAMEPORT);
+                       superio_outb(gpact, ACTREG);
+               } else {
+                       superio_select(CIR);
+                       superio_outb(ciract, ACTREG);
+               }
+               superio_exit();
        }
-       superio_exit();
-       if (!nolock)
-               spin_unlock_irqrestore(&spinlock, flags);
 
        misc_deregister(&wdt_miscdev);
        unregister_reboot_notifier(&wdt_notifier);
index 2b4af22..4dc3102 100644 (file)
@@ -407,12 +407,35 @@ static int __devexit mpcore_wdt_remove(struct platform_device *dev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int mpcore_wdt_suspend(struct platform_device *dev, pm_message_t msg)
+{
+       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
+       mpcore_wdt_stop(wdt);           /* Turn the WDT off */
+       return 0;
+}
+
+static int mpcore_wdt_resume(struct platform_device *dev)
+{
+       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
+       /* re-activate timer */
+       if (test_bit(0, &wdt->timer_alive))
+               mpcore_wdt_start(wdt);
+       return 0;
+}
+#else
+#define mpcore_wdt_suspend     NULL
+#define mpcore_wdt_resume      NULL
+#endif
+
 /* work with hotplug and coldplug */
 MODULE_ALIAS("platform:mpcore_wdt");
 
 static struct platform_driver mpcore_wdt_driver = {
        .probe          = mpcore_wdt_probe,
        .remove         = __devexit_p(mpcore_wdt_remove),
+       .suspend        = mpcore_wdt_suspend,
+       .resume         = mpcore_wdt_resume,
        .shutdown       = mpcore_wdt_shutdown,
        .driver         = {
                .owner  = THIS_MODULE,
index 0430e09..ac37bb8 100644 (file)
@@ -225,11 +225,11 @@ static int __devinit mtx1_wdt_probe(struct platform_device *pdev)
 
        ret = misc_register(&mtx1_wdt_misc);
        if (ret < 0) {
-               printk(KERN_ERR " mtx-1_wdt : failed to register\n");
+               dev_err(&pdev->dev, "failed to register\n");
                return ret;
        }
        mtx1_wdt_start();
-       printk(KERN_INFO "MTX-1 Watchdog driver\n");
+       dev_info(&pdev->dev, "MTX-1 Watchdog driver\n");
        return 0;
 }
 
index afa78a5..809f41c 100644 (file)
@@ -458,7 +458,15 @@ static int __devexit nv_tco_remove(struct platform_device *dev)
 
 static void nv_tco_shutdown(struct platform_device *dev)
 {
+       u32 val;
+
        tco_timer_stop();
+
+       /* Some BIOSes fail the POST (once) if the NO_REBOOT flag is not
+        * unset during shutdown. */
+       pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val);
+       val &= ~MCP51_SMBUS_SETUP_B_TCO_REBOOT;
+       pci_write_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, val);
 }
 
 static struct platform_driver nv_tco_driver = {
diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
new file mode 100644 (file)
index 0000000..4ec741a
--- /dev/null
@@ -0,0 +1,433 @@
+/*
+*   of_xilinx_wdt.c  1.01  A Watchdog Device Driver for Xilinx xps_timebase_wdt
+*
+*   (C) Copyright 2011 (Alejandro Cabrera <aldaya@gmail.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.
+*
+*       -----------------------
+*      30-May-2011 Alejandro Cabrera <aldaya@gmail.com>
+*              - If "xlnx,wdt-enable-once" wasn't found on device tree the
+*                module will use CONFIG_WATCHDOG_NOWAYOUT
+*              - If the device tree parameters ("clock-frequency" and
+*                "xlnx,wdt-interval") wasn't found the driver won't
+*                know the wdt reset interval
+*/
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/watchdog.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+
+/* Register offsets for the Wdt device */
+#define XWT_TWCSR0_OFFSET   0x0 /* Control/Status Register0 */
+#define XWT_TWCSR1_OFFSET   0x4 /* Control/Status Register1 */
+#define XWT_TBR_OFFSET      0x8 /* Timebase Register Offset */
+
+/* Control/Status Register Masks  */
+#define XWT_CSR0_WRS_MASK   0x00000008 /* Reset status */
+#define XWT_CSR0_WDS_MASK   0x00000004 /* Timer state  */
+#define XWT_CSR0_EWDT1_MASK 0x00000002 /* Enable bit 1 */
+
+/* Control/Status Register 0/1 bits  */
+#define XWT_CSRX_EWDT2_MASK 0x00000001 /* Enable bit 2 */
+
+/* SelfTest constants */
+#define XWT_MAX_SELFTEST_LOOP_COUNT 0x00010000
+#define XWT_TIMER_FAILED            0xFFFFFFFF
+
+#define WATCHDOG_NAME     "Xilinx Watchdog"
+#define PFX WATCHDOG_NAME ": "
+
+struct xwdt_device {
+       struct resource  res;
+       void __iomem *base;
+       u32 nowayout;
+       u32 wdt_interval;
+       u32 boot_status;
+};
+
+static struct xwdt_device xdev;
+
+static  u32 timeout;
+static  u32 control_status_reg;
+static  u8  expect_close;
+static  u8  no_timeout;
+static unsigned long driver_open;
+
+static  DEFINE_SPINLOCK(spinlock);
+
+static void xwdt_start(void)
+{
+       spin_lock(&spinlock);
+
+       /* Clean previous status and enable the watchdog timer */
+       control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
+       control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK);
+
+       iowrite32((control_status_reg | XWT_CSR0_EWDT1_MASK),
+                               xdev.base + XWT_TWCSR0_OFFSET);
+
+       iowrite32(XWT_CSRX_EWDT2_MASK, xdev.base + XWT_TWCSR1_OFFSET);
+
+       spin_unlock(&spinlock);
+}
+
+static void xwdt_stop(void)
+{
+       spin_lock(&spinlock);
+
+       control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
+
+       iowrite32((control_status_reg & ~XWT_CSR0_EWDT1_MASK),
+                               xdev.base + XWT_TWCSR0_OFFSET);
+
+       iowrite32(0, xdev.base + XWT_TWCSR1_OFFSET);
+
+       spin_unlock(&spinlock);
+       printk(KERN_INFO PFX "Stopped!\n");
+}
+
+static void xwdt_keepalive(void)
+{
+       spin_lock(&spinlock);
+
+       control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
+       control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK);
+       iowrite32(control_status_reg, xdev.base + XWT_TWCSR0_OFFSET);
+
+       spin_unlock(&spinlock);
+}
+
+static void xwdt_get_status(int *status)
+{
+       int new_status;
+
+       spin_lock(&spinlock);
+
+       control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
+       new_status = ((control_status_reg &
+                       (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK)) != 0);
+       spin_unlock(&spinlock);
+
+       *status = 0;
+       if (new_status & 1)
+               *status |= WDIOF_CARDRESET;
+}
+
+static u32 xwdt_selftest(void)
+{
+       int i;
+       u32 timer_value1;
+       u32 timer_value2;
+
+       spin_lock(&spinlock);
+
+       timer_value1 = ioread32(xdev.base + XWT_TBR_OFFSET);
+       timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET);
+
+       for (i = 0;
+               ((i <= XWT_MAX_SELFTEST_LOOP_COUNT) &&
+                       (timer_value2 == timer_value1)); i++) {
+               timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET);
+       }
+
+       spin_unlock(&spinlock);
+
+       if (timer_value2 != timer_value1)
+               return ~XWT_TIMER_FAILED;
+       else
+               return XWT_TIMER_FAILED;
+}
+
+static int xwdt_open(struct inode *inode, struct file *file)
+{
+       /* Only one process can handle the wdt at a time */
+       if (test_and_set_bit(0, &driver_open))
+               return -EBUSY;
+
+       /* Make sure that the module are always loaded...*/
+       if (xdev.nowayout)
+               __module_get(THIS_MODULE);
+
+       xwdt_start();
+       printk(KERN_INFO PFX "Started...\n");
+
+       return nonseekable_open(inode, file);
+}
+
+static int xwdt_release(struct inode *inode, struct file *file)
+{
+       if (expect_close == 42) {
+               xwdt_stop();
+       } else {
+               printk(KERN_CRIT PFX
+                       "Unexpected close, not stopping watchdog!\n");
+               xwdt_keepalive();
+       }
+
+       clear_bit(0, &driver_open);
+       expect_close = 0;
+       return 0;
+}
+
+/*
+ *      xwdt_write:
+ *      @file: file handle to the watchdog
+ *      @buf: buffer to write (unused as data does not matter here
+ *      @count: count of bytes
+ *      @ppos: pointer to the position to write. No seeks allowed
+ *
+ *      A write to a watchdog device is defined as a keepalive signal. Any
+ *      write of data will do, as we don't define content meaning.
+ */
+static ssize_t xwdt_write(struct file *file, const char __user *buf,
+                                               size_t len, loff_t *ppos)
+{
+       if (len) {
+               if (!xdev.nowayout) {
+                       size_t i;
+
+                       /* In case it was set long ago */
+                       expect_close = 0;
+
+                       for (i = 0; i != len; i++) {
+                               char c;
+
+                               if (get_user(c, buf + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+               xwdt_keepalive();
+       }
+       return len;
+}
+
+static const struct watchdog_info ident = {
+       .options =  WDIOF_MAGICCLOSE |
+                   WDIOF_KEEPALIVEPING,
+       .firmware_version =     1,
+       .identity =     WATCHDOG_NAME,
+};
+
+/*
+ *      xwdt_ioctl:
+ *      @file: file handle to the device
+ *      @cmd: watchdog command
+ *      @arg: argument pointer
+ *
+ *      The watchdog API defines a common set of functions for all watchdogs
+ *      according to their available features.
+ */
+static long xwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       int status;
+
+       union {
+               struct watchdog_info __user *ident;
+               int __user *i;
+       } uarg;
+
+       uarg.i = (int __user *)arg;
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               return copy_to_user(uarg.ident, &ident,
+                                       sizeof(ident)) ? -EFAULT : 0;
+
+       case WDIOC_GETBOOTSTATUS:
+               return put_user(xdev.boot_status, uarg.i);
+
+       case WDIOC_GETSTATUS:
+               xwdt_get_status(&status);
+               return put_user(status, uarg.i);
+
+       case WDIOC_KEEPALIVE:
+               xwdt_keepalive();
+               return 0;
+
+       case WDIOC_GETTIMEOUT:
+               if (no_timeout)
+                       return -ENOTTY;
+               else
+                       return put_user(timeout, uarg.i);
+
+       default:
+               return -ENOTTY;
+       }
+}
+
+static const struct file_operations xwdt_fops = {
+       .owner      = THIS_MODULE,
+       .llseek     = no_llseek,
+       .write      = xwdt_write,
+       .open       = xwdt_open,
+       .release    = xwdt_release,
+       .unlocked_ioctl = xwdt_ioctl,
+};
+
+static struct miscdevice xwdt_miscdev = {
+       .minor      = WATCHDOG_MINOR,
+       .name       = "watchdog",
+       .fops       = &xwdt_fops,
+};
+
+static int __devinit xwdt_probe(struct platform_device *pdev)
+{
+       int rc;
+       u32 *tmptr;
+       u32 *pfreq;
+
+       no_timeout = 0;
+
+       pfreq = (u32 *)of_get_property(pdev->dev.of_node->parent,
+                                       "clock-frequency", NULL);
+
+       if (pfreq == NULL) {
+               printk(KERN_WARNING PFX
+                       "The watchdog clock frequency cannot be obtained!\n");
+               no_timeout = 1;
+       }
+
+       rc = of_address_to_resource(pdev->dev.of_node, 0, &xdev.res);
+       if (rc) {
+               printk(KERN_WARNING PFX "invalid address!\n");
+               return rc;
+       }
+
+       tmptr = (u32 *)of_get_property(pdev->dev.of_node,
+                                       "xlnx,wdt-interval", NULL);
+       if (tmptr == NULL) {
+               printk(KERN_WARNING PFX "Parameter \"xlnx,wdt-interval\""
+                                       " not found in device tree!\n");
+               no_timeout = 1;
+       } else {
+               xdev.wdt_interval = *tmptr;
+       }
+
+       tmptr = (u32 *)of_get_property(pdev->dev.of_node,
+                                       "xlnx,wdt-enable-once", NULL);
+       if (tmptr == NULL) {
+               printk(KERN_WARNING PFX "Parameter \"xlnx,wdt-enable-once\""
+                                       " not found in device tree!\n");
+               xdev.nowayout = WATCHDOG_NOWAYOUT;
+       }
+
+/*
+ *  Twice of the 2^wdt_interval / freq  because the first wdt overflow is
+ *  ignored (interrupt), reset is only generated at second wdt overflow
+ */
+       if (!no_timeout)
+               timeout = 2 * ((1<<xdev.wdt_interval) / *pfreq);
+
+       if (!request_mem_region(xdev.res.start,
+                       xdev.res.end - xdev.res.start + 1, WATCHDOG_NAME)) {
+               rc = -ENXIO;
+               printk(KERN_ERR PFX "memory request failure!\n");
+               goto err_out;
+       }
+
+       xdev.base = ioremap(xdev.res.start, xdev.res.end - xdev.res.start + 1);
+       if (xdev.base == NULL) {
+               rc = -ENOMEM;
+               printk(KERN_ERR PFX "ioremap failure!\n");
+               goto release_mem;
+       }
+
+       rc = xwdt_selftest();
+       if (rc == XWT_TIMER_FAILED) {
+               printk(KERN_ERR PFX "SelfTest routine error!\n");
+               goto unmap_io;
+       }
+
+       xwdt_get_status(&xdev.boot_status);
+
+       rc = misc_register(&xwdt_miscdev);
+       if (rc) {
+               printk(KERN_ERR PFX
+                       "cannot register miscdev on minor=%d (err=%d)\n",
+                                               xwdt_miscdev.minor, rc);
+               goto unmap_io;
+       }
+
+       if (no_timeout)
+               printk(KERN_INFO PFX
+                       "driver loaded (timeout=? sec, nowayout=%d)\n",
+                                                   xdev.nowayout);
+       else
+               printk(KERN_INFO PFX
+                       "driver loaded (timeout=%d sec, nowayout=%d)\n",
+                                       timeout, xdev.nowayout);
+
+       expect_close = 0;
+       clear_bit(0, &driver_open);
+
+       return 0;
+
+unmap_io:
+       iounmap(xdev.base);
+release_mem:
+       release_mem_region(xdev.res.start, resource_size(&xdev.res));
+err_out:
+       return rc;
+}
+
+static int __devexit xwdt_remove(struct platform_device *dev)
+{
+       misc_deregister(&xwdt_miscdev);
+       iounmap(xdev.base);
+       release_mem_region(xdev.res.start, resource_size(&xdev.res));
+
+       return 0;
+}
+
+/* Match table for of_platform binding */
+static struct of_device_id __devinitdata xwdt_of_match[] = {
+       { .compatible = "xlnx,xps-timebase-wdt-1.01.a", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, xwdt_of_match);
+
+static struct platform_driver xwdt_driver = {
+       .probe       = xwdt_probe,
+       .remove      = __devexit_p(xwdt_remove),
+       .driver = {
+               .owner = THIS_MODULE,
+               .name  = WATCHDOG_NAME,
+               .of_match_table = xwdt_of_match,
+       },
+};
+
+static int __init xwdt_init(void)
+{
+       return platform_driver_register(&xwdt_driver);
+}
+
+static void __exit xwdt_exit(void)
+{
+       platform_driver_unregister(&xwdt_driver);
+}
+
+module_init(xwdt_init);
+module_exit(xwdt_exit);
+
+MODULE_AUTHOR("Alejandro Cabrera <aldaya@gmail.com>");
+MODULE_DESCRIPTION("Xilinx Watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
index b7c1390..e78d899 100644 (file)
@@ -56,6 +56,7 @@
 #define IO_DEFAULT     0x2E            /* Address used on Portwell Boards */
 
 static int io = IO_DEFAULT;
+static int swc_base_addr = -1;
 
 static int timeout = DEFAULT_TIMEOUT;  /* timeout value */
 static unsigned long timer_enabled;    /* is the timer enabled? */
@@ -116,9 +117,8 @@ static inline void pc87413_enable_swc(void)
 
 /* Read SWC I/O base address */
 
-static inline unsigned int pc87413_get_swc_base(void)
+static void pc87413_get_swc_base_addr(void)
 {
-       unsigned int  swc_base_addr = 0;
        unsigned char addr_l, addr_h = 0;
 
        /* Step 3: Read SWC I/O Base Address */
@@ -136,12 +136,11 @@ static inline unsigned int pc87413_get_swc_base(void)
                "Read SWC I/O Base Address: low %d, high %d, res %d\n",
                                                addr_l, addr_h, swc_base_addr);
 #endif
-       return swc_base_addr;
 }
 
 /* Select Bank 3 of SWC */
 
-static inline void pc87413_swc_bank3(unsigned int swc_base_addr)
+static inline void pc87413_swc_bank3(void)
 {
        /* Step 4: Select Bank3 of SWC */
        outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f);
@@ -152,8 +151,7 @@ static inline void pc87413_swc_bank3(unsigned int swc_base_addr)
 
 /* Set watchdog timeout to x minutes */
 
-static inline void pc87413_programm_wdto(unsigned int swc_base_addr,
-                                        char pc87413_time)
+static inline void pc87413_programm_wdto(char pc87413_time)
 {
        /* Step 5: Programm WDTO, Twd. */
        outb_p(pc87413_time, swc_base_addr + WDTO);
@@ -164,7 +162,7 @@ static inline void pc87413_programm_wdto(unsigned int swc_base_addr,
 
 /* Enable WDEN */
 
-static inline void pc87413_enable_wden(unsigned int swc_base_addr)
+static inline void pc87413_enable_wden(void)
 {
        /* Step 6: Enable WDEN */
        outb_p(inb(swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL);
@@ -174,7 +172,7 @@ static inline void pc87413_enable_wden(unsigned int swc_base_addr)
 }
 
 /* Enable SW_WD_TREN */
-static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr)
+static inline void pc87413_enable_sw_wd_tren(void)
 {
        /* Enable SW_WD_TREN */
        outb_p(inb(swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG);
@@ -185,7 +183,7 @@ static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr)
 
 /* Disable SW_WD_TREN */
 
-static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr)
+static inline void pc87413_disable_sw_wd_tren(void)
 {
        /* Disable SW_WD_TREN */
        outb_p(inb(swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG);
@@ -196,7 +194,7 @@ static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr)
 
 /* Enable SW_WD_TRG */
 
-static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr)
+static inline void pc87413_enable_sw_wd_trg(void)
 {
        /* Enable SW_WD_TRG */
        outb_p(inb(swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL);
@@ -207,7 +205,7 @@ static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr)
 
 /* Disable SW_WD_TRG */
 
-static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr)
+static inline void pc87413_disable_sw_wd_trg(void)
 {
        /* Disable SW_WD_TRG */
        outb_p(inb(swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL);
@@ -222,18 +220,13 @@ static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr)
 
 static void pc87413_enable(void)
 {
-       unsigned int swc_base_addr;
-
        spin_lock(&io_lock);
 
-       pc87413_select_wdt_out();
-       pc87413_enable_swc();
-       swc_base_addr = pc87413_get_swc_base();
-       pc87413_swc_bank3(swc_base_addr);
-       pc87413_programm_wdto(swc_base_addr, timeout);
-       pc87413_enable_wden(swc_base_addr);
-       pc87413_enable_sw_wd_tren(swc_base_addr);
-       pc87413_enable_sw_wd_trg(swc_base_addr);
+       pc87413_swc_bank3();
+       pc87413_programm_wdto(timeout);
+       pc87413_enable_wden();
+       pc87413_enable_sw_wd_tren();
+       pc87413_enable_sw_wd_trg();
 
        spin_unlock(&io_lock);
 }
@@ -242,17 +235,12 @@ static void pc87413_enable(void)
 
 static void pc87413_disable(void)
 {
-       unsigned int swc_base_addr;
-
        spin_lock(&io_lock);
 
-       pc87413_select_wdt_out();
-       pc87413_enable_swc();
-       swc_base_addr = pc87413_get_swc_base();
-       pc87413_swc_bank3(swc_base_addr);
-       pc87413_disable_sw_wd_tren(swc_base_addr);
-       pc87413_disable_sw_wd_trg(swc_base_addr);
-       pc87413_programm_wdto(swc_base_addr, 0);
+       pc87413_swc_bank3();
+       pc87413_disable_sw_wd_tren();
+       pc87413_disable_sw_wd_trg();
+       pc87413_programm_wdto(0);
 
        spin_unlock(&io_lock);
 }
@@ -261,20 +249,15 @@ static void pc87413_disable(void)
 
 static void pc87413_refresh(void)
 {
-       unsigned int swc_base_addr;
-
        spin_lock(&io_lock);
 
-       pc87413_select_wdt_out();
-       pc87413_enable_swc();
-       swc_base_addr = pc87413_get_swc_base();
-       pc87413_swc_bank3(swc_base_addr);
-       pc87413_disable_sw_wd_tren(swc_base_addr);
-       pc87413_disable_sw_wd_trg(swc_base_addr);
-       pc87413_programm_wdto(swc_base_addr, timeout);
-       pc87413_enable_wden(swc_base_addr);
-       pc87413_enable_sw_wd_tren(swc_base_addr);
-       pc87413_enable_sw_wd_trg(swc_base_addr);
+       pc87413_swc_bank3();
+       pc87413_disable_sw_wd_tren();
+       pc87413_disable_sw_wd_trg();
+       pc87413_programm_wdto(timeout);
+       pc87413_enable_wden();
+       pc87413_enable_sw_wd_tren();
+       pc87413_enable_sw_wd_trg();
 
        spin_unlock(&io_lock);
 }
@@ -528,7 +511,8 @@ static int __init pc87413_init(void)
        printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n",
                                                        WDT_INDEX_IO_PORT);
 
-       /* request_region(io, 2, "pc87413"); */
+       if (!request_muxed_region(io, 2, MODNAME))
+               return -EBUSY;
 
        ret = register_reboot_notifier(&pc87413_notifier);
        if (ret != 0) {
@@ -541,12 +525,32 @@ static int __init pc87413_init(void)
                printk(KERN_ERR PFX
                        "cannot register miscdev on minor=%d (err=%d)\n",
                        WATCHDOG_MINOR, ret);
-               unregister_reboot_notifier(&pc87413_notifier);
-               return ret;
+               goto reboot_unreg;
        }
        printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout);
+
+       pc87413_select_wdt_out();
+       pc87413_enable_swc();
+       pc87413_get_swc_base_addr();
+
+       if (!request_region(swc_base_addr, 0x20, MODNAME)) {
+               printk(KERN_ERR PFX
+                       "cannot request SWC region at 0x%x\n", swc_base_addr);
+               ret = -EBUSY;
+               goto misc_unreg;
+       }
+
        pc87413_enable();
+
+       release_region(io, 2);
        return 0;
+
+misc_unreg:
+       misc_deregister(&pc87413_miscdev);
+reboot_unreg:
+       unregister_reboot_notifier(&pc87413_notifier);
+       release_region(io, 2);
+       return ret;
 }
 
 /**
@@ -569,7 +573,7 @@ static void __exit pc87413_exit(void)
 
        misc_deregister(&pc87413_miscdev);
        unregister_reboot_notifier(&pc87413_notifier);
-       /* release_region(io, 2); */
+       release_region(swc_base_addr, 0x20);
 
        printk(KERN_INFO MODNAME " watchdog component driver removed.\n");
 }
index f7f5aa0..30da88f 100644 (file)
@@ -589,6 +589,15 @@ static int s3c2410wdt_resume(struct platform_device *dev)
 #define s3c2410wdt_resume  NULL
 #endif /* CONFIG_PM */
 
+#ifdef CONFIG_OF
+static const struct of_device_id s3c2410_wdt_match[] = {
+       { .compatible = "samsung,s3c2410-wdt" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, s3c2410_wdt_match);
+#else
+#define s3c2410_wdt_match NULL
+#endif
 
 static struct platform_driver s3c2410wdt_driver = {
        .probe          = s3c2410wdt_probe,
@@ -599,6 +608,7 @@ static struct platform_driver s3c2410wdt_driver = {
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "s3c2410-wdt",
+               .of_match_table = s3c2410_wdt_match,
        },
 };
 
index c7cf4b0..029467e 100644 (file)
@@ -472,15 +472,10 @@ static void sch311x_wdt_shutdown(struct platform_device *dev)
        sch311x_wdt_stop();
 }
 
-#define sch311x_wdt_suspend NULL
-#define sch311x_wdt_resume  NULL
-
 static struct platform_driver sch311x_wdt_driver = {
        .probe          = sch311x_wdt_probe,
        .remove         = __devexit_p(sch311x_wdt_remove),
        .shutdown       = sch311x_wdt_shutdown,
-       .suspend        = sch311x_wdt_suspend,
-       .resume         = sch311x_wdt_resume,
        .driver         = {
                .owner = THIS_MODULE,
                .name = DRV_NAME,
index db84f23..a267dc0 100644 (file)
@@ -64,7 +64,7 @@
  * misses its deadline, the kernel timer will allow the WDT to overflow.
  */
 static int clock_division_ratio = WTCSR_CKS_4096;
-#define next_ping_period(cks)  msecs_to_jiffies(cks - 4)
+#define next_ping_period(cks)  (jiffies + msecs_to_jiffies(cks - 4))
 
 static const struct watchdog_info sh_wdt_info;
 static struct platform_device *sh_wdt_dev;
index 0d80e08..cc2cfbe 100644 (file)
@@ -134,6 +134,8 @@ static void wdt_enable(void)
        writel(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
        writel(LOCK, wdt->base + WDTLOCK);
 
+       /* Flush posted writes. */
+       readl(wdt->base + WDTLOCK);
        spin_unlock(&wdt->lock);
 }
 
@@ -144,9 +146,10 @@ static void wdt_disable(void)
 
        writel(UNLOCK, wdt->base + WDTLOCK);
        writel(0, wdt->base + WDTCONTROL);
-       writel(0, wdt->base + WDTLOAD);
        writel(LOCK, wdt->base + WDTLOCK);
 
+       /* Flush posted writes. */
+       readl(wdt->base + WDTLOCK);
        spin_unlock(&wdt->lock);
 }
 
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
new file mode 100644 (file)
index 0000000..cfa1a15
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *     watchdog_core.c
+ *
+ *     (c) Copyright 2008-2011 Alan Cox <alan@lxorguk.ukuu.org.uk>,
+ *                                             All Rights Reserved.
+ *
+ *     (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>.
+ *
+ *     This source code is part of the generic code that can be used
+ *     by all the watchdog timer drivers.
+ *
+ *     Based on source code of the following authors:
+ *       Matt Domsch <Matt_Domsch@dell.com>,
+ *       Rob Radez <rob@osinvestor.com>,
+ *       Rusty Lynch <rusty@linux.co.intel.com>
+ *       Satyam Sharma <satyam@infradead.org>
+ *       Randy Dunlap <randy.dunlap@oracle.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.
+ *
+ *     Neither Alan Cox, CymruNet Ltd., Wim Van Sebroeck nor Iguana vzw.
+ *     admit liability nor provide warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>      /* For EXPORT_SYMBOL/module stuff/... */
+#include <linux/types.h>       /* For standard types */
+#include <linux/errno.h>       /* For the -ENODEV/... values */
+#include <linux/kernel.h>      /* For printk/panic/... */
+#include <linux/watchdog.h>    /* For watchdog specific items */
+#include <linux/init.h>                /* For __init/__exit/... */
+
+#include "watchdog_dev.h"      /* For watchdog_dev_register/... */
+
+/**
+ * watchdog_register_device() - register a watchdog device
+ * @wdd: watchdog device
+ *
+ * Register a watchdog device with the kernel so that the
+ * watchdog timer can be accessed from userspace.
+ *
+ * A zero is returned on success and a negative errno code for
+ * failure.
+ */
+int watchdog_register_device(struct watchdog_device *wdd)
+{
+       int ret;
+
+       if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL)
+               return -EINVAL;
+
+       /* Mandatory operations need to be supported */
+       if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
+               return -EINVAL;
+
+       /*
+        * Check that we have valid min and max timeout values, if
+        * not reset them both to 0 (=not used or unknown)
+        */
+       if (wdd->min_timeout > wdd->max_timeout) {
+               pr_info("Invalid min and max timeout values, resetting to 0!\n");
+               wdd->min_timeout = 0;
+               wdd->max_timeout = 0;
+       }
+
+       /*
+        * Note: now that all watchdog_device data has been verified, we
+        * will not check this anymore in other functions. If data gets
+        * corrupted in a later stage then we expect a kernel panic!
+        */
+
+       /* We only support 1 watchdog device via the /dev/watchdog interface */
+       ret = watchdog_dev_register(wdd);
+       if (ret) {
+               pr_err("error registering /dev/watchdog (err=%d).\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(watchdog_register_device);
+
+/**
+ * watchdog_unregister_device() - unregister a watchdog device
+ * @wdd: watchdog device to unregister
+ *
+ * Unregister a watchdog device that was previously successfully
+ * registered with watchdog_register_device().
+ */
+void watchdog_unregister_device(struct watchdog_device *wdd)
+{
+       int ret;
+
+       if (wdd == NULL)
+               return;
+
+       ret = watchdog_dev_unregister(wdd);
+       if (ret)
+               pr_err("error unregistering /dev/watchdog (err=%d).\n", ret);
+}
+EXPORT_SYMBOL_GPL(watchdog_unregister_device);
+
+MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>");
+MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
+MODULE_DESCRIPTION("WatchDog Timer Driver Core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
new file mode 100644 (file)
index 0000000..d33520d
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ *     watchdog_dev.c
+ *
+ *     (c) Copyright 2008-2011 Alan Cox <alan@lxorguk.ukuu.org.uk>,
+ *                                             All Rights Reserved.
+ *
+ *     (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>.
+ *
+ *
+ *     This source code is part of the generic code that can be used
+ *     by all the watchdog timer drivers.
+ *
+ *     This part of the generic code takes care of the following
+ *     misc device: /dev/watchdog.
+ *
+ *     Based on source code of the following authors:
+ *       Matt Domsch <Matt_Domsch@dell.com>,
+ *       Rob Radez <rob@osinvestor.com>,
+ *       Rusty Lynch <rusty@linux.co.intel.com>
+ *       Satyam Sharma <satyam@infradead.org>
+ *       Randy Dunlap <randy.dunlap@oracle.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.
+ *
+ *     Neither Alan Cox, CymruNet Ltd., Wim Van Sebroeck nor Iguana vzw.
+ *     admit liability nor provide warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>      /* For module stuff/... */
+#include <linux/types.h>       /* For standard types (like size_t) */
+#include <linux/errno.h>       /* For the -ENODEV/... values */
+#include <linux/kernel.h>      /* For printk/panic/... */
+#include <linux/fs.h>          /* For file operations */
+#include <linux/watchdog.h>    /* For watchdog specific items */
+#include <linux/miscdevice.h>  /* For handling misc devices */
+#include <linux/init.h>                /* For __init/__exit/... */
+#include <linux/uaccess.h>     /* For copy_to_user/put_user/... */
+
+/* make sure we only register one /dev/watchdog device */
+static unsigned long watchdog_dev_busy;
+/* the watchdog device behind /dev/watchdog */
+static struct watchdog_device *wdd;
+
+/*
+ *     watchdog_ping: ping the watchdog.
+ *     @wddev: the watchdog device to ping
+ *
+ *     If the watchdog has no own ping operation then it needs to be
+ *     restarted via the start operation. This wrapper function does
+ *     exactly that.
+ *     We only ping when the watchdog device is running.
+ */
+
+static int watchdog_ping(struct watchdog_device *wddev)
+{
+       if (test_bit(WDOG_ACTIVE, &wdd->status)) {
+               if (wddev->ops->ping)
+                       return wddev->ops->ping(wddev);  /* ping the watchdog */
+               else
+                       return wddev->ops->start(wddev); /* restart watchdog */
+       }
+       return 0;
+}
+
+/*
+ *     watchdog_start: wrapper to start the watchdog.
+ *     @wddev: the watchdog device to start
+ *
+ *     Start the watchdog if it is not active and mark it active.
+ *     This function returns zero on success or a negative errno code for
+ *     failure.
+ */
+
+static int watchdog_start(struct watchdog_device *wddev)
+{
+       int err;
+
+       if (!test_bit(WDOG_ACTIVE, &wdd->status)) {
+               err = wddev->ops->start(wddev);
+               if (err < 0)
+                       return err;
+
+               set_bit(WDOG_ACTIVE, &wdd->status);
+       }
+       return 0;
+}
+
+/*
+ *     watchdog_stop: wrapper to stop the watchdog.
+ *     @wddev: the watchdog device to stop
+ *
+ *     Stop the watchdog if it is still active and unmark it active.
+ *     This function returns zero on success or a negative errno code for
+ *     failure.
+ *     If the 'nowayout' feature was set, the watchdog cannot be stopped.
+ */
+
+static int watchdog_stop(struct watchdog_device *wddev)
+{
+       int err = -EBUSY;
+
+       if (test_bit(WDOG_NO_WAY_OUT, &wdd->status)) {
+               pr_info("%s: nowayout prevents watchdog to be stopped!\n",
+                                                       wdd->info->identity);
+               return err;
+       }
+
+       if (test_bit(WDOG_ACTIVE, &wdd->status)) {
+               err = wddev->ops->stop(wddev);
+               if (err < 0)
+                       return err;
+
+               clear_bit(WDOG_ACTIVE, &wdd->status);
+       }
+       return 0;
+}
+
+/*
+ *     watchdog_write: writes to the watchdog.
+ *     @file: file from VFS
+ *     @data: user address of data
+ *     @len: length of data
+ *     @ppos: pointer to the file offset
+ *
+ *     A write to a watchdog device is defined as a keepalive ping.
+ *     Writing the magic 'V' sequence allows the next close to turn
+ *     off the watchdog (if 'nowayout' is not set).
+ */
+
+static ssize_t watchdog_write(struct file *file, const char __user *data,
+                                               size_t len, loff_t *ppos)
+{
+       size_t i;
+       char c;
+
+       if (len == 0)
+               return 0;
+
+       /*
+        * Note: just in case someone wrote the magic character
+        * five months ago...
+        */
+       clear_bit(WDOG_ALLOW_RELEASE, &wdd->status);
+
+       /* scan to see whether or not we got the magic character */
+       for (i = 0; i != len; i++) {
+               if (get_user(c, data + i))
+                       return -EFAULT;
+               if (c == 'V')
+                       set_bit(WDOG_ALLOW_RELEASE, &wdd->status);
+       }
+
+       /* someone wrote to us, so we send the watchdog a keepalive ping */
+       watchdog_ping(wdd);
+
+       return len;
+}
+
+/*
+ *     watchdog_ioctl: handle the different ioctl's for the watchdog device.
+ *     @file: file handle to the device
+ *     @cmd: watchdog command
+ *     @arg: argument pointer
+ *
+ *     The watchdog API defines a common set of functions for all watchdogs
+ *     according to their available features.
+ */
+
+static long watchdog_ioctl(struct file *file, unsigned int cmd,
+                                                       unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       unsigned int val;
+       int err;
+
+       if (wdd->ops->ioctl) {
+               err = wdd->ops->ioctl(wdd, cmd, arg);
+               if (err != -ENOIOCTLCMD)
+                       return err;
+       }
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               return copy_to_user(argp, wdd->info,
+                       sizeof(struct watchdog_info)) ? -EFAULT : 0;
+       case WDIOC_GETSTATUS:
+               val = wdd->ops->status ? wdd->ops->status(wdd) : 0;
+               return put_user(val, p);
+       case WDIOC_GETBOOTSTATUS:
+               return put_user(wdd->bootstatus, p);
+       case WDIOC_SETOPTIONS:
+               if (get_user(val, p))
+                       return -EFAULT;
+               if (val & WDIOS_DISABLECARD) {
+                       err = watchdog_stop(wdd);
+                       if (err < 0)
+                               return err;
+               }
+               if (val & WDIOS_ENABLECARD) {
+                       err = watchdog_start(wdd);
+                       if (err < 0)
+                               return err;
+               }
+               return 0;
+       case WDIOC_KEEPALIVE:
+               if (!(wdd->info->options & WDIOF_KEEPALIVEPING))
+                       return -EOPNOTSUPP;
+               watchdog_ping(wdd);
+               return 0;
+       case WDIOC_SETTIMEOUT:
+               if ((wdd->ops->set_timeout == NULL) ||
+                   !(wdd->info->options & WDIOF_SETTIMEOUT))
+                       return -EOPNOTSUPP;
+               if (get_user(val, p))
+                       return -EFAULT;
+               if ((wdd->max_timeout != 0) &&
+                   (val < wdd->min_timeout || val > wdd->max_timeout))
+                               return -EINVAL;
+               err = wdd->ops->set_timeout(wdd, val);
+               if (err < 0)
+                       return err;
+               wdd->timeout = val;
+               /* If the watchdog is active then we send a keepalive ping
+                * to make sure that the watchdog keep's running (and if
+                * possible that it takes the new timeout) */
+               watchdog_ping(wdd);
+               /* Fall */
+       case WDIOC_GETTIMEOUT:
+               /* timeout == 0 means that we don't know the timeout */
+               if (wdd->timeout == 0)
+                       return -EOPNOTSUPP;
+               return put_user(wdd->timeout, p);
+       default:
+               return -ENOTTY;
+       }
+}
+
+/*
+ *     watchdog_open: open the /dev/watchdog device.
+ *     @inode: inode of device
+ *     @file: file handle to device
+ *
+ *     When the /dev/watchdog device gets opened, we start the watchdog.
+ *     Watch out: the /dev/watchdog device is single open, so we make sure
+ *     it can only be opened once.
+ */
+
+static int watchdog_open(struct inode *inode, struct file *file)
+{
+       int err = -EBUSY;
+
+       /* the watchdog is single open! */
+       if (test_and_set_bit(WDOG_DEV_OPEN, &wdd->status))
+               return -EBUSY;
+
+       /*
+        * If the /dev/watchdog device is open, we don't want the module
+        * to be unloaded.
+        */
+       if (!try_module_get(wdd->ops->owner))
+               goto out;
+
+       err = watchdog_start(wdd);
+       if (err < 0)
+               goto out_mod;
+
+       /* dev/watchdog is a virtual (and thus non-seekable) filesystem */
+       return nonseekable_open(inode, file);
+
+out_mod:
+       module_put(wdd->ops->owner);
+out:
+       clear_bit(WDOG_DEV_OPEN, &wdd->status);
+       return err;
+}
+
+/*
+ *      watchdog_release: release the /dev/watchdog device.
+ *      @inode: inode of device
+ *      @file: file handle to device
+ *
+ *     This is the code for when /dev/watchdog gets closed. We will only
+ *     stop the watchdog when we have received the magic char (and nowayout
+ *     was not set), else the watchdog will keep running.
+ */
+
+static int watchdog_release(struct inode *inode, struct file *file)
+{
+       int err = -EBUSY;
+
+       /*
+        * We only stop the watchdog if we received the magic character
+        * or if WDIOF_MAGICCLOSE is not set. If nowayout was set then
+        * watchdog_stop will fail.
+        */
+       if (test_and_clear_bit(WDOG_ALLOW_RELEASE, &wdd->status) ||
+           !(wdd->info->options & WDIOF_MAGICCLOSE))
+               err = watchdog_stop(wdd);
+
+       /* If the watchdog was not stopped, send a keepalive ping */
+       if (err < 0) {
+               pr_crit("%s: watchdog did not stop!\n", wdd->info->identity);
+               watchdog_ping(wdd);
+       }
+
+       /* Allow the owner module to be unloaded again */
+       module_put(wdd->ops->owner);
+
+       /* make sure that /dev/watchdog can be re-opened */
+       clear_bit(WDOG_DEV_OPEN, &wdd->status);
+
+       return 0;
+}
+
+static const struct file_operations watchdog_fops = {
+       .owner          = THIS_MODULE,
+       .write          = watchdog_write,
+       .unlocked_ioctl = watchdog_ioctl,
+       .open           = watchdog_open,
+       .release        = watchdog_release,
+};
+
+static struct miscdevice watchdog_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &watchdog_fops,
+};
+
+/*
+ *     watchdog_dev_register:
+ *     @watchdog: watchdog device
+ *
+ *     Register a watchdog device as /dev/watchdog. /dev/watchdog
+ *     is actually a miscdevice and thus we set it up like that.
+ */
+
+int watchdog_dev_register(struct watchdog_device *watchdog)
+{
+       int err;
+
+       /* Only one device can register for /dev/watchdog */
+       if (test_and_set_bit(0, &watchdog_dev_busy)) {
+               pr_err("only one watchdog can use /dev/watchdog.\n");
+               return -EBUSY;
+       }
+
+       wdd = watchdog;
+
+       err = misc_register(&watchdog_miscdev);
+       if (err != 0) {
+               pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n",
+                       watchdog->info->identity, WATCHDOG_MINOR, err);
+               goto out;
+       }
+
+       return 0;
+
+out:
+       wdd = NULL;
+       clear_bit(0, &watchdog_dev_busy);
+       return err;
+}
+
+/*
+ *     watchdog_dev_unregister:
+ *     @watchdog: watchdog device
+ *
+ *     Deregister the /dev/watchdog device.
+ */
+
+int watchdog_dev_unregister(struct watchdog_device *watchdog)
+{
+       /* Check that a watchdog device was registered in the past */
+       if (!test_bit(0, &watchdog_dev_busy) || !wdd)
+               return -ENODEV;
+
+       /* We can only unregister the watchdog device that was registered */
+       if (watchdog != wdd) {
+               pr_err("%s: watchdog was not registered as /dev/watchdog.\n",
+                       watchdog->info->identity);
+               return -ENODEV;
+       }
+
+       misc_deregister(&watchdog_miscdev);
+       wdd = NULL;
+       clear_bit(0, &watchdog_dev_busy);
+       return 0;
+}
diff --git a/drivers/watchdog/watchdog_dev.h b/drivers/watchdog/watchdog_dev.h
new file mode 100644 (file)
index 0000000..bc7612b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *     watchdog_core.h
+ *
+ *     (c) Copyright 2008-2011 Alan Cox <alan@lxorguk.ukuu.org.uk>,
+ *                                             All Rights Reserved.
+ *
+ *     (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>.
+ *
+ *     This source code is part of the generic code that can be used
+ *     by all the watchdog timer drivers.
+ *
+ *     Based on source code of the following authors:
+ *       Matt Domsch <Matt_Domsch@dell.com>,
+ *       Rob Radez <rob@osinvestor.com>,
+ *       Rusty Lynch <rusty@linux.co.intel.com>
+ *       Satyam Sharma <satyam@infradead.org>
+ *       Randy Dunlap <randy.dunlap@oracle.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.
+ *
+ *     Neither Alan Cox, CymruNet Ltd., Wim Van Sebroeck nor Iguana vzw.
+ *     admit liability nor provide warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ */
+
+/*
+ *     Functions/procedures to be called by the core
+ */
+int watchdog_dev_register(struct watchdog_device *);
+int watchdog_dev_unregister(struct watchdog_device *);
index f815283..5f7ff8e 100644 (file)
@@ -11,7 +11,7 @@ config XEN_BALLOON
 
 config XEN_SELFBALLOONING
        bool "Dynamically self-balloon kernel memory to target"
-       depends on XEN && XEN_BALLOON && CLEANCACHE && SWAP
+       depends on XEN && XEN_BALLOON && CLEANCACHE && SWAP && XEN_TMEM
        default n
        help
          Self-ballooning dynamically balloons available kernel memory driven
index fd725cd..4f44b34 100644 (file)
@@ -82,7 +82,7 @@ static inline grant_ref_t *__gnttab_entry(grant_ref_t entry)
 static int get_free_entries(unsigned count)
 {
        unsigned long flags;
-       int ref, rc;
+       int ref, rc = 0;
        grant_ref_t head;
 
        spin_lock_irqsave(&gnttab_list_lock, flags);
index 206c4ce..978d2c6 100644 (file)
@@ -11,7 +11,6 @@
 #include <xen/xenbus.h>
 #include <xen/events.h>
 #include <asm/xen/pci.h>
-#include <linux/workqueue.h>
 #include "pciback.h"
 
 #define        DRV_NAME        "xen-pciback"
index 010937b..1b4afd8 100644 (file)
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
-
+#include <linux/workqueue.h>
 #include <xen/balloon.h>
-
 #include <xen/tmem.h>
+#include <xen/xen.h>
 
 /* Enable/disable with sysfs. */
 static int xen_selfballooning_enabled __read_mostly;
index e9cb57f..9a1d426 100644 (file)
@@ -182,11 +182,11 @@ int v9fs_set_create_acl(struct dentry *dentry,
        return 0;
 }
 
-int v9fs_acl_mode(struct inode *dir, mode_t *modep,
+int v9fs_acl_mode(struct inode *dir, umode_t *modep,
                  struct posix_acl **dpacl, struct posix_acl **pacl)
 {
        int retval = 0;
-       mode_t mode = *modep;
+       umode_t mode = *modep;
        struct posix_acl *acl = NULL;
 
        if (!S_ISLNK(mode)) {
@@ -319,7 +319,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
        case ACL_TYPE_ACCESS:
                name = POSIX_ACL_XATTR_ACCESS;
                if (acl) {
-                       mode_t mode = inode->i_mode;
+                       umode_t mode = inode->i_mode;
                        retval = posix_acl_equiv_mode(acl, &mode);
                        if (retval < 0)
                                goto err_out;
index ddb7ae1..5595564 100644 (file)
@@ -20,7 +20,7 @@ extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type);
 extern int v9fs_acl_chmod(struct dentry *);
 extern int v9fs_set_create_acl(struct dentry *,
                               struct posix_acl **, struct posix_acl **);
-extern int v9fs_acl_mode(struct inode *dir, mode_t *modep,
+extern int v9fs_acl_mode(struct inode *dir, umode_t *modep,
                         struct posix_acl **dpacl, struct posix_acl **pacl);
 #else
 #define v9fs_iop_get_acl NULL
@@ -38,7 +38,7 @@ static inline int v9fs_set_create_acl(struct dentry *dentry,
 {
        return 0;
 }
-static inline int v9fs_acl_mode(struct inode *dir, mode_t *modep,
+static inline int v9fs_acl_mode(struct inode *dir, umode_t *modep,
                                struct posix_acl **dpacl,
                                struct posix_acl **pacl)
 {
index 9a26dce..b6c8ed2 100644 (file)
@@ -206,7 +206,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
        int err = 0;
        gid_t gid;
        int flags;
-       mode_t mode;
+       umode_t mode;
        char *name = NULL;
        struct file *filp;
        struct p9_qid qid;
@@ -348,7 +348,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
        struct p9_fid *fid = NULL, *dfid = NULL;
        gid_t gid;
        char *name;
-       mode_t mode;
+       umode_t mode;
        struct inode *inode;
        struct p9_qid qid;
        struct dentry *dir_dentry;
@@ -751,7 +751,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
        int err;
        gid_t gid;
        char *name;
-       mode_t mode;
+       umode_t mode;
        struct v9fs_session_info *v9ses;
        struct p9_fid *fid = NULL, *dfid = NULL;
        struct inode *inode;
index 19891aa..9fe0b34 100644 (file)
@@ -127,14 +127,21 @@ config TMPFS_POSIX_ACL
        select TMPFS_XATTR
        select GENERIC_ACL
        help
-         POSIX Access Control Lists (ACLs) support permissions for users and
-         groups beyond the owner/group/world scheme.
+         POSIX Access Control Lists (ACLs) support additional access rights
+         for users and groups beyond the standard owner/group/world scheme,
+         and this option selects support for ACLs specifically for tmpfs
+         filesystems.
+
+         If you've selected TMPFS, it's possible that you'll also need
+         this option as there are a number of Linux distros that require
+         POSIX ACL support under /dev for certain features to work properly.
+         For example, some distros need this feature for ALSA-related /dev
+         files for sound to work properly.  In short, if you're not sure,
+         say Y.
 
          To learn more about Access Control Lists, visit the POSIX ACLs for
          Linux website <http://acl.bestbits.at/>.
 
-         If you don't know what Access Control Lists are, say N.
-
 config TMPFS_XATTR
        bool "Tmpfs extended attributes"
        depends on TMPFS
index 475f9c5..326dc08 100644 (file)
 
 /* #define DEBUG */
 
-#ifdef DEBUG
-#define DPRINTK(fmt, args...)                          \
-do {                                                   \
-       printk(KERN_DEBUG "pid %d: %s: " fmt "\n",      \
-               current->pid, __func__, ##args);        \
-} while (0)
-#else
-#define DPRINTK(fmt, args...) do {} while (0)
-#endif
-
-#define AUTOFS_WARN(fmt, args...)                      \
-do {                                                   \
+#define DPRINTK(fmt, ...)                              \
+       pr_debug("pid %d: %s: " fmt "\n",               \
+               current->pid, __func__, ##__VA_ARGS__)
+
+#define AUTOFS_WARN(fmt, ...)                          \
        printk(KERN_WARNING "pid %d: %s: " fmt "\n",    \
-               current->pid, __func__, ##args);        \
-} while (0)
+               current->pid, __func__, ##__VA_ARGS__)
 
-#define AUTOFS_ERROR(fmt, args...)                     \
-do {                                                   \
+#define AUTOFS_ERROR(fmt, ...)                         \
        printk(KERN_ERR "pid %d: %s: " fmt "\n",        \
-               current->pid, __func__, ##args);        \
-} while (0)
+               current->pid, __func__, ##__VA_ARGS__)
 
 /* Unified info structure.  This is pointed to by both the dentry and
    inode structures.  Each file in the filesystem has an instance of this
index 2543598..e1fbdee 100644 (file)
@@ -104,7 +104,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
        size_t pktsz;
 
        DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d",
-               wq->wait_queue_token, wq->name.len, wq->name.name, type);
+               (unsigned long) wq->wait_queue_token, wq->name.len, wq->name.name, type);
 
        memset(&pkt,0,sizeof pkt); /* For security reasons */
 
index f55aad4..ff77262 100644 (file)
@@ -387,6 +387,10 @@ int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
        struct inode *bd_inode = filp->f_mapping->host;
        struct block_device *bdev = I_BDEV(bd_inode);
        int error;
+       
+       error = filemap_write_and_wait_range(filp->f_mapping, start, end);
+       if (error)
+               return error;
 
        /*
         * There is no need to serialise calls to blkdev_issue_flush with
@@ -552,6 +556,7 @@ struct block_device *bdget(dev_t dev)
 
        if (inode->i_state & I_NEW) {
                bdev->bd_contains = NULL;
+               bdev->bd_super = NULL;
                bdev->bd_inode = inode;
                bdev->bd_block_size = (1 << inode->i_blkbits);
                bdev->bd_part_count = 0;
index 9b72dcf..40e6ac0 100644 (file)
@@ -6,5 +6,7 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
           transaction.o inode.o file.o tree-defrag.o \
           extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
           extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
-          export.o tree-log.o acl.o free-space-cache.o zlib.o lzo.o \
+          export.o tree-log.o free-space-cache.o zlib.o lzo.o \
           compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o
+
+btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o
index 65a735d..eb159aa 100644 (file)
@@ -28,8 +28,6 @@
 #include "btrfs_inode.h"
 #include "xattr.h"
 
-#ifdef CONFIG_BTRFS_FS_POSIX_ACL
-
 struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
 {
        int size;
@@ -111,7 +109,6 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans,
        int ret, size = 0;
        const char *name;
        char *value = NULL;
-       mode_t mode;
 
        if (acl) {
                ret = posix_acl_valid(acl);
@@ -122,13 +119,11 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans,
 
        switch (type) {
        case ACL_TYPE_ACCESS:
-               mode = inode->i_mode;
                name = POSIX_ACL_XATTR_ACCESS;
                if (acl) {
-                       ret = posix_acl_equiv_mode(acl, &mode);
+                       ret = posix_acl_equiv_mode(acl, &inode->i_mode);
                        if (ret < 0)
                                return ret;
-                       inode->i_mode = mode;
                }
                ret = 0;
                break;
@@ -222,19 +217,16 @@ int btrfs_init_acl(struct btrfs_trans_handle *trans,
        }
 
        if (IS_POSIXACL(dir) && acl) {
-               mode_t mode = inode->i_mode;
-
                if (S_ISDIR(inode->i_mode)) {
                        ret = btrfs_set_acl(trans, inode, acl,
                                            ACL_TYPE_DEFAULT);
                        if (ret)
                                goto failed;
                }
-               ret = posix_acl_create(&acl, GFP_NOFS, &mode);
+               ret = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
                if (ret < 0)
                        return ret;
 
-               inode->i_mode = mode;
                if (ret > 0) {
                        /* we need an acl */
                        ret = btrfs_set_acl(trans, inode, acl, ACL_TYPE_ACCESS);
@@ -282,18 +274,3 @@ const struct xattr_handler btrfs_xattr_acl_access_handler = {
        .get    = btrfs_xattr_acl_get,
        .set    = btrfs_xattr_acl_set,
 };
-
-#else /* CONFIG_BTRFS_FS_POSIX_ACL */
-
-int btrfs_acl_chmod(struct inode *inode)
-{
-       return 0;
-}
-
-int btrfs_init_acl(struct btrfs_trans_handle *trans,
-                  struct inode *inode, struct inode *dir)
-{
-       return 0;
-}
-
-#endif /* CONFIG_BTRFS_FS_POSIX_ACL */
index bfe42b0..8ec5d86 100644 (file)
@@ -338,6 +338,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
        u64 first_byte = disk_start;
        struct block_device *bdev;
        int ret;
+       int skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
 
        WARN_ON(start & ((u64)PAGE_CACHE_SIZE - 1));
        cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS);
@@ -392,8 +393,11 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
                        ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
                        BUG_ON(ret);
 
-                       ret = btrfs_csum_one_bio(root, inode, bio, start, 1);
-                       BUG_ON(ret);
+                       if (!skip_sum) {
+                               ret = btrfs_csum_one_bio(root, inode, bio,
+                                                        start, 1);
+                               BUG_ON(ret);
+                       }
 
                        ret = btrfs_map_bio(root, WRITE, bio, 0, 1);
                        BUG_ON(ret);
@@ -418,8 +422,10 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
        ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
        BUG_ON(ret);
 
-       ret = btrfs_csum_one_bio(root, inode, bio, start, 1);
-       BUG_ON(ret);
+       if (!skip_sum) {
+               ret = btrfs_csum_one_bio(root, inode, bio, start, 1);
+               BUG_ON(ret);
+       }
 
        ret = btrfs_map_bio(root, WRITE, bio, 0, 1);
        BUG_ON(ret);
index 365c4e1..0469263 100644 (file)
@@ -2406,8 +2406,8 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct
                         btrfs_root_item *item, struct btrfs_key *key);
 int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid);
 int btrfs_find_orphan_roots(struct btrfs_root *tree_root);
-int btrfs_set_root_node(struct btrfs_root_item *item,
-                       struct extent_buffer *node);
+void btrfs_set_root_node(struct btrfs_root_item *item,
+                        struct extent_buffer *node);
 void btrfs_check_and_init_root_item(struct btrfs_root_item *item);
 
 /* dir-item.c */
@@ -2523,6 +2523,14 @@ struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *pag
 #define PageChecked PageFsMisc
 #endif
 
+/* This forces readahead on a given range of bytes in an inode */
+static inline void btrfs_force_ra(struct address_space *mapping,
+                                 struct file_ra_state *ra, struct file *file,
+                                 pgoff_t offset, unsigned long req_size)
+{
+       page_cache_sync_readahead(mapping, ra, file, offset, req_size);
+}
+
 struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry);
 int btrfs_set_inode_index(struct inode *dir, u64 *index);
 int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
@@ -2551,9 +2559,6 @@ int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
 int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
                         size_t size, struct bio *bio, unsigned long bio_flags);
 
-unsigned long btrfs_force_ra(struct address_space *mapping,
-                             struct file_ra_state *ra, struct file *file,
-                             pgoff_t offset, pgoff_t last_index);
 int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
 int btrfs_readpage(struct file *file, struct page *page);
 void btrfs_evict_inode(struct inode *inode);
@@ -2648,12 +2653,21 @@ do {                                                            \
 /* acl.c */
 #ifdef CONFIG_BTRFS_FS_POSIX_ACL
 struct posix_acl *btrfs_get_acl(struct inode *inode, int type);
-#else
-#define btrfs_get_acl NULL
-#endif
 int btrfs_init_acl(struct btrfs_trans_handle *trans,
                   struct inode *inode, struct inode *dir);
 int btrfs_acl_chmod(struct inode *inode);
+#else
+#define btrfs_get_acl NULL
+static inline int btrfs_init_acl(struct btrfs_trans_handle *trans,
+                                struct inode *inode, struct inode *dir)
+{
+       return 0;
+}
+static inline int btrfs_acl_chmod(struct inode *inode)
+{
+       return 0;
+}
+#endif
 
 /* relocation.c */
 int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start);
index c360a84..31d84e7 100644 (file)
@@ -198,8 +198,6 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
        struct btrfs_key key;
        int ins_len = mod < 0 ? -1 : 0;
        int cow = mod != 0;
-       struct btrfs_key found_key;
-       struct extent_buffer *leaf;
 
        key.objectid = dir;
        btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
@@ -209,18 +207,7 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
        ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
        if (ret < 0)
                return ERR_PTR(ret);
-       if (ret > 0) {
-               if (path->slots[0] == 0)
-                       return NULL;
-               path->slots[0]--;
-       }
-
-       leaf = path->nodes[0];
-       btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
-
-       if (found_key.objectid != dir ||
-           btrfs_key_type(&found_key) != BTRFS_DIR_ITEM_KEY ||
-           found_key.offset != key.offset)
+       if (ret > 0)
                return NULL;
 
        return btrfs_match_dir_item_name(root, path, name, name_len);
@@ -315,8 +302,6 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
        struct btrfs_key key;
        int ins_len = mod < 0 ? -1 : 0;
        int cow = mod != 0;
-       struct btrfs_key found_key;
-       struct extent_buffer *leaf;
 
        key.objectid = dir;
        btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
@@ -324,18 +309,7 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
        ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
        if (ret < 0)
                return ERR_PTR(ret);
-       if (ret > 0) {
-               if (path->slots[0] == 0)
-                       return NULL;
-               path->slots[0]--;
-       }
-
-       leaf = path->nodes[0];
-       btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
-
-       if (found_key.objectid != dir ||
-           btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY ||
-           found_key.offset != key.offset)
+       if (ret > 0)
                return NULL;
 
        return btrfs_match_dir_item_name(root, path, name, name_len);
index 4d08ed7..66bac22 100644 (file)
@@ -663,7 +663,9 @@ int btrfs_lookup_extent(struct btrfs_root *root, u64 start, u64 len)
        struct btrfs_path *path;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
+
        key.objectid = start;
        key.offset = len;
        btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
@@ -3272,6 +3274,9 @@ again:
        }
 
        ret = btrfs_alloc_chunk(trans, extent_root, flags);
+       if (ret < 0 && ret != -ENOSPC)
+               goto out;
+
        spin_lock(&space_info->lock);
        if (ret)
                space_info->full = 1;
@@ -3281,6 +3286,7 @@ again:
        space_info->force_alloc = CHUNK_ALLOC_NO_FORCE;
        space_info->chunk_alloc = 0;
        spin_unlock(&space_info->lock);
+out:
        mutex_unlock(&extent_root->fs_info->chunk_mutex);
        return ret;
 }
@@ -4456,7 +4462,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                                printk(KERN_ERR "umm, got %d back from search"
                                       ", was looking for %llu\n", ret,
                                       (unsigned long long)bytenr);
-                               btrfs_print_leaf(extent_root, path->nodes[0]);
+                               if (ret > 0)
+                                       btrfs_print_leaf(extent_root,
+                                                        path->nodes[0]);
                        }
                        BUG_ON(ret);
                        extent_slot = path->slots[0];
@@ -5073,7 +5081,9 @@ have_block_group:
                         * group is does point to and try again
                         */
                        if (!last_ptr_loop && last_ptr->block_group &&
-                           last_ptr->block_group != block_group) {
+                           last_ptr->block_group != block_group &&
+                           index <=
+                                get_block_group_index(last_ptr->block_group)) {
 
                                btrfs_put_block_group(block_group);
                                block_group = last_ptr->block_group;
@@ -5501,7 +5511,8 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
        u32 size = sizeof(*extent_item) + sizeof(*block_info) + sizeof(*iref);
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        path->leave_spinning = 1;
        ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
@@ -6272,10 +6283,14 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
        int level;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        wc = kzalloc(sizeof(*wc), GFP_NOFS);
-       BUG_ON(!wc);
+       if (!wc) {
+               btrfs_free_path(path);
+               return -ENOMEM;
+       }
 
        trans = btrfs_start_transaction(tree_root, 0);
        BUG_ON(IS_ERR(trans));
@@ -6538,8 +6553,6 @@ static int set_block_group_ro(struct btrfs_block_group_cache *cache, int force)
        u64 min_allocable_bytes;
        int ret = -ENOSPC;
 
-       if (cache->ro)
-               return 0;
 
        /*
         * We need some metadata space and system metadata space for
@@ -6555,6 +6568,12 @@ static int set_block_group_ro(struct btrfs_block_group_cache *cache, int force)
 
        spin_lock(&sinfo->lock);
        spin_lock(&cache->lock);
+
+       if (cache->ro) {
+               ret = 0;
+               goto out;
+       }
+
        num_bytes = cache->key.offset - cache->reserved - cache->pinned -
                    cache->bytes_super - btrfs_block_group_used(&cache->item);
 
@@ -6568,7 +6587,7 @@ static int set_block_group_ro(struct btrfs_block_group_cache *cache, int force)
                cache->ro = 1;
                ret = 0;
        }
-
+out:
        spin_unlock(&cache->lock);
        spin_unlock(&sinfo->lock);
        return ret;
@@ -7183,11 +7202,15 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        spin_unlock(&cluster->refill_lock);
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path) {
+               ret = -ENOMEM;
+               goto out;
+       }
 
        inode = lookup_free_space_inode(root, block_group, path);
        if (!IS_ERR(inode)) {
-               btrfs_orphan_add(trans, inode);
+               ret = btrfs_orphan_add(trans, inode);
+               BUG_ON(ret);
                clear_nlink(inode);
                /* One for the block groups ref */
                spin_lock(&block_group->lock);
index 067b174..d418164 100644 (file)
@@ -254,14 +254,14 @@ static void merge_cb(struct extent_io_tree *tree, struct extent_state *new,
  *
  * This should be called with the tree lock held.
  */
-static int merge_state(struct extent_io_tree *tree,
-                      struct extent_state *state)
+static void merge_state(struct extent_io_tree *tree,
+                       struct extent_state *state)
 {
        struct extent_state *other;
        struct rb_node *other_node;
 
        if (state->state & (EXTENT_IOBITS | EXTENT_BOUNDARY))
-               return 0;
+               return;
 
        other_node = rb_prev(&state->rb_node);
        if (other_node) {
@@ -287,19 +287,13 @@ static int merge_state(struct extent_io_tree *tree,
                        free_extent_state(other);
                }
        }
-
-       return 0;
 }
 
-static int set_state_cb(struct extent_io_tree *tree,
+static void set_state_cb(struct extent_io_tree *tree,
                         struct extent_state *state, int *bits)
 {
-       if (tree->ops && tree->ops->set_bit_hook) {
-               return tree->ops->set_bit_hook(tree->mapping->host,
-                                              state, bits);
-       }
-
-       return 0;
+       if (tree->ops && tree->ops->set_bit_hook)
+               tree->ops->set_bit_hook(tree->mapping->host, state, bits);
 }
 
 static void clear_state_cb(struct extent_io_tree *tree,
@@ -309,6 +303,9 @@ static void clear_state_cb(struct extent_io_tree *tree,
                tree->ops->clear_bit_hook(tree->mapping->host, state, bits);
 }
 
+static void set_state_bits(struct extent_io_tree *tree,
+                          struct extent_state *state, int *bits);
+
 /*
  * insert an extent_state struct into the tree.  'bits' are set on the
  * struct before it is inserted.
@@ -324,8 +321,6 @@ static int insert_state(struct extent_io_tree *tree,
                        int *bits)
 {
        struct rb_node *node;
-       int bits_to_set = *bits & ~EXTENT_CTLBITS;
-       int ret;
 
        if (end < start) {
                printk(KERN_ERR "btrfs end < start %llu %llu\n",
@@ -335,13 +330,9 @@ static int insert_state(struct extent_io_tree *tree,
        }
        state->start = start;
        state->end = end;
-       ret = set_state_cb(tree, state, bits);
-       if (ret)
-               return ret;
 
-       if (bits_to_set & EXTENT_DIRTY)
-               tree->dirty_bytes += end - start + 1;
-       state->state |= bits_to_set;
+       set_state_bits(tree, state, bits);
+
        node = tree_insert(&tree->state, end, &state->rb_node);
        if (node) {
                struct extent_state *found;
@@ -357,13 +348,11 @@ static int insert_state(struct extent_io_tree *tree,
        return 0;
 }
 
-static int split_cb(struct extent_io_tree *tree, struct extent_state *orig,
+static void split_cb(struct extent_io_tree *tree, struct extent_state *orig,
                     u64 split)
 {
        if (tree->ops && tree->ops->split_extent_hook)
-               return tree->ops->split_extent_hook(tree->mapping->host,
-                                                   orig, split);
-       return 0;
+               tree->ops->split_extent_hook(tree->mapping->host, orig, split);
 }
 
 /*
@@ -659,34 +648,25 @@ again:
                if (start > end)
                        break;
 
-               if (need_resched()) {
-                       spin_unlock(&tree->lock);
-                       cond_resched();
-                       spin_lock(&tree->lock);
-               }
+               cond_resched_lock(&tree->lock);
        }
 out:
        spin_unlock(&tree->lock);
        return 0;
 }
 
-static int set_state_bits(struct extent_io_tree *tree,
+static void set_state_bits(struct extent_io_tree *tree,
                           struct extent_state *state,
                           int *bits)
 {
-       int ret;
        int bits_to_set = *bits & ~EXTENT_CTLBITS;
 
-       ret = set_state_cb(tree, state, bits);
-       if (ret)
-               return ret;
+       set_state_cb(tree, state, bits);
        if ((bits_to_set & EXTENT_DIRTY) && !(state->state & EXTENT_DIRTY)) {
                u64 range = state->end - state->start + 1;
                tree->dirty_bytes += range;
        }
        state->state |= bits_to_set;
-
-       return 0;
 }
 
 static void cache_state(struct extent_state *state,
@@ -779,9 +759,7 @@ hit_next:
                        goto out;
                }
 
-               err = set_state_bits(tree, state, &bits);
-               if (err)
-                       goto out;
+               set_state_bits(tree, state, &bits);
 
                cache_state(state, cached_state);
                merge_state(tree, state);
@@ -830,9 +808,7 @@ hit_next:
                if (err)
                        goto out;
                if (state->end <= end) {
-                       err = set_state_bits(tree, state, &bits);
-                       if (err)
-                               goto out;
+                       set_state_bits(tree, state, &bits);
                        cache_state(state, cached_state);
                        merge_state(tree, state);
                        if (last_end == (u64)-1)
@@ -893,11 +869,7 @@ hit_next:
                err = split_state(tree, state, prealloc, end + 1);
                BUG_ON(err == -EEXIST);
 
-               err = set_state_bits(tree, prealloc, &bits);
-               if (err) {
-                       prealloc = NULL;
-                       goto out;
-               }
+               set_state_bits(tree, prealloc, &bits);
                cache_state(prealloc, cached_state);
                merge_state(tree, prealloc);
                prealloc = NULL;
@@ -1059,46 +1031,6 @@ static int set_range_writeback(struct extent_io_tree *tree, u64 start, u64 end)
        return 0;
 }
 
-/*
- * find the first offset in the io tree with 'bits' set. zero is
- * returned if we find something, and *start_ret and *end_ret are
- * set to reflect the state struct that was found.
- *
- * If nothing was found, 1 is returned, < 0 on error
- */
-int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
-                         u64 *start_ret, u64 *end_ret, int bits)
-{
-       struct rb_node *node;
-       struct extent_state *state;
-       int ret = 1;
-
-       spin_lock(&tree->lock);
-       /*
-        * this search will find all the extents that end after
-        * our range starts.
-        */
-       node = tree_search(tree, start);
-       if (!node)
-               goto out;
-
-       while (1) {
-               state = rb_entry(node, struct extent_state, rb_node);
-               if (state->end >= start && (state->state & bits)) {
-                       *start_ret = state->start;
-                       *end_ret = state->end;
-                       ret = 0;
-                       break;
-               }
-               node = rb_next(node);
-               if (!node)
-                       break;
-       }
-out:
-       spin_unlock(&tree->lock);
-       return ret;
-}
-
 /* find the first state struct with 'bits' set after 'start', and
  * return it.  tree->lock must be held.  NULL will returned if
  * nothing was found after 'start'
@@ -1130,6 +1062,30 @@ out:
        return NULL;
 }
 
+/*
+ * find the first offset in the io tree with 'bits' set. zero is
+ * returned if we find something, and *start_ret and *end_ret are
+ * set to reflect the state struct that was found.
+ *
+ * If nothing was found, 1 is returned, < 0 on error
+ */
+int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
+                         u64 *start_ret, u64 *end_ret, int bits)
+{
+       struct extent_state *state;
+       int ret = 1;
+
+       spin_lock(&tree->lock);
+       state = find_first_extent_bit_state(tree, start, bits);
+       if (state) {
+               *start_ret = state->start;
+               *end_ret = state->end;
+               ret = 0;
+       }
+       spin_unlock(&tree->lock);
+       return ret;
+}
+
 /*
  * find a contiguous range of bytes in the file marked as delalloc, not
  * more than 'max_bytes'.  start and end are used to return the range,
@@ -2546,7 +2502,6 @@ int extent_write_full_page(struct extent_io_tree *tree, struct page *page,
                          struct writeback_control *wbc)
 {
        int ret;
-       struct address_space *mapping = page->mapping;
        struct extent_page_data epd = {
                .bio = NULL,
                .tree = tree,
@@ -2554,17 +2509,9 @@ int extent_write_full_page(struct extent_io_tree *tree, struct page *page,
                .extent_locked = 0,
                .sync_io = wbc->sync_mode == WB_SYNC_ALL,
        };
-       struct writeback_control wbc_writepages = {
-               .sync_mode      = wbc->sync_mode,
-               .nr_to_write    = 64,
-               .range_start    = page_offset(page) + PAGE_CACHE_SIZE,
-               .range_end      = (loff_t)-1,
-       };
 
        ret = __extent_writepage(page, wbc, &epd);
 
-       extent_write_cache_pages(tree, mapping, &wbc_writepages,
-                                __extent_writepage, &epd, flush_write_bio);
        flush_epd_write_bio(&epd);
        return ret;
 }
index 21a7ca9..7b2f0c3 100644 (file)
@@ -76,15 +76,15 @@ struct extent_io_ops {
                                    struct extent_state *state);
        int (*writepage_end_io_hook)(struct page *page, u64 start, u64 end,
                                      struct extent_state *state, int uptodate);
-       int (*set_bit_hook)(struct inode *inode, struct extent_state *state,
-                           int *bits);
-       int (*clear_bit_hook)(struct inode *inode, struct extent_state *state,
-                             int *bits);
-       int (*merge_extent_hook)(struct inode *inode,
-                                struct extent_state *new,
-                                struct extent_state *other);
-       int (*split_extent_hook)(struct inode *inode,
-                                struct extent_state *orig, u64 split);
+       void (*set_bit_hook)(struct inode *inode, struct extent_state *state,
+                            int *bits);
+       void (*clear_bit_hook)(struct inode *inode, struct extent_state *state,
+                              int *bits);
+       void (*merge_extent_hook)(struct inode *inode,
+                                 struct extent_state *new,
+                                 struct extent_state *other);
+       void (*split_extent_hook)(struct inode *inode,
+                                 struct extent_state *orig, u64 split);
        int (*write_cache_pages_lock_hook)(struct page *page);
 };
 
@@ -108,8 +108,6 @@ struct extent_state {
        wait_queue_head_t wq;
        atomic_t refs;
        unsigned long state;
-       u64 split_start;
-       u64 split_end;
 
        /* for use by the FS */
        u64 private;
index 2d04103..7c97b33 100644 (file)
@@ -183,22 +183,10 @@ static int mergable_maps(struct extent_map *prev, struct extent_map *next)
        return 0;
 }
 
-int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len)
+static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
 {
-       int ret = 0;
        struct extent_map *merge = NULL;
        struct rb_node *rb;
-       struct extent_map *em;
-
-       write_lock(&tree->lock);
-       em = lookup_extent_mapping(tree, start, len);
-
-       WARN_ON(!em || em->start != start);
-
-       if (!em)
-               goto out;
-
-       clear_bit(EXTENT_FLAG_PINNED, &em->flags);
 
        if (em->start != 0) {
                rb = rb_prev(&em->rb_node);
@@ -225,6 +213,24 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len)
                merge->in_tree = 0;
                free_extent_map(merge);
        }
+}
+
+int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len)
+{
+       int ret = 0;
+       struct extent_map *em;
+
+       write_lock(&tree->lock);
+       em = lookup_extent_mapping(tree, start, len);
+
+       WARN_ON(!em || em->start != start);
+
+       if (!em)
+               goto out;
+
+       clear_bit(EXTENT_FLAG_PINNED, &em->flags);
+
+       try_merge_map(tree, em);
 
        free_extent_map(em);
 out:
@@ -247,7 +253,6 @@ int add_extent_mapping(struct extent_map_tree *tree,
                       struct extent_map *em)
 {
        int ret = 0;
-       struct extent_map *merge = NULL;
        struct rb_node *rb;
        struct extent_map *exist;
 
@@ -263,30 +268,8 @@ int add_extent_mapping(struct extent_map_tree *tree,
                goto out;
        }
        atomic_inc(&em->refs);
-       if (em->start != 0) {
-               rb = rb_prev(&em->rb_node);
-               if (rb)
-                       merge = rb_entry(rb, struct extent_map, rb_node);
-               if (rb && mergable_maps(merge, em)) {
-                       em->start = merge->start;
-                       em->len += merge->len;
-                       em->block_len += merge->block_len;
-                       em->block_start = merge->block_start;
-                       merge->in_tree = 0;
-                       rb_erase(&merge->rb_node, &tree->map);
-                       free_extent_map(merge);
-               }
-        }
-       rb = rb_next(&em->rb_node);
-       if (rb)
-               merge = rb_entry(rb, struct extent_map, rb_node);
-       if (rb && mergable_maps(em, merge)) {
-               em->len += merge->len;
-               em->block_len += merge->len;
-               rb_erase(&merge->rb_node, &tree->map);
-               merge->in_tree = 0;
-               free_extent_map(merge);
-       }
+
+       try_merge_map(tree, em);
 out:
        return ret;
 }
@@ -299,19 +282,8 @@ static u64 range_end(u64 start, u64 len)
        return start + len;
 }
 
-/**
- * lookup_extent_mapping - lookup extent_map
- * @tree:      tree to lookup in
- * @start:     byte offset to start the search
- * @len:       length of the lookup range
- *
- * Find and return the first extent_map struct in @tree that intersects the
- * [start, len] range.  There may be additional objects in the tree that
- * intersect, so check the object returned carefully to make sure that no
- * additional lookups are needed.
- */
-struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree,
-                                        u64 start, u64 len)
+struct extent_map *__lookup_extent_mapping(struct extent_map_tree *tree,
+                                          u64 start, u64 len, int strict)
 {
        struct extent_map *em;
        struct rb_node *rb_node;
@@ -320,37 +292,41 @@ struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree,
        u64 end = range_end(start, len);
 
        rb_node = __tree_search(&tree->map, start, &prev, &next);
-       if (!rb_node && prev) {
-               em = rb_entry(prev, struct extent_map, rb_node);
-               if (end > em->start && start < extent_map_end(em))
-                       goto found;
-       }
-       if (!rb_node && next) {
-               em = rb_entry(next, struct extent_map, rb_node);
-               if (end > em->start && start < extent_map_end(em))
-                       goto found;
-       }
        if (!rb_node) {
-               em = NULL;
-               goto out;
-       }
-       if (IS_ERR(rb_node)) {
-               em = ERR_CAST(rb_node);
-               goto out;
+               if (prev)
+                       rb_node = prev;
+               else if (next)
+                       rb_node = next;
+               else
+                       return NULL;
        }
+
        em = rb_entry(rb_node, struct extent_map, rb_node);
-       if (end > em->start && start < extent_map_end(em))
-               goto found;
 
-       em = NULL;
-       goto out;
+       if (strict && !(end > em->start && start < extent_map_end(em)))
+               return NULL;
 
-found:
        atomic_inc(&em->refs);
-out:
        return em;
 }
 
+/**
+ * lookup_extent_mapping - lookup extent_map
+ * @tree:      tree to lookup in
+ * @start:     byte offset to start the search
+ * @len:       length of the lookup range
+ *
+ * Find and return the first extent_map struct in @tree that intersects the
+ * [start, len] range.  There may be additional objects in the tree that
+ * intersect, so check the object returned carefully to make sure that no
+ * additional lookups are needed.
+ */
+struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree,
+                                        u64 start, u64 len)
+{
+       return __lookup_extent_mapping(tree, start, len, 1);
+}
+
 /**
  * search_extent_mapping - find a nearby extent map
  * @tree:      tree to lookup in
@@ -365,38 +341,7 @@ out:
 struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
                                         u64 start, u64 len)
 {
-       struct extent_map *em;
-       struct rb_node *rb_node;
-       struct rb_node *prev = NULL;
-       struct rb_node *next = NULL;
-
-       rb_node = __tree_search(&tree->map, start, &prev, &next);
-       if (!rb_node && prev) {
-               em = rb_entry(prev, struct extent_map, rb_node);
-               goto found;
-       }
-       if (!rb_node && next) {
-               em = rb_entry(next, struct extent_map, rb_node);
-               goto found;
-       }
-       if (!rb_node) {
-               em = NULL;
-               goto out;
-       }
-       if (IS_ERR(rb_node)) {
-               em = ERR_CAST(rb_node);
-               goto out;
-       }
-       em = rb_entry(rb_node, struct extent_map, rb_node);
-       goto found;
-
-       em = NULL;
-       goto out;
-
-found:
-       atomic_inc(&em->refs);
-out:
-       return em;
+       return __lookup_extent_mapping(tree, start, len, 0);
 }
 
 /**
index 08bcfa9..b910694 100644 (file)
@@ -291,7 +291,8 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
        u16 csum_size = btrfs_super_csum_size(&root->fs_info->super_copy);
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        if (search_commit) {
                path->skip_locking = 1;
@@ -677,7 +678,9 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
                btrfs_super_csum_size(&root->fs_info->super_copy);
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
+
        sector_sum = sums->sums;
 again:
        next_offset = (u64)-1;
index a35e51c..658d669 100644 (file)
@@ -74,7 +74,7 @@ struct inode_defrag {
  * If an existing record is found the defrag item you
  * pass in is freed
  */
-static int __btrfs_add_inode_defrag(struct inode *inode,
+static void __btrfs_add_inode_defrag(struct inode *inode,
                                    struct inode_defrag *defrag)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -106,11 +106,11 @@ static int __btrfs_add_inode_defrag(struct inode *inode,
        BTRFS_I(inode)->in_defrag = 1;
        rb_link_node(&defrag->rb_node, parent, p);
        rb_insert_color(&defrag->rb_node, &root->fs_info->defrag_inodes);
-       return 0;
+       return;
 
 exists:
        kfree(defrag);
-       return 0;
+       return;
 
 }
 
@@ -123,7 +123,6 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct inode_defrag *defrag;
-       int ret = 0;
        u64 transid;
 
        if (!btrfs_test_opt(root, AUTO_DEFRAG))
@@ -150,9 +149,9 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
 
        spin_lock(&root->fs_info->defrag_inodes_lock);
        if (!BTRFS_I(inode)->in_defrag)
-               ret = __btrfs_add_inode_defrag(inode, defrag);
+               __btrfs_add_inode_defrag(inode, defrag);
        spin_unlock(&root->fs_info->defrag_inodes_lock);
-       return ret;
+       return 0;
 }
 
 /*
@@ -855,7 +854,8 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
        btrfs_drop_extent_cache(inode, start, end - 1, 0);
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 again:
        recow = 0;
        split = start;
@@ -1059,7 +1059,7 @@ static int prepare_uptodate_page(struct page *page, u64 pos)
 static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
                         struct page **pages, size_t num_pages,
                         loff_t pos, unsigned long first_index,
-                        unsigned long last_index, size_t write_bytes)
+                        size_t write_bytes)
 {
        struct extent_state *cached_state = NULL;
        int i;
@@ -1159,7 +1159,6 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct page **pages = NULL;
        unsigned long first_index;
-       unsigned long last_index;
        size_t num_written = 0;
        int nrptrs;
        int ret = 0;
@@ -1172,7 +1171,6 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
                return -ENOMEM;
 
        first_index = pos >> PAGE_CACHE_SHIFT;
-       last_index = (pos + iov_iter_count(i)) >> PAGE_CACHE_SHIFT;
 
        while (iov_iter_count(i) > 0) {
                size_t offset = pos & (PAGE_CACHE_SIZE - 1);
@@ -1206,8 +1204,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
                 * contents of pages from loop to loop
                 */
                ret = prepare_pages(root, file, pages, num_pages,
-                                   pos, first_index, last_index,
-                                   write_bytes);
+                                   pos, first_index, write_bytes);
                if (ret) {
                        btrfs_delalloc_release_space(inode,
                                        num_pages << PAGE_CACHE_SHIFT);
index 13e6255..15fceef 100644 (file)
@@ -1061,7 +1061,8 @@ static noinline int run_delalloc_nocow(struct inode *inode,
        u64 ino = btrfs_ino(inode);
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        nolock = btrfs_is_free_space_inode(root, inode);
 
@@ -1282,17 +1283,16 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page,
        return ret;
 }
 
-static int btrfs_split_extent_hook(struct inode *inode,
-                                  struct extent_state *orig, u64 split)
+static void btrfs_split_extent_hook(struct inode *inode,
+                                   struct extent_state *orig, u64 split)
 {
        /* not delalloc, ignore it */
        if (!(orig->state & EXTENT_DELALLOC))
-               return 0;
+               return;
 
        spin_lock(&BTRFS_I(inode)->lock);
        BTRFS_I(inode)->outstanding_extents++;
        spin_unlock(&BTRFS_I(inode)->lock);
-       return 0;
 }
 
 /*
@@ -1301,18 +1301,17 @@ static int btrfs_split_extent_hook(struct inode *inode,
  * extents, such as when we are doing sequential writes, so we can properly
  * account for the metadata space we'll need.
  */
-static int btrfs_merge_extent_hook(struct inode *inode,
-                                  struct extent_state *new,
-                                  struct extent_state *other)
+static void btrfs_merge_extent_hook(struct inode *inode,
+                                   struct extent_state *new,
+                                   struct extent_state *other)
 {
        /* not delalloc, ignore it */
        if (!(other->state & EXTENT_DELALLOC))
-               return 0;
+               return;
 
        spin_lock(&BTRFS_I(inode)->lock);
        BTRFS_I(inode)->outstanding_extents--;
        spin_unlock(&BTRFS_I(inode)->lock);
-       return 0;
 }
 
 /*
@@ -1320,8 +1319,8 @@ static int btrfs_merge_extent_hook(struct inode *inode,
  * bytes in this file, and to maintain the list of inodes that
  * have pending delalloc work to be done.
  */
-static int btrfs_set_bit_hook(struct inode *inode,
-                             struct extent_state *state, int *bits)
+static void btrfs_set_bit_hook(struct inode *inode,
+                              struct extent_state *state, int *bits)
 {
 
        /*
@@ -1351,14 +1350,13 @@ static int btrfs_set_bit_hook(struct inode *inode,
                }
                spin_unlock(&root->fs_info->delalloc_lock);
        }
-       return 0;
 }
 
 /*
  * extent_io.c clear_bit_hook, see set_bit_hook for why
  */
-static int btrfs_clear_bit_hook(struct inode *inode,
-                               struct extent_state *state, int *bits)
+static void btrfs_clear_bit_hook(struct inode *inode,
+                                struct extent_state *state, int *bits)
 {
        /*
         * set_bit and clear bit hooks normally require _irqsave/restore
@@ -1395,7 +1393,6 @@ static int btrfs_clear_bit_hook(struct inode *inode,
                }
                spin_unlock(&root->fs_info->delalloc_lock);
        }
-       return 0;
 }
 
 /*
@@ -1645,7 +1642,8 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
        int ret;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        path->leave_spinning = 1;
 
@@ -2215,7 +2213,8 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode)
 
        if (!root->orphan_block_rsv) {
                block_rsv = btrfs_alloc_block_rsv(root);
-               BUG_ON(!block_rsv);
+               if (!block_rsv)
+                       return -ENOMEM;
        }
 
        spin_lock(&root->orphan_lock);
@@ -2517,7 +2516,9 @@ static void btrfs_read_locked_inode(struct inode *inode)
                filled = true;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               goto make_bad;
+
        path->leave_spinning = 1;
        memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
 
@@ -2998,13 +2999,16 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
 
        ret = btrfs_unlink_inode(trans, root, dir, dentry->d_inode,
                                 dentry->d_name.name, dentry->d_name.len);
-       BUG_ON(ret);
+       if (ret)
+               goto out;
 
        if (inode->i_nlink == 0) {
                ret = btrfs_orphan_add(trans, inode);
-               BUG_ON(ret);
+               if (ret)
+                       goto out;
        }
 
+out:
        nr = trans->blocks_used;
        __unlink_end_trans(trans, root);
        btrfs_btree_balance_dirty(root, nr);
@@ -3147,6 +3151,11 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
 
        BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
 
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+       path->reada = -1;
+
        if (root->ref_cows || root == root->fs_info->tree_root)
                btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0);
 
@@ -3159,10 +3168,6 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
        if (min_type == 0 && root == BTRFS_I(inode)->root)
                btrfs_kill_delayed_inode_items(inode);
 
-       path = btrfs_alloc_path();
-       BUG_ON(!path);
-       path->reada = -1;
-
        key.objectid = ino;
        key.offset = (u64)-1;
        key.type = (u8)-1;
@@ -3690,7 +3695,8 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry,
        int ret = 0;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        di = btrfs_lookup_dir_item(NULL, root, path, btrfs_ino(dir), name,
                                    namelen, 0);
@@ -3946,6 +3952,7 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
                         struct btrfs_root *root, int *new)
 {
        struct inode *inode;
+       int bad_inode = 0;
 
        inode = btrfs_iget_locked(s, location->objectid, root);
        if (!inode)
@@ -3955,10 +3962,19 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
                BTRFS_I(inode)->root = root;
                memcpy(&BTRFS_I(inode)->location, location, sizeof(*location));
                btrfs_read_locked_inode(inode);
-               inode_tree_add(inode);
-               unlock_new_inode(inode);
-               if (new)
-                       *new = 1;
+               if (!is_bad_inode(inode)) {
+                       inode_tree_add(inode);
+                       unlock_new_inode(inode);
+                       if (new)
+                               *new = 1;
+               } else {
+                       bad_inode = 1;
+               }
+       }
+
+       if (bad_inode) {
+               iput(inode);
+               inode = ERR_PTR(-ESTALE);
        }
 
        return inode;
@@ -3993,12 +4009,19 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
        struct btrfs_root *sub_root = root;
        struct btrfs_key location;
        int index;
-       int ret;
+       int ret = 0;
 
        if (dentry->d_name.len > BTRFS_NAME_LEN)
                return ERR_PTR(-ENAMETOOLONG);
 
-       ret = btrfs_inode_by_name(dir, dentry, &location);
+       if (unlikely(d_need_lookup(dentry))) {
+               memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key));
+               kfree(dentry->d_fsdata);
+               dentry->d_fsdata = NULL;
+               d_clear_need_lookup(dentry);
+       } else {
+               ret = btrfs_inode_by_name(dir, dentry, &location);
+       }
 
        if (ret < 0)
                return ERR_PTR(ret);
@@ -4053,6 +4076,12 @@ static int btrfs_dentry_delete(const struct dentry *dentry)
        return 0;
 }
 
+static void btrfs_dentry_release(struct dentry *dentry)
+{
+       if (dentry->d_fsdata)
+               kfree(dentry->d_fsdata);
+}
+
 static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
                                   struct nameidata *nd)
 {
@@ -4075,6 +4104,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
        struct btrfs_path *path;
        struct list_head ins_list;
        struct list_head del_list;
+       struct qstr q;
        int ret;
        struct extent_buffer *leaf;
        int slot;
@@ -4164,6 +4194,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
 
                while (di_cur < di_total) {
                        struct btrfs_key location;
+                       struct dentry *tmp;
 
                        if (verify_dir_item(root, leaf, di))
                                break;
@@ -4184,6 +4215,33 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
                        d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
                        btrfs_dir_item_key_to_cpu(leaf, di, &location);
 
+                       q.name = name_ptr;
+                       q.len = name_len;
+                       q.hash = full_name_hash(q.name, q.len);
+                       tmp = d_lookup(filp->f_dentry, &q);
+                       if (!tmp) {
+                               struct btrfs_key *newkey;
+
+                               newkey = kzalloc(sizeof(struct btrfs_key),
+                                                GFP_NOFS);
+                               if (!newkey)
+                                       goto no_dentry;
+                               tmp = d_alloc(filp->f_dentry, &q);
+                               if (!tmp) {
+                                       kfree(newkey);
+                                       dput(tmp);
+                                       goto no_dentry;
+                               }
+                               memcpy(newkey, &location,
+                                      sizeof(struct btrfs_key));
+                               tmp->d_fsdata = newkey;
+                               tmp->d_flags |= DCACHE_NEED_LOOKUP;
+                               d_rehash(tmp);
+                               dput(tmp);
+                       } else {
+                               dput(tmp);
+                       }
+no_dentry:
                        /* is this a reference to our own snapshot? If so
                         * skip it
                         */
@@ -4409,7 +4467,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
        int owner;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return ERR_PTR(-ENOMEM);
 
        inode = new_inode(root->fs_info->sb);
        if (!inode) {
@@ -6669,19 +6728,6 @@ int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-/* helper function for file defrag and space balancing.  This
- * forces readahead on a given range of bytes in an inode
- */
-unsigned long btrfs_force_ra(struct address_space *mapping,
-                             struct file_ra_state *ra, struct file *file,
-                             pgoff_t offset, pgoff_t last_index)
-{
-       pgoff_t req_size = last_index - offset + 1;
-
-       page_cache_sync_readahead(mapping, ra, file, offset, req_size);
-       return offset + req_size;
-}
-
 struct inode *btrfs_alloc_inode(struct super_block *sb)
 {
        struct btrfs_inode *ei;
@@ -7164,7 +7210,11 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
                goto out_unlock;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path) {
+               err = -ENOMEM;
+               drop_inode = 1;
+               goto out_unlock;
+       }
        key.objectid = btrfs_ino(inode);
        key.offset = 0;
        btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY);
@@ -7430,4 +7480,5 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
 
 const struct dentry_operations btrfs_dentry_operations = {
        .d_delete       = btrfs_dentry_delete,
+       .d_release      = btrfs_dentry_release,
 };
index 0b980af..7cf0133 100644 (file)
@@ -1749,11 +1749,10 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info,
                key.objectid = key.offset;
                key.offset = (u64)-1;
                dirid = key.objectid;
-
        }
        if (ptr < name)
                goto out;
-       memcpy(name, ptr, total_len);
+       memmove(name, ptr, total_len);
        name[total_len]='\0';
        ret = 0;
 out:
diff --git a/fs/btrfs/ref-cache.c b/fs/btrfs/ref-cache.c
deleted file mode 100644 (file)
index 82d569c..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2008 Oracle.  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 v2 as published by the Free Software Foundation.
- *
- * 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 021110-1307, USA.
- */
-
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/sort.h>
-#include "ctree.h"
-#include "ref-cache.h"
-#include "transaction.h"
-
-static struct rb_node *tree_insert(struct rb_root *root, u64 bytenr,
-                                  struct rb_node *node)
-{
-       struct rb_node **p = &root->rb_node;
-       struct rb_node *parent = NULL;
-       struct btrfs_leaf_ref *entry;
-
-       while (*p) {
-               parent = *p;
-               entry = rb_entry(parent, struct btrfs_leaf_ref, rb_node);
-
-               if (bytenr < entry->bytenr)
-                       p = &(*p)->rb_left;
-               else if (bytenr > entry->bytenr)
-                       p = &(*p)->rb_right;
-               else
-                       return parent;
-       }
-
-       entry = rb_entry(node, struct btrfs_leaf_ref, rb_node);
-       rb_link_node(node, parent, p);
-       rb_insert_color(node, root);
-       return NULL;
-}
-
-static struct rb_node *tree_search(struct rb_root *root, u64 bytenr)
-{
-       struct rb_node *n = root->rb_node;
-       struct btrfs_leaf_ref *entry;
-
-       while (n) {
-               entry = rb_entry(n, struct btrfs_leaf_ref, rb_node);
-               WARN_ON(!entry->in_tree);
-
-               if (bytenr < entry->bytenr)
-                       n = n->rb_left;
-               else if (bytenr > entry->bytenr)
-                       n = n->rb_right;
-               else
-                       return n;
-       }
-       return NULL;
-}
diff --git a/fs/btrfs/ref-cache.h b/fs/btrfs/ref-cache.h
deleted file mode 100644 (file)
index 24f7001..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2008 Oracle.  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 v2 as published by the Free Software Foundation.
- *
- * 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 021110-1307, USA.
- */
-#ifndef __REFCACHE__
-#define __REFCACHE__
-
-struct btrfs_extent_info {
-       /* bytenr and num_bytes find the extent in the extent allocation tree */
-       u64 bytenr;
-       u64 num_bytes;
-
-       /* objectid and offset find the back reference for the file */
-       u64 objectid;
-       u64 offset;
-};
-
-struct btrfs_leaf_ref {
-       struct rb_node rb_node;
-       struct btrfs_leaf_ref_tree *tree;
-       int in_tree;
-       atomic_t usage;
-
-       u64 root_gen;
-       u64 bytenr;
-       u64 owner;
-       u64 generation;
-       int nritems;
-
-       struct list_head list;
-       struct btrfs_extent_info extents[];
-};
-
-static inline size_t btrfs_leaf_ref_size(int nr_extents)
-{
-       return sizeof(struct btrfs_leaf_ref) +
-              sizeof(struct btrfs_extent_info) * nr_extents;
-}
-#endif
index ebe4544..f409990 100644 (file)
@@ -71,13 +71,12 @@ out:
        return ret;
 }
 
-int btrfs_set_root_node(struct btrfs_root_item *item,
-                       struct extent_buffer *node)
+void btrfs_set_root_node(struct btrfs_root_item *item,
+                        struct extent_buffer *node)
 {
        btrfs_set_root_bytenr(item, node->start);
        btrfs_set_root_level(item, btrfs_header_level(node));
        btrfs_set_root_generation(item, btrfs_header_generation(node));
-       return 0;
 }
 
 /*
index eb55863..7dc36fa 100644 (file)
@@ -216,17 +216,11 @@ static void wait_current_trans(struct btrfs_root *root)
        spin_lock(&root->fs_info->trans_lock);
        cur_trans = root->fs_info->running_transaction;
        if (cur_trans && cur_trans->blocked) {
-               DEFINE_WAIT(wait);
                atomic_inc(&cur_trans->use_count);
                spin_unlock(&root->fs_info->trans_lock);
-               while (1) {
-                       prepare_to_wait(&root->fs_info->transaction_wait, &wait,
-                                       TASK_UNINTERRUPTIBLE);
-                       if (!cur_trans->blocked)
-                               break;
-                       schedule();
-               }
-               finish_wait(&root->fs_info->transaction_wait, &wait);
+
+               wait_event(root->fs_info->transaction_wait,
+                          !cur_trans->blocked);
                put_transaction(cur_trans);
        } else {
                spin_unlock(&root->fs_info->trans_lock);
@@ -357,19 +351,10 @@ struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root
 }
 
 /* wait for a transaction commit to be fully complete */
-static noinline int wait_for_commit(struct btrfs_root *root,
+static noinline void wait_for_commit(struct btrfs_root *root,
                                    struct btrfs_transaction *commit)
 {
-       DEFINE_WAIT(wait);
-       while (!commit->commit_done) {
-               prepare_to_wait(&commit->commit_wait, &wait,
-                               TASK_UNINTERRUPTIBLE);
-               if (commit->commit_done)
-                       break;
-               schedule();
-       }
-       finish_wait(&commit->commit_wait, &wait);
-       return 0;
+       wait_event(commit->commit_wait, commit->commit_done);
 }
 
 int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid)
@@ -1085,22 +1070,7 @@ int btrfs_transaction_blocked(struct btrfs_fs_info *info)
 static void wait_current_trans_commit_start(struct btrfs_root *root,
                                            struct btrfs_transaction *trans)
 {
-       DEFINE_WAIT(wait);
-
-       if (trans->in_commit)
-               return;
-
-       while (1) {
-               prepare_to_wait(&root->fs_info->transaction_blocked_wait, &wait,
-                               TASK_UNINTERRUPTIBLE);
-               if (trans->in_commit) {
-                       finish_wait(&root->fs_info->transaction_blocked_wait,
-                                   &wait);
-                       break;
-               }
-               schedule();
-               finish_wait(&root->fs_info->transaction_blocked_wait, &wait);
-       }
+       wait_event(root->fs_info->transaction_blocked_wait, trans->in_commit);
 }
 
 /*
@@ -1110,24 +1080,8 @@ static void wait_current_trans_commit_start(struct btrfs_root *root,
 static void wait_current_trans_commit_start_and_unblock(struct btrfs_root *root,
                                         struct btrfs_transaction *trans)
 {
-       DEFINE_WAIT(wait);
-
-       if (trans->commit_done || (trans->in_commit && !trans->blocked))
-               return;
-
-       while (1) {
-               prepare_to_wait(&root->fs_info->transaction_wait, &wait,
-                               TASK_UNINTERRUPTIBLE);
-               if (trans->commit_done ||
-                   (trans->in_commit && !trans->blocked)) {
-                       finish_wait(&root->fs_info->transaction_wait,
-                                   &wait);
-                       break;
-               }
-               schedule();
-               finish_wait(&root->fs_info->transaction_wait,
-                           &wait);
-       }
+       wait_event(root->fs_info->transaction_wait,
+                  trans->commit_done || (trans->in_commit && !trans->blocked));
 }
 
 /*
@@ -1234,8 +1188,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                atomic_inc(&cur_trans->use_count);
                btrfs_end_transaction(trans, root);
 
-               ret = wait_for_commit(root, cur_trans);
-               BUG_ON(ret);
+               wait_for_commit(root, cur_trans);
 
                put_transaction(cur_trans);
 
index ac278dd..babee65 100644 (file)
@@ -1617,7 +1617,8 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
                return 0;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        nritems = btrfs_header_nritems(eb);
        for (i = 0; i < nritems; i++) {
@@ -1723,7 +1724,9 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
                        return -ENOMEM;
 
                if (*level == 1) {
-                       wc->process_func(root, next, wc, ptr_gen);
+                       ret = wc->process_func(root, next, wc, ptr_gen);
+                       if (ret)
+                               return ret;
 
                        path->slots[*level]++;
                        if (wc->free) {
@@ -1788,8 +1791,11 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
                                parent = path->nodes[*level + 1];
 
                        root_owner = btrfs_header_owner(parent);
-                       wc->process_func(root, path->nodes[*level], wc,
+                       ret = wc->process_func(root, path->nodes[*level], wc,
                                 btrfs_header_generation(path->nodes[*level]));
+                       if (ret)
+                               return ret;
+
                        if (wc->free) {
                                struct extent_buffer *next;
 
index b89e372..53875ae 100644 (file)
@@ -1037,7 +1037,8 @@ static noinline int find_next_chunk(struct btrfs_root *root,
        struct btrfs_key found_key;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        key.objectid = objectid;
        key.offset = (u64)-1;
@@ -2061,8 +2062,10 @@ int btrfs_balance(struct btrfs_root *dev_root)
 
        /* step two, relocate all the chunks */
        path = btrfs_alloc_path();
-       BUG_ON(!path);
-
+       if (!path) {
+               ret = -ENOMEM;
+               goto error;
+       }
        key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
        key.offset = (u64)-1;
        key.type = BTRFS_CHUNK_ITEM_KEY;
@@ -2661,7 +2664,8 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
 
        ret = find_next_chunk(fs_info->chunk_root,
                              BTRFS_FIRST_CHUNK_TREE_OBJECTID, &chunk_offset);
-       BUG_ON(ret);
+       if (ret)
+               return ret;
 
        alloc_profile = BTRFS_BLOCK_GROUP_METADATA |
                        (fs_info->metadata_alloc_profile &
index 8d8f28c..6873bb6 100644 (file)
@@ -141,10 +141,11 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
 
        rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
        if (rc < 0) {
-               cERROR(1, "%s: Failed to resolve server part of %s to IP: %d",
-                         __func__, *devname, rc);
+               cFYI(1, "%s: Failed to resolve server part of %s to IP: %d",
+                       __func__, *devname, rc);
                goto compose_mount_options_err;
        }
+
        /* md_len = strlen(...) + 12 for 'sep+prefixpath='
         * assuming that we have 'unc=' and 'ip=' in
         * the original sb_mountdata
index 259991b..e76bfeb 100644 (file)
@@ -87,9 +87,15 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
        if ((cifs_pdu == NULL) || (server == NULL))
                return -EINVAL;
 
-       if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
+       if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
+           server->tcpStatus == CifsNeedNegotiate)
                return rc;
 
+       if (!server->session_estab) {
+               strncpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
+               return rc;
+       }
+
        cifs_pdu->Signature.Sequence.SequenceNumber =
                        cpu_to_le32(server->sequence_number);
        cifs_pdu->Signature.Sequence.Reserved = 0;
@@ -178,9 +184,15 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
        if ((cifs_pdu == NULL) || (server == NULL))
                return -EINVAL;
 
-       if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
+       if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
+           server->tcpStatus == CifsNeedNegotiate)
                return rc;
 
+       if (!server->session_estab) {
+               strncpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
+               return rc;
+       }
+
        cifs_pdu->Signature.Sequence.SequenceNumber =
                                cpu_to_le32(server->sequence_number);
        cifs_pdu->Signature.Sequence.Reserved = 0;
index 8655174..f93eb94 100644 (file)
@@ -86,24 +86,6 @@ extern mempool_t *cifs_sm_req_poolp;
 extern mempool_t *cifs_req_poolp;
 extern mempool_t *cifs_mid_poolp;
 
-void
-cifs_sb_active(struct super_block *sb)
-{
-       struct cifs_sb_info *server = CIFS_SB(sb);
-
-       if (atomic_inc_return(&server->active) == 1)
-               atomic_inc(&sb->s_active);
-}
-
-void
-cifs_sb_deactive(struct super_block *sb)
-{
-       struct cifs_sb_info *server = CIFS_SB(sb);
-
-       if (atomic_dec_and_test(&server->active))
-               deactivate_super(sb);
-}
-
 static int
 cifs_read_super(struct super_block *sb)
 {
@@ -581,6 +563,10 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
                mutex_unlock(&dir->i_mutex);
                dput(dentry);
                dentry = child;
+               if (!dentry->d_inode) {
+                       dput(dentry);
+                       dentry = ERR_PTR(-ENOENT);
+               }
        } while (!IS_ERR(dentry));
        _FreeXid(xid);
        kfree(full_path);
index fbd050c..cb71dc1 100644 (file)
@@ -41,10 +41,6 @@ extern struct file_system_type cifs_fs_type;
 extern const struct address_space_operations cifs_addr_ops;
 extern const struct address_space_operations cifs_addr_ops_smallbuf;
 
-/* Functions related to super block operations */
-extern void cifs_sb_active(struct super_block *sb);
-extern void cifs_sb_deactive(struct super_block *sb);
-
 /* Functions related to inodes */
 extern const struct inode_operations cifs_dir_inode_ops;
 extern struct inode *cifs_root_iget(struct super_block *);
index 1fcf4e5..38ce6d4 100644 (file)
@@ -942,8 +942,6 @@ GLOBAL_EXTERN spinlock_t siduidlock;
 GLOBAL_EXTERN spinlock_t sidgidlock;
 
 void cifs_oplock_break(struct work_struct *work);
-void cifs_oplock_break_get(struct cifsFileInfo *cfile);
-void cifs_oplock_break_put(struct cifsFileInfo *cfile);
 
 extern const struct slow_work_ops cifs_oplock_break_ops;
 
index 1a9fe7f..aac37d9 100644 (file)
@@ -107,7 +107,7 @@ static void mark_open_files_invalid(struct cifs_tcon *pTcon)
 static int
 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
 {
-       int rc = 0;
+       int rc;
        struct cifs_ses *ses;
        struct TCP_Server_Info *server;
        struct nls_table *nls_codepage;
@@ -5720,6 +5720,7 @@ CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon,
        char *temp_ptr;
        char *end_of_smb;
        __u16 params, byte_count, data_offset;
+       unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
 
        cFYI(1, "In Query All EAs path %s", searchName);
 QAllEAsRetry:
@@ -5837,7 +5838,8 @@ QAllEAsRetry:
                }
 
                if (ea_name) {
-                       if (strncmp(ea_name, temp_ptr, name_len) == 0) {
+                       if (ea_name_len == name_len &&
+                           strncmp(ea_name, temp_ptr, name_len) == 0) {
                                temp_ptr += name_len + 1;
                                rc = value_len;
                                if (buf_size == 0)
index e66297b..80c2e3a 100644 (file)
@@ -319,25 +319,328 @@ requeue_echo:
        queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL);
 }
 
+static bool
+allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size,
+                bool is_large_buf)
+{
+       char *bbuf = *bigbuf, *sbuf = *smallbuf;
+
+       if (bbuf == NULL) {
+               bbuf = (char *)cifs_buf_get();
+               if (!bbuf) {
+                       cERROR(1, "No memory for large SMB response");
+                       msleep(3000);
+                       /* retry will check if exiting */
+                       return false;
+               }
+       } else if (is_large_buf) {
+               /* we are reusing a dirty large buf, clear its start */
+               memset(bbuf, 0, size);
+       }
+
+       if (sbuf == NULL) {
+               sbuf = (char *)cifs_small_buf_get();
+               if (!sbuf) {
+                       cERROR(1, "No memory for SMB response");
+                       msleep(1000);
+                       /* retry will check if exiting */
+                       return false;
+               }
+               /* beginning of smb buffer is cleared in our buf_get */
+       } else {
+               /* if existing small buf clear beginning */
+               memset(sbuf, 0, size);
+       }
+
+       *bigbuf = bbuf;
+       *smallbuf = sbuf;
+
+       return true;
+}
+
+static int
+read_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg,
+                struct kvec *iov, unsigned int to_read,
+                unsigned int *ptotal_read, bool is_header_read)
+{
+       int length, rc = 0;
+       unsigned int total_read;
+       char *buf = iov->iov_base;
+
+       for (total_read = 0; total_read < to_read; total_read += length) {
+               length = kernel_recvmsg(server->ssocket, smb_msg, iov, 1,
+                                       to_read - total_read, 0);
+               if (server->tcpStatus == CifsExiting) {
+                       /* then will exit */
+                       rc = 2;
+                       break;
+               } else if (server->tcpStatus == CifsNeedReconnect) {
+                       cifs_reconnect(server);
+                       /* Reconnect wakes up rspns q */
+                       /* Now we will reread sock */
+                       rc = 1;
+                       break;
+               } else if (length == -ERESTARTSYS ||
+                          length == -EAGAIN ||
+                          length == -EINTR) {
+                       /*
+                        * Minimum sleep to prevent looping, allowing socket
+                        * to clear and app threads to set tcpStatus
+                        * CifsNeedReconnect if server hung.
+                        */
+                       usleep_range(1000, 2000);
+                       length = 0;
+                       if (!is_header_read)
+                               continue;
+                       /* Special handling for header read */
+                       if (total_read) {
+                               iov->iov_base = (to_read - total_read) +
+                                               buf;
+                               iov->iov_len = to_read - total_read;
+                               smb_msg->msg_control = NULL;
+                               smb_msg->msg_controllen = 0;
+                               rc = 3;
+                       } else
+                               rc = 1;
+                       break;
+               } else if (length <= 0) {
+                       cERROR(1, "Received no data, expecting %d",
+                              to_read - total_read);
+                       cifs_reconnect(server);
+                       rc = 1;
+                       break;
+               }
+       }
+
+       *ptotal_read = total_read;
+       return rc;
+}
+
+static bool
+check_rfc1002_header(struct TCP_Server_Info *server, char *buf)
+{
+       char temp = *buf;
+       unsigned int pdu_length = be32_to_cpu(
+                               ((struct smb_hdr *)buf)->smb_buf_length);
+
+       /*
+        * The first byte big endian of the length field,
+        * is actually not part of the length but the type
+        * with the most common, zero, as regular data.
+        */
+       if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
+               return false;
+       } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
+               cFYI(1, "Good RFC 1002 session rsp");
+               return false;
+       } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
+               /*
+                * We get this from Windows 98 instead of an error on
+                * SMB negprot response.
+                */
+               cFYI(1, "Negative RFC1002 Session Response Error 0x%x)",
+                       pdu_length);
+               /* give server a second to clean up */
+               msleep(1000);
+               /*
+                * Always try 445 first on reconnect since we get NACK
+                * on some if we ever connected to port 139 (the NACK
+                * is since we do not begin with RFC1001 session
+                * initialize frame).
+                */
+               cifs_set_port((struct sockaddr *)
+                               &server->dstaddr, CIFS_PORT);
+               cifs_reconnect(server);
+               wake_up(&server->response_q);
+               return false;
+       } else if (temp != (char) 0) {
+               cERROR(1, "Unknown RFC 1002 frame");
+               cifs_dump_mem(" Received Data: ", buf, 4);
+               cifs_reconnect(server);
+               return false;
+       }
+
+       /* else we have an SMB response */
+       if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
+           (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
+               cERROR(1, "Invalid size SMB length %d pdu_length %d",
+                      4, pdu_length+4);
+               cifs_reconnect(server);
+               wake_up(&server->response_q);
+               return false;
+       }
+
+       return true;
+}
+
+static struct mid_q_entry *
+find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
+             int *length, bool is_large_buf, bool *is_multi_rsp, char **bigbuf)
+{
+       struct mid_q_entry *mid = NULL, *tmp_mid, *ret = NULL;
+
+       spin_lock(&GlobalMid_Lock);
+       list_for_each_entry_safe(mid, tmp_mid, &server->pending_mid_q, qhead) {
+               if (mid->mid != buf->Mid ||
+                   mid->midState != MID_REQUEST_SUBMITTED ||
+                   mid->command != buf->Command)
+                       continue;
+
+               if (*length == 0 && check2ndT2(buf, server->maxBuf) > 0) {
+                       /* We have a multipart transact2 resp */
+                       *is_multi_rsp = true;
+                       if (mid->resp_buf) {
+                               /* merge response - fix up 1st*/
+                               *length = coalesce_t2(buf, mid->resp_buf);
+                               if (*length > 0) {
+                                       *length = 0;
+                                       mid->multiRsp = true;
+                                       break;
+                               }
+                               /* All parts received or packet is malformed. */
+                               mid->multiEnd = true;
+                               goto multi_t2_fnd;
+                       }
+                       if (!is_large_buf) {
+                               /*FIXME: switch to already allocated largebuf?*/
+                               cERROR(1, "1st trans2 resp needs bigbuf");
+                       } else {
+                               /* Have first buffer */
+                               mid->resp_buf = buf;
+                               mid->largeBuf = true;
+                               *bigbuf = NULL;
+                       }
+                       break;
+               }
+               mid->resp_buf = buf;
+               mid->largeBuf = is_large_buf;
+multi_t2_fnd:
+               if (*length == 0)
+                       mid->midState = MID_RESPONSE_RECEIVED;
+               else
+                       mid->midState = MID_RESPONSE_MALFORMED;
+#ifdef CONFIG_CIFS_STATS2
+               mid->when_received = jiffies;
+#endif
+               list_del_init(&mid->qhead);
+               ret = mid;
+               break;
+       }
+       spin_unlock(&GlobalMid_Lock);
+
+       return ret;
+}
+
+static void clean_demultiplex_info(struct TCP_Server_Info *server)
+{
+       int length;
+
+       /* take it off the list, if it's not already */
+       spin_lock(&cifs_tcp_ses_lock);
+       list_del_init(&server->tcp_ses_list);
+       spin_unlock(&cifs_tcp_ses_lock);
+
+       spin_lock(&GlobalMid_Lock);
+       server->tcpStatus = CifsExiting;
+       spin_unlock(&GlobalMid_Lock);
+       wake_up_all(&server->response_q);
+
+       /*
+        * Check if we have blocked requests that need to free. Note that
+        * cifs_max_pending is normally 50, but can be set at module install
+        * time to as little as two.
+        */
+       spin_lock(&GlobalMid_Lock);
+       if (atomic_read(&server->inFlight) >= cifs_max_pending)
+               atomic_set(&server->inFlight, cifs_max_pending - 1);
+       /*
+        * We do not want to set the max_pending too low or we could end up
+        * with the counter going negative.
+        */
+       spin_unlock(&GlobalMid_Lock);
+       /*
+        * Although there should not be any requests blocked on this queue it
+        * can not hurt to be paranoid and try to wake up requests that may
+        * haven been blocked when more than 50 at time were on the wire to the
+        * same server - they now will see the session is in exit state and get
+        * out of SendReceive.
+        */
+       wake_up_all(&server->request_q);
+       /* give those requests time to exit */
+       msleep(125);
+
+       if (server->ssocket) {
+               sock_release(server->ssocket);
+               server->ssocket = NULL;
+       }
+
+       if (!list_empty(&server->pending_mid_q)) {
+               struct list_head dispose_list;
+               struct mid_q_entry *mid_entry;
+               struct list_head *tmp, *tmp2;
+
+               INIT_LIST_HEAD(&dispose_list);
+               spin_lock(&GlobalMid_Lock);
+               list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
+                       mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
+                       cFYI(1, "Clearing mid 0x%x", mid_entry->mid);
+                       mid_entry->midState = MID_SHUTDOWN;
+                       list_move(&mid_entry->qhead, &dispose_list);
+               }
+               spin_unlock(&GlobalMid_Lock);
+
+               /* now walk dispose list and issue callbacks */
+               list_for_each_safe(tmp, tmp2, &dispose_list) {
+                       mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
+                       cFYI(1, "Callback mid 0x%x", mid_entry->mid);
+                       list_del_init(&mid_entry->qhead);
+                       mid_entry->callback(mid_entry);
+               }
+               /* 1/8th of sec is more than enough time for them to exit */
+               msleep(125);
+       }
+
+       if (!list_empty(&server->pending_mid_q)) {
+               /*
+                * mpx threads have not exited yet give them at least the smb
+                * send timeout time for long ops.
+                *
+                * Due to delays on oplock break requests, we need to wait at
+                * least 45 seconds before giving up on a request getting a
+                * response and going ahead and killing cifsd.
+                */
+               cFYI(1, "Wait for exit from demultiplex thread");
+               msleep(46000);
+               /*
+                * If threads still have not exited they are probably never
+                * coming home not much else we can do but free the memory.
+                */
+       }
+
+       kfree(server->hostname);
+       kfree(server);
+
+       length = atomic_dec_return(&tcpSesAllocCount);
+       if (length > 0)
+               mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
+                               GFP_KERNEL);
+}
+
 static int
 cifs_demultiplex_thread(void *p)
 {
        int length;
        struct TCP_Server_Info *server = p;
        unsigned int pdu_length, total_read;
+       char *buf = NULL, *bigbuf = NULL, *smallbuf = NULL;
        struct smb_hdr *smb_buffer = NULL;
-       struct smb_hdr *bigbuf = NULL;
-       struct smb_hdr *smallbuf = NULL;
        struct msghdr smb_msg;
        struct kvec iov;
-       struct socket *csocket = server->ssocket;
-       struct list_head *tmp, *tmp2;
        struct task_struct *task_to_wake = NULL;
        struct mid_q_entry *mid_entry;
-       char temp;
        bool isLargeBuf = false;
-       bool isMultiRsp;
-       int reconnect;
+       bool isMultiRsp = false;
+       int rc;
 
        current->flags |= PF_MEMALLOC;
        cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
@@ -351,35 +654,16 @@ cifs_demultiplex_thread(void *p)
        while (server->tcpStatus != CifsExiting) {
                if (try_to_freeze())
                        continue;
-               if (bigbuf == NULL) {
-                       bigbuf = cifs_buf_get();
-                       if (!bigbuf) {
-                               cERROR(1, "No memory for large SMB response");
-                               msleep(3000);
-                               /* retry will check if exiting */
-                               continue;
-                       }
-               } else if (isLargeBuf) {
-                       /* we are reusing a dirty large buf, clear its start */
-                       memset(bigbuf, 0, sizeof(struct smb_hdr));
-               }
 
-               if (smallbuf == NULL) {
-                       smallbuf = cifs_small_buf_get();
-                       if (!smallbuf) {
-                               cERROR(1, "No memory for SMB response");
-                               msleep(1000);
-                               /* retry will check if exiting */
-                               continue;
-                       }
-                       /* beginning of smb buffer is cleared in our buf_get */
-               } else /* if existing small buf clear beginning */
-                       memset(smallbuf, 0, sizeof(struct smb_hdr));
+               if (!allocate_buffers(&bigbuf, &smallbuf,
+                                     sizeof(struct smb_hdr), isLargeBuf))
+                       continue;
 
                isLargeBuf = false;
                isMultiRsp = false;
-               smb_buffer = smallbuf;
-               iov.iov_base = smb_buffer;
+               smb_buffer = (struct smb_hdr *)smallbuf;
+               buf = smallbuf;
+               iov.iov_base = buf;
                iov.iov_len = 4;
                smb_msg.msg_control = NULL;
                smb_msg.msg_controllen = 0;
@@ -393,158 +677,50 @@ incomplete_rcv:
                                  "Reconnecting...", server->hostname,
                                  (echo_retries * SMB_ECHO_INTERVAL / HZ));
                        cifs_reconnect(server);
-                       csocket = server->ssocket;
                        wake_up(&server->response_q);
                        continue;
                }
 
-               length =
-                   kernel_recvmsg(csocket, &smb_msg,
-                               &iov, 1, pdu_length, 0 /* BB other flags? */);
-
-               if (server->tcpStatus == CifsExiting) {
+               rc = read_from_socket(server, &smb_msg, &iov, pdu_length,
+                                     &total_read, true /* header read */);
+               if (rc == 3)
+                       goto incomplete_rcv;
+               else if (rc == 2)
                        break;
-               } else if (server->tcpStatus == CifsNeedReconnect) {
-                       cFYI(1, "Reconnect after server stopped responding");
-                       cifs_reconnect(server);
-                       cFYI(1, "call to reconnect done");
-                       csocket = server->ssocket;
-                       continue;
-               } else if (length == -ERESTARTSYS ||
-                          length == -EAGAIN ||
-                          length == -EINTR) {
-                       msleep(1); /* minimum sleep to prevent looping
-                               allowing socket to clear and app threads to set
-                               tcpStatus CifsNeedReconnect if server hung */
-                       if (pdu_length < 4) {
-                               iov.iov_base = (4 - pdu_length) +
-                                                       (char *)smb_buffer;
-                               iov.iov_len = pdu_length;
-                               smb_msg.msg_control = NULL;
-                               smb_msg.msg_controllen = 0;
-                               goto incomplete_rcv;
-                       } else
-                               continue;
-               } else if (length <= 0) {
-                       cFYI(1, "Reconnect after unexpected peek error %d",
-                               length);
-                       cifs_reconnect(server);
-                       csocket = server->ssocket;
-                       wake_up(&server->response_q);
+               else if (rc == 1)
                        continue;
-               } else if (length < pdu_length) {
-                       cFYI(1, "requested %d bytes but only got %d bytes",
-                                 pdu_length, length);
-                       pdu_length -= length;
-                       msleep(1);
-                       goto incomplete_rcv;
-               }
-
-               /* The right amount was read from socket - 4 bytes */
-               /* so we can now interpret the length field */
 
-               /* the first byte big endian of the length field,
-               is actually not part of the length but the type
-               with the most common, zero, as regular data */
-               temp = *((char *) smb_buffer);
+               /*
+                * The right amount was read from socket - 4 bytes,
+                * so we can now interpret the length field.
+                */
 
-               /* Note that FC 1001 length is big endian on the wire,
-               but we convert it here so it is always manipulated
-               as host byte order */
+               /*
+                * Note that RFC 1001 length is big endian on the wire,
+                * but we convert it here so it is always manipulated
+                * as host byte order.
+                */
                pdu_length = be32_to_cpu(smb_buffer->smb_buf_length);
 
                cFYI(1, "rfc1002 length 0x%x", pdu_length+4);
-
-               if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
-                       continue;
-               } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
-                       cFYI(1, "Good RFC 1002 session rsp");
-                       continue;
-               } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
-                       /* we get this from Windows 98 instead of
-                          an error on SMB negprot response */
-                       cFYI(1, "Negative RFC1002 Session Response Error 0x%x)",
-                               pdu_length);
-                       /* give server a second to clean up  */
-                       msleep(1000);
-                       /* always try 445 first on reconnect since we get NACK
-                        * on some if we ever connected to port 139 (the NACK
-                        * is since we do not begin with RFC1001 session
-                        * initialize frame)
-                        */
-                       cifs_set_port((struct sockaddr *)
-                                       &server->dstaddr, CIFS_PORT);
-                       cifs_reconnect(server);
-                       csocket = server->ssocket;
-                       wake_up(&server->response_q);
-                       continue;
-               } else if (temp != (char) 0) {
-                       cERROR(1, "Unknown RFC 1002 frame");
-                       cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
-                                     length);
-                       cifs_reconnect(server);
-                       csocket = server->ssocket;
+               if (!check_rfc1002_header(server, buf))
                        continue;
-               }
-
-               /* else we have an SMB response */
-               if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
-                           (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
-                       cERROR(1, "Invalid size SMB length %d pdu_length %d",
-                                       length, pdu_length+4);
-                       cifs_reconnect(server);
-                       csocket = server->ssocket;
-                       wake_up(&server->response_q);
-                       continue;
-               }
 
                /* else length ok */
-               reconnect = 0;
-
                if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
                        isLargeBuf = true;
                        memcpy(bigbuf, smallbuf, 4);
-                       smb_buffer = bigbuf;
+                       smb_buffer = (struct smb_hdr *)bigbuf;
+                       buf = bigbuf;
                }
-               length = 0;
-               iov.iov_base = 4 + (char *)smb_buffer;
+
+               iov.iov_base = 4 + buf;
                iov.iov_len = pdu_length;
-               for (total_read = 0; total_read < pdu_length;
-                    total_read += length) {
-                       length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
-                                               pdu_length - total_read, 0);
-                       if (server->tcpStatus == CifsExiting) {
-                               /* then will exit */
-                               reconnect = 2;
-                               break;
-                       } else if (server->tcpStatus == CifsNeedReconnect) {
-                               cifs_reconnect(server);
-                               csocket = server->ssocket;
-                               /* Reconnect wakes up rspns q */
-                               /* Now we will reread sock */
-                               reconnect = 1;
-                               break;
-                       } else if (length == -ERESTARTSYS ||
-                                  length == -EAGAIN ||
-                                  length == -EINTR) {
-                               msleep(1); /* minimum sleep to prevent looping,
-                                             allowing socket to clear and app
-                                             threads to set tcpStatus
-                                             CifsNeedReconnect if server hung*/
-                               length = 0;
-                               continue;
-                       } else if (length <= 0) {
-                               cERROR(1, "Received no data, expecting %d",
-                                             pdu_length - total_read);
-                               cifs_reconnect(server);
-                               csocket = server->ssocket;
-                               reconnect = 1;
-                               break;
-                       }
-               }
-               if (reconnect == 2)
+               rc = read_from_socket(server, &smb_msg, &iov, pdu_length,
+                                     &total_read, false);
+               if (rc == 2)
                        break;
-               else if (reconnect == 1)
+               else if (rc == 1)
                        continue;
 
                total_read += 4; /* account for rfc1002 hdr */
@@ -562,75 +738,13 @@ incomplete_rcv:
                 */
                length = checkSMB(smb_buffer, smb_buffer->Mid, total_read);
                if (length != 0)
-                       cifs_dump_mem("Bad SMB: ", smb_buffer,
-                                       min_t(unsigned int, total_read, 48));
+                       cifs_dump_mem("Bad SMB: ", buf,
+                                     min_t(unsigned int, total_read, 48));
 
-               mid_entry = NULL;
                server->lstrp = jiffies;
 
-               spin_lock(&GlobalMid_Lock);
-               list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
-                       mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
-
-                       if (mid_entry->mid != smb_buffer->Mid ||
-                           mid_entry->midState != MID_REQUEST_SUBMITTED ||
-                           mid_entry->command != smb_buffer->Command) {
-                               mid_entry = NULL;
-                               continue;
-                       }
-
-                       if (length == 0 &&
-                           check2ndT2(smb_buffer, server->maxBuf) > 0) {
-                               /* We have a multipart transact2 resp */
-                               isMultiRsp = true;
-                               if (mid_entry->resp_buf) {
-                                       /* merge response - fix up 1st*/
-                                       length = coalesce_t2(smb_buffer,
-                                                       mid_entry->resp_buf);
-                                       if (length > 0) {
-                                               length = 0;
-                                               mid_entry->multiRsp = true;
-                                               break;
-                                       } else {
-                                               /* all parts received or
-                                                * packet is malformed
-                                                */
-                                               mid_entry->multiEnd = true;
-                                               goto multi_t2_fnd;
-                                       }
-                               } else {
-                                       if (!isLargeBuf) {
-                                               /*
-                                                * FIXME: switch to already
-                                                *        allocated largebuf?
-                                                */
-                                               cERROR(1, "1st trans2 resp "
-                                                         "needs bigbuf");
-                                       } else {
-                                               /* Have first buffer */
-                                               mid_entry->resp_buf =
-                                                        smb_buffer;
-                                               mid_entry->largeBuf = true;
-                                               bigbuf = NULL;
-                                       }
-                               }
-                               break;
-                       }
-                       mid_entry->resp_buf = smb_buffer;
-                       mid_entry->largeBuf = isLargeBuf;
-multi_t2_fnd:
-                       if (length == 0)
-                               mid_entry->midState = MID_RESPONSE_RECEIVED;
-                       else
-                               mid_entry->midState = MID_RESPONSE_MALFORMED;
-#ifdef CONFIG_CIFS_STATS2
-                       mid_entry->when_received = jiffies;
-#endif
-                       list_del_init(&mid_entry->qhead);
-                       break;
-               }
-               spin_unlock(&GlobalMid_Lock);
-
+               mid_entry = find_cifs_mid(server, smb_buffer, &length,
+                                         isLargeBuf, &isMultiRsp, &bigbuf);
                if (mid_entry != NULL) {
                        mid_entry->callback(mid_entry);
                        /* Was previous buf put in mpx struct for multi-rsp? */
@@ -648,7 +762,7 @@ multi_t2_fnd:
                           !isMultiRsp) {
                        cERROR(1, "No task to wake, unknown frame received! "
                                   "NumMids %d", atomic_read(&midCount));
-                       cifs_dump_mem("Received Data is: ", (char *)smb_buffer,
+                       cifs_dump_mem("Received Data is: ", buf,
                                      sizeof(struct smb_hdr));
 #ifdef CONFIG_CIFS_DEBUG2
                        cifs_dump_detail(smb_buffer);
@@ -658,88 +772,13 @@ multi_t2_fnd:
                }
        } /* end while !EXITING */
 
-       /* take it off the list, if it's not already */
-       spin_lock(&cifs_tcp_ses_lock);
-       list_del_init(&server->tcp_ses_list);
-       spin_unlock(&cifs_tcp_ses_lock);
-
-       spin_lock(&GlobalMid_Lock);
-       server->tcpStatus = CifsExiting;
-       spin_unlock(&GlobalMid_Lock);
-       wake_up_all(&server->response_q);
-
-       /* check if we have blocked requests that need to free */
-       /* Note that cifs_max_pending is normally 50, but
-       can be set at module install time to as little as two */
-       spin_lock(&GlobalMid_Lock);
-       if (atomic_read(&server->inFlight) >= cifs_max_pending)
-               atomic_set(&server->inFlight, cifs_max_pending - 1);
-       /* We do not want to set the max_pending too low or we
-       could end up with the counter going negative */
-       spin_unlock(&GlobalMid_Lock);
-       /* Although there should not be any requests blocked on
-       this queue it can not hurt to be paranoid and try to wake up requests
-       that may haven been blocked when more than 50 at time were on the wire
-       to the same server - they now will see the session is in exit state
-       and get out of SendReceive.  */
-       wake_up_all(&server->request_q);
-       /* give those requests time to exit */
-       msleep(125);
-
-       if (server->ssocket) {
-               sock_release(csocket);
-               server->ssocket = NULL;
-       }
        /* buffer usually freed in free_mid - need to free it here on exit */
        cifs_buf_release(bigbuf);
        if (smallbuf) /* no sense logging a debug message if NULL */
                cifs_small_buf_release(smallbuf);
 
-       if (!list_empty(&server->pending_mid_q)) {
-               struct list_head dispose_list;
-
-               INIT_LIST_HEAD(&dispose_list);
-               spin_lock(&GlobalMid_Lock);
-               list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
-                       mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
-                       cFYI(1, "Clearing mid 0x%x", mid_entry->mid);
-                       mid_entry->midState = MID_SHUTDOWN;
-                       list_move(&mid_entry->qhead, &dispose_list);
-               }
-               spin_unlock(&GlobalMid_Lock);
-
-               /* now walk dispose list and issue callbacks */
-               list_for_each_safe(tmp, tmp2, &dispose_list) {
-                       mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
-                       cFYI(1, "Callback mid 0x%x", mid_entry->mid);
-                       list_del_init(&mid_entry->qhead);
-                       mid_entry->callback(mid_entry);
-               }
-               /* 1/8th of sec is more than enough time for them to exit */
-               msleep(125);
-       }
-
-       if (!list_empty(&server->pending_mid_q)) {
-               /* mpx threads have not exited yet give them
-               at least the smb send timeout time for long ops */
-               /* due to delays on oplock break requests, we need
-               to wait at least 45 seconds before giving up
-               on a request getting a response and going ahead
-               and killing cifsd */
-               cFYI(1, "Wait for exit from demultiplex thread");
-               msleep(46000);
-               /* if threads still have not exited they are probably never
-               coming home not much else we can do but free the memory */
-       }
-
-       kfree(server->hostname);
        task_to_wake = xchg(&server->tsk, NULL);
-       kfree(server);
-
-       length = atomic_dec_return(&tcpSesAllocCount);
-       if (length  > 0)
-               mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
-                               GFP_KERNEL);
+       clean_demultiplex_info(server);
 
        /* if server->tsk was NULL then wait for a signal before exiting */
        if (!task_to_wake) {
@@ -3193,15 +3232,9 @@ mount_fail_check:
                else
                        cifs_put_tcp_session(srvTcp);
                bdi_destroy(&cifs_sb->bdi);
-               goto out;
        }
 
-       /* volume_info->password is freed above when existing session found
-       (in which case it is not needed anymore) but when new sesion is created
-       the password ptr is put in the new session structure (in which case the
-       password will be freed at unmount time) */
 out:
-       /* zero out password before freeing */
        FreeXid(xid);
        return rc;
 }
index 548f062..1d2d91d 100644 (file)
@@ -79,8 +79,8 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
        /* Perform the upcall */
        rc = dns_query(NULL, hostname, len, NULL, ip_addr, NULL);
        if (rc < 0)
-               cERROR(1, "%s: unable to resolve: %*.*s",
-                      __func__, len, len, hostname);
+               cFYI(1, "%s: unable to resolve: %*.*s",
+                       __func__, len, len, hostname);
        else
                cFYI(1, "%s: resolved: %*.*s to %s",
                     __func__, len, len, hostname, *ip_addr);
index 378acda..9f41a10 100644 (file)
@@ -314,6 +314,8 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
        }
        spin_unlock(&cifs_file_list_lock);
 
+       cancel_work_sync(&cifs_file->oplock_break);
+
        if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
                int xid, rc;
 
@@ -2418,31 +2420,6 @@ void cifs_oplock_break(struct work_struct *work)
                                 cinode->clientCanCacheRead ? 1 : 0);
                cFYI(1, "Oplock release rc = %d", rc);
        }
-
-       /*
-        * We might have kicked in before is_valid_oplock_break()
-        * finished grabbing reference for us.  Make sure it's done by
-        * waiting for cifs_file_list_lock.
-        */
-       spin_lock(&cifs_file_list_lock);
-       spin_unlock(&cifs_file_list_lock);
-
-       cifs_oplock_break_put(cfile);
-}
-
-/* must be called while holding cifs_file_list_lock */
-void cifs_oplock_break_get(struct cifsFileInfo *cfile)
-{
-       cifs_sb_active(cfile->dentry->d_sb);
-       cifsFileInfo_get(cfile);
-}
-
-void cifs_oplock_break_put(struct cifsFileInfo *cfile)
-{
-       struct super_block *sb = cfile->dentry->d_sb;
-
-       cifsFileInfo_put(cfile);
-       cifs_sb_deactive(sb);
 }
 
 const struct address_space_operations cifs_addr_ops = {
index 9b018c8..a7b2dcd 100644 (file)
@@ -764,20 +764,10 @@ char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
        if (full_path == NULL)
                return full_path;
 
-       if (dfsplen) {
+       if (dfsplen)
                strncpy(full_path, tcon->treeName, dfsplen);
-               /* switch slash direction in prepath depending on whether
-                * windows or posix style path names
-                */
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
-                       int i;
-                       for (i = 0; i < dfsplen; i++) {
-                               if (full_path[i] == '\\')
-                                       full_path[i] = '/';
-                       }
-               }
-       }
        strncpy(full_path + dfsplen, vol->prepath, pplen);
+       convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
        full_path[dfsplen + pplen] = 0; /* add trailing null */
        return full_path;
 }
index 03a1f49..7c16933 100644 (file)
@@ -585,15 +585,8 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
 
                                cifs_set_oplock_level(pCifsInode,
                                        pSMB->OplockLevel ? OPLOCK_READ : 0);
-                               /*
-                                * cifs_oplock_break_put() can't be called
-                                * from here.  Get reference after queueing
-                                * succeeded.  cifs_oplock_break() will
-                                * synchronize using cifs_file_list_lock.
-                                */
-                               if (queue_work(system_nrt_wq,
-                                              &netfile->oplock_break))
-                                       cifs_oplock_break_get(netfile);
+                               queue_work(system_nrt_wq,
+                                          &netfile->oplock_break);
                                netfile->oplock_break_cancelled = false;
 
                                spin_unlock(&cifs_file_list_lock);
index 147aa22..c1b9c4b 100644 (file)
@@ -362,6 +362,8 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
        mid = AllocMidQEntry(hdr, server);
        if (mid == NULL) {
                mutex_unlock(&server->srv_mutex);
+               atomic_dec(&server->inFlight);
+               wake_up(&server->request_q);
                return -ENOMEM;
        }
 
index 8be086e..51352de 100644 (file)
@@ -1003,6 +1003,7 @@ COMPATIBLE_IOCTL(PPPIOCCONNECT)
 COMPATIBLE_IOCTL(PPPIOCDISCONN)
 COMPATIBLE_IOCTL(PPPIOCATTCHAN)
 COMPATIBLE_IOCTL(PPPIOCGCHAN)
+COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS)
 /* PPPOX */
 COMPATIBLE_IOCTL(PPPOEIOCSFWD)
 COMPATIBLE_IOCTL(PPPOEIOCDFWD)
index b05aac3..a88948b 100644 (file)
@@ -301,6 +301,27 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
        return parent;
 }
 
+/*
+ * Unhash a dentry without inserting an RCU walk barrier or checking that
+ * dentry->d_lock is locked.  The caller must take care of that, if
+ * appropriate.
+ */
+static void __d_shrink(struct dentry *dentry)
+{
+       if (!d_unhashed(dentry)) {
+               struct hlist_bl_head *b;
+               if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED))
+                       b = &dentry->d_sb->s_anon;
+               else
+                       b = d_hash(dentry->d_parent, dentry->d_name.hash);
+
+               hlist_bl_lock(b);
+               __hlist_bl_del(&dentry->d_hash);
+               dentry->d_hash.pprev = NULL;
+               hlist_bl_unlock(b);
+       }
+}
+
 /**
  * d_drop - drop a dentry
  * @dentry: dentry to drop
@@ -319,17 +340,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
 void __d_drop(struct dentry *dentry)
 {
        if (!d_unhashed(dentry)) {
-               struct hlist_bl_head *b;
-               if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED))
-                       b = &dentry->d_sb->s_anon;
-               else
-                       b = d_hash(dentry->d_parent, dentry->d_name.hash);
-
-               hlist_bl_lock(b);
-               __hlist_bl_del(&dentry->d_hash);
-               dentry->d_hash.pprev = NULL;
-               hlist_bl_unlock(b);
-
+               __d_shrink(dentry);
                dentry_rcuwalk_barrier(dentry);
        }
 }
@@ -784,6 +795,7 @@ relock:
 
 /**
  * prune_dcache_sb - shrink the dcache
+ * @sb: superblock
  * @nr_to_scan: number of entries to try to free
  *
  * Attempt to shrink the superblock dcache LRU by @nr_to_scan entries. This is
@@ -828,44 +840,24 @@ EXPORT_SYMBOL(shrink_dcache_sb);
 static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
 {
        struct dentry *parent;
-       unsigned detached = 0;
 
        BUG_ON(!IS_ROOT(dentry));
 
-       /* detach this root from the system */
-       spin_lock(&dentry->d_lock);
-       dentry_lru_del(dentry);
-       __d_drop(dentry);
-       spin_unlock(&dentry->d_lock);
-
        for (;;) {
                /* descend to the first leaf in the current subtree */
-               while (!list_empty(&dentry->d_subdirs)) {
-                       struct dentry *loop;
-
-                       /* this is a branch with children - detach all of them
-                        * from the system in one go */
-                       spin_lock(&dentry->d_lock);
-                       list_for_each_entry(loop, &dentry->d_subdirs,
-                                           d_u.d_child) {
-                               spin_lock_nested(&loop->d_lock,
-                                               DENTRY_D_LOCK_NESTED);
-                               dentry_lru_del(loop);
-                               __d_drop(loop);
-                               spin_unlock(&loop->d_lock);
-                       }
-                       spin_unlock(&dentry->d_lock);
-
-                       /* move to the first child */
+               while (!list_empty(&dentry->d_subdirs))
                        dentry = list_entry(dentry->d_subdirs.next,
                                            struct dentry, d_u.d_child);
-               }
 
                /* consume the dentries from this leaf up through its parents
                 * until we find one with children or run out altogether */
                do {
                        struct inode *inode;
 
+                       /* detach from the system */
+                       dentry_lru_del(dentry);
+                       __d_shrink(dentry);
+
                        if (dentry->d_count != 0) {
                                printk(KERN_ERR
                                       "BUG: Dentry %p{i=%lx,n=%s}"
@@ -886,14 +878,10 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
                                list_del(&dentry->d_u.d_child);
                        } else {
                                parent = dentry->d_parent;
-                               spin_lock(&parent->d_lock);
                                parent->d_count--;
                                list_del(&dentry->d_u.d_child);
-                               spin_unlock(&parent->d_lock);
                        }
 
-                       detached++;
-
                        inode = dentry->d_inode;
                        if (inode) {
                                dentry->d_inode = NULL;
@@ -938,9 +926,7 @@ void shrink_dcache_for_umount(struct super_block *sb)
 
        dentry = sb->s_root;
        sb->s_root = NULL;
-       spin_lock(&dentry->d_lock);
        dentry->d_count--;
-       spin_unlock(&dentry->d_lock);
        shrink_dcache_for_umount_subtree(dentry);
 
        while (!hlist_bl_empty(&sb->s_anon)) {
@@ -1743,7 +1729,7 @@ seqretry:
                 */
                if (read_seqcount_retry(&dentry->d_seq, *seq))
                        goto seqretry;
-               if (parent->d_flags & DCACHE_OP_COMPARE) {
+               if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) {
                        if (parent->d_op->d_compare(parent, *inode,
                                                dentry, i,
                                                tlen, tname, name))
index 1cd6d9d..cc16562 100644 (file)
@@ -1,6 +1,6 @@
 config ECRYPT_FS
        tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && KEYS && CRYPTO
+       depends on EXPERIMENTAL && KEYS && CRYPTO && (ENCRYPTED_KEYS || ENCRYPTED_KEYS=n)
        select CRYPTO_ECB
        select CRYPTO_CBC
        select CRYPTO_MD5
index 340c657..11f8582 100644 (file)
@@ -69,6 +69,7 @@ static int ecryptfs_inode_set(struct inode *inode, void *opaque)
        inode->i_ino = lower_inode->i_ino;
        inode->i_version++;
        inode->i_mapping->a_ops = &ecryptfs_aops;
+       inode->i_mapping->backing_dev_info = inode->i_sb->s_bdi;
 
        if (S_ISLNK(inode->i_mode))
                inode->i_op = &ecryptfs_symlink_iops;
index c472533..ac1ad48 100644 (file)
@@ -1871,11 +1871,6 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
         * just one will be sufficient to decrypt to get the FEK. */
 find_next_matching_auth_tok:
        found_auth_tok = 0;
-       if (auth_tok_key) {
-               up_write(&(auth_tok_key->sem));
-               key_put(auth_tok_key);
-               auth_tok_key = NULL;
-       }
        list_for_each_entry(auth_tok_list_item, &auth_tok_list, list) {
                candidate_auth_tok = &auth_tok_list_item->auth_tok;
                if (unlikely(ecryptfs_verbosity > 0)) {
@@ -1912,14 +1907,22 @@ found_matching_auth_tok:
                memcpy(&(candidate_auth_tok->token.private_key),
                       &(matching_auth_tok->token.private_key),
                       sizeof(struct ecryptfs_private_key));
+               up_write(&(auth_tok_key->sem));
+               key_put(auth_tok_key);
                rc = decrypt_pki_encrypted_session_key(candidate_auth_tok,
                                                       crypt_stat);
        } else if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD) {
                memcpy(&(candidate_auth_tok->token.password),
                       &(matching_auth_tok->token.password),
                       sizeof(struct ecryptfs_password));
+               up_write(&(auth_tok_key->sem));
+               key_put(auth_tok_key);
                rc = decrypt_passphrase_encrypted_session_key(
                        candidate_auth_tok, crypt_stat);
+       } else {
+               up_write(&(auth_tok_key->sem));
+               key_put(auth_tok_key);
+               rc = -EINVAL;
        }
        if (rc) {
                struct ecryptfs_auth_tok_list_item *auth_tok_list_item_tmp;
@@ -1959,21 +1962,18 @@ found_matching_auth_tok:
 out_wipe_list:
        wipe_auth_tok_list(&auth_tok_list);
 out:
-       if (auth_tok_key) {
-               up_write(&(auth_tok_key->sem));
-               key_put(auth_tok_key);
-       }
        return rc;
 }
 
 static int
-pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
+pki_encrypt_session_key(struct key *auth_tok_key,
+                       struct ecryptfs_auth_tok *auth_tok,
                        struct ecryptfs_crypt_stat *crypt_stat,
                        struct ecryptfs_key_record *key_rec)
 {
        struct ecryptfs_msg_ctx *msg_ctx = NULL;
        char *payload = NULL;
-       size_t payload_len;
+       size_t payload_len = 0;
        struct ecryptfs_message *msg;
        int rc;
 
@@ -1982,6 +1982,8 @@ pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
                                         crypt_stat->cipher,
                                         crypt_stat->key_size),
                                 crypt_stat, &payload, &payload_len);
+       up_write(&(auth_tok_key->sem));
+       key_put(auth_tok_key);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n");
                goto out;
@@ -2011,6 +2013,8 @@ out:
  * write_tag_1_packet - Write an RFC2440-compatible tag 1 (public key) packet
  * @dest: Buffer into which to write the packet
  * @remaining_bytes: Maximum number of bytes that can be writtn
+ * @auth_tok_key: The authentication token key to unlock and put when done with
+ *                @auth_tok
  * @auth_tok: The authentication token used for generating the tag 1 packet
  * @crypt_stat: The cryptographic context
  * @key_rec: The key record struct for the tag 1 packet
@@ -2021,7 +2025,7 @@ out:
  */
 static int
 write_tag_1_packet(char *dest, size_t *remaining_bytes,
-                  struct ecryptfs_auth_tok *auth_tok,
+                  struct key *auth_tok_key, struct ecryptfs_auth_tok *auth_tok,
                   struct ecryptfs_crypt_stat *crypt_stat,
                   struct ecryptfs_key_record *key_rec, size_t *packet_size)
 {
@@ -2042,12 +2046,15 @@ write_tag_1_packet(char *dest, size_t *remaining_bytes,
                memcpy(key_rec->enc_key,
                       auth_tok->session_key.encrypted_key,
                       auth_tok->session_key.encrypted_key_size);
+               up_write(&(auth_tok_key->sem));
+               key_put(auth_tok_key);
                goto encrypted_session_key_set;
        }
        if (auth_tok->session_key.encrypted_key_size == 0)
                auth_tok->session_key.encrypted_key_size =
                        auth_tok->token.private_key.key_size;
-       rc = pki_encrypt_session_key(auth_tok, crypt_stat, key_rec);
+       rc = pki_encrypt_session_key(auth_tok_key, auth_tok, crypt_stat,
+                                    key_rec);
        if (rc) {
                printk(KERN_ERR "Failed to encrypt session key via a key "
                       "module; rc = [%d]\n", rc);
@@ -2424,6 +2431,8 @@ ecryptfs_generate_key_packet_set(char *dest_base,
                                                &max, auth_tok,
                                                crypt_stat, key_rec,
                                                &written);
+                       up_write(&(auth_tok_key->sem));
+                       key_put(auth_tok_key);
                        if (rc) {
                                ecryptfs_printk(KERN_WARNING, "Error "
                                                "writing tag 3 packet\n");
@@ -2441,8 +2450,8 @@ ecryptfs_generate_key_packet_set(char *dest_base,
                        }
                        (*len) += written;
                } else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
-                       rc = write_tag_1_packet(dest_base + (*len),
-                                               &max, auth_tok,
+                       rc = write_tag_1_packet(dest_base + (*len), &max,
+                                               auth_tok_key, auth_tok,
                                                crypt_stat, key_rec, &written);
                        if (rc) {
                                ecryptfs_printk(KERN_WARNING, "Error "
@@ -2451,14 +2460,13 @@ ecryptfs_generate_key_packet_set(char *dest_base,
                        }
                        (*len) += written;
                } else {
+                       up_write(&(auth_tok_key->sem));
+                       key_put(auth_tok_key);
                        ecryptfs_printk(KERN_WARNING, "Unsupported "
                                        "authentication token type\n");
                        rc = -EINVAL;
                        goto out_free;
                }
-               up_write(&(auth_tok_key->sem));
-               key_put(auth_tok_key);
-               auth_tok_key = NULL;
        }
        if (likely(max > 0)) {
                dest_base[(*len)] = 0x00;
@@ -2471,11 +2479,6 @@ out_free:
 out:
        if (rc)
                (*len) = 0;
-       if (auth_tok_key) {
-               up_write(&(auth_tok_key->sem));
-               key_put(auth_tok_key);
-       }
-
        mutex_unlock(&crypt_stat->keysig_list_mutex);
        return rc;
 }
index 9f1bb74..b4a6bef 100644 (file)
@@ -175,6 +175,7 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
        ecryptfs_opt_encrypted_view, ecryptfs_opt_fnek_sig,
        ecryptfs_opt_fn_cipher, ecryptfs_opt_fn_cipher_key_bytes,
        ecryptfs_opt_unlink_sigs, ecryptfs_opt_mount_auth_tok_only,
+       ecryptfs_opt_check_dev_ruid,
        ecryptfs_opt_err };
 
 static const match_table_t tokens = {
@@ -191,6 +192,7 @@ static const match_table_t tokens = {
        {ecryptfs_opt_fn_cipher_key_bytes, "ecryptfs_fn_key_bytes=%u"},
        {ecryptfs_opt_unlink_sigs, "ecryptfs_unlink_sigs"},
        {ecryptfs_opt_mount_auth_tok_only, "ecryptfs_mount_auth_tok_only"},
+       {ecryptfs_opt_check_dev_ruid, "ecryptfs_check_dev_ruid"},
        {ecryptfs_opt_err, NULL}
 };
 
@@ -236,6 +238,7 @@ static void ecryptfs_init_mount_crypt_stat(
  * ecryptfs_parse_options
  * @sb: The ecryptfs super block
  * @options: The options passed to the kernel
+ * @check_ruid: set to 1 if device uid should be checked against the ruid
  *
  * Parse mount options:
  * debug=N        - ecryptfs_verbosity level for debug output
@@ -251,7 +254,8 @@ static void ecryptfs_init_mount_crypt_stat(
  *
  * Returns zero on success; non-zero on error
  */
-static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options)
+static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options,
+                                 uid_t *check_ruid)
 {
        char *p;
        int rc = 0;
@@ -276,6 +280,8 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options)
        char *cipher_key_bytes_src;
        char *fn_cipher_key_bytes_src;
 
+       *check_ruid = 0;
+
        if (!options) {
                rc = -EINVAL;
                goto out;
@@ -380,6 +386,9 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options)
                        mount_crypt_stat->flags |=
                                ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY;
                        break;
+               case ecryptfs_opt_check_dev_ruid:
+                       *check_ruid = 1;
+                       break;
                case ecryptfs_opt_err:
                default:
                        printk(KERN_WARNING
@@ -475,6 +484,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
        const char *err = "Getting sb failed";
        struct inode *inode;
        struct path path;
+       uid_t check_ruid;
        int rc;
 
        sbi = kmem_cache_zalloc(ecryptfs_sb_info_cache, GFP_KERNEL);
@@ -483,7 +493,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
                goto out;
        }
 
-       rc = ecryptfs_parse_options(sbi, raw_data);
+       rc = ecryptfs_parse_options(sbi, raw_data, &check_ruid);
        if (rc) {
                err = "Error parsing options";
                goto out;
@@ -521,6 +531,15 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
                        "known incompatibilities\n");
                goto out_free;
        }
+
+       if (check_ruid && path.dentry->d_inode->i_uid != current_uid()) {
+               rc = -EPERM;
+               printk(KERN_ERR "Mount of device (uid: %d) not owned by "
+                      "requested user (uid: %d)\n",
+                      path.dentry->d_inode->i_uid, current_uid());
+               goto out_free;
+       }
+
        ecryptfs_set_superblock_lower(s, path.dentry->d_sb);
        s->s_maxbytes = path.dentry->d_sb->s_maxbytes;
        s->s_blocksize = path.dentry->d_sb->s_blocksize;
index 85d4309..3745f7c 100644 (file)
 int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
                         loff_t offset, size_t size)
 {
-       struct ecryptfs_inode_info *inode_info;
+       struct file *lower_file;
        mm_segment_t fs_save;
        ssize_t rc;
 
-       inode_info = ecryptfs_inode_to_private(ecryptfs_inode);
-       BUG_ON(!inode_info->lower_file);
+       lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file;
+       if (!lower_file)
+               return -EIO;
        fs_save = get_fs();
        set_fs(get_ds());
-       rc = vfs_write(inode_info->lower_file, data, size, &offset);
+       rc = vfs_write(lower_file, data, size, &offset);
        set_fs(fs_save);
        mark_inode_dirty_sync(ecryptfs_inode);
        return rc;
@@ -225,15 +226,16 @@ out:
 int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
                        struct inode *ecryptfs_inode)
 {
-       struct ecryptfs_inode_info *inode_info =
-               ecryptfs_inode_to_private(ecryptfs_inode);
+       struct file *lower_file;
        mm_segment_t fs_save;
        ssize_t rc;
 
-       BUG_ON(!inode_info->lower_file);
+       lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file;
+       if (!lower_file)
+               return -EIO;
        fs_save = get_fs();
        set_fs(get_ds());
-       rc = vfs_read(inode_info->lower_file, data, size, &offset);
+       rc = vfs_read(lower_file, data, size, &offset);
        set_fs(fs_save);
        return rc;
 }
index da80612..25dcbe5 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1459,6 +1459,23 @@ static int do_execve_common(const char *filename,
        struct files_struct *displaced;
        bool clear_in_exec;
        int retval;
+       const struct cred *cred = current_cred();
+
+       /*
+        * We move the actual failure in case of RLIMIT_NPROC excess from
+        * set*uid() to execve() because too many poorly written programs
+        * don't check setuid() return code.  Here we additionally recheck
+        * whether NPROC limit is still exceeded.
+        */
+       if ((current->flags & PF_NPROC_EXCEEDED) &&
+           atomic_read(&cred->user->processes) > rlimit(RLIMIT_NPROC)) {
+               retval = -EAGAIN;
+               goto out_ret;
+       }
+
+       /* We're below the limit (still or again), so we don't want to make
+        * further execve() calls fail. */
+       current->flags &= ~PF_NPROC_EXCEEDED;
 
        retval = unshare_files(&displaced);
        if (retval)
index 2d0f757..c5a5855 100644 (file)
@@ -12,5 +12,8 @@
 # Kbuild - Gets included from the Kernels Makefile and build system
 #
 
-exofs-y := ios.o inode.o file.o symlink.o namei.o dir.o super.o
+# ore module library
+obj-$(CONFIG_ORE) += ore.o
+
+exofs-y := inode.o file.o symlink.o namei.o dir.o super.o
 obj-$(CONFIG_EXOFS_FS) += exofs.o
index 86194b2..70bae41 100644 (file)
@@ -1,6 +1,10 @@
+config ORE
+       tristate
+
 config EXOFS_FS
        tristate "exofs: OSD based file system support"
        depends on SCSI_OSD_ULD
+       select ORE
        help
          EXOFS is a file system that uses an OSD storage device,
          as its backing storage.
index c965806..f4e442e 100644 (file)
 #include <linux/fs.h>
 #include <linux/time.h>
 #include <linux/backing-dev.h>
-#include "common.h"
+#include <scsi/osd_ore.h>
 
-/* FIXME: Remove once pnfs hits mainline
- * #include <linux/exportfs/pnfs_osd_xdr.h>
- */
-#include "pnfs.h"
+#include "common.h"
 
 #define EXOFS_ERR(fmt, a...) printk(KERN_ERR "exofs: " fmt, ##a)
 
 /* u64 has problems with printk this will cast it to unsigned long long */
 #define _LLU(x) (unsigned long long)(x)
 
-struct exofs_layout {
-       osd_id          s_pid;                  /* partition ID of file system*/
-
-       /* Our way of looking at the data_map */
-       unsigned stripe_unit;
-       unsigned mirrors_p1;
-
-       unsigned group_width;
-       u64      group_depth;
-       unsigned group_count;
-
-       enum exofs_inode_layout_gen_functions lay_func;
-
-       unsigned        s_numdevs;              /* Num of devices in array    */
-       struct osd_dev  *s_ods[0];              /* Variable length            */
-};
-
 /*
  * our extension to the in-memory superblock
  */
 struct exofs_sb_info {
+       struct backing_dev_info bdi;            /* register our bdi with VFS  */
        struct exofs_sb_stats s_ess;            /* Written often, pre-allocate*/
        int             s_timeout;              /* timeout for OSD operations */
        uint64_t        s_nextid;               /* highest object ID used     */
@@ -84,16 +65,13 @@ struct exofs_sb_info {
        spinlock_t      s_next_gen_lock;        /* spinlock for gen # update  */
        u32             s_next_generation;      /* next gen # to use          */
        atomic_t        s_curr_pending;         /* number of pending commands */
-       uint8_t         s_cred[OSD_CAP_LEN];    /* credential for the fscb    */
-       struct          backing_dev_info bdi;   /* register our bdi with VFS  */
 
        struct pnfs_osd_data_map data_map;      /* Default raid to use
                                                 * FIXME: Needed ?
                                                 */
-/*     struct exofs_layout     dir_layout;*/   /* Default dir layout */
-       struct exofs_layout     layout;         /* Default files layout,
-                                                * contains the variable osd_dev
-                                                * array. Keep last */
+       struct ore_layout       layout;         /* Default files layout       */
+       struct ore_comp one_comp;               /* id & cred of partition id=0*/
+       struct ore_components comps;            /* comps for the partition    */
        struct osd_dev  *_min_one_dev[1];       /* Place holder for one dev   */
 };
 
@@ -107,7 +85,8 @@ struct exofs_i_info {
        uint32_t       i_data[EXOFS_IDATA];/*short symlink names and device #s*/
        uint32_t       i_dir_start_lookup; /* which page to start lookup      */
        uint64_t       i_commit_size;      /* the object's written length     */
-       uint8_t        i_cred[OSD_CAP_LEN];/* all-powerful credential         */
+       struct ore_comp one_comp;          /* same component for all devices  */
+       struct ore_components comps;       /* inode view of the device table  */
 };
 
 static inline osd_id exofs_oi_objno(struct exofs_i_info *oi)
@@ -115,52 +94,6 @@ static inline osd_id exofs_oi_objno(struct exofs_i_info *oi)
        return oi->vfs_inode.i_ino + EXOFS_OBJ_OFF;
 }
 
-struct exofs_io_state;
-typedef void (*exofs_io_done_fn)(struct exofs_io_state *or, void *private);
-
-struct exofs_io_state {
-       struct kref             kref;
-
-       void                    *private;
-       exofs_io_done_fn        done;
-
-       struct exofs_layout     *layout;
-       struct osd_obj_id       obj;
-       u8                      *cred;
-
-       /* Global read/write IO*/
-       loff_t                  offset;
-       unsigned long           length;
-       void                    *kern_buff;
-
-       struct page             **pages;
-       unsigned                nr_pages;
-       unsigned                pgbase;
-       unsigned                pages_consumed;
-
-       /* Attributes */
-       unsigned                in_attr_len;
-       struct osd_attr         *in_attr;
-       unsigned                out_attr_len;
-       struct osd_attr         *out_attr;
-
-       /* Variable array of size numdevs */
-       unsigned numdevs;
-       struct exofs_per_dev_state {
-               struct osd_request *or;
-               struct bio *bio;
-               loff_t offset;
-               unsigned length;
-               unsigned dev;
-       } per_dev[];
-};
-
-static inline unsigned exofs_io_state_size(unsigned numdevs)
-{
-       return sizeof(struct exofs_io_state) +
-               sizeof(struct exofs_per_dev_state) * numdevs;
-}
-
 /*
  * our inode flags
  */
@@ -204,12 +137,6 @@ static inline struct exofs_i_info *exofs_i(struct inode *inode)
        return container_of(inode, struct exofs_i_info, vfs_inode);
 }
 
-/*
- * Given a layout, object_number and stripe_index return the associated global
- * dev_index
- */
-unsigned exofs_layout_od_id(struct exofs_layout *layout,
-                           osd_id obj_no, unsigned layout_index);
 /*
  * Maximum count of links to a file
  */
@@ -219,44 +146,8 @@ unsigned exofs_layout_od_id(struct exofs_layout *layout,
  * function declarations *
  *************************/
 
-/* ios.c */
-void exofs_make_credential(u8 cred_a[OSD_CAP_LEN],
-                          const struct osd_obj_id *obj);
-int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj,
-                   u64 offset, void *p, unsigned length);
-
-int  exofs_get_io_state(struct exofs_layout *layout,
-                       struct exofs_io_state **ios);
-void exofs_put_io_state(struct exofs_io_state *ios);
-
-int exofs_check_io(struct exofs_io_state *ios, u64 *resid);
-
-int exofs_sbi_create(struct exofs_io_state *ios);
-int exofs_sbi_remove(struct exofs_io_state *ios);
-int exofs_sbi_write(struct exofs_io_state *ios);
-int exofs_sbi_read(struct exofs_io_state *ios);
-
-int extract_attr_from_ios(struct exofs_io_state *ios, struct osd_attr *attr);
-
-int exofs_oi_truncate(struct exofs_i_info *oi, u64 new_len);
-static inline int exofs_oi_write(struct exofs_i_info *oi,
-                                struct exofs_io_state *ios)
-{
-       ios->obj.id = exofs_oi_objno(oi);
-       ios->cred = oi->i_cred;
-       return exofs_sbi_write(ios);
-}
-
-static inline int exofs_oi_read(struct exofs_i_info *oi,
-                               struct exofs_io_state *ios)
-{
-       ios->obj.id = exofs_oi_objno(oi);
-       ios->cred = oi->i_cred;
-       return exofs_sbi_read(ios);
-}
-
 /* inode.c               */
-unsigned exofs_max_io_pages(struct exofs_layout *layout,
+unsigned exofs_max_io_pages(struct ore_layout *layout,
                            unsigned expected_pages);
 int exofs_setattr(struct dentry *, struct iattr *);
 int exofs_write_begin(struct file *file, struct address_space *mapping,
@@ -281,6 +172,8 @@ int exofs_set_link(struct inode *, struct exofs_dir_entry *, struct page *,
                    struct inode *);
 
 /* super.c               */
+void exofs_make_credential(u8 cred_a[OSD_CAP_LEN],
+                          const struct osd_obj_id *obj);
 int exofs_sbi_write_stats(struct exofs_sb_info *sbi);
 
 /*********************
@@ -295,7 +188,6 @@ extern const struct file_operations exofs_file_operations;
 
 /* inode.c           */
 extern const struct address_space_operations exofs_aops;
-extern const struct osd_attr g_attr_logical_length;
 
 /* namei.c           */
 extern const struct inode_operations exofs_dir_inode_operations;
@@ -305,4 +197,33 @@ extern const struct inode_operations exofs_special_inode_operations;
 extern const struct inode_operations exofs_symlink_inode_operations;
 extern const struct inode_operations exofs_fast_symlink_inode_operations;
 
+/* exofs_init_comps will initialize an ore_components device array
+ * pointing to a single ore_comp struct, and a round-robin view
+ * of the device table.
+ * The first device of each inode is the [inode->ino % num_devices]
+ * and the rest of the devices sequentially following where the
+ * first device is after the last device.
+ * It is assumed that the global device array at @sbi is twice
+ * bigger and that the device table repeats twice.
+ * See: exofs_read_lookup_dev_table()
+ */
+static inline void exofs_init_comps(struct ore_components *comps,
+                                   struct ore_comp *one_comp,
+                                   struct exofs_sb_info *sbi, osd_id oid)
+{
+       unsigned dev_mod = (unsigned)oid, first_dev;
+
+       one_comp->obj.partition = sbi->one_comp.obj.partition;
+       one_comp->obj.id = oid;
+       exofs_make_credential(one_comp->cred, &one_comp->obj);
+
+       comps->numdevs = sbi->comps.numdevs;
+       comps->single_comp = EC_SINGLE_COMP;
+       comps->comps = one_comp;
+
+       /* Round robin device view of the table */
+       first_dev = (dev_mod * sbi->layout.mirrors_p1) % sbi->comps.numdevs;
+       comps->ods = sbi->comps.ods + first_dev;
+}
+
 #endif
index 8472c09..f39a38f 100644 (file)
@@ -43,7 +43,7 @@ enum { BIO_MAX_PAGES_KMALLOC =
                PAGE_SIZE / sizeof(struct page *),
 };
 
-unsigned exofs_max_io_pages(struct exofs_layout *layout,
+unsigned exofs_max_io_pages(struct ore_layout *layout,
                            unsigned expected_pages)
 {
        unsigned pages = min_t(unsigned, expected_pages, MAX_PAGES_KMALLOC);
@@ -58,7 +58,7 @@ struct page_collect {
        struct exofs_sb_info *sbi;
        struct inode *inode;
        unsigned expected_pages;
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
 
        struct page **pages;
        unsigned alloc_pages;
@@ -110,13 +110,6 @@ static int pcol_try_alloc(struct page_collect *pcol)
 {
        unsigned pages;
 
-       if (!pcol->ios) { /* First time allocate io_state */
-               int ret = exofs_get_io_state(&pcol->sbi->layout, &pcol->ios);
-
-               if (ret)
-                       return ret;
-       }
-
        /* TODO: easily support bio chaining */
        pages =  exofs_max_io_pages(&pcol->sbi->layout, pcol->expected_pages);
 
@@ -140,7 +133,7 @@ static void pcol_free(struct page_collect *pcol)
        pcol->pages = NULL;
 
        if (pcol->ios) {
-               exofs_put_io_state(pcol->ios);
+               ore_put_io_state(pcol->ios);
                pcol->ios = NULL;
        }
 }
@@ -200,7 +193,7 @@ static int __readpages_done(struct page_collect *pcol)
        u64 resid;
        u64 good_bytes;
        u64 length = 0;
-       int ret = exofs_check_io(pcol->ios, &resid);
+       int ret = ore_check_io(pcol->ios, &resid);
 
        if (likely(!ret))
                good_bytes = pcol->length;
@@ -241,7 +234,7 @@ static int __readpages_done(struct page_collect *pcol)
 }
 
 /* callback of async reads */
-static void readpages_done(struct exofs_io_state *ios, void *p)
+static void readpages_done(struct ore_io_state *ios, void *p)
 {
        struct page_collect *pcol = p;
 
@@ -269,20 +262,28 @@ static void _unlock_pcol_pages(struct page_collect *pcol, int ret, int rw)
 static int read_exec(struct page_collect *pcol)
 {
        struct exofs_i_info *oi = exofs_i(pcol->inode);
-       struct exofs_io_state *ios = pcol->ios;
+       struct ore_io_state *ios;
        struct page_collect *pcol_copy = NULL;
        int ret;
 
        if (!pcol->pages)
                return 0;
 
+       if (!pcol->ios) {
+               int ret = ore_get_rw_state(&pcol->sbi->layout, &oi->comps, true,
+                                            pcol->pg_first << PAGE_CACHE_SHIFT,
+                                            pcol->length, &pcol->ios);
+
+               if (ret)
+                       return ret;
+       }
+
+       ios = pcol->ios;
        ios->pages = pcol->pages;
        ios->nr_pages = pcol->nr_pages;
-       ios->length = pcol->length;
-       ios->offset = pcol->pg_first << PAGE_CACHE_SHIFT;
 
        if (pcol->read_4_write) {
-               exofs_oi_read(oi, pcol->ios);
+               ore_read(pcol->ios);
                return __readpages_done(pcol);
        }
 
@@ -295,14 +296,14 @@ static int read_exec(struct page_collect *pcol)
        *pcol_copy = *pcol;
        ios->done = readpages_done;
        ios->private = pcol_copy;
-       ret = exofs_oi_read(oi, ios);
+       ret = ore_read(ios);
        if (unlikely(ret))
                goto err;
 
        atomic_inc(&pcol->sbi->s_curr_pending);
 
        EXOFS_DBGMSG2("read_exec obj=0x%llx start=0x%llx length=0x%lx\n",
-                 ios->obj.id, _LLU(ios->offset), pcol->length);
+                 oi->one_comp.obj.id, _LLU(ios->offset), pcol->length);
 
        /* pages ownership was passed to pcol_copy */
        _pcol_reset(pcol);
@@ -457,14 +458,14 @@ static int exofs_readpage(struct file *file, struct page *page)
 }
 
 /* Callback for osd_write. All writes are asynchronous */
-static void writepages_done(struct exofs_io_state *ios, void *p)
+static void writepages_done(struct ore_io_state *ios, void *p)
 {
        struct page_collect *pcol = p;
        int i;
        u64 resid;
        u64  good_bytes;
        u64  length = 0;
-       int ret = exofs_check_io(ios, &resid);
+       int ret = ore_check_io(ios, &resid);
 
        atomic_dec(&pcol->sbi->s_curr_pending);
 
@@ -507,13 +508,21 @@ static void writepages_done(struct exofs_io_state *ios, void *p)
 static int write_exec(struct page_collect *pcol)
 {
        struct exofs_i_info *oi = exofs_i(pcol->inode);
-       struct exofs_io_state *ios = pcol->ios;
+       struct ore_io_state *ios;
        struct page_collect *pcol_copy = NULL;
        int ret;
 
        if (!pcol->pages)
                return 0;
 
+       BUG_ON(pcol->ios);
+       ret = ore_get_rw_state(&pcol->sbi->layout, &oi->comps, false,
+                                pcol->pg_first << PAGE_CACHE_SHIFT,
+                                pcol->length, &pcol->ios);
+
+       if (unlikely(ret))
+               goto err;
+
        pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL);
        if (!pcol_copy) {
                EXOFS_ERR("write_exec: Failed to kmalloc(pcol)\n");
@@ -523,16 +532,15 @@ static int write_exec(struct page_collect *pcol)
 
        *pcol_copy = *pcol;
 
+       ios = pcol->ios;
        ios->pages = pcol_copy->pages;
        ios->nr_pages = pcol_copy->nr_pages;
-       ios->offset = pcol_copy->pg_first << PAGE_CACHE_SHIFT;
-       ios->length = pcol_copy->length;
        ios->done = writepages_done;
        ios->private = pcol_copy;
 
-       ret = exofs_oi_write(oi, ios);
+       ret = ore_write(ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("write_exec: exofs_oi_write() Failed\n");
+               EXOFS_ERR("write_exec: ore_write() Failed\n");
                goto err;
        }
 
@@ -844,17 +852,15 @@ static inline int exofs_inode_is_fast_symlink(struct inode *inode)
        return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0);
 }
 
-const struct osd_attr g_attr_logical_length = ATTR_DEF(
-       OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);
-
 static int _do_truncate(struct inode *inode, loff_t newsize)
 {
        struct exofs_i_info *oi = exofs_i(inode);
+       struct exofs_sb_info *sbi = inode->i_sb->s_fs_info;
        int ret;
 
        inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 
-       ret = exofs_oi_truncate(oi, (u64)newsize);
+       ret = ore_truncate(&sbi->layout, &oi->comps, (u64)newsize);
        if (likely(!ret))
                truncate_setsize(inode, newsize);
 
@@ -917,30 +923,26 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi,
                [1] = g_attr_inode_file_layout,
                [2] = g_attr_inode_dir_layout,
        };
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        struct exofs_on_disk_inode_layout *layout;
        int ret;
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &oi->comps, &ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__);
+               EXOFS_ERR("%s: ore_get_io_state failed.\n", __func__);
                return ret;
        }
 
-       ios->obj.id = exofs_oi_objno(oi);
-       exofs_make_credential(oi->i_cred, &ios->obj);
-       ios->cred = oi->i_cred;
-
-       attrs[1].len = exofs_on_disk_inode_layout_size(sbi->layout.s_numdevs);
-       attrs[2].len = exofs_on_disk_inode_layout_size(sbi->layout.s_numdevs);
+       attrs[1].len = exofs_on_disk_inode_layout_size(sbi->comps.numdevs);
+       attrs[2].len = exofs_on_disk_inode_layout_size(sbi->comps.numdevs);
 
        ios->in_attr = attrs;
        ios->in_attr_len = ARRAY_SIZE(attrs);
 
-       ret = exofs_sbi_read(ios);
+       ret = ore_read(ios);
        if (unlikely(ret)) {
                EXOFS_ERR("object(0x%llx) corrupted, return empty file=>%d\n",
-                         _LLU(ios->obj.id), ret);
+                         _LLU(oi->one_comp.obj.id), ret);
                memset(inode, 0, sizeof(*inode));
                inode->i_mode = 0040000 | (0777 & ~022);
                /* If object is lost on target we might as well enable it's
@@ -990,7 +992,7 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi,
        }
 
 out:
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
        return ret;
 }
 
@@ -1016,6 +1018,8 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino)
                return inode;
        oi = exofs_i(inode);
        __oi_init(oi);
+       exofs_init_comps(&oi->comps, &oi->one_comp, sb->s_fs_info,
+                        exofs_oi_objno(oi));
 
        /* read the inode from the osd */
        ret = exofs_get_inode(sb, oi, &fcb);
@@ -1107,21 +1111,22 @@ int __exofs_wait_obj_created(struct exofs_i_info *oi)
  * set the obj_created flag so that other methods know that the object exists on
  * the OSD.
  */
-static void create_done(struct exofs_io_state *ios, void *p)
+static void create_done(struct ore_io_state *ios, void *p)
 {
        struct inode *inode = p;
        struct exofs_i_info *oi = exofs_i(inode);
        struct exofs_sb_info *sbi = inode->i_sb->s_fs_info;
        int ret;
 
-       ret = exofs_check_io(ios, NULL);
-       exofs_put_io_state(ios);
+       ret = ore_check_io(ios, NULL);
+       ore_put_io_state(ios);
 
        atomic_dec(&sbi->s_curr_pending);
 
        if (unlikely(ret)) {
                EXOFS_ERR("object=0x%llx creation failed in pid=0x%llx",
-                         _LLU(exofs_oi_objno(oi)), _LLU(sbi->layout.s_pid));
+                         _LLU(exofs_oi_objno(oi)),
+                         _LLU(oi->one_comp.obj.partition));
                /*TODO: When FS is corrupted creation can fail, object already
                 * exist. Get rid of this asynchronous creation, if exist
                 * increment the obj counter and try the next object. Until we
@@ -1140,14 +1145,13 @@ static void create_done(struct exofs_io_state *ios, void *p)
  */
 struct inode *exofs_new_inode(struct inode *dir, int mode)
 {
-       struct super_block *sb;
+       struct super_block *sb = dir->i_sb;
+       struct exofs_sb_info *sbi = sb->s_fs_info;
        struct inode *inode;
        struct exofs_i_info *oi;
-       struct exofs_sb_info *sbi;
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        int ret;
 
-       sb = dir->i_sb;
        inode = new_inode(sb);
        if (!inode)
                return ERR_PTR(-ENOMEM);
@@ -1157,8 +1161,6 @@ struct inode *exofs_new_inode(struct inode *dir, int mode)
 
        set_obj_2bcreated(oi);
 
-       sbi = sb->s_fs_info;
-
        inode->i_mapping->backing_dev_info = sb->s_bdi;
        inode_init_owner(inode, dir, mode);
        inode->i_ino = sbi->s_nextid++;
@@ -1170,25 +1172,24 @@ struct inode *exofs_new_inode(struct inode *dir, int mode)
        spin_unlock(&sbi->s_next_gen_lock);
        insert_inode_hash(inode);
 
+       exofs_init_comps(&oi->comps, &oi->one_comp, sb->s_fs_info,
+                        exofs_oi_objno(oi));
        exofs_sbi_write_stats(sbi); /* Make sure new sbi->s_nextid is on disk */
 
        mark_inode_dirty(inode);
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &oi->comps, &ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("exofs_new_inode: exofs_get_io_state failed\n");
+               EXOFS_ERR("exofs_new_inode: ore_get_io_state failed\n");
                return ERR_PTR(ret);
        }
 
-       ios->obj.id = exofs_oi_objno(oi);
-       exofs_make_credential(oi->i_cred, &ios->obj);
-
        ios->done = create_done;
        ios->private = inode;
-       ios->cred = oi->i_cred;
-       ret = exofs_sbi_create(ios);
+
+       ret = ore_create(ios);
        if (ret) {
-               exofs_put_io_state(ios);
+               ore_put_io_state(ios);
                return ERR_PTR(ret);
        }
        atomic_inc(&sbi->s_curr_pending);
@@ -1207,11 +1208,11 @@ struct updatei_args {
 /*
  * Callback function from exofs_update_inode().
  */
-static void updatei_done(struct exofs_io_state *ios, void *p)
+static void updatei_done(struct ore_io_state *ios, void *p)
 {
        struct updatei_args *args = p;
 
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
 
        atomic_dec(&args->sbi->s_curr_pending);
 
@@ -1227,7 +1228,7 @@ static int exofs_update_inode(struct inode *inode, int do_sync)
        struct exofs_i_info *oi = exofs_i(inode);
        struct super_block *sb = inode->i_sb;
        struct exofs_sb_info *sbi = sb->s_fs_info;
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        struct osd_attr attr;
        struct exofs_fcb *fcb;
        struct updatei_args *args;
@@ -1266,9 +1267,9 @@ static int exofs_update_inode(struct inode *inode, int do_sync)
        } else
                memcpy(fcb->i_data, oi->i_data, sizeof(fcb->i_data));
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &oi->comps, &ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__);
+               EXOFS_ERR("%s: ore_get_io_state failed.\n", __func__);
                goto free_args;
        }
 
@@ -1285,13 +1286,13 @@ static int exofs_update_inode(struct inode *inode, int do_sync)
                ios->private = args;
        }
 
-       ret = exofs_oi_write(oi, ios);
+       ret = ore_write(ios);
        if (!do_sync && !ret) {
                atomic_inc(&sbi->s_curr_pending);
                goto out; /* deallocation in updatei_done */
        }
 
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
 free_args:
        kfree(args);
 out:
@@ -1310,11 +1311,11 @@ int exofs_write_inode(struct inode *inode, struct writeback_control *wbc)
  * Callback function from exofs_delete_inode() - don't have much cleaning up to
  * do.
  */
-static void delete_done(struct exofs_io_state *ios, void *p)
+static void delete_done(struct ore_io_state *ios, void *p)
 {
        struct exofs_sb_info *sbi = p;
 
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
 
        atomic_dec(&sbi->s_curr_pending);
 }
@@ -1329,7 +1330,7 @@ void exofs_evict_inode(struct inode *inode)
        struct exofs_i_info *oi = exofs_i(inode);
        struct super_block *sb = inode->i_sb;
        struct exofs_sb_info *sbi = sb->s_fs_info;
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        int ret;
 
        truncate_inode_pages(&inode->i_data, 0);
@@ -1349,20 +1350,19 @@ void exofs_evict_inode(struct inode *inode)
        /* ignore the error, attempt a remove anyway */
 
        /* Now Remove the OSD objects */
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &oi->comps, &ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__);
+               EXOFS_ERR("%s: ore_get_io_state failed\n", __func__);
                return;
        }
 
-       ios->obj.id = exofs_oi_objno(oi);
        ios->done = delete_done;
        ios->private = sbi;
-       ios->cred = oi->i_cred;
-       ret = exofs_sbi_remove(ios);
+
+       ret = ore_remove(ios);
        if (ret) {
-               EXOFS_ERR("%s: exofs_sbi_remove failed\n", __func__);
-               exofs_put_io_state(ios);
+               EXOFS_ERR("%s: ore_remove failed\n", __func__);
+               ore_put_io_state(ios);
                return;
        }
        atomic_inc(&sbi->s_curr_pending);
similarity index 61%
rename from fs/exofs/ios.c
rename to fs/exofs/ore.c
index f74a2ec..25305af 100644 (file)
  */
 
 #include <linux/slab.h>
-#include <scsi/scsi_device.h>
 #include <asm/div64.h>
 
-#include "exofs.h"
+#include <scsi/osd_ore.h>
 
-#define EXOFS_DBGMSG2(M...) do {} while (0)
-/* #define EXOFS_DBGMSG2 EXOFS_DBGMSG */
+#define ORE_ERR(fmt, a...) printk(KERN_ERR "ore: " fmt, ##a)
 
-void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], const struct osd_obj_id *obj)
-{
-       osd_sec_init_nosec_doall_caps(cred_a, obj, false, true);
-}
+#ifdef CONFIG_EXOFS_DEBUG
+#define ORE_DBGMSG(fmt, a...) \
+       printk(KERN_NOTICE "ore @%s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define ORE_DBGMSG(fmt, a...) \
+       do { if (0) printk(fmt, ##a); } while (0)
+#endif
 
-int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj,
-                   u64 offset, void *p, unsigned length)
-{
-       struct osd_request *or = osd_start_request(od, GFP_KERNEL);
-/*     struct osd_sense_info osi = {.key = 0};*/
-       int ret;
+/* u64 has problems with printk this will cast it to unsigned long long */
+#define _LLU(x) (unsigned long long)(x)
 
-       if (unlikely(!or)) {
-               EXOFS_DBGMSG("%s: osd_start_request failed.\n", __func__);
-               return -ENOMEM;
-       }
-       ret = osd_req_read_kern(or, obj, offset, p, length);
-       if (unlikely(ret)) {
-               EXOFS_DBGMSG("%s: osd_req_read_kern failed.\n", __func__);
-               goto out;
-       }
+#define ORE_DBGMSG2(M...) do {} while (0)
+/* #define ORE_DBGMSG2 ORE_DBGMSG */
 
-       ret = osd_finalize_request(or, 0, cred, NULL);
-       if (unlikely(ret)) {
-               EXOFS_DBGMSG("Failed to osd_finalize_request() => %d\n", ret);
-               goto out;
-       }
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("Objects Raid Engine ore.ko");
+MODULE_LICENSE("GPL");
 
-       ret = osd_execute_request(or);
-       if (unlikely(ret))
-               EXOFS_DBGMSG("osd_execute_request() => %d\n", ret);
-       /* osd_req_decode_sense(or, ret); */
+static u8 *_ios_cred(struct ore_io_state *ios, unsigned index)
+{
+       return ios->comps->comps[index & ios->comps->single_comp].cred;
+}
 
-out:
-       osd_end_request(or);
-       return ret;
+static struct osd_obj_id *_ios_obj(struct ore_io_state *ios, unsigned index)
+{
+       return &ios->comps->comps[index & ios->comps->single_comp].obj;
 }
 
-int exofs_get_io_state(struct exofs_layout *layout,
-                      struct exofs_io_state **pios)
+static struct osd_dev *_ios_od(struct ore_io_state *ios, unsigned index)
 {
-       struct exofs_io_state *ios;
+       return ios->comps->ods[index];
+}
+
+int  ore_get_rw_state(struct ore_layout *layout, struct ore_components *comps,
+                     bool is_reading, u64 offset, u64 length,
+                     struct ore_io_state **pios)
+{
+       struct ore_io_state *ios;
 
        /*TODO: Maybe use kmem_cach per sbi of size
         * exofs_io_state_size(layout->s_numdevs)
         */
-       ios = kzalloc(exofs_io_state_size(layout->s_numdevs), GFP_KERNEL);
+       ios = kzalloc(ore_io_state_size(comps->numdevs), GFP_KERNEL);
        if (unlikely(!ios)) {
-               EXOFS_DBGMSG("Failed kzalloc bytes=%d\n",
-                            exofs_io_state_size(layout->s_numdevs));
+               ORE_DBGMSG("Failed kzalloc bytes=%d\n",
+                            ore_io_state_size(comps->numdevs));
                *pios = NULL;
                return -ENOMEM;
        }
 
        ios->layout = layout;
-       ios->obj.partition = layout->s_pid;
+       ios->comps = comps;
+       ios->offset = offset;
+       ios->length = length;
+       ios->reading = is_reading;
+
        *pios = ios;
        return 0;
 }
+EXPORT_SYMBOL(ore_get_rw_state);
+
+int  ore_get_io_state(struct ore_layout *layout, struct ore_components *comps,
+                     struct ore_io_state **ios)
+{
+       return ore_get_rw_state(layout, comps, true, 0, 0, ios);
+}
+EXPORT_SYMBOL(ore_get_io_state);
 
-void exofs_put_io_state(struct exofs_io_state *ios)
+void ore_put_io_state(struct ore_io_state *ios)
 {
        if (ios) {
                unsigned i;
 
                for (i = 0; i < ios->numdevs; i++) {
-                       struct exofs_per_dev_state *per_dev = &ios->per_dev[i];
+                       struct ore_per_dev_state *per_dev = &ios->per_dev[i];
 
                        if (per_dev->or)
                                osd_end_request(per_dev->or);
@@ -108,31 +114,9 @@ void exofs_put_io_state(struct exofs_io_state *ios)
                kfree(ios);
        }
 }
+EXPORT_SYMBOL(ore_put_io_state);
 
-unsigned exofs_layout_od_id(struct exofs_layout *layout,
-                           osd_id obj_no, unsigned layout_index)
-{
-/*     switch (layout->lay_func) {
-       case LAYOUT_MOVING_WINDOW:
-       {*/
-               unsigned dev_mod = obj_no;
-
-               return (layout_index + dev_mod * layout->mirrors_p1) %
-                                                             layout->s_numdevs;
-/*     }
-       case LAYOUT_FUNC_IMPLICT:
-               return layout->devs[layout_index];
-       }*/
-}
-
-static inline struct osd_dev *exofs_ios_od(struct exofs_io_state *ios,
-                                          unsigned layout_index)
-{
-       return ios->layout->s_ods[
-               exofs_layout_od_id(ios->layout, ios->obj.id, layout_index)];
-}
-
-static void _sync_done(struct exofs_io_state *ios, void *p)
+static void _sync_done(struct ore_io_state *ios, void *p)
 {
        struct completion *waiting = p;
 
@@ -141,20 +125,20 @@ static void _sync_done(struct exofs_io_state *ios, void *p)
 
 static void _last_io(struct kref *kref)
 {
-       struct exofs_io_state *ios = container_of(
-                                       kref, struct exofs_io_state, kref);
+       struct ore_io_state *ios = container_of(
+                                       kref, struct ore_io_state, kref);
 
        ios->done(ios, ios->private);
 }
 
 static void _done_io(struct osd_request *or, void *p)
 {
-       struct exofs_io_state *ios = p;
+       struct ore_io_state *ios = p;
 
        kref_put(&ios->kref, _last_io);
 }
 
-static int exofs_io_execute(struct exofs_io_state *ios)
+static int ore_io_execute(struct ore_io_state *ios)
 {
        DECLARE_COMPLETION_ONSTACK(wait);
        bool sync = (ios->done == NULL);
@@ -170,9 +154,9 @@ static int exofs_io_execute(struct exofs_io_state *ios)
                if (unlikely(!or))
                        continue;
 
-               ret = osd_finalize_request(or, 0, ios->cred, NULL);
+               ret = osd_finalize_request(or, 0, _ios_cred(ios, i), NULL);
                if (unlikely(ret)) {
-                       EXOFS_DBGMSG("Failed to osd_finalize_request() => %d\n",
+                       ORE_DBGMSG("Failed to osd_finalize_request() => %d\n",
                                     ret);
                        return ret;
                }
@@ -194,7 +178,7 @@ static int exofs_io_execute(struct exofs_io_state *ios)
 
        if (sync) {
                wait_for_completion(&wait);
-               ret = exofs_check_io(ios, NULL);
+               ret = ore_check_io(ios, NULL);
        }
        return ret;
 }
@@ -214,7 +198,7 @@ static void _clear_bio(struct bio *bio)
        }
 }
 
-int exofs_check_io(struct exofs_io_state *ios, u64 *resid)
+int ore_check_io(struct ore_io_state *ios, u64 *resid)
 {
        enum osd_err_priority acumulated_osd_err = 0;
        int acumulated_lin_err = 0;
@@ -235,7 +219,7 @@ int exofs_check_io(struct exofs_io_state *ios, u64 *resid)
                if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) {
                        /* start read offset passed endof file */
                        _clear_bio(ios->per_dev[i].bio);
-                       EXOFS_DBGMSG("start read offset passed end of file "
+                       ORE_DBGMSG("start read offset passed end of file "
                                "offset=0x%llx, length=0x%llx\n",
                                _LLU(ios->per_dev[i].offset),
                                _LLU(ios->per_dev[i].length));
@@ -259,6 +243,7 @@ int exofs_check_io(struct exofs_io_state *ios, u64 *resid)
 
        return acumulated_lin_err;
 }
+EXPORT_SYMBOL(ore_check_io);
 
 /*
  * L - logical offset into the file
@@ -305,20 +290,21 @@ int exofs_check_io(struct exofs_io_state *ios, u64 *resid)
 struct _striping_info {
        u64 obj_offset;
        u64 group_length;
+       u64 M; /* for truncate */
        unsigned dev;
        unsigned unit_off;
 };
 
-static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset,
+static void _calc_stripe_info(struct ore_layout *layout, u64 file_offset,
                              struct _striping_info *si)
 {
-       u32     stripe_unit = ios->layout->stripe_unit;
-       u32     group_width = ios->layout->group_width;
-       u64     group_depth = ios->layout->group_depth;
+       u32     stripe_unit = layout->stripe_unit;
+       u32     group_width = layout->group_width;
+       u64     group_depth = layout->group_depth;
 
        u32     U = stripe_unit * group_width;
        u64     T = U * group_depth;
-       u64     S = T * ios->layout->group_count;
+       u64     S = T * layout->group_count;
        u64     M = div64_u64(file_offset, S);
 
        /*
@@ -333,7 +319,7 @@ static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset,
 
        /* "H - (N * U)" is just "H % U" so it's bound to u32 */
        si->dev = (u32)(H - (N * U)) / stripe_unit + G * group_width;
-       si->dev *= ios->layout->mirrors_p1;
+       si->dev *= layout->mirrors_p1;
 
        div_u64_rem(file_offset, stripe_unit, &si->unit_off);
 
@@ -341,15 +327,16 @@ static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset,
                                  (M * group_depth * stripe_unit);
 
        si->group_length = T - H;
+       si->M = M;
 }
 
-static int _add_stripe_unit(struct exofs_io_state *ios,  unsigned *cur_pg,
-               unsigned pgbase, struct exofs_per_dev_state *per_dev,
+static int _add_stripe_unit(struct ore_io_state *ios,  unsigned *cur_pg,
+               unsigned pgbase, struct ore_per_dev_state *per_dev,
                int cur_len)
 {
        unsigned pg = *cur_pg;
        struct request_queue *q =
-                       osd_request_queue(exofs_ios_od(ios, per_dev->dev));
+                       osd_request_queue(_ios_od(ios, per_dev->dev));
 
        per_dev->length += cur_len;
 
@@ -361,7 +348,7 @@ static int _add_stripe_unit(struct exofs_io_state *ios,  unsigned *cur_pg,
 
                per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size);
                if (unlikely(!per_dev->bio)) {
-                       EXOFS_DBGMSG("Failed to allocate BIO size=%u\n",
+                       ORE_DBGMSG("Failed to allocate BIO size=%u\n",
                                     bio_size);
                        return -ENOMEM;
                }
@@ -387,7 +374,7 @@ static int _add_stripe_unit(struct exofs_io_state *ios,  unsigned *cur_pg,
        return 0;
 }
 
-static int _prepare_one_group(struct exofs_io_state *ios, u64 length,
+static int _prepare_one_group(struct ore_io_state *ios, u64 length,
                              struct _striping_info *si)
 {
        unsigned stripe_unit = ios->layout->stripe_unit;
@@ -400,7 +387,7 @@ static int _prepare_one_group(struct exofs_io_state *ios, u64 length,
        int ret = 0;
 
        while (length) {
-               struct exofs_per_dev_state *per_dev = &ios->per_dev[dev];
+               struct ore_per_dev_state *per_dev = &ios->per_dev[dev];
                unsigned cur_len, page_off = 0;
 
                if (!per_dev->length) {
@@ -443,7 +430,7 @@ out:
        return ret;
 }
 
-static int _prepare_for_striping(struct exofs_io_state *ios)
+static int _prepare_for_striping(struct ore_io_state *ios)
 {
        u64 length = ios->length;
        u64 offset = ios->offset;
@@ -452,9 +439,9 @@ static int _prepare_for_striping(struct exofs_io_state *ios)
 
        if (!ios->pages) {
                if (ios->kern_buff) {
-                       struct exofs_per_dev_state *per_dev = &ios->per_dev[0];
+                       struct ore_per_dev_state *per_dev = &ios->per_dev[0];
 
-                       _calc_stripe_info(ios, ios->offset, &si);
+                       _calc_stripe_info(ios->layout, ios->offset, &si);
                        per_dev->offset = si.obj_offset;
                        per_dev->dev = si.dev;
 
@@ -468,7 +455,7 @@ static int _prepare_for_striping(struct exofs_io_state *ios)
        }
 
        while (length) {
-               _calc_stripe_info(ios, offset, &si);
+               _calc_stripe_info(ios->layout, offset, &si);
 
                if (length < si.group_length)
                        si.group_length = length;
@@ -485,57 +472,59 @@ out:
        return ret;
 }
 
-int exofs_sbi_create(struct exofs_io_state *ios)
+int ore_create(struct ore_io_state *ios)
 {
        int i, ret;
 
-       for (i = 0; i < ios->layout->s_numdevs; i++) {
+       for (i = 0; i < ios->comps->numdevs; i++) {
                struct osd_request *or;
 
-               or = osd_start_request(exofs_ios_od(ios, i), GFP_KERNEL);
+               or = osd_start_request(_ios_od(ios, i), GFP_KERNEL);
                if (unlikely(!or)) {
-                       EXOFS_ERR("%s: osd_start_request failed\n", __func__);
+                       ORE_ERR("%s: osd_start_request failed\n", __func__);
                        ret = -ENOMEM;
                        goto out;
                }
                ios->per_dev[i].or = or;
                ios->numdevs++;
 
-               osd_req_create_object(or, &ios->obj);
+               osd_req_create_object(or, _ios_obj(ios, i));
        }
-       ret = exofs_io_execute(ios);
+       ret = ore_io_execute(ios);
 
 out:
        return ret;
 }
+EXPORT_SYMBOL(ore_create);
 
-int exofs_sbi_remove(struct exofs_io_state *ios)
+int ore_remove(struct ore_io_state *ios)
 {
        int i, ret;
 
-       for (i = 0; i < ios->layout->s_numdevs; i++) {
+       for (i = 0; i < ios->comps->numdevs; i++) {
                struct osd_request *or;
 
-               or = osd_start_request(exofs_ios_od(ios, i), GFP_KERNEL);
+               or = osd_start_request(_ios_od(ios, i), GFP_KERNEL);
                if (unlikely(!or)) {
-                       EXOFS_ERR("%s: osd_start_request failed\n", __func__);
+                       ORE_ERR("%s: osd_start_request failed\n", __func__);
                        ret = -ENOMEM;
                        goto out;
                }
                ios->per_dev[i].or = or;
                ios->numdevs++;
 
-               osd_req_remove_object(or, &ios->obj);
+               osd_req_remove_object(or, _ios_obj(ios, i));
        }
-       ret = exofs_io_execute(ios);
+       ret = ore_io_execute(ios);
 
 out:
        return ret;
 }
+EXPORT_SYMBOL(ore_remove);
 
-static int _sbi_write_mirror(struct exofs_io_state *ios, int cur_comp)
+static int _write_mirror(struct ore_io_state *ios, int cur_comp)
 {
-       struct exofs_per_dev_state *master_dev = &ios->per_dev[cur_comp];
+       struct ore_per_dev_state *master_dev = &ios->per_dev[cur_comp];
        unsigned dev = ios->per_dev[cur_comp].dev;
        unsigned last_comp = cur_comp + ios->layout->mirrors_p1;
        int ret = 0;
@@ -544,12 +533,12 @@ static int _sbi_write_mirror(struct exofs_io_state *ios, int cur_comp)
                return 0; /* Just an empty slot */
 
        for (; cur_comp < last_comp; ++cur_comp, ++dev) {
-               struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
+               struct ore_per_dev_state *per_dev = &ios->per_dev[cur_comp];
                struct osd_request *or;
 
-               or = osd_start_request(exofs_ios_od(ios, dev), GFP_KERNEL);
+               or = osd_start_request(_ios_od(ios, dev), GFP_KERNEL);
                if (unlikely(!or)) {
-                       EXOFS_ERR("%s: osd_start_request failed\n", __func__);
+                       ORE_ERR("%s: osd_start_request failed\n", __func__);
                        ret = -ENOMEM;
                        goto out;
                }
@@ -563,7 +552,7 @@ static int _sbi_write_mirror(struct exofs_io_state *ios, int cur_comp)
                                bio = bio_kmalloc(GFP_KERNEL,
                                                  master_dev->bio->bi_max_vecs);
                                if (unlikely(!bio)) {
-                                       EXOFS_DBGMSG(
+                                       ORE_DBGMSG(
                                              "Failed to allocate BIO size=%u\n",
                                              master_dev->bio->bi_max_vecs);
                                        ret = -ENOMEM;
@@ -582,25 +571,29 @@ static int _sbi_write_mirror(struct exofs_io_state *ios, int cur_comp)
                                bio->bi_rw |= REQ_WRITE;
                        }
 
-                       osd_req_write(or, &ios->obj, per_dev->offset, bio,
-                                     per_dev->length);
-                       EXOFS_DBGMSG("write(0x%llx) offset=0x%llx "
+                       osd_req_write(or, _ios_obj(ios, dev), per_dev->offset,
+                                     bio, per_dev->length);
+                       ORE_DBGMSG("write(0x%llx) offset=0x%llx "
                                      "length=0x%llx dev=%d\n",
-                                    _LLU(ios->obj.id), _LLU(per_dev->offset),
+                                    _LLU(_ios_obj(ios, dev)->id),
+                                    _LLU(per_dev->offset),
                                     _LLU(per_dev->length), dev);
                } else if (ios->kern_buff) {
-                       ret = osd_req_write_kern(or, &ios->obj, per_dev->offset,
-                                          ios->kern_buff, ios->length);
+                       ret = osd_req_write_kern(or, _ios_obj(ios, dev),
+                                                per_dev->offset,
+                                                ios->kern_buff, ios->length);
                        if (unlikely(ret))
                                goto out;
-                       EXOFS_DBGMSG2("write_kern(0x%llx) offset=0x%llx "
+                       ORE_DBGMSG2("write_kern(0x%llx) offset=0x%llx "
                                      "length=0x%llx dev=%d\n",
-                                    _LLU(ios->obj.id), _LLU(per_dev->offset),
+                                    _LLU(_ios_obj(ios, dev)->id),
+                                    _LLU(per_dev->offset),
                                     _LLU(ios->length), dev);
                } else {
-                       osd_req_set_attributes(or, &ios->obj);
-                       EXOFS_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n",
-                                    _LLU(ios->obj.id), ios->out_attr_len, dev);
+                       osd_req_set_attributes(or, _ios_obj(ios, dev));
+                       ORE_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n",
+                                    _LLU(_ios_obj(ios, dev)->id),
+                                    ios->out_attr_len, dev);
                }
 
                if (ios->out_attr)
@@ -616,7 +609,7 @@ out:
        return ret;
 }
 
-int exofs_sbi_write(struct exofs_io_state *ios)
+int ore_write(struct ore_io_state *ios)
 {
        int i;
        int ret;
@@ -626,52 +619,55 @@ int exofs_sbi_write(struct exofs_io_state *ios)
                return ret;
 
        for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) {
-               ret = _sbi_write_mirror(ios, i);
+               ret = _write_mirror(ios, i);
                if (unlikely(ret))
                        return ret;
        }
 
-       ret = exofs_io_execute(ios);
+       ret = ore_io_execute(ios);
        return ret;
 }
+EXPORT_SYMBOL(ore_write);
 
-static int _sbi_read_mirror(struct exofs_io_state *ios, unsigned cur_comp)
+static int _read_mirror(struct ore_io_state *ios, unsigned cur_comp)
 {
        struct osd_request *or;
-       struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
-       unsigned first_dev = (unsigned)ios->obj.id;
+       struct ore_per_dev_state *per_dev = &ios->per_dev[cur_comp];
+       struct osd_obj_id *obj = _ios_obj(ios, cur_comp);
+       unsigned first_dev = (unsigned)obj->id;
 
        if (ios->pages && !per_dev->length)
                return 0; /* Just an empty slot */
 
        first_dev = per_dev->dev + first_dev % ios->layout->mirrors_p1;
-       or = osd_start_request(exofs_ios_od(ios, first_dev), GFP_KERNEL);
+       or = osd_start_request(_ios_od(ios, first_dev), GFP_KERNEL);
        if (unlikely(!or)) {
-               EXOFS_ERR("%s: osd_start_request failed\n", __func__);
+               ORE_ERR("%s: osd_start_request failed\n", __func__);
                return -ENOMEM;
        }
        per_dev->or = or;
 
        if (ios->pages) {
-               osd_req_read(or, &ios->obj, per_dev->offset,
+               osd_req_read(or, obj, per_dev->offset,
                                per_dev->bio, per_dev->length);
-               EXOFS_DBGMSG("read(0x%llx) offset=0x%llx length=0x%llx"
-                            " dev=%d\n", _LLU(ios->obj.id),
+               ORE_DBGMSG("read(0x%llx) offset=0x%llx length=0x%llx"
+                            " dev=%d\n", _LLU(obj->id),
                             _LLU(per_dev->offset), _LLU(per_dev->length),
                             first_dev);
        } else if (ios->kern_buff) {
-               int ret = osd_req_read_kern(or, &ios->obj, per_dev->offset,
+               int ret = osd_req_read_kern(or, obj, per_dev->offset,
                                            ios->kern_buff, ios->length);
-               EXOFS_DBGMSG2("read_kern(0x%llx) offset=0x%llx "
+               ORE_DBGMSG2("read_kern(0x%llx) offset=0x%llx "
                              "length=0x%llx dev=%d ret=>%d\n",
-                             _LLU(ios->obj.id), _LLU(per_dev->offset),
+                             _LLU(obj->id), _LLU(per_dev->offset),
                              _LLU(ios->length), first_dev, ret);
                if (unlikely(ret))
                        return ret;
        } else {
-               osd_req_get_attributes(or, &ios->obj);
-               EXOFS_DBGMSG2("obj(0x%llx) get_attributes=%d dev=%d\n",
-                             _LLU(ios->obj.id), ios->in_attr_len, first_dev);
+               osd_req_get_attributes(or, obj);
+               ORE_DBGMSG2("obj(0x%llx) get_attributes=%d dev=%d\n",
+                             _LLU(obj->id),
+                             ios->in_attr_len, first_dev);
        }
        if (ios->out_attr)
                osd_req_add_set_attr_list(or, ios->out_attr, ios->out_attr_len);
@@ -682,7 +678,7 @@ static int _sbi_read_mirror(struct exofs_io_state *ios, unsigned cur_comp)
        return 0;
 }
 
-int exofs_sbi_read(struct exofs_io_state *ios)
+int ore_read(struct ore_io_state *ios)
 {
        int i;
        int ret;
@@ -692,16 +688,17 @@ int exofs_sbi_read(struct exofs_io_state *ios)
                return ret;
 
        for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) {
-               ret = _sbi_read_mirror(ios, i);
+               ret = _read_mirror(ios, i);
                if (unlikely(ret))
                        return ret;
        }
 
-       ret = exofs_io_execute(ios);
+       ret = ore_io_execute(ios);
        return ret;
 }
+EXPORT_SYMBOL(ore_read);
 
-int extract_attr_from_ios(struct exofs_io_state *ios, struct osd_attr *attr)
+int extract_attr_from_ios(struct ore_io_state *ios, struct osd_attr *attr)
 {
        struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */
        void *iter = NULL;
@@ -721,83 +718,118 @@ int extract_attr_from_ios(struct exofs_io_state *ios, struct osd_attr *attr)
 
        return -EIO;
 }
+EXPORT_SYMBOL(extract_attr_from_ios);
 
-static int _truncate_mirrors(struct exofs_io_state *ios, unsigned cur_comp,
+static int _truncate_mirrors(struct ore_io_state *ios, unsigned cur_comp,
                             struct osd_attr *attr)
 {
        int last_comp = cur_comp + ios->layout->mirrors_p1;
 
        for (; cur_comp < last_comp; ++cur_comp) {
-               struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
+               struct ore_per_dev_state *per_dev = &ios->per_dev[cur_comp];
                struct osd_request *or;
 
-               or = osd_start_request(exofs_ios_od(ios, cur_comp), GFP_KERNEL);
+               or = osd_start_request(_ios_od(ios, cur_comp), GFP_KERNEL);
                if (unlikely(!or)) {
-                       EXOFS_ERR("%s: osd_start_request failed\n", __func__);
+                       ORE_ERR("%s: osd_start_request failed\n", __func__);
                        return -ENOMEM;
                }
                per_dev->or = or;
 
-               osd_req_set_attributes(or, &ios->obj);
+               osd_req_set_attributes(or, _ios_obj(ios, cur_comp));
                osd_req_add_set_attr_list(or, attr, 1);
        }
 
        return 0;
 }
 
-int exofs_oi_truncate(struct exofs_i_info *oi, u64 size)
+struct _trunc_info {
+       struct _striping_info si;
+       u64 prev_group_obj_off;
+       u64 next_group_obj_off;
+
+       unsigned first_group_dev;
+       unsigned nex_group_dev;
+       unsigned max_devs;
+};
+
+void _calc_trunk_info(struct ore_layout *layout, u64 file_offset,
+                      struct _trunc_info *ti)
+{
+       unsigned stripe_unit = layout->stripe_unit;
+
+       _calc_stripe_info(layout, file_offset, &ti->si);
+
+       ti->prev_group_obj_off = ti->si.M * stripe_unit;
+       ti->next_group_obj_off = ti->si.M ? (ti->si.M - 1) * stripe_unit : 0;
+
+       ti->first_group_dev = ti->si.dev - (ti->si.dev % layout->group_width);
+       ti->nex_group_dev = ti->first_group_dev + layout->group_width;
+       ti->max_devs = layout->group_width * layout->group_count;
+}
+
+int ore_truncate(struct ore_layout *layout, struct ore_components *comps,
+                  u64 size)
 {
-       struct exofs_sb_info *sbi = oi->vfs_inode.i_sb->s_fs_info;
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        struct exofs_trunc_attr {
                struct osd_attr attr;
                __be64 newsize;
        } *size_attrs;
-       struct _striping_info si;
+       struct _trunc_info ti;
        int i, ret;
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(layout, comps, &ios);
        if (unlikely(ret))
                return ret;
 
-       size_attrs = kcalloc(ios->layout->group_width, sizeof(*size_attrs),
+       _calc_trunk_info(ios->layout, size, &ti);
+
+       size_attrs = kcalloc(ti.max_devs, sizeof(*size_attrs),
                             GFP_KERNEL);
        if (unlikely(!size_attrs)) {
                ret = -ENOMEM;
                goto out;
        }
 
-       ios->obj.id = exofs_oi_objno(oi);
-       ios->cred = oi->i_cred;
+       ios->numdevs = ios->comps->numdevs;
 
-       ios->numdevs = ios->layout->s_numdevs;
-       _calc_stripe_info(ios, size, &si);
-
-       for (i = 0; i < ios->layout->group_width; ++i) {
+       for (i = 0; i < ti.max_devs; ++i) {
                struct exofs_trunc_attr *size_attr = &size_attrs[i];
                u64 obj_size;
 
-               if (i < si.dev)
-                       obj_size = si.obj_offset +
-                                       ios->layout->stripe_unit - si.unit_off;
-               else if (i == si.dev)
-                       obj_size = si.obj_offset;
-               else /* i > si.dev */
-                       obj_size = si.obj_offset - si.unit_off;
+               if (i < ti.first_group_dev)
+                       obj_size = ti.prev_group_obj_off;
+               else if (i >= ti.nex_group_dev)
+                       obj_size = ti.next_group_obj_off;
+               else if (i < ti.si.dev) /* dev within this group */
+                       obj_size = ti.si.obj_offset +
+                                     ios->layout->stripe_unit - ti.si.unit_off;
+               else if (i == ti.si.dev)
+                       obj_size = ti.si.obj_offset;
+               else /* i > ti.dev */
+                       obj_size = ti.si.obj_offset - ti.si.unit_off;
 
                size_attr->newsize = cpu_to_be64(obj_size);
                size_attr->attr = g_attr_logical_length;
                size_attr->attr.val_ptr = &size_attr->newsize;
 
+               ORE_DBGMSG("trunc(0x%llx) obj_offset=0x%llx dev=%d\n",
+                            _LLU(comps->comps->obj.id), _LLU(obj_size), i);
                ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1,
                                        &size_attr->attr);
                if (unlikely(ret))
                        goto out;
        }
-       ret = exofs_io_execute(ios);
+       ret = ore_io_execute(ios);
 
 out:
        kfree(size_attrs);
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
        return ret;
 }
+EXPORT_SYMBOL(ore_truncate);
+
+const struct osd_attr g_attr_logical_length = ATTR_DEF(
+       OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);
+EXPORT_SYMBOL(g_attr_logical_length);
diff --git a/fs/exofs/pnfs.h b/fs/exofs/pnfs.h
deleted file mode 100644 (file)
index c52e988..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2008, 2009
- * Boaz Harrosh <bharrosh@panasas.com>
- *
- * This file is part of exofs.
- *
- * exofs 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.
- *
- */
-
-/* FIXME: Remove this file once pnfs hits mainline */
-
-#ifndef __EXOFS_PNFS_H__
-#define __EXOFS_PNFS_H__
-
-#if ! defined(__PNFS_OSD_XDR_H__)
-
-enum pnfs_iomode {
-       IOMODE_READ = 1,
-       IOMODE_RW = 2,
-       IOMODE_ANY = 3,
-};
-
-/* Layout Structure */
-enum pnfs_osd_raid_algorithm4 {
-       PNFS_OSD_RAID_0         = 1,
-       PNFS_OSD_RAID_4         = 2,
-       PNFS_OSD_RAID_5         = 3,
-       PNFS_OSD_RAID_PQ        = 4     /* Reed-Solomon P+Q */
-};
-
-struct pnfs_osd_data_map {
-       u32     odm_num_comps;
-       u64     odm_stripe_unit;
-       u32     odm_group_width;
-       u32     odm_group_depth;
-       u32     odm_mirror_cnt;
-       u32     odm_raid_algorithm;
-};
-
-#endif /* ! defined(__PNFS_OSD_XDR_H__) */
-
-#endif /* __EXOFS_PNFS_H__ */
index c57bedd..2748940 100644 (file)
@@ -40,6 +40,8 @@
 
 #include "exofs.h"
 
+#define EXOFS_DBGMSG2(M...) do {} while (0)
+
 /******************************************************************************
  * MOUNT OPTIONS
  *****************************************************************************/
@@ -208,10 +210,48 @@ static void destroy_inodecache(void)
 }
 
 /******************************************************************************
- * SUPERBLOCK FUNCTIONS
+ * Some osd helpers
  *****************************************************************************/
-static const struct super_operations exofs_sops;
-static const struct export_operations exofs_export_ops;
+void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], const struct osd_obj_id *obj)
+{
+       osd_sec_init_nosec_doall_caps(cred_a, obj, false, true);
+}
+
+static int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj,
+                   u64 offset, void *p, unsigned length)
+{
+       struct osd_request *or = osd_start_request(od, GFP_KERNEL);
+/*     struct osd_sense_info osi = {.key = 0};*/
+       int ret;
+
+       if (unlikely(!or)) {
+               EXOFS_DBGMSG("%s: osd_start_request failed.\n", __func__);
+               return -ENOMEM;
+       }
+       ret = osd_req_read_kern(or, obj, offset, p, length);
+       if (unlikely(ret)) {
+               EXOFS_DBGMSG("%s: osd_req_read_kern failed.\n", __func__);
+               goto out;
+       }
+
+       ret = osd_finalize_request(or, 0, cred, NULL);
+       if (unlikely(ret)) {
+               EXOFS_DBGMSG("Failed to osd_finalize_request() => %d\n", ret);
+               goto out;
+       }
+
+       ret = osd_execute_request(or);
+       if (unlikely(ret))
+               EXOFS_DBGMSG("osd_execute_request() => %d\n", ret);
+       /* osd_req_decode_sense(or, ret); */
+
+out:
+       osd_end_request(or);
+       EXOFS_DBGMSG2("read_kern(0x%llx) offset=0x%llx "
+                     "length=0x%llx dev=%p ret=>%d\n",
+                     _LLU(obj->id), _LLU(offset), _LLU(length), od, ret);
+       return ret;
+}
 
 static const struct osd_attr g_attr_sb_stats = ATTR_DEF(
        EXOFS_APAGE_SB_DATA,
@@ -223,21 +263,19 @@ static int __sbi_read_stats(struct exofs_sb_info *sbi)
        struct osd_attr attrs[] = {
                [0] = g_attr_sb_stats,
        };
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        int ret;
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &sbi->comps, &ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__);
+               EXOFS_ERR("%s: ore_get_io_state failed.\n", __func__);
                return ret;
        }
 
-       ios->cred = sbi->s_cred;
-
        ios->in_attr = attrs;
        ios->in_attr_len = ARRAY_SIZE(attrs);
 
-       ret = exofs_sbi_read(ios);
+       ret = ore_read(ios);
        if (unlikely(ret)) {
                EXOFS_ERR("Error reading super_block stats => %d\n", ret);
                goto out;
@@ -264,13 +302,13 @@ static int __sbi_read_stats(struct exofs_sb_info *sbi)
        }
 
 out:
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
        return ret;
 }
 
-static void stats_done(struct exofs_io_state *ios, void *p)
+static void stats_done(struct ore_io_state *ios, void *p)
 {
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
        /* Good thanks nothing to do anymore */
 }
 
@@ -280,12 +318,12 @@ int exofs_sbi_write_stats(struct exofs_sb_info *sbi)
        struct osd_attr attrs[] = {
                [0] = g_attr_sb_stats,
        };
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        int ret;
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &sbi->comps, &ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__);
+               EXOFS_ERR("%s: ore_get_io_state failed.\n", __func__);
                return ret;
        }
 
@@ -293,21 +331,27 @@ int exofs_sbi_write_stats(struct exofs_sb_info *sbi)
        sbi->s_ess.s_numfiles = cpu_to_le64(sbi->s_numfiles);
        attrs[0].val_ptr = &sbi->s_ess;
 
-       ios->cred = sbi->s_cred;
+
        ios->done = stats_done;
        ios->private = sbi;
        ios->out_attr = attrs;
        ios->out_attr_len = ARRAY_SIZE(attrs);
 
-       ret = exofs_sbi_write(ios);
+       ret = ore_write(ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("%s: exofs_sbi_write failed.\n", __func__);
-               exofs_put_io_state(ios);
+               EXOFS_ERR("%s: ore_write failed.\n", __func__);
+               ore_put_io_state(ios);
        }
 
        return ret;
 }
 
+/******************************************************************************
+ * SUPERBLOCK FUNCTIONS
+ *****************************************************************************/
+static const struct super_operations exofs_sops;
+static const struct export_operations exofs_export_ops;
+
 /*
  * Write the superblock to the OSD
  */
@@ -315,7 +359,9 @@ int exofs_sync_fs(struct super_block *sb, int wait)
 {
        struct exofs_sb_info *sbi;
        struct exofs_fscb *fscb;
-       struct exofs_io_state *ios;
+       struct ore_comp one_comp;
+       struct ore_components comps;
+       struct ore_io_state *ios;
        int ret = -ENOMEM;
 
        fscb = kmalloc(sizeof(*fscb), GFP_KERNEL);
@@ -331,7 +377,10 @@ int exofs_sync_fs(struct super_block *sb, int wait)
         * version). Otherwise the exofs_fscb is read-only from mkfs time. All
         * the writeable info is set in exofs_sbi_write_stats() above.
         */
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+
+       exofs_init_comps(&comps, &one_comp, sbi, EXOFS_SUPER_ID);
+
+       ret = ore_get_io_state(&sbi->layout, &comps, &ios);
        if (unlikely(ret))
                goto out;
 
@@ -345,14 +394,12 @@ int exofs_sync_fs(struct super_block *sb, int wait)
        fscb->s_newfs = 0;
        fscb->s_version = EXOFS_FSCB_VER;
 
-       ios->obj.id = EXOFS_SUPER_ID;
        ios->offset = 0;
        ios->kern_buff = fscb;
-       ios->cred = sbi->s_cred;
 
-       ret = exofs_sbi_write(ios);
+       ret = ore_write(ios);
        if (unlikely(ret))
-               EXOFS_ERR("%s: exofs_sbi_write failed.\n", __func__);
+               EXOFS_ERR("%s: ore_write failed.\n", __func__);
        else
                sb->s_dirt = 0;
 
@@ -360,7 +407,7 @@ int exofs_sync_fs(struct super_block *sb, int wait)
        unlock_super(sb);
 out:
        EXOFS_DBGMSG("s_nextid=0x%llx ret=%d\n", _LLU(sbi->s_nextid), ret);
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
        kfree(fscb);
        return ret;
 }
@@ -384,15 +431,17 @@ static void _exofs_print_device(const char *msg, const char *dev_path,
 
 void exofs_free_sbi(struct exofs_sb_info *sbi)
 {
-       while (sbi->layout.s_numdevs) {
-               int i = --sbi->layout.s_numdevs;
-               struct osd_dev *od = sbi->layout.s_ods[i];
+       while (sbi->comps.numdevs) {
+               int i = --sbi->comps.numdevs;
+               struct osd_dev *od = sbi->comps.ods[i];
 
                if (od) {
-                       sbi->layout.s_ods[i] = NULL;
+                       sbi->comps.ods[i] = NULL;
                        osduld_put_device(od);
                }
        }
+       if (sbi->comps.ods != sbi->_min_one_dev)
+               kfree(sbi->comps.ods);
        kfree(sbi);
 }
 
@@ -419,8 +468,8 @@ static void exofs_put_super(struct super_block *sb)
                                  msecs_to_jiffies(100));
        }
 
-       _exofs_print_device("Unmounting", NULL, sbi->layout.s_ods[0],
-                           sbi->layout.s_pid);
+       _exofs_print_device("Unmounting", NULL, sbi->comps.ods[0],
+                           sbi->one_comp.obj.partition);
 
        bdi_destroy(&sbi->bdi);
        exofs_free_sbi(sbi);
@@ -501,10 +550,19 @@ static int _read_and_match_data_map(struct exofs_sb_info *sbi, unsigned numdevs,
                return -EINVAL;
        }
 
+       EXOFS_DBGMSG("exofs: layout: "
+               "num_comps=%u stripe_unit=0x%x group_width=%u "
+               "group_depth=0x%llx mirrors_p1=%u raid_algorithm=%u\n",
+               numdevs,
+               sbi->layout.stripe_unit,
+               sbi->layout.group_width,
+               _LLU(sbi->layout.group_depth),
+               sbi->layout.mirrors_p1,
+               sbi->data_map.odm_raid_algorithm);
        return 0;
 }
 
-static unsigned __ra_pages(struct exofs_layout *layout)
+static unsigned __ra_pages(struct ore_layout *layout)
 {
        const unsigned _MIN_RA = 32; /* min 128K read-ahead */
        unsigned ra_pages = layout->group_width * layout->stripe_unit /
@@ -547,13 +605,11 @@ static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev,
        return !(odi->systemid_len || odi->osdname_len);
 }
 
-static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
+static int exofs_read_lookup_dev_table(struct exofs_sb_info *sbi,
+                                      struct osd_dev *fscb_od,
                                       unsigned table_count)
 {
-       struct exofs_sb_info *sbi = *psbi;
-       struct osd_dev *fscb_od;
-       struct osd_obj_id obj = {.partition = sbi->layout.s_pid,
-                                .id = EXOFS_DEVTABLE_ID};
+       struct ore_comp comp;
        struct exofs_device_table *dt;
        unsigned table_bytes = table_count * sizeof(dt->dt_dev_table[0]) +
                                             sizeof(*dt);
@@ -567,10 +623,14 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
                return -ENOMEM;
        }
 
-       fscb_od = sbi->layout.s_ods[0];
-       sbi->layout.s_ods[0] = NULL;
-       sbi->layout.s_numdevs = 0;
-       ret = exofs_read_kern(fscb_od, sbi->s_cred, &obj, 0, dt, table_bytes);
+       sbi->comps.numdevs = 0;
+
+       comp.obj.partition = sbi->one_comp.obj.partition;
+       comp.obj.id = EXOFS_DEVTABLE_ID;
+       exofs_make_credential(comp.cred, &comp.obj);
+
+       ret = exofs_read_kern(fscb_od, comp.cred, &comp.obj, 0, dt,
+                             table_bytes);
        if (unlikely(ret)) {
                EXOFS_ERR("ERROR: reading device table\n");
                goto out;
@@ -588,16 +648,18 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
                goto out;
 
        if (likely(numdevs > 1)) {
-               unsigned size = numdevs * sizeof(sbi->layout.s_ods[0]);
+               unsigned size = numdevs * sizeof(sbi->comps.ods[0]);
 
-               sbi = krealloc(sbi, sizeof(*sbi) + size, GFP_KERNEL);
-               if (unlikely(!sbi)) {
+               /* Twice bigger table: See exofs_init_comps() and below
+                * comment
+                */
+               sbi->comps.ods = kzalloc(size + size - 1, GFP_KERNEL);
+               if (unlikely(!sbi->comps.ods)) {
+                       EXOFS_ERR("ERROR: faild allocating Device array[%d]\n",
+                                 numdevs);
                        ret = -ENOMEM;
                        goto out;
                }
-               memset(&sbi->layout.s_ods[1], 0,
-                      size - sizeof(sbi->layout.s_ods[0]));
-               *psbi = sbi;
        }
 
        for (i = 0; i < numdevs; i++) {
@@ -619,8 +681,8 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
                 * line. We always keep them in device-table order.
                 */
                if (fscb_od && osduld_device_same(fscb_od, &odi)) {
-                       sbi->layout.s_ods[i] = fscb_od;
-                       ++sbi->layout.s_numdevs;
+                       sbi->comps.ods[i] = fscb_od;
+                       ++sbi->comps.numdevs;
                        fscb_od = NULL;
                        continue;
                }
@@ -633,13 +695,13 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
                        goto out;
                }
 
-               sbi->layout.s_ods[i] = od;
-               ++sbi->layout.s_numdevs;
+               sbi->comps.ods[i] = od;
+               ++sbi->comps.numdevs;
 
                /* Read the fscb of the other devices to make sure the FS
                 * partition is there.
                 */
-               ret = exofs_read_kern(od, sbi->s_cred, &obj, 0, &fscb,
+               ret = exofs_read_kern(od, comp.cred, &comp.obj, 0, &fscb,
                                      sizeof(fscb));
                if (unlikely(ret)) {
                        EXOFS_ERR("ERROR: Malformed participating device "
@@ -656,13 +718,22 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
 
 out:
        kfree(dt);
-       if (unlikely(!ret && fscb_od)) {
-               EXOFS_ERR(
-                     "ERROR: Bad device-table container device not present\n");
-               osduld_put_device(fscb_od);
-               ret = -EINVAL;
-       }
+       if (likely(!ret)) {
+               unsigned numdevs = sbi->comps.numdevs;
 
+               if (unlikely(fscb_od)) {
+                       EXOFS_ERR("ERROR: Bad device-table container device not present\n");
+                       osduld_put_device(fscb_od);
+                       return -EINVAL;
+               }
+               /* exofs round-robins the device table view according to inode
+                * number. We hold a: twice bigger table hence inodes can point
+                * to any device and have a sequential view of the table
+                * starting at this device. See exofs_init_comps()
+                */
+               for (i = 0; i < numdevs - 1; ++i)
+                       sbi->comps.ods[i + numdevs] = sbi->comps.ods[i];
+       }
        return ret;
 }
 
@@ -676,7 +747,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
        struct exofs_sb_info *sbi;      /*extended info                  */
        struct osd_dev *od;             /* Master device                 */
        struct exofs_fscb fscb;         /*on-disk superblock info        */
-       struct osd_obj_id obj;
+       struct ore_comp comp;
        unsigned table_count;
        int ret;
 
@@ -684,10 +755,6 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
        if (!sbi)
                return -ENOMEM;
 
-       ret = bdi_setup_and_register(&sbi->bdi, "exofs", BDI_CAP_MAP_COPY);
-       if (ret)
-               goto free_bdi;
-
        /* use mount options to fill superblock */
        if (opts->is_osdname) {
                struct osd_dev_info odi = {.systemid_len = 0};
@@ -695,6 +762,8 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
                odi.osdname_len = strlen(opts->dev_name);
                odi.osdname = (u8 *)opts->dev_name;
                od = osduld_info_lookup(&odi);
+               kfree(opts->dev_name);
+               opts->dev_name = NULL;
        } else {
                od = osduld_path_lookup(opts->dev_name);
        }
@@ -709,11 +778,16 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
        sbi->layout.group_width = 1;
        sbi->layout.group_depth = -1;
        sbi->layout.group_count = 1;
-       sbi->layout.s_ods[0] = od;
-       sbi->layout.s_numdevs = 1;
-       sbi->layout.s_pid = opts->pid;
        sbi->s_timeout = opts->timeout;
 
+       sbi->one_comp.obj.partition = opts->pid;
+       sbi->one_comp.obj.id = 0;
+       exofs_make_credential(sbi->one_comp.cred, &sbi->one_comp.obj);
+       sbi->comps.numdevs = 1;
+       sbi->comps.single_comp = EC_SINGLE_COMP;
+       sbi->comps.comps = &sbi->one_comp;
+       sbi->comps.ods = sbi->_min_one_dev;
+
        /* fill in some other data by hand */
        memset(sb->s_id, 0, sizeof(sb->s_id));
        strcpy(sb->s_id, "exofs");
@@ -724,11 +798,11 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_bdev = NULL;
        sb->s_dev = 0;
 
-       obj.partition = sbi->layout.s_pid;
-       obj.id = EXOFS_SUPER_ID;
-       exofs_make_credential(sbi->s_cred, &obj);
+       comp.obj.partition = sbi->one_comp.obj.partition;
+       comp.obj.id = EXOFS_SUPER_ID;
+       exofs_make_credential(comp.cred, &comp.obj);
 
-       ret = exofs_read_kern(od, sbi->s_cred, &obj, 0, &fscb, sizeof(fscb));
+       ret = exofs_read_kern(od, comp.cred, &comp.obj, 0, &fscb, sizeof(fscb));
        if (unlikely(ret))
                goto free_sbi;
 
@@ -757,9 +831,11 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
 
        table_count = le64_to_cpu(fscb.s_dev_table_count);
        if (table_count) {
-               ret = exofs_read_lookup_dev_table(&sbi, table_count);
+               ret = exofs_read_lookup_dev_table(sbi, od, table_count);
                if (unlikely(ret))
                        goto free_sbi;
+       } else {
+               sbi->comps.ods[0] = od;
        }
 
        __sbi_read_stats(sbi);
@@ -793,20 +869,20 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
                goto free_sbi;
        }
 
-       _exofs_print_device("Mounting", opts->dev_name, sbi->layout.s_ods[0],
-                           sbi->layout.s_pid);
-       if (opts->is_osdname)
-               kfree(opts->dev_name);
+       ret = bdi_setup_and_register(&sbi->bdi, "exofs", BDI_CAP_MAP_COPY);
+       if (ret) {
+               EXOFS_DBGMSG("Failed to bdi_setup_and_register\n");
+               goto free_sbi;
+       }
+
+       _exofs_print_device("Mounting", opts->dev_name, sbi->comps.ods[0],
+                           sbi->one_comp.obj.partition);
        return 0;
 
 free_sbi:
-       bdi_destroy(&sbi->bdi);
-free_bdi:
        EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n",
-                 opts->dev_name, sbi->layout.s_pid, ret);
+                 opts->dev_name, sbi->one_comp.obj.partition, ret);
        exofs_free_sbi(sbi);
-       if (opts->is_osdname)
-               kfree(opts->dev_name);
        return ret;
 }
 
@@ -837,7 +913,7 @@ static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct super_block *sb = dentry->d_sb;
        struct exofs_sb_info *sbi = sb->s_fs_info;
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        struct osd_attr attrs[] = {
                ATTR_DEF(OSD_APAGE_PARTITION_QUOTAS,
                        OSD_ATTR_PQ_CAPACITY_QUOTA, sizeof(__be64)),
@@ -846,21 +922,18 @@ static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf)
        };
        uint64_t capacity = ULLONG_MAX;
        uint64_t used = ULLONG_MAX;
-       uint8_t cred_a[OSD_CAP_LEN];
        int ret;
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &sbi->comps, &ios);
        if (ret) {
-               EXOFS_DBGMSG("exofs_get_io_state failed.\n");
+               EXOFS_DBGMSG("ore_get_io_state failed.\n");
                return ret;
        }
 
-       exofs_make_credential(cred_a, &ios->obj);
-       ios->cred = sbi->s_cred;
        ios->in_attr = attrs;
        ios->in_attr_len = ARRAY_SIZE(attrs);
 
-       ret = exofs_sbi_read(ios);
+       ret = ore_read(ios);
        if (unlikely(ret))
                goto out;
 
@@ -889,7 +962,7 @@ static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_namelen = EXOFS_NAME_LEN;
 
 out:
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
        return ret;
 }
 
index 52c0537..35d6a3c 100644 (file)
@@ -194,12 +194,10 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
                case ACL_TYPE_ACCESS:
                        name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
                        if (acl) {
-                               mode_t mode = inode->i_mode;
-                               error = posix_acl_equiv_mode(acl, &mode);
+                               error = posix_acl_equiv_mode(acl, &inode->i_mode);
                                if (error < 0)
                                        return error;
                                else {
-                                       inode->i_mode = mode;
                                        inode->i_ctime = CURRENT_TIME_SEC;
                                        mark_inode_dirty(inode);
                                        if (error == 0)
@@ -253,16 +251,14 @@ ext2_init_acl(struct inode *inode, struct inode *dir)
                        inode->i_mode &= ~current_umask();
        }
        if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-               mode_t mode = inode->i_mode;
                if (S_ISDIR(inode->i_mode)) {
                        error = ext2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
                        if (error)
                                goto cleanup;
                }
-               error = posix_acl_create(&acl, GFP_KERNEL, &mode);
+               error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
                if (error < 0)
                        return error;
-               inode->i_mode = mode;
                if (error > 0) {
                        /* This is an extended ACL */
                        error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
index 5c0a6a4..503bfb0 100644 (file)
@@ -61,7 +61,6 @@ extern int ext2_init_acl (struct inode *, struct inode *);
 #else
 #include <linux/sched.h>
 #define ext2_get_acl   NULL
-#define ext2_get_acl   NULL
 #define ext2_set_acl   NULL
 
 static inline int
index 6c29bf0..3091f62 100644 (file)
@@ -199,12 +199,10 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
                case ACL_TYPE_ACCESS:
                        name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
                        if (acl) {
-                               mode_t mode = inode->i_mode;
-                               error = posix_acl_equiv_mode(acl, &mode);
+                               error = posix_acl_equiv_mode(acl, &inode->i_mode);
                                if (error < 0)
                                        return error;
                                else {
-                                       inode->i_mode = mode;
                                        inode->i_ctime = CURRENT_TIME_SEC;
                                        ext3_mark_inode_dirty(handle, inode);
                                        if (error == 0)
@@ -261,19 +259,16 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
                        inode->i_mode &= ~current_umask();
        }
        if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-               mode_t mode = inode->i_mode;
-
                if (S_ISDIR(inode->i_mode)) {
                        error = ext3_set_acl(handle, inode,
                                             ACL_TYPE_DEFAULT, acl);
                        if (error)
                                goto cleanup;
                }
-               error = posix_acl_create(&acl, GFP_NOFS, &mode);
+               error = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
                if (error < 0)
                        return error;
 
-               inode->i_mode = mode;
                if (error > 0) {
                        /* This is an extended ACL */
                        error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
index 6e18a0b..5571708 100644 (file)
@@ -2209,9 +2209,11 @@ static int ext3_symlink (struct inode * dir,
                /*
                 * For non-fast symlinks, we just allocate inode and put it on
                 * orphan list in the first transaction => we need bitmap,
-                * group descriptor, sb, inode block, quota blocks.
+                * group descriptor, sb, inode block, quota blocks, and
+                * possibly selinux xattr blocks.
                 */
-               credits = 4 + EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb);
+               credits = 4 + EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb) +
+                         EXT3_XATTR_TRANS_BLOCKS;
        } else {
                /*
                 * Fast symlink. We have to add entry to directory
index 0410946..56fd8f8 100644 (file)
@@ -7,7 +7,7 @@ obj-$(CONFIG_EXT4_FS) += ext4.o
 ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
                ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
                ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \
-               mmp.o
+               mmp.o indirect.o
 
 ext4-$(CONFIG_EXT4_FS_XATTR)           += xattr.o xattr_user.o xattr_trusted.o
 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)       += acl.o
index dca2d1d..a5c29bb 100644 (file)
@@ -198,12 +198,10 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type,
        case ACL_TYPE_ACCESS:
                name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
                if (acl) {
-                       mode_t mode = inode->i_mode;
-                       error = posix_acl_equiv_mode(acl, &mode);
+                       error = posix_acl_equiv_mode(acl, &inode->i_mode);
                        if (error < 0)
                                return error;
                        else {
-                               inode->i_mode = mode;
                                inode->i_ctime = ext4_current_time(inode);
                                ext4_mark_inode_dirty(handle, inode);
                                if (error == 0)
@@ -259,19 +257,16 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
                        inode->i_mode &= ~current_umask();
        }
        if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-               mode_t mode = inode->i_mode;
-
                if (S_ISDIR(inode->i_mode)) {
                        error = ext4_set_acl(handle, inode,
                                             ACL_TYPE_DEFAULT, acl);
                        if (error)
                                goto cleanup;
                }
-               error = posix_acl_create(&acl, GFP_NOFS, &mode);
+               error = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
                if (error < 0)
                        return error;
 
-               inode->i_mode = mode;
                if (error > 0) {
                        /* This is an extended ACL */
                        error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
index 264f694..f8224ad 100644 (file)
@@ -620,3 +620,51 @@ unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
 
 }
 
+/**
+ *     ext4_inode_to_goal_block - return a hint for block allocation
+ *     @inode: inode for block allocation
+ *
+ *     Return the ideal location to start allocating blocks for a
+ *     newly created inode.
+ */
+ext4_fsblk_t ext4_inode_to_goal_block(struct inode *inode)
+{
+       struct ext4_inode_info *ei = EXT4_I(inode);
+       ext4_group_t block_group;
+       ext4_grpblk_t colour;
+       int flex_size = ext4_flex_bg_size(EXT4_SB(inode->i_sb));
+       ext4_fsblk_t bg_start;
+       ext4_fsblk_t last_block;
+
+       block_group = ei->i_block_group;
+       if (flex_size >= EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME) {
+               /*
+                * If there are at least EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME
+                * block groups per flexgroup, reserve the first block
+                * group for directories and special files.  Regular
+                * files will start at the second block group.  This
+                * tends to speed up directory access and improves
+                * fsck times.
+                */
+               block_group &= ~(flex_size-1);
+               if (S_ISREG(inode->i_mode))
+                       block_group++;
+       }
+       bg_start = ext4_group_first_block_no(inode->i_sb, block_group);
+       last_block = ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es) - 1;
+
+       /*
+        * If we are doing delayed allocation, we don't need take
+        * colour into account.
+        */
+       if (test_opt(inode->i_sb, DELALLOC))
+               return bg_start;
+
+       if (bg_start + EXT4_BLOCKS_PER_GROUP(inode->i_sb) <= last_block)
+               colour = (current->pid % 16) *
+                       (EXT4_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+       else
+               colour = (current->pid % 16) * ((last_block - bg_start) / 16);
+       return bg_start + colour;
+}
+
index fac90f3..8efb2f0 100644 (file)
@@ -246,3 +246,24 @@ int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk,
        return 1;
 }
 
+int ext4_check_blockref(const char *function, unsigned int line,
+                       struct inode *inode, __le32 *p, unsigned int max)
+{
+       struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+       __le32 *bref = p;
+       unsigned int blk;
+
+       while (bref < p+max) {
+               blk = le32_to_cpu(*bref++);
+               if (blk &&
+                   unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
+                                                   blk, 1))) {
+                       es->s_last_error_block = cpu_to_le64(blk);
+                       ext4_error_inode(inode, function, line, blk,
+                                        "invalid block");
+                       return -EIO;
+               }
+       }
+       return 0;
+}
+
index fa44df8..e717dfd 100644 (file)
@@ -526,6 +526,7 @@ struct ext4_new_group_data {
 #define EXT4_FREE_BLOCKS_METADATA      0x0001
 #define EXT4_FREE_BLOCKS_FORGET                0x0002
 #define EXT4_FREE_BLOCKS_VALIDATED     0x0004
+#define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE        0x0008
 
 /*
  * ioctl commands
@@ -939,6 +940,8 @@ struct ext4_inode_info {
 #define ext4_find_next_zero_bit                find_next_zero_bit_le
 #define ext4_find_next_bit             find_next_bit_le
 
+extern void ext4_set_bits(void *bm, int cur, int len);
+
 /*
  * Maximal mount counts between two filesystem checks
  */
@@ -1126,7 +1129,8 @@ struct ext4_sb_info {
        struct journal_s *s_journal;
        struct list_head s_orphan;
        struct mutex s_orphan_lock;
-       struct mutex s_resize_lock;
+       unsigned long s_resize_flags;           /* Flags indicating if there
+                                                  is a resizer */
        unsigned long s_commit_interval;
        u32 s_max_batch_time;
        u32 s_min_batch_time;
@@ -1214,6 +1218,9 @@ struct ext4_sb_info {
 
        /* Kernel thread for multiple mount protection */
        struct task_struct *s_mmp_tsk;
+
+       /* record the last minlen when FITRIM is called. */
+       atomic_t s_last_trim_minblks;
 };
 
 static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
@@ -1743,6 +1750,7 @@ extern unsigned ext4_init_block_bitmap(struct super_block *sb,
                                       struct ext4_group_desc *desc);
 #define ext4_free_blocks_after_init(sb, group, desc)                   \
                ext4_init_block_bitmap(sb, NULL, group, desc)
+ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);
 
 /* dir.c */
 extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
@@ -1793,7 +1801,7 @@ extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
                             unsigned long count, int flags);
 extern int ext4_mb_add_groupinfo(struct super_block *sb,
                ext4_group_t i, struct ext4_group_desc *desc);
-extern void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
+extern int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
                                ext4_fsblk_t block, unsigned long count);
 extern int ext4_trim_fs(struct super_block *, struct fstrim_range *);
 
@@ -1834,6 +1842,17 @@ extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
 extern qsize_t *ext4_get_reserved_space(struct inode *inode);
 extern void ext4_da_update_reserve_space(struct inode *inode,
                                        int used, int quota_claim);
+
+/* indirect.c */
+extern int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
+                               struct ext4_map_blocks *map, int flags);
+extern ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
+                               const struct iovec *iov, loff_t offset,
+                               unsigned long nr_segs);
+extern int ext4_ind_calc_metadata_amount(struct inode *inode, sector_t lblock);
+extern int ext4_ind_trans_blocks(struct inode *inode, int nrblocks, int chunk);
+extern void ext4_ind_truncate(struct inode *inode);
+
 /* ioctl.c */
 extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
 extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
@@ -1855,6 +1874,9 @@ extern int ext4_group_extend(struct super_block *sb,
                                ext4_fsblk_t n_blocks_count);
 
 /* super.c */
+extern void *ext4_kvmalloc(size_t size, gfp_t flags);
+extern void *ext4_kvzalloc(size_t size, gfp_t flags);
+extern void ext4_kvfree(void *ptr);
 extern void __ext4_error(struct super_block *, const char *, unsigned int,
                         const char *, ...)
        __attribute__ ((format (printf, 4, 5)));
@@ -2067,11 +2089,19 @@ struct ext4_group_info {
                                         * 5 free 8-block regions. */
 };
 
-#define EXT4_GROUP_INFO_NEED_INIT_BIT  0
+#define EXT4_GROUP_INFO_NEED_INIT_BIT          0
+#define EXT4_GROUP_INFO_WAS_TRIMMED_BIT                1
 
 #define EXT4_MB_GRP_NEED_INIT(grp)     \
        (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
 
+#define EXT4_MB_GRP_WAS_TRIMMED(grp)   \
+       (test_bit(EXT4_GROUP_INFO_WAS_TRIMMED_BIT, &((grp)->bb_state)))
+#define EXT4_MB_GRP_SET_TRIMMED(grp)   \
+       (set_bit(EXT4_GROUP_INFO_WAS_TRIMMED_BIT, &((grp)->bb_state)))
+#define EXT4_MB_GRP_CLEAR_TRIMMED(grp) \
+       (clear_bit(EXT4_GROUP_INFO_WAS_TRIMMED_BIT, &((grp)->bb_state)))
+
 #define EXT4_MAX_CONTENTION            8
 #define EXT4_CONTENTION_THRESHOLD      2
 
@@ -2122,6 +2152,19 @@ static inline void ext4_mark_super_dirty(struct super_block *sb)
                sb->s_dirt =1;
 }
 
+/*
+ * Block validity checking
+ */
+#define ext4_check_indirect_blockref(inode, bh)                                \
+       ext4_check_blockref(__func__, __LINE__, inode,                  \
+                           (__le32 *)(bh)->b_data,                     \
+                           EXT4_ADDR_PER_BLOCK((inode)->i_sb))
+
+#define ext4_ind_check_inode(inode)                                    \
+       ext4_check_blockref(__func__, __LINE__, inode,                  \
+                           EXT4_I(inode)->i_data,                      \
+                           EXT4_NDIR_BLOCKS)
+
 /*
  * Inodes and files operations
  */
@@ -2151,6 +2194,8 @@ extern void ext4_exit_system_zone(void);
 extern int ext4_data_block_valid(struct ext4_sb_info *sbi,
                                 ext4_fsblk_t start_blk,
                                 unsigned int count);
+extern int ext4_check_blockref(const char *, unsigned int,
+                              struct inode *, __le32 *, unsigned int);
 
 /* extents.c */
 extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
@@ -2230,6 +2275,10 @@ static inline void set_bitmap_uptodate(struct buffer_head *bh)
 extern wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ];
 extern struct mutex ext4__aio_mutex[EXT4_WQ_HASH_SZ];
 
+#define EXT4_RESIZING  0
+extern int ext4_resize_begin(struct super_block *sb);
+extern void ext4_resize_end(struct super_block *sb);
+
 #endif /* __KERNEL__ */
 
 #endif /* _EXT4_H */
index f815cc8..57cf568 100644 (file)
@@ -114,12 +114,6 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode,
                              struct ext4_ext_path *path,
                              ext4_lblk_t block)
 {
-       struct ext4_inode_info *ei = EXT4_I(inode);
-       ext4_fsblk_t bg_start;
-       ext4_fsblk_t last_block;
-       ext4_grpblk_t colour;
-       ext4_group_t block_group;
-       int flex_size = ext4_flex_bg_size(EXT4_SB(inode->i_sb));
        int depth;
 
        if (path) {
@@ -161,36 +155,7 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode,
        }
 
        /* OK. use inode's group */
-       block_group = ei->i_block_group;
-       if (flex_size >= EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME) {
-               /*
-                * If there are at least EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME
-                * block groups per flexgroup, reserve the first block
-                * group for directories and special files.  Regular
-                * files will start at the second block group.  This
-                * tends to speed up directory access and improves
-                * fsck times.
-                */
-               block_group &= ~(flex_size-1);
-               if (S_ISREG(inode->i_mode))
-                       block_group++;
-       }
-       bg_start = ext4_group_first_block_no(inode->i_sb, block_group);
-       last_block = ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es) - 1;
-
-       /*
-        * If we are doing delayed allocation, we don't need take
-        * colour into account.
-        */
-       if (test_opt(inode->i_sb, DELALLOC))
-               return bg_start;
-
-       if (bg_start + EXT4_BLOCKS_PER_GROUP(inode->i_sb) <= last_block)
-               colour = (current->pid % 16) *
-                       (EXT4_BLOCKS_PER_GROUP(inode->i_sb) / 16);
-       else
-               colour = (current->pid % 16) * ((last_block - bg_start) / 16);
-       return bg_start + colour + block;
+       return ext4_inode_to_goal_block(inode);
 }
 
 /*
@@ -776,6 +741,16 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
                                 logical, le32_to_cpu(curp->p_idx->ei_block));
                return -EIO;
        }
+
+       if (unlikely(le16_to_cpu(curp->p_hdr->eh_entries)
+                            >= le16_to_cpu(curp->p_hdr->eh_max))) {
+               EXT4_ERROR_INODE(inode,
+                                "eh_entries %d >= eh_max %d!",
+                                le16_to_cpu(curp->p_hdr->eh_entries),
+                                le16_to_cpu(curp->p_hdr->eh_max));
+               return -EIO;
+       }
+
        len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;
        if (logical > le32_to_cpu(curp->p_idx->ei_block)) {
                /* insert after */
@@ -805,13 +780,6 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
        ext4_idx_store_pblock(ix, ptr);
        le16_add_cpu(&curp->p_hdr->eh_entries, 1);
 
-       if (unlikely(le16_to_cpu(curp->p_hdr->eh_entries)
-                            > le16_to_cpu(curp->p_hdr->eh_max))) {
-               EXT4_ERROR_INODE(inode,
-                                "logical %d == ei_block %d!",
-                                logical, le32_to_cpu(curp->p_idx->ei_block));
-               return -EIO;
-       }
        if (unlikely(ix > EXT_LAST_INDEX(curp->p_hdr))) {
                EXT4_ERROR_INODE(inode, "ix > EXT_LAST_INDEX!");
                return -EIO;
@@ -1446,8 +1414,7 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path)
  * ext4_ext_next_leaf_block:
  * returns first allocated block from next leaf or EXT_MAX_BLOCKS
  */
-static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode,
-                                       struct ext4_ext_path *path)
+static ext4_lblk_t ext4_ext_next_leaf_block(struct ext4_ext_path *path)
 {
        int depth;
 
@@ -1757,7 +1724,6 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
                goto merge;
        }
 
-repeat:
        depth = ext_depth(inode);
        eh = path[depth].p_hdr;
        if (le16_to_cpu(eh->eh_entries) < le16_to_cpu(eh->eh_max))
@@ -1765,9 +1731,10 @@ repeat:
 
        /* probably next leaf has space for us? */
        fex = EXT_LAST_EXTENT(eh);
-       next = ext4_ext_next_leaf_block(inode, path);
-       if (le32_to_cpu(newext->ee_block) > le32_to_cpu(fex->ee_block)
-           && next != EXT_MAX_BLOCKS) {
+       next = EXT_MAX_BLOCKS;
+       if (le32_to_cpu(newext->ee_block) > le32_to_cpu(fex->ee_block))
+               next = ext4_ext_next_leaf_block(path);
+       if (next != EXT_MAX_BLOCKS) {
                ext_debug("next leaf block - %d\n", next);
                BUG_ON(npath != NULL);
                npath = ext4_ext_find_extent(inode, next, NULL);
@@ -1779,7 +1746,7 @@ repeat:
                        ext_debug("next leaf isn't full(%d)\n",
                                  le16_to_cpu(eh->eh_entries));
                        path = npath;
-                       goto repeat;
+                       goto has_space;
                }
                ext_debug("next leaf has no free space(%d,%d)\n",
                          le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max));
@@ -1839,7 +1806,7 @@ has_space:
                                ext4_ext_pblock(newext),
                                ext4_ext_is_uninitialized(newext),
                                ext4_ext_get_actual_len(newext),
-                               nearex, len, nearex + 1, nearex + 2);
+                               nearex, len, nearex, nearex + 1);
                memmove(nearex + 1, nearex, len);
                path[depth].p_ext = nearex;
        }
@@ -2052,7 +2019,7 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
 }
 
 /*
- * ext4_ext_in_cache()
+ * ext4_ext_check_cache()
  * Checks to see if the given block is in the cache.
  * If it is, the cached extent is stored in the given
  * cache extent pointer.  If the cached extent is a hole,
@@ -2134,8 +2101,6 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block,
 /*
  * ext4_ext_rm_idx:
  * removes index from the index block.
- * It's used in truncate case only, thus all requests are for
- * last index in the block only.
  */
 static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
                        struct ext4_ext_path *path)
@@ -2153,6 +2118,13 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
        err = ext4_ext_get_access(handle, inode, path);
        if (err)
                return err;
+
+       if (path->p_idx != EXT_LAST_INDEX(path->p_hdr)) {
+               int len = EXT_LAST_INDEX(path->p_hdr) - path->p_idx;
+               len *= sizeof(struct ext4_extent_idx);
+               memmove(path->p_idx, path->p_idx + 1, len);
+       }
+
        le16_add_cpu(&path->p_hdr->eh_entries, -1);
        err = ext4_ext_dirty(handle, inode, path);
        if (err)
@@ -2534,8 +2506,7 @@ ext4_ext_more_to_rm(struct ext4_ext_path *path)
        return 1;
 }
 
-static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
-                               ext4_lblk_t end)
+static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
 {
        struct super_block *sb = inode->i_sb;
        int depth = ext_depth(inode);
@@ -2575,7 +2546,7 @@ again:
                if (i == depth) {
                        /* this is leaf block */
                        err = ext4_ext_rm_leaf(handle, inode, path,
-                                       start, end);
+                                       start, EXT_MAX_BLOCKS - 1);
                        /* root level has p_bh == NULL, brelse() eats this */
                        brelse(path[i].p_bh);
                        path[i].p_bh = NULL;
@@ -3107,12 +3078,10 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
                                              struct ext4_ext_path *path)
 {
        struct ext4_extent *ex;
-       struct ext4_extent_header *eh;
        int depth;
        int err = 0;
 
        depth = ext_depth(inode);
-       eh = path[depth].p_hdr;
        ex = path[depth].p_ext;
 
        ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical"
@@ -3357,8 +3326,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
        trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags);
 
        /* check in cache */
-       if (ext4_ext_in_cache(inode, map->m_lblk, &newex) &&
-               ((flags & EXT4_GET_BLOCKS_PUNCH_OUT_EXT) == 0)) {
+       if (!(flags & EXT4_GET_BLOCKS_PUNCH_OUT_EXT) &&
+               ext4_ext_in_cache(inode, map->m_lblk, &newex)) {
                if (!newex.ee_start_lo && !newex.ee_start_hi) {
                        if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
                                /*
@@ -3497,8 +3466,27 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 
                        ext4_ext_mark_uninitialized(ex);
 
-                       err = ext4_ext_remove_space(inode, map->m_lblk,
-                               map->m_lblk + punched_out);
+                       ext4_ext_invalidate_cache(inode);
+
+                       err = ext4_ext_rm_leaf(handle, inode, path,
+                               map->m_lblk, map->m_lblk + punched_out);
+
+                       if (!err && path->p_hdr->eh_entries == 0) {
+                               /*
+                                * Punch hole freed all of this sub tree,
+                                * so we need to correct eh_depth
+                                */
+                               err = ext4_ext_get_access(handle, inode, path);
+                               if (err == 0) {
+                                       ext_inode_hdr(inode)->eh_depth = 0;
+                                       ext_inode_hdr(inode)->eh_max =
+                                       cpu_to_le16(ext4_ext_space_root(
+                                               inode, 0));
+
+                                       err = ext4_ext_dirty(
+                                               handle, inode, path);
+                               }
+                       }
 
                        goto out2;
                }
@@ -3596,17 +3584,18 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
        }
 
        err = check_eofblocks_fl(handle, inode, map->m_lblk, path, ar.len);
-       if (err)
-               goto out2;
-
-       err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
+       if (!err)
+               err = ext4_ext_insert_extent(handle, inode, path,
+                                            &newex, flags);
        if (err) {
+               int fb_flags = flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE ?
+                       EXT4_FREE_BLOCKS_NO_QUOT_UPDATE : 0;
                /* free data blocks we just allocated */
                /* not a good idea to call discard here directly,
                 * but otherwise we'd need to call it every free() */
                ext4_discard_preallocations(inode);
                ext4_free_blocks(handle, inode, NULL, ext4_ext_pblock(&newex),
-                                ext4_ext_get_actual_len(&newex), 0);
+                                ext4_ext_get_actual_len(&newex), fb_flags);
                goto out2;
        }
 
@@ -3699,7 +3688,7 @@ void ext4_ext_truncate(struct inode *inode)
 
        last_block = (inode->i_size + sb->s_blocksize - 1)
                        >> EXT4_BLOCK_SIZE_BITS(sb);
-       err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1);
+       err = ext4_ext_remove_space(inode, last_block);
 
        /* In a multi-transaction truncate, we only make the final
         * transaction synchronous.
@@ -3835,7 +3824,7 @@ retry:
                                                blkbits) >> blkbits))
                        new_size = offset + len;
                else
-                       new_size = (map.m_lblk + ret) << blkbits;
+                       new_size = ((loff_t) map.m_lblk + ret) << blkbits;
 
                ext4_falloc_update_inode(inode, mode, new_size,
                                         (map.m_flags & EXT4_MAP_NEW));
index da3bed3..036f78f 100644 (file)
@@ -129,15 +129,30 @@ static int ext4_sync_parent(struct inode *inode)
 {
        struct writeback_control wbc;
        struct dentry *dentry = NULL;
+       struct inode *next;
        int ret = 0;
 
-       while (inode && ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
+       if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY))
+               return 0;
+       inode = igrab(inode);
+       while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
                ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
-               dentry = list_entry(inode->i_dentry.next,
-                                   struct dentry, d_alias);
-               if (!dentry || !dentry->d_parent || !dentry->d_parent->d_inode)
+               dentry = NULL;
+               spin_lock(&inode->i_lock);
+               if (!list_empty(&inode->i_dentry)) {
+                       dentry = list_first_entry(&inode->i_dentry,
+                                                 struct dentry, d_alias);
+                       dget(dentry);
+               }
+               spin_unlock(&inode->i_lock);
+               if (!dentry)
                        break;
-               inode = dentry->d_parent->d_inode;
+               next = igrab(dentry->d_parent->d_inode);
+               dput(dentry);
+               if (!next)
+                       break;
+               iput(inode);
+               inode = next;
                ret = sync_mapping_buffers(inode->i_mapping);
                if (ret)
                        break;
@@ -148,6 +163,7 @@ static int ext4_sync_parent(struct inode *inode)
                if (ret)
                        break;
        }
+       iput(inode);
        return ret;
 }
 
index 21bb2f6..9c63f27 100644 (file)
@@ -1287,7 +1287,7 @@ extern int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
                           group, used_blks,
                           ext4_itable_unused_count(sb, gdp));
                ret = 1;
-               goto out;
+               goto err_out;
        }
 
        blk = ext4_inode_table(sb, gdp) + used_blks;
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
new file mode 100644 (file)
index 0000000..b8602cd
--- /dev/null
@@ -0,0 +1,1482 @@
+/*
+ *  linux/fs/ext4/indirect.c
+ *
+ *  from
+ *
+ *  linux/fs/ext4/inode.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/fs/minix/inode.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Goal-directed block allocation by Stephen Tweedie
+ *     (sct@redhat.com), 1993, 1998
+ */
+
+#include <linux/module.h>
+#include "ext4_jbd2.h"
+#include "truncate.h"
+
+#include <trace/events/ext4.h>
+
+typedef struct {
+       __le32  *p;
+       __le32  key;
+       struct buffer_head *bh;
+} Indirect;
+
+static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v)
+{
+       p->key = *(p->p = v);
+       p->bh = bh;
+}
+
+/**
+ *     ext4_block_to_path - parse the block number into array of offsets
+ *     @inode: inode in question (we are only interested in its superblock)
+ *     @i_block: block number to be parsed
+ *     @offsets: array to store the offsets in
+ *     @boundary: set this non-zero if the referred-to block is likely to be
+ *            followed (on disk) by an indirect block.
+ *
+ *     To store the locations of file's data ext4 uses a data structure common
+ *     for UNIX filesystems - tree of pointers anchored in the inode, with
+ *     data blocks at leaves and indirect blocks in intermediate nodes.
+ *     This function translates the block number into path in that tree -
+ *     return value is the path length and @offsets[n] is the offset of
+ *     pointer to (n+1)th node in the nth one. If @block is out of range
+ *     (negative or too large) warning is printed and zero returned.
+ *
+ *     Note: function doesn't find node addresses, so no IO is needed. All
+ *     we need to know is the capacity of indirect blocks (taken from the
+ *     inode->i_sb).
+ */
+
+/*
+ * Portability note: the last comparison (check that we fit into triple
+ * indirect block) is spelled differently, because otherwise on an
+ * architecture with 32-bit longs and 8Kb pages we might get into trouble
+ * if our filesystem had 8Kb blocks. We might use long long, but that would
+ * kill us on x86. Oh, well, at least the sign propagation does not matter -
+ * i_block would have to be negative in the very beginning, so we would not
+ * get there at all.
+ */
+
+static int ext4_block_to_path(struct inode *inode,
+                             ext4_lblk_t i_block,
+                             ext4_lblk_t offsets[4], int *boundary)
+{
+       int ptrs = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+       int ptrs_bits = EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb);
+       const long direct_blocks = EXT4_NDIR_BLOCKS,
+               indirect_blocks = ptrs,
+               double_blocks = (1 << (ptrs_bits * 2));
+       int n = 0;
+       int final = 0;
+
+       if (i_block < direct_blocks) {
+               offsets[n++] = i_block;
+               final = direct_blocks;
+       } else if ((i_block -= direct_blocks) < indirect_blocks) {
+               offsets[n++] = EXT4_IND_BLOCK;
+               offsets[n++] = i_block;
+               final = ptrs;
+       } else if ((i_block -= indirect_blocks) < double_blocks) {
+               offsets[n++] = EXT4_DIND_BLOCK;
+               offsets[n++] = i_block >> ptrs_bits;
+               offsets[n++] = i_block & (ptrs - 1);
+               final = ptrs;
+       } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) {
+               offsets[n++] = EXT4_TIND_BLOCK;
+               offsets[n++] = i_block >> (ptrs_bits * 2);
+               offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1);
+               offsets[n++] = i_block & (ptrs - 1);
+               final = ptrs;
+       } else {
+               ext4_warning(inode->i_sb, "block %lu > max in inode %lu",
+                            i_block + direct_blocks +
+                            indirect_blocks + double_blocks, inode->i_ino);
+       }
+       if (boundary)
+               *boundary = final - 1 - (i_block & (ptrs - 1));
+       return n;
+}
+
+/**
+ *     ext4_get_branch - read the chain of indirect blocks leading to data
+ *     @inode: inode in question
+ *     @depth: depth of the chain (1 - direct pointer, etc.)
+ *     @offsets: offsets of pointers in inode/indirect blocks
+ *     @chain: place to store the result
+ *     @err: here we store the error value
+ *
+ *     Function fills the array of triples <key, p, bh> and returns %NULL
+ *     if everything went OK or the pointer to the last filled triple
+ *     (incomplete one) otherwise. Upon the return chain[i].key contains
+ *     the number of (i+1)-th block in the chain (as it is stored in memory,
+ *     i.e. little-endian 32-bit), chain[i].p contains the address of that
+ *     number (it points into struct inode for i==0 and into the bh->b_data
+ *     for i>0) and chain[i].bh points to the buffer_head of i-th indirect
+ *     block for i>0 and NULL for i==0. In other words, it holds the block
+ *     numbers of the chain, addresses they were taken from (and where we can
+ *     verify that chain did not change) and buffer_heads hosting these
+ *     numbers.
+ *
+ *     Function stops when it stumbles upon zero pointer (absent block)
+ *             (pointer to last triple returned, *@err == 0)
+ *     or when it gets an IO error reading an indirect block
+ *             (ditto, *@err == -EIO)
+ *     or when it reads all @depth-1 indirect blocks successfully and finds
+ *     the whole chain, all way to the data (returns %NULL, *err == 0).
+ *
+ *      Need to be called with
+ *      down_read(&EXT4_I(inode)->i_data_sem)
+ */
+static Indirect *ext4_get_branch(struct inode *inode, int depth,
+                                ext4_lblk_t  *offsets,
+                                Indirect chain[4], int *err)
+{
+       struct super_block *sb = inode->i_sb;
+       Indirect *p = chain;
+       struct buffer_head *bh;
+
+       *err = 0;
+       /* i_data is not going away, no lock needed */
+       add_chain(chain, NULL, EXT4_I(inode)->i_data + *offsets);
+       if (!p->key)
+               goto no_block;
+       while (--depth) {
+               bh = sb_getblk(sb, le32_to_cpu(p->key));
+               if (unlikely(!bh))
+                       goto failure;
+
+               if (!bh_uptodate_or_lock(bh)) {
+                       if (bh_submit_read(bh) < 0) {
+                               put_bh(bh);
+                               goto failure;
+                       }
+                       /* validate block references */
+                       if (ext4_check_indirect_blockref(inode, bh)) {
+                               put_bh(bh);
+                               goto failure;
+                       }
+               }
+
+               add_chain(++p, bh, (__le32 *)bh->b_data + *++offsets);
+               /* Reader: end */
+               if (!p->key)
+                       goto no_block;
+       }
+       return NULL;
+
+failure:
+       *err = -EIO;
+no_block:
+       return p;
+}
+
+/**
+ *     ext4_find_near - find a place for allocation with sufficient locality
+ *     @inode: owner
+ *     @ind: descriptor of indirect block.
+ *
+ *     This function returns the preferred place for block allocation.
+ *     It is used when heuristic for sequential allocation fails.
+ *     Rules are:
+ *       + if there is a block to the left of our position - allocate near it.
+ *       + if pointer will live in indirect block - allocate near that block.
+ *       + if pointer will live in inode - allocate in the same
+ *         cylinder group.
+ *
+ * In the latter case we colour the starting block by the callers PID to
+ * prevent it from clashing with concurrent allocations for a different inode
+ * in the same block group.   The PID is used here so that functionally related
+ * files will be close-by on-disk.
+ *
+ *     Caller must make sure that @ind is valid and will stay that way.
+ */
+static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind)
+{
+       struct ext4_inode_info *ei = EXT4_I(inode);
+       __le32 *start = ind->bh ? (__le32 *) ind->bh->b_data : ei->i_data;
+       __le32 *p;
+
+       /* Try to find previous block */
+       for (p = ind->p - 1; p >= start; p--) {
+               if (*p)
+                       return le32_to_cpu(*p);
+       }
+
+       /* No such thing, so let's try location of indirect block */
+       if (ind->bh)
+               return ind->bh->b_blocknr;
+
+       /*
+        * It is going to be referred to from the inode itself? OK, just put it
+        * into the same cylinder group then.
+        */
+       return ext4_inode_to_goal_block(inode);
+}
+
+/**
+ *     ext4_find_goal - find a preferred place for allocation.
+ *     @inode: owner
+ *     @block:  block we want
+ *     @partial: pointer to the last triple within a chain
+ *
+ *     Normally this function find the preferred place for block allocation,
+ *     returns it.
+ *     Because this is only used for non-extent files, we limit the block nr
+ *     to 32 bits.
+ */
+static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
+                                  Indirect *partial)
+{
+       ext4_fsblk_t goal;
+
+       /*
+        * XXX need to get goal block from mballoc's data structures
+        */
+
+       goal = ext4_find_near(inode, partial);
+       goal = goal & EXT4_MAX_BLOCK_FILE_PHYS;
+       return goal;
+}
+
+/**
+ *     ext4_blks_to_allocate - Look up the block map and count the number
+ *     of direct blocks need to be allocated for the given branch.
+ *
+ *     @branch: chain of indirect blocks
+ *     @k: number of blocks need for indirect blocks
+ *     @blks: number of data blocks to be mapped.
+ *     @blocks_to_boundary:  the offset in the indirect block
+ *
+ *     return the total number of blocks to be allocate, including the
+ *     direct and indirect blocks.
+ */
+static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
+                                int blocks_to_boundary)
+{
+       unsigned int count = 0;
+
+       /*
+        * Simple case, [t,d]Indirect block(s) has not allocated yet
+        * then it's clear blocks on that path have not allocated
+        */
+       if (k > 0) {
+               /* right now we don't handle cross boundary allocation */
+               if (blks < blocks_to_boundary + 1)
+                       count += blks;
+               else
+                       count += blocks_to_boundary + 1;
+               return count;
+       }
+
+       count++;
+       while (count < blks && count <= blocks_to_boundary &&
+               le32_to_cpu(*(branch[0].p + count)) == 0) {
+               count++;
+       }
+       return count;
+}
+
+/**
+ *     ext4_alloc_blocks: multiple allocate blocks needed for a branch
+ *     @handle: handle for this transaction
+ *     @inode: inode which needs allocated blocks
+ *     @iblock: the logical block to start allocated at
+ *     @goal: preferred physical block of allocation
+ *     @indirect_blks: the number of blocks need to allocate for indirect
+ *                     blocks
+ *     @blks: number of desired blocks
+ *     @new_blocks: on return it will store the new block numbers for
+ *     the indirect blocks(if needed) and the first direct block,
+ *     @err: on return it will store the error code
+ *
+ *     This function will return the number of blocks allocated as
+ *     requested by the passed-in parameters.
+ */
+static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+                            ext4_lblk_t iblock, ext4_fsblk_t goal,
+                            int indirect_blks, int blks,
+                            ext4_fsblk_t new_blocks[4], int *err)
+{
+       struct ext4_allocation_request ar;
+       int target, i;
+       unsigned long count = 0, blk_allocated = 0;
+       int index = 0;
+       ext4_fsblk_t current_block = 0;
+       int ret = 0;
+
+       /*
+        * Here we try to allocate the requested multiple blocks at once,
+        * on a best-effort basis.
+        * To build a branch, we should allocate blocks for
+        * the indirect blocks(if not allocated yet), and at least
+        * the first direct block of this branch.  That's the
+        * minimum number of blocks need to allocate(required)
+        */
+       /* first we try to allocate the indirect blocks */
+       target = indirect_blks;
+       while (target > 0) {
+               count = target;
+               /* allocating blocks for indirect blocks and direct blocks */
+               current_block = ext4_new_meta_blocks(handle, inode, goal,
+                                                    0, &count, err);
+               if (*err)
+                       goto failed_out;
+
+               if (unlikely(current_block + count > EXT4_MAX_BLOCK_FILE_PHYS)) {
+                       EXT4_ERROR_INODE(inode,
+                                        "current_block %llu + count %lu > %d!",
+                                        current_block, count,
+                                        EXT4_MAX_BLOCK_FILE_PHYS);
+                       *err = -EIO;
+                       goto failed_out;
+               }
+
+               target -= count;
+               /* allocate blocks for indirect blocks */
+               while (index < indirect_blks && count) {
+                       new_blocks[index++] = current_block++;
+                       count--;
+               }
+               if (count > 0) {
+                       /*
+                        * save the new block number
+                        * for the first direct block
+                        */
+                       new_blocks[index] = current_block;
+                       printk(KERN_INFO "%s returned more blocks than "
+                                               "requested\n", __func__);
+                       WARN_ON(1);
+                       break;
+               }
+       }
+
+       target = blks - count ;
+       blk_allocated = count;
+       if (!target)
+               goto allocated;
+       /* Now allocate data blocks */
+       memset(&ar, 0, sizeof(ar));
+       ar.inode = inode;
+       ar.goal = goal;
+       ar.len = target;
+       ar.logical = iblock;
+       if (S_ISREG(inode->i_mode))
+               /* enable in-core preallocation only for regular files */
+               ar.flags = EXT4_MB_HINT_DATA;
+
+       current_block = ext4_mb_new_blocks(handle, &ar, err);
+       if (unlikely(current_block + ar.len > EXT4_MAX_BLOCK_FILE_PHYS)) {
+               EXT4_ERROR_INODE(inode,
+                                "current_block %llu + ar.len %d > %d!",
+                                current_block, ar.len,
+                                EXT4_MAX_BLOCK_FILE_PHYS);
+               *err = -EIO;
+               goto failed_out;
+       }
+
+       if (*err && (target == blks)) {
+               /*
+                * if the allocation failed and we didn't allocate
+                * any blocks before
+                */
+               goto failed_out;
+       }
+       if (!*err) {
+               if (target == blks) {
+                       /*
+                        * save the new block number
+                        * for the first direct block
+                        */
+                       new_blocks[index] = current_block;
+               }
+               blk_allocated += ar.len;
+       }
+allocated:
+       /* total number of blocks allocated for direct blocks */
+       ret = blk_allocated;
+       *err = 0;
+       return ret;
+failed_out:
+       for (i = 0; i < index; i++)
+               ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0);
+       return ret;
+}
+
+/**
+ *     ext4_alloc_branch - allocate and set up a chain of blocks.
+ *     @handle: handle for this transaction
+ *     @inode: owner
+ *     @indirect_blks: number of allocated indirect blocks
+ *     @blks: number of allocated direct blocks
+ *     @goal: preferred place for allocation
+ *     @offsets: offsets (in the blocks) to store the pointers to next.
+ *     @branch: place to store the chain in.
+ *
+ *     This function allocates blocks, zeroes out all but the last one,
+ *     links them into chain and (if we are synchronous) writes them to disk.
+ *     In other words, it prepares a branch that can be spliced onto the
+ *     inode. It stores the information about that chain in the branch[], in
+ *     the same format as ext4_get_branch() would do. We are calling it after
+ *     we had read the existing part of chain and partial points to the last
+ *     triple of that (one with zero ->key). Upon the exit we have the same
+ *     picture as after the successful ext4_get_block(), except that in one
+ *     place chain is disconnected - *branch->p is still zero (we did not
+ *     set the last link), but branch->key contains the number that should
+ *     be placed into *branch->p to fill that gap.
+ *
+ *     If allocation fails we free all blocks we've allocated (and forget
+ *     their buffer_heads) and return the error value the from failed
+ *     ext4_alloc_block() (normally -ENOSPC). Otherwise we set the chain
+ *     as described above and return 0.
+ */
+static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+                            ext4_lblk_t iblock, int indirect_blks,
+                            int *blks, ext4_fsblk_t goal,
+                            ext4_lblk_t *offsets, Indirect *branch)
+{
+       int blocksize = inode->i_sb->s_blocksize;
+       int i, n = 0;
+       int err = 0;
+       struct buffer_head *bh;
+       int num;
+       ext4_fsblk_t new_blocks[4];
+       ext4_fsblk_t current_block;
+
+       num = ext4_alloc_blocks(handle, inode, iblock, goal, indirect_blks,
+                               *blks, new_blocks, &err);
+       if (err)
+               return err;
+
+       branch[0].key = cpu_to_le32(new_blocks[0]);
+       /*
+        * metadata blocks and data blocks are allocated.
+        */
+       for (n = 1; n <= indirect_blks;  n++) {
+               /*
+                * Get buffer_head for parent block, zero it out
+                * and set the pointer to new one, then send
+                * parent to disk.
+                */
+               bh = sb_getblk(inode->i_sb, new_blocks[n-1]);
+               if (unlikely(!bh)) {
+                       err = -EIO;
+                       goto failed;
+               }
+
+               branch[n].bh = bh;
+               lock_buffer(bh);
+               BUFFER_TRACE(bh, "call get_create_access");
+               err = ext4_journal_get_create_access(handle, bh);
+               if (err) {
+                       /* Don't brelse(bh) here; it's done in
+                        * ext4_journal_forget() below */
+                       unlock_buffer(bh);
+                       goto failed;
+               }
+
+               memset(bh->b_data, 0, blocksize);
+               branch[n].p = (__le32 *) bh->b_data + offsets[n];
+               branch[n].key = cpu_to_le32(new_blocks[n]);
+               *branch[n].p = branch[n].key;
+               if (n == indirect_blks) {
+                       current_block = new_blocks[n];
+                       /*
+                        * End of chain, update the last new metablock of
+                        * the chain to point to the new allocated
+                        * data blocks numbers
+                        */
+                       for (i = 1; i < num; i++)
+                               *(branch[n].p + i) = cpu_to_le32(++current_block);
+               }
+               BUFFER_TRACE(bh, "marking uptodate");
+               set_buffer_uptodate(bh);
+               unlock_buffer(bh);
+
+               BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+               err = ext4_handle_dirty_metadata(handle, inode, bh);
+               if (err)
+                       goto failed;
+       }
+       *blks = num;
+       return err;
+failed:
+       /* Allocation failed, free what we already allocated */
+       ext4_free_blocks(handle, inode, NULL, new_blocks[0], 1, 0);
+       for (i = 1; i <= n ; i++) {
+               /*
+                * branch[i].bh is newly allocated, so there is no
+                * need to revoke the block, which is why we don't
+                * need to set EXT4_FREE_BLOCKS_METADATA.
+                */
+               ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1,
+                                EXT4_FREE_BLOCKS_FORGET);
+       }
+       for (i = n+1; i < indirect_blks; i++)
+               ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0);
+
+       ext4_free_blocks(handle, inode, NULL, new_blocks[i], num, 0);
+
+       return err;
+}
+
+/**
+ * ext4_splice_branch - splice the allocated branch onto inode.
+ * @handle: handle for this transaction
+ * @inode: owner
+ * @block: (logical) number of block we are adding
+ * @chain: chain of indirect blocks (with a missing link - see
+ *     ext4_alloc_branch)
+ * @where: location of missing link
+ * @num:   number of indirect blocks we are adding
+ * @blks:  number of direct blocks we are adding
+ *
+ * This function fills the missing link and does all housekeeping needed in
+ * inode (->i_blocks, etc.). In case of success we end up with the full
+ * chain to new block and return 0.
+ */
+static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+                             ext4_lblk_t block, Indirect *where, int num,
+                             int blks)
+{
+       int i;
+       int err = 0;
+       ext4_fsblk_t current_block;
+
+       /*
+        * If we're splicing into a [td]indirect block (as opposed to the
+        * inode) then we need to get write access to the [td]indirect block
+        * before the splice.
+        */
+       if (where->bh) {
+               BUFFER_TRACE(where->bh, "get_write_access");
+               err = ext4_journal_get_write_access(handle, where->bh);
+               if (err)
+                       goto err_out;
+       }
+       /* That's it */
+
+       *where->p = where->key;
+
+       /*
+        * Update the host buffer_head or inode to point to more just allocated
+        * direct blocks blocks
+        */
+       if (num == 0 && blks > 1) {
+               current_block = le32_to_cpu(where->key) + 1;
+               for (i = 1; i < blks; i++)
+                       *(where->p + i) = cpu_to_le32(current_block++);
+       }
+
+       /* We are done with atomic stuff, now do the rest of housekeeping */
+       /* had we spliced it onto indirect block? */
+       if (where->bh) {
+               /*
+                * If we spliced it onto an indirect block, we haven't
+                * altered the inode.  Note however that if it is being spliced
+                * onto an indirect block at the very end of the file (the
+                * file is growing) then we *will* alter the inode to reflect
+                * the new i_size.  But that is not done here - it is done in
+                * generic_commit_write->__mark_inode_dirty->ext4_dirty_inode.
+                */
+               jbd_debug(5, "splicing indirect only\n");
+               BUFFER_TRACE(where->bh, "call ext4_handle_dirty_metadata");
+               err = ext4_handle_dirty_metadata(handle, inode, where->bh);
+               if (err)
+                       goto err_out;
+       } else {
+               /*
+                * OK, we spliced it into the inode itself on a direct block.
+                */
+               ext4_mark_inode_dirty(handle, inode);
+               jbd_debug(5, "splicing direct\n");
+       }
+       return err;
+
+err_out:
+       for (i = 1; i <= num; i++) {
+               /*
+                * branch[i].bh is newly allocated, so there is no
+                * need to revoke the block, which is why we don't
+                * need to set EXT4_FREE_BLOCKS_METADATA.
+                */
+               ext4_free_blocks(handle, inode, where[i].bh, 0, 1,
+                                EXT4_FREE_BLOCKS_FORGET);
+       }
+       ext4_free_blocks(handle, inode, NULL, le32_to_cpu(where[num].key),
+                        blks, 0);
+
+       return err;
+}
+
+/*
+ * The ext4_ind_map_blocks() function handles non-extents inodes
+ * (i.e., using the traditional indirect/double-indirect i_blocks
+ * scheme) for ext4_map_blocks().
+ *
+ * Allocation strategy is simple: if we have to allocate something, we will
+ * have to go the whole way to leaf. So let's do it before attaching anything
+ * to tree, set linkage between the newborn blocks, write them if sync is
+ * required, recheck the path, free and repeat if check fails, otherwise
+ * set the last missing link (that will protect us from any truncate-generated
+ * removals - all blocks on the path are immune now) and possibly force the
+ * write on the parent block.
+ * That has a nice additional property: no special recovery from the failed
+ * allocations is needed - we simply release blocks and do not touch anything
+ * reachable from inode.
+ *
+ * `handle' can be NULL if create == 0.
+ *
+ * return > 0, # of blocks mapped or allocated.
+ * return = 0, if plain lookup failed.
+ * return < 0, error case.
+ *
+ * The ext4_ind_get_blocks() function should be called with
+ * down_write(&EXT4_I(inode)->i_data_sem) if allocating filesystem
+ * blocks (i.e., flags has EXT4_GET_BLOCKS_CREATE set) or
+ * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system
+ * blocks.
+ */
+int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
+                       struct ext4_map_blocks *map,
+                       int flags)
+{
+       int err = -EIO;
+       ext4_lblk_t offsets[4];
+       Indirect chain[4];
+       Indirect *partial;
+       ext4_fsblk_t goal;
+       int indirect_blks;
+       int blocks_to_boundary = 0;
+       int depth;
+       int count = 0;
+       ext4_fsblk_t first_block = 0;
+
+       trace_ext4_ind_map_blocks_enter(inode, map->m_lblk, map->m_len, flags);
+       J_ASSERT(!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)));
+       J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0);
+       depth = ext4_block_to_path(inode, map->m_lblk, offsets,
+                                  &blocks_to_boundary);
+
+       if (depth == 0)
+               goto out;
+
+       partial = ext4_get_branch(inode, depth, offsets, chain, &err);
+
+       /* Simplest case - block found, no allocation needed */
+       if (!partial) {
+               first_block = le32_to_cpu(chain[depth - 1].key);
+               count++;
+               /*map more blocks*/
+               while (count < map->m_len && count <= blocks_to_boundary) {
+                       ext4_fsblk_t blk;
+
+                       blk = le32_to_cpu(*(chain[depth-1].p + count));
+
+                       if (blk == first_block + count)
+                               count++;
+                       else
+                               break;
+               }
+               goto got_it;
+       }
+
+       /* Next simple case - plain lookup or failed read of indirect block */
+       if ((flags & EXT4_GET_BLOCKS_CREATE) == 0 || err == -EIO)
+               goto cleanup;
+
+       /*
+        * Okay, we need to do block allocation.
+       */
+       goal = ext4_find_goal(inode, map->m_lblk, partial);
+
+       /* the number of blocks need to allocate for [d,t]indirect blocks */
+       indirect_blks = (chain + depth) - partial - 1;
+
+       /*
+        * Next look up the indirect map to count the totoal number of
+        * direct blocks to allocate for this branch.
+        */
+       count = ext4_blks_to_allocate(partial, indirect_blks,
+                                     map->m_len, blocks_to_boundary);
+       /*
+        * Block out ext4_truncate while we alter the tree
+        */
+       err = ext4_alloc_branch(handle, inode, map->m_lblk, indirect_blks,
+                               &count, goal,
+                               offsets + (partial - chain), partial);
+
+       /*
+        * The ext4_splice_branch call will free and forget any buffers
+        * on the new chain if there is a failure, but that risks using
+        * up transaction credits, especially for bitmaps where the
+        * credits cannot be returned.  Can we handle this somehow?  We
+        * may need to return -EAGAIN upwards in the worst case.  --sct
+        */
+       if (!err)
+               err = ext4_splice_branch(handle, inode, map->m_lblk,
+                                        partial, indirect_blks, count);
+       if (err)
+               goto cleanup;
+
+       map->m_flags |= EXT4_MAP_NEW;
+
+       ext4_update_inode_fsync_trans(handle, inode, 1);
+got_it:
+       map->m_flags |= EXT4_MAP_MAPPED;
+       map->m_pblk = le32_to_cpu(chain[depth-1].key);
+       map->m_len = count;
+       if (count > blocks_to_boundary)
+               map->m_flags |= EXT4_MAP_BOUNDARY;
+       err = count;
+       /* Clean up and exit */
+       partial = chain + depth - 1;    /* the whole chain */
+cleanup:
+       while (partial > chain) {
+               BUFFER_TRACE(partial->bh, "call brelse");
+               brelse(partial->bh);
+               partial--;
+       }
+out:
+       trace_ext4_ind_map_blocks_exit(inode, map->m_lblk,
+                               map->m_pblk, map->m_len, err);
+       return err;
+}
+
+/*
+ * O_DIRECT for ext3 (or indirect map) based files
+ *
+ * If the O_DIRECT write will extend the file then add this inode to the
+ * orphan list.  So recovery will truncate it back to the original size
+ * if the machine crashes during the write.
+ *
+ * If the O_DIRECT write is intantiating holes inside i_size and the machine
+ * crashes then stale disk data _may_ be exposed inside the file. But current
+ * VFS code falls back into buffered path in that case so we are safe.
+ */
+ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
+                          const struct iovec *iov, loff_t offset,
+                          unsigned long nr_segs)
+{
+       struct file *file = iocb->ki_filp;
+       struct inode *inode = file->f_mapping->host;
+       struct ext4_inode_info *ei = EXT4_I(inode);
+       handle_t *handle;
+       ssize_t ret;
+       int orphan = 0;
+       size_t count = iov_length(iov, nr_segs);
+       int retries = 0;
+
+       if (rw == WRITE) {
+               loff_t final_size = offset + count;
+
+               if (final_size > inode->i_size) {
+                       /* Credits for sb + inode write */
+                       handle = ext4_journal_start(inode, 2);
+                       if (IS_ERR(handle)) {
+                               ret = PTR_ERR(handle);
+                               goto out;
+                       }
+                       ret = ext4_orphan_add(handle, inode);
+                       if (ret) {
+                               ext4_journal_stop(handle);
+                               goto out;
+                       }
+                       orphan = 1;
+                       ei->i_disksize = inode->i_size;
+                       ext4_journal_stop(handle);
+               }
+       }
+
+retry:
+       if (rw == READ && ext4_should_dioread_nolock(inode))
+               ret = __blockdev_direct_IO(rw, iocb, inode,
+                                inode->i_sb->s_bdev, iov,
+                                offset, nr_segs,
+                                ext4_get_block, NULL, NULL, 0);
+       else {
+               ret = blockdev_direct_IO(rw, iocb, inode, iov,
+                                offset, nr_segs, ext4_get_block);
+
+               if (unlikely((rw & WRITE) && ret < 0)) {
+                       loff_t isize = i_size_read(inode);
+                       loff_t end = offset + iov_length(iov, nr_segs);
+
+                       if (end > isize)
+                               ext4_truncate_failed_write(inode);
+               }
+       }
+       if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+               goto retry;
+
+       if (orphan) {
+               int err;
+
+               /* Credits for sb + inode write */
+               handle = ext4_journal_start(inode, 2);
+               if (IS_ERR(handle)) {
+                       /* This is really bad luck. We've written the data
+                        * but cannot extend i_size. Bail out and pretend
+                        * the write failed... */
+                       ret = PTR_ERR(handle);
+                       if (inode->i_nlink)
+                               ext4_orphan_del(NULL, inode);
+
+                       goto out;
+               }
+               if (inode->i_nlink)
+                       ext4_orphan_del(handle, inode);
+               if (ret > 0) {
+                       loff_t end = offset + ret;
+                       if (end > inode->i_size) {
+                               ei->i_disksize = end;
+                               i_size_write(inode, end);
+                               /*
+                                * We're going to return a positive `ret'
+                                * here due to non-zero-length I/O, so there's
+                                * no way of reporting error returns from
+                                * ext4_mark_inode_dirty() to userspace.  So
+                                * ignore it.
+                                */
+                               ext4_mark_inode_dirty(handle, inode);
+                       }
+               }
+               err = ext4_journal_stop(handle);
+               if (ret == 0)
+                       ret = err;
+       }
+out:
+       return ret;
+}
+
+/*
+ * Calculate the number of metadata blocks need to reserve
+ * to allocate a new block at @lblocks for non extent file based file
+ */
+int ext4_ind_calc_metadata_amount(struct inode *inode, sector_t lblock)
+{
+       struct ext4_inode_info *ei = EXT4_I(inode);
+       sector_t dind_mask = ~((sector_t)EXT4_ADDR_PER_BLOCK(inode->i_sb) - 1);
+       int blk_bits;
+
+       if (lblock < EXT4_NDIR_BLOCKS)
+               return 0;
+
+       lblock -= EXT4_NDIR_BLOCKS;
+
+       if (ei->i_da_metadata_calc_len &&
+           (lblock & dind_mask) == ei->i_da_metadata_calc_last_lblock) {
+               ei->i_da_metadata_calc_len++;
+               return 0;
+       }
+       ei->i_da_metadata_calc_last_lblock = lblock & dind_mask;
+       ei->i_da_metadata_calc_len = 1;
+       blk_bits = order_base_2(lblock);
+       return (blk_bits / EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb)) + 1;
+}
+
+int ext4_ind_trans_blocks(struct inode *inode, int nrblocks, int chunk)
+{
+       int indirects;
+
+       /* if nrblocks are contiguous */
+       if (chunk) {
+               /*
+                * With N contiguous data blocks, we need at most
+                * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) + 1 indirect blocks,
+                * 2 dindirect blocks, and 1 tindirect block
+                */
+               return DIV_ROUND_UP(nrblocks,
+                                   EXT4_ADDR_PER_BLOCK(inode->i_sb)) + 4;
+       }
+       /*
+        * if nrblocks are not contiguous, worse case, each block touch
+        * a indirect block, and each indirect block touch a double indirect
+        * block, plus a triple indirect block
+        */
+       indirects = nrblocks * 2 + 1;
+       return indirects;
+}
+
+/*
+ * Truncate transactions can be complex and absolutely huge.  So we need to
+ * be able to restart the transaction at a conventient checkpoint to make
+ * sure we don't overflow the journal.
+ *
+ * start_transaction gets us a new handle for a truncate transaction,
+ * and extend_transaction tries to extend the existing one a bit.  If
+ * extend fails, we need to propagate the failure up and restart the
+ * transaction in the top-level truncate loop. --sct
+ */
+static handle_t *start_transaction(struct inode *inode)
+{
+       handle_t *result;
+
+       result = ext4_journal_start(inode, ext4_blocks_for_truncate(inode));
+       if (!IS_ERR(result))
+               return result;
+
+       ext4_std_error(inode->i_sb, PTR_ERR(result));
+       return result;
+}
+
+/*
+ * Try to extend this transaction for the purposes of truncation.
+ *
+ * Returns 0 if we managed to create more room.  If we can't create more
+ * room, and the transaction must be restarted we return 1.
+ */
+static int try_to_extend_transaction(handle_t *handle, struct inode *inode)
+{
+       if (!ext4_handle_valid(handle))
+               return 0;
+       if (ext4_handle_has_enough_credits(handle, EXT4_RESERVE_TRANS_BLOCKS+1))
+               return 0;
+       if (!ext4_journal_extend(handle, ext4_blocks_for_truncate(inode)))
+               return 0;
+       return 1;
+}
+
+/*
+ * Probably it should be a library function... search for first non-zero word
+ * or memcmp with zero_page, whatever is better for particular architecture.
+ * Linus?
+ */
+static inline int all_zeroes(__le32 *p, __le32 *q)
+{
+       while (p < q)
+               if (*p++)
+                       return 0;
+       return 1;
+}
+
+/**
+ *     ext4_find_shared - find the indirect blocks for partial truncation.
+ *     @inode:   inode in question
+ *     @depth:   depth of the affected branch
+ *     @offsets: offsets of pointers in that branch (see ext4_block_to_path)
+ *     @chain:   place to store the pointers to partial indirect blocks
+ *     @top:     place to the (detached) top of branch
+ *
+ *     This is a helper function used by ext4_truncate().
+ *
+ *     When we do truncate() we may have to clean the ends of several
+ *     indirect blocks but leave the blocks themselves alive. Block is
+ *     partially truncated if some data below the new i_size is referred
+ *     from it (and it is on the path to the first completely truncated
+ *     data block, indeed).  We have to free the top of that path along
+ *     with everything to the right of the path. Since no allocation
+ *     past the truncation point is possible until ext4_truncate()
+ *     finishes, we may safely do the latter, but top of branch may
+ *     require special attention - pageout below the truncation point
+ *     might try to populate it.
+ *
+ *     We atomically detach the top of branch from the tree, store the
+ *     block number of its root in *@top, pointers to buffer_heads of
+ *     partially truncated blocks - in @chain[].bh and pointers to
+ *     their last elements that should not be removed - in
+ *     @chain[].p. Return value is the pointer to last filled element
+ *     of @chain.
+ *
+ *     The work left to caller to do the actual freeing of subtrees:
+ *             a) free the subtree starting from *@top
+ *             b) free the subtrees whose roots are stored in
+ *                     (@chain[i].p+1 .. end of @chain[i].bh->b_data)
+ *             c) free the subtrees growing from the inode past the @chain[0].
+ *                     (no partially truncated stuff there).  */
+
+static Indirect *ext4_find_shared(struct inode *inode, int depth,
+                                 ext4_lblk_t offsets[4], Indirect chain[4],
+                                 __le32 *top)
+{
+       Indirect *partial, *p;
+       int k, err;
+
+       *top = 0;
+       /* Make k index the deepest non-null offset + 1 */
+       for (k = depth; k > 1 && !offsets[k-1]; k--)
+               ;
+       partial = ext4_get_branch(inode, k, offsets, chain, &err);
+       /* Writer: pointers */
+       if (!partial)
+               partial = chain + k-1;
+       /*
+        * If the branch acquired continuation since we've looked at it -
+        * fine, it should all survive and (new) top doesn't belong to us.
+        */
+       if (!partial->key && *partial->p)
+               /* Writer: end */
+               goto no_top;
+       for (p = partial; (p > chain) && all_zeroes((__le32 *) p->bh->b_data, p->p); p--)
+               ;
+       /*
+        * OK, we've found the last block that must survive. The rest of our
+        * branch should be detached before unlocking. However, if that rest
+        * of branch is all ours and does not grow immediately from the inode
+        * it's easier to cheat and just decrement partial->p.
+        */
+       if (p == chain + k - 1 && p > chain) {
+               p->p--;
+       } else {
+               *top = *p->p;
+               /* Nope, don't do this in ext4.  Must leave the tree intact */
+#if 0
+               *p->p = 0;
+#endif
+       }
+       /* Writer: end */
+
+       while (partial > p) {
+               brelse(partial->bh);
+               partial--;
+       }
+no_top:
+       return partial;
+}
+
+/*
+ * Zero a number of block pointers in either an inode or an indirect block.
+ * If we restart the transaction we must again get write access to the
+ * indirect block for further modification.
+ *
+ * We release `count' blocks on disk, but (last - first) may be greater
+ * than `count' because there can be holes in there.
+ *
+ * Return 0 on success, 1 on invalid block range
+ * and < 0 on fatal error.
+ */
+static int ext4_clear_blocks(handle_t *handle, struct inode *inode,
+                            struct buffer_head *bh,
+                            ext4_fsblk_t block_to_free,
+                            unsigned long count, __le32 *first,
+                            __le32 *last)
+{
+       __le32 *p;
+       int     flags = EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_VALIDATED;
+       int     err;
+
+       if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+               flags |= EXT4_FREE_BLOCKS_METADATA;
+
+       if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), block_to_free,
+                                  count)) {
+               EXT4_ERROR_INODE(inode, "attempt to clear invalid "
+                                "blocks %llu len %lu",
+                                (unsigned long long) block_to_free, count);
+               return 1;
+       }
+
+       if (try_to_extend_transaction(handle, inode)) {
+               if (bh) {
+                       BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+                       err = ext4_handle_dirty_metadata(handle, inode, bh);
+                       if (unlikely(err))
+                               goto out_err;
+               }
+               err = ext4_mark_inode_dirty(handle, inode);
+               if (unlikely(err))
+                       goto out_err;
+               err = ext4_truncate_restart_trans(handle, inode,
+                                       ext4_blocks_for_truncate(inode));
+               if (unlikely(err))
+                       goto out_err;
+               if (bh) {
+                       BUFFER_TRACE(bh, "retaking write access");
+                       err = ext4_journal_get_write_access(handle, bh);
+                       if (unlikely(err))
+                               goto out_err;
+               }
+       }
+
+       for (p = first; p < last; p++)
+               *p = 0;
+
+       ext4_free_blocks(handle, inode, NULL, block_to_free, count, flags);
+       return 0;
+out_err:
+       ext4_std_error(inode->i_sb, err);
+       return err;
+}
+
+/**
+ * ext4_free_data - free a list of data blocks
+ * @handle:    handle for this transaction
+ * @inode:     inode we are dealing with
+ * @this_bh:   indirect buffer_head which contains *@first and *@last
+ * @first:     array of block numbers
+ * @last:      points immediately past the end of array
+ *
+ * We are freeing all blocks referred from that array (numbers are stored as
+ * little-endian 32-bit) and updating @inode->i_blocks appropriately.
+ *
+ * We accumulate contiguous runs of blocks to free.  Conveniently, if these
+ * blocks are contiguous then releasing them at one time will only affect one
+ * or two bitmap blocks (+ group descriptor(s) and superblock) and we won't
+ * actually use a lot of journal space.
+ *
+ * @this_bh will be %NULL if @first and @last point into the inode's direct
+ * block pointers.
+ */
+static void ext4_free_data(handle_t *handle, struct inode *inode,
+                          struct buffer_head *this_bh,
+                          __le32 *first, __le32 *last)
+{
+       ext4_fsblk_t block_to_free = 0;    /* Starting block # of a run */
+       unsigned long count = 0;            /* Number of blocks in the run */
+       __le32 *block_to_free_p = NULL;     /* Pointer into inode/ind
+                                              corresponding to
+                                              block_to_free */
+       ext4_fsblk_t nr;                    /* Current block # */
+       __le32 *p;                          /* Pointer into inode/ind
+                                              for current block */
+       int err = 0;
+
+       if (this_bh) {                          /* For indirect block */
+               BUFFER_TRACE(this_bh, "get_write_access");
+               err = ext4_journal_get_write_access(handle, this_bh);
+               /* Important: if we can't update the indirect pointers
+                * to the blocks, we can't free them. */
+               if (err)
+                       return;
+       }
+
+       for (p = first; p < last; p++) {
+               nr = le32_to_cpu(*p);
+               if (nr) {
+                       /* accumulate blocks to free if they're contiguous */
+                       if (count == 0) {
+                               block_to_free = nr;
+                               block_to_free_p = p;
+                               count = 1;
+                       } else if (nr == block_to_free + count) {
+                               count++;
+                       } else {
+                               err = ext4_clear_blocks(handle, inode, this_bh,
+                                                       block_to_free, count,
+                                                       block_to_free_p, p);
+                               if (err)
+                                       break;
+                               block_to_free = nr;
+                               block_to_free_p = p;
+                               count = 1;
+                       }
+               }
+       }
+
+       if (!err && count > 0)
+               err = ext4_clear_blocks(handle, inode, this_bh, block_to_free,
+                                       count, block_to_free_p, p);
+       if (err < 0)
+               /* fatal error */
+               return;
+
+       if (this_bh) {
+               BUFFER_TRACE(this_bh, "call ext4_handle_dirty_metadata");
+
+               /*
+                * The buffer head should have an attached journal head at this
+                * point. However, if the data is corrupted and an indirect
+                * block pointed to itself, it would have been detached when
+                * the block was cleared. Check for this instead of OOPSing.
+                */
+               if ((EXT4_JOURNAL(inode) == NULL) || bh2jh(this_bh))
+                       ext4_handle_dirty_metadata(handle, inode, this_bh);
+               else
+                       EXT4_ERROR_INODE(inode,
+                                        "circular indirect block detected at "
+                                        "block %llu",
+                               (unsigned long long) this_bh->b_blocknr);
+       }
+}
+
+/**
+ *     ext4_free_branches - free an array of branches
+ *     @handle: JBD handle for this transaction
+ *     @inode: inode we are dealing with
+ *     @parent_bh: the buffer_head which contains *@first and *@last
+ *     @first: array of block numbers
+ *     @last:  pointer immediately past the end of array
+ *     @depth: depth of the branches to free
+ *
+ *     We are freeing all blocks referred from these branches (numbers are
+ *     stored as little-endian 32-bit) and updating @inode->i_blocks
+ *     appropriately.
+ */
+static void ext4_free_branches(handle_t *handle, struct inode *inode,
+                              struct buffer_head *parent_bh,
+                              __le32 *first, __le32 *last, int depth)
+{
+       ext4_fsblk_t nr;
+       __le32 *p;
+
+       if (ext4_handle_is_aborted(handle))
+               return;
+
+       if (depth--) {
+               struct buffer_head *bh;
+               int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+               p = last;
+               while (--p >= first) {
+                       nr = le32_to_cpu(*p);
+                       if (!nr)
+                               continue;               /* A hole */
+
+                       if (!ext4_data_block_valid(EXT4_SB(inode->i_sb),
+                                                  nr, 1)) {
+                               EXT4_ERROR_INODE(inode,
+                                                "invalid indirect mapped "
+                                                "block %lu (level %d)",
+                                                (unsigned long) nr, depth);
+                               break;
+                       }
+
+                       /* Go read the buffer for the next level down */
+                       bh = sb_bread(inode->i_sb, nr);
+
+                       /*
+                        * A read failure? Report error and clear slot
+                        * (should be rare).
+                        */
+                       if (!bh) {
+                               EXT4_ERROR_INODE_BLOCK(inode, nr,
+                                                      "Read failure");
+                               continue;
+                       }
+
+                       /* This zaps the entire block.  Bottom up. */
+                       BUFFER_TRACE(bh, "free child branches");
+                       ext4_free_branches(handle, inode, bh,
+                                       (__le32 *) bh->b_data,
+                                       (__le32 *) bh->b_data + addr_per_block,
+                                       depth);
+                       brelse(bh);
+
+                       /*
+                        * Everything below this this pointer has been
+                        * released.  Now let this top-of-subtree go.
+                        *
+                        * We want the freeing of this indirect block to be
+                        * atomic in the journal with the updating of the
+                        * bitmap block which owns it.  So make some room in
+                        * the journal.
+                        *
+                        * We zero the parent pointer *after* freeing its
+                        * pointee in the bitmaps, so if extend_transaction()
+                        * for some reason fails to put the bitmap changes and
+                        * the release into the same transaction, recovery
+                        * will merely complain about releasing a free block,
+                        * rather than leaking blocks.
+                        */
+                       if (ext4_handle_is_aborted(handle))
+                               return;
+                       if (try_to_extend_transaction(handle, inode)) {
+                               ext4_mark_inode_dirty(handle, inode);
+                               ext4_truncate_restart_trans(handle, inode,
+                                           ext4_blocks_for_truncate(inode));
+                       }
+
+                       /*
+                        * The forget flag here is critical because if
+                        * we are journaling (and not doing data
+                        * journaling), we have to make sure a revoke
+                        * record is written to prevent the journal
+                        * replay from overwriting the (former)
+                        * indirect block if it gets reallocated as a
+                        * data block.  This must happen in the same
+                        * transaction where the data blocks are
+                        * actually freed.
+                        */
+                       ext4_free_blocks(handle, inode, NULL, nr, 1,
+                                        EXT4_FREE_BLOCKS_METADATA|
+                                        EXT4_FREE_BLOCKS_FORGET);
+
+                       if (parent_bh) {
+                               /*
+                                * The block which we have just freed is
+                                * pointed to by an indirect block: journal it
+                                */
+                               BUFFER_TRACE(parent_bh, "get_write_access");
+                               if (!ext4_journal_get_write_access(handle,
+                                                                  parent_bh)){
+                                       *p = 0;
+                                       BUFFER_TRACE(parent_bh,
+                                       "call ext4_handle_dirty_metadata");
+                                       ext4_handle_dirty_metadata(handle,
+                                                                  inode,
+                                                                  parent_bh);
+                               }
+                       }
+               }
+       } else {
+               /* We have reached the bottom of the tree. */
+               BUFFER_TRACE(parent_bh, "free data blocks");
+               ext4_free_data(handle, inode, parent_bh, first, last);
+       }
+}
+
+void ext4_ind_truncate(struct inode *inode)
+{
+       handle_t *handle;
+       struct ext4_inode_info *ei = EXT4_I(inode);
+       __le32 *i_data = ei->i_data;
+       int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+       struct address_space *mapping = inode->i_mapping;
+       ext4_lblk_t offsets[4];
+       Indirect chain[4];
+       Indirect *partial;
+       __le32 nr = 0;
+       int n = 0;
+       ext4_lblk_t last_block, max_block;
+       unsigned blocksize = inode->i_sb->s_blocksize;
+
+       handle = start_transaction(inode);
+       if (IS_ERR(handle))
+               return;         /* AKPM: return what? */
+
+       last_block = (inode->i_size + blocksize-1)
+                                       >> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
+       max_block = (EXT4_SB(inode->i_sb)->s_bitmap_maxbytes + blocksize-1)
+                                       >> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
+
+       if (inode->i_size & (blocksize - 1))
+               if (ext4_block_truncate_page(handle, mapping, inode->i_size))
+                       goto out_stop;
+
+       if (last_block != max_block) {
+               n = ext4_block_to_path(inode, last_block, offsets, NULL);
+               if (n == 0)
+                       goto out_stop;  /* error */
+       }
+
+       /*
+        * OK.  This truncate is going to happen.  We add the inode to the
+        * orphan list, so that if this truncate spans multiple transactions,
+        * and we crash, we will resume the truncate when the filesystem
+        * recovers.  It also marks the inode dirty, to catch the new size.
+        *
+        * Implication: the file must always be in a sane, consistent
+        * truncatable state while each transaction commits.
+        */
+       if (ext4_orphan_add(handle, inode))
+               goto out_stop;
+
+       /*
+        * From here we block out all ext4_get_block() callers who want to
+        * modify the block allocation tree.
+        */
+       down_write(&ei->i_data_sem);
+
+       ext4_discard_preallocations(inode);
+
+       /*
+        * The orphan list entry will now protect us from any crash which
+        * occurs before the truncate completes, so it is now safe to propagate
+        * the new, shorter inode size (held for now in i_size) into the
+        * on-disk inode. We do this via i_disksize, which is the value which
+        * ext4 *really* writes onto the disk inode.
+        */
+       ei->i_disksize = inode->i_size;
+
+       if (last_block == max_block) {
+               /*
+                * It is unnecessary to free any data blocks if last_block is
+                * equal to the indirect block limit.
+                */
+               goto out_unlock;
+       } else if (n == 1) {            /* direct blocks */
+               ext4_free_data(handle, inode, NULL, i_data+offsets[0],
+                              i_data + EXT4_NDIR_BLOCKS);
+               goto do_indirects;
+       }
+
+       partial = ext4_find_shared(inode, n, offsets, chain, &nr);
+       /* Kill the top of shared branch (not detached) */
+       if (nr) {
+               if (partial == chain) {
+                       /* Shared branch grows from the inode */
+                       ext4_free_branches(handle, inode, NULL,
+                                          &nr, &nr+1, (chain+n-1) - partial);
+                       *partial->p = 0;
+                       /*
+                        * We mark the inode dirty prior to restart,
+                        * and prior to stop.  No need for it here.
+                        */
+               } else {
+                       /* Shared branch grows from an indirect block */
+                       BUFFER_TRACE(partial->bh, "get_write_access");
+                       ext4_free_branches(handle, inode, partial->bh,
+                                       partial->p,
+                                       partial->p+1, (chain+n-1) - partial);
+               }
+       }
+       /* Clear the ends of indirect blocks on the shared branch */
+       while (partial > chain) {
+               ext4_free_branches(handle, inode, partial->bh, partial->p + 1,
+                                  (__le32*)partial->bh->b_data+addr_per_block,
+                                  (chain+n-1) - partial);
+               BUFFER_TRACE(partial->bh, "call brelse");
+               brelse(partial->bh);
+               partial--;
+       }
+do_indirects:
+       /* Kill the remaining (whole) subtrees */
+       switch (offsets[0]) {
+       default:
+               nr = i_data[EXT4_IND_BLOCK];
+               if (nr) {
+                       ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
+                       i_data[EXT4_IND_BLOCK] = 0;
+               }
+       case EXT4_IND_BLOCK:
+               nr = i_data[EXT4_DIND_BLOCK];
+               if (nr) {
+                       ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
+                       i_data[EXT4_DIND_BLOCK] = 0;
+               }
+       case EXT4_DIND_BLOCK:
+               nr = i_data[EXT4_TIND_BLOCK];
+               if (nr) {
+                       ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
+                       i_data[EXT4_TIND_BLOCK] = 0;
+               }
+       case EXT4_TIND_BLOCK:
+               ;
+       }
+
+out_unlock:
+       up_write(&ei->i_data_sem);
+       inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
+       ext4_mark_inode_dirty(handle, inode);
+
+       /*
+        * In a multi-transaction truncate, we only make the final transaction
+        * synchronous
+        */
+       if (IS_SYNC(inode))
+               ext4_handle_sync(handle);
+out_stop:
+       /*
+        * If this was a simple ftruncate(), and the file will remain alive
+        * then we need to clear up the orphan record which we created above.
+        * However, if this was a real unlink then we were called by
+        * ext4_delete_inode(), and we allow that function to clean up the
+        * orphan info for us.
+        */
+       if (inode->i_nlink)
+               ext4_orphan_del(handle, inode);
+
+       ext4_journal_stop(handle);
+       trace_ext4_truncate_exit(inode);
+}
+
index 3e5191f..d47264c 100644 (file)
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
- *  Goal-directed block allocation by Stephen Tweedie
- *     (sct@redhat.com), 1993, 1998
- *  Big-endian to little-endian byte-swapping/bitmaps by
- *        David S. Miller (davem@caip.rutgers.edu), 1995
  *  64-bit file support on 64-bit platforms by Jakub Jelinek
  *     (jj@sunsite.ms.mff.cuni.cz)
  *
@@ -47,6 +43,7 @@
 #include "xattr.h"
 #include "acl.h"
 #include "ext4_extents.h"
+#include "truncate.h"
 
 #include <trace/events/ext4.h>
 
@@ -88,72 +85,6 @@ static int ext4_inode_is_fast_symlink(struct inode *inode)
        return (S_ISLNK(inode->i_mode) && inode->i_blocks - ea_blocks == 0);
 }
 
-/*
- * Work out how many blocks we need to proceed with the next chunk of a
- * truncate transaction.
- */
-static unsigned long blocks_for_truncate(struct inode *inode)
-{
-       ext4_lblk_t needed;
-
-       needed = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9);
-
-       /* Give ourselves just enough room to cope with inodes in which
-        * i_blocks is corrupt: we've seen disk corruptions in the past
-        * which resulted in random data in an inode which looked enough
-        * like a regular file for ext4 to try to delete it.  Things
-        * will go a bit crazy if that happens, but at least we should
-        * try not to panic the whole kernel. */
-       if (needed < 2)
-               needed = 2;
-
-       /* But we need to bound the transaction so we don't overflow the
-        * journal. */
-       if (needed > EXT4_MAX_TRANS_DATA)
-               needed = EXT4_MAX_TRANS_DATA;
-
-       return EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
-}
-
-/*
- * Truncate transactions can be complex and absolutely huge.  So we need to
- * be able to restart the transaction at a conventient checkpoint to make
- * sure we don't overflow the journal.
- *
- * start_transaction gets us a new handle for a truncate transaction,
- * and extend_transaction tries to extend the existing one a bit.  If
- * extend fails, we need to propagate the failure up and restart the
- * transaction in the top-level truncate loop. --sct
- */
-static handle_t *start_transaction(struct inode *inode)
-{
-       handle_t *result;
-
-       result = ext4_journal_start(inode, blocks_for_truncate(inode));
-       if (!IS_ERR(result))
-               return result;
-
-       ext4_std_error(inode->i_sb, PTR_ERR(result));
-       return result;
-}
-
-/*
- * Try to extend this transaction for the purposes of truncation.
- *
- * Returns 0 if we managed to create more room.  If we can't create more
- * room, and the transaction must be restarted we return 1.
- */
-static int try_to_extend_transaction(handle_t *handle, struct inode *inode)
-{
-       if (!ext4_handle_valid(handle))
-               return 0;
-       if (ext4_handle_has_enough_credits(handle, EXT4_RESERVE_TRANS_BLOCKS+1))
-               return 0;
-       if (!ext4_journal_extend(handle, blocks_for_truncate(inode)))
-               return 0;
-       return 1;
-}
-
 /*
  * Restart the transaction associated with *handle.  This does a commit,
  * so before we call here everything must be consistently dirtied against
@@ -190,6 +121,33 @@ void ext4_evict_inode(struct inode *inode)
 
        trace_ext4_evict_inode(inode);
        if (inode->i_nlink) {
+               /*
+                * When journalling data dirty buffers are tracked only in the
+                * journal. So although mm thinks everything is clean and
+                * ready for reaping the inode might still have some pages to
+                * write in the running transaction or waiting to be
+                * checkpointed. Thus calling jbd2_journal_invalidatepage()
+                * (via truncate_inode_pages()) to discard these buffers can
+                * cause data loss. Also even if we did not discard these
+                * buffers, we would have no way to find them after the inode
+                * is reaped and thus user could see stale data if he tries to
+                * read them before the transaction is checkpointed. So be
+                * careful and force everything to disk here... We use
+                * ei->i_datasync_tid to store the newest transaction
+                * containing inode's data.
+                *
+                * Note that directories do not have this problem because they
+                * don't use page cache.
+                */
+               if (ext4_should_journal_data(inode) &&
+                   (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) {
+                       journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
+                       tid_t commit_tid = EXT4_I(inode)->i_datasync_tid;
+
+                       jbd2_log_start_commit(journal, commit_tid);
+                       jbd2_log_wait_commit(journal, commit_tid);
+                       filemap_write_and_wait(&inode->i_data);
+               }
                truncate_inode_pages(&inode->i_data, 0);
                goto no_delete;
        }
@@ -204,7 +162,7 @@ void ext4_evict_inode(struct inode *inode)
        if (is_bad_inode(inode))
                goto no_delete;
 
-       handle = ext4_journal_start(inode, blocks_for_truncate(inode)+3);
+       handle = ext4_journal_start(inode, ext4_blocks_for_truncate(inode)+3);
        if (IS_ERR(handle)) {
                ext4_std_error(inode->i_sb, PTR_ERR(handle));
                /*
@@ -277,793 +235,6 @@ no_delete:
        ext4_clear_inode(inode);        /* We must guarantee clearing of inode... */
 }
 
-typedef struct {
-       __le32  *p;
-       __le32  key;
-       struct buffer_head *bh;
-} Indirect;
-
-static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v)
-{
-       p->key = *(p->p = v);
-       p->bh = bh;
-}
-
-/**
- *     ext4_block_to_path - parse the block number into array of offsets
- *     @inode: inode in question (we are only interested in its superblock)
- *     @i_block: block number to be parsed
- *     @offsets: array to store the offsets in
- *     @boundary: set this non-zero if the referred-to block is likely to be
- *            followed (on disk) by an indirect block.
- *
- *     To store the locations of file's data ext4 uses a data structure common
- *     for UNIX filesystems - tree of pointers anchored in the inode, with
- *     data blocks at leaves and indirect blocks in intermediate nodes.
- *     This function translates the block number into path in that tree -
- *     return value is the path length and @offsets[n] is the offset of
- *     pointer to (n+1)th node in the nth one. If @block is out of range
- *     (negative or too large) warning is printed and zero returned.
- *
- *     Note: function doesn't find node addresses, so no IO is needed. All
- *     we need to know is the capacity of indirect blocks (taken from the
- *     inode->i_sb).
- */
-
-/*
- * Portability note: the last comparison (check that we fit into triple
- * indirect block) is spelled differently, because otherwise on an
- * architecture with 32-bit longs and 8Kb pages we might get into trouble
- * if our filesystem had 8Kb blocks. We might use long long, but that would
- * kill us on x86. Oh, well, at least the sign propagation does not matter -
- * i_block would have to be negative in the very beginning, so we would not
- * get there at all.
- */
-
-static int ext4_block_to_path(struct inode *inode,
-                             ext4_lblk_t i_block,
-                             ext4_lblk_t offsets[4], int *boundary)
-{
-       int ptrs = EXT4_ADDR_PER_BLOCK(inode->i_sb);
-       int ptrs_bits = EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb);
-       const long direct_blocks = EXT4_NDIR_BLOCKS,
-               indirect_blocks = ptrs,
-               double_blocks = (1 << (ptrs_bits * 2));
-       int n = 0;
-       int final = 0;
-
-       if (i_block < direct_blocks) {
-               offsets[n++] = i_block;
-               final = direct_blocks;
-       } else if ((i_block -= direct_blocks) < indirect_blocks) {
-               offsets[n++] = EXT4_IND_BLOCK;
-               offsets[n++] = i_block;
-               final = ptrs;
-       } else if ((i_block -= indirect_blocks) < double_blocks) {
-               offsets[n++] = EXT4_DIND_BLOCK;
-               offsets[n++] = i_block >> ptrs_bits;
-               offsets[n++] = i_block & (ptrs - 1);
-               final = ptrs;
-       } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) {
-               offsets[n++] = EXT4_TIND_BLOCK;
-               offsets[n++] = i_block >> (ptrs_bits * 2);
-               offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1);
-               offsets[n++] = i_block & (ptrs - 1);
-               final = ptrs;
-       } else {
-               ext4_warning(inode->i_sb, "block %lu > max in inode %lu",
-                            i_block + direct_blocks +
-                            indirect_blocks + double_blocks, inode->i_ino);
-       }
-       if (boundary)
-               *boundary = final - 1 - (i_block & (ptrs - 1));
-       return n;
-}
-
-static int __ext4_check_blockref(const char *function, unsigned int line,
-                                struct inode *inode,
-                                __le32 *p, unsigned int max)
-{
-       struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
-       __le32 *bref = p;
-       unsigned int blk;
-
-       while (bref < p+max) {
-               blk = le32_to_cpu(*bref++);
-               if (blk &&
-                   unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
-                                                   blk, 1))) {
-                       es->s_last_error_block = cpu_to_le64(blk);
-                       ext4_error_inode(inode, function, line, blk,
-                                        "invalid block");
-                       return -EIO;
-               }
-       }
-       return 0;
-}
-
-
-#define ext4_check_indirect_blockref(inode, bh)                         \
-       __ext4_check_blockref(__func__, __LINE__, inode,                \
-                             (__le32 *)(bh)->b_data,                   \
-                             EXT4_ADDR_PER_BLOCK((inode)->i_sb))
-
-#define ext4_check_inode_blockref(inode)                                \
-       __ext4_check_blockref(__func__, __LINE__, inode,                \
-                             EXT4_I(inode)->i_data,                    \
-                             EXT4_NDIR_BLOCKS)
-
-/**
- *     ext4_get_branch - read the chain of indirect blocks leading to data
- *     @inode: inode in question
- *     @depth: depth of the chain (1 - direct pointer, etc.)
- *     @offsets: offsets of pointers in inode/indirect blocks
- *     @chain: place to store the result
- *     @err: here we store the error value
- *
- *     Function fills the array of triples <key, p, bh> and returns %NULL
- *     if everything went OK or the pointer to the last filled triple
- *     (incomplete one) otherwise. Upon the return chain[i].key contains
- *     the number of (i+1)-th block in the chain (as it is stored in memory,
- *     i.e. little-endian 32-bit), chain[i].p contains the address of that
- *     number (it points into struct inode for i==0 and into the bh->b_data
- *     for i>0) and chain[i].bh points to the buffer_head of i-th indirect
- *     block for i>0 and NULL for i==0. In other words, it holds the block
- *     numbers of the chain, addresses they were taken from (and where we can
- *     verify that chain did not change) and buffer_heads hosting these
- *     numbers.
- *
- *     Function stops when it stumbles upon zero pointer (absent block)
- *             (pointer to last triple returned, *@err == 0)
- *     or when it gets an IO error reading an indirect block
- *             (ditto, *@err == -EIO)
- *     or when it reads all @depth-1 indirect blocks successfully and finds
- *     the whole chain, all way to the data (returns %NULL, *err == 0).
- *
- *      Need to be called with
- *      down_read(&EXT4_I(inode)->i_data_sem)
- */
-static Indirect *ext4_get_branch(struct inode *inode, int depth,
-                                ext4_lblk_t  *offsets,
-                                Indirect chain[4], int *err)
-{
-       struct super_block *sb = inode->i_sb;
-       Indirect *p = chain;
-       struct buffer_head *bh;
-
-       *err = 0;
-       /* i_data is not going away, no lock needed */
-       add_chain(chain, NULL, EXT4_I(inode)->i_data + *offsets);
-       if (!p->key)
-               goto no_block;
-       while (--depth) {
-               bh = sb_getblk(sb, le32_to_cpu(p->key));
-               if (unlikely(!bh))
-                       goto failure;
-
-               if (!bh_uptodate_or_lock(bh)) {
-                       if (bh_submit_read(bh) < 0) {
-                               put_bh(bh);
-                               goto failure;
-                       }
-                       /* validate block references */
-                       if (ext4_check_indirect_blockref(inode, bh)) {
-                               put_bh(bh);
-                               goto failure;
-                       }
-               }
-
-               add_chain(++p, bh, (__le32 *)bh->b_data + *++offsets);
-               /* Reader: end */
-               if (!p->key)
-                       goto no_block;
-       }
-       return NULL;
-
-failure:
-       *err = -EIO;
-no_block:
-       return p;
-}
-
-/**
- *     ext4_find_near - find a place for allocation with sufficient locality
- *     @inode: owner
- *     @ind: descriptor of indirect block.
- *
- *     This function returns the preferred place for block allocation.
- *     It is used when heuristic for sequential allocation fails.
- *     Rules are:
- *       + if there is a block to the left of our position - allocate near it.
- *       + if pointer will live in indirect block - allocate near that block.
- *       + if pointer will live in inode - allocate in the same
- *         cylinder group.
- *
- * In the latter case we colour the starting block by the callers PID to
- * prevent it from clashing with concurrent allocations for a different inode
- * in the same block group.   The PID is used here so that functionally related
- * files will be close-by on-disk.
- *
- *     Caller must make sure that @ind is valid and will stay that way.
- */
-static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind)
-{
-       struct ext4_inode_info *ei = EXT4_I(inode);
-       __le32 *start = ind->bh ? (__le32 *) ind->bh->b_data : ei->i_data;
-       __le32 *p;
-       ext4_fsblk_t bg_start;
-       ext4_fsblk_t last_block;
-       ext4_grpblk_t colour;
-       ext4_group_t block_group;
-       int flex_size = ext4_flex_bg_size(EXT4_SB(inode->i_sb));
-
-       /* Try to find previous block */
-       for (p = ind->p - 1; p >= start; p--) {
-               if (*p)
-                       return le32_to_cpu(*p);
-       }
-
-       /* No such thing, so let's try location of indirect block */
-       if (ind->bh)
-               return ind->bh->b_blocknr;
-
-       /*
-        * It is going to be referred to from the inode itself? OK, just put it
-        * into the same cylinder group then.
-        */
-       block_group = ei->i_block_group;
-       if (flex_size >= EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME) {
-               block_group &= ~(flex_size-1);
-               if (S_ISREG(inode->i_mode))
-                       block_group++;
-       }
-       bg_start = ext4_group_first_block_no(inode->i_sb, block_group);
-       last_block = ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es) - 1;
-
-       /*
-        * If we are doing delayed allocation, we don't need take
-        * colour into account.
-        */
-       if (test_opt(inode->i_sb, DELALLOC))
-               return bg_start;
-
-       if (bg_start + EXT4_BLOCKS_PER_GROUP(inode->i_sb) <= last_block)
-               colour = (current->pid % 16) *
-                       (EXT4_BLOCKS_PER_GROUP(inode->i_sb) / 16);
-       else
-               colour = (current->pid % 16) * ((last_block - bg_start) / 16);
-       return bg_start + colour;
-}
-
-/**
- *     ext4_find_goal - find a preferred place for allocation.
- *     @inode: owner
- *     @block:  block we want
- *     @partial: pointer to the last triple within a chain
- *
- *     Normally this function find the preferred place for block allocation,
- *     returns it.
- *     Because this is only used for non-extent files, we limit the block nr
- *     to 32 bits.
- */
-static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
-                                  Indirect *partial)
-{
-       ext4_fsblk_t goal;
-
-       /*
-        * XXX need to get goal block from mballoc's data structures
-        */
-
-       goal = ext4_find_near(inode, partial);
-       goal = goal & EXT4_MAX_BLOCK_FILE_PHYS;
-       return goal;
-}
-
-/**
- *     ext4_blks_to_allocate - Look up the block map and count the number
- *     of direct blocks need to be allocated for the given branch.
- *
- *     @branch: chain of indirect blocks
- *     @k: number of blocks need for indirect blocks
- *     @blks: number of data blocks to be mapped.
- *     @blocks_to_boundary:  the offset in the indirect block
- *
- *     return the total number of blocks to be allocate, including the
- *     direct and indirect blocks.
- */
-static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
-                                int blocks_to_boundary)
-{
-       unsigned int count = 0;
-
-       /*
-        * Simple case, [t,d]Indirect block(s) has not allocated yet
-        * then it's clear blocks on that path have not allocated
-        */
-       if (k > 0) {
-               /* right now we don't handle cross boundary allocation */
-               if (blks < blocks_to_boundary + 1)
-                       count += blks;
-               else
-                       count += blocks_to_boundary + 1;
-               return count;
-       }
-
-       count++;
-       while (count < blks && count <= blocks_to_boundary &&
-               le32_to_cpu(*(branch[0].p + count)) == 0) {
-               count++;
-       }
-       return count;
-}
-
-/**
- *     ext4_alloc_blocks: multiple allocate blocks needed for a branch
- *     @handle: handle for this transaction
- *     @inode: inode which needs allocated blocks
- *     @iblock: the logical block to start allocated at
- *     @goal: preferred physical block of allocation
- *     @indirect_blks: the number of blocks need to allocate for indirect
- *                     blocks
- *     @blks: number of desired blocks
- *     @new_blocks: on return it will store the new block numbers for
- *     the indirect blocks(if needed) and the first direct block,
- *     @err: on return it will store the error code
- *
- *     This function will return the number of blocks allocated as
- *     requested by the passed-in parameters.
- */
-static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
-                            ext4_lblk_t iblock, ext4_fsblk_t goal,
-                            int indirect_blks, int blks,
-                            ext4_fsblk_t new_blocks[4], int *err)
-{
-       struct ext4_allocation_request ar;
-       int target, i;
-       unsigned long count = 0, blk_allocated = 0;
-       int index = 0;
-       ext4_fsblk_t current_block = 0;
-       int ret = 0;
-
-       /*
-        * Here we try to allocate the requested multiple blocks at once,
-        * on a best-effort basis.
-        * To build a branch, we should allocate blocks for
-        * the indirect blocks(if not allocated yet), and at least
-        * the first direct block of this branch.  That's the
-        * minimum number of blocks need to allocate(required)
-        */
-       /* first we try to allocate the indirect blocks */
-       target = indirect_blks;
-       while (target > 0) {
-               count = target;
-               /* allocating blocks for indirect blocks and direct blocks */
-               current_block = ext4_new_meta_blocks(handle, inode, goal,
-                                                    0, &count, err);
-               if (*err)
-                       goto failed_out;
-
-               if (unlikely(current_block + count > EXT4_MAX_BLOCK_FILE_PHYS)) {
-                       EXT4_ERROR_INODE(inode,
-                                        "current_block %llu + count %lu > %d!",
-                                        current_block, count,
-                                        EXT4_MAX_BLOCK_FILE_PHYS);
-                       *err = -EIO;
-                       goto failed_out;
-               }
-
-               target -= count;
-               /* allocate blocks for indirect blocks */
-               while (index < indirect_blks && count) {
-                       new_blocks[index++] = current_block++;
-                       count--;
-               }
-               if (count > 0) {
-                       /*
-                        * save the new block number
-                        * for the first direct block
-                        */
-                       new_blocks[index] = current_block;
-                       printk(KERN_INFO "%s returned more blocks than "
-                                               "requested\n", __func__);
-                       WARN_ON(1);
-                       break;
-               }
-       }
-
-       target = blks - count ;
-       blk_allocated = count;
-       if (!target)
-               goto allocated;
-       /* Now allocate data blocks */
-       memset(&ar, 0, sizeof(ar));
-       ar.inode = inode;
-       ar.goal = goal;
-       ar.len = target;
-       ar.logical = iblock;
-       if (S_ISREG(inode->i_mode))
-               /* enable in-core preallocation only for regular files */
-               ar.flags = EXT4_MB_HINT_DATA;
-
-       current_block = ext4_mb_new_blocks(handle, &ar, err);
-       if (unlikely(current_block + ar.len > EXT4_MAX_BLOCK_FILE_PHYS)) {
-               EXT4_ERROR_INODE(inode,
-                                "current_block %llu + ar.len %d > %d!",
-                                current_block, ar.len,
-                                EXT4_MAX_BLOCK_FILE_PHYS);
-               *err = -EIO;
-               goto failed_out;
-       }
-
-       if (*err && (target == blks)) {
-               /*
-                * if the allocation failed and we didn't allocate
-                * any blocks before
-                */
-               goto failed_out;
-       }
-       if (!*err) {
-               if (target == blks) {
-                       /*
-                        * save the new block number
-                        * for the first direct block
-                        */
-                       new_blocks[index] = current_block;
-               }
-               blk_allocated += ar.len;
-       }
-allocated:
-       /* total number of blocks allocated for direct blocks */
-       ret = blk_allocated;
-       *err = 0;
-       return ret;
-failed_out:
-       for (i = 0; i < index; i++)
-               ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0);
-       return ret;
-}
-
-/**
- *     ext4_alloc_branch - allocate and set up a chain of blocks.
- *     @handle: handle for this transaction
- *     @inode: owner
- *     @indirect_blks: number of allocated indirect blocks
- *     @blks: number of allocated direct blocks
- *     @goal: preferred place for allocation
- *     @offsets: offsets (in the blocks) to store the pointers to next.
- *     @branch: place to store the chain in.
- *
- *     This function allocates blocks, zeroes out all but the last one,
- *     links them into chain and (if we are synchronous) writes them to disk.
- *     In other words, it prepares a branch that can be spliced onto the
- *     inode. It stores the information about that chain in the branch[], in
- *     the same format as ext4_get_branch() would do. We are calling it after
- *     we had read the existing part of chain and partial points to the last
- *     triple of that (one with zero ->key). Upon the exit we have the same
- *     picture as after the successful ext4_get_block(), except that in one
- *     place chain is disconnected - *branch->p is still zero (we did not
- *     set the last link), but branch->key contains the number that should
- *     be placed into *branch->p to fill that gap.
- *
- *     If allocation fails we free all blocks we've allocated (and forget
- *     their buffer_heads) and return the error value the from failed
- *     ext4_alloc_block() (normally -ENOSPC). Otherwise we set the chain
- *     as described above and return 0.
- */
-static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
-                            ext4_lblk_t iblock, int indirect_blks,
-                            int *blks, ext4_fsblk_t goal,
-                            ext4_lblk_t *offsets, Indirect *branch)
-{
-       int blocksize = inode->i_sb->s_blocksize;
-       int i, n = 0;
-       int err = 0;
-       struct buffer_head *bh;
-       int num;
-       ext4_fsblk_t new_blocks[4];
-       ext4_fsblk_t current_block;
-
-       num = ext4_alloc_blocks(handle, inode, iblock, goal, indirect_blks,
-                               *blks, new_blocks, &err);
-       if (err)
-               return err;
-
-       branch[0].key = cpu_to_le32(new_blocks[0]);
-       /*
-        * metadata blocks and data blocks are allocated.
-        */
-       for (n = 1; n <= indirect_blks;  n++) {
-               /*
-                * Get buffer_head for parent block, zero it out
-                * and set the pointer to new one, then send
-                * parent to disk.
-                */
-               bh = sb_getblk(inode->i_sb, new_blocks[n-1]);
-               if (unlikely(!bh)) {
-                       err = -EIO;
-                       goto failed;
-               }
-
-               branch[n].bh = bh;
-               lock_buffer(bh);
-               BUFFER_TRACE(bh, "call get_create_access");
-               err = ext4_journal_get_create_access(handle, bh);
-               if (err) {
-                       /* Don't brelse(bh) here; it's done in
-                        * ext4_journal_forget() below */
-                       unlock_buffer(bh);
-                       goto failed;
-               }
-
-               memset(bh->b_data, 0, blocksize);
-               branch[n].p = (__le32 *) bh->b_data + offsets[n];
-               branch[n].key = cpu_to_le32(new_blocks[n]);
-               *branch[n].p = branch[n].key;
-               if (n == indirect_blks) {
-                       current_block = new_blocks[n];
-                       /*
-                        * End of chain, update the last new metablock of
-                        * the chain to point to the new allocated
-                        * data blocks numbers
-                        */
-                       for (i = 1; i < num; i++)
-                               *(branch[n].p + i) = cpu_to_le32(++current_block);
-               }
-               BUFFER_TRACE(bh, "marking uptodate");
-               set_buffer_uptodate(bh);
-               unlock_buffer(bh);
-
-               BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
-               err = ext4_handle_dirty_metadata(handle, inode, bh);
-               if (err)
-                       goto failed;
-       }
-       *blks = num;
-       return err;
-failed:
-       /* Allocation failed, free what we already allocated */
-       ext4_free_blocks(handle, inode, NULL, new_blocks[0], 1, 0);
-       for (i = 1; i <= n ; i++) {
-               /*
-                * branch[i].bh is newly allocated, so there is no
-                * need to revoke the block, which is why we don't
-                * need to set EXT4_FREE_BLOCKS_METADATA.
-                */
-               ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1,
-                                EXT4_FREE_BLOCKS_FORGET);
-       }
-       for (i = n+1; i < indirect_blks; i++)
-               ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0);
-
-       ext4_free_blocks(handle, inode, NULL, new_blocks[i], num, 0);
-
-       return err;
-}
-
-/**
- * ext4_splice_branch - splice the allocated branch onto inode.
- * @handle: handle for this transaction
- * @inode: owner
- * @block: (logical) number of block we are adding
- * @chain: chain of indirect blocks (with a missing link - see
- *     ext4_alloc_branch)
- * @where: location of missing link
- * @num:   number of indirect blocks we are adding
- * @blks:  number of direct blocks we are adding
- *
- * This function fills the missing link and does all housekeeping needed in
- * inode (->i_blocks, etc.). In case of success we end up with the full
- * chain to new block and return 0.
- */
-static int ext4_splice_branch(handle_t *handle, struct inode *inode,
-                             ext4_lblk_t block, Indirect *where, int num,
-                             int blks)
-{
-       int i;
-       int err = 0;
-       ext4_fsblk_t current_block;
-
-       /*
-        * If we're splicing into a [td]indirect block (as opposed to the
-        * inode) then we need to get write access to the [td]indirect block
-        * before the splice.
-        */
-       if (where->bh) {
-               BUFFER_TRACE(where->bh, "get_write_access");
-               err = ext4_journal_get_write_access(handle, where->bh);
-               if (err)
-                       goto err_out;
-       }
-       /* That's it */
-
-       *where->p = where->key;
-
-       /*
-        * Update the host buffer_head or inode to point to more just allocated
-        * direct blocks blocks
-        */
-       if (num == 0 && blks > 1) {
-               current_block = le32_to_cpu(where->key) + 1;
-               for (i = 1; i < blks; i++)
-                       *(where->p + i) = cpu_to_le32(current_block++);
-       }
-
-       /* We are done with atomic stuff, now do the rest of housekeeping */
-       /* had we spliced it onto indirect block? */
-       if (where->bh) {
-               /*
-                * If we spliced it onto an indirect block, we haven't
-                * altered the inode.  Note however that if it is being spliced
-                * onto an indirect block at the very end of the file (the
-                * file is growing) then we *will* alter the inode to reflect
-                * the new i_size.  But that is not done here - it is done in
-                * generic_commit_write->__mark_inode_dirty->ext4_dirty_inode.
-                */
-               jbd_debug(5, "splicing indirect only\n");
-               BUFFER_TRACE(where->bh, "call ext4_handle_dirty_metadata");
-               err = ext4_handle_dirty_metadata(handle, inode, where->bh);
-               if (err)
-                       goto err_out;
-       } else {
-               /*
-                * OK, we spliced it into the inode itself on a direct block.
-                */
-               ext4_mark_inode_dirty(handle, inode);
-               jbd_debug(5, "splicing direct\n");
-       }
-       return err;
-
-err_out:
-       for (i = 1; i <= num; i++) {
-               /*
-                * branch[i].bh is newly allocated, so there is no
-                * need to revoke the block, which is why we don't
-                * need to set EXT4_FREE_BLOCKS_METADATA.
-                */
-               ext4_free_blocks(handle, inode, where[i].bh, 0, 1,
-                                EXT4_FREE_BLOCKS_FORGET);
-       }
-       ext4_free_blocks(handle, inode, NULL, le32_to_cpu(where[num].key),
-                        blks, 0);
-
-       return err;
-}
-
-/*
- * The ext4_ind_map_blocks() function handles non-extents inodes
- * (i.e., using the traditional indirect/double-indirect i_blocks
- * scheme) for ext4_map_blocks().
- *
- * Allocation strategy is simple: if we have to allocate something, we will
- * have to go the whole way to leaf. So let's do it before attaching anything
- * to tree, set linkage between the newborn blocks, write them if sync is
- * required, recheck the path, free and repeat if check fails, otherwise
- * set the last missing link (that will protect us from any truncate-generated
- * removals - all blocks on the path are immune now) and possibly force the
- * write on the parent block.
- * That has a nice additional property: no special recovery from the failed
- * allocations is needed - we simply release blocks and do not touch anything
- * reachable from inode.
- *
- * `handle' can be NULL if create == 0.
- *
- * return > 0, # of blocks mapped or allocated.
- * return = 0, if plain lookup failed.
- * return < 0, error case.
- *
- * The ext4_ind_get_blocks() function should be called with
- * down_write(&EXT4_I(inode)->i_data_sem) if allocating filesystem
- * blocks (i.e., flags has EXT4_GET_BLOCKS_CREATE set) or
- * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system
- * blocks.
- */
-static int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
-                              struct ext4_map_blocks *map,
-                              int flags)
-{
-       int err = -EIO;
-       ext4_lblk_t offsets[4];
-       Indirect chain[4];
-       Indirect *partial;
-       ext4_fsblk_t goal;
-       int indirect_blks;
-       int blocks_to_boundary = 0;
-       int depth;
-       int count = 0;
-       ext4_fsblk_t first_block = 0;
-
-       trace_ext4_ind_map_blocks_enter(inode, map->m_lblk, map->m_len, flags);
-       J_ASSERT(!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)));
-       J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0);
-       depth = ext4_block_to_path(inode, map->m_lblk, offsets,
-                                  &blocks_to_boundary);
-
-       if (depth == 0)
-               goto out;
-
-       partial = ext4_get_branch(inode, depth, offsets, chain, &err);
-
-       /* Simplest case - block found, no allocation needed */
-       if (!partial) {
-               first_block = le32_to_cpu(chain[depth - 1].key);
-               count++;
-               /*map more blocks*/
-               while (count < map->m_len && count <= blocks_to_boundary) {
-                       ext4_fsblk_t blk;
-
-                       blk = le32_to_cpu(*(chain[depth-1].p + count));
-
-                       if (blk == first_block + count)
-                               count++;
-                       else
-                               break;
-               }
-               goto got_it;
-       }
-
-       /* Next simple case - plain lookup or failed read of indirect block */
-       if ((flags & EXT4_GET_BLOCKS_CREATE) == 0 || err == -EIO)
-               goto cleanup;
-
-       /*
-        * Okay, we need to do block allocation.
-       */
-       goal = ext4_find_goal(inode, map->m_lblk, partial);
-
-       /* the number of blocks need to allocate for [d,t]indirect blocks */
-       indirect_blks = (chain + depth) - partial - 1;
-
-       /*
-        * Next look up the indirect map to count the totoal number of
-        * direct blocks to allocate for this branch.
-        */
-       count = ext4_blks_to_allocate(partial, indirect_blks,
-                                     map->m_len, blocks_to_boundary);
-       /*
-        * Block out ext4_truncate while we alter the tree
-        */
-       err = ext4_alloc_branch(handle, inode, map->m_lblk, indirect_blks,
-                               &count, goal,
-                               offsets + (partial - chain), partial);
-
-       /*
-        * The ext4_splice_branch call will free and forget any buffers
-        * on the new chain if there is a failure, but that risks using
-        * up transaction credits, especially for bitmaps where the
-        * credits cannot be returned.  Can we handle this somehow?  We
-        * may need to return -EAGAIN upwards in the worst case.  --sct
-        */
-       if (!err)
-               err = ext4_splice_branch(handle, inode, map->m_lblk,
-                                        partial, indirect_blks, count);
-       if (err)
-               goto cleanup;
-
-       map->m_flags |= EXT4_MAP_NEW;
-
-       ext4_update_inode_fsync_trans(handle, inode, 1);
-got_it:
-       map->m_flags |= EXT4_MAP_MAPPED;
-       map->m_pblk = le32_to_cpu(chain[depth-1].key);
-       map->m_len = count;
-       if (count > blocks_to_boundary)
-               map->m_flags |= EXT4_MAP_BOUNDARY;
-       err = count;
-       /* Clean up and exit */
-       partial = chain + depth - 1;    /* the whole chain */
-cleanup:
-       while (partial > chain) {
-               BUFFER_TRACE(partial->bh, "call brelse");
-               brelse(partial->bh);
-               partial--;
-       }
-out:
-       trace_ext4_ind_map_blocks_exit(inode, map->m_lblk,
-                               map->m_pblk, map->m_len, err);
-       return err;
-}
-
 #ifdef CONFIG_QUOTA
 qsize_t *ext4_get_reserved_space(struct inode *inode)
 {
@@ -1071,33 +242,6 @@ qsize_t *ext4_get_reserved_space(struct inode *inode)
 }
 #endif
 
-/*
- * Calculate the number of metadata blocks need to reserve
- * to allocate a new block at @lblocks for non extent file based file
- */
-static int ext4_indirect_calc_metadata_amount(struct inode *inode,
-                                             sector_t lblock)
-{
-       struct ext4_inode_info *ei = EXT4_I(inode);
-       sector_t dind_mask = ~((sector_t)EXT4_ADDR_PER_BLOCK(inode->i_sb) - 1);
-       int blk_bits;
-
-       if (lblock < EXT4_NDIR_BLOCKS)
-               return 0;
-
-       lblock -= EXT4_NDIR_BLOCKS;
-
-       if (ei->i_da_metadata_calc_len &&
-           (lblock & dind_mask) == ei->i_da_metadata_calc_last_lblock) {
-               ei->i_da_metadata_calc_len++;
-               return 0;
-       }
-       ei->i_da_metadata_calc_last_lblock = lblock & dind_mask;
-       ei->i_da_metadata_calc_len = 1;
-       blk_bits = order_base_2(lblock);
-       return (blk_bits / EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb)) + 1;
-}
-
 /*
  * Calculate the number of metadata blocks need to reserve
  * to allocate a block located at @lblock
@@ -1107,7 +251,7 @@ static int ext4_calc_metadata_amount(struct inode *inode, ext4_lblk_t lblock)
        if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
                return ext4_ext_calc_metadata_amount(inode, lblock);
 
-       return ext4_indirect_calc_metadata_amount(inode, lblock);
+       return ext4_ind_calc_metadata_amount(inode, lblock);
 }
 
 /*
@@ -1589,16 +733,6 @@ static int do_journal_get_write_access(handle_t *handle,
        return ret;
 }
 
-/*
- * Truncate blocks that were not used by write. We have to truncate the
- * pagecache as well so that corresponding buffers get properly unmapped.
- */
-static void ext4_truncate_failed_write(struct inode *inode)
-{
-       truncate_inode_pages(inode->i_mapping, inode->i_size);
-       ext4_truncate(inode);
-}
-
 static int ext4_get_block_write(struct inode *inode, sector_t iblock,
                   struct buffer_head *bh_result, int create);
 static int ext4_write_begin(struct file *file, struct address_space *mapping,
@@ -1863,6 +997,7 @@ static int ext4_journalled_write_end(struct file *file,
        if (new_i_size > inode->i_size)
                i_size_write(inode, pos+copied);
        ext4_set_inode_state(inode, EXT4_STATE_JDATA);
+       EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid;
        if (new_i_size > EXT4_I(inode)->i_disksize) {
                ext4_update_i_disksize(inode, new_i_size);
                ret2 = ext4_mark_inode_dirty(handle, inode);
@@ -2571,6 +1706,7 @@ static int __ext4_journalled_writepage(struct page *page,
                                write_end_fn);
        if (ret == 0)
                ret = err;
+       EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid;
        err = ext4_journal_stop(handle);
        if (!ret)
                ret = err;
@@ -3449,112 +2585,6 @@ static int ext4_releasepage(struct page *page, gfp_t wait)
                return try_to_free_buffers(page);
 }
 
-/*
- * O_DIRECT for ext3 (or indirect map) based files
- *
- * If the O_DIRECT write will extend the file then add this inode to the
- * orphan list.  So recovery will truncate it back to the original size
- * if the machine crashes during the write.
- *
- * If the O_DIRECT write is intantiating holes inside i_size and the machine
- * crashes then stale disk data _may_ be exposed inside the file. But current
- * VFS code falls back into buffered path in that case so we are safe.
- */
-static ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
-                             const struct iovec *iov, loff_t offset,
-                             unsigned long nr_segs)
-{
-       struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_mapping->host;
-       struct ext4_inode_info *ei = EXT4_I(inode);
-       handle_t *handle;
-       ssize_t ret;
-       int orphan = 0;
-       size_t count = iov_length(iov, nr_segs);
-       int retries = 0;
-
-       if (rw == WRITE) {
-               loff_t final_size = offset + count;
-
-               if (final_size > inode->i_size) {
-                       /* Credits for sb + inode write */
-                       handle = ext4_journal_start(inode, 2);
-                       if (IS_ERR(handle)) {
-                               ret = PTR_ERR(handle);
-                               goto out;
-                       }
-                       ret = ext4_orphan_add(handle, inode);
-                       if (ret) {
-                               ext4_journal_stop(handle);
-                               goto out;
-                       }
-                       orphan = 1;
-                       ei->i_disksize = inode->i_size;
-                       ext4_journal_stop(handle);
-               }
-       }
-
-retry:
-       if (rw == READ && ext4_should_dioread_nolock(inode))
-               ret = __blockdev_direct_IO(rw, iocb, inode,
-                                inode->i_sb->s_bdev, iov,
-                                offset, nr_segs,
-                                ext4_get_block, NULL, NULL, 0);
-       else {
-               ret = blockdev_direct_IO(rw, iocb, inode, iov,
-                                offset, nr_segs, ext4_get_block);
-
-               if (unlikely((rw & WRITE) && ret < 0)) {
-                       loff_t isize = i_size_read(inode);
-                       loff_t end = offset + iov_length(iov, nr_segs);
-
-                       if (end > isize)
-                               ext4_truncate_failed_write(inode);
-               }
-       }
-       if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
-               goto retry;
-
-       if (orphan) {
-               int err;
-
-               /* Credits for sb + inode write */
-               handle = ext4_journal_start(inode, 2);
-               if (IS_ERR(handle)) {
-                       /* This is really bad luck. We've written the data
-                        * but cannot extend i_size. Bail out and pretend
-                        * the write failed... */
-                       ret = PTR_ERR(handle);
-                       if (inode->i_nlink)
-                               ext4_orphan_del(NULL, inode);
-
-                       goto out;
-               }
-               if (inode->i_nlink)
-                       ext4_orphan_del(handle, inode);
-               if (ret > 0) {
-                       loff_t end = offset + ret;
-                       if (end > inode->i_size) {
-                               ei->i_disksize = end;
-                               i_size_write(inode, end);
-                               /*
-                                * We're going to return a positive `ret'
-                                * here due to non-zero-length I/O, so there's
-                                * no way of reporting error returns from
-                                * ext4_mark_inode_dirty() to userspace.  So
-                                * ignore it.
-                                */
-                               ext4_mark_inode_dirty(handle, inode);
-                       }
-               }
-               err = ext4_journal_stop(handle);
-               if (ret == 0)
-                       ret = err;
-       }
-out:
-       return ret;
-}
-
 /*
  * ext4_get_block used when preparing for a DIO write or buffer write.
  * We allocate an uinitialized extent if blocks haven't been allocated.
@@ -4033,383 +3063,6 @@ unlock:
        return err;
 }
 
-/*
- * Probably it should be a library function... search for first non-zero word
- * or memcmp with zero_page, whatever is better for particular architecture.
- * Linus?
- */
-static inline int all_zeroes(__le32 *p, __le32 *q)
-{
-       while (p < q)
-               if (*p++)
-                       return 0;
-       return 1;
-}
-
-/**
- *     ext4_find_shared - find the indirect blocks for partial truncation.
- *     @inode:   inode in question
- *     @depth:   depth of the affected branch
- *     @offsets: offsets of pointers in that branch (see ext4_block_to_path)
- *     @chain:   place to store the pointers to partial indirect blocks
- *     @top:     place to the (detached) top of branch
- *
- *     This is a helper function used by ext4_truncate().
- *
- *     When we do truncate() we may have to clean the ends of several
- *     indirect blocks but leave the blocks themselves alive. Block is
- *     partially truncated if some data below the new i_size is referred
- *     from it (and it is on the path to the first completely truncated
- *     data block, indeed).  We have to free the top of that path along
- *     with everything to the right of the path. Since no allocation
- *     past the truncation point is possible until ext4_truncate()
- *     finishes, we may safely do the latter, but top of branch may
- *     require special attention - pageout below the truncation point
- *     might try to populate it.
- *
- *     We atomically detach the top of branch from the tree, store the
- *     block number of its root in *@top, pointers to buffer_heads of
- *     partially truncated blocks - in @chain[].bh and pointers to
- *     their last elements that should not be removed - in
- *     @chain[].p. Return value is the pointer to last filled element
- *     of @chain.
- *
- *     The work left to caller to do the actual freeing of subtrees:
- *             a) free the subtree starting from *@top
- *             b) free the subtrees whose roots are stored in
- *                     (@chain[i].p+1 .. end of @chain[i].bh->b_data)
- *             c) free the subtrees growing from the inode past the @chain[0].
- *                     (no partially truncated stuff there).  */
-
-static Indirect *ext4_find_shared(struct inode *inode, int depth,
-                                 ext4_lblk_t offsets[4], Indirect chain[4],
-                                 __le32 *top)
-{
-       Indirect *partial, *p;
-       int k, err;
-
-       *top = 0;
-       /* Make k index the deepest non-null offset + 1 */
-       for (k = depth; k > 1 && !offsets[k-1]; k--)
-               ;
-       partial = ext4_get_branch(inode, k, offsets, chain, &err);
-       /* Writer: pointers */
-       if (!partial)
-               partial = chain + k-1;
-       /*
-        * If the branch acquired continuation since we've looked at it -
-        * fine, it should all survive and (new) top doesn't belong to us.
-        */
-       if (!partial->key && *partial->p)
-               /* Writer: end */
-               goto no_top;
-       for (p = partial; (p > chain) && all_zeroes((__le32 *) p->bh->b_data, p->p); p--)
-               ;
-       /*
-        * OK, we've found the last block that must survive. The rest of our
-        * branch should be detached before unlocking. However, if that rest
-        * of branch is all ours and does not grow immediately from the inode
-        * it's easier to cheat and just decrement partial->p.
-        */
-       if (p == chain + k - 1 && p > chain) {
-               p->p--;
-       } else {
-               *top = *p->p;
-               /* Nope, don't do this in ext4.  Must leave the tree intact */
-#if 0
-               *p->p = 0;
-#endif
-       }
-       /* Writer: end */
-
-       while (partial > p) {
-               brelse(partial->bh);
-               partial--;
-       }
-no_top:
-       return partial;
-}
-
-/*
- * Zero a number of block pointers in either an inode or an indirect block.
- * If we restart the transaction we must again get write access to the
- * indirect block for further modification.
- *
- * We release `count' blocks on disk, but (last - first) may be greater
- * than `count' because there can be holes in there.
- *
- * Return 0 on success, 1 on invalid block range
- * and < 0 on fatal error.
- */
-static int ext4_clear_blocks(handle_t *handle, struct inode *inode,
-                            struct buffer_head *bh,
-                            ext4_fsblk_t block_to_free,
-                            unsigned long count, __le32 *first,
-                            __le32 *last)
-{
-       __le32 *p;
-       int     flags = EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_VALIDATED;
-       int     err;
-
-       if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
-               flags |= EXT4_FREE_BLOCKS_METADATA;
-
-       if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), block_to_free,
-                                  count)) {
-               EXT4_ERROR_INODE(inode, "attempt to clear invalid "
-                                "blocks %llu len %lu",
-                                (unsigned long long) block_to_free, count);
-               return 1;
-       }
-
-       if (try_to_extend_transaction(handle, inode)) {
-               if (bh) {
-                       BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
-                       err = ext4_handle_dirty_metadata(handle, inode, bh);
-                       if (unlikely(err))
-                               goto out_err;
-               }
-               err = ext4_mark_inode_dirty(handle, inode);
-               if (unlikely(err))
-                       goto out_err;
-               err = ext4_truncate_restart_trans(handle, inode,
-                                                 blocks_for_truncate(inode));
-               if (unlikely(err))
-                       goto out_err;
-               if (bh) {
-                       BUFFER_TRACE(bh, "retaking write access");
-                       err = ext4_journal_get_write_access(handle, bh);
-                       if (unlikely(err))
-                               goto out_err;
-               }
-       }
-
-       for (p = first; p < last; p++)
-               *p = 0;
-
-       ext4_free_blocks(handle, inode, NULL, block_to_free, count, flags);
-       return 0;
-out_err:
-       ext4_std_error(inode->i_sb, err);
-       return err;
-}
-
-/**
- * ext4_free_data - free a list of data blocks
- * @handle:    handle for this transaction
- * @inode:     inode we are dealing with
- * @this_bh:   indirect buffer_head which contains *@first and *@last
- * @first:     array of block numbers
- * @last:      points immediately past the end of array
- *
- * We are freeing all blocks referred from that array (numbers are stored as
- * little-endian 32-bit) and updating @inode->i_blocks appropriately.
- *
- * We accumulate contiguous runs of blocks to free.  Conveniently, if these
- * blocks are contiguous then releasing them at one time will only affect one
- * or two bitmap blocks (+ group descriptor(s) and superblock) and we won't
- * actually use a lot of journal space.
- *
- * @this_bh will be %NULL if @first and @last point into the inode's direct
- * block pointers.
- */
-static void ext4_free_data(handle_t *handle, struct inode *inode,
-                          struct buffer_head *this_bh,
-                          __le32 *first, __le32 *last)
-{
-       ext4_fsblk_t block_to_free = 0;    /* Starting block # of a run */
-       unsigned long count = 0;            /* Number of blocks in the run */
-       __le32 *block_to_free_p = NULL;     /* Pointer into inode/ind
-                                              corresponding to
-                                              block_to_free */
-       ext4_fsblk_t nr;                    /* Current block # */
-       __le32 *p;                          /* Pointer into inode/ind
-                                              for current block */
-       int err = 0;
-
-       if (this_bh) {                          /* For indirect block */
-               BUFFER_TRACE(this_bh, "get_write_access");
-               err = ext4_journal_get_write_access(handle, this_bh);
-               /* Important: if we can't update the indirect pointers
-                * to the blocks, we can't free them. */
-               if (err)
-                       return;
-       }
-
-       for (p = first; p < last; p++) {
-               nr = le32_to_cpu(*p);
-               if (nr) {
-                       /* accumulate blocks to free if they're contiguous */
-                       if (count == 0) {
-                               block_to_free = nr;
-                               block_to_free_p = p;
-                               count = 1;
-                       } else if (nr == block_to_free + count) {
-                               count++;
-                       } else {
-                               err = ext4_clear_blocks(handle, inode, this_bh,
-                                                       block_to_free, count,
-                                                       block_to_free_p, p);
-                               if (err)
-                                       break;
-                               block_to_free = nr;
-                               block_to_free_p = p;
-                               count = 1;
-                       }
-               }
-       }
-
-       if (!err && count > 0)
-               err = ext4_clear_blocks(handle, inode, this_bh, block_to_free,
-                                       count, block_to_free_p, p);
-       if (err < 0)
-               /* fatal error */
-               return;
-
-       if (this_bh) {
-               BUFFER_TRACE(this_bh, "call ext4_handle_dirty_metadata");
-
-               /*
-                * The buffer head should have an attached journal head at this
-                * point. However, if the data is corrupted and an indirect
-                * block pointed to itself, it would have been detached when
-                * the block was cleared. Check for this instead of OOPSing.
-                */
-               if ((EXT4_JOURNAL(inode) == NULL) || bh2jh(this_bh))
-                       ext4_handle_dirty_metadata(handle, inode, this_bh);
-               else
-                       EXT4_ERROR_INODE(inode,
-                                        "circular indirect block detected at "
-                                        "block %llu",
-                               (unsigned long long) this_bh->b_blocknr);
-       }
-}
-
-/**
- *     ext4_free_branches - free an array of branches
- *     @handle: JBD handle for this transaction
- *     @inode: inode we are dealing with
- *     @parent_bh: the buffer_head which contains *@first and *@last
- *     @first: array of block numbers
- *     @last:  pointer immediately past the end of array
- *     @depth: depth of the branches to free
- *
- *     We are freeing all blocks referred from these branches (numbers are
- *     stored as little-endian 32-bit) and updating @inode->i_blocks
- *     appropriately.
- */
-static void ext4_free_branches(handle_t *handle, struct inode *inode,
-                              struct buffer_head *parent_bh,
-                              __le32 *first, __le32 *last, int depth)
-{
-       ext4_fsblk_t nr;
-       __le32 *p;
-
-       if (ext4_handle_is_aborted(handle))
-               return;
-
-       if (depth--) {
-               struct buffer_head *bh;
-               int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb);
-               p = last;
-               while (--p >= first) {
-                       nr = le32_to_cpu(*p);
-                       if (!nr)
-                               continue;               /* A hole */
-
-                       if (!ext4_data_block_valid(EXT4_SB(inode->i_sb),
-                                                  nr, 1)) {
-                               EXT4_ERROR_INODE(inode,
-                                                "invalid indirect mapped "
-                                                "block %lu (level %d)",
-                                                (unsigned long) nr, depth);
-                               break;
-                       }
-
-                       /* Go read the buffer for the next level down */
-                       bh = sb_bread(inode->i_sb, nr);
-
-                       /*
-                        * A read failure? Report error and clear slot
-                        * (should be rare).
-                        */
-                       if (!bh) {
-                               EXT4_ERROR_INODE_BLOCK(inode, nr,
-                                                      "Read failure");
-                               continue;
-                       }
-
-                       /* This zaps the entire block.  Bottom up. */
-                       BUFFER_TRACE(bh, "free child branches");
-                       ext4_free_branches(handle, inode, bh,
-                                       (__le32 *) bh->b_data,
-                                       (__le32 *) bh->b_data + addr_per_block,
-                                       depth);
-                       brelse(bh);
-
-                       /*
-                        * Everything below this this pointer has been
-                        * released.  Now let this top-of-subtree go.
-                        *
-                        * We want the freeing of this indirect block to be
-                        * atomic in the journal with the updating of the
-                        * bitmap block which owns it.  So make some room in
-                        * the journal.
-                        *
-                        * We zero the parent pointer *after* freeing its
-                        * pointee in the bitmaps, so if extend_transaction()
-                        * for some reason fails to put the bitmap changes and
-                        * the release into the same transaction, recovery
-                        * will merely complain about releasing a free block,
-                        * rather than leaking blocks.
-                        */
-                       if (ext4_handle_is_aborted(handle))
-                               return;
-                       if (try_to_extend_transaction(handle, inode)) {
-                               ext4_mark_inode_dirty(handle, inode);
-                               ext4_truncate_restart_trans(handle, inode,
-                                           blocks_for_truncate(inode));
-                       }
-
-                       /*
-                        * The forget flag here is critical because if
-                        * we are journaling (and not doing data
-                        * journaling), we have to make sure a revoke
-                        * record is written to prevent the journal
-                        * replay from overwriting the (former)
-                        * indirect block if it gets reallocated as a
-                        * data block.  This must happen in the same
-                        * transaction where the data blocks are
-                        * actually freed.
-                        */
-                       ext4_free_blocks(handle, inode, NULL, nr, 1,
-                                        EXT4_FREE_BLOCKS_METADATA|
-                                        EXT4_FREE_BLOCKS_FORGET);
-
-                       if (parent_bh) {
-                               /*
-                                * The block which we have just freed is
-                                * pointed to by an indirect block: journal it
-                                */
-                               BUFFER_TRACE(parent_bh, "get_write_access");
-                               if (!ext4_journal_get_write_access(handle,
-                                                                  parent_bh)){
-                                       *p = 0;
-                                       BUFFER_TRACE(parent_bh,
-                                       "call ext4_handle_dirty_metadata");
-                                       ext4_handle_dirty_metadata(handle,
-                                                                  inode,
-                                                                  parent_bh);
-                               }
-                       }
-               }
-       } else {
-               /* We have reached the bottom of the tree. */
-               BUFFER_TRACE(parent_bh, "free data blocks");
-               ext4_free_data(handle, inode, parent_bh, first, last);
-       }
-}
-
 int ext4_can_truncate(struct inode *inode)
 {
        if (S_ISREG(inode->i_mode))
@@ -4476,19 +3129,6 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
  */
 void ext4_truncate(struct inode *inode)
 {
-       handle_t *handle;
-       struct ext4_inode_info *ei = EXT4_I(inode);
-       __le32 *i_data = ei->i_data;
-       int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb);
-       struct address_space *mapping = inode->i_mapping;
-       ext4_lblk_t offsets[4];
-       Indirect chain[4];
-       Indirect *partial;
-       __le32 nr = 0;
-       int n = 0;
-       ext4_lblk_t last_block, max_block;
-       unsigned blocksize = inode->i_sb->s_blocksize;
-
        trace_ext4_truncate_enter(inode);
 
        if (!ext4_can_truncate(inode))
@@ -4499,149 +3139,11 @@ void ext4_truncate(struct inode *inode)
        if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC))
                ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE);
 
-       if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
+       if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
                ext4_ext_truncate(inode);
-               trace_ext4_truncate_exit(inode);
-               return;
-       }
-
-       handle = start_transaction(inode);
-       if (IS_ERR(handle))
-               return;         /* AKPM: return what? */
-
-       last_block = (inode->i_size + blocksize-1)
-                                       >> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
-       max_block = (EXT4_SB(inode->i_sb)->s_bitmap_maxbytes + blocksize-1)
-                                       >> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
-
-       if (inode->i_size & (blocksize - 1))
-               if (ext4_block_truncate_page(handle, mapping, inode->i_size))
-                       goto out_stop;
-
-       if (last_block != max_block) {
-               n = ext4_block_to_path(inode, last_block, offsets, NULL);
-               if (n == 0)
-                       goto out_stop;  /* error */
-       }
-
-       /*
-        * OK.  This truncate is going to happen.  We add the inode to the
-        * orphan list, so that if this truncate spans multiple transactions,
-        * and we crash, we will resume the truncate when the filesystem
-        * recovers.  It also marks the inode dirty, to catch the new size.
-        *
-        * Implication: the file must always be in a sane, consistent
-        * truncatable state while each transaction commits.
-        */
-       if (ext4_orphan_add(handle, inode))
-               goto out_stop;
-
-       /*
-        * From here we block out all ext4_get_block() callers who want to
-        * modify the block allocation tree.
-        */
-       down_write(&ei->i_data_sem);
-
-       ext4_discard_preallocations(inode);
-
-       /*
-        * The orphan list entry will now protect us from any crash which
-        * occurs before the truncate completes, so it is now safe to propagate
-        * the new, shorter inode size (held for now in i_size) into the
-        * on-disk inode. We do this via i_disksize, which is the value which
-        * ext4 *really* writes onto the disk inode.
-        */
-       ei->i_disksize = inode->i_size;
-
-       if (last_block == max_block) {
-               /*
-                * It is unnecessary to free any data blocks if last_block is
-                * equal to the indirect block limit.
-                */
-               goto out_unlock;
-       } else if (n == 1) {            /* direct blocks */
-               ext4_free_data(handle, inode, NULL, i_data+offsets[0],
-                              i_data + EXT4_NDIR_BLOCKS);
-               goto do_indirects;
-       }
-
-       partial = ext4_find_shared(inode, n, offsets, chain, &nr);
-       /* Kill the top of shared branch (not detached) */
-       if (nr) {
-               if (partial == chain) {
-                       /* Shared branch grows from the inode */
-                       ext4_free_branches(handle, inode, NULL,
-                                          &nr, &nr+1, (chain+n-1) - partial);
-                       *partial->p = 0;
-                       /*
-                        * We mark the inode dirty prior to restart,
-                        * and prior to stop.  No need for it here.
-                        */
-               } else {
-                       /* Shared branch grows from an indirect block */
-                       BUFFER_TRACE(partial->bh, "get_write_access");
-                       ext4_free_branches(handle, inode, partial->bh,
-                                       partial->p,
-                                       partial->p+1, (chain+n-1) - partial);
-               }
-       }
-       /* Clear the ends of indirect blocks on the shared branch */
-       while (partial > chain) {
-               ext4_free_branches(handle, inode, partial->bh, partial->p + 1,
-                                  (__le32*)partial->bh->b_data+addr_per_block,
-                                  (chain+n-1) - partial);
-               BUFFER_TRACE(partial->bh, "call brelse");
-               brelse(partial->bh);
-               partial--;
-       }
-do_indirects:
-       /* Kill the remaining (whole) subtrees */
-       switch (offsets[0]) {
-       default:
-               nr = i_data[EXT4_IND_BLOCK];
-               if (nr) {
-                       ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
-                       i_data[EXT4_IND_BLOCK] = 0;
-               }
-       case EXT4_IND_BLOCK:
-               nr = i_data[EXT4_DIND_BLOCK];
-               if (nr) {
-                       ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
-                       i_data[EXT4_DIND_BLOCK] = 0;
-               }
-       case EXT4_DIND_BLOCK:
-               nr = i_data[EXT4_TIND_BLOCK];
-               if (nr) {
-                       ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
-                       i_data[EXT4_TIND_BLOCK] = 0;
-               }
-       case EXT4_TIND_BLOCK:
-               ;
-       }
-
-out_unlock:
-       up_write(&ei->i_data_sem);
-       inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
-       ext4_mark_inode_dirty(handle, inode);
-
-       /*
-        * In a multi-transaction truncate, we only make the final transaction
-        * synchronous
-        */
-       if (IS_SYNC(inode))
-               ext4_handle_sync(handle);
-out_stop:
-       /*
-        * If this was a simple ftruncate(), and the file will remain alive
-        * then we need to clear up the orphan record which we created above.
-        * However, if this was a real unlink then we were called by
-        * ext4_delete_inode(), and we allow that function to clean up the
-        * orphan info for us.
-        */
-       if (inode->i_nlink)
-               ext4_orphan_del(handle, inode);
+       else
+               ext4_ind_truncate(inode);
 
-       ext4_journal_stop(handle);
        trace_ext4_truncate_exit(inode);
 }
 
@@ -5012,7 +3514,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
                   (S_ISLNK(inode->i_mode) &&
                    !ext4_inode_is_fast_symlink(inode))) {
                /* Validate block references which are part of inode */
-               ret = ext4_check_inode_blockref(inode);
+               ret = ext4_ind_check_inode(inode);
        }
        if (ret)
                goto bad_inode;
@@ -5459,34 +3961,10 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
        return 0;
 }
 
-static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks,
-                                     int chunk)
-{
-       int indirects;
-
-       /* if nrblocks are contiguous */
-       if (chunk) {
-               /*
-                * With N contiguous data blocks, we need at most
-                * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) + 1 indirect blocks,
-                * 2 dindirect blocks, and 1 tindirect block
-                */
-               return DIV_ROUND_UP(nrblocks,
-                                   EXT4_ADDR_PER_BLOCK(inode->i_sb)) + 4;
-       }
-       /*
-        * if nrblocks are not contiguous, worse case, each block touch
-        * a indirect block, and each indirect block touch a double indirect
-        * block, plus a triple indirect block
-        */
-       indirects = nrblocks * 2 + 1;
-       return indirects;
-}
-
 static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
 {
        if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
-               return ext4_indirect_trans_blocks(inode, nrblocks, chunk);
+               return ext4_ind_trans_blocks(inode, nrblocks, chunk);
        return ext4_ext_index_trans_blocks(inode, nrblocks, chunk);
 }
 
index 808c554..f18bfe3 100644 (file)
@@ -202,8 +202,9 @@ setversion_out:
                struct super_block *sb = inode->i_sb;
                int err, err2=0;
 
-               if (!capable(CAP_SYS_RESOURCE))
-                       return -EPERM;
+               err = ext4_resize_begin(sb);
+               if (err)
+                       return err;
 
                if (get_user(n_blocks_count, (__u32 __user *)arg))
                        return -EFAULT;
@@ -221,6 +222,7 @@ setversion_out:
                if (err == 0)
                        err = err2;
                mnt_drop_write(filp->f_path.mnt);
+               ext4_resize_end(sb);
 
                return err;
        }
@@ -271,8 +273,9 @@ mext_out:
                struct super_block *sb = inode->i_sb;
                int err, err2=0;
 
-               if (!capable(CAP_SYS_RESOURCE))
-                       return -EPERM;
+               err = ext4_resize_begin(sb);
+               if (err)
+                       return err;
 
                if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg,
                                sizeof(input)))
@@ -291,6 +294,7 @@ mext_out:
                if (err == 0)
                        err = err2;
                mnt_drop_write(filp->f_path.mnt);
+               ext4_resize_end(sb);
 
                return err;
        }
index 6ed859d..17a5a57 100644 (file)
@@ -75,8 +75,8 @@
  *
  * The inode preallocation space is used looking at the _logical_ start
  * block. If only the logical file block falls within the range of prealloc
- * space we will consume the particular prealloc space. This make sure that
- * that the we have contiguous physical blocks representing the file blocks
+ * space we will consume the particular prealloc space. This makes sure that
+ * we have contiguous physical blocks representing the file blocks
  *
  * The important thing to be noted in case of inode prealloc space is that
  * we don't modify the values associated to inode prealloc space except
@@ -84,7 +84,7 @@
  *
  * If we are not able to find blocks in the inode prealloc space and if we
  * have the group allocation flag set then we look at the locality group
- * prealloc space. These are per CPU prealloc list repreasented as
+ * prealloc space. These are per CPU prealloc list represented as
  *
  * ext4_sb_info.s_locality_groups[smp_processor_id()]
  *
  * we are doing a group prealloc we try to normalize the request to
  * sbi->s_mb_group_prealloc. Default value of s_mb_group_prealloc is
  * 512 blocks. This can be tuned via
- * /sys/fs/ext4/<partition/mb_group_prealloc. The value is represented in
+ * /sys/fs/ext4/<partition>/mb_group_prealloc. The value is represented in
  * terms of number of blocks. If we have mounted the file system with -O
  * stripe=<value> option the group prealloc request is normalized to the
- * stripe value (sbi->s_stripe)
+ * the smallest multiple of the stripe value (sbi->s_stripe) which is
+ * greater than the default mb_group_prealloc.
  *
- * The regular allocator(using the buddy cache) supports few tunables.
+ * The regular allocator (using the buddy cache) supports a few tunables.
  *
  * /sys/fs/ext4/<partition>/mb_min_to_scan
  * /sys/fs/ext4/<partition>/mb_max_to_scan
  * best extent in the found extents. Searching for the blocks starts with
  * the group specified as the goal value in allocation context via
  * ac_g_ex. Each group is first checked based on the criteria whether it
- * can used for allocation. ext4_mb_good_group explains how the groups are
+ * can be used for allocation. ext4_mb_good_group explains how the groups are
  * checked.
  *
  * Both the prealloc space are getting populated as above. So for the first
@@ -492,10 +493,11 @@ static void mb_cmp_bitmaps(struct ext4_buddy *e4b, void *bitmap)
                b2 = (unsigned char *) bitmap;
                for (i = 0; i < e4b->bd_sb->s_blocksize; i++) {
                        if (b1[i] != b2[i]) {
-                               printk(KERN_ERR "corruption in group %u "
-                                      "at byte %u(%u): %x in copy != %x "
-                                      "on disk/prealloc\n",
-                                      e4b->bd_group, i, i * 8, b1[i], b2[i]);
+                               ext4_msg(e4b->bd_sb, KERN_ERR,
+                                        "corruption in group %u "
+                                        "at byte %u(%u): %x in copy != %x "
+                                        "on disk/prealloc",
+                                        e4b->bd_group, i, i * 8, b1[i], b2[i]);
                                BUG();
                        }
                }
@@ -1125,7 +1127,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
        grp = ext4_get_group_info(sb, group);
 
        e4b->bd_blkbits = sb->s_blocksize_bits;
-       e4b->bd_info = ext4_get_group_info(sb, group);
+       e4b->bd_info = grp;
        e4b->bd_sb = sb;
        e4b->bd_group = group;
        e4b->bd_buddy_page = NULL;
@@ -1281,7 +1283,7 @@ static void mb_clear_bits(void *bm, int cur, int len)
        }
 }
 
-static void mb_set_bits(void *bm, int cur, int len)
+void ext4_set_bits(void *bm, int cur, int len)
 {
        __u32 *addr;
 
@@ -1510,7 +1512,7 @@ static int mb_mark_used(struct ext4_buddy *e4b, struct ext4_free_extent *ex)
        }
        mb_set_largest_free_order(e4b->bd_sb, e4b->bd_info);
 
-       mb_set_bits(EXT4_MB_BITMAP(e4b), ex->fe_start, len0);
+       ext4_set_bits(EXT4_MB_BITMAP(e4b), ex->fe_start, len0);
        mb_check_buddy(e4b);
 
        return ret;
@@ -2223,8 +2225,8 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
                        EXT4_DESC_PER_BLOCK_BITS(sb);
                meta_group_info = kmalloc(metalen, GFP_KERNEL);
                if (meta_group_info == NULL) {
-                       printk(KERN_ERR "EXT4-fs: can't allocate mem for a "
-                              "buddy group\n");
+                       ext4_msg(sb, KERN_ERR, "EXT4-fs: can't allocate mem "
+                                "for a buddy group");
                        goto exit_meta_group_info;
                }
                sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)] =
@@ -2237,7 +2239,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
 
        meta_group_info[i] = kmem_cache_alloc(cachep, GFP_KERNEL);
        if (meta_group_info[i] == NULL) {
-               printk(KERN_ERR "EXT4-fs: can't allocate buddy mem\n");
+               ext4_msg(sb, KERN_ERR, "EXT4-fs: can't allocate buddy mem");
                goto exit_group_info;
        }
        memset(meta_group_info[i], 0, kmem_cache_size(cachep));
@@ -2279,8 +2281,10 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
 
 exit_group_info:
        /* If a meta_group_info table has been allocated, release it now */
-       if (group % EXT4_DESC_PER_BLOCK(sb) == 0)
+       if (group % EXT4_DESC_PER_BLOCK(sb) == 0) {
                kfree(sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)]);
+               sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)] = NULL;
+       }
 exit_meta_group_info:
        return -ENOMEM;
 } /* ext4_mb_add_groupinfo */
@@ -2328,23 +2332,26 @@ static int ext4_mb_init_backend(struct super_block *sb)
        /* An 8TB filesystem with 64-bit pointers requires a 4096 byte
         * kmalloc. A 128kb malloc should suffice for a 256TB filesystem.
         * So a two level scheme suffices for now. */
-       sbi->s_group_info = kzalloc(array_size, GFP_KERNEL);
+       sbi->s_group_info = ext4_kvzalloc(array_size, GFP_KERNEL);
        if (sbi->s_group_info == NULL) {
-               printk(KERN_ERR "EXT4-fs: can't allocate buddy meta group\n");
+               ext4_msg(sb, KERN_ERR, "can't allocate buddy meta group");
                return -ENOMEM;
        }
        sbi->s_buddy_cache = new_inode(sb);
        if (sbi->s_buddy_cache == NULL) {
-               printk(KERN_ERR "EXT4-fs: can't get new inode\n");
+               ext4_msg(sb, KERN_ERR, "can't get new inode");
                goto err_freesgi;
        }
-       sbi->s_buddy_cache->i_ino = get_next_ino();
+       /* To avoid potentially colliding with an valid on-disk inode number,
+        * use EXT4_BAD_INO for the buddy cache inode number.  This inode is
+        * not in the inode hash, so it should never be found by iget(), but
+        * this will avoid confusion if it ever shows up during debugging. */
+       sbi->s_buddy_cache->i_ino = EXT4_BAD_INO;
        EXT4_I(sbi->s_buddy_cache)->i_disksize = 0;
        for (i = 0; i < ngroups; i++) {
                desc = ext4_get_group_desc(sb, i, NULL);
                if (desc == NULL) {
-                       printk(KERN_ERR
-                               "EXT4-fs: can't read descriptor %u\n", i);
+                       ext4_msg(sb, KERN_ERR, "can't read descriptor %u", i);
                        goto err_freebuddy;
                }
                if (ext4_mb_add_groupinfo(sb, i, desc) != 0)
@@ -2362,7 +2369,7 @@ err_freebuddy:
                kfree(sbi->s_group_info[i]);
        iput(sbi->s_buddy_cache);
 err_freesgi:
-       kfree(sbi->s_group_info);
+       ext4_kvfree(sbi->s_group_info);
        return -ENOMEM;
 }
 
@@ -2404,14 +2411,15 @@ static int ext4_groupinfo_create_slab(size_t size)
                                        slab_size, 0, SLAB_RECLAIM_ACCOUNT,
                                        NULL);
 
+       ext4_groupinfo_caches[cache_index] = cachep;
+
        mutex_unlock(&ext4_grpinfo_slab_create_mutex);
        if (!cachep) {
-               printk(KERN_EMERG "EXT4: no memory for groupinfo slab cache\n");
+               printk(KERN_EMERG
+                      "EXT4-fs: no memory for groupinfo slab cache\n");
                return -ENOMEM;
        }
 
-       ext4_groupinfo_caches[cache_index] = cachep;
-
        return 0;
 }
 
@@ -2457,12 +2465,6 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
                i++;
        } while (i <= sb->s_blocksize_bits + 1);
 
-       /* init file for buddy data */
-       ret = ext4_mb_init_backend(sb);
-       if (ret != 0) {
-               goto out;
-       }
-
        spin_lock_init(&sbi->s_md_lock);
        spin_lock_init(&sbi->s_bal_lock);
 
@@ -2472,6 +2474,18 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
        sbi->s_mb_stream_request = MB_DEFAULT_STREAM_THRESHOLD;
        sbi->s_mb_order2_reqs = MB_DEFAULT_ORDER2_REQS;
        sbi->s_mb_group_prealloc = MB_DEFAULT_GROUP_PREALLOC;
+       /*
+        * If there is a s_stripe > 1, then we set the s_mb_group_prealloc
+        * to the lowest multiple of s_stripe which is bigger than
+        * the s_mb_group_prealloc as determined above. We want
+        * the preallocation size to be an exact multiple of the
+        * RAID stripe size so that preallocations don't fragment
+        * the stripes.
+        */
+       if (sbi->s_stripe > 1) {
+               sbi->s_mb_group_prealloc = roundup(
+                       sbi->s_mb_group_prealloc, sbi->s_stripe);
+       }
 
        sbi->s_locality_groups = alloc_percpu(struct ext4_locality_group);
        if (sbi->s_locality_groups == NULL) {
@@ -2487,6 +2501,12 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
                spin_lock_init(&lg->lg_prealloc_lock);
        }
 
+       /* init file for buddy data */
+       ret = ext4_mb_init_backend(sb);
+       if (ret != 0) {
+               goto out;
+       }
+
        if (sbi->s_proc)
                proc_create_data("mb_groups", S_IRUGO, sbi->s_proc,
                                 &ext4_mb_seq_groups_fops, sb);
@@ -2544,32 +2564,32 @@ int ext4_mb_release(struct super_block *sb)
                        EXT4_DESC_PER_BLOCK_BITS(sb);
                for (i = 0; i < num_meta_group_infos; i++)
                        kfree(sbi->s_group_info[i]);
-               kfree(sbi->s_group_info);
+               ext4_kvfree(sbi->s_group_info);
        }
        kfree(sbi->s_mb_offsets);
        kfree(sbi->s_mb_maxs);
        if (sbi->s_buddy_cache)
                iput(sbi->s_buddy_cache);
        if (sbi->s_mb_stats) {
-               printk(KERN_INFO
-                      "EXT4-fs: mballoc: %u blocks %u reqs (%u success)\n",
+               ext4_msg(sb, KERN_INFO,
+                      "mballoc: %u blocks %u reqs (%u success)",
                                atomic_read(&sbi->s_bal_allocated),
                                atomic_read(&sbi->s_bal_reqs),
                                atomic_read(&sbi->s_bal_success));
-               printk(KERN_INFO
-                     "EXT4-fs: mballoc: %u extents scanned, %u goal hits, "
-                               "%u 2^N hits, %u breaks, %u lost\n",
+               ext4_msg(sb, KERN_INFO,
+                     "mballoc: %u extents scanned, %u goal hits, "
+                               "%u 2^N hits, %u breaks, %u lost",
                                atomic_read(&sbi->s_bal_ex_scanned),
                                atomic_read(&sbi->s_bal_goals),
                                atomic_read(&sbi->s_bal_2orders),
                                atomic_read(&sbi->s_bal_breaks),
                                atomic_read(&sbi->s_mb_lost_chunks));
-               printk(KERN_INFO
-                      "EXT4-fs: mballoc: %lu generated and it took %Lu\n",
-                               sbi->s_mb_buddies_generated++,
+               ext4_msg(sb, KERN_INFO,
+                      "mballoc: %lu generated and it took %Lu",
+                               sbi->s_mb_buddies_generated,
                                sbi->s_mb_generation_time);
-               printk(KERN_INFO
-                      "EXT4-fs: mballoc: %u preallocated, %u discarded\n",
+               ext4_msg(sb, KERN_INFO,
+                      "mballoc: %u preallocated, %u discarded",
                                atomic_read(&sbi->s_mb_preallocated),
                                atomic_read(&sbi->s_mb_discarded));
        }
@@ -2628,6 +2648,15 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
                rb_erase(&entry->node, &(db->bb_free_root));
                mb_free_blocks(NULL, &e4b, entry->start_blk, entry->count);
 
+               /*
+                * Clear the trimmed flag for the group so that the next
+                * ext4_trim_fs can trim it.
+                * If the volume is mounted with -o discard, online discard
+                * is supported and the free blocks will be trimmed online.
+                */
+               if (!test_opt(sb, DISCARD))
+                       EXT4_MB_GRP_CLEAR_TRIMMED(db);
+
                if (!db->bb_free_root.rb_node) {
                        /* No more items in the per group rb tree
                         * balance refcounts from ext4_mb_free_metadata()
@@ -2771,8 +2800,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
                 * We leak some of the blocks here.
                 */
                ext4_lock_group(sb, ac->ac_b_ex.fe_group);
-               mb_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start,
-                           ac->ac_b_ex.fe_len);
+               ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start,
+                             ac->ac_b_ex.fe_len);
                ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
                err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
                if (!err)
@@ -2790,7 +2819,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
                }
        }
 #endif
-       mb_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start,ac->ac_b_ex.fe_len);
+       ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start,
+                     ac->ac_b_ex.fe_len);
        if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
                gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
                ext4_free_blks_set(sb, gdp,
@@ -2830,8 +2860,9 @@ out_err:
 
 /*
  * here we normalize request for locality group
- * Group request are normalized to s_strip size if we set the same via mount
- * option. If not we set it to s_mb_group_prealloc which can be configured via
+ * Group request are normalized to s_mb_group_prealloc, which goes to
+ * s_strip if we set the same via mount option.
+ * s_mb_group_prealloc can be configured via
  * /sys/fs/ext4/<partition>/mb_group_prealloc
  *
  * XXX: should we try to preallocate more than the group has now?
@@ -2842,10 +2873,7 @@ static void ext4_mb_normalize_group_request(struct ext4_allocation_context *ac)
        struct ext4_locality_group *lg = ac->ac_lg;
 
        BUG_ON(lg == NULL);
-       if (EXT4_SB(sb)->s_stripe)
-               ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_stripe;
-       else
-               ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc;
+       ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc;
        mb_debug(1, "#%u: goal %u blocks for locality group\n",
                current->pid, ac->ac_g_ex.fe_len);
 }
@@ -3001,9 +3029,10 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
 
        if (start + size <= ac->ac_o_ex.fe_logical &&
                        start > ac->ac_o_ex.fe_logical) {
-               printk(KERN_ERR "start %lu, size %lu, fe_logical %lu\n",
-                       (unsigned long) start, (unsigned long) size,
-                       (unsigned long) ac->ac_o_ex.fe_logical);
+               ext4_msg(ac->ac_sb, KERN_ERR,
+                        "start %lu, size %lu, fe_logical %lu",
+                        (unsigned long) start, (unsigned long) size,
+                        (unsigned long) ac->ac_o_ex.fe_logical);
        }
        BUG_ON(start + size <= ac->ac_o_ex.fe_logical &&
                        start > ac->ac_o_ex.fe_logical);
@@ -3262,7 +3291,7 @@ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
 
        while (n) {
                entry = rb_entry(n, struct ext4_free_data, node);
-               mb_set_bits(bitmap, entry->start_blk, entry->count);
+               ext4_set_bits(bitmap, entry->start_blk, entry->count);
                n = rb_next(n);
        }
        return;
@@ -3304,7 +3333,7 @@ void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
                if (unlikely(len == 0))
                        continue;
                BUG_ON(groupnr != group);
-               mb_set_bits(bitmap, start, len);
+               ext4_set_bits(bitmap, start, len);
                preallocated += len;
                count++;
        }
@@ -3584,10 +3613,11 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
                bit = next + 1;
        }
        if (free != pa->pa_free) {
-               printk(KERN_CRIT "pa %p: logic %lu, phys. %lu, len %lu\n",
-                       pa, (unsigned long) pa->pa_lstart,
-                       (unsigned long) pa->pa_pstart,
-                       (unsigned long) pa->pa_len);
+               ext4_msg(e4b->bd_sb, KERN_CRIT,
+                        "pa %p: logic %lu, phys. %lu, len %lu",
+                        pa, (unsigned long) pa->pa_lstart,
+                        (unsigned long) pa->pa_pstart,
+                        (unsigned long) pa->pa_len);
                ext4_grp_locked_error(sb, group, 0, 0, "free %u, pa_free %u",
                                        free, pa->pa_free);
                /*
@@ -3775,7 +3805,8 @@ repeat:
                         * use preallocation while we're discarding it */
                        spin_unlock(&pa->pa_lock);
                        spin_unlock(&ei->i_prealloc_lock);
-                       printk(KERN_ERR "uh-oh! used pa while discarding\n");
+                       ext4_msg(sb, KERN_ERR,
+                                "uh-oh! used pa while discarding");
                        WARN_ON(1);
                        schedule_timeout_uninterruptible(HZ);
                        goto repeat;
@@ -3852,12 +3883,13 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
            (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED))
                return;
 
-       printk(KERN_ERR "EXT4-fs: Can't allocate:"
-                       " Allocation context details:\n");
-       printk(KERN_ERR "EXT4-fs: status %d flags %d\n",
+       ext4_msg(ac->ac_sb, KERN_ERR, "EXT4-fs: Can't allocate:"
+                       " Allocation context details:");
+       ext4_msg(ac->ac_sb, KERN_ERR, "EXT4-fs: status %d flags %d",
                        ac->ac_status, ac->ac_flags);
-       printk(KERN_ERR "EXT4-fs: orig %lu/%lu/%lu@%lu, goal %lu/%lu/%lu@%lu, "
-                       "best %lu/%lu/%lu@%lu cr %d\n",
+       ext4_msg(ac->ac_sb, KERN_ERR, "EXT4-fs: orig %lu/%lu/%lu@%lu, "
+                       "goal %lu/%lu/%lu@%lu, "
+                       "best %lu/%lu/%lu@%lu cr %d",
                        (unsigned long)ac->ac_o_ex.fe_group,
                        (unsigned long)ac->ac_o_ex.fe_start,
                        (unsigned long)ac->ac_o_ex.fe_len,
@@ -3871,9 +3903,9 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
                        (unsigned long)ac->ac_b_ex.fe_len,
                        (unsigned long)ac->ac_b_ex.fe_logical,
                        (int)ac->ac_criteria);
-       printk(KERN_ERR "EXT4-fs: %lu scanned, %d found\n", ac->ac_ex_scanned,
-               ac->ac_found);
-       printk(KERN_ERR "EXT4-fs: groups: \n");
+       ext4_msg(ac->ac_sb, KERN_ERR, "EXT4-fs: %lu scanned, %d found",
+                ac->ac_ex_scanned, ac->ac_found);
+       ext4_msg(ac->ac_sb, KERN_ERR, "EXT4-fs: groups: ");
        ngroups = ext4_get_groups_count(sb);
        for (i = 0; i < ngroups; i++) {
                struct ext4_group_info *grp = ext4_get_group_info(sb, i);
@@ -4637,7 +4669,7 @@ do_more:
        }
        ext4_mark_super_dirty(sb);
 error_return:
-       if (freed)
+       if (freed && !(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
                dquot_free_block(inode, freed);
        brelse(bitmap_bh);
        ext4_std_error(sb, err);
@@ -4645,7 +4677,7 @@ error_return:
 }
 
 /**
- * ext4_add_groupblocks() -- Add given blocks to an existing group
+ * ext4_group_add_blocks() -- Add given blocks to an existing group
  * @handle:                    handle to this transaction
  * @sb:                                super block
  * @block:                     start physcial block to add to the block group
@@ -4653,7 +4685,7 @@ error_return:
  *
  * This marks the blocks as free in the bitmap and buddy.
  */
-void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
+int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
                         ext4_fsblk_t block, unsigned long count)
 {
        struct buffer_head *bitmap_bh = NULL;
@@ -4666,25 +4698,35 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
        struct ext4_buddy e4b;
        int err = 0, ret, blk_free_count;
        ext4_grpblk_t blocks_freed;
-       struct ext4_group_info *grp;
 
        ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1);
 
+       if (count == 0)
+               return 0;
+
        ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
-       grp = ext4_get_group_info(sb, block_group);
        /*
         * Check to see if we are freeing blocks across a group
         * boundary.
         */
-       if (bit + count > EXT4_BLOCKS_PER_GROUP(sb))
+       if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) {
+               ext4_warning(sb, "too much blocks added to group %u\n",
+                            block_group);
+               err = -EINVAL;
                goto error_return;
+       }
 
        bitmap_bh = ext4_read_block_bitmap(sb, block_group);
-       if (!bitmap_bh)
+       if (!bitmap_bh) {
+               err = -EIO;
                goto error_return;
+       }
+
        desc = ext4_get_group_desc(sb, block_group, &gd_bh);
-       if (!desc)
+       if (!desc) {
+               err = -EIO;
                goto error_return;
+       }
 
        if (in_range(ext4_block_bitmap(sb, desc), block, count) ||
            in_range(ext4_inode_bitmap(sb, desc), block, count) ||
@@ -4694,6 +4736,7 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
                ext4_error(sb, "Adding blocks in system zones - "
                           "Block = %llu, count = %lu",
                           block, count);
+               err = -EINVAL;
                goto error_return;
        }
 
@@ -4762,7 +4805,7 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
 error_return:
        brelse(bitmap_bh);
        ext4_std_error(sb, err);
-       return;
+       return err;
 }
 
 /**
@@ -4782,6 +4825,8 @@ static void ext4_trim_extent(struct super_block *sb, int start, int count,
 {
        struct ext4_free_extent ex;
 
+       trace_ext4_trim_extent(sb, group, start, count);
+
        assert_spin_locked(ext4_group_lock_ptr(sb, group));
 
        ex.fe_start = start;
@@ -4802,7 +4847,7 @@ static void ext4_trim_extent(struct super_block *sb, int start, int count,
 /**
  * ext4_trim_all_free -- function to trim all free space in alloc. group
  * @sb:                        super block for file system
- * @e4b:               ext4 buddy
+ * @group:             group to be trimmed
  * @start:             first group block to examine
  * @max:               last group block to examine
  * @minblocks:         minimum extent block count
@@ -4823,10 +4868,12 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
                   ext4_grpblk_t minblocks)
 {
        void *bitmap;
-       ext4_grpblk_t next, count = 0;
+       ext4_grpblk_t next, count = 0, free_count = 0;
        struct ext4_buddy e4b;
        int ret;
 
+       trace_ext4_trim_all_free(sb, group, start, max);
+
        ret = ext4_mb_load_buddy(sb, group, &e4b);
        if (ret) {
                ext4_error(sb, "Error in loading buddy "
@@ -4836,6 +4883,10 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
        bitmap = e4b.bd_bitmap;
 
        ext4_lock_group(sb, group);
+       if (EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) &&
+           minblocks >= atomic_read(&EXT4_SB(sb)->s_last_trim_minblks))
+               goto out;
+
        start = (e4b.bd_info->bb_first_free > start) ?
                e4b.bd_info->bb_first_free : start;
 
@@ -4850,6 +4901,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
                                         next - start, group, &e4b);
                        count += next - start;
                }
+               free_count += next - start;
                start = next + 1;
 
                if (fatal_signal_pending(current)) {
@@ -4863,9 +4915,13 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
                        ext4_lock_group(sb, group);
                }
 
-               if ((e4b.bd_info->bb_free - count) < minblocks)
+               if ((e4b.bd_info->bb_free - free_count) < minblocks)
                        break;
        }
+
+       if (!ret)
+               EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
+out:
        ext4_unlock_group(sb, group);
        ext4_mb_unload_buddy(&e4b);
 
@@ -4904,6 +4960,8 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
 
        if (unlikely(minlen > EXT4_BLOCKS_PER_GROUP(sb)))
                return -EINVAL;
+       if (start + len <= first_data_blk)
+               goto out;
        if (start < first_data_blk) {
                len -= first_data_blk - start;
                start = first_data_blk;
@@ -4952,5 +5010,9 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
        }
        range->len = trimmed * sb->s_blocksize;
 
+       if (!ret)
+               atomic_set(&EXT4_SB(sb)->s_last_trim_minblks, minlen);
+
+out:
        return ret;
 }
index 20b5e7b..9d4a636 100644 (file)
@@ -187,7 +187,6 @@ struct ext4_allocation_context {
        __u16 ac_flags;         /* allocation hints */
        __u8 ac_status;
        __u8 ac_criteria;
-       __u8 ac_repeats;
        __u8 ac_2order;         /* if request is to allocate 2^N blocks and
                                 * N > 0, the field stores N, otherwise 0 */
        __u8 ac_op;             /* operation, for history only */
index 8c9baba..f8068c7 100644 (file)
@@ -289,7 +289,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext4_dir_ent
                                while (len--) printk("%c", *name++);
                                ext4fs_dirhash(de->name, de->name_len, &h);
                                printk(":%x.%u ", h.hash,
-                                      ((char *) de - base));
+                                      (unsigned) ((char *) de - base));
                        }
                        space += EXT4_DIR_REC_LEN(de->name_len);
                        names++;
@@ -1013,7 +1013,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
 
        *err = -ENOENT;
 errout:
-       dxtrace(printk(KERN_DEBUG "%s not found\n", name));
+       dxtrace(printk(KERN_DEBUG "%s not found\n", d_name->name));
        dx_release (frames);
        return NULL;
 }
@@ -1985,18 +1985,11 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
        if (!list_empty(&EXT4_I(inode)->i_orphan))
                goto out_unlock;
 
-       /* Orphan handling is only valid for files with data blocks
-        * being truncated, or files being unlinked. */
-
-       /* @@@ FIXME: Observation from aviro:
-        * I think I can trigger J_ASSERT in ext4_orphan_add().  We block
-        * here (on s_orphan_lock), so race with ext4_link() which might bump
-        * ->i_nlink. For, say it, character device. Not a regular file,
-        * not a directory, not a symlink and ->i_nlink > 0.
-        *
-        * tytso, 4/25/2009: I'm not sure how that could happen;
-        * shouldn't the fs core protect us from these sort of
-        * unlink()/link() races?
+       /*
+        * Orphan handling is only valid for files with data blocks
+        * being truncated, or files being unlinked. Note that we either
+        * hold i_mutex, or the inode can not be referenced from outside,
+        * so i_nlink should not be bumped due to race
         */
        J_ASSERT((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
                  S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
@@ -2260,9 +2253,11 @@ static int ext4_symlink(struct inode *dir,
                /*
                 * For non-fast symlinks, we just allocate inode and put it on
                 * orphan list in the first transaction => we need bitmap,
-                * group descriptor, sb, inode block, quota blocks.
+                * group descriptor, sb, inode block, quota blocks, and
+                * possibly selinux xattr blocks.
                 */
-               credits = 4 + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb);
+               credits = 4 + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb) +
+                         EXT4_XATTR_TRANS_BLOCKS;
        } else {
                /*
                 * Fast symlink. We have to add entry to directory
index 7bb8f76..430c401 100644 (file)
@@ -285,11 +285,7 @@ static int io_submit_init(struct ext4_io_submit *io,
        io_end = ext4_init_io_end(inode, GFP_NOFS);
        if (!io_end)
                return -ENOMEM;
-       do {
-               bio = bio_alloc(GFP_NOIO, nvecs);
-               nvecs >>= 1;
-       } while (bio == NULL);
-
+       bio = bio_alloc(GFP_NOIO, min(nvecs, BIO_MAX_PAGES));
        bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);
        bio->bi_bdev = bh->b_bdev;
        bio->bi_private = io->io_end = io_end;
index 80bbc9c..707d3f1 100644 (file)
 
 #include "ext4_jbd2.h"
 
+int ext4_resize_begin(struct super_block *sb)
+{
+       int ret = 0;
+
+       if (!capable(CAP_SYS_RESOURCE))
+               return -EPERM;
+
+       /*
+        * We are not allowed to do online-resizing on a filesystem mounted
+        * with error, because it can destroy the filesystem easily.
+        */
+       if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
+               ext4_warning(sb, "There are errors in the filesystem, "
+                            "so online resizing is not allowed\n");
+               return -EPERM;
+       }
+
+       if (test_and_set_bit_lock(EXT4_RESIZING, &EXT4_SB(sb)->s_resize_flags))
+               ret = -EBUSY;
+
+       return ret;
+}
+
+void ext4_resize_end(struct super_block *sb)
+{
+       clear_bit_unlock(EXT4_RESIZING, &EXT4_SB(sb)->s_resize_flags);
+       smp_mb__after_clear_bit();
+}
+
 #define outside(b, first, last)        ((b) < (first) || (b) >= (last))
 #define inside(b, first, last) ((b) >= (first) && (b) < (last))
 
@@ -118,10 +147,8 @@ static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,
                brelse(bh);
                bh = ERR_PTR(err);
        } else {
-               lock_buffer(bh);
                memset(bh->b_data, 0, sb->s_blocksize);
                set_buffer_uptodate(bh);
-               unlock_buffer(bh);
        }
 
        return bh;
@@ -132,8 +159,7 @@ static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,
  * If that fails, restart the transaction & regain write access for the
  * buffer head which is used for block_bitmap modifications.
  */
-static int extend_or_restart_transaction(handle_t *handle, int thresh,
-                                        struct buffer_head *bh)
+static int extend_or_restart_transaction(handle_t *handle, int thresh)
 {
        int err;
 
@@ -144,9 +170,8 @@ static int extend_or_restart_transaction(handle_t *handle, int thresh,
        if (err < 0)
                return err;
        if (err) {
-               if ((err = ext4_journal_restart(handle, EXT4_MAX_TRANS_DATA)))
-                       return err;
-               if ((err = ext4_journal_get_write_access(handle, bh)))
+               err = ext4_journal_restart(handle, EXT4_MAX_TRANS_DATA);
+               if (err)
                        return err;
        }
 
@@ -181,21 +206,7 @@ static int setup_new_group_blocks(struct super_block *sb,
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
-       mutex_lock(&sbi->s_resize_lock);
-       if (input->group != sbi->s_groups_count) {
-               err = -EBUSY;
-               goto exit_journal;
-       }
-
-       if (IS_ERR(bh = bclean(handle, sb, input->block_bitmap))) {
-               err = PTR_ERR(bh);
-               goto exit_journal;
-       }
-
-       if (ext4_bg_has_super(sb, input->group)) {
-               ext4_debug("mark backup superblock %#04llx (+0)\n", start);
-               ext4_set_bit(0, bh->b_data);
-       }
+       BUG_ON(input->group != sbi->s_groups_count);
 
        /* Copy all of the GDT blocks into the backup in this group */
        for (i = 0, bit = 1, block = start + 1;
@@ -203,29 +214,26 @@ static int setup_new_group_blocks(struct super_block *sb,
                struct buffer_head *gdb;
 
                ext4_debug("update backup group %#04llx (+%d)\n", block, bit);
-
-               if ((err = extend_or_restart_transaction(handle, 1, bh)))
-                       goto exit_bh;
+               err = extend_or_restart_transaction(handle, 1);
+               if (err)
+                       goto exit_journal;
 
                gdb = sb_getblk(sb, block);
                if (!gdb) {
                        err = -EIO;
-                       goto exit_bh;
+                       goto exit_journal;
                }
                if ((err = ext4_journal_get_write_access(handle, gdb))) {
                        brelse(gdb);
-                       goto exit_bh;
+                       goto exit_journal;
                }
-               lock_buffer(gdb);
                memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size);
                set_buffer_uptodate(gdb);
-               unlock_buffer(gdb);
                err = ext4_handle_dirty_metadata(handle, NULL, gdb);
                if (unlikely(err)) {
                        brelse(gdb);
-                       goto exit_bh;
+                       goto exit_journal;
                }
-               ext4_set_bit(bit, bh->b_data);
                brelse(gdb);
        }
 
@@ -235,9 +243,22 @@ static int setup_new_group_blocks(struct super_block *sb,
        err = sb_issue_zeroout(sb, gdblocks + start + 1, reserved_gdb,
                               GFP_NOFS);
        if (err)
-               goto exit_bh;
-       for (i = 0, bit = gdblocks + 1; i < reserved_gdb; i++, bit++)
-               ext4_set_bit(bit, bh->b_data);
+               goto exit_journal;
+
+       err = extend_or_restart_transaction(handle, 2);
+       if (err)
+               goto exit_journal;
+
+       bh = bclean(handle, sb, input->block_bitmap);
+       if (IS_ERR(bh)) {
+               err = PTR_ERR(bh);
+               goto exit_journal;
+       }
+
+       if (ext4_bg_has_super(sb, input->group)) {
+               ext4_debug("mark backup group tables %#04llx (+0)\n", start);
+               ext4_set_bits(bh->b_data, 0, gdblocks + reserved_gdb + 1);
+       }
 
        ext4_debug("mark block bitmap %#04llx (+%llu)\n", input->block_bitmap,
                   input->block_bitmap - start);
@@ -253,12 +274,9 @@ static int setup_new_group_blocks(struct super_block *sb,
        err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group, GFP_NOFS);
        if (err)
                goto exit_bh;
-       for (i = 0, bit = input->inode_table - start;
-            i < sbi->s_itb_per_group; i++, bit++)
-               ext4_set_bit(bit, bh->b_data);
+       ext4_set_bits(bh->b_data, input->inode_table - start,
+                     sbi->s_itb_per_group);
 
-       if ((err = extend_or_restart_transaction(handle, 2, bh)))
-               goto exit_bh;
 
        ext4_mark_bitmap_end(input->blocks_count, sb->s_blocksize * 8,
                             bh->b_data);
@@ -285,7 +303,6 @@ exit_bh:
        brelse(bh);
 
 exit_journal:
-       mutex_unlock(&sbi->s_resize_lock);
        if ((err2 = ext4_journal_stop(handle)) && !err)
                err = err2;
 
@@ -377,15 +394,15 @@ static int verify_reserved_gdb(struct super_block *sb,
  * fail once we start modifying the data on disk, because JBD has no rollback.
  */
 static int add_new_gdb(handle_t *handle, struct inode *inode,
-                      struct ext4_new_group_data *input,
-                      struct buffer_head **primary)
+                      ext4_group_t group)
 {
        struct super_block *sb = inode->i_sb;
        struct ext4_super_block *es = EXT4_SB(sb)->s_es;
-       unsigned long gdb_num = input->group / EXT4_DESC_PER_BLOCK(sb);
+       unsigned long gdb_num = group / EXT4_DESC_PER_BLOCK(sb);
        ext4_fsblk_t gdblock = EXT4_SB(sb)->s_sbh->b_blocknr + 1 + gdb_num;
        struct buffer_head **o_group_desc, **n_group_desc;
        struct buffer_head *dind;
+       struct buffer_head *gdb_bh;
        int gdbackups;
        struct ext4_iloc iloc;
        __le32 *data;
@@ -408,11 +425,12 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
                return -EPERM;
        }
 
-       *primary = sb_bread(sb, gdblock);
-       if (!*primary)
+       gdb_bh = sb_bread(sb, gdblock);
+       if (!gdb_bh)
                return -EIO;
 
-       if ((gdbackups = verify_reserved_gdb(sb, *primary)) < 0) {
+       gdbackups = verify_reserved_gdb(sb, gdb_bh);
+       if (gdbackups < 0) {
                err = gdbackups;
                goto exit_bh;
        }
@@ -427,7 +445,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        data = (__le32 *)dind->b_data;
        if (le32_to_cpu(data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)]) != gdblock) {
                ext4_warning(sb, "new group %u GDT block %llu not reserved",
-                            input->group, gdblock);
+                            group, gdblock);
                err = -EINVAL;
                goto exit_dind;
        }
@@ -436,7 +454,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        if (unlikely(err))
                goto exit_dind;
 
-       err = ext4_journal_get_write_access(handle, *primary);
+       err = ext4_journal_get_write_access(handle, gdb_bh);
        if (unlikely(err))
                goto exit_sbh;
 
@@ -449,12 +467,13 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        if (unlikely(err))
                goto exit_dindj;
 
-       n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
-                       GFP_NOFS);
+       n_group_desc = ext4_kvmalloc((gdb_num + 1) *
+                                    sizeof(struct buffer_head *),
+                                    GFP_NOFS);
        if (!n_group_desc) {
                err = -ENOMEM;
-               ext4_warning(sb,
-                             "not enough memory for %lu groups", gdb_num + 1);
+               ext4_warning(sb, "not enough memory for %lu groups",
+                            gdb_num + 1);
                goto exit_inode;
        }
 
@@ -475,8 +494,8 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        }
        inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9;
        ext4_mark_iloc_dirty(handle, inode, &iloc);
-       memset((*primary)->b_data, 0, sb->s_blocksize);
-       err = ext4_handle_dirty_metadata(handle, NULL, *primary);
+       memset(gdb_bh->b_data, 0, sb->s_blocksize);
+       err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh);
        if (unlikely(err)) {
                ext4_std_error(sb, err);
                goto exit_inode;
@@ -486,10 +505,10 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        o_group_desc = EXT4_SB(sb)->s_group_desc;
        memcpy(n_group_desc, o_group_desc,
               EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
-       n_group_desc[gdb_num] = *primary;
+       n_group_desc[gdb_num] = gdb_bh;
        EXT4_SB(sb)->s_group_desc = n_group_desc;
        EXT4_SB(sb)->s_gdb_count++;
-       kfree(o_group_desc);
+       ext4_kvfree(o_group_desc);
 
        le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
        err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
@@ -499,6 +518,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        return err;
 
 exit_inode:
+       ext4_kvfree(n_group_desc);
        /* ext4_handle_release_buffer(handle, iloc.bh); */
        brelse(iloc.bh);
 exit_dindj:
@@ -508,7 +528,7 @@ exit_sbh:
 exit_dind:
        brelse(dind);
 exit_bh:
-       brelse(*primary);
+       brelse(gdb_bh);
 
        ext4_debug("leaving with error %d\n", err);
        return err;
@@ -528,7 +548,7 @@ exit_bh:
  * backup GDT blocks are stored in their reserved primary GDT block.
  */
 static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
-                             struct ext4_new_group_data *input)
+                             ext4_group_t group)
 {
        struct super_block *sb = inode->i_sb;
        int reserved_gdb =le16_to_cpu(EXT4_SB(sb)->s_es->s_reserved_gdt_blocks);
@@ -599,7 +619,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
         * Finally we can add each of the reserved backup GDT blocks from
         * the new group to its reserved primary GDT block.
         */
-       blk = input->group * EXT4_BLOCKS_PER_GROUP(sb);
+       blk = group * EXT4_BLOCKS_PER_GROUP(sb);
        for (i = 0; i < reserved_gdb; i++) {
                int err2;
                data = (__le32 *)primary[i]->b_data;
@@ -799,13 +819,6 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
                goto exit_put;
        }
 
-       mutex_lock(&sbi->s_resize_lock);
-       if (input->group != sbi->s_groups_count) {
-               ext4_warning(sb, "multiple resizers run on filesystem!");
-               err = -EBUSY;
-               goto exit_journal;
-       }
-
        if ((err = ext4_journal_get_write_access(handle, sbi->s_sbh)))
                goto exit_journal;
 
@@ -820,16 +833,25 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
                if ((err = ext4_journal_get_write_access(handle, primary)))
                        goto exit_journal;
 
-               if (reserved_gdb && ext4_bg_num_gdb(sb, input->group) &&
-                   (err = reserve_backup_gdb(handle, inode, input)))
+               if (reserved_gdb && ext4_bg_num_gdb(sb, input->group)) {
+                       err = reserve_backup_gdb(handle, inode, input->group);
+                       if (err)
+                               goto exit_journal;
+               }
+       } else {
+               /*
+                * Note that we can access new group descriptor block safely
+                * only if add_new_gdb() succeeds.
+                */
+               err = add_new_gdb(handle, inode, input->group);
+               if (err)
                        goto exit_journal;
-       } else if ((err = add_new_gdb(handle, inode, input, &primary)))
-               goto exit_journal;
+               primary = sbi->s_group_desc[gdb_num];
+       }
 
         /*
          * OK, now we've set up the new group.  Time to make it active.
          *
-         * We do not lock all allocations via s_resize_lock
          * so we have to be safe wrt. concurrent accesses the group
          * data.  So we need to be careful to set all of the relevant
          * group descriptor data etc. *before* we enable the group.
@@ -886,13 +908,9 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
         *
         * The precise rules we use are:
         *
-        * * Writers of s_groups_count *must* hold s_resize_lock
-        * AND
         * * Writers must perform a smp_wmb() after updating all dependent
         *   data and before modifying the groups count
         *
-        * * Readers must hold s_resize_lock over the access
-        * OR
         * * Readers must perform an smp_rmb() after reading the groups count
         *   and before reading any dependent data.
         *
@@ -937,10 +955,9 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
        ext4_handle_dirty_super(handle, sb);
 
 exit_journal:
-       mutex_unlock(&sbi->s_resize_lock);
        if ((err2 = ext4_journal_stop(handle)) && !err)
                err = err2;
-       if (!err) {
+       if (!err && primary) {
                update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es,
                               sizeof(struct ext4_super_block));
                update_backups(sb, primary->b_blocknr, primary->b_data,
@@ -969,16 +986,13 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
        ext4_grpblk_t add;
        struct buffer_head *bh;
        handle_t *handle;
-       int err;
+       int err, err2;
        ext4_group_t group;
 
-       /* We don't need to worry about locking wrt other resizers just
-        * yet: we're going to revalidate es->s_blocks_count after
-        * taking the s_resize_lock below. */
        o_blocks_count = ext4_blocks_count(es);
 
        if (test_opt(sb, DEBUG))
-               printk(KERN_DEBUG "EXT4-fs: extending last group from %llu uto %llu blocks\n",
+               printk(KERN_DEBUG "EXT4-fs: extending last group from %llu to %llu blocks\n",
                       o_blocks_count, n_blocks_count);
 
        if (n_blocks_count == 0 || n_blocks_count == o_blocks_count)
@@ -995,7 +1009,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
 
        if (n_blocks_count < o_blocks_count) {
                ext4_warning(sb, "can't shrink FS - resize aborted");
-               return -EBUSY;
+               return -EINVAL;
        }
 
        /* Handle the remaining blocks in the last group only. */
@@ -1038,32 +1052,25 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
                goto exit_put;
        }
 
-       mutex_lock(&EXT4_SB(sb)->s_resize_lock);
-       if (o_blocks_count != ext4_blocks_count(es)) {
-               ext4_warning(sb, "multiple resizers run on filesystem!");
-               mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
-               ext4_journal_stop(handle);
-               err = -EBUSY;
-               goto exit_put;
-       }
-
        if ((err = ext4_journal_get_write_access(handle,
                                                 EXT4_SB(sb)->s_sbh))) {
                ext4_warning(sb, "error %d on journal write access", err);
-               mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
                ext4_journal_stop(handle);
                goto exit_put;
        }
        ext4_blocks_count_set(es, o_blocks_count + add);
-       mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
        ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count,
                   o_blocks_count + add);
        /* We add the blocks to the bitmap and set the group need init bit */
-       ext4_add_groupblocks(handle, sb, o_blocks_count, add);
+       err = ext4_group_add_blocks(handle, sb, o_blocks_count, add);
        ext4_handle_dirty_super(handle, sb);
        ext4_debug("freed blocks %llu through %llu\n", o_blocks_count,
                   o_blocks_count + add);
-       if ((err = ext4_journal_stop(handle)))
+       err2 = ext4_journal_stop(handle);
+       if (!err && err2)
+               err = err2;
+
+       if (err)
                goto exit_put;
 
        if (test_opt(sb, DEBUG))
index 9ea71aa..4687fea 100644 (file)
@@ -110,6 +110,35 @@ static struct file_system_type ext3_fs_type = {
 #define IS_EXT3_SB(sb) (0)
 #endif
 
+void *ext4_kvmalloc(size_t size, gfp_t flags)
+{
+       void *ret;
+
+       ret = kmalloc(size, flags);
+       if (!ret)
+               ret = __vmalloc(size, flags, PAGE_KERNEL);
+       return ret;
+}
+
+void *ext4_kvzalloc(size_t size, gfp_t flags)
+{
+       void *ret;
+
+       ret = kzalloc(size, flags);
+       if (!ret)
+               ret = __vmalloc(size, flags | __GFP_ZERO, PAGE_KERNEL);
+       return ret;
+}
+
+void ext4_kvfree(void *ptr)
+{
+       if (is_vmalloc_addr(ptr))
+               vfree(ptr);
+       else
+               kfree(ptr);
+
+}
+
 ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
                               struct ext4_group_desc *bg)
 {
@@ -269,6 +298,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
        journal_t *journal;
        handle_t  *handle;
 
+       trace_ext4_journal_start(sb, nblocks, _RET_IP_);
        if (sb->s_flags & MS_RDONLY)
                return ERR_PTR(-EROFS);
 
@@ -789,11 +819,8 @@ static void ext4_put_super(struct super_block *sb)
 
        for (i = 0; i < sbi->s_gdb_count; i++)
                brelse(sbi->s_group_desc[i]);
-       kfree(sbi->s_group_desc);
-       if (is_vmalloc_addr(sbi->s_flex_groups))
-               vfree(sbi->s_flex_groups);
-       else
-               kfree(sbi->s_flex_groups);
+       ext4_kvfree(sbi->s_group_desc);
+       ext4_kvfree(sbi->s_flex_groups);
        percpu_counter_destroy(&sbi->s_freeblocks_counter);
        percpu_counter_destroy(&sbi->s_freeinodes_counter);
        percpu_counter_destroy(&sbi->s_dirs_counter);
@@ -1976,15 +2003,11 @@ static int ext4_fill_flex_info(struct super_block *sb)
                        ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) <<
                              EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex;
        size = flex_group_count * sizeof(struct flex_groups);
-       sbi->s_flex_groups = kzalloc(size, GFP_KERNEL);
+       sbi->s_flex_groups = ext4_kvzalloc(size, GFP_KERNEL);
        if (sbi->s_flex_groups == NULL) {
-               sbi->s_flex_groups = vzalloc(size);
-               if (sbi->s_flex_groups == NULL) {
-                       ext4_msg(sb, KERN_ERR,
-                                "not enough memory for %u flex groups",
-                                flex_group_count);
-                       goto failed;
-               }
+               ext4_msg(sb, KERN_ERR, "not enough memory for %u flex groups",
+                        flex_group_count);
+               goto failed;
        }
 
        for (i = 0; i < sbi->s_groups_count; i++) {
@@ -2383,17 +2406,25 @@ static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi)
        unsigned long stride = le16_to_cpu(sbi->s_es->s_raid_stride);
        unsigned long stripe_width =
                        le32_to_cpu(sbi->s_es->s_raid_stripe_width);
+       int ret;
 
        if (sbi->s_stripe && sbi->s_stripe <= sbi->s_blocks_per_group)
-               return sbi->s_stripe;
-
-       if (stripe_width <= sbi->s_blocks_per_group)
-               return stripe_width;
+               ret = sbi->s_stripe;
+       else if (stripe_width <= sbi->s_blocks_per_group)
+               ret = stripe_width;
+       else if (stride <= sbi->s_blocks_per_group)
+               ret = stride;
+       else
+               ret = 0;
 
-       if (stride <= sbi->s_blocks_per_group)
-               return stride;
+       /*
+        * If the stripe width is 1, this makes no sense and
+        * we set it to 0 to turn off stripe handling code.
+        */
+       if (ret <= 1)
+               ret = 0;
 
-       return 0;
+       return ret;
 }
 
 /* sysfs supprt */
@@ -3408,8 +3439,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                        (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
        db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
                   EXT4_DESC_PER_BLOCK(sb);
-       sbi->s_group_desc = kmalloc(db_count * sizeof(struct buffer_head *),
-                                   GFP_KERNEL);
+       sbi->s_group_desc = ext4_kvmalloc(db_count *
+                                         sizeof(struct buffer_head *),
+                                         GFP_KERNEL);
        if (sbi->s_group_desc == NULL) {
                ext4_msg(sb, KERN_ERR, "not enough memory");
                goto failed_mount;
@@ -3491,7 +3523,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 
        INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
        mutex_init(&sbi->s_orphan_lock);
-       mutex_init(&sbi->s_resize_lock);
+       sbi->s_resize_flags = 0;
 
        sb->s_root = NULL;
 
@@ -3741,12 +3773,8 @@ failed_mount_wq:
        }
 failed_mount3:
        del_timer(&sbi->s_err_report);
-       if (sbi->s_flex_groups) {
-               if (is_vmalloc_addr(sbi->s_flex_groups))
-                       vfree(sbi->s_flex_groups);
-               else
-                       kfree(sbi->s_flex_groups);
-       }
+       if (sbi->s_flex_groups)
+               ext4_kvfree(sbi->s_flex_groups);
        percpu_counter_destroy(&sbi->s_freeblocks_counter);
        percpu_counter_destroy(&sbi->s_freeinodes_counter);
        percpu_counter_destroy(&sbi->s_dirs_counter);
@@ -3756,7 +3784,7 @@ failed_mount3:
 failed_mount2:
        for (i = 0; i < db_count; i++)
                brelse(sbi->s_group_desc[i]);
-       kfree(sbi->s_group_desc);
+       ext4_kvfree(sbi->s_group_desc);
 failed_mount:
        if (sbi->s_proc) {
                remove_proc_entry(sb->s_id, ext4_proc_root);
diff --git a/fs/ext4/truncate.h b/fs/ext4/truncate.h
new file mode 100644 (file)
index 0000000..011ba66
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * linux/fs/ext4/truncate.h
+ *
+ * Common inline functions needed for truncate support
+ */
+
+/*
+ * Truncate blocks that were not used by write. We have to truncate the
+ * pagecache as well so that corresponding buffers get properly unmapped.
+ */
+static inline void ext4_truncate_failed_write(struct inode *inode)
+{
+       truncate_inode_pages(inode->i_mapping, inode->i_size);
+       ext4_truncate(inode);
+}
+
+/*
+ * Work out how many blocks we need to proceed with the next chunk of a
+ * truncate transaction.
+ */
+static inline unsigned long ext4_blocks_for_truncate(struct inode *inode)
+{
+       ext4_lblk_t needed;
+
+       needed = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9);
+
+       /* Give ourselves just enough room to cope with inodes in which
+        * i_blocks is corrupt: we've seen disk corruptions in the past
+        * which resulted in random data in an inode which looked enough
+        * like a regular file for ext4 to try to delete it.  Things
+        * will go a bit crazy if that happens, but at least we should
+        * try not to panic the whole kernel. */
+       if (needed < 2)
+               needed = 2;
+
+       /* But we need to bound the transaction so we don't overflow the
+        * journal. */
+       if (needed > EXT4_MAX_TRANS_DATA)
+               needed = EXT4_MAX_TRANS_DATA;
+
+       return EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
+}
+
index 1599aa9..04cf3b9 100644 (file)
@@ -618,7 +618,12 @@ static long __writeback_inodes_wb(struct bdi_writeback *wb,
                struct super_block *sb = inode->i_sb;
 
                if (!grab_super_passive(sb)) {
-                       requeue_io(inode, wb);
+                       /*
+                        * grab_super_passive() may fail consistently due to
+                        * s_umount being grabbed by someone else. Don't use
+                        * requeue_io() to avoid busy retrying the inode/sb.
+                        */
+                       redirty_tail(inode, wb);
                        continue;
                }
                wrote += writeback_sb_inodes(sb, wb, work);
index d5e33a0..d0dddac 100644 (file)
@@ -82,18 +82,14 @@ generic_acl_set(struct dentry *dentry, const char *name, const void *value,
                        return PTR_ERR(acl);
        }
        if (acl) {
-               mode_t mode;
-
                error = posix_acl_valid(acl);
                if (error)
                        goto failed;
                switch (type) {
                case ACL_TYPE_ACCESS:
-                       mode = inode->i_mode;
-                       error = posix_acl_equiv_mode(acl, &mode);
+                       error = posix_acl_equiv_mode(acl, &inode->i_mode);
                        if (error < 0)
                                goto failed;
-                       inode->i_mode = mode;
                        inode->i_ctime = CURRENT_TIME;
                        if (error == 0) {
                                posix_acl_release(acl);
@@ -125,21 +121,20 @@ int
 generic_acl_init(struct inode *inode, struct inode *dir)
 {
        struct posix_acl *acl = NULL;
-       mode_t mode = inode->i_mode;
        int error;
 
-       inode->i_mode = mode & ~current_umask();
        if (!S_ISLNK(inode->i_mode))
                acl = get_cached_acl(dir, ACL_TYPE_DEFAULT);
        if (acl) {
                if (S_ISDIR(inode->i_mode))
                        set_cached_acl(inode, ACL_TYPE_DEFAULT, acl);
-               error = posix_acl_create(&acl, GFP_KERNEL, &mode);
+               error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
                if (error < 0)
                        return error;
-               inode->i_mode = mode;
                if (error > 0)
                        set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
+       } else {
+               inode->i_mode &= ~current_umask();
        }
        error = 0;
 
index 884c9af..34501b6 100644 (file)
@@ -72,7 +72,7 @@ struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
        return gfs2_acl_get(GFS2_I(inode), type);
 }
 
-static int gfs2_set_mode(struct inode *inode, mode_t mode)
+static int gfs2_set_mode(struct inode *inode, umode_t mode)
 {
        int error = 0;
 
@@ -117,7 +117,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct posix_acl *acl;
-       mode_t mode = inode->i_mode;
+       umode_t mode = inode->i_mode;
        int error = 0;
 
        if (!sdp->sd_args.ar_posix_acl)
@@ -276,7 +276,7 @@ static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
                goto out_release;
 
        if (type == ACL_TYPE_ACCESS) {
-               mode_t mode = inode->i_mode;
+               umode_t mode = inode->i_mode;
                error = posix_acl_equiv_mode(acl, &mode);
 
                if (error <= 0) {
index 8635be5..970ea98 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/statfs.h>
 #include <linux/types.h>
 #include <linux/pid_namespace.h>
+#include <linux/namei.h>
 #include <asm/uaccess.h>
 #include "os.h"
 
index d0c72ff..73920d5 100644 (file)
@@ -143,6 +143,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
        inode->i_op = &empty_iops;
        inode->i_fop = &empty_fops;
        inode->i_nlink = 1;
+       inode->i_opflags = 0;
        inode->i_uid = 0;
        inode->i_gid = 0;
        atomic_set(&inode->i_writecount, 0);
@@ -399,12 +400,12 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval)
 EXPORT_SYMBOL(__insert_inode_hash);
 
 /**
- *     remove_inode_hash - remove an inode from the hash
+ *     __remove_inode_hash - remove an inode from the hash
  *     @inode: inode to unhash
  *
  *     Remove an inode from the superblock.
  */
-void remove_inode_hash(struct inode *inode)
+void __remove_inode_hash(struct inode *inode)
 {
        spin_lock(&inode_hash_lock);
        spin_lock(&inode->i_lock);
@@ -412,7 +413,7 @@ void remove_inode_hash(struct inode *inode)
        spin_unlock(&inode->i_lock);
        spin_unlock(&inode_hash_lock);
 }
-EXPORT_SYMBOL(remove_inode_hash);
+EXPORT_SYMBOL(__remove_inode_hash);
 
 void end_writeback(struct inode *inode)
 {
@@ -454,7 +455,9 @@ static void evict(struct inode *inode)
        BUG_ON(!(inode->i_state & I_FREEING));
        BUG_ON(!list_empty(&inode->i_lru));
 
-       inode_wb_list_del(inode);
+       if (!list_empty(&inode->i_wb_list))
+               inode_wb_list_del(inode);
+
        inode_sb_list_del(inode);
 
        if (op->evict_inode) {
@@ -1328,7 +1331,8 @@ static void iput_final(struct inode *inode)
        }
 
        inode->i_state |= I_FREEING;
-       inode_lru_list_del(inode);
+       if (!list_empty(&inode->i_lru))
+               inode_lru_list_del(inode);
        spin_unlock(&inode->i_lock);
 
        evict(inode);
index 2c62c5a..16a698b 100644 (file)
@@ -257,9 +257,12 @@ static void
 __flush_batch(journal_t *journal, int *batch_count)
 {
        int i;
+       struct blk_plug plug;
 
+       blk_start_plug(&plug);
        for (i = 0; i < *batch_count; i++)
-               write_dirty_buffer(journal->j_chkpt_bhs[i], WRITE);
+               write_dirty_buffer(journal->j_chkpt_bhs[i], WRITE_SYNC);
+       blk_finish_plug(&plug);
 
        for (i = 0; i < *batch_count; i++) {
                struct buffer_head *bh = journal->j_chkpt_bhs[i];
index 0dfa5b5..f24df13 100644 (file)
@@ -2390,73 +2390,6 @@ static void __exit journal_exit(void)
        jbd2_journal_destroy_caches();
 }
 
-/* 
- * jbd2_dev_to_name is a utility function used by the jbd2 and ext4 
- * tracing infrastructure to map a dev_t to a device name.
- *
- * The caller should use rcu_read_lock() in order to make sure the
- * device name stays valid until its done with it.  We use
- * rcu_read_lock() as well to make sure we're safe in case the caller
- * gets sloppy, and because rcu_read_lock() is cheap and can be safely
- * nested.
- */
-struct devname_cache {
-       struct rcu_head rcu;
-       dev_t           device;
-       char            devname[BDEVNAME_SIZE];
-};
-#define CACHE_SIZE_BITS 6
-static struct devname_cache *devcache[1 << CACHE_SIZE_BITS];
-static DEFINE_SPINLOCK(devname_cache_lock);
-
-static void free_devcache(struct rcu_head *rcu)
-{
-       kfree(rcu);
-}
-
-const char *jbd2_dev_to_name(dev_t device)
-{
-       int     i = hash_32(device, CACHE_SIZE_BITS);
-       char    *ret;
-       struct block_device *bd;
-       static struct devname_cache *new_dev;
-
-       rcu_read_lock();
-       if (devcache[i] && devcache[i]->device == device) {
-               ret = devcache[i]->devname;
-               rcu_read_unlock();
-               return ret;
-       }
-       rcu_read_unlock();
-
-       new_dev = kmalloc(sizeof(struct devname_cache), GFP_KERNEL);
-       if (!new_dev)
-               return "NODEV-ALLOCFAILURE"; /* Something non-NULL */
-       bd = bdget(device);
-       spin_lock(&devname_cache_lock);
-       if (devcache[i]) {
-               if (devcache[i]->device == device) {
-                       kfree(new_dev);
-                       bdput(bd);
-                       ret = devcache[i]->devname;
-                       spin_unlock(&devname_cache_lock);
-                       return ret;
-               }
-               call_rcu(&devcache[i]->rcu, free_devcache);
-       }
-       devcache[i] = new_dev;
-       devcache[i]->device = device;
-       if (bd) {
-               bdevname(bd, devcache[i]->devname);
-               bdput(bd);
-       } else
-               __bdevname(device, devcache[i]->devname);
-       ret = devcache[i]->devname;
-       spin_unlock(&devname_cache_lock);
-       return ret;
-}
-EXPORT_SYMBOL(jbd2_dev_to_name);
-
 MODULE_LICENSE("GPL");
 module_init(journal_init);
 module_exit(journal_exit);
index 27c511a..926d020 100644 (file)
@@ -227,7 +227,7 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
        case ACL_TYPE_ACCESS:
                xprefix = JFFS2_XPREFIX_ACL_ACCESS;
                if (acl) {
-                       mode_t mode = inode->i_mode;
+                       umode_t mode = inode->i_mode;
                        rc = posix_acl_equiv_mode(acl, &mode);
                        if (rc < 0)
                                return rc;
@@ -259,7 +259,7 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
        return rc;
 }
 
-int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, mode_t *i_mode)
+int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, umode_t *i_mode)
 {
        struct posix_acl *acl;
        int rc;
index b3421c7..9b47724 100644 (file)
@@ -28,7 +28,7 @@ struct jffs2_acl_header {
 
 struct posix_acl *jffs2_get_acl(struct inode *inode, int type);
 extern int jffs2_acl_chmod(struct inode *);
-extern int jffs2_init_acl_pre(struct inode *, struct inode *, mode_t *);
+extern int jffs2_init_acl_pre(struct inode *, struct inode *, umode_t *);
 extern int jffs2_init_acl_post(struct inode *);
 
 extern const struct xattr_handler jffs2_acl_access_xattr_handler;
index b81b35d..bbcb975 100644 (file)
@@ -406,7 +406,7 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
 
 /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
    fill in the raw_inode while you're at it. */
-struct inode *jffs2_new_inode (struct inode *dir_i, mode_t mode, struct jffs2_raw_inode *ri)
+struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_raw_inode *ri)
 {
        struct inode *inode;
        struct super_block *sb = dir_i->i_sb;
index 526979c..6c1755c 100644 (file)
@@ -173,7 +173,7 @@ int jffs2_do_setattr (struct inode *, struct iattr *);
 struct inode *jffs2_iget(struct super_block *, unsigned long);
 void jffs2_evict_inode (struct inode *);
 void jffs2_dirty_inode(struct inode *inode, int flags);
-struct inode *jffs2_new_inode (struct inode *dir_i, mode_t mode,
+struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode,
                               struct jffs2_raw_inode *ri);
 int jffs2_statfs (struct dentry *, struct kstatfs *);
 int jffs2_remount_fs (struct super_block *, int *, char *);
index b3a32ca..45559dc 100644 (file)
@@ -127,16 +127,14 @@ int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
                return PTR_ERR(acl);
 
        if (acl) {
-               mode_t mode = inode->i_mode;
                if (S_ISDIR(inode->i_mode)) {
                        rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl);
                        if (rc)
                                goto cleanup;
                }
-               rc = posix_acl_create(&acl, GFP_KERNEL, &mode);
+               rc = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
                if (rc < 0)
                        goto cleanup; /* posix_acl_release(NULL) is no-op */
-               inode->i_mode = mode;
                if (rc > 0)
                        rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
 cleanup:
index 24838f1..e87fede 100644 (file)
@@ -693,8 +693,7 @@ static int can_set_system_xattr(struct inode *inode, const char *name,
                        return rc;
                }
                if (acl) {
-                       mode_t mode = inode->i_mode;
-                       rc = posix_acl_equiv_mode(acl, &mode);
+                       rc = posix_acl_equiv_mode(acl, &inode->i_mode);
                        posix_acl_release(acl);
                        if (rc < 0) {
                                printk(KERN_ERR
@@ -702,7 +701,6 @@ static int can_set_system_xattr(struct inode *inode, const char *name,
                                       rc);
                                return rc;
                        }
-                       inode->i_mode = mode;
                        mark_inode_dirty(inode);
                }
                /*
index f8c69d3..2826db3 100644 (file)
@@ -179,19 +179,14 @@ static int check_acl(struct inode *inode, int mask)
 #ifdef CONFIG_FS_POSIX_ACL
        struct posix_acl *acl;
 
-       /*
-        * Under RCU walk, we cannot even do a "get_cached_acl()",
-        * because that involves locking and getting a refcount on
-        * a cached ACL.
-        *
-        * So the only case we handle during RCU walking is the
-        * case of a cached "no ACL at all", which needs no locks
-        * or refcounts.
-        */
        if (mask & MAY_NOT_BLOCK) {
-               if (negative_cached_acl(inode, ACL_TYPE_ACCESS))
+               acl = get_cached_acl_rcu(inode, ACL_TYPE_ACCESS);
+               if (!acl)
                        return -EAGAIN;
-               return -ECHILD;
+               /* no ->get_acl() calls in RCU mode... */
+               if (acl == ACL_NOT_CACHED)
+                       return -ECHILD;
+               return posix_acl_permission(inode, acl, mask & ~MAY_NOT_BLOCK);
        }
 
        acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
@@ -313,6 +308,26 @@ int generic_permission(struct inode *inode, int mask)
        return -EACCES;
 }
 
+/*
+ * We _really_ want to just do "generic_permission()" without
+ * even looking at the inode->i_op values. So we keep a cache
+ * flag in inode->i_opflags, that says "this has not special
+ * permission function, use the fast case".
+ */
+static inline int do_inode_permission(struct inode *inode, int mask)
+{
+       if (unlikely(!(inode->i_opflags & IOP_FASTPERM))) {
+               if (likely(inode->i_op->permission))
+                       return inode->i_op->permission(inode, mask);
+
+               /* This gets set once for the inode lifetime */
+               spin_lock(&inode->i_lock);
+               inode->i_opflags |= IOP_FASTPERM;
+               spin_unlock(&inode->i_lock);
+       }
+       return generic_permission(inode, mask);
+}
+
 /**
  * inode_permission  -  check for access rights to a given inode
  * @inode:     inode to check permission on
@@ -327,7 +342,7 @@ int inode_permission(struct inode *inode, int mask)
 {
        int retval;
 
-       if (mask & MAY_WRITE) {
+       if (unlikely(mask & MAY_WRITE)) {
                umode_t mode = inode->i_mode;
 
                /*
@@ -344,11 +359,7 @@ int inode_permission(struct inode *inode, int mask)
                        return -EACCES;
        }
 
-       if (inode->i_op->permission)
-               retval = inode->i_op->permission(inode, mask);
-       else
-               retval = generic_permission(inode, mask);
-
+       retval = do_inode_permission(inode, mask);
        if (retval)
                return retval;
 
@@ -716,19 +727,25 @@ static int follow_automount(struct path *path, unsigned flags,
        if ((flags & LOOKUP_NO_AUTOMOUNT) && !(flags & LOOKUP_PARENT))
                return -EISDIR; /* we actually want to stop here */
 
-       /* We want to mount if someone is trying to open/create a file of any
-        * type under the mountpoint, wants to traverse through the mountpoint
-        * or wants to open the mounted directory.
-        *
+       /*
         * We don't want to mount if someone's just doing a stat and they've
         * set AT_SYMLINK_NOFOLLOW - unless they're stat'ing a directory and
         * appended a '/' to the name.
         */
-       if (!(flags & LOOKUP_FOLLOW) &&
-           !(flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
-                      LOOKUP_OPEN | LOOKUP_CREATE)))
-               return -EISDIR;
-
+       if (!(flags & LOOKUP_FOLLOW)) {
+               /* We do, however, want to mount if someone wants to open or
+                * create a file of any type under the mountpoint, wants to
+                * traverse through the mountpoint or wants to open the mounted
+                * directory.
+                * Also, autofs may mark negative dentries as being automount
+                * points.  These will need the attentions of the daemon to
+                * instantiate them before they can be used.
+                */
+               if (!(flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
+                            LOOKUP_OPEN | LOOKUP_CREATE)) &&
+                   path->dentry->d_inode)
+                       return -EISDIR;
+       }
        current->total_link_count++;
        if (current->total_link_count >= 40)
                return -ELOOP;
@@ -1244,6 +1261,26 @@ static void terminate_walk(struct nameidata *nd)
        }
 }
 
+/*
+ * Do we need to follow links? We _really_ want to be able
+ * to do this check without having to look at inode->i_op,
+ * so we keep a cache of "no, this doesn't need follow_link"
+ * for the common case.
+ */
+static inline int should_follow_link(struct inode *inode, int follow)
+{
+       if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) {
+               if (likely(inode->i_op->follow_link))
+                       return follow;
+
+               /* This gets set once for the inode lifetime */
+               spin_lock(&inode->i_lock);
+               inode->i_opflags |= IOP_NOFOLLOW;
+               spin_unlock(&inode->i_lock);
+       }
+       return 0;
+}
+
 static inline int walk_component(struct nameidata *nd, struct path *path,
                struct qstr *name, int type, int follow)
 {
@@ -1266,7 +1303,7 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
                terminate_walk(nd);
                return -ENOENT;
        }
-       if (unlikely(inode->i_op->follow_link) && follow) {
+       if (should_follow_link(inode, follow)) {
                if (nd->flags & LOOKUP_RCU) {
                        if (unlikely(unlazy_walk(nd, path->dentry))) {
                                terminate_walk(nd);
@@ -1318,6 +1355,26 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
        return res;
 }
 
+/*
+ * We really don't want to look at inode->i_op->lookup
+ * when we don't have to. So we keep a cache bit in
+ * the inode ->i_opflags field that says "yes, we can
+ * do lookup on this inode".
+ */
+static inline int can_lookup(struct inode *inode)
+{
+       if (likely(inode->i_opflags & IOP_LOOKUP))
+               return 1;
+       if (likely(!inode->i_op->lookup))
+               return 0;
+
+       /* We do this once for the lifetime of the inode */
+       spin_lock(&inode->i_lock);
+       inode->i_opflags |= IOP_LOOKUP;
+       spin_unlock(&inode->i_lock);
+       return 1;
+}
+
 /*
  * Name resolution.
  * This is the basic name resolution function, turning a pathname into
@@ -1397,10 +1454,10 @@ static int link_path_walk(const char *name, struct nameidata *nd)
                        if (err)
                                return err;
                }
+               if (can_lookup(nd->inode))
+                       continue;
                err = -ENOTDIR; 
-               if (!nd->inode->i_op->lookup)
-                       break;
-               continue;
+               break;
                /* here ends the main loop */
 
 last_component:
index 2cde5d9..dbcd821 100644 (file)
@@ -88,15 +88,15 @@ config NFS_V4_1
 config PNFS_FILE_LAYOUT
        tristate
 
+config PNFS_BLOCK
+       tristate
+       depends on NFS_FS && NFS_V4_1 && BLK_DEV_DM
+       default m
+
 config PNFS_OBJLAYOUT
-       tristate "Provide support for the pNFS Objects Layout Driver for NFSv4.1 pNFS (EXPERIMENTAL)"
+       tristate
        depends on NFS_FS && NFS_V4_1 && SCSI_OSD_ULD
-       help
-         Say M here if you want your pNFS client to support the Objects Layout Driver.
-         Requires the SCSI osd initiator library (SCSI_OSD_INITIATOR) and
-         upper level driver (SCSI_OSD_ULD).
-
-         If unsure, say N.
+       default m
 
 config ROOT_NFS
        bool "Root file system on NFS"
index 6a34f7d..b58613d 100644 (file)
@@ -23,3 +23,4 @@ obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
 nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o
 
 obj-$(CONFIG_PNFS_OBJLAYOUT) += objlayout/
+obj-$(CONFIG_PNFS_BLOCK) += blocklayout/
diff --git a/fs/nfs/blocklayout/Makefile b/fs/nfs/blocklayout/Makefile
new file mode 100644 (file)
index 0000000..d581550
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the pNFS block layout driver kernel module
+#
+obj-$(CONFIG_PNFS_BLOCK) += blocklayoutdriver.o
+blocklayoutdriver-objs := blocklayout.o extents.o blocklayoutdev.o blocklayoutdm.o
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
new file mode 100644 (file)
index 0000000..e56564d
--- /dev/null
@@ -0,0 +1,1019 @@
+/*
+ *  linux/fs/nfs/blocklayout/blocklayout.c
+ *
+ *  Module for the NFSv4.1 pNFS block layout driver.
+ *
+ *  Copyright (c) 2006 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@citi.umich.edu>
+ *  Fred Isaman <iisaman@umich.edu>
+ *
+ * permission is granted to use, copy, create derivative works and
+ * redistribute this software and such derivative works for any purpose,
+ * so long as the name of the university of michigan is not used in
+ * any advertising or publicity pertaining to the use or distribution
+ * of this software without specific, written prior authorization.  if
+ * the above copyright notice or any other identification of the
+ * university of michigan is included in any copy of any portion of
+ * this software, then the disclaimer below must also be included.
+ *
+ * this software is provided as is, without representation from the
+ * university of michigan as to its fitness for any purpose, and without
+ * warranty by the university of michigan of any kind, either express
+ * or implied, including without limitation the implied warranties of
+ * merchantability and fitness for a particular purpose.  the regents
+ * of the university of michigan shall not be liable for any damages,
+ * including special, indirect, incidental, or consequential damages,
+ * with respect to any claim arising out or in connection with the use
+ * of the software, even if it has been or is hereafter advised of the
+ * possibility of such damages.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/bio.h>         /* struct bio */
+#include <linux/buffer_head.h> /* various write calls */
+
+#include "blocklayout.h"
+
+#define NFSDBG_FACILITY        NFSDBG_PNFS_LD
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Andy Adamson <andros@citi.umich.edu>");
+MODULE_DESCRIPTION("The NFSv4.1 pNFS Block layout driver");
+
+struct dentry *bl_device_pipe;
+wait_queue_head_t bl_wq;
+
+static void print_page(struct page *page)
+{
+       dprintk("PRINTPAGE page %p\n", page);
+       dprintk("       PagePrivate %d\n", PagePrivate(page));
+       dprintk("       PageUptodate %d\n", PageUptodate(page));
+       dprintk("       PageError %d\n", PageError(page));
+       dprintk("       PageDirty %d\n", PageDirty(page));
+       dprintk("       PageReferenced %d\n", PageReferenced(page));
+       dprintk("       PageLocked %d\n", PageLocked(page));
+       dprintk("       PageWriteback %d\n", PageWriteback(page));
+       dprintk("       PageMappedToDisk %d\n", PageMappedToDisk(page));
+       dprintk("\n");
+}
+
+/* Given the be associated with isect, determine if page data needs to be
+ * initialized.
+ */
+static int is_hole(struct pnfs_block_extent *be, sector_t isect)
+{
+       if (be->be_state == PNFS_BLOCK_NONE_DATA)
+               return 1;
+       else if (be->be_state != PNFS_BLOCK_INVALID_DATA)
+               return 0;
+       else
+               return !bl_is_sector_init(be->be_inval, isect);
+}
+
+/* Given the be associated with isect, determine if page data can be
+ * written to disk.
+ */
+static int is_writable(struct pnfs_block_extent *be, sector_t isect)
+{
+       return (be->be_state == PNFS_BLOCK_READWRITE_DATA ||
+               be->be_state == PNFS_BLOCK_INVALID_DATA);
+}
+
+/* The data we are handed might be spread across several bios.  We need
+ * to track when the last one is finished.
+ */
+struct parallel_io {
+       struct kref refcnt;
+       struct rpc_call_ops call_ops;
+       void (*pnfs_callback) (void *data);
+       void *data;
+};
+
+static inline struct parallel_io *alloc_parallel(void *data)
+{
+       struct parallel_io *rv;
+
+       rv  = kmalloc(sizeof(*rv), GFP_NOFS);
+       if (rv) {
+               rv->data = data;
+               kref_init(&rv->refcnt);
+       }
+       return rv;
+}
+
+static inline void get_parallel(struct parallel_io *p)
+{
+       kref_get(&p->refcnt);
+}
+
+static void destroy_parallel(struct kref *kref)
+{
+       struct parallel_io *p = container_of(kref, struct parallel_io, refcnt);
+
+       dprintk("%s enter\n", __func__);
+       p->pnfs_callback(p->data);
+       kfree(p);
+}
+
+static inline void put_parallel(struct parallel_io *p)
+{
+       kref_put(&p->refcnt, destroy_parallel);
+}
+
+static struct bio *
+bl_submit_bio(int rw, struct bio *bio)
+{
+       if (bio) {
+               get_parallel(bio->bi_private);
+               dprintk("%s submitting %s bio %u@%llu\n", __func__,
+                       rw == READ ? "read" : "write",
+                       bio->bi_size, (unsigned long long)bio->bi_sector);
+               submit_bio(rw, bio);
+       }
+       return NULL;
+}
+
+static struct bio *bl_alloc_init_bio(int npg, sector_t isect,
+                                    struct pnfs_block_extent *be,
+                                    void (*end_io)(struct bio *, int err),
+                                    struct parallel_io *par)
+{
+       struct bio *bio;
+
+       bio = bio_alloc(GFP_NOIO, npg);
+       if (!bio)
+               return NULL;
+
+       bio->bi_sector = isect - be->be_f_offset + be->be_v_offset;
+       bio->bi_bdev = be->be_mdev;
+       bio->bi_end_io = end_io;
+       bio->bi_private = par;
+       return bio;
+}
+
+static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw,
+                                     sector_t isect, struct page *page,
+                                     struct pnfs_block_extent *be,
+                                     void (*end_io)(struct bio *, int err),
+                                     struct parallel_io *par)
+{
+retry:
+       if (!bio) {
+               bio = bl_alloc_init_bio(npg, isect, be, end_io, par);
+               if (!bio)
+                       return ERR_PTR(-ENOMEM);
+       }
+       if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) {
+               bio = bl_submit_bio(rw, bio);
+               goto retry;
+       }
+       return bio;
+}
+
+static void bl_set_lo_fail(struct pnfs_layout_segment *lseg)
+{
+       if (lseg->pls_range.iomode == IOMODE_RW) {
+               dprintk("%s Setting layout IOMODE_RW fail bit\n", __func__);
+               set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags);
+       } else {
+               dprintk("%s Setting layout IOMODE_READ fail bit\n", __func__);
+               set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags);
+       }
+}
+
+/* This is basically copied from mpage_end_io_read */
+static void bl_end_io_read(struct bio *bio, int err)
+{
+       struct parallel_io *par = bio->bi_private;
+       const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+       struct nfs_read_data *rdata = (struct nfs_read_data *)par->data;
+
+       do {
+               struct page *page = bvec->bv_page;
+
+               if (--bvec >= bio->bi_io_vec)
+                       prefetchw(&bvec->bv_page->flags);
+               if (uptodate)
+                       SetPageUptodate(page);
+       } while (bvec >= bio->bi_io_vec);
+       if (!uptodate) {
+               if (!rdata->pnfs_error)
+                       rdata->pnfs_error = -EIO;
+               bl_set_lo_fail(rdata->lseg);
+       }
+       bio_put(bio);
+       put_parallel(par);
+}
+
+static void bl_read_cleanup(struct work_struct *work)
+{
+       struct rpc_task *task;
+       struct nfs_read_data *rdata;
+       dprintk("%s enter\n", __func__);
+       task = container_of(work, struct rpc_task, u.tk_work);
+       rdata = container_of(task, struct nfs_read_data, task);
+       pnfs_ld_read_done(rdata);
+}
+
+static void
+bl_end_par_io_read(void *data)
+{
+       struct nfs_read_data *rdata = data;
+
+       INIT_WORK(&rdata->task.u.tk_work, bl_read_cleanup);
+       schedule_work(&rdata->task.u.tk_work);
+}
+
+/* We don't want normal .rpc_call_done callback used, so we replace it
+ * with this stub.
+ */
+static void bl_rpc_do_nothing(struct rpc_task *task, void *calldata)
+{
+       return;
+}
+
+static enum pnfs_try_status
+bl_read_pagelist(struct nfs_read_data *rdata)
+{
+       int i, hole;
+       struct bio *bio = NULL;
+       struct pnfs_block_extent *be = NULL, *cow_read = NULL;
+       sector_t isect, extent_length = 0;
+       struct parallel_io *par;
+       loff_t f_offset = rdata->args.offset;
+       size_t count = rdata->args.count;
+       struct page **pages = rdata->args.pages;
+       int pg_index = rdata->args.pgbase >> PAGE_CACHE_SHIFT;
+
+       dprintk("%s enter nr_pages %u offset %lld count %Zd\n", __func__,
+              rdata->npages, f_offset, count);
+
+       par = alloc_parallel(rdata);
+       if (!par)
+               goto use_mds;
+       par->call_ops = *rdata->mds_ops;
+       par->call_ops.rpc_call_done = bl_rpc_do_nothing;
+       par->pnfs_callback = bl_end_par_io_read;
+       /* At this point, we can no longer jump to use_mds */
+
+       isect = (sector_t) (f_offset >> SECTOR_SHIFT);
+       /* Code assumes extents are page-aligned */
+       for (i = pg_index; i < rdata->npages; i++) {
+               if (!extent_length) {
+                       /* We've used up the previous extent */
+                       bl_put_extent(be);
+                       bl_put_extent(cow_read);
+                       bio = bl_submit_bio(READ, bio);
+                       /* Get the next one */
+                       be = bl_find_get_extent(BLK_LSEG2EXT(rdata->lseg),
+                                            isect, &cow_read);
+                       if (!be) {
+                               rdata->pnfs_error = -EIO;
+                               goto out;
+                       }
+                       extent_length = be->be_length -
+                               (isect - be->be_f_offset);
+                       if (cow_read) {
+                               sector_t cow_length = cow_read->be_length -
+                                       (isect - cow_read->be_f_offset);
+                               extent_length = min(extent_length, cow_length);
+                       }
+               }
+               hole = is_hole(be, isect);
+               if (hole && !cow_read) {
+                       bio = bl_submit_bio(READ, bio);
+                       /* Fill hole w/ zeroes w/o accessing device */
+                       dprintk("%s Zeroing page for hole\n", __func__);
+                       zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE);
+                       print_page(pages[i]);
+                       SetPageUptodate(pages[i]);
+               } else {
+                       struct pnfs_block_extent *be_read;
+
+                       be_read = (hole && cow_read) ? cow_read : be;
+                       bio = bl_add_page_to_bio(bio, rdata->npages - i, READ,
+                                                isect, pages[i], be_read,
+                                                bl_end_io_read, par);
+                       if (IS_ERR(bio)) {
+                               rdata->pnfs_error = PTR_ERR(bio);
+                               goto out;
+                       }
+               }
+               isect += PAGE_CACHE_SECTORS;
+               extent_length -= PAGE_CACHE_SECTORS;
+       }
+       if ((isect << SECTOR_SHIFT) >= rdata->inode->i_size) {
+               rdata->res.eof = 1;
+               rdata->res.count = rdata->inode->i_size - f_offset;
+       } else {
+               rdata->res.count = (isect << SECTOR_SHIFT) - f_offset;
+       }
+out:
+       bl_put_extent(be);
+       bl_put_extent(cow_read);
+       bl_submit_bio(READ, bio);
+       put_parallel(par);
+       return PNFS_ATTEMPTED;
+
+ use_mds:
+       dprintk("Giving up and using normal NFS\n");
+       return PNFS_NOT_ATTEMPTED;
+}
+
+static void mark_extents_written(struct pnfs_block_layout *bl,
+                                __u64 offset, __u32 count)
+{
+       sector_t isect, end;
+       struct pnfs_block_extent *be;
+
+       dprintk("%s(%llu, %u)\n", __func__, offset, count);
+       if (count == 0)
+               return;
+       isect = (offset & (long)(PAGE_CACHE_MASK)) >> SECTOR_SHIFT;
+       end = (offset + count + PAGE_CACHE_SIZE - 1) & (long)(PAGE_CACHE_MASK);
+       end >>= SECTOR_SHIFT;
+       while (isect < end) {
+               sector_t len;
+               be = bl_find_get_extent(bl, isect, NULL);
+               BUG_ON(!be); /* FIXME */
+               len = min(end, be->be_f_offset + be->be_length) - isect;
+               if (be->be_state == PNFS_BLOCK_INVALID_DATA)
+                       bl_mark_for_commit(be, isect, len); /* What if fails? */
+               isect += len;
+               bl_put_extent(be);
+       }
+}
+
+static void bl_end_io_write_zero(struct bio *bio, int err)
+{
+       struct parallel_io *par = bio->bi_private;
+       const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+       struct nfs_write_data *wdata = (struct nfs_write_data *)par->data;
+
+       do {
+               struct page *page = bvec->bv_page;
+
+               if (--bvec >= bio->bi_io_vec)
+                       prefetchw(&bvec->bv_page->flags);
+               /* This is the zeroing page we added */
+               end_page_writeback(page);
+               page_cache_release(page);
+       } while (bvec >= bio->bi_io_vec);
+       if (!uptodate) {
+               if (!wdata->pnfs_error)
+                       wdata->pnfs_error = -EIO;
+               bl_set_lo_fail(wdata->lseg);
+       }
+       bio_put(bio);
+       put_parallel(par);
+}
+
+/* This is basically copied from mpage_end_io_read */
+static void bl_end_io_write(struct bio *bio, int err)
+{
+       struct parallel_io *par = bio->bi_private;
+       const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+       struct nfs_write_data *wdata = (struct nfs_write_data *)par->data;
+
+       if (!uptodate) {
+               if (!wdata->pnfs_error)
+                       wdata->pnfs_error = -EIO;
+               bl_set_lo_fail(wdata->lseg);
+       }
+       bio_put(bio);
+       put_parallel(par);
+}
+
+/* Function scheduled for call during bl_end_par_io_write,
+ * it marks sectors as written and extends the commitlist.
+ */
+static void bl_write_cleanup(struct work_struct *work)
+{
+       struct rpc_task *task;
+       struct nfs_write_data *wdata;
+       dprintk("%s enter\n", __func__);
+       task = container_of(work, struct rpc_task, u.tk_work);
+       wdata = container_of(task, struct nfs_write_data, task);
+       if (!wdata->pnfs_error) {
+               /* Marks for LAYOUTCOMMIT */
+               mark_extents_written(BLK_LSEG2EXT(wdata->lseg),
+                                    wdata->args.offset, wdata->args.count);
+       }
+       pnfs_ld_write_done(wdata);
+}
+
+/* Called when last of bios associated with a bl_write_pagelist call finishes */
+static void bl_end_par_io_write(void *data)
+{
+       struct nfs_write_data *wdata = data;
+
+       wdata->task.tk_status = 0;
+       wdata->verf.committed = NFS_FILE_SYNC;
+       INIT_WORK(&wdata->task.u.tk_work, bl_write_cleanup);
+       schedule_work(&wdata->task.u.tk_work);
+}
+
+/* FIXME STUB - mark intersection of layout and page as bad, so is not
+ * used again.
+ */
+static void mark_bad_read(void)
+{
+       return;
+}
+
+/*
+ * map_block:  map a requested I/0 block (isect) into an offset in the LVM
+ * block_device
+ */
+static void
+map_block(struct buffer_head *bh, sector_t isect, struct pnfs_block_extent *be)
+{
+       dprintk("%s enter be=%p\n", __func__, be);
+
+       set_buffer_mapped(bh);
+       bh->b_bdev = be->be_mdev;
+       bh->b_blocknr = (isect - be->be_f_offset + be->be_v_offset) >>
+           (be->be_mdev->bd_inode->i_blkbits - SECTOR_SHIFT);
+
+       dprintk("%s isect %llu, bh->b_blocknr %ld, using bsize %Zd\n",
+               __func__, (unsigned long long)isect, (long)bh->b_blocknr,
+               bh->b_size);
+       return;
+}
+
+/* Given an unmapped page, zero it or read in page for COW, page is locked
+ * by caller.
+ */
+static int
+init_page_for_write(struct page *page, struct pnfs_block_extent *cow_read)
+{
+       struct buffer_head *bh = NULL;
+       int ret = 0;
+       sector_t isect;
+
+       dprintk("%s enter, %p\n", __func__, page);
+       BUG_ON(PageUptodate(page));
+       if (!cow_read) {
+               zero_user_segment(page, 0, PAGE_SIZE);
+               SetPageUptodate(page);
+               goto cleanup;
+       }
+
+       bh = alloc_page_buffers(page, PAGE_CACHE_SIZE, 0);
+       if (!bh) {
+               ret = -ENOMEM;
+               goto cleanup;
+       }
+
+       isect = (sector_t) page->index << PAGE_CACHE_SECTOR_SHIFT;
+       map_block(bh, isect, cow_read);
+       if (!bh_uptodate_or_lock(bh))
+               ret = bh_submit_read(bh);
+       if (ret)
+               goto cleanup;
+       SetPageUptodate(page);
+
+cleanup:
+       bl_put_extent(cow_read);
+       if (bh)
+               free_buffer_head(bh);
+       if (ret) {
+               /* Need to mark layout with bad read...should now
+                * just use nfs4 for reads and writes.
+                */
+               mark_bad_read();
+       }
+       return ret;
+}
+
+static enum pnfs_try_status
+bl_write_pagelist(struct nfs_write_data *wdata, int sync)
+{
+       int i, ret, npg_zero, pg_index, last = 0;
+       struct bio *bio = NULL;
+       struct pnfs_block_extent *be = NULL, *cow_read = NULL;
+       sector_t isect, last_isect = 0, extent_length = 0;
+       struct parallel_io *par;
+       loff_t offset = wdata->args.offset;
+       size_t count = wdata->args.count;
+       struct page **pages = wdata->args.pages;
+       struct page *page;
+       pgoff_t index;
+       u64 temp;
+       int npg_per_block =
+           NFS_SERVER(wdata->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT;
+
+       dprintk("%s enter, %Zu@%lld\n", __func__, count, offset);
+       /* At this point, wdata->pages is a (sequential) list of nfs_pages.
+        * We want to write each, and if there is an error set pnfs_error
+        * to have it redone using nfs.
+        */
+       par = alloc_parallel(wdata);
+       if (!par)
+               return PNFS_NOT_ATTEMPTED;
+       par->call_ops = *wdata->mds_ops;
+       par->call_ops.rpc_call_done = bl_rpc_do_nothing;
+       par->pnfs_callback = bl_end_par_io_write;
+       /* At this point, have to be more careful with error handling */
+
+       isect = (sector_t) ((offset & (long)PAGE_CACHE_MASK) >> SECTOR_SHIFT);
+       be = bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg), isect, &cow_read);
+       if (!be || !is_writable(be, isect)) {
+               dprintk("%s no matching extents!\n", __func__);
+               wdata->pnfs_error = -EINVAL;
+               goto out;
+       }
+
+       /* First page inside INVALID extent */
+       if (be->be_state == PNFS_BLOCK_INVALID_DATA) {
+               temp = offset >> PAGE_CACHE_SHIFT;
+               npg_zero = do_div(temp, npg_per_block);
+               isect = (sector_t) (((offset - npg_zero * PAGE_CACHE_SIZE) &
+                                    (long)PAGE_CACHE_MASK) >> SECTOR_SHIFT);
+               extent_length = be->be_length - (isect - be->be_f_offset);
+
+fill_invalid_ext:
+               dprintk("%s need to zero %d pages\n", __func__, npg_zero);
+               for (;npg_zero > 0; npg_zero--) {
+                       /* page ref released in bl_end_io_write_zero */
+                       index = isect >> PAGE_CACHE_SECTOR_SHIFT;
+                       dprintk("%s zero %dth page: index %lu isect %llu\n",
+                               __func__, npg_zero, index,
+                               (unsigned long long)isect);
+                       page =
+                           find_or_create_page(wdata->inode->i_mapping, index,
+                                               GFP_NOFS);
+                       if (!page) {
+                               dprintk("%s oom\n", __func__);
+                               wdata->pnfs_error = -ENOMEM;
+                               goto out;
+                       }
+
+                       /* PageDirty: Other will write this out
+                        * PageWriteback: Other is writing this out
+                        * PageUptodate: It was read before
+                        * sector_initialized: already written out
+                        */
+                       if (PageDirty(page) || PageWriteback(page) ||
+                           bl_is_sector_init(be->be_inval, isect)) {
+                               print_page(page);
+                               unlock_page(page);
+                               page_cache_release(page);
+                               goto next_page;
+                       }
+                       if (!PageUptodate(page)) {
+                               /* New page, readin or zero it */
+                               init_page_for_write(page, cow_read);
+                       }
+                       set_page_writeback(page);
+                       unlock_page(page);
+
+                       ret = bl_mark_sectors_init(be->be_inval, isect,
+                                                      PAGE_CACHE_SECTORS,
+                                                      NULL);
+                       if (unlikely(ret)) {
+                               dprintk("%s bl_mark_sectors_init fail %d\n",
+                                       __func__, ret);
+                               end_page_writeback(page);
+                               page_cache_release(page);
+                               wdata->pnfs_error = ret;
+                               goto out;
+                       }
+                       bio = bl_add_page_to_bio(bio, npg_zero, WRITE,
+                                                isect, page, be,
+                                                bl_end_io_write_zero, par);
+                       if (IS_ERR(bio)) {
+                               wdata->pnfs_error = PTR_ERR(bio);
+                               goto out;
+                       }
+                       /* FIXME: This should be done in bi_end_io */
+                       mark_extents_written(BLK_LSEG2EXT(wdata->lseg),
+                                            page->index << PAGE_CACHE_SHIFT,
+                                            PAGE_CACHE_SIZE);
+next_page:
+                       isect += PAGE_CACHE_SECTORS;
+                       extent_length -= PAGE_CACHE_SECTORS;
+               }
+               if (last)
+                       goto write_done;
+       }
+       bio = bl_submit_bio(WRITE, bio);
+
+       /* Middle pages */
+       pg_index = wdata->args.pgbase >> PAGE_CACHE_SHIFT;
+       for (i = pg_index; i < wdata->npages; i++) {
+               if (!extent_length) {
+                       /* We've used up the previous extent */
+                       bl_put_extent(be);
+                       bio = bl_submit_bio(WRITE, bio);
+                       /* Get the next one */
+                       be = bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg),
+                                            isect, NULL);
+                       if (!be || !is_writable(be, isect)) {
+                               wdata->pnfs_error = -EINVAL;
+                               goto out;
+                       }
+                       extent_length = be->be_length -
+                           (isect - be->be_f_offset);
+               }
+               if (be->be_state == PNFS_BLOCK_INVALID_DATA) {
+                       ret = bl_mark_sectors_init(be->be_inval, isect,
+                                                      PAGE_CACHE_SECTORS,
+                                                      NULL);
+                       if (unlikely(ret)) {
+                               dprintk("%s bl_mark_sectors_init fail %d\n",
+                                       __func__, ret);
+                               wdata->pnfs_error = ret;
+                               goto out;
+                       }
+               }
+               bio = bl_add_page_to_bio(bio, wdata->npages - i, WRITE,
+                                        isect, pages[i], be,
+                                        bl_end_io_write, par);
+               if (IS_ERR(bio)) {
+                       wdata->pnfs_error = PTR_ERR(bio);
+                       goto out;
+               }
+               isect += PAGE_CACHE_SECTORS;
+               last_isect = isect;
+               extent_length -= PAGE_CACHE_SECTORS;
+       }
+
+       /* Last page inside INVALID extent */
+       if (be->be_state == PNFS_BLOCK_INVALID_DATA) {
+               bio = bl_submit_bio(WRITE, bio);
+               temp = last_isect >> PAGE_CACHE_SECTOR_SHIFT;
+               npg_zero = npg_per_block - do_div(temp, npg_per_block);
+               if (npg_zero < npg_per_block) {
+                       last = 1;
+                       goto fill_invalid_ext;
+               }
+       }
+
+write_done:
+       wdata->res.count = (last_isect << SECTOR_SHIFT) - (offset);
+       if (count < wdata->res.count) {
+               wdata->res.count = count;
+       }
+out:
+       bl_put_extent(be);
+       bl_submit_bio(WRITE, bio);
+       put_parallel(par);
+       return PNFS_ATTEMPTED;
+}
+
+/* FIXME - range ignored */
+static void
+release_extents(struct pnfs_block_layout *bl, struct pnfs_layout_range *range)
+{
+       int i;
+       struct pnfs_block_extent *be;
+
+       spin_lock(&bl->bl_ext_lock);
+       for (i = 0; i < EXTENT_LISTS; i++) {
+               while (!list_empty(&bl->bl_extents[i])) {
+                       be = list_first_entry(&bl->bl_extents[i],
+                                             struct pnfs_block_extent,
+                                             be_node);
+                       list_del(&be->be_node);
+                       bl_put_extent(be);
+               }
+       }
+       spin_unlock(&bl->bl_ext_lock);
+}
+
+static void
+release_inval_marks(struct pnfs_inval_markings *marks)
+{
+       struct pnfs_inval_tracking *pos, *temp;
+
+       list_for_each_entry_safe(pos, temp, &marks->im_tree.mtt_stub, it_link) {
+               list_del(&pos->it_link);
+               kfree(pos);
+       }
+       return;
+}
+
+static void bl_free_layout_hdr(struct pnfs_layout_hdr *lo)
+{
+       struct pnfs_block_layout *bl = BLK_LO2EXT(lo);
+
+       dprintk("%s enter\n", __func__);
+       release_extents(bl, NULL);
+       release_inval_marks(&bl->bl_inval);
+       kfree(bl);
+}
+
+static struct pnfs_layout_hdr *bl_alloc_layout_hdr(struct inode *inode,
+                                                  gfp_t gfp_flags)
+{
+       struct pnfs_block_layout *bl;
+
+       dprintk("%s enter\n", __func__);
+       bl = kzalloc(sizeof(*bl), gfp_flags);
+       if (!bl)
+               return NULL;
+       spin_lock_init(&bl->bl_ext_lock);
+       INIT_LIST_HEAD(&bl->bl_extents[0]);
+       INIT_LIST_HEAD(&bl->bl_extents[1]);
+       INIT_LIST_HEAD(&bl->bl_commit);
+       INIT_LIST_HEAD(&bl->bl_committing);
+       bl->bl_count = 0;
+       bl->bl_blocksize = NFS_SERVER(inode)->pnfs_blksize >> SECTOR_SHIFT;
+       BL_INIT_INVAL_MARKS(&bl->bl_inval, bl->bl_blocksize);
+       return &bl->bl_layout;
+}
+
+static void bl_free_lseg(struct pnfs_layout_segment *lseg)
+{
+       dprintk("%s enter\n", __func__);
+       kfree(lseg);
+}
+
+/* We pretty much ignore lseg, and store all data layout wide, so we
+ * can correctly merge.
+ */
+static struct pnfs_layout_segment *bl_alloc_lseg(struct pnfs_layout_hdr *lo,
+                                                struct nfs4_layoutget_res *lgr,
+                                                gfp_t gfp_flags)
+{
+       struct pnfs_layout_segment *lseg;
+       int status;
+
+       dprintk("%s enter\n", __func__);
+       lseg = kzalloc(sizeof(*lseg), gfp_flags);
+       if (!lseg)
+               return ERR_PTR(-ENOMEM);
+       status = nfs4_blk_process_layoutget(lo, lgr, gfp_flags);
+       if (status) {
+               /* We don't want to call the full-blown bl_free_lseg,
+                * since on error extents were not touched.
+                */
+               kfree(lseg);
+               return ERR_PTR(status);
+       }
+       return lseg;
+}
+
+static void
+bl_encode_layoutcommit(struct pnfs_layout_hdr *lo, struct xdr_stream *xdr,
+                      const struct nfs4_layoutcommit_args *arg)
+{
+       dprintk("%s enter\n", __func__);
+       encode_pnfs_block_layoutupdate(BLK_LO2EXT(lo), xdr, arg);
+}
+
+static void
+bl_cleanup_layoutcommit(struct nfs4_layoutcommit_data *lcdata)
+{
+       struct pnfs_layout_hdr *lo = NFS_I(lcdata->args.inode)->layout;
+
+       dprintk("%s enter\n", __func__);
+       clean_pnfs_block_layoutupdate(BLK_LO2EXT(lo), &lcdata->args, lcdata->res.status);
+}
+
+static void free_blk_mountid(struct block_mount_id *mid)
+{
+       if (mid) {
+               struct pnfs_block_dev *dev;
+               spin_lock(&mid->bm_lock);
+               while (!list_empty(&mid->bm_devlist)) {
+                       dev = list_first_entry(&mid->bm_devlist,
+                                              struct pnfs_block_dev,
+                                              bm_node);
+                       list_del(&dev->bm_node);
+                       bl_free_block_dev(dev);
+               }
+               spin_unlock(&mid->bm_lock);
+               kfree(mid);
+       }
+}
+
+/* This is mostly copied from the filelayout's get_device_info function.
+ * It seems much of this should be at the generic pnfs level.
+ */
+static struct pnfs_block_dev *
+nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh,
+                       struct nfs4_deviceid *d_id)
+{
+       struct pnfs_device *dev;
+       struct pnfs_block_dev *rv = NULL;
+       u32 max_resp_sz;
+       int max_pages;
+       struct page **pages = NULL;
+       int i, rc;
+
+       /*
+        * Use the session max response size as the basis for setting
+        * GETDEVICEINFO's maxcount
+        */
+       max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
+       max_pages = max_resp_sz >> PAGE_SHIFT;
+       dprintk("%s max_resp_sz %u max_pages %d\n",
+               __func__, max_resp_sz, max_pages);
+
+       dev = kmalloc(sizeof(*dev), GFP_NOFS);
+       if (!dev) {
+               dprintk("%s kmalloc failed\n", __func__);
+               return NULL;
+       }
+
+       pages = kzalloc(max_pages * sizeof(struct page *), GFP_NOFS);
+       if (pages == NULL) {
+               kfree(dev);
+               return NULL;
+       }
+       for (i = 0; i < max_pages; i++) {
+               pages[i] = alloc_page(GFP_NOFS);
+               if (!pages[i])
+                       goto out_free;
+       }
+
+       memcpy(&dev->dev_id, d_id, sizeof(*d_id));
+       dev->layout_type = LAYOUT_BLOCK_VOLUME;
+       dev->pages = pages;
+       dev->pgbase = 0;
+       dev->pglen = PAGE_SIZE * max_pages;
+       dev->mincount = 0;
+
+       dprintk("%s: dev_id: %s\n", __func__, dev->dev_id.data);
+       rc = nfs4_proc_getdeviceinfo(server, dev);
+       dprintk("%s getdevice info returns %d\n", __func__, rc);
+       if (rc)
+               goto out_free;
+
+       rv = nfs4_blk_decode_device(server, dev);
+ out_free:
+       for (i = 0; i < max_pages; i++)
+               __free_page(pages[i]);
+       kfree(pages);
+       kfree(dev);
+       return rv;
+}
+
+static int
+bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh)
+{
+       struct block_mount_id *b_mt_id = NULL;
+       struct pnfs_devicelist *dlist = NULL;
+       struct pnfs_block_dev *bdev;
+       LIST_HEAD(block_disklist);
+       int status = 0, i;
+
+       dprintk("%s enter\n", __func__);
+
+       if (server->pnfs_blksize == 0) {
+               dprintk("%s Server did not return blksize\n", __func__);
+               return -EINVAL;
+       }
+       b_mt_id = kzalloc(sizeof(struct block_mount_id), GFP_NOFS);
+       if (!b_mt_id) {
+               status = -ENOMEM;
+               goto out_error;
+       }
+       /* Initialize nfs4 block layout mount id */
+       spin_lock_init(&b_mt_id->bm_lock);
+       INIT_LIST_HEAD(&b_mt_id->bm_devlist);
+
+       dlist = kmalloc(sizeof(struct pnfs_devicelist), GFP_NOFS);
+       if (!dlist) {
+               status = -ENOMEM;
+               goto out_error;
+       }
+       dlist->eof = 0;
+       while (!dlist->eof) {
+               status = nfs4_proc_getdevicelist(server, fh, dlist);
+               if (status)
+                       goto out_error;
+               dprintk("%s GETDEVICELIST numdevs=%i, eof=%i\n",
+                       __func__, dlist->num_devs, dlist->eof);
+               for (i = 0; i < dlist->num_devs; i++) {
+                       bdev = nfs4_blk_get_deviceinfo(server, fh,
+                                                      &dlist->dev_id[i]);
+                       if (!bdev) {
+                               status = -ENODEV;
+                               goto out_error;
+                       }
+                       spin_lock(&b_mt_id->bm_lock);
+                       list_add(&bdev->bm_node, &b_mt_id->bm_devlist);
+                       spin_unlock(&b_mt_id->bm_lock);
+               }
+       }
+       dprintk("%s SUCCESS\n", __func__);
+       server->pnfs_ld_data = b_mt_id;
+
+ out_return:
+       kfree(dlist);
+       return status;
+
+ out_error:
+       free_blk_mountid(b_mt_id);
+       goto out_return;
+}
+
+static int
+bl_clear_layoutdriver(struct nfs_server *server)
+{
+       struct block_mount_id *b_mt_id = server->pnfs_ld_data;
+
+       dprintk("%s enter\n", __func__);
+       free_blk_mountid(b_mt_id);
+       dprintk("%s RETURNS\n", __func__);
+       return 0;
+}
+
+static const struct nfs_pageio_ops bl_pg_read_ops = {
+       .pg_init = pnfs_generic_pg_init_read,
+       .pg_test = pnfs_generic_pg_test,
+       .pg_doio = pnfs_generic_pg_readpages,
+};
+
+static const struct nfs_pageio_ops bl_pg_write_ops = {
+       .pg_init = pnfs_generic_pg_init_write,
+       .pg_test = pnfs_generic_pg_test,
+       .pg_doio = pnfs_generic_pg_writepages,
+};
+
+static struct pnfs_layoutdriver_type blocklayout_type = {
+       .id                             = LAYOUT_BLOCK_VOLUME,
+       .name                           = "LAYOUT_BLOCK_VOLUME",
+       .read_pagelist                  = bl_read_pagelist,
+       .write_pagelist                 = bl_write_pagelist,
+       .alloc_layout_hdr               = bl_alloc_layout_hdr,
+       .free_layout_hdr                = bl_free_layout_hdr,
+       .alloc_lseg                     = bl_alloc_lseg,
+       .free_lseg                      = bl_free_lseg,
+       .encode_layoutcommit            = bl_encode_layoutcommit,
+       .cleanup_layoutcommit           = bl_cleanup_layoutcommit,
+       .set_layoutdriver               = bl_set_layoutdriver,
+       .clear_layoutdriver             = bl_clear_layoutdriver,
+       .pg_read_ops                    = &bl_pg_read_ops,
+       .pg_write_ops                   = &bl_pg_write_ops,
+};
+
+static const struct rpc_pipe_ops bl_upcall_ops = {
+       .upcall         = bl_pipe_upcall,
+       .downcall       = bl_pipe_downcall,
+       .destroy_msg    = bl_pipe_destroy_msg,
+};
+
+static int __init nfs4blocklayout_init(void)
+{
+       struct vfsmount *mnt;
+       struct path path;
+       int ret;
+
+       dprintk("%s: NFSv4 Block Layout Driver Registering...\n", __func__);
+
+       ret = pnfs_register_layoutdriver(&blocklayout_type);
+       if (ret)
+               goto out;
+
+       init_waitqueue_head(&bl_wq);
+
+       mnt = rpc_get_mount();
+       if (IS_ERR(mnt)) {
+               ret = PTR_ERR(mnt);
+               goto out_remove;
+       }
+
+       ret = vfs_path_lookup(mnt->mnt_root,
+                             mnt,
+                             NFS_PIPE_DIRNAME, 0, &path);
+       if (ret)
+               goto out_remove;
+
+       bl_device_pipe = rpc_mkpipe(path.dentry, "blocklayout", NULL,
+                                   &bl_upcall_ops, 0);
+       if (IS_ERR(bl_device_pipe)) {
+               ret = PTR_ERR(bl_device_pipe);
+               goto out_remove;
+       }
+out:
+       return ret;
+
+out_remove:
+       pnfs_unregister_layoutdriver(&blocklayout_type);
+       return ret;
+}
+
+static void __exit nfs4blocklayout_exit(void)
+{
+       dprintk("%s: NFSv4 Block Layout Driver Unregistering...\n",
+              __func__);
+
+       pnfs_unregister_layoutdriver(&blocklayout_type);
+       rpc_unlink(bl_device_pipe);
+}
+
+MODULE_ALIAS("nfs-layouttype4-3");
+
+module_init(nfs4blocklayout_init);
+module_exit(nfs4blocklayout_exit);
diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
new file mode 100644 (file)
index 0000000..f27d827
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ *  linux/fs/nfs/blocklayout/blocklayout.h
+ *
+ *  Module for the NFSv4.1 pNFS block layout driver.
+ *
+ *  Copyright (c) 2006 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@citi.umich.edu>
+ *  Fred Isaman <iisaman@umich.edu>
+ *
+ * permission is granted to use, copy, create derivative works and
+ * redistribute this software and such derivative works for any purpose,
+ * so long as the name of the university of michigan is not used in
+ * any advertising or publicity pertaining to the use or distribution
+ * of this software without specific, written prior authorization.  if
+ * the above copyright notice or any other identification of the
+ * university of michigan is included in any copy of any portion of
+ * this software, then the disclaimer below must also be included.
+ *
+ * this software is provided as is, without representation from the
+ * university of michigan as to its fitness for any purpose, and without
+ * warranty by the university of michigan of any kind, either express
+ * or implied, including without limitation the implied warranties of
+ * merchantability and fitness for a particular purpose.  the regents
+ * of the university of michigan shall not be liable for any damages,
+ * including special, indirect, incidental, or consequential damages,
+ * with respect to any claim arising out or in connection with the use
+ * of the software, even if it has been or is hereafter advised of the
+ * possibility of such damages.
+ */
+#ifndef FS_NFS_NFS4BLOCKLAYOUT_H
+#define FS_NFS_NFS4BLOCKLAYOUT_H
+
+#include <linux/device-mapper.h>
+#include <linux/nfs_fs.h>
+#include <linux/sunrpc/rpc_pipe_fs.h>
+
+#include "../pnfs.h"
+
+#define PAGE_CACHE_SECTORS (PAGE_CACHE_SIZE >> SECTOR_SHIFT)
+#define PAGE_CACHE_SECTOR_SHIFT (PAGE_CACHE_SHIFT - SECTOR_SHIFT)
+
+struct block_mount_id {
+       spinlock_t                      bm_lock;    /* protects list */
+       struct list_head                bm_devlist; /* holds pnfs_block_dev */
+};
+
+struct pnfs_block_dev {
+       struct list_head                bm_node;
+       struct nfs4_deviceid            bm_mdevid;    /* associated devid */
+       struct block_device             *bm_mdev;     /* meta device itself */
+};
+
+enum exstate4 {
+       PNFS_BLOCK_READWRITE_DATA       = 0,
+       PNFS_BLOCK_READ_DATA            = 1,
+       PNFS_BLOCK_INVALID_DATA         = 2, /* mapped, but data is invalid */
+       PNFS_BLOCK_NONE_DATA            = 3  /* unmapped, it's a hole */
+};
+
+#define MY_MAX_TAGS (15) /* tag bitnums used must be less than this */
+
+struct my_tree {
+       sector_t                mtt_step_size;  /* Internal sector alignment */
+       struct list_head        mtt_stub; /* Should be a radix tree */
+};
+
+struct pnfs_inval_markings {
+       spinlock_t      im_lock;
+       struct my_tree  im_tree;        /* Sectors that need LAYOUTCOMMIT */
+       sector_t        im_block_size;  /* Server blocksize in sectors */
+};
+
+struct pnfs_inval_tracking {
+       struct list_head it_link;
+       int              it_sector;
+       int              it_tags;
+};
+
+/* sector_t fields are all in 512-byte sectors */
+struct pnfs_block_extent {
+       struct kref     be_refcnt;
+       struct list_head be_node;       /* link into lseg list */
+       struct nfs4_deviceid be_devid;  /* FIXME: could use device cache instead */
+       struct block_device *be_mdev;
+       sector_t        be_f_offset;    /* the starting offset in the file */
+       sector_t        be_length;      /* the size of the extent */
+       sector_t        be_v_offset;    /* the starting offset in the volume */
+       enum exstate4   be_state;       /* the state of this extent */
+       struct pnfs_inval_markings *be_inval; /* tracks INVAL->RW transition */
+};
+
+/* Shortened extent used by LAYOUTCOMMIT */
+struct pnfs_block_short_extent {
+       struct list_head bse_node;
+       struct nfs4_deviceid bse_devid;
+       struct block_device *bse_mdev;
+       sector_t        bse_f_offset;   /* the starting offset in the file */
+       sector_t        bse_length;     /* the size of the extent */
+};
+
+static inline void
+BL_INIT_INVAL_MARKS(struct pnfs_inval_markings *marks, sector_t blocksize)
+{
+       spin_lock_init(&marks->im_lock);
+       INIT_LIST_HEAD(&marks->im_tree.mtt_stub);
+       marks->im_block_size = blocksize;
+       marks->im_tree.mtt_step_size = min((sector_t)PAGE_CACHE_SECTORS,
+                                          blocksize);
+}
+
+enum extentclass4 {
+       RW_EXTENT       = 0, /* READWRTE and INVAL */
+       RO_EXTENT       = 1, /* READ and NONE */
+       EXTENT_LISTS    = 2,
+};
+
+static inline int bl_choose_list(enum exstate4 state)
+{
+       if (state == PNFS_BLOCK_READ_DATA || state == PNFS_BLOCK_NONE_DATA)
+               return RO_EXTENT;
+       else
+               return RW_EXTENT;
+}
+
+struct pnfs_block_layout {
+       struct pnfs_layout_hdr bl_layout;
+       struct pnfs_inval_markings bl_inval; /* tracks INVAL->RW transition */
+       spinlock_t              bl_ext_lock;   /* Protects list manipulation */
+       struct list_head        bl_extents[EXTENT_LISTS]; /* R and RW extents */
+       struct list_head        bl_commit;      /* Needs layout commit */
+       struct list_head        bl_committing;  /* Layout committing */
+       unsigned int            bl_count;       /* entries in bl_commit */
+       sector_t                bl_blocksize;  /* Server blocksize in sectors */
+};
+
+#define BLK_ID(lo) ((struct block_mount_id *)(NFS_SERVER(lo->plh_inode)->pnfs_ld_data))
+
+static inline struct pnfs_block_layout *
+BLK_LO2EXT(struct pnfs_layout_hdr *lo)
+{
+       return container_of(lo, struct pnfs_block_layout, bl_layout);
+}
+
+static inline struct pnfs_block_layout *
+BLK_LSEG2EXT(struct pnfs_layout_segment *lseg)
+{
+       return BLK_LO2EXT(lseg->pls_layout);
+}
+
+struct bl_dev_msg {
+       int status;
+       uint32_t major, minor;
+};
+
+struct bl_msg_hdr {
+       u8  type;
+       u16 totallen; /* length of entire message, including hdr itself */
+};
+
+extern struct dentry *bl_device_pipe;
+extern wait_queue_head_t bl_wq;
+
+#define BL_DEVICE_UMOUNT               0x0 /* Umount--delete devices */
+#define BL_DEVICE_MOUNT                0x1 /* Mount--create devices*/
+#define BL_DEVICE_REQUEST_INIT         0x0 /* Start request */
+#define BL_DEVICE_REQUEST_PROC         0x1 /* User level process succeeds */
+#define BL_DEVICE_REQUEST_ERR          0x2 /* User level process fails */
+
+/* blocklayoutdev.c */
+ssize_t bl_pipe_upcall(struct file *, struct rpc_pipe_msg *,
+                      char __user *, size_t);
+ssize_t bl_pipe_downcall(struct file *, const char __user *, size_t);
+void bl_pipe_destroy_msg(struct rpc_pipe_msg *);
+struct block_device *nfs4_blkdev_get(dev_t dev);
+int nfs4_blkdev_put(struct block_device *bdev);
+struct pnfs_block_dev *nfs4_blk_decode_device(struct nfs_server *server,
+                                               struct pnfs_device *dev);
+int nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo,
+                               struct nfs4_layoutget_res *lgr, gfp_t gfp_flags);
+
+/* blocklayoutdm.c */
+void bl_free_block_dev(struct pnfs_block_dev *bdev);
+
+/* extents.c */
+struct pnfs_block_extent *
+bl_find_get_extent(struct pnfs_block_layout *bl, sector_t isect,
+               struct pnfs_block_extent **cow_read);
+int bl_mark_sectors_init(struct pnfs_inval_markings *marks,
+                            sector_t offset, sector_t length,
+                            sector_t **pages);
+void bl_put_extent(struct pnfs_block_extent *be);
+struct pnfs_block_extent *bl_alloc_extent(void);
+int bl_is_sector_init(struct pnfs_inval_markings *marks, sector_t isect);
+int encode_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
+                                  struct xdr_stream *xdr,
+                                  const struct nfs4_layoutcommit_args *arg);
+void clean_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
+                                  const struct nfs4_layoutcommit_args *arg,
+                                  int status);
+int bl_add_merge_extent(struct pnfs_block_layout *bl,
+                        struct pnfs_block_extent *new);
+int bl_mark_for_commit(struct pnfs_block_extent *be,
+                       sector_t offset, sector_t length);
+
+#endif /* FS_NFS_NFS4BLOCKLAYOUT_H */
diff --git a/fs/nfs/blocklayout/blocklayoutdev.c b/fs/nfs/blocklayout/blocklayoutdev.c
new file mode 100644 (file)
index 0000000..a83b393
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ *  linux/fs/nfs/blocklayout/blocklayoutdev.c
+ *
+ *  Device operations for the pnfs nfs4 file layout driver.
+ *
+ *  Copyright (c) 2006 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@citi.umich.edu>
+ *  Fred Isaman <iisaman@umich.edu>
+ *
+ * permission is granted to use, copy, create derivative works and
+ * redistribute this software and such derivative works for any purpose,
+ * so long as the name of the university of michigan is not used in
+ * any advertising or publicity pertaining to the use or distribution
+ * of this software without specific, written prior authorization.  if
+ * the above copyright notice or any other identification of the
+ * university of michigan is included in any copy of any portion of
+ * this software, then the disclaimer below must also be included.
+ *
+ * this software is provided as is, without representation from the
+ * university of michigan as to its fitness for any purpose, and without
+ * warranty by the university of michigan of any kind, either express
+ * or implied, including without limitation the implied warranties of
+ * merchantability and fitness for a particular purpose.  the regents
+ * of the university of michigan shall not be liable for any damages,
+ * including special, indirect, incidental, or consequential damages,
+ * with respect to any claim arising out or in connection with the use
+ * of the software, even if it has been or is hereafter advised of the
+ * possibility of such damages.
+ */
+#include <linux/module.h>
+#include <linux/buffer_head.h> /* __bread */
+
+#include <linux/genhd.h>
+#include <linux/blkdev.h>
+#include <linux/hash.h>
+
+#include "blocklayout.h"
+
+#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
+
+static int decode_sector_number(__be32 **rp, sector_t *sp)
+{
+       uint64_t s;
+
+       *rp = xdr_decode_hyper(*rp, &s);
+       if (s & 0x1ff) {
+               printk(KERN_WARNING "%s: sector not aligned\n", __func__);
+               return -1;
+       }
+       *sp = s >> SECTOR_SHIFT;
+       return 0;
+}
+
+/* Open a block_device by device number. */
+struct block_device *nfs4_blkdev_get(dev_t dev)
+{
+       struct block_device *bd;
+
+       dprintk("%s enter\n", __func__);
+       bd = blkdev_get_by_dev(dev, FMODE_READ, NULL);
+       if (IS_ERR(bd))
+               goto fail;
+       return bd;
+fail:
+       dprintk("%s failed to open device : %ld\n",
+                       __func__, PTR_ERR(bd));
+       return NULL;
+}
+
+/*
+ * Release the block device
+ */
+int nfs4_blkdev_put(struct block_device *bdev)
+{
+       dprintk("%s for device %d:%d\n", __func__, MAJOR(bdev->bd_dev),
+                       MINOR(bdev->bd_dev));
+       return blkdev_put(bdev, FMODE_READ);
+}
+
+/*
+ * Shouldn't there be a rpc_generic_upcall() to do this for us?
+ */
+ssize_t bl_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
+                      char __user *dst, size_t buflen)
+{
+       char *data = (char *)msg->data + msg->copied;
+       size_t mlen = min(msg->len - msg->copied, buflen);
+       unsigned long left;
+
+       left = copy_to_user(dst, data, mlen);
+       if (left == mlen) {
+               msg->errno = -EFAULT;
+               return -EFAULT;
+       }
+
+       mlen -= left;
+       msg->copied += mlen;
+       msg->errno = 0;
+       return mlen;
+}
+
+static struct bl_dev_msg bl_mount_reply;
+
+ssize_t bl_pipe_downcall(struct file *filp, const char __user *src,
+                        size_t mlen)
+{
+       if (mlen != sizeof (struct bl_dev_msg))
+               return -EINVAL;
+
+       if (copy_from_user(&bl_mount_reply, src, mlen) != 0)
+               return -EFAULT;
+
+       wake_up(&bl_wq);
+
+       return mlen;
+}
+
+void bl_pipe_destroy_msg(struct rpc_pipe_msg *msg)
+{
+       if (msg->errno >= 0)
+               return;
+       wake_up(&bl_wq);
+}
+
+/*
+ * Decodes pnfs_block_deviceaddr4 which is XDR encoded in dev->dev_addr_buf.
+ */
+struct pnfs_block_dev *
+nfs4_blk_decode_device(struct nfs_server *server,
+                      struct pnfs_device *dev)
+{
+       struct pnfs_block_dev *rv = NULL;
+       struct block_device *bd = NULL;
+       struct rpc_pipe_msg msg;
+       struct bl_msg_hdr bl_msg = {
+               .type = BL_DEVICE_MOUNT,
+               .totallen = dev->mincount,
+       };
+       uint8_t *dataptr;
+       DECLARE_WAITQUEUE(wq, current);
+       struct bl_dev_msg *reply = &bl_mount_reply;
+       int offset, len, i;
+
+       dprintk("%s CREATING PIPEFS MESSAGE\n", __func__);
+       dprintk("%s: deviceid: %s, mincount: %d\n", __func__, dev->dev_id.data,
+               dev->mincount);
+
+       memset(&msg, 0, sizeof(msg));
+       msg.data = kzalloc(sizeof(bl_msg) + dev->mincount, GFP_NOFS);
+       if (!msg.data) {
+               rv = ERR_PTR(-ENOMEM);
+               goto out;
+       }
+
+       memcpy(msg.data, &bl_msg, sizeof(bl_msg));
+       dataptr = (uint8_t *) msg.data;
+       len = dev->mincount;
+       offset = sizeof(bl_msg);
+       for (i = 0; len > 0; i++) {
+               memcpy(&dataptr[offset], page_address(dev->pages[i]),
+                               len < PAGE_CACHE_SIZE ? len : PAGE_CACHE_SIZE);
+               len -= PAGE_CACHE_SIZE;
+               offset += PAGE_CACHE_SIZE;
+       }
+       msg.len = sizeof(bl_msg) + dev->mincount;
+
+       dprintk("%s CALLING USERSPACE DAEMON\n", __func__);
+       add_wait_queue(&bl_wq, &wq);
+       if (rpc_queue_upcall(bl_device_pipe->d_inode, &msg) < 0) {
+               remove_wait_queue(&bl_wq, &wq);
+               goto out;
+       }
+
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule();
+       __set_current_state(TASK_RUNNING);
+       remove_wait_queue(&bl_wq, &wq);
+
+       if (reply->status != BL_DEVICE_REQUEST_PROC) {
+               dprintk("%s failed to open device: %d\n",
+                       __func__, reply->status);
+               rv = ERR_PTR(-EINVAL);
+               goto out;
+       }
+
+       bd = nfs4_blkdev_get(MKDEV(reply->major, reply->minor));
+       if (IS_ERR(bd)) {
+               dprintk("%s failed to open device : %ld\n",
+                       __func__, PTR_ERR(bd));
+               goto out;
+       }
+
+       rv = kzalloc(sizeof(*rv), GFP_NOFS);
+       if (!rv) {
+               rv = ERR_PTR(-ENOMEM);
+               goto out;
+       }
+
+       rv->bm_mdev = bd;
+       memcpy(&rv->bm_mdevid, &dev->dev_id, sizeof(struct nfs4_deviceid));
+       dprintk("%s Created device %s with bd_block_size %u\n",
+               __func__,
+               bd->bd_disk->disk_name,
+               bd->bd_block_size);
+
+out:
+       kfree(msg.data);
+       return rv;
+}
+
+/* Map deviceid returned by the server to constructed block_device */
+static struct block_device *translate_devid(struct pnfs_layout_hdr *lo,
+                                           struct nfs4_deviceid *id)
+{
+       struct block_device *rv = NULL;
+       struct block_mount_id *mid;
+       struct pnfs_block_dev *dev;
+
+       dprintk("%s enter, lo=%p, id=%p\n", __func__, lo, id);
+       mid = BLK_ID(lo);
+       spin_lock(&mid->bm_lock);
+       list_for_each_entry(dev, &mid->bm_devlist, bm_node) {
+               if (memcmp(id->data, dev->bm_mdevid.data,
+                          NFS4_DEVICEID4_SIZE) == 0) {
+                       rv = dev->bm_mdev;
+                       goto out;
+               }
+       }
+ out:
+       spin_unlock(&mid->bm_lock);
+       dprintk("%s returning %p\n", __func__, rv);
+       return rv;
+}
+
+/* Tracks info needed to ensure extents in layout obey constraints of spec */
+struct layout_verification {
+       u32 mode;       /* R or RW */
+       u64 start;      /* Expected start of next non-COW extent */
+       u64 inval;      /* Start of INVAL coverage */
+       u64 cowread;    /* End of COW read coverage */
+};
+
+/* Verify the extent meets the layout requirements of the pnfs-block draft,
+ * section 2.3.1.
+ */
+static int verify_extent(struct pnfs_block_extent *be,
+                        struct layout_verification *lv)
+{
+       if (lv->mode == IOMODE_READ) {
+               if (be->be_state == PNFS_BLOCK_READWRITE_DATA ||
+                   be->be_state == PNFS_BLOCK_INVALID_DATA)
+                       return -EIO;
+               if (be->be_f_offset != lv->start)
+                       return -EIO;
+               lv->start += be->be_length;
+               return 0;
+       }
+       /* lv->mode == IOMODE_RW */
+       if (be->be_state == PNFS_BLOCK_READWRITE_DATA) {
+               if (be->be_f_offset != lv->start)
+                       return -EIO;
+               if (lv->cowread > lv->start)
+                       return -EIO;
+               lv->start += be->be_length;
+               lv->inval = lv->start;
+               return 0;
+       } else if (be->be_state == PNFS_BLOCK_INVALID_DATA) {
+               if (be->be_f_offset != lv->start)
+                       return -EIO;
+               lv->start += be->be_length;
+               return 0;
+       } else if (be->be_state == PNFS_BLOCK_READ_DATA) {
+               if (be->be_f_offset > lv->start)
+                       return -EIO;
+               if (be->be_f_offset < lv->inval)
+                       return -EIO;
+               if (be->be_f_offset < lv->cowread)
+                       return -EIO;
+               /* It looks like you might want to min this with lv->start,
+                * but you really don't.
+                */
+               lv->inval = lv->inval + be->be_length;
+               lv->cowread = be->be_f_offset + be->be_length;
+               return 0;
+       } else
+               return -EIO;
+}
+
+/* XDR decode pnfs_block_layout4 structure */
+int
+nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo,
+                          struct nfs4_layoutget_res *lgr, gfp_t gfp_flags)
+{
+       struct pnfs_block_layout *bl = BLK_LO2EXT(lo);
+       int i, status = -EIO;
+       uint32_t count;
+       struct pnfs_block_extent *be = NULL, *save;
+       struct xdr_stream stream;
+       struct xdr_buf buf;
+       struct page *scratch;
+       __be32 *p;
+       struct layout_verification lv = {
+               .mode = lgr->range.iomode,
+               .start = lgr->range.offset >> SECTOR_SHIFT,
+               .inval = lgr->range.offset >> SECTOR_SHIFT,
+               .cowread = lgr->range.offset >> SECTOR_SHIFT,
+       };
+       LIST_HEAD(extents);
+
+       dprintk("---> %s\n", __func__);
+
+       scratch = alloc_page(gfp_flags);
+       if (!scratch)
+               return -ENOMEM;
+
+       xdr_init_decode_pages(&stream, &buf, lgr->layoutp->pages, lgr->layoutp->len);
+       xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
+
+       p = xdr_inline_decode(&stream, 4);
+       if (unlikely(!p))
+               goto out_err;
+
+       count = be32_to_cpup(p++);
+
+       dprintk("%s enter, number of extents %i\n", __func__, count);
+       p = xdr_inline_decode(&stream, (28 + NFS4_DEVICEID4_SIZE) * count);
+       if (unlikely(!p))
+               goto out_err;
+
+       /* Decode individual extents, putting them in temporary
+        * staging area until whole layout is decoded to make error
+        * recovery easier.
+        */
+       for (i = 0; i < count; i++) {
+               be = bl_alloc_extent();
+               if (!be) {
+                       status = -ENOMEM;
+                       goto out_err;
+               }
+               memcpy(&be->be_devid, p, NFS4_DEVICEID4_SIZE);
+               p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE);
+               be->be_mdev = translate_devid(lo, &be->be_devid);
+               if (!be->be_mdev)
+                       goto out_err;
+
+               /* The next three values are read in as bytes,
+                * but stored as 512-byte sector lengths
+                */
+               if (decode_sector_number(&p, &be->be_f_offset) < 0)
+                       goto out_err;
+               if (decode_sector_number(&p, &be->be_length) < 0)
+                       goto out_err;
+               if (decode_sector_number(&p, &be->be_v_offset) < 0)
+                       goto out_err;
+               be->be_state = be32_to_cpup(p++);
+               if (be->be_state == PNFS_BLOCK_INVALID_DATA)
+                       be->be_inval = &bl->bl_inval;
+               if (verify_extent(be, &lv)) {
+                       dprintk("%s verify failed\n", __func__);
+                       goto out_err;
+               }
+               list_add_tail(&be->be_node, &extents);
+       }
+       if (lgr->range.offset + lgr->range.length !=
+                       lv.start << SECTOR_SHIFT) {
+               dprintk("%s Final length mismatch\n", __func__);
+               be = NULL;
+               goto out_err;
+       }
+       if (lv.start < lv.cowread) {
+               dprintk("%s Final uncovered COW extent\n", __func__);
+               be = NULL;
+               goto out_err;
+       }
+       /* Extents decoded properly, now try to merge them in to
+        * existing layout extents.
+        */
+       spin_lock(&bl->bl_ext_lock);
+       list_for_each_entry_safe(be, save, &extents, be_node) {
+               list_del(&be->be_node);
+               status = bl_add_merge_extent(bl, be);
+               if (status) {
+                       spin_unlock(&bl->bl_ext_lock);
+                       /* This is a fairly catastrophic error, as the
+                        * entire layout extent lists are now corrupted.
+                        * We should have some way to distinguish this.
+                        */
+                       be = NULL;
+                       goto out_err;
+               }
+       }
+       spin_unlock(&bl->bl_ext_lock);
+       status = 0;
+ out:
+       __free_page(scratch);
+       dprintk("%s returns %i\n", __func__, status);
+       return status;
+
+ out_err:
+       bl_put_extent(be);
+       while (!list_empty(&extents)) {
+               be = list_first_entry(&extents, struct pnfs_block_extent,
+                                     be_node);
+               list_del(&be->be_node);
+               bl_put_extent(be);
+       }
+       goto out;
+}
diff --git a/fs/nfs/blocklayout/blocklayoutdm.c b/fs/nfs/blocklayout/blocklayoutdm.c
new file mode 100644 (file)
index 0000000..d055c75
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *  linux/fs/nfs/blocklayout/blocklayoutdm.c
+ *
+ *  Module for the NFSv4.1 pNFS block layout driver.
+ *
+ *  Copyright (c) 2007 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Fred Isaman <iisaman@umich.edu>
+ *  Andy Adamson <andros@citi.umich.edu>
+ *
+ * permission is granted to use, copy, create derivative works and
+ * redistribute this software and such derivative works for any purpose,
+ * so long as the name of the university of michigan is not used in
+ * any advertising or publicity pertaining to the use or distribution
+ * of this software without specific, written prior authorization.  if
+ * the above copyright notice or any other identification of the
+ * university of michigan is included in any copy of any portion of
+ * this software, then the disclaimer below must also be included.
+ *
+ * this software is provided as is, without representation from the
+ * university of michigan as to its fitness for any purpose, and without
+ * warranty by the university of michigan of any kind, either express
+ * or implied, including without limitation the implied warranties of
+ * merchantability and fitness for a particular purpose.  the regents
+ * of the university of michigan shall not be liable for any damages,
+ * including special, indirect, incidental, or consequential damages,
+ * with respect to any claim arising out or in connection with the use
+ * of the software, even if it has been or is hereafter advised of the
+ * possibility of such damages.
+ */
+
+#include <linux/genhd.h> /* gendisk - used in a dprintk*/
+#include <linux/sched.h>
+#include <linux/hash.h>
+
+#include "blocklayout.h"
+
+#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
+
+static void dev_remove(dev_t dev)
+{
+       struct rpc_pipe_msg msg;
+       struct bl_dev_msg bl_umount_request;
+       struct bl_msg_hdr bl_msg = {
+               .type = BL_DEVICE_UMOUNT,
+               .totallen = sizeof(bl_umount_request),
+       };
+       uint8_t *dataptr;
+       DECLARE_WAITQUEUE(wq, current);
+
+       dprintk("Entering %s\n", __func__);
+
+       memset(&msg, 0, sizeof(msg));
+       msg.data = kzalloc(1 + sizeof(bl_umount_request), GFP_NOFS);
+       if (!msg.data)
+               goto out;
+
+       memset(&bl_umount_request, 0, sizeof(bl_umount_request));
+       bl_umount_request.major = MAJOR(dev);
+       bl_umount_request.minor = MINOR(dev);
+
+       memcpy(msg.data, &bl_msg, sizeof(bl_msg));
+       dataptr = (uint8_t *) msg.data;
+       memcpy(&dataptr[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request));
+       msg.len = sizeof(bl_msg) + bl_msg.totallen;
+
+       add_wait_queue(&bl_wq, &wq);
+       if (rpc_queue_upcall(bl_device_pipe->d_inode, &msg) < 0) {
+               remove_wait_queue(&bl_wq, &wq);
+               goto out;
+       }
+
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule();
+       __set_current_state(TASK_RUNNING);
+       remove_wait_queue(&bl_wq, &wq);
+
+out:
+       kfree(msg.data);
+}
+
+/*
+ * Release meta device
+ */
+static void nfs4_blk_metadev_release(struct pnfs_block_dev *bdev)
+{
+       int rv;
+
+       dprintk("%s Releasing\n", __func__);
+       rv = nfs4_blkdev_put(bdev->bm_mdev);
+       if (rv)
+               printk(KERN_ERR "%s nfs4_blkdev_put returns %d\n",
+                               __func__, rv);
+
+       dev_remove(bdev->bm_mdev->bd_dev);
+}
+
+void bl_free_block_dev(struct pnfs_block_dev *bdev)
+{
+       if (bdev) {
+               if (bdev->bm_mdev) {
+                       dprintk("%s Removing DM device: %d:%d\n",
+                               __func__,
+                               MAJOR(bdev->bm_mdev->bd_dev),
+                               MINOR(bdev->bm_mdev->bd_dev));
+                       nfs4_blk_metadev_release(bdev);
+               }
+               kfree(bdev);
+       }
+}
diff --git a/fs/nfs/blocklayout/extents.c b/fs/nfs/blocklayout/extents.c
new file mode 100644 (file)
index 0000000..19fa7b0
--- /dev/null
@@ -0,0 +1,935 @@
+/*
+ *  linux/fs/nfs/blocklayout/blocklayout.h
+ *
+ *  Module for the NFSv4.1 pNFS block layout driver.
+ *
+ *  Copyright (c) 2006 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@citi.umich.edu>
+ *  Fred Isaman <iisaman@umich.edu>
+ *
+ * permission is granted to use, copy, create derivative works and
+ * redistribute this software and such derivative works for any purpose,
+ * so long as the name of the university of michigan is not used in
+ * any advertising or publicity pertaining to the use or distribution
+ * of this software without specific, written prior authorization.  if
+ * the above copyright notice or any other identification of the
+ * university of michigan is included in any copy of any portion of
+ * this software, then the disclaimer below must also be included.
+ *
+ * this software is provided as is, without representation from the
+ * university of michigan as to its fitness for any purpose, and without
+ * warranty by the university of michigan of any kind, either express
+ * or implied, including without limitation the implied warranties of
+ * merchantability and fitness for a particular purpose.  the regents
+ * of the university of michigan shall not be liable for any damages,
+ * including special, indirect, incidental, or consequential damages,
+ * with respect to any claim arising out or in connection with the use
+ * of the software, even if it has been or is hereafter advised of the
+ * possibility of such damages.
+ */
+
+#include "blocklayout.h"
+#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
+
+/* Bit numbers */
+#define EXTENT_INITIALIZED 0
+#define EXTENT_WRITTEN     1
+#define EXTENT_IN_COMMIT   2
+#define INTERNAL_EXISTS    MY_MAX_TAGS
+#define INTERNAL_MASK      ((1 << INTERNAL_EXISTS) - 1)
+
+/* Returns largest t<=s s.t. t%base==0 */
+static inline sector_t normalize(sector_t s, int base)
+{
+       sector_t tmp = s; /* Since do_div modifies its argument */
+       return s - do_div(tmp, base);
+}
+
+static inline sector_t normalize_up(sector_t s, int base)
+{
+       return normalize(s + base - 1, base);
+}
+
+/* Complete stub using list while determine API wanted */
+
+/* Returns tags, or negative */
+static int32_t _find_entry(struct my_tree *tree, u64 s)
+{
+       struct pnfs_inval_tracking *pos;
+
+       dprintk("%s(%llu) enter\n", __func__, s);
+       list_for_each_entry_reverse(pos, &tree->mtt_stub, it_link) {
+               if (pos->it_sector > s)
+                       continue;
+               else if (pos->it_sector == s)
+                       return pos->it_tags & INTERNAL_MASK;
+               else
+                       break;
+       }
+       return -ENOENT;
+}
+
+static inline
+int _has_tag(struct my_tree *tree, u64 s, int32_t tag)
+{
+       int32_t tags;
+
+       dprintk("%s(%llu, %i) enter\n", __func__, s, tag);
+       s = normalize(s, tree->mtt_step_size);
+       tags = _find_entry(tree, s);
+       if ((tags < 0) || !(tags & (1 << tag)))
+               return 0;
+       else
+               return 1;
+}
+
+/* Creates entry with tag, or if entry already exists, unions tag to it.
+ * If storage is not NULL, newly created entry will use it.
+ * Returns number of entries added, or negative on error.
+ */
+static int _add_entry(struct my_tree *tree, u64 s, int32_t tag,
+                     struct pnfs_inval_tracking *storage)
+{
+       int found = 0;
+       struct pnfs_inval_tracking *pos;
+
+       dprintk("%s(%llu, %i, %p) enter\n", __func__, s, tag, storage);
+       list_for_each_entry_reverse(pos, &tree->mtt_stub, it_link) {
+               if (pos->it_sector > s)
+                       continue;
+               else if (pos->it_sector == s) {
+                       found = 1;
+                       break;
+               } else
+                       break;
+       }
+       if (found) {
+               pos->it_tags |= (1 << tag);
+               return 0;
+       } else {
+               struct pnfs_inval_tracking *new;
+               if (storage)
+                       new = storage;
+               else {
+                       new = kmalloc(sizeof(*new), GFP_NOFS);
+                       if (!new)
+                               return -ENOMEM;
+               }
+               new->it_sector = s;
+               new->it_tags = (1 << tag);
+               list_add(&new->it_link, &pos->it_link);
+               return 1;
+       }
+}
+
+/* XXXX Really want option to not create */
+/* Over range, unions tag with existing entries, else creates entry with tag */
+static int _set_range(struct my_tree *tree, int32_t tag, u64 s, u64 length)
+{
+       u64 i;
+
+       dprintk("%s(%i, %llu, %llu) enter\n", __func__, tag, s, length);
+       for (i = normalize(s, tree->mtt_step_size); i < s + length;
+            i += tree->mtt_step_size)
+               if (_add_entry(tree, i, tag, NULL))
+                       return -ENOMEM;
+       return 0;
+}
+
+/* Ensure that future operations on given range of tree will not malloc */
+static int _preload_range(struct my_tree *tree, u64 offset, u64 length)
+{
+       u64 start, end, s;
+       int count, i, used = 0, status = -ENOMEM;
+       struct pnfs_inval_tracking **storage;
+
+       dprintk("%s(%llu, %llu) enter\n", __func__, offset, length);
+       start = normalize(offset, tree->mtt_step_size);
+       end = normalize_up(offset + length, tree->mtt_step_size);
+       count = (int)(end - start) / (int)tree->mtt_step_size;
+
+       /* Pre-malloc what memory we might need */
+       storage = kmalloc(sizeof(*storage) * count, GFP_NOFS);
+       if (!storage)
+               return -ENOMEM;
+       for (i = 0; i < count; i++) {
+               storage[i] = kmalloc(sizeof(struct pnfs_inval_tracking),
+                                    GFP_NOFS);
+               if (!storage[i])
+                       goto out_cleanup;
+       }
+
+       /* Now need lock - HOW??? */
+
+       for (s = start; s < end; s += tree->mtt_step_size)
+               used += _add_entry(tree, s, INTERNAL_EXISTS, storage[used]);
+
+       /* Unlock - HOW??? */
+       status = 0;
+
+ out_cleanup:
+       for (i = used; i < count; i++) {
+               if (!storage[i])
+                       break;
+               kfree(storage[i]);
+       }
+       kfree(storage);
+       return status;
+}
+
+static void set_needs_init(sector_t *array, sector_t offset)
+{
+       sector_t *p = array;
+
+       dprintk("%s enter\n", __func__);
+       if (!p)
+               return;
+       while (*p < offset)
+               p++;
+       if (*p == offset)
+               return;
+       else if (*p == ~0) {
+               *p++ = offset;
+               *p = ~0;
+               return;
+       } else {
+               sector_t *save = p;
+               dprintk("%s Adding %llu\n", __func__, (u64)offset);
+               while (*p != ~0)
+                       p++;
+               p++;
+               memmove(save + 1, save, (char *)p - (char *)save);
+               *save = offset;
+               return;
+       }
+}
+
+/* We are relying on page lock to serialize this */
+int bl_is_sector_init(struct pnfs_inval_markings *marks, sector_t isect)
+{
+       int rv;
+
+       spin_lock(&marks->im_lock);
+       rv = _has_tag(&marks->im_tree, isect, EXTENT_INITIALIZED);
+       spin_unlock(&marks->im_lock);
+       return rv;
+}
+
+/* Assume start, end already sector aligned */
+static int
+_range_has_tag(struct my_tree *tree, u64 start, u64 end, int32_t tag)
+{
+       struct pnfs_inval_tracking *pos;
+       u64 expect = 0;
+
+       dprintk("%s(%llu, %llu, %i) enter\n", __func__, start, end, tag);
+       list_for_each_entry_reverse(pos, &tree->mtt_stub, it_link) {
+               if (pos->it_sector >= end)
+                       continue;
+               if (!expect) {
+                       if ((pos->it_sector == end - tree->mtt_step_size) &&
+                           (pos->it_tags & (1 << tag))) {
+                               expect = pos->it_sector - tree->mtt_step_size;
+                               if (pos->it_sector < tree->mtt_step_size || expect < start)
+                                       return 1;
+                               continue;
+                       } else {
+                               return 0;
+                       }
+               }
+               if (pos->it_sector != expect || !(pos->it_tags & (1 << tag)))
+                       return 0;
+               expect -= tree->mtt_step_size;
+               if (expect < start)
+                       return 1;
+       }
+       return 0;
+}
+
+static int is_range_written(struct pnfs_inval_markings *marks,
+                           sector_t start, sector_t end)
+{
+       int rv;
+
+       spin_lock(&marks->im_lock);
+       rv = _range_has_tag(&marks->im_tree, start, end, EXTENT_WRITTEN);
+       spin_unlock(&marks->im_lock);
+       return rv;
+}
+
+/* Marks sectors in [offest, offset_length) as having been initialized.
+ * All lengths are step-aligned, where step is min(pagesize, blocksize).
+ * Notes where partial block is initialized, and helps prepare it for
+ * complete initialization later.
+ */
+/* Currently assumes offset is page-aligned */
+int bl_mark_sectors_init(struct pnfs_inval_markings *marks,
+                            sector_t offset, sector_t length,
+                            sector_t **pages)
+{
+       sector_t s, start, end;
+       sector_t *array = NULL; /* Pages to mark */
+
+       dprintk("%s(offset=%llu,len=%llu) enter\n",
+               __func__, (u64)offset, (u64)length);
+       s = max((sector_t) 3,
+               2 * (marks->im_block_size / (PAGE_CACHE_SECTORS)));
+       dprintk("%s set max=%llu\n", __func__, (u64)s);
+       if (pages) {
+               array = kmalloc(s * sizeof(sector_t), GFP_NOFS);
+               if (!array)
+                       goto outerr;
+               array[0] = ~0;
+       }
+
+       start = normalize(offset, marks->im_block_size);
+       end = normalize_up(offset + length, marks->im_block_size);
+       if (_preload_range(&marks->im_tree, start, end - start))
+               goto outerr;
+
+       spin_lock(&marks->im_lock);
+
+       for (s = normalize_up(start, PAGE_CACHE_SECTORS);
+            s < offset; s += PAGE_CACHE_SECTORS) {
+               dprintk("%s pre-area pages\n", __func__);
+               /* Portion of used block is not initialized */
+               if (!_has_tag(&marks->im_tree, s, EXTENT_INITIALIZED))
+                       set_needs_init(array, s);
+       }
+       if (_set_range(&marks->im_tree, EXTENT_INITIALIZED, offset, length))
+               goto out_unlock;
+       for (s = normalize_up(offset + length, PAGE_CACHE_SECTORS);
+            s < end; s += PAGE_CACHE_SECTORS) {
+               dprintk("%s post-area pages\n", __func__);
+               if (!_has_tag(&marks->im_tree, s, EXTENT_INITIALIZED))
+                       set_needs_init(array, s);
+       }
+
+       spin_unlock(&marks->im_lock);
+
+       if (pages) {
+               if (array[0] == ~0) {
+                       kfree(array);
+                       *pages = NULL;
+               } else
+                       *pages = array;
+       }
+       return 0;
+
+ out_unlock:
+       spin_unlock(&marks->im_lock);
+ outerr:
+       if (pages) {
+               kfree(array);
+               *pages = NULL;
+       }
+       return -ENOMEM;
+}
+
+/* Marks sectors in [offest, offset+length) as having been written to disk.
+ * All lengths should be block aligned.
+ */
+static int mark_written_sectors(struct pnfs_inval_markings *marks,
+                               sector_t offset, sector_t length)
+{
+       int status;
+
+       dprintk("%s(offset=%llu,len=%llu) enter\n", __func__,
+               (u64)offset, (u64)length);
+       spin_lock(&marks->im_lock);
+       status = _set_range(&marks->im_tree, EXTENT_WRITTEN, offset, length);
+       spin_unlock(&marks->im_lock);
+       return status;
+}
+
+static void print_short_extent(struct pnfs_block_short_extent *be)
+{
+       dprintk("PRINT SHORT EXTENT extent %p\n", be);
+       if (be) {
+               dprintk("        be_f_offset %llu\n", (u64)be->bse_f_offset);
+               dprintk("        be_length   %llu\n", (u64)be->bse_length);
+       }
+}
+
+static void print_clist(struct list_head *list, unsigned int count)
+{
+       struct pnfs_block_short_extent *be;
+       unsigned int i = 0;
+
+       ifdebug(FACILITY) {
+               printk(KERN_DEBUG "****************\n");
+               printk(KERN_DEBUG "Extent list looks like:\n");
+               list_for_each_entry(be, list, bse_node) {
+                       i++;
+                       print_short_extent(be);
+               }
+               if (i != count)
+                       printk(KERN_DEBUG "\n\nExpected %u entries\n\n\n", count);
+               printk(KERN_DEBUG "****************\n");
+       }
+}
+
+/* Note: In theory, we should do more checking that devid's match between
+ * old and new, but if they don't, the lists are too corrupt to salvage anyway.
+ */
+/* Note this is very similar to bl_add_merge_extent */
+static void add_to_commitlist(struct pnfs_block_layout *bl,
+                             struct pnfs_block_short_extent *new)
+{
+       struct list_head *clist = &bl->bl_commit;
+       struct pnfs_block_short_extent *old, *save;
+       sector_t end = new->bse_f_offset + new->bse_length;
+
+       dprintk("%s enter\n", __func__);
+       print_short_extent(new);
+       print_clist(clist, bl->bl_count);
+       bl->bl_count++;
+       /* Scan for proper place to insert, extending new to the left
+        * as much as possible.
+        */
+       list_for_each_entry_safe(old, save, clist, bse_node) {
+               if (new->bse_f_offset < old->bse_f_offset)
+                       break;
+               if (end <= old->bse_f_offset + old->bse_length) {
+                       /* Range is already in list */
+                       bl->bl_count--;
+                       kfree(new);
+                       return;
+               } else if (new->bse_f_offset <=
+                               old->bse_f_offset + old->bse_length) {
+                       /* new overlaps or abuts existing be */
+                       if (new->bse_mdev == old->bse_mdev) {
+                               /* extend new to fully replace old */
+                               new->bse_length += new->bse_f_offset -
+                                               old->bse_f_offset;
+                               new->bse_f_offset = old->bse_f_offset;
+                               list_del(&old->bse_node);
+                               bl->bl_count--;
+                               kfree(old);
+                       }
+               }
+       }
+       /* Note that if we never hit the above break, old will not point to a
+        * valid extent.  However, in that case &old->bse_node==list.
+        */
+       list_add_tail(&new->bse_node, &old->bse_node);
+       /* Scan forward for overlaps.  If we find any, extend new and
+        * remove the overlapped extent.
+        */
+       old = list_prepare_entry(new, clist, bse_node);
+       list_for_each_entry_safe_continue(old, save, clist, bse_node) {
+               if (end < old->bse_f_offset)
+                       break;
+               /* new overlaps or abuts old */
+               if (new->bse_mdev == old->bse_mdev) {
+                       if (end < old->bse_f_offset + old->bse_length) {
+                               /* extend new to fully cover old */
+                               end = old->bse_f_offset + old->bse_length;
+                               new->bse_length = end - new->bse_f_offset;
+                       }
+                       list_del(&old->bse_node);
+                       bl->bl_count--;
+                       kfree(old);
+               }
+       }
+       dprintk("%s: after merging\n", __func__);
+       print_clist(clist, bl->bl_count);
+}
+
+/* Note the range described by offset, length is guaranteed to be contained
+ * within be.
+ */
+int bl_mark_for_commit(struct pnfs_block_extent *be,
+                   sector_t offset, sector_t length)
+{
+       sector_t new_end, end = offset + length;
+       struct pnfs_block_short_extent *new;
+       struct pnfs_block_layout *bl = container_of(be->be_inval,
+                                                   struct pnfs_block_layout,
+                                                   bl_inval);
+
+       new = kmalloc(sizeof(*new), GFP_NOFS);
+       if (!new)
+               return -ENOMEM;
+
+       mark_written_sectors(be->be_inval, offset, length);
+       /* We want to add the range to commit list, but it must be
+        * block-normalized, and verified that the normalized range has
+        * been entirely written to disk.
+        */
+       new->bse_f_offset = offset;
+       offset = normalize(offset, bl->bl_blocksize);
+       if (offset < new->bse_f_offset) {
+               if (is_range_written(be->be_inval, offset, new->bse_f_offset))
+                       new->bse_f_offset = offset;
+               else
+                       new->bse_f_offset = offset + bl->bl_blocksize;
+       }
+       new_end = normalize_up(end, bl->bl_blocksize);
+       if (end < new_end) {
+               if (is_range_written(be->be_inval, end, new_end))
+                       end = new_end;
+               else
+                       end = new_end - bl->bl_blocksize;
+       }
+       if (end <= new->bse_f_offset) {
+               kfree(new);
+               return 0;
+       }
+       new->bse_length = end - new->bse_f_offset;
+       new->bse_devid = be->be_devid;
+       new->bse_mdev = be->be_mdev;
+
+       spin_lock(&bl->bl_ext_lock);
+       /* new will be freed, either by add_to_commitlist if it decides not
+        * to use it, or after LAYOUTCOMMIT uses it in the commitlist.
+        */
+       add_to_commitlist(bl, new);
+       spin_unlock(&bl->bl_ext_lock);
+       return 0;
+}
+
+static void print_bl_extent(struct pnfs_block_extent *be)
+{
+       dprintk("PRINT EXTENT extent %p\n", be);
+       if (be) {
+               dprintk("        be_f_offset %llu\n", (u64)be->be_f_offset);
+               dprintk("        be_length   %llu\n", (u64)be->be_length);
+               dprintk("        be_v_offset %llu\n", (u64)be->be_v_offset);
+               dprintk("        be_state    %d\n", be->be_state);
+       }
+}
+
+static void
+destroy_extent(struct kref *kref)
+{
+       struct pnfs_block_extent *be;
+
+       be = container_of(kref, struct pnfs_block_extent, be_refcnt);
+       dprintk("%s be=%p\n", __func__, be);
+       kfree(be);
+}
+
+void
+bl_put_extent(struct pnfs_block_extent *be)
+{
+       if (be) {
+               dprintk("%s enter %p (%i)\n", __func__, be,
+                       atomic_read(&be->be_refcnt.refcount));
+               kref_put(&be->be_refcnt, destroy_extent);
+       }
+}
+
+struct pnfs_block_extent *bl_alloc_extent(void)
+{
+       struct pnfs_block_extent *be;
+
+       be = kmalloc(sizeof(struct pnfs_block_extent), GFP_NOFS);
+       if (!be)
+               return NULL;
+       INIT_LIST_HEAD(&be->be_node);
+       kref_init(&be->be_refcnt);
+       be->be_inval = NULL;
+       return be;
+}
+
+static void print_elist(struct list_head *list)
+{
+       struct pnfs_block_extent *be;
+       dprintk("****************\n");
+       dprintk("Extent list looks like:\n");
+       list_for_each_entry(be, list, be_node) {
+               print_bl_extent(be);
+       }
+       dprintk("****************\n");
+}
+
+static inline int
+extents_consistent(struct pnfs_block_extent *old, struct pnfs_block_extent *new)
+{
+       /* Note this assumes new->be_f_offset >= old->be_f_offset */
+       return (new->be_state == old->be_state) &&
+               ((new->be_state == PNFS_BLOCK_NONE_DATA) ||
+                ((new->be_v_offset - old->be_v_offset ==
+                  new->be_f_offset - old->be_f_offset) &&
+                 new->be_mdev == old->be_mdev));
+}
+
+/* Adds new to appropriate list in bl, modifying new and removing existing
+ * extents as appropriate to deal with overlaps.
+ *
+ * See bl_find_get_extent for list constraints.
+ *
+ * Refcount on new is already set.  If end up not using it, or error out,
+ * need to put the reference.
+ *
+ * bl->bl_ext_lock is held by caller.
+ */
+int
+bl_add_merge_extent(struct pnfs_block_layout *bl,
+                    struct pnfs_block_extent *new)
+{
+       struct pnfs_block_extent *be, *tmp;
+       sector_t end = new->be_f_offset + new->be_length;
+       struct list_head *list;
+
+       dprintk("%s enter with be=%p\n", __func__, new);
+       print_bl_extent(new);
+       list = &bl->bl_extents[bl_choose_list(new->be_state)];
+       print_elist(list);
+
+       /* Scan for proper place to insert, extending new to the left
+        * as much as possible.
+        */
+       list_for_each_entry_safe_reverse(be, tmp, list, be_node) {
+               if (new->be_f_offset >= be->be_f_offset + be->be_length)
+                       break;
+               if (new->be_f_offset >= be->be_f_offset) {
+                       if (end <= be->be_f_offset + be->be_length) {
+                               /* new is a subset of existing be*/
+                               if (extents_consistent(be, new)) {
+                                       dprintk("%s: new is subset, ignoring\n",
+                                               __func__);
+                                       bl_put_extent(new);
+                                       return 0;
+                               } else {
+                                       goto out_err;
+                               }
+                       } else {
+                               /* |<--   be   -->|
+                                *          |<--   new   -->| */
+                               if (extents_consistent(be, new)) {
+                                       /* extend new to fully replace be */
+                                       new->be_length += new->be_f_offset -
+                                               be->be_f_offset;
+                                       new->be_f_offset = be->be_f_offset;
+                                       new->be_v_offset = be->be_v_offset;
+                                       dprintk("%s: removing %p\n", __func__, be);
+                                       list_del(&be->be_node);
+                                       bl_put_extent(be);
+                               } else {
+                                       goto out_err;
+                               }
+                       }
+               } else if (end >= be->be_f_offset + be->be_length) {
+                       /* new extent overlap existing be */
+                       if (extents_consistent(be, new)) {
+                               /* extend new to fully replace be */
+                               dprintk("%s: removing %p\n", __func__, be);
+                               list_del(&be->be_node);
+                               bl_put_extent(be);
+                       } else {
+                               goto out_err;
+                       }
+               } else if (end > be->be_f_offset) {
+                       /*           |<--   be   -->|
+                        *|<--   new   -->| */
+                       if (extents_consistent(new, be)) {
+                               /* extend new to fully replace be */
+                               new->be_length += be->be_f_offset + be->be_length -
+                                       new->be_f_offset - new->be_length;
+                               dprintk("%s: removing %p\n", __func__, be);
+                               list_del(&be->be_node);
+                               bl_put_extent(be);
+                       } else {
+                               goto out_err;
+                       }
+               }
+       }
+       /* Note that if we never hit the above break, be will not point to a
+        * valid extent.  However, in that case &be->be_node==list.
+        */
+       list_add(&new->be_node, &be->be_node);
+       dprintk("%s: inserting new\n", __func__);
+       print_elist(list);
+       /* FIXME - The per-list consistency checks have all been done,
+        * should now check cross-list consistency.
+        */
+       return 0;
+
+ out_err:
+       bl_put_extent(new);
+       return -EIO;
+}
+
+/* Returns extent, or NULL.  If a second READ extent exists, it is returned
+ * in cow_read, if given.
+ *
+ * The extents are kept in two seperate ordered lists, one for READ and NONE,
+ * one for READWRITE and INVALID.  Within each list, we assume:
+ * 1. Extents are ordered by file offset.
+ * 2. For any given isect, there is at most one extents that matches.
+ */
+struct pnfs_block_extent *
+bl_find_get_extent(struct pnfs_block_layout *bl, sector_t isect,
+           struct pnfs_block_extent **cow_read)
+{
+       struct pnfs_block_extent *be, *cow, *ret;
+       int i;
+
+       dprintk("%s enter with isect %llu\n", __func__, (u64)isect);
+       cow = ret = NULL;
+       spin_lock(&bl->bl_ext_lock);
+       for (i = 0; i < EXTENT_LISTS; i++) {
+               list_for_each_entry_reverse(be, &bl->bl_extents[i], be_node) {
+                       if (isect >= be->be_f_offset + be->be_length)
+                               break;
+                       if (isect >= be->be_f_offset) {
+                               /* We have found an extent */
+                               dprintk("%s Get %p (%i)\n", __func__, be,
+                                       atomic_read(&be->be_refcnt.refcount));
+                               kref_get(&be->be_refcnt);
+                               if (!ret)
+                                       ret = be;
+                               else if (be->be_state != PNFS_BLOCK_READ_DATA)
+                                       bl_put_extent(be);
+                               else
+                                       cow = be;
+                               break;
+                       }
+               }
+               if (ret &&
+                   (!cow_read || ret->be_state != PNFS_BLOCK_INVALID_DATA))
+                       break;
+       }
+       spin_unlock(&bl->bl_ext_lock);
+       if (cow_read)
+               *cow_read = cow;
+       print_bl_extent(ret);
+       return ret;
+}
+
+/* Similar to bl_find_get_extent, but called with lock held, and ignores cow */
+static struct pnfs_block_extent *
+bl_find_get_extent_locked(struct pnfs_block_layout *bl, sector_t isect)
+{
+       struct pnfs_block_extent *be, *ret = NULL;
+       int i;
+
+       dprintk("%s enter with isect %llu\n", __func__, (u64)isect);
+       for (i = 0; i < EXTENT_LISTS; i++) {
+               if (ret)
+                       break;
+               list_for_each_entry_reverse(be, &bl->bl_extents[i], be_node) {
+                       if (isect >= be->be_f_offset + be->be_length)
+                               break;
+                       if (isect >= be->be_f_offset) {
+                               /* We have found an extent */
+                               dprintk("%s Get %p (%i)\n", __func__, be,
+                                       atomic_read(&be->be_refcnt.refcount));
+                               kref_get(&be->be_refcnt);
+                               ret = be;
+                               break;
+                       }
+               }
+       }
+       print_bl_extent(ret);
+       return ret;
+}
+
+int
+encode_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
+                              struct xdr_stream *xdr,
+                              const struct nfs4_layoutcommit_args *arg)
+{
+       struct pnfs_block_short_extent *lce, *save;
+       unsigned int count = 0;
+       __be32 *p, *xdr_start;
+
+       dprintk("%s enter\n", __func__);
+       /* BUG - creation of bl_commit is buggy - need to wait for
+        * entire block to be marked WRITTEN before it can be added.
+        */
+       spin_lock(&bl->bl_ext_lock);
+       /* Want to adjust for possible truncate */
+       /* We now want to adjust argument range */
+
+       /* XDR encode the ranges found */
+       xdr_start = xdr_reserve_space(xdr, 8);
+       if (!xdr_start)
+               goto out;
+       list_for_each_entry_safe(lce, save, &bl->bl_commit, bse_node) {
+               p = xdr_reserve_space(xdr, 7 * 4 + sizeof(lce->bse_devid.data));
+               if (!p)
+                       break;
+               p = xdr_encode_opaque_fixed(p, lce->bse_devid.data, NFS4_DEVICEID4_SIZE);
+               p = xdr_encode_hyper(p, lce->bse_f_offset << SECTOR_SHIFT);
+               p = xdr_encode_hyper(p, lce->bse_length << SECTOR_SHIFT);
+               p = xdr_encode_hyper(p, 0LL);
+               *p++ = cpu_to_be32(PNFS_BLOCK_READWRITE_DATA);
+               list_del(&lce->bse_node);
+               list_add_tail(&lce->bse_node, &bl->bl_committing);
+               bl->bl_count--;
+               count++;
+       }
+       xdr_start[0] = cpu_to_be32((xdr->p - xdr_start - 1) * 4);
+       xdr_start[1] = cpu_to_be32(count);
+out:
+       spin_unlock(&bl->bl_ext_lock);
+       dprintk("%s found %i ranges\n", __func__, count);
+       return 0;
+}
+
+/* Helper function to set_to_rw that initialize a new extent */
+static void
+_prep_new_extent(struct pnfs_block_extent *new,
+                struct pnfs_block_extent *orig,
+                sector_t offset, sector_t length, int state)
+{
+       kref_init(&new->be_refcnt);
+       /* don't need to INIT_LIST_HEAD(&new->be_node) */
+       memcpy(&new->be_devid, &orig->be_devid, sizeof(struct nfs4_deviceid));
+       new->be_mdev = orig->be_mdev;
+       new->be_f_offset = offset;
+       new->be_length = length;
+       new->be_v_offset = orig->be_v_offset - orig->be_f_offset + offset;
+       new->be_state = state;
+       new->be_inval = orig->be_inval;
+}
+
+/* Tries to merge be with extent in front of it in list.
+ * Frees storage if not used.
+ */
+static struct pnfs_block_extent *
+_front_merge(struct pnfs_block_extent *be, struct list_head *head,
+            struct pnfs_block_extent *storage)
+{
+       struct pnfs_block_extent *prev;
+
+       if (!storage)
+               goto no_merge;
+       if (&be->be_node == head || be->be_node.prev == head)
+               goto no_merge;
+       prev = list_entry(be->be_node.prev, struct pnfs_block_extent, be_node);
+       if ((prev->be_f_offset + prev->be_length != be->be_f_offset) ||
+           !extents_consistent(prev, be))
+               goto no_merge;
+       _prep_new_extent(storage, prev, prev->be_f_offset,
+                        prev->be_length + be->be_length, prev->be_state);
+       list_replace(&prev->be_node, &storage->be_node);
+       bl_put_extent(prev);
+       list_del(&be->be_node);
+       bl_put_extent(be);
+       return storage;
+
+ no_merge:
+       kfree(storage);
+       return be;
+}
+
+static u64
+set_to_rw(struct pnfs_block_layout *bl, u64 offset, u64 length)
+{
+       u64 rv = offset + length;
+       struct pnfs_block_extent *be, *e1, *e2, *e3, *new, *old;
+       struct pnfs_block_extent *children[3];
+       struct pnfs_block_extent *merge1 = NULL, *merge2 = NULL;
+       int i = 0, j;
+
+       dprintk("%s(%llu, %llu)\n", __func__, offset, length);
+       /* Create storage for up to three new extents e1, e2, e3 */
+       e1 = kmalloc(sizeof(*e1), GFP_ATOMIC);
+       e2 = kmalloc(sizeof(*e2), GFP_ATOMIC);
+       e3 = kmalloc(sizeof(*e3), GFP_ATOMIC);
+       /* BUG - we are ignoring any failure */
+       if (!e1 || !e2 || !e3)
+               goto out_nosplit;
+
+       spin_lock(&bl->bl_ext_lock);
+       be = bl_find_get_extent_locked(bl, offset);
+       rv = be->be_f_offset + be->be_length;
+       if (be->be_state != PNFS_BLOCK_INVALID_DATA) {
+               spin_unlock(&bl->bl_ext_lock);
+               goto out_nosplit;
+       }
+       /* Add e* to children, bumping e*'s krefs */
+       if (be->be_f_offset != offset) {
+               _prep_new_extent(e1, be, be->be_f_offset,
+                                offset - be->be_f_offset,
+                                PNFS_BLOCK_INVALID_DATA);
+               children[i++] = e1;
+               print_bl_extent(e1);
+       } else
+               merge1 = e1;
+       _prep_new_extent(e2, be, offset,
+                        min(length, be->be_f_offset + be->be_length - offset),
+                        PNFS_BLOCK_READWRITE_DATA);
+       children[i++] = e2;
+       print_bl_extent(e2);
+       if (offset + length < be->be_f_offset + be->be_length) {
+               _prep_new_extent(e3, be, e2->be_f_offset + e2->be_length,
+                                be->be_f_offset + be->be_length -
+                                offset - length,
+                                PNFS_BLOCK_INVALID_DATA);
+               children[i++] = e3;
+               print_bl_extent(e3);
+       } else
+               merge2 = e3;
+
+       /* Remove be from list, and insert the e* */
+       /* We don't get refs on e*, since this list is the base reference
+        * set when init'ed.
+        */
+       if (i < 3)
+               children[i] = NULL;
+       new = children[0];
+       list_replace(&be->be_node, &new->be_node);
+       bl_put_extent(be);
+       new = _front_merge(new, &bl->bl_extents[RW_EXTENT], merge1);
+       for (j = 1; j < i; j++) {
+               old = new;
+               new = children[j];
+               list_add(&new->be_node, &old->be_node);
+       }
+       if (merge2) {
+               /* This is a HACK, should just create a _back_merge function */
+               new = list_entry(new->be_node.next,
+                                struct pnfs_block_extent, be_node);
+               new = _front_merge(new, &bl->bl_extents[RW_EXTENT], merge2);
+       }
+       spin_unlock(&bl->bl_ext_lock);
+
+       /* Since we removed the base reference above, be is now scheduled for
+        * destruction.
+        */
+       bl_put_extent(be);
+       dprintk("%s returns %llu after split\n", __func__, rv);
+       return rv;
+
+ out_nosplit:
+       kfree(e1);
+       kfree(e2);
+       kfree(e3);
+       dprintk("%s returns %llu without splitting\n", __func__, rv);
+       return rv;
+}
+
+void
+clean_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
+                             const struct nfs4_layoutcommit_args *arg,
+                             int status)
+{
+       struct pnfs_block_short_extent *lce, *save;
+
+       dprintk("%s status %d\n", __func__, status);
+       list_for_each_entry_safe(lce, save, &bl->bl_committing, bse_node) {
+               if (likely(!status)) {
+                       u64 offset = lce->bse_f_offset;
+                       u64 end = offset + lce->bse_length;
+
+                       do {
+                               offset = set_to_rw(bl, offset, end - offset);
+                       } while (offset < end);
+                       list_del(&lce->bse_node);
+
+                       kfree(lce);
+               } else {
+                       list_del(&lce->bse_node);
+                       spin_lock(&bl->bl_ext_lock);
+                       add_to_commitlist(bl, lce);
+                       spin_unlock(&bl->bl_ext_lock);
+               }
+       }
+}
index 19ea7d9..5833fbb 100644 (file)
@@ -105,7 +105,7 @@ struct rpc_program nfs_program = {
        .nrvers                 = ARRAY_SIZE(nfs_version),
        .version                = nfs_version,
        .stats                  = &nfs_rpcstat,
-       .pipe_dir_name          = "/nfs",
+       .pipe_dir_name          = NFS_PIPE_DIRNAME,
 };
 
 struct rpc_stat nfs_rpcstat = {
@@ -904,7 +904,9 @@ error:
 /*
  * Load up the server record from information gained in an fsinfo record
  */
-static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *fsinfo)
+static void nfs_server_set_fsinfo(struct nfs_server *server,
+                                 struct nfs_fh *mntfh,
+                                 struct nfs_fsinfo *fsinfo)
 {
        unsigned long max_rpc_payload;
 
@@ -934,7 +936,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *
        if (server->wsize > NFS_MAX_FILE_IO_SIZE)
                server->wsize = NFS_MAX_FILE_IO_SIZE;
        server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-       set_pnfs_layoutdriver(server, fsinfo->layouttype);
+       server->pnfs_blksize = fsinfo->blksize;
+       set_pnfs_layoutdriver(server, mntfh, fsinfo->layouttype);
 
        server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
 
@@ -980,7 +983,7 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str
        if (error < 0)
                goto out_error;
 
-       nfs_server_set_fsinfo(server, &fsinfo);
+       nfs_server_set_fsinfo(server, mntfh, &fsinfo);
 
        /* Get some general file system info */
        if (server->namelen == 0) {
index 57f578e..b238d95 100644 (file)
@@ -134,18 +134,19 @@ const struct inode_operations nfs4_dir_inode_operations = {
 
 #endif /* CONFIG_NFS_V4 */
 
-static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct rpc_cred *cred)
+static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir, struct rpc_cred *cred)
 {
        struct nfs_open_dir_context *ctx;
        ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
        if (ctx != NULL) {
                ctx->duped = 0;
+               ctx->attr_gencount = NFS_I(dir)->attr_gencount;
                ctx->dir_cookie = 0;
                ctx->dup_cookie = 0;
                ctx->cred = get_rpccred(cred);
-       } else
-               ctx = ERR_PTR(-ENOMEM);
-       return ctx;
+               return ctx;
+       }
+       return  ERR_PTR(-ENOMEM);
 }
 
 static void put_nfs_open_dir_context(struct nfs_open_dir_context *ctx)
@@ -173,7 +174,7 @@ nfs_opendir(struct inode *inode, struct file *filp)
        cred = rpc_lookup_cred();
        if (IS_ERR(cred))
                return PTR_ERR(cred);
-       ctx = alloc_nfs_open_dir_context(cred);
+       ctx = alloc_nfs_open_dir_context(inode, cred);
        if (IS_ERR(ctx)) {
                res = PTR_ERR(ctx);
                goto out;
@@ -323,7 +324,6 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri
 {
        loff_t diff = desc->file->f_pos - desc->current_index;
        unsigned int index;
-       struct nfs_open_dir_context *ctx = desc->file->private_data;
 
        if (diff < 0)
                goto out_eof;
@@ -336,7 +336,6 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri
        index = (unsigned int)diff;
        *desc->dir_cookie = array->array[index].cookie;
        desc->cache_entry_index = index;
-       ctx->duped = 0;
        return 0;
 out_eof:
        desc->eof = 1;
@@ -349,14 +348,34 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
        int i;
        loff_t new_pos;
        int status = -EAGAIN;
-       struct nfs_open_dir_context *ctx = desc->file->private_data;
 
        for (i = 0; i < array->size; i++) {
                if (array->array[i].cookie == *desc->dir_cookie) {
+                       struct nfs_inode *nfsi = NFS_I(desc->file->f_path.dentry->d_inode);
+                       struct nfs_open_dir_context *ctx = desc->file->private_data;
+
                        new_pos = desc->current_index + i;
-                       if (new_pos < desc->file->f_pos) {
+                       if (ctx->attr_gencount != nfsi->attr_gencount
+                           || (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))) {
+                               ctx->duped = 0;
+                               ctx->attr_gencount = nfsi->attr_gencount;
+                       } else if (new_pos < desc->file->f_pos) {
+                               if (ctx->duped > 0
+                                   && ctx->dup_cookie == *desc->dir_cookie) {
+                                       if (printk_ratelimit()) {
+                                               pr_notice("NFS: directory %s/%s contains a readdir loop."
+                                                               "Please contact your server vendor.  "
+                                                               "The file: %s has duplicate cookie %llu\n",
+                                                               desc->file->f_dentry->d_parent->d_name.name,
+                                                               desc->file->f_dentry->d_name.name,
+                                                               array->array[i].string.name,
+                                                               *desc->dir_cookie);
+                                       }
+                                       status = -ELOOP;
+                                       goto out;
+                               }
                                ctx->dup_cookie = *desc->dir_cookie;
-                               ctx->duped = 1;
+                               ctx->duped = -1;
                        }
                        desc->file->f_pos = new_pos;
                        desc->cache_entry_index = i;
@@ -368,6 +387,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
                if (*desc->dir_cookie == array->last_cookie)
                        desc->eof = 1;
        }
+out:
        return status;
 }
 
@@ -740,19 +760,6 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
        struct nfs_cache_array *array = NULL;
        struct nfs_open_dir_context *ctx = file->private_data;
 
-       if (ctx->duped != 0 && ctx->dup_cookie == *desc->dir_cookie) {
-               if (printk_ratelimit()) {
-                       pr_notice("NFS: directory %s/%s contains a readdir loop.  "
-                               "Please contact your server vendor.  "
-                               "Offending cookie: %llu\n",
-                               file->f_dentry->d_parent->d_name.name,
-                               file->f_dentry->d_name.name,
-                               *desc->dir_cookie);
-               }
-               res = -ELOOP;
-               goto out;
-       }
-
        array = nfs_readdir_get_array(desc->page);
        if (IS_ERR(array)) {
                res = PTR_ERR(array);
@@ -774,6 +781,8 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
                        *desc->dir_cookie = array->array[i+1].cookie;
                else
                        *desc->dir_cookie = array->last_cookie;
+               if (ctx->duped != 0)
+                       ctx->duped = 1;
        }
        if (array->eof_index >= 0)
                desc->eof = 1;
@@ -805,6 +814,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
        struct page     *page = NULL;
        int             status;
        struct inode *inode = desc->file->f_path.dentry->d_inode;
+       struct nfs_open_dir_context *ctx = desc->file->private_data;
 
        dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n",
                        (unsigned long long)*desc->dir_cookie);
@@ -818,6 +828,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
        desc->page_index = 0;
        desc->last_cookie = *desc->dir_cookie;
        desc->page = page;
+       ctx->duped = 0;
 
        status = nfs_readdir_xdr_to_array(desc, page, inode);
        if (status < 0)
index e49e731..7ef2397 100644 (file)
@@ -415,7 +415,7 @@ fail:
 }
 
 int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
-               mode_t mode)
+               umode_t mode)
 {
        struct posix_acl *dfacl, *acl;
        int error = 0;
index 38053d8..85f1690 100644 (file)
@@ -316,7 +316,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                 int flags, struct nfs_open_context *ctx)
 {
        struct nfs3_createdata *data;
-       mode_t mode = sattr->ia_mode;
+       umode_t mode = sattr->ia_mode;
        int status = -ENOMEM;
 
        dprintk("NFS call  create %s\n", dentry->d_name.name);
@@ -562,7 +562,7 @@ static int
 nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
 {
        struct nfs3_createdata *data;
-       int mode = sattr->ia_mode;
+       umode_t mode = sattr->ia_mode;
        int status = -ENOMEM;
 
        dprintk("NFS call  mkdir %s\n", dentry->d_name.name);
@@ -681,7 +681,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                dev_t rdev)
 {
        struct nfs3_createdata *data;
-       mode_t mode = sattr->ia_mode;
+       umode_t mode = sattr->ia_mode;
        int status = -ENOMEM;
 
        dprintk("NFS call  mknod %s %u:%u\n", dentry->d_name.name,
index 1909ee8..1ec1a85 100644 (file)
@@ -318,7 +318,7 @@ extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[];
 extern const u32 nfs4_fattr_bitmap[2];
 extern const u32 nfs4_statfs_bitmap[2];
 extern const u32 nfs4_pathconf_bitmap[2];
-extern const u32 nfs4_fsinfo_bitmap[2];
+extern const u32 nfs4_fsinfo_bitmap[3];
 extern const u32 nfs4_fs_locations_bitmap[2];
 
 /* nfs4renewd.c */
index be93a62..e8915d4 100644 (file)
@@ -170,7 +170,7 @@ filelayout_set_layoutcommit(struct nfs_write_data *wdata)
 
        pnfs_set_layoutcommit(wdata);
        dprintk("%s ionde %lu pls_end_pos %lu\n", __func__, wdata->inode->i_ino,
-               (unsigned long) wdata->lseg->pls_end_pos);
+               (unsigned long) NFS_I(wdata->inode)->layout->plh_lwb);
 }
 
 /*
index 079614d..8c77039 100644 (file)
@@ -140,12 +140,13 @@ const u32 nfs4_pathconf_bitmap[2] = {
        0
 };
 
-const u32 nfs4_fsinfo_bitmap[2] = { FATTR4_WORD0_MAXFILESIZE
+const u32 nfs4_fsinfo_bitmap[3] = { FATTR4_WORD0_MAXFILESIZE
                        | FATTR4_WORD0_MAXREAD
                        | FATTR4_WORD0_MAXWRITE
                        | FATTR4_WORD0_LEASE_TIME,
                        FATTR4_WORD1_TIME_DELTA
-                       | FATTR4_WORD1_FS_LAYOUT_TYPES
+                       | FATTR4_WORD1_FS_LAYOUT_TYPES,
+                       FATTR4_WORD2_LAYOUT_BLKSIZE
 };
 
 const u32 nfs4_fs_locations_bitmap[2] = {
@@ -5834,6 +5835,54 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp)
        return status;
 }
 
+/*
+ * Retrieve the list of Data Server devices from the MDS.
+ */
+static int _nfs4_getdevicelist(struct nfs_server *server,
+                                   const struct nfs_fh *fh,
+                                   struct pnfs_devicelist *devlist)
+{
+       struct nfs4_getdevicelist_args args = {
+               .fh = fh,
+               .layoutclass = server->pnfs_curr_ld->id,
+       };
+       struct nfs4_getdevicelist_res res = {
+               .devlist = devlist,
+       };
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICELIST],
+               .rpc_argp = &args,
+               .rpc_resp = &res,
+       };
+       int status;
+
+       dprintk("--> %s\n", __func__);
+       status = nfs4_call_sync(server->client, server, &msg, &args.seq_args,
+                               &res.seq_res, 0);
+       dprintk("<-- %s status=%d\n", __func__, status);
+       return status;
+}
+
+int nfs4_proc_getdevicelist(struct nfs_server *server,
+                           const struct nfs_fh *fh,
+                           struct pnfs_devicelist *devlist)
+{
+       struct nfs4_exception exception = { };
+       int err;
+
+       do {
+               err = nfs4_handle_exception(server,
+                               _nfs4_getdevicelist(server, fh, devlist),
+                               &exception);
+       } while (exception.retry);
+
+       dprintk("%s: err=%d, num_devs=%u\n", __func__,
+               err, devlist->num_devs);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(nfs4_proc_getdevicelist);
+
 static int
 _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev)
 {
@@ -5912,9 +5961,16 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
 static void nfs4_layoutcommit_release(void *calldata)
 {
        struct nfs4_layoutcommit_data *data = calldata;
+       struct pnfs_layout_segment *lseg, *tmp;
 
+       pnfs_cleanup_layoutcommit(data);
        /* Matched by references in pnfs_set_layoutcommit */
-       put_lseg(data->lseg);
+       list_for_each_entry_safe(lseg, tmp, &data->lseg_list, pls_lc_list) {
+               list_del_init(&lseg->pls_lc_list);
+               if (test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT,
+                                      &lseg->pls_flags))
+                       put_lseg(lseg);
+       }
        put_rpccred(data->cred);
        kfree(data);
 }
index c191a9b..1dce12f 100644 (file)
@@ -113,7 +113,11 @@ static int nfs4_stat_to_errno(int);
 #define encode_restorefh_maxsz  (op_encode_hdr_maxsz)
 #define decode_restorefh_maxsz  (op_decode_hdr_maxsz)
 #define encode_fsinfo_maxsz    (encode_getattr_maxsz)
-#define decode_fsinfo_maxsz    (op_decode_hdr_maxsz + 15)
+/* The 5 accounts for the PNFS attributes, and assumes that at most three
+ * layout types will be returned.
+ */
+#define decode_fsinfo_maxsz    (op_decode_hdr_maxsz + \
+                                nfs4_fattr_bitmap_maxsz + 4 + 8 + 5)
 #define encode_renew_maxsz     (op_encode_hdr_maxsz + 3)
 #define decode_renew_maxsz     (op_decode_hdr_maxsz)
 #define encode_setclientid_maxsz \
@@ -314,6 +318,17 @@ static int nfs4_stat_to_errno(int);
                                XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
 #define encode_reclaim_complete_maxsz  (op_encode_hdr_maxsz + 4)
 #define decode_reclaim_complete_maxsz  (op_decode_hdr_maxsz + 4)
+#define encode_getdevicelist_maxsz (op_encode_hdr_maxsz + 4 + \
+                               encode_verifier_maxsz)
+#define decode_getdevicelist_maxsz (op_decode_hdr_maxsz + \
+                               2 /* nfs_cookie4 gdlr_cookie */ + \
+                               decode_verifier_maxsz \
+                                 /* verifier4 gdlr_verifier */ + \
+                               1 /* gdlr_deviceid_list count */ + \
+                               XDR_QUADLEN(NFS4_PNFS_GETDEVLIST_MAXNUM * \
+                                           NFS4_DEVICEID4_SIZE) \
+                                 /* gdlr_deviceid_list */ + \
+                               1 /* bool gdlr_eof */)
 #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \
                                XDR_QUADLEN(NFS4_DEVICEID4_SIZE))
 #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \
@@ -748,6 +763,14 @@ static int nfs4_stat_to_errno(int);
 #define NFS4_dec_reclaim_complete_sz   (compound_decode_hdr_maxsz + \
                                         decode_sequence_maxsz + \
                                         decode_reclaim_complete_maxsz)
+#define NFS4_enc_getdevicelist_sz (compound_encode_hdr_maxsz + \
+                               encode_sequence_maxsz + \
+                               encode_putfh_maxsz + \
+                               encode_getdevicelist_maxsz)
+#define NFS4_dec_getdevicelist_sz (compound_decode_hdr_maxsz + \
+                               decode_sequence_maxsz + \
+                               decode_putfh_maxsz + \
+                               decode_getdevicelist_maxsz)
 #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz +    \
                                encode_sequence_maxsz +\
                                encode_getdeviceinfo_maxsz)
@@ -1104,6 +1127,35 @@ static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm
        hdr->replen += decode_getattr_maxsz;
 }
 
+static void
+encode_getattr_three(struct xdr_stream *xdr,
+                    uint32_t bm0, uint32_t bm1, uint32_t bm2,
+                    struct compound_hdr *hdr)
+{
+       __be32 *p;
+
+       p = reserve_space(xdr, 4);
+       *p = cpu_to_be32(OP_GETATTR);
+       if (bm2) {
+               p = reserve_space(xdr, 16);
+               *p++ = cpu_to_be32(3);
+               *p++ = cpu_to_be32(bm0);
+               *p++ = cpu_to_be32(bm1);
+               *p = cpu_to_be32(bm2);
+       } else if (bm1) {
+               p = reserve_space(xdr, 12);
+               *p++ = cpu_to_be32(2);
+               *p++ = cpu_to_be32(bm0);
+               *p = cpu_to_be32(bm1);
+       } else {
+               p = reserve_space(xdr, 8);
+               *p++ = cpu_to_be32(1);
+               *p = cpu_to_be32(bm0);
+       }
+       hdr->nops++;
+       hdr->replen += decode_getattr_maxsz;
+}
+
 static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
 {
        encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0],
@@ -1112,8 +1164,11 @@ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct c
 
 static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
 {
-       encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0],
-                          bitmask[1] & nfs4_fsinfo_bitmap[1], hdr);
+       encode_getattr_three(xdr,
+                            bitmask[0] & nfs4_fsinfo_bitmap[0],
+                            bitmask[1] & nfs4_fsinfo_bitmap[1],
+                            bitmask[2] & nfs4_fsinfo_bitmap[2],
+                            hdr);
 }
 
 static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
@@ -1854,6 +1909,26 @@ static void encode_sequence(struct xdr_stream *xdr,
 }
 
 #ifdef CONFIG_NFS_V4_1
+static void
+encode_getdevicelist(struct xdr_stream *xdr,
+                    const struct nfs4_getdevicelist_args *args,
+                    struct compound_hdr *hdr)
+{
+       __be32 *p;
+       nfs4_verifier dummy = {
+               .data = "dummmmmy",
+       };
+
+       p = reserve_space(xdr, 20);
+       *p++ = cpu_to_be32(OP_GETDEVICELIST);
+       *p++ = cpu_to_be32(args->layoutclass);
+       *p++ = cpu_to_be32(NFS4_PNFS_GETDEVLIST_MAXNUM);
+       xdr_encode_hyper(p, 0ULL);                          /* cookie */
+       encode_nfs4_verifier(xdr, &dummy);
+       hdr->nops++;
+       hdr->replen += decode_getdevicelist_maxsz;
+}
+
 static void
 encode_getdeviceinfo(struct xdr_stream *xdr,
                     const struct nfs4_getdeviceinfo_args *args,
@@ -1916,7 +1991,7 @@ encode_layoutcommit(struct xdr_stream *xdr,
        *p++ = cpu_to_be32(OP_LAYOUTCOMMIT);
        /* Only whole file layouts */
        p = xdr_encode_hyper(p, 0); /* offset */
-       p = xdr_encode_hyper(p, NFS4_MAX_UINT64); /* length */
+       p = xdr_encode_hyper(p, args->lastbytewritten + 1);     /* length */
        *p++ = cpu_to_be32(0); /* reclaim */
        p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE);
        *p++ = cpu_to_be32(1); /* newoffset = TRUE */
@@ -2604,7 +2679,7 @@ static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req,
        struct compound_hdr hdr = {
                .nops   = 0,
        };
-       const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
+       const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME };
 
        encode_compound_hdr(xdr, req, &hdr);
        encode_setclientid_confirm(xdr, arg, &hdr);
@@ -2748,7 +2823,7 @@ static void nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req,
        struct compound_hdr hdr = {
                .minorversion = nfs4_xdr_minorversion(&args->la_seq_args),
        };
-       const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
+       const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME };
 
        encode_compound_hdr(xdr, req, &hdr);
        encode_sequence(xdr, &args->la_seq_args, &hdr);
@@ -2774,6 +2849,24 @@ static void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req,
        encode_nops(&hdr);
 }
 
+/*
+ * Encode GETDEVICELIST request
+ */
+static void nfs4_xdr_enc_getdevicelist(struct rpc_rqst *req,
+                                      struct xdr_stream *xdr,
+                                      struct nfs4_getdevicelist_args *args)
+{
+       struct compound_hdr hdr = {
+               .minorversion = nfs4_xdr_minorversion(&args->seq_args),
+       };
+
+       encode_compound_hdr(xdr, req, &hdr);
+       encode_sequence(xdr, &args->seq_args, &hdr);
+       encode_putfh(xdr, args->fh, &hdr);
+       encode_getdevicelist(xdr, args, &hdr);
+       encode_nops(&hdr);
+}
+
 /*
  * Encode GETDEVICEINFO request
  */
@@ -3011,14 +3104,17 @@ static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
                goto out_overflow;
        bmlen = be32_to_cpup(p);
 
-       bitmap[0] = bitmap[1] = 0;
+       bitmap[0] = bitmap[1] = bitmap[2] = 0;
        p = xdr_inline_decode(xdr, (bmlen << 2));
        if (unlikely(!p))
                goto out_overflow;
        if (bmlen > 0) {
                bitmap[0] = be32_to_cpup(p++);
-               if (bmlen > 1)
-                       bitmap[1] = be32_to_cpup(p);
+               if (bmlen > 1) {
+                       bitmap[1] = be32_to_cpup(p++);
+                       if (bmlen > 2)
+                               bitmap[2] = be32_to_cpup(p);
+               }
        }
        return 0;
 out_overflow:
@@ -3050,8 +3146,9 @@ static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint3
                        return ret;
                bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
        } else
-               bitmask[0] = bitmask[1] = 0;
-       dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]);
+               bitmask[0] = bitmask[1] = bitmask[2] = 0;
+       dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__,
+               bitmask[0], bitmask[1], bitmask[2]);
        return 0;
 }
 
@@ -4105,7 +4202,7 @@ out_overflow:
 static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)
 {
        __be32 *savep;
-       uint32_t attrlen, bitmap[2] = {0};
+       uint32_t attrlen, bitmap[3] = {0};
        int status;
 
        if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
@@ -4131,7 +4228,7 @@ xdr_error:
 static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
 {
        __be32 *savep;
-       uint32_t attrlen, bitmap[2] = {0};
+       uint32_t attrlen, bitmap[3] = {0};
        int status;
 
        if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
@@ -4163,7 +4260,7 @@ xdr_error:
 static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf)
 {
        __be32 *savep;
-       uint32_t attrlen, bitmap[2] = {0};
+       uint32_t attrlen, bitmap[3] = {0};
        int status;
 
        if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
@@ -4303,7 +4400,7 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat
 {
        __be32 *savep;
        uint32_t attrlen,
-                bitmap[2] = {0};
+                bitmap[3] = {0};
        int status;
 
        status = decode_op_hdr(xdr, OP_GETATTR);
@@ -4389,10 +4486,32 @@ static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap,
        return status;
 }
 
+/*
+ * The prefered block size for layout directed io
+ */
+static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap,
+                                     uint32_t *res)
+{
+       __be32 *p;
+
+       dprintk("%s: bitmap is %x\n", __func__, bitmap[2]);
+       *res = 0;
+       if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p)) {
+                       print_overflow_msg(__func__, xdr);
+                       return -EIO;
+               }
+               *res = be32_to_cpup(p);
+               bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE;
+       }
+       return 0;
+}
+
 static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
 {
        __be32 *savep;
-       uint32_t attrlen, bitmap[2];
+       uint32_t attrlen, bitmap[3];
        int status;
 
        if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
@@ -4420,6 +4539,9 @@ static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
        status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype);
        if (status != 0)
                goto xdr_error;
+       status = decode_attr_layout_blksize(xdr, bitmap, &fsinfo->blksize);
+       if (status)
+               goto xdr_error;
 
        status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
@@ -4839,7 +4961,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
 {
        __be32 *savep;
        uint32_t attrlen,
-                bitmap[2] = {0};
+                bitmap[3] = {0};
        struct kvec *iov = req->rq_rcv_buf.head;
        int status;
 
@@ -5268,6 +5390,53 @@ out_overflow:
 }
 
 #if defined(CONFIG_NFS_V4_1)
+/*
+ * TODO: Need to handle case when EOF != true;
+ */
+static int decode_getdevicelist(struct xdr_stream *xdr,
+                               struct pnfs_devicelist *res)
+{
+       __be32 *p;
+       int status, i;
+       struct nfs_writeverf verftemp;
+
+       status = decode_op_hdr(xdr, OP_GETDEVICELIST);
+       if (status)
+               return status;
+
+       p = xdr_inline_decode(xdr, 8 + 8 + 4);
+       if (unlikely(!p))
+               goto out_overflow;
+
+       /* TODO: Skip cookie for now */
+       p += 2;
+
+       /* Read verifier */
+       p = xdr_decode_opaque_fixed(p, verftemp.verifier, 8);
+
+       res->num_devs = be32_to_cpup(p);
+
+       dprintk("%s: num_dev %d\n", __func__, res->num_devs);
+
+       if (res->num_devs > NFS4_PNFS_GETDEVLIST_MAXNUM) {
+               printk(KERN_ERR "%s too many result dev_num %u\n",
+                               __func__, res->num_devs);
+               return -EIO;
+       }
+
+       p = xdr_inline_decode(xdr,
+                             res->num_devs * NFS4_DEVICEID4_SIZE + 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       for (i = 0; i < res->num_devs; i++)
+               p = xdr_decode_opaque_fixed(p, res->dev_id[i].data,
+                                           NFS4_DEVICEID4_SIZE);
+       res->eof = be32_to_cpup(p);
+       return 0;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return -EIO;
+}
 
 static int decode_getdeviceinfo(struct xdr_stream *xdr,
                                struct pnfs_device *pdev)
@@ -5430,6 +5599,7 @@ static int decode_layoutcommit(struct xdr_stream *xdr,
        int status;
 
        status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT);
+       res->status = status;
        if (status)
                return status;
 
@@ -6541,6 +6711,32 @@ static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp,
        return status;
 }
 
+/*
+ * Decode GETDEVICELIST response
+ */
+static int nfs4_xdr_dec_getdevicelist(struct rpc_rqst *rqstp,
+                                     struct xdr_stream *xdr,
+                                     struct nfs4_getdevicelist_res *res)
+{
+       struct compound_hdr hdr;
+       int status;
+
+       dprintk("encoding getdevicelist!\n");
+
+       status = decode_compound_hdr(xdr, &hdr);
+       if (status != 0)
+               goto out;
+       status = decode_sequence(xdr, &res->seq_res, rqstp);
+       if (status != 0)
+               goto out;
+       status = decode_putfh(xdr);
+       if (status != 0)
+               goto out;
+       status = decode_getdevicelist(xdr, res->devlist);
+out:
+       return status;
+}
+
 /*
  * Decode GETDEVINFO response
  */
@@ -6722,7 +6918,7 @@ out:
 int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
                       int plus)
 {
-       uint32_t bitmap[2] = {0};
+       uint32_t bitmap[3] = {0};
        uint32_t len;
        __be32 *p = xdr_inline_decode(xdr, 4);
        if (unlikely(!p))
@@ -6908,6 +7104,7 @@ struct rpc_procinfo       nfs4_procedures[] = {
        PROC(SECINFO_NO_NAME,   enc_secinfo_no_name,    dec_secinfo_no_name),
        PROC(TEST_STATEID,      enc_test_stateid,       dec_test_stateid),
        PROC(FREE_STATEID,      enc_free_stateid,       dec_free_stateid),
+       PROC(GETDEVICELIST,     enc_getdevicelist,      dec_getdevicelist),
 #endif /* CONFIG_NFS_V4_1 */
 };
 
index 38e5508..e550e88 100644 (file)
@@ -76,8 +76,11 @@ find_pnfs_driver(u32 id)
 void
 unset_pnfs_layoutdriver(struct nfs_server *nfss)
 {
-       if (nfss->pnfs_curr_ld)
+       if (nfss->pnfs_curr_ld) {
+               if (nfss->pnfs_curr_ld->clear_layoutdriver)
+                       nfss->pnfs_curr_ld->clear_layoutdriver(nfss);
                module_put(nfss->pnfs_curr_ld->owner);
+       }
        nfss->pnfs_curr_ld = NULL;
 }
 
@@ -88,7 +91,8 @@ unset_pnfs_layoutdriver(struct nfs_server *nfss)
  * @id layout type. Zero (illegal layout type) indicates pNFS not in use.
  */
 void
-set_pnfs_layoutdriver(struct nfs_server *server, u32 id)
+set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh,
+                     u32 id)
 {
        struct pnfs_layoutdriver_type *ld_type = NULL;
 
@@ -115,6 +119,13 @@ set_pnfs_layoutdriver(struct nfs_server *server, u32 id)
                goto out_no_driver;
        }
        server->pnfs_curr_ld = ld_type;
+       if (ld_type->set_layoutdriver
+           && ld_type->set_layoutdriver(server, mntfh)) {
+               printk(KERN_ERR "%s: Error initializing pNFS layout driver %u.\n",
+                               __func__, id);
+               module_put(ld_type->owner);
+               goto out_no_driver;
+       }
 
        dprintk("%s: pNFS module for %u set\n", __func__, id);
        return;
@@ -190,6 +201,7 @@ static void
 pnfs_free_layout_hdr(struct pnfs_layout_hdr *lo)
 {
        struct pnfs_layoutdriver_type *ld = NFS_SERVER(lo->plh_inode)->pnfs_curr_ld;
+       put_rpccred(lo->plh_lc_cred);
        return ld->alloc_layout_hdr ? ld->free_layout_hdr(lo) : kfree(lo);
 }
 
@@ -224,6 +236,7 @@ static void
 init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg)
 {
        INIT_LIST_HEAD(&lseg->pls_list);
+       INIT_LIST_HEAD(&lseg->pls_lc_list);
        atomic_set(&lseg->pls_refcount, 1);
        smp_mb();
        set_bit(NFS_LSEG_VALID, &lseg->pls_flags);
@@ -816,7 +829,9 @@ out:
 }
 
 static struct pnfs_layout_hdr *
-alloc_init_layout_hdr(struct inode *ino, gfp_t gfp_flags)
+alloc_init_layout_hdr(struct inode *ino,
+                     struct nfs_open_context *ctx,
+                     gfp_t gfp_flags)
 {
        struct pnfs_layout_hdr *lo;
 
@@ -828,11 +843,14 @@ alloc_init_layout_hdr(struct inode *ino, gfp_t gfp_flags)
        INIT_LIST_HEAD(&lo->plh_segs);
        INIT_LIST_HEAD(&lo->plh_bulk_recall);
        lo->plh_inode = ino;
+       lo->plh_lc_cred = get_rpccred(ctx->state->owner->so_cred);
        return lo;
 }
 
 static struct pnfs_layout_hdr *
-pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags)
+pnfs_find_alloc_layout(struct inode *ino,
+                      struct nfs_open_context *ctx,
+                      gfp_t gfp_flags)
 {
        struct nfs_inode *nfsi = NFS_I(ino);
        struct pnfs_layout_hdr *new = NULL;
@@ -847,7 +865,7 @@ pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags)
                        return nfsi->layout;
        }
        spin_unlock(&ino->i_lock);
-       new = alloc_init_layout_hdr(ino, gfp_flags);
+       new = alloc_init_layout_hdr(ino, ctx, gfp_flags);
        spin_lock(&ino->i_lock);
 
        if (likely(nfsi->layout == NULL))       /* Won the race? */
@@ -940,7 +958,7 @@ pnfs_update_layout(struct inode *ino,
        if (!pnfs_enabled_sb(NFS_SERVER(ino)))
                return NULL;
        spin_lock(&ino->i_lock);
-       lo = pnfs_find_alloc_layout(ino, gfp_flags);
+       lo = pnfs_find_alloc_layout(ino, ctx, gfp_flags);
        if (lo == NULL) {
                dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__);
                goto out_unlock;
@@ -1350,16 +1368,17 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
 EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages);
 
 /*
- * Currently there is only one (whole file) write lseg.
+ * There can be multiple RW segments.
  */
-static struct pnfs_layout_segment *pnfs_list_write_lseg(struct inode *inode)
+static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp)
 {
-       struct pnfs_layout_segment *lseg, *rv = NULL;
+       struct pnfs_layout_segment *lseg;
 
-       list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list)
-               if (lseg->pls_range.iomode == IOMODE_RW)
-                       rv = lseg;
-       return rv;
+       list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) {
+               if (lseg->pls_range.iomode == IOMODE_RW &&
+                   test_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
+                       list_add(&lseg->pls_lc_list, listp);
+       }
 }
 
 void
@@ -1371,17 +1390,19 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
 
        spin_lock(&nfsi->vfs_inode.i_lock);
        if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
-               /* references matched in nfs4_layoutcommit_release */
-               get_lseg(wdata->lseg);
-               wdata->lseg->pls_lc_cred =
-                       get_rpccred(wdata->args.context->state->owner->so_cred);
                mark_as_dirty = true;
                dprintk("%s: Set layoutcommit for inode %lu ",
                        __func__, wdata->inode->i_ino);
        }
-       if (end_pos > wdata->lseg->pls_end_pos)
-               wdata->lseg->pls_end_pos = end_pos;
+       if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &wdata->lseg->pls_flags)) {
+               /* references matched in nfs4_layoutcommit_release */
+               get_lseg(wdata->lseg);
+       }
+       if (end_pos > nfsi->layout->plh_lwb)
+               nfsi->layout->plh_lwb = end_pos;
        spin_unlock(&nfsi->vfs_inode.i_lock);
+       dprintk("%s: lseg %p end_pos %llu\n",
+               __func__, wdata->lseg, nfsi->layout->plh_lwb);
 
        /* if pnfs_layoutcommit_inode() runs between inode locks, the next one
         * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */
@@ -1390,6 +1411,14 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
 }
 EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit);
 
+void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data)
+{
+       struct nfs_server *nfss = NFS_SERVER(data->args.inode);
+
+       if (nfss->pnfs_curr_ld->cleanup_layoutcommit)
+               nfss->pnfs_curr_ld->cleanup_layoutcommit(data);
+}
+
 /*
  * For the LAYOUT4_NFSV4_1_FILES layout type, NFS_DATA_SYNC WRITEs and
  * NFS_UNSTABLE WRITEs with a COMMIT to data servers must store enough
@@ -1403,8 +1432,6 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
 {
        struct nfs4_layoutcommit_data *data;
        struct nfs_inode *nfsi = NFS_I(inode);
-       struct pnfs_layout_segment *lseg;
-       struct rpc_cred *cred;
        loff_t end_pos;
        int status = 0;
 
@@ -1421,30 +1448,25 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
                goto out;
        }
 
+       INIT_LIST_HEAD(&data->lseg_list);
        spin_lock(&inode->i_lock);
        if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
                spin_unlock(&inode->i_lock);
                kfree(data);
                goto out;
        }
-       /*
-        * Currently only one (whole file) write lseg which is referenced
-        * in pnfs_set_layoutcommit and will be found.
-        */
-       lseg = pnfs_list_write_lseg(inode);
 
-       end_pos = lseg->pls_end_pos;
-       cred = lseg->pls_lc_cred;
-       lseg->pls_end_pos = 0;
-       lseg->pls_lc_cred = NULL;
+       pnfs_list_write_lseg(inode, &data->lseg_list);
+
+       end_pos = nfsi->layout->plh_lwb;
+       nfsi->layout->plh_lwb = 0;
 
        memcpy(&data->args.stateid.data, nfsi->layout->plh_stateid.data,
                sizeof(nfsi->layout->plh_stateid.data));
        spin_unlock(&inode->i_lock);
 
        data->args.inode = inode;
-       data->lseg = lseg;
-       data->cred = cred;
+       data->cred = get_rpccred(nfsi->layout->plh_lc_cred);
        nfs_fattr_init(&data->fattr);
        data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask;
        data->res.fattr = &data->fattr;
index 078670d..01cbfd5 100644 (file)
 enum {
        NFS_LSEG_VALID = 0,     /* cleared when lseg is recalled/returned */
        NFS_LSEG_ROC,           /* roc bit received from server */
+       NFS_LSEG_LAYOUTCOMMIT,  /* layoutcommit bit set for layoutcommit */
 };
 
 struct pnfs_layout_segment {
        struct list_head pls_list;
+       struct list_head pls_lc_list;
        struct pnfs_layout_range pls_range;
        atomic_t pls_refcount;
        unsigned long pls_flags;
        struct pnfs_layout_hdr *pls_layout;
-       struct rpc_cred *pls_lc_cred; /* LAYOUTCOMMIT credential */
-       loff_t pls_end_pos; /* LAYOUTCOMMIT write end */
 };
 
 enum pnfs_try_status {
@@ -80,6 +80,9 @@ struct pnfs_layoutdriver_type {
        struct module *owner;
        unsigned flags;
 
+       int (*set_layoutdriver) (struct nfs_server *, const struct nfs_fh *);
+       int (*clear_layoutdriver) (struct nfs_server *);
+
        struct pnfs_layout_hdr * (*alloc_layout_hdr) (struct inode *inode, gfp_t gfp_flags);
        void (*free_layout_hdr) (struct pnfs_layout_hdr *);
 
@@ -110,6 +113,8 @@ struct pnfs_layoutdriver_type {
                                     struct xdr_stream *xdr,
                                     const struct nfs4_layoutreturn_args *args);
 
+       void (*cleanup_layoutcommit) (struct nfs4_layoutcommit_data *data);
+
        void (*encode_layoutcommit) (struct pnfs_layout_hdr *layoutid,
                                     struct xdr_stream *xdr,
                                     const struct nfs4_layoutcommit_args *args);
@@ -125,6 +130,8 @@ struct pnfs_layout_hdr {
        unsigned long           plh_block_lgets; /* block LAYOUTGET if >0 */
        u32                     plh_barrier; /* ignore lower seqids */
        unsigned long           plh_flags;
+       loff_t                  plh_lwb; /* last write byte for layoutcommit */
+       struct rpc_cred         *plh_lc_cred; /* layoutcommit cred */
        struct inode            *plh_inode;
 };
 
@@ -137,10 +144,21 @@ struct pnfs_device {
        unsigned int  pglen;
 };
 
+#define NFS4_PNFS_GETDEVLIST_MAXNUM 16
+
+struct pnfs_devicelist {
+       unsigned int            eof;
+       unsigned int            num_devs;
+       struct nfs4_deviceid    dev_id[NFS4_PNFS_GETDEVLIST_MAXNUM];
+};
+
 extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
 extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
 
 /* nfs4proc.c */
+extern int nfs4_proc_getdevicelist(struct nfs_server *server,
+                                  const struct nfs_fh *fh,
+                                  struct pnfs_devicelist *devlist);
 extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
                                   struct pnfs_device *dev);
 extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp);
@@ -153,7 +171,7 @@ void put_lseg(struct pnfs_layout_segment *lseg);
 bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *);
 bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, int);
 
-void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
+void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32);
 void unset_pnfs_layoutdriver(struct nfs_server *);
 void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *);
 int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
@@ -179,6 +197,7 @@ void pnfs_roc_release(struct inode *ino);
 void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);
 bool pnfs_roc_drain(struct inode *ino, u32 *barrier);
 void pnfs_set_layoutcommit(struct nfs_write_data *wdata);
+void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data);
 int pnfs_layoutcommit_inode(struct inode *inode, bool sync);
 int _pnfs_return_layout(struct inode *);
 int pnfs_ld_write_done(struct nfs_write_data *);
@@ -360,7 +379,8 @@ pnfs_roc_drain(struct inode *ino, u32 *barrier)
        return false;
 }
 
-static inline void set_pnfs_layoutdriver(struct nfs_server *s, u32 id)
+static inline void set_pnfs_layoutdriver(struct nfs_server *s,
+                                        const struct nfs_fh *mntfh, u32 id)
 {
 }
 
index 783c58d..a721907 100644 (file)
@@ -247,7 +247,7 @@ static int ocfs2_set_acl(handle_t *handle,
        case ACL_TYPE_ACCESS:
                name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
                if (acl) {
-                       mode_t mode = inode->i_mode;
+                       umode_t mode = inode->i_mode;
                        ret = posix_acl_equiv_mode(acl, &mode);
                        if (ret < 0)
                                return ret;
@@ -351,7 +351,7 @@ int ocfs2_init_acl(handle_t *handle,
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct posix_acl *acl = NULL;
        int ret = 0, ret2;
-       mode_t mode;
+       umode_t mode;
 
        if (!S_ISLNK(inode->i_mode)) {
                if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
index d43729a..10027b4 100644 (file)
@@ -149,10 +149,10 @@ posix_acl_valid(const struct posix_acl *acl)
  * file mode permission bits, or else 1. Returns -E... on error.
  */
 int
-posix_acl_equiv_mode(const struct posix_acl *acl, mode_t *mode_p)
+posix_acl_equiv_mode(const struct posix_acl *acl, umode_t *mode_p)
 {
        const struct posix_acl_entry *pa, *pe;
-       mode_t mode = 0;
+       umode_t mode = 0;
        int not_equiv = 0;
 
        FOREACH_ACL_ENTRY(pa, acl, pe) {
@@ -188,7 +188,7 @@ posix_acl_equiv_mode(const struct posix_acl *acl, mode_t *mode_p)
  * Create an ACL representing the file mode permission bits of an inode.
  */
 struct posix_acl *
-posix_acl_from_mode(mode_t mode, gfp_t flags)
+posix_acl_from_mode(umode_t mode, gfp_t flags)
 {
        struct posix_acl *acl = posix_acl_alloc(3, flags);
        if (!acl)
@@ -279,11 +279,11 @@ check_perm:
  * system calls. All permissions that are not granted by the acl are removed.
  * The permissions in the acl are changed to reflect the mode_p parameter.
  */
-static int posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
+static int posix_acl_create_masq(struct posix_acl *acl, umode_t *mode_p)
 {
        struct posix_acl_entry *pa, *pe;
        struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
-       mode_t mode = *mode_p;
+       umode_t mode = *mode_p;
        int not_equiv = 0;
 
        /* assert(atomic_read(acl->a_refcount) == 1); */
@@ -336,7 +336,7 @@ static int posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
 /*
  * Modify the ACL for the chmod syscall.
  */
-static int posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
+static int posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode)
 {
        struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
        struct posix_acl_entry *pa, *pe;
@@ -382,7 +382,7 @@ static int posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
 }
 
 int
-posix_acl_create(struct posix_acl **acl, gfp_t gfp, mode_t *mode_p)
+posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p)
 {
        struct posix_acl *clone = posix_acl_clone(*acl, gfp);
        int err = -ENOMEM;
@@ -400,7 +400,7 @@ posix_acl_create(struct posix_acl **acl, gfp_t gfp, mode_t *mode_p)
 EXPORT_SYMBOL(posix_acl_create);
 
 int
-posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, mode_t mode)
+posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
 {
        struct posix_acl *clone = posix_acl_clone(*acl, gfp);
        int err = -ENOMEM;
index 08e3ecc..5eb0206 100644 (file)
@@ -1118,7 +1118,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
         * Warn that /proc/pid/oom_adj is deprecated, see
         * Documentation/feature-removal-schedule.txt.
         */
-       WARN_ONCE(1, "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n",
+       printk_once(KERN_WARNING "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n",
                  current->comm, task_pid_nr(current), task_pid_nr(task),
                  task_pid_nr(task));
        task->signal->oom_adj = oom_adjust;
@@ -1919,6 +1919,14 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info)
                spin_lock(&files->file_lock);
                file = fcheck_files(files, fd);
                if (file) {
+                       unsigned int f_flags;
+                       struct fdtable *fdt;
+
+                       fdt = files_fdtable(files);
+                       f_flags = file->f_flags & ~O_CLOEXEC;
+                       if (FD_ISSET(fd, fdt->close_on_exec))
+                               f_flags |= O_CLOEXEC;
+
                        if (path) {
                                *path = file->f_path;
                                path_get(&file->f_path);
@@ -1928,7 +1936,7 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info)
                                         "pos:\t%lli\n"
                                         "flags:\t0%o\n",
                                         (long long) file->f_pos,
-                                        file->f_flags);
+                                        f_flags);
                        spin_unlock(&files->file_lock);
                        put_files_struct(files);
                        return 0;
index 977ed27..893b961 100644 (file)
@@ -39,8 +39,9 @@
 #define        PSTORE_NAMELEN  64
 
 struct pstore_private {
+       struct pstore_info *psi;
+       enum pstore_type_id type;
        u64     id;
-       int     (*erase)(u64);
        ssize_t size;
        char    data[];
 };
@@ -73,7 +74,7 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct pstore_private *p = dentry->d_inode->i_private;
 
-       p->erase(p->id);
+       p->psi->erase(p->type, p->id, p->psi);
 
        return simple_unlink(dir, dentry);
 }
@@ -175,8 +176,8 @@ int pstore_is_mounted(void)
  * Set the mtime & ctime to the date that this record was originally stored.
  */
 int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
-                             char *data, size_t size,
-                             struct timespec time, int (*erase)(u64))
+                 char *data, size_t size, struct timespec time,
+                 struct pstore_info *psi)
 {
        struct dentry           *root = pstore_sb->s_root;
        struct dentry           *dentry;
@@ -192,8 +193,9 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
        private = kmalloc(sizeof *private + size, GFP_KERNEL);
        if (!private)
                goto fail_alloc;
+       private->type = type;
        private->id = id;
-       private->erase = erase;
+       private->psi = psi;
 
        switch (type) {
        case PSTORE_TYPE_DMESG:
index 8c9f23e..611c1b3 100644 (file)
@@ -2,5 +2,5 @@ extern void     pstore_set_kmsg_bytes(int);
 extern void    pstore_get_records(void);
 extern int     pstore_mkfile(enum pstore_type_id, char *psname, u64 id,
                              char *data, size_t size,
-                             struct timespec time, int (*erase)(u64));
+                             struct timespec time, struct pstore_info *psi);
 extern int     pstore_is_mounted(void);
index f2c3ff2..c5300ec 100644 (file)
@@ -37,6 +37,8 @@
 static DEFINE_SPINLOCK(pstore_lock);
 static struct pstore_info *psinfo;
 
+static char *backend;
+
 /* How much of the console log to snapshot */
 static unsigned long kmsg_bytes = 10240;
 
@@ -67,7 +69,8 @@ static void pstore_dump(struct kmsg_dumper *dumper,
        unsigned long   size, total = 0;
        char            *dst, *why;
        u64             id;
-       int             hsize, part = 1;
+       int             hsize;
+       unsigned int    part = 1;
 
        if (reason < ARRAY_SIZE(reason_str))
                why = reason_str[reason];
@@ -78,7 +81,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
        oopscount++;
        while (total < kmsg_bytes) {
                dst = psinfo->buf;
-               hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part++);
+               hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
                size = psinfo->bufsize - hsize;
                dst += hsize;
 
@@ -94,14 +97,16 @@ static void pstore_dump(struct kmsg_dumper *dumper,
                memcpy(dst, s1 + s1_start, l1_cpy);
                memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
 
-               id = psinfo->write(PSTORE_TYPE_DMESG, hsize + l1_cpy + l2_cpy);
+               id = psinfo->write(PSTORE_TYPE_DMESG, part,
+                                  hsize + l1_cpy + l2_cpy, psinfo);
                if (reason == KMSG_DUMP_OOPS && pstore_is_mounted())
                        pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id,
                                      psinfo->buf, hsize + l1_cpy + l2_cpy,
-                                     CURRENT_TIME, psinfo->erase);
+                                     CURRENT_TIME, psinfo);
                l1 -= l1_cpy;
                l2 -= l2_cpy;
                total += l1_cpy + l2_cpy;
+               part++;
        }
        mutex_unlock(&psinfo->buf_mutex);
 }
@@ -128,6 +133,12 @@ int pstore_register(struct pstore_info *psi)
                spin_unlock(&pstore_lock);
                return -EBUSY;
        }
+
+       if (backend && strcmp(backend, psi->name)) {
+               spin_unlock(&pstore_lock);
+               return -EINVAL;
+       }
+
        psinfo = psi;
        spin_unlock(&pstore_lock);
 
@@ -166,9 +177,9 @@ void pstore_get_records(void)
        if (rc)
                goto out;
 
-       while ((size = psi->read(&id, &type, &time)) > 0) {
+       while ((size = psi->read(&id, &type, &time, psi)) > 0) {
                if (pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size,
-                                 time, psi->erase))
+                                 time, psi))
                        failed++;
        }
        psi->close(psi);
@@ -196,12 +207,15 @@ int pstore_write(enum pstore_type_id type, char *buf, size_t size)
 
        mutex_lock(&psinfo->buf_mutex);
        memcpy(psinfo->buf, buf, size);
-       id = psinfo->write(type, size);
+       id = psinfo->write(type, 0, size, psinfo);
        if (pstore_is_mounted())
                pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf,
-                             size, CURRENT_TIME, psinfo->erase);
+                             size, CURRENT_TIME, psinfo);
        mutex_unlock(&psinfo->buf_mutex);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(pstore_write);
+
+module_param(backend, charp, 0444);
+MODULE_PARM_DESC(backend, "Pstore backend to use");
index 7362cf4..6da0396 100644 (file)
@@ -272,12 +272,10 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
        case ACL_TYPE_ACCESS:
                name = POSIX_ACL_XATTR_ACCESS;
                if (acl) {
-                       mode_t mode = inode->i_mode;
-                       error = posix_acl_equiv_mode(acl, &mode);
+                       error = posix_acl_equiv_mode(acl, &inode->i_mode);
                        if (error < 0)
                                return error;
                        else {
-                               inode->i_mode = mode;
                                if (error == 0)
                                        acl = NULL;
                        }
@@ -354,8 +352,6 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
                return PTR_ERR(acl);
 
        if (acl) {
-               mode_t mode = inode->i_mode;
-
                /* Copy the default ACL to the default ACL of a new directory */
                if (S_ISDIR(inode->i_mode)) {
                        err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
@@ -366,12 +362,10 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
 
                /* Now we reconcile the new ACL and the mode,
                   potentially modifying both */
-               err = posix_acl_create(&acl, GFP_NOFS, &mode);
+               err = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
                if (err < 0)
                        return err;
 
-               inode->i_mode = mode;
-
                /* If we need an ACL.. */
                if (err > 0)
                        err = reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS, acl);
index 4a6f7f4..b4f2ab4 100644 (file)
@@ -29,10 +29,7 @@ void fsstack_copy_inode_size(struct inode *dst, struct inode *src)
         *
         * We don't actually know what locking is used at the lower level;
         * but if it's a filesystem that supports quotas, it will be using
-        * i_lock as in inode_add_bytes().  tmpfs uses other locking, and
-        * its 32-bit is (just) able to exceed 2TB i_size with the aid of
-        * holes; but its i_blocks cannot carry into the upper long without
-        * almost 2TB swap - let's ignore that case.
+        * i_lock as in inode_add_bytes().
         */
        if (sizeof(i_blocks) > sizeof(long))
                spin_lock(&src->i_lock);
index 9610391..ba5316f 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -27,12 +27,12 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
        stat->uid = inode->i_uid;
        stat->gid = inode->i_gid;
        stat->rdev = inode->i_rdev;
+       stat->size = i_size_read(inode);
        stat->atime = inode->i_atime;
        stat->mtime = inode->i_mtime;
        stat->ctime = inode->i_ctime;
-       stat->size = i_size_read(inode);
-       stat->blocks = inode->i_blocks;
        stat->blksize = (1 << inode->i_blkbits);
+       stat->blocks = inode->i_blocks;
 }
 
 EXPORT_SYMBOL(generic_fillattr);
index 44ce516..b6c4b37 100644 (file)
@@ -221,7 +221,7 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
 }
 
 static int
-xfs_set_mode(struct inode *inode, mode_t mode)
+xfs_set_mode(struct inode *inode, umode_t mode)
 {
        int error = 0;
 
@@ -267,7 +267,7 @@ posix_acl_default_exists(struct inode *inode)
 int
 xfs_inherit_acl(struct inode *inode, struct posix_acl *acl)
 {
-       mode_t mode = inode->i_mode;
+       umode_t mode = inode->i_mode;
        int error = 0, inherit = 0;
 
        if (S_ISDIR(inode->i_mode)) {
@@ -381,7 +381,7 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,
                goto out_release;
 
        if (type == ACL_TYPE_ACCESS) {
-               mode_t mode = inode->i_mode;
+               umode_t mode = inode->i_mode;
                error = posix_acl_equiv_mode(acl, &mode);
 
                if (error <= 0) {
index d1fe745..c57836d 100644 (file)
@@ -596,7 +596,7 @@ _xfs_buf_read(
        bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD);
 
        status = xfs_buf_iorequest(bp);
-       if (status || XFS_BUF_ISERROR(bp) || (flags & XBF_ASYNC))
+       if (status || bp->b_error || (flags & XBF_ASYNC))
                return status;
        return xfs_buf_iowait(bp);
 }
@@ -679,7 +679,6 @@ xfs_buf_read_uncached(
        /* set up the buffer for a read IO */
        XFS_BUF_SET_ADDR(bp, daddr);
        XFS_BUF_READ(bp);
-       XFS_BUF_BUSY(bp);
 
        xfsbdstrat(mp, bp);
        error = xfs_buf_iowait(bp);
@@ -1069,7 +1068,7 @@ xfs_bioerror(
        /*
         * No need to wait until the buffer is unpinned, we aren't flushing it.
         */
-       XFS_BUF_ERROR(bp, EIO);
+       xfs_buf_ioerror(bp, EIO);
 
        /*
         * We're calling xfs_buf_ioend, so delete XBF_DONE flag.
@@ -1094,7 +1093,7 @@ STATIC int
 xfs_bioerror_relse(
        struct xfs_buf  *bp)
 {
-       int64_t         fl = XFS_BUF_BFLAGS(bp);
+       int64_t         fl = bp->b_flags;
        /*
         * No need to wait until the buffer is unpinned.
         * We aren't flushing it.
@@ -1115,7 +1114,7 @@ xfs_bioerror_relse(
                 * There's no reason to mark error for
                 * ASYNC buffers.
                 */
-               XFS_BUF_ERROR(bp, EIO);
+               xfs_buf_ioerror(bp, EIO);
                XFS_BUF_FINISH_IOWAIT(bp);
        } else {
                xfs_buf_relse(bp);
@@ -1324,7 +1323,7 @@ xfs_buf_offset(
        struct page             *page;
 
        if (bp->b_flags & XBF_MAPPED)
-               return XFS_BUF_PTR(bp) + offset;
+               return bp->b_addr + offset;
 
        offset += bp->b_offset;
        page = bp->b_pages[offset >> PAGE_SHIFT];
@@ -1484,7 +1483,7 @@ xfs_setsize_buftarg_flags(
        if (set_blocksize(btp->bt_bdev, sectorsize)) {
                xfs_warn(btp->bt_mount,
                        "Cannot set_blocksize to %u on device %s\n",
-                       sectorsize, XFS_BUFTARG_NAME(btp));
+                       sectorsize, xfs_buf_target_name(btp));
                return EINVAL;
        }
 
@@ -1681,7 +1680,7 @@ xfs_buf_delwri_split(
        list_for_each_entry_safe(bp, n, dwq, b_list) {
                ASSERT(bp->b_flags & XBF_DELWRI);
 
-               if (!XFS_BUF_ISPINNED(bp) && xfs_buf_trylock(bp)) {
+               if (!xfs_buf_ispinned(bp) && xfs_buf_trylock(bp)) {
                        if (!force &&
                            time_before(jiffies, bp->b_queuetime + age)) {
                                xfs_buf_unlock(bp);
index 6a83b46..620972b 100644 (file)
@@ -228,11 +228,15 @@ extern void xfs_buf_delwri_promote(xfs_buf_t *);
 extern int xfs_buf_init(void);
 extern void xfs_buf_terminate(void);
 
-#define xfs_buf_target_name(target)    \
-       ({ char __b[BDEVNAME_SIZE]; bdevname((target)->bt_bdev, __b); __b; })
+static inline const char *
+xfs_buf_target_name(struct xfs_buftarg *target)
+{
+       static char __b[BDEVNAME_SIZE];
+
+       return bdevname(target->bt_bdev, __b);
+}
 
 
-#define XFS_BUF_BFLAGS(bp)     ((bp)->b_flags)
 #define XFS_BUF_ZEROFLAGS(bp) \
        ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI| \
                            XBF_SYNCIO|XBF_FUA|XBF_FLUSH))
@@ -251,23 +255,14 @@ void xfs_buf_stale(struct xfs_buf *bp);
 #define XFS_BUF_UNDELAYWRITE(bp)       xfs_buf_delwri_dequeue(bp)
 #define XFS_BUF_ISDELAYWRITE(bp)       ((bp)->b_flags & XBF_DELWRI)
 
-#define XFS_BUF_ERROR(bp,no)   xfs_buf_ioerror(bp,no)
-#define XFS_BUF_GETERROR(bp)   xfs_buf_geterror(bp)
-#define XFS_BUF_ISERROR(bp)    (xfs_buf_geterror(bp) ? 1 : 0)
-
 #define XFS_BUF_DONE(bp)       ((bp)->b_flags |= XBF_DONE)
 #define XFS_BUF_UNDONE(bp)     ((bp)->b_flags &= ~XBF_DONE)
 #define XFS_BUF_ISDONE(bp)     ((bp)->b_flags & XBF_DONE)
 
-#define XFS_BUF_BUSY(bp)       do { } while (0)
-#define XFS_BUF_UNBUSY(bp)     do { } while (0)
-#define XFS_BUF_ISBUSY(bp)     (1)
-
 #define XFS_BUF_ASYNC(bp)      ((bp)->b_flags |= XBF_ASYNC)
 #define XFS_BUF_UNASYNC(bp)    ((bp)->b_flags &= ~XBF_ASYNC)
 #define XFS_BUF_ISASYNC(bp)    ((bp)->b_flags & XBF_ASYNC)
 
-#define XFS_BUF_HOLD(bp)       xfs_buf_hold(bp)
 #define XFS_BUF_READ(bp)       ((bp)->b_flags |= XBF_READ)
 #define XFS_BUF_UNREAD(bp)     ((bp)->b_flags &= ~XBF_READ)
 #define XFS_BUF_ISREAD(bp)     ((bp)->b_flags & XBF_READ)
@@ -276,10 +271,6 @@ void xfs_buf_stale(struct xfs_buf *bp);
 #define XFS_BUF_UNWRITE(bp)    ((bp)->b_flags &= ~XBF_WRITE)
 #define XFS_BUF_ISWRITE(bp)    ((bp)->b_flags & XBF_WRITE)
 
-#define XFS_BUF_SET_START(bp)                  do { } while (0)
-
-#define XFS_BUF_PTR(bp)                        (xfs_caddr_t)((bp)->b_addr)
-#define XFS_BUF_SET_PTR(bp, val, cnt)  xfs_buf_associate_memory(bp, val, cnt)
 #define XFS_BUF_ADDR(bp)               ((bp)->b_bn)
 #define XFS_BUF_SET_ADDR(bp, bno)      ((bp)->b_bn = (xfs_daddr_t)(bno))
 #define XFS_BUF_OFFSET(bp)             ((bp)->b_file_offset)
@@ -299,14 +290,13 @@ xfs_buf_set_ref(
 #define XFS_BUF_SET_VTYPE_REF(bp, type, ref)   xfs_buf_set_ref(bp, ref)
 #define XFS_BUF_SET_VTYPE(bp, type)            do { } while (0)
 
-#define XFS_BUF_ISPINNED(bp)   atomic_read(&((bp)->b_pin_count))
+static inline int xfs_buf_ispinned(struct xfs_buf *bp)
+{
+       return atomic_read(&bp->b_pin_count);
+}
 
 #define XFS_BUF_FINISH_IOWAIT(bp)      complete(&bp->b_iowait);
 
-#define XFS_BUF_SET_TARGET(bp, target) ((bp)->b_target = (target))
-#define XFS_BUF_TARGET(bp)             ((bp)->b_target)
-#define XFS_BUFTARG_NAME(target)       xfs_buf_target_name(target)
-
 static inline void xfs_buf_relse(xfs_buf_t *bp)
 {
        xfs_buf_unlock(bp);
index e4c938a..4604f90 100644 (file)
@@ -332,7 +332,7 @@ xfs_sync_fsdata(
         * between there and here.
         */
        bp = xfs_getsb(mp, 0);
-       if (XFS_BUF_ISPINNED(bp))
+       if (xfs_buf_ispinned(bp))
                xfs_log_force(mp, 0);
 
        return xfs_bwrite(mp, bp);
index 837f311..db62959 100644 (file)
@@ -318,10 +318,9 @@ xfs_qm_init_dquot_blk(
        int             curid, i;
 
        ASSERT(tp);
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(xfs_buf_islocked(bp));
 
-       d = (xfs_dqblk_t *)XFS_BUF_PTR(bp);
+       d = bp->b_addr;
 
        /*
         * ID of the first dquot in the block - id's are zero based.
@@ -403,7 +402,7 @@ xfs_qm_dqalloc(
                               dqp->q_blkno,
                               mp->m_quotainfo->qi_dqchunklen,
                               0);
-       if (!bp || (error = XFS_BUF_GETERROR(bp)))
+       if (!bp || (error = xfs_buf_geterror(bp)))
                goto error1;
        /*
         * Make a chunk of dquots out of this buffer and log
@@ -534,13 +533,12 @@ xfs_qm_dqtobp(
                        return XFS_ERROR(error);
        }
 
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(xfs_buf_islocked(bp));
 
        /*
         * calculate the location of the dquot inside the buffer.
         */
-       ddq = (struct xfs_disk_dquot *)(XFS_BUF_PTR(bp) + dqp->q_bufoffset);
+       ddq = bp->b_addr + dqp->q_bufoffset;
 
        /*
         * A simple sanity check in case we got a corrupted dquot...
@@ -553,7 +551,6 @@ xfs_qm_dqtobp(
                        xfs_trans_brelse(tp, bp);
                        return XFS_ERROR(EIO);
                }
-               XFS_BUF_BUSY(bp); /* We dirtied this */
        }
 
        *O_bpp = bp;
@@ -622,7 +619,6 @@ xfs_qm_dqread(
         * this particular dquot was repaired. We still aren't afraid to
         * brelse it because we have the changes incore.
         */
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(xfs_buf_islocked(bp));
        xfs_trans_brelse(tp, bp);
 
@@ -1204,7 +1200,7 @@ xfs_qm_dqflush(
        /*
         * Calculate the location of the dquot inside the buffer.
         */
-       ddqp = (struct xfs_disk_dquot *)(XFS_BUF_PTR(bp) + dqp->q_bufoffset);
+       ddqp = bp->b_addr + dqp->q_bufoffset;
 
        /*
         * A simple sanity check in case we got a corrupted dquot..
@@ -1240,7 +1236,7 @@ xfs_qm_dqflush(
         * If the buffer is pinned then push on the log so we won't
         * get stuck waiting in the write for too long.
         */
-       if (XFS_BUF_ISPINNED(bp)) {
+       if (xfs_buf_ispinned(bp)) {
                trace_xfs_dqflush_force(dqp);
                xfs_log_force(mp, 0);
        }
@@ -1447,7 +1443,7 @@ xfs_qm_dqflock_pushbuf_wait(
                goto out_lock;
 
        if (XFS_BUF_ISDELAYWRITE(bp)) {
-               if (XFS_BUF_ISPINNED(bp))
+               if (xfs_buf_ispinned(bp))
                        xfs_log_force(mp, 0);
                xfs_buf_delwri_promote(bp);
                wake_up_process(bp->b_target->bt_task);
index 46e54ad..9a0aa76 100644 (file)
@@ -1240,7 +1240,7 @@ xfs_qm_reset_dqcounts(
        do_div(j, sizeof(xfs_dqblk_t));
        ASSERT(mp->m_quotainfo->qi_dqperchunk == j);
 #endif
-       ddq = (xfs_disk_dquot_t *)XFS_BUF_PTR(bp);
+       ddq = bp->b_addr;
        for (j = 0; j < mp->m_quotainfo->qi_dqperchunk; j++) {
                /*
                 * Do a sanity check, and if needed, repair the dqblk. Don't
index 2c656ef..39632d9 100644 (file)
@@ -51,7 +51,10 @@ extern int posix_acl_default_exists(struct inode *inode);
 extern const struct xattr_handler xfs_xattr_acl_access_handler;
 extern const struct xattr_handler xfs_xattr_acl_default_handler;
 #else
-# define xfs_get_acl(inode, type)                      NULL
+static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type)
+{
+       return NULL;
+}
 # define xfs_inherit_acl(inode, default_acl)           0
 # define xfs_acl_chmod(inode)                          0
 # define posix_acl_access_exists(inode)                        0
index 6530769..4805f00 100644 (file)
@@ -103,7 +103,7 @@ typedef struct xfs_agf {
 /* disk block (xfs_daddr_t) in the AG */
 #define XFS_AGF_DADDR(mp)      ((xfs_daddr_t)(1 << (mp)->m_sectbb_log))
 #define        XFS_AGF_BLOCK(mp)       XFS_HDR_BLOCK(mp, XFS_AGF_DADDR(mp))
-#define        XFS_BUF_TO_AGF(bp)      ((xfs_agf_t *)XFS_BUF_PTR(bp))
+#define        XFS_BUF_TO_AGF(bp)      ((xfs_agf_t *)((bp)->b_addr))
 
 extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
                        xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
@@ -156,7 +156,7 @@ typedef struct xfs_agi {
 /* disk block (xfs_daddr_t) in the AG */
 #define XFS_AGI_DADDR(mp)      ((xfs_daddr_t)(2 << (mp)->m_sectbb_log))
 #define        XFS_AGI_BLOCK(mp)       XFS_HDR_BLOCK(mp, XFS_AGI_DADDR(mp))
-#define        XFS_BUF_TO_AGI(bp)      ((xfs_agi_t *)XFS_BUF_PTR(bp))
+#define        XFS_BUF_TO_AGI(bp)      ((xfs_agi_t *)((bp)->b_addr))
 
 extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp,
                                xfs_agnumber_t agno, struct xfs_buf **bpp);
@@ -168,7 +168,7 @@ extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp,
 #define XFS_AGFL_DADDR(mp)     ((xfs_daddr_t)(3 << (mp)->m_sectbb_log))
 #define        XFS_AGFL_BLOCK(mp)      XFS_HDR_BLOCK(mp, XFS_AGFL_DADDR(mp))
 #define XFS_AGFL_SIZE(mp)      ((mp)->m_sb.sb_sectsize / sizeof(xfs_agblock_t))
-#define        XFS_BUF_TO_AGFL(bp)     ((xfs_agfl_t *)XFS_BUF_PTR(bp))
+#define        XFS_BUF_TO_AGFL(bp)     ((xfs_agfl_t *)((bp)->b_addr))
 
 typedef struct xfs_agfl {
        __be32          agfl_bno[1];    /* actually XFS_AGFL_SIZE(mp) */
index 1e00b3e..bdd9cb5 100644 (file)
@@ -451,8 +451,7 @@ xfs_alloc_read_agfl(
                        XFS_FSS_TO_BB(mp, 1), 0, &bp);
        if (error)
                return error;
-       ASSERT(bp);
-       ASSERT(!XFS_BUF_GETERROR(bp));
+       ASSERT(!xfs_buf_geterror(bp));
        XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGFL, XFS_AGFL_REF);
        *bpp = bp;
        return 0;
@@ -2116,7 +2115,7 @@ xfs_read_agf(
        if (!*bpp)
                return 0;
 
-       ASSERT(!XFS_BUF_GETERROR(*bpp));
+       ASSERT(!(*bpp)->b_error);
        agf = XFS_BUF_TO_AGF(*bpp);
 
        /*
@@ -2168,7 +2167,7 @@ xfs_alloc_read_agf(
                return error;
        if (!*bpp)
                return 0;
-       ASSERT(!XFS_BUF_GETERROR(*bpp));
+       ASSERT(!(*bpp)->b_error);
 
        agf = XFS_BUF_TO_AGF(*bpp);
        pag = xfs_perag_get(mp, agno);
index cbae424..160bcdc 100644 (file)
@@ -2121,8 +2121,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
 
                bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt,
                                 XBF_LOCK | XBF_DONT_BLOCK);
-               ASSERT(bp);
-               ASSERT(!XFS_BUF_GETERROR(bp));
+               ASSERT(!xfs_buf_geterror(bp));
 
                tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen :
                                                        XFS_BUF_SIZE(bp);
index ab3e5c6..452a291 100644 (file)
@@ -3383,8 +3383,7 @@ xfs_bmap_local_to_extents(
                ASSERT(args.len == 1);
                *firstblock = args.fsbno;
                bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
-               memcpy((char *)XFS_BUF_PTR(bp), ifp->if_u1.if_data,
-                       ifp->if_bytes);
+               memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
                xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
                xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
                xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
index cabf4b5..2b9fd38 100644 (file)
@@ -275,8 +275,7 @@ xfs_btree_dup_cursor(
                                return error;
                        }
                        new->bc_bufs[i] = bp;
-                       ASSERT(bp);
-                       ASSERT(!XFS_BUF_GETERROR(bp));
+                       ASSERT(!xfs_buf_geterror(bp));
                } else
                        new->bc_bufs[i] = NULL;
        }
@@ -467,8 +466,7 @@ xfs_btree_get_bufl(
        ASSERT(fsbno != NULLFSBLOCK);
        d = XFS_FSB_TO_DADDR(mp, fsbno);
        bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
-       ASSERT(bp);
-       ASSERT(!XFS_BUF_GETERROR(bp));
+       ASSERT(!xfs_buf_geterror(bp));
        return bp;
 }
 
@@ -491,8 +489,7 @@ xfs_btree_get_bufs(
        ASSERT(agbno != NULLAGBLOCK);
        d = XFS_AGB_TO_DADDR(mp, agno, agbno);
        bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
-       ASSERT(bp);
-       ASSERT(!XFS_BUF_GETERROR(bp));
+       ASSERT(!xfs_buf_geterror(bp));
        return bp;
 }
 
@@ -632,7 +629,7 @@ xfs_btree_read_bufl(
                        mp->m_bsize, lock, &bp))) {
                return error;
        }
-       ASSERT(!bp || !XFS_BUF_GETERROR(bp));
+       ASSERT(!xfs_buf_geterror(bp));
        if (bp)
                XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);
        *bpp = bp;
@@ -973,8 +970,7 @@ xfs_btree_get_buf_block(
        *bpp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d,
                                 mp->m_bsize, flags);
 
-       ASSERT(*bpp);
-       ASSERT(!XFS_BUF_GETERROR(*bpp));
+       ASSERT(!xfs_buf_geterror(*bpp));
 
        *block = XFS_BUF_TO_BLOCK(*bpp);
        return 0;
@@ -1006,8 +1002,7 @@ xfs_btree_read_buf_block(
        if (error)
                return error;
 
-       ASSERT(*bpp != NULL);
-       ASSERT(!XFS_BUF_GETERROR(*bpp));
+       ASSERT(!xfs_buf_geterror(*bpp));
 
        xfs_btree_set_refs(cur, *bpp);
        *block = XFS_BUF_TO_BLOCK(*bpp);
index 8d05a6a..5b240de 100644 (file)
@@ -262,7 +262,7 @@ typedef struct xfs_btree_cur
 /*
  * Convert from buffer to btree block header.
  */
-#define        XFS_BUF_TO_BLOCK(bp)    ((struct xfs_btree_block *)XFS_BUF_PTR(bp))
+#define        XFS_BUF_TO_BLOCK(bp)    ((struct xfs_btree_block *)((bp)->b_addr))
 
 
 /*
index 8849291..cac2ecf 100644 (file)
@@ -124,9 +124,9 @@ xfs_buf_item_log_check(
 
        bp = bip->bli_buf;
        ASSERT(XFS_BUF_COUNT(bp) > 0);
-       ASSERT(XFS_BUF_PTR(bp) != NULL);
+       ASSERT(bp->b_addr != NULL);
        orig = bip->bli_orig;
-       buffer = XFS_BUF_PTR(bp);
+       buffer = bp->b_addr;
        for (x = 0; x < XFS_BUF_COUNT(bp); x++) {
                if (orig[x] != buffer[x] && !btst(bip->bli_logged, x)) {
                        xfs_emerg(bp->b_mount,
@@ -371,7 +371,6 @@ xfs_buf_item_pin(
 {
        struct xfs_buf_log_item *bip = BUF_ITEM(lip);
 
-       ASSERT(XFS_BUF_ISBUSY(bip->bli_buf));
        ASSERT(atomic_read(&bip->bli_refcount) > 0);
        ASSERT((bip->bli_flags & XFS_BLI_LOGGED) ||
               (bip->bli_flags & XFS_BLI_STALE));
@@ -479,13 +478,13 @@ xfs_buf_item_trylock(
        struct xfs_buf_log_item *bip = BUF_ITEM(lip);
        struct xfs_buf          *bp = bip->bli_buf;
 
-       if (XFS_BUF_ISPINNED(bp))
+       if (xfs_buf_ispinned(bp))
                return XFS_ITEM_PINNED;
        if (!xfs_buf_trylock(bp))
                return XFS_ITEM_LOCKED;
 
        /* take a reference to the buffer.  */
-       XFS_BUF_HOLD(bp);
+       xfs_buf_hold(bp);
 
        ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
        trace_xfs_buf_item_trylock(bip);
@@ -726,7 +725,7 @@ xfs_buf_item_init(
         * to have logged.
         */
        bip->bli_orig = (char *)kmem_alloc(XFS_BUF_COUNT(bp), KM_SLEEP);
-       memcpy(bip->bli_orig, XFS_BUF_PTR(bp), XFS_BUF_COUNT(bp));
+       memcpy(bip->bli_orig, bp->b_addr, XFS_BUF_COUNT(bp));
        bip->bli_logged = (char *)kmem_zalloc(XFS_BUF_COUNT(bp) / NBBY, KM_SLEEP);
 #endif
 
@@ -895,7 +894,6 @@ xfs_buf_attach_iodone(
 {
        xfs_log_item_t  *head_lip;
 
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(xfs_buf_islocked(bp));
 
        lip->li_cb = cb;
@@ -960,7 +958,7 @@ xfs_buf_iodone_callbacks(
        static ulong            lasttime;
        static xfs_buftarg_t    *lasttarg;
 
-       if (likely(!XFS_BUF_GETERROR(bp)))
+       if (likely(!xfs_buf_geterror(bp)))
                goto do_callbacks;
 
        /*
@@ -973,14 +971,14 @@ xfs_buf_iodone_callbacks(
                goto do_callbacks;
        }
 
-       if (XFS_BUF_TARGET(bp) != lasttarg ||
+       if (bp->b_target != lasttarg ||
            time_after(jiffies, (lasttime + 5*HZ))) {
                lasttime = jiffies;
                xfs_alert(mp, "Device %s: metadata write error block 0x%llx",
-                       XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),
+                       xfs_buf_target_name(bp->b_target),
                      (__uint64_t)XFS_BUF_ADDR(bp));
        }
-       lasttarg = XFS_BUF_TARGET(bp);
+       lasttarg = bp->b_target;
 
        /*
         * If the write was asynchronous then no one will be looking for the
@@ -991,12 +989,11 @@ xfs_buf_iodone_callbacks(
         * around.
         */
        if (XFS_BUF_ISASYNC(bp)) {
-               XFS_BUF_ERROR(bp, 0); /* errno of 0 unsets the flag */
+               xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */
 
                if (!XFS_BUF_ISSTALE(bp)) {
                        XFS_BUF_DELAYWRITE(bp);
                        XFS_BUF_DONE(bp);
-                       XFS_BUF_SET_START(bp);
                }
                ASSERT(bp->b_iodone != NULL);
                trace_xfs_buf_item_iodone_async(bp, _RET_IP_);
@@ -1013,7 +1010,6 @@ xfs_buf_iodone_callbacks(
        XFS_BUF_UNDELAYWRITE(bp);
 
        trace_xfs_buf_error_relse(bp, _RET_IP_);
-       xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
 
 do_callbacks:
        xfs_buf_do_callbacks(bp);
index 5bfcb87..ee9d542 100644 (file)
@@ -2050,7 +2050,7 @@ xfs_da_do_buf(
                case 0:
                        bp = xfs_trans_get_buf(trans, mp->m_ddev_targp,
                                mappedbno, nmapped, 0);
-                       error = bp ? XFS_BUF_GETERROR(bp) : XFS_ERROR(EIO);
+                       error = bp ? bp->b_error : XFS_ERROR(EIO);
                        break;
                case 1:
                case 2:
@@ -2268,7 +2268,7 @@ xfs_da_buf_make(int nbuf, xfs_buf_t **bps)
                dabuf->nbuf = 1;
                bp = bps[0];
                dabuf->bbcount = (short)BTOBB(XFS_BUF_COUNT(bp));
-               dabuf->data = XFS_BUF_PTR(bp);
+               dabuf->data = bp->b_addr;
                dabuf->bps[0] = bp;
        } else {
                dabuf->nbuf = nbuf;
@@ -2279,7 +2279,7 @@ xfs_da_buf_make(int nbuf, xfs_buf_t **bps)
                dabuf->data = kmem_alloc(BBTOB(dabuf->bbcount), KM_SLEEP);
                for (i = off = 0; i < nbuf; i++, off += XFS_BUF_COUNT(bp)) {
                        bp = bps[i];
-                       memcpy((char *)dabuf->data + off, XFS_BUF_PTR(bp),
+                       memcpy((char *)dabuf->data + off, bp->b_addr,
                                XFS_BUF_COUNT(bp));
                }
        }
@@ -2302,8 +2302,8 @@ xfs_da_buf_clean(xfs_dabuf_t *dabuf)
                for (i = off = 0; i < dabuf->nbuf;
                                i++, off += XFS_BUF_COUNT(bp)) {
                        bp = dabuf->bps[i];
-                       memcpy(XFS_BUF_PTR(bp), (char *)dabuf->data + off,
-                               XFS_BUF_COUNT(bp));
+                       memcpy(bp->b_addr, dabuf->data + off,
+                                               XFS_BUF_COUNT(bp));
                }
        }
 }
@@ -2340,7 +2340,7 @@ xfs_da_log_buf(xfs_trans_t *tp, xfs_dabuf_t *dabuf, uint first, uint last)
 
        ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]);
        if (dabuf->nbuf == 1) {
-               ASSERT(dabuf->data == (void *)XFS_BUF_PTR(dabuf->bps[0]));
+               ASSERT(dabuf->data == dabuf->bps[0]->b_addr);
                xfs_trans_log_buf(tp, dabuf->bps[0], first, last);
                return;
        }
index dffba9b..a372163 100644 (file)
@@ -148,7 +148,7 @@ typedef enum xfs_dinode_fmt {
                be32_to_cpu((dip)->di_nextents) : \
                be16_to_cpu((dip)->di_anextents))
 
-#define        XFS_BUF_TO_DINODE(bp)   ((xfs_dinode_t *)XFS_BUF_PTR(bp))
+#define        XFS_BUF_TO_DINODE(bp)   ((xfs_dinode_t *)((bp)->b_addr))
 
 /*
  * For block and character special files the 32bit dev_t is stored at the
index dd5628b..9f24ec2 100644 (file)
@@ -202,8 +202,7 @@ xfs_ialloc_inode_init(
                fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
                                         mp->m_bsize * blks_per_cluster,
                                         XBF_LOCK);
-               ASSERT(fbuf);
-               ASSERT(!XFS_BUF_GETERROR(fbuf));
+               ASSERT(!xfs_buf_geterror(fbuf));
 
                /*
                 * Initialize all inodes in this buffer and then log them.
@@ -1486,7 +1485,7 @@ xfs_read_agi(
        if (error)
                return error;
 
-       ASSERT(*bpp && !XFS_BUF_GETERROR(*bpp));
+       ASSERT(!xfs_buf_geterror(*bpp));
        agi = XFS_BUF_TO_AGI(*bpp);
 
        /*
index 2fcca4b..0239a7c 100644 (file)
@@ -2473,7 +2473,7 @@ cluster_corrupt_out:
                if (bp->b_iodone) {
                        XFS_BUF_UNDONE(bp);
                        XFS_BUF_STALE(bp);
-                       XFS_BUF_ERROR(bp,EIO);
+                       xfs_buf_ioerror(bp, EIO);
                        xfs_buf_ioend(bp, 0);
                } else {
                        XFS_BUF_STALE(bp);
@@ -2585,7 +2585,7 @@ xfs_iflush(
         * If the buffer is pinned then push on the log now so we won't
         * get stuck waiting in the write for too long.
         */
-       if (XFS_BUF_ISPINNED(bp))
+       if (xfs_buf_ispinned(bp))
                xfs_log_force(mp, 0);
 
        /*
index 06ff843..3a8d4f6 100644 (file)
@@ -878,7 +878,7 @@ xlog_iodone(xfs_buf_t *bp)
        /*
         * Race to shutdown the filesystem if we see an error.
         */
-       if (XFS_TEST_ERROR((XFS_BUF_GETERROR(bp)), l->l_mp,
+       if (XFS_TEST_ERROR((xfs_buf_geterror(bp)), l->l_mp,
                        XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) {
                xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp));
                XFS_BUF_STALE(bp);
@@ -1051,7 +1051,6 @@ xlog_alloc_log(xfs_mount_t        *mp,
        if (!bp)
                goto out_free_log;
        bp->b_iodone = xlog_iodone;
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(xfs_buf_islocked(bp));
        log->l_xbuf = bp;
 
@@ -1108,7 +1107,6 @@ xlog_alloc_log(xfs_mount_t        *mp,
                iclog->ic_callback_tail = &(iclog->ic_callback);
                iclog->ic_datap = (char *)iclog->ic_data + log->l_iclog_hsize;
 
-               ASSERT(XFS_BUF_ISBUSY(iclog->ic_bp));
                ASSERT(xfs_buf_islocked(iclog->ic_bp));
                init_waitqueue_head(&iclog->ic_force_wait);
                init_waitqueue_head(&iclog->ic_write_wait);
@@ -1248,7 +1246,7 @@ xlog_bdstrat(
        struct xlog_in_core     *iclog = bp->b_fspriv;
 
        if (iclog->ic_state & XLOG_STATE_IOERROR) {
-               XFS_BUF_ERROR(bp, EIO);
+               xfs_buf_ioerror(bp, EIO);
                XFS_BUF_STALE(bp);
                xfs_buf_ioend(bp, 0);
                /*
@@ -1355,7 +1353,6 @@ xlog_sync(xlog_t          *log,
        XFS_BUF_SET_COUNT(bp, count);
        bp->b_fspriv = iclog;
        XFS_BUF_ZEROFLAGS(bp);
-       XFS_BUF_BUSY(bp);
        XFS_BUF_ASYNC(bp);
        bp->b_flags |= XBF_SYNCIO;
 
@@ -1398,16 +1395,15 @@ xlog_sync(xlog_t                *log,
        if (split) {
                bp = iclog->ic_log->l_xbuf;
                XFS_BUF_SET_ADDR(bp, 0);             /* logical 0 */
-               XFS_BUF_SET_PTR(bp, (xfs_caddr_t)((__psint_t)&(iclog->ic_header)+
-                                           (__psint_t)count), split);
+               xfs_buf_associate_memory(bp,
+                               (char *)&iclog->ic_header + count, split);
                bp->b_fspriv = iclog;
                XFS_BUF_ZEROFLAGS(bp);
-               XFS_BUF_BUSY(bp);
                XFS_BUF_ASYNC(bp);
                bp->b_flags |= XBF_SYNCIO;
                if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
                        bp->b_flags |= XBF_FUA;
-               dptr = XFS_BUF_PTR(bp);
+               dptr = bp->b_addr;
                /*
                 * Bump the cycle numbers at the start of each block
                 * since this part of the buffer is at the start of
index 052a2c0..a199dbc 100644 (file)
@@ -147,7 +147,7 @@ xlog_align(
        xfs_daddr_t     offset = blk_no & ((xfs_daddr_t)log->l_sectBBsize - 1);
 
        ASSERT(BBTOB(offset + nbblks) <= XFS_BUF_SIZE(bp));
-       return XFS_BUF_PTR(bp) + BBTOB(offset);
+       return bp->b_addr + BBTOB(offset);
 }
 
 
@@ -178,9 +178,7 @@ xlog_bread_noalign(
 
        XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no);
        XFS_BUF_READ(bp);
-       XFS_BUF_BUSY(bp);
        XFS_BUF_SET_COUNT(bp, BBTOB(nbblks));
-       XFS_BUF_SET_TARGET(bp, log->l_mp->m_logdev_targp);
 
        xfsbdstrat(log->l_mp, bp);
        error = xfs_buf_iowait(bp);
@@ -220,18 +218,18 @@ xlog_bread_offset(
        xfs_buf_t       *bp,
        xfs_caddr_t     offset)
 {
-       xfs_caddr_t     orig_offset = XFS_BUF_PTR(bp);
+       xfs_caddr_t     orig_offset = bp->b_addr;
        int             orig_len = bp->b_buffer_length;
        int             error, error2;
 
-       error = XFS_BUF_SET_PTR(bp, offset, BBTOB(nbblks));
+       error = xfs_buf_associate_memory(bp, offset, BBTOB(nbblks));
        if (error)
                return error;
 
        error = xlog_bread_noalign(log, blk_no, nbblks, bp);
 
        /* must reset buffer pointer even on error */
-       error2 = XFS_BUF_SET_PTR(bp, orig_offset, orig_len);
+       error2 = xfs_buf_associate_memory(bp, orig_offset, orig_len);
        if (error)
                return error;
        return error2;
@@ -266,11 +264,9 @@ xlog_bwrite(
 
        XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no);
        XFS_BUF_ZEROFLAGS(bp);
-       XFS_BUF_BUSY(bp);
-       XFS_BUF_HOLD(bp);
+       xfs_buf_hold(bp);
        xfs_buf_lock(bp);
        XFS_BUF_SET_COUNT(bp, BBTOB(nbblks));
-       XFS_BUF_SET_TARGET(bp, log->l_mp->m_logdev_targp);
 
        if ((error = xfs_bwrite(log->l_mp, bp)))
                xfs_ioerror_alert("xlog_bwrite", log->l_mp,
@@ -360,7 +356,7 @@ STATIC void
 xlog_recover_iodone(
        struct xfs_buf  *bp)
 {
-       if (XFS_BUF_GETERROR(bp)) {
+       if (bp->b_error) {
                /*
                 * We're not going to bother about retrying
                 * this during recovery. One strike!
@@ -1262,7 +1258,7 @@ xlog_write_log_records(
                 */
                ealign = round_down(end_block, sectbb);
                if (j == 0 && (start_block + endcount > ealign)) {
-                       offset = XFS_BUF_PTR(bp) + BBTOB(ealign - start_block);
+                       offset = bp->b_addr + BBTOB(ealign - start_block);
                        error = xlog_bread_offset(log, ealign, sectbb,
                                                        bp, offset);
                        if (error)
@@ -2135,15 +2131,16 @@ xlog_recover_buffer_pass2(
 
        bp = xfs_buf_read(mp->m_ddev_targp, buf_f->blf_blkno, buf_f->blf_len,
                          buf_flags);
-       if (XFS_BUF_ISERROR(bp)) {
+       if (!bp)
+               return XFS_ERROR(ENOMEM);
+       error = bp->b_error;
+       if (error) {
                xfs_ioerror_alert("xlog_recover_do..(read#1)", mp,
                                  bp, buf_f->blf_blkno);
-               error = XFS_BUF_GETERROR(bp);
                xfs_buf_relse(bp);
                return error;
        }
 
-       error = 0;
        if (buf_f->blf_flags & XFS_BLF_INODE_BUF) {
                error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f);
        } else if (buf_f->blf_flags &
@@ -2227,14 +2224,17 @@ xlog_recover_inode_pass2(
 
        bp = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len,
                          XBF_LOCK);
-       if (XFS_BUF_ISERROR(bp)) {
+       if (!bp) {
+               error = ENOMEM;
+               goto error;
+       }
+       error = bp->b_error;
+       if (error) {
                xfs_ioerror_alert("xlog_recover_do..(read#2)", mp,
                                  bp, in_f->ilf_blkno);
-               error = XFS_BUF_GETERROR(bp);
                xfs_buf_relse(bp);
                goto error;
        }
-       error = 0;
        ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
        dip = (xfs_dinode_t *)xfs_buf_offset(bp, in_f->ilf_boffset);
 
@@ -3437,7 +3437,7 @@ xlog_do_recovery_pass(
                        /*
                         * Check for header wrapping around physical end-of-log
                         */
-                       offset = XFS_BUF_PTR(hbp);
+                       offset = hbp->b_addr;
                        split_hblks = 0;
                        wrapped_hblks = 0;
                        if (blk_no + hblks <= log->l_logBBsize) {
@@ -3497,7 +3497,7 @@ xlog_do_recovery_pass(
                        } else {
                                /* This log record is split across the
                                 * physical end of log */
-                               offset = XFS_BUF_PTR(dbp);
+                               offset = dbp->b_addr;
                                split_bblks = 0;
                                if (blk_no != log->l_logBBsize) {
                                        /* some data is before the physical
index 092e16a..0081657 100644 (file)
@@ -1615,7 +1615,7 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
                XFS_BUF_UNDELAYWRITE(sbp);
                XFS_BUF_WRITE(sbp);
                XFS_BUF_UNASYNC(sbp);
-               ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp);
+               ASSERT(sbp->b_target == mp->m_ddev_targp);
                xfsbdstrat(mp, sbp);
                error = xfs_buf_iowait(sbp);
                if (error)
@@ -1938,7 +1938,7 @@ xfs_getsb(
                xfs_buf_lock(bp);
        }
 
-       XFS_BUF_HOLD(bp);
+       xfs_buf_hold(bp);
        ASSERT(XFS_BUF_ISDONE(bp));
        return bp;
 }
index 8f76fdf..35561a5 100644 (file)
@@ -168,7 +168,7 @@ error_cancel:
                                xfs_trans_cancel(tp, cancelflags);
                                goto error;
                        }
-                       memset(XFS_BUF_PTR(bp), 0, mp->m_sb.sb_blocksize);
+                       memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
                        xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
                        /*
                         * Commit the transaction.
@@ -883,7 +883,7 @@ xfs_rtbuf_get(
        if (error) {
                return error;
        }
-       ASSERT(bp && !XFS_BUF_GETERROR(bp));
+       ASSERT(!xfs_buf_geterror(bp));
        *bpp = bp;
        return 0;
 }
@@ -943,7 +943,7 @@ xfs_rtcheck_range(
        if (error) {
                return error;
        }
-       bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
+       bufp = bp->b_addr;
        /*
         * Compute the starting word's address, and starting bit.
         */
@@ -994,7 +994,7 @@ xfs_rtcheck_range(
                        if (error) {
                                return error;
                        }
-                       b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
+                       b = bufp = bp->b_addr;
                        word = 0;
                } else {
                        /*
@@ -1040,7 +1040,7 @@ xfs_rtcheck_range(
                        if (error) {
                                return error;
                        }
-                       b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
+                       b = bufp = bp->b_addr;
                        word = 0;
                } else {
                        /*
@@ -1158,7 +1158,7 @@ xfs_rtfind_back(
        if (error) {
                return error;
        }
-       bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
+       bufp = bp->b_addr;
        /*
         * Get the first word's index & point to it.
         */
@@ -1210,7 +1210,7 @@ xfs_rtfind_back(
                        if (error) {
                                return error;
                        }
-                       bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
+                       bufp = bp->b_addr;
                        word = XFS_BLOCKWMASK(mp);
                        b = &bufp[word];
                } else {
@@ -1256,7 +1256,7 @@ xfs_rtfind_back(
                        if (error) {
                                return error;
                        }
-                       bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
+                       bufp = bp->b_addr;
                        word = XFS_BLOCKWMASK(mp);
                        b = &bufp[word];
                } else {
@@ -1333,7 +1333,7 @@ xfs_rtfind_forw(
        if (error) {
                return error;
        }
-       bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
+       bufp = bp->b_addr;
        /*
         * Get the first word's index & point to it.
         */
@@ -1384,7 +1384,7 @@ xfs_rtfind_forw(
                        if (error) {
                                return error;
                        }
-                       b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
+                       b = bufp = bp->b_addr;
                        word = 0;
                } else {
                        /*
@@ -1429,7 +1429,7 @@ xfs_rtfind_forw(
                        if (error) {
                                return error;
                        }
-                       b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
+                       b = bufp = bp->b_addr;
                        word = 0;
                } else {
                        /*
@@ -1649,7 +1649,7 @@ xfs_rtmodify_range(
        if (error) {
                return error;
        }
-       bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
+       bufp = bp->b_addr;
        /*
         * Compute the starting word's address, and starting bit.
         */
@@ -1694,7 +1694,7 @@ xfs_rtmodify_range(
                        if (error) {
                                return error;
                        }
-                       first = b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
+                       first = b = bufp = bp->b_addr;
                        word = 0;
                } else {
                        /*
@@ -1734,7 +1734,7 @@ xfs_rtmodify_range(
                        if (error) {
                                return error;
                        }
-                       first = b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
+                       first = b = bufp = bp->b_addr;
                        word = 0;
                } else {
                        /*
@@ -1832,8 +1832,8 @@ xfs_rtmodify_summary(
         */
        sp = XFS_SUMPTR(mp, bp, so);
        *sp += delta;
-       xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)XFS_BUF_PTR(bp)),
-               (uint)((char *)sp - (char *)XFS_BUF_PTR(bp) + sizeof(*sp) - 1));
+       xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr),
+               (uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1));
        return 0;
 }
 
index 09e1f4f..f7f3a35 100644 (file)
@@ -47,7 +47,7 @@ struct xfs_trans;
 #define        XFS_SUMOFFSTOBLOCK(mp,s)        \
        (((s) * (uint)sizeof(xfs_suminfo_t)) >> (mp)->m_sb.sb_blocklog)
 #define        XFS_SUMPTR(mp,bp,so)    \
-       ((xfs_suminfo_t *)((char *)XFS_BUF_PTR(bp) + \
+       ((xfs_suminfo_t *)((bp)->b_addr + \
                (((so) * (uint)sizeof(xfs_suminfo_t)) & XFS_BLOCKMASK(mp))))
 
 #define        XFS_BITTOBLOCK(mp,bi)   ((bi) >> (mp)->m_blkbit_log)
index d6d6fdf..c96a8a0 100644 (file)
@@ -104,9 +104,9 @@ xfs_ioerror_alert(
        xfs_alert(mp,
                 "I/O error occurred: meta-data dev %s block 0x%llx"
                 "       (\"%s\") error %d buf count %zd",
-               XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),
+               xfs_buf_target_name(bp->b_target),
                (__uint64_t)blkno, func,
-               XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp));
+               bp->b_error, XFS_BUF_COUNT(bp));
 }
 
 /*
@@ -137,8 +137,8 @@ xfs_read_buf(
        bp = xfs_buf_read(target, blkno, len, flags);
        if (!bp)
                return XFS_ERROR(EIO);
-       error = XFS_BUF_GETERROR(bp);
-       if (bp && !error && !XFS_FORCED_SHUTDOWN(mp)) {
+       error = bp->b_error;
+       if (!error && !XFS_FORCED_SHUTDOWN(mp)) {
                *bpp = bp;
        } else {
                *bpp = NULL;
index 1eb2ba5..cb6ae71 100644 (file)
@@ -509,7 +509,7 @@ static inline int xfs_sb_version_hasprojid32bit(xfs_sb_t *sbp)
 
 #define XFS_SB_DADDR           ((xfs_daddr_t)0) /* daddr in filesystem/ag */
 #define        XFS_SB_BLOCK(mp)        XFS_HDR_BLOCK(mp, XFS_SB_DADDR)
-#define XFS_BUF_TO_SBP(bp)     ((xfs_dsb_t *)XFS_BUF_PTR(bp))
+#define XFS_BUF_TO_SBP(bp)     ((xfs_dsb_t *)((bp)->b_addr))
 
 #define        XFS_HDR_BLOCK(mp,d)     ((xfs_agblock_t)XFS_BB_TO_FSBT(mp,d))
 #define        XFS_DADDR_TO_FSB(mp,d)  XFS_AGB_TO_FSB(mp, \
index 43233e9..c15aa29 100644 (file)
@@ -299,7 +299,7 @@ xfs_trans_ail_cursor_last(
  * Splice the log item list into the AIL at the given LSN. We splice to the
  * tail of the given LSN to maintain insert order for push traversals. The
  * cursor is optional, allowing repeated updates to the same LSN to avoid
- * repeated traversals.
+ * repeated traversals.  This should not be called with an empty list.
  */
 static void
 xfs_ail_splice(
@@ -308,50 +308,39 @@ xfs_ail_splice(
        struct list_head        *list,
        xfs_lsn_t               lsn)
 {
-       struct xfs_log_item     *lip = cur ? cur->item : NULL;
-       struct xfs_log_item     *next_lip;
+       struct xfs_log_item     *lip;
+
+       ASSERT(!list_empty(list));
 
        /*
-        * Get a new cursor if we don't have a placeholder or the existing one
-        * has been invalidated.
+        * Use the cursor to determine the insertion point if one is
+        * provided.  If not, or if the one we got is not valid,
+        * find the place in the AIL where the items belong.
         */
-       if (!lip || (__psint_t)lip & 1) {
+       lip = cur ? cur->item : NULL;
+       if (!lip || (__psint_t) lip & 1)
                lip = __xfs_trans_ail_cursor_last(ailp, lsn);
 
-               if (!lip) {
-                       /* The list is empty, so just splice and return.  */
-                       if (cur)
-                               cur->item = NULL;
-                       list_splice(list, &ailp->xa_ail);
-                       return;
-               }
-       }
+       /*
+        * If a cursor is provided, we know we're processing the AIL
+        * in lsn order, and future items to be spliced in will
+        * follow the last one being inserted now.  Update the
+        * cursor to point to that last item, now while we have a
+        * reliable pointer to it.
+        */
+       if (cur)
+               cur->item = list_entry(list->prev, struct xfs_log_item, li_ail);
 
        /*
-        * Our cursor points to the item we want to insert _after_, so we have
-        * to update the cursor to point to the end of the list we are splicing
-        * in so that it points to the correct location for the next splice.
-        * i.e. before the splice
-        *
-        *  lsn -> lsn -> lsn + x -> lsn + x ...
-        *          ^
-        *          | cursor points here
-        *
-        * After the splice we have:
-        *
-        *  lsn -> lsn -> lsn -> lsn -> .... -> lsn -> lsn + x -> lsn + x ...
-        *          ^                            ^
-        *          | cursor points here         | needs to move here
-        *
-        * So we set the cursor to the last item in the list to be spliced
-        * before we execute the splice, resulting in the cursor pointing to
-        * the correct item after the splice occurs.
+        * Finally perform the splice.  Unless the AIL was empty,
+        * lip points to the item in the AIL _after_ which the new
+        * items should go.  If lip is null the AIL was empty, so
+        * the new items go at the head of the AIL.
         */
-       if (cur) {
-               next_lip = list_entry(list->prev, struct xfs_log_item, li_ail);
-               cur->item = next_lip;
-       }
-       list_splice(list, &lip->li_ail);
+       if (lip)
+               list_splice(list, &lip->li_ail);
+       else
+               list_splice(list, &ailp->xa_ail);
 }
 
 /*
@@ -682,6 +671,7 @@ xfs_trans_ail_update_bulk(
        int                     i;
        LIST_HEAD(tmp);
 
+       ASSERT(nr_items > 0);           /* Not required, but true. */
        mlip = xfs_ail_min(ailp);
 
        for (i = 0; i < nr_items; i++) {
@@ -701,7 +691,8 @@ xfs_trans_ail_update_bulk(
                list_add(&lip->li_ail, &tmp);
        }
 
-       xfs_ail_splice(ailp, cur, &tmp, lsn);
+       if (!list_empty(&tmp))
+               xfs_ail_splice(ailp, cur, &tmp, lsn);
 
        if (!mlip_changed) {
                spin_unlock(&ailp->xa_lock);
index 15584fc..137e2b9 100644 (file)
@@ -54,7 +54,7 @@ xfs_trans_buf_item_match(
        list_for_each_entry(lidp, &tp->t_items, lid_trans) {
                blip = (struct xfs_buf_log_item *)lidp->lid_item;
                if (blip->bli_item.li_type == XFS_LI_BUF &&
-                   XFS_BUF_TARGET(blip->bli_buf) == target &&
+                   blip->bli_buf->b_target == target &&
                    XFS_BUF_ADDR(blip->bli_buf) == blkno &&
                    XFS_BUF_COUNT(blip->bli_buf) == len)
                        return blip->bli_buf;
@@ -80,7 +80,6 @@ _xfs_trans_bjoin(
 {
        struct xfs_buf_log_item *bip;
 
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(bp->b_transp == NULL);
 
        /*
@@ -194,7 +193,7 @@ xfs_trans_get_buf(xfs_trans_t       *tp,
                return NULL;
        }
 
-       ASSERT(!XFS_BUF_GETERROR(bp));
+       ASSERT(!bp->b_error);
 
        _xfs_trans_bjoin(tp, bp, 1);
        trace_xfs_trans_get_buf(bp->b_fspriv);
@@ -293,10 +292,10 @@ xfs_trans_read_buf(
                        return (flags & XBF_TRYLOCK) ?
                                        EAGAIN : XFS_ERROR(ENOMEM);
 
-               if (XFS_BUF_GETERROR(bp) != 0) {
+               if (bp->b_error) {
+                       error = bp->b_error;
                        xfs_ioerror_alert("xfs_trans_read_buf", mp,
                                          bp, blkno);
-                       error = XFS_BUF_GETERROR(bp);
                        xfs_buf_relse(bp);
                        return error;
                }
@@ -330,7 +329,7 @@ xfs_trans_read_buf(
                ASSERT(xfs_buf_islocked(bp));
                ASSERT(bp->b_transp == tp);
                ASSERT(bp->b_fspriv != NULL);
-               ASSERT((XFS_BUF_ISERROR(bp)) == 0);
+               ASSERT(!bp->b_error);
                if (!(XFS_BUF_ISDONE(bp))) {
                        trace_xfs_trans_read_buf_io(bp, _RET_IP_);
                        ASSERT(!XFS_BUF_ISASYNC(bp));
@@ -386,10 +385,9 @@ xfs_trans_read_buf(
                return (flags & XBF_TRYLOCK) ?
                                        0 : XFS_ERROR(ENOMEM);
        }
-       if (XFS_BUF_GETERROR(bp) != 0) {
-           XFS_BUF_SUPER_STALE(bp);
-               error = XFS_BUF_GETERROR(bp);
-
+       if (bp->b_error) {
+               error = bp->b_error;
+               XFS_BUF_SUPER_STALE(bp);
                xfs_ioerror_alert("xfs_trans_read_buf", mp,
                                  bp, blkno);
                if (tp->t_flags & XFS_TRANS_DIRTY)
@@ -430,7 +428,7 @@ shutdown_abort:
        if (XFS_BUF_ISSTALE(bp) && XFS_BUF_ISDELAYWRITE(bp))
                xfs_notice(mp, "about to pop assert, bp == 0x%p", bp);
 #endif
-       ASSERT((XFS_BUF_BFLAGS(bp) & (XBF_STALE|XBF_DELWRI)) !=
+       ASSERT((bp->b_flags & (XBF_STALE|XBF_DELWRI)) !=
                                     (XBF_STALE|XBF_DELWRI));
 
        trace_xfs_trans_read_buf_shut(bp, _RET_IP_);
@@ -581,7 +579,6 @@ xfs_trans_bhold(xfs_trans_t *tp,
 {
        xfs_buf_log_item_t      *bip = bp->b_fspriv;
 
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(bp->b_transp == tp);
        ASSERT(bip != NULL);
        ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
@@ -602,7 +599,6 @@ xfs_trans_bhold_release(xfs_trans_t *tp,
 {
        xfs_buf_log_item_t      *bip = bp->b_fspriv;
 
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(bp->b_transp == tp);
        ASSERT(bip != NULL);
        ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
@@ -631,7 +627,6 @@ xfs_trans_log_buf(xfs_trans_t       *tp,
 {
        xfs_buf_log_item_t      *bip = bp->b_fspriv;
 
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(bp->b_transp == tp);
        ASSERT(bip != NULL);
        ASSERT((first <= last) && (last < XFS_BUF_COUNT(bp)));
@@ -702,7 +697,6 @@ xfs_trans_binval(
 {
        xfs_buf_log_item_t      *bip = bp->b_fspriv;
 
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(bp->b_transp == tp);
        ASSERT(bip != NULL);
        ASSERT(atomic_read(&bip->bli_refcount) > 0);
@@ -774,7 +768,6 @@ xfs_trans_inode_buf(
 {
        xfs_buf_log_item_t      *bip = bp->b_fspriv;
 
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(bp->b_transp == tp);
        ASSERT(bip != NULL);
        ASSERT(atomic_read(&bip->bli_refcount) > 0);
@@ -798,7 +791,6 @@ xfs_trans_stale_inode_buf(
 {
        xfs_buf_log_item_t      *bip = bp->b_fspriv;
 
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(bp->b_transp == tp);
        ASSERT(bip != NULL);
        ASSERT(atomic_read(&bip->bli_refcount) > 0);
@@ -823,7 +815,6 @@ xfs_trans_inode_alloc_buf(
 {
        xfs_buf_log_item_t      *bip = bp->b_fspriv;
 
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(bp->b_transp == tp);
        ASSERT(bip != NULL);
        ASSERT(atomic_read(&bip->bli_refcount) > 0);
@@ -851,7 +842,6 @@ xfs_trans_dquot_buf(
 {
        xfs_buf_log_item_t      *bip = bp->b_fspriv;
 
-       ASSERT(XFS_BUF_ISBUSY(bp));
        ASSERT(bp->b_transp == tp);
        ASSERT(bip != NULL);
        ASSERT(type == XFS_BLF_UDQUOT_BUF ||
index 9322e13..51fc429 100644 (file)
@@ -83,7 +83,9 @@ xfs_readlink_bmap(
 
                bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt),
                                  XBF_LOCK | XBF_MAPPED | XBF_DONT_BLOCK);
-               error = XFS_BUF_GETERROR(bp);
+               if (!bp)
+                       return XFS_ERROR(ENOMEM);
+               error = bp->b_error;
                if (error) {
                        xfs_ioerror_alert("xfs_readlink",
                                  ip->i_mount, bp, XFS_BUF_ADDR(bp));
@@ -94,7 +96,7 @@ xfs_readlink_bmap(
                        byte_cnt = pathlen;
                pathlen -= byte_cnt;
 
-               memcpy(link, XFS_BUF_PTR(bp), byte_cnt);
+               memcpy(link, bp->b_addr, byte_cnt);
                xfs_buf_relse(bp);
        }
 
@@ -1648,13 +1650,13 @@ xfs_symlink(
                        byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
                        bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
                                               BTOBB(byte_cnt), 0);
-                       ASSERT(bp && !XFS_BUF_GETERROR(bp));
+                       ASSERT(!xfs_buf_geterror(bp));
                        if (pathlen < byte_cnt) {
                                byte_cnt = pathlen;
                        }
                        pathlen -= byte_cnt;
 
-                       memcpy(XFS_BUF_PTR(bp), cur_chunk, byte_cnt);
+                       memcpy(bp->b_addr, cur_chunk, byte_cnt);
                        cur_chunk += byte_cnt;
 
                        xfs_trans_log_buf(tp, bp, 0, byte_cnt - 1);
@@ -1999,7 +2001,7 @@ xfs_zero_remaining_bytes(
                                          mp, bp, XFS_BUF_ADDR(bp));
                        break;
                }
-               memset(XFS_BUF_PTR(bp) +
+               memset(bp->b_addr +
                        (offset - XFS_FSB_TO_B(mp, imap.br_startoff)),
                      0, lastoffset - offset + 1);
                XFS_BUF_UNDONE(bp);
index 3090471..e49c36d 100644 (file)
@@ -128,7 +128,7 @@ extern int is_dock_device(acpi_handle handle);
 extern int register_dock_notifier(struct notifier_block *nb);
 extern void unregister_dock_notifier(struct notifier_block *nb);
 extern int register_hotplug_dock_device(acpi_handle handle,
-                                       struct acpi_dock_ops *ops,
+                                       const struct acpi_dock_ops *ops,
                                        void *context);
 extern void unregister_hotplug_dock_device(acpi_handle handle);
 #else
index 2ed0a84..f554a93 100644 (file)
@@ -47,7 +47,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20110413
+#define ACPI_CA_VERSION                 0x20110623
 
 #include "actypes.h"
 #include "actbl.h"
@@ -69,6 +69,7 @@ extern u32 acpi_gbl_trace_flags;
 extern u32 acpi_gbl_enable_aml_debug_object;
 extern u8 acpi_gbl_copy_dsdt_locally;
 extern u8 acpi_gbl_truncate_io_addresses;
+extern u8 acpi_gbl_disable_auto_repair;
 
 extern u32 acpi_current_gpe_count;
 extern struct acpi_table_fadt acpi_gbl_FADT;
index e67b523..51a527d 100644 (file)
 
 extern int hest_disable;
 extern int erst_disable;
+#ifdef CONFIG_ACPI_APEI_GHES
+extern int ghes_disable;
+#else
+#define ghes_disable 1
+#endif
 
 #ifdef CONFIG_ACPI_APEI
 void __init acpi_hest_init(void);
index ba4928c..67055f1 100644 (file)
@@ -337,7 +337,7 @@ extern struct cpuidle_driver acpi_idle_driver;
 
 /* in processor_thermal.c */
 int acpi_processor_get_limit_info(struct acpi_processor *pr);
-extern struct thermal_cooling_device_ops processor_cooling_ops;
+extern const struct thermal_cooling_device_ops processor_cooling_ops;
 #ifdef CONFIG_CPU_FREQ
 void acpi_thermal_cpufreq_init(void);
 void acpi_thermal_cpufreq_exit(void);
index 33d12f8..44335e5 100644 (file)
@@ -205,6 +205,8 @@ struct drm_display_info {
        enum subpixel_order subpixel_order;
        u32 color_formats;
 
+       u8 cea_rev;
+
        char *raw_edid; /* if any */
 };
 
@@ -802,6 +804,7 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
 extern int drm_add_modes_noedid(struct drm_connector *connector,
                                int hdisplay, int vdisplay);
 
+extern int drm_edid_header_is_valid(const u8 *raw_edid);
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
                                           int hsize, int vsize, int fresh);
index c4d6dbf..28c0d11 100644 (file)
@@ -237,7 +237,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_GET_APERTURE        DRM_IOR  (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
 #define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_i915_get_pipe_from_crtc_id)
 #define DRM_IOCTL_I915_GEM_MADVISE     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
-#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE       DRM_IOW(DRM_COMMAND_BASE + DRM_IOCTL_I915_OVERLAY_ATTRS, struct drm_intel_overlay_put_image)
+#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE       DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image)
 #define DRM_IOCTL_I915_OVERLAY_ATTRS   DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
index 1deb2a7..6001b4d 100644 (file)
@@ -238,7 +238,6 @@ extern int acpi_paddr_to_node(u64 start_addr, u64 size);
 extern int pnpacpi_disabled;
 
 #define PXM_INVAL      (-1)
-#define NID_INVAL      (-1)
 
 int acpi_check_resource_conflict(const struct resource *res);
 
@@ -280,6 +279,8 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
 #define OSC_SB_CPUHP_OST_SUPPORT       8
 #define OSC_SB_APEI_SUPPORT            16
 
+extern bool osc_sb_apei_support_acked;
+
 /* PCI defined _OSC bits */
 /* _OSC DW1 Definition (OS Support Fields) */
 #define OSC_EXT_PCI_CONFIG_SUPPORT             1
index 8414de2..544abdb 100644 (file)
@@ -51,5 +51,8 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
 
 extern void cper_print_aer(const char *prefix, int cper_severity,
                           struct aer_capability_regs *aer);
+extern int cper_severity_to_aer(int cper_severity);
+extern void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
+                             int severity);
 #endif //_AER_H_
 
index 3111385..e6e28f3 100644 (file)
@@ -172,8 +172,11 @@ struct pl08x_dma_chan {
        int phychan_hold;
        struct tasklet_struct tasklet;
        char *name;
-       struct pl08x_channel_data *cd;
-       dma_addr_t runtime_addr;
+       const struct pl08x_channel_data *cd;
+       dma_addr_t src_addr;
+       dma_addr_t dst_addr;
+       u32 src_cctl;
+       u32 dst_cctl;
        enum dma_data_direction runtime_direction;
        dma_cookie_t lc;
        struct list_head pend_list;
@@ -202,7 +205,7 @@ struct pl08x_dma_chan {
  * @mem_buses: buses which memory can be accessed from: PL08X_AHB1 | PL08X_AHB2
  */
 struct pl08x_platform_data {
-       struct pl08x_channel_data *slave_channels;
+       const struct pl08x_channel_data *slave_channels;
        unsigned int num_slave_channels;
        struct pl08x_channel_data memcpy_channel;
        int (*get_signal)(struct pl08x_dma_chan *);
index d34c187..f57c368 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/types.h>
 #include <asm/byteorder.h>
+#include <linux/socket.h>
 
 /*
  * AppleTalk networking structures
@@ -28,7 +29,7 @@ struct atalk_addr {
 };
 
 struct sockaddr_at {
-       sa_family_t       sat_family;
+       __kernel_sa_family_t sat_family;
        __u8              sat_port;
        struct atalk_addr sat_addr;
        char              sat_zero[8];
index 56c11f0..74c89a4 100644 (file)
@@ -47,7 +47,7 @@ typedef struct {
 } ax25_address;
 
 struct sockaddr_ax25 {
-       sa_family_t     sax25_family;
+       __kernel_sa_family_t sax25_family;
        ax25_address    sax25_call;
        int             sax25_ndigis;
        /* Digipeater ax25_address sets follow */
index 3bac44c..7ad6345 100644 (file)
@@ -146,6 +146,7 @@ extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
 extern void bitmap_copy_le(void *dst, const unsigned long *src, int nbits);
 extern int bitmap_ord_to_pos(const unsigned long *bitmap, int n, int bits);
 
+#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
 #define BITMAP_LAST_WORD_MASK(nbits)                                   \
 (                                                                      \
        ((nbits) % BITS_PER_LONG) ?                                     \
index d9cb19b..3f3bac6 100644 (file)
@@ -9,12 +9,7 @@
 #define _LINUX_CAIF_SOCKET_H
 
 #include <linux/types.h>
-
-#ifdef __KERNEL__
 #include <linux/socket.h>
-#else
-#include <sys/socket.h>
-#endif
 
 /**
  * enum caif_link_selector -    Physical Link Selection.
@@ -144,7 +139,7 @@ enum caif_debug_service {
  * CAIF Channel. It defines the service to connect to on the modem.
  */
 struct sockaddr_caif {
-       sa_family_t  family;
+       __kernel_sa_family_t  family;
        union {
                struct {
                        __u8  type;             /* type: enum caif_at_type */
index d183333..bb047dc 100644 (file)
@@ -78,7 +78,7 @@ struct can_frame {
  * @can_addr:    protocol specific address information
  */
 struct sockaddr_can {
-       sa_family_t can_family;
+       __kernel_sa_family_t can_family;
        int         can_ifindex;
        union {
                /* transport protocol class address information (e.g. ISOTP) */
index 1432b27..e96154d 100644 (file)
@@ -15,6 +15,7 @@
 #define CAN_BCM_H
 
 #include <linux/types.h>
+#include <linux/can.h>
 
 /**
  * struct bcm_msg_head - head of messages to/from the broadcast manager
index 36719ea..b51629e 100644 (file)
@@ -122,6 +122,8 @@ struct cpuidle_driver {
 };
 
 #ifdef CONFIG_CPU_IDLE
+extern void disable_cpuidle(void);
+extern int cpuidle_idle_call(void);
 
 extern int cpuidle_register_driver(struct cpuidle_driver *drv);
 struct cpuidle_driver *cpuidle_get_driver(void);
@@ -135,6 +137,8 @@ extern int cpuidle_enable_device(struct cpuidle_device *dev);
 extern void cpuidle_disable_device(struct cpuidle_device *dev);
 
 #else
+static inline void disable_cpuidle(void) { }
+static inline int cpuidle_idle_call(void) { return -ENODEV; }
 
 static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
 {return -ENODEV; }
index 48e82af..4030896 100644 (file)
@@ -265,10 +265,11 @@ static inline void put_cred(const struct cred *_cred)
 /**
  * current_cred - Access the current task's subjective credentials
  *
- * Access the subjective credentials of the current task.
+ * Access the subjective credentials of the current task.  RCU-safe,
+ * since nobody else can modify it.
  */
 #define current_cred() \
-       (current->cred)
+       rcu_dereference_protected(current->cred, 1)
 
 /**
  * __task_cred - Access a task's objective credentials
@@ -306,8 +307,8 @@ static inline void put_cred(const struct cred *_cred)
 #define get_current_user()                             \
 ({                                                     \
        struct user_struct *__u;                        \
-       struct cred *__cred;                            \
-       __cred = (struct cred *) current_cred();        \
+       const struct cred *__cred;                      \
+       __cred = current_cred();                        \
        __u = get_uid(__cred->user);                    \
        __u;                                            \
 })
@@ -321,8 +322,8 @@ static inline void put_cred(const struct cred *_cred)
 #define get_current_groups()                           \
 ({                                                     \
        struct group_info *__groups;                    \
-       struct cred *__cred;                            \
-       __cred = (struct cred *) current_cred();        \
+       const struct cred *__cred;                      \
+       __cred = current_cred();                        \
        __groups = get_group_info(__cred->group_info);  \
        __groups;                                       \
 })
@@ -341,7 +342,7 @@ static inline void put_cred(const struct cred *_cred)
 
 #define current_cred_xxx(xxx)                  \
 ({                                             \
-       current->cred->xxx;                     \
+       current_cred()->xxx;                    \
 })
 
 #define current_uid()          (current_cred_xxx(uid))
index ec78a4b..2cd9f1c 100644 (file)
@@ -3,11 +3,16 @@
 
 #define SHA_DIGEST_WORDS 5
 #define SHA_MESSAGE_BYTES (512 /*bits*/ / 8)
-#define SHA_WORKSPACE_WORDS 80
+#define SHA_WORKSPACE_WORDS 16
 
 void sha_init(__u32 *buf);
 void sha_transform(__u32 *digest, const char *data, __u32 *W);
 
+#define MD5_DIGEST_WORDS 4
+#define MD5_MESSAGE_BYTES 64
+
+void md5_transform(__u32 *hash, __u32 const *in);
+
 __u32 half_md4_transform(__u32 buf[4], __u32 const in[8]);
 
 #endif
index d37d2a7..62157c0 100644 (file)
@@ -180,12 +180,12 @@ struct dentry_operations {
  */
 
 /* d_flags entries */
-#define DCACHE_AUTOFS_PENDING 0x0001    /* autofs: "under construction" */
-#define DCACHE_NFSFS_RENAMED  0x0002
-     /* this dentry has been "silly renamed" and has to be deleted on the last
-      * dput() */
+#define DCACHE_OP_HASH         0x0001
+#define DCACHE_OP_COMPARE      0x0002
+#define DCACHE_OP_REVALIDATE   0x0004
+#define DCACHE_OP_DELETE       0x0008
 
-#define        DCACHE_DISCONNECTED     0x0004
+#define        DCACHE_DISCONNECTED     0x0010
      /* This dentry is possibly not currently connected to the dcache tree, in
       * which case its parent will either be itself, or will have this flag as
       * well.  nfsd will not use a dentry with this bit set, but will first
@@ -196,22 +196,18 @@ struct dentry_operations {
       * dentry into place and return that dentry rather than the passed one,
       * typically using d_splice_alias. */
 
-#define DCACHE_REFERENCED      0x0008  /* Recently used, don't discard. */
-#define DCACHE_RCUACCESS       0x0010  /* Entry has ever been RCU-visible */
-#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020
-     /* Parent inode is watched by inotify */
-
-#define DCACHE_COOKIE          0x0040  /* For use by dcookie subsystem */
-#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080
-     /* Parent inode is watched by some fsnotify listener */
+#define DCACHE_REFERENCED      0x0020  /* Recently used, don't discard. */
+#define DCACHE_RCUACCESS       0x0040  /* Entry has ever been RCU-visible */
 
 #define DCACHE_CANT_MOUNT      0x0100
 #define DCACHE_GENOCIDE                0x0200
 
-#define DCACHE_OP_HASH         0x1000
-#define DCACHE_OP_COMPARE      0x2000
-#define DCACHE_OP_REVALIDATE   0x4000
-#define DCACHE_OP_DELETE       0x8000
+#define DCACHE_NFSFS_RENAMED   0x1000
+     /* this dentry has been "silly renamed" and has to be deleted on the last
+      * dput() */
+#define DCACHE_COOKIE          0x2000  /* For use by dcookie subsystem */
+#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x4000
+     /* Parent inode is watched by some fsnotify listener */
 
 #define DCACHE_MOUNTED         0x10000 /* is a mountpoint */
 #define DCACHE_NEED_AUTOMOUNT  0x20000 /* handle automount on this dir */
index 4427e04..3fa1f3d 100644 (file)
@@ -208,6 +208,49 @@ struct dm_target_callbacks {
 int dm_register_target(struct target_type *t);
 void dm_unregister_target(struct target_type *t);
 
+/*
+ * Target argument parsing.
+ */
+struct dm_arg_set {
+       unsigned argc;
+       char **argv;
+};
+
+/*
+ * The minimum and maximum value of a numeric argument, together with
+ * the error message to use if the number is found to be outside that range.
+ */
+struct dm_arg {
+       unsigned min;
+       unsigned max;
+       char *error;
+};
+
+/*
+ * Validate the next argument, either returning it as *value or, if invalid,
+ * returning -EINVAL and setting *error.
+ */
+int dm_read_arg(struct dm_arg *arg, struct dm_arg_set *arg_set,
+               unsigned *value, char **error);
+
+/*
+ * Process the next argument as the start of a group containing between
+ * arg->min and arg->max further arguments. Either return the size as
+ * *num_args or, if invalid, return -EINVAL and set *error.
+ */
+int dm_read_arg_group(struct dm_arg *arg, struct dm_arg_set *arg_set,
+                     unsigned *num_args, char **error);
+
+/*
+ * Return the current argument and shift to the next.
+ */
+const char *dm_shift_arg(struct dm_arg_set *as);
+
+/*
+ * Move through num_args arguments.
+ */
+void dm_consume_args(struct dm_arg_set *as, unsigned num_args);
+
 /*-----------------------------------------------------------------
  * Functions for creating and manipulating mapped devices.
  * Drop the reference with dm_put when you finish with the object.
index 3708455..0cb8eff 100644 (file)
@@ -267,9 +267,9 @@ enum {
 #define DM_DEV_SET_GEOMETRY    _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR       4
-#define DM_VERSION_MINOR       20
+#define DM_VERSION_MINOR       21
 #define DM_VERSION_PATCHLEVEL  0
-#define DM_VERSION_EXTRA       "-ioctl (2011-02-02)"
+#define DM_VERSION_EXTRA       "-ioctl (2011-07-06)"
 
 /* Status bits */
 #define DM_READONLY_FLAG       (1 << 0) /* In/Out */
index 298d587..5e54458 100644 (file)
@@ -42,5 +42,20 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
                   unsigned num_dests, struct dm_io_region *dests,
                   unsigned flags, dm_kcopyd_notify_fn fn, void *context);
 
+/*
+ * Prepare a callback and submit it via the kcopyd thread.
+ *
+ * dm_kcopyd_prepare_callback allocates a callback structure and returns it.
+ * It must not be called from interrupt context.
+ * The returned value should be passed into dm_kcopyd_do_callback.
+ *
+ * dm_kcopyd_do_callback submits the callback.
+ * It may be called from interrupt context.
+ * The callback is issued from the kcopyd thread.
+ */
+void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc,
+                                dm_kcopyd_notify_fn fn, void *context);
+void dm_kcopyd_do_callback(void *job, int read_err, unsigned long write_err);
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_DM_KCOPYD_H */
index fec66bd..d47bccd 100644 (file)
@@ -67,7 +67,7 @@ typedef struct audio_status {
 
 
 typedef
-struct audio_karaoke{  /* if Vocal1 or Vocal2 are non-zero, they get mixed  */
+struct audio_karaoke {  /* if Vocal1 or Vocal2 are non-zero, they get mixed  */
        int vocal1;    /* into left and right t at 70% each */
        int vocal2;    /* if both, Vocal1 and Vocal2 are non-zero, Vocal1 gets*/
        int melody;    /* mixed into the left channel and */
index ec25726..2362a0b 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/rtc.h>
 #include <linux/ioport.h>
 #include <linux/pfn.h>
+#include <linux/pstore.h>
 
 #include <asm/page.h>
 #include <asm/system.h>
@@ -232,6 +233,9 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
 #define UV_SYSTEM_TABLE_GUID \
     EFI_GUID(  0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 )
 
+#define LINUX_EFI_CRASH_GUID \
+    EFI_GUID(  0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 )
+
 typedef struct {
        efi_guid_t guid;
        unsigned long table;
@@ -458,6 +462,8 @@ struct efivars {
        struct kset *kset;
        struct bin_attribute *new_var, *del_var;
        const struct efivar_operations *ops;
+       struct efivar_entry *walk_entry;
+       struct pstore_info efi_pstore_info;
 };
 
 int register_efivars(struct efivars *efivars,
index c6e427a..3829712 100644 (file)
@@ -117,99 +117,101 @@ struct ethtool_eeprom {
        __u8    data[0];
 };
 
-/* for configuring coalescing parameters of chip */
+/**
+ * struct ethtool_coalesce - coalescing parameters for IRQs and stats updates
+ * @cmd: ETHTOOL_{G,S}COALESCE
+ * @rx_coalesce_usecs: How many usecs to delay an RX interrupt after
+ *     a packet arrives.
+ * @rx_max_coalesced_frames: Maximum number of packets to receive
+ *     before an RX interrupt.
+ * @rx_coalesce_usecs_irq: Same as @rx_coalesce_usecs, except that
+ *     this value applies while an IRQ is being serviced by the host.
+ * @rx_max_coalesced_frames_irq: Same as @rx_max_coalesced_frames,
+ *     except that this value applies while an IRQ is being serviced
+ *     by the host.
+ * @tx_coalesce_usecs: How many usecs to delay a TX interrupt after
+ *     a packet is sent.
+ * @tx_max_coalesced_frames: Maximum number of packets to be sent
+ *     before a TX interrupt.
+ * @tx_coalesce_usecs_irq: Same as @tx_coalesce_usecs, except that
+ *     this value applies while an IRQ is being serviced by the host.
+ * @tx_max_coalesced_frames_irq: Same as @tx_max_coalesced_frames,
+ *     except that this value applies while an IRQ is being serviced
+ *     by the host.
+ * @stats_block_coalesce_usecs: How many usecs to delay in-memory
+ *     statistics block updates.  Some drivers do not have an
+ *     in-memory statistic block, and in such cases this value is
+ *     ignored.  This value must not be zero.
+ * @use_adaptive_rx_coalesce: Enable adaptive RX coalescing.
+ * @use_adaptive_tx_coalesce: Enable adaptive TX coalescing.
+ * @pkt_rate_low: Threshold for low packet rate (packets per second).
+ * @rx_coalesce_usecs_low: How many usecs to delay an RX interrupt after
+ *     a packet arrives, when the packet rate is below @pkt_rate_low.
+ * @rx_max_coalesced_frames_low: Maximum number of packets to be received
+ *     before an RX interrupt, when the packet rate is below @pkt_rate_low.
+ * @tx_coalesce_usecs_low: How many usecs to delay a TX interrupt after
+ *     a packet is sent, when the packet rate is below @pkt_rate_low.
+ * @tx_max_coalesced_frames_low: Maximum nuumber of packets to be sent before
+ *     a TX interrupt, when the packet rate is below @pkt_rate_low.
+ * @pkt_rate_high: Threshold for high packet rate (packets per second).
+ * @rx_coalesce_usecs_high: How many usecs to delay an RX interrupt after
+ *     a packet arrives, when the packet rate is above @pkt_rate_high.
+ * @rx_max_coalesced_frames_high: Maximum number of packets to be received
+ *     before an RX interrupt, when the packet rate is above @pkt_rate_high.
+ * @tx_coalesce_usecs_high: How many usecs to delay a TX interrupt after
+ *     a packet is sent, when the packet rate is above @pkt_rate_high.
+ * @tx_max_coalesced_frames_high: Maximum number of packets to be sent before
+ *     a TX interrupt, when the packet rate is above @pkt_rate_high.
+ * @rate_sample_interval: How often to do adaptive coalescing packet rate
+ *     sampling, measured in seconds.  Must not be zero.
+ *
+ * Each pair of (usecs, max_frames) fields specifies this exit
+ * condition for interrupt coalescing:
+ *     (usecs > 0 && time_since_first_completion >= usecs) ||
+ *     (max_frames > 0 && completed_frames >= max_frames)
+ * It is illegal to set both usecs and max_frames to zero as this
+ * would cause interrupts to never be generated.  To disable
+ * coalescing, set usecs = 0 and max_frames = 1.
+ *
+ * Some implementations ignore the value of max_frames and use the
+ * condition:
+ *     time_since_first_completion >= usecs
+ * This is deprecated.  Drivers for hardware that does not support
+ * counting completions should validate that max_frames == !rx_usecs.
+ *
+ * Adaptive RX/TX coalescing is an algorithm implemented by some
+ * drivers to improve latency under low packet rates and improve
+ * throughput under high packet rates.  Some drivers only implement
+ * one of RX or TX adaptive coalescing.  Anything not implemented by
+ * the driver causes these values to be silently ignored.
+ *
+ * When the packet rate is below @pkt_rate_high but above
+ * @pkt_rate_low (both measured in packets per second) the
+ * normal {rx,tx}_* coalescing parameters are used.
+ */
 struct ethtool_coalesce {
-       __u32   cmd;    /* ETHTOOL_{G,S}COALESCE */
-
-       /* How many usecs to delay an RX interrupt after
-        * a packet arrives.  If 0, only rx_max_coalesced_frames
-        * is used.
-        */
+       __u32   cmd;
        __u32   rx_coalesce_usecs;
-
-       /* How many packets to delay an RX interrupt after
-        * a packet arrives.  If 0, only rx_coalesce_usecs is
-        * used.  It is illegal to set both usecs and max frames
-        * to zero as this would cause RX interrupts to never be
-        * generated.
-        */
        __u32   rx_max_coalesced_frames;
-
-       /* Same as above two parameters, except that these values
-        * apply while an IRQ is being serviced by the host.  Not
-        * all cards support this feature and the values are ignored
-        * in that case.
-        */
        __u32   rx_coalesce_usecs_irq;
        __u32   rx_max_coalesced_frames_irq;
-
-       /* How many usecs to delay a TX interrupt after
-        * a packet is sent.  If 0, only tx_max_coalesced_frames
-        * is used.
-        */
        __u32   tx_coalesce_usecs;
-
-       /* How many packets to delay a TX interrupt after
-        * a packet is sent.  If 0, only tx_coalesce_usecs is
-        * used.  It is illegal to set both usecs and max frames
-        * to zero as this would cause TX interrupts to never be
-        * generated.
-        */
        __u32   tx_max_coalesced_frames;
-
-       /* Same as above two parameters, except that these values
-        * apply while an IRQ is being serviced by the host.  Not
-        * all cards support this feature and the values are ignored
-        * in that case.
-        */
        __u32   tx_coalesce_usecs_irq;
        __u32   tx_max_coalesced_frames_irq;
-
-       /* How many usecs to delay in-memory statistics
-        * block updates.  Some drivers do not have an in-memory
-        * statistic block, and in such cases this value is ignored.
-        * This value must not be zero.
-        */
        __u32   stats_block_coalesce_usecs;
-
-       /* Adaptive RX/TX coalescing is an algorithm implemented by
-        * some drivers to improve latency under low packet rates and
-        * improve throughput under high packet rates.  Some drivers
-        * only implement one of RX or TX adaptive coalescing.  Anything
-        * not implemented by the driver causes these values to be
-        * silently ignored.
-        */
        __u32   use_adaptive_rx_coalesce;
        __u32   use_adaptive_tx_coalesce;
-
-       /* When the packet rate (measured in packets per second)
-        * is below pkt_rate_low, the {rx,tx}_*_low parameters are
-        * used.
-        */
        __u32   pkt_rate_low;
        __u32   rx_coalesce_usecs_low;
        __u32   rx_max_coalesced_frames_low;
        __u32   tx_coalesce_usecs_low;
        __u32   tx_max_coalesced_frames_low;
-
-       /* When the packet rate is below pkt_rate_high but above
-        * pkt_rate_low (both measured in packets per second) the
-        * normal {rx,tx}_* coalescing parameters are used.
-        */
-
-       /* When the packet rate is (measured in packets per second)
-        * is above pkt_rate_high, the {rx,tx}_*_high parameters are
-        * used.
-        */
        __u32   pkt_rate_high;
        __u32   rx_coalesce_usecs_high;
        __u32   rx_max_coalesced_frames_high;
        __u32   tx_coalesce_usecs_high;
        __u32   tx_max_coalesced_frames_high;
-
-       /* How often to do adaptive coalescing packet rate sampling,
-        * measured in seconds.  Must not be zero.
-        */
        __u32   rate_sample_interval;
 };
 
index 3ff060a..c6f996f 100644 (file)
@@ -25,10 +25,6 @@ struct fault_attr {
        unsigned long reject_end;
 
        unsigned long count;
-
-#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
-       struct dentry *dir;
-#endif
 };
 
 #define FAULT_ATTR_INITIALIZER {                               \
@@ -45,19 +41,15 @@ bool should_fail(struct fault_attr *attr, ssize_t size);
 
 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
 
-int init_fault_attr_dentries(struct fault_attr *attr, const char *name);
-void cleanup_fault_attr_dentries(struct fault_attr *attr);
+struct dentry *fault_create_debugfs_attr(const char *name,
+                       struct dentry *parent, struct fault_attr *attr);
 
 #else /* CONFIG_FAULT_INJECTION_DEBUG_FS */
 
-static inline int init_fault_attr_dentries(struct fault_attr *attr,
-                                         const char *name)
-{
-       return -ENODEV;
-}
-
-static inline void cleanup_fault_attr_dentries(struct fault_attr *attr)
+static inline struct dentry *fault_create_debugfs_attr(const char *name,
+                       struct dentry *parent, struct fault_attr *attr)
 {
+       return ERR_PTR(-ENODEV);
 }
 
 #endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
index f23bcb7..178cdb4 100644 (file)
@@ -738,22 +738,54 @@ static inline int mapping_writably_mapped(struct address_space *mapping)
 struct posix_acl;
 #define ACL_NOT_CACHED ((void *)(-1))
 
+#define IOP_FASTPERM   0x0001
+#define IOP_LOOKUP     0x0002
+#define IOP_NOFOLLOW   0x0004
+
+/*
+ * Keep mostly read-only and often accessed (especially for
+ * the RCU path lookup and 'stat' data) fields at the beginning
+ * of the 'struct inode'
+ */
 struct inode {
-       /* RCU path lookup touches following: */
        umode_t                 i_mode;
+       unsigned short          i_opflags;
        uid_t                   i_uid;
        gid_t                   i_gid;
+       unsigned int            i_flags;
+
+#ifdef CONFIG_FS_POSIX_ACL
+       struct posix_acl        *i_acl;
+       struct posix_acl        *i_default_acl;
+#endif
+
        const struct inode_operations   *i_op;
        struct super_block      *i_sb;
+       struct address_space    *i_mapping;
 
-       spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i_size */
-       unsigned int            i_flags;
-       unsigned long           i_state;
 #ifdef CONFIG_SECURITY
        void                    *i_security;
 #endif
-       struct mutex            i_mutex;
 
+       /* Stat data, not accessed from path walking */
+       unsigned long           i_ino;
+       unsigned int            i_nlink;
+       dev_t                   i_rdev;
+       loff_t                  i_size;
+       struct timespec         i_atime;
+       struct timespec         i_mtime;
+       struct timespec         i_ctime;
+       unsigned int            i_blkbits;
+       blkcnt_t                i_blocks;
+
+#ifdef __NEED_I_SIZE_ORDERED
+       seqcount_t              i_size_seqcount;
+#endif
+
+       /* Misc */
+       unsigned long           i_state;
+       spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i_size */
+       struct mutex            i_mutex;
 
        unsigned long           dirtied_when;   /* jiffies of first dirtying */
 
@@ -765,25 +797,12 @@ struct inode {
                struct list_head        i_dentry;
                struct rcu_head         i_rcu;
        };
-       unsigned long           i_ino;
        atomic_t                i_count;
-       unsigned int            i_nlink;
-       dev_t                   i_rdev;
-       unsigned int            i_blkbits;
        u64                     i_version;
-       loff_t                  i_size;
-#ifdef __NEED_I_SIZE_ORDERED
-       seqcount_t              i_size_seqcount;
-#endif
-       struct timespec         i_atime;
-       struct timespec         i_mtime;
-       struct timespec         i_ctime;
-       blkcnt_t                i_blocks;
        unsigned short          i_bytes;
        atomic_t                i_dio_count;
        const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */
        struct file_lock        *i_flock;
-       struct address_space    *i_mapping;
        struct address_space    i_data;
 #ifdef CONFIG_QUOTA
        struct dquot            *i_dquot[MAXQUOTAS];
@@ -806,10 +825,6 @@ struct inode {
        atomic_t                i_readcount; /* struct files open RO */
 #endif
        atomic_t                i_writecount;
-#ifdef CONFIG_FS_POSIX_ACL
-       struct posix_acl        *i_acl;
-       struct posix_acl        *i_default_acl;
-#endif
        void                    *i_private; /* fs or device private pointer */
 };
 
@@ -2317,11 +2332,18 @@ extern int should_remove_suid(struct dentry *);
 extern int file_remove_suid(struct file *);
 
 extern void __insert_inode_hash(struct inode *, unsigned long hashval);
-extern void remove_inode_hash(struct inode *);
 static inline void insert_inode_hash(struct inode *inode)
 {
        __insert_inode_hash(inode, inode->i_ino);
 }
+
+extern void __remove_inode_hash(struct inode *);
+static inline void remove_inode_hash(struct inode *inode)
+{
+       if (!inode_unhashed(inode))
+               __remove_inode_hash(inode);
+}
+
 extern void inode_sb_list_add(struct inode *inode);
 
 #ifdef CONFIG_BLOCK
index 5bbebda..5e98eeb 100644 (file)
@@ -1,8 +1,26 @@
 /*
- * Basic general purpose allocator for managing special purpose memory
- * not managed by the regular kmalloc/kfree interface.
- * Uses for this includes on-device special memory, uncached memory
- * etc.
+ * Basic general purpose allocator for managing special purpose
+ * memory, for example, memory that is not managed by the regular
+ * kmalloc/kfree interface.  Uses for this includes on-device special
+ * memory, uncached memory etc.
+ *
+ * It is safe to use the allocator in NMI handlers and other special
+ * unblockable contexts that could otherwise deadlock on locks.  This
+ * is implemented by using atomic operations and retries on any
+ * conflicts.  The disadvantage is that there may be livelocks in
+ * extreme cases.  For better scalability, one allocator can be used
+ * for each CPU.
+ *
+ * The lockless operation only works if there is enough memory
+ * available.  If new memory is added to the pool a lock has to be
+ * still taken.  So any user relying on locklessness has to ensure
+ * that sufficient memory is preallocated.
+ *
+ * The basic atomic operation of this allocator is cmpxchg on long.
+ * On architectures that don't have NMI-safe cmpxchg implementation,
+ * the allocator can NOT be used in NMI handler.  So code uses the
+ * allocator in NMI handler should depend on
+ * CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG.
  *
  * This source code is licensed under the GNU General Public License,
  * Version 2.  See the file COPYING for more details.
@@ -15,7 +33,7 @@
  *  General purpose special memory pool descriptor.
  */
 struct gen_pool {
-       rwlock_t lock;
+       spinlock_t lock;
        struct list_head chunks;        /* list of chunks in this pool */
        int min_alloc_order;            /* minimum allocation order */
 };
@@ -24,8 +42,8 @@ struct gen_pool {
  *  General purpose special memory pool chunk descriptor.
  */
 struct gen_pool_chunk {
-       spinlock_t lock;
        struct list_head next_chunk;    /* next chunk in pool */
+       atomic_t avail;
        phys_addr_t phys_addr;          /* physical starting address of memory chunk */
        unsigned long start_addr;       /* starting address of memory chunk */
        unsigned long end_addr;         /* ending address of memory chunk */
@@ -56,4 +74,8 @@ static inline int gen_pool_add(struct gen_pool *pool, unsigned long addr,
 extern void gen_pool_destroy(struct gen_pool *);
 extern unsigned long gen_pool_alloc(struct gen_pool *, size_t);
 extern void gen_pool_free(struct gen_pool *, unsigned long, size_t);
+extern void gen_pool_for_each_chunk(struct gen_pool *,
+       void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *);
+extern size_t gen_pool_avail(struct gen_pool *);
+extern size_t gen_pool_size(struct gen_pool *);
 #endif /* __GENALLOC_H__ */
index cb40892..3a76faf 100644 (file)
@@ -92,7 +92,7 @@ struct vm_area_struct;
  */
 #define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK)
 
-#define __GFP_BITS_SHIFT 23    /* Room for 23 __GFP_FOO bits */
+#define __GFP_BITS_SHIFT 24    /* Room for N __GFP_FOO bits */
 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
 
 /* This equals 0, but use constants in case they ever change */
index 13a801f..255491c 100644 (file)
@@ -146,6 +146,10 @@ void ida_remove(struct ida *ida, int id);
 void ida_destroy(struct ida *ida);
 void ida_init(struct ida *ida);
 
+int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
+                  gfp_t gfp_mask);
+void ida_simple_remove(struct ida *ida, unsigned int id);
+
 void __init idr_init_cache(void);
 
 #endif /* __IDR_H__ */
index 03489ca..db20bd4 100644 (file)
@@ -78,6 +78,7 @@
                                         * datapath port */
 #define IFF_TX_SKB_SHARING     0x10000 /* The interface supports sharing
                                         * skbs on transmit */
+#define IFF_UNICAST_FLT        0x20000         /* Supports unicast filtering   */
 
 #define IF_GET_IFACE   0x0001          /* for querying only */
 #define IF_GET_PROTO   0x0002
index a3d99ff..c63bbd7 100644 (file)
@@ -88,6 +88,7 @@
 #define ETH_P_QINQ2    0x9200          /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_QINQ3    0x9300          /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_EDSA     0xDADA          /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_AF_IUCV   0xFBFB         /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
 
 /*
  *     Non DIX types. Won't clash for 1500 types.
index c148606..5e76988 100644 (file)
@@ -61,6 +61,17 @@ struct tpacket_stats {
        unsigned int    tp_drops;
 };
 
+struct tpacket_stats_v3 {
+       unsigned int    tp_packets;
+       unsigned int    tp_drops;
+       unsigned int    tp_freeze_q_cnt;
+};
+
+union tpacket_stats_u {
+       struct tpacket_stats stats1;
+       struct tpacket_stats_v3 stats3;
+};
+
 struct tpacket_auxdata {
        __u32           tp_status;
        __u32           tp_len;
@@ -78,6 +89,7 @@ struct tpacket_auxdata {
 #define TP_STATUS_LOSING       0x4
 #define TP_STATUS_CSUMNOTREADY 0x8
 #define TP_STATUS_VLAN_VALID   0x10 /* auxdata has valid tp_vlan_tci */
+#define TP_STATUS_BLK_TMO      0x20
 
 /* Tx ring - header status */
 #define TP_STATUS_AVAILABLE    0x0
@@ -85,6 +97,9 @@ struct tpacket_auxdata {
 #define TP_STATUS_SENDING      0x2
 #define TP_STATUS_WRONG_FORMAT 0x4
 
+/* Rx ring - feature request bits */
+#define TP_FT_REQ_FILL_RXHASH  0x1
+
 struct tpacket_hdr {
        unsigned long   tp_status;
        unsigned int    tp_len;
@@ -111,11 +126,100 @@ struct tpacket2_hdr {
        __u16           tp_padding;
 };
 
+struct tpacket_hdr_variant1 {
+       __u32   tp_rxhash;
+       __u32   tp_vlan_tci;
+};
+
+struct tpacket3_hdr {
+       __u32           tp_next_offset;
+       __u32           tp_sec;
+       __u32           tp_nsec;
+       __u32           tp_snaplen;
+       __u32           tp_len;
+       __u32           tp_status;
+       __u16           tp_mac;
+       __u16           tp_net;
+       /* pkt_hdr variants */
+       union {
+               struct tpacket_hdr_variant1 hv1;
+       };
+};
+
+struct tpacket_bd_ts {
+       unsigned int ts_sec;
+       union {
+               unsigned int ts_usec;
+               unsigned int ts_nsec;
+       };
+};
+
+struct tpacket_hdr_v1 {
+       __u32   block_status;
+       __u32   num_pkts;
+       __u32   offset_to_first_pkt;
+
+       /* Number of valid bytes (including padding)
+        * blk_len <= tp_block_size
+        */
+       __u32   blk_len;
+
+       /*
+        * Quite a few uses of sequence number:
+        * 1. Make sure cache flush etc worked.
+        *    Well, one can argue - why not use the increasing ts below?
+        *    But look at 2. below first.
+        * 2. When you pass around blocks to other user space decoders,
+        *    you can see which blk[s] is[are] outstanding etc.
+        * 3. Validate kernel code.
+        */
+       aligned_u64     seq_num;
+
+       /*
+        * ts_last_pkt:
+        *
+        * Case 1.      Block has 'N'(N >=1) packets and TMO'd(timed out)
+        *              ts_last_pkt == 'time-stamp of last packet' and NOT the
+        *              time when the timer fired and the block was closed.
+        *              By providing the ts of the last packet we can absolutely
+        *              guarantee that time-stamp wise, the first packet in the
+        *              next block will never precede the last packet of the
+        *              previous block.
+        * Case 2.      Block has zero packets and TMO'd
+        *              ts_last_pkt = time when the timer fired and the block
+        *              was closed.
+        * Case 3.      Block has 'N' packets and NO TMO.
+        *              ts_last_pkt = time-stamp of the last pkt in the block.
+        *
+        * ts_first_pkt:
+        *              Is always the time-stamp when the block was opened.
+        *              Case a) ZERO packets
+        *                      No packets to deal with but atleast you know the
+        *                      time-interval of this block.
+        *              Case b) Non-zero packets
+        *                      Use the ts of the first packet in the block.
+        *
+        */
+       struct tpacket_bd_ts    ts_first_pkt, ts_last_pkt;
+};
+
+union tpacket_bd_header_u {
+       struct tpacket_hdr_v1 bh1;
+};
+
+struct tpacket_block_desc {
+       __u32 version;
+       __u32 offset_to_priv;
+       union tpacket_bd_header_u hdr;
+};
+
 #define TPACKET2_HDRLEN                (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll))
+#define TPACKET3_HDRLEN                (TPACKET_ALIGN(sizeof(struct tpacket3_hdr)) + sizeof(struct sockaddr_ll))
 
 enum tpacket_versions {
        TPACKET_V1,
        TPACKET_V2,
+       TPACKET_V3
 };
 
 /*
@@ -138,6 +242,21 @@ struct tpacket_req {
        unsigned int    tp_frame_nr;    /* Total number of frames */
 };
 
+struct tpacket_req3 {
+       unsigned int    tp_block_size;  /* Minimal size of contiguous block */
+       unsigned int    tp_block_nr;    /* Number of blocks */
+       unsigned int    tp_frame_size;  /* Size of frame */
+       unsigned int    tp_frame_nr;    /* Total number of frames */
+       unsigned int    tp_retire_blk_tov; /* timeout in msecs */
+       unsigned int    tp_sizeof_priv; /* offset to private data area */
+       unsigned int    tp_feature_req_word;
+};
+
+union tpacket_req_u {
+       struct tpacket_req      req;
+       struct tpacket_req3     req3;
+};
+
 struct packet_mreq {
        int             mr_ifindex;
        unsigned short  mr_type;
index 184bc55..23cefa1 100644 (file)
@@ -39,7 +39,7 @@ struct pppol2tp_addr {
  * bits. So we need a different sockaddr structure.
  */
 struct pppol2tpv3_addr {
-       pid_t   pid;                    /* pid that owns the fd.
+       __kernel_pid_t  pid;            /* pid that owns the fd.
                                         * 0 => current */
        int     fd;                     /* FD of UDP or IP socket to use */
 
index 397921b..b5f927f 100644 (file)
@@ -20,8 +20,9 @@
 #include <linux/types.h>
 #include <asm/byteorder.h>
 
-#ifdef  __KERNEL__
+#include <linux/socket.h>
 #include <linux/if_ether.h>
+#ifdef  __KERNEL__
 #include <linux/if.h>
 #include <linux/netdevice.h>
 #include <linux/ppp_channel.h>
@@ -63,7 +64,7 @@ struct pptp_addr {
 #define PX_MAX_PROTO   3
 
 struct sockaddr_pppox {
-       sa_family_t     sa_family;            /* address family, AF_PPPOX */
+       __kernel_sa_family_t sa_family;       /* address family, AF_PPPOX */
        unsigned int    sa_protocol;          /* protocol identifier */
        union {
                struct pppoe_addr  pppoe;
@@ -77,7 +78,7 @@ struct sockaddr_pppox {
  * type instead.
  */
 struct sockaddr_pppol2tp {
-       sa_family_t     sa_family;      /* address family, AF_PPPOX */
+       __kernel_sa_family_t sa_family; /* address family, AF_PPPOX */
        unsigned int    sa_protocol;    /* protocol identifier */
        struct pppol2tp_addr pppol2tp;
 } __attribute__((packed));
@@ -86,7 +87,7 @@ struct sockaddr_pppol2tp {
  * bits. So we need a different sockaddr structure.
  */
 struct sockaddr_pppol2tpv3 {
-       sa_family_t     sa_family;      /* address family, AF_PPPOX */
+       __kernel_sa_family_t sa_family; /* address family, AF_PPPOX */
        unsigned int    sa_protocol;    /* protocol identifier */
        struct pppol2tpv3_addr pppol2tp;
 } __attribute__((packed));
index beeb6de..01129c0 100644 (file)
@@ -182,7 +182,7 @@ struct in_pktinfo {
 /* Structure describing an Internet (IP) socket address. */
 #define __SOCK_SIZE__  16              /* sizeof(struct sockaddr)      */
 struct sockaddr_in {
-  sa_family_t          sin_family;     /* Address family               */
+  __kernel_sa_family_t sin_family;     /* Address family               */
   __be16               sin_port;       /* Port number                  */
   struct in_addr       sin_addr;       /* Internet address             */
 
index 068784e..a637e78 100644 (file)
@@ -438,6 +438,8 @@ struct input_keymap_entry {
 #define KEY_WIMAX              246
 #define KEY_RFKILL             247     /* Key that controls all radios */
 
+#define KEY_MICMUTE            248     /* Mute / unmute the microphone */
+
 /* Code 255 is reserved for special needs of AT keyboard driver */
 
 #define BTN_MISC               0x100
index c2ebfe6..9d57a71 100644 (file)
@@ -162,6 +162,7 @@ extern int allocate_resource(struct resource *root, struct resource *new,
                                                       resource_size_t,
                                                       resource_size_t),
                             void *alignf_data);
+struct resource *lookup_resource(struct resource *root, resource_size_t start);
 int adjust_resource(struct resource *res, resource_size_t start,
                    resource_size_t size);
 resource_size_t resource_alignment(struct resource *res);
index aabb1d2..3d48014 100644 (file)
@@ -7,7 +7,7 @@
 #define IPX_MTU                576
 
 struct sockaddr_ipx {
-       sa_family_t     sipx_family;
+       __kernel_sa_family_t sipx_family;
        __be16          sipx_port;
        __be32          sipx_network;
        unsigned char   sipx_node[IPX_NODE_LEN];
index 00bdad0..a014c32 100644 (file)
 #define KERNEL_IRDA_H
 
 #include <linux/types.h>
+#include <linux/socket.h>
 
-/* Please do *not* add any #include in this file, this file is
- * included as-is in user space.
- * Please fix the calling file to properly included needed files before
- * this one, or preferably to include <net/irda/irda.h> instead.
- * Jean II */
+/* Note that this file is shared with user space. */
 
 /* Hint bit positions for first hint byte */
 #define HINT_PNP         0x01
@@ -125,7 +122,7 @@ enum {
 #define LSAP_ANY              0xff
 
 struct sockaddr_irda {
-       sa_family_t sir_family;   /* AF_IRDA */
+       __kernel_sa_family_t sir_family; /* AF_IRDA */
        __u8        sir_lsap_sel; /* LSAP selector */
        __u32       sir_addr;     /* Device address */
        char        sir_name[25]; /* Usually <service>:IrDA:TinyTP */
index 5f69504..87a06f3 100644 (file)
@@ -108,14 +108,18 @@ enum {
 };
 
 struct msi_desc;
+struct irq_domain;
 
 /**
  * struct irq_data - per irq and irq chip data passed down to chip functions
  * @irq:               interrupt number
+ * @hwirq:             hardware interrupt number, local to the interrupt domain
  * @node:              node index useful for balancing
  * @state_use_accessors: status information for irq chip functions.
  *                     Use accessor functions to deal with it
  * @chip:              low level interrupt hardware access
+ * @domain:            Interrupt translation domain; responsible for mapping
+ *                     between hwirq number and linux irq number.
  * @handler_data:      per-IRQ data for the irq_chip methods
  * @chip_data:         platform-specific per-chip private data for the chip
  *                     methods, to allow shared chip implementations
@@ -128,9 +132,11 @@ struct msi_desc;
  */
 struct irq_data {
        unsigned int            irq;
+       unsigned long           hwirq;
        unsigned int            node;
        unsigned int            state_use_accessors;
        struct irq_chip         *chip;
+       struct irq_domain       *domain;
        void                    *handler_data;
        void                    *chip_data;
        struct msi_desc         *msi_desc;
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
new file mode 100644 (file)
index 0000000..e807ad6
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * irq_domain - IRQ translation domains
+ *
+ * Translation infrastructure between hw and linux irq numbers.  This is
+ * helpful for interrupt controllers to implement mapping between hardware
+ * irq numbers and the Linux irq number space.
+ *
+ * irq_domains also have a hook for translating device tree interrupt
+ * representation into a hardware irq number that can be mapped back to a
+ * Linux irq number without any extra platform support code.
+ *
+ * irq_domain is expected to be embedded in an interrupt controller's private
+ * data structure.
+ */
+#ifndef _LINUX_IRQDOMAIN_H
+#define _LINUX_IRQDOMAIN_H
+
+#include <linux/irq.h>
+#include <linux/mod_devicetable.h>
+
+#ifdef CONFIG_IRQ_DOMAIN
+struct device_node;
+struct irq_domain;
+
+/**
+ * struct irq_domain_ops - Methods for irq_domain objects
+ * @to_irq: (optional) given a local hardware irq number, return the linux
+ *          irq number.  If to_irq is not implemented, then the irq_domain
+ *          will use this translation: irq = (domain->irq_base + hwirq)
+ * @dt_translate: Given a device tree node and interrupt specifier, decode
+ *                the hardware irq number and linux irq type value.
+ */
+struct irq_domain_ops {
+       unsigned int (*to_irq)(struct irq_domain *d, unsigned long hwirq);
+
+#ifdef CONFIG_OF
+       int (*dt_translate)(struct irq_domain *d, struct device_node *node,
+                           const u32 *intspec, unsigned int intsize,
+                           unsigned long *out_hwirq, unsigned int *out_type);
+#endif /* CONFIG_OF */
+};
+
+/**
+ * struct irq_domain - Hardware interrupt number translation object
+ * @list: Element in global irq_domain list.
+ * @irq_base: Start of irq_desc range assigned to the irq_domain.  The creator
+ *            of the irq_domain is responsible for allocating the array of
+ *            irq_desc structures.
+ * @nr_irq: Number of irqs managed by the irq domain
+ * @ops: pointer to irq_domain methods
+ * @priv: private data pointer for use by owner.  Not touched by irq_domain
+ *        core code.
+ * @of_node: (optional) Pointer to device tree nodes associated with the
+ *           irq_domain.  Used when decoding device tree interrupt specifiers.
+ */
+struct irq_domain {
+       struct list_head list;
+       unsigned int irq_base;
+       unsigned int nr_irq;
+       const struct irq_domain_ops *ops;
+       void *priv;
+       struct device_node *of_node;
+};
+
+/**
+ * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number
+ *
+ * Returns the linux irq number associated with a hardware irq.  By default,
+ * the mapping is irq == domain->irq_base + hwirq, but this mapping can
+ * be overridden if the irq_domain implements a .to_irq() hook.
+ */
+static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
+                                            unsigned long hwirq)
+{
+       return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
+}
+
+extern void irq_domain_add(struct irq_domain *domain);
+extern void irq_domain_del(struct irq_domain *domain);
+#endif /* CONFIG_IRQ_DOMAIN */
+
+#if defined(CONFIG_IRQ_DOMAIN) && defined(CONFIG_OF_IRQ)
+extern void irq_domain_add_simple(struct device_node *controller, int irq_base);
+extern void irq_domain_generate_simple(const struct of_device_id *match,
+                                       u64 phys_base, unsigned int irq_start);
+#else /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */
+static inline void irq_domain_generate_simple(const struct of_device_id *match,
+                                       u64 phys_base, unsigned int irq_start) { }
+#endif /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */
+
+#endif /* _LINUX_IRQDOMAIN_H */
index d087c2e..38f307b 100644 (file)
@@ -1329,12 +1329,6 @@ extern int jbd_blocks_per_page(struct inode *inode);
 #define BUFFER_TRACE2(bh, bh2, info)   do {} while (0)
 #define JBUFFER_TRACE(jh, info)        do {} while (0)
 
-/* 
- * jbd2_dev_to_name is a utility function used by the jbd2 and ext4 
- * tracing infrastructure to map a dev_t to a device name.
- */
-extern const char *jbd2_dev_to_name(dev_t device);
-
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_JBD2_H */
diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h
new file mode 100644 (file)
index 0000000..067eda0
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __LINUX_KCONFIG_H
+#define __LINUX_KCONFIG_H
+
+#include <generated/autoconf.h>
+
+/*
+ * Helper macros to use CONFIG_ options in C expressions. Note that
+ * these only work with boolean and tristate options.
+ */
+
+/*
+ * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
+ * 0 otherwise.
+ *
+ */
+#define IS_ENABLED(option) \
+       (__enabled_ ## option || __enabled_ ## option ## _MODULE)
+
+/*
+ * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0
+ * otherwise. For boolean options, this is equivalent to
+ * IS_ENABLED(CONFIG_FOO).
+ */
+#define IS_BUILTIN(option) __enabled_ ## option
+
+/*
+ * IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0
+ * otherwise.
+ */
+#define IS_MODULE(option) __enabled_ ## option ## _MODULE
+
+#endif /* __LINUX_KCONFIG_H */
index 4bdb31d..e77d7f9 100644 (file)
@@ -8,8 +8,8 @@
 #define _LINUX_L2TP_H_
 
 #include <linux/types.h>
-#ifdef __KERNEL__
 #include <linux/socket.h>
+#ifdef __KERNEL__
 #include <linux/in.h>
 #else
 #include <netinet/in.h>
 #define __SOCK_SIZE__  16              /* sizeof(struct sockaddr)      */
 struct sockaddr_l2tpip {
        /* The first fields must match struct sockaddr_in */
-       sa_family_t     l2tp_family;    /* AF_INET */
+       __kernel_sa_family_t l2tp_family; /* AF_INET */
        __be16          l2tp_unused;    /* INET port number (unused) */
        struct in_addr  l2tp_addr;      /* Internet address */
 
        __u32           l2tp_conn_id;   /* Connection ID of tunnel */
 
        /* Pad to size of `struct sockaddr'. */
-       unsigned char   __pad[sizeof(struct sockaddr) - sizeof(sa_family_t) -
+       unsigned char   __pad[sizeof(struct sockaddr) -
+                             sizeof(__kernel_sa_family_t) -
                              sizeof(__be16) - sizeof(struct in_addr) -
                              sizeof(__u32)];
 };
index ad7074b..a2418ae 100644 (file)
  *
  * See the GNU General Public License for more details.
  */
+
+#include <linux/socket.h>
+
 #define __LLC_SOCK_SIZE__ 16   /* sizeof(sockaddr_llc), word align. */
 struct sockaddr_llc {
-       sa_family_t     sllc_family;    /* AF_LLC */
-       sa_family_t     sllc_arphrd;    /* ARPHRD_ETHER */
+       __kernel_sa_family_t sllc_family; /* AF_LLC */
+       __kernel_sa_family_t sllc_arphrd; /* ARPHRD_ETHER */
        unsigned char   sllc_test;
        unsigned char   sllc_xid;
        unsigned char   sllc_ua;        /* UA data, only for SOCK_STREAM. */
        unsigned char   sllc_sap;
        unsigned char   sllc_mac[IFHWADDRLEN];
-       unsigned char   __pad[__LLC_SOCK_SIZE__ - sizeof(sa_family_t) * 2 -
+       unsigned char   __pad[__LLC_SOCK_SIZE__ -
+                             sizeof(__kernel_sa_family_t) * 2 -
                              sizeof(unsigned char) * 4 - IFHWADDRLEN];
 };
 
diff --git a/include/linux/llist.h b/include/linux/llist.h
new file mode 100644 (file)
index 0000000..aa0c8b5
--- /dev/null
@@ -0,0 +1,126 @@
+#ifndef LLIST_H
+#define LLIST_H
+/*
+ * Lock-less NULL terminated single linked list
+ *
+ * If there are multiple producers and multiple consumers, llist_add
+ * can be used in producers and llist_del_all can be used in
+ * consumers.  They can work simultaneously without lock.  But
+ * llist_del_first can not be used here.  Because llist_del_first
+ * depends on list->first->next does not changed if list->first is not
+ * changed during its operation, but llist_del_first, llist_add,
+ * llist_add (or llist_del_all, llist_add, llist_add) sequence in
+ * another consumer may violate that.
+ *
+ * If there are multiple producers and one consumer, llist_add can be
+ * used in producers and llist_del_all or llist_del_first can be used
+ * in the consumer.
+ *
+ * This can be summarized as follow:
+ *
+ *           |   add    | del_first |  del_all
+ * add       |    -     |     -     |     -
+ * del_first |          |     L     |     L
+ * del_all   |          |           |     -
+ *
+ * Where "-" stands for no lock is needed, while "L" stands for lock
+ * is needed.
+ *
+ * The list entries deleted via llist_del_all can be traversed with
+ * traversing function such as llist_for_each etc.  But the list
+ * entries can not be traversed safely before deleted from the list.
+ * The order of deleted entries is from the newest to the oldest added
+ * one.  If you want to traverse from the oldest to the newest, you
+ * must reverse the order by yourself before traversing.
+ *
+ * The basic atomic operation of this list is cmpxchg on long.  On
+ * architectures that don't have NMI-safe cmpxchg implementation, the
+ * list can NOT be used in NMI handler.  So code uses the list in NMI
+ * handler should depend on CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG.
+ */
+
+struct llist_head {
+       struct llist_node *first;
+};
+
+struct llist_node {
+       struct llist_node *next;
+};
+
+#define LLIST_HEAD_INIT(name)  { NULL }
+#define LLIST_HEAD(name)       struct llist_head name = LLIST_HEAD_INIT(name)
+
+/**
+ * init_llist_head - initialize lock-less list head
+ * @head:      the head for your lock-less list
+ */
+static inline void init_llist_head(struct llist_head *list)
+{
+       list->first = NULL;
+}
+
+/**
+ * llist_entry - get the struct of this entry
+ * @ptr:       the &struct llist_node pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the llist_node within the struct.
+ */
+#define llist_entry(ptr, type, member)         \
+       container_of(ptr, type, member)
+
+/**
+ * llist_for_each - iterate over some deleted entries of a lock-less list
+ * @pos:       the &struct llist_node to use as a loop cursor
+ * @node:      the first entry of deleted list entries
+ *
+ * In general, some entries of the lock-less list can be traversed
+ * safely only after being deleted from list, so start with an entry
+ * instead of list head.
+ *
+ * If being used on entries deleted from lock-less list directly, the
+ * traverse order is from the newest to the oldest added entry.  If
+ * you want to traverse from the oldest to the newest, you must
+ * reverse the order by yourself before traversing.
+ */
+#define llist_for_each(pos, node)                      \
+       for ((pos) = (node); pos; (pos) = (pos)->next)
+
+/**
+ * llist_for_each_entry - iterate over some deleted entries of lock-less list of given type
+ * @pos:       the type * to use as a loop cursor.
+ * @node:      the fist entry of deleted list entries.
+ * @member:    the name of the llist_node with the struct.
+ *
+ * In general, some entries of the lock-less list can be traversed
+ * safely only after being removed from list, so start with an entry
+ * instead of list head.
+ *
+ * If being used on entries deleted from lock-less list directly, the
+ * traverse order is from the newest to the oldest added entry.  If
+ * you want to traverse from the oldest to the newest, you must
+ * reverse the order by yourself before traversing.
+ */
+#define llist_for_each_entry(pos, node, member)                                \
+       for ((pos) = llist_entry((node), typeof(*(pos)), member);       \
+            &(pos)->member != NULL;                                    \
+            (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member))
+
+/**
+ * llist_empty - tests whether a lock-less list is empty
+ * @head:      the list to test
+ *
+ * Not guaranteed to be accurate or up to date.  Just a quick way to
+ * test whether the list is empty without deleting something from the
+ * list.
+ */
+static inline int llist_empty(const struct llist_head *head)
+{
+       return ACCESS_ONCE(head->first) == NULL;
+}
+
+void llist_add(struct llist_node *new, struct llist_head *head);
+void llist_add_batch(struct llist_node *new_first, struct llist_node *new_last,
+                    struct llist_head *head);
+struct llist_node *llist_del_first(struct llist_head *head);
+struct llist_node *llist_del_all(struct llist_head *head);
+#endif /* LLIST_H */
index b966007..3b535db 100644 (file)
@@ -86,8 +86,6 @@ extern void mem_cgroup_uncharge_end(void);
 
 extern void mem_cgroup_uncharge_page(struct page *page);
 extern void mem_cgroup_uncharge_cache_page(struct page *page);
-extern int mem_cgroup_shmem_charge_fallback(struct page *page,
-                       struct mm_struct *mm, gfp_t gfp_mask);
 
 extern void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask);
 int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem);
@@ -225,12 +223,6 @@ static inline void mem_cgroup_uncharge_cache_page(struct page *page)
 {
 }
 
-static inline int mem_cgroup_shmem_charge_fallback(struct page *page,
-                       struct mm_struct *mm, gfp_t gfp_mask)
-{
-       return 0;
-}
-
 static inline void mem_cgroup_add_lru_list(struct page *page, int lru)
 {
 }
diff --git a/include/linux/mfd/aat2870.h b/include/linux/mfd/aat2870.h
new file mode 100644 (file)
index 0000000..f7316c2
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * linux/include/linux/mfd/aat2870.h
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ * Author: Jin Park <jinyoungp@nvidia.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __LINUX_MFD_AAT2870_H
+#define __LINUX_MFD_AAT2870_H
+
+#include <linux/debugfs.h>
+#include <linux/i2c.h>
+
+/* Register offsets */
+#define AAT2870_BL_CH_EN       0x00
+#define AAT2870_BLM            0x01
+#define AAT2870_BLS            0x02
+#define AAT2870_BL1            0x03
+#define AAT2870_BL2            0x04
+#define AAT2870_BL3            0x05
+#define AAT2870_BL4            0x06
+#define AAT2870_BL5            0x07
+#define AAT2870_BL6            0x08
+#define AAT2870_BL7            0x09
+#define AAT2870_BL8            0x0A
+#define AAT2870_FLR            0x0B
+#define AAT2870_FM             0x0C
+#define AAT2870_FS             0x0D
+#define AAT2870_ALS_CFG0       0x0E
+#define AAT2870_ALS_CFG1       0x0F
+#define AAT2870_ALS_CFG2       0x10
+#define AAT2870_AMB            0x11
+#define AAT2870_ALS0           0x12
+#define AAT2870_ALS1           0x13
+#define AAT2870_ALS2           0x14
+#define AAT2870_ALS3           0x15
+#define AAT2870_ALS4           0x16
+#define AAT2870_ALS5           0x17
+#define AAT2870_ALS6           0x18
+#define AAT2870_ALS7           0x19
+#define AAT2870_ALS8           0x1A
+#define AAT2870_ALS9           0x1B
+#define AAT2870_ALSA           0x1C
+#define AAT2870_ALSB           0x1D
+#define AAT2870_ALSC           0x1E
+#define AAT2870_ALSD           0x1F
+#define AAT2870_ALSE           0x20
+#define AAT2870_ALSF           0x21
+#define AAT2870_SUB_SET                0x22
+#define AAT2870_SUB_CTRL       0x23
+#define AAT2870_LDO_AB         0x24
+#define AAT2870_LDO_CD         0x25
+#define AAT2870_LDO_EN         0x26
+#define AAT2870_REG_NUM                0x27
+
+/* Device IDs */
+enum aat2870_id {
+       AAT2870_ID_BL,
+       AAT2870_ID_LDOA,
+       AAT2870_ID_LDOB,
+       AAT2870_ID_LDOC,
+       AAT2870_ID_LDOD
+};
+
+/* Backlight channels */
+#define AAT2870_BL_CH1         0x01
+#define AAT2870_BL_CH2         0x02
+#define AAT2870_BL_CH3         0x04
+#define AAT2870_BL_CH4         0x08
+#define AAT2870_BL_CH5         0x10
+#define AAT2870_BL_CH6         0x20
+#define AAT2870_BL_CH7         0x40
+#define AAT2870_BL_CH8         0x80
+#define AAT2870_BL_CH_ALL      0xFF
+
+/* Backlight current magnitude (mA) */
+enum aat2870_current {
+       AAT2870_CURRENT_0_45 = 1,
+       AAT2870_CURRENT_0_90,
+       AAT2870_CURRENT_1_80,
+       AAT2870_CURRENT_2_70,
+       AAT2870_CURRENT_3_60,
+       AAT2870_CURRENT_4_50,
+       AAT2870_CURRENT_5_40,
+       AAT2870_CURRENT_6_30,
+       AAT2870_CURRENT_7_20,
+       AAT2870_CURRENT_8_10,
+       AAT2870_CURRENT_9_00,
+       AAT2870_CURRENT_9_90,
+       AAT2870_CURRENT_10_8,
+       AAT2870_CURRENT_11_7,
+       AAT2870_CURRENT_12_6,
+       AAT2870_CURRENT_13_5,
+       AAT2870_CURRENT_14_4,
+       AAT2870_CURRENT_15_3,
+       AAT2870_CURRENT_16_2,
+       AAT2870_CURRENT_17_1,
+       AAT2870_CURRENT_18_0,
+       AAT2870_CURRENT_18_9,
+       AAT2870_CURRENT_19_8,
+       AAT2870_CURRENT_20_7,
+       AAT2870_CURRENT_21_6,
+       AAT2870_CURRENT_22_5,
+       AAT2870_CURRENT_23_4,
+       AAT2870_CURRENT_24_3,
+       AAT2870_CURRENT_25_2,
+       AAT2870_CURRENT_26_1,
+       AAT2870_CURRENT_27_0,
+       AAT2870_CURRENT_27_9
+};
+
+struct aat2870_register {
+       bool readable;
+       bool writeable;
+       u8 value;
+};
+
+struct aat2870_data {
+       struct device *dev;
+       struct i2c_client *client;
+
+       struct mutex io_lock;
+       struct aat2870_register *reg_cache; /* register cache */
+       int en_pin; /* enable GPIO pin (if < 0, ignore this value) */
+       bool is_enable;
+
+       /* init and uninit for platform specified */
+       int (*init)(struct aat2870_data *aat2870);
+       void (*uninit)(struct aat2870_data *aat2870);
+
+       /* i2c io funcntions */
+       int (*read)(struct aat2870_data *aat2870, u8 addr, u8 *val);
+       int (*write)(struct aat2870_data *aat2870, u8 addr, u8 val);
+       int (*update)(struct aat2870_data *aat2870, u8 addr, u8 mask, u8 val);
+
+       /* for debugfs */
+       struct dentry *dentry_root;
+       struct dentry *dentry_reg;
+};
+
+struct aat2870_subdev_info {
+       int id;
+       const char *name;
+       void *platform_data;
+};
+
+struct aat2870_platform_data {
+       int en_pin; /* enable GPIO pin (if < 0, ignore this value) */
+
+       struct aat2870_subdev_info *subdevs;
+       int num_subdevs;
+
+       /* init and uninit for platform specified */
+       int (*init)(struct aat2870_data *aat2870);
+       void (*uninit)(struct aat2870_data *aat2870);
+};
+
+struct aat2870_bl_platform_data {
+       /* backlight channels, default is AAT2870_BL_CH_ALL */
+       int channels;
+       /* backlight current magnitude, default is AAT2870_CURRENT_27_9 */
+       int max_current;
+       /* maximum brightness, default is 255 */
+       int max_brightness;
+};
+
+#endif /* __LINUX_MFD_AAT2870_H */
index b318430..838c6b4 100644 (file)
@@ -28,6 +28,7 @@
 #define AB8500_INTERRUPT       0xE
 #define AB8500_RTC             0xF
 #define AB8500_MISC            0x10
+#define AB8500_DEVELOPMENT     0x11
 #define AB8500_DEBUG           0x12
 #define AB8500_PROD_TEST       0x13
 #define AB8500_OTP_EMUL                0x15
 #define AB8500_INT_ACC_DETECT_21DB_F   37
 #define AB8500_INT_ACC_DETECT_21DB_R   38
 #define AB8500_INT_GP_SW_ADC_CONV_END  39
-#define AB8500_INT_ACC_DETECT_1DB_F    33
-#define AB8500_INT_ACC_DETECT_1DB_R    34
-#define AB8500_INT_ACC_DETECT_22DB_F   35
-#define AB8500_INT_ACC_DETECT_22DB_R   36
-#define AB8500_INT_ACC_DETECT_21DB_F   37
-#define AB8500_INT_ACC_DETECT_21DB_R   38
-#define AB8500_INT_GP_SW_ADC_CONV_END  39
 #define AB8500_INT_GPIO6R              40
 #define AB8500_INT_GPIO7R              41
 #define AB8500_INT_GPIO8R              42
index 60931d0..0bbd13d 100644 (file)
@@ -107,11 +107,16 @@ struct max8997_platform_data {
        unsigned int buck5_voltage[8];
        bool buck5_gpiodvs;
 
+       /* ---- Charger control ---- */
+       /* eoc stands for 'end of charge' */
+       int eoc_mA; /* 50 ~ 200mA by 10mA step */
+       /* charge Full Timeout */
+       int timeout; /* 0 (no timeout), 5, 6, 7 hours */
+
        /* MUIC: Not implemented */
        /* HAPTIC: Not implemented */
        /* RTC: Not implemented */
        /* Flash: Not implemented */
-       /* Charger control: Not implemented */
 };
 
 #endif /* __LINUX_MFD_MAX8998_H */
index 61daa16..f4f0dfa 100644 (file)
@@ -87,6 +87,15 @@ struct max8998_regulator_data {
  * @wakeup: Allow to wake up from suspend
  * @rtc_delay: LP3974 RTC chip bug that requires delay after a register
  * write before reading it.
+ * @eoc: End of Charge Level in percent: 10% ~ 45% by 5% step
+ *   If it equals 0, leave it unchanged.
+ *   Otherwise, it is a invalid value.
+ * @restart: Restart Level in mV: 100, 150, 200, and -1 for disable.
+ *   If it equals 0, leave it unchanged.
+ *   Otherwise, it is a invalid value.
+ * @timeout: Full Timeout in hours: 5, 6, 7, and -1 for disable.
+ *   If it equals 0, leave it unchanged.
+ *   Otherwise, leave it unchanged.
  */
 struct max8998_platform_data {
        struct max8998_regulator_data   *regulators;
@@ -107,6 +116,9 @@ struct max8998_platform_data {
        int                             buck2_default_idx;
        bool                            wakeup;
        bool                            rtc_delay;
+       int                             eoc;
+       int                             restart;
+       int                             timeout;
 };
 
 #endif /*  __LINUX_MFD_MAX8998_H */
index e762c27..be1af7c 100644 (file)
@@ -57,6 +57,7 @@ struct stmpe_variant_info;
  * @irq_lock: IRQ bus lock
  * @dev: device, mostly for dev_dbg()
  * @i2c: i2c client
+ * @partnum: part number
  * @variant: the detected STMPE model number
  * @regs: list of addresses of registers which are at different addresses on
  *       different variants.  Indexed by one of STMPE_IDX_*.
@@ -121,6 +122,8 @@ struct stmpe_keypad_platform_data {
  * @norequest_mask: bitmask specifying which GPIOs should _not_ be
  *                 requestable due to different usage (e.g. touch, keypad)
  *                 STMPE_GPIO_NOREQ_* macros can be used here.
+ * @setup: board specific setup callback.
+ * @remove: board specific remove callback
  */
 struct stmpe_gpio_platform_data {
        int gpio_base;
index 73572c6..82b4c88 100644 (file)
@@ -791,6 +791,7 @@ int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
 void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base);
 int tps65910_irq_init(struct tps65910 *tps65910, int irq,
                struct tps65910_platform_data *pdata);
+int tps65910_irq_exit(struct tps65910 *tps65910);
 
 static inline int tps65910_chip_id(struct tps65910 *tps65910)
 {
diff --git a/include/linux/mfd/tps65912.h b/include/linux/mfd/tps65912.h
new file mode 100644 (file)
index 0000000..aaceab4
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * tps65912.h  --  TI TPS6591x
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya <magi@slimlogic.co.uk>
+ *
+ *  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.
+ *
+ */
+
+#ifndef __LINUX_MFD_TPS65912_H
+#define __LINUX_MFD_TPS65912_H
+
+/* TPS regulator type list */
+#define REGULATOR_LDO          0
+#define REGULATOR_DCDC         1
+
+/*
+ * List of registers for TPS65912
+ */
+
+#define TPS65912_DCDC1_CTRL            0x00
+#define TPS65912_DCDC2_CTRL            0x01
+#define TPS65912_DCDC3_CTRL            0x02
+#define TPS65912_DCDC4_CTRL            0x03
+#define TPS65912_DCDC1_OP              0x04
+#define TPS65912_DCDC1_AVS             0x05
+#define TPS65912_DCDC1_LIMIT           0x06
+#define TPS65912_DCDC2_OP              0x07
+#define TPS65912_DCDC2_AVS             0x08
+#define TPS65912_DCDC2_LIMIT           0x09
+#define TPS65912_DCDC3_OP              0x0A
+#define TPS65912_DCDC3_AVS             0x0B
+#define TPS65912_DCDC3_LIMIT           0x0C
+#define TPS65912_DCDC4_OP              0x0D
+#define TPS65912_DCDC4_AVS             0x0E
+#define TPS65912_DCDC4_LIMIT           0x0F
+#define TPS65912_LDO1_OP               0x10
+#define TPS65912_LDO1_AVS              0x11
+#define TPS65912_LDO1_LIMIT            0x12
+#define TPS65912_LDO2_OP               0x13
+#define TPS65912_LDO2_AVS              0x14
+#define TPS65912_LDO2_LIMIT            0x15
+#define TPS65912_LDO3_OP               0x16
+#define TPS65912_LDO3_AVS              0x17
+#define TPS65912_LDO3_LIMIT            0x18
+#define TPS65912_LDO4_OP               0x19
+#define TPS65912_LDO4_AVS              0x1A
+#define TPS65912_LDO4_LIMIT            0x1B
+#define TPS65912_LDO5                  0x1C
+#define TPS65912_LDO6                  0x1D
+#define TPS65912_LDO7                  0x1E
+#define TPS65912_LDO8                  0x1F
+#define TPS65912_LDO9                  0x20
+#define TPS65912_LDO10                 0x21
+#define TPS65912_THRM                  0x22
+#define TPS65912_CLK32OUT              0x23
+#define TPS65912_DEVCTRL               0x24
+#define TPS65912_DEVCTRL2              0x25
+#define TPS65912_I2C_SPI_CFG           0x26
+#define TPS65912_KEEP_ON               0x27
+#define TPS65912_KEEP_ON2              0x28
+#define TPS65912_SET_OFF1              0x29
+#define TPS65912_SET_OFF2              0x2A
+#define TPS65912_DEF_VOLT              0x2B
+#define TPS65912_DEF_VOLT_MAPPING      0x2C
+#define TPS65912_DISCHARGE             0x2D
+#define TPS65912_DISCHARGE2            0x2E
+#define TPS65912_EN1_SET1              0x2F
+#define TPS65912_EN1_SET2              0x30
+#define TPS65912_EN2_SET1              0x31
+#define TPS65912_EN2_SET2              0x32
+#define TPS65912_EN3_SET1              0x33
+#define TPS65912_EN3_SET2              0x34
+#define TPS65912_EN4_SET1              0x35
+#define TPS65912_EN4_SET2              0x36
+#define TPS65912_PGOOD                 0x37
+#define TPS65912_PGOOD2                        0x38
+#define TPS65912_INT_STS               0x39
+#define TPS65912_INT_MSK               0x3A
+#define TPS65912_INT_STS2              0x3B
+#define TPS65912_INT_MSK2              0x3C
+#define TPS65912_INT_STS3              0x3D
+#define TPS65912_INT_MSK3              0x3E
+#define TPS65912_INT_STS4              0x3F
+#define TPS65912_INT_MSK4              0x40
+#define TPS65912_GPIO1                 0x41
+#define TPS65912_GPIO2                 0x42
+#define TPS65912_GPIO3                 0x43
+#define TPS65912_GPIO4                 0x44
+#define TPS65912_GPIO5                 0x45
+#define TPS65912_VMON                  0x46
+#define TPS65912_LEDA_CTRL1            0x47
+#define TPS65912_LEDA_CTRL2            0x48
+#define TPS65912_LEDA_CTRL3            0x49
+#define TPS65912_LEDA_CTRL4            0x4A
+#define TPS65912_LEDA_CTRL5            0x4B
+#define TPS65912_LEDA_CTRL6            0x4C
+#define TPS65912_LEDA_CTRL7            0x4D
+#define TPS65912_LEDA_CTRL8            0x4E
+#define TPS65912_LEDB_CTRL1            0x4F
+#define TPS65912_LEDB_CTRL2            0x50
+#define TPS65912_LEDB_CTRL3            0x51
+#define TPS65912_LEDB_CTRL4            0x52
+#define TPS65912_LEDB_CTRL5            0x53
+#define TPS65912_LEDB_CTRL6            0x54
+#define TPS65912_LEDB_CTRL7            0x55
+#define TPS65912_LEDB_CTRL8            0x56
+#define TPS65912_LEDC_CTRL1            0x57
+#define TPS65912_LEDC_CTRL2            0x58
+#define TPS65912_LEDC_CTRL3            0x59
+#define TPS65912_LEDC_CTRL4            0x5A
+#define TPS65912_LEDC_CTRL5            0x5B
+#define TPS65912_LEDC_CTRL6            0x5C
+#define TPS65912_LEDC_CTRL7            0x5D
+#define TPS65912_LEDC_CTRL8            0x5E
+#define TPS65912_LED_RAMP_UP_TIME      0x5F
+#define TPS65912_LED_RAMP_DOWN_TIME    0x60
+#define TPS65912_LED_SEQ_EN            0x61
+#define TPS65912_LOADSWITCH            0x62
+#define TPS65912_SPARE                 0x63
+#define TPS65912_VERNUM                        0x64
+#define TPS6591X_MAX_REGISTER          0x64
+
+/* IRQ Definitions */
+#define TPS65912_IRQ_PWRHOLD_F         0
+#define TPS65912_IRQ_VMON              1
+#define TPS65912_IRQ_PWRON             2
+#define TPS65912_IRQ_PWRON_LP          3
+#define TPS65912_IRQ_PWRHOLD_R         4
+#define TPS65912_IRQ_HOTDIE            5
+#define TPS65912_IRQ_GPIO1_R           6
+#define TPS65912_IRQ_GPIO1_F           7
+#define TPS65912_IRQ_GPIO2_R           8
+#define TPS65912_IRQ_GPIO2_F           9
+#define TPS65912_IRQ_GPIO3_R           10
+#define TPS65912_IRQ_GPIO3_F           11
+#define TPS65912_IRQ_GPIO4_R           12
+#define TPS65912_IRQ_GPIO4_F           13
+#define TPS65912_IRQ_GPIO5_R           14
+#define TPS65912_IRQ_GPIO5_F           15
+#define TPS65912_IRQ_PGOOD_DCDC1       16
+#define TPS65912_IRQ_PGOOD_DCDC2       17
+#define TPS65912_IRQ_PGOOD_DCDC3       18
+#define TPS65912_IRQ_PGOOD_DCDC4       19
+#define TPS65912_IRQ_PGOOD_LDO1                20
+#define TPS65912_IRQ_PGOOD_LDO2                21
+#define TPS65912_IRQ_PGOOD_LDO3                22
+#define TPS65912_IRQ_PGOOD_LDO4                23
+#define TPS65912_IRQ_PGOOD_LDO5                24
+#define TPS65912_IRQ_PGOOD_LDO6                25
+#define TPS65912_IRQ_PGOOD_LDO7                26
+#define TPS65912_IRQ_PGOOD_LD08                27
+#define TPS65912_IRQ_PGOOD_LDO9                28
+#define TPS65912_IRQ_PGOOD_LDO10       29
+
+#define TPS65912_NUM_IRQ               30
+
+/* GPIO 1 and 2 Register Definitions */
+#define GPIO_SLEEP_MASK                        0x80
+#define GPIO_SLEEP_SHIFT               7
+#define GPIO_DEB_MASK                  0x10
+#define GPIO_DEB_SHIFT                 4
+#define GPIO_CFG_MASK                  0x04
+#define GPIO_CFG_SHIFT                 2
+#define GPIO_STS_MASK                  0x02
+#define GPIO_STS_SHIFT                 1
+#define GPIO_SET_MASK                  0x01
+#define GPIO_SET_SHIFT                 0
+
+/* GPIO 3 Register Definitions */
+#define GPIO3_SLEEP_MASK               0x80
+#define GPIO3_SLEEP_SHIFT              7
+#define GPIO3_SEL_MASK                 0x40
+#define GPIO3_SEL_SHIFT                        6
+#define GPIO3_ODEN_MASK                        0x20
+#define GPIO3_ODEN_SHIFT               5
+#define GPIO3_DEB_MASK                 0x10
+#define GPIO3_DEB_SHIFT                        4
+#define GPIO3_PDEN_MASK                        0x08
+#define GPIO3_PDEN_SHIFT               3
+#define GPIO3_CFG_MASK                 0x04
+#define GPIO3_CFG_SHIFT                        2
+#define GPIO3_STS_MASK                 0x02
+#define GPIO3_STS_SHIFT                        1
+#define GPIO3_SET_MASK                 0x01
+#define GPIO3_SET_SHIFT                        0
+
+/* GPIO 4 Register Definitions */
+#define GPIO4_SLEEP_MASK               0x80
+#define GPIO4_SLEEP_SHIFT              7
+#define GPIO4_SEL_MASK                 0x40
+#define GPIO4_SEL_SHIFT                        6
+#define GPIO4_ODEN_MASK                        0x20
+#define GPIO4_ODEN_SHIFT               5
+#define GPIO4_DEB_MASK                 0x10
+#define GPIO4_DEB_SHIFT                        4
+#define GPIO4_PDEN_MASK                        0x08
+#define GPIO4_PDEN_SHIFT               3
+#define GPIO4_CFG_MASK                 0x04
+#define GPIO4_CFG_SHIFT                        2
+#define GPIO4_STS_MASK                 0x02
+#define GPIO4_STS_SHIFT                        1
+#define GPIO4_SET_MASK                 0x01
+#define GPIO4_SET_SHIFT                        0
+
+/* Register THERM  (0x80) register.RegisterDescription */
+#define THERM_THERM_HD_MASK            0x20
+#define THERM_THERM_HD_SHIFT           5
+#define THERM_THERM_TS_MASK            0x10
+#define THERM_THERM_TS_SHIFT           4
+#define THERM_THERM_HDSEL_MASK         0x0C
+#define THERM_THERM_HDSEL_SHIFT                2
+#define THERM_RSVD1_MASK               0x02
+#define THERM_RSVD1_SHIFT              1
+#define THERM_THERM_STATE_MASK         0x01
+#define THERM_THERM_STATE_SHIFT                0
+
+/* Register DCDCCTRL1 register.RegisterDescription */
+#define DCDCCTRL_VCON_ENABLE_MASK      0x80
+#define DCDCCTRL_VCON_ENABLE_SHIFT     7
+#define DCDCCTRL_VCON_RANGE1_MASK      0x40
+#define DCDCCTRL_VCON_RANGE1_SHIFT     6
+#define DCDCCTRL_VCON_RANGE0_MASK      0x20
+#define DCDCCTRL_VCON_RANGE0_SHIFT     5
+#define DCDCCTRL_TSTEP2_MASK           0x10
+#define DCDCCTRL_TSTEP2_SHIFT          4
+#define DCDCCTRL_TSTEP1_MASK           0x08
+#define DCDCCTRL_TSTEP1_SHIFT          3
+#define DCDCCTRL_TSTEP0_MASK           0x04
+#define DCDCCTRL_TSTEP0_SHIFT          2
+#define DCDCCTRL_DCDC1_MODE_MASK       0x02
+#define DCDCCTRL_DCDC1_MODE_SHIFT      1
+
+/* Register DCDCCTRL2 and DCDCCTRL3 register.RegisterDescription */
+#define DCDCCTRL_TSTEP2_MASK           0x10
+#define DCDCCTRL_TSTEP2_SHIFT          4
+#define DCDCCTRL_TSTEP1_MASK           0x08
+#define DCDCCTRL_TSTEP1_SHIFT          3
+#define DCDCCTRL_TSTEP0_MASK           0x04
+#define DCDCCTRL_TSTEP0_SHIFT          2
+#define DCDCCTRL_DCDC_MODE_MASK                0x02
+#define DCDCCTRL_DCDC_MODE_SHIFT       1
+#define DCDCCTRL_RSVD0_MASK            0x01
+#define DCDCCTRL_RSVD0_SHIFT           0
+
+/* Register DCDCCTRL4 register.RegisterDescription */
+#define DCDCCTRL_RAMP_TIME_MASK                0x01
+#define DCDCCTRL_RAMP_TIME_SHIFT       0
+
+/* Register DCDCx_AVS */
+#define DCDC_AVS_ENABLE_MASK           0x80
+#define DCDC_AVS_ENABLE_SHIFT          7
+#define DCDC_AVS_ECO_MASK              0x40
+#define DCDC_AVS_ECO_SHIFT             6
+
+/* Register DCDCx_LIMIT */
+#define DCDC_LIMIT_RANGE_MASK          0xC0
+#define DCDC_LIMIT_RANGE_SHIFT         6
+#define DCDC_LIMIT_MAX_SEL_MASK                0x3F
+#define DCDC_LIMIT_MAX_SEL_SHIFT       0
+
+/**
+ * struct tps65912_board
+ * Board platform dat may be used to initialize regulators.
+ */
+struct tps65912_board {
+       int is_dcdc1_avs;
+       int is_dcdc2_avs;
+       int is_dcdc3_avs;
+       int is_dcdc4_avs;
+       int irq;
+       int irq_base;
+       int gpio_base;
+       struct regulator_init_data *tps65912_pmic_init_data;
+};
+
+/**
+ * struct tps65912 - tps65912 sub-driver chip access routines
+ */
+
+struct tps65912 {
+       struct device *dev;
+       /* for read/write acces */
+       struct mutex io_mutex;
+
+       /* For device IO interfaces: I2C or SPI */
+       void *control_data;
+
+       int (*read)(struct tps65912 *tps65912, u8 reg, int size, void *dest);
+       int (*write)(struct tps65912 *tps65912, u8 reg, int size, void *src);
+
+       /* Client devices */
+       struct tps65912_pmic *pmic;
+
+       /* GPIO Handling */
+       struct gpio_chip gpio;
+
+       /* IRQ Handling */
+       struct mutex irq_lock;
+       int chip_irq;
+       int irq_base;
+       int irq_num;
+       u32 irq_mask;
+};
+
+struct tps65912_platform_data {
+       int irq;
+       int irq_base;
+};
+
+unsigned int tps_chip(void);
+
+int tps65912_set_bits(struct tps65912 *tps65912, u8 reg, u8 mask);
+int tps65912_clear_bits(struct tps65912 *tps65912, u8 reg, u8 mask);
+int tps65912_reg_read(struct tps65912 *tps65912, u8 reg);
+int tps65912_reg_write(struct tps65912 *tps65912, u8 reg, u8 val);
+int tps65912_device_init(struct tps65912 *tps65912);
+void tps65912_device_exit(struct tps65912 *tps65912);
+int tps65912_irq_init(struct tps65912 *tps65912, int irq,
+                       struct tps65912_platform_data *pdata);
+
+#endif /*  __LINUX_MFD_TPS65912_H */
index 0d515ee..8dda8de 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/completion.h>
 #include <linux/interrupt.h>
+#include <linux/list.h>
 
 /*
  * Register values.
 #define WM831X_ON_PIN_TO_SHIFT                       0  /* ON_PIN_TO - [1:0] */
 #define WM831X_ON_PIN_TO_WIDTH                       2  /* ON_PIN_TO - [1:0] */
 
+/*
+ * R16528 (0x4090) - Clock Control 1
+ */
+#define WM831X_CLKOUT_ENA                       0x8000  /* CLKOUT_ENA */
+#define WM831X_CLKOUT_ENA_MASK                  0x8000  /* CLKOUT_ENA */
+#define WM831X_CLKOUT_ENA_SHIFT                     15  /* CLKOUT_ENA */
+#define WM831X_CLKOUT_ENA_WIDTH                      1  /* CLKOUT_ENA */
+#define WM831X_CLKOUT_OD                        0x2000  /* CLKOUT_OD */
+#define WM831X_CLKOUT_OD_MASK                   0x2000  /* CLKOUT_OD */
+#define WM831X_CLKOUT_OD_SHIFT                      13  /* CLKOUT_OD */
+#define WM831X_CLKOUT_OD_WIDTH                       1  /* CLKOUT_OD */
+#define WM831X_CLKOUT_SLOT_MASK                 0x0700  /* CLKOUT_SLOT - [10:8] */
+#define WM831X_CLKOUT_SLOT_SHIFT                     8  /* CLKOUT_SLOT - [10:8] */
+#define WM831X_CLKOUT_SLOT_WIDTH                     3  /* CLKOUT_SLOT - [10:8] */
+#define WM831X_CLKOUT_SLPSLOT_MASK              0x0070  /* CLKOUT_SLPSLOT - [6:4] */
+#define WM831X_CLKOUT_SLPSLOT_SHIFT                  4  /* CLKOUT_SLPSLOT - [6:4] */
+#define WM831X_CLKOUT_SLPSLOT_WIDTH                  3  /* CLKOUT_SLPSLOT - [6:4] */
+#define WM831X_CLKOUT_SRC                       0x0001  /* CLKOUT_SRC */
+#define WM831X_CLKOUT_SRC_MASK                  0x0001  /* CLKOUT_SRC */
+#define WM831X_CLKOUT_SRC_SHIFT                      0  /* CLKOUT_SRC */
+#define WM831X_CLKOUT_SRC_WIDTH                      1  /* CLKOUT_SRC */
+
+/*
+ * R16529 (0x4091) - Clock Control 2
+ */
+#define WM831X_XTAL_INH                         0x8000  /* XTAL_INH */
+#define WM831X_XTAL_INH_MASK                    0x8000  /* XTAL_INH */
+#define WM831X_XTAL_INH_SHIFT                       15  /* XTAL_INH */
+#define WM831X_XTAL_INH_WIDTH                        1  /* XTAL_INH */
+#define WM831X_XTAL_ENA                         0x2000  /* XTAL_ENA */
+#define WM831X_XTAL_ENA_MASK                    0x2000  /* XTAL_ENA */
+#define WM831X_XTAL_ENA_SHIFT                       13  /* XTAL_ENA */
+#define WM831X_XTAL_ENA_WIDTH                        1  /* XTAL_ENA */
+#define WM831X_XTAL_BKUPENA                     0x1000  /* XTAL_BKUPENA */
+#define WM831X_XTAL_BKUPENA_MASK                0x1000  /* XTAL_BKUPENA */
+#define WM831X_XTAL_BKUPENA_SHIFT                   12  /* XTAL_BKUPENA */
+#define WM831X_XTAL_BKUPENA_WIDTH                    1  /* XTAL_BKUPENA */
+#define WM831X_FLL_AUTO                         0x0080  /* FLL_AUTO */
+#define WM831X_FLL_AUTO_MASK                    0x0080  /* FLL_AUTO */
+#define WM831X_FLL_AUTO_SHIFT                        7  /* FLL_AUTO */
+#define WM831X_FLL_AUTO_WIDTH                        1  /* FLL_AUTO */
+#define WM831X_FLL_AUTO_FREQ_MASK               0x0007  /* FLL_AUTO_FREQ - [2:0] */
+#define WM831X_FLL_AUTO_FREQ_SHIFT                   0  /* FLL_AUTO_FREQ - [2:0] */
+#define WM831X_FLL_AUTO_FREQ_WIDTH                   3  /* FLL_AUTO_FREQ - [2:0] */
+
+/*
+ * R16530 (0x4092) - FLL Control 1
+ */
+#define WM831X_FLL_FRAC                         0x0004  /* FLL_FRAC */
+#define WM831X_FLL_FRAC_MASK                    0x0004  /* FLL_FRAC */
+#define WM831X_FLL_FRAC_SHIFT                        2  /* FLL_FRAC */
+#define WM831X_FLL_FRAC_WIDTH                        1  /* FLL_FRAC */
+#define WM831X_FLL_OSC_ENA                      0x0002  /* FLL_OSC_ENA */
+#define WM831X_FLL_OSC_ENA_MASK                 0x0002  /* FLL_OSC_ENA */
+#define WM831X_FLL_OSC_ENA_SHIFT                     1  /* FLL_OSC_ENA */
+#define WM831X_FLL_OSC_ENA_WIDTH                     1  /* FLL_OSC_ENA */
+#define WM831X_FLL_ENA                          0x0001  /* FLL_ENA */
+#define WM831X_FLL_ENA_MASK                     0x0001  /* FLL_ENA */
+#define WM831X_FLL_ENA_SHIFT                         0  /* FLL_ENA */
+#define WM831X_FLL_ENA_WIDTH                         1  /* FLL_ENA */
+
+/*
+ * R16531 (0x4093) - FLL Control 2
+ */
+#define WM831X_FLL_OUTDIV_MASK                  0x3F00  /* FLL_OUTDIV - [13:8] */
+#define WM831X_FLL_OUTDIV_SHIFT                      8  /* FLL_OUTDIV - [13:8] */
+#define WM831X_FLL_OUTDIV_WIDTH                      6  /* FLL_OUTDIV - [13:8] */
+#define WM831X_FLL_CTRL_RATE_MASK               0x0070  /* FLL_CTRL_RATE - [6:4] */
+#define WM831X_FLL_CTRL_RATE_SHIFT                   4  /* FLL_CTRL_RATE - [6:4] */
+#define WM831X_FLL_CTRL_RATE_WIDTH                   3  /* FLL_CTRL_RATE - [6:4] */
+#define WM831X_FLL_FRATIO_MASK                  0x0007  /* FLL_FRATIO - [2:0] */
+#define WM831X_FLL_FRATIO_SHIFT                      0  /* FLL_FRATIO - [2:0] */
+#define WM831X_FLL_FRATIO_WIDTH                      3  /* FLL_FRATIO - [2:0] */
+
+/*
+ * R16532 (0x4094) - FLL Control 3
+ */
+#define WM831X_FLL_K_MASK                       0xFFFF  /* FLL_K - [15:0] */
+#define WM831X_FLL_K_SHIFT                           0  /* FLL_K - [15:0] */
+#define WM831X_FLL_K_WIDTH                          16  /* FLL_K - [15:0] */
+
+/*
+ * R16533 (0x4095) - FLL Control 4
+ */
+#define WM831X_FLL_N_MASK                       0x7FE0  /* FLL_N - [14:5] */
+#define WM831X_FLL_N_SHIFT                           5  /* FLL_N - [14:5] */
+#define WM831X_FLL_N_WIDTH                          10  /* FLL_N - [14:5] */
+#define WM831X_FLL_GAIN_MASK                    0x000F  /* FLL_GAIN - [3:0] */
+#define WM831X_FLL_GAIN_SHIFT                        0  /* FLL_GAIN - [3:0] */
+#define WM831X_FLL_GAIN_WIDTH                        4  /* FLL_GAIN - [3:0] */
+
+/*
+ * R16534 (0x4096) - FLL Control 5
+ */
+#define WM831X_FLL_CLK_REF_DIV_MASK             0x0018  /* FLL_CLK_REF_DIV - [4:3] */
+#define WM831X_FLL_CLK_REF_DIV_SHIFT                 3  /* FLL_CLK_REF_DIV - [4:3] */
+#define WM831X_FLL_CLK_REF_DIV_WIDTH                 2  /* FLL_CLK_REF_DIV - [4:3] */
+#define WM831X_FLL_CLK_SRC_MASK                 0x0003  /* FLL_CLK_SRC - [1:0] */
+#define WM831X_FLL_CLK_SRC_SHIFT                     0  /* FLL_CLK_SRC - [1:0] */
+#define WM831X_FLL_CLK_SRC_WIDTH                     2  /* FLL_CLK_SRC - [1:0] */
+
 struct regulator_dev;
 
 #define WM831X_NUM_IRQ_REGS 5
+#define WM831X_NUM_GPIO_REGS 16
 
 enum wm831x_parent {
        WM8310 = 0x8310,
@@ -248,6 +351,12 @@ enum wm831x_parent {
        WM8326 = 0x8326,
 };
 
+struct wm831x;
+enum wm831x_auxadc;
+
+typedef int (*wm831x_auxadc_read_fn)(struct wm831x *wm831x,
+                                    enum wm831x_auxadc input);
+
 struct wm831x {
        struct mutex io_lock;
 
@@ -261,7 +370,7 @@ struct wm831x {
 
        int irq;  /* Our chip IRQ */
        struct mutex irq_lock;
-       unsigned int irq_base;
+       int irq_base;
        int irq_masks_cur[WM831X_NUM_IRQ_REGS];   /* Currently active value */
        int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */
 
@@ -272,8 +381,13 @@ struct wm831x {
 
        int num_gpio;
 
+       /* Used by the interrupt controller code to post writes */
+       int gpio_update[WM831X_NUM_GPIO_REGS];
+
        struct mutex auxadc_lock;
-       struct completion auxadc_done;
+       struct list_head auxadc_pending;
+       u16 auxadc_active;
+       wm831x_auxadc_read_fn auxadc_read;
 
        /* The WM831x has a security key blocking access to certain
         * registers.  The mutex is taken by the accessors for locking
@@ -300,5 +414,6 @@ void wm831x_device_exit(struct wm831x *wm831x);
 int wm831x_device_suspend(struct wm831x *wm831x);
 int wm831x_irq_init(struct wm831x *wm831x, int irq);
 void wm831x_irq_exit(struct wm831x *wm831x);
+void wm831x_auxadc_init(struct wm831x *wm831x);
 
 #endif
index ff42d70..0ba2459 100644 (file)
@@ -120,6 +120,9 @@ struct wm831x_pdata {
        /** Put the /IRQ line into CMOS mode */
        bool irq_cmos;
 
+       /** Disable the touchscreen */
+       bool disable_touch;
+
        int irq_base;
        int gpio_base;
        int gpio_defaults[WM831X_GPIO_NUM];
index 3172a1c..fd599f4 100644 (file)
@@ -962,6 +962,8 @@ int invalidate_inode_page(struct page *page);
 #ifdef CONFIG_MMU
 extern int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                        unsigned long address, unsigned int flags);
+extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
+                           unsigned long address, unsigned int fault_flags);
 #else
 static inline int handle_mm_fault(struct mm_struct *mm,
                        struct vm_area_struct *vma, unsigned long address,
@@ -971,6 +973,14 @@ static inline int handle_mm_fault(struct mm_struct *mm,
        BUG();
        return VM_FAULT_SIGBUS;
 }
+static inline int fixup_user_fault(struct task_struct *tsk,
+               struct mm_struct *mm, unsigned long address,
+               unsigned int fault_flags)
+{
+       /* should never happen if there's no MMU */
+       BUG();
+       return -EFAULT;
+}
 #endif
 
 extern int make_pages_present(unsigned long addr, unsigned long end);
@@ -988,8 +998,6 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 int get_user_pages_fast(unsigned long start, int nr_pages, int write,
                        struct page **pages);
 struct page *get_dump_page(unsigned long addr);
-extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
-                           unsigned long address, unsigned int fault_flags);
 
 extern int try_to_release_page(struct page * page, gfp_t gfp_mask);
 extern void do_invalidatepage(struct page *page, unsigned long offset);
@@ -1600,6 +1608,7 @@ enum mf_flags {
 };
 extern void memory_failure(unsigned long pfn, int trapno);
 extern int __memory_failure(unsigned long pfn, int trapno, int flags);
+extern void memory_failure_queue(unsigned long pfn, int trapno, int flags);
 extern int unpoison_memory(unsigned long pfn);
 extern int sysctl_memory_failure_early_kill;
 extern int sysctl_memory_failure_recovery;
index 027935c..774b895 100644 (file)
@@ -30,23 +30,61 @@ struct address_space;
  * moment. Note that we have no way to track which tasks are using
  * a page, though if it is a pagecache page, rmap structures can tell us
  * who is mapping it.
+ *
+ * The objects in struct page are organized in double word blocks in
+ * order to allows us to use atomic double word operations on portions
+ * of struct page. That is currently only used by slub but the arrangement
+ * allows the use of atomic double word operations on the flags/mapping
+ * and lru list pointers also.
  */
 struct page {
+       /* First double word block */
        unsigned long flags;            /* Atomic flags, some possibly
                                         * updated asynchronously */
-       atomic_t _count;                /* Usage count, see below. */
-       union {
-               atomic_t _mapcount;     /* Count of ptes mapped in mms,
-                                        * to show when page is mapped
-                                        * & limit reverse map searches.
+       struct address_space *mapping;  /* If low bit clear, points to
+                                        * inode address_space, or NULL.
+                                        * If page mapped as anonymous
+                                        * memory, low bit is set, and
+                                        * it points to anon_vma object:
+                                        * see PAGE_MAPPING_ANON below.
                                         */
-               struct {                /* SLUB */
-                       u16 inuse;
-                       u16 objects;
+       /* Second double word */
+       struct {
+               union {
+                       pgoff_t index;          /* Our offset within mapping. */
+                       void *freelist;         /* slub first free object */
+               };
+
+               union {
+                       /* Used for cmpxchg_double in slub */
+                       unsigned long counters;
+
+                       struct {
+
+                               union {
+                                       atomic_t _mapcount;     /* Count of ptes mapped in mms,
+                                                        * to show when page is mapped
+                                                        * & limit reverse map searches.
+                                                        */
+
+                                       struct {
+                                               unsigned inuse:16;
+                                               unsigned objects:15;
+                                               unsigned frozen:1;
+                                       };
+                               };
+                               atomic_t _count;                /* Usage count, see below. */
+                       };
                };
        };
+
+       /* Third double word block */
+       struct list_head lru;           /* Pageout list, eg. active_list
+                                        * protected by zone->lru_lock !
+                                        */
+
+       /* Remainder is not double word aligned */
        union {
-           struct {
                unsigned long private;          /* Mapping-private opaque data:
                                                 * usually used for buffer_heads
                                                 * if PagePrivate set; used for
@@ -54,27 +92,13 @@ struct page {
                                                 * indicates order in the buddy
                                                 * system if PG_buddy is set.
                                                 */
-               struct address_space *mapping;  /* If low bit clear, points to
-                                                * inode address_space, or NULL.
-                                                * If page mapped as anonymous
-                                                * memory, low bit is set, and
-                                                * it points to anon_vma object:
-                                                * see PAGE_MAPPING_ANON below.
-                                                */
-           };
 #if USE_SPLIT_PTLOCKS
-           spinlock_t ptl;
+               spinlock_t ptl;
 #endif
-           struct kmem_cache *slab;    /* SLUB: Pointer to slab */
-           struct page *first_page;    /* Compound tail pages */
-       };
-       union {
-               pgoff_t index;          /* Our offset within mapping. */
-               void *freelist;         /* SLUB: freelist req. slab lock */
+               struct kmem_cache *slab;        /* SLUB: Pointer to slab */
+               struct page *first_page;        /* Compound tail pages */
        };
-       struct list_head lru;           /* Pageout list, eg. active_list
-                                        * protected by zone->lru_lock !
-                                        */
+
        /*
         * On machines where all RAM is mapped into kernel address space,
         * we can simply calculate the virtual address. On machines with
@@ -100,7 +124,16 @@ struct page {
         */
        void *shadow;
 #endif
-};
+}
+/*
+ * If another subsystem starts using the double word pairing for atomic
+ * operations on struct page then it must change the #if to ensure
+ * proper alignment of the page struct.
+ */
+#if defined(CONFIG_SLUB) && defined(CONFIG_CMPXCHG_LOCAL)
+       __attribute__((__aligned__(2*sizeof(unsigned long))))
+#endif
+;
 
 typedef unsigned long __nocast vm_flags_t;
 
index ddee79b..0a7f619 100644 (file)
@@ -723,9 +723,8 @@ struct netdev_tc_txq {
  *
  * void (*ndo_set_rx_mode)(struct net_device *dev);
  *     This function is called device changes address list filtering.
- *
- * void (*ndo_set_multicast_list)(struct net_device *dev);
- *     This function is called when the multicast address list changes.
+ *     If driver handles unicast address filtering, it should set
+ *     IFF_UNICAST_FLT to its priv_flags.
  *
  * int (*ndo_set_mac_address)(struct net_device *dev, void *addr);
  *     This function  is called when the Media Access Control address
@@ -868,7 +867,6 @@ struct net_device_ops {
        void                    (*ndo_change_rx_flags)(struct net_device *dev,
                                                       int flags);
        void                    (*ndo_set_rx_mode)(struct net_device *dev);
-       void                    (*ndo_set_multicast_list)(struct net_device *dev);
        int                     (*ndo_set_mac_address)(struct net_device *dev,
                                                       void *addr);
        int                     (*ndo_validate_addr)(struct net_device *dev);
@@ -924,11 +922,15 @@ struct net_device_ops {
                                                       u16 xid,
                                                       struct scatterlist *sgl,
                                                       unsigned int sgc);
+#endif
+
+#if defined(CONFIG_LIBFCOE) || defined(CONFIG_LIBFCOE_MODULE)
 #define NETDEV_FCOE_WWNN 0
 #define NETDEV_FCOE_WWPN 1
        int                     (*ndo_fcoe_get_wwn)(struct net_device *dev,
                                                    u64 *wwn, int type);
 #endif
+
 #ifdef CONFIG_RFS_ACCEL
        int                     (*ndo_rx_flow_steer)(struct net_device *dev,
                                                     const struct sk_buff *skb,
index 0ca66e9..d1366f0 100644 (file)
@@ -2,6 +2,7 @@
 #define _XT_CONNLIMIT_H
 
 #include <linux/types.h>
+#include <linux/netfilter.h>
 
 struct xt_connlimit_data;
 
index 74b904d..e3c041d 100644 (file)
@@ -6,6 +6,7 @@
 #define _XT_CONNTRACK_H
 
 #include <linux/types.h>
+#include <linux/netfilter.h>
 #include <linux/netfilter/nf_conntrack_tuple_common.h>
 
 #define XT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
index c1f21a7..25fd7cf 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_NETFILTER_XT_IPRANGE_H 1
 
 #include <linux/types.h>
+#include <linux/netfilter.h>
 
 enum {
        IPRANGE_SRC     = 1 << 0,       /* match source IP address */
index adbf4bf..e08565d 100644 (file)
@@ -52,7 +52,7 @@ struct arpt_arp {
        struct in_addr smsk, tmsk;
 
        /* Device hw address length, src+target device addresses */
-       u_int8_t arhln, arhln_mask;
+       __u8 arhln, arhln_mask;
        struct arpt_devaddr_info src_devaddr;
        struct arpt_devaddr_info tgt_devaddr;
 
@@ -71,9 +71,9 @@ struct arpt_arp {
        unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
 
        /* Flags word */
-       u_int8_t flags;
+       __u8 flags;
        /* Inverse flags */
-       u_int16_t invflags;
+       __u16 invflags;
 };
 
 /* Values for "flag" field in struct arpt_ip (general arp structure).
@@ -102,9 +102,9 @@ struct arpt_entry
        struct arpt_arp arp;
 
        /* Size of arpt_entry + matches */
-       u_int16_t target_offset;
+       __u16 target_offset;
        /* Size of arpt_entry + matches + target */
-       u_int16_t next_offset;
+       __u16 next_offset;
 
        /* Back pointer */
        unsigned int comefrom;
@@ -260,8 +260,8 @@ extern unsigned int arpt_do_table(struct sk_buff *skb,
 
 struct compat_arpt_entry {
        struct arpt_arp arp;
-       u_int16_t target_offset;
-       u_int16_t next_offset;
+       __u16 target_offset;
+       __u16 next_offset;
        compat_uint_t comefrom;
        struct compat_xt_counters counters;
        unsigned char elems[0];
index 6f42536..0b09732 100644 (file)
@@ -11,6 +11,9 @@
 
 /* only for userspace compatibility */
 #ifndef __KERNEL__
+
+#include <limits.h> /* for INT_MIN, INT_MAX */
+
 /* IP Cache bits. */
 /* Src IP address. */
 #define NFC_DN_SRC             0x0001
index 29c7727..fa0946c 100644 (file)
@@ -9,6 +9,9 @@
 
 /* only for userspace compatibility */
 #ifndef __KERNEL__
+
+#include <limits.h> /* for INT_MIN, INT_MAX */
+
 /* IP Cache bits. */
 /* Src IP address. */
 #define NFC_IP_SRC             0x0001
index 64a5d95..db79231 100644 (file)
@@ -81,12 +81,12 @@ struct ipt_ip {
        unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
 
        /* Protocol, 0 = ANY */
-       u_int16_t proto;
+       __u16 proto;
 
        /* Flags word */
-       u_int8_t flags;
+       __u8 flags;
        /* Inverse flags */
-       u_int8_t invflags;
+       __u8 invflags;
 };
 
 /* Values for "flag" field in struct ipt_ip (general ip structure). */
@@ -114,9 +114,9 @@ struct ipt_entry {
        unsigned int nfcache;
 
        /* Size of ipt_entry + matches */
-       u_int16_t target_offset;
+       __u16 target_offset;
        /* Size of ipt_entry + matches + target */
-       u_int16_t next_offset;
+       __u16 next_offset;
 
        /* Back pointer */
        unsigned int comefrom;
@@ -149,9 +149,9 @@ struct ipt_entry {
 
 /* ICMP matching stuff */
 struct ipt_icmp {
-       u_int8_t type;                          /* type to match */
-       u_int8_t code[2];                       /* range of code */
-       u_int8_t invflags;                      /* Inverse flags */
+       __u8 type;                              /* type to match */
+       __u8 code[2];                           /* range of code */
+       __u8 invflags;                          /* Inverse flags */
 };
 
 /* Values for "inv" field for struct ipt_icmp. */
@@ -288,8 +288,8 @@ extern unsigned int ipt_do_table(struct sk_buff *skb,
 struct compat_ipt_entry {
        struct ipt_ip ip;
        compat_uint_t nfcache;
-       u_int16_t target_offset;
-       u_int16_t next_offset;
+       __u16 target_offset;
+       __u16 next_offset;
        compat_uint_t comefrom;
        struct compat_xt_counters counters;
        unsigned char elems[0];
index 1f7e300..57c0251 100644 (file)
@@ -12,6 +12,9 @@
 
 /* only for userspace compatibility */
 #ifndef __KERNEL__
+
+#include <limits.h> /* for INT_MIN, INT_MAX */
+
 /* IP Cache bits. */
 /* Src IP address. */
 #define NFC_IP6_SRC              0x0001
index c9784f7..f549adc 100644 (file)
@@ -81,14 +81,14 @@ struct ip6t_ip6 {
         *   MH do not match any packets.
         * - You also need to set IP6T_FLAGS_PROTO to "flags" to check protocol.
         */
-       u_int16_t proto;
+       __u16 proto;
        /* TOS to match iff flags & IP6T_F_TOS */
-       u_int8_t tos;
+       __u8 tos;
 
        /* Flags word */
-       u_int8_t flags;
+       __u8 flags;
        /* Inverse flags */
-       u_int8_t invflags;
+       __u8 invflags;
 };
 
 /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
@@ -118,9 +118,9 @@ struct ip6t_entry {
        unsigned int nfcache;
 
        /* Size of ipt_entry + matches */
-       u_int16_t target_offset;
+       __u16 target_offset;
        /* Size of ipt_entry + matches + target */
-       u_int16_t next_offset;
+       __u16 next_offset;
 
        /* Back pointer */
        unsigned int comefrom;
@@ -186,9 +186,9 @@ struct ip6t_error {
 
 /* ICMP matching stuff */
 struct ip6t_icmp {
-       u_int8_t type;                          /* type to match */
-       u_int8_t code[2];                       /* range of code */
-       u_int8_t invflags;                      /* Inverse flags */
+       __u8 type;                              /* type to match */
+       __u8 code[2];                           /* range of code */
+       __u8 invflags;                          /* Inverse flags */
 };
 
 /* Values for "inv" field for struct ipt_icmp. */
@@ -298,8 +298,8 @@ extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
 struct compat_ip6t_entry {
        struct ip6t_ip6 ipv6;
        compat_uint_t nfcache;
-       u_int16_t target_offset;
-       u_int16_t next_offset;
+       __u16 target_offset;
+       __u16 next_offset;
        compat_uint_t comefrom;
        struct compat_xt_counters counters;
        unsigned char elems[0];
index 2e17c5d..8180cd9 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __LINUX_NETLINK_H
 #define __LINUX_NETLINK_H
 
-#include <linux/socket.h> /* for sa_family_t */
+#include <linux/socket.h> /* for __kernel_sa_family_t */
 #include <linux/types.h>
 
 #define NETLINK_ROUTE          0       /* Routing/device hook                          */
@@ -29,7 +29,7 @@
 #define MAX_LINKS 32           
 
 struct sockaddr_nl {
-       sa_family_t     nl_family;      /* AF_NETLINK   */
+       __kernel_sa_family_t    nl_family;      /* AF_NETLINK   */
        unsigned short  nl_pad;         /* zero         */
        __u32           nl_pid;         /* port ID      */
                __u32           nl_groups;      /* multicast groups mask */
index 6939b32..af7313c 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef        NETROM_KERNEL_H
 #define        NETROM_KERNEL_H
 
+#include <linux/ax25.h>
+
 #define NETROM_MTU     236
 
 #define NETROM_T1      1
index f387919..8c6ee44 100644 (file)
@@ -29,6 +29,8 @@
 #define NFS_MNT_VERSION                1
 #define NFS_MNT3_VERSION       3
 
+#define NFS_PIPE_DIRNAME "/nfs"
+
 /*
  * NFS stats. The good thing with these values is that NFSv3 errors are
  * a superset of NFSv2 errors (with the exception of NFSERR_WFLUSH which
index a3c4bc8..76f99e8 100644 (file)
@@ -566,6 +566,7 @@ enum {
        NFSPROC4_CLNT_SECINFO_NO_NAME,
        NFSPROC4_CLNT_TEST_STATEID,
        NFSPROC4_CLNT_FREE_STATEID,
+       NFSPROC4_CLNT_GETDEVICELIST,
 };
 
 /* nfs41 types */
index 8b579be..eaac770 100644 (file)
@@ -99,9 +99,10 @@ struct nfs_open_context {
 
 struct nfs_open_dir_context {
        struct rpc_cred *cred;
+       unsigned long attr_gencount;
        __u64 dir_cookie;
        __u64 dup_cookie;
-       int duped;
+       signed char duped;
 };
 
 /*
@@ -568,12 +569,12 @@ extern struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type);
 extern int nfs3_proc_setacl(struct inode *inode, int type,
                            struct posix_acl *acl);
 extern int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
-               mode_t mode);
+               umode_t mode);
 extern void nfs3_forget_cached_acls(struct inode *inode);
 #else
 static inline int nfs3_proc_set_default_acl(struct inode *dir,
                                            struct inode *inode,
-                                           mode_t mode)
+                                           umode_t mode)
 {
        return 0;
 }
index 50a661f..b5479df 100644 (file)
@@ -131,8 +131,9 @@ struct nfs_server {
        struct fscache_cookie   *fscache;       /* superblock cookie */
 #endif
 
+       u32                     pnfs_blksize;   /* layout_blksize attr */
 #ifdef CONFIG_NFS_V4
-       u32                     attr_bitmask[2];/* V4 bitmask representing the set
+       u32                     attr_bitmask[3];/* V4 bitmask representing the set
                                                   of attributes supported on this
                                                   filesystem */
        u32                     cache_consistency_bitmask[2];
@@ -145,6 +146,7 @@ struct nfs_server {
                                                   filesystem */
        struct pnfs_layoutdriver_type  *pnfs_curr_ld; /* Active layout driver */
        struct rpc_wait_queue   roc_rpcwaitq;
+       void                    *pnfs_ld_data;  /* per mount point data */
 
        /* the following fields are protected by nfs_client->cl_lock */
        struct rb_root          state_owners;
index 5b11595..abd615d 100644 (file)
@@ -122,6 +122,7 @@ struct nfs_fsinfo {
        struct timespec         time_delta; /* server time granularity */
        __u32                   lease_time; /* in seconds */
        __u32                   layouttype; /* supported pnfs layout driver */
+       __u32                   blksize; /* preferred pnfs io block size */
 };
 
 struct nfs_fsstat {
@@ -235,6 +236,17 @@ struct nfs4_layoutget {
        gfp_t gfp_flags;
 };
 
+struct nfs4_getdevicelist_args {
+       const struct nfs_fh *fh;
+       u32 layoutclass;
+       struct nfs4_sequence_args seq_args;
+};
+
+struct nfs4_getdevicelist_res {
+       struct pnfs_devicelist *devlist;
+       struct nfs4_sequence_res seq_res;
+};
+
 struct nfs4_getdeviceinfo_args {
        struct pnfs_device *pdev;
        struct nfs4_sequence_args seq_args;
@@ -257,12 +269,13 @@ struct nfs4_layoutcommit_res {
        struct nfs_fattr *fattr;
        const struct nfs_server *server;
        struct nfs4_sequence_res seq_res;
+       int status;
 };
 
 struct nfs4_layoutcommit_data {
        struct rpc_task task;
        struct nfs_fattr fattr;
-       struct pnfs_layout_segment *lseg;
+       struct list_head lseg_list;
        struct rpc_cred *cred;
        struct nfs4_layoutcommit_args args;
        struct nfs4_layoutcommit_res res;
@@ -760,6 +773,11 @@ struct nfs3_getaclres {
        struct posix_acl *      acl_default;
 };
 
+struct nfs4_string {
+       unsigned int len;
+       char *data;
+};
+
 #ifdef CONFIG_NFS_V4
 
 typedef u64 clientid4;
@@ -943,18 +961,13 @@ struct nfs4_server_caps_arg {
 };
 
 struct nfs4_server_caps_res {
-       u32                             attr_bitmask[2];
+       u32                             attr_bitmask[3];
        u32                             acl_bitmask;
        u32                             has_links;
        u32                             has_symlinks;
        struct nfs4_sequence_res        seq_res;
 };
 
-struct nfs4_string {
-       unsigned int len;
-       char *data;
-};
-
 #define NFS4_PATHNAME_MAXCOMPONENTS 512
 struct nfs4_pathname {
        unsigned int ncomponents;
index bd716f8..9180dc5 100644 (file)
@@ -196,12 +196,13 @@ extern struct property *of_find_property(const struct device_node *np,
                                         const char *name,
                                         int *lenp);
 extern int of_property_read_u32_array(const struct device_node *np,
-                                     char *propname,
+                                     const char *propname,
                                      u32 *out_values,
                                      size_t sz);
 
-extern int of_property_read_string(struct device_node *np, char *propname,
-                                       const char **out_string);
+extern int of_property_read_string(struct device_node *np,
+                                  const char *propname,
+                                  const char **out_string);
 extern int of_device_is_compatible(const struct device_node *device,
                                   const char *);
 extern int of_device_is_available(const struct device_node *device);
@@ -242,21 +243,30 @@ static inline bool of_have_populated_dt(void)
 }
 
 static inline int of_property_read_u32_array(const struct device_node *np,
-                               char *propname, u32 *out_values, size_t sz)
+                                            const char *propname,
+                                            u32 *out_values, size_t sz)
 {
        return -ENOSYS;
 }
 
 static inline int of_property_read_string(struct device_node *np,
-                               char *propname, const char **out_string)
+                                         const char *propname,
+                                         const char **out_string)
 {
        return -ENOSYS;
 }
 
+static inline const void *of_get_property(const struct device_node *node,
+                               const char *name,
+                               int *lenp)
+{
+       return NULL;
+}
+
 #endif /* CONFIG_OF */
 
 static inline int of_property_read_u32(const struct device_node *np,
-                                      char *propname,
+                                      const char *propname,
                                       u32 *out_value)
 {
        return of_property_read_u32_array(np, propname, out_value, 1);
index aec8025..52280a2 100644 (file)
@@ -57,6 +57,8 @@ extern int of_mm_gpiochip_add(struct device_node *np,
 extern void of_gpiochip_add(struct gpio_chip *gc);
 extern void of_gpiochip_remove(struct gpio_chip *gc);
 extern struct gpio_chip *of_node_to_gpiochip(struct device_node *np);
+extern int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
+                               const void *gpio_spec, u32 *flags);
 
 #else /* CONFIG_OF_GPIO */
 
@@ -72,6 +74,13 @@ static inline unsigned int of_gpio_count(struct device_node *np)
        return 0;
 }
 
+static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
+                                      struct device_node *np,
+                                      const void *gpio_spec, u32 *flags)
+{
+       return -ENOSYS;
+}
+
 static inline void of_gpiochip_add(struct gpio_chip *gc) { }
 static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
 
index e6955f5..cd2e61c 100644 (file)
@@ -63,6 +63,9 @@ extern int of_irq_map_one(struct device_node *device, int index,
 extern unsigned int irq_create_of_mapping(struct device_node *controller,
                                          const u32 *intspec,
                                          unsigned int intsize);
+#ifdef CONFIG_IRQ_DOMAIN
+extern void irq_dispose_mapping(unsigned int irq);
+#endif
 extern int of_irq_to_resource(struct device_node *dev, int index,
                              struct resource *r);
 extern int of_irq_count(struct device_node *dev);
@@ -70,6 +73,7 @@ extern int of_irq_to_resource_table(struct device_node *dev,
                struct resource *res, int nr_irqs);
 extern struct device_node *of_irq_find_parent(struct device_node *child);
 
+
 #endif /* CONFIG_OF_IRQ */
 #endif /* CONFIG_OF */
 #endif /* __OF_IRQ_H */
index e913081..f474641 100644 (file)
@@ -9,6 +9,7 @@
 
 #ifdef CONFIG_OF_NET
 #include <linux/of.h>
+extern const int of_get_phy_mode(struct device_node *np);
 extern const void *of_get_mac_address(struct device_node *np);
 #endif
 
index 3e5a1b1..e90a673 100644 (file)
@@ -124,9 +124,6 @@ enum pageflags {
 
        /* SLOB */
        PG_slob_free = PG_private,
-
-       /* SLUB */
-       PG_slub_frozen = PG_active,
 };
 
 #ifndef __GENERATING_BOUNDS_H
@@ -212,8 +209,6 @@ PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked)
 
 __PAGEFLAG(SlobFree, slob_free)
 
-__PAGEFLAG(SlubFrozen, slub_frozen)
-
 /*
  * Private page markings that may be used by the filesystem that owns the page
  * for its own purposes.
index 3a5626d..f27893b 100644 (file)
@@ -843,8 +843,8 @@ void pci_enable_ido(struct pci_dev *dev, unsigned long type);
 void pci_disable_ido(struct pci_dev *dev, unsigned long type);
 
 enum pci_obff_signal_type {
-       PCI_EXP_OBFF_SIGNAL_L0,
-       PCI_EXP_OBFF_SIGNAL_ALWAYS,
+       PCI_EXP_OBFF_SIGNAL_L0 = 0,
+       PCI_EXP_OBFF_SIGNAL_ALWAYS = 1,
 };
 int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type);
 void pci_disable_obff(struct pci_dev *dev);
@@ -879,7 +879,7 @@ void pdev_enable_device(struct pci_dev *);
 void pdev_sort_resources(struct pci_dev *, struct resource_list *);
 int pci_enable_resources(struct pci_dev *, int mask);
 void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
-                   int (*)(struct pci_dev *, u8, u8));
+                   int (*)(const struct pci_dev *, u8, u8));
 #define HAVE_PCI_REQ_REGIONS   2
 int __must_check pci_request_regions(struct pci_dev *, const char *);
 int __must_check pci_request_regions_exclusive(struct pci_dev *, const char *);
index b00c4ec..ae96bbe 100644 (file)
 #define PCI_DEVICE_ID_INTEL_ICH10_5    0x3a60
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN      0x3b00
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX      0x3b1f
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB0  0x3c20
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB1  0x3c21
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB2  0x3c22
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB3  0x3c23
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB4  0x3c24
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB5  0x3c25
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB6  0x3c26
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB7  0x3c27
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB8  0x3c2e
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB9  0x3c2f
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB   0x402f
 #define PCI_DEVICE_ID_INTEL_5100_16    0x65f0
 #define PCI_DEVICE_ID_INTEL_5100_21    0x65f5
index 6fb1384..f53a416 100644 (file)
@@ -24,6 +24,7 @@
 #define LINUX_PHONET_H
 
 #include <linux/types.h>
+#include <linux/socket.h>
 
 /* Automatic protocol selection */
 #define PN_PROTO_TRANSPORT     0
@@ -96,11 +97,11 @@ struct phonetmsg {
 
 /* Phonet socket address structure */
 struct sockaddr_pn {
-       sa_family_t spn_family;
+       __kernel_sa_family_t spn_family;
        __u8 spn_obj;
        __u8 spn_dev;
        __u8 spn_resource;
-       __u8 spn_zero[sizeof(struct sockaddr) - sizeof(sa_family_t) - 3];
+       __u8 spn_zero[sizeof(struct sockaddr) - sizeof(__kernel_sa_family_t) - 3];
 } __attribute__((packed));
 
 /* Well known address */
index ad51863..54fc413 100644 (file)
@@ -53,6 +53,7 @@
 
 /* Interface Mode definitions */
 typedef enum {
+       PHY_INTERFACE_MODE_NA,
        PHY_INTERFACE_MODE_MII,
        PHY_INTERFACE_MODE_GMII,
        PHY_INTERFACE_MODE_SGMII,
@@ -62,7 +63,8 @@ typedef enum {
        PHY_INTERFACE_MODE_RGMII_ID,
        PHY_INTERFACE_MODE_RGMII_RXID,
        PHY_INTERFACE_MODE_RGMII_TXID,
-       PHY_INTERFACE_MODE_RTBI
+       PHY_INTERFACE_MODE_RTBI,
+       PHY_INTERFACE_MODE_SMII,
 } phy_interface_t;
 
 
diff --git a/include/linux/platform_data/ntc_thermistor.h b/include/linux/platform_data/ntc_thermistor.h
new file mode 100644 (file)
index 0000000..abd2862
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * ntc_thermistor.h - NTC Thermistors
+ *
+ *  Copyright (C) 2010 Samsung Electronics
+ *  MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _LINUX_NTC_H
+#define _LINUX_NTC_H
+
+enum ntc_thermistor_type {
+       TYPE_NCPXXWB473,
+       TYPE_NCPXXWL333,
+};
+
+struct ntc_thermistor_platform_data {
+       /*
+        * One (not both) of read_uV and read_ohm should be provided and only
+        * one of the two should be provided.
+        * Both functions should return negative value for an error case.
+        *
+        * pullup_uV, pullup_ohm, pulldown_ohm, and connect are required to use
+        * read_uV()
+        *
+        * How to setup pullup_ohm, pulldown_ohm, and connect is
+        * described at Documentation/hwmon/ntc
+        *
+        * pullup/down_ohm: 0 for infinite / not-connected
+        */
+       int (*read_uV)(void);
+       unsigned int pullup_uV;
+
+       unsigned int pullup_ohm;
+       unsigned int pulldown_ohm;
+       enum { NTC_CONNECTED_POSITIVE, NTC_CONNECTED_GROUND } connect;
+
+       int (*read_ohm)(void);
+};
+
+#endif /* _LINUX_NTC_H */
index 9a53b99..b768110 100644 (file)
@@ -9,6 +9,7 @@
 #define __LINUX_POSIX_ACL_H
 
 #include <linux/slab.h>
+#include <linux/rcupdate.h>
 
 #define ACL_UNDEFINED_ID       (-1)
 
@@ -38,7 +39,10 @@ struct posix_acl_entry {
 };
 
 struct posix_acl {
-       atomic_t                a_refcount;
+       union {
+               atomic_t                a_refcount;
+               struct rcu_head         a_rcu;
+       };
        unsigned int            a_count;
        struct posix_acl_entry  a_entries[0];
 };
@@ -65,7 +69,7 @@ static inline void
 posix_acl_release(struct posix_acl *acl)
 {
        if (acl && atomic_dec_and_test(&acl->a_refcount))
-               kfree(acl);
+               kfree_rcu(acl, a_rcu);
 }
 
 
@@ -75,29 +79,31 @@ extern void posix_acl_init(struct posix_acl *, int);
 extern struct posix_acl *posix_acl_alloc(int, gfp_t);
 extern int posix_acl_valid(const struct posix_acl *);
 extern int posix_acl_permission(struct inode *, const struct posix_acl *, int);
-extern struct posix_acl *posix_acl_from_mode(mode_t, gfp_t);
-extern int posix_acl_equiv_mode(const struct posix_acl *, mode_t *);
-extern int posix_acl_create(struct posix_acl **, gfp_t, mode_t *);
-extern int posix_acl_chmod(struct posix_acl **, gfp_t, mode_t);
+extern struct posix_acl *posix_acl_from_mode(umode_t, gfp_t);
+extern int posix_acl_equiv_mode(const struct posix_acl *, umode_t *);
+extern int posix_acl_create(struct posix_acl **, gfp_t, umode_t *);
+extern int posix_acl_chmod(struct posix_acl **, gfp_t, umode_t);
 
 extern struct posix_acl *get_posix_acl(struct inode *, int);
 extern int set_posix_acl(struct inode *, int, struct posix_acl *);
 
 #ifdef CONFIG_FS_POSIX_ACL
-static inline struct posix_acl *get_cached_acl(struct inode *inode, int type)
+static inline struct posix_acl **acl_by_type(struct inode *inode, int type)
 {
-       struct posix_acl **p, *acl;
        switch (type) {
        case ACL_TYPE_ACCESS:
-               p = &inode->i_acl;
-               break;
+               return &inode->i_acl;
        case ACL_TYPE_DEFAULT:
-               p = &inode->i_default_acl;
-               break;
+               return &inode->i_default_acl;
        default:
-               return ERR_PTR(-EINVAL);
+               BUG();
        }
-       acl = ACCESS_ONCE(*p);
+}
+
+static inline struct posix_acl *get_cached_acl(struct inode *inode, int type)
+{
+       struct posix_acl **p = acl_by_type(inode, type);
+       struct posix_acl *acl = ACCESS_ONCE(*p);
        if (acl) {
                spin_lock(&inode->i_lock);
                acl = *p;
@@ -108,41 +114,20 @@ static inline struct posix_acl *get_cached_acl(struct inode *inode, int type)
        return acl;
 }
 
-static inline int negative_cached_acl(struct inode *inode, int type)
+static inline struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type)
 {
-       struct posix_acl **p, *acl;
-       switch (type) {
-       case ACL_TYPE_ACCESS:
-               p = &inode->i_acl;
-               break;
-       case ACL_TYPE_DEFAULT:
-               p = &inode->i_default_acl;
-               break;
-       default:
-               BUG();
-       }
-       acl = ACCESS_ONCE(*p);
-       if (acl)
-               return 0;
-       return 1;
+       return rcu_dereference(*acl_by_type(inode, type));
 }
 
 static inline void set_cached_acl(struct inode *inode,
                                  int type,
                                  struct posix_acl *acl)
 {
-       struct posix_acl *old = NULL;
+       struct posix_acl **p = acl_by_type(inode, type);
+       struct posix_acl *old;
        spin_lock(&inode->i_lock);
-       switch (type) {
-       case ACL_TYPE_ACCESS:
-               old = inode->i_acl;
-               inode->i_acl = posix_acl_dup(acl);
-               break;
-       case ACL_TYPE_DEFAULT:
-               old = inode->i_default_acl;
-               inode->i_default_acl = posix_acl_dup(acl);
-               break;
-       }
+       old = *p;
+       rcu_assign_pointer(*p, posix_acl_dup(acl));
        spin_unlock(&inode->i_lock);
        if (old != ACL_NOT_CACHED)
                posix_acl_release(old);
@@ -150,18 +135,11 @@ static inline void set_cached_acl(struct inode *inode,
 
 static inline void forget_cached_acl(struct inode *inode, int type)
 {
-       struct posix_acl *old = NULL;
+       struct posix_acl **p = acl_by_type(inode, type);
+       struct posix_acl *old;
        spin_lock(&inode->i_lock);
-       switch (type) {
-       case ACL_TYPE_ACCESS:
-               old = inode->i_acl;
-               inode->i_acl = ACL_NOT_CACHED;
-               break;
-       case ACL_TYPE_DEFAULT:
-               old = inode->i_default_acl;
-               inode->i_default_acl = ACL_NOT_CACHED;
-               break;
-       }
+       old = *p;
+       *p = ACL_NOT_CACHED;
        spin_unlock(&inode->i_lock);
        if (old != ACL_NOT_CACHED)
                posix_acl_release(old);
index b0843b6..1398eb0 100644 (file)
  * @battery_detect:            GPIO which is used to detect battery presence
  * @battery_detect_present:    gpio state when battery is present (0 / 1)
  * @i2c_retry_count:           # of times to retry on i2c IO failure
+ * @poll_retry_count:          # of times to retry looking for new status after
+ *                             external change notification
  */
 struct bq20z75_platform_data {
        int battery_detect;
        int battery_detect_present;
        int i2c_retry_count;
+       int poll_retry_count;
 };
 
 #endif
index 7995deb..fe99211 100644 (file)
 #ifndef __MAX17042_BATTERY_H_
 #define __MAX17042_BATTERY_H_
 
+#define MAX17042_STATUS_BattAbsent     (1 << 3)
+#define MAX17042_BATTERY_FULL  (100)
+#define MAX17042_DEFAULT_SNS_RESISTOR  (10000)
+
+enum max17042_register {
+       MAX17042_STATUS         = 0x00,
+       MAX17042_VALRT_Th       = 0x01,
+       MAX17042_TALRT_Th       = 0x02,
+       MAX17042_SALRT_Th       = 0x03,
+       MAX17042_AtRate         = 0x04,
+       MAX17042_RepCap         = 0x05,
+       MAX17042_RepSOC         = 0x06,
+       MAX17042_Age            = 0x07,
+       MAX17042_TEMP           = 0x08,
+       MAX17042_VCELL          = 0x09,
+       MAX17042_Current        = 0x0A,
+       MAX17042_AvgCurrent     = 0x0B,
+       MAX17042_Qresidual      = 0x0C,
+       MAX17042_SOC            = 0x0D,
+       MAX17042_AvSOC          = 0x0E,
+       MAX17042_RemCap         = 0x0F,
+       MAX17402_FullCAP        = 0x10,
+       MAX17042_TTE            = 0x11,
+       MAX17042_V_empty        = 0x12,
+
+       MAX17042_RSLOW          = 0x14,
+
+       MAX17042_AvgTA          = 0x16,
+       MAX17042_Cycles         = 0x17,
+       MAX17042_DesignCap      = 0x18,
+       MAX17042_AvgVCELL       = 0x19,
+       MAX17042_MinMaxTemp     = 0x1A,
+       MAX17042_MinMaxVolt     = 0x1B,
+       MAX17042_MinMaxCurr     = 0x1C,
+       MAX17042_CONFIG         = 0x1D,
+       MAX17042_ICHGTerm       = 0x1E,
+       MAX17042_AvCap          = 0x1F,
+       MAX17042_ManName        = 0x20,
+       MAX17042_DevName        = 0x21,
+       MAX17042_DevChem        = 0x22,
+
+       MAX17042_TempNom        = 0x24,
+       MAX17042_TempCold       = 0x25,
+       MAX17042_TempHot        = 0x26,
+       MAX17042_AIN            = 0x27,
+       MAX17042_LearnCFG       = 0x28,
+       MAX17042_SHFTCFG        = 0x29,
+       MAX17042_RelaxCFG       = 0x2A,
+       MAX17042_MiscCFG        = 0x2B,
+       MAX17042_TGAIN          = 0x2C,
+       MAx17042_TOFF           = 0x2D,
+       MAX17042_CGAIN          = 0x2E,
+       MAX17042_COFF           = 0x2F,
+
+       MAX17042_Q_empty        = 0x33,
+       MAX17042_T_empty        = 0x34,
+
+       MAX17042_RCOMP0         = 0x38,
+       MAX17042_TempCo         = 0x39,
+       MAX17042_Rx             = 0x3A,
+       MAX17042_T_empty0       = 0x3B,
+       MAX17042_TaskPeriod     = 0x3C,
+       MAX17042_FSTAT          = 0x3D,
+
+       MAX17042_SHDNTIMER      = 0x3F,
+
+       MAX17042_VFRemCap       = 0x4A,
+
+       MAX17042_QH             = 0x4D,
+       MAX17042_QL             = 0x4E,
+};
+
+/*
+ * used for setting a register to a desired value
+ * addr : address for a register
+ * data : setting value for the register
+ */
+struct max17042_reg_data {
+       u8 addr;
+       u16 data;
+};
+
 struct max17042_platform_data {
+       struct max17042_reg_data *init_data;
+       int num_init_data; /* Number of enties in init_data array */
        bool enable_current_sense;
+
+       /*
+        * R_sns in micro-ohms.
+        * default 10000 (if r_sns = 0) as it is the recommended value by
+        * the datasheet although it can be changed by board designers.
+        */
+       unsigned int r_sns;
 };
 
 #endif /* __MAX17042_BATTERY_H_ */
index 2455ef2..cc03bbf 100644 (file)
@@ -38,9 +38,12 @@ struct pstore_info {
        int             (*open)(struct pstore_info *psi);
        int             (*close)(struct pstore_info *psi);
        ssize_t         (*read)(u64 *id, enum pstore_type_id *type,
-                       struct timespec *time);
-       u64             (*write)(enum pstore_type_id type, size_t size);
-       int             (*erase)(u64 id);
+                       struct timespec *time, struct pstore_info *psi);
+       u64             (*write)(enum pstore_type_id type, unsigned int part,
+                       size_t size, struct pstore_info *psi);
+       int             (*erase)(enum pstore_type_id type, u64 id,
+                       struct pstore_info *psi);
+       void            *data;
 };
 
 #ifdef CONFIG_PSTORE
index 23241c2..9d4539c 100644 (file)
  * when it is shrunk, before we rcu free the node. See shrink code for
  * details.
  */
-#define RADIX_TREE_INDIRECT_PTR        1
+#define RADIX_TREE_INDIRECT_PTR                1
+/*
+ * A common use of the radix tree is to store pointers to struct pages;
+ * but shmem/tmpfs needs also to store swap entries in the same tree:
+ * those are marked as exceptional entries to distinguish them.
+ * EXCEPTIONAL_ENTRY tests the bit, EXCEPTIONAL_SHIFT shifts content past it.
+ */
+#define RADIX_TREE_EXCEPTIONAL_ENTRY   2
+#define RADIX_TREE_EXCEPTIONAL_SHIFT   2
 
 #define radix_tree_indirect_to_ptr(ptr) \
        radix_tree_indirect_to_ptr((void __force *)(ptr))
@@ -173,6 +181,28 @@ static inline int radix_tree_deref_retry(void *arg)
        return unlikely((unsigned long)arg & RADIX_TREE_INDIRECT_PTR);
 }
 
+/**
+ * radix_tree_exceptional_entry        - radix_tree_deref_slot gave exceptional entry?
+ * @arg:       value returned by radix_tree_deref_slot
+ * Returns:    0 if well-aligned pointer, non-0 if exceptional entry.
+ */
+static inline int radix_tree_exceptional_entry(void *arg)
+{
+       /* Not unlikely because radix_tree_exception often tested first */
+       return (unsigned long)arg & RADIX_TREE_EXCEPTIONAL_ENTRY;
+}
+
+/**
+ * radix_tree_exception        - radix_tree_deref_slot returned either exception?
+ * @arg:       value returned by radix_tree_deref_slot
+ * Returns:    0 if well-aligned pointer, non-0 if either kind of exception.
+ */
+static inline int radix_tree_exception(void *arg)
+{
+       return unlikely((unsigned long)arg &
+               (RADIX_TREE_INDIRECT_PTR | RADIX_TREE_EXCEPTIONAL_ENTRY));
+}
+
 /**
  * radix_tree_replace_slot     - replace item in a slot
  * @pslot:     pointer to slot, returned by radix_tree_lookup_slot
@@ -194,8 +224,8 @@ void *radix_tree_delete(struct radix_tree_root *, unsigned long);
 unsigned int
 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
                        unsigned long first_index, unsigned int max_items);
-unsigned int
-radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
+unsigned int radix_tree_gang_lookup_slot(struct radix_tree_root *root,
+                       void ***results, unsigned long *indices,
                        unsigned long first_index, unsigned int max_items);
 unsigned long radix_tree_next_hole(struct radix_tree_root *root,
                                unsigned long index, unsigned long max_scan);
@@ -222,6 +252,7 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
                unsigned long nr_to_tag,
                unsigned int fromtag, unsigned int totag);
 int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag);
+unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item);
 
 static inline void radix_tree_preload_end(void)
 {
index ce29a04..d13059f 100644 (file)
@@ -57,18 +57,6 @@ extern void add_interrupt_randomness(int irq);
 extern void get_random_bytes(void *buf, int nbytes);
 void generate_random_uuid(unsigned char uuid_out[16]);
 
-extern __u32 secure_ip_id(__be32 daddr);
-extern __u32 secure_ipv6_id(const __be32 daddr[4]);
-extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
-extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
-                                     __be16 dport);
-extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
-                                       __be16 sport, __be16 dport);
-extern __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
-                                         __be16 sport, __be16 dport);
-extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
-                                      __be16 sport, __be16 dport);
-
 #ifndef MODULE
 extern const struct file_operations random_fops, urandom_fops;
 #endif
index 9e87c1c..26f6ea4 100644 (file)
@@ -122,6 +122,9 @@ struct regulator;
 struct regulator_bulk_data {
        const char *supply;
        struct regulator *consumer;
+
+       /* Internal use */
+       int ret;
 };
 
 #if defined(CONFIG_REGULATOR)
index 6c433b8..1a80bc7 100644 (file)
@@ -188,18 +188,16 @@ struct regulator_dev {
 
        /* lists we belong to */
        struct list_head list; /* list of all regulators */
-       struct list_head slist; /* list of supplied regulators */
 
        /* lists we own */
        struct list_head consumer_list; /* consumers we supply */
-       struct list_head supply_list; /* regulators we supply */
 
        struct blocking_notifier_head notifier;
        struct mutex mutex; /* consumer lock */
        struct module *owner;
        struct device dev;
        struct regulation_constraints *constraints;
-       struct regulator_dev *supply;   /* for tree */
+       struct regulator *supply;       /* for tree */
 
        void *reg_data;         /* regulator_dev data */
 
index c7b4b18..1fcfe95 100644 (file)
@@ -7,6 +7,9 @@
 #ifndef        ROSE_KERNEL_H
 #define        ROSE_KERNEL_H
 
+#include <linux/socket.h>
+#include <linux/ax25.h>
+
 #define ROSE_MTU       251
 
 #define ROSE_MAX_DIGIS 6
@@ -44,7 +47,7 @@ typedef struct {
 } rose_address;
 
 struct sockaddr_rose {
-       sa_family_t     srose_family;
+       __kernel_sa_family_t srose_family;
        rose_address    srose_addr;
        ax25_address    srose_call;
        int             srose_ndigis;
@@ -52,7 +55,7 @@ struct sockaddr_rose {
 };
 
 struct full_sockaddr_rose {
-       sa_family_t     srose_family;
+       __kernel_sa_family_t srose_family;
        rose_address    srose_addr;
        ax25_address    srose_call;
        unsigned int    srose_ndigis;
index 20b03bf..4ac2c05 100644 (file)
@@ -1767,6 +1767,7 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *
 #define PF_DUMPCORE    0x00000200      /* dumped core */
 #define PF_SIGNALED    0x00000400      /* killed by a signal */
 #define PF_MEMALLOC    0x00000800      /* Allocating memory */
+#define PF_NPROC_EXCEEDED 0x00001000   /* set_user noticed that RLIMIT_NPROC was exceeded */
 #define PF_USED_MATH   0x00002000      /* if unset the fpu must be initialized before use */
 #define PF_FREEZING    0x00004000      /* freeze in progress. do not account to load */
 #define PF_NOFREEZE    0x00008000      /* this thread should not be frozen */
index a2afc9f..8bffe9a 100644 (file)
@@ -8,6 +8,8 @@
  * Generic header for SuperH SCI(F) (used by sh/sh64/h8300 and related parts)
  */
 
+#define SCIx_NOT_SUPPORTED     (-1)
+
 enum {
        SCBRR_ALGO_1,           /* ((clk + 16 * bps) / (16 * bps) - 1) */
        SCBRR_ALGO_2,           /* ((clk + 16 * bps) / (32 * bps) - 1) */
@@ -25,6 +27,28 @@ enum {
 #define SCSCR_CKE1     (1 << 1)
 #define SCSCR_CKE0     (1 << 0)
 
+/* SCxSR SCI */
+#define SCI_TDRE  0x80
+#define SCI_RDRF  0x40
+#define SCI_ORER  0x20
+#define SCI_FER   0x10
+#define SCI_PER   0x08
+#define SCI_TEND  0x04
+
+#define SCI_DEFAULT_ERROR_MASK (SCI_PER | SCI_FER)
+
+/* SCxSR SCIF */
+#define SCIF_ER    0x0080
+#define SCIF_TEND  0x0040
+#define SCIF_TDFE  0x0020
+#define SCIF_BRK   0x0010
+#define SCIF_FER   0x0008
+#define SCIF_PER   0x0004
+#define SCIF_RDF   0x0002
+#define SCIF_DR    0x0001
+
+#define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
+
 /* Offsets into the sci_port->irqs array */
 enum {
        SCIx_ERI_IRQ,
@@ -32,6 +56,24 @@ enum {
        SCIx_TXI_IRQ,
        SCIx_BRI_IRQ,
        SCIx_NR_IRQS,
+
+       SCIx_MUX_IRQ = SCIx_NR_IRQS,    /* special case */
+};
+
+enum {
+       SCIx_PROBE_REGTYPE,
+
+       SCIx_SCI_REGTYPE,
+       SCIx_IRDA_REGTYPE,
+       SCIx_SCIFA_REGTYPE,
+       SCIx_SCIFB_REGTYPE,
+       SCIx_SH3_SCIF_REGTYPE,
+       SCIx_SH4_SCIF_REGTYPE,
+       SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
+       SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+       SCIx_SH7705_SCIF_REGTYPE,
+
+       SCIx_NR_REGTYPES,
 };
 
 #define SCIx_IRQ_MUXED(irq)            \
@@ -42,8 +84,29 @@ enum {
        [SCIx_BRI_IRQ]  = (irq),        \
 }
 
+#define SCIx_IRQ_IS_MUXED(port)                        \
+       ((port)->cfg->irqs[SCIx_ERI_IRQ] ==     \
+        (port)->cfg->irqs[SCIx_RXI_IRQ]) ||    \
+       ((port)->cfg->irqs[SCIx_ERI_IRQ] &&     \
+        !(port)->cfg->irqs[SCIx_RXI_IRQ])
+/*
+ * SCI register subset common for all port types.
+ * Not all registers will exist on all parts.
+ */
+enum {
+       SCSMR, SCBRR, SCSCR, SCxSR,
+       SCFCR, SCFDR, SCxTDR, SCxRDR,
+       SCLSR, SCTFDR, SCRFDR, SCSPTR,
+
+       SCIx_NR_REGS,
+};
+
 struct device;
 
+struct plat_sci_port_ops {
+       void (*init_pins)(struct uart_port *, unsigned int cflag);
+};
+
 /*
  * Platform device specific platform_data struct
  */
@@ -56,6 +119,18 @@ struct plat_sci_port {
        unsigned int    scbrr_algo_id;          /* SCBRR calculation algo */
        unsigned int    scscr;                  /* SCSCR initialization */
 
+       /*
+        * Platform overrides if necessary, defaults otherwise.
+        */
+       int             overrun_bit;
+       unsigned int    error_mask;
+
+       int             port_reg;
+       unsigned char   regshift;
+       unsigned char   regtype;
+
+       struct plat_sci_port_ops        *ops;
+
        struct device   *dma_dev;
 
        unsigned int    dma_slave_tx;
index 9a52f72..3ccf186 100644 (file)
@@ -147,4 +147,8 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
 int sh_clk_div6_register(struct clk *clks, int nr);
 int sh_clk_div6_reparent_register(struct clk *clks, int nr);
 
+#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
+#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
+#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk }
+
 #endif /* __SH_CLOCK_H */
index b08cd4e..cb2dd11 100644 (file)
@@ -62,6 +62,12 @@ struct sh_dmae_pdata {
        const unsigned int *ts_shift;
        int ts_shift_num;
        u16 dmaor_init;
+       unsigned int chcr_offset;
+       u32 chcr_ie_bit;
+
+       unsigned int dmaor_is_32bit:1;
+       unsigned int needs_tend_set:1;
+       unsigned int no_dmars:1;
 };
 
 /* DMA register */
@@ -71,6 +77,8 @@ struct sh_dmae_pdata {
 #define CHCR   0x0C
 #define DMAOR  0x40
 
+#define TEND   0x18 /* USB-DMAC */
+
 /* DMAOR definitions */
 #define DMAOR_AE       0x00000004
 #define DMAOR_NMIF     0x00000002
index 7d27ffd..92808b8 100644 (file)
@@ -95,6 +95,9 @@ struct shmid_kernel /* private to the kernel */
        pid_t                   shm_cprid;
        pid_t                   shm_lprid;
        struct user_struct      *mlock_user;
+
+       /* The task created the shm object.  NULL if the task is dead. */
+       struct task_struct      *shm_creator;
 };
 
 /* shm_mode upper byte flags */
index aa08fa8..9291ac3 100644 (file)
@@ -8,22 +8,15 @@
 
 /* inode in-kernel data */
 
-#define SHMEM_NR_DIRECT 16
-
-#define SHMEM_SYMLINK_INLINE_LEN (SHMEM_NR_DIRECT * sizeof(swp_entry_t))
-
 struct shmem_inode_info {
        spinlock_t              lock;
        unsigned long           flags;
        unsigned long           alloced;        /* data pages alloced to file */
-       unsigned long           swapped;        /* subtotal assigned to swap */
-       unsigned long           next_index;     /* highest alloced index + 1 */
-       struct shared_policy    policy;         /* NUMA memory alloc policy */
-       struct page             *i_indirect;    /* top indirect blocks page */
        union {
-               swp_entry_t     i_direct[SHMEM_NR_DIRECT]; /* first blocks */
-               char            inline_symlink[SHMEM_SYMLINK_INLINE_LEN];
+               unsigned long   swapped;        /* subtotal assigned to swap */
+               char            *symlink;       /* unswappable short symlink */
        };
+       struct shared_policy    policy;         /* NUMA memory alloc policy */
        struct list_head        swaplist;       /* chain of maybes on swap */
        struct list_head        xattr_list;     /* list of shmem_xattr */
        struct inode            vfs_inode;
@@ -49,7 +42,7 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
 /*
  * Functions in mm/shmem.c called directly from elsewhere:
  */
-extern int init_tmpfs(void);
+extern int shmem_init(void);
 extern int shmem_fill_super(struct super_block *sb, void *data, int silent);
 extern struct file *shmem_file_setup(const char *name,
                                        loff_t size, unsigned long flags);
@@ -59,8 +52,6 @@ extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
                                        pgoff_t index, gfp_t gfp_mask);
 extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end);
 extern int shmem_unuse(swp_entry_t entry, struct page *page);
-extern void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff,
-                                       struct page **pagep, swp_entry_t *ent);
 
 static inline struct page *shmem_read_mapping_page(
                                struct address_space *mapping, pgoff_t index)
index 7b996ed..8d42628 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/rcupdate.h>
 #include <linux/dmaengine.h>
 #include <linux/hrtimer.h>
+#include <linux/dma-mapping.h>
 
 /* Don't change this without changing skb_csum_unnecessary! */
 #define CHECKSUM_NONE 0
@@ -322,6 +323,8 @@ typedef unsigned char *sk_buff_data_t;
  *     @queue_mapping: Queue mapping for multiqueue devices
  *     @ndisc_nodetype: router type (from link layer)
  *     @ooo_okay: allow the mapping of a socket to a queue to be changed
+ *     @l4_rxhash: indicate rxhash is a canonical 4-tuple hash over transport
+ *             ports.
  *     @dma_cookie: a cookie to one of several possible DMA operations
  *             done by skb DMA functions
  *     @secmark: security marking
@@ -414,6 +417,7 @@ struct sk_buff {
        __u8                    ndisc_nodetype:2;
 #endif
        __u8                    ooo_okay:1;
+       __u8                    l4_rxhash:1;
        kmemcheck_bitfield_end(flags2);
 
        /* 0/13 bit hole */
@@ -572,11 +576,11 @@ extern unsigned int   skb_find_text(struct sk_buff *skb, unsigned int from,
                                    unsigned int to, struct ts_config *config,
                                    struct ts_state *state);
 
-extern __u32 __skb_get_rxhash(struct sk_buff *skb);
+extern void __skb_get_rxhash(struct sk_buff *skb);
 static inline __u32 skb_get_rxhash(struct sk_buff *skb)
 {
        if (!skb->rxhash)
-               skb->rxhash = __skb_get_rxhash(skb);
+               __skb_get_rxhash(skb);
 
        return skb->rxhash;
 }
@@ -1126,14 +1130,47 @@ static inline int skb_pagelen(const struct sk_buff *skb)
        return len + skb_headlen(skb);
 }
 
-static inline void skb_fill_page_desc(struct sk_buff *skb, int i,
-                                     struct page *page, int off, int size)
+/**
+ * __skb_fill_page_desc - initialise a paged fragment in an skb
+ * @skb: buffer containing fragment to be initialised
+ * @i: paged fragment index to initialise
+ * @page: the page to use for this fragment
+ * @off: the offset to the data with @page
+ * @size: the length of the data
+ *
+ * Initialises the @i'th fragment of @skb to point to &size bytes at
+ * offset @off within @page.
+ *
+ * Does not take any additional reference on the fragment.
+ */
+static inline void __skb_fill_page_desc(struct sk_buff *skb, int i,
+                                       struct page *page, int off, int size)
 {
        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
        frag->page                = page;
        frag->page_offset         = off;
        frag->size                = size;
+}
+
+/**
+ * skb_fill_page_desc - initialise a paged fragment in an skb
+ * @skb: buffer containing fragment to be initialised
+ * @i: paged fragment index to initialise
+ * @page: the page to use for this fragment
+ * @off: the offset to the data with @page
+ * @size: the length of the data
+ *
+ * As per __skb_fill_page_desc() -- initialises the @i'th fragment of
+ * @skb to point to &size bytes at offset @off within @page. In
+ * addition updates @skb such that @i is the last fragment.
+ *
+ * Does not take any additional reference on the fragment.
+ */
+static inline void skb_fill_page_desc(struct sk_buff *skb, int i,
+                                     struct page *page, int off, int size)
+{
+       __skb_fill_page_desc(skb, i, page, off, size);
        skb_shinfo(skb)->nr_frags = i + 1;
 }
 
@@ -1627,6 +1664,138 @@ static inline void netdev_free_page(struct net_device *dev, struct page *page)
        __free_page(page);
 }
 
+/**
+ * skb_frag_page - retrieve the page refered to by a paged fragment
+ * @frag: the paged fragment
+ *
+ * Returns the &struct page associated with @frag.
+ */
+static inline struct page *skb_frag_page(const skb_frag_t *frag)
+{
+       return frag->page;
+}
+
+/**
+ * __skb_frag_ref - take an addition reference on a paged fragment.
+ * @frag: the paged fragment
+ *
+ * Takes an additional reference on the paged fragment @frag.
+ */
+static inline void __skb_frag_ref(skb_frag_t *frag)
+{
+       get_page(skb_frag_page(frag));
+}
+
+/**
+ * skb_frag_ref - take an addition reference on a paged fragment of an skb.
+ * @skb: the buffer
+ * @f: the fragment offset.
+ *
+ * Takes an additional reference on the @f'th paged fragment of @skb.
+ */
+static inline void skb_frag_ref(struct sk_buff *skb, int f)
+{
+       __skb_frag_ref(&skb_shinfo(skb)->frags[f]);
+}
+
+/**
+ * __skb_frag_unref - release a reference on a paged fragment.
+ * @frag: the paged fragment
+ *
+ * Releases a reference on the paged fragment @frag.
+ */
+static inline void __skb_frag_unref(skb_frag_t *frag)
+{
+       put_page(skb_frag_page(frag));
+}
+
+/**
+ * skb_frag_unref - release a reference on a paged fragment of an skb.
+ * @skb: the buffer
+ * @f: the fragment offset
+ *
+ * Releases a reference on the @f'th paged fragment of @skb.
+ */
+static inline void skb_frag_unref(struct sk_buff *skb, int f)
+{
+       __skb_frag_unref(&skb_shinfo(skb)->frags[f]);
+}
+
+/**
+ * skb_frag_address - gets the address of the data contained in a paged fragment
+ * @frag: the paged fragment buffer
+ *
+ * Returns the address of the data within @frag. The page must already
+ * be mapped.
+ */
+static inline void *skb_frag_address(const skb_frag_t *frag)
+{
+       return page_address(skb_frag_page(frag)) + frag->page_offset;
+}
+
+/**
+ * skb_frag_address_safe - gets the address of the data contained in a paged fragment
+ * @frag: the paged fragment buffer
+ *
+ * Returns the address of the data within @frag. Checks that the page
+ * is mapped and returns %NULL otherwise.
+ */
+static inline void *skb_frag_address_safe(const skb_frag_t *frag)
+{
+       void *ptr = page_address(skb_frag_page(frag));
+       if (unlikely(!ptr))
+               return NULL;
+
+       return ptr + frag->page_offset;
+}
+
+/**
+ * __skb_frag_set_page - sets the page contained in a paged fragment
+ * @frag: the paged fragment
+ * @page: the page to set
+ *
+ * Sets the fragment @frag to contain @page.
+ */
+static inline void __skb_frag_set_page(skb_frag_t *frag, struct page *page)
+{
+       frag->page = page;
+       __skb_frag_ref(frag);
+}
+
+/**
+ * skb_frag_set_page - sets the page contained in a paged fragment of an skb
+ * @skb: the buffer
+ * @f: the fragment offset
+ * @page: the page to set
+ *
+ * Sets the @f'th fragment of @skb to contain @page.
+ */
+static inline void skb_frag_set_page(struct sk_buff *skb, int f,
+                                    struct page *page)
+{
+       __skb_frag_set_page(&skb_shinfo(skb)->frags[f], page);
+}
+
+/**
+ * skb_frag_dma_map - maps a paged fragment via the DMA API
+ * @device: the device to map the fragment to
+ * @frag: the paged fragment to map
+ * @offset: the offset within the fragment (starting at the
+ *          fragment's own offset)
+ * @size: the number of bytes to map
+ * @direction: the direction of the mapping (%PCI_DMA_*)
+ *
+ * Maps the page associated with @frag to @device.
+ */
+static inline dma_addr_t skb_frag_dma_map(struct device *dev,
+                                         const skb_frag_t *frag,
+                                         size_t offset, size_t size,
+                                         enum dma_data_direction dir)
+{
+       return dma_map_page(dev, skb_frag_page(frag),
+                           frag->page_offset + offset, size, dir);
+}
+
 /**
  *     skb_clone_writable - is the header of a clone writable
  *     @skb: buffer to check
@@ -1729,12 +1898,12 @@ static inline int skb_add_data(struct sk_buff *skb,
 }
 
 static inline int skb_can_coalesce(struct sk_buff *skb, int i,
-                                  struct page *page, int off)
+                                  const struct page *page, int off)
 {
        if (i) {
                struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1];
 
-               return page == frag->page &&
+               return page == skb_frag_page(frag) &&
                       off == frag->page_offset + frag->size;
        }
        return 0;
index 4b35c06..f58d641 100644 (file)
@@ -24,6 +24,7 @@ enum stat_item {
        ALLOC_FROM_PARTIAL,     /* Cpu slab acquired from partial list */
        ALLOC_SLAB,             /* Cpu slab acquired from page allocator */
        ALLOC_REFILL,           /* Refill cpu slab from slab freelist */
+       ALLOC_NODE_MISMATCH,    /* Switching cpu slab */
        FREE_SLAB,              /* Slab freed to the page allocator */
        CPUSLAB_FLUSH,          /* Abandoning of the cpu slab */
        DEACTIVATE_FULL,        /* Cpu slab was full when deactivated */
@@ -31,8 +32,10 @@ enum stat_item {
        DEACTIVATE_TO_HEAD,     /* Cpu slab was moved to the head of partials */
        DEACTIVATE_TO_TAIL,     /* Cpu slab was moved to the tail of partials */
        DEACTIVATE_REMOTE_FREES,/* Slab contained remotely freed objects */
+       DEACTIVATE_BYPASS,      /* Implicit deactivation */
        ORDER_FALLBACK,         /* Number of times fallback was necessary */
        CMPXCHG_DOUBLE_CPU_FAIL,/* Failure of this_cpu_cmpxchg_double */
+       CMPXCHG_DOUBLE_FAIL,    /* Number of times that cmpxchg double did not match */
        NR_SLUB_STAT_ITEMS };
 
 struct kmem_cache_cpu {
index e17f822..d0e77f6 100644 (file)
@@ -8,8 +8,10 @@
 #define _K_SS_ALIGNSIZE        (__alignof__ (struct sockaddr *))
                                /* Implementation specific desired alignment */
 
+typedef unsigned short __kernel_sa_family_t;
+
 struct __kernel_sockaddr_storage {
-       unsigned short  ss_family;              /* address family */
+       __kernel_sa_family_t    ss_family;              /* address family */
        /* Following field(s) are implementation specific */
        char            __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
                                /* space to achieve desired size, */
@@ -35,7 +37,7 @@ struct seq_file;
 extern void socket_seq_show(struct seq_file *seq);
 #endif
 
-typedef unsigned short sa_family_t;
+typedef __kernel_sa_family_t   sa_family_t;
 
 /*
  *     1003.1g requires sa_family_t and that sa_data is char.
similarity index 98%
rename from drivers/net/sungem_phy.h
rename to include/linux/sungem_phy.h
index af02f94..bd9be9f 100644 (file)
@@ -61,7 +61,7 @@ struct mii_phy
 /* Pass in a struct mii_phy with dev, mdio_read and mdio_write
  * filled, the remaining fields will be filled on return
  */
-extern int mii_phy_probe(struct mii_phy *phy, int mii_id);
+extern int sungem_phy_probe(struct mii_phy *phy, int mii_id);
 
 
 /* MII definitions missing from mii.h */
index cd42e30..2189d3f 100644 (file)
@@ -1,3 +1,8 @@
+#ifndef _LINUX_SWAPOPS_H
+#define _LINUX_SWAPOPS_H
+
+#include <linux/radix-tree.h>
+
 /*
  * swapcache pages are stored in the swapper_space radix tree.  We want to
  * get good packing density in that tree, so the index should be dense in
@@ -76,6 +81,22 @@ static inline pte_t swp_entry_to_pte(swp_entry_t entry)
        return __swp_entry_to_pte(arch_entry);
 }
 
+static inline swp_entry_t radix_to_swp_entry(void *arg)
+{
+       swp_entry_t entry;
+
+       entry.val = (unsigned long)arg >> RADIX_TREE_EXCEPTIONAL_SHIFT;
+       return entry;
+}
+
+static inline void *swp_to_radix_entry(swp_entry_t entry)
+{
+       unsigned long value;
+
+       value = entry.val << RADIX_TREE_EXCEPTIONAL_SHIFT;
+       return (void *)(value | RADIX_TREE_EXCEPTIONAL_ENTRY);
+}
+
 #ifdef CONFIG_MIGRATION
 static inline swp_entry_t make_migration_entry(struct page *page, int write)
 {
@@ -169,3 +190,5 @@ static inline int non_swap_entry(swp_entry_t entry)
        return 0;
 }
 #endif
+
+#endif /* _LINUX_SWAPOPS_H */
index 531ede8..6b63b31 100644 (file)
@@ -379,6 +379,10 @@ struct tcp_sock {
        u32     snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */
        u32     snd_cwnd_used;
        u32     snd_cwnd_stamp;
+       u32     prior_cwnd;     /* Congestion window at start of Recovery. */
+       u32     prr_delivered;  /* Number of newly delivered packets to
+                                * receiver in Recovery. */
+       u32     prr_out;        /* Total number of pkts sent during Recovery. */
 
        u32     rcv_wnd;        /* Current receiver window              */
        u32     write_seq;      /* Tail(+1) of data held in tcp send buffer */
index d3ec89f..47b4a27 100644 (file)
@@ -85,22 +85,6 @@ struct thermal_cooling_device {
                                ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
 #define CELSIUS_TO_KELVIN(t)   ((t)*10+2732)
 
-#if defined(CONFIG_THERMAL_HWMON)
-/* thermal zone devices with the same type share one hwmon device */
-struct thermal_hwmon_device {
-       char type[THERMAL_NAME_LENGTH];
-       struct device *device;
-       int count;
-       struct list_head tz_list;
-       struct list_head node;
-};
-
-struct thermal_hwmon_attr {
-       struct device_attribute attr;
-       char name[16];
-};
-#endif
-
 struct thermal_zone_device {
        int id;
        char type[THERMAL_NAME_LENGTH];
@@ -120,12 +104,6 @@ struct thermal_zone_device {
        struct mutex lock;      /* protect cooling devices list */
        struct list_head node;
        struct delayed_work poll_queue;
-#if defined(CONFIG_THERMAL_HWMON)
-       struct list_head hwmon_node;
-       struct thermal_hwmon_device *hwmon;
-       struct thermal_hwmon_attr temp_input;   /* hwmon sys attr */
-       struct thermal_hwmon_attr temp_crit;    /* hwmon sys attr */
-#endif
 };
 /* Adding event notification support elements */
 #define THERMAL_GENL_FAMILY_NAME                "thermal_event"
index 0db2395..9730b0e 100644 (file)
 #include <linux/string.h>
 #include <asm/byteorder.h>
 
+#ifndef __KERNEL__
+#include <arpa/inet.h> /* for ntohs etc. */
+#endif
+
 /*
  * Configuration
  *
index 45561c5..3ed3e46 100644 (file)
@@ -1,10 +1,12 @@
 #ifndef _LINUX_UN_H
 #define _LINUX_UN_H
 
+#include <linux/socket.h>
+
 #define UNIX_PATH_MAX  108
 
 struct sockaddr_un {
-       sa_family_t sun_family; /* AF_UNIX */
+       __kernel_sa_family_t sun_family; /* AF_UNIX */
        char sun_path[UNIX_PATH_MAX];   /* pathname */
 };
 
index 8a4c309..fca24cc 100644 (file)
@@ -376,7 +376,16 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_MJPEG    v4l2_fourcc('M', 'J', 'P', 'G') /* Motion-JPEG   */
 #define V4L2_PIX_FMT_JPEG     v4l2_fourcc('J', 'P', 'E', 'G') /* JFIF JPEG     */
 #define V4L2_PIX_FMT_DV       v4l2_fourcc('d', 'v', 's', 'd') /* 1394          */
-#define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4    */
+#define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 Multiplexed */
+#define V4L2_PIX_FMT_H264     v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */
+#define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */
+#define V4L2_PIX_FMT_H263     v4l2_fourcc('H', '2', '6', '3') /* H263          */
+#define V4L2_PIX_FMT_MPEG1    v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES     */
+#define V4L2_PIX_FMT_MPEG2    v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES     */
+#define V4L2_PIX_FMT_MPEG4    v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 ES     */
+#define V4L2_PIX_FMT_XVID     v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid           */
+#define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE 421M Annex G compliant stream */
+#define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
 
 /*  Vendor-specific formats   */
 #define V4L2_PIX_FMT_CPIA1    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
@@ -402,6 +411,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_CIT_YYVYUY v4l2_fourcc('C', 'I', 'T', 'V') /* one line of Y then 1 line of VYUY */
 #define V4L2_PIX_FMT_KONICA420  v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
 #define V4L2_PIX_FMT_JPGL      v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */
+#define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
 
 /*
  *     F O R M A T   E N U M E R A T I O N
@@ -1026,6 +1036,7 @@ struct v4l2_ext_controls {
 #define V4L2_CTRL_CLASS_MPEG 0x00990000        /* MPEG-compression controls */
 #define V4L2_CTRL_CLASS_CAMERA 0x009a0000      /* Camera class controls */
 #define V4L2_CTRL_CLASS_FM_TX 0x009b0000       /* FM Modulator control class */
+#define V4L2_CTRL_CLASS_FLASH 0x009c0000       /* Camera flash controls */
 
 #define V4L2_CTRL_ID_MASK                (0x0fffffff)
 #define V4L2_CTRL_ID2CLASS(id)    ((id) & 0x0fff0000UL)
@@ -1039,6 +1050,7 @@ enum v4l2_ctrl_type {
        V4L2_CTRL_TYPE_INTEGER64     = 5,
        V4L2_CTRL_TYPE_CTRL_CLASS    = 6,
        V4L2_CTRL_TYPE_STRING        = 7,
+       V4L2_CTRL_TYPE_BITMASK       = 8,
 };
 
 /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
@@ -1144,14 +1156,19 @@ enum v4l2_colorfx {
 #define V4L2_CID_ILLUMINATORS_1                        (V4L2_CID_BASE+37)
 #define V4L2_CID_ILLUMINATORS_2                        (V4L2_CID_BASE+38)
 
+#define V4L2_CID_MIN_BUFFERS_FOR_CAPTURE       (V4L2_CID_BASE+39)
+#define V4L2_CID_MIN_BUFFERS_FOR_OUTPUT                (V4L2_CID_BASE+40)
+
 /* last CID + 1 */
-#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+39)
+#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+41)
+
+/* Minimum number of buffer neede by the device */
 
 /*  MPEG-class control IDs defined by V4L2 */
 #define V4L2_CID_MPEG_BASE                     (V4L2_CTRL_CLASS_MPEG | 0x900)
 #define V4L2_CID_MPEG_CLASS                    (V4L2_CTRL_CLASS_MPEG | 1)
 
-/*  MPEG streams */
+/*  MPEG streams, specific to multiplexed streams */
 #define V4L2_CID_MPEG_STREAM_TYPE              (V4L2_CID_MPEG_BASE+0)
 enum v4l2_mpeg_stream_type {
        V4L2_MPEG_STREAM_TYPE_MPEG2_PS   = 0, /* MPEG-2 program stream */
@@ -1173,7 +1190,7 @@ enum v4l2_mpeg_stream_vbi_fmt {
        V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1,  /* VBI in private packets, IVTV format */
 };
 
-/*  MPEG audio */
+/*  MPEG audio controls specific to multiplexed streams  */
 #define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ      (V4L2_CID_MPEG_BASE+100)
 enum v4l2_mpeg_audio_sampling_freq {
        V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0,
@@ -1289,7 +1306,7 @@ enum v4l2_mpeg_audio_ac3_bitrate {
        V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18,
 };
 
-/*  MPEG video */
+/*  MPEG video controls specific to multiplexed streams */
 #define V4L2_CID_MPEG_VIDEO_ENCODING           (V4L2_CID_MPEG_BASE+200)
 enum v4l2_mpeg_video_encoding {
        V4L2_MPEG_VIDEO_ENCODING_MPEG_1     = 0,
@@ -1317,6 +1334,141 @@ enum v4l2_mpeg_video_bitrate_mode {
 #define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_MPEG_BASE+209)
 #define V4L2_CID_MPEG_VIDEO_MUTE               (V4L2_CID_MPEG_BASE+210)
 #define V4L2_CID_MPEG_VIDEO_MUTE_YUV           (V4L2_CID_MPEG_BASE+211)
+#define V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE            (V4L2_CID_MPEG_BASE+212)
+#define V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER       (V4L2_CID_MPEG_BASE+213)
+#define V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB            (V4L2_CID_MPEG_BASE+214)
+#define V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE                    (V4L2_CID_MPEG_BASE+215)
+#define V4L2_CID_MPEG_VIDEO_HEADER_MODE                                (V4L2_CID_MPEG_BASE+216)
+enum v4l2_mpeg_video_header_mode {
+       V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE                    = 0,
+       V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME       = 1,
+
+};
+#define V4L2_CID_MPEG_VIDEO_MAX_REF_PIC                        (V4L2_CID_MPEG_BASE+217)
+#define V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE               (V4L2_CID_MPEG_BASE+218)
+#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES      (V4L2_CID_MPEG_BASE+219)
+#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB         (V4L2_CID_MPEG_BASE+220)
+#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE           (V4L2_CID_MPEG_BASE+221)
+enum v4l2_mpeg_video_multi_slice_mode {
+       V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE         = 0,
+       V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB          = 1,
+       V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES       = 2,
+};
+#define V4L2_CID_MPEG_VIDEO_VBV_SIZE                   (V4L2_CID_MPEG_BASE+222)
+#define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP            (V4L2_CID_MPEG_BASE+300)
+#define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP            (V4L2_CID_MPEG_BASE+301)
+#define V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP            (V4L2_CID_MPEG_BASE+302)
+#define V4L2_CID_MPEG_VIDEO_H263_MIN_QP                        (V4L2_CID_MPEG_BASE+303)
+#define V4L2_CID_MPEG_VIDEO_H263_MAX_QP                        (V4L2_CID_MPEG_BASE+304)
+#define V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP            (V4L2_CID_MPEG_BASE+350)
+#define V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP            (V4L2_CID_MPEG_BASE+351)
+#define V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP            (V4L2_CID_MPEG_BASE+352)
+#define V4L2_CID_MPEG_VIDEO_H264_MIN_QP                        (V4L2_CID_MPEG_BASE+353)
+#define V4L2_CID_MPEG_VIDEO_H264_MAX_QP                        (V4L2_CID_MPEG_BASE+354)
+#define V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM         (V4L2_CID_MPEG_BASE+355)
+#define V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE              (V4L2_CID_MPEG_BASE+356)
+#define V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE          (V4L2_CID_MPEG_BASE+357)
+enum v4l2_mpeg_video_h264_entropy_mode {
+       V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC = 0,
+       V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_I_PERIOD              (V4L2_CID_MPEG_BASE+358)
+#define V4L2_CID_MPEG_VIDEO_H264_LEVEL                 (V4L2_CID_MPEG_BASE+359)
+enum v4l2_mpeg_video_h264_level {
+       V4L2_MPEG_VIDEO_H264_LEVEL_1_0  = 0,
+       V4L2_MPEG_VIDEO_H264_LEVEL_1B   = 1,
+       V4L2_MPEG_VIDEO_H264_LEVEL_1_1  = 2,
+       V4L2_MPEG_VIDEO_H264_LEVEL_1_2  = 3,
+       V4L2_MPEG_VIDEO_H264_LEVEL_1_3  = 4,
+       V4L2_MPEG_VIDEO_H264_LEVEL_2_0  = 5,
+       V4L2_MPEG_VIDEO_H264_LEVEL_2_1  = 6,
+       V4L2_MPEG_VIDEO_H264_LEVEL_2_2  = 7,
+       V4L2_MPEG_VIDEO_H264_LEVEL_3_0  = 8,
+       V4L2_MPEG_VIDEO_H264_LEVEL_3_1  = 9,
+       V4L2_MPEG_VIDEO_H264_LEVEL_3_2  = 10,
+       V4L2_MPEG_VIDEO_H264_LEVEL_4_0  = 11,
+       V4L2_MPEG_VIDEO_H264_LEVEL_4_1  = 12,
+       V4L2_MPEG_VIDEO_H264_LEVEL_4_2  = 13,
+       V4L2_MPEG_VIDEO_H264_LEVEL_5_0  = 14,
+       V4L2_MPEG_VIDEO_H264_LEVEL_5_1  = 15,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA     (V4L2_CID_MPEG_BASE+360)
+#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA      (V4L2_CID_MPEG_BASE+361)
+#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE      (V4L2_CID_MPEG_BASE+362)
+enum v4l2_mpeg_video_h264_loop_filter_mode {
+       V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED                           = 0,
+       V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED                          = 1,
+       V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY        = 2,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_PROFILE               (V4L2_CID_MPEG_BASE+363)
+enum v4l2_mpeg_video_h264_profile {
+       V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE                   = 0,
+       V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE       = 1,
+       V4L2_MPEG_VIDEO_H264_PROFILE_MAIN                       = 2,
+       V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED                   = 3,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH                       = 4,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10                    = 5,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422                   = 6,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE        = 7,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA              = 8,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA             = 9,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA             = 10,
+       V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA            = 11,
+       V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE          = 12,
+       V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH              = 13,
+       V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA        = 14,
+       V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH                = 15,
+       V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH             = 16,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT    (V4L2_CID_MPEG_BASE+364)
+#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH     (V4L2_CID_MPEG_BASE+365)
+#define V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE                (V4L2_CID_MPEG_BASE+366)
+#define V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC           (V4L2_CID_MPEG_BASE+367)
+enum v4l2_mpeg_video_h264_vui_sar_idc {
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED    = 0,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1            = 1,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_12x11          = 2,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_10x11          = 3,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_16x11          = 4,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_40x33          = 5,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_24x11          = 6,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_20x11          = 7,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_32x11          = 8,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_80x33          = 9,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_18x11          = 10,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_15x11          = 11,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_64x33          = 12,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_160x99         = 13,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_4x3            = 14,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_3x2            = 15,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1            = 16,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED       = 17,
+};
+#define V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP   (V4L2_CID_MPEG_BASE+400)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP   (V4L2_CID_MPEG_BASE+401)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP   (V4L2_CID_MPEG_BASE+402)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP       (V4L2_CID_MPEG_BASE+403)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP       (V4L2_CID_MPEG_BASE+404)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL                (V4L2_CID_MPEG_BASE+405)
+enum v4l2_mpeg_video_mpeg4_level {
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_0   = 0,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B  = 1,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_1   = 2,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_2   = 3,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_3   = 4,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B  = 5,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_4   = 6,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_5   = 7,
+};
+#define V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE      (V4L2_CID_MPEG_BASE+406)
+enum v4l2_mpeg_video_mpeg4_profile {
+       V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE                            = 0,
+       V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE                   = 1,
+       V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE                              = 2,
+       V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE                   = 3,
+       V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY        = 4,
+};
+#define V4L2_CID_MPEG_VIDEO_MPEG4_QPEL         (V4L2_CID_MPEG_BASE+407)
 
 /*  MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */
 #define V4L2_CID_MPEG_CX2341X_BASE                             (V4L2_CTRL_CLASS_MPEG | 0x1000)
@@ -1359,6 +1511,33 @@ enum v4l2_mpeg_cx2341x_video_median_filter_type {
 #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP   (V4L2_CID_MPEG_CX2341X_BASE+10)
 #define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS        (V4L2_CID_MPEG_CX2341X_BASE+11)
 
+/*  MPEG-class control IDs specific to the Samsung MFC 5.1 driver as defined by V4L2 */
+#define V4L2_CID_MPEG_MFC51_BASE                               (V4L2_CTRL_CLASS_MPEG | 0x1100)
+
+#define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY           (V4L2_CID_MPEG_MFC51_BASE+0)
+#define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE    (V4L2_CID_MPEG_MFC51_BASE+1)
+#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE                      (V4L2_CID_MPEG_MFC51_BASE+2)
+enum v4l2_mpeg_mfc51_video_frame_skip_mode {
+       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED          = 0,
+       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT       = 1,
+       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT         = 2,
+};
+#define V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE                     (V4L2_CID_MPEG_MFC51_BASE+3)
+enum v4l2_mpeg_mfc51_video_force_frame_type {
+       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED         = 0,
+       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME          = 1,
+       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED        = 2,
+};
+#define V4L2_CID_MPEG_MFC51_VIDEO_PADDING                              (V4L2_CID_MPEG_MFC51_BASE+4)
+#define V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV                          (V4L2_CID_MPEG_MFC51_BASE+5)
+#define V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT                  (V4L2_CID_MPEG_MFC51_BASE+6)
+#define V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF                    (V4L2_CID_MPEG_MFC51_BASE+7)
+#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY            (V4L2_CID_MPEG_MFC51_BASE+50)
+#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK                        (V4L2_CID_MPEG_MFC51_BASE+51)
+#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH              (V4L2_CID_MPEG_MFC51_BASE+52)
+#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC              (V4L2_CID_MPEG_MFC51_BASE+53)
+#define V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P               (V4L2_CID_MPEG_MFC51_BASE+54)
+
 /*  Camera class control IDs */
 #define V4L2_CID_CAMERA_CLASS_BASE     (V4L2_CTRL_CLASS_CAMERA | 0x900)
 #define V4L2_CID_CAMERA_CLASS          (V4L2_CTRL_CLASS_CAMERA | 1)
@@ -1427,6 +1606,41 @@ enum v4l2_preemphasis {
 #define V4L2_CID_TUNE_POWER_LEVEL              (V4L2_CID_FM_TX_CLASS_BASE + 113)
 #define V4L2_CID_TUNE_ANTENNA_CAPACITOR                (V4L2_CID_FM_TX_CLASS_BASE + 114)
 
+/* Flash and privacy (indicator) light controls */
+#define V4L2_CID_FLASH_CLASS_BASE              (V4L2_CTRL_CLASS_FLASH | 0x900)
+#define V4L2_CID_FLASH_CLASS                   (V4L2_CTRL_CLASS_FLASH | 1)
+
+#define V4L2_CID_FLASH_LED_MODE                        (V4L2_CID_FLASH_CLASS_BASE + 1)
+enum v4l2_flash_led_mode {
+       V4L2_FLASH_LED_MODE_NONE,
+       V4L2_FLASH_LED_MODE_FLASH,
+       V4L2_FLASH_LED_MODE_TORCH,
+};
+
+#define V4L2_CID_FLASH_STROBE_SOURCE           (V4L2_CID_FLASH_CLASS_BASE + 2)
+enum v4l2_flash_strobe_source {
+       V4L2_FLASH_STROBE_SOURCE_SOFTWARE,
+       V4L2_FLASH_STROBE_SOURCE_EXTERNAL,
+};
+
+#define V4L2_CID_FLASH_STROBE                  (V4L2_CID_FLASH_CLASS_BASE + 3)
+#define V4L2_CID_FLASH_STROBE_STOP             (V4L2_CID_FLASH_CLASS_BASE + 4)
+#define V4L2_CID_FLASH_STROBE_STATUS           (V4L2_CID_FLASH_CLASS_BASE + 5)
+
+#define V4L2_CID_FLASH_TIMEOUT                 (V4L2_CID_FLASH_CLASS_BASE + 6)
+#define V4L2_CID_FLASH_INTENSITY               (V4L2_CID_FLASH_CLASS_BASE + 7)
+#define V4L2_CID_FLASH_TORCH_INTENSITY         (V4L2_CID_FLASH_CLASS_BASE + 8)
+#define V4L2_CID_FLASH_INDICATOR_INTENSITY     (V4L2_CID_FLASH_CLASS_BASE + 9)
+
+#define V4L2_CID_FLASH_FAULT                   (V4L2_CID_FLASH_CLASS_BASE + 10)
+#define V4L2_FLASH_FAULT_OVER_VOLTAGE          (1 << 0)
+#define V4L2_FLASH_FAULT_TIMEOUT               (1 << 1)
+#define V4L2_FLASH_FAULT_OVER_TEMPERATURE      (1 << 2)
+#define V4L2_FLASH_FAULT_SHORT_CIRCUIT         (1 << 3)
+
+#define V4L2_CID_FLASH_CHARGE                  (V4L2_CID_FLASH_CLASS_BASE + 11)
+#define V4L2_CID_FLASH_READY                   (V4L2_CID_FLASH_CLASS_BASE + 12)
+
 /*
  *     T U N I N G
  */
@@ -1791,6 +2005,7 @@ struct v4l2_streamparm {
 #define V4L2_EVENT_ALL                         0
 #define V4L2_EVENT_VSYNC                       1
 #define V4L2_EVENT_EOS                         2
+#define V4L2_EVENT_CTRL                                3
 #define V4L2_EVENT_PRIVATE_START               0x08000000
 
 /* Payload for V4L2_EVENT_VSYNC */
@@ -1799,21 +2014,46 @@ struct v4l2_event_vsync {
        __u8 field;
 } __attribute__ ((packed));
 
+/* Payload for V4L2_EVENT_CTRL */
+#define V4L2_EVENT_CTRL_CH_VALUE               (1 << 0)
+#define V4L2_EVENT_CTRL_CH_FLAGS               (1 << 1)
+
+struct v4l2_event_ctrl {
+       __u32 changes;
+       __u32 type;
+       union {
+               __s32 value;
+               __s64 value64;
+       };
+       __u32 flags;
+       __s32 minimum;
+       __s32 maximum;
+       __s32 step;
+       __s32 default_value;
+};
+
 struct v4l2_event {
        __u32                           type;
        union {
                struct v4l2_event_vsync vsync;
+               struct v4l2_event_ctrl  ctrl;
                __u8                    data[64];
        } u;
        __u32                           pending;
        __u32                           sequence;
        struct timespec                 timestamp;
-       __u32                           reserved[9];
+       __u32                           id;
+       __u32                           reserved[8];
 };
 
+#define V4L2_EVENT_SUB_FL_SEND_INITIAL         (1 << 0)
+#define V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK       (1 << 1)
+
 struct v4l2_event_subscription {
        __u32                           type;
-       __u32                           reserved[7];
+       __u32                           id;
+       __u32                           flags;
+       __u32                           reserved[5];
 };
 
 /*
index 011bcfe..111843f 100644 (file)
@@ -59,6 +59,84 @@ struct watchdog_info {
 #define WATCHDOG_NOWAYOUT      0
 #endif
 
+struct watchdog_ops;
+struct watchdog_device;
+
+/** struct watchdog_ops - The watchdog-devices operations
+ *
+ * @owner:     The module owner.
+ * @start:     The routine for starting the watchdog device.
+ * @stop:      The routine for stopping the watchdog device.
+ * @ping:      The routine that sends a keepalive ping to the watchdog device.
+ * @status:    The routine that shows the status of the watchdog device.
+ * @set_timeout:The routine for setting the watchdog devices timeout value.
+ * @ioctl:     The routines that handles extra ioctl calls.
+ *
+ * The watchdog_ops structure contains a list of low-level operations
+ * that control a watchdog device. It also contains the module that owns
+ * these operations. The start and stop function are mandatory, all other
+ * functions are optonal.
+ */
+struct watchdog_ops {
+       struct module *owner;
+       /* mandatory operations */
+       int (*start)(struct watchdog_device *);
+       int (*stop)(struct watchdog_device *);
+       /* optional operations */
+       int (*ping)(struct watchdog_device *);
+       unsigned int (*status)(struct watchdog_device *);
+       int (*set_timeout)(struct watchdog_device *, unsigned int);
+       long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
+};
+
+/** struct watchdog_device - The structure that defines a watchdog device
+ *
+ * @info:      Pointer to a watchdog_info structure.
+ * @ops:       Pointer to the list of watchdog operations.
+ * @bootstatus:        Status of the watchdog device at boot.
+ * @timeout:   The watchdog devices timeout value.
+ * @min_timeout:The watchdog devices minimum timeout value.
+ * @max_timeout:The watchdog devices maximum timeout value.
+ * @driver-data:Pointer to the drivers private data.
+ * @status:    Field that contains the devices internal status bits.
+ *
+ * The watchdog_device structure contains all information about a
+ * watchdog timer device.
+ *
+ * The driver-data field may not be accessed directly. It must be accessed
+ * via the watchdog_set_drvdata and watchdog_get_drvdata helpers.
+ */
+struct watchdog_device {
+       const struct watchdog_info *info;
+       const struct watchdog_ops *ops;
+       unsigned int bootstatus;
+       unsigned int timeout;
+       unsigned int min_timeout;
+       unsigned int max_timeout;
+       void *driver_data;
+       unsigned long status;
+/* Bit numbers for status flags */
+#define WDOG_ACTIVE            0       /* Is the watchdog running/active */
+#define WDOG_DEV_OPEN          1       /* Opened via /dev/watchdog ? */
+#define WDOG_ALLOW_RELEASE     2       /* Did we receive the magic char ? */
+#define WDOG_NO_WAY_OUT                3       /* Is 'nowayout' feature set ? */
+};
+
+/* Use the following functions to manipulate watchdog driver specific data */
+static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
+{
+       wdd->driver_data = data;
+}
+
+static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
+{
+       return wdd->driver_data;
+}
+
+/* drivers/watchdog/core/watchdog_core.c */
+extern int watchdog_register_device(struct watchdog_device *);
+extern void watchdog_unregister_device(struct watchdog_device *);
+
 #endif /* __KERNEL__ */
 
 #endif  /* ifndef _LINUX_WATCHDOG_H */
index 6450a7f..810cce6 100644 (file)
@@ -12,6 +12,7 @@
 #define        X25_KERNEL_H
 
 #include <linux/types.h>
+#include <linux/socket.h>
 
 #define        SIOCX25GSUBSCRIP        (SIOCPROTOPRIVATE + 0)
 #define        SIOCX25SSUBSCRIP        (SIOCPROTOPRIVATE + 1)
@@ -57,7 +58,7 @@ struct x25_address {
  *     Linux X.25 Address structure, used for bind, and connect mostly.
  */
 struct sockaddr_x25 {
-       sa_family_t        sx25_family;         /* Must be AF_X25 */
+       __kernel_sa_family_t sx25_family;       /* Must be AF_X25 */
        struct x25_address sx25_addr;           /* X.121 Address */
 };
 
diff --git a/include/media/adp1653.h b/include/media/adp1653.h
new file mode 100644 (file)
index 0000000..50a1af8
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * include/media/adp1653.h
+ *
+ * Copyright (C) 2008--2011 Nokia Corporation
+ *
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * Contributors:
+ *     Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *     Tuukka Toivonen <tuukkat76@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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef ADP1653_H
+#define ADP1653_H
+
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#define ADP1653_NAME                           "adp1653"
+#define ADP1653_I2C_ADDR                       (0x60 >> 1)
+
+/* Register definitions */
+#define ADP1653_REG_OUT_SEL                    0x00
+#define ADP1653_REG_OUT_SEL_HPLED_TORCH_MIN    0x01
+#define ADP1653_REG_OUT_SEL_HPLED_TORCH_MAX    0x0b
+#define ADP1653_REG_OUT_SEL_HPLED_FLASH_MIN    0x0c
+#define ADP1653_REG_OUT_SEL_HPLED_FLASH_MAX    0x1f
+#define ADP1653_REG_OUT_SEL_HPLED_SHIFT                3
+#define ADP1653_REG_OUT_SEL_ILED_MAX           0x07
+#define ADP1653_REG_OUT_SEL_ILED_SHIFT         0
+
+#define ADP1653_REG_CONFIG                     0x01
+#define ADP1653_REG_CONFIG_TMR_CFG             (1 << 4)
+#define ADP1653_REG_CONFIG_TMR_SET_MAX         0x0f
+#define ADP1653_REG_CONFIG_TMR_SET_SHIFT       0
+
+#define ADP1653_REG_SW_STROBE                  0x02
+#define ADP1653_REG_SW_STROBE_SW_STROBE                (1 << 0)
+
+#define ADP1653_REG_FAULT                      0x03
+#define ADP1653_REG_FAULT_FLT_SCP              (1 << 3)
+#define ADP1653_REG_FAULT_FLT_OT               (1 << 2)
+#define ADP1653_REG_FAULT_FLT_TMR              (1 << 1)
+#define ADP1653_REG_FAULT_FLT_OV               (1 << 0)
+
+#define ADP1653_INDICATOR_INTENSITY_MIN                0
+#define ADP1653_INDICATOR_INTENSITY_STEP       2500
+#define ADP1653_INDICATOR_INTENSITY_MAX                \
+       (ADP1653_REG_OUT_SEL_ILED_MAX * ADP1653_INDICATOR_INTENSITY_STEP)
+#define ADP1653_INDICATOR_INTENSITY_uA_TO_REG(a) \
+       ((a) / ADP1653_INDICATOR_INTENSITY_STEP)
+#define ADP1653_INDICATOR_INTENSITY_REG_TO_uA(a) \
+       ((a) * ADP1653_INDICATOR_INTENSITY_STEP)
+
+#define ADP1653_FLASH_INTENSITY_BASE           35
+#define ADP1653_FLASH_INTENSITY_STEP           15
+#define ADP1653_FLASH_INTENSITY_MIN                                    \
+       (ADP1653_FLASH_INTENSITY_BASE                                   \
+        + ADP1653_REG_OUT_SEL_HPLED_FLASH_MIN * ADP1653_FLASH_INTENSITY_STEP)
+#define ADP1653_FLASH_INTENSITY_MAX                    \
+       (ADP1653_FLASH_INTENSITY_MIN +                  \
+        (ADP1653_REG_OUT_SEL_HPLED_FLASH_MAX -         \
+         ADP1653_REG_OUT_SEL_HPLED_FLASH_MIN + 1) *    \
+        ADP1653_FLASH_INTENSITY_STEP)
+
+#define ADP1653_FLASH_INTENSITY_mA_TO_REG(a)                           \
+       ((a) < ADP1653_FLASH_INTENSITY_BASE ? 0 :                       \
+        (((a) - ADP1653_FLASH_INTENSITY_BASE) / ADP1653_FLASH_INTENSITY_STEP))
+#define ADP1653_FLASH_INTENSITY_REG_TO_mA(a)           \
+       ((a) * ADP1653_FLASH_INTENSITY_STEP + ADP1653_FLASH_INTENSITY_BASE)
+
+#define ADP1653_TORCH_INTENSITY_MIN                                    \
+       (ADP1653_FLASH_INTENSITY_BASE                                   \
+        + ADP1653_REG_OUT_SEL_HPLED_TORCH_MIN * ADP1653_FLASH_INTENSITY_STEP)
+#define ADP1653_TORCH_INTENSITY_MAX                    \
+       (ADP1653_TORCH_INTENSITY_MIN +                  \
+        (ADP1653_REG_OUT_SEL_HPLED_TORCH_MAX -         \
+         ADP1653_REG_OUT_SEL_HPLED_TORCH_MIN + 1) *    \
+        ADP1653_FLASH_INTENSITY_STEP)
+
+struct adp1653_platform_data {
+       int (*power)(struct v4l2_subdev *sd, int on);
+
+       u32 max_flash_timeout;          /* flash light timeout in us */
+       u32 max_flash_intensity;        /* led intensity, flash mode */
+       u32 max_torch_intensity;        /* led intensity, torch mode */
+       u32 max_indicator_intensity;    /* indicator led intensity */
+};
+
+#define to_adp1653_flash(sd)   container_of(sd, struct adp1653_flash, subdev)
+
+struct adp1653_flash {
+       struct v4l2_subdev subdev;
+       struct adp1653_platform_data *platform_data;
+
+       struct v4l2_ctrl_handler ctrls;
+       struct v4l2_ctrl *led_mode;
+       struct v4l2_ctrl *flash_timeout;
+       struct v4l2_ctrl *flash_intensity;
+       struct v4l2_ctrl *torch_intensity;
+       struct v4l2_ctrl *indicator_intensity;
+
+       struct mutex power_lock;
+       int power_count;
+       int fault;
+};
+
+#endif /* ADP1653_H */
diff --git a/include/media/atmel-isi.h b/include/media/atmel-isi.h
new file mode 100644 (file)
index 0000000..26cece5
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Register definitions for the Atmel Image Sensor Interface.
+ *
+ * Copyright (C) 2011 Atmel Corporation
+ * Josh Wu, <josh.wu@atmel.com>
+ *
+ * Based on previous work by Lars Haring, <lars.haring@atmel.com>
+ * and Sedji Gaouaou
+ *
+ * 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 __ATMEL_ISI_H__
+#define __ATMEL_ISI_H__
+
+#include <linux/types.h>
+
+/* ISI_V2 register offsets */
+#define ISI_CFG1                               0x0000
+#define ISI_CFG2                               0x0004
+#define ISI_PSIZE                              0x0008
+#define ISI_PDECF                              0x000c
+#define ISI_Y2R_SET0                           0x0010
+#define ISI_Y2R_SET1                           0x0014
+#define ISI_R2Y_SET0                           0x0018
+#define ISI_R2Y_SET1                           0x001C
+#define ISI_R2Y_SET2                           0x0020
+#define ISI_CTRL                               0x0024
+#define ISI_STATUS                             0x0028
+#define ISI_INTEN                              0x002C
+#define ISI_INTDIS                             0x0030
+#define ISI_INTMASK                            0x0034
+#define ISI_DMA_CHER                           0x0038
+#define ISI_DMA_CHDR                           0x003C
+#define ISI_DMA_CHSR                           0x0040
+#define ISI_DMA_P_ADDR                         0x0044
+#define ISI_DMA_P_CTRL                         0x0048
+#define ISI_DMA_P_DSCR                         0x004C
+#define ISI_DMA_C_ADDR                         0x0050
+#define ISI_DMA_C_CTRL                         0x0054
+#define ISI_DMA_C_DSCR                         0x0058
+
+/* Bitfields in CFG1 */
+#define ISI_CFG1_HSYNC_POL_ACTIVE_LOW          (1 << 2)
+#define ISI_CFG1_VSYNC_POL_ACTIVE_LOW          (1 << 3)
+#define ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING     (1 << 4)
+#define ISI_CFG1_EMB_SYNC                      (1 << 6)
+#define ISI_CFG1_CRC_SYNC                      (1 << 7)
+/* Constants for FRATE(ISI_V2) */
+#define                ISI_CFG1_FRATE_CAPTURE_ALL      (0 << 8)
+#define                ISI_CFG1_FRATE_DIV_2            (1 << 8)
+#define                ISI_CFG1_FRATE_DIV_3            (2 << 8)
+#define                ISI_CFG1_FRATE_DIV_4            (3 << 8)
+#define                ISI_CFG1_FRATE_DIV_5            (4 << 8)
+#define                ISI_CFG1_FRATE_DIV_6            (5 << 8)
+#define                ISI_CFG1_FRATE_DIV_7            (6 << 8)
+#define                ISI_CFG1_FRATE_DIV_8            (7 << 8)
+#define ISI_CFG1_DISCR                         (1 << 11)
+#define ISI_CFG1_FULL_MODE                     (1 << 12)
+
+/* Bitfields in CFG2 */
+#define ISI_CFG2_GRAYSCALE                     (1 << 13)
+/* Constants for YCC_SWAP(ISI_V2) */
+#define                ISI_CFG2_YCC_SWAP_DEFAULT       (0 << 28)
+#define                ISI_CFG2_YCC_SWAP_MODE_1        (1 << 28)
+#define                ISI_CFG2_YCC_SWAP_MODE_2        (2 << 28)
+#define                ISI_CFG2_YCC_SWAP_MODE_3        (3 << 28)
+#define ISI_CFG2_IM_VSIZE_OFFSET               0
+#define ISI_CFG2_IM_HSIZE_OFFSET               16
+#define ISI_CFG2_IM_VSIZE_MASK         (0x7FF << ISI_CFG2_IM_VSIZE_OFFSET)
+#define ISI_CFG2_IM_HSIZE_MASK         (0x7FF << ISI_CFG2_IM_HSIZE_OFFSET)
+
+/* Bitfields in CTRL */
+/* Also using in SR(ISI_V2) */
+#define ISI_CTRL_EN                            (1 << 0)
+#define ISI_CTRL_CDC                           (1 << 8)
+/* Also using in SR/IER/IDR/IMR(ISI_V2) */
+#define ISI_CTRL_DIS                           (1 << 1)
+#define ISI_CTRL_SRST                          (1 << 2)
+
+/* Bitfields in SR */
+#define ISI_SR_SIP                             (1 << 19)
+/* Also using in SR/IER/IDR/IMR */
+#define ISI_SR_VSYNC                           (1 << 10)
+#define ISI_SR_PXFR_DONE                       (1 << 16)
+#define ISI_SR_CXFR_DONE                       (1 << 17)
+#define ISI_SR_P_OVR                           (1 << 24)
+#define ISI_SR_C_OVR                           (1 << 25)
+#define ISI_SR_CRC_ERR                         (1 << 26)
+#define ISI_SR_FR_OVR                          (1 << 27)
+
+/* Bitfields in DMA_C_CTRL & in DMA_P_CTRL */
+#define ISI_DMA_CTRL_FETCH                     (1 << 0)
+#define ISI_DMA_CTRL_WB                                (1 << 1)
+#define ISI_DMA_CTRL_IEN                       (1 << 2)
+#define ISI_DMA_CTRL_DONE                      (1 << 3)
+
+/* Bitfields in DMA_CHSR/CHER/CHDR */
+#define ISI_DMA_CHSR_P_CH                      (1 << 0)
+#define ISI_DMA_CHSR_C_CH                      (1 << 1)
+
+/* Definition for isi_platform_data */
+#define ISI_DATAWIDTH_8                                0x01
+#define ISI_DATAWIDTH_10                       0x02
+
+struct isi_platform_data {
+       u8 has_emb_sync;
+       u8 emb_crc_sync;
+       u8 hsync_act_low;
+       u8 vsync_act_low;
+       u8 pclk_act_falling;
+       u8 isi_full_mode;
+       u32 data_width_flags;
+       /* Using for ISI_CFG1 */
+       u32 frate;
+};
+
+#endif /* __ATMEL_ISI_H__ */
diff --git a/include/media/davinci/vpbe.h b/include/media/davinci/vpbe.h
new file mode 100644 (file)
index 0000000..8b11fb0
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2010 Texas Instruments 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 version 2.
+ *
+ * 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 _VPBE_H
+#define _VPBE_H
+
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/davinci/vpbe_osd.h>
+#include <media/davinci/vpbe_venc.h>
+#include <media/davinci/vpbe_types.h>
+
+/* OSD configuration info */
+struct osd_config_info {
+       char module_name[32];
+};
+
+struct vpbe_output {
+       struct v4l2_output output;
+       /*
+        * If output capabilities include dv_preset, list supported presets
+        * below
+        */
+       char *subdev_name;
+       /*
+        * defualt_mode identifies the default timings set at the venc or
+        * external encoder.
+        */
+       char *default_mode;
+       /*
+        * Fields below are used for supporting multiple modes. For example,
+        * LCD panel might support different modes and they are listed here.
+        * Similarly for supporting external encoders, lcd controller port
+        * requires a set of non-standard timing values to be listed here for
+        * each supported mode since venc is used in non-standard timing mode
+        * for interfacing with external encoder similar to configuring lcd
+        * panel timings
+        */
+       unsigned int num_modes;
+       struct vpbe_enc_mode_info *modes;
+       /*
+        * Bus configuration goes here for external encoders. Some encoders
+        * may require multiple interface types for each of the output. For
+        * example, SD modes would use YCC8 where as HD mode would use YCC16.
+        * Not sure if this is needed on a per mode basis instead of per
+        * output basis. If per mode is needed, we may have to move this to
+        * mode_info structure
+        */
+};
+
+/* encoder configuration info */
+struct encoder_config_info {
+       char module_name[32];
+       /* Is this an i2c device ? */
+       unsigned int is_i2c:1;
+       /* i2c subdevice board info */
+       struct i2c_board_info board_info;
+};
+
+/* structure for defining vpbe display subsystem components */
+struct vpbe_config {
+       char module_name[32];
+       /* i2c bus adapter no */
+       int i2c_adapter_id;
+       struct osd_config_info osd;
+       struct encoder_config_info venc;
+       /* external encoder information goes here */
+       int num_ext_encoders;
+       struct encoder_config_info *ext_encoders;
+       int num_outputs;
+       /* Order is venc outputs followed by LCD and then external encoders */
+       struct vpbe_output *outputs;
+};
+
+struct vpbe_device;
+
+struct vpbe_device_ops {
+       /* crop cap for the display */
+       int (*g_cropcap)(struct vpbe_device *vpbe_dev,
+                        struct v4l2_cropcap *cropcap);
+
+       /* Enumerate the outputs */
+       int (*enum_outputs)(struct vpbe_device *vpbe_dev,
+                           struct v4l2_output *output);
+
+       /* Set output to the given index */
+       int (*set_output)(struct vpbe_device *vpbe_dev,
+                        int index);
+
+       /* Get current output */
+       unsigned int (*get_output)(struct vpbe_device *vpbe_dev);
+
+       /* Set DV preset at current output */
+       int (*s_dv_preset)(struct vpbe_device *vpbe_dev,
+                          struct v4l2_dv_preset *dv_preset);
+
+       /* Get DV presets supported at the output */
+       int (*g_dv_preset)(struct vpbe_device *vpbe_dev,
+                          struct v4l2_dv_preset *dv_preset);
+
+       /* Enumerate the DV Presets supported at the output */
+       int (*enum_dv_presets)(struct vpbe_device *vpbe_dev,
+                              struct v4l2_dv_enum_preset *preset_info);
+
+       /* Set std at the output */
+       int (*s_std)(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id);
+
+       /* Get the current std at the output */
+       int (*g_std)(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id);
+
+       /* initialize the device */
+       int (*initialize)(struct device *dev, struct vpbe_device *vpbe_dev);
+
+       /* De-initialize the device */
+       void (*deinitialize)(struct device *dev, struct vpbe_device *vpbe_dev);
+
+       /* Get the current mode info */
+       int (*get_mode_info)(struct vpbe_device *vpbe_dev,
+                            struct vpbe_enc_mode_info*);
+
+       /*
+        * Set the current mode in the encoder. Alternate way of setting
+        * standard or DV preset or custom timings in the encoder
+        */
+       int (*set_mode)(struct vpbe_device *vpbe_dev,
+                       struct vpbe_enc_mode_info*);
+       /* Power management operations */
+       int (*suspend)(struct vpbe_device *vpbe_dev);
+       int (*resume)(struct vpbe_device *vpbe_dev);
+};
+
+/* struct for vpbe device */
+struct vpbe_device {
+       /* V4l2 device */
+       struct v4l2_device v4l2_dev;
+       /* vpbe dispay controller cfg */
+       struct vpbe_config *cfg;
+       /* parent device */
+       struct device *pdev;
+       /* external encoder v4l2 sub devices */
+       struct v4l2_subdev **encoders;
+       /* current encoder index */
+       int current_sd_index;
+       struct mutex lock;
+       /* device initialized */
+       int initialized;
+       /* vpbe dac clock */
+       struct clk *dac_clk;
+       /* osd_device pointer */
+       struct osd_state *osd_device;
+       /*
+        * fields below are accessed by users of vpbe_device. Not the
+        * ones above
+        */
+
+       /* current output */
+       int current_out_index;
+       /* lock used by caller to do atomic operation on vpbe device */
+       /* current timings set in the controller */
+       struct vpbe_enc_mode_info current_timings;
+       /* venc sub device */
+       struct v4l2_subdev *venc;
+       /* device operations below */
+       struct vpbe_device_ops ops;
+};
+
+#endif
diff --git a/include/media/davinci/vpbe_display.h b/include/media/davinci/vpbe_display.h
new file mode 100644 (file)
index 0000000..dbf6b37
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.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 version 2.
+ *
+ * This program is distributed WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef VPBE_DISPLAY_H
+#define VPBE_DISPLAY_H
+
+/* Header files */
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/videobuf-dma-contig.h>
+#include <media/davinci/vpbe_types.h>
+#include <media/davinci/vpbe_osd.h>
+#include <media/davinci/vpbe.h>
+
+#define VPBE_DISPLAY_MAX_DEVICES 2
+
+enum vpbe_display_device_id {
+       VPBE_DISPLAY_DEVICE_0,
+       VPBE_DISPLAY_DEVICE_1
+};
+
+#define VPBE_DISPLAY_DRV_NAME  "vpbe-display"
+
+#define VPBE_DISPLAY_MAJOR_RELEASE              1
+#define VPBE_DISPLAY_MINOR_RELEASE              0
+#define VPBE_DISPLAY_BUILD                      1
+#define VPBE_DISPLAY_VERSION_CODE ((VPBE_DISPLAY_MAJOR_RELEASE << 16) | \
+       (VPBE_DISPLAY_MINOR_RELEASE << 8)  | \
+       VPBE_DISPLAY_BUILD)
+
+#define VPBE_DISPLAY_VALID_FIELD(field)   ((V4L2_FIELD_NONE == field) || \
+        (V4L2_FIELD_ANY == field) || (V4L2_FIELD_INTERLACED == field))
+
+/* Exp ratio numerator and denominator constants */
+#define VPBE_DISPLAY_H_EXP_RATIO_N     9
+#define VPBE_DISPLAY_H_EXP_RATIO_D     8
+#define VPBE_DISPLAY_V_EXP_RATIO_N     6
+#define VPBE_DISPLAY_V_EXP_RATIO_D     5
+
+/* Zoom multiplication factor */
+#define VPBE_DISPLAY_ZOOM_4X   4
+#define VPBE_DISPLAY_ZOOM_2X   2
+
+/* Structures */
+struct display_layer_info {
+       int enable;
+       /* Layer ID used by Display Manager */
+       enum osd_layer id;
+       struct osd_layer_config config;
+       enum osd_zoom_factor h_zoom;
+       enum osd_zoom_factor v_zoom;
+       enum osd_h_exp_ratio h_exp;
+       enum osd_v_exp_ratio v_exp;
+};
+
+/* vpbe display object structure */
+struct vpbe_layer {
+       /* number of buffers in fbuffers */
+       unsigned int numbuffers;
+       /* Pointer to the vpbe_display */
+       struct vpbe_display *disp_dev;
+       /* Pointer pointing to current v4l2_buffer */
+       struct videobuf_buffer *cur_frm;
+       /* Pointer pointing to next v4l2_buffer */
+       struct videobuf_buffer *next_frm;
+       /* videobuf specific parameters
+        * Buffer queue used in video-buf
+        */
+       struct videobuf_queue buffer_queue;
+       /* Queue of filled frames */
+       struct list_head dma_queue;
+       /* Used in video-buf */
+       spinlock_t irqlock;
+       /* V4l2 specific parameters */
+       /* Identifies video device for this layer */
+       struct video_device video_dev;
+       /* This field keeps track of type of buffer exchange mechanism user
+        * has selected
+        */
+       enum v4l2_memory memory;
+       /* Used to keep track of state of the priority */
+       struct v4l2_prio_state prio;
+       /* Used to store pixel format */
+       struct v4l2_pix_format pix_fmt;
+       enum v4l2_field buf_field;
+       /* Video layer configuration params */
+       struct display_layer_info layer_info;
+       /* vpbe specific parameters
+        * enable window for display
+        */
+       unsigned char window_enable;
+       /* number of open instances of the layer */
+       unsigned int usrs;
+       /* number of users performing IO */
+       unsigned int io_usrs;
+       /* Indicates id of the field which is being displayed */
+       unsigned int field_id;
+       /* Indicates whether streaming started */
+       unsigned char started;
+       /* Identifies device object */
+       enum vpbe_display_device_id device_id;
+       /* facilitation of ioctl ops lock by v4l2*/
+       struct mutex opslock;
+       u8 layer_first_int;
+};
+
+/* vpbe device structure */
+struct vpbe_display {
+       /* layer specific parameters */
+       /* lock for isr updates to buf layers*/
+       spinlock_t dma_queue_lock;
+       /* C-Plane offset from start of y-plane */
+       unsigned int cbcr_ofst;
+       struct vpbe_layer *dev[VPBE_DISPLAY_MAX_DEVICES];
+       struct vpbe_device *vpbe_dev;
+       struct osd_state *osd_device;
+};
+
+/* File handle structure */
+struct vpbe_fh {
+       /* vpbe device structure */
+       struct vpbe_display *disp_dev;
+       /* pointer to layer object for opened device */
+       struct vpbe_layer *layer;
+       /* Indicates whether this file handle is doing IO */
+       unsigned char io_allowed;
+       /* Used to keep track priority of this instance */
+       enum v4l2_priority prio;
+};
+
+struct buf_config_params {
+       unsigned char min_numbuffers;
+       unsigned char numbuffers[VPBE_DISPLAY_MAX_DEVICES];
+       unsigned int min_bufsize[VPBE_DISPLAY_MAX_DEVICES];
+       unsigned int layer_bufsize[VPBE_DISPLAY_MAX_DEVICES];
+};
+
+#endif /* VPBE_DISPLAY_H */
diff --git a/include/media/davinci/vpbe_osd.h b/include/media/davinci/vpbe_osd.h
new file mode 100644 (file)
index 0000000..d7e397a
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2007-2009 Texas Instruments Inc
+ * Copyright (C) 2007 MontaVista Software, Inc.
+ *
+ * Andy Lowe (alowe@mvista.com), MontaVista Software
+ * - Initial version
+ * Murali Karicheri (mkaricheri@gmail.com), Texas Instruments Ltd.
+ * - ported to sub device interface
+ *
+ * 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..
+ *
+ * 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 _OSD_H
+#define _OSD_H
+
+#include <media/davinci/vpbe_types.h>
+
+#define VPBE_OSD_SUBDEV_NAME "vpbe-osd"
+
+/**
+ * enum osd_layer
+ * @WIN_OSD0: On-Screen Display Window 0
+ * @WIN_VID0: Video Window 0
+ * @WIN_OSD1: On-Screen Display Window 1
+ * @WIN_VID1: Video Window 1
+ *
+ * Description:
+ * An enumeration of the osd display layers.
+ */
+enum osd_layer {
+       WIN_OSD0,
+       WIN_VID0,
+       WIN_OSD1,
+       WIN_VID1,
+};
+
+/**
+ * enum osd_win_layer
+ * @OSDWIN_OSD0: On-Screen Display Window 0
+ * @OSDWIN_OSD1: On-Screen Display Window 1
+ *
+ * Description:
+ * An enumeration of the OSD Window layers.
+ */
+enum osd_win_layer {
+       OSDWIN_OSD0,
+       OSDWIN_OSD1,
+};
+
+/**
+ * enum osd_pix_format
+ * @PIXFMT_1BPP: 1-bit-per-pixel bitmap
+ * @PIXFMT_2BPP: 2-bits-per-pixel bitmap
+ * @PIXFMT_4BPP: 4-bits-per-pixel bitmap
+ * @PIXFMT_8BPP: 8-bits-per-pixel bitmap
+ * @PIXFMT_RGB565: 16-bits-per-pixel RGB565
+ * @PIXFMT_YCbCrI: YUV 4:2:2
+ * @PIXFMT_RGB888: 24-bits-per-pixel RGB888
+ * @PIXFMT_YCrCbI: YUV 4:2:2 with chroma swap
+ * @PIXFMT_NV12: YUV 4:2:0 planar
+ * @PIXFMT_OSD_ATTR: OSD Attribute Window pixel format (4bpp)
+ *
+ * Description:
+ * An enumeration of the DaVinci pixel formats.
+ */
+enum osd_pix_format {
+       PIXFMT_1BPP = 0,
+       PIXFMT_2BPP,
+       PIXFMT_4BPP,
+       PIXFMT_8BPP,
+       PIXFMT_RGB565,
+       PIXFMT_YCbCrI,
+       PIXFMT_RGB888,
+       PIXFMT_YCrCbI,
+       PIXFMT_NV12,
+       PIXFMT_OSD_ATTR,
+};
+
+/**
+ * enum osd_h_exp_ratio
+ * @H_EXP_OFF: no expansion (1/1)
+ * @H_EXP_9_OVER_8: 9/8 expansion ratio
+ * @H_EXP_3_OVER_2: 3/2 expansion ratio
+ *
+ * Description:
+ * An enumeration of the available horizontal expansion ratios.
+ */
+enum osd_h_exp_ratio {
+       H_EXP_OFF,
+       H_EXP_9_OVER_8,
+       H_EXP_3_OVER_2,
+};
+
+/**
+ * enum osd_v_exp_ratio
+ * @V_EXP_OFF: no expansion (1/1)
+ * @V_EXP_6_OVER_5: 6/5 expansion ratio
+ *
+ * Description:
+ * An enumeration of the available vertical expansion ratios.
+ */
+enum osd_v_exp_ratio {
+       V_EXP_OFF,
+       V_EXP_6_OVER_5,
+};
+
+/**
+ * enum osd_zoom_factor
+ * @ZOOM_X1: no zoom (x1)
+ * @ZOOM_X2: x2 zoom
+ * @ZOOM_X4: x4 zoom
+ *
+ * Description:
+ * An enumeration of the available zoom factors.
+ */
+enum osd_zoom_factor {
+       ZOOM_X1,
+       ZOOM_X2,
+       ZOOM_X4,
+};
+
+/**
+ * enum osd_clut
+ * @ROM_CLUT: ROM CLUT
+ * @RAM_CLUT: RAM CLUT
+ *
+ * Description:
+ * An enumeration of the available Color Lookup Tables (CLUTs).
+ */
+enum osd_clut {
+       ROM_CLUT,
+       RAM_CLUT,
+};
+
+/**
+ * enum osd_rom_clut
+ * @ROM_CLUT0: Macintosh CLUT
+ * @ROM_CLUT1: CLUT from DM270 and prior devices
+ *
+ * Description:
+ * An enumeration of the ROM Color Lookup Table (CLUT) options.
+ */
+enum osd_rom_clut {
+       ROM_CLUT0,
+       ROM_CLUT1,
+};
+
+/**
+ * enum osd_blending_factor
+ * @OSD_0_VID_8: OSD pixels are fully transparent
+ * @OSD_1_VID_7: OSD pixels contribute 1/8, video pixels contribute 7/8
+ * @OSD_2_VID_6: OSD pixels contribute 2/8, video pixels contribute 6/8
+ * @OSD_3_VID_5: OSD pixels contribute 3/8, video pixels contribute 5/8
+ * @OSD_4_VID_4: OSD pixels contribute 4/8, video pixels contribute 4/8
+ * @OSD_5_VID_3: OSD pixels contribute 5/8, video pixels contribute 3/8
+ * @OSD_6_VID_2: OSD pixels contribute 6/8, video pixels contribute 2/8
+ * @OSD_8_VID_0: OSD pixels are fully opaque
+ *
+ * Description:
+ * An enumeration of the DaVinci pixel blending factor options.
+ */
+enum osd_blending_factor {
+       OSD_0_VID_8,
+       OSD_1_VID_7,
+       OSD_2_VID_6,
+       OSD_3_VID_5,
+       OSD_4_VID_4,
+       OSD_5_VID_3,
+       OSD_6_VID_2,
+       OSD_8_VID_0,
+};
+
+/**
+ * enum osd_blink_interval
+ * @BLINK_X1: blink interval is 1 vertical refresh cycle
+ * @BLINK_X2: blink interval is 2 vertical refresh cycles
+ * @BLINK_X3: blink interval is 3 vertical refresh cycles
+ * @BLINK_X4: blink interval is 4 vertical refresh cycles
+ *
+ * Description:
+ * An enumeration of the DaVinci pixel blinking interval options.
+ */
+enum osd_blink_interval {
+       BLINK_X1,
+       BLINK_X2,
+       BLINK_X3,
+       BLINK_X4,
+};
+
+/**
+ * enum osd_cursor_h_width
+ * @H_WIDTH_1: horizontal line width is 1 pixel
+ * @H_WIDTH_4: horizontal line width is 4 pixels
+ * @H_WIDTH_8: horizontal line width is 8 pixels
+ * @H_WIDTH_12: horizontal line width is 12 pixels
+ * @H_WIDTH_16: horizontal line width is 16 pixels
+ * @H_WIDTH_20: horizontal line width is 20 pixels
+ * @H_WIDTH_24: horizontal line width is 24 pixels
+ * @H_WIDTH_28: horizontal line width is 28 pixels
+ */
+enum osd_cursor_h_width {
+       H_WIDTH_1,
+       H_WIDTH_4,
+       H_WIDTH_8,
+       H_WIDTH_12,
+       H_WIDTH_16,
+       H_WIDTH_20,
+       H_WIDTH_24,
+       H_WIDTH_28,
+};
+
+/**
+ * enum davinci_cursor_v_width
+ * @V_WIDTH_1: vertical line width is 1 line
+ * @V_WIDTH_2: vertical line width is 2 lines
+ * @V_WIDTH_4: vertical line width is 4 lines
+ * @V_WIDTH_6: vertical line width is 6 lines
+ * @V_WIDTH_8: vertical line width is 8 lines
+ * @V_WIDTH_10: vertical line width is 10 lines
+ * @V_WIDTH_12: vertical line width is 12 lines
+ * @V_WIDTH_14: vertical line width is 14 lines
+ */
+enum osd_cursor_v_width {
+       V_WIDTH_1,
+       V_WIDTH_2,
+       V_WIDTH_4,
+       V_WIDTH_6,
+       V_WIDTH_8,
+       V_WIDTH_10,
+       V_WIDTH_12,
+       V_WIDTH_14,
+};
+
+/**
+ * struct osd_cursor_config
+ * @xsize: horizontal size in pixels
+ * @ysize: vertical size in lines
+ * @xpos: horizontal offset in pixels from the left edge of the display
+ * @ypos: vertical offset in lines from the top of the display
+ * @interlaced: Non-zero if the display is interlaced, or zero otherwise
+ * @h_width: horizontal line width
+ * @v_width: vertical line width
+ * @clut: the CLUT selector (ROM or RAM) for the cursor color
+ * @clut_index: an index into the CLUT for the cursor color
+ *
+ * Description:
+ * A structure describing the configuration parameters of the hardware
+ * rectangular cursor.
+ */
+struct osd_cursor_config {
+       unsigned xsize;
+       unsigned ysize;
+       unsigned xpos;
+       unsigned ypos;
+       int interlaced;
+       enum osd_cursor_h_width h_width;
+       enum osd_cursor_v_width v_width;
+       enum osd_clut clut;
+       unsigned char clut_index;
+};
+
+/**
+ * struct osd_layer_config
+ * @pixfmt: pixel format
+ * @line_length: offset in bytes between start of each line in memory
+ * @xsize: number of horizontal pixels displayed per line
+ * @ysize: number of lines displayed
+ * @xpos: horizontal offset in pixels from the left edge of the display
+ * @ypos: vertical offset in lines from the top of the display
+ * @interlaced: Non-zero if the display is interlaced, or zero otherwise
+ *
+ * Description:
+ * A structure describing the configuration parameters of an On-Screen Display
+ * (OSD) or video layer related to how the image is stored in memory.
+ * @line_length must be a multiple of the cache line size (32 bytes).
+ */
+struct osd_layer_config {
+       enum osd_pix_format pixfmt;
+       unsigned line_length;
+       unsigned xsize;
+       unsigned ysize;
+       unsigned xpos;
+       unsigned ypos;
+       int interlaced;
+};
+
+/* parameters that apply on a per-window (OSD or video) basis */
+struct osd_window_state {
+       int is_allocated;
+       int is_enabled;
+       unsigned long fb_base_phys;
+       enum osd_zoom_factor h_zoom;
+       enum osd_zoom_factor v_zoom;
+       struct osd_layer_config lconfig;
+};
+
+/* parameters that apply on a per-OSD-window basis */
+struct osd_osdwin_state {
+       enum osd_clut clut;
+       enum osd_blending_factor blend;
+       int colorkey_blending;
+       unsigned colorkey;
+       int rec601_attenuation;
+       /* index is pixel value */
+       unsigned char palette_map[16];
+};
+
+/* hardware rectangular cursor parameters */
+struct osd_cursor_state {
+       int is_enabled;
+       struct osd_cursor_config config;
+};
+
+struct osd_state;
+
+struct vpbe_osd_ops {
+       int (*initialize)(struct osd_state *sd);
+       int (*request_layer)(struct osd_state *sd, enum osd_layer layer);
+       void (*release_layer)(struct osd_state *sd, enum osd_layer layer);
+       int (*enable_layer)(struct osd_state *sd, enum osd_layer layer,
+                           int otherwin);
+       void (*disable_layer)(struct osd_state *sd, enum osd_layer layer);
+       int (*set_layer_config)(struct osd_state *sd, enum osd_layer layer,
+                               struct osd_layer_config *lconfig);
+       void (*get_layer_config)(struct osd_state *sd, enum osd_layer layer,
+                                struct osd_layer_config *lconfig);
+       void (*start_layer)(struct osd_state *sd, enum osd_layer layer,
+                           unsigned long fb_base_phys,
+                           unsigned long cbcr_ofst);
+       void (*set_left_margin)(struct osd_state *sd, u32 val);
+       void (*set_top_margin)(struct osd_state *sd, u32 val);
+       void (*set_interpolation_filter)(struct osd_state *sd, int filter);
+       int (*set_vid_expansion)(struct osd_state *sd,
+                                       enum osd_h_exp_ratio h_exp,
+                                       enum osd_v_exp_ratio v_exp);
+       void (*get_vid_expansion)(struct osd_state *sd,
+                                       enum osd_h_exp_ratio *h_exp,
+                                       enum osd_v_exp_ratio *v_exp);
+       void (*set_zoom)(struct osd_state *sd, enum osd_layer layer,
+                               enum osd_zoom_factor h_zoom,
+                               enum osd_zoom_factor v_zoom);
+};
+
+struct osd_state {
+       enum vpbe_version vpbe_type;
+       spinlock_t lock;
+       struct device *dev;
+       dma_addr_t osd_base_phys;
+       unsigned long osd_base;
+       unsigned long osd_size;
+       /* 1-->the isr will toggle the VID0 ping-pong buffer */
+       int pingpong;
+       int interpolation_filter;
+       int field_inversion;
+       enum osd_h_exp_ratio osd_h_exp;
+       enum osd_v_exp_ratio osd_v_exp;
+       enum osd_h_exp_ratio vid_h_exp;
+       enum osd_v_exp_ratio vid_v_exp;
+       enum osd_clut backg_clut;
+       unsigned backg_clut_index;
+       enum osd_rom_clut rom_clut;
+       int is_blinking;
+       /* attribute window blinking enabled */
+       enum osd_blink_interval blink;
+       /* YCbCrI or YCrCbI */
+       enum osd_pix_format yc_pixfmt;
+       /* columns are Y, Cb, Cr */
+       unsigned char clut_ram[256][3];
+       struct osd_cursor_state cursor;
+       /* OSD0, VID0, OSD1, VID1 */
+       struct osd_window_state win[4];
+       /* OSD0, OSD1 */
+       struct osd_osdwin_state osdwin[2];
+       /* OSD device Operations */
+       struct vpbe_osd_ops ops;
+};
+
+struct osd_platform_data {
+       enum vpbe_version vpbe_type;
+       int  field_inv_wa_enable;
+};
+
+#endif
diff --git a/include/media/davinci/vpbe_types.h b/include/media/davinci/vpbe_types.h
new file mode 100644 (file)
index 0000000..727f551
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2010 Texas Instruments 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 version 2.
+ *
+ * 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 _VPBE_TYPES_H
+#define _VPBE_TYPES_H
+
+enum vpbe_version {
+       VPBE_VERSION_1 = 1,
+       VPBE_VERSION_2,
+       VPBE_VERSION_3,
+};
+
+/* vpbe_timing_type - Timing types used in vpbe device */
+enum vpbe_enc_timings_type {
+       VPBE_ENC_STD = 0x1,
+       VPBE_ENC_DV_PRESET = 0x2,
+       VPBE_ENC_CUSTOM_TIMINGS = 0x4,
+       /* Used when set timings through FB device interface */
+       VPBE_ENC_TIMINGS_INVALID = 0x8,
+};
+
+union vpbe_timings {
+       v4l2_std_id std_id;
+       unsigned int dv_preset;
+};
+
+/*
+ * struct vpbe_enc_mode_info
+ * @name: ptr to name string of the standard, "NTSC", "PAL" etc
+ * @std: standard or non-standard mode. 1 - standard, 0 - nonstandard
+ * @interlaced: 1 - interlaced, 0 - non interlaced/progressive
+ * @xres: x or horizontal resolution of the display
+ * @yres: y or vertical resolution of the display
+ * @fps: frame per second
+ * @left_margin: left margin of the display
+ * @right_margin: right margin of the display
+ * @upper_margin: upper margin of the display
+ * @lower_margin: lower margin of the display
+ * @hsync_len: h-sync length
+ * @vsync_len: v-sync length
+ * @flags: bit field: bit usage is documented below
+ *
+ * Description:
+ *  Structure holding timing and resolution information of a standard.
+ * Used by vpbe_device to set required non-standard timing in the
+ * venc when lcd controller output is connected to a external encoder.
+ * A table of timings is maintained in vpbe device to set this in
+ * venc when external encoder is connected to lcd controller output.
+ * Encoder may provide a g_dv_timings() API to override these values
+ * as needed.
+ *
+ *  Notes
+ *  ------
+ *  if_type should be used only by encoder manager and encoder.
+ *  flags usage
+ *     b0 (LSB) - hsync polarity, 0 - negative, 1 - positive
+ *     b1       - vsync polarity, 0 - negative, 1 - positive
+ *     b2       - field id polarity, 0 - negative, 1  - positive
+ */
+struct vpbe_enc_mode_info {
+       unsigned char *name;
+       enum vpbe_enc_timings_type timings_type;
+       union vpbe_timings timings;
+       unsigned int interlaced;
+       unsigned int xres;
+       unsigned int yres;
+       struct v4l2_fract aspect;
+       struct v4l2_fract fps;
+       unsigned int left_margin;
+       unsigned int right_margin;
+       unsigned int upper_margin;
+       unsigned int lower_margin;
+       unsigned int hsync_len;
+       unsigned int vsync_len;
+       unsigned int flags;
+};
+
+#endif
diff --git a/include/media/davinci/vpbe_venc.h b/include/media/davinci/vpbe_venc.h
new file mode 100644 (file)
index 0000000..426c205
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 Texas Instruments 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 version 2.
+ *
+ * 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 _VPBE_VENC_H
+#define _VPBE_VENC_H
+
+#include <media/v4l2-subdev.h>
+#include <media/davinci/vpbe_types.h>
+
+#define VPBE_VENC_SUBDEV_NAME "vpbe-venc"
+
+/* venc events */
+#define VENC_END_OF_FRAME      BIT(0)
+#define VENC_FIRST_FIELD       BIT(1)
+#define VENC_SECOND_FIELD      BIT(2)
+
+struct venc_platform_data {
+       enum vpbe_version venc_type;
+       int (*setup_clock)(enum vpbe_enc_timings_type type,
+                          unsigned int mode);
+       /* Number of LCD outputs supported */
+       int num_lcd_outputs;
+};
+
+enum venc_ioctls {
+       VENC_GET_FLD = 1,
+};
+
+/* exported functions */
+struct v4l2_subdev *venc_sub_dev_init(struct v4l2_device *v4l2_dev,
+               const char *venc_name);
+#endif
diff --git a/include/media/mmp-camera.h b/include/media/mmp-camera.h
new file mode 100644 (file)
index 0000000..7611963
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * Information for the Marvell Armada MMP camera
+ */
+
+struct mmp_camera_platform_data {
+       struct platform_device *i2c_device;
+       int sensor_power_gpio;
+       int sensor_reset_gpio;
+};
index 60536c7..b1f19b7 100644 (file)
@@ -117,7 +117,7 @@ struct rc_dev {
        int                             (*s_tx_carrier)(struct rc_dev *dev, u32 carrier);
        int                             (*s_tx_duty_cycle)(struct rc_dev *dev, u32 duty_cycle);
        int                             (*s_rx_carrier_range)(struct rc_dev *dev, u32 min, u32 max);
-       int                             (*tx_ir)(struct rc_dev *dev, int *txbuf, u32 n);
+       int                             (*tx_ir)(struct rc_dev *dev, unsigned *txbuf, unsigned n);
        void                            (*s_idle)(struct rc_dev *dev, bool enable);
        int                             (*s_learning_mode)(struct rc_dev *dev, int enable);
        int                             (*s_carrier_report) (struct rc_dev *dev, int enable);
index 4e1409e..17c9759 100644 (file)
 #define RC_TYPE_JVC    (1  << 3)       /* JVC protocol */
 #define RC_TYPE_SONY   (1  << 4)       /* Sony12/15/20 protocol */
 #define RC_TYPE_RC5_SZ (1  << 5)       /* RC5 variant used by Streamzap */
+#define RC_TYPE_MCE_KBD        (1  << 29)      /* RC6-ish MCE keyboard/mouse */
 #define RC_TYPE_LIRC   (1  << 30)      /* Pass raw IR to lirc userspace */
 #define RC_TYPE_OTHER  (1u << 31)
 
 #define RC_TYPE_ALL (RC_TYPE_RC5 | RC_TYPE_NEC  | RC_TYPE_RC6  | \
                     RC_TYPE_JVC | RC_TYPE_SONY | RC_TYPE_LIRC | \
-                    RC_TYPE_RC5_SZ | RC_TYPE_OTHER)
+                    RC_TYPE_RC5_SZ | RC_TYPE_MCE_KBD | RC_TYPE_OTHER)
 
 struct rc_map_table {
        u32     scancode;
index 80346a6..48413b4 100644 (file)
@@ -7,10 +7,18 @@
 #define SH_CEU_FLAG_VSYNC_LOW          (1 << 3) /* default High if possible */
 
 struct device;
+struct resource;
+
+struct sh_mobile_ceu_companion {
+       u32             num_resources;
+       struct resource *resource;
+       int             id;
+       void            *platform_data;
+};
 
 struct sh_mobile_ceu_info {
        unsigned long flags;
-       struct device *csi2_dev;
+       struct sh_mobile_ceu_companion *csi2;
 };
 
 #endif /* __ASM_SH_MOBILE_CEU_H__ */
index 4d26151..c586c4f 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef SH_MIPI_CSI
 #define SH_MIPI_CSI
 
+#include <linux/list.h>
+
 enum sh_csi2_phy {
        SH_CSI2_PHY_MAIN,
        SH_CSI2_PHY_SUB,
@@ -33,14 +35,14 @@ struct sh_csi2_client_config {
        struct platform_device *pdev;   /* client platform device */
 };
 
+struct v4l2_device;
+
 struct sh_csi2_pdata {
        enum sh_csi2_type type;
        unsigned int flags;
        struct sh_csi2_client_config *clients;
        int num_clients;
+       struct v4l2_device *v4l2_dev;
 };
 
-struct device;
-struct v4l2_device;
-
 #endif
index 238bd33..7582952 100644 (file)
 #include <media/videobuf2-core.h>
 #include <media/v4l2-device.h>
 
-extern struct bus_type soc_camera_bus_type;
-
 struct file;
+struct soc_camera_link;
 
 struct soc_camera_device {
-       struct list_head list;
-       struct device dev;
+       struct list_head list;          /* list of all registered devices */
+       struct soc_camera_link *link;
        struct device *pdev;            /* Platform device */
+       struct device *parent;          /* Camera host device */
+       struct device *control;         /* E.g., the i2c client */
        s32 user_width;
        s32 user_height;
        u32 bytesperline;               /* for padding, zero if unused */
@@ -66,8 +67,6 @@ struct soc_camera_host_ops {
        struct module *owner;
        int (*add)(struct soc_camera_device *);
        void (*remove)(struct soc_camera_device *);
-       int (*suspend)(struct soc_camera_device *, pm_message_t);
-       int (*resume)(struct soc_camera_device *);
        /*
         * .get_formats() is called for each client device format, but
         * .put_formats() is only called once. Further, if any of the calls to
@@ -109,12 +108,6 @@ struct soc_camera_host_ops {
 #define SOCAM_SENSOR_INVERT_HSYNC      (1 << 2)
 #define SOCAM_SENSOR_INVERT_VSYNC      (1 << 3)
 #define SOCAM_SENSOR_INVERT_DATA       (1 << 4)
-#define SOCAM_MIPI_1LANE               (1 << 5)
-#define SOCAM_MIPI_2LANE               (1 << 6)
-#define SOCAM_MIPI_3LANE               (1 << 7)
-#define SOCAM_MIPI_4LANE               (1 << 8)
-#define SOCAM_MIPI     (SOCAM_MIPI_1LANE | SOCAM_MIPI_2LANE | \
-                       SOCAM_MIPI_3LANE | SOCAM_MIPI_4LANE)
 
 struct i2c_board_info;
 struct regulator_bulk_data;
@@ -134,11 +127,11 @@ struct soc_camera_link {
        int num_regulators;
 
        /*
-        * For non-I2C devices platform platform has to provide methods to
-        * add a device to the system and to remove
+        * For non-I2C devices platform has to provide methods to add a device
+        * to the system and to remove it
         */
-       int (*add_device)(struct soc_camera_link *, struct device *);
-       void (*del_device)(struct soc_camera_link *);
+       int (*add_device)(struct soc_camera_device *);
+       void (*del_device)(struct soc_camera_device *);
        /* Optional callbacks to power on or off and reset the sensor */
        int (*power)(struct device *, int);
        int (*reset)(struct device *);
@@ -152,12 +145,6 @@ struct soc_camera_link {
        void (*free_bus)(struct soc_camera_link *);
 };
 
-static inline struct soc_camera_device *to_soc_camera_dev(
-       const struct device *dev)
-{
-       return container_of(dev, struct soc_camera_device, dev);
-}
-
 static inline struct soc_camera_host *to_soc_camera_host(
        const struct device *dev)
 {
@@ -169,13 +156,13 @@ static inline struct soc_camera_host *to_soc_camera_host(
 static inline struct soc_camera_link *to_soc_camera_link(
        const struct soc_camera_device *icd)
 {
-       return icd->dev.platform_data;
+       return icd->link;
 }
 
 static inline struct device *to_soc_camera_control(
        const struct soc_camera_device *icd)
 {
-       return dev_get_drvdata(&icd->dev);
+       return icd->control;
 }
 
 static inline struct v4l2_subdev *soc_camera_to_subdev(
@@ -207,11 +194,8 @@ struct soc_camera_format_xlate {
 };
 
 struct soc_camera_ops {
-       int (*suspend)(struct soc_camera_device *, pm_message_t state);
-       int (*resume)(struct soc_camera_device *);
        unsigned long (*query_bus_param)(struct soc_camera_device *);
        int (*set_bus_param)(struct soc_camera_device *, unsigned long);
-       int (*enum_input)(struct soc_camera_device *, struct v4l2_input *);
        const struct v4l2_queryctrl *controls;
        int num_controls;
 };
@@ -270,6 +254,12 @@ static inline struct v4l2_queryctrl const *soc_camera_find_qctrl(
 #define SOCAM_PCLK_SAMPLE_FALLING      (1 << 13)
 #define SOCAM_DATA_ACTIVE_HIGH         (1 << 14)
 #define SOCAM_DATA_ACTIVE_LOW          (1 << 15)
+#define SOCAM_MIPI_1LANE               (1 << 16)
+#define SOCAM_MIPI_2LANE               (1 << 17)
+#define SOCAM_MIPI_3LANE               (1 << 18)
+#define SOCAM_MIPI_4LANE               (1 << 19)
+#define SOCAM_MIPI     (SOCAM_MIPI_1LANE | SOCAM_MIPI_2LANE | \
+                       SOCAM_MIPI_3LANE | SOCAM_MIPI_4LANE)
 
 #define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_4 | SOCAM_DATAWIDTH_8 | \
                              SOCAM_DATAWIDTH_9 | SOCAM_DATAWIDTH_10 | \
index 6d7a4fd..74f0fa1 100644 (file)
@@ -21,7 +21,7 @@ struct soc_camera_platform_info {
        unsigned long format_depth;
        struct v4l2_mbus_framefmt format;
        unsigned long bus_param;
-       struct device *dev;
+       struct soc_camera_device *icd;
        int (*set_capture)(struct soc_camera_platform_info *info, int enable);
 };
 
@@ -30,8 +30,7 @@ static inline void soc_camera_platform_release(struct platform_device **pdev)
        *pdev = NULL;
 }
 
-static inline int soc_camera_platform_add(const struct soc_camera_link *icl,
-                                         struct device *dev,
+static inline int soc_camera_platform_add(struct soc_camera_device *icd,
                                          struct platform_device **pdev,
                                          struct soc_camera_link *plink,
                                          void (*release)(struct device *dev),
@@ -40,7 +39,7 @@ static inline int soc_camera_platform_add(const struct soc_camera_link *icl,
        struct soc_camera_platform_info *info = plink->priv;
        int ret;
 
-       if (icl != plink)
+       if (icd->link != plink)
                return -ENODEV;
 
        if (*pdev)
@@ -50,7 +49,7 @@ static inline int soc_camera_platform_add(const struct soc_camera_link *icl,
        if (!*pdev)
                return -ENOMEM;
 
-       info->dev = dev;
+       info->icd = icd;
 
        (*pdev)->dev.platform_data = info;
        (*pdev)->dev.release = release;
@@ -59,17 +58,17 @@ static inline int soc_camera_platform_add(const struct soc_camera_link *icl,
        if (ret < 0) {
                platform_device_put(*pdev);
                *pdev = NULL;
-               info->dev = NULL;
+               info->icd = NULL;
        }
 
        return ret;
 }
 
-static inline void soc_camera_platform_del(const struct soc_camera_link *icl,
+static inline void soc_camera_platform_del(const struct soc_camera_device *icd,
                                           struct platform_device *pdev,
                                           const struct soc_camera_link *plink)
 {
-       if (icl != plink || !pdev)
+       if (icd->link != plink || !pdev)
                return;
 
        platform_device_unregister(pdev);
index a59a848..a40a6a3 100644 (file)
 
 struct timb_radio_platform_data {
        int i2c_adapter; /* I2C adapter where the tuner and dsp are attached */
-       struct {
-               struct i2c_board_info *info;
-       } tuner;
-       struct {
-               const char *module_name;
-               struct i2c_board_info *info;
-       } dsp;
+       struct i2c_board_info *tuner;
+       struct i2c_board_info *dsp;
 };
 
 #endif
index 963e334..89c290b 100644 (file)
 #define TUNER_PHILIPS_FMD1216MEX_MK3   78
 #define TUNER_PHILIPS_FM1216MK5                79
 #define TUNER_PHILIPS_FQ1216LME_MK3    80      /* Active loopthrough, no FM */
+#define TUNER_XC4000                   81      /* Xceive Silicon Tuner */
+
 #define TUNER_PARTSNIC_PTI_5NF05       81
 #define TUNER_PHILIPS_CU1216L           82
 #define TUNER_NXP_TDA18271             83
index b3edb67..63fd9d3 100644 (file)
@@ -76,6 +76,7 @@ enum {
        V4L2_IDENT_OV6650 = 258,
        V4L2_IDENT_OV2640 = 259,
        V4L2_IDENT_OV9740 = 260,
+       V4L2_IDENT_OV5642 = 261,
 
        /* module saa7146: reserved range 300-309 */
        V4L2_IDENT_SAA7146 = 300,
@@ -185,8 +186,9 @@ enum {
        /* module wm8775: just ident 8775 */
        V4L2_IDENT_WM8775 = 8775,
 
-       /* module cafe_ccic, just ident 8801 */
+       /* Marvell controllers starting at 8801 */
        V4L2_IDENT_CAFE = 8801,
+       V4L2_IDENT_ARMADA610 = 8802,
 
        /* AKM AK8813/AK8814 */
        V4L2_IDENT_AK8813 = 8813,
index 97d0638..13fe4d7 100644 (file)
 
 /* forward references */
 struct v4l2_ctrl_handler;
+struct v4l2_ctrl_helper;
 struct v4l2_ctrl;
 struct video_device;
 struct v4l2_subdev;
+struct v4l2_subscribed_event;
+struct v4l2_fh;
 
 /** struct v4l2_ctrl_ops - The control operations that the driver has to provide.
   * @g_volatile_ctrl: Get a new value for this control. Generally only relevant
@@ -51,6 +54,7 @@ struct v4l2_ctrl_ops {
 
 /** struct v4l2_ctrl - The control structure.
   * @node:     The list node.
+  * @ev_subs:  The list of control event subscriptions.
   * @handler:  The handler that owns the control.
   * @cluster:  Point to start of cluster array.
   * @ncontrols:        Number of controls in cluster array.
@@ -65,6 +69,15 @@ struct v4l2_ctrl_ops {
   *            control's current value cannot be cached and needs to be
   *            retrieved through the g_volatile_ctrl op. Drivers can set
   *            this flag.
+  * @is_auto:   If set, then this control selects whether the other cluster
+  *            members are in 'automatic' mode or 'manual' mode. This is
+  *            used for autogain/gain type clusters. Drivers should never
+  *            set this flag directly.
+  * @manual_mode_value: If the is_auto flag is set, then this is the value
+  *            of the auto control that determines if that control is in
+  *            manual mode. So if the value of the auto control equals this
+  *            value, then the whole cluster is in manual mode. Drivers should
+  *            never set this flag directly.
   * @ops:      The control ops.
   * @id:       The control ID.
   * @name:     The control name.
@@ -97,6 +110,7 @@ struct v4l2_ctrl_ops {
 struct v4l2_ctrl {
        /* Administrative fields */
        struct list_head node;
+       struct list_head ev_subs;
        struct v4l2_ctrl_handler *handler;
        struct v4l2_ctrl **cluster;
        unsigned ncontrols;
@@ -105,6 +119,8 @@ struct v4l2_ctrl {
        unsigned int is_new:1;
        unsigned int is_private:1;
        unsigned int is_volatile:1;
+       unsigned int is_auto:1;
+       unsigned int manual_mode_value:8;
 
        const struct v4l2_ctrl_ops *ops;
        u32 id;
@@ -134,6 +150,7 @@ struct v4l2_ctrl {
   * @node:     List node for the sorted list.
   * @next:     Single-link list node for the hash.
   * @ctrl:     The actual control information.
+  * @helper:   Pointer to helper struct. Used internally in prepare_ext_ctrls().
   *
   * Each control handler has a list of these refs. The list_head is used to
   * keep a sorted-by-control-ID list of all controls, while the next pointer
@@ -143,6 +160,7 @@ struct v4l2_ctrl_ref {
        struct list_head node;
        struct v4l2_ctrl_ref *next;
        struct v4l2_ctrl *ctrl;
+       struct v4l2_ctrl_helper *helper;
 };
 
 /** struct v4l2_ctrl_handler - The control handler keeps track of all the
@@ -363,6 +381,40 @@ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
 void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls);
 
 
+/** v4l2_ctrl_auto_cluster() - Mark all controls in the cluster as belonging to
+  * that cluster and set it up for autofoo/foo-type handling.
+  * @ncontrols:        The number of controls in this cluster.
+  * @controls: The cluster control array of size @ncontrols. The first control
+  *            must be the 'auto' control (e.g. autogain, autoexposure, etc.)
+  * @manual_val: The value for the first control in the cluster that equals the
+  *            manual setting.
+  * @set_volatile: If true, then all controls except the first auto control will
+  *            have is_volatile set to true. If false, then is_volatile will not
+  *            be touched.
+  *
+  * Use for control groups where one control selects some automatic feature and
+  * the other controls are only active whenever the automatic feature is turned
+  * off (manual mode). Typical examples: autogain vs gain, auto-whitebalance vs
+  * red and blue balance, etc.
+  *
+  * The behavior of such controls is as follows:
+  *
+  * When the autofoo control is set to automatic, then any manual controls
+  * are set to inactive and any reads will call g_volatile_ctrl (if the control
+  * was marked volatile).
+  *
+  * When the autofoo control is set to manual, then any manual controls will
+  * be marked active, and any reads will just return the current value without
+  * going through g_volatile_ctrl.
+  *
+  * In addition, this function will set the V4L2_CTRL_FLAG_UPDATE flag
+  * on the autofoo control and V4L2_CTRL_FLAG_INACTIVE on the foo control(s)
+  * if autofoo is in auto mode.
+  */
+void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
+                       u8 manual_val, bool set_volatile);
+
+
 /** v4l2_ctrl_find() - Find a control with the given ID.
   * @hdl:      The control handler.
   * @id:       The control ID to find.
@@ -379,9 +431,9 @@ struct v4l2_ctrl *v4l2_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id);
   * This sets or clears the V4L2_CTRL_FLAG_INACTIVE flag atomically.
   * Does nothing if @ctrl == NULL.
   * This will usually be called from within the s_ctrl op.
+  * The V4L2_EVENT_CTRL event will be generated afterwards.
   *
-  * This function can be called regardless of whether the control handler
-  * is locked or not.
+  * This function assumes that the control handler is locked.
   */
 void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active);
 
@@ -391,11 +443,12 @@ void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active);
   *
   * This sets or clears the V4L2_CTRL_FLAG_GRABBED flag atomically.
   * Does nothing if @ctrl == NULL.
+  * The V4L2_EVENT_CTRL event will be generated afterwards.
   * This will usually be called when starting or stopping streaming in the
   * driver.
   *
-  * This function can be called regardless of whether the control handler
-  * is locked or not.
+  * This function assumes that the control handler is not locked and will
+  * take the lock itself.
   */
 void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed);
 
@@ -440,15 +493,22 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
   */
 int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
 
+/* Internal helper functions that deal with control events. */
+void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl,
+               struct v4l2_subscribed_event *sev);
+void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl,
+               struct v4l2_subscribed_event *sev);
 
 /* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */
 int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc);
 int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm);
 int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl);
-int v4l2_s_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl);
+int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
+                                               struct v4l2_control *ctrl);
 int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c);
 int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c);
-int v4l2_s_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c);
+int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
+                                               struct v4l2_ext_controls *c);
 
 /* Helpers for subdevices. If the associated ctrl_handler == NULL then they
    will all return -EINVAL. */
index 3b86177..5f14e88 100644 (file)
 #include <linux/videodev2.h>
 #include <linux/wait.h>
 
+/*
+ * Overview:
+ *
+ * Events are subscribed per-filehandle. An event specification consists of a
+ * type and is optionally associated with an object identified through the
+ * 'id' field. So an event is uniquely identified by the (type, id) tuple.
+ *
+ * The v4l2-fh struct has a list of subscribed events. The v4l2_subscribed_event
+ * struct is added to that list, one for every subscribed event.
+ *
+ * Each v4l2_subscribed_event struct ends with an array of v4l2_kevent structs.
+ * This array (ringbuffer, really) is used to store any events raised by the
+ * driver. The v4l2_kevent struct links into the 'available' list of the
+ * v4l2_fh struct so VIDIOC_DQEVENT will know which event to dequeue first.
+ *
+ * Finally, if the event subscription is associated with a particular object
+ * such as a V4L2 control, then that object needs to know about that as well
+ * so that an event can be raised by that object. So the 'node' field can
+ * be used to link the v4l2_subscribed_event struct into a list of that
+ * object.
+ *
+ * So to summarize:
+ *
+ * struct v4l2_fh has two lists: one of the subscribed events, and one of the
+ * pending events.
+ *
+ * struct v4l2_subscribed_event has a ringbuffer of raised (pending) events of
+ * that particular type.
+ *
+ * If struct v4l2_subscribed_event is associated with a specific object, then
+ * that object will have an internal list of struct v4l2_subscribed_event so
+ * it knows who subscribed an event to that object.
+ */
+
 struct v4l2_fh;
+struct v4l2_subscribed_event;
 struct video_device;
 
+/** struct v4l2_kevent - Internal kernel event struct.
+  * @list:     List node for the v4l2_fh->available list.
+  * @sev:      Pointer to parent v4l2_subscribed_event.
+  * @event:    The event itself.
+  */
 struct v4l2_kevent {
        struct list_head        list;
+       struct v4l2_subscribed_event *sev;
        struct v4l2_event       event;
 };
 
+/** struct v4l2_subscribed_event - Internal struct representing a subscribed event.
+  * @list:     List node for the v4l2_fh->subscribed list.
+  * @type:     Event type.
+  * @id:       Associated object ID (e.g. control ID). 0 if there isn't any.
+  * @flags:    Copy of v4l2_event_subscription->flags.
+  * @fh:       Filehandle that subscribed to this event.
+  * @node:     List node that hooks into the object's event list (if there is one).
+  * @replace:  Optional callback that can replace event 'old' with event 'new'.
+  * @merge:    Optional callback that can merge event 'old' into event 'new'.
+  * @elems:    The number of elements in the events array.
+  * @first:    The index of the events containing the oldest available event.
+  * @in_use:   The number of queued events.
+  * @events:   An array of @elems events.
+  */
 struct v4l2_subscribed_event {
        struct list_head        list;
        u32                     type;
+       u32                     id;
+       u32                     flags;
+       struct v4l2_fh          *fh;
+       struct list_head        node;
+       void                    (*replace)(struct v4l2_event *old,
+                                          const struct v4l2_event *new);
+       void                    (*merge)(const struct v4l2_event *old,
+                                        struct v4l2_event *new);
+       unsigned                elems;
+       unsigned                first;
+       unsigned                in_use;
+       struct v4l2_kevent      events[];
 };
 
-struct v4l2_events {
-       wait_queue_head_t       wait;
-       struct list_head        subscribed; /* Subscribed events */
-       struct list_head        free; /* Events ready for use */
-       struct list_head        available; /* Dequeueable event */
-       unsigned int            navailable;
-       unsigned int            nallocated; /* Number of allocated events */
-       u32                     sequence;
-};
-
-int v4l2_event_init(struct v4l2_fh *fh);
-int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n);
-void v4l2_event_free(struct v4l2_fh *fh);
 int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
                       int nonblocking);
 void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev);
+void v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev);
 int v4l2_event_pending(struct v4l2_fh *fh);
 int v4l2_event_subscribe(struct v4l2_fh *fh,
-                        struct v4l2_event_subscription *sub);
+                        struct v4l2_event_subscription *sub, unsigned elems);
 int v4l2_event_unsubscribe(struct v4l2_fh *fh,
                           struct v4l2_event_subscription *sub);
+void v4l2_event_unsubscribe_all(struct v4l2_fh *fh);
 
 #endif /* V4L2_EVENT_H */
index 0206aa5..52513c2 100644 (file)
 #include <linux/list.h>
 
 struct video_device;
-struct v4l2_events;
+struct v4l2_ctrl_handler;
 
 struct v4l2_fh {
        struct list_head        list;
        struct video_device     *vdev;
-       struct v4l2_events      *events; /* events, pending and subscribed */
+       struct v4l2_ctrl_handler *ctrl_handler;
        enum v4l2_priority      prio;
+
+       /* Events */
+       wait_queue_head_t       wait;
+       struct list_head        subscribed; /* Subscribed events */
+       struct list_head        available; /* Dequeueable event */
+       unsigned int            navailable;
+       u32                     sequence;
 };
 
 /*
@@ -44,7 +51,7 @@ struct v4l2_fh {
  * from driver's v4l2_file_operations->open() handler if the driver
  * uses v4l2_fh.
  */
-int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev);
+void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev);
 /*
  * Add the fh to the list of file handles on a video_device. The file
  * handle must be initialised first.
index 971c7fa..6114007 100644 (file)
 
 #include <linux/v4l2-mediabus.h>
 
+/* Parallel flags */
+/*
+ * Can the client run in master or in slave mode. By "Master mode" an operation
+ * mode is meant, when the client (e.g., a camera sensor) is producing
+ * horizontal and vertical synchronisation. In "Slave mode" the host is
+ * providing these signals to the slave.
+ */
+#define V4L2_MBUS_MASTER                       (1 << 0)
+#define V4L2_MBUS_SLAVE                                (1 << 1)
+/* Which signal polarities it supports */
+/* Note: in BT.656 mode HSYNC and VSYNC are unused */
+#define V4L2_MBUS_HSYNC_ACTIVE_HIGH            (1 << 2)
+#define V4L2_MBUS_HSYNC_ACTIVE_LOW             (1 << 3)
+#define V4L2_MBUS_VSYNC_ACTIVE_HIGH            (1 << 4)
+#define V4L2_MBUS_VSYNC_ACTIVE_LOW             (1 << 5)
+#define V4L2_MBUS_PCLK_SAMPLE_RISING           (1 << 6)
+#define V4L2_MBUS_PCLK_SAMPLE_FALLING          (1 << 7)
+#define V4L2_MBUS_DATA_ACTIVE_HIGH             (1 << 8)
+#define V4L2_MBUS_DATA_ACTIVE_LOW              (1 << 9)
+
+/* Serial flags */
+/* How many lanes the client can use */
+#define V4L2_MBUS_CSI2_1_LANE                  (1 << 0)
+#define V4L2_MBUS_CSI2_2_LANE                  (1 << 1)
+#define V4L2_MBUS_CSI2_3_LANE                  (1 << 2)
+#define V4L2_MBUS_CSI2_4_LANE                  (1 << 3)
+/* On which channels it can send video data */
+#define V4L2_MBUS_CSI2_CHANNEL_0               (1 << 4)
+#define V4L2_MBUS_CSI2_CHANNEL_1               (1 << 5)
+#define V4L2_MBUS_CSI2_CHANNEL_2               (1 << 6)
+#define V4L2_MBUS_CSI2_CHANNEL_3               (1 << 7)
+/* Does it support only continuous or also non-continuous clock mode */
+#define V4L2_MBUS_CSI2_CONTINUOUS_CLOCK                (1 << 8)
+#define V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK     (1 << 9)
+
+#define V4L2_MBUS_CSI2_LANES           (V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_2_LANE | \
+                                        V4L2_MBUS_CSI2_3_LANE | V4L2_MBUS_CSI2_4_LANE)
+#define V4L2_MBUS_CSI2_CHANNELS                (V4L2_MBUS_CSI2_CHANNEL_0 | V4L2_MBUS_CSI2_CHANNEL_1 | \
+                                        V4L2_MBUS_CSI2_CHANNEL_2 | V4L2_MBUS_CSI2_CHANNEL_3)
+
+/**
+ * v4l2_mbus_type - media bus type
+ * @V4L2_MBUS_PARALLEL:        parallel interface with hsync and vsync
+ * @V4L2_MBUS_BT656:   parallel interface with embedded synchronisation, can
+ *                     also be used for BT.1120
+ * @V4L2_MBUS_CSI2:    MIPI CSI-2 serial interface
+ */
+enum v4l2_mbus_type {
+       V4L2_MBUS_PARALLEL,
+       V4L2_MBUS_BT656,
+       V4L2_MBUS_CSI2,
+};
+
+/**
+ * v4l2_mbus_config - media bus configuration
+ * @type:      in: interface type
+ * @flags:     in / out: configuration flags, depending on @type
+ */
+struct v4l2_mbus_config {
+       enum v4l2_mbus_type type;
+       unsigned int flags;
+};
+
 static inline void v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt,
                                const struct v4l2_mbus_framefmt *mbus_fmt)
 {
index 2884e3e..257da1a 100644 (file)
@@ -229,6 +229,12 @@ struct v4l2_subdev_audio_ops {
    s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by
        video input devices.
 
+   g_std_output: get current standard for video OUTPUT devices. This is ignored
+       by video input devices.
+
+   g_tvnorms_output: get v4l2_std_id with all standards supported by video
+       OUTPUT device. This is ignored by video input devices.
+
    s_crystal_freq: sets the frequency of the crystal used to generate the
        clocks in Hz. An extra flags field allows device specific configuration
        regarding clock frequency dividers, etc. If not used, then set flags
@@ -243,6 +249,8 @@ struct v4l2_subdev_audio_ops {
    s_dv_preset: set dv (Digital Video) preset in the sub device. Similar to
        s_std()
 
+   g_dv_preset: get current dv (Digital Video) preset in the sub device.
+
    query_dv_preset: query dv preset in the sub device. This is similar to
        querystd()
 
@@ -259,12 +267,20 @@ struct v4l2_subdev_audio_ops {
    try_mbus_fmt: try to set a pixel format on a video data source
 
    s_mbus_fmt: set a pixel format on a video data source
+
+   g_mbus_config: get supported mediabus configurations
+
+   s_mbus_config: set a certain mediabus configuration. This operation is added
+       for compatibility with soc-camera drivers and should not be used by new
+       software.
  */
 struct v4l2_subdev_video_ops {
        int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
        int (*s_crystal_freq)(struct v4l2_subdev *sd, u32 freq, u32 flags);
        int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std);
+       int (*g_std_output)(struct v4l2_subdev *sd, v4l2_std_id *std);
        int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std);
+       int (*g_tvnorms_output)(struct v4l2_subdev *sd, v4l2_std_id *std);
        int (*g_input_status)(struct v4l2_subdev *sd, u32 *status);
        int (*s_stream)(struct v4l2_subdev *sd, int enable);
        int (*cropcap)(struct v4l2_subdev *sd, struct v4l2_cropcap *cc);
@@ -282,6 +298,8 @@ struct v4l2_subdev_video_ops {
                        struct v4l2_dv_enum_preset *preset);
        int (*s_dv_preset)(struct v4l2_subdev *sd,
                        struct v4l2_dv_preset *preset);
+       int (*g_dv_preset)(struct v4l2_subdev *sd,
+                       struct v4l2_dv_preset *preset);
        int (*query_dv_preset)(struct v4l2_subdev *sd,
                        struct v4l2_dv_preset *preset);
        int (*s_dv_timings)(struct v4l2_subdev *sd,
@@ -298,6 +316,10 @@ struct v4l2_subdev_video_ops {
                            struct v4l2_mbus_framefmt *fmt);
        int (*s_mbus_fmt)(struct v4l2_subdev *sd,
                          struct v4l2_mbus_framefmt *fmt);
+       int (*g_mbus_config)(struct v4l2_subdev *sd,
+                            struct v4l2_mbus_config *cfg);
+       int (*s_mbus_config)(struct v4l2_subdev *sd,
+                            const struct v4l2_mbus_config *cfg);
 };
 
 /*
@@ -513,8 +535,6 @@ struct v4l2_subdev {
        void *host_priv;
        /* subdev device node */
        struct video_device devnode;
-       /* number of events to be allocated on open */
-       unsigned int nevents;
 };
 
 #define media_entity_to_v4l2_subdev(ent) \
index 582e4ae..cbc6bb0 100644 (file)
@@ -8,7 +8,7 @@
 
 #define TEMP_VALID_LIFETIME            (7*86400)
 #define TEMP_PREFERRED_LIFETIME                (86400)
-#define REGEN_MAX_RETRY                        (5)
+#define REGEN_MAX_RETRY                        (3)
 #define MAX_DESYNC_FACTOR              (600)
 
 #define ADDR_CHECK_FREQUENCY           (120*HZ)
index 3b93874..9808877 100644 (file)
@@ -8,7 +8,7 @@
  * have chosen to adopt the protocol and over the years it has become a
  * de-facto standard for labeled networking.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index 29e2557..4fb6c43 100644 (file)
@@ -37,7 +37,7 @@ struct dst_entry {
        unsigned long           _metrics;
        unsigned long           expires;
        struct dst_entry        *path;
-       struct neighbour        *_neighbour;
+       struct neighbour __rcu  *_neighbour;
 #ifdef CONFIG_XFRM
        struct xfrm_state       *xfrm;
 #else
@@ -88,12 +88,17 @@ struct dst_entry {
 
 static inline struct neighbour *dst_get_neighbour(struct dst_entry *dst)
 {
-       return dst->_neighbour;
+       return rcu_dereference(dst->_neighbour);
+}
+
+static inline struct neighbour *dst_get_neighbour_raw(struct dst_entry *dst)
+{
+       return rcu_dereference_raw(dst->_neighbour);
 }
 
 static inline void dst_set_neighbour(struct dst_entry *dst, struct neighbour *neigh)
 {
-       dst->_neighbour = neigh;
+       rcu_assign_pointer(dst->_neighbour, neigh);
 }
 
 extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
@@ -320,7 +325,14 @@ static inline void skb_dst_force(struct sk_buff *skb)
 static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
 {
        skb->dev = dev;
-       skb->rxhash = 0;
+
+       /*
+        * Clear rxhash so that we can recalulate the hash for the
+        * encapsulated packet, unless we have already determine the hash
+        * over the L4 4-tuple.
+        */
+       if (!skb->l4_rxhash)
+               skb->rxhash = 0;
        skb_set_queue_mapping(skb, 0);
        skb_dst_drop(skb);
        nf_reset(skb);
@@ -382,8 +394,12 @@ static inline void dst_rcu_free(struct rcu_head *head)
 static inline void dst_confirm(struct dst_entry *dst)
 {
        if (dst) {
-               struct neighbour *n = dst_get_neighbour(dst);
+               struct neighbour *n;
+
+               rcu_read_lock();
+               n = dst_get_neighbour(dst);
                neigh_confirm(n);
+               rcu_read_unlock();
        }
 }
 
index 11cf373..51a7031 100644 (file)
@@ -41,6 +41,7 @@ struct inet6_ifaddr {
        struct in6_addr         addr;
        __u32                   prefix_len;
        
+       /* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
        __u32                   valid_lft;
        __u32                   prefered_lft;
        atomic_t                refcnt;
index caaff5f..b897d6e 100644 (file)
@@ -238,7 +238,7 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
 {
        __u8 flags = 0;
 
-       if (inet_sk(sk)->transparent)
+       if (inet_sk(sk)->transparent || inet_sk(sk)->hdrincl)
                flags |= FLOWI_FLAG_ANYSRC;
        if (sk->sk_protocol == IPPROTO_TCP)
                flags |= FLOWI_FLAG_PRECOW_METRICS;
index f82a1e8..f2419cf 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/list.h>
 #include <linux/poll.h>
 #include <linux/socket.h>
+#include <net/iucv/iucv.h>
 
 #ifndef AF_IUCV
 #define AF_IUCV                32
@@ -33,6 +34,7 @@ enum {
 };
 
 #define IUCV_QUEUELEN_DEFAULT  65535
+#define IUCV_HIPER_MSGLIM_DEFAULT      128
 #define IUCV_CONN_TIMEOUT      (HZ * 40)
 #define IUCV_DISCONN_TIMEOUT   (HZ * 2)
 #define IUCV_CONN_IDLE_TIMEOUT (HZ * 60)
@@ -57,8 +59,51 @@ struct sock_msg_q {
        spinlock_t              lock;
 };
 
+#define AF_IUCV_FLAG_ACK 0x1
+#define AF_IUCV_FLAG_SYN 0x2
+#define AF_IUCV_FLAG_FIN 0x4
+#define AF_IUCV_FLAG_WIN 0x8
+
+struct af_iucv_trans_hdr {
+       u16 magic;
+       u8 version;
+       u8 flags;
+       u16 window;
+       char destNodeID[8];
+       char destUserID[8];
+       char destAppName[16];
+       char srcNodeID[8];
+       char srcUserID[8];
+       char srcAppName[16];             /* => 70 bytes */
+       struct iucv_message iucv_hdr;    /* => 33 bytes */
+       u8 pad;                          /* total 104 bytes */
+} __packed;
+
+enum iucv_tx_notify {
+       /* transmission of skb is completed and was successful */
+       TX_NOTIFY_OK = 0,
+       /* target is unreachable */
+       TX_NOTIFY_UNREACHABLE = 1,
+       /* transfer pending queue full */
+       TX_NOTIFY_TPQFULL = 2,
+       /* general error */
+       TX_NOTIFY_GENERALERROR = 3,
+       /* transmission of skb is pending - may interleave
+        * with TX_NOTIFY_DELAYED_* */
+       TX_NOTIFY_PENDING = 4,
+       /* transmission of skb was done successfully (delayed) */
+       TX_NOTIFY_DELAYED_OK = 5,
+       /* target unreachable (detected delayed) */
+       TX_NOTIFY_DELAYED_UNREACHABLE = 6,
+       /* general error (detected delayed) */
+       TX_NOTIFY_DELAYED_GENERALERROR = 7,
+};
+
 #define iucv_sk(__sk) ((struct iucv_sock *) __sk)
 
+#define AF_IUCV_TRANS_IUCV 0
+#define AF_IUCV_TRANS_HIPER 1
+
 struct iucv_sock {
        struct sock             sk;
        char                    src_user_id[8];
@@ -75,6 +120,13 @@ struct iucv_sock {
        unsigned int            send_tag;
        u8                      flags;
        u16                     msglimit;
+       u16                     msglimit_peer;
+       atomic_t                msg_sent;
+       atomic_t                msg_recv;
+       atomic_t                pendings;
+       int                     transport;
+       void                    (*sk_txnotify)(struct sk_buff *skb,
+                                              enum iucv_tx_notify n);
 };
 
 /* iucv socket options (SOL_IUCV) */
index 1121baa..0894ced 100644 (file)
@@ -120,7 +120,7 @@ struct iucv_message {
        u32 reply_size;
        u8  rmmsg[8];
        u8  flags;
-};
+} __packed;
 
 /*
  * struct iucv_handler
@@ -459,3 +459,37 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
 int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
                          u8 flags, u32 srccls, void *buffer, size_t size,
                          void *answer, size_t asize, size_t *residual);
+
+struct iucv_interface {
+       int (*message_receive)(struct iucv_path *path, struct iucv_message *msg,
+               u8 flags, void *buffer, size_t size, size_t *residual);
+       int (*__message_receive)(struct iucv_path *path,
+               struct iucv_message *msg, u8 flags, void *buffer, size_t size,
+               size_t *residual);
+       int (*message_reply)(struct iucv_path *path, struct iucv_message *msg,
+               u8 flags, void *reply, size_t size);
+       int (*message_reject)(struct iucv_path *path, struct iucv_message *msg);
+       int (*message_send)(struct iucv_path *path, struct iucv_message *msg,
+               u8 flags, u32 srccls, void *buffer, size_t size);
+       int (*__message_send)(struct iucv_path *path, struct iucv_message *msg,
+               u8 flags, u32 srccls, void *buffer, size_t size);
+       int (*message_send2way)(struct iucv_path *path,
+               struct iucv_message *msg, u8 flags, u32 srccls, void *buffer,
+               size_t size, void *answer, size_t asize, size_t *residual);
+       int (*message_purge)(struct iucv_path *path, struct iucv_message *msg,
+               u32 srccls);
+       int (*path_accept)(struct iucv_path *path, struct iucv_handler *handler,
+               u8 userdata[16], void *private);
+       int (*path_connect)(struct iucv_path *path,
+               struct iucv_handler *handler,
+               u8 userid[8], u8 system[8], u8 userdata[16], void *private);
+       int (*path_quiesce)(struct iucv_path *path, u8 userdata[16]);
+       int (*path_resume)(struct iucv_path *path, u8 userdata[16]);
+       int (*path_sever)(struct iucv_path *path, u8 userdata[16]);
+       int (*iucv_register)(struct iucv_handler *handler, int smp);
+       void (*iucv_unregister)(struct iucv_handler *handler, int smp);
+       struct bus_type *bus;
+       struct device *root;
+};
+
+extern struct iucv_interface iucv_if;
index f21a16e..f674409 100644 (file)
@@ -4,7 +4,7 @@
  * The NetLabel system manages static and dynamic label mappings for network
  * protocols such as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index 745460f..68e1e48 100644 (file)
@@ -53,6 +53,14 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm,
        cred_to_ucred(pid, cred, &scm->creds);
 }
 
+static __inline__ void scm_set_cred_noref(struct scm_cookie *scm,
+                                   struct pid *pid, const struct cred *cred)
+{
+       scm->pid  = pid;
+       scm->cred = cred;
+       cred_to_ucred(pid, cred, &scm->creds);
+}
+
 static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
 {
        put_pid(scm->pid);
@@ -70,6 +78,15 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
                __scm_destroy(scm);
 }
 
+static __inline__ void scm_release(struct scm_cookie *scm)
+{
+       /* keep ref on pid and cred */
+       scm->pid = NULL;
+       scm->cred = NULL;
+       if (scm->fp)
+               __scm_destroy(scm);
+}
+
 static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
                               struct scm_cookie *scm)
 {
@@ -108,15 +125,14 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
        if (!msg->msg_control) {
                if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
                        msg->msg_flags |= MSG_CTRUNC;
-               scm_destroy(scm);
+               if (scm && scm->fp)
+                       __scm_destroy(scm);
                return;
        }
 
        if (test_bit(SOCK_PASSCRED, &sock->flags))
                put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
 
-       scm_destroy_cred(scm);
-
        scm_passec(sock, msg, scm);
 
        if (!scm->fp)
index f7d9c3f..e90e7a9 100644 (file)
@@ -1915,6 +1915,7 @@ struct sctp_association {
        __u32 addip_serial;
        union sctp_addr *asconf_addr_del_pending;
        int src_out_of_asoc_ok;
+       struct sctp_transport *new_transport;
 
        /* SCTP AUTH: list of the endpoint shared keys.  These
         * keys are provided out of band by the user applicaton
diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h
new file mode 100644 (file)
index 0000000..d97f689
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _NET_SECURE_SEQ
+#define _NET_SECURE_SEQ
+
+#include <linux/types.h>
+
+extern __u32 secure_ip_id(__be32 daddr);
+extern __u32 secure_ipv6_id(const __be32 daddr[4]);
+extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
+extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+                                     __be16 dport);
+extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+                                       __be16 sport, __be16 dport);
+extern __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+                                         __be16 sport, __be16 dport);
+extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
+                                      __be16 sport, __be16 dport);
+extern u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+                                        __be16 sport, __be16 dport);
+
+#endif /* _NET_SECURE_SEQ */
index 8e4062f..5ac682f 100644 (file)
@@ -686,16 +686,25 @@ static inline void sock_rps_reset_flow(const struct sock *sk)
 #endif
 }
 
-static inline void sock_rps_save_rxhash(struct sock *sk, u32 rxhash)
+static inline void sock_rps_save_rxhash(struct sock *sk,
+                                       const struct sk_buff *skb)
 {
 #ifdef CONFIG_RPS
-       if (unlikely(sk->sk_rxhash != rxhash)) {
+       if (unlikely(sk->sk_rxhash != skb->rxhash)) {
                sock_rps_reset_flow(sk);
-               sk->sk_rxhash = rxhash;
+               sk->sk_rxhash = skb->rxhash;
        }
 #endif
 }
 
+static inline void sock_rps_reset_rxhash(struct sock *sk)
+{
+#ifdef CONFIG_RPS
+       sock_rps_reset_flow(sk);
+       sk->sk_rxhash = 0;
+#endif
+}
+
 #define sk_wait_event(__sk, __timeo, __condition)                      \
        ({      int __rc;                                               \
                release_sock(__sk);                                     \
index 4ad0204..8225d80 100644 (file)
@@ -78,7 +78,6 @@ struct fc_frame {
 };
 
 struct fcoe_rcv_info {
-       struct packet_type  *ptype;
        struct fc_lport *fr_dev;        /* transport layer private pointer */
        struct fc_seq   *fr_seq;        /* for use with exchange manager */
        struct fc_fcp_pkt *fr_fsp;      /* for the corresponding fcp I/O */
diff --git a/include/scsi/osd_ore.h b/include/scsi/osd_ore.h
new file mode 100644 (file)
index 0000000..c5c5e00
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2011
+ * Boaz Harrosh <bharrosh@panasas.com>
+ *
+ * Public Declarations of the ORE API
+ *
+ * This file is part of the ORE (Object Raid Engine) library.
+ *
+ * ORE 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. (GPL v2)
+ *
+ * ORE 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 the ORE; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef __ORE_H__
+#define __ORE_H__
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_attributes.h>
+#include <scsi/osd_sec.h>
+#include <linux/pnfs_osd_xdr.h>
+
+struct ore_comp {
+       struct osd_obj_id       obj;
+       u8                      cred[OSD_CAP_LEN];
+};
+
+struct ore_layout {
+       /* Our way of looking at the data_map */
+       unsigned stripe_unit;
+       unsigned mirrors_p1;
+
+       unsigned group_width;
+       u64      group_depth;
+       unsigned group_count;
+};
+
+struct ore_components {
+       unsigned        numdevs;                /* Num of devices in array    */
+       /* If @single_comp == EC_SINGLE_COMP, @comps points to a single
+        * component. else there are @numdevs components
+        */
+       enum EC_COMP_USAGE {
+               EC_SINGLE_COMP = 0, EC_MULTPLE_COMPS = 0xffffffff
+       }               single_comp;
+       struct ore_comp *comps;
+       struct osd_dev  **ods;                  /* osd_dev array              */
+};
+
+struct ore_io_state;
+typedef void (*ore_io_done_fn)(struct ore_io_state *ios, void *private);
+
+struct ore_io_state {
+       struct kref             kref;
+
+       void                    *private;
+       ore_io_done_fn  done;
+
+       struct ore_layout       *layout;
+       struct ore_components   *comps;
+
+       /* Global read/write IO*/
+       loff_t                  offset;
+       unsigned long           length;
+       void                    *kern_buff;
+
+       struct page             **pages;
+       unsigned                nr_pages;
+       unsigned                pgbase;
+       unsigned                pages_consumed;
+
+       /* Attributes */
+       unsigned                in_attr_len;
+       struct osd_attr         *in_attr;
+       unsigned                out_attr_len;
+       struct osd_attr         *out_attr;
+
+       bool                    reading;
+
+       /* Variable array of size numdevs */
+       unsigned numdevs;
+       struct ore_per_dev_state {
+               struct osd_request *or;
+               struct bio *bio;
+               loff_t offset;
+               unsigned length;
+               unsigned dev;
+       } per_dev[];
+};
+
+static inline unsigned ore_io_state_size(unsigned numdevs)
+{
+       return sizeof(struct ore_io_state) +
+               sizeof(struct ore_per_dev_state) * numdevs;
+}
+
+/* ore.c */
+int ore_get_rw_state(struct ore_layout *layout, struct ore_components *comps,
+                    bool is_reading, u64 offset, u64 length,
+                    struct ore_io_state **ios);
+int ore_get_io_state(struct ore_layout *layout, struct ore_components *comps,
+                    struct ore_io_state **ios);
+void ore_put_io_state(struct ore_io_state *ios);
+
+int ore_check_io(struct ore_io_state *ios, u64 *resid);
+
+int ore_create(struct ore_io_state *ios);
+int ore_remove(struct ore_io_state *ios);
+int ore_write(struct ore_io_state *ios);
+int ore_read(struct ore_io_state *ios);
+int ore_truncate(struct ore_layout *layout, struct ore_components *comps,
+                u64 size);
+
+int extract_attr_from_ios(struct ore_io_state *ios, struct osd_attr *attr);
+
+extern const struct osd_attr g_attr_logical_length;
+
+#endif
index d2ea112..726e947 100644 (file)
@@ -23,8 +23,8 @@
  */
 
 #include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-dev.h>
-#include <media/v4l2-ioctl.h>
 
 #define TEA575X_FMIF   10700
 
@@ -42,18 +42,20 @@ struct snd_tea575x_ops {
 };
 
 struct snd_tea575x {
-       struct video_device *vd;        /* video device */
+       struct video_device vd;         /* video device */
        bool tea5759;                   /* 5759 chip is present */
        bool mute;                      /* Device is muted? */
        bool stereo;                    /* receiving stereo */
        bool tuned;                     /* tuned to a station */
        unsigned int val;               /* hw value */
        unsigned long freq;             /* frequency */
-       unsigned long in_use;           /* set if the device is in use */
+       struct mutex mutex;
        struct snd_tea575x_ops *ops;
        void *private_data;
        u8 card[32];
        u8 bus_info[32];
+       struct v4l2_ctrl_handler ctrl_handler;
+       int (*ext_init)(struct snd_tea575x *tea);
 };
 
 int snd_tea575x_init(struct snd_tea575x *tea);
similarity index 63%
rename from include/sound/wm8915.h
rename to include/sound/wm8996.h
index 5817d76..ea4d88f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/sound/wm8915.h -- Platform data for WM8915
+ * linux/sound/wm8996.h -- Platform data for WM8996
  *
  * Copyright 2011 Wolfson Microelectronics. PLC.
  *
@@ -8,14 +8,14 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef __LINUX_SND_WM8903_H
-#define __LINUX_SND_WM8903_H
+#ifndef __LINUX_SND_WM8996_H
+#define __LINUX_SND_WM8996_H
 
-enum wm8915_inmode {
-       WM8915_DIFFERRENTIAL_1 = 0,   /* IN1xP - IN1xN */
-       WM8915_INVERTING = 1,         /* IN1xN */
-       WM8915_NON_INVERTING = 2,     /* IN1xP */
-       WM8915_DIFFERENTIAL_2 = 3,    /* IN2xP - IN2xP */
+enum wm8996_inmode {
+       WM8996_DIFFERRENTIAL_1 = 0,   /* IN1xP - IN1xN */
+       WM8996_INVERTING = 1,         /* IN1xN */
+       WM8996_NON_INVERTING = 2,     /* IN1xP */
+       WM8996_DIFFERENTIAL_2 = 3,    /* IN2xP - IN2xP */
 };
 
 /**
@@ -25,23 +25,23 @@ enum wm8915_inmode {
  * Configurations are expected to be generated using the ReTune Mobile
  * control panel in WISCE - see http://www.wolfsonmicro.com/wisce/
  */
-struct wm8915_retune_mobile_config {
+struct wm8996_retune_mobile_config {
        const char *name;
        int rate;
        u16 regs[20];
 };
 
-#define WM8915_SET_DEFAULT 0x10000
+#define WM8996_SET_DEFAULT 0x10000
 
-struct wm8915_pdata {
+struct wm8996_pdata {
        int irq_flags;  /** Set IRQ trigger flags; default active low */
 
        int ldo_ena;  /** GPIO for LDO1; -1 for none */
 
        int micdet_def;  /** Default MICDET_SRC/HP1FB_SRC/MICD_BIAS */
 
-       enum wm8915_inmode inl_mode;
-       enum wm8915_inmode inr_mode;
+       enum wm8996_inmode inl_mode;
+       enum wm8996_inmode inr_mode;
 
        u32 spkmute_seq;  /** Value for register 0x802 */
 
@@ -49,7 +49,7 @@ struct wm8915_pdata {
        u32 gpio_default[5];
 
        int num_retune_mobile_cfgs;
-       struct wm8915_retune_mobile_config *retune_mobile_cfgs;
+       struct wm8996_retune_mobile_config *retune_mobile_cfgs;
 };
 
 #endif
index 6363193..b50a547 100644 (file)
@@ -23,7 +23,7 @@ TRACE_EVENT(ext4_free_inode,
        TP_STRUCT__entry(
                __field(        dev_t,  dev                     )
                __field(        ino_t,  ino                     )
-               __field(        umode_t, mode                   )
+               __field(        __u16, mode                     )
                __field(        uid_t,  uid                     )
                __field(        gid_t,  gid                     )
                __field(        __u64, blocks                   )
@@ -52,7 +52,7 @@ TRACE_EVENT(ext4_request_inode,
        TP_STRUCT__entry(
                __field(        dev_t,  dev                     )
                __field(        ino_t,  dir                     )
-               __field(        umode_t, mode                   )
+               __field(        __u16, mode                     )
        ),
 
        TP_fast_assign(
@@ -75,7 +75,7 @@ TRACE_EVENT(ext4_allocate_inode,
                __field(        dev_t,  dev                     )
                __field(        ino_t,  ino                     )
                __field(        ino_t,  dir                     )
-               __field(        umode_t, mode                   )
+               __field(        __u16,  mode                    )
        ),
 
        TP_fast_assign(
@@ -725,7 +725,7 @@ TRACE_EVENT(ext4_free_blocks,
        TP_STRUCT__entry(
                __field(        dev_t,  dev                     )
                __field(        ino_t,  ino                     )
-               __field(        umode_t, mode                   )
+               __field(        __u16,  mode                    )
                __field(        __u64,  block                   )
                __field(        unsigned long,  count           )
                __field(        int,    flags                   )
@@ -1012,7 +1012,7 @@ TRACE_EVENT(ext4_forget,
        TP_STRUCT__entry(
                __field(        dev_t,  dev                     )
                __field(        ino_t,  ino                     )
-               __field(        umode_t, mode                   )
+               __field(        __u16,  mode                    )
                __field(        int,    is_metadata             )
                __field(        __u64,  block                   )
        ),
@@ -1039,7 +1039,7 @@ TRACE_EVENT(ext4_da_update_reserve_space,
        TP_STRUCT__entry(
                __field(        dev_t,  dev                     )
                __field(        ino_t,  ino                     )
-               __field(        umode_t, mode                   )
+               __field(        __u16,  mode                    )
                __field(        __u64,  i_blocks                )
                __field(        int,    used_blocks             )
                __field(        int,    reserved_data_blocks    )
@@ -1076,7 +1076,7 @@ TRACE_EVENT(ext4_da_reserve_space,
        TP_STRUCT__entry(
                __field(        dev_t,  dev                     )
                __field(        ino_t,  ino                     )
-               __field(        umode_t, mode                   )
+               __field(        __u16,  mode                    )
                __field(        __u64,  i_blocks                )
                __field(        int,    md_needed               )
                __field(        int,    reserved_data_blocks    )
@@ -1110,7 +1110,7 @@ TRACE_EVENT(ext4_da_release_space,
        TP_STRUCT__entry(
                __field(        dev_t,  dev                     )
                __field(        ino_t,  ino                     )
-               __field(        umode_t, mode                   )
+               __field(        __u16,  mode                    )
                __field(        __u64,  i_blocks                )
                __field(        int,    freed_blocks            )
                __field(        int,    reserved_data_blocks    )
@@ -1518,6 +1518,77 @@ TRACE_EVENT(ext4_load_inode,
                  (unsigned long) __entry->ino)
 );
 
+TRACE_EVENT(ext4_journal_start,
+       TP_PROTO(struct super_block *sb, int nblocks, unsigned long IP),
+
+       TP_ARGS(sb, nblocks, IP),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(          int,  nblocks                 )
+               __field(unsigned long,  ip                      )
+       ),
+
+       TP_fast_assign(
+               __entry->dev     = sb->s_dev;
+               __entry->nblocks = nblocks;
+               __entry->ip      = IP;
+       ),
+
+       TP_printk("dev %d,%d nblocks %d caller %pF",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->nblocks, (void *)__entry->ip)
+);
+
+DECLARE_EVENT_CLASS(ext4__trim,
+       TP_PROTO(struct super_block *sb,
+                ext4_group_t group,
+                ext4_grpblk_t start,
+                ext4_grpblk_t len),
+
+       TP_ARGS(sb, group, start, len),
+
+       TP_STRUCT__entry(
+               __field(        int,    dev_major               )
+               __field(        int,    dev_minor               )
+               __field(        __u32,  group                   )
+               __field(        int,    start                   )
+               __field(        int,    len                     )
+       ),
+
+       TP_fast_assign(
+               __entry->dev_major      = MAJOR(sb->s_dev);
+               __entry->dev_minor      = MINOR(sb->s_dev);
+               __entry->group          = group;
+               __entry->start          = start;
+               __entry->len            = len;
+       ),
+
+       TP_printk("dev %d,%d group %u, start %d, len %d",
+                 __entry->dev_major, __entry->dev_minor,
+                 __entry->group, __entry->start, __entry->len)
+);
+
+DEFINE_EVENT(ext4__trim, ext4_trim_extent,
+
+       TP_PROTO(struct super_block *sb,
+                ext4_group_t group,
+                ext4_grpblk_t start,
+                ext4_grpblk_t len),
+
+       TP_ARGS(sb, group, start, len)
+);
+
+DEFINE_EVENT(ext4__trim, ext4_trim_all_free,
+
+       TP_PROTO(struct super_block *sb,
+                ext4_group_t group,
+                ext4_grpblk_t start,
+                ext4_grpblk_t len),
+
+       TP_ARGS(sb, group, start, len)
+);
+
 #endif /* _TRACE_EXT4_H */
 
 /* This part must be outside protection */
index bf16545..7596441 100644 (file)
@@ -26,8 +26,8 @@ TRACE_EVENT(jbd2_checkpoint,
                __entry->result         = result;
        ),
 
-       TP_printk("dev %s result %d",
-                 jbd2_dev_to_name(__entry->dev), __entry->result)
+       TP_printk("dev %d,%d result %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev), __entry->result)
 );
 
 DECLARE_EVENT_CLASS(jbd2_commit,
@@ -48,9 +48,9 @@ DECLARE_EVENT_CLASS(jbd2_commit,
                __entry->transaction    = commit_transaction->t_tid;
        ),
 
-       TP_printk("dev %s transaction %d sync %d",
-                 jbd2_dev_to_name(__entry->dev), __entry->transaction,
-                 __entry->sync_commit)
+       TP_printk("dev %d,%d transaction %d sync %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->transaction, __entry->sync_commit)
 );
 
 DEFINE_EVENT(jbd2_commit, jbd2_start_commit,
@@ -100,9 +100,9 @@ TRACE_EVENT(jbd2_end_commit,
                __entry->head           = journal->j_tail_sequence;
        ),
 
-       TP_printk("dev %s transaction %d sync %d head %d",
-                 jbd2_dev_to_name(__entry->dev), __entry->transaction,
-                 __entry->sync_commit, __entry->head)
+       TP_printk("dev %d,%d transaction %d sync %d head %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->transaction, __entry->sync_commit, __entry->head)
 );
 
 TRACE_EVENT(jbd2_submit_inode_data,
@@ -120,8 +120,9 @@ TRACE_EVENT(jbd2_submit_inode_data,
                __entry->ino    = inode->i_ino;
        ),
 
-       TP_printk("dev %s ino %lu",
-                 jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino)
+       TP_printk("dev %d,%d ino %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino)
 );
 
 TRACE_EVENT(jbd2_run_stats,
@@ -156,9 +157,9 @@ TRACE_EVENT(jbd2_run_stats,
                __entry->blocks_logged  = stats->rs_blocks_logged;
        ),
 
-       TP_printk("dev %s tid %lu wait %u running %u locked %u flushing %u "
+       TP_printk("dev %d,%d tid %lu wait %u running %u locked %u flushing %u "
                  "logging %u handle_count %u blocks %u blocks_logged %u",
-                 jbd2_dev_to_name(__entry->dev), __entry->tid,
+                 MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid,
                  jiffies_to_msecs(__entry->wait),
                  jiffies_to_msecs(__entry->running),
                  jiffies_to_msecs(__entry->locked),
@@ -192,9 +193,9 @@ TRACE_EVENT(jbd2_checkpoint_stats,
                __entry->dropped        = stats->cs_dropped;
        ),
 
-       TP_printk("dev %s tid %lu chp_time %u forced_to_close %u "
+       TP_printk("dev %d,%d tid %lu chp_time %u forced_to_close %u "
                  "written %u dropped %u",
-                 jbd2_dev_to_name(__entry->dev), __entry->tid,
+                 MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid,
                  jiffies_to_msecs(__entry->chp_time),
                  __entry->forced_to_close, __entry->written, __entry->dropped)
 );
@@ -222,9 +223,10 @@ TRACE_EVENT(jbd2_cleanup_journal_tail,
                __entry->freed          = freed;
        ),
 
-       TP_printk("dev %s from %u to %u offset %lu freed %lu",
-                 jbd2_dev_to_name(__entry->dev), __entry->tail_sequence,
-                 __entry->first_tid, __entry->block_nr, __entry->freed)
+       TP_printk("dev %d,%d from %u to %u offset %lu freed %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->tail_sequence, __entry->first_tid,
+                 __entry->block_nr, __entry->freed)
 );
 
 #endif /* _TRACE_JBD2_H */
index 44d8dec..92f1a79 100644 (file)
@@ -8,6 +8,8 @@
 #include <asm/paravirt_types.h>
 #include <asm/xen/trace_types.h>
 
+struct multicall_entry;
+
 /* Multicalls */
 DECLARE_EVENT_CLASS(xen_mc__batch,
            TP_PROTO(enum paravirt_lazy_mode mode),
index 892b97f..3b55ef2 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/list.h>
 #include <linux/kobject.h>
 #include <linux/device.h>
-#include <linux/platform_device.h>
-#include <asm/atomic.h>
 
 #define DISPC_IRQ_FRAMEDONE            (1 << 0)
 #define DISPC_IRQ_VSYNC                        (1 << 1)
@@ -136,12 +134,6 @@ enum omap_display_caps {
        OMAP_DSS_DISPLAY_CAP_TEAR_ELIM          = 1 << 1,
 };
 
-enum omap_dss_update_mode {
-       OMAP_DSS_UPDATE_DISABLED = 0,
-       OMAP_DSS_UPDATE_AUTO,
-       OMAP_DSS_UPDATE_MANUAL,
-};
-
 enum omap_dss_display_state {
        OMAP_DSS_DISPLAY_DISABLED = 0,
        OMAP_DSS_DISPLAY_ACTIVE,
@@ -246,7 +238,7 @@ int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
 
 /* Board specific data */
 struct omap_dss_board_info {
-       int (*get_last_off_on_transaction_id)(struct device *dev);
+       int (*get_context_loss_count)(struct device *dev);
        int num_devices;
        struct omap_dss_device **devices;
        struct omap_dss_device *default_device;
@@ -266,8 +258,6 @@ static inline int omap_display_init(struct omap_dss_board_info *board_data)
 struct omap_display_platform_data {
        struct omap_dss_board_info *board_data;
        /* TODO: Additional members to be added when PM is considered */
-
-       bool (*opt_clock_available)(const char *clk_role);
 };
 
 struct omap_video_timings {
@@ -300,6 +290,12 @@ extern const struct omap_video_timings omap_dss_pal_timings;
 extern const struct omap_video_timings omap_dss_ntsc_timings;
 #endif
 
+struct omap_dss_cpr_coefs {
+       s16 rr, rg, rb;
+       s16 gr, gg, gb;
+       s16 br, bg, bb;
+};
+
 struct omap_overlay_info {
        bool enabled;
 
@@ -359,6 +355,9 @@ struct omap_overlay_manager_info {
        bool trans_enabled;
 
        bool alpha_enabled;
+
+       bool cpr_enable;
+       struct omap_dss_cpr_coefs cpr_coefs;
 };
 
 struct omap_overlay_manager {
@@ -526,11 +525,6 @@ struct omap_dss_driver {
        int (*resume)(struct omap_dss_device *display);
        int (*run_test)(struct omap_dss_device *display, int test);
 
-       int (*set_update_mode)(struct omap_dss_device *dssdev,
-                       enum omap_dss_update_mode);
-       enum omap_dss_update_mode (*get_update_mode)(
-                       struct omap_dss_device *dssdev);
-
        int (*update)(struct omap_dss_device *dssdev,
                               u16 x, u16 y, u16 w, u16 h);
        int (*sync)(struct omap_dss_device *dssdev);
index d7211fa..9c51ee7 100644 (file)
@@ -369,9 +369,12 @@ static noinline void __init_refok rest_init(void)
        init_idle_bootup_task(current);
        preempt_enable_no_resched();
        schedule();
-       preempt_disable();
+
+       /* At this point, we can enable user mode helper functionality */
+       usermodehelper_enable();
 
        /* Call into cpu_idle with preempt disabled */
+       preempt_disable();
        cpu_idle();
 }
 
@@ -715,7 +718,7 @@ static void __init do_basic_setup(void)
 {
        cpuset_init_smp();
        usermodehelper_init();
-       init_tmpfs();
+       shmem_init();
        driver_init();
        init_irq_proc();
        do_ctors();
index 3f5b143..02ecf2c 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -105,9 +105,16 @@ void shm_exit_ns(struct ipc_namespace *ns)
 }
 #endif
 
-void __init shm_init (void)
+static int __init ipc_ns_init(void)
 {
        shm_init_ns(&init_ipc_ns);
+       return 0;
+}
+
+pure_initcall(ipc_ns_init);
+
+void __init shm_init (void)
+{
        ipc_init_proc_interface("sysvipc/shm",
 #if BITS_PER_LONG <= 32
                                "       key      shmid perms       size  cpid  lpid nattch   uid   gid  cuid  cgid      atime      dtime      ctime        rss       swap\n",
@@ -131,6 +138,12 @@ static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id)
        return container_of(ipcp, struct shmid_kernel, shm_perm);
 }
 
+static inline void shm_lock_by_ptr(struct shmid_kernel *ipcp)
+{
+       rcu_read_lock();
+       spin_lock(&ipcp->shm_perm.lock);
+}
+
 static inline struct shmid_kernel *shm_lock_check(struct ipc_namespace *ns,
                                                int id)
 {
@@ -231,76 +244,80 @@ static void shm_close(struct vm_area_struct *vma)
        up_write(&shm_ids(ns).rw_mutex);
 }
 
+/* Called with ns->shm_ids(ns).rw_mutex locked */
 static int shm_try_destroy_current(int id, void *p, void *data)
 {
        struct ipc_namespace *ns = data;
-       struct shmid_kernel *shp = shm_lock(ns, id);
+       struct kern_ipc_perm *ipcp = p;
+       struct shmid_kernel *shp = container_of(ipcp, struct shmid_kernel, shm_perm);
 
-       if (IS_ERR(shp))
+       if (shp->shm_creator != current)
                return 0;
 
-       if (shp->shm_cprid != task_tgid_vnr(current)) {
-               shm_unlock(shp);
+       /*
+        * Mark it as orphaned to destroy the segment when
+        * kernel.shm_rmid_forced is changed.
+        * It is noop if the following shm_may_destroy() returns true.
+        */
+       shp->shm_creator = NULL;
+
+       /*
+        * Don't even try to destroy it.  If shm_rmid_forced=0 and IPC_RMID
+        * is not set, it shouldn't be deleted here.
+        */
+       if (!ns->shm_rmid_forced)
                return 0;
-       }
 
-       if (shm_may_destroy(ns, shp))
+       if (shm_may_destroy(ns, shp)) {
+               shm_lock_by_ptr(shp);
                shm_destroy(ns, shp);
-       else
-               shm_unlock(shp);
+       }
        return 0;
 }
 
+/* Called with ns->shm_ids(ns).rw_mutex locked */
 static int shm_try_destroy_orphaned(int id, void *p, void *data)
 {
        struct ipc_namespace *ns = data;
-       struct shmid_kernel *shp = shm_lock(ns, id);
-       struct task_struct *task;
-
-       if (IS_ERR(shp))
-               return 0;
+       struct kern_ipc_perm *ipcp = p;
+       struct shmid_kernel *shp = container_of(ipcp, struct shmid_kernel, shm_perm);
 
        /*
         * We want to destroy segments without users and with already
         * exit'ed originating process.
         *
-        * XXX: the originating process may exist in another pid namespace.
+        * As shp->* are changed under rw_mutex, it's safe to skip shp locking.
         */
-       task = find_task_by_vpid(shp->shm_cprid);
-       if (task != NULL) {
-               shm_unlock(shp);
+       if (shp->shm_creator != NULL)
                return 0;
-       }
 
-       if (shm_may_destroy(ns, shp))
+       if (shm_may_destroy(ns, shp)) {
+               shm_lock_by_ptr(shp);
                shm_destroy(ns, shp);
-       else
-               shm_unlock(shp);
+       }
        return 0;
 }
 
 void shm_destroy_orphaned(struct ipc_namespace *ns)
 {
        down_write(&shm_ids(ns).rw_mutex);
-       idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_orphaned, ns);
+       if (shm_ids(ns).in_use)
+               idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_orphaned, ns);
        up_write(&shm_ids(ns).rw_mutex);
 }
 
 
 void exit_shm(struct task_struct *task)
 {
-       struct nsproxy *nsp = task->nsproxy;
-       struct ipc_namespace *ns;
+       struct ipc_namespace *ns = task->nsproxy->ipc_ns;
 
-       if (!nsp)
-               return;
-       ns = nsp->ipc_ns;
-       if (!ns || !ns->shm_rmid_forced)
+       if (shm_ids(ns).in_use == 0)
                return;
 
        /* Destroy all already created segments, but not mapped yet */
        down_write(&shm_ids(ns).rw_mutex);
-       idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_current, ns);
+       if (shm_ids(ns).in_use)
+               idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_current, ns);
        up_write(&shm_ids(ns).rw_mutex);
 }
 
@@ -494,6 +511,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        shp->shm_segsz = size;
        shp->shm_nattch = 0;
        shp->shm_file = file;
+       shp->shm_creator = current;
        /*
         * shmid gets reported as "inode#" in /proc/pid/maps.
         * proc-ps tools use this. Changing this will break them.
index d06467f..eca595e 100644 (file)
@@ -10,7 +10,7 @@ obj-y     = sched.o fork.o exec_domain.o panic.o printk.o \
            kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
            hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
            notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \
-           async.o range.o jump_label.o
+           async.o range.o
 obj-y += groups.o
 
 ifdef CONFIG_FUNCTION_TRACER
@@ -107,6 +107,7 @@ obj-$(CONFIG_PERF_EVENTS) += events/
 obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
 obj-$(CONFIG_PADATA) += padata.o
 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
+obj-$(CONFIG_JUMP_LABEL) += jump_label.o
 
 ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
index 616c781..e2435ee 100644 (file)
@@ -158,6 +158,7 @@ int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user
                        __put_user(ts->tv_sec, &cts->tv_sec) ||
                        __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
 }
+EXPORT_SYMBOL_GPL(put_compat_timespec);
 
 static long compat_nanosleep_restart(struct restart_block *restart)
 {
index 174fa84..8ef31f5 100644 (file)
@@ -508,10 +508,8 @@ int commit_creds(struct cred *new)
                key_fsgid_changed(task);
 
        /* do it
-        * - What if a process setreuid()'s and this brings the
-        *   new uid over his NPROC rlimit?  We can check this now
-        *   cheaply with the new uid cache, so if it matters
-        *   we should be checking for it.  -DaveM
+        * RLIMIT_NPROC limits on user->processes have already been checked
+        * in set_user().
         */
        alter_cred_subscribers(new, 2);
        if (new->user != old->user)
index a11db95..3487248 100644 (file)
@@ -42,6 +42,8 @@
 /* Our I/O buffers. */
 static char                    remcom_in_buffer[BUFMAX];
 static char                    remcom_out_buffer[BUFMAX];
+static int                     gdbstub_use_prev_in_buf;
+static int                     gdbstub_prev_in_buf_pos;
 
 /* Storage for the registers, in GDB format. */
 static unsigned long           gdb_regs[(NUMREGBYTES +
@@ -58,6 +60,13 @@ static int gdbstub_read_wait(void)
        int ret = -1;
        int i;
 
+       if (unlikely(gdbstub_use_prev_in_buf)) {
+               if (gdbstub_prev_in_buf_pos < gdbstub_use_prev_in_buf)
+                       return remcom_in_buffer[gdbstub_prev_in_buf_pos++];
+               else
+                       gdbstub_use_prev_in_buf = 0;
+       }
+
        /* poll any additional I/O interfaces that are defined */
        while (ret < 0)
                for (i = 0; kdb_poll_funcs[i] != NULL; i++) {
@@ -109,7 +118,6 @@ static void get_packet(char *buffer)
                        buffer[count] = ch;
                        count = count + 1;
                }
-               buffer[count] = 0;
 
                if (ch == '#') {
                        xmitcsum = hex_to_bin(gdbstub_read_wait()) << 4;
@@ -124,6 +132,7 @@ static void get_packet(char *buffer)
                        if (dbg_io_ops->flush)
                                dbg_io_ops->flush();
                }
+               buffer[count] = 0;
        } while (checksum != xmitcsum);
 }
 
@@ -1082,12 +1091,11 @@ int gdbstub_state(struct kgdb_state *ks, char *cmd)
        case 'c':
                strcpy(remcom_in_buffer, cmd);
                return 0;
-       case '?':
-               gdb_cmd_status(ks);
-               break;
-       case '\0':
-               strcpy(remcom_out_buffer, "");
-               break;
+       case '$':
+               strcpy(remcom_in_buffer, cmd);
+               gdbstub_use_prev_in_buf = strlen(remcom_in_buffer);
+               gdbstub_prev_in_buf_pos = 0;
+               return 0;
        }
        dbg_io_ops->write_char('+');
        put_packet(remcom_out_buffer);
index 2f62fe8..7179eac 100644 (file)
@@ -112,9 +112,8 @@ kdb_bt(int argc, const char **argv)
        unsigned long addr;
        long offset;
 
-       kdbgetintenv("BTARGS", &argcount);      /* Arguments to print */
-       kdbgetintenv("BTAPROMPT", &btaprompt);  /* Prompt after each
-                                                * proc in bta */
+       /* Prompt after each proc in bta */
+       kdbgetintenv("BTAPROMPT", &btaprompt);
 
        if (strcmp(argv[0], "bta") == 0) {
                struct task_struct *g, *p;
index 56c88e4..9834ad3 100644 (file)
@@ -18,16 +18,12 @@ defcmd dumpcommon "" "Common kdb debugging"
 endefcmd
 
 defcmd dumpall "" "First line debugging"
-  set BTSYMARG 1
-  set BTARGS 9
   pid R
   -dumpcommon
   -bta
 endefcmd
 
 defcmd dumpcpu "" "Same as dumpall but only tasks on cpus"
-  set BTSYMARG 1
-  set BTARGS 9
   pid R
   -dumpcommon
   -btc
index dd0b1b7..d9ca9aa 100644 (file)
@@ -30,6 +30,8 @@ EXPORT_SYMBOL_GPL(kdb_poll_funcs);
 int kdb_poll_idx = 1;
 EXPORT_SYMBOL_GPL(kdb_poll_idx);
 
+static struct kgdb_state *kdb_ks;
+
 int kdb_stub(struct kgdb_state *ks)
 {
        int error = 0;
@@ -39,6 +41,7 @@ int kdb_stub(struct kgdb_state *ks)
        kdb_dbtrap_t db_result = KDB_DB_NOBPT;
        int i;
 
+       kdb_ks = ks;
        if (KDB_STATE(REENTRY)) {
                reason = KDB_REASON_SWITCH;
                KDB_STATE_CLEAR(REENTRY);
@@ -123,20 +126,8 @@ int kdb_stub(struct kgdb_state *ks)
        KDB_STATE_CLEAR(PAGER);
        kdbnearsym_cleanup();
        if (error == KDB_CMD_KGDB) {
-               if (KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)) {
-       /*
-        * This inteface glue which allows kdb to transition in into
-        * the gdb stub.  In order to do this the '?' or '' gdb serial
-        * packet response is processed here.  And then control is
-        * passed to the gdbstub.
-        */
-                       if (KDB_STATE(DOING_KGDB))
-                               gdbstub_state(ks, "?");
-                       else
-                               gdbstub_state(ks, "");
+               if (KDB_STATE(DOING_KGDB))
                        KDB_STATE_CLEAR(DOING_KGDB);
-                       KDB_STATE_CLEAR(DOING_KGDB2);
-               }
                return DBG_PASS_EVENT;
        }
        kdb_bp_install(ks->linux_regs);
@@ -166,3 +157,7 @@ int kdb_stub(struct kgdb_state *ks)
        return kgdb_info[ks->cpu].ret_state;
 }
 
+void kdb_gdb_state_pass(char *buf)
+{
+       gdbstub_state(kdb_ks, buf);
+}
index 96fdaac..4802eb5 100644 (file)
@@ -31,15 +31,21 @@ char kdb_prompt_str[CMD_BUFLEN];
 
 int kdb_trap_printk;
 
-static void kgdb_transition_check(char *buffer)
+static int kgdb_transition_check(char *buffer)
 {
-       int slen = strlen(buffer);
-       if (strncmp(buffer, "$?#3f", slen) != 0 &&
-           strncmp(buffer, "$qSupported#37", slen) != 0 &&
-           strncmp(buffer, "+$qSupported#37", slen) != 0) {
+       if (buffer[0] != '+' && buffer[0] != '$') {
                KDB_STATE_SET(KGDB_TRANS);
                kdb_printf("%s", buffer);
+       } else {
+               int slen = strlen(buffer);
+               if (slen > 3 && buffer[slen - 3] == '#') {
+                       kdb_gdb_state_pass(buffer);
+                       strcpy(buffer, "kgdb");
+                       KDB_STATE_SET(DOING_KGDB);
+                       return 1;
+               }
        }
+       return 0;
 }
 
 static int kdb_read_get_key(char *buffer, size_t bufsize)
@@ -251,6 +257,10 @@ poll_again:
        case 13: /* enter */
                *lastchar++ = '\n';
                *lastchar++ = '\0';
+               if (!KDB_STATE(KGDB_TRANS)) {
+                       KDB_STATE_SET(KGDB_TRANS);
+                       kdb_printf("%s", buffer);
+               }
                kdb_printf("\n");
                return buffer;
        case 4: /* Del */
@@ -382,22 +392,26 @@ poll_again:
                                 * printed characters if we think that
                                 * kgdb is connecting, until the check
                                 * fails */
-                               if (!KDB_STATE(KGDB_TRANS))
-                                       kgdb_transition_check(buffer);
-                               else
+                               if (!KDB_STATE(KGDB_TRANS)) {
+                                       if (kgdb_transition_check(buffer))
+                                               return buffer;
+                               } else {
                                        kdb_printf("%c", key);
+                               }
                        }
                        /* Special escape to kgdb */
                        if (lastchar - buffer >= 5 &&
                            strcmp(lastchar - 5, "$?#3f") == 0) {
+                               kdb_gdb_state_pass(lastchar - 5);
                                strcpy(buffer, "kgdb");
                                KDB_STATE_SET(DOING_KGDB);
                                return buffer;
                        }
-                       if (lastchar - buffer >= 14 &&
-                           strcmp(lastchar - 14, "$qSupported#37") == 0) {
+                       if (lastchar - buffer >= 11 &&
+                           strcmp(lastchar - 11, "$qSupported") == 0) {
+                               kdb_gdb_state_pass(lastchar - 11);
                                strcpy(buffer, "kgdb");
-                               KDB_STATE_SET(DOING_KGDB2);
+                               KDB_STATE_SET(DOING_KGDB);
                                return buffer;
                        }
                }
index be14779..63786e7 100644 (file)
@@ -145,7 +145,6 @@ static char *__env[] = {
 #endif
  "RADIX=16",
  "MDCOUNT=8",                  /* lines of md output */
- "BTARGS=9",                   /* 9 possible args in bt */
  KDB_PLATFORM_ENV,
  "DTABCOUNT=30",
  "NOSECT=1",
@@ -172,6 +171,7 @@ static char *__env[] = {
  (char *)0,
  (char *)0,
  (char *)0,
+ (char *)0,
 };
 
 static const int __nenv = (sizeof(__env) / sizeof(char *));
@@ -1386,7 +1386,7 @@ int kdb_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,
                }
 
                if (result == KDB_CMD_KGDB) {
-                       if (!(KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)))
+                       if (!KDB_STATE(DOING_KGDB))
                                kdb_printf("Entering please attach debugger "
                                           "or use $D#44+ or $3#33\n");
                        break;
index 35d69ed..e381d10 100644 (file)
@@ -21,7 +21,6 @@
 #define KDB_CMD_SS     (-1003)
 #define KDB_CMD_SSB    (-1004)
 #define KDB_CMD_KGDB (-1005)
-#define KDB_CMD_KGDB2 (-1006)
 
 /* Internal debug flags */
 #define KDB_DEBUG_FLAG_BP      0x0002  /* Breakpoint subsystem debug */
@@ -146,7 +145,6 @@ extern int kdb_state;
                                                 * keyboard on this cpu */
 #define KDB_STATE_KEXEC                0x00040000      /* kexec issued */
 #define KDB_STATE_DOING_KGDB   0x00080000      /* kgdb enter now issued */
-#define KDB_STATE_DOING_KGDB2  0x00100000      /* kgdb enter now issued */
 #define KDB_STATE_KGDB_TRANS   0x00200000      /* Transition to kgdb */
 #define KDB_STATE_ARCH         0xff000000      /* Reserved for arch
                                                 * specific use */
@@ -218,6 +216,7 @@ extern void kdb_print_nameval(const char *name, unsigned long val);
 extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info);
 extern void kdb_meminfo_proc_show(void);
 extern char *kdb_getstr(char *, size_t, char *);
+extern void kdb_gdb_state_pass(char *buf);
 
 /* Defines for kdb_symbol_print */
 #define KDB_SP_SPACEB  0x0001          /* Space before string */
index e7ceaca..8e6b6f4 100644 (file)
@@ -1111,6 +1111,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                    p->real_cred->user != INIT_USER)
                        goto bad_fork_free;
        }
+       current->flags &= ~PF_NPROC_EXCEEDED;
 
        retval = copy_creds(p, clone_flags);
        if (retval < 0)
index 0a30897..11cbe05 100644 (file)
@@ -218,6 +218,8 @@ static void drop_futex_key_refs(union futex_key *key)
  * @uaddr:     virtual address of the futex
  * @fshared:   0 for a PROCESS_PRIVATE futex, 1 for PROCESS_SHARED
  * @key:       address where result is stored.
+ * @rw:                mapping needs to be read/write (values: VERIFY_READ,
+ *              VERIFY_WRITE)
  *
  * Returns a negative error code or 0
  * The key words are stored in *key on success.
@@ -229,12 +231,12 @@ static void drop_futex_key_refs(union futex_key *key)
  * lock_page() might sleep, the caller should not hold a spinlock.
  */
 static int
-get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key)
+get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
 {
        unsigned long address = (unsigned long)uaddr;
        struct mm_struct *mm = current->mm;
        struct page *page, *page_head;
-       int err;
+       int err, ro = 0;
 
        /*
         * The futex address must be "naturally" aligned.
@@ -262,8 +264,18 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key)
 
 again:
        err = get_user_pages_fast(address, 1, 1, &page);
+       /*
+        * If write access is not required (eg. FUTEX_WAIT), try
+        * and get read-only access.
+        */
+       if (err == -EFAULT && rw == VERIFY_READ) {
+               err = get_user_pages_fast(address, 1, 0, &page);
+               ro = 1;
+       }
        if (err < 0)
                return err;
+       else
+               err = 0;
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
        page_head = page;
@@ -305,6 +317,13 @@ again:
        if (!page_head->mapping) {
                unlock_page(page_head);
                put_page(page_head);
+               /*
+               * ZERO_PAGE pages don't have a mapping. Avoid a busy loop
+               * trying to find one. RW mapping would have COW'd (and thus
+               * have a mapping) so this page is RO and won't ever change.
+               */
+               if ((page_head == ZERO_PAGE(address)))
+                       return -EFAULT;
                goto again;
        }
 
@@ -316,6 +335,15 @@ again:
         * the object not the particular process.
         */
        if (PageAnon(page_head)) {
+               /*
+                * A RO anonymous page will never change and thus doesn't make
+                * sense for futex operations.
+                */
+               if (ro) {
+                       err = -EFAULT;
+                       goto out;
+               }
+
                key->both.offset |= FUT_OFF_MMSHARED; /* ref taken on mm */
                key->private.mm = mm;
                key->private.address = address;
@@ -327,9 +355,10 @@ again:
 
        get_futex_key_refs(key);
 
+out:
        unlock_page(page_head);
        put_page(page_head);
-       return 0;
+       return err;
 }
 
 static inline void put_futex_key(union futex_key *key)
@@ -940,7 +969,7 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
        if (!bitset)
                return -EINVAL;
 
-       ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key);
+       ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, VERIFY_READ);
        if (unlikely(ret != 0))
                goto out;
 
@@ -986,10 +1015,10 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
        int ret, op_ret;
 
 retry:
-       ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1);
+       ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, VERIFY_READ);
        if (unlikely(ret != 0))
                goto out;
-       ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2);
+       ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, VERIFY_WRITE);
        if (unlikely(ret != 0))
                goto out_put_key1;
 
@@ -1243,10 +1272,11 @@ retry:
                pi_state = NULL;
        }
 
-       ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1);
+       ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, VERIFY_READ);
        if (unlikely(ret != 0))
                goto out;
-       ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2);
+       ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2,
+                           requeue_pi ? VERIFY_WRITE : VERIFY_READ);
        if (unlikely(ret != 0))
                goto out_put_key1;
 
@@ -1790,7 +1820,7 @@ static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
         * while the syscall executes.
         */
 retry:
-       ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q->key);
+       ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q->key, VERIFY_READ);
        if (unlikely(ret != 0))
                return ret;
 
@@ -1941,7 +1971,7 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, int detect,
        }
 
 retry:
-       ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q.key);
+       ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q.key, VERIFY_WRITE);
        if (unlikely(ret != 0))
                goto out;
 
@@ -2060,7 +2090,7 @@ retry:
        if ((uval & FUTEX_TID_MASK) != vpid)
                return -EPERM;
 
-       ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key);
+       ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, VERIFY_WRITE);
        if (unlikely(ret != 0))
                goto out;
 
@@ -2249,7 +2279,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
        debug_rt_mutex_init_waiter(&rt_waiter);
        rt_waiter.task = NULL;
 
-       ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2);
+       ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, VERIFY_WRITE);
        if (unlikely(ret != 0))
                goto out;
 
index d1d051b..5a38bf4 100644 (file)
@@ -52,6 +52,10 @@ config IRQ_EDGE_EOI_HANDLER
 config GENERIC_IRQ_CHIP
        bool
 
+# Generic irq_domain hw <--> linux irq number translation
+config IRQ_DOMAIN
+       bool
+
 # Support forced irq threading
 config IRQ_FORCED_THREADING
        bool
index 7329005..fff1738 100644 (file)
@@ -2,6 +2,7 @@
 obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o
 obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
+obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
 obj-$(CONFIG_PM_SLEEP) += pm.o
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
new file mode 100644 (file)
index 0000000..d5828da
--- /dev/null
@@ -0,0 +1,180 @@
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+static LIST_HEAD(irq_domain_list);
+static DEFINE_MUTEX(irq_domain_mutex);
+
+/**
+ * irq_domain_add() - Register an irq_domain
+ * @domain: ptr to initialized irq_domain structure
+ *
+ * Registers an irq_domain structure.  The irq_domain must at a minimum be
+ * initialized with an ops structure pointer, and either a ->to_irq hook or
+ * a valid irq_base value.  Everything else is optional.
+ */
+void irq_domain_add(struct irq_domain *domain)
+{
+       struct irq_data *d;
+       int hwirq;
+
+       /*
+        * This assumes that the irq_domain owner has already allocated
+        * the irq_descs.  This block will be removed when support for dynamic
+        * allocation of irq_descs is added to irq_domain.
+        */
+       for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
+               d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+               if (d || d->domain) {
+                       /* things are broken; just report, don't clean up */
+                       WARN(1, "error: irq_desc already assigned to a domain");
+                       return;
+               }
+               d->domain = domain;
+               d->hwirq = hwirq;
+       }
+
+       mutex_lock(&irq_domain_mutex);
+       list_add(&domain->list, &irq_domain_list);
+       mutex_unlock(&irq_domain_mutex);
+}
+
+/**
+ * irq_domain_del() - Unregister an irq_domain
+ * @domain: ptr to registered irq_domain.
+ */
+void irq_domain_del(struct irq_domain *domain)
+{
+       struct irq_data *d;
+       int hwirq;
+
+       mutex_lock(&irq_domain_mutex);
+       list_del(&domain->list);
+       mutex_unlock(&irq_domain_mutex);
+
+       /* Clear the irq_domain assignments */
+       for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
+               d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+               d->domain = NULL;
+       }
+}
+
+#if defined(CONFIG_OF_IRQ)
+/**
+ * irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec
+ *
+ * Used by the device tree interrupt mapping code to translate a device tree
+ * interrupt specifier to a valid linux irq number.  Returns either a valid
+ * linux IRQ number or 0.
+ *
+ * When the caller no longer need the irq number returned by this function it
+ * should arrange to call irq_dispose_mapping().
+ */
+unsigned int irq_create_of_mapping(struct device_node *controller,
+                                  const u32 *intspec, unsigned int intsize)
+{
+       struct irq_domain *domain;
+       unsigned long hwirq;
+       unsigned int irq, type;
+       int rc = -EINVAL;
+
+       /* Find a domain which can translate the irq spec */
+       mutex_lock(&irq_domain_mutex);
+       list_for_each_entry(domain, &irq_domain_list, list) {
+               if (!domain->ops->dt_translate)
+                       continue;
+               rc = domain->ops->dt_translate(domain, controller,
+                                       intspec, intsize, &hwirq, &type);
+               if (rc == 0)
+                       break;
+       }
+       mutex_unlock(&irq_domain_mutex);
+
+       if (rc != 0)
+               return 0;
+
+       irq = irq_domain_to_irq(domain, hwirq);
+       if (type != IRQ_TYPE_NONE)
+               irq_set_irq_type(irq, type);
+       pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n",
+                controller->full_name, (int)hwirq, irq, type);
+       return irq;
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+
+/**
+ * irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping()
+ * @irq: linux irq number to be discarded
+ *
+ * Calling this function indicates the caller no longer needs a reference to
+ * the linux irq number returned by a prior call to irq_create_of_mapping().
+ */
+void irq_dispose_mapping(unsigned int irq)
+{
+       /*
+        * nothing yet; will be filled when support for dynamic allocation of
+        * irq_descs is added to irq_domain
+        */
+}
+EXPORT_SYMBOL_GPL(irq_dispose_mapping);
+
+int irq_domain_simple_dt_translate(struct irq_domain *d,
+                           struct device_node *controller,
+                           const u32 *intspec, unsigned int intsize,
+                           unsigned long *out_hwirq, unsigned int *out_type)
+{
+       if (d->of_node != controller)
+               return -EINVAL;
+       if (intsize < 1)
+               return -EINVAL;
+
+       *out_hwirq = intspec[0];
+       *out_type = IRQ_TYPE_NONE;
+       if (intsize > 1)
+               *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+       return 0;
+}
+
+struct irq_domain_ops irq_domain_simple_ops = {
+       .dt_translate = irq_domain_simple_dt_translate,
+};
+EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
+
+/**
+ * irq_domain_create_simple() - Set up a 'simple' translation range
+ */
+void irq_domain_add_simple(struct device_node *controller, int irq_base)
+{
+       struct irq_domain *domain;
+
+       domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+       if (!domain) {
+               WARN_ON(1);
+               return;
+       }
+
+       domain->irq_base = irq_base;
+       domain->of_node = of_node_get(controller);
+       domain->ops = &irq_domain_simple_ops;
+       irq_domain_add(domain);
+}
+EXPORT_SYMBOL_GPL(irq_domain_add_simple);
+
+void irq_domain_generate_simple(const struct of_device_id *match,
+                               u64 phys_base, unsigned int irq_start)
+{
+       struct device_node *node;
+       pr_info("looking for phys_base=%llx, irq_start=%i\n",
+               (unsigned long long) phys_base, (int) irq_start);
+       node = of_find_matching_node_by_address(NULL, match, phys_base);
+       if (node)
+               irq_domain_add_simple(node, irq_start);
+       else
+               pr_info("no node found\n");
+}
+EXPORT_SYMBOL_GPL(irq_domain_generate_simple);
+#endif /* CONFIG_OF_IRQ */
index 47613df..ddc7644 100644 (file)
@@ -274,7 +274,7 @@ static void __call_usermodehelper(struct work_struct *work)
  * (used for preventing user land processes from being created after the user
  * land has been frozen during a system-wide hibernation or suspend operation).
  */
-static int usermodehelper_disabled;
+static int usermodehelper_disabled = 1;
 
 /* Number of helpers running */
 static atomic_t running_helpers = ATOMIC_INIT(0);
index 3956f51..8c24294 100644 (file)
@@ -2468,7 +2468,7 @@ mark_held_locks(struct task_struct *curr, enum mark_type mark)
 
                BUG_ON(usage_bit >= LOCK_USAGE_STATES);
 
-               if (hlock_class(hlock)->key == &__lockdep_no_validate__)
+               if (hlock_class(hlock)->key == __lockdep_no_validate__.subkeys)
                        continue;
 
                if (!mark_lock(curr, hlock, usage_bit))
@@ -2485,23 +2485,9 @@ static void __trace_hardirqs_on_caller(unsigned long ip)
 {
        struct task_struct *curr = current;
 
-       if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
-               return;
-
-       if (unlikely(curr->hardirqs_enabled)) {
-               /*
-                * Neither irq nor preemption are disabled here
-                * so this is racy by nature but losing one hit
-                * in a stat is not a big deal.
-                */
-               __debug_atomic_inc(redundant_hardirqs_on);
-               return;
-       }
        /* we'll do an OFF -> ON transition: */
        curr->hardirqs_enabled = 1;
 
-       if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
-               return;
        /*
         * We are going to turn hardirqs on, so set the
         * usage bit for all held locks:
@@ -2529,9 +2515,25 @@ void trace_hardirqs_on_caller(unsigned long ip)
        if (unlikely(!debug_locks || current->lockdep_recursion))
                return;
 
+       if (unlikely(current->hardirqs_enabled)) {
+               /*
+                * Neither irq nor preemption are disabled here
+                * so this is racy by nature but losing one hit
+                * in a stat is not a big deal.
+                */
+               __debug_atomic_inc(redundant_hardirqs_on);
+               return;
+       }
+
        if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
                return;
 
+       if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
+               return;
+
+       if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
+               return;
+
        current->lockdep_recursion = 1;
        __trace_hardirqs_on_caller(ip);
        current->lockdep_recursion = 0;
@@ -2872,10 +2874,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
 void lockdep_init_map(struct lockdep_map *lock, const char *name,
                      struct lock_class_key *key, int subclass)
 {
-       int i;
-
-       for (i = 0; i < NR_LOCKDEP_CACHING_CLASSES; i++)
-               lock->class_cache[i] = NULL;
+       memset(lock, 0, sizeof(*lock));
 
 #ifdef CONFIG_LOCK_STAT
        lock->cpu = raw_smp_processor_id();
index 37dff34..836a2ae 100644 (file)
@@ -318,8 +318,10 @@ static int check_syslog_permissions(int type, bool from_file)
                        return 0;
                /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */
                if (capable(CAP_SYS_ADMIN)) {
-                       WARN_ONCE(1, "Attempt to access syslog with CAP_SYS_ADMIN "
-                                "but no CAP_SYSLOG (deprecated).\n");
+                       printk_once(KERN_WARNING "%s (%d): "
+                                "Attempt to access syslog with CAP_SYS_ADMIN "
+                                "but no CAP_SYSLOG (deprecated).\n",
+                                current->comm, task_pid_nr(current));
                        return 0;
                }
                return -EPERM;
index 3ff4017..3b3cedc 100644 (file)
@@ -553,6 +553,27 @@ int allocate_resource(struct resource *root, struct resource *new,
 
 EXPORT_SYMBOL(allocate_resource);
 
+/**
+ * lookup_resource - find an existing resource by a resource start address
+ * @root: root resource descriptor
+ * @start: resource start address
+ *
+ * Returns a pointer to the resource if found, NULL otherwise
+ */
+struct resource *lookup_resource(struct resource *root, resource_size_t start)
+{
+       struct resource *res;
+
+       read_lock(&resource_lock);
+       for (res = root->child; res; res = res->sibling) {
+               if (res->start == start)
+                       break;
+       }
+       read_unlock(&resource_lock);
+
+       return res;
+}
+
 /*
  * Insert a resource into the resource tree. If successful, return NULL,
  * otherwise return the conflicting resource (compare to __request_resource())
index a101ba3..dd948a1 100644 (file)
@@ -621,11 +621,18 @@ static int set_user(struct cred *new)
        if (!new_user)
                return -EAGAIN;
 
+       /*
+        * We don't fail in case of NPROC limit excess here because too many
+        * poorly written programs don't check set*uid() return code, assuming
+        * it never fails if called by root.  We may still enforce NPROC limit
+        * for programs doing set*uid()+execve() by harmlessly deferring the
+        * failure to the execve() stage.
+        */
        if (atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) &&
-                       new_user != INIT_USER) {
-               free_uid(new_user);
-               return -EAGAIN;
-       }
+                       new_user != INIT_USER)
+               current->flags |= PF_NPROC_EXCEEDED;
+       else
+               current->flags &= ~PF_NPROC_EXCEEDED;
 
        free_uid(new->user);
        new->user = new_user;
index d1db288..e19ce14 100644 (file)
@@ -291,30 +291,28 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
        if (!cpumask_subset(mask, cpu_possible_mask))
                return -EINVAL;
 
-       s = NULL;
        if (isadd == REGISTER) {
                for_each_cpu(cpu, mask) {
-                       if (!s)
-                               s = kmalloc_node(sizeof(struct listener),
-                                                GFP_KERNEL, cpu_to_node(cpu));
+                       s = kmalloc_node(sizeof(struct listener),
+                                       GFP_KERNEL, cpu_to_node(cpu));
                        if (!s)
                                goto cleanup;
+
                        s->pid = pid;
-                       INIT_LIST_HEAD(&s->list);
                        s->valid = 1;
 
                        listeners = &per_cpu(listener_array, cpu);
                        down_write(&listeners->sem);
-                       list_for_each_entry_safe(s2, tmp, &listeners->list, list) {
-                               if (s2->pid == pid)
-                                       goto next_cpu;
+                       list_for_each_entry(s2, &listeners->list, list) {
+                               if (s2->pid == pid && s2->valid)
+                                       goto exists;
                        }
                        list_add(&s->list, &listeners->list);
                        s = NULL;
-next_cpu:
+exists:
                        up_write(&listeners->sem);
+                       kfree(s); /* nop if NULL */
                }
-               kfree(s);
                return 0;
        }
 
index 2ad39e5..cd31345 100644 (file)
@@ -82,7 +82,7 @@ config EVENT_POWER_TRACING_DEPRECATED
          power:power_frequency
          This is for userspace compatibility
          and will vanish after 5 kernel iterations,
-         namely 2.6.41.
+         namely 3.1.
 
 config CONTEXT_SWITCH_TRACER
        bool
index 32f3e5a..6c695ff 100644 (file)
@@ -276,4 +276,7 @@ config CORDIC
          so its calculations are in fixed point. Modules can select this
          when they require this function. Module will be called cordic.
 
+config LLIST
+       bool
+
 endmenu
index 892f4e2..d5d175c 100644 (file)
@@ -10,7 +10,7 @@ endif
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
         rbtree.o radix-tree.o dump_stack.o timerqueue.o\
         idr.o int_sqrt.o extable.o prio_tree.o \
-        sha1.o irq_regs.o reciprocal_div.o argv_split.o \
+        sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
         proportions.o prio_heap.o ratelimit.o show_mem.o \
         is_single_threaded.o plist.o decompress.o find_next_bit.o
 
@@ -115,6 +115,8 @@ obj-$(CONFIG_CPU_RMAP) += cpu_rmap.o
 
 obj-$(CONFIG_CORDIC) += cordic.o
 
+obj-$(CONFIG_LLIST) += llist.o
+
 hostprogs-y    := gen_crc32table
 clean-files    := crc32table.h
 
index 37ef4b0..2f4412e 100644 (file)
@@ -271,8 +271,6 @@ int __bitmap_weight(const unsigned long *bitmap, int bits)
 }
 EXPORT_SYMBOL(__bitmap_weight);
 
-#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
-
 void bitmap_set(unsigned long *map, int start, int nr)
 {
        unsigned long *p = map + BIT_WORD(start);
index 2577b12..f193b77 100644 (file)
@@ -197,21 +197,15 @@ static struct dentry *debugfs_create_atomic_t(const char *name, mode_t mode,
        return debugfs_create_file(name, mode, parent, value, &fops_atomic_t);
 }
 
-void cleanup_fault_attr_dentries(struct fault_attr *attr)
-{
-       debugfs_remove_recursive(attr->dir);
-}
-
-int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
+struct dentry *fault_create_debugfs_attr(const char *name,
+                       struct dentry *parent, struct fault_attr *attr)
 {
        mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
        struct dentry *dir;
 
-       dir = debugfs_create_dir(name, NULL);
+       dir = debugfs_create_dir(name, parent);
        if (!dir)
-               return -ENOMEM;
-
-       attr->dir = dir;
+               return ERR_PTR(-ENOMEM);
 
        if (!debugfs_create_ul("probability", mode, dir, &attr->probability))
                goto fail;
@@ -243,11 +237,11 @@ int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
 
 #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
 
-       return 0;
+       return dir;
 fail:
-       debugfs_remove_recursive(attr->dir);
+       debugfs_remove_recursive(dir);
 
-       return -ENOMEM;
+       return ERR_PTR(-ENOMEM);
 }
 
 #endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
index 577ddf8..f352cc4 100644 (file)
@@ -1,8 +1,26 @@
 /*
- * Basic general purpose allocator for managing special purpose memory
- * not managed by the regular kmalloc/kfree interface.
- * Uses for this includes on-device special memory, uncached memory
- * etc.
+ * Basic general purpose allocator for managing special purpose
+ * memory, for example, memory that is not managed by the regular
+ * kmalloc/kfree interface.  Uses for this includes on-device special
+ * memory, uncached memory etc.
+ *
+ * It is safe to use the allocator in NMI handlers and other special
+ * unblockable contexts that could otherwise deadlock on locks.  This
+ * is implemented by using atomic operations and retries on any
+ * conflicts.  The disadvantage is that there may be livelocks in
+ * extreme cases.  For better scalability, one allocator can be used
+ * for each CPU.
+ *
+ * The lockless operation only works if there is enough memory
+ * available.  If new memory is added to the pool a lock has to be
+ * still taken.  So any user relying on locklessness has to ensure
+ * that sufficient memory is preallocated.
+ *
+ * The basic atomic operation of this allocator is cmpxchg on long.
+ * On architectures that don't have NMI-safe cmpxchg implementation,
+ * the allocator can NOT be used in NMI handler.  So code uses the
+ * allocator in NMI handler should depend on
+ * CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG.
  *
  * Copyright 2005 (C) Jes Sorensen <jes@trained-monkey.org>
  *
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/bitmap.h>
+#include <linux/rculist.h>
+#include <linux/interrupt.h>
 #include <linux/genalloc.h>
 
+static int set_bits_ll(unsigned long *addr, unsigned long mask_to_set)
+{
+       unsigned long val, nval;
+
+       nval = *addr;
+       do {
+               val = nval;
+               if (val & mask_to_set)
+                       return -EBUSY;
+               cpu_relax();
+       } while ((nval = cmpxchg(addr, val, val | mask_to_set)) != val);
+
+       return 0;
+}
+
+static int clear_bits_ll(unsigned long *addr, unsigned long mask_to_clear)
+{
+       unsigned long val, nval;
+
+       nval = *addr;
+       do {
+               val = nval;
+               if ((val & mask_to_clear) != mask_to_clear)
+                       return -EBUSY;
+               cpu_relax();
+       } while ((nval = cmpxchg(addr, val, val & ~mask_to_clear)) != val);
+
+       return 0;
+}
+
+/*
+ * bitmap_set_ll - set the specified number of bits at the specified position
+ * @map: pointer to a bitmap
+ * @start: a bit position in @map
+ * @nr: number of bits to set
+ *
+ * Set @nr bits start from @start in @map lock-lessly. Several users
+ * can set/clear the same bitmap simultaneously without lock. If two
+ * users set the same bit, one user will return remain bits, otherwise
+ * return 0.
+ */
+static int bitmap_set_ll(unsigned long *map, int start, int nr)
+{
+       unsigned long *p = map + BIT_WORD(start);
+       const int size = start + nr;
+       int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
+       unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
+
+       while (nr - bits_to_set >= 0) {
+               if (set_bits_ll(p, mask_to_set))
+                       return nr;
+               nr -= bits_to_set;
+               bits_to_set = BITS_PER_LONG;
+               mask_to_set = ~0UL;
+               p++;
+       }
+       if (nr) {
+               mask_to_set &= BITMAP_LAST_WORD_MASK(size);
+               if (set_bits_ll(p, mask_to_set))
+                       return nr;
+       }
+
+       return 0;
+}
+
+/*
+ * bitmap_clear_ll - clear the specified number of bits at the specified position
+ * @map: pointer to a bitmap
+ * @start: a bit position in @map
+ * @nr: number of bits to set
+ *
+ * Clear @nr bits start from @start in @map lock-lessly. Several users
+ * can set/clear the same bitmap simultaneously without lock. If two
+ * users clear the same bit, one user will return remain bits,
+ * otherwise return 0.
+ */
+static int bitmap_clear_ll(unsigned long *map, int start, int nr)
+{
+       unsigned long *p = map + BIT_WORD(start);
+       const int size = start + nr;
+       int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
+       unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
+
+       while (nr - bits_to_clear >= 0) {
+               if (clear_bits_ll(p, mask_to_clear))
+                       return nr;
+               nr -= bits_to_clear;
+               bits_to_clear = BITS_PER_LONG;
+               mask_to_clear = ~0UL;
+               p++;
+       }
+       if (nr) {
+               mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
+               if (clear_bits_ll(p, mask_to_clear))
+                       return nr;
+       }
+
+       return 0;
+}
 
 /**
  * gen_pool_create - create a new special memory pool
@@ -30,7 +149,7 @@ struct gen_pool *gen_pool_create(int min_alloc_order, int nid)
 
        pool = kmalloc_node(sizeof(struct gen_pool), GFP_KERNEL, nid);
        if (pool != NULL) {
-               rwlock_init(&pool->lock);
+               spin_lock_init(&pool->lock);
                INIT_LIST_HEAD(&pool->chunks);
                pool->min_alloc_order = min_alloc_order;
        }
@@ -63,14 +182,14 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy
        if (unlikely(chunk == NULL))
                return -ENOMEM;
 
-       spin_lock_init(&chunk->lock);
        chunk->phys_addr = phys;
        chunk->start_addr = virt;
        chunk->end_addr = virt + size;
+       atomic_set(&chunk->avail, size);
 
-       write_lock(&pool->lock);
-       list_add(&chunk->next_chunk, &pool->chunks);
-       write_unlock(&pool->lock);
+       spin_lock(&pool->lock);
+       list_add_rcu(&chunk->next_chunk, &pool->chunks);
+       spin_unlock(&pool->lock);
 
        return 0;
 }
@@ -85,19 +204,19 @@ EXPORT_SYMBOL(gen_pool_add_virt);
  */
 phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long addr)
 {
-       struct list_head *_chunk;
        struct gen_pool_chunk *chunk;
+       phys_addr_t paddr = -1;
 
-       read_lock(&pool->lock);
-       list_for_each(_chunk, &pool->chunks) {
-               chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
-
-               if (addr >= chunk->start_addr && addr < chunk->end_addr)
-                       return chunk->phys_addr + addr - chunk->start_addr;
+       rcu_read_lock();
+       list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
+               if (addr >= chunk->start_addr && addr < chunk->end_addr) {
+                       paddr = chunk->phys_addr + (addr - chunk->start_addr);
+                       break;
+               }
        }
-       read_unlock(&pool->lock);
+       rcu_read_unlock();
 
-       return -1;
+       return paddr;
 }
 EXPORT_SYMBOL(gen_pool_virt_to_phys);
 
@@ -115,7 +234,6 @@ void gen_pool_destroy(struct gen_pool *pool)
        int order = pool->min_alloc_order;
        int bit, end_bit;
 
-
        list_for_each_safe(_chunk, _next_chunk, &pool->chunks) {
                chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
                list_del(&chunk->next_chunk);
@@ -137,44 +255,50 @@ EXPORT_SYMBOL(gen_pool_destroy);
  * @size: number of bytes to allocate from the pool
  *
  * Allocate the requested number of bytes from the specified pool.
- * Uses a first-fit algorithm.
+ * Uses a first-fit algorithm. Can not be used in NMI handler on
+ * architectures without NMI-safe cmpxchg implementation.
  */
 unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
 {
-       struct list_head *_chunk;
        struct gen_pool_chunk *chunk;
-       unsigned long addr, flags;
+       unsigned long addr = 0;
        int order = pool->min_alloc_order;
-       int nbits, start_bit, end_bit;
+       int nbits, start_bit = 0, end_bit, remain;
+
+#ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
+       BUG_ON(in_nmi());
+#endif
 
        if (size == 0)
                return 0;
 
        nbits = (size + (1UL << order) - 1) >> order;
-
-       read_lock(&pool->lock);
-       list_for_each(_chunk, &pool->chunks) {
-               chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
+       rcu_read_lock();
+       list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
+               if (size > atomic_read(&chunk->avail))
+                       continue;
 
                end_bit = (chunk->end_addr - chunk->start_addr) >> order;
-
-               spin_lock_irqsave(&chunk->lock, flags);
-               start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit, 0,
-                                               nbits, 0);
-               if (start_bit >= end_bit) {
-                       spin_unlock_irqrestore(&chunk->lock, flags);
+retry:
+               start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit,
+                                                      start_bit, nbits, 0);
+               if (start_bit >= end_bit)
                        continue;
+               remain = bitmap_set_ll(chunk->bits, start_bit, nbits);
+               if (remain) {
+                       remain = bitmap_clear_ll(chunk->bits, start_bit,
+                                                nbits - remain);
+                       BUG_ON(remain);
+                       goto retry;
                }
 
                addr = chunk->start_addr + ((unsigned long)start_bit << order);
-
-               bitmap_set(chunk->bits, start_bit, nbits);
-               spin_unlock_irqrestore(&chunk->lock, flags);
-               read_unlock(&pool->lock);
-               return addr;
+               size = nbits << order;
+               atomic_sub(size, &chunk->avail);
+               break;
        }
-       read_unlock(&pool->lock);
-       return 0;
+       rcu_read_unlock();
+       return addr;
 }
 EXPORT_SYMBOL(gen_pool_alloc);
 
@@ -184,33 +308,95 @@ EXPORT_SYMBOL(gen_pool_alloc);
  * @addr: starting address of memory to free back to pool
  * @size: size in bytes of memory to free
  *
- * Free previously allocated special memory back to the specified pool.
+ * Free previously allocated special memory back to the specified
+ * pool.  Can not be used in NMI handler on architectures without
+ * NMI-safe cmpxchg implementation.
  */
 void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size)
 {
-       struct list_head *_chunk;
        struct gen_pool_chunk *chunk;
-       unsigned long flags;
        int order = pool->min_alloc_order;
-       int bit, nbits;
+       int start_bit, nbits, remain;
 
-       nbits = (size + (1UL << order) - 1) >> order;
-
-       read_lock(&pool->lock);
-       list_for_each(_chunk, &pool->chunks) {
-               chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
+#ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
+       BUG_ON(in_nmi());
+#endif
 
+       nbits = (size + (1UL << order) - 1) >> order;
+       rcu_read_lock();
+       list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
                if (addr >= chunk->start_addr && addr < chunk->end_addr) {
                        BUG_ON(addr + size > chunk->end_addr);
-                       spin_lock_irqsave(&chunk->lock, flags);
-                       bit = (addr - chunk->start_addr) >> order;
-                       while (nbits--)
-                               __clear_bit(bit++, chunk->bits);
-                       spin_unlock_irqrestore(&chunk->lock, flags);
-                       break;
+                       start_bit = (addr - chunk->start_addr) >> order;
+                       remain = bitmap_clear_ll(chunk->bits, start_bit, nbits);
+                       BUG_ON(remain);
+                       size = nbits << order;
+                       atomic_add(size, &chunk->avail);
+                       rcu_read_unlock();
+                       return;
                }
        }
-       BUG_ON(nbits > 0);
-       read_unlock(&pool->lock);
+       rcu_read_unlock();
+       BUG();
 }
 EXPORT_SYMBOL(gen_pool_free);
+
+/**
+ * gen_pool_for_each_chunk - call func for every chunk of generic memory pool
+ * @pool:      the generic memory pool
+ * @func:      func to call
+ * @data:      additional data used by @func
+ *
+ * Call @func for every chunk of generic memory pool.  The @func is
+ * called with rcu_read_lock held.
+ */
+void gen_pool_for_each_chunk(struct gen_pool *pool,
+       void (*func)(struct gen_pool *pool, struct gen_pool_chunk *chunk, void *data),
+       void *data)
+{
+       struct gen_pool_chunk *chunk;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(chunk, &(pool)->chunks, next_chunk)
+               func(pool, chunk, data);
+       rcu_read_unlock();
+}
+EXPORT_SYMBOL(gen_pool_for_each_chunk);
+
+/**
+ * gen_pool_avail - get available free space of the pool
+ * @pool: pool to get available free space
+ *
+ * Return available free space of the specified pool.
+ */
+size_t gen_pool_avail(struct gen_pool *pool)
+{
+       struct gen_pool_chunk *chunk;
+       size_t avail = 0;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk)
+               avail += atomic_read(&chunk->avail);
+       rcu_read_unlock();
+       return avail;
+}
+EXPORT_SYMBOL_GPL(gen_pool_avail);
+
+/**
+ * gen_pool_size - get size in bytes of memory managed by the pool
+ * @pool: pool to get size
+ *
+ * Return size in bytes of memory managed by the pool.
+ */
+size_t gen_pool_size(struct gen_pool *pool)
+{
+       struct gen_pool_chunk *chunk;
+       size_t size = 0;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk)
+               size += chunk->end_addr - chunk->start_addr;
+       rcu_read_unlock();
+       return size;
+}
+EXPORT_SYMBOL_GPL(gen_pool_size);
index e15502e..db040ce 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
 #include <linux/err.h>
 #include <linux/string.h>
 #include <linux/idr.h>
+#include <linux/spinlock.h>
 
 static struct kmem_cache *idr_layer_cache;
+static DEFINE_SPINLOCK(simple_ida_lock);
 
 static struct idr_layer *get_from_free_list(struct idr *idp)
 {
@@ -925,6 +927,71 @@ void ida_destroy(struct ida *ida)
 }
 EXPORT_SYMBOL(ida_destroy);
 
+/**
+ * ida_simple_get - get a new id.
+ * @ida: the (initialized) ida.
+ * @start: the minimum id (inclusive, < 0x8000000)
+ * @end: the maximum id (exclusive, < 0x8000000 or 0)
+ * @gfp_mask: memory allocation flags
+ *
+ * Allocates an id in the range start <= id < end, or returns -ENOSPC.
+ * On memory allocation failure, returns -ENOMEM.
+ *
+ * Use ida_simple_remove() to get rid of an id.
+ */
+int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
+                  gfp_t gfp_mask)
+{
+       int ret, id;
+       unsigned int max;
+
+       BUG_ON((int)start < 0);
+       BUG_ON((int)end < 0);
+
+       if (end == 0)
+               max = 0x80000000;
+       else {
+               BUG_ON(end < start);
+               max = end - 1;
+       }
+
+again:
+       if (!ida_pre_get(ida, gfp_mask))
+               return -ENOMEM;
+
+       spin_lock(&simple_ida_lock);
+       ret = ida_get_new_above(ida, start, &id);
+       if (!ret) {
+               if (id > max) {
+                       ida_remove(ida, id);
+                       ret = -ENOSPC;
+               } else {
+                       ret = id;
+               }
+       }
+       spin_unlock(&simple_ida_lock);
+
+       if (unlikely(ret == -EAGAIN))
+               goto again;
+
+       return ret;
+}
+EXPORT_SYMBOL(ida_simple_get);
+
+/**
+ * ida_simple_remove - remove an allocated id.
+ * @ida: the (initialized) ida.
+ * @id: the id returned by ida_simple_get.
+ */
+void ida_simple_remove(struct ida *ida, unsigned int id)
+{
+       BUG_ON((int)id < 0);
+       spin_lock(&simple_ida_lock);
+       ida_remove(ida, id);
+       spin_unlock(&simple_ida_lock);
+}
+EXPORT_SYMBOL(ida_simple_remove);
+
 /**
  * ida_init - initialize ida handle
  * @ida:       ida handle
diff --git a/lib/llist.c b/lib/llist.c
new file mode 100644 (file)
index 0000000..da44572
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Lock-less NULL terminated single linked list
+ *
+ * The basic atomic operation of this list is cmpxchg on long.  On
+ * architectures that don't have NMI-safe cmpxchg implementation, the
+ * list can NOT be used in NMI handler.  So code uses the list in NMI
+ * handler should depend on CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG.
+ *
+ * Copyright 2010,2011 Intel Corp.
+ *   Author: Huang Ying <ying.huang@intel.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;
+ *
+ * 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/module.h>
+#include <linux/interrupt.h>
+#include <linux/llist.h>
+
+#include <asm/system.h>
+
+/**
+ * llist_add - add a new entry
+ * @new:       new entry to be added
+ * @head:      the head for your lock-less list
+ */
+void llist_add(struct llist_node *new, struct llist_head *head)
+{
+       struct llist_node *entry, *old_entry;
+
+#ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
+       BUG_ON(in_nmi());
+#endif
+
+       entry = head->first;
+       do {
+               old_entry = entry;
+               new->next = entry;
+               cpu_relax();
+       } while ((entry = cmpxchg(&head->first, old_entry, new)) != old_entry);
+}
+EXPORT_SYMBOL_GPL(llist_add);
+
+/**
+ * llist_add_batch - add several linked entries in batch
+ * @new_first: first entry in batch to be added
+ * @new_last:  last entry in batch to be added
+ * @head:      the head for your lock-less list
+ */
+void llist_add_batch(struct llist_node *new_first, struct llist_node *new_last,
+                    struct llist_head *head)
+{
+       struct llist_node *entry, *old_entry;
+
+#ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
+       BUG_ON(in_nmi());
+#endif
+
+       entry = head->first;
+       do {
+               old_entry = entry;
+               new_last->next = entry;
+               cpu_relax();
+       } while ((entry = cmpxchg(&head->first, old_entry, new_first)) != old_entry);
+}
+EXPORT_SYMBOL_GPL(llist_add_batch);
+
+/**
+ * llist_del_first - delete the first entry of lock-less list
+ * @head:      the head for your lock-less list
+ *
+ * If list is empty, return NULL, otherwise, return the first entry
+ * deleted, this is the newest added one.
+ *
+ * Only one llist_del_first user can be used simultaneously with
+ * multiple llist_add users without lock.  Because otherwise
+ * llist_del_first, llist_add, llist_add (or llist_del_all, llist_add,
+ * llist_add) sequence in another user may change @head->first->next,
+ * but keep @head->first.  If multiple consumers are needed, please
+ * use llist_del_all or use lock between consumers.
+ */
+struct llist_node *llist_del_first(struct llist_head *head)
+{
+       struct llist_node *entry, *old_entry, *next;
+
+#ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
+       BUG_ON(in_nmi());
+#endif
+
+       entry = head->first;
+       do {
+               if (entry == NULL)
+                       return NULL;
+               old_entry = entry;
+               next = entry->next;
+               cpu_relax();
+       } while ((entry = cmpxchg(&head->first, old_entry, next)) != old_entry);
+
+       return entry;
+}
+EXPORT_SYMBOL_GPL(llist_del_first);
+
+/**
+ * llist_del_all - delete all entries from lock-less list
+ * @head:      the head of lock-less list to delete all entries
+ *
+ * If list is empty, return NULL, otherwise, delete all entries and
+ * return the pointer to the first entry.  The order of entries
+ * deleted is from the newest to the oldest added one.
+ */
+struct llist_node *llist_del_all(struct llist_head *head)
+{
+#ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
+       BUG_ON(in_nmi());
+#endif
+
+       return xchg(&head->first, NULL);
+}
+EXPORT_SYMBOL_GPL(llist_del_all);
diff --git a/lib/md5.c b/lib/md5.c
new file mode 100644 (file)
index 0000000..c777180
--- /dev/null
+++ b/lib/md5.c
@@ -0,0 +1,95 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cryptohash.h>
+
+#define F1(x, y, z)    (z ^ (x & (y ^ z)))
+#define F2(x, y, z)    F1(z, x, y)
+#define F3(x, y, z)    (x ^ y ^ z)
+#define F4(x, y, z)    (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, in, s) \
+       (w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
+
+void md5_transform(__u32 *hash, __u32 const *in)
+{
+       u32 a, b, c, d;
+
+       a = hash[0];
+       b = hash[1];
+       c = hash[2];
+       d = hash[3];
+
+       MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+       MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+       MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+       MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+       MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+       MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+       MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+       MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+       MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+       MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+       MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+       MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+       MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+       MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+       MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+       MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+       MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+       MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+       MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+       MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+       MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+       MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+       MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+       MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+       MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+       MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+       MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+       MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+       MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+       MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+       MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+       MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+       MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+       MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+       MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+       MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+       MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+       MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+       MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+       MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+       MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+       MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+       MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+       MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+       MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+       MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+       MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+       MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+       MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+       MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+       MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+       MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+       MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+       MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+       MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+       MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+       MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+       MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+       MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+       MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+       MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+       MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+       MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+       MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+       hash[0] += a;
+       hash[1] += b;
+       hash[2] += c;
+       hash[3] += d;
+}
+EXPORT_SYMBOL(md5_transform);
index 7ea2e03..a2f9da5 100644 (file)
@@ -823,8 +823,8 @@ unsigned long radix_tree_prev_hole(struct radix_tree_root *root,
 EXPORT_SYMBOL(radix_tree_prev_hole);
 
 static unsigned int
-__lookup(struct radix_tree_node *slot, void ***results, unsigned long index,
-       unsigned int max_items, unsigned long *next_index)
+__lookup(struct radix_tree_node *slot, void ***results, unsigned long *indices,
+       unsigned long index, unsigned int max_items, unsigned long *next_index)
 {
        unsigned int nr_found = 0;
        unsigned int shift, height;
@@ -857,12 +857,16 @@ __lookup(struct radix_tree_node *slot, void ***results, unsigned long index,
 
        /* Bottom level: grab some items */
        for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) {
-               index++;
                if (slot->slots[i]) {
-                       results[nr_found++] = &(slot->slots[i]);
-                       if (nr_found == max_items)
+                       results[nr_found] = &(slot->slots[i]);
+                       if (indices)
+                               indices[nr_found] = index;
+                       if (++nr_found == max_items) {
+                               index++;
                                goto out;
+                       }
                }
+               index++;
        }
 out:
        *next_index = index;
@@ -918,8 +922,8 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
 
                if (cur_index > max_index)
                        break;
-               slots_found = __lookup(node, (void ***)results + ret, cur_index,
-                                       max_items - ret, &next_index);
+               slots_found = __lookup(node, (void ***)results + ret, NULL,
+                               cur_index, max_items - ret, &next_index);
                nr_found = 0;
                for (i = 0; i < slots_found; i++) {
                        struct radix_tree_node *slot;
@@ -944,6 +948,7 @@ EXPORT_SYMBOL(radix_tree_gang_lookup);
  *     radix_tree_gang_lookup_slot - perform multiple slot lookup on radix tree
  *     @root:          radix tree root
  *     @results:       where the results of the lookup are placed
+ *     @indices:       where their indices should be placed (but usually NULL)
  *     @first_index:   start the lookup from this key
  *     @max_items:     place up to this many items at *results
  *
@@ -958,7 +963,8 @@ EXPORT_SYMBOL(radix_tree_gang_lookup);
  *     protection, radix_tree_deref_slot may fail requiring a retry.
  */
 unsigned int
-radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
+radix_tree_gang_lookup_slot(struct radix_tree_root *root,
+                       void ***results, unsigned long *indices,
                        unsigned long first_index, unsigned int max_items)
 {
        unsigned long max_index;
@@ -974,6 +980,8 @@ radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
                if (first_index > 0)
                        return 0;
                results[0] = (void **)&root->rnode;
+               if (indices)
+                       indices[0] = 0;
                return 1;
        }
        node = indirect_to_ptr(node);
@@ -987,8 +995,9 @@ radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
 
                if (cur_index > max_index)
                        break;
-               slots_found = __lookup(node, results + ret, cur_index,
-                                       max_items - ret, &next_index);
+               slots_found = __lookup(node, results + ret,
+                               indices ? indices + ret : NULL,
+                               cur_index, max_items - ret, &next_index);
                ret += slots_found;
                if (next_index == 0)
                        break;
@@ -1194,6 +1203,98 @@ radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results,
 }
 EXPORT_SYMBOL(radix_tree_gang_lookup_tag_slot);
 
+#if defined(CONFIG_SHMEM) && defined(CONFIG_SWAP)
+#include <linux/sched.h> /* for cond_resched() */
+
+/*
+ * This linear search is at present only useful to shmem_unuse_inode().
+ */
+static unsigned long __locate(struct radix_tree_node *slot, void *item,
+                             unsigned long index, unsigned long *found_index)
+{
+       unsigned int shift, height;
+       unsigned long i;
+
+       height = slot->height;
+       shift = (height-1) * RADIX_TREE_MAP_SHIFT;
+
+       for ( ; height > 1; height--) {
+               i = (index >> shift) & RADIX_TREE_MAP_MASK;
+               for (;;) {
+                       if (slot->slots[i] != NULL)
+                               break;
+                       index &= ~((1UL << shift) - 1);
+                       index += 1UL << shift;
+                       if (index == 0)
+                               goto out;       /* 32-bit wraparound */
+                       i++;
+                       if (i == RADIX_TREE_MAP_SIZE)
+                               goto out;
+               }
+
+               shift -= RADIX_TREE_MAP_SHIFT;
+               slot = rcu_dereference_raw(slot->slots[i]);
+               if (slot == NULL)
+                       goto out;
+       }
+
+       /* Bottom level: check items */
+       for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) {
+               if (slot->slots[i] == item) {
+                       *found_index = index + i;
+                       index = 0;
+                       goto out;
+               }
+       }
+       index += RADIX_TREE_MAP_SIZE;
+out:
+       return index;
+}
+
+/**
+ *     radix_tree_locate_item - search through radix tree for item
+ *     @root:          radix tree root
+ *     @item:          item to be found
+ *
+ *     Returns index where item was found, or -1 if not found.
+ *     Caller must hold no lock (since this time-consuming function needs
+ *     to be preemptible), and must check afterwards if item is still there.
+ */
+unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item)
+{
+       struct radix_tree_node *node;
+       unsigned long max_index;
+       unsigned long cur_index = 0;
+       unsigned long found_index = -1;
+
+       do {
+               rcu_read_lock();
+               node = rcu_dereference_raw(root->rnode);
+               if (!radix_tree_is_indirect_ptr(node)) {
+                       rcu_read_unlock();
+                       if (node == item)
+                               found_index = 0;
+                       break;
+               }
+
+               node = indirect_to_ptr(node);
+               max_index = radix_tree_maxindex(node->height);
+               if (cur_index > max_index)
+                       break;
+
+               cur_index = __locate(node, item, cur_index, &found_index);
+               rcu_read_unlock();
+               cond_resched();
+       } while (cur_index != 0 && cur_index <= max_index);
+
+       return found_index;
+}
+#else
+unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item)
+{
+       return -1;
+}
+#endif /* CONFIG_SHMEM && CONFIG_SWAP */
 
 /**
  *     radix_tree_shrink    -    shrink height of a radix tree to minimal
index 4c45fd5..f33271d 100644 (file)
@@ -1,31 +1,72 @@
 /*
- * SHA transform algorithm, originally taken from code written by
- * Peter Gutmann, and placed in the public domain.
+ * SHA1 routine optimized to do word accesses rather than byte accesses,
+ * and to avoid unnecessary copies into the context array.
+ *
+ * This was based on the git SHA1 implementation.
  */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/cryptohash.h>
+#include <linux/bitops.h>
+#include <asm/unaligned.h>
 
-/* The SHA f()-functions.  */
+/*
+ * If you have 32 registers or more, the compiler can (and should)
+ * try to change the array[] accesses into registers. However, on
+ * machines with less than ~25 registers, that won't really work,
+ * and at least gcc will make an unholy mess of it.
+ *
+ * So to avoid that mess which just slows things down, we force
+ * the stores to memory to actually happen (we might be better off
+ * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as
+ * suggested by Artur Skawina - that will also make gcc unable to
+ * try to do the silly "optimize away loads" part because it won't
+ * see what the value will be).
+ *
+ * Ben Herrenschmidt reports that on PPC, the C version comes close
+ * to the optimized asm with this (ie on PPC you don't want that
+ * 'volatile', since there are lots of registers).
+ *
+ * On ARM we get the best code generation by forcing a full memory barrier
+ * between each SHA_ROUND, otherwise gcc happily get wild with spilling and
+ * the stack frame size simply explode and performance goes down the drain.
+ */
 
-#define f1(x,y,z)   (z ^ (x & (y ^ z)))                /* x ? y : z */
-#define f2(x,y,z)   (x ^ y ^ z)                        /* XOR */
-#define f3(x,y,z)   ((x & y) + (z & (x ^ y)))  /* majority */
+#ifdef CONFIG_X86
+  #define setW(x, val) (*(volatile __u32 *)&W(x) = (val))
+#elif defined(CONFIG_ARM)
+  #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0)
+#else
+  #define setW(x, val) (W(x) = (val))
+#endif
 
-/* The SHA Mysterious Constants */
+/* This "rolls" over the 512-bit array */
+#define W(x) (array[(x)&15])
 
-#define K1  0x5A827999L                        /* Rounds  0-19: sqrt(2) * 2^30 */
-#define K2  0x6ED9EBA1L                        /* Rounds 20-39: sqrt(3) * 2^30 */
-#define K3  0x8F1BBCDCL                        /* Rounds 40-59: sqrt(5) * 2^30 */
-#define K4  0xCA62C1D6L                        /* Rounds 60-79: sqrt(10) * 2^30 */
+/*
+ * Where do we get the source from? The first 16 iterations get it from
+ * the input data, the next mix it from the 512-bit array.
+ */
+#define SHA_SRC(t) get_unaligned_be32((__u32 *)data + t)
+#define SHA_MIX(t) rol32(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1)
+
+#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \
+       __u32 TEMP = input(t); setW(t, TEMP); \
+       E += TEMP + rol32(A,5) + (fn) + (constant); \
+       B = ror32(B, 2); } while (0)
+
+#define T_0_15(t, A, B, C, D, E)  SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
+#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
+#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E )
+#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E )
+#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) ,  0xca62c1d6, A, B, C, D, E )
 
 /**
  * sha_transform - single block SHA1 transform
  *
  * @digest: 160 bit digest to update
  * @data:   512 bits of data to hash
- * @W:      80 words of workspace (see note)
+ * @array:  16 words of workspace (see note)
  *
  * This function generates a SHA1 digest for a single 512-bit block.
  * Be warned, it does not handle padding and message digest, do not
  * to clear the workspace. This is left to the caller to avoid
  * unnecessary clears between chained hashing operations.
  */
-void sha_transform(__u32 *digest, const char *in, __u32 *W)
+void sha_transform(__u32 *digest, const char *data, __u32 *array)
 {
-       __u32 a, b, c, d, e, t, i;
-
-       for (i = 0; i < 16; i++)
-               W[i] = be32_to_cpu(((const __be32 *)in)[i]);
-
-       for (i = 0; i < 64; i++)
-               W[i+16] = rol32(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 1);
-
-       a = digest[0];
-       b = digest[1];
-       c = digest[2];
-       d = digest[3];
-       e = digest[4];
-
-       for (i = 0; i < 20; i++) {
-               t = f1(b, c, d) + K1 + rol32(a, 5) + e + W[i];
-               e = d; d = c; c = rol32(b, 30); b = a; a = t;
-       }
-
-       for (; i < 40; i ++) {
-               t = f2(b, c, d) + K2 + rol32(a, 5) + e + W[i];
-               e = d; d = c; c = rol32(b, 30); b = a; a = t;
-       }
-
-       for (; i < 60; i ++) {
-               t = f3(b, c, d) + K3 + rol32(a, 5) + e + W[i];
-               e = d; d = c; c = rol32(b, 30); b = a; a = t;
-       }
-
-       for (; i < 80; i ++) {
-               t = f2(b, c, d) + K4 + rol32(a, 5) + e + W[i];
-               e = d; d = c; c = rol32(b, 30); b = a; a = t;
-       }
-
-       digest[0] += a;
-       digest[1] += b;
-       digest[2] += c;
-       digest[3] += d;
-       digest[4] += e;
+       __u32 A, B, C, D, E;
+
+       A = digest[0];
+       B = digest[1];
+       C = digest[2];
+       D = digest[3];
+       E = digest[4];
+
+       /* Round 1 - iterations 0-16 take their input from 'data' */
+       T_0_15( 0, A, B, C, D, E);
+       T_0_15( 1, E, A, B, C, D);
+       T_0_15( 2, D, E, A, B, C);
+       T_0_15( 3, C, D, E, A, B);
+       T_0_15( 4, B, C, D, E, A);
+       T_0_15( 5, A, B, C, D, E);
+       T_0_15( 6, E, A, B, C, D);
+       T_0_15( 7, D, E, A, B, C);
+       T_0_15( 8, C, D, E, A, B);
+       T_0_15( 9, B, C, D, E, A);
+       T_0_15(10, A, B, C, D, E);
+       T_0_15(11, E, A, B, C, D);
+       T_0_15(12, D, E, A, B, C);
+       T_0_15(13, C, D, E, A, B);
+       T_0_15(14, B, C, D, E, A);
+       T_0_15(15, A, B, C, D, E);
+
+       /* Round 1 - tail. Input from 512-bit mixing array */
+       T_16_19(16, E, A, B, C, D);
+       T_16_19(17, D, E, A, B, C);
+       T_16_19(18, C, D, E, A, B);
+       T_16_19(19, B, C, D, E, A);
+
+       /* Round 2 */
+       T_20_39(20, A, B, C, D, E);
+       T_20_39(21, E, A, B, C, D);
+       T_20_39(22, D, E, A, B, C);
+       T_20_39(23, C, D, E, A, B);
+       T_20_39(24, B, C, D, E, A);
+       T_20_39(25, A, B, C, D, E);
+       T_20_39(26, E, A, B, C, D);
+       T_20_39(27, D, E, A, B, C);
+       T_20_39(28, C, D, E, A, B);
+       T_20_39(29, B, C, D, E, A);
+       T_20_39(30, A, B, C, D, E);
+       T_20_39(31, E, A, B, C, D);
+       T_20_39(32, D, E, A, B, C);
+       T_20_39(33, C, D, E, A, B);
+       T_20_39(34, B, C, D, E, A);
+       T_20_39(35, A, B, C, D, E);
+       T_20_39(36, E, A, B, C, D);
+       T_20_39(37, D, E, A, B, C);
+       T_20_39(38, C, D, E, A, B);
+       T_20_39(39, B, C, D, E, A);
+
+       /* Round 3 */
+       T_40_59(40, A, B, C, D, E);
+       T_40_59(41, E, A, B, C, D);
+       T_40_59(42, D, E, A, B, C);
+       T_40_59(43, C, D, E, A, B);
+       T_40_59(44, B, C, D, E, A);
+       T_40_59(45, A, B, C, D, E);
+       T_40_59(46, E, A, B, C, D);
+       T_40_59(47, D, E, A, B, C);
+       T_40_59(48, C, D, E, A, B);
+       T_40_59(49, B, C, D, E, A);
+       T_40_59(50, A, B, C, D, E);
+       T_40_59(51, E, A, B, C, D);
+       T_40_59(52, D, E, A, B, C);
+       T_40_59(53, C, D, E, A, B);
+       T_40_59(54, B, C, D, E, A);
+       T_40_59(55, A, B, C, D, E);
+       T_40_59(56, E, A, B, C, D);
+       T_40_59(57, D, E, A, B, C);
+       T_40_59(58, C, D, E, A, B);
+       T_40_59(59, B, C, D, E, A);
+
+       /* Round 4 */
+       T_60_79(60, A, B, C, D, E);
+       T_60_79(61, E, A, B, C, D);
+       T_60_79(62, D, E, A, B, C);
+       T_60_79(63, C, D, E, A, B);
+       T_60_79(64, B, C, D, E, A);
+       T_60_79(65, A, B, C, D, E);
+       T_60_79(66, E, A, B, C, D);
+       T_60_79(67, D, E, A, B, C);
+       T_60_79(68, C, D, E, A, B);
+       T_60_79(69, B, C, D, E, A);
+       T_60_79(70, A, B, C, D, E);
+       T_60_79(71, E, A, B, C, D);
+       T_60_79(72, D, E, A, B, C);
+       T_60_79(73, C, D, E, A, B);
+       T_60_79(74, B, C, D, E, A);
+       T_60_79(75, A, B, C, D, E);
+       T_60_79(76, E, A, B, C, D);
+       T_60_79(77, D, E, A, B, C);
+       T_60_79(78, C, D, E, A, B);
+       T_60_79(79, B, C, D, E, A);
+
+       digest[0] += A;
+       digest[1] += B;
+       digest[2] += C;
+       digest[3] += D;
+       digest[4] += E;
 }
 EXPORT_SYMBOL(sha_transform);
 
@@ -92,4 +197,3 @@ void sha_init(__u32 *buf)
        buf[3] = 0x10325476;
        buf[4] = 0xc3d2e1f0;
 }
-
index 1ce58c2..0dd7b8f 100644 (file)
@@ -34,23 +34,23 @@ __setup("failslab=", setup_failslab);
 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
 static int __init failslab_debugfs_init(void)
 {
+       struct dentry *dir;
        mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
-       int err;
 
-       err = init_fault_attr_dentries(&failslab.attr, "failslab");
-       if (err)
-               return err;
+       dir = fault_create_debugfs_attr("failslab", NULL, &failslab.attr);
+       if (IS_ERR(dir))
+               return PTR_ERR(dir);
 
-       if (!debugfs_create_bool("ignore-gfp-wait", mode, failslab.attr.dir,
+       if (!debugfs_create_bool("ignore-gfp-wait", mode, dir,
                                &failslab.ignore_gfp_wait))
                goto fail;
-       if (!debugfs_create_bool("cache-filter", mode, failslab.attr.dir,
+       if (!debugfs_create_bool("cache-filter", mode, dir,
                                &failslab.cache_filter))
                goto fail;
 
        return 0;
 fail:
-       cleanup_fault_attr_dentries(&failslab.attr);
+       debugfs_remove_recursive(dir);
 
        return -ENOMEM;
 }
index 867d402..645a080 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/cpuset.h>
 #include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */
 #include <linux/memcontrol.h>
-#include <linux/mm_inline.h> /* for page_is_file_cache() */
 #include <linux/cleancache.h>
 #include "internal.h"
 
@@ -462,6 +461,7 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
        int error;
 
        VM_BUG_ON(!PageLocked(page));
+       VM_BUG_ON(PageSwapBacked(page));
 
        error = mem_cgroup_cache_charge(page, current->mm,
                                        gfp_mask & GFP_RECLAIM_MASK);
@@ -479,8 +479,6 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
                if (likely(!error)) {
                        mapping->nrpages++;
                        __inc_zone_page_state(page, NR_FILE_PAGES);
-                       if (PageSwapBacked(page))
-                               __inc_zone_page_state(page, NR_SHMEM);
                        spin_unlock_irq(&mapping->tree_lock);
                } else {
                        page->mapping = NULL;
@@ -502,22 +500,9 @@ int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
 {
        int ret;
 
-       /*
-        * Splice_read and readahead add shmem/tmpfs pages into the page cache
-        * before shmem_readpage has a chance to mark them as SwapBacked: they
-        * need to go on the anon lru below, and mem_cgroup_cache_charge
-        * (called in add_to_page_cache) needs to know where they're going too.
-        */
-       if (mapping_cap_swap_backed(mapping))
-               SetPageSwapBacked(page);
-
        ret = add_to_page_cache(page, mapping, offset, gfp_mask);
-       if (ret == 0) {
-               if (page_is_file_cache(page))
-                       lru_cache_add_file(page);
-               else
-                       lru_cache_add_anon(page);
-       }
+       if (ret == 0)
+               lru_cache_add_file(page);
        return ret;
 }
 EXPORT_SYMBOL_GPL(add_to_page_cache_lru);
@@ -714,9 +699,16 @@ repeat:
                page = radix_tree_deref_slot(pagep);
                if (unlikely(!page))
                        goto out;
-               if (radix_tree_deref_retry(page))
-                       goto repeat;
-
+               if (radix_tree_exception(page)) {
+                       if (radix_tree_deref_retry(page))
+                               goto repeat;
+                       /*
+                        * Otherwise, shmem/tmpfs must be storing a swap entry
+                        * here as an exceptional entry: so return it without
+                        * attempting to raise page count.
+                        */
+                       goto out;
+               }
                if (!page_cache_get_speculative(page))
                        goto repeat;
 
@@ -753,7 +745,7 @@ struct page *find_lock_page(struct address_space *mapping, pgoff_t offset)
 
 repeat:
        page = find_get_page(mapping, offset);
-       if (page) {
+       if (page && !radix_tree_exception(page)) {
                lock_page(page);
                /* Has the page been truncated? */
                if (unlikely(page->mapping != mapping)) {
@@ -840,7 +832,7 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
        rcu_read_lock();
 restart:
        nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,
-                               (void ***)pages, start, nr_pages);
+                               (void ***)pages, NULL, start, nr_pages);
        ret = 0;
        for (i = 0; i < nr_found; i++) {
                struct page *page;
@@ -849,13 +841,22 @@ repeat:
                if (unlikely(!page))
                        continue;
 
-               /*
-                * This can only trigger when the entry at index 0 moves out
-                * of or back to the root: none yet gotten, safe to restart.
-                */
-               if (radix_tree_deref_retry(page)) {
-                       WARN_ON(start | i);
-                       goto restart;
+               if (radix_tree_exception(page)) {
+                       if (radix_tree_deref_retry(page)) {
+                               /*
+                                * Transient condition which can only trigger
+                                * when entry at index 0 moves out of or back
+                                * to root: none yet gotten, safe to restart.
+                                */
+                               WARN_ON(start | i);
+                               goto restart;
+                       }
+                       /*
+                        * Otherwise, shmem/tmpfs must be storing a swap entry
+                        * here as an exceptional entry: so skip over it -
+                        * we only reach this from invalidate_mapping_pages().
+                        */
+                       continue;
                }
 
                if (!page_cache_get_speculative(page))
@@ -903,7 +904,7 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index,
        rcu_read_lock();
 restart:
        nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,
-                               (void ***)pages, index, nr_pages);
+                               (void ***)pages, NULL, index, nr_pages);
        ret = 0;
        for (i = 0; i < nr_found; i++) {
                struct page *page;
@@ -912,12 +913,22 @@ repeat:
                if (unlikely(!page))
                        continue;
 
-               /*
-                * This can only trigger when the entry at index 0 moves out
-                * of or back to the root: none yet gotten, safe to restart.
-                */
-               if (radix_tree_deref_retry(page))
-                       goto restart;
+               if (radix_tree_exception(page)) {
+                       if (radix_tree_deref_retry(page)) {
+                               /*
+                                * Transient condition which can only trigger
+                                * when entry at index 0 moves out of or back
+                                * to root: none yet gotten, safe to restart.
+                                */
+                               goto restart;
+                       }
+                       /*
+                        * Otherwise, shmem/tmpfs must be storing a swap entry
+                        * here as an exceptional entry: so stop looking for
+                        * contiguous pages.
+                        */
+                       break;
+               }
 
                if (!page_cache_get_speculative(page))
                        goto repeat;
@@ -977,12 +988,21 @@ repeat:
                if (unlikely(!page))
                        continue;
 
-               /*
-                * This can only trigger when the entry at index 0 moves out
-                * of or back to the root: none yet gotten, safe to restart.
-                */
-               if (radix_tree_deref_retry(page))
-                       goto restart;
+               if (radix_tree_exception(page)) {
+                       if (radix_tree_deref_retry(page)) {
+                               /*
+                                * Transient condition which can only trigger
+                                * when entry at index 0 moves out of or back
+                                * to root: none yet gotten, safe to restart.
+                                */
+                               goto restart;
+                       }
+                       /*
+                        * This function is never used on a shmem/tmpfs
+                        * mapping, so a swap entry won't be found here.
+                        */
+                       BUG();
+               }
 
                if (!page_cache_get_speculative(page))
                        goto repeat;
index 5f84d23..930de94 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/limits.h>
 #include <linux/mutex.h>
 #include <linux/rbtree.h>
-#include <linux/shmem_fs.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
@@ -2092,6 +2091,7 @@ struct memcg_stock_pcp {
 #define FLUSHING_CACHED_CHARGE (0)
 };
 static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock);
+static DEFINE_MUTEX(percpu_charge_mutex);
 
 /*
  * Try to consume stocked charge on this cpu. If success, one page is consumed
@@ -2198,8 +2198,7 @@ static void drain_all_stock(struct mem_cgroup *root_mem, bool sync)
 
        for_each_online_cpu(cpu) {
                struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
-               if (mem_cgroup_same_or_subtree(root_mem, stock->cached) &&
-                               test_bit(FLUSHING_CACHED_CHARGE, &stock->flags))
+               if (test_bit(FLUSHING_CACHED_CHARGE, &stock->flags))
                        flush_work(&stock->work);
        }
 out:
@@ -2214,14 +2213,22 @@ out:
  */
 static void drain_all_stock_async(struct mem_cgroup *root_mem)
 {
+       /*
+        * If someone calls draining, avoid adding more kworker runs.
+        */
+       if (!mutex_trylock(&percpu_charge_mutex))
+               return;
        drain_all_stock(root_mem, false);
+       mutex_unlock(&percpu_charge_mutex);
 }
 
 /* This is a synchronous drain interface. */
 static void drain_all_stock_sync(struct mem_cgroup *root_mem)
 {
        /* called when force_empty is called */
+       mutex_lock(&percpu_charge_mutex);
        drain_all_stock(root_mem, true);
+       mutex_unlock(&percpu_charge_mutex);
 }
 
 /*
@@ -2873,30 +2880,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
                return 0;
        if (PageCompound(page))
                return 0;
-       /*
-        * Corner case handling. This is called from add_to_page_cache()
-        * in usual. But some FS (shmem) precharges this page before calling it
-        * and call add_to_page_cache() with GFP_NOWAIT.
-        *
-        * For GFP_NOWAIT case, the page may be pre-charged before calling
-        * add_to_page_cache(). (See shmem.c) check it here and avoid to call
-        * charge twice. (It works but has to pay a bit larger cost.)
-        * And when the page is SwapCache, it should take swap information
-        * into account. This is under lock_page() now.
-        */
-       if (!(gfp_mask & __GFP_WAIT)) {
-               struct page_cgroup *pc;
-
-               pc = lookup_page_cgroup(page);
-               if (!pc)
-                       return 0;
-               lock_page_cgroup(pc);
-               if (PageCgroupUsed(pc)) {
-                       unlock_page_cgroup(pc);
-                       return 0;
-               }
-               unlock_page_cgroup(pc);
-       }
 
        if (unlikely(!mm))
                mm = &init_mm;
@@ -3486,31 +3469,6 @@ void mem_cgroup_end_migration(struct mem_cgroup *mem,
        cgroup_release_and_wakeup_rmdir(&mem->css);
 }
 
-/*
- * A call to try to shrink memory usage on charge failure at shmem's swapin.
- * Calling hierarchical_reclaim is not enough because we should update
- * last_oom_jiffies to prevent pagefault_out_of_memory from invoking global OOM.
- * Moreover considering hierarchy, we should reclaim from the mem_over_limit,
- * not from the memcg which this page would be charged to.
- * try_charge_swapin does all of these works properly.
- */
-int mem_cgroup_shmem_charge_fallback(struct page *page,
-                           struct mm_struct *mm,
-                           gfp_t gfp_mask)
-{
-       struct mem_cgroup *mem;
-       int ret;
-
-       if (mem_cgroup_disabled())
-               return 0;
-
-       ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &mem);
-       if (!ret)
-               mem_cgroup_cancel_charge_swapin(mem); /* it does !mem check */
-
-       return ret;
-}
-
 #ifdef CONFIG_DEBUG_VM
 static struct page_cgroup *lookup_page_cgroup_used(struct page *page)
 {
@@ -5330,15 +5288,17 @@ static struct page *mc_handle_file_pte(struct vm_area_struct *vma,
                pgoff = pte_to_pgoff(ptent);
 
        /* page is moved even if it's not RSS of this task(page-faulted). */
-       if (!mapping_cap_swap_backed(mapping)) { /* normal file */
-               page = find_get_page(mapping, pgoff);
-       } else { /* shmem/tmpfs file. we should take account of swap too. */
-               swp_entry_t ent;
-               mem_cgroup_get_shmem_target(inode, pgoff, &page, &ent);
+       page = find_get_page(mapping, pgoff);
+
+#ifdef CONFIG_SWAP
+       /* shmem/tmpfs may report page out on swap: account for that too. */
+       if (radix_tree_exceptional_entry(page)) {
+               swp_entry_t swap = radix_to_swp_entry(page);
                if (do_swap_account)
-                       entry->val = ent.val;
+                       *entry = swap;
+               page = find_get_page(&swapper_space, swap.val);
        }
-
+#endif
        return page;
 }
 
index 740c4f5..2b43ba0 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/hugetlb.h>
 #include <linux/memory_hotplug.h>
 #include <linux/mm_inline.h>
+#include <linux/kfifo.h>
 #include "internal.h"
 
 int sysctl_memory_failure_early_kill __read_mostly = 0;
@@ -1178,6 +1179,97 @@ void memory_failure(unsigned long pfn, int trapno)
        __memory_failure(pfn, trapno, 0);
 }
 
+#define MEMORY_FAILURE_FIFO_ORDER      4
+#define MEMORY_FAILURE_FIFO_SIZE       (1 << MEMORY_FAILURE_FIFO_ORDER)
+
+struct memory_failure_entry {
+       unsigned long pfn;
+       int trapno;
+       int flags;
+};
+
+struct memory_failure_cpu {
+       DECLARE_KFIFO(fifo, struct memory_failure_entry,
+                     MEMORY_FAILURE_FIFO_SIZE);
+       spinlock_t lock;
+       struct work_struct work;
+};
+
+static DEFINE_PER_CPU(struct memory_failure_cpu, memory_failure_cpu);
+
+/**
+ * memory_failure_queue - Schedule handling memory failure of a page.
+ * @pfn: Page Number of the corrupted page
+ * @trapno: Trap number reported in the signal to user space.
+ * @flags: Flags for memory failure handling
+ *
+ * This function is called by the low level hardware error handler
+ * when it detects hardware memory corruption of a page. It schedules
+ * the recovering of error page, including dropping pages, killing
+ * processes etc.
+ *
+ * The function is primarily of use for corruptions that
+ * happen outside the current execution context (e.g. when
+ * detected by a background scrubber)
+ *
+ * Can run in IRQ context.
+ */
+void memory_failure_queue(unsigned long pfn, int trapno, int flags)
+{
+       struct memory_failure_cpu *mf_cpu;
+       unsigned long proc_flags;
+       struct memory_failure_entry entry = {
+               .pfn =          pfn,
+               .trapno =       trapno,
+               .flags =        flags,
+       };
+
+       mf_cpu = &get_cpu_var(memory_failure_cpu);
+       spin_lock_irqsave(&mf_cpu->lock, proc_flags);
+       if (kfifo_put(&mf_cpu->fifo, &entry))
+               schedule_work_on(smp_processor_id(), &mf_cpu->work);
+       else
+               pr_err("Memory failure: buffer overflow when queuing memory failure at 0x%#lx\n",
+                      pfn);
+       spin_unlock_irqrestore(&mf_cpu->lock, proc_flags);
+       put_cpu_var(memory_failure_cpu);
+}
+EXPORT_SYMBOL_GPL(memory_failure_queue);
+
+static void memory_failure_work_func(struct work_struct *work)
+{
+       struct memory_failure_cpu *mf_cpu;
+       struct memory_failure_entry entry = { 0, };
+       unsigned long proc_flags;
+       int gotten;
+
+       mf_cpu = &__get_cpu_var(memory_failure_cpu);
+       for (;;) {
+               spin_lock_irqsave(&mf_cpu->lock, proc_flags);
+               gotten = kfifo_get(&mf_cpu->fifo, &entry);
+               spin_unlock_irqrestore(&mf_cpu->lock, proc_flags);
+               if (!gotten)
+                       break;
+               __memory_failure(entry.pfn, entry.trapno, entry.flags);
+       }
+}
+
+static int __init memory_failure_init(void)
+{
+       struct memory_failure_cpu *mf_cpu;
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               mf_cpu = &per_cpu(memory_failure_cpu, cpu);
+               spin_lock_init(&mf_cpu->lock);
+               INIT_KFIFO(mf_cpu->fifo);
+               INIT_WORK(&mf_cpu->work, memory_failure_work_func);
+       }
+
+       return 0;
+}
+core_initcall(memory_failure_init);
+
 /**
  * unpoison_memory - Unpoison a previously poisoned page
  * @pfn: Page number of the to be unpoisoned page
index a4e6b9d..636a868 100644 (file)
@@ -69,12 +69,15 @@ static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff)
         * file will not get a swp_entry_t in its pte, but rather it is like
         * any other file mapping (ie. marked !present and faulted in with
         * tmpfs's .fault). So swapped out tmpfs mappings are tested here.
-        *
-        * However when tmpfs moves the page from pagecache and into swapcache,
-        * it is still in core, but the find_get_page below won't find it.
-        * No big deal, but make a note of it.
         */
        page = find_get_page(mapping, pgoff);
+#ifdef CONFIG_SWAP
+       /* shmem/tmpfs may return swap: account for swapcache page too. */
+       if (radix_tree_exceptional_entry(page)) {
+               swp_entry_t swap = radix_to_swp_entry(page);
+               page = find_get_page(&swapper_space, swap.val);
+       }
+#endif
        if (page) {
                present = PageUptodate(page);
                page_cache_release(page);
index eafff89..626303b 100644 (file)
@@ -303,7 +303,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
        do_each_thread(g, p) {
                unsigned int points;
 
-               if (!p->mm)
+               if (p->exit_state)
                        continue;
                if (oom_unkillable_task(p, mem, nodemask))
                        continue;
@@ -319,6 +319,8 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
                 */
                if (test_tsk_thread_flag(p, TIF_MEMDIE))
                        return ERR_PTR(-1UL);
+               if (!p->mm)
+                       continue;
 
                if (p->flags & PF_EXITING) {
                        /*
index 1dbcf88..6e8ecb6 100644 (file)
@@ -1409,14 +1409,11 @@ static int __init fail_page_alloc_debugfs(void)
 {
        mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
        struct dentry *dir;
-       int err;
 
-       err = init_fault_attr_dentries(&fail_page_alloc.attr,
-                                      "fail_page_alloc");
-       if (err)
-               return err;
-
-       dir = fail_page_alloc.attr.dir;
+       dir = fault_create_debugfs_attr("fail_page_alloc", NULL,
+                                       &fail_page_alloc.attr);
+       if (IS_ERR(dir))
+               return PTR_ERR(dir);
 
        if (!debugfs_create_bool("ignore-gfp-wait", mode, dir,
                                &fail_page_alloc.ignore_gfp_wait))
@@ -1430,7 +1427,7 @@ static int __init fail_page_alloc_debugfs(void)
 
        return 0;
 fail:
-       cleanup_fault_attr_dentries(&fail_page_alloc.attr);
+       debugfs_remove_recursive(dir);
 
        return -ENOMEM;
 }
index 5cc21f8..32f6763 100644 (file)
@@ -6,7 +6,8 @@
  *              2000-2001 Christoph Rohland
  *              2000-2001 SAP AG
  *              2002 Red Hat Inc.
- * Copyright (C) 2002-2005 Hugh Dickins.
+ * Copyright (C) 2002-2011 Hugh Dickins.
+ * Copyright (C) 2011 Google Inc.
  * Copyright (C) 2002-2005 VERITAS Software Corporation.
  * Copyright (C) 2004 Andi Kleen, SuSE Labs
  *
@@ -28,7 +29,6 @@
 #include <linux/file.h>
 #include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/percpu_counter.h>
 #include <linux/swap.h>
 
 static struct vfsmount *shm_mnt;
@@ -51,6 +51,8 @@ static struct vfsmount *shm_mnt;
 #include <linux/shmem_fs.h>
 #include <linux/writeback.h>
 #include <linux/blkdev.h>
+#include <linux/pagevec.h>
+#include <linux/percpu_counter.h>
 #include <linux/splice.h>
 #include <linux/security.h>
 #include <linux/swapops.h>
@@ -63,43 +65,17 @@ static struct vfsmount *shm_mnt;
 #include <linux/magic.h>
 
 #include <asm/uaccess.h>
-#include <asm/div64.h>
 #include <asm/pgtable.h>
 
-/*
- * The maximum size of a shmem/tmpfs file is limited by the maximum size of
- * its triple-indirect swap vector - see illustration at shmem_swp_entry().
- *
- * With 4kB page size, maximum file size is just over 2TB on a 32-bit kernel,
- * but one eighth of that on a 64-bit kernel.  With 8kB page size, maximum
- * file size is just over 4TB on a 64-bit kernel, but 16TB on a 32-bit kernel,
- * MAX_LFS_FILESIZE being then more restrictive than swap vector layout.
- *
- * We use / and * instead of shifts in the definitions below, so that the swap
- * vector can be tested with small even values (e.g. 20) for ENTRIES_PER_PAGE.
- */
-#define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))
-#define ENTRIES_PER_PAGEPAGE ((unsigned long long)ENTRIES_PER_PAGE*ENTRIES_PER_PAGE)
-
-#define SHMSWP_MAX_INDEX (SHMEM_NR_DIRECT + (ENTRIES_PER_PAGEPAGE/2) * (ENTRIES_PER_PAGE+1))
-#define SHMSWP_MAX_BYTES (SHMSWP_MAX_INDEX << PAGE_CACHE_SHIFT)
-
-#define SHMEM_MAX_BYTES  min_t(unsigned long long, SHMSWP_MAX_BYTES, MAX_LFS_FILESIZE)
-#define SHMEM_MAX_INDEX  ((unsigned long)((SHMEM_MAX_BYTES+1) >> PAGE_CACHE_SHIFT))
-
 #define BLOCKS_PER_PAGE  (PAGE_CACHE_SIZE/512)
 #define VM_ACCT(size)    (PAGE_CACHE_ALIGN(size) >> PAGE_SHIFT)
 
-/* info->flags needs VM_flags to handle pagein/truncate races efficiently */
-#define SHMEM_PAGEIN    VM_READ
-#define SHMEM_TRUNCATE  VM_WRITE
-
-/* Definition to limit shmem_truncate's steps between cond_rescheds */
-#define LATENCY_LIMIT   64
-
 /* Pretend that each entry is of this size in directory's i_size */
 #define BOGO_DIRENT_SIZE 20
 
+/* Symlink up to this size is kmalloc'ed instead of using a swappable page */
+#define SHORT_SYMLINK_LEN 128
+
 struct shmem_xattr {
        struct list_head list;  /* anchored by shmem_inode_info->xattr_list */
        char *name;             /* xattr name */
@@ -107,7 +83,7 @@ struct shmem_xattr {
        char value[0];
 };
 
-/* Flag allocation requirements to shmem_getpage and shmem_swp_alloc */
+/* Flag allocation requirements to shmem_getpage */
 enum sgp_type {
        SGP_READ,       /* don't exceed i_size, don't allocate page */
        SGP_CACHE,      /* don't exceed i_size, may allocate page */
@@ -137,56 +113,6 @@ static inline int shmem_getpage(struct inode *inode, pgoff_t index,
                        mapping_gfp_mask(inode->i_mapping), fault_type);
 }
 
-static inline struct page *shmem_dir_alloc(gfp_t gfp_mask)
-{
-       /*
-        * The above definition of ENTRIES_PER_PAGE, and the use of
-        * BLOCKS_PER_PAGE on indirect pages, assume PAGE_CACHE_SIZE:
-        * might be reconsidered if it ever diverges from PAGE_SIZE.
-        *
-        * Mobility flags are masked out as swap vectors cannot move
-        */
-       return alloc_pages((gfp_mask & ~GFP_MOVABLE_MASK) | __GFP_ZERO,
-                               PAGE_CACHE_SHIFT-PAGE_SHIFT);
-}
-
-static inline void shmem_dir_free(struct page *page)
-{
-       __free_pages(page, PAGE_CACHE_SHIFT-PAGE_SHIFT);
-}
-
-static struct page **shmem_dir_map(struct page *page)
-{
-       return (struct page **)kmap_atomic(page, KM_USER0);
-}
-
-static inline void shmem_dir_unmap(struct page **dir)
-{
-       kunmap_atomic(dir, KM_USER0);
-}
-
-static swp_entry_t *shmem_swp_map(struct page *page)
-{
-       return (swp_entry_t *)kmap_atomic(page, KM_USER1);
-}
-
-static inline void shmem_swp_balance_unmap(void)
-{
-       /*
-        * When passing a pointer to an i_direct entry, to code which
-        * also handles indirect entries and so will shmem_swp_unmap,
-        * we must arrange for the preempt count to remain in balance.
-        * What kmap_atomic of a lowmem page does depends on config
-        * and architecture, so pretend to kmap_atomic some lowmem page.
-        */
-       (void) kmap_atomic(ZERO_PAGE(0), KM_USER1);
-}
-
-static inline void shmem_swp_unmap(swp_entry_t *entry)
-{
-       kunmap_atomic(entry, KM_USER1);
-}
-
 static inline struct shmem_sb_info *SHMEM_SB(struct super_block *sb)
 {
        return sb->s_fs_info;
@@ -244,15 +170,6 @@ static struct backing_dev_info shmem_backing_dev_info  __read_mostly = {
 static LIST_HEAD(shmem_swaplist);
 static DEFINE_MUTEX(shmem_swaplist_mutex);
 
-static void shmem_free_blocks(struct inode *inode, long pages)
-{
-       struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
-       if (sbinfo->max_blocks) {
-               percpu_counter_add(&sbinfo->used_blocks, -pages);
-               inode->i_blocks -= pages*BLOCKS_PER_PAGE;
-       }
-}
-
 static int shmem_reserve_inode(struct super_block *sb)
 {
        struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
@@ -279,7 +196,7 @@ static void shmem_free_inode(struct super_block *sb)
 }
 
 /**
- * shmem_recalc_inode - recalculate the size of an inode
+ * shmem_recalc_inode - recalculate the block usage of an inode
  * @inode: inode to recalc
  *
  * We have to calculate the free blocks since the mm can drop
@@ -297,474 +214,297 @@ static void shmem_recalc_inode(struct inode *inode)
 
        freed = info->alloced - info->swapped - inode->i_mapping->nrpages;
        if (freed > 0) {
+               struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
+               if (sbinfo->max_blocks)
+                       percpu_counter_add(&sbinfo->used_blocks, -freed);
                info->alloced -= freed;
+               inode->i_blocks -= freed * BLOCKS_PER_PAGE;
                shmem_unacct_blocks(info->flags, freed);
-               shmem_free_blocks(inode, freed);
        }
 }
 
-/**
- * shmem_swp_entry - find the swap vector position in the info structure
- * @info:  info structure for the inode
- * @index: index of the page to find
- * @page:  optional page to add to the structure. Has to be preset to
- *         all zeros
- *
- * If there is no space allocated yet it will return NULL when
- * page is NULL, else it will use the page for the needed block,
- * setting it to NULL on return to indicate that it has been used.
- *
- * The swap vector is organized the following way:
- *
- * There are SHMEM_NR_DIRECT entries directly stored in the
- * shmem_inode_info structure. So small files do not need an addional
- * allocation.
- *
- * For pages with index > SHMEM_NR_DIRECT there is the pointer
- * i_indirect which points to a page which holds in the first half
- * doubly indirect blocks, in the second half triple indirect blocks:
- *
- * For an artificial ENTRIES_PER_PAGE = 4 this would lead to the
- * following layout (for SHMEM_NR_DIRECT == 16):
- *
- * i_indirect -> dir --> 16-19
- *           |      +-> 20-23
- *           |
- *           +-->dir2 --> 24-27
- *           |        +-> 28-31
- *           |        +-> 32-35
- *           |        +-> 36-39
- *           |
- *           +-->dir3 --> 40-43
- *                    +-> 44-47
- *                    +-> 48-51
- *                    +-> 52-55
+/*
+ * Replace item expected in radix tree by a new item, while holding tree lock.
  */
-static swp_entry_t *shmem_swp_entry(struct shmem_inode_info *info, unsigned long index, struct page **page)
-{
-       unsigned long offset;
-       struct page **dir;
-       struct page *subdir;
-
-       if (index < SHMEM_NR_DIRECT) {
-               shmem_swp_balance_unmap();
-               return info->i_direct+index;
-       }
-       if (!info->i_indirect) {
-               if (page) {
-                       info->i_indirect = *page;
-                       *page = NULL;
-               }
-               return NULL;                    /* need another page */
-       }
-
-       index -= SHMEM_NR_DIRECT;
-       offset = index % ENTRIES_PER_PAGE;
-       index /= ENTRIES_PER_PAGE;
-       dir = shmem_dir_map(info->i_indirect);
-
-       if (index >= ENTRIES_PER_PAGE/2) {
-               index -= ENTRIES_PER_PAGE/2;
-               dir += ENTRIES_PER_PAGE/2 + index/ENTRIES_PER_PAGE;
-               index %= ENTRIES_PER_PAGE;
-               subdir = *dir;
-               if (!subdir) {
-                       if (page) {
-                               *dir = *page;
-                               *page = NULL;
-                       }
-                       shmem_dir_unmap(dir);
-                       return NULL;            /* need another page */
-               }
-               shmem_dir_unmap(dir);
-               dir = shmem_dir_map(subdir);
-       }
+static int shmem_radix_tree_replace(struct address_space *mapping,
+                       pgoff_t index, void *expected, void *replacement)
+{
+       void **pslot;
+       void *item = NULL;
+
+       VM_BUG_ON(!expected);
+       pslot = radix_tree_lookup_slot(&mapping->page_tree, index);
+       if (pslot)
+               item = radix_tree_deref_slot_protected(pslot,
+                                                       &mapping->tree_lock);
+       if (item != expected)
+               return -ENOENT;
+       if (replacement)
+               radix_tree_replace_slot(pslot, replacement);
+       else
+               radix_tree_delete(&mapping->page_tree, index);
+       return 0;
+}
 
-       dir += index;
-       subdir = *dir;
-       if (!subdir) {
-               if (!page || !(subdir = *page)) {
-                       shmem_dir_unmap(dir);
-                       return NULL;            /* need a page */
+/*
+ * Like add_to_page_cache_locked, but error if expected item has gone.
+ */
+static int shmem_add_to_page_cache(struct page *page,
+                                  struct address_space *mapping,
+                                  pgoff_t index, gfp_t gfp, void *expected)
+{
+       int error = 0;
+
+       VM_BUG_ON(!PageLocked(page));
+       VM_BUG_ON(!PageSwapBacked(page));
+
+       if (!expected)
+               error = radix_tree_preload(gfp & GFP_RECLAIM_MASK);
+       if (!error) {
+               page_cache_get(page);
+               page->mapping = mapping;
+               page->index = index;
+
+               spin_lock_irq(&mapping->tree_lock);
+               if (!expected)
+                       error = radix_tree_insert(&mapping->page_tree,
+                                                       index, page);
+               else
+                       error = shmem_radix_tree_replace(mapping, index,
+                                                       expected, page);
+               if (!error) {
+                       mapping->nrpages++;
+                       __inc_zone_page_state(page, NR_FILE_PAGES);
+                       __inc_zone_page_state(page, NR_SHMEM);
+                       spin_unlock_irq(&mapping->tree_lock);
+               } else {
+                       page->mapping = NULL;
+                       spin_unlock_irq(&mapping->tree_lock);
+                       page_cache_release(page);
                }
-               *dir = subdir;
-               *page = NULL;
+               if (!expected)
+                       radix_tree_preload_end();
        }
-       shmem_dir_unmap(dir);
-       return shmem_swp_map(subdir) + offset;
+       if (error)
+               mem_cgroup_uncharge_cache_page(page);
+       return error;
 }
 
-static void shmem_swp_set(struct shmem_inode_info *info, swp_entry_t *entry, unsigned long value)
+/*
+ * Like delete_from_page_cache, but substitutes swap for page.
+ */
+static void shmem_delete_from_page_cache(struct page *page, void *radswap)
 {
-       long incdec = value? 1: -1;
+       struct address_space *mapping = page->mapping;
+       int error;
 
-       entry->val = value;
-       info->swapped += incdec;
-       if ((unsigned long)(entry - info->i_direct) >= SHMEM_NR_DIRECT) {
-               struct page *page = kmap_atomic_to_page(entry);
-               set_page_private(page, page_private(page) + incdec);
-       }
+       spin_lock_irq(&mapping->tree_lock);
+       error = shmem_radix_tree_replace(mapping, page->index, page, radswap);
+       page->mapping = NULL;
+       mapping->nrpages--;
+       __dec_zone_page_state(page, NR_FILE_PAGES);
+       __dec_zone_page_state(page, NR_SHMEM);
+       spin_unlock_irq(&mapping->tree_lock);
+       page_cache_release(page);
+       BUG_ON(error);
 }
 
-/**
- * shmem_swp_alloc - get the position of the swap entry for the page.
- * @info:      info structure for the inode
- * @index:     index of the page to find
- * @sgp:       check and recheck i_size? skip allocation?
- * @gfp:       gfp mask to use for any page allocation
- *
- * If the entry does not exist, allocate it.
+/*
+ * Like find_get_pages, but collecting swap entries as well as pages.
  */
-static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info,
-                       unsigned long index, enum sgp_type sgp, gfp_t gfp)
-{
-       struct inode *inode = &info->vfs_inode;
-       struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
-       struct page *page = NULL;
-       swp_entry_t *entry;
-
-       if (sgp != SGP_WRITE &&
-           ((loff_t) index << PAGE_CACHE_SHIFT) >= i_size_read(inode))
-               return ERR_PTR(-EINVAL);
-
-       while (!(entry = shmem_swp_entry(info, index, &page))) {
-               if (sgp == SGP_READ)
-                       return shmem_swp_map(ZERO_PAGE(0));
-               /*
-                * Test used_blocks against 1 less max_blocks, since we have 1 data
-                * page (and perhaps indirect index pages) yet to allocate:
-                * a waste to allocate index if we cannot allocate data.
-                */
-               if (sbinfo->max_blocks) {
-                       if (percpu_counter_compare(&sbinfo->used_blocks,
-                                               sbinfo->max_blocks - 1) >= 0)
-                               return ERR_PTR(-ENOSPC);
-                       percpu_counter_inc(&sbinfo->used_blocks);
-                       inode->i_blocks += BLOCKS_PER_PAGE;
+static unsigned shmem_find_get_pages_and_swap(struct address_space *mapping,
+                                       pgoff_t start, unsigned int nr_pages,
+                                       struct page **pages, pgoff_t *indices)
+{
+       unsigned int i;
+       unsigned int ret;
+       unsigned int nr_found;
+
+       rcu_read_lock();
+restart:
+       nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,
+                               (void ***)pages, indices, start, nr_pages);
+       ret = 0;
+       for (i = 0; i < nr_found; i++) {
+               struct page *page;
+repeat:
+               page = radix_tree_deref_slot((void **)pages[i]);
+               if (unlikely(!page))
+                       continue;
+               if (radix_tree_exception(page)) {
+                       if (radix_tree_deref_retry(page))
+                               goto restart;
+                       /*
+                        * Otherwise, we must be storing a swap entry
+                        * here as an exceptional entry: so return it
+                        * without attempting to raise page count.
+                        */
+                       goto export;
                }
+               if (!page_cache_get_speculative(page))
+                       goto repeat;
 
-               spin_unlock(&info->lock);
-               page = shmem_dir_alloc(gfp);
-               spin_lock(&info->lock);
-
-               if (!page) {
-                       shmem_free_blocks(inode, 1);
-                       return ERR_PTR(-ENOMEM);
-               }
-               if (sgp != SGP_WRITE &&
-                   ((loff_t) index << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
-                       entry = ERR_PTR(-EINVAL);
-                       break;
+               /* Has the page moved? */
+               if (unlikely(page != *((void **)pages[i]))) {
+                       page_cache_release(page);
+                       goto repeat;
                }
-               if (info->next_index <= index)
-                       info->next_index = index + 1;
-       }
-       if (page) {
-               /* another task gave its page, or truncated the file */
-               shmem_free_blocks(inode, 1);
-               shmem_dir_free(page);
-       }
-       if (info->next_index <= index && !IS_ERR(entry))
-               info->next_index = index + 1;
-       return entry;
+export:
+               indices[ret] = indices[i];
+               pages[ret] = page;
+               ret++;
+       }
+       if (unlikely(!ret && nr_found))
+               goto restart;
+       rcu_read_unlock();
+       return ret;
 }
 
-/**
- * shmem_free_swp - free some swap entries in a directory
- * @dir:        pointer to the directory
- * @edir:       pointer after last entry of the directory
- * @punch_lock: pointer to spinlock when needed for the holepunch case
+/*
+ * Remove swap entry from radix tree, free the swap and its page cache.
  */
-static int shmem_free_swp(swp_entry_t *dir, swp_entry_t *edir,
-                                               spinlock_t *punch_lock)
-{
-       spinlock_t *punch_unlock = NULL;
-       swp_entry_t *ptr;
-       int freed = 0;
-
-       for (ptr = dir; ptr < edir; ptr++) {
-               if (ptr->val) {
-                       if (unlikely(punch_lock)) {
-                               punch_unlock = punch_lock;
-                               punch_lock = NULL;
-                               spin_lock(punch_unlock);
-                               if (!ptr->val)
-                                       continue;
-                       }
-                       free_swap_and_cache(*ptr);
-                       *ptr = (swp_entry_t){0};
-                       freed++;
-               }
-       }
-       if (punch_unlock)
-               spin_unlock(punch_unlock);
-       return freed;
-}
-
-static int shmem_map_and_free_swp(struct page *subdir, int offset,
-               int limit, struct page ***dir, spinlock_t *punch_lock)
-{
-       swp_entry_t *ptr;
-       int freed = 0;
-
-       ptr = shmem_swp_map(subdir);
-       for (; offset < limit; offset += LATENCY_LIMIT) {
-               int size = limit - offset;
-               if (size > LATENCY_LIMIT)
-                       size = LATENCY_LIMIT;
-               freed += shmem_free_swp(ptr+offset, ptr+offset+size,
-                                                       punch_lock);
-               if (need_resched()) {
-                       shmem_swp_unmap(ptr);
-                       if (*dir) {
-                               shmem_dir_unmap(*dir);
-                               *dir = NULL;
-                       }
-                       cond_resched();
-                       ptr = shmem_swp_map(subdir);
-               }
-       }
-       shmem_swp_unmap(ptr);
-       return freed;
+static int shmem_free_swap(struct address_space *mapping,
+                          pgoff_t index, void *radswap)
+{
+       int error;
+
+       spin_lock_irq(&mapping->tree_lock);
+       error = shmem_radix_tree_replace(mapping, index, radswap, NULL);
+       spin_unlock_irq(&mapping->tree_lock);
+       if (!error)
+               free_swap_and_cache(radix_to_swp_entry(radswap));
+       return error;
 }
 
-static void shmem_free_pages(struct list_head *next)
+/*
+ * Pagevec may contain swap entries, so shuffle up pages before releasing.
+ */
+static void shmem_pagevec_release(struct pagevec *pvec)
 {
-       struct page *page;
-       int freed = 0;
-
-       do {
-               page = container_of(next, struct page, lru);
-               next = next->next;
-               shmem_dir_free(page);
-               freed++;
-               if (freed >= LATENCY_LIMIT) {
-                       cond_resched();
-                       freed = 0;
-               }
-       } while (next);
+       int i, j;
+
+       for (i = 0, j = 0; i < pagevec_count(pvec); i++) {
+               struct page *page = pvec->pages[i];
+               if (!radix_tree_exceptional_entry(page))
+                       pvec->pages[j++] = page;
+       }
+       pvec->nr = j;
+       pagevec_release(pvec);
 }
 
-void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end)
+/*
+ * Remove range of pages and swap entries from radix tree, and free them.
+ */
+void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
 {
+       struct address_space *mapping = inode->i_mapping;
        struct shmem_inode_info *info = SHMEM_I(inode);
-       unsigned long idx;
-       unsigned long size;
-       unsigned long limit;
-       unsigned long stage;
-       unsigned long diroff;
-       struct page **dir;
-       struct page *topdir;
-       struct page *middir;
-       struct page *subdir;
-       swp_entry_t *ptr;
-       LIST_HEAD(pages_to_free);
-       long nr_pages_to_free = 0;
+       pgoff_t start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       unsigned partial = lstart & (PAGE_CACHE_SIZE - 1);
+       pgoff_t end = (lend >> PAGE_CACHE_SHIFT);
+       struct pagevec pvec;
+       pgoff_t indices[PAGEVEC_SIZE];
        long nr_swaps_freed = 0;
-       int offset;
-       int freed;
-       int punch_hole;
-       spinlock_t *needs_lock;
-       spinlock_t *punch_lock;
-       unsigned long upper_limit;
+       pgoff_t index;
+       int i;
 
-       truncate_inode_pages_range(inode->i_mapping, start, end);
+       BUG_ON((lend & (PAGE_CACHE_SIZE - 1)) != (PAGE_CACHE_SIZE - 1));
 
-       inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-       idx = (start + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-       if (idx >= info->next_index)
-               return;
+       pagevec_init(&pvec, 0);
+       index = start;
+       while (index <= end) {
+               pvec.nr = shmem_find_get_pages_and_swap(mapping, index,
+                       min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1,
+                                                       pvec.pages, indices);
+               if (!pvec.nr)
+                       break;
+               mem_cgroup_uncharge_start();
+               for (i = 0; i < pagevec_count(&pvec); i++) {
+                       struct page *page = pvec.pages[i];
 
-       spin_lock(&info->lock);
-       info->flags |= SHMEM_TRUNCATE;
-       if (likely(end == (loff_t) -1)) {
-               limit = info->next_index;
-               upper_limit = SHMEM_MAX_INDEX;
-               info->next_index = idx;
-               needs_lock = NULL;
-               punch_hole = 0;
-       } else {
-               if (end + 1 >= inode->i_size) { /* we may free a little more */
-                       limit = (inode->i_size + PAGE_CACHE_SIZE - 1) >>
-                                                       PAGE_CACHE_SHIFT;
-                       upper_limit = SHMEM_MAX_INDEX;
-               } else {
-                       limit = (end + 1) >> PAGE_CACHE_SHIFT;
-                       upper_limit = limit;
-               }
-               needs_lock = &info->lock;
-               punch_hole = 1;
-       }
+                       index = indices[i];
+                       if (index > end)
+                               break;
+
+                       if (radix_tree_exceptional_entry(page)) {
+                               nr_swaps_freed += !shmem_free_swap(mapping,
+                                                               index, page);
+                               continue;
+                       }
 
-       topdir = info->i_indirect;
-       if (topdir && idx <= SHMEM_NR_DIRECT && !punch_hole) {
-               info->i_indirect = NULL;
-               nr_pages_to_free++;
-               list_add(&topdir->lru, &pages_to_free);
+                       if (!trylock_page(page))
+                               continue;
+                       if (page->mapping == mapping) {
+                               VM_BUG_ON(PageWriteback(page));
+                               truncate_inode_page(mapping, page);
+                       }
+                       unlock_page(page);
+               }
+               shmem_pagevec_release(&pvec);
+               mem_cgroup_uncharge_end();
+               cond_resched();
+               index++;
        }
-       spin_unlock(&info->lock);
 
-       if (info->swapped && idx < SHMEM_NR_DIRECT) {
-               ptr = info->i_direct;
-               size = limit;
-               if (size > SHMEM_NR_DIRECT)
-                       size = SHMEM_NR_DIRECT;
-               nr_swaps_freed = shmem_free_swp(ptr+idx, ptr+size, needs_lock);
+       if (partial) {
+               struct page *page = NULL;
+               shmem_getpage(inode, start - 1, &page, SGP_READ, NULL);
+               if (page) {
+                       zero_user_segment(page, partial, PAGE_CACHE_SIZE);
+                       set_page_dirty(page);
+                       unlock_page(page);
+                       page_cache_release(page);
+               }
        }
 
-       /*
-        * If there are no indirect blocks or we are punching a hole
-        * below indirect blocks, nothing to be done.
-        */
-       if (!topdir || limit <= SHMEM_NR_DIRECT)
-               goto done2;
+       index = start;
+       for ( ; ; ) {
+               cond_resched();
+               pvec.nr = shmem_find_get_pages_and_swap(mapping, index,
+                       min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1,
+                                                       pvec.pages, indices);
+               if (!pvec.nr) {
+                       if (index == start)
+                               break;
+                       index = start;
+                       continue;
+               }
+               if (index == start && indices[0] > end) {
+                       shmem_pagevec_release(&pvec);
+                       break;
+               }
+               mem_cgroup_uncharge_start();
+               for (i = 0; i < pagevec_count(&pvec); i++) {
+                       struct page *page = pvec.pages[i];
 
-       /*
-        * The truncation case has already dropped info->lock, and we're safe
-        * because i_size and next_index have already been lowered, preventing
-        * access beyond.  But in the punch_hole case, we still need to take
-        * the lock when updating the swap directory, because there might be
-        * racing accesses by shmem_getpage(SGP_CACHE), shmem_unuse_inode or
-        * shmem_writepage.  However, whenever we find we can remove a whole
-        * directory page (not at the misaligned start or end of the range),
-        * we first NULLify its pointer in the level above, and then have no
-        * need to take the lock when updating its contents: needs_lock and
-        * punch_lock (either pointing to info->lock or NULL) manage this.
-        */
+                       index = indices[i];
+                       if (index > end)
+                               break;
 
-       upper_limit -= SHMEM_NR_DIRECT;
-       limit -= SHMEM_NR_DIRECT;
-       idx = (idx > SHMEM_NR_DIRECT)? (idx - SHMEM_NR_DIRECT): 0;
-       offset = idx % ENTRIES_PER_PAGE;
-       idx -= offset;
-
-       dir = shmem_dir_map(topdir);
-       stage = ENTRIES_PER_PAGEPAGE/2;
-       if (idx < ENTRIES_PER_PAGEPAGE/2) {
-               middir = topdir;
-               diroff = idx/ENTRIES_PER_PAGE;
-       } else {
-               dir += ENTRIES_PER_PAGE/2;
-               dir += (idx - ENTRIES_PER_PAGEPAGE/2)/ENTRIES_PER_PAGEPAGE;
-               while (stage <= idx)
-                       stage += ENTRIES_PER_PAGEPAGE;
-               middir = *dir;
-               if (*dir) {
-                       diroff = ((idx - ENTRIES_PER_PAGEPAGE/2) %
-                               ENTRIES_PER_PAGEPAGE) / ENTRIES_PER_PAGE;
-                       if (!diroff && !offset && upper_limit >= stage) {
-                               if (needs_lock) {
-                                       spin_lock(needs_lock);
-                                       *dir = NULL;
-                                       spin_unlock(needs_lock);
-                                       needs_lock = NULL;
-                               } else
-                                       *dir = NULL;
-                               nr_pages_to_free++;
-                               list_add(&middir->lru, &pages_to_free);
+                       if (radix_tree_exceptional_entry(page)) {
+                               nr_swaps_freed += !shmem_free_swap(mapping,
+                                                               index, page);
+                               continue;
                        }
-                       shmem_dir_unmap(dir);
-                       dir = shmem_dir_map(middir);
-               } else {
-                       diroff = 0;
-                       offset = 0;
-                       idx = stage;
-               }
-       }
 
-       for (; idx < limit; idx += ENTRIES_PER_PAGE, diroff++) {
-               if (unlikely(idx == stage)) {
-                       shmem_dir_unmap(dir);
-                       dir = shmem_dir_map(topdir) +
-                           ENTRIES_PER_PAGE/2 + idx/ENTRIES_PER_PAGEPAGE;
-                       while (!*dir) {
-                               dir++;
-                               idx += ENTRIES_PER_PAGEPAGE;
-                               if (idx >= limit)
-                                       goto done1;
-                       }
-                       stage = idx + ENTRIES_PER_PAGEPAGE;
-                       middir = *dir;
-                       if (punch_hole)
-                               needs_lock = &info->lock;
-                       if (upper_limit >= stage) {
-                               if (needs_lock) {
-                                       spin_lock(needs_lock);
-                                       *dir = NULL;
-                                       spin_unlock(needs_lock);
-                                       needs_lock = NULL;
-                               } else
-                                       *dir = NULL;
-                               nr_pages_to_free++;
-                               list_add(&middir->lru, &pages_to_free);
+                       lock_page(page);
+                       if (page->mapping == mapping) {
+                               VM_BUG_ON(PageWriteback(page));
+                               truncate_inode_page(mapping, page);
                        }
-                       shmem_dir_unmap(dir);
-                       cond_resched();
-                       dir = shmem_dir_map(middir);
-                       diroff = 0;
-               }
-               punch_lock = needs_lock;
-               subdir = dir[diroff];
-               if (subdir && !offset && upper_limit-idx >= ENTRIES_PER_PAGE) {
-                       if (needs_lock) {
-                               spin_lock(needs_lock);
-                               dir[diroff] = NULL;
-                               spin_unlock(needs_lock);
-                               punch_lock = NULL;
-                       } else
-                               dir[diroff] = NULL;
-                       nr_pages_to_free++;
-                       list_add(&subdir->lru, &pages_to_free);
-               }
-               if (subdir && page_private(subdir) /* has swap entries */) {
-                       size = limit - idx;
-                       if (size > ENTRIES_PER_PAGE)
-                               size = ENTRIES_PER_PAGE;
-                       freed = shmem_map_and_free_swp(subdir,
-                                       offset, size, &dir, punch_lock);
-                       if (!dir)
-                               dir = shmem_dir_map(middir);
-                       nr_swaps_freed += freed;
-                       if (offset || punch_lock) {
-                               spin_lock(&info->lock);
-                               set_page_private(subdir,
-                                       page_private(subdir) - freed);
-                               spin_unlock(&info->lock);
-                       } else
-                               BUG_ON(page_private(subdir) != freed);
+                       unlock_page(page);
                }
-               offset = 0;
-       }
-done1:
-       shmem_dir_unmap(dir);
-done2:
-       if (inode->i_mapping->nrpages && (info->flags & SHMEM_PAGEIN)) {
-               /*
-                * Call truncate_inode_pages again: racing shmem_unuse_inode
-                * may have swizzled a page in from swap since
-                * truncate_pagecache or generic_delete_inode did it, before we
-                * lowered next_index.  Also, though shmem_getpage checks
-                * i_size before adding to cache, no recheck after: so fix the
-                * narrow window there too.
-                */
-               truncate_inode_pages_range(inode->i_mapping, start, end);
+               shmem_pagevec_release(&pvec);
+               mem_cgroup_uncharge_end();
+               index++;
        }
 
        spin_lock(&info->lock);
-       info->flags &= ~SHMEM_TRUNCATE;
        info->swapped -= nr_swaps_freed;
-       if (nr_pages_to_free)
-               shmem_free_blocks(inode, nr_pages_to_free);
        shmem_recalc_inode(inode);
        spin_unlock(&info->lock);
 
-       /*
-        * Empty swap vector directory pages to be freed?
-        */
-       if (!list_empty(&pages_to_free)) {
-               pages_to_free.prev->next = NULL;
-               shmem_free_pages(pages_to_free.next);
-       }
+       inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 }
 EXPORT_SYMBOL_GPL(shmem_truncate_range);
 
@@ -780,37 +520,7 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr)
        if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
                loff_t oldsize = inode->i_size;
                loff_t newsize = attr->ia_size;
-               struct page *page = NULL;
 
-               if (newsize < oldsize) {
-                       /*
-                        * If truncating down to a partial page, then
-                        * if that page is already allocated, hold it
-                        * in memory until the truncation is over, so
-                        * truncate_partial_page cannot miss it were
-                        * it assigned to swap.
-                        */
-                       if (newsize & (PAGE_CACHE_SIZE-1)) {
-                               (void) shmem_getpage(inode,
-                                       newsize >> PAGE_CACHE_SHIFT,
-                                               &page, SGP_READ, NULL);
-                               if (page)
-                                       unlock_page(page);
-                       }
-                       /*
-                        * Reset SHMEM_PAGEIN flag so that shmem_truncate can
-                        * detect if any pages might have been added to cache
-                        * after truncate_inode_pages.  But we needn't bother
-                        * if it's being fully truncated to zero-length: the
-                        * nrpages check is efficient enough in that case.
-                        */
-                       if (newsize) {
-                               struct shmem_inode_info *info = SHMEM_I(inode);
-                               spin_lock(&info->lock);
-                               info->flags &= ~SHMEM_PAGEIN;
-                               spin_unlock(&info->lock);
-                       }
-               }
                if (newsize != oldsize) {
                        i_size_write(inode, newsize);
                        inode->i_ctime = inode->i_mtime = CURRENT_TIME;
@@ -822,8 +532,6 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr)
                        /* unmap again to remove racily COWed private pages */
                        unmap_mapping_range(inode->i_mapping, holebegin, 0, 1);
                }
-               if (page)
-                       page_cache_release(page);
        }
 
        setattr_copy(inode, attr);
@@ -848,7 +556,8 @@ static void shmem_evict_inode(struct inode *inode)
                        list_del_init(&info->swaplist);
                        mutex_unlock(&shmem_swaplist_mutex);
                }
-       }
+       } else
+               kfree(info->symlink);
 
        list_for_each_entry_safe(xattr, nxattr, &info->xattr_list, list) {
                kfree(xattr->name);
@@ -859,106 +568,27 @@ static void shmem_evict_inode(struct inode *inode)
        end_writeback(inode);
 }
 
-static inline int shmem_find_swp(swp_entry_t entry, swp_entry_t *dir, swp_entry_t *edir)
-{
-       swp_entry_t *ptr;
-
-       for (ptr = dir; ptr < edir; ptr++) {
-               if (ptr->val == entry.val)
-                       return ptr - dir;
-       }
-       return -1;
-}
-
-static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, struct page *page)
+/*
+ * If swap found in inode, free it and move page from swapcache to filecache.
+ */
+static int shmem_unuse_inode(struct shmem_inode_info *info,
+                            swp_entry_t swap, struct page *page)
 {
-       struct address_space *mapping;
-       unsigned long idx;
-       unsigned long size;
-       unsigned long limit;
-       unsigned long stage;
-       struct page **dir;
-       struct page *subdir;
-       swp_entry_t *ptr;
-       int offset;
+       struct address_space *mapping = info->vfs_inode.i_mapping;
+       void *radswap;
+       pgoff_t index;
        int error;
 
-       idx = 0;
-       ptr = info->i_direct;
-       spin_lock(&info->lock);
-       if (!info->swapped) {
-               list_del_init(&info->swaplist);
-               goto lost2;
-       }
-       limit = info->next_index;
-       size = limit;
-       if (size > SHMEM_NR_DIRECT)
-               size = SHMEM_NR_DIRECT;
-       offset = shmem_find_swp(entry, ptr, ptr+size);
-       if (offset >= 0) {
-               shmem_swp_balance_unmap();
-               goto found;
-       }
-       if (!info->i_indirect)
-               goto lost2;
-
-       dir = shmem_dir_map(info->i_indirect);
-       stage = SHMEM_NR_DIRECT + ENTRIES_PER_PAGEPAGE/2;
-
-       for (idx = SHMEM_NR_DIRECT; idx < limit; idx += ENTRIES_PER_PAGE, dir++) {
-               if (unlikely(idx == stage)) {
-                       shmem_dir_unmap(dir-1);
-                       if (cond_resched_lock(&info->lock)) {
-                               /* check it has not been truncated */
-                               if (limit > info->next_index) {
-                                       limit = info->next_index;
-                                       if (idx >= limit)
-                                               goto lost2;
-                               }
-                       }
-                       dir = shmem_dir_map(info->i_indirect) +
-                           ENTRIES_PER_PAGE/2 + idx/ENTRIES_PER_PAGEPAGE;
-                       while (!*dir) {
-                               dir++;
-                               idx += ENTRIES_PER_PAGEPAGE;
-                               if (idx >= limit)
-                                       goto lost1;
-                       }
-                       stage = idx + ENTRIES_PER_PAGEPAGE;
-                       subdir = *dir;
-                       shmem_dir_unmap(dir);
-                       dir = shmem_dir_map(subdir);
-               }
-               subdir = *dir;
-               if (subdir && page_private(subdir)) {
-                       ptr = shmem_swp_map(subdir);
-                       size = limit - idx;
-                       if (size > ENTRIES_PER_PAGE)
-                               size = ENTRIES_PER_PAGE;
-                       offset = shmem_find_swp(entry, ptr, ptr+size);
-                       shmem_swp_unmap(ptr);
-                       if (offset >= 0) {
-                               shmem_dir_unmap(dir);
-                               ptr = shmem_swp_map(subdir);
-                               goto found;
-                       }
-               }
-       }
-lost1:
-       shmem_dir_unmap(dir-1);
-lost2:
-       spin_unlock(&info->lock);
-       return 0;
-found:
-       idx += offset;
-       ptr += offset;
+       radswap = swp_to_radix_entry(swap);
+       index = radix_tree_locate_item(&mapping->page_tree, radswap);
+       if (index == -1)
+               return 0;
 
        /*
         * Move _head_ to start search for next from here.
         * But be careful: shmem_evict_inode checks list_empty without taking
         * mutex, and there's an instant in list_move_tail when info->swaplist
-        * would appear empty, if it were the only one on shmem_swaplist.  We
-        * could avoid doing it if inode NULL; or use this minor optimization.
+        * would appear empty, if it were the only one on shmem_swaplist.
         */
        if (shmem_swaplist.next != &info->swaplist)
                list_move_tail(&shmem_swaplist, &info->swaplist);
@@ -968,29 +598,34 @@ found:
         * but also to hold up shmem_evict_inode(): so inode cannot be freed
         * beneath us (pagelock doesn't help until the page is in pagecache).
         */
-       mapping = info->vfs_inode.i_mapping;
-       error = add_to_page_cache_locked(page, mapping, idx, GFP_NOWAIT);
+       error = shmem_add_to_page_cache(page, mapping, index,
+                                               GFP_NOWAIT, radswap);
        /* which does mem_cgroup_uncharge_cache_page on error */
 
        if (error != -ENOMEM) {
+               /*
+                * Truncation and eviction use free_swap_and_cache(), which
+                * only does trylock page: if we raced, best clean up here.
+                */
                delete_from_swap_cache(page);
                set_page_dirty(page);
-               info->flags |= SHMEM_PAGEIN;
-               shmem_swp_set(info, ptr, 0);
-               swap_free(entry);
+               if (!error) {
+                       spin_lock(&info->lock);
+                       info->swapped--;
+                       spin_unlock(&info->lock);
+                       swap_free(swap);
+               }
                error = 1;      /* not an error, but entry was found */
        }
-       shmem_swp_unmap(ptr);
-       spin_unlock(&info->lock);
        return error;
 }
 
 /*
- * shmem_unuse() search for an eventually swapped out shmem page.
+ * Search through swapped inodes to find and replace swap by page.
  */
-int shmem_unuse(swp_entry_t entry, struct page *page)
+int shmem_unuse(swp_entry_t swap, struct page *page)
 {
-       struct list_head *p, *next;
+       struct list_head *this, *next;
        struct shmem_inode_info *info;
        int found = 0;
        int error;
@@ -999,32 +634,25 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
         * Charge page using GFP_KERNEL while we can wait, before taking
         * the shmem_swaplist_mutex which might hold up shmem_writepage().
         * Charged back to the user (not to caller) when swap account is used.
-        * add_to_page_cache() will be called with GFP_NOWAIT.
         */
        error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL);
        if (error)
                goto out;
-       /*
-        * Try to preload while we can wait, to not make a habit of
-        * draining atomic reserves; but don't latch on to this cpu,
-        * it's okay if sometimes we get rescheduled after this.
-        */
-       error = radix_tree_preload(GFP_KERNEL);
-       if (error)
-               goto uncharge;
-       radix_tree_preload_end();
+       /* No radix_tree_preload: swap entry keeps a place for page in tree */
 
        mutex_lock(&shmem_swaplist_mutex);
-       list_for_each_safe(p, next, &shmem_swaplist) {
-               info = list_entry(p, struct shmem_inode_info, swaplist);
-               found = shmem_unuse_inode(info, entry, page);
+       list_for_each_safe(this, next, &shmem_swaplist) {
+               info = list_entry(this, struct shmem_inode_info, swaplist);
+               if (info->swapped)
+                       found = shmem_unuse_inode(info, swap, page);
+               else
+                       list_del_init(&info->swaplist);
                cond_resched();
                if (found)
                        break;
        }
        mutex_unlock(&shmem_swaplist_mutex);
 
-uncharge:
        if (!found)
                mem_cgroup_uncharge_cache_page(page);
        if (found < 0)
@@ -1041,10 +669,10 @@ out:
 static int shmem_writepage(struct page *page, struct writeback_control *wbc)
 {
        struct shmem_inode_info *info;
-       swp_entry_t *entry, swap;
        struct address_space *mapping;
-       unsigned long index;
        struct inode *inode;
+       swp_entry_t swap;
+       pgoff_t index;
 
        BUG_ON(!PageLocked(page));
        mapping = page->mapping;
@@ -1073,50 +701,32 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
 
        /*
         * Add inode to shmem_unuse()'s list of swapped-out inodes,
-        * if it's not already there.  Do it now because we cannot take
-        * mutex while holding spinlock, and must do so before the page
-        * is moved to swap cache, when its pagelock no longer protects
+        * if it's not already there.  Do it now before the page is
+        * moved to swap cache, when its pagelock no longer protects
         * the inode from eviction.  But don't unlock the mutex until
-        * we've taken the spinlock, because shmem_unuse_inode() will
-        * prune a !swapped inode from the swaplist under both locks.
+        * we've incremented swapped, because shmem_unuse_inode() will
+        * prune a !swapped inode from the swaplist under this mutex.
         */
        mutex_lock(&shmem_swaplist_mutex);
        if (list_empty(&info->swaplist))
                list_add_tail(&info->swaplist, &shmem_swaplist);
 
-       spin_lock(&info->lock);
-       mutex_unlock(&shmem_swaplist_mutex);
-
-       if (index >= info->next_index) {
-               BUG_ON(!(info->flags & SHMEM_TRUNCATE));
-               goto unlock;
-       }
-       entry = shmem_swp_entry(info, index, NULL);
-       if (entry->val) {
-               WARN_ON_ONCE(1);        /* Still happens? Tell us about it! */
-               free_swap_and_cache(*entry);
-               shmem_swp_set(info, entry, 0);
-       }
-       shmem_recalc_inode(inode);
-
        if (add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) {
-               delete_from_page_cache(page);
-               shmem_swp_set(info, entry, swap.val);
-               shmem_swp_unmap(entry);
                swap_shmem_alloc(swap);
+               shmem_delete_from_page_cache(page, swp_to_radix_entry(swap));
+
+               spin_lock(&info->lock);
+               info->swapped++;
+               shmem_recalc_inode(inode);
                spin_unlock(&info->lock);
+
+               mutex_unlock(&shmem_swaplist_mutex);
                BUG_ON(page_mapped(page));
                swap_writepage(page, wbc);
                return 0;
        }
 
-       shmem_swp_unmap(entry);
-unlock:
-       spin_unlock(&info->lock);
-       /*
-        * add_to_swap_cache() doesn't return -EEXIST, so we can safely
-        * clear SWAP_HAS_CACHE flag.
-        */
+       mutex_unlock(&shmem_swaplist_mutex);
        swapcache_free(swap, NULL);
 redirty:
        set_page_dirty(page);
@@ -1153,35 +763,33 @@ static struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
 }
 #endif /* CONFIG_TMPFS */
 
-static struct page *shmem_swapin(swp_entry_t entry, gfp_t gfp,
-                       struct shmem_inode_info *info, unsigned long idx)
+static struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp,
+                       struct shmem_inode_info *info, pgoff_t index)
 {
        struct mempolicy mpol, *spol;
        struct vm_area_struct pvma;
-       struct page *page;
 
        spol = mpol_cond_copy(&mpol,
-                               mpol_shared_policy_lookup(&info->policy, idx));
+                       mpol_shared_policy_lookup(&info->policy, index));
 
        /* Create a pseudo vma that just contains the policy */
        pvma.vm_start = 0;
-       pvma.vm_pgoff = idx;
+       pvma.vm_pgoff = index;
        pvma.vm_ops = NULL;
        pvma.vm_policy = spol;
-       page = swapin_readahead(entry, gfp, &pvma, 0);
-       return page;
+       return swapin_readahead(swap, gfp, &pvma, 0);
 }
 
 static struct page *shmem_alloc_page(gfp_t gfp,
-                       struct shmem_inode_info *info, unsigned long idx)
+                       struct shmem_inode_info *info, pgoff_t index)
 {
        struct vm_area_struct pvma;
 
        /* Create a pseudo vma that just contains the policy */
        pvma.vm_start = 0;
-       pvma.vm_pgoff = idx;
+       pvma.vm_pgoff = index;
        pvma.vm_ops = NULL;
-       pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx);
+       pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index);
 
        /*
         * alloc_page_vma() will drop the shared policy reference
@@ -1190,19 +798,19 @@ static struct page *shmem_alloc_page(gfp_t gfp,
 }
 #else /* !CONFIG_NUMA */
 #ifdef CONFIG_TMPFS
-static inline void shmem_show_mpol(struct seq_file *seq, struct mempolicy *p)
+static inline void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol)
 {
 }
 #endif /* CONFIG_TMPFS */
 
-static inline struct page *shmem_swapin(swp_entry_t entry, gfp_t gfp,
-                       struct shmem_inode_info *info, unsigned long idx)
+static inline struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp,
+                       struct shmem_inode_info *info, pgoff_t index)
 {
-       return swapin_readahead(entry, gfp, NULL, 0);
+       return swapin_readahead(swap, gfp, NULL, 0);
 }
 
 static inline struct page *shmem_alloc_page(gfp_t gfp,
-                       struct shmem_inode_info *info, unsigned long idx)
+                       struct shmem_inode_info *info, pgoff_t index)
 {
        return alloc_page(gfp);
 }
@@ -1222,243 +830,190 @@ static inline struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
  * vm. If we swap it in we mark it dirty since we also free the swap
  * entry since a page cannot live in both the swap and page cache
  */
-static int shmem_getpage_gfp(struct inode *inode, pgoff_t idx,
+static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
        struct page **pagep, enum sgp_type sgp, gfp_t gfp, int *fault_type)
 {
        struct address_space *mapping = inode->i_mapping;
-       struct shmem_inode_info *info = SHMEM_I(inode);
+       struct shmem_inode_info *info;
        struct shmem_sb_info *sbinfo;
        struct page *page;
-       struct page *prealloc_page = NULL;
-       swp_entry_t *entry;
        swp_entry_t swap;
        int error;
-       int ret;
+       int once = 0;
 
-       if (idx >= SHMEM_MAX_INDEX)
+       if (index > (MAX_LFS_FILESIZE >> PAGE_CACHE_SHIFT))
                return -EFBIG;
 repeat:
-       page = find_lock_page(mapping, idx);
-       if (page) {
+       swap.val = 0;
+       page = find_lock_page(mapping, index);
+       if (radix_tree_exceptional_entry(page)) {
+               swap = radix_to_swp_entry(page);
+               page = NULL;
+       }
+
+       if (sgp != SGP_WRITE &&
+           ((loff_t)index << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
+               error = -EINVAL;
+               goto failed;
+       }
+
+       if (page || (sgp == SGP_READ && !swap.val)) {
                /*
                 * Once we can get the page lock, it must be uptodate:
                 * if there were an error in reading back from swap,
                 * the page would not be inserted into the filecache.
                 */
-               BUG_ON(!PageUptodate(page));
-               goto done;
+               BUG_ON(page && !PageUptodate(page));
+               *pagep = page;
+               return 0;
        }
 
        /*
-        * Try to preload while we can wait, to not make a habit of
-        * draining atomic reserves; but don't latch on to this cpu.
+        * Fast cache lookup did not find it:
+        * bring it back from swap or allocate.
         */
-       error = radix_tree_preload(gfp & GFP_RECLAIM_MASK);
-       if (error)
-               goto out;
-       radix_tree_preload_end();
-
-       if (sgp != SGP_READ && !prealloc_page) {
-               prealloc_page = shmem_alloc_page(gfp, info, idx);
-               if (prealloc_page) {
-                       SetPageSwapBacked(prealloc_page);
-                       if (mem_cgroup_cache_charge(prealloc_page,
-                                       current->mm, GFP_KERNEL)) {
-                               page_cache_release(prealloc_page);
-                               prealloc_page = NULL;
-                       }
-               }
-       }
-
-       spin_lock(&info->lock);
-       shmem_recalc_inode(inode);
-       entry = shmem_swp_alloc(info, idx, sgp, gfp);
-       if (IS_ERR(entry)) {
-               spin_unlock(&info->lock);
-               error = PTR_ERR(entry);
-               goto out;
-       }
-       swap = *entry;
+       info = SHMEM_I(inode);
+       sbinfo = SHMEM_SB(inode->i_sb);
 
        if (swap.val) {
                /* Look it up and read it in.. */
                page = lookup_swap_cache(swap);
                if (!page) {
-                       shmem_swp_unmap(entry);
-                       spin_unlock(&info->lock);
                        /* here we actually do the io */
                        if (fault_type)
                                *fault_type |= VM_FAULT_MAJOR;
-                       page = shmem_swapin(swap, gfp, info, idx);
+                       page = shmem_swapin(swap, gfp, info, index);
                        if (!page) {
-                               spin_lock(&info->lock);
-                               entry = shmem_swp_alloc(info, idx, sgp, gfp);
-                               if (IS_ERR(entry))
-                                       error = PTR_ERR(entry);
-                               else {
-                                       if (entry->val == swap.val)
-                                               error = -ENOMEM;
-                                       shmem_swp_unmap(entry);
-                               }
-                               spin_unlock(&info->lock);
-                               if (error)
-                                       goto out;
-                               goto repeat;
+                               error = -ENOMEM;
+                               goto failed;
                        }
-                       wait_on_page_locked(page);
-                       page_cache_release(page);
-                       goto repeat;
                }
 
                /* We have to do this with page locked to prevent races */
-               if (!trylock_page(page)) {
-                       shmem_swp_unmap(entry);
-                       spin_unlock(&info->lock);
-                       wait_on_page_locked(page);
-                       page_cache_release(page);
-                       goto repeat;
-               }
-               if (PageWriteback(page)) {
-                       shmem_swp_unmap(entry);
-                       spin_unlock(&info->lock);
-                       wait_on_page_writeback(page);
-                       unlock_page(page);
-                       page_cache_release(page);
-                       goto repeat;
-               }
+               lock_page(page);
                if (!PageUptodate(page)) {
-                       shmem_swp_unmap(entry);
-                       spin_unlock(&info->lock);
-                       unlock_page(page);
-                       page_cache_release(page);
                        error = -EIO;
-                       goto out;
+                       goto failed;
                }
-
-               error = add_to_page_cache_locked(page, mapping,
-                                                idx, GFP_NOWAIT);
-               if (error) {
-                       shmem_swp_unmap(entry);
-                       spin_unlock(&info->lock);
-                       if (error == -ENOMEM) {
-                               /*
-                                * reclaim from proper memory cgroup and
-                                * call memcg's OOM if needed.
-                                */
-                               error = mem_cgroup_shmem_charge_fallback(
-                                               page, current->mm, gfp);
-                               if (error) {
-                                       unlock_page(page);
-                                       page_cache_release(page);
-                                       goto out;
-                               }
-                       }
-                       unlock_page(page);
-                       page_cache_release(page);
-                       goto repeat;
+               wait_on_page_writeback(page);
+
+               /* Someone may have already done it for us */
+               if (page->mapping) {
+                       if (page->mapping == mapping &&
+                           page->index == index)
+                               goto done;
+                       error = -EEXIST;
+                       goto failed;
                }
 
-               info->flags |= SHMEM_PAGEIN;
-               shmem_swp_set(info, entry, 0);
-               shmem_swp_unmap(entry);
-               delete_from_swap_cache(page);
+               error = mem_cgroup_cache_charge(page, current->mm,
+                                               gfp & GFP_RECLAIM_MASK);
+               if (!error)
+                       error = shmem_add_to_page_cache(page, mapping, index,
+                                               gfp, swp_to_radix_entry(swap));
+               if (error)
+                       goto failed;
+
+               spin_lock(&info->lock);
+               info->swapped--;
+               shmem_recalc_inode(inode);
                spin_unlock(&info->lock);
+
+               delete_from_swap_cache(page);
                set_page_dirty(page);
                swap_free(swap);
 
-       } else if (sgp == SGP_READ) {
-               shmem_swp_unmap(entry);
-               page = find_get_page(mapping, idx);
-               if (page && !trylock_page(page)) {
-                       spin_unlock(&info->lock);
-                       wait_on_page_locked(page);
-                       page_cache_release(page);
-                       goto repeat;
+       } else {
+               if (shmem_acct_block(info->flags)) {
+                       error = -ENOSPC;
+                       goto failed;
                }
-               spin_unlock(&info->lock);
-
-       } else if (prealloc_page) {
-               shmem_swp_unmap(entry);
-               sbinfo = SHMEM_SB(inode->i_sb);
                if (sbinfo->max_blocks) {
                        if (percpu_counter_compare(&sbinfo->used_blocks,
-                                               sbinfo->max_blocks) >= 0 ||
-                           shmem_acct_block(info->flags))
-                               goto nospace;
+                                               sbinfo->max_blocks) >= 0) {
+                               error = -ENOSPC;
+                               goto unacct;
+                       }
                        percpu_counter_inc(&sbinfo->used_blocks);
-                       inode->i_blocks += BLOCKS_PER_PAGE;
-               } else if (shmem_acct_block(info->flags))
-                       goto nospace;
-
-               page = prealloc_page;
-               prealloc_page = NULL;
-
-               entry = shmem_swp_alloc(info, idx, sgp, gfp);
-               if (IS_ERR(entry))
-                       error = PTR_ERR(entry);
-               else {
-                       swap = *entry;
-                       shmem_swp_unmap(entry);
                }
-               ret = error || swap.val;
-               if (ret)
-                       mem_cgroup_uncharge_cache_page(page);
-               else
-                       ret = add_to_page_cache_lru(page, mapping,
-                                               idx, GFP_NOWAIT);
-               /*
-                * At add_to_page_cache_lru() failure,
-                * uncharge will be done automatically.
-                */
-               if (ret) {
-                       shmem_unacct_blocks(info->flags, 1);
-                       shmem_free_blocks(inode, 1);
-                       spin_unlock(&info->lock);
-                       page_cache_release(page);
-                       if (error)
-                               goto out;
-                       goto repeat;
+
+               page = shmem_alloc_page(gfp, info, index);
+               if (!page) {
+                       error = -ENOMEM;
+                       goto decused;
                }
 
-               info->flags |= SHMEM_PAGEIN;
+               SetPageSwapBacked(page);
+               __set_page_locked(page);
+               error = mem_cgroup_cache_charge(page, current->mm,
+                                               gfp & GFP_RECLAIM_MASK);
+               if (!error)
+                       error = shmem_add_to_page_cache(page, mapping, index,
+                                               gfp, NULL);
+               if (error)
+                       goto decused;
+               lru_cache_add_anon(page);
+
+               spin_lock(&info->lock);
                info->alloced++;
+               inode->i_blocks += BLOCKS_PER_PAGE;
+               shmem_recalc_inode(inode);
                spin_unlock(&info->lock);
+
                clear_highpage(page);
                flush_dcache_page(page);
                SetPageUptodate(page);
                if (sgp == SGP_DIRTY)
                        set_page_dirty(page);
-
-       } else {
-               spin_unlock(&info->lock);
-               error = -ENOMEM;
-               goto out;
        }
 done:
-       *pagep = page;
-       error = 0;
-out:
-       if (prealloc_page) {
-               mem_cgroup_uncharge_cache_page(prealloc_page);
-               page_cache_release(prealloc_page);
+       /* Perhaps the file has been truncated since we checked */
+       if (sgp != SGP_WRITE &&
+           ((loff_t)index << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
+               error = -EINVAL;
+               goto trunc;
        }
-       return error;
+       *pagep = page;
+       return 0;
 
-nospace:
        /*
-        * Perhaps the page was brought in from swap between find_lock_page
-        * and taking info->lock?  We allow for that at add_to_page_cache_lru,
-        * but must also avoid reporting a spurious ENOSPC while working on a
-        * full tmpfs.
+        * Error recovery.
         */
-       page = find_get_page(mapping, idx);
+trunc:
+       ClearPageDirty(page);
+       delete_from_page_cache(page);
+       spin_lock(&info->lock);
+       info->alloced--;
+       inode->i_blocks -= BLOCKS_PER_PAGE;
        spin_unlock(&info->lock);
+decused:
+       if (sbinfo->max_blocks)
+               percpu_counter_add(&sbinfo->used_blocks, -1);
+unacct:
+       shmem_unacct_blocks(info->flags, 1);
+failed:
+       if (swap.val && error != -EINVAL) {
+               struct page *test = find_get_page(mapping, index);
+               if (test && !radix_tree_exceptional_entry(test))
+                       page_cache_release(test);
+               /* Have another try if the entry has changed */
+               if (test != swp_to_radix_entry(swap))
+                       error = -EEXIST;
+       }
        if (page) {
+               unlock_page(page);
                page_cache_release(page);
+       }
+       if (error == -ENOSPC && !once++) {
+               info = SHMEM_I(inode);
+               spin_lock(&info->lock);
+               shmem_recalc_inode(inode);
+               spin_unlock(&info->lock);
                goto repeat;
        }
-       error = -ENOSPC;
-       goto out;
+       if (error == -EEXIST)
+               goto repeat;
+       return error;
 }
 
 static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -1467,9 +1022,6 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        int error;
        int ret = VM_FAULT_LOCKED;
 
-       if (((loff_t)vmf->pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode))
-               return VM_FAULT_SIGBUS;
-
        error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_CACHE, &ret);
        if (error)
                return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS);
@@ -1482,20 +1034,20 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 }
 
 #ifdef CONFIG_NUMA
-static int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
+static int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *mpol)
 {
-       struct inode *i = vma->vm_file->f_path.dentry->d_inode;
-       return mpol_set_shared_policy(&SHMEM_I(i)->policy, vma, new);
+       struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+       return mpol_set_shared_policy(&SHMEM_I(inode)->policy, vma, mpol);
 }
 
 static struct mempolicy *shmem_get_policy(struct vm_area_struct *vma,
                                          unsigned long addr)
 {
-       struct inode *i = vma->vm_file->f_path.dentry->d_inode;
-       unsigned long idx;
+       struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+       pgoff_t index;
 
-       idx = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
-       return mpol_shared_policy_lookup(&SHMEM_I(i)->policy, idx);
+       index = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+       return mpol_shared_policy_lookup(&SHMEM_I(inode)->policy, index);
 }
 #endif
 
@@ -1593,7 +1145,7 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
 
 #ifdef CONFIG_TMPFS
 static const struct inode_operations shmem_symlink_inode_operations;
-static const struct inode_operations shmem_symlink_inline_operations;
+static const struct inode_operations shmem_short_symlink_operations;
 
 static int
 shmem_write_begin(struct file *file, struct address_space *mapping,
@@ -1626,7 +1178,8 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
 {
        struct inode *inode = filp->f_path.dentry->d_inode;
        struct address_space *mapping = inode->i_mapping;
-       unsigned long index, offset;
+       pgoff_t index;
+       unsigned long offset;
        enum sgp_type sgp = SGP_READ;
 
        /*
@@ -1642,7 +1195,8 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
 
        for (;;) {
                struct page *page = NULL;
-               unsigned long end_index, nr, ret;
+               pgoff_t end_index;
+               unsigned long nr, ret;
                loff_t i_size = i_size_read(inode);
 
                end_index = i_size >> PAGE_CACHE_SHIFT;
@@ -1880,8 +1434,9 @@ static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_namelen = NAME_MAX;
        if (sbinfo->max_blocks) {
                buf->f_blocks = sbinfo->max_blocks;
-               buf->f_bavail = buf->f_bfree =
-                               sbinfo->max_blocks - percpu_counter_sum(&sbinfo->used_blocks);
+               buf->f_bavail =
+               buf->f_bfree  = sbinfo->max_blocks -
+                               percpu_counter_sum(&sbinfo->used_blocks);
        }
        if (sbinfo->max_inodes) {
                buf->f_files = sbinfo->max_inodes;
@@ -2055,10 +1610,13 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
 
        info = SHMEM_I(inode);
        inode->i_size = len-1;
-       if (len <= SHMEM_SYMLINK_INLINE_LEN) {
-               /* do it inline */
-               memcpy(info->inline_symlink, symname, len);
-               inode->i_op = &shmem_symlink_inline_operations;
+       if (len <= SHORT_SYMLINK_LEN) {
+               info->symlink = kmemdup(symname, len, GFP_KERNEL);
+               if (!info->symlink) {
+                       iput(inode);
+                       return -ENOMEM;
+               }
+               inode->i_op = &shmem_short_symlink_operations;
        } else {
                error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
                if (error) {
@@ -2081,17 +1639,17 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
        return 0;
 }
 
-static void *shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
+static void *shmem_follow_short_symlink(struct dentry *dentry, struct nameidata *nd)
 {
-       nd_set_link(nd, SHMEM_I(dentry->d_inode)->inline_symlink);
+       nd_set_link(nd, SHMEM_I(dentry->d_inode)->symlink);
        return NULL;
 }
 
 static void *shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct page *page = NULL;
-       int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL);
-       nd_set_link(nd, res ? ERR_PTR(res) : kmap(page));
+       int error = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL);
+       nd_set_link(nd, error ? ERR_PTR(error) : kmap(page));
        if (page)
                unlock_page(page);
        return page;
@@ -2202,7 +1760,6 @@ out:
        return err;
 }
 
-
 static const struct xattr_handler *shmem_xattr_handlers[] = {
 #ifdef CONFIG_TMPFS_POSIX_ACL
        &generic_acl_access_handler,
@@ -2332,9 +1889,9 @@ static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size)
 }
 #endif /* CONFIG_TMPFS_XATTR */
 
-static const struct inode_operations shmem_symlink_inline_operations = {
+static const struct inode_operations shmem_short_symlink_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = shmem_follow_link_inline,
+       .follow_link    = shmem_follow_short_symlink,
 #ifdef CONFIG_TMPFS_XATTR
        .setxattr       = shmem_setxattr,
        .getxattr       = shmem_getxattr,
@@ -2534,8 +2091,7 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
        if (config.max_inodes < inodes)
                goto out;
        /*
-        * Those tests also disallow limited->unlimited while any are in
-        * use, so i_blocks will always be zero when max_blocks is zero;
+        * Those tests disallow limited->unlimited while any are in use;
         * but we must separately disallow unlimited->limited, because
         * in that case we have no record of how much is already in use.
         */
@@ -2627,7 +2183,7 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent)
                goto failed;
        sbinfo->free_inodes = sbinfo->max_inodes;
 
-       sb->s_maxbytes = SHMEM_MAX_BYTES;
+       sb->s_maxbytes = MAX_LFS_FILESIZE;
        sb->s_blocksize = PAGE_CACHE_SIZE;
        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
        sb->s_magic = TMPFS_MAGIC;
@@ -2662,14 +2218,14 @@ static struct kmem_cache *shmem_inode_cachep;
 
 static struct inode *shmem_alloc_inode(struct super_block *sb)
 {
-       struct shmem_inode_info *p;
-       p = (struct shmem_inode_info *)kmem_cache_alloc(shmem_inode_cachep, GFP_KERNEL);
-       if (!p)
+       struct shmem_inode_info *info;
+       info = kmem_cache_alloc(shmem_inode_cachep, GFP_KERNEL);
+       if (!info)
                return NULL;
-       return &p->vfs_inode;
+       return &info->vfs_inode;
 }
 
-static void shmem_i_callback(struct rcu_head *head)
+static void shmem_destroy_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
        INIT_LIST_HEAD(&inode->i_dentry);
@@ -2678,29 +2234,26 @@ static void shmem_i_callback(struct rcu_head *head)
 
 static void shmem_destroy_inode(struct inode *inode)
 {
-       if ((inode->i_mode & S_IFMT) == S_IFREG) {
-               /* only struct inode is valid if it's an inline symlink */
+       if ((inode->i_mode & S_IFMT) == S_IFREG)
                mpol_free_shared_policy(&SHMEM_I(inode)->policy);
-       }
-       call_rcu(&inode->i_rcu, shmem_i_callback);
+       call_rcu(&inode->i_rcu, shmem_destroy_callback);
 }
 
-static void init_once(void *foo)
+static void shmem_init_inode(void *foo)
 {
-       struct shmem_inode_info *p = (struct shmem_inode_info *) foo;
-
-       inode_init_once(&p->vfs_inode);
+       struct shmem_inode_info *info = foo;
+       inode_init_once(&info->vfs_inode);
 }
 
-static int init_inodecache(void)
+static int shmem_init_inodecache(void)
 {
        shmem_inode_cachep = kmem_cache_create("shmem_inode_cache",
                                sizeof(struct shmem_inode_info),
-                               0, SLAB_PANIC, init_once);
+                               0, SLAB_PANIC, shmem_init_inode);
        return 0;
 }
 
-static void destroy_inodecache(void)
+static void shmem_destroy_inodecache(void)
 {
        kmem_cache_destroy(shmem_inode_cachep);
 }
@@ -2797,21 +2350,20 @@ static const struct vm_operations_struct shmem_vm_ops = {
 #endif
 };
 
-
 static struct dentry *shmem_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data)
 {
        return mount_nodev(fs_type, flags, data, shmem_fill_super);
 }
 
-static struct file_system_type tmpfs_fs_type = {
+static struct file_system_type shmem_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "tmpfs",
        .mount          = shmem_mount,
        .kill_sb        = kill_litter_super,
 };
 
-int __init init_tmpfs(void)
+int __init shmem_init(void)
 {
        int error;
 
@@ -2819,18 +2371,18 @@ int __init init_tmpfs(void)
        if (error)
                goto out4;
 
-       error = init_inodecache();
+       error = shmem_init_inodecache();
        if (error)
                goto out3;
 
-       error = register_filesystem(&tmpfs_fs_type);
+       error = register_filesystem(&shmem_fs_type);
        if (error) {
                printk(KERN_ERR "Could not register tmpfs\n");
                goto out2;
        }
 
-       shm_mnt = vfs_kern_mount(&tmpfs_fs_type, MS_NOUSER,
-                               tmpfs_fs_type.name, NULL);
+       shm_mnt = vfs_kern_mount(&shmem_fs_type, MS_NOUSER,
+                                shmem_fs_type.name, NULL);
        if (IS_ERR(shm_mnt)) {
                error = PTR_ERR(shm_mnt);
                printk(KERN_ERR "Could not kern_mount tmpfs\n");
@@ -2839,9 +2391,9 @@ int __init init_tmpfs(void)
        return 0;
 
 out1:
-       unregister_filesystem(&tmpfs_fs_type);
+       unregister_filesystem(&shmem_fs_type);
 out2:
-       destroy_inodecache();
+       shmem_destroy_inodecache();
 out3:
        bdi_destroy(&shmem_backing_dev_info);
 out4:
@@ -2849,45 +2401,6 @@ out4:
        return error;
 }
 
-#ifdef CONFIG_CGROUP_MEM_RES_CTLR
-/**
- * mem_cgroup_get_shmem_target - find a page or entry assigned to the shmem file
- * @inode: the inode to be searched
- * @pgoff: the offset to be searched
- * @pagep: the pointer for the found page to be stored
- * @ent: the pointer for the found swap entry to be stored
- *
- * If a page is found, refcount of it is incremented. Callers should handle
- * these refcount.
- */
-void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff,
-                                       struct page **pagep, swp_entry_t *ent)
-{
-       swp_entry_t entry = { .val = 0 }, *ptr;
-       struct page *page = NULL;
-       struct shmem_inode_info *info = SHMEM_I(inode);
-
-       if ((pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode))
-               goto out;
-
-       spin_lock(&info->lock);
-       ptr = shmem_swp_entry(info, pgoff, NULL);
-#ifdef CONFIG_SWAP
-       if (ptr && ptr->val) {
-               entry.val = ptr->val;
-               page = find_get_page(&swapper_space, entry.val);
-       } else
-#endif
-               page = find_get_page(inode->i_mapping, pgoff);
-       if (ptr)
-               shmem_swp_unmap(ptr);
-       spin_unlock(&info->lock);
-out:
-       *pagep = page;
-       *ent = entry;
-}
-#endif
-
 #else /* !CONFIG_SHMEM */
 
 /*
@@ -2901,23 +2414,23 @@ out:
 
 #include <linux/ramfs.h>
 
-static struct file_system_type tmpfs_fs_type = {
+static struct file_system_type shmem_fs_type = {
        .name           = "tmpfs",
        .mount          = ramfs_mount,
        .kill_sb        = kill_litter_super,
 };
 
-int __init init_tmpfs(void)
+int __init shmem_init(void)
 {
-       BUG_ON(register_filesystem(&tmpfs_fs_type) != 0);
+       BUG_ON(register_filesystem(&shmem_fs_type) != 0);
 
-       shm_mnt = kern_mount(&tmpfs_fs_type);
+       shm_mnt = kern_mount(&shmem_fs_type);
        BUG_ON(IS_ERR(shm_mnt));
 
        return 0;
 }
 
-int shmem_unuse(swp_entry_t entry, struct page *page)
+int shmem_unuse(swp_entry_t swap, struct page *page)
 {
        return 0;
 }
@@ -2927,43 +2440,17 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
        return 0;
 }
 
-void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end)
+void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
 {
-       truncate_inode_pages_range(inode->i_mapping, start, end);
+       truncate_inode_pages_range(inode->i_mapping, lstart, lend);
 }
 EXPORT_SYMBOL_GPL(shmem_truncate_range);
 
-#ifdef CONFIG_CGROUP_MEM_RES_CTLR
-/**
- * mem_cgroup_get_shmem_target - find a page or entry assigned to the shmem file
- * @inode: the inode to be searched
- * @pgoff: the offset to be searched
- * @pagep: the pointer for the found page to be stored
- * @ent: the pointer for the found swap entry to be stored
- *
- * If a page is found, refcount of it is incremented. Callers should handle
- * these refcount.
- */
-void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff,
-                                       struct page **pagep, swp_entry_t *ent)
-{
-       struct page *page = NULL;
-
-       if ((pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode))
-               goto out;
-       page = find_get_page(inode->i_mapping, pgoff);
-out:
-       *pagep = page;
-       *ent = (swp_entry_t){ .val = 0 };
-}
-#endif
-
 #define shmem_vm_ops                           generic_file_vm_ops
 #define shmem_file_operations                  ramfs_file_operations
 #define shmem_get_inode(sb, dir, mode, dev, flags)     ramfs_get_inode(sb, dir, mode, dev)
 #define shmem_acct_size(flags, size)           0
 #define shmem_unacct_size(flags, size)         do {} while (0)
-#define SHMEM_MAX_BYTES                                MAX_LFS_FILESIZE
 
 #endif /* CONFIG_SHMEM */
 
@@ -2987,7 +2474,7 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags
        if (IS_ERR(shm_mnt))
                return (void *)shm_mnt;
 
-       if (size < 0 || size > SHMEM_MAX_BYTES)
+       if (size < 0 || size > MAX_LFS_FILESIZE)
                return ERR_PTR(-EINVAL);
 
        if (shmem_acct_size(flags, size))
index 1e523ed..6d90a09 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -622,6 +622,51 @@ int slab_is_available(void)
 static struct lock_class_key on_slab_l3_key;
 static struct lock_class_key on_slab_alc_key;
 
+static struct lock_class_key debugobj_l3_key;
+static struct lock_class_key debugobj_alc_key;
+
+static void slab_set_lock_classes(struct kmem_cache *cachep,
+               struct lock_class_key *l3_key, struct lock_class_key *alc_key,
+               int q)
+{
+       struct array_cache **alc;
+       struct kmem_list3 *l3;
+       int r;
+
+       l3 = cachep->nodelists[q];
+       if (!l3)
+               return;
+
+       lockdep_set_class(&l3->list_lock, l3_key);
+       alc = l3->alien;
+       /*
+        * FIXME: This check for BAD_ALIEN_MAGIC
+        * should go away when common slab code is taught to
+        * work even without alien caches.
+        * Currently, non NUMA code returns BAD_ALIEN_MAGIC
+        * for alloc_alien_cache,
+        */
+       if (!alc || (unsigned long)alc == BAD_ALIEN_MAGIC)
+               return;
+       for_each_node(r) {
+               if (alc[r])
+                       lockdep_set_class(&alc[r]->lock, alc_key);
+       }
+}
+
+static void slab_set_debugobj_lock_classes_node(struct kmem_cache *cachep, int node)
+{
+       slab_set_lock_classes(cachep, &debugobj_l3_key, &debugobj_alc_key, node);
+}
+
+static void slab_set_debugobj_lock_classes(struct kmem_cache *cachep)
+{
+       int node;
+
+       for_each_online_node(node)
+               slab_set_debugobj_lock_classes_node(cachep, node);
+}
+
 static void init_node_lock_keys(int q)
 {
        struct cache_sizes *s = malloc_sizes;
@@ -630,29 +675,14 @@ static void init_node_lock_keys(int q)
                return;
 
        for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) {
-               struct array_cache **alc;
                struct kmem_list3 *l3;
-               int r;
 
                l3 = s->cs_cachep->nodelists[q];
                if (!l3 || OFF_SLAB(s->cs_cachep))
                        continue;
-               lockdep_set_class(&l3->list_lock, &on_slab_l3_key);
-               alc = l3->alien;
-               /*
-                * FIXME: This check for BAD_ALIEN_MAGIC
-                * should go away when common slab code is taught to
-                * work even without alien caches.
-                * Currently, non NUMA code returns BAD_ALIEN_MAGIC
-                * for alloc_alien_cache,
-                */
-               if (!alc || (unsigned long)alc == BAD_ALIEN_MAGIC)
-                       continue;
-               for_each_node(r) {
-                       if (alc[r])
-                               lockdep_set_class(&alc[r]->lock,
-                                       &on_slab_alc_key);
-               }
+
+               slab_set_lock_classes(s->cs_cachep, &on_slab_l3_key,
+                               &on_slab_alc_key, q);
        }
 }
 
@@ -671,6 +701,14 @@ static void init_node_lock_keys(int q)
 static inline void init_lock_keys(void)
 {
 }
+
+static void slab_set_debugobj_lock_classes_node(struct kmem_cache *cachep, int node)
+{
+}
+
+static void slab_set_debugobj_lock_classes(struct kmem_cache *cachep)
+{
+}
 #endif
 
 /*
@@ -1264,6 +1302,8 @@ static int __cpuinit cpuup_prepare(long cpu)
                spin_unlock_irq(&l3->list_lock);
                kfree(shared);
                free_alien_cache(alien);
+               if (cachep->flags & SLAB_DEBUG_OBJECTS)
+                       slab_set_debugobj_lock_classes_node(cachep, node);
        }
        init_node_lock_keys(node);
 
@@ -1626,6 +1666,9 @@ void __init kmem_cache_init_late(void)
 {
        struct kmem_cache *cachep;
 
+       /* Annotate slab for lockdep -- annotate the malloc caches */
+       init_lock_keys();
+
        /* 6) resize the head arrays to their final sizes */
        mutex_lock(&cache_chain_mutex);
        list_for_each_entry(cachep, &cache_chain, next)
@@ -1636,9 +1679,6 @@ void __init kmem_cache_init_late(void)
        /* Done! */
        g_cpucache_up = FULL;
 
-       /* Annotate slab for lockdep -- annotate the malloc caches */
-       init_lock_keys();
-
        /*
         * Register a cpu startup notifier callback that initializes
         * cpu_cache_get for all new cpus
@@ -2426,6 +2466,16 @@ kmem_cache_create (const char *name, size_t size, size_t align,
                goto oops;
        }
 
+       if (flags & SLAB_DEBUG_OBJECTS) {
+               /*
+                * Would deadlock through slab_destroy()->call_rcu()->
+                * debug_object_activate()->kmem_cache_alloc().
+                */
+               WARN_ON_ONCE(flags & SLAB_DESTROY_BY_RCU);
+
+               slab_set_debugobj_lock_classes(cachep);
+       }
+
        /* cache setup completed, link it into the list */
        list_add(&cachep->next, &cache_chain);
 oops:
@@ -3403,7 +3453,7 @@ __cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
        cache_alloc_debugcheck_before(cachep, flags);
        local_irq_save(save_flags);
 
-       if (nodeid == -1)
+       if (nodeid == NUMA_NO_NODE)
                nodeid = slab_node;
 
        if (unlikely(!cachep->nodelists[nodeid])) {
@@ -3934,7 +3984,7 @@ fail:
 
 struct ccupdate_struct {
        struct kmem_cache *cachep;
-       struct array_cache *new[NR_CPUS];
+       struct array_cache *new[0];
 };
 
 static void do_ccupdate_local(void *info)
@@ -3956,7 +4006,8 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
        struct ccupdate_struct *new;
        int i;
 
-       new = kzalloc(sizeof(*new), gfp);
+       new = kzalloc(sizeof(*new) + nr_cpu_ids * sizeof(struct array_cache *),
+                     gfp);
        if (!new)
                return -ENOMEM;
 
index f8f5e8e..9f662d7 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2,10 +2,11 @@
  * SLUB: A slab allocator that limits cache line use instead of queuing
  * objects in per cpu and per node lists.
  *
- * The allocator synchronizes using per slab locks and only
- * uses a centralized lock to manage a pool of partial slabs.
+ * The allocator synchronizes using per slab locks or atomic operatios
+ * and only uses a centralized lock to manage a pool of partial slabs.
  *
  * (C) 2007 SGI, Christoph Lameter
+ * (C) 2011 Linux Foundation, Christoph Lameter
  */
 
 #include <linux/mm.h>
 
 /*
  * Lock order:
- *   1. slab_lock(page)
- *   2. slab->list_lock
+ *   1. slub_lock (Global Semaphore)
+ *   2. node->list_lock
+ *   3. slab_lock(page) (Only on some arches and for debugging)
  *
- *   The slab_lock protects operations on the object of a particular
- *   slab and its metadata in the page struct. If the slab lock
- *   has been taken then no allocations nor frees can be performed
- *   on the objects in the slab nor can the slab be added or removed
- *   from the partial or full lists since this would mean modifying
- *   the page_struct of the slab.
+ *   slub_lock
+ *
+ *   The role of the slub_lock is to protect the list of all the slabs
+ *   and to synchronize major metadata changes to slab cache structures.
+ *
+ *   The slab_lock is only used for debugging and on arches that do not
+ *   have the ability to do a cmpxchg_double. It only protects the second
+ *   double word in the page struct. Meaning
+ *     A. page->freelist       -> List of object free in a page
+ *     B. page->counters       -> Counters of objects
+ *     C. page->frozen         -> frozen state
+ *
+ *   If a slab is frozen then it is exempt from list management. It is not
+ *   on any list. The processor that froze the slab is the one who can
+ *   perform list operations on the page. Other processors may put objects
+ *   onto the freelist but the processor that froze the slab is the only
+ *   one that can retrieve the objects from the page's freelist.
  *
  *   The list_lock protects the partial and full list on each node and
  *   the partial slab counter. If taken then no new slabs may be added or
  *   slabs, operations can continue without any centralized lock. F.e.
  *   allocating a long series of objects that fill up slabs does not require
  *   the list lock.
- *
- *   The lock order is sometimes inverted when we are trying to get a slab
- *   off a list. We take the list_lock and then look for a page on the list
- *   to use. While we do that objects in the slabs may be freed. We can
- *   only operate on the slab if we have also taken the slab_lock. So we use
- *   a slab_trylock() on the slab. If trylock was successful then no frees
- *   can occur anymore and we can use the slab for allocations etc. If the
- *   slab_trylock() does not succeed then frees are in progress in the slab and
- *   we must stay away from it for a while since we may cause a bouncing
- *   cacheline if we try to acquire the lock. So go onto the next slab.
- *   If all pages are busy then we may allocate a new slab instead of reusing
- *   a partial slab. A new slab has no one operating on it and thus there is
- *   no danger of cacheline contention.
- *
  *   Interrupts are disabled during allocation and deallocation in order to
  *   make the slab allocator safe to use in the context of an irq. In addition
  *   interrupts are disabled to ensure that the processor does not change
@@ -132,6 +131,9 @@ static inline int kmem_cache_debug(struct kmem_cache *s)
 /* Enable to test recovery from slab corruption on boot */
 #undef SLUB_RESILIENCY_TEST
 
+/* Enable to log cmpxchg failures */
+#undef SLUB_DEBUG_CMPXCHG
+
 /*
  * Mininum number of partial slabs. These will be left on the partial
  * lists even if they are empty. kmem_cache_shrink may reclaim them.
@@ -167,10 +169,11 @@ static inline int kmem_cache_debug(struct kmem_cache *s)
 
 #define OO_SHIFT       16
 #define OO_MASK                ((1 << OO_SHIFT) - 1)
-#define MAX_OBJS_PER_PAGE      65535 /* since page.objects is u16 */
+#define MAX_OBJS_PER_PAGE      32767 /* since page.objects is u15 */
 
 /* Internal SLUB flags */
 #define __OBJECT_POISON                0x80000000UL /* Poison object */
+#define __CMPXCHG_DOUBLE       0x40000000UL /* Use cmpxchg_double */
 
 static int kmem_size = sizeof(struct kmem_cache);
 
@@ -343,11 +346,99 @@ static inline int oo_objects(struct kmem_cache_order_objects x)
        return x.x & OO_MASK;
 }
 
+/*
+ * Per slab locking using the pagelock
+ */
+static __always_inline void slab_lock(struct page *page)
+{
+       bit_spin_lock(PG_locked, &page->flags);
+}
+
+static __always_inline void slab_unlock(struct page *page)
+{
+       __bit_spin_unlock(PG_locked, &page->flags);
+}
+
+/* Interrupts must be disabled (for the fallback code to work right) */
+static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct page *page,
+               void *freelist_old, unsigned long counters_old,
+               void *freelist_new, unsigned long counters_new,
+               const char *n)
+{
+       VM_BUG_ON(!irqs_disabled());
+#ifdef CONFIG_CMPXCHG_DOUBLE
+       if (s->flags & __CMPXCHG_DOUBLE) {
+               if (cmpxchg_double(&page->freelist,
+                       freelist_old, counters_old,
+                       freelist_new, counters_new))
+               return 1;
+       } else
+#endif
+       {
+               slab_lock(page);
+               if (page->freelist == freelist_old && page->counters == counters_old) {
+                       page->freelist = freelist_new;
+                       page->counters = counters_new;
+                       slab_unlock(page);
+                       return 1;
+               }
+               slab_unlock(page);
+       }
+
+       cpu_relax();
+       stat(s, CMPXCHG_DOUBLE_FAIL);
+
+#ifdef SLUB_DEBUG_CMPXCHG
+       printk(KERN_INFO "%s %s: cmpxchg double redo ", n, s->name);
+#endif
+
+       return 0;
+}
+
+static inline bool cmpxchg_double_slab(struct kmem_cache *s, struct page *page,
+               void *freelist_old, unsigned long counters_old,
+               void *freelist_new, unsigned long counters_new,
+               const char *n)
+{
+#ifdef CONFIG_CMPXCHG_DOUBLE
+       if (s->flags & __CMPXCHG_DOUBLE) {
+               if (cmpxchg_double(&page->freelist,
+                       freelist_old, counters_old,
+                       freelist_new, counters_new))
+               return 1;
+       } else
+#endif
+       {
+               unsigned long flags;
+
+               local_irq_save(flags);
+               slab_lock(page);
+               if (page->freelist == freelist_old && page->counters == counters_old) {
+                       page->freelist = freelist_new;
+                       page->counters = counters_new;
+                       slab_unlock(page);
+                       local_irq_restore(flags);
+                       return 1;
+               }
+               slab_unlock(page);
+               local_irq_restore(flags);
+       }
+
+       cpu_relax();
+       stat(s, CMPXCHG_DOUBLE_FAIL);
+
+#ifdef SLUB_DEBUG_CMPXCHG
+       printk(KERN_INFO "%s %s: cmpxchg double redo ", n, s->name);
+#endif
+
+       return 0;
+}
+
 #ifdef CONFIG_SLUB_DEBUG
 /*
  * Determine a map of object in use on a page.
  *
- * Slab lock or node listlock must be held to guarantee that the page does
+ * Node listlock must be held to guarantee that the page does
  * not vanish from under us.
  */
 static void get_map(struct kmem_cache *s, struct page *page, unsigned long *map)
@@ -610,7 +701,7 @@ static u8 *check_bytes(u8 *start, u8 value, unsigned int bytes)
                return check_bytes8(start, value, bytes);
 
        value64 = value | value << 8 | value << 16 | value << 24;
-       value64 = value64 | value64 << 32;
+       value64 = (value64 & 0xffffffff) | value64 << 32;
        prefix = 8 - ((unsigned long)start) % 8;
 
        if (prefix) {
@@ -838,10 +929,11 @@ static int check_slab(struct kmem_cache *s, struct page *page)
 static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
 {
        int nr = 0;
-       void *fp = page->freelist;
+       void *fp;
        void *object = NULL;
        unsigned long max_objects;
 
+       fp = page->freelist;
        while (fp && nr <= page->objects) {
                if (fp == search)
                        return 1;
@@ -946,26 +1038,27 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x)
 
 /*
  * Tracking of fully allocated slabs for debugging purposes.
+ *
+ * list_lock must be held.
  */
-static void add_full(struct kmem_cache_node *n, struct page *page)
+static void add_full(struct kmem_cache *s,
+       struct kmem_cache_node *n, struct page *page)
 {
-       spin_lock(&n->list_lock);
+       if (!(s->flags & SLAB_STORE_USER))
+               return;
+
        list_add(&page->lru, &n->full);
-       spin_unlock(&n->list_lock);
 }
 
+/*
+ * list_lock must be held.
+ */
 static void remove_full(struct kmem_cache *s, struct page *page)
 {
-       struct kmem_cache_node *n;
-
        if (!(s->flags & SLAB_STORE_USER))
                return;
 
-       n = get_node(s, page_to_nid(page));
-
-       spin_lock(&n->list_lock);
        list_del(&page->lru);
-       spin_unlock(&n->list_lock);
 }
 
 /* Tracking of the number of slabs for debugging purposes */
@@ -1021,11 +1114,6 @@ static noinline int alloc_debug_processing(struct kmem_cache *s, struct page *pa
        if (!check_slab(s, page))
                goto bad;
 
-       if (!on_freelist(s, page, object)) {
-               object_err(s, page, object, "Object already allocated");
-               goto bad;
-       }
-
        if (!check_valid_pointer(s, page, object)) {
                object_err(s, page, object, "Freelist Pointer check fails");
                goto bad;
@@ -1058,6 +1146,12 @@ bad:
 static noinline int free_debug_processing(struct kmem_cache *s,
                 struct page *page, void *object, unsigned long addr)
 {
+       unsigned long flags;
+       int rc = 0;
+
+       local_irq_save(flags);
+       slab_lock(page);
+
        if (!check_slab(s, page))
                goto fail;
 
@@ -1072,7 +1166,7 @@ static noinline int free_debug_processing(struct kmem_cache *s,
        }
 
        if (!check_object(s, page, object, SLUB_RED_ACTIVE))
-               return 0;
+               goto out;
 
        if (unlikely(s != page->slab)) {
                if (!PageSlab(page)) {
@@ -1089,18 +1183,19 @@ static noinline int free_debug_processing(struct kmem_cache *s,
                goto fail;
        }
 
-       /* Special debug activities for freeing objects */
-       if (!PageSlubFrozen(page) && !page->freelist)
-               remove_full(s, page);
        if (s->flags & SLAB_STORE_USER)
                set_track(s, object, TRACK_FREE, addr);
        trace(s, page, object, 0);
        init_object(s, object, SLUB_RED_INACTIVE);
-       return 1;
+       rc = 1;
+out:
+       slab_unlock(page);
+       local_irq_restore(flags);
+       return rc;
 
 fail:
        slab_fix(s, "Object at 0x%p not freed", object);
-       return 0;
+       goto out;
 }
 
 static int __init setup_slub_debug(char *str)
@@ -1200,7 +1295,9 @@ static inline int slab_pad_check(struct kmem_cache *s, struct page *page)
                        { return 1; }
 static inline int check_object(struct kmem_cache *s, struct page *page,
                        void *object, u8 val) { return 1; }
-static inline void add_full(struct kmem_cache_node *n, struct page *page) {}
+static inline void add_full(struct kmem_cache *s, struct kmem_cache_node *n,
+                                       struct page *page) {}
+static inline void remove_full(struct kmem_cache *s, struct page *page) {}
 static inline unsigned long kmem_cache_flags(unsigned long objsize,
        unsigned long flags, const char *name,
        void (*ctor)(void *))
@@ -1252,6 +1349,11 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
        struct kmem_cache_order_objects oo = s->oo;
        gfp_t alloc_gfp;
 
+       flags &= gfp_allowed_mask;
+
+       if (flags & __GFP_WAIT)
+               local_irq_enable();
+
        flags |= s->allocflags;
 
        /*
@@ -1268,12 +1370,17 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
                 * Try a lower order alloc if possible
                 */
                page = alloc_slab_page(flags, node, oo);
-               if (!page)
-                       return NULL;
 
-               stat(s, ORDER_FALLBACK);
+               if (page)
+                       stat(s, ORDER_FALLBACK);
        }
 
+       if (flags & __GFP_WAIT)
+               local_irq_disable();
+
+       if (!page)
+               return NULL;
+
        if (kmemcheck_enabled
                && !(s->flags & (SLAB_NOTRACK | DEBUG_DEFAULT_FLAGS))) {
                int pages = 1 << oo_order(oo);
@@ -1341,6 +1448,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
 
        page->freelist = start;
        page->inuse = 0;
+       page->frozen = 1;
 out:
        return page;
 }
@@ -1418,77 +1526,87 @@ static void discard_slab(struct kmem_cache *s, struct page *page)
 }
 
 /*
- * Per slab locking using the pagelock
- */
-static __always_inline void slab_lock(struct page *page)
-{
-       bit_spin_lock(PG_locked, &page->flags);
-}
-
-static __always_inline void slab_unlock(struct page *page)
-{
-       __bit_spin_unlock(PG_locked, &page->flags);
-}
-
-static __always_inline int slab_trylock(struct page *page)
-{
-       int rc = 1;
-
-       rc = bit_spin_trylock(PG_locked, &page->flags);
-       return rc;
-}
-
-/*
- * Management of partially allocated slabs
+ * Management of partially allocated slabs.
+ *
+ * list_lock must be held.
  */
-static void add_partial(struct kmem_cache_node *n,
+static inline void add_partial(struct kmem_cache_node *n,
                                struct page *page, int tail)
 {
-       spin_lock(&n->list_lock);
        n->nr_partial++;
        if (tail)
                list_add_tail(&page->lru, &n->partial);
        else
                list_add(&page->lru, &n->partial);
-       spin_unlock(&n->list_lock);
 }
 
-static inline void __remove_partial(struct kmem_cache_node *n,
+/*
+ * list_lock must be held.
+ */
+static inline void remove_partial(struct kmem_cache_node *n,
                                        struct page *page)
 {
        list_del(&page->lru);
        n->nr_partial--;
 }
 
-static void remove_partial(struct kmem_cache *s, struct page *page)
-{
-       struct kmem_cache_node *n = get_node(s, page_to_nid(page));
-
-       spin_lock(&n->list_lock);
-       __remove_partial(n, page);
-       spin_unlock(&n->list_lock);
-}
-
 /*
- * Lock slab and remove from the partial list.
+ * Lock slab, remove from the partial list and put the object into the
+ * per cpu freelist.
  *
  * Must hold list_lock.
  */
-static inline int lock_and_freeze_slab(struct kmem_cache_node *n,
-                                                       struct page *page)
+static inline int acquire_slab(struct kmem_cache *s,
+               struct kmem_cache_node *n, struct page *page)
 {
-       if (slab_trylock(page)) {
-               __remove_partial(n, page);
-               __SetPageSlubFrozen(page);
+       void *freelist;
+       unsigned long counters;
+       struct page new;
+
+       /*
+        * Zap the freelist and set the frozen bit.
+        * The old freelist is the list of objects for the
+        * per cpu allocation list.
+        */
+       do {
+               freelist = page->freelist;
+               counters = page->counters;
+               new.counters = counters;
+               new.inuse = page->objects;
+
+               VM_BUG_ON(new.frozen);
+               new.frozen = 1;
+
+       } while (!__cmpxchg_double_slab(s, page,
+                       freelist, counters,
+                       NULL, new.counters,
+                       "lock and freeze"));
+
+       remove_partial(n, page);
+
+       if (freelist) {
+               /* Populate the per cpu freelist */
+               this_cpu_write(s->cpu_slab->freelist, freelist);
+               this_cpu_write(s->cpu_slab->page, page);
+               this_cpu_write(s->cpu_slab->node, page_to_nid(page));
                return 1;
+       } else {
+               /*
+                * Slab page came from the wrong list. No object to allocate
+                * from. Put it onto the correct list and continue partial
+                * scan.
+                */
+               printk(KERN_ERR "SLUB: %s : Page without available objects on"
+                       " partial list\n", s->name);
+               return 0;
        }
-       return 0;
 }
 
 /*
  * Try to allocate a partial slab from a specific node.
  */
-static struct page *get_partial_node(struct kmem_cache_node *n)
+static struct page *get_partial_node(struct kmem_cache *s,
+                                       struct kmem_cache_node *n)
 {
        struct page *page;
 
@@ -1503,7 +1621,7 @@ static struct page *get_partial_node(struct kmem_cache_node *n)
 
        spin_lock(&n->list_lock);
        list_for_each_entry(page, &n->partial, lru)
-               if (lock_and_freeze_slab(n, page))
+               if (acquire_slab(s, n, page))
                        goto out;
        page = NULL;
 out:
@@ -1554,7 +1672,7 @@ static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags)
 
                if (n && cpuset_zone_allowed_hardwall(zone, flags) &&
                                n->nr_partial > s->min_partial) {
-                       page = get_partial_node(n);
+                       page = get_partial_node(s, n);
                        if (page) {
                                put_mems_allowed();
                                return page;
@@ -1574,60 +1692,13 @@ static struct page *get_partial(struct kmem_cache *s, gfp_t flags, int node)
        struct page *page;
        int searchnode = (node == NUMA_NO_NODE) ? numa_node_id() : node;
 
-       page = get_partial_node(get_node(s, searchnode));
+       page = get_partial_node(s, get_node(s, searchnode));
        if (page || node != NUMA_NO_NODE)
                return page;
 
        return get_any_partial(s, flags);
 }
 
-/*
- * Move a page back to the lists.
- *
- * Must be called with the slab lock held.
- *
- * On exit the slab lock will have been dropped.
- */
-static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
-       __releases(bitlock)
-{
-       struct kmem_cache_node *n = get_node(s, page_to_nid(page));
-
-       __ClearPageSlubFrozen(page);
-       if (page->inuse) {
-
-               if (page->freelist) {
-                       add_partial(n, page, tail);
-                       stat(s, tail ? DEACTIVATE_TO_TAIL : DEACTIVATE_TO_HEAD);
-               } else {
-                       stat(s, DEACTIVATE_FULL);
-                       if (kmem_cache_debug(s) && (s->flags & SLAB_STORE_USER))
-                               add_full(n, page);
-               }
-               slab_unlock(page);
-       } else {
-               stat(s, DEACTIVATE_EMPTY);
-               if (n->nr_partial < s->min_partial) {
-                       /*
-                        * Adding an empty slab to the partial slabs in order
-                        * to avoid page allocator overhead. This slab needs
-                        * to come after the other slabs with objects in
-                        * so that the others get filled first. That way the
-                        * size of the partial list stays small.
-                        *
-                        * kmem_cache_shrink can reclaim any empty slabs from
-                        * the partial list.
-                        */
-                       add_partial(n, page, 1);
-                       slab_unlock(page);
-               } else {
-                       slab_unlock(page);
-                       stat(s, FREE_SLAB);
-                       discard_slab(s, page);
-               }
-       }
-}
-
 #ifdef CONFIG_PREEMPT
 /*
  * Calculate the next globally unique transaction for disambiguiation
@@ -1694,45 +1765,164 @@ void init_kmem_cache_cpus(struct kmem_cache *s)
        for_each_possible_cpu(cpu)
                per_cpu_ptr(s->cpu_slab, cpu)->tid = init_tid(cpu);
 }
+/*
+ * Remove the cpu slab
+ */
+
 /*
  * Remove the cpu slab
  */
 static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
-       __releases(bitlock)
 {
+       enum slab_modes { M_NONE, M_PARTIAL, M_FULL, M_FREE };
        struct page *page = c->page;
-       int tail = 1;
-
-       if (page->freelist)
+       struct kmem_cache_node *n = get_node(s, page_to_nid(page));
+       int lock = 0;
+       enum slab_modes l = M_NONE, m = M_NONE;
+       void *freelist;
+       void *nextfree;
+       int tail = 0;
+       struct page new;
+       struct page old;
+
+       if (page->freelist) {
                stat(s, DEACTIVATE_REMOTE_FREES);
+               tail = 1;
+       }
+
+       c->tid = next_tid(c->tid);
+       c->page = NULL;
+       freelist = c->freelist;
+       c->freelist = NULL;
+
        /*
-        * Merge cpu freelist into slab freelist. Typically we get here
-        * because both freelists are empty. So this is unlikely
-        * to occur.
+        * Stage one: Free all available per cpu objects back
+        * to the page freelist while it is still frozen. Leave the
+        * last one.
+        *
+        * There is no need to take the list->lock because the page
+        * is still frozen.
+        */
+       while (freelist && (nextfree = get_freepointer(s, freelist))) {
+               void *prior;
+               unsigned long counters;
+
+               do {
+                       prior = page->freelist;
+                       counters = page->counters;
+                       set_freepointer(s, freelist, prior);
+                       new.counters = counters;
+                       new.inuse--;
+                       VM_BUG_ON(!new.frozen);
+
+               } while (!__cmpxchg_double_slab(s, page,
+                       prior, counters,
+                       freelist, new.counters,
+                       "drain percpu freelist"));
+
+               freelist = nextfree;
+       }
+
+       /*
+        * Stage two: Ensure that the page is unfrozen while the
+        * list presence reflects the actual number of objects
+        * during unfreeze.
+        *
+        * We setup the list membership and then perform a cmpxchg
+        * with the count. If there is a mismatch then the page
+        * is not unfrozen but the page is on the wrong list.
+        *
+        * Then we restart the process which may have to remove
+        * the page from the list that we just put it on again
+        * because the number of objects in the slab may have
+        * changed.
         */
-       while (unlikely(c->freelist)) {
-               void **object;
+redo:
 
-               tail = 0;       /* Hot objects. Put the slab first */
+       old.freelist = page->freelist;
+       old.counters = page->counters;
+       VM_BUG_ON(!old.frozen);
 
-               /* Retrieve object from cpu_freelist */
-               object = c->freelist;
-               c->freelist = get_freepointer(s, c->freelist);
+       /* Determine target state of the slab */
+       new.counters = old.counters;
+       if (freelist) {
+               new.inuse--;
+               set_freepointer(s, freelist, old.freelist);
+               new.freelist = freelist;
+       } else
+               new.freelist = old.freelist;
 
-               /* And put onto the regular freelist */
-               set_freepointer(s, object, page->freelist);
-               page->freelist = object;
-               page->inuse--;
+       new.frozen = 0;
+
+       if (!new.inuse && n->nr_partial > s->min_partial)
+               m = M_FREE;
+       else if (new.freelist) {
+               m = M_PARTIAL;
+               if (!lock) {
+                       lock = 1;
+                       /*
+                        * Taking the spinlock removes the possiblity
+                        * that acquire_slab() will see a slab page that
+                        * is frozen
+                        */
+                       spin_lock(&n->list_lock);
+               }
+       } else {
+               m = M_FULL;
+               if (kmem_cache_debug(s) && !lock) {
+                       lock = 1;
+                       /*
+                        * This also ensures that the scanning of full
+                        * slabs from diagnostic functions will not see
+                        * any frozen slabs.
+                        */
+                       spin_lock(&n->list_lock);
+               }
+       }
+
+       if (l != m) {
+
+               if (l == M_PARTIAL)
+
+                       remove_partial(n, page);
+
+               else if (l == M_FULL)
+
+                       remove_full(s, page);
+
+               if (m == M_PARTIAL) {
+
+                       add_partial(n, page, tail);
+                       stat(s, tail ? DEACTIVATE_TO_TAIL : DEACTIVATE_TO_HEAD);
+
+               } else if (m == M_FULL) {
+
+                       stat(s, DEACTIVATE_FULL);
+                       add_full(s, n, page);
+
+               }
+       }
+
+       l = m;
+       if (!__cmpxchg_double_slab(s, page,
+                               old.freelist, old.counters,
+                               new.freelist, new.counters,
+                               "unfreezing slab"))
+               goto redo;
+
+       if (lock)
+               spin_unlock(&n->list_lock);
+
+       if (m == M_FREE) {
+               stat(s, DEACTIVATE_EMPTY);
+               discard_slab(s, page);
+               stat(s, FREE_SLAB);
        }
-       c->page = NULL;
-       c->tid = next_tid(c->tid);
-       unfreeze_slab(s, page, tail);
 }
 
 static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
 {
        stat(s, CPUSLAB_FLUSH);
-       slab_lock(c->page);
        deactivate_slab(s, c);
 }
 
@@ -1861,6 +2051,8 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
        void **object;
        struct page *page;
        unsigned long flags;
+       struct page new;
+       unsigned long counters;
 
        local_irq_save(flags);
 #ifdef CONFIG_PREEMPT
@@ -1879,72 +2071,97 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
        if (!page)
                goto new_slab;
 
-       slab_lock(page);
-       if (unlikely(!node_match(c, node)))
-               goto another_slab;
+       if (unlikely(!node_match(c, node))) {
+               stat(s, ALLOC_NODE_MISMATCH);
+               deactivate_slab(s, c);
+               goto new_slab;
+       }
+
+       stat(s, ALLOC_SLOWPATH);
+
+       do {
+               object = page->freelist;
+               counters = page->counters;
+               new.counters = counters;
+               VM_BUG_ON(!new.frozen);
+
+               /*
+                * If there is no object left then we use this loop to
+                * deactivate the slab which is simple since no objects
+                * are left in the slab and therefore we do not need to
+                * put the page back onto the partial list.
+                *
+                * If there are objects left then we retrieve them
+                * and use them to refill the per cpu queue.
+               */
+
+               new.inuse = page->objects;
+               new.frozen = object != NULL;
+
+       } while (!__cmpxchg_double_slab(s, page,
+                       object, counters,
+                       NULL, new.counters,
+                       "__slab_alloc"));
+
+       if (unlikely(!object)) {
+               c->page = NULL;
+               stat(s, DEACTIVATE_BYPASS);
+               goto new_slab;
+       }
 
        stat(s, ALLOC_REFILL);
 
 load_freelist:
-       object = page->freelist;
-       if (unlikely(!object))
-               goto another_slab;
-       if (kmem_cache_debug(s))
-               goto debug;
-
+       VM_BUG_ON(!page->frozen);
        c->freelist = get_freepointer(s, object);
-       page->inuse = page->objects;
-       page->freelist = NULL;
-
-       slab_unlock(page);
        c->tid = next_tid(c->tid);
        local_irq_restore(flags);
-       stat(s, ALLOC_SLOWPATH);
        return object;
 
-another_slab:
-       deactivate_slab(s, c);
-
 new_slab:
        page = get_partial(s, gfpflags, node);
        if (page) {
                stat(s, ALLOC_FROM_PARTIAL);
-               c->node = page_to_nid(page);
-               c->page = page;
+               object = c->freelist;
+
+               if (kmem_cache_debug(s))
+                       goto debug;
                goto load_freelist;
        }
 
-       gfpflags &= gfp_allowed_mask;
-       if (gfpflags & __GFP_WAIT)
-               local_irq_enable();
-
        page = new_slab(s, gfpflags, node);
 
-       if (gfpflags & __GFP_WAIT)
-               local_irq_disable();
-
        if (page) {
                c = __this_cpu_ptr(s->cpu_slab);
-               stat(s, ALLOC_SLAB);
                if (c->page)
                        flush_slab(s, c);
 
-               slab_lock(page);
-               __SetPageSlubFrozen(page);
+               /*
+                * No other reference to the page yet so we can
+                * muck around with it freely without cmpxchg
+                */
+               object = page->freelist;
+               page->freelist = NULL;
+               page->inuse = page->objects;
+
+               stat(s, ALLOC_SLAB);
                c->node = page_to_nid(page);
                c->page = page;
+
+               if (kmem_cache_debug(s))
+                       goto debug;
                goto load_freelist;
        }
        if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit())
                slab_out_of_memory(s, gfpflags, node);
        local_irq_restore(flags);
        return NULL;
+
 debug:
-       if (!alloc_debug_processing(s, page, object, addr))
-               goto another_slab;
+       if (!object || !alloc_debug_processing(s, page, object, addr))
+               goto new_slab;
 
-       page->inuse++;
-       page->freelist = get_freepointer(s, object);
+       c->freelist = get_freepointer(s, object);
        deactivate_slab(s, c);
        c->page = NULL;
        c->node = NUMA_NO_NODE;
@@ -2096,52 +2313,89 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 {
        void *prior;
        void **object = (void *)x;
-       unsigned long flags;
+       int was_frozen;
+       int inuse;
+       struct page new;
+       unsigned long counters;
+       struct kmem_cache_node *n = NULL;
+       unsigned long uninitialized_var(flags);
 
-       local_irq_save(flags);
-       slab_lock(page);
        stat(s, FREE_SLOWPATH);
 
        if (kmem_cache_debug(s) && !free_debug_processing(s, page, x, addr))
-               goto out_unlock;
+               return;
 
-       prior = page->freelist;
-       set_freepointer(s, object, prior);
-       page->freelist = object;
-       page->inuse--;
+       do {
+               prior = page->freelist;
+               counters = page->counters;
+               set_freepointer(s, object, prior);
+               new.counters = counters;
+               was_frozen = new.frozen;
+               new.inuse--;
+               if ((!new.inuse || !prior) && !was_frozen && !n) {
+                        n = get_node(s, page_to_nid(page));
+                       /*
+                        * Speculatively acquire the list_lock.
+                        * If the cmpxchg does not succeed then we may
+                        * drop the list_lock without any processing.
+                        *
+                        * Otherwise the list_lock will synchronize with
+                        * other processors updating the list of slabs.
+                        */
+                        spin_lock_irqsave(&n->list_lock, flags);
+               }
+               inuse = new.inuse;
 
-       if (unlikely(PageSlubFrozen(page))) {
-               stat(s, FREE_FROZEN);
-               goto out_unlock;
-       }
+       } while (!cmpxchg_double_slab(s, page,
+               prior, counters,
+               object, new.counters,
+               "__slab_free"));
 
-       if (unlikely(!page->inuse))
-               goto slab_empty;
+       if (likely(!n)) {
+                /*
+                * The list lock was not taken therefore no list
+                * activity can be necessary.
+                */
+                if (was_frozen)
+                        stat(s, FREE_FROZEN);
+                return;
+        }
 
        /*
-        * Objects left in the slab. If it was not on the partial list before
-        * then add it.
+        * was_frozen may have been set after we acquired the list_lock in
+        * an earlier loop. So we need to check it here again.
         */
-       if (unlikely(!prior)) {
-               add_partial(get_node(s, page_to_nid(page)), page, 1);
-               stat(s, FREE_ADD_PARTIAL);
-       }
+       if (was_frozen)
+               stat(s, FREE_FROZEN);
+       else {
+               if (unlikely(!inuse && n->nr_partial > s->min_partial))
+                        goto slab_empty;
 
-out_unlock:
-       slab_unlock(page);
-       local_irq_restore(flags);
+               /*
+                * Objects left in the slab. If it was not on the partial list before
+                * then add it.
+                */
+               if (unlikely(!prior)) {
+                       remove_full(s, page);
+                       add_partial(n, page, 0);
+                       stat(s, FREE_ADD_PARTIAL);
+               }
+       }
+       spin_unlock_irqrestore(&n->list_lock, flags);
        return;
 
 slab_empty:
        if (prior) {
                /*
-                * Slab still on the partial list.
+                * Slab on the partial list.
                 */
-               remove_partial(s, page);
+               remove_partial(n, page);
                stat(s, FREE_REMOVE_PARTIAL);
-       }
-       slab_unlock(page);
-       local_irq_restore(flags);
+       } else
+               /* Slab must be on the full list */
+               remove_full(s, page);
+
+       spin_unlock_irqrestore(&n->list_lock, flags);
        stat(s, FREE_SLAB);
        discard_slab(s, page);
 }
@@ -2415,7 +2669,6 @@ static void early_kmem_cache_node_alloc(int node)
 {
        struct page *page;
        struct kmem_cache_node *n;
-       unsigned long flags;
 
        BUG_ON(kmem_cache_node->size < sizeof(struct kmem_cache_node));
 
@@ -2433,6 +2686,7 @@ static void early_kmem_cache_node_alloc(int node)
        BUG_ON(!n);
        page->freelist = get_freepointer(kmem_cache_node, n);
        page->inuse++;
+       page->frozen = 0;
        kmem_cache_node->node[node] = n;
 #ifdef CONFIG_SLUB_DEBUG
        init_object(kmem_cache_node, n, SLUB_RED_ACTIVE);
@@ -2441,14 +2695,7 @@ static void early_kmem_cache_node_alloc(int node)
        init_kmem_cache_node(n, kmem_cache_node);
        inc_slabs_node(kmem_cache_node, node, page->objects);
 
-       /*
-        * lockdep requires consistent irq usage for each lock
-        * so even though there cannot be a race this early in
-        * the boot sequence, we still disable irqs.
-        */
-       local_irq_save(flags);
        add_partial(n, page, 0);
-       local_irq_restore(flags);
 }
 
 static void free_kmem_cache_nodes(struct kmem_cache *s)
@@ -2654,6 +2901,12 @@ static int kmem_cache_open(struct kmem_cache *s,
                }
        }
 
+#ifdef CONFIG_CMPXCHG_DOUBLE
+       if (system_has_cmpxchg_double() && (s->flags & SLAB_DEBUG_FLAGS) == 0)
+               /* Enable fast mode */
+               s->flags |= __CMPXCHG_DOUBLE;
+#endif
+
        /*
         * The larger the object size is, the more pages we want on the partial
         * list to avoid pounding the page allocator excessively.
@@ -2726,7 +2979,7 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
        spin_lock_irqsave(&n->list_lock, flags);
        list_for_each_entry_safe(page, h, &n->partial, lru) {
                if (!page->inuse) {
-                       __remove_partial(n, page);
+                       remove_partial(n, page);
                        discard_slab(s, page);
                } else {
                        list_slab_objects(s, page,
@@ -3094,14 +3347,8 @@ int kmem_cache_shrink(struct kmem_cache *s)
                 * list_lock. page->inuse here is the upper limit.
                 */
                list_for_each_entry_safe(page, t, &n->partial, lru) {
-                       if (!page->inuse && slab_trylock(page)) {
-                               /*
-                                * Must hold slab lock here because slab_free
-                                * may have freed the last object and be
-                                * waiting to release the slab.
-                                */
-                               __remove_partial(n, page);
-                               slab_unlock(page);
+                       if (!page->inuse) {
+                               remove_partial(n, page);
                                discard_slab(s, page);
                        } else {
                                list_move(&page->lru,
@@ -3689,12 +3936,9 @@ static int validate_slab(struct kmem_cache *s, struct page *page,
 static void validate_slab_slab(struct kmem_cache *s, struct page *page,
                                                unsigned long *map)
 {
-       if (slab_trylock(page)) {
-               validate_slab(s, page, map);
-               slab_unlock(page);
-       } else
-               printk(KERN_INFO "SLUB %s: Skipped busy slab 0x%p\n",
-                       s->name, page);
+       slab_lock(page);
+       validate_slab(s, page, map);
+       slab_unlock(page);
 }
 
 static int validate_slab_node(struct kmem_cache *s,
@@ -4342,8 +4586,10 @@ static ssize_t sanity_checks_store(struct kmem_cache *s,
                                const char *buf, size_t length)
 {
        s->flags &= ~SLAB_DEBUG_FREE;
-       if (buf[0] == '1')
+       if (buf[0] == '1') {
+               s->flags &= ~__CMPXCHG_DOUBLE;
                s->flags |= SLAB_DEBUG_FREE;
+       }
        return length;
 }
 SLAB_ATTR(sanity_checks);
@@ -4357,8 +4603,10 @@ static ssize_t trace_store(struct kmem_cache *s, const char *buf,
                                                        size_t length)
 {
        s->flags &= ~SLAB_TRACE;
-       if (buf[0] == '1')
+       if (buf[0] == '1') {
+               s->flags &= ~__CMPXCHG_DOUBLE;
                s->flags |= SLAB_TRACE;
+       }
        return length;
 }
 SLAB_ATTR(trace);
@@ -4375,8 +4623,10 @@ static ssize_t red_zone_store(struct kmem_cache *s,
                return -EBUSY;
 
        s->flags &= ~SLAB_RED_ZONE;
-       if (buf[0] == '1')
+       if (buf[0] == '1') {
+               s->flags &= ~__CMPXCHG_DOUBLE;
                s->flags |= SLAB_RED_ZONE;
+       }
        calculate_sizes(s, -1);
        return length;
 }
@@ -4394,8 +4644,10 @@ static ssize_t poison_store(struct kmem_cache *s,
                return -EBUSY;
 
        s->flags &= ~SLAB_POISON;
-       if (buf[0] == '1')
+       if (buf[0] == '1') {
+               s->flags &= ~__CMPXCHG_DOUBLE;
                s->flags |= SLAB_POISON;
+       }
        calculate_sizes(s, -1);
        return length;
 }
@@ -4413,8 +4665,10 @@ static ssize_t store_user_store(struct kmem_cache *s,
                return -EBUSY;
 
        s->flags &= ~SLAB_STORE_USER;
-       if (buf[0] == '1')
+       if (buf[0] == '1') {
+               s->flags &= ~__CMPXCHG_DOUBLE;
                s->flags |= SLAB_STORE_USER;
+       }
        calculate_sizes(s, -1);
        return length;
 }
@@ -4579,6 +4833,7 @@ STAT_ATTR(FREE_REMOVE_PARTIAL, free_remove_partial);
 STAT_ATTR(ALLOC_FROM_PARTIAL, alloc_from_partial);
 STAT_ATTR(ALLOC_SLAB, alloc_slab);
 STAT_ATTR(ALLOC_REFILL, alloc_refill);
+STAT_ATTR(ALLOC_NODE_MISMATCH, alloc_node_mismatch);
 STAT_ATTR(FREE_SLAB, free_slab);
 STAT_ATTR(CPUSLAB_FLUSH, cpuslab_flush);
 STAT_ATTR(DEACTIVATE_FULL, deactivate_full);
@@ -4586,7 +4841,10 @@ STAT_ATTR(DEACTIVATE_EMPTY, deactivate_empty);
 STAT_ATTR(DEACTIVATE_TO_HEAD, deactivate_to_head);
 STAT_ATTR(DEACTIVATE_TO_TAIL, deactivate_to_tail);
 STAT_ATTR(DEACTIVATE_REMOTE_FREES, deactivate_remote_frees);
+STAT_ATTR(DEACTIVATE_BYPASS, deactivate_bypass);
 STAT_ATTR(ORDER_FALLBACK, order_fallback);
+STAT_ATTR(CMPXCHG_DOUBLE_CPU_FAIL, cmpxchg_double_cpu_fail);
+STAT_ATTR(CMPXCHG_DOUBLE_FAIL, cmpxchg_double_fail);
 #endif
 
 static struct attribute *slab_attrs[] = {
@@ -4636,6 +4894,7 @@ static struct attribute *slab_attrs[] = {
        &alloc_from_partial_attr.attr,
        &alloc_slab_attr.attr,
        &alloc_refill_attr.attr,
+       &alloc_node_mismatch_attr.attr,
        &free_slab_attr.attr,
        &cpuslab_flush_attr.attr,
        &deactivate_full_attr.attr,
@@ -4643,7 +4902,10 @@ static struct attribute *slab_attrs[] = {
        &deactivate_to_head_attr.attr,
        &deactivate_to_tail_attr.attr,
        &deactivate_remote_frees_attr.attr,
+       &deactivate_bypass_attr.attr,
        &order_fallback_attr.attr,
+       &cmpxchg_double_fail_attr.attr,
+       &cmpxchg_double_cpu_fail_attr.attr,
 #endif
 #ifdef CONFIG_FAILSLAB
        &failslab_attr.attr,
index 1b8c339..17bc224 100644 (file)
@@ -1924,20 +1924,24 @@ static unsigned long read_swap_header(struct swap_info_struct *p,
 
        /*
         * Find out how many pages are allowed for a single swap
-        * device. There are two limiting factors: 1) the number of
-        * bits for the swap offset in the swp_entry_t type and
-        * 2) the number of bits in the a swap pte as defined by
-        * the different architectures. In order to find the
-        * largest possible bit mask a swap entry with swap type 0
+        * device. There are three limiting factors: 1) the number
+        * of bits for the swap offset in the swp_entry_t type, and
+        * 2) the number of bits in the swap pte as defined by the
+        * the different architectures, and 3) the number of free bits
+        * in an exceptional radix_tree entry. In order to find the
+        * largest possible bit mask, a swap entry with swap type 0
         * and swap offset ~0UL is created, encoded to a swap pte,
-        * decoded to a swp_entry_t again and finally the swap
+        * decoded to a swp_entry_t again, and finally the swap
         * offset is extracted. This will mask all the bits from
         * the initial ~0UL mask that can't be encoded in either
         * the swp_entry_t or the architecture definition of a
-        * swap pte.
+        * swap pte.  Then the same is done for a radix_tree entry.
         */
        maxpages = swp_offset(pte_to_swp_entry(
-                       swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1;
+                       swp_entry_to_pte(swp_entry(0, ~0UL))));
+       maxpages = swp_offset(radix_to_swp_entry(
+                       swp_to_radix_entry(swp_entry(0, maxpages)))) + 1;
+
        if (maxpages > swap_header->info.last_page) {
                maxpages = swap_header->info.last_page + 1;
                /* p->max is an unsigned int: don't overflow it */
index 232eb27..b40ac6d 100644 (file)
@@ -336,6 +336,14 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
        unsigned long count = 0;
        int i;
 
+       /*
+        * Note: this function may get called on a shmem/tmpfs mapping:
+        * pagevec_lookup() might then return 0 prematurely (because it
+        * got a gangful of swap entries); but it's hardly worth worrying
+        * about - it can rarely have anything to free from such a mapping
+        * (most pages are dirty), and already skips over any difficulties.
+        */
+
        pagevec_init(&pvec, 0);
        while (index <= end && pagevec_lookup(&pvec, mapping, index,
                        min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
index 1610295..070bf44 100644 (file)
@@ -553,7 +553,7 @@ static void garp_release_port(struct net_device *dev)
                if (rtnl_dereference(port->applicants[i]))
                        return;
        }
-       rcu_assign_pointer(dev->garp_port, NULL);
+       RCU_INIT_POINTER(dev->garp_port, NULL);
        kfree_rcu(port, rcu);
 }
 
@@ -605,7 +605,7 @@ void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl
 
        ASSERT_RTNL();
 
-       rcu_assign_pointer(port->applicants[appl->type], NULL);
+       RCU_INIT_POINTER(port->applicants[appl->type], NULL);
 
        /* Delete timer and generate a final TRANSMIT_PDU event to flush out
         * all pending messages before the applicant is gone. */
index 978c30b..0e136ef 100644 (file)
@@ -88,9 +88,9 @@ void stp_proto_unregister(const struct stp_proto *proto)
 {
        mutex_lock(&stp_proto_mutex);
        if (is_zero_ether_addr(proto->group_address))
-               rcu_assign_pointer(stp_proto, NULL);
+               RCU_INIT_POINTER(stp_proto, NULL);
        else
-               rcu_assign_pointer(garp_protos[proto->group_address[5] -
+               RCU_INIT_POINTER(garp_protos[proto->group_address[5] -
                                               GARP_ADDR_MIN], NULL);
        synchronize_rcu();
 
index 8970ba1..5471628 100644 (file)
@@ -133,7 +133,7 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
        if (grp->nr_vlans == 0) {
                vlan_gvrp_uninit_applicant(real_dev);
 
-               rcu_assign_pointer(real_dev->vlgrp, NULL);
+               RCU_INIT_POINTER(real_dev->vlgrp, NULL);
 
                /* Free the group, after all cpu's are done. */
                call_rcu(&grp->rcu, vlan_rcu_free);
index 5f27f8e..f1f2f7b 100644 (file)
@@ -167,6 +167,8 @@ struct sk_buff *vlan_untag(struct sk_buff *skb)
        if (unlikely(!skb))
                goto err_free;
 
+       skb_reset_network_header(skb);
+       skb_reset_transport_header(skb);
        return skb;
 
 err_free:
index 9d40a07..eba705b 100644 (file)
@@ -674,7 +674,6 @@ static const struct net_device_ops vlan_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = vlan_dev_set_mac_address,
        .ndo_set_rx_mode        = vlan_dev_set_rx_mode,
-       .ndo_set_multicast_list = vlan_dev_set_rx_mode,
        .ndo_change_rx_flags    = vlan_dev_change_rx_flags,
        .ndo_do_ioctl           = vlan_dev_ioctl,
        .ndo_neigh_setup        = vlan_dev_neigh_setup,
index 2252c20..52cfd0c 100644 (file)
@@ -242,8 +242,6 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
                if (brdev->payload == p_bridged) {
                        skb_push(skb, 2);
                        memset(skb->data, 0, 2);
-               } else { /* p_routed */
-                       skb_pull(skb, ETH_HLEN);
                }
        }
        skb_debug(skb);
index 215c9fa..f1964ca 100644 (file)
@@ -643,7 +643,7 @@ static const struct net_device_ops lec_netdev_ops = {
        .ndo_start_xmit         = lec_start_xmit,
        .ndo_change_mtu         = lec_change_mtu,
        .ndo_tx_timeout         = lec_tx_timeout,
-       .ndo_set_multicast_list = lec_set_multicast_list,
+       .ndo_set_rx_mode        = lec_set_multicast_list,
 };
 
 static const unsigned char lec_ctrl_magic[] = {
index 216337b..df4a5a9 100644 (file)
@@ -28,8 +28,7 @@
 static inline int aggregated_packet(int buff_pos, int packet_len,
                                    int tt_num_changes)
 {
-       int next_buff_pos = buff_pos + BAT_PACKET_LEN + (tt_num_changes *
-                                               sizeof(struct tt_change));
+       int next_buff_pos = buff_pos + BAT_PACKET_LEN + tt_len(tt_num_changes);
 
        return (next_buff_pos <= packet_len) &&
                (next_buff_pos <= MAX_AGGREGATION_BYTES);
index cd15deb..b8a7414 100644 (file)
@@ -380,6 +380,7 @@ static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr,
 BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
 BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
 BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu);
+BAT_ATTR_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
 static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
 static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode);
 BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL);
@@ -396,6 +397,7 @@ static struct bat_attribute *mesh_attrs[] = {
        &bat_attr_aggregated_ogms,
        &bat_attr_bonding,
        &bat_attr_fragmentation,
+       &bat_attr_ap_isolation,
        &bat_attr_vis_mode,
        &bat_attr_gw_mode,
        &bat_attr_orig_interval,
index c1f4bfc..0be9ff3 100644 (file)
@@ -97,12 +97,12 @@ static void bit_shift(unsigned long *seq_bits, int32_t n)
                        (seq_bits[i - word_num - 1] >>
                         (WORD_BIT_SIZE-word_offset));
                /* and the upper part of the right half and shift it left to
-                * it's position */
+                * its position */
                /* for our example that would be: word[0] = 9800 + 0076 =
                 * 9876 */
        }
-       /* now for our last word, i==word_num, we only have the it's "left"
-        * half. that's the 1000 word in our example.*/
+       /* now for our last word, i==word_num, we only have its "left" half.
+        * that's the 1000 word in our example.*/
 
        seq_bits[i] = (seq_bits[i - word_num] << word_offset);
 
index 056180e..619fb73 100644 (file)
@@ -532,14 +532,14 @@ static bool is_type_dhcprequest(struct sk_buff *skb, int header_len)
        pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1;
 
        /* Access the dhcp option lists. Each entry is made up by:
-        * - octect 1: option type
-        * - octect 2: option data len (only if type != 255 and 0)
-        * - octect 3: option data */
+        * - octet 1: option type
+        * - octet 2: option data len (only if type != 255 and 0)
+        * - octet 3: option data */
        while (*p != 255 && !ret) {
-               /* p now points to the first octect: option type */
+               /* p now points to the first octet: option type */
                if (*p == 53) {
                        /* type 53 is the message type option.
-                        * Jump the len octect and go to the data octect */
+                        * Jump the len octet and go to the data octet */
                        if (pkt_len < 2)
                                goto out;
                        p += 2;
index db7aacf..bf91e4d 100644 (file)
@@ -249,7 +249,7 @@ static void hardif_activate_interface(struct hard_iface *hard_iface)
 
        /**
         * the first active interface becomes our primary interface or
-        * the next active interface after the old primay interface was removed
+        * the next active interface after the old primary interface was removed
         */
        primary_if = primary_if_get_selected(bat_priv);
        if (!primary_if)
@@ -573,7 +573,7 @@ out:
        return NOTIFY_DONE;
 }
 
-/* receive a packet with the batman ethertype coming on a hard
+/* incoming packets with the batman ethertype received on any active hard
  * interface */
 static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
                           struct packet_type *ptype,
@@ -681,6 +681,36 @@ err_out:
        return NET_RX_DROP;
 }
 
+/* This function returns true if the interface represented by ifindex is a
+ * 802.11 wireless device */
+bool is_wifi_iface(int ifindex)
+{
+       struct net_device *net_device = NULL;
+       bool ret = false;
+
+       if (ifindex == NULL_IFINDEX)
+               goto out;
+
+       net_device = dev_get_by_index(&init_net, ifindex);
+       if (!net_device)
+               goto out;
+
+#ifdef CONFIG_WIRELESS_EXT
+       /* pre-cfg80211 drivers have to implement WEXT, so it is possible to
+        * check for wireless_handlers != NULL */
+       if (net_device->wireless_handlers)
+               ret = true;
+       else
+#endif
+               /* cfg80211 drivers have to set ieee80211_ptr */
+               if (net_device->ieee80211_ptr)
+                       ret = true;
+out:
+       if (net_device)
+               dev_put(net_device);
+       return ret;
+}
+
 struct notifier_block hard_if_notifier = {
        .notifier_call = hard_if_event,
 };
index 442eacb..67f78d1 100644 (file)
@@ -42,6 +42,7 @@ void hardif_remove_interfaces(void);
 int hardif_min_mtu(struct net_device *soft_iface);
 void update_min_mtu(struct net_device *soft_iface);
 void hardif_free_rcu(struct rcu_head *rcu);
+bool is_wifi_iface(int ifindex);
 
 static inline void hardif_free_ref(struct hard_iface *hard_iface)
 {
index dd5c9fd..d20aa71 100644 (file)
@@ -76,19 +76,30 @@ static inline void hash_delete(struct hashtable_t *hash,
        hash_destroy(hash);
 }
 
-/* adds data to the hashtable. returns 0 on success, -1 on error */
+/**
+ *     hash_add - adds data to the hashtable
+ *     @hash: storage hash table
+ *     @compare: callback to determine if 2 hash elements are identical
+ *     @choose: callback calculating the hash index
+ *     @data: data passed to the aforementioned callbacks as argument
+ *     @data_node: to be added element
+ *
+ *     Returns 0 on success, 1 if the element already is in the hash
+ *     and -1 on error.
+ */
+
 static inline int hash_add(struct hashtable_t *hash,
                           hashdata_compare_cb compare,
                           hashdata_choose_cb choose,
                           const void *data, struct hlist_node *data_node)
 {
-       int index;
+       int index, ret = -1;
        struct hlist_head *head;
        struct hlist_node *node;
        spinlock_t *list_lock; /* spinlock to protect write access */
 
        if (!hash)
-               goto err;
+               goto out;
 
        index = choose(data, hash->size);
        head = &hash->table[index];
@@ -99,6 +110,7 @@ static inline int hash_add(struct hashtable_t *hash,
                if (!compare(node, data))
                        continue;
 
+               ret = 1;
                goto err_unlock;
        }
        rcu_read_unlock();
@@ -108,12 +120,13 @@ static inline int hash_add(struct hashtable_t *hash,
        hlist_add_head_rcu(data_node, head);
        spin_unlock_bh(list_lock);
 
-       return 0;
+       ret = 0;
+       goto out;
 
 err_unlock:
        rcu_read_unlock();
-err:
-       return -1;
+out:
+       return ret;
 }
 
 /* removes data from hash, if found. returns pointer do data on success, so you
index b0f9068..79b9ae5 100644 (file)
@@ -107,7 +107,7 @@ int mesh_init(struct net_device *soft_iface)
        if (tt_init(bat_priv) < 1)
                goto err;
 
-       tt_local_add(soft_iface, soft_iface->dev_addr);
+       tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX);
 
        if (vis_init(bat_priv) < 1)
                goto err;
index a6df61a..60b3696 100644 (file)
@@ -44,7 +44,7 @@
 #define PURGE_TIMEOUT 200
 #define TT_LOCAL_TIMEOUT 3600 /* in seconds */
 #define TT_CLIENT_ROAM_TIMEOUT 600
-/* sliding packet range of received originator messages in squence numbers
+/* sliding packet range of received originator messages in sequence numbers
  * (should be a multiple of our word size) */
 #define TQ_LOCAL_WINDOW_SIZE 64
 #define TT_REQUEST_TIMEOUT 3 /* seconds we have to keep pending tt_req */
@@ -62,6 +62,8 @@
 
 #define NO_FLAGS 0
 
+#define NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */
+
 #define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
 
 #define LOG_BUF_LEN 8192         /* has to be a power of 2 */
@@ -133,7 +135,7 @@ enum dbg_level {
 #include <linux/mutex.h>       /* mutex */
 #include <linux/module.h>      /* needed by all modules */
 #include <linux/netdevice.h>   /* netdevice */
-#include <linux/etherdevice.h>  /* ethernet address classifaction */
+#include <linux/etherdevice.h>  /* ethernet address classification */
 #include <linux/if_ether.h>    /* ethernet header */
 #include <linux/poll.h>                /* poll_table */
 #include <linux/kthread.h>     /* kernel threads */
index f3c3f62..d448018 100644 (file)
@@ -252,7 +252,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr)
 
        hash_added = hash_add(bat_priv->orig_hash, compare_orig,
                              choose_orig, orig_node, &orig_node->hash_entry);
-       if (hash_added < 0)
+       if (hash_added != 0)
                goto free_bcast_own_sum;
 
        return orig_node;
index b76b4be..8802eab 100644 (file)
@@ -84,6 +84,7 @@ enum tt_query_flags {
 enum tt_client_flags {
        TT_CLIENT_DEL     = 1 << 0,
        TT_CLIENT_ROAM    = 1 << 1,
+       TT_CLIENT_WIFI    = 1 << 2,
        TT_CLIENT_NOPURGE = 1 << 8,
        TT_CLIENT_NEW     = 1 << 9,
        TT_CLIENT_PENDING = 1 << 10
index 0f32c81..1949928 100644 (file)
@@ -64,66 +64,6 @@ void slide_own_bcast_window(struct hard_iface *hard_iface)
        }
 }
 
-static void update_transtable(struct bat_priv *bat_priv,
-                             struct orig_node *orig_node,
-                             const unsigned char *tt_buff,
-                             uint8_t tt_num_changes, uint8_t ttvn,
-                             uint16_t tt_crc)
-{
-       uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
-       bool full_table = true;
-
-       /* the ttvn increased by one -> we can apply the attached changes */
-       if (ttvn - orig_ttvn == 1) {
-               /* the OGM could not contain the changes because they were too
-                * many to fit in one frame or because they have already been
-                * sent TT_OGM_APPEND_MAX times. In this case send a tt
-                * request */
-               if (!tt_num_changes) {
-                       full_table = false;
-                       goto request_table;
-               }
-
-               tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
-                                 (struct tt_change *)tt_buff);
-
-               /* Even if we received the crc into the OGM, we prefer
-                * to recompute it to spot any possible inconsistency
-                * in the global table */
-               orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
-
-               /* The ttvn alone is not enough to guarantee consistency
-                * because a single value could repesent different states
-                * (due to the wrap around). Thus a node has to check whether
-                * the resulting table (after applying the changes) is still
-                * consistent or not. E.g. a node could disconnect while its
-                * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
-                * checking the CRC value is mandatory to detect the
-                * inconsistency */
-               if (orig_node->tt_crc != tt_crc)
-                       goto request_table;
-
-               /* Roaming phase is over: tables are in sync again. I can
-                * unset the flag */
-               orig_node->tt_poss_change = false;
-       } else {
-               /* if we missed more than one change or our tables are not
-                * in sync anymore -> request fresh tt data */
-               if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
-request_table:
-                       bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
-                               "Need to retrieve the correct information "
-                               "(ttvn: %u last_ttvn: %u crc: %u last_crc: "
-                               "%u num_changes: %u)\n", orig_node->orig, ttvn,
-                               orig_ttvn, tt_crc, orig_node->tt_crc,
-                               tt_num_changes);
-                       send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
-                                       full_table);
-                       return;
-               }
-       }
-}
-
 static void update_route(struct bat_priv *bat_priv,
                         struct orig_node *orig_node,
                         struct neigh_node *neigh_node)
@@ -228,7 +168,7 @@ static int is_bidirectional_neigh(struct orig_node *orig_node,
        if (!neigh_node)
                goto out;
 
-       /* if orig_node is direct neighbour update neigh_node last_valid */
+       /* if orig_node is direct neighbor update neigh_node last_valid */
        if (orig_node == orig_neigh_node)
                neigh_node->last_valid = jiffies;
 
@@ -473,7 +413,7 @@ static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
        if (router && (router->tq_avg > neigh_node->tq_avg))
                goto update_tt;
 
-       /* if the TQ is the same and the link not more symetric we
+       /* if the TQ is the same and the link not more symmetric we
         * won't consider it either */
        if (router && (neigh_node->tq_avg == router->tq_avg)) {
                orig_node_tmp = router->orig_node;
@@ -500,10 +440,9 @@ update_tt:
        if (((batman_packet->orig != ethhdr->h_source) &&
                                (batman_packet->ttl > 2)) ||
                                (batman_packet->flags & PRIMARIES_FIRST_HOP))
-               update_transtable(bat_priv, orig_node, tt_buff,
-                                 batman_packet->tt_num_changes,
-                                 batman_packet->ttvn,
-                                 batman_packet->tt_crc);
+               tt_update_orig(bat_priv, orig_node, tt_buff,
+                              batman_packet->tt_num_changes,
+                              batman_packet->ttvn, batman_packet->tt_crc);
 
        if (orig_node->gw_flags != batman_packet->gw_flags)
                gw_node_update(bat_priv, orig_node, batman_packet->gw_flags);
@@ -1243,7 +1182,7 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
                }
                break;
        case TT_RESPONSE:
-               /* packet needs to be linearised to access the TT changes */
+               /* packet needs to be linearized to access the TT changes */
                if (skb_linearize(skb) < 0)
                        goto out;
 
@@ -1300,7 +1239,7 @@ int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if)
                roam_adv_packet->client);
 
        tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
-                     atomic_read(&orig_node->last_ttvn) + 1, true);
+                     atomic_read(&orig_node->last_ttvn) + 1, true, false);
 
        /* Roaming phase starts: I have new information but the ttvn has not
         * been incremented yet. This flag will make me check all the incoming
@@ -1536,7 +1475,7 @@ static int check_unicast_ttvn(struct bat_priv *bat_priv,
 
                ethhdr = (struct ethhdr *)(skb->data +
                        sizeof(struct unicast_packet));
-               orig_node = transtable_search(bat_priv, ethhdr->h_dest);
+               orig_node = transtable_search(bat_priv, NULL, ethhdr->h_dest);
 
                if (!orig_node) {
                        if (!is_my_client(bat_priv, ethhdr->h_dest))
index 58d1447..57ae809 100644 (file)
@@ -135,7 +135,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
                                                            "Forwarding"));
                bat_dbg(DBG_BATMAN, bat_priv,
                        "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
-                       " IDF %s, hvn %d) on interface %s [%pM]\n",
+                       " IDF %s, ttvn %d) on interface %s [%pM]\n",
                        fwd_str, (packet_num > 0 ? "aggregated " : ""),
                        batman_packet->orig, ntohl(batman_packet->seqno),
                        batman_packet->tq, batman_packet->ttl,
@@ -313,7 +313,7 @@ void schedule_own_packet(struct hard_iface *hard_iface)
                        prepare_packet_buffer(bat_priv, hard_iface);
                }
 
-               /* if the changes have been sent enough times */
+               /* if the changes have been sent often enough */
                if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))
                        reset_packet_buffer(bat_priv, hard_iface);
        }
@@ -454,7 +454,7 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
 }
 
 /* add a broadcast packet to the queue and setup timers. broadcast packets
- * are sent multiple times to increase probability for beeing received.
+ * are sent multiple times to increase probability for being received.
  *
  * This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on
  * errors.
@@ -612,7 +612,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
                                  &bat_priv->forw_bcast_list, list) {
 
                /**
-                * if purge_outstanding_packets() was called with an argmument
+                * if purge_outstanding_packets() was called with an argument
                 * we delete only packets belonging to the given interface
                 */
                if ((hard_iface) &&
@@ -641,7 +641,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
                                  &bat_priv->forw_bat_list, list) {
 
                /**
-                * if purge_outstanding_packets() was called with an argmument
+                * if purge_outstanding_packets() was called with an argument
                 * we delete only packets belonging to the given interface
                 */
                if ((hard_iface) &&
index 3e2f91f..402fd96 100644 (file)
@@ -532,11 +532,11 @@ static int interface_set_mac_addr(struct net_device *dev, void *p)
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
 
-       /* only modify transtable if it has been initialised before */
+       /* only modify transtable if it has been initialized before */
        if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
                tt_local_remove(bat_priv, dev->dev_addr,
                                "mac address changed", false);
-               tt_local_add(dev, addr->sa_data);
+               tt_local_add(dev, addr->sa_data, NULL_IFINDEX);
        }
 
        memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
@@ -595,9 +595,10 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
                goto dropped;
 
        /* Register the client MAC in the transtable */
-       tt_local_add(soft_iface, ethhdr->h_source);
+       tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
 
-       orig_node = transtable_search(bat_priv, ethhdr->h_dest);
+       orig_node = transtable_search(bat_priv, ethhdr->h_source,
+                                     ethhdr->h_dest);
        if (is_multicast_ether_addr(ethhdr->h_dest) ||
                                (orig_node && orig_node->gw_flags)) {
                ret = gw_is_target(bat_priv, skb, orig_node);
@@ -739,6 +740,9 @@ void interface_rx(struct net_device *soft_iface,
 
        soft_iface->last_rx = jiffies;
 
+       if (is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
+               goto dropped;
+
        netif_rx(skb);
        goto out;
 
@@ -812,6 +816,7 @@ struct net_device *softif_create(const char *name)
 
        atomic_set(&bat_priv->aggregated_ogms, 1);
        atomic_set(&bat_priv->bonding, 0);
+       atomic_set(&bat_priv->ap_isolation, 0);
        atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
        atomic_set(&bat_priv->gw_mode, GW_MODE_OFF);
        atomic_set(&bat_priv->gw_sel_class, 20);
index fb6931d..cc53f78 100644 (file)
@@ -183,7 +183,8 @@ static int tt_local_init(struct bat_priv *bat_priv)
        return 1;
 }
 
-void tt_local_add(struct net_device *soft_iface, const uint8_t *addr)
+void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
+                 int ifindex)
 {
        struct bat_priv *bat_priv = netdev_priv(soft_iface);
        struct tt_local_entry *tt_local_entry = NULL;
@@ -207,6 +208,8 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr)
        memcpy(tt_local_entry->addr, addr, ETH_ALEN);
        tt_local_entry->last_seen = jiffies;
        tt_local_entry->flags = NO_FLAGS;
+       if (is_wifi_iface(ifindex))
+               tt_local_entry->flags |= TT_CLIENT_WIFI;
        atomic_set(&tt_local_entry->refcount, 2);
 
        /* the batman interface mac address should never be purged */
@@ -329,7 +332,7 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
 
                rcu_read_lock();
                __hlist_for_each_rcu(node, head)
-                       buf_size += 21;
+                       buf_size += 29;
                rcu_read_unlock();
        }
 
@@ -348,8 +351,19 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
                rcu_read_lock();
                hlist_for_each_entry_rcu(tt_local_entry, node,
                                         head, hash_entry) {
-                       pos += snprintf(buff + pos, 22, " * %pM\n",
-                                       tt_local_entry->addr);
+                       pos += snprintf(buff + pos, 30, " * %pM "
+                                       "[%c%c%c%c%c]\n",
+                                       tt_local_entry->addr,
+                                       (tt_local_entry->flags &
+                                        TT_CLIENT_ROAM ? 'R' : '.'),
+                                       (tt_local_entry->flags &
+                                        TT_CLIENT_NOPURGE ? 'P' : '.'),
+                                       (tt_local_entry->flags &
+                                        TT_CLIENT_NEW ? 'N' : '.'),
+                                       (tt_local_entry->flags &
+                                        TT_CLIENT_PENDING ? 'X' : '.'),
+                                       (tt_local_entry->flags &
+                                        TT_CLIENT_WIFI ? 'W' : '.'));
                }
                rcu_read_unlock();
        }
@@ -369,8 +383,8 @@ static void tt_local_set_pending(struct bat_priv *bat_priv,
        tt_local_event(bat_priv, tt_local_entry->addr,
                       tt_local_entry->flags | flags);
 
-       /* The local client has to be merked as "pending to be removed" but has
-        * to be kept in the table in order to send it in an full tables
+       /* The local client has to be marked as "pending to be removed" but has
+        * to be kept in the table in order to send it in a full table
         * response issued before the net ttvn increment (consistency check) */
        tt_local_entry->flags |= TT_CLIENT_PENDING;
 }
@@ -495,7 +509,8 @@ static void tt_changes_list_free(struct bat_priv *bat_priv)
 
 /* caller must hold orig_node refcount */
 int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
-                 const unsigned char *tt_addr, uint8_t ttvn, bool roaming)
+                 const unsigned char *tt_addr, uint8_t ttvn, bool roaming,
+                 bool wifi)
 {
        struct tt_global_entry *tt_global_entry;
        struct orig_node *orig_node_tmp;
@@ -537,6 +552,9 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
                tt_global_entry->roam_at = 0;
        }
 
+       if (wifi)
+               tt_global_entry->flags |= TT_CLIENT_WIFI;
+
        bat_dbg(DBG_TT, bat_priv,
                "Creating new global tt entry: %pM (via %pM)\n",
                tt_global_entry->addr, orig_node->orig);
@@ -582,8 +600,8 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
        seq_printf(seq,
                   "Globally announced TT entries received via the mesh %s\n",
                   net_dev->name);
-       seq_printf(seq, "       %-13s %s       %-15s %s\n",
-                  "Client", "(TTVN)", "Originator", "(Curr TTVN)");
+       seq_printf(seq, "       %-13s %s       %-15s %s %s\n",
+                  "Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags");
 
        buf_size = 1;
        /* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via
@@ -593,7 +611,7 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
 
                rcu_read_lock();
                __hlist_for_each_rcu(node, head)
-                       buf_size += 59;
+                       buf_size += 67;
                rcu_read_unlock();
        }
 
@@ -612,14 +630,20 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
                rcu_read_lock();
                hlist_for_each_entry_rcu(tt_global_entry, node,
                                         head, hash_entry) {
-                       pos += snprintf(buff + pos, 61,
-                                       " * %pM  (%3u) via %pM     (%3u)\n",
-                                       tt_global_entry->addr,
+                       pos += snprintf(buff + pos, 69,
+                                       " * %pM  (%3u) via %pM     (%3u)   "
+                                       "[%c%c%c]\n", tt_global_entry->addr,
                                        tt_global_entry->ttvn,
                                        tt_global_entry->orig_node->orig,
                                        (uint8_t) atomic_read(
                                                &tt_global_entry->orig_node->
-                                               last_ttvn));
+                                               last_ttvn),
+                                       (tt_global_entry->flags &
+                                        TT_CLIENT_ROAM ? 'R' : '.'),
+                                       (tt_global_entry->flags &
+                                        TT_CLIENT_PENDING ? 'X' : '.'),
+                                       (tt_global_entry->flags &
+                                        TT_CLIENT_WIFI ? 'W' : '.'));
                }
                rcu_read_unlock();
        }
@@ -774,30 +798,56 @@ static void tt_global_table_free(struct bat_priv *bat_priv)
        bat_priv->tt_global_hash = NULL;
 }
 
+static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry,
+                           struct tt_global_entry *tt_global_entry)
+{
+       bool ret = false;
+
+       if (tt_local_entry->flags & TT_CLIENT_WIFI &&
+           tt_global_entry->flags & TT_CLIENT_WIFI)
+               ret = true;
+
+       return ret;
+}
+
 struct orig_node *transtable_search(struct bat_priv *bat_priv,
-                                   const uint8_t *addr)
+                                   const uint8_t *src, const uint8_t *addr)
 {
-       struct tt_global_entry *tt_global_entry;
+       struct tt_local_entry *tt_local_entry = NULL;
+       struct tt_global_entry *tt_global_entry = NULL;
        struct orig_node *orig_node = NULL;
 
-       tt_global_entry = tt_global_hash_find(bat_priv, addr);
+       if (src && atomic_read(&bat_priv->ap_isolation)) {
+               tt_local_entry = tt_local_hash_find(bat_priv, src);
+               if (!tt_local_entry)
+                       goto out;
+       }
 
+       tt_global_entry = tt_global_hash_find(bat_priv, addr);
        if (!tt_global_entry)
                goto out;
 
+       /* check whether the clients should not communicate due to AP
+        * isolation */
+       if (tt_local_entry && _is_ap_isolated(tt_local_entry, tt_global_entry))
+               goto out;
+
        if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount))
-               goto free_tt;
+               goto out;
 
        /* A global client marked as PENDING has already moved from that
         * originator */
        if (tt_global_entry->flags & TT_CLIENT_PENDING)
-               goto free_tt;
+               goto out;
 
        orig_node = tt_global_entry->orig_node;
 
-free_tt:
-       tt_global_entry_free_ref(tt_global_entry);
 out:
+       if (tt_global_entry)
+               tt_global_entry_free_ref(tt_global_entry);
+       if (tt_local_entry)
+               tt_local_entry_free_ref(tt_local_entry);
+
        return orig_node;
 }
 
@@ -1029,8 +1079,9 @@ out:
        return skb;
 }
 
-int send_tt_request(struct bat_priv *bat_priv, struct orig_node *dst_orig_node,
-                   uint8_t ttvn, uint16_t tt_crc, bool full_table)
+static int send_tt_request(struct bat_priv *bat_priv,
+                          struct orig_node *dst_orig_node,
+                          uint8_t ttvn, uint16_t tt_crc, bool full_table)
 {
        struct sk_buff *skb = NULL;
        struct tt_query_packet *tt_request;
@@ -1137,12 +1188,12 @@ static bool send_other_tt_response(struct bat_priv *bat_priv,
        orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
        req_ttvn = tt_request->ttvn;
 
-       /* I have not the requested data */
+       /* I don't have the requested data */
        if (orig_ttvn != req_ttvn ||
            tt_request->tt_data != req_dst_orig_node->tt_crc)
                goto out;
 
-       /* If it has explicitly been requested the full table */
+       /* If the full table has been explicitly requested */
        if (tt_request->flags & TT_FULL_TABLE ||
            !req_dst_orig_node->tt_buff)
                full_table = true;
@@ -1363,7 +1414,9 @@ static void _tt_update_changes(struct bat_priv *bat_priv,
                                      (tt_change + i)->flags & TT_CLIENT_ROAM);
                else
                        if (!tt_global_add(bat_priv, orig_node,
-                                          (tt_change + i)->addr, ttvn, false))
+                                          (tt_change + i)->addr, ttvn, false,
+                                          (tt_change + i)->flags &
+                                                       TT_CLIENT_WIFI))
                                /* In case of problem while storing a
                                 * global_entry, we stop the updating
                                 * procedure without committing the
@@ -1403,9 +1456,10 @@ out:
                orig_node_free_ref(orig_node);
 }
 
-void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node,
-                      uint16_t tt_num_changes, uint8_t ttvn,
-                      struct tt_change *tt_change)
+static void tt_update_changes(struct bat_priv *bat_priv,
+                             struct orig_node *orig_node,
+                             uint16_t tt_num_changes, uint8_t ttvn,
+                             struct tt_change *tt_change)
 {
        _tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes,
                           ttvn);
@@ -1720,3 +1774,90 @@ void tt_commit_changes(struct bat_priv *bat_priv)
        atomic_inc(&bat_priv->ttvn);
        bat_priv->tt_poss_change = false;
 }
+
+bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst)
+{
+       struct tt_local_entry *tt_local_entry = NULL;
+       struct tt_global_entry *tt_global_entry = NULL;
+       bool ret = true;
+
+       if (!atomic_read(&bat_priv->ap_isolation))
+               return false;
+
+       tt_local_entry = tt_local_hash_find(bat_priv, dst);
+       if (!tt_local_entry)
+               goto out;
+
+       tt_global_entry = tt_global_hash_find(bat_priv, src);
+       if (!tt_global_entry)
+               goto out;
+
+       if (_is_ap_isolated(tt_local_entry, tt_global_entry))
+               goto out;
+
+       ret = false;
+
+out:
+       if (tt_global_entry)
+               tt_global_entry_free_ref(tt_global_entry);
+       if (tt_local_entry)
+               tt_local_entry_free_ref(tt_local_entry);
+       return ret;
+}
+
+void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
+                   const unsigned char *tt_buff, uint8_t tt_num_changes,
+                   uint8_t ttvn, uint16_t tt_crc)
+{
+       uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
+       bool full_table = true;
+
+       /* the ttvn increased by one -> we can apply the attached changes */
+       if (ttvn - orig_ttvn == 1) {
+               /* the OGM could not contain the changes due to their size or
+                * because they have already been sent TT_OGM_APPEND_MAX times.
+                * In this case send a tt request */
+               if (!tt_num_changes) {
+                       full_table = false;
+                       goto request_table;
+               }
+
+               tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
+                                 (struct tt_change *)tt_buff);
+
+               /* Even if we received the precomputed crc with the OGM, we
+                * prefer to recompute it to spot any possible inconsistency
+                * in the global table */
+               orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
+
+               /* The ttvn alone is not enough to guarantee consistency
+                * because a single value could represent different states
+                * (due to the wrap around). Thus a node has to check whether
+                * the resulting table (after applying the changes) is still
+                * consistent or not. E.g. a node could disconnect while its
+                * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
+                * checking the CRC value is mandatory to detect the
+                * inconsistency */
+               if (orig_node->tt_crc != tt_crc)
+                       goto request_table;
+
+               /* Roaming phase is over: tables are in sync again. I can
+                * unset the flag */
+               orig_node->tt_poss_change = false;
+       } else {
+               /* if we missed more than one change or our tables are not
+                * in sync anymore -> request fresh tt data */
+               if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
+request_table:
+                       bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
+                               "Need to retrieve the correct information "
+                               "(ttvn: %u last_ttvn: %u crc: %u last_crc: "
+                               "%u num_changes: %u)\n", orig_node->orig, ttvn,
+                               orig_ttvn, tt_crc, orig_node->tt_crc,
+                               tt_num_changes);
+                       send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
+                                       full_table);
+                       return;
+               }
+       }
+}
index d4122cb..30efd49 100644 (file)
@@ -26,15 +26,16 @@ int tt_len(int changes_num);
 int tt_changes_fill_buffer(struct bat_priv *bat_priv,
                           unsigned char *buff, int buff_len);
 int tt_init(struct bat_priv *bat_priv);
-void tt_local_add(struct net_device *soft_iface, const uint8_t *addr);
+void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
+                 int ifindex);
 void tt_local_remove(struct bat_priv *bat_priv,
                     const uint8_t *addr, const char *message, bool roaming);
 int tt_local_seq_print_text(struct seq_file *seq, void *offset);
 void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
                        const unsigned char *tt_buff, int tt_buff_len);
-int tt_global_add(struct bat_priv *bat_priv,
-                 struct orig_node *orig_node, const unsigned char *addr,
-                 uint8_t ttvn, bool roaming);
+int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
+                 const unsigned char *addr, uint8_t ttvn, bool roaming,
+                 bool wifi);
 int tt_global_seq_print_text(struct seq_file *seq, void *offset);
 void tt_global_del_orig(struct bat_priv *bat_priv,
                        struct orig_node *orig_node, const char *message);
@@ -42,25 +43,23 @@ void tt_global_del(struct bat_priv *bat_priv,
                   struct orig_node *orig_node, const unsigned char *addr,
                   const char *message, bool roaming);
 struct orig_node *transtable_search(struct bat_priv *bat_priv,
-                                   const uint8_t *addr);
+                                   const uint8_t *src, const uint8_t *addr);
 void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node,
                         const unsigned char *tt_buff, uint8_t tt_num_changes);
 uint16_t tt_local_crc(struct bat_priv *bat_priv);
 uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node);
 void tt_free(struct bat_priv *bat_priv);
-int send_tt_request(struct bat_priv *bat_priv,
-                   struct orig_node *dst_orig_node, uint8_t hvn,
-                   uint16_t tt_crc, bool full_table);
 bool send_tt_response(struct bat_priv *bat_priv,
                      struct tt_query_packet *tt_request);
-void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node,
-                      uint16_t tt_num_changes, uint8_t ttvn,
-                      struct tt_change *tt_change);
 bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr);
 void handle_tt_response(struct bat_priv *bat_priv,
                        struct tt_query_packet *tt_response);
 void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
                   struct orig_node *orig_node);
 void tt_commit_changes(struct bat_priv *bat_priv);
+bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst);
+void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
+                   const unsigned char *tt_buff, uint8_t tt_num_changes,
+                   uint8_t ttvn, uint16_t tt_crc);
 
 #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
index 25bd1db..1ae3557 100644 (file)
@@ -57,7 +57,7 @@ struct hard_iface {
  *     @batman_seqno_reset: time when the batman seqno window was reset
  *     @gw_flags: flags related to gateway class
  *     @flags: for now only VIS_SERVER flag
- *     @last_real_seqno: last and best known squence number
+ *     @last_real_seqno: last and best known sequence number
  *     @last_ttl: ttl of last received packet
  *     @last_bcast_seqno: last broadcast sequence number received by this host
  *
@@ -146,6 +146,7 @@ struct bat_priv {
        atomic_t aggregated_ogms;       /* boolean */
        atomic_t bonding;               /* boolean */
        atomic_t fragmentation;         /* boolean */
+       atomic_t ap_isolation;          /* boolean */
        atomic_t vis_mode;              /* VIS_TYPE_* */
        atomic_t gw_mode;               /* GW_MODE_* */
        atomic_t gw_sel_class;          /* uint */
@@ -156,7 +157,7 @@ struct bat_priv {
        atomic_t bcast_seqno;
        atomic_t bcast_queue_left;
        atomic_t batman_queue_left;
-       atomic_t ttvn; /* tranlation table version number */
+       atomic_t ttvn; /* translation table version number */
        atomic_t tt_ogm_append_cnt;
        atomic_t tt_local_changes; /* changes registered in a OGM interval */
        /* The tt_poss_change flag is used to detect an ongoing roaming phase.
index 32b125f..07d1c1d 100644 (file)
@@ -299,8 +299,10 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
                        goto find_router;
        }
 
-       /* check for tt host - increases orig_node refcount */
-       orig_node = transtable_search(bat_priv, ethhdr->h_dest);
+       /* check for tt host - increases orig_node refcount.
+        * returns NULL in case of AP isolation */
+       orig_node = transtable_search(bat_priv, ethhdr->h_source,
+                                     ethhdr->h_dest);
 
 find_router:
        /**
index 62f54b9..8fd5535 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "packet.h"
 
-#define FRAG_TIMEOUT 10000     /* purge frag list entrys after time in ms */
+#define FRAG_TIMEOUT 10000     /* purge frag list entries after time in ms */
 #define FRAG_BUFFER_SIZE 6     /* number of list elements in buffer */
 
 int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
index 8a1b985..fb9b19f 100644 (file)
@@ -131,7 +131,7 @@ static void vis_data_insert_interface(const uint8_t *interface,
                        return;
        }
 
-       /* its a new address, add it to the list */
+       /* it's a new address, add it to the list */
        entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
        if (!entry)
                return;
@@ -465,7 +465,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
        /* try to add it */
        hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
                              info, &info->hash_entry);
-       if (hash_added < 0) {
+       if (hash_added != 0) {
                /* did not work (for some reason) */
                kref_put(&info->refcount, free_info);
                info = NULL;
@@ -920,7 +920,7 @@ int vis_init(struct bat_priv *bat_priv)
        hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
                              bat_priv->my_vis_info,
                              &bat_priv->my_vis_info->hash_entry);
-       if (hash_added < 0) {
+       if (hash_added != 0) {
                pr_err("Can't add own vis packet into hash\n");
                /* not in hash, need to remove it manually. */
                kref_put(&bat_priv->my_vis_info->refcount, free_info);
index d4f5dff..bc40864 100644 (file)
@@ -217,7 +217,7 @@ static const struct net_device_ops bnep_netdev_ops = {
        .ndo_stop            = bnep_net_close,
        .ndo_start_xmit      = bnep_net_xmit,
        .ndo_validate_addr   = eth_validate_addr,
-       .ndo_set_multicast_list = bnep_net_set_mc_list,
+       .ndo_set_rx_mode     = bnep_net_set_mc_list,
        .ndo_set_mac_address = bnep_net_set_mac_addr,
        .ndo_tx_timeout      = bnep_net_timeout,
        .ndo_change_mtu      = eth_change_mtu,
index 32b8f9f..ee68eee 100644 (file)
@@ -304,7 +304,7 @@ static const struct net_device_ops br_netdev_ops = {
        .ndo_start_xmit          = br_dev_xmit,
        .ndo_get_stats64         = br_get_stats64,
        .ndo_set_mac_address     = br_set_mac_address,
-       .ndo_set_multicast_list  = br_dev_set_multicast_list,
+       .ndo_set_rx_mode         = br_dev_set_multicast_list,
        .ndo_change_mtu          = br_change_mtu,
        .ndo_do_ioctl            = br_dev_ioctl,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 3176e2e..2cdf007 100644 (file)
@@ -417,6 +417,7 @@ put_back:
 int br_del_if(struct net_bridge *br, struct net_device *dev)
 {
        struct net_bridge_port *p;
+       bool changed_addr;
 
        p = br_port_get_rtnl(dev);
        if (!p || p->br != br)
@@ -425,9 +426,12 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
        del_nbp(p);
 
        spin_lock_bh(&br->lock);
-       br_stp_recalculate_bridge_id(br);
+       changed_addr = br_stp_recalculate_bridge_id(br);
        spin_unlock_bh(&br->lock);
 
+       if (changed_addr)
+               call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
+
        netdev_update_features(br->dev);
 
        return 0;
index 6545ee9..a76b621 100644 (file)
@@ -34,6 +34,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
        struct net_device *dev = ptr;
        struct net_bridge_port *p;
        struct net_bridge *br;
+       bool changed_addr;
        int err;
 
        /* register of bridge completed, add sysfs entries */
@@ -57,8 +58,12 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
        case NETDEV_CHANGEADDR:
                spin_lock_bh(&br->lock);
                br_fdb_changeaddr(p, dev->dev_addr);
-               br_stp_recalculate_bridge_id(br);
+               changed_addr = br_stp_recalculate_bridge_id(br);
                spin_unlock_bh(&br->lock);
+
+               if (changed_addr)
+                       call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
+
                break;
 
        case NETDEV_CHANGE:
index 1bcaf36..40d8258 100644 (file)
@@ -87,14 +87,14 @@ static int __init ebtable_broute_init(void)
        if (ret < 0)
                return ret;
        /* see br_input.c */
-       rcu_assign_pointer(br_should_route_hook,
+       RCU_INIT_POINTER(br_should_route_hook,
                           (br_should_route_hook_t *)ebt_broute);
        return 0;
 }
 
 static void __exit ebtable_broute_fini(void)
 {
-       rcu_assign_pointer(br_should_route_hook, NULL);
+       RCU_INIT_POINTER(br_should_route_hook, NULL);
        synchronize_net();
        unregister_pernet_subsys(&broute_net_ops);
 }
index 2b5ca1a..5864cc4 100644 (file)
@@ -1198,7 +1198,8 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table)
 
        if (table->check && table->check(newinfo, table->valid_hooks)) {
                BUGPRINT("The table doesn't like its own initial data, lol\n");
-               return ERR_PTR(-EINVAL);
+               ret = -EINVAL;
+               goto free_chainstack;
        }
 
        table->private = newinfo;
index 52fe33b..f07ab8c 100644 (file)
@@ -78,10 +78,8 @@ struct cfcnfg *cfcnfg_create(void)
 
        /* Initiate this layer */
        this = kzalloc(sizeof(struct cfcnfg), GFP_ATOMIC);
-       if (!this) {
-               pr_warn("Out of memory\n");
+       if (!this)
                return NULL;
-       }
        this->mux = cfmuxl_create();
        if (!this->mux)
                goto out_of_mem;
@@ -108,8 +106,6 @@ struct cfcnfg *cfcnfg_create(void)
 
        return this;
 out_of_mem:
-       pr_warn("Out of memory\n");
-
        synchronize_rcu();
 
        kfree(this->mux);
@@ -448,10 +444,8 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
                                "- unknown channel type\n");
                goto unlock;
        }
-       if (!servicel) {
-               pr_warn("Out of memory\n");
+       if (!servicel)
                goto unlock;
-       }
        layer_set_dn(servicel, cnfg->mux);
        cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id);
        layer_set_up(servicel, adapt_layer);
@@ -497,10 +491,8 @@ got_phyid:
        case CFPHYTYPE_FRAG:
                phy_driver =
                    cfserl_create(CFPHYTYPE_FRAG, phyid, stx);
-               if (!phy_driver) {
-                       pr_warn("Out of memory\n");
+               if (!phy_driver)
                        goto out;
-               }
                break;
        case CFPHYTYPE_CAIF:
                phy_driver = NULL;
@@ -521,7 +513,6 @@ got_phyid:
        frml = cffrml_create(phyid, fcs);
 
        if (!frml) {
-               pr_warn("Out of memory\n");
                kfree(phyinfo);
                goto out;
        }
index e22671b..5cf5222 100644 (file)
@@ -35,15 +35,12 @@ struct cflayer *cfctrl_create(void)
 {
        struct dev_info dev_info;
        struct cfctrl *this =
-               kmalloc(sizeof(struct cfctrl), GFP_ATOMIC);
-       if (!this) {
-               pr_warn("Out of memory\n");
+               kzalloc(sizeof(struct cfctrl), GFP_ATOMIC);
+       if (!this)
                return NULL;
-       }
        caif_assert(offsetof(struct cfctrl, serv.layer) == 0);
        memset(&dev_info, 0, sizeof(dev_info));
        dev_info.id = 0xff;
-       memset(this, 0, sizeof(*this));
        cfsrvl_init(&this->serv, 0, &dev_info, false);
        atomic_set(&this->req_seq_no, 1);
        atomic_set(&this->rsp_seq_no, 1);
@@ -180,10 +177,8 @@ void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid)
        struct cfctrl *cfctrl = container_obj(layer);
        struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
        struct cflayer *dn = cfctrl->serv.layer.dn;
-       if (!pkt) {
-               pr_warn("Out of memory\n");
+       if (!pkt)
                return;
-       }
        if (!dn) {
                pr_debug("not able to send enum request\n");
                return;
@@ -224,10 +219,8 @@ int cfctrl_linkup_request(struct cflayer *layer,
        }
 
        pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
-       if (!pkt) {
-               pr_warn("Out of memory\n");
+       if (!pkt)
                return -ENOMEM;
-       }
        cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP);
        cfpkt_addbdy(pkt, (param->chtype << 4) | param->linktype);
        cfpkt_addbdy(pkt, (param->priority << 3) | param->phyid);
@@ -275,10 +268,8 @@ int cfctrl_linkup_request(struct cflayer *layer,
                return -EINVAL;
        }
        req = kzalloc(sizeof(*req), GFP_KERNEL);
-       if (!req) {
-               pr_warn("Out of memory\n");
+       if (!req)
                return -ENOMEM;
-       }
        req->client_layer = user_layer;
        req->cmd = CFCTRL_CMD_LINK_SETUP;
        req->param = *param;
@@ -312,10 +303,8 @@ int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid,
        struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
        struct cflayer *dn = cfctrl->serv.layer.dn;
 
-       if (!pkt) {
-               pr_warn("Out of memory\n");
+       if (!pkt)
                return -ENOMEM;
-       }
 
        if (!dn) {
                pr_debug("not able to send link-down request\n");
index 11a2af4..65d6ef3 100644 (file)
@@ -19,13 +19,10 @@ static int cfdbgl_transmit(struct cflayer *layr, struct cfpkt *pkt);
 
 struct cflayer *cfdbgl_create(u8 channel_id, struct dev_info *dev_info)
 {
-       struct cfsrvl *dbg = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
-       if (!dbg) {
-               pr_warn("Out of memory\n");
+       struct cfsrvl *dbg = kzalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
+       if (!dbg)
                return NULL;
-       }
        caif_assert(offsetof(struct cfsrvl, layer) == 0);
-       memset(dbg, 0, sizeof(struct cfsrvl));
        cfsrvl_init(dbg, channel_id, dev_info, false);
        dbg->layer.receive = cfdbgl_receive;
        dbg->layer.transmit = cfdbgl_transmit;
index 0382dec..0f5ff27 100644 (file)
@@ -26,13 +26,10 @@ static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt);
 
 struct cflayer *cfdgml_create(u8 channel_id, struct dev_info *dev_info)
 {
-       struct cfsrvl *dgm = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
-       if (!dgm) {
-               pr_warn("Out of memory\n");
+       struct cfsrvl *dgm = kzalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
+       if (!dgm)
                return NULL;
-       }
        caif_assert(offsetof(struct cfsrvl, layer) == 0);
-       memset(dgm, 0, sizeof(struct cfsrvl));
        cfsrvl_init(dgm, channel_id, dev_info, true);
        dgm->layer.receive = cfdgml_receive;
        dgm->layer.transmit = cfdgml_transmit;
index 04204b2..f399211 100644 (file)
@@ -34,11 +34,9 @@ static u32 cffrml_rcv_error;
 static u32 cffrml_rcv_checsum_error;
 struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
 {
-       struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC);
-       if (!this) {
-               pr_warn("Out of memory\n");
+       struct cffrml *this = kzalloc(sizeof(struct cffrml), GFP_ATOMIC);
+       if (!this)
                return NULL;
-       }
        this->pcpu_refcnt = alloc_percpu(int);
        if (this->pcpu_refcnt == NULL) {
                kfree(this);
@@ -47,7 +45,6 @@ struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
 
        caif_assert(offsetof(struct cffrml, layer) == 0);
 
-       memset(this, 0, sizeof(struct cflayer));
        this->layer.receive = cffrml_receive;
        this->layer.transmit = cffrml_transmit;
        this->layer.ctrlcmd = cffrml_ctrlcmd;
index c23979e..b36f24a 100644 (file)
@@ -108,7 +108,7 @@ struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid)
        int idx = phyid % DN_CACHE_SIZE;
 
        spin_lock_bh(&muxl->transmit_lock);
-       rcu_assign_pointer(muxl->dn_cache[idx], NULL);
+       RCU_INIT_POINTER(muxl->dn_cache[idx], NULL);
        dn = get_from_id(&muxl->frml_list, phyid);
        if (dn == NULL)
                goto out;
@@ -164,7 +164,7 @@ struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 id)
        if (up == NULL)
                goto out;
 
-       rcu_assign_pointer(muxl->up_cache[idx], NULL);
+       RCU_INIT_POINTER(muxl->up_cache[idx], NULL);
        list_del_rcu(&up->node);
 out:
        spin_unlock_bh(&muxl->receive_lock);
@@ -261,7 +261,7 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
 
                                idx = layer->id % UP_CACHE_SIZE;
                                spin_lock_bh(&muxl->receive_lock);
-                               rcu_assign_pointer(muxl->up_cache[idx], NULL);
+                               RCU_INIT_POINTER(muxl->up_cache[idx], NULL);
                                list_del_rcu(&layer->node);
                                spin_unlock_bh(&muxl->receive_lock);
                        }
index 0deabb4..81660f8 100644 (file)
@@ -46,13 +46,10 @@ struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info,
                                        int mtu_size)
 {
        int tmp;
-       struct cfrfml *this =
-               kzalloc(sizeof(struct cfrfml), GFP_ATOMIC);
+       struct cfrfml *this = kzalloc(sizeof(struct cfrfml), GFP_ATOMIC);
 
-       if (!this) {
-               pr_warn("Out of memory\n");
+       if (!this)
                return NULL;
-       }
 
        cfsrvl_init(&this->serv, channel_id, dev_info, false);
        this->serv.release = cfrfml_release;
index 2715c84..797c8d1 100644 (file)
@@ -33,13 +33,10 @@ static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
 
 struct cflayer *cfserl_create(int type, int instance, bool use_stx)
 {
-       struct cfserl *this = kmalloc(sizeof(struct cfserl), GFP_ATOMIC);
-       if (!this) {
-               pr_warn("Out of memory\n");
+       struct cfserl *this = kzalloc(sizeof(struct cfserl), GFP_ATOMIC);
+       if (!this)
                return NULL;
-       }
        caif_assert(offsetof(struct cfserl, layer) == 0);
-       memset(this, 0, sizeof(struct cfserl));
        this->layer.receive = cfserl_receive;
        this->layer.transmit = cfserl_transmit;
        this->layer.ctrlcmd = cfserl_ctrlcmd;
index 535a1e7..b99f5b2 100644 (file)
@@ -108,10 +108,8 @@ static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl)
                        struct caif_payload_info *info;
                        u8 flow_on = SRVL_FLOW_ON;
                        pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE);
-                       if (!pkt) {
-                               pr_warn("Out of memory\n");
+                       if (!pkt)
                                return -ENOMEM;
-                       }
 
                        if (cfpkt_add_head(pkt, &flow_on, 1) < 0) {
                                pr_err("Packet is erroneous!\n");
@@ -130,10 +128,8 @@ static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl)
                        struct caif_payload_info *info;
                        u8 flow_off = SRVL_FLOW_OFF;
                        pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE);
-                       if (!pkt) {
-                               pr_warn("Out of memory\n");
+                       if (!pkt)
                                return -ENOMEM;
-                       }
 
                        if (cfpkt_add_head(pkt, &flow_off, 1) < 0) {
                                pr_err("Packet is erroneous!\n");
index 98e027d..53e49f3 100644 (file)
@@ -26,13 +26,10 @@ static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt);
 
 struct cflayer *cfutill_create(u8 channel_id, struct dev_info *dev_info)
 {
-       struct cfsrvl *util = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
-       if (!util) {
-               pr_warn("Out of memory\n");
+       struct cfsrvl *util = kzalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
+       if (!util)
                return NULL;
-       }
        caif_assert(offsetof(struct cfsrvl, layer) == 0);
-       memset(util, 0, sizeof(struct cfsrvl));
        cfsrvl_init(util, channel_id, dev_info, true);
        util->layer.receive = cfutill_receive;
        util->layer.transmit = cfutill_transmit;
index 3ec83fb..910ab06 100644 (file)
@@ -25,13 +25,10 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt);
 
 struct cflayer *cfvei_create(u8 channel_id, struct dev_info *dev_info)
 {
-       struct cfsrvl *vei = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
-       if (!vei) {
-               pr_warn("Out of memory\n");
+       struct cfsrvl *vei = kzalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
+       if (!vei)
                return NULL;
-       }
        caif_assert(offsetof(struct cfsrvl, layer) == 0);
-       memset(vei, 0, sizeof(struct cfsrvl));
        cfsrvl_init(vei, channel_id, dev_info, true);
        vei->layer.receive = cfvei_receive;
        vei->layer.transmit = cfvei_transmit;
index b2f5989..e3f37db 100644 (file)
@@ -21,14 +21,11 @@ static int cfvidl_transmit(struct cflayer *layr, struct cfpkt *pkt);
 
 struct cflayer *cfvidl_create(u8 channel_id, struct dev_info *dev_info)
 {
-       struct cfsrvl *vid = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
-       if (!vid) {
-               pr_warn("Out of memory\n");
+       struct cfsrvl *vid = kzalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
+       if (!vid)
                return NULL;
-       }
        caif_assert(offsetof(struct cfsrvl, layer) == 0);
 
-       memset(vid, 0, sizeof(struct cfsrvl));
        cfsrvl_init(vid, channel_id, dev_info, false);
        vid->layer.receive = cfvidl_receive;
        vid->layer.transmit = cfvidl_transmit;
index 8ce926d..b9efa94 100644 (file)
@@ -719,7 +719,7 @@ int can_proto_register(const struct can_proto *cp)
                       proto);
                err = -EBUSY;
        } else
-               rcu_assign_pointer(proto_tab[proto], cp);
+               RCU_INIT_POINTER(proto_tab[proto], cp);
 
        mutex_unlock(&proto_tab_lock);
 
@@ -740,7 +740,7 @@ void can_proto_unregister(const struct can_proto *cp)
 
        mutex_lock(&proto_tab_lock);
        BUG_ON(proto_tab[proto] != cp);
-       rcu_assign_pointer(proto_tab[proto], NULL);
+       RCU_INIT_POINTER(proto_tab[proto], NULL);
        mutex_unlock(&proto_tab_lock);
 
        synchronize_rcu();
index 8a04dd2..0d357b1 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
-        gen_stats.o gen_estimator.o net_namespace.o
+        gen_stats.o gen_estimator.o net_namespace.o secure_seq.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
index 18ac112..6449bed 100644 (file)
@@ -332,7 +332,7 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
                        int err;
                        u8  *vaddr;
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-                       struct page *page = frag->page;
+                       struct page *page = skb_frag_page(frag);
 
                        if (copy > len)
                                copy = len;
@@ -418,7 +418,7 @@ int skb_copy_datagram_const_iovec(const struct sk_buff *skb, int offset,
                        int err;
                        u8  *vaddr;
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-                       struct page *page = frag->page;
+                       struct page *page = skb_frag_page(frag);
 
                        if (copy > len)
                                copy = len;
@@ -508,7 +508,7 @@ int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset,
                        int err;
                        u8  *vaddr;
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-                       struct page *page = frag->page;
+                       struct page *page = skb_frag_page(frag);
 
                        if (copy > len)
                                copy = len;
@@ -594,7 +594,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
                        int err = 0;
                        u8  *vaddr;
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-                       struct page *page = frag->page;
+                       struct page *page = skb_frag_page(frag);
 
                        if (copy > len)
                                copy = len;
index 17d67b5..b2e262e 100644 (file)
 #include <linux/pci.h>
 #include <linux/inetdevice.h>
 #include <linux/cpu_rmap.h>
+#include <linux/if_tunnel.h>
+#include <linux/if_pppox.h>
 
 #include "net-sysfs.h"
 
@@ -1947,9 +1949,11 @@ static int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
 #ifdef CONFIG_HIGHMEM
        int i;
        if (!(dev->features & NETIF_F_HIGHDMA)) {
-               for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-                       if (PageHighMem(skb_shinfo(skb)->frags[i].page))
+               for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+                       skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+                       if (PageHighMem(skb_frag_page(frag)))
                                return 1;
+               }
        }
 
        if (PCI_DMA_BUS_IS_PHYS) {
@@ -1958,7 +1962,8 @@ static int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
                if (!pdev)
                        return 0;
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-                       dma_addr_t addr = page_to_phys(skb_shinfo(skb)->frags[i].page);
+                       skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+                       dma_addr_t addr = page_to_phys(skb_frag_page(frag));
                        if (!pdev->dma_mask || addr + PAGE_SIZE - 1 > *pdev->dma_mask)
                                return 1;
                }
@@ -2519,24 +2524,29 @@ static inline void ____napi_schedule(struct softnet_data *sd,
 
 /*
  * __skb_get_rxhash: calculate a flow hash based on src/dst addresses
- * and src/dst port numbers. Returns a non-zero hash number on success
- * and 0 on failure.
+ * and src/dst port numbers.  Sets rxhash in skb to non-zero hash value
+ * on success, zero indicates no valid hash.  Also, sets l4_rxhash in skb
+ * if hash is a canonical 4-tuple hash over transport ports.
  */
-__u32 __skb_get_rxhash(struct sk_buff *skb)
+void __skb_get_rxhash(struct sk_buff *skb)
 {
        int nhoff, hash = 0, poff;
        const struct ipv6hdr *ip6;
        const struct iphdr *ip;
+       const struct vlan_hdr *vlan;
        u8 ip_proto;
-       u32 addr1, addr2, ihl;
+       u32 addr1, addr2;
+       u16 proto;
        union {
                u32 v32;
                u16 v16[2];
        } ports;
 
        nhoff = skb_network_offset(skb);
+       proto = skb->protocol;
 
-       switch (skb->protocol) {
+again:
+       switch (proto) {
        case __constant_htons(ETH_P_IP):
                if (!pskb_may_pull(skb, sizeof(*ip) + nhoff))
                        goto done;
@@ -2548,7 +2558,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb)
                        ip_proto = ip->protocol;
                addr1 = (__force u32) ip->saddr;
                addr2 = (__force u32) ip->daddr;
-               ihl = ip->ihl;
+               nhoff += ip->ihl * 4;
                break;
        case __constant_htons(ETH_P_IPV6):
                if (!pskb_may_pull(skb, sizeof(*ip6) + nhoff))
@@ -2558,20 +2568,64 @@ __u32 __skb_get_rxhash(struct sk_buff *skb)
                ip_proto = ip6->nexthdr;
                addr1 = (__force u32) ip6->saddr.s6_addr32[3];
                addr2 = (__force u32) ip6->daddr.s6_addr32[3];
-               ihl = (40 >> 2);
+               nhoff += 40;
                break;
+       case __constant_htons(ETH_P_8021Q):
+               if (!pskb_may_pull(skb, sizeof(*vlan) + nhoff))
+                       goto done;
+               vlan = (const struct vlan_hdr *) (skb->data + nhoff);
+               proto = vlan->h_vlan_encapsulated_proto;
+               nhoff += sizeof(*vlan);
+               goto again;
+       case __constant_htons(ETH_P_PPP_SES):
+               if (!pskb_may_pull(skb, PPPOE_SES_HLEN + nhoff))
+                       goto done;
+               proto = *((__be16 *) (skb->data + nhoff +
+                                     sizeof(struct pppoe_hdr)));
+               nhoff += PPPOE_SES_HLEN;
+               goto again;
        default:
                goto done;
        }
 
+       switch (ip_proto) {
+       case IPPROTO_GRE:
+               if (pskb_may_pull(skb, nhoff + 16)) {
+                       u8 *h = skb->data + nhoff;
+                       __be16 flags = *(__be16 *)h;
+
+                       /*
+                        * Only look inside GRE if version zero and no
+                        * routing
+                        */
+                       if (!(flags & (GRE_VERSION|GRE_ROUTING))) {
+                               proto = *(__be16 *)(h + 2);
+                               nhoff += 4;
+                               if (flags & GRE_CSUM)
+                                       nhoff += 4;
+                               if (flags & GRE_KEY)
+                                       nhoff += 4;
+                               if (flags & GRE_SEQ)
+                                       nhoff += 4;
+                               goto again;
+                       }
+               }
+               break;
+       case IPPROTO_IPIP:
+               goto again;
+       default:
+               break;
+       }
+
        ports.v32 = 0;
        poff = proto_ports_offset(ip_proto);
        if (poff >= 0) {
-               nhoff += ihl * 4 + poff;
+               nhoff += poff;
                if (pskb_may_pull(skb, nhoff + 4)) {
                        ports.v32 = * (__force u32 *) (skb->data + nhoff);
                        if (ports.v16[1] < ports.v16[0])
                                swap(ports.v16[0], ports.v16[1]);
+                       skb->l4_rxhash = 1;
                }
        }
 
@@ -2584,7 +2638,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb)
                hash = 1;
 
 done:
-       return hash;
+       skb->rxhash = hash;
 }
 EXPORT_SYMBOL(__skb_get_rxhash);
 
@@ -2673,13 +2727,13 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
        map = rcu_dereference(rxqueue->rps_map);
        if (map) {
                if (map->len == 1 &&
-                   !rcu_dereference_raw(rxqueue->rps_flow_table)) {
+                   !rcu_access_pointer(rxqueue->rps_flow_table)) {
                        tcpu = map->cpus[0];
                        if (cpu_online(tcpu))
                                cpu = tcpu;
                        goto done;
                }
-       } else if (!rcu_dereference_raw(rxqueue->rps_flow_table)) {
+       } else if (!rcu_access_pointer(rxqueue->rps_flow_table)) {
                goto done;
        }
 
@@ -3094,8 +3148,8 @@ void netdev_rx_handler_unregister(struct net_device *dev)
 {
 
        ASSERT_RTNL();
-       rcu_assign_pointer(dev->rx_handler, NULL);
-       rcu_assign_pointer(dev->rx_handler_data, NULL);
+       RCU_INIT_POINTER(dev->rx_handler, NULL);
+       RCU_INIT_POINTER(dev->rx_handler_data, NULL);
 }
 EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
 
@@ -3187,10 +3241,9 @@ ncls:
                        ret = deliver_skb(skb, pt_prev, orig_dev);
                        pt_prev = NULL;
                }
-               if (vlan_do_receive(&skb)) {
-                       ret = __netif_receive_skb(skb);
-                       goto out;
-               } else if (unlikely(!skb))
+               if (vlan_do_receive(&skb))
+                       goto another_round;
+               else if (unlikely(!skb))
                        goto out;
        }
 
@@ -3424,7 +3477,7 @@ pull:
                skb_shinfo(skb)->frags[0].size -= grow;
 
                if (unlikely(!skb_shinfo(skb)->frags[0].size)) {
-                       put_page(skb_shinfo(skb)->frags[0].page);
+                       skb_frag_unref(skb, 0);
                        memmove(skb_shinfo(skb)->frags,
                                skb_shinfo(skb)->frags + 1,
                                --skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t));
@@ -3488,10 +3541,9 @@ void skb_gro_reset_offset(struct sk_buff *skb)
        NAPI_GRO_CB(skb)->frag0_len = 0;
 
        if (skb->mac_header == skb->tail &&
-           !PageHighMem(skb_shinfo(skb)->frags[0].page)) {
+           !PageHighMem(skb_frag_page(&skb_shinfo(skb)->frags[0]))) {
                NAPI_GRO_CB(skb)->frag0 =
-                       page_address(skb_shinfo(skb)->frags[0].page) +
-                       skb_shinfo(skb)->frags[0].page_offset;
+                       skb_frag_address(&skb_shinfo(skb)->frags[0]);
                NAPI_GRO_CB(skb)->frag0_len = skb_shinfo(skb)->frags[0].size;
        }
 }
@@ -4489,9 +4541,7 @@ void __dev_set_rx_mode(struct net_device *dev)
        if (!netif_device_present(dev))
                return;
 
-       if (ops->ndo_set_rx_mode)
-               ops->ndo_set_rx_mode(dev);
-       else {
+       if (!(dev->priv_flags & IFF_UNICAST_FLT)) {
                /* Unicast addresses changes may only happen under the rtnl,
                 * therefore calling __dev_set_promiscuity here is safe.
                 */
@@ -4502,10 +4552,10 @@ void __dev_set_rx_mode(struct net_device *dev)
                        __dev_set_promiscuity(dev, -1);
                        dev->uc_promisc = false;
                }
-
-               if (ops->ndo_set_multicast_list)
-                       ops->ndo_set_multicast_list(dev);
        }
+
+       if (ops->ndo_set_rx_mode)
+               ops->ndo_set_rx_mode(dev);
 }
 
 void dev_set_rx_mode(struct net_device *dev)
@@ -4855,7 +4905,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
                return -EOPNOTSUPP;
 
        case SIOCADDMULTI:
-               if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) ||
+               if (!ops->ndo_set_rx_mode ||
                    ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
                        return -EINVAL;
                if (!netif_device_present(dev))
@@ -4863,7 +4913,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
                return dev_mc_add_global(dev, ifr->ifr_hwaddr.sa_data);
 
        case SIOCDELMULTI:
-               if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) ||
+               if (!ops->ndo_set_rx_mode ||
                    ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
                        return -EINVAL;
                if (!netif_device_present(dev))
@@ -5727,8 +5777,8 @@ void netdev_run_todo(void)
 
                /* paranoia */
                BUG_ON(netdev_refcnt_read(dev));
-               WARN_ON(rcu_dereference_raw(dev->ip_ptr));
-               WARN_ON(rcu_dereference_raw(dev->ip6_ptr));
+               WARN_ON(rcu_access_pointer(dev->ip_ptr));
+               WARN_ON(rcu_access_pointer(dev->ip6_ptr));
                WARN_ON(dev->dn_ptr);
 
                if (dev->destructor)
@@ -5932,7 +5982,7 @@ void free_netdev(struct net_device *dev)
        kfree(dev->_rx);
 #endif
 
-       kfree(rcu_dereference_raw(dev->ingress_queue));
+       kfree(rcu_dereference_protected(dev->ingress_queue, 1));
 
        /* Flush device addresses */
        dev_addr_flush(dev);
index e2e6693..283d1b8 100644 (file)
@@ -591,8 +591,8 @@ EXPORT_SYMBOL(dev_mc_del_global);
  *     addresses that have no users left. The source device must be
  *     locked by netif_tx_lock_bh.
  *
- *     This function is intended to be called from the dev->set_multicast_list
- *     or dev->set_rx_mode function of layered software devices.
+ *     This function is intended to be called from the ndo_set_rx_mode
+ *     function of layered software devices.
  */
 int dev_mc_sync(struct net_device *to, struct net_device *from)
 {
index 14b33ba..d5e2c4c 100644 (file)
@@ -171,7 +171,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
        dst_init_metrics(dst, dst_default_metrics, true);
        dst->expires = 0UL;
        dst->path = dst;
-       dst->_neighbour = NULL;
+       RCU_INIT_POINTER(dst->_neighbour, NULL);
 #ifdef CONFIG_XFRM
        dst->xfrm = NULL;
 #endif
@@ -229,11 +229,11 @@ struct dst_entry *dst_destroy(struct dst_entry * dst)
        smp_rmb();
 
 again:
-       neigh = dst->_neighbour;
+       neigh = rcu_dereference_protected(dst->_neighbour, 1);
        child = dst->child;
 
        if (neigh) {
-               dst->_neighbour = NULL;
+               RCU_INIT_POINTER(dst->_neighbour, NULL);
                neigh_release(neigh);
        }
 
@@ -360,14 +360,19 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
        if (!unregister) {
                dst->input = dst->output = dst_discard;
        } else {
+               struct neighbour *neigh;
+
                dst->dev = dev_net(dst->dev)->loopback_dev;
                dev_hold(dst->dev);
                dev_put(dev);
-               if (dst->_neighbour && dst->_neighbour->dev == dev) {
-                       dst->_neighbour->dev = dst->dev;
+               rcu_read_lock();
+               neigh = dst_get_neighbour(dst);
+               if (neigh && neigh->dev == dev) {
+                       neigh->dev = dst->dev;
                        dev_hold(dst->dev);
                        dev_put(dev);
                }
+               rcu_read_unlock();
        }
 }
 
index e7ab0c0..67c5c28 100644 (file)
@@ -487,7 +487,7 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
                if (ops->nr_goto_rules > 0) {
                        list_for_each_entry(tmp, &ops->rules_list, list) {
                                if (rtnl_dereference(tmp->ctarget) == rule) {
-                                       rcu_assign_pointer(tmp->ctarget, NULL);
+                                       RCU_INIT_POINTER(tmp->ctarget, NULL);
                                        ops->unresolved_rules++;
                                }
                        }
@@ -545,7 +545,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
        frh->flags = rule->flags;
 
        if (rule->action == FR_ACT_GOTO &&
-           rcu_dereference_raw(rule->ctarget) == NULL)
+           rcu_access_pointer(rule->ctarget) == NULL)
                frh->flags |= FIB_RULE_UNRESOLVED;
 
        if (rule->iifname[0]) {
index 36f975f..8fcc2d7 100644 (file)
@@ -645,7 +645,7 @@ int sk_detach_filter(struct sock *sk)
        filter = rcu_dereference_protected(sk->sk_filter,
                                           sock_owned_by_user(sk));
        if (filter) {
-               rcu_assign_pointer(sk->sk_filter, NULL);
+               RCU_INIT_POINTER(sk->sk_filter, NULL);
                sk_filter_uncharge(sk, filter);
                ret = 0;
        }
index 283c2b9..81e1ed7 100644 (file)
@@ -7,7 +7,7 @@ static inline void *kmap_skb_frag(const skb_frag_t *frag)
 
        local_bh_disable();
 #endif
-       return kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ);
+       return kmap_atomic(skb_frag_page(frag), KM_SKB_DATA_SOFTIRQ);
 }
 
 static inline void kunmap_skb_frag(void *vaddr)
index 8fab9b0..4002261 100644 (file)
@@ -844,6 +844,19 @@ static void neigh_invalidate(struct neighbour *neigh)
        skb_queue_purge(&neigh->arp_queue);
 }
 
+static void neigh_probe(struct neighbour *neigh)
+       __releases(neigh->lock)
+{
+       struct sk_buff *skb = skb_peek(&neigh->arp_queue);
+       /* keep skb alive even if arp_queue overflows */
+       if (skb)
+               skb = skb_copy(skb, GFP_ATOMIC);
+       write_unlock(&neigh->lock);
+       neigh->ops->solicit(neigh, skb);
+       atomic_inc(&neigh->probes);
+       kfree_skb(skb);
+}
+
 /* Called when a timer expires for a neighbour entry. */
 
 static void neigh_timer_handler(unsigned long arg)
@@ -920,14 +933,7 @@ static void neigh_timer_handler(unsigned long arg)
                        neigh_hold(neigh);
        }
        if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
-               struct sk_buff *skb = skb_peek(&neigh->arp_queue);
-               /* keep skb alive even if arp_queue overflows */
-               if (skb)
-                       skb = skb_copy(skb, GFP_ATOMIC);
-               write_unlock(&neigh->lock);
-               neigh->ops->solicit(neigh, skb);
-               atomic_inc(&neigh->probes);
-               kfree_skb(skb);
+               neigh_probe(neigh);
        } else {
 out:
                write_unlock(&neigh->lock);
@@ -942,7 +948,7 @@ out:
 int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
 {
        int rc;
-       unsigned long now;
+       bool immediate_probe = false;
 
        write_lock_bh(&neigh->lock);
 
@@ -950,14 +956,16 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
        if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
                goto out_unlock_bh;
 
-       now = jiffies;
-
        if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
                if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
+                       unsigned long next, now = jiffies;
+
                        atomic_set(&neigh->probes, neigh->parms->ucast_probes);
                        neigh->nud_state     = NUD_INCOMPLETE;
-                       neigh->updated = jiffies;
-                       neigh_add_timer(neigh, now + 1);
+                       neigh->updated = now;
+                       next = now + max(neigh->parms->retrans_time, HZ/2);
+                       neigh_add_timer(neigh, next);
+                       immediate_probe = true;
                } else {
                        neigh->nud_state = NUD_FAILED;
                        neigh->updated = jiffies;
@@ -989,7 +997,11 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
                rc = 1;
        }
 out_unlock_bh:
-       write_unlock_bh(&neigh->lock);
+       if (immediate_probe)
+               neigh_probe(neigh);
+       else
+               write_unlock(&neigh->lock);
+       local_bh_enable();
        return rc;
 }
 EXPORT_SYMBOL(__neigh_event_send);
index 1683e5d..56e42ab 100644 (file)
@@ -712,13 +712,13 @@ static void rx_queue_release(struct kobject *kobj)
        struct rps_dev_flow_table *flow_table;
 
 
-       map = rcu_dereference_raw(queue->rps_map);
+       map = rcu_dereference_protected(queue->rps_map, 1);
        if (map) {
                RCU_INIT_POINTER(queue->rps_map, NULL);
                kfree_rcu(map, rcu);
        }
 
-       flow_table = rcu_dereference_raw(queue->rps_flow_table);
+       flow_table = rcu_dereference_protected(queue->rps_flow_table, 1);
        if (flow_table) {
                RCU_INIT_POINTER(queue->rps_flow_table, NULL);
                call_rcu(&flow_table->rcu, rps_dev_flow_table_release);
@@ -987,10 +987,10 @@ static ssize_t store_xps_map(struct netdev_queue *queue,
        }
 
        if (nonempty)
-               rcu_assign_pointer(dev->xps_maps, new_dev_maps);
+               RCU_INIT_POINTER(dev->xps_maps, new_dev_maps);
        else {
                kfree(new_dev_maps);
-               rcu_assign_pointer(dev->xps_maps, NULL);
+               RCU_INIT_POINTER(dev->xps_maps, NULL);
        }
 
        if (dev_maps)
index adf84dd..d676a56 100644 (file)
@@ -760,7 +760,7 @@ int __netpoll_setup(struct netpoll *np)
        }
 
        /* last thing to do is link it to the net device structure */
-       rcu_assign_pointer(ndev->npinfo, npinfo);
+       RCU_INIT_POINTER(ndev->npinfo, npinfo);
 
        return 0;
 
@@ -901,7 +901,7 @@ void __netpoll_cleanup(struct netpoll *np)
                if (ops->ndo_netpoll_cleanup)
                        ops->ndo_netpoll_cleanup(np->dev);
 
-               rcu_assign_pointer(np->dev->npinfo, NULL);
+               RCU_INIT_POINTER(np->dev->npinfo, NULL);
 
                /* avoid racing with NAPI reading npinfo */
                synchronize_rcu_bh();
index e35a6fb..796044a 100644 (file)
@@ -2602,8 +2602,7 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb,
                                if (!pkt_dev->page)
                                        break;
                        }
-                       skb_shinfo(skb)->frags[i].page = pkt_dev->page;
-                       get_page(pkt_dev->page);
+                       skb_frag_set_page(skb, i, pkt_dev->page);
                        skb_shinfo(skb)->frags[i].page_offset = 0;
                        /*last fragment, fill rest of data*/
                        if (i == (frags - 1))
index 99d9e95..39f8dd6 100644 (file)
@@ -1604,7 +1604,6 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
        dev_net_set(dev, net);
        dev->rtnl_link_ops = ops;
        dev->rtnl_link_state = RTNL_LINK_INITIALIZING;
-       dev->real_num_tx_queues = real_num_queues;
 
        if (tb[IFLA_MTU])
                dev->mtu = nla_get_u32(tb[IFLA_MTU]);
index 4c1ef02..811b53f 100644 (file)
@@ -192,7 +192,7 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
                                        goto error;
 
                                cred->uid = cred->euid = p->creds.uid;
-                               cred->gid = cred->egid = p->creds.uid;
+                               cred->gid = cred->egid = p->creds.gid;
                                put_cred(p->cred);
                                p->cred = cred;
                        }
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
new file mode 100644 (file)
index 0000000..45329d7
--- /dev/null
@@ -0,0 +1,184 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cryptohash.h>
+#include <linux/module.h>
+#include <linux/cache.h>
+#include <linux/random.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
+#include <linux/string.h>
+
+#include <net/secure_seq.h>
+
+static u32 net_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
+
+static int __init net_secret_init(void)
+{
+       get_random_bytes(net_secret, sizeof(net_secret));
+       return 0;
+}
+late_initcall(net_secret_init);
+
+static u32 seq_scale(u32 seq)
+{
+       /*
+        *      As close as possible to RFC 793, which
+        *      suggests using a 250 kHz clock.
+        *      Further reading shows this assumes 2 Mb/s networks.
+        *      For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
+        *      For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
+        *      we also need to limit the resolution so that the u32 seq
+        *      overlaps less than one time per MSL (2 minutes).
+        *      Choosing a clock of 64 ns period is OK. (period of 274 s)
+        */
+       return seq + (ktime_to_ns(ktime_get_real()) >> 6);
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+__u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+                                  __be16 sport, __be16 dport)
+{
+       u32 secret[MD5_MESSAGE_BYTES / 4];
+       u32 hash[MD5_DIGEST_WORDS];
+       u32 i;
+
+       memcpy(hash, saddr, 16);
+       for (i = 0; i < 4; i++)
+               secret[i] = net_secret[i] + daddr[i];
+       secret[4] = net_secret[4] +
+               (((__force u16)sport << 16) + (__force u16)dport);
+       for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
+               secret[i] = net_secret[i];
+
+       md5_transform(hash, secret);
+
+       return seq_scale(hash[0]);
+}
+EXPORT_SYMBOL(secure_tcpv6_sequence_number);
+
+u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+                              __be16 dport)
+{
+       u32 secret[MD5_MESSAGE_BYTES / 4];
+       u32 hash[MD5_DIGEST_WORDS];
+       u32 i;
+
+       memcpy(hash, saddr, 16);
+       for (i = 0; i < 4; i++)
+               secret[i] = net_secret[i] + (__force u32) daddr[i];
+       secret[4] = net_secret[4] + (__force u32)dport;
+       for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
+               secret[i] = net_secret[i];
+
+       md5_transform(hash, secret);
+
+       return hash[0];
+}
+#endif
+
+#ifdef CONFIG_INET
+__u32 secure_ip_id(__be32 daddr)
+{
+       u32 hash[MD5_DIGEST_WORDS];
+
+       hash[0] = (__force __u32) daddr;
+       hash[1] = net_secret[13];
+       hash[2] = net_secret[14];
+       hash[3] = net_secret[15];
+
+       md5_transform(hash, net_secret);
+
+       return hash[0];
+}
+
+__u32 secure_ipv6_id(const __be32 daddr[4])
+{
+       __u32 hash[4];
+
+       memcpy(hash, daddr, 16);
+       md5_transform(hash, net_secret);
+
+       return hash[0];
+}
+
+__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+                                __be16 sport, __be16 dport)
+{
+       u32 hash[MD5_DIGEST_WORDS];
+
+       hash[0] = (__force u32)saddr;
+       hash[1] = (__force u32)daddr;
+       hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
+       hash[3] = net_secret[15];
+
+       md5_transform(hash, net_secret);
+
+       return seq_scale(hash[0]);
+}
+
+u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
+{
+       u32 hash[MD5_DIGEST_WORDS];
+
+       hash[0] = (__force u32)saddr;
+       hash[1] = (__force u32)daddr;
+       hash[2] = (__force u32)dport ^ net_secret[14];
+       hash[3] = net_secret[15];
+
+       md5_transform(hash, net_secret);
+
+       return hash[0];
+}
+EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
+#endif
+
+#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
+u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
+                               __be16 sport, __be16 dport)
+{
+       u32 hash[MD5_DIGEST_WORDS];
+       u64 seq;
+
+       hash[0] = (__force u32)saddr;
+       hash[1] = (__force u32)daddr;
+       hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
+       hash[3] = net_secret[15];
+
+       md5_transform(hash, net_secret);
+
+       seq = hash[0] | (((u64)hash[1]) << 32);
+       seq += ktime_to_ns(ktime_get_real());
+       seq &= (1ull << 48) - 1;
+
+       return seq;
+}
+EXPORT_SYMBOL(secure_dccp_sequence_number);
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+                                 __be16 sport, __be16 dport)
+{
+       u32 secret[MD5_MESSAGE_BYTES / 4];
+       u32 hash[MD5_DIGEST_WORDS];
+       u64 seq;
+       u32 i;
+
+       memcpy(hash, saddr, 16);
+       for (i = 0; i < 4; i++)
+               secret[i] = net_secret[i] + daddr[i];
+       secret[4] = net_secret[4] +
+               (((__force u16)sport << 16) + (__force u16)dport);
+       for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
+               secret[i] = net_secret[i];
+
+       md5_transform(hash, secret);
+
+       seq = hash[0] | (((u64)hash[1]) << 32);
+       seq += ktime_to_ns(ktime_get_real());
+       seq &= (1ull << 48) - 1;
+
+       return seq;
+}
+EXPORT_SYMBOL(secure_dccpv6_sequence_number);
+#endif
+#endif
index 2beda82..296afd0 100644 (file)
@@ -326,7 +326,7 @@ static void skb_release_data(struct sk_buff *skb)
                if (skb_shinfo(skb)->nr_frags) {
                        int i;
                        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-                               put_page(skb_shinfo(skb)->frags[i].page);
+                               skb_frag_unref(skb, i);
                }
 
                /*
@@ -529,6 +529,8 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
        new->mac_header         = old->mac_header;
        skb_dst_copy(new, old);
        new->rxhash             = old->rxhash;
+       new->ooo_okay           = old->ooo_okay;
+       new->l4_rxhash          = old->l4_rxhash;
 #ifdef CONFIG_XFRM
        new->sp                 = secpath_get(old->sp);
 #endif
@@ -807,7 +809,7 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask)
                }
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                        skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
-                       get_page(skb_shinfo(n)->frags[i].page);
+                       skb_frag_ref(skb, i);
                }
                skb_shinfo(n)->nr_frags = i;
        }
@@ -899,7 +901,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
                        skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
                }
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-                       get_page(skb_shinfo(skb)->frags[i].page);
+                       skb_frag_ref(skb, i);
 
                if (skb_has_frag_list(skb))
                        skb_clone_fraglist(skb);
@@ -1179,7 +1181,7 @@ drop_pages:
                skb_shinfo(skb)->nr_frags = i;
 
                for (; i < nfrags; i++)
-                       put_page(skb_shinfo(skb)->frags[i].page);
+                       skb_frag_unref(skb, i);
 
                if (skb_has_frag_list(skb))
                        skb_drop_fraglist(skb);
@@ -1348,7 +1350,7 @@ pull_pages:
        k = 0;
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                if (skb_shinfo(skb)->frags[i].size <= eat) {
-                       put_page(skb_shinfo(skb)->frags[i].page);
+                       skb_frag_unref(skb, i);
                        eat -= skb_shinfo(skb)->frags[i].size;
                } else {
                        skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
@@ -1369,8 +1371,21 @@ pull_pages:
 }
 EXPORT_SYMBOL(__pskb_pull_tail);
 
-/* Copy some data bits from skb to kernel buffer. */
-
+/**
+ *     skb_copy_bits - copy bits from skb to kernel buffer
+ *     @skb: source skb
+ *     @offset: offset in source
+ *     @to: destination buffer
+ *     @len: number of bytes to copy
+ *
+ *     Copy the specified number of bytes from the source skb to the
+ *     destination buffer.
+ *
+ *     CAUTION ! :
+ *             If its prototype is ever changed,
+ *             check arch/{*}/net/{*}.S files,
+ *             since it is called from BPF assembly code.
+ */
 int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
 {
        int start = skb_headlen(skb);
@@ -1594,7 +1609,8 @@ static int __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
        for (seg = 0; seg < skb_shinfo(skb)->nr_frags; seg++) {
                const skb_frag_t *f = &skb_shinfo(skb)->frags[seg];
 
-               if (__splice_segment(f->page, f->page_offset, f->size,
+               if (__splice_segment(skb_frag_page(f),
+                                    f->page_offset, f->size,
                                     offset, len, skb, spd, 0, sk, pipe))
                        return 1;
        }
@@ -2139,7 +2155,7 @@ static inline void skb_split_no_header(struct sk_buff *skb,
                                 *    where splitting is expensive.
                                 * 2. Split is accurately. We make this.
                                 */
-                               get_page(skb_shinfo(skb)->frags[i].page);
+                               skb_frag_ref(skb, i);
                                skb_shinfo(skb1)->frags[0].page_offset += len - pos;
                                skb_shinfo(skb1)->frags[0].size -= len - pos;
                                skb_shinfo(skb)->frags[i].size  = len - pos;
@@ -2214,7 +2230,8 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
         * commit all, so that we don't have to undo partial changes
         */
        if (!to ||
-           !skb_can_coalesce(tgt, to, fragfrom->page, fragfrom->page_offset)) {
+           !skb_can_coalesce(tgt, to, skb_frag_page(fragfrom),
+                             fragfrom->page_offset)) {
                merge = -1;
        } else {
                merge = to - 1;
@@ -2261,7 +2278,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
                        to++;
 
                } else {
-                       get_page(fragfrom->page);
+                       __skb_frag_ref(fragfrom);
                        fragto->page = fragfrom->page;
                        fragto->page_offset = fragfrom->page_offset;
                        fragto->size = todo;
@@ -2283,7 +2300,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
                fragto = &skb_shinfo(tgt)->frags[merge];
 
                fragto->size += fragfrom->size;
-               put_page(fragfrom->page);
+               __skb_frag_unref(fragfrom);
        }
 
        /* Reposition in the original skb */
@@ -2528,8 +2545,7 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
                left = PAGE_SIZE - frag->page_offset;
                copy = (length > left)? left : length;
 
-               ret = getfrag(from, (page_address(frag->page) +
-                           frag->page_offset + frag->size),
+               ret = getfrag(from, skb_frag_address(frag) + frag->size,
                            offset, copy, 0, skb);
                if (ret < 0)
                        return -EFAULT;
@@ -2681,7 +2697,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, u32 features)
 
                while (pos < offset + len && i < nfrags) {
                        *frag = skb_shinfo(skb)->frags[i];
-                       get_page(frag->page);
+                       __skb_frag_ref(frag);
                        size = frag->size;
 
                        if (pos < offset) {
@@ -2904,7 +2920,7 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
 
                        if (copy > len)
                                copy = len;
-                       sg_set_page(&sg[elt], frag->page, copy,
+                       sg_set_page(&sg[elt], skb_frag_page(frag), copy,
                                        frag->page_offset+offset-start);
                        elt++;
                        if (!(len -= copy))
index bc745d0..b29ab61 100644 (file)
@@ -387,7 +387,7 @@ struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie)
 
        if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
                sk_tx_queue_clear(sk);
-               rcu_assign_pointer(sk->sk_dst_cache, NULL);
+               RCU_INIT_POINTER(sk->sk_dst_cache, NULL);
                dst_release(dst);
                return NULL;
        }
@@ -1158,7 +1158,7 @@ static void __sk_free(struct sock *sk)
                                       atomic_read(&sk->sk_wmem_alloc) == 0);
        if (filter) {
                sk_filter_uncharge(sk, filter);
-               rcu_assign_pointer(sk->sk_filter, NULL);
+               RCU_INIT_POINTER(sk->sk_filter, NULL);
        }
 
        sock_disable_timestamp(sk, SOCK_TIMESTAMP);
@@ -1533,7 +1533,6 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
                                skb_shinfo(skb)->nr_frags = npages;
                                for (i = 0; i < npages; i++) {
                                        struct page *page;
-                                       skb_frag_t *frag;
 
                                        page = alloc_pages(sk->sk_allocation, 0);
                                        if (!page) {
@@ -1543,12 +1542,11 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
                                                goto failure;
                                        }
 
-                                       frag = &skb_shinfo(skb)->frags[i];
-                                       frag->page = page;
-                                       frag->page_offset = 0;
-                                       frag->size = (data_len >= PAGE_SIZE ?
-                                                     PAGE_SIZE :
-                                                     data_len);
+                                       __skb_fill_page_desc(skb, i,
+                                                       page, 0,
+                                                       (data_len >= PAGE_SIZE ?
+                                                        PAGE_SIZE :
+                                                        data_len));
                                        data_len -= PAGE_SIZE;
                                }
 
index 25d717e..34e9664 100644 (file)
@@ -78,7 +78,7 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan,
                copy = end - offset;
                if (copy > 0) {
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-                       struct page *page = frag->page;
+                       struct page *page = skb_frag_page(frag);
 
                        if (copy > len)
                                copy = len;
index 0462040..67164bb 100644 (file)
@@ -85,7 +85,6 @@ static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
 
 static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val)
 {
-       struct dccp_sock *dp = dccp_sk(sk);
        u32 max_ratio = DIV_ROUND_UP(ccid2_hc_tx_sk(sk)->tx_cwnd, 2);
 
        /*
@@ -98,14 +97,33 @@ static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val)
                DCCP_WARN("Limiting Ack Ratio (%u) to %u\n", val, max_ratio);
                val = max_ratio;
        }
-       if (val > DCCPF_ACK_RATIO_MAX)
-               val = DCCPF_ACK_RATIO_MAX;
+       dccp_feat_signal_nn_change(sk, DCCPF_ACK_RATIO,
+                                  min_t(u32, val, DCCPF_ACK_RATIO_MAX));
+}
 
-       if (val == dp->dccps_l_ack_ratio)
-               return;
+static void ccid2_check_l_ack_ratio(struct sock *sk)
+{
+       struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
 
-       ccid2_pr_debug("changing local ack ratio to %u\n", val);
-       dp->dccps_l_ack_ratio = val;
+       /*
+        * After a loss, idle period, application limited period, or RTO we
+        * need to check that the ack ratio is still less than the congestion
+        * window. Otherwise, we will send an entire congestion window of
+        * packets and got no response because we haven't sent ack ratio
+        * packets yet.
+        * If the ack ratio does need to be reduced, we reduce it to half of
+        * the congestion window (or 1 if that's zero) instead of to the
+        * congestion window. This prevents problems if one ack is lost.
+        */
+       if (dccp_feat_nn_get(sk, DCCPF_ACK_RATIO) > hc->tx_cwnd)
+               ccid2_change_l_ack_ratio(sk, hc->tx_cwnd/2 ? : 1U);
+}
+
+static void ccid2_change_l_seq_window(struct sock *sk, u64 val)
+{
+       dccp_feat_signal_nn_change(sk, DCCPF_SEQUENCE_WINDOW,
+                                  clamp_val(val, DCCPF_SEQ_WMIN,
+                                                 DCCPF_SEQ_WMAX));
 }
 
 static void ccid2_hc_tx_rto_expire(unsigned long data)
@@ -187,6 +205,8 @@ static void ccid2_cwnd_application_limited(struct sock *sk, const u32 now)
        }
        hc->tx_cwnd_used  = 0;
        hc->tx_cwnd_stamp = now;
+
+       ccid2_check_l_ack_ratio(sk);
 }
 
 /* This borrows the code of tcp_cwnd_restart() */
@@ -205,6 +225,8 @@ static void ccid2_cwnd_restart(struct sock *sk, const u32 now)
 
        hc->tx_cwnd_stamp = now;
        hc->tx_cwnd_used  = 0;
+
+       ccid2_check_l_ack_ratio(sk);
 }
 
 static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
@@ -405,17 +427,37 @@ static void ccid2_new_ack(struct sock *sk, struct ccid2_seq *seqp,
                          unsigned int *maxincr)
 {
        struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
-
-       if (hc->tx_cwnd < hc->tx_ssthresh) {
-               if (*maxincr > 0 && ++hc->tx_packets_acked == 2) {
+       struct dccp_sock *dp = dccp_sk(sk);
+       int r_seq_used = hc->tx_cwnd / dp->dccps_l_ack_ratio;
+
+       if (hc->tx_cwnd < dp->dccps_l_seq_win &&
+           r_seq_used < dp->dccps_r_seq_win) {
+               if (hc->tx_cwnd < hc->tx_ssthresh) {
+                       if (*maxincr > 0 && ++hc->tx_packets_acked >= 2) {
+                               hc->tx_cwnd += 1;
+                               *maxincr    -= 1;
+                               hc->tx_packets_acked = 0;
+                       }
+               } else if (++hc->tx_packets_acked >= hc->tx_cwnd) {
                        hc->tx_cwnd += 1;
-                       *maxincr    -= 1;
                        hc->tx_packets_acked = 0;
                }
-       } else if (++hc->tx_packets_acked >= hc->tx_cwnd) {
-                       hc->tx_cwnd += 1;
-                       hc->tx_packets_acked = 0;
        }
+
+       /*
+        * Adjust the local sequence window and the ack ratio to allow about
+        * 5 times the number of packets in the network (RFC 4340 7.5.2)
+        */
+       if (r_seq_used * CCID2_WIN_CHANGE_FACTOR >= dp->dccps_r_seq_win)
+               ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio * 2);
+       else if (r_seq_used * CCID2_WIN_CHANGE_FACTOR < dp->dccps_r_seq_win/2)
+               ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio / 2 ? : 1U);
+
+       if (hc->tx_cwnd * CCID2_WIN_CHANGE_FACTOR >= dp->dccps_l_seq_win)
+               ccid2_change_l_seq_window(sk, dp->dccps_l_seq_win * 2);
+       else if (hc->tx_cwnd * CCID2_WIN_CHANGE_FACTOR < dp->dccps_l_seq_win/2)
+               ccid2_change_l_seq_window(sk, dp->dccps_l_seq_win / 2);
+
        /*
         * FIXME: RTT is sampled several times per acknowledgment (for each
         * entry in the Ack Vector), instead of once per Ack (as in TCP SACK).
@@ -441,9 +483,7 @@ static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp)
        hc->tx_cwnd      = hc->tx_cwnd / 2 ? : 1U;
        hc->tx_ssthresh  = max(hc->tx_cwnd, 2U);
 
-       /* Avoid spurious timeouts resulting from Ack Ratio > cwnd */
-       if (dccp_sk(sk)->dccps_l_ack_ratio > hc->tx_cwnd)
-               ccid2_change_l_ack_ratio(sk, hc->tx_cwnd);
+       ccid2_check_l_ack_ratio(sk);
 }
 
 static int ccid2_hc_tx_parse_options(struct sock *sk, u8 packet_type,
@@ -494,8 +534,16 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
                        if (hc->tx_rpdupack >= NUMDUPACK) {
                                hc->tx_rpdupack = -1; /* XXX lame */
                                hc->tx_rpseq    = 0;
-
+#ifdef __CCID2_COPES_GRACEFULLY_WITH_ACK_CONGESTION_CONTROL__
+                               /*
+                                * FIXME: Ack Congestion Control is broken; in
+                                * the current state instabilities occurred with
+                                * Ack Ratios greater than 1; causing hang-ups
+                                * and long RTO timeouts. This needs to be fixed
+                                * before opening up dynamic changes. -- gerrit
+                                */
                                ccid2_change_l_ack_ratio(sk, 2 * dp->dccps_l_ack_ratio);
+#endif
                        }
                }
        }
index f585d33..18c9754 100644 (file)
@@ -43,6 +43,12 @@ struct ccid2_seq {
 #define CCID2_SEQBUF_LEN 1024
 #define CCID2_SEQBUF_MAX 128
 
+/*
+ * Multiple of congestion window to keep the sequence window at
+ * (RFC 4340 7.5.2)
+ */
+#define CCID2_WIN_CHANGE_FACTOR 5
+
 /**
  * struct ccid2_hc_tx_sock - CCID2 TX half connection
  * @tx_{cwnd,ssthresh,pipe}: as per RFC 4341, section 5
index 5fdb072..583490a 100644 (file)
@@ -474,6 +474,7 @@ static inline int dccp_ack_pending(const struct sock *sk)
        return dccp_ackvec_pending(sk) || inet_csk_ack_scheduled(sk);
 }
 
+extern int  dccp_feat_signal_nn_change(struct sock *sk, u8 feat, u64 nn_val);
 extern int  dccp_feat_finalise_settings(struct dccp_sock *dp);
 extern int  dccp_feat_server_ccid_dependencies(struct dccp_request_sock *dreq);
 extern int  dccp_feat_insert_opts(struct dccp_sock*, struct dccp_request_sock*,
index 568def9..23cea0e 100644 (file)
@@ -12,6 +12,7 @@
  *  -----------
  *  o Feature negotiation is coordinated with connection setup (as in TCP), wild
  *    changes of parameters of an established connection are not supported.
+ *  o Changing non-negotiable (NN) values is supported in state OPEN/PARTOPEN.
  *  o All currently known SP features have 1-byte quantities. If in the future
  *    extensions of RFCs 4340..42 define features with item lengths larger than
  *    one byte, a feature-specific extension of the code will be required.
@@ -343,6 +344,20 @@ static int __dccp_feat_activate(struct sock *sk, const int idx,
        return dccp_feat_table[idx].activation_hdlr(sk, val, rx);
 }
 
+/**
+ * dccp_feat_activate  -  Activate feature value on socket
+ * @sk: fully connected DCCP socket (after handshake is complete)
+ * @feat_num: feature to activate, one of %dccp_feature_numbers
+ * @local: whether local (1) or remote (0) @feat_num is meant
+ * @fval: the value (SP or NN) to activate, or NULL to use the default value
+ * For general use this function is preferable over __dccp_feat_activate().
+ */
+static int dccp_feat_activate(struct sock *sk, u8 feat_num, bool local,
+                             dccp_feat_val const *fval)
+{
+       return __dccp_feat_activate(sk, dccp_feat_index(feat_num), local, fval);
+}
+
 /* Test for "Req'd" feature (RFC 4340, 6.4) */
 static inline int dccp_feat_must_be_understood(u8 feat_num)
 {
@@ -650,11 +665,22 @@ int dccp_feat_insert_opts(struct dccp_sock *dp, struct dccp_request_sock *dreq,
                        return -1;
                if (pos->needs_mandatory && dccp_insert_option_mandatory(skb))
                        return -1;
-               /*
-                * Enter CHANGING after transmitting the Change option (6.6.2).
-                */
-               if (pos->state == FEAT_INITIALISING)
-                       pos->state = FEAT_CHANGING;
+
+               if (skb->sk->sk_state == DCCP_OPEN &&
+                   (opt == DCCPO_CONFIRM_R || opt == DCCPO_CONFIRM_L)) {
+                       /*
+                        * Confirms don't get retransmitted (6.6.3) once the
+                        * connection is in state OPEN
+                        */
+                       dccp_feat_list_pop(pos);
+               } else {
+                       /*
+                        * Enter CHANGING after transmitting the Change
+                        * option (6.6.2).
+                        */
+                       if (pos->state == FEAT_INITIALISING)
+                               pos->state = FEAT_CHANGING;
+               }
        }
        return 0;
 }
@@ -730,6 +756,70 @@ int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local,
                                  0, list, len);
 }
 
+/**
+ * dccp_feat_nn_get  -  Query current/pending value of NN feature
+ * @sk: DCCP socket of an established connection
+ * @feat: NN feature number from %dccp_feature_numbers
+ * For a known NN feature, returns value currently being negotiated, or
+ * current (confirmed) value if no negotiation is going on.
+ */
+u64 dccp_feat_nn_get(struct sock *sk, u8 feat)
+{
+       if (dccp_feat_type(feat) == FEAT_NN) {
+               struct dccp_sock *dp = dccp_sk(sk);
+               struct dccp_feat_entry *entry;
+
+               entry = dccp_feat_list_lookup(&dp->dccps_featneg, feat, 1);
+               if (entry != NULL)
+                       return entry->val.nn;
+
+               switch (feat) {
+               case DCCPF_ACK_RATIO:
+                       return dp->dccps_l_ack_ratio;
+               case DCCPF_SEQUENCE_WINDOW:
+                       return dp->dccps_l_seq_win;
+               }
+       }
+       DCCP_BUG("attempt to look up unsupported feature %u", feat);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dccp_feat_nn_get);
+
+/**
+ * dccp_feat_signal_nn_change  -  Update NN values for an established connection
+ * @sk: DCCP socket of an established connection
+ * @feat: NN feature number from %dccp_feature_numbers
+ * @nn_val: the new value to use
+ * This function is used to communicate NN updates out-of-band.
+ */
+int dccp_feat_signal_nn_change(struct sock *sk, u8 feat, u64 nn_val)
+{
+       struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
+       dccp_feat_val fval = { .nn = nn_val };
+       struct dccp_feat_entry *entry;
+
+       if (sk->sk_state != DCCP_OPEN && sk->sk_state != DCCP_PARTOPEN)
+               return 0;
+
+       if (dccp_feat_type(feat) != FEAT_NN ||
+           !dccp_feat_is_valid_nn_val(feat, nn_val))
+               return -EINVAL;
+
+       if (nn_val == dccp_feat_nn_get(sk, feat))
+               return 0;       /* already set or negotiation under way */
+
+       entry = dccp_feat_list_lookup(fn, feat, 1);
+       if (entry != NULL) {
+               dccp_pr_debug("Clobbering existing NN entry %llu -> %llu\n",
+                             (unsigned long long)entry->val.nn,
+                             (unsigned long long)nn_val);
+               dccp_feat_list_pop(entry);
+       }
+
+       inet_csk_schedule_ack(sk);
+       return dccp_feat_push_change(fn, feat, 1, 0, &fval);
+}
+EXPORT_SYMBOL_GPL(dccp_feat_signal_nn_change);
 
 /*
  *     Tracking features whose value depend on the choice of CCID
@@ -1186,6 +1276,100 @@ confirmation_failed:
                            : DCCP_RESET_CODE_OPTION_ERROR;
 }
 
+/**
+ * dccp_feat_handle_nn_established  -  Fast-path reception of NN options
+ * @sk:                socket of an established DCCP connection
+ * @mandatory: whether @opt was preceded by a Mandatory option
+ * @opt:       %DCCPO_CHANGE_L | %DCCPO_CONFIRM_R (NN only)
+ * @feat:      NN number, one of %dccp_feature_numbers
+ * @val:       NN value
+ * @len:       length of @val in bytes
+ * This function combines the functionality of change_recv/confirm_recv, with
+ * the following differences (reset codes are the same):
+ *    - cleanup after receiving the Confirm;
+ *    - values are directly activated after successful parsing;
+ *    - deliberately restricted to NN features.
+ * The restriction to NN features is essential since SP features can have non-
+ * predictable outcomes (depending on the remote configuration), and are inter-
+ * dependent (CCIDs for instance cause further dependencies).
+ */
+static u8 dccp_feat_handle_nn_established(struct sock *sk, u8 mandatory, u8 opt,
+                                         u8 feat, u8 *val, u8 len)
+{
+       struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
+       const bool local = (opt == DCCPO_CONFIRM_R);
+       struct dccp_feat_entry *entry;
+       u8 type = dccp_feat_type(feat);
+       dccp_feat_val fval;
+
+       dccp_feat_print_opt(opt, feat, val, len, mandatory);
+
+       /* Ignore non-mandatory unknown and non-NN features */
+       if (type == FEAT_UNKNOWN) {
+               if (local && !mandatory)
+                       return 0;
+               goto fast_path_unknown;
+       } else if (type != FEAT_NN) {
+               return 0;
+       }
+
+       /*
+        * We don't accept empty Confirms, since in fast-path feature
+        * negotiation the values are enabled immediately after sending
+        * the Change option.
+        * Empty Changes on the other hand are invalid (RFC 4340, 6.1).
+        */
+       if (len == 0 || len > sizeof(fval.nn))
+               goto fast_path_unknown;
+
+       if (opt == DCCPO_CHANGE_L) {
+               fval.nn = dccp_decode_value_var(val, len);
+               if (!dccp_feat_is_valid_nn_val(feat, fval.nn))
+                       goto fast_path_unknown;
+
+               if (dccp_feat_push_confirm(fn, feat, local, &fval) ||
+                   dccp_feat_activate(sk, feat, local, &fval))
+                       return DCCP_RESET_CODE_TOO_BUSY;
+
+               /* set the `Ack Pending' flag to piggyback a Confirm */
+               inet_csk_schedule_ack(sk);
+
+       } else if (opt == DCCPO_CONFIRM_R) {
+               entry = dccp_feat_list_lookup(fn, feat, local);
+               if (entry == NULL || entry->state != FEAT_CHANGING)
+                       return 0;
+
+               fval.nn = dccp_decode_value_var(val, len);
+               /*
+                * Just ignore a value that doesn't match our current value.
+                * If the option changes twice within two RTTs, then at least
+                * one CONFIRM will be received for the old value after a
+                * new CHANGE was sent.
+                */
+               if (fval.nn != entry->val.nn)
+                       return 0;
+
+               /* Only activate after receiving the Confirm option (6.6.1). */
+               dccp_feat_activate(sk, feat, local, &fval);
+
+               /* It has been confirmed - so remove the entry */
+               dccp_feat_list_pop(entry);
+
+       } else {
+               DCCP_WARN("Received illegal option %u\n", opt);
+               goto fast_path_failed;
+       }
+       return 0;
+
+fast_path_unknown:
+       if (!mandatory)
+               return dccp_push_empty_confirm(fn, feat, local);
+
+fast_path_failed:
+       return mandatory ? DCCP_RESET_CODE_MANDATORY_ERROR
+                        : DCCP_RESET_CODE_OPTION_ERROR;
+}
+
 /**
  * dccp_feat_parse_options  -  Process Feature-Negotiation Options
  * @sk: for general use and used by the client during connection setup
@@ -1221,6 +1405,14 @@ int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
                        return dccp_feat_confirm_recv(fn, mandatory, opt, feat,
                                                      val, len, server);
                }
+               break;
+       /*
+        *      Support for exchanging NN options on an established connection.
+        */
+       case DCCP_OPEN:
+       case DCCP_PARTOPEN:
+               return dccp_feat_handle_nn_established(sk, mandatory, opt, feat,
+                                                      val, len);
        }
        return 0;       /* ignore FN options in all other states */
 }
index e56a4e5..90b957d 100644 (file)
@@ -129,6 +129,7 @@ extern int  dccp_feat_clone_list(struct list_head const *, struct list_head *);
 
 extern void dccp_encode_value_var(const u64 value, u8 *to, const u8 len);
 extern u64  dccp_decode_value_var(const u8 *bf, const u8 len);
+extern u64  dccp_feat_nn_get(struct sock *sk, u8 feat);
 
 extern int  dccp_insert_option_mandatory(struct sk_buff *skb);
 extern int  dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat,
index 8c36adf..332639b 100644 (file)
@@ -26,6 +26,7 @@
 #include <net/timewait_sock.h>
 #include <net/tcp_states.h>
 #include <net/xfrm.h>
+#include <net/secure_seq.h>
 
 #include "ackvec.h"
 #include "ccid.h"
index 8dc4348..b74f761 100644 (file)
@@ -29,6 +29,7 @@
 #include <net/transp_v6.h>
 #include <net/ip6_checksum.h>
 #include <net/xfrm.h>
+#include <net/secure_seq.h>
 
 #include "dccp.h"
 #include "ipv6.h"
@@ -69,13 +70,7 @@ static inline void dccp_v6_send_check(struct sock *sk, struct sk_buff *skb)
        dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr);
 }
 
-static inline __u32 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
-                                                 __be16 sport, __be16 dport   )
-{
-       return secure_tcpv6_sequence_number(saddr, daddr, sport, dport);
-}
-
-static inline __u32 dccp_v6_init_sequence(struct sk_buff *skb)
+static inline __u64 dccp_v6_init_sequence(struct sk_buff *skb)
 {
        return secure_dccpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
                                             ipv6_hdr(skb)->saddr.s6_addr32,
index 152975d..e742f90 100644 (file)
@@ -184,7 +184,6 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
        dp->dccps_rate_last     = jiffies;
        dp->dccps_role          = DCCP_ROLE_UNDEFINED;
        dp->dccps_service       = DCCP_SERVICE_CODE_IS_ABSENT;
-       dp->dccps_l_ack_ratio   = dp->dccps_r_ack_ratio = 1;
        dp->dccps_tx_qlen       = sysctl_dccp_tx_qlen;
 
        dccp_init_xmit_timers(sk);
index ba4face..2ab16e1 100644 (file)
@@ -388,7 +388,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
        }
 
        ifa->ifa_next = dn_db->ifa_list;
-       rcu_assign_pointer(dn_db->ifa_list, ifa);
+       RCU_INIT_POINTER(dn_db->ifa_list, ifa);
 
        dn_ifaddr_notify(RTM_NEWADDR, ifa);
        blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
@@ -1093,7 +1093,7 @@ static struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
 
        memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));
 
-       rcu_assign_pointer(dev->dn_ptr, dn_db);
+       RCU_INIT_POINTER(dev->dn_ptr, dn_db);
        dn_db->dev = dev;
        init_timer(&dn_db->timer);
 
@@ -1101,7 +1101,7 @@ static struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
 
        dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
        if (!dn_db->neigh_parms) {
-               rcu_assign_pointer(dev->dn_ptr, NULL);
+               RCU_INIT_POINTER(dev->dn_ptr, NULL);
                kfree(dn_db);
                return NULL;
        }
index 0a47b6c..56cf9b8 100644 (file)
@@ -301,7 +301,6 @@ static const struct net_device_ops dsa_netdev_ops = {
        .ndo_start_xmit         = dsa_xmit,
        .ndo_change_rx_flags    = dsa_slave_change_rx_flags,
        .ndo_set_rx_mode        = dsa_slave_set_rx_mode,
-       .ndo_set_multicast_list = dsa_slave_set_rx_mode,
        .ndo_set_mac_address    = dsa_slave_set_mac_address,
        .ndo_do_ioctl           = dsa_slave_ioctl,
 };
@@ -314,7 +313,6 @@ static const struct net_device_ops edsa_netdev_ops = {
        .ndo_start_xmit         = edsa_xmit,
        .ndo_change_rx_flags    = dsa_slave_change_rx_flags,
        .ndo_set_rx_mode        = dsa_slave_set_rx_mode,
-       .ndo_set_multicast_list = dsa_slave_set_rx_mode,
        .ndo_set_mac_address    = dsa_slave_set_mac_address,
        .ndo_do_ioctl           = dsa_slave_ioctl,
 };
@@ -327,7 +325,6 @@ static const struct net_device_ops trailer_netdev_ops = {
        .ndo_start_xmit         = trailer_xmit,
        .ndo_change_rx_flags    = dsa_slave_change_rx_flags,
        .ndo_set_rx_mode        = dsa_slave_set_rx_mode,
-       .ndo_set_multicast_list = dsa_slave_set_rx_mode,
        .ndo_set_mac_address    = dsa_slave_set_mac_address,
        .ndo_do_ioctl           = dsa_slave_ioctl,
 };
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
new file mode 100644 (file)
index 0000000..cf304cc
--- /dev/null
@@ -0,0 +1,885 @@
+/*
+ * Copyright 2011, Siemens AG
+ * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ */
+
+/*
+ * Based on patches from Jon Smirl <jonsmirl@gmail.com>
+ * Copyright (c) 2011 Jon Smirl <jonsmirl@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.
+ *
+ * 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.
+ */
+
+/* Jon's code is based on 6lowpan implementation for Contiki which is:
+ * Copyright (c) 2008, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define DEBUG
+
+#include <linux/bitops.h>
+#include <linux/if_arp.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/netdevice.h>
+#include <net/af_ieee802154.h>
+#include <net/ieee802154.h>
+#include <net/ieee802154_netdev.h>
+#include <net/ipv6.h>
+
+#include "6lowpan.h"
+
+/* TTL uncompression values */
+static const u8 lowpan_ttl_values[] = {0, 1, 64, 255};
+
+static LIST_HEAD(lowpan_devices);
+
+/*
+ * Uncompression of linklocal:
+ *   0 -> 16 bytes from packet
+ *   1 -> 2  bytes from prefix - bunch of zeroes and 8 from packet
+ *   2 -> 2  bytes from prefix - zeroes + 2 from packet
+ *   3 -> 2  bytes from prefix - infer 8 bytes from lladdr
+ *
+ *  NOTE: => the uncompress function does change 0xf to 0x10
+ *  NOTE: 0x00 => no-autoconfig => unspecified
+ */
+static const u8 lowpan_unc_llconf[] = {0x0f, 0x28, 0x22, 0x20};
+
+/*
+ * Uncompression of ctx-based:
+ *   0 -> 0 bits  from packet [unspecified / reserved]
+ *   1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet
+ *   2 -> 8 bytes from prefix - zeroes + 2 from packet
+ *   3 -> 8 bytes from prefix - infer 8 bytes from lladdr
+ */
+static const u8 lowpan_unc_ctxconf[] = {0x00, 0x88, 0x82, 0x80};
+
+/*
+ * Uncompression of ctx-base
+ *   0 -> 0 bits from packet
+ *   1 -> 2 bytes from prefix - bunch of zeroes 5 from packet
+ *   2 -> 2 bytes from prefix - zeroes + 3 from packet
+ *   3 -> 2 bytes from prefix - infer 1 bytes from lladdr
+ */
+static const u8 lowpan_unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
+
+/* Link local prefix */
+static const u8 lowpan_llprefix[] = {0xfe, 0x80};
+
+/* private device info */
+struct lowpan_dev_info {
+       struct net_device       *real_dev; /* real WPAN device ptr */
+       struct mutex            dev_list_mtx; /* mutex for list ops */
+};
+
+struct lowpan_dev_record {
+       struct net_device *ldev;
+       struct list_head list;
+};
+
+static inline struct
+lowpan_dev_info *lowpan_dev_info(const struct net_device *dev)
+{
+       return netdev_priv(dev);
+}
+
+static inline void lowpan_address_flip(u8 *src, u8 *dest)
+{
+       int i;
+       for (i = 0; i < IEEE802154_ADDR_LEN; i++)
+               (dest)[IEEE802154_ADDR_LEN - i - 1] = (src)[i];
+}
+
+/* list of all 6lowpan devices, uses for package delivering */
+/* print data in line */
+static inline void lowpan_raw_dump_inline(const char *caller, char *msg,
+                                  unsigned char *buf, int len)
+{
+#ifdef DEBUG
+       if (msg)
+               pr_debug("(%s) %s: ", caller, msg);
+       print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE,
+                      16, 1, buf, len, false);
+#endif /* DEBUG */
+}
+
+/*
+ * print data in a table format:
+ *
+ * addr: xx xx xx xx xx xx
+ * addr: xx xx xx xx xx xx
+ * ...
+ */
+static inline void lowpan_raw_dump_table(const char *caller, char *msg,
+                                  unsigned char *buf, int len)
+{
+#ifdef DEBUG
+       if (msg)
+               pr_debug("(%s) %s:\n", caller, msg);
+       print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET,
+                      16, 1, buf, len, false);
+#endif /* DEBUG */
+}
+
+static u8
+lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, const struct in6_addr *ipaddr,
+                const unsigned char *lladdr)
+{
+       u8 val = 0;
+
+       if (is_addr_mac_addr_based(ipaddr, lladdr))
+               val = 3; /* 0-bits */
+       else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
+               /* compress IID to 16 bits xxxx::XXXX */
+               memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2);
+               *hc06_ptr += 2;
+               val = 2; /* 16-bits */
+       } else {
+               /* do not compress IID => xxxx::IID */
+               memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8);
+               *hc06_ptr += 8;
+               val = 1; /* 64-bits */
+       }
+
+       return rol8(val, shift);
+}
+
+static void
+lowpan_uip_ds6_set_addr_iid(struct in6_addr *ipaddr, unsigned char *lladdr)
+{
+       memcpy(&ipaddr->s6_addr[8], lladdr, IEEE802154_ALEN);
+       /* second bit-flip (Universe/Local) is done according RFC2464 */
+       ipaddr->s6_addr[8] ^= 0x02;
+}
+
+/*
+ * Uncompress addresses based on a prefix and a postfix with zeroes in
+ * between. If the postfix is zero in length it will use the link address
+ * to configure the IP address (autoconf style).
+ * pref_post_count takes a byte where the first nibble specify prefix count
+ * and the second postfix count (NOTE: 15/0xf => 16 bytes copy).
+ */
+static int
+lowpan_uncompress_addr(struct sk_buff *skb, struct in6_addr *ipaddr,
+       u8 const *prefix, u8 pref_post_count, unsigned char *lladdr)
+{
+       u8 prefcount = pref_post_count >> 4;
+       u8 postcount = pref_post_count & 0x0f;
+
+       /* full nibble 15 => 16 */
+       prefcount = (prefcount == 15 ? 16 : prefcount);
+       postcount = (postcount == 15 ? 16 : postcount);
+
+       if (lladdr)
+               lowpan_raw_dump_inline(__func__, "linklocal address",
+                                               lladdr, IEEE802154_ALEN);
+       if (prefcount > 0)
+               memcpy(ipaddr, prefix, prefcount);
+
+       if (prefcount + postcount < 16)
+               memset(&ipaddr->s6_addr[prefcount], 0,
+                                       16 - (prefcount + postcount));
+
+       if (postcount > 0) {
+               memcpy(&ipaddr->s6_addr[16 - postcount], skb->data, postcount);
+               skb_pull(skb, postcount);
+       } else if (prefcount > 0) {
+               if (lladdr == NULL)
+                       return -EINVAL;
+
+               /* no IID based configuration if no prefix and no data */
+               lowpan_uip_ds6_set_addr_iid(ipaddr, lladdr);
+       }
+
+       pr_debug("(%s): uncompressing %d + %d => ", __func__, prefcount,
+                                                               postcount);
+       lowpan_raw_dump_inline(NULL, NULL, ipaddr->s6_addr, 16);
+
+       return 0;
+}
+
+static u8 lowpan_fetch_skb_u8(struct sk_buff *skb)
+{
+       u8 ret;
+
+       ret = skb->data[0];
+       skb_pull(skb, 1);
+
+       return ret;
+}
+
+static int lowpan_header_create(struct sk_buff *skb,
+                          struct net_device *dev,
+                          unsigned short type, const void *_daddr,
+                          const void *_saddr, unsigned len)
+{
+       u8 tmp, iphc0, iphc1, *hc06_ptr;
+       struct ipv6hdr *hdr;
+       const u8 *saddr = _saddr;
+       const u8 *daddr = _daddr;
+       u8 *head;
+       struct ieee802154_addr sa, da;
+
+       if (type != ETH_P_IPV6)
+               return 0;
+               /* TODO:
+                * if this package isn't ipv6 one, where should it be routed?
+                */
+       head = kzalloc(100, GFP_KERNEL);
+       if (head == NULL)
+               return -ENOMEM;
+
+       hdr = ipv6_hdr(skb);
+       hc06_ptr = head + 2;
+
+       pr_debug("(%s): IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n"
+                "\tnexthdr = 0x%02x\n\thop_lim = %d\n", __func__,
+               hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
+               hdr->hop_limit);
+
+       lowpan_raw_dump_table(__func__, "raw skb network header dump",
+               skb_network_header(skb), sizeof(struct ipv6hdr));
+
+       if (!saddr)
+               saddr = dev->dev_addr;
+
+       lowpan_raw_dump_inline(__func__, "saddr", (unsigned char *)saddr, 8);
+
+       /*
+        * As we copy some bit-length fields, in the IPHC encoding bytes,
+        * we sometimes use |=
+        * If the field is 0, and the current bit value in memory is 1,
+        * this does not work. We therefore reset the IPHC encoding here
+        */
+       iphc0 = LOWPAN_DISPATCH_IPHC;
+       iphc1 = 0;
+
+       /* TODO: context lookup */
+
+       lowpan_raw_dump_inline(__func__, "daddr", (unsigned char *)daddr, 8);
+
+       /*
+        * Traffic class, flow label
+        * If flow label is 0, compress it. If traffic class is 0, compress it
+        * We have to process both in the same time as the offset of traffic
+        * class depends on the presence of version and flow label
+        */
+
+       /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */
+       tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
+       tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
+
+       if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
+            (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
+               /* flow label can be compressed */
+               iphc0 |= LOWPAN_IPHC_FL_C;
+               if ((hdr->priority == 0) &&
+                  ((hdr->flow_lbl[0] & 0xF0) == 0)) {
+                       /* compress (elide) all */
+                       iphc0 |= LOWPAN_IPHC_TC_C;
+               } else {
+                       /* compress only the flow label */
+                       *hc06_ptr = tmp;
+                       hc06_ptr += 1;
+               }
+       } else {
+               /* Flow label cannot be compressed */
+               if ((hdr->priority == 0) &&
+                  ((hdr->flow_lbl[0] & 0xF0) == 0)) {
+                       /* compress only traffic class */
+                       iphc0 |= LOWPAN_IPHC_TC_C;
+                       *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
+                       memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2);
+                       hc06_ptr += 3;
+               } else {
+                       /* compress nothing */
+                       memcpy(hc06_ptr, &hdr, 4);
+                       /* replace the top byte with new ECN | DSCP format */
+                       *hc06_ptr = tmp;
+                       hc06_ptr += 4;
+               }
+       }
+
+       /* NOTE: payload length is always compressed */
+
+       /* Next Header is compress if UDP */
+       if (hdr->nexthdr == UIP_PROTO_UDP)
+               iphc0 |= LOWPAN_IPHC_NH_C;
+
+/* TODO: next header compression */
+
+       if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
+               *hc06_ptr = hdr->nexthdr;
+               hc06_ptr += 1;
+       }
+
+       /*
+        * Hop limit
+        * if 1:   compress, encoding is 01
+        * if 64:  compress, encoding is 10
+        * if 255: compress, encoding is 11
+        * else do not compress
+        */
+       switch (hdr->hop_limit) {
+       case 1:
+               iphc0 |= LOWPAN_IPHC_TTL_1;
+               break;
+       case 64:
+               iphc0 |= LOWPAN_IPHC_TTL_64;
+               break;
+       case 255:
+               iphc0 |= LOWPAN_IPHC_TTL_255;
+               break;
+       default:
+               *hc06_ptr = hdr->hop_limit;
+               break;
+       }
+
+       /* source address compression */
+       if (is_addr_unspecified(&hdr->saddr)) {
+               pr_debug("(%s): source address is unspecified, setting SAC\n",
+                                                               __func__);
+               iphc1 |= LOWPAN_IPHC_SAC;
+       /* TODO: context lookup */
+       } else if (is_addr_link_local(&hdr->saddr)) {
+               pr_debug("(%s): source address is link-local\n", __func__);
+               iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
+                               LOWPAN_IPHC_SAM_BIT, &hdr->saddr, saddr);
+       } else {
+               pr_debug("(%s): send the full source address\n", __func__);
+               memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16);
+               hc06_ptr += 16;
+       }
+
+       /* destination address compression */
+       if (is_addr_mcast(&hdr->daddr)) {
+               pr_debug("(%s): destination address is multicast", __func__);
+               iphc1 |= LOWPAN_IPHC_M;
+               if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
+                       pr_debug("compressed to 1 octet\n");
+                       iphc1 |= LOWPAN_IPHC_DAM_11;
+                       /* use last byte */
+                       *hc06_ptr = hdr->daddr.s6_addr[15];
+                       hc06_ptr += 1;
+               } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
+                       pr_debug("compressed to 4 octets\n");
+                       iphc1 |= LOWPAN_IPHC_DAM_10;
+                       /* second byte + the last three */
+                       *hc06_ptr = hdr->daddr.s6_addr[1];
+                       memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3);
+                       hc06_ptr += 4;
+               } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
+                       pr_debug("compressed to 6 octets\n");
+                       iphc1 |= LOWPAN_IPHC_DAM_01;
+                       /* second byte + the last five */
+                       *hc06_ptr = hdr->daddr.s6_addr[1];
+                       memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5);
+                       hc06_ptr += 6;
+               } else {
+                       pr_debug("using full address\n");
+                       iphc1 |= LOWPAN_IPHC_DAM_00;
+                       memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16);
+                       hc06_ptr += 16;
+               }
+       } else {
+               pr_debug("(%s): destination address is unicast: ", __func__);
+               /* TODO: context lookup */
+               if (is_addr_link_local(&hdr->daddr)) {
+                       pr_debug("destination address is link-local\n");
+                       iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
+                               LOWPAN_IPHC_DAM_BIT, &hdr->daddr, daddr);
+               } else {
+                       pr_debug("using full address\n");
+                       memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16);
+                       hc06_ptr += 16;
+               }
+       }
+
+       /* TODO: UDP header compression */
+       /* TODO: Next Header compression */
+
+       head[0] = iphc0;
+       head[1] = iphc1;
+
+       skb_pull(skb, sizeof(struct ipv6hdr));
+       memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head);
+
+       kfree(head);
+
+       lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
+                               skb->len);
+
+       /*
+        * NOTE1: I'm still unsure about the fact that compression and WPAN
+        * header are created here and not later in the xmit. So wait for
+        * an opinion of net maintainers.
+        */
+       /*
+        * NOTE2: to be absolutely correct, we must derive PANid information
+        * from MAC subif of the 'dev' and 'real_dev' network devices, but
+        * this isn't implemented in mainline yet, so currently we assign 0xff
+        */
+       {
+               /* prepare wpan address data */
+               sa.addr_type = IEEE802154_ADDR_LONG;
+               sa.pan_id = 0xff;
+
+               da.addr_type = IEEE802154_ADDR_LONG;
+               da.pan_id = 0xff;
+
+               memcpy(&(da.hwaddr), daddr, 8);
+               memcpy(&(sa.hwaddr), saddr, 8);
+
+               mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
+               return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
+                               type, (void *)&da, (void *)&sa, skb->len);
+       }
+}
+
+static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
+{
+       struct sk_buff *new;
+       struct lowpan_dev_record *entry;
+       int stat = NET_RX_SUCCESS;
+
+       new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
+                                                               GFP_KERNEL);
+       kfree_skb(skb);
+
+       if (NULL == new)
+               return -ENOMEM;
+
+       skb_push(new, sizeof(struct ipv6hdr));
+       skb_reset_network_header(new);
+       skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr));
+
+       new->protocol = htons(ETH_P_IPV6);
+       new->pkt_type = PACKET_HOST;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(entry, &lowpan_devices, list)
+               if (lowpan_dev_info(entry->ldev)->real_dev == new->dev) {
+                       skb = skb_copy(new, GFP_KERNEL);
+                       skb->dev = entry->ldev;
+
+                       if (in_interrupt())
+                               stat = netif_rx(skb);
+                       else
+                               stat = netif_rx_ni(skb);
+               }
+       rcu_read_unlock();
+
+       kfree_skb(new);
+
+       return stat;
+}
+
+static int
+lowpan_process_data(struct sk_buff *skb)
+{
+       struct ipv6hdr hdr;
+       u8 tmp, iphc0, iphc1, num_context = 0;
+       u8 *_saddr, *_daddr;
+       int err;
+
+       lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
+                               skb->len);
+       /* at least two bytes will be used for the encoding */
+       if (skb->len < 2)
+               goto drop;
+       iphc0 = lowpan_fetch_skb_u8(skb);
+       iphc1 = lowpan_fetch_skb_u8(skb);
+
+       _saddr = mac_cb(skb)->sa.hwaddr;
+       _daddr = mac_cb(skb)->da.hwaddr;
+
+       pr_debug("(%s): iphc0 = %02x, iphc1 = %02x\n", __func__, iphc0, iphc1);
+
+       /* another if the CID flag is set */
+       if (iphc1 & LOWPAN_IPHC_CID) {
+               pr_debug("(%s): CID flag is set, increase header with one\n",
+                                                               __func__);
+               if (!skb->len)
+                       goto drop;
+               num_context = lowpan_fetch_skb_u8(skb);
+       }
+
+       hdr.version = 6;
+
+       /* Traffic Class and Flow Label */
+       switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
+       /*
+        * Traffic Class and FLow Label carried in-line
+        * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
+        */
+       case 0: /* 00b */
+               if (!skb->len)
+                       goto drop;
+               tmp = lowpan_fetch_skb_u8(skb);
+               memcpy(&hdr.flow_lbl, &skb->data[0], 3);
+               skb_pull(skb, 3);
+               hdr.priority = ((tmp >> 2) & 0x0f);
+               hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
+                                       (hdr.flow_lbl[0] & 0x0f);
+               break;
+       /*
+        * Traffic class carried in-line
+        * ECN + DSCP (1 byte), Flow Label is elided
+        */
+       case 1: /* 10b */
+               if (!skb->len)
+                       goto drop;
+               tmp = lowpan_fetch_skb_u8(skb);
+               hdr.priority = ((tmp >> 2) & 0x0f);
+               hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
+               hdr.flow_lbl[1] = 0;
+               hdr.flow_lbl[2] = 0;
+               break;
+       /*
+        * Flow Label carried in-line
+        * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
+        */
+       case 2: /* 01b */
+               if (!skb->len)
+                       goto drop;
+               tmp = lowpan_fetch_skb_u8(skb);
+               hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
+               memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
+               skb_pull(skb, 2);
+               break;
+       /* Traffic Class and Flow Label are elided */
+       case 3: /* 11b */
+               hdr.priority = 0;
+               hdr.flow_lbl[0] = 0;
+               hdr.flow_lbl[1] = 0;
+               hdr.flow_lbl[2] = 0;
+               break;
+       default:
+               break;
+       }
+
+       /* Next Header */
+       if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
+               /* Next header is carried inline */
+               if (!skb->len)
+                       goto drop;
+               hdr.nexthdr = lowpan_fetch_skb_u8(skb);
+               pr_debug("(%s): NH flag is set, next header is carried "
+                        "inline: %02x\n", __func__, hdr.nexthdr);
+       }
+
+       /* Hop Limit */
+       if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I)
+               hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
+       else {
+               if (!skb->len)
+                       goto drop;
+               hdr.hop_limit = lowpan_fetch_skb_u8(skb);
+       }
+
+       /* Extract SAM to the tmp variable */
+       tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
+
+       /* Source address uncompression */
+       pr_debug("(%s): source address stateless compression\n", __func__);
+       err = lowpan_uncompress_addr(skb, &hdr.saddr, lowpan_llprefix,
+                               lowpan_unc_llconf[tmp], skb->data);
+       if (err)
+               goto drop;
+
+       /* Extract DAM to the tmp variable */
+       tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
+
+       /* check for Multicast Compression */
+       if (iphc1 & LOWPAN_IPHC_M) {
+               if (iphc1 & LOWPAN_IPHC_DAC) {
+                       pr_debug("(%s): destination address context-based "
+                                "multicast compression\n", __func__);
+                       /* TODO: implement this */
+               } else {
+                       u8 prefix[] = {0xff, 0x02};
+
+                       pr_debug("(%s): destination address non-context-based"
+                                " multicast compression\n", __func__);
+                       if (0 < tmp && tmp < 3) {
+                               if (!skb->len)
+                                       goto drop;
+                               else
+                                       prefix[1] = lowpan_fetch_skb_u8(skb);
+                       }
+
+                       err = lowpan_uncompress_addr(skb, &hdr.daddr, prefix,
+                                       lowpan_unc_mxconf[tmp], NULL);
+                       if (err)
+                               goto drop;
+               }
+       } else {
+               pr_debug("(%s): destination address stateless compression\n",
+                                                               __func__);
+               err = lowpan_uncompress_addr(skb, &hdr.daddr, lowpan_llprefix,
+                               lowpan_unc_llconf[tmp], skb->data);
+               if (err)
+                       goto drop;
+       }
+
+       /* TODO: UDP header parse */
+
+       /* Not fragmented package */
+       hdr.payload_len = htons(skb->len);
+
+       pr_debug("(%s): skb headroom size = %d, data length = %d\n", __func__,
+                                               skb_headroom(skb), skb->len);
+
+       pr_debug("(%s): IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n\t"
+                "nexthdr = 0x%02x\n\thop_lim = %d\n", __func__, hdr.version,
+                ntohs(hdr.payload_len), hdr.nexthdr, hdr.hop_limit);
+
+       lowpan_raw_dump_table(__func__, "raw header dump", (u8 *)&hdr,
+                                                       sizeof(hdr));
+       return lowpan_skb_deliver(skb, &hdr);
+drop:
+       kfree(skb);
+       return -EINVAL;
+}
+
+static int lowpan_set_address(struct net_device *dev, void *p)
+{
+       struct sockaddr *sa = p;
+
+       if (netif_running(dev))
+               return -EBUSY;
+
+       /* TODO: validate addr */
+       memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+
+       return 0;
+}
+
+static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       int err = 0;
+
+       pr_debug("(%s): package xmit\n", __func__);
+
+       skb->dev = lowpan_dev_info(dev)->real_dev;
+       if (skb->dev == NULL) {
+               pr_debug("(%s) ERROR: no real wpan device found\n", __func__);
+               dev_kfree_skb(skb);
+       } else
+               err = dev_queue_xmit(skb);
+
+       return (err < 0 ? NETDEV_TX_BUSY : NETDEV_TX_OK);
+}
+
+static void lowpan_dev_free(struct net_device *dev)
+{
+       dev_put(lowpan_dev_info(dev)->real_dev);
+       free_netdev(dev);
+}
+
+static struct header_ops lowpan_header_ops = {
+       .create = lowpan_header_create,
+};
+
+static const struct net_device_ops lowpan_netdev_ops = {
+       .ndo_start_xmit         = lowpan_xmit,
+       .ndo_set_mac_address    = lowpan_set_address,
+};
+
+static void lowpan_setup(struct net_device *dev)
+{
+       pr_debug("(%s)\n", __func__);
+
+       dev->addr_len           = IEEE802154_ADDR_LEN;
+       memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
+       dev->type               = ARPHRD_IEEE802154;
+       dev->features           = NETIF_F_NO_CSUM;
+       /* Frame Control + Sequence Number + Address fields + Security Header */
+       dev->hard_header_len    = 2 + 1 + 20 + 14;
+       dev->needed_tailroom    = 2; /* FCS */
+       dev->mtu                = 1281;
+       dev->tx_queue_len       = 0;
+       dev->flags              = IFF_NOARP | IFF_BROADCAST;
+       dev->watchdog_timeo     = 0;
+
+       dev->netdev_ops         = &lowpan_netdev_ops;
+       dev->header_ops         = &lowpan_header_ops;
+       dev->destructor         = lowpan_dev_free;
+}
+
+static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+       pr_debug("(%s)\n", __func__);
+
+       if (tb[IFLA_ADDRESS]) {
+               if (nla_len(tb[IFLA_ADDRESS]) != IEEE802154_ADDR_LEN)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
+       struct packet_type *pt, struct net_device *orig_dev)
+{
+       if (!netif_running(dev))
+               goto drop;
+
+       if (dev->type != ARPHRD_IEEE802154)
+               goto drop;
+
+       /* check that it's our buffer */
+       if ((skb->data[0] & 0xe0) == 0x60)
+               lowpan_process_data(skb);
+
+       return NET_RX_SUCCESS;
+
+drop:
+       kfree_skb(skb);
+       return NET_RX_DROP;
+}
+
+static int lowpan_newlink(struct net *src_net, struct net_device *dev,
+                         struct nlattr *tb[], struct nlattr *data[])
+{
+       struct net_device *real_dev;
+       struct lowpan_dev_record *entry;
+
+       pr_debug("(%s)\n", __func__);
+
+       if (!tb[IFLA_LINK])
+               return -EINVAL;
+       /* find and hold real wpan device */
+       real_dev = dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
+       if (!real_dev)
+               return -ENODEV;
+
+       lowpan_dev_info(dev)->real_dev = real_dev;
+       mutex_init(&lowpan_dev_info(dev)->dev_list_mtx);
+
+       entry = kzalloc(sizeof(struct lowpan_dev_record), GFP_KERNEL);
+       if (!entry)
+               return -ENOMEM;
+
+       entry->ldev = dev;
+
+       mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
+       INIT_LIST_HEAD(&entry->list);
+       list_add_tail(&entry->list, &lowpan_devices);
+       mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
+
+       register_netdevice(dev);
+
+       return 0;
+}
+
+static void lowpan_dellink(struct net_device *dev, struct list_head *head)
+{
+       struct lowpan_dev_info *lowpan_dev = lowpan_dev_info(dev);
+       struct net_device *real_dev = lowpan_dev->real_dev;
+       struct lowpan_dev_record *entry;
+
+       ASSERT_RTNL();
+
+       mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
+       list_for_each_entry(entry, &lowpan_devices, list)
+               if (entry->ldev == dev) {
+                       list_del(&entry->list);
+                       kfree(entry);
+               }
+       mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
+
+       mutex_destroy(&lowpan_dev_info(dev)->dev_list_mtx);
+
+       unregister_netdevice_queue(dev, head);
+
+       dev_put(real_dev);
+}
+
+static struct rtnl_link_ops lowpan_link_ops __read_mostly = {
+       .kind           = "lowpan",
+       .priv_size      = sizeof(struct lowpan_dev_info),
+       .setup          = lowpan_setup,
+       .newlink        = lowpan_newlink,
+       .dellink        = lowpan_dellink,
+       .validate       = lowpan_validate,
+};
+
+static inline int __init lowpan_netlink_init(void)
+{
+       return rtnl_link_register(&lowpan_link_ops);
+}
+
+static inline void __init lowpan_netlink_fini(void)
+{
+       rtnl_link_unregister(&lowpan_link_ops);
+}
+
+static struct packet_type lowpan_packet_type = {
+       .type = __constant_htons(ETH_P_IEEE802154),
+       .func = lowpan_rcv,
+};
+
+static int __init lowpan_init_module(void)
+{
+       int err = 0;
+
+       pr_debug("(%s)\n", __func__);
+
+       err = lowpan_netlink_init();
+       if (err < 0)
+               goto out;
+
+       dev_add_pack(&lowpan_packet_type);
+out:
+       return err;
+}
+
+static void __exit lowpan_cleanup_module(void)
+{
+       pr_debug("(%s)\n", __func__);
+
+       lowpan_netlink_fini();
+
+       dev_remove_pack(&lowpan_packet_type);
+}
+
+module_init(lowpan_init_module);
+module_exit(lowpan_cleanup_module);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_RTNL_LINK("lowpan");
diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
new file mode 100644 (file)
index 0000000..5d8cf80
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2011, Siemens AG
+ * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ */
+
+/*
+ * Based on patches from Jon Smirl <jonsmirl@gmail.com>
+ * Copyright (c) 2011 Jon Smirl <jonsmirl@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.
+ *
+ * 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.
+ */
+
+/* Jon's code is based on 6lowpan implementation for Contiki which is:
+ * Copyright (c) 2008, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __6LOWPAN_H__
+#define __6LOWPAN_H__
+
+/* need to know address length to manipulate with it */
+#define IEEE802154_ALEN                8
+
+#define UIP_802154_SHORTADDR_LEN       2  /* compressed ipv6 address length */
+#define UIP_IPH_LEN                    40 /* ipv6 fixed header size */
+#define UIP_PROTO_UDP                  17 /* ipv6 next header value for UDP */
+#define UIP_FRAGH_LEN                  8  /* ipv6 fragment header size */
+
+/*
+ * ipv6 address based on mac
+ * second bit-flip (Universe/Local) is done according RFC2464
+ */
+#define is_addr_mac_addr_based(a, m) \
+       ((((a)->s6_addr[8])  == (((m)[0]) ^ 0x02)) &&   \
+        (((a)->s6_addr[9])  == (m)[1]) &&              \
+        (((a)->s6_addr[10]) == (m)[2]) &&              \
+        (((a)->s6_addr[11]) == (m)[3]) &&              \
+        (((a)->s6_addr[12]) == (m)[4]) &&              \
+        (((a)->s6_addr[13]) == (m)[5]) &&              \
+        (((a)->s6_addr[14]) == (m)[6]) &&              \
+        (((a)->s6_addr[15]) == (m)[7]))
+
+/* ipv6 address is unspecified */
+#define is_addr_unspecified(a)         \
+       ((((a)->s6_addr32[0]) == 0) &&  \
+        (((a)->s6_addr32[1]) == 0) &&  \
+        (((a)->s6_addr32[2]) == 0) &&  \
+        (((a)->s6_addr32[3]) == 0))
+
+/* compare ipv6 addresses prefixes */
+#define ipaddr_prefixcmp(addr1, addr2, length) \
+       (memcmp(addr1, addr2, length >> 3) == 0)
+
+/* local link, i.e. FE80::/10 */
+#define is_addr_link_local(a) (((a)->s6_addr16[0]) == 0x80FE)
+
+/*
+ * check whether we can compress the IID to 16 bits,
+ * it's possible for unicast adresses with first 49 bits are zero only.
+ */
+#define lowpan_is_iid_16_bit_compressable(a)   \
+       ((((a)->s6_addr16[4]) == 0) &&          \
+        (((a)->s6_addr16[5]) == 0) &&          \
+        (((a)->s6_addr16[6]) == 0) &&          \
+        ((((a)->s6_addr[14]) & 0x80) == 0))
+
+/* multicast address */
+#define is_addr_mcast(a) (((a)->s6_addr[0]) == 0xFF)
+
+/* check whether the 112-bit gid of the multicast address is mappable to: */
+
+/* 9 bits, for FF02::1 (all nodes) and FF02::2 (all routers) addresses only. */
+#define lowpan_is_mcast_addr_compressable(a)   \
+       ((((a)->s6_addr16[1]) == 0) &&          \
+        (((a)->s6_addr16[2]) == 0) &&          \
+        (((a)->s6_addr16[3]) == 0) &&          \
+        (((a)->s6_addr16[4]) == 0) &&          \
+        (((a)->s6_addr16[5]) == 0) &&          \
+        (((a)->s6_addr16[6]) == 0) &&          \
+        (((a)->s6_addr[14])  == 0) &&          \
+        ((((a)->s6_addr[15]) == 1) || (((a)->s6_addr[15]) == 2)))
+
+/* 48 bits, FFXX::00XX:XXXX:XXXX */
+#define lowpan_is_mcast_addr_compressable48(a) \
+       ((((a)->s6_addr16[1]) == 0) &&          \
+        (((a)->s6_addr16[2]) == 0) &&          \
+        (((a)->s6_addr16[3]) == 0) &&          \
+        (((a)->s6_addr16[4]) == 0) &&          \
+        (((a)->s6_addr[10]) == 0))
+
+/* 32 bits, FFXX::00XX:XXXX */
+#define lowpan_is_mcast_addr_compressable32(a) \
+       ((((a)->s6_addr16[1]) == 0) &&          \
+        (((a)->s6_addr16[2]) == 0) &&          \
+        (((a)->s6_addr16[3]) == 0) &&          \
+        (((a)->s6_addr16[4]) == 0) &&          \
+        (((a)->s6_addr16[5]) == 0) &&          \
+        (((a)->s6_addr[12]) == 0))
+
+/* 8 bits, FF02::00XX */
+#define lowpan_is_mcast_addr_compressable8(a)  \
+       ((((a)->s6_addr[1])  == 2) &&           \
+        (((a)->s6_addr16[1]) == 0) &&          \
+        (((a)->s6_addr16[2]) == 0) &&          \
+        (((a)->s6_addr16[3]) == 0) &&          \
+        (((a)->s6_addr16[4]) == 0) &&          \
+        (((a)->s6_addr16[5]) == 0) &&          \
+        (((a)->s6_addr16[6]) == 0) &&          \
+        (((a)->s6_addr[14]) == 0))
+
+#define lowpan_is_addr_broadcast(a)    \
+       ((((a)[0]) == 0xFF) &&  \
+        (((a)[1]) == 0xFF) &&  \
+        (((a)[2]) == 0xFF) &&  \
+        (((a)[3]) == 0xFF) &&  \
+        (((a)[4]) == 0xFF) &&  \
+        (((a)[5]) == 0xFF) &&  \
+        (((a)[6]) == 0xFF) &&  \
+        (((a)[7]) == 0xFF))
+
+#define LOWPAN_DISPATCH_IPV6   0x41 /* 01000001 = 65 */
+#define LOWPAN_DISPATCH_HC1    0x42 /* 01000010 = 66 */
+#define LOWPAN_DISPATCH_IPHC   0x60 /* 011xxxxx = ... */
+#define LOWPAN_DISPATCH_FRAG1  0xc0 /* 11000xxx */
+#define LOWPAN_DISPATCH_FRAGN  0xe0 /* 11100xxx */
+
+/*
+ * Values of fields within the IPHC encoding first byte
+ * (C stands for compressed and I for inline)
+ */
+#define LOWPAN_IPHC_TF         0x18
+
+#define LOWPAN_IPHC_FL_C       0x10
+#define LOWPAN_IPHC_TC_C       0x08
+#define LOWPAN_IPHC_NH_C       0x04
+#define LOWPAN_IPHC_TTL_1      0x01
+#define LOWPAN_IPHC_TTL_64     0x02
+#define LOWPAN_IPHC_TTL_255    0x03
+#define LOWPAN_IPHC_TTL_I      0x00
+
+
+/* Values of fields within the IPHC encoding second byte */
+#define LOWPAN_IPHC_CID                0x80
+
+#define LOWPAN_IPHC_SAC                0x40
+#define LOWPAN_IPHC_SAM_00     0x00
+#define LOWPAN_IPHC_SAM_01     0x10
+#define LOWPAN_IPHC_SAM_10     0x20
+#define LOWPAN_IPHC_SAM                0x30
+
+#define LOWPAN_IPHC_SAM_BIT    4
+
+#define LOWPAN_IPHC_M          0x08
+#define LOWPAN_IPHC_DAC                0x04
+#define LOWPAN_IPHC_DAM_00     0x00
+#define LOWPAN_IPHC_DAM_01     0x01
+#define LOWPAN_IPHC_DAM_10     0x02
+#define LOWPAN_IPHC_DAM_11     0x03
+
+#define LOWPAN_IPHC_DAM_BIT    0
+/*
+ * LOWPAN_UDP encoding (works together with IPHC)
+ */
+#define LOWPAN_NHC_UDP_MASK            0xF8
+#define LOWPAN_NHC_UDP_ID              0xF0
+#define LOWPAN_NHC_UDP_CHECKSUMC       0x04
+#define LOWPAN_NHC_UDP_CHECKSUMI       0x00
+
+/* values for port compression, _with checksum_ ie bit 5 set to 0 */
+#define LOWPAN_NHC_UDP_CS_P_00 0xF0 /* all inline */
+#define LOWPAN_NHC_UDP_CS_P_01 0xF1 /* source 16bit inline,
+                                       dest = 0xF0 + 8 bit inline */
+#define LOWPAN_NHC_UDP_CS_P_10 0xF2 /* source = 0xF0 + 8bit inline,
+                                       dest = 16 bit inline */
+#define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */
+
+#endif /* __6LOWPAN_H__ */
index 1c1de97..7dee650 100644 (file)
@@ -10,3 +10,9 @@ config IEEE802154
 
          Say Y here to compile LR-WPAN support into the kernel or say M to
          compile it as modules.
+
+config IEEE802154_6LOWPAN
+       tristate "6lowpan support over IEEE 802.15.4"
+       depends on IEEE802154 && IPV6
+       ---help---
+       IPv6 compression over IEEE 802.15.4.
index 5761185..d7716d6 100644 (file)
@@ -1,3 +1,5 @@
-obj-$(CONFIG_IEEE802154) +=    ieee802154.o af_802154.o
-ieee802154-y           := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
-af_802154-y            := af_ieee802154.o raw.o dgram.o
+obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o
+obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o
+
+ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
+af_802154-y := af_ieee802154.o raw.o dgram.o
index bc19bd0..c6b5092 100644 (file)
@@ -258,7 +258,7 @@ static struct in_device *inetdev_init(struct net_device *dev)
                ip_mc_up(in_dev);
 
        /* we can receive as soon as ip_ptr is set -- do this last */
-       rcu_assign_pointer(dev->ip_ptr, in_dev);
+       RCU_INIT_POINTER(dev->ip_ptr, in_dev);
 out:
        return in_dev;
 out_kfree:
@@ -291,7 +291,7 @@ static void inetdev_destroy(struct in_device *in_dev)
                inet_free_ifa(ifa);
        }
 
-       rcu_assign_pointer(dev->ip_ptr, NULL);
+       RCU_INIT_POINTER(dev->ip_ptr, NULL);
 
        devinet_sysctl_unregister(in_dev);
        neigh_parms_release(&arp_tbl, in_dev->arp_parms);
@@ -1175,7 +1175,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
        switch (event) {
        case NETDEV_REGISTER:
                printk(KERN_DEBUG "inetdev_event: bug\n");
-               rcu_assign_pointer(dev->ip_ptr, NULL);
+               RCU_INIT_POINTER(dev->ip_ptr, NULL);
                break;
        case NETDEV_UP:
                if (!inetdev_valid_mtu(dev->mtu))
index de9e297..89d6f71 100644 (file)
@@ -204,7 +204,7 @@ static inline struct tnode *node_parent_rcu(const struct rt_trie_node *node)
        return (struct tnode *)(parent & ~NODE_TYPE_MASK);
 }
 
-/* Same as rcu_assign_pointer
+/* Same as RCU_INIT_POINTER
  * but that macro() assumes that value is a pointer.
  */
 static inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr)
@@ -528,7 +528,7 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *
        if (n)
                node_set_parent(n, tn);
 
-       rcu_assign_pointer(tn->child[i], n);
+       RCU_INIT_POINTER(tn->child[i], n);
 }
 
 #define MAX_WORK 10
@@ -1014,7 +1014,7 @@ static void trie_rebalance(struct trie *t, struct tnode *tn)
 
                tp = node_parent((struct rt_trie_node *) tn);
                if (!tp)
-                       rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
+                       RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn);
 
                tnode_free_flush();
                if (!tp)
@@ -1026,7 +1026,7 @@ static void trie_rebalance(struct trie *t, struct tnode *tn)
        if (IS_TNODE(tn))
                tn = (struct tnode *)resize(t, (struct tnode *)tn);
 
-       rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
+       RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn);
        tnode_free_flush();
 }
 
@@ -1163,7 +1163,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
                        put_child(t, (struct tnode *)tp, cindex,
                                  (struct rt_trie_node *)tn);
                } else {
-                       rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
+                       RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn);
                        tp = tn;
                }
        }
@@ -1621,7 +1621,7 @@ static void trie_leaf_remove(struct trie *t, struct leaf *l)
                put_child(t, (struct tnode *)tp, cindex, NULL);
                trie_rebalance(t, tp);
        } else
-               rcu_assign_pointer(t->trie, NULL);
+               RCU_INIT_POINTER(t->trie, NULL);
 
        free_leaf(l);
 }
index dbfc21d..8cb1ebb 100644 (file)
@@ -34,7 +34,7 @@ int gre_add_protocol(const struct gre_protocol *proto, u8 version)
        if (gre_proto[version])
                goto err_out_unlock;
 
-       rcu_assign_pointer(gre_proto[version], proto);
+       RCU_INIT_POINTER(gre_proto[version], proto);
        spin_unlock(&gre_proto_lock);
        return 0;
 
@@ -54,7 +54,7 @@ int gre_del_protocol(const struct gre_protocol *proto, u8 version)
        if (rcu_dereference_protected(gre_proto[version],
                        lockdep_is_held(&gre_proto_lock)) != proto)
                goto err_out_unlock;
-       rcu_assign_pointer(gre_proto[version], NULL);
+       RCU_INIT_POINTER(gre_proto[version], NULL);
        spin_unlock(&gre_proto_lock);
        synchronize_rcu();
        return 0;
index f1d27f6..ce57bde 100644 (file)
@@ -1009,7 +1009,7 @@ static void ip_mc_filter_add(struct in_device *in_dev, __be32 addr)
 
        /* Checking for IFF_MULTICAST here is WRONG-WRONG-WRONG.
           We will get multicast token leakage, when IFF_MULTICAST
-          is changed. This check should be done in dev->set_multicast_list
+          is changed. This check should be done in ndo_set_rx_mode
           routine. Something sort of:
           if (dev->mc_list && dev->flags&IFF_MULTICAST) { do it; }
           --ANK
@@ -1242,7 +1242,7 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
 
        im->next_rcu = in_dev->mc_list;
        in_dev->mc_count++;
-       rcu_assign_pointer(in_dev->mc_list, im);
+       RCU_INIT_POINTER(in_dev->mc_list, im);
 
 #ifdef CONFIG_IP_MULTICAST
        igmpv3_del_delrec(in_dev, im->multiaddr);
@@ -1718,7 +1718,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
 
                pmc->sfcount[sfmode]--;
                for (j=0; j<i; j++)
-                       (void) ip_mc_del1_src(pmc, sfmode, &psfsrc[i]);
+                       (void) ip_mc_del1_src(pmc, sfmode, &psfsrc[j]);
        } else if (isexclude != (pmc->sfcount[MCAST_EXCLUDE] != 0)) {
 #ifdef CONFIG_IP_MULTICAST
                struct ip_sf_list *psf;
@@ -1813,7 +1813,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
        iml->next_rcu = inet->mc_list;
        iml->sflist = NULL;
        iml->sfmode = MCAST_EXCLUDE;
-       rcu_assign_pointer(inet->mc_list, iml);
+       RCU_INIT_POINTER(inet->mc_list, iml);
        ip_mc_inc_group(in_dev, addr);
        err = 0;
 done:
@@ -1835,7 +1835,7 @@ static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
        }
        err = ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr,
                        iml->sfmode, psf->sl_count, psf->sl_addr, 0);
-       rcu_assign_pointer(iml->sflist, NULL);
+       RCU_INIT_POINTER(iml->sflist, NULL);
        /* decrease mem now to avoid the memleak warning */
        atomic_sub(IP_SFLSIZE(psf->sl_max), &sk->sk_omem_alloc);
        kfree_rcu(psf, rcu);
@@ -2000,7 +2000,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
                        atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc);
                        kfree_rcu(psl, rcu);
                }
-               rcu_assign_pointer(pmc->sflist, newpsl);
+               RCU_INIT_POINTER(pmc->sflist, newpsl);
                psl = newpsl;
        }
        rv = 1; /* > 0 for insert logic below if sl_count is 0 */
@@ -2103,7 +2103,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
        } else
                (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode,
                        0, NULL, 0);
-       rcu_assign_pointer(pmc->sflist, newpsl);
+       RCU_INIT_POINTER(pmc->sflist, newpsl);
        pmc->sfmode = msf->imsf_fmode;
        err = 0;
 done:
index 3c0369a..984ec65 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <net/inet_connection_sock.h>
 #include <net/inet_hashtables.h>
+#include <net/secure_seq.h>
 #include <net/ip.h>
 
 /*
index ef7ae60..8e6be5a 100644 (file)
@@ -433,7 +433,7 @@ static struct sk_buff *__lro_proc_segment(struct net_lro_mgr *lro_mgr,
        if (!lro_mgr->get_frag_header ||
            lro_mgr->get_frag_header(frags, (void *)&mac_hdr, (void *)&iph,
                                     (void *)&tcph, &flags, priv)) {
-               mac_hdr = page_address(frags->page) + frags->page_offset;
+               mac_hdr = skb_frag_address(frags);
                goto out1;
        }
 
index e382138..86f13c6 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/net.h>
 #include <net/ip.h>
 #include <net/inetpeer.h>
+#include <net/secure_seq.h>
 
 /*
  *  Theory of operations.
index ccaaa85..ae3bb14 100644 (file)
@@ -122,6 +122,7 @@ static int ip_dev_loopback_xmit(struct sk_buff *newskb)
        newskb->pkt_type = PACKET_LOOPBACK;
        newskb->ip_summed = CHECKSUM_UNNECESSARY;
        WARN_ON(!skb_dst(newskb));
+       skb_dst_force(newskb);
        netif_rx_ni(newskb);
        return 0;
 }
@@ -204,9 +205,15 @@ static inline int ip_finish_output2(struct sk_buff *skb)
                skb = skb2;
        }
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(dst);
-       if (neigh)
-               return neigh_output(neigh, skb);
+       if (neigh) {
+               int res = neigh_output(neigh, skb);
+
+               rcu_read_unlock();
+               return res;
+       }
+       rcu_read_unlock();
 
        if (net_ratelimit())
                printk(KERN_DEBUG "ip_finish_output2: No header cache and no neighbour!\n");
@@ -982,13 +989,13 @@ alloc_new_skb:
                        if (page && (left = PAGE_SIZE - off) > 0) {
                                if (copy >= left)
                                        copy = left;
-                               if (page != frag->page) {
+                               if (page != skb_frag_page(frag)) {
                                        if (i == MAX_SKB_FRAGS) {
                                                err = -EMSGSIZE;
                                                goto error;
                                        }
-                                       get_page(page);
                                        skb_fill_page_desc(skb, i, page, off, 0);
+                                       skb_frag_ref(skb, i);
                                        frag = &skb_shinfo(skb)->frags[i];
                                }
                        } else if (i < MAX_SKB_FRAGS) {
@@ -1008,7 +1015,8 @@ alloc_new_skb:
                                err = -EMSGSIZE;
                                goto error;
                        }
-                       if (getfrag(from, page_address(frag->page)+frag->page_offset+frag->size, offset, copy, skb->len, skb) < 0) {
+                       if (getfrag(from, skb_frag_address(frag)+frag->size,
+                                   offset, copy, skb->len, skb) < 0) {
                                err = -EFAULT;
                                goto error;
                        }
index ab0c9ef..8905e92 100644 (file)
@@ -1067,7 +1067,7 @@ EXPORT_SYMBOL(compat_ip_setsockopt);
  */
 
 static int do_ip_getsockopt(struct sock *sk, int level, int optname,
-                           char __user *optval, int __user *optlen)
+                           char __user *optval, int __user *optlen, unsigned flags)
 {
        struct inet_sock *inet = inet_sk(sk);
        int val;
@@ -1240,7 +1240,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
 
                msg.msg_control = optval;
                msg.msg_controllen = len;
-               msg.msg_flags = 0;
+               msg.msg_flags = flags;
 
                if (inet->cmsg_flags & IP_CMSG_PKTINFO) {
                        struct in_pktinfo info;
@@ -1294,7 +1294,7 @@ int ip_getsockopt(struct sock *sk, int level,
 {
        int err;
 
-       err = do_ip_getsockopt(sk, level, optname, optval, optlen);
+       err = do_ip_getsockopt(sk, level, optname, optval, optlen, 0);
 #ifdef CONFIG_NETFILTER
        /* we need to exclude all possible ENOPROTOOPTs except default case */
        if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS &&
@@ -1327,7 +1327,8 @@ int compat_ip_getsockopt(struct sock *sk, int level, int optname,
                return compat_mc_getsockopt(sk, level, optname, optval, optlen,
                        ip_getsockopt);
 
-       err = do_ip_getsockopt(sk, level, optname, optval, optlen);
+       err = do_ip_getsockopt(sk, level, optname, optval, optlen,
+               MSG_CMSG_COMPAT);
 
 #ifdef CONFIG_NETFILTER
        /* we need to exclude all possible ENOPROTOOPTs except default case */
index 378b20b..065effd 100644 (file)
@@ -231,7 +231,7 @@ static void ipip_tunnel_unlink(struct ipip_net *ipn, struct ip_tunnel *t)
             (iter = rtnl_dereference(*tp)) != NULL;
             tp = &iter->next) {
                if (t == iter) {
-                       rcu_assign_pointer(*tp, t->next);
+                       RCU_INIT_POINTER(*tp, t->next);
                        break;
                }
        }
@@ -241,8 +241,8 @@ static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t)
 {
        struct ip_tunnel __rcu **tp = ipip_bucket(ipn, t);
 
-       rcu_assign_pointer(t->next, rtnl_dereference(*tp));
-       rcu_assign_pointer(*tp, t);
+       RCU_INIT_POINTER(t->next, rtnl_dereference(*tp));
+       RCU_INIT_POINTER(*tp, t);
 }
 
 static struct ip_tunnel * ipip_tunnel_locate(struct net *net,
@@ -301,7 +301,7 @@ static void ipip_tunnel_uninit(struct net_device *dev)
        struct ipip_net *ipn = net_generic(net, ipip_net_id);
 
        if (dev == ipn->fb_tunnel_dev)
-               rcu_assign_pointer(ipn->tunnels_wc[0], NULL);
+               RCU_INIT_POINTER(ipn->tunnels_wc[0], NULL);
        else
                ipip_tunnel_unlink(ipn, netdev_priv(dev));
        dev_put(dev);
@@ -791,7 +791,7 @@ static int __net_init ipip_fb_tunnel_init(struct net_device *dev)
                return -ENOMEM;
 
        dev_hold(dev);
-       rcu_assign_pointer(ipn->tunnels_wc[0], tunnel);
+       RCU_INIT_POINTER(ipn->tunnels_wc[0], tunnel);
        return 0;
 }
 
index 58e8791..6164e98 100644 (file)
@@ -1176,7 +1176,7 @@ static void mrtsock_destruct(struct sock *sk)
        ipmr_for_each_table(mrt, net) {
                if (sk == rtnl_dereference(mrt->mroute_sk)) {
                        IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
-                       rcu_assign_pointer(mrt->mroute_sk, NULL);
+                       RCU_INIT_POINTER(mrt->mroute_sk, NULL);
                        mroute_clean_tables(mrt);
                }
        }
@@ -1203,7 +1203,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
                return -ENOENT;
 
        if (optname != MRT_INIT) {
-               if (sk != rcu_dereference_raw(mrt->mroute_sk) &&
+               if (sk != rcu_access_pointer(mrt->mroute_sk) &&
                    !capable(CAP_NET_ADMIN))
                        return -EACCES;
        }
@@ -1224,13 +1224,13 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
 
                ret = ip_ra_control(sk, 1, mrtsock_destruct);
                if (ret == 0) {
-                       rcu_assign_pointer(mrt->mroute_sk, sk);
+                       RCU_INIT_POINTER(mrt->mroute_sk, sk);
                        IPV4_DEVCONF_ALL(net, MC_FORWARDING)++;
                }
                rtnl_unlock();
                return ret;
        case MRT_DONE:
-               if (sk != rcu_dereference_raw(mrt->mroute_sk))
+               if (sk != rcu_access_pointer(mrt->mroute_sk))
                        return -EACCES;
                return ip_ra_control(sk, 0, NULL);
        case MRT_ADD_VIF:
index 2e97e3e..929b27b 100644 (file)
@@ -18,17 +18,15 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
        struct rtable *rt;
        struct flowi4 fl4 = {};
        __be32 saddr = iph->saddr;
-       __u8 flags = 0;
+       __u8 flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
        unsigned int hh_len;
 
-       if (!skb->sk && addr_type != RTN_LOCAL) {
-               if (addr_type == RTN_UNSPEC)
-                       addr_type = inet_addr_type(net, saddr);
-               if (addr_type == RTN_LOCAL || addr_type == RTN_UNICAST)
-                       flags |= FLOWI_FLAG_ANYSRC;
-               else
-                       saddr = 0;
-       }
+       if (addr_type == RTN_UNSPEC)
+               addr_type = inet_addr_type(net, saddr);
+       if (addr_type == RTN_LOCAL || addr_type == RTN_UNICAST)
+               flags |= FLOWI_FLAG_ANYSRC;
+       else
+               saddr = 0;
 
        /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
         * packets with foreign saddr to appear on the NF_INET_LOCAL_OUT hook.
@@ -38,7 +36,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
        fl4.flowi4_tos = RT_TOS(iph->tos);
        fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
        fl4.flowi4_mark = skb->mark;
-       fl4.flowi4_flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : flags;
+       fl4.flowi4_flags = flags;
        rt = ip_route_output_key(net, &fl4);
        if (IS_ERR(rt))
                return -1;
index 703f366..7b22382 100644 (file)
@@ -70,14 +70,14 @@ static unsigned int help(struct sk_buff *skb,
 
 static void __exit nf_nat_amanda_fini(void)
 {
-       rcu_assign_pointer(nf_nat_amanda_hook, NULL);
+       RCU_INIT_POINTER(nf_nat_amanda_hook, NULL);
        synchronize_rcu();
 }
 
 static int __init nf_nat_amanda_init(void)
 {
        BUG_ON(nf_nat_amanda_hook != NULL);
-       rcu_assign_pointer(nf_nat_amanda_hook, help);
+       RCU_INIT_POINTER(nf_nat_amanda_hook, help);
        return 0;
 }
 
index 3346de5..447bc5c 100644 (file)
@@ -514,7 +514,7 @@ int nf_nat_protocol_register(const struct nf_nat_protocol *proto)
                ret = -EBUSY;
                goto out;
        }
-       rcu_assign_pointer(nf_nat_protos[proto->protonum], proto);
+       RCU_INIT_POINTER(nf_nat_protos[proto->protonum], proto);
  out:
        spin_unlock_bh(&nf_nat_lock);
        return ret;
@@ -525,7 +525,7 @@ EXPORT_SYMBOL(nf_nat_protocol_register);
 void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto)
 {
        spin_lock_bh(&nf_nat_lock);
-       rcu_assign_pointer(nf_nat_protos[proto->protonum],
+       RCU_INIT_POINTER(nf_nat_protos[proto->protonum],
                           &nf_nat_unknown_protocol);
        spin_unlock_bh(&nf_nat_lock);
        synchronize_rcu();
@@ -736,10 +736,10 @@ static int __init nf_nat_init(void)
        /* Sew in builtin protocols. */
        spin_lock_bh(&nf_nat_lock);
        for (i = 0; i < MAX_IP_NAT_PROTO; i++)
-               rcu_assign_pointer(nf_nat_protos[i], &nf_nat_unknown_protocol);
-       rcu_assign_pointer(nf_nat_protos[IPPROTO_TCP], &nf_nat_protocol_tcp);
-       rcu_assign_pointer(nf_nat_protos[IPPROTO_UDP], &nf_nat_protocol_udp);
-       rcu_assign_pointer(nf_nat_protos[IPPROTO_ICMP], &nf_nat_protocol_icmp);
+               RCU_INIT_POINTER(nf_nat_protos[i], &nf_nat_unknown_protocol);
+       RCU_INIT_POINTER(nf_nat_protos[IPPROTO_TCP], &nf_nat_protocol_tcp);
+       RCU_INIT_POINTER(nf_nat_protos[IPPROTO_UDP], &nf_nat_protocol_udp);
+       RCU_INIT_POINTER(nf_nat_protos[IPPROTO_ICMP], &nf_nat_protocol_icmp);
        spin_unlock_bh(&nf_nat_lock);
 
        /* Initialize fake conntrack so that NAT will skip it */
@@ -748,12 +748,12 @@ static int __init nf_nat_init(void)
        l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
 
        BUG_ON(nf_nat_seq_adjust_hook != NULL);
-       rcu_assign_pointer(nf_nat_seq_adjust_hook, nf_nat_seq_adjust);
+       RCU_INIT_POINTER(nf_nat_seq_adjust_hook, nf_nat_seq_adjust);
        BUG_ON(nfnetlink_parse_nat_setup_hook != NULL);
-       rcu_assign_pointer(nfnetlink_parse_nat_setup_hook,
+       RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook,
                           nfnetlink_parse_nat_setup);
        BUG_ON(nf_ct_nat_offset != NULL);
-       rcu_assign_pointer(nf_ct_nat_offset, nf_nat_get_offset);
+       RCU_INIT_POINTER(nf_ct_nat_offset, nf_nat_get_offset);
        return 0;
 
  cleanup_extend:
@@ -766,9 +766,9 @@ static void __exit nf_nat_cleanup(void)
        unregister_pernet_subsys(&nf_nat_net_ops);
        nf_ct_l3proto_put(l3proto);
        nf_ct_extend_unregister(&nat_extend);
-       rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL);
-       rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, NULL);
-       rcu_assign_pointer(nf_ct_nat_offset, NULL);
+       RCU_INIT_POINTER(nf_nat_seq_adjust_hook, NULL);
+       RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, NULL);
+       RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
        synchronize_net();
 }
 
index dc73abb..e462a95 100644 (file)
@@ -113,14 +113,14 @@ out:
 
 static void __exit nf_nat_ftp_fini(void)
 {
-       rcu_assign_pointer(nf_nat_ftp_hook, NULL);
+       RCU_INIT_POINTER(nf_nat_ftp_hook, NULL);
        synchronize_rcu();
 }
 
 static int __init nf_nat_ftp_init(void)
 {
        BUG_ON(nf_nat_ftp_hook != NULL);
-       rcu_assign_pointer(nf_nat_ftp_hook, nf_nat_ftp);
+       RCU_INIT_POINTER(nf_nat_ftp_hook, nf_nat_ftp);
        return 0;
 }
 
index 790f316..b9a1136 100644 (file)
@@ -581,30 +581,30 @@ static int __init init(void)
        BUG_ON(nat_callforwarding_hook != NULL);
        BUG_ON(nat_q931_hook != NULL);
 
-       rcu_assign_pointer(set_h245_addr_hook, set_h245_addr);
-       rcu_assign_pointer(set_h225_addr_hook, set_h225_addr);
-       rcu_assign_pointer(set_sig_addr_hook, set_sig_addr);
-       rcu_assign_pointer(set_ras_addr_hook, set_ras_addr);
-       rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp);
-       rcu_assign_pointer(nat_t120_hook, nat_t120);
-       rcu_assign_pointer(nat_h245_hook, nat_h245);
-       rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
-       rcu_assign_pointer(nat_q931_hook, nat_q931);
+       RCU_INIT_POINTER(set_h245_addr_hook, set_h245_addr);
+       RCU_INIT_POINTER(set_h225_addr_hook, set_h225_addr);
+       RCU_INIT_POINTER(set_sig_addr_hook, set_sig_addr);
+       RCU_INIT_POINTER(set_ras_addr_hook, set_ras_addr);
+       RCU_INIT_POINTER(nat_rtp_rtcp_hook, nat_rtp_rtcp);
+       RCU_INIT_POINTER(nat_t120_hook, nat_t120);
+       RCU_INIT_POINTER(nat_h245_hook, nat_h245);
+       RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding);
+       RCU_INIT_POINTER(nat_q931_hook, nat_q931);
        return 0;
 }
 
 /****************************************************************************/
 static void __exit fini(void)
 {
-       rcu_assign_pointer(set_h245_addr_hook, NULL);
-       rcu_assign_pointer(set_h225_addr_hook, NULL);
-       rcu_assign_pointer(set_sig_addr_hook, NULL);
-       rcu_assign_pointer(set_ras_addr_hook, NULL);
-       rcu_assign_pointer(nat_rtp_rtcp_hook, NULL);
-       rcu_assign_pointer(nat_t120_hook, NULL);
-       rcu_assign_pointer(nat_h245_hook, NULL);
-       rcu_assign_pointer(nat_callforwarding_hook, NULL);
-       rcu_assign_pointer(nat_q931_hook, NULL);
+       RCU_INIT_POINTER(set_h245_addr_hook, NULL);
+       RCU_INIT_POINTER(set_h225_addr_hook, NULL);
+       RCU_INIT_POINTER(set_sig_addr_hook, NULL);
+       RCU_INIT_POINTER(set_ras_addr_hook, NULL);
+       RCU_INIT_POINTER(nat_rtp_rtcp_hook, NULL);
+       RCU_INIT_POINTER(nat_t120_hook, NULL);
+       RCU_INIT_POINTER(nat_h245_hook, NULL);
+       RCU_INIT_POINTER(nat_callforwarding_hook, NULL);
+       RCU_INIT_POINTER(nat_q931_hook, NULL);
        synchronize_rcu();
 }
 
index 535e1a8..979ae16 100644 (file)
@@ -75,14 +75,14 @@ static unsigned int help(struct sk_buff *skb,
 
 static void __exit nf_nat_irc_fini(void)
 {
-       rcu_assign_pointer(nf_nat_irc_hook, NULL);
+       RCU_INIT_POINTER(nf_nat_irc_hook, NULL);
        synchronize_rcu();
 }
 
 static int __init nf_nat_irc_init(void)
 {
        BUG_ON(nf_nat_irc_hook != NULL);
-       rcu_assign_pointer(nf_nat_irc_hook, help);
+       RCU_INIT_POINTER(nf_nat_irc_hook, help);
        return 0;
 }
 
index 4c06003..3e8284b 100644 (file)
@@ -282,25 +282,25 @@ static int __init nf_nat_helper_pptp_init(void)
        nf_nat_need_gre();
 
        BUG_ON(nf_nat_pptp_hook_outbound != NULL);
-       rcu_assign_pointer(nf_nat_pptp_hook_outbound, pptp_outbound_pkt);
+       RCU_INIT_POINTER(nf_nat_pptp_hook_outbound, pptp_outbound_pkt);
 
        BUG_ON(nf_nat_pptp_hook_inbound != NULL);
-       rcu_assign_pointer(nf_nat_pptp_hook_inbound, pptp_inbound_pkt);
+       RCU_INIT_POINTER(nf_nat_pptp_hook_inbound, pptp_inbound_pkt);
 
        BUG_ON(nf_nat_pptp_hook_exp_gre != NULL);
-       rcu_assign_pointer(nf_nat_pptp_hook_exp_gre, pptp_exp_gre);
+       RCU_INIT_POINTER(nf_nat_pptp_hook_exp_gre, pptp_exp_gre);
 
        BUG_ON(nf_nat_pptp_hook_expectfn != NULL);
-       rcu_assign_pointer(nf_nat_pptp_hook_expectfn, pptp_nat_expected);
+       RCU_INIT_POINTER(nf_nat_pptp_hook_expectfn, pptp_nat_expected);
        return 0;
 }
 
 static void __exit nf_nat_helper_pptp_fini(void)
 {
-       rcu_assign_pointer(nf_nat_pptp_hook_expectfn, NULL);
-       rcu_assign_pointer(nf_nat_pptp_hook_exp_gre, NULL);
-       rcu_assign_pointer(nf_nat_pptp_hook_inbound, NULL);
-       rcu_assign_pointer(nf_nat_pptp_hook_outbound, NULL);
+       RCU_INIT_POINTER(nf_nat_pptp_hook_expectfn, NULL);
+       RCU_INIT_POINTER(nf_nat_pptp_hook_exp_gre, NULL);
+       RCU_INIT_POINTER(nf_nat_pptp_hook_inbound, NULL);
+       RCU_INIT_POINTER(nf_nat_pptp_hook_outbound, NULL);
        synchronize_rcu();
 }
 
index 3e61faf..f52d41e 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/ip.h>
 
 #include <linux/netfilter.h>
+#include <net/secure_seq.h>
 #include <net/netfilter/nf_nat.h>
 #include <net/netfilter/nf_nat_core.h>
 #include <net/netfilter/nf_nat_rule.h>
index e40cf78..78844d9 100644 (file)
@@ -528,13 +528,13 @@ err1:
 
 static void __exit nf_nat_sip_fini(void)
 {
-       rcu_assign_pointer(nf_nat_sip_hook, NULL);
-       rcu_assign_pointer(nf_nat_sip_seq_adjust_hook, NULL);
-       rcu_assign_pointer(nf_nat_sip_expect_hook, NULL);
-       rcu_assign_pointer(nf_nat_sdp_addr_hook, NULL);
-       rcu_assign_pointer(nf_nat_sdp_port_hook, NULL);
-       rcu_assign_pointer(nf_nat_sdp_session_hook, NULL);
-       rcu_assign_pointer(nf_nat_sdp_media_hook, NULL);
+       RCU_INIT_POINTER(nf_nat_sip_hook, NULL);
+       RCU_INIT_POINTER(nf_nat_sip_seq_adjust_hook, NULL);
+       RCU_INIT_POINTER(nf_nat_sip_expect_hook, NULL);
+       RCU_INIT_POINTER(nf_nat_sdp_addr_hook, NULL);
+       RCU_INIT_POINTER(nf_nat_sdp_port_hook, NULL);
+       RCU_INIT_POINTER(nf_nat_sdp_session_hook, NULL);
+       RCU_INIT_POINTER(nf_nat_sdp_media_hook, NULL);
        synchronize_rcu();
 }
 
@@ -547,13 +547,13 @@ static int __init nf_nat_sip_init(void)
        BUG_ON(nf_nat_sdp_port_hook != NULL);
        BUG_ON(nf_nat_sdp_session_hook != NULL);
        BUG_ON(nf_nat_sdp_media_hook != NULL);
-       rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip);
-       rcu_assign_pointer(nf_nat_sip_seq_adjust_hook, ip_nat_sip_seq_adjust);
-       rcu_assign_pointer(nf_nat_sip_expect_hook, ip_nat_sip_expect);
-       rcu_assign_pointer(nf_nat_sdp_addr_hook, ip_nat_sdp_addr);
-       rcu_assign_pointer(nf_nat_sdp_port_hook, ip_nat_sdp_port);
-       rcu_assign_pointer(nf_nat_sdp_session_hook, ip_nat_sdp_session);
-       rcu_assign_pointer(nf_nat_sdp_media_hook, ip_nat_sdp_media);
+       RCU_INIT_POINTER(nf_nat_sip_hook, ip_nat_sip);
+       RCU_INIT_POINTER(nf_nat_sip_seq_adjust_hook, ip_nat_sip_seq_adjust);
+       RCU_INIT_POINTER(nf_nat_sip_expect_hook, ip_nat_sip_expect);
+       RCU_INIT_POINTER(nf_nat_sdp_addr_hook, ip_nat_sdp_addr);
+       RCU_INIT_POINTER(nf_nat_sdp_port_hook, ip_nat_sdp_port);
+       RCU_INIT_POINTER(nf_nat_sdp_session_hook, ip_nat_sdp_session);
+       RCU_INIT_POINTER(nf_nat_sdp_media_hook, ip_nat_sdp_media);
        return 0;
 }
 
index 076b7c8..d1cb412 100644 (file)
@@ -1310,7 +1310,7 @@ static int __init nf_nat_snmp_basic_init(void)
        int ret = 0;
 
        BUG_ON(nf_nat_snmp_hook != NULL);
-       rcu_assign_pointer(nf_nat_snmp_hook, help);
+       RCU_INIT_POINTER(nf_nat_snmp_hook, help);
 
        ret = nf_conntrack_helper_register(&snmp_trap_helper);
        if (ret < 0) {
@@ -1322,7 +1322,7 @@ static int __init nf_nat_snmp_basic_init(void)
 
 static void __exit nf_nat_snmp_basic_fini(void)
 {
-       rcu_assign_pointer(nf_nat_snmp_hook, NULL);
+       RCU_INIT_POINTER(nf_nat_snmp_hook, NULL);
        nf_conntrack_helper_unregister(&snmp_trap_helper);
 }
 
index a6e606e..9290048 100644 (file)
@@ -284,7 +284,7 @@ static int __init nf_nat_standalone_init(void)
 
 #ifdef CONFIG_XFRM
        BUG_ON(ip_nat_decode_session != NULL);
-       rcu_assign_pointer(ip_nat_decode_session, nat_decode_session);
+       RCU_INIT_POINTER(ip_nat_decode_session, nat_decode_session);
 #endif
        ret = nf_nat_rule_init();
        if (ret < 0) {
@@ -302,7 +302,7 @@ static int __init nf_nat_standalone_init(void)
        nf_nat_rule_cleanup();
  cleanup_decode_session:
 #ifdef CONFIG_XFRM
-       rcu_assign_pointer(ip_nat_decode_session, NULL);
+       RCU_INIT_POINTER(ip_nat_decode_session, NULL);
        synchronize_net();
 #endif
        return ret;
@@ -313,7 +313,7 @@ static void __exit nf_nat_standalone_fini(void)
        nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
        nf_nat_rule_cleanup();
 #ifdef CONFIG_XFRM
-       rcu_assign_pointer(ip_nat_decode_session, NULL);
+       RCU_INIT_POINTER(ip_nat_decode_session, NULL);
        synchronize_net();
 #endif
        /* Conntrack caches are unregistered in nf_conntrack_cleanup */
index 7274a43..a2901bf 100644 (file)
@@ -36,14 +36,14 @@ static unsigned int help(struct sk_buff *skb,
 
 static void __exit nf_nat_tftp_fini(void)
 {
-       rcu_assign_pointer(nf_nat_tftp_hook, NULL);
+       RCU_INIT_POINTER(nf_nat_tftp_hook, NULL);
        synchronize_rcu();
 }
 
 static int __init nf_nat_tftp_init(void)
 {
        BUG_ON(nf_nat_tftp_hook != NULL);
-       rcu_assign_pointer(nf_nat_tftp_hook, help);
+       RCU_INIT_POINTER(nf_nat_tftp_hook, help);
        return 0;
 }
 
index 1457acb..61714bd 100644 (file)
@@ -563,7 +563,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
                           RT_SCOPE_UNIVERSE,
                           inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
-                          FLOWI_FLAG_CAN_SLEEP, daddr, saddr, 0, 0);
+                          inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP,
+                          daddr, saddr, 0, 0);
 
        if (!inet->hdrincl) {
                err = raw_probe_proto_opt(&fl4, msg);
index 1730689..2c21d3b 100644 (file)
 #include <linux/sysctl.h>
 #endif
 #include <net/atmclip.h>
+#include <net/secure_seq.h>
 
 #define RT_FL_TOS(oldflp4) \
     ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
@@ -323,7 +324,7 @@ static struct rtable *rt_cache_get_first(struct seq_file *seq)
        struct rtable *r = NULL;
 
        for (st->bucket = rt_hash_mask; st->bucket >= 0; --st->bucket) {
-               if (!rcu_dereference_raw(rt_hash_table[st->bucket].chain))
+               if (!rcu_access_pointer(rt_hash_table[st->bucket].chain))
                        continue;
                rcu_read_lock_bh();
                r = rcu_dereference_bh(rt_hash_table[st->bucket].chain);
@@ -349,7 +350,7 @@ static struct rtable *__rt_cache_get_next(struct seq_file *seq,
                do {
                        if (--st->bucket < 0)
                                return NULL;
-               } while (!rcu_dereference_raw(rt_hash_table[st->bucket].chain));
+               } while (!rcu_access_pointer(rt_hash_table[st->bucket].chain));
                rcu_read_lock_bh();
                r = rcu_dereference_bh(rt_hash_table[st->bucket].chain);
        }
@@ -721,7 +722,7 @@ static inline bool compare_hash_inputs(const struct rtable *rt1,
 {
        return ((((__force u32)rt1->rt_key_dst ^ (__force u32)rt2->rt_key_dst) |
                ((__force u32)rt1->rt_key_src ^ (__force u32)rt2->rt_key_src) |
-               (rt1->rt_iif ^ rt2->rt_iif)) == 0);
+               (rt1->rt_route_iif ^ rt2->rt_route_iif)) == 0);
 }
 
 static inline int compare_keys(struct rtable *rt1, struct rtable *rt2)
@@ -730,8 +731,8 @@ static inline int compare_keys(struct rtable *rt1, struct rtable *rt2)
                ((__force u32)rt1->rt_key_src ^ (__force u32)rt2->rt_key_src) |
                (rt1->rt_mark ^ rt2->rt_mark) |
                (rt1->rt_key_tos ^ rt2->rt_key_tos) |
-               (rt1->rt_oif ^ rt2->rt_oif) |
-               (rt1->rt_iif ^ rt2->rt_iif)) == 0;
+               (rt1->rt_route_iif ^ rt2->rt_route_iif) |
+               (rt1->rt_oif ^ rt2->rt_oif)) == 0;
 }
 
 static inline int compare_netns(struct rtable *rt1, struct rtable *rt2)
@@ -760,7 +761,7 @@ static void rt_do_flush(struct net *net, int process_context)
 
                if (process_context && need_resched())
                        cond_resched();
-               rth = rcu_dereference_raw(rt_hash_table[i].chain);
+               rth = rcu_access_pointer(rt_hash_table[i].chain);
                if (!rth)
                        continue;
 
@@ -1628,16 +1629,18 @@ static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
 {
        struct rtable *rt = (struct rtable *) dst;
        __be32 orig_gw = rt->rt_gateway;
-       struct neighbour *n;
+       struct neighbour *n, *old_n;
 
        dst_confirm(&rt->dst);
 
-       neigh_release(dst_get_neighbour(&rt->dst));
-       dst_set_neighbour(&rt->dst, NULL);
-
        rt->rt_gateway = peer->redirect_learned.a4;
-       rt_bind_neighbour(rt);
-       n = dst_get_neighbour(&rt->dst);
+
+       n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
+       if (IS_ERR(n))
+               return PTR_ERR(n);
+       old_n = xchg(&rt->dst._neighbour, n);
+       if (old_n)
+               neigh_release(old_n);
        if (!n || !(n->nud_state & NUD_VALID)) {
                if (n)
                        neigh_event_send(n, NULL);
@@ -2317,8 +2320,7 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr,
             rth = rcu_dereference(rth->dst.rt_next)) {
                if ((((__force u32)rth->rt_key_dst ^ (__force u32)daddr) |
                     ((__force u32)rth->rt_key_src ^ (__force u32)saddr) |
-                    (rth->rt_iif ^ iif) |
-                    rth->rt_oif |
+                    (rth->rt_route_iif ^ iif) |
                     (rth->rt_key_tos ^ tos)) == 0 &&
                    rth->rt_mark == skb->mark &&
                    net_eq(dev_net(rth->dst.dev), net) &&
index 92bb943..3bc5c8f 100644 (file)
@@ -276,7 +276,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
        int mss;
        struct rtable *rt;
        __u8 rcv_wscale;
-       bool ecn_ok;
+       bool ecn_ok = false;
 
        if (!sysctl_tcp_syncookies || !th->ack || th->rst)
                goto out;
index 46febca..5fe632c 100644 (file)
@@ -3035,7 +3035,8 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp,
 
        for (i = 0; i < shi->nr_frags; ++i) {
                const struct skb_frag_struct *f = &shi->frags[i];
-               sg_set_page(&sg, f->page, f->size, f->page_offset);
+               struct page *page = skb_frag_page(f);
+               sg_set_page(&sg, page, f->size, f->page_offset);
                if (crypto_hash_update(desc, &sg, f->size))
                        return 1;
        }
index ea0d218..385c470 100644 (file)
@@ -2830,9 +2830,13 @@ static int tcp_try_undo_loss(struct sock *sk)
 static inline void tcp_complete_cwr(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
-       /* Do not moderate cwnd if it's already undone in cwr or recovery */
-       if (tp->undo_marker && tp->snd_cwnd > tp->snd_ssthresh) {
-               tp->snd_cwnd = tp->snd_ssthresh;
+
+       /* Do not moderate cwnd if it's already undone in cwr or recovery. */
+       if (tp->undo_marker) {
+               if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR)
+                       tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
+               else /* PRR */
+                       tp->snd_cwnd = tp->snd_ssthresh;
                tp->snd_cwnd_stamp = tcp_time_stamp;
        }
        tcp_ca_event(sk, CA_EVENT_COMPLETE_CWR);
@@ -2950,6 +2954,38 @@ void tcp_simple_retransmit(struct sock *sk)
 }
 EXPORT_SYMBOL(tcp_simple_retransmit);
 
+/* This function implements the PRR algorithm, specifcally the PRR-SSRB
+ * (proportional rate reduction with slow start reduction bound) as described in
+ * http://www.ietf.org/id/draft-mathis-tcpm-proportional-rate-reduction-01.txt.
+ * It computes the number of packets to send (sndcnt) based on packets newly
+ * delivered:
+ *   1) If the packets in flight is larger than ssthresh, PRR spreads the
+ *     cwnd reductions across a full RTT.
+ *   2) If packets in flight is lower than ssthresh (such as due to excess
+ *     losses and/or application stalls), do not perform any further cwnd
+ *     reductions, but instead slow start up to ssthresh.
+ */
+static void tcp_update_cwnd_in_recovery(struct sock *sk, int newly_acked_sacked,
+                                       int fast_rexmit, int flag)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       int sndcnt = 0;
+       int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp);
+
+       if (tcp_packets_in_flight(tp) > tp->snd_ssthresh) {
+               u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered +
+                              tp->prior_cwnd - 1;
+               sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out;
+       } else {
+               sndcnt = min_t(int, delta,
+                              max_t(int, tp->prr_delivered - tp->prr_out,
+                                    newly_acked_sacked) + 1);
+       }
+
+       sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0));
+       tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt;
+}
+
 /* Process an event, which can update packets-in-flight not trivially.
  * Main goal of this function is to calculate new estimate for left_out,
  * taking into account both packets sitting in receiver's buffer and
@@ -2961,7 +2997,8 @@ EXPORT_SYMBOL(tcp_simple_retransmit);
  * It does _not_ decide what to send, it is made in function
  * tcp_xmit_retransmit_queue().
  */
-static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag)
+static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
+                                 int newly_acked_sacked, int flag)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
@@ -3111,13 +3148,17 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag)
 
                tp->bytes_acked = 0;
                tp->snd_cwnd_cnt = 0;
+               tp->prior_cwnd = tp->snd_cwnd;
+               tp->prr_delivered = 0;
+               tp->prr_out = 0;
                tcp_set_ca_state(sk, TCP_CA_Recovery);
                fast_rexmit = 1;
        }
 
        if (do_lost || (tcp_is_fack(tp) && tcp_head_timedout(sk)))
                tcp_update_scoreboard(sk, fast_rexmit);
-       tcp_cwnd_down(sk, flag);
+       tp->prr_delivered += newly_acked_sacked;
+       tcp_update_cwnd_in_recovery(sk, newly_acked_sacked, fast_rexmit, flag);
        tcp_xmit_retransmit_queue(sk);
 }
 
@@ -3632,6 +3673,8 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
        u32 prior_in_flight;
        u32 prior_fackets;
        int prior_packets;
+       int prior_sacked = tp->sacked_out;
+       int newly_acked_sacked = 0;
        int frto_cwnd = 0;
 
        /* If the ack is older than previous acks
@@ -3703,6 +3746,9 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
        /* See if we can take anything off of the retransmit queue. */
        flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una);
 
+       newly_acked_sacked = (prior_packets - prior_sacked) -
+                            (tp->packets_out - tp->sacked_out);
+
        if (tp->frto_counter)
                frto_cwnd = tcp_process_frto(sk, flag);
        /* Guarantee sacktag reordering detection against wrap-arounds */
@@ -3715,7 +3761,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
                    tcp_may_raise_cwnd(sk, flag))
                        tcp_cong_avoid(sk, ack, prior_in_flight);
                tcp_fastretrans_alert(sk, prior_packets - tp->packets_out,
-                                     flag);
+                                     newly_acked_sacked, flag);
        } else {
                if ((flag & FLAG_DATA_ACKED) && !frto_cwnd)
                        tcp_cong_avoid(sk, ack, prior_in_flight);
index 955b8e6..b3f2611 100644 (file)
@@ -72,6 +72,7 @@
 #include <net/timewait_sock.h>
 #include <net/xfrm.h>
 #include <net/netdma.h>
+#include <net/secure_seq.h>
 
 #include <linux/inet.h>
 #include <linux/ipv6.h>
@@ -1577,7 +1578,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
 #endif
 
        if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
-               sock_rps_save_rxhash(sk, skb->rxhash);
+               sock_rps_save_rxhash(sk, skb);
                if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
                        rsk = sk;
                        goto reset;
@@ -1594,7 +1595,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
                        goto discard;
 
                if (nsk != sk) {
-                       sock_rps_save_rxhash(nsk, skb->rxhash);
+                       sock_rps_save_rxhash(nsk, skb);
                        if (tcp_child_process(sk, nsk, skb)) {
                                rsk = nsk;
                                goto reset;
@@ -1602,7 +1603,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
                        return 0;
                }
        } else
-               sock_rps_save_rxhash(sk, skb->rxhash);
+               sock_rps_save_rxhash(sk, skb);
 
        if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) {
                rsk = sk;
index 882e0b0..081dcd6 100644 (file)
@@ -1095,7 +1095,7 @@ static void __pskb_trim_head(struct sk_buff *skb, int len)
        k = 0;
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                if (skb_shinfo(skb)->frags[i].size <= eat) {
-                       put_page(skb_shinfo(skb)->frags[i].page);
+                       skb_frag_unref(skb, i);
                        eat -= skb_shinfo(skb)->frags[i].size;
                } else {
                        skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
@@ -1796,11 +1796,13 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
                tcp_event_new_data_sent(sk, skb);
 
                tcp_minshall_update(tp, mss_now, skb);
-               sent_pkts++;
+               sent_pkts += tcp_skb_pcount(skb);
 
                if (push_one)
                        break;
        }
+       if (inet_csk(sk)->icsk_ca_state == TCP_CA_Recovery)
+               tp->prr_out += sent_pkts;
 
        if (likely(sent_pkts)) {
                tcp_cwnd_validate(sk);
@@ -2294,6 +2296,9 @@ begin_fwd:
                        return;
                NET_INC_STATS_BH(sock_net(sk), mib_idx);
 
+               if (inet_csk(sk)->icsk_ca_state == TCP_CA_Recovery)
+                       tp->prr_out += tcp_skb_pcount(skb);
+
                if (skb == tcp_write_queue_head(sk))
                        inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
                                                  inet_csk(sk)->icsk_rto,
index 1b5a193..ebaa96b 100644 (file)
@@ -1267,7 +1267,7 @@ int udp_disconnect(struct sock *sk, int flags)
        sk->sk_state = TCP_CLOSE;
        inet->inet_daddr = 0;
        inet->inet_dport = 0;
-       sock_rps_save_rxhash(sk, 0);
+       sock_rps_reset_rxhash(sk);
        sk->sk_bound_dev_if = 0;
        if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
                inet_reset_saddr(sk);
@@ -1355,7 +1355,7 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
        int rc;
 
        if (inet_sk(sk)->inet_daddr)
-               sock_rps_save_rxhash(sk, skb->rxhash);
+               sock_rps_save_rxhash(sk, skb);
 
        rc = ip_queue_rcv_skb(sk, skb);
        if (rc < 0) {
@@ -1461,10 +1461,9 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                }
        }
 
-       if (rcu_dereference_raw(sk->sk_filter)) {
-               if (udp_lib_checksum_complete(skb))
-                       goto drop;
-       }
+       if (rcu_access_pointer(sk->sk_filter) &&
+           udp_lib_checksum_complete(skb))
+               goto drop;
 
 
        if (sk_rcvqueues_full(sk, skb))
index a55500c..8f1e5be 100644 (file)
@@ -428,7 +428,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
        ndev->tstamp = jiffies;
        addrconf_sysctl_register(ndev);
        /* protected by rtnl_lock */
-       rcu_assign_pointer(dev->ip6_ptr, ndev);
+       RCU_INIT_POINTER(dev->ip6_ptr, ndev);
 
        /* Join all-node multicast group */
        ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes);
@@ -656,7 +656,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
         * layer address of our nexhop router
         */
 
-       if (dst_get_neighbour(&rt->dst) == NULL)
+       if (dst_get_neighbour_raw(&rt->dst) == NULL)
                ifa->flags &= ~IFA_F_OPTIMISTIC;
 
        ifa->idev = idev;
@@ -824,12 +824,13 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
 {
        struct inet6_dev *idev = ifp->idev;
        struct in6_addr addr, *tmpaddr;
-       unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp, age;
+       unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_tstamp, age;
        unsigned long regen_advance;
        int tmp_plen;
        int ret = 0;
        int max_addresses;
        u32 addr_flags;
+       unsigned long now = jiffies;
 
        write_lock(&idev->lock);
        if (ift) {
@@ -874,7 +875,7 @@ retry:
                goto out;
        }
        memcpy(&addr.s6_addr[8], idev->rndid, 8);
-       age = (jiffies - ifp->tstamp) / HZ;
+       age = (now - ifp->tstamp) / HZ;
        tmp_valid_lft = min_t(__u32,
                              ifp->valid_lft,
                              idev->cnf.temp_valid_lft + age);
@@ -884,7 +885,6 @@ retry:
                                 idev->cnf.max_desync_factor);
        tmp_plen = ifp->prefix_len;
        max_addresses = idev->cnf.max_addresses;
-       tmp_cstamp = ifp->cstamp;
        tmp_tstamp = ifp->tstamp;
        spin_unlock_bh(&ifp->lock);
 
@@ -929,7 +929,7 @@ retry:
        ift->ifpub = ifp;
        ift->valid_lft = tmp_valid_lft;
        ift->prefered_lft = tmp_prefered_lft;
-       ift->cstamp = tmp_cstamp;
+       ift->cstamp = now;
        ift->tstamp = tmp_tstamp;
        spin_unlock_bh(&ift->lock);
 
@@ -1999,25 +1999,50 @@ ok:
 #ifdef CONFIG_IPV6_PRIVACY
                        read_lock_bh(&in6_dev->lock);
                        /* update all temporary addresses in the list */
-                       list_for_each_entry(ift, &in6_dev->tempaddr_list, tmp_list) {
-                               /*
-                                * When adjusting the lifetimes of an existing
-                                * temporary address, only lower the lifetimes.
-                                * Implementations must not increase the
-                                * lifetimes of an existing temporary address
-                                * when processing a Prefix Information Option.
-                                */
+                       list_for_each_entry(ift, &in6_dev->tempaddr_list,
+                                           tmp_list) {
+                               int age, max_valid, max_prefered;
+
                                if (ifp != ift->ifpub)
                                        continue;
 
+                               /*
+                                * RFC 4941 section 3.3:
+                                * If a received option will extend the lifetime
+                                * of a public address, the lifetimes of
+                                * temporary addresses should be extended,
+                                * subject to the overall constraint that no
+                                * temporary addresses should ever remain
+                                * "valid" or "preferred" for a time longer than
+                                * (TEMP_VALID_LIFETIME) or
+                                * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR),
+                                * respectively.
+                                */
+                               age = (now - ift->cstamp) / HZ;
+                               max_valid = in6_dev->cnf.temp_valid_lft - age;
+                               if (max_valid < 0)
+                                       max_valid = 0;
+
+                               max_prefered = in6_dev->cnf.temp_prefered_lft -
+                                              in6_dev->cnf.max_desync_factor -
+                                              age;
+                               if (max_prefered < 0)
+                                       max_prefered = 0;
+
+                               if (valid_lft > max_valid)
+                                       valid_lft = max_valid;
+
+                               if (prefered_lft > max_prefered)
+                                       prefered_lft = max_prefered;
+
                                spin_lock(&ift->lock);
                                flags = ift->flags;
-                               if (ift->valid_lft > valid_lft &&
-                                   ift->valid_lft - valid_lft > (jiffies - ift->tstamp) / HZ)
-                                       ift->valid_lft = valid_lft + (jiffies - ift->tstamp) / HZ;
-                               if (ift->prefered_lft > prefered_lft &&
-                                   ift->prefered_lft - prefered_lft > (jiffies - ift->tstamp) / HZ)
-                                       ift->prefered_lft = prefered_lft + (jiffies - ift->tstamp) / HZ;
+                               ift->valid_lft = valid_lft;
+                               ift->prefered_lft = prefered_lft;
+                               ift->tstamp = now;
+                               if (prefered_lft > 0)
+                                       ift->flags &= ~IFA_F_DEPRECATED;
+
                                spin_unlock(&ift->lock);
                                if (!(flags&IFA_F_TENTATIVE))
                                        ipv6_ifa_notify(0, ift);
@@ -2025,9 +2050,11 @@ ok:
 
                        if ((create || list_empty(&in6_dev->tempaddr_list)) && in6_dev->cnf.use_tempaddr > 0) {
                                /*
-                                * When a new public address is created as described in [ADDRCONF],
-                                * also create a new temporary address. Also create a temporary
-                                * address if it's enabled but no temporary address currently exists.
+                                * When a new public address is created as
+                                * described in [ADDRCONF], also create a new
+                                * temporary address. Also create a temporary
+                                * address if it's enabled but no temporary
+                                * address currently exists.
                                 */
                                read_unlock_bh(&in6_dev->lock);
                                ipv6_create_tempaddr(ifp, NULL);
@@ -2706,7 +2733,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
                idev->dead = 1;
 
                /* protected by rtnl_lock */
-               rcu_assign_pointer(dev->ip6_ptr, NULL);
+               RCU_INIT_POINTER(dev->ip6_ptr, NULL);
 
                /* Step 1.5: remove snmp6 entry */
                snmp6_unregister_dev(idev);
index 1656033..9ef1831 100644 (file)
 #include <linux/errqueue.h>
 #include <asm/uaccess.h>
 
+static inline int ipv6_mapped_addr_any(const struct in6_addr *a)
+{
+       return (ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0));
+}
+
 int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
        struct sockaddr_in6     *usin = (struct sockaddr_in6 *) uaddr;
@@ -102,10 +107,12 @@ ipv4_connected:
 
                ipv6_addr_set_v4mapped(inet->inet_daddr, &np->daddr);
 
-               if (ipv6_addr_any(&np->saddr))
+               if (ipv6_addr_any(&np->saddr) ||
+                   ipv6_mapped_addr_any(&np->saddr))
                        ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
 
-               if (ipv6_addr_any(&np->rcv_saddr)) {
+               if (ipv6_addr_any(&np->rcv_saddr) ||
+                   ipv6_mapped_addr_any(&np->rcv_saddr)) {
                        ipv6_addr_set_v4mapped(inet->inet_rcv_saddr,
                                               &np->rcv_saddr);
                        if (sk->sk_prot->rehash)
index 79a485e..1318de4 100644 (file)
@@ -273,12 +273,12 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
        __u16 dstbuf;
 #endif
-       struct dst_entry *dst;
+       struct dst_entry *dst = skb_dst(skb);
 
        if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
            !pskb_may_pull(skb, (skb_transport_offset(skb) +
                                 ((skb_transport_header(skb)[1] + 1) << 3)))) {
-               IP6_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)),
+               IP6_INC_STATS_BH(dev_net(dst->dev), ip6_dst_idev(dst),
                                 IPSTATS_MIB_INHDRERRORS);
                kfree_skb(skb);
                return -1;
@@ -289,9 +289,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
        dstbuf = opt->dst1;
 #endif
 
-       dst = dst_clone(skb_dst(skb));
        if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
-               dst_release(dst);
                skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
                opt = IP6CB(skb);
 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
@@ -304,7 +302,6 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
 
        IP6_INC_STATS_BH(dev_net(dst->dev),
                         ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
-       dst_release(dst);
        return -1;
 }
 
index 1190041..2b59154 100644 (file)
@@ -490,7 +490,8 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
                goto out_dst_release;
        }
 
-       idev = in6_dev_get(skb->dev);
+       rcu_read_lock();
+       idev = __in6_dev_get(skb->dev);
 
        err = ip6_append_data(sk, icmpv6_getfrag, &msg,
                              len + sizeof(struct icmp6hdr),
@@ -500,19 +501,16 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
        if (err) {
                ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
                ip6_flush_pending_frames(sk);
-               goto out_put;
+       } else {
+               err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr,
+                                                len + sizeof(struct icmp6hdr));
        }
-       err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, len + sizeof(struct icmp6hdr));
-
-out_put:
-       if (likely(idev != NULL))
-               in6_dev_put(idev);
+       rcu_read_unlock();
 out_dst_release:
        dst_release(dst);
 out:
        icmpv6_xmit_unlock(sk);
 }
-
 EXPORT_SYMBOL(icmpv6_send);
 
 static void icmpv6_echo_reply(struct sk_buff *skb)
@@ -569,7 +567,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
        if (hlimit < 0)
                hlimit = ip6_dst_hoplimit(dst);
 
-       idev = in6_dev_get(skb->dev);
+       idev = __in6_dev_get(skb->dev);
 
        msg.skb = skb;
        msg.offset = 0;
@@ -583,13 +581,10 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
        if (err) {
                ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
                ip6_flush_pending_frames(sk);
-               goto out_put;
+       } else {
+               err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr,
+                                                skb->len + sizeof(struct icmp6hdr));
        }
-       err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, skb->len + sizeof(struct icmp6hdr));
-
-out_put:
-       if (likely(idev != NULL))
-               in6_dev_put(idev);
        dst_release(dst);
 out:
        icmpv6_xmit_unlock(sk);
index 8a58e8c..2916200 100644 (file)
@@ -211,6 +211,7 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused)
        struct flowi6 fl6;
        struct dst_entry *dst;
        struct in6_addr *final_p, final;
+       int res;
 
        memset(&fl6, 0, sizeof(fl6));
        fl6.flowi6_proto = sk->sk_protocol;
@@ -241,12 +242,14 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused)
                __inet6_csk_dst_store(sk, dst, NULL, NULL);
        }
 
-       skb_dst_set(skb, dst_clone(dst));
+       rcu_read_lock();
+       skb_dst_set_noref(skb, dst);
 
        /* Restore final destination back after routing done */
        ipv6_addr_copy(&fl6.daddr, &np->daddr);
 
-       return ip6_xmit(sk, skb, &fl6, np->opt);
+       res = ip6_xmit(sk, skb, &fl6, np->opt);
+       rcu_read_unlock();
+       return res;
 }
-
 EXPORT_SYMBOL_GPL(inet6_csk_xmit);
index b531972..73f1a00 100644 (file)
@@ -20,6 +20,7 @@
 #include <net/inet_connection_sock.h>
 #include <net/inet_hashtables.h>
 #include <net/inet6_hashtables.h>
+#include <net/secure_seq.h>
 #include <net/ip.h>
 
 int __inet6_hash(struct sock *sk, struct inet_timewait_sock *tw)
index 54a4678..320d91d 100644 (file)
@@ -1455,7 +1455,7 @@ static int fib6_age(struct rt6_info *rt, void *arg)
                        RT6_TRACE("aging clone %p\n", rt);
                        return -1;
                } else if ((rt->rt6i_flags & RTF_GATEWAY) &&
-                          (!(dst_get_neighbour(&rt->dst)->flags & NTF_ROUTER))) {
+                          (!(dst_get_neighbour_raw(&rt->dst)->flags & NTF_ROUTER))) {
                        RT6_TRACE("purging route %p via non-router but gateway\n",
                                  rt);
                        return -1;
index 32e5339..835c04b 100644 (file)
@@ -135,10 +135,15 @@ static int ip6_finish_output2(struct sk_buff *skb)
                                skb->len);
        }
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(dst);
-       if (neigh)
-               return neigh_output(neigh, skb);
+       if (neigh) {
+               int res = neigh_output(neigh, skb);
 
+               rcu_read_unlock();
+               return res;
+       }
+       rcu_read_unlock();
        IP6_INC_STATS_BH(dev_net(dst->dev),
                         ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
        kfree_skb(skb);
@@ -975,12 +980,14 @@ static int ip6_dst_lookup_tail(struct sock *sk,
         * dst entry and replace it instead with the
         * dst entry of the nexthop router
         */
+       rcu_read_lock();
        n = dst_get_neighbour(*dst);
        if (n && !(n->nud_state & NUD_VALID)) {
                struct inet6_ifaddr *ifp;
                struct flowi6 fl_gw6;
                int redirect;
 
+               rcu_read_unlock();
                ifp = ipv6_get_ifaddr(net, &fl6->saddr,
                                      (*dst)->dev, 1);
 
@@ -1000,6 +1007,8 @@ static int ip6_dst_lookup_tail(struct sock *sk,
                        if ((err = (*dst)->error))
                                goto out_err_release;
                }
+       } else {
+               rcu_read_unlock();
        }
 #endif
 
@@ -1471,13 +1480,13 @@ alloc_new_skb:
                        if (page && (left = PAGE_SIZE - off) > 0) {
                                if (copy >= left)
                                        copy = left;
-                               if (page != frag->page) {
+                               if (page != skb_frag_page(frag)) {
                                        if (i == MAX_SKB_FRAGS) {
                                                err = -EMSGSIZE;
                                                goto error;
                                        }
-                                       get_page(page);
                                        skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
+                                       skb_frag_ref(skb, i);
                                        frag = &skb_shinfo(skb)->frags[i];
                                }
                        } else if(i < MAX_SKB_FRAGS) {
@@ -1497,7 +1506,8 @@ alloc_new_skb:
                                err = -EMSGSIZE;
                                goto error;
                        }
-                       if (getfrag(from, page_address(frag->page)+frag->page_offset+frag->size, offset, copy, skb->len, skb) < 0) {
+                       if (getfrag(from, skb_frag_address(frag)+frag->size,
+                                   offset, copy, skb->len, skb) < 0) {
                                err = -EFAULT;
                                goto error;
                        }
index 0bc9888..694d70a 100644 (file)
@@ -218,8 +218,8 @@ ip6_tnl_link(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
 {
        struct ip6_tnl __rcu **tp = ip6_tnl_bucket(ip6n, &t->parms);
 
-       rcu_assign_pointer(t->next , rtnl_dereference(*tp));
-       rcu_assign_pointer(*tp, t);
+       RCU_INIT_POINTER(t->next , rtnl_dereference(*tp));
+       RCU_INIT_POINTER(*tp, t);
 }
 
 /**
@@ -237,7 +237,7 @@ ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
             (iter = rtnl_dereference(*tp)) != NULL;
             tp = &iter->next) {
                if (t == iter) {
-                       rcu_assign_pointer(*tp, t->next);
+                       RCU_INIT_POINTER(*tp, t->next);
                        break;
                }
        }
@@ -350,7 +350,7 @@ ip6_tnl_dev_uninit(struct net_device *dev)
        struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
 
        if (dev == ip6n->fb_tnl_dev)
-               rcu_assign_pointer(ip6n->tnls_wc[0], NULL);
+               RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL);
        else
                ip6_tnl_unlink(ip6n, t);
        ip6_tnl_dst_reset(t);
@@ -889,7 +889,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
        struct net_device_stats *stats = &t->dev->stats;
        struct ipv6hdr *ipv6h = ipv6_hdr(skb);
        struct ipv6_tel_txoption opt;
-       struct dst_entry *dst;
+       struct dst_entry *dst, *ndst = NULL;
        struct net_device *tdev;
        int mtu;
        unsigned int max_headroom = sizeof(struct ipv6hdr);
@@ -897,19 +897,19 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
        int err = -1;
        int pkt_len;
 
-       if ((dst = ip6_tnl_dst_check(t)) != NULL)
-               dst_hold(dst);
-       else {
-               dst = ip6_route_output(net, NULL, fl6);
+       dst = ip6_tnl_dst_check(t);
+       if (!dst) {
+               ndst = ip6_route_output(net, NULL, fl6);
 
-               if (dst->error)
+               if (ndst->error)
                        goto tx_err_link_failure;
-               dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), NULL, 0);
-               if (IS_ERR(dst)) {
-                       err = PTR_ERR(dst);
-                       dst = NULL;
+               ndst = xfrm_lookup(net, ndst, flowi6_to_flowi(fl6), NULL, 0);
+               if (IS_ERR(ndst)) {
+                       err = PTR_ERR(ndst);
+                       ndst = NULL;
                        goto tx_err_link_failure;
                }
+               dst = ndst;
        }
 
        tdev = dst->dev;
@@ -955,7 +955,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
                skb = new_skb;
        }
        skb_dst_drop(skb);
-       skb_dst_set(skb, dst_clone(dst));
+       skb_dst_set_noref(skb, dst);
 
        skb->transport_header = skb->network_header;
 
@@ -987,13 +987,14 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
                stats->tx_errors++;
                stats->tx_aborted_errors++;
        }
-       ip6_tnl_dst_store(t, dst);
+       if (ndst)
+               ip6_tnl_dst_store(t, ndst);
        return 0;
 tx_err_link_failure:
        stats->tx_carrier_errors++;
        dst_link_failure(skb);
 tx_err_dst_release:
-       dst_release(dst);
+       dst_release(ndst);
        return err;
 }
 
@@ -1439,7 +1440,7 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev)
 
        t->parms.proto = IPPROTO_IPV6;
        dev_hold(dev);
-       rcu_assign_pointer(ip6n->tnls_wc[0], t);
+       RCU_INIT_POINTER(ip6n->tnls_wc[0], t);
        return 0;
 }
 
index 9cb191e..147ede3 100644 (file)
@@ -913,7 +913,7 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
 }
 
 static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
-                   char __user *optval, int __user *optlen)
+                   char __user *optval, int __user *optlen, unsigned flags)
 {
        struct ipv6_pinfo *np = inet6_sk(sk);
        int len;
@@ -962,7 +962,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
 
                msg.msg_control = optval;
                msg.msg_controllen = len;
-               msg.msg_flags = 0;
+               msg.msg_flags = flags;
 
                lock_sock(sk);
                skb = np->pktoptions;
@@ -1222,7 +1222,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
        if(level != SOL_IPV6)
                return -ENOPROTOOPT;
 
-       err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
+       err = do_ipv6_getsockopt(sk, level, optname, optval, optlen, 0);
 #ifdef CONFIG_NETFILTER
        /* we need to exclude all possible ENOPROTOOPTs except default case */
        if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
@@ -1264,7 +1264,8 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
                return compat_mc_getsockopt(sk, level, optname, optval, optlen,
                        ipv6_getsockopt);
 
-       err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
+       err = do_ipv6_getsockopt(sk, level, optname, optval, optlen,
+                                MSG_CMSG_COMPAT);
 #ifdef CONFIG_NETFILTER
        /* we need to exclude all possible ENOPROTOOPTs except default case */
        if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
index 9da6e02..1f52dd2 100644 (file)
@@ -533,7 +533,8 @@ void ndisc_send_skb(struct sk_buff *skb,
 
        skb_dst_set(skb, dst);
 
-       idev = in6_dev_get(dst->dev);
+       rcu_read_lock();
+       idev = __in6_dev_get(dst->dev);
        IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
 
        err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
@@ -543,8 +544,7 @@ void ndisc_send_skb(struct sk_buff *skb,
                ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
        }
 
-       if (likely(idev != NULL))
-               in6_dev_put(idev);
+       rcu_read_unlock();
 }
 
 EXPORT_SYMBOL(ndisc_send_skb);
@@ -1039,7 +1039,7 @@ static void ndisc_recv_rs(struct sk_buff *skb)
        if (skb->len < sizeof(*rs_msg))
                return;
 
-       idev = in6_dev_get(skb->dev);
+       idev = __in6_dev_get(skb->dev);
        if (!idev) {
                if (net_ratelimit())
                        ND_PRINTK1("ICMP6 RS: can't find in6 device\n");
@@ -1080,7 +1080,7 @@ static void ndisc_recv_rs(struct sk_buff *skb)
                neigh_release(neigh);
        }
 out:
-       in6_dev_put(idev);
+       return;
 }
 
 static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt)
@@ -1179,7 +1179,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
         *      set the RA_RECV flag in the interface
         */
 
-       in6_dev = in6_dev_get(skb->dev);
+       in6_dev = __in6_dev_get(skb->dev);
        if (in6_dev == NULL) {
                ND_PRINTK0(KERN_ERR
                           "ICMPv6 RA: can't find inet6 device for %s.\n",
@@ -1188,7 +1188,6 @@ static void ndisc_router_discovery(struct sk_buff *skb)
        }
 
        if (!ndisc_parse_options(opt, optlen, &ndopts)) {
-               in6_dev_put(in6_dev);
                ND_PRINTK2(KERN_WARNING
                           "ICMP6 RA: invalid ND options\n");
                return;
@@ -1255,7 +1254,6 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                        ND_PRINTK0(KERN_ERR
                                   "ICMPv6 RA: %s() failed to add default route.\n",
                                   __func__);
-                       in6_dev_put(in6_dev);
                        return;
                }
 
@@ -1265,7 +1263,6 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                                   "ICMPv6 RA: %s() got default router without neighbour.\n",
                                   __func__);
                        dst_release(&rt->dst);
-                       in6_dev_put(in6_dev);
                        return;
                }
                neigh->flags |= NTF_ROUTER;
@@ -1422,7 +1419,6 @@ out:
                dst_release(&rt->dst);
        else if (neigh)
                neigh_release(neigh);
-       in6_dev_put(in6_dev);
 }
 
 static void ndisc_redirect_rcv(struct sk_buff *skb)
@@ -1481,13 +1477,11 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
                return;
        }
 
-       in6_dev = in6_dev_get(skb->dev);
+       in6_dev = __in6_dev_get(skb->dev);
        if (!in6_dev)
                return;
-       if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) {
-               in6_dev_put(in6_dev);
+       if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects)
                return;
-       }
 
        /* RFC2461 8.1:
         *      The IP source address of the Redirect MUST be the same as the current
@@ -1497,7 +1491,6 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
        if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) {
                ND_PRINTK2(KERN_WARNING
                           "ICMPv6 Redirect: invalid ND options\n");
-               in6_dev_put(in6_dev);
                return;
        }
        if (ndopts.nd_opts_tgt_lladdr) {
@@ -1506,7 +1499,6 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
                if (!lladdr) {
                        ND_PRINTK2(KERN_WARNING
                                   "ICMPv6 Redirect: invalid link-layer address length\n");
-                       in6_dev_put(in6_dev);
                        return;
                }
        }
@@ -1518,7 +1510,6 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
                             on_link);
                neigh_release(neigh);
        }
-       in6_dev_put(in6_dev);
 }
 
 void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
@@ -1651,7 +1642,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
                                             csum_partial(icmph, len, 0));
 
        skb_dst_set(buff, dst);
-       idev = in6_dev_get(dst->dev);
+       rcu_read_lock();
+       idev = __in6_dev_get(dst->dev);
        IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
        err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev,
                      dst_output);
@@ -1660,8 +1652,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
                ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
        }
 
-       if (likely(idev != NULL))
-               in6_dev_put(idev);
+       rcu_read_unlock();
        return;
 
 release:
index 6a79f30..f34902f 100644 (file)
@@ -130,14 +130,14 @@ static mh_filter_t __rcu *mh_filter __read_mostly;
 
 int rawv6_mh_filter_register(mh_filter_t filter)
 {
-       rcu_assign_pointer(mh_filter, filter);
+       RCU_INIT_POINTER(mh_filter, filter);
        return 0;
 }
 EXPORT_SYMBOL(rawv6_mh_filter_register);
 
 int rawv6_mh_filter_unregister(mh_filter_t filter)
 {
-       rcu_assign_pointer(mh_filter, NULL);
+       RCU_INIT_POINTER(mh_filter, NULL);
        synchronize_rcu();
        return 0;
 }
@@ -372,9 +372,9 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
        read_unlock(&raw_v6_hashinfo.lock);
 }
 
-static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
+static inline int rawv6_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
-       if ((raw6_sk(sk)->checksum || rcu_dereference_raw(sk->sk_filter)) &&
+       if ((raw6_sk(sk)->checksum || rcu_access_pointer(sk->sk_filter)) &&
            skb_checksum_complete(skb)) {
                atomic_inc(&sk->sk_drops);
                kfree_skb(skb);
index e8987da..9e69eb0 100644 (file)
@@ -364,7 +364,7 @@ out:
 #ifdef CONFIG_IPV6_ROUTER_PREF
 static void rt6_probe(struct rt6_info *rt)
 {
-       struct neighbour *neigh = rt ? dst_get_neighbour(&rt->dst) : NULL;
+       struct neighbour *neigh;
        /*
         * Okay, this does not seem to be appropriate
         * for now, however, we need to check if it
@@ -373,8 +373,10 @@ static void rt6_probe(struct rt6_info *rt)
         * Router Reachability Probe MUST be rate-limited
         * to no more than one per minute.
         */
+       rcu_read_lock();
+       neigh = rt ? dst_get_neighbour(&rt->dst) : NULL;
        if (!neigh || (neigh->nud_state & NUD_VALID))
-               return;
+               goto out;
        read_lock_bh(&neigh->lock);
        if (!(neigh->nud_state & NUD_VALID) &&
            time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
@@ -387,8 +389,11 @@ static void rt6_probe(struct rt6_info *rt)
                target = (struct in6_addr *)&neigh->primary_key;
                addrconf_addr_solict_mult(target, &mcaddr);
                ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL);
-       } else
+       } else {
                read_unlock_bh(&neigh->lock);
+       }
+out:
+       rcu_read_unlock();
 }
 #else
 static inline void rt6_probe(struct rt6_info *rt)
@@ -412,8 +417,11 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
 
 static inline int rt6_check_neigh(struct rt6_info *rt)
 {
-       struct neighbour *neigh = dst_get_neighbour(&rt->dst);
+       struct neighbour *neigh;
        int m;
+
+       rcu_read_lock();
+       neigh = dst_get_neighbour(&rt->dst);
        if (rt->rt6i_flags & RTF_NONEXTHOP ||
            !(rt->rt6i_flags & RTF_GATEWAY))
                m = 1;
@@ -430,6 +438,7 @@ static inline int rt6_check_neigh(struct rt6_info *rt)
                read_unlock_bh(&neigh->lock);
        } else
                m = 0;
+       rcu_read_unlock();
        return m;
 }
 
@@ -769,7 +778,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort,
                rt->rt6i_dst.plen = 128;
                rt->rt6i_flags |= RTF_CACHE;
                rt->dst.flags |= DST_HOST;
-               dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour(&ort->dst)));
+               dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst)));
        }
        return rt;
 }
@@ -803,7 +812,7 @@ restart:
        dst_hold(&rt->dst);
        read_unlock_bh(&table->tb6_lock);
 
-       if (!dst_get_neighbour(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
+       if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
                nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
        else if (!(rt->dst.flags & DST_HOST))
                nrt = rt6_alloc_clone(rt, &fl6->daddr);
@@ -1587,7 +1596,7 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
        dst_confirm(&rt->dst);
 
        /* Duplicate redirect: silently ignore. */
-       if (neigh == dst_get_neighbour(&rt->dst))
+       if (neigh == dst_get_neighbour_raw(&rt->dst))
                goto out;
 
        nrt = ip6_rt_copy(rt, dest);
@@ -1682,7 +1691,7 @@ again:
           1. It is connected route. Action: COW
           2. It is gatewayed route or NONEXTHOP route. Action: clone it.
         */
-       if (!dst_get_neighbour(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
+       if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
                nrt = rt6_alloc_cow(rt, daddr, saddr);
        else
                nrt = rt6_alloc_clone(rt, daddr);
@@ -2326,6 +2335,7 @@ static int rt6_fill_node(struct net *net,
        struct nlmsghdr *nlh;
        long expires;
        u32 table;
+       struct neighbour *n;
 
        if (prefix) {   /* user wants prefix routes only */
                if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
@@ -2414,8 +2424,11 @@ static int rt6_fill_node(struct net *net,
        if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
                goto nla_put_failure;
 
-       if (dst_get_neighbour(&rt->dst))
-               NLA_PUT(skb, RTA_GATEWAY, 16, &dst_get_neighbour(&rt->dst)->primary_key);
+       rcu_read_lock();
+       n = dst_get_neighbour(&rt->dst);
+       if (n)
+               NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key);
+       rcu_read_unlock();
 
        if (rt->dst.dev)
                NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex);
@@ -2608,12 +2621,14 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
 #else
        seq_puts(m, "00000000000000000000000000000000 00 ");
 #endif
+       rcu_read_lock();
        n = dst_get_neighbour(&rt->dst);
        if (n) {
                seq_printf(m, "%pi6", n->primary_key);
        } else {
                seq_puts(m, "00000000000000000000000000000000");
        }
+       rcu_read_unlock();
        seq_printf(m, " %08x %08x %08x %08x %8s\n",
                   rt->rt6i_metric, atomic_read(&rt->dst.__refcnt),
                   rt->dst.__use, rt->rt6i_flags,
index 07bf108..a7a1860 100644 (file)
@@ -182,7 +182,7 @@ static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t)
             (iter = rtnl_dereference(*tp)) != NULL;
             tp = &iter->next) {
                if (t == iter) {
-                       rcu_assign_pointer(*tp, t->next);
+                       RCU_INIT_POINTER(*tp, t->next);
                        break;
                }
        }
@@ -192,8 +192,8 @@ static void ipip6_tunnel_link(struct sit_net *sitn, struct ip_tunnel *t)
 {
        struct ip_tunnel __rcu **tp = ipip6_bucket(sitn, t);
 
-       rcu_assign_pointer(t->next, rtnl_dereference(*tp));
-       rcu_assign_pointer(*tp, t);
+       RCU_INIT_POINTER(t->next, rtnl_dereference(*tp));
+       RCU_INIT_POINTER(*tp, t);
 }
 
 static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn)
@@ -391,7 +391,7 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg)
        p->addr = a->addr;
        p->flags = a->flags;
        t->prl_count++;
-       rcu_assign_pointer(t->prl, p);
+       RCU_INIT_POINTER(t->prl, p);
 out:
        return err;
 }
@@ -474,7 +474,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
        struct sit_net *sitn = net_generic(net, sit_net_id);
 
        if (dev == sitn->fb_tunnel_dev) {
-               rcu_assign_pointer(sitn->tunnels_wc[0], NULL);
+               RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL);
        } else {
                ipip6_tunnel_unlink(sitn, netdev_priv(dev));
                ipip6_tunnel_del_prl(netdev_priv(dev), NULL);
@@ -672,6 +672,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
        if (skb->protocol != htons(ETH_P_IPV6))
                goto tx_error;
 
+       if (tos == 1)
+               tos = ipv6_get_dsfield(iph6);
+
        /* ISATAP (RFC4214) - must come before 6to4 */
        if (dev->priv_flags & IFF_ISATAP) {
                struct neighbour *neigh = NULL;
@@ -1173,7 +1176,7 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
        if (!dev->tstats)
                return -ENOMEM;
        dev_hold(dev);
-       rcu_assign_pointer(sitn->tunnels_wc[0], tunnel);
+       RCU_INIT_POINTER(sitn->tunnels_wc[0], tunnel);
        return 0;
 }
 
index 89d5bf8..ac83896 100644 (file)
@@ -165,7 +165,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
        int mss;
        struct dst_entry *dst;
        __u8 rcv_wscale;
-       bool ecn_ok;
+       bool ecn_ok = false;
 
        if (!sysctl_tcp_syncookies || !th->ack || th->rst)
                goto out;
index 78aa534..44a5859 100644 (file)
@@ -61,6 +61,7 @@
 #include <net/timewait_sock.h>
 #include <net/netdma.h>
 #include <net/inet_common.h>
+#include <net/secure_seq.h>
 
 #include <asm/uaccess.h>
 
@@ -1627,7 +1628,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
                opt_skb = skb_clone(skb, GFP_ATOMIC);
 
        if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
-               sock_rps_save_rxhash(sk, skb->rxhash);
+               sock_rps_save_rxhash(sk, skb);
                if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len))
                        goto reset;
                if (opt_skb)
@@ -1649,7 +1650,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
                 * the new socket..
                 */
                if(nsk != sk) {
-                       sock_rps_save_rxhash(nsk, skb->rxhash);
+                       sock_rps_save_rxhash(nsk, skb);
                        if (tcp_child_process(sk, nsk, skb))
                                goto reset;
                        if (opt_skb)
@@ -1657,7 +1658,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
                        return 0;
                }
        } else
-               sock_rps_save_rxhash(sk, skb->rxhash);
+               sock_rps_save_rxhash(sk, skb);
 
        if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len))
                goto reset;
index 29213b5..35bbdc4 100644 (file)
@@ -509,7 +509,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
        int is_udplite = IS_UDPLITE(sk);
 
        if (!ipv6_addr_any(&inet6_sk(sk)->daddr))
-               sock_rps_save_rxhash(sk, skb->rxhash);
+               sock_rps_save_rxhash(sk, skb);
 
        if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
                goto drop;
@@ -533,7 +533,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
                }
        }
 
-       if (rcu_dereference_raw(sk->sk_filter)) {
+       if (rcu_access_pointer(sk->sk_filter)) {
                if (udp_lib_checksum_complete(skb))
                        goto drop;
        }
index e8d5f44..d14152e 100644 (file)
@@ -50,7 +50,7 @@ static const struct net_device_ops irlan_eth_netdev_ops = {
        .ndo_open               = irlan_eth_open,
        .ndo_stop               = irlan_eth_close,
        .ndo_start_xmit         = irlan_eth_xmit,
-       .ndo_set_multicast_list = irlan_eth_set_multicast_list,
+       .ndo_set_rx_mode        = irlan_eth_set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 16ce9cd..497fbe7 100644 (file)
@@ -1,15 +1,17 @@
 config IUCV
-       tristate "IUCV support (S390 - z/VM only)"
        depends on S390
+       def_tristate y if S390
+       prompt "IUCV support (S390 - z/VM only)"
        help
          Select this option if you want to use inter-user communication
          under VM or VIF. If you run on z/VM, say "Y" to enable a fast
          communication link between VM guests.
 
 config AFIUCV
-       tristate "AF_IUCV support (S390 - z/VM only)"
-       depends on IUCV
+       depends on S390
+       def_tristate m if QETH_L3 || IUCV
+       prompt "AF_IUCV Socket support (S390 - z/VM and HiperSockets transport)"
        help
-         Select this option if you want to use inter-user communication under
-         VM or VIF sockets. If you run on z/VM, say "Y" to enable a fast
-         communication link between VM guests.
+         Select this option if you want to use AF_IUCV socket applications
+         based on z/VM inter-user communication vehicle or based on
+         HiperSockets.
index e2013e4..c39f3a4 100644 (file)
 #include <asm/cpcmd.h>
 #include <linux/kmod.h>
 
-#include <net/iucv/iucv.h>
 #include <net/iucv/af_iucv.h>
 
-#define VERSION "1.1"
+#define VERSION "1.2"
 
 static char iucv_userid[80];
 
@@ -42,6 +41,8 @@ static struct proto iucv_proto = {
        .obj_size       = sizeof(struct iucv_sock),
 };
 
+static struct iucv_interface *pr_iucv;
+
 /* special AF_IUCV IPRM messages */
 static const u8 iprm_shutdown[8] =
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
@@ -90,6 +91,12 @@ do {                                                                 \
 static void iucv_sock_kill(struct sock *sk);
 static void iucv_sock_close(struct sock *sk);
 
+static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
+       struct packet_type *pt, struct net_device *orig_dev);
+static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
+                  struct sk_buff *skb, u8 flags);
+static void afiucv_hs_callback_txnotify(struct sk_buff *, enum iucv_tx_notify);
+
 /* Call Back functions */
 static void iucv_callback_rx(struct iucv_path *, struct iucv_message *);
 static void iucv_callback_txdone(struct iucv_path *, struct iucv_message *);
@@ -165,7 +172,7 @@ static int afiucv_pm_freeze(struct device *dev)
                case IUCV_CLOSING:
                case IUCV_CONNECTED:
                        if (iucv->path) {
-                               err = iucv_path_sever(iucv->path, NULL);
+                               err = pr_iucv->path_sever(iucv->path, NULL);
                                iucv_path_free(iucv->path);
                                iucv->path = NULL;
                        }
@@ -229,7 +236,7 @@ static const struct dev_pm_ops afiucv_pm_ops = {
 static struct device_driver af_iucv_driver = {
        .owner = THIS_MODULE,
        .name = "afiucv",
-       .bus  = &iucv_bus,
+       .bus  = NULL,
        .pm   = &afiucv_pm_ops,
 };
 
@@ -294,7 +301,11 @@ static inline int iucv_below_msglim(struct sock *sk)
 
        if (sk->sk_state != IUCV_CONNECTED)
                return 1;
-       return (skb_queue_len(&iucv->send_skb_q) < iucv->path->msglim);
+       if (iucv->transport == AF_IUCV_TRANS_IUCV)
+               return (skb_queue_len(&iucv->send_skb_q) < iucv->path->msglim);
+       else
+               return ((atomic_read(&iucv->msg_sent) < iucv->msglimit_peer) &&
+                       (atomic_read(&iucv->pendings) <= 0));
 }
 
 /**
@@ -312,6 +323,79 @@ static void iucv_sock_wake_msglim(struct sock *sk)
        rcu_read_unlock();
 }
 
+/**
+ * afiucv_hs_send() - send a message through HiperSockets transport
+ */
+static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
+                  struct sk_buff *skb, u8 flags)
+{
+       struct net *net = sock_net(sock);
+       struct iucv_sock *iucv = iucv_sk(sock);
+       struct af_iucv_trans_hdr *phs_hdr;
+       struct sk_buff *nskb;
+       int err, confirm_recv = 0;
+
+       memset(skb->head, 0, ETH_HLEN);
+       phs_hdr = (struct af_iucv_trans_hdr *)skb_push(skb,
+                                       sizeof(struct af_iucv_trans_hdr));
+       skb_reset_mac_header(skb);
+       skb_reset_network_header(skb);
+       skb_push(skb, ETH_HLEN);
+       skb_reset_mac_header(skb);
+       memset(phs_hdr, 0, sizeof(struct af_iucv_trans_hdr));
+
+       phs_hdr->magic = ETH_P_AF_IUCV;
+       phs_hdr->version = 1;
+       phs_hdr->flags = flags;
+       if (flags == AF_IUCV_FLAG_SYN)
+               phs_hdr->window = iucv->msglimit;
+       else if ((flags == AF_IUCV_FLAG_WIN) || !flags) {
+               confirm_recv = atomic_read(&iucv->msg_recv);
+               phs_hdr->window = confirm_recv;
+               if (confirm_recv)
+                       phs_hdr->flags = phs_hdr->flags | AF_IUCV_FLAG_WIN;
+       }
+       memcpy(phs_hdr->destUserID, iucv->dst_user_id, 8);
+       memcpy(phs_hdr->destAppName, iucv->dst_name, 8);
+       memcpy(phs_hdr->srcUserID, iucv->src_user_id, 8);
+       memcpy(phs_hdr->srcAppName, iucv->src_name, 8);
+       ASCEBC(phs_hdr->destUserID, sizeof(phs_hdr->destUserID));
+       ASCEBC(phs_hdr->destAppName, sizeof(phs_hdr->destAppName));
+       ASCEBC(phs_hdr->srcUserID, sizeof(phs_hdr->srcUserID));
+       ASCEBC(phs_hdr->srcAppName, sizeof(phs_hdr->srcAppName));
+       if (imsg)
+               memcpy(&phs_hdr->iucv_hdr, imsg, sizeof(struct iucv_message));
+
+       rcu_read_lock();
+       skb->dev = dev_get_by_index_rcu(net, sock->sk_bound_dev_if);
+       rcu_read_unlock();
+       if (!skb->dev)
+               return -ENODEV;
+       if (!(skb->dev->flags & IFF_UP))
+               return -ENETDOWN;
+       if (skb->len > skb->dev->mtu) {
+               if (sock->sk_type == SOCK_SEQPACKET)
+                       return -EMSGSIZE;
+               else
+                       skb_trim(skb, skb->dev->mtu);
+       }
+       skb->protocol = ETH_P_AF_IUCV;
+       skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF;
+       nskb = skb_clone(skb, GFP_ATOMIC);
+       if (!nskb)
+               return -ENOMEM;
+       skb_queue_tail(&iucv->send_skb_q, nskb);
+       err = dev_queue_xmit(skb);
+       if (err) {
+               skb_unlink(nskb, &iucv->send_skb_q);
+               kfree_skb(nskb);
+       } else {
+               atomic_sub(confirm_recv, &iucv->msg_recv);
+               WARN_ON(atomic_read(&iucv->msg_recv) < 0);
+       }
+       return err;
+}
+
 /* Timers */
 static void iucv_sock_timeout(unsigned long arg)
 {
@@ -380,6 +464,8 @@ static void iucv_sock_close(struct sock *sk)
        unsigned char user_data[16];
        struct iucv_sock *iucv = iucv_sk(sk);
        unsigned long timeo;
+       int err, blen;
+       struct sk_buff *skb;
 
        iucv_sock_clear_timer(sk);
        lock_sock(sk);
@@ -390,6 +476,20 @@ static void iucv_sock_close(struct sock *sk)
                break;
 
        case IUCV_CONNECTED:
+               if (iucv->transport == AF_IUCV_TRANS_HIPER) {
+                       /* send fin */
+                       blen = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
+                       skb = sock_alloc_send_skb(sk, blen, 1, &err);
+                       if (skb) {
+                               skb_reserve(skb,
+                                       sizeof(struct af_iucv_trans_hdr) +
+                                       ETH_HLEN);
+                               err = afiucv_hs_send(NULL, sk, skb,
+                                                    AF_IUCV_FLAG_FIN);
+                       }
+                       sk->sk_state = IUCV_DISCONN;
+                       sk->sk_state_change(sk);
+               }
        case IUCV_DISCONN:
                sk->sk_state = IUCV_CLOSING;
                sk->sk_state_change(sk);
@@ -412,7 +512,7 @@ static void iucv_sock_close(struct sock *sk)
                        low_nmcpy(user_data, iucv->src_name);
                        high_nmcpy(user_data, iucv->dst_name);
                        ASCEBC(user_data, sizeof(user_data));
-                       iucv_path_sever(iucv->path, user_data);
+                       pr_iucv->path_sever(iucv->path, user_data);
                        iucv_path_free(iucv->path);
                        iucv->path = NULL;
                }
@@ -444,23 +544,33 @@ static void iucv_sock_init(struct sock *sk, struct sock *parent)
 static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio)
 {
        struct sock *sk;
+       struct iucv_sock *iucv;
 
        sk = sk_alloc(&init_net, PF_IUCV, prio, &iucv_proto);
        if (!sk)
                return NULL;
+       iucv = iucv_sk(sk);
 
        sock_init_data(sock, sk);
-       INIT_LIST_HEAD(&iucv_sk(sk)->accept_q);
-       spin_lock_init(&iucv_sk(sk)->accept_q_lock);
-       skb_queue_head_init(&iucv_sk(sk)->send_skb_q);
-       INIT_LIST_HEAD(&iucv_sk(sk)->message_q.list);
-       spin_lock_init(&iucv_sk(sk)->message_q.lock);
-       skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q);
-       iucv_sk(sk)->send_tag = 0;
-       iucv_sk(sk)->flags = 0;
-       iucv_sk(sk)->msglimit = IUCV_QUEUELEN_DEFAULT;
-       iucv_sk(sk)->path = NULL;
-       memset(&iucv_sk(sk)->src_user_id , 0, 32);
+       INIT_LIST_HEAD(&iucv->accept_q);
+       spin_lock_init(&iucv->accept_q_lock);
+       skb_queue_head_init(&iucv->send_skb_q);
+       INIT_LIST_HEAD(&iucv->message_q.list);
+       spin_lock_init(&iucv->message_q.lock);
+       skb_queue_head_init(&iucv->backlog_skb_q);
+       iucv->send_tag = 0;
+       atomic_set(&iucv->pendings, 0);
+       iucv->flags = 0;
+       iucv->msglimit = 0;
+       atomic_set(&iucv->msg_sent, 0);
+       atomic_set(&iucv->msg_recv, 0);
+       iucv->path = NULL;
+       iucv->sk_txnotify = afiucv_hs_callback_txnotify;
+       memset(&iucv->src_user_id , 0, 32);
+       if (pr_iucv)
+               iucv->transport = AF_IUCV_TRANS_IUCV;
+       else
+               iucv->transport = AF_IUCV_TRANS_HIPER;
 
        sk->sk_destruct = iucv_sock_destruct;
        sk->sk_sndtimeo = IUCV_CONN_TIMEOUT;
@@ -591,7 +701,9 @@ static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr,
        struct sockaddr_iucv *sa = (struct sockaddr_iucv *) addr;
        struct sock *sk = sock->sk;
        struct iucv_sock *iucv;
-       int err;
+       int err = 0;
+       struct net_device *dev;
+       char uid[9];
 
        /* Verify the input sockaddr */
        if (!addr || addr->sa_family != AF_IUCV)
@@ -610,19 +722,46 @@ static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr,
                err = -EADDRINUSE;
                goto done_unlock;
        }
-       if (iucv->path) {
-               err = 0;
+       if (iucv->path)
                goto done_unlock;
-       }
 
        /* Bind the socket */
-       memcpy(iucv->src_name, sa->siucv_name, 8);
 
-       /* Copy the user id */
-       memcpy(iucv->src_user_id, iucv_userid, 8);
-       sk->sk_state = IUCV_BOUND;
-       err = 0;
+       if (pr_iucv)
+               if (!memcmp(sa->siucv_user_id, iucv_userid, 8))
+                       goto vm_bind; /* VM IUCV transport */
 
+       /* try hiper transport */
+       memcpy(uid, sa->siucv_user_id, sizeof(uid));
+       ASCEBC(uid, 8);
+       rcu_read_lock();
+       for_each_netdev_rcu(&init_net, dev) {
+               if (!memcmp(dev->perm_addr, uid, 8)) {
+                       memcpy(iucv->src_name, sa->siucv_name, 8);
+                       memcpy(iucv->src_user_id, sa->siucv_user_id, 8);
+                       sock->sk->sk_bound_dev_if = dev->ifindex;
+                       sk->sk_state = IUCV_BOUND;
+                       iucv->transport = AF_IUCV_TRANS_HIPER;
+                       if (!iucv->msglimit)
+                               iucv->msglimit = IUCV_HIPER_MSGLIM_DEFAULT;
+                       rcu_read_unlock();
+                       goto done_unlock;
+               }
+       }
+       rcu_read_unlock();
+vm_bind:
+       if (pr_iucv) {
+               /* use local userid for backward compat */
+               memcpy(iucv->src_name, sa->siucv_name, 8);
+               memcpy(iucv->src_user_id, iucv_userid, 8);
+               sk->sk_state = IUCV_BOUND;
+               iucv->transport = AF_IUCV_TRANS_IUCV;
+               if (!iucv->msglimit)
+                       iucv->msglimit = IUCV_QUEUELEN_DEFAULT;
+               goto done_unlock;
+       }
+       /* found no dev to bind */
+       err = -ENODEV;
 done_unlock:
        /* Release the socket list lock */
        write_unlock_bh(&iucv_sk_list.lock);
@@ -658,45 +797,44 @@ static int iucv_sock_autobind(struct sock *sk)
 
        memcpy(&iucv->src_name, name, 8);
 
+       if (!iucv->msglimit)
+               iucv->msglimit = IUCV_QUEUELEN_DEFAULT;
+
        return err;
 }
 
-/* Connect an unconnected socket */
-static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
-                            int alen, int flags)
+static int afiucv_hs_connect(struct socket *sock)
 {
-       struct sockaddr_iucv *sa = (struct sockaddr_iucv *) addr;
        struct sock *sk = sock->sk;
-       struct iucv_sock *iucv;
-       unsigned char user_data[16];
-       int err;
-
-       if (addr->sa_family != AF_IUCV || alen < sizeof(struct sockaddr_iucv))
-               return -EINVAL;
-
-       if (sk->sk_state != IUCV_OPEN && sk->sk_state != IUCV_BOUND)
-               return -EBADFD;
-
-       if (sk->sk_type != SOCK_STREAM && sk->sk_type != SOCK_SEQPACKET)
-               return -EINVAL;
+       struct sk_buff *skb;
+       int blen = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
+       int err = 0;
 
-       if (sk->sk_state == IUCV_OPEN) {
-               err = iucv_sock_autobind(sk);
-               if (unlikely(err))
-                       return err;
+       /* send syn */
+       skb = sock_alloc_send_skb(sk, blen, 1, &err);
+       if (!skb) {
+               err = -ENOMEM;
+               goto done;
        }
+       skb->dev = NULL;
+       skb_reserve(skb, blen);
+       err = afiucv_hs_send(NULL, sk, skb, AF_IUCV_FLAG_SYN);
+done:
+       return err;
+}
 
-       lock_sock(sk);
-
-       /* Set the destination information */
-       memcpy(iucv_sk(sk)->dst_user_id, sa->siucv_user_id, 8);
-       memcpy(iucv_sk(sk)->dst_name, sa->siucv_name, 8);
+static int afiucv_path_connect(struct socket *sock, struct sockaddr *addr)
+{
+       struct sockaddr_iucv *sa = (struct sockaddr_iucv *) addr;
+       struct sock *sk = sock->sk;
+       struct iucv_sock *iucv = iucv_sk(sk);
+       unsigned char user_data[16];
+       int err;
 
        high_nmcpy(user_data, sa->siucv_name);
-       low_nmcpy(user_data, iucv_sk(sk)->src_name);
+       low_nmcpy(user_data, iucv->src_name);
        ASCEBC(user_data, sizeof(user_data));
 
-       iucv = iucv_sk(sk);
        /* Create path. */
        iucv->path = iucv_path_alloc(iucv->msglimit,
                                     IUCV_IPRMDATA, GFP_KERNEL);
@@ -704,8 +842,9 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
                err = -ENOMEM;
                goto done;
        }
-       err = iucv_path_connect(iucv->path, &af_iucv_handler,
-                               sa->siucv_user_id, NULL, user_data, sk);
+       err = pr_iucv->path_connect(iucv->path, &af_iucv_handler,
+                                   sa->siucv_user_id, NULL, user_data,
+                                   sk);
        if (err) {
                iucv_path_free(iucv->path);
                iucv->path = NULL;
@@ -724,21 +863,62 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
                        err = -ECONNREFUSED;
                        break;
                }
-               goto done;
        }
+done:
+       return err;
+}
 
-       if (sk->sk_state != IUCV_CONNECTED) {
+/* Connect an unconnected socket */
+static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
+                            int alen, int flags)
+{
+       struct sockaddr_iucv *sa = (struct sockaddr_iucv *) addr;
+       struct sock *sk = sock->sk;
+       struct iucv_sock *iucv = iucv_sk(sk);
+       int err;
+
+       if (addr->sa_family != AF_IUCV || alen < sizeof(struct sockaddr_iucv))
+               return -EINVAL;
+
+       if (sk->sk_state != IUCV_OPEN && sk->sk_state != IUCV_BOUND)
+               return -EBADFD;
+
+       if (sk->sk_state == IUCV_OPEN &&
+           iucv->transport == AF_IUCV_TRANS_HIPER)
+               return -EBADFD; /* explicit bind required */
+
+       if (sk->sk_type != SOCK_STREAM && sk->sk_type != SOCK_SEQPACKET)
+               return -EINVAL;
+
+       if (sk->sk_state == IUCV_OPEN) {
+               err = iucv_sock_autobind(sk);
+               if (unlikely(err))
+                       return err;
+       }
+
+       lock_sock(sk);
+
+       /* Set the destination information */
+       memcpy(iucv->dst_user_id, sa->siucv_user_id, 8);
+       memcpy(iucv->dst_name, sa->siucv_name, 8);
+
+       if (iucv->transport == AF_IUCV_TRANS_HIPER)
+               err = afiucv_hs_connect(sock);
+       else
+               err = afiucv_path_connect(sock, addr);
+       if (err)
+               goto done;
+
+       if (sk->sk_state != IUCV_CONNECTED)
                err = iucv_sock_wait(sk, iucv_sock_in_state(sk, IUCV_CONNECTED,
                                                            IUCV_DISCONN),
                                     sock_sndtimeo(sk, flags & O_NONBLOCK));
-       }
 
-       if (sk->sk_state == IUCV_DISCONN) {
+       if (sk->sk_state == IUCV_DISCONN || sk->sk_state == IUCV_CLOSED)
                err = -ECONNREFUSED;
-       }
 
-       if (err) {
-               iucv_path_sever(iucv->path, NULL);
+       if (err && iucv->transport == AF_IUCV_TRANS_IUCV) {
+               pr_iucv->path_sever(iucv->path, NULL);
                iucv_path_free(iucv->path);
                iucv->path = NULL;
        }
@@ -833,20 +1013,21 @@ static int iucv_sock_getname(struct socket *sock, struct sockaddr *addr,
 {
        struct sockaddr_iucv *siucv = (struct sockaddr_iucv *) addr;
        struct sock *sk = sock->sk;
+       struct iucv_sock *iucv = iucv_sk(sk);
 
        addr->sa_family = AF_IUCV;
        *len = sizeof(struct sockaddr_iucv);
 
        if (peer) {
-               memcpy(siucv->siucv_user_id, iucv_sk(sk)->dst_user_id, 8);
-               memcpy(siucv->siucv_name, &iucv_sk(sk)->dst_name, 8);
+               memcpy(siucv->siucv_user_id, iucv->dst_user_id, 8);
+               memcpy(siucv->siucv_name, iucv->dst_name, 8);
        } else {
-               memcpy(siucv->siucv_user_id, iucv_sk(sk)->src_user_id, 8);
-               memcpy(siucv->siucv_name, iucv_sk(sk)->src_name, 8);
+               memcpy(siucv->siucv_user_id, iucv->src_user_id, 8);
+               memcpy(siucv->siucv_name, iucv->src_name, 8);
        }
        memset(&siucv->siucv_port, 0, sizeof(siucv->siucv_port));
        memset(&siucv->siucv_addr, 0, sizeof(siucv->siucv_addr));
-       memset(siucv->siucv_nodeid, 0, sizeof(siucv->siucv_nodeid));
+       memset(&siucv->siucv_nodeid, 0, sizeof(siucv->siucv_nodeid));
 
        return 0;
 }
@@ -871,7 +1052,7 @@ static int iucv_send_iprm(struct iucv_path *path, struct iucv_message *msg,
 
        memcpy(prmdata, (void *) skb->data, skb->len);
        prmdata[7] = 0xff - (u8) skb->len;
-       return iucv_message_send(path, msg, IUCV_IPRMDATA, 0,
+       return pr_iucv->message_send(path, msg, IUCV_IPRMDATA, 0,
                                 (void *) prmdata, 8);
 }
 
@@ -960,9 +1141,16 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
         * this is fine for SOCK_SEQPACKET (unless we want to support
         * segmented records using the MSG_EOR flag), but
         * for SOCK_STREAM we might want to improve it in future */
-       skb = sock_alloc_send_skb(sk, len, noblock, &err);
+       if (iucv->transport == AF_IUCV_TRANS_HIPER)
+               skb = sock_alloc_send_skb(sk,
+                       len + sizeof(struct af_iucv_trans_hdr) + ETH_HLEN,
+                       noblock, &err);
+       else
+               skb = sock_alloc_send_skb(sk, len, noblock, &err);
        if (!skb)
                goto out;
+       if (iucv->transport == AF_IUCV_TRANS_HIPER)
+               skb_reserve(skb, sizeof(struct af_iucv_trans_hdr) + ETH_HLEN);
        if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
                err = -EFAULT;
                goto fail;
@@ -983,6 +1171,15 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
        /* increment and save iucv message tag for msg_completion cbk */
        txmsg.tag = iucv->send_tag++;
        memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN);
+       if (iucv->transport == AF_IUCV_TRANS_HIPER) {
+               atomic_inc(&iucv->msg_sent);
+               err = afiucv_hs_send(&txmsg, sk, skb, 0);
+               if (err) {
+                       atomic_dec(&iucv->msg_sent);
+                       goto fail;
+               }
+               goto release;
+       }
        skb_queue_tail(&iucv->send_skb_q, skb);
 
        if (((iucv->path->flags & IUCV_IPRMDATA) & iucv->flags)
@@ -999,13 +1196,13 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                /* this error should never happen since the
                 * IUCV_IPRMDATA path flag is set... sever path */
                if (err == 0x15) {
-                       iucv_path_sever(iucv->path, NULL);
+                       pr_iucv->path_sever(iucv->path, NULL);
                        skb_unlink(skb, &iucv->send_skb_q);
                        err = -EPIPE;
                        goto fail;
                }
        } else
-               err = iucv_message_send(iucv->path, &txmsg, 0, 0,
+               err = pr_iucv->message_send(iucv->path, &txmsg, 0, 0,
                                        (void *) skb->data, skb->len);
        if (err) {
                if (err == 3) {
@@ -1023,6 +1220,7 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                goto fail;
        }
 
+release:
        release_sock(sk);
        return len;
 
@@ -1095,8 +1293,9 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
                        skb->len = 0;
                }
        } else {
-               rc = iucv_message_receive(path, msg, msg->flags & IUCV_IPRMDATA,
-                                         skb->data, len, NULL);
+               rc = pr_iucv->message_receive(path, msg,
+                                             msg->flags & IUCV_IPRMDATA,
+                                             skb->data, len, NULL);
                if (rc) {
                        kfree_skb(skb);
                        return;
@@ -1110,7 +1309,7 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
                        kfree_skb(skb);
                        skb = NULL;
                        if (rc) {
-                               iucv_path_sever(path, NULL);
+                               pr_iucv->path_sever(path, NULL);
                                return;
                        }
                        skb = skb_dequeue(&iucv_sk(sk)->backlog_skb_q);
@@ -1154,7 +1353,8 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
        struct sock *sk = sock->sk;
        struct iucv_sock *iucv = iucv_sk(sk);
        unsigned int copied, rlen;
-       struct sk_buff *skb, *rskb, *cskb;
+       struct sk_buff *skb, *rskb, *cskb, *sskb;
+       int blen;
        int err = 0;
 
        if ((sk->sk_state == IUCV_DISCONN || sk->sk_state == IUCV_SEVERED) &&
@@ -1179,7 +1379,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
        copied = min_t(unsigned int, rlen, len);
 
        cskb = skb;
-       if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) {
+       if (skb_copy_datagram_iovec(cskb, 0, msg->msg_iov, copied)) {
                if (!(flags & MSG_PEEK))
                        skb_queue_head(&sk->sk_receive_queue, skb);
                return -EFAULT;
@@ -1217,6 +1417,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                }
 
                kfree_skb(skb);
+               atomic_inc(&iucv->msg_recv);
 
                /* Queue backlog skbs */
                spin_lock_bh(&iucv->message_q.lock);
@@ -1233,6 +1434,24 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                if (skb_queue_empty(&iucv->backlog_skb_q)) {
                        if (!list_empty(&iucv->message_q.list))
                                iucv_process_message_q(sk);
+                       if (atomic_read(&iucv->msg_recv) >=
+                                                       iucv->msglimit / 2) {
+                               /* send WIN to peer */
+                               blen = sizeof(struct af_iucv_trans_hdr) +
+                                       ETH_HLEN;
+                               sskb = sock_alloc_send_skb(sk, blen, 1, &err);
+                               if (sskb) {
+                                       skb_reserve(sskb,
+                                               sizeof(struct af_iucv_trans_hdr)
+                                               + ETH_HLEN);
+                                       err = afiucv_hs_send(NULL, sk, sskb,
+                                                            AF_IUCV_FLAG_WIN);
+                               }
+                               if (err) {
+                                       sk->sk_state = IUCV_DISCONN;
+                                       sk->sk_state_change(sk);
+                               }
+                       }
                }
                spin_unlock_bh(&iucv->message_q.lock);
        }
@@ -1327,8 +1546,8 @@ static int iucv_sock_shutdown(struct socket *sock, int how)
        if (how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) {
                txmsg.class = 0;
                txmsg.tag = 0;
-               err = iucv_message_send(iucv->path, &txmsg, IUCV_IPRMDATA, 0,
-                                       (void *) iprm_shutdown, 8);
+               err = pr_iucv->message_send(iucv->path, &txmsg, IUCV_IPRMDATA,
+                                       0, (void *) iprm_shutdown, 8);
                if (err) {
                        switch (err) {
                        case 1:
@@ -1345,7 +1564,7 @@ static int iucv_sock_shutdown(struct socket *sock, int how)
        }
 
        if (how == RCV_SHUTDOWN || how == SHUTDOWN_MASK) {
-               err = iucv_path_quiesce(iucv_sk(sk)->path, NULL);
+               err = pr_iucv->path_quiesce(iucv->path, NULL);
                if (err)
                        err = -ENOTCONN;
 
@@ -1372,7 +1591,7 @@ static int iucv_sock_release(struct socket *sock)
 
        /* Unregister with IUCV base support */
        if (iucv_sk(sk)->path) {
-               iucv_path_sever(iucv_sk(sk)->path, NULL);
+               pr_iucv->path_sever(iucv_sk(sk)->path, NULL);
                iucv_path_free(iucv_sk(sk)->path);
                iucv_sk(sk)->path = NULL;
        }
@@ -1514,14 +1733,14 @@ static int iucv_callback_connreq(struct iucv_path *path,
        high_nmcpy(user_data, iucv->dst_name);
        ASCEBC(user_data, sizeof(user_data));
        if (sk->sk_state != IUCV_LISTEN) {
-               err = iucv_path_sever(path, user_data);
+               err = pr_iucv->path_sever(path, user_data);
                iucv_path_free(path);
                goto fail;
        }
 
        /* Check for backlog size */
        if (sk_acceptq_is_full(sk)) {
-               err = iucv_path_sever(path, user_data);
+               err = pr_iucv->path_sever(path, user_data);
                iucv_path_free(path);
                goto fail;
        }
@@ -1529,7 +1748,7 @@ static int iucv_callback_connreq(struct iucv_path *path,
        /* Create the new socket */
        nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC);
        if (!nsk) {
-               err = iucv_path_sever(path, user_data);
+               err = pr_iucv->path_sever(path, user_data);
                iucv_path_free(path);
                goto fail;
        }
@@ -1553,9 +1772,9 @@ static int iucv_callback_connreq(struct iucv_path *path,
        /* set message limit for path based on msglimit of accepting socket */
        niucv->msglimit = iucv->msglimit;
        path->msglim = iucv->msglimit;
-       err = iucv_path_accept(path, &af_iucv_handler, nuser_data, nsk);
+       err = pr_iucv->path_accept(path, &af_iucv_handler, nuser_data, nsk);
        if (err) {
-               err = iucv_path_sever(path, user_data);
+               err = pr_iucv->path_sever(path, user_data);
                iucv_path_free(path);
                iucv_sock_kill(nsk);
                goto fail;
@@ -1589,7 +1808,7 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg)
        int len;
 
        if (sk->sk_shutdown & RCV_SHUTDOWN) {
-               iucv_message_reject(path, msg);
+               pr_iucv->message_reject(path, msg);
                return;
        }
 
@@ -1692,6 +1911,389 @@ static void iucv_callback_shutdown(struct iucv_path *path, u8 ipuser[16])
        bh_unlock_sock(sk);
 }
 
+/***************** HiperSockets transport callbacks ********************/
+static void afiucv_swap_src_dest(struct sk_buff *skb)
+{
+       struct af_iucv_trans_hdr *trans_hdr =
+                               (struct af_iucv_trans_hdr *)skb->data;
+       char tmpID[8];
+       char tmpName[8];
+
+       ASCEBC(trans_hdr->destUserID, sizeof(trans_hdr->destUserID));
+       ASCEBC(trans_hdr->destAppName, sizeof(trans_hdr->destAppName));
+       ASCEBC(trans_hdr->srcUserID, sizeof(trans_hdr->srcUserID));
+       ASCEBC(trans_hdr->srcAppName, sizeof(trans_hdr->srcAppName));
+       memcpy(tmpID, trans_hdr->srcUserID, 8);
+       memcpy(tmpName, trans_hdr->srcAppName, 8);
+       memcpy(trans_hdr->srcUserID, trans_hdr->destUserID, 8);
+       memcpy(trans_hdr->srcAppName, trans_hdr->destAppName, 8);
+       memcpy(trans_hdr->destUserID, tmpID, 8);
+       memcpy(trans_hdr->destAppName, tmpName, 8);
+       skb_push(skb, ETH_HLEN);
+       memset(skb->data, 0, ETH_HLEN);
+}
+
+/**
+ * afiucv_hs_callback_syn - react on received SYN
+ **/
+static int afiucv_hs_callback_syn(struct sock *sk, struct sk_buff *skb)
+{
+       struct sock *nsk;
+       struct iucv_sock *iucv, *niucv;
+       struct af_iucv_trans_hdr *trans_hdr;
+       int err;
+
+       iucv = iucv_sk(sk);
+       trans_hdr = (struct af_iucv_trans_hdr *)skb->data;
+       if (!iucv) {
+               /* no sock - connection refused */
+               afiucv_swap_src_dest(skb);
+               trans_hdr->flags = AF_IUCV_FLAG_SYN | AF_IUCV_FLAG_FIN;
+               err = dev_queue_xmit(skb);
+               goto out;
+       }
+
+       nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC);
+       bh_lock_sock(sk);
+       if ((sk->sk_state != IUCV_LISTEN) ||
+           sk_acceptq_is_full(sk) ||
+           !nsk) {
+               /* error on server socket - connection refused */
+               if (nsk)
+                       sk_free(nsk);
+               afiucv_swap_src_dest(skb);
+               trans_hdr->flags = AF_IUCV_FLAG_SYN | AF_IUCV_FLAG_FIN;
+               err = dev_queue_xmit(skb);
+               bh_unlock_sock(sk);
+               goto out;
+       }
+
+       niucv = iucv_sk(nsk);
+       iucv_sock_init(nsk, sk);
+       niucv->transport = AF_IUCV_TRANS_HIPER;
+       niucv->msglimit = iucv->msglimit;
+       if (!trans_hdr->window)
+               niucv->msglimit_peer = IUCV_HIPER_MSGLIM_DEFAULT;
+       else
+               niucv->msglimit_peer = trans_hdr->window;
+       memcpy(niucv->dst_name, trans_hdr->srcAppName, 8);
+       memcpy(niucv->dst_user_id, trans_hdr->srcUserID, 8);
+       memcpy(niucv->src_name, iucv->src_name, 8);
+       memcpy(niucv->src_user_id, iucv->src_user_id, 8);
+       nsk->sk_bound_dev_if = sk->sk_bound_dev_if;
+       afiucv_swap_src_dest(skb);
+       trans_hdr->flags = AF_IUCV_FLAG_SYN | AF_IUCV_FLAG_ACK;
+       trans_hdr->window = niucv->msglimit;
+       /* if receiver acks the xmit connection is established */
+       err = dev_queue_xmit(skb);
+       if (!err) {
+               iucv_accept_enqueue(sk, nsk);
+               nsk->sk_state = IUCV_CONNECTED;
+               sk->sk_data_ready(sk, 1);
+       } else
+               iucv_sock_kill(nsk);
+       bh_unlock_sock(sk);
+
+out:
+       return NET_RX_SUCCESS;
+}
+
+/**
+ * afiucv_hs_callback_synack() - react on received SYN-ACK
+ **/
+static int afiucv_hs_callback_synack(struct sock *sk, struct sk_buff *skb)
+{
+       struct iucv_sock *iucv = iucv_sk(sk);
+       struct af_iucv_trans_hdr *trans_hdr =
+                                       (struct af_iucv_trans_hdr *)skb->data;
+
+       if (!iucv)
+               goto out;
+       if (sk->sk_state != IUCV_BOUND)
+               goto out;
+       bh_lock_sock(sk);
+       iucv->msglimit_peer = trans_hdr->window;
+       sk->sk_state = IUCV_CONNECTED;
+       sk->sk_state_change(sk);
+       bh_unlock_sock(sk);
+out:
+       kfree_skb(skb);
+       return NET_RX_SUCCESS;
+}
+
+/**
+ * afiucv_hs_callback_synfin() - react on received SYN_FIN
+ **/
+static int afiucv_hs_callback_synfin(struct sock *sk, struct sk_buff *skb)
+{
+       struct iucv_sock *iucv = iucv_sk(sk);
+
+       if (!iucv)
+               goto out;
+       if (sk->sk_state != IUCV_BOUND)
+               goto out;
+       bh_lock_sock(sk);
+       sk->sk_state = IUCV_DISCONN;
+       sk->sk_state_change(sk);
+       bh_unlock_sock(sk);
+out:
+       kfree_skb(skb);
+       return NET_RX_SUCCESS;
+}
+
+/**
+ * afiucv_hs_callback_fin() - react on received FIN
+ **/
+static int afiucv_hs_callback_fin(struct sock *sk, struct sk_buff *skb)
+{
+       struct iucv_sock *iucv = iucv_sk(sk);
+
+       /* other end of connection closed */
+       if (iucv) {
+               bh_lock_sock(sk);
+               if (!list_empty(&iucv->accept_q))
+                       sk->sk_state = IUCV_SEVERED;
+               else
+                       sk->sk_state = IUCV_DISCONN;
+               sk->sk_state_change(sk);
+               bh_unlock_sock(sk);
+       }
+       kfree_skb(skb);
+       return NET_RX_SUCCESS;
+}
+
+/**
+ * afiucv_hs_callback_win() - react on received WIN
+ **/
+static int afiucv_hs_callback_win(struct sock *sk, struct sk_buff *skb)
+{
+       struct iucv_sock *iucv = iucv_sk(sk);
+       struct af_iucv_trans_hdr *trans_hdr =
+                                       (struct af_iucv_trans_hdr *)skb->data;
+
+       if (!iucv)
+               return NET_RX_SUCCESS;
+
+       if (sk->sk_state != IUCV_CONNECTED)
+               return NET_RX_SUCCESS;
+
+       atomic_sub(trans_hdr->window, &iucv->msg_sent);
+       iucv_sock_wake_msglim(sk);
+       return NET_RX_SUCCESS;
+}
+
+/**
+ * afiucv_hs_callback_rx() - react on received data
+ **/
+static int afiucv_hs_callback_rx(struct sock *sk, struct sk_buff *skb)
+{
+       struct iucv_sock *iucv = iucv_sk(sk);
+
+       if (!iucv) {
+               kfree_skb(skb);
+               return NET_RX_SUCCESS;
+       }
+
+       if (sk->sk_state != IUCV_CONNECTED) {
+               kfree_skb(skb);
+               return NET_RX_SUCCESS;
+       }
+
+               /* write stuff from iucv_msg to skb cb */
+       if (skb->len <= sizeof(struct af_iucv_trans_hdr)) {
+               kfree_skb(skb);
+               return NET_RX_SUCCESS;
+       }
+       skb_pull(skb, sizeof(struct af_iucv_trans_hdr));
+       skb_reset_transport_header(skb);
+       skb_reset_network_header(skb);
+       spin_lock(&iucv->message_q.lock);
+       if (skb_queue_empty(&iucv->backlog_skb_q)) {
+               if (sock_queue_rcv_skb(sk, skb)) {
+                       /* handle rcv queue full */
+                       skb_queue_tail(&iucv->backlog_skb_q, skb);
+               }
+       } else
+               skb_queue_tail(&iucv_sk(sk)->backlog_skb_q, skb);
+       spin_unlock(&iucv->message_q.lock);
+       return NET_RX_SUCCESS;
+}
+
+/**
+ * afiucv_hs_rcv() - base function for arriving data through HiperSockets
+ *                   transport
+ *                   called from netif RX softirq
+ **/
+static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
+       struct packet_type *pt, struct net_device *orig_dev)
+{
+       struct hlist_node *node;
+       struct sock *sk;
+       struct iucv_sock *iucv;
+       struct af_iucv_trans_hdr *trans_hdr;
+       char nullstring[8];
+       int err = 0;
+
+       skb_pull(skb, ETH_HLEN);
+       trans_hdr = (struct af_iucv_trans_hdr *)skb->data;
+       EBCASC(trans_hdr->destAppName, sizeof(trans_hdr->destAppName));
+       EBCASC(trans_hdr->destUserID, sizeof(trans_hdr->destUserID));
+       EBCASC(trans_hdr->srcAppName, sizeof(trans_hdr->srcAppName));
+       EBCASC(trans_hdr->srcUserID, sizeof(trans_hdr->srcUserID));
+       memset(nullstring, 0, sizeof(nullstring));
+       iucv = NULL;
+       sk = NULL;
+       read_lock(&iucv_sk_list.lock);
+       sk_for_each(sk, node, &iucv_sk_list.head) {
+               if (trans_hdr->flags == AF_IUCV_FLAG_SYN) {
+                       if ((!memcmp(&iucv_sk(sk)->src_name,
+                                    trans_hdr->destAppName, 8)) &&
+                           (!memcmp(&iucv_sk(sk)->src_user_id,
+                                    trans_hdr->destUserID, 8)) &&
+                           (!memcmp(&iucv_sk(sk)->dst_name, nullstring, 8)) &&
+                           (!memcmp(&iucv_sk(sk)->dst_user_id,
+                                    nullstring, 8))) {
+                               iucv = iucv_sk(sk);
+                               break;
+                       }
+               } else {
+                       if ((!memcmp(&iucv_sk(sk)->src_name,
+                                    trans_hdr->destAppName, 8)) &&
+                           (!memcmp(&iucv_sk(sk)->src_user_id,
+                                    trans_hdr->destUserID, 8)) &&
+                           (!memcmp(&iucv_sk(sk)->dst_name,
+                                    trans_hdr->srcAppName, 8)) &&
+                           (!memcmp(&iucv_sk(sk)->dst_user_id,
+                                    trans_hdr->srcUserID, 8))) {
+                               iucv = iucv_sk(sk);
+                               break;
+                       }
+               }
+       }
+       read_unlock(&iucv_sk_list.lock);
+       if (!iucv)
+               sk = NULL;
+
+       /* no sock
+       how should we send with no sock
+       1) send without sock no send rc checking?
+       2) introduce default sock to handle this cases
+
+        SYN -> send SYN|ACK in good case, send SYN|FIN in bad case
+        data -> send FIN
+        SYN|ACK, SYN|FIN, FIN -> no action? */
+
+       switch (trans_hdr->flags) {
+       case AF_IUCV_FLAG_SYN:
+               /* connect request */
+               err = afiucv_hs_callback_syn(sk, skb);
+               break;
+       case (AF_IUCV_FLAG_SYN | AF_IUCV_FLAG_ACK):
+               /* connect request confirmed */
+               err = afiucv_hs_callback_synack(sk, skb);
+               break;
+       case (AF_IUCV_FLAG_SYN | AF_IUCV_FLAG_FIN):
+               /* connect request refused */
+               err = afiucv_hs_callback_synfin(sk, skb);
+               break;
+       case (AF_IUCV_FLAG_FIN):
+               /* close request */
+               err = afiucv_hs_callback_fin(sk, skb);
+               break;
+       case (AF_IUCV_FLAG_WIN):
+               err = afiucv_hs_callback_win(sk, skb);
+               if (skb->len > sizeof(struct af_iucv_trans_hdr))
+                       err = afiucv_hs_callback_rx(sk, skb);
+               else
+                       kfree(skb);
+               break;
+       case 0:
+               /* plain data frame */
+               err = afiucv_hs_callback_rx(sk, skb);
+               break;
+       default:
+               ;
+       }
+
+       return err;
+}
+
+/**
+ * afiucv_hs_callback_txnotify() - handle send notifcations from HiperSockets
+ *                                 transport
+ **/
+static void afiucv_hs_callback_txnotify(struct sk_buff *skb,
+                                       enum iucv_tx_notify n)
+{
+       struct sock *isk = skb->sk;
+       struct sock *sk = NULL;
+       struct iucv_sock *iucv = NULL;
+       struct sk_buff_head *list;
+       struct sk_buff *list_skb;
+       struct sk_buff *this = NULL;
+       unsigned long flags;
+       struct hlist_node *node;
+
+       read_lock(&iucv_sk_list.lock);
+       sk_for_each(sk, node, &iucv_sk_list.head)
+               if (sk == isk) {
+                       iucv = iucv_sk(sk);
+                       break;
+               }
+       read_unlock(&iucv_sk_list.lock);
+
+       if (!iucv)
+               return;
+
+       bh_lock_sock(sk);
+       list = &iucv->send_skb_q;
+       list_skb = list->next;
+       if (skb_queue_empty(list))
+               goto out_unlock;
+
+       spin_lock_irqsave(&list->lock, flags);
+       while (list_skb != (struct sk_buff *)list) {
+               if (skb_shinfo(list_skb) == skb_shinfo(skb)) {
+                       this = list_skb;
+                       switch (n) {
+                       case TX_NOTIFY_OK:
+                               __skb_unlink(this, list);
+                               iucv_sock_wake_msglim(sk);
+                               kfree_skb(this);
+                               break;
+                       case TX_NOTIFY_PENDING:
+                               atomic_inc(&iucv->pendings);
+                               break;
+                       case TX_NOTIFY_DELAYED_OK:
+                               __skb_unlink(this, list);
+                               atomic_dec(&iucv->pendings);
+                               if (atomic_read(&iucv->pendings) <= 0)
+                                       iucv_sock_wake_msglim(sk);
+                               kfree_skb(this);
+                               break;
+                       case TX_NOTIFY_UNREACHABLE:
+                       case TX_NOTIFY_DELAYED_UNREACHABLE:
+                       case TX_NOTIFY_TPQFULL: /* not yet used */
+                       case TX_NOTIFY_GENERALERROR:
+                       case TX_NOTIFY_DELAYED_GENERALERROR:
+                               __skb_unlink(this, list);
+                               kfree_skb(this);
+                               if (!list_empty(&iucv->accept_q))
+                                       sk->sk_state = IUCV_SEVERED;
+                               else
+                                       sk->sk_state = IUCV_DISCONN;
+                               sk->sk_state_change(sk);
+                               break;
+                       }
+                       break;
+               }
+               list_skb = list_skb->next;
+       }
+       spin_unlock_irqrestore(&list->lock, flags);
+
+out_unlock:
+       bh_unlock_sock(sk);
+}
 static const struct proto_ops iucv_sock_ops = {
        .family         = PF_IUCV,
        .owner          = THIS_MODULE,
@@ -1718,71 +2320,104 @@ static const struct net_proto_family iucv_sock_family_ops = {
        .create = iucv_sock_create,
 };
 
-static int __init afiucv_init(void)
+static struct packet_type iucv_packet_type = {
+       .type = cpu_to_be16(ETH_P_AF_IUCV),
+       .func = afiucv_hs_rcv,
+};
+
+static int afiucv_iucv_init(void)
 {
        int err;
 
-       if (!MACHINE_IS_VM) {
-               pr_err("The af_iucv module cannot be loaded"
-                      " without z/VM\n");
-               err = -EPROTONOSUPPORT;
-               goto out;
-       }
-       cpcmd("QUERY USERID", iucv_userid, sizeof(iucv_userid), &err);
-       if (unlikely(err)) {
-               WARN_ON(err);
-               err = -EPROTONOSUPPORT;
-               goto out;
-       }
-
-       err = iucv_register(&af_iucv_handler, 0);
+       err = pr_iucv->iucv_register(&af_iucv_handler, 0);
        if (err)
                goto out;
-       err = proto_register(&iucv_proto, 0);
-       if (err)
-               goto out_iucv;
-       err = sock_register(&iucv_sock_family_ops);
-       if (err)
-               goto out_proto;
        /* establish dummy device */
+       af_iucv_driver.bus = pr_iucv->bus;
        err = driver_register(&af_iucv_driver);
        if (err)
-               goto out_sock;
+               goto out_iucv;
        af_iucv_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
        if (!af_iucv_dev) {
                err = -ENOMEM;
                goto out_driver;
        }
        dev_set_name(af_iucv_dev, "af_iucv");
-       af_iucv_dev->bus = &iucv_bus;
-       af_iucv_dev->parent = iucv_root;
+       af_iucv_dev->bus = pr_iucv->bus;
+       af_iucv_dev->parent = pr_iucv->root;
        af_iucv_dev->release = (void (*)(struct device *))kfree;
        af_iucv_dev->driver = &af_iucv_driver;
        err = device_register(af_iucv_dev);
        if (err)
                goto out_driver;
-
        return 0;
 
 out_driver:
        driver_unregister(&af_iucv_driver);
+out_iucv:
+       pr_iucv->iucv_unregister(&af_iucv_handler, 0);
+out:
+       return err;
+}
+
+static int __init afiucv_init(void)
+{
+       int err;
+
+       if (MACHINE_IS_VM) {
+               cpcmd("QUERY USERID", iucv_userid, sizeof(iucv_userid), &err);
+               if (unlikely(err)) {
+                       WARN_ON(err);
+                       err = -EPROTONOSUPPORT;
+                       goto out;
+               }
+
+               pr_iucv = try_then_request_module(symbol_get(iucv_if), "iucv");
+               if (!pr_iucv) {
+                       printk(KERN_WARNING "iucv_if lookup failed\n");
+                       memset(&iucv_userid, 0, sizeof(iucv_userid));
+               }
+       } else {
+               memset(&iucv_userid, 0, sizeof(iucv_userid));
+               pr_iucv = NULL;
+       }
+
+       err = proto_register(&iucv_proto, 0);
+       if (err)
+               goto out;
+       err = sock_register(&iucv_sock_family_ops);
+       if (err)
+               goto out_proto;
+
+       if (pr_iucv) {
+               err = afiucv_iucv_init();
+               if (err)
+                       goto out_sock;
+       }
+       dev_add_pack(&iucv_packet_type);
+       return 0;
+
 out_sock:
        sock_unregister(PF_IUCV);
 out_proto:
        proto_unregister(&iucv_proto);
-out_iucv:
-       iucv_unregister(&af_iucv_handler, 0);
 out:
+       if (pr_iucv)
+               symbol_put(iucv_if);
        return err;
 }
 
 static void __exit afiucv_exit(void)
 {
-       device_unregister(af_iucv_dev);
-       driver_unregister(&af_iucv_driver);
+       if (pr_iucv) {
+               device_unregister(af_iucv_dev);
+               driver_unregister(&af_iucv_driver);
+               pr_iucv->iucv_unregister(&af_iucv_handler, 0);
+               symbol_put(iucv_if);
+       }
+       dev_remove_pack(&iucv_packet_type);
        sock_unregister(PF_IUCV);
        proto_unregister(&iucv_proto);
-       iucv_unregister(&af_iucv_handler, 0);
 }
 
 module_init(afiucv_init);
@@ -1793,3 +2428,4 @@ MODULE_DESCRIPTION("IUCV Sockets ver " VERSION);
 MODULE_VERSION(VERSION);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NETPROTO(PF_IUCV);
+
index 075a380..403be43 100644 (file)
@@ -1974,6 +1974,27 @@ out:
        return rc;
 }
 
+struct iucv_interface iucv_if = {
+       .message_receive = iucv_message_receive,
+       .__message_receive = __iucv_message_receive,
+       .message_reply = iucv_message_reply,
+       .message_reject = iucv_message_reject,
+       .message_send = iucv_message_send,
+       .__message_send = __iucv_message_send,
+       .message_send2way = iucv_message_send2way,
+       .message_purge = iucv_message_purge,
+       .path_accept = iucv_path_accept,
+       .path_connect = iucv_path_connect,
+       .path_quiesce = iucv_path_quiesce,
+       .path_resume = iucv_path_resume,
+       .path_sever = iucv_path_sever,
+       .iucv_register = iucv_register,
+       .iucv_unregister = iucv_unregister,
+       .bus = NULL,
+       .root = NULL,
+};
+EXPORT_SYMBOL(iucv_if);
+
 /**
  * iucv_init
  *
@@ -2038,6 +2059,8 @@ static int __init iucv_init(void)
        rc = bus_register(&iucv_bus);
        if (rc)
                goto out_reboot;
+       iucv_if.root = iucv_root;
+       iucv_if.bus = &iucv_bus;
        return 0;
 
 out_reboot:
index fd1aaf2..9b5bd8c 100644 (file)
@@ -69,7 +69,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
        if (!tid_rx)
                return;
 
-       rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], NULL);
+       RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL);
 
 #ifdef CONFIG_MAC80211_HT_DEBUG
        printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n",
@@ -340,7 +340,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
        status = WLAN_STATUS_SUCCESS;
 
        /* activate it for RX */
-       rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx);
+       RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx);
 
        if (timeout)
                mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout));
index 0baaaec..4baa03b 100644 (file)
@@ -62,7 +62,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
 
        if (type == NL80211_IFTYPE_AP_VLAN &&
            params && params->use_4addr == 0)
-               rcu_assign_pointer(sdata->u.vlan.sta, NULL);
+               RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
        else if (type == NL80211_IFTYPE_STATION &&
                 params && params->use_4addr >= 0)
                sdata->u.mgd.use_4addr = params->use_4addr;
@@ -542,7 +542,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
 
        sdata->vif.bss_conf.dtim_period = new->dtim_period;
 
-       rcu_assign_pointer(sdata->u.ap.beacon, new);
+       RCU_INIT_POINTER(sdata->u.ap.beacon, new);
 
        synchronize_rcu();
 
@@ -594,7 +594,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
        if (!old)
                return -ENOENT;
 
-       rcu_assign_pointer(sdata->u.ap.beacon, NULL);
+       RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
        synchronize_rcu();
        kfree(old);
 
@@ -860,7 +860,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
                                return -EBUSY;
                        }
 
-                       rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
+                       RCU_INIT_POINTER(vlansdata->u.vlan.sta, sta);
                }
 
                sta->sdata = vlansdata;
index 56c24ca..4f9235b 100644 (file)
@@ -84,7 +84,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        drv_reset_tsf(local);
 
        skb = ifibss->skb;
-       rcu_assign_pointer(ifibss->presp, NULL);
+       RCU_INIT_POINTER(ifibss->presp, NULL);
        synchronize_rcu();
        skb->data = skb->head;
        skb->len = 0;
@@ -184,7 +184,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
                *pos++ = 0; /* U-APSD no in use */
        }
 
-       rcu_assign_pointer(ifibss->presp, skb);
+       RCU_INIT_POINTER(ifibss->presp, skb);
 
        sdata->vif.bss_conf.beacon_int = beacon_int;
        sdata->vif.bss_conf.basic_rates = basic_rates;
@@ -995,7 +995,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
        kfree(sdata->u.ibss.ie);
        skb = rcu_dereference_protected(sdata->u.ibss.presp,
                                        lockdep_is_held(&sdata->u.ibss.mtx));
-       rcu_assign_pointer(sdata->u.ibss.presp, NULL);
+       RCU_INIT_POINTER(sdata->u.ibss.presp, NULL);
        sdata->vif.bss_conf.ibss_joined = false;
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
                                                BSS_CHANGED_IBSS);
index 556e7e6..d10dc4d 100644 (file)
@@ -456,7 +456,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                                                 BSS_CHANGED_BEACON_ENABLED);
 
                /* remove beacon */
-               rcu_assign_pointer(sdata->u.ap.beacon, NULL);
+               RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
                synchronize_rcu();
                kfree(old_beacon);
 
@@ -645,7 +645,7 @@ static const struct net_device_ops ieee80211_dataif_ops = {
        .ndo_stop               = ieee80211_stop,
        .ndo_uninit             = ieee80211_teardown_sdata,
        .ndo_start_xmit         = ieee80211_subif_start_xmit,
-       .ndo_set_multicast_list = ieee80211_set_multicast_list,
+       .ndo_set_rx_mode        = ieee80211_set_multicast_list,
        .ndo_change_mtu         = ieee80211_change_mtu,
        .ndo_set_mac_address    = ieee80211_change_mac,
        .ndo_select_queue       = ieee80211_netdev_select_queue,
@@ -689,7 +689,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
        .ndo_stop               = ieee80211_stop,
        .ndo_uninit             = ieee80211_teardown_sdata,
        .ndo_start_xmit         = ieee80211_monitor_start_xmit,
-       .ndo_set_multicast_list = ieee80211_set_multicast_list,
+       .ndo_set_rx_mode        = ieee80211_set_multicast_list,
        .ndo_change_mtu         = ieee80211_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_select_queue       = ieee80211_monitor_select_queue,
index 3c2bcb2..7fde321 100644 (file)
@@ -1132,6 +1132,6 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
 void mesh_pathtbl_unregister(void)
 {
        /* no need for locking during exit path */
-       mesh_table_free(rcu_dereference_raw(mesh_paths), true);
-       mesh_table_free(rcu_dereference_raw(mpp_paths), true);
+       mesh_table_free(rcu_dereference_protected(mesh_paths, 1), true);
+       mesh_table_free(rcu_dereference_protected(mpp_paths, 1), true);
 }
index 17caba2..6bc17fb 100644 (file)
@@ -72,7 +72,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
        if (!s)
                return -ENOENT;
        if (s == sta) {
-               rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)],
+               RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)],
                                   s->hnext);
                return 0;
        }
@@ -82,7 +82,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
                s = rcu_dereference_protected(s->hnext,
                                        lockdep_is_held(&local->sta_lock));
        if (rcu_access_pointer(s->hnext)) {
-               rcu_assign_pointer(s->hnext, sta->hnext);
+               RCU_INIT_POINTER(s->hnext, sta->hnext);
                return 0;
        }
 
@@ -231,7 +231,7 @@ static void sta_info_hash_add(struct ieee80211_local *local,
                              struct sta_info *sta)
 {
        sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)];
-       rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
+       RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
 }
 
 static void sta_unblock(struct work_struct *wk)
@@ -803,7 +803,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
        local->sta_generation++;
 
        if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-               rcu_assign_pointer(sdata->u.vlan.sta, NULL);
+               RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
 
        if (sta->uploaded) {
                if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
index 899b71c..3346829 100644 (file)
@@ -37,7 +37,7 @@ int nf_register_afinfo(const struct nf_afinfo *afinfo)
        err = mutex_lock_interruptible(&afinfo_mutex);
        if (err < 0)
                return err;
-       rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo);
+       RCU_INIT_POINTER(nf_afinfo[afinfo->family], afinfo);
        mutex_unlock(&afinfo_mutex);
        return 0;
 }
@@ -46,7 +46,7 @@ EXPORT_SYMBOL_GPL(nf_register_afinfo);
 void nf_unregister_afinfo(const struct nf_afinfo *afinfo)
 {
        mutex_lock(&afinfo_mutex);
-       rcu_assign_pointer(nf_afinfo[afinfo->family], NULL);
+       RCU_INIT_POINTER(nf_afinfo[afinfo->family], NULL);
        mutex_unlock(&afinfo_mutex);
        synchronize_rcu();
 }
index be43fd8..2b771dc 100644 (file)
@@ -3771,6 +3771,7 @@ err_sock:
 void ip_vs_control_cleanup(void)
 {
        EnterFunction(2);
+       unregister_netdevice_notifier(&ip_vs_dst_notifier);
        ip_vs_genl_unregister();
        nf_unregister_sockopt(&ip_vs_sockopts);
        LeaveFunction(2);
index f7af8b8..5acfaf5 100644 (file)
@@ -779,7 +779,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
                if (exp->helper) {
                        help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
                        if (help)
-                               rcu_assign_pointer(help->helper, exp->helper);
+                               RCU_INIT_POINTER(help->helper, exp->helper);
                }
 
 #ifdef CONFIG_NF_CONNTRACK_MARK
@@ -1317,7 +1317,7 @@ static void nf_conntrack_cleanup_net(struct net *net)
 void nf_conntrack_cleanup(struct net *net)
 {
        if (net_eq(net, &init_net))
-               rcu_assign_pointer(ip_ct_attach, NULL);
+               RCU_INIT_POINTER(ip_ct_attach, NULL);
 
        /* This makes sure all current packets have passed through
           netfilter framework.  Roll on, two-stage module
@@ -1327,7 +1327,7 @@ void nf_conntrack_cleanup(struct net *net)
        nf_conntrack_cleanup_net(net);
 
        if (net_eq(net, &init_net)) {
-               rcu_assign_pointer(nf_ct_destroy, NULL);
+               RCU_INIT_POINTER(nf_ct_destroy, NULL);
                nf_conntrack_cleanup_init_net();
        }
 }
@@ -1576,11 +1576,11 @@ int nf_conntrack_init(struct net *net)
 
        if (net_eq(net, &init_net)) {
                /* For use by REJECT target */
-               rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
-               rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
+               RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach);
+               RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack);
 
                /* Howto get NAT offsets */
-               rcu_assign_pointer(nf_ct_nat_offset, NULL);
+               RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
        }
        return 0;
 
index 63a1b91..3add994 100644 (file)
@@ -94,7 +94,7 @@ int nf_conntrack_register_notifier(struct nf_ct_event_notifier *new)
                ret = -EBUSY;
                goto out_unlock;
        }
-       rcu_assign_pointer(nf_conntrack_event_cb, new);
+       RCU_INIT_POINTER(nf_conntrack_event_cb, new);
        mutex_unlock(&nf_ct_ecache_mutex);
        return ret;
 
@@ -112,7 +112,7 @@ void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *new)
        notify = rcu_dereference_protected(nf_conntrack_event_cb,
                                           lockdep_is_held(&nf_ct_ecache_mutex));
        BUG_ON(notify != new);
-       rcu_assign_pointer(nf_conntrack_event_cb, NULL);
+       RCU_INIT_POINTER(nf_conntrack_event_cb, NULL);
        mutex_unlock(&nf_ct_ecache_mutex);
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
@@ -129,7 +129,7 @@ int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *new)
                ret = -EBUSY;
                goto out_unlock;
        }
-       rcu_assign_pointer(nf_expect_event_cb, new);
+       RCU_INIT_POINTER(nf_expect_event_cb, new);
        mutex_unlock(&nf_ct_ecache_mutex);
        return ret;
 
@@ -147,7 +147,7 @@ void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *new)
        notify = rcu_dereference_protected(nf_expect_event_cb,
                                           lockdep_is_held(&nf_ct_ecache_mutex));
        BUG_ON(notify != new);
-       rcu_assign_pointer(nf_expect_event_cb, NULL);
+       RCU_INIT_POINTER(nf_expect_event_cb, NULL);
        mutex_unlock(&nf_ct_ecache_mutex);
 }
 EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier);
index 05ecdc2..4605c94 100644 (file)
@@ -169,7 +169,7 @@ int nf_ct_extend_register(struct nf_ct_ext_type *type)
           before updating alloc_size */
        type->alloc_size = ALIGN(sizeof(struct nf_ct_ext), type->align)
                           + type->len;
-       rcu_assign_pointer(nf_ct_ext_types[type->id], type);
+       RCU_INIT_POINTER(nf_ct_ext_types[type->id], type);
        update_alloc_size(type);
 out:
        mutex_unlock(&nf_ct_ext_type_mutex);
@@ -181,7 +181,7 @@ EXPORT_SYMBOL_GPL(nf_ct_extend_register);
 void nf_ct_extend_unregister(struct nf_ct_ext_type *type)
 {
        mutex_lock(&nf_ct_ext_type_mutex);
-       rcu_assign_pointer(nf_ct_ext_types[type->id], NULL);
+       RCU_INIT_POINTER(nf_ct_ext_types[type->id], NULL);
        update_alloc_size(type);
        mutex_unlock(&nf_ct_ext_type_mutex);
        rcu_barrier(); /* Wait for completion of call_rcu()'s */
index 1bdfea3..93c4bdb 100644 (file)
@@ -131,7 +131,7 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
                helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
        if (helper == NULL) {
                if (help)
-                       rcu_assign_pointer(help->helper, NULL);
+                       RCU_INIT_POINTER(help->helper, NULL);
                goto out;
        }
 
@@ -145,7 +145,7 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
                memset(&help->help, 0, sizeof(help->help));
        }
 
-       rcu_assign_pointer(help->helper, helper);
+       RCU_INIT_POINTER(help->helper, helper);
 out:
        return ret;
 }
@@ -162,7 +162,7 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i,
                        lockdep_is_held(&nf_conntrack_lock)
                        ) == me) {
                nf_conntrack_event(IPCT_HELPER, ct);
-               rcu_assign_pointer(help->helper, NULL);
+               RCU_INIT_POINTER(help->helper, NULL);
        }
        return 0;
 }
index 7dec88a..e58aa9b 100644 (file)
@@ -1125,7 +1125,7 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[])
                if (help && help->helper) {
                        /* we had a helper before ... */
                        nf_ct_remove_expectations(ct);
-                       rcu_assign_pointer(help->helper, NULL);
+                       RCU_INIT_POINTER(help->helper, NULL);
                }
 
                return 0;
@@ -1163,7 +1163,7 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[])
                return -EOPNOTSUPP;
        }
 
-       rcu_assign_pointer(help->helper, helper);
+       RCU_INIT_POINTER(help->helper, helper);
 
        return 0;
 }
@@ -1386,7 +1386,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
                        }
 
                        /* not in hash table yet so not strictly necessary */
-                       rcu_assign_pointer(help->helper, helper);
+                       RCU_INIT_POINTER(help->helper, helper);
                }
        } else {
                /* try an implicit helper assignation */
index 20714ed..ce0c406 100644 (file)
@@ -55,7 +55,7 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger)
                llog = rcu_dereference_protected(nf_loggers[pf],
                                                 lockdep_is_held(&nf_log_mutex));
                if (llog == NULL)
-                       rcu_assign_pointer(nf_loggers[pf], logger);
+                       RCU_INIT_POINTER(nf_loggers[pf], logger);
        }
 
        mutex_unlock(&nf_log_mutex);
@@ -74,7 +74,7 @@ void nf_log_unregister(struct nf_logger *logger)
                c_logger = rcu_dereference_protected(nf_loggers[i],
                                                     lockdep_is_held(&nf_log_mutex));
                if (c_logger == logger)
-                       rcu_assign_pointer(nf_loggers[i], NULL);
+                       RCU_INIT_POINTER(nf_loggers[i], NULL);
                list_del(&logger->list[i]);
        }
        mutex_unlock(&nf_log_mutex);
@@ -92,7 +92,7 @@ int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger)
                mutex_unlock(&nf_log_mutex);
                return -ENOENT;
        }
-       rcu_assign_pointer(nf_loggers[pf], logger);
+       RCU_INIT_POINTER(nf_loggers[pf], logger);
        mutex_unlock(&nf_log_mutex);
        return 0;
 }
@@ -103,7 +103,7 @@ void nf_log_unbind_pf(u_int8_t pf)
        if (pf >= ARRAY_SIZE(nf_loggers))
                return;
        mutex_lock(&nf_log_mutex);
-       rcu_assign_pointer(nf_loggers[pf], NULL);
+       RCU_INIT_POINTER(nf_loggers[pf], NULL);
        mutex_unlock(&nf_log_mutex);
 }
 EXPORT_SYMBOL(nf_log_unbind_pf);
@@ -250,7 +250,7 @@ static int nf_log_proc_dostring(ctl_table *table, int write,
                        mutex_unlock(&nf_log_mutex);
                        return -ENOENT;
                }
-               rcu_assign_pointer(nf_loggers[tindex], logger);
+               RCU_INIT_POINTER(nf_loggers[tindex], logger);
                mutex_unlock(&nf_log_mutex);
        } else {
                mutex_lock(&nf_log_mutex);
index 5b466cd..99ffd28 100644 (file)
@@ -40,7 +40,7 @@ int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
        else if (old)
                ret = -EBUSY;
        else {
-               rcu_assign_pointer(queue_handler[pf], qh);
+               RCU_INIT_POINTER(queue_handler[pf], qh);
                ret = 0;
        }
        mutex_unlock(&queue_handler_mutex);
@@ -65,7 +65,7 @@ int nf_unregister_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
                return -EINVAL;
        }
 
-       rcu_assign_pointer(queue_handler[pf], NULL);
+       RCU_INIT_POINTER(queue_handler[pf], NULL);
        mutex_unlock(&queue_handler_mutex);
 
        synchronize_rcu();
@@ -84,7 +84,7 @@ void nf_unregister_queue_handlers(const struct nf_queue_handler *qh)
                                queue_handler[pf],
                                lockdep_is_held(&queue_handler_mutex)
                                ) == qh)
-                       rcu_assign_pointer(queue_handler[pf], NULL);
+                       RCU_INIT_POINTER(queue_handler[pf], NULL);
        }
        mutex_unlock(&queue_handler_mutex);
 
@@ -312,6 +312,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
                }
                break;
        case NF_STOLEN:
+               break;
        default:
                kfree_skb(skb);
        }
index 1905976..c879c1a 100644 (file)
@@ -59,7 +59,7 @@ int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
                nfnl_unlock();
                return -EBUSY;
        }
-       rcu_assign_pointer(subsys_table[n->subsys_id], n);
+       RCU_INIT_POINTER(subsys_table[n->subsys_id], n);
        nfnl_unlock();
 
        return 0;
@@ -210,7 +210,7 @@ static int __net_init nfnetlink_net_init(struct net *net)
        if (!nfnl)
                return -ENOMEM;
        net->nfnl_stash = nfnl;
-       rcu_assign_pointer(net->nfnl, nfnl);
+       RCU_INIT_POINTER(net->nfnl, nfnl);
        return 0;
 }
 
@@ -219,7 +219,7 @@ static void __net_exit nfnetlink_net_exit_batch(struct list_head *net_exit_list)
        struct net *net;
 
        list_for_each_entry(net, net_exit_list, exit_list)
-               rcu_assign_pointer(net->nfnl, NULL);
+               RCU_INIT_POINTER(net->nfnl, NULL);
        synchronize_net();
        list_for_each_entry(net, net_exit_list, exit_list)
                netlink_kernel_release(net->nfnl_stash);
index ea750e9..d2732fc 100644 (file)
@@ -1,8 +1,6 @@
 #
 # Makefile for the NetLabel subsystem.
 #
-# Feb 9, 2006, Paul Moore <paul.moore@hp.com>
-#
 
 # base objects
 obj-y  := netlabel_user.o netlabel_kapi.o
index c051913..96b749d 100644 (file)
@@ -6,7 +6,7 @@
  * system manages static and dynamic label mappings for network protocols such
  * as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index 2b9644e..fdbc1d2 100644 (file)
@@ -6,7 +6,7 @@
  * system manages static and dynamic label mappings for network protocols such
  * as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index dd53a36..6bf8783 100644 (file)
@@ -5,7 +5,7 @@
  * NetLabel system manages static and dynamic label mappings for network
  * protocols such as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index af7f335..d24d774 100644 (file)
@@ -5,7 +5,7 @@
  * NetLabel system manages static and dynamic label mappings for network
  * protocols such as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index 2aa975e..3f905e5 100644 (file)
@@ -6,7 +6,7 @@
  * system manages static and dynamic label mappings for network protocols such
  * as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
@@ -282,7 +282,7 @@ int __init netlbl_domhsh_init(u32 size)
                INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
 
        spin_lock(&netlbl_domhsh_lock);
-       rcu_assign_pointer(netlbl_domhsh, hsh_tbl);
+       RCU_INIT_POINTER(netlbl_domhsh, hsh_tbl);
        spin_unlock(&netlbl_domhsh_lock);
 
        return 0;
@@ -330,7 +330,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
                                    &rcu_dereference(netlbl_domhsh)->tbl[bkt]);
                } else {
                        INIT_LIST_HEAD(&entry->list);
-                       rcu_assign_pointer(netlbl_domhsh_def, entry);
+                       RCU_INIT_POINTER(netlbl_domhsh_def, entry);
                }
 
                if (entry->type == NETLBL_NLTYPE_ADDRSELECT) {
@@ -451,7 +451,7 @@ int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry,
                if (entry != rcu_dereference(netlbl_domhsh_def))
                        list_del_rcu(&entry->list);
                else
-                       rcu_assign_pointer(netlbl_domhsh_def, NULL);
+                       RCU_INIT_POINTER(netlbl_domhsh_def, NULL);
        } else
                ret_val = -ENOENT;
        spin_unlock(&netlbl_domhsh_lock);
index 0261dda..bfcc0f7 100644 (file)
@@ -6,7 +6,7 @@
  * system manages static and dynamic label mappings for network protocols such
  * as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index b528dd9..9c24de1 100644 (file)
@@ -5,7 +5,7 @@
  * system manages static and dynamic label mappings for network protocols such
  * as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
@@ -341,11 +341,11 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,
 
        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
        if (entry == NULL)
-               return -ENOMEM;
+               goto out_entry;
        if (domain != NULL) {
                entry->domain = kstrdup(domain, GFP_ATOMIC);
                if (entry->domain == NULL)
-                       goto cfg_cipsov4_map_add_failure;
+                       goto out_domain;
        }
 
        if (addr == NULL && mask == NULL) {
@@ -354,13 +354,13 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,
        } else if (addr != NULL && mask != NULL) {
                addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
                if (addrmap == NULL)
-                       goto cfg_cipsov4_map_add_failure;
+                       goto out_addrmap;
                INIT_LIST_HEAD(&addrmap->list4);
                INIT_LIST_HEAD(&addrmap->list6);
 
                addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
                if (addrinfo == NULL)
-                       goto cfg_cipsov4_map_add_failure;
+                       goto out_addrinfo;
                addrinfo->type_def.cipsov4 = doi_def;
                addrinfo->type = NETLBL_NLTYPE_CIPSOV4;
                addrinfo->list.addr = addr->s_addr & mask->s_addr;
@@ -374,7 +374,7 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,
                entry->type = NETLBL_NLTYPE_ADDRSELECT;
        } else {
                ret_val = -EINVAL;
-               goto cfg_cipsov4_map_add_failure;
+               goto out_addrmap;
        }
 
        ret_val = netlbl_domhsh_add(entry, audit_info);
@@ -384,11 +384,15 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,
        return 0;
 
 cfg_cipsov4_map_add_failure:
-       cipso_v4_doi_putdef(doi_def);
+       kfree(addrinfo);
+out_addrinfo:
+       kfree(addrmap);
+out_addrmap:
        kfree(entry->domain);
+out_domain:
        kfree(entry);
-       kfree(addrmap);
-       kfree(addrinfo);
+out_entry:
+       cipso_v4_doi_putdef(doi_def);
        return ret_val;
 }
 
index dff8a08..bfa5558 100644 (file)
@@ -5,7 +5,7 @@
  * NetLabel system manages static and dynamic label mappings for network
  * protocols such as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index 8db37f4..5a9f31c 100644 (file)
@@ -5,7 +5,7 @@
  * NetLabel system manages static and dynamic label mappings for network
  * protocols such as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index f1ecf84..e251c2c 100644 (file)
@@ -5,7 +5,7 @@
  * NetLabel system.  The NetLabel system manages static and dynamic label
  * mappings for network protocols such as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
@@ -354,7 +354,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)
                INIT_LIST_HEAD(&iface->list);
                if (netlbl_unlhsh_rcu_deref(netlbl_unlhsh_def) != NULL)
                        goto add_iface_failure;
-               rcu_assign_pointer(netlbl_unlhsh_def, iface);
+               RCU_INIT_POINTER(netlbl_unlhsh_def, iface);
        }
        spin_unlock(&netlbl_unlhsh_lock);
 
@@ -621,7 +621,7 @@ static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface)
        if (iface->ifindex > 0)
                list_del_rcu(&iface->list);
        else
-               rcu_assign_pointer(netlbl_unlhsh_def, NULL);
+               RCU_INIT_POINTER(netlbl_unlhsh_def, NULL);
        spin_unlock(&netlbl_unlhsh_lock);
 
        call_rcu(&iface->rcu, netlbl_unlhsh_free_iface);
@@ -1449,7 +1449,7 @@ int __init netlbl_unlabel_init(u32 size)
 
        rcu_read_lock();
        spin_lock(&netlbl_unlhsh_lock);
-       rcu_assign_pointer(netlbl_unlhsh, hsh_tbl);
+       RCU_INIT_POINTER(netlbl_unlhsh, hsh_tbl);
        spin_unlock(&netlbl_unlhsh_lock);
        rcu_read_unlock();
 
index 0bc8dc3..700af49 100644 (file)
@@ -5,7 +5,7 @@
  * NetLabel system.  The NetLabel system manages static and dynamic label
  * mappings for network protocols such as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index a3fd75a..9fae63f 100644 (file)
@@ -5,7 +5,7 @@
  * NetLabel system manages static and dynamic label mappings for network
  * protocols such as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index f4fc4c9..8196978 100644 (file)
@@ -5,7 +5,7 @@
  * NetLabel system manages static and dynamic label mappings for network
  * protocols such as CIPSO and RIPSO.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index 0a4db02..4330db9 100644 (file)
@@ -1578,7 +1578,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups)
                new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC);
                if (!new)
                        return -ENOMEM;
-               old = rcu_dereference_raw(tbl->listeners);
+               old = rcu_dereference_protected(tbl->listeners, 1);
                memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups));
                rcu_assign_pointer(tbl->listeners, new);
 
index c698cec..2ea3d63 100644 (file)
  *                                     byte arrays at the end of sockaddr_ll
  *                                     and packet_mreq.
  *             Johann Baudy    :       Added TX RING.
+ *             Chetan Loke     :       Implemented TPACKET_V3 block abstraction
+ *                                     layer.
+ *                                     Copyright (C) 2011, <lokec@ccs.neu.edu>
+ *
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -161,9 +165,56 @@ struct packet_mreq_max {
        unsigned char   mr_address[MAX_ADDR_LEN];
 };
 
-static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
+static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                int closing, int tx_ring);
 
+
+#define V3_ALIGNMENT   (8)
+
+#define BLK_HDR_LEN    (ALIGN(sizeof(struct tpacket_block_desc), V3_ALIGNMENT))
+
+#define BLK_PLUS_PRIV(sz_of_priv) \
+       (BLK_HDR_LEN + ALIGN((sz_of_priv), V3_ALIGNMENT))
+
+/* kbdq - kernel block descriptor queue */
+struct tpacket_kbdq_core {
+       struct pgv      *pkbdq;
+       unsigned int    feature_req_word;
+       unsigned int    hdrlen;
+       unsigned char   reset_pending_on_curr_blk;
+       unsigned char   delete_blk_timer;
+       unsigned short  kactive_blk_num;
+       unsigned short  blk_sizeof_priv;
+
+       /* last_kactive_blk_num:
+        * trick to see if user-space has caught up
+        * in order to avoid refreshing timer when every single pkt arrives.
+        */
+       unsigned short  last_kactive_blk_num;
+
+       char            *pkblk_start;
+       char            *pkblk_end;
+       int             kblk_size;
+       unsigned int    knum_blocks;
+       uint64_t        knxt_seq_num;
+       char            *prev;
+       char            *nxt_offset;
+       struct sk_buff  *skb;
+
+       atomic_t        blk_fill_in_prog;
+
+       /* Default is set to 8ms */
+#define DEFAULT_PRB_RETIRE_TOV (8)
+
+       unsigned short  retire_blk_tov;
+       unsigned short  version;
+       unsigned long   tov_in_jiffies;
+
+       /* timer to retire an outstanding block */
+       struct timer_list retire_blk_timer;
+};
+
+#define PGV_FROM_VMALLOC 1
 struct pgv {
        char *buffer;
 };
@@ -179,12 +230,44 @@ struct packet_ring_buffer {
        unsigned int            pg_vec_pages;
        unsigned int            pg_vec_len;
 
+       struct tpacket_kbdq_core        prb_bdqc;
        atomic_t                pending;
 };
 
+#define BLOCK_STATUS(x)        ((x)->hdr.bh1.block_status)
+#define BLOCK_NUM_PKTS(x)      ((x)->hdr.bh1.num_pkts)
+#define BLOCK_O2FP(x)          ((x)->hdr.bh1.offset_to_first_pkt)
+#define BLOCK_LEN(x)           ((x)->hdr.bh1.blk_len)
+#define BLOCK_SNUM(x)          ((x)->hdr.bh1.seq_num)
+#define BLOCK_O2PRIV(x)        ((x)->offset_to_priv)
+#define BLOCK_PRIV(x)          ((void *)((char *)(x) + BLOCK_O2PRIV(x)))
+
 struct packet_sock;
 static int tpacket_snd(struct packet_sock *po, struct msghdr *msg);
 
+static void *packet_previous_frame(struct packet_sock *po,
+               struct packet_ring_buffer *rb,
+               int status);
+static void packet_increment_head(struct packet_ring_buffer *buff);
+static int prb_curr_blk_in_use(struct tpacket_kbdq_core *,
+                       struct tpacket_block_desc *);
+static void *prb_dispatch_next_block(struct tpacket_kbdq_core *,
+                       struct packet_sock *);
+static void prb_retire_current_block(struct tpacket_kbdq_core *,
+               struct packet_sock *, unsigned int status);
+static int prb_queue_frozen(struct tpacket_kbdq_core *);
+static void prb_open_block(struct tpacket_kbdq_core *,
+               struct tpacket_block_desc *);
+static void prb_retire_rx_blk_timer_expired(unsigned long);
+static void _prb_refresh_rx_retire_blk_timer(struct tpacket_kbdq_core *);
+static void prb_init_blk_timer(struct packet_sock *,
+               struct tpacket_kbdq_core *,
+               void (*func) (unsigned long));
+static void prb_fill_rxhash(struct tpacket_kbdq_core *, struct tpacket3_hdr *);
+static void prb_clear_rxhash(struct tpacket_kbdq_core *,
+               struct tpacket3_hdr *);
+static void prb_fill_vlan_info(struct tpacket_kbdq_core *,
+               struct tpacket3_hdr *);
 static void packet_flush_mclist(struct sock *sk);
 
 struct packet_fanout;
@@ -193,6 +276,7 @@ struct packet_sock {
        struct sock             sk;
        struct packet_fanout    *fanout;
        struct tpacket_stats    stats;
+       union  tpacket_stats_u  stats_u;
        struct packet_ring_buffer       rx_ring;
        struct packet_ring_buffer       tx_ring;
        int                     copy_thresh;
@@ -242,6 +326,15 @@ struct packet_skb_cb {
 
 #define PACKET_SKB_CB(__skb)   ((struct packet_skb_cb *)((__skb)->cb))
 
+#define GET_PBDQC_FROM_RB(x)   ((struct tpacket_kbdq_core *)(&(x)->prb_bdqc))
+#define GET_PBLOCK_DESC(x, bid)        \
+       ((struct tpacket_block_desc *)((x)->pkbdq[(bid)].buffer))
+#define GET_CURR_PBLOCK_DESC_FROM_CORE(x)      \
+       ((struct tpacket_block_desc *)((x)->pkbdq[(x)->kactive_blk_num].buffer))
+#define GET_NEXT_PRB_BLK_NUM(x) \
+       (((x)->kactive_blk_num < ((x)->knum_blocks-1)) ? \
+       ((x)->kactive_blk_num+1) : 0)
+
 static inline struct packet_sock *pkt_sk(struct sock *sk)
 {
        return (struct packet_sock *)sk;
@@ -325,8 +418,9 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status)
                h.h2->tp_status = status;
                flush_dcache_page(pgv_to_page(&h.h2->tp_status));
                break;
+       case TPACKET_V3:
        default:
-               pr_err("TPACKET version not supported\n");
+               WARN(1, "TPACKET version not supported.\n");
                BUG();
        }
 
@@ -351,8 +445,9 @@ static int __packet_get_status(struct packet_sock *po, void *frame)
        case TPACKET_V2:
                flush_dcache_page(pgv_to_page(&h.h2->tp_status));
                return h.h2->tp_status;
+       case TPACKET_V3:
        default:
-               pr_err("TPACKET version not supported\n");
+               WARN(1, "TPACKET version not supported.\n");
                BUG();
                return 0;
        }
@@ -389,6 +484,668 @@ static inline void *packet_current_frame(struct packet_sock *po,
        return packet_lookup_frame(po, rb, rb->head, status);
 }
 
+static void prb_del_retire_blk_timer(struct tpacket_kbdq_core *pkc)
+{
+       del_timer_sync(&pkc->retire_blk_timer);
+}
+
+static void prb_shutdown_retire_blk_timer(struct packet_sock *po,
+               int tx_ring,
+               struct sk_buff_head *rb_queue)
+{
+       struct tpacket_kbdq_core *pkc;
+
+       pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc;
+
+       spin_lock(&rb_queue->lock);
+       pkc->delete_blk_timer = 1;
+       spin_unlock(&rb_queue->lock);
+
+       prb_del_retire_blk_timer(pkc);
+}
+
+static void prb_init_blk_timer(struct packet_sock *po,
+               struct tpacket_kbdq_core *pkc,
+               void (*func) (unsigned long))
+{
+       init_timer(&pkc->retire_blk_timer);
+       pkc->retire_blk_timer.data = (long)po;
+       pkc->retire_blk_timer.function = func;
+       pkc->retire_blk_timer.expires = jiffies;
+}
+
+static void prb_setup_retire_blk_timer(struct packet_sock *po, int tx_ring)
+{
+       struct tpacket_kbdq_core *pkc;
+
+       if (tx_ring)
+               BUG();
+
+       pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc;
+       prb_init_blk_timer(po, pkc, prb_retire_rx_blk_timer_expired);
+}
+
+static int prb_calc_retire_blk_tmo(struct packet_sock *po,
+                               int blk_size_in_bytes)
+{
+       struct net_device *dev;
+       unsigned int mbits = 0, msec = 0, div = 0, tmo = 0;
+
+       dev = dev_get_by_index(sock_net(&po->sk), po->ifindex);
+       if (unlikely(dev == NULL))
+               return DEFAULT_PRB_RETIRE_TOV;
+
+       if (dev->ethtool_ops && dev->ethtool_ops->get_settings) {
+               struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, };
+
+               if (!dev->ethtool_ops->get_settings(dev, &ecmd)) {
+                       switch (ecmd.speed) {
+                       case SPEED_10000:
+                               msec = 1;
+                               div = 10000/1000;
+                               break;
+                       case SPEED_1000:
+                               msec = 1;
+                               div = 1000/1000;
+                               break;
+                       /*
+                        * If the link speed is so slow you don't really
+                        * need to worry about perf anyways
+                        */
+                       case SPEED_100:
+                       case SPEED_10:
+                       default:
+                               return DEFAULT_PRB_RETIRE_TOV;
+                       }
+               }
+       }
+
+       mbits = (blk_size_in_bytes * 8) / (1024 * 1024);
+
+       if (div)
+               mbits /= div;
+
+       tmo = mbits * msec;
+
+       if (div)
+               return tmo+1;
+       return tmo;
+}
+
+static void prb_init_ft_ops(struct tpacket_kbdq_core *p1,
+                       union tpacket_req_u *req_u)
+{
+       p1->feature_req_word = req_u->req3.tp_feature_req_word;
+}
+
+static void init_prb_bdqc(struct packet_sock *po,
+                       struct packet_ring_buffer *rb,
+                       struct pgv *pg_vec,
+                       union tpacket_req_u *req_u, int tx_ring)
+{
+       struct tpacket_kbdq_core *p1 = &rb->prb_bdqc;
+       struct tpacket_block_desc *pbd;
+
+       memset(p1, 0x0, sizeof(*p1));
+
+       p1->knxt_seq_num = 1;
+       p1->pkbdq = pg_vec;
+       pbd = (struct tpacket_block_desc *)pg_vec[0].buffer;
+       p1->pkblk_start = (char *)pg_vec[0].buffer;
+       p1->kblk_size = req_u->req3.tp_block_size;
+       p1->knum_blocks = req_u->req3.tp_block_nr;
+       p1->hdrlen = po->tp_hdrlen;
+       p1->version = po->tp_version;
+       p1->last_kactive_blk_num = 0;
+       po->stats_u.stats3.tp_freeze_q_cnt = 0;
+       if (req_u->req3.tp_retire_blk_tov)
+               p1->retire_blk_tov = req_u->req3.tp_retire_blk_tov;
+       else
+               p1->retire_blk_tov = prb_calc_retire_blk_tmo(po,
+                                               req_u->req3.tp_block_size);
+       p1->tov_in_jiffies = msecs_to_jiffies(p1->retire_blk_tov);
+       p1->blk_sizeof_priv = req_u->req3.tp_sizeof_priv;
+
+       prb_init_ft_ops(p1, req_u);
+       prb_setup_retire_blk_timer(po, tx_ring);
+       prb_open_block(p1, pbd);
+}
+
+/*  Do NOT update the last_blk_num first.
+ *  Assumes sk_buff_head lock is held.
+ */
+static void _prb_refresh_rx_retire_blk_timer(struct tpacket_kbdq_core *pkc)
+{
+       mod_timer(&pkc->retire_blk_timer,
+                       jiffies + pkc->tov_in_jiffies);
+       pkc->last_kactive_blk_num = pkc->kactive_blk_num;
+}
+
+/*
+ * Timer logic:
+ * 1) We refresh the timer only when we open a block.
+ *    By doing this we don't waste cycles refreshing the timer
+ *       on packet-by-packet basis.
+ *
+ * With a 1MB block-size, on a 1Gbps line, it will take
+ * i) ~8 ms to fill a block + ii) memcpy etc.
+ * In this cut we are not accounting for the memcpy time.
+ *
+ * So, if the user sets the 'tmo' to 10ms then the timer
+ * will never fire while the block is still getting filled
+ * (which is what we want). However, the user could choose
+ * to close a block early and that's fine.
+ *
+ * But when the timer does fire, we check whether or not to refresh it.
+ * Since the tmo granularity is in msecs, it is not too expensive
+ * to refresh the timer, lets say every '8' msecs.
+ * Either the user can set the 'tmo' or we can derive it based on
+ * a) line-speed and b) block-size.
+ * prb_calc_retire_blk_tmo() calculates the tmo.
+ *
+ */
+static void prb_retire_rx_blk_timer_expired(unsigned long data)
+{
+       struct packet_sock *po = (struct packet_sock *)data;
+       struct tpacket_kbdq_core *pkc = &po->rx_ring.prb_bdqc;
+       unsigned int frozen;
+       struct tpacket_block_desc *pbd;
+
+       spin_lock(&po->sk.sk_receive_queue.lock);
+
+       frozen = prb_queue_frozen(pkc);
+       pbd = GET_CURR_PBLOCK_DESC_FROM_CORE(pkc);
+
+       if (unlikely(pkc->delete_blk_timer))
+               goto out;
+
+       /* We only need to plug the race when the block is partially filled.
+        * tpacket_rcv:
+        *              lock(); increment BLOCK_NUM_PKTS; unlock()
+        *              copy_bits() is in progress ...
+        *              timer fires on other cpu:
+        *              we can't retire the current block because copy_bits
+        *              is in progress.
+        *
+        */
+       if (BLOCK_NUM_PKTS(pbd)) {
+               while (atomic_read(&pkc->blk_fill_in_prog)) {
+                       /* Waiting for skb_copy_bits to finish... */
+                       cpu_relax();
+               }
+       }
+
+       if (pkc->last_kactive_blk_num == pkc->kactive_blk_num) {
+               if (!frozen) {
+                       prb_retire_current_block(pkc, po, TP_STATUS_BLK_TMO);
+                       if (!prb_dispatch_next_block(pkc, po))
+                               goto refresh_timer;
+                       else
+                               goto out;
+               } else {
+                       /* Case 1. Queue was frozen because user-space was
+                        *         lagging behind.
+                        */
+                       if (prb_curr_blk_in_use(pkc, pbd)) {
+                               /*
+                                * Ok, user-space is still behind.
+                                * So just refresh the timer.
+                                */
+                               goto refresh_timer;
+                       } else {
+                              /* Case 2. queue was frozen,user-space caught up,
+                               * now the link went idle && the timer fired.
+                               * We don't have a block to close.So we open this
+                               * block and restart the timer.
+                               * opening a block thaws the queue,restarts timer
+                               * Thawing/timer-refresh is a side effect.
+                               */
+                               prb_open_block(pkc, pbd);
+                               goto out;
+                       }
+               }
+       }
+
+refresh_timer:
+       _prb_refresh_rx_retire_blk_timer(pkc);
+
+out:
+       spin_unlock(&po->sk.sk_receive_queue.lock);
+}
+
+static inline void prb_flush_block(struct tpacket_kbdq_core *pkc1,
+               struct tpacket_block_desc *pbd1, __u32 status)
+{
+       /* Flush everything minus the block header */
+
+#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE == 1
+       u8 *start, *end;
+
+       start = (u8 *)pbd1;
+
+       /* Skip the block header(we know header WILL fit in 4K) */
+       start += PAGE_SIZE;
+
+       end = (u8 *)PAGE_ALIGN((unsigned long)pkc1->pkblk_end);
+       for (; start < end; start += PAGE_SIZE)
+               flush_dcache_page(pgv_to_page(start));
+
+       smp_wmb();
+#endif
+
+       /* Now update the block status. */
+
+       BLOCK_STATUS(pbd1) = status;
+
+       /* Flush the block header */
+
+#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE == 1
+       start = (u8 *)pbd1;
+       flush_dcache_page(pgv_to_page(start));
+
+       smp_wmb();
+#endif
+}
+
+/*
+ * Side effect:
+ *
+ * 1) flush the block
+ * 2) Increment active_blk_num
+ *
+ * Note:We DONT refresh the timer on purpose.
+ *     Because almost always the next block will be opened.
+ */
+static void prb_close_block(struct tpacket_kbdq_core *pkc1,
+               struct tpacket_block_desc *pbd1,
+               struct packet_sock *po, unsigned int stat)
+{
+       __u32 status = TP_STATUS_USER | stat;
+
+       struct tpacket3_hdr *last_pkt;
+       struct tpacket_hdr_v1 *h1 = &pbd1->hdr.bh1;
+
+       if (po->stats.tp_drops)
+               status |= TP_STATUS_LOSING;
+
+       last_pkt = (struct tpacket3_hdr *)pkc1->prev;
+       last_pkt->tp_next_offset = 0;
+
+       /* Get the ts of the last pkt */
+       if (BLOCK_NUM_PKTS(pbd1)) {
+               h1->ts_last_pkt.ts_sec = last_pkt->tp_sec;
+               h1->ts_last_pkt.ts_nsec = last_pkt->tp_nsec;
+       } else {
+               /* Ok, we tmo'd - so get the current time */
+               struct timespec ts;
+               getnstimeofday(&ts);
+               h1->ts_last_pkt.ts_sec = ts.tv_sec;
+               h1->ts_last_pkt.ts_nsec = ts.tv_nsec;
+       }
+
+       smp_wmb();
+
+       /* Flush the block */
+       prb_flush_block(pkc1, pbd1, status);
+
+       pkc1->kactive_blk_num = GET_NEXT_PRB_BLK_NUM(pkc1);
+}
+
+static inline void prb_thaw_queue(struct tpacket_kbdq_core *pkc)
+{
+       pkc->reset_pending_on_curr_blk = 0;
+}
+
+/*
+ * Side effect of opening a block:
+ *
+ * 1) prb_queue is thawed.
+ * 2) retire_blk_timer is refreshed.
+ *
+ */
+static void prb_open_block(struct tpacket_kbdq_core *pkc1,
+       struct tpacket_block_desc *pbd1)
+{
+       struct timespec ts;
+       struct tpacket_hdr_v1 *h1 = &pbd1->hdr.bh1;
+
+       smp_rmb();
+
+       if (likely(TP_STATUS_KERNEL == BLOCK_STATUS(pbd1))) {
+
+               /* We could have just memset this but we will lose the
+                * flexibility of making the priv area sticky
+                */
+               BLOCK_SNUM(pbd1) = pkc1->knxt_seq_num++;
+               BLOCK_NUM_PKTS(pbd1) = 0;
+               BLOCK_LEN(pbd1) = BLK_PLUS_PRIV(pkc1->blk_sizeof_priv);
+               getnstimeofday(&ts);
+               h1->ts_first_pkt.ts_sec = ts.tv_sec;
+               h1->ts_first_pkt.ts_nsec = ts.tv_nsec;
+               pkc1->pkblk_start = (char *)pbd1;
+               pkc1->nxt_offset = (char *)(pkc1->pkblk_start +
+               BLK_PLUS_PRIV(pkc1->blk_sizeof_priv));
+               BLOCK_O2FP(pbd1) = (__u32)BLK_PLUS_PRIV(pkc1->blk_sizeof_priv);
+               BLOCK_O2PRIV(pbd1) = BLK_HDR_LEN;
+               pbd1->version = pkc1->version;
+               pkc1->prev = pkc1->nxt_offset;
+               pkc1->pkblk_end = pkc1->pkblk_start + pkc1->kblk_size;
+               prb_thaw_queue(pkc1);
+               _prb_refresh_rx_retire_blk_timer(pkc1);
+
+               smp_wmb();
+
+               return;
+       }
+
+       WARN(1, "ERROR block:%p is NOT FREE status:%d kactive_blk_num:%d\n",
+               pbd1, BLOCK_STATUS(pbd1), pkc1->kactive_blk_num);
+       dump_stack();
+       BUG();
+}
+
+/*
+ * Queue freeze logic:
+ * 1) Assume tp_block_nr = 8 blocks.
+ * 2) At time 't0', user opens Rx ring.
+ * 3) Some time past 't0', kernel starts filling blocks starting from 0 .. 7
+ * 4) user-space is either sleeping or processing block '0'.
+ * 5) tpacket_rcv is currently filling block '7', since there is no space left,
+ *    it will close block-7,loop around and try to fill block '0'.
+ *    call-flow:
+ *    __packet_lookup_frame_in_block
+ *      prb_retire_current_block()
+ *      prb_dispatch_next_block()
+ *        |->(BLOCK_STATUS == USER) evaluates to true
+ *    5.1) Since block-0 is currently in-use, we just freeze the queue.
+ * 6) Now there are two cases:
+ *    6.1) Link goes idle right after the queue is frozen.
+ *         But remember, the last open_block() refreshed the timer.
+ *         When this timer expires,it will refresh itself so that we can
+ *         re-open block-0 in near future.
+ *    6.2) Link is busy and keeps on receiving packets. This is a simple
+ *         case and __packet_lookup_frame_in_block will check if block-0
+ *         is free and can now be re-used.
+ */
+static inline void prb_freeze_queue(struct tpacket_kbdq_core *pkc,
+                                 struct packet_sock *po)
+{
+       pkc->reset_pending_on_curr_blk = 1;
+       po->stats_u.stats3.tp_freeze_q_cnt++;
+}
+
+#define TOTAL_PKT_LEN_INCL_ALIGN(length) (ALIGN((length), V3_ALIGNMENT))
+
+/*
+ * If the next block is free then we will dispatch it
+ * and return a good offset.
+ * Else, we will freeze the queue.
+ * So, caller must check the return value.
+ */
+static void *prb_dispatch_next_block(struct tpacket_kbdq_core *pkc,
+               struct packet_sock *po)
+{
+       struct tpacket_block_desc *pbd;
+
+       smp_rmb();
+
+       /* 1. Get current block num */
+       pbd = GET_CURR_PBLOCK_DESC_FROM_CORE(pkc);
+
+       /* 2. If this block is currently in_use then freeze the queue */
+       if (TP_STATUS_USER & BLOCK_STATUS(pbd)) {
+               prb_freeze_queue(pkc, po);
+               return NULL;
+       }
+
+       /*
+        * 3.
+        * open this block and return the offset where the first packet
+        * needs to get stored.
+        */
+       prb_open_block(pkc, pbd);
+       return (void *)pkc->nxt_offset;
+}
+
+static void prb_retire_current_block(struct tpacket_kbdq_core *pkc,
+               struct packet_sock *po, unsigned int status)
+{
+       struct tpacket_block_desc *pbd = GET_CURR_PBLOCK_DESC_FROM_CORE(pkc);
+
+       /* retire/close the current block */
+       if (likely(TP_STATUS_KERNEL == BLOCK_STATUS(pbd))) {
+               /*
+                * Plug the case where copy_bits() is in progress on
+                * cpu-0 and tpacket_rcv() got invoked on cpu-1, didn't
+                * have space to copy the pkt in the current block and
+                * called prb_retire_current_block()
+                *
+                * We don't need to worry about the TMO case because
+                * the timer-handler already handled this case.
+                */
+               if (!(status & TP_STATUS_BLK_TMO)) {
+                       while (atomic_read(&pkc->blk_fill_in_prog)) {
+                               /* Waiting for skb_copy_bits to finish... */
+                               cpu_relax();
+                       }
+               }
+               prb_close_block(pkc, pbd, po, status);
+               return;
+       }
+
+       WARN(1, "ERROR-pbd[%d]:%p\n", pkc->kactive_blk_num, pbd);
+       dump_stack();
+       BUG();
+}
+
+static inline int prb_curr_blk_in_use(struct tpacket_kbdq_core *pkc,
+                                     struct tpacket_block_desc *pbd)
+{
+       return TP_STATUS_USER & BLOCK_STATUS(pbd);
+}
+
+static inline int prb_queue_frozen(struct tpacket_kbdq_core *pkc)
+{
+       return pkc->reset_pending_on_curr_blk;
+}
+
+static inline void prb_clear_blk_fill_status(struct packet_ring_buffer *rb)
+{
+       struct tpacket_kbdq_core *pkc  = GET_PBDQC_FROM_RB(rb);
+       atomic_dec(&pkc->blk_fill_in_prog);
+}
+
+static inline void prb_fill_rxhash(struct tpacket_kbdq_core *pkc,
+                       struct tpacket3_hdr *ppd)
+{
+       ppd->hv1.tp_rxhash = skb_get_rxhash(pkc->skb);
+}
+
+static inline void prb_clear_rxhash(struct tpacket_kbdq_core *pkc,
+                       struct tpacket3_hdr *ppd)
+{
+       ppd->hv1.tp_rxhash = 0;
+}
+
+static inline void prb_fill_vlan_info(struct tpacket_kbdq_core *pkc,
+                       struct tpacket3_hdr *ppd)
+{
+       if (vlan_tx_tag_present(pkc->skb)) {
+               ppd->hv1.tp_vlan_tci = vlan_tx_tag_get(pkc->skb);
+               ppd->tp_status = TP_STATUS_VLAN_VALID;
+       } else {
+               ppd->hv1.tp_vlan_tci = ppd->tp_status = 0;
+       }
+}
+
+static void prb_run_all_ft_ops(struct tpacket_kbdq_core *pkc,
+                       struct tpacket3_hdr *ppd)
+{
+       prb_fill_vlan_info(pkc, ppd);
+
+       if (pkc->feature_req_word & TP_FT_REQ_FILL_RXHASH)
+               prb_fill_rxhash(pkc, ppd);
+       else
+               prb_clear_rxhash(pkc, ppd);
+}
+
+static inline void prb_fill_curr_block(char *curr,
+                               struct tpacket_kbdq_core *pkc,
+                               struct tpacket_block_desc *pbd,
+                               unsigned int len)
+{
+       struct tpacket3_hdr *ppd;
+
+       ppd  = (struct tpacket3_hdr *)curr;
+       ppd->tp_next_offset = TOTAL_PKT_LEN_INCL_ALIGN(len);
+       pkc->prev = curr;
+       pkc->nxt_offset += TOTAL_PKT_LEN_INCL_ALIGN(len);
+       BLOCK_LEN(pbd) += TOTAL_PKT_LEN_INCL_ALIGN(len);
+       BLOCK_NUM_PKTS(pbd) += 1;
+       atomic_inc(&pkc->blk_fill_in_prog);
+       prb_run_all_ft_ops(pkc, ppd);
+}
+
+/* Assumes caller has the sk->rx_queue.lock */
+static void *__packet_lookup_frame_in_block(struct packet_sock *po,
+                                           struct sk_buff *skb,
+                                               int status,
+                                           unsigned int len
+                                           )
+{
+       struct tpacket_kbdq_core *pkc;
+       struct tpacket_block_desc *pbd;
+       char *curr, *end;
+
+       pkc = GET_PBDQC_FROM_RB(((struct packet_ring_buffer *)&po->rx_ring));
+       pbd = GET_CURR_PBLOCK_DESC_FROM_CORE(pkc);
+
+       /* Queue is frozen when user space is lagging behind */
+       if (prb_queue_frozen(pkc)) {
+               /*
+                * Check if that last block which caused the queue to freeze,
+                * is still in_use by user-space.
+                */
+               if (prb_curr_blk_in_use(pkc, pbd)) {
+                       /* Can't record this packet */
+                       return NULL;
+               } else {
+                       /*
+                        * Ok, the block was released by user-space.
+                        * Now let's open that block.
+                        * opening a block also thaws the queue.
+                        * Thawing is a side effect.
+                        */
+                       prb_open_block(pkc, pbd);
+               }
+       }
+
+       smp_mb();
+       curr = pkc->nxt_offset;
+       pkc->skb = skb;
+       end = (char *) ((char *)pbd + pkc->kblk_size);
+
+       /* first try the current block */
+       if (curr+TOTAL_PKT_LEN_INCL_ALIGN(len) < end) {
+               prb_fill_curr_block(curr, pkc, pbd, len);
+               return (void *)curr;
+       }
+
+       /* Ok, close the current block */
+       prb_retire_current_block(pkc, po, 0);
+
+       /* Now, try to dispatch the next block */
+       curr = (char *)prb_dispatch_next_block(pkc, po);
+       if (curr) {
+               pbd = GET_CURR_PBLOCK_DESC_FROM_CORE(pkc);
+               prb_fill_curr_block(curr, pkc, pbd, len);
+               return (void *)curr;
+       }
+
+       /*
+        * No free blocks are available.user_space hasn't caught up yet.
+        * Queue was just frozen and now this packet will get dropped.
+        */
+       return NULL;
+}
+
+static inline void *packet_current_rx_frame(struct packet_sock *po,
+                                           struct sk_buff *skb,
+                                           int status, unsigned int len)
+{
+       char *curr = NULL;
+       switch (po->tp_version) {
+       case TPACKET_V1:
+       case TPACKET_V2:
+               curr = packet_lookup_frame(po, &po->rx_ring,
+                                       po->rx_ring.head, status);
+               return curr;
+       case TPACKET_V3:
+               return __packet_lookup_frame_in_block(po, skb, status, len);
+       default:
+               WARN(1, "TPACKET version not supported\n");
+               BUG();
+               return 0;
+       }
+}
+
+static inline void *prb_lookup_block(struct packet_sock *po,
+                                    struct packet_ring_buffer *rb,
+                                    unsigned int previous,
+                                    int status)
+{
+       struct tpacket_kbdq_core *pkc  = GET_PBDQC_FROM_RB(rb);
+       struct tpacket_block_desc *pbd = GET_PBLOCK_DESC(pkc, previous);
+
+       if (status != BLOCK_STATUS(pbd))
+               return NULL;
+       return pbd;
+}
+
+static inline int prb_previous_blk_num(struct packet_ring_buffer *rb)
+{
+       unsigned int prev;
+       if (rb->prb_bdqc.kactive_blk_num)
+               prev = rb->prb_bdqc.kactive_blk_num-1;
+       else
+               prev = rb->prb_bdqc.knum_blocks-1;
+       return prev;
+}
+
+/* Assumes caller has held the rx_queue.lock */
+static inline void *__prb_previous_block(struct packet_sock *po,
+                                        struct packet_ring_buffer *rb,
+                                        int status)
+{
+       unsigned int previous = prb_previous_blk_num(rb);
+       return prb_lookup_block(po, rb, previous, status);
+}
+
+static inline void *packet_previous_rx_frame(struct packet_sock *po,
+                                            struct packet_ring_buffer *rb,
+                                            int status)
+{
+       if (po->tp_version <= TPACKET_V2)
+               return packet_previous_frame(po, rb, status);
+
+       return __prb_previous_block(po, rb, status);
+}
+
+static inline void packet_increment_rx_head(struct packet_sock *po,
+                                           struct packet_ring_buffer *rb)
+{
+       switch (po->tp_version) {
+       case TPACKET_V1:
+       case TPACKET_V2:
+               return packet_increment_head(rb);
+       case TPACKET_V3:
+       default:
+               WARN(1, "TPACKET version not supported.\n");
+               BUG();
+               return;
+       }
+}
+
 static inline void *packet_previous_frame(struct packet_sock *po,
                struct packet_ring_buffer *rb,
                int status)
@@ -982,12 +1739,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
        union {
                struct tpacket_hdr *h1;
                struct tpacket2_hdr *h2;
+               struct tpacket3_hdr *h3;
                void *raw;
        } h;
        u8 *skb_head = skb->data;
        int skb_len = skb->len;
        unsigned int snaplen, res;
-       unsigned long status = TP_STATUS_LOSING|TP_STATUS_USER;
+       unsigned long status = TP_STATUS_USER;
        unsigned short macoff, netoff, hdrlen;
        struct sk_buff *copy_skb = NULL;
        struct timeval tv;
@@ -1033,37 +1791,46 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
                        po->tp_reserve;
                macoff = netoff - maclen;
        }
-
-       if (macoff + snaplen > po->rx_ring.frame_size) {
-               if (po->copy_thresh &&
-                   atomic_read(&sk->sk_rmem_alloc) + skb->truesize <
-                   (unsigned)sk->sk_rcvbuf) {
-                       if (skb_shared(skb)) {
-                               copy_skb = skb_clone(skb, GFP_ATOMIC);
-                       } else {
-                               copy_skb = skb_get(skb);
-                               skb_head = skb->data;
+       if (po->tp_version <= TPACKET_V2) {
+               if (macoff + snaplen > po->rx_ring.frame_size) {
+                       if (po->copy_thresh &&
+                               atomic_read(&sk->sk_rmem_alloc) + skb->truesize
+                               < (unsigned)sk->sk_rcvbuf) {
+                               if (skb_shared(skb)) {
+                                       copy_skb = skb_clone(skb, GFP_ATOMIC);
+                               } else {
+                                       copy_skb = skb_get(skb);
+                                       skb_head = skb->data;
+                               }
+                               if (copy_skb)
+                                       skb_set_owner_r(copy_skb, sk);
                        }
-                       if (copy_skb)
-                               skb_set_owner_r(copy_skb, sk);
+                       snaplen = po->rx_ring.frame_size - macoff;
+                       if ((int)snaplen < 0)
+                               snaplen = 0;
                }
-               snaplen = po->rx_ring.frame_size - macoff;
-               if ((int)snaplen < 0)
-                       snaplen = 0;
        }
-
        spin_lock(&sk->sk_receive_queue.lock);
-       h.raw = packet_current_frame(po, &po->rx_ring, TP_STATUS_KERNEL);
+       h.raw = packet_current_rx_frame(po, skb,
+                                       TP_STATUS_KERNEL, (macoff+snaplen));
        if (!h.raw)
                goto ring_is_full;
-       packet_increment_head(&po->rx_ring);
+       if (po->tp_version <= TPACKET_V2) {
+               packet_increment_rx_head(po, &po->rx_ring);
+       /*
+        * LOSING will be reported till you read the stats,
+        * because it's COR - Clear On Read.
+        * Anyways, moving it for V1/V2 only as V3 doesn't need this
+        * at packet level.
+        */
+               if (po->stats.tp_drops)
+                       status |= TP_STATUS_LOSING;
+       }
        po->stats.tp_packets++;
        if (copy_skb) {
                status |= TP_STATUS_COPY;
                __skb_queue_tail(&sk->sk_receive_queue, copy_skb);
        }
-       if (!po->stats.tp_drops)
-               status &= ~TP_STATUS_LOSING;
        spin_unlock(&sk->sk_receive_queue.lock);
 
        skb_copy_bits(skb, 0, h.raw + macoff, snaplen);
@@ -1114,6 +1881,29 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
                h.h2->tp_padding = 0;
                hdrlen = sizeof(*h.h2);
                break;
+       case TPACKET_V3:
+               /* tp_nxt_offset,vlan are already populated above.
+                * So DONT clear those fields here
+                */
+               h.h3->tp_status |= status;
+               h.h3->tp_len = skb->len;
+               h.h3->tp_snaplen = snaplen;
+               h.h3->tp_mac = macoff;
+               h.h3->tp_net = netoff;
+               if ((po->tp_tstamp & SOF_TIMESTAMPING_SYS_HARDWARE)
+                               && shhwtstamps->syststamp.tv64)
+                       ts = ktime_to_timespec(shhwtstamps->syststamp);
+               else if ((po->tp_tstamp & SOF_TIMESTAMPING_RAW_HARDWARE)
+                               && shhwtstamps->hwtstamp.tv64)
+                       ts = ktime_to_timespec(shhwtstamps->hwtstamp);
+               else if (skb->tstamp.tv64)
+                       ts = ktime_to_timespec(skb->tstamp);
+               else
+                       getnstimeofday(&ts);
+               h.h3->tp_sec  = ts.tv_sec;
+               h.h3->tp_nsec = ts.tv_nsec;
+               hdrlen = sizeof(*h.h3);
+               break;
        default:
                BUG();
        }
@@ -1134,13 +1924,19 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
        {
                u8 *start, *end;
 
-               end = (u8 *)PAGE_ALIGN((unsigned long)h.raw + macoff + snaplen);
-               for (start = h.raw; start < end; start += PAGE_SIZE)
-                       flush_dcache_page(pgv_to_page(start));
+               if (po->tp_version <= TPACKET_V2) {
+                       end = (u8 *)PAGE_ALIGN((unsigned long)h.raw
+                               + macoff + snaplen);
+                       for (start = h.raw; start < end; start += PAGE_SIZE)
+                               flush_dcache_page(pgv_to_page(start));
+               }
                smp_wmb();
        }
 #endif
-       __packet_set_status(po, h.raw, status);
+       if (po->tp_version <= TPACKET_V2)
+               __packet_set_status(po, h.raw, status);
+       else
+               prb_clear_blk_fill_status(&po->rx_ring);
 
        sk->sk_data_ready(sk, 0);
 
@@ -1631,7 +2427,7 @@ static int packet_release(struct socket *sock)
        struct sock *sk = sock->sk;
        struct packet_sock *po;
        struct net *net;
-       struct tpacket_req req;
+       union tpacket_req_u req_u;
 
        if (!sk)
                return 0;
@@ -1654,13 +2450,13 @@ static int packet_release(struct socket *sock)
 
        packet_flush_mclist(sk);
 
-       memset(&req, 0, sizeof(req));
+       memset(&req_u, 0, sizeof(req_u));
 
        if (po->rx_ring.pg_vec)
-               packet_set_ring(sk, &req, 1, 0);
+               packet_set_ring(sk, &req_u, 1, 0);
 
        if (po->tx_ring.pg_vec)
-               packet_set_ring(sk, &req, 1, 1);
+               packet_set_ring(sk, &req_u, 1, 1);
 
        fanout_release(sk);
 
@@ -2280,15 +3076,27 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
        case PACKET_RX_RING:
        case PACKET_TX_RING:
        {
-               struct tpacket_req req;
+               union tpacket_req_u req_u;
+               int len;
 
-               if (optlen < sizeof(req))
+               switch (po->tp_version) {
+               case TPACKET_V1:
+               case TPACKET_V2:
+                       len = sizeof(req_u.req);
+                       break;
+               case TPACKET_V3:
+               default:
+                       len = sizeof(req_u.req3);
+                       break;
+               }
+               if (optlen < len)
                        return -EINVAL;
                if (pkt_sk(sk)->has_vnet_hdr)
                        return -EINVAL;
-               if (copy_from_user(&req, optval, sizeof(req)))
+               if (copy_from_user(&req_u.req, optval, len))
                        return -EFAULT;
-               return packet_set_ring(sk, &req, 0, optname == PACKET_TX_RING);
+               return packet_set_ring(sk, &req_u, 0,
+                       optname == PACKET_TX_RING);
        }
        case PACKET_COPY_THRESH:
        {
@@ -2315,6 +3123,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
                switch (val) {
                case TPACKET_V1:
                case TPACKET_V2:
+               case TPACKET_V3:
                        po->tp_version = val;
                        return 0;
                default:
@@ -2424,6 +3233,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
        struct packet_sock *po = pkt_sk(sk);
        void *data;
        struct tpacket_stats st;
+       union tpacket_stats_u st_u;
 
        if (level != SOL_PACKET)
                return -ENOPROTOOPT;
@@ -2436,15 +3246,27 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 
        switch (optname) {
        case PACKET_STATISTICS:
-               if (len > sizeof(struct tpacket_stats))
-                       len = sizeof(struct tpacket_stats);
+               if (po->tp_version == TPACKET_V3) {
+                       len = sizeof(struct tpacket_stats_v3);
+               } else {
+                       if (len > sizeof(struct tpacket_stats))
+                               len = sizeof(struct tpacket_stats);
+               }
                spin_lock_bh(&sk->sk_receive_queue.lock);
-               st = po->stats;
+               if (po->tp_version == TPACKET_V3) {
+                       memcpy(&st_u.stats3, &po->stats,
+                       sizeof(struct tpacket_stats));
+                       st_u.stats3.tp_freeze_q_cnt =
+                       po->stats_u.stats3.tp_freeze_q_cnt;
+                       st_u.stats3.tp_packets += po->stats.tp_drops;
+                       data = &st_u.stats3;
+               } else {
+                       st = po->stats;
+                       st.tp_packets += st.tp_drops;
+                       data = &st;
+               }
                memset(&po->stats, 0, sizeof(st));
                spin_unlock_bh(&sk->sk_receive_queue.lock);
-               st.tp_packets += st.tp_drops;
-
-               data = &st;
                break;
        case PACKET_AUXDATA:
                if (len > sizeof(int))
@@ -2485,6 +3307,9 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
                case TPACKET_V2:
                        val = sizeof(struct tpacket2_hdr);
                        break;
+               case TPACKET_V3:
+                       val = sizeof(struct tpacket3_hdr);
+                       break;
                default:
                        return -EINVAL;
                }
@@ -2641,7 +3466,8 @@ static unsigned int packet_poll(struct file *file, struct socket *sock,
 
        spin_lock_bh(&sk->sk_receive_queue.lock);
        if (po->rx_ring.pg_vec) {
-               if (!packet_previous_frame(po, &po->rx_ring, TP_STATUS_KERNEL))
+               if (!packet_previous_rx_frame(po, &po->rx_ring,
+                       TP_STATUS_KERNEL))
                        mask |= POLLIN | POLLRDNORM;
        }
        spin_unlock_bh(&sk->sk_receive_queue.lock);
@@ -2760,7 +3586,7 @@ out_free_pgvec:
        goto out;
 }
 
-static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
+static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                int closing, int tx_ring)
 {
        struct pgv *pg_vec = NULL;
@@ -2769,7 +3595,15 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
        struct packet_ring_buffer *rb;
        struct sk_buff_head *rb_queue;
        __be16 num;
-       int err;
+       int err = -EINVAL;
+       /* Added to avoid minimal code churn */
+       struct tpacket_req *req = &req_u->req;
+
+       /* Opening a Tx-ring is NOT supported in TPACKET_V3 */
+       if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) {
+               WARN(1, "Tx-ring is not supported.\n");
+               goto out;
+       }
 
        rb = tx_ring ? &po->tx_ring : &po->rx_ring;
        rb_queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue;
@@ -2795,6 +3629,9 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
                case TPACKET_V2:
                        po->tp_hdrlen = TPACKET2_HDRLEN;
                        break;
+               case TPACKET_V3:
+                       po->tp_hdrlen = TPACKET3_HDRLEN;
+                       break;
                }
 
                err = -EINVAL;
@@ -2820,6 +3657,17 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
                pg_vec = alloc_pg_vec(req, order);
                if (unlikely(!pg_vec))
                        goto out;
+               switch (po->tp_version) {
+               case TPACKET_V3:
+               /* Transmit path is not supported. We checked
+                * it above but just being paranoid
+                */
+                       if (!tx_ring)
+                               init_prb_bdqc(po, rb, pg_vec, req_u, tx_ring);
+                               break;
+               default:
+                       break;
+               }
        }
        /* Done */
        else {
@@ -2872,7 +3720,11 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
                register_prot_hook(sk);
        }
        spin_unlock(&po->bind_lock);
-
+       if (closing && (po->tp_version > TPACKET_V2)) {
+               /* Because we don't support block-based V3 on tx-ring */
+               if (!tx_ring)
+                       prb_shutdown_retire_blk_timer(po, tx_ring, rb_queue);
+       }
        release_sock(sk);
 
        if (pg_vec)
index c6fffd9..bf10ea8 100644 (file)
@@ -480,7 +480,7 @@ int __init_or_module phonet_proto_register(unsigned int protocol,
        if (proto_tab[protocol])
                err = -EBUSY;
        else
-               rcu_assign_pointer(proto_tab[protocol], pp);
+               RCU_INIT_POINTER(proto_tab[protocol], pp);
        mutex_unlock(&proto_tab_lock);
 
        return err;
@@ -491,7 +491,7 @@ void phonet_proto_unregister(unsigned int protocol, struct phonet_protocol *pp)
 {
        mutex_lock(&proto_tab_lock);
        BUG_ON(proto_tab[protocol] != pp);
-       rcu_assign_pointer(proto_tab[protocol], NULL);
+       RCU_INIT_POINTER(proto_tab[protocol], NULL);
        mutex_unlock(&proto_tab_lock);
        synchronize_rcu();
        proto_unregister(pp->prot);
index d2df8f3..c582761 100644 (file)
@@ -276,7 +276,7 @@ static void phonet_route_autodel(struct net_device *dev)
        mutex_lock(&pnn->routes.lock);
        for (i = 0; i < 64; i++)
                if (dev == pnn->routes.table[i]) {
-                       rcu_assign_pointer(pnn->routes.table[i], NULL);
+                       RCU_INIT_POINTER(pnn->routes.table[i], NULL);
                        set_bit(i, deleted);
                }
        mutex_unlock(&pnn->routes.lock);
@@ -390,7 +390,7 @@ int phonet_route_add(struct net_device *dev, u8 daddr)
        daddr = daddr >> 2;
        mutex_lock(&routes->lock);
        if (routes->table[daddr] == NULL) {
-               rcu_assign_pointer(routes->table[daddr], dev);
+               RCU_INIT_POINTER(routes->table[daddr], dev);
                dev_hold(dev);
                err = 0;
        }
@@ -406,7 +406,7 @@ int phonet_route_del(struct net_device *dev, u8 daddr)
        daddr = daddr >> 2;
        mutex_lock(&routes->lock);
        if (dev == routes->table[daddr])
-               rcu_assign_pointer(routes->table[daddr], NULL);
+               RCU_INIT_POINTER(routes->table[daddr], NULL);
        else
                dev = NULL;
        mutex_unlock(&routes->lock);
index ab07711..676d18d 100644 (file)
@@ -679,7 +679,7 @@ int pn_sock_bind_res(struct sock *sk, u8 res)
        mutex_lock(&resource_mutex);
        if (pnres.sk[res] == NULL) {
                sock_hold(sk);
-               rcu_assign_pointer(pnres.sk[res], sk);
+               RCU_INIT_POINTER(pnres.sk[res], sk);
                ret = 0;
        }
        mutex_unlock(&resource_mutex);
@@ -695,7 +695,7 @@ int pn_sock_unbind_res(struct sock *sk, u8 res)
 
        mutex_lock(&resource_mutex);
        if (pnres.sk[res] == sk) {
-               rcu_assign_pointer(pnres.sk[res], NULL);
+               RCU_INIT_POINTER(pnres.sk[res], NULL);
                ret = 0;
        }
        mutex_unlock(&resource_mutex);
@@ -714,7 +714,7 @@ void pn_sock_unbind_all_res(struct sock *sk)
        mutex_lock(&resource_mutex);
        for (res = 0; res < 256; res++) {
                if (pnres.sk[res] == sk) {
-                       rcu_assign_pointer(pnres.sk[res], NULL);
+                       RCU_INIT_POINTER(pnres.sk[res], NULL);
                        match++;
                }
        }
index 102fc21..e051398 100644 (file)
@@ -196,8 +196,7 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
 
        skb2->skb_iif = skb->dev->ifindex;
        skb2->dev = dev;
-       dev_queue_xmit(skb2);
-       err = 0;
+       err = dev_queue_xmit(skb2);
 
 out:
        if (err) {
index 2a318f2..b5d56a2 100644 (file)
@@ -112,7 +112,7 @@ static struct sk_buff *prio_dequeue(struct Qdisc *sch)
 
        for (prio = 0; prio < q->bands; prio++) {
                struct Qdisc *qdisc = q->queues[prio];
-               struct sk_buff *skb = qdisc->dequeue(qdisc);
+               struct sk_buff *skb = qdisc_dequeue_peeked(qdisc);
                if (skb) {
                        qdisc_bstats_update(sch, skb);
                        sch->q.qlen--;
index 0a833d0..e83c272 100644 (file)
@@ -287,6 +287,12 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        u32 r, slot, salt, sfbhash;
        int ret = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
 
+       if (unlikely(sch->q.qlen >= q->limit)) {
+               sch->qstats.overlimits++;
+               q->stats.queuedrop++;
+               goto drop;
+       }
+
        if (q->rehash_interval > 0) {
                unsigned long limit = q->rehash_time + q->rehash_interval;
 
@@ -332,12 +338,9 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        slot ^= 1;
        sfb_skb_cb(skb)->hashes[slot] = 0;
 
-       if (unlikely(minqlen >= q->max || sch->q.qlen >= q->limit)) {
+       if (unlikely(minqlen >= q->max)) {
                sch->qstats.overlimits++;
-               if (minqlen >= q->max)
-                       q->stats.bucketdrop++;
-               else
-                       q->stats.queuedrop++;
+               q->stats.bucketdrop++;
                goto drop;
        }
 
index 4536ee6..4f5510e 100644 (file)
@@ -410,7 +410,12 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        /* Return Congestion Notification only if we dropped a packet
         * from this flow.
         */
-       return (qlen != slot->qlen) ? NET_XMIT_CN : NET_XMIT_SUCCESS;
+       if (qlen != slot->qlen)
+               return NET_XMIT_CN;
+
+       /* As we dropped a packet, better let upper stack know this */
+       qdisc_tree_decrease_qlen(sch, 1);
+       return NET_XMIT_SUCCESS;
 }
 
 static struct sk_buff *
index dc16b90..152b5b3 100644 (file)
@@ -282,6 +282,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
                asoc->peer.asconf_capable = 1;
        asoc->asconf_addr_del_pending = NULL;
        asoc->src_out_of_asoc_ok = 0;
+       asoc->new_transport = NULL;
 
        /* Create an input queue.  */
        sctp_inq_init(&asoc->base.inqueue);
index a6d27bf..14c2b06 100644 (file)
@@ -917,6 +917,8 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
                 * current cwnd).
                 */
                if (!list_empty(&q->retransmit)) {
+                       if (asoc->peer.retran_path->state == SCTP_UNCONFIRMED)
+                               goto sctp_flush_out;
                        if (transport == asoc->peer.retran_path)
                                goto retran;
 
@@ -989,6 +991,8 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
                            ((new_transport->state == SCTP_INACTIVE) ||
                             (new_transport->state == SCTP_UNCONFIRMED)))
                                new_transport = asoc->peer.active_path;
+                       if (new_transport->state == SCTP_UNCONFIRMED)
+                               continue;
 
                        /* Change packets if necessary.  */
                        if (new_transport != transport) {
index 81db4e3..0121e0a 100644 (file)
@@ -3015,6 +3015,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
                /* Start the heartbeat timer. */
                if (!mod_timer(&peer->hb_timer, sctp_transport_timeout(peer)))
                        sctp_transport_hold(peer);
+               asoc->new_transport = peer;
                break;
        case SCTP_PARAM_DEL_IP:
                /* ADDIP 4.3 D7) If a request is received to delete the
index 49b847b..73d14fc 100644 (file)
@@ -3612,6 +3612,11 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
         */
        asconf_ack->dest = chunk->source;
        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(asconf_ack));
+       if (asoc->new_transport) {
+               sctp_sf_heartbeat(ep, asoc, type, asoc->new_transport,
+                    commands);
+               ((struct sctp_association *)asoc)->new_transport = NULL;
+       }
 
        return SCTP_DISPOSITION_CONSUME;
 }
index b1cbbcd..2517e11 100644 (file)
@@ -1871,8 +1871,14 @@ SYSCALL_DEFINE2(shutdown, int, fd, int, how)
 #define COMPAT_NAMELEN(msg)    COMPAT_MSG(msg, msg_namelen)
 #define COMPAT_FLAGS(msg)      COMPAT_MSG(msg, msg_flags)
 
+struct used_address {
+       struct sockaddr_storage name;
+       unsigned int name_len;
+};
+
 static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
-                        struct msghdr *msg_sys, unsigned flags, int nosec)
+                        struct msghdr *msg_sys, unsigned flags,
+                        struct used_address *used_address)
 {
        struct compat_msghdr __user *msg_compat =
            (struct compat_msghdr __user *)msg;
@@ -1953,8 +1959,28 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
 
        if (sock->file->f_flags & O_NONBLOCK)
                msg_sys->msg_flags |= MSG_DONTWAIT;
-       err = (nosec ? sock_sendmsg_nosec : sock_sendmsg)(sock, msg_sys,
-                                                         total_len);
+       /*
+        * If this is sendmmsg() and current destination address is same as
+        * previously succeeded address, omit asking LSM's decision.
+        * used_address->name_len is initialized to UINT_MAX so that the first
+        * destination address never matches.
+        */
+       if (used_address && used_address->name_len == msg_sys->msg_namelen &&
+           !memcmp(&used_address->name, msg->msg_name,
+                   used_address->name_len)) {
+               err = sock_sendmsg_nosec(sock, msg_sys, total_len);
+               goto out_freectl;
+       }
+       err = sock_sendmsg(sock, msg_sys, total_len);
+       /*
+        * If this is sendmmsg() and sending to current destination address was
+        * successful, remember it.
+        */
+       if (used_address && err >= 0) {
+               used_address->name_len = msg_sys->msg_namelen;
+               memcpy(&used_address->name, msg->msg_name,
+                      used_address->name_len);
+       }
 
 out_freectl:
        if (ctl_buf != ctl)
@@ -1979,7 +2005,7 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags)
        if (!sock)
                goto out;
 
-       err = __sys_sendmsg(sock, msg, &msg_sys, flags, 0);
+       err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
 
        fput_light(sock->file, fput_needed);
 out:
@@ -1998,6 +2024,10 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
        struct mmsghdr __user *entry;
        struct compat_mmsghdr __user *compat_entry;
        struct msghdr msg_sys;
+       struct used_address used_address;
+
+       if (vlen > UIO_MAXIOV)
+               vlen = UIO_MAXIOV;
 
        datagrams = 0;
 
@@ -2005,27 +2035,22 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
        if (!sock)
                return err;
 
-       err = sock_error(sock->sk);
-       if (err)
-               goto out_put;
-
+       used_address.name_len = UINT_MAX;
        entry = mmsg;
        compat_entry = (struct compat_mmsghdr __user *)mmsg;
+       err = 0;
 
        while (datagrams < vlen) {
-               /*
-                * No need to ask LSM for more than the first datagram.
-                */
                if (MSG_CMSG_COMPAT & flags) {
                        err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
-                                           &msg_sys, flags, datagrams);
+                                           &msg_sys, flags, &used_address);
                        if (err < 0)
                                break;
                        err = __put_user(err, &compat_entry->msg_len);
                        ++compat_entry;
                } else {
                        err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
-                                           &msg_sys, flags, datagrams);
+                                           &msg_sys, flags, &used_address);
                        if (err < 0)
                                break;
                        err = put_user(err, &entry->msg_len);
@@ -2037,29 +2062,11 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
                ++datagrams;
        }
 
-out_put:
        fput_light(sock->file, fput_needed);
 
-       if (err == 0)
-               return datagrams;
-
-       if (datagrams != 0) {
-               /*
-                * We may send less entries than requested (vlen) if the
-                * sock is non blocking...
-                */
-               if (err != -EAGAIN) {
-                       /*
-                        * ... or if sendmsg returns an error after we
-                        * send some datagrams, where we record the
-                        * error to return on the next call or if the
-                        * app asks about it using getsockopt(SO_ERROR).
-                        */
-                       sock->sk->sk_err = -err;
-               }
-
+       /* We only return an error if no datagrams were able to be sent */
+       if (datagrams != 0)
                return datagrams;
-       }
 
        return err;
 }
@@ -2463,7 +2470,7 @@ int sock_register(const struct net_proto_family *ops)
                                      lockdep_is_held(&net_family_lock)))
                err = -EEXIST;
        else {
-               rcu_assign_pointer(net_families[ops->family], ops);
+               RCU_INIT_POINTER(net_families[ops->family], ops);
                err = 0;
        }
        spin_unlock(&net_family_lock);
@@ -2491,7 +2498,7 @@ void sock_unregister(int family)
        BUG_ON(family < 0 || family >= NPROTO);
 
        spin_lock(&net_family_lock);
-       rcu_assign_pointer(net_families[family], NULL);
+       RCU_INIT_POINTER(net_families[family], NULL);
        spin_unlock(&net_family_lock);
 
        synchronize_rcu();
index 364eb45..d413275 100644 (file)
@@ -122,7 +122,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
        if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags))
                return;
        gss_get_ctx(ctx);
-       rcu_assign_pointer(gss_cred->gc_ctx, ctx);
+       RCU_INIT_POINTER(gss_cred->gc_ctx, ctx);
        set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
        smp_mb__before_clear_bit();
        clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
@@ -970,7 +970,7 @@ gss_destroy_nullcred(struct rpc_cred *cred)
        struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
        struct gss_cl_ctx *ctx = gss_cred->gc_ctx;
 
-       rcu_assign_pointer(gss_cred->gc_ctx, NULL);
+       RCU_INIT_POINTER(gss_cred->gc_ctx, NULL);
        call_rcu(&cred->cr_rcu, gss_free_cred_callback);
        if (ctx)
                gss_put_ctx(ctx);
index 9b6a4d1..f4385e4 100644 (file)
@@ -187,6 +187,7 @@ EXPORT_SYMBOL_GPL(xprt_load_transport);
 /**
  * xprt_reserve_xprt - serialize write access to transports
  * @task: task that is requesting access to the transport
+ * @xprt: pointer to the target transport
  *
  * This prevents mixing the payload of separate requests, and prevents
  * transport connects from colliding with writes.  No congestion control
index ec68e1c..e6d9d10 100644 (file)
@@ -1378,11 +1378,17 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
        return max_level;
 }
 
-static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
+static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb,
+                          bool send_fds, bool ref)
 {
        int err = 0;
-       UNIXCB(skb).pid  = get_pid(scm->pid);
-       UNIXCB(skb).cred = get_cred(scm->cred);
+       if (ref) {
+               UNIXCB(skb).pid  = get_pid(scm->pid);
+               UNIXCB(skb).cred = get_cred(scm->cred);
+       } else {
+               UNIXCB(skb).pid  = scm->pid;
+               UNIXCB(skb).cred = scm->cred;
+       }
        UNIXCB(skb).fp = NULL;
        if (scm->fp && send_fds)
                err = unix_attach_fds(scm, skb);
@@ -1407,7 +1413,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
        int namelen = 0; /* fake GCC */
        int err;
        unsigned hash;
-       struct sk_buff *skb;
+       struct sk_buff *skb = NULL;
        long timeo;
        struct scm_cookie tmp_scm;
        int max_level;
@@ -1448,7 +1454,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
        if (skb == NULL)
                goto out;
 
-       err = unix_scm_to_skb(siocb->scm, skb, true);
+       err = unix_scm_to_skb(siocb->scm, skb, true, false);
        if (err < 0)
                goto out_free;
        max_level = err + 1;
@@ -1544,7 +1550,7 @@ restart:
        unix_state_unlock(other);
        other->sk_data_ready(other, len);
        sock_put(other);
-       scm_destroy(siocb->scm);
+       scm_release(siocb->scm);
        return len;
 
 out_unlock:
@@ -1554,7 +1560,8 @@ out_free:
 out:
        if (other)
                sock_put(other);
-       scm_destroy(siocb->scm);
+       if (skb == NULL)
+               scm_destroy(siocb->scm);
        return err;
 }
 
@@ -1566,7 +1573,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
        struct sock *sk = sock->sk;
        struct sock *other = NULL;
        int err, size;
-       struct sk_buff *skb;
+       struct sk_buff *skb = NULL;
        int sent = 0;
        struct scm_cookie tmp_scm;
        bool fds_sent = false;
@@ -1631,11 +1638,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
                size = min_t(int, size, skb_tailroom(skb));
 
 
-               /* Only send the fds in the first buffer */
-               err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
+               /* Only send the fds and no ref to pid in the first buffer */
+               err = unix_scm_to_skb(siocb->scm, skb, !fds_sent, fds_sent);
                if (err < 0) {
                        kfree_skb(skb);
-                       goto out_err;
+                       goto out;
                }
                max_level = err + 1;
                fds_sent = true;
@@ -1643,7 +1650,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
                err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
                if (err) {
                        kfree_skb(skb);
-                       goto out_err;
+                       goto out;
                }
 
                unix_state_lock(other);
@@ -1660,7 +1667,10 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
                sent += size;
        }
 
-       scm_destroy(siocb->scm);
+       if (skb)
+               scm_release(siocb->scm);
+       else
+               scm_destroy(siocb->scm);
        siocb->scm = NULL;
 
        return sent;
@@ -1673,7 +1683,9 @@ pipe_err:
                send_sig(SIGPIPE, current, 0);
        err = -EPIPE;
 out_err:
-       scm_destroy(siocb->scm);
+       if (skb == NULL)
+               scm_destroy(siocb->scm);
+out:
        siocb->scm = NULL;
        return sent ? : err;
 }
@@ -1777,7 +1789,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
                siocb->scm = &tmp_scm;
                memset(&tmp_scm, 0, sizeof(tmp_scm));
        }
-       scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
+       scm_set_cred_noref(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
        unix_set_secdata(siocb->scm, skb);
 
        if (!(flags & MSG_PEEK)) {
@@ -1939,7 +1951,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                        }
                } else {
                        /* Copy credentials */
-                       scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
+                       scm_set_cred_noref(siocb->scm, UNIXCB(skb).pid,
+                                          UNIXCB(skb).cred);
                        check_creds = 1;
                }
 
index 58064d9..791ab2e 100644 (file)
@@ -462,8 +462,8 @@ static struct xfrm_algo_desc ealg_list[] = {
        .desc = {
                .sadb_alg_id = SADB_X_EALG_AESCTR,
                .sadb_alg_ivlen = 8,
-               .sadb_alg_minbits = 128,
-               .sadb_alg_maxbits = 256
+               .sadb_alg_minbits = 160,
+               .sadb_alg_maxbits = 288
        }
 },
 };
index fc91ad7..f781b9a 100644 (file)
@@ -70,26 +70,29 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
 
        while ((scratch += len, dlen -= len) > 0) {
                skb_frag_t *frag;
+               struct page *page;
 
                err = -EMSGSIZE;
                if (WARN_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS))
                        goto out;
 
                frag = skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags;
-               frag->page = alloc_page(GFP_ATOMIC);
+               page = alloc_page(GFP_ATOMIC);
 
                err = -ENOMEM;
-               if (!frag->page)
+               if (!page)
                        goto out;
 
+               __skb_frag_set_page(frag, page);
+
                len = PAGE_SIZE;
                if (dlen < len)
                        len = dlen;
 
-               memcpy(page_address(frag->page), scratch, len);
-
                frag->page_offset = 0;
                frag->size = len;
+               memcpy(skb_frag_address(frag), scratch, len);
+
                skb->truesize += len;
                skb->data_len += len;
                skb->len += len;
index 0256b8a..d0a42df 100644 (file)
@@ -2927,7 +2927,7 @@ static int __net_init xfrm_user_net_init(struct net *net)
        if (nlsk == NULL)
                return -ENOMEM;
        net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */
-       rcu_assign_pointer(net->xfrm.nlsk, nlsk);
+       RCU_INIT_POINTER(net->xfrm.nlsk, nlsk);
        return 0;
 }
 
@@ -2935,7 +2935,7 @@ static void __net_exit xfrm_user_net_exit(struct list_head *net_exit_list)
 {
        struct net *net;
        list_for_each_entry(net, net_exit_list, exit_list)
-               rcu_assign_pointer(net->xfrm.nlsk, NULL);
+               RCU_INIT_POINTER(net->xfrm.nlsk, NULL);
        synchronize_net();
        list_for_each_entry(net, net_exit_list, exit_list)
                netlink_kernel_release(net->xfrm.nlsk_stash);
index 0b4276c..82d2eb2 100644 (file)
@@ -170,8 +170,8 @@ mconf-objs     := mconf.o zconf.tab.o $(lxdialog)
 nconf-objs     := nconf.o zconf.tab.o nconf.gui.o
 kxgettext-objs := kxgettext.o zconf.tab.o
 qconf-cxxobjs  := qconf.o
-qconf-objs     := kconfig_load.o zconf.tab.o
-gconf-objs     := gconf.o kconfig_load.o zconf.tab.o
+qconf-objs     := zconf.tab.o
+gconf-objs     := gconf.o zconf.tab.o
 
 hostprogs-y := conf
 
@@ -203,7 +203,7 @@ ifeq ($(gconf-target),1)
        hostprogs-y += gconf
 endif
 
-clean-files    := lkc_defs.h qconf.moc .tmp_qtcheck .tmp_gtkcheck
+clean-files    := qconf.moc .tmp_qtcheck .tmp_gtkcheck
 clean-files    += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h
 clean-files     += mconf qconf gconf nconf
 clean-files     += config.pot linux.pot
@@ -226,12 +226,12 @@ HOSTCFLAGS_zconf.tab.o    := -I$(src)
 LEX_PREFIX_zconf       := zconf
 YACC_PREFIX_zconf      := zconf
 
-HOSTLOADLIBES_qconf    = $(KC_QT_LIBS) -ldl
-HOSTCXXFLAGS_qconf.o   = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK
+HOSTLOADLIBES_qconf    = $(KC_QT_LIBS)
+HOSTCXXFLAGS_qconf.o   = $(KC_QT_CFLAGS)
 
-HOSTLOADLIBES_gconf    = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` -ldl
+HOSTLOADLIBES_gconf    = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`
 HOSTCFLAGS_gconf.o     = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
-                          -D LKC_DIRECT_LINK
+                          -Wno-missing-prototypes
 
 HOSTLOADLIBES_mconf   = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
 
@@ -321,18 +321,11 @@ endif
 
 $(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c
 
-$(obj)/kconfig_load.o: $(obj)/lkc_defs.h
-
-$(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h
-
-$(obj)/gconf.o: $(obj)/lkc_defs.h
+$(obj)/qconf.o: $(obj)/qconf.moc
 
 $(obj)/%.moc: $(src)/%.h
        $(KC_QT_MOC) -i $< -o $@
 
-$(obj)/lkc_defs.h: $(src)/lkc_proto.h
-       $(Q)sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
-
 # Extract gconf menu items for I18N support
 $(obj)/gconf.glade.h: $(obj)/gconf.glade
        $(Q)intltool-extract --type=gettext/glade --srcdir=$(srctree) \
index 006ad81..f208f90 100644 (file)
 #include <sys/stat.h>
 #include <sys/time.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 static void conf(struct menu *menu);
 static void check_conf(struct menu *menu);
+static void xfgets(char *str, int size, FILE *in);
 
 enum input_mode {
        oldaskconfig,
@@ -35,8 +35,6 @@ enum input_mode {
        oldnoconfig,
 } input_mode = oldaskconfig;
 
-char *defconfig_file;
-
 static int indent = 1;
 static int valid_stdin = 1;
 static int sync_kconfig;
@@ -106,6 +104,7 @@ static int conf_askvalue(struct symbol *sym, const char *def)
                        return 0;
                }
                check_stdin();
+               /* fall through */
        case oldaskconfig:
                fflush(stdout);
                xfgets(line, 128, stdin);
@@ -150,6 +149,7 @@ static int conf_string(struct menu *menu)
                                def = NULL;
                                break;
                        }
+                       /* fall through */
                default:
                        line[strlen(line)-1] = 0;
                        def = line;
@@ -304,6 +304,7 @@ static int conf_choice(struct menu *menu)
                                break;
                        }
                        check_stdin();
+                       /* fall through */
                case oldaskconfig:
                        fflush(stdout);
                        xfgets(line, 128, stdin);
@@ -369,6 +370,7 @@ static void conf(struct menu *menu)
                                check_conf(menu);
                                return;
                        }
+                       /* fall through */
                case P_COMMENT:
                        prompt = menu_get_prompt(menu);
                        if (prompt)
@@ -456,10 +458,30 @@ static struct option long_opts[] = {
        {NULL, 0, NULL, 0}
 };
 
+static void conf_usage(const char *progname)
+{
+
+       printf("Usage: %s [option] <kconfig-file>\n", progname);
+       printf("[option] is _one_ of the following:\n");
+       printf("  --listnewconfig         List new options\n");
+       printf("  --oldaskconfig          Start a new configuration using a line-oriented program\n");
+       printf("  --oldconfig             Update a configuration using a provided .config as base\n");
+       printf("  --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\n");
+       printf("  --oldnoconfig           Same as silentoldconfig but set new symbols to no\n");
+       printf("  --defconfig <file>      New config with default defined in <file>\n");
+       printf("  --savedefconfig <file>  Save the minimal current configuration to <file>\n");
+       printf("  --allnoconfig           New config where all options are answered with no\n");
+       printf("  --allyesconfig          New config where all options are answered with yes\n");
+       printf("  --allmodconfig          New config where all options are answered with mod\n");
+       printf("  --alldefconfig          New config with all symbols set to default\n");
+       printf("  --randconfig            New config with random answer to all options\n");
+}
+
 int main(int ac, char **av)
 {
+       const char *progname = av[0];
        int opt;
-       const char *name;
+       const char *name, *defconfig_file = NULL /* gcc uninit */;
        struct stat tmpstat;
 
        setlocale(LC_ALL, "");
@@ -491,14 +513,24 @@ int main(int ac, char **av)
                        srand(seed);
                        break;
                }
+               case oldaskconfig:
+               case oldconfig:
+               case allnoconfig:
+               case allyesconfig:
+               case allmodconfig:
+               case alldefconfig:
+               case listnewconfig:
+               case oldnoconfig:
+                       break;
                case '?':
-                       fprintf(stderr, _("See README for usage info\n"));
+                       conf_usage(progname);
                        exit(1);
                        break;
                }
        }
        if (ac == optind) {
                printf(_("%s: Kconfig file missing\n"), av[0]);
+               conf_usage(progname);
                exit(1);
        }
        name = av[optind];
@@ -641,13 +673,11 @@ int main(int ac, char **av)
        }
        return 0;
 }
+
 /*
  * Helper function to facilitate fgets() by Jean Sacren.
  */
-void xfgets(str, size, in)
-       char *str;
-       int size;
-       FILE *in;
+void xfgets(char *str, int size, FILE *in)
 {
        if (fgets(str, size, in) == NULL)
                fprintf(stderr, "\nError in reading or end of file.\n");
index 2bafd9a..59b667c 100644 (file)
@@ -7,13 +7,13 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 static void conf_warning(const char *fmt, ...)
@@ -128,6 +128,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        sym->flags |= def_flags;
                        break;
                }
+               /* fall through */
        case S_BOOLEAN:
                if (p[0] == 'y') {
                        sym->def[def].tri = yes;
@@ -140,7 +141,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        break;
                }
                conf_warning("symbol value '%s' invalid for %s", p, sym->name);
-               break;
+               return 1;
        case S_OTHER:
                if (*p != '"') {
                        for (p2 = p; *p2 && !isspace(*p2); p2++)
@@ -148,6 +149,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        sym->type = S_STRING;
                        goto done;
                }
+               /* fall through */
        case S_STRING:
                if (*p++ != '"')
                        break;
@@ -162,6 +164,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        conf_warning("invalid string found");
                        return 1;
                }
+               /* fall through */
        case S_INT:
        case S_HEX:
        done:
@@ -237,6 +240,7 @@ load:
                case S_STRING:
                        if (sym->def[def].val)
                                free(sym->def[def].val);
+                       /* fall through */
                default:
                        sym->def[def].val = NULL;
                        sym->def[def].tri = no;
@@ -363,6 +367,7 @@ int conf_read(const char *name)
                                        break;
                                if (!sym_is_choice(sym))
                                        goto sym_ok;
+                               /* fall through */
                        default:
                                if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
                                        goto sym_ok;
@@ -417,64 +422,202 @@ int conf_read(const char *name)
        return 0;
 }
 
-/* Write a S_STRING */
-static void conf_write_string(bool headerfile, const char *name,
-                              const char *str, FILE *out)
+/*
+ * Kconfig configuration printer
+ *
+ * This printer is used when generating the resulting configuration after
+ * kconfig invocation and `defconfig' files. Unset symbol might be omitted by
+ * passing a non-NULL argument to the printer.
+ *
+ */
+static void
+kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
 {
-       int l;
-       if (headerfile)
-               fprintf(out, "#define %s%s \"", CONFIG_, name);
-       else
-               fprintf(out, "%s%s=\"", CONFIG_, name);
-
-       while (1) {
-               l = strcspn(str, "\"\\");
+
+       switch (sym->type) {
+       case S_BOOLEAN:
+       case S_TRISTATE:
+               if (*value == 'n') {
+                       bool skip_unset = (arg != NULL);
+
+                       if (!skip_unset)
+                               fprintf(fp, "# %s%s is not set\n",
+                                   CONFIG_, sym->name);
+                       return;
+               }
+               break;
+       default:
+               break;
+       }
+
+       fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value);
+}
+
+static void
+kconfig_print_comment(FILE *fp, const char *value, void *arg)
+{
+       const char *p = value;
+       size_t l;
+
+       for (;;) {
+               l = strcspn(p, "\n");
+               fprintf(fp, "#");
                if (l) {
-                       xfwrite(str, l, 1, out);
-                       str += l;
+                       fprintf(fp, " ");
+                       fwrite(p, l, 1, fp);
+                       p += l;
                }
-               if (!*str)
+               fprintf(fp, "\n");
+               if (*p++ == '\0')
                        break;
-               fprintf(out, "\\%c", *str++);
        }
-       fputs("\"\n", out);
 }
 
-static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no)
+static struct conf_printer kconfig_printer_cb =
+{
+       .print_symbol = kconfig_print_symbol,
+       .print_comment = kconfig_print_comment,
+};
+
+/*
+ * Header printer
+ *
+ * This printer is used when generating the `include/generated/autoconf.h' file.
+ */
+static void
+header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
 {
-       const char *str;
 
        switch (sym->type) {
        case S_BOOLEAN:
-       case S_TRISTATE:
-               switch (sym_get_tristate_value(sym)) {
-               case no:
-                       if (write_no)
-                               fprintf(out, "# %s%s is not set\n",
-                                   CONFIG_, sym->name);
-                       break;
-               case mod:
-                       fprintf(out, "%s%s=m\n", CONFIG_, sym->name);
-                       break;
-               case yes:
-                       fprintf(out, "%s%s=y\n", CONFIG_, sym->name);
+       case S_TRISTATE: {
+               const char *suffix = "";
+
+               switch (*value) {
+               case 'n':
                        break;
+               case 'm':
+                       suffix = "_MODULE";
+                       /* fall through */
+               default:
+                       fprintf(fp, "#define %s%s%s 1\n",
+                           CONFIG_, sym->name, suffix);
                }
+               /*
+                * Generate the __enabled_CONFIG_* and
+                * __enabled_CONFIG_*_MODULE macros for use by the
+                * IS_{ENABLED,BUILTIN,MODULE} macros. The _MODULE variant is
+                * generated even for booleans so that the IS_ENABLED() macro
+                * works.
+                */
+               fprintf(fp, "#define __enabled_" CONFIG_ "%s %d\n",
+                               sym->name, (*value == 'y'));
+               fprintf(fp, "#define __enabled_" CONFIG_ "%s_MODULE %d\n",
+                               sym->name, (*value == 'm'));
                break;
-       case S_STRING:
-               conf_write_string(false, sym->name, sym_get_string_value(sym), out);
+       }
+       case S_HEX: {
+               const char *prefix = "";
+
+               if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X'))
+                       prefix = "0x";
+               fprintf(fp, "#define %s%s %s%s\n",
+                   CONFIG_, sym->name, prefix, value);
                break;
-       case S_HEX:
+       }
+       case S_STRING:
        case S_INT:
-               str = sym_get_string_value(sym);
-               fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str);
+               fprintf(fp, "#define %s%s %s\n",
+                   CONFIG_, sym->name, value);
+               break;
+       default:
                break;
+       }
+
+}
+
+static void
+header_print_comment(FILE *fp, const char *value, void *arg)
+{
+       const char *p = value;
+       size_t l;
+
+       fprintf(fp, "/*\n");
+       for (;;) {
+               l = strcspn(p, "\n");
+               fprintf(fp, " *");
+               if (l) {
+                       fprintf(fp, " ");
+                       fwrite(p, l, 1, fp);
+                       p += l;
+               }
+               fprintf(fp, "\n");
+               if (*p++ == '\0')
+                       break;
+       }
+       fprintf(fp, " */\n");
+}
+
+static struct conf_printer header_printer_cb =
+{
+       .print_symbol = header_print_symbol,
+       .print_comment = header_print_comment,
+};
+
+/*
+ * Tristate printer
+ *
+ * This printer is used when generating the `include/config/tristate.conf' file.
+ */
+static void
+tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+       if (sym->type == S_TRISTATE && *value != 'n')
+               fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value));
+}
+
+static struct conf_printer tristate_printer_cb =
+{
+       .print_symbol = tristate_print_symbol,
+       .print_comment = kconfig_print_comment,
+};
+
+static void conf_write_symbol(FILE *fp, struct symbol *sym,
+                             struct conf_printer *printer, void *printer_arg)
+{
+       const char *str;
+
+       switch (sym->type) {
        case S_OTHER:
        case S_UNKNOWN:
                break;
+       case S_STRING:
+               str = sym_get_string_value(sym);
+               str = sym_escape_string_value(str);
+               printer->print_symbol(fp, sym, str, printer_arg);
+               free((void *)str);
+               break;
+       default:
+               str = sym_get_string_value(sym);
+               printer->print_symbol(fp, sym, str, printer_arg);
        }
 }
 
+static void
+conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg)
+{
+       char buf[256];
+
+       snprintf(buf, sizeof(buf),
+           "\n"
+           "Automatically generated file; DO NOT EDIT.\n"
+           "%s\n",
+           rootmenu.prompt->text);
+
+       printer->print_comment(fp, buf, printer_arg);
+}
+
 /*
  * Write out a minimal config.
  * All values that has default values are skipped as this is redundant.
@@ -531,7 +674,7 @@ int conf_write_defconfig(const char *filename)
                                                goto next_menu;
                                }
                        }
-                       conf_write_symbol(sym, out, true);
+                       conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
                }
 next_menu:
                if (menu->list != NULL) {
@@ -596,11 +739,7 @@ int conf_write(const char *name)
        if (!out)
                return 1;
 
-       fprintf(out, _("#\n"
-                      "# Automatically generated make config: don't edit\n"
-                      "# %s\n"
-                      "#\n"),
-                    rootmenu.prompt->text);
+       conf_write_heading(out, &kconfig_printer_cb, NULL);
 
        if (!conf_get_changed())
                sym_clear_all_valid();
@@ -621,8 +760,8 @@ int conf_write(const char *name)
                        if (!(sym->flags & SYMBOL_WRITE))
                                goto next;
                        sym->flags &= ~SYMBOL_WRITE;
-                       /* Write config symbol to file */
-                       conf_write_symbol(sym, out, true);
+
+                       conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
                }
 
 next:
@@ -771,7 +910,6 @@ out:
 int conf_write_autoconf(void)
 {
        struct symbol *sym;
-       const char *str;
        const char *name;
        FILE *out, *tristate, *out_h;
        int i;
@@ -800,68 +938,23 @@ int conf_write_autoconf(void)
                return 1;
        }
 
-       fprintf(out, "#\n"
-                    "# Automatically generated make config: don't edit\n"
-                    "# %s\n"
-                    "#\n",
-                    rootmenu.prompt->text);
-       fprintf(tristate, "#\n"
-                         "# Automatically generated - do not edit\n"
-                         "\n");
-       fprintf(out_h, "/*\n"
-                      " * Automatically generated C config: don't edit\n"
-                      " * %s\n"
-                      " */\n",
-                      rootmenu.prompt->text);
+       conf_write_heading(out, &kconfig_printer_cb, NULL);
+
+       conf_write_heading(tristate, &tristate_printer_cb, NULL);
+
+       conf_write_heading(out_h, &header_printer_cb, NULL);
 
        for_all_symbols(i, sym) {
                sym_calc_value(sym);
                if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
                        continue;
 
-               /* write symbol to config file */
-               conf_write_symbol(sym, out, false);
+               /* write symbol to auto.conf, tristate and header files */
+               conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
 
-               /* update autoconf and tristate files */
-               switch (sym->type) {
-               case S_BOOLEAN:
-               case S_TRISTATE:
-                       switch (sym_get_tristate_value(sym)) {
-                       case no:
-                               break;
-                       case mod:
-                               fprintf(tristate, "%s%s=M\n",
-                                   CONFIG_, sym->name);
-                               fprintf(out_h, "#define %s%s_MODULE 1\n",
-                                   CONFIG_, sym->name);
-                               break;
-                       case yes:
-                               if (sym->type == S_TRISTATE)
-                                       fprintf(tristate,"%s%s=Y\n",
-                                           CONFIG_, sym->name);
-                               fprintf(out_h, "#define %s%s 1\n",
-                                   CONFIG_, sym->name);
-                               break;
-                       }
-                       break;
-               case S_STRING:
-                       conf_write_string(true, sym->name, sym_get_string_value(sym), out_h);
-                       break;
-               case S_HEX:
-                       str = sym_get_string_value(sym);
-                       if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
-                               fprintf(out_h, "#define %s%s 0x%s\n",
-                                   CONFIG_, sym->name, str);
-                               break;
-                       }
-               case S_INT:
-                       str = sym_get_string_value(sym);
-                       fprintf(out_h, "#define %s%s %s\n",
-                           CONFIG_, sym->name, str);
-                       break;
-               default:
-                       break;
-               }
+               conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
+
+               conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
        }
        fclose(out);
        fclose(tristate);
index 0010034..290ce41 100644 (file)
@@ -7,15 +7,13 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 #define DEBUG_EXPR     0
 
 struct expr *expr_alloc_symbol(struct symbol *sym)
 {
-       struct expr *e = malloc(sizeof(*e));
-       memset(e, 0, sizeof(*e));
+       struct expr *e = calloc(1, sizeof(*e));
        e->type = E_SYMBOL;
        e->left.sym = sym;
        return e;
@@ -23,8 +21,7 @@ struct expr *expr_alloc_symbol(struct symbol *sym)
 
 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
 {
-       struct expr *e = malloc(sizeof(*e));
-       memset(e, 0, sizeof(*e));
+       struct expr *e = calloc(1, sizeof(*e));
        e->type = type;
        e->left.expr = ce;
        return e;
@@ -32,8 +29,7 @@ struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
 
 struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
 {
-       struct expr *e = malloc(sizeof(*e));
-       memset(e, 0, sizeof(*e));
+       struct expr *e = calloc(1, sizeof(*e));
        e->type = type;
        e->left.expr = e1;
        e->right.expr = e2;
@@ -42,8 +38,7 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e
 
 struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
 {
-       struct expr *e = malloc(sizeof(*e));
-       memset(e, 0, sizeof(*e));
+       struct expr *e = calloc(1, sizeof(*e));
        e->type = type;
        e->left.sym = s1;
        e->right.sym = s2;
index 16bfae2..80fce57 100644 (file)
@@ -172,8 +172,6 @@ struct menu {
 #define MENU_CHANGED           0x0001
 #define MENU_ROOT              0x0002
 
-#ifndef SWIG
-
 extern struct file *file_list;
 extern struct file *current_file;
 struct file *lookup_file(const char *name);
@@ -218,7 +216,6 @@ static inline int expr_is_no(struct expr *e)
 {
        return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
 }
-#endif
 
 #ifdef __cplusplus
 }
index a11d5f7..9f44380 100644 (file)
@@ -285,8 +285,6 @@ void init_left_tree(void)
 static void renderer_edited(GtkCellRendererText * cell,
                            const gchar * path_string,
                            const gchar * new_text, gpointer user_data);
-static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
-                            gchar * arg1, gpointer user_data);
 
 void init_right_tree(void)
 {
@@ -320,8 +318,6 @@ void init_right_tree(void)
                                            "inconsistent", COL_BTNINC,
                                            "visible", COL_BTNVIS,
                                            "radio", COL_BTNRAD, NULL);
-       /*g_signal_connect(G_OBJECT(renderer), "toggled",
-          G_CALLBACK(renderer_toggled), NULL); */
        renderer = gtk_cell_renderer_text_new();
        gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
                                        renderer, FALSE);
@@ -888,35 +884,6 @@ static void toggle_sym_value(struct menu *menu)
                display_tree_part();    //fixme: keep exp/coll
 }
 
-static void renderer_toggled(GtkCellRendererToggle * cell,
-                            gchar * path_string, gpointer user_data)
-{
-       GtkTreePath *path, *sel_path = NULL;
-       GtkTreeIter iter, sel_iter;
-       GtkTreeSelection *sel;
-       struct menu *menu;
-
-       path = gtk_tree_path_new_from_string(path_string);
-       if (!gtk_tree_model_get_iter(model2, &iter, path))
-               return;
-
-       sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
-       if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
-               sel_path = gtk_tree_model_get_path(model2, &sel_iter);
-       if (!sel_path)
-               goto out1;
-       if (gtk_tree_path_compare(path, sel_path))
-               goto out2;
-
-       gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
-       toggle_sym_value(menu);
-
-      out2:
-       gtk_tree_path_free(sel_path);
-      out1:
-       gtk_tree_path_free(path);
-}
-
 static gint column2index(GtkTreeViewColumn * column)
 {
        gint i;
@@ -1172,6 +1139,7 @@ static gchar **fill_row(struct menu *menu)
                        row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
                if (sym_is_choice(sym))
                        break;
+               /* fall through */
        case S_TRISTATE:
                val = sym_get_tristate_value(sym);
                switch (val) {
@@ -1506,10 +1474,6 @@ int main(int ac, char *av[])
        char *env;
        gchar *glade_file;
 
-#ifndef LKC_DIRECT_LINK
-       kconfig_load();
-#endif
-
        bindtextdomain(PACKAGE, LOCALEDIR);
        bind_textdomain_codeset(PACKAGE, "UTF-8");
        textdomain(PACKAGE);
diff --git a/scripts/kconfig/kconfig_load.c b/scripts/kconfig/kconfig_load.c
deleted file mode 100644 (file)
index dbdcaad..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <dlfcn.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "lkc.h"
-
-#define P(name,type,arg)       type (*name ## _p) arg
-#include "lkc_proto.h"
-#undef P
-
-void kconfig_load(void)
-{
-       void *handle;
-       char *error;
-
-       handle = dlopen("./libkconfig.so", RTLD_LAZY);
-       if (!handle) {
-               handle = dlopen("./scripts/kconfig/libkconfig.so", RTLD_LAZY);
-               if (!handle) {
-                       fprintf(stderr, "%s\n", dlerror());
-                       exit(1);
-               }
-       }
-
-#define P(name,type,arg)                       \
-{                                              \
-       name ## _p = dlsym(handle, #name);      \
-        if ((error = dlerror()))  {            \
-                fprintf(stderr, "%s\n", error);        \
-               exit(1);                        \
-       }                                       \
-}
-#include "lkc_proto.h"
-#undef P
-}
index e9d8e79..2858738 100644 (file)
@@ -7,7 +7,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 static char *escape(const char* text, char *bf, int len)
index f34a0a9..b633bdb 100644 (file)
@@ -21,12 +21,7 @@ static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c;
 extern "C" {
 #endif
 
-#ifdef LKC_DIRECT_LINK
 #define P(name,type,arg)       extern type name arg
-#else
-#include "lkc_defs.h"
-#define P(name,type,arg)       extern type (*name ## _p) arg
-#endif
 #include "lkc_proto.h"
 #undef P
 
@@ -79,9 +74,6 @@ void zconf_nextfile(const char *name);
 int zconf_lineno(void);
 const char *zconf_curname(void);
 
-/* conf.c */
-void xfgets(char *str, int size, FILE *in);
-
 /* confdata.c */
 const char *conf_get_configname(void);
 const char *conf_get_autoconfig_name(void);
@@ -90,6 +82,11 @@ void sym_set_change_count(int count);
 void sym_add_change_count(int count);
 void conf_set_all_new_symbols(enum conf_def_mode mode);
 
+struct conf_printer {
+       void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
+       void (*print_comment)(FILE *, const char *, void *);
+};
+
 /* confdata.c and expr.c */
 static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
 {
@@ -97,9 +94,6 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
                fprintf(stderr, "\nError in writing or end of file.\n");
 }
 
-/* kconfig_load.c */
-void kconfig_load(void);
-
 /* menu.c */
 void _menu_init(void);
 void menu_warn(struct menu *menu, const char *fmt, ...);
index 17342fe..47fe9c3 100644 (file)
@@ -31,6 +31,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
 P(sym_lookup,struct symbol *,(const char *name, int flags));
 P(sym_find,struct symbol *,(const char *name));
 P(sym_expand_string_value,const char *,(const char *in));
+P(sym_escape_string_value, const char *,(const char *in));
 P(sym_re_search,struct symbol **,(const char *pattern));
 P(sym_type_name,const char *,(enum symbol_type type));
 P(sym_calc_value,void,(struct symbol *sym));
index d433c7a..820d2b6 100644 (file)
@@ -18,7 +18,6 @@
 #include <unistd.h>
 #include <locale.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 #include "lxdialog/dialog.h"
 
@@ -845,6 +844,7 @@ int main(int ac, char **av)
                                "\n\n"));
                        return 1;
                }
+               /* fall through */
        case -1:
                printf(_("\n\n"
                        "*** End of the configuration.\n"
index 5fdf10d..d660086 100644 (file)
@@ -3,10 +3,11 @@
  * Released under the terms of the GNU GPL v2.0.
  */
 
+#include <ctype.h>
+#include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 static const char nohelp_text[] = N_(
@@ -350,7 +351,7 @@ void menu_finalize(struct menu *parent)
                        last_menu->next = NULL;
                }
 
-               sym->dir_dep.expr = parent->dep;
+               sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);
        }
        for (menu = parent->list; menu; menu = menu->next) {
                if (sym && sym_is_choice(sym) &&
index 488dd74..39ca1f1 100644 (file)
@@ -7,7 +7,7 @@
  */
 #define _GNU_SOURCE
 #include <string.h>
-#define LKC_DIRECT_LINK
+
 #include "lkc.h"
 #include "nconf.h"
 #include <ctype.h>
@@ -1067,7 +1067,6 @@ static void conf(struct menu *menu)
        struct menu *submenu = 0;
        const char *prompt = menu_get_prompt(menu);
        struct symbol *sym;
-       struct menu *active_menu = NULL;
        int res;
        int current_index = 0;
        int last_top_row = 0;
@@ -1152,13 +1151,9 @@ static void conf(struct menu *menu)
                        continue;
 
                submenu = (struct menu *) item_data();
-               active_menu = (struct menu *)item_data();
                if (!submenu || !menu_is_visible(submenu))
                        continue;
-               if (submenu)
-                       sym = submenu->sym;
-               else
-                       sym = NULL;
+               sym = submenu->sym;
 
                switch (res) {
                case ' ':
@@ -1222,20 +1217,13 @@ static void conf_message_callback(const char *fmt, va_list ap)
 
 static void show_help(struct menu *menu)
 {
-       struct gstr help = str_new();
-
-       if (menu && menu->sym && menu_has_help(menu)) {
-               if (menu->sym->name) {
-                       str_printf(&help, "%s%s:\n\n", CONFIG_, menu->sym->name);
-                       str_append(&help, _(menu_get_help(menu)));
-                       str_append(&help, "\n");
-                       get_symbol_str(&help, menu->sym);
-               } else {
-                       str_append(&help, _(menu_get_help(menu)));
-               }
-       } else {
-               str_append(&help, nohelp_text);
-       }
+       struct gstr help;
+
+       if (!menu)
+               return;
+
+       help = str_new();
+       menu_get_ext_help(menu, &help);
        show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help));
        str_free(&help);
 }
index c2796b8..df274fe 100644 (file)
@@ -1478,10 +1478,13 @@ void ConfigMainWindow::loadConfig(void)
        ConfigView::updateListAll();
 }
 
-void ConfigMainWindow::saveConfig(void)
+bool ConfigMainWindow::saveConfig(void)
 {
-       if (conf_write(NULL))
+       if (conf_write(NULL)) {
                QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
+               return false;
+       }
+       return true;
 }
 
 void ConfigMainWindow::saveConfigAs(void)
@@ -1642,7 +1645,11 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
        mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
        switch (mb.exec()) {
        case QMessageBox::Yes:
-               saveConfig();
+               if (saveConfig())
+                       e->accept();
+               else
+                       e->ignore();
+               break;
        case QMessageBox::No:
                e->accept();
                break;
@@ -1745,10 +1752,6 @@ int main(int ac, char** av)
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
 
-#ifndef LKC_DIRECT_LINK
-       kconfig_load();
-#endif
-
        progname = av[0];
        configApp = new QApplication(ac, av);
        if (ac > 1 && av[1][0] == '-') {
index 91677d9..3715b3e 100644 (file)
@@ -311,7 +311,7 @@ public slots:
        void listFocusChanged(void);
        void goBack(void);
        void loadConfig(void);
-       void saveConfig(void);
+       bool saveConfig(void);
        void saveConfigAs(void);
        void searchConfig(void);
        void showSingleView(void);
index a796c95..071f00c 100644 (file)
@@ -9,7 +9,6 @@
 #include <regex.h>
 #include <sys/utsname.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 struct symbol symbol_yes = {
@@ -751,7 +750,8 @@ const char *sym_get_string_value(struct symbol *sym)
                case no:
                        return "n";
                case mod:
-                       return "m";
+                       sym_calc_value(modules_sym);
+                       return (modules_sym->curr.tri == no) ? "n" : "m";
                case yes:
                        return "y";
                }
@@ -893,6 +893,49 @@ const char *sym_expand_string_value(const char *in)
        return res;
 }
 
+const char *sym_escape_string_value(const char *in)
+{
+       const char *p;
+       size_t reslen;
+       char *res;
+       size_t l;
+
+       reslen = strlen(in) + strlen("\"\"") + 1;
+
+       p = in;
+       for (;;) {
+               l = strcspn(p, "\"\\");
+               p += l;
+
+               if (p[0] == '\0')
+                       break;
+
+               reslen++;
+               p++;
+       }
+
+       res = malloc(reslen);
+       res[0] = '\0';
+
+       strcat(res, "\"");
+
+       p = in;
+       for (;;) {
+               l = strcspn(p, "\"\\");
+               strncat(res, p, l);
+               p += l;
+
+               if (p[0] == '\0')
+                       break;
+
+               strcat(res, "\\");
+               strncat(res, p++, 1);
+       }
+
+       strcat(res, "\"");
+       return res;
+}
+
 struct symbol **sym_re_search(const char *pattern)
 {
        struct symbol *sym, **sym_arr = NULL;
index 6330cc8..d0b8b23 100644 (file)
@@ -5,6 +5,8 @@
  * Released under the terms of the GNU GPL v2.0.
  */
 
+#include <stdarg.h>
+#include <stdlib.h>
 #include <string.h>
 #include "lkc.h"
 
index ddee5fc..00f9d3a 100644 (file)
@@ -14,7 +14,6 @@
 #include <string.h>
 #include <unistd.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 #define START_STRSIZE  16
index 906c099..c32b1a4 100644 (file)
@@ -776,7 +776,6 @@ char *zconftext;
 #include <string.h>
 #include <unistd.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 #define START_STRSIZE  16
index 211e1a2..f636141 100644 (file)
@@ -87,7 +87,6 @@
 #include <string.h>
 #include <stdbool.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
index c38cc5a..864da07 100644 (file)
@@ -11,7 +11,6 @@
 #include <string.h>
 #include <stdbool.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
index a38316b..266a229 100644 (file)
@@ -14,7 +14,7 @@
  *  Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  *                         <dgoeddel@trustedcs.com>
  *  Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
- *     Paul Moore <paul.moore@hp.com>
+ *     Paul Moore <paul@paul-moore.com>
  *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
  *                    Yuichi Nakamura <ynakam@hitachisoft.jp>
  *
index ce23edd..43d5072 100644 (file)
@@ -8,7 +8,7 @@
  *
  * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
  * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
- *                    Paul Moore, <paul.moore@hp.com>
+ *                    Paul Moore <paul@paul-moore.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,
index cf2f628..8c59b8f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SELinux interface to the NetLabel subsystem
  *
- * Author : Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index 1b94450..df7a5ed 100644 (file)
@@ -6,7 +6,7 @@
  * needed to reduce the lookup overhead since most of these queries happen on
  * a per-packet basis.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index 8991752..4d965b8 100644 (file)
@@ -5,7 +5,7 @@
  * mapping is maintained as part of the normal policy but a fast cache is
  * needed to reduce the lookup overhead.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index 58cc481..326f22c 100644 (file)
@@ -8,7 +8,7 @@
  *
  * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
  * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
- *                   Paul Moore <paul.moore@hp.com>
+ *                   Paul Moore <paul@paul-moore.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,
index c3bf3ed..da4b8b2 100644 (file)
@@ -4,7 +4,7 @@
  * This file provides the necessary glue to tie NetLabel into the SELinux
  * subsystem.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  */
 
index 8b691a8..3bf46ab 100644 (file)
@@ -6,7 +6,7 @@
  * needed to reduce the lookup overhead since most of these queries happen on
  * a per-packet basis.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  * This code is heavily based on the "netif" concept originally developed by
  * James Morris <jmorris@redhat.com>
index ae76e29..0b62bd1 100644 (file)
@@ -5,7 +5,7 @@
  * mapping is maintained as part of the normal policy but a fast cache is
  * needed to reduce the lookup overhead.
  *
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
  *
  * This code is heavily based on the "netif" concept originally developed by
  * James Morris <jmorris@redhat.com>
index de7900e..55d92cb 100644 (file)
@@ -2,7 +2,7 @@
  *
  *     Added conditional policy language extensions
  *
- *  Updated: Hewlett-Packard <paul.moore@hp.com>
+ *  Updated: Hewlett-Packard <paul@paul-moore.com>
  *
  *     Added support for the policy capability bitmap
  *
index d42951f..30f119b 100644 (file)
@@ -4,7 +4,7 @@
  * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
  */
 /*
- * Updated: Hewlett-Packard <paul.moore@hp.com>
+ * Updated: Hewlett-Packard <paul@paul-moore.com>
  *
  *      Added support to import/export the NetLabel category bitmap
  *
index e961742..fbf9c58 100644 (file)
@@ -11,7 +11,7 @@
  * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
  */
 /*
- * Updated: Hewlett-Packard <paul.moore@hp.com>
+ * Updated: Hewlett-Packard <paul@paul-moore.com>
  *
  *      Added support to import/export the MLS label from NetLabel
  *
index 037bf9d..e4369e3 100644 (file)
@@ -11,7 +11,7 @@
  * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
  */
 /*
- * Updated: Hewlett-Packard <paul.moore@hp.com>
+ * Updated: Hewlett-Packard <paul@paul-moore.com>
  *
  *     Added support to import/export the MLS label from NetLabel
  *
index d246aca..2381d0d 100644 (file)
@@ -13,7 +13,7 @@
  *
  *     Added conditional policy language extensions
  *
- * Updated: Hewlett-Packard <paul.moore@hp.com>
+ * Updated: Hewlett-Packard <paul@paul-moore.com>
  *
  *      Added support for the policy capability bitmap
  *
index 973e00e..f6917bc 100644 (file)
@@ -13,7 +13,7 @@
  *
  *     Added conditional policy language extensions
  *
- * Updated: Hewlett-Packard <paul.moore@hp.com>
+ * Updated: Hewlett-Packard <paul@paul-moore.com>
  *
  *      Added support for NetLabel
  *      Added support for the policy capability bitmap
index f375eb2..b9c5e14 100644 (file)
@@ -9,7 +9,7 @@
  *
  *  Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
  *  Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
- *                Paul Moore <paul.moore@hp.com>
+ *                Paul Moore <paul@paul-moore.com>
  *  Copyright (C) 2010 Nokia Corporation
  *
  *     This program is free software; you can redistribute it and/or modify
index c8439cf..2e43aec 100644 (file)
@@ -710,8 +710,10 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
                      head->r.index++)
                        if (ns->profile_ptr[head->r.index])
                                break;
-               if (head->r.index == TOMOYO_MAX_PROFILES)
+               if (head->r.index == TOMOYO_MAX_PROFILES) {
+                       head->r.eof = true;
                        return;
+               }
                head->r.step++;
                break;
        case 2:
@@ -723,6 +725,7 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
                        tomoyo_io_printf(head, "%u-COMMENT=", index);
                        tomoyo_set_string(head, comment ? comment->name : "");
                        tomoyo_set_lf(head);
+                       tomoyo_print_namespace(head);
                        tomoyo_io_printf(head, "%u-PREFERENCE={ ", index);
                        for (i = 0; i < TOMOYO_MAX_PREF; i++)
                                tomoyo_io_printf(head, "%s=%u ",
index 5fb2e28..91cdf94 100644 (file)
@@ -342,7 +342,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
                        kfree(bufs);
                        return -EFAULT;
                }
-               bufs[ch] = compat_ptr(ptr);
+               bufs[i] = compat_ptr(ptr);
                bufptr++;
        }
        if (dir == SNDRV_PCM_STREAM_PLAYBACK)
index 0851cd1..e85e72b 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
 #include <linux/log2.h>
 #include <sound/core.h>
 #include <sound/timer.h>
index 7c1cbf0..67ebf1c 100644 (file)
@@ -328,6 +328,8 @@ int snd_timer_close(struct snd_timer_instance *timeri)
                mutex_unlock(&register_mutex);
        } else {
                timer = timeri->timer;
+               if (snd_BUG_ON(!timer))
+                       goto out;
                /* wait, until the active callback is finished */
                spin_lock_irq(&timer->lock);
                while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
@@ -353,6 +355,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
                }
                mutex_unlock(&register_mutex);
        }
+ out:
        if (timeri->private_free)
                timeri->private_free(timeri);
        kfree(timeri->owner);
@@ -531,6 +534,8 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
        if (err < 0)
                return err;
        timer = timeri->timer;
+       if (!timer)
+               return -EINVAL;
        spin_lock_irqsave(&timer->lock, flags);
        timeri->cticks = timeri->ticks;
        timeri->pticks = 0;
index 4831800..484a35b 100644 (file)
 
 #include <asm/io.h>
 #include <linux/delay.h>
-#include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/version.h>
-#include <sound/core.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
 #include <sound/tea575x-tuner.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
@@ -62,17 +62,6 @@ module_param(radio_nr, int, 0);
 #define TEA575X_BIT_DUMMY      (1<<15)         /* buffer */
 #define TEA575X_BIT_FREQ_MASK  0x7fff
 
-static struct v4l2_queryctrl radio_qctrl[] = {
-       {
-               .id            = V4L2_CID_AUDIO_MUTE,
-               .name          = "Mute",
-               .minimum       = 0,
-               .maximum       = 1,
-               .default_value = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       }
-};
-
 /*
  * lowlevel part
  */
@@ -266,83 +255,23 @@ static int vidioc_s_audio(struct file *file, void *priv,
        return 0;
 }
 
-static int vidioc_queryctrl(struct file *file, void *priv,
-                                       struct v4l2_queryctrl *qc)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-               if (qc->id && qc->id == radio_qctrl[i].id) {
-                       memcpy(qc, &(radio_qctrl[i]),
-                                               sizeof(*qc));
-                       return 0;
-               }
-       }
-       return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                                       struct v4l2_control *ctrl)
+static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-       struct snd_tea575x *tea = video_drvdata(file);
+       struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
-               ctrl->value = tea->mute;
+               tea->mute = ctrl->val;
+               snd_tea575x_set_freq(tea);
                return 0;
        }
-       return -EINVAL;
-}
 
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                                       struct v4l2_control *ctrl)
-{
-       struct snd_tea575x *tea = video_drvdata(file);
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUDIO_MUTE:
-               if (tea->mute != ctrl->value) {
-                       tea->mute = ctrl->value;
-                       snd_tea575x_set_freq(tea);
-               }
-               return 0;
-       }
        return -EINVAL;
 }
 
-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-
-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
-       if (i != 0)
-               return -EINVAL;
-       return 0;
-}
-
-static int snd_tea575x_exclusive_open(struct file *file)
-{
-       struct snd_tea575x *tea = video_drvdata(file);
-
-       return test_and_set_bit(0, &tea->in_use) ? -EBUSY : 0;
-}
-
-static int snd_tea575x_exclusive_release(struct file *file)
-{
-       struct snd_tea575x *tea = video_drvdata(file);
-
-       clear_bit(0, &tea->in_use);
-       return 0;
-}
-
 static const struct v4l2_file_operations tea575x_fops = {
        .owner          = THIS_MODULE,
-       .open           = snd_tea575x_exclusive_open,
-       .release        = snd_tea575x_exclusive_release,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops tea575x_ioctl_ops = {
@@ -351,20 +280,19 @@ static const struct v4l2_ioctl_ops tea575x_ioctl_ops = {
        .vidioc_s_tuner     = vidioc_s_tuner,
        .vidioc_g_audio     = vidioc_g_audio,
        .vidioc_s_audio     = vidioc_s_audio,
-       .vidioc_g_input     = vidioc_g_input,
-       .vidioc_s_input     = vidioc_s_input,
        .vidioc_g_frequency = vidioc_g_frequency,
        .vidioc_s_frequency = vidioc_s_frequency,
-       .vidioc_queryctrl   = vidioc_queryctrl,
-       .vidioc_g_ctrl      = vidioc_g_ctrl,
-       .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
 static struct video_device tea575x_radio = {
        .name           = "tea575x-tuner",
        .fops           = &tea575x_fops,
        .ioctl_ops      = &tea575x_ioctl_ops,
-       .release        = video_device_release,
+       .release        = video_device_release_empty,
+};
+
+static const struct v4l2_ctrl_ops tea575x_ctrl_ops = {
+       .s_ctrl = tea575x_s_ctrl,
 };
 
 /*
@@ -373,7 +301,6 @@ static struct video_device tea575x_radio = {
 int snd_tea575x_init(struct snd_tea575x *tea)
 {
        int retval;
-       struct video_device *tea575x_radio_inst;
 
        tea->mute = 1;
 
@@ -381,43 +308,49 @@ int snd_tea575x_init(struct snd_tea575x *tea)
        if (snd_tea575x_read(tea) != 0x55AA)
                return -ENODEV;
 
-       tea->in_use = 0;
        tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40;
        tea->freq = 90500 * 16;         /* 90.5Mhz default */
+       snd_tea575x_set_freq(tea);
 
-       tea575x_radio_inst = video_device_alloc();
-       if (tea575x_radio_inst == NULL) {
-               printk(KERN_ERR "tea575x-tuner: not enough memory\n");
-               return -ENOMEM;
-       }
+       tea->vd = tea575x_radio;
+       video_set_drvdata(&tea->vd, tea);
+       mutex_init(&tea->mutex);
+       tea->vd.lock = &tea->mutex;
 
-       memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio));
+       v4l2_ctrl_handler_init(&tea->ctrl_handler, 1);
+       tea->vd.ctrl_handler = &tea->ctrl_handler;
+       v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
+       retval = tea->ctrl_handler.error;
+       if (retval) {
+               printk(KERN_ERR "tea575x-tuner: can't initialize controls\n");
+               v4l2_ctrl_handler_free(&tea->ctrl_handler);
+               return retval;
+       }
 
-       strcpy(tea575x_radio.name, tea->tea5759 ?
-                                  "TEA5759 radio" : "TEA5757 radio");
+       if (tea->ext_init) {
+               retval = tea->ext_init(tea);
+               if (retval) {
+                       v4l2_ctrl_handler_free(&tea->ctrl_handler);
+                       return retval;
+               }
+       }
 
-       video_set_drvdata(tea575x_radio_inst, tea);
+       v4l2_ctrl_handler_setup(&tea->ctrl_handler);
 
-       retval = video_register_device(tea575x_radio_inst,
-                                      VFL_TYPE_RADIO, radio_nr);
+       retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, radio_nr);
        if (retval) {
                printk(KERN_ERR "tea575x-tuner: can't register video device!\n");
-               kfree(tea575x_radio_inst);
+               v4l2_ctrl_handler_free(&tea->ctrl_handler);
                return retval;
        }
 
-       snd_tea575x_set_freq(tea);
-       tea->vd = tea575x_radio_inst;
-
        return 0;
 }
 
 void snd_tea575x_exit(struct snd_tea575x *tea)
 {
-       if (tea->vd) {
-               video_unregister_device(tea->vd);
-               tea->vd = NULL;
-       }
+       video_unregister_device(&tea->vd);
+       v4l2_ctrl_handler_free(&tea->ctrl_handler);
 }
 
 static int __init alsa_tea575x_module_init(void)
index 8f7d175..6f13ab4 100644 (file)
@@ -63,13 +63,13 @@ static int pcm_set_speed(int arg)
 
        if (pcm_channels & 2)
        {
-               foo = ((CLOCK_TICK_RATE / 2) + (arg / 2)) / arg;
-               arg = ((CLOCK_TICK_RATE / 2) + (foo / 2)) / foo;
+               foo = ((PIT_TICK_RATE / 2) + (arg / 2)) / arg;
+               arg = ((PIT_TICK_RATE / 2) + (foo / 2)) / foo;
        }
        else
        {
-               foo = (CLOCK_TICK_RATE + (arg / 2)) / arg;
-               arg = (CLOCK_TICK_RATE + (foo / 2)) / foo;
+               foo = (PIT_TICK_RATE + (arg / 2)) / arg;
+               arg = (PIT_TICK_RATE + (foo / 2)) / foo;
        }
 
        pcm_speed = arg;
index 9b800ce..2fc0624 100644 (file)
@@ -673,7 +673,8 @@ static void configure_nonsound_components(void)
 
        if (pss_cdrom_port == -1) {     /* If cdrom port enablation wasn't requested */
                printk(KERN_INFO "PSS: CDROM port not enabled.\n");
-       } else if (check_region(pss_cdrom_port, 2)) {
+       } else if (!request_region(pss_cdrom_port, 2, "PSS CDROM")) {
+               pss_cdrom_port = -1;
                printk(KERN_ERR "PSS: CDROM I/O port conflict.\n");
        } else {
                set_io_base(devc, CONF_CDROM, pss_cdrom_port);
@@ -1232,7 +1233,8 @@ static void __exit cleanup_pss(void)
                if(pssmpu)
                        unload_pss_mpu(&cfg_mpu);
                unload_pss(&cfg);
-       }
+       } else if (pss_cdrom_port != -1)
+               release_region(pss_cdrom_port, 2);
 
        if(!pss_keep_settings)  /* Keep hardware settings if asked */
        {
index e90d103..8816804 100644 (file)
@@ -1,5 +1,10 @@
 # ALSA PCI drivers
 
+config SND_TEA575X
+       tristate
+       depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2
+       default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2
+
 menuconfig SND_PCI
        bool "PCI sound devices"
        depends on PCI
@@ -563,11 +568,6 @@ config SND_FM801_TEA575X_BOOL
          FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and
          SF64-PCR) into the snd-fm801 driver.
 
-config SND_TEA575X
-       tristate
-       depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO
-       default SND_FM801 || SND_ES1968
-
 source "sound/pci/hda/Kconfig"
 
 config SND_HDSP
index 65b7ca1..bd47521 100644 (file)
@@ -631,13 +631,12 @@ struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
        if (!p_cache)
                return NULL;
 
-       p_cache->p_info =
-               kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL);
+       p_cache->p_info = kzalloc(sizeof(*p_cache->p_info) * control_count,
+                                 GFP_KERNEL);
        if (!p_cache->p_info) {
                kfree(p_cache);
                return NULL;
        }
-       memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count);
        p_cache->cache_size_in_bytes = size_in_bytes;
        p_cache->control_count = control_count;
        p_cache->p_cache = p_dsp_control_buffer;
index 3a7afa3..71d32c8 100644 (file)
@@ -43,6 +43,7 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
        struct pci_dev *dev = os_data;
        struct code_header header;
        char fw_name[20];
+       short err_ret = HPI_ERROR_DSP_FILE_NOT_FOUND;
        int err;
 
        sprintf(fw_name, "asihpi/dsp%04x.bin", adapter);
@@ -85,8 +86,10 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
 
        HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
        dsp_code->pvt = kmalloc(sizeof(*dsp_code->pvt), GFP_KERNEL);
-       if (!dsp_code->pvt)
-               return HPI_ERROR_MEMORY_ALLOC;
+       if (!dsp_code->pvt) {
+               err_ret = HPI_ERROR_MEMORY_ALLOC;
+               goto error2;
+       }
 
        dsp_code->pvt->dev = dev;
        dsp_code->pvt->firmware = firmware;
@@ -99,7 +102,7 @@ error2:
        release_firmware(firmware);
 error1:
        dsp_code->block_length = 0;
-       return HPI_ERROR_DSP_FILE_NOT_FOUND;
+       return err_ret;
 }
 
 /*-------------------------------------------------------------------*/
index 9683f84..a32502e 100644 (file)
@@ -177,16 +177,21 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        } else {
                u16 __user *ptr = NULL;
                u32 size = 0;
-
+               u32 adapter_present;
                /* -1=no data 0=read from user mem, 1=write to user mem */
                int wrflag = -1;
-               u32 adapter = hm->h.adapter_index;
-               struct hpi_adapter *pa = &adapters[adapter];
+               struct hpi_adapter *pa;
+
+               if (hm->h.adapter_index < HPI_MAX_ADAPTERS) {
+                       pa = &adapters[hm->h.adapter_index];
+                       adapter_present = pa->type;
+               } else {
+                       adapter_present = 0;
+               }
 
-               if ((adapter >= HPI_MAX_ADAPTERS) || (!pa->type)) {
-                       hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER,
-                               HPI_ADAPTER_OPEN,
-                               HPI_ERROR_BAD_ADAPTER_NUMBER);
+               if (!adapter_present) {
+                       hpi_init_response(&hr->r0, hm->h.object,
+                               hm->h.function, HPI_ERROR_BAD_ADAPTER_NUMBER);
 
                        uncopied_bytes =
                                copy_to_user(puhr, hr, sizeof(hr->h));
index 14fdcf2..5ac0e21 100644 (file)
@@ -531,17 +531,10 @@ static const struct snd_pci_quirk alc269_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC),
-       SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC),
-       SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
-                     ALC269_DMIC),
-       SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
-                     ALC269_DMIC),
-       SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC),
-       SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC),
        SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO),
        SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
        SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC),
index e125c60..9a1aa09 100644 (file)
@@ -4484,6 +4484,22 @@ static void alc269_fixup_pcm_44k(struct hda_codec *codec,
        spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
 }
 
+static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
+                                    const struct alc_fixup *fix, int action)
+{
+       int coef;
+
+       if (action != ALC_FIXUP_ACT_INIT)
+               return;
+       /* The digital-mic unit sends PDM (differential signal) instead of
+        * the standard PCM, thus you can't record a valid mono stream as is.
+        * Below is a workaround specific to ALC269 to control the dmic
+        * signal source as mono.
+        */
+       coef = alc_read_coef_idx(codec, 0x07);
+       alc_write_coef_idx(codec, 0x07, coef | 0x80);
+}
+
 enum {
        ALC269_FIXUP_SONY_VAIO,
        ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -4494,6 +4510,7 @@ enum {
        ALC275_FIXUP_SONY_HWEQ,
        ALC271_FIXUP_DMIC,
        ALC269_FIXUP_PCM_44K,
+       ALC269_FIXUP_STEREO_DMIC,
 };
 
 static const struct alc_fixup alc269_fixups[] = {
@@ -4556,10 +4573,19 @@ static const struct alc_fixup alc269_fixups[] = {
                .type = ALC_FIXUP_FUNC,
                .v.func = alc269_fixup_pcm_44k,
        },
+       [ALC269_FIXUP_STEREO_DMIC] = {
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc269_fixup_stereo_dmic,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
+       SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
        SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
index 84d8798..4ebfbd8 100644 (file)
@@ -2084,7 +2084,7 @@ static int via_auto_create_speaker_ctls(struct hda_codec *codec)
        struct via_spec *spec = codec->spec;
        struct nid_path *path;
        bool check_dac;
-       hda_nid_t pin, dac;
+       hda_nid_t pin, dac = 0;
        int err;
 
        pin = spec->autocfg.speaker_pins[0];
index af130ee..493e394 100644 (file)
@@ -521,6 +521,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
 
 /* revisions >= 230 indicate AES32 card */
+#define HDSPM_MADI_ANCIENT_REV 204
 #define HDSPM_MADI_OLD_REV     207
 #define HDSPM_MADI_REV         210
 #define HDSPM_RAYDAT_REV       211
@@ -1217,6 +1218,22 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
                                rate = 0;
                                break;
                        }
+
+                       /* QS and DS rates normally can not be detected
+                        * automatically by the card. Only exception is MADI
+                        * in 96k frame mode.
+                        *
+                        * So if we read SS values (32 .. 48k), check for
+                        * user-provided DS/QS bits in the control register
+                        * and multiply the base frequency accordingly.
+                        */
+                       if (rate <= 48000) {
+                               if (hdspm->control_register & HDSPM_QuadSpeed)
+                                       rate *= 4;
+                               else if (hdspm->control_register &
+                                               HDSPM_DoubleSpeed)
+                                       rate *= 2;
+                       }
                }
                break;
        }
@@ -1322,6 +1339,10 @@ static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
                break;
        case MADIface:
                freq_const = 131072000000000ULL;
+               break;
+       default:
+               snd_BUG();
+               return 0;
        }
 
        return div_u64(freq_const, period);
@@ -1339,16 +1360,19 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
 
        switch (hdspm->io_type) {
        case MADIface:
-         n = 131072000000000ULL;  /* 125 MHz */
-         break;
+               n = 131072000000000ULL;  /* 125 MHz */
+               break;
        case MADI:
        case AES32:
-         n = 110069313433624ULL;  /* 105 MHz */
-         break;
+               n = 110069313433624ULL;  /* 105 MHz */
+               break;
        case RayDAT:
        case AIO:
-         n = 104857600000000ULL;  /* 100 MHz */
-         break;
+               n = 104857600000000ULL;  /* 100 MHz */
+               break;
+       default:
+               snd_BUG();
+               return;
        }
 
        n = div_u64(n, rate);
@@ -3415,6 +3439,91 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
        return change;
 }
 
+#define HDSPM_MADI_SPEEDMODE(xname, xindex) \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_madi_speedmode, \
+       .get = snd_hdspm_get_madi_speedmode, \
+       .put = snd_hdspm_put_madi_speedmode \
+}
+
+static int hdspm_madi_speedmode(struct hdspm *hdspm)
+{
+       if (hdspm->control_register & HDSPM_QuadSpeed)
+               return 2;
+       if (hdspm->control_register & HDSPM_DoubleSpeed)
+               return 1;
+       return 0;
+}
+
+static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
+{
+       hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed);
+       switch (mode) {
+       case 0:
+               break;
+       case 1:
+               hdspm->control_register |= HDSPM_DoubleSpeed;
+               break;
+       case 2:
+               hdspm->control_register |= HDSPM_QuadSpeed;
+               break;
+       }
+       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+       return 0;
+}
+
+static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_info *uinfo)
+{
+       static char *texts[] = { "Single", "Double", "Quad" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 3;
+
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item =
+                   uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name,
+              texts[uinfo->value.enumerated.item]);
+
+       return 0;
+}
+
+static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+       spin_lock_irq(&hdspm->lock);
+       ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm);
+       spin_unlock_irq(&hdspm->lock);
+       return 0;
+}
+
+static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+       int change;
+       int val;
+
+       if (!snd_hdspm_use_is_exclusive(hdspm))
+               return -EBUSY;
+       val = ucontrol->value.integer.value[0];
+       if (val < 0)
+               val = 0;
+       if (val > 2)
+               val = 2;
+       spin_lock_irq(&hdspm->lock);
+       change = val != hdspm_madi_speedmode(hdspm);
+       hdspm_set_madi_speedmode(hdspm, val);
+       spin_unlock_irq(&hdspm->lock);
+       return change;
+}
 
 #define HDSPM_MIXER(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
@@ -4289,7 +4398,8 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
        HDSPM_TX_64("TX 64 channels mode", 0),
        HDSPM_C_TMS("Clear Track Marker", 0),
        HDSPM_SAFE_MODE("Safe Mode", 0),
-       HDSPM_INPUT_SELECT("Input Select", 0)
+       HDSPM_INPUT_SELECT("Input Select", 0),
+       HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
 };
 
 
@@ -4302,7 +4412,8 @@ static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
        HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
        HDSPM_TX_64("TX 64 channels mode", 0),
        HDSPM_C_TMS("Clear Track Marker", 0),
-       HDSPM_SAFE_MODE("Safe Mode", 0)
+       HDSPM_SAFE_MODE("Safe Mode", 0),
+       HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
 };
 
 static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
@@ -6381,6 +6492,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
        switch (hdspm->firmware_rev) {
        case HDSPM_MADI_REV:
        case HDSPM_MADI_OLD_REV:
+       case HDSPM_MADI_ANCIENT_REV:
                hdspm->io_type = MADI;
                hdspm->card_name = "RME MADI";
                hdspm->midiPorts = 3;
index 379b2e3..665d924 100644 (file)
@@ -78,7 +78,6 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_WM8900 if I2C
        select SND_SOC_WM8903 if I2C
        select SND_SOC_WM8904 if I2C
-       select SND_SOC_WM8915 if I2C
        select SND_SOC_WM8940 if I2C
        select SND_SOC_WM8955 if I2C
        select SND_SOC_WM8960 if I2C
@@ -95,6 +94,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_WM8993 if I2C
        select SND_SOC_WM8994 if MFD_WM8994
        select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI
+       select SND_SOC_WM8996 if I2C
        select SND_SOC_WM9081 if I2C
        select SND_SOC_WM9090 if I2C
        select SND_SOC_WM9705 if SND_SOC_AC97_BUS
@@ -329,9 +329,6 @@ config SND_SOC_WM8903
 config SND_SOC_WM8904
        tristate
 
-config SND_SOC_WM8915
-       tristate
-
 config SND_SOC_WM8940
         tristate
 
@@ -380,6 +377,9 @@ config SND_SOC_WM8994
 config SND_SOC_WM8995
        tristate
 
+config SND_SOC_WM8996
+       tristate
+
 config SND_SOC_WM9081
        tristate
 
index da9990f..5119a7e 100644 (file)
@@ -63,7 +63,7 @@ snd-soc-wm8804-objs := wm8804.o
 snd-soc-wm8900-objs := wm8900.o
 snd-soc-wm8903-objs := wm8903.o
 snd-soc-wm8904-objs := wm8904.o
-snd-soc-wm8915-objs := wm8915.o
+snd-soc-wm8996-objs := wm8996.o
 snd-soc-wm8940-objs := wm8940.o
 snd-soc-wm8955-objs := wm8955.o
 snd-soc-wm8960-objs := wm8960.o
@@ -160,7 +160,7 @@ obj-$(CONFIG_SND_SOC_WM8804)        += snd-soc-wm8804.o
 obj-$(CONFIG_SND_SOC_WM8900)   += snd-soc-wm8900.o
 obj-$(CONFIG_SND_SOC_WM8903)   += snd-soc-wm8903.o
 obj-$(CONFIG_SND_SOC_WM8904)   += snd-soc-wm8904.o
-obj-$(CONFIG_SND_SOC_WM8915)   += snd-soc-wm8915.o
+obj-$(CONFIG_SND_SOC_WM8996)   += snd-soc-wm8996.o
 obj-$(CONFIG_SND_SOC_WM8940)   += snd-soc-wm8940.o
 obj-$(CONFIG_SND_SOC_WM8955)   += snd-soc-wm8955.o
 obj-$(CONFIG_SND_SOC_WM8960)   += snd-soc-wm8960.o
index 76258f2..7e4066e 100644 (file)
 #define SGTL5000_DAP_REG_OFFSET        0x0100
 #define SGTL5000_MAX_REG_OFFSET        0x013A
 
-/* default value of sgtl5000 registers except DAP */
-static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET >> 1] =  {
-       0xa011, /* 0x0000, CHIP_ID. 11 stand for revison 17 */
-       0x0000, /* 0x0002, CHIP_DIG_POWER. */
-       0x0008, /* 0x0004, CHIP_CKL_CTRL */
-       0x0010, /* 0x0006, CHIP_I2S_CTRL */
-       0x0000, /* 0x0008, reserved */
-       0x0008, /* 0x000A, CHIP_SSS_CTRL */
-       0x0000, /* 0x000C, reserved */
-       0x020c, /* 0x000E, CHIP_ADCDAC_CTRL */
-       0x3c3c, /* 0x0010, CHIP_DAC_VOL */
-       0x0000, /* 0x0012, reserved */
-       0x015f, /* 0x0014, CHIP_PAD_STRENGTH */
-       0x0000, /* 0x0016, reserved */
-       0x0000, /* 0x0018, reserved */
-       0x0000, /* 0x001A, reserved */
-       0x0000, /* 0x001E, reserved */
-       0x0000, /* 0x0020, CHIP_ANA_ADC_CTRL */
-       0x1818, /* 0x0022, CHIP_ANA_HP_CTRL */
-       0x0111, /* 0x0024, CHIP_ANN_CTRL */
-       0x0000, /* 0x0026, CHIP_LINREG_CTRL */
-       0x0000, /* 0x0028, CHIP_REF_CTRL */
-       0x0000, /* 0x002A, CHIP_MIC_CTRL */
-       0x0000, /* 0x002C, CHIP_LINE_OUT_CTRL */
-       0x0404, /* 0x002E, CHIP_LINE_OUT_VOL */
-       0x7060, /* 0x0030, CHIP_ANA_POWER */
-       0x5000, /* 0x0032, CHIP_PLL_CTRL */
-       0x0000, /* 0x0034, CHIP_CLK_TOP_CTRL */
-       0x0000, /* 0x0036, CHIP_ANA_STATUS */
-       0x0000, /* 0x0038, reserved */
-       0x0000, /* 0x003A, CHIP_ANA_TEST2 */
-       0x0000, /* 0x003C, CHIP_SHORT_CTRL */
-       0x0000, /* reserved */
-};
-
-/* default value of dap registers */
-static const u16 sgtl5000_dap_regs[] = {
-       0x0000, /* 0x0100, DAP_CONTROL */
-       0x0000, /* 0x0102, DAP_PEQ */
-       0x0040, /* 0x0104, DAP_BASS_ENHANCE */
-       0x051f, /* 0x0106, DAP_BASS_ENHANCE_CTRL */
-       0x0000, /* 0x0108, DAP_AUDIO_EQ */
-       0x0040, /* 0x010A, DAP_SGTL_SURROUND */
-       0x0000, /* 0x010C, DAP_FILTER_COEF_ACCESS */
-       0x0000, /* 0x010E, DAP_COEF_WR_B0_MSB */
-       0x0000, /* 0x0110, DAP_COEF_WR_B0_LSB */
-       0x0000, /* 0x0112, reserved */
-       0x0000, /* 0x0114, reserved */
-       0x002f, /* 0x0116, DAP_AUDIO_EQ_BASS_BAND0 */
-       0x002f, /* 0x0118, DAP_AUDIO_EQ_BAND0 */
-       0x002f, /* 0x011A, DAP_AUDIO_EQ_BAND2 */
-       0x002f, /* 0x011C, DAP_AUDIO_EQ_BAND3 */
-       0x002f, /* 0x011E, DAP_AUDIO_EQ_TREBLE_BAND4 */
-       0x8000, /* 0x0120, DAP_MAIN_CHAN */
-       0x0000, /* 0x0122, DAP_MIX_CHAN */
-       0x0510, /* 0x0124, DAP_AVC_CTRL */
-       0x1473, /* 0x0126, DAP_AVC_THRESHOLD */
-       0x0028, /* 0x0128, DAP_AVC_ATTACK */
-       0x0050, /* 0x012A, DAP_AVC_DECAY */
-       0x0000, /* 0x012C, DAP_COEF_WR_B1_MSB */
-       0x0000, /* 0x012E, DAP_COEF_WR_B1_LSB */
-       0x0000, /* 0x0130, DAP_COEF_WR_B2_MSB */
-       0x0000, /* 0x0132, DAP_COEF_WR_B2_LSB */
-       0x0000, /* 0x0134, DAP_COEF_WR_A1_MSB */
-       0x0000, /* 0x0136, DAP_COEF_WR_A1_LSB */
-       0x0000, /* 0x0138, DAP_COEF_WR_A2_MSB */
-       0x0000, /* 0x013A, DAP_COEF_WR_A2_LSB */
+/* default value of sgtl5000 registers */
+static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET] =  {
+       [SGTL5000_CHIP_CLK_CTRL] = 0x0008,
+       [SGTL5000_CHIP_I2S_CTRL] = 0x0010,
+       [SGTL5000_CHIP_SSS_CTRL] = 0x0008,
+       [SGTL5000_CHIP_DAC_VOL] = 0x3c3c,
+       [SGTL5000_CHIP_PAD_STRENGTH] = 0x015f,
+       [SGTL5000_CHIP_ANA_HP_CTRL] = 0x1818,
+       [SGTL5000_CHIP_ANA_CTRL] = 0x0111,
+       [SGTL5000_CHIP_LINE_OUT_VOL] = 0x0404,
+       [SGTL5000_CHIP_ANA_POWER] = 0x7060,
+       [SGTL5000_CHIP_PLL_CTRL] = 0x5000,
+       [SGTL5000_DAP_BASS_ENHANCE] = 0x0040,
+       [SGTL5000_DAP_BASS_ENHANCE_CTRL] = 0x051f,
+       [SGTL5000_DAP_SURROUND] = 0x0040,
+       [SGTL5000_DAP_EQ_BASS_BAND0] = 0x002f,
+       [SGTL5000_DAP_EQ_BASS_BAND1] = 0x002f,
+       [SGTL5000_DAP_EQ_BASS_BAND2] = 0x002f,
+       [SGTL5000_DAP_EQ_BASS_BAND3] = 0x002f,
+       [SGTL5000_DAP_EQ_BASS_BAND4] = 0x002f,
+       [SGTL5000_DAP_MAIN_CHAN] = 0x8000,
+       [SGTL5000_DAP_AVC_CTRL] = 0x0510,
+       [SGTL5000_DAP_AVC_THRESHOLD] = 0x1473,
+       [SGTL5000_DAP_AVC_ATTACK] = 0x0028,
+       [SGTL5000_DAP_AVC_DECAY] = 0x0050,
 };
 
 /* regulator supplies for sgtl5000, VDDD is an optional external supply */
@@ -1023,12 +981,10 @@ static int sgtl5000_suspend(struct snd_soc_codec *codec, pm_message_t state)
 static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
 {
        u16 *cache = codec->reg_cache;
-       int i;
-       int regular_regs = SGTL5000_CHIP_SHORT_CTRL >> 1;
+       u16 reg;
 
        /* restore regular registers */
-       for (i = 0; i < regular_regs; i++) {
-               int reg = i << 1;
+       for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
 
                /* this regs depends on the others */
                if (reg == SGTL5000_CHIP_ANA_POWER ||
@@ -1038,35 +994,31 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
                        reg == SGTL5000_CHIP_CLK_CTRL)
                        continue;
 
-               snd_soc_write(codec, reg, cache[i]);
+               snd_soc_write(codec, reg, cache[reg]);
        }
 
        /* restore dap registers */
-       for (i = SGTL5000_DAP_REG_OFFSET >> 1;
-                       i < SGTL5000_MAX_REG_OFFSET >> 1; i++) {
-               int reg = i << 1;
-
-               snd_soc_write(codec, reg, cache[i]);
-       }
+       for (reg = SGTL5000_DAP_REG_OFFSET; reg < SGTL5000_MAX_REG_OFFSET; reg += 2)
+               snd_soc_write(codec, reg, cache[reg]);
 
        /*
         * restore power and other regs according
         * to set_power() and set_clock()
         */
        snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
-                       cache[SGTL5000_CHIP_LINREG_CTRL >> 1]);
+                       cache[SGTL5000_CHIP_LINREG_CTRL]);
 
        snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER,
-                       cache[SGTL5000_CHIP_ANA_POWER >> 1]);
+                       cache[SGTL5000_CHIP_ANA_POWER]);
 
        snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL,
-                       cache[SGTL5000_CHIP_CLK_CTRL >> 1]);
+                       cache[SGTL5000_CHIP_CLK_CTRL]);
 
        snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL,
-                       cache[SGTL5000_CHIP_REF_CTRL >> 1]);
+                       cache[SGTL5000_CHIP_REF_CTRL]);
 
        snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
-                       cache[SGTL5000_CHIP_LINE_OUT_CTRL >> 1]);
+                       cache[SGTL5000_CHIP_LINE_OUT_CTRL]);
        return 0;
 }
 
@@ -1454,16 +1406,6 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
        if (!sgtl5000)
                return -ENOMEM;
 
-       /*
-        * copy DAP default values to default value array.
-        * sgtl5000 register space has a big hole, merge it
-        * at init phase makes life easy.
-        * FIXME: should we drop 'const' of sgtl5000_regs?
-        */
-       memcpy((void *)(&sgtl5000_regs[0] + (SGTL5000_DAP_REG_OFFSET >> 1)),
-                       sgtl5000_dap_regs,
-                       SGTL5000_MAX_REG_OFFSET - SGTL5000_DAP_REG_OFFSET);
-
        i2c_set_clientdata(client, sgtl5000);
 
        ret = snd_soc_register_codec(&client->dev,
diff --git a/sound/soc/codecs/wm8915.c b/sound/soc/codecs/wm8915.c
deleted file mode 100644 (file)
index 423baa9..0000000
+++ /dev/null
@@ -1,2995 +0,0 @@
-/*
- * wm8915.c - WM8915 audio codec interface
- *
- * Copyright 2011 Wolfson Microelectronics PLC.
- * Author: Mark Brown <broonie@opensource.wolfsonmicro.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.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/gcd.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <sound/core.h>
-#include <sound/jack.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/initval.h>
-#include <sound/tlv.h>
-#include <trace/events/asoc.h>
-
-#include <sound/wm8915.h>
-#include "wm8915.h"
-
-#define WM8915_AIFS 2
-
-#define HPOUT1L 1
-#define HPOUT1R 2
-#define HPOUT2L 4
-#define HPOUT2R 8
-
-#define WM8915_NUM_SUPPLIES 4
-static const char *wm8915_supply_names[WM8915_NUM_SUPPLIES] = {
-       "DBVDD",
-       "AVDD1",
-       "AVDD2",
-       "CPVDD",
-};
-
-struct wm8915_priv {
-       struct snd_soc_codec *codec;
-
-       int ldo1ena;
-
-       int sysclk;
-       int sysclk_src;
-
-       int fll_src;
-       int fll_fref;
-       int fll_fout;
-
-       struct completion fll_lock;
-
-       u16 dcs_pending;
-       struct completion dcs_done;
-
-       u16 hpout_ena;
-       u16 hpout_pending;
-
-       struct regulator_bulk_data supplies[WM8915_NUM_SUPPLIES];
-       struct notifier_block disable_nb[WM8915_NUM_SUPPLIES];
-
-       struct wm8915_pdata pdata;
-
-       int rx_rate[WM8915_AIFS];
-       int bclk_rate[WM8915_AIFS];
-
-       /* Platform dependant ReTune mobile configuration */
-       int num_retune_mobile_texts;
-       const char **retune_mobile_texts;
-       int retune_mobile_cfg[2];
-       struct soc_enum retune_mobile_enum;
-
-       struct snd_soc_jack *jack;
-       bool detecting;
-       bool jack_mic;
-       wm8915_polarity_fn polarity_cb;
-
-#ifdef CONFIG_GPIOLIB
-       struct gpio_chip gpio_chip;
-#endif
-};
-
-/* We can't use the same notifier block for more than one supply and
- * there's no way I can see to get from a callback to the caller
- * except container_of().
- */
-#define WM8915_REGULATOR_EVENT(n) \
-static int wm8915_regulator_event_##n(struct notifier_block *nb, \
-                                   unsigned long event, void *data)    \
-{ \
-       struct wm8915_priv *wm8915 = container_of(nb, struct wm8915_priv, \
-                                                 disable_nb[n]); \
-       if (event & REGULATOR_EVENT_DISABLE) { \
-               wm8915->codec->cache_sync = 1; \
-       } \
-       return 0; \
-}
-
-WM8915_REGULATOR_EVENT(0)
-WM8915_REGULATOR_EVENT(1)
-WM8915_REGULATOR_EVENT(2)
-WM8915_REGULATOR_EVENT(3)
-
-static const u16 wm8915_reg[WM8915_MAX_REGISTER] = {
-       [WM8915_SOFTWARE_RESET] = 0x8915,
-       [WM8915_POWER_MANAGEMENT_7] = 0x10,
-       [WM8915_DAC1_HPOUT1_VOLUME] = 0x88,
-       [WM8915_DAC2_HPOUT2_VOLUME] = 0x88,
-       [WM8915_DAC1_LEFT_VOLUME] = 0x2c0,
-       [WM8915_DAC1_RIGHT_VOLUME] = 0x2c0,
-       [WM8915_DAC2_LEFT_VOLUME] = 0x2c0,
-       [WM8915_DAC2_RIGHT_VOLUME] = 0x2c0,
-       [WM8915_OUTPUT1_LEFT_VOLUME] = 0x80,
-       [WM8915_OUTPUT1_RIGHT_VOLUME] = 0x80,
-       [WM8915_OUTPUT2_LEFT_VOLUME] = 0x80,
-       [WM8915_OUTPUT2_RIGHT_VOLUME] = 0x80,
-       [WM8915_MICBIAS_1] = 0x39,
-       [WM8915_MICBIAS_2] = 0x39,
-       [WM8915_LDO_1] = 0x3,
-       [WM8915_LDO_2] = 0x13,
-       [WM8915_ACCESSORY_DETECT_MODE_1] = 0x4,
-       [WM8915_HEADPHONE_DETECT_1] = 0x20,
-       [WM8915_MIC_DETECT_1] = 0x7600,
-       [WM8915_MIC_DETECT_2] = 0xbf,
-       [WM8915_CHARGE_PUMP_1] = 0x1f25,
-       [WM8915_CHARGE_PUMP_2] = 0xab19,
-       [WM8915_DC_SERVO_5] = 0x2a2a,
-       [WM8915_CONTROL_INTERFACE_1] = 0x8004,
-       [WM8915_CLOCKING_1] = 0x10,
-       [WM8915_AIF_RATE] = 0x83,
-       [WM8915_FLL_CONTROL_4] = 0x5dc0,
-       [WM8915_FLL_CONTROL_5] = 0xc84,
-       [WM8915_FLL_EFS_2] = 0x2,
-       [WM8915_AIF1_TX_LRCLK_1] = 0x80,
-       [WM8915_AIF1_TX_LRCLK_2] = 0x8,
-       [WM8915_AIF1_RX_LRCLK_1] = 0x80,
-       [WM8915_AIF1TX_DATA_CONFIGURATION_1] = 0x1818,
-       [WM8915_AIF1RX_DATA_CONFIGURATION] = 0x1818,
-       [WM8915_AIF1TX_TEST] = 0x7,
-       [WM8915_AIF2_TX_LRCLK_1] = 0x80,
-       [WM8915_AIF2_TX_LRCLK_2] = 0x8,
-       [WM8915_AIF2_RX_LRCLK_1] = 0x80,
-       [WM8915_AIF2TX_DATA_CONFIGURATION_1] = 0x1818,
-       [WM8915_AIF2RX_DATA_CONFIGURATION] = 0x1818,
-       [WM8915_AIF2TX_TEST] = 0x1,
-       [WM8915_DSP1_TX_LEFT_VOLUME] = 0xc0,
-       [WM8915_DSP1_TX_RIGHT_VOLUME] = 0xc0,
-       [WM8915_DSP1_RX_LEFT_VOLUME] = 0xc0,
-       [WM8915_DSP1_RX_RIGHT_VOLUME] = 0xc0,
-       [WM8915_DSP1_TX_FILTERS] = 0x2000,
-       [WM8915_DSP1_RX_FILTERS_1] = 0x200,
-       [WM8915_DSP1_RX_FILTERS_2] = 0x10,
-       [WM8915_DSP1_DRC_1] = 0x98,
-       [WM8915_DSP1_DRC_2] = 0x845,
-       [WM8915_DSP1_RX_EQ_GAINS_1] = 0x6318,
-       [WM8915_DSP1_RX_EQ_GAINS_2] = 0x6300,
-       [WM8915_DSP1_RX_EQ_BAND_1_A] = 0xfca,
-       [WM8915_DSP1_RX_EQ_BAND_1_B] = 0x400,
-       [WM8915_DSP1_RX_EQ_BAND_1_PG] = 0xd8,
-       [WM8915_DSP1_RX_EQ_BAND_2_A] = 0x1eb5,
-       [WM8915_DSP1_RX_EQ_BAND_2_B] = 0xf145,
-       [WM8915_DSP1_RX_EQ_BAND_2_C] = 0xb75,
-       [WM8915_DSP1_RX_EQ_BAND_2_PG] = 0x1c5,
-       [WM8915_DSP1_RX_EQ_BAND_3_A] = 0x1c58,
-       [WM8915_DSP1_RX_EQ_BAND_3_B] = 0xf373,
-       [WM8915_DSP1_RX_EQ_BAND_3_C] = 0xa54,
-       [WM8915_DSP1_RX_EQ_BAND_3_PG] = 0x558,
-       [WM8915_DSP1_RX_EQ_BAND_4_A] = 0x168e,
-       [WM8915_DSP1_RX_EQ_BAND_4_B] = 0xf829,
-       [WM8915_DSP1_RX_EQ_BAND_4_C] = 0x7ad,
-       [WM8915_DSP1_RX_EQ_BAND_4_PG] = 0x1103,
-       [WM8915_DSP1_RX_EQ_BAND_5_A] = 0x564,
-       [WM8915_DSP1_RX_EQ_BAND_5_B] = 0x559,
-       [WM8915_DSP1_RX_EQ_BAND_5_PG] = 0x4000,
-       [WM8915_DSP2_TX_LEFT_VOLUME] = 0xc0,
-       [WM8915_DSP2_TX_RIGHT_VOLUME] = 0xc0,
-       [WM8915_DSP2_RX_LEFT_VOLUME] = 0xc0,
-       [WM8915_DSP2_RX_RIGHT_VOLUME] = 0xc0,
-       [WM8915_DSP2_TX_FILTERS] = 0x2000,
-       [WM8915_DSP2_RX_FILTERS_1] = 0x200,
-       [WM8915_DSP2_RX_FILTERS_2] = 0x10,
-       [WM8915_DSP2_DRC_1] = 0x98,
-       [WM8915_DSP2_DRC_2] = 0x845,
-       [WM8915_DSP2_RX_EQ_GAINS_1] = 0x6318,
-       [WM8915_DSP2_RX_EQ_GAINS_2] = 0x6300,
-       [WM8915_DSP2_RX_EQ_BAND_1_A] = 0xfca,
-       [WM8915_DSP2_RX_EQ_BAND_1_B] = 0x400,
-       [WM8915_DSP2_RX_EQ_BAND_1_PG] = 0xd8,
-       [WM8915_DSP2_RX_EQ_BAND_2_A] = 0x1eb5,
-       [WM8915_DSP2_RX_EQ_BAND_2_B] = 0xf145,
-       [WM8915_DSP2_RX_EQ_BAND_2_C] = 0xb75,
-       [WM8915_DSP2_RX_EQ_BAND_2_PG] = 0x1c5,
-       [WM8915_DSP2_RX_EQ_BAND_3_A] = 0x1c58,
-       [WM8915_DSP2_RX_EQ_BAND_3_B] = 0xf373,
-       [WM8915_DSP2_RX_EQ_BAND_3_C] = 0xa54,
-       [WM8915_DSP2_RX_EQ_BAND_3_PG] = 0x558,
-       [WM8915_DSP2_RX_EQ_BAND_4_A] = 0x168e,
-       [WM8915_DSP2_RX_EQ_BAND_4_B] = 0xf829,
-       [WM8915_DSP2_RX_EQ_BAND_4_C] = 0x7ad,
-       [WM8915_DSP2_RX_EQ_BAND_4_PG] = 0x1103,
-       [WM8915_DSP2_RX_EQ_BAND_5_A] = 0x564,
-       [WM8915_DSP2_RX_EQ_BAND_5_B] = 0x559,
-       [WM8915_DSP2_RX_EQ_BAND_5_PG] = 0x4000,
-       [WM8915_OVERSAMPLING] = 0xd,
-       [WM8915_SIDETONE] = 0x1040,
-       [WM8915_GPIO_1] = 0xa101,
-       [WM8915_GPIO_2] = 0xa101,
-       [WM8915_GPIO_3] = 0xa101,
-       [WM8915_GPIO_4] = 0xa101,
-       [WM8915_GPIO_5] = 0xa101,
-       [WM8915_PULL_CONTROL_2] = 0x140,
-       [WM8915_INTERRUPT_STATUS_1_MASK] = 0x1f,
-       [WM8915_INTERRUPT_STATUS_2_MASK] = 0x1ecf,
-       [WM8915_RIGHT_PDM_SPEAKER] = 0x1,
-       [WM8915_PDM_SPEAKER_MUTE_SEQUENCE] = 0x69,
-       [WM8915_PDM_SPEAKER_VOLUME] = 0x66,
-       [WM8915_WRITE_SEQUENCER_0] = 0x1,
-       [WM8915_WRITE_SEQUENCER_1] = 0x1,
-       [WM8915_WRITE_SEQUENCER_3] = 0x6,
-       [WM8915_WRITE_SEQUENCER_4] = 0x40,
-       [WM8915_WRITE_SEQUENCER_5] = 0x1,
-       [WM8915_WRITE_SEQUENCER_6] = 0xf,
-       [WM8915_WRITE_SEQUENCER_7] = 0x6,
-       [WM8915_WRITE_SEQUENCER_8] = 0x1,
-       [WM8915_WRITE_SEQUENCER_9] = 0x3,
-       [WM8915_WRITE_SEQUENCER_10] = 0x104,
-       [WM8915_WRITE_SEQUENCER_12] = 0x60,
-       [WM8915_WRITE_SEQUENCER_13] = 0x11,
-       [WM8915_WRITE_SEQUENCER_14] = 0x401,
-       [WM8915_WRITE_SEQUENCER_16] = 0x50,
-       [WM8915_WRITE_SEQUENCER_17] = 0x3,
-       [WM8915_WRITE_SEQUENCER_18] = 0x100,
-       [WM8915_WRITE_SEQUENCER_20] = 0x51,
-       [WM8915_WRITE_SEQUENCER_21] = 0x3,
-       [WM8915_WRITE_SEQUENCER_22] = 0x104,
-       [WM8915_WRITE_SEQUENCER_23] = 0xa,
-       [WM8915_WRITE_SEQUENCER_24] = 0x60,
-       [WM8915_WRITE_SEQUENCER_25] = 0x3b,
-       [WM8915_WRITE_SEQUENCER_26] = 0x502,
-       [WM8915_WRITE_SEQUENCER_27] = 0x100,
-       [WM8915_WRITE_SEQUENCER_28] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_32] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_36] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_40] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_44] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_48] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_52] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_56] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_60] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_64] = 0x1,
-       [WM8915_WRITE_SEQUENCER_65] = 0x1,
-       [WM8915_WRITE_SEQUENCER_67] = 0x6,
-       [WM8915_WRITE_SEQUENCER_68] = 0x40,
-       [WM8915_WRITE_SEQUENCER_69] = 0x1,
-       [WM8915_WRITE_SEQUENCER_70] = 0xf,
-       [WM8915_WRITE_SEQUENCER_71] = 0x6,
-       [WM8915_WRITE_SEQUENCER_72] = 0x1,
-       [WM8915_WRITE_SEQUENCER_73] = 0x3,
-       [WM8915_WRITE_SEQUENCER_74] = 0x104,
-       [WM8915_WRITE_SEQUENCER_76] = 0x60,
-       [WM8915_WRITE_SEQUENCER_77] = 0x11,
-       [WM8915_WRITE_SEQUENCER_78] = 0x401,
-       [WM8915_WRITE_SEQUENCER_80] = 0x50,
-       [WM8915_WRITE_SEQUENCER_81] = 0x3,
-       [WM8915_WRITE_SEQUENCER_82] = 0x100,
-       [WM8915_WRITE_SEQUENCER_84] = 0x60,
-       [WM8915_WRITE_SEQUENCER_85] = 0x3b,
-       [WM8915_WRITE_SEQUENCER_86] = 0x502,
-       [WM8915_WRITE_SEQUENCER_87] = 0x100,
-       [WM8915_WRITE_SEQUENCER_88] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_92] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_96] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_100] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_104] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_108] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_112] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_116] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_120] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_124] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_128] = 0x1,
-       [WM8915_WRITE_SEQUENCER_129] = 0x1,
-       [WM8915_WRITE_SEQUENCER_131] = 0x6,
-       [WM8915_WRITE_SEQUENCER_132] = 0x40,
-       [WM8915_WRITE_SEQUENCER_133] = 0x1,
-       [WM8915_WRITE_SEQUENCER_134] = 0xf,
-       [WM8915_WRITE_SEQUENCER_135] = 0x6,
-       [WM8915_WRITE_SEQUENCER_136] = 0x1,
-       [WM8915_WRITE_SEQUENCER_137] = 0x3,
-       [WM8915_WRITE_SEQUENCER_138] = 0x106,
-       [WM8915_WRITE_SEQUENCER_140] = 0x61,
-       [WM8915_WRITE_SEQUENCER_141] = 0x11,
-       [WM8915_WRITE_SEQUENCER_142] = 0x401,
-       [WM8915_WRITE_SEQUENCER_144] = 0x50,
-       [WM8915_WRITE_SEQUENCER_145] = 0x3,
-       [WM8915_WRITE_SEQUENCER_146] = 0x102,
-       [WM8915_WRITE_SEQUENCER_148] = 0x51,
-       [WM8915_WRITE_SEQUENCER_149] = 0x3,
-       [WM8915_WRITE_SEQUENCER_150] = 0x106,
-       [WM8915_WRITE_SEQUENCER_151] = 0xa,
-       [WM8915_WRITE_SEQUENCER_152] = 0x61,
-       [WM8915_WRITE_SEQUENCER_153] = 0x3b,
-       [WM8915_WRITE_SEQUENCER_154] = 0x502,
-       [WM8915_WRITE_SEQUENCER_155] = 0x100,
-       [WM8915_WRITE_SEQUENCER_156] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_160] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_164] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_168] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_172] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_176] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_180] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_184] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_188] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_192] = 0x1,
-       [WM8915_WRITE_SEQUENCER_193] = 0x1,
-       [WM8915_WRITE_SEQUENCER_195] = 0x6,
-       [WM8915_WRITE_SEQUENCER_196] = 0x40,
-       [WM8915_WRITE_SEQUENCER_197] = 0x1,
-       [WM8915_WRITE_SEQUENCER_198] = 0xf,
-       [WM8915_WRITE_SEQUENCER_199] = 0x6,
-       [WM8915_WRITE_SEQUENCER_200] = 0x1,
-       [WM8915_WRITE_SEQUENCER_201] = 0x3,
-       [WM8915_WRITE_SEQUENCER_202] = 0x106,
-       [WM8915_WRITE_SEQUENCER_204] = 0x61,
-       [WM8915_WRITE_SEQUENCER_205] = 0x11,
-       [WM8915_WRITE_SEQUENCER_206] = 0x401,
-       [WM8915_WRITE_SEQUENCER_208] = 0x50,
-       [WM8915_WRITE_SEQUENCER_209] = 0x3,
-       [WM8915_WRITE_SEQUENCER_210] = 0x102,
-       [WM8915_WRITE_SEQUENCER_212] = 0x61,
-       [WM8915_WRITE_SEQUENCER_213] = 0x3b,
-       [WM8915_WRITE_SEQUENCER_214] = 0x502,
-       [WM8915_WRITE_SEQUENCER_215] = 0x100,
-       [WM8915_WRITE_SEQUENCER_216] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_220] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_224] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_228] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_232] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_236] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_240] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_244] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_248] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_252] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_256] = 0x60,
-       [WM8915_WRITE_SEQUENCER_258] = 0x601,
-       [WM8915_WRITE_SEQUENCER_260] = 0x50,
-       [WM8915_WRITE_SEQUENCER_262] = 0x100,
-       [WM8915_WRITE_SEQUENCER_264] = 0x1,
-       [WM8915_WRITE_SEQUENCER_266] = 0x104,
-       [WM8915_WRITE_SEQUENCER_267] = 0x100,
-       [WM8915_WRITE_SEQUENCER_268] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_272] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_276] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_280] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_284] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_288] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_292] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_296] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_300] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_304] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_308] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_312] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_316] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_320] = 0x61,
-       [WM8915_WRITE_SEQUENCER_322] = 0x601,
-       [WM8915_WRITE_SEQUENCER_324] = 0x50,
-       [WM8915_WRITE_SEQUENCER_326] = 0x102,
-       [WM8915_WRITE_SEQUENCER_328] = 0x1,
-       [WM8915_WRITE_SEQUENCER_330] = 0x106,
-       [WM8915_WRITE_SEQUENCER_331] = 0x100,
-       [WM8915_WRITE_SEQUENCER_332] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_336] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_340] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_344] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_348] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_352] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_356] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_360] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_364] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_368] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_372] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_376] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_380] = 0x2fff,
-       [WM8915_WRITE_SEQUENCER_384] = 0x60,
-       [WM8915_WRITE_SEQUENCER_386] = 0x601,
-       [WM8915_WRITE_SEQUENCER_388] = 0x61,
-       [WM8915_WRITE_SEQUENCER_390] = 0x601,
-       [WM8915_WRITE_SEQUENCER_392] = 0x50,
-       [WM8915_WRITE_SEQUENCER_394] = 0x300,
-       [WM8915_WRITE_SEQUENCER_396] = 0x1,
-       [WM8915_WRITE_SEQUENCER_398] = 0x304,
-       [WM8915_WRITE_SEQUENCER_400] = 0x40,
-       [WM8915_WRITE_SEQUENCER_402] = 0xf,
-       [WM8915_WRITE_SEQUENCER_404] = 0x1,
-       [WM8915_WRITE_SEQUENCER_407] = 0x100,
-};
-
-static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0);
-static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 150, 0);
-static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
-static const DECLARE_TLV_DB_SCALE(out_digital_tlv, -1200, 150, 0);
-static const DECLARE_TLV_DB_SCALE(out_tlv, -900, 75, 0);
-static const DECLARE_TLV_DB_SCALE(spk_tlv, -900, 150, 0);
-static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
-
-static const char *sidetone_hpf_text[] = {
-       "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz"
-};
-
-static const struct soc_enum sidetone_hpf =
-       SOC_ENUM_SINGLE(WM8915_SIDETONE, 7, 6, sidetone_hpf_text);
-
-static const char *hpf_mode_text[] = {
-       "HiFi", "Custom", "Voice"
-};
-
-static const struct soc_enum dsp1tx_hpf_mode =
-       SOC_ENUM_SINGLE(WM8915_DSP1_TX_FILTERS, 3, 3, hpf_mode_text);
-
-static const struct soc_enum dsp2tx_hpf_mode =
-       SOC_ENUM_SINGLE(WM8915_DSP2_TX_FILTERS, 3, 3, hpf_mode_text);
-
-static const char *hpf_cutoff_text[] = {
-       "50Hz", "75Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
-};
-
-static const struct soc_enum dsp1tx_hpf_cutoff =
-       SOC_ENUM_SINGLE(WM8915_DSP1_TX_FILTERS, 0, 7, hpf_cutoff_text);
-
-static const struct soc_enum dsp2tx_hpf_cutoff =
-       SOC_ENUM_SINGLE(WM8915_DSP2_TX_FILTERS, 0, 7, hpf_cutoff_text);
-
-static void wm8915_set_retune_mobile(struct snd_soc_codec *codec, int block)
-{
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       struct wm8915_pdata *pdata = &wm8915->pdata;
-       int base, best, best_val, save, i, cfg, iface;
-
-       if (!wm8915->num_retune_mobile_texts)
-               return;
-
-       switch (block) {
-       case 0:
-               base = WM8915_DSP1_RX_EQ_GAINS_1;
-               if (snd_soc_read(codec, WM8915_POWER_MANAGEMENT_8) &
-                   WM8915_DSP1RX_SRC)
-                       iface = 1;
-               else
-                       iface = 0;
-               break;
-       case 1:
-               base = WM8915_DSP1_RX_EQ_GAINS_2;
-               if (snd_soc_read(codec, WM8915_POWER_MANAGEMENT_8) &
-                   WM8915_DSP2RX_SRC)
-                       iface = 1;
-               else
-                       iface = 0;
-               break;
-       default:
-               return;
-       }
-
-       /* Find the version of the currently selected configuration
-        * with the nearest sample rate. */
-       cfg = wm8915->retune_mobile_cfg[block];
-       best = 0;
-       best_val = INT_MAX;
-       for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) {
-               if (strcmp(pdata->retune_mobile_cfgs[i].name,
-                          wm8915->retune_mobile_texts[cfg]) == 0 &&
-                   abs(pdata->retune_mobile_cfgs[i].rate
-                       - wm8915->rx_rate[iface]) < best_val) {
-                       best = i;
-                       best_val = abs(pdata->retune_mobile_cfgs[i].rate
-                                      - wm8915->rx_rate[iface]);
-               }
-       }
-
-       dev_dbg(codec->dev, "ReTune Mobile %d %s/%dHz for %dHz sample rate\n",
-               block,
-               pdata->retune_mobile_cfgs[best].name,
-               pdata->retune_mobile_cfgs[best].rate,
-               wm8915->rx_rate[iface]);
-
-       /* The EQ will be disabled while reconfiguring it, remember the
-        * current configuration. 
-        */
-       save = snd_soc_read(codec, base);
-       save &= WM8915_DSP1RX_EQ_ENA;
-
-       for (i = 0; i < ARRAY_SIZE(pdata->retune_mobile_cfgs[best].regs); i++)
-               snd_soc_update_bits(codec, base + i, 0xffff,
-                                   pdata->retune_mobile_cfgs[best].regs[i]);
-
-       snd_soc_update_bits(codec, base, WM8915_DSP1RX_EQ_ENA, save);
-}
-
-/* Icky as hell but saves code duplication */
-static int wm8915_get_retune_mobile_block(const char *name)
-{
-       if (strcmp(name, "DSP1 EQ Mode") == 0)
-               return 0;
-       if (strcmp(name, "DSP2 EQ Mode") == 0)
-               return 1;
-       return -EINVAL;
-}
-
-static int wm8915_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
-                                        struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       struct wm8915_pdata *pdata = &wm8915->pdata;
-       int block = wm8915_get_retune_mobile_block(kcontrol->id.name);
-       int value = ucontrol->value.integer.value[0];
-
-       if (block < 0)
-               return block;
-
-       if (value >= pdata->num_retune_mobile_cfgs)
-               return -EINVAL;
-
-       wm8915->retune_mobile_cfg[block] = value;
-
-       wm8915_set_retune_mobile(codec, block);
-
-       return 0;
-}
-
-static int wm8915_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
-                                        struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       int block = wm8915_get_retune_mobile_block(kcontrol->id.name);
-
-       ucontrol->value.enumerated.item[0] = wm8915->retune_mobile_cfg[block];
-
-       return 0;
-}
-
-static const struct snd_kcontrol_new wm8915_snd_controls[] = {
-SOC_DOUBLE_R_TLV("Capture Volume", WM8915_LEFT_LINE_INPUT_VOLUME,
-                WM8915_RIGHT_LINE_INPUT_VOLUME, 0, 31, 0, inpga_tlv),
-SOC_DOUBLE_R("Capture ZC Switch", WM8915_LEFT_LINE_INPUT_VOLUME,
-            WM8915_RIGHT_LINE_INPUT_VOLUME, 5, 1, 0),
-
-SOC_DOUBLE_TLV("DAC1 Sidetone Volume", WM8915_DAC1_MIXER_VOLUMES,
-              0, 5, 24, 0, sidetone_tlv),
-SOC_DOUBLE_TLV("DAC2 Sidetone Volume", WM8915_DAC2_MIXER_VOLUMES,
-              0, 5, 24, 0, sidetone_tlv),
-SOC_SINGLE("Sidetone LPF Switch", WM8915_SIDETONE, 12, 1, 0),
-SOC_ENUM("Sidetone HPF Cut-off", sidetone_hpf),
-SOC_SINGLE("Sidetone HPF Switch", WM8915_SIDETONE, 6, 1, 0),
-
-SOC_DOUBLE_R_TLV("DSP1 Capture Volume", WM8915_DSP1_TX_LEFT_VOLUME,
-                WM8915_DSP1_TX_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
-SOC_DOUBLE_R_TLV("DSP2 Capture Volume", WM8915_DSP2_TX_LEFT_VOLUME,
-                WM8915_DSP2_TX_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
-
-SOC_SINGLE("DSP1 Capture Notch Filter Switch", WM8915_DSP1_TX_FILTERS,
-          13, 1, 0),
-SOC_DOUBLE("DSP1 Capture HPF Switch", WM8915_DSP1_TX_FILTERS, 12, 11, 1, 0),
-SOC_ENUM("DSP1 Capture HPF Mode", dsp1tx_hpf_mode),
-SOC_ENUM("DSP1 Capture HPF Cutoff", dsp1tx_hpf_cutoff),
-
-SOC_SINGLE("DSP2 Capture Notch Filter Switch", WM8915_DSP2_TX_FILTERS,
-          13, 1, 0),
-SOC_DOUBLE("DSP2 Capture HPF Switch", WM8915_DSP2_TX_FILTERS, 12, 11, 1, 0),
-SOC_ENUM("DSP2 Capture HPF Mode", dsp2tx_hpf_mode),
-SOC_ENUM("DSP2 Capture HPF Cutoff", dsp2tx_hpf_cutoff),
-
-SOC_DOUBLE_R_TLV("DSP1 Playback Volume", WM8915_DSP1_RX_LEFT_VOLUME,
-                WM8915_DSP1_RX_RIGHT_VOLUME, 1, 112, 0, digital_tlv),
-SOC_SINGLE("DSP1 Playback Switch", WM8915_DSP1_RX_FILTERS_1, 9, 1, 1),
-
-SOC_DOUBLE_R_TLV("DSP2 Playback Volume", WM8915_DSP2_RX_LEFT_VOLUME,
-                WM8915_DSP2_RX_RIGHT_VOLUME, 1, 112, 0, digital_tlv),
-SOC_SINGLE("DSP2 Playback Switch", WM8915_DSP2_RX_FILTERS_1, 9, 1, 1),
-
-SOC_DOUBLE_R_TLV("DAC1 Volume", WM8915_DAC1_LEFT_VOLUME,
-                WM8915_DAC1_RIGHT_VOLUME, 1, 112, 0, digital_tlv),
-SOC_DOUBLE_R("DAC1 Switch", WM8915_DAC1_LEFT_VOLUME,
-            WM8915_DAC1_RIGHT_VOLUME, 9, 1, 1),
-
-SOC_DOUBLE_R_TLV("DAC2 Volume", WM8915_DAC2_LEFT_VOLUME,
-                WM8915_DAC2_RIGHT_VOLUME, 1, 112, 0, digital_tlv),
-SOC_DOUBLE_R("DAC2 Switch", WM8915_DAC2_LEFT_VOLUME,
-            WM8915_DAC2_RIGHT_VOLUME, 9, 1, 1),
-
-SOC_SINGLE("Speaker High Performance Switch", WM8915_OVERSAMPLING, 3, 1, 0),
-SOC_SINGLE("DMIC High Performance Switch", WM8915_OVERSAMPLING, 2, 1, 0),
-SOC_SINGLE("ADC High Performance Switch", WM8915_OVERSAMPLING, 1, 1, 0),
-SOC_SINGLE("DAC High Performance Switch", WM8915_OVERSAMPLING, 0, 1, 0),
-
-SOC_SINGLE("DAC Soft Mute Switch", WM8915_DAC_SOFTMUTE, 1, 1, 0),
-SOC_SINGLE("DAC Slow Soft Mute Switch", WM8915_DAC_SOFTMUTE, 0, 1, 0),
-
-SOC_DOUBLE_TLV("Digital Output 1 Volume", WM8915_DAC1_HPOUT1_VOLUME, 0, 4,
-              8, 0, out_digital_tlv),
-SOC_DOUBLE_TLV("Digital Output 2 Volume", WM8915_DAC2_HPOUT2_VOLUME, 0, 4,
-              8, 0, out_digital_tlv),
-
-SOC_DOUBLE_R_TLV("Output 1 Volume", WM8915_OUTPUT1_LEFT_VOLUME,
-                WM8915_OUTPUT1_RIGHT_VOLUME, 0, 12, 0, out_tlv),
-SOC_DOUBLE_R("Output 1 ZC Switch",  WM8915_OUTPUT1_LEFT_VOLUME,
-            WM8915_OUTPUT1_RIGHT_VOLUME, 7, 1, 0),
-
-SOC_DOUBLE_R_TLV("Output 2 Volume", WM8915_OUTPUT2_LEFT_VOLUME,
-                WM8915_OUTPUT2_RIGHT_VOLUME, 0, 12, 0, out_tlv),
-SOC_DOUBLE_R("Output 2 ZC Switch",  WM8915_OUTPUT2_LEFT_VOLUME,
-            WM8915_OUTPUT2_RIGHT_VOLUME, 7, 1, 0),
-
-SOC_DOUBLE_TLV("Speaker Volume", WM8915_PDM_SPEAKER_VOLUME, 0, 4, 8, 0,
-              spk_tlv),
-SOC_DOUBLE_R("Speaker Switch", WM8915_LEFT_PDM_SPEAKER,
-            WM8915_RIGHT_PDM_SPEAKER, 3, 1, 1),
-SOC_DOUBLE_R("Speaker ZC Switch", WM8915_LEFT_PDM_SPEAKER,
-            WM8915_RIGHT_PDM_SPEAKER, 2, 1, 0),
-
-SOC_SINGLE("DSP1 EQ Switch", WM8915_DSP1_RX_EQ_GAINS_1, 0, 1, 0),
-SOC_SINGLE("DSP2 EQ Switch", WM8915_DSP2_RX_EQ_GAINS_1, 0, 1, 0),
-};
-
-static const struct snd_kcontrol_new wm8915_eq_controls[] = {
-SOC_SINGLE_TLV("DSP1 EQ B1 Volume", WM8915_DSP1_RX_EQ_GAINS_1, 11, 31, 0,
-              eq_tlv),
-SOC_SINGLE_TLV("DSP1 EQ B2 Volume", WM8915_DSP1_RX_EQ_GAINS_1, 6, 31, 0,
-              eq_tlv),
-SOC_SINGLE_TLV("DSP1 EQ B3 Volume", WM8915_DSP1_RX_EQ_GAINS_1, 1, 31, 0,
-              eq_tlv),
-SOC_SINGLE_TLV("DSP1 EQ B4 Volume", WM8915_DSP1_RX_EQ_GAINS_2, 11, 31, 0,
-              eq_tlv),
-SOC_SINGLE_TLV("DSP1 EQ B5 Volume", WM8915_DSP1_RX_EQ_GAINS_2, 6, 31, 0,
-              eq_tlv),
-
-SOC_SINGLE_TLV("DSP2 EQ B1 Volume", WM8915_DSP2_RX_EQ_GAINS_1, 11, 31, 0,
-              eq_tlv),
-SOC_SINGLE_TLV("DSP2 EQ B2 Volume", WM8915_DSP2_RX_EQ_GAINS_1, 6, 31, 0,
-              eq_tlv),
-SOC_SINGLE_TLV("DSP2 EQ B3 Volume", WM8915_DSP2_RX_EQ_GAINS_1, 1, 31, 0,
-              eq_tlv),
-SOC_SINGLE_TLV("DSP2 EQ B4 Volume", WM8915_DSP2_RX_EQ_GAINS_2, 11, 31, 0,
-              eq_tlv),
-SOC_SINGLE_TLV("DSP2 EQ B5 Volume", WM8915_DSP2_RX_EQ_GAINS_2, 6, 31, 0,
-              eq_tlv),
-};
-
-static int cp_event(struct snd_soc_dapm_widget *w,
-                   struct snd_kcontrol *kcontrol, int event)
-{
-       switch (event) {
-       case SND_SOC_DAPM_POST_PMU:
-               msleep(5);
-               break;
-       default:
-               BUG();
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int rmv_short_event(struct snd_soc_dapm_widget *w,
-                          struct snd_kcontrol *kcontrol, int event)
-{
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(w->codec);
-
-       /* Record which outputs we enabled */
-       switch (event) {
-       case SND_SOC_DAPM_PRE_PMD:
-               wm8915->hpout_pending &= ~w->shift;
-               break;
-       case SND_SOC_DAPM_PRE_PMU:
-               wm8915->hpout_pending |= w->shift;
-               break;
-       default:
-               BUG();
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask)
-{
-       struct i2c_client *i2c = to_i2c_client(codec->dev);
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       int i, ret;
-       unsigned long timeout = 200;
-
-       snd_soc_write(codec, WM8915_DC_SERVO_2, mask);
-
-       /* Use the interrupt if possible */
-       do {
-               if (i2c->irq) {
-                       timeout = wait_for_completion_timeout(&wm8915->dcs_done,
-                                                             msecs_to_jiffies(200));
-                       if (timeout == 0)
-                               dev_err(codec->dev, "DC servo timed out\n");
-
-               } else {
-                       msleep(1);
-                       if (--i) {
-                               timeout = 0;
-                               break;
-                       }
-               }
-
-               ret = snd_soc_read(codec, WM8915_DC_SERVO_2);
-               dev_dbg(codec->dev, "DC servo state: %x\n", ret);
-       } while (ret & mask);
-
-       if (timeout == 0)
-               dev_err(codec->dev, "DC servo timed out for %x\n", mask);
-       else
-               dev_dbg(codec->dev, "DC servo complete for %x\n", mask);
-}
-
-static void wm8915_seq_notifier(struct snd_soc_dapm_context *dapm,
-                               enum snd_soc_dapm_type event, int subseq)
-{
-       struct snd_soc_codec *codec = container_of(dapm,
-                                                  struct snd_soc_codec, dapm);
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       u16 val, mask;
-
-       /* Complete any pending DC servo starts */
-       if (wm8915->dcs_pending) {
-               dev_dbg(codec->dev, "Starting DC servo for %x\n",
-                       wm8915->dcs_pending);
-
-               /* Trigger a startup sequence */
-               wait_for_dc_servo(codec, wm8915->dcs_pending
-                                        << WM8915_DCS_TRIG_STARTUP_0_SHIFT);
-
-               wm8915->dcs_pending = 0;
-       }
-
-       if (wm8915->hpout_pending != wm8915->hpout_ena) {
-               dev_dbg(codec->dev, "Applying RMV_SHORTs %x->%x\n",
-                       wm8915->hpout_ena, wm8915->hpout_pending);
-
-               val = 0;
-               mask = 0;
-               if (wm8915->hpout_pending & HPOUT1L) {
-                       val |= WM8915_HPOUT1L_RMV_SHORT;
-                       mask |= WM8915_HPOUT1L_RMV_SHORT;
-               } else {
-                       mask |= WM8915_HPOUT1L_RMV_SHORT |
-                               WM8915_HPOUT1L_OUTP |
-                               WM8915_HPOUT1L_DLY;
-               }
-
-               if (wm8915->hpout_pending & HPOUT1R) {
-                       val |= WM8915_HPOUT1R_RMV_SHORT;
-                       mask |= WM8915_HPOUT1R_RMV_SHORT;
-               } else {
-                       mask |= WM8915_HPOUT1R_RMV_SHORT |
-                               WM8915_HPOUT1R_OUTP |
-                               WM8915_HPOUT1R_DLY;
-               }
-
-               snd_soc_update_bits(codec, WM8915_ANALOGUE_HP_1, mask, val);
-
-               val = 0;
-               mask = 0;
-               if (wm8915->hpout_pending & HPOUT2L) {
-                       val |= WM8915_HPOUT2L_RMV_SHORT;
-                       mask |= WM8915_HPOUT2L_RMV_SHORT;
-               } else {
-                       mask |= WM8915_HPOUT2L_RMV_SHORT |
-                               WM8915_HPOUT2L_OUTP |
-                               WM8915_HPOUT2L_DLY;
-               }
-
-               if (wm8915->hpout_pending & HPOUT2R) {
-                       val |= WM8915_HPOUT2R_RMV_SHORT;
-                       mask |= WM8915_HPOUT2R_RMV_SHORT;
-               } else {
-                       mask |= WM8915_HPOUT2R_RMV_SHORT |
-                               WM8915_HPOUT2R_OUTP |
-                               WM8915_HPOUT2R_DLY;
-               }
-
-               snd_soc_update_bits(codec, WM8915_ANALOGUE_HP_2, mask, val);
-
-               wm8915->hpout_ena = wm8915->hpout_pending;
-       }
-}
-
-static int dcs_start(struct snd_soc_dapm_widget *w,
-                    struct snd_kcontrol *kcontrol, int event)
-{
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(w->codec);
-
-       switch (event) {
-       case SND_SOC_DAPM_POST_PMU:
-               wm8915->dcs_pending |= 1 << w->shift;
-               break;
-       default:
-               BUG();
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static const char *sidetone_text[] = {
-       "IN1", "IN2",
-};
-
-static const struct soc_enum left_sidetone_enum =
-       SOC_ENUM_SINGLE(WM8915_SIDETONE, 0, 2, sidetone_text);
-
-static const struct snd_kcontrol_new left_sidetone =
-       SOC_DAPM_ENUM("Left Sidetone", left_sidetone_enum);
-
-static const struct soc_enum right_sidetone_enum =
-       SOC_ENUM_SINGLE(WM8915_SIDETONE, 1, 2, sidetone_text);
-
-static const struct snd_kcontrol_new right_sidetone =
-       SOC_DAPM_ENUM("Right Sidetone", right_sidetone_enum);
-
-static const char *spk_text[] = {
-       "DAC1L", "DAC1R", "DAC2L", "DAC2R"
-};
-
-static const struct soc_enum spkl_enum =
-       SOC_ENUM_SINGLE(WM8915_LEFT_PDM_SPEAKER, 0, 4, spk_text);
-
-static const struct snd_kcontrol_new spkl_mux =
-       SOC_DAPM_ENUM("SPKL", spkl_enum);
-
-static const struct soc_enum spkr_enum =
-       SOC_ENUM_SINGLE(WM8915_RIGHT_PDM_SPEAKER, 0, 4, spk_text);
-
-static const struct snd_kcontrol_new spkr_mux =
-       SOC_DAPM_ENUM("SPKR", spkr_enum);
-
-static const char *dsp1rx_text[] = {
-       "AIF1", "AIF2"
-};
-
-static const struct soc_enum dsp1rx_enum =
-       SOC_ENUM_SINGLE(WM8915_POWER_MANAGEMENT_8, 0, 2, dsp1rx_text);
-
-static const struct snd_kcontrol_new dsp1rx =
-       SOC_DAPM_ENUM("DSP1RX", dsp1rx_enum);
-
-static const char *dsp2rx_text[] = {
-        "AIF2", "AIF1"
-};
-
-static const struct soc_enum dsp2rx_enum =
-       SOC_ENUM_SINGLE(WM8915_POWER_MANAGEMENT_8, 4, 2, dsp2rx_text);
-
-static const struct snd_kcontrol_new dsp2rx =
-       SOC_DAPM_ENUM("DSP2RX", dsp2rx_enum);
-
-static const char *aif2tx_text[] = {
-       "DSP2", "DSP1", "AIF1"
-};
-
-static const struct soc_enum aif2tx_enum =
-       SOC_ENUM_SINGLE(WM8915_POWER_MANAGEMENT_8, 6, 3, aif2tx_text);
-
-static const struct snd_kcontrol_new aif2tx =
-       SOC_DAPM_ENUM("AIF2TX", aif2tx_enum);
-
-static const char *inmux_text[] = {
-       "ADC", "DMIC1", "DMIC2"
-};
-
-static const struct soc_enum in1_enum =
-       SOC_ENUM_SINGLE(WM8915_POWER_MANAGEMENT_7, 0, 3, inmux_text);
-
-static const struct snd_kcontrol_new in1_mux =
-       SOC_DAPM_ENUM("IN1 Mux", in1_enum);
-
-static const struct soc_enum in2_enum =
-       SOC_ENUM_SINGLE(WM8915_POWER_MANAGEMENT_7, 4, 3, inmux_text);
-
-static const struct snd_kcontrol_new in2_mux =
-       SOC_DAPM_ENUM("IN2 Mux", in2_enum);
-
-static const struct snd_kcontrol_new dac2r_mix[] = {
-SOC_DAPM_SINGLE("Right Sidetone Switch", WM8915_DAC2_RIGHT_MIXER_ROUTING,
-               5, 1, 0),
-SOC_DAPM_SINGLE("Left Sidetone Switch", WM8915_DAC2_RIGHT_MIXER_ROUTING,
-               4, 1, 0),
-SOC_DAPM_SINGLE("DSP2 Switch", WM8915_DAC2_RIGHT_MIXER_ROUTING, 1, 1, 0),
-SOC_DAPM_SINGLE("DSP1 Switch", WM8915_DAC2_RIGHT_MIXER_ROUTING, 0, 1, 0),
-};
-
-static const struct snd_kcontrol_new dac2l_mix[] = {
-SOC_DAPM_SINGLE("Right Sidetone Switch", WM8915_DAC2_LEFT_MIXER_ROUTING,
-               5, 1, 0),
-SOC_DAPM_SINGLE("Left Sidetone Switch", WM8915_DAC2_LEFT_MIXER_ROUTING,
-               4, 1, 0),
-SOC_DAPM_SINGLE("DSP2 Switch", WM8915_DAC2_LEFT_MIXER_ROUTING, 1, 1, 0),
-SOC_DAPM_SINGLE("DSP1 Switch", WM8915_DAC2_LEFT_MIXER_ROUTING, 0, 1, 0),
-};
-
-static const struct snd_kcontrol_new dac1r_mix[] = {
-SOC_DAPM_SINGLE("Right Sidetone Switch", WM8915_DAC1_RIGHT_MIXER_ROUTING,
-               5, 1, 0),
-SOC_DAPM_SINGLE("Left Sidetone Switch", WM8915_DAC1_RIGHT_MIXER_ROUTING,
-               4, 1, 0),
-SOC_DAPM_SINGLE("DSP2 Switch", WM8915_DAC1_RIGHT_MIXER_ROUTING, 1, 1, 0),
-SOC_DAPM_SINGLE("DSP1 Switch", WM8915_DAC1_RIGHT_MIXER_ROUTING, 0, 1, 0),
-};
-
-static const struct snd_kcontrol_new dac1l_mix[] = {
-SOC_DAPM_SINGLE("Right Sidetone Switch", WM8915_DAC1_LEFT_MIXER_ROUTING,
-               5, 1, 0),
-SOC_DAPM_SINGLE("Left Sidetone Switch", WM8915_DAC1_LEFT_MIXER_ROUTING,
-               4, 1, 0),
-SOC_DAPM_SINGLE("DSP2 Switch", WM8915_DAC1_LEFT_MIXER_ROUTING, 1, 1, 0),
-SOC_DAPM_SINGLE("DSP1 Switch", WM8915_DAC1_LEFT_MIXER_ROUTING, 0, 1, 0),
-};
-
-static const struct snd_kcontrol_new dsp1txl[] = {
-SOC_DAPM_SINGLE("IN1 Switch", WM8915_DSP1_TX_LEFT_MIXER_ROUTING,
-               1, 1, 0),
-SOC_DAPM_SINGLE("DAC Switch", WM8915_DSP1_TX_LEFT_MIXER_ROUTING,
-               0, 1, 0),
-};
-
-static const struct snd_kcontrol_new dsp1txr[] = {
-SOC_DAPM_SINGLE("IN1 Switch", WM8915_DSP1_TX_RIGHT_MIXER_ROUTING,
-               1, 1, 0),
-SOC_DAPM_SINGLE("DAC Switch", WM8915_DSP1_TX_RIGHT_MIXER_ROUTING,
-               0, 1, 0),
-};
-
-static const struct snd_kcontrol_new dsp2txl[] = {
-SOC_DAPM_SINGLE("IN1 Switch", WM8915_DSP2_TX_LEFT_MIXER_ROUTING,
-               1, 1, 0),
-SOC_DAPM_SINGLE("DAC Switch", WM8915_DSP2_TX_LEFT_MIXER_ROUTING,
-               0, 1, 0),
-};
-
-static const struct snd_kcontrol_new dsp2txr[] = {
-SOC_DAPM_SINGLE("IN1 Switch", WM8915_DSP2_TX_RIGHT_MIXER_ROUTING,
-               1, 1, 0),
-SOC_DAPM_SINGLE("DAC Switch", WM8915_DSP2_TX_RIGHT_MIXER_ROUTING,
-               0, 1, 0),
-};
-
-
-static const struct snd_soc_dapm_widget wm8915_dapm_widgets[] = {
-SND_SOC_DAPM_INPUT("IN1LN"),
-SND_SOC_DAPM_INPUT("IN1LP"),
-SND_SOC_DAPM_INPUT("IN1RN"),
-SND_SOC_DAPM_INPUT("IN1RP"),
-
-SND_SOC_DAPM_INPUT("IN2LN"),
-SND_SOC_DAPM_INPUT("IN2LP"),
-SND_SOC_DAPM_INPUT("IN2RN"),
-SND_SOC_DAPM_INPUT("IN2RP"),
-
-SND_SOC_DAPM_INPUT("DMIC1DAT"),
-SND_SOC_DAPM_INPUT("DMIC2DAT"),
-
-SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8915_AIF_CLOCKING_1, 0, 0, NULL, 0),
-SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8915_CLOCKING_1, 1, 0, NULL, 0),
-SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8915_CLOCKING_1, 2, 0, NULL, 0),
-SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8915_CHARGE_PUMP_1, 15, 0, cp_event,
-                     SND_SOC_DAPM_POST_PMU),
-
-SND_SOC_DAPM_SUPPLY("LDO2", WM8915_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
-SND_SOC_DAPM_MICBIAS("MICB2", WM8915_POWER_MANAGEMENT_1, 9, 0),
-SND_SOC_DAPM_MICBIAS("MICB1", WM8915_POWER_MANAGEMENT_1, 8, 0),
-
-SND_SOC_DAPM_PGA("IN1L PGA", WM8915_POWER_MANAGEMENT_2, 5, 0, NULL, 0),
-SND_SOC_DAPM_PGA("IN1R PGA", WM8915_POWER_MANAGEMENT_2, 4, 0, NULL, 0),
-
-SND_SOC_DAPM_MUX("IN1L Mux", SND_SOC_NOPM, 0, 0, &in1_mux),
-SND_SOC_DAPM_MUX("IN1R Mux", SND_SOC_NOPM, 0, 0, &in1_mux),
-SND_SOC_DAPM_MUX("IN2L Mux", SND_SOC_NOPM, 0, 0, &in2_mux),
-SND_SOC_DAPM_MUX("IN2R Mux", SND_SOC_NOPM, 0, 0, &in2_mux),
-
-SND_SOC_DAPM_PGA("IN1L", WM8915_POWER_MANAGEMENT_7, 2, 0, NULL, 0),
-SND_SOC_DAPM_PGA("IN1R", WM8915_POWER_MANAGEMENT_7, 3, 0, NULL, 0),
-SND_SOC_DAPM_PGA("IN2L", WM8915_POWER_MANAGEMENT_7, 6, 0, NULL, 0),
-SND_SOC_DAPM_PGA("IN2R", WM8915_POWER_MANAGEMENT_7, 7, 0, NULL, 0),
-
-SND_SOC_DAPM_SUPPLY("DMIC2", WM8915_POWER_MANAGEMENT_7, 9, 0, NULL, 0),
-SND_SOC_DAPM_SUPPLY("DMIC1", WM8915_POWER_MANAGEMENT_7, 8, 0, NULL, 0),
-
-SND_SOC_DAPM_ADC("DMIC2L", NULL, WM8915_POWER_MANAGEMENT_3, 5, 0),
-SND_SOC_DAPM_ADC("DMIC2R", NULL, WM8915_POWER_MANAGEMENT_3, 4, 0),
-SND_SOC_DAPM_ADC("DMIC1L", NULL, WM8915_POWER_MANAGEMENT_3, 3, 0),
-SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8915_POWER_MANAGEMENT_3, 2, 0),
-
-SND_SOC_DAPM_ADC("ADCL", NULL, WM8915_POWER_MANAGEMENT_3, 1, 0),
-SND_SOC_DAPM_ADC("ADCR", NULL, WM8915_POWER_MANAGEMENT_3, 0, 0),
-
-SND_SOC_DAPM_MUX("Left Sidetone", SND_SOC_NOPM, 0, 0, &left_sidetone),
-SND_SOC_DAPM_MUX("Right Sidetone", SND_SOC_NOPM, 0, 0, &right_sidetone),
-
-SND_SOC_DAPM_AIF_IN("DSP2RXL", NULL, 0, WM8915_POWER_MANAGEMENT_3, 11, 0),
-SND_SOC_DAPM_AIF_IN("DSP2RXR", NULL, 1, WM8915_POWER_MANAGEMENT_3, 10, 0),
-SND_SOC_DAPM_AIF_IN("DSP1RXL", NULL, 0, WM8915_POWER_MANAGEMENT_3, 9, 0),
-SND_SOC_DAPM_AIF_IN("DSP1RXR", NULL, 1, WM8915_POWER_MANAGEMENT_3, 8, 0),
-
-SND_SOC_DAPM_MIXER("DSP2TXL", WM8915_POWER_MANAGEMENT_5, 11, 0,
-                  dsp2txl, ARRAY_SIZE(dsp2txl)),
-SND_SOC_DAPM_MIXER("DSP2TXR", WM8915_POWER_MANAGEMENT_5, 10, 0,
-                  dsp2txr, ARRAY_SIZE(dsp2txr)),
-SND_SOC_DAPM_MIXER("DSP1TXL", WM8915_POWER_MANAGEMENT_5, 9, 0,
-                  dsp1txl, ARRAY_SIZE(dsp1txl)),
-SND_SOC_DAPM_MIXER("DSP1TXR", WM8915_POWER_MANAGEMENT_5, 8, 0,
-                  dsp1txr, ARRAY_SIZE(dsp1txr)),
-
-SND_SOC_DAPM_MIXER("DAC2L Mixer", SND_SOC_NOPM, 0, 0,
-                  dac2l_mix, ARRAY_SIZE(dac2l_mix)),
-SND_SOC_DAPM_MIXER("DAC2R Mixer", SND_SOC_NOPM, 0, 0,
-                  dac2r_mix, ARRAY_SIZE(dac2r_mix)),
-SND_SOC_DAPM_MIXER("DAC1L Mixer", SND_SOC_NOPM, 0, 0,
-                  dac1l_mix, ARRAY_SIZE(dac1l_mix)),
-SND_SOC_DAPM_MIXER("DAC1R Mixer", SND_SOC_NOPM, 0, 0,
-                  dac1r_mix, ARRAY_SIZE(dac1r_mix)),
-
-SND_SOC_DAPM_DAC("DAC2L", NULL, WM8915_POWER_MANAGEMENT_5, 3, 0),
-SND_SOC_DAPM_DAC("DAC2R", NULL, WM8915_POWER_MANAGEMENT_5, 2, 0),
-SND_SOC_DAPM_DAC("DAC1L", NULL, WM8915_POWER_MANAGEMENT_5, 1, 0),
-SND_SOC_DAPM_DAC("DAC1R", NULL, WM8915_POWER_MANAGEMENT_5, 0, 0),
-
-SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 1,
-                   WM8915_POWER_MANAGEMENT_4, 9, 0),
-SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 2,
-                   WM8915_POWER_MANAGEMENT_4, 8, 0),
-
-SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 1,
-                   WM8915_POWER_MANAGEMENT_6, 9, 0),
-SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 2,
-                   WM8915_POWER_MANAGEMENT_6, 8, 0),
-
-SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5,
-                   WM8915_POWER_MANAGEMENT_4, 5, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 4,
-                   WM8915_POWER_MANAGEMENT_4, 4, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 3,
-                   WM8915_POWER_MANAGEMENT_4, 3, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 2,
-                   WM8915_POWER_MANAGEMENT_4, 2, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 1,
-                   WM8915_POWER_MANAGEMENT_4, 1, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX0", "AIF1 Playback", 0,
-                   WM8915_POWER_MANAGEMENT_4, 0, 0),
-
-SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 5,
-                    WM8915_POWER_MANAGEMENT_6, 5, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 4,
-                    WM8915_POWER_MANAGEMENT_6, 4, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 3,
-                    WM8915_POWER_MANAGEMENT_6, 3, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 2,
-                    WM8915_POWER_MANAGEMENT_6, 2, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 1,
-                    WM8915_POWER_MANAGEMENT_6, 1, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX0", "AIF1 Capture", 0,
-                    WM8915_POWER_MANAGEMENT_6, 0, 0),
-
-/* We route as stereo pairs so define some dummy widgets to squash
- * things down for now.  RXA = 0,1, RXB = 2,3 and so on */
-SND_SOC_DAPM_PGA("AIF1RXA", SND_SOC_NOPM, 0, 0, NULL, 0),
-SND_SOC_DAPM_PGA("AIF1RXB", SND_SOC_NOPM, 0, 0, NULL, 0),
-SND_SOC_DAPM_PGA("AIF1RXC", SND_SOC_NOPM, 0, 0, NULL, 0),
-SND_SOC_DAPM_PGA("AIF2RX", SND_SOC_NOPM, 0, 0, NULL, 0),
-SND_SOC_DAPM_PGA("DSP2TX", SND_SOC_NOPM, 0, 0, NULL, 0),
-
-SND_SOC_DAPM_MUX("DSP1RX", SND_SOC_NOPM, 0, 0, &dsp1rx),
-SND_SOC_DAPM_MUX("DSP2RX", SND_SOC_NOPM, 0, 0, &dsp2rx),
-SND_SOC_DAPM_MUX("AIF2TX", SND_SOC_NOPM, 0, 0, &aif2tx),
-
-SND_SOC_DAPM_MUX("SPKL", SND_SOC_NOPM, 0, 0, &spkl_mux),
-SND_SOC_DAPM_MUX("SPKR", SND_SOC_NOPM, 0, 0, &spkr_mux),
-SND_SOC_DAPM_PGA("SPKL PGA", WM8915_LEFT_PDM_SPEAKER, 4, 0, NULL, 0),
-SND_SOC_DAPM_PGA("SPKR PGA", WM8915_RIGHT_PDM_SPEAKER, 4, 0, NULL, 0),
-
-SND_SOC_DAPM_PGA_S("HPOUT2L PGA", 0, WM8915_POWER_MANAGEMENT_1, 7, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPOUT2L_DLY", 1, WM8915_ANALOGUE_HP_2, 5, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPOUT2L_DCS", 2, WM8915_DC_SERVO_1, 2, 0, dcs_start,
-                  SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT2L_OUTP", 3, WM8915_ANALOGUE_HP_2, 6, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPOUT2L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2L, 0,
-                  rmv_short_event,
-                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
-
-SND_SOC_DAPM_PGA_S("HPOUT2R PGA", 0, WM8915_POWER_MANAGEMENT_1, 6, 0,NULL, 0),
-SND_SOC_DAPM_PGA_S("HPOUT2R_DLY", 1, WM8915_ANALOGUE_HP_2, 1, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPOUT2R_DCS", 2, WM8915_DC_SERVO_1, 3, 0, dcs_start,
-                  SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT2R_OUTP", 3, WM8915_ANALOGUE_HP_2, 2, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPOUT2R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2R, 0,
-                  rmv_short_event,
-                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
-
-SND_SOC_DAPM_PGA_S("HPOUT1L PGA", 0, WM8915_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPOUT1L_DLY", 1, WM8915_ANALOGUE_HP_1, 5, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPOUT1L_DCS", 2, WM8915_DC_SERVO_1, 0, 0, dcs_start,
-                  SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT1L_OUTP", 3, WM8915_ANALOGUE_HP_1, 6, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPOUT1L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1L, 0,
-                  rmv_short_event,
-                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
-
-SND_SOC_DAPM_PGA_S("HPOUT1R PGA", 0, WM8915_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPOUT1R_DLY", 1, WM8915_ANALOGUE_HP_1, 1, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPOUT1R_DCS", 2, WM8915_DC_SERVO_1, 1, 0, dcs_start,
-                  SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT1R_OUTP", 3, WM8915_ANALOGUE_HP_1, 2, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPOUT1R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1R, 0,
-                  rmv_short_event,
-                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
-
-SND_SOC_DAPM_OUTPUT("HPOUT1L"),
-SND_SOC_DAPM_OUTPUT("HPOUT1R"),
-SND_SOC_DAPM_OUTPUT("HPOUT2L"),
-SND_SOC_DAPM_OUTPUT("HPOUT2R"),
-SND_SOC_DAPM_OUTPUT("SPKDAT"),
-};
-
-static const struct snd_soc_dapm_route wm8915_dapm_routes[] = {
-       { "AIFCLK", NULL, "SYSCLK" },
-       { "SYSDSPCLK", NULL, "SYSCLK" },
-       { "Charge Pump", NULL, "SYSCLK" },
-
-       { "MICB1", NULL, "LDO2" },
-       { "MICB2", NULL, "LDO2" },
-
-       { "IN1L PGA", NULL, "IN2LN" },
-       { "IN1L PGA", NULL, "IN2LP" },
-       { "IN1L PGA", NULL, "IN1LN" },
-       { "IN1L PGA", NULL, "IN1LP" },
-
-       { "IN1R PGA", NULL, "IN2RN" },
-       { "IN1R PGA", NULL, "IN2RP" },
-       { "IN1R PGA", NULL, "IN1RN" },
-       { "IN1R PGA", NULL, "IN1RP" },
-
-       { "ADCL", NULL, "IN1L PGA" },
-
-       { "ADCR", NULL, "IN1R PGA" },
-
-       { "DMIC1L", NULL, "DMIC1DAT" },
-       { "DMIC1R", NULL, "DMIC1DAT" },
-       { "DMIC2L", NULL, "DMIC2DAT" },
-       { "DMIC2R", NULL, "DMIC2DAT" },
-
-       { "DMIC2L", NULL, "DMIC2" },
-       { "DMIC2R", NULL, "DMIC2" },
-       { "DMIC1L", NULL, "DMIC1" },
-       { "DMIC1R", NULL, "DMIC1" },
-
-       { "IN1L Mux", "ADC", "ADCL" },
-       { "IN1L Mux", "DMIC1", "DMIC1L" },
-       { "IN1L Mux", "DMIC2", "DMIC2L" },
-
-       { "IN1R Mux", "ADC", "ADCR" },
-       { "IN1R Mux", "DMIC1", "DMIC1R" },
-       { "IN1R Mux", "DMIC2", "DMIC2R" },
-
-       { "IN2L Mux", "ADC", "ADCL" },
-       { "IN2L Mux", "DMIC1", "DMIC1L" },
-       { "IN2L Mux", "DMIC2", "DMIC2L" },
-
-       { "IN2R Mux", "ADC", "ADCR" },
-       { "IN2R Mux", "DMIC1", "DMIC1R" },
-       { "IN2R Mux", "DMIC2", "DMIC2R" },
-
-       { "Left Sidetone", "IN1", "IN1L Mux" },
-       { "Left Sidetone", "IN2", "IN2L Mux" },
-
-       { "Right Sidetone", "IN1", "IN1R Mux" },
-       { "Right Sidetone", "IN2", "IN2R Mux" },
-
-       { "DSP1TXL", "IN1 Switch", "IN1L Mux" },
-       { "DSP1TXR", "IN1 Switch", "IN1R Mux" },
-
-       { "DSP2TXL", "IN1 Switch", "IN2L Mux" },
-       { "DSP2TXR", "IN1 Switch", "IN2R Mux" },
-
-       { "AIF1TX0", NULL, "DSP1TXL" },
-       { "AIF1TX1", NULL, "DSP1TXR" },
-       { "AIF1TX2", NULL, "DSP2TXL" },
-       { "AIF1TX3", NULL, "DSP2TXR" },
-       { "AIF1TX4", NULL, "AIF2RX0" },
-       { "AIF1TX5", NULL, "AIF2RX1" },
-
-       { "AIF1RX0", NULL, "AIFCLK" },
-       { "AIF1RX1", NULL, "AIFCLK" },
-       { "AIF1RX2", NULL, "AIFCLK" },
-       { "AIF1RX3", NULL, "AIFCLK" },
-       { "AIF1RX4", NULL, "AIFCLK" },
-       { "AIF1RX5", NULL, "AIFCLK" },
-
-       { "AIF2RX0", NULL, "AIFCLK" },
-       { "AIF2RX1", NULL, "AIFCLK" },
-
-       { "DSP1RXL", NULL, "SYSDSPCLK" },
-       { "DSP1RXR", NULL, "SYSDSPCLK" },
-       { "DSP2RXL", NULL, "SYSDSPCLK" },
-       { "DSP2RXR", NULL, "SYSDSPCLK" },
-       { "DSP1TXL", NULL, "SYSDSPCLK" },
-       { "DSP1TXR", NULL, "SYSDSPCLK" },
-       { "DSP2TXL", NULL, "SYSDSPCLK" },
-       { "DSP2TXR", NULL, "SYSDSPCLK" },
-
-       { "AIF1RXA", NULL, "AIF1RX0" },
-       { "AIF1RXA", NULL, "AIF1RX1" },
-       { "AIF1RXB", NULL, "AIF1RX2" },
-       { "AIF1RXB", NULL, "AIF1RX3" },
-       { "AIF1RXC", NULL, "AIF1RX4" },
-       { "AIF1RXC", NULL, "AIF1RX5" },
-
-       { "AIF2RX", NULL, "AIF2RX0" },
-       { "AIF2RX", NULL, "AIF2RX1" },
-
-       { "AIF2TX", "DSP2", "DSP2TX" },
-       { "AIF2TX", "DSP1", "DSP1RX" },
-       { "AIF2TX", "AIF1", "AIF1RXC" },
-
-       { "DSP1RXL", NULL, "DSP1RX" },
-       { "DSP1RXR", NULL, "DSP1RX" },
-       { "DSP2RXL", NULL, "DSP2RX" },
-       { "DSP2RXR", NULL, "DSP2RX" },
-
-       { "DSP2TX", NULL, "DSP2TXL" },
-       { "DSP2TX", NULL, "DSP2TXR" },
-
-       { "DSP1RX", "AIF1", "AIF1RXA" },
-       { "DSP1RX", "AIF2", "AIF2RX" },
-
-       { "DSP2RX", "AIF1", "AIF1RXB" },
-       { "DSP2RX", "AIF2", "AIF2RX" },
-
-       { "DAC2L Mixer", "DSP2 Switch", "DSP2RXL" },
-       { "DAC2L Mixer", "DSP1 Switch", "DSP1RXL" },
-       { "DAC2L Mixer", "Right Sidetone Switch", "Right Sidetone" },
-       { "DAC2L Mixer", "Left Sidetone Switch", "Left Sidetone" },
-
-       { "DAC2R Mixer", "DSP2 Switch", "DSP2RXR" },
-       { "DAC2R Mixer", "DSP1 Switch", "DSP1RXR" },
-       { "DAC2R Mixer", "Right Sidetone Switch", "Right Sidetone" },
-       { "DAC2R Mixer", "Left Sidetone Switch", "Left Sidetone" },
-
-       { "DAC1L Mixer", "DSP2 Switch", "DSP2RXL" },
-       { "DAC1L Mixer", "DSP1 Switch", "DSP1RXL" },
-       { "DAC1L Mixer", "Right Sidetone Switch", "Right Sidetone" },
-       { "DAC1L Mixer", "Left Sidetone Switch", "Left Sidetone" },
-
-       { "DAC1R Mixer", "DSP2 Switch", "DSP2RXR" },
-       { "DAC1R Mixer", "DSP1 Switch", "DSP1RXR" },
-       { "DAC1R Mixer", "Right Sidetone Switch", "Right Sidetone" },
-       { "DAC1R Mixer", "Left Sidetone Switch", "Left Sidetone" },
-
-       { "DAC1L", NULL, "DAC1L Mixer" },
-       { "DAC1R", NULL, "DAC1R Mixer" },
-       { "DAC2L", NULL, "DAC2L Mixer" },
-       { "DAC2R", NULL, "DAC2R Mixer" },
-
-       { "HPOUT2L PGA", NULL, "Charge Pump" },
-       { "HPOUT2L PGA", NULL, "DAC2L" },
-       { "HPOUT2L_DLY", NULL, "HPOUT2L PGA" },
-       { "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" },
-       { "HPOUT2L_OUTP", NULL, "HPOUT2L_DCS" },
-       { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" },
-
-       { "HPOUT2R PGA", NULL, "Charge Pump" },
-       { "HPOUT2R PGA", NULL, "DAC2R" },
-       { "HPOUT2R_DLY", NULL, "HPOUT2R PGA" },
-       { "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" },
-       { "HPOUT2R_OUTP", NULL, "HPOUT2R_DCS" },
-       { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" },
-
-       { "HPOUT1L PGA", NULL, "Charge Pump" },
-       { "HPOUT1L PGA", NULL, "DAC1L" },
-       { "HPOUT1L_DLY", NULL, "HPOUT1L PGA" },
-       { "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" },
-       { "HPOUT1L_OUTP", NULL, "HPOUT1L_DCS" },
-       { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" },
-
-       { "HPOUT1R PGA", NULL, "Charge Pump" },
-       { "HPOUT1R PGA", NULL, "DAC1R" },
-       { "HPOUT1R_DLY", NULL, "HPOUT1R PGA" },
-       { "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" },
-       { "HPOUT1R_OUTP", NULL, "HPOUT1R_DCS" },
-       { "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_OUTP" },
-
-       { "HPOUT2L", NULL, "HPOUT2L_RMV_SHORT" },
-       { "HPOUT2R", NULL, "HPOUT2R_RMV_SHORT" },
-       { "HPOUT1L", NULL, "HPOUT1L_RMV_SHORT" },
-       { "HPOUT1R", NULL, "HPOUT1R_RMV_SHORT" },
-
-       { "SPKL", "DAC1L", "DAC1L" },
-       { "SPKL", "DAC1R", "DAC1R" },
-       { "SPKL", "DAC2L", "DAC2L" },
-       { "SPKL", "DAC2R", "DAC2R" },
-
-       { "SPKR", "DAC1L", "DAC1L" },
-       { "SPKR", "DAC1R", "DAC1R" },
-       { "SPKR", "DAC2L", "DAC2L" },
-       { "SPKR", "DAC2R", "DAC2R" },
-
-       { "SPKL PGA", NULL, "SPKL" },
-       { "SPKR PGA", NULL, "SPKR" },
-
-       { "SPKDAT", NULL, "SPKL PGA" },
-       { "SPKDAT", NULL, "SPKR PGA" },
-};
-
-static int wm8915_readable_register(struct snd_soc_codec *codec,
-                                   unsigned int reg)
-{
-       /* Due to the sparseness of the register map the compiler
-        * output from an explicit switch statement ends up being much
-        * more efficient than a table.
-        */
-       switch (reg) {
-       case WM8915_SOFTWARE_RESET:
-       case WM8915_POWER_MANAGEMENT_1:
-       case WM8915_POWER_MANAGEMENT_2:
-       case WM8915_POWER_MANAGEMENT_3:
-       case WM8915_POWER_MANAGEMENT_4:
-       case WM8915_POWER_MANAGEMENT_5:
-       case WM8915_POWER_MANAGEMENT_6:
-       case WM8915_POWER_MANAGEMENT_7:
-       case WM8915_POWER_MANAGEMENT_8:
-       case WM8915_LEFT_LINE_INPUT_VOLUME:
-       case WM8915_RIGHT_LINE_INPUT_VOLUME:
-       case WM8915_LINE_INPUT_CONTROL:
-       case WM8915_DAC1_HPOUT1_VOLUME:
-       case WM8915_DAC2_HPOUT2_VOLUME:
-       case WM8915_DAC1_LEFT_VOLUME:
-       case WM8915_DAC1_RIGHT_VOLUME:
-       case WM8915_DAC2_LEFT_VOLUME:
-       case WM8915_DAC2_RIGHT_VOLUME:
-       case WM8915_OUTPUT1_LEFT_VOLUME:
-       case WM8915_OUTPUT1_RIGHT_VOLUME:
-       case WM8915_OUTPUT2_LEFT_VOLUME:
-       case WM8915_OUTPUT2_RIGHT_VOLUME:
-       case WM8915_MICBIAS_1:
-       case WM8915_MICBIAS_2:
-       case WM8915_LDO_1:
-       case WM8915_LDO_2:
-       case WM8915_ACCESSORY_DETECT_MODE_1:
-       case WM8915_ACCESSORY_DETECT_MODE_2:
-       case WM8915_HEADPHONE_DETECT_1:
-       case WM8915_HEADPHONE_DETECT_2:
-       case WM8915_MIC_DETECT_1:
-       case WM8915_MIC_DETECT_2:
-       case WM8915_MIC_DETECT_3:
-       case WM8915_CHARGE_PUMP_1:
-       case WM8915_CHARGE_PUMP_2:
-       case WM8915_DC_SERVO_1:
-       case WM8915_DC_SERVO_2:
-       case WM8915_DC_SERVO_3:
-       case WM8915_DC_SERVO_5:
-       case WM8915_DC_SERVO_6:
-       case WM8915_DC_SERVO_7:
-       case WM8915_DC_SERVO_READBACK_0:
-       case WM8915_ANALOGUE_HP_1:
-       case WM8915_ANALOGUE_HP_2:
-       case WM8915_CHIP_REVISION:
-       case WM8915_CONTROL_INTERFACE_1:
-       case WM8915_WRITE_SEQUENCER_CTRL_1:
-       case WM8915_WRITE_SEQUENCER_CTRL_2:
-       case WM8915_AIF_CLOCKING_1:
-       case WM8915_AIF_CLOCKING_2:
-       case WM8915_CLOCKING_1:
-       case WM8915_CLOCKING_2:
-       case WM8915_AIF_RATE:
-       case WM8915_FLL_CONTROL_1:
-       case WM8915_FLL_CONTROL_2:
-       case WM8915_FLL_CONTROL_3:
-       case WM8915_FLL_CONTROL_4:
-       case WM8915_FLL_CONTROL_5:
-       case WM8915_FLL_CONTROL_6:
-       case WM8915_FLL_EFS_1:
-       case WM8915_FLL_EFS_2:
-       case WM8915_AIF1_CONTROL:
-       case WM8915_AIF1_BCLK:
-       case WM8915_AIF1_TX_LRCLK_1:
-       case WM8915_AIF1_TX_LRCLK_2:
-       case WM8915_AIF1_RX_LRCLK_1:
-       case WM8915_AIF1_RX_LRCLK_2:
-       case WM8915_AIF1TX_DATA_CONFIGURATION_1:
-       case WM8915_AIF1TX_DATA_CONFIGURATION_2:
-       case WM8915_AIF1RX_DATA_CONFIGURATION:
-       case WM8915_AIF1TX_CHANNEL_0_CONFIGURATION:
-       case WM8915_AIF1TX_CHANNEL_1_CONFIGURATION:
-       case WM8915_AIF1TX_CHANNEL_2_CONFIGURATION:
-       case WM8915_AIF1TX_CHANNEL_3_CONFIGURATION:
-       case WM8915_AIF1TX_CHANNEL_4_CONFIGURATION:
-       case WM8915_AIF1TX_CHANNEL_5_CONFIGURATION:
-       case WM8915_AIF1RX_CHANNEL_0_CONFIGURATION:
-       case WM8915_AIF1RX_CHANNEL_1_CONFIGURATION:
-       case WM8915_AIF1RX_CHANNEL_2_CONFIGURATION:
-       case WM8915_AIF1RX_CHANNEL_3_CONFIGURATION:
-       case WM8915_AIF1RX_CHANNEL_4_CONFIGURATION:
-       case WM8915_AIF1RX_CHANNEL_5_CONFIGURATION:
-       case WM8915_AIF1RX_MONO_CONFIGURATION:
-       case WM8915_AIF1TX_TEST:
-       case WM8915_AIF2_CONTROL:
-       case WM8915_AIF2_BCLK:
-       case WM8915_AIF2_TX_LRCLK_1:
-       case WM8915_AIF2_TX_LRCLK_2:
-       case WM8915_AIF2_RX_LRCLK_1:
-       case WM8915_AIF2_RX_LRCLK_2:
-       case WM8915_AIF2TX_DATA_CONFIGURATION_1:
-       case WM8915_AIF2TX_DATA_CONFIGURATION_2:
-       case WM8915_AIF2RX_DATA_CONFIGURATION:
-       case WM8915_AIF2TX_CHANNEL_0_CONFIGURATION:
-       case WM8915_AIF2TX_CHANNEL_1_CONFIGURATION:
-       case WM8915_AIF2RX_CHANNEL_0_CONFIGURATION:
-       case WM8915_AIF2RX_CHANNEL_1_CONFIGURATION:
-       case WM8915_AIF2RX_MONO_CONFIGURATION:
-       case WM8915_AIF2TX_TEST:
-       case WM8915_DSP1_TX_LEFT_VOLUME:
-       case WM8915_DSP1_TX_RIGHT_VOLUME:
-       case WM8915_DSP1_RX_LEFT_VOLUME:
-       case WM8915_DSP1_RX_RIGHT_VOLUME:
-       case WM8915_DSP1_TX_FILTERS:
-       case WM8915_DSP1_RX_FILTERS_1:
-       case WM8915_DSP1_RX_FILTERS_2:
-       case WM8915_DSP1_DRC_1:
-       case WM8915_DSP1_DRC_2:
-       case WM8915_DSP1_DRC_3:
-       case WM8915_DSP1_DRC_4:
-       case WM8915_DSP1_DRC_5:
-       case WM8915_DSP1_RX_EQ_GAINS_1:
-       case WM8915_DSP1_RX_EQ_GAINS_2:
-       case WM8915_DSP1_RX_EQ_BAND_1_A:
-       case WM8915_DSP1_RX_EQ_BAND_1_B:
-       case WM8915_DSP1_RX_EQ_BAND_1_PG:
-       case WM8915_DSP1_RX_EQ_BAND_2_A:
-       case WM8915_DSP1_RX_EQ_BAND_2_B:
-       case WM8915_DSP1_RX_EQ_BAND_2_C:
-       case WM8915_DSP1_RX_EQ_BAND_2_PG:
-       case WM8915_DSP1_RX_EQ_BAND_3_A:
-       case WM8915_DSP1_RX_EQ_BAND_3_B:
-       case WM8915_DSP1_RX_EQ_BAND_3_C:
-       case WM8915_DSP1_RX_EQ_BAND_3_PG:
-       case WM8915_DSP1_RX_EQ_BAND_4_A:
-       case WM8915_DSP1_RX_EQ_BAND_4_B:
-       case WM8915_DSP1_RX_EQ_BAND_4_C:
-       case WM8915_DSP1_RX_EQ_BAND_4_PG:
-       case WM8915_DSP1_RX_EQ_BAND_5_A:
-       case WM8915_DSP1_RX_EQ_BAND_5_B:
-       case WM8915_DSP1_RX_EQ_BAND_5_PG:
-       case WM8915_DSP2_TX_LEFT_VOLUME:
-       case WM8915_DSP2_TX_RIGHT_VOLUME:
-       case WM8915_DSP2_RX_LEFT_VOLUME:
-       case WM8915_DSP2_RX_RIGHT_VOLUME:
-       case WM8915_DSP2_TX_FILTERS:
-       case WM8915_DSP2_RX_FILTERS_1:
-       case WM8915_DSP2_RX_FILTERS_2:
-       case WM8915_DSP2_DRC_1:
-       case WM8915_DSP2_DRC_2:
-       case WM8915_DSP2_DRC_3:
-       case WM8915_DSP2_DRC_4:
-       case WM8915_DSP2_DRC_5:
-       case WM8915_DSP2_RX_EQ_GAINS_1:
-       case WM8915_DSP2_RX_EQ_GAINS_2:
-       case WM8915_DSP2_RX_EQ_BAND_1_A:
-       case WM8915_DSP2_RX_EQ_BAND_1_B:
-       case WM8915_DSP2_RX_EQ_BAND_1_PG:
-       case WM8915_DSP2_RX_EQ_BAND_2_A:
-       case WM8915_DSP2_RX_EQ_BAND_2_B:
-       case WM8915_DSP2_RX_EQ_BAND_2_C:
-       case WM8915_DSP2_RX_EQ_BAND_2_PG:
-       case WM8915_DSP2_RX_EQ_BAND_3_A:
-       case WM8915_DSP2_RX_EQ_BAND_3_B:
-       case WM8915_DSP2_RX_EQ_BAND_3_C:
-       case WM8915_DSP2_RX_EQ_BAND_3_PG:
-       case WM8915_DSP2_RX_EQ_BAND_4_A:
-       case WM8915_DSP2_RX_EQ_BAND_4_B:
-       case WM8915_DSP2_RX_EQ_BAND_4_C:
-       case WM8915_DSP2_RX_EQ_BAND_4_PG:
-       case WM8915_DSP2_RX_EQ_BAND_5_A:
-       case WM8915_DSP2_RX_EQ_BAND_5_B:
-       case WM8915_DSP2_RX_EQ_BAND_5_PG:
-       case WM8915_DAC1_MIXER_VOLUMES:
-       case WM8915_DAC1_LEFT_MIXER_ROUTING:
-       case WM8915_DAC1_RIGHT_MIXER_ROUTING:
-       case WM8915_DAC2_MIXER_VOLUMES:
-       case WM8915_DAC2_LEFT_MIXER_ROUTING:
-       case WM8915_DAC2_RIGHT_MIXER_ROUTING:
-       case WM8915_DSP1_TX_LEFT_MIXER_ROUTING:
-       case WM8915_DSP1_TX_RIGHT_MIXER_ROUTING:
-       case WM8915_DSP2_TX_LEFT_MIXER_ROUTING:
-       case WM8915_DSP2_TX_RIGHT_MIXER_ROUTING:
-       case WM8915_DSP_TX_MIXER_SELECT:
-       case WM8915_DAC_SOFTMUTE:
-       case WM8915_OVERSAMPLING:
-       case WM8915_SIDETONE:
-       case WM8915_GPIO_1:
-       case WM8915_GPIO_2:
-       case WM8915_GPIO_3:
-       case WM8915_GPIO_4:
-       case WM8915_GPIO_5:
-       case WM8915_PULL_CONTROL_1:
-       case WM8915_PULL_CONTROL_2:
-       case WM8915_INTERRUPT_STATUS_1:
-       case WM8915_INTERRUPT_STATUS_2:
-       case WM8915_INTERRUPT_RAW_STATUS_2:
-       case WM8915_INTERRUPT_STATUS_1_MASK:
-       case WM8915_INTERRUPT_STATUS_2_MASK:
-       case WM8915_INTERRUPT_CONTROL:
-       case WM8915_LEFT_PDM_SPEAKER:
-       case WM8915_RIGHT_PDM_SPEAKER:
-       case WM8915_PDM_SPEAKER_MUTE_SEQUENCE:
-       case WM8915_PDM_SPEAKER_VOLUME:
-               return 1;
-       default:
-               return 0;
-       }
-}
-
-static int wm8915_volatile_register(struct snd_soc_codec *codec,
-                                   unsigned int reg)
-{
-       switch (reg) {
-       case WM8915_SOFTWARE_RESET:
-       case WM8915_CHIP_REVISION:
-       case WM8915_LDO_1:
-       case WM8915_LDO_2:
-       case WM8915_INTERRUPT_STATUS_1:
-       case WM8915_INTERRUPT_STATUS_2:
-       case WM8915_INTERRUPT_RAW_STATUS_2:
-       case WM8915_DC_SERVO_READBACK_0:
-       case WM8915_DC_SERVO_2:
-       case WM8915_DC_SERVO_6:
-       case WM8915_DC_SERVO_7:
-       case WM8915_FLL_CONTROL_6:
-       case WM8915_MIC_DETECT_3:
-       case WM8915_HEADPHONE_DETECT_1:
-       case WM8915_HEADPHONE_DETECT_2:
-               return 1;
-       default:
-               return 0;
-       }
-}
-
-static int wm8915_reset(struct snd_soc_codec *codec)
-{
-       return snd_soc_write(codec, WM8915_SOFTWARE_RESET, 0x8915);
-}
-
-static const int bclk_divs[] = {
-       1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96
-};
-
-static void wm8915_update_bclk(struct snd_soc_codec *codec)
-{
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       int aif, best, cur_val, bclk_rate, bclk_reg, i;
-
-       /* Don't bother if we're in a low frequency idle mode that
-        * can't support audio.
-        */
-       if (wm8915->sysclk < 64000)
-               return;
-
-       for (aif = 0; aif < WM8915_AIFS; aif++) {
-               switch (aif) {
-               case 0:
-                       bclk_reg = WM8915_AIF1_BCLK;
-                       break;
-               case 1:
-                       bclk_reg = WM8915_AIF2_BCLK;
-                       break;
-               }
-
-               bclk_rate = wm8915->bclk_rate[aif];
-
-               /* Pick a divisor for BCLK as close as we can get to ideal */
-               best = 0;
-               for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
-                       cur_val = (wm8915->sysclk / bclk_divs[i]) - bclk_rate;
-                       if (cur_val < 0) /* BCLK table is sorted */
-                               break;
-                       best = i;
-               }
-               bclk_rate = wm8915->sysclk / bclk_divs[best];
-               dev_dbg(codec->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n",
-                       bclk_divs[best], bclk_rate);
-
-               snd_soc_update_bits(codec, bclk_reg,
-                                   WM8915_AIF1_BCLK_DIV_MASK, best);
-       }
-}
-
-static int wm8915_set_bias_level(struct snd_soc_codec *codec,
-                                enum snd_soc_bias_level level)
-{
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       int ret;
-
-       switch (level) {
-       case SND_SOC_BIAS_ON:
-               break;
-
-       case SND_SOC_BIAS_PREPARE:
-               if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
-                       snd_soc_update_bits(codec, WM8915_POWER_MANAGEMENT_1,
-                                           WM8915_BG_ENA, WM8915_BG_ENA);
-                       msleep(2);
-               }
-               break;
-
-       case SND_SOC_BIAS_STANDBY:
-               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       ret = regulator_bulk_enable(ARRAY_SIZE(wm8915->supplies),
-                                                   wm8915->supplies);
-                       if (ret != 0) {
-                               dev_err(codec->dev,
-                                       "Failed to enable supplies: %d\n",
-                                       ret);
-                               return ret;
-                       }
-
-                       if (wm8915->pdata.ldo_ena >= 0) {
-                               gpio_set_value_cansleep(wm8915->pdata.ldo_ena,
-                                                       1);
-                               msleep(5);
-                       }
-
-                       codec->cache_only = false;
-                       snd_soc_cache_sync(codec);
-               }
-
-               snd_soc_update_bits(codec, WM8915_POWER_MANAGEMENT_1,
-                                   WM8915_BG_ENA, 0);
-               break;
-
-       case SND_SOC_BIAS_OFF:
-               codec->cache_only = true;
-               if (wm8915->pdata.ldo_ena >= 0)
-                       gpio_set_value_cansleep(wm8915->pdata.ldo_ena, 0);
-               regulator_bulk_disable(ARRAY_SIZE(wm8915->supplies),
-                                      wm8915->supplies);
-               break;
-       }
-
-       codec->dapm.bias_level = level;
-
-       return 0;
-}
-
-static int wm8915_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       int aifctrl = 0;
-       int bclk = 0;
-       int lrclk_tx = 0;
-       int lrclk_rx = 0;
-       int aifctrl_reg, bclk_reg, lrclk_tx_reg, lrclk_rx_reg;
-
-       switch (dai->id) {
-       case 0:
-               aifctrl_reg = WM8915_AIF1_CONTROL;
-               bclk_reg = WM8915_AIF1_BCLK;
-               lrclk_tx_reg = WM8915_AIF1_TX_LRCLK_2;
-               lrclk_rx_reg = WM8915_AIF1_RX_LRCLK_2;
-               break;
-       case 1:
-               aifctrl_reg = WM8915_AIF2_CONTROL;
-               bclk_reg = WM8915_AIF2_BCLK;
-               lrclk_tx_reg = WM8915_AIF2_TX_LRCLK_2;
-               lrclk_rx_reg = WM8915_AIF2_RX_LRCLK_2;
-               break;
-       default:
-               BUG();
-               return -EINVAL;
-       }
-
-       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-       case SND_SOC_DAIFMT_NB_NF:
-               break;
-       case SND_SOC_DAIFMT_IB_NF:
-               bclk |= WM8915_AIF1_BCLK_INV;
-               break;
-       case SND_SOC_DAIFMT_NB_IF:
-               lrclk_tx |= WM8915_AIF1TX_LRCLK_INV;
-               lrclk_rx |= WM8915_AIF1RX_LRCLK_INV;
-               break;
-       case SND_SOC_DAIFMT_IB_IF:
-               bclk |= WM8915_AIF1_BCLK_INV;
-               lrclk_tx |= WM8915_AIF1TX_LRCLK_INV;
-               lrclk_rx |= WM8915_AIF1RX_LRCLK_INV;
-               break;
-       }
-
-       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-       case SND_SOC_DAIFMT_CBS_CFS:
-               break;
-       case SND_SOC_DAIFMT_CBS_CFM:
-               lrclk_tx |= WM8915_AIF1TX_LRCLK_MSTR;
-               lrclk_rx |= WM8915_AIF1RX_LRCLK_MSTR;
-               break;
-       case SND_SOC_DAIFMT_CBM_CFS:
-               bclk |= WM8915_AIF1_BCLK_MSTR;
-               break;
-       case SND_SOC_DAIFMT_CBM_CFM:
-               bclk |= WM8915_AIF1_BCLK_MSTR;
-               lrclk_tx |= WM8915_AIF1TX_LRCLK_MSTR;
-               lrclk_rx |= WM8915_AIF1RX_LRCLK_MSTR;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-       case SND_SOC_DAIFMT_DSP_A:
-               break;
-       case SND_SOC_DAIFMT_DSP_B:
-               aifctrl |= 1;
-               break;
-       case SND_SOC_DAIFMT_I2S:
-               aifctrl |= 2;
-               break;
-       case SND_SOC_DAIFMT_LEFT_J:
-               aifctrl |= 3;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       snd_soc_update_bits(codec, aifctrl_reg, WM8915_AIF1_FMT_MASK, aifctrl);
-       snd_soc_update_bits(codec, bclk_reg,
-                           WM8915_AIF1_BCLK_INV | WM8915_AIF1_BCLK_MSTR,
-                           bclk);
-       snd_soc_update_bits(codec, lrclk_tx_reg,
-                           WM8915_AIF1TX_LRCLK_INV |
-                           WM8915_AIF1TX_LRCLK_MSTR,
-                           lrclk_tx);
-       snd_soc_update_bits(codec, lrclk_rx_reg,
-                           WM8915_AIF1RX_LRCLK_INV |
-                           WM8915_AIF1RX_LRCLK_MSTR,
-                           lrclk_rx);
-
-       return 0;
-}
-
-static const int dsp_divs[] = {
-       48000, 32000, 16000, 8000
-};
-
-static int wm8915_hw_params(struct snd_pcm_substream *substream,
-                           struct snd_pcm_hw_params *params,
-                           struct snd_soc_dai *dai)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       int bits, i, bclk_rate;
-       int aifdata = 0;
-       int lrclk = 0;
-       int dsp = 0;
-       int aifdata_reg, lrclk_reg, dsp_shift;
-
-       switch (dai->id) {
-       case 0:
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
-                   (snd_soc_read(codec, WM8915_GPIO_1)) & WM8915_GP1_FN_MASK) {
-                       aifdata_reg = WM8915_AIF1RX_DATA_CONFIGURATION;
-                       lrclk_reg = WM8915_AIF1_RX_LRCLK_1;
-               } else {
-                       aifdata_reg = WM8915_AIF1TX_DATA_CONFIGURATION_1;
-                       lrclk_reg = WM8915_AIF1_TX_LRCLK_1;
-               }
-               dsp_shift = 0;
-               break;
-       case 1:
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
-                   (snd_soc_read(codec, WM8915_GPIO_2)) & WM8915_GP2_FN_MASK) {
-                       aifdata_reg = WM8915_AIF2RX_DATA_CONFIGURATION;
-                       lrclk_reg = WM8915_AIF2_RX_LRCLK_1;
-               } else {
-                       aifdata_reg = WM8915_AIF2TX_DATA_CONFIGURATION_1;
-                       lrclk_reg = WM8915_AIF2_TX_LRCLK_1;
-               }
-               dsp_shift = WM8915_DSP2_DIV_SHIFT;
-               break;
-       default:
-               BUG();
-               return -EINVAL;
-       }
-
-       bclk_rate = snd_soc_params_to_bclk(params);
-       if (bclk_rate < 0) {
-               dev_err(codec->dev, "Unsupported BCLK rate: %d\n", bclk_rate);
-               return bclk_rate;
-       }
-
-       wm8915->bclk_rate[dai->id] = bclk_rate;
-       wm8915->rx_rate[dai->id] = params_rate(params);
-
-       /* Needs looking at for TDM */
-       bits = snd_pcm_format_width(params_format(params));
-       if (bits < 0)
-               return bits;
-       aifdata |= (bits << WM8915_AIF1TX_WL_SHIFT) | bits;
-
-       for (i = 0; i < ARRAY_SIZE(dsp_divs); i++) {
-               if (dsp_divs[i] == params_rate(params))
-                       break;
-       }
-       if (i == ARRAY_SIZE(dsp_divs)) {
-               dev_err(codec->dev, "Unsupported sample rate %dHz\n",
-                       params_rate(params));
-               return -EINVAL;
-       }
-       dsp |= i << dsp_shift;
-
-       wm8915_update_bclk(codec);
-
-       lrclk = bclk_rate / params_rate(params);
-       dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n",
-               lrclk, bclk_rate / lrclk);
-
-       snd_soc_update_bits(codec, aifdata_reg,
-                           WM8915_AIF1TX_WL_MASK |
-                           WM8915_AIF1TX_SLOT_LEN_MASK,
-                           aifdata);
-       snd_soc_update_bits(codec, lrclk_reg, WM8915_AIF1RX_RATE_MASK,
-                           lrclk);
-       snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_2,
-                           WM8915_DSP1_DIV_SHIFT << dsp_shift, dsp);
-
-       return 0;
-}
-
-static int wm8915_set_sysclk(struct snd_soc_dai *dai,
-               int clk_id, unsigned int freq, int dir)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       int lfclk = 0;
-       int ratediv = 0;
-       int src;
-       int old;
-
-       if (freq == wm8915->sysclk && clk_id == wm8915->sysclk_src)
-               return 0;
-
-       /* Disable SYSCLK while we reconfigure */
-       old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1) & WM8915_SYSCLK_ENA;
-       snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1,
-                           WM8915_SYSCLK_ENA, 0);
-
-       switch (clk_id) {
-       case WM8915_SYSCLK_MCLK1:
-               wm8915->sysclk = freq;
-               src = 0;
-               break;
-       case WM8915_SYSCLK_MCLK2:
-               wm8915->sysclk = freq;
-               src = 1;
-               break;
-       case WM8915_SYSCLK_FLL:
-               wm8915->sysclk = freq;
-               src = 2;
-               break;
-       default:
-               dev_err(codec->dev, "Unsupported clock source %d\n", clk_id);
-               return -EINVAL;
-       }
-
-       switch (wm8915->sysclk) {
-       case 6144000:
-               snd_soc_update_bits(codec, WM8915_AIF_RATE,
-                                   WM8915_SYSCLK_RATE, 0);
-               break;
-       case 24576000:
-               ratediv = WM8915_SYSCLK_DIV;
-       case 12288000:
-               snd_soc_update_bits(codec, WM8915_AIF_RATE,
-                                   WM8915_SYSCLK_RATE, WM8915_SYSCLK_RATE);
-               break;
-       case 32000:
-       case 32768:
-               lfclk = WM8915_LFCLK_ENA;
-               break;
-       default:
-               dev_warn(codec->dev, "Unsupported clock rate %dHz\n",
-                        wm8915->sysclk);
-               return -EINVAL;
-       }
-
-       wm8915_update_bclk(codec);
-
-       snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1,
-                           WM8915_SYSCLK_SRC_MASK | WM8915_SYSCLK_DIV_MASK,
-                           src << WM8915_SYSCLK_SRC_SHIFT | ratediv);
-       snd_soc_update_bits(codec, WM8915_CLOCKING_1, WM8915_LFCLK_ENA, lfclk);
-       snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1,
-                           WM8915_SYSCLK_ENA, old);
-
-       wm8915->sysclk_src = clk_id;
-
-       return 0;
-}
-
-struct _fll_div {
-       u16 fll_fratio;
-       u16 fll_outdiv;
-       u16 fll_refclk_div;
-       u16 fll_loop_gain;
-       u16 fll_ref_freq;
-       u16 n;
-       u16 theta;
-       u16 lambda;
-};
-
-static struct {
-       unsigned int min;
-       unsigned int max;
-       u16 fll_fratio;
-       int ratio;
-} fll_fratios[] = {
-       {       0,    64000, 4, 16 },
-       {   64000,   128000, 3,  8 },
-       {  128000,   256000, 2,  4 },
-       {  256000,  1000000, 1,  2 },
-       { 1000000, 13500000, 0,  1 },
-};
-
-static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
-                      unsigned int Fout)
-{
-       unsigned int target;
-       unsigned int div;
-       unsigned int fratio, gcd_fll;
-       int i;
-
-       /* Fref must be <=13.5MHz */
-       div = 1;
-       fll_div->fll_refclk_div = 0;
-       while ((Fref / div) > 13500000) {
-               div *= 2;
-               fll_div->fll_refclk_div++;
-
-               if (div > 8) {
-                       pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
-                              Fref);
-                       return -EINVAL;
-               }
-       }
-
-       pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
-
-       /* Apply the division for our remaining calculations */
-       Fref /= div;
-
-       if (Fref >= 3000000)
-               fll_div->fll_loop_gain = 5;
-       else
-               fll_div->fll_loop_gain = 0;
-
-       if (Fref >= 48000)
-               fll_div->fll_ref_freq = 0;
-       else
-               fll_div->fll_ref_freq = 1;
-
-       /* Fvco should be 90-100MHz; don't check the upper bound */
-       div = 2;
-       while (Fout * div < 90000000) {
-               div++;
-               if (div > 64) {
-                       pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
-                              Fout);
-                       return -EINVAL;
-               }
-       }
-       target = Fout * div;
-       fll_div->fll_outdiv = div - 1;
-
-       pr_debug("FLL Fvco=%dHz\n", target);
-
-       /* Find an appropraite FLL_FRATIO and factor it out of the target */
-       for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
-               if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
-                       fll_div->fll_fratio = fll_fratios[i].fll_fratio;
-                       fratio = fll_fratios[i].ratio;
-                       break;
-               }
-       }
-       if (i == ARRAY_SIZE(fll_fratios)) {
-               pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
-               return -EINVAL;
-       }
-
-       fll_div->n = target / (fratio * Fref);
-
-       if (target % Fref == 0) {
-               fll_div->theta = 0;
-               fll_div->lambda = 0;
-       } else {
-               gcd_fll = gcd(target, fratio * Fref);
-
-               fll_div->theta = (target - (fll_div->n * fratio * Fref))
-                       / gcd_fll;
-               fll_div->lambda = (fratio * Fref) / gcd_fll;
-       }
-
-       pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
-                fll_div->n, fll_div->theta, fll_div->lambda);
-       pr_debug("FLL_FRATIO=%x FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
-                fll_div->fll_fratio, fll_div->fll_outdiv,
-                fll_div->fll_refclk_div);
-
-       return 0;
-}
-
-static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
-                         unsigned int Fref, unsigned int Fout)
-{
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       struct i2c_client *i2c = to_i2c_client(codec->dev);
-       struct _fll_div fll_div;
-       unsigned long timeout;
-       int ret, reg;
-
-       /* Any change? */
-       if (source == wm8915->fll_src && Fref == wm8915->fll_fref &&
-           Fout == wm8915->fll_fout)
-               return 0;
-
-       if (Fout == 0) {
-               dev_dbg(codec->dev, "FLL disabled\n");
-
-               wm8915->fll_fref = 0;
-               wm8915->fll_fout = 0;
-
-               snd_soc_update_bits(codec, WM8915_FLL_CONTROL_1,
-                                   WM8915_FLL_ENA, 0);
-
-               return 0;
-       }
-
-       ret = fll_factors(&fll_div, Fref, Fout);
-       if (ret != 0)
-               return ret;
-
-       switch (source) {
-       case WM8915_FLL_MCLK1:
-               reg = 0;
-               break;
-       case WM8915_FLL_MCLK2:
-               reg = 1;
-               break;
-       case WM8915_FLL_DACLRCLK1:
-               reg = 2;
-               break;
-       case WM8915_FLL_BCLK1:
-               reg = 3;
-               break;
-       default:
-               dev_err(codec->dev, "Unknown FLL source %d\n", ret);
-               return -EINVAL;
-       }
-
-       reg |= fll_div.fll_refclk_div << WM8915_FLL_REFCLK_DIV_SHIFT;
-       reg |= fll_div.fll_ref_freq << WM8915_FLL_REF_FREQ_SHIFT;
-
-       snd_soc_update_bits(codec, WM8915_FLL_CONTROL_5,
-                           WM8915_FLL_REFCLK_DIV_MASK | WM8915_FLL_REF_FREQ |
-                           WM8915_FLL_REFCLK_SRC_MASK, reg);
-
-       reg = 0;
-       if (fll_div.theta || fll_div.lambda)
-               reg |= WM8915_FLL_EFS_ENA | (3 << WM8915_FLL_LFSR_SEL_SHIFT);
-       else
-               reg |= 1 << WM8915_FLL_LFSR_SEL_SHIFT;
-       snd_soc_write(codec, WM8915_FLL_EFS_2, reg);
-
-       snd_soc_update_bits(codec, WM8915_FLL_CONTROL_2,
-                           WM8915_FLL_OUTDIV_MASK |
-                           WM8915_FLL_FRATIO_MASK,
-                           (fll_div.fll_outdiv << WM8915_FLL_OUTDIV_SHIFT) |
-                           (fll_div.fll_fratio));
-
-       snd_soc_write(codec, WM8915_FLL_CONTROL_3, fll_div.theta);
-
-       snd_soc_update_bits(codec, WM8915_FLL_CONTROL_4,
-                           WM8915_FLL_N_MASK | WM8915_FLL_LOOP_GAIN_MASK,
-                           (fll_div.n << WM8915_FLL_N_SHIFT) |
-                           fll_div.fll_loop_gain);
-
-       snd_soc_write(codec, WM8915_FLL_EFS_1, fll_div.lambda);
-
-       snd_soc_update_bits(codec, WM8915_FLL_CONTROL_1,
-                           WM8915_FLL_ENA, WM8915_FLL_ENA);
-
-       /* The FLL supports live reconfiguration - kick that in case we were
-        * already enabled.
-        */
-       snd_soc_write(codec, WM8915_FLL_CONTROL_6, WM8915_FLL_SWITCH_CLK);
-
-       /* Wait for the FLL to lock, using the interrupt if possible */
-       if (Fref > 1000000)
-               timeout = usecs_to_jiffies(300);
-       else
-               timeout = msecs_to_jiffies(2);
-
-       /* Allow substantially longer if we've actually got the IRQ */
-       if (i2c->irq)
-               timeout *= 1000;
-
-       ret = wait_for_completion_timeout(&wm8915->fll_lock, timeout);
-
-       if (ret == 0 && i2c->irq) {
-               dev_err(codec->dev, "Timed out waiting for FLL\n");
-               ret = -ETIMEDOUT;
-       } else {
-               ret = 0;
-       }
-
-       dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
-
-       wm8915->fll_fref = Fref;
-       wm8915->fll_fout = Fout;
-       wm8915->fll_src = source;
-
-       return ret;
-}
-
-#ifdef CONFIG_GPIOLIB
-static inline struct wm8915_priv *gpio_to_wm8915(struct gpio_chip *chip)
-{
-       return container_of(chip, struct wm8915_priv, gpio_chip);
-}
-
-static void wm8915_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct wm8915_priv *wm8915 = gpio_to_wm8915(chip);
-       struct snd_soc_codec *codec = wm8915->codec;
-
-       snd_soc_update_bits(codec, WM8915_GPIO_1 + offset,
-                           WM8915_GP1_LVL, !!value << WM8915_GP1_LVL_SHIFT);
-}
-
-static int wm8915_gpio_direction_out(struct gpio_chip *chip,
-                                    unsigned offset, int value)
-{
-       struct wm8915_priv *wm8915 = gpio_to_wm8915(chip);
-       struct snd_soc_codec *codec = wm8915->codec;
-       int val;
-
-       val = (1 << WM8915_GP1_FN_SHIFT) | (!!value << WM8915_GP1_LVL_SHIFT);
-
-       return snd_soc_update_bits(codec, WM8915_GPIO_1 + offset,
-                                  WM8915_GP1_FN_MASK | WM8915_GP1_DIR |
-                                  WM8915_GP1_LVL, val);
-}
-
-static int wm8915_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct wm8915_priv *wm8915 = gpio_to_wm8915(chip);
-       struct snd_soc_codec *codec = wm8915->codec;
-       int ret;
-
-       ret = snd_soc_read(codec, WM8915_GPIO_1 + offset);
-       if (ret < 0)
-               return ret;
-
-       return (ret & WM8915_GP1_LVL) != 0;
-}
-
-static int wm8915_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-       struct wm8915_priv *wm8915 = gpio_to_wm8915(chip);
-       struct snd_soc_codec *codec = wm8915->codec;
-
-       return snd_soc_update_bits(codec, WM8915_GPIO_1 + offset,
-                                  WM8915_GP1_FN_MASK | WM8915_GP1_DIR,
-                                  (1 << WM8915_GP1_FN_SHIFT) |
-                                  (1 << WM8915_GP1_DIR_SHIFT));
-}
-
-static struct gpio_chip wm8915_template_chip = {
-       .label                  = "wm8915",
-       .owner                  = THIS_MODULE,
-       .direction_output       = wm8915_gpio_direction_out,
-       .set                    = wm8915_gpio_set,
-       .direction_input        = wm8915_gpio_direction_in,
-       .get                    = wm8915_gpio_get,
-       .can_sleep              = 1,
-};
-
-static void wm8915_init_gpio(struct snd_soc_codec *codec)
-{
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       int ret;
-
-       wm8915->gpio_chip = wm8915_template_chip;
-       wm8915->gpio_chip.ngpio = 5;
-       wm8915->gpio_chip.dev = codec->dev;
-
-       if (wm8915->pdata.gpio_base)
-               wm8915->gpio_chip.base = wm8915->pdata.gpio_base;
-       else
-               wm8915->gpio_chip.base = -1;
-
-       ret = gpiochip_add(&wm8915->gpio_chip);
-       if (ret != 0)
-               dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
-}
-
-static void wm8915_free_gpio(struct snd_soc_codec *codec)
-{
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       int ret;
-
-       ret = gpiochip_remove(&wm8915->gpio_chip);
-       if (ret != 0)
-               dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
-}
-#else
-static void wm8915_init_gpio(struct snd_soc_codec *codec)
-{
-}
-
-static void wm8915_free_gpio(struct snd_soc_codec *codec)
-{
-}
-#endif
-
-/**
- * wm8915_detect - Enable default WM8915 jack detection
- *
- * The WM8915 has advanced accessory detection support for headsets.
- * This function provides a default implementation which integrates
- * the majority of this functionality with minimal user configuration.
- *
- * This will detect headset, headphone and short circuit button and
- * will also detect inverted microphone ground connections and update
- * the polarity of the connections.
- */
-int wm8915_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
-                 wm8915_polarity_fn polarity_cb)
-{
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-
-       wm8915->jack = jack;
-       wm8915->detecting = true;
-       wm8915->polarity_cb = polarity_cb;
-
-       if (wm8915->polarity_cb)
-               wm8915->polarity_cb(codec, 0);
-
-       /* Clear discarge to avoid noise during detection */
-       snd_soc_update_bits(codec, WM8915_MICBIAS_1,
-                           WM8915_MICB1_DISCH, 0);
-       snd_soc_update_bits(codec, WM8915_MICBIAS_2,
-                           WM8915_MICB2_DISCH, 0);
-
-       /* LDO2 powers the microphones, SYSCLK clocks detection */
-       snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2");
-       snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
-
-       /* We start off just enabling microphone detection - even a
-        * plain headphone will trigger detection.
-        */
-       snd_soc_update_bits(codec, WM8915_MIC_DETECT_1,
-                           WM8915_MICD_ENA, WM8915_MICD_ENA);
-
-       /* Slowest detection rate, gives debounce for initial detection */
-       snd_soc_update_bits(codec, WM8915_MIC_DETECT_1,
-                           WM8915_MICD_RATE_MASK,
-                           WM8915_MICD_RATE_MASK);
-
-       /* Enable interrupts and we're off */
-       snd_soc_update_bits(codec, WM8915_INTERRUPT_STATUS_2_MASK,
-                           WM8915_IM_MICD_EINT, 0);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(wm8915_detect);
-
-static void wm8915_micd(struct snd_soc_codec *codec)
-{
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       int val, reg;
-
-       val = snd_soc_read(codec, WM8915_MIC_DETECT_3);
-
-       dev_dbg(codec->dev, "Microphone event: %x\n", val);
-
-       if (!(val & WM8915_MICD_VALID)) {
-               dev_warn(codec->dev, "Microphone detection state invalid\n");
-               return;
-       }
-
-       /* No accessory, reset everything and report removal */
-       if (!(val & WM8915_MICD_STS)) {
-               dev_dbg(codec->dev, "Jack removal detected\n");
-               wm8915->jack_mic = false;
-               wm8915->detecting = true;
-               snd_soc_jack_report(wm8915->jack, 0,
-                                   SND_JACK_HEADSET | SND_JACK_BTN_0);
-               snd_soc_update_bits(codec, WM8915_MIC_DETECT_1,
-                                   WM8915_MICD_RATE_MASK,
-                                   WM8915_MICD_RATE_MASK);
-               return;
-       }
-
-       /* If the measurement is very high we've got a microphone but
-        * do a little debounce to account for mechanical issues.
-        */
-       if (val & 0x400) {
-               dev_dbg(codec->dev, "Microphone detected\n");
-               snd_soc_jack_report(wm8915->jack, SND_JACK_HEADSET,
-                                   SND_JACK_HEADSET | SND_JACK_BTN_0);
-               wm8915->jack_mic = true;
-               wm8915->detecting = false;
-
-               /* Increase poll rate to give better responsiveness
-                * for buttons */
-               snd_soc_update_bits(codec, WM8915_MIC_DETECT_1,
-                                   WM8915_MICD_RATE_MASK,
-                                   5 << WM8915_MICD_RATE_SHIFT);
-       }
-
-       /* If we detected a lower impedence during initial startup
-        * then we probably have the wrong polarity, flip it.  Don't
-        * do this for the lowest impedences to speed up detection of
-        * plain headphones.
-        */
-       if (wm8915->detecting && (val & 0x3f0)) {
-               reg = snd_soc_read(codec, WM8915_ACCESSORY_DETECT_MODE_2);
-               reg ^= WM8915_HPOUT1FB_SRC | WM8915_MICD_SRC |
-                       WM8915_MICD_BIAS_SRC;
-               snd_soc_update_bits(codec, WM8915_ACCESSORY_DETECT_MODE_2,
-                                   WM8915_HPOUT1FB_SRC | WM8915_MICD_SRC |
-                                   WM8915_MICD_BIAS_SRC, reg);
-
-               if (wm8915->polarity_cb)
-                       wm8915->polarity_cb(codec,
-                                           (reg & WM8915_MICD_SRC) != 0);
-
-               dev_dbg(codec->dev, "Set microphone polarity to %d\n",
-                       (reg & WM8915_MICD_SRC) != 0);
-
-               return;
-       }
-
-       /* Don't distinguish between buttons, just report any low
-        * impedence as BTN_0.
-        */
-       if (val & 0x3fc) {
-               if (wm8915->jack_mic) {
-                       dev_dbg(codec->dev, "Mic button detected\n");
-                       snd_soc_jack_report(wm8915->jack,
-                                           SND_JACK_HEADSET | SND_JACK_BTN_0,
-                                           SND_JACK_HEADSET | SND_JACK_BTN_0);
-               } else {
-                       dev_dbg(codec->dev, "Headphone detected\n");
-                       snd_soc_jack_report(wm8915->jack,
-                                           SND_JACK_HEADPHONE,
-                                           SND_JACK_HEADSET |
-                                           SND_JACK_BTN_0);
-
-                       /* Increase the detection rate a bit for
-                        * responsiveness.
-                        */
-                       snd_soc_update_bits(codec, WM8915_MIC_DETECT_1,
-                                           WM8915_MICD_RATE_MASK,
-                                           7 << WM8915_MICD_RATE_SHIFT);
-
-                       wm8915->detecting = false;
-               }
-       }
-}
-
-static irqreturn_t wm8915_irq(int irq, void *data)
-{
-       struct snd_soc_codec *codec = data;
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       int irq_val;
-
-       irq_val = snd_soc_read(codec, WM8915_INTERRUPT_STATUS_2);
-       if (irq_val < 0) {
-               dev_err(codec->dev, "Failed to read IRQ status: %d\n",
-                       irq_val);
-               return IRQ_NONE;
-       }
-       irq_val &= ~snd_soc_read(codec, WM8915_INTERRUPT_STATUS_2_MASK);
-
-       if (irq_val & (WM8915_DCS_DONE_01_EINT | WM8915_DCS_DONE_23_EINT)) {
-               dev_dbg(codec->dev, "DC servo IRQ\n");
-               complete(&wm8915->dcs_done);
-       }
-
-       if (irq_val & WM8915_FIFOS_ERR_EINT)
-               dev_err(codec->dev, "Digital core FIFO error\n");
-
-       if (irq_val & WM8915_FLL_LOCK_EINT) {
-               dev_dbg(codec->dev, "FLL locked\n");
-               complete(&wm8915->fll_lock);
-       }
-
-       if (irq_val & WM8915_MICD_EINT)
-               wm8915_micd(codec);
-
-       if (irq_val) {
-               snd_soc_write(codec, WM8915_INTERRUPT_STATUS_2, irq_val);
-
-               return IRQ_HANDLED;
-       } else {
-               return IRQ_NONE;
-       }
-}
-
-static irqreturn_t wm8915_edge_irq(int irq, void *data)
-{
-       irqreturn_t ret = IRQ_NONE;
-       irqreturn_t val;
-
-       do {
-               val = wm8915_irq(irq, data);
-               if (val != IRQ_NONE)
-                       ret = val;
-       } while (val != IRQ_NONE);
-
-       return ret;
-}
-
-static void wm8915_retune_mobile_pdata(struct snd_soc_codec *codec)
-{
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       struct wm8915_pdata *pdata = &wm8915->pdata;
-
-       struct snd_kcontrol_new controls[] = {
-               SOC_ENUM_EXT("DSP1 EQ Mode",
-                            wm8915->retune_mobile_enum,
-                            wm8915_get_retune_mobile_enum,
-                            wm8915_put_retune_mobile_enum),
-               SOC_ENUM_EXT("DSP2 EQ Mode",
-                            wm8915->retune_mobile_enum,
-                            wm8915_get_retune_mobile_enum,
-                            wm8915_put_retune_mobile_enum),
-       };
-       int ret, i, j;
-       const char **t;
-
-       /* We need an array of texts for the enum API but the number
-        * of texts is likely to be less than the number of
-        * configurations due to the sample rate dependency of the
-        * configurations. */
-       wm8915->num_retune_mobile_texts = 0;
-       wm8915->retune_mobile_texts = NULL;
-       for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) {
-               for (j = 0; j < wm8915->num_retune_mobile_texts; j++) {
-                       if (strcmp(pdata->retune_mobile_cfgs[i].name,
-                                  wm8915->retune_mobile_texts[j]) == 0)
-                               break;
-               }
-
-               if (j != wm8915->num_retune_mobile_texts)
-                       continue;
-
-               /* Expand the array... */
-               t = krealloc(wm8915->retune_mobile_texts,
-                            sizeof(char *) * 
-                            (wm8915->num_retune_mobile_texts + 1),
-                            GFP_KERNEL);
-               if (t == NULL)
-                       continue;
-
-               /* ...store the new entry... */
-               t[wm8915->num_retune_mobile_texts] = 
-                       pdata->retune_mobile_cfgs[i].name;
-
-               /* ...and remember the new version. */
-               wm8915->num_retune_mobile_texts++;
-               wm8915->retune_mobile_texts = t;
-       }
-
-       dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n",
-               wm8915->num_retune_mobile_texts);
-
-       wm8915->retune_mobile_enum.max = wm8915->num_retune_mobile_texts;
-       wm8915->retune_mobile_enum.texts = wm8915->retune_mobile_texts;
-
-       ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
-       if (ret != 0)
-               dev_err(codec->dev,
-                       "Failed to add ReTune Mobile controls: %d\n", ret);
-}
-
-static int wm8915_probe(struct snd_soc_codec *codec)
-{
-       int ret;
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       struct i2c_client *i2c = to_i2c_client(codec->dev);
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int i, irq_flags;
-
-       wm8915->codec = codec;
-
-       init_completion(&wm8915->dcs_done);
-       init_completion(&wm8915->fll_lock);
-
-       dapm->idle_bias_off = true;
-       dapm->bias_level = SND_SOC_BIAS_OFF;
-
-       ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-               goto err;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++)
-               wm8915->supplies[i].supply = wm8915_supply_names[i];
-
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8915->supplies),
-                                wm8915->supplies);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               goto err;
-       }
-
-       wm8915->disable_nb[0].notifier_call = wm8915_regulator_event_0;
-       wm8915->disable_nb[1].notifier_call = wm8915_regulator_event_1;
-       wm8915->disable_nb[2].notifier_call = wm8915_regulator_event_2;
-       wm8915->disable_nb[3].notifier_call = wm8915_regulator_event_3;
-
-       /* This should really be moved into the regulator core */
-       for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++) {
-               ret = regulator_register_notifier(wm8915->supplies[i].consumer,
-                                                 &wm8915->disable_nb[i]);
-               if (ret != 0) {
-                       dev_err(codec->dev,
-                               "Failed to register regulator notifier: %d\n",
-                               ret);
-               }
-       }
-
-       ret = regulator_bulk_enable(ARRAY_SIZE(wm8915->supplies),
-                                   wm8915->supplies);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_get;
-       }
-
-       if (wm8915->pdata.ldo_ena >= 0) {
-               gpio_set_value_cansleep(wm8915->pdata.ldo_ena, 1);
-               msleep(5);
-       }
-
-       ret = snd_soc_read(codec, WM8915_SOFTWARE_RESET);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to read ID register: %d\n", ret);
-               goto err_enable;
-       }
-       if (ret != 0x8915) {
-               dev_err(codec->dev, "Device is not a WM8915, ID %x\n", ret);
-               ret = -EINVAL;
-               goto err_enable;
-       }
-
-       ret = snd_soc_read(codec, WM8915_CHIP_REVISION);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to read device revision: %d\n",
-                       ret);
-               goto err_enable;
-       }
-       
-       dev_info(codec->dev, "revision %c\n",
-                (ret & WM8915_CHIP_REV_MASK) + 'A');
-
-       if (wm8915->pdata.ldo_ena >= 0) {
-               gpio_set_value_cansleep(wm8915->pdata.ldo_ena, 0);
-       } else {
-               ret = wm8915_reset(codec);
-               if (ret < 0) {
-                       dev_err(codec->dev, "Failed to issue reset\n");
-                       goto err_enable;
-               }
-       }
-
-       codec->cache_only = true;
-
-       /* Apply platform data settings */
-       snd_soc_update_bits(codec, WM8915_LINE_INPUT_CONTROL,
-                           WM8915_INL_MODE_MASK | WM8915_INR_MODE_MASK,
-                           wm8915->pdata.inl_mode << WM8915_INL_MODE_SHIFT |
-                           wm8915->pdata.inr_mode);
-
-       for (i = 0; i < ARRAY_SIZE(wm8915->pdata.gpio_default); i++) {
-               if (!wm8915->pdata.gpio_default[i])
-                       continue;
-
-               snd_soc_write(codec, WM8915_GPIO_1 + i,
-                             wm8915->pdata.gpio_default[i] & 0xffff);
-       }
-
-       if (wm8915->pdata.spkmute_seq)
-               snd_soc_update_bits(codec, WM8915_PDM_SPEAKER_MUTE_SEQUENCE,
-                                   WM8915_SPK_MUTE_ENDIAN |
-                                   WM8915_SPK_MUTE_SEQ1_MASK,
-                                   wm8915->pdata.spkmute_seq);
-
-       snd_soc_update_bits(codec, WM8915_ACCESSORY_DETECT_MODE_2,
-                           WM8915_MICD_BIAS_SRC | WM8915_HPOUT1FB_SRC |
-                           WM8915_MICD_SRC, wm8915->pdata.micdet_def);
-
-       /* Latch volume update bits */
-       snd_soc_update_bits(codec, WM8915_LEFT_LINE_INPUT_VOLUME,
-                           WM8915_IN1_VU, WM8915_IN1_VU);
-       snd_soc_update_bits(codec, WM8915_RIGHT_LINE_INPUT_VOLUME,
-                           WM8915_IN1_VU, WM8915_IN1_VU);
-
-       snd_soc_update_bits(codec, WM8915_DAC1_LEFT_VOLUME,
-                           WM8915_DAC1_VU, WM8915_DAC1_VU);
-       snd_soc_update_bits(codec, WM8915_DAC1_RIGHT_VOLUME,
-                           WM8915_DAC1_VU, WM8915_DAC1_VU);
-       snd_soc_update_bits(codec, WM8915_DAC2_LEFT_VOLUME,
-                           WM8915_DAC2_VU, WM8915_DAC2_VU);
-       snd_soc_update_bits(codec, WM8915_DAC2_RIGHT_VOLUME,
-                           WM8915_DAC2_VU, WM8915_DAC2_VU);
-
-       snd_soc_update_bits(codec, WM8915_OUTPUT1_LEFT_VOLUME,
-                           WM8915_DAC1_VU, WM8915_DAC1_VU);
-       snd_soc_update_bits(codec, WM8915_OUTPUT1_RIGHT_VOLUME,
-                           WM8915_DAC1_VU, WM8915_DAC1_VU);
-       snd_soc_update_bits(codec, WM8915_OUTPUT2_LEFT_VOLUME,
-                           WM8915_DAC2_VU, WM8915_DAC2_VU);
-       snd_soc_update_bits(codec, WM8915_OUTPUT2_RIGHT_VOLUME,
-                           WM8915_DAC2_VU, WM8915_DAC2_VU);
-
-       snd_soc_update_bits(codec, WM8915_DSP1_TX_LEFT_VOLUME,
-                           WM8915_DSP1TX_VU, WM8915_DSP1TX_VU);
-       snd_soc_update_bits(codec, WM8915_DSP1_TX_RIGHT_VOLUME,
-                           WM8915_DSP1TX_VU, WM8915_DSP1TX_VU);
-       snd_soc_update_bits(codec, WM8915_DSP2_TX_LEFT_VOLUME,
-                           WM8915_DSP2TX_VU, WM8915_DSP2TX_VU);
-       snd_soc_update_bits(codec, WM8915_DSP2_TX_RIGHT_VOLUME,
-                           WM8915_DSP2TX_VU, WM8915_DSP2TX_VU);
-
-       snd_soc_update_bits(codec, WM8915_DSP1_RX_LEFT_VOLUME,
-                           WM8915_DSP1RX_VU, WM8915_DSP1RX_VU);
-       snd_soc_update_bits(codec, WM8915_DSP1_RX_RIGHT_VOLUME,
-                           WM8915_DSP1RX_VU, WM8915_DSP1RX_VU);
-       snd_soc_update_bits(codec, WM8915_DSP2_RX_LEFT_VOLUME,
-                           WM8915_DSP2RX_VU, WM8915_DSP2RX_VU);
-       snd_soc_update_bits(codec, WM8915_DSP2_RX_RIGHT_VOLUME,
-                           WM8915_DSP2RX_VU, WM8915_DSP2RX_VU);
-
-       /* No support currently for the underclocked TDM modes and
-        * pick a default TDM layout with each channel pair working with
-        * slots 0 and 1. */
-       snd_soc_update_bits(codec, WM8915_AIF1RX_CHANNEL_0_CONFIGURATION,
-                           WM8915_AIF1RX_CHAN0_SLOTS_MASK |
-                           WM8915_AIF1RX_CHAN0_START_SLOT_MASK,
-                           1 << WM8915_AIF1RX_CHAN0_SLOTS_SHIFT | 0);
-       snd_soc_update_bits(codec, WM8915_AIF1RX_CHANNEL_1_CONFIGURATION,
-                           WM8915_AIF1RX_CHAN1_SLOTS_MASK |
-                           WM8915_AIF1RX_CHAN1_START_SLOT_MASK,
-                           1 << WM8915_AIF1RX_CHAN1_SLOTS_SHIFT | 1);
-       snd_soc_update_bits(codec, WM8915_AIF1RX_CHANNEL_2_CONFIGURATION,
-                           WM8915_AIF1RX_CHAN2_SLOTS_MASK |
-                           WM8915_AIF1RX_CHAN2_START_SLOT_MASK,
-                           1 << WM8915_AIF1RX_CHAN2_SLOTS_SHIFT | 0);
-       snd_soc_update_bits(codec, WM8915_AIF1RX_CHANNEL_3_CONFIGURATION,
-                           WM8915_AIF1RX_CHAN3_SLOTS_MASK |
-                           WM8915_AIF1RX_CHAN0_START_SLOT_MASK,
-                           1 << WM8915_AIF1RX_CHAN3_SLOTS_SHIFT | 1);
-       snd_soc_update_bits(codec, WM8915_AIF1RX_CHANNEL_4_CONFIGURATION,
-                           WM8915_AIF1RX_CHAN4_SLOTS_MASK |
-                           WM8915_AIF1RX_CHAN0_START_SLOT_MASK,
-                           1 << WM8915_AIF1RX_CHAN4_SLOTS_SHIFT | 0);
-       snd_soc_update_bits(codec, WM8915_AIF1RX_CHANNEL_5_CONFIGURATION,
-                           WM8915_AIF1RX_CHAN5_SLOTS_MASK |
-                           WM8915_AIF1RX_CHAN0_START_SLOT_MASK,
-                           1 << WM8915_AIF1RX_CHAN5_SLOTS_SHIFT | 1);
-
-       snd_soc_update_bits(codec, WM8915_AIF2RX_CHANNEL_0_CONFIGURATION,
-                           WM8915_AIF2RX_CHAN0_SLOTS_MASK |
-                           WM8915_AIF2RX_CHAN0_START_SLOT_MASK,
-                           1 << WM8915_AIF2RX_CHAN0_SLOTS_SHIFT | 0);
-       snd_soc_update_bits(codec, WM8915_AIF2RX_CHANNEL_1_CONFIGURATION,
-                           WM8915_AIF2RX_CHAN1_SLOTS_MASK |
-                           WM8915_AIF2RX_CHAN1_START_SLOT_MASK,
-                           1 << WM8915_AIF2RX_CHAN1_SLOTS_SHIFT | 1);
-
-       snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_0_CONFIGURATION,
-                           WM8915_AIF1TX_CHAN0_SLOTS_MASK |
-                           WM8915_AIF1TX_CHAN0_START_SLOT_MASK,
-                           1 << WM8915_AIF1TX_CHAN0_SLOTS_SHIFT | 0);
-       snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_1_CONFIGURATION,
-                           WM8915_AIF1TX_CHAN1_SLOTS_MASK |
-                           WM8915_AIF1TX_CHAN0_START_SLOT_MASK,
-                           1 << WM8915_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
-       snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_2_CONFIGURATION,
-                           WM8915_AIF1TX_CHAN2_SLOTS_MASK |
-                           WM8915_AIF1TX_CHAN0_START_SLOT_MASK,
-                           1 << WM8915_AIF1TX_CHAN2_SLOTS_SHIFT | 0);
-       snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_3_CONFIGURATION,
-                           WM8915_AIF1TX_CHAN3_SLOTS_MASK |
-                           WM8915_AIF1TX_CHAN0_START_SLOT_MASK,
-                           1 << WM8915_AIF1TX_CHAN3_SLOTS_SHIFT | 1);
-       snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_4_CONFIGURATION,
-                           WM8915_AIF1TX_CHAN4_SLOTS_MASK |
-                           WM8915_AIF1TX_CHAN0_START_SLOT_MASK,
-                           1 << WM8915_AIF1TX_CHAN4_SLOTS_SHIFT | 0);
-       snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_5_CONFIGURATION,
-                           WM8915_AIF1TX_CHAN5_SLOTS_MASK |
-                           WM8915_AIF1TX_CHAN0_START_SLOT_MASK,
-                           1 << WM8915_AIF1TX_CHAN5_SLOTS_SHIFT | 1);
-
-       snd_soc_update_bits(codec, WM8915_AIF2TX_CHANNEL_0_CONFIGURATION,
-                           WM8915_AIF2TX_CHAN0_SLOTS_MASK |
-                           WM8915_AIF2TX_CHAN0_START_SLOT_MASK,
-                           1 << WM8915_AIF2TX_CHAN0_SLOTS_SHIFT | 0);
-       snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_1_CONFIGURATION,
-                           WM8915_AIF2TX_CHAN1_SLOTS_MASK |
-                           WM8915_AIF2TX_CHAN1_START_SLOT_MASK,
-                           1 << WM8915_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
-
-       if (wm8915->pdata.num_retune_mobile_cfgs)
-               wm8915_retune_mobile_pdata(codec);
-       else
-               snd_soc_add_controls(codec, wm8915_eq_controls,
-                                    ARRAY_SIZE(wm8915_eq_controls));
-
-       /* If the TX LRCLK pins are not in LRCLK mode configure the
-        * AIFs to source their clocks from the RX LRCLKs.
-        */
-       if ((snd_soc_read(codec, WM8915_GPIO_1)))
-               snd_soc_update_bits(codec, WM8915_AIF1_TX_LRCLK_2,
-                                   WM8915_AIF1TX_LRCLK_MODE,
-                                   WM8915_AIF1TX_LRCLK_MODE);
-
-       if ((snd_soc_read(codec, WM8915_GPIO_2)))
-               snd_soc_update_bits(codec, WM8915_AIF2_TX_LRCLK_2,
-                                   WM8915_AIF2TX_LRCLK_MODE,
-                                   WM8915_AIF2TX_LRCLK_MODE);
-
-       regulator_bulk_disable(ARRAY_SIZE(wm8915->supplies), wm8915->supplies);
-
-       wm8915_init_gpio(codec);
-
-       if (i2c->irq) {
-               if (wm8915->pdata.irq_flags)
-                       irq_flags = wm8915->pdata.irq_flags;
-               else
-                       irq_flags = IRQF_TRIGGER_LOW;
-
-               irq_flags |= IRQF_ONESHOT;
-
-               if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
-                       ret = request_threaded_irq(i2c->irq, NULL,
-                                                  wm8915_edge_irq,
-                                                  irq_flags, "wm8915", codec);
-               else
-                       ret = request_threaded_irq(i2c->irq, NULL, wm8915_irq,
-                                                  irq_flags, "wm8915", codec);
-
-               if (ret == 0) {
-                       /* Unmask the interrupt */
-                       snd_soc_update_bits(codec, WM8915_INTERRUPT_CONTROL,
-                                           WM8915_IM_IRQ, 0);
-
-                       /* Enable error reporting and DC servo status */
-                       snd_soc_update_bits(codec,
-                                           WM8915_INTERRUPT_STATUS_2_MASK,
-                                           WM8915_IM_DCS_DONE_23_EINT |
-                                           WM8915_IM_DCS_DONE_01_EINT |
-                                           WM8915_IM_FLL_LOCK_EINT |
-                                           WM8915_IM_FIFOS_ERR_EINT,
-                                           0);
-               } else {
-                       dev_err(codec->dev, "Failed to request IRQ: %d\n",
-                               ret);
-               }
-       }
-
-       return 0;
-
-err_enable:
-       if (wm8915->pdata.ldo_ena >= 0)
-               gpio_set_value_cansleep(wm8915->pdata.ldo_ena, 0);
-
-       regulator_bulk_disable(ARRAY_SIZE(wm8915->supplies), wm8915->supplies);
-err_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8915->supplies), wm8915->supplies);
-err:
-       return ret;
-}
-
-static int wm8915_remove(struct snd_soc_codec *codec)
-{
-       struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-       struct i2c_client *i2c = to_i2c_client(codec->dev);
-       int i;
-
-       snd_soc_update_bits(codec, WM8915_INTERRUPT_CONTROL,
-                           WM8915_IM_IRQ, WM8915_IM_IRQ);
-
-       if (i2c->irq)
-               free_irq(i2c->irq, codec);
-
-       wm8915_free_gpio(codec);
-
-       for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++)
-               regulator_unregister_notifier(wm8915->supplies[i].consumer,
-                                             &wm8915->disable_nb[i]);
-       regulator_bulk_free(ARRAY_SIZE(wm8915->supplies), wm8915->supplies);
-
-       return 0;
-}
-
-static struct snd_soc_codec_driver soc_codec_dev_wm8915 = {
-       .probe =        wm8915_probe,
-       .remove =       wm8915_remove,
-       .set_bias_level = wm8915_set_bias_level,
-       .seq_notifier = wm8915_seq_notifier,
-       .reg_cache_size = WM8915_MAX_REGISTER + 1,
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8915_reg,
-       .volatile_register = wm8915_volatile_register,
-       .readable_register = wm8915_readable_register,
-       .compress_type = SND_SOC_RBTREE_COMPRESSION,
-       .controls = wm8915_snd_controls,
-       .num_controls = ARRAY_SIZE(wm8915_snd_controls),
-       .dapm_widgets = wm8915_dapm_widgets,
-       .num_dapm_widgets = ARRAY_SIZE(wm8915_dapm_widgets),
-       .dapm_routes = wm8915_dapm_routes,
-       .num_dapm_routes = ARRAY_SIZE(wm8915_dapm_routes),
-       .set_pll = wm8915_set_fll,
-};
-
-#define WM8915_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
-                     SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
-#define WM8915_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
-                       SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\
-                       SNDRV_PCM_FMTBIT_S32_LE)
-
-static struct snd_soc_dai_ops wm8915_dai_ops = {
-       .set_fmt = wm8915_set_fmt,
-       .hw_params = wm8915_hw_params,
-       .set_sysclk = wm8915_set_sysclk,
-};
-
-static struct snd_soc_dai_driver wm8915_dai[] = {
-       {
-               .name = "wm8915-aif1",
-               .playback = {
-                       .stream_name = "AIF1 Playback",
-                       .channels_min = 1,
-                       .channels_max = 6,
-                       .rates = WM8915_RATES,
-                       .formats = WM8915_FORMATS,
-               },
-               .capture = {
-                        .stream_name = "AIF1 Capture",
-                        .channels_min = 1,
-                        .channels_max = 6,
-                        .rates = WM8915_RATES,
-                        .formats = WM8915_FORMATS,
-                },
-               .ops = &wm8915_dai_ops,
-       },
-       {
-               .name = "wm8915-aif2",
-               .playback = {
-                       .stream_name = "AIF2 Playback",
-                       .channels_min = 1,
-                       .channels_max = 2,
-                       .rates = WM8915_RATES,
-                       .formats = WM8915_FORMATS,
-               },
-               .capture = {
-                        .stream_name = "AIF2 Capture",
-                        .channels_min = 1,
-                        .channels_max = 2,
-                        .rates = WM8915_RATES,
-                        .formats = WM8915_FORMATS,
-                },
-               .ops = &wm8915_dai_ops,
-       },
-};
-
-static __devinit int wm8915_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
-{
-       struct wm8915_priv *wm8915;
-       int ret;
-
-       wm8915 = kzalloc(sizeof(struct wm8915_priv), GFP_KERNEL);
-       if (wm8915 == NULL)
-               return -ENOMEM;
-
-       i2c_set_clientdata(i2c, wm8915);
-
-       if (dev_get_platdata(&i2c->dev))
-               memcpy(&wm8915->pdata, dev_get_platdata(&i2c->dev),
-                      sizeof(wm8915->pdata));
-
-       if (wm8915->pdata.ldo_ena > 0) {
-               ret = gpio_request_one(wm8915->pdata.ldo_ena,
-                                      GPIOF_OUT_INIT_LOW, "WM8915 ENA");
-               if (ret < 0) {
-                       dev_err(&i2c->dev, "Failed to request GPIO %d: %d\n",
-                               wm8915->pdata.ldo_ena, ret);
-                       goto err;
-               }
-       }
-
-       ret = snd_soc_register_codec(&i2c->dev,
-                                    &soc_codec_dev_wm8915, wm8915_dai,
-                                    ARRAY_SIZE(wm8915_dai));
-       if (ret < 0)
-               goto err_gpio;
-
-       return ret;
-
-err_gpio:
-       if (wm8915->pdata.ldo_ena > 0)
-               gpio_free(wm8915->pdata.ldo_ena);
-err:
-       kfree(wm8915);
-
-       return ret;
-}
-
-static __devexit int wm8915_i2c_remove(struct i2c_client *client)
-{
-       struct wm8915_priv *wm8915 = i2c_get_clientdata(client);
-
-       snd_soc_unregister_codec(&client->dev);
-       if (wm8915->pdata.ldo_ena > 0)
-               gpio_free(wm8915->pdata.ldo_ena);
-       kfree(i2c_get_clientdata(client));
-       return 0;
-}
-
-static const struct i2c_device_id wm8915_i2c_id[] = {
-       { "wm8915", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8915_i2c_id);
-
-static struct i2c_driver wm8915_i2c_driver = {
-       .driver = {
-               .name = "wm8915",
-               .owner = THIS_MODULE,
-       },
-       .probe =    wm8915_i2c_probe,
-       .remove =   __devexit_p(wm8915_i2c_remove),
-       .id_table = wm8915_i2c_id,
-};
-
-static int __init wm8915_modinit(void)
-{
-       int ret;
-
-       ret = i2c_add_driver(&wm8915_i2c_driver);
-       if (ret != 0) {
-               printk(KERN_ERR "Failed to register WM8915 I2C driver: %d\n",
-                      ret);
-       }
-
-       return ret;
-}
-module_init(wm8915_modinit);
-
-static void __exit wm8915_exit(void)
-{
-       i2c_del_driver(&wm8915_i2c_driver);
-}
-module_exit(wm8915_exit);
-
-MODULE_DESCRIPTION("ASoC WM8915 driver");
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8915.h b/sound/soc/codecs/wm8915.h
deleted file mode 100644 (file)
index 200ffd7..0000000
+++ /dev/null
@@ -1,3717 +0,0 @@
-/*
- * wm8915.h - WM8915 audio codec interface
- *
- * Copyright 2011 Wolfson Microelectronics PLC.
- * Author: Mark Brown <broonie@opensource.wolfsonmicro.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.
- */
-
-#ifndef _WM8915_H
-#define _WM8915_H
-
-#define WM8915_SYSCLK_MCLK1 1
-#define WM8915_SYSCLK_MCLK2 2
-#define WM8915_SYSCLK_FLL   3
-
-#define WM8915_FLL_MCLK1      1
-#define WM8915_FLL_MCLK2      2
-#define WM8915_FLL_DACLRCLK1  3
-#define WM8915_FLL_BCLK1      4
-
-typedef void (*wm8915_polarity_fn)(struct snd_soc_codec *codec, int polarity);
-
-int wm8915_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
-                 wm8915_polarity_fn polarity_cb);
-
-/*
- * Register values.
- */
-#define WM8915_SOFTWARE_RESET                   0x00
-#define WM8915_POWER_MANAGEMENT_1               0x01
-#define WM8915_POWER_MANAGEMENT_2               0x02
-#define WM8915_POWER_MANAGEMENT_3               0x03
-#define WM8915_POWER_MANAGEMENT_4               0x04
-#define WM8915_POWER_MANAGEMENT_5               0x05
-#define WM8915_POWER_MANAGEMENT_6               0x06
-#define WM8915_POWER_MANAGEMENT_7               0x07
-#define WM8915_POWER_MANAGEMENT_8               0x08
-#define WM8915_LEFT_LINE_INPUT_VOLUME           0x10
-#define WM8915_RIGHT_LINE_INPUT_VOLUME          0x11
-#define WM8915_LINE_INPUT_CONTROL               0x12
-#define WM8915_DAC1_HPOUT1_VOLUME               0x15
-#define WM8915_DAC2_HPOUT2_VOLUME               0x16
-#define WM8915_DAC1_LEFT_VOLUME                 0x18
-#define WM8915_DAC1_RIGHT_VOLUME                0x19
-#define WM8915_DAC2_LEFT_VOLUME                 0x1A
-#define WM8915_DAC2_RIGHT_VOLUME                0x1B
-#define WM8915_OUTPUT1_LEFT_VOLUME              0x1C
-#define WM8915_OUTPUT1_RIGHT_VOLUME             0x1D
-#define WM8915_OUTPUT2_LEFT_VOLUME              0x1E
-#define WM8915_OUTPUT2_RIGHT_VOLUME             0x1F
-#define WM8915_MICBIAS_1                        0x20
-#define WM8915_MICBIAS_2                        0x21
-#define WM8915_LDO_1                            0x28
-#define WM8915_LDO_2                            0x29
-#define WM8915_ACCESSORY_DETECT_MODE_1          0x30
-#define WM8915_ACCESSORY_DETECT_MODE_2          0x31
-#define WM8915_HEADPHONE_DETECT_1               0x34
-#define WM8915_HEADPHONE_DETECT_2               0x35
-#define WM8915_MIC_DETECT_1                     0x38
-#define WM8915_MIC_DETECT_2                     0x39
-#define WM8915_MIC_DETECT_3                     0x3A
-#define WM8915_CHARGE_PUMP_1                    0x40
-#define WM8915_CHARGE_PUMP_2                    0x41
-#define WM8915_DC_SERVO_1                       0x50
-#define WM8915_DC_SERVO_2                       0x51
-#define WM8915_DC_SERVO_3                       0x52
-#define WM8915_DC_SERVO_5                       0x54
-#define WM8915_DC_SERVO_6                       0x55
-#define WM8915_DC_SERVO_7                       0x56
-#define WM8915_DC_SERVO_READBACK_0              0x57
-#define WM8915_ANALOGUE_HP_1                    0x60
-#define WM8915_ANALOGUE_HP_2                    0x61
-#define WM8915_CHIP_REVISION                    0x100
-#define WM8915_CONTROL_INTERFACE_1              0x101
-#define WM8915_WRITE_SEQUENCER_CTRL_1           0x110
-#define WM8915_WRITE_SEQUENCER_CTRL_2           0x111
-#define WM8915_AIF_CLOCKING_1                   0x200
-#define WM8915_AIF_CLOCKING_2                   0x201
-#define WM8915_CLOCKING_1                       0x208
-#define WM8915_CLOCKING_2                       0x209
-#define WM8915_AIF_RATE                         0x210
-#define WM8915_FLL_CONTROL_1                    0x220
-#define WM8915_FLL_CONTROL_2                    0x221
-#define WM8915_FLL_CONTROL_3                    0x222
-#define WM8915_FLL_CONTROL_4                    0x223
-#define WM8915_FLL_CONTROL_5                    0x224
-#define WM8915_FLL_CONTROL_6                    0x225
-#define WM8915_FLL_EFS_1                        0x226
-#define WM8915_FLL_EFS_2                        0x227
-#define WM8915_AIF1_CONTROL                     0x300
-#define WM8915_AIF1_BCLK                        0x301
-#define WM8915_AIF1_TX_LRCLK_1                  0x302
-#define WM8915_AIF1_TX_LRCLK_2                  0x303
-#define WM8915_AIF1_RX_LRCLK_1                  0x304
-#define WM8915_AIF1_RX_LRCLK_2                  0x305
-#define WM8915_AIF1TX_DATA_CONFIGURATION_1      0x306
-#define WM8915_AIF1TX_DATA_CONFIGURATION_2      0x307
-#define WM8915_AIF1RX_DATA_CONFIGURATION        0x308
-#define WM8915_AIF1TX_CHANNEL_0_CONFIGURATION   0x309
-#define WM8915_AIF1TX_CHANNEL_1_CONFIGURATION   0x30A
-#define WM8915_AIF1TX_CHANNEL_2_CONFIGURATION   0x30B
-#define WM8915_AIF1TX_CHANNEL_3_CONFIGURATION   0x30C
-#define WM8915_AIF1TX_CHANNEL_4_CONFIGURATION   0x30D
-#define WM8915_AIF1TX_CHANNEL_5_CONFIGURATION   0x30E
-#define WM8915_AIF1RX_CHANNEL_0_CONFIGURATION   0x30F
-#define WM8915_AIF1RX_CHANNEL_1_CONFIGURATION   0x310
-#define WM8915_AIF1RX_CHANNEL_2_CONFIGURATION   0x311
-#define WM8915_AIF1RX_CHANNEL_3_CONFIGURATION   0x312
-#define WM8915_AIF1RX_CHANNEL_4_CONFIGURATION   0x313
-#define WM8915_AIF1RX_CHANNEL_5_CONFIGURATION   0x314
-#define WM8915_AIF1RX_MONO_CONFIGURATION        0x315
-#define WM8915_AIF1TX_TEST                      0x31A
-#define WM8915_AIF2_CONTROL                     0x320
-#define WM8915_AIF2_BCLK                        0x321
-#define WM8915_AIF2_TX_LRCLK_1                  0x322
-#define WM8915_AIF2_TX_LRCLK_2                  0x323
-#define WM8915_AIF2_RX_LRCLK_1                  0x324
-#define WM8915_AIF2_RX_LRCLK_2                  0x325
-#define WM8915_AIF2TX_DATA_CONFIGURATION_1      0x326
-#define WM8915_AIF2TX_DATA_CONFIGURATION_2      0x327
-#define WM8915_AIF2RX_DATA_CONFIGURATION        0x328
-#define WM8915_AIF2TX_CHANNEL_0_CONFIGURATION   0x329
-#define WM8915_AIF2TX_CHANNEL_1_CONFIGURATION   0x32A
-#define WM8915_AIF2RX_CHANNEL_0_CONFIGURATION   0x32B
-#define WM8915_AIF2RX_CHANNEL_1_CONFIGURATION   0x32C
-#define WM8915_AIF2RX_MONO_CONFIGURATION        0x32D
-#define WM8915_AIF2TX_TEST                      0x32F
-#define WM8915_DSP1_TX_LEFT_VOLUME              0x400
-#define WM8915_DSP1_TX_RIGHT_VOLUME             0x401
-#define WM8915_DSP1_RX_LEFT_VOLUME              0x402
-#define WM8915_DSP1_RX_RIGHT_VOLUME             0x403
-#define WM8915_DSP1_TX_FILTERS                  0x410
-#define WM8915_DSP1_RX_FILTERS_1                0x420
-#define WM8915_DSP1_RX_FILTERS_2                0x421
-#define WM8915_DSP1_DRC_1                       0x440
-#define WM8915_DSP1_DRC_2                       0x441
-#define WM8915_DSP1_DRC_3                       0x442
-#define WM8915_DSP1_DRC_4                       0x443
-#define WM8915_DSP1_DRC_5                       0x444
-#define WM8915_DSP1_RX_EQ_GAINS_1               0x480
-#define WM8915_DSP1_RX_EQ_GAINS_2               0x481
-#define WM8915_DSP1_RX_EQ_BAND_1_A              0x482
-#define WM8915_DSP1_RX_EQ_BAND_1_B              0x483
-#define WM8915_DSP1_RX_EQ_BAND_1_PG             0x484
-#define WM8915_DSP1_RX_EQ_BAND_2_A              0x485
-#define WM8915_DSP1_RX_EQ_BAND_2_B              0x486
-#define WM8915_DSP1_RX_EQ_BAND_2_C              0x487
-#define WM8915_DSP1_RX_EQ_BAND_2_PG             0x488
-#define WM8915_DSP1_RX_EQ_BAND_3_A              0x489
-#define WM8915_DSP1_RX_EQ_BAND_3_B              0x48A
-#define WM8915_DSP1_RX_EQ_BAND_3_C              0x48B
-#define WM8915_DSP1_RX_EQ_BAND_3_PG             0x48C
-#define WM8915_DSP1_RX_EQ_BAND_4_A              0x48D
-#define WM8915_DSP1_RX_EQ_BAND_4_B              0x48E
-#define WM8915_DSP1_RX_EQ_BAND_4_C              0x48F
-#define WM8915_DSP1_RX_EQ_BAND_4_PG             0x490
-#define WM8915_DSP1_RX_EQ_BAND_5_A              0x491
-#define WM8915_DSP1_RX_EQ_BAND_5_B              0x492
-#define WM8915_DSP1_RX_EQ_BAND_5_PG             0x493
-#define WM8915_DSP2_TX_LEFT_VOLUME              0x500
-#define WM8915_DSP2_TX_RIGHT_VOLUME             0x501
-#define WM8915_DSP2_RX_LEFT_VOLUME              0x502
-#define WM8915_DSP2_RX_RIGHT_VOLUME             0x503
-#define WM8915_DSP2_TX_FILTERS                  0x510
-#define WM8915_DSP2_RX_FILTERS_1                0x520
-#define WM8915_DSP2_RX_FILTERS_2                0x521
-#define WM8915_DSP2_DRC_1                       0x540
-#define WM8915_DSP2_DRC_2                       0x541
-#define WM8915_DSP2_DRC_3                       0x542
-#define WM8915_DSP2_DRC_4                       0x543
-#define WM8915_DSP2_DRC_5                       0x544
-#define WM8915_DSP2_RX_EQ_GAINS_1               0x580
-#define WM8915_DSP2_RX_EQ_GAINS_2               0x581
-#define WM8915_DSP2_RX_EQ_BAND_1_A              0x582
-#define WM8915_DSP2_RX_EQ_BAND_1_B              0x583
-#define WM8915_DSP2_RX_EQ_BAND_1_PG             0x584
-#define WM8915_DSP2_RX_EQ_BAND_2_A              0x585
-#define WM8915_DSP2_RX_EQ_BAND_2_B              0x586
-#define WM8915_DSP2_RX_EQ_BAND_2_C              0x587
-#define WM8915_DSP2_RX_EQ_BAND_2_PG             0x588
-#define WM8915_DSP2_RX_EQ_BAND_3_A              0x589
-#define WM8915_DSP2_RX_EQ_BAND_3_B              0x58A
-#define WM8915_DSP2_RX_EQ_BAND_3_C              0x58B
-#define WM8915_DSP2_RX_EQ_BAND_3_PG             0x58C
-#define WM8915_DSP2_RX_EQ_BAND_4_A              0x58D
-#define WM8915_DSP2_RX_EQ_BAND_4_B              0x58E
-#define WM8915_DSP2_RX_EQ_BAND_4_C              0x58F
-#define WM8915_DSP2_RX_EQ_BAND_4_PG             0x590
-#define WM8915_DSP2_RX_EQ_BAND_5_A              0x591
-#define WM8915_DSP2_RX_EQ_BAND_5_B              0x592
-#define WM8915_DSP2_RX_EQ_BAND_5_PG             0x593
-#define WM8915_DAC1_MIXER_VOLUMES               0x600
-#define WM8915_DAC1_LEFT_MIXER_ROUTING          0x601
-#define WM8915_DAC1_RIGHT_MIXER_ROUTING         0x602
-#define WM8915_DAC2_MIXER_VOLUMES               0x603
-#define WM8915_DAC2_LEFT_MIXER_ROUTING          0x604
-#define WM8915_DAC2_RIGHT_MIXER_ROUTING         0x605
-#define WM8915_DSP1_TX_LEFT_MIXER_ROUTING       0x606
-#define WM8915_DSP1_TX_RIGHT_MIXER_ROUTING      0x607
-#define WM8915_DSP2_TX_LEFT_MIXER_ROUTING       0x608
-#define WM8915_DSP2_TX_RIGHT_MIXER_ROUTING      0x609
-#define WM8915_DSP_TX_MIXER_SELECT              0x60A
-#define WM8915_DAC_SOFTMUTE                     0x610
-#define WM8915_OVERSAMPLING                     0x620
-#define WM8915_SIDETONE                         0x621
-#define WM8915_GPIO_1                           0x700
-#define WM8915_GPIO_2                           0x701
-#define WM8915_GPIO_3                           0x702
-#define WM8915_GPIO_4                           0x703
-#define WM8915_GPIO_5                           0x704
-#define WM8915_PULL_CONTROL_1                   0x720
-#define WM8915_PULL_CONTROL_2                   0x721
-#define WM8915_INTERRUPT_STATUS_1               0x730
-#define WM8915_INTERRUPT_STATUS_2               0x731
-#define WM8915_INTERRUPT_RAW_STATUS_2           0x732
-#define WM8915_INTERRUPT_STATUS_1_MASK          0x738
-#define WM8915_INTERRUPT_STATUS_2_MASK          0x739
-#define WM8915_INTERRUPT_CONTROL                0x740
-#define WM8915_LEFT_PDM_SPEAKER                 0x800
-#define WM8915_RIGHT_PDM_SPEAKER                0x801
-#define WM8915_PDM_SPEAKER_MUTE_SEQUENCE        0x802
-#define WM8915_PDM_SPEAKER_VOLUME               0x803
-#define WM8915_WRITE_SEQUENCER_0                0x3000
-#define WM8915_WRITE_SEQUENCER_1                0x3001
-#define WM8915_WRITE_SEQUENCER_2                0x3002
-#define WM8915_WRITE_SEQUENCER_3                0x3003
-#define WM8915_WRITE_SEQUENCER_4                0x3004
-#define WM8915_WRITE_SEQUENCER_5                0x3005
-#define WM8915_WRITE_SEQUENCER_6                0x3006
-#define WM8915_WRITE_SEQUENCER_7                0x3007
-#define WM8915_WRITE_SEQUENCER_8                0x3008
-#define WM8915_WRITE_SEQUENCER_9                0x3009
-#define WM8915_WRITE_SEQUENCER_10               0x300A
-#define WM8915_WRITE_SEQUENCER_11               0x300B
-#define WM8915_WRITE_SEQUENCER_12               0x300C
-#define WM8915_WRITE_SEQUENCER_13               0x300D
-#define WM8915_WRITE_SEQUENCER_14               0x300E
-#define WM8915_WRITE_SEQUENCER_15               0x300F
-#define WM8915_WRITE_SEQUENCER_16               0x3010
-#define WM8915_WRITE_SEQUENCER_17               0x3011
-#define WM8915_WRITE_SEQUENCER_18               0x3012
-#define WM8915_WRITE_SEQUENCER_19               0x3013
-#define WM8915_WRITE_SEQUENCER_20               0x3014
-#define WM8915_WRITE_SEQUENCER_21               0x3015
-#define WM8915_WRITE_SEQUENCER_22               0x3016
-#define WM8915_WRITE_SEQUENCER_23               0x3017
-#define WM8915_WRITE_SEQUENCER_24               0x3018
-#define WM8915_WRITE_SEQUENCER_25               0x3019
-#define WM8915_WRITE_SEQUENCER_26               0x301A
-#define WM8915_WRITE_SEQUENCER_27               0x301B
-#define WM8915_WRITE_SEQUENCER_28               0x301C
-#define WM8915_WRITE_SEQUENCER_29               0x301D
-#define WM8915_WRITE_SEQUENCER_30               0x301E
-#define WM8915_WRITE_SEQUENCER_31               0x301F
-#define WM8915_WRITE_SEQUENCER_32               0x3020
-#define WM8915_WRITE_SEQUENCER_33               0x3021
-#define WM8915_WRITE_SEQUENCER_34               0x3022
-#define WM8915_WRITE_SEQUENCER_35               0x3023
-#define WM8915_WRITE_SEQUENCER_36               0x3024
-#define WM8915_WRITE_SEQUENCER_37               0x3025
-#define WM8915_WRITE_SEQUENCER_38               0x3026
-#define WM8915_WRITE_SEQUENCER_39               0x3027
-#define WM8915_WRITE_SEQUENCER_40               0x3028
-#define WM8915_WRITE_SEQUENCER_41               0x3029
-#define WM8915_WRITE_SEQUENCER_42               0x302A
-#define WM8915_WRITE_SEQUENCER_43               0x302B
-#define WM8915_WRITE_SEQUENCER_44               0x302C
-#define WM8915_WRITE_SEQUENCER_45               0x302D
-#define WM8915_WRITE_SEQUENCER_46               0x302E
-#define WM8915_WRITE_SEQUENCER_47               0x302F
-#define WM8915_WRITE_SEQUENCER_48               0x3030
-#define WM8915_WRITE_SEQUENCER_49               0x3031
-#define WM8915_WRITE_SEQUENCER_50               0x3032
-#define WM8915_WRITE_SEQUENCER_51               0x3033
-#define WM8915_WRITE_SEQUENCER_52               0x3034
-#define WM8915_WRITE_SEQUENCER_53               0x3035
-#define WM8915_WRITE_SEQUENCER_54               0x3036
-#define WM8915_WRITE_SEQUENCER_55               0x3037
-#define WM8915_WRITE_SEQUENCER_56               0x3038
-#define WM8915_WRITE_SEQUENCER_57               0x3039
-#define WM8915_WRITE_SEQUENCER_58               0x303A
-#define WM8915_WRITE_SEQUENCER_59               0x303B
-#define WM8915_WRITE_SEQUENCER_60               0x303C
-#define WM8915_WRITE_SEQUENCER_61               0x303D
-#define WM8915_WRITE_SEQUENCER_62               0x303E
-#define WM8915_WRITE_SEQUENCER_63               0x303F
-#define WM8915_WRITE_SEQUENCER_64               0x3040
-#define WM8915_WRITE_SEQUENCER_65               0x3041
-#define WM8915_WRITE_SEQUENCER_66               0x3042
-#define WM8915_WRITE_SEQUENCER_67               0x3043
-#define WM8915_WRITE_SEQUENCER_68               0x3044
-#define WM8915_WRITE_SEQUENCER_69               0x3045
-#define WM8915_WRITE_SEQUENCER_70               0x3046
-#define WM8915_WRITE_SEQUENCER_71               0x3047
-#define WM8915_WRITE_SEQUENCER_72               0x3048
-#define WM8915_WRITE_SEQUENCER_73               0x3049
-#define WM8915_WRITE_SEQUENCER_74               0x304A
-#define WM8915_WRITE_SEQUENCER_75               0x304B
-#define WM8915_WRITE_SEQUENCER_76               0x304C
-#define WM8915_WRITE_SEQUENCER_77               0x304D
-#define WM8915_WRITE_SEQUENCER_78               0x304E
-#define WM8915_WRITE_SEQUENCER_79               0x304F
-#define WM8915_WRITE_SEQUENCER_80               0x3050
-#define WM8915_WRITE_SEQUENCER_81               0x3051
-#define WM8915_WRITE_SEQUENCER_82               0x3052
-#define WM8915_WRITE_SEQUENCER_83               0x3053
-#define WM8915_WRITE_SEQUENCER_84               0x3054
-#define WM8915_WRITE_SEQUENCER_85               0x3055
-#define WM8915_WRITE_SEQUENCER_86               0x3056
-#define WM8915_WRITE_SEQUENCER_87               0x3057
-#define WM8915_WRITE_SEQUENCER_88               0x3058
-#define WM8915_WRITE_SEQUENCER_89               0x3059
-#define WM8915_WRITE_SEQUENCER_90               0x305A
-#define WM8915_WRITE_SEQUENCER_91               0x305B
-#define WM8915_WRITE_SEQUENCER_92               0x305C
-#define WM8915_WRITE_SEQUENCER_93               0x305D
-#define WM8915_WRITE_SEQUENCER_94               0x305E
-#define WM8915_WRITE_SEQUENCER_95               0x305F
-#define WM8915_WRITE_SEQUENCER_96               0x3060
-#define WM8915_WRITE_SEQUENCER_97               0x3061
-#define WM8915_WRITE_SEQUENCER_98               0x3062
-#define WM8915_WRITE_SEQUENCER_99               0x3063
-#define WM8915_WRITE_SEQUENCER_100              0x3064
-#define WM8915_WRITE_SEQUENCER_101              0x3065
-#define WM8915_WRITE_SEQUENCER_102              0x3066
-#define WM8915_WRITE_SEQUENCER_103              0x3067
-#define WM8915_WRITE_SEQUENCER_104              0x3068
-#define WM8915_WRITE_SEQUENCER_105              0x3069
-#define WM8915_WRITE_SEQUENCER_106              0x306A
-#define WM8915_WRITE_SEQUENCER_107              0x306B
-#define WM8915_WRITE_SEQUENCER_108              0x306C
-#define WM8915_WRITE_SEQUENCER_109              0x306D
-#define WM8915_WRITE_SEQUENCER_110              0x306E
-#define WM8915_WRITE_SEQUENCER_111              0x306F
-#define WM8915_WRITE_SEQUENCER_112              0x3070
-#define WM8915_WRITE_SEQUENCER_113              0x3071
-#define WM8915_WRITE_SEQUENCER_114              0x3072
-#define WM8915_WRITE_SEQUENCER_115              0x3073
-#define WM8915_WRITE_SEQUENCER_116              0x3074
-#define WM8915_WRITE_SEQUENCER_117              0x3075
-#define WM8915_WRITE_SEQUENCER_118              0x3076
-#define WM8915_WRITE_SEQUENCER_119              0x3077
-#define WM8915_WRITE_SEQUENCER_120              0x3078
-#define WM8915_WRITE_SEQUENCER_121              0x3079
-#define WM8915_WRITE_SEQUENCER_122              0x307A
-#define WM8915_WRITE_SEQUENCER_123              0x307B
-#define WM8915_WRITE_SEQUENCER_124              0x307C
-#define WM8915_WRITE_SEQUENCER_125              0x307D
-#define WM8915_WRITE_SEQUENCER_126              0x307E
-#define WM8915_WRITE_SEQUENCER_127              0x307F
-#define WM8915_WRITE_SEQUENCER_128              0x3080
-#define WM8915_WRITE_SEQUENCER_129              0x3081
-#define WM8915_WRITE_SEQUENCER_130              0x3082
-#define WM8915_WRITE_SEQUENCER_131              0x3083
-#define WM8915_WRITE_SEQUENCER_132              0x3084
-#define WM8915_WRITE_SEQUENCER_133              0x3085
-#define WM8915_WRITE_SEQUENCER_134              0x3086
-#define WM8915_WRITE_SEQUENCER_135              0x3087
-#define WM8915_WRITE_SEQUENCER_136              0x3088
-#define WM8915_WRITE_SEQUENCER_137              0x3089
-#define WM8915_WRITE_SEQUENCER_138              0x308A
-#define WM8915_WRITE_SEQUENCER_139              0x308B
-#define WM8915_WRITE_SEQUENCER_140              0x308C
-#define WM8915_WRITE_SEQUENCER_141              0x308D
-#define WM8915_WRITE_SEQUENCER_142              0x308E
-#define WM8915_WRITE_SEQUENCER_143              0x308F
-#define WM8915_WRITE_SEQUENCER_144              0x3090
-#define WM8915_WRITE_SEQUENCER_145              0x3091
-#define WM8915_WRITE_SEQUENCER_146              0x3092
-#define WM8915_WRITE_SEQUENCER_147              0x3093
-#define WM8915_WRITE_SEQUENCER_148              0x3094
-#define WM8915_WRITE_SEQUENCER_149              0x3095
-#define WM8915_WRITE_SEQUENCER_150              0x3096
-#define WM8915_WRITE_SEQUENCER_151              0x3097
-#define WM8915_WRITE_SEQUENCER_152              0x3098
-#define WM8915_WRITE_SEQUENCER_153              0x3099
-#define WM8915_WRITE_SEQUENCER_154              0x309A
-#define WM8915_WRITE_SEQUENCER_155              0x309B
-#define WM8915_WRITE_SEQUENCER_156              0x309C
-#define WM8915_WRITE_SEQUENCER_157              0x309D
-#define WM8915_WRITE_SEQUENCER_158              0x309E
-#define WM8915_WRITE_SEQUENCER_159              0x309F
-#define WM8915_WRITE_SEQUENCER_160              0x30A0
-#define WM8915_WRITE_SEQUENCER_161              0x30A1
-#define WM8915_WRITE_SEQUENCER_162              0x30A2
-#define WM8915_WRITE_SEQUENCER_163              0x30A3
-#define WM8915_WRITE_SEQUENCER_164              0x30A4
-#define WM8915_WRITE_SEQUENCER_165              0x30A5
-#define WM8915_WRITE_SEQUENCER_166              0x30A6
-#define WM8915_WRITE_SEQUENCER_167              0x30A7
-#define WM8915_WRITE_SEQUENCER_168              0x30A8
-#define WM8915_WRITE_SEQUENCER_169              0x30A9
-#define WM8915_WRITE_SEQUENCER_170              0x30AA
-#define WM8915_WRITE_SEQUENCER_171              0x30AB
-#define WM8915_WRITE_SEQUENCER_172              0x30AC
-#define WM8915_WRITE_SEQUENCER_173              0x30AD
-#define WM8915_WRITE_SEQUENCER_174              0x30AE
-#define WM8915_WRITE_SEQUENCER_175              0x30AF
-#define WM8915_WRITE_SEQUENCER_176              0x30B0
-#define WM8915_WRITE_SEQUENCER_177              0x30B1
-#define WM8915_WRITE_SEQUENCER_178              0x30B2
-#define WM8915_WRITE_SEQUENCER_179              0x30B3
-#define WM8915_WRITE_SEQUENCER_180              0x30B4
-#define WM8915_WRITE_SEQUENCER_181              0x30B5
-#define WM8915_WRITE_SEQUENCER_182              0x30B6
-#define WM8915_WRITE_SEQUENCER_183              0x30B7
-#define WM8915_WRITE_SEQUENCER_184              0x30B8
-#define WM8915_WRITE_SEQUENCER_185              0x30B9
-#define WM8915_WRITE_SEQUENCER_186              0x30BA
-#define WM8915_WRITE_SEQUENCER_187              0x30BB
-#define WM8915_WRITE_SEQUENCER_188              0x30BC
-#define WM8915_WRITE_SEQUENCER_189              0x30BD
-#define WM8915_WRITE_SEQUENCER_190              0x30BE
-#define WM8915_WRITE_SEQUENCER_191              0x30BF
-#define WM8915_WRITE_SEQUENCER_192              0x30C0
-#define WM8915_WRITE_SEQUENCER_193              0x30C1
-#define WM8915_WRITE_SEQUENCER_194              0x30C2
-#define WM8915_WRITE_SEQUENCER_195              0x30C3
-#define WM8915_WRITE_SEQUENCER_196              0x30C4
-#define WM8915_WRITE_SEQUENCER_197              0x30C5
-#define WM8915_WRITE_SEQUENCER_198              0x30C6
-#define WM8915_WRITE_SEQUENCER_199              0x30C7
-#define WM8915_WRITE_SEQUENCER_200              0x30C8
-#define WM8915_WRITE_SEQUENCER_201              0x30C9
-#define WM8915_WRITE_SEQUENCER_202              0x30CA
-#define WM8915_WRITE_SEQUENCER_203              0x30CB
-#define WM8915_WRITE_SEQUENCER_204              0x30CC
-#define WM8915_WRITE_SEQUENCER_205              0x30CD
-#define WM8915_WRITE_SEQUENCER_206              0x30CE
-#define WM8915_WRITE_SEQUENCER_207              0x30CF
-#define WM8915_WRITE_SEQUENCER_208              0x30D0
-#define WM8915_WRITE_SEQUENCER_209              0x30D1
-#define WM8915_WRITE_SEQUENCER_210              0x30D2
-#define WM8915_WRITE_SEQUENCER_211              0x30D3
-#define WM8915_WRITE_SEQUENCER_212              0x30D4
-#define WM8915_WRITE_SEQUENCER_213              0x30D5
-#define WM8915_WRITE_SEQUENCER_214              0x30D6
-#define WM8915_WRITE_SEQUENCER_215              0x30D7
-#define WM8915_WRITE_SEQUENCER_216              0x30D8
-#define WM8915_WRITE_SEQUENCER_217              0x30D9
-#define WM8915_WRITE_SEQUENCER_218              0x30DA
-#define WM8915_WRITE_SEQUENCER_219              0x30DB
-#define WM8915_WRITE_SEQUENCER_220              0x30DC
-#define WM8915_WRITE_SEQUENCER_221              0x30DD
-#define WM8915_WRITE_SEQUENCER_222              0x30DE
-#define WM8915_WRITE_SEQUENCER_223              0x30DF
-#define WM8915_WRITE_SEQUENCER_224              0x30E0
-#define WM8915_WRITE_SEQUENCER_225              0x30E1
-#define WM8915_WRITE_SEQUENCER_226              0x30E2
-#define WM8915_WRITE_SEQUENCER_227              0x30E3
-#define WM8915_WRITE_SEQUENCER_228              0x30E4
-#define WM8915_WRITE_SEQUENCER_229              0x30E5
-#define WM8915_WRITE_SEQUENCER_230              0x30E6
-#define WM8915_WRITE_SEQUENCER_231              0x30E7
-#define WM8915_WRITE_SEQUENCER_232              0x30E8
-#define WM8915_WRITE_SEQUENCER_233              0x30E9
-#define WM8915_WRITE_SEQUENCER_234              0x30EA
-#define WM8915_WRITE_SEQUENCER_235              0x30EB
-#define WM8915_WRITE_SEQUENCER_236              0x30EC
-#define WM8915_WRITE_SEQUENCER_237              0x30ED
-#define WM8915_WRITE_SEQUENCER_238              0x30EE
-#define WM8915_WRITE_SEQUENCER_239              0x30EF
-#define WM8915_WRITE_SEQUENCER_240              0x30F0
-#define WM8915_WRITE_SEQUENCER_241              0x30F1
-#define WM8915_WRITE_SEQUENCER_242              0x30F2
-#define WM8915_WRITE_SEQUENCER_243              0x30F3
-#define WM8915_WRITE_SEQUENCER_244              0x30F4
-#define WM8915_WRITE_SEQUENCER_245              0x30F5
-#define WM8915_WRITE_SEQUENCER_246              0x30F6
-#define WM8915_WRITE_SEQUENCER_247              0x30F7
-#define WM8915_WRITE_SEQUENCER_248              0x30F8
-#define WM8915_WRITE_SEQUENCER_249              0x30F9
-#define WM8915_WRITE_SEQUENCER_250              0x30FA
-#define WM8915_WRITE_SEQUENCER_251              0x30FB
-#define WM8915_WRITE_SEQUENCER_252              0x30FC
-#define WM8915_WRITE_SEQUENCER_253              0x30FD
-#define WM8915_WRITE_SEQUENCER_254              0x30FE
-#define WM8915_WRITE_SEQUENCER_255              0x30FF
-#define WM8915_WRITE_SEQUENCER_256              0x3100
-#define WM8915_WRITE_SEQUENCER_257              0x3101
-#define WM8915_WRITE_SEQUENCER_258              0x3102
-#define WM8915_WRITE_SEQUENCER_259              0x3103
-#define WM8915_WRITE_SEQUENCER_260              0x3104
-#define WM8915_WRITE_SEQUENCER_261              0x3105
-#define WM8915_WRITE_SEQUENCER_262              0x3106
-#define WM8915_WRITE_SEQUENCER_263              0x3107
-#define WM8915_WRITE_SEQUENCER_264              0x3108
-#define WM8915_WRITE_SEQUENCER_265              0x3109
-#define WM8915_WRITE_SEQUENCER_266              0x310A
-#define WM8915_WRITE_SEQUENCER_267              0x310B
-#define WM8915_WRITE_SEQUENCER_268              0x310C
-#define WM8915_WRITE_SEQUENCER_269              0x310D
-#define WM8915_WRITE_SEQUENCER_270              0x310E
-#define WM8915_WRITE_SEQUENCER_271              0x310F
-#define WM8915_WRITE_SEQUENCER_272              0x3110
-#define WM8915_WRITE_SEQUENCER_273              0x3111
-#define WM8915_WRITE_SEQUENCER_274              0x3112
-#define WM8915_WRITE_SEQUENCER_275              0x3113
-#define WM8915_WRITE_SEQUENCER_276              0x3114
-#define WM8915_WRITE_SEQUENCER_277              0x3115
-#define WM8915_WRITE_SEQUENCER_278              0x3116
-#define WM8915_WRITE_SEQUENCER_279              0x3117
-#define WM8915_WRITE_SEQUENCER_280              0x3118
-#define WM8915_WRITE_SEQUENCER_281              0x3119
-#define WM8915_WRITE_SEQUENCER_282              0x311A
-#define WM8915_WRITE_SEQUENCER_283              0x311B
-#define WM8915_WRITE_SEQUENCER_284              0x311C
-#define WM8915_WRITE_SEQUENCER_285              0x311D
-#define WM8915_WRITE_SEQUENCER_286              0x311E
-#define WM8915_WRITE_SEQUENCER_287              0x311F
-#define WM8915_WRITE_SEQUENCER_288              0x3120
-#define WM8915_WRITE_SEQUENCER_289              0x3121
-#define WM8915_WRITE_SEQUENCER_290              0x3122
-#define WM8915_WRITE_SEQUENCER_291              0x3123
-#define WM8915_WRITE_SEQUENCER_292              0x3124
-#define WM8915_WRITE_SEQUENCER_293              0x3125
-#define WM8915_WRITE_SEQUENCER_294              0x3126
-#define WM8915_WRITE_SEQUENCER_295              0x3127
-#define WM8915_WRITE_SEQUENCER_296              0x3128
-#define WM8915_WRITE_SEQUENCER_297              0x3129
-#define WM8915_WRITE_SEQUENCER_298              0x312A
-#define WM8915_WRITE_SEQUENCER_299              0x312B
-#define WM8915_WRITE_SEQUENCER_300              0x312C
-#define WM8915_WRITE_SEQUENCER_301              0x312D
-#define WM8915_WRITE_SEQUENCER_302              0x312E
-#define WM8915_WRITE_SEQUENCER_303              0x312F
-#define WM8915_WRITE_SEQUENCER_304              0x3130
-#define WM8915_WRITE_SEQUENCER_305              0x3131
-#define WM8915_WRITE_SEQUENCER_306              0x3132
-#define WM8915_WRITE_SEQUENCER_307              0x3133
-#define WM8915_WRITE_SEQUENCER_308              0x3134
-#define WM8915_WRITE_SEQUENCER_309              0x3135
-#define WM8915_WRITE_SEQUENCER_310              0x3136
-#define WM8915_WRITE_SEQUENCER_311              0x3137
-#define WM8915_WRITE_SEQUENCER_312              0x3138
-#define WM8915_WRITE_SEQUENCER_313              0x3139
-#define WM8915_WRITE_SEQUENCER_314              0x313A
-#define WM8915_WRITE_SEQUENCER_315              0x313B
-#define WM8915_WRITE_SEQUENCER_316              0x313C
-#define WM8915_WRITE_SEQUENCER_317              0x313D
-#define WM8915_WRITE_SEQUENCER_318              0x313E
-#define WM8915_WRITE_SEQUENCER_319              0x313F
-#define WM8915_WRITE_SEQUENCER_320              0x3140
-#define WM8915_WRITE_SEQUENCER_321              0x3141
-#define WM8915_WRITE_SEQUENCER_322              0x3142
-#define WM8915_WRITE_SEQUENCER_323              0x3143
-#define WM8915_WRITE_SEQUENCER_324              0x3144
-#define WM8915_WRITE_SEQUENCER_325              0x3145
-#define WM8915_WRITE_SEQUENCER_326              0x3146
-#define WM8915_WRITE_SEQUENCER_327              0x3147
-#define WM8915_WRITE_SEQUENCER_328              0x3148
-#define WM8915_WRITE_SEQUENCER_329              0x3149
-#define WM8915_WRITE_SEQUENCER_330              0x314A
-#define WM8915_WRITE_SEQUENCER_331              0x314B
-#define WM8915_WRITE_SEQUENCER_332              0x314C
-#define WM8915_WRITE_SEQUENCER_333              0x314D
-#define WM8915_WRITE_SEQUENCER_334              0x314E
-#define WM8915_WRITE_SEQUENCER_335              0x314F
-#define WM8915_WRITE_SEQUENCER_336              0x3150
-#define WM8915_WRITE_SEQUENCER_337              0x3151
-#define WM8915_WRITE_SEQUENCER_338              0x3152
-#define WM8915_WRITE_SEQUENCER_339              0x3153
-#define WM8915_WRITE_SEQUENCER_340              0x3154
-#define WM8915_WRITE_SEQUENCER_341              0x3155
-#define WM8915_WRITE_SEQUENCER_342              0x3156
-#define WM8915_WRITE_SEQUENCER_343              0x3157
-#define WM8915_WRITE_SEQUENCER_344              0x3158
-#define WM8915_WRITE_SEQUENCER_345              0x3159
-#define WM8915_WRITE_SEQUENCER_346              0x315A
-#define WM8915_WRITE_SEQUENCER_347              0x315B
-#define WM8915_WRITE_SEQUENCER_348              0x315C
-#define WM8915_WRITE_SEQUENCER_349              0x315D
-#define WM8915_WRITE_SEQUENCER_350              0x315E
-#define WM8915_WRITE_SEQUENCER_351              0x315F
-#define WM8915_WRITE_SEQUENCER_352              0x3160
-#define WM8915_WRITE_SEQUENCER_353              0x3161
-#define WM8915_WRITE_SEQUENCER_354              0x3162
-#define WM8915_WRITE_SEQUENCER_355              0x3163
-#define WM8915_WRITE_SEQUENCER_356              0x3164
-#define WM8915_WRITE_SEQUENCER_357              0x3165
-#define WM8915_WRITE_SEQUENCER_358              0x3166
-#define WM8915_WRITE_SEQUENCER_359              0x3167
-#define WM8915_WRITE_SEQUENCER_360              0x3168
-#define WM8915_WRITE_SEQUENCER_361              0x3169
-#define WM8915_WRITE_SEQUENCER_362              0x316A
-#define WM8915_WRITE_SEQUENCER_363              0x316B
-#define WM8915_WRITE_SEQUENCER_364              0x316C
-#define WM8915_WRITE_SEQUENCER_365              0x316D
-#define WM8915_WRITE_SEQUENCER_366              0x316E
-#define WM8915_WRITE_SEQUENCER_367              0x316F
-#define WM8915_WRITE_SEQUENCER_368              0x3170
-#define WM8915_WRITE_SEQUENCER_369              0x3171
-#define WM8915_WRITE_SEQUENCER_370              0x3172
-#define WM8915_WRITE_SEQUENCER_371              0x3173
-#define WM8915_WRITE_SEQUENCER_372              0x3174
-#define WM8915_WRITE_SEQUENCER_373              0x3175
-#define WM8915_WRITE_SEQUENCER_374              0x3176
-#define WM8915_WRITE_SEQUENCER_375              0x3177
-#define WM8915_WRITE_SEQUENCER_376              0x3178
-#define WM8915_WRITE_SEQUENCER_377              0x3179
-#define WM8915_WRITE_SEQUENCER_378              0x317A
-#define WM8915_WRITE_SEQUENCER_379              0x317B
-#define WM8915_WRITE_SEQUENCER_380              0x317C
-#define WM8915_WRITE_SEQUENCER_381              0x317D
-#define WM8915_WRITE_SEQUENCER_382              0x317E
-#define WM8915_WRITE_SEQUENCER_383              0x317F
-#define WM8915_WRITE_SEQUENCER_384              0x3180
-#define WM8915_WRITE_SEQUENCER_385              0x3181
-#define WM8915_WRITE_SEQUENCER_386              0x3182
-#define WM8915_WRITE_SEQUENCER_387              0x3183
-#define WM8915_WRITE_SEQUENCER_388              0x3184
-#define WM8915_WRITE_SEQUENCER_389              0x3185
-#define WM8915_WRITE_SEQUENCER_390              0x3186
-#define WM8915_WRITE_SEQUENCER_391              0x3187
-#define WM8915_WRITE_SEQUENCER_392              0x3188
-#define WM8915_WRITE_SEQUENCER_393              0x3189
-#define WM8915_WRITE_SEQUENCER_394              0x318A
-#define WM8915_WRITE_SEQUENCER_395              0x318B
-#define WM8915_WRITE_SEQUENCER_396              0x318C
-#define WM8915_WRITE_SEQUENCER_397              0x318D
-#define WM8915_WRITE_SEQUENCER_398              0x318E
-#define WM8915_WRITE_SEQUENCER_399              0x318F
-#define WM8915_WRITE_SEQUENCER_400              0x3190
-#define WM8915_WRITE_SEQUENCER_401              0x3191
-#define WM8915_WRITE_SEQUENCER_402              0x3192
-#define WM8915_WRITE_SEQUENCER_403              0x3193
-#define WM8915_WRITE_SEQUENCER_404              0x3194
-#define WM8915_WRITE_SEQUENCER_405              0x3195
-#define WM8915_WRITE_SEQUENCER_406              0x3196
-#define WM8915_WRITE_SEQUENCER_407              0x3197
-#define WM8915_WRITE_SEQUENCER_408              0x3198
-#define WM8915_WRITE_SEQUENCER_409              0x3199
-#define WM8915_WRITE_SEQUENCER_410              0x319A
-#define WM8915_WRITE_SEQUENCER_411              0x319B
-#define WM8915_WRITE_SEQUENCER_412              0x319C
-#define WM8915_WRITE_SEQUENCER_413              0x319D
-#define WM8915_WRITE_SEQUENCER_414              0x319E
-#define WM8915_WRITE_SEQUENCER_415              0x319F
-#define WM8915_WRITE_SEQUENCER_416              0x31A0
-#define WM8915_WRITE_SEQUENCER_417              0x31A1
-#define WM8915_WRITE_SEQUENCER_418              0x31A2
-#define WM8915_WRITE_SEQUENCER_419              0x31A3
-#define WM8915_WRITE_SEQUENCER_420              0x31A4
-#define WM8915_WRITE_SEQUENCER_421              0x31A5
-#define WM8915_WRITE_SEQUENCER_422              0x31A6
-#define WM8915_WRITE_SEQUENCER_423              0x31A7
-#define WM8915_WRITE_SEQUENCER_424              0x31A8
-#define WM8915_WRITE_SEQUENCER_425              0x31A9
-#define WM8915_WRITE_SEQUENCER_426              0x31AA
-#define WM8915_WRITE_SEQUENCER_427              0x31AB
-#define WM8915_WRITE_SEQUENCER_428              0x31AC
-#define WM8915_WRITE_SEQUENCER_429              0x31AD
-#define WM8915_WRITE_SEQUENCER_430              0x31AE
-#define WM8915_WRITE_SEQUENCER_431              0x31AF
-#define WM8915_WRITE_SEQUENCER_432              0x31B0
-#define WM8915_WRITE_SEQUENCER_433              0x31B1
-#define WM8915_WRITE_SEQUENCER_434              0x31B2
-#define WM8915_WRITE_SEQUENCER_435              0x31B3
-#define WM8915_WRITE_SEQUENCER_436              0x31B4
-#define WM8915_WRITE_SEQUENCER_437              0x31B5
-#define WM8915_WRITE_SEQUENCER_438              0x31B6
-#define WM8915_WRITE_SEQUENCER_439              0x31B7
-#define WM8915_WRITE_SEQUENCER_440              0x31B8
-#define WM8915_WRITE_SEQUENCER_441              0x31B9
-#define WM8915_WRITE_SEQUENCER_442              0x31BA
-#define WM8915_WRITE_SEQUENCER_443              0x31BB
-#define WM8915_WRITE_SEQUENCER_444              0x31BC
-#define WM8915_WRITE_SEQUENCER_445              0x31BD
-#define WM8915_WRITE_SEQUENCER_446              0x31BE
-#define WM8915_WRITE_SEQUENCER_447              0x31BF
-#define WM8915_WRITE_SEQUENCER_448              0x31C0
-#define WM8915_WRITE_SEQUENCER_449              0x31C1
-#define WM8915_WRITE_SEQUENCER_450              0x31C2
-#define WM8915_WRITE_SEQUENCER_451              0x31C3
-#define WM8915_WRITE_SEQUENCER_452              0x31C4
-#define WM8915_WRITE_SEQUENCER_453              0x31C5
-#define WM8915_WRITE_SEQUENCER_454              0x31C6
-#define WM8915_WRITE_SEQUENCER_455              0x31C7
-#define WM8915_WRITE_SEQUENCER_456              0x31C8
-#define WM8915_WRITE_SEQUENCER_457              0x31C9
-#define WM8915_WRITE_SEQUENCER_458              0x31CA
-#define WM8915_WRITE_SEQUENCER_459              0x31CB
-#define WM8915_WRITE_SEQUENCER_460              0x31CC
-#define WM8915_WRITE_SEQUENCER_461              0x31CD
-#define WM8915_WRITE_SEQUENCER_462              0x31CE
-#define WM8915_WRITE_SEQUENCER_463              0x31CF
-#define WM8915_WRITE_SEQUENCER_464              0x31D0
-#define WM8915_WRITE_SEQUENCER_465              0x31D1
-#define WM8915_WRITE_SEQUENCER_466              0x31D2
-#define WM8915_WRITE_SEQUENCER_467              0x31D3
-#define WM8915_WRITE_SEQUENCER_468              0x31D4
-#define WM8915_WRITE_SEQUENCER_469              0x31D5
-#define WM8915_WRITE_SEQUENCER_470              0x31D6
-#define WM8915_WRITE_SEQUENCER_471              0x31D7
-#define WM8915_WRITE_SEQUENCER_472              0x31D8
-#define WM8915_WRITE_SEQUENCER_473              0x31D9
-#define WM8915_WRITE_SEQUENCER_474              0x31DA
-#define WM8915_WRITE_SEQUENCER_475              0x31DB
-#define WM8915_WRITE_SEQUENCER_476              0x31DC
-#define WM8915_WRITE_SEQUENCER_477              0x31DD
-#define WM8915_WRITE_SEQUENCER_478              0x31DE
-#define WM8915_WRITE_SEQUENCER_479              0x31DF
-#define WM8915_WRITE_SEQUENCER_480              0x31E0
-#define WM8915_WRITE_SEQUENCER_481              0x31E1
-#define WM8915_WRITE_SEQUENCER_482              0x31E2
-#define WM8915_WRITE_SEQUENCER_483              0x31E3
-#define WM8915_WRITE_SEQUENCER_484              0x31E4
-#define WM8915_WRITE_SEQUENCER_485              0x31E5
-#define WM8915_WRITE_SEQUENCER_486              0x31E6
-#define WM8915_WRITE_SEQUENCER_487              0x31E7
-#define WM8915_WRITE_SEQUENCER_488              0x31E8
-#define WM8915_WRITE_SEQUENCER_489              0x31E9
-#define WM8915_WRITE_SEQUENCER_490              0x31EA
-#define WM8915_WRITE_SEQUENCER_491              0x31EB
-#define WM8915_WRITE_SEQUENCER_492              0x31EC
-#define WM8915_WRITE_SEQUENCER_493              0x31ED
-#define WM8915_WRITE_SEQUENCER_494              0x31EE
-#define WM8915_WRITE_SEQUENCER_495              0x31EF
-#define WM8915_WRITE_SEQUENCER_496              0x31F0
-#define WM8915_WRITE_SEQUENCER_497              0x31F1
-#define WM8915_WRITE_SEQUENCER_498              0x31F2
-#define WM8915_WRITE_SEQUENCER_499              0x31F3
-#define WM8915_WRITE_SEQUENCER_500              0x31F4
-#define WM8915_WRITE_SEQUENCER_501              0x31F5
-#define WM8915_WRITE_SEQUENCER_502              0x31F6
-#define WM8915_WRITE_SEQUENCER_503              0x31F7
-#define WM8915_WRITE_SEQUENCER_504              0x31F8
-#define WM8915_WRITE_SEQUENCER_505              0x31F9
-#define WM8915_WRITE_SEQUENCER_506              0x31FA
-#define WM8915_WRITE_SEQUENCER_507              0x31FB
-#define WM8915_WRITE_SEQUENCER_508              0x31FC
-#define WM8915_WRITE_SEQUENCER_509              0x31FD
-#define WM8915_WRITE_SEQUENCER_510              0x31FE
-#define WM8915_WRITE_SEQUENCER_511              0x31FF
-
-#define WM8915_REGISTER_COUNT                   706
-#define WM8915_MAX_REGISTER                     0x31FF
-
-/*
- * Field Definitions.
- */
-
-/*
- * R0 (0x00) - Software Reset
- */
-#define WM8915_SW_RESET_MASK                    0xFFFF  /* SW_RESET - [15:0] */
-#define WM8915_SW_RESET_SHIFT                        0  /* SW_RESET - [15:0] */
-#define WM8915_SW_RESET_WIDTH                       16  /* SW_RESET - [15:0] */
-
-/*
- * R1 (0x01) - Power Management (1)
- */
-#define WM8915_MICB2_ENA                        0x0200  /* MICB2_ENA */
-#define WM8915_MICB2_ENA_MASK                   0x0200  /* MICB2_ENA */
-#define WM8915_MICB2_ENA_SHIFT                       9  /* MICB2_ENA */
-#define WM8915_MICB2_ENA_WIDTH                       1  /* MICB2_ENA */
-#define WM8915_MICB1_ENA                        0x0100  /* MICB1_ENA */
-#define WM8915_MICB1_ENA_MASK                   0x0100  /* MICB1_ENA */
-#define WM8915_MICB1_ENA_SHIFT                       8  /* MICB1_ENA */
-#define WM8915_MICB1_ENA_WIDTH                       1  /* MICB1_ENA */
-#define WM8915_HPOUT2L_ENA                      0x0080  /* HPOUT2L_ENA */
-#define WM8915_HPOUT2L_ENA_MASK                 0x0080  /* HPOUT2L_ENA */
-#define WM8915_HPOUT2L_ENA_SHIFT                     7  /* HPOUT2L_ENA */
-#define WM8915_HPOUT2L_ENA_WIDTH                     1  /* HPOUT2L_ENA */
-#define WM8915_HPOUT2R_ENA                      0x0040  /* HPOUT2R_ENA */
-#define WM8915_HPOUT2R_ENA_MASK                 0x0040  /* HPOUT2R_ENA */
-#define WM8915_HPOUT2R_ENA_SHIFT                     6  /* HPOUT2R_ENA */
-#define WM8915_HPOUT2R_ENA_WIDTH                     1  /* HPOUT2R_ENA */
-#define WM8915_HPOUT1L_ENA                      0x0020  /* HPOUT1L_ENA */
-#define WM8915_HPOUT1L_ENA_MASK                 0x0020  /* HPOUT1L_ENA */
-#define WM8915_HPOUT1L_ENA_SHIFT                     5  /* HPOUT1L_ENA */
-#define WM8915_HPOUT1L_ENA_WIDTH                     1  /* HPOUT1L_ENA */
-#define WM8915_HPOUT1R_ENA                      0x0010  /* HPOUT1R_ENA */
-#define WM8915_HPOUT1R_ENA_MASK                 0x0010  /* HPOUT1R_ENA */
-#define WM8915_HPOUT1R_ENA_SHIFT                     4  /* HPOUT1R_ENA */
-#define WM8915_HPOUT1R_ENA_WIDTH                     1  /* HPOUT1R_ENA */
-#define WM8915_BG_ENA                           0x0001  /* BG_ENA */
-#define WM8915_BG_ENA_MASK                      0x0001  /* BG_ENA */
-#define WM8915_BG_ENA_SHIFT                          0  /* BG_ENA */
-#define WM8915_BG_ENA_WIDTH                          1  /* BG_ENA */
-
-/*
- * R2 (0x02) - Power Management (2)
- */
-#define WM8915_OPCLK_ENA                        0x0800  /* OPCLK_ENA */
-#define WM8915_OPCLK_ENA_MASK                   0x0800  /* OPCLK_ENA */
-#define WM8915_OPCLK_ENA_SHIFT                      11  /* OPCLK_ENA */
-#define WM8915_OPCLK_ENA_WIDTH                       1  /* OPCLK_ENA */
-#define WM8915_INL_ENA                          0x0020  /* INL_ENA */
-#define WM8915_INL_ENA_MASK                     0x0020  /* INL_ENA */
-#define WM8915_INL_ENA_SHIFT                         5  /* INL_ENA */
-#define WM8915_INL_ENA_WIDTH                         1  /* INL_ENA */
-#define WM8915_INR_ENA                          0x0010  /* INR_ENA */
-#define WM8915_INR_ENA_MASK                     0x0010  /* INR_ENA */
-#define WM8915_INR_ENA_SHIFT                         4  /* INR_ENA */
-#define WM8915_INR_ENA_WIDTH                         1  /* INR_ENA */
-#define WM8915_LDO2_ENA                         0x0002  /* LDO2_ENA */
-#define WM8915_LDO2_ENA_MASK                    0x0002  /* LDO2_ENA */
-#define WM8915_LDO2_ENA_SHIFT                        1  /* LDO2_ENA */
-#define WM8915_LDO2_ENA_WIDTH                        1  /* LDO2_ENA */
-
-/*
- * R3 (0x03) - Power Management (3)
- */
-#define WM8915_DSP2RXL_ENA                      0x0800  /* DSP2RXL_ENA */
-#define WM8915_DSP2RXL_ENA_MASK                 0x0800  /* DSP2RXL_ENA */
-#define WM8915_DSP2RXL_ENA_SHIFT                    11  /* DSP2RXL_ENA */
-#define WM8915_DSP2RXL_ENA_WIDTH                     1  /* DSP2RXL_ENA */
-#define WM8915_DSP2RXR_ENA                      0x0400  /* DSP2RXR_ENA */
-#define WM8915_DSP2RXR_ENA_MASK                 0x0400  /* DSP2RXR_ENA */
-#define WM8915_DSP2RXR_ENA_SHIFT                    10  /* DSP2RXR_ENA */
-#define WM8915_DSP2RXR_ENA_WIDTH                     1  /* DSP2RXR_ENA */
-#define WM8915_DSP1RXL_ENA                      0x0200  /* DSP1RXL_ENA */
-#define WM8915_DSP1RXL_ENA_MASK                 0x0200  /* DSP1RXL_ENA */
-#define WM8915_DSP1RXL_ENA_SHIFT                     9  /* DSP1RXL_ENA */
-#define WM8915_DSP1RXL_ENA_WIDTH                     1  /* DSP1RXL_ENA */
-#define WM8915_DSP1RXR_ENA                      0x0100  /* DSP1RXR_ENA */
-#define WM8915_DSP1RXR_ENA_MASK                 0x0100  /* DSP1RXR_ENA */
-#define WM8915_DSP1RXR_ENA_SHIFT                     8  /* DSP1RXR_ENA */
-#define WM8915_DSP1RXR_ENA_WIDTH                     1  /* DSP1RXR_ENA */
-#define WM8915_DMIC2L_ENA                       0x0020  /* DMIC2L_ENA */
-#define WM8915_DMIC2L_ENA_MASK                  0x0020  /* DMIC2L_ENA */
-#define WM8915_DMIC2L_ENA_SHIFT                      5  /* DMIC2L_ENA */
-#define WM8915_DMIC2L_ENA_WIDTH                      1  /* DMIC2L_ENA */
-#define WM8915_DMIC2R_ENA                       0x0010  /* DMIC2R_ENA */
-#define WM8915_DMIC2R_ENA_MASK                  0x0010  /* DMIC2R_ENA */
-#define WM8915_DMIC2R_ENA_SHIFT                      4  /* DMIC2R_ENA */
-#define WM8915_DMIC2R_ENA_WIDTH                      1  /* DMIC2R_ENA */
-#define WM8915_DMIC1L_ENA                       0x0008  /* DMIC1L_ENA */
-#define WM8915_DMIC1L_ENA_MASK                  0x0008  /* DMIC1L_ENA */
-#define WM8915_DMIC1L_ENA_SHIFT                      3  /* DMIC1L_ENA */
-#define WM8915_DMIC1L_ENA_WIDTH                      1  /* DMIC1L_ENA */
-#define WM8915_DMIC1R_ENA                       0x0004  /* DMIC1R_ENA */
-#define WM8915_DMIC1R_ENA_MASK                  0x0004  /* DMIC1R_ENA */
-#define WM8915_DMIC1R_ENA_SHIFT                      2  /* DMIC1R_ENA */
-#define WM8915_DMIC1R_ENA_WIDTH                      1  /* DMIC1R_ENA */
-#define WM8915_ADCL_ENA                         0x0002  /* ADCL_ENA */
-#define WM8915_ADCL_ENA_MASK                    0x0002  /* ADCL_ENA */
-#define WM8915_ADCL_ENA_SHIFT                        1  /* ADCL_ENA */
-#define WM8915_ADCL_ENA_WIDTH                        1  /* ADCL_ENA */
-#define WM8915_ADCR_ENA                         0x0001  /* ADCR_ENA */
-#define WM8915_ADCR_ENA_MASK                    0x0001  /* ADCR_ENA */
-#define WM8915_ADCR_ENA_SHIFT                        0  /* ADCR_ENA */
-#define WM8915_ADCR_ENA_WIDTH                        1  /* ADCR_ENA */
-
-/*
- * R4 (0x04) - Power Management (4)
- */
-#define WM8915_AIF2RX_CHAN1_ENA                 0x0200  /* AIF2RX_CHAN1_ENA */
-#define WM8915_AIF2RX_CHAN1_ENA_MASK            0x0200  /* AIF2RX_CHAN1_ENA */
-#define WM8915_AIF2RX_CHAN1_ENA_SHIFT                9  /* AIF2RX_CHAN1_ENA */
-#define WM8915_AIF2RX_CHAN1_ENA_WIDTH                1  /* AIF2RX_CHAN1_ENA */
-#define WM8915_AIF2RX_CHAN0_ENA                 0x0100  /* AIF2RX_CHAN0_ENA */
-#define WM8915_AIF2RX_CHAN0_ENA_MASK            0x0100  /* AIF2RX_CHAN0_ENA */
-#define WM8915_AIF2RX_CHAN0_ENA_SHIFT                8  /* AIF2RX_CHAN0_ENA */
-#define WM8915_AIF2RX_CHAN0_ENA_WIDTH                1  /* AIF2RX_CHAN0_ENA */
-#define WM8915_AIF1RX_CHAN5_ENA                 0x0020  /* AIF1RX_CHAN5_ENA */
-#define WM8915_AIF1RX_CHAN5_ENA_MASK            0x0020  /* AIF1RX_CHAN5_ENA */
-#define WM8915_AIF1RX_CHAN5_ENA_SHIFT                5  /* AIF1RX_CHAN5_ENA */
-#define WM8915_AIF1RX_CHAN5_ENA_WIDTH                1  /* AIF1RX_CHAN5_ENA */
-#define WM8915_AIF1RX_CHAN4_ENA                 0x0010  /* AIF1RX_CHAN4_ENA */
-#define WM8915_AIF1RX_CHAN4_ENA_MASK            0x0010  /* AIF1RX_CHAN4_ENA */
-#define WM8915_AIF1RX_CHAN4_ENA_SHIFT                4  /* AIF1RX_CHAN4_ENA */
-#define WM8915_AIF1RX_CHAN4_ENA_WIDTH                1  /* AIF1RX_CHAN4_ENA */
-#define WM8915_AIF1RX_CHAN3_ENA                 0x0008  /* AIF1RX_CHAN3_ENA */
-#define WM8915_AIF1RX_CHAN3_ENA_MASK            0x0008  /* AIF1RX_CHAN3_ENA */
-#define WM8915_AIF1RX_CHAN3_ENA_SHIFT                3  /* AIF1RX_CHAN3_ENA */
-#define WM8915_AIF1RX_CHAN3_ENA_WIDTH                1  /* AIF1RX_CHAN3_ENA */
-#define WM8915_AIF1RX_CHAN2_ENA                 0x0004  /* AIF1RX_CHAN2_ENA */
-#define WM8915_AIF1RX_CHAN2_ENA_MASK            0x0004  /* AIF1RX_CHAN2_ENA */
-#define WM8915_AIF1RX_CHAN2_ENA_SHIFT                2  /* AIF1RX_CHAN2_ENA */
-#define WM8915_AIF1RX_CHAN2_ENA_WIDTH                1  /* AIF1RX_CHAN2_ENA */
-#define WM8915_AIF1RX_CHAN1_ENA                 0x0002  /* AIF1RX_CHAN1_ENA */
-#define WM8915_AIF1RX_CHAN1_ENA_MASK            0x0002  /* AIF1RX_CHAN1_ENA */
-#define WM8915_AIF1RX_CHAN1_ENA_SHIFT                1  /* AIF1RX_CHAN1_ENA */
-#define WM8915_AIF1RX_CHAN1_ENA_WIDTH                1  /* AIF1RX_CHAN1_ENA */
-#define WM8915_AIF1RX_CHAN0_ENA                 0x0001  /* AIF1RX_CHAN0_ENA */
-#define WM8915_AIF1RX_CHAN0_ENA_MASK            0x0001  /* AIF1RX_CHAN0_ENA */
-#define WM8915_AIF1RX_CHAN0_ENA_SHIFT                0  /* AIF1RX_CHAN0_ENA */
-#define WM8915_AIF1RX_CHAN0_ENA_WIDTH                1  /* AIF1RX_CHAN0_ENA */
-
-/*
- * R5 (0x05) - Power Management (5)
- */
-#define WM8915_DSP2TXL_ENA                      0x0800  /* DSP2TXL_ENA */
-#define WM8915_DSP2TXL_ENA_MASK                 0x0800  /* DSP2TXL_ENA */
-#define WM8915_DSP2TXL_ENA_SHIFT                    11  /* DSP2TXL_ENA */
-#define WM8915_DSP2TXL_ENA_WIDTH                     1  /* DSP2TXL_ENA */
-#define WM8915_DSP2TXR_ENA                      0x0400  /* DSP2TXR_ENA */
-#define WM8915_DSP2TXR_ENA_MASK                 0x0400  /* DSP2TXR_ENA */
-#define WM8915_DSP2TXR_ENA_SHIFT                    10  /* DSP2TXR_ENA */
-#define WM8915_DSP2TXR_ENA_WIDTH                     1  /* DSP2TXR_ENA */
-#define WM8915_DSP1TXL_ENA                      0x0200  /* DSP1TXL_ENA */
-#define WM8915_DSP1TXL_ENA_MASK                 0x0200  /* DSP1TXL_ENA */
-#define WM8915_DSP1TXL_ENA_SHIFT                     9  /* DSP1TXL_ENA */
-#define WM8915_DSP1TXL_ENA_WIDTH                     1  /* DSP1TXL_ENA */
-#define WM8915_DSP1TXR_ENA                      0x0100  /* DSP1TXR_ENA */
-#define WM8915_DSP1TXR_ENA_MASK                 0x0100  /* DSP1TXR_ENA */
-#define WM8915_DSP1TXR_ENA_SHIFT                     8  /* DSP1TXR_ENA */
-#define WM8915_DSP1TXR_ENA_WIDTH                     1  /* DSP1TXR_ENA */
-#define WM8915_DAC2L_ENA                        0x0008  /* DAC2L_ENA */
-#define WM8915_DAC2L_ENA_MASK                   0x0008  /* DAC2L_ENA */
-#define WM8915_DAC2L_ENA_SHIFT                       3  /* DAC2L_ENA */
-#define WM8915_DAC2L_ENA_WIDTH                       1  /* DAC2L_ENA */
-#define WM8915_DAC2R_ENA                        0x0004  /* DAC2R_ENA */
-#define WM8915_DAC2R_ENA_MASK                   0x0004  /* DAC2R_ENA */
-#define WM8915_DAC2R_ENA_SHIFT                       2  /* DAC2R_ENA */
-#define WM8915_DAC2R_ENA_WIDTH                       1  /* DAC2R_ENA */
-#define WM8915_DAC1L_ENA                        0x0002  /* DAC1L_ENA */
-#define WM8915_DAC1L_ENA_MASK                   0x0002  /* DAC1L_ENA */
-#define WM8915_DAC1L_ENA_SHIFT                       1  /* DAC1L_ENA */
-#define WM8915_DAC1L_ENA_WIDTH                       1  /* DAC1L_ENA */
-#define WM8915_DAC1R_ENA                        0x0001  /* DAC1R_ENA */
-#define WM8915_DAC1R_ENA_MASK                   0x0001  /* DAC1R_ENA */
-#define WM8915_DAC1R_ENA_SHIFT                       0  /* DAC1R_ENA */
-#define WM8915_DAC1R_ENA_WIDTH                       1  /* DAC1R_ENA */
-
-/*
- * R6 (0x06) - Power Management (6)
- */
-#define WM8915_AIF2TX_CHAN1_ENA                 0x0200  /* AIF2TX_CHAN1_ENA */
-#define WM8915_AIF2TX_CHAN1_ENA_MASK            0x0200  /* AIF2TX_CHAN1_ENA */
-#define WM8915_AIF2TX_CHAN1_ENA_SHIFT                9  /* AIF2TX_CHAN1_ENA */
-#define WM8915_AIF2TX_CHAN1_ENA_WIDTH                1  /* AIF2TX_CHAN1_ENA */
-#define WM8915_AIF2TX_CHAN0_ENA                 0x0100  /* AIF2TX_CHAN0_ENA */
-#define WM8915_AIF2TX_CHAN0_ENA_MASK            0x0100  /* AIF2TX_CHAN0_ENA */
-#define WM8915_AIF2TX_CHAN0_ENA_SHIFT                8  /* AIF2TX_CHAN0_ENA */
-#define WM8915_AIF2TX_CHAN0_ENA_WIDTH                1  /* AIF2TX_CHAN0_ENA */
-#define WM8915_AIF1TX_CHAN5_ENA                 0x0020  /* AIF1TX_CHAN5_ENA */
-#define WM8915_AIF1TX_CHAN5_ENA_MASK            0x0020  /* AIF1TX_CHAN5_ENA */
-#define WM8915_AIF1TX_CHAN5_ENA_SHIFT                5  /* AIF1TX_CHAN5_ENA */
-#define WM8915_AIF1TX_CHAN5_ENA_WIDTH                1  /* AIF1TX_CHAN5_ENA */
-#define WM8915_AIF1TX_CHAN4_ENA                 0x0010  /* AIF1TX_CHAN4_ENA */
-#define WM8915_AIF1TX_CHAN4_ENA_MASK            0x0010  /* AIF1TX_CHAN4_ENA */
-#define WM8915_AIF1TX_CHAN4_ENA_SHIFT                4  /* AIF1TX_CHAN4_ENA */
-#define WM8915_AIF1TX_CHAN4_ENA_WIDTH                1  /* AIF1TX_CHAN4_ENA */
-#define WM8915_AIF1TX_CHAN3_ENA                 0x0008  /* AIF1TX_CHAN3_ENA */
-#define WM8915_AIF1TX_CHAN3_ENA_MASK            0x0008  /* AIF1TX_CHAN3_ENA */
-#define WM8915_AIF1TX_CHAN3_ENA_SHIFT                3  /* AIF1TX_CHAN3_ENA */
-#define WM8915_AIF1TX_CHAN3_ENA_WIDTH                1  /* AIF1TX_CHAN3_ENA */
-#define WM8915_AIF1TX_CHAN2_ENA                 0x0004  /* AIF1TX_CHAN2_ENA */
-#define WM8915_AIF1TX_CHAN2_ENA_MASK            0x0004  /* AIF1TX_CHAN2_ENA */
-#define WM8915_AIF1TX_CHAN2_ENA_SHIFT                2  /* AIF1TX_CHAN2_ENA */
-#define WM8915_AIF1TX_CHAN2_ENA_WIDTH                1  /* AIF1TX_CHAN2_ENA */
-#define WM8915_AIF1TX_CHAN1_ENA                 0x0002  /* AIF1TX_CHAN1_ENA */
-#define WM8915_AIF1TX_CHAN1_ENA_MASK            0x0002  /* AIF1TX_CHAN1_ENA */
-#define WM8915_AIF1TX_CHAN1_ENA_SHIFT                1  /* AIF1TX_CHAN1_ENA */
-#define WM8915_AIF1TX_CHAN1_ENA_WIDTH                1  /* AIF1TX_CHAN1_ENA */
-#define WM8915_AIF1TX_CHAN0_ENA                 0x0001  /* AIF1TX_CHAN0_ENA */
-#define WM8915_AIF1TX_CHAN0_ENA_MASK            0x0001  /* AIF1TX_CHAN0_ENA */
-#define WM8915_AIF1TX_CHAN0_ENA_SHIFT                0  /* AIF1TX_CHAN0_ENA */
-#define WM8915_AIF1TX_CHAN0_ENA_WIDTH                1  /* AIF1TX_CHAN0_ENA */
-
-/*
- * R7 (0x07) - Power Management (7)
- */
-#define WM8915_DMIC2_FN                         0x0200  /* DMIC2_FN */
-#define WM8915_DMIC2_FN_MASK                    0x0200  /* DMIC2_FN */
-#define WM8915_DMIC2_FN_SHIFT                        9  /* DMIC2_FN */
-#define WM8915_DMIC2_FN_WIDTH                        1  /* DMIC2_FN */
-#define WM8915_DMIC1_FN                         0x0100  /* DMIC1_FN */
-#define WM8915_DMIC1_FN_MASK                    0x0100  /* DMIC1_FN */
-#define WM8915_DMIC1_FN_SHIFT                        8  /* DMIC1_FN */
-#define WM8915_DMIC1_FN_WIDTH                        1  /* DMIC1_FN */
-#define WM8915_ADC_DMIC_DSP2R_ENA               0x0080  /* ADC_DMIC_DSP2R_ENA */
-#define WM8915_ADC_DMIC_DSP2R_ENA_MASK          0x0080  /* ADC_DMIC_DSP2R_ENA */
-#define WM8915_ADC_DMIC_DSP2R_ENA_SHIFT              7  /* ADC_DMIC_DSP2R_ENA */
-#define WM8915_ADC_DMIC_DSP2R_ENA_WIDTH              1  /* ADC_DMIC_DSP2R_ENA */
-#define WM8915_ADC_DMIC_DSP2L_ENA               0x0040  /* ADC_DMIC_DSP2L_ENA */
-#define WM8915_ADC_DMIC_DSP2L_ENA_MASK          0x0040  /* ADC_DMIC_DSP2L_ENA */
-#define WM8915_ADC_DMIC_DSP2L_ENA_SHIFT              6  /* ADC_DMIC_DSP2L_ENA */
-#define WM8915_ADC_DMIC_DSP2L_ENA_WIDTH              1  /* ADC_DMIC_DSP2L_ENA */
-#define WM8915_ADC_DMIC_SRC2_MASK               0x0030  /* ADC_DMIC_SRC2 - [5:4] */
-#define WM8915_ADC_DMIC_SRC2_SHIFT                   4  /* ADC_DMIC_SRC2 - [5:4] */
-#define WM8915_ADC_DMIC_SRC2_WIDTH                   2  /* ADC_DMIC_SRC2 - [5:4] */
-#define WM8915_ADC_DMIC_DSP1R_ENA               0x0008  /* ADC_DMIC_DSP1R_ENA */
-#define WM8915_ADC_DMIC_DSP1R_ENA_MASK          0x0008  /* ADC_DMIC_DSP1R_ENA */
-#define WM8915_ADC_DMIC_DSP1R_ENA_SHIFT              3  /* ADC_DMIC_DSP1R_ENA */
-#define WM8915_ADC_DMIC_DSP1R_ENA_WIDTH              1  /* ADC_DMIC_DSP1R_ENA */
-#define WM8915_ADC_DMIC_DSP1L_ENA               0x0004  /* ADC_DMIC_DSP1L_ENA */
-#define WM8915_ADC_DMIC_DSP1L_ENA_MASK          0x0004  /* ADC_DMIC_DSP1L_ENA */
-#define WM8915_ADC_DMIC_DSP1L_ENA_SHIFT              2  /* ADC_DMIC_DSP1L_ENA */
-#define WM8915_ADC_DMIC_DSP1L_ENA_WIDTH              1  /* ADC_DMIC_DSP1L_ENA */
-#define WM8915_ADC_DMIC_SRC1_MASK               0x0003  /* ADC_DMIC_SRC1 - [1:0] */
-#define WM8915_ADC_DMIC_SRC1_SHIFT                   0  /* ADC_DMIC_SRC1 - [1:0] */
-#define WM8915_ADC_DMIC_SRC1_WIDTH                   2  /* ADC_DMIC_SRC1 - [1:0] */
-
-/*
- * R8 (0x08) - Power Management (8)
- */
-#define WM8915_AIF2TX_SRC_MASK                  0x00C0  /* AIF2TX_SRC - [7:6] */
-#define WM8915_AIF2TX_SRC_SHIFT                      6  /* AIF2TX_SRC - [7:6] */
-#define WM8915_AIF2TX_SRC_WIDTH                      2  /* AIF2TX_SRC - [7:6] */
-#define WM8915_DSP2RX_SRC                       0x0010  /* DSP2RX_SRC */
-#define WM8915_DSP2RX_SRC_MASK                  0x0010  /* DSP2RX_SRC */
-#define WM8915_DSP2RX_SRC_SHIFT                      4  /* DSP2RX_SRC */
-#define WM8915_DSP2RX_SRC_WIDTH                      1  /* DSP2RX_SRC */
-#define WM8915_DSP1RX_SRC                       0x0001  /* DSP1RX_SRC */
-#define WM8915_DSP1RX_SRC_MASK                  0x0001  /* DSP1RX_SRC */
-#define WM8915_DSP1RX_SRC_SHIFT                      0  /* DSP1RX_SRC */
-#define WM8915_DSP1RX_SRC_WIDTH                      1  /* DSP1RX_SRC */
-
-/*
- * R16 (0x10) - Left Line Input Volume
- */
-#define WM8915_IN1_VU                           0x0080  /* IN1_VU */
-#define WM8915_IN1_VU_MASK                      0x0080  /* IN1_VU */
-#define WM8915_IN1_VU_SHIFT                          7  /* IN1_VU */
-#define WM8915_IN1_VU_WIDTH                          1  /* IN1_VU */
-#define WM8915_IN1L_ZC                          0x0020  /* IN1L_ZC */
-#define WM8915_IN1L_ZC_MASK                     0x0020  /* IN1L_ZC */
-#define WM8915_IN1L_ZC_SHIFT                         5  /* IN1L_ZC */
-#define WM8915_IN1L_ZC_WIDTH                         1  /* IN1L_ZC */
-#define WM8915_IN1L_VOL_MASK                    0x001F  /* IN1L_VOL - [4:0] */
-#define WM8915_IN1L_VOL_SHIFT                        0  /* IN1L_VOL - [4:0] */
-#define WM8915_IN1L_VOL_WIDTH                        5  /* IN1L_VOL - [4:0] */
-
-/*
- * R17 (0x11) - Right Line Input Volume
- */
-#define WM8915_IN1_VU                           0x0080  /* IN1_VU */
-#define WM8915_IN1_VU_MASK                      0x0080  /* IN1_VU */
-#define WM8915_IN1_VU_SHIFT                          7  /* IN1_VU */
-#define WM8915_IN1_VU_WIDTH                          1  /* IN1_VU */
-#define WM8915_IN1R_ZC                          0x0020  /* IN1R_ZC */
-#define WM8915_IN1R_ZC_MASK                     0x0020  /* IN1R_ZC */
-#define WM8915_IN1R_ZC_SHIFT                         5  /* IN1R_ZC */
-#define WM8915_IN1R_ZC_WIDTH                         1  /* IN1R_ZC */
-#define WM8915_IN1R_VOL_MASK                    0x001F  /* IN1R_VOL - [4:0] */
-#define WM8915_IN1R_VOL_SHIFT                        0  /* IN1R_VOL - [4:0] */
-#define WM8915_IN1R_VOL_WIDTH                        5  /* IN1R_VOL - [4:0] */
-
-/*
- * R18 (0x12) - Line Input Control
- */
-#define WM8915_INL_MODE_MASK                    0x000C  /* INL_MODE - [3:2] */
-#define WM8915_INL_MODE_SHIFT                        2  /* INL_MODE - [3:2] */
-#define WM8915_INL_MODE_WIDTH                        2  /* INL_MODE - [3:2] */
-#define WM8915_INR_MODE_MASK                    0x0003  /* INR_MODE - [1:0] */
-#define WM8915_INR_MODE_SHIFT                        0  /* INR_MODE - [1:0] */
-#define WM8915_INR_MODE_WIDTH                        2  /* INR_MODE - [1:0] */
-
-/*
- * R21 (0x15) - DAC1 HPOUT1 Volume
- */
-#define WM8915_DAC1R_HPOUT1R_VOL_MASK           0x00F0  /* DAC1R_HPOUT1R_VOL - [7:4] */
-#define WM8915_DAC1R_HPOUT1R_VOL_SHIFT               4  /* DAC1R_HPOUT1R_VOL - [7:4] */
-#define WM8915_DAC1R_HPOUT1R_VOL_WIDTH               4  /* DAC1R_HPOUT1R_VOL - [7:4] */
-#define WM8915_DAC1L_HPOUT1L_VOL_MASK           0x000F  /* DAC1L_HPOUT1L_VOL - [3:0] */
-#define WM8915_DAC1L_HPOUT1L_VOL_SHIFT               0  /* DAC1L_HPOUT1L_VOL - [3:0] */
-#define WM8915_DAC1L_HPOUT1L_VOL_WIDTH               4  /* DAC1L_HPOUT1L_VOL - [3:0] */
-
-/*
- * R22 (0x16) - DAC2 HPOUT2 Volume
- */
-#define WM8915_DAC2R_HPOUT2R_VOL_MASK           0x00F0  /* DAC2R_HPOUT2R_VOL - [7:4] */
-#define WM8915_DAC2R_HPOUT2R_VOL_SHIFT               4  /* DAC2R_HPOUT2R_VOL - [7:4] */
-#define WM8915_DAC2R_HPOUT2R_VOL_WIDTH               4  /* DAC2R_HPOUT2R_VOL - [7:4] */
-#define WM8915_DAC2L_HPOUT2L_VOL_MASK           0x000F  /* DAC2L_HPOUT2L_VOL - [3:0] */
-#define WM8915_DAC2L_HPOUT2L_VOL_SHIFT               0  /* DAC2L_HPOUT2L_VOL - [3:0] */
-#define WM8915_DAC2L_HPOUT2L_VOL_WIDTH               4  /* DAC2L_HPOUT2L_VOL - [3:0] */
-
-/*
- * R24 (0x18) - DAC1 Left Volume
- */
-#define WM8915_DAC1L_MUTE                       0x0200  /* DAC1L_MUTE */
-#define WM8915_DAC1L_MUTE_MASK                  0x0200  /* DAC1L_MUTE */
-#define WM8915_DAC1L_MUTE_SHIFT                      9  /* DAC1L_MUTE */
-#define WM8915_DAC1L_MUTE_WIDTH                      1  /* DAC1L_MUTE */
-#define WM8915_DAC1_VU                          0x0100  /* DAC1_VU */
-#define WM8915_DAC1_VU_MASK                     0x0100  /* DAC1_VU */
-#define WM8915_DAC1_VU_SHIFT                         8  /* DAC1_VU */
-#define WM8915_DAC1_VU_WIDTH                         1  /* DAC1_VU */
-#define WM8915_DAC1L_VOL_MASK                   0x00FF  /* DAC1L_VOL - [7:0] */
-#define WM8915_DAC1L_VOL_SHIFT                       0  /* DAC1L_VOL - [7:0] */
-#define WM8915_DAC1L_VOL_WIDTH                       8  /* DAC1L_VOL - [7:0] */
-
-/*
- * R25 (0x19) - DAC1 Right Volume
- */
-#define WM8915_DAC1R_MUTE                       0x0200  /* DAC1R_MUTE */
-#define WM8915_DAC1R_MUTE_MASK                  0x0200  /* DAC1R_MUTE */
-#define WM8915_DAC1R_MUTE_SHIFT                      9  /* DAC1R_MUTE */
-#define WM8915_DAC1R_MUTE_WIDTH                      1  /* DAC1R_MUTE */
-#define WM8915_DAC1_VU                          0x0100  /* DAC1_VU */
-#define WM8915_DAC1_VU_MASK                     0x0100  /* DAC1_VU */
-#define WM8915_DAC1_VU_SHIFT                         8  /* DAC1_VU */
-#define WM8915_DAC1_VU_WIDTH                         1  /* DAC1_VU */
-#define WM8915_DAC1R_VOL_MASK                   0x00FF  /* DAC1R_VOL - [7:0] */
-#define WM8915_DAC1R_VOL_SHIFT                       0  /* DAC1R_VOL - [7:0] */
-#define WM8915_DAC1R_VOL_WIDTH                       8  /* DAC1R_VOL - [7:0] */
-
-/*
- * R26 (0x1A) - DAC2 Left Volume
- */
-#define WM8915_DAC2L_MUTE                       0x0200  /* DAC2L_MUTE */
-#define WM8915_DAC2L_MUTE_MASK                  0x0200  /* DAC2L_MUTE */
-#define WM8915_DAC2L_MUTE_SHIFT                      9  /* DAC2L_MUTE */
-#define WM8915_DAC2L_MUTE_WIDTH                      1  /* DAC2L_MUTE */
-#define WM8915_DAC2_VU                          0x0100  /* DAC2_VU */
-#define WM8915_DAC2_VU_MASK                     0x0100  /* DAC2_VU */
-#define WM8915_DAC2_VU_SHIFT                         8  /* DAC2_VU */
-#define WM8915_DAC2_VU_WIDTH                         1  /* DAC2_VU */
-#define WM8915_DAC2L_VOL_MASK                   0x00FF  /* DAC2L_VOL - [7:0] */
-#define WM8915_DAC2L_VOL_SHIFT                       0  /* DAC2L_VOL - [7:0] */
-#define WM8915_DAC2L_VOL_WIDTH                       8  /* DAC2L_VOL - [7:0] */
-
-/*
- * R27 (0x1B) - DAC2 Right Volume
- */
-#define WM8915_DAC2R_MUTE                       0x0200  /* DAC2R_MUTE */
-#define WM8915_DAC2R_MUTE_MASK                  0x0200  /* DAC2R_MUTE */
-#define WM8915_DAC2R_MUTE_SHIFT                      9  /* DAC2R_MUTE */
-#define WM8915_DAC2R_MUTE_WIDTH                      1  /* DAC2R_MUTE */
-#define WM8915_DAC2_VU                          0x0100  /* DAC2_VU */
-#define WM8915_DAC2_VU_MASK                     0x0100  /* DAC2_VU */
-#define WM8915_DAC2_VU_SHIFT                         8  /* DAC2_VU */
-#define WM8915_DAC2_VU_WIDTH                         1  /* DAC2_VU */
-#define WM8915_DAC2R_VOL_MASK                   0x00FF  /* DAC2R_VOL - [7:0] */
-#define WM8915_DAC2R_VOL_SHIFT                       0  /* DAC2R_VOL - [7:0] */
-#define WM8915_DAC2R_VOL_WIDTH                       8  /* DAC2R_VOL - [7:0] */
-
-/*
- * R28 (0x1C) - Output1 Left Volume
- */
-#define WM8915_DAC1_VU                          0x0100  /* DAC1_VU */
-#define WM8915_DAC1_VU_MASK                     0x0100  /* DAC1_VU */
-#define WM8915_DAC1_VU_SHIFT                         8  /* DAC1_VU */
-#define WM8915_DAC1_VU_WIDTH                         1  /* DAC1_VU */
-#define WM8915_HPOUT1L_ZC                       0x0080  /* HPOUT1L_ZC */
-#define WM8915_HPOUT1L_ZC_MASK                  0x0080  /* HPOUT1L_ZC */
-#define WM8915_HPOUT1L_ZC_SHIFT                      7  /* HPOUT1L_ZC */
-#define WM8915_HPOUT1L_ZC_WIDTH                      1  /* HPOUT1L_ZC */
-#define WM8915_HPOUT1L_VOL_MASK                 0x000F  /* HPOUT1L_VOL - [3:0] */
-#define WM8915_HPOUT1L_VOL_SHIFT                     0  /* HPOUT1L_VOL - [3:0] */
-#define WM8915_HPOUT1L_VOL_WIDTH                     4  /* HPOUT1L_VOL - [3:0] */
-
-/*
- * R29 (0x1D) - Output1 Right Volume
- */
-#define WM8915_DAC1_VU                          0x0100  /* DAC1_VU */
-#define WM8915_DAC1_VU_MASK                     0x0100  /* DAC1_VU */
-#define WM8915_DAC1_VU_SHIFT                         8  /* DAC1_VU */
-#define WM8915_DAC1_VU_WIDTH                         1  /* DAC1_VU */
-#define WM8915_HPOUT1R_ZC                       0x0080  /* HPOUT1R_ZC */
-#define WM8915_HPOUT1R_ZC_MASK                  0x0080  /* HPOUT1R_ZC */
-#define WM8915_HPOUT1R_ZC_SHIFT                      7  /* HPOUT1R_ZC */
-#define WM8915_HPOUT1R_ZC_WIDTH                      1  /* HPOUT1R_ZC */
-#define WM8915_HPOUT1R_VOL_MASK                 0x000F  /* HPOUT1R_VOL - [3:0] */
-#define WM8915_HPOUT1R_VOL_SHIFT                     0  /* HPOUT1R_VOL - [3:0] */
-#define WM8915_HPOUT1R_VOL_WIDTH                     4  /* HPOUT1R_VOL - [3:0] */
-
-/*
- * R30 (0x1E) - Output2 Left Volume
- */
-#define WM8915_DAC2_VU                          0x0100  /* DAC2_VU */
-#define WM8915_DAC2_VU_MASK                     0x0100  /* DAC2_VU */
-#define WM8915_DAC2_VU_SHIFT                         8  /* DAC2_VU */
-#define WM8915_DAC2_VU_WIDTH                         1  /* DAC2_VU */
-#define WM8915_HPOUT2L_ZC                       0x0080  /* HPOUT2L_ZC */
-#define WM8915_HPOUT2L_ZC_MASK                  0x0080  /* HPOUT2L_ZC */
-#define WM8915_HPOUT2L_ZC_SHIFT                      7  /* HPOUT2L_ZC */
-#define WM8915_HPOUT2L_ZC_WIDTH                      1  /* HPOUT2L_ZC */
-#define WM8915_HPOUT2L_VOL_MASK                 0x000F  /* HPOUT2L_VOL - [3:0] */
-#define WM8915_HPOUT2L_VOL_SHIFT                     0  /* HPOUT2L_VOL - [3:0] */
-#define WM8915_HPOUT2L_VOL_WIDTH                     4  /* HPOUT2L_VOL - [3:0] */
-
-/*
- * R31 (0x1F) - Output2 Right Volume
- */
-#define WM8915_DAC2_VU                          0x0100  /* DAC2_VU */
-#define WM8915_DAC2_VU_MASK                     0x0100  /* DAC2_VU */
-#define WM8915_DAC2_VU_SHIFT                         8  /* DAC2_VU */
-#define WM8915_DAC2_VU_WIDTH                         1  /* DAC2_VU */
-#define WM8915_HPOUT2R_ZC                       0x0080  /* HPOUT2R_ZC */
-#define WM8915_HPOUT2R_ZC_MASK                  0x0080  /* HPOUT2R_ZC */
-#define WM8915_HPOUT2R_ZC_SHIFT                      7  /* HPOUT2R_ZC */
-#define WM8915_HPOUT2R_ZC_WIDTH                      1  /* HPOUT2R_ZC */
-#define WM8915_HPOUT2R_VOL_MASK                 0x000F  /* HPOUT2R_VOL - [3:0] */
-#define WM8915_HPOUT2R_VOL_SHIFT                     0  /* HPOUT2R_VOL - [3:0] */
-#define WM8915_HPOUT2R_VOL_WIDTH                     4  /* HPOUT2R_VOL - [3:0] */
-
-/*
- * R32 (0x20) - MICBIAS (1)
- */
-#define WM8915_MICB1_RATE                       0x0020  /* MICB1_RATE */
-#define WM8915_MICB1_RATE_MASK                  0x0020  /* MICB1_RATE */
-#define WM8915_MICB1_RATE_SHIFT                      5  /* MICB1_RATE */
-#define WM8915_MICB1_RATE_WIDTH                      1  /* MICB1_RATE */
-#define WM8915_MICB1_MODE                       0x0010  /* MICB1_MODE */
-#define WM8915_MICB1_MODE_MASK                  0x0010  /* MICB1_MODE */
-#define WM8915_MICB1_MODE_SHIFT                      4  /* MICB1_MODE */
-#define WM8915_MICB1_MODE_WIDTH                      1  /* MICB1_MODE */
-#define WM8915_MICB1_LVL_MASK                   0x000E  /* MICB1_LVL - [3:1] */
-#define WM8915_MICB1_LVL_SHIFT                       1  /* MICB1_LVL - [3:1] */
-#define WM8915_MICB1_LVL_WIDTH                       3  /* MICB1_LVL - [3:1] */
-#define WM8915_MICB1_DISCH                      0x0001  /* MICB1_DISCH */
-#define WM8915_MICB1_DISCH_MASK                 0x0001  /* MICB1_DISCH */
-#define WM8915_MICB1_DISCH_SHIFT                     0  /* MICB1_DISCH */
-#define WM8915_MICB1_DISCH_WIDTH                     1  /* MICB1_DISCH */
-
-/*
- * R33 (0x21) - MICBIAS (2)
- */
-#define WM8915_MICB2_RATE                       0x0020  /* MICB2_RATE */
-#define WM8915_MICB2_RATE_MASK                  0x0020  /* MICB2_RATE */
-#define WM8915_MICB2_RATE_SHIFT                      5  /* MICB2_RATE */
-#define WM8915_MICB2_RATE_WIDTH                      1  /* MICB2_RATE */
-#define WM8915_MICB2_MODE                       0x0010  /* MICB2_MODE */
-#define WM8915_MICB2_MODE_MASK                  0x0010  /* MICB2_MODE */
-#define WM8915_MICB2_MODE_SHIFT                      4  /* MICB2_MODE */
-#define WM8915_MICB2_MODE_WIDTH                      1  /* MICB2_MODE */
-#define WM8915_MICB2_LVL_MASK                   0x000E  /* MICB2_LVL - [3:1] */
-#define WM8915_MICB2_LVL_SHIFT                       1  /* MICB2_LVL - [3:1] */
-#define WM8915_MICB2_LVL_WIDTH                       3  /* MICB2_LVL - [3:1] */
-#define WM8915_MICB2_DISCH                      0x0001  /* MICB2_DISCH */
-#define WM8915_MICB2_DISCH_MASK                 0x0001  /* MICB2_DISCH */
-#define WM8915_MICB2_DISCH_SHIFT                     0  /* MICB2_DISCH */
-#define WM8915_MICB2_DISCH_WIDTH                     1  /* MICB2_DISCH */
-
-/*
- * R40 (0x28) - LDO 1
- */
-#define WM8915_LDO1_MODE                        0x0020  /* LDO1_MODE */
-#define WM8915_LDO1_MODE_MASK                   0x0020  /* LDO1_MODE */
-#define WM8915_LDO1_MODE_SHIFT                       5  /* LDO1_MODE */
-#define WM8915_LDO1_MODE_WIDTH                       1  /* LDO1_MODE */
-#define WM8915_LDO1_VSEL_MASK                   0x0006  /* LDO1_VSEL - [2:1] */
-#define WM8915_LDO1_VSEL_SHIFT                       1  /* LDO1_VSEL - [2:1] */
-#define WM8915_LDO1_VSEL_WIDTH                       2  /* LDO1_VSEL - [2:1] */
-#define WM8915_LDO1_DISCH                       0x0001  /* LDO1_DISCH */
-#define WM8915_LDO1_DISCH_MASK                  0x0001  /* LDO1_DISCH */
-#define WM8915_LDO1_DISCH_SHIFT                      0  /* LDO1_DISCH */
-#define WM8915_LDO1_DISCH_WIDTH                      1  /* LDO1_DISCH */
-
-/*
- * R41 (0x29) - LDO 2
- */
-#define WM8915_LDO2_MODE                        0x0020  /* LDO2_MODE */
-#define WM8915_LDO2_MODE_MASK                   0x0020  /* LDO2_MODE */
-#define WM8915_LDO2_MODE_SHIFT                       5  /* LDO2_MODE */
-#define WM8915_LDO2_MODE_WIDTH                       1  /* LDO2_MODE */
-#define WM8915_LDO2_VSEL_MASK                   0x001E  /* LDO2_VSEL - [4:1] */
-#define WM8915_LDO2_VSEL_SHIFT                       1  /* LDO2_VSEL - [4:1] */
-#define WM8915_LDO2_VSEL_WIDTH                       4  /* LDO2_VSEL - [4:1] */
-#define WM8915_LDO2_DISCH                       0x0001  /* LDO2_DISCH */
-#define WM8915_LDO2_DISCH_MASK                  0x0001  /* LDO2_DISCH */
-#define WM8915_LDO2_DISCH_SHIFT                      0  /* LDO2_DISCH */
-#define WM8915_LDO2_DISCH_WIDTH                      1  /* LDO2_DISCH */
-
-/*
- * R48 (0x30) - Accessory Detect Mode 1
- */
-#define WM8915_JD_MODE_MASK                     0x0003  /* JD_MODE - [1:0] */
-#define WM8915_JD_MODE_SHIFT                         0  /* JD_MODE - [1:0] */
-#define WM8915_JD_MODE_WIDTH                         2  /* JD_MODE - [1:0] */
-
-/*
- * R49 (0x31) - Accessory Detect Mode 2
- */
-#define WM8915_HPOUT1FB_SRC                     0x0004  /* HPOUT1FB_SRC */
-#define WM8915_HPOUT1FB_SRC_MASK                0x0004  /* HPOUT1FB_SRC */
-#define WM8915_HPOUT1FB_SRC_SHIFT                    2  /* HPOUT1FB_SRC */
-#define WM8915_HPOUT1FB_SRC_WIDTH                    1  /* HPOUT1FB_SRC */
-#define WM8915_MICD_SRC                         0x0002  /* MICD_SRC */
-#define WM8915_MICD_SRC_MASK                    0x0002  /* MICD_SRC */
-#define WM8915_MICD_SRC_SHIFT                        1  /* MICD_SRC */
-#define WM8915_MICD_SRC_WIDTH                        1  /* MICD_SRC */
-#define WM8915_MICD_BIAS_SRC                    0x0001  /* MICD_BIAS_SRC */
-#define WM8915_MICD_BIAS_SRC_MASK               0x0001  /* MICD_BIAS_SRC */
-#define WM8915_MICD_BIAS_SRC_SHIFT                   0  /* MICD_BIAS_SRC */
-#define WM8915_MICD_BIAS_SRC_WIDTH                   1  /* MICD_BIAS_SRC */
-
-/*
- * R52 (0x34) - Headphone Detect 1
- */
-#define WM8915_HP_HOLDTIME_MASK                 0x00E0  /* HP_HOLDTIME - [7:5] */
-#define WM8915_HP_HOLDTIME_SHIFT                     5  /* HP_HOLDTIME - [7:5] */
-#define WM8915_HP_HOLDTIME_WIDTH                     3  /* HP_HOLDTIME - [7:5] */
-#define WM8915_HP_CLK_DIV_MASK                  0x0018  /* HP_CLK_DIV - [4:3] */
-#define WM8915_HP_CLK_DIV_SHIFT                      3  /* HP_CLK_DIV - [4:3] */
-#define WM8915_HP_CLK_DIV_WIDTH                      2  /* HP_CLK_DIV - [4:3] */
-#define WM8915_HP_STEP_SIZE                     0x0002  /* HP_STEP_SIZE */
-#define WM8915_HP_STEP_SIZE_MASK                0x0002  /* HP_STEP_SIZE */
-#define WM8915_HP_STEP_SIZE_SHIFT                    1  /* HP_STEP_SIZE */
-#define WM8915_HP_STEP_SIZE_WIDTH                    1  /* HP_STEP_SIZE */
-#define WM8915_HP_POLL                          0x0001  /* HP_POLL */
-#define WM8915_HP_POLL_MASK                     0x0001  /* HP_POLL */
-#define WM8915_HP_POLL_SHIFT                         0  /* HP_POLL */
-#define WM8915_HP_POLL_WIDTH                         1  /* HP_POLL */
-
-/*
- * R53 (0x35) - Headphone Detect 2
- */
-#define WM8915_HP_DONE                          0x0080  /* HP_DONE */
-#define WM8915_HP_DONE_MASK                     0x0080  /* HP_DONE */
-#define WM8915_HP_DONE_SHIFT                         7  /* HP_DONE */
-#define WM8915_HP_DONE_WIDTH                         1  /* HP_DONE */
-#define WM8915_HP_LVL_MASK                      0x007F  /* HP_LVL - [6:0] */
-#define WM8915_HP_LVL_SHIFT                          0  /* HP_LVL - [6:0] */
-#define WM8915_HP_LVL_WIDTH                          7  /* HP_LVL - [6:0] */
-
-/*
- * R56 (0x38) - Mic Detect 1
- */
-#define WM8915_MICD_BIAS_STARTTIME_MASK         0xF000  /* MICD_BIAS_STARTTIME - [15:12] */
-#define WM8915_MICD_BIAS_STARTTIME_SHIFT            12  /* MICD_BIAS_STARTTIME - [15:12] */
-#define WM8915_MICD_BIAS_STARTTIME_WIDTH             4  /* MICD_BIAS_STARTTIME - [15:12] */
-#define WM8915_MICD_RATE_MASK                   0x0F00  /* MICD_RATE - [11:8] */
-#define WM8915_MICD_RATE_SHIFT                       8  /* MICD_RATE - [11:8] */
-#define WM8915_MICD_RATE_WIDTH                       4  /* MICD_RATE - [11:8] */
-#define WM8915_MICD_DBTIME                      0x0002  /* MICD_DBTIME */
-#define WM8915_MICD_DBTIME_MASK                 0x0002  /* MICD_DBTIME */
-#define WM8915_MICD_DBTIME_SHIFT                     1  /* MICD_DBTIME */
-#define WM8915_MICD_DBTIME_WIDTH                     1  /* MICD_DBTIME */
-#define WM8915_MICD_ENA                         0x0001  /* MICD_ENA */
-#define WM8915_MICD_ENA_MASK                    0x0001  /* MICD_ENA */
-#define WM8915_MICD_ENA_SHIFT                        0  /* MICD_ENA */
-#define WM8915_MICD_ENA_WIDTH                        1  /* MICD_ENA */
-
-/*
- * R57 (0x39) - Mic Detect 2
- */
-#define WM8915_MICD_LVL_SEL_MASK                0x00FF  /* MICD_LVL_SEL - [7:0] */
-#define WM8915_MICD_LVL_SEL_SHIFT                    0  /* MICD_LVL_SEL - [7:0] */
-#define WM8915_MICD_LVL_SEL_WIDTH                    8  /* MICD_LVL_SEL - [7:0] */
-
-/*
- * R58 (0x3A) - Mic Detect 3
- */
-#define WM8915_MICD_LVL_MASK                    0x07FC  /* MICD_LVL - [10:2] */
-#define WM8915_MICD_LVL_SHIFT                        2  /* MICD_LVL - [10:2] */
-#define WM8915_MICD_LVL_WIDTH                        9  /* MICD_LVL - [10:2] */
-#define WM8915_MICD_VALID                       0x0002  /* MICD_VALID */
-#define WM8915_MICD_VALID_MASK                  0x0002  /* MICD_VALID */
-#define WM8915_MICD_VALID_SHIFT                      1  /* MICD_VALID */
-#define WM8915_MICD_VALID_WIDTH                      1  /* MICD_VALID */
-#define WM8915_MICD_STS                         0x0001  /* MICD_STS */
-#define WM8915_MICD_STS_MASK                    0x0001  /* MICD_STS */
-#define WM8915_MICD_STS_SHIFT                        0  /* MICD_STS */
-#define WM8915_MICD_STS_WIDTH                        1  /* MICD_STS */
-
-/*
- * R64 (0x40) - Charge Pump (1)
- */
-#define WM8915_CP_ENA                           0x8000  /* CP_ENA */
-#define WM8915_CP_ENA_MASK                      0x8000  /* CP_ENA */
-#define WM8915_CP_ENA_SHIFT                         15  /* CP_ENA */
-#define WM8915_CP_ENA_WIDTH                          1  /* CP_ENA */
-
-/*
- * R65 (0x41) - Charge Pump (2)
- */
-#define WM8915_CP_DISCH                         0x8000  /* CP_DISCH */
-#define WM8915_CP_DISCH_MASK                    0x8000  /* CP_DISCH */
-#define WM8915_CP_DISCH_SHIFT                       15  /* CP_DISCH */
-#define WM8915_CP_DISCH_WIDTH                        1  /* CP_DISCH */
-
-/*
- * R80 (0x50) - DC Servo (1)
- */
-#define WM8915_DCS_ENA_CHAN_3                   0x0008  /* DCS_ENA_CHAN_3 */
-#define WM8915_DCS_ENA_CHAN_3_MASK              0x0008  /* DCS_ENA_CHAN_3 */
-#define WM8915_DCS_ENA_CHAN_3_SHIFT                  3  /* DCS_ENA_CHAN_3 */
-#define WM8915_DCS_ENA_CHAN_3_WIDTH                  1  /* DCS_ENA_CHAN_3 */
-#define WM8915_DCS_ENA_CHAN_2                   0x0004  /* DCS_ENA_CHAN_2 */
-#define WM8915_DCS_ENA_CHAN_2_MASK              0x0004  /* DCS_ENA_CHAN_2 */
-#define WM8915_DCS_ENA_CHAN_2_SHIFT                  2  /* DCS_ENA_CHAN_2 */
-#define WM8915_DCS_ENA_CHAN_2_WIDTH                  1  /* DCS_ENA_CHAN_2 */
-#define WM8915_DCS_ENA_CHAN_1                   0x0002  /* DCS_ENA_CHAN_1 */
-#define WM8915_DCS_ENA_CHAN_1_MASK              0x0002  /* DCS_ENA_CHAN_1 */
-#define WM8915_DCS_ENA_CHAN_1_SHIFT                  1  /* DCS_ENA_CHAN_1 */
-#define WM8915_DCS_ENA_CHAN_1_WIDTH                  1  /* DCS_ENA_CHAN_1 */
-#define WM8915_DCS_ENA_CHAN_0                   0x0001  /* DCS_ENA_CHAN_0 */
-#define WM8915_DCS_ENA_CHAN_0_MASK              0x0001  /* DCS_ENA_CHAN_0 */
-#define WM8915_DCS_ENA_CHAN_0_SHIFT                  0  /* DCS_ENA_CHAN_0 */
-#define WM8915_DCS_ENA_CHAN_0_WIDTH                  1  /* DCS_ENA_CHAN_0 */
-
-/*
- * R81 (0x51) - DC Servo (2)
- */
-#define WM8915_DCS_TRIG_SINGLE_3                0x8000  /* DCS_TRIG_SINGLE_3 */
-#define WM8915_DCS_TRIG_SINGLE_3_MASK           0x8000  /* DCS_TRIG_SINGLE_3 */
-#define WM8915_DCS_TRIG_SINGLE_3_SHIFT              15  /* DCS_TRIG_SINGLE_3 */
-#define WM8915_DCS_TRIG_SINGLE_3_WIDTH               1  /* DCS_TRIG_SINGLE_3 */
-#define WM8915_DCS_TRIG_SINGLE_2                0x4000  /* DCS_TRIG_SINGLE_2 */
-#define WM8915_DCS_TRIG_SINGLE_2_MASK           0x4000  /* DCS_TRIG_SINGLE_2 */
-#define WM8915_DCS_TRIG_SINGLE_2_SHIFT              14  /* DCS_TRIG_SINGLE_2 */
-#define WM8915_DCS_TRIG_SINGLE_2_WIDTH               1  /* DCS_TRIG_SINGLE_2 */
-#define WM8915_DCS_TRIG_SINGLE_1                0x2000  /* DCS_TRIG_SINGLE_1 */
-#define WM8915_DCS_TRIG_SINGLE_1_MASK           0x2000  /* DCS_TRIG_SINGLE_1 */
-#define WM8915_DCS_TRIG_SINGLE_1_SHIFT              13  /* DCS_TRIG_SINGLE_1 */
-#define WM8915_DCS_TRIG_SINGLE_1_WIDTH               1  /* DCS_TRIG_SINGLE_1 */
-#define WM8915_DCS_TRIG_SINGLE_0                0x1000  /* DCS_TRIG_SINGLE_0 */
-#define WM8915_DCS_TRIG_SINGLE_0_MASK           0x1000  /* DCS_TRIG_SINGLE_0 */
-#define WM8915_DCS_TRIG_SINGLE_0_SHIFT              12  /* DCS_TRIG_SINGLE_0 */
-#define WM8915_DCS_TRIG_SINGLE_0_WIDTH               1  /* DCS_TRIG_SINGLE_0 */
-#define WM8915_DCS_TRIG_SERIES_3                0x0800  /* DCS_TRIG_SERIES_3 */
-#define WM8915_DCS_TRIG_SERIES_3_MASK           0x0800  /* DCS_TRIG_SERIES_3 */
-#define WM8915_DCS_TRIG_SERIES_3_SHIFT              11  /* DCS_TRIG_SERIES_3 */
-#define WM8915_DCS_TRIG_SERIES_3_WIDTH               1  /* DCS_TRIG_SERIES_3 */
-#define WM8915_DCS_TRIG_SERIES_2                0x0400  /* DCS_TRIG_SERIES_2 */
-#define WM8915_DCS_TRIG_SERIES_2_MASK           0x0400  /* DCS_TRIG_SERIES_2 */
-#define WM8915_DCS_TRIG_SERIES_2_SHIFT              10  /* DCS_TRIG_SERIES_2 */
-#define WM8915_DCS_TRIG_SERIES_2_WIDTH               1  /* DCS_TRIG_SERIES_2 */
-#define WM8915_DCS_TRIG_SERIES_1                0x0200  /* DCS_TRIG_SERIES_1 */
-#define WM8915_DCS_TRIG_SERIES_1_MASK           0x0200  /* DCS_TRIG_SERIES_1 */
-#define WM8915_DCS_TRIG_SERIES_1_SHIFT               9  /* DCS_TRIG_SERIES_1 */
-#define WM8915_DCS_TRIG_SERIES_1_WIDTH               1  /* DCS_TRIG_SERIES_1 */
-#define WM8915_DCS_TRIG_SERIES_0                0x0100  /* DCS_TRIG_SERIES_0 */
-#define WM8915_DCS_TRIG_SERIES_0_MASK           0x0100  /* DCS_TRIG_SERIES_0 */
-#define WM8915_DCS_TRIG_SERIES_0_SHIFT               8  /* DCS_TRIG_SERIES_0 */
-#define WM8915_DCS_TRIG_SERIES_0_WIDTH               1  /* DCS_TRIG_SERIES_0 */
-#define WM8915_DCS_TRIG_STARTUP_3               0x0080  /* DCS_TRIG_STARTUP_3 */
-#define WM8915_DCS_TRIG_STARTUP_3_MASK          0x0080  /* DCS_TRIG_STARTUP_3 */
-#define WM8915_DCS_TRIG_STARTUP_3_SHIFT              7  /* DCS_TRIG_STARTUP_3 */
-#define WM8915_DCS_TRIG_STARTUP_3_WIDTH              1  /* DCS_TRIG_STARTUP_3 */
-#define WM8915_DCS_TRIG_STARTUP_2               0x0040  /* DCS_TRIG_STARTUP_2 */
-#define WM8915_DCS_TRIG_STARTUP_2_MASK          0x0040  /* DCS_TRIG_STARTUP_2 */
-#define WM8915_DCS_TRIG_STARTUP_2_SHIFT              6  /* DCS_TRIG_STARTUP_2 */
-#define WM8915_DCS_TRIG_STARTUP_2_WIDTH              1  /* DCS_TRIG_STARTUP_2 */
-#define WM8915_DCS_TRIG_STARTUP_1               0x0020  /* DCS_TRIG_STARTUP_1 */
-#define WM8915_DCS_TRIG_STARTUP_1_MASK          0x0020  /* DCS_TRIG_STARTUP_1 */
-#define WM8915_DCS_TRIG_STARTUP_1_SHIFT              5  /* DCS_TRIG_STARTUP_1 */
-#define WM8915_DCS_TRIG_STARTUP_1_WIDTH              1  /* DCS_TRIG_STARTUP_1 */
-#define WM8915_DCS_TRIG_STARTUP_0               0x0010  /* DCS_TRIG_STARTUP_0 */
-#define WM8915_DCS_TRIG_STARTUP_0_MASK          0x0010  /* DCS_TRIG_STARTUP_0 */
-#define WM8915_DCS_TRIG_STARTUP_0_SHIFT              4  /* DCS_TRIG_STARTUP_0 */
-#define WM8915_DCS_TRIG_STARTUP_0_WIDTH              1  /* DCS_TRIG_STARTUP_0 */
-#define WM8915_DCS_TRIG_DAC_WR_3                0x0008  /* DCS_TRIG_DAC_WR_3 */
-#define WM8915_DCS_TRIG_DAC_WR_3_MASK           0x0008  /* DCS_TRIG_DAC_WR_3 */
-#define WM8915_DCS_TRIG_DAC_WR_3_SHIFT               3  /* DCS_TRIG_DAC_WR_3 */
-#define WM8915_DCS_TRIG_DAC_WR_3_WIDTH               1  /* DCS_TRIG_DAC_WR_3 */
-#define WM8915_DCS_TRIG_DAC_WR_2                0x0004  /* DCS_TRIG_DAC_WR_2 */
-#define WM8915_DCS_TRIG_DAC_WR_2_MASK           0x0004  /* DCS_TRIG_DAC_WR_2 */
-#define WM8915_DCS_TRIG_DAC_WR_2_SHIFT               2  /* DCS_TRIG_DAC_WR_2 */
-#define WM8915_DCS_TRIG_DAC_WR_2_WIDTH               1  /* DCS_TRIG_DAC_WR_2 */
-#define WM8915_DCS_TRIG_DAC_WR_1                0x0002  /* DCS_TRIG_DAC_WR_1 */
-#define WM8915_DCS_TRIG_DAC_WR_1_MASK           0x0002  /* DCS_TRIG_DAC_WR_1 */
-#define WM8915_DCS_TRIG_DAC_WR_1_SHIFT               1  /* DCS_TRIG_DAC_WR_1 */
-#define WM8915_DCS_TRIG_DAC_WR_1_WIDTH               1  /* DCS_TRIG_DAC_WR_1 */
-#define WM8915_DCS_TRIG_DAC_WR_0                0x0001  /* DCS_TRIG_DAC_WR_0 */
-#define WM8915_DCS_TRIG_DAC_WR_0_MASK           0x0001  /* DCS_TRIG_DAC_WR_0 */
-#define WM8915_DCS_TRIG_DAC_WR_0_SHIFT               0  /* DCS_TRIG_DAC_WR_0 */
-#define WM8915_DCS_TRIG_DAC_WR_0_WIDTH               1  /* DCS_TRIG_DAC_WR_0 */
-
-/*
- * R82 (0x52) - DC Servo (3)
- */
-#define WM8915_DCS_TIMER_PERIOD_23_MASK         0x0F00  /* DCS_TIMER_PERIOD_23 - [11:8] */
-#define WM8915_DCS_TIMER_PERIOD_23_SHIFT             8  /* DCS_TIMER_PERIOD_23 - [11:8] */
-#define WM8915_DCS_TIMER_PERIOD_23_WIDTH             4  /* DCS_TIMER_PERIOD_23 - [11:8] */
-#define WM8915_DCS_TIMER_PERIOD_01_MASK         0x000F  /* DCS_TIMER_PERIOD_01 - [3:0] */
-#define WM8915_DCS_TIMER_PERIOD_01_SHIFT             0  /* DCS_TIMER_PERIOD_01 - [3:0] */
-#define WM8915_DCS_TIMER_PERIOD_01_WIDTH             4  /* DCS_TIMER_PERIOD_01 - [3:0] */
-
-/*
- * R84 (0x54) - DC Servo (5)
- */
-#define WM8915_DCS_SERIES_NO_23_MASK            0x7F00  /* DCS_SERIES_NO_23 - [14:8] */
-#define WM8915_DCS_SERIES_NO_23_SHIFT                8  /* DCS_SERIES_NO_23 - [14:8] */
-#define WM8915_DCS_SERIES_NO_23_WIDTH                7  /* DCS_SERIES_NO_23 - [14:8] */
-#define WM8915_DCS_SERIES_NO_01_MASK            0x007F  /* DCS_SERIES_NO_01 - [6:0] */
-#define WM8915_DCS_SERIES_NO_01_SHIFT                0  /* DCS_SERIES_NO_01 - [6:0] */
-#define WM8915_DCS_SERIES_NO_01_WIDTH                7  /* DCS_SERIES_NO_01 - [6:0] */
-
-/*
- * R85 (0x55) - DC Servo (6)
- */
-#define WM8915_DCS_DAC_WR_VAL_3_MASK            0xFF00  /* DCS_DAC_WR_VAL_3 - [15:8] */
-#define WM8915_DCS_DAC_WR_VAL_3_SHIFT                8  /* DCS_DAC_WR_VAL_3 - [15:8] */
-#define WM8915_DCS_DAC_WR_VAL_3_WIDTH                8  /* DCS_DAC_WR_VAL_3 - [15:8] */
-#define WM8915_DCS_DAC_WR_VAL_2_MASK            0x00FF  /* DCS_DAC_WR_VAL_2 - [7:0] */
-#define WM8915_DCS_DAC_WR_VAL_2_SHIFT                0  /* DCS_DAC_WR_VAL_2 - [7:0] */
-#define WM8915_DCS_DAC_WR_VAL_2_WIDTH                8  /* DCS_DAC_WR_VAL_2 - [7:0] */
-
-/*
- * R86 (0x56) - DC Servo (7)
- */
-#define WM8915_DCS_DAC_WR_VAL_1_MASK            0xFF00  /* DCS_DAC_WR_VAL_1 - [15:8] */
-#define WM8915_DCS_DAC_WR_VAL_1_SHIFT                8  /* DCS_DAC_WR_VAL_1 - [15:8] */
-#define WM8915_DCS_DAC_WR_VAL_1_WIDTH                8  /* DCS_DAC_WR_VAL_1 - [15:8] */
-#define WM8915_DCS_DAC_WR_VAL_0_MASK            0x00FF  /* DCS_DAC_WR_VAL_0 - [7:0] */
-#define WM8915_DCS_DAC_WR_VAL_0_SHIFT                0  /* DCS_DAC_WR_VAL_0 - [7:0] */
-#define WM8915_DCS_DAC_WR_VAL_0_WIDTH                8  /* DCS_DAC_WR_VAL_0 - [7:0] */
-
-/*
- * R87 (0x57) - DC Servo Readback 0
- */
-#define WM8915_DCS_CAL_COMPLETE_MASK            0x0F00  /* DCS_CAL_COMPLETE - [11:8] */
-#define WM8915_DCS_CAL_COMPLETE_SHIFT                8  /* DCS_CAL_COMPLETE - [11:8] */
-#define WM8915_DCS_CAL_COMPLETE_WIDTH                4  /* DCS_CAL_COMPLETE - [11:8] */
-#define WM8915_DCS_DAC_WR_COMPLETE_MASK         0x00F0  /* DCS_DAC_WR_COMPLETE - [7:4] */
-#define WM8915_DCS_DAC_WR_COMPLETE_SHIFT             4  /* DCS_DAC_WR_COMPLETE - [7:4] */
-#define WM8915_DCS_DAC_WR_COMPLETE_WIDTH             4  /* DCS_DAC_WR_COMPLETE - [7:4] */
-#define WM8915_DCS_STARTUP_COMPLETE_MASK        0x000F  /* DCS_STARTUP_COMPLETE - [3:0] */
-#define WM8915_DCS_STARTUP_COMPLETE_SHIFT            0  /* DCS_STARTUP_COMPLETE - [3:0] */
-#define WM8915_DCS_STARTUP_COMPLETE_WIDTH            4  /* DCS_STARTUP_COMPLETE - [3:0] */
-
-/*
- * R96 (0x60) - Analogue HP (1)
- */
-#define WM8915_HPOUT1L_RMV_SHORT                0x0080  /* HPOUT1L_RMV_SHORT */
-#define WM8915_HPOUT1L_RMV_SHORT_MASK           0x0080  /* HPOUT1L_RMV_SHORT */
-#define WM8915_HPOUT1L_RMV_SHORT_SHIFT               7  /* HPOUT1L_RMV_SHORT */
-#define WM8915_HPOUT1L_RMV_SHORT_WIDTH               1  /* HPOUT1L_RMV_SHORT */
-#define WM8915_HPOUT1L_OUTP                     0x0040  /* HPOUT1L_OUTP */
-#define WM8915_HPOUT1L_OUTP_MASK                0x0040  /* HPOUT1L_OUTP */
-#define WM8915_HPOUT1L_OUTP_SHIFT                    6  /* HPOUT1L_OUTP */
-#define WM8915_HPOUT1L_OUTP_WIDTH                    1  /* HPOUT1L_OUTP */
-#define WM8915_HPOUT1L_DLY                      0x0020  /* HPOUT1L_DLY */
-#define WM8915_HPOUT1L_DLY_MASK                 0x0020  /* HPOUT1L_DLY */
-#define WM8915_HPOUT1L_DLY_SHIFT                     5  /* HPOUT1L_DLY */
-#define WM8915_HPOUT1L_DLY_WIDTH                     1  /* HPOUT1L_DLY */
-#define WM8915_HPOUT1R_RMV_SHORT                0x0008  /* HPOUT1R_RMV_SHORT */
-#define WM8915_HPOUT1R_RMV_SHORT_MASK           0x0008  /* HPOUT1R_RMV_SHORT */
-#define WM8915_HPOUT1R_RMV_SHORT_SHIFT               3  /* HPOUT1R_RMV_SHORT */
-#define WM8915_HPOUT1R_RMV_SHORT_WIDTH               1  /* HPOUT1R_RMV_SHORT */
-#define WM8915_HPOUT1R_OUTP                     0x0004  /* HPOUT1R_OUTP */
-#define WM8915_HPOUT1R_OUTP_MASK                0x0004  /* HPOUT1R_OUTP */
-#define WM8915_HPOUT1R_OUTP_SHIFT                    2  /* HPOUT1R_OUTP */
-#define WM8915_HPOUT1R_OUTP_WIDTH                    1  /* HPOUT1R_OUTP */
-#define WM8915_HPOUT1R_DLY                      0x0002  /* HPOUT1R_DLY */
-#define WM8915_HPOUT1R_DLY_MASK                 0x0002  /* HPOUT1R_DLY */
-#define WM8915_HPOUT1R_DLY_SHIFT                     1  /* HPOUT1R_DLY */
-#define WM8915_HPOUT1R_DLY_WIDTH                     1  /* HPOUT1R_DLY */
-
-/*
- * R97 (0x61) - Analogue HP (2)
- */
-#define WM8915_HPOUT2L_RMV_SHORT                0x0080  /* HPOUT2L_RMV_SHORT */
-#define WM8915_HPOUT2L_RMV_SHORT_MASK           0x0080  /* HPOUT2L_RMV_SHORT */
-#define WM8915_HPOUT2L_RMV_SHORT_SHIFT               7  /* HPOUT2L_RMV_SHORT */
-#define WM8915_HPOUT2L_RMV_SHORT_WIDTH               1  /* HPOUT2L_RMV_SHORT */
-#define WM8915_HPOUT2L_OUTP                     0x0040  /* HPOUT2L_OUTP */
-#define WM8915_HPOUT2L_OUTP_MASK                0x0040  /* HPOUT2L_OUTP */
-#define WM8915_HPOUT2L_OUTP_SHIFT                    6  /* HPOUT2L_OUTP */
-#define WM8915_HPOUT2L_OUTP_WIDTH                    1  /* HPOUT2L_OUTP */
-#define WM8915_HPOUT2L_DLY                      0x0020  /* HPOUT2L_DLY */
-#define WM8915_HPOUT2L_DLY_MASK                 0x0020  /* HPOUT2L_DLY */
-#define WM8915_HPOUT2L_DLY_SHIFT                     5  /* HPOUT2L_DLY */
-#define WM8915_HPOUT2L_DLY_WIDTH                     1  /* HPOUT2L_DLY */
-#define WM8915_HPOUT2R_RMV_SHORT                0x0008  /* HPOUT2R_RMV_SHORT */
-#define WM8915_HPOUT2R_RMV_SHORT_MASK           0x0008  /* HPOUT2R_RMV_SHORT */
-#define WM8915_HPOUT2R_RMV_SHORT_SHIFT               3  /* HPOUT2R_RMV_SHORT */
-#define WM8915_HPOUT2R_RMV_SHORT_WIDTH               1  /* HPOUT2R_RMV_SHORT */
-#define WM8915_HPOUT2R_OUTP                     0x0004  /* HPOUT2R_OUTP */
-#define WM8915_HPOUT2R_OUTP_MASK                0x0004  /* HPOUT2R_OUTP */
-#define WM8915_HPOUT2R_OUTP_SHIFT                    2  /* HPOUT2R_OUTP */
-#define WM8915_HPOUT2R_OUTP_WIDTH                    1  /* HPOUT2R_OUTP */
-#define WM8915_HPOUT2R_DLY                      0x0002  /* HPOUT2R_DLY */
-#define WM8915_HPOUT2R_DLY_MASK                 0x0002  /* HPOUT2R_DLY */
-#define WM8915_HPOUT2R_DLY_SHIFT                     1  /* HPOUT2R_DLY */
-#define WM8915_HPOUT2R_DLY_WIDTH                     1  /* HPOUT2R_DLY */
-
-/*
- * R256 (0x100) - Chip Revision
- */
-#define WM8915_CHIP_REV_MASK                    0x000F  /* CHIP_REV - [3:0] */
-#define WM8915_CHIP_REV_SHIFT                        0  /* CHIP_REV - [3:0] */
-#define WM8915_CHIP_REV_WIDTH                        4  /* CHIP_REV - [3:0] */
-
-/*
- * R257 (0x101) - Control Interface (1)
- */
-#define WM8915_AUTO_INC                         0x0004  /* AUTO_INC */
-#define WM8915_AUTO_INC_MASK                    0x0004  /* AUTO_INC */
-#define WM8915_AUTO_INC_SHIFT                        2  /* AUTO_INC */
-#define WM8915_AUTO_INC_WIDTH                        1  /* AUTO_INC */
-
-/*
- * R272 (0x110) - Write Sequencer Ctrl (1)
- */
-#define WM8915_WSEQ_ENA                         0x8000  /* WSEQ_ENA */
-#define WM8915_WSEQ_ENA_MASK                    0x8000  /* WSEQ_ENA */
-#define WM8915_WSEQ_ENA_SHIFT                       15  /* WSEQ_ENA */
-#define WM8915_WSEQ_ENA_WIDTH                        1  /* WSEQ_ENA */
-#define WM8915_WSEQ_ABORT                       0x0200  /* WSEQ_ABORT */
-#define WM8915_WSEQ_ABORT_MASK                  0x0200  /* WSEQ_ABORT */
-#define WM8915_WSEQ_ABORT_SHIFT                      9  /* WSEQ_ABORT */
-#define WM8915_WSEQ_ABORT_WIDTH                      1  /* WSEQ_ABORT */
-#define WM8915_WSEQ_START                       0x0100  /* WSEQ_START */
-#define WM8915_WSEQ_START_MASK                  0x0100  /* WSEQ_START */
-#define WM8915_WSEQ_START_SHIFT                      8  /* WSEQ_START */
-#define WM8915_WSEQ_START_WIDTH                      1  /* WSEQ_START */
-#define WM8915_WSEQ_START_INDEX_MASK            0x007F  /* WSEQ_START_INDEX - [6:0] */
-#define WM8915_WSEQ_START_INDEX_SHIFT                0  /* WSEQ_START_INDEX - [6:0] */
-#define WM8915_WSEQ_START_INDEX_WIDTH                7  /* WSEQ_START_INDEX - [6:0] */
-
-/*
- * R273 (0x111) - Write Sequencer Ctrl (2)
- */
-#define WM8915_WSEQ_BUSY                        0x0100  /* WSEQ_BUSY */
-#define WM8915_WSEQ_BUSY_MASK                   0x0100  /* WSEQ_BUSY */
-#define WM8915_WSEQ_BUSY_SHIFT                       8  /* WSEQ_BUSY */
-#define WM8915_WSEQ_BUSY_WIDTH                       1  /* WSEQ_BUSY */
-#define WM8915_WSEQ_CURRENT_INDEX_MASK          0x007F  /* WSEQ_CURRENT_INDEX - [6:0] */
-#define WM8915_WSEQ_CURRENT_INDEX_SHIFT              0  /* WSEQ_CURRENT_INDEX - [6:0] */
-#define WM8915_WSEQ_CURRENT_INDEX_WIDTH              7  /* WSEQ_CURRENT_INDEX - [6:0] */
-
-/*
- * R512 (0x200) - AIF Clocking (1)
- */
-#define WM8915_SYSCLK_SRC_MASK                  0x0018  /* SYSCLK_SRC - [4:3] */
-#define WM8915_SYSCLK_SRC_SHIFT                      3  /* SYSCLK_SRC - [4:3] */
-#define WM8915_SYSCLK_SRC_WIDTH                      2  /* SYSCLK_SRC - [4:3] */
-#define WM8915_SYSCLK_INV                       0x0004  /* SYSCLK_INV */
-#define WM8915_SYSCLK_INV_MASK                  0x0004  /* SYSCLK_INV */
-#define WM8915_SYSCLK_INV_SHIFT                      2  /* SYSCLK_INV */
-#define WM8915_SYSCLK_INV_WIDTH                      1  /* SYSCLK_INV */
-#define WM8915_SYSCLK_DIV                       0x0002  /* SYSCLK_DIV */
-#define WM8915_SYSCLK_DIV_MASK                  0x0002  /* SYSCLK_DIV */
-#define WM8915_SYSCLK_DIV_SHIFT                      1  /* SYSCLK_DIV */
-#define WM8915_SYSCLK_DIV_WIDTH                      1  /* SYSCLK_DIV */
-#define WM8915_SYSCLK_ENA                       0x0001  /* SYSCLK_ENA */
-#define WM8915_SYSCLK_ENA_MASK                  0x0001  /* SYSCLK_ENA */
-#define WM8915_SYSCLK_ENA_SHIFT                      0  /* SYSCLK_ENA */
-#define WM8915_SYSCLK_ENA_WIDTH                      1  /* SYSCLK_ENA */
-
-/*
- * R513 (0x201) - AIF Clocking (2)
- */
-#define WM8915_DSP2_DIV_MASK                    0x0018  /* DSP2_DIV - [4:3] */
-#define WM8915_DSP2_DIV_SHIFT                        3  /* DSP2_DIV - [4:3] */
-#define WM8915_DSP2_DIV_WIDTH                        2  /* DSP2_DIV - [4:3] */
-#define WM8915_DSP1_DIV_MASK                    0x0003  /* DSP1_DIV - [1:0] */
-#define WM8915_DSP1_DIV_SHIFT                        0  /* DSP1_DIV - [1:0] */
-#define WM8915_DSP1_DIV_WIDTH                        2  /* DSP1_DIV - [1:0] */
-
-/*
- * R520 (0x208) - Clocking (1)
- */
-#define WM8915_LFCLK_ENA                        0x0020  /* LFCLK_ENA */
-#define WM8915_LFCLK_ENA_MASK                   0x0020  /* LFCLK_ENA */
-#define WM8915_LFCLK_ENA_SHIFT                       5  /* LFCLK_ENA */
-#define WM8915_LFCLK_ENA_WIDTH                       1  /* LFCLK_ENA */
-#define WM8915_TOCLK_ENA                        0x0010  /* TOCLK_ENA */
-#define WM8915_TOCLK_ENA_MASK                   0x0010  /* TOCLK_ENA */
-#define WM8915_TOCLK_ENA_SHIFT                       4  /* TOCLK_ENA */
-#define WM8915_TOCLK_ENA_WIDTH                       1  /* TOCLK_ENA */
-#define WM8915_AIFCLK_ENA                       0x0004  /* AIFCLK_ENA */
-#define WM8915_AIFCLK_ENA_MASK                  0x0004  /* AIFCLK_ENA */
-#define WM8915_AIFCLK_ENA_SHIFT                      2  /* AIFCLK_ENA */
-#define WM8915_AIFCLK_ENA_WIDTH                      1  /* AIFCLK_ENA */
-#define WM8915_SYSDSPCLK_ENA                    0x0002  /* SYSDSPCLK_ENA */
-#define WM8915_SYSDSPCLK_ENA_MASK               0x0002  /* SYSDSPCLK_ENA */
-#define WM8915_SYSDSPCLK_ENA_SHIFT                   1  /* SYSDSPCLK_ENA */
-#define WM8915_SYSDSPCLK_ENA_WIDTH                   1  /* SYSDSPCLK_ENA */
-
-/*
- * R521 (0x209) - Clocking (2)
- */
-#define WM8915_TOCLK_DIV_MASK                   0x0700  /* TOCLK_DIV - [10:8] */
-#define WM8915_TOCLK_DIV_SHIFT                       8  /* TOCLK_DIV - [10:8] */
-#define WM8915_TOCLK_DIV_WIDTH                       3  /* TOCLK_DIV - [10:8] */
-#define WM8915_DBCLK_DIV_MASK                   0x00F0  /* DBCLK_DIV - [7:4] */
-#define WM8915_DBCLK_DIV_SHIFT                       4  /* DBCLK_DIV - [7:4] */
-#define WM8915_DBCLK_DIV_WIDTH                       4  /* DBCLK_DIV - [7:4] */
-#define WM8915_OPCLK_DIV_MASK                   0x0007  /* OPCLK_DIV - [2:0] */
-#define WM8915_OPCLK_DIV_SHIFT                       0  /* OPCLK_DIV - [2:0] */
-#define WM8915_OPCLK_DIV_WIDTH                       3  /* OPCLK_DIV - [2:0] */
-
-/*
- * R528 (0x210) - AIF Rate
- */
-#define WM8915_SYSCLK_RATE                      0x0001  /* SYSCLK_RATE */
-#define WM8915_SYSCLK_RATE_MASK                 0x0001  /* SYSCLK_RATE */
-#define WM8915_SYSCLK_RATE_SHIFT                     0  /* SYSCLK_RATE */
-#define WM8915_SYSCLK_RATE_WIDTH                     1  /* SYSCLK_RATE */
-
-/*
- * R544 (0x220) - FLL Control (1)
- */
-#define WM8915_FLL_OSC_ENA                      0x0002  /* FLL_OSC_ENA */
-#define WM8915_FLL_OSC_ENA_MASK                 0x0002  /* FLL_OSC_ENA */
-#define WM8915_FLL_OSC_ENA_SHIFT                     1  /* FLL_OSC_ENA */
-#define WM8915_FLL_OSC_ENA_WIDTH                     1  /* FLL_OSC_ENA */
-#define WM8915_FLL_ENA                          0x0001  /* FLL_ENA */
-#define WM8915_FLL_ENA_MASK                     0x0001  /* FLL_ENA */
-#define WM8915_FLL_ENA_SHIFT                         0  /* FLL_ENA */
-#define WM8915_FLL_ENA_WIDTH                         1  /* FLL_ENA */
-
-/*
- * R545 (0x221) - FLL Control (2)
- */
-#define WM8915_FLL_OUTDIV_MASK                  0x3F00  /* FLL_OUTDIV - [13:8] */
-#define WM8915_FLL_OUTDIV_SHIFT                      8  /* FLL_OUTDIV - [13:8] */
-#define WM8915_FLL_OUTDIV_WIDTH                      6  /* FLL_OUTDIV - [13:8] */
-#define WM8915_FLL_FRATIO_MASK                  0x0007  /* FLL_FRATIO - [2:0] */
-#define WM8915_FLL_FRATIO_SHIFT                      0  /* FLL_FRATIO - [2:0] */
-#define WM8915_FLL_FRATIO_WIDTH                      3  /* FLL_FRATIO - [2:0] */
-
-/*
- * R546 (0x222) - FLL Control (3)
- */
-#define WM8915_FLL_THETA_MASK                   0xFFFF  /* FLL_THETA - [15:0] */
-#define WM8915_FLL_THETA_SHIFT                       0  /* FLL_THETA - [15:0] */
-#define WM8915_FLL_THETA_WIDTH                      16  /* FLL_THETA - [15:0] */
-
-/*
- * R547 (0x223) - FLL Control (4)
- */
-#define WM8915_FLL_N_MASK                       0x7FE0  /* FLL_N - [14:5] */
-#define WM8915_FLL_N_SHIFT                           5  /* FLL_N - [14:5] */
-#define WM8915_FLL_N_WIDTH                          10  /* FLL_N - [14:5] */
-#define WM8915_FLL_LOOP_GAIN_MASK               0x000F  /* FLL_LOOP_GAIN - [3:0] */
-#define WM8915_FLL_LOOP_GAIN_SHIFT                   0  /* FLL_LOOP_GAIN - [3:0] */
-#define WM8915_FLL_LOOP_GAIN_WIDTH                   4  /* FLL_LOOP_GAIN - [3:0] */
-
-/*
- * R548 (0x224) - FLL Control (5)
- */
-#define WM8915_FLL_FRC_NCO_VAL_MASK             0x1F80  /* FLL_FRC_NCO_VAL - [12:7] */
-#define WM8915_FLL_FRC_NCO_VAL_SHIFT                 7  /* FLL_FRC_NCO_VAL - [12:7] */
-#define WM8915_FLL_FRC_NCO_VAL_WIDTH                 6  /* FLL_FRC_NCO_VAL - [12:7] */
-#define WM8915_FLL_FRC_NCO                      0x0040  /* FLL_FRC_NCO */
-#define WM8915_FLL_FRC_NCO_MASK                 0x0040  /* FLL_FRC_NCO */
-#define WM8915_FLL_FRC_NCO_SHIFT                     6  /* FLL_FRC_NCO */
-#define WM8915_FLL_FRC_NCO_WIDTH                     1  /* FLL_FRC_NCO */
-#define WM8915_FLL_REFCLK_DIV_MASK              0x0018  /* FLL_REFCLK_DIV - [4:3] */
-#define WM8915_FLL_REFCLK_DIV_SHIFT                  3  /* FLL_REFCLK_DIV - [4:3] */
-#define WM8915_FLL_REFCLK_DIV_WIDTH                  2  /* FLL_REFCLK_DIV - [4:3] */
-#define WM8915_FLL_REF_FREQ                     0x0004  /* FLL_REF_FREQ */
-#define WM8915_FLL_REF_FREQ_MASK                0x0004  /* FLL_REF_FREQ */
-#define WM8915_FLL_REF_FREQ_SHIFT                    2  /* FLL_REF_FREQ */
-#define WM8915_FLL_REF_FREQ_WIDTH                    1  /* FLL_REF_FREQ */
-#define WM8915_FLL_REFCLK_SRC_MASK              0x0003  /* FLL_REFCLK_SRC - [1:0] */
-#define WM8915_FLL_REFCLK_SRC_SHIFT                  0  /* FLL_REFCLK_SRC - [1:0] */
-#define WM8915_FLL_REFCLK_SRC_WIDTH                  2  /* FLL_REFCLK_SRC - [1:0] */
-
-/*
- * R549 (0x225) - FLL Control (6)
- */
-#define WM8915_FLL_REFCLK_SRC_STS_MASK          0x000C  /* FLL_REFCLK_SRC_STS - [3:2] */
-#define WM8915_FLL_REFCLK_SRC_STS_SHIFT              2  /* FLL_REFCLK_SRC_STS - [3:2] */
-#define WM8915_FLL_REFCLK_SRC_STS_WIDTH              2  /* FLL_REFCLK_SRC_STS - [3:2] */
-#define WM8915_FLL_SWITCH_CLK                   0x0001  /* FLL_SWITCH_CLK */
-#define WM8915_FLL_SWITCH_CLK_MASK              0x0001  /* FLL_SWITCH_CLK */
-#define WM8915_FLL_SWITCH_CLK_SHIFT                  0  /* FLL_SWITCH_CLK */
-#define WM8915_FLL_SWITCH_CLK_WIDTH                  1  /* FLL_SWITCH_CLK */
-
-/*
- * R550 (0x226) - FLL EFS 1
- */
-#define WM8915_FLL_LAMBDA_MASK                  0xFFFF  /* FLL_LAMBDA - [15:0] */
-#define WM8915_FLL_LAMBDA_SHIFT                      0  /* FLL_LAMBDA - [15:0] */
-#define WM8915_FLL_LAMBDA_WIDTH                     16  /* FLL_LAMBDA - [15:0] */
-
-/*
- * R551 (0x227) - FLL EFS 2
- */
-#define WM8915_FLL_LFSR_SEL_MASK                0x0006  /* FLL_LFSR_SEL - [2:1] */
-#define WM8915_FLL_LFSR_SEL_SHIFT                    1  /* FLL_LFSR_SEL - [2:1] */
-#define WM8915_FLL_LFSR_SEL_WIDTH                    2  /* FLL_LFSR_SEL - [2:1] */
-#define WM8915_FLL_EFS_ENA                      0x0001  /* FLL_EFS_ENA */
-#define WM8915_FLL_EFS_ENA_MASK                 0x0001  /* FLL_EFS_ENA */
-#define WM8915_FLL_EFS_ENA_SHIFT                     0  /* FLL_EFS_ENA */
-#define WM8915_FLL_EFS_ENA_WIDTH                     1  /* FLL_EFS_ENA */
-
-/*
- * R768 (0x300) - AIF1 Control
- */
-#define WM8915_AIF1_TRI                         0x0004  /* AIF1_TRI */
-#define WM8915_AIF1_TRI_MASK                    0x0004  /* AIF1_TRI */
-#define WM8915_AIF1_TRI_SHIFT                        2  /* AIF1_TRI */
-#define WM8915_AIF1_TRI_WIDTH                        1  /* AIF1_TRI */
-#define WM8915_AIF1_FMT_MASK                    0x0003  /* AIF1_FMT - [1:0] */
-#define WM8915_AIF1_FMT_SHIFT                        0  /* AIF1_FMT - [1:0] */
-#define WM8915_AIF1_FMT_WIDTH                        2  /* AIF1_FMT - [1:0] */
-
-/*
- * R769 (0x301) - AIF1 BCLK
- */
-#define WM8915_AIF1_BCLK_INV                    0x0400  /* AIF1_BCLK_INV */
-#define WM8915_AIF1_BCLK_INV_MASK               0x0400  /* AIF1_BCLK_INV */
-#define WM8915_AIF1_BCLK_INV_SHIFT                  10  /* AIF1_BCLK_INV */
-#define WM8915_AIF1_BCLK_INV_WIDTH                   1  /* AIF1_BCLK_INV */
-#define WM8915_AIF1_BCLK_FRC                    0x0200  /* AIF1_BCLK_FRC */
-#define WM8915_AIF1_BCLK_FRC_MASK               0x0200  /* AIF1_BCLK_FRC */
-#define WM8915_AIF1_BCLK_FRC_SHIFT                   9  /* AIF1_BCLK_FRC */
-#define WM8915_AIF1_BCLK_FRC_WIDTH                   1  /* AIF1_BCLK_FRC */
-#define WM8915_AIF1_BCLK_MSTR                   0x0100  /* AIF1_BCLK_MSTR */
-#define WM8915_AIF1_BCLK_MSTR_MASK              0x0100  /* AIF1_BCLK_MSTR */
-#define WM8915_AIF1_BCLK_MSTR_SHIFT                  8  /* AIF1_BCLK_MSTR */
-#define WM8915_AIF1_BCLK_MSTR_WIDTH                  1  /* AIF1_BCLK_MSTR */
-#define WM8915_AIF1_BCLK_DIV_MASK               0x000F  /* AIF1_BCLK_DIV - [3:0] */
-#define WM8915_AIF1_BCLK_DIV_SHIFT                   0  /* AIF1_BCLK_DIV - [3:0] */
-#define WM8915_AIF1_BCLK_DIV_WIDTH                   4  /* AIF1_BCLK_DIV - [3:0] */
-
-/*
- * R770 (0x302) - AIF1 TX LRCLK(1)
- */
-#define WM8915_AIF1TX_RATE_MASK                 0x07FF  /* AIF1TX_RATE - [10:0] */
-#define WM8915_AIF1TX_RATE_SHIFT                     0  /* AIF1TX_RATE - [10:0] */
-#define WM8915_AIF1TX_RATE_WIDTH                    11  /* AIF1TX_RATE - [10:0] */
-
-/*
- * R771 (0x303) - AIF1 TX LRCLK(2)
- */
-#define WM8915_AIF1TX_LRCLK_MODE                0x0008  /* AIF1TX_LRCLK_MODE */
-#define WM8915_AIF1TX_LRCLK_MODE_MASK           0x0008  /* AIF1TX_LRCLK_MODE */
-#define WM8915_AIF1TX_LRCLK_MODE_SHIFT               3  /* AIF1TX_LRCLK_MODE */
-#define WM8915_AIF1TX_LRCLK_MODE_WIDTH               1  /* AIF1TX_LRCLK_MODE */
-#define WM8915_AIF1TX_LRCLK_INV                 0x0004  /* AIF1TX_LRCLK_INV */
-#define WM8915_AIF1TX_LRCLK_INV_MASK            0x0004  /* AIF1TX_LRCLK_INV */
-#define WM8915_AIF1TX_LRCLK_INV_SHIFT                2  /* AIF1TX_LRCLK_INV */
-#define WM8915_AIF1TX_LRCLK_INV_WIDTH                1  /* AIF1TX_LRCLK_INV */
-#define WM8915_AIF1TX_LRCLK_FRC                 0x0002  /* AIF1TX_LRCLK_FRC */
-#define WM8915_AIF1TX_LRCLK_FRC_MASK            0x0002  /* AIF1TX_LRCLK_FRC */
-#define WM8915_AIF1TX_LRCLK_FRC_SHIFT                1  /* AIF1TX_LRCLK_FRC */
-#define WM8915_AIF1TX_LRCLK_FRC_WIDTH                1  /* AIF1TX_LRCLK_FRC */
-#define WM8915_AIF1TX_LRCLK_MSTR                0x0001  /* AIF1TX_LRCLK_MSTR */
-#define WM8915_AIF1TX_LRCLK_MSTR_MASK           0x0001  /* AIF1TX_LRCLK_MSTR */
-#define WM8915_AIF1TX_LRCLK_MSTR_SHIFT               0  /* AIF1TX_LRCLK_MSTR */
-#define WM8915_AIF1TX_LRCLK_MSTR_WIDTH               1  /* AIF1TX_LRCLK_MSTR */
-
-/*
- * R772 (0x304) - AIF1 RX LRCLK(1)
- */
-#define WM8915_AIF1RX_RATE_MASK                 0x07FF  /* AIF1RX_RATE - [10:0] */
-#define WM8915_AIF1RX_RATE_SHIFT                     0  /* AIF1RX_RATE - [10:0] */
-#define WM8915_AIF1RX_RATE_WIDTH                    11  /* AIF1RX_RATE - [10:0] */
-
-/*
- * R773 (0x305) - AIF1 RX LRCLK(2)
- */
-#define WM8915_AIF1RX_LRCLK_INV                 0x0004  /* AIF1RX_LRCLK_INV */
-#define WM8915_AIF1RX_LRCLK_INV_MASK            0x0004  /* AIF1RX_LRCLK_INV */
-#define WM8915_AIF1RX_LRCLK_INV_SHIFT                2  /* AIF1RX_LRCLK_INV */
-#define WM8915_AIF1RX_LRCLK_INV_WIDTH                1  /* AIF1RX_LRCLK_INV */
-#define WM8915_AIF1RX_LRCLK_FRC                 0x0002  /* AIF1RX_LRCLK_FRC */
-#define WM8915_AIF1RX_LRCLK_FRC_MASK            0x0002  /* AIF1RX_LRCLK_FRC */
-#define WM8915_AIF1RX_LRCLK_FRC_SHIFT                1  /* AIF1RX_LRCLK_FRC */
-#define WM8915_AIF1RX_LRCLK_FRC_WIDTH                1  /* AIF1RX_LRCLK_FRC */
-#define WM8915_AIF1RX_LRCLK_MSTR                0x0001  /* AIF1RX_LRCLK_MSTR */
-#define WM8915_AIF1RX_LRCLK_MSTR_MASK           0x0001  /* AIF1RX_LRCLK_MSTR */
-#define WM8915_AIF1RX_LRCLK_MSTR_SHIFT               0  /* AIF1RX_LRCLK_MSTR */
-#define WM8915_AIF1RX_LRCLK_MSTR_WIDTH               1  /* AIF1RX_LRCLK_MSTR */
-
-/*
- * R774 (0x306) - AIF1TX Data Configuration (1)
- */
-#define WM8915_AIF1TX_WL_MASK                   0xFF00  /* AIF1TX_WL - [15:8] */
-#define WM8915_AIF1TX_WL_SHIFT                       8  /* AIF1TX_WL - [15:8] */
-#define WM8915_AIF1TX_WL_WIDTH                       8  /* AIF1TX_WL - [15:8] */
-#define WM8915_AIF1TX_SLOT_LEN_MASK             0x00FF  /* AIF1TX_SLOT_LEN - [7:0] */
-#define WM8915_AIF1TX_SLOT_LEN_SHIFT                 0  /* AIF1TX_SLOT_LEN - [7:0] */
-#define WM8915_AIF1TX_SLOT_LEN_WIDTH                 8  /* AIF1TX_SLOT_LEN - [7:0] */
-
-/*
- * R775 (0x307) - AIF1TX Data Configuration (2)
- */
-#define WM8915_AIF1TX_DAT_TRI                   0x0001  /* AIF1TX_DAT_TRI */
-#define WM8915_AIF1TX_DAT_TRI_MASK              0x0001  /* AIF1TX_DAT_TRI */
-#define WM8915_AIF1TX_DAT_TRI_SHIFT                  0  /* AIF1TX_DAT_TRI */
-#define WM8915_AIF1TX_DAT_TRI_WIDTH                  1  /* AIF1TX_DAT_TRI */
-
-/*
- * R776 (0x308) - AIF1RX Data Configuration
- */
-#define WM8915_AIF1RX_WL_MASK                   0xFF00  /* AIF1RX_WL - [15:8] */
-#define WM8915_AIF1RX_WL_SHIFT                       8  /* AIF1RX_WL - [15:8] */
-#define WM8915_AIF1RX_WL_WIDTH                       8  /* AIF1RX_WL - [15:8] */
-#define WM8915_AIF1RX_SLOT_LEN_MASK             0x00FF  /* AIF1RX_SLOT_LEN - [7:0] */
-#define WM8915_AIF1RX_SLOT_LEN_SHIFT                 0  /* AIF1RX_SLOT_LEN - [7:0] */
-#define WM8915_AIF1RX_SLOT_LEN_WIDTH                 8  /* AIF1RX_SLOT_LEN - [7:0] */
-
-/*
- * R777 (0x309) - AIF1TX Channel 0 Configuration
- */
-#define WM8915_AIF1TX_CHAN0_DAT_INV             0x8000  /* AIF1TX_CHAN0_DAT_INV */
-#define WM8915_AIF1TX_CHAN0_DAT_INV_MASK        0x8000  /* AIF1TX_CHAN0_DAT_INV */
-#define WM8915_AIF1TX_CHAN0_DAT_INV_SHIFT           15  /* AIF1TX_CHAN0_DAT_INV */
-#define WM8915_AIF1TX_CHAN0_DAT_INV_WIDTH            1  /* AIF1TX_CHAN0_DAT_INV */
-#define WM8915_AIF1TX_CHAN0_SPACING_MASK        0x7E00  /* AIF1TX_CHAN0_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN0_SPACING_SHIFT            9  /* AIF1TX_CHAN0_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN0_SPACING_WIDTH            6  /* AIF1TX_CHAN0_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN0_SLOTS_MASK          0x01C0  /* AIF1TX_CHAN0_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN0_SLOTS_SHIFT              6  /* AIF1TX_CHAN0_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN0_SLOTS_WIDTH              3  /* AIF1TX_CHAN0_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN0_START_SLOT_MASK     0x003F  /* AIF1TX_CHAN0_START_SLOT - [5:0] */
-#define WM8915_AIF1TX_CHAN0_START_SLOT_SHIFT         0  /* AIF1TX_CHAN0_START_SLOT - [5:0] */
-#define WM8915_AIF1TX_CHAN0_START_SLOT_WIDTH         6  /* AIF1TX_CHAN0_START_SLOT - [5:0] */
-
-/*
- * R778 (0x30A) - AIF1TX Channel 1 Configuration
- */
-#define WM8915_AIF1TX_CHAN1_DAT_INV             0x8000  /* AIF1TX_CHAN1_DAT_INV */
-#define WM8915_AIF1TX_CHAN1_DAT_INV_MASK        0x8000  /* AIF1TX_CHAN1_DAT_INV */
-#define WM8915_AIF1TX_CHAN1_DAT_INV_SHIFT           15  /* AIF1TX_CHAN1_DAT_INV */
-#define WM8915_AIF1TX_CHAN1_DAT_INV_WIDTH            1  /* AIF1TX_CHAN1_DAT_INV */
-#define WM8915_AIF1TX_CHAN1_SPACING_MASK        0x7E00  /* AIF1TX_CHAN1_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN1_SPACING_SHIFT            9  /* AIF1TX_CHAN1_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN1_SPACING_WIDTH            6  /* AIF1TX_CHAN1_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN1_SLOTS_MASK          0x01C0  /* AIF1TX_CHAN1_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN1_SLOTS_SHIFT              6  /* AIF1TX_CHAN1_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN1_SLOTS_WIDTH              3  /* AIF1TX_CHAN1_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN1_START_SLOT_MASK     0x003F  /* AIF1TX_CHAN1_START_SLOT - [5:0] */
-#define WM8915_AIF1TX_CHAN1_START_SLOT_SHIFT         0  /* AIF1TX_CHAN1_START_SLOT - [5:0] */
-#define WM8915_AIF1TX_CHAN1_START_SLOT_WIDTH         6  /* AIF1TX_CHAN1_START_SLOT - [5:0] */
-
-/*
- * R779 (0x30B) - AIF1TX Channel 2 Configuration
- */
-#define WM8915_AIF1TX_CHAN2_DAT_INV             0x8000  /* AIF1TX_CHAN2_DAT_INV */
-#define WM8915_AIF1TX_CHAN2_DAT_INV_MASK        0x8000  /* AIF1TX_CHAN2_DAT_INV */
-#define WM8915_AIF1TX_CHAN2_DAT_INV_SHIFT           15  /* AIF1TX_CHAN2_DAT_INV */
-#define WM8915_AIF1TX_CHAN2_DAT_INV_WIDTH            1  /* AIF1TX_CHAN2_DAT_INV */
-#define WM8915_AIF1TX_CHAN2_SPACING_MASK        0x7E00  /* AIF1TX_CHAN2_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN2_SPACING_SHIFT            9  /* AIF1TX_CHAN2_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN2_SPACING_WIDTH            6  /* AIF1TX_CHAN2_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN2_SLOTS_MASK          0x01C0  /* AIF1TX_CHAN2_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN2_SLOTS_SHIFT              6  /* AIF1TX_CHAN2_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN2_SLOTS_WIDTH              3  /* AIF1TX_CHAN2_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN2_START_SLOT_MASK     0x003F  /* AIF1TX_CHAN2_START_SLOT - [5:0] */
-#define WM8915_AIF1TX_CHAN2_START_SLOT_SHIFT         0  /* AIF1TX_CHAN2_START_SLOT - [5:0] */
-#define WM8915_AIF1TX_CHAN2_START_SLOT_WIDTH         6  /* AIF1TX_CHAN2_START_SLOT - [5:0] */
-
-/*
- * R780 (0x30C) - AIF1TX Channel 3 Configuration
- */
-#define WM8915_AIF1TX_CHAN3_DAT_INV             0x8000  /* AIF1TX_CHAN3_DAT_INV */
-#define WM8915_AIF1TX_CHAN3_DAT_INV_MASK        0x8000  /* AIF1TX_CHAN3_DAT_INV */
-#define WM8915_AIF1TX_CHAN3_DAT_INV_SHIFT           15  /* AIF1TX_CHAN3_DAT_INV */
-#define WM8915_AIF1TX_CHAN3_DAT_INV_WIDTH            1  /* AIF1TX_CHAN3_DAT_INV */
-#define WM8915_AIF1TX_CHAN3_SPACING_MASK        0x7E00  /* AIF1TX_CHAN3_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN3_SPACING_SHIFT            9  /* AIF1TX_CHAN3_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN3_SPACING_WIDTH            6  /* AIF1TX_CHAN3_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN3_SLOTS_MASK          0x01C0  /* AIF1TX_CHAN3_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN3_SLOTS_SHIFT              6  /* AIF1TX_CHAN3_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN3_SLOTS_WIDTH              3  /* AIF1TX_CHAN3_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN3_START_SLOT_MASK     0x003F  /* AIF1TX_CHAN3_START_SLOT - [5:0] */
-#define WM8915_AIF1TX_CHAN3_START_SLOT_SHIFT         0  /* AIF1TX_CHAN3_START_SLOT - [5:0] */
-#define WM8915_AIF1TX_CHAN3_START_SLOT_WIDTH         6  /* AIF1TX_CHAN3_START_SLOT - [5:0] */
-
-/*
- * R781 (0x30D) - AIF1TX Channel 4 Configuration
- */
-#define WM8915_AIF1TX_CHAN4_DAT_INV             0x8000  /* AIF1TX_CHAN4_DAT_INV */
-#define WM8915_AIF1TX_CHAN4_DAT_INV_MASK        0x8000  /* AIF1TX_CHAN4_DAT_INV */
-#define WM8915_AIF1TX_CHAN4_DAT_INV_SHIFT           15  /* AIF1TX_CHAN4_DAT_INV */
-#define WM8915_AIF1TX_CHAN4_DAT_INV_WIDTH            1  /* AIF1TX_CHAN4_DAT_INV */
-#define WM8915_AIF1TX_CHAN4_SPACING_MASK        0x7E00  /* AIF1TX_CHAN4_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN4_SPACING_SHIFT            9  /* AIF1TX_CHAN4_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN4_SPACING_WIDTH            6  /* AIF1TX_CHAN4_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN4_SLOTS_MASK          0x01C0  /* AIF1TX_CHAN4_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN4_SLOTS_SHIFT              6  /* AIF1TX_CHAN4_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN4_SLOTS_WIDTH              3  /* AIF1TX_CHAN4_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN4_START_SLOT_MASK     0x003F  /* AIF1TX_CHAN4_START_SLOT - [5:0] */
-#define WM8915_AIF1TX_CHAN4_START_SLOT_SHIFT         0  /* AIF1TX_CHAN4_START_SLOT - [5:0] */
-#define WM8915_AIF1TX_CHAN4_START_SLOT_WIDTH         6  /* AIF1TX_CHAN4_START_SLOT - [5:0] */
-
-/*
- * R782 (0x30E) - AIF1TX Channel 5 Configuration
- */
-#define WM8915_AIF1TX_CHAN5_DAT_INV             0x8000  /* AIF1TX_CHAN5_DAT_INV */
-#define WM8915_AIF1TX_CHAN5_DAT_INV_MASK        0x8000  /* AIF1TX_CHAN5_DAT_INV */
-#define WM8915_AIF1TX_CHAN5_DAT_INV_SHIFT           15  /* AIF1TX_CHAN5_DAT_INV */
-#define WM8915_AIF1TX_CHAN5_DAT_INV_WIDTH            1  /* AIF1TX_CHAN5_DAT_INV */
-#define WM8915_AIF1TX_CHAN5_SPACING_MASK        0x7E00  /* AIF1TX_CHAN5_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN5_SPACING_SHIFT            9  /* AIF1TX_CHAN5_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN5_SPACING_WIDTH            6  /* AIF1TX_CHAN5_SPACING - [14:9] */
-#define WM8915_AIF1TX_CHAN5_SLOTS_MASK          0x01C0  /* AIF1TX_CHAN5_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN5_SLOTS_SHIFT              6  /* AIF1TX_CHAN5_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN5_SLOTS_WIDTH              3  /* AIF1TX_CHAN5_SLOTS - [8:6] */
-#define WM8915_AIF1TX_CHAN5_START_SLOT_MASK     0x003F  /* AIF1TX_CHAN5_START_SLOT - [5:0] */
-#define WM8915_AIF1TX_CHAN5_START_SLOT_SHIFT         0  /* AIF1TX_CHAN5_START_SLOT - [5:0] */
-#define WM8915_AIF1TX_CHAN5_START_SLOT_WIDTH         6  /* AIF1TX_CHAN5_START_SLOT - [5:0] */
-
-/*
- * R783 (0x30F) - AIF1RX Channel 0 Configuration
- */
-#define WM8915_AIF1RX_CHAN0_DAT_INV             0x8000  /* AIF1RX_CHAN0_DAT_INV */
-#define WM8915_AIF1RX_CHAN0_DAT_INV_MASK        0x8000  /* AIF1RX_CHAN0_DAT_INV */
-#define WM8915_AIF1RX_CHAN0_DAT_INV_SHIFT           15  /* AIF1RX_CHAN0_DAT_INV */
-#define WM8915_AIF1RX_CHAN0_DAT_INV_WIDTH            1  /* AIF1RX_CHAN0_DAT_INV */
-#define WM8915_AIF1RX_CHAN0_SPACING_MASK        0x7E00  /* AIF1RX_CHAN0_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN0_SPACING_SHIFT            9  /* AIF1RX_CHAN0_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN0_SPACING_WIDTH            6  /* AIF1RX_CHAN0_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN0_SLOTS_MASK          0x01C0  /* AIF1RX_CHAN0_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN0_SLOTS_SHIFT              6  /* AIF1RX_CHAN0_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN0_SLOTS_WIDTH              3  /* AIF1RX_CHAN0_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN0_START_SLOT_MASK     0x003F  /* AIF1RX_CHAN0_START_SLOT - [5:0] */
-#define WM8915_AIF1RX_CHAN0_START_SLOT_SHIFT         0  /* AIF1RX_CHAN0_START_SLOT - [5:0] */
-#define WM8915_AIF1RX_CHAN0_START_SLOT_WIDTH         6  /* AIF1RX_CHAN0_START_SLOT - [5:0] */
-
-/*
- * R784 (0x310) - AIF1RX Channel 1 Configuration
- */
-#define WM8915_AIF1RX_CHAN1_DAT_INV             0x8000  /* AIF1RX_CHAN1_DAT_INV */
-#define WM8915_AIF1RX_CHAN1_DAT_INV_MASK        0x8000  /* AIF1RX_CHAN1_DAT_INV */
-#define WM8915_AIF1RX_CHAN1_DAT_INV_SHIFT           15  /* AIF1RX_CHAN1_DAT_INV */
-#define WM8915_AIF1RX_CHAN1_DAT_INV_WIDTH            1  /* AIF1RX_CHAN1_DAT_INV */
-#define WM8915_AIF1RX_CHAN1_SPACING_MASK        0x7E00  /* AIF1RX_CHAN1_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN1_SPACING_SHIFT            9  /* AIF1RX_CHAN1_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN1_SPACING_WIDTH            6  /* AIF1RX_CHAN1_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN1_SLOTS_MASK          0x01C0  /* AIF1RX_CHAN1_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN1_SLOTS_SHIFT              6  /* AIF1RX_CHAN1_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN1_SLOTS_WIDTH              3  /* AIF1RX_CHAN1_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN1_START_SLOT_MASK     0x003F  /* AIF1RX_CHAN1_START_SLOT - [5:0] */
-#define WM8915_AIF1RX_CHAN1_START_SLOT_SHIFT         0  /* AIF1RX_CHAN1_START_SLOT - [5:0] */
-#define WM8915_AIF1RX_CHAN1_START_SLOT_WIDTH         6  /* AIF1RX_CHAN1_START_SLOT - [5:0] */
-
-/*
- * R785 (0x311) - AIF1RX Channel 2 Configuration
- */
-#define WM8915_AIF1RX_CHAN2_DAT_INV             0x8000  /* AIF1RX_CHAN2_DAT_INV */
-#define WM8915_AIF1RX_CHAN2_DAT_INV_MASK        0x8000  /* AIF1RX_CHAN2_DAT_INV */
-#define WM8915_AIF1RX_CHAN2_DAT_INV_SHIFT           15  /* AIF1RX_CHAN2_DAT_INV */
-#define WM8915_AIF1RX_CHAN2_DAT_INV_WIDTH            1  /* AIF1RX_CHAN2_DAT_INV */
-#define WM8915_AIF1RX_CHAN2_SPACING_MASK        0x7E00  /* AIF1RX_CHAN2_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN2_SPACING_SHIFT            9  /* AIF1RX_CHAN2_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN2_SPACING_WIDTH            6  /* AIF1RX_CHAN2_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN2_SLOTS_MASK          0x01C0  /* AIF1RX_CHAN2_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN2_SLOTS_SHIFT              6  /* AIF1RX_CHAN2_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN2_SLOTS_WIDTH              3  /* AIF1RX_CHAN2_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN2_START_SLOT_MASK     0x003F  /* AIF1RX_CHAN2_START_SLOT - [5:0] */
-#define WM8915_AIF1RX_CHAN2_START_SLOT_SHIFT         0  /* AIF1RX_CHAN2_START_SLOT - [5:0] */
-#define WM8915_AIF1RX_CHAN2_START_SLOT_WIDTH         6  /* AIF1RX_CHAN2_START_SLOT - [5:0] */
-
-/*
- * R786 (0x312) - AIF1RX Channel 3 Configuration
- */
-#define WM8915_AIF1RX_CHAN3_DAT_INV             0x8000  /* AIF1RX_CHAN3_DAT_INV */
-#define WM8915_AIF1RX_CHAN3_DAT_INV_MASK        0x8000  /* AIF1RX_CHAN3_DAT_INV */
-#define WM8915_AIF1RX_CHAN3_DAT_INV_SHIFT           15  /* AIF1RX_CHAN3_DAT_INV */
-#define WM8915_AIF1RX_CHAN3_DAT_INV_WIDTH            1  /* AIF1RX_CHAN3_DAT_INV */
-#define WM8915_AIF1RX_CHAN3_SPACING_MASK        0x7E00  /* AIF1RX_CHAN3_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN3_SPACING_SHIFT            9  /* AIF1RX_CHAN3_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN3_SPACING_WIDTH            6  /* AIF1RX_CHAN3_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN3_SLOTS_MASK          0x01C0  /* AIF1RX_CHAN3_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN3_SLOTS_SHIFT              6  /* AIF1RX_CHAN3_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN3_SLOTS_WIDTH              3  /* AIF1RX_CHAN3_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN3_START_SLOT_MASK     0x003F  /* AIF1RX_CHAN3_START_SLOT - [5:0] */
-#define WM8915_AIF1RX_CHAN3_START_SLOT_SHIFT         0  /* AIF1RX_CHAN3_START_SLOT - [5:0] */
-#define WM8915_AIF1RX_CHAN3_START_SLOT_WIDTH         6  /* AIF1RX_CHAN3_START_SLOT - [5:0] */
-
-/*
- * R787 (0x313) - AIF1RX Channel 4 Configuration
- */
-#define WM8915_AIF1RX_CHAN4_DAT_INV             0x8000  /* AIF1RX_CHAN4_DAT_INV */
-#define WM8915_AIF1RX_CHAN4_DAT_INV_MASK        0x8000  /* AIF1RX_CHAN4_DAT_INV */
-#define WM8915_AIF1RX_CHAN4_DAT_INV_SHIFT           15  /* AIF1RX_CHAN4_DAT_INV */
-#define WM8915_AIF1RX_CHAN4_DAT_INV_WIDTH            1  /* AIF1RX_CHAN4_DAT_INV */
-#define WM8915_AIF1RX_CHAN4_SPACING_MASK        0x7E00  /* AIF1RX_CHAN4_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN4_SPACING_SHIFT            9  /* AIF1RX_CHAN4_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN4_SPACING_WIDTH            6  /* AIF1RX_CHAN4_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN4_SLOTS_MASK          0x01C0  /* AIF1RX_CHAN4_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN4_SLOTS_SHIFT              6  /* AIF1RX_CHAN4_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN4_SLOTS_WIDTH              3  /* AIF1RX_CHAN4_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN4_START_SLOT_MASK     0x003F  /* AIF1RX_CHAN4_START_SLOT - [5:0] */
-#define WM8915_AIF1RX_CHAN4_START_SLOT_SHIFT         0  /* AIF1RX_CHAN4_START_SLOT - [5:0] */
-#define WM8915_AIF1RX_CHAN4_START_SLOT_WIDTH         6  /* AIF1RX_CHAN4_START_SLOT - [5:0] */
-
-/*
- * R788 (0x314) - AIF1RX Channel 5 Configuration
- */
-#define WM8915_AIF1RX_CHAN5_DAT_INV             0x8000  /* AIF1RX_CHAN5_DAT_INV */
-#define WM8915_AIF1RX_CHAN5_DAT_INV_MASK        0x8000  /* AIF1RX_CHAN5_DAT_INV */
-#define WM8915_AIF1RX_CHAN5_DAT_INV_SHIFT           15  /* AIF1RX_CHAN5_DAT_INV */
-#define WM8915_AIF1RX_CHAN5_DAT_INV_WIDTH            1  /* AIF1RX_CHAN5_DAT_INV */
-#define WM8915_AIF1RX_CHAN5_SPACING_MASK        0x7E00  /* AIF1RX_CHAN5_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN5_SPACING_SHIFT            9  /* AIF1RX_CHAN5_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN5_SPACING_WIDTH            6  /* AIF1RX_CHAN5_SPACING - [14:9] */
-#define WM8915_AIF1RX_CHAN5_SLOTS_MASK          0x01C0  /* AIF1RX_CHAN5_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN5_SLOTS_SHIFT              6  /* AIF1RX_CHAN5_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN5_SLOTS_WIDTH              3  /* AIF1RX_CHAN5_SLOTS - [8:6] */
-#define WM8915_AIF1RX_CHAN5_START_SLOT_MASK     0x003F  /* AIF1RX_CHAN5_START_SLOT - [5:0] */
-#define WM8915_AIF1RX_CHAN5_START_SLOT_SHIFT         0  /* AIF1RX_CHAN5_START_SLOT - [5:0] */
-#define WM8915_AIF1RX_CHAN5_START_SLOT_WIDTH         6  /* AIF1RX_CHAN5_START_SLOT - [5:0] */
-
-/*
- * R789 (0x315) - AIF1RX Mono Configuration
- */
-#define WM8915_AIF1RX_CHAN4_MONO_MODE           0x0004  /* AIF1RX_CHAN4_MONO_MODE */
-#define WM8915_AIF1RX_CHAN4_MONO_MODE_MASK      0x0004  /* AIF1RX_CHAN4_MONO_MODE */
-#define WM8915_AIF1RX_CHAN4_MONO_MODE_SHIFT          2  /* AIF1RX_CHAN4_MONO_MODE */
-#define WM8915_AIF1RX_CHAN4_MONO_MODE_WIDTH          1  /* AIF1RX_CHAN4_MONO_MODE */
-#define WM8915_AIF1RX_CHAN2_MONO_MODE           0x0002  /* AIF1RX_CHAN2_MONO_MODE */
-#define WM8915_AIF1RX_CHAN2_MONO_MODE_MASK      0x0002  /* AIF1RX_CHAN2_MONO_MODE */
-#define WM8915_AIF1RX_CHAN2_MONO_MODE_SHIFT          1  /* AIF1RX_CHAN2_MONO_MODE */
-#define WM8915_AIF1RX_CHAN2_MONO_MODE_WIDTH          1  /* AIF1RX_CHAN2_MONO_MODE */
-#define WM8915_AIF1RX_CHAN0_MONO_MODE           0x0001  /* AIF1RX_CHAN0_MONO_MODE */
-#define WM8915_AIF1RX_CHAN0_MONO_MODE_MASK      0x0001  /* AIF1RX_CHAN0_MONO_MODE */
-#define WM8915_AIF1RX_CHAN0_MONO_MODE_SHIFT          0  /* AIF1RX_CHAN0_MONO_MODE */
-#define WM8915_AIF1RX_CHAN0_MONO_MODE_WIDTH          1  /* AIF1RX_CHAN0_MONO_MODE */
-
-/*
- * R794 (0x31A) - AIF1TX Test
- */
-#define WM8915_AIF1TX45_DITHER_ENA              0x0004  /* AIF1TX45_DITHER_ENA */
-#define WM8915_AIF1TX45_DITHER_ENA_MASK         0x0004  /* AIF1TX45_DITHER_ENA */
-#define WM8915_AIF1TX45_DITHER_ENA_SHIFT             2  /* AIF1TX45_DITHER_ENA */
-#define WM8915_AIF1TX45_DITHER_ENA_WIDTH             1  /* AIF1TX45_DITHER_ENA */
-#define WM8915_AIF1TX23_DITHER_ENA              0x0002  /* AIF1TX23_DITHER_ENA */
-#define WM8915_AIF1TX23_DITHER_ENA_MASK         0x0002  /* AIF1TX23_DITHER_ENA */
-#define WM8915_AIF1TX23_DITHER_ENA_SHIFT             1  /* AIF1TX23_DITHER_ENA */
-#define WM8915_AIF1TX23_DITHER_ENA_WIDTH             1  /* AIF1TX23_DITHER_ENA */
-#define WM8915_AIF1TX01_DITHER_ENA              0x0001  /* AIF1TX01_DITHER_ENA */
-#define WM8915_AIF1TX01_DITHER_ENA_MASK         0x0001  /* AIF1TX01_DITHER_ENA */
-#define WM8915_AIF1TX01_DITHER_ENA_SHIFT             0  /* AIF1TX01_DITHER_ENA */
-#define WM8915_AIF1TX01_DITHER_ENA_WIDTH             1  /* AIF1TX01_DITHER_ENA */
-
-/*
- * R800 (0x320) - AIF2 Control
- */
-#define WM8915_AIF2_TRI                         0x0004  /* AIF2_TRI */
-#define WM8915_AIF2_TRI_MASK                    0x0004  /* AIF2_TRI */
-#define WM8915_AIF2_TRI_SHIFT                        2  /* AIF2_TRI */
-#define WM8915_AIF2_TRI_WIDTH                        1  /* AIF2_TRI */
-#define WM8915_AIF2_FMT_MASK                    0x0003  /* AIF2_FMT - [1:0] */
-#define WM8915_AIF2_FMT_SHIFT                        0  /* AIF2_FMT - [1:0] */
-#define WM8915_AIF2_FMT_WIDTH                        2  /* AIF2_FMT - [1:0] */
-
-/*
- * R801 (0x321) - AIF2 BCLK
- */
-#define WM8915_AIF2_BCLK_INV                    0x0400  /* AIF2_BCLK_INV */
-#define WM8915_AIF2_BCLK_INV_MASK               0x0400  /* AIF2_BCLK_INV */
-#define WM8915_AIF2_BCLK_INV_SHIFT                  10  /* AIF2_BCLK_INV */
-#define WM8915_AIF2_BCLK_INV_WIDTH                   1  /* AIF2_BCLK_INV */
-#define WM8915_AIF2_BCLK_FRC                    0x0200  /* AIF2_BCLK_FRC */
-#define WM8915_AIF2_BCLK_FRC_MASK               0x0200  /* AIF2_BCLK_FRC */
-#define WM8915_AIF2_BCLK_FRC_SHIFT                   9  /* AIF2_BCLK_FRC */
-#define WM8915_AIF2_BCLK_FRC_WIDTH                   1  /* AIF2_BCLK_FRC */
-#define WM8915_AIF2_BCLK_MSTR                   0x0100  /* AIF2_BCLK_MSTR */
-#define WM8915_AIF2_BCLK_MSTR_MASK              0x0100  /* AIF2_BCLK_MSTR */
-#define WM8915_AIF2_BCLK_MSTR_SHIFT                  8  /* AIF2_BCLK_MSTR */
-#define WM8915_AIF2_BCLK_MSTR_WIDTH                  1  /* AIF2_BCLK_MSTR */
-#define WM8915_AIF2_BCLK_DIV_MASK               0x000F  /* AIF2_BCLK_DIV - [3:0] */
-#define WM8915_AIF2_BCLK_DIV_SHIFT                   0  /* AIF2_BCLK_DIV - [3:0] */
-#define WM8915_AIF2_BCLK_DIV_WIDTH                   4  /* AIF2_BCLK_DIV - [3:0] */
-
-/*
- * R802 (0x322) - AIF2 TX LRCLK(1)
- */
-#define WM8915_AIF2TX_RATE_MASK                 0x07FF  /* AIF2TX_RATE - [10:0] */
-#define WM8915_AIF2TX_RATE_SHIFT                     0  /* AIF2TX_RATE - [10:0] */
-#define WM8915_AIF2TX_RATE_WIDTH                    11  /* AIF2TX_RATE - [10:0] */
-
-/*
- * R803 (0x323) - AIF2 TX LRCLK(2)
- */
-#define WM8915_AIF2TX_LRCLK_MODE                0x0008  /* AIF2TX_LRCLK_MODE */
-#define WM8915_AIF2TX_LRCLK_MODE_MASK           0x0008  /* AIF2TX_LRCLK_MODE */
-#define WM8915_AIF2TX_LRCLK_MODE_SHIFT               3  /* AIF2TX_LRCLK_MODE */
-#define WM8915_AIF2TX_LRCLK_MODE_WIDTH               1  /* AIF2TX_LRCLK_MODE */
-#define WM8915_AIF2TX_LRCLK_INV                 0x0004  /* AIF2TX_LRCLK_INV */
-#define WM8915_AIF2TX_LRCLK_INV_MASK            0x0004  /* AIF2TX_LRCLK_INV */
-#define WM8915_AIF2TX_LRCLK_INV_SHIFT                2  /* AIF2TX_LRCLK_INV */
-#define WM8915_AIF2TX_LRCLK_INV_WIDTH                1  /* AIF2TX_LRCLK_INV */
-#define WM8915_AIF2TX_LRCLK_FRC                 0x0002  /* AIF2TX_LRCLK_FRC */
-#define WM8915_AIF2TX_LRCLK_FRC_MASK            0x0002  /* AIF2TX_LRCLK_FRC */
-#define WM8915_AIF2TX_LRCLK_FRC_SHIFT                1  /* AIF2TX_LRCLK_FRC */
-#define WM8915_AIF2TX_LRCLK_FRC_WIDTH                1  /* AIF2TX_LRCLK_FRC */
-#define WM8915_AIF2TX_LRCLK_MSTR                0x0001  /* AIF2TX_LRCLK_MSTR */
-#define WM8915_AIF2TX_LRCLK_MSTR_MASK           0x0001  /* AIF2TX_LRCLK_MSTR */
-#define WM8915_AIF2TX_LRCLK_MSTR_SHIFT               0  /* AIF2TX_LRCLK_MSTR */
-#define WM8915_AIF2TX_LRCLK_MSTR_WIDTH               1  /* AIF2TX_LRCLK_MSTR */
-
-/*
- * R804 (0x324) - AIF2 RX LRCLK(1)
- */
-#define WM8915_AIF2RX_RATE_MASK                 0x07FF  /* AIF2RX_RATE - [10:0] */
-#define WM8915_AIF2RX_RATE_SHIFT                     0  /* AIF2RX_RATE - [10:0] */
-#define WM8915_AIF2RX_RATE_WIDTH                    11  /* AIF2RX_RATE - [10:0] */
-
-/*
- * R805 (0x325) - AIF2 RX LRCLK(2)
- */
-#define WM8915_AIF2RX_LRCLK_INV                 0x0004  /* AIF2RX_LRCLK_INV */
-#define WM8915_AIF2RX_LRCLK_INV_MASK            0x0004  /* AIF2RX_LRCLK_INV */
-#define WM8915_AIF2RX_LRCLK_INV_SHIFT                2  /* AIF2RX_LRCLK_INV */
-#define WM8915_AIF2RX_LRCLK_INV_WIDTH                1  /* AIF2RX_LRCLK_INV */
-#define WM8915_AIF2RX_LRCLK_FRC                 0x0002  /* AIF2RX_LRCLK_FRC */
-#define WM8915_AIF2RX_LRCLK_FRC_MASK            0x0002  /* AIF2RX_LRCLK_FRC */
-#define WM8915_AIF2RX_LRCLK_FRC_SHIFT                1  /* AIF2RX_LRCLK_FRC */
-#define WM8915_AIF2RX_LRCLK_FRC_WIDTH                1  /* AIF2RX_LRCLK_FRC */
-#define WM8915_AIF2RX_LRCLK_MSTR                0x0001  /* AIF2RX_LRCLK_MSTR */
-#define WM8915_AIF2RX_LRCLK_MSTR_MASK           0x0001  /* AIF2RX_LRCLK_MSTR */
-#define WM8915_AIF2RX_LRCLK_MSTR_SHIFT               0  /* AIF2RX_LRCLK_MSTR */
-#define WM8915_AIF2RX_LRCLK_MSTR_WIDTH               1  /* AIF2RX_LRCLK_MSTR */
-
-/*
- * R806 (0x326) - AIF2TX Data Configuration (1)
- */
-#define WM8915_AIF2TX_WL_MASK                   0xFF00  /* AIF2TX_WL - [15:8] */
-#define WM8915_AIF2TX_WL_SHIFT                       8  /* AIF2TX_WL - [15:8] */
-#define WM8915_AIF2TX_WL_WIDTH                       8  /* AIF2TX_WL - [15:8] */
-#define WM8915_AIF2TX_SLOT_LEN_MASK             0x00FF  /* AIF2TX_SLOT_LEN - [7:0] */
-#define WM8915_AIF2TX_SLOT_LEN_SHIFT                 0  /* AIF2TX_SLOT_LEN - [7:0] */
-#define WM8915_AIF2TX_SLOT_LEN_WIDTH                 8  /* AIF2TX_SLOT_LEN - [7:0] */
-
-/*
- * R807 (0x327) - AIF2TX Data Configuration (2)
- */
-#define WM8915_AIF2TX_DAT_TRI                   0x0001  /* AIF2TX_DAT_TRI */
-#define WM8915_AIF2TX_DAT_TRI_MASK              0x0001  /* AIF2TX_DAT_TRI */
-#define WM8915_AIF2TX_DAT_TRI_SHIFT                  0  /* AIF2TX_DAT_TRI */
-#define WM8915_AIF2TX_DAT_TRI_WIDTH                  1  /* AIF2TX_DAT_TRI */
-
-/*
- * R808 (0x328) - AIF2RX Data Configuration
- */
-#define WM8915_AIF2RX_WL_MASK                   0xFF00  /* AIF2RX_WL - [15:8] */
-#define WM8915_AIF2RX_WL_SHIFT                       8  /* AIF2RX_WL - [15:8] */
-#define WM8915_AIF2RX_WL_WIDTH                       8  /* AIF2RX_WL - [15:8] */
-#define WM8915_AIF2RX_SLOT_LEN_MASK             0x00FF  /* AIF2RX_SLOT_LEN - [7:0] */
-#define WM8915_AIF2RX_SLOT_LEN_SHIFT                 0  /* AIF2RX_SLOT_LEN - [7:0] */
-#define WM8915_AIF2RX_SLOT_LEN_WIDTH                 8  /* AIF2RX_SLOT_LEN - [7:0] */
-
-/*
- * R809 (0x329) - AIF2TX Channel 0 Configuration
- */
-#define WM8915_AIF2TX_CHAN0_DAT_INV             0x8000  /* AIF2TX_CHAN0_DAT_INV */
-#define WM8915_AIF2TX_CHAN0_DAT_INV_MASK        0x8000  /* AIF2TX_CHAN0_DAT_INV */
-#define WM8915_AIF2TX_CHAN0_DAT_INV_SHIFT           15  /* AIF2TX_CHAN0_DAT_INV */
-#define WM8915_AIF2TX_CHAN0_DAT_INV_WIDTH            1  /* AIF2TX_CHAN0_DAT_INV */
-#define WM8915_AIF2TX_CHAN0_SPACING_MASK        0x7E00  /* AIF2TX_CHAN0_SPACING - [14:9] */
-#define WM8915_AIF2TX_CHAN0_SPACING_SHIFT            9  /* AIF2TX_CHAN0_SPACING - [14:9] */
-#define WM8915_AIF2TX_CHAN0_SPACING_WIDTH            6  /* AIF2TX_CHAN0_SPACING - [14:9] */
-#define WM8915_AIF2TX_CHAN0_SLOTS_MASK          0x01C0  /* AIF2TX_CHAN0_SLOTS - [8:6] */
-#define WM8915_AIF2TX_CHAN0_SLOTS_SHIFT              6  /* AIF2TX_CHAN0_SLOTS - [8:6] */
-#define WM8915_AIF2TX_CHAN0_SLOTS_WIDTH              3  /* AIF2TX_CHAN0_SLOTS - [8:6] */
-#define WM8915_AIF2TX_CHAN0_START_SLOT_MASK     0x003F  /* AIF2TX_CHAN0_START_SLOT - [5:0] */
-#define WM8915_AIF2TX_CHAN0_START_SLOT_SHIFT         0  /* AIF2TX_CHAN0_START_SLOT - [5:0] */
-#define WM8915_AIF2TX_CHAN0_START_SLOT_WIDTH         6  /* AIF2TX_CHAN0_START_SLOT - [5:0] */
-
-/*
- * R810 (0x32A) - AIF2TX Channel 1 Configuration
- */
-#define WM8915_AIF2TX_CHAN1_DAT_INV             0x8000  /* AIF2TX_CHAN1_DAT_INV */
-#define WM8915_AIF2TX_CHAN1_DAT_INV_MASK        0x8000  /* AIF2TX_CHAN1_DAT_INV */
-#define WM8915_AIF2TX_CHAN1_DAT_INV_SHIFT           15  /* AIF2TX_CHAN1_DAT_INV */
-#define WM8915_AIF2TX_CHAN1_DAT_INV_WIDTH            1  /* AIF2TX_CHAN1_DAT_INV */
-#define WM8915_AIF2TX_CHAN1_SPACING_MASK        0x7E00  /* AIF2TX_CHAN1_SPACING - [14:9] */
-#define WM8915_AIF2TX_CHAN1_SPACING_SHIFT            9  /* AIF2TX_CHAN1_SPACING - [14:9] */
-#define WM8915_AIF2TX_CHAN1_SPACING_WIDTH            6  /* AIF2TX_CHAN1_SPACING - [14:9] */
-#define WM8915_AIF2TX_CHAN1_SLOTS_MASK          0x01C0  /* AIF2TX_CHAN1_SLOTS - [8:6] */
-#define WM8915_AIF2TX_CHAN1_SLOTS_SHIFT              6  /* AIF2TX_CHAN1_SLOTS - [8:6] */
-#define WM8915_AIF2TX_CHAN1_SLOTS_WIDTH              3  /* AIF2TX_CHAN1_SLOTS - [8:6] */
-#define WM8915_AIF2TX_CHAN1_START_SLOT_MASK     0x003F  /* AIF2TX_CHAN1_START_SLOT - [5:0] */
-#define WM8915_AIF2TX_CHAN1_START_SLOT_SHIFT         0  /* AIF2TX_CHAN1_START_SLOT - [5:0] */
-#define WM8915_AIF2TX_CHAN1_START_SLOT_WIDTH         6  /* AIF2TX_CHAN1_START_SLOT - [5:0] */
-
-/*
- * R811 (0x32B) - AIF2RX Channel 0 Configuration
- */
-#define WM8915_AIF2RX_CHAN0_DAT_INV             0x8000  /* AIF2RX_CHAN0_DAT_INV */
-#define WM8915_AIF2RX_CHAN0_DAT_INV_MASK        0x8000  /* AIF2RX_CHAN0_DAT_INV */
-#define WM8915_AIF2RX_CHAN0_DAT_INV_SHIFT           15  /* AIF2RX_CHAN0_DAT_INV */
-#define WM8915_AIF2RX_CHAN0_DAT_INV_WIDTH            1  /* AIF2RX_CHAN0_DAT_INV */
-#define WM8915_AIF2RX_CHAN0_SPACING_MASK        0x7E00  /* AIF2RX_CHAN0_SPACING - [14:9] */
-#define WM8915_AIF2RX_CHAN0_SPACING_SHIFT            9  /* AIF2RX_CHAN0_SPACING - [14:9] */
-#define WM8915_AIF2RX_CHAN0_SPACING_WIDTH            6  /* AIF2RX_CHAN0_SPACING - [14:9] */
-#define WM8915_AIF2RX_CHAN0_SLOTS_MASK          0x01C0  /* AIF2RX_CHAN0_SLOTS - [8:6] */
-#define WM8915_AIF2RX_CHAN0_SLOTS_SHIFT              6  /* AIF2RX_CHAN0_SLOTS - [8:6] */
-#define WM8915_AIF2RX_CHAN0_SLOTS_WIDTH              3  /* AIF2RX_CHAN0_SLOTS - [8:6] */
-#define WM8915_AIF2RX_CHAN0_START_SLOT_MASK     0x003F  /* AIF2RX_CHAN0_START_SLOT - [5:0] */
-#define WM8915_AIF2RX_CHAN0_START_SLOT_SHIFT         0  /* AIF2RX_CHAN0_START_SLOT - [5:0] */
-#define WM8915_AIF2RX_CHAN0_START_SLOT_WIDTH         6  /* AIF2RX_CHAN0_START_SLOT - [5:0] */
-
-/*
- * R812 (0x32C) - AIF2RX Channel 1 Configuration
- */
-#define WM8915_AIF2RX_CHAN1_DAT_INV             0x8000  /* AIF2RX_CHAN1_DAT_INV */
-#define WM8915_AIF2RX_CHAN1_DAT_INV_MASK        0x8000  /* AIF2RX_CHAN1_DAT_INV */
-#define WM8915_AIF2RX_CHAN1_DAT_INV_SHIFT           15  /* AIF2RX_CHAN1_DAT_INV */
-#define WM8915_AIF2RX_CHAN1_DAT_INV_WIDTH            1  /* AIF2RX_CHAN1_DAT_INV */
-#define WM8915_AIF2RX_CHAN1_SPACING_MASK        0x7E00  /* AIF2RX_CHAN1_SPACING - [14:9] */
-#define WM8915_AIF2RX_CHAN1_SPACING_SHIFT            9  /* AIF2RX_CHAN1_SPACING - [14:9] */
-#define WM8915_AIF2RX_CHAN1_SPACING_WIDTH            6  /* AIF2RX_CHAN1_SPACING - [14:9] */
-#define WM8915_AIF2RX_CHAN1_SLOTS_MASK          0x01C0  /* AIF2RX_CHAN1_SLOTS - [8:6] */
-#define WM8915_AIF2RX_CHAN1_SLOTS_SHIFT              6  /* AIF2RX_CHAN1_SLOTS - [8:6] */
-#define WM8915_AIF2RX_CHAN1_SLOTS_WIDTH              3  /* AIF2RX_CHAN1_SLOTS - [8:6] */
-#define WM8915_AIF2RX_CHAN1_START_SLOT_MASK     0x003F  /* AIF2RX_CHAN1_START_SLOT - [5:0] */
-#define WM8915_AIF2RX_CHAN1_START_SLOT_SHIFT         0  /* AIF2RX_CHAN1_START_SLOT - [5:0] */
-#define WM8915_AIF2RX_CHAN1_START_SLOT_WIDTH         6  /* AIF2RX_CHAN1_START_SLOT - [5:0] */
-
-/*
- * R813 (0x32D) - AIF2RX Mono Configuration
- */
-#define WM8915_AIF2RX_CHAN0_MONO_MODE           0x0001  /* AIF2RX_CHAN0_MONO_MODE */
-#define WM8915_AIF2RX_CHAN0_MONO_MODE_MASK      0x0001  /* AIF2RX_CHAN0_MONO_MODE */
-#define WM8915_AIF2RX_CHAN0_MONO_MODE_SHIFT          0  /* AIF2RX_CHAN0_MONO_MODE */
-#define WM8915_AIF2RX_CHAN0_MONO_MODE_WIDTH          1  /* AIF2RX_CHAN0_MONO_MODE */
-
-/*
- * R815 (0x32F) - AIF2TX Test
- */
-#define WM8915_AIF2TX_DITHER_ENA                0x0001  /* AIF2TX_DITHER_ENA */
-#define WM8915_AIF2TX_DITHER_ENA_MASK           0x0001  /* AIF2TX_DITHER_ENA */
-#define WM8915_AIF2TX_DITHER_ENA_SHIFT               0  /* AIF2TX_DITHER_ENA */
-#define WM8915_AIF2TX_DITHER_ENA_WIDTH               1  /* AIF2TX_DITHER_ENA */
-
-/*
- * R1024 (0x400) - DSP1 TX Left Volume
- */
-#define WM8915_DSP1TX_VU                        0x0100  /* DSP1TX_VU */
-#define WM8915_DSP1TX_VU_MASK                   0x0100  /* DSP1TX_VU */
-#define WM8915_DSP1TX_VU_SHIFT                       8  /* DSP1TX_VU */
-#define WM8915_DSP1TX_VU_WIDTH                       1  /* DSP1TX_VU */
-#define WM8915_DSP1TXL_VOL_MASK                 0x00FF  /* DSP1TXL_VOL - [7:0] */
-#define WM8915_DSP1TXL_VOL_SHIFT                     0  /* DSP1TXL_VOL - [7:0] */
-#define WM8915_DSP1TXL_VOL_WIDTH                     8  /* DSP1TXL_VOL - [7:0] */
-
-/*
- * R1025 (0x401) - DSP1 TX Right Volume
- */
-#define WM8915_DSP1TX_VU                        0x0100  /* DSP1TX_VU */
-#define WM8915_DSP1TX_VU_MASK                   0x0100  /* DSP1TX_VU */
-#define WM8915_DSP1TX_VU_SHIFT                       8  /* DSP1TX_VU */
-#define WM8915_DSP1TX_VU_WIDTH                       1  /* DSP1TX_VU */
-#define WM8915_DSP1TXR_VOL_MASK                 0x00FF  /* DSP1TXR_VOL - [7:0] */
-#define WM8915_DSP1TXR_VOL_SHIFT                     0  /* DSP1TXR_VOL - [7:0] */
-#define WM8915_DSP1TXR_VOL_WIDTH                     8  /* DSP1TXR_VOL - [7:0] */
-
-/*
- * R1026 (0x402) - DSP1 RX Left Volume
- */
-#define WM8915_DSP1RX_VU                        0x0100  /* DSP1RX_VU */
-#define WM8915_DSP1RX_VU_MASK                   0x0100  /* DSP1RX_VU */
-#define WM8915_DSP1RX_VU_SHIFT                       8  /* DSP1RX_VU */
-#define WM8915_DSP1RX_VU_WIDTH                       1  /* DSP1RX_VU */
-#define WM8915_DSP1RXL_VOL_MASK                 0x00FF  /* DSP1RXL_VOL - [7:0] */
-#define WM8915_DSP1RXL_VOL_SHIFT                     0  /* DSP1RXL_VOL - [7:0] */
-#define WM8915_DSP1RXL_VOL_WIDTH                     8  /* DSP1RXL_VOL - [7:0] */
-
-/*
- * R1027 (0x403) - DSP1 RX Right Volume
- */
-#define WM8915_DSP1RX_VU                        0x0100  /* DSP1RX_VU */
-#define WM8915_DSP1RX_VU_MASK                   0x0100  /* DSP1RX_VU */
-#define WM8915_DSP1RX_VU_SHIFT                       8  /* DSP1RX_VU */
-#define WM8915_DSP1RX_VU_WIDTH                       1  /* DSP1RX_VU */
-#define WM8915_DSP1RXR_VOL_MASK                 0x00FF  /* DSP1RXR_VOL - [7:0] */
-#define WM8915_DSP1RXR_VOL_SHIFT                     0  /* DSP1RXR_VOL - [7:0] */
-#define WM8915_DSP1RXR_VOL_WIDTH                     8  /* DSP1RXR_VOL - [7:0] */
-
-/*
- * R1040 (0x410) - DSP1 TX Filters
- */
-#define WM8915_DSP1TX_NF                        0x2000  /* DSP1TX_NF */
-#define WM8915_DSP1TX_NF_MASK                   0x2000  /* DSP1TX_NF */
-#define WM8915_DSP1TX_NF_SHIFT                      13  /* DSP1TX_NF */
-#define WM8915_DSP1TX_NF_WIDTH                       1  /* DSP1TX_NF */
-#define WM8915_DSP1TXL_HPF                      0x1000  /* DSP1TXL_HPF */
-#define WM8915_DSP1TXL_HPF_MASK                 0x1000  /* DSP1TXL_HPF */
-#define WM8915_DSP1TXL_HPF_SHIFT                    12  /* DSP1TXL_HPF */
-#define WM8915_DSP1TXL_HPF_WIDTH                     1  /* DSP1TXL_HPF */
-#define WM8915_DSP1TXR_HPF                      0x0800  /* DSP1TXR_HPF */
-#define WM8915_DSP1TXR_HPF_MASK                 0x0800  /* DSP1TXR_HPF */
-#define WM8915_DSP1TXR_HPF_SHIFT                    11  /* DSP1TXR_HPF */
-#define WM8915_DSP1TXR_HPF_WIDTH                     1  /* DSP1TXR_HPF */
-#define WM8915_DSP1TX_HPF_MODE_MASK             0x0018  /* DSP1TX_HPF_MODE - [4:3] */
-#define WM8915_DSP1TX_HPF_MODE_SHIFT                 3  /* DSP1TX_HPF_MODE - [4:3] */
-#define WM8915_DSP1TX_HPF_MODE_WIDTH                 2  /* DSP1TX_HPF_MODE - [4:3] */
-#define WM8915_DSP1TX_HPF_CUT_MASK              0x0007  /* DSP1TX_HPF_CUT - [2:0] */
-#define WM8915_DSP1TX_HPF_CUT_SHIFT                  0  /* DSP1TX_HPF_CUT - [2:0] */
-#define WM8915_DSP1TX_HPF_CUT_WIDTH                  3  /* DSP1TX_HPF_CUT - [2:0] */
-
-/*
- * R1056 (0x420) - DSP1 RX Filters (1)
- */
-#define WM8915_DSP1RX_MUTE                      0x0200  /* DSP1RX_MUTE */
-#define WM8915_DSP1RX_MUTE_MASK                 0x0200  /* DSP1RX_MUTE */
-#define WM8915_DSP1RX_MUTE_SHIFT                     9  /* DSP1RX_MUTE */
-#define WM8915_DSP1RX_MUTE_WIDTH                     1  /* DSP1RX_MUTE */
-#define WM8915_DSP1RX_MONO                      0x0080  /* DSP1RX_MONO */
-#define WM8915_DSP1RX_MONO_MASK                 0x0080  /* DSP1RX_MONO */
-#define WM8915_DSP1RX_MONO_SHIFT                     7  /* DSP1RX_MONO */
-#define WM8915_DSP1RX_MONO_WIDTH                     1  /* DSP1RX_MONO */
-#define WM8915_DSP1RX_MUTERATE                  0x0020  /* DSP1RX_MUTERATE */
-#define WM8915_DSP1RX_MUTERATE_MASK             0x0020  /* DSP1RX_MUTERATE */
-#define WM8915_DSP1RX_MUTERATE_SHIFT                 5  /* DSP1RX_MUTERATE */
-#define WM8915_DSP1RX_MUTERATE_WIDTH                 1  /* DSP1RX_MUTERATE */
-#define WM8915_DSP1RX_UNMUTE_RAMP               0x0010  /* DSP1RX_UNMUTE_RAMP */
-#define WM8915_DSP1RX_UNMUTE_RAMP_MASK          0x0010  /* DSP1RX_UNMUTE_RAMP */
-#define WM8915_DSP1RX_UNMUTE_RAMP_SHIFT              4  /* DSP1RX_UNMUTE_RAMP */
-#define WM8915_DSP1RX_UNMUTE_RAMP_WIDTH              1  /* DSP1RX_UNMUTE_RAMP */
-
-/*
- * R1057 (0x421) - DSP1 RX Filters (2)
- */
-#define WM8915_DSP1RX_3D_GAIN_MASK              0x3E00  /* DSP1RX_3D_GAIN - [13:9] */
-#define WM8915_DSP1RX_3D_GAIN_SHIFT                  9  /* DSP1RX_3D_GAIN - [13:9] */
-#define WM8915_DSP1RX_3D_GAIN_WIDTH                  5  /* DSP1RX_3D_GAIN - [13:9] */
-#define WM8915_DSP1RX_3D_ENA                    0x0100  /* DSP1RX_3D_ENA */
-#define WM8915_DSP1RX_3D_ENA_MASK               0x0100  /* DSP1RX_3D_ENA */
-#define WM8915_DSP1RX_3D_ENA_SHIFT                   8  /* DSP1RX_3D_ENA */
-#define WM8915_DSP1RX_3D_ENA_WIDTH                   1  /* DSP1RX_3D_ENA */
-
-/*
- * R1088 (0x440) - DSP1 DRC (1)
- */
-#define WM8915_DSP1DRC_SIG_DET_RMS_MASK         0xF800  /* DSP1DRC_SIG_DET_RMS - [15:11] */
-#define WM8915_DSP1DRC_SIG_DET_RMS_SHIFT            11  /* DSP1DRC_SIG_DET_RMS - [15:11] */
-#define WM8915_DSP1DRC_SIG_DET_RMS_WIDTH             5  /* DSP1DRC_SIG_DET_RMS - [15:11] */
-#define WM8915_DSP1DRC_SIG_DET_PK_MASK          0x0600  /* DSP1DRC_SIG_DET_PK - [10:9] */
-#define WM8915_DSP1DRC_SIG_DET_PK_SHIFT              9  /* DSP1DRC_SIG_DET_PK - [10:9] */
-#define WM8915_DSP1DRC_SIG_DET_PK_WIDTH              2  /* DSP1DRC_SIG_DET_PK - [10:9] */
-#define WM8915_DSP1DRC_NG_ENA                   0x0100  /* DSP1DRC_NG_ENA */
-#define WM8915_DSP1DRC_NG_ENA_MASK              0x0100  /* DSP1DRC_NG_ENA */
-#define WM8915_DSP1DRC_NG_ENA_SHIFT                  8  /* DSP1DRC_NG_ENA */
-#define WM8915_DSP1DRC_NG_ENA_WIDTH                  1  /* DSP1DRC_NG_ENA */
-#define WM8915_DSP1DRC_SIG_DET_MODE             0x0080  /* DSP1DRC_SIG_DET_MODE */
-#define WM8915_DSP1DRC_SIG_DET_MODE_MASK        0x0080  /* DSP1DRC_SIG_DET_MODE */
-#define WM8915_DSP1DRC_SIG_DET_MODE_SHIFT            7  /* DSP1DRC_SIG_DET_MODE */
-#define WM8915_DSP1DRC_SIG_DET_MODE_WIDTH            1  /* DSP1DRC_SIG_DET_MODE */
-#define WM8915_DSP1DRC_SIG_DET                  0x0040  /* DSP1DRC_SIG_DET */
-#define WM8915_DSP1DRC_SIG_DET_MASK             0x0040  /* DSP1DRC_SIG_DET */
-#define WM8915_DSP1DRC_SIG_DET_SHIFT                 6  /* DSP1DRC_SIG_DET */
-#define WM8915_DSP1DRC_SIG_DET_WIDTH                 1  /* DSP1DRC_SIG_DET */
-#define WM8915_DSP1DRC_KNEE2_OP_ENA             0x0020  /* DSP1DRC_KNEE2_OP_ENA */
-#define WM8915_DSP1DRC_KNEE2_OP_ENA_MASK        0x0020  /* DSP1DRC_KNEE2_OP_ENA */
-#define WM8915_DSP1DRC_KNEE2_OP_ENA_SHIFT            5  /* DSP1DRC_KNEE2_OP_ENA */
-#define WM8915_DSP1DRC_KNEE2_OP_ENA_WIDTH            1  /* DSP1DRC_KNEE2_OP_ENA */
-#define WM8915_DSP1DRC_QR                       0x0010  /* DSP1DRC_QR */
-#define WM8915_DSP1DRC_QR_MASK                  0x0010  /* DSP1DRC_QR */
-#define WM8915_DSP1DRC_QR_SHIFT                      4  /* DSP1DRC_QR */
-#define WM8915_DSP1DRC_QR_WIDTH                      1  /* DSP1DRC_QR */
-#define WM8915_DSP1DRC_ANTICLIP                 0x0008  /* DSP1DRC_ANTICLIP */
-#define WM8915_DSP1DRC_ANTICLIP_MASK            0x0008  /* DSP1DRC_ANTICLIP */
-#define WM8915_DSP1DRC_ANTICLIP_SHIFT                3  /* DSP1DRC_ANTICLIP */
-#define WM8915_DSP1DRC_ANTICLIP_WIDTH                1  /* DSP1DRC_ANTICLIP */
-#define WM8915_DSP1RX_DRC_ENA                   0x0004  /* DSP1RX_DRC_ENA */
-#define WM8915_DSP1RX_DRC_ENA_MASK              0x0004  /* DSP1RX_DRC_ENA */
-#define WM8915_DSP1RX_DRC_ENA_SHIFT                  2  /* DSP1RX_DRC_ENA */
-#define WM8915_DSP1RX_DRC_ENA_WIDTH                  1  /* DSP1RX_DRC_ENA */
-#define WM8915_DSP1TXL_DRC_ENA                  0x0002  /* DSP1TXL_DRC_ENA */
-#define WM8915_DSP1TXL_DRC_ENA_MASK             0x0002  /* DSP1TXL_DRC_ENA */
-#define WM8915_DSP1TXL_DRC_ENA_SHIFT                 1  /* DSP1TXL_DRC_ENA */
-#define WM8915_DSP1TXL_DRC_ENA_WIDTH                 1  /* DSP1TXL_DRC_ENA */
-#define WM8915_DSP1TXR_DRC_ENA                  0x0001  /* DSP1TXR_DRC_ENA */
-#define WM8915_DSP1TXR_DRC_ENA_MASK             0x0001  /* DSP1TXR_DRC_ENA */
-#define WM8915_DSP1TXR_DRC_ENA_SHIFT                 0  /* DSP1TXR_DRC_ENA */
-#define WM8915_DSP1TXR_DRC_ENA_WIDTH                 1  /* DSP1TXR_DRC_ENA */
-
-/*
- * R1089 (0x441) - DSP1 DRC (2)
- */
-#define WM8915_DSP1DRC_ATK_MASK                 0x1E00  /* DSP1DRC_ATK - [12:9] */
-#define WM8915_DSP1DRC_ATK_SHIFT                     9  /* DSP1DRC_ATK - [12:9] */
-#define WM8915_DSP1DRC_ATK_WIDTH                     4  /* DSP1DRC_ATK - [12:9] */
-#define WM8915_DSP1DRC_DCY_MASK                 0x01E0  /* DSP1DRC_DCY - [8:5] */
-#define WM8915_DSP1DRC_DCY_SHIFT                     5  /* DSP1DRC_DCY - [8:5] */
-#define WM8915_DSP1DRC_DCY_WIDTH                     4  /* DSP1DRC_DCY - [8:5] */
-#define WM8915_DSP1DRC_MINGAIN_MASK             0x001C  /* DSP1DRC_MINGAIN - [4:2] */
-#define WM8915_DSP1DRC_MINGAIN_SHIFT                 2  /* DSP1DRC_MINGAIN - [4:2] */
-#define WM8915_DSP1DRC_MINGAIN_WIDTH                 3  /* DSP1DRC_MINGAIN - [4:2] */
-#define WM8915_DSP1DRC_MAXGAIN_MASK             0x0003  /* DSP1DRC_MAXGAIN - [1:0] */
-#define WM8915_DSP1DRC_MAXGAIN_SHIFT                 0  /* DSP1DRC_MAXGAIN - [1:0] */
-#define WM8915_DSP1DRC_MAXGAIN_WIDTH                 2  /* DSP1DRC_MAXGAIN - [1:0] */
-
-/*
- * R1090 (0x442) - DSP1 DRC (3)
- */
-#define WM8915_DSP1DRC_NG_MINGAIN_MASK          0xF000  /* DSP1DRC_NG_MINGAIN - [15:12] */
-#define WM8915_DSP1DRC_NG_MINGAIN_SHIFT             12  /* DSP1DRC_NG_MINGAIN - [15:12] */
-#define WM8915_DSP1DRC_NG_MINGAIN_WIDTH              4  /* DSP1DRC_NG_MINGAIN - [15:12] */
-#define WM8915_DSP1DRC_NG_EXP_MASK              0x0C00  /* DSP1DRC_NG_EXP - [11:10] */
-#define WM8915_DSP1DRC_NG_EXP_SHIFT                 10  /* DSP1DRC_NG_EXP - [11:10] */
-#define WM8915_DSP1DRC_NG_EXP_WIDTH                  2  /* DSP1DRC_NG_EXP - [11:10] */
-#define WM8915_DSP1DRC_QR_THR_MASK              0x0300  /* DSP1DRC_QR_THR - [9:8] */
-#define WM8915_DSP1DRC_QR_THR_SHIFT                  8  /* DSP1DRC_QR_THR - [9:8] */
-#define WM8915_DSP1DRC_QR_THR_WIDTH                  2  /* DSP1DRC_QR_THR - [9:8] */
-#define WM8915_DSP1DRC_QR_DCY_MASK              0x00C0  /* DSP1DRC_QR_DCY - [7:6] */
-#define WM8915_DSP1DRC_QR_DCY_SHIFT                  6  /* DSP1DRC_QR_DCY - [7:6] */
-#define WM8915_DSP1DRC_QR_DCY_WIDTH                  2  /* DSP1DRC_QR_DCY - [7:6] */
-#define WM8915_DSP1DRC_HI_COMP_MASK             0x0038  /* DSP1DRC_HI_COMP - [5:3] */
-#define WM8915_DSP1DRC_HI_COMP_SHIFT                 3  /* DSP1DRC_HI_COMP - [5:3] */
-#define WM8915_DSP1DRC_HI_COMP_WIDTH                 3  /* DSP1DRC_HI_COMP - [5:3] */
-#define WM8915_DSP1DRC_LO_COMP_MASK             0x0007  /* DSP1DRC_LO_COMP - [2:0] */
-#define WM8915_DSP1DRC_LO_COMP_SHIFT                 0  /* DSP1DRC_LO_COMP - [2:0] */
-#define WM8915_DSP1DRC_LO_COMP_WIDTH                 3  /* DSP1DRC_LO_COMP - [2:0] */
-
-/*
- * R1091 (0x443) - DSP1 DRC (4)
- */
-#define WM8915_DSP1DRC_KNEE_IP_MASK             0x07E0  /* DSP1DRC_KNEE_IP - [10:5] */
-#define WM8915_DSP1DRC_KNEE_IP_SHIFT                 5  /* DSP1DRC_KNEE_IP - [10:5] */
-#define WM8915_DSP1DRC_KNEE_IP_WIDTH                 6  /* DSP1DRC_KNEE_IP - [10:5] */
-#define WM8915_DSP1DRC_KNEE_OP_MASK             0x001F  /* DSP1DRC_KNEE_OP - [4:0] */
-#define WM8915_DSP1DRC_KNEE_OP_SHIFT                 0  /* DSP1DRC_KNEE_OP - [4:0] */
-#define WM8915_DSP1DRC_KNEE_OP_WIDTH                 5  /* DSP1DRC_KNEE_OP - [4:0] */
-
-/*
- * R1092 (0x444) - DSP1 DRC (5)
- */
-#define WM8915_DSP1DRC_KNEE2_IP_MASK            0x03E0  /* DSP1DRC_KNEE2_IP - [9:5] */
-#define WM8915_DSP1DRC_KNEE2_IP_SHIFT                5  /* DSP1DRC_KNEE2_IP - [9:5] */
-#define WM8915_DSP1DRC_KNEE2_IP_WIDTH                5  /* DSP1DRC_KNEE2_IP - [9:5] */
-#define WM8915_DSP1DRC_KNEE2_OP_MASK            0x001F  /* DSP1DRC_KNEE2_OP - [4:0] */
-#define WM8915_DSP1DRC_KNEE2_OP_SHIFT                0  /* DSP1DRC_KNEE2_OP - [4:0] */
-#define WM8915_DSP1DRC_KNEE2_OP_WIDTH                5  /* DSP1DRC_KNEE2_OP - [4:0] */
-
-/*
- * R1152 (0x480) - DSP1 RX EQ Gains (1)
- */
-#define WM8915_DSP1RX_EQ_B1_GAIN_MASK           0xF800  /* DSP1RX_EQ_B1_GAIN - [15:11] */
-#define WM8915_DSP1RX_EQ_B1_GAIN_SHIFT              11  /* DSP1RX_EQ_B1_GAIN - [15:11] */
-#define WM8915_DSP1RX_EQ_B1_GAIN_WIDTH               5  /* DSP1RX_EQ_B1_GAIN - [15:11] */
-#define WM8915_DSP1RX_EQ_B2_GAIN_MASK           0x07C0  /* DSP1RX_EQ_B2_GAIN - [10:6] */
-#define WM8915_DSP1RX_EQ_B2_GAIN_SHIFT               6  /* DSP1RX_EQ_B2_GAIN - [10:6] */
-#define WM8915_DSP1RX_EQ_B2_GAIN_WIDTH               5  /* DSP1RX_EQ_B2_GAIN - [10:6] */
-#define WM8915_DSP1RX_EQ_B3_GAIN_MASK           0x003E  /* DSP1RX_EQ_B3_GAIN - [5:1] */
-#define WM8915_DSP1RX_EQ_B3_GAIN_SHIFT               1  /* DSP1RX_EQ_B3_GAIN - [5:1] */
-#define WM8915_DSP1RX_EQ_B3_GAIN_WIDTH               5  /* DSP1RX_EQ_B3_GAIN - [5:1] */
-#define WM8915_DSP1RX_EQ_ENA                    0x0001  /* DSP1RX_EQ_ENA */
-#define WM8915_DSP1RX_EQ_ENA_MASK               0x0001  /* DSP1RX_EQ_ENA */
-#define WM8915_DSP1RX_EQ_ENA_SHIFT                   0  /* DSP1RX_EQ_ENA */
-#define WM8915_DSP1RX_EQ_ENA_WIDTH                   1  /* DSP1RX_EQ_ENA */
-
-/*
- * R1153 (0x481) - DSP1 RX EQ Gains (2)
- */
-#define WM8915_DSP1RX_EQ_B4_GAIN_MASK           0xF800  /* DSP1RX_EQ_B4_GAIN - [15:11] */
-#define WM8915_DSP1RX_EQ_B4_GAIN_SHIFT              11  /* DSP1RX_EQ_B4_GAIN - [15:11] */
-#define WM8915_DSP1RX_EQ_B4_GAIN_WIDTH               5  /* DSP1RX_EQ_B4_GAIN - [15:11] */
-#define WM8915_DSP1RX_EQ_B5_GAIN_MASK           0x07C0  /* DSP1RX_EQ_B5_GAIN - [10:6] */
-#define WM8915_DSP1RX_EQ_B5_GAIN_SHIFT               6  /* DSP1RX_EQ_B5_GAIN - [10:6] */
-#define WM8915_DSP1RX_EQ_B5_GAIN_WIDTH               5  /* DSP1RX_EQ_B5_GAIN - [10:6] */
-
-/*
- * R1154 (0x482) - DSP1 RX EQ Band 1 A
- */
-#define WM8915_DSP1RX_EQ_B1_A_MASK              0xFFFF  /* DSP1RX_EQ_B1_A - [15:0] */
-#define WM8915_DSP1RX_EQ_B1_A_SHIFT                  0  /* DSP1RX_EQ_B1_A - [15:0] */
-#define WM8915_DSP1RX_EQ_B1_A_WIDTH                 16  /* DSP1RX_EQ_B1_A - [15:0] */
-
-/*
- * R1155 (0x483) - DSP1 RX EQ Band 1 B
- */
-#define WM8915_DSP1RX_EQ_B1_B_MASK              0xFFFF  /* DSP1RX_EQ_B1_B - [15:0] */
-#define WM8915_DSP1RX_EQ_B1_B_SHIFT                  0  /* DSP1RX_EQ_B1_B - [15:0] */
-#define WM8915_DSP1RX_EQ_B1_B_WIDTH                 16  /* DSP1RX_EQ_B1_B - [15:0] */
-
-/*
- * R1156 (0x484) - DSP1 RX EQ Band 1 PG
- */
-#define WM8915_DSP1RX_EQ_B1_PG_MASK             0xFFFF  /* DSP1RX_EQ_B1_PG - [15:0] */
-#define WM8915_DSP1RX_EQ_B1_PG_SHIFT                 0  /* DSP1RX_EQ_B1_PG - [15:0] */
-#define WM8915_DSP1RX_EQ_B1_PG_WIDTH                16  /* DSP1RX_EQ_B1_PG - [15:0] */
-
-/*
- * R1157 (0x485) - DSP1 RX EQ Band 2 A
- */
-#define WM8915_DSP1RX_EQ_B2_A_MASK              0xFFFF  /* DSP1RX_EQ_B2_A - [15:0] */
-#define WM8915_DSP1RX_EQ_B2_A_SHIFT                  0  /* DSP1RX_EQ_B2_A - [15:0] */
-#define WM8915_DSP1RX_EQ_B2_A_WIDTH                 16  /* DSP1RX_EQ_B2_A - [15:0] */
-
-/*
- * R1158 (0x486) - DSP1 RX EQ Band 2 B
- */
-#define WM8915_DSP1RX_EQ_B2_B_MASK              0xFFFF  /* DSP1RX_EQ_B2_B - [15:0] */
-#define WM8915_DSP1RX_EQ_B2_B_SHIFT                  0  /* DSP1RX_EQ_B2_B - [15:0] */
-#define WM8915_DSP1RX_EQ_B2_B_WIDTH                 16  /* DSP1RX_EQ_B2_B - [15:0] */
-
-/*
- * R1159 (0x487) - DSP1 RX EQ Band 2 C
- */
-#define WM8915_DSP1RX_EQ_B2_C_MASK              0xFFFF  /* DSP1RX_EQ_B2_C - [15:0] */
-#define WM8915_DSP1RX_EQ_B2_C_SHIFT                  0  /* DSP1RX_EQ_B2_C - [15:0] */
-#define WM8915_DSP1RX_EQ_B2_C_WIDTH                 16  /* DSP1RX_EQ_B2_C - [15:0] */
-
-/*
- * R1160 (0x488) - DSP1 RX EQ Band 2 PG
- */
-#define WM8915_DSP1RX_EQ_B2_PG_MASK             0xFFFF  /* DSP1RX_EQ_B2_PG - [15:0] */
-#define WM8915_DSP1RX_EQ_B2_PG_SHIFT                 0  /* DSP1RX_EQ_B2_PG - [15:0] */
-#define WM8915_DSP1RX_EQ_B2_PG_WIDTH                16  /* DSP1RX_EQ_B2_PG - [15:0] */
-
-/*
- * R1161 (0x489) - DSP1 RX EQ Band 3 A
- */
-#define WM8915_DSP1RX_EQ_B3_A_MASK              0xFFFF  /* DSP1RX_EQ_B3_A - [15:0] */
-#define WM8915_DSP1RX_EQ_B3_A_SHIFT                  0  /* DSP1RX_EQ_B3_A - [15:0] */
-#define WM8915_DSP1RX_EQ_B3_A_WIDTH                 16  /* DSP1RX_EQ_B3_A - [15:0] */
-
-/*
- * R1162 (0x48A) - DSP1 RX EQ Band 3 B
- */
-#define WM8915_DSP1RX_EQ_B3_B_MASK              0xFFFF  /* DSP1RX_EQ_B3_B - [15:0] */
-#define WM8915_DSP1RX_EQ_B3_B_SHIFT                  0  /* DSP1RX_EQ_B3_B - [15:0] */
-#define WM8915_DSP1RX_EQ_B3_B_WIDTH                 16  /* DSP1RX_EQ_B3_B - [15:0] */
-
-/*
- * R1163 (0x48B) - DSP1 RX EQ Band 3 C
- */
-#define WM8915_DSP1RX_EQ_B3_C_MASK              0xFFFF  /* DSP1RX_EQ_B3_C - [15:0] */
-#define WM8915_DSP1RX_EQ_B3_C_SHIFT                  0  /* DSP1RX_EQ_B3_C - [15:0] */
-#define WM8915_DSP1RX_EQ_B3_C_WIDTH                 16  /* DSP1RX_EQ_B3_C - [15:0] */
-
-/*
- * R1164 (0x48C) - DSP1 RX EQ Band 3 PG
- */
-#define WM8915_DSP1RX_EQ_B3_PG_MASK             0xFFFF  /* DSP1RX_EQ_B3_PG - [15:0] */
-#define WM8915_DSP1RX_EQ_B3_PG_SHIFT                 0  /* DSP1RX_EQ_B3_PG - [15:0] */
-#define WM8915_DSP1RX_EQ_B3_PG_WIDTH                16  /* DSP1RX_EQ_B3_PG - [15:0] */
-
-/*
- * R1165 (0x48D) - DSP1 RX EQ Band 4 A
- */
-#define WM8915_DSP1RX_EQ_B4_A_MASK              0xFFFF  /* DSP1RX_EQ_B4_A - [15:0] */
-#define WM8915_DSP1RX_EQ_B4_A_SHIFT                  0  /* DSP1RX_EQ_B4_A - [15:0] */
-#define WM8915_DSP1RX_EQ_B4_A_WIDTH                 16  /* DSP1RX_EQ_B4_A - [15:0] */
-
-/*
- * R1166 (0x48E) - DSP1 RX EQ Band 4 B
- */
-#define WM8915_DSP1RX_EQ_B4_B_MASK              0xFFFF  /* DSP1RX_EQ_B4_B - [15:0] */
-#define WM8915_DSP1RX_EQ_B4_B_SHIFT                  0  /* DSP1RX_EQ_B4_B - [15:0] */
-#define WM8915_DSP1RX_EQ_B4_B_WIDTH                 16  /* DSP1RX_EQ_B4_B - [15:0] */
-
-/*
- * R1167 (0x48F) - DSP1 RX EQ Band 4 C
- */
-#define WM8915_DSP1RX_EQ_B4_C_MASK              0xFFFF  /* DSP1RX_EQ_B4_C - [15:0] */
-#define WM8915_DSP1RX_EQ_B4_C_SHIFT                  0  /* DSP1RX_EQ_B4_C - [15:0] */
-#define WM8915_DSP1RX_EQ_B4_C_WIDTH                 16  /* DSP1RX_EQ_B4_C - [15:0] */
-
-/*
- * R1168 (0x490) - DSP1 RX EQ Band 4 PG
- */
-#define WM8915_DSP1RX_EQ_B4_PG_MASK             0xFFFF  /* DSP1RX_EQ_B4_PG - [15:0] */
-#define WM8915_DSP1RX_EQ_B4_PG_SHIFT                 0  /* DSP1RX_EQ_B4_PG - [15:0] */
-#define WM8915_DSP1RX_EQ_B4_PG_WIDTH                16  /* DSP1RX_EQ_B4_PG - [15:0] */
-
-/*
- * R1169 (0x491) - DSP1 RX EQ Band 5 A
- */
-#define WM8915_DSP1RX_EQ_B5_A_MASK              0xFFFF  /* DSP1RX_EQ_B5_A - [15:0] */
-#define WM8915_DSP1RX_EQ_B5_A_SHIFT                  0  /* DSP1RX_EQ_B5_A - [15:0] */
-#define WM8915_DSP1RX_EQ_B5_A_WIDTH                 16  /* DSP1RX_EQ_B5_A - [15:0] */
-
-/*
- * R1170 (0x492) - DSP1 RX EQ Band 5 B
- */
-#define WM8915_DSP1RX_EQ_B5_B_MASK              0xFFFF  /* DSP1RX_EQ_B5_B - [15:0] */
-#define WM8915_DSP1RX_EQ_B5_B_SHIFT                  0  /* DSP1RX_EQ_B5_B - [15:0] */
-#define WM8915_DSP1RX_EQ_B5_B_WIDTH                 16  /* DSP1RX_EQ_B5_B - [15:0] */
-
-/*
- * R1171 (0x493) - DSP1 RX EQ Band 5 PG
- */
-#define WM8915_DSP1RX_EQ_B5_PG_MASK             0xFFFF  /* DSP1RX_EQ_B5_PG - [15:0] */
-#define WM8915_DSP1RX_EQ_B5_PG_SHIFT                 0  /* DSP1RX_EQ_B5_PG - [15:0] */
-#define WM8915_DSP1RX_EQ_B5_PG_WIDTH                16  /* DSP1RX_EQ_B5_PG - [15:0] */
-
-/*
- * R1280 (0x500) - DSP2 TX Left Volume
- */
-#define WM8915_DSP2TX_VU                        0x0100  /* DSP2TX_VU */
-#define WM8915_DSP2TX_VU_MASK                   0x0100  /* DSP2TX_VU */
-#define WM8915_DSP2TX_VU_SHIFT                       8  /* DSP2TX_VU */
-#define WM8915_DSP2TX_VU_WIDTH                       1  /* DSP2TX_VU */
-#define WM8915_DSP2TXL_VOL_MASK                 0x00FF  /* DSP2TXL_VOL - [7:0] */
-#define WM8915_DSP2TXL_VOL_SHIFT                     0  /* DSP2TXL_VOL - [7:0] */
-#define WM8915_DSP2TXL_VOL_WIDTH                     8  /* DSP2TXL_VOL - [7:0] */
-
-/*
- * R1281 (0x501) - DSP2 TX Right Volume
- */
-#define WM8915_DSP2TX_VU                        0x0100  /* DSP2TX_VU */
-#define WM8915_DSP2TX_VU_MASK                   0x0100  /* DSP2TX_VU */
-#define WM8915_DSP2TX_VU_SHIFT                       8  /* DSP2TX_VU */
-#define WM8915_DSP2TX_VU_WIDTH                       1  /* DSP2TX_VU */
-#define WM8915_DSP2TXR_VOL_MASK                 0x00FF  /* DSP2TXR_VOL - [7:0] */
-#define WM8915_DSP2TXR_VOL_SHIFT                     0  /* DSP2TXR_VOL - [7:0] */
-#define WM8915_DSP2TXR_VOL_WIDTH                     8  /* DSP2TXR_VOL - [7:0] */
-
-/*
- * R1282 (0x502) - DSP2 RX Left Volume
- */
-#define WM8915_DSP2RX_VU                        0x0100  /* DSP2RX_VU */
-#define WM8915_DSP2RX_VU_MASK                   0x0100  /* DSP2RX_VU */
-#define WM8915_DSP2RX_VU_SHIFT                       8  /* DSP2RX_VU */
-#define WM8915_DSP2RX_VU_WIDTH                       1  /* DSP2RX_VU */
-#define WM8915_DSP2RXL_VOL_MASK                 0x00FF  /* DSP2RXL_VOL - [7:0] */
-#define WM8915_DSP2RXL_VOL_SHIFT                     0  /* DSP2RXL_VOL - [7:0] */
-#define WM8915_DSP2RXL_VOL_WIDTH                     8  /* DSP2RXL_VOL - [7:0] */
-
-/*
- * R1283 (0x503) - DSP2 RX Right Volume
- */
-#define WM8915_DSP2RX_VU                        0x0100  /* DSP2RX_VU */
-#define WM8915_DSP2RX_VU_MASK                   0x0100  /* DSP2RX_VU */
-#define WM8915_DSP2RX_VU_SHIFT                       8  /* DSP2RX_VU */
-#define WM8915_DSP2RX_VU_WIDTH                       1  /* DSP2RX_VU */
-#define WM8915_DSP2RXR_VOL_MASK                 0x00FF  /* DSP2RXR_VOL - [7:0] */
-#define WM8915_DSP2RXR_VOL_SHIFT                     0  /* DSP2RXR_VOL - [7:0] */
-#define WM8915_DSP2RXR_VOL_WIDTH                     8  /* DSP2RXR_VOL - [7:0] */
-
-/*
- * R1296 (0x510) - DSP2 TX Filters
- */
-#define WM8915_DSP2TX_NF                        0x2000  /* DSP2TX_NF */
-#define WM8915_DSP2TX_NF_MASK                   0x2000  /* DSP2TX_NF */
-#define WM8915_DSP2TX_NF_SHIFT                      13  /* DSP2TX_NF */
-#define WM8915_DSP2TX_NF_WIDTH                       1  /* DSP2TX_NF */
-#define WM8915_DSP2TXL_HPF                      0x1000  /* DSP2TXL_HPF */
-#define WM8915_DSP2TXL_HPF_MASK                 0x1000  /* DSP2TXL_HPF */
-#define WM8915_DSP2TXL_HPF_SHIFT                    12  /* DSP2TXL_HPF */
-#define WM8915_DSP2TXL_HPF_WIDTH                     1  /* DSP2TXL_HPF */
-#define WM8915_DSP2TXR_HPF                      0x0800  /* DSP2TXR_HPF */
-#define WM8915_DSP2TXR_HPF_MASK                 0x0800  /* DSP2TXR_HPF */
-#define WM8915_DSP2TXR_HPF_SHIFT                    11  /* DSP2TXR_HPF */
-#define WM8915_DSP2TXR_HPF_WIDTH                     1  /* DSP2TXR_HPF */
-#define WM8915_DSP2TX_HPF_MODE_MASK             0x0018  /* DSP2TX_HPF_MODE - [4:3] */
-#define WM8915_DSP2TX_HPF_MODE_SHIFT                 3  /* DSP2TX_HPF_MODE - [4:3] */
-#define WM8915_DSP2TX_HPF_MODE_WIDTH                 2  /* DSP2TX_HPF_MODE - [4:3] */
-#define WM8915_DSP2TX_HPF_CUT_MASK              0x0007  /* DSP2TX_HPF_CUT - [2:0] */
-#define WM8915_DSP2TX_HPF_CUT_SHIFT                  0  /* DSP2TX_HPF_CUT - [2:0] */
-#define WM8915_DSP2TX_HPF_CUT_WIDTH                  3  /* DSP2TX_HPF_CUT - [2:0] */
-
-/*
- * R1312 (0x520) - DSP2 RX Filters (1)
- */
-#define WM8915_DSP2RX_MUTE                      0x0200  /* DSP2RX_MUTE */
-#define WM8915_DSP2RX_MUTE_MASK                 0x0200  /* DSP2RX_MUTE */
-#define WM8915_DSP2RX_MUTE_SHIFT                     9  /* DSP2RX_MUTE */
-#define WM8915_DSP2RX_MUTE_WIDTH                     1  /* DSP2RX_MUTE */
-#define WM8915_DSP2RX_MONO                      0x0080  /* DSP2RX_MONO */
-#define WM8915_DSP2RX_MONO_MASK                 0x0080  /* DSP2RX_MONO */
-#define WM8915_DSP2RX_MONO_SHIFT                     7  /* DSP2RX_MONO */
-#define WM8915_DSP2RX_MONO_WIDTH                     1  /* DSP2RX_MONO */
-#define WM8915_DSP2RX_MUTERATE                  0x0020  /* DSP2RX_MUTERATE */
-#define WM8915_DSP2RX_MUTERATE_MASK             0x0020  /* DSP2RX_MUTERATE */
-#define WM8915_DSP2RX_MUTERATE_SHIFT                 5  /* DSP2RX_MUTERATE */
-#define WM8915_DSP2RX_MUTERATE_WIDTH                 1  /* DSP2RX_MUTERATE */
-#define WM8915_DSP2RX_UNMUTE_RAMP               0x0010  /* DSP2RX_UNMUTE_RAMP */
-#define WM8915_DSP2RX_UNMUTE_RAMP_MASK          0x0010  /* DSP2RX_UNMUTE_RAMP */
-#define WM8915_DSP2RX_UNMUTE_RAMP_SHIFT              4  /* DSP2RX_UNMUTE_RAMP */
-#define WM8915_DSP2RX_UNMUTE_RAMP_WIDTH              1  /* DSP2RX_UNMUTE_RAMP */
-
-/*
- * R1313 (0x521) - DSP2 RX Filters (2)
- */
-#define WM8915_DSP2RX_3D_GAIN_MASK              0x3E00  /* DSP2RX_3D_GAIN - [13:9] */
-#define WM8915_DSP2RX_3D_GAIN_SHIFT                  9  /* DSP2RX_3D_GAIN - [13:9] */
-#define WM8915_DSP2RX_3D_GAIN_WIDTH                  5  /* DSP2RX_3D_GAIN - [13:9] */
-#define WM8915_DSP2RX_3D_ENA                    0x0100  /* DSP2RX_3D_ENA */
-#define WM8915_DSP2RX_3D_ENA_MASK               0x0100  /* DSP2RX_3D_ENA */
-#define WM8915_DSP2RX_3D_ENA_SHIFT                   8  /* DSP2RX_3D_ENA */
-#define WM8915_DSP2RX_3D_ENA_WIDTH                   1  /* DSP2RX_3D_ENA */
-
-/*
- * R1344 (0x540) - DSP2 DRC (1)
- */
-#define WM8915_DSP2DRC_SIG_DET_RMS_MASK         0xF800  /* DSP2DRC_SIG_DET_RMS - [15:11] */
-#define WM8915_DSP2DRC_SIG_DET_RMS_SHIFT            11  /* DSP2DRC_SIG_DET_RMS - [15:11] */
-#define WM8915_DSP2DRC_SIG_DET_RMS_WIDTH             5  /* DSP2DRC_SIG_DET_RMS - [15:11] */
-#define WM8915_DSP2DRC_SIG_DET_PK_MASK          0x0600  /* DSP2DRC_SIG_DET_PK - [10:9] */
-#define WM8915_DSP2DRC_SIG_DET_PK_SHIFT              9  /* DSP2DRC_SIG_DET_PK - [10:9] */
-#define WM8915_DSP2DRC_SIG_DET_PK_WIDTH              2  /* DSP2DRC_SIG_DET_PK - [10:9] */
-#define WM8915_DSP2DRC_NG_ENA                   0x0100  /* DSP2DRC_NG_ENA */
-#define WM8915_DSP2DRC_NG_ENA_MASK              0x0100  /* DSP2DRC_NG_ENA */
-#define WM8915_DSP2DRC_NG_ENA_SHIFT                  8  /* DSP2DRC_NG_ENA */
-#define WM8915_DSP2DRC_NG_ENA_WIDTH                  1  /* DSP2DRC_NG_ENA */
-#define WM8915_DSP2DRC_SIG_DET_MODE             0x0080  /* DSP2DRC_SIG_DET_MODE */
-#define WM8915_DSP2DRC_SIG_DET_MODE_MASK        0x0080  /* DSP2DRC_SIG_DET_MODE */
-#define WM8915_DSP2DRC_SIG_DET_MODE_SHIFT            7  /* DSP2DRC_SIG_DET_MODE */
-#define WM8915_DSP2DRC_SIG_DET_MODE_WIDTH            1  /* DSP2DRC_SIG_DET_MODE */
-#define WM8915_DSP2DRC_SIG_DET                  0x0040  /* DSP2DRC_SIG_DET */
-#define WM8915_DSP2DRC_SIG_DET_MASK             0x0040  /* DSP2DRC_SIG_DET */
-#define WM8915_DSP2DRC_SIG_DET_SHIFT                 6  /* DSP2DRC_SIG_DET */
-#define WM8915_DSP2DRC_SIG_DET_WIDTH                 1  /* DSP2DRC_SIG_DET */
-#define WM8915_DSP2DRC_KNEE2_OP_ENA             0x0020  /* DSP2DRC_KNEE2_OP_ENA */
-#define WM8915_DSP2DRC_KNEE2_OP_ENA_MASK        0x0020  /* DSP2DRC_KNEE2_OP_ENA */
-#define WM8915_DSP2DRC_KNEE2_OP_ENA_SHIFT            5  /* DSP2DRC_KNEE2_OP_ENA */
-#define WM8915_DSP2DRC_KNEE2_OP_ENA_WIDTH            1  /* DSP2DRC_KNEE2_OP_ENA */
-#define WM8915_DSP2DRC_QR                       0x0010  /* DSP2DRC_QR */
-#define WM8915_DSP2DRC_QR_MASK                  0x0010  /* DSP2DRC_QR */
-#define WM8915_DSP2DRC_QR_SHIFT                      4  /* DSP2DRC_QR */
-#define WM8915_DSP2DRC_QR_WIDTH                      1  /* DSP2DRC_QR */
-#define WM8915_DSP2DRC_ANTICLIP                 0x0008  /* DSP2DRC_ANTICLIP */
-#define WM8915_DSP2DRC_ANTICLIP_MASK            0x0008  /* DSP2DRC_ANTICLIP */
-#define WM8915_DSP2DRC_ANTICLIP_SHIFT                3  /* DSP2DRC_ANTICLIP */
-#define WM8915_DSP2DRC_ANTICLIP_WIDTH                1  /* DSP2DRC_ANTICLIP */
-#define WM8915_DSP2RX_DRC_ENA                   0x0004  /* DSP2RX_DRC_ENA */
-#define WM8915_DSP2RX_DRC_ENA_MASK              0x0004  /* DSP2RX_DRC_ENA */
-#define WM8915_DSP2RX_DRC_ENA_SHIFT                  2  /* DSP2RX_DRC_ENA */
-#define WM8915_DSP2RX_DRC_ENA_WIDTH                  1  /* DSP2RX_DRC_ENA */
-#define WM8915_DSP2TXL_DRC_ENA                  0x0002  /* DSP2TXL_DRC_ENA */
-#define WM8915_DSP2TXL_DRC_ENA_MASK             0x0002  /* DSP2TXL_DRC_ENA */
-#define WM8915_DSP2TXL_DRC_ENA_SHIFT                 1  /* DSP2TXL_DRC_ENA */
-#define WM8915_DSP2TXL_DRC_ENA_WIDTH                 1  /* DSP2TXL_DRC_ENA */
-#define WM8915_DSP2TXR_DRC_ENA                  0x0001  /* DSP2TXR_DRC_ENA */
-#define WM8915_DSP2TXR_DRC_ENA_MASK             0x0001  /* DSP2TXR_DRC_ENA */
-#define WM8915_DSP2TXR_DRC_ENA_SHIFT                 0  /* DSP2TXR_DRC_ENA */
-#define WM8915_DSP2TXR_DRC_ENA_WIDTH                 1  /* DSP2TXR_DRC_ENA */
-
-/*
- * R1345 (0x541) - DSP2 DRC (2)
- */
-#define WM8915_DSP2DRC_ATK_MASK                 0x1E00  /* DSP2DRC_ATK - [12:9] */
-#define WM8915_DSP2DRC_ATK_SHIFT                     9  /* DSP2DRC_ATK - [12:9] */
-#define WM8915_DSP2DRC_ATK_WIDTH                     4  /* DSP2DRC_ATK - [12:9] */
-#define WM8915_DSP2DRC_DCY_MASK                 0x01E0  /* DSP2DRC_DCY - [8:5] */
-#define WM8915_DSP2DRC_DCY_SHIFT                     5  /* DSP2DRC_DCY - [8:5] */
-#define WM8915_DSP2DRC_DCY_WIDTH                     4  /* DSP2DRC_DCY - [8:5] */
-#define WM8915_DSP2DRC_MINGAIN_MASK             0x001C  /* DSP2DRC_MINGAIN - [4:2] */
-#define WM8915_DSP2DRC_MINGAIN_SHIFT                 2  /* DSP2DRC_MINGAIN - [4:2] */
-#define WM8915_DSP2DRC_MINGAIN_WIDTH                 3  /* DSP2DRC_MINGAIN - [4:2] */
-#define WM8915_DSP2DRC_MAXGAIN_MASK             0x0003  /* DSP2DRC_MAXGAIN - [1:0] */
-#define WM8915_DSP2DRC_MAXGAIN_SHIFT                 0  /* DSP2DRC_MAXGAIN - [1:0] */
-#define WM8915_DSP2DRC_MAXGAIN_WIDTH                 2  /* DSP2DRC_MAXGAIN - [1:0] */
-
-/*
- * R1346 (0x542) - DSP2 DRC (3)
- */
-#define WM8915_DSP2DRC_NG_MINGAIN_MASK          0xF000  /* DSP2DRC_NG_MINGAIN - [15:12] */
-#define WM8915_DSP2DRC_NG_MINGAIN_SHIFT             12  /* DSP2DRC_NG_MINGAIN - [15:12] */
-#define WM8915_DSP2DRC_NG_MINGAIN_WIDTH              4  /* DSP2DRC_NG_MINGAIN - [15:12] */
-#define WM8915_DSP2DRC_NG_EXP_MASK              0x0C00  /* DSP2DRC_NG_EXP - [11:10] */
-#define WM8915_DSP2DRC_NG_EXP_SHIFT                 10  /* DSP2DRC_NG_EXP - [11:10] */
-#define WM8915_DSP2DRC_NG_EXP_WIDTH                  2  /* DSP2DRC_NG_EXP - [11:10] */
-#define WM8915_DSP2DRC_QR_THR_MASK              0x0300  /* DSP2DRC_QR_THR - [9:8] */
-#define WM8915_DSP2DRC_QR_THR_SHIFT                  8  /* DSP2DRC_QR_THR - [9:8] */
-#define WM8915_DSP2DRC_QR_THR_WIDTH                  2  /* DSP2DRC_QR_THR - [9:8] */
-#define WM8915_DSP2DRC_QR_DCY_MASK              0x00C0  /* DSP2DRC_QR_DCY - [7:6] */
-#define WM8915_DSP2DRC_QR_DCY_SHIFT                  6  /* DSP2DRC_QR_DCY - [7:6] */
-#define WM8915_DSP2DRC_QR_DCY_WIDTH                  2  /* DSP2DRC_QR_DCY - [7:6] */
-#define WM8915_DSP2DRC_HI_COMP_MASK             0x0038  /* DSP2DRC_HI_COMP - [5:3] */
-#define WM8915_DSP2DRC_HI_COMP_SHIFT                 3  /* DSP2DRC_HI_COMP - [5:3] */
-#define WM8915_DSP2DRC_HI_COMP_WIDTH                 3  /* DSP2DRC_HI_COMP - [5:3] */
-#define WM8915_DSP2DRC_LO_COMP_MASK             0x0007  /* DSP2DRC_LO_COMP - [2:0] */
-#define WM8915_DSP2DRC_LO_COMP_SHIFT                 0  /* DSP2DRC_LO_COMP - [2:0] */
-#define WM8915_DSP2DRC_LO_COMP_WIDTH                 3  /* DSP2DRC_LO_COMP - [2:0] */
-
-/*
- * R1347 (0x543) - DSP2 DRC (4)
- */
-#define WM8915_DSP2DRC_KNEE_IP_MASK             0x07E0  /* DSP2DRC_KNEE_IP - [10:5] */
-#define WM8915_DSP2DRC_KNEE_IP_SHIFT                 5  /* DSP2DRC_KNEE_IP - [10:5] */
-#define WM8915_DSP2DRC_KNEE_IP_WIDTH                 6  /* DSP2DRC_KNEE_IP - [10:5] */
-#define WM8915_DSP2DRC_KNEE_OP_MASK             0x001F  /* DSP2DRC_KNEE_OP - [4:0] */
-#define WM8915_DSP2DRC_KNEE_OP_SHIFT                 0  /* DSP2DRC_KNEE_OP - [4:0] */
-#define WM8915_DSP2DRC_KNEE_OP_WIDTH                 5  /* DSP2DRC_KNEE_OP - [4:0] */
-
-/*
- * R1348 (0x544) - DSP2 DRC (5)
- */
-#define WM8915_DSP2DRC_KNEE2_IP_MASK            0x03E0  /* DSP2DRC_KNEE2_IP - [9:5] */
-#define WM8915_DSP2DRC_KNEE2_IP_SHIFT                5  /* DSP2DRC_KNEE2_IP - [9:5] */
-#define WM8915_DSP2DRC_KNEE2_IP_WIDTH                5  /* DSP2DRC_KNEE2_IP - [9:5] */
-#define WM8915_DSP2DRC_KNEE2_OP_MASK            0x001F  /* DSP2DRC_KNEE2_OP - [4:0] */
-#define WM8915_DSP2DRC_KNEE2_OP_SHIFT                0  /* DSP2DRC_KNEE2_OP - [4:0] */
-#define WM8915_DSP2DRC_KNEE2_OP_WIDTH                5  /* DSP2DRC_KNEE2_OP - [4:0] */
-
-/*
- * R1408 (0x580) - DSP2 RX EQ Gains (1)
- */
-#define WM8915_DSP2RX_EQ_B1_GAIN_MASK           0xF800  /* DSP2RX_EQ_B1_GAIN - [15:11] */
-#define WM8915_DSP2RX_EQ_B1_GAIN_SHIFT              11  /* DSP2RX_EQ_B1_GAIN - [15:11] */
-#define WM8915_DSP2RX_EQ_B1_GAIN_WIDTH               5  /* DSP2RX_EQ_B1_GAIN - [15:11] */
-#define WM8915_DSP2RX_EQ_B2_GAIN_MASK           0x07C0  /* DSP2RX_EQ_B2_GAIN - [10:6] */
-#define WM8915_DSP2RX_EQ_B2_GAIN_SHIFT               6  /* DSP2RX_EQ_B2_GAIN - [10:6] */
-#define WM8915_DSP2RX_EQ_B2_GAIN_WIDTH               5  /* DSP2RX_EQ_B2_GAIN - [10:6] */
-#define WM8915_DSP2RX_EQ_B3_GAIN_MASK           0x003E  /* DSP2RX_EQ_B3_GAIN - [5:1] */
-#define WM8915_DSP2RX_EQ_B3_GAIN_SHIFT               1  /* DSP2RX_EQ_B3_GAIN - [5:1] */
-#define WM8915_DSP2RX_EQ_B3_GAIN_WIDTH               5  /* DSP2RX_EQ_B3_GAIN - [5:1] */
-#define WM8915_DSP2RX_EQ_ENA                    0x0001  /* DSP2RX_EQ_ENA */
-#define WM8915_DSP2RX_EQ_ENA_MASK               0x0001  /* DSP2RX_EQ_ENA */
-#define WM8915_DSP2RX_EQ_ENA_SHIFT                   0  /* DSP2RX_EQ_ENA */
-#define WM8915_DSP2RX_EQ_ENA_WIDTH                   1  /* DSP2RX_EQ_ENA */
-
-/*
- * R1409 (0x581) - DSP2 RX EQ Gains (2)
- */
-#define WM8915_DSP2RX_EQ_B4_GAIN_MASK           0xF800  /* DSP2RX_EQ_B4_GAIN - [15:11] */
-#define WM8915_DSP2RX_EQ_B4_GAIN_SHIFT              11  /* DSP2RX_EQ_B4_GAIN - [15:11] */
-#define WM8915_DSP2RX_EQ_B4_GAIN_WIDTH               5  /* DSP2RX_EQ_B4_GAIN - [15:11] */
-#define WM8915_DSP2RX_EQ_B5_GAIN_MASK           0x07C0  /* DSP2RX_EQ_B5_GAIN - [10:6] */
-#define WM8915_DSP2RX_EQ_B5_GAIN_SHIFT               6  /* DSP2RX_EQ_B5_GAIN - [10:6] */
-#define WM8915_DSP2RX_EQ_B5_GAIN_WIDTH               5  /* DSP2RX_EQ_B5_GAIN - [10:6] */
-
-/*
- * R1410 (0x582) - DSP2 RX EQ Band 1 A
- */
-#define WM8915_DSP2RX_EQ_B1_A_MASK              0xFFFF  /* DSP2RX_EQ_B1_A - [15:0] */
-#define WM8915_DSP2RX_EQ_B1_A_SHIFT                  0  /* DSP2RX_EQ_B1_A - [15:0] */
-#define WM8915_DSP2RX_EQ_B1_A_WIDTH                 16  /* DSP2RX_EQ_B1_A - [15:0] */
-
-/*
- * R1411 (0x583) - DSP2 RX EQ Band 1 B
- */
-#define WM8915_DSP2RX_EQ_B1_B_MASK              0xFFFF  /* DSP2RX_EQ_B1_B - [15:0] */
-#define WM8915_DSP2RX_EQ_B1_B_SHIFT                  0  /* DSP2RX_EQ_B1_B - [15:0] */
-#define WM8915_DSP2RX_EQ_B1_B_WIDTH                 16  /* DSP2RX_EQ_B1_B - [15:0] */
-
-/*
- * R1412 (0x584) - DSP2 RX EQ Band 1 PG
- */
-#define WM8915_DSP2RX_EQ_B1_PG_MASK             0xFFFF  /* DSP2RX_EQ_B1_PG - [15:0] */
-#define WM8915_DSP2RX_EQ_B1_PG_SHIFT                 0  /* DSP2RX_EQ_B1_PG - [15:0] */
-#define WM8915_DSP2RX_EQ_B1_PG_WIDTH                16  /* DSP2RX_EQ_B1_PG - [15:0] */
-
-/*
- * R1413 (0x585) - DSP2 RX EQ Band 2 A
- */
-#define WM8915_DSP2RX_EQ_B2_A_MASK              0xFFFF  /* DSP2RX_EQ_B2_A - [15:0] */
-#define WM8915_DSP2RX_EQ_B2_A_SHIFT                  0  /* DSP2RX_EQ_B2_A - [15:0] */
-#define WM8915_DSP2RX_EQ_B2_A_WIDTH                 16  /* DSP2RX_EQ_B2_A - [15:0] */
-
-/*
- * R1414 (0x586) - DSP2 RX EQ Band 2 B
- */
-#define WM8915_DSP2RX_EQ_B2_B_MASK              0xFFFF  /* DSP2RX_EQ_B2_B - [15:0] */
-#define WM8915_DSP2RX_EQ_B2_B_SHIFT                  0  /* DSP2RX_EQ_B2_B - [15:0] */
-#define WM8915_DSP2RX_EQ_B2_B_WIDTH                 16  /* DSP2RX_EQ_B2_B - [15:0] */
-
-/*
- * R1415 (0x587) - DSP2 RX EQ Band 2 C
- */
-#define WM8915_DSP2RX_EQ_B2_C_MASK              0xFFFF  /* DSP2RX_EQ_B2_C - [15:0] */
-#define WM8915_DSP2RX_EQ_B2_C_SHIFT                  0  /* DSP2RX_EQ_B2_C - [15:0] */
-#define WM8915_DSP2RX_EQ_B2_C_WIDTH                 16  /* DSP2RX_EQ_B2_C - [15:0] */
-
-/*
- * R1416 (0x588) - DSP2 RX EQ Band 2 PG
- */
-#define WM8915_DSP2RX_EQ_B2_PG_MASK             0xFFFF  /* DSP2RX_EQ_B2_PG - [15:0] */
-#define WM8915_DSP2RX_EQ_B2_PG_SHIFT                 0  /* DSP2RX_EQ_B2_PG - [15:0] */
-#define WM8915_DSP2RX_EQ_B2_PG_WIDTH                16  /* DSP2RX_EQ_B2_PG - [15:0] */
-
-/*
- * R1417 (0x589) - DSP2 RX EQ Band 3 A
- */
-#define WM8915_DSP2RX_EQ_B3_A_MASK              0xFFFF  /* DSP2RX_EQ_B3_A - [15:0] */
-#define WM8915_DSP2RX_EQ_B3_A_SHIFT                  0  /* DSP2RX_EQ_B3_A - [15:0] */
-#define WM8915_DSP2RX_EQ_B3_A_WIDTH                 16  /* DSP2RX_EQ_B3_A - [15:0] */
-
-/*
- * R1418 (0x58A) - DSP2 RX EQ Band 3 B
- */
-#define WM8915_DSP2RX_EQ_B3_B_MASK              0xFFFF  /* DSP2RX_EQ_B3_B - [15:0] */
-#define WM8915_DSP2RX_EQ_B3_B_SHIFT                  0  /* DSP2RX_EQ_B3_B - [15:0] */
-#define WM8915_DSP2RX_EQ_B3_B_WIDTH                 16  /* DSP2RX_EQ_B3_B - [15:0] */
-
-/*
- * R1419 (0x58B) - DSP2 RX EQ Band 3 C
- */
-#define WM8915_DSP2RX_EQ_B3_C_MASK              0xFFFF  /* DSP2RX_EQ_B3_C - [15:0] */
-#define WM8915_DSP2RX_EQ_B3_C_SHIFT                  0  /* DSP2RX_EQ_B3_C - [15:0] */
-#define WM8915_DSP2RX_EQ_B3_C_WIDTH                 16  /* DSP2RX_EQ_B3_C - [15:0] */
-
-/*
- * R1420 (0x58C) - DSP2 RX EQ Band 3 PG
- */
-#define WM8915_DSP2RX_EQ_B3_PG_MASK             0xFFFF  /* DSP2RX_EQ_B3_PG - [15:0] */
-#define WM8915_DSP2RX_EQ_B3_PG_SHIFT                 0  /* DSP2RX_EQ_B3_PG - [15:0] */
-#define WM8915_DSP2RX_EQ_B3_PG_WIDTH                16  /* DSP2RX_EQ_B3_PG - [15:0] */
-
-/*
- * R1421 (0x58D) - DSP2 RX EQ Band 4 A
- */
-#define WM8915_DSP2RX_EQ_B4_A_MASK              0xFFFF  /* DSP2RX_EQ_B4_A - [15:0] */
-#define WM8915_DSP2RX_EQ_B4_A_SHIFT                  0  /* DSP2RX_EQ_B4_A - [15:0] */
-#define WM8915_DSP2RX_EQ_B4_A_WIDTH                 16  /* DSP2RX_EQ_B4_A - [15:0] */
-
-/*
- * R1422 (0x58E) - DSP2 RX EQ Band 4 B
- */
-#define WM8915_DSP2RX_EQ_B4_B_MASK              0xFFFF  /* DSP2RX_EQ_B4_B - [15:0] */
-#define WM8915_DSP2RX_EQ_B4_B_SHIFT                  0  /* DSP2RX_EQ_B4_B - [15:0] */
-#define WM8915_DSP2RX_EQ_B4_B_WIDTH                 16  /* DSP2RX_EQ_B4_B - [15:0] */
-
-/*
- * R1423 (0x58F) - DSP2 RX EQ Band 4 C
- */
-#define WM8915_DSP2RX_EQ_B4_C_MASK              0xFFFF  /* DSP2RX_EQ_B4_C - [15:0] */
-#define WM8915_DSP2RX_EQ_B4_C_SHIFT                  0  /* DSP2RX_EQ_B4_C - [15:0] */
-#define WM8915_DSP2RX_EQ_B4_C_WIDTH                 16  /* DSP2RX_EQ_B4_C - [15:0] */
-
-/*
- * R1424 (0x590) - DSP2 RX EQ Band 4 PG
- */
-#define WM8915_DSP2RX_EQ_B4_PG_MASK             0xFFFF  /* DSP2RX_EQ_B4_PG - [15:0] */
-#define WM8915_DSP2RX_EQ_B4_PG_SHIFT                 0  /* DSP2RX_EQ_B4_PG - [15:0] */
-#define WM8915_DSP2RX_EQ_B4_PG_WIDTH                16  /* DSP2RX_EQ_B4_PG - [15:0] */
-
-/*
- * R1425 (0x591) - DSP2 RX EQ Band 5 A
- */
-#define WM8915_DSP2RX_EQ_B5_A_MASK              0xFFFF  /* DSP2RX_EQ_B5_A - [15:0] */
-#define WM8915_DSP2RX_EQ_B5_A_SHIFT                  0  /* DSP2RX_EQ_B5_A - [15:0] */
-#define WM8915_DSP2RX_EQ_B5_A_WIDTH                 16  /* DSP2RX_EQ_B5_A - [15:0] */
-
-/*
- * R1426 (0x592) - DSP2 RX EQ Band 5 B
- */
-#define WM8915_DSP2RX_EQ_B5_B_MASK              0xFFFF  /* DSP2RX_EQ_B5_B - [15:0] */
-#define WM8915_DSP2RX_EQ_B5_B_SHIFT                  0  /* DSP2RX_EQ_B5_B - [15:0] */
-#define WM8915_DSP2RX_EQ_B5_B_WIDTH                 16  /* DSP2RX_EQ_B5_B - [15:0] */
-
-/*
- * R1427 (0x593) - DSP2 RX EQ Band 5 PG
- */
-#define WM8915_DSP2RX_EQ_B5_PG_MASK             0xFFFF  /* DSP2RX_EQ_B5_PG - [15:0] */
-#define WM8915_DSP2RX_EQ_B5_PG_SHIFT                 0  /* DSP2RX_EQ_B5_PG - [15:0] */
-#define WM8915_DSP2RX_EQ_B5_PG_WIDTH                16  /* DSP2RX_EQ_B5_PG - [15:0] */
-
-/*
- * R1536 (0x600) - DAC1 Mixer Volumes
- */
-#define WM8915_ADCR_DAC1_VOL_MASK               0x03E0  /* ADCR_DAC1_VOL - [9:5] */
-#define WM8915_ADCR_DAC1_VOL_SHIFT                   5  /* ADCR_DAC1_VOL - [9:5] */
-#define WM8915_ADCR_DAC1_VOL_WIDTH                   5  /* ADCR_DAC1_VOL - [9:5] */
-#define WM8915_ADCL_DAC1_VOL_MASK               0x001F  /* ADCL_DAC1_VOL - [4:0] */
-#define WM8915_ADCL_DAC1_VOL_SHIFT                   0  /* ADCL_DAC1_VOL - [4:0] */
-#define WM8915_ADCL_DAC1_VOL_WIDTH                   5  /* ADCL_DAC1_VOL - [4:0] */
-
-/*
- * R1537 (0x601) - DAC1 Left Mixer Routing
- */
-#define WM8915_ADCR_TO_DAC1L                    0x0020  /* ADCR_TO_DAC1L */
-#define WM8915_ADCR_TO_DAC1L_MASK               0x0020  /* ADCR_TO_DAC1L */
-#define WM8915_ADCR_TO_DAC1L_SHIFT                   5  /* ADCR_TO_DAC1L */
-#define WM8915_ADCR_TO_DAC1L_WIDTH                   1  /* ADCR_TO_DAC1L */
-#define WM8915_ADCL_TO_DAC1L                    0x0010  /* ADCL_TO_DAC1L */
-#define WM8915_ADCL_TO_DAC1L_MASK               0x0010  /* ADCL_TO_DAC1L */
-#define WM8915_ADCL_TO_DAC1L_SHIFT                   4  /* ADCL_TO_DAC1L */
-#define WM8915_ADCL_TO_DAC1L_WIDTH                   1  /* ADCL_TO_DAC1L */
-#define WM8915_DSP2RXL_TO_DAC1L                 0x0002  /* DSP2RXL_TO_DAC1L */
-#define WM8915_DSP2RXL_TO_DAC1L_MASK            0x0002  /* DSP2RXL_TO_DAC1L */
-#define WM8915_DSP2RXL_TO_DAC1L_SHIFT                1  /* DSP2RXL_TO_DAC1L */
-#define WM8915_DSP2RXL_TO_DAC1L_WIDTH                1  /* DSP2RXL_TO_DAC1L */
-#define WM8915_DSP1RXL_TO_DAC1L                 0x0001  /* DSP1RXL_TO_DAC1L */
-#define WM8915_DSP1RXL_TO_DAC1L_MASK            0x0001  /* DSP1RXL_TO_DAC1L */
-#define WM8915_DSP1RXL_TO_DAC1L_SHIFT                0  /* DSP1RXL_TO_DAC1L */
-#define WM8915_DSP1RXL_TO_DAC1L_WIDTH                1  /* DSP1RXL_TO_DAC1L */
-
-/*
- * R1538 (0x602) - DAC1 Right Mixer Routing
- */
-#define WM8915_ADCR_TO_DAC1R                    0x0020  /* ADCR_TO_DAC1R */
-#define WM8915_ADCR_TO_DAC1R_MASK               0x0020  /* ADCR_TO_DAC1R */
-#define WM8915_ADCR_TO_DAC1R_SHIFT                   5  /* ADCR_TO_DAC1R */
-#define WM8915_ADCR_TO_DAC1R_WIDTH                   1  /* ADCR_TO_DAC1R */
-#define WM8915_ADCL_TO_DAC1R                    0x0010  /* ADCL_TO_DAC1R */
-#define WM8915_ADCL_TO_DAC1R_MASK               0x0010  /* ADCL_TO_DAC1R */
-#define WM8915_ADCL_TO_DAC1R_SHIFT                   4  /* ADCL_TO_DAC1R */
-#define WM8915_ADCL_TO_DAC1R_WIDTH                   1  /* ADCL_TO_DAC1R */
-#define WM8915_DSP2RXR_TO_DAC1R                 0x0002  /* DSP2RXR_TO_DAC1R */
-#define WM8915_DSP2RXR_TO_DAC1R_MASK            0x0002  /* DSP2RXR_TO_DAC1R */
-#define WM8915_DSP2RXR_TO_DAC1R_SHIFT                1  /* DSP2RXR_TO_DAC1R */
-#define WM8915_DSP2RXR_TO_DAC1R_WIDTH                1  /* DSP2RXR_TO_DAC1R */
-#define WM8915_DSP1RXR_TO_DAC1R                 0x0001  /* DSP1RXR_TO_DAC1R */
-#define WM8915_DSP1RXR_TO_DAC1R_MASK            0x0001  /* DSP1RXR_TO_DAC1R */
-#define WM8915_DSP1RXR_TO_DAC1R_SHIFT                0  /* DSP1RXR_TO_DAC1R */
-#define WM8915_DSP1RXR_TO_DAC1R_WIDTH                1  /* DSP1RXR_TO_DAC1R */
-
-/*
- * R1539 (0x603) - DAC2 Mixer Volumes
- */
-#define WM8915_ADCR_DAC2_VOL_MASK               0x03E0  /* ADCR_DAC2_VOL - [9:5] */
-#define WM8915_ADCR_DAC2_VOL_SHIFT                   5  /* ADCR_DAC2_VOL - [9:5] */
-#define WM8915_ADCR_DAC2_VOL_WIDTH                   5  /* ADCR_DAC2_VOL - [9:5] */
-#define WM8915_ADCL_DAC2_VOL_MASK               0x001F  /* ADCL_DAC2_VOL - [4:0] */
-#define WM8915_ADCL_DAC2_VOL_SHIFT                   0  /* ADCL_DAC2_VOL - [4:0] */
-#define WM8915_ADCL_DAC2_VOL_WIDTH                   5  /* ADCL_DAC2_VOL - [4:0] */
-
-/*
- * R1540 (0x604) - DAC2 Left Mixer Routing
- */
-#define WM8915_ADCR_TO_DAC2L                    0x0020  /* ADCR_TO_DAC2L */
-#define WM8915_ADCR_TO_DAC2L_MASK               0x0020  /* ADCR_TO_DAC2L */
-#define WM8915_ADCR_TO_DAC2L_SHIFT                   5  /* ADCR_TO_DAC2L */
-#define WM8915_ADCR_TO_DAC2L_WIDTH                   1  /* ADCR_TO_DAC2L */
-#define WM8915_ADCL_TO_DAC2L                    0x0010  /* ADCL_TO_DAC2L */
-#define WM8915_ADCL_TO_DAC2L_MASK               0x0010  /* ADCL_TO_DAC2L */
-#define WM8915_ADCL_TO_DAC2L_SHIFT                   4  /* ADCL_TO_DAC2L */
-#define WM8915_ADCL_TO_DAC2L_WIDTH                   1  /* ADCL_TO_DAC2L */
-#define WM8915_DSP2RXL_TO_DAC2L                 0x0002  /* DSP2RXL_TO_DAC2L */
-#define WM8915_DSP2RXL_TO_DAC2L_MASK            0x0002  /* DSP2RXL_TO_DAC2L */
-#define WM8915_DSP2RXL_TO_DAC2L_SHIFT                1  /* DSP2RXL_TO_DAC2L */
-#define WM8915_DSP2RXL_TO_DAC2L_WIDTH                1  /* DSP2RXL_TO_DAC2L */
-#define WM8915_DSP1RXL_TO_DAC2L                 0x0001  /* DSP1RXL_TO_DAC2L */
-#define WM8915_DSP1RXL_TO_DAC2L_MASK            0x0001  /* DSP1RXL_TO_DAC2L */
-#define WM8915_DSP1RXL_TO_DAC2L_SHIFT                0  /* DSP1RXL_TO_DAC2L */
-#define WM8915_DSP1RXL_TO_DAC2L_WIDTH                1  /* DSP1RXL_TO_DAC2L */
-
-/*
- * R1541 (0x605) - DAC2 Right Mixer Routing
- */
-#define WM8915_ADCR_TO_DAC2R                    0x0020  /* ADCR_TO_DAC2R */
-#define WM8915_ADCR_TO_DAC2R_MASK               0x0020  /* ADCR_TO_DAC2R */
-#define WM8915_ADCR_TO_DAC2R_SHIFT                   5  /* ADCR_TO_DAC2R */
-#define WM8915_ADCR_TO_DAC2R_WIDTH                   1  /* ADCR_TO_DAC2R */
-#define WM8915_ADCL_TO_DAC2R                    0x0010  /* ADCL_TO_DAC2R */
-#define WM8915_ADCL_TO_DAC2R_MASK               0x0010  /* ADCL_TO_DAC2R */
-#define WM8915_ADCL_TO_DAC2R_SHIFT                   4  /* ADCL_TO_DAC2R */
-#define WM8915_ADCL_TO_DAC2R_WIDTH                   1  /* ADCL_TO_DAC2R */
-#define WM8915_DSP2RXR_TO_DAC2R                 0x0002  /* DSP2RXR_TO_DAC2R */
-#define WM8915_DSP2RXR_TO_DAC2R_MASK            0x0002  /* DSP2RXR_TO_DAC2R */
-#define WM8915_DSP2RXR_TO_DAC2R_SHIFT                1  /* DSP2RXR_TO_DAC2R */
-#define WM8915_DSP2RXR_TO_DAC2R_WIDTH                1  /* DSP2RXR_TO_DAC2R */
-#define WM8915_DSP1RXR_TO_DAC2R                 0x0001  /* DSP1RXR_TO_DAC2R */
-#define WM8915_DSP1RXR_TO_DAC2R_MASK            0x0001  /* DSP1RXR_TO_DAC2R */
-#define WM8915_DSP1RXR_TO_DAC2R_SHIFT                0  /* DSP1RXR_TO_DAC2R */
-#define WM8915_DSP1RXR_TO_DAC2R_WIDTH                1  /* DSP1RXR_TO_DAC2R */
-
-/*
- * R1542 (0x606) - DSP1 TX Left Mixer Routing
- */
-#define WM8915_ADC1L_TO_DSP1TXL                 0x0002  /* ADC1L_TO_DSP1TXL */
-#define WM8915_ADC1L_TO_DSP1TXL_MASK            0x0002  /* ADC1L_TO_DSP1TXL */
-#define WM8915_ADC1L_TO_DSP1TXL_SHIFT                1  /* ADC1L_TO_DSP1TXL */
-#define WM8915_ADC1L_TO_DSP1TXL_WIDTH                1  /* ADC1L_TO_DSP1TXL */
-#define WM8915_DACL_TO_DSP1TXL                  0x0001  /* DACL_TO_DSP1TXL */
-#define WM8915_DACL_TO_DSP1TXL_MASK             0x0001  /* DACL_TO_DSP1TXL */
-#define WM8915_DACL_TO_DSP1TXL_SHIFT                 0  /* DACL_TO_DSP1TXL */
-#define WM8915_DACL_TO_DSP1TXL_WIDTH                 1  /* DACL_TO_DSP1TXL */
-
-/*
- * R1543 (0x607) - DSP1 TX Right Mixer Routing
- */
-#define WM8915_ADC1R_TO_DSP1TXR                 0x0002  /* ADC1R_TO_DSP1TXR */
-#define WM8915_ADC1R_TO_DSP1TXR_MASK            0x0002  /* ADC1R_TO_DSP1TXR */
-#define WM8915_ADC1R_TO_DSP1TXR_SHIFT                1  /* ADC1R_TO_DSP1TXR */
-#define WM8915_ADC1R_TO_DSP1TXR_WIDTH                1  /* ADC1R_TO_DSP1TXR */
-#define WM8915_DACR_TO_DSP1TXR                  0x0001  /* DACR_TO_DSP1TXR */
-#define WM8915_DACR_TO_DSP1TXR_MASK             0x0001  /* DACR_TO_DSP1TXR */
-#define WM8915_DACR_TO_DSP1TXR_SHIFT                 0  /* DACR_TO_DSP1TXR */
-#define WM8915_DACR_TO_DSP1TXR_WIDTH                 1  /* DACR_TO_DSP1TXR */
-
-/*
- * R1544 (0x608) - DSP2 TX Left Mixer Routing
- */
-#define WM8915_ADC2L_TO_DSP2TXL                 0x0002  /* ADC2L_TO_DSP2TXL */
-#define WM8915_ADC2L_TO_DSP2TXL_MASK            0x0002  /* ADC2L_TO_DSP2TXL */
-#define WM8915_ADC2L_TO_DSP2TXL_SHIFT                1  /* ADC2L_TO_DSP2TXL */
-#define WM8915_ADC2L_TO_DSP2TXL_WIDTH                1  /* ADC2L_TO_DSP2TXL */
-#define WM8915_DACL_TO_DSP2TXL                  0x0001  /* DACL_TO_DSP2TXL */
-#define WM8915_DACL_TO_DSP2TXL_MASK             0x0001  /* DACL_TO_DSP2TXL */
-#define WM8915_DACL_TO_DSP2TXL_SHIFT                 0  /* DACL_TO_DSP2TXL */
-#define WM8915_DACL_TO_DSP2TXL_WIDTH                 1  /* DACL_TO_DSP2TXL */
-
-/*
- * R1545 (0x609) - DSP2 TX Right Mixer Routing
- */
-#define WM8915_ADC2R_TO_DSP2TXR                 0x0002  /* ADC2R_TO_DSP2TXR */
-#define WM8915_ADC2R_TO_DSP2TXR_MASK            0x0002  /* ADC2R_TO_DSP2TXR */
-#define WM8915_ADC2R_TO_DSP2TXR_SHIFT                1  /* ADC2R_TO_DSP2TXR */
-#define WM8915_ADC2R_TO_DSP2TXR_WIDTH                1  /* ADC2R_TO_DSP2TXR */
-#define WM8915_DACR_TO_DSP2TXR                  0x0001  /* DACR_TO_DSP2TXR */
-#define WM8915_DACR_TO_DSP2TXR_MASK             0x0001  /* DACR_TO_DSP2TXR */
-#define WM8915_DACR_TO_DSP2TXR_SHIFT                 0  /* DACR_TO_DSP2TXR */
-#define WM8915_DACR_TO_DSP2TXR_WIDTH                 1  /* DACR_TO_DSP2TXR */
-
-/*
- * R1546 (0x60A) - DSP TX Mixer Select
- */
-#define WM8915_DAC_TO_DSPTX_SRC                 0x0001  /* DAC_TO_DSPTX_SRC */
-#define WM8915_DAC_TO_DSPTX_SRC_MASK            0x0001  /* DAC_TO_DSPTX_SRC */
-#define WM8915_DAC_TO_DSPTX_SRC_SHIFT                0  /* DAC_TO_DSPTX_SRC */
-#define WM8915_DAC_TO_DSPTX_SRC_WIDTH                1  /* DAC_TO_DSPTX_SRC */
-
-/*
- * R1552 (0x610) - DAC Softmute
- */
-#define WM8915_DAC_SOFTMUTEMODE                 0x0002  /* DAC_SOFTMUTEMODE */
-#define WM8915_DAC_SOFTMUTEMODE_MASK            0x0002  /* DAC_SOFTMUTEMODE */
-#define WM8915_DAC_SOFTMUTEMODE_SHIFT                1  /* DAC_SOFTMUTEMODE */
-#define WM8915_DAC_SOFTMUTEMODE_WIDTH                1  /* DAC_SOFTMUTEMODE */
-#define WM8915_DAC_MUTERATE                     0x0001  /* DAC_MUTERATE */
-#define WM8915_DAC_MUTERATE_MASK                0x0001  /* DAC_MUTERATE */
-#define WM8915_DAC_MUTERATE_SHIFT                    0  /* DAC_MUTERATE */
-#define WM8915_DAC_MUTERATE_WIDTH                    1  /* DAC_MUTERATE */
-
-/*
- * R1568 (0x620) - Oversampling
- */
-#define WM8915_SPK_OSR128                       0x0008  /* SPK_OSR128 */
-#define WM8915_SPK_OSR128_MASK                  0x0008  /* SPK_OSR128 */
-#define WM8915_SPK_OSR128_SHIFT                      3  /* SPK_OSR128 */
-#define WM8915_SPK_OSR128_WIDTH                      1  /* SPK_OSR128 */
-#define WM8915_DMIC_OSR64                       0x0004  /* DMIC_OSR64 */
-#define WM8915_DMIC_OSR64_MASK                  0x0004  /* DMIC_OSR64 */
-#define WM8915_DMIC_OSR64_SHIFT                      2  /* DMIC_OSR64 */
-#define WM8915_DMIC_OSR64_WIDTH                      1  /* DMIC_OSR64 */
-#define WM8915_ADC_OSR128                       0x0002  /* ADC_OSR128 */
-#define WM8915_ADC_OSR128_MASK                  0x0002  /* ADC_OSR128 */
-#define WM8915_ADC_OSR128_SHIFT                      1  /* ADC_OSR128 */
-#define WM8915_ADC_OSR128_WIDTH                      1  /* ADC_OSR128 */
-#define WM8915_DAC_OSR128                       0x0001  /* DAC_OSR128 */
-#define WM8915_DAC_OSR128_MASK                  0x0001  /* DAC_OSR128 */
-#define WM8915_DAC_OSR128_SHIFT                      0  /* DAC_OSR128 */
-#define WM8915_DAC_OSR128_WIDTH                      1  /* DAC_OSR128 */
-
-/*
- * R1569 (0x621) - Sidetone
- */
-#define WM8915_ST_LPF                           0x1000  /* ST_LPF */
-#define WM8915_ST_LPF_MASK                      0x1000  /* ST_LPF */
-#define WM8915_ST_LPF_SHIFT                         12  /* ST_LPF */
-#define WM8915_ST_LPF_WIDTH                          1  /* ST_LPF */
-#define WM8915_ST_HPF_CUT_MASK                  0x0380  /* ST_HPF_CUT - [9:7] */
-#define WM8915_ST_HPF_CUT_SHIFT                      7  /* ST_HPF_CUT - [9:7] */
-#define WM8915_ST_HPF_CUT_WIDTH                      3  /* ST_HPF_CUT - [9:7] */
-#define WM8915_ST_HPF                           0x0040  /* ST_HPF */
-#define WM8915_ST_HPF_MASK                      0x0040  /* ST_HPF */
-#define WM8915_ST_HPF_SHIFT                          6  /* ST_HPF */
-#define WM8915_ST_HPF_WIDTH                          1  /* ST_HPF */
-#define WM8915_STR_SEL                          0x0002  /* STR_SEL */
-#define WM8915_STR_SEL_MASK                     0x0002  /* STR_SEL */
-#define WM8915_STR_SEL_SHIFT                         1  /* STR_SEL */
-#define WM8915_STR_SEL_WIDTH                         1  /* STR_SEL */
-#define WM8915_STL_SEL                          0x0001  /* STL_SEL */
-#define WM8915_STL_SEL_MASK                     0x0001  /* STL_SEL */
-#define WM8915_STL_SEL_SHIFT                         0  /* STL_SEL */
-#define WM8915_STL_SEL_WIDTH                         1  /* STL_SEL */
-
-/*
- * R1792 (0x700) - GPIO 1
- */
-#define WM8915_GP1_DIR                          0x8000  /* GP1_DIR */
-#define WM8915_GP1_DIR_MASK                     0x8000  /* GP1_DIR */
-#define WM8915_GP1_DIR_SHIFT                        15  /* GP1_DIR */
-#define WM8915_GP1_DIR_WIDTH                         1  /* GP1_DIR */
-#define WM8915_GP1_PU                           0x4000  /* GP1_PU */
-#define WM8915_GP1_PU_MASK                      0x4000  /* GP1_PU */
-#define WM8915_GP1_PU_SHIFT                         14  /* GP1_PU */
-#define WM8915_GP1_PU_WIDTH                          1  /* GP1_PU */
-#define WM8915_GP1_PD                           0x2000  /* GP1_PD */
-#define WM8915_GP1_PD_MASK                      0x2000  /* GP1_PD */
-#define WM8915_GP1_PD_SHIFT                         13  /* GP1_PD */
-#define WM8915_GP1_PD_WIDTH                          1  /* GP1_PD */
-#define WM8915_GP1_POL                          0x0400  /* GP1_POL */
-#define WM8915_GP1_POL_MASK                     0x0400  /* GP1_POL */
-#define WM8915_GP1_POL_SHIFT                        10  /* GP1_POL */
-#define WM8915_GP1_POL_WIDTH                         1  /* GP1_POL */
-#define WM8915_GP1_OP_CFG                       0x0200  /* GP1_OP_CFG */
-#define WM8915_GP1_OP_CFG_MASK                  0x0200  /* GP1_OP_CFG */
-#define WM8915_GP1_OP_CFG_SHIFT                      9  /* GP1_OP_CFG */
-#define WM8915_GP1_OP_CFG_WIDTH                      1  /* GP1_OP_CFG */
-#define WM8915_GP1_DB                           0x0100  /* GP1_DB */
-#define WM8915_GP1_DB_MASK                      0x0100  /* GP1_DB */
-#define WM8915_GP1_DB_SHIFT                          8  /* GP1_DB */
-#define WM8915_GP1_DB_WIDTH                          1  /* GP1_DB */
-#define WM8915_GP1_LVL                          0x0040  /* GP1_LVL */
-#define WM8915_GP1_LVL_MASK                     0x0040  /* GP1_LVL */
-#define WM8915_GP1_LVL_SHIFT                         6  /* GP1_LVL */
-#define WM8915_GP1_LVL_WIDTH                         1  /* GP1_LVL */
-#define WM8915_GP1_FN_MASK                      0x000F  /* GP1_FN - [3:0] */
-#define WM8915_GP1_FN_SHIFT                          0  /* GP1_FN - [3:0] */
-#define WM8915_GP1_FN_WIDTH                          4  /* GP1_FN - [3:0] */
-
-/*
- * R1793 (0x701) - GPIO 2
- */
-#define WM8915_GP2_DIR                          0x8000  /* GP2_DIR */
-#define WM8915_GP2_DIR_MASK                     0x8000  /* GP2_DIR */
-#define WM8915_GP2_DIR_SHIFT                        15  /* GP2_DIR */
-#define WM8915_GP2_DIR_WIDTH                         1  /* GP2_DIR */
-#define WM8915_GP2_PU                           0x4000  /* GP2_PU */
-#define WM8915_GP2_PU_MASK                      0x4000  /* GP2_PU */
-#define WM8915_GP2_PU_SHIFT                         14  /* GP2_PU */
-#define WM8915_GP2_PU_WIDTH                          1  /* GP2_PU */
-#define WM8915_GP2_PD                           0x2000  /* GP2_PD */
-#define WM8915_GP2_PD_MASK                      0x2000  /* GP2_PD */
-#define WM8915_GP2_PD_SHIFT                         13  /* GP2_PD */
-#define WM8915_GP2_PD_WIDTH                          1  /* GP2_PD */
-#define WM8915_GP2_POL                          0x0400  /* GP2_POL */
-#define WM8915_GP2_POL_MASK                     0x0400  /* GP2_POL */
-#define WM8915_GP2_POL_SHIFT                        10  /* GP2_POL */
-#define WM8915_GP2_POL_WIDTH                         1  /* GP2_POL */
-#define WM8915_GP2_OP_CFG                       0x0200  /* GP2_OP_CFG */
-#define WM8915_GP2_OP_CFG_MASK                  0x0200  /* GP2_OP_CFG */
-#define WM8915_GP2_OP_CFG_SHIFT                      9  /* GP2_OP_CFG */
-#define WM8915_GP2_OP_CFG_WIDTH                      1  /* GP2_OP_CFG */
-#define WM8915_GP2_DB                           0x0100  /* GP2_DB */
-#define WM8915_GP2_DB_MASK                      0x0100  /* GP2_DB */
-#define WM8915_GP2_DB_SHIFT                          8  /* GP2_DB */
-#define WM8915_GP2_DB_WIDTH                          1  /* GP2_DB */
-#define WM8915_GP2_LVL                          0x0040  /* GP2_LVL */
-#define WM8915_GP2_LVL_MASK                     0x0040  /* GP2_LVL */
-#define WM8915_GP2_LVL_SHIFT                         6  /* GP2_LVL */
-#define WM8915_GP2_LVL_WIDTH                         1  /* GP2_LVL */
-#define WM8915_GP2_FN_MASK                      0x000F  /* GP2_FN - [3:0] */
-#define WM8915_GP2_FN_SHIFT                          0  /* GP2_FN - [3:0] */
-#define WM8915_GP2_FN_WIDTH                          4  /* GP2_FN - [3:0] */
-
-/*
- * R1794 (0x702) - GPIO 3
- */
-#define WM8915_GP3_DIR                          0x8000  /* GP3_DIR */
-#define WM8915_GP3_DIR_MASK                     0x8000  /* GP3_DIR */
-#define WM8915_GP3_DIR_SHIFT                        15  /* GP3_DIR */
-#define WM8915_GP3_DIR_WIDTH                         1  /* GP3_DIR */
-#define WM8915_GP3_PU                           0x4000  /* GP3_PU */
-#define WM8915_GP3_PU_MASK                      0x4000  /* GP3_PU */
-#define WM8915_GP3_PU_SHIFT                         14  /* GP3_PU */
-#define WM8915_GP3_PU_WIDTH                          1  /* GP3_PU */
-#define WM8915_GP3_PD                           0x2000  /* GP3_PD */
-#define WM8915_GP3_PD_MASK                      0x2000  /* GP3_PD */
-#define WM8915_GP3_PD_SHIFT                         13  /* GP3_PD */
-#define WM8915_GP3_PD_WIDTH                          1  /* GP3_PD */
-#define WM8915_GP3_POL                          0x0400  /* GP3_POL */
-#define WM8915_GP3_POL_MASK                     0x0400  /* GP3_POL */
-#define WM8915_GP3_POL_SHIFT                        10  /* GP3_POL */
-#define WM8915_GP3_POL_WIDTH                         1  /* GP3_POL */
-#define WM8915_GP3_OP_CFG                       0x0200  /* GP3_OP_CFG */
-#define WM8915_GP3_OP_CFG_MASK                  0x0200  /* GP3_OP_CFG */
-#define WM8915_GP3_OP_CFG_SHIFT                      9  /* GP3_OP_CFG */
-#define WM8915_GP3_OP_CFG_WIDTH                      1  /* GP3_OP_CFG */
-#define WM8915_GP3_DB                           0x0100  /* GP3_DB */
-#define WM8915_GP3_DB_MASK                      0x0100  /* GP3_DB */
-#define WM8915_GP3_DB_SHIFT                          8  /* GP3_DB */
-#define WM8915_GP3_DB_WIDTH                          1  /* GP3_DB */
-#define WM8915_GP3_LVL                          0x0040  /* GP3_LVL */
-#define WM8915_GP3_LVL_MASK                     0x0040  /* GP3_LVL */
-#define WM8915_GP3_LVL_SHIFT                         6  /* GP3_LVL */
-#define WM8915_GP3_LVL_WIDTH                         1  /* GP3_LVL */
-#define WM8915_GP3_FN_MASK                      0x000F  /* GP3_FN - [3:0] */
-#define WM8915_GP3_FN_SHIFT                          0  /* GP3_FN - [3:0] */
-#define WM8915_GP3_FN_WIDTH                          4  /* GP3_FN - [3:0] */
-
-/*
- * R1795 (0x703) - GPIO 4
- */
-#define WM8915_GP4_DIR                          0x8000  /* GP4_DIR */
-#define WM8915_GP4_DIR_MASK                     0x8000  /* GP4_DIR */
-#define WM8915_GP4_DIR_SHIFT                        15  /* GP4_DIR */
-#define WM8915_GP4_DIR_WIDTH                         1  /* GP4_DIR */
-#define WM8915_GP4_PU                           0x4000  /* GP4_PU */
-#define WM8915_GP4_PU_MASK                      0x4000  /* GP4_PU */
-#define WM8915_GP4_PU_SHIFT                         14  /* GP4_PU */
-#define WM8915_GP4_PU_WIDTH                          1  /* GP4_PU */
-#define WM8915_GP4_PD                           0x2000  /* GP4_PD */
-#define WM8915_GP4_PD_MASK                      0x2000  /* GP4_PD */
-#define WM8915_GP4_PD_SHIFT                         13  /* GP4_PD */
-#define WM8915_GP4_PD_WIDTH                          1  /* GP4_PD */
-#define WM8915_GP4_POL                          0x0400  /* GP4_POL */
-#define WM8915_GP4_POL_MASK                     0x0400  /* GP4_POL */
-#define WM8915_GP4_POL_SHIFT                        10  /* GP4_POL */
-#define WM8915_GP4_POL_WIDTH                         1  /* GP4_POL */
-#define WM8915_GP4_OP_CFG                       0x0200  /* GP4_OP_CFG */
-#define WM8915_GP4_OP_CFG_MASK                  0x0200  /* GP4_OP_CFG */
-#define WM8915_GP4_OP_CFG_SHIFT                      9  /* GP4_OP_CFG */
-#define WM8915_GP4_OP_CFG_WIDTH                      1  /* GP4_OP_CFG */
-#define WM8915_GP4_DB                           0x0100  /* GP4_DB */
-#define WM8915_GP4_DB_MASK                      0x0100  /* GP4_DB */
-#define WM8915_GP4_DB_SHIFT                          8  /* GP4_DB */
-#define WM8915_GP4_DB_WIDTH                          1  /* GP4_DB */
-#define WM8915_GP4_LVL                          0x0040  /* GP4_LVL */
-#define WM8915_GP4_LVL_MASK                     0x0040  /* GP4_LVL */
-#define WM8915_GP4_LVL_SHIFT                         6  /* GP4_LVL */
-#define WM8915_GP4_LVL_WIDTH                         1  /* GP4_LVL */
-#define WM8915_GP4_FN_MASK                      0x000F  /* GP4_FN - [3:0] */
-#define WM8915_GP4_FN_SHIFT                          0  /* GP4_FN - [3:0] */
-#define WM8915_GP4_FN_WIDTH                          4  /* GP4_FN - [3:0] */
-
-/*
- * R1796 (0x704) - GPIO 5
- */
-#define WM8915_GP5_DIR                          0x8000  /* GP5_DIR */
-#define WM8915_GP5_DIR_MASK                     0x8000  /* GP5_DIR */
-#define WM8915_GP5_DIR_SHIFT                        15  /* GP5_DIR */
-#define WM8915_GP5_DIR_WIDTH                         1  /* GP5_DIR */
-#define WM8915_GP5_PU                           0x4000  /* GP5_PU */
-#define WM8915_GP5_PU_MASK                      0x4000  /* GP5_PU */
-#define WM8915_GP5_PU_SHIFT                         14  /* GP5_PU */
-#define WM8915_GP5_PU_WIDTH                          1  /* GP5_PU */
-#define WM8915_GP5_PD                           0x2000  /* GP5_PD */
-#define WM8915_GP5_PD_MASK                      0x2000  /* GP5_PD */
-#define WM8915_GP5_PD_SHIFT                         13  /* GP5_PD */
-#define WM8915_GP5_PD_WIDTH                          1  /* GP5_PD */
-#define WM8915_GP5_POL                          0x0400  /* GP5_POL */
-#define WM8915_GP5_POL_MASK                     0x0400  /* GP5_POL */
-#define WM8915_GP5_POL_SHIFT                        10  /* GP5_POL */
-#define WM8915_GP5_POL_WIDTH                         1  /* GP5_POL */
-#define WM8915_GP5_OP_CFG                       0x0200  /* GP5_OP_CFG */
-#define WM8915_GP5_OP_CFG_MASK                  0x0200  /* GP5_OP_CFG */
-#define WM8915_GP5_OP_CFG_SHIFT                      9  /* GP5_OP_CFG */
-#define WM8915_GP5_OP_CFG_WIDTH                      1  /* GP5_OP_CFG */
-#define WM8915_GP5_DB                           0x0100  /* GP5_DB */
-#define WM8915_GP5_DB_MASK                      0x0100  /* GP5_DB */
-#define WM8915_GP5_DB_SHIFT                          8  /* GP5_DB */
-#define WM8915_GP5_DB_WIDTH                          1  /* GP5_DB */
-#define WM8915_GP5_LVL                          0x0040  /* GP5_LVL */
-#define WM8915_GP5_LVL_MASK                     0x0040  /* GP5_LVL */
-#define WM8915_GP5_LVL_SHIFT                         6  /* GP5_LVL */
-#define WM8915_GP5_LVL_WIDTH                         1  /* GP5_LVL */
-#define WM8915_GP5_FN_MASK                      0x000F  /* GP5_FN - [3:0] */
-#define WM8915_GP5_FN_SHIFT                          0  /* GP5_FN - [3:0] */
-#define WM8915_GP5_FN_WIDTH                          4  /* GP5_FN - [3:0] */
-
-/*
- * R1824 (0x720) - Pull Control (1)
- */
-#define WM8915_DMICDAT2_PD                      0x1000  /* DMICDAT2_PD */
-#define WM8915_DMICDAT2_PD_MASK                 0x1000  /* DMICDAT2_PD */
-#define WM8915_DMICDAT2_PD_SHIFT                    12  /* DMICDAT2_PD */
-#define WM8915_DMICDAT2_PD_WIDTH                     1  /* DMICDAT2_PD */
-#define WM8915_DMICDAT1_PD                      0x0400  /* DMICDAT1_PD */
-#define WM8915_DMICDAT1_PD_MASK                 0x0400  /* DMICDAT1_PD */
-#define WM8915_DMICDAT1_PD_SHIFT                    10  /* DMICDAT1_PD */
-#define WM8915_DMICDAT1_PD_WIDTH                     1  /* DMICDAT1_PD */
-#define WM8915_MCLK2_PU                         0x0200  /* MCLK2_PU */
-#define WM8915_MCLK2_PU_MASK                    0x0200  /* MCLK2_PU */
-#define WM8915_MCLK2_PU_SHIFT                        9  /* MCLK2_PU */
-#define WM8915_MCLK2_PU_WIDTH                        1  /* MCLK2_PU */
-#define WM8915_MCLK2_PD                         0x0100  /* MCLK2_PD */
-#define WM8915_MCLK2_PD_MASK                    0x0100  /* MCLK2_PD */
-#define WM8915_MCLK2_PD_SHIFT                        8  /* MCLK2_PD */
-#define WM8915_MCLK2_PD_WIDTH                        1  /* MCLK2_PD */
-#define WM8915_MCLK1_PU                         0x0080  /* MCLK1_PU */
-#define WM8915_MCLK1_PU_MASK                    0x0080  /* MCLK1_PU */
-#define WM8915_MCLK1_PU_SHIFT                        7  /* MCLK1_PU */
-#define WM8915_MCLK1_PU_WIDTH                        1  /* MCLK1_PU */
-#define WM8915_MCLK1_PD                         0x0040  /* MCLK1_PD */
-#define WM8915_MCLK1_PD_MASK                    0x0040  /* MCLK1_PD */
-#define WM8915_MCLK1_PD_SHIFT                        6  /* MCLK1_PD */
-#define WM8915_MCLK1_PD_WIDTH                        1  /* MCLK1_PD */
-#define WM8915_DACDAT1_PU                       0x0020  /* DACDAT1_PU */
-#define WM8915_DACDAT1_PU_MASK                  0x0020  /* DACDAT1_PU */
-#define WM8915_DACDAT1_PU_SHIFT                      5  /* DACDAT1_PU */
-#define WM8915_DACDAT1_PU_WIDTH                      1  /* DACDAT1_PU */
-#define WM8915_DACDAT1_PD                       0x0010  /* DACDAT1_PD */
-#define WM8915_DACDAT1_PD_MASK                  0x0010  /* DACDAT1_PD */
-#define WM8915_DACDAT1_PD_SHIFT                      4  /* DACDAT1_PD */
-#define WM8915_DACDAT1_PD_WIDTH                      1  /* DACDAT1_PD */
-#define WM8915_DACLRCLK1_PU                     0x0008  /* DACLRCLK1_PU */
-#define WM8915_DACLRCLK1_PU_MASK                0x0008  /* DACLRCLK1_PU */
-#define WM8915_DACLRCLK1_PU_SHIFT                    3  /* DACLRCLK1_PU */
-#define WM8915_DACLRCLK1_PU_WIDTH                    1  /* DACLRCLK1_PU */
-#define WM8915_DACLRCLK1_PD                     0x0004  /* DACLRCLK1_PD */
-#define WM8915_DACLRCLK1_PD_MASK                0x0004  /* DACLRCLK1_PD */
-#define WM8915_DACLRCLK1_PD_SHIFT                    2  /* DACLRCLK1_PD */
-#define WM8915_DACLRCLK1_PD_WIDTH                    1  /* DACLRCLK1_PD */
-#define WM8915_BCLK1_PU                         0x0002  /* BCLK1_PU */
-#define WM8915_BCLK1_PU_MASK                    0x0002  /* BCLK1_PU */
-#define WM8915_BCLK1_PU_SHIFT                        1  /* BCLK1_PU */
-#define WM8915_BCLK1_PU_WIDTH                        1  /* BCLK1_PU */
-#define WM8915_BCLK1_PD                         0x0001  /* BCLK1_PD */
-#define WM8915_BCLK1_PD_MASK                    0x0001  /* BCLK1_PD */
-#define WM8915_BCLK1_PD_SHIFT                        0  /* BCLK1_PD */
-#define WM8915_BCLK1_PD_WIDTH                        1  /* BCLK1_PD */
-
-/*
- * R1825 (0x721) - Pull Control (2)
- */
-#define WM8915_LDO1ENA_PD                       0x0100  /* LDO1ENA_PD */
-#define WM8915_LDO1ENA_PD_MASK                  0x0100  /* LDO1ENA_PD */
-#define WM8915_LDO1ENA_PD_SHIFT                      8  /* LDO1ENA_PD */
-#define WM8915_LDO1ENA_PD_WIDTH                      1  /* LDO1ENA_PD */
-#define WM8915_ADDR_PD                          0x0040  /* ADDR_PD */
-#define WM8915_ADDR_PD_MASK                     0x0040  /* ADDR_PD */
-#define WM8915_ADDR_PD_SHIFT                         6  /* ADDR_PD */
-#define WM8915_ADDR_PD_WIDTH                         1  /* ADDR_PD */
-#define WM8915_DACDAT2_PU                       0x0020  /* DACDAT2_PU */
-#define WM8915_DACDAT2_PU_MASK                  0x0020  /* DACDAT2_PU */
-#define WM8915_DACDAT2_PU_SHIFT                      5  /* DACDAT2_PU */
-#define WM8915_DACDAT2_PU_WIDTH                      1  /* DACDAT2_PU */
-#define WM8915_DACDAT2_PD                       0x0010  /* DACDAT2_PD */
-#define WM8915_DACDAT2_PD_MASK                  0x0010  /* DACDAT2_PD */
-#define WM8915_DACDAT2_PD_SHIFT                      4  /* DACDAT2_PD */
-#define WM8915_DACDAT2_PD_WIDTH                      1  /* DACDAT2_PD */
-#define WM8915_DACLRCLK2_PU                     0x0008  /* DACLRCLK2_PU */
-#define WM8915_DACLRCLK2_PU_MASK                0x0008  /* DACLRCLK2_PU */
-#define WM8915_DACLRCLK2_PU_SHIFT                    3  /* DACLRCLK2_PU */
-#define WM8915_DACLRCLK2_PU_WIDTH                    1  /* DACLRCLK2_PU */
-#define WM8915_DACLRCLK2_PD                     0x0004  /* DACLRCLK2_PD */
-#define WM8915_DACLRCLK2_PD_MASK                0x0004  /* DACLRCLK2_PD */
-#define WM8915_DACLRCLK2_PD_SHIFT                    2  /* DACLRCLK2_PD */
-#define WM8915_DACLRCLK2_PD_WIDTH                    1  /* DACLRCLK2_PD */
-#define WM8915_BCLK2_PU                         0x0002  /* BCLK2_PU */
-#define WM8915_BCLK2_PU_MASK                    0x0002  /* BCLK2_PU */
-#define WM8915_BCLK2_PU_SHIFT                        1  /* BCLK2_PU */
-#define WM8915_BCLK2_PU_WIDTH                        1  /* BCLK2_PU */
-#define WM8915_BCLK2_PD                         0x0001  /* BCLK2_PD */
-#define WM8915_BCLK2_PD_MASK                    0x0001  /* BCLK2_PD */
-#define WM8915_BCLK2_PD_SHIFT                        0  /* BCLK2_PD */
-#define WM8915_BCLK2_PD_WIDTH                        1  /* BCLK2_PD */
-
-/*
- * R1840 (0x730) - Interrupt Status 1
- */
-#define WM8915_GP5_EINT                         0x0010  /* GP5_EINT */
-#define WM8915_GP5_EINT_MASK                    0x0010  /* GP5_EINT */
-#define WM8915_GP5_EINT_SHIFT                        4  /* GP5_EINT */
-#define WM8915_GP5_EINT_WIDTH                        1  /* GP5_EINT */
-#define WM8915_GP4_EINT                         0x0008  /* GP4_EINT */
-#define WM8915_GP4_EINT_MASK                    0x0008  /* GP4_EINT */
-#define WM8915_GP4_EINT_SHIFT                        3  /* GP4_EINT */
-#define WM8915_GP4_EINT_WIDTH                        1  /* GP4_EINT */
-#define WM8915_GP3_EINT                         0x0004  /* GP3_EINT */
-#define WM8915_GP3_EINT_MASK                    0x0004  /* GP3_EINT */
-#define WM8915_GP3_EINT_SHIFT                        2  /* GP3_EINT */
-#define WM8915_GP3_EINT_WIDTH                        1  /* GP3_EINT */
-#define WM8915_GP2_EINT                         0x0002  /* GP2_EINT */
-#define WM8915_GP2_EINT_MASK                    0x0002  /* GP2_EINT */
-#define WM8915_GP2_EINT_SHIFT                        1  /* GP2_EINT */
-#define WM8915_GP2_EINT_WIDTH                        1  /* GP2_EINT */
-#define WM8915_GP1_EINT                         0x0001  /* GP1_EINT */
-#define WM8915_GP1_EINT_MASK                    0x0001  /* GP1_EINT */
-#define WM8915_GP1_EINT_SHIFT                        0  /* GP1_EINT */
-#define WM8915_GP1_EINT_WIDTH                        1  /* GP1_EINT */
-
-/*
- * R1841 (0x731) - Interrupt Status 2
- */
-#define WM8915_DCS_DONE_23_EINT                 0x1000  /* DCS_DONE_23_EINT */
-#define WM8915_DCS_DONE_23_EINT_MASK            0x1000  /* DCS_DONE_23_EINT */
-#define WM8915_DCS_DONE_23_EINT_SHIFT               12  /* DCS_DONE_23_EINT */
-#define WM8915_DCS_DONE_23_EINT_WIDTH                1  /* DCS_DONE_23_EINT */
-#define WM8915_DCS_DONE_01_EINT                 0x0800  /* DCS_DONE_01_EINT */
-#define WM8915_DCS_DONE_01_EINT_MASK            0x0800  /* DCS_DONE_01_EINT */
-#define WM8915_DCS_DONE_01_EINT_SHIFT               11  /* DCS_DONE_01_EINT */
-#define WM8915_DCS_DONE_01_EINT_WIDTH                1  /* DCS_DONE_01_EINT */
-#define WM8915_WSEQ_DONE_EINT                   0x0400  /* WSEQ_DONE_EINT */
-#define WM8915_WSEQ_DONE_EINT_MASK              0x0400  /* WSEQ_DONE_EINT */
-#define WM8915_WSEQ_DONE_EINT_SHIFT                 10  /* WSEQ_DONE_EINT */
-#define WM8915_WSEQ_DONE_EINT_WIDTH                  1  /* WSEQ_DONE_EINT */
-#define WM8915_FIFOS_ERR_EINT                   0x0200  /* FIFOS_ERR_EINT */
-#define WM8915_FIFOS_ERR_EINT_MASK              0x0200  /* FIFOS_ERR_EINT */
-#define WM8915_FIFOS_ERR_EINT_SHIFT                  9  /* FIFOS_ERR_EINT */
-#define WM8915_FIFOS_ERR_EINT_WIDTH                  1  /* FIFOS_ERR_EINT */
-#define WM8915_DSP2DRC_SIG_DET_EINT             0x0080  /* DSP2DRC_SIG_DET_EINT */
-#define WM8915_DSP2DRC_SIG_DET_EINT_MASK        0x0080  /* DSP2DRC_SIG_DET_EINT */
-#define WM8915_DSP2DRC_SIG_DET_EINT_SHIFT            7  /* DSP2DRC_SIG_DET_EINT */
-#define WM8915_DSP2DRC_SIG_DET_EINT_WIDTH            1  /* DSP2DRC_SIG_DET_EINT */
-#define WM8915_DSP1DRC_SIG_DET_EINT             0x0040  /* DSP1DRC_SIG_DET_EINT */
-#define WM8915_DSP1DRC_SIG_DET_EINT_MASK        0x0040  /* DSP1DRC_SIG_DET_EINT */
-#define WM8915_DSP1DRC_SIG_DET_EINT_SHIFT            6  /* DSP1DRC_SIG_DET_EINT */
-#define WM8915_DSP1DRC_SIG_DET_EINT_WIDTH            1  /* DSP1DRC_SIG_DET_EINT */
-#define WM8915_FLL_SW_CLK_DONE_EINT             0x0008  /* FLL_SW_CLK_DONE_EINT */
-#define WM8915_FLL_SW_CLK_DONE_EINT_MASK        0x0008  /* FLL_SW_CLK_DONE_EINT */
-#define WM8915_FLL_SW_CLK_DONE_EINT_SHIFT            3  /* FLL_SW_CLK_DONE_EINT */
-#define WM8915_FLL_SW_CLK_DONE_EINT_WIDTH            1  /* FLL_SW_CLK_DONE_EINT */
-#define WM8915_FLL_LOCK_EINT                    0x0004  /* FLL_LOCK_EINT */
-#define WM8915_FLL_LOCK_EINT_MASK               0x0004  /* FLL_LOCK_EINT */
-#define WM8915_FLL_LOCK_EINT_SHIFT                   2  /* FLL_LOCK_EINT */
-#define WM8915_FLL_LOCK_EINT_WIDTH                   1  /* FLL_LOCK_EINT */
-#define WM8915_HP_DONE_EINT                     0x0002  /* HP_DONE_EINT */
-#define WM8915_HP_DONE_EINT_MASK                0x0002  /* HP_DONE_EINT */
-#define WM8915_HP_DONE_EINT_SHIFT                    1  /* HP_DONE_EINT */
-#define WM8915_HP_DONE_EINT_WIDTH                    1  /* HP_DONE_EINT */
-#define WM8915_MICD_EINT                        0x0001  /* MICD_EINT */
-#define WM8915_MICD_EINT_MASK                   0x0001  /* MICD_EINT */
-#define WM8915_MICD_EINT_SHIFT                       0  /* MICD_EINT */
-#define WM8915_MICD_EINT_WIDTH                       1  /* MICD_EINT */
-
-/*
- * R1842 (0x732) - Interrupt Raw Status 2
- */
-#define WM8915_DCS_DONE_23_STS                  0x1000  /* DCS_DONE_23_STS */
-#define WM8915_DCS_DONE_23_STS_MASK             0x1000  /* DCS_DONE_23_STS */
-#define WM8915_DCS_DONE_23_STS_SHIFT                12  /* DCS_DONE_23_STS */
-#define WM8915_DCS_DONE_23_STS_WIDTH                 1  /* DCS_DONE_23_STS */
-#define WM8915_DCS_DONE_01_STS                  0x0800  /* DCS_DONE_01_STS */
-#define WM8915_DCS_DONE_01_STS_MASK             0x0800  /* DCS_DONE_01_STS */
-#define WM8915_DCS_DONE_01_STS_SHIFT                11  /* DCS_DONE_01_STS */
-#define WM8915_DCS_DONE_01_STS_WIDTH                 1  /* DCS_DONE_01_STS */
-#define WM8915_WSEQ_DONE_STS                    0x0400  /* WSEQ_DONE_STS */
-#define WM8915_WSEQ_DONE_STS_MASK               0x0400  /* WSEQ_DONE_STS */
-#define WM8915_WSEQ_DONE_STS_SHIFT                  10  /* WSEQ_DONE_STS */
-#define WM8915_WSEQ_DONE_STS_WIDTH                   1  /* WSEQ_DONE_STS */
-#define WM8915_FIFOS_ERR_STS                    0x0200  /* FIFOS_ERR_STS */
-#define WM8915_FIFOS_ERR_STS_MASK               0x0200  /* FIFOS_ERR_STS */
-#define WM8915_FIFOS_ERR_STS_SHIFT                   9  /* FIFOS_ERR_STS */
-#define WM8915_FIFOS_ERR_STS_WIDTH                   1  /* FIFOS_ERR_STS */
-#define WM8915_DSP2DRC_SIG_DET_STS              0x0080  /* DSP2DRC_SIG_DET_STS */
-#define WM8915_DSP2DRC_SIG_DET_STS_MASK         0x0080  /* DSP2DRC_SIG_DET_STS */
-#define WM8915_DSP2DRC_SIG_DET_STS_SHIFT             7  /* DSP2DRC_SIG_DET_STS */
-#define WM8915_DSP2DRC_SIG_DET_STS_WIDTH             1  /* DSP2DRC_SIG_DET_STS */
-#define WM8915_DSP1DRC_SIG_DET_STS              0x0040  /* DSP1DRC_SIG_DET_STS */
-#define WM8915_DSP1DRC_SIG_DET_STS_MASK         0x0040  /* DSP1DRC_SIG_DET_STS */
-#define WM8915_DSP1DRC_SIG_DET_STS_SHIFT             6  /* DSP1DRC_SIG_DET_STS */
-#define WM8915_DSP1DRC_SIG_DET_STS_WIDTH             1  /* DSP1DRC_SIG_DET_STS */
-#define WM8915_FLL_LOCK_STS                     0x0004  /* FLL_LOCK_STS */
-#define WM8915_FLL_LOCK_STS_MASK                0x0004  /* FLL_LOCK_STS */
-#define WM8915_FLL_LOCK_STS_SHIFT                    2  /* FLL_LOCK_STS */
-#define WM8915_FLL_LOCK_STS_WIDTH                    1  /* FLL_LOCK_STS */
-
-/*
- * R1848 (0x738) - Interrupt Status 1 Mask
- */
-#define WM8915_IM_GP5_EINT                      0x0010  /* IM_GP5_EINT */
-#define WM8915_IM_GP5_EINT_MASK                 0x0010  /* IM_GP5_EINT */
-#define WM8915_IM_GP5_EINT_SHIFT                     4  /* IM_GP5_EINT */
-#define WM8915_IM_GP5_EINT_WIDTH                     1  /* IM_GP5_EINT */
-#define WM8915_IM_GP4_EINT                      0x0008  /* IM_GP4_EINT */
-#define WM8915_IM_GP4_EINT_MASK                 0x0008  /* IM_GP4_EINT */
-#define WM8915_IM_GP4_EINT_SHIFT                     3  /* IM_GP4_EINT */
-#define WM8915_IM_GP4_EINT_WIDTH                     1  /* IM_GP4_EINT */
-#define WM8915_IM_GP3_EINT                      0x0004  /* IM_GP3_EINT */
-#define WM8915_IM_GP3_EINT_MASK                 0x0004  /* IM_GP3_EINT */
-#define WM8915_IM_GP3_EINT_SHIFT                     2  /* IM_GP3_EINT */
-#define WM8915_IM_GP3_EINT_WIDTH                     1  /* IM_GP3_EINT */
-#define WM8915_IM_GP2_EINT                      0x0002  /* IM_GP2_EINT */
-#define WM8915_IM_GP2_EINT_MASK                 0x0002  /* IM_GP2_EINT */
-#define WM8915_IM_GP2_EINT_SHIFT                     1  /* IM_GP2_EINT */
-#define WM8915_IM_GP2_EINT_WIDTH                     1  /* IM_GP2_EINT */
-#define WM8915_IM_GP1_EINT                      0x0001  /* IM_GP1_EINT */
-#define WM8915_IM_GP1_EINT_MASK                 0x0001  /* IM_GP1_EINT */
-#define WM8915_IM_GP1_EINT_SHIFT                     0  /* IM_GP1_EINT */
-#define WM8915_IM_GP1_EINT_WIDTH                     1  /* IM_GP1_EINT */
-
-/*
- * R1849 (0x739) - Interrupt Status 2 Mask
- */
-#define WM8915_IM_DCS_DONE_23_EINT              0x1000  /* IM_DCS_DONE_23_EINT */
-#define WM8915_IM_DCS_DONE_23_EINT_MASK         0x1000  /* IM_DCS_DONE_23_EINT */
-#define WM8915_IM_DCS_DONE_23_EINT_SHIFT            12  /* IM_DCS_DONE_23_EINT */
-#define WM8915_IM_DCS_DONE_23_EINT_WIDTH             1  /* IM_DCS_DONE_23_EINT */
-#define WM8915_IM_DCS_DONE_01_EINT              0x0800  /* IM_DCS_DONE_01_EINT */
-#define WM8915_IM_DCS_DONE_01_EINT_MASK         0x0800  /* IM_DCS_DONE_01_EINT */
-#define WM8915_IM_DCS_DONE_01_EINT_SHIFT            11  /* IM_DCS_DONE_01_EINT */
-#define WM8915_IM_DCS_DONE_01_EINT_WIDTH             1  /* IM_DCS_DONE_01_EINT */
-#define WM8915_IM_WSEQ_DONE_EINT                0x0400  /* IM_WSEQ_DONE_EINT */
-#define WM8915_IM_WSEQ_DONE_EINT_MASK           0x0400  /* IM_WSEQ_DONE_EINT */
-#define WM8915_IM_WSEQ_DONE_EINT_SHIFT              10  /* IM_WSEQ_DONE_EINT */
-#define WM8915_IM_WSEQ_DONE_EINT_WIDTH               1  /* IM_WSEQ_DONE_EINT */
-#define WM8915_IM_FIFOS_ERR_EINT                0x0200  /* IM_FIFOS_ERR_EINT */
-#define WM8915_IM_FIFOS_ERR_EINT_MASK           0x0200  /* IM_FIFOS_ERR_EINT */
-#define WM8915_IM_FIFOS_ERR_EINT_SHIFT               9  /* IM_FIFOS_ERR_EINT */
-#define WM8915_IM_FIFOS_ERR_EINT_WIDTH               1  /* IM_FIFOS_ERR_EINT */
-#define WM8915_IM_DSP2DRC_SIG_DET_EINT          0x0080  /* IM_DSP2DRC_SIG_DET_EINT */
-#define WM8915_IM_DSP2DRC_SIG_DET_EINT_MASK     0x0080  /* IM_DSP2DRC_SIG_DET_EINT */
-#define WM8915_IM_DSP2DRC_SIG_DET_EINT_SHIFT         7  /* IM_DSP2DRC_SIG_DET_EINT */
-#define WM8915_IM_DSP2DRC_SIG_DET_EINT_WIDTH         1  /* IM_DSP2DRC_SIG_DET_EINT */
-#define WM8915_IM_DSP1DRC_SIG_DET_EINT          0x0040  /* IM_DSP1DRC_SIG_DET_EINT */
-#define WM8915_IM_DSP1DRC_SIG_DET_EINT_MASK     0x0040  /* IM_DSP1DRC_SIG_DET_EINT */
-#define WM8915_IM_DSP1DRC_SIG_DET_EINT_SHIFT         6  /* IM_DSP1DRC_SIG_DET_EINT */
-#define WM8915_IM_DSP1DRC_SIG_DET_EINT_WIDTH         1  /* IM_DSP1DRC_SIG_DET_EINT */
-#define WM8915_IM_FLL_SW_CLK_DONE_EINT          0x0008  /* IM_FLL_SW_CLK_DONE_EINT */
-#define WM8915_IM_FLL_SW_CLK_DONE_EINT_MASK     0x0008  /* IM_FLL_SW_CLK_DONE_EINT */
-#define WM8915_IM_FLL_SW_CLK_DONE_EINT_SHIFT         3  /* IM_FLL_SW_CLK_DONE_EINT */
-#define WM8915_IM_FLL_SW_CLK_DONE_EINT_WIDTH         1  /* IM_FLL_SW_CLK_DONE_EINT */
-#define WM8915_IM_FLL_LOCK_EINT                 0x0004  /* IM_FLL_LOCK_EINT */
-#define WM8915_IM_FLL_LOCK_EINT_MASK            0x0004  /* IM_FLL_LOCK_EINT */
-#define WM8915_IM_FLL_LOCK_EINT_SHIFT                2  /* IM_FLL_LOCK_EINT */
-#define WM8915_IM_FLL_LOCK_EINT_WIDTH                1  /* IM_FLL_LOCK_EINT */
-#define WM8915_IM_HP_DONE_EINT                  0x0002  /* IM_HP_DONE_EINT */
-#define WM8915_IM_HP_DONE_EINT_MASK             0x0002  /* IM_HP_DONE_EINT */
-#define WM8915_IM_HP_DONE_EINT_SHIFT                 1  /* IM_HP_DONE_EINT */
-#define WM8915_IM_HP_DONE_EINT_WIDTH                 1  /* IM_HP_DONE_EINT */
-#define WM8915_IM_MICD_EINT                     0x0001  /* IM_MICD_EINT */
-#define WM8915_IM_MICD_EINT_MASK                0x0001  /* IM_MICD_EINT */
-#define WM8915_IM_MICD_EINT_SHIFT                    0  /* IM_MICD_EINT */
-#define WM8915_IM_MICD_EINT_WIDTH                    1  /* IM_MICD_EINT */
-
-/*
- * R1856 (0x740) - Interrupt Control
- */
-#define WM8915_IM_IRQ                           0x0001  /* IM_IRQ */
-#define WM8915_IM_IRQ_MASK                      0x0001  /* IM_IRQ */
-#define WM8915_IM_IRQ_SHIFT                          0  /* IM_IRQ */
-#define WM8915_IM_IRQ_WIDTH                          1  /* IM_IRQ */
-
-/*
- * R2048 (0x800) - Left PDM Speaker
- */
-#define WM8915_SPKL_ENA                         0x0010  /* SPKL_ENA */
-#define WM8915_SPKL_ENA_MASK                    0x0010  /* SPKL_ENA */
-#define WM8915_SPKL_ENA_SHIFT                        4  /* SPKL_ENA */
-#define WM8915_SPKL_ENA_WIDTH                        1  /* SPKL_ENA */
-#define WM8915_SPKL_MUTE                        0x0008  /* SPKL_MUTE */
-#define WM8915_SPKL_MUTE_MASK                   0x0008  /* SPKL_MUTE */
-#define WM8915_SPKL_MUTE_SHIFT                       3  /* SPKL_MUTE */
-#define WM8915_SPKL_MUTE_WIDTH                       1  /* SPKL_MUTE */
-#define WM8915_SPKL_MUTE_ZC                     0x0004  /* SPKL_MUTE_ZC */
-#define WM8915_SPKL_MUTE_ZC_MASK                0x0004  /* SPKL_MUTE_ZC */
-#define WM8915_SPKL_MUTE_ZC_SHIFT                    2  /* SPKL_MUTE_ZC */
-#define WM8915_SPKL_MUTE_ZC_WIDTH                    1  /* SPKL_MUTE_ZC */
-#define WM8915_SPKL_SRC_MASK                    0x0003  /* SPKL_SRC - [1:0] */
-#define WM8915_SPKL_SRC_SHIFT                        0  /* SPKL_SRC - [1:0] */
-#define WM8915_SPKL_SRC_WIDTH                        2  /* SPKL_SRC - [1:0] */
-
-/*
- * R2049 (0x801) - Right PDM Speaker
- */
-#define WM8915_SPKR_ENA                         0x0010  /* SPKR_ENA */
-#define WM8915_SPKR_ENA_MASK                    0x0010  /* SPKR_ENA */
-#define WM8915_SPKR_ENA_SHIFT                        4  /* SPKR_ENA */
-#define WM8915_SPKR_ENA_WIDTH                        1  /* SPKR_ENA */
-#define WM8915_SPKR_MUTE                        0x0008  /* SPKR_MUTE */
-#define WM8915_SPKR_MUTE_MASK                   0x0008  /* SPKR_MUTE */
-#define WM8915_SPKR_MUTE_SHIFT                       3  /* SPKR_MUTE */
-#define WM8915_SPKR_MUTE_WIDTH                       1  /* SPKR_MUTE */
-#define WM8915_SPKR_MUTE_ZC                     0x0004  /* SPKR_MUTE_ZC */
-#define WM8915_SPKR_MUTE_ZC_MASK                0x0004  /* SPKR_MUTE_ZC */
-#define WM8915_SPKR_MUTE_ZC_SHIFT                    2  /* SPKR_MUTE_ZC */
-#define WM8915_SPKR_MUTE_ZC_WIDTH                    1  /* SPKR_MUTE_ZC */
-#define WM8915_SPKR_SRC_MASK                    0x0003  /* SPKR_SRC - [1:0] */
-#define WM8915_SPKR_SRC_SHIFT                        0  /* SPKR_SRC - [1:0] */
-#define WM8915_SPKR_SRC_WIDTH                        2  /* SPKR_SRC - [1:0] */
-
-/*
- * R2050 (0x802) - PDM Speaker Mute Sequence
- */
-#define WM8915_SPK_MUTE_ENDIAN                  0x0100  /* SPK_MUTE_ENDIAN */
-#define WM8915_SPK_MUTE_ENDIAN_MASK             0x0100  /* SPK_MUTE_ENDIAN */
-#define WM8915_SPK_MUTE_ENDIAN_SHIFT                 8  /* SPK_MUTE_ENDIAN */
-#define WM8915_SPK_MUTE_ENDIAN_WIDTH                 1  /* SPK_MUTE_ENDIAN */
-#define WM8915_SPK_MUTE_SEQ1_MASK               0x00FF  /* SPK_MUTE_SEQ1 - [7:0] */
-#define WM8915_SPK_MUTE_SEQ1_SHIFT                   0  /* SPK_MUTE_SEQ1 - [7:0] */
-#define WM8915_SPK_MUTE_SEQ1_WIDTH                   8  /* SPK_MUTE_SEQ1 - [7:0] */
-
-/*
- * R2051 (0x803) - PDM Speaker Volume
- */
-#define WM8915_SPKR_VOL_MASK                    0x00F0  /* SPKR_VOL - [7:4] */
-#define WM8915_SPKR_VOL_SHIFT                        4  /* SPKR_VOL - [7:4] */
-#define WM8915_SPKR_VOL_WIDTH                        4  /* SPKR_VOL - [7:4] */
-#define WM8915_SPKL_VOL_MASK                    0x000F  /* SPKL_VOL - [3:0] */
-#define WM8915_SPKL_VOL_SHIFT                        0  /* SPKL_VOL - [3:0] */
-#define WM8915_SPKL_VOL_WIDTH                        4  /* SPKL_VOL - [3:0] */
-
-#endif
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
new file mode 100644 (file)
index 0000000..ab8e9d1
--- /dev/null
@@ -0,0 +1,2994 @@
+/*
+ * wm8996.c - WM8996 audio codec interface
+ *
+ * Copyright 2011 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gcd.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <trace/events/asoc.h>
+
+#include <sound/wm8996.h>
+#include "wm8996.h"
+
+#define WM8996_AIFS 2
+
+#define HPOUT1L 1
+#define HPOUT1R 2
+#define HPOUT2L 4
+#define HPOUT2R 8
+
+#define WM8996_NUM_SUPPLIES 4
+static const char *wm8996_supply_names[WM8996_NUM_SUPPLIES] = {
+       "DBVDD",
+       "AVDD1",
+       "AVDD2",
+       "CPVDD",
+};
+
+struct wm8996_priv {
+       struct snd_soc_codec *codec;
+
+       int ldo1ena;
+
+       int sysclk;
+       int sysclk_src;
+
+       int fll_src;
+       int fll_fref;
+       int fll_fout;
+
+       struct completion fll_lock;
+
+       u16 dcs_pending;
+       struct completion dcs_done;
+
+       u16 hpout_ena;
+       u16 hpout_pending;
+
+       struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES];
+       struct notifier_block disable_nb[WM8996_NUM_SUPPLIES];
+
+       struct wm8996_pdata pdata;
+
+       int rx_rate[WM8996_AIFS];
+       int bclk_rate[WM8996_AIFS];
+
+       /* Platform dependant ReTune mobile configuration */
+       int num_retune_mobile_texts;
+       const char **retune_mobile_texts;
+       int retune_mobile_cfg[2];
+       struct soc_enum retune_mobile_enum;
+
+       struct snd_soc_jack *jack;
+       bool detecting;
+       bool jack_mic;
+       wm8996_polarity_fn polarity_cb;
+
+#ifdef CONFIG_GPIOLIB
+       struct gpio_chip gpio_chip;
+#endif
+};
+
+/* We can't use the same notifier block for more than one supply and
+ * there's no way I can see to get from a callback to the caller
+ * except container_of().
+ */
+#define WM8996_REGULATOR_EVENT(n) \
+static int wm8996_regulator_event_##n(struct notifier_block *nb, \
+                                   unsigned long event, void *data)    \
+{ \
+       struct wm8996_priv *wm8996 = container_of(nb, struct wm8996_priv, \
+                                                 disable_nb[n]); \
+       if (event & REGULATOR_EVENT_DISABLE) { \
+               wm8996->codec->cache_sync = 1; \
+       } \
+       return 0; \
+}
+
+WM8996_REGULATOR_EVENT(0)
+WM8996_REGULATOR_EVENT(1)
+WM8996_REGULATOR_EVENT(2)
+WM8996_REGULATOR_EVENT(3)
+
+static const u16 wm8996_reg[WM8996_MAX_REGISTER] = {
+       [WM8996_SOFTWARE_RESET] = 0x8996,
+       [WM8996_POWER_MANAGEMENT_7] = 0x10,
+       [WM8996_DAC1_HPOUT1_VOLUME] = 0x88,
+       [WM8996_DAC2_HPOUT2_VOLUME] = 0x88,
+       [WM8996_DAC1_LEFT_VOLUME] = 0x2c0,
+       [WM8996_DAC1_RIGHT_VOLUME] = 0x2c0,
+       [WM8996_DAC2_LEFT_VOLUME] = 0x2c0,
+       [WM8996_DAC2_RIGHT_VOLUME] = 0x2c0,
+       [WM8996_OUTPUT1_LEFT_VOLUME] = 0x80,
+       [WM8996_OUTPUT1_RIGHT_VOLUME] = 0x80,
+       [WM8996_OUTPUT2_LEFT_VOLUME] = 0x80,
+       [WM8996_OUTPUT2_RIGHT_VOLUME] = 0x80,
+       [WM8996_MICBIAS_1] = 0x39,
+       [WM8996_MICBIAS_2] = 0x39,
+       [WM8996_LDO_1] = 0x3,
+       [WM8996_LDO_2] = 0x13,
+       [WM8996_ACCESSORY_DETECT_MODE_1] = 0x4,
+       [WM8996_HEADPHONE_DETECT_1] = 0x20,
+       [WM8996_MIC_DETECT_1] = 0x7600,
+       [WM8996_MIC_DETECT_2] = 0xbf,
+       [WM8996_CHARGE_PUMP_1] = 0x1f25,
+       [WM8996_CHARGE_PUMP_2] = 0xab19,
+       [WM8996_DC_SERVO_5] = 0x2a2a,
+       [WM8996_CONTROL_INTERFACE_1] = 0x8004,
+       [WM8996_CLOCKING_1] = 0x10,
+       [WM8996_AIF_RATE] = 0x83,
+       [WM8996_FLL_CONTROL_4] = 0x5dc0,
+       [WM8996_FLL_CONTROL_5] = 0xc84,
+       [WM8996_FLL_EFS_2] = 0x2,
+       [WM8996_AIF1_TX_LRCLK_1] = 0x80,
+       [WM8996_AIF1_TX_LRCLK_2] = 0x8,
+       [WM8996_AIF1_RX_LRCLK_1] = 0x80,
+       [WM8996_AIF1TX_DATA_CONFIGURATION_1] = 0x1818,
+       [WM8996_AIF1RX_DATA_CONFIGURATION] = 0x1818,
+       [WM8996_AIF1TX_TEST] = 0x7,
+       [WM8996_AIF2_TX_LRCLK_1] = 0x80,
+       [WM8996_AIF2_TX_LRCLK_2] = 0x8,
+       [WM8996_AIF2_RX_LRCLK_1] = 0x80,
+       [WM8996_AIF2TX_DATA_CONFIGURATION_1] = 0x1818,
+       [WM8996_AIF2RX_DATA_CONFIGURATION] = 0x1818,
+       [WM8996_AIF2TX_TEST] = 0x1,
+       [WM8996_DSP1_TX_LEFT_VOLUME] = 0xc0,
+       [WM8996_DSP1_TX_RIGHT_VOLUME] = 0xc0,
+       [WM8996_DSP1_RX_LEFT_VOLUME] = 0xc0,
+       [WM8996_DSP1_RX_RIGHT_VOLUME] = 0xc0,
+       [WM8996_DSP1_TX_FILTERS] = 0x2000,
+       [WM8996_DSP1_RX_FILTERS_1] = 0x200,
+       [WM8996_DSP1_RX_FILTERS_2] = 0x10,
+       [WM8996_DSP1_DRC_1] = 0x98,
+       [WM8996_DSP1_DRC_2] = 0x845,
+       [WM8996_DSP1_RX_EQ_GAINS_1] = 0x6318,
+       [WM8996_DSP1_RX_EQ_GAINS_2] = 0x6300,
+       [WM8996_DSP1_RX_EQ_BAND_1_A] = 0xfca,
+       [WM8996_DSP1_RX_EQ_BAND_1_B] = 0x400,
+       [WM8996_DSP1_RX_EQ_BAND_1_PG] = 0xd8,
+       [WM8996_DSP1_RX_EQ_BAND_2_A] = 0x1eb5,
+       [WM8996_DSP1_RX_EQ_BAND_2_B] = 0xf145,
+       [WM8996_DSP1_RX_EQ_BAND_2_C] = 0xb75,
+       [WM8996_DSP1_RX_EQ_BAND_2_PG] = 0x1c5,
+       [WM8996_DSP1_RX_EQ_BAND_3_A] = 0x1c58,
+       [WM8996_DSP1_RX_EQ_BAND_3_B] = 0xf373,
+       [WM8996_DSP1_RX_EQ_BAND_3_C] = 0xa54,
+       [WM8996_DSP1_RX_EQ_BAND_3_PG] = 0x558,
+       [WM8996_DSP1_RX_EQ_BAND_4_A] = 0x168e,
+       [WM8996_DSP1_RX_EQ_BAND_4_B] = 0xf829,
+       [WM8996_DSP1_RX_EQ_BAND_4_C] = 0x7ad,
+       [WM8996_DSP1_RX_EQ_BAND_4_PG] = 0x1103,
+       [WM8996_DSP1_RX_EQ_BAND_5_A] = 0x564,
+       [WM8996_DSP1_RX_EQ_BAND_5_B] = 0x559,
+       [WM8996_DSP1_RX_EQ_BAND_5_PG] = 0x4000,
+       [WM8996_DSP2_TX_LEFT_VOLUME] = 0xc0,
+       [WM8996_DSP2_TX_RIGHT_VOLUME] = 0xc0,
+       [WM8996_DSP2_RX_LEFT_VOLUME] = 0xc0,
+       [WM8996_DSP2_RX_RIGHT_VOLUME] = 0xc0,
+       [WM8996_DSP2_TX_FILTERS] = 0x2000,
+       [WM8996_DSP2_RX_FILTERS_1] = 0x200,
+       [WM8996_DSP2_RX_FILTERS_2] = 0x10,
+       [WM8996_DSP2_DRC_1] = 0x98,
+       [WM8996_DSP2_DRC_2] = 0x845,
+       [WM8996_DSP2_RX_EQ_GAINS_1] = 0x6318,
+       [WM8996_DSP2_RX_EQ_GAINS_2] = 0x6300,
+       [WM8996_DSP2_RX_EQ_BAND_1_A] = 0xfca,
+       [WM8996_DSP2_RX_EQ_BAND_1_B] = 0x400,
+       [WM8996_DSP2_RX_EQ_BAND_1_PG] = 0xd8,
+       [WM8996_DSP2_RX_EQ_BAND_2_A] = 0x1eb5,
+       [WM8996_DSP2_RX_EQ_BAND_2_B] = 0xf145,
+       [WM8996_DSP2_RX_EQ_BAND_2_C] = 0xb75,
+       [WM8996_DSP2_RX_EQ_BAND_2_PG] = 0x1c5,
+       [WM8996_DSP2_RX_EQ_BAND_3_A] = 0x1c58,
+       [WM8996_DSP2_RX_EQ_BAND_3_B] = 0xf373,
+       [WM8996_DSP2_RX_EQ_BAND_3_C] = 0xa54,
+       [WM8996_DSP2_RX_EQ_BAND_3_PG] = 0x558,
+       [WM8996_DSP2_RX_EQ_BAND_4_A] = 0x168e,
+       [WM8996_DSP2_RX_EQ_BAND_4_B] = 0xf829,
+       [WM8996_DSP2_RX_EQ_BAND_4_C] = 0x7ad,
+       [WM8996_DSP2_RX_EQ_BAND_4_PG] = 0x1103,
+       [WM8996_DSP2_RX_EQ_BAND_5_A] = 0x564,
+       [WM8996_DSP2_RX_EQ_BAND_5_B] = 0x559,
+       [WM8996_DSP2_RX_EQ_BAND_5_PG] = 0x4000,
+       [WM8996_OVERSAMPLING] = 0xd,
+       [WM8996_SIDETONE] = 0x1040,
+       [WM8996_GPIO_1] = 0xa101,
+       [WM8996_GPIO_2] = 0xa101,
+       [WM8996_GPIO_3] = 0xa101,
+       [WM8996_GPIO_4] = 0xa101,
+       [WM8996_GPIO_5] = 0xa101,
+       [WM8996_PULL_CONTROL_2] = 0x140,
+       [WM8996_INTERRUPT_STATUS_1_MASK] = 0x1f,
+       [WM8996_INTERRUPT_STATUS_2_MASK] = 0x1ecf,
+       [WM8996_RIGHT_PDM_SPEAKER] = 0x1,
+       [WM8996_PDM_SPEAKER_MUTE_SEQUENCE] = 0x69,
+       [WM8996_PDM_SPEAKER_VOLUME] = 0x66,
+       [WM8996_WRITE_SEQUENCER_0] = 0x1,
+       [WM8996_WRITE_SEQUENCER_1] = 0x1,
+       [WM8996_WRITE_SEQUENCER_3] = 0x6,
+       [WM8996_WRITE_SEQUENCER_4] = 0x40,
+       [WM8996_WRITE_SEQUENCER_5] = 0x1,
+       [WM8996_WRITE_SEQUENCER_6] = 0xf,
+       [WM8996_WRITE_SEQUENCER_7] = 0x6,
+       [WM8996_WRITE_SEQUENCER_8] = 0x1,
+       [WM8996_WRITE_SEQUENCER_9] = 0x3,
+       [WM8996_WRITE_SEQUENCER_10] = 0x104,
+       [WM8996_WRITE_SEQUENCER_12] = 0x60,
+       [WM8996_WRITE_SEQUENCER_13] = 0x11,
+       [WM8996_WRITE_SEQUENCER_14] = 0x401,
+       [WM8996_WRITE_SEQUENCER_16] = 0x50,
+       [WM8996_WRITE_SEQUENCER_17] = 0x3,
+       [WM8996_WRITE_SEQUENCER_18] = 0x100,
+       [WM8996_WRITE_SEQUENCER_20] = 0x51,
+       [WM8996_WRITE_SEQUENCER_21] = 0x3,
+       [WM8996_WRITE_SEQUENCER_22] = 0x104,
+       [WM8996_WRITE_SEQUENCER_23] = 0xa,
+       [WM8996_WRITE_SEQUENCER_24] = 0x60,
+       [WM8996_WRITE_SEQUENCER_25] = 0x3b,
+       [WM8996_WRITE_SEQUENCER_26] = 0x502,
+       [WM8996_WRITE_SEQUENCER_27] = 0x100,
+       [WM8996_WRITE_SEQUENCER_28] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_32] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_36] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_40] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_44] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_48] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_52] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_56] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_60] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_64] = 0x1,
+       [WM8996_WRITE_SEQUENCER_65] = 0x1,
+       [WM8996_WRITE_SEQUENCER_67] = 0x6,
+       [WM8996_WRITE_SEQUENCER_68] = 0x40,
+       [WM8996_WRITE_SEQUENCER_69] = 0x1,
+       [WM8996_WRITE_SEQUENCER_70] = 0xf,
+       [WM8996_WRITE_SEQUENCER_71] = 0x6,
+       [WM8996_WRITE_SEQUENCER_72] = 0x1,
+       [WM8996_WRITE_SEQUENCER_73] = 0x3,
+       [WM8996_WRITE_SEQUENCER_74] = 0x104,
+       [WM8996_WRITE_SEQUENCER_76] = 0x60,
+       [WM8996_WRITE_SEQUENCER_77] = 0x11,
+       [WM8996_WRITE_SEQUENCER_78] = 0x401,
+       [WM8996_WRITE_SEQUENCER_80] = 0x50,
+       [WM8996_WRITE_SEQUENCER_81] = 0x3,
+       [WM8996_WRITE_SEQUENCER_82] = 0x100,
+       [WM8996_WRITE_SEQUENCER_84] = 0x60,
+       [WM8996_WRITE_SEQUENCER_85] = 0x3b,
+       [WM8996_WRITE_SEQUENCER_86] = 0x502,
+       [WM8996_WRITE_SEQUENCER_87] = 0x100,
+       [WM8996_WRITE_SEQUENCER_88] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_92] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_96] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_100] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_104] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_108] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_112] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_116] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_120] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_124] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_128] = 0x1,
+       [WM8996_WRITE_SEQUENCER_129] = 0x1,
+       [WM8996_WRITE_SEQUENCER_131] = 0x6,
+       [WM8996_WRITE_SEQUENCER_132] = 0x40,
+       [WM8996_WRITE_SEQUENCER_133] = 0x1,
+       [WM8996_WRITE_SEQUENCER_134] = 0xf,
+       [WM8996_WRITE_SEQUENCER_135] = 0x6,
+       [WM8996_WRITE_SEQUENCER_136] = 0x1,
+       [WM8996_WRITE_SEQUENCER_137] = 0x3,
+       [WM8996_WRITE_SEQUENCER_138] = 0x106,
+       [WM8996_WRITE_SEQUENCER_140] = 0x61,
+       [WM8996_WRITE_SEQUENCER_141] = 0x11,
+       [WM8996_WRITE_SEQUENCER_142] = 0x401,
+       [WM8996_WRITE_SEQUENCER_144] = 0x50,
+       [WM8996_WRITE_SEQUENCER_145] = 0x3,
+       [WM8996_WRITE_SEQUENCER_146] = 0x102,
+       [WM8996_WRITE_SEQUENCER_148] = 0x51,
+       [WM8996_WRITE_SEQUENCER_149] = 0x3,
+       [WM8996_WRITE_SEQUENCER_150] = 0x106,
+       [WM8996_WRITE_SEQUENCER_151] = 0xa,
+       [WM8996_WRITE_SEQUENCER_152] = 0x61,
+       [WM8996_WRITE_SEQUENCER_153] = 0x3b,
+       [WM8996_WRITE_SEQUENCER_154] = 0x502,
+       [WM8996_WRITE_SEQUENCER_155] = 0x100,
+       [WM8996_WRITE_SEQUENCER_156] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_160] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_164] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_168] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_172] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_176] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_180] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_184] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_188] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_192] = 0x1,
+       [WM8996_WRITE_SEQUENCER_193] = 0x1,
+       [WM8996_WRITE_SEQUENCER_195] = 0x6,
+       [WM8996_WRITE_SEQUENCER_196] = 0x40,
+       [WM8996_WRITE_SEQUENCER_197] = 0x1,
+       [WM8996_WRITE_SEQUENCER_198] = 0xf,
+       [WM8996_WRITE_SEQUENCER_199] = 0x6,
+       [WM8996_WRITE_SEQUENCER_200] = 0x1,
+       [WM8996_WRITE_SEQUENCER_201] = 0x3,
+       [WM8996_WRITE_SEQUENCER_202] = 0x106,
+       [WM8996_WRITE_SEQUENCER_204] = 0x61,
+       [WM8996_WRITE_SEQUENCER_205] = 0x11,
+       [WM8996_WRITE_SEQUENCER_206] = 0x401,
+       [WM8996_WRITE_SEQUENCER_208] = 0x50,
+       [WM8996_WRITE_SEQUENCER_209] = 0x3,
+       [WM8996_WRITE_SEQUENCER_210] = 0x102,
+       [WM8996_WRITE_SEQUENCER_212] = 0x61,
+       [WM8996_WRITE_SEQUENCER_213] = 0x3b,
+       [WM8996_WRITE_SEQUENCER_214] = 0x502,
+       [WM8996_WRITE_SEQUENCER_215] = 0x100,
+       [WM8996_WRITE_SEQUENCER_216] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_220] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_224] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_228] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_232] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_236] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_240] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_244] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_248] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_252] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_256] = 0x60,
+       [WM8996_WRITE_SEQUENCER_258] = 0x601,
+       [WM8996_WRITE_SEQUENCER_260] = 0x50,
+       [WM8996_WRITE_SEQUENCER_262] = 0x100,
+       [WM8996_WRITE_SEQUENCER_264] = 0x1,
+       [WM8996_WRITE_SEQUENCER_266] = 0x104,
+       [WM8996_WRITE_SEQUENCER_267] = 0x100,
+       [WM8996_WRITE_SEQUENCER_268] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_272] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_276] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_280] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_284] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_288] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_292] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_296] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_300] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_304] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_308] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_312] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_316] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_320] = 0x61,
+       [WM8996_WRITE_SEQUENCER_322] = 0x601,
+       [WM8996_WRITE_SEQUENCER_324] = 0x50,
+       [WM8996_WRITE_SEQUENCER_326] = 0x102,
+       [WM8996_WRITE_SEQUENCER_328] = 0x1,
+       [WM8996_WRITE_SEQUENCER_330] = 0x106,
+       [WM8996_WRITE_SEQUENCER_331] = 0x100,
+       [WM8996_WRITE_SEQUENCER_332] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_336] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_340] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_344] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_348] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_352] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_356] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_360] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_364] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_368] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_372] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_376] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_380] = 0x2fff,
+       [WM8996_WRITE_SEQUENCER_384] = 0x60,
+       [WM8996_WRITE_SEQUENCER_386] = 0x601,
+       [WM8996_WRITE_SEQUENCER_388] = 0x61,
+       [WM8996_WRITE_SEQUENCER_390] = 0x601,
+       [WM8996_WRITE_SEQUENCER_392] = 0x50,
+       [WM8996_WRITE_SEQUENCER_394] = 0x300,
+       [WM8996_WRITE_SEQUENCER_396] = 0x1,
+       [WM8996_WRITE_SEQUENCER_398] = 0x304,
+       [WM8996_WRITE_SEQUENCER_400] = 0x40,
+       [WM8996_WRITE_SEQUENCER_402] = 0xf,
+       [WM8996_WRITE_SEQUENCER_404] = 0x1,
+       [WM8996_WRITE_SEQUENCER_407] = 0x100,
+};
+
+static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0);
+static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 150, 0);
+static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
+static const DECLARE_TLV_DB_SCALE(out_digital_tlv, -1200, 150, 0);
+static const DECLARE_TLV_DB_SCALE(out_tlv, -900, 75, 0);
+static const DECLARE_TLV_DB_SCALE(spk_tlv, -900, 150, 0);
+static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+
+static const char *sidetone_hpf_text[] = {
+       "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz"
+};
+
+static const struct soc_enum sidetone_hpf =
+       SOC_ENUM_SINGLE(WM8996_SIDETONE, 7, 6, sidetone_hpf_text);
+
+static const char *hpf_mode_text[] = {
+       "HiFi", "Custom", "Voice"
+};
+
+static const struct soc_enum dsp1tx_hpf_mode =
+       SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 3, 3, hpf_mode_text);
+
+static const struct soc_enum dsp2tx_hpf_mode =
+       SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 3, 3, hpf_mode_text);
+
+static const char *hpf_cutoff_text[] = {
+       "50Hz", "75Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
+};
+
+static const struct soc_enum dsp1tx_hpf_cutoff =
+       SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 0, 7, hpf_cutoff_text);
+
+static const struct soc_enum dsp2tx_hpf_cutoff =
+       SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 0, 7, hpf_cutoff_text);
+
+static void wm8996_set_retune_mobile(struct snd_soc_codec *codec, int block)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       struct wm8996_pdata *pdata = &wm8996->pdata;
+       int base, best, best_val, save, i, cfg, iface;
+
+       if (!wm8996->num_retune_mobile_texts)
+               return;
+
+       switch (block) {
+       case 0:
+               base = WM8996_DSP1_RX_EQ_GAINS_1;
+               if (snd_soc_read(codec, WM8996_POWER_MANAGEMENT_8) &
+                   WM8996_DSP1RX_SRC)
+                       iface = 1;
+               else
+                       iface = 0;
+               break;
+       case 1:
+               base = WM8996_DSP1_RX_EQ_GAINS_2;
+               if (snd_soc_read(codec, WM8996_POWER_MANAGEMENT_8) &
+                   WM8996_DSP2RX_SRC)
+                       iface = 1;
+               else
+                       iface = 0;
+               break;
+       default:
+               return;
+       }
+
+       /* Find the version of the currently selected configuration
+        * with the nearest sample rate. */
+       cfg = wm8996->retune_mobile_cfg[block];
+       best = 0;
+       best_val = INT_MAX;
+       for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) {
+               if (strcmp(pdata->retune_mobile_cfgs[i].name,
+                          wm8996->retune_mobile_texts[cfg]) == 0 &&
+                   abs(pdata->retune_mobile_cfgs[i].rate
+                       - wm8996->rx_rate[iface]) < best_val) {
+                       best = i;
+                       best_val = abs(pdata->retune_mobile_cfgs[i].rate
+                                      - wm8996->rx_rate[iface]);
+               }
+       }
+
+       dev_dbg(codec->dev, "ReTune Mobile %d %s/%dHz for %dHz sample rate\n",
+               block,
+               pdata->retune_mobile_cfgs[best].name,
+               pdata->retune_mobile_cfgs[best].rate,
+               wm8996->rx_rate[iface]);
+
+       /* The EQ will be disabled while reconfiguring it, remember the
+        * current configuration. 
+        */
+       save = snd_soc_read(codec, base);
+       save &= WM8996_DSP1RX_EQ_ENA;
+
+       for (i = 0; i < ARRAY_SIZE(pdata->retune_mobile_cfgs[best].regs); i++)
+               snd_soc_update_bits(codec, base + i, 0xffff,
+                                   pdata->retune_mobile_cfgs[best].regs[i]);
+
+       snd_soc_update_bits(codec, base, WM8996_DSP1RX_EQ_ENA, save);
+}
+
+/* Icky as hell but saves code duplication */
+static int wm8996_get_retune_mobile_block(const char *name)
+{
+       if (strcmp(name, "DSP1 EQ Mode") == 0)
+               return 0;
+       if (strcmp(name, "DSP2 EQ Mode") == 0)
+               return 1;
+       return -EINVAL;
+}
+
+static int wm8996_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       struct wm8996_pdata *pdata = &wm8996->pdata;
+       int block = wm8996_get_retune_mobile_block(kcontrol->id.name);
+       int value = ucontrol->value.integer.value[0];
+
+       if (block < 0)
+               return block;
+
+       if (value >= pdata->num_retune_mobile_cfgs)
+               return -EINVAL;
+
+       wm8996->retune_mobile_cfg[block] = value;
+
+       wm8996_set_retune_mobile(codec, block);
+
+       return 0;
+}
+
+static int wm8996_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       int block = wm8996_get_retune_mobile_block(kcontrol->id.name);
+
+       ucontrol->value.enumerated.item[0] = wm8996->retune_mobile_cfg[block];
+
+       return 0;
+}
+
+static const struct snd_kcontrol_new wm8996_snd_controls[] = {
+SOC_DOUBLE_R_TLV("Capture Volume", WM8996_LEFT_LINE_INPUT_VOLUME,
+                WM8996_RIGHT_LINE_INPUT_VOLUME, 0, 31, 0, inpga_tlv),
+SOC_DOUBLE_R("Capture ZC Switch", WM8996_LEFT_LINE_INPUT_VOLUME,
+            WM8996_RIGHT_LINE_INPUT_VOLUME, 5, 1, 0),
+
+SOC_DOUBLE_TLV("DAC1 Sidetone Volume", WM8996_DAC1_MIXER_VOLUMES,
+              0, 5, 24, 0, sidetone_tlv),
+SOC_DOUBLE_TLV("DAC2 Sidetone Volume", WM8996_DAC2_MIXER_VOLUMES,
+              0, 5, 24, 0, sidetone_tlv),
+SOC_SINGLE("Sidetone LPF Switch", WM8996_SIDETONE, 12, 1, 0),
+SOC_ENUM("Sidetone HPF Cut-off", sidetone_hpf),
+SOC_SINGLE("Sidetone HPF Switch", WM8996_SIDETONE, 6, 1, 0),
+
+SOC_DOUBLE_R_TLV("DSP1 Capture Volume", WM8996_DSP1_TX_LEFT_VOLUME,
+                WM8996_DSP1_TX_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("DSP2 Capture Volume", WM8996_DSP2_TX_LEFT_VOLUME,
+                WM8996_DSP2_TX_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
+
+SOC_SINGLE("DSP1 Capture Notch Filter Switch", WM8996_DSP1_TX_FILTERS,
+          13, 1, 0),
+SOC_DOUBLE("DSP1 Capture HPF Switch", WM8996_DSP1_TX_FILTERS, 12, 11, 1, 0),
+SOC_ENUM("DSP1 Capture HPF Mode", dsp1tx_hpf_mode),
+SOC_ENUM("DSP1 Capture HPF Cutoff", dsp1tx_hpf_cutoff),
+
+SOC_SINGLE("DSP2 Capture Notch Filter Switch", WM8996_DSP2_TX_FILTERS,
+          13, 1, 0),
+SOC_DOUBLE("DSP2 Capture HPF Switch", WM8996_DSP2_TX_FILTERS, 12, 11, 1, 0),
+SOC_ENUM("DSP2 Capture HPF Mode", dsp2tx_hpf_mode),
+SOC_ENUM("DSP2 Capture HPF Cutoff", dsp2tx_hpf_cutoff),
+
+SOC_DOUBLE_R_TLV("DSP1 Playback Volume", WM8996_DSP1_RX_LEFT_VOLUME,
+                WM8996_DSP1_RX_RIGHT_VOLUME, 1, 112, 0, digital_tlv),
+SOC_SINGLE("DSP1 Playback Switch", WM8996_DSP1_RX_FILTERS_1, 9, 1, 1),
+
+SOC_DOUBLE_R_TLV("DSP2 Playback Volume", WM8996_DSP2_RX_LEFT_VOLUME,
+                WM8996_DSP2_RX_RIGHT_VOLUME, 1, 112, 0, digital_tlv),
+SOC_SINGLE("DSP2 Playback Switch", WM8996_DSP2_RX_FILTERS_1, 9, 1, 1),
+
+SOC_DOUBLE_R_TLV("DAC1 Volume", WM8996_DAC1_LEFT_VOLUME,
+                WM8996_DAC1_RIGHT_VOLUME, 1, 112, 0, digital_tlv),
+SOC_DOUBLE_R("DAC1 Switch", WM8996_DAC1_LEFT_VOLUME,
+            WM8996_DAC1_RIGHT_VOLUME, 9, 1, 1),
+
+SOC_DOUBLE_R_TLV("DAC2 Volume", WM8996_DAC2_LEFT_VOLUME,
+                WM8996_DAC2_RIGHT_VOLUME, 1, 112, 0, digital_tlv),
+SOC_DOUBLE_R("DAC2 Switch", WM8996_DAC2_LEFT_VOLUME,
+            WM8996_DAC2_RIGHT_VOLUME, 9, 1, 1),
+
+SOC_SINGLE("Speaker High Performance Switch", WM8996_OVERSAMPLING, 3, 1, 0),
+SOC_SINGLE("DMIC High Performance Switch", WM8996_OVERSAMPLING, 2, 1, 0),
+SOC_SINGLE("ADC High Performance Switch", WM8996_OVERSAMPLING, 1, 1, 0),
+SOC_SINGLE("DAC High Performance Switch", WM8996_OVERSAMPLING, 0, 1, 0),
+
+SOC_SINGLE("DAC Soft Mute Switch", WM8996_DAC_SOFTMUTE, 1, 1, 0),
+SOC_SINGLE("DAC Slow Soft Mute Switch", WM8996_DAC_SOFTMUTE, 0, 1, 0),
+
+SOC_DOUBLE_TLV("Digital Output 1 Volume", WM8996_DAC1_HPOUT1_VOLUME, 0, 4,
+              8, 0, out_digital_tlv),
+SOC_DOUBLE_TLV("Digital Output 2 Volume", WM8996_DAC2_HPOUT2_VOLUME, 0, 4,
+              8, 0, out_digital_tlv),
+
+SOC_DOUBLE_R_TLV("Output 1 Volume", WM8996_OUTPUT1_LEFT_VOLUME,
+                WM8996_OUTPUT1_RIGHT_VOLUME, 0, 12, 0, out_tlv),
+SOC_DOUBLE_R("Output 1 ZC Switch",  WM8996_OUTPUT1_LEFT_VOLUME,
+            WM8996_OUTPUT1_RIGHT_VOLUME, 7, 1, 0),
+
+SOC_DOUBLE_R_TLV("Output 2 Volume", WM8996_OUTPUT2_LEFT_VOLUME,
+                WM8996_OUTPUT2_RIGHT_VOLUME, 0, 12, 0, out_tlv),
+SOC_DOUBLE_R("Output 2 ZC Switch",  WM8996_OUTPUT2_LEFT_VOLUME,
+            WM8996_OUTPUT2_RIGHT_VOLUME, 7, 1, 0),
+
+SOC_DOUBLE_TLV("Speaker Volume", WM8996_PDM_SPEAKER_VOLUME, 0, 4, 8, 0,
+              spk_tlv),
+SOC_DOUBLE_R("Speaker Switch", WM8996_LEFT_PDM_SPEAKER,
+            WM8996_RIGHT_PDM_SPEAKER, 3, 1, 1),
+SOC_DOUBLE_R("Speaker ZC Switch", WM8996_LEFT_PDM_SPEAKER,
+            WM8996_RIGHT_PDM_SPEAKER, 2, 1, 0),
+
+SOC_SINGLE("DSP1 EQ Switch", WM8996_DSP1_RX_EQ_GAINS_1, 0, 1, 0),
+SOC_SINGLE("DSP2 EQ Switch", WM8996_DSP2_RX_EQ_GAINS_1, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8996_eq_controls[] = {
+SOC_SINGLE_TLV("DSP1 EQ B1 Volume", WM8996_DSP1_RX_EQ_GAINS_1, 11, 31, 0,
+              eq_tlv),
+SOC_SINGLE_TLV("DSP1 EQ B2 Volume", WM8996_DSP1_RX_EQ_GAINS_1, 6, 31, 0,
+              eq_tlv),
+SOC_SINGLE_TLV("DSP1 EQ B3 Volume", WM8996_DSP1_RX_EQ_GAINS_1, 1, 31, 0,
+              eq_tlv),
+SOC_SINGLE_TLV("DSP1 EQ B4 Volume", WM8996_DSP1_RX_EQ_GAINS_2, 11, 31, 0,
+              eq_tlv),
+SOC_SINGLE_TLV("DSP1 EQ B5 Volume", WM8996_DSP1_RX_EQ_GAINS_2, 6, 31, 0,
+              eq_tlv),
+
+SOC_SINGLE_TLV("DSP2 EQ B1 Volume", WM8996_DSP2_RX_EQ_GAINS_1, 11, 31, 0,
+              eq_tlv),
+SOC_SINGLE_TLV("DSP2 EQ B2 Volume", WM8996_DSP2_RX_EQ_GAINS_1, 6, 31, 0,
+              eq_tlv),
+SOC_SINGLE_TLV("DSP2 EQ B3 Volume", WM8996_DSP2_RX_EQ_GAINS_1, 1, 31, 0,
+              eq_tlv),
+SOC_SINGLE_TLV("DSP2 EQ B4 Volume", WM8996_DSP2_RX_EQ_GAINS_2, 11, 31, 0,
+              eq_tlv),
+SOC_SINGLE_TLV("DSP2 EQ B5 Volume", WM8996_DSP2_RX_EQ_GAINS_2, 6, 31, 0,
+              eq_tlv),
+};
+
+static int cp_event(struct snd_soc_dapm_widget *w,
+                   struct snd_kcontrol *kcontrol, int event)
+{
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               msleep(5);
+               break;
+       default:
+               BUG();
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int rmv_short_event(struct snd_soc_dapm_widget *w,
+                          struct snd_kcontrol *kcontrol, int event)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(w->codec);
+
+       /* Record which outputs we enabled */
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMD:
+               wm8996->hpout_pending &= ~w->shift;
+               break;
+       case SND_SOC_DAPM_PRE_PMU:
+               wm8996->hpout_pending |= w->shift;
+               break;
+       default:
+               BUG();
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask)
+{
+       struct i2c_client *i2c = to_i2c_client(codec->dev);
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       int i, ret;
+       unsigned long timeout = 200;
+
+       snd_soc_write(codec, WM8996_DC_SERVO_2, mask);
+
+       /* Use the interrupt if possible */
+       do {
+               if (i2c->irq) {
+                       timeout = wait_for_completion_timeout(&wm8996->dcs_done,
+                                                             msecs_to_jiffies(200));
+                       if (timeout == 0)
+                               dev_err(codec->dev, "DC servo timed out\n");
+
+               } else {
+                       msleep(1);
+                       if (--i) {
+                               timeout = 0;
+                               break;
+                       }
+               }
+
+               ret = snd_soc_read(codec, WM8996_DC_SERVO_2);
+               dev_dbg(codec->dev, "DC servo state: %x\n", ret);
+       } while (ret & mask);
+
+       if (timeout == 0)
+               dev_err(codec->dev, "DC servo timed out for %x\n", mask);
+       else
+               dev_dbg(codec->dev, "DC servo complete for %x\n", mask);
+}
+
+static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
+                               enum snd_soc_dapm_type event, int subseq)
+{
+       struct snd_soc_codec *codec = container_of(dapm,
+                                                  struct snd_soc_codec, dapm);
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       u16 val, mask;
+
+       /* Complete any pending DC servo starts */
+       if (wm8996->dcs_pending) {
+               dev_dbg(codec->dev, "Starting DC servo for %x\n",
+                       wm8996->dcs_pending);
+
+               /* Trigger a startup sequence */
+               wait_for_dc_servo(codec, wm8996->dcs_pending
+                                        << WM8996_DCS_TRIG_STARTUP_0_SHIFT);
+
+               wm8996->dcs_pending = 0;
+       }
+
+       if (wm8996->hpout_pending != wm8996->hpout_ena) {
+               dev_dbg(codec->dev, "Applying RMV_SHORTs %x->%x\n",
+                       wm8996->hpout_ena, wm8996->hpout_pending);
+
+               val = 0;
+               mask = 0;
+               if (wm8996->hpout_pending & HPOUT1L) {
+                       val |= WM8996_HPOUT1L_RMV_SHORT;
+                       mask |= WM8996_HPOUT1L_RMV_SHORT;
+               } else {
+                       mask |= WM8996_HPOUT1L_RMV_SHORT |
+                               WM8996_HPOUT1L_OUTP |
+                               WM8996_HPOUT1L_DLY;
+               }
+
+               if (wm8996->hpout_pending & HPOUT1R) {
+                       val |= WM8996_HPOUT1R_RMV_SHORT;
+                       mask |= WM8996_HPOUT1R_RMV_SHORT;
+               } else {
+                       mask |= WM8996_HPOUT1R_RMV_SHORT |
+                               WM8996_HPOUT1R_OUTP |
+                               WM8996_HPOUT1R_DLY;
+               }
+
+               snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1, mask, val);
+
+               val = 0;
+               mask = 0;
+               if (wm8996->hpout_pending & HPOUT2L) {
+                       val |= WM8996_HPOUT2L_RMV_SHORT;
+                       mask |= WM8996_HPOUT2L_RMV_SHORT;
+               } else {
+                       mask |= WM8996_HPOUT2L_RMV_SHORT |
+                               WM8996_HPOUT2L_OUTP |
+                               WM8996_HPOUT2L_DLY;
+               }
+
+               if (wm8996->hpout_pending & HPOUT2R) {
+                       val |= WM8996_HPOUT2R_RMV_SHORT;
+                       mask |= WM8996_HPOUT2R_RMV_SHORT;
+               } else {
+                       mask |= WM8996_HPOUT2R_RMV_SHORT |
+                               WM8996_HPOUT2R_OUTP |
+                               WM8996_HPOUT2R_DLY;
+               }
+
+               snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_2, mask, val);
+
+               wm8996->hpout_ena = wm8996->hpout_pending;
+       }
+}
+
+static int dcs_start(struct snd_soc_dapm_widget *w,
+                    struct snd_kcontrol *kcontrol, int event)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(w->codec);
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               wm8996->dcs_pending |= 1 << w->shift;
+               break;
+       default:
+               BUG();
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const char *sidetone_text[] = {
+       "IN1", "IN2",
+};
+
+static const struct soc_enum left_sidetone_enum =
+       SOC_ENUM_SINGLE(WM8996_SIDETONE, 0, 2, sidetone_text);
+
+static const struct snd_kcontrol_new left_sidetone =
+       SOC_DAPM_ENUM("Left Sidetone", left_sidetone_enum);
+
+static const struct soc_enum right_sidetone_enum =
+       SOC_ENUM_SINGLE(WM8996_SIDETONE, 1, 2, sidetone_text);
+
+static const struct snd_kcontrol_new right_sidetone =
+       SOC_DAPM_ENUM("Right Sidetone", right_sidetone_enum);
+
+static const char *spk_text[] = {
+       "DAC1L", "DAC1R", "DAC2L", "DAC2R"
+};
+
+static const struct soc_enum spkl_enum =
+       SOC_ENUM_SINGLE(WM8996_LEFT_PDM_SPEAKER, 0, 4, spk_text);
+
+static const struct snd_kcontrol_new spkl_mux =
+       SOC_DAPM_ENUM("SPKL", spkl_enum);
+
+static const struct soc_enum spkr_enum =
+       SOC_ENUM_SINGLE(WM8996_RIGHT_PDM_SPEAKER, 0, 4, spk_text);
+
+static const struct snd_kcontrol_new spkr_mux =
+       SOC_DAPM_ENUM("SPKR", spkr_enum);
+
+static const char *dsp1rx_text[] = {
+       "AIF1", "AIF2"
+};
+
+static const struct soc_enum dsp1rx_enum =
+       SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 0, 2, dsp1rx_text);
+
+static const struct snd_kcontrol_new dsp1rx =
+       SOC_DAPM_ENUM("DSP1RX", dsp1rx_enum);
+
+static const char *dsp2rx_text[] = {
+        "AIF2", "AIF1"
+};
+
+static const struct soc_enum dsp2rx_enum =
+       SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 4, 2, dsp2rx_text);
+
+static const struct snd_kcontrol_new dsp2rx =
+       SOC_DAPM_ENUM("DSP2RX", dsp2rx_enum);
+
+static const char *aif2tx_text[] = {
+       "DSP2", "DSP1", "AIF1"
+};
+
+static const struct soc_enum aif2tx_enum =
+       SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 6, 3, aif2tx_text);
+
+static const struct snd_kcontrol_new aif2tx =
+       SOC_DAPM_ENUM("AIF2TX", aif2tx_enum);
+
+static const char *inmux_text[] = {
+       "ADC", "DMIC1", "DMIC2"
+};
+
+static const struct soc_enum in1_enum =
+       SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 0, 3, inmux_text);
+
+static const struct snd_kcontrol_new in1_mux =
+       SOC_DAPM_ENUM("IN1 Mux", in1_enum);
+
+static const struct soc_enum in2_enum =
+       SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 4, 3, inmux_text);
+
+static const struct snd_kcontrol_new in2_mux =
+       SOC_DAPM_ENUM("IN2 Mux", in2_enum);
+
+static const struct snd_kcontrol_new dac2r_mix[] = {
+SOC_DAPM_SINGLE("Right Sidetone Switch", WM8996_DAC2_RIGHT_MIXER_ROUTING,
+               5, 1, 0),
+SOC_DAPM_SINGLE("Left Sidetone Switch", WM8996_DAC2_RIGHT_MIXER_ROUTING,
+               4, 1, 0),
+SOC_DAPM_SINGLE("DSP2 Switch", WM8996_DAC2_RIGHT_MIXER_ROUTING, 1, 1, 0),
+SOC_DAPM_SINGLE("DSP1 Switch", WM8996_DAC2_RIGHT_MIXER_ROUTING, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new dac2l_mix[] = {
+SOC_DAPM_SINGLE("Right Sidetone Switch", WM8996_DAC2_LEFT_MIXER_ROUTING,
+               5, 1, 0),
+SOC_DAPM_SINGLE("Left Sidetone Switch", WM8996_DAC2_LEFT_MIXER_ROUTING,
+               4, 1, 0),
+SOC_DAPM_SINGLE("DSP2 Switch", WM8996_DAC2_LEFT_MIXER_ROUTING, 1, 1, 0),
+SOC_DAPM_SINGLE("DSP1 Switch", WM8996_DAC2_LEFT_MIXER_ROUTING, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new dac1r_mix[] = {
+SOC_DAPM_SINGLE("Right Sidetone Switch", WM8996_DAC1_RIGHT_MIXER_ROUTING,
+               5, 1, 0),
+SOC_DAPM_SINGLE("Left Sidetone Switch", WM8996_DAC1_RIGHT_MIXER_ROUTING,
+               4, 1, 0),
+SOC_DAPM_SINGLE("DSP2 Switch", WM8996_DAC1_RIGHT_MIXER_ROUTING, 1, 1, 0),
+SOC_DAPM_SINGLE("DSP1 Switch", WM8996_DAC1_RIGHT_MIXER_ROUTING, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new dac1l_mix[] = {
+SOC_DAPM_SINGLE("Right Sidetone Switch", WM8996_DAC1_LEFT_MIXER_ROUTING,
+               5, 1, 0),
+SOC_DAPM_SINGLE("Left Sidetone Switch", WM8996_DAC1_LEFT_MIXER_ROUTING,
+               4, 1, 0),
+SOC_DAPM_SINGLE("DSP2 Switch", WM8996_DAC1_LEFT_MIXER_ROUTING, 1, 1, 0),
+SOC_DAPM_SINGLE("DSP1 Switch", WM8996_DAC1_LEFT_MIXER_ROUTING, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new dsp1txl[] = {
+SOC_DAPM_SINGLE("IN1 Switch", WM8996_DSP1_TX_LEFT_MIXER_ROUTING,
+               1, 1, 0),
+SOC_DAPM_SINGLE("DAC Switch", WM8996_DSP1_TX_LEFT_MIXER_ROUTING,
+               0, 1, 0),
+};
+
+static const struct snd_kcontrol_new dsp1txr[] = {
+SOC_DAPM_SINGLE("IN1 Switch", WM8996_DSP1_TX_RIGHT_MIXER_ROUTING,
+               1, 1, 0),
+SOC_DAPM_SINGLE("DAC Switch", WM8996_DSP1_TX_RIGHT_MIXER_ROUTING,
+               0, 1, 0),
+};
+
+static const struct snd_kcontrol_new dsp2txl[] = {
+SOC_DAPM_SINGLE("IN1 Switch", WM8996_DSP2_TX_LEFT_MIXER_ROUTING,
+               1, 1, 0),
+SOC_DAPM_SINGLE("DAC Switch", WM8996_DSP2_TX_LEFT_MIXER_ROUTING,
+               0, 1, 0),
+};
+
+static const struct snd_kcontrol_new dsp2txr[] = {
+SOC_DAPM_SINGLE("IN1 Switch", WM8996_DSP2_TX_RIGHT_MIXER_ROUTING,
+               1, 1, 0),
+SOC_DAPM_SINGLE("DAC Switch", WM8996_DSP2_TX_RIGHT_MIXER_ROUTING,
+               0, 1, 0),
+};
+
+
+static const struct snd_soc_dapm_widget wm8996_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("IN1LN"),
+SND_SOC_DAPM_INPUT("IN1LP"),
+SND_SOC_DAPM_INPUT("IN1RN"),
+SND_SOC_DAPM_INPUT("IN1RP"),
+
+SND_SOC_DAPM_INPUT("IN2LN"),
+SND_SOC_DAPM_INPUT("IN2LP"),
+SND_SOC_DAPM_INPUT("IN2RN"),
+SND_SOC_DAPM_INPUT("IN2RP"),
+
+SND_SOC_DAPM_INPUT("DMIC1DAT"),
+SND_SOC_DAPM_INPUT("DMIC2DAT"),
+
+SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event,
+                     SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
+SND_SOC_DAPM_MICBIAS("MICB2", WM8996_POWER_MANAGEMENT_1, 9, 0),
+SND_SOC_DAPM_MICBIAS("MICB1", WM8996_POWER_MANAGEMENT_1, 8, 0),
+
+SND_SOC_DAPM_PGA("IN1L PGA", WM8996_POWER_MANAGEMENT_2, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA("IN1R PGA", WM8996_POWER_MANAGEMENT_2, 4, 0, NULL, 0),
+
+SND_SOC_DAPM_MUX("IN1L Mux", SND_SOC_NOPM, 0, 0, &in1_mux),
+SND_SOC_DAPM_MUX("IN1R Mux", SND_SOC_NOPM, 0, 0, &in1_mux),
+SND_SOC_DAPM_MUX("IN2L Mux", SND_SOC_NOPM, 0, 0, &in2_mux),
+SND_SOC_DAPM_MUX("IN2R Mux", SND_SOC_NOPM, 0, 0, &in2_mux),
+
+SND_SOC_DAPM_PGA("IN1L", WM8996_POWER_MANAGEMENT_7, 2, 0, NULL, 0),
+SND_SOC_DAPM_PGA("IN1R", WM8996_POWER_MANAGEMENT_7, 3, 0, NULL, 0),
+SND_SOC_DAPM_PGA("IN2L", WM8996_POWER_MANAGEMENT_7, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA("IN2R", WM8996_POWER_MANAGEMENT_7, 7, 0, NULL, 0),
+
+SND_SOC_DAPM_SUPPLY("DMIC2", WM8996_POWER_MANAGEMENT_7, 9, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("DMIC1", WM8996_POWER_MANAGEMENT_7, 8, 0, NULL, 0),
+
+SND_SOC_DAPM_ADC("DMIC2L", NULL, WM8996_POWER_MANAGEMENT_3, 5, 0),
+SND_SOC_DAPM_ADC("DMIC2R", NULL, WM8996_POWER_MANAGEMENT_3, 4, 0),
+SND_SOC_DAPM_ADC("DMIC1L", NULL, WM8996_POWER_MANAGEMENT_3, 3, 0),
+SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8996_POWER_MANAGEMENT_3, 2, 0),
+
+SND_SOC_DAPM_ADC("ADCL", NULL, WM8996_POWER_MANAGEMENT_3, 1, 0),
+SND_SOC_DAPM_ADC("ADCR", NULL, WM8996_POWER_MANAGEMENT_3, 0, 0),
+
+SND_SOC_DAPM_MUX("Left Sidetone", SND_SOC_NOPM, 0, 0, &left_sidetone),
+SND_SOC_DAPM_MUX("Right Sidetone", SND_SOC_NOPM, 0, 0, &right_sidetone),
+
+SND_SOC_DAPM_AIF_IN("DSP2RXL", NULL, 0, WM8996_POWER_MANAGEMENT_3, 11, 0),
+SND_SOC_DAPM_AIF_IN("DSP2RXR", NULL, 1, WM8996_POWER_MANAGEMENT_3, 10, 0),
+SND_SOC_DAPM_AIF_IN("DSP1RXL", NULL, 0, WM8996_POWER_MANAGEMENT_3, 9, 0),
+SND_SOC_DAPM_AIF_IN("DSP1RXR", NULL, 1, WM8996_POWER_MANAGEMENT_3, 8, 0),
+
+SND_SOC_DAPM_MIXER("DSP2TXL", WM8996_POWER_MANAGEMENT_5, 11, 0,
+                  dsp2txl, ARRAY_SIZE(dsp2txl)),
+SND_SOC_DAPM_MIXER("DSP2TXR", WM8996_POWER_MANAGEMENT_5, 10, 0,
+                  dsp2txr, ARRAY_SIZE(dsp2txr)),
+SND_SOC_DAPM_MIXER("DSP1TXL", WM8996_POWER_MANAGEMENT_5, 9, 0,
+                  dsp1txl, ARRAY_SIZE(dsp1txl)),
+SND_SOC_DAPM_MIXER("DSP1TXR", WM8996_POWER_MANAGEMENT_5, 8, 0,
+                  dsp1txr, ARRAY_SIZE(dsp1txr)),
+
+SND_SOC_DAPM_MIXER("DAC2L Mixer", SND_SOC_NOPM, 0, 0,
+                  dac2l_mix, ARRAY_SIZE(dac2l_mix)),
+SND_SOC_DAPM_MIXER("DAC2R Mixer", SND_SOC_NOPM, 0, 0,
+                  dac2r_mix, ARRAY_SIZE(dac2r_mix)),
+SND_SOC_DAPM_MIXER("DAC1L Mixer", SND_SOC_NOPM, 0, 0,
+                  dac1l_mix, ARRAY_SIZE(dac1l_mix)),
+SND_SOC_DAPM_MIXER("DAC1R Mixer", SND_SOC_NOPM, 0, 0,
+                  dac1r_mix, ARRAY_SIZE(dac1r_mix)),
+
+SND_SOC_DAPM_DAC("DAC2L", NULL, WM8996_POWER_MANAGEMENT_5, 3, 0),
+SND_SOC_DAPM_DAC("DAC2R", NULL, WM8996_POWER_MANAGEMENT_5, 2, 0),
+SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0),
+SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 1,
+                   WM8996_POWER_MANAGEMENT_4, 9, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 2,
+                   WM8996_POWER_MANAGEMENT_4, 8, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 1,
+                   WM8996_POWER_MANAGEMENT_6, 9, 0),
+SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 2,
+                   WM8996_POWER_MANAGEMENT_6, 8, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5,
+                   WM8996_POWER_MANAGEMENT_4, 5, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 4,
+                   WM8996_POWER_MANAGEMENT_4, 4, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 3,
+                   WM8996_POWER_MANAGEMENT_4, 3, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 2,
+                   WM8996_POWER_MANAGEMENT_4, 2, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 1,
+                   WM8996_POWER_MANAGEMENT_4, 1, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX0", "AIF1 Playback", 0,
+                   WM8996_POWER_MANAGEMENT_4, 0, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 5,
+                    WM8996_POWER_MANAGEMENT_6, 5, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 4,
+                    WM8996_POWER_MANAGEMENT_6, 4, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 3,
+                    WM8996_POWER_MANAGEMENT_6, 3, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 2,
+                    WM8996_POWER_MANAGEMENT_6, 2, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 1,
+                    WM8996_POWER_MANAGEMENT_6, 1, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX0", "AIF1 Capture", 0,
+                    WM8996_POWER_MANAGEMENT_6, 0, 0),
+
+/* We route as stereo pairs so define some dummy widgets to squash
+ * things down for now.  RXA = 0,1, RXB = 2,3 and so on */
+SND_SOC_DAPM_PGA("AIF1RXA", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_PGA("AIF1RXB", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_PGA("AIF1RXC", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_PGA("AIF2RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_PGA("DSP2TX", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+SND_SOC_DAPM_MUX("DSP1RX", SND_SOC_NOPM, 0, 0, &dsp1rx),
+SND_SOC_DAPM_MUX("DSP2RX", SND_SOC_NOPM, 0, 0, &dsp2rx),
+SND_SOC_DAPM_MUX("AIF2TX", SND_SOC_NOPM, 0, 0, &aif2tx),
+
+SND_SOC_DAPM_MUX("SPKL", SND_SOC_NOPM, 0, 0, &spkl_mux),
+SND_SOC_DAPM_MUX("SPKR", SND_SOC_NOPM, 0, 0, &spkr_mux),
+SND_SOC_DAPM_PGA("SPKL PGA", WM8996_LEFT_PDM_SPEAKER, 4, 0, NULL, 0),
+SND_SOC_DAPM_PGA("SPKR PGA", WM8996_RIGHT_PDM_SPEAKER, 4, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("HPOUT2L PGA", 0, WM8996_POWER_MANAGEMENT_1, 7, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPOUT2L_DLY", 1, WM8996_ANALOGUE_HP_2, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPOUT2L_DCS", 2, WM8996_DC_SERVO_1, 2, 0, dcs_start,
+                  SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_S("HPOUT2L_OUTP", 3, WM8996_ANALOGUE_HP_2, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPOUT2L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2L, 0,
+                  rmv_short_event,
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+
+SND_SOC_DAPM_PGA_S("HPOUT2R PGA", 0, WM8996_POWER_MANAGEMENT_1, 6, 0,NULL, 0),
+SND_SOC_DAPM_PGA_S("HPOUT2R_DLY", 1, WM8996_ANALOGUE_HP_2, 1, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPOUT2R_DCS", 2, WM8996_DC_SERVO_1, 3, 0, dcs_start,
+                  SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_S("HPOUT2R_OUTP", 3, WM8996_ANALOGUE_HP_2, 2, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPOUT2R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2R, 0,
+                  rmv_short_event,
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+
+SND_SOC_DAPM_PGA_S("HPOUT1L PGA", 0, WM8996_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPOUT1L_DLY", 1, WM8996_ANALOGUE_HP_1, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPOUT1L_DCS", 2, WM8996_DC_SERVO_1, 0, 0, dcs_start,
+                  SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_S("HPOUT1L_OUTP", 3, WM8996_ANALOGUE_HP_1, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPOUT1L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1L, 0,
+                  rmv_short_event,
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+
+SND_SOC_DAPM_PGA_S("HPOUT1R PGA", 0, WM8996_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPOUT1R_DLY", 1, WM8996_ANALOGUE_HP_1, 1, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPOUT1R_DCS", 2, WM8996_DC_SERVO_1, 1, 0, dcs_start,
+                  SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_S("HPOUT1R_OUTP", 3, WM8996_ANALOGUE_HP_1, 2, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPOUT1R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1R, 0,
+                  rmv_short_event,
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+
+SND_SOC_DAPM_OUTPUT("HPOUT1L"),
+SND_SOC_DAPM_OUTPUT("HPOUT1R"),
+SND_SOC_DAPM_OUTPUT("HPOUT2L"),
+SND_SOC_DAPM_OUTPUT("HPOUT2R"),
+SND_SOC_DAPM_OUTPUT("SPKDAT"),
+};
+
+static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
+       { "AIFCLK", NULL, "SYSCLK" },
+       { "SYSDSPCLK", NULL, "SYSCLK" },
+       { "Charge Pump", NULL, "SYSCLK" },
+
+       { "MICB1", NULL, "LDO2" },
+       { "MICB2", NULL, "LDO2" },
+
+       { "IN1L PGA", NULL, "IN2LN" },
+       { "IN1L PGA", NULL, "IN2LP" },
+       { "IN1L PGA", NULL, "IN1LN" },
+       { "IN1L PGA", NULL, "IN1LP" },
+
+       { "IN1R PGA", NULL, "IN2RN" },
+       { "IN1R PGA", NULL, "IN2RP" },
+       { "IN1R PGA", NULL, "IN1RN" },
+       { "IN1R PGA", NULL, "IN1RP" },
+
+       { "ADCL", NULL, "IN1L PGA" },
+
+       { "ADCR", NULL, "IN1R PGA" },
+
+       { "DMIC1L", NULL, "DMIC1DAT" },
+       { "DMIC1R", NULL, "DMIC1DAT" },
+       { "DMIC2L", NULL, "DMIC2DAT" },
+       { "DMIC2R", NULL, "DMIC2DAT" },
+
+       { "DMIC2L", NULL, "DMIC2" },
+       { "DMIC2R", NULL, "DMIC2" },
+       { "DMIC1L", NULL, "DMIC1" },
+       { "DMIC1R", NULL, "DMIC1" },
+
+       { "IN1L Mux", "ADC", "ADCL" },
+       { "IN1L Mux", "DMIC1", "DMIC1L" },
+       { "IN1L Mux", "DMIC2", "DMIC2L" },
+
+       { "IN1R Mux", "ADC", "ADCR" },
+       { "IN1R Mux", "DMIC1", "DMIC1R" },
+       { "IN1R Mux", "DMIC2", "DMIC2R" },
+
+       { "IN2L Mux", "ADC", "ADCL" },
+       { "IN2L Mux", "DMIC1", "DMIC1L" },
+       { "IN2L Mux", "DMIC2", "DMIC2L" },
+
+       { "IN2R Mux", "ADC", "ADCR" },
+       { "IN2R Mux", "DMIC1", "DMIC1R" },
+       { "IN2R Mux", "DMIC2", "DMIC2R" },
+
+       { "Left Sidetone", "IN1", "IN1L Mux" },
+       { "Left Sidetone", "IN2", "IN2L Mux" },
+
+       { "Right Sidetone", "IN1", "IN1R Mux" },
+       { "Right Sidetone", "IN2", "IN2R Mux" },
+
+       { "DSP1TXL", "IN1 Switch", "IN1L Mux" },
+       { "DSP1TXR", "IN1 Switch", "IN1R Mux" },
+
+       { "DSP2TXL", "IN1 Switch", "IN2L Mux" },
+       { "DSP2TXR", "IN1 Switch", "IN2R Mux" },
+
+       { "AIF1TX0", NULL, "DSP1TXL" },
+       { "AIF1TX1", NULL, "DSP1TXR" },
+       { "AIF1TX2", NULL, "DSP2TXL" },
+       { "AIF1TX3", NULL, "DSP2TXR" },
+       { "AIF1TX4", NULL, "AIF2RX0" },
+       { "AIF1TX5", NULL, "AIF2RX1" },
+
+       { "AIF1RX0", NULL, "AIFCLK" },
+       { "AIF1RX1", NULL, "AIFCLK" },
+       { "AIF1RX2", NULL, "AIFCLK" },
+       { "AIF1RX3", NULL, "AIFCLK" },
+       { "AIF1RX4", NULL, "AIFCLK" },
+       { "AIF1RX5", NULL, "AIFCLK" },
+
+       { "AIF2RX0", NULL, "AIFCLK" },
+       { "AIF2RX1", NULL, "AIFCLK" },
+
+       { "DSP1RXL", NULL, "SYSDSPCLK" },
+       { "DSP1RXR", NULL, "SYSDSPCLK" },
+       { "DSP2RXL", NULL, "SYSDSPCLK" },
+       { "DSP2RXR", NULL, "SYSDSPCLK" },
+       { "DSP1TXL", NULL, "SYSDSPCLK" },
+       { "DSP1TXR", NULL, "SYSDSPCLK" },
+       { "DSP2TXL", NULL, "SYSDSPCLK" },
+       { "DSP2TXR", NULL, "SYSDSPCLK" },
+
+       { "AIF1RXA", NULL, "AIF1RX0" },
+       { "AIF1RXA", NULL, "AIF1RX1" },
+       { "AIF1RXB", NULL, "AIF1RX2" },
+       { "AIF1RXB", NULL, "AIF1RX3" },
+       { "AIF1RXC", NULL, "AIF1RX4" },
+       { "AIF1RXC", NULL, "AIF1RX5" },
+
+       { "AIF2RX", NULL, "AIF2RX0" },
+       { "AIF2RX", NULL, "AIF2RX1" },
+
+       { "AIF2TX", "DSP2", "DSP2TX" },
+       { "AIF2TX", "DSP1", "DSP1RX" },
+       { "AIF2TX", "AIF1", "AIF1RXC" },
+
+       { "DSP1RXL", NULL, "DSP1RX" },
+       { "DSP1RXR", NULL, "DSP1RX" },
+       { "DSP2RXL", NULL, "DSP2RX" },
+       { "DSP2RXR", NULL, "DSP2RX" },
+
+       { "DSP2TX", NULL, "DSP2TXL" },
+       { "DSP2TX", NULL, "DSP2TXR" },
+
+       { "DSP1RX", "AIF1", "AIF1RXA" },
+       { "DSP1RX", "AIF2", "AIF2RX" },
+
+       { "DSP2RX", "AIF1", "AIF1RXB" },
+       { "DSP2RX", "AIF2", "AIF2RX" },
+
+       { "DAC2L Mixer", "DSP2 Switch", "DSP2RXL" },
+       { "DAC2L Mixer", "DSP1 Switch", "DSP1RXL" },
+       { "DAC2L Mixer", "Right Sidetone Switch", "Right Sidetone" },
+       { "DAC2L Mixer", "Left Sidetone Switch", "Left Sidetone" },
+
+       { "DAC2R Mixer", "DSP2 Switch", "DSP2RXR" },
+       { "DAC2R Mixer", "DSP1 Switch", "DSP1RXR" },
+       { "DAC2R Mixer", "Right Sidetone Switch", "Right Sidetone" },
+       { "DAC2R Mixer", "Left Sidetone Switch", "Left Sidetone" },
+
+       { "DAC1L Mixer", "DSP2 Switch", "DSP2RXL" },
+       { "DAC1L Mixer", "DSP1 Switch", "DSP1RXL" },
+       { "DAC1L Mixer", "Right Sidetone Switch", "Right Sidetone" },
+       { "DAC1L Mixer", "Left Sidetone Switch", "Left Sidetone" },
+
+       { "DAC1R Mixer", "DSP2 Switch", "DSP2RXR" },
+       { "DAC1R Mixer", "DSP1 Switch", "DSP1RXR" },
+       { "DAC1R Mixer", "Right Sidetone Switch", "Right Sidetone" },
+       { "DAC1R Mixer", "Left Sidetone Switch", "Left Sidetone" },
+
+       { "DAC1L", NULL, "DAC1L Mixer" },
+       { "DAC1R", NULL, "DAC1R Mixer" },
+       { "DAC2L", NULL, "DAC2L Mixer" },
+       { "DAC2R", NULL, "DAC2R Mixer" },
+
+       { "HPOUT2L PGA", NULL, "Charge Pump" },
+       { "HPOUT2L PGA", NULL, "DAC2L" },
+       { "HPOUT2L_DLY", NULL, "HPOUT2L PGA" },
+       { "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" },
+       { "HPOUT2L_OUTP", NULL, "HPOUT2L_DCS" },
+       { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" },
+
+       { "HPOUT2R PGA", NULL, "Charge Pump" },
+       { "HPOUT2R PGA", NULL, "DAC2R" },
+       { "HPOUT2R_DLY", NULL, "HPOUT2R PGA" },
+       { "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" },
+       { "HPOUT2R_OUTP", NULL, "HPOUT2R_DCS" },
+       { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" },
+
+       { "HPOUT1L PGA", NULL, "Charge Pump" },
+       { "HPOUT1L PGA", NULL, "DAC1L" },
+       { "HPOUT1L_DLY", NULL, "HPOUT1L PGA" },
+       { "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" },
+       { "HPOUT1L_OUTP", NULL, "HPOUT1L_DCS" },
+       { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" },
+
+       { "HPOUT1R PGA", NULL, "Charge Pump" },
+       { "HPOUT1R PGA", NULL, "DAC1R" },
+       { "HPOUT1R_DLY", NULL, "HPOUT1R PGA" },
+       { "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" },
+       { "HPOUT1R_OUTP", NULL, "HPOUT1R_DCS" },
+       { "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_OUTP" },
+
+       { "HPOUT2L", NULL, "HPOUT2L_RMV_SHORT" },
+       { "HPOUT2R", NULL, "HPOUT2R_RMV_SHORT" },
+       { "HPOUT1L", NULL, "HPOUT1L_RMV_SHORT" },
+       { "HPOUT1R", NULL, "HPOUT1R_RMV_SHORT" },
+
+       { "SPKL", "DAC1L", "DAC1L" },
+       { "SPKL", "DAC1R", "DAC1R" },
+       { "SPKL", "DAC2L", "DAC2L" },
+       { "SPKL", "DAC2R", "DAC2R" },
+
+       { "SPKR", "DAC1L", "DAC1L" },
+       { "SPKR", "DAC1R", "DAC1R" },
+       { "SPKR", "DAC2L", "DAC2L" },
+       { "SPKR", "DAC2R", "DAC2R" },
+
+       { "SPKL PGA", NULL, "SPKL" },
+       { "SPKR PGA", NULL, "SPKR" },
+
+       { "SPKDAT", NULL, "SPKL PGA" },
+       { "SPKDAT", NULL, "SPKR PGA" },
+};
+
+static int wm8996_readable_register(struct snd_soc_codec *codec,
+                                   unsigned int reg)
+{
+       /* Due to the sparseness of the register map the compiler
+        * output from an explicit switch statement ends up being much
+        * more efficient than a table.
+        */
+       switch (reg) {
+       case WM8996_SOFTWARE_RESET:
+       case WM8996_POWER_MANAGEMENT_1:
+       case WM8996_POWER_MANAGEMENT_2:
+       case WM8996_POWER_MANAGEMENT_3:
+       case WM8996_POWER_MANAGEMENT_4:
+       case WM8996_POWER_MANAGEMENT_5:
+       case WM8996_POWER_MANAGEMENT_6:
+       case WM8996_POWER_MANAGEMENT_7:
+       case WM8996_POWER_MANAGEMENT_8:
+       case WM8996_LEFT_LINE_INPUT_VOLUME:
+       case WM8996_RIGHT_LINE_INPUT_VOLUME:
+       case WM8996_LINE_INPUT_CONTROL:
+       case WM8996_DAC1_HPOUT1_VOLUME:
+       case WM8996_DAC2_HPOUT2_VOLUME:
+       case WM8996_DAC1_LEFT_VOLUME:
+       case WM8996_DAC1_RIGHT_VOLUME:
+       case WM8996_DAC2_LEFT_VOLUME:
+       case WM8996_DAC2_RIGHT_VOLUME:
+       case WM8996_OUTPUT1_LEFT_VOLUME:
+       case WM8996_OUTPUT1_RIGHT_VOLUME:
+       case WM8996_OUTPUT2_LEFT_VOLUME:
+       case WM8996_OUTPUT2_RIGHT_VOLUME:
+       case WM8996_MICBIAS_1:
+       case WM8996_MICBIAS_2:
+       case WM8996_LDO_1:
+       case WM8996_LDO_2:
+       case WM8996_ACCESSORY_DETECT_MODE_1:
+       case WM8996_ACCESSORY_DETECT_MODE_2:
+       case WM8996_HEADPHONE_DETECT_1:
+       case WM8996_HEADPHONE_DETECT_2:
+       case WM8996_MIC_DETECT_1:
+       case WM8996_MIC_DETECT_2:
+       case WM8996_MIC_DETECT_3:
+       case WM8996_CHARGE_PUMP_1:
+       case WM8996_CHARGE_PUMP_2:
+       case WM8996_DC_SERVO_1:
+       case WM8996_DC_SERVO_2:
+       case WM8996_DC_SERVO_3:
+       case WM8996_DC_SERVO_5:
+       case WM8996_DC_SERVO_6:
+       case WM8996_DC_SERVO_7:
+       case WM8996_DC_SERVO_READBACK_0:
+       case WM8996_ANALOGUE_HP_1:
+       case WM8996_ANALOGUE_HP_2:
+       case WM8996_CHIP_REVISION:
+       case WM8996_CONTROL_INTERFACE_1:
+       case WM8996_WRITE_SEQUENCER_CTRL_1:
+       case WM8996_WRITE_SEQUENCER_CTRL_2:
+       case WM8996_AIF_CLOCKING_1:
+       case WM8996_AIF_CLOCKING_2:
+       case WM8996_CLOCKING_1:
+       case WM8996_CLOCKING_2:
+       case WM8996_AIF_RATE:
+       case WM8996_FLL_CONTROL_1:
+       case WM8996_FLL_CONTROL_2:
+       case WM8996_FLL_CONTROL_3:
+       case WM8996_FLL_CONTROL_4:
+       case WM8996_FLL_CONTROL_5:
+       case WM8996_FLL_CONTROL_6:
+       case WM8996_FLL_EFS_1:
+       case WM8996_FLL_EFS_2:
+       case WM8996_AIF1_CONTROL:
+       case WM8996_AIF1_BCLK:
+       case WM8996_AIF1_TX_LRCLK_1:
+       case WM8996_AIF1_TX_LRCLK_2:
+       case WM8996_AIF1_RX_LRCLK_1:
+       case WM8996_AIF1_RX_LRCLK_2:
+       case WM8996_AIF1TX_DATA_CONFIGURATION_1:
+       case WM8996_AIF1TX_DATA_CONFIGURATION_2:
+       case WM8996_AIF1RX_DATA_CONFIGURATION:
+       case WM8996_AIF1TX_CHANNEL_0_CONFIGURATION:
+       case WM8996_AIF1TX_CHANNEL_1_CONFIGURATION:
+       case WM8996_AIF1TX_CHANNEL_2_CONFIGURATION:
+       case WM8996_AIF1TX_CHANNEL_3_CONFIGURATION:
+       case WM8996_AIF1TX_CHANNEL_4_CONFIGURATION:
+       case WM8996_AIF1TX_CHANNEL_5_CONFIGURATION:
+       case WM8996_AIF1RX_CHANNEL_0_CONFIGURATION:
+       case WM8996_AIF1RX_CHANNEL_1_CONFIGURATION:
+       case WM8996_AIF1RX_CHANNEL_2_CONFIGURATION:
+       case WM8996_AIF1RX_CHANNEL_3_CONFIGURATION:
+       case WM8996_AIF1RX_CHANNEL_4_CONFIGURATION:
+       case WM8996_AIF1RX_CHANNEL_5_CONFIGURATION:
+       case WM8996_AIF1RX_MONO_CONFIGURATION:
+       case WM8996_AIF1TX_TEST:
+       case WM8996_AIF2_CONTROL:
+       case WM8996_AIF2_BCLK:
+       case WM8996_AIF2_TX_LRCLK_1:
+       case WM8996_AIF2_TX_LRCLK_2:
+       case WM8996_AIF2_RX_LRCLK_1:
+       case WM8996_AIF2_RX_LRCLK_2:
+       case WM8996_AIF2TX_DATA_CONFIGURATION_1:
+       case WM8996_AIF2TX_DATA_CONFIGURATION_2:
+       case WM8996_AIF2RX_DATA_CONFIGURATION:
+       case WM8996_AIF2TX_CHANNEL_0_CONFIGURATION:
+       case WM8996_AIF2TX_CHANNEL_1_CONFIGURATION:
+       case WM8996_AIF2RX_CHANNEL_0_CONFIGURATION:
+       case WM8996_AIF2RX_CHANNEL_1_CONFIGURATION:
+       case WM8996_AIF2RX_MONO_CONFIGURATION:
+       case WM8996_AIF2TX_TEST:
+       case WM8996_DSP1_TX_LEFT_VOLUME:
+       case WM8996_DSP1_TX_RIGHT_VOLUME:
+       case WM8996_DSP1_RX_LEFT_VOLUME:
+       case WM8996_DSP1_RX_RIGHT_VOLUME:
+       case WM8996_DSP1_TX_FILTERS:
+       case WM8996_DSP1_RX_FILTERS_1:
+       case WM8996_DSP1_RX_FILTERS_2:
+       case WM8996_DSP1_DRC_1:
+       case WM8996_DSP1_DRC_2:
+       case WM8996_DSP1_DRC_3:
+       case WM8996_DSP1_DRC_4:
+       case WM8996_DSP1_DRC_5:
+       case WM8996_DSP1_RX_EQ_GAINS_1:
+       case WM8996_DSP1_RX_EQ_GAINS_2:
+       case WM8996_DSP1_RX_EQ_BAND_1_A:
+       case WM8996_DSP1_RX_EQ_BAND_1_B:
+       case WM8996_DSP1_RX_EQ_BAND_1_PG:
+       case WM8996_DSP1_RX_EQ_BAND_2_A:
+       case WM8996_DSP1_RX_EQ_BAND_2_B:
+       case WM8996_DSP1_RX_EQ_BAND_2_C:
+       case WM8996_DSP1_RX_EQ_BAND_2_PG:
+       case WM8996_DSP1_RX_EQ_BAND_3_A:
+       case WM8996_DSP1_RX_EQ_BAND_3_B:
+       case WM8996_DSP1_RX_EQ_BAND_3_C:
+       case WM8996_DSP1_RX_EQ_BAND_3_PG:
+       case WM8996_DSP1_RX_EQ_BAND_4_A:
+       case WM8996_DSP1_RX_EQ_BAND_4_B:
+       case WM8996_DSP1_RX_EQ_BAND_4_C:
+       case WM8996_DSP1_RX_EQ_BAND_4_PG:
+       case WM8996_DSP1_RX_EQ_BAND_5_A:
+       case WM8996_DSP1_RX_EQ_BAND_5_B:
+       case WM8996_DSP1_RX_EQ_BAND_5_PG:
+       case WM8996_DSP2_TX_LEFT_VOLUME:
+       case WM8996_DSP2_TX_RIGHT_VOLUME:
+       case WM8996_DSP2_RX_LEFT_VOLUME:
+       case WM8996_DSP2_RX_RIGHT_VOLUME:
+       case WM8996_DSP2_TX_FILTERS:
+       case WM8996_DSP2_RX_FILTERS_1:
+       case WM8996_DSP2_RX_FILTERS_2:
+       case WM8996_DSP2_DRC_1:
+       case WM8996_DSP2_DRC_2:
+       case WM8996_DSP2_DRC_3:
+       case WM8996_DSP2_DRC_4:
+       case WM8996_DSP2_DRC_5:
+       case WM8996_DSP2_RX_EQ_GAINS_1:
+       case WM8996_DSP2_RX_EQ_GAINS_2:
+       case WM8996_DSP2_RX_EQ_BAND_1_A:
+       case WM8996_DSP2_RX_EQ_BAND_1_B:
+       case WM8996_DSP2_RX_EQ_BAND_1_PG:
+       case WM8996_DSP2_RX_EQ_BAND_2_A:
+       case WM8996_DSP2_RX_EQ_BAND_2_B:
+       case WM8996_DSP2_RX_EQ_BAND_2_C:
+       case WM8996_DSP2_RX_EQ_BAND_2_PG:
+       case WM8996_DSP2_RX_EQ_BAND_3_A:
+       case WM8996_DSP2_RX_EQ_BAND_3_B:
+       case WM8996_DSP2_RX_EQ_BAND_3_C:
+       case WM8996_DSP2_RX_EQ_BAND_3_PG:
+       case WM8996_DSP2_RX_EQ_BAND_4_A:
+       case WM8996_DSP2_RX_EQ_BAND_4_B:
+       case WM8996_DSP2_RX_EQ_BAND_4_C:
+       case WM8996_DSP2_RX_EQ_BAND_4_PG:
+       case WM8996_DSP2_RX_EQ_BAND_5_A:
+       case WM8996_DSP2_RX_EQ_BAND_5_B:
+       case WM8996_DSP2_RX_EQ_BAND_5_PG:
+       case WM8996_DAC1_MIXER_VOLUMES:
+       case WM8996_DAC1_LEFT_MIXER_ROUTING:
+       case WM8996_DAC1_RIGHT_MIXER_ROUTING:
+       case WM8996_DAC2_MIXER_VOLUMES:
+       case WM8996_DAC2_LEFT_MIXER_ROUTING:
+       case WM8996_DAC2_RIGHT_MIXER_ROUTING:
+       case WM8996_DSP1_TX_LEFT_MIXER_ROUTING:
+       case WM8996_DSP1_TX_RIGHT_MIXER_ROUTING:
+       case WM8996_DSP2_TX_LEFT_MIXER_ROUTING:
+       case WM8996_DSP2_TX_RIGHT_MIXER_ROUTING:
+       case WM8996_DSP_TX_MIXER_SELECT:
+       case WM8996_DAC_SOFTMUTE:
+       case WM8996_OVERSAMPLING:
+       case WM8996_SIDETONE:
+       case WM8996_GPIO_1:
+       case WM8996_GPIO_2:
+       case WM8996_GPIO_3:
+       case WM8996_GPIO_4:
+       case WM8996_GPIO_5:
+       case WM8996_PULL_CONTROL_1:
+       case WM8996_PULL_CONTROL_2:
+       case WM8996_INTERRUPT_STATUS_1:
+       case WM8996_INTERRUPT_STATUS_2:
+       case WM8996_INTERRUPT_RAW_STATUS_2:
+       case WM8996_INTERRUPT_STATUS_1_MASK:
+       case WM8996_INTERRUPT_STATUS_2_MASK:
+       case WM8996_INTERRUPT_CONTROL:
+       case WM8996_LEFT_PDM_SPEAKER:
+       case WM8996_RIGHT_PDM_SPEAKER:
+       case WM8996_PDM_SPEAKER_MUTE_SEQUENCE:
+       case WM8996_PDM_SPEAKER_VOLUME:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static int wm8996_volatile_register(struct snd_soc_codec *codec,
+                                   unsigned int reg)
+{
+       switch (reg) {
+       case WM8996_SOFTWARE_RESET:
+       case WM8996_CHIP_REVISION:
+       case WM8996_LDO_1:
+       case WM8996_LDO_2:
+       case WM8996_INTERRUPT_STATUS_1:
+       case WM8996_INTERRUPT_STATUS_2:
+       case WM8996_INTERRUPT_RAW_STATUS_2:
+       case WM8996_DC_SERVO_READBACK_0:
+       case WM8996_DC_SERVO_2:
+       case WM8996_DC_SERVO_6:
+       case WM8996_DC_SERVO_7:
+       case WM8996_FLL_CONTROL_6:
+       case WM8996_MIC_DETECT_3:
+       case WM8996_HEADPHONE_DETECT_1:
+       case WM8996_HEADPHONE_DETECT_2:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static int wm8996_reset(struct snd_soc_codec *codec)
+{
+       return snd_soc_write(codec, WM8996_SOFTWARE_RESET, 0x8915);
+}
+
+static const int bclk_divs[] = {
+       1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96
+};
+
+static void wm8996_update_bclk(struct snd_soc_codec *codec)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       int aif, best, cur_val, bclk_rate, bclk_reg, i;
+
+       /* Don't bother if we're in a low frequency idle mode that
+        * can't support audio.
+        */
+       if (wm8996->sysclk < 64000)
+               return;
+
+       for (aif = 0; aif < WM8996_AIFS; aif++) {
+               switch (aif) {
+               case 0:
+                       bclk_reg = WM8996_AIF1_BCLK;
+                       break;
+               case 1:
+                       bclk_reg = WM8996_AIF2_BCLK;
+                       break;
+               }
+
+               bclk_rate = wm8996->bclk_rate[aif];
+
+               /* Pick a divisor for BCLK as close as we can get to ideal */
+               best = 0;
+               for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
+                       cur_val = (wm8996->sysclk / bclk_divs[i]) - bclk_rate;
+                       if (cur_val < 0) /* BCLK table is sorted */
+                               break;
+                       best = i;
+               }
+               bclk_rate = wm8996->sysclk / bclk_divs[best];
+               dev_dbg(codec->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n",
+                       bclk_divs[best], bclk_rate);
+
+               snd_soc_update_bits(codec, bclk_reg,
+                                   WM8996_AIF1_BCLK_DIV_MASK, best);
+       }
+}
+
+static int wm8996_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+
+       case SND_SOC_BIAS_PREPARE:
+               if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
+                       snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1,
+                                           WM8996_BG_ENA, WM8996_BG_ENA);
+                       msleep(2);
+               }
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
+                                                   wm8996->supplies);
+                       if (ret != 0) {
+                               dev_err(codec->dev,
+                                       "Failed to enable supplies: %d\n",
+                                       ret);
+                               return ret;
+                       }
+
+                       if (wm8996->pdata.ldo_ena >= 0) {
+                               gpio_set_value_cansleep(wm8996->pdata.ldo_ena,
+                                                       1);
+                               msleep(5);
+                       }
+
+                       codec->cache_only = false;
+                       snd_soc_cache_sync(codec);
+               }
+
+               snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1,
+                                   WM8996_BG_ENA, 0);
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               codec->cache_only = true;
+               if (wm8996->pdata.ldo_ena >= 0)
+                       gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+               regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies),
+                                      wm8996->supplies);
+               break;
+       }
+
+       codec->dapm.bias_level = level;
+
+       return 0;
+}
+
+static int wm8996_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       int aifctrl = 0;
+       int bclk = 0;
+       int lrclk_tx = 0;
+       int lrclk_rx = 0;
+       int aifctrl_reg, bclk_reg, lrclk_tx_reg, lrclk_rx_reg;
+
+       switch (dai->id) {
+       case 0:
+               aifctrl_reg = WM8996_AIF1_CONTROL;
+               bclk_reg = WM8996_AIF1_BCLK;
+               lrclk_tx_reg = WM8996_AIF1_TX_LRCLK_2;
+               lrclk_rx_reg = WM8996_AIF1_RX_LRCLK_2;
+               break;
+       case 1:
+               aifctrl_reg = WM8996_AIF2_CONTROL;
+               bclk_reg = WM8996_AIF2_BCLK;
+               lrclk_tx_reg = WM8996_AIF2_TX_LRCLK_2;
+               lrclk_rx_reg = WM8996_AIF2_RX_LRCLK_2;
+               break;
+       default:
+               BUG();
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               bclk |= WM8996_AIF1_BCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               lrclk_tx |= WM8996_AIF1TX_LRCLK_INV;
+               lrclk_rx |= WM8996_AIF1RX_LRCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               bclk |= WM8996_AIF1_BCLK_INV;
+               lrclk_tx |= WM8996_AIF1TX_LRCLK_INV;
+               lrclk_rx |= WM8996_AIF1RX_LRCLK_INV;
+               break;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       case SND_SOC_DAIFMT_CBS_CFM:
+               lrclk_tx |= WM8996_AIF1TX_LRCLK_MSTR;
+               lrclk_rx |= WM8996_AIF1RX_LRCLK_MSTR;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS:
+               bclk |= WM8996_AIF1_BCLK_MSTR;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               bclk |= WM8996_AIF1_BCLK_MSTR;
+               lrclk_tx |= WM8996_AIF1TX_LRCLK_MSTR;
+               lrclk_rx |= WM8996_AIF1RX_LRCLK_MSTR;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               aifctrl |= 1;
+               break;
+       case SND_SOC_DAIFMT_I2S:
+               aifctrl |= 2;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               aifctrl |= 3;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, aifctrl_reg, WM8996_AIF1_FMT_MASK, aifctrl);
+       snd_soc_update_bits(codec, bclk_reg,
+                           WM8996_AIF1_BCLK_INV | WM8996_AIF1_BCLK_MSTR,
+                           bclk);
+       snd_soc_update_bits(codec, lrclk_tx_reg,
+                           WM8996_AIF1TX_LRCLK_INV |
+                           WM8996_AIF1TX_LRCLK_MSTR,
+                           lrclk_tx);
+       snd_soc_update_bits(codec, lrclk_rx_reg,
+                           WM8996_AIF1RX_LRCLK_INV |
+                           WM8996_AIF1RX_LRCLK_MSTR,
+                           lrclk_rx);
+
+       return 0;
+}
+
+static const int dsp_divs[] = {
+       48000, 32000, 16000, 8000
+};
+
+static int wm8996_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       int bits, i, bclk_rate;
+       int aifdata = 0;
+       int lrclk = 0;
+       int dsp = 0;
+       int aifdata_reg, lrclk_reg, dsp_shift;
+
+       switch (dai->id) {
+       case 0:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+                   (snd_soc_read(codec, WM8996_GPIO_1)) & WM8996_GP1_FN_MASK) {
+                       aifdata_reg = WM8996_AIF1RX_DATA_CONFIGURATION;
+                       lrclk_reg = WM8996_AIF1_RX_LRCLK_1;
+               } else {
+                       aifdata_reg = WM8996_AIF1TX_DATA_CONFIGURATION_1;
+                       lrclk_reg = WM8996_AIF1_TX_LRCLK_1;
+               }
+               dsp_shift = 0;
+               break;
+       case 1:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+                   (snd_soc_read(codec, WM8996_GPIO_2)) & WM8996_GP2_FN_MASK) {
+                       aifdata_reg = WM8996_AIF2RX_DATA_CONFIGURATION;
+                       lrclk_reg = WM8996_AIF2_RX_LRCLK_1;
+               } else {
+                       aifdata_reg = WM8996_AIF2TX_DATA_CONFIGURATION_1;
+                       lrclk_reg = WM8996_AIF2_TX_LRCLK_1;
+               }
+               dsp_shift = WM8996_DSP2_DIV_SHIFT;
+               break;
+       default:
+               BUG();
+               return -EINVAL;
+       }
+
+       bclk_rate = snd_soc_params_to_bclk(params);
+       if (bclk_rate < 0) {
+               dev_err(codec->dev, "Unsupported BCLK rate: %d\n", bclk_rate);
+               return bclk_rate;
+       }
+
+       wm8996->bclk_rate[dai->id] = bclk_rate;
+       wm8996->rx_rate[dai->id] = params_rate(params);
+
+       /* Needs looking at for TDM */
+       bits = snd_pcm_format_width(params_format(params));
+       if (bits < 0)
+               return bits;
+       aifdata |= (bits << WM8996_AIF1TX_WL_SHIFT) | bits;
+
+       for (i = 0; i < ARRAY_SIZE(dsp_divs); i++) {
+               if (dsp_divs[i] == params_rate(params))
+                       break;
+       }
+       if (i == ARRAY_SIZE(dsp_divs)) {
+               dev_err(codec->dev, "Unsupported sample rate %dHz\n",
+                       params_rate(params));
+               return -EINVAL;
+       }
+       dsp |= i << dsp_shift;
+
+       wm8996_update_bclk(codec);
+
+       lrclk = bclk_rate / params_rate(params);
+       dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n",
+               lrclk, bclk_rate / lrclk);
+
+       snd_soc_update_bits(codec, aifdata_reg,
+                           WM8996_AIF1TX_WL_MASK |
+                           WM8996_AIF1TX_SLOT_LEN_MASK,
+                           aifdata);
+       snd_soc_update_bits(codec, lrclk_reg, WM8996_AIF1RX_RATE_MASK,
+                           lrclk);
+       snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_2,
+                           WM8996_DSP1_DIV_SHIFT << dsp_shift, dsp);
+
+       return 0;
+}
+
+static int wm8996_set_sysclk(struct snd_soc_dai *dai,
+               int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       int lfclk = 0;
+       int ratediv = 0;
+       int src;
+       int old;
+
+       if (freq == wm8996->sysclk && clk_id == wm8996->sysclk_src)
+               return 0;
+
+       /* Disable SYSCLK while we reconfigure */
+       old = snd_soc_read(codec, WM8996_AIF_CLOCKING_1) & WM8996_SYSCLK_ENA;
+       snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1,
+                           WM8996_SYSCLK_ENA, 0);
+
+       switch (clk_id) {
+       case WM8996_SYSCLK_MCLK1:
+               wm8996->sysclk = freq;
+               src = 0;
+               break;
+       case WM8996_SYSCLK_MCLK2:
+               wm8996->sysclk = freq;
+               src = 1;
+               break;
+       case WM8996_SYSCLK_FLL:
+               wm8996->sysclk = freq;
+               src = 2;
+               break;
+       default:
+               dev_err(codec->dev, "Unsupported clock source %d\n", clk_id);
+               return -EINVAL;
+       }
+
+       switch (wm8996->sysclk) {
+       case 6144000:
+               snd_soc_update_bits(codec, WM8996_AIF_RATE,
+                                   WM8996_SYSCLK_RATE, 0);
+               break;
+       case 24576000:
+               ratediv = WM8996_SYSCLK_DIV;
+       case 12288000:
+               snd_soc_update_bits(codec, WM8996_AIF_RATE,
+                                   WM8996_SYSCLK_RATE, WM8996_SYSCLK_RATE);
+               break;
+       case 32000:
+       case 32768:
+               lfclk = WM8996_LFCLK_ENA;
+               break;
+       default:
+               dev_warn(codec->dev, "Unsupported clock rate %dHz\n",
+                        wm8996->sysclk);
+               return -EINVAL;
+       }
+
+       wm8996_update_bclk(codec);
+
+       snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1,
+                           WM8996_SYSCLK_SRC_MASK | WM8996_SYSCLK_DIV_MASK,
+                           src << WM8996_SYSCLK_SRC_SHIFT | ratediv);
+       snd_soc_update_bits(codec, WM8996_CLOCKING_1, WM8996_LFCLK_ENA, lfclk);
+       snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1,
+                           WM8996_SYSCLK_ENA, old);
+
+       wm8996->sysclk_src = clk_id;
+
+       return 0;
+}
+
+struct _fll_div {
+       u16 fll_fratio;
+       u16 fll_outdiv;
+       u16 fll_refclk_div;
+       u16 fll_loop_gain;
+       u16 fll_ref_freq;
+       u16 n;
+       u16 theta;
+       u16 lambda;
+};
+
+static struct {
+       unsigned int min;
+       unsigned int max;
+       u16 fll_fratio;
+       int ratio;
+} fll_fratios[] = {
+       {       0,    64000, 4, 16 },
+       {   64000,   128000, 3,  8 },
+       {  128000,   256000, 2,  4 },
+       {  256000,  1000000, 1,  2 },
+       { 1000000, 13500000, 0,  1 },
+};
+
+static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
+                      unsigned int Fout)
+{
+       unsigned int target;
+       unsigned int div;
+       unsigned int fratio, gcd_fll;
+       int i;
+
+       /* Fref must be <=13.5MHz */
+       div = 1;
+       fll_div->fll_refclk_div = 0;
+       while ((Fref / div) > 13500000) {
+               div *= 2;
+               fll_div->fll_refclk_div++;
+
+               if (div > 8) {
+                       pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
+                              Fref);
+                       return -EINVAL;
+               }
+       }
+
+       pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
+
+       /* Apply the division for our remaining calculations */
+       Fref /= div;
+
+       if (Fref >= 3000000)
+               fll_div->fll_loop_gain = 5;
+       else
+               fll_div->fll_loop_gain = 0;
+
+       if (Fref >= 48000)
+               fll_div->fll_ref_freq = 0;
+       else
+               fll_div->fll_ref_freq = 1;
+
+       /* Fvco should be 90-100MHz; don't check the upper bound */
+       div = 2;
+       while (Fout * div < 90000000) {
+               div++;
+               if (div > 64) {
+                       pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
+                              Fout);
+                       return -EINVAL;
+               }
+       }
+       target = Fout * div;
+       fll_div->fll_outdiv = div - 1;
+
+       pr_debug("FLL Fvco=%dHz\n", target);
+
+       /* Find an appropraite FLL_FRATIO and factor it out of the target */
+       for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
+               if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
+                       fll_div->fll_fratio = fll_fratios[i].fll_fratio;
+                       fratio = fll_fratios[i].ratio;
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(fll_fratios)) {
+               pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
+               return -EINVAL;
+       }
+
+       fll_div->n = target / (fratio * Fref);
+
+       if (target % Fref == 0) {
+               fll_div->theta = 0;
+               fll_div->lambda = 0;
+       } else {
+               gcd_fll = gcd(target, fratio * Fref);
+
+               fll_div->theta = (target - (fll_div->n * fratio * Fref))
+                       / gcd_fll;
+               fll_div->lambda = (fratio * Fref) / gcd_fll;
+       }
+
+       pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
+                fll_div->n, fll_div->theta, fll_div->lambda);
+       pr_debug("FLL_FRATIO=%x FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
+                fll_div->fll_fratio, fll_div->fll_outdiv,
+                fll_div->fll_refclk_div);
+
+       return 0;
+}
+
+static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+                         unsigned int Fref, unsigned int Fout)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       struct i2c_client *i2c = to_i2c_client(codec->dev);
+       struct _fll_div fll_div;
+       unsigned long timeout;
+       int ret, reg;
+
+       /* Any change? */
+       if (source == wm8996->fll_src && Fref == wm8996->fll_fref &&
+           Fout == wm8996->fll_fout)
+               return 0;
+
+       if (Fout == 0) {
+               dev_dbg(codec->dev, "FLL disabled\n");
+
+               wm8996->fll_fref = 0;
+               wm8996->fll_fout = 0;
+
+               snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1,
+                                   WM8996_FLL_ENA, 0);
+
+               return 0;
+       }
+
+       ret = fll_factors(&fll_div, Fref, Fout);
+       if (ret != 0)
+               return ret;
+
+       switch (source) {
+       case WM8996_FLL_MCLK1:
+               reg = 0;
+               break;
+       case WM8996_FLL_MCLK2:
+               reg = 1;
+               break;
+       case WM8996_FLL_DACLRCLK1:
+               reg = 2;
+               break;
+       case WM8996_FLL_BCLK1:
+               reg = 3;
+               break;
+       default:
+               dev_err(codec->dev, "Unknown FLL source %d\n", ret);
+               return -EINVAL;
+       }
+
+       reg |= fll_div.fll_refclk_div << WM8996_FLL_REFCLK_DIV_SHIFT;
+       reg |= fll_div.fll_ref_freq << WM8996_FLL_REF_FREQ_SHIFT;
+
+       snd_soc_update_bits(codec, WM8996_FLL_CONTROL_5,
+                           WM8996_FLL_REFCLK_DIV_MASK | WM8996_FLL_REF_FREQ |
+                           WM8996_FLL_REFCLK_SRC_MASK, reg);
+
+       reg = 0;
+       if (fll_div.theta || fll_div.lambda)
+               reg |= WM8996_FLL_EFS_ENA | (3 << WM8996_FLL_LFSR_SEL_SHIFT);
+       else
+               reg |= 1 << WM8996_FLL_LFSR_SEL_SHIFT;
+       snd_soc_write(codec, WM8996_FLL_EFS_2, reg);
+
+       snd_soc_update_bits(codec, WM8996_FLL_CONTROL_2,
+                           WM8996_FLL_OUTDIV_MASK |
+                           WM8996_FLL_FRATIO_MASK,
+                           (fll_div.fll_outdiv << WM8996_FLL_OUTDIV_SHIFT) |
+                           (fll_div.fll_fratio));
+
+       snd_soc_write(codec, WM8996_FLL_CONTROL_3, fll_div.theta);
+
+       snd_soc_update_bits(codec, WM8996_FLL_CONTROL_4,
+                           WM8996_FLL_N_MASK | WM8996_FLL_LOOP_GAIN_MASK,
+                           (fll_div.n << WM8996_FLL_N_SHIFT) |
+                           fll_div.fll_loop_gain);
+
+       snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda);
+
+       snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1,
+                           WM8996_FLL_ENA, WM8996_FLL_ENA);
+
+       /* The FLL supports live reconfiguration - kick that in case we were
+        * already enabled.
+        */
+       snd_soc_write(codec, WM8996_FLL_CONTROL_6, WM8996_FLL_SWITCH_CLK);
+
+       /* Wait for the FLL to lock, using the interrupt if possible */
+       if (Fref > 1000000)
+               timeout = usecs_to_jiffies(300);
+       else
+               timeout = msecs_to_jiffies(2);
+
+       /* Allow substantially longer if we've actually got the IRQ */
+       if (i2c->irq)
+               timeout *= 1000;
+
+       ret = wait_for_completion_timeout(&wm8996->fll_lock, timeout);
+
+       if (ret == 0 && i2c->irq) {
+               dev_err(codec->dev, "Timed out waiting for FLL\n");
+               ret = -ETIMEDOUT;
+       } else {
+               ret = 0;
+       }
+
+       dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
+
+       wm8996->fll_fref = Fref;
+       wm8996->fll_fout = Fout;
+       wm8996->fll_src = source;
+
+       return ret;
+}
+
+#ifdef CONFIG_GPIOLIB
+static inline struct wm8996_priv *gpio_to_wm8996(struct gpio_chip *chip)
+{
+       return container_of(chip, struct wm8996_priv, gpio_chip);
+}
+
+static void wm8996_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
+       struct snd_soc_codec *codec = wm8996->codec;
+
+       snd_soc_update_bits(codec, WM8996_GPIO_1 + offset,
+                           WM8996_GP1_LVL, !!value << WM8996_GP1_LVL_SHIFT);
+}
+
+static int wm8996_gpio_direction_out(struct gpio_chip *chip,
+                                    unsigned offset, int value)
+{
+       struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
+       struct snd_soc_codec *codec = wm8996->codec;
+       int val;
+
+       val = (1 << WM8996_GP1_FN_SHIFT) | (!!value << WM8996_GP1_LVL_SHIFT);
+
+       return snd_soc_update_bits(codec, WM8996_GPIO_1 + offset,
+                                  WM8996_GP1_FN_MASK | WM8996_GP1_DIR |
+                                  WM8996_GP1_LVL, val);
+}
+
+static int wm8996_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
+       struct snd_soc_codec *codec = wm8996->codec;
+       int ret;
+
+       ret = snd_soc_read(codec, WM8996_GPIO_1 + offset);
+       if (ret < 0)
+               return ret;
+
+       return (ret & WM8996_GP1_LVL) != 0;
+}
+
+static int wm8996_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
+       struct snd_soc_codec *codec = wm8996->codec;
+
+       return snd_soc_update_bits(codec, WM8996_GPIO_1 + offset,
+                                  WM8996_GP1_FN_MASK | WM8996_GP1_DIR,
+                                  (1 << WM8996_GP1_FN_SHIFT) |
+                                  (1 << WM8996_GP1_DIR_SHIFT));
+}
+
+static struct gpio_chip wm8996_template_chip = {
+       .label                  = "wm8996",
+       .owner                  = THIS_MODULE,
+       .direction_output       = wm8996_gpio_direction_out,
+       .set                    = wm8996_gpio_set,
+       .direction_input        = wm8996_gpio_direction_in,
+       .get                    = wm8996_gpio_get,
+       .can_sleep              = 1,
+};
+
+static void wm8996_init_gpio(struct snd_soc_codec *codec)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       wm8996->gpio_chip = wm8996_template_chip;
+       wm8996->gpio_chip.ngpio = 5;
+       wm8996->gpio_chip.dev = codec->dev;
+
+       if (wm8996->pdata.gpio_base)
+               wm8996->gpio_chip.base = wm8996->pdata.gpio_base;
+       else
+               wm8996->gpio_chip.base = -1;
+
+       ret = gpiochip_add(&wm8996->gpio_chip);
+       if (ret != 0)
+               dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+}
+
+static void wm8996_free_gpio(struct snd_soc_codec *codec)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       ret = gpiochip_remove(&wm8996->gpio_chip);
+       if (ret != 0)
+               dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+}
+#else
+static void wm8996_init_gpio(struct snd_soc_codec *codec)
+{
+}
+
+static void wm8996_free_gpio(struct snd_soc_codec *codec)
+{
+}
+#endif
+
+/**
+ * wm8996_detect - Enable default WM8996 jack detection
+ *
+ * The WM8996 has advanced accessory detection support for headsets.
+ * This function provides a default implementation which integrates
+ * the majority of this functionality with minimal user configuration.
+ *
+ * This will detect headset, headphone and short circuit button and
+ * will also detect inverted microphone ground connections and update
+ * the polarity of the connections.
+ */
+int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
+                 wm8996_polarity_fn polarity_cb)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+
+       wm8996->jack = jack;
+       wm8996->detecting = true;
+       wm8996->polarity_cb = polarity_cb;
+
+       if (wm8996->polarity_cb)
+               wm8996->polarity_cb(codec, 0);
+
+       /* Clear discarge to avoid noise during detection */
+       snd_soc_update_bits(codec, WM8996_MICBIAS_1,
+                           WM8996_MICB1_DISCH, 0);
+       snd_soc_update_bits(codec, WM8996_MICBIAS_2,
+                           WM8996_MICB2_DISCH, 0);
+
+       /* LDO2 powers the microphones, SYSCLK clocks detection */
+       snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2");
+       snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
+
+       /* We start off just enabling microphone detection - even a
+        * plain headphone will trigger detection.
+        */
+       snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+                           WM8996_MICD_ENA, WM8996_MICD_ENA);
+
+       /* Slowest detection rate, gives debounce for initial detection */
+       snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+                           WM8996_MICD_RATE_MASK,
+                           WM8996_MICD_RATE_MASK);
+
+       /* Enable interrupts and we're off */
+       snd_soc_update_bits(codec, WM8996_INTERRUPT_STATUS_2_MASK,
+                           WM8996_IM_MICD_EINT, 0);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm8996_detect);
+
+static void wm8996_micd(struct snd_soc_codec *codec)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       int val, reg;
+
+       val = snd_soc_read(codec, WM8996_MIC_DETECT_3);
+
+       dev_dbg(codec->dev, "Microphone event: %x\n", val);
+
+       if (!(val & WM8996_MICD_VALID)) {
+               dev_warn(codec->dev, "Microphone detection state invalid\n");
+               return;
+       }
+
+       /* No accessory, reset everything and report removal */
+       if (!(val & WM8996_MICD_STS)) {
+               dev_dbg(codec->dev, "Jack removal detected\n");
+               wm8996->jack_mic = false;
+               wm8996->detecting = true;
+               snd_soc_jack_report(wm8996->jack, 0,
+                                   SND_JACK_HEADSET | SND_JACK_BTN_0);
+               snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+                                   WM8996_MICD_RATE_MASK,
+                                   WM8996_MICD_RATE_MASK);
+               return;
+       }
+
+       /* If the measurement is very high we've got a microphone but
+        * do a little debounce to account for mechanical issues.
+        */
+       if (val & 0x400) {
+               dev_dbg(codec->dev, "Microphone detected\n");
+               snd_soc_jack_report(wm8996->jack, SND_JACK_HEADSET,
+                                   SND_JACK_HEADSET | SND_JACK_BTN_0);
+               wm8996->jack_mic = true;
+               wm8996->detecting = false;
+
+               /* Increase poll rate to give better responsiveness
+                * for buttons */
+               snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+                                   WM8996_MICD_RATE_MASK,
+                                   5 << WM8996_MICD_RATE_SHIFT);
+       }
+
+       /* If we detected a lower impedence during initial startup
+        * then we probably have the wrong polarity, flip it.  Don't
+        * do this for the lowest impedences to speed up detection of
+        * plain headphones.
+        */
+       if (wm8996->detecting && (val & 0x3f0)) {
+               reg = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2);
+               reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC |
+                       WM8996_MICD_BIAS_SRC;
+               snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_2,
+                                   WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC |
+                                   WM8996_MICD_BIAS_SRC, reg);
+
+               if (wm8996->polarity_cb)
+                       wm8996->polarity_cb(codec,
+                                           (reg & WM8996_MICD_SRC) != 0);
+
+               dev_dbg(codec->dev, "Set microphone polarity to %d\n",
+                       (reg & WM8996_MICD_SRC) != 0);
+
+               return;
+       }
+
+       /* Don't distinguish between buttons, just report any low
+        * impedence as BTN_0.
+        */
+       if (val & 0x3fc) {
+               if (wm8996->jack_mic) {
+                       dev_dbg(codec->dev, "Mic button detected\n");
+                       snd_soc_jack_report(wm8996->jack,
+                                           SND_JACK_HEADSET | SND_JACK_BTN_0,
+                                           SND_JACK_HEADSET | SND_JACK_BTN_0);
+               } else {
+                       dev_dbg(codec->dev, "Headphone detected\n");
+                       snd_soc_jack_report(wm8996->jack,
+                                           SND_JACK_HEADPHONE,
+                                           SND_JACK_HEADSET |
+                                           SND_JACK_BTN_0);
+
+                       /* Increase the detection rate a bit for
+                        * responsiveness.
+                        */
+                       snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+                                           WM8996_MICD_RATE_MASK,
+                                           7 << WM8996_MICD_RATE_SHIFT);
+
+                       wm8996->detecting = false;
+               }
+       }
+}
+
+static irqreturn_t wm8996_irq(int irq, void *data)
+{
+       struct snd_soc_codec *codec = data;
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       int irq_val;
+
+       irq_val = snd_soc_read(codec, WM8996_INTERRUPT_STATUS_2);
+       if (irq_val < 0) {
+               dev_err(codec->dev, "Failed to read IRQ status: %d\n",
+                       irq_val);
+               return IRQ_NONE;
+       }
+       irq_val &= ~snd_soc_read(codec, WM8996_INTERRUPT_STATUS_2_MASK);
+
+       snd_soc_write(codec, WM8996_INTERRUPT_STATUS_2, irq_val);
+
+       if (irq_val & (WM8996_DCS_DONE_01_EINT | WM8996_DCS_DONE_23_EINT)) {
+               dev_dbg(codec->dev, "DC servo IRQ\n");
+               complete(&wm8996->dcs_done);
+       }
+
+       if (irq_val & WM8996_FIFOS_ERR_EINT)
+               dev_err(codec->dev, "Digital core FIFO error\n");
+
+       if (irq_val & WM8996_FLL_LOCK_EINT) {
+               dev_dbg(codec->dev, "FLL locked\n");
+               complete(&wm8996->fll_lock);
+       }
+
+       if (irq_val & WM8996_MICD_EINT)
+               wm8996_micd(codec);
+
+       if (irq_val)
+               return IRQ_HANDLED;
+       else
+               return IRQ_NONE;
+}
+
+static irqreturn_t wm8996_edge_irq(int irq, void *data)
+{
+       irqreturn_t ret = IRQ_NONE;
+       irqreturn_t val;
+
+       do {
+               val = wm8996_irq(irq, data);
+               if (val != IRQ_NONE)
+                       ret = val;
+       } while (val != IRQ_NONE);
+
+       return ret;
+}
+
+static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       struct wm8996_pdata *pdata = &wm8996->pdata;
+
+       struct snd_kcontrol_new controls[] = {
+               SOC_ENUM_EXT("DSP1 EQ Mode",
+                            wm8996->retune_mobile_enum,
+                            wm8996_get_retune_mobile_enum,
+                            wm8996_put_retune_mobile_enum),
+               SOC_ENUM_EXT("DSP2 EQ Mode",
+                            wm8996->retune_mobile_enum,
+                            wm8996_get_retune_mobile_enum,
+                            wm8996_put_retune_mobile_enum),
+       };
+       int ret, i, j;
+       const char **t;
+
+       /* We need an array of texts for the enum API but the number
+        * of texts is likely to be less than the number of
+        * configurations due to the sample rate dependency of the
+        * configurations. */
+       wm8996->num_retune_mobile_texts = 0;
+       wm8996->retune_mobile_texts = NULL;
+       for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) {
+               for (j = 0; j < wm8996->num_retune_mobile_texts; j++) {
+                       if (strcmp(pdata->retune_mobile_cfgs[i].name,
+                                  wm8996->retune_mobile_texts[j]) == 0)
+                               break;
+               }
+
+               if (j != wm8996->num_retune_mobile_texts)
+                       continue;
+
+               /* Expand the array... */
+               t = krealloc(wm8996->retune_mobile_texts,
+                            sizeof(char *) * 
+                            (wm8996->num_retune_mobile_texts + 1),
+                            GFP_KERNEL);
+               if (t == NULL)
+                       continue;
+
+               /* ...store the new entry... */
+               t[wm8996->num_retune_mobile_texts] = 
+                       pdata->retune_mobile_cfgs[i].name;
+
+               /* ...and remember the new version. */
+               wm8996->num_retune_mobile_texts++;
+               wm8996->retune_mobile_texts = t;
+       }
+
+       dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n",
+               wm8996->num_retune_mobile_texts);
+
+       wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts;
+       wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts;
+
+       ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+       if (ret != 0)
+               dev_err(codec->dev,
+                       "Failed to add ReTune Mobile controls: %d\n", ret);
+}
+
+static int wm8996_probe(struct snd_soc_codec *codec)
+{
+       int ret;
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       struct i2c_client *i2c = to_i2c_client(codec->dev);
+       struct snd_soc_dapm_context *dapm = &codec->dapm;
+       int i, irq_flags;
+
+       wm8996->codec = codec;
+
+       init_completion(&wm8996->dcs_done);
+       init_completion(&wm8996->fll_lock);
+
+       dapm->idle_bias_off = true;
+       dapm->bias_level = SND_SOC_BIAS_OFF;
+
+       ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
+               wm8996->supplies[i].supply = wm8996_supply_names[i];
+
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8996->supplies),
+                                wm8996->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               goto err;
+       }
+
+       wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0;
+       wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1;
+       wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2;
+       wm8996->disable_nb[3].notifier_call = wm8996_regulator_event_3;
+
+       /* This should really be moved into the regulator core */
+       for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) {
+               ret = regulator_register_notifier(wm8996->supplies[i].consumer,
+                                                 &wm8996->disable_nb[i]);
+               if (ret != 0) {
+                       dev_err(codec->dev,
+                               "Failed to register regulator notifier: %d\n",
+                               ret);
+               }
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
+                                   wm8996->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+               goto err_get;
+       }
+
+       if (wm8996->pdata.ldo_ena >= 0) {
+               gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
+               msleep(5);
+       }
+
+       ret = snd_soc_read(codec, WM8996_SOFTWARE_RESET);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read ID register: %d\n", ret);
+               goto err_enable;
+       }
+       if (ret != 0x8915) {
+               dev_err(codec->dev, "Device is not a WM8996, ID %x\n", ret);
+               ret = -EINVAL;
+               goto err_enable;
+       }
+
+       ret = snd_soc_read(codec, WM8996_CHIP_REVISION);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read device revision: %d\n",
+                       ret);
+               goto err_enable;
+       }
+       
+       dev_info(codec->dev, "revision %c\n",
+                (ret & WM8996_CHIP_REV_MASK) + 'A');
+
+       if (wm8996->pdata.ldo_ena >= 0) {
+               gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+       } else {
+               ret = wm8996_reset(codec);
+               if (ret < 0) {
+                       dev_err(codec->dev, "Failed to issue reset\n");
+                       goto err_enable;
+               }
+       }
+
+       codec->cache_only = true;
+
+       /* Apply platform data settings */
+       snd_soc_update_bits(codec, WM8996_LINE_INPUT_CONTROL,
+                           WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK,
+                           wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT |
+                           wm8996->pdata.inr_mode);
+
+       for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) {
+               if (!wm8996->pdata.gpio_default[i])
+                       continue;
+
+               snd_soc_write(codec, WM8996_GPIO_1 + i,
+                             wm8996->pdata.gpio_default[i] & 0xffff);
+       }
+
+       if (wm8996->pdata.spkmute_seq)
+               snd_soc_update_bits(codec, WM8996_PDM_SPEAKER_MUTE_SEQUENCE,
+                                   WM8996_SPK_MUTE_ENDIAN |
+                                   WM8996_SPK_MUTE_SEQ1_MASK,
+                                   wm8996->pdata.spkmute_seq);
+
+       snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_2,
+                           WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC |
+                           WM8996_MICD_SRC, wm8996->pdata.micdet_def);
+
+       /* Latch volume update bits */
+       snd_soc_update_bits(codec, WM8996_LEFT_LINE_INPUT_VOLUME,
+                           WM8996_IN1_VU, WM8996_IN1_VU);
+       snd_soc_update_bits(codec, WM8996_RIGHT_LINE_INPUT_VOLUME,
+                           WM8996_IN1_VU, WM8996_IN1_VU);
+
+       snd_soc_update_bits(codec, WM8996_DAC1_LEFT_VOLUME,
+                           WM8996_DAC1_VU, WM8996_DAC1_VU);
+       snd_soc_update_bits(codec, WM8996_DAC1_RIGHT_VOLUME,
+                           WM8996_DAC1_VU, WM8996_DAC1_VU);
+       snd_soc_update_bits(codec, WM8996_DAC2_LEFT_VOLUME,
+                           WM8996_DAC2_VU, WM8996_DAC2_VU);
+       snd_soc_update_bits(codec, WM8996_DAC2_RIGHT_VOLUME,
+                           WM8996_DAC2_VU, WM8996_DAC2_VU);
+
+       snd_soc_update_bits(codec, WM8996_OUTPUT1_LEFT_VOLUME,
+                           WM8996_DAC1_VU, WM8996_DAC1_VU);
+       snd_soc_update_bits(codec, WM8996_OUTPUT1_RIGHT_VOLUME,
+                           WM8996_DAC1_VU, WM8996_DAC1_VU);
+       snd_soc_update_bits(codec, WM8996_OUTPUT2_LEFT_VOLUME,
+                           WM8996_DAC2_VU, WM8996_DAC2_VU);
+       snd_soc_update_bits(codec, WM8996_OUTPUT2_RIGHT_VOLUME,
+                           WM8996_DAC2_VU, WM8996_DAC2_VU);
+
+       snd_soc_update_bits(codec, WM8996_DSP1_TX_LEFT_VOLUME,
+                           WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
+       snd_soc_update_bits(codec, WM8996_DSP1_TX_RIGHT_VOLUME,
+                           WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
+       snd_soc_update_bits(codec, WM8996_DSP2_TX_LEFT_VOLUME,
+                           WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);
+       snd_soc_update_bits(codec, WM8996_DSP2_TX_RIGHT_VOLUME,
+                           WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);
+
+       snd_soc_update_bits(codec, WM8996_DSP1_RX_LEFT_VOLUME,
+                           WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
+       snd_soc_update_bits(codec, WM8996_DSP1_RX_RIGHT_VOLUME,
+                           WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
+       snd_soc_update_bits(codec, WM8996_DSP2_RX_LEFT_VOLUME,
+                           WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);
+       snd_soc_update_bits(codec, WM8996_DSP2_RX_RIGHT_VOLUME,
+                           WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);
+
+       /* No support currently for the underclocked TDM modes and
+        * pick a default TDM layout with each channel pair working with
+        * slots 0 and 1. */
+       snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_0_CONFIGURATION,
+                           WM8996_AIF1RX_CHAN0_SLOTS_MASK |
+                           WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
+                           1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0);
+       snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_1_CONFIGURATION,
+                           WM8996_AIF1RX_CHAN1_SLOTS_MASK |
+                           WM8996_AIF1RX_CHAN1_START_SLOT_MASK,
+                           1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1);
+       snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_2_CONFIGURATION,
+                           WM8996_AIF1RX_CHAN2_SLOTS_MASK |
+                           WM8996_AIF1RX_CHAN2_START_SLOT_MASK,
+                           1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0);
+       snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_3_CONFIGURATION,
+                           WM8996_AIF1RX_CHAN3_SLOTS_MASK |
+                           WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
+                           1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1);
+       snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_4_CONFIGURATION,
+                           WM8996_AIF1RX_CHAN4_SLOTS_MASK |
+                           WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
+                           1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0);
+       snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_5_CONFIGURATION,
+                           WM8996_AIF1RX_CHAN5_SLOTS_MASK |
+                           WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
+                           1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1);
+
+       snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_0_CONFIGURATION,
+                           WM8996_AIF2RX_CHAN0_SLOTS_MASK |
+                           WM8996_AIF2RX_CHAN0_START_SLOT_MASK,
+                           1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0);
+       snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_1_CONFIGURATION,
+                           WM8996_AIF2RX_CHAN1_SLOTS_MASK |
+                           WM8996_AIF2RX_CHAN1_START_SLOT_MASK,
+                           1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1);
+
+       snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_0_CONFIGURATION,
+                           WM8996_AIF1TX_CHAN0_SLOTS_MASK |
+                           WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
+                           1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0);
+       snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
+                           WM8996_AIF1TX_CHAN1_SLOTS_MASK |
+                           WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
+                           1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
+       snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_2_CONFIGURATION,
+                           WM8996_AIF1TX_CHAN2_SLOTS_MASK |
+                           WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
+                           1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0);
+       snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_3_CONFIGURATION,
+                           WM8996_AIF1TX_CHAN3_SLOTS_MASK |
+                           WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
+                           1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1);
+       snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_4_CONFIGURATION,
+                           WM8996_AIF1TX_CHAN4_SLOTS_MASK |
+                           WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
+                           1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0);
+       snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_5_CONFIGURATION,
+                           WM8996_AIF1TX_CHAN5_SLOTS_MASK |
+                           WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
+                           1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1);
+
+       snd_soc_update_bits(codec, WM8996_AIF2TX_CHANNEL_0_CONFIGURATION,
+                           WM8996_AIF2TX_CHAN0_SLOTS_MASK |
+                           WM8996_AIF2TX_CHAN0_START_SLOT_MASK,
+                           1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0);
+       snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
+                           WM8996_AIF2TX_CHAN1_SLOTS_MASK |
+                           WM8996_AIF2TX_CHAN1_START_SLOT_MASK,
+                           1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
+
+       if (wm8996->pdata.num_retune_mobile_cfgs)
+               wm8996_retune_mobile_pdata(codec);
+       else
+               snd_soc_add_controls(codec, wm8996_eq_controls,
+                                    ARRAY_SIZE(wm8996_eq_controls));
+
+       /* If the TX LRCLK pins are not in LRCLK mode configure the
+        * AIFs to source their clocks from the RX LRCLKs.
+        */
+       if ((snd_soc_read(codec, WM8996_GPIO_1)))
+               snd_soc_update_bits(codec, WM8996_AIF1_TX_LRCLK_2,
+                                   WM8996_AIF1TX_LRCLK_MODE,
+                                   WM8996_AIF1TX_LRCLK_MODE);
+
+       if ((snd_soc_read(codec, WM8996_GPIO_2)))
+               snd_soc_update_bits(codec, WM8996_AIF2_TX_LRCLK_2,
+                                   WM8996_AIF2TX_LRCLK_MODE,
+                                   WM8996_AIF2TX_LRCLK_MODE);
+
+       regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
+
+       wm8996_init_gpio(codec);
+
+       if (i2c->irq) {
+               if (wm8996->pdata.irq_flags)
+                       irq_flags = wm8996->pdata.irq_flags;
+               else
+                       irq_flags = IRQF_TRIGGER_LOW;
+
+               irq_flags |= IRQF_ONESHOT;
+
+               if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
+                       ret = request_threaded_irq(i2c->irq, NULL,
+                                                  wm8996_edge_irq,
+                                                  irq_flags, "wm8996", codec);
+               else
+                       ret = request_threaded_irq(i2c->irq, NULL, wm8996_irq,
+                                                  irq_flags, "wm8996", codec);
+
+               if (ret == 0) {
+                       /* Unmask the interrupt */
+                       snd_soc_update_bits(codec, WM8996_INTERRUPT_CONTROL,
+                                           WM8996_IM_IRQ, 0);
+
+                       /* Enable error reporting and DC servo status */
+                       snd_soc_update_bits(codec,
+                                           WM8996_INTERRUPT_STATUS_2_MASK,
+                                           WM8996_IM_DCS_DONE_23_EINT |
+                                           WM8996_IM_DCS_DONE_01_EINT |
+                                           WM8996_IM_FLL_LOCK_EINT |
+                                           WM8996_IM_FIFOS_ERR_EINT,
+                                           0);
+               } else {
+                       dev_err(codec->dev, "Failed to request IRQ: %d\n",
+                               ret);
+               }
+       }
+
+       return 0;
+
+err_enable:
+       if (wm8996->pdata.ldo_ena >= 0)
+               gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+
+       regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
+err_get:
+       regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
+err:
+       return ret;
+}
+
+static int wm8996_remove(struct snd_soc_codec *codec)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       struct i2c_client *i2c = to_i2c_client(codec->dev);
+       int i;
+
+       snd_soc_update_bits(codec, WM8996_INTERRUPT_CONTROL,
+                           WM8996_IM_IRQ, WM8996_IM_IRQ);
+
+       if (i2c->irq)
+               free_irq(i2c->irq, codec);
+
+       wm8996_free_gpio(codec);
+
+       for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
+               regulator_unregister_notifier(wm8996->supplies[i].consumer,
+                                             &wm8996->disable_nb[i]);
+       regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
+
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
+       .probe =        wm8996_probe,
+       .remove =       wm8996_remove,
+       .set_bias_level = wm8996_set_bias_level,
+       .seq_notifier = wm8996_seq_notifier,
+       .reg_cache_size = WM8996_MAX_REGISTER + 1,
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8996_reg,
+       .volatile_register = wm8996_volatile_register,
+       .readable_register = wm8996_readable_register,
+       .compress_type = SND_SOC_RBTREE_COMPRESSION,
+       .controls = wm8996_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8996_snd_controls),
+       .dapm_widgets = wm8996_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8996_dapm_widgets),
+       .dapm_routes = wm8996_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8996_dapm_routes),
+       .set_pll = wm8996_set_fll,
+};
+
+#define WM8996_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+                     SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
+#define WM8996_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
+                       SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\
+                       SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops wm8996_dai_ops = {
+       .set_fmt = wm8996_set_fmt,
+       .hw_params = wm8996_hw_params,
+       .set_sysclk = wm8996_set_sysclk,
+};
+
+static struct snd_soc_dai_driver wm8996_dai[] = {
+       {
+               .name = "wm8996-aif1",
+               .playback = {
+                       .stream_name = "AIF1 Playback",
+                       .channels_min = 1,
+                       .channels_max = 6,
+                       .rates = WM8996_RATES,
+                       .formats = WM8996_FORMATS,
+               },
+               .capture = {
+                        .stream_name = "AIF1 Capture",
+                        .channels_min = 1,
+                        .channels_max = 6,
+                        .rates = WM8996_RATES,
+                        .formats = WM8996_FORMATS,
+                },
+               .ops = &wm8996_dai_ops,
+       },
+       {
+               .name = "wm8996-aif2",
+               .playback = {
+                       .stream_name = "AIF2 Playback",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = WM8996_RATES,
+                       .formats = WM8996_FORMATS,
+               },
+               .capture = {
+                        .stream_name = "AIF2 Capture",
+                        .channels_min = 1,
+                        .channels_max = 2,
+                        .rates = WM8996_RATES,
+                        .formats = WM8996_FORMATS,
+                },
+               .ops = &wm8996_dai_ops,
+       },
+};
+
+static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm8996_priv *wm8996;
+       int ret;
+
+       wm8996 = kzalloc(sizeof(struct wm8996_priv), GFP_KERNEL);
+       if (wm8996 == NULL)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, wm8996);
+
+       if (dev_get_platdata(&i2c->dev))
+               memcpy(&wm8996->pdata, dev_get_platdata(&i2c->dev),
+                      sizeof(wm8996->pdata));
+
+       if (wm8996->pdata.ldo_ena > 0) {
+               ret = gpio_request_one(wm8996->pdata.ldo_ena,
+                                      GPIOF_OUT_INIT_LOW, "WM8996 ENA");
+               if (ret < 0) {
+                       dev_err(&i2c->dev, "Failed to request GPIO %d: %d\n",
+                               wm8996->pdata.ldo_ena, ret);
+                       goto err;
+               }
+       }
+
+       ret = snd_soc_register_codec(&i2c->dev,
+                                    &soc_codec_dev_wm8996, wm8996_dai,
+                                    ARRAY_SIZE(wm8996_dai));
+       if (ret < 0)
+               goto err_gpio;
+
+       return ret;
+
+err_gpio:
+       if (wm8996->pdata.ldo_ena > 0)
+               gpio_free(wm8996->pdata.ldo_ena);
+err:
+       kfree(wm8996);
+
+       return ret;
+}
+
+static __devexit int wm8996_i2c_remove(struct i2c_client *client)
+{
+       struct wm8996_priv *wm8996 = i2c_get_clientdata(client);
+
+       snd_soc_unregister_codec(&client->dev);
+       if (wm8996->pdata.ldo_ena > 0)
+               gpio_free(wm8996->pdata.ldo_ena);
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+static const struct i2c_device_id wm8996_i2c_id[] = {
+       { "wm8996", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8996_i2c_id);
+
+static struct i2c_driver wm8996_i2c_driver = {
+       .driver = {
+               .name = "wm8996",
+               .owner = THIS_MODULE,
+       },
+       .probe =    wm8996_i2c_probe,
+       .remove =   __devexit_p(wm8996_i2c_remove),
+       .id_table = wm8996_i2c_id,
+};
+
+static int __init wm8996_modinit(void)
+{
+       int ret;
+
+       ret = i2c_add_driver(&wm8996_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register WM8996 I2C driver: %d\n",
+                      ret);
+       }
+
+       return ret;
+}
+module_init(wm8996_modinit);
+
+static void __exit wm8996_exit(void)
+{
+       i2c_del_driver(&wm8996_i2c_driver);
+}
+module_exit(wm8996_exit);
+
+MODULE_DESCRIPTION("ASoC WM8996 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8996.h b/sound/soc/codecs/wm8996.h
new file mode 100644 (file)
index 0000000..0fde643
--- /dev/null
@@ -0,0 +1,3717 @@
+/*
+ * wm8996.h - WM8996 audio codec interface
+ *
+ * Copyright 2011 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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.
+ */
+
+#ifndef _WM8996_H
+#define _WM8996_H
+
+#define WM8996_SYSCLK_MCLK1 1
+#define WM8996_SYSCLK_MCLK2 2
+#define WM8996_SYSCLK_FLL   3
+
+#define WM8996_FLL_MCLK1      1
+#define WM8996_FLL_MCLK2      2
+#define WM8996_FLL_DACLRCLK1  3
+#define WM8996_FLL_BCLK1      4
+
+typedef void (*wm8996_polarity_fn)(struct snd_soc_codec *codec, int polarity);
+
+int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
+                 wm8996_polarity_fn polarity_cb);
+
+/*
+ * Register values.
+ */
+#define WM8996_SOFTWARE_RESET                   0x00
+#define WM8996_POWER_MANAGEMENT_1               0x01
+#define WM8996_POWER_MANAGEMENT_2               0x02
+#define WM8996_POWER_MANAGEMENT_3               0x03
+#define WM8996_POWER_MANAGEMENT_4               0x04
+#define WM8996_POWER_MANAGEMENT_5               0x05
+#define WM8996_POWER_MANAGEMENT_6               0x06
+#define WM8996_POWER_MANAGEMENT_7               0x07
+#define WM8996_POWER_MANAGEMENT_8               0x08
+#define WM8996_LEFT_LINE_INPUT_VOLUME           0x10
+#define WM8996_RIGHT_LINE_INPUT_VOLUME          0x11
+#define WM8996_LINE_INPUT_CONTROL               0x12
+#define WM8996_DAC1_HPOUT1_VOLUME               0x15
+#define WM8996_DAC2_HPOUT2_VOLUME               0x16
+#define WM8996_DAC1_LEFT_VOLUME                 0x18
+#define WM8996_DAC1_RIGHT_VOLUME                0x19
+#define WM8996_DAC2_LEFT_VOLUME                 0x1A
+#define WM8996_DAC2_RIGHT_VOLUME                0x1B
+#define WM8996_OUTPUT1_LEFT_VOLUME              0x1C
+#define WM8996_OUTPUT1_RIGHT_VOLUME             0x1D
+#define WM8996_OUTPUT2_LEFT_VOLUME              0x1E
+#define WM8996_OUTPUT2_RIGHT_VOLUME             0x1F
+#define WM8996_MICBIAS_1                        0x20
+#define WM8996_MICBIAS_2                        0x21
+#define WM8996_LDO_1                            0x28
+#define WM8996_LDO_2                            0x29
+#define WM8996_ACCESSORY_DETECT_MODE_1          0x30
+#define WM8996_ACCESSORY_DETECT_MODE_2          0x31
+#define WM8996_HEADPHONE_DETECT_1               0x34
+#define WM8996_HEADPHONE_DETECT_2               0x35
+#define WM8996_MIC_DETECT_1                     0x38
+#define WM8996_MIC_DETECT_2                     0x39
+#define WM8996_MIC_DETECT_3                     0x3A
+#define WM8996_CHARGE_PUMP_1                    0x40
+#define WM8996_CHARGE_PUMP_2                    0x41
+#define WM8996_DC_SERVO_1                       0x50
+#define WM8996_DC_SERVO_2                       0x51
+#define WM8996_DC_SERVO_3                       0x52
+#define WM8996_DC_SERVO_5                       0x54
+#define WM8996_DC_SERVO_6                       0x55
+#define WM8996_DC_SERVO_7                       0x56
+#define WM8996_DC_SERVO_READBACK_0              0x57
+#define WM8996_ANALOGUE_HP_1                    0x60
+#define WM8996_ANALOGUE_HP_2                    0x61
+#define WM8996_CHIP_REVISION                    0x100
+#define WM8996_CONTROL_INTERFACE_1              0x101
+#define WM8996_WRITE_SEQUENCER_CTRL_1           0x110
+#define WM8996_WRITE_SEQUENCER_CTRL_2           0x111
+#define WM8996_AIF_CLOCKING_1                   0x200
+#define WM8996_AIF_CLOCKING_2                   0x201
+#define WM8996_CLOCKING_1                       0x208
+#define WM8996_CLOCKING_2                       0x209
+#define WM8996_AIF_RATE                         0x210
+#define WM8996_FLL_CONTROL_1                    0x220
+#define WM8996_FLL_CONTROL_2                    0x221
+#define WM8996_FLL_CONTROL_3                    0x222
+#define WM8996_FLL_CONTROL_4                    0x223
+#define WM8996_FLL_CONTROL_5                    0x224
+#define WM8996_FLL_CONTROL_6                    0x225
+#define WM8996_FLL_EFS_1                        0x226
+#define WM8996_FLL_EFS_2                        0x227
+#define WM8996_AIF1_CONTROL                     0x300
+#define WM8996_AIF1_BCLK                        0x301
+#define WM8996_AIF1_TX_LRCLK_1                  0x302
+#define WM8996_AIF1_TX_LRCLK_2                  0x303
+#define WM8996_AIF1_RX_LRCLK_1                  0x304
+#define WM8996_AIF1_RX_LRCLK_2                  0x305
+#define WM8996_AIF1TX_DATA_CONFIGURATION_1      0x306
+#define WM8996_AIF1TX_DATA_CONFIGURATION_2      0x307
+#define WM8996_AIF1RX_DATA_CONFIGURATION        0x308
+#define WM8996_AIF1TX_CHANNEL_0_CONFIGURATION   0x309
+#define WM8996_AIF1TX_CHANNEL_1_CONFIGURATION   0x30A
+#define WM8996_AIF1TX_CHANNEL_2_CONFIGURATION   0x30B
+#define WM8996_AIF1TX_CHANNEL_3_CONFIGURATION   0x30C
+#define WM8996_AIF1TX_CHANNEL_4_CONFIGURATION   0x30D
+#define WM8996_AIF1TX_CHANNEL_5_CONFIGURATION   0x30E
+#define WM8996_AIF1RX_CHANNEL_0_CONFIGURATION   0x30F
+#define WM8996_AIF1RX_CHANNEL_1_CONFIGURATION   0x310
+#define WM8996_AIF1RX_CHANNEL_2_CONFIGURATION   0x311
+#define WM8996_AIF1RX_CHANNEL_3_CONFIGURATION   0x312
+#define WM8996_AIF1RX_CHANNEL_4_CONFIGURATION   0x313
+#define WM8996_AIF1RX_CHANNEL_5_CONFIGURATION   0x314
+#define WM8996_AIF1RX_MONO_CONFIGURATION        0x315
+#define WM8996_AIF1TX_TEST                      0x31A
+#define WM8996_AIF2_CONTROL                     0x320
+#define WM8996_AIF2_BCLK                        0x321
+#define WM8996_AIF2_TX_LRCLK_1                  0x322
+#define WM8996_AIF2_TX_LRCLK_2                  0x323
+#define WM8996_AIF2_RX_LRCLK_1                  0x324
+#define WM8996_AIF2_RX_LRCLK_2                  0x325
+#define WM8996_AIF2TX_DATA_CONFIGURATION_1      0x326
+#define WM8996_AIF2TX_DATA_CONFIGURATION_2      0x327
+#define WM8996_AIF2RX_DATA_CONFIGURATION        0x328
+#define WM8996_AIF2TX_CHANNEL_0_CONFIGURATION   0x329
+#define WM8996_AIF2TX_CHANNEL_1_CONFIGURATION   0x32A
+#define WM8996_AIF2RX_CHANNEL_0_CONFIGURATION   0x32B
+#define WM8996_AIF2RX_CHANNEL_1_CONFIGURATION   0x32C
+#define WM8996_AIF2RX_MONO_CONFIGURATION        0x32D
+#define WM8996_AIF2TX_TEST                      0x32F
+#define WM8996_DSP1_TX_LEFT_VOLUME              0x400
+#define WM8996_DSP1_TX_RIGHT_VOLUME             0x401
+#define WM8996_DSP1_RX_LEFT_VOLUME              0x402
+#define WM8996_DSP1_RX_RIGHT_VOLUME             0x403
+#define WM8996_DSP1_TX_FILTERS                  0x410
+#define WM8996_DSP1_RX_FILTERS_1                0x420
+#define WM8996_DSP1_RX_FILTERS_2                0x421
+#define WM8996_DSP1_DRC_1                       0x440
+#define WM8996_DSP1_DRC_2                       0x441
+#define WM8996_DSP1_DRC_3                       0x442
+#define WM8996_DSP1_DRC_4                       0x443
+#define WM8996_DSP1_DRC_5                       0x444
+#define WM8996_DSP1_RX_EQ_GAINS_1               0x480
+#define WM8996_DSP1_RX_EQ_GAINS_2               0x481
+#define WM8996_DSP1_RX_EQ_BAND_1_A              0x482
+#define WM8996_DSP1_RX_EQ_BAND_1_B              0x483
+#define WM8996_DSP1_RX_EQ_BAND_1_PG             0x484
+#define WM8996_DSP1_RX_EQ_BAND_2_A              0x485
+#define WM8996_DSP1_RX_EQ_BAND_2_B              0x486
+#define WM8996_DSP1_RX_EQ_BAND_2_C              0x487
+#define WM8996_DSP1_RX_EQ_BAND_2_PG             0x488
+#define WM8996_DSP1_RX_EQ_BAND_3_A              0x489
+#define WM8996_DSP1_RX_EQ_BAND_3_B              0x48A
+#define WM8996_DSP1_RX_EQ_BAND_3_C              0x48B
+#define WM8996_DSP1_RX_EQ_BAND_3_PG             0x48C
+#define WM8996_DSP1_RX_EQ_BAND_4_A              0x48D
+#define WM8996_DSP1_RX_EQ_BAND_4_B              0x48E
+#define WM8996_DSP1_RX_EQ_BAND_4_C              0x48F
+#define WM8996_DSP1_RX_EQ_BAND_4_PG             0x490
+#define WM8996_DSP1_RX_EQ_BAND_5_A              0x491
+#define WM8996_DSP1_RX_EQ_BAND_5_B              0x492
+#define WM8996_DSP1_RX_EQ_BAND_5_PG             0x493
+#define WM8996_DSP2_TX_LEFT_VOLUME              0x500
+#define WM8996_DSP2_TX_RIGHT_VOLUME             0x501
+#define WM8996_DSP2_RX_LEFT_VOLUME              0x502
+#define WM8996_DSP2_RX_RIGHT_VOLUME             0x503
+#define WM8996_DSP2_TX_FILTERS                  0x510
+#define WM8996_DSP2_RX_FILTERS_1                0x520
+#define WM8996_DSP2_RX_FILTERS_2                0x521
+#define WM8996_DSP2_DRC_1                       0x540
+#define WM8996_DSP2_DRC_2                       0x541
+#define WM8996_DSP2_DRC_3                       0x542
+#define WM8996_DSP2_DRC_4                       0x543
+#define WM8996_DSP2_DRC_5                       0x544
+#define WM8996_DSP2_RX_EQ_GAINS_1               0x580
+#define WM8996_DSP2_RX_EQ_GAINS_2               0x581
+#define WM8996_DSP2_RX_EQ_BAND_1_A              0x582
+#define WM8996_DSP2_RX_EQ_BAND_1_B              0x583
+#define WM8996_DSP2_RX_EQ_BAND_1_PG             0x584
+#define WM8996_DSP2_RX_EQ_BAND_2_A              0x585
+#define WM8996_DSP2_RX_EQ_BAND_2_B              0x586
+#define WM8996_DSP2_RX_EQ_BAND_2_C              0x587
+#define WM8996_DSP2_RX_EQ_BAND_2_PG             0x588
+#define WM8996_DSP2_RX_EQ_BAND_3_A              0x589
+#define WM8996_DSP2_RX_EQ_BAND_3_B              0x58A
+#define WM8996_DSP2_RX_EQ_BAND_3_C              0x58B
+#define WM8996_DSP2_RX_EQ_BAND_3_PG             0x58C
+#define WM8996_DSP2_RX_EQ_BAND_4_A              0x58D
+#define WM8996_DSP2_RX_EQ_BAND_4_B              0x58E
+#define WM8996_DSP2_RX_EQ_BAND_4_C              0x58F
+#define WM8996_DSP2_RX_EQ_BAND_4_PG             0x590
+#define WM8996_DSP2_RX_EQ_BAND_5_A              0x591
+#define WM8996_DSP2_RX_EQ_BAND_5_B              0x592
+#define WM8996_DSP2_RX_EQ_BAND_5_PG             0x593
+#define WM8996_DAC1_MIXER_VOLUMES               0x600
+#define WM8996_DAC1_LEFT_MIXER_ROUTING          0x601
+#define WM8996_DAC1_RIGHT_MIXER_ROUTING         0x602
+#define WM8996_DAC2_MIXER_VOLUMES               0x603
+#define WM8996_DAC2_LEFT_MIXER_ROUTING          0x604
+#define WM8996_DAC2_RIGHT_MIXER_ROUTING         0x605
+#define WM8996_DSP1_TX_LEFT_MIXER_ROUTING       0x606
+#define WM8996_DSP1_TX_RIGHT_MIXER_ROUTING      0x607
+#define WM8996_DSP2_TX_LEFT_MIXER_ROUTING       0x608
+#define WM8996_DSP2_TX_RIGHT_MIXER_ROUTING      0x609
+#define WM8996_DSP_TX_MIXER_SELECT              0x60A
+#define WM8996_DAC_SOFTMUTE                     0x610
+#define WM8996_OVERSAMPLING                     0x620
+#define WM8996_SIDETONE                         0x621
+#define WM8996_GPIO_1                           0x700
+#define WM8996_GPIO_2                           0x701
+#define WM8996_GPIO_3                           0x702
+#define WM8996_GPIO_4                           0x703
+#define WM8996_GPIO_5                           0x704
+#define WM8996_PULL_CONTROL_1                   0x720
+#define WM8996_PULL_CONTROL_2                   0x721
+#define WM8996_INTERRUPT_STATUS_1               0x730
+#define WM8996_INTERRUPT_STATUS_2               0x731
+#define WM8996_INTERRUPT_RAW_STATUS_2           0x732
+#define WM8996_INTERRUPT_STATUS_1_MASK          0x738
+#define WM8996_INTERRUPT_STATUS_2_MASK          0x739
+#define WM8996_INTERRUPT_CONTROL                0x740
+#define WM8996_LEFT_PDM_SPEAKER                 0x800
+#define WM8996_RIGHT_PDM_SPEAKER                0x801
+#define WM8996_PDM_SPEAKER_MUTE_SEQUENCE        0x802
+#define WM8996_PDM_SPEAKER_VOLUME               0x803
+#define WM8996_WRITE_SEQUENCER_0                0x3000
+#define WM8996_WRITE_SEQUENCER_1                0x3001
+#define WM8996_WRITE_SEQUENCER_2                0x3002
+#define WM8996_WRITE_SEQUENCER_3                0x3003
+#define WM8996_WRITE_SEQUENCER_4                0x3004
+#define WM8996_WRITE_SEQUENCER_5                0x3005
+#define WM8996_WRITE_SEQUENCER_6                0x3006
+#define WM8996_WRITE_SEQUENCER_7                0x3007
+#define WM8996_WRITE_SEQUENCER_8                0x3008
+#define WM8996_WRITE_SEQUENCER_9                0x3009
+#define WM8996_WRITE_SEQUENCER_10               0x300A
+#define WM8996_WRITE_SEQUENCER_11               0x300B
+#define WM8996_WRITE_SEQUENCER_12               0x300C
+#define WM8996_WRITE_SEQUENCER_13               0x300D
+#define WM8996_WRITE_SEQUENCER_14               0x300E
+#define WM8996_WRITE_SEQUENCER_15               0x300F
+#define WM8996_WRITE_SEQUENCER_16               0x3010
+#define WM8996_WRITE_SEQUENCER_17               0x3011
+#define WM8996_WRITE_SEQUENCER_18               0x3012
+#define WM8996_WRITE_SEQUENCER_19               0x3013
+#define WM8996_WRITE_SEQUENCER_20               0x3014
+#define WM8996_WRITE_SEQUENCER_21               0x3015
+#define WM8996_WRITE_SEQUENCER_22               0x3016
+#define WM8996_WRITE_SEQUENCER_23               0x3017
+#define WM8996_WRITE_SEQUENCER_24               0x3018
+#define WM8996_WRITE_SEQUENCER_25               0x3019
+#define WM8996_WRITE_SEQUENCER_26               0x301A
+#define WM8996_WRITE_SEQUENCER_27               0x301B
+#define WM8996_WRITE_SEQUENCER_28               0x301C
+#define WM8996_WRITE_SEQUENCER_29               0x301D
+#define WM8996_WRITE_SEQUENCER_30               0x301E
+#define WM8996_WRITE_SEQUENCER_31               0x301F
+#define WM8996_WRITE_SEQUENCER_32               0x3020
+#define WM8996_WRITE_SEQUENCER_33               0x3021
+#define WM8996_WRITE_SEQUENCER_34               0x3022
+#define WM8996_WRITE_SEQUENCER_35               0x3023
+#define WM8996_WRITE_SEQUENCER_36               0x3024
+#define WM8996_WRITE_SEQUENCER_37               0x3025
+#define WM8996_WRITE_SEQUENCER_38               0x3026
+#define WM8996_WRITE_SEQUENCER_39               0x3027
+#define WM8996_WRITE_SEQUENCER_40               0x3028
+#define WM8996_WRITE_SEQUENCER_41               0x3029
+#define WM8996_WRITE_SEQUENCER_42               0x302A
+#define WM8996_WRITE_SEQUENCER_43               0x302B
+#define WM8996_WRITE_SEQUENCER_44               0x302C
+#define WM8996_WRITE_SEQUENCER_45               0x302D
+#define WM8996_WRITE_SEQUENCER_46               0x302E
+#define WM8996_WRITE_SEQUENCER_47               0x302F
+#define WM8996_WRITE_SEQUENCER_48               0x3030
+#define WM8996_WRITE_SEQUENCER_49               0x3031
+#define WM8996_WRITE_SEQUENCER_50               0x3032
+#define WM8996_WRITE_SEQUENCER_51               0x3033
+#define WM8996_WRITE_SEQUENCER_52               0x3034
+#define WM8996_WRITE_SEQUENCER_53               0x3035
+#define WM8996_WRITE_SEQUENCER_54               0x3036
+#define WM8996_WRITE_SEQUENCER_55               0x3037
+#define WM8996_WRITE_SEQUENCER_56               0x3038
+#define WM8996_WRITE_SEQUENCER_57               0x3039
+#define WM8996_WRITE_SEQUENCER_58               0x303A
+#define WM8996_WRITE_SEQUENCER_59               0x303B
+#define WM8996_WRITE_SEQUENCER_60               0x303C
+#define WM8996_WRITE_SEQUENCER_61               0x303D
+#define WM8996_WRITE_SEQUENCER_62               0x303E
+#define WM8996_WRITE_SEQUENCER_63               0x303F
+#define WM8996_WRITE_SEQUENCER_64               0x3040
+#define WM8996_WRITE_SEQUENCER_65               0x3041
+#define WM8996_WRITE_SEQUENCER_66               0x3042
+#define WM8996_WRITE_SEQUENCER_67               0x3043
+#define WM8996_WRITE_SEQUENCER_68               0x3044
+#define WM8996_WRITE_SEQUENCER_69               0x3045
+#define WM8996_WRITE_SEQUENCER_70               0x3046
+#define WM8996_WRITE_SEQUENCER_71               0x3047
+#define WM8996_WRITE_SEQUENCER_72               0x3048
+#define WM8996_WRITE_SEQUENCER_73               0x3049
+#define WM8996_WRITE_SEQUENCER_74               0x304A
+#define WM8996_WRITE_SEQUENCER_75               0x304B
+#define WM8996_WRITE_SEQUENCER_76               0x304C
+#define WM8996_WRITE_SEQUENCER_77               0x304D
+#define WM8996_WRITE_SEQUENCER_78               0x304E
+#define WM8996_WRITE_SEQUENCER_79               0x304F
+#define WM8996_WRITE_SEQUENCER_80               0x3050
+#define WM8996_WRITE_SEQUENCER_81               0x3051
+#define WM8996_WRITE_SEQUENCER_82               0x3052
+#define WM8996_WRITE_SEQUENCER_83               0x3053
+#define WM8996_WRITE_SEQUENCER_84               0x3054
+#define WM8996_WRITE_SEQUENCER_85               0x3055
+#define WM8996_WRITE_SEQUENCER_86               0x3056
+#define WM8996_WRITE_SEQUENCER_87               0x3057
+#define WM8996_WRITE_SEQUENCER_88               0x3058
+#define WM8996_WRITE_SEQUENCER_89               0x3059
+#define WM8996_WRITE_SEQUENCER_90               0x305A
+#define WM8996_WRITE_SEQUENCER_91               0x305B
+#define WM8996_WRITE_SEQUENCER_92               0x305C
+#define WM8996_WRITE_SEQUENCER_93               0x305D
+#define WM8996_WRITE_SEQUENCER_94               0x305E
+#define WM8996_WRITE_SEQUENCER_95               0x305F
+#define WM8996_WRITE_SEQUENCER_96               0x3060
+#define WM8996_WRITE_SEQUENCER_97               0x3061
+#define WM8996_WRITE_SEQUENCER_98               0x3062
+#define WM8996_WRITE_SEQUENCER_99               0x3063
+#define WM8996_WRITE_SEQUENCER_100              0x3064
+#define WM8996_WRITE_SEQUENCER_101              0x3065
+#define WM8996_WRITE_SEQUENCER_102              0x3066
+#define WM8996_WRITE_SEQUENCER_103              0x3067
+#define WM8996_WRITE_SEQUENCER_104              0x3068
+#define WM8996_WRITE_SEQUENCER_105              0x3069
+#define WM8996_WRITE_SEQUENCER_106              0x306A
+#define WM8996_WRITE_SEQUENCER_107              0x306B
+#define WM8996_WRITE_SEQUENCER_108              0x306C
+#define WM8996_WRITE_SEQUENCER_109              0x306D
+#define WM8996_WRITE_SEQUENCER_110              0x306E
+#define WM8996_WRITE_SEQUENCER_111              0x306F
+#define WM8996_WRITE_SEQUENCER_112              0x3070
+#define WM8996_WRITE_SEQUENCER_113              0x3071
+#define WM8996_WRITE_SEQUENCER_114              0x3072
+#define WM8996_WRITE_SEQUENCER_115              0x3073
+#define WM8996_WRITE_SEQUENCER_116              0x3074
+#define WM8996_WRITE_SEQUENCER_117              0x3075
+#define WM8996_WRITE_SEQUENCER_118              0x3076
+#define WM8996_WRITE_SEQUENCER_119              0x3077
+#define WM8996_WRITE_SEQUENCER_120              0x3078
+#define WM8996_WRITE_SEQUENCER_121              0x3079
+#define WM8996_WRITE_SEQUENCER_122              0x307A
+#define WM8996_WRITE_SEQUENCER_123              0x307B
+#define WM8996_WRITE_SEQUENCER_124              0x307C
+#define WM8996_WRITE_SEQUENCER_125              0x307D
+#define WM8996_WRITE_SEQUENCER_126              0x307E
+#define WM8996_WRITE_SEQUENCER_127              0x307F
+#define WM8996_WRITE_SEQUENCER_128              0x3080
+#define WM8996_WRITE_SEQUENCER_129              0x3081
+#define WM8996_WRITE_SEQUENCER_130              0x3082
+#define WM8996_WRITE_SEQUENCER_131              0x3083
+#define WM8996_WRITE_SEQUENCER_132              0x3084
+#define WM8996_WRITE_SEQUENCER_133              0x3085
+#define WM8996_WRITE_SEQUENCER_134              0x3086
+#define WM8996_WRITE_SEQUENCER_135              0x3087
+#define WM8996_WRITE_SEQUENCER_136              0x3088
+#define WM8996_WRITE_SEQUENCER_137              0x3089
+#define WM8996_WRITE_SEQUENCER_138              0x308A
+#define WM8996_WRITE_SEQUENCER_139              0x308B
+#define WM8996_WRITE_SEQUENCER_140              0x308C
+#define WM8996_WRITE_SEQUENCER_141              0x308D
+#define WM8996_WRITE_SEQUENCER_142              0x308E
+#define WM8996_WRITE_SEQUENCER_143              0x308F
+#define WM8996_WRITE_SEQUENCER_144              0x3090
+#define WM8996_WRITE_SEQUENCER_145              0x3091
+#define WM8996_WRITE_SEQUENCER_146              0x3092
+#define WM8996_WRITE_SEQUENCER_147              0x3093
+#define WM8996_WRITE_SEQUENCER_148              0x3094
+#define WM8996_WRITE_SEQUENCER_149              0x3095
+#define WM8996_WRITE_SEQUENCER_150              0x3096
+#define WM8996_WRITE_SEQUENCER_151              0x3097
+#define WM8996_WRITE_SEQUENCER_152              0x3098
+#define WM8996_WRITE_SEQUENCER_153              0x3099
+#define WM8996_WRITE_SEQUENCER_154              0x309A
+#define WM8996_WRITE_SEQUENCER_155              0x309B
+#define WM8996_WRITE_SEQUENCER_156              0x309C
+#define WM8996_WRITE_SEQUENCER_157              0x309D
+#define WM8996_WRITE_SEQUENCER_158              0x309E
+#define WM8996_WRITE_SEQUENCER_159              0x309F
+#define WM8996_WRITE_SEQUENCER_160              0x30A0
+#define WM8996_WRITE_SEQUENCER_161              0x30A1
+#define WM8996_WRITE_SEQUENCER_162              0x30A2
+#define WM8996_WRITE_SEQUENCER_163              0x30A3
+#define WM8996_WRITE_SEQUENCER_164              0x30A4
+#define WM8996_WRITE_SEQUENCER_165              0x30A5
+#define WM8996_WRITE_SEQUENCER_166              0x30A6
+#define WM8996_WRITE_SEQUENCER_167              0x30A7
+#define WM8996_WRITE_SEQUENCER_168              0x30A8
+#define WM8996_WRITE_SEQUENCER_169              0x30A9
+#define WM8996_WRITE_SEQUENCER_170              0x30AA
+#define WM8996_WRITE_SEQUENCER_171              0x30AB
+#define WM8996_WRITE_SEQUENCER_172              0x30AC
+#define WM8996_WRITE_SEQUENCER_173              0x30AD
+#define WM8996_WRITE_SEQUENCER_174              0x30AE
+#define WM8996_WRITE_SEQUENCER_175              0x30AF
+#define WM8996_WRITE_SEQUENCER_176              0x30B0
+#define WM8996_WRITE_SEQUENCER_177              0x30B1
+#define WM8996_WRITE_SEQUENCER_178              0x30B2
+#define WM8996_WRITE_SEQUENCER_179              0x30B3
+#define WM8996_WRITE_SEQUENCER_180              0x30B4
+#define WM8996_WRITE_SEQUENCER_181              0x30B5
+#define WM8996_WRITE_SEQUENCER_182              0x30B6
+#define WM8996_WRITE_SEQUENCER_183              0x30B7
+#define WM8996_WRITE_SEQUENCER_184              0x30B8
+#define WM8996_WRITE_SEQUENCER_185              0x30B9
+#define WM8996_WRITE_SEQUENCER_186              0x30BA
+#define WM8996_WRITE_SEQUENCER_187              0x30BB
+#define WM8996_WRITE_SEQUENCER_188              0x30BC
+#define WM8996_WRITE_SEQUENCER_189              0x30BD
+#define WM8996_WRITE_SEQUENCER_190              0x30BE
+#define WM8996_WRITE_SEQUENCER_191              0x30BF
+#define WM8996_WRITE_SEQUENCER_192              0x30C0
+#define WM8996_WRITE_SEQUENCER_193              0x30C1
+#define WM8996_WRITE_SEQUENCER_194              0x30C2
+#define WM8996_WRITE_SEQUENCER_195              0x30C3
+#define WM8996_WRITE_SEQUENCER_196              0x30C4
+#define WM8996_WRITE_SEQUENCER_197              0x30C5
+#define WM8996_WRITE_SEQUENCER_198              0x30C6
+#define WM8996_WRITE_SEQUENCER_199              0x30C7
+#define WM8996_WRITE_SEQUENCER_200              0x30C8
+#define WM8996_WRITE_SEQUENCER_201              0x30C9
+#define WM8996_WRITE_SEQUENCER_202              0x30CA
+#define WM8996_WRITE_SEQUENCER_203              0x30CB
+#define WM8996_WRITE_SEQUENCER_204              0x30CC
+#define WM8996_WRITE_SEQUENCER_205              0x30CD
+#define WM8996_WRITE_SEQUENCER_206              0x30CE
+#define WM8996_WRITE_SEQUENCER_207              0x30CF
+#define WM8996_WRITE_SEQUENCER_208              0x30D0
+#define WM8996_WRITE_SEQUENCER_209              0x30D1
+#define WM8996_WRITE_SEQUENCER_210              0x30D2
+#define WM8996_WRITE_SEQUENCER_211              0x30D3
+#define WM8996_WRITE_SEQUENCER_212              0x30D4
+#define WM8996_WRITE_SEQUENCER_213              0x30D5
+#define WM8996_WRITE_SEQUENCER_214              0x30D6
+#define WM8996_WRITE_SEQUENCER_215              0x30D7
+#define WM8996_WRITE_SEQUENCER_216              0x30D8
+#define WM8996_WRITE_SEQUENCER_217              0x30D9
+#define WM8996_WRITE_SEQUENCER_218              0x30DA
+#define WM8996_WRITE_SEQUENCER_219              0x30DB
+#define WM8996_WRITE_SEQUENCER_220              0x30DC
+#define WM8996_WRITE_SEQUENCER_221              0x30DD
+#define WM8996_WRITE_SEQUENCER_222              0x30DE
+#define WM8996_WRITE_SEQUENCER_223              0x30DF
+#define WM8996_WRITE_SEQUENCER_224              0x30E0
+#define WM8996_WRITE_SEQUENCER_225              0x30E1
+#define WM8996_WRITE_SEQUENCER_226              0x30E2
+#define WM8996_WRITE_SEQUENCER_227              0x30E3
+#define WM8996_WRITE_SEQUENCER_228              0x30E4
+#define WM8996_WRITE_SEQUENCER_229              0x30E5
+#define WM8996_WRITE_SEQUENCER_230              0x30E6
+#define WM8996_WRITE_SEQUENCER_231              0x30E7
+#define WM8996_WRITE_SEQUENCER_232              0x30E8
+#define WM8996_WRITE_SEQUENCER_233              0x30E9
+#define WM8996_WRITE_SEQUENCER_234              0x30EA
+#define WM8996_WRITE_SEQUENCER_235              0x30EB
+#define WM8996_WRITE_SEQUENCER_236              0x30EC
+#define WM8996_WRITE_SEQUENCER_237              0x30ED
+#define WM8996_WRITE_SEQUENCER_238              0x30EE
+#define WM8996_WRITE_SEQUENCER_239              0x30EF
+#define WM8996_WRITE_SEQUENCER_240              0x30F0
+#define WM8996_WRITE_SEQUENCER_241              0x30F1
+#define WM8996_WRITE_SEQUENCER_242              0x30F2
+#define WM8996_WRITE_SEQUENCER_243              0x30F3
+#define WM8996_WRITE_SEQUENCER_244              0x30F4
+#define WM8996_WRITE_SEQUENCER_245              0x30F5
+#define WM8996_WRITE_SEQUENCER_246              0x30F6
+#define WM8996_WRITE_SEQUENCER_247              0x30F7
+#define WM8996_WRITE_SEQUENCER_248              0x30F8
+#define WM8996_WRITE_SEQUENCER_249              0x30F9
+#define WM8996_WRITE_SEQUENCER_250              0x30FA
+#define WM8996_WRITE_SEQUENCER_251              0x30FB
+#define WM8996_WRITE_SEQUENCER_252              0x30FC
+#define WM8996_WRITE_SEQUENCER_253              0x30FD
+#define WM8996_WRITE_SEQUENCER_254              0x30FE
+#define WM8996_WRITE_SEQUENCER_255              0x30FF
+#define WM8996_WRITE_SEQUENCER_256              0x3100
+#define WM8996_WRITE_SEQUENCER_257              0x3101
+#define WM8996_WRITE_SEQUENCER_258              0x3102
+#define WM8996_WRITE_SEQUENCER_259              0x3103
+#define WM8996_WRITE_SEQUENCER_260              0x3104
+#define WM8996_WRITE_SEQUENCER_261              0x3105
+#define WM8996_WRITE_SEQUENCER_262              0x3106
+#define WM8996_WRITE_SEQUENCER_263              0x3107
+#define WM8996_WRITE_SEQUENCER_264              0x3108
+#define WM8996_WRITE_SEQUENCER_265              0x3109
+#define WM8996_WRITE_SEQUENCER_266              0x310A
+#define WM8996_WRITE_SEQUENCER_267              0x310B
+#define WM8996_WRITE_SEQUENCER_268              0x310C
+#define WM8996_WRITE_SEQUENCER_269              0x310D
+#define WM8996_WRITE_SEQUENCER_270              0x310E
+#define WM8996_WRITE_SEQUENCER_271              0x310F
+#define WM8996_WRITE_SEQUENCER_272              0x3110
+#define WM8996_WRITE_SEQUENCER_273              0x3111
+#define WM8996_WRITE_SEQUENCER_274              0x3112
+#define WM8996_WRITE_SEQUENCER_275              0x3113
+#define WM8996_WRITE_SEQUENCER_276              0x3114
+#define WM8996_WRITE_SEQUENCER_277              0x3115
+#define WM8996_WRITE_SEQUENCER_278              0x3116
+#define WM8996_WRITE_SEQUENCER_279              0x3117
+#define WM8996_WRITE_SEQUENCER_280              0x3118
+#define WM8996_WRITE_SEQUENCER_281              0x3119
+#define WM8996_WRITE_SEQUENCER_282              0x311A
+#define WM8996_WRITE_SEQUENCER_283              0x311B
+#define WM8996_WRITE_SEQUENCER_284              0x311C
+#define WM8996_WRITE_SEQUENCER_285              0x311D
+#define WM8996_WRITE_SEQUENCER_286              0x311E
+#define WM8996_WRITE_SEQUENCER_287              0x311F
+#define WM8996_WRITE_SEQUENCER_288              0x3120
+#define WM8996_WRITE_SEQUENCER_289              0x3121
+#define WM8996_WRITE_SEQUENCER_290              0x3122
+#define WM8996_WRITE_SEQUENCER_291              0x3123
+#define WM8996_WRITE_SEQUENCER_292              0x3124
+#define WM8996_WRITE_SEQUENCER_293              0x3125
+#define WM8996_WRITE_SEQUENCER_294              0x3126
+#define WM8996_WRITE_SEQUENCER_295              0x3127
+#define WM8996_WRITE_SEQUENCER_296              0x3128
+#define WM8996_WRITE_SEQUENCER_297              0x3129
+#define WM8996_WRITE_SEQUENCER_298              0x312A
+#define WM8996_WRITE_SEQUENCER_299              0x312B
+#define WM8996_WRITE_SEQUENCER_300              0x312C
+#define WM8996_WRITE_SEQUENCER_301              0x312D
+#define WM8996_WRITE_SEQUENCER_302              0x312E
+#define WM8996_WRITE_SEQUENCER_303              0x312F
+#define WM8996_WRITE_SEQUENCER_304              0x3130
+#define WM8996_WRITE_SEQUENCER_305              0x3131
+#define WM8996_WRITE_SEQUENCER_306              0x3132
+#define WM8996_WRITE_SEQUENCER_307              0x3133
+#define WM8996_WRITE_SEQUENCER_308              0x3134
+#define WM8996_WRITE_SEQUENCER_309              0x3135
+#define WM8996_WRITE_SEQUENCER_310              0x3136
+#define WM8996_WRITE_SEQUENCER_311              0x3137
+#define WM8996_WRITE_SEQUENCER_312              0x3138
+#define WM8996_WRITE_SEQUENCER_313              0x3139
+#define WM8996_WRITE_SEQUENCER_314              0x313A
+#define WM8996_WRITE_SEQUENCER_315              0x313B
+#define WM8996_WRITE_SEQUENCER_316              0x313C
+#define WM8996_WRITE_SEQUENCER_317              0x313D
+#define WM8996_WRITE_SEQUENCER_318              0x313E
+#define WM8996_WRITE_SEQUENCER_319              0x313F
+#define WM8996_WRITE_SEQUENCER_320              0x3140
+#define WM8996_WRITE_SEQUENCER_321              0x3141
+#define WM8996_WRITE_SEQUENCER_322              0x3142
+#define WM8996_WRITE_SEQUENCER_323              0x3143
+#define WM8996_WRITE_SEQUENCER_324              0x3144
+#define WM8996_WRITE_SEQUENCER_325              0x3145
+#define WM8996_WRITE_SEQUENCER_326              0x3146
+#define WM8996_WRITE_SEQUENCER_327              0x3147
+#define WM8996_WRITE_SEQUENCER_328              0x3148
+#define WM8996_WRITE_SEQUENCER_329              0x3149
+#define WM8996_WRITE_SEQUENCER_330              0x314A
+#define WM8996_WRITE_SEQUENCER_331              0x314B
+#define WM8996_WRITE_SEQUENCER_332              0x314C
+#define WM8996_WRITE_SEQUENCER_333              0x314D
+#define WM8996_WRITE_SEQUENCER_334              0x314E
+#define WM8996_WRITE_SEQUENCER_335              0x314F
+#define WM8996_WRITE_SEQUENCER_336              0x3150
+#define WM8996_WRITE_SEQUENCER_337              0x3151
+#define WM8996_WRITE_SEQUENCER_338              0x3152
+#define WM8996_WRITE_SEQUENCER_339              0x3153
+#define WM8996_WRITE_SEQUENCER_340              0x3154
+#define WM8996_WRITE_SEQUENCER_341              0x3155
+#define WM8996_WRITE_SEQUENCER_342              0x3156
+#define WM8996_WRITE_SEQUENCER_343              0x3157
+#define WM8996_WRITE_SEQUENCER_344              0x3158
+#define WM8996_WRITE_SEQUENCER_345              0x3159
+#define WM8996_WRITE_SEQUENCER_346              0x315A
+#define WM8996_WRITE_SEQUENCER_347              0x315B
+#define WM8996_WRITE_SEQUENCER_348              0x315C
+#define WM8996_WRITE_SEQUENCER_349              0x315D
+#define WM8996_WRITE_SEQUENCER_350              0x315E
+#define WM8996_WRITE_SEQUENCER_351              0x315F
+#define WM8996_WRITE_SEQUENCER_352              0x3160
+#define WM8996_WRITE_SEQUENCER_353              0x3161
+#define WM8996_WRITE_SEQUENCER_354              0x3162
+#define WM8996_WRITE_SEQUENCER_355              0x3163
+#define WM8996_WRITE_SEQUENCER_356              0x3164
+#define WM8996_WRITE_SEQUENCER_357              0x3165
+#define WM8996_WRITE_SEQUENCER_358              0x3166
+#define WM8996_WRITE_SEQUENCER_359              0x3167
+#define WM8996_WRITE_SEQUENCER_360              0x3168
+#define WM8996_WRITE_SEQUENCER_361              0x3169
+#define WM8996_WRITE_SEQUENCER_362              0x316A
+#define WM8996_WRITE_SEQUENCER_363              0x316B
+#define WM8996_WRITE_SEQUENCER_364              0x316C
+#define WM8996_WRITE_SEQUENCER_365              0x316D
+#define WM8996_WRITE_SEQUENCER_366              0x316E
+#define WM8996_WRITE_SEQUENCER_367              0x316F
+#define WM8996_WRITE_SEQUENCER_368              0x3170
+#define WM8996_WRITE_SEQUENCER_369              0x3171
+#define WM8996_WRITE_SEQUENCER_370              0x3172
+#define WM8996_WRITE_SEQUENCER_371              0x3173
+#define WM8996_WRITE_SEQUENCER_372              0x3174
+#define WM8996_WRITE_SEQUENCER_373              0x3175
+#define WM8996_WRITE_SEQUENCER_374              0x3176
+#define WM8996_WRITE_SEQUENCER_375              0x3177
+#define WM8996_WRITE_SEQUENCER_376              0x3178
+#define WM8996_WRITE_SEQUENCER_377              0x3179
+#define WM8996_WRITE_SEQUENCER_378              0x317A
+#define WM8996_WRITE_SEQUENCER_379              0x317B
+#define WM8996_WRITE_SEQUENCER_380              0x317C
+#define WM8996_WRITE_SEQUENCER_381              0x317D
+#define WM8996_WRITE_SEQUENCER_382              0x317E
+#define WM8996_WRITE_SEQUENCER_383              0x317F
+#define WM8996_WRITE_SEQUENCER_384              0x3180
+#define WM8996_WRITE_SEQUENCER_385              0x3181
+#define WM8996_WRITE_SEQUENCER_386              0x3182
+#define WM8996_WRITE_SEQUENCER_387              0x3183
+#define WM8996_WRITE_SEQUENCER_388              0x3184
+#define WM8996_WRITE_SEQUENCER_389              0x3185
+#define WM8996_WRITE_SEQUENCER_390              0x3186
+#define WM8996_WRITE_SEQUENCER_391              0x3187
+#define WM8996_WRITE_SEQUENCER_392              0x3188
+#define WM8996_WRITE_SEQUENCER_393              0x3189
+#define WM8996_WRITE_SEQUENCER_394              0x318A
+#define WM8996_WRITE_SEQUENCER_395              0x318B
+#define WM8996_WRITE_SEQUENCER_396              0x318C
+#define WM8996_WRITE_SEQUENCER_397              0x318D
+#define WM8996_WRITE_SEQUENCER_398              0x318E
+#define WM8996_WRITE_SEQUENCER_399              0x318F
+#define WM8996_WRITE_SEQUENCER_400              0x3190
+#define WM8996_WRITE_SEQUENCER_401              0x3191
+#define WM8996_WRITE_SEQUENCER_402              0x3192
+#define WM8996_WRITE_SEQUENCER_403              0x3193
+#define WM8996_WRITE_SEQUENCER_404              0x3194
+#define WM8996_WRITE_SEQUENCER_405              0x3195
+#define WM8996_WRITE_SEQUENCER_406              0x3196
+#define WM8996_WRITE_SEQUENCER_407              0x3197
+#define WM8996_WRITE_SEQUENCER_408              0x3198
+#define WM8996_WRITE_SEQUENCER_409              0x3199
+#define WM8996_WRITE_SEQUENCER_410              0x319A
+#define WM8996_WRITE_SEQUENCER_411              0x319B
+#define WM8996_WRITE_SEQUENCER_412              0x319C
+#define WM8996_WRITE_SEQUENCER_413              0x319D
+#define WM8996_WRITE_SEQUENCER_414              0x319E
+#define WM8996_WRITE_SEQUENCER_415              0x319F
+#define WM8996_WRITE_SEQUENCER_416              0x31A0
+#define WM8996_WRITE_SEQUENCER_417              0x31A1
+#define WM8996_WRITE_SEQUENCER_418              0x31A2
+#define WM8996_WRITE_SEQUENCER_419              0x31A3
+#define WM8996_WRITE_SEQUENCER_420              0x31A4
+#define WM8996_WRITE_SEQUENCER_421              0x31A5
+#define WM8996_WRITE_SEQUENCER_422              0x31A6
+#define WM8996_WRITE_SEQUENCER_423              0x31A7
+#define WM8996_WRITE_SEQUENCER_424              0x31A8
+#define WM8996_WRITE_SEQUENCER_425              0x31A9
+#define WM8996_WRITE_SEQUENCER_426              0x31AA
+#define WM8996_WRITE_SEQUENCER_427              0x31AB
+#define WM8996_WRITE_SEQUENCER_428              0x31AC
+#define WM8996_WRITE_SEQUENCER_429              0x31AD
+#define WM8996_WRITE_SEQUENCER_430              0x31AE
+#define WM8996_WRITE_SEQUENCER_431              0x31AF
+#define WM8996_WRITE_SEQUENCER_432              0x31B0
+#define WM8996_WRITE_SEQUENCER_433              0x31B1
+#define WM8996_WRITE_SEQUENCER_434              0x31B2
+#define WM8996_WRITE_SEQUENCER_435              0x31B3
+#define WM8996_WRITE_SEQUENCER_436              0x31B4
+#define WM8996_WRITE_SEQUENCER_437              0x31B5
+#define WM8996_WRITE_SEQUENCER_438              0x31B6
+#define WM8996_WRITE_SEQUENCER_439              0x31B7
+#define WM8996_WRITE_SEQUENCER_440              0x31B8
+#define WM8996_WRITE_SEQUENCER_441              0x31B9
+#define WM8996_WRITE_SEQUENCER_442              0x31BA
+#define WM8996_WRITE_SEQUENCER_443              0x31BB
+#define WM8996_WRITE_SEQUENCER_444              0x31BC
+#define WM8996_WRITE_SEQUENCER_445              0x31BD
+#define WM8996_WRITE_SEQUENCER_446              0x31BE
+#define WM8996_WRITE_SEQUENCER_447              0x31BF
+#define WM8996_WRITE_SEQUENCER_448              0x31C0
+#define WM8996_WRITE_SEQUENCER_449              0x31C1
+#define WM8996_WRITE_SEQUENCER_450              0x31C2
+#define WM8996_WRITE_SEQUENCER_451              0x31C3
+#define WM8996_WRITE_SEQUENCER_452              0x31C4
+#define WM8996_WRITE_SEQUENCER_453              0x31C5
+#define WM8996_WRITE_SEQUENCER_454              0x31C6
+#define WM8996_WRITE_SEQUENCER_455              0x31C7
+#define WM8996_WRITE_SEQUENCER_456              0x31C8
+#define WM8996_WRITE_SEQUENCER_457              0x31C9
+#define WM8996_WRITE_SEQUENCER_458              0x31CA
+#define WM8996_WRITE_SEQUENCER_459              0x31CB
+#define WM8996_WRITE_SEQUENCER_460              0x31CC
+#define WM8996_WRITE_SEQUENCER_461              0x31CD
+#define WM8996_WRITE_SEQUENCER_462              0x31CE
+#define WM8996_WRITE_SEQUENCER_463              0x31CF
+#define WM8996_WRITE_SEQUENCER_464              0x31D0
+#define WM8996_WRITE_SEQUENCER_465              0x31D1
+#define WM8996_WRITE_SEQUENCER_466              0x31D2
+#define WM8996_WRITE_SEQUENCER_467              0x31D3
+#define WM8996_WRITE_SEQUENCER_468              0x31D4
+#define WM8996_WRITE_SEQUENCER_469              0x31D5
+#define WM8996_WRITE_SEQUENCER_470              0x31D6
+#define WM8996_WRITE_SEQUENCER_471              0x31D7
+#define WM8996_WRITE_SEQUENCER_472              0x31D8
+#define WM8996_WRITE_SEQUENCER_473              0x31D9
+#define WM8996_WRITE_SEQUENCER_474              0x31DA
+#define WM8996_WRITE_SEQUENCER_475              0x31DB
+#define WM8996_WRITE_SEQUENCER_476              0x31DC
+#define WM8996_WRITE_SEQUENCER_477              0x31DD
+#define WM8996_WRITE_SEQUENCER_478              0x31DE
+#define WM8996_WRITE_SEQUENCER_479              0x31DF
+#define WM8996_WRITE_SEQUENCER_480              0x31E0
+#define WM8996_WRITE_SEQUENCER_481              0x31E1
+#define WM8996_WRITE_SEQUENCER_482              0x31E2
+#define WM8996_WRITE_SEQUENCER_483              0x31E3
+#define WM8996_WRITE_SEQUENCER_484              0x31E4
+#define WM8996_WRITE_SEQUENCER_485              0x31E5
+#define WM8996_WRITE_SEQUENCER_486              0x31E6
+#define WM8996_WRITE_SEQUENCER_487              0x31E7
+#define WM8996_WRITE_SEQUENCER_488              0x31E8
+#define WM8996_WRITE_SEQUENCER_489              0x31E9
+#define WM8996_WRITE_SEQUENCER_490              0x31EA
+#define WM8996_WRITE_SEQUENCER_491              0x31EB
+#define WM8996_WRITE_SEQUENCER_492              0x31EC
+#define WM8996_WRITE_SEQUENCER_493              0x31ED
+#define WM8996_WRITE_SEQUENCER_494              0x31EE
+#define WM8996_WRITE_SEQUENCER_495              0x31EF
+#define WM8996_WRITE_SEQUENCER_496              0x31F0
+#define WM8996_WRITE_SEQUENCER_497              0x31F1
+#define WM8996_WRITE_SEQUENCER_498              0x31F2
+#define WM8996_WRITE_SEQUENCER_499              0x31F3
+#define WM8996_WRITE_SEQUENCER_500              0x31F4
+#define WM8996_WRITE_SEQUENCER_501              0x31F5
+#define WM8996_WRITE_SEQUENCER_502              0x31F6
+#define WM8996_WRITE_SEQUENCER_503              0x31F7
+#define WM8996_WRITE_SEQUENCER_504              0x31F8
+#define WM8996_WRITE_SEQUENCER_505              0x31F9
+#define WM8996_WRITE_SEQUENCER_506              0x31FA
+#define WM8996_WRITE_SEQUENCER_507              0x31FB
+#define WM8996_WRITE_SEQUENCER_508              0x31FC
+#define WM8996_WRITE_SEQUENCER_509              0x31FD
+#define WM8996_WRITE_SEQUENCER_510              0x31FE
+#define WM8996_WRITE_SEQUENCER_511              0x31FF
+
+#define WM8996_REGISTER_COUNT                   706
+#define WM8996_MAX_REGISTER                     0x31FF
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Software Reset
+ */
+#define WM8996_SW_RESET_MASK                    0xFFFF  /* SW_RESET - [15:0] */
+#define WM8996_SW_RESET_SHIFT                        0  /* SW_RESET - [15:0] */
+#define WM8996_SW_RESET_WIDTH                       16  /* SW_RESET - [15:0] */
+
+/*
+ * R1 (0x01) - Power Management (1)
+ */
+#define WM8996_MICB2_ENA                        0x0200  /* MICB2_ENA */
+#define WM8996_MICB2_ENA_MASK                   0x0200  /* MICB2_ENA */
+#define WM8996_MICB2_ENA_SHIFT                       9  /* MICB2_ENA */
+#define WM8996_MICB2_ENA_WIDTH                       1  /* MICB2_ENA */
+#define WM8996_MICB1_ENA                        0x0100  /* MICB1_ENA */
+#define WM8996_MICB1_ENA_MASK                   0x0100  /* MICB1_ENA */
+#define WM8996_MICB1_ENA_SHIFT                       8  /* MICB1_ENA */
+#define WM8996_MICB1_ENA_WIDTH                       1  /* MICB1_ENA */
+#define WM8996_HPOUT2L_ENA                      0x0080  /* HPOUT2L_ENA */
+#define WM8996_HPOUT2L_ENA_MASK                 0x0080  /* HPOUT2L_ENA */
+#define WM8996_HPOUT2L_ENA_SHIFT                     7  /* HPOUT2L_ENA */
+#define WM8996_HPOUT2L_ENA_WIDTH                     1  /* HPOUT2L_ENA */
+#define WM8996_HPOUT2R_ENA                      0x0040  /* HPOUT2R_ENA */
+#define WM8996_HPOUT2R_ENA_MASK                 0x0040  /* HPOUT2R_ENA */
+#define WM8996_HPOUT2R_ENA_SHIFT                     6  /* HPOUT2R_ENA */
+#define WM8996_HPOUT2R_ENA_WIDTH                     1  /* HPOUT2R_ENA */
+#define WM8996_HPOUT1L_ENA                      0x0020  /* HPOUT1L_ENA */
+#define WM8996_HPOUT1L_ENA_MASK                 0x0020  /* HPOUT1L_ENA */
+#define WM8996_HPOUT1L_ENA_SHIFT                     5  /* HPOUT1L_ENA */
+#define WM8996_HPOUT1L_ENA_WIDTH                     1  /* HPOUT1L_ENA */
+#define WM8996_HPOUT1R_ENA                      0x0010  /* HPOUT1R_ENA */
+#define WM8996_HPOUT1R_ENA_MASK                 0x0010  /* HPOUT1R_ENA */
+#define WM8996_HPOUT1R_ENA_SHIFT                     4  /* HPOUT1R_ENA */
+#define WM8996_HPOUT1R_ENA_WIDTH                     1  /* HPOUT1R_ENA */
+#define WM8996_BG_ENA                           0x0001  /* BG_ENA */
+#define WM8996_BG_ENA_MASK                      0x0001  /* BG_ENA */
+#define WM8996_BG_ENA_SHIFT                          0  /* BG_ENA */
+#define WM8996_BG_ENA_WIDTH                          1  /* BG_ENA */
+
+/*
+ * R2 (0x02) - Power Management (2)
+ */
+#define WM8996_OPCLK_ENA                        0x0800  /* OPCLK_ENA */
+#define WM8996_OPCLK_ENA_MASK                   0x0800  /* OPCLK_ENA */
+#define WM8996_OPCLK_ENA_SHIFT                      11  /* OPCLK_ENA */
+#define WM8996_OPCLK_ENA_WIDTH                       1  /* OPCLK_ENA */
+#define WM8996_INL_ENA                          0x0020  /* INL_ENA */
+#define WM8996_INL_ENA_MASK                     0x0020  /* INL_ENA */
+#define WM8996_INL_ENA_SHIFT                         5  /* INL_ENA */
+#define WM8996_INL_ENA_WIDTH                         1  /* INL_ENA */
+#define WM8996_INR_ENA                          0x0010  /* INR_ENA */
+#define WM8996_INR_ENA_MASK                     0x0010  /* INR_ENA */
+#define WM8996_INR_ENA_SHIFT                         4  /* INR_ENA */
+#define WM8996_INR_ENA_WIDTH                         1  /* INR_ENA */
+#define WM8996_LDO2_ENA                         0x0002  /* LDO2_ENA */
+#define WM8996_LDO2_ENA_MASK                    0x0002  /* LDO2_ENA */
+#define WM8996_LDO2_ENA_SHIFT                        1  /* LDO2_ENA */
+#define WM8996_LDO2_ENA_WIDTH                        1  /* LDO2_ENA */
+
+/*
+ * R3 (0x03) - Power Management (3)
+ */
+#define WM8996_DSP2RXL_ENA                      0x0800  /* DSP2RXL_ENA */
+#define WM8996_DSP2RXL_ENA_MASK                 0x0800  /* DSP2RXL_ENA */
+#define WM8996_DSP2RXL_ENA_SHIFT                    11  /* DSP2RXL_ENA */
+#define WM8996_DSP2RXL_ENA_WIDTH                     1  /* DSP2RXL_ENA */
+#define WM8996_DSP2RXR_ENA                      0x0400  /* DSP2RXR_ENA */
+#define WM8996_DSP2RXR_ENA_MASK                 0x0400  /* DSP2RXR_ENA */
+#define WM8996_DSP2RXR_ENA_SHIFT                    10  /* DSP2RXR_ENA */
+#define WM8996_DSP2RXR_ENA_WIDTH                     1  /* DSP2RXR_ENA */
+#define WM8996_DSP1RXL_ENA                      0x0200  /* DSP1RXL_ENA */
+#define WM8996_DSP1RXL_ENA_MASK                 0x0200  /* DSP1RXL_ENA */
+#define WM8996_DSP1RXL_ENA_SHIFT                     9  /* DSP1RXL_ENA */
+#define WM8996_DSP1RXL_ENA_WIDTH                     1  /* DSP1RXL_ENA */
+#define WM8996_DSP1RXR_ENA                      0x0100  /* DSP1RXR_ENA */
+#define WM8996_DSP1RXR_ENA_MASK                 0x0100  /* DSP1RXR_ENA */
+#define WM8996_DSP1RXR_ENA_SHIFT                     8  /* DSP1RXR_ENA */
+#define WM8996_DSP1RXR_ENA_WIDTH                     1  /* DSP1RXR_ENA */
+#define WM8996_DMIC2L_ENA                       0x0020  /* DMIC2L_ENA */
+#define WM8996_DMIC2L_ENA_MASK                  0x0020  /* DMIC2L_ENA */
+#define WM8996_DMIC2L_ENA_SHIFT                      5  /* DMIC2L_ENA */
+#define WM8996_DMIC2L_ENA_WIDTH                      1  /* DMIC2L_ENA */
+#define WM8996_DMIC2R_ENA                       0x0010  /* DMIC2R_ENA */
+#define WM8996_DMIC2R_ENA_MASK                  0x0010  /* DMIC2R_ENA */
+#define WM8996_DMIC2R_ENA_SHIFT                      4  /* DMIC2R_ENA */
+#define WM8996_DMIC2R_ENA_WIDTH                      1  /* DMIC2R_ENA */
+#define WM8996_DMIC1L_ENA                       0x0008  /* DMIC1L_ENA */
+#define WM8996_DMIC1L_ENA_MASK                  0x0008  /* DMIC1L_ENA */
+#define WM8996_DMIC1L_ENA_SHIFT                      3  /* DMIC1L_ENA */
+#define WM8996_DMIC1L_ENA_WIDTH                      1  /* DMIC1L_ENA */
+#define WM8996_DMIC1R_ENA                       0x0004  /* DMIC1R_ENA */
+#define WM8996_DMIC1R_ENA_MASK                  0x0004  /* DMIC1R_ENA */
+#define WM8996_DMIC1R_ENA_SHIFT                      2  /* DMIC1R_ENA */
+#define WM8996_DMIC1R_ENA_WIDTH                      1  /* DMIC1R_ENA */
+#define WM8996_ADCL_ENA                         0x0002  /* ADCL_ENA */
+#define WM8996_ADCL_ENA_MASK                    0x0002  /* ADCL_ENA */
+#define WM8996_ADCL_ENA_SHIFT                        1  /* ADCL_ENA */
+#define WM8996_ADCL_ENA_WIDTH                        1  /* ADCL_ENA */
+#define WM8996_ADCR_ENA                         0x0001  /* ADCR_ENA */
+#define WM8996_ADCR_ENA_MASK                    0x0001  /* ADCR_ENA */
+#define WM8996_ADCR_ENA_SHIFT                        0  /* ADCR_ENA */
+#define WM8996_ADCR_ENA_WIDTH                        1  /* ADCR_ENA */
+
+/*
+ * R4 (0x04) - Power Management (4)
+ */
+#define WM8996_AIF2RX_CHAN1_ENA                 0x0200  /* AIF2RX_CHAN1_ENA */
+#define WM8996_AIF2RX_CHAN1_ENA_MASK            0x0200  /* AIF2RX_CHAN1_ENA */
+#define WM8996_AIF2RX_CHAN1_ENA_SHIFT                9  /* AIF2RX_CHAN1_ENA */
+#define WM8996_AIF2RX_CHAN1_ENA_WIDTH                1  /* AIF2RX_CHAN1_ENA */
+#define WM8996_AIF2RX_CHAN0_ENA                 0x0100  /* AIF2RX_CHAN0_ENA */
+#define WM8996_AIF2RX_CHAN0_ENA_MASK            0x0100  /* AIF2RX_CHAN0_ENA */
+#define WM8996_AIF2RX_CHAN0_ENA_SHIFT                8  /* AIF2RX_CHAN0_ENA */
+#define WM8996_AIF2RX_CHAN0_ENA_WIDTH                1  /* AIF2RX_CHAN0_ENA */
+#define WM8996_AIF1RX_CHAN5_ENA                 0x0020  /* AIF1RX_CHAN5_ENA */
+#define WM8996_AIF1RX_CHAN5_ENA_MASK            0x0020  /* AIF1RX_CHAN5_ENA */
+#define WM8996_AIF1RX_CHAN5_ENA_SHIFT                5  /* AIF1RX_CHAN5_ENA */
+#define WM8996_AIF1RX_CHAN5_ENA_WIDTH                1  /* AIF1RX_CHAN5_ENA */
+#define WM8996_AIF1RX_CHAN4_ENA                 0x0010  /* AIF1RX_CHAN4_ENA */
+#define WM8996_AIF1RX_CHAN4_ENA_MASK            0x0010  /* AIF1RX_CHAN4_ENA */
+#define WM8996_AIF1RX_CHAN4_ENA_SHIFT                4  /* AIF1RX_CHAN4_ENA */
+#define WM8996_AIF1RX_CHAN4_ENA_WIDTH                1  /* AIF1RX_CHAN4_ENA */
+#define WM8996_AIF1RX_CHAN3_ENA                 0x0008  /* AIF1RX_CHAN3_ENA */
+#define WM8996_AIF1RX_CHAN3_ENA_MASK            0x0008  /* AIF1RX_CHAN3_ENA */
+#define WM8996_AIF1RX_CHAN3_ENA_SHIFT                3  /* AIF1RX_CHAN3_ENA */
+#define WM8996_AIF1RX_CHAN3_ENA_WIDTH                1  /* AIF1RX_CHAN3_ENA */
+#define WM8996_AIF1RX_CHAN2_ENA                 0x0004  /* AIF1RX_CHAN2_ENA */
+#define WM8996_AIF1RX_CHAN2_ENA_MASK            0x0004  /* AIF1RX_CHAN2_ENA */
+#define WM8996_AIF1RX_CHAN2_ENA_SHIFT                2  /* AIF1RX_CHAN2_ENA */
+#define WM8996_AIF1RX_CHAN2_ENA_WIDTH                1  /* AIF1RX_CHAN2_ENA */
+#define WM8996_AIF1RX_CHAN1_ENA                 0x0002  /* AIF1RX_CHAN1_ENA */
+#define WM8996_AIF1RX_CHAN1_ENA_MASK            0x0002  /* AIF1RX_CHAN1_ENA */
+#define WM8996_AIF1RX_CHAN1_ENA_SHIFT                1  /* AIF1RX_CHAN1_ENA */
+#define WM8996_AIF1RX_CHAN1_ENA_WIDTH                1  /* AIF1RX_CHAN1_ENA */
+#define WM8996_AIF1RX_CHAN0_ENA                 0x0001  /* AIF1RX_CHAN0_ENA */
+#define WM8996_AIF1RX_CHAN0_ENA_MASK            0x0001  /* AIF1RX_CHAN0_ENA */
+#define WM8996_AIF1RX_CHAN0_ENA_SHIFT                0  /* AIF1RX_CHAN0_ENA */
+#define WM8996_AIF1RX_CHAN0_ENA_WIDTH                1  /* AIF1RX_CHAN0_ENA */
+
+/*
+ * R5 (0x05) - Power Management (5)
+ */
+#define WM8996_DSP2TXL_ENA                      0x0800  /* DSP2TXL_ENA */
+#define WM8996_DSP2TXL_ENA_MASK                 0x0800  /* DSP2TXL_ENA */
+#define WM8996_DSP2TXL_ENA_SHIFT                    11  /* DSP2TXL_ENA */
+#define WM8996_DSP2TXL_ENA_WIDTH                     1  /* DSP2TXL_ENA */
+#define WM8996_DSP2TXR_ENA                      0x0400  /* DSP2TXR_ENA */
+#define WM8996_DSP2TXR_ENA_MASK                 0x0400  /* DSP2TXR_ENA */
+#define WM8996_DSP2TXR_ENA_SHIFT                    10  /* DSP2TXR_ENA */
+#define WM8996_DSP2TXR_ENA_WIDTH                     1  /* DSP2TXR_ENA */
+#define WM8996_DSP1TXL_ENA                      0x0200  /* DSP1TXL_ENA */
+#define WM8996_DSP1TXL_ENA_MASK                 0x0200  /* DSP1TXL_ENA */
+#define WM8996_DSP1TXL_ENA_SHIFT                     9  /* DSP1TXL_ENA */
+#define WM8996_DSP1TXL_ENA_WIDTH                     1  /* DSP1TXL_ENA */
+#define WM8996_DSP1TXR_ENA                      0x0100  /* DSP1TXR_ENA */
+#define WM8996_DSP1TXR_ENA_MASK                 0x0100  /* DSP1TXR_ENA */
+#define WM8996_DSP1TXR_ENA_SHIFT                     8  /* DSP1TXR_ENA */
+#define WM8996_DSP1TXR_ENA_WIDTH                     1  /* DSP1TXR_ENA */
+#define WM8996_DAC2L_ENA                        0x0008  /* DAC2L_ENA */
+#define WM8996_DAC2L_ENA_MASK                   0x0008  /* DAC2L_ENA */
+#define WM8996_DAC2L_ENA_SHIFT                       3  /* DAC2L_ENA */
+#define WM8996_DAC2L_ENA_WIDTH                       1  /* DAC2L_ENA */
+#define WM8996_DAC2R_ENA                        0x0004  /* DAC2R_ENA */
+#define WM8996_DAC2R_ENA_MASK                   0x0004  /* DAC2R_ENA */
+#define WM8996_DAC2R_ENA_SHIFT                       2  /* DAC2R_ENA */
+#define WM8996_DAC2R_ENA_WIDTH                       1  /* DAC2R_ENA */
+#define WM8996_DAC1L_ENA                        0x0002  /* DAC1L_ENA */
+#define WM8996_DAC1L_ENA_MASK                   0x0002  /* DAC1L_ENA */
+#define WM8996_DAC1L_ENA_SHIFT                       1  /* DAC1L_ENA */
+#define WM8996_DAC1L_ENA_WIDTH                       1  /* DAC1L_ENA */
+#define WM8996_DAC1R_ENA                        0x0001  /* DAC1R_ENA */
+#define WM8996_DAC1R_ENA_MASK                   0x0001  /* DAC1R_ENA */
+#define WM8996_DAC1R_ENA_SHIFT                       0  /* DAC1R_ENA */
+#define WM8996_DAC1R_ENA_WIDTH                       1  /* DAC1R_ENA */
+
+/*
+ * R6 (0x06) - Power Management (6)
+ */
+#define WM8996_AIF2TX_CHAN1_ENA                 0x0200  /* AIF2TX_CHAN1_ENA */
+#define WM8996_AIF2TX_CHAN1_ENA_MASK            0x0200  /* AIF2TX_CHAN1_ENA */
+#define WM8996_AIF2TX_CHAN1_ENA_SHIFT                9  /* AIF2TX_CHAN1_ENA */
+#define WM8996_AIF2TX_CHAN1_ENA_WIDTH                1  /* AIF2TX_CHAN1_ENA */
+#define WM8996_AIF2TX_CHAN0_ENA                 0x0100  /* AIF2TX_CHAN0_ENA */
+#define WM8996_AIF2TX_CHAN0_ENA_MASK            0x0100  /* AIF2TX_CHAN0_ENA */
+#define WM8996_AIF2TX_CHAN0_ENA_SHIFT                8  /* AIF2TX_CHAN0_ENA */
+#define WM8996_AIF2TX_CHAN0_ENA_WIDTH                1  /* AIF2TX_CHAN0_ENA */
+#define WM8996_AIF1TX_CHAN5_ENA                 0x0020  /* AIF1TX_CHAN5_ENA */
+#define WM8996_AIF1TX_CHAN5_ENA_MASK            0x0020  /* AIF1TX_CHAN5_ENA */
+#define WM8996_AIF1TX_CHAN5_ENA_SHIFT                5  /* AIF1TX_CHAN5_ENA */
+#define WM8996_AIF1TX_CHAN5_ENA_WIDTH                1  /* AIF1TX_CHAN5_ENA */
+#define WM8996_AIF1TX_CHAN4_ENA                 0x0010  /* AIF1TX_CHAN4_ENA */
+#define WM8996_AIF1TX_CHAN4_ENA_MASK            0x0010  /* AIF1TX_CHAN4_ENA */
+#define WM8996_AIF1TX_CHAN4_ENA_SHIFT                4  /* AIF1TX_CHAN4_ENA */
+#define WM8996_AIF1TX_CHAN4_ENA_WIDTH                1  /* AIF1TX_CHAN4_ENA */
+#define WM8996_AIF1TX_CHAN3_ENA                 0x0008  /* AIF1TX_CHAN3_ENA */
+#define WM8996_AIF1TX_CHAN3_ENA_MASK            0x0008  /* AIF1TX_CHAN3_ENA */
+#define WM8996_AIF1TX_CHAN3_ENA_SHIFT                3  /* AIF1TX_CHAN3_ENA */
+#define WM8996_AIF1TX_CHAN3_ENA_WIDTH                1  /* AIF1TX_CHAN3_ENA */
+#define WM8996_AIF1TX_CHAN2_ENA                 0x0004  /* AIF1TX_CHAN2_ENA */
+#define WM8996_AIF1TX_CHAN2_ENA_MASK            0x0004  /* AIF1TX_CHAN2_ENA */
+#define WM8996_AIF1TX_CHAN2_ENA_SHIFT                2  /* AIF1TX_CHAN2_ENA */
+#define WM8996_AIF1TX_CHAN2_ENA_WIDTH                1  /* AIF1TX_CHAN2_ENA */
+#define WM8996_AIF1TX_CHAN1_ENA                 0x0002  /* AIF1TX_CHAN1_ENA */
+#define WM8996_AIF1TX_CHAN1_ENA_MASK            0x0002  /* AIF1TX_CHAN1_ENA */
+#define WM8996_AIF1TX_CHAN1_ENA_SHIFT                1  /* AIF1TX_CHAN1_ENA */
+#define WM8996_AIF1TX_CHAN1_ENA_WIDTH                1  /* AIF1TX_CHAN1_ENA */
+#define WM8996_AIF1TX_CHAN0_ENA                 0x0001  /* AIF1TX_CHAN0_ENA */
+#define WM8996_AIF1TX_CHAN0_ENA_MASK            0x0001  /* AIF1TX_CHAN0_ENA */
+#define WM8996_AIF1TX_CHAN0_ENA_SHIFT                0  /* AIF1TX_CHAN0_ENA */
+#define WM8996_AIF1TX_CHAN0_ENA_WIDTH                1  /* AIF1TX_CHAN0_ENA */
+
+/*
+ * R7 (0x07) - Power Management (7)
+ */
+#define WM8996_DMIC2_FN                         0x0200  /* DMIC2_FN */
+#define WM8996_DMIC2_FN_MASK                    0x0200  /* DMIC2_FN */
+#define WM8996_DMIC2_FN_SHIFT                        9  /* DMIC2_FN */
+#define WM8996_DMIC2_FN_WIDTH                        1  /* DMIC2_FN */
+#define WM8996_DMIC1_FN                         0x0100  /* DMIC1_FN */
+#define WM8996_DMIC1_FN_MASK                    0x0100  /* DMIC1_FN */
+#define WM8996_DMIC1_FN_SHIFT                        8  /* DMIC1_FN */
+#define WM8996_DMIC1_FN_WIDTH                        1  /* DMIC1_FN */
+#define WM8996_ADC_DMIC_DSP2R_ENA               0x0080  /* ADC_DMIC_DSP2R_ENA */
+#define WM8996_ADC_DMIC_DSP2R_ENA_MASK          0x0080  /* ADC_DMIC_DSP2R_ENA */
+#define WM8996_ADC_DMIC_DSP2R_ENA_SHIFT              7  /* ADC_DMIC_DSP2R_ENA */
+#define WM8996_ADC_DMIC_DSP2R_ENA_WIDTH              1  /* ADC_DMIC_DSP2R_ENA */
+#define WM8996_ADC_DMIC_DSP2L_ENA               0x0040  /* ADC_DMIC_DSP2L_ENA */
+#define WM8996_ADC_DMIC_DSP2L_ENA_MASK          0x0040  /* ADC_DMIC_DSP2L_ENA */
+#define WM8996_ADC_DMIC_DSP2L_ENA_SHIFT              6  /* ADC_DMIC_DSP2L_ENA */
+#define WM8996_ADC_DMIC_DSP2L_ENA_WIDTH              1  /* ADC_DMIC_DSP2L_ENA */
+#define WM8996_ADC_DMIC_SRC2_MASK               0x0030  /* ADC_DMIC_SRC2 - [5:4] */
+#define WM8996_ADC_DMIC_SRC2_SHIFT                   4  /* ADC_DMIC_SRC2 - [5:4] */
+#define WM8996_ADC_DMIC_SRC2_WIDTH                   2  /* ADC_DMIC_SRC2 - [5:4] */
+#define WM8996_ADC_DMIC_DSP1R_ENA               0x0008  /* ADC_DMIC_DSP1R_ENA */
+#define WM8996_ADC_DMIC_DSP1R_ENA_MASK          0x0008  /* ADC_DMIC_DSP1R_ENA */
+#define WM8996_ADC_DMIC_DSP1R_ENA_SHIFT              3  /* ADC_DMIC_DSP1R_ENA */
+#define WM8996_ADC_DMIC_DSP1R_ENA_WIDTH              1  /* ADC_DMIC_DSP1R_ENA */
+#define WM8996_ADC_DMIC_DSP1L_ENA               0x0004  /* ADC_DMIC_DSP1L_ENA */
+#define WM8996_ADC_DMIC_DSP1L_ENA_MASK          0x0004  /* ADC_DMIC_DSP1L_ENA */
+#define WM8996_ADC_DMIC_DSP1L_ENA_SHIFT              2  /* ADC_DMIC_DSP1L_ENA */
+#define WM8996_ADC_DMIC_DSP1L_ENA_WIDTH              1  /* ADC_DMIC_DSP1L_ENA */
+#define WM8996_ADC_DMIC_SRC1_MASK               0x0003  /* ADC_DMIC_SRC1 - [1:0] */
+#define WM8996_ADC_DMIC_SRC1_SHIFT                   0  /* ADC_DMIC_SRC1 - [1:0] */
+#define WM8996_ADC_DMIC_SRC1_WIDTH                   2  /* ADC_DMIC_SRC1 - [1:0] */
+
+/*
+ * R8 (0x08) - Power Management (8)
+ */
+#define WM8996_AIF2TX_SRC_MASK                  0x00C0  /* AIF2TX_SRC - [7:6] */
+#define WM8996_AIF2TX_SRC_SHIFT                      6  /* AIF2TX_SRC - [7:6] */
+#define WM8996_AIF2TX_SRC_WIDTH                      2  /* AIF2TX_SRC - [7:6] */
+#define WM8996_DSP2RX_SRC                       0x0010  /* DSP2RX_SRC */
+#define WM8996_DSP2RX_SRC_MASK                  0x0010  /* DSP2RX_SRC */
+#define WM8996_DSP2RX_SRC_SHIFT                      4  /* DSP2RX_SRC */
+#define WM8996_DSP2RX_SRC_WIDTH                      1  /* DSP2RX_SRC */
+#define WM8996_DSP1RX_SRC                       0x0001  /* DSP1RX_SRC */
+#define WM8996_DSP1RX_SRC_MASK                  0x0001  /* DSP1RX_SRC */
+#define WM8996_DSP1RX_SRC_SHIFT                      0  /* DSP1RX_SRC */
+#define WM8996_DSP1RX_SRC_WIDTH                      1  /* DSP1RX_SRC */
+
+/*
+ * R16 (0x10) - Left Line Input Volume
+ */
+#define WM8996_IN1_VU                           0x0080  /* IN1_VU */
+#define WM8996_IN1_VU_MASK                      0x0080  /* IN1_VU */
+#define WM8996_IN1_VU_SHIFT                          7  /* IN1_VU */
+#define WM8996_IN1_VU_WIDTH                          1  /* IN1_VU */
+#define WM8996_IN1L_ZC                          0x0020  /* IN1L_ZC */
+#define WM8996_IN1L_ZC_MASK                     0x0020  /* IN1L_ZC */
+#define WM8996_IN1L_ZC_SHIFT                         5  /* IN1L_ZC */
+#define WM8996_IN1L_ZC_WIDTH                         1  /* IN1L_ZC */
+#define WM8996_IN1L_VOL_MASK                    0x001F  /* IN1L_VOL - [4:0] */
+#define WM8996_IN1L_VOL_SHIFT                        0  /* IN1L_VOL - [4:0] */
+#define WM8996_IN1L_VOL_WIDTH                        5  /* IN1L_VOL - [4:0] */
+
+/*
+ * R17 (0x11) - Right Line Input Volume
+ */
+#define WM8996_IN1_VU                           0x0080  /* IN1_VU */
+#define WM8996_IN1_VU_MASK                      0x0080  /* IN1_VU */
+#define WM8996_IN1_VU_SHIFT                          7  /* IN1_VU */
+#define WM8996_IN1_VU_WIDTH                          1  /* IN1_VU */
+#define WM8996_IN1R_ZC                          0x0020  /* IN1R_ZC */
+#define WM8996_IN1R_ZC_MASK                     0x0020  /* IN1R_ZC */
+#define WM8996_IN1R_ZC_SHIFT                         5  /* IN1R_ZC */
+#define WM8996_IN1R_ZC_WIDTH                         1  /* IN1R_ZC */
+#define WM8996_IN1R_VOL_MASK                    0x001F  /* IN1R_VOL - [4:0] */
+#define WM8996_IN1R_VOL_SHIFT                        0  /* IN1R_VOL - [4:0] */
+#define WM8996_IN1R_VOL_WIDTH                        5  /* IN1R_VOL - [4:0] */
+
+/*
+ * R18 (0x12) - Line Input Control
+ */
+#define WM8996_INL_MODE_MASK                    0x000C  /* INL_MODE - [3:2] */
+#define WM8996_INL_MODE_SHIFT                        2  /* INL_MODE - [3:2] */
+#define WM8996_INL_MODE_WIDTH                        2  /* INL_MODE - [3:2] */
+#define WM8996_INR_MODE_MASK                    0x0003  /* INR_MODE - [1:0] */
+#define WM8996_INR_MODE_SHIFT                        0  /* INR_MODE - [1:0] */
+#define WM8996_INR_MODE_WIDTH                        2  /* INR_MODE - [1:0] */
+
+/*
+ * R21 (0x15) - DAC1 HPOUT1 Volume
+ */
+#define WM8996_DAC1R_HPOUT1R_VOL_MASK           0x00F0  /* DAC1R_HPOUT1R_VOL - [7:4] */
+#define WM8996_DAC1R_HPOUT1R_VOL_SHIFT               4  /* DAC1R_HPOUT1R_VOL - [7:4] */
+#define WM8996_DAC1R_HPOUT1R_VOL_WIDTH               4  /* DAC1R_HPOUT1R_VOL - [7:4] */
+#define WM8996_DAC1L_HPOUT1L_VOL_MASK           0x000F  /* DAC1L_HPOUT1L_VOL - [3:0] */
+#define WM8996_DAC1L_HPOUT1L_VOL_SHIFT               0  /* DAC1L_HPOUT1L_VOL - [3:0] */
+#define WM8996_DAC1L_HPOUT1L_VOL_WIDTH               4  /* DAC1L_HPOUT1L_VOL - [3:0] */
+
+/*
+ * R22 (0x16) - DAC2 HPOUT2 Volume
+ */
+#define WM8996_DAC2R_HPOUT2R_VOL_MASK           0x00F0  /* DAC2R_HPOUT2R_VOL - [7:4] */
+#define WM8996_DAC2R_HPOUT2R_VOL_SHIFT               4  /* DAC2R_HPOUT2R_VOL - [7:4] */
+#define WM8996_DAC2R_HPOUT2R_VOL_WIDTH               4  /* DAC2R_HPOUT2R_VOL - [7:4] */
+#define WM8996_DAC2L_HPOUT2L_VOL_MASK           0x000F  /* DAC2L_HPOUT2L_VOL - [3:0] */
+#define WM8996_DAC2L_HPOUT2L_VOL_SHIFT               0  /* DAC2L_HPOUT2L_VOL - [3:0] */
+#define WM8996_DAC2L_HPOUT2L_VOL_WIDTH               4  /* DAC2L_HPOUT2L_VOL - [3:0] */
+
+/*
+ * R24 (0x18) - DAC1 Left Volume
+ */
+#define WM8996_DAC1L_MUTE                       0x0200  /* DAC1L_MUTE */
+#define WM8996_DAC1L_MUTE_MASK                  0x0200  /* DAC1L_MUTE */
+#define WM8996_DAC1L_MUTE_SHIFT                      9  /* DAC1L_MUTE */
+#define WM8996_DAC1L_MUTE_WIDTH                      1  /* DAC1L_MUTE */
+#define WM8996_DAC1_VU                          0x0100  /* DAC1_VU */
+#define WM8996_DAC1_VU_MASK                     0x0100  /* DAC1_VU */
+#define WM8996_DAC1_VU_SHIFT                         8  /* DAC1_VU */
+#define WM8996_DAC1_VU_WIDTH                         1  /* DAC1_VU */
+#define WM8996_DAC1L_VOL_MASK                   0x00FF  /* DAC1L_VOL - [7:0] */
+#define WM8996_DAC1L_VOL_SHIFT                       0  /* DAC1L_VOL - [7:0] */
+#define WM8996_DAC1L_VOL_WIDTH                       8  /* DAC1L_VOL - [7:0] */
+
+/*
+ * R25 (0x19) - DAC1 Right Volume
+ */
+#define WM8996_DAC1R_MUTE                       0x0200  /* DAC1R_MUTE */
+#define WM8996_DAC1R_MUTE_MASK                  0x0200  /* DAC1R_MUTE */
+#define WM8996_DAC1R_MUTE_SHIFT                      9  /* DAC1R_MUTE */
+#define WM8996_DAC1R_MUTE_WIDTH                      1  /* DAC1R_MUTE */
+#define WM8996_DAC1_VU                          0x0100  /* DAC1_VU */
+#define WM8996_DAC1_VU_MASK                     0x0100  /* DAC1_VU */
+#define WM8996_DAC1_VU_SHIFT                         8  /* DAC1_VU */
+#define WM8996_DAC1_VU_WIDTH                         1  /* DAC1_VU */
+#define WM8996_DAC1R_VOL_MASK                   0x00FF  /* DAC1R_VOL - [7:0] */
+#define WM8996_DAC1R_VOL_SHIFT                       0  /* DAC1R_VOL - [7:0] */
+#define WM8996_DAC1R_VOL_WIDTH                       8  /* DAC1R_VOL - [7:0] */
+
+/*
+ * R26 (0x1A) - DAC2 Left Volume
+ */
+#define WM8996_DAC2L_MUTE                       0x0200  /* DAC2L_MUTE */
+#define WM8996_DAC2L_MUTE_MASK                  0x0200  /* DAC2L_MUTE */
+#define WM8996_DAC2L_MUTE_SHIFT                      9  /* DAC2L_MUTE */
+#define WM8996_DAC2L_MUTE_WIDTH                      1  /* DAC2L_MUTE */
+#define WM8996_DAC2_VU                          0x0100  /* DAC2_VU */
+#define WM8996_DAC2_VU_MASK                     0x0100  /* DAC2_VU */
+#define WM8996_DAC2_VU_SHIFT                         8  /* DAC2_VU */
+#define WM8996_DAC2_VU_WIDTH                         1  /* DAC2_VU */
+#define WM8996_DAC2L_VOL_MASK                   0x00FF  /* DAC2L_VOL - [7:0] */
+#define WM8996_DAC2L_VOL_SHIFT                       0  /* DAC2L_VOL - [7:0] */
+#define WM8996_DAC2L_VOL_WIDTH                       8  /* DAC2L_VOL - [7:0] */
+
+/*
+ * R27 (0x1B) - DAC2 Right Volume
+ */
+#define WM8996_DAC2R_MUTE                       0x0200  /* DAC2R_MUTE */
+#define WM8996_DAC2R_MUTE_MASK                  0x0200  /* DAC2R_MUTE */
+#define WM8996_DAC2R_MUTE_SHIFT                      9  /* DAC2R_MUTE */
+#define WM8996_DAC2R_MUTE_WIDTH                      1  /* DAC2R_MUTE */
+#define WM8996_DAC2_VU                          0x0100  /* DAC2_VU */
+#define WM8996_DAC2_VU_MASK                     0x0100  /* DAC2_VU */
+#define WM8996_DAC2_VU_SHIFT                         8  /* DAC2_VU */
+#define WM8996_DAC2_VU_WIDTH                         1  /* DAC2_VU */
+#define WM8996_DAC2R_VOL_MASK                   0x00FF  /* DAC2R_VOL - [7:0] */
+#define WM8996_DAC2R_VOL_SHIFT                       0  /* DAC2R_VOL - [7:0] */
+#define WM8996_DAC2R_VOL_WIDTH                       8  /* DAC2R_VOL - [7:0] */
+
+/*
+ * R28 (0x1C) - Output1 Left Volume
+ */
+#define WM8996_DAC1_VU                          0x0100  /* DAC1_VU */
+#define WM8996_DAC1_VU_MASK                     0x0100  /* DAC1_VU */
+#define WM8996_DAC1_VU_SHIFT                         8  /* DAC1_VU */
+#define WM8996_DAC1_VU_WIDTH                         1  /* DAC1_VU */
+#define WM8996_HPOUT1L_ZC                       0x0080  /* HPOUT1L_ZC */
+#define WM8996_HPOUT1L_ZC_MASK                  0x0080  /* HPOUT1L_ZC */
+#define WM8996_HPOUT1L_ZC_SHIFT                      7  /* HPOUT1L_ZC */
+#define WM8996_HPOUT1L_ZC_WIDTH                      1  /* HPOUT1L_ZC */
+#define WM8996_HPOUT1L_VOL_MASK                 0x000F  /* HPOUT1L_VOL - [3:0] */
+#define WM8996_HPOUT1L_VOL_SHIFT                     0  /* HPOUT1L_VOL - [3:0] */
+#define WM8996_HPOUT1L_VOL_WIDTH                     4  /* HPOUT1L_VOL - [3:0] */
+
+/*
+ * R29 (0x1D) - Output1 Right Volume
+ */
+#define WM8996_DAC1_VU                          0x0100  /* DAC1_VU */
+#define WM8996_DAC1_VU_MASK                     0x0100  /* DAC1_VU */
+#define WM8996_DAC1_VU_SHIFT                         8  /* DAC1_VU */
+#define WM8996_DAC1_VU_WIDTH                         1  /* DAC1_VU */
+#define WM8996_HPOUT1R_ZC                       0x0080  /* HPOUT1R_ZC */
+#define WM8996_HPOUT1R_ZC_MASK                  0x0080  /* HPOUT1R_ZC */
+#define WM8996_HPOUT1R_ZC_SHIFT                      7  /* HPOUT1R_ZC */
+#define WM8996_HPOUT1R_ZC_WIDTH                      1  /* HPOUT1R_ZC */
+#define WM8996_HPOUT1R_VOL_MASK                 0x000F  /* HPOUT1R_VOL - [3:0] */
+#define WM8996_HPOUT1R_VOL_SHIFT                     0  /* HPOUT1R_VOL - [3:0] */
+#define WM8996_HPOUT1R_VOL_WIDTH                     4  /* HPOUT1R_VOL - [3:0] */
+
+/*
+ * R30 (0x1E) - Output2 Left Volume
+ */
+#define WM8996_DAC2_VU                          0x0100  /* DAC2_VU */
+#define WM8996_DAC2_VU_MASK                     0x0100  /* DAC2_VU */
+#define WM8996_DAC2_VU_SHIFT                         8  /* DAC2_VU */
+#define WM8996_DAC2_VU_WIDTH                         1  /* DAC2_VU */
+#define WM8996_HPOUT2L_ZC                       0x0080  /* HPOUT2L_ZC */
+#define WM8996_HPOUT2L_ZC_MASK                  0x0080  /* HPOUT2L_ZC */
+#define WM8996_HPOUT2L_ZC_SHIFT                      7  /* HPOUT2L_ZC */
+#define WM8996_HPOUT2L_ZC_WIDTH                      1  /* HPOUT2L_ZC */
+#define WM8996_HPOUT2L_VOL_MASK                 0x000F  /* HPOUT2L_VOL - [3:0] */
+#define WM8996_HPOUT2L_VOL_SHIFT                     0  /* HPOUT2L_VOL - [3:0] */
+#define WM8996_HPOUT2L_VOL_WIDTH                     4  /* HPOUT2L_VOL - [3:0] */
+
+/*
+ * R31 (0x1F) - Output2 Right Volume
+ */
+#define WM8996_DAC2_VU                          0x0100  /* DAC2_VU */
+#define WM8996_DAC2_VU_MASK                     0x0100  /* DAC2_VU */
+#define WM8996_DAC2_VU_SHIFT                         8  /* DAC2_VU */
+#define WM8996_DAC2_VU_WIDTH                         1  /* DAC2_VU */
+#define WM8996_HPOUT2R_ZC                       0x0080  /* HPOUT2R_ZC */
+#define WM8996_HPOUT2R_ZC_MASK                  0x0080  /* HPOUT2R_ZC */
+#define WM8996_HPOUT2R_ZC_SHIFT                      7  /* HPOUT2R_ZC */
+#define WM8996_HPOUT2R_ZC_WIDTH                      1  /* HPOUT2R_ZC */
+#define WM8996_HPOUT2R_VOL_MASK                 0x000F  /* HPOUT2R_VOL - [3:0] */
+#define WM8996_HPOUT2R_VOL_SHIFT                     0  /* HPOUT2R_VOL - [3:0] */
+#define WM8996_HPOUT2R_VOL_WIDTH                     4  /* HPOUT2R_VOL - [3:0] */
+
+/*
+ * R32 (0x20) - MICBIAS (1)
+ */
+#define WM8996_MICB1_RATE                       0x0020  /* MICB1_RATE */
+#define WM8996_MICB1_RATE_MASK                  0x0020  /* MICB1_RATE */
+#define WM8996_MICB1_RATE_SHIFT                      5  /* MICB1_RATE */
+#define WM8996_MICB1_RATE_WIDTH                      1  /* MICB1_RATE */
+#define WM8996_MICB1_MODE                       0x0010  /* MICB1_MODE */
+#define WM8996_MICB1_MODE_MASK                  0x0010  /* MICB1_MODE */
+#define WM8996_MICB1_MODE_SHIFT                      4  /* MICB1_MODE */
+#define WM8996_MICB1_MODE_WIDTH                      1  /* MICB1_MODE */
+#define WM8996_MICB1_LVL_MASK                   0x000E  /* MICB1_LVL - [3:1] */
+#define WM8996_MICB1_LVL_SHIFT                       1  /* MICB1_LVL - [3:1] */
+#define WM8996_MICB1_LVL_WIDTH                       3  /* MICB1_LVL - [3:1] */
+#define WM8996_MICB1_DISCH                      0x0001  /* MICB1_DISCH */
+#define WM8996_MICB1_DISCH_MASK                 0x0001  /* MICB1_DISCH */
+#define WM8996_MICB1_DISCH_SHIFT                     0  /* MICB1_DISCH */
+#define WM8996_MICB1_DISCH_WIDTH                     1  /* MICB1_DISCH */
+
+/*
+ * R33 (0x21) - MICBIAS (2)
+ */
+#define WM8996_MICB2_RATE                       0x0020  /* MICB2_RATE */
+#define WM8996_MICB2_RATE_MASK                  0x0020  /* MICB2_RATE */
+#define WM8996_MICB2_RATE_SHIFT                      5  /* MICB2_RATE */
+#define WM8996_MICB2_RATE_WIDTH                      1  /* MICB2_RATE */
+#define WM8996_MICB2_MODE                       0x0010  /* MICB2_MODE */
+#define WM8996_MICB2_MODE_MASK                  0x0010  /* MICB2_MODE */
+#define WM8996_MICB2_MODE_SHIFT                      4  /* MICB2_MODE */
+#define WM8996_MICB2_MODE_WIDTH                      1  /* MICB2_MODE */
+#define WM8996_MICB2_LVL_MASK                   0x000E  /* MICB2_LVL - [3:1] */
+#define WM8996_MICB2_LVL_SHIFT                       1  /* MICB2_LVL - [3:1] */
+#define WM8996_MICB2_LVL_WIDTH                       3  /* MICB2_LVL - [3:1] */
+#define WM8996_MICB2_DISCH                      0x0001  /* MICB2_DISCH */
+#define WM8996_MICB2_DISCH_MASK                 0x0001  /* MICB2_DISCH */
+#define WM8996_MICB2_DISCH_SHIFT                     0  /* MICB2_DISCH */
+#define WM8996_MICB2_DISCH_WIDTH                     1  /* MICB2_DISCH */
+
+/*
+ * R40 (0x28) - LDO 1
+ */
+#define WM8996_LDO1_MODE                        0x0020  /* LDO1_MODE */
+#define WM8996_LDO1_MODE_MASK                   0x0020  /* LDO1_MODE */
+#define WM8996_LDO1_MODE_SHIFT                       5  /* LDO1_MODE */
+#define WM8996_LDO1_MODE_WIDTH                       1  /* LDO1_MODE */
+#define WM8996_LDO1_VSEL_MASK                   0x0006  /* LDO1_VSEL - [2:1] */
+#define WM8996_LDO1_VSEL_SHIFT                       1  /* LDO1_VSEL - [2:1] */
+#define WM8996_LDO1_VSEL_WIDTH                       2  /* LDO1_VSEL - [2:1] */
+#define WM8996_LDO1_DISCH                       0x0001  /* LDO1_DISCH */
+#define WM8996_LDO1_DISCH_MASK                  0x0001  /* LDO1_DISCH */
+#define WM8996_LDO1_DISCH_SHIFT                      0  /* LDO1_DISCH */
+#define WM8996_LDO1_DISCH_WIDTH                      1  /* LDO1_DISCH */
+
+/*
+ * R41 (0x29) - LDO 2
+ */
+#define WM8996_LDO2_MODE                        0x0020  /* LDO2_MODE */
+#define WM8996_LDO2_MODE_MASK                   0x0020  /* LDO2_MODE */
+#define WM8996_LDO2_MODE_SHIFT                       5  /* LDO2_MODE */
+#define WM8996_LDO2_MODE_WIDTH                       1  /* LDO2_MODE */
+#define WM8996_LDO2_VSEL_MASK                   0x001E  /* LDO2_VSEL - [4:1] */
+#define WM8996_LDO2_VSEL_SHIFT                       1  /* LDO2_VSEL - [4:1] */
+#define WM8996_LDO2_VSEL_WIDTH                       4  /* LDO2_VSEL - [4:1] */
+#define WM8996_LDO2_DISCH                       0x0001  /* LDO2_DISCH */
+#define WM8996_LDO2_DISCH_MASK                  0x0001  /* LDO2_DISCH */
+#define WM8996_LDO2_DISCH_SHIFT                      0  /* LDO2_DISCH */
+#define WM8996_LDO2_DISCH_WIDTH                      1  /* LDO2_DISCH */
+
+/*
+ * R48 (0x30) - Accessory Detect Mode 1
+ */
+#define WM8996_JD_MODE_MASK                     0x0003  /* JD_MODE - [1:0] */
+#define WM8996_JD_MODE_SHIFT                         0  /* JD_MODE - [1:0] */
+#define WM8996_JD_MODE_WIDTH                         2  /* JD_MODE - [1:0] */
+
+/*
+ * R49 (0x31) - Accessory Detect Mode 2
+ */
+#define WM8996_HPOUT1FB_SRC                     0x0004  /* HPOUT1FB_SRC */
+#define WM8996_HPOUT1FB_SRC_MASK                0x0004  /* HPOUT1FB_SRC */
+#define WM8996_HPOUT1FB_SRC_SHIFT                    2  /* HPOUT1FB_SRC */
+#define WM8996_HPOUT1FB_SRC_WIDTH                    1  /* HPOUT1FB_SRC */
+#define WM8996_MICD_SRC                         0x0002  /* MICD_SRC */
+#define WM8996_MICD_SRC_MASK                    0x0002  /* MICD_SRC */
+#define WM8996_MICD_SRC_SHIFT                        1  /* MICD_SRC */
+#define WM8996_MICD_SRC_WIDTH                        1  /* MICD_SRC */
+#define WM8996_MICD_BIAS_SRC                    0x0001  /* MICD_BIAS_SRC */
+#define WM8996_MICD_BIAS_SRC_MASK               0x0001  /* MICD_BIAS_SRC */
+#define WM8996_MICD_BIAS_SRC_SHIFT                   0  /* MICD_BIAS_SRC */
+#define WM8996_MICD_BIAS_SRC_WIDTH                   1  /* MICD_BIAS_SRC */
+
+/*
+ * R52 (0x34) - Headphone Detect 1
+ */
+#define WM8996_HP_HOLDTIME_MASK                 0x00E0  /* HP_HOLDTIME - [7:5] */
+#define WM8996_HP_HOLDTIME_SHIFT                     5  /* HP_HOLDTIME - [7:5] */
+#define WM8996_HP_HOLDTIME_WIDTH                     3  /* HP_HOLDTIME - [7:5] */
+#define WM8996_HP_CLK_DIV_MASK                  0x0018  /* HP_CLK_DIV - [4:3] */
+#define WM8996_HP_CLK_DIV_SHIFT                      3  /* HP_CLK_DIV - [4:3] */
+#define WM8996_HP_CLK_DIV_WIDTH                      2  /* HP_CLK_DIV - [4:3] */
+#define WM8996_HP_STEP_SIZE                     0x0002  /* HP_STEP_SIZE */
+#define WM8996_HP_STEP_SIZE_MASK                0x0002  /* HP_STEP_SIZE */
+#define WM8996_HP_STEP_SIZE_SHIFT                    1  /* HP_STEP_SIZE */
+#define WM8996_HP_STEP_SIZE_WIDTH                    1  /* HP_STEP_SIZE */
+#define WM8996_HP_POLL                          0x0001  /* HP_POLL */
+#define WM8996_HP_POLL_MASK                     0x0001  /* HP_POLL */
+#define WM8996_HP_POLL_SHIFT                         0  /* HP_POLL */
+#define WM8996_HP_POLL_WIDTH                         1  /* HP_POLL */
+
+/*
+ * R53 (0x35) - Headphone Detect 2
+ */
+#define WM8996_HP_DONE                          0x0080  /* HP_DONE */
+#define WM8996_HP_DONE_MASK                     0x0080  /* HP_DONE */
+#define WM8996_HP_DONE_SHIFT                         7  /* HP_DONE */
+#define WM8996_HP_DONE_WIDTH                         1  /* HP_DONE */
+#define WM8996_HP_LVL_MASK                      0x007F  /* HP_LVL - [6:0] */
+#define WM8996_HP_LVL_SHIFT                          0  /* HP_LVL - [6:0] */
+#define WM8996_HP_LVL_WIDTH                          7  /* HP_LVL - [6:0] */
+
+/*
+ * R56 (0x38) - Mic Detect 1
+ */
+#define WM8996_MICD_BIAS_STARTTIME_MASK         0xF000  /* MICD_BIAS_STARTTIME - [15:12] */
+#define WM8996_MICD_BIAS_STARTTIME_SHIFT            12  /* MICD_BIAS_STARTTIME - [15:12] */
+#define WM8996_MICD_BIAS_STARTTIME_WIDTH             4  /* MICD_BIAS_STARTTIME - [15:12] */
+#define WM8996_MICD_RATE_MASK                   0x0F00  /* MICD_RATE - [11:8] */
+#define WM8996_MICD_RATE_SHIFT                       8  /* MICD_RATE - [11:8] */
+#define WM8996_MICD_RATE_WIDTH                       4  /* MICD_RATE - [11:8] */
+#define WM8996_MICD_DBTIME                      0x0002  /* MICD_DBTIME */
+#define WM8996_MICD_DBTIME_MASK                 0x0002  /* MICD_DBTIME */
+#define WM8996_MICD_DBTIME_SHIFT                     1  /* MICD_DBTIME */
+#define WM8996_MICD_DBTIME_WIDTH                     1  /* MICD_DBTIME */
+#define WM8996_MICD_ENA                         0x0001  /* MICD_ENA */
+#define WM8996_MICD_ENA_MASK                    0x0001  /* MICD_ENA */
+#define WM8996_MICD_ENA_SHIFT                        0  /* MICD_ENA */
+#define WM8996_MICD_ENA_WIDTH                        1  /* MICD_ENA */
+
+/*
+ * R57 (0x39) - Mic Detect 2
+ */
+#define WM8996_MICD_LVL_SEL_MASK                0x00FF  /* MICD_LVL_SEL - [7:0] */
+#define WM8996_MICD_LVL_SEL_SHIFT                    0  /* MICD_LVL_SEL - [7:0] */
+#define WM8996_MICD_LVL_SEL_WIDTH                    8  /* MICD_LVL_SEL - [7:0] */
+
+/*
+ * R58 (0x3A) - Mic Detect 3
+ */
+#define WM8996_MICD_LVL_MASK                    0x07FC  /* MICD_LVL - [10:2] */
+#define WM8996_MICD_LVL_SHIFT                        2  /* MICD_LVL - [10:2] */
+#define WM8996_MICD_LVL_WIDTH                        9  /* MICD_LVL - [10:2] */
+#define WM8996_MICD_VALID                       0x0002  /* MICD_VALID */
+#define WM8996_MICD_VALID_MASK                  0x0002  /* MICD_VALID */
+#define WM8996_MICD_VALID_SHIFT                      1  /* MICD_VALID */
+#define WM8996_MICD_VALID_WIDTH                      1  /* MICD_VALID */
+#define WM8996_MICD_STS                         0x0001  /* MICD_STS */
+#define WM8996_MICD_STS_MASK                    0x0001  /* MICD_STS */
+#define WM8996_MICD_STS_SHIFT                        0  /* MICD_STS */
+#define WM8996_MICD_STS_WIDTH                        1  /* MICD_STS */
+
+/*
+ * R64 (0x40) - Charge Pump (1)
+ */
+#define WM8996_CP_ENA                           0x8000  /* CP_ENA */
+#define WM8996_CP_ENA_MASK                      0x8000  /* CP_ENA */
+#define WM8996_CP_ENA_SHIFT                         15  /* CP_ENA */
+#define WM8996_CP_ENA_WIDTH                          1  /* CP_ENA */
+
+/*
+ * R65 (0x41) - Charge Pump (2)
+ */
+#define WM8996_CP_DISCH                         0x8000  /* CP_DISCH */
+#define WM8996_CP_DISCH_MASK                    0x8000  /* CP_DISCH */
+#define WM8996_CP_DISCH_SHIFT                       15  /* CP_DISCH */
+#define WM8996_CP_DISCH_WIDTH                        1  /* CP_DISCH */
+
+/*
+ * R80 (0x50) - DC Servo (1)
+ */
+#define WM8996_DCS_ENA_CHAN_3                   0x0008  /* DCS_ENA_CHAN_3 */
+#define WM8996_DCS_ENA_CHAN_3_MASK              0x0008  /* DCS_ENA_CHAN_3 */
+#define WM8996_DCS_ENA_CHAN_3_SHIFT                  3  /* DCS_ENA_CHAN_3 */
+#define WM8996_DCS_ENA_CHAN_3_WIDTH                  1  /* DCS_ENA_CHAN_3 */
+#define WM8996_DCS_ENA_CHAN_2                   0x0004  /* DCS_ENA_CHAN_2 */
+#define WM8996_DCS_ENA_CHAN_2_MASK              0x0004  /* DCS_ENA_CHAN_2 */
+#define WM8996_DCS_ENA_CHAN_2_SHIFT                  2  /* DCS_ENA_CHAN_2 */
+#define WM8996_DCS_ENA_CHAN_2_WIDTH                  1  /* DCS_ENA_CHAN_2 */
+#define WM8996_DCS_ENA_CHAN_1                   0x0002  /* DCS_ENA_CHAN_1 */
+#define WM8996_DCS_ENA_CHAN_1_MASK              0x0002  /* DCS_ENA_CHAN_1 */
+#define WM8996_DCS_ENA_CHAN_1_SHIFT                  1  /* DCS_ENA_CHAN_1 */
+#define WM8996_DCS_ENA_CHAN_1_WIDTH                  1  /* DCS_ENA_CHAN_1 */
+#define WM8996_DCS_ENA_CHAN_0                   0x0001  /* DCS_ENA_CHAN_0 */
+#define WM8996_DCS_ENA_CHAN_0_MASK              0x0001  /* DCS_ENA_CHAN_0 */
+#define WM8996_DCS_ENA_CHAN_0_SHIFT                  0  /* DCS_ENA_CHAN_0 */
+#define WM8996_DCS_ENA_CHAN_0_WIDTH                  1  /* DCS_ENA_CHAN_0 */
+
+/*
+ * R81 (0x51) - DC Servo (2)
+ */
+#define WM8996_DCS_TRIG_SINGLE_3                0x8000  /* DCS_TRIG_SINGLE_3 */
+#define WM8996_DCS_TRIG_SINGLE_3_MASK           0x8000  /* DCS_TRIG_SINGLE_3 */
+#define WM8996_DCS_TRIG_SINGLE_3_SHIFT              15  /* DCS_TRIG_SINGLE_3 */
+#define WM8996_DCS_TRIG_SINGLE_3_WIDTH               1  /* DCS_TRIG_SINGLE_3 */
+#define WM8996_DCS_TRIG_SINGLE_2                0x4000  /* DCS_TRIG_SINGLE_2 */
+#define WM8996_DCS_TRIG_SINGLE_2_MASK           0x4000  /* DCS_TRIG_SINGLE_2 */
+#define WM8996_DCS_TRIG_SINGLE_2_SHIFT              14  /* DCS_TRIG_SINGLE_2 */
+#define WM8996_DCS_TRIG_SINGLE_2_WIDTH               1  /* DCS_TRIG_SINGLE_2 */
+#define WM8996_DCS_TRIG_SINGLE_1                0x2000  /* DCS_TRIG_SINGLE_1 */
+#define WM8996_DCS_TRIG_SINGLE_1_MASK           0x2000  /* DCS_TRIG_SINGLE_1 */
+#define WM8996_DCS_TRIG_SINGLE_1_SHIFT              13  /* DCS_TRIG_SINGLE_1 */
+#define WM8996_DCS_TRIG_SINGLE_1_WIDTH               1  /* DCS_TRIG_SINGLE_1 */
+#define WM8996_DCS_TRIG_SINGLE_0                0x1000  /* DCS_TRIG_SINGLE_0 */
+#define WM8996_DCS_TRIG_SINGLE_0_MASK           0x1000  /* DCS_TRIG_SINGLE_0 */
+#define WM8996_DCS_TRIG_SINGLE_0_SHIFT              12  /* DCS_TRIG_SINGLE_0 */
+#define WM8996_DCS_TRIG_SINGLE_0_WIDTH               1  /* DCS_TRIG_SINGLE_0 */
+#define WM8996_DCS_TRIG_SERIES_3                0x0800  /* DCS_TRIG_SERIES_3 */
+#define WM8996_DCS_TRIG_SERIES_3_MASK           0x0800  /* DCS_TRIG_SERIES_3 */
+#define WM8996_DCS_TRIG_SERIES_3_SHIFT              11  /* DCS_TRIG_SERIES_3 */
+#define WM8996_DCS_TRIG_SERIES_3_WIDTH               1  /* DCS_TRIG_SERIES_3 */
+#define WM8996_DCS_TRIG_SERIES_2                0x0400  /* DCS_TRIG_SERIES_2 */
+#define WM8996_DCS_TRIG_SERIES_2_MASK           0x0400  /* DCS_TRIG_SERIES_2 */
+#define WM8996_DCS_TRIG_SERIES_2_SHIFT              10  /* DCS_TRIG_SERIES_2 */
+#define WM8996_DCS_TRIG_SERIES_2_WIDTH               1  /* DCS_TRIG_SERIES_2 */
+#define WM8996_DCS_TRIG_SERIES_1                0x0200  /* DCS_TRIG_SERIES_1 */
+#define WM8996_DCS_TRIG_SERIES_1_MASK           0x0200  /* DCS_TRIG_SERIES_1 */
+#define WM8996_DCS_TRIG_SERIES_1_SHIFT               9  /* DCS_TRIG_SERIES_1 */
+#define WM8996_DCS_TRIG_SERIES_1_WIDTH               1  /* DCS_TRIG_SERIES_1 */
+#define WM8996_DCS_TRIG_SERIES_0                0x0100  /* DCS_TRIG_SERIES_0 */
+#define WM8996_DCS_TRIG_SERIES_0_MASK           0x0100  /* DCS_TRIG_SERIES_0 */
+#define WM8996_DCS_TRIG_SERIES_0_SHIFT               8  /* DCS_TRIG_SERIES_0 */
+#define WM8996_DCS_TRIG_SERIES_0_WIDTH               1  /* DCS_TRIG_SERIES_0 */
+#define WM8996_DCS_TRIG_STARTUP_3               0x0080  /* DCS_TRIG_STARTUP_3 */
+#define WM8996_DCS_TRIG_STARTUP_3_MASK          0x0080  /* DCS_TRIG_STARTUP_3 */
+#define WM8996_DCS_TRIG_STARTUP_3_SHIFT              7  /* DCS_TRIG_STARTUP_3 */
+#define WM8996_DCS_TRIG_STARTUP_3_WIDTH              1  /* DCS_TRIG_STARTUP_3 */
+#define WM8996_DCS_TRIG_STARTUP_2               0x0040  /* DCS_TRIG_STARTUP_2 */
+#define WM8996_DCS_TRIG_STARTUP_2_MASK          0x0040  /* DCS_TRIG_STARTUP_2 */
+#define WM8996_DCS_TRIG_STARTUP_2_SHIFT              6  /* DCS_TRIG_STARTUP_2 */
+#define WM8996_DCS_TRIG_STARTUP_2_WIDTH              1  /* DCS_TRIG_STARTUP_2 */
+#define WM8996_DCS_TRIG_STARTUP_1               0x0020  /* DCS_TRIG_STARTUP_1 */
+#define WM8996_DCS_TRIG_STARTUP_1_MASK          0x0020  /* DCS_TRIG_STARTUP_1 */
+#define WM8996_DCS_TRIG_STARTUP_1_SHIFT              5  /* DCS_TRIG_STARTUP_1 */
+#define WM8996_DCS_TRIG_STARTUP_1_WIDTH              1  /* DCS_TRIG_STARTUP_1 */
+#define WM8996_DCS_TRIG_STARTUP_0               0x0010  /* DCS_TRIG_STARTUP_0 */
+#define WM8996_DCS_TRIG_STARTUP_0_MASK          0x0010  /* DCS_TRIG_STARTUP_0 */
+#define WM8996_DCS_TRIG_STARTUP_0_SHIFT              4  /* DCS_TRIG_STARTUP_0 */
+#define WM8996_DCS_TRIG_STARTUP_0_WIDTH              1  /* DCS_TRIG_STARTUP_0 */
+#define WM8996_DCS_TRIG_DAC_WR_3                0x0008  /* DCS_TRIG_DAC_WR_3 */
+#define WM8996_DCS_TRIG_DAC_WR_3_MASK           0x0008  /* DCS_TRIG_DAC_WR_3 */
+#define WM8996_DCS_TRIG_DAC_WR_3_SHIFT               3  /* DCS_TRIG_DAC_WR_3 */
+#define WM8996_DCS_TRIG_DAC_WR_3_WIDTH               1  /* DCS_TRIG_DAC_WR_3 */
+#define WM8996_DCS_TRIG_DAC_WR_2                0x0004  /* DCS_TRIG_DAC_WR_2 */
+#define WM8996_DCS_TRIG_DAC_WR_2_MASK           0x0004  /* DCS_TRIG_DAC_WR_2 */
+#define WM8996_DCS_TRIG_DAC_WR_2_SHIFT               2  /* DCS_TRIG_DAC_WR_2 */
+#define WM8996_DCS_TRIG_DAC_WR_2_WIDTH               1  /* DCS_TRIG_DAC_WR_2 */
+#define WM8996_DCS_TRIG_DAC_WR_1                0x0002  /* DCS_TRIG_DAC_WR_1 */
+#define WM8996_DCS_TRIG_DAC_WR_1_MASK           0x0002  /* DCS_TRIG_DAC_WR_1 */
+#define WM8996_DCS_TRIG_DAC_WR_1_SHIFT               1  /* DCS_TRIG_DAC_WR_1 */
+#define WM8996_DCS_TRIG_DAC_WR_1_WIDTH               1  /* DCS_TRIG_DAC_WR_1 */
+#define WM8996_DCS_TRIG_DAC_WR_0                0x0001  /* DCS_TRIG_DAC_WR_0 */
+#define WM8996_DCS_TRIG_DAC_WR_0_MASK           0x0001  /* DCS_TRIG_DAC_WR_0 */
+#define WM8996_DCS_TRIG_DAC_WR_0_SHIFT               0  /* DCS_TRIG_DAC_WR_0 */
+#define WM8996_DCS_TRIG_DAC_WR_0_WIDTH               1  /* DCS_TRIG_DAC_WR_0 */
+
+/*
+ * R82 (0x52) - DC Servo (3)
+ */
+#define WM8996_DCS_TIMER_PERIOD_23_MASK         0x0F00  /* DCS_TIMER_PERIOD_23 - [11:8] */
+#define WM8996_DCS_TIMER_PERIOD_23_SHIFT             8  /* DCS_TIMER_PERIOD_23 - [11:8] */
+#define WM8996_DCS_TIMER_PERIOD_23_WIDTH             4  /* DCS_TIMER_PERIOD_23 - [11:8] */
+#define WM8996_DCS_TIMER_PERIOD_01_MASK         0x000F  /* DCS_TIMER_PERIOD_01 - [3:0] */
+#define WM8996_DCS_TIMER_PERIOD_01_SHIFT             0  /* DCS_TIMER_PERIOD_01 - [3:0] */
+#define WM8996_DCS_TIMER_PERIOD_01_WIDTH             4  /* DCS_TIMER_PERIOD_01 - [3:0] */
+
+/*
+ * R84 (0x54) - DC Servo (5)
+ */
+#define WM8996_DCS_SERIES_NO_23_MASK            0x7F00  /* DCS_SERIES_NO_23 - [14:8] */
+#define WM8996_DCS_SERIES_NO_23_SHIFT                8  /* DCS_SERIES_NO_23 - [14:8] */
+#define WM8996_DCS_SERIES_NO_23_WIDTH                7  /* DCS_SERIES_NO_23 - [14:8] */
+#define WM8996_DCS_SERIES_NO_01_MASK            0x007F  /* DCS_SERIES_NO_01 - [6:0] */
+#define WM8996_DCS_SERIES_NO_01_SHIFT                0  /* DCS_SERIES_NO_01 - [6:0] */
+#define WM8996_DCS_SERIES_NO_01_WIDTH                7  /* DCS_SERIES_NO_01 - [6:0] */
+
+/*
+ * R85 (0x55) - DC Servo (6)
+ */
+#define WM8996_DCS_DAC_WR_VAL_3_MASK            0xFF00  /* DCS_DAC_WR_VAL_3 - [15:8] */
+#define WM8996_DCS_DAC_WR_VAL_3_SHIFT                8  /* DCS_DAC_WR_VAL_3 - [15:8] */
+#define WM8996_DCS_DAC_WR_VAL_3_WIDTH                8  /* DCS_DAC_WR_VAL_3 - [15:8] */
+#define WM8996_DCS_DAC_WR_VAL_2_MASK            0x00FF  /* DCS_DAC_WR_VAL_2 - [7:0] */
+#define WM8996_DCS_DAC_WR_VAL_2_SHIFT                0  /* DCS_DAC_WR_VAL_2 - [7:0] */
+#define WM8996_DCS_DAC_WR_VAL_2_WIDTH                8  /* DCS_DAC_WR_VAL_2 - [7:0] */
+
+/*
+ * R86 (0x56) - DC Servo (7)
+ */
+#define WM8996_DCS_DAC_WR_VAL_1_MASK            0xFF00  /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8996_DCS_DAC_WR_VAL_1_SHIFT                8  /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8996_DCS_DAC_WR_VAL_1_WIDTH                8  /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8996_DCS_DAC_WR_VAL_0_MASK            0x00FF  /* DCS_DAC_WR_VAL_0 - [7:0] */
+#define WM8996_DCS_DAC_WR_VAL_0_SHIFT                0  /* DCS_DAC_WR_VAL_0 - [7:0] */
+#define WM8996_DCS_DAC_WR_VAL_0_WIDTH                8  /* DCS_DAC_WR_VAL_0 - [7:0] */
+
+/*
+ * R87 (0x57) - DC Servo Readback 0
+ */
+#define WM8996_DCS_CAL_COMPLETE_MASK            0x0F00  /* DCS_CAL_COMPLETE - [11:8] */
+#define WM8996_DCS_CAL_COMPLETE_SHIFT                8  /* DCS_CAL_COMPLETE - [11:8] */
+#define WM8996_DCS_CAL_COMPLETE_WIDTH                4  /* DCS_CAL_COMPLETE - [11:8] */
+#define WM8996_DCS_DAC_WR_COMPLETE_MASK         0x00F0  /* DCS_DAC_WR_COMPLETE - [7:4] */
+#define WM8996_DCS_DAC_WR_COMPLETE_SHIFT             4  /* DCS_DAC_WR_COMPLETE - [7:4] */
+#define WM8996_DCS_DAC_WR_COMPLETE_WIDTH             4  /* DCS_DAC_WR_COMPLETE - [7:4] */
+#define WM8996_DCS_STARTUP_COMPLETE_MASK        0x000F  /* DCS_STARTUP_COMPLETE - [3:0] */
+#define WM8996_DCS_STARTUP_COMPLETE_SHIFT            0  /* DCS_STARTUP_COMPLETE - [3:0] */
+#define WM8996_DCS_STARTUP_COMPLETE_WIDTH            4  /* DCS_STARTUP_COMPLETE - [3:0] */
+
+/*
+ * R96 (0x60) - Analogue HP (1)
+ */
+#define WM8996_HPOUT1L_RMV_SHORT                0x0080  /* HPOUT1L_RMV_SHORT */
+#define WM8996_HPOUT1L_RMV_SHORT_MASK           0x0080  /* HPOUT1L_RMV_SHORT */
+#define WM8996_HPOUT1L_RMV_SHORT_SHIFT               7  /* HPOUT1L_RMV_SHORT */
+#define WM8996_HPOUT1L_RMV_SHORT_WIDTH               1  /* HPOUT1L_RMV_SHORT */
+#define WM8996_HPOUT1L_OUTP                     0x0040  /* HPOUT1L_OUTP */
+#define WM8996_HPOUT1L_OUTP_MASK                0x0040  /* HPOUT1L_OUTP */
+#define WM8996_HPOUT1L_OUTP_SHIFT                    6  /* HPOUT1L_OUTP */
+#define WM8996_HPOUT1L_OUTP_WIDTH                    1  /* HPOUT1L_OUTP */
+#define WM8996_HPOUT1L_DLY                      0x0020  /* HPOUT1L_DLY */
+#define WM8996_HPOUT1L_DLY_MASK                 0x0020  /* HPOUT1L_DLY */
+#define WM8996_HPOUT1L_DLY_SHIFT                     5  /* HPOUT1L_DLY */
+#define WM8996_HPOUT1L_DLY_WIDTH                     1  /* HPOUT1L_DLY */
+#define WM8996_HPOUT1R_RMV_SHORT                0x0008  /* HPOUT1R_RMV_SHORT */
+#define WM8996_HPOUT1R_RMV_SHORT_MASK           0x0008  /* HPOUT1R_RMV_SHORT */
+#define WM8996_HPOUT1R_RMV_SHORT_SHIFT               3  /* HPOUT1R_RMV_SHORT */
+#define WM8996_HPOUT1R_RMV_SHORT_WIDTH               1  /* HPOUT1R_RMV_SHORT */
+#define WM8996_HPOUT1R_OUTP                     0x0004  /* HPOUT1R_OUTP */
+#define WM8996_HPOUT1R_OUTP_MASK                0x0004  /* HPOUT1R_OUTP */
+#define WM8996_HPOUT1R_OUTP_SHIFT                    2  /* HPOUT1R_OUTP */
+#define WM8996_HPOUT1R_OUTP_WIDTH                    1  /* HPOUT1R_OUTP */
+#define WM8996_HPOUT1R_DLY                      0x0002  /* HPOUT1R_DLY */
+#define WM8996_HPOUT1R_DLY_MASK                 0x0002  /* HPOUT1R_DLY */
+#define WM8996_HPOUT1R_DLY_SHIFT                     1  /* HPOUT1R_DLY */
+#define WM8996_HPOUT1R_DLY_WIDTH                     1  /* HPOUT1R_DLY */
+
+/*
+ * R97 (0x61) - Analogue HP (2)
+ */
+#define WM8996_HPOUT2L_RMV_SHORT                0x0080  /* HPOUT2L_RMV_SHORT */
+#define WM8996_HPOUT2L_RMV_SHORT_MASK           0x0080  /* HPOUT2L_RMV_SHORT */
+#define WM8996_HPOUT2L_RMV_SHORT_SHIFT               7  /* HPOUT2L_RMV_SHORT */
+#define WM8996_HPOUT2L_RMV_SHORT_WIDTH               1  /* HPOUT2L_RMV_SHORT */
+#define WM8996_HPOUT2L_OUTP                     0x0040  /* HPOUT2L_OUTP */
+#define WM8996_HPOUT2L_OUTP_MASK                0x0040  /* HPOUT2L_OUTP */
+#define WM8996_HPOUT2L_OUTP_SHIFT                    6  /* HPOUT2L_OUTP */
+#define WM8996_HPOUT2L_OUTP_WIDTH                    1  /* HPOUT2L_OUTP */
+#define WM8996_HPOUT2L_DLY                      0x0020  /* HPOUT2L_DLY */
+#define WM8996_HPOUT2L_DLY_MASK                 0x0020  /* HPOUT2L_DLY */
+#define WM8996_HPOUT2L_DLY_SHIFT                     5  /* HPOUT2L_DLY */
+#define WM8996_HPOUT2L_DLY_WIDTH                     1  /* HPOUT2L_DLY */
+#define WM8996_HPOUT2R_RMV_SHORT                0x0008  /* HPOUT2R_RMV_SHORT */
+#define WM8996_HPOUT2R_RMV_SHORT_MASK           0x0008  /* HPOUT2R_RMV_SHORT */
+#define WM8996_HPOUT2R_RMV_SHORT_SHIFT               3  /* HPOUT2R_RMV_SHORT */
+#define WM8996_HPOUT2R_RMV_SHORT_WIDTH               1  /* HPOUT2R_RMV_SHORT */
+#define WM8996_HPOUT2R_OUTP                     0x0004  /* HPOUT2R_OUTP */
+#define WM8996_HPOUT2R_OUTP_MASK                0x0004  /* HPOUT2R_OUTP */
+#define WM8996_HPOUT2R_OUTP_SHIFT                    2  /* HPOUT2R_OUTP */
+#define WM8996_HPOUT2R_OUTP_WIDTH                    1  /* HPOUT2R_OUTP */
+#define WM8996_HPOUT2R_DLY                      0x0002  /* HPOUT2R_DLY */
+#define WM8996_HPOUT2R_DLY_MASK                 0x0002  /* HPOUT2R_DLY */
+#define WM8996_HPOUT2R_DLY_SHIFT                     1  /* HPOUT2R_DLY */
+#define WM8996_HPOUT2R_DLY_WIDTH                     1  /* HPOUT2R_DLY */
+
+/*
+ * R256 (0x100) - Chip Revision
+ */
+#define WM8996_CHIP_REV_MASK                    0x000F  /* CHIP_REV - [3:0] */
+#define WM8996_CHIP_REV_SHIFT                        0  /* CHIP_REV - [3:0] */
+#define WM8996_CHIP_REV_WIDTH                        4  /* CHIP_REV - [3:0] */
+
+/*
+ * R257 (0x101) - Control Interface (1)
+ */
+#define WM8996_AUTO_INC                         0x0004  /* AUTO_INC */
+#define WM8996_AUTO_INC_MASK                    0x0004  /* AUTO_INC */
+#define WM8996_AUTO_INC_SHIFT                        2  /* AUTO_INC */
+#define WM8996_AUTO_INC_WIDTH                        1  /* AUTO_INC */
+
+/*
+ * R272 (0x110) - Write Sequencer Ctrl (1)
+ */
+#define WM8996_WSEQ_ENA                         0x8000  /* WSEQ_ENA */
+#define WM8996_WSEQ_ENA_MASK                    0x8000  /* WSEQ_ENA */
+#define WM8996_WSEQ_ENA_SHIFT                       15  /* WSEQ_ENA */
+#define WM8996_WSEQ_ENA_WIDTH                        1  /* WSEQ_ENA */
+#define WM8996_WSEQ_ABORT                       0x0200  /* WSEQ_ABORT */
+#define WM8996_WSEQ_ABORT_MASK                  0x0200  /* WSEQ_ABORT */
+#define WM8996_WSEQ_ABORT_SHIFT                      9  /* WSEQ_ABORT */
+#define WM8996_WSEQ_ABORT_WIDTH                      1  /* WSEQ_ABORT */
+#define WM8996_WSEQ_START                       0x0100  /* WSEQ_START */
+#define WM8996_WSEQ_START_MASK                  0x0100  /* WSEQ_START */
+#define WM8996_WSEQ_START_SHIFT                      8  /* WSEQ_START */
+#define WM8996_WSEQ_START_WIDTH                      1  /* WSEQ_START */
+#define WM8996_WSEQ_START_INDEX_MASK            0x007F  /* WSEQ_START_INDEX - [6:0] */
+#define WM8996_WSEQ_START_INDEX_SHIFT                0  /* WSEQ_START_INDEX - [6:0] */
+#define WM8996_WSEQ_START_INDEX_WIDTH                7  /* WSEQ_START_INDEX - [6:0] */
+
+/*
+ * R273 (0x111) - Write Sequencer Ctrl (2)
+ */
+#define WM8996_WSEQ_BUSY                        0x0100  /* WSEQ_BUSY */
+#define WM8996_WSEQ_BUSY_MASK                   0x0100  /* WSEQ_BUSY */
+#define WM8996_WSEQ_BUSY_SHIFT                       8  /* WSEQ_BUSY */
+#define WM8996_WSEQ_BUSY_WIDTH                       1  /* WSEQ_BUSY */
+#define WM8996_WSEQ_CURRENT_INDEX_MASK          0x007F  /* WSEQ_CURRENT_INDEX - [6:0] */
+#define WM8996_WSEQ_CURRENT_INDEX_SHIFT              0  /* WSEQ_CURRENT_INDEX - [6:0] */
+#define WM8996_WSEQ_CURRENT_INDEX_WIDTH              7  /* WSEQ_CURRENT_INDEX - [6:0] */
+
+/*
+ * R512 (0x200) - AIF Clocking (1)
+ */
+#define WM8996_SYSCLK_SRC_MASK                  0x0018  /* SYSCLK_SRC - [4:3] */
+#define WM8996_SYSCLK_SRC_SHIFT                      3  /* SYSCLK_SRC - [4:3] */
+#define WM8996_SYSCLK_SRC_WIDTH                      2  /* SYSCLK_SRC - [4:3] */
+#define WM8996_SYSCLK_INV                       0x0004  /* SYSCLK_INV */
+#define WM8996_SYSCLK_INV_MASK                  0x0004  /* SYSCLK_INV */
+#define WM8996_SYSCLK_INV_SHIFT                      2  /* SYSCLK_INV */
+#define WM8996_SYSCLK_INV_WIDTH                      1  /* SYSCLK_INV */
+#define WM8996_SYSCLK_DIV                       0x0002  /* SYSCLK_DIV */
+#define WM8996_SYSCLK_DIV_MASK                  0x0002  /* SYSCLK_DIV */
+#define WM8996_SYSCLK_DIV_SHIFT                      1  /* SYSCLK_DIV */
+#define WM8996_SYSCLK_DIV_WIDTH                      1  /* SYSCLK_DIV */
+#define WM8996_SYSCLK_ENA                       0x0001  /* SYSCLK_ENA */
+#define WM8996_SYSCLK_ENA_MASK                  0x0001  /* SYSCLK_ENA */
+#define WM8996_SYSCLK_ENA_SHIFT                      0  /* SYSCLK_ENA */
+#define WM8996_SYSCLK_ENA_WIDTH                      1  /* SYSCLK_ENA */
+
+/*
+ * R513 (0x201) - AIF Clocking (2)
+ */
+#define WM8996_DSP2_DIV_MASK                    0x0018  /* DSP2_DIV - [4:3] */
+#define WM8996_DSP2_DIV_SHIFT                        3  /* DSP2_DIV - [4:3] */
+#define WM8996_DSP2_DIV_WIDTH                        2  /* DSP2_DIV - [4:3] */
+#define WM8996_DSP1_DIV_MASK                    0x0003  /* DSP1_DIV - [1:0] */
+#define WM8996_DSP1_DIV_SHIFT                        0  /* DSP1_DIV - [1:0] */
+#define WM8996_DSP1_DIV_WIDTH                        2  /* DSP1_DIV - [1:0] */
+
+/*
+ * R520 (0x208) - Clocking (1)
+ */
+#define WM8996_LFCLK_ENA                        0x0020  /* LFCLK_ENA */
+#define WM8996_LFCLK_ENA_MASK                   0x0020  /* LFCLK_ENA */
+#define WM8996_LFCLK_ENA_SHIFT                       5  /* LFCLK_ENA */
+#define WM8996_LFCLK_ENA_WIDTH                       1  /* LFCLK_ENA */
+#define WM8996_TOCLK_ENA                        0x0010  /* TOCLK_ENA */
+#define WM8996_TOCLK_ENA_MASK                   0x0010  /* TOCLK_ENA */
+#define WM8996_TOCLK_ENA_SHIFT                       4  /* TOCLK_ENA */
+#define WM8996_TOCLK_ENA_WIDTH                       1  /* TOCLK_ENA */
+#define WM8996_AIFCLK_ENA                       0x0004  /* AIFCLK_ENA */
+#define WM8996_AIFCLK_ENA_MASK                  0x0004  /* AIFCLK_ENA */
+#define WM8996_AIFCLK_ENA_SHIFT                      2  /* AIFCLK_ENA */
+#define WM8996_AIFCLK_ENA_WIDTH                      1  /* AIFCLK_ENA */
+#define WM8996_SYSDSPCLK_ENA                    0x0002  /* SYSDSPCLK_ENA */
+#define WM8996_SYSDSPCLK_ENA_MASK               0x0002  /* SYSDSPCLK_ENA */
+#define WM8996_SYSDSPCLK_ENA_SHIFT                   1  /* SYSDSPCLK_ENA */
+#define WM8996_SYSDSPCLK_ENA_WIDTH                   1  /* SYSDSPCLK_ENA */
+
+/*
+ * R521 (0x209) - Clocking (2)
+ */
+#define WM8996_TOCLK_DIV_MASK                   0x0700  /* TOCLK_DIV - [10:8] */
+#define WM8996_TOCLK_DIV_SHIFT                       8  /* TOCLK_DIV - [10:8] */
+#define WM8996_TOCLK_DIV_WIDTH                       3  /* TOCLK_DIV - [10:8] */
+#define WM8996_DBCLK_DIV_MASK                   0x00F0  /* DBCLK_DIV - [7:4] */
+#define WM8996_DBCLK_DIV_SHIFT                       4  /* DBCLK_DIV - [7:4] */
+#define WM8996_DBCLK_DIV_WIDTH                       4  /* DBCLK_DIV - [7:4] */
+#define WM8996_OPCLK_DIV_MASK                   0x0007  /* OPCLK_DIV - [2:0] */
+#define WM8996_OPCLK_DIV_SHIFT                       0  /* OPCLK_DIV - [2:0] */
+#define WM8996_OPCLK_DIV_WIDTH                       3  /* OPCLK_DIV - [2:0] */
+
+/*
+ * R528 (0x210) - AIF Rate
+ */
+#define WM8996_SYSCLK_RATE                      0x0001  /* SYSCLK_RATE */
+#define WM8996_SYSCLK_RATE_MASK                 0x0001  /* SYSCLK_RATE */
+#define WM8996_SYSCLK_RATE_SHIFT                     0  /* SYSCLK_RATE */
+#define WM8996_SYSCLK_RATE_WIDTH                     1  /* SYSCLK_RATE */
+
+/*
+ * R544 (0x220) - FLL Control (1)
+ */
+#define WM8996_FLL_OSC_ENA                      0x0002  /* FLL_OSC_ENA */
+#define WM8996_FLL_OSC_ENA_MASK                 0x0002  /* FLL_OSC_ENA */
+#define WM8996_FLL_OSC_ENA_SHIFT                     1  /* FLL_OSC_ENA */
+#define WM8996_FLL_OSC_ENA_WIDTH                     1  /* FLL_OSC_ENA */
+#define WM8996_FLL_ENA                          0x0001  /* FLL_ENA */
+#define WM8996_FLL_ENA_MASK                     0x0001  /* FLL_ENA */
+#define WM8996_FLL_ENA_SHIFT                         0  /* FLL_ENA */
+#define WM8996_FLL_ENA_WIDTH                         1  /* FLL_ENA */
+
+/*
+ * R545 (0x221) - FLL Control (2)
+ */
+#define WM8996_FLL_OUTDIV_MASK                  0x3F00  /* FLL_OUTDIV - [13:8] */
+#define WM8996_FLL_OUTDIV_SHIFT                      8  /* FLL_OUTDIV - [13:8] */
+#define WM8996_FLL_OUTDIV_WIDTH                      6  /* FLL_OUTDIV - [13:8] */
+#define WM8996_FLL_FRATIO_MASK                  0x0007  /* FLL_FRATIO - [2:0] */
+#define WM8996_FLL_FRATIO_SHIFT                      0  /* FLL_FRATIO - [2:0] */
+#define WM8996_FLL_FRATIO_WIDTH                      3  /* FLL_FRATIO - [2:0] */
+
+/*
+ * R546 (0x222) - FLL Control (3)
+ */
+#define WM8996_FLL_THETA_MASK                   0xFFFF  /* FLL_THETA - [15:0] */
+#define WM8996_FLL_THETA_SHIFT                       0  /* FLL_THETA - [15:0] */
+#define WM8996_FLL_THETA_WIDTH                      16  /* FLL_THETA - [15:0] */
+
+/*
+ * R547 (0x223) - FLL Control (4)
+ */
+#define WM8996_FLL_N_MASK                       0x7FE0  /* FLL_N - [14:5] */
+#define WM8996_FLL_N_SHIFT                           5  /* FLL_N - [14:5] */
+#define WM8996_FLL_N_WIDTH                          10  /* FLL_N - [14:5] */
+#define WM8996_FLL_LOOP_GAIN_MASK               0x000F  /* FLL_LOOP_GAIN - [3:0] */
+#define WM8996_FLL_LOOP_GAIN_SHIFT                   0  /* FLL_LOOP_GAIN - [3:0] */
+#define WM8996_FLL_LOOP_GAIN_WIDTH                   4  /* FLL_LOOP_GAIN - [3:0] */
+
+/*
+ * R548 (0x224) - FLL Control (5)
+ */
+#define WM8996_FLL_FRC_NCO_VAL_MASK             0x1F80  /* FLL_FRC_NCO_VAL - [12:7] */
+#define WM8996_FLL_FRC_NCO_VAL_SHIFT                 7  /* FLL_FRC_NCO_VAL - [12:7] */
+#define WM8996_FLL_FRC_NCO_VAL_WIDTH                 6  /* FLL_FRC_NCO_VAL - [12:7] */
+#define WM8996_FLL_FRC_NCO                      0x0040  /* FLL_FRC_NCO */
+#define WM8996_FLL_FRC_NCO_MASK                 0x0040  /* FLL_FRC_NCO */
+#define WM8996_FLL_FRC_NCO_SHIFT                     6  /* FLL_FRC_NCO */
+#define WM8996_FLL_FRC_NCO_WIDTH                     1  /* FLL_FRC_NCO */
+#define WM8996_FLL_REFCLK_DIV_MASK              0x0018  /* FLL_REFCLK_DIV - [4:3] */
+#define WM8996_FLL_REFCLK_DIV_SHIFT                  3  /* FLL_REFCLK_DIV - [4:3] */
+#define WM8996_FLL_REFCLK_DIV_WIDTH                  2  /* FLL_REFCLK_DIV - [4:3] */
+#define WM8996_FLL_REF_FREQ                     0x0004  /* FLL_REF_FREQ */
+#define WM8996_FLL_REF_FREQ_MASK                0x0004  /* FLL_REF_FREQ */
+#define WM8996_FLL_REF_FREQ_SHIFT                    2  /* FLL_REF_FREQ */
+#define WM8996_FLL_REF_FREQ_WIDTH                    1  /* FLL_REF_FREQ */
+#define WM8996_FLL_REFCLK_SRC_MASK              0x0003  /* FLL_REFCLK_SRC - [1:0] */
+#define WM8996_FLL_REFCLK_SRC_SHIFT                  0  /* FLL_REFCLK_SRC - [1:0] */
+#define WM8996_FLL_REFCLK_SRC_WIDTH                  2  /* FLL_REFCLK_SRC - [1:0] */
+
+/*
+ * R549 (0x225) - FLL Control (6)
+ */
+#define WM8996_FLL_REFCLK_SRC_STS_MASK          0x000C  /* FLL_REFCLK_SRC_STS - [3:2] */
+#define WM8996_FLL_REFCLK_SRC_STS_SHIFT              2  /* FLL_REFCLK_SRC_STS - [3:2] */
+#define WM8996_FLL_REFCLK_SRC_STS_WIDTH              2  /* FLL_REFCLK_SRC_STS - [3:2] */
+#define WM8996_FLL_SWITCH_CLK                   0x0001  /* FLL_SWITCH_CLK */
+#define WM8996_FLL_SWITCH_CLK_MASK              0x0001  /* FLL_SWITCH_CLK */
+#define WM8996_FLL_SWITCH_CLK_SHIFT                  0  /* FLL_SWITCH_CLK */
+#define WM8996_FLL_SWITCH_CLK_WIDTH                  1  /* FLL_SWITCH_CLK */
+
+/*
+ * R550 (0x226) - FLL EFS 1
+ */
+#define WM8996_FLL_LAMBDA_MASK                  0xFFFF  /* FLL_LAMBDA - [15:0] */
+#define WM8996_FLL_LAMBDA_SHIFT                      0  /* FLL_LAMBDA - [15:0] */
+#define WM8996_FLL_LAMBDA_WIDTH                     16  /* FLL_LAMBDA - [15:0] */
+
+/*
+ * R551 (0x227) - FLL EFS 2
+ */
+#define WM8996_FLL_LFSR_SEL_MASK                0x0006  /* FLL_LFSR_SEL - [2:1] */
+#define WM8996_FLL_LFSR_SEL_SHIFT                    1  /* FLL_LFSR_SEL - [2:1] */
+#define WM8996_FLL_LFSR_SEL_WIDTH                    2  /* FLL_LFSR_SEL - [2:1] */
+#define WM8996_FLL_EFS_ENA                      0x0001  /* FLL_EFS_ENA */
+#define WM8996_FLL_EFS_ENA_MASK                 0x0001  /* FLL_EFS_ENA */
+#define WM8996_FLL_EFS_ENA_SHIFT                     0  /* FLL_EFS_ENA */
+#define WM8996_FLL_EFS_ENA_WIDTH                     1  /* FLL_EFS_ENA */
+
+/*
+ * R768 (0x300) - AIF1 Control
+ */
+#define WM8996_AIF1_TRI                         0x0004  /* AIF1_TRI */
+#define WM8996_AIF1_TRI_MASK                    0x0004  /* AIF1_TRI */
+#define WM8996_AIF1_TRI_SHIFT                        2  /* AIF1_TRI */
+#define WM8996_AIF1_TRI_WIDTH                        1  /* AIF1_TRI */
+#define WM8996_AIF1_FMT_MASK                    0x0003  /* AIF1_FMT - [1:0] */
+#define WM8996_AIF1_FMT_SHIFT                        0  /* AIF1_FMT - [1:0] */
+#define WM8996_AIF1_FMT_WIDTH                        2  /* AIF1_FMT - [1:0] */
+
+/*
+ * R769 (0x301) - AIF1 BCLK
+ */
+#define WM8996_AIF1_BCLK_INV                    0x0400  /* AIF1_BCLK_INV */
+#define WM8996_AIF1_BCLK_INV_MASK               0x0400  /* AIF1_BCLK_INV */
+#define WM8996_AIF1_BCLK_INV_SHIFT                  10  /* AIF1_BCLK_INV */
+#define WM8996_AIF1_BCLK_INV_WIDTH                   1  /* AIF1_BCLK_INV */
+#define WM8996_AIF1_BCLK_FRC                    0x0200  /* AIF1_BCLK_FRC */
+#define WM8996_AIF1_BCLK_FRC_MASK               0x0200  /* AIF1_BCLK_FRC */
+#define WM8996_AIF1_BCLK_FRC_SHIFT                   9  /* AIF1_BCLK_FRC */
+#define WM8996_AIF1_BCLK_FRC_WIDTH                   1  /* AIF1_BCLK_FRC */
+#define WM8996_AIF1_BCLK_MSTR                   0x0100  /* AIF1_BCLK_MSTR */
+#define WM8996_AIF1_BCLK_MSTR_MASK              0x0100  /* AIF1_BCLK_MSTR */
+#define WM8996_AIF1_BCLK_MSTR_SHIFT                  8  /* AIF1_BCLK_MSTR */
+#define WM8996_AIF1_BCLK_MSTR_WIDTH                  1  /* AIF1_BCLK_MSTR */
+#define WM8996_AIF1_BCLK_DIV_MASK               0x000F  /* AIF1_BCLK_DIV - [3:0] */
+#define WM8996_AIF1_BCLK_DIV_SHIFT                   0  /* AIF1_BCLK_DIV - [3:0] */
+#define WM8996_AIF1_BCLK_DIV_WIDTH                   4  /* AIF1_BCLK_DIV - [3:0] */
+
+/*
+ * R770 (0x302) - AIF1 TX LRCLK(1)
+ */
+#define WM8996_AIF1TX_RATE_MASK                 0x07FF  /* AIF1TX_RATE - [10:0] */
+#define WM8996_AIF1TX_RATE_SHIFT                     0  /* AIF1TX_RATE - [10:0] */
+#define WM8996_AIF1TX_RATE_WIDTH                    11  /* AIF1TX_RATE - [10:0] */
+
+/*
+ * R771 (0x303) - AIF1 TX LRCLK(2)
+ */
+#define WM8996_AIF1TX_LRCLK_MODE                0x0008  /* AIF1TX_LRCLK_MODE */
+#define WM8996_AIF1TX_LRCLK_MODE_MASK           0x0008  /* AIF1TX_LRCLK_MODE */
+#define WM8996_AIF1TX_LRCLK_MODE_SHIFT               3  /* AIF1TX_LRCLK_MODE */
+#define WM8996_AIF1TX_LRCLK_MODE_WIDTH               1  /* AIF1TX_LRCLK_MODE */
+#define WM8996_AIF1TX_LRCLK_INV                 0x0004  /* AIF1TX_LRCLK_INV */
+#define WM8996_AIF1TX_LRCLK_INV_MASK            0x0004  /* AIF1TX_LRCLK_INV */
+#define WM8996_AIF1TX_LRCLK_INV_SHIFT                2  /* AIF1TX_LRCLK_INV */
+#define WM8996_AIF1TX_LRCLK_INV_WIDTH                1  /* AIF1TX_LRCLK_INV */
+#define WM8996_AIF1TX_LRCLK_FRC                 0x0002  /* AIF1TX_LRCLK_FRC */
+#define WM8996_AIF1TX_LRCLK_FRC_MASK            0x0002  /* AIF1TX_LRCLK_FRC */
+#define WM8996_AIF1TX_LRCLK_FRC_SHIFT                1  /* AIF1TX_LRCLK_FRC */
+#define WM8996_AIF1TX_LRCLK_FRC_WIDTH                1  /* AIF1TX_LRCLK_FRC */
+#define WM8996_AIF1TX_LRCLK_MSTR                0x0001  /* AIF1TX_LRCLK_MSTR */
+#define WM8996_AIF1TX_LRCLK_MSTR_MASK           0x0001  /* AIF1TX_LRCLK_MSTR */
+#define WM8996_AIF1TX_LRCLK_MSTR_SHIFT               0  /* AIF1TX_LRCLK_MSTR */
+#define WM8996_AIF1TX_LRCLK_MSTR_WIDTH               1  /* AIF1TX_LRCLK_MSTR */
+
+/*
+ * R772 (0x304) - AIF1 RX LRCLK(1)
+ */
+#define WM8996_AIF1RX_RATE_MASK                 0x07FF  /* AIF1RX_RATE - [10:0] */
+#define WM8996_AIF1RX_RATE_SHIFT                     0  /* AIF1RX_RATE - [10:0] */
+#define WM8996_AIF1RX_RATE_WIDTH                    11  /* AIF1RX_RATE - [10:0] */
+
+/*
+ * R773 (0x305) - AIF1 RX LRCLK(2)
+ */
+#define WM8996_AIF1RX_LRCLK_INV                 0x0004  /* AIF1RX_LRCLK_INV */
+#define WM8996_AIF1RX_LRCLK_INV_MASK            0x0004  /* AIF1RX_LRCLK_INV */
+#define WM8996_AIF1RX_LRCLK_INV_SHIFT                2  /* AIF1RX_LRCLK_INV */
+#define WM8996_AIF1RX_LRCLK_INV_WIDTH                1  /* AIF1RX_LRCLK_INV */
+#define WM8996_AIF1RX_LRCLK_FRC                 0x0002  /* AIF1RX_LRCLK_FRC */
+#define WM8996_AIF1RX_LRCLK_FRC_MASK            0x0002  /* AIF1RX_LRCLK_FRC */
+#define WM8996_AIF1RX_LRCLK_FRC_SHIFT                1  /* AIF1RX_LRCLK_FRC */
+#define WM8996_AIF1RX_LRCLK_FRC_WIDTH                1  /* AIF1RX_LRCLK_FRC */
+#define WM8996_AIF1RX_LRCLK_MSTR                0x0001  /* AIF1RX_LRCLK_MSTR */
+#define WM8996_AIF1RX_LRCLK_MSTR_MASK           0x0001  /* AIF1RX_LRCLK_MSTR */
+#define WM8996_AIF1RX_LRCLK_MSTR_SHIFT               0  /* AIF1RX_LRCLK_MSTR */
+#define WM8996_AIF1RX_LRCLK_MSTR_WIDTH               1  /* AIF1RX_LRCLK_MSTR */
+
+/*
+ * R774 (0x306) - AIF1TX Data Configuration (1)
+ */
+#define WM8996_AIF1TX_WL_MASK                   0xFF00  /* AIF1TX_WL - [15:8] */
+#define WM8996_AIF1TX_WL_SHIFT                       8  /* AIF1TX_WL - [15:8] */
+#define WM8996_AIF1TX_WL_WIDTH                       8  /* AIF1TX_WL - [15:8] */
+#define WM8996_AIF1TX_SLOT_LEN_MASK             0x00FF  /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM8996_AIF1TX_SLOT_LEN_SHIFT                 0  /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM8996_AIF1TX_SLOT_LEN_WIDTH                 8  /* AIF1TX_SLOT_LEN - [7:0] */
+
+/*
+ * R775 (0x307) - AIF1TX Data Configuration (2)
+ */
+#define WM8996_AIF1TX_DAT_TRI                   0x0001  /* AIF1TX_DAT_TRI */
+#define WM8996_AIF1TX_DAT_TRI_MASK              0x0001  /* AIF1TX_DAT_TRI */
+#define WM8996_AIF1TX_DAT_TRI_SHIFT                  0  /* AIF1TX_DAT_TRI */
+#define WM8996_AIF1TX_DAT_TRI_WIDTH                  1  /* AIF1TX_DAT_TRI */
+
+/*
+ * R776 (0x308) - AIF1RX Data Configuration
+ */
+#define WM8996_AIF1RX_WL_MASK                   0xFF00  /* AIF1RX_WL - [15:8] */
+#define WM8996_AIF1RX_WL_SHIFT                       8  /* AIF1RX_WL - [15:8] */
+#define WM8996_AIF1RX_WL_WIDTH                       8  /* AIF1RX_WL - [15:8] */
+#define WM8996_AIF1RX_SLOT_LEN_MASK             0x00FF  /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM8996_AIF1RX_SLOT_LEN_SHIFT                 0  /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM8996_AIF1RX_SLOT_LEN_WIDTH                 8  /* AIF1RX_SLOT_LEN - [7:0] */
+
+/*
+ * R777 (0x309) - AIF1TX Channel 0 Configuration
+ */
+#define WM8996_AIF1TX_CHAN0_DAT_INV             0x8000  /* AIF1TX_CHAN0_DAT_INV */
+#define WM8996_AIF1TX_CHAN0_DAT_INV_MASK        0x8000  /* AIF1TX_CHAN0_DAT_INV */
+#define WM8996_AIF1TX_CHAN0_DAT_INV_SHIFT           15  /* AIF1TX_CHAN0_DAT_INV */
+#define WM8996_AIF1TX_CHAN0_DAT_INV_WIDTH            1  /* AIF1TX_CHAN0_DAT_INV */
+#define WM8996_AIF1TX_CHAN0_SPACING_MASK        0x7E00  /* AIF1TX_CHAN0_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN0_SPACING_SHIFT            9  /* AIF1TX_CHAN0_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN0_SPACING_WIDTH            6  /* AIF1TX_CHAN0_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN0_SLOTS_MASK          0x01C0  /* AIF1TX_CHAN0_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN0_SLOTS_SHIFT              6  /* AIF1TX_CHAN0_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN0_SLOTS_WIDTH              3  /* AIF1TX_CHAN0_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN0_START_SLOT_MASK     0x003F  /* AIF1TX_CHAN0_START_SLOT - [5:0] */
+#define WM8996_AIF1TX_CHAN0_START_SLOT_SHIFT         0  /* AIF1TX_CHAN0_START_SLOT - [5:0] */
+#define WM8996_AIF1TX_CHAN0_START_SLOT_WIDTH         6  /* AIF1TX_CHAN0_START_SLOT - [5:0] */
+
+/*
+ * R778 (0x30A) - AIF1TX Channel 1 Configuration
+ */
+#define WM8996_AIF1TX_CHAN1_DAT_INV             0x8000  /* AIF1TX_CHAN1_DAT_INV */
+#define WM8996_AIF1TX_CHAN1_DAT_INV_MASK        0x8000  /* AIF1TX_CHAN1_DAT_INV */
+#define WM8996_AIF1TX_CHAN1_DAT_INV_SHIFT           15  /* AIF1TX_CHAN1_DAT_INV */
+#define WM8996_AIF1TX_CHAN1_DAT_INV_WIDTH            1  /* AIF1TX_CHAN1_DAT_INV */
+#define WM8996_AIF1TX_CHAN1_SPACING_MASK        0x7E00  /* AIF1TX_CHAN1_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN1_SPACING_SHIFT            9  /* AIF1TX_CHAN1_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN1_SPACING_WIDTH            6  /* AIF1TX_CHAN1_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN1_SLOTS_MASK          0x01C0  /* AIF1TX_CHAN1_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN1_SLOTS_SHIFT              6  /* AIF1TX_CHAN1_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN1_SLOTS_WIDTH              3  /* AIF1TX_CHAN1_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN1_START_SLOT_MASK     0x003F  /* AIF1TX_CHAN1_START_SLOT - [5:0] */
+#define WM8996_AIF1TX_CHAN1_START_SLOT_SHIFT         0  /* AIF1TX_CHAN1_START_SLOT - [5:0] */
+#define WM8996_AIF1TX_CHAN1_START_SLOT_WIDTH         6  /* AIF1TX_CHAN1_START_SLOT - [5:0] */
+
+/*
+ * R779 (0x30B) - AIF1TX Channel 2 Configuration
+ */
+#define WM8996_AIF1TX_CHAN2_DAT_INV             0x8000  /* AIF1TX_CHAN2_DAT_INV */
+#define WM8996_AIF1TX_CHAN2_DAT_INV_MASK        0x8000  /* AIF1TX_CHAN2_DAT_INV */
+#define WM8996_AIF1TX_CHAN2_DAT_INV_SHIFT           15  /* AIF1TX_CHAN2_DAT_INV */
+#define WM8996_AIF1TX_CHAN2_DAT_INV_WIDTH            1  /* AIF1TX_CHAN2_DAT_INV */
+#define WM8996_AIF1TX_CHAN2_SPACING_MASK        0x7E00  /* AIF1TX_CHAN2_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN2_SPACING_SHIFT            9  /* AIF1TX_CHAN2_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN2_SPACING_WIDTH            6  /* AIF1TX_CHAN2_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN2_SLOTS_MASK          0x01C0  /* AIF1TX_CHAN2_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN2_SLOTS_SHIFT              6  /* AIF1TX_CHAN2_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN2_SLOTS_WIDTH              3  /* AIF1TX_CHAN2_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN2_START_SLOT_MASK     0x003F  /* AIF1TX_CHAN2_START_SLOT - [5:0] */
+#define WM8996_AIF1TX_CHAN2_START_SLOT_SHIFT         0  /* AIF1TX_CHAN2_START_SLOT - [5:0] */
+#define WM8996_AIF1TX_CHAN2_START_SLOT_WIDTH         6  /* AIF1TX_CHAN2_START_SLOT - [5:0] */
+
+/*
+ * R780 (0x30C) - AIF1TX Channel 3 Configuration
+ */
+#define WM8996_AIF1TX_CHAN3_DAT_INV             0x8000  /* AIF1TX_CHAN3_DAT_INV */
+#define WM8996_AIF1TX_CHAN3_DAT_INV_MASK        0x8000  /* AIF1TX_CHAN3_DAT_INV */
+#define WM8996_AIF1TX_CHAN3_DAT_INV_SHIFT           15  /* AIF1TX_CHAN3_DAT_INV */
+#define WM8996_AIF1TX_CHAN3_DAT_INV_WIDTH            1  /* AIF1TX_CHAN3_DAT_INV */
+#define WM8996_AIF1TX_CHAN3_SPACING_MASK        0x7E00  /* AIF1TX_CHAN3_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN3_SPACING_SHIFT            9  /* AIF1TX_CHAN3_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN3_SPACING_WIDTH            6  /* AIF1TX_CHAN3_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN3_SLOTS_MASK          0x01C0  /* AIF1TX_CHAN3_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN3_SLOTS_SHIFT              6  /* AIF1TX_CHAN3_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN3_SLOTS_WIDTH              3  /* AIF1TX_CHAN3_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN3_START_SLOT_MASK     0x003F  /* AIF1TX_CHAN3_START_SLOT - [5:0] */
+#define WM8996_AIF1TX_CHAN3_START_SLOT_SHIFT         0  /* AIF1TX_CHAN3_START_SLOT - [5:0] */
+#define WM8996_AIF1TX_CHAN3_START_SLOT_WIDTH         6  /* AIF1TX_CHAN3_START_SLOT - [5:0] */
+
+/*
+ * R781 (0x30D) - AIF1TX Channel 4 Configuration
+ */
+#define WM8996_AIF1TX_CHAN4_DAT_INV             0x8000  /* AIF1TX_CHAN4_DAT_INV */
+#define WM8996_AIF1TX_CHAN4_DAT_INV_MASK        0x8000  /* AIF1TX_CHAN4_DAT_INV */
+#define WM8996_AIF1TX_CHAN4_DAT_INV_SHIFT           15  /* AIF1TX_CHAN4_DAT_INV */
+#define WM8996_AIF1TX_CHAN4_DAT_INV_WIDTH            1  /* AIF1TX_CHAN4_DAT_INV */
+#define WM8996_AIF1TX_CHAN4_SPACING_MASK        0x7E00  /* AIF1TX_CHAN4_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN4_SPACING_SHIFT            9  /* AIF1TX_CHAN4_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN4_SPACING_WIDTH            6  /* AIF1TX_CHAN4_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN4_SLOTS_MASK          0x01C0  /* AIF1TX_CHAN4_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN4_SLOTS_SHIFT              6  /* AIF1TX_CHAN4_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN4_SLOTS_WIDTH              3  /* AIF1TX_CHAN4_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN4_START_SLOT_MASK     0x003F  /* AIF1TX_CHAN4_START_SLOT - [5:0] */
+#define WM8996_AIF1TX_CHAN4_START_SLOT_SHIFT         0  /* AIF1TX_CHAN4_START_SLOT - [5:0] */
+#define WM8996_AIF1TX_CHAN4_START_SLOT_WIDTH         6  /* AIF1TX_CHAN4_START_SLOT - [5:0] */
+
+/*
+ * R782 (0x30E) - AIF1TX Channel 5 Configuration
+ */
+#define WM8996_AIF1TX_CHAN5_DAT_INV             0x8000  /* AIF1TX_CHAN5_DAT_INV */
+#define WM8996_AIF1TX_CHAN5_DAT_INV_MASK        0x8000  /* AIF1TX_CHAN5_DAT_INV */
+#define WM8996_AIF1TX_CHAN5_DAT_INV_SHIFT           15  /* AIF1TX_CHAN5_DAT_INV */
+#define WM8996_AIF1TX_CHAN5_DAT_INV_WIDTH            1  /* AIF1TX_CHAN5_DAT_INV */
+#define WM8996_AIF1TX_CHAN5_SPACING_MASK        0x7E00  /* AIF1TX_CHAN5_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN5_SPACING_SHIFT            9  /* AIF1TX_CHAN5_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN5_SPACING_WIDTH            6  /* AIF1TX_CHAN5_SPACING - [14:9] */
+#define WM8996_AIF1TX_CHAN5_SLOTS_MASK          0x01C0  /* AIF1TX_CHAN5_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN5_SLOTS_SHIFT              6  /* AIF1TX_CHAN5_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN5_SLOTS_WIDTH              3  /* AIF1TX_CHAN5_SLOTS - [8:6] */
+#define WM8996_AIF1TX_CHAN5_START_SLOT_MASK     0x003F  /* AIF1TX_CHAN5_START_SLOT - [5:0] */
+#define WM8996_AIF1TX_CHAN5_START_SLOT_SHIFT         0  /* AIF1TX_CHAN5_START_SLOT - [5:0] */
+#define WM8996_AIF1TX_CHAN5_START_SLOT_WIDTH         6  /* AIF1TX_CHAN5_START_SLOT - [5:0] */
+
+/*
+ * R783 (0x30F) - AIF1RX Channel 0 Configuration
+ */
+#define WM8996_AIF1RX_CHAN0_DAT_INV             0x8000  /* AIF1RX_CHAN0_DAT_INV */
+#define WM8996_AIF1RX_CHAN0_DAT_INV_MASK        0x8000  /* AIF1RX_CHAN0_DAT_INV */
+#define WM8996_AIF1RX_CHAN0_DAT_INV_SHIFT           15  /* AIF1RX_CHAN0_DAT_INV */
+#define WM8996_AIF1RX_CHAN0_DAT_INV_WIDTH            1  /* AIF1RX_CHAN0_DAT_INV */
+#define WM8996_AIF1RX_CHAN0_SPACING_MASK        0x7E00  /* AIF1RX_CHAN0_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN0_SPACING_SHIFT            9  /* AIF1RX_CHAN0_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN0_SPACING_WIDTH            6  /* AIF1RX_CHAN0_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN0_SLOTS_MASK          0x01C0  /* AIF1RX_CHAN0_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN0_SLOTS_SHIFT              6  /* AIF1RX_CHAN0_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN0_SLOTS_WIDTH              3  /* AIF1RX_CHAN0_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN0_START_SLOT_MASK     0x003F  /* AIF1RX_CHAN0_START_SLOT - [5:0] */
+#define WM8996_AIF1RX_CHAN0_START_SLOT_SHIFT         0  /* AIF1RX_CHAN0_START_SLOT - [5:0] */
+#define WM8996_AIF1RX_CHAN0_START_SLOT_WIDTH         6  /* AIF1RX_CHAN0_START_SLOT - [5:0] */
+
+/*
+ * R784 (0x310) - AIF1RX Channel 1 Configuration
+ */
+#define WM8996_AIF1RX_CHAN1_DAT_INV             0x8000  /* AIF1RX_CHAN1_DAT_INV */
+#define WM8996_AIF1RX_CHAN1_DAT_INV_MASK        0x8000  /* AIF1RX_CHAN1_DAT_INV */
+#define WM8996_AIF1RX_CHAN1_DAT_INV_SHIFT           15  /* AIF1RX_CHAN1_DAT_INV */
+#define WM8996_AIF1RX_CHAN1_DAT_INV_WIDTH            1  /* AIF1RX_CHAN1_DAT_INV */
+#define WM8996_AIF1RX_CHAN1_SPACING_MASK        0x7E00  /* AIF1RX_CHAN1_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN1_SPACING_SHIFT            9  /* AIF1RX_CHAN1_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN1_SPACING_WIDTH            6  /* AIF1RX_CHAN1_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN1_SLOTS_MASK          0x01C0  /* AIF1RX_CHAN1_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN1_SLOTS_SHIFT              6  /* AIF1RX_CHAN1_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN1_SLOTS_WIDTH              3  /* AIF1RX_CHAN1_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN1_START_SLOT_MASK     0x003F  /* AIF1RX_CHAN1_START_SLOT - [5:0] */
+#define WM8996_AIF1RX_CHAN1_START_SLOT_SHIFT         0  /* AIF1RX_CHAN1_START_SLOT - [5:0] */
+#define WM8996_AIF1RX_CHAN1_START_SLOT_WIDTH         6  /* AIF1RX_CHAN1_START_SLOT - [5:0] */
+
+/*
+ * R785 (0x311) - AIF1RX Channel 2 Configuration
+ */
+#define WM8996_AIF1RX_CHAN2_DAT_INV             0x8000  /* AIF1RX_CHAN2_DAT_INV */
+#define WM8996_AIF1RX_CHAN2_DAT_INV_MASK        0x8000  /* AIF1RX_CHAN2_DAT_INV */
+#define WM8996_AIF1RX_CHAN2_DAT_INV_SHIFT           15  /* AIF1RX_CHAN2_DAT_INV */
+#define WM8996_AIF1RX_CHAN2_DAT_INV_WIDTH            1  /* AIF1RX_CHAN2_DAT_INV */
+#define WM8996_AIF1RX_CHAN2_SPACING_MASK        0x7E00  /* AIF1RX_CHAN2_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN2_SPACING_SHIFT            9  /* AIF1RX_CHAN2_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN2_SPACING_WIDTH            6  /* AIF1RX_CHAN2_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN2_SLOTS_MASK          0x01C0  /* AIF1RX_CHAN2_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN2_SLOTS_SHIFT              6  /* AIF1RX_CHAN2_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN2_SLOTS_WIDTH              3  /* AIF1RX_CHAN2_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN2_START_SLOT_MASK     0x003F  /* AIF1RX_CHAN2_START_SLOT - [5:0] */
+#define WM8996_AIF1RX_CHAN2_START_SLOT_SHIFT         0  /* AIF1RX_CHAN2_START_SLOT - [5:0] */
+#define WM8996_AIF1RX_CHAN2_START_SLOT_WIDTH         6  /* AIF1RX_CHAN2_START_SLOT - [5:0] */
+
+/*
+ * R786 (0x312) - AIF1RX Channel 3 Configuration
+ */
+#define WM8996_AIF1RX_CHAN3_DAT_INV             0x8000  /* AIF1RX_CHAN3_DAT_INV */
+#define WM8996_AIF1RX_CHAN3_DAT_INV_MASK        0x8000  /* AIF1RX_CHAN3_DAT_INV */
+#define WM8996_AIF1RX_CHAN3_DAT_INV_SHIFT           15  /* AIF1RX_CHAN3_DAT_INV */
+#define WM8996_AIF1RX_CHAN3_DAT_INV_WIDTH            1  /* AIF1RX_CHAN3_DAT_INV */
+#define WM8996_AIF1RX_CHAN3_SPACING_MASK        0x7E00  /* AIF1RX_CHAN3_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN3_SPACING_SHIFT            9  /* AIF1RX_CHAN3_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN3_SPACING_WIDTH            6  /* AIF1RX_CHAN3_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN3_SLOTS_MASK          0x01C0  /* AIF1RX_CHAN3_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN3_SLOTS_SHIFT              6  /* AIF1RX_CHAN3_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN3_SLOTS_WIDTH              3  /* AIF1RX_CHAN3_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN3_START_SLOT_MASK     0x003F  /* AIF1RX_CHAN3_START_SLOT - [5:0] */
+#define WM8996_AIF1RX_CHAN3_START_SLOT_SHIFT         0  /* AIF1RX_CHAN3_START_SLOT - [5:0] */
+#define WM8996_AIF1RX_CHAN3_START_SLOT_WIDTH         6  /* AIF1RX_CHAN3_START_SLOT - [5:0] */
+
+/*
+ * R787 (0x313) - AIF1RX Channel 4 Configuration
+ */
+#define WM8996_AIF1RX_CHAN4_DAT_INV             0x8000  /* AIF1RX_CHAN4_DAT_INV */
+#define WM8996_AIF1RX_CHAN4_DAT_INV_MASK        0x8000  /* AIF1RX_CHAN4_DAT_INV */
+#define WM8996_AIF1RX_CHAN4_DAT_INV_SHIFT           15  /* AIF1RX_CHAN4_DAT_INV */
+#define WM8996_AIF1RX_CHAN4_DAT_INV_WIDTH            1  /* AIF1RX_CHAN4_DAT_INV */
+#define WM8996_AIF1RX_CHAN4_SPACING_MASK        0x7E00  /* AIF1RX_CHAN4_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN4_SPACING_SHIFT            9  /* AIF1RX_CHAN4_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN4_SPACING_WIDTH            6  /* AIF1RX_CHAN4_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN4_SLOTS_MASK          0x01C0  /* AIF1RX_CHAN4_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN4_SLOTS_SHIFT              6  /* AIF1RX_CHAN4_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN4_SLOTS_WIDTH              3  /* AIF1RX_CHAN4_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN4_START_SLOT_MASK     0x003F  /* AIF1RX_CHAN4_START_SLOT - [5:0] */
+#define WM8996_AIF1RX_CHAN4_START_SLOT_SHIFT         0  /* AIF1RX_CHAN4_START_SLOT - [5:0] */
+#define WM8996_AIF1RX_CHAN4_START_SLOT_WIDTH         6  /* AIF1RX_CHAN4_START_SLOT - [5:0] */
+
+/*
+ * R788 (0x314) - AIF1RX Channel 5 Configuration
+ */
+#define WM8996_AIF1RX_CHAN5_DAT_INV             0x8000  /* AIF1RX_CHAN5_DAT_INV */
+#define WM8996_AIF1RX_CHAN5_DAT_INV_MASK        0x8000  /* AIF1RX_CHAN5_DAT_INV */
+#define WM8996_AIF1RX_CHAN5_DAT_INV_SHIFT           15  /* AIF1RX_CHAN5_DAT_INV */
+#define WM8996_AIF1RX_CHAN5_DAT_INV_WIDTH            1  /* AIF1RX_CHAN5_DAT_INV */
+#define WM8996_AIF1RX_CHAN5_SPACING_MASK        0x7E00  /* AIF1RX_CHAN5_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN5_SPACING_SHIFT            9  /* AIF1RX_CHAN5_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN5_SPACING_WIDTH            6  /* AIF1RX_CHAN5_SPACING - [14:9] */
+#define WM8996_AIF1RX_CHAN5_SLOTS_MASK          0x01C0  /* AIF1RX_CHAN5_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN5_SLOTS_SHIFT              6  /* AIF1RX_CHAN5_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN5_SLOTS_WIDTH              3  /* AIF1RX_CHAN5_SLOTS - [8:6] */
+#define WM8996_AIF1RX_CHAN5_START_SLOT_MASK     0x003F  /* AIF1RX_CHAN5_START_SLOT - [5:0] */
+#define WM8996_AIF1RX_CHAN5_START_SLOT_SHIFT         0  /* AIF1RX_CHAN5_START_SLOT - [5:0] */
+#define WM8996_AIF1RX_CHAN5_START_SLOT_WIDTH         6  /* AIF1RX_CHAN5_START_SLOT - [5:0] */
+
+/*
+ * R789 (0x315) - AIF1RX Mono Configuration
+ */
+#define WM8996_AIF1RX_CHAN4_MONO_MODE           0x0004  /* AIF1RX_CHAN4_MONO_MODE */
+#define WM8996_AIF1RX_CHAN4_MONO_MODE_MASK      0x0004  /* AIF1RX_CHAN4_MONO_MODE */
+#define WM8996_AIF1RX_CHAN4_MONO_MODE_SHIFT          2  /* AIF1RX_CHAN4_MONO_MODE */
+#define WM8996_AIF1RX_CHAN4_MONO_MODE_WIDTH          1  /* AIF1RX_CHAN4_MONO_MODE */
+#define WM8996_AIF1RX_CHAN2_MONO_MODE           0x0002  /* AIF1RX_CHAN2_MONO_MODE */
+#define WM8996_AIF1RX_CHAN2_MONO_MODE_MASK      0x0002  /* AIF1RX_CHAN2_MONO_MODE */
+#define WM8996_AIF1RX_CHAN2_MONO_MODE_SHIFT          1  /* AIF1RX_CHAN2_MONO_MODE */
+#define WM8996_AIF1RX_CHAN2_MONO_MODE_WIDTH          1  /* AIF1RX_CHAN2_MONO_MODE */
+#define WM8996_AIF1RX_CHAN0_MONO_MODE           0x0001  /* AIF1RX_CHAN0_MONO_MODE */
+#define WM8996_AIF1RX_CHAN0_MONO_MODE_MASK      0x0001  /* AIF1RX_CHAN0_MONO_MODE */
+#define WM8996_AIF1RX_CHAN0_MONO_MODE_SHIFT          0  /* AIF1RX_CHAN0_MONO_MODE */
+#define WM8996_AIF1RX_CHAN0_MONO_MODE_WIDTH          1  /* AIF1RX_CHAN0_MONO_MODE */
+
+/*
+ * R794 (0x31A) - AIF1TX Test
+ */
+#define WM8996_AIF1TX45_DITHER_ENA              0x0004  /* AIF1TX45_DITHER_ENA */
+#define WM8996_AIF1TX45_DITHER_ENA_MASK         0x0004  /* AIF1TX45_DITHER_ENA */
+#define WM8996_AIF1TX45_DITHER_ENA_SHIFT             2  /* AIF1TX45_DITHER_ENA */
+#define WM8996_AIF1TX45_DITHER_ENA_WIDTH             1  /* AIF1TX45_DITHER_ENA */
+#define WM8996_AIF1TX23_DITHER_ENA              0x0002  /* AIF1TX23_DITHER_ENA */
+#define WM8996_AIF1TX23_DITHER_ENA_MASK         0x0002  /* AIF1TX23_DITHER_ENA */
+#define WM8996_AIF1TX23_DITHER_ENA_SHIFT             1  /* AIF1TX23_DITHER_ENA */
+#define WM8996_AIF1TX23_DITHER_ENA_WIDTH             1  /* AIF1TX23_DITHER_ENA */
+#define WM8996_AIF1TX01_DITHER_ENA              0x0001  /* AIF1TX01_DITHER_ENA */
+#define WM8996_AIF1TX01_DITHER_ENA_MASK         0x0001  /* AIF1TX01_DITHER_ENA */
+#define WM8996_AIF1TX01_DITHER_ENA_SHIFT             0  /* AIF1TX01_DITHER_ENA */
+#define WM8996_AIF1TX01_DITHER_ENA_WIDTH             1  /* AIF1TX01_DITHER_ENA */
+
+/*
+ * R800 (0x320) - AIF2 Control
+ */
+#define WM8996_AIF2_TRI                         0x0004  /* AIF2_TRI */
+#define WM8996_AIF2_TRI_MASK                    0x0004  /* AIF2_TRI */
+#define WM8996_AIF2_TRI_SHIFT                        2  /* AIF2_TRI */
+#define WM8996_AIF2_TRI_WIDTH                        1  /* AIF2_TRI */
+#define WM8996_AIF2_FMT_MASK                    0x0003  /* AIF2_FMT - [1:0] */
+#define WM8996_AIF2_FMT_SHIFT                        0  /* AIF2_FMT - [1:0] */
+#define WM8996_AIF2_FMT_WIDTH                        2  /* AIF2_FMT - [1:0] */
+
+/*
+ * R801 (0x321) - AIF2 BCLK
+ */
+#define WM8996_AIF2_BCLK_INV                    0x0400  /* AIF2_BCLK_INV */
+#define WM8996_AIF2_BCLK_INV_MASK               0x0400  /* AIF2_BCLK_INV */
+#define WM8996_AIF2_BCLK_INV_SHIFT                  10  /* AIF2_BCLK_INV */
+#define WM8996_AIF2_BCLK_INV_WIDTH                   1  /* AIF2_BCLK_INV */
+#define WM8996_AIF2_BCLK_FRC                    0x0200  /* AIF2_BCLK_FRC */
+#define WM8996_AIF2_BCLK_FRC_MASK               0x0200  /* AIF2_BCLK_FRC */
+#define WM8996_AIF2_BCLK_FRC_SHIFT                   9  /* AIF2_BCLK_FRC */
+#define WM8996_AIF2_BCLK_FRC_WIDTH                   1  /* AIF2_BCLK_FRC */
+#define WM8996_AIF2_BCLK_MSTR                   0x0100  /* AIF2_BCLK_MSTR */
+#define WM8996_AIF2_BCLK_MSTR_MASK              0x0100  /* AIF2_BCLK_MSTR */
+#define WM8996_AIF2_BCLK_MSTR_SHIFT                  8  /* AIF2_BCLK_MSTR */
+#define WM8996_AIF2_BCLK_MSTR_WIDTH                  1  /* AIF2_BCLK_MSTR */
+#define WM8996_AIF2_BCLK_DIV_MASK               0x000F  /* AIF2_BCLK_DIV - [3:0] */
+#define WM8996_AIF2_BCLK_DIV_SHIFT                   0  /* AIF2_BCLK_DIV - [3:0] */
+#define WM8996_AIF2_BCLK_DIV_WIDTH                   4  /* AIF2_BCLK_DIV - [3:0] */
+
+/*
+ * R802 (0x322) - AIF2 TX LRCLK(1)
+ */
+#define WM8996_AIF2TX_RATE_MASK                 0x07FF  /* AIF2TX_RATE - [10:0] */
+#define WM8996_AIF2TX_RATE_SHIFT                     0  /* AIF2TX_RATE - [10:0] */
+#define WM8996_AIF2TX_RATE_WIDTH                    11  /* AIF2TX_RATE - [10:0] */
+
+/*
+ * R803 (0x323) - AIF2 TX LRCLK(2)
+ */
+#define WM8996_AIF2TX_LRCLK_MODE                0x0008  /* AIF2TX_LRCLK_MODE */
+#define WM8996_AIF2TX_LRCLK_MODE_MASK           0x0008  /* AIF2TX_LRCLK_MODE */
+#define WM8996_AIF2TX_LRCLK_MODE_SHIFT               3  /* AIF2TX_LRCLK_MODE */
+#define WM8996_AIF2TX_LRCLK_MODE_WIDTH               1  /* AIF2TX_LRCLK_MODE */
+#define WM8996_AIF2TX_LRCLK_INV                 0x0004  /* AIF2TX_LRCLK_INV */
+#define WM8996_AIF2TX_LRCLK_INV_MASK            0x0004  /* AIF2TX_LRCLK_INV */
+#define WM8996_AIF2TX_LRCLK_INV_SHIFT                2  /* AIF2TX_LRCLK_INV */
+#define WM8996_AIF2TX_LRCLK_INV_WIDTH                1  /* AIF2TX_LRCLK_INV */
+#define WM8996_AIF2TX_LRCLK_FRC                 0x0002  /* AIF2TX_LRCLK_FRC */
+#define WM8996_AIF2TX_LRCLK_FRC_MASK            0x0002  /* AIF2TX_LRCLK_FRC */
+#define WM8996_AIF2TX_LRCLK_FRC_SHIFT                1  /* AIF2TX_LRCLK_FRC */
+#define WM8996_AIF2TX_LRCLK_FRC_WIDTH                1  /* AIF2TX_LRCLK_FRC */
+#define WM8996_AIF2TX_LRCLK_MSTR                0x0001  /* AIF2TX_LRCLK_MSTR */
+#define WM8996_AIF2TX_LRCLK_MSTR_MASK           0x0001  /* AIF2TX_LRCLK_MSTR */
+#define WM8996_AIF2TX_LRCLK_MSTR_SHIFT               0  /* AIF2TX_LRCLK_MSTR */
+#define WM8996_AIF2TX_LRCLK_MSTR_WIDTH               1  /* AIF2TX_LRCLK_MSTR */
+
+/*
+ * R804 (0x324) - AIF2 RX LRCLK(1)
+ */
+#define WM8996_AIF2RX_RATE_MASK                 0x07FF  /* AIF2RX_RATE - [10:0] */
+#define WM8996_AIF2RX_RATE_SHIFT                     0  /* AIF2RX_RATE - [10:0] */
+#define WM8996_AIF2RX_RATE_WIDTH                    11  /* AIF2RX_RATE - [10:0] */
+
+/*
+ * R805 (0x325) - AIF2 RX LRCLK(2)
+ */
+#define WM8996_AIF2RX_LRCLK_INV                 0x0004  /* AIF2RX_LRCLK_INV */
+#define WM8996_AIF2RX_LRCLK_INV_MASK            0x0004  /* AIF2RX_LRCLK_INV */
+#define WM8996_AIF2RX_LRCLK_INV_SHIFT                2  /* AIF2RX_LRCLK_INV */
+#define WM8996_AIF2RX_LRCLK_INV_WIDTH                1  /* AIF2RX_LRCLK_INV */
+#define WM8996_AIF2RX_LRCLK_FRC                 0x0002  /* AIF2RX_LRCLK_FRC */
+#define WM8996_AIF2RX_LRCLK_FRC_MASK            0x0002  /* AIF2RX_LRCLK_FRC */
+#define WM8996_AIF2RX_LRCLK_FRC_SHIFT                1  /* AIF2RX_LRCLK_FRC */
+#define WM8996_AIF2RX_LRCLK_FRC_WIDTH                1  /* AIF2RX_LRCLK_FRC */
+#define WM8996_AIF2RX_LRCLK_MSTR                0x0001  /* AIF2RX_LRCLK_MSTR */
+#define WM8996_AIF2RX_LRCLK_MSTR_MASK           0x0001  /* AIF2RX_LRCLK_MSTR */
+#define WM8996_AIF2RX_LRCLK_MSTR_SHIFT               0  /* AIF2RX_LRCLK_MSTR */
+#define WM8996_AIF2RX_LRCLK_MSTR_WIDTH               1  /* AIF2RX_LRCLK_MSTR */
+
+/*
+ * R806 (0x326) - AIF2TX Data Configuration (1)
+ */
+#define WM8996_AIF2TX_WL_MASK                   0xFF00  /* AIF2TX_WL - [15:8] */
+#define WM8996_AIF2TX_WL_SHIFT                       8  /* AIF2TX_WL - [15:8] */
+#define WM8996_AIF2TX_WL_WIDTH                       8  /* AIF2TX_WL - [15:8] */
+#define WM8996_AIF2TX_SLOT_LEN_MASK             0x00FF  /* AIF2TX_SLOT_LEN - [7:0] */
+#define WM8996_AIF2TX_SLOT_LEN_SHIFT                 0  /* AIF2TX_SLOT_LEN - [7:0] */
+#define WM8996_AIF2TX_SLOT_LEN_WIDTH                 8  /* AIF2TX_SLOT_LEN - [7:0] */
+
+/*
+ * R807 (0x327) - AIF2TX Data Configuration (2)
+ */
+#define WM8996_AIF2TX_DAT_TRI                   0x0001  /* AIF2TX_DAT_TRI */
+#define WM8996_AIF2TX_DAT_TRI_MASK              0x0001  /* AIF2TX_DAT_TRI */
+#define WM8996_AIF2TX_DAT_TRI_SHIFT                  0  /* AIF2TX_DAT_TRI */
+#define WM8996_AIF2TX_DAT_TRI_WIDTH                  1  /* AIF2TX_DAT_TRI */
+
+/*
+ * R808 (0x328) - AIF2RX Data Configuration
+ */
+#define WM8996_AIF2RX_WL_MASK                   0xFF00  /* AIF2RX_WL - [15:8] */
+#define WM8996_AIF2RX_WL_SHIFT                       8  /* AIF2RX_WL - [15:8] */
+#define WM8996_AIF2RX_WL_WIDTH                       8  /* AIF2RX_WL - [15:8] */
+#define WM8996_AIF2RX_SLOT_LEN_MASK             0x00FF  /* AIF2RX_SLOT_LEN - [7:0] */
+#define WM8996_AIF2RX_SLOT_LEN_SHIFT                 0  /* AIF2RX_SLOT_LEN - [7:0] */
+#define WM8996_AIF2RX_SLOT_LEN_WIDTH                 8  /* AIF2RX_SLOT_LEN - [7:0] */
+
+/*
+ * R809 (0x329) - AIF2TX Channel 0 Configuration
+ */
+#define WM8996_AIF2TX_CHAN0_DAT_INV             0x8000  /* AIF2TX_CHAN0_DAT_INV */
+#define WM8996_AIF2TX_CHAN0_DAT_INV_MASK        0x8000  /* AIF2TX_CHAN0_DAT_INV */
+#define WM8996_AIF2TX_CHAN0_DAT_INV_SHIFT           15  /* AIF2TX_CHAN0_DAT_INV */
+#define WM8996_AIF2TX_CHAN0_DAT_INV_WIDTH            1  /* AIF2TX_CHAN0_DAT_INV */
+#define WM8996_AIF2TX_CHAN0_SPACING_MASK        0x7E00  /* AIF2TX_CHAN0_SPACING - [14:9] */
+#define WM8996_AIF2TX_CHAN0_SPACING_SHIFT            9  /* AIF2TX_CHAN0_SPACING - [14:9] */
+#define WM8996_AIF2TX_CHAN0_SPACING_WIDTH            6  /* AIF2TX_CHAN0_SPACING - [14:9] */
+#define WM8996_AIF2TX_CHAN0_SLOTS_MASK          0x01C0  /* AIF2TX_CHAN0_SLOTS - [8:6] */
+#define WM8996_AIF2TX_CHAN0_SLOTS_SHIFT              6  /* AIF2TX_CHAN0_SLOTS - [8:6] */
+#define WM8996_AIF2TX_CHAN0_SLOTS_WIDTH              3  /* AIF2TX_CHAN0_SLOTS - [8:6] */
+#define WM8996_AIF2TX_CHAN0_START_SLOT_MASK     0x003F  /* AIF2TX_CHAN0_START_SLOT - [5:0] */
+#define WM8996_AIF2TX_CHAN0_START_SLOT_SHIFT         0  /* AIF2TX_CHAN0_START_SLOT - [5:0] */
+#define WM8996_AIF2TX_CHAN0_START_SLOT_WIDTH         6  /* AIF2TX_CHAN0_START_SLOT - [5:0] */
+
+/*
+ * R810 (0x32A) - AIF2TX Channel 1 Configuration
+ */
+#define WM8996_AIF2TX_CHAN1_DAT_INV             0x8000  /* AIF2TX_CHAN1_DAT_INV */
+#define WM8996_AIF2TX_CHAN1_DAT_INV_MASK        0x8000  /* AIF2TX_CHAN1_DAT_INV */
+#define WM8996_AIF2TX_CHAN1_DAT_INV_SHIFT           15  /* AIF2TX_CHAN1_DAT_INV */
+#define WM8996_AIF2TX_CHAN1_DAT_INV_WIDTH            1  /* AIF2TX_CHAN1_DAT_INV */
+#define WM8996_AIF2TX_CHAN1_SPACING_MASK        0x7E00  /* AIF2TX_CHAN1_SPACING - [14:9] */
+#define WM8996_AIF2TX_CHAN1_SPACING_SHIFT            9  /* AIF2TX_CHAN1_SPACING - [14:9] */
+#define WM8996_AIF2TX_CHAN1_SPACING_WIDTH            6  /* AIF2TX_CHAN1_SPACING - [14:9] */
+#define WM8996_AIF2TX_CHAN1_SLOTS_MASK          0x01C0  /* AIF2TX_CHAN1_SLOTS - [8:6] */
+#define WM8996_AIF2TX_CHAN1_SLOTS_SHIFT              6  /* AIF2TX_CHAN1_SLOTS - [8:6] */
+#define WM8996_AIF2TX_CHAN1_SLOTS_WIDTH              3  /* AIF2TX_CHAN1_SLOTS - [8:6] */
+#define WM8996_AIF2TX_CHAN1_START_SLOT_MASK     0x003F  /* AIF2TX_CHAN1_START_SLOT - [5:0] */
+#define WM8996_AIF2TX_CHAN1_START_SLOT_SHIFT         0  /* AIF2TX_CHAN1_START_SLOT - [5:0] */
+#define WM8996_AIF2TX_CHAN1_START_SLOT_WIDTH         6  /* AIF2TX_CHAN1_START_SLOT - [5:0] */
+
+/*
+ * R811 (0x32B) - AIF2RX Channel 0 Configuration
+ */
+#define WM8996_AIF2RX_CHAN0_DAT_INV             0x8000  /* AIF2RX_CHAN0_DAT_INV */
+#define WM8996_AIF2RX_CHAN0_DAT_INV_MASK        0x8000  /* AIF2RX_CHAN0_DAT_INV */
+#define WM8996_AIF2RX_CHAN0_DAT_INV_SHIFT           15  /* AIF2RX_CHAN0_DAT_INV */
+#define WM8996_AIF2RX_CHAN0_DAT_INV_WIDTH            1  /* AIF2RX_CHAN0_DAT_INV */
+#define WM8996_AIF2RX_CHAN0_SPACING_MASK        0x7E00  /* AIF2RX_CHAN0_SPACING - [14:9] */
+#define WM8996_AIF2RX_CHAN0_SPACING_SHIFT            9  /* AIF2RX_CHAN0_SPACING - [14:9] */
+#define WM8996_AIF2RX_CHAN0_SPACING_WIDTH            6  /* AIF2RX_CHAN0_SPACING - [14:9] */
+#define WM8996_AIF2RX_CHAN0_SLOTS_MASK          0x01C0  /* AIF2RX_CHAN0_SLOTS - [8:6] */
+#define WM8996_AIF2RX_CHAN0_SLOTS_SHIFT              6  /* AIF2RX_CHAN0_SLOTS - [8:6] */
+#define WM8996_AIF2RX_CHAN0_SLOTS_WIDTH              3  /* AIF2RX_CHAN0_SLOTS - [8:6] */
+#define WM8996_AIF2RX_CHAN0_START_SLOT_MASK     0x003F  /* AIF2RX_CHAN0_START_SLOT - [5:0] */
+#define WM8996_AIF2RX_CHAN0_START_SLOT_SHIFT         0  /* AIF2RX_CHAN0_START_SLOT - [5:0] */
+#define WM8996_AIF2RX_CHAN0_START_SLOT_WIDTH         6  /* AIF2RX_CHAN0_START_SLOT - [5:0] */
+
+/*
+ * R812 (0x32C) - AIF2RX Channel 1 Configuration
+ */
+#define WM8996_AIF2RX_CHAN1_DAT_INV             0x8000  /* AIF2RX_CHAN1_DAT_INV */
+#define WM8996_AIF2RX_CHAN1_DAT_INV_MASK        0x8000  /* AIF2RX_CHAN1_DAT_INV */
+#define WM8996_AIF2RX_CHAN1_DAT_INV_SHIFT           15  /* AIF2RX_CHAN1_DAT_INV */
+#define WM8996_AIF2RX_CHAN1_DAT_INV_WIDTH            1  /* AIF2RX_CHAN1_DAT_INV */
+#define WM8996_AIF2RX_CHAN1_SPACING_MASK        0x7E00  /* AIF2RX_CHAN1_SPACING - [14:9] */
+#define WM8996_AIF2RX_CHAN1_SPACING_SHIFT            9  /* AIF2RX_CHAN1_SPACING - [14:9] */
+#define WM8996_AIF2RX_CHAN1_SPACING_WIDTH            6  /* AIF2RX_CHAN1_SPACING - [14:9] */
+#define WM8996_AIF2RX_CHAN1_SLOTS_MASK          0x01C0  /* AIF2RX_CHAN1_SLOTS - [8:6] */
+#define WM8996_AIF2RX_CHAN1_SLOTS_SHIFT              6  /* AIF2RX_CHAN1_SLOTS - [8:6] */
+#define WM8996_AIF2RX_CHAN1_SLOTS_WIDTH              3  /* AIF2RX_CHAN1_SLOTS - [8:6] */
+#define WM8996_AIF2RX_CHAN1_START_SLOT_MASK     0x003F  /* AIF2RX_CHAN1_START_SLOT - [5:0] */
+#define WM8996_AIF2RX_CHAN1_START_SLOT_SHIFT         0  /* AIF2RX_CHAN1_START_SLOT - [5:0] */
+#define WM8996_AIF2RX_CHAN1_START_SLOT_WIDTH         6  /* AIF2RX_CHAN1_START_SLOT - [5:0] */
+
+/*
+ * R813 (0x32D) - AIF2RX Mono Configuration
+ */
+#define WM8996_AIF2RX_CHAN0_MONO_MODE           0x0001  /* AIF2RX_CHAN0_MONO_MODE */
+#define WM8996_AIF2RX_CHAN0_MONO_MODE_MASK      0x0001  /* AIF2RX_CHAN0_MONO_MODE */
+#define WM8996_AIF2RX_CHAN0_MONO_MODE_SHIFT          0  /* AIF2RX_CHAN0_MONO_MODE */
+#define WM8996_AIF2RX_CHAN0_MONO_MODE_WIDTH          1  /* AIF2RX_CHAN0_MONO_MODE */
+
+/*
+ * R815 (0x32F) - AIF2TX Test
+ */
+#define WM8996_AIF2TX_DITHER_ENA                0x0001  /* AIF2TX_DITHER_ENA */
+#define WM8996_AIF2TX_DITHER_ENA_MASK           0x0001  /* AIF2TX_DITHER_ENA */
+#define WM8996_AIF2TX_DITHER_ENA_SHIFT               0  /* AIF2TX_DITHER_ENA */
+#define WM8996_AIF2TX_DITHER_ENA_WIDTH               1  /* AIF2TX_DITHER_ENA */
+
+/*
+ * R1024 (0x400) - DSP1 TX Left Volume
+ */
+#define WM8996_DSP1TX_VU                        0x0100  /* DSP1TX_VU */
+#define WM8996_DSP1TX_VU_MASK                   0x0100  /* DSP1TX_VU */
+#define WM8996_DSP1TX_VU_SHIFT                       8  /* DSP1TX_VU */
+#define WM8996_DSP1TX_VU_WIDTH                       1  /* DSP1TX_VU */
+#define WM8996_DSP1TXL_VOL_MASK                 0x00FF  /* DSP1TXL_VOL - [7:0] */
+#define WM8996_DSP1TXL_VOL_SHIFT                     0  /* DSP1TXL_VOL - [7:0] */
+#define WM8996_DSP1TXL_VOL_WIDTH                     8  /* DSP1TXL_VOL - [7:0] */
+
+/*
+ * R1025 (0x401) - DSP1 TX Right Volume
+ */
+#define WM8996_DSP1TX_VU                        0x0100  /* DSP1TX_VU */
+#define WM8996_DSP1TX_VU_MASK                   0x0100  /* DSP1TX_VU */
+#define WM8996_DSP1TX_VU_SHIFT                       8  /* DSP1TX_VU */
+#define WM8996_DSP1TX_VU_WIDTH                       1  /* DSP1TX_VU */
+#define WM8996_DSP1TXR_VOL_MASK                 0x00FF  /* DSP1TXR_VOL - [7:0] */
+#define WM8996_DSP1TXR_VOL_SHIFT                     0  /* DSP1TXR_VOL - [7:0] */
+#define WM8996_DSP1TXR_VOL_WIDTH                     8  /* DSP1TXR_VOL - [7:0] */
+
+/*
+ * R1026 (0x402) - DSP1 RX Left Volume
+ */
+#define WM8996_DSP1RX_VU                        0x0100  /* DSP1RX_VU */
+#define WM8996_DSP1RX_VU_MASK                   0x0100  /* DSP1RX_VU */
+#define WM8996_DSP1RX_VU_SHIFT                       8  /* DSP1RX_VU */
+#define WM8996_DSP1RX_VU_WIDTH                       1  /* DSP1RX_VU */
+#define WM8996_DSP1RXL_VOL_MASK                 0x00FF  /* DSP1RXL_VOL - [7:0] */
+#define WM8996_DSP1RXL_VOL_SHIFT                     0  /* DSP1RXL_VOL - [7:0] */
+#define WM8996_DSP1RXL_VOL_WIDTH                     8  /* DSP1RXL_VOL - [7:0] */
+
+/*
+ * R1027 (0x403) - DSP1 RX Right Volume
+ */
+#define WM8996_DSP1RX_VU                        0x0100  /* DSP1RX_VU */
+#define WM8996_DSP1RX_VU_MASK                   0x0100  /* DSP1RX_VU */
+#define WM8996_DSP1RX_VU_SHIFT                       8  /* DSP1RX_VU */
+#define WM8996_DSP1RX_VU_WIDTH                       1  /* DSP1RX_VU */
+#define WM8996_DSP1RXR_VOL_MASK                 0x00FF  /* DSP1RXR_VOL - [7:0] */
+#define WM8996_DSP1RXR_VOL_SHIFT                     0  /* DSP1RXR_VOL - [7:0] */
+#define WM8996_DSP1RXR_VOL_WIDTH                     8  /* DSP1RXR_VOL - [7:0] */
+
+/*
+ * R1040 (0x410) - DSP1 TX Filters
+ */
+#define WM8996_DSP1TX_NF                        0x2000  /* DSP1TX_NF */
+#define WM8996_DSP1TX_NF_MASK                   0x2000  /* DSP1TX_NF */
+#define WM8996_DSP1TX_NF_SHIFT                      13  /* DSP1TX_NF */
+#define WM8996_DSP1TX_NF_WIDTH                       1  /* DSP1TX_NF */
+#define WM8996_DSP1TXL_HPF                      0x1000  /* DSP1TXL_HPF */
+#define WM8996_DSP1TXL_HPF_MASK                 0x1000  /* DSP1TXL_HPF */
+#define WM8996_DSP1TXL_HPF_SHIFT                    12  /* DSP1TXL_HPF */
+#define WM8996_DSP1TXL_HPF_WIDTH                     1  /* DSP1TXL_HPF */
+#define WM8996_DSP1TXR_HPF                      0x0800  /* DSP1TXR_HPF */
+#define WM8996_DSP1TXR_HPF_MASK                 0x0800  /* DSP1TXR_HPF */
+#define WM8996_DSP1TXR_HPF_SHIFT                    11  /* DSP1TXR_HPF */
+#define WM8996_DSP1TXR_HPF_WIDTH                     1  /* DSP1TXR_HPF */
+#define WM8996_DSP1TX_HPF_MODE_MASK             0x0018  /* DSP1TX_HPF_MODE - [4:3] */
+#define WM8996_DSP1TX_HPF_MODE_SHIFT                 3  /* DSP1TX_HPF_MODE - [4:3] */
+#define WM8996_DSP1TX_HPF_MODE_WIDTH                 2  /* DSP1TX_HPF_MODE - [4:3] */
+#define WM8996_DSP1TX_HPF_CUT_MASK              0x0007  /* DSP1TX_HPF_CUT - [2:0] */
+#define WM8996_DSP1TX_HPF_CUT_SHIFT                  0  /* DSP1TX_HPF_CUT - [2:0] */
+#define WM8996_DSP1TX_HPF_CUT_WIDTH                  3  /* DSP1TX_HPF_CUT - [2:0] */
+
+/*
+ * R1056 (0x420) - DSP1 RX Filters (1)
+ */
+#define WM8996_DSP1RX_MUTE                      0x0200  /* DSP1RX_MUTE */
+#define WM8996_DSP1RX_MUTE_MASK                 0x0200  /* DSP1RX_MUTE */
+#define WM8996_DSP1RX_MUTE_SHIFT                     9  /* DSP1RX_MUTE */
+#define WM8996_DSP1RX_MUTE_WIDTH                     1  /* DSP1RX_MUTE */
+#define WM8996_DSP1RX_MONO                      0x0080  /* DSP1RX_MONO */
+#define WM8996_DSP1RX_MONO_MASK                 0x0080  /* DSP1RX_MONO */
+#define WM8996_DSP1RX_MONO_SHIFT                     7  /* DSP1RX_MONO */
+#define WM8996_DSP1RX_MONO_WIDTH                     1  /* DSP1RX_MONO */
+#define WM8996_DSP1RX_MUTERATE                  0x0020  /* DSP1RX_MUTERATE */
+#define WM8996_DSP1RX_MUTERATE_MASK             0x0020  /* DSP1RX_MUTERATE */
+#define WM8996_DSP1RX_MUTERATE_SHIFT                 5  /* DSP1RX_MUTERATE */
+#define WM8996_DSP1RX_MUTERATE_WIDTH                 1  /* DSP1RX_MUTERATE */
+#define WM8996_DSP1RX_UNMUTE_RAMP               0x0010  /* DSP1RX_UNMUTE_RAMP */
+#define WM8996_DSP1RX_UNMUTE_RAMP_MASK          0x0010  /* DSP1RX_UNMUTE_RAMP */
+#define WM8996_DSP1RX_UNMUTE_RAMP_SHIFT              4  /* DSP1RX_UNMUTE_RAMP */
+#define WM8996_DSP1RX_UNMUTE_RAMP_WIDTH              1  /* DSP1RX_UNMUTE_RAMP */
+
+/*
+ * R1057 (0x421) - DSP1 RX Filters (2)
+ */
+#define WM8996_DSP1RX_3D_GAIN_MASK              0x3E00  /* DSP1RX_3D_GAIN - [13:9] */
+#define WM8996_DSP1RX_3D_GAIN_SHIFT                  9  /* DSP1RX_3D_GAIN - [13:9] */
+#define WM8996_DSP1RX_3D_GAIN_WIDTH                  5  /* DSP1RX_3D_GAIN - [13:9] */
+#define WM8996_DSP1RX_3D_ENA                    0x0100  /* DSP1RX_3D_ENA */
+#define WM8996_DSP1RX_3D_ENA_MASK               0x0100  /* DSP1RX_3D_ENA */
+#define WM8996_DSP1RX_3D_ENA_SHIFT                   8  /* DSP1RX_3D_ENA */
+#define WM8996_DSP1RX_3D_ENA_WIDTH                   1  /* DSP1RX_3D_ENA */
+
+/*
+ * R1088 (0x440) - DSP1 DRC (1)
+ */
+#define WM8996_DSP1DRC_SIG_DET_RMS_MASK         0xF800  /* DSP1DRC_SIG_DET_RMS - [15:11] */
+#define WM8996_DSP1DRC_SIG_DET_RMS_SHIFT            11  /* DSP1DRC_SIG_DET_RMS - [15:11] */
+#define WM8996_DSP1DRC_SIG_DET_RMS_WIDTH             5  /* DSP1DRC_SIG_DET_RMS - [15:11] */
+#define WM8996_DSP1DRC_SIG_DET_PK_MASK          0x0600  /* DSP1DRC_SIG_DET_PK - [10:9] */
+#define WM8996_DSP1DRC_SIG_DET_PK_SHIFT              9  /* DSP1DRC_SIG_DET_PK - [10:9] */
+#define WM8996_DSP1DRC_SIG_DET_PK_WIDTH              2  /* DSP1DRC_SIG_DET_PK - [10:9] */
+#define WM8996_DSP1DRC_NG_ENA                   0x0100  /* DSP1DRC_NG_ENA */
+#define WM8996_DSP1DRC_NG_ENA_MASK              0x0100  /* DSP1DRC_NG_ENA */
+#define WM8996_DSP1DRC_NG_ENA_SHIFT                  8  /* DSP1DRC_NG_ENA */
+#define WM8996_DSP1DRC_NG_ENA_WIDTH                  1  /* DSP1DRC_NG_ENA */
+#define WM8996_DSP1DRC_SIG_DET_MODE             0x0080  /* DSP1DRC_SIG_DET_MODE */
+#define WM8996_DSP1DRC_SIG_DET_MODE_MASK        0x0080  /* DSP1DRC_SIG_DET_MODE */
+#define WM8996_DSP1DRC_SIG_DET_MODE_SHIFT            7  /* DSP1DRC_SIG_DET_MODE */
+#define WM8996_DSP1DRC_SIG_DET_MODE_WIDTH            1  /* DSP1DRC_SIG_DET_MODE */
+#define WM8996_DSP1DRC_SIG_DET                  0x0040  /* DSP1DRC_SIG_DET */
+#define WM8996_DSP1DRC_SIG_DET_MASK             0x0040  /* DSP1DRC_SIG_DET */
+#define WM8996_DSP1DRC_SIG_DET_SHIFT                 6  /* DSP1DRC_SIG_DET */
+#define WM8996_DSP1DRC_SIG_DET_WIDTH                 1  /* DSP1DRC_SIG_DET */
+#define WM8996_DSP1DRC_KNEE2_OP_ENA             0x0020  /* DSP1DRC_KNEE2_OP_ENA */
+#define WM8996_DSP1DRC_KNEE2_OP_ENA_MASK        0x0020  /* DSP1DRC_KNEE2_OP_ENA */
+#define WM8996_DSP1DRC_KNEE2_OP_ENA_SHIFT            5  /* DSP1DRC_KNEE2_OP_ENA */
+#define WM8996_DSP1DRC_KNEE2_OP_ENA_WIDTH            1  /* DSP1DRC_KNEE2_OP_ENA */
+#define WM8996_DSP1DRC_QR                       0x0010  /* DSP1DRC_QR */
+#define WM8996_DSP1DRC_QR_MASK                  0x0010  /* DSP1DRC_QR */
+#define WM8996_DSP1DRC_QR_SHIFT                      4  /* DSP1DRC_QR */
+#define WM8996_DSP1DRC_QR_WIDTH                      1  /* DSP1DRC_QR */
+#define WM8996_DSP1DRC_ANTICLIP                 0x0008  /* DSP1DRC_ANTICLIP */
+#define WM8996_DSP1DRC_ANTICLIP_MASK            0x0008  /* DSP1DRC_ANTICLIP */
+#define WM8996_DSP1DRC_ANTICLIP_SHIFT                3  /* DSP1DRC_ANTICLIP */
+#define WM8996_DSP1DRC_ANTICLIP_WIDTH                1  /* DSP1DRC_ANTICLIP */
+#define WM8996_DSP1RX_DRC_ENA                   0x0004  /* DSP1RX_DRC_ENA */
+#define WM8996_DSP1RX_DRC_ENA_MASK              0x0004  /* DSP1RX_DRC_ENA */
+#define WM8996_DSP1RX_DRC_ENA_SHIFT                  2  /* DSP1RX_DRC_ENA */
+#define WM8996_DSP1RX_DRC_ENA_WIDTH                  1  /* DSP1RX_DRC_ENA */
+#define WM8996_DSP1TXL_DRC_ENA                  0x0002  /* DSP1TXL_DRC_ENA */
+#define WM8996_DSP1TXL_DRC_ENA_MASK             0x0002  /* DSP1TXL_DRC_ENA */
+#define WM8996_DSP1TXL_DRC_ENA_SHIFT                 1  /* DSP1TXL_DRC_ENA */
+#define WM8996_DSP1TXL_DRC_ENA_WIDTH                 1  /* DSP1TXL_DRC_ENA */
+#define WM8996_DSP1TXR_DRC_ENA                  0x0001  /* DSP1TXR_DRC_ENA */
+#define WM8996_DSP1TXR_DRC_ENA_MASK             0x0001  /* DSP1TXR_DRC_ENA */
+#define WM8996_DSP1TXR_DRC_ENA_SHIFT                 0  /* DSP1TXR_DRC_ENA */
+#define WM8996_DSP1TXR_DRC_ENA_WIDTH                 1  /* DSP1TXR_DRC_ENA */
+
+/*
+ * R1089 (0x441) - DSP1 DRC (2)
+ */
+#define WM8996_DSP1DRC_ATK_MASK                 0x1E00  /* DSP1DRC_ATK - [12:9] */
+#define WM8996_DSP1DRC_ATK_SHIFT                     9  /* DSP1DRC_ATK - [12:9] */
+#define WM8996_DSP1DRC_ATK_WIDTH                     4  /* DSP1DRC_ATK - [12:9] */
+#define WM8996_DSP1DRC_DCY_MASK                 0x01E0  /* DSP1DRC_DCY - [8:5] */
+#define WM8996_DSP1DRC_DCY_SHIFT                     5  /* DSP1DRC_DCY - [8:5] */
+#define WM8996_DSP1DRC_DCY_WIDTH                     4  /* DSP1DRC_DCY - [8:5] */
+#define WM8996_DSP1DRC_MINGAIN_MASK             0x001C  /* DSP1DRC_MINGAIN - [4:2] */
+#define WM8996_DSP1DRC_MINGAIN_SHIFT                 2  /* DSP1DRC_MINGAIN - [4:2] */
+#define WM8996_DSP1DRC_MINGAIN_WIDTH                 3  /* DSP1DRC_MINGAIN - [4:2] */
+#define WM8996_DSP1DRC_MAXGAIN_MASK             0x0003  /* DSP1DRC_MAXGAIN - [1:0] */
+#define WM8996_DSP1DRC_MAXGAIN_SHIFT                 0  /* DSP1DRC_MAXGAIN - [1:0] */
+#define WM8996_DSP1DRC_MAXGAIN_WIDTH                 2  /* DSP1DRC_MAXGAIN - [1:0] */
+
+/*
+ * R1090 (0x442) - DSP1 DRC (3)
+ */
+#define WM8996_DSP1DRC_NG_MINGAIN_MASK          0xF000  /* DSP1DRC_NG_MINGAIN - [15:12] */
+#define WM8996_DSP1DRC_NG_MINGAIN_SHIFT             12  /* DSP1DRC_NG_MINGAIN - [15:12] */
+#define WM8996_DSP1DRC_NG_MINGAIN_WIDTH              4  /* DSP1DRC_NG_MINGAIN - [15:12] */
+#define WM8996_DSP1DRC_NG_EXP_MASK              0x0C00  /* DSP1DRC_NG_EXP - [11:10] */
+#define WM8996_DSP1DRC_NG_EXP_SHIFT                 10  /* DSP1DRC_NG_EXP - [11:10] */
+#define WM8996_DSP1DRC_NG_EXP_WIDTH                  2  /* DSP1DRC_NG_EXP - [11:10] */
+#define WM8996_DSP1DRC_QR_THR_MASK              0x0300  /* DSP1DRC_QR_THR - [9:8] */
+#define WM8996_DSP1DRC_QR_THR_SHIFT                  8  /* DSP1DRC_QR_THR - [9:8] */
+#define WM8996_DSP1DRC_QR_THR_WIDTH                  2  /* DSP1DRC_QR_THR - [9:8] */
+#define WM8996_DSP1DRC_QR_DCY_MASK              0x00C0  /* DSP1DRC_QR_DCY - [7:6] */
+#define WM8996_DSP1DRC_QR_DCY_SHIFT                  6  /* DSP1DRC_QR_DCY - [7:6] */
+#define WM8996_DSP1DRC_QR_DCY_WIDTH                  2  /* DSP1DRC_QR_DCY - [7:6] */
+#define WM8996_DSP1DRC_HI_COMP_MASK             0x0038  /* DSP1DRC_HI_COMP - [5:3] */
+#define WM8996_DSP1DRC_HI_COMP_SHIFT                 3  /* DSP1DRC_HI_COMP - [5:3] */
+#define WM8996_DSP1DRC_HI_COMP_WIDTH                 3  /* DSP1DRC_HI_COMP - [5:3] */
+#define WM8996_DSP1DRC_LO_COMP_MASK             0x0007  /* DSP1DRC_LO_COMP - [2:0] */
+#define WM8996_DSP1DRC_LO_COMP_SHIFT                 0  /* DSP1DRC_LO_COMP - [2:0] */
+#define WM8996_DSP1DRC_LO_COMP_WIDTH                 3  /* DSP1DRC_LO_COMP - [2:0] */
+
+/*
+ * R1091 (0x443) - DSP1 DRC (4)
+ */
+#define WM8996_DSP1DRC_KNEE_IP_MASK             0x07E0  /* DSP1DRC_KNEE_IP - [10:5] */
+#define WM8996_DSP1DRC_KNEE_IP_SHIFT                 5  /* DSP1DRC_KNEE_IP - [10:5] */
+#define WM8996_DSP1DRC_KNEE_IP_WIDTH                 6  /* DSP1DRC_KNEE_IP - [10:5] */
+#define WM8996_DSP1DRC_KNEE_OP_MASK             0x001F  /* DSP1DRC_KNEE_OP - [4:0] */
+#define WM8996_DSP1DRC_KNEE_OP_SHIFT                 0  /* DSP1DRC_KNEE_OP - [4:0] */
+#define WM8996_DSP1DRC_KNEE_OP_WIDTH                 5  /* DSP1DRC_KNEE_OP - [4:0] */
+
+/*
+ * R1092 (0x444) - DSP1 DRC (5)
+ */
+#define WM8996_DSP1DRC_KNEE2_IP_MASK            0x03E0  /* DSP1DRC_KNEE2_IP - [9:5] */
+#define WM8996_DSP1DRC_KNEE2_IP_SHIFT                5  /* DSP1DRC_KNEE2_IP - [9:5] */
+#define WM8996_DSP1DRC_KNEE2_IP_WIDTH                5  /* DSP1DRC_KNEE2_IP - [9:5] */
+#define WM8996_DSP1DRC_KNEE2_OP_MASK            0x001F  /* DSP1DRC_KNEE2_OP - [4:0] */
+#define WM8996_DSP1DRC_KNEE2_OP_SHIFT                0  /* DSP1DRC_KNEE2_OP - [4:0] */
+#define WM8996_DSP1DRC_KNEE2_OP_WIDTH                5  /* DSP1DRC_KNEE2_OP - [4:0] */
+
+/*
+ * R1152 (0x480) - DSP1 RX EQ Gains (1)
+ */
+#define WM8996_DSP1RX_EQ_B1_GAIN_MASK           0xF800  /* DSP1RX_EQ_B1_GAIN - [15:11] */
+#define WM8996_DSP1RX_EQ_B1_GAIN_SHIFT              11  /* DSP1RX_EQ_B1_GAIN - [15:11] */
+#define WM8996_DSP1RX_EQ_B1_GAIN_WIDTH               5  /* DSP1RX_EQ_B1_GAIN - [15:11] */
+#define WM8996_DSP1RX_EQ_B2_GAIN_MASK           0x07C0  /* DSP1RX_EQ_B2_GAIN - [10:6] */
+#define WM8996_DSP1RX_EQ_B2_GAIN_SHIFT               6  /* DSP1RX_EQ_B2_GAIN - [10:6] */
+#define WM8996_DSP1RX_EQ_B2_GAIN_WIDTH               5  /* DSP1RX_EQ_B2_GAIN - [10:6] */
+#define WM8996_DSP1RX_EQ_B3_GAIN_MASK           0x003E  /* DSP1RX_EQ_B3_GAIN - [5:1] */
+#define WM8996_DSP1RX_EQ_B3_GAIN_SHIFT               1  /* DSP1RX_EQ_B3_GAIN - [5:1] */
+#define WM8996_DSP1RX_EQ_B3_GAIN_WIDTH               5  /* DSP1RX_EQ_B3_GAIN - [5:1] */
+#define WM8996_DSP1RX_EQ_ENA                    0x0001  /* DSP1RX_EQ_ENA */
+#define WM8996_DSP1RX_EQ_ENA_MASK               0x0001  /* DSP1RX_EQ_ENA */
+#define WM8996_DSP1RX_EQ_ENA_SHIFT                   0  /* DSP1RX_EQ_ENA */
+#define WM8996_DSP1RX_EQ_ENA_WIDTH                   1  /* DSP1RX_EQ_ENA */
+
+/*
+ * R1153 (0x481) - DSP1 RX EQ Gains (2)
+ */
+#define WM8996_DSP1RX_EQ_B4_GAIN_MASK           0xF800  /* DSP1RX_EQ_B4_GAIN - [15:11] */
+#define WM8996_DSP1RX_EQ_B4_GAIN_SHIFT              11  /* DSP1RX_EQ_B4_GAIN - [15:11] */
+#define WM8996_DSP1RX_EQ_B4_GAIN_WIDTH               5  /* DSP1RX_EQ_B4_GAIN - [15:11] */
+#define WM8996_DSP1RX_EQ_B5_GAIN_MASK           0x07C0  /* DSP1RX_EQ_B5_GAIN - [10:6] */
+#define WM8996_DSP1RX_EQ_B5_GAIN_SHIFT               6  /* DSP1RX_EQ_B5_GAIN - [10:6] */
+#define WM8996_DSP1RX_EQ_B5_GAIN_WIDTH               5  /* DSP1RX_EQ_B5_GAIN - [10:6] */
+
+/*
+ * R1154 (0x482) - DSP1 RX EQ Band 1 A
+ */
+#define WM8996_DSP1RX_EQ_B1_A_MASK              0xFFFF  /* DSP1RX_EQ_B1_A - [15:0] */
+#define WM8996_DSP1RX_EQ_B1_A_SHIFT                  0  /* DSP1RX_EQ_B1_A - [15:0] */
+#define WM8996_DSP1RX_EQ_B1_A_WIDTH                 16  /* DSP1RX_EQ_B1_A - [15:0] */
+
+/*
+ * R1155 (0x483) - DSP1 RX EQ Band 1 B
+ */
+#define WM8996_DSP1RX_EQ_B1_B_MASK              0xFFFF  /* DSP1RX_EQ_B1_B - [15:0] */
+#define WM8996_DSP1RX_EQ_B1_B_SHIFT                  0  /* DSP1RX_EQ_B1_B - [15:0] */
+#define WM8996_DSP1RX_EQ_B1_B_WIDTH                 16  /* DSP1RX_EQ_B1_B - [15:0] */
+
+/*
+ * R1156 (0x484) - DSP1 RX EQ Band 1 PG
+ */
+#define WM8996_DSP1RX_EQ_B1_PG_MASK             0xFFFF  /* DSP1RX_EQ_B1_PG - [15:0] */
+#define WM8996_DSP1RX_EQ_B1_PG_SHIFT                 0  /* DSP1RX_EQ_B1_PG - [15:0] */
+#define WM8996_DSP1RX_EQ_B1_PG_WIDTH                16  /* DSP1RX_EQ_B1_PG - [15:0] */
+
+/*
+ * R1157 (0x485) - DSP1 RX EQ Band 2 A
+ */
+#define WM8996_DSP1RX_EQ_B2_A_MASK              0xFFFF  /* DSP1RX_EQ_B2_A - [15:0] */
+#define WM8996_DSP1RX_EQ_B2_A_SHIFT                  0  /* DSP1RX_EQ_B2_A - [15:0] */
+#define WM8996_DSP1RX_EQ_B2_A_WIDTH                 16  /* DSP1RX_EQ_B2_A - [15:0] */
+
+/*
+ * R1158 (0x486) - DSP1 RX EQ Band 2 B
+ */
+#define WM8996_DSP1RX_EQ_B2_B_MASK              0xFFFF  /* DSP1RX_EQ_B2_B - [15:0] */
+#define WM8996_DSP1RX_EQ_B2_B_SHIFT                  0  /* DSP1RX_EQ_B2_B - [15:0] */
+#define WM8996_DSP1RX_EQ_B2_B_WIDTH                 16  /* DSP1RX_EQ_B2_B - [15:0] */
+
+/*
+ * R1159 (0x487) - DSP1 RX EQ Band 2 C
+ */
+#define WM8996_DSP1RX_EQ_B2_C_MASK              0xFFFF  /* DSP1RX_EQ_B2_C - [15:0] */
+#define WM8996_DSP1RX_EQ_B2_C_SHIFT                  0  /* DSP1RX_EQ_B2_C - [15:0] */
+#define WM8996_DSP1RX_EQ_B2_C_WIDTH                 16  /* DSP1RX_EQ_B2_C - [15:0] */
+
+/*
+ * R1160 (0x488) - DSP1 RX EQ Band 2 PG
+ */
+#define WM8996_DSP1RX_EQ_B2_PG_MASK             0xFFFF  /* DSP1RX_EQ_B2_PG - [15:0] */
+#define WM8996_DSP1RX_EQ_B2_PG_SHIFT                 0  /* DSP1RX_EQ_B2_PG - [15:0] */
+#define WM8996_DSP1RX_EQ_B2_PG_WIDTH                16  /* DSP1RX_EQ_B2_PG - [15:0] */
+
+/*
+ * R1161 (0x489) - DSP1 RX EQ Band 3 A
+ */
+#define WM8996_DSP1RX_EQ_B3_A_MASK              0xFFFF  /* DSP1RX_EQ_B3_A - [15:0] */
+#define WM8996_DSP1RX_EQ_B3_A_SHIFT                  0  /* DSP1RX_EQ_B3_A - [15:0] */
+#define WM8996_DSP1RX_EQ_B3_A_WIDTH                 16  /* DSP1RX_EQ_B3_A - [15:0] */
+
+/*
+ * R1162 (0x48A) - DSP1 RX EQ Band 3 B
+ */
+#define WM8996_DSP1RX_EQ_B3_B_MASK              0xFFFF  /* DSP1RX_EQ_B3_B - [15:0] */
+#define WM8996_DSP1RX_EQ_B3_B_SHIFT                  0  /* DSP1RX_EQ_B3_B - [15:0] */
+#define WM8996_DSP1RX_EQ_B3_B_WIDTH                 16  /* DSP1RX_EQ_B3_B - [15:0] */
+
+/*
+ * R1163 (0x48B) - DSP1 RX EQ Band 3 C
+ */
+#define WM8996_DSP1RX_EQ_B3_C_MASK              0xFFFF  /* DSP1RX_EQ_B3_C - [15:0] */
+#define WM8996_DSP1RX_EQ_B3_C_SHIFT                  0  /* DSP1RX_EQ_B3_C - [15:0] */
+#define WM8996_DSP1RX_EQ_B3_C_WIDTH                 16  /* DSP1RX_EQ_B3_C - [15:0] */
+
+/*
+ * R1164 (0x48C) - DSP1 RX EQ Band 3 PG
+ */
+#define WM8996_DSP1RX_EQ_B3_PG_MASK             0xFFFF  /* DSP1RX_EQ_B3_PG - [15:0] */
+#define WM8996_DSP1RX_EQ_B3_PG_SHIFT                 0  /* DSP1RX_EQ_B3_PG - [15:0] */
+#define WM8996_DSP1RX_EQ_B3_PG_WIDTH                16  /* DSP1RX_EQ_B3_PG - [15:0] */
+
+/*
+ * R1165 (0x48D) - DSP1 RX EQ Band 4 A
+ */
+#define WM8996_DSP1RX_EQ_B4_A_MASK              0xFFFF  /* DSP1RX_EQ_B4_A - [15:0] */
+#define WM8996_DSP1RX_EQ_B4_A_SHIFT                  0  /* DSP1RX_EQ_B4_A - [15:0] */
+#define WM8996_DSP1RX_EQ_B4_A_WIDTH                 16  /* DSP1RX_EQ_B4_A - [15:0] */
+
+/*
+ * R1166 (0x48E) - DSP1 RX EQ Band 4 B
+ */
+#define WM8996_DSP1RX_EQ_B4_B_MASK              0xFFFF  /* DSP1RX_EQ_B4_B - [15:0] */
+#define WM8996_DSP1RX_EQ_B4_B_SHIFT                  0  /* DSP1RX_EQ_B4_B - [15:0] */
+#define WM8996_DSP1RX_EQ_B4_B_WIDTH                 16  /* DSP1RX_EQ_B4_B - [15:0] */
+
+/*
+ * R1167 (0x48F) - DSP1 RX EQ Band 4 C
+ */
+#define WM8996_DSP1RX_EQ_B4_C_MASK              0xFFFF  /* DSP1RX_EQ_B4_C - [15:0] */
+#define WM8996_DSP1RX_EQ_B4_C_SHIFT                  0  /* DSP1RX_EQ_B4_C - [15:0] */
+#define WM8996_DSP1RX_EQ_B4_C_WIDTH                 16  /* DSP1RX_EQ_B4_C - [15:0] */
+
+/*
+ * R1168 (0x490) - DSP1 RX EQ Band 4 PG
+ */
+#define WM8996_DSP1RX_EQ_B4_PG_MASK             0xFFFF  /* DSP1RX_EQ_B4_PG - [15:0] */
+#define WM8996_DSP1RX_EQ_B4_PG_SHIFT                 0  /* DSP1RX_EQ_B4_PG - [15:0] */
+#define WM8996_DSP1RX_EQ_B4_PG_WIDTH                16  /* DSP1RX_EQ_B4_PG - [15:0] */
+
+/*
+ * R1169 (0x491) - DSP1 RX EQ Band 5 A
+ */
+#define WM8996_DSP1RX_EQ_B5_A_MASK              0xFFFF  /* DSP1RX_EQ_B5_A - [15:0] */
+#define WM8996_DSP1RX_EQ_B5_A_SHIFT                  0  /* DSP1RX_EQ_B5_A - [15:0] */
+#define WM8996_DSP1RX_EQ_B5_A_WIDTH                 16  /* DSP1RX_EQ_B5_A - [15:0] */
+
+/*
+ * R1170 (0x492) - DSP1 RX EQ Band 5 B
+ */
+#define WM8996_DSP1RX_EQ_B5_B_MASK              0xFFFF  /* DSP1RX_EQ_B5_B - [15:0] */
+#define WM8996_DSP1RX_EQ_B5_B_SHIFT                  0  /* DSP1RX_EQ_B5_B - [15:0] */
+#define WM8996_DSP1RX_EQ_B5_B_WIDTH                 16  /* DSP1RX_EQ_B5_B - [15:0] */
+
+/*
+ * R1171 (0x493) - DSP1 RX EQ Band 5 PG
+ */
+#define WM8996_DSP1RX_EQ_B5_PG_MASK             0xFFFF  /* DSP1RX_EQ_B5_PG - [15:0] */
+#define WM8996_DSP1RX_EQ_B5_PG_SHIFT                 0  /* DSP1RX_EQ_B5_PG - [15:0] */
+#define WM8996_DSP1RX_EQ_B5_PG_WIDTH                16  /* DSP1RX_EQ_B5_PG - [15:0] */
+
+/*
+ * R1280 (0x500) - DSP2 TX Left Volume
+ */
+#define WM8996_DSP2TX_VU                        0x0100  /* DSP2TX_VU */
+#define WM8996_DSP2TX_VU_MASK                   0x0100  /* DSP2TX_VU */
+#define WM8996_DSP2TX_VU_SHIFT                       8  /* DSP2TX_VU */
+#define WM8996_DSP2TX_VU_WIDTH                       1  /* DSP2TX_VU */
+#define WM8996_DSP2TXL_VOL_MASK                 0x00FF  /* DSP2TXL_VOL - [7:0] */
+#define WM8996_DSP2TXL_VOL_SHIFT                     0  /* DSP2TXL_VOL - [7:0] */
+#define WM8996_DSP2TXL_VOL_WIDTH                     8  /* DSP2TXL_VOL - [7:0] */
+
+/*
+ * R1281 (0x501) - DSP2 TX Right Volume
+ */
+#define WM8996_DSP2TX_VU                        0x0100  /* DSP2TX_VU */
+#define WM8996_DSP2TX_VU_MASK                   0x0100  /* DSP2TX_VU */
+#define WM8996_DSP2TX_VU_SHIFT                       8  /* DSP2TX_VU */
+#define WM8996_DSP2TX_VU_WIDTH                       1  /* DSP2TX_VU */
+#define WM8996_DSP2TXR_VOL_MASK                 0x00FF  /* DSP2TXR_VOL - [7:0] */
+#define WM8996_DSP2TXR_VOL_SHIFT                     0  /* DSP2TXR_VOL - [7:0] */
+#define WM8996_DSP2TXR_VOL_WIDTH                     8  /* DSP2TXR_VOL - [7:0] */
+
+/*
+ * R1282 (0x502) - DSP2 RX Left Volume
+ */
+#define WM8996_DSP2RX_VU                        0x0100  /* DSP2RX_VU */
+#define WM8996_DSP2RX_VU_MASK                   0x0100  /* DSP2RX_VU */
+#define WM8996_DSP2RX_VU_SHIFT                       8  /* DSP2RX_VU */
+#define WM8996_DSP2RX_VU_WIDTH                       1  /* DSP2RX_VU */
+#define WM8996_DSP2RXL_VOL_MASK                 0x00FF  /* DSP2RXL_VOL - [7:0] */
+#define WM8996_DSP2RXL_VOL_SHIFT                     0  /* DSP2RXL_VOL - [7:0] */
+#define WM8996_DSP2RXL_VOL_WIDTH                     8  /* DSP2RXL_VOL - [7:0] */
+
+/*
+ * R1283 (0x503) - DSP2 RX Right Volume
+ */
+#define WM8996_DSP2RX_VU                        0x0100  /* DSP2RX_VU */
+#define WM8996_DSP2RX_VU_MASK                   0x0100  /* DSP2RX_VU */
+#define WM8996_DSP2RX_VU_SHIFT                       8  /* DSP2RX_VU */
+#define WM8996_DSP2RX_VU_WIDTH                       1  /* DSP2RX_VU */
+#define WM8996_DSP2RXR_VOL_MASK                 0x00FF  /* DSP2RXR_VOL - [7:0] */
+#define WM8996_DSP2RXR_VOL_SHIFT                     0  /* DSP2RXR_VOL - [7:0] */
+#define WM8996_DSP2RXR_VOL_WIDTH                     8  /* DSP2RXR_VOL - [7:0] */
+
+/*
+ * R1296 (0x510) - DSP2 TX Filters
+ */
+#define WM8996_DSP2TX_NF                        0x2000  /* DSP2TX_NF */
+#define WM8996_DSP2TX_NF_MASK                   0x2000  /* DSP2TX_NF */
+#define WM8996_DSP2TX_NF_SHIFT                      13  /* DSP2TX_NF */
+#define WM8996_DSP2TX_NF_WIDTH                       1  /* DSP2TX_NF */
+#define WM8996_DSP2TXL_HPF                      0x1000  /* DSP2TXL_HPF */
+#define WM8996_DSP2TXL_HPF_MASK                 0x1000  /* DSP2TXL_HPF */
+#define WM8996_DSP2TXL_HPF_SHIFT                    12  /* DSP2TXL_HPF */
+#define WM8996_DSP2TXL_HPF_WIDTH                     1  /* DSP2TXL_HPF */
+#define WM8996_DSP2TXR_HPF                      0x0800  /* DSP2TXR_HPF */
+#define WM8996_DSP2TXR_HPF_MASK                 0x0800  /* DSP2TXR_HPF */
+#define WM8996_DSP2TXR_HPF_SHIFT                    11  /* DSP2TXR_HPF */
+#define WM8996_DSP2TXR_HPF_WIDTH                     1  /* DSP2TXR_HPF */
+#define WM8996_DSP2TX_HPF_MODE_MASK             0x0018  /* DSP2TX_HPF_MODE - [4:3] */
+#define WM8996_DSP2TX_HPF_MODE_SHIFT                 3  /* DSP2TX_HPF_MODE - [4:3] */
+#define WM8996_DSP2TX_HPF_MODE_WIDTH                 2  /* DSP2TX_HPF_MODE - [4:3] */
+#define WM8996_DSP2TX_HPF_CUT_MASK              0x0007  /* DSP2TX_HPF_CUT - [2:0] */
+#define WM8996_DSP2TX_HPF_CUT_SHIFT                  0  /* DSP2TX_HPF_CUT - [2:0] */
+#define WM8996_DSP2TX_HPF_CUT_WIDTH                  3  /* DSP2TX_HPF_CUT - [2:0] */
+
+/*
+ * R1312 (0x520) - DSP2 RX Filters (1)
+ */
+#define WM8996_DSP2RX_MUTE                      0x0200  /* DSP2RX_MUTE */
+#define WM8996_DSP2RX_MUTE_MASK                 0x0200  /* DSP2RX_MUTE */
+#define WM8996_DSP2RX_MUTE_SHIFT                     9  /* DSP2RX_MUTE */
+#define WM8996_DSP2RX_MUTE_WIDTH                     1  /* DSP2RX_MUTE */
+#define WM8996_DSP2RX_MONO                      0x0080  /* DSP2RX_MONO */
+#define WM8996_DSP2RX_MONO_MASK                 0x0080  /* DSP2RX_MONO */
+#define WM8996_DSP2RX_MONO_SHIFT                     7  /* DSP2RX_MONO */
+#define WM8996_DSP2RX_MONO_WIDTH                     1  /* DSP2RX_MONO */
+#define WM8996_DSP2RX_MUTERATE                  0x0020  /* DSP2RX_MUTERATE */
+#define WM8996_DSP2RX_MUTERATE_MASK             0x0020  /* DSP2RX_MUTERATE */
+#define WM8996_DSP2RX_MUTERATE_SHIFT                 5  /* DSP2RX_MUTERATE */
+#define WM8996_DSP2RX_MUTERATE_WIDTH                 1  /* DSP2RX_MUTERATE */
+#define WM8996_DSP2RX_UNMUTE_RAMP               0x0010  /* DSP2RX_UNMUTE_RAMP */
+#define WM8996_DSP2RX_UNMUTE_RAMP_MASK          0x0010  /* DSP2RX_UNMUTE_RAMP */
+#define WM8996_DSP2RX_UNMUTE_RAMP_SHIFT              4  /* DSP2RX_UNMUTE_RAMP */
+#define WM8996_DSP2RX_UNMUTE_RAMP_WIDTH              1  /* DSP2RX_UNMUTE_RAMP */
+
+/*
+ * R1313 (0x521) - DSP2 RX Filters (2)
+ */
+#define WM8996_DSP2RX_3D_GAIN_MASK              0x3E00  /* DSP2RX_3D_GAIN - [13:9] */
+#define WM8996_DSP2RX_3D_GAIN_SHIFT                  9  /* DSP2RX_3D_GAIN - [13:9] */
+#define WM8996_DSP2RX_3D_GAIN_WIDTH                  5  /* DSP2RX_3D_GAIN - [13:9] */
+#define WM8996_DSP2RX_3D_ENA                    0x0100  /* DSP2RX_3D_ENA */
+#define WM8996_DSP2RX_3D_ENA_MASK               0x0100  /* DSP2RX_3D_ENA */
+#define WM8996_DSP2RX_3D_ENA_SHIFT                   8  /* DSP2RX_3D_ENA */
+#define WM8996_DSP2RX_3D_ENA_WIDTH                   1  /* DSP2RX_3D_ENA */
+
+/*
+ * R1344 (0x540) - DSP2 DRC (1)
+ */
+#define WM8996_DSP2DRC_SIG_DET_RMS_MASK         0xF800  /* DSP2DRC_SIG_DET_RMS - [15:11] */
+#define WM8996_DSP2DRC_SIG_DET_RMS_SHIFT            11  /* DSP2DRC_SIG_DET_RMS - [15:11] */
+#define WM8996_DSP2DRC_SIG_DET_RMS_WIDTH             5  /* DSP2DRC_SIG_DET_RMS - [15:11] */
+#define WM8996_DSP2DRC_SIG_DET_PK_MASK          0x0600  /* DSP2DRC_SIG_DET_PK - [10:9] */
+#define WM8996_DSP2DRC_SIG_DET_PK_SHIFT              9  /* DSP2DRC_SIG_DET_PK - [10:9] */
+#define WM8996_DSP2DRC_SIG_DET_PK_WIDTH              2  /* DSP2DRC_SIG_DET_PK - [10:9] */
+#define WM8996_DSP2DRC_NG_ENA                   0x0100  /* DSP2DRC_NG_ENA */
+#define WM8996_DSP2DRC_NG_ENA_MASK              0x0100  /* DSP2DRC_NG_ENA */
+#define WM8996_DSP2DRC_NG_ENA_SHIFT                  8  /* DSP2DRC_NG_ENA */
+#define WM8996_DSP2DRC_NG_ENA_WIDTH                  1  /* DSP2DRC_NG_ENA */
+#define WM8996_DSP2DRC_SIG_DET_MODE             0x0080  /* DSP2DRC_SIG_DET_MODE */
+#define WM8996_DSP2DRC_SIG_DET_MODE_MASK        0x0080  /* DSP2DRC_SIG_DET_MODE */
+#define WM8996_DSP2DRC_SIG_DET_MODE_SHIFT            7  /* DSP2DRC_SIG_DET_MODE */
+#define WM8996_DSP2DRC_SIG_DET_MODE_WIDTH            1  /* DSP2DRC_SIG_DET_MODE */
+#define WM8996_DSP2DRC_SIG_DET                  0x0040  /* DSP2DRC_SIG_DET */
+#define WM8996_DSP2DRC_SIG_DET_MASK             0x0040  /* DSP2DRC_SIG_DET */
+#define WM8996_DSP2DRC_SIG_DET_SHIFT                 6  /* DSP2DRC_SIG_DET */
+#define WM8996_DSP2DRC_SIG_DET_WIDTH                 1  /* DSP2DRC_SIG_DET */
+#define WM8996_DSP2DRC_KNEE2_OP_ENA             0x0020  /* DSP2DRC_KNEE2_OP_ENA */
+#define WM8996_DSP2DRC_KNEE2_OP_ENA_MASK        0x0020  /* DSP2DRC_KNEE2_OP_ENA */
+#define WM8996_DSP2DRC_KNEE2_OP_ENA_SHIFT            5  /* DSP2DRC_KNEE2_OP_ENA */
+#define WM8996_DSP2DRC_KNEE2_OP_ENA_WIDTH            1  /* DSP2DRC_KNEE2_OP_ENA */
+#define WM8996_DSP2DRC_QR                       0x0010  /* DSP2DRC_QR */
+#define WM8996_DSP2DRC_QR_MASK                  0x0010  /* DSP2DRC_QR */
+#define WM8996_DSP2DRC_QR_SHIFT                      4  /* DSP2DRC_QR */
+#define WM8996_DSP2DRC_QR_WIDTH                      1  /* DSP2DRC_QR */
+#define WM8996_DSP2DRC_ANTICLIP                 0x0008  /* DSP2DRC_ANTICLIP */
+#define WM8996_DSP2DRC_ANTICLIP_MASK            0x0008  /* DSP2DRC_ANTICLIP */
+#define WM8996_DSP2DRC_ANTICLIP_SHIFT                3  /* DSP2DRC_ANTICLIP */
+#define WM8996_DSP2DRC_ANTICLIP_WIDTH                1  /* DSP2DRC_ANTICLIP */
+#define WM8996_DSP2RX_DRC_ENA                   0x0004  /* DSP2RX_DRC_ENA */
+#define WM8996_DSP2RX_DRC_ENA_MASK              0x0004  /* DSP2RX_DRC_ENA */
+#define WM8996_DSP2RX_DRC_ENA_SHIFT                  2  /* DSP2RX_DRC_ENA */
+#define WM8996_DSP2RX_DRC_ENA_WIDTH                  1  /* DSP2RX_DRC_ENA */
+#define WM8996_DSP2TXL_DRC_ENA                  0x0002  /* DSP2TXL_DRC_ENA */
+#define WM8996_DSP2TXL_DRC_ENA_MASK             0x0002  /* DSP2TXL_DRC_ENA */
+#define WM8996_DSP2TXL_DRC_ENA_SHIFT                 1  /* DSP2TXL_DRC_ENA */
+#define WM8996_DSP2TXL_DRC_ENA_WIDTH                 1  /* DSP2TXL_DRC_ENA */
+#define WM8996_DSP2TXR_DRC_ENA                  0x0001  /* DSP2TXR_DRC_ENA */
+#define WM8996_DSP2TXR_DRC_ENA_MASK             0x0001  /* DSP2TXR_DRC_ENA */
+#define WM8996_DSP2TXR_DRC_ENA_SHIFT                 0  /* DSP2TXR_DRC_ENA */
+#define WM8996_DSP2TXR_DRC_ENA_WIDTH                 1  /* DSP2TXR_DRC_ENA */
+
+/*
+ * R1345 (0x541) - DSP2 DRC (2)
+ */
+#define WM8996_DSP2DRC_ATK_MASK                 0x1E00  /* DSP2DRC_ATK - [12:9] */
+#define WM8996_DSP2DRC_ATK_SHIFT                     9  /* DSP2DRC_ATK - [12:9] */
+#define WM8996_DSP2DRC_ATK_WIDTH                     4  /* DSP2DRC_ATK - [12:9] */
+#define WM8996_DSP2DRC_DCY_MASK                 0x01E0  /* DSP2DRC_DCY - [8:5] */
+#define WM8996_DSP2DRC_DCY_SHIFT                     5  /* DSP2DRC_DCY - [8:5] */
+#define WM8996_DSP2DRC_DCY_WIDTH                     4  /* DSP2DRC_DCY - [8:5] */
+#define WM8996_DSP2DRC_MINGAIN_MASK             0x001C  /* DSP2DRC_MINGAIN - [4:2] */
+#define WM8996_DSP2DRC_MINGAIN_SHIFT                 2  /* DSP2DRC_MINGAIN - [4:2] */
+#define WM8996_DSP2DRC_MINGAIN_WIDTH                 3  /* DSP2DRC_MINGAIN - [4:2] */
+#define WM8996_DSP2DRC_MAXGAIN_MASK             0x0003  /* DSP2DRC_MAXGAIN - [1:0] */
+#define WM8996_DSP2DRC_MAXGAIN_SHIFT                 0  /* DSP2DRC_MAXGAIN - [1:0] */
+#define WM8996_DSP2DRC_MAXGAIN_WIDTH                 2  /* DSP2DRC_MAXGAIN - [1:0] */
+
+/*
+ * R1346 (0x542) - DSP2 DRC (3)
+ */
+#define WM8996_DSP2DRC_NG_MINGAIN_MASK          0xF000  /* DSP2DRC_NG_MINGAIN - [15:12] */
+#define WM8996_DSP2DRC_NG_MINGAIN_SHIFT             12  /* DSP2DRC_NG_MINGAIN - [15:12] */
+#define WM8996_DSP2DRC_NG_MINGAIN_WIDTH              4  /* DSP2DRC_NG_MINGAIN - [15:12] */
+#define WM8996_DSP2DRC_NG_EXP_MASK              0x0C00  /* DSP2DRC_NG_EXP - [11:10] */
+#define WM8996_DSP2DRC_NG_EXP_SHIFT                 10  /* DSP2DRC_NG_EXP - [11:10] */
+#define WM8996_DSP2DRC_NG_EXP_WIDTH                  2  /* DSP2DRC_NG_EXP - [11:10] */
+#define WM8996_DSP2DRC_QR_THR_MASK              0x0300  /* DSP2DRC_QR_THR - [9:8] */
+#define WM8996_DSP2DRC_QR_THR_SHIFT                  8  /* DSP2DRC_QR_THR - [9:8] */
+#define WM8996_DSP2DRC_QR_THR_WIDTH                  2  /* DSP2DRC_QR_THR - [9:8] */
+#define WM8996_DSP2DRC_QR_DCY_MASK              0x00C0  /* DSP2DRC_QR_DCY - [7:6] */
+#define WM8996_DSP2DRC_QR_DCY_SHIFT                  6  /* DSP2DRC_QR_DCY - [7:6] */
+#define WM8996_DSP2DRC_QR_DCY_WIDTH                  2  /* DSP2DRC_QR_DCY - [7:6] */
+#define WM8996_DSP2DRC_HI_COMP_MASK             0x0038  /* DSP2DRC_HI_COMP - [5:3] */
+#define WM8996_DSP2DRC_HI_COMP_SHIFT                 3  /* DSP2DRC_HI_COMP - [5:3] */
+#define WM8996_DSP2DRC_HI_COMP_WIDTH                 3  /* DSP2DRC_HI_COMP - [5:3] */
+#define WM8996_DSP2DRC_LO_COMP_MASK             0x0007  /* DSP2DRC_LO_COMP - [2:0] */
+#define WM8996_DSP2DRC_LO_COMP_SHIFT                 0  /* DSP2DRC_LO_COMP - [2:0] */
+#define WM8996_DSP2DRC_LO_COMP_WIDTH                 3  /* DSP2DRC_LO_COMP - [2:0] */
+
+/*
+ * R1347 (0x543) - DSP2 DRC (4)
+ */
+#define WM8996_DSP2DRC_KNEE_IP_MASK             0x07E0  /* DSP2DRC_KNEE_IP - [10:5] */
+#define WM8996_DSP2DRC_KNEE_IP_SHIFT                 5  /* DSP2DRC_KNEE_IP - [10:5] */
+#define WM8996_DSP2DRC_KNEE_IP_WIDTH                 6  /* DSP2DRC_KNEE_IP - [10:5] */
+#define WM8996_DSP2DRC_KNEE_OP_MASK             0x001F  /* DSP2DRC_KNEE_OP - [4:0] */
+#define WM8996_DSP2DRC_KNEE_OP_SHIFT                 0  /* DSP2DRC_KNEE_OP - [4:0] */
+#define WM8996_DSP2DRC_KNEE_OP_WIDTH                 5  /* DSP2DRC_KNEE_OP - [4:0] */
+
+/*
+ * R1348 (0x544) - DSP2 DRC (5)
+ */
+#define WM8996_DSP2DRC_KNEE2_IP_MASK            0x03E0  /* DSP2DRC_KNEE2_IP - [9:5] */
+#define WM8996_DSP2DRC_KNEE2_IP_SHIFT                5  /* DSP2DRC_KNEE2_IP - [9:5] */
+#define WM8996_DSP2DRC_KNEE2_IP_WIDTH                5  /* DSP2DRC_KNEE2_IP - [9:5] */
+#define WM8996_DSP2DRC_KNEE2_OP_MASK            0x001F  /* DSP2DRC_KNEE2_OP - [4:0] */
+#define WM8996_DSP2DRC_KNEE2_OP_SHIFT                0  /* DSP2DRC_KNEE2_OP - [4:0] */
+#define WM8996_DSP2DRC_KNEE2_OP_WIDTH                5  /* DSP2DRC_KNEE2_OP - [4:0] */
+
+/*
+ * R1408 (0x580) - DSP2 RX EQ Gains (1)
+ */
+#define WM8996_DSP2RX_EQ_B1_GAIN_MASK           0xF800  /* DSP2RX_EQ_B1_GAIN - [15:11] */
+#define WM8996_DSP2RX_EQ_B1_GAIN_SHIFT              11  /* DSP2RX_EQ_B1_GAIN - [15:11] */
+#define WM8996_DSP2RX_EQ_B1_GAIN_WIDTH               5  /* DSP2RX_EQ_B1_GAIN - [15:11] */
+#define WM8996_DSP2RX_EQ_B2_GAIN_MASK           0x07C0  /* DSP2RX_EQ_B2_GAIN - [10:6] */
+#define WM8996_DSP2RX_EQ_B2_GAIN_SHIFT               6  /* DSP2RX_EQ_B2_GAIN - [10:6] */
+#define WM8996_DSP2RX_EQ_B2_GAIN_WIDTH               5  /* DSP2RX_EQ_B2_GAIN - [10:6] */
+#define WM8996_DSP2RX_EQ_B3_GAIN_MASK           0x003E  /* DSP2RX_EQ_B3_GAIN - [5:1] */
+#define WM8996_DSP2RX_EQ_B3_GAIN_SHIFT               1  /* DSP2RX_EQ_B3_GAIN - [5:1] */
+#define WM8996_DSP2RX_EQ_B3_GAIN_WIDTH               5  /* DSP2RX_EQ_B3_GAIN - [5:1] */
+#define WM8996_DSP2RX_EQ_ENA                    0x0001  /* DSP2RX_EQ_ENA */
+#define WM8996_DSP2RX_EQ_ENA_MASK               0x0001  /* DSP2RX_EQ_ENA */
+#define WM8996_DSP2RX_EQ_ENA_SHIFT                   0  /* DSP2RX_EQ_ENA */
+#define WM8996_DSP2RX_EQ_ENA_WIDTH                   1  /* DSP2RX_EQ_ENA */
+
+/*
+ * R1409 (0x581) - DSP2 RX EQ Gains (2)
+ */
+#define WM8996_DSP2RX_EQ_B4_GAIN_MASK           0xF800  /* DSP2RX_EQ_B4_GAIN - [15:11] */
+#define WM8996_DSP2RX_EQ_B4_GAIN_SHIFT              11  /* DSP2RX_EQ_B4_GAIN - [15:11] */
+#define WM8996_DSP2RX_EQ_B4_GAIN_WIDTH               5  /* DSP2RX_EQ_B4_GAIN - [15:11] */
+#define WM8996_DSP2RX_EQ_B5_GAIN_MASK           0x07C0  /* DSP2RX_EQ_B5_GAIN - [10:6] */
+#define WM8996_DSP2RX_EQ_B5_GAIN_SHIFT               6  /* DSP2RX_EQ_B5_GAIN - [10:6] */
+#define WM8996_DSP2RX_EQ_B5_GAIN_WIDTH               5  /* DSP2RX_EQ_B5_GAIN - [10:6] */
+
+/*
+ * R1410 (0x582) - DSP2 RX EQ Band 1 A
+ */
+#define WM8996_DSP2RX_EQ_B1_A_MASK              0xFFFF  /* DSP2RX_EQ_B1_A - [15:0] */
+#define WM8996_DSP2RX_EQ_B1_A_SHIFT                  0  /* DSP2RX_EQ_B1_A - [15:0] */
+#define WM8996_DSP2RX_EQ_B1_A_WIDTH                 16  /* DSP2RX_EQ_B1_A - [15:0] */
+
+/*
+ * R1411 (0x583) - DSP2 RX EQ Band 1 B
+ */
+#define WM8996_DSP2RX_EQ_B1_B_MASK              0xFFFF  /* DSP2RX_EQ_B1_B - [15:0] */
+#define WM8996_DSP2RX_EQ_B1_B_SHIFT                  0  /* DSP2RX_EQ_B1_B - [15:0] */
+#define WM8996_DSP2RX_EQ_B1_B_WIDTH                 16  /* DSP2RX_EQ_B1_B - [15:0] */
+
+/*
+ * R1412 (0x584) - DSP2 RX EQ Band 1 PG
+ */
+#define WM8996_DSP2RX_EQ_B1_PG_MASK             0xFFFF  /* DSP2RX_EQ_B1_PG - [15:0] */
+#define WM8996_DSP2RX_EQ_B1_PG_SHIFT                 0  /* DSP2RX_EQ_B1_PG - [15:0] */
+#define WM8996_DSP2RX_EQ_B1_PG_WIDTH                16  /* DSP2RX_EQ_B1_PG - [15:0] */
+
+/*
+ * R1413 (0x585) - DSP2 RX EQ Band 2 A
+ */
+#define WM8996_DSP2RX_EQ_B2_A_MASK              0xFFFF  /* DSP2RX_EQ_B2_A - [15:0] */
+#define WM8996_DSP2RX_EQ_B2_A_SHIFT                  0  /* DSP2RX_EQ_B2_A - [15:0] */
+#define WM8996_DSP2RX_EQ_B2_A_WIDTH                 16  /* DSP2RX_EQ_B2_A - [15:0] */
+
+/*
+ * R1414 (0x586) - DSP2 RX EQ Band 2 B
+ */
+#define WM8996_DSP2RX_EQ_B2_B_MASK              0xFFFF  /* DSP2RX_EQ_B2_B - [15:0] */
+#define WM8996_DSP2RX_EQ_B2_B_SHIFT                  0  /* DSP2RX_EQ_B2_B - [15:0] */
+#define WM8996_DSP2RX_EQ_B2_B_WIDTH                 16  /* DSP2RX_EQ_B2_B - [15:0] */
+
+/*
+ * R1415 (0x587) - DSP2 RX EQ Band 2 C
+ */
+#define WM8996_DSP2RX_EQ_B2_C_MASK              0xFFFF  /* DSP2RX_EQ_B2_C - [15:0] */
+#define WM8996_DSP2RX_EQ_B2_C_SHIFT                  0  /* DSP2RX_EQ_B2_C - [15:0] */
+#define WM8996_DSP2RX_EQ_B2_C_WIDTH                 16  /* DSP2RX_EQ_B2_C - [15:0] */
+
+/*
+ * R1416 (0x588) - DSP2 RX EQ Band 2 PG
+ */
+#define WM8996_DSP2RX_EQ_B2_PG_MASK             0xFFFF  /* DSP2RX_EQ_B2_PG - [15:0] */
+#define WM8996_DSP2RX_EQ_B2_PG_SHIFT                 0  /* DSP2RX_EQ_B2_PG - [15:0] */
+#define WM8996_DSP2RX_EQ_B2_PG_WIDTH                16  /* DSP2RX_EQ_B2_PG - [15:0] */
+
+/*
+ * R1417 (0x589) - DSP2 RX EQ Band 3 A
+ */
+#define WM8996_DSP2RX_EQ_B3_A_MASK              0xFFFF  /* DSP2RX_EQ_B3_A - [15:0] */
+#define WM8996_DSP2RX_EQ_B3_A_SHIFT                  0  /* DSP2RX_EQ_B3_A - [15:0] */
+#define WM8996_DSP2RX_EQ_B3_A_WIDTH                 16  /* DSP2RX_EQ_B3_A - [15:0] */
+
+/*
+ * R1418 (0x58A) - DSP2 RX EQ Band 3 B
+ */
+#define WM8996_DSP2RX_EQ_B3_B_MASK              0xFFFF  /* DSP2RX_EQ_B3_B - [15:0] */
+#define WM8996_DSP2RX_EQ_B3_B_SHIFT                  0  /* DSP2RX_EQ_B3_B - [15:0] */
+#define WM8996_DSP2RX_EQ_B3_B_WIDTH                 16  /* DSP2RX_EQ_B3_B - [15:0] */
+
+/*
+ * R1419 (0x58B) - DSP2 RX EQ Band 3 C
+ */
+#define WM8996_DSP2RX_EQ_B3_C_MASK              0xFFFF  /* DSP2RX_EQ_B3_C - [15:0] */
+#define WM8996_DSP2RX_EQ_B3_C_SHIFT                  0  /* DSP2RX_EQ_B3_C - [15:0] */
+#define WM8996_DSP2RX_EQ_B3_C_WIDTH                 16  /* DSP2RX_EQ_B3_C - [15:0] */
+
+/*
+ * R1420 (0x58C) - DSP2 RX EQ Band 3 PG
+ */
+#define WM8996_DSP2RX_EQ_B3_PG_MASK             0xFFFF  /* DSP2RX_EQ_B3_PG - [15:0] */
+#define WM8996_DSP2RX_EQ_B3_PG_SHIFT                 0  /* DSP2RX_EQ_B3_PG - [15:0] */
+#define WM8996_DSP2RX_EQ_B3_PG_WIDTH                16  /* DSP2RX_EQ_B3_PG - [15:0] */
+
+/*
+ * R1421 (0x58D) - DSP2 RX EQ Band 4 A
+ */
+#define WM8996_DSP2RX_EQ_B4_A_MASK              0xFFFF  /* DSP2RX_EQ_B4_A - [15:0] */
+#define WM8996_DSP2RX_EQ_B4_A_SHIFT                  0  /* DSP2RX_EQ_B4_A - [15:0] */
+#define WM8996_DSP2RX_EQ_B4_A_WIDTH                 16  /* DSP2RX_EQ_B4_A - [15:0] */
+
+/*
+ * R1422 (0x58E) - DSP2 RX EQ Band 4 B
+ */
+#define WM8996_DSP2RX_EQ_B4_B_MASK              0xFFFF  /* DSP2RX_EQ_B4_B - [15:0] */
+#define WM8996_DSP2RX_EQ_B4_B_SHIFT                  0  /* DSP2RX_EQ_B4_B - [15:0] */
+#define WM8996_DSP2RX_EQ_B4_B_WIDTH                 16  /* DSP2RX_EQ_B4_B - [15:0] */
+
+/*
+ * R1423 (0x58F) - DSP2 RX EQ Band 4 C
+ */
+#define WM8996_DSP2RX_EQ_B4_C_MASK              0xFFFF  /* DSP2RX_EQ_B4_C - [15:0] */
+#define WM8996_DSP2RX_EQ_B4_C_SHIFT                  0  /* DSP2RX_EQ_B4_C - [15:0] */
+#define WM8996_DSP2RX_EQ_B4_C_WIDTH                 16  /* DSP2RX_EQ_B4_C - [15:0] */
+
+/*
+ * R1424 (0x590) - DSP2 RX EQ Band 4 PG
+ */
+#define WM8996_DSP2RX_EQ_B4_PG_MASK             0xFFFF  /* DSP2RX_EQ_B4_PG - [15:0] */
+#define WM8996_DSP2RX_EQ_B4_PG_SHIFT                 0  /* DSP2RX_EQ_B4_PG - [15:0] */
+#define WM8996_DSP2RX_EQ_B4_PG_WIDTH                16  /* DSP2RX_EQ_B4_PG - [15:0] */
+
+/*
+ * R1425 (0x591) - DSP2 RX EQ Band 5 A
+ */
+#define WM8996_DSP2RX_EQ_B5_A_MASK              0xFFFF  /* DSP2RX_EQ_B5_A - [15:0] */
+#define WM8996_DSP2RX_EQ_B5_A_SHIFT                  0  /* DSP2RX_EQ_B5_A - [15:0] */
+#define WM8996_DSP2RX_EQ_B5_A_WIDTH                 16  /* DSP2RX_EQ_B5_A - [15:0] */
+
+/*
+ * R1426 (0x592) - DSP2 RX EQ Band 5 B
+ */
+#define WM8996_DSP2RX_EQ_B5_B_MASK              0xFFFF  /* DSP2RX_EQ_B5_B - [15:0] */
+#define WM8996_DSP2RX_EQ_B5_B_SHIFT                  0  /* DSP2RX_EQ_B5_B - [15:0] */
+#define WM8996_DSP2RX_EQ_B5_B_WIDTH                 16  /* DSP2RX_EQ_B5_B - [15:0] */
+
+/*
+ * R1427 (0x593) - DSP2 RX EQ Band 5 PG
+ */
+#define WM8996_DSP2RX_EQ_B5_PG_MASK             0xFFFF  /* DSP2RX_EQ_B5_PG - [15:0] */
+#define WM8996_DSP2RX_EQ_B5_PG_SHIFT                 0  /* DSP2RX_EQ_B5_PG - [15:0] */
+#define WM8996_DSP2RX_EQ_B5_PG_WIDTH                16  /* DSP2RX_EQ_B5_PG - [15:0] */
+
+/*
+ * R1536 (0x600) - DAC1 Mixer Volumes
+ */
+#define WM8996_ADCR_DAC1_VOL_MASK               0x03E0  /* ADCR_DAC1_VOL - [9:5] */
+#define WM8996_ADCR_DAC1_VOL_SHIFT                   5  /* ADCR_DAC1_VOL - [9:5] */
+#define WM8996_ADCR_DAC1_VOL_WIDTH                   5  /* ADCR_DAC1_VOL - [9:5] */
+#define WM8996_ADCL_DAC1_VOL_MASK               0x001F  /* ADCL_DAC1_VOL - [4:0] */
+#define WM8996_ADCL_DAC1_VOL_SHIFT                   0  /* ADCL_DAC1_VOL - [4:0] */
+#define WM8996_ADCL_DAC1_VOL_WIDTH                   5  /* ADCL_DAC1_VOL - [4:0] */
+
+/*
+ * R1537 (0x601) - DAC1 Left Mixer Routing
+ */
+#define WM8996_ADCR_TO_DAC1L                    0x0020  /* ADCR_TO_DAC1L */
+#define WM8996_ADCR_TO_DAC1L_MASK               0x0020  /* ADCR_TO_DAC1L */
+#define WM8996_ADCR_TO_DAC1L_SHIFT                   5  /* ADCR_TO_DAC1L */
+#define WM8996_ADCR_TO_DAC1L_WIDTH                   1  /* ADCR_TO_DAC1L */
+#define WM8996_ADCL_TO_DAC1L                    0x0010  /* ADCL_TO_DAC1L */
+#define WM8996_ADCL_TO_DAC1L_MASK               0x0010  /* ADCL_TO_DAC1L */
+#define WM8996_ADCL_TO_DAC1L_SHIFT                   4  /* ADCL_TO_DAC1L */
+#define WM8996_ADCL_TO_DAC1L_WIDTH                   1  /* ADCL_TO_DAC1L */
+#define WM8996_DSP2RXL_TO_DAC1L                 0x0002  /* DSP2RXL_TO_DAC1L */
+#define WM8996_DSP2RXL_TO_DAC1L_MASK            0x0002  /* DSP2RXL_TO_DAC1L */
+#define WM8996_DSP2RXL_TO_DAC1L_SHIFT                1  /* DSP2RXL_TO_DAC1L */
+#define WM8996_DSP2RXL_TO_DAC1L_WIDTH                1  /* DSP2RXL_TO_DAC1L */
+#define WM8996_DSP1RXL_TO_DAC1L                 0x0001  /* DSP1RXL_TO_DAC1L */
+#define WM8996_DSP1RXL_TO_DAC1L_MASK            0x0001  /* DSP1RXL_TO_DAC1L */
+#define WM8996_DSP1RXL_TO_DAC1L_SHIFT                0  /* DSP1RXL_TO_DAC1L */
+#define WM8996_DSP1RXL_TO_DAC1L_WIDTH                1  /* DSP1RXL_TO_DAC1L */
+
+/*
+ * R1538 (0x602) - DAC1 Right Mixer Routing
+ */
+#define WM8996_ADCR_TO_DAC1R                    0x0020  /* ADCR_TO_DAC1R */
+#define WM8996_ADCR_TO_DAC1R_MASK               0x0020  /* ADCR_TO_DAC1R */
+#define WM8996_ADCR_TO_DAC1R_SHIFT                   5  /* ADCR_TO_DAC1R */
+#define WM8996_ADCR_TO_DAC1R_WIDTH                   1  /* ADCR_TO_DAC1R */
+#define WM8996_ADCL_TO_DAC1R                    0x0010  /* ADCL_TO_DAC1R */
+#define WM8996_ADCL_TO_DAC1R_MASK               0x0010  /* ADCL_TO_DAC1R */
+#define WM8996_ADCL_TO_DAC1R_SHIFT                   4  /* ADCL_TO_DAC1R */
+#define WM8996_ADCL_TO_DAC1R_WIDTH                   1  /* ADCL_TO_DAC1R */
+#define WM8996_DSP2RXR_TO_DAC1R                 0x0002  /* DSP2RXR_TO_DAC1R */
+#define WM8996_DSP2RXR_TO_DAC1R_MASK            0x0002  /* DSP2RXR_TO_DAC1R */
+#define WM8996_DSP2RXR_TO_DAC1R_SHIFT                1  /* DSP2RXR_TO_DAC1R */
+#define WM8996_DSP2RXR_TO_DAC1R_WIDTH                1  /* DSP2RXR_TO_DAC1R */
+#define WM8996_DSP1RXR_TO_DAC1R                 0x0001  /* DSP1RXR_TO_DAC1R */
+#define WM8996_DSP1RXR_TO_DAC1R_MASK            0x0001  /* DSP1RXR_TO_DAC1R */
+#define WM8996_DSP1RXR_TO_DAC1R_SHIFT                0  /* DSP1RXR_TO_DAC1R */
+#define WM8996_DSP1RXR_TO_DAC1R_WIDTH                1  /* DSP1RXR_TO_DAC1R */
+
+/*
+ * R1539 (0x603) - DAC2 Mixer Volumes
+ */
+#define WM8996_ADCR_DAC2_VOL_MASK               0x03E0  /* ADCR_DAC2_VOL - [9:5] */
+#define WM8996_ADCR_DAC2_VOL_SHIFT                   5  /* ADCR_DAC2_VOL - [9:5] */
+#define WM8996_ADCR_DAC2_VOL_WIDTH                   5  /* ADCR_DAC2_VOL - [9:5] */
+#define WM8996_ADCL_DAC2_VOL_MASK               0x001F  /* ADCL_DAC2_VOL - [4:0] */
+#define WM8996_ADCL_DAC2_VOL_SHIFT                   0  /* ADCL_DAC2_VOL - [4:0] */
+#define WM8996_ADCL_DAC2_VOL_WIDTH                   5  /* ADCL_DAC2_VOL - [4:0] */
+
+/*
+ * R1540 (0x604) - DAC2 Left Mixer Routing
+ */
+#define WM8996_ADCR_TO_DAC2L                    0x0020  /* ADCR_TO_DAC2L */
+#define WM8996_ADCR_TO_DAC2L_MASK               0x0020  /* ADCR_TO_DAC2L */
+#define WM8996_ADCR_TO_DAC2L_SHIFT                   5  /* ADCR_TO_DAC2L */
+#define WM8996_ADCR_TO_DAC2L_WIDTH                   1  /* ADCR_TO_DAC2L */
+#define WM8996_ADCL_TO_DAC2L                    0x0010  /* ADCL_TO_DAC2L */
+#define WM8996_ADCL_TO_DAC2L_MASK               0x0010  /* ADCL_TO_DAC2L */
+#define WM8996_ADCL_TO_DAC2L_SHIFT                   4  /* ADCL_TO_DAC2L */
+#define WM8996_ADCL_TO_DAC2L_WIDTH                   1  /* ADCL_TO_DAC2L */
+#define WM8996_DSP2RXL_TO_DAC2L                 0x0002  /* DSP2RXL_TO_DAC2L */
+#define WM8996_DSP2RXL_TO_DAC2L_MASK            0x0002  /* DSP2RXL_TO_DAC2L */
+#define WM8996_DSP2RXL_TO_DAC2L_SHIFT                1  /* DSP2RXL_TO_DAC2L */
+#define WM8996_DSP2RXL_TO_DAC2L_WIDTH                1  /* DSP2RXL_TO_DAC2L */
+#define WM8996_DSP1RXL_TO_DAC2L                 0x0001  /* DSP1RXL_TO_DAC2L */
+#define WM8996_DSP1RXL_TO_DAC2L_MASK            0x0001  /* DSP1RXL_TO_DAC2L */
+#define WM8996_DSP1RXL_TO_DAC2L_SHIFT                0  /* DSP1RXL_TO_DAC2L */
+#define WM8996_DSP1RXL_TO_DAC2L_WIDTH                1  /* DSP1RXL_TO_DAC2L */
+
+/*
+ * R1541 (0x605) - DAC2 Right Mixer Routing
+ */
+#define WM8996_ADCR_TO_DAC2R                    0x0020  /* ADCR_TO_DAC2R */
+#define WM8996_ADCR_TO_DAC2R_MASK               0x0020  /* ADCR_TO_DAC2R */
+#define WM8996_ADCR_TO_DAC2R_SHIFT                   5  /* ADCR_TO_DAC2R */
+#define WM8996_ADCR_TO_DAC2R_WIDTH                   1  /* ADCR_TO_DAC2R */
+#define WM8996_ADCL_TO_DAC2R                    0x0010  /* ADCL_TO_DAC2R */
+#define WM8996_ADCL_TO_DAC2R_MASK               0x0010  /* ADCL_TO_DAC2R */
+#define WM8996_ADCL_TO_DAC2R_SHIFT                   4  /* ADCL_TO_DAC2R */
+#define WM8996_ADCL_TO_DAC2R_WIDTH                   1  /* ADCL_TO_DAC2R */
+#define WM8996_DSP2RXR_TO_DAC2R                 0x0002  /* DSP2RXR_TO_DAC2R */
+#define WM8996_DSP2RXR_TO_DAC2R_MASK            0x0002  /* DSP2RXR_TO_DAC2R */
+#define WM8996_DSP2RXR_TO_DAC2R_SHIFT                1  /* DSP2RXR_TO_DAC2R */
+#define WM8996_DSP2RXR_TO_DAC2R_WIDTH                1  /* DSP2RXR_TO_DAC2R */
+#define WM8996_DSP1RXR_TO_DAC2R                 0x0001  /* DSP1RXR_TO_DAC2R */
+#define WM8996_DSP1RXR_TO_DAC2R_MASK            0x0001  /* DSP1RXR_TO_DAC2R */
+#define WM8996_DSP1RXR_TO_DAC2R_SHIFT                0  /* DSP1RXR_TO_DAC2R */
+#define WM8996_DSP1RXR_TO_DAC2R_WIDTH                1  /* DSP1RXR_TO_DAC2R */
+
+/*
+ * R1542 (0x606) - DSP1 TX Left Mixer Routing
+ */
+#define WM8996_ADC1L_TO_DSP1TXL                 0x0002  /* ADC1L_TO_DSP1TXL */
+#define WM8996_ADC1L_TO_DSP1TXL_MASK            0x0002  /* ADC1L_TO_DSP1TXL */
+#define WM8996_ADC1L_TO_DSP1TXL_SHIFT                1  /* ADC1L_TO_DSP1TXL */
+#define WM8996_ADC1L_TO_DSP1TXL_WIDTH                1  /* ADC1L_TO_DSP1TXL */
+#define WM8996_DACL_TO_DSP1TXL                  0x0001  /* DACL_TO_DSP1TXL */
+#define WM8996_DACL_TO_DSP1TXL_MASK             0x0001  /* DACL_TO_DSP1TXL */
+#define WM8996_DACL_TO_DSP1TXL_SHIFT                 0  /* DACL_TO_DSP1TXL */
+#define WM8996_DACL_TO_DSP1TXL_WIDTH                 1  /* DACL_TO_DSP1TXL */
+
+/*
+ * R1543 (0x607) - DSP1 TX Right Mixer Routing
+ */
+#define WM8996_ADC1R_TO_DSP1TXR                 0x0002  /* ADC1R_TO_DSP1TXR */
+#define WM8996_ADC1R_TO_DSP1TXR_MASK            0x0002  /* ADC1R_TO_DSP1TXR */
+#define WM8996_ADC1R_TO_DSP1TXR_SHIFT                1  /* ADC1R_TO_DSP1TXR */
+#define WM8996_ADC1R_TO_DSP1TXR_WIDTH                1  /* ADC1R_TO_DSP1TXR */
+#define WM8996_DACR_TO_DSP1TXR                  0x0001  /* DACR_TO_DSP1TXR */
+#define WM8996_DACR_TO_DSP1TXR_MASK             0x0001  /* DACR_TO_DSP1TXR */
+#define WM8996_DACR_TO_DSP1TXR_SHIFT                 0  /* DACR_TO_DSP1TXR */
+#define WM8996_DACR_TO_DSP1TXR_WIDTH                 1  /* DACR_TO_DSP1TXR */
+
+/*
+ * R1544 (0x608) - DSP2 TX Left Mixer Routing
+ */
+#define WM8996_ADC2L_TO_DSP2TXL                 0x0002  /* ADC2L_TO_DSP2TXL */
+#define WM8996_ADC2L_TO_DSP2TXL_MASK            0x0002  /* ADC2L_TO_DSP2TXL */
+#define WM8996_ADC2L_TO_DSP2TXL_SHIFT                1  /* ADC2L_TO_DSP2TXL */
+#define WM8996_ADC2L_TO_DSP2TXL_WIDTH                1  /* ADC2L_TO_DSP2TXL */
+#define WM8996_DACL_TO_DSP2TXL                  0x0001  /* DACL_TO_DSP2TXL */
+#define WM8996_DACL_TO_DSP2TXL_MASK             0x0001  /* DACL_TO_DSP2TXL */
+#define WM8996_DACL_TO_DSP2TXL_SHIFT                 0  /* DACL_TO_DSP2TXL */
+#define WM8996_DACL_TO_DSP2TXL_WIDTH                 1  /* DACL_TO_DSP2TXL */
+
+/*
+ * R1545 (0x609) - DSP2 TX Right Mixer Routing
+ */
+#define WM8996_ADC2R_TO_DSP2TXR                 0x0002  /* ADC2R_TO_DSP2TXR */
+#define WM8996_ADC2R_TO_DSP2TXR_MASK            0x0002  /* ADC2R_TO_DSP2TXR */
+#define WM8996_ADC2R_TO_DSP2TXR_SHIFT                1  /* ADC2R_TO_DSP2TXR */
+#define WM8996_ADC2R_TO_DSP2TXR_WIDTH                1  /* ADC2R_TO_DSP2TXR */
+#define WM8996_DACR_TO_DSP2TXR                  0x0001  /* DACR_TO_DSP2TXR */
+#define WM8996_DACR_TO_DSP2TXR_MASK             0x0001  /* DACR_TO_DSP2TXR */
+#define WM8996_DACR_TO_DSP2TXR_SHIFT                 0  /* DACR_TO_DSP2TXR */
+#define WM8996_DACR_TO_DSP2TXR_WIDTH                 1  /* DACR_TO_DSP2TXR */
+
+/*
+ * R1546 (0x60A) - DSP TX Mixer Select
+ */
+#define WM8996_DAC_TO_DSPTX_SRC                 0x0001  /* DAC_TO_DSPTX_SRC */
+#define WM8996_DAC_TO_DSPTX_SRC_MASK            0x0001  /* DAC_TO_DSPTX_SRC */
+#define WM8996_DAC_TO_DSPTX_SRC_SHIFT                0  /* DAC_TO_DSPTX_SRC */
+#define WM8996_DAC_TO_DSPTX_SRC_WIDTH                1  /* DAC_TO_DSPTX_SRC */
+
+/*
+ * R1552 (0x610) - DAC Softmute
+ */
+#define WM8996_DAC_SOFTMUTEMODE                 0x0002  /* DAC_SOFTMUTEMODE */
+#define WM8996_DAC_SOFTMUTEMODE_MASK            0x0002  /* DAC_SOFTMUTEMODE */
+#define WM8996_DAC_SOFTMUTEMODE_SHIFT                1  /* DAC_SOFTMUTEMODE */
+#define WM8996_DAC_SOFTMUTEMODE_WIDTH                1  /* DAC_SOFTMUTEMODE */
+#define WM8996_DAC_MUTERATE                     0x0001  /* DAC_MUTERATE */
+#define WM8996_DAC_MUTERATE_MASK                0x0001  /* DAC_MUTERATE */
+#define WM8996_DAC_MUTERATE_SHIFT                    0  /* DAC_MUTERATE */
+#define WM8996_DAC_MUTERATE_WIDTH                    1  /* DAC_MUTERATE */
+
+/*
+ * R1568 (0x620) - Oversampling
+ */
+#define WM8996_SPK_OSR128                       0x0008  /* SPK_OSR128 */
+#define WM8996_SPK_OSR128_MASK                  0x0008  /* SPK_OSR128 */
+#define WM8996_SPK_OSR128_SHIFT                      3  /* SPK_OSR128 */
+#define WM8996_SPK_OSR128_WIDTH                      1  /* SPK_OSR128 */
+#define WM8996_DMIC_OSR64                       0x0004  /* DMIC_OSR64 */
+#define WM8996_DMIC_OSR64_MASK                  0x0004  /* DMIC_OSR64 */
+#define WM8996_DMIC_OSR64_SHIFT                      2  /* DMIC_OSR64 */
+#define WM8996_DMIC_OSR64_WIDTH                      1  /* DMIC_OSR64 */
+#define WM8996_ADC_OSR128                       0x0002  /* ADC_OSR128 */
+#define WM8996_ADC_OSR128_MASK                  0x0002  /* ADC_OSR128 */
+#define WM8996_ADC_OSR128_SHIFT                      1  /* ADC_OSR128 */
+#define WM8996_ADC_OSR128_WIDTH                      1  /* ADC_OSR128 */
+#define WM8996_DAC_OSR128                       0x0001  /* DAC_OSR128 */
+#define WM8996_DAC_OSR128_MASK                  0x0001  /* DAC_OSR128 */
+#define WM8996_DAC_OSR128_SHIFT                      0  /* DAC_OSR128 */
+#define WM8996_DAC_OSR128_WIDTH                      1  /* DAC_OSR128 */
+
+/*
+ * R1569 (0x621) - Sidetone
+ */
+#define WM8996_ST_LPF                           0x1000  /* ST_LPF */
+#define WM8996_ST_LPF_MASK                      0x1000  /* ST_LPF */
+#define WM8996_ST_LPF_SHIFT                         12  /* ST_LPF */
+#define WM8996_ST_LPF_WIDTH                          1  /* ST_LPF */
+#define WM8996_ST_HPF_CUT_MASK                  0x0380  /* ST_HPF_CUT - [9:7] */
+#define WM8996_ST_HPF_CUT_SHIFT                      7  /* ST_HPF_CUT - [9:7] */
+#define WM8996_ST_HPF_CUT_WIDTH                      3  /* ST_HPF_CUT - [9:7] */
+#define WM8996_ST_HPF                           0x0040  /* ST_HPF */
+#define WM8996_ST_HPF_MASK                      0x0040  /* ST_HPF */
+#define WM8996_ST_HPF_SHIFT                          6  /* ST_HPF */
+#define WM8996_ST_HPF_WIDTH                          1  /* ST_HPF */
+#define WM8996_STR_SEL                          0x0002  /* STR_SEL */
+#define WM8996_STR_SEL_MASK                     0x0002  /* STR_SEL */
+#define WM8996_STR_SEL_SHIFT                         1  /* STR_SEL */
+#define WM8996_STR_SEL_WIDTH                         1  /* STR_SEL */
+#define WM8996_STL_SEL                          0x0001  /* STL_SEL */
+#define WM8996_STL_SEL_MASK                     0x0001  /* STL_SEL */
+#define WM8996_STL_SEL_SHIFT                         0  /* STL_SEL */
+#define WM8996_STL_SEL_WIDTH                         1  /* STL_SEL */
+
+/*
+ * R1792 (0x700) - GPIO 1
+ */
+#define WM8996_GP1_DIR                          0x8000  /* GP1_DIR */
+#define WM8996_GP1_DIR_MASK                     0x8000  /* GP1_DIR */
+#define WM8996_GP1_DIR_SHIFT                        15  /* GP1_DIR */
+#define WM8996_GP1_DIR_WIDTH                         1  /* GP1_DIR */
+#define WM8996_GP1_PU                           0x4000  /* GP1_PU */
+#define WM8996_GP1_PU_MASK                      0x4000  /* GP1_PU */
+#define WM8996_GP1_PU_SHIFT                         14  /* GP1_PU */
+#define WM8996_GP1_PU_WIDTH                          1  /* GP1_PU */
+#define WM8996_GP1_PD                           0x2000  /* GP1_PD */
+#define WM8996_GP1_PD_MASK                      0x2000  /* GP1_PD */
+#define WM8996_GP1_PD_SHIFT                         13  /* GP1_PD */
+#define WM8996_GP1_PD_WIDTH                          1  /* GP1_PD */
+#define WM8996_GP1_POL                          0x0400  /* GP1_POL */
+#define WM8996_GP1_POL_MASK                     0x0400  /* GP1_POL */
+#define WM8996_GP1_POL_SHIFT                        10  /* GP1_POL */
+#define WM8996_GP1_POL_WIDTH                         1  /* GP1_POL */
+#define WM8996_GP1_OP_CFG                       0x0200  /* GP1_OP_CFG */
+#define WM8996_GP1_OP_CFG_MASK                  0x0200  /* GP1_OP_CFG */
+#define WM8996_GP1_OP_CFG_SHIFT                      9  /* GP1_OP_CFG */
+#define WM8996_GP1_OP_CFG_WIDTH                      1  /* GP1_OP_CFG */
+#define WM8996_GP1_DB                           0x0100  /* GP1_DB */
+#define WM8996_GP1_DB_MASK                      0x0100  /* GP1_DB */
+#define WM8996_GP1_DB_SHIFT                          8  /* GP1_DB */
+#define WM8996_GP1_DB_WIDTH                          1  /* GP1_DB */
+#define WM8996_GP1_LVL                          0x0040  /* GP1_LVL */
+#define WM8996_GP1_LVL_MASK                     0x0040  /* GP1_LVL */
+#define WM8996_GP1_LVL_SHIFT                         6  /* GP1_LVL */
+#define WM8996_GP1_LVL_WIDTH                         1  /* GP1_LVL */
+#define WM8996_GP1_FN_MASK                      0x000F  /* GP1_FN - [3:0] */
+#define WM8996_GP1_FN_SHIFT                          0  /* GP1_FN - [3:0] */
+#define WM8996_GP1_FN_WIDTH                          4  /* GP1_FN - [3:0] */
+
+/*
+ * R1793 (0x701) - GPIO 2
+ */
+#define WM8996_GP2_DIR                          0x8000  /* GP2_DIR */
+#define WM8996_GP2_DIR_MASK                     0x8000  /* GP2_DIR */
+#define WM8996_GP2_DIR_SHIFT                        15  /* GP2_DIR */
+#define WM8996_GP2_DIR_WIDTH                         1  /* GP2_DIR */
+#define WM8996_GP2_PU                           0x4000  /* GP2_PU */
+#define WM8996_GP2_PU_MASK                      0x4000  /* GP2_PU */
+#define WM8996_GP2_PU_SHIFT                         14  /* GP2_PU */
+#define WM8996_GP2_PU_WIDTH                          1  /* GP2_PU */
+#define WM8996_GP2_PD                           0x2000  /* GP2_PD */
+#define WM8996_GP2_PD_MASK                      0x2000  /* GP2_PD */
+#define WM8996_GP2_PD_SHIFT                         13  /* GP2_PD */
+#define WM8996_GP2_PD_WIDTH                          1  /* GP2_PD */
+#define WM8996_GP2_POL                          0x0400  /* GP2_POL */
+#define WM8996_GP2_POL_MASK                     0x0400  /* GP2_POL */
+#define WM8996_GP2_POL_SHIFT                        10  /* GP2_POL */
+#define WM8996_GP2_POL_WIDTH                         1  /* GP2_POL */
+#define WM8996_GP2_OP_CFG                       0x0200  /* GP2_OP_CFG */
+#define WM8996_GP2_OP_CFG_MASK                  0x0200  /* GP2_OP_CFG */
+#define WM8996_GP2_OP_CFG_SHIFT                      9  /* GP2_OP_CFG */
+#define WM8996_GP2_OP_CFG_WIDTH                      1  /* GP2_OP_CFG */
+#define WM8996_GP2_DB                           0x0100  /* GP2_DB */
+#define WM8996_GP2_DB_MASK                      0x0100  /* GP2_DB */
+#define WM8996_GP2_DB_SHIFT                          8  /* GP2_DB */
+#define WM8996_GP2_DB_WIDTH                          1  /* GP2_DB */
+#define WM8996_GP2_LVL                          0x0040  /* GP2_LVL */
+#define WM8996_GP2_LVL_MASK                     0x0040  /* GP2_LVL */
+#define WM8996_GP2_LVL_SHIFT                         6  /* GP2_LVL */
+#define WM8996_GP2_LVL_WIDTH                         1  /* GP2_LVL */
+#define WM8996_GP2_FN_MASK                      0x000F  /* GP2_FN - [3:0] */
+#define WM8996_GP2_FN_SHIFT                          0  /* GP2_FN - [3:0] */
+#define WM8996_GP2_FN_WIDTH                          4  /* GP2_FN - [3:0] */
+
+/*
+ * R1794 (0x702) - GPIO 3
+ */
+#define WM8996_GP3_DIR                          0x8000  /* GP3_DIR */
+#define WM8996_GP3_DIR_MASK                     0x8000  /* GP3_DIR */
+#define WM8996_GP3_DIR_SHIFT                        15  /* GP3_DIR */
+#define WM8996_GP3_DIR_WIDTH                         1  /* GP3_DIR */
+#define WM8996_GP3_PU                           0x4000  /* GP3_PU */
+#define WM8996_GP3_PU_MASK                      0x4000  /* GP3_PU */
+#define WM8996_GP3_PU_SHIFT                         14  /* GP3_PU */
+#define WM8996_GP3_PU_WIDTH                          1  /* GP3_PU */
+#define WM8996_GP3_PD                           0x2000  /* GP3_PD */
+#define WM8996_GP3_PD_MASK                      0x2000  /* GP3_PD */
+#define WM8996_GP3_PD_SHIFT                         13  /* GP3_PD */
+#define WM8996_GP3_PD_WIDTH                          1  /* GP3_PD */
+#define WM8996_GP3_POL                          0x0400  /* GP3_POL */
+#define WM8996_GP3_POL_MASK                     0x0400  /* GP3_POL */
+#define WM8996_GP3_POL_SHIFT                        10  /* GP3_POL */
+#define WM8996_GP3_POL_WIDTH                         1  /* GP3_POL */
+#define WM8996_GP3_OP_CFG                       0x0200  /* GP3_OP_CFG */
+#define WM8996_GP3_OP_CFG_MASK                  0x0200  /* GP3_OP_CFG */
+#define WM8996_GP3_OP_CFG_SHIFT                      9  /* GP3_OP_CFG */
+#define WM8996_GP3_OP_CFG_WIDTH                      1  /* GP3_OP_CFG */
+#define WM8996_GP3_DB                           0x0100  /* GP3_DB */
+#define WM8996_GP3_DB_MASK                      0x0100  /* GP3_DB */
+#define WM8996_GP3_DB_SHIFT                          8  /* GP3_DB */
+#define WM8996_GP3_DB_WIDTH                          1  /* GP3_DB */
+#define WM8996_GP3_LVL                          0x0040  /* GP3_LVL */
+#define WM8996_GP3_LVL_MASK                     0x0040  /* GP3_LVL */
+#define WM8996_GP3_LVL_SHIFT                         6  /* GP3_LVL */
+#define WM8996_GP3_LVL_WIDTH                         1  /* GP3_LVL */
+#define WM8996_GP3_FN_MASK                      0x000F  /* GP3_FN - [3:0] */
+#define WM8996_GP3_FN_SHIFT                          0  /* GP3_FN - [3:0] */
+#define WM8996_GP3_FN_WIDTH                          4  /* GP3_FN - [3:0] */
+
+/*
+ * R1795 (0x703) - GPIO 4
+ */
+#define WM8996_GP4_DIR                          0x8000  /* GP4_DIR */
+#define WM8996_GP4_DIR_MASK                     0x8000  /* GP4_DIR */
+#define WM8996_GP4_DIR_SHIFT                        15  /* GP4_DIR */
+#define WM8996_GP4_DIR_WIDTH                         1  /* GP4_DIR */
+#define WM8996_GP4_PU                           0x4000  /* GP4_PU */
+#define WM8996_GP4_PU_MASK                      0x4000  /* GP4_PU */
+#define WM8996_GP4_PU_SHIFT                         14  /* GP4_PU */
+#define WM8996_GP4_PU_WIDTH                          1  /* GP4_PU */
+#define WM8996_GP4_PD                           0x2000  /* GP4_PD */
+#define WM8996_GP4_PD_MASK                      0x2000  /* GP4_PD */
+#define WM8996_GP4_PD_SHIFT                         13  /* GP4_PD */
+#define WM8996_GP4_PD_WIDTH                          1  /* GP4_PD */
+#define WM8996_GP4_POL                          0x0400  /* GP4_POL */
+#define WM8996_GP4_POL_MASK                     0x0400  /* GP4_POL */
+#define WM8996_GP4_POL_SHIFT                        10  /* GP4_POL */
+#define WM8996_GP4_POL_WIDTH                         1  /* GP4_POL */
+#define WM8996_GP4_OP_CFG                       0x0200  /* GP4_OP_CFG */
+#define WM8996_GP4_OP_CFG_MASK                  0x0200  /* GP4_OP_CFG */
+#define WM8996_GP4_OP_CFG_SHIFT                      9  /* GP4_OP_CFG */
+#define WM8996_GP4_OP_CFG_WIDTH                      1  /* GP4_OP_CFG */
+#define WM8996_GP4_DB                           0x0100  /* GP4_DB */
+#define WM8996_GP4_DB_MASK                      0x0100  /* GP4_DB */
+#define WM8996_GP4_DB_SHIFT                          8  /* GP4_DB */
+#define WM8996_GP4_DB_WIDTH                          1  /* GP4_DB */
+#define WM8996_GP4_LVL                          0x0040  /* GP4_LVL */
+#define WM8996_GP4_LVL_MASK                     0x0040  /* GP4_LVL */
+#define WM8996_GP4_LVL_SHIFT                         6  /* GP4_LVL */
+#define WM8996_GP4_LVL_WIDTH                         1  /* GP4_LVL */
+#define WM8996_GP4_FN_MASK                      0x000F  /* GP4_FN - [3:0] */
+#define WM8996_GP4_FN_SHIFT                          0  /* GP4_FN - [3:0] */
+#define WM8996_GP4_FN_WIDTH                          4  /* GP4_FN - [3:0] */
+
+/*
+ * R1796 (0x704) - GPIO 5
+ */
+#define WM8996_GP5_DIR                          0x8000  /* GP5_DIR */
+#define WM8996_GP5_DIR_MASK                     0x8000  /* GP5_DIR */
+#define WM8996_GP5_DIR_SHIFT                        15  /* GP5_DIR */
+#define WM8996_GP5_DIR_WIDTH                         1  /* GP5_DIR */
+#define WM8996_GP5_PU                           0x4000  /* GP5_PU */
+#define WM8996_GP5_PU_MASK                      0x4000  /* GP5_PU */
+#define WM8996_GP5_PU_SHIFT                         14  /* GP5_PU */
+#define WM8996_GP5_PU_WIDTH                          1  /* GP5_PU */
+#define WM8996_GP5_PD                           0x2000  /* GP5_PD */
+#define WM8996_GP5_PD_MASK                      0x2000  /* GP5_PD */
+#define WM8996_GP5_PD_SHIFT                         13  /* GP5_PD */
+#define WM8996_GP5_PD_WIDTH                          1  /* GP5_PD */
+#define WM8996_GP5_POL                          0x0400  /* GP5_POL */
+#define WM8996_GP5_POL_MASK                     0x0400  /* GP5_POL */
+#define WM8996_GP5_POL_SHIFT                        10  /* GP5_POL */
+#define WM8996_GP5_POL_WIDTH                         1  /* GP5_POL */
+#define WM8996_GP5_OP_CFG                       0x0200  /* GP5_OP_CFG */
+#define WM8996_GP5_OP_CFG_MASK                  0x0200  /* GP5_OP_CFG */
+#define WM8996_GP5_OP_CFG_SHIFT                      9  /* GP5_OP_CFG */
+#define WM8996_GP5_OP_CFG_WIDTH                      1  /* GP5_OP_CFG */
+#define WM8996_GP5_DB                           0x0100  /* GP5_DB */
+#define WM8996_GP5_DB_MASK                      0x0100  /* GP5_DB */
+#define WM8996_GP5_DB_SHIFT                          8  /* GP5_DB */
+#define WM8996_GP5_DB_WIDTH                          1  /* GP5_DB */
+#define WM8996_GP5_LVL                          0x0040  /* GP5_LVL */
+#define WM8996_GP5_LVL_MASK                     0x0040  /* GP5_LVL */
+#define WM8996_GP5_LVL_SHIFT                         6  /* GP5_LVL */
+#define WM8996_GP5_LVL_WIDTH                         1  /* GP5_LVL */
+#define WM8996_GP5_FN_MASK                      0x000F  /* GP5_FN - [3:0] */
+#define WM8996_GP5_FN_SHIFT                          0  /* GP5_FN - [3:0] */
+#define WM8996_GP5_FN_WIDTH                          4  /* GP5_FN - [3:0] */
+
+/*
+ * R1824 (0x720) - Pull Control (1)
+ */
+#define WM8996_DMICDAT2_PD                      0x1000  /* DMICDAT2_PD */
+#define WM8996_DMICDAT2_PD_MASK                 0x1000  /* DMICDAT2_PD */
+#define WM8996_DMICDAT2_PD_SHIFT                    12  /* DMICDAT2_PD */
+#define WM8996_DMICDAT2_PD_WIDTH                     1  /* DMICDAT2_PD */
+#define WM8996_DMICDAT1_PD                      0x0400  /* DMICDAT1_PD */
+#define WM8996_DMICDAT1_PD_MASK                 0x0400  /* DMICDAT1_PD */
+#define WM8996_DMICDAT1_PD_SHIFT                    10  /* DMICDAT1_PD */
+#define WM8996_DMICDAT1_PD_WIDTH                     1  /* DMICDAT1_PD */
+#define WM8996_MCLK2_PU                         0x0200  /* MCLK2_PU */
+#define WM8996_MCLK2_PU_MASK                    0x0200  /* MCLK2_PU */
+#define WM8996_MCLK2_PU_SHIFT                        9  /* MCLK2_PU */
+#define WM8996_MCLK2_PU_WIDTH                        1  /* MCLK2_PU */
+#define WM8996_MCLK2_PD                         0x0100  /* MCLK2_PD */
+#define WM8996_MCLK2_PD_MASK                    0x0100  /* MCLK2_PD */
+#define WM8996_MCLK2_PD_SHIFT                        8  /* MCLK2_PD */
+#define WM8996_MCLK2_PD_WIDTH                        1  /* MCLK2_PD */
+#define WM8996_MCLK1_PU                         0x0080  /* MCLK1_PU */
+#define WM8996_MCLK1_PU_MASK                    0x0080  /* MCLK1_PU */
+#define WM8996_MCLK1_PU_SHIFT                        7  /* MCLK1_PU */
+#define WM8996_MCLK1_PU_WIDTH                        1  /* MCLK1_PU */
+#define WM8996_MCLK1_PD                         0x0040  /* MCLK1_PD */
+#define WM8996_MCLK1_PD_MASK                    0x0040  /* MCLK1_PD */
+#define WM8996_MCLK1_PD_SHIFT                        6  /* MCLK1_PD */
+#define WM8996_MCLK1_PD_WIDTH                        1  /* MCLK1_PD */
+#define WM8996_DACDAT1_PU                       0x0020  /* DACDAT1_PU */
+#define WM8996_DACDAT1_PU_MASK                  0x0020  /* DACDAT1_PU */
+#define WM8996_DACDAT1_PU_SHIFT                      5  /* DACDAT1_PU */
+#define WM8996_DACDAT1_PU_WIDTH                      1  /* DACDAT1_PU */
+#define WM8996_DACDAT1_PD                       0x0010  /* DACDAT1_PD */
+#define WM8996_DACDAT1_PD_MASK                  0x0010  /* DACDAT1_PD */
+#define WM8996_DACDAT1_PD_SHIFT                      4  /* DACDAT1_PD */
+#define WM8996_DACDAT1_PD_WIDTH                      1  /* DACDAT1_PD */
+#define WM8996_DACLRCLK1_PU                     0x0008  /* DACLRCLK1_PU */
+#define WM8996_DACLRCLK1_PU_MASK                0x0008  /* DACLRCLK1_PU */
+#define WM8996_DACLRCLK1_PU_SHIFT                    3  /* DACLRCLK1_PU */
+#define WM8996_DACLRCLK1_PU_WIDTH                    1  /* DACLRCLK1_PU */
+#define WM8996_DACLRCLK1_PD                     0x0004  /* DACLRCLK1_PD */
+#define WM8996_DACLRCLK1_PD_MASK                0x0004  /* DACLRCLK1_PD */
+#define WM8996_DACLRCLK1_PD_SHIFT                    2  /* DACLRCLK1_PD */
+#define WM8996_DACLRCLK1_PD_WIDTH                    1  /* DACLRCLK1_PD */
+#define WM8996_BCLK1_PU                         0x0002  /* BCLK1_PU */
+#define WM8996_BCLK1_PU_MASK                    0x0002  /* BCLK1_PU */
+#define WM8996_BCLK1_PU_SHIFT                        1  /* BCLK1_PU */
+#define WM8996_BCLK1_PU_WIDTH                        1  /* BCLK1_PU */
+#define WM8996_BCLK1_PD                         0x0001  /* BCLK1_PD */
+#define WM8996_BCLK1_PD_MASK                    0x0001  /* BCLK1_PD */
+#define WM8996_BCLK1_PD_SHIFT                        0  /* BCLK1_PD */
+#define WM8996_BCLK1_PD_WIDTH                        1  /* BCLK1_PD */
+
+/*
+ * R1825 (0x721) - Pull Control (2)
+ */
+#define WM8996_LDO1ENA_PD                       0x0100  /* LDO1ENA_PD */
+#define WM8996_LDO1ENA_PD_MASK                  0x0100  /* LDO1ENA_PD */
+#define WM8996_LDO1ENA_PD_SHIFT                      8  /* LDO1ENA_PD */
+#define WM8996_LDO1ENA_PD_WIDTH                      1  /* LDO1ENA_PD */
+#define WM8996_ADDR_PD                          0x0040  /* ADDR_PD */
+#define WM8996_ADDR_PD_MASK                     0x0040  /* ADDR_PD */
+#define WM8996_ADDR_PD_SHIFT                         6  /* ADDR_PD */
+#define WM8996_ADDR_PD_WIDTH                         1  /* ADDR_PD */
+#define WM8996_DACDAT2_PU                       0x0020  /* DACDAT2_PU */
+#define WM8996_DACDAT2_PU_MASK                  0x0020  /* DACDAT2_PU */
+#define WM8996_DACDAT2_PU_SHIFT                      5  /* DACDAT2_PU */
+#define WM8996_DACDAT2_PU_WIDTH                      1  /* DACDAT2_PU */
+#define WM8996_DACDAT2_PD                       0x0010  /* DACDAT2_PD */
+#define WM8996_DACDAT2_PD_MASK                  0x0010  /* DACDAT2_PD */
+#define WM8996_DACDAT2_PD_SHIFT                      4  /* DACDAT2_PD */
+#define WM8996_DACDAT2_PD_WIDTH                      1  /* DACDAT2_PD */
+#define WM8996_DACLRCLK2_PU                     0x0008  /* DACLRCLK2_PU */
+#define WM8996_DACLRCLK2_PU_MASK                0x0008  /* DACLRCLK2_PU */
+#define WM8996_DACLRCLK2_PU_SHIFT                    3  /* DACLRCLK2_PU */
+#define WM8996_DACLRCLK2_PU_WIDTH                    1  /* DACLRCLK2_PU */
+#define WM8996_DACLRCLK2_PD                     0x0004  /* DACLRCLK2_PD */
+#define WM8996_DACLRCLK2_PD_MASK                0x0004  /* DACLRCLK2_PD */
+#define WM8996_DACLRCLK2_PD_SHIFT                    2  /* DACLRCLK2_PD */
+#define WM8996_DACLRCLK2_PD_WIDTH                    1  /* DACLRCLK2_PD */
+#define WM8996_BCLK2_PU                         0x0002  /* BCLK2_PU */
+#define WM8996_BCLK2_PU_MASK                    0x0002  /* BCLK2_PU */
+#define WM8996_BCLK2_PU_SHIFT                        1  /* BCLK2_PU */
+#define WM8996_BCLK2_PU_WIDTH                        1  /* BCLK2_PU */
+#define WM8996_BCLK2_PD                         0x0001  /* BCLK2_PD */
+#define WM8996_BCLK2_PD_MASK                    0x0001  /* BCLK2_PD */
+#define WM8996_BCLK2_PD_SHIFT                        0  /* BCLK2_PD */
+#define WM8996_BCLK2_PD_WIDTH                        1  /* BCLK2_PD */
+
+/*
+ * R1840 (0x730) - Interrupt Status 1
+ */
+#define WM8996_GP5_EINT                         0x0010  /* GP5_EINT */
+#define WM8996_GP5_EINT_MASK                    0x0010  /* GP5_EINT */
+#define WM8996_GP5_EINT_SHIFT                        4  /* GP5_EINT */
+#define WM8996_GP5_EINT_WIDTH                        1  /* GP5_EINT */
+#define WM8996_GP4_EINT                         0x0008  /* GP4_EINT */
+#define WM8996_GP4_EINT_MASK                    0x0008  /* GP4_EINT */
+#define WM8996_GP4_EINT_SHIFT                        3  /* GP4_EINT */
+#define WM8996_GP4_EINT_WIDTH                        1  /* GP4_EINT */
+#define WM8996_GP3_EINT                         0x0004  /* GP3_EINT */
+#define WM8996_GP3_EINT_MASK                    0x0004  /* GP3_EINT */
+#define WM8996_GP3_EINT_SHIFT                        2  /* GP3_EINT */
+#define WM8996_GP3_EINT_WIDTH                        1  /* GP3_EINT */
+#define WM8996_GP2_EINT                         0x0002  /* GP2_EINT */
+#define WM8996_GP2_EINT_MASK                    0x0002  /* GP2_EINT */
+#define WM8996_GP2_EINT_SHIFT                        1  /* GP2_EINT */
+#define WM8996_GP2_EINT_WIDTH                        1  /* GP2_EINT */
+#define WM8996_GP1_EINT                         0x0001  /* GP1_EINT */
+#define WM8996_GP1_EINT_MASK                    0x0001  /* GP1_EINT */
+#define WM8996_GP1_EINT_SHIFT                        0  /* GP1_EINT */
+#define WM8996_GP1_EINT_WIDTH                        1  /* GP1_EINT */
+
+/*
+ * R1841 (0x731) - Interrupt Status 2
+ */
+#define WM8996_DCS_DONE_23_EINT                 0x1000  /* DCS_DONE_23_EINT */
+#define WM8996_DCS_DONE_23_EINT_MASK            0x1000  /* DCS_DONE_23_EINT */
+#define WM8996_DCS_DONE_23_EINT_SHIFT               12  /* DCS_DONE_23_EINT */
+#define WM8996_DCS_DONE_23_EINT_WIDTH                1  /* DCS_DONE_23_EINT */
+#define WM8996_DCS_DONE_01_EINT                 0x0800  /* DCS_DONE_01_EINT */
+#define WM8996_DCS_DONE_01_EINT_MASK            0x0800  /* DCS_DONE_01_EINT */
+#define WM8996_DCS_DONE_01_EINT_SHIFT               11  /* DCS_DONE_01_EINT */
+#define WM8996_DCS_DONE_01_EINT_WIDTH                1  /* DCS_DONE_01_EINT */
+#define WM8996_WSEQ_DONE_EINT                   0x0400  /* WSEQ_DONE_EINT */
+#define WM8996_WSEQ_DONE_EINT_MASK              0x0400  /* WSEQ_DONE_EINT */
+#define WM8996_WSEQ_DONE_EINT_SHIFT                 10  /* WSEQ_DONE_EINT */
+#define WM8996_WSEQ_DONE_EINT_WIDTH                  1  /* WSEQ_DONE_EINT */
+#define WM8996_FIFOS_ERR_EINT                   0x0200  /* FIFOS_ERR_EINT */
+#define WM8996_FIFOS_ERR_EINT_MASK              0x0200  /* FIFOS_ERR_EINT */
+#define WM8996_FIFOS_ERR_EINT_SHIFT                  9  /* FIFOS_ERR_EINT */
+#define WM8996_FIFOS_ERR_EINT_WIDTH                  1  /* FIFOS_ERR_EINT */
+#define WM8996_DSP2DRC_SIG_DET_EINT             0x0080  /* DSP2DRC_SIG_DET_EINT */
+#define WM8996_DSP2DRC_SIG_DET_EINT_MASK        0x0080  /* DSP2DRC_SIG_DET_EINT */
+#define WM8996_DSP2DRC_SIG_DET_EINT_SHIFT            7  /* DSP2DRC_SIG_DET_EINT */
+#define WM8996_DSP2DRC_SIG_DET_EINT_WIDTH            1  /* DSP2DRC_SIG_DET_EINT */
+#define WM8996_DSP1DRC_SIG_DET_EINT             0x0040  /* DSP1DRC_SIG_DET_EINT */
+#define WM8996_DSP1DRC_SIG_DET_EINT_MASK        0x0040  /* DSP1DRC_SIG_DET_EINT */
+#define WM8996_DSP1DRC_SIG_DET_EINT_SHIFT            6  /* DSP1DRC_SIG_DET_EINT */
+#define WM8996_DSP1DRC_SIG_DET_EINT_WIDTH            1  /* DSP1DRC_SIG_DET_EINT */
+#define WM8996_FLL_SW_CLK_DONE_EINT             0x0008  /* FLL_SW_CLK_DONE_EINT */
+#define WM8996_FLL_SW_CLK_DONE_EINT_MASK        0x0008  /* FLL_SW_CLK_DONE_EINT */
+#define WM8996_FLL_SW_CLK_DONE_EINT_SHIFT            3  /* FLL_SW_CLK_DONE_EINT */
+#define WM8996_FLL_SW_CLK_DONE_EINT_WIDTH            1  /* FLL_SW_CLK_DONE_EINT */
+#define WM8996_FLL_LOCK_EINT                    0x0004  /* FLL_LOCK_EINT */
+#define WM8996_FLL_LOCK_EINT_MASK               0x0004  /* FLL_LOCK_EINT */
+#define WM8996_FLL_LOCK_EINT_SHIFT                   2  /* FLL_LOCK_EINT */
+#define WM8996_FLL_LOCK_EINT_WIDTH                   1  /* FLL_LOCK_EINT */
+#define WM8996_HP_DONE_EINT                     0x0002  /* HP_DONE_EINT */
+#define WM8996_HP_DONE_EINT_MASK                0x0002  /* HP_DONE_EINT */
+#define WM8996_HP_DONE_EINT_SHIFT                    1  /* HP_DONE_EINT */
+#define WM8996_HP_DONE_EINT_WIDTH                    1  /* HP_DONE_EINT */
+#define WM8996_MICD_EINT                        0x0001  /* MICD_EINT */
+#define WM8996_MICD_EINT_MASK                   0x0001  /* MICD_EINT */
+#define WM8996_MICD_EINT_SHIFT                       0  /* MICD_EINT */
+#define WM8996_MICD_EINT_WIDTH                       1  /* MICD_EINT */
+
+/*
+ * R1842 (0x732) - Interrupt Raw Status 2
+ */
+#define WM8996_DCS_DONE_23_STS                  0x1000  /* DCS_DONE_23_STS */
+#define WM8996_DCS_DONE_23_STS_MASK             0x1000  /* DCS_DONE_23_STS */
+#define WM8996_DCS_DONE_23_STS_SHIFT                12  /* DCS_DONE_23_STS */
+#define WM8996_DCS_DONE_23_STS_WIDTH                 1  /* DCS_DONE_23_STS */
+#define WM8996_DCS_DONE_01_STS                  0x0800  /* DCS_DONE_01_STS */
+#define WM8996_DCS_DONE_01_STS_MASK             0x0800  /* DCS_DONE_01_STS */
+#define WM8996_DCS_DONE_01_STS_SHIFT                11  /* DCS_DONE_01_STS */
+#define WM8996_DCS_DONE_01_STS_WIDTH                 1  /* DCS_DONE_01_STS */
+#define WM8996_WSEQ_DONE_STS                    0x0400  /* WSEQ_DONE_STS */
+#define WM8996_WSEQ_DONE_STS_MASK               0x0400  /* WSEQ_DONE_STS */
+#define WM8996_WSEQ_DONE_STS_SHIFT                  10  /* WSEQ_DONE_STS */
+#define WM8996_WSEQ_DONE_STS_WIDTH                   1  /* WSEQ_DONE_STS */
+#define WM8996_FIFOS_ERR_STS                    0x0200  /* FIFOS_ERR_STS */
+#define WM8996_FIFOS_ERR_STS_MASK               0x0200  /* FIFOS_ERR_STS */
+#define WM8996_FIFOS_ERR_STS_SHIFT                   9  /* FIFOS_ERR_STS */
+#define WM8996_FIFOS_ERR_STS_WIDTH                   1  /* FIFOS_ERR_STS */
+#define WM8996_DSP2DRC_SIG_DET_STS              0x0080  /* DSP2DRC_SIG_DET_STS */
+#define WM8996_DSP2DRC_SIG_DET_STS_MASK         0x0080  /* DSP2DRC_SIG_DET_STS */
+#define WM8996_DSP2DRC_SIG_DET_STS_SHIFT             7  /* DSP2DRC_SIG_DET_STS */
+#define WM8996_DSP2DRC_SIG_DET_STS_WIDTH             1  /* DSP2DRC_SIG_DET_STS */
+#define WM8996_DSP1DRC_SIG_DET_STS              0x0040  /* DSP1DRC_SIG_DET_STS */
+#define WM8996_DSP1DRC_SIG_DET_STS_MASK         0x0040  /* DSP1DRC_SIG_DET_STS */
+#define WM8996_DSP1DRC_SIG_DET_STS_SHIFT             6  /* DSP1DRC_SIG_DET_STS */
+#define WM8996_DSP1DRC_SIG_DET_STS_WIDTH             1  /* DSP1DRC_SIG_DET_STS */
+#define WM8996_FLL_LOCK_STS                     0x0004  /* FLL_LOCK_STS */
+#define WM8996_FLL_LOCK_STS_MASK                0x0004  /* FLL_LOCK_STS */
+#define WM8996_FLL_LOCK_STS_SHIFT                    2  /* FLL_LOCK_STS */
+#define WM8996_FLL_LOCK_STS_WIDTH                    1  /* FLL_LOCK_STS */
+
+/*
+ * R1848 (0x738) - Interrupt Status 1 Mask
+ */
+#define WM8996_IM_GP5_EINT                      0x0010  /* IM_GP5_EINT */
+#define WM8996_IM_GP5_EINT_MASK                 0x0010  /* IM_GP5_EINT */
+#define WM8996_IM_GP5_EINT_SHIFT                     4  /* IM_GP5_EINT */
+#define WM8996_IM_GP5_EINT_WIDTH                     1  /* IM_GP5_EINT */
+#define WM8996_IM_GP4_EINT                      0x0008  /* IM_GP4_EINT */
+#define WM8996_IM_GP4_EINT_MASK                 0x0008  /* IM_GP4_EINT */
+#define WM8996_IM_GP4_EINT_SHIFT                     3  /* IM_GP4_EINT */
+#define WM8996_IM_GP4_EINT_WIDTH                     1  /* IM_GP4_EINT */
+#define WM8996_IM_GP3_EINT                      0x0004  /* IM_GP3_EINT */
+#define WM8996_IM_GP3_EINT_MASK                 0x0004  /* IM_GP3_EINT */
+#define WM8996_IM_GP3_EINT_SHIFT                     2  /* IM_GP3_EINT */
+#define WM8996_IM_GP3_EINT_WIDTH                     1  /* IM_GP3_EINT */
+#define WM8996_IM_GP2_EINT                      0x0002  /* IM_GP2_EINT */
+#define WM8996_IM_GP2_EINT_MASK                 0x0002  /* IM_GP2_EINT */
+#define WM8996_IM_GP2_EINT_SHIFT                     1  /* IM_GP2_EINT */
+#define WM8996_IM_GP2_EINT_WIDTH                     1  /* IM_GP2_EINT */
+#define WM8996_IM_GP1_EINT                      0x0001  /* IM_GP1_EINT */
+#define WM8996_IM_GP1_EINT_MASK                 0x0001  /* IM_GP1_EINT */
+#define WM8996_IM_GP1_EINT_SHIFT                     0  /* IM_GP1_EINT */
+#define WM8996_IM_GP1_EINT_WIDTH                     1  /* IM_GP1_EINT */
+
+/*
+ * R1849 (0x739) - Interrupt Status 2 Mask
+ */
+#define WM8996_IM_DCS_DONE_23_EINT              0x1000  /* IM_DCS_DONE_23_EINT */
+#define WM8996_IM_DCS_DONE_23_EINT_MASK         0x1000  /* IM_DCS_DONE_23_EINT */
+#define WM8996_IM_DCS_DONE_23_EINT_SHIFT            12  /* IM_DCS_DONE_23_EINT */
+#define WM8996_IM_DCS_DONE_23_EINT_WIDTH             1  /* IM_DCS_DONE_23_EINT */
+#define WM8996_IM_DCS_DONE_01_EINT              0x0800  /* IM_DCS_DONE_01_EINT */
+#define WM8996_IM_DCS_DONE_01_EINT_MASK         0x0800  /* IM_DCS_DONE_01_EINT */
+#define WM8996_IM_DCS_DONE_01_EINT_SHIFT            11  /* IM_DCS_DONE_01_EINT */
+#define WM8996_IM_DCS_DONE_01_EINT_WIDTH             1  /* IM_DCS_DONE_01_EINT */
+#define WM8996_IM_WSEQ_DONE_EINT                0x0400  /* IM_WSEQ_DONE_EINT */
+#define WM8996_IM_WSEQ_DONE_EINT_MASK           0x0400  /* IM_WSEQ_DONE_EINT */
+#define WM8996_IM_WSEQ_DONE_EINT_SHIFT              10  /* IM_WSEQ_DONE_EINT */
+#define WM8996_IM_WSEQ_DONE_EINT_WIDTH               1  /* IM_WSEQ_DONE_EINT */
+#define WM8996_IM_FIFOS_ERR_EINT                0x0200  /* IM_FIFOS_ERR_EINT */
+#define WM8996_IM_FIFOS_ERR_EINT_MASK           0x0200  /* IM_FIFOS_ERR_EINT */
+#define WM8996_IM_FIFOS_ERR_EINT_SHIFT               9  /* IM_FIFOS_ERR_EINT */
+#define WM8996_IM_FIFOS_ERR_EINT_WIDTH               1  /* IM_FIFOS_ERR_EINT */
+#define WM8996_IM_DSP2DRC_SIG_DET_EINT          0x0080  /* IM_DSP2DRC_SIG_DET_EINT */
+#define WM8996_IM_DSP2DRC_SIG_DET_EINT_MASK     0x0080  /* IM_DSP2DRC_SIG_DET_EINT */
+#define WM8996_IM_DSP2DRC_SIG_DET_EINT_SHIFT         7  /* IM_DSP2DRC_SIG_DET_EINT */
+#define WM8996_IM_DSP2DRC_SIG_DET_EINT_WIDTH         1  /* IM_DSP2DRC_SIG_DET_EINT */
+#define WM8996_IM_DSP1DRC_SIG_DET_EINT          0x0040  /* IM_DSP1DRC_SIG_DET_EINT */
+#define WM8996_IM_DSP1DRC_SIG_DET_EINT_MASK     0x0040  /* IM_DSP1DRC_SIG_DET_EINT */
+#define WM8996_IM_DSP1DRC_SIG_DET_EINT_SHIFT         6  /* IM_DSP1DRC_SIG_DET_EINT */
+#define WM8996_IM_DSP1DRC_SIG_DET_EINT_WIDTH         1  /* IM_DSP1DRC_SIG_DET_EINT */
+#define WM8996_IM_FLL_SW_CLK_DONE_EINT          0x0008  /* IM_FLL_SW_CLK_DONE_EINT */
+#define WM8996_IM_FLL_SW_CLK_DONE_EINT_MASK     0x0008  /* IM_FLL_SW_CLK_DONE_EINT */
+#define WM8996_IM_FLL_SW_CLK_DONE_EINT_SHIFT         3  /* IM_FLL_SW_CLK_DONE_EINT */
+#define WM8996_IM_FLL_SW_CLK_DONE_EINT_WIDTH         1  /* IM_FLL_SW_CLK_DONE_EINT */
+#define WM8996_IM_FLL_LOCK_EINT                 0x0004  /* IM_FLL_LOCK_EINT */
+#define WM8996_IM_FLL_LOCK_EINT_MASK            0x0004  /* IM_FLL_LOCK_EINT */
+#define WM8996_IM_FLL_LOCK_EINT_SHIFT                2  /* IM_FLL_LOCK_EINT */
+#define WM8996_IM_FLL_LOCK_EINT_WIDTH                1  /* IM_FLL_LOCK_EINT */
+#define WM8996_IM_HP_DONE_EINT                  0x0002  /* IM_HP_DONE_EINT */
+#define WM8996_IM_HP_DONE_EINT_MASK             0x0002  /* IM_HP_DONE_EINT */
+#define WM8996_IM_HP_DONE_EINT_SHIFT                 1  /* IM_HP_DONE_EINT */
+#define WM8996_IM_HP_DONE_EINT_WIDTH                 1  /* IM_HP_DONE_EINT */
+#define WM8996_IM_MICD_EINT                     0x0001  /* IM_MICD_EINT */
+#define WM8996_IM_MICD_EINT_MASK                0x0001  /* IM_MICD_EINT */
+#define WM8996_IM_MICD_EINT_SHIFT                    0  /* IM_MICD_EINT */
+#define WM8996_IM_MICD_EINT_WIDTH                    1  /* IM_MICD_EINT */
+
+/*
+ * R1856 (0x740) - Interrupt Control
+ */
+#define WM8996_IM_IRQ                           0x0001  /* IM_IRQ */
+#define WM8996_IM_IRQ_MASK                      0x0001  /* IM_IRQ */
+#define WM8996_IM_IRQ_SHIFT                          0  /* IM_IRQ */
+#define WM8996_IM_IRQ_WIDTH                          1  /* IM_IRQ */
+
+/*
+ * R2048 (0x800) - Left PDM Speaker
+ */
+#define WM8996_SPKL_ENA                         0x0010  /* SPKL_ENA */
+#define WM8996_SPKL_ENA_MASK                    0x0010  /* SPKL_ENA */
+#define WM8996_SPKL_ENA_SHIFT                        4  /* SPKL_ENA */
+#define WM8996_SPKL_ENA_WIDTH                        1  /* SPKL_ENA */
+#define WM8996_SPKL_MUTE                        0x0008  /* SPKL_MUTE */
+#define WM8996_SPKL_MUTE_MASK                   0x0008  /* SPKL_MUTE */
+#define WM8996_SPKL_MUTE_SHIFT                       3  /* SPKL_MUTE */
+#define WM8996_SPKL_MUTE_WIDTH                       1  /* SPKL_MUTE */
+#define WM8996_SPKL_MUTE_ZC                     0x0004  /* SPKL_MUTE_ZC */
+#define WM8996_SPKL_MUTE_ZC_MASK                0x0004  /* SPKL_MUTE_ZC */
+#define WM8996_SPKL_MUTE_ZC_SHIFT                    2  /* SPKL_MUTE_ZC */
+#define WM8996_SPKL_MUTE_ZC_WIDTH                    1  /* SPKL_MUTE_ZC */
+#define WM8996_SPKL_SRC_MASK                    0x0003  /* SPKL_SRC - [1:0] */
+#define WM8996_SPKL_SRC_SHIFT                        0  /* SPKL_SRC - [1:0] */
+#define WM8996_SPKL_SRC_WIDTH                        2  /* SPKL_SRC - [1:0] */
+
+/*
+ * R2049 (0x801) - Right PDM Speaker
+ */
+#define WM8996_SPKR_ENA                         0x0010  /* SPKR_ENA */
+#define WM8996_SPKR_ENA_MASK                    0x0010  /* SPKR_ENA */
+#define WM8996_SPKR_ENA_SHIFT                        4  /* SPKR_ENA */
+#define WM8996_SPKR_ENA_WIDTH                        1  /* SPKR_ENA */
+#define WM8996_SPKR_MUTE                        0x0008  /* SPKR_MUTE */
+#define WM8996_SPKR_MUTE_MASK                   0x0008  /* SPKR_MUTE */
+#define WM8996_SPKR_MUTE_SHIFT                       3  /* SPKR_MUTE */
+#define WM8996_SPKR_MUTE_WIDTH                       1  /* SPKR_MUTE */
+#define WM8996_SPKR_MUTE_ZC                     0x0004  /* SPKR_MUTE_ZC */
+#define WM8996_SPKR_MUTE_ZC_MASK                0x0004  /* SPKR_MUTE_ZC */
+#define WM8996_SPKR_MUTE_ZC_SHIFT                    2  /* SPKR_MUTE_ZC */
+#define WM8996_SPKR_MUTE_ZC_WIDTH                    1  /* SPKR_MUTE_ZC */
+#define WM8996_SPKR_SRC_MASK                    0x0003  /* SPKR_SRC - [1:0] */
+#define WM8996_SPKR_SRC_SHIFT                        0  /* SPKR_SRC - [1:0] */
+#define WM8996_SPKR_SRC_WIDTH                        2  /* SPKR_SRC - [1:0] */
+
+/*
+ * R2050 (0x802) - PDM Speaker Mute Sequence
+ */
+#define WM8996_SPK_MUTE_ENDIAN                  0x0100  /* SPK_MUTE_ENDIAN */
+#define WM8996_SPK_MUTE_ENDIAN_MASK             0x0100  /* SPK_MUTE_ENDIAN */
+#define WM8996_SPK_MUTE_ENDIAN_SHIFT                 8  /* SPK_MUTE_ENDIAN */
+#define WM8996_SPK_MUTE_ENDIAN_WIDTH                 1  /* SPK_MUTE_ENDIAN */
+#define WM8996_SPK_MUTE_SEQ1_MASK               0x00FF  /* SPK_MUTE_SEQ1 - [7:0] */
+#define WM8996_SPK_MUTE_SEQ1_SHIFT                   0  /* SPK_MUTE_SEQ1 - [7:0] */
+#define WM8996_SPK_MUTE_SEQ1_WIDTH                   8  /* SPK_MUTE_SEQ1 - [7:0] */
+
+/*
+ * R2051 (0x803) - PDM Speaker Volume
+ */
+#define WM8996_SPKR_VOL_MASK                    0x00F0  /* SPKR_VOL - [7:4] */
+#define WM8996_SPKR_VOL_SHIFT                        4  /* SPKR_VOL - [7:4] */
+#define WM8996_SPKR_VOL_WIDTH                        4  /* SPKR_VOL - [7:4] */
+#define WM8996_SPKL_VOL_MASK                    0x000F  /* SPKL_VOL - [3:0] */
+#define WM8996_SPKL_VOL_SHIFT                        0  /* SPKL_VOL - [3:0] */
+#define WM8996_SPKL_VOL_WIDTH                        4  /* SPKL_VOL - [3:0] */
+
+#endif
index 4cc2d56..e763c54 100644 (file)
@@ -440,9 +440,8 @@ static int hp_event(struct snd_soc_dapm_widget *w,
                reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY;
                snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg);
 
-               /* Smallest supported update interval */
                snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
-                                   WM8993_DCS_TIMER_PERIOD_01_MASK, 1);
+                                   WM8993_DCS_TIMER_PERIOD_01_MASK, 0);
 
                calibrate_dc_servo(codec);
 
index 54b0e4b..b99091f 100644 (file)
@@ -183,7 +183,7 @@ config SND_SOC_SPEYSIDE
        tristate "Audio support for Wolfson Speyside"
        depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
        select SND_SAMSUNG_I2S
-       select SND_SOC_WM8915
+       select SND_SOC_WM8996
        select SND_SOC_WM9081
 
 config SND_SOC_SPEYSIDE_WM8962
index d6dee4d..590e927 100644 (file)
 #include <sound/jack.h>
 #include <linux/gpio.h>
 
-#include "../codecs/wm8915.h"
+#include "../codecs/wm8996.h"
 #include "../codecs/wm9081.h"
 
-#define WM8915_HPSEL_GPIO 214
+#define WM8996_HPSEL_GPIO 214
 
 static int speyside_set_bias_level(struct snd_soc_card *card,
                                   struct snd_soc_dapm_context *dapm,
@@ -31,12 +31,12 @@ static int speyside_set_bias_level(struct snd_soc_card *card,
 
        switch (level) {
        case SND_SOC_BIAS_STANDBY:
-               ret = snd_soc_dai_set_sysclk(codec_dai, WM8915_SYSCLK_MCLK2,
+               ret = snd_soc_dai_set_sysclk(codec_dai, WM8996_SYSCLK_MCLK2,
                                             32768, SND_SOC_CLOCK_IN);
                if (ret < 0)
                        return ret;
 
-               ret = snd_soc_dai_set_pll(codec_dai, WM8915_FLL_MCLK2,
+               ret = snd_soc_dai_set_pll(codec_dai, WM8996_FLL_MCLK2,
                                          0, 0, 0);
                if (ret < 0) {
                        pr_err("Failed to stop FLL\n");
@@ -65,7 +65,7 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card,
        case SND_SOC_BIAS_PREPARE:
                if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
                        ret = snd_soc_dai_set_pll(codec_dai, 0,
-                                                 WM8915_FLL_MCLK2,
+                                                 WM8996_FLL_MCLK2,
                                                  32768, 48000 * 256);
                        if (ret < 0) {
                                pr_err("Failed to start FLL\n");
@@ -73,7 +73,7 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card,
                        }
 
                        ret = snd_soc_dai_set_sysclk(codec_dai,
-                                                    WM8915_SYSCLK_FLL,
+                                                    WM8996_SYSCLK_FLL,
                                                     48000 * 256,
                                                     SND_SOC_CLOCK_IN);
                        if (ret < 0)
@@ -149,26 +149,26 @@ static void speyside_set_polarity(struct snd_soc_codec *codec,
                                  int polarity)
 {
        speyside_jack_polarity = !polarity;
-       gpio_direction_output(WM8915_HPSEL_GPIO, speyside_jack_polarity);
+       gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity);
 
        /* Re-run DAPM to make sure we're using the correct mic bias */
        snd_soc_dapm_sync(&codec->dapm);
 }
 
-static int speyside_wm8915_init(struct snd_soc_pcm_runtime *rtd)
+static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_dai *dai = rtd->codec_dai;
        struct snd_soc_codec *codec = rtd->codec;
        int ret;
 
-       ret = snd_soc_dai_set_sysclk(dai, WM8915_SYSCLK_MCLK2, 32768, 0);
+       ret = snd_soc_dai_set_sysclk(dai, WM8996_SYSCLK_MCLK2, 32768, 0);
        if (ret < 0)
                return ret;
 
-       ret = gpio_request(WM8915_HPSEL_GPIO, "HP_SEL");
+       ret = gpio_request(WM8996_HPSEL_GPIO, "HP_SEL");
        if (ret != 0)
                pr_err("Failed to request HP_SEL GPIO: %d\n", ret);
-       gpio_direction_output(WM8915_HPSEL_GPIO, speyside_jack_polarity);
+       gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity);
 
        ret = snd_soc_jack_new(codec, "Headset",
                               SND_JACK_HEADSET | SND_JACK_BTN_0,
@@ -182,7 +182,7 @@ static int speyside_wm8915_init(struct snd_soc_pcm_runtime *rtd)
        if (ret)
                return ret;
 
-       wm8915_detect(codec, &speyside_headset, speyside_set_polarity);
+       wm8996_detect(codec, &speyside_headset, speyside_set_polarity);
 
        return 0;
 }
@@ -205,16 +205,16 @@ static struct snd_soc_dai_link speyside_dai[] = {
                .name = "CPU",
                .stream_name = "CPU",
                .cpu_dai_name = "samsung-i2s.0",
-               .codec_dai_name = "wm8915-aif1",
+               .codec_dai_name = "wm8996-aif1",
                .platform_name = "samsung-audio",
-               .codec_name = "wm8915.1-001a",
-               .init = speyside_wm8915_init,
+               .codec_name = "wm8996.1-001a",
+               .init = speyside_wm8996_init,
                .ops = &speyside_ops,
        },
        {
                .name = "Baseband",
                .stream_name = "Baseband",
-               .cpu_dai_name = "wm8915-aif2",
+               .cpu_dai_name = "wm8996-aif2",
                .codec_dai_name = "wm1250-ev1",
                .codec_name = "wm1250-ev1.1-0027",
                .ops = &speyside_ops,
index 34aa972..3de99af 100644 (file)
@@ -290,6 +290,7 @@ static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static int txx9aclc_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_card *card = rtd->card->snd_card;
        struct snd_soc_dai *dai = rtd->cpu_dai;
        struct snd_pcm *pcm = rtd->pcm;
        struct platform_device *pdev = to_platform_device(dai->platform->dev);
index 4432ef7..a213813 100644 (file)
@@ -30,7 +30,7 @@ static unsigned short keycode_ak1[] =  { KEY_C, KEY_B, KEY_A };
 static unsigned short keycode_rk2[] =  { KEY_1, KEY_2, KEY_3, KEY_4,
                                         KEY_5, KEY_6, KEY_7 };
 static unsigned short keycode_rk3[] =  { KEY_1, KEY_2, KEY_3, KEY_4,
-                                        KEY_5, KEY_6, KEY_7, KEY_5, KEY_6 };
+                                        KEY_5, KEY_6, KEY_7, KEY_8, KEY_9 };
 
 static unsigned short keycode_kore[] = {
        KEY_FN_F1,      /* "menu"               */
index 7c0d21e..7d46e48 100644 (file)
@@ -352,7 +352,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                        continue;
                }
                if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
-                   ((protocol == UAC_VERSION_2) && (fmt->bLength != 6))) {
+                   ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
                        snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
                                   dev->devnum, iface_no, altno);
                        continue;
index c22fa76..c04d7c7 100644 (file)
@@ -1191,6 +1191,11 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
 
        if (state->mixer->protocol == UAC_VERSION_1) {
                csize = hdr->bControlSize;
+               if (!csize) {
+                       snd_printdd(KERN_ERR "usbaudio: unit %u: "
+                                   "invalid bControlSize == 0\n", unitid);
+                       return -EINVAL;
+               }
                channels = (hdr->bLength - 7) / csize - 1;
                bmaControls = hdr->bmaControls;
        } else {
@@ -1934,15 +1939,13 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
        struct mixer_build state;
        int err;
        const struct usbmix_ctl_map *map;
-       struct usb_host_interface *hostif;
        void *p;
 
-       hostif = mixer->chip->ctrl_intf;
        memset(&state, 0, sizeof(state));
        state.chip = mixer->chip;
        state.mixer = mixer;
-       state.buffer = hostif->extra;
-       state.buflen = hostif->extralen;
+       state.buffer = mixer->hostif->extra;
+       state.buflen = mixer->hostif->extralen;
 
        /* check the mapping table */
        for (map = usbmix_ctl_maps; map->id; map++) {
@@ -1955,7 +1958,8 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
        }
 
        p = NULL;
-       while ((p = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, p, UAC_OUTPUT_TERMINAL)) != NULL) {
+       while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen,
+                                           p, UAC_OUTPUT_TERMINAL)) != NULL) {
                if (mixer->protocol == UAC_VERSION_1) {
                        struct uac1_output_terminal_descriptor *desc = p;
 
@@ -2162,17 +2166,15 @@ int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
 /* create the handler for the optional status interrupt endpoint */
 static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
 {
-       struct usb_host_interface *hostif;
        struct usb_endpoint_descriptor *ep;
        void *transfer_buffer;
        int buffer_length;
        unsigned int epnum;
 
-       hostif = mixer->chip->ctrl_intf;
        /* we need one interrupt input endpoint */
-       if (get_iface_desc(hostif)->bNumEndpoints < 1)
+       if (get_iface_desc(mixer->hostif)->bNumEndpoints < 1)
                return 0;
-       ep = get_endpoint(hostif, 0);
+       ep = get_endpoint(mixer->hostif, 0);
        if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_int(ep))
                return 0;
 
@@ -2202,7 +2204,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
        };
        struct usb_mixer_interface *mixer;
        struct snd_info_entry *entry;
-       struct usb_host_interface *host_iface;
        int err;
 
        strcpy(chip->card->mixername, "USB Mixer");
@@ -2219,8 +2220,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
                return -ENOMEM;
        }
 
-       host_iface = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
-       switch (get_iface_desc(host_iface)->bInterfaceProtocol) {
+       mixer->hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
+       switch (get_iface_desc(mixer->hostif)->bInterfaceProtocol) {
        case UAC_VERSION_1:
        default:
                mixer->protocol = UAC_VERSION_1;
index ae1a14d..81b2d8a 100644 (file)
@@ -3,6 +3,7 @@
 
 struct usb_mixer_interface {
        struct snd_usb_audio *chip;
+       struct usb_host_interface *hostif;
        struct list_head list;
        unsigned int ignore_ctl_error;
        struct urb *urb;
index dba0b7f..4d4f865 100644 (file)
@@ -2417,6 +2417,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .idProduct = 0x1020,
 },
 
+/* KeithMcMillen Stringport */
+{
+       USB_DEVICE(0x1f38, 0x0001),
+       .bInterfaceClass = USB_CLASS_AUDIO,
+},
+
 /* Miditech devices */
 {
        USB_DEVICE(0x4752, 0x0011),
index 77762c9..81e07d8 100644 (file)
@@ -426,7 +426,7 @@ static int snd_usb_cm106_boot_quirk(struct usb_device *dev)
  */
 static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
 {
-       int err, reg;
+       int err  = 0, reg;
        int val[] = {0x2004, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000};
 
        for (reg = 0; reg < ARRAY_SIZE(val); reg++) {
index 56d62d3..3b8f7b8 100644 (file)
@@ -181,9 +181,9 @@ strip-libs = $(filter-out -l%,$(1))
 
 $(OUTPUT)python/perf.so: $(PYRF_OBJS)
        $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
-         --quiet build_ext \
-         --build-lib='$(OUTPUT)python' \
-         --build-temp='$(OUTPUT)python/temp'
+         --quiet build_ext; \
+       mkdir -p $(OUTPUT)python && \
+       cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
 #
 # No Perl scripts right now:
 #
@@ -509,9 +509,13 @@ else
 
   PYTHON_WORD := $(call shell-wordify,$(PYTHON))
 
-  python-clean := $(PYTHON_WORD) util/setup.py clean \
-    --build-lib='$(OUTPUT)python' \
-    --build-temp='$(OUTPUT)python/temp'
+  # python extension build directories
+  PYTHON_EXTBUILD     := $(OUTPUT)python_ext_build/
+  PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
+  PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
+  export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
+
+  python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
 
   ifdef NO_LIBPYTHON
     $(call disable-python)
@@ -868,6 +872,9 @@ install: all
        $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'
        $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
 
+install-python_ext:
+       $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
+
 install-doc:
        $(MAKE) -C Documentation install
 
@@ -895,7 +902,7 @@ quick-install-html:
 ### Cleaning rules
 
 clean:
-       $(RM) $(OUTPUT){*.o,*/*.o,*/*/*.o,*/*/*/*.o,$(LIB_FILE),perf-archive}
+       $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS)
        $(RM) $(ALL_PROGRAMS) perf
        $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
        $(MAKE) -C Documentation/ clean
index 9ac05aa..899080a 100644 (file)
@@ -942,10 +942,10 @@ static const char *record_args[] = {
        "-f",
        "-m", "1024",
        "-c", "1",
-       "-e", "lock:lock_acquire:r",
-       "-e", "lock:lock_acquired:r",
-       "-e", "lock:lock_contended:r",
-       "-e", "lock:lock_release:r",
+       "-e", "lock:lock_acquire",
+       "-e", "lock:lock_acquired",
+       "-e", "lock:lock_contended",
+       "-e", "lock:lock_release",
 };
 
 static int __cmd_record(int argc, const char **argv)
index 80dc5b7..f6426b4 100644 (file)
@@ -30,8 +30,6 @@
 #include <sched.h>
 #include <sys/mman.h>
 
-#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
-
 enum write_mode_t {
        WRITE_FORCE,
        WRITE_APPEND
@@ -438,7 +436,6 @@ static void mmap_read_all(void)
 
 static int __cmd_record(int argc, const char **argv)
 {
-       int i;
        struct stat st;
        int flags;
        int err;
@@ -682,7 +679,6 @@ static int __cmd_record(int argc, const char **argv)
 
        for (;;) {
                int hits = samples;
-               int thread;
 
                mmap_read_all();
 
@@ -693,19 +689,8 @@ static int __cmd_record(int argc, const char **argv)
                        waking++;
                }
 
-               if (done) {
-                       for (i = 0; i < evsel_list->cpus->nr; i++) {
-                               struct perf_evsel *pos;
-
-                               list_for_each_entry(pos, &evsel_list->entries, node) {
-                                       for (thread = 0;
-                                               thread < evsel_list->threads->nr;
-                                               thread++)
-                                               ioctl(FD(pos, i, thread),
-                                                       PERF_EVENT_IOC_DISABLE);
-                               }
-                       }
-               }
+               if (done)
+                       perf_evlist__disable(evsel_list);
        }
 
        if (quiet || signr == SIGUSR1)
index f854efd..d7ff277 100644 (file)
@@ -162,23 +162,22 @@ static int perf_session__setup_sample_type(struct perf_session *self)
 {
        if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
                if (sort__has_parent) {
-                       fprintf(stderr, "selected --sort parent, but no"
-                                       " callchain data. Did you call"
-                                       " perf record without -g?\n");
+                       ui__warning("Selected --sort parent, but no "
+                                   "callchain data. Did you call "
+                                   "'perf record' without -g?\n");
                        return -EINVAL;
                }
                if (symbol_conf.use_callchain) {
-                       fprintf(stderr, "selected -g but no callchain data."
-                                       " Did you call perf record without"
-                                       " -g?\n");
+                       ui__warning("Selected -g but no callchain data. Did "
+                                   "you call 'perf record' without -g?\n");
                        return -1;
                }
        } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE &&
                   !symbol_conf.use_callchain) {
                        symbol_conf.use_callchain = true;
                        if (callchain_register_param(&callchain_param) < 0) {
-                               fprintf(stderr, "Can't register callchain"
-                                               " params\n");
+                               ui__warning("Can't register callchain "
+                                           "params.\n");
                                return -EINVAL;
                        }
        }
index dcfe887..5177964 100644 (file)
@@ -1637,23 +1637,29 @@ static struct perf_event_ops event_ops = {
        .ordered_samples        = true,
 };
 
-static int read_events(void)
+static void read_events(bool destroy, struct perf_session **psession)
 {
        int err = -EINVAL;
        struct perf_session *session = perf_session__new(input_name, O_RDONLY,
                                                         0, false, &event_ops);
        if (session == NULL)
-               return -ENOMEM;
+               die("No Memory");
 
        if (perf_session__has_traces(session, "record -R")) {
                err = perf_session__process_events(session, &event_ops);
+               if (err)
+                       die("Failed to process events, error %d", err);
+
                nr_events      = session->hists.stats.nr_events[0];
                nr_lost_events = session->hists.stats.total_lost;
                nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST];
        }
 
-       perf_session__delete(session);
-       return err;
+       if (destroy)
+               perf_session__delete(session);
+
+       if (psession)
+               *psession = session;
 }
 
 static void print_bad_events(void)
@@ -1689,9 +1695,10 @@ static void print_bad_events(void)
 static void __cmd_lat(void)
 {
        struct rb_node *next;
+       struct perf_session *session;
 
        setup_pager();
-       read_events();
+       read_events(false, &session);
        sort_lat();
 
        printf("\n ---------------------------------------------------------------------------------------------------------------\n");
@@ -1717,6 +1724,7 @@ static void __cmd_lat(void)
        print_bad_events();
        printf("\n");
 
+       perf_session__delete(session);
 }
 
 static struct trace_sched_handler map_ops  = {
@@ -1731,7 +1739,7 @@ static void __cmd_map(void)
        max_cpu = sysconf(_SC_NPROCESSORS_CONF);
 
        setup_pager();
-       read_events();
+       read_events(true, NULL);
        print_bad_events();
 }
 
@@ -1744,7 +1752,7 @@ static void __cmd_replay(void)
 
        test_calibrations();
 
-       read_events();
+       read_events(true, NULL);
 
        printf("nr_run_events:        %ld\n", nr_run_events);
        printf("nr_sleep_events:      %ld\n", nr_sleep_events);
@@ -1769,7 +1777,7 @@ static void __cmd_replay(void)
 
 
 static const char * const sched_usage[] = {
-       "perf sched [<options>] {record|latency|map|replay|trace}",
+       "perf sched [<options>] {record|latency|map|replay|script}",
        NULL
 };
 
index e02d78c..fe02903 100644 (file)
@@ -399,7 +399,6 @@ static int perf_config_global(void)
 int perf_config(config_fn_t fn, void *data)
 {
        int ret = 0, found = 0;
-       char *repo_config = NULL;
        const char *home = NULL;
 
        /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
@@ -414,19 +413,32 @@ int perf_config(config_fn_t fn, void *data)
        home = getenv("HOME");
        if (perf_config_global() && home) {
                char *user_config = strdup(mkpath("%s/.perfconfig", home));
-               if (!access(user_config, R_OK)) {
-                       ret += perf_config_from_file(fn, user_config, data);
-                       found += 1;
+               struct stat st;
+
+               if (user_config == NULL) {
+                       warning("Not enough memory to process %s/.perfconfig, "
+                               "ignoring it.", home);
+                       goto out;
                }
-               free(user_config);
-       }
 
-       repo_config = perf_pathdup("config");
-       if (!access(repo_config, R_OK)) {
-               ret += perf_config_from_file(fn, repo_config, data);
+               if (stat(user_config, &st) < 0)
+                       goto out_free;
+
+               if (st.st_uid && (st.st_uid != geteuid())) {
+                       warning("File %s not owned by current user or root, "
+                               "ignoring it.", user_config);
+                       goto out_free;
+               }
+
+               if (!st.st_size)
+                       goto out_free;
+
+               ret += perf_config_from_file(fn, user_config, data);
                found += 1;
+out_free:
+               free(user_config);
        }
-       free(repo_config);
+out:
        if (found == 0)
                return -1;
        return ret;
index b021ea9..e03e7bc 100644 (file)
@@ -91,6 +91,19 @@ int perf_evlist__add_default(struct perf_evlist *evlist)
        return 0;
 }
 
+void perf_evlist__disable(struct perf_evlist *evlist)
+{
+       int cpu, thread;
+       struct perf_evsel *pos;
+
+       for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
+               list_for_each_entry(pos, &evlist->entries, node) {
+                       for (thread = 0; thread < evlist->threads->nr; thread++)
+                               ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_DISABLE);
+               }
+       }
+}
+
 int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
 {
        int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries;
index b2b8623..ce85ae9 100644 (file)
@@ -53,6 +53,8 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
 int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
 void perf_evlist__munmap(struct perf_evlist *evlist);
 
+void perf_evlist__disable(struct perf_evlist *evlist);
+
 static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
                                         struct cpu_map *cpus,
                                         struct thread_map *threads)
index cb2959a..d4f3101 100644 (file)
@@ -189,8 +189,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
                          const char *name, bool is_kallsyms)
 {
        const size_t size = PATH_MAX;
-       char *realname, *filename = malloc(size),
-            *linkname = malloc(size), *targetname;
+       char *realname, *filename = zalloc(size),
+            *linkname = zalloc(size), *targetname;
        int len, err = -1;
 
        if (is_kallsyms) {
@@ -254,8 +254,8 @@ static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
 int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
 {
        const size_t size = PATH_MAX;
-       char *filename = malloc(size),
-            *linkname = malloc(size);
+       char *filename = zalloc(size),
+            *linkname = zalloc(size);
        int err = -1;
 
        if (filename == NULL || linkname == NULL)
index b82d54f..1c7bfa5 100644 (file)
@@ -1820,11 +1820,15 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
                ret = -ENOMEM;
                goto error;
        }
-       tev->point.module = strdup(module);
-       if (tev->point.module == NULL) {
-               ret = -ENOMEM;
-               goto error;
+
+       if (module) {
+               tev->point.module = strdup(module);
+               if (tev->point.module == NULL) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
        }
+
        tev->point.offset = pev->point.offset;
        tev->point.retprobe = pev->point.retprobe;
        tev->nargs = pev->nargs;
index 8e0b5a3..cbc8f21 100644 (file)
@@ -187,14 +187,117 @@ static PyTypeObject pyrf_throttle_event__type = {
        .tp_repr        = (reprfunc)pyrf_throttle_event__repr,
 };
 
+static char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object.");
+
+static PyMemberDef pyrf_lost_event__members[] = {
+       sample_members
+       member_def(lost_event, id, T_ULONGLONG, "event id"),
+       member_def(lost_event, lost, T_ULONGLONG, "number of lost events"),
+       { .name = NULL, },
+};
+
+static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent)
+{
+       PyObject *ret;
+       char *s;
+
+       if (asprintf(&s, "{ type: lost, id: %#" PRIx64 ", "
+                        "lost: %#" PRIx64 " }",
+                    pevent->event.lost.id, pevent->event.lost.lost) < 0) {
+               ret = PyErr_NoMemory();
+       } else {
+               ret = PyString_FromString(s);
+               free(s);
+       }
+       return ret;
+}
+
+static PyTypeObject pyrf_lost_event__type = {
+       PyVarObject_HEAD_INIT(NULL, 0)
+       .tp_name        = "perf.lost_event",
+       .tp_basicsize   = sizeof(struct pyrf_event),
+       .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+       .tp_doc         = pyrf_lost_event__doc,
+       .tp_members     = pyrf_lost_event__members,
+       .tp_repr        = (reprfunc)pyrf_lost_event__repr,
+};
+
+static char pyrf_read_event__doc[] = PyDoc_STR("perf read event object.");
+
+static PyMemberDef pyrf_read_event__members[] = {
+       sample_members
+       member_def(read_event, pid, T_UINT, "event pid"),
+       member_def(read_event, tid, T_UINT, "event tid"),
+       { .name = NULL, },
+};
+
+static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent)
+{
+       return PyString_FromFormat("{ type: read, pid: %u, tid: %u }",
+                                  pevent->event.read.pid,
+                                  pevent->event.read.tid);
+       /*
+        * FIXME: return the array of read values,
+        * making this method useful ;-)
+        */
+}
+
+static PyTypeObject pyrf_read_event__type = {
+       PyVarObject_HEAD_INIT(NULL, 0)
+       .tp_name        = "perf.read_event",
+       .tp_basicsize   = sizeof(struct pyrf_event),
+       .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+       .tp_doc         = pyrf_read_event__doc,
+       .tp_members     = pyrf_read_event__members,
+       .tp_repr        = (reprfunc)pyrf_read_event__repr,
+};
+
+static char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object.");
+
+static PyMemberDef pyrf_sample_event__members[] = {
+       sample_members
+       member_def(perf_event_header, type, T_UINT, "event type"),
+       { .name = NULL, },
+};
+
+static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent)
+{
+       PyObject *ret;
+       char *s;
+
+       if (asprintf(&s, "{ type: sample }") < 0) {
+               ret = PyErr_NoMemory();
+       } else {
+               ret = PyString_FromString(s);
+               free(s);
+       }
+       return ret;
+}
+
+static PyTypeObject pyrf_sample_event__type = {
+       PyVarObject_HEAD_INIT(NULL, 0)
+       .tp_name        = "perf.sample_event",
+       .tp_basicsize   = sizeof(struct pyrf_event),
+       .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+       .tp_doc         = pyrf_sample_event__doc,
+       .tp_members     = pyrf_sample_event__members,
+       .tp_repr        = (reprfunc)pyrf_sample_event__repr,
+};
+
 static int pyrf_event__setup_types(void)
 {
        int err;
        pyrf_mmap_event__type.tp_new =
        pyrf_task_event__type.tp_new =
        pyrf_comm_event__type.tp_new =
+       pyrf_lost_event__type.tp_new =
+       pyrf_read_event__type.tp_new =
+       pyrf_sample_event__type.tp_new =
        pyrf_throttle_event__type.tp_new = PyType_GenericNew;
        err = PyType_Ready(&pyrf_mmap_event__type);
+       if (err < 0)
+               goto out;
+       err = PyType_Ready(&pyrf_lost_event__type);
        if (err < 0)
                goto out;
        err = PyType_Ready(&pyrf_task_event__type);
@@ -206,20 +309,26 @@ static int pyrf_event__setup_types(void)
        err = PyType_Ready(&pyrf_throttle_event__type);
        if (err < 0)
                goto out;
+       err = PyType_Ready(&pyrf_read_event__type);
+       if (err < 0)
+               goto out;
+       err = PyType_Ready(&pyrf_sample_event__type);
+       if (err < 0)
+               goto out;
 out:
        return err;
 }
 
 static PyTypeObject *pyrf_event__type[] = {
        [PERF_RECORD_MMAP]       = &pyrf_mmap_event__type,
-       [PERF_RECORD_LOST]       = &pyrf_mmap_event__type,
+       [PERF_RECORD_LOST]       = &pyrf_lost_event__type,
        [PERF_RECORD_COMM]       = &pyrf_comm_event__type,
        [PERF_RECORD_EXIT]       = &pyrf_task_event__type,
        [PERF_RECORD_THROTTLE]   = &pyrf_throttle_event__type,
        [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
        [PERF_RECORD_FORK]       = &pyrf_task_event__type,
-       [PERF_RECORD_READ]       = &pyrf_mmap_event__type,
-       [PERF_RECORD_SAMPLE]     = &pyrf_mmap_event__type,
+       [PERF_RECORD_READ]       = &pyrf_read_event__type,
+       [PERF_RECORD_SAMPLE]     = &pyrf_sample_event__type,
 };
 
 static PyObject *pyrf_event__new(union perf_event *event)
index bbc982f..95d3700 100644 (file)
@@ -3,9 +3,27 @@
 from distutils.core import setup, Extension
 from os import getenv
 
+from distutils.command.build_ext   import build_ext   as _build_ext
+from distutils.command.install_lib import install_lib as _install_lib
+
+class build_ext(_build_ext):
+    def finalize_options(self):
+        _build_ext.finalize_options(self)
+        self.build_lib  = build_lib
+        self.build_temp = build_tmp
+
+class install_lib(_install_lib):
+    def finalize_options(self):
+        _install_lib.finalize_options(self)
+        self.build_dir = build_lib
+
+
 cflags = ['-fno-strict-aliasing', '-Wno-write-strings']
 cflags += getenv('CFLAGS', '').split()
 
+build_lib = getenv('PYTHON_EXTBUILD_LIB')
+build_tmp = getenv('PYTHON_EXTBUILD_TMP')
+
 perf = Extension('perf',
                  sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c',
                             'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
@@ -21,4 +39,5 @@ setup(name='perf',
       author_email='acme@redhat.com',
       license='GPLv2',
       url='http://perf.wiki.kernel.org',
-      ext_modules=[perf])
+      ext_modules=[perf],
+      cmdclass={'build_ext': build_ext, 'install_lib': install_lib})
index eec1963..a8b5371 100644 (file)
@@ -1504,6 +1504,17 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
        dso->adjust_symbols = 0;
 
        if (strncmp(dso->name, "/tmp/perf-", 10) == 0) {
+               struct stat st;
+
+               if (stat(dso->name, &st) < 0)
+                       return -1;
+
+               if (st.st_uid && (st.st_uid != geteuid())) {
+                       pr_warning("File %s not owned by current user or root, "
+                               "ignoring it.\n", dso->name);
+                       return -1;
+               }
+
                ret = dso__load_perf_map(dso, map, filter);
                dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT :
                                              SYMTAB__NOT_FOUND;
diff --git a/tools/power/cpupower/.gitignore b/tools/power/cpupower/.gitignore
new file mode 100644 (file)
index 0000000..8a83dd2
--- /dev/null
@@ -0,0 +1,22 @@
+.libs
+libcpupower.so
+libcpupower.so.0
+libcpupower.so.0.0.0
+build/ccdv
+cpufreq-info
+cpufreq-set
+cpufreq-aperf
+lib/.libs
+lib/cpufreq.lo
+lib/cpufreq.o
+lib/proc.lo
+lib/proc.o
+lib/sysfs.lo
+lib/sysfs.o
+po/cpupowerutils.pot
+po/*.gmo
+utils/cpufreq-info.o
+utils/cpufreq-set.o
+utils/cpufreq-aperf.o
+cpupower
+bench/cpufreq-bench
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
new file mode 100644 (file)
index 0000000..94c2cf0
--- /dev/null
@@ -0,0 +1,279 @@
+# Makefile for cpupower
+#
+# Copyright (C) 2005,2006 Dominik Brodowski <linux@dominikbrodowski.net>
+#
+# Based largely on the Makefile for udev by:
+#
+# Copyright (C) 2003,2004 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; version 2 of the License.
+#
+# 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
+#
+
+# --- CONFIGURATION BEGIN ---
+
+# Set the following to `true' to make a unstripped, unoptimized
+# binary. Leave this set to `false' for production use.
+DEBUG ?=       false
+
+# make the build silent. Set this to something else to make it noisy again.
+V ?=           false
+
+# Internationalization support (output in different languages).
+# Requires gettext.
+NLS ?=         true
+
+# Set the following to 'true' to build/install the
+# cpufreq-bench benchmarking tool
+CPUFRQ_BENCH ?= true
+
+# Prefix to the directories we're installing to
+DESTDIR ?=
+
+# --- CONFIGURATION END ---
+
+
+
+# Package-related definitions. Distributions can modify the version
+# and _should_ modify the PACKAGE_BUGREPORT definition
+
+VERSION=                       $(shell ./utils/version-gen.sh)
+LIB_MAJ=                       0.0.0
+LIB_MIN=                       0
+
+PACKAGE =                      cpupower
+PACKAGE_BUGREPORT =            cpufreq@vger.kernel.org
+LANGUAGES =                    de fr it cs pt
+
+
+# Directory definitions. These are default and most probably
+# do not need to be changed. Please note that DESTDIR is
+# added in front of any of them
+
+bindir ?=      /usr/bin
+sbindir ?=     /usr/sbin
+mandir ?=      /usr/man
+includedir ?=  /usr/include
+libdir ?=      /usr/lib
+localedir ?=   /usr/share/locale
+docdir ?=       /usr/share/doc/packages/cpupower
+confdir ?=      /etc/
+
+# Toolchain: what tools do we use, and what options do they need:
+
+CP = cp -fpR
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA  = ${INSTALL} -m 644
+INSTALL_SCRIPT = ${INSTALL_PROGRAM}
+
+# If you are running a cross compiler, you may want to set this
+# to something more interesting, like "arm-linux-".  If you want
+# to compile vs uClibc, that can be done here as well.
+CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc-
+CC = $(CROSS)gcc
+LD = $(CROSS)gcc
+AR = $(CROSS)ar
+STRIP = $(CROSS)strip
+RANLIB = $(CROSS)ranlib
+HOSTCC = gcc
+
+
+# Now we set up the build system
+#
+
+# set up PWD so that older versions of make will work with our build.
+PWD = $(shell pwd)
+
+GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo po/$$HLANG.gmo; done;}
+
+export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS
+
+# check if compiler option is supported
+cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;}
+
+# use '-Os' optimization if available, else use -O2
+OPTIMIZATION := $(call cc-supports,-Os,-O2)
+
+WARNINGS := -Wall -Wchar-subscripts -Wpointer-arith -Wsign-compare
+WARNINGS += $(call cc-supports,-Wno-pointer-sign)
+WARNINGS += $(call cc-supports,-Wdeclaration-after-statement)
+WARNINGS += -Wshadow
+
+CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \
+               -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE
+
+UTIL_OBJS =  utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \
+       utils/helpers/sysfs.o utils/helpers/misc.o utils/helpers/cpuid.o \
+       utils/helpers/pci.o utils/helpers/bitmask.o \
+       utils/idle_monitor/nhm_idle.o utils/idle_monitor/snb_idle.o \
+       utils/idle_monitor/amd_fam14h_idle.o utils/idle_monitor/cpuidle_sysfs.o \
+       utils/idle_monitor/mperf_monitor.o utils/idle_monitor/cpupower-monitor.o \
+       utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \
+       utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o
+
+UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \
+       utils/helpers/bitmask.h \
+       utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def
+
+UTIL_SRC := $(UTIL_OBJS:.o=.c)
+
+LIB_HEADERS =  lib/cpufreq.h lib/sysfs.h
+LIB_SRC =      lib/cpufreq.c lib/sysfs.c
+LIB_OBJS =     lib/cpufreq.o lib/sysfs.o
+
+CFLAGS +=      -pipe
+
+ifeq ($(strip $(NLS)),true)
+       INSTALL_NLS += install-gmo
+       COMPILE_NLS += create-gmo
+endif
+
+ifeq ($(strip $(CPUFRQ_BENCH)),true)
+       INSTALL_BENCH += install-bench
+       COMPILE_BENCH += compile-bench
+endif
+
+CFLAGS += $(WARNINGS)
+
+ifeq ($(strip $(V)),false)
+       QUIET=@
+       ECHO=@echo
+else
+       QUIET=
+       ECHO=@\#
+endif
+export QUIET ECHO
+
+# if DEBUG is enabled, then we do not strip or optimize
+ifeq ($(strip $(DEBUG)),true)
+       CFLAGS += -O1 -g -DDEBUG
+       STRIPCMD = /bin/true -Since_we_are_debugging
+else
+       CFLAGS += $(OPTIMIZATION) -fomit-frame-pointer
+       STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment
+endif
+
+
+# the actual make rules
+
+all: libcpupower cpupower $(COMPILE_NLS) $(COMPILE_BENCH)
+
+lib/%.o: $(LIB_SRC) $(LIB_HEADERS)
+       $(ECHO) "  CC      " $@
+       $(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c
+
+libcpupower.so.$(LIB_MAJ): $(LIB_OBJS)
+       $(ECHO) "  LD      " $@
+       $(QUIET) $(CC) -shared $(CFLAGS) $(LDFLAGS) -o $@ \
+               -Wl,-soname,libcpupower.so.$(LIB_MIN) $(LIB_OBJS)
+       @ln -sf $@ libcpupower.so
+       @ln -sf $@ libcpupower.so.$(LIB_MIN)
+
+libcpupower: libcpupower.so.$(LIB_MAJ)
+
+# Let all .o files depend on its .c file and all headers
+# Might be worth to put this into utils/Makefile at some point of time
+$(UTIL_OBJS): $(UTIL_HEADERS)
+
+.c.o:
+       $(ECHO) "  CC      " $@
+       $(QUIET) $(CC) $(CFLAGS) -I./lib -I ./utils -o $@ -c $*.c
+
+cpupower: $(UTIL_OBJS) libcpupower.so.$(LIB_MAJ)
+       $(ECHO) "  CC      " $@
+       $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -lcpupower -lrt -lpci -L. -o $@ $(UTIL_OBJS)
+       $(QUIET) $(STRIPCMD) $@
+
+po/$(PACKAGE).pot: $(UTIL_SRC)
+       $(ECHO) "  GETTEXT " $@
+       $(QUIET) xgettext --default-domain=$(PACKAGE) --add-comments \
+               --keyword=_ --keyword=N_ $(UTIL_SRC) && \
+       test -f $(PACKAGE).po && \
+       mv -f $(PACKAGE).po po/$(PACKAGE).pot
+
+po/%.gmo: po/%.po
+       $(ECHO) "  MSGFMT  " $@
+       $(QUIET) msgfmt -o $@ po/$*.po
+
+create-gmo: ${GMO_FILES}
+
+update-po: po/$(PACKAGE).pot
+       $(ECHO) "  MSGMRG  " $@
+       $(QUIET) @for HLANG in $(LANGUAGES); do \
+               echo -n "Updating $$HLANG "; \
+               if msgmerge po/$$HLANG.po po/$(PACKAGE).pot -o \
+                  po/$$HLANG.new.po; then \
+                       mv -f po/$$HLANG.new.po po/$$HLANG.po; \
+               else \
+                       echo "msgmerge for $$HLANG failed!"; \
+                       rm -f po/$$HLANG.new.po; \
+               fi; \
+       done;
+
+compile-bench: libcpupower.so.$(LIB_MAJ)
+       @V=$(V) confdir=$(confdir) $(MAKE) -C bench
+
+clean:
+       -find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \
+        | xargs rm -f
+       -rm -f $(UTIL_BINS)
+       -rm -f $(IDLE_OBJS)
+       -rm -f cpupower
+       -rm -f libcpupower.so*
+       -rm -rf po/*.gmo po/*.pot
+       $(MAKE) -C bench clean
+
+
+install-lib:
+       $(INSTALL) -d $(DESTDIR)${libdir}
+       $(CP) libcpupower.so* $(DESTDIR)${libdir}/
+       $(INSTALL) -d $(DESTDIR)${includedir}
+       $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h
+
+install-tools:
+       $(INSTALL) -d $(DESTDIR)${bindir}
+       $(INSTALL_PROGRAM) cpupower $(DESTDIR)${bindir}
+
+install-man:
+       $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1
+       $(INSTALL_DATA) -D man/cpupower-frequency-set.1 $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1
+       $(INSTALL_DATA) -D man/cpupower-frequency-info.1 $(DESTDIR)${mandir}/man1/cpupower-frequency-info.1
+       $(INSTALL_DATA) -D man/cpupower-set.1 $(DESTDIR)${mandir}/man1/cpupower-set.1
+       $(INSTALL_DATA) -D man/cpupower-info.1 $(DESTDIR)${mandir}/man1/cpupower-info.1
+       $(INSTALL_DATA) -D man/cpupower-monitor.1 $(DESTDIR)${mandir}/man1/cpupower-monitor.1
+
+install-gmo:
+       $(INSTALL) -d $(DESTDIR)${localedir}
+       for HLANG in $(LANGUAGES); do \
+               echo '$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo'; \
+               $(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
+       done;
+
+install-bench:
+       @#DESTDIR must be set from outside to survive
+       @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench install
+
+install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH)
+
+uninstall:
+       - rm -f $(DESTDIR)${libdir}/libcpupower.*
+       - rm -f $(DESTDIR)${includedir}/cpufreq.h
+       - rm -f $(DESTDIR)${bindir}/utils/cpupower
+       - rm -f $(DESTDIR)${mandir}/man1/cpufreq-set.1
+       - rm -f $(DESTDIR)${mandir}/man1/cpufreq-info.1
+       - for HLANG in $(LANGUAGES); do \
+               rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
+         done;
+
+.PHONY: all utils libcpupower update-po create-gmo install-lib install-tools install-man install-gmo install uninstall clean
diff --git a/tools/power/cpupower/README b/tools/power/cpupower/README
new file mode 100644 (file)
index 0000000..fd9d4c0
--- /dev/null
@@ -0,0 +1,49 @@
+The cpufrequtils package (homepage: 
+http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufrequtils.html ) 
+consists of the following elements:
+
+requirements
+------------
+
+On x86 pciutils is needed at runtime (-lpci).
+For compilation pciutils-devel (pci/pci.h) and a gcc version
+providing cpuid.h is needed.
+For both it's not explicitly checked for (yet).
+
+
+libcpufreq
+----------
+
+"libcpufreq" is a library which offers a unified access method for userspace
+tools and programs to the cpufreq core and drivers in the Linux kernel. This
+allows for code reduction in userspace tools, a clean implementation of
+the interaction to the cpufreq core, and support for both the sysfs and proc
+interfaces [depending on configuration, see below].
+
+
+compilation and installation
+----------------------------
+
+make
+su
+make install
+
+should suffice on most systems. It builds default libcpufreq,
+cpufreq-set and cpufreq-info files and installs them in /usr/lib and
+/usr/bin, respectively. If you want to set up the paths differently and/or
+want to configure the package to your specific needs, you need to open
+"Makefile" with an editor of your choice and edit the block marked
+CONFIGURATION.
+
+
+THANKS
+------
+Many thanks to Mattia Dongili who wrote the autotoolization and
+libtoolization, the manpages and the italian language file for cpufrequtils;
+to Dave Jones for his feedback and his dump_psb tool; to Bruno Ducrot for his
+powernow-k8-decode and intel_gsic tools as well as the french language file;
+and to various others commenting on the previous (pre-)releases of 
+cpufrequtils.
+
+
+        Dominik Brodowski
diff --git a/tools/power/cpupower/ToDo b/tools/power/cpupower/ToDo
new file mode 100644 (file)
index 0000000..874b78b
--- /dev/null
@@ -0,0 +1,11 @@
+ToDos sorted by priority:
+
+- Use bitmask functions to parse CPU topology more robust
+  (current implementation has issues on AMD)
+- Try to read out boost states and frequencies on Intel
+- Adjust README
+- Somewhere saw the ability to read power consumption of
+  RAM from HW on Intel SandyBridge -> another monitor?
+- Add another c1e debug idle monitor
+  -> Is by design racy with BIOS, but could be added
+     with a --force option and some "be careful" messages
diff --git a/tools/power/cpupower/bench/Makefile b/tools/power/cpupower/bench/Makefile
new file mode 100644 (file)
index 0000000..2b67606
--- /dev/null
@@ -0,0 +1,29 @@
+LIBS = -L../ -lm -lcpupower
+
+OBJS = main.o parse.o system.o benchmark.o
+CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\"
+
+%.o : %.c
+       $(ECHO) "  CC      " $@
+       $(QUIET) $(CC) -c $(CFLAGS) $< -o $@
+
+cpufreq-bench: $(OBJS)
+       $(ECHO) "  CC      " $@
+       $(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS)
+
+all: cpufreq-bench
+
+install:
+       mkdir -p $(DESTDIR)/$(sbindir)
+       mkdir -p $(DESTDIR)/$(bindir)
+       mkdir -p $(DESTDIR)/$(docdir)
+       mkdir -p $(DESTDIR)/$(confdir)
+       install -m 755 cpufreq-bench $(DESTDIR)/$(sbindir)/cpufreq-bench
+       install -m 755 cpufreq-bench_plot.sh $(DESTDIR)/$(bindir)/cpufreq-bench_plot.sh
+       install -m 644 README-BENCH $(DESTDIR)/$(docdir)/README-BENCH
+       install -m 755 cpufreq-bench_script.sh $(DESTDIR)/$(docdir)/cpufreq-bench_script.sh
+       install -m 644 example.cfg $(DESTDIR)/$(confdir)/cpufreq-bench.conf
+
+clean:
+       rm -f *.o
+       rm -f cpufreq-bench
diff --git a/tools/power/cpupower/bench/README-BENCH b/tools/power/cpupower/bench/README-BENCH
new file mode 100644 (file)
index 0000000..8093ec7
--- /dev/null
@@ -0,0 +1,124 @@
+This is cpufreq-bench, a microbenchmark for the cpufreq framework.
+
+Purpose
+=======
+
+What is this benchmark for:
+  - Identify worst case performance loss when doing dynamic frequency
+    scaling using Linux kernel governors
+  - Identify average reaction time of a governor to CPU load changes
+  - (Stress) Testing whether a cpufreq low level driver or governor works
+    as expected
+  - Identify cpufreq related performance regressions between kernels
+  - Possibly Real time priority testing? -> what happens if there are
+    processes with a higher prio than the governor's kernel thread
+  - ...
+
+What this benchmark does *not* cover:
+  - Power saving related regressions (In fact as better the performance
+    throughput is, the worse the power savings will be, but the first should
+    mostly count more...)
+  - Real world (workloads)
+
+
+Description
+===========
+
+cpufreq-bench helps to test the condition of a given cpufreq governor.
+For that purpose, it compares the performance governor to a configured
+powersave module.
+
+
+How it works
+============
+You can specify load (100% CPU load) and sleep (0% CPU load) times in us which
+will be run X time in a row (cycles):
+
+         sleep=25000
+         load=25000
+         cycles=20
+
+This part of the configuration file will create 25ms load/sleep turns,
+repeated 20 times.
+
+Adding this:
+         sleep_step=25000
+         load_step=25000
+         rounds=5
+Will increase load and sleep time by 25ms 5 times.
+Together you get following test:
+25ms  load/sleep time repeated 20 times (cycles).
+50ms  load/sleep time repeated 20 times (cycles).
+..
+100ms load/sleep time repeated 20 times (cycles).
+
+First it is calibrated how long a specific CPU intensive calculation
+takes on this machine and needs to be run in a loop using the performance
+governor.
+Then the above test runs are processed using the performance governor
+and the governor to test. The time the calculation really needed
+with the dynamic freq scaling governor is compared with the time needed
+on full performance and you get the overall performance loss.
+
+
+Example of expected results with ondemand governor:
+
+This shows expected results of the first two test run rounds from
+above config, you there have:
+
+100% CPU load (load) | 0 % CPU load (sleep)  | round
+   25 ms             |    25 ms              |   1
+   50 ms             |    50 ms              |   2
+
+For example if ondemand governor is configured to have a 50ms
+sampling rate you get:
+
+In round 1, ondemand should have rather static 50% load and probably
+won't ever switch up (as long as up_threshold is above).
+
+In round 2, if the ondemand sampling times exactly match the load/sleep
+trigger of the cpufreq-bench, you will see no performance loss (compare with
+below possible ondemand sample kick ins (1)):
+
+But if ondemand always kicks in in the middle of the load sleep cycles, it
+will always see 50% loads and you get worst performance impact never
+switching up (compare with below possible ondemand sample kick ins (2))::
+
+      50     50   50   50ms ->time
+load -----|     |-----|     |-----|     |-----|
+          |     |     |     |     |     |     |
+sleep     |-----|     |-----|     |-----|     |----
+    |-----|-----|-----|-----|-----|-----|-----|----  ondemand sampling (1)
+         100    0    100    0    100    0    100     load seen by ondemand(%)
+       |-----|-----|-----|-----|-----|-----|-----|--   ondemand sampling (2)
+      50     50    50    50    50    50    50        load seen by ondemand(%)
+
+You can easily test all kind of load/sleep times and check whether your
+governor in average behaves as expected.
+
+
+ToDo
+====
+
+Provide a gnuplot utility script for easy generation of plots to present
+the outcome nicely.
+
+
+cpufreq-bench Command Usage
+===========================
+-l, --load=<long int>           initial load time in us
+-s, --sleep=<long int>          initial sleep time in us
+-x, --load-step=<long int>      time to be added to load time, in us
+-y, --sleep-step=<long int>     time to be added to sleep time, in us
+-c, --cpu=<unsigned int>        CPU Number to use, starting at 0
+-p, --prio=<priority>           scheduler priority, HIGH, LOW or DEFAULT
+-g, --governor=<governor>       cpufreq governor to test
+-n, --cycles=<int>              load/sleep cycles to get an avarage value to compare
+-r, --rounds<int>               load/sleep rounds
+-f, --file=<configfile>         config file to use
+-o, --output=<dir>              output dir, must exist
+-v, --verbose                   verbose output on/off
+
+Due to the high priority, the application may not be responsible for some time.
+After the benchmark, the logfile is saved in OUTPUTDIR/benchmark_TIMESTAMP.log
+
diff --git a/tools/power/cpupower/bench/benchmark.c b/tools/power/cpupower/bench/benchmark.c
new file mode 100644 (file)
index 0000000..81b1c48
--- /dev/null
@@ -0,0 +1,194 @@
+/*  cpufreq-bench CPUFreq microbenchmark
+ *
+ *  Copyright (C) 2008 Christian Kornacker <ckornacker@suse.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "config.h"
+#include "system.h"
+#include "benchmark.h"
+
+/* Print out progress if we log into a file */
+#define show_progress(total_time, progress_time)       \
+if (config->output != stdout) {                                \
+       fprintf(stdout, "Progress: %02lu %%\r",         \
+               (progress_time * 100) / total_time);    \
+       fflush(stdout);                                 \
+}
+
+/**
+ * compute how many rounds of calculation we should do
+ * to get the given load time
+ *
+ * @param load aimed load time in µs
+ *
+ * @retval rounds of calculation
+ **/
+
+unsigned int calculate_timespace(long load, struct config *config)
+{
+       int i;
+       long long now, then;
+       unsigned int estimated = GAUGECOUNT;
+       unsigned int rounds = 0;
+       unsigned int timed = 0;
+
+       if (config->verbose)
+               printf("calibrating load of %lius, please wait...\n", load);
+
+       /* get the initial calculation time for a specific number of rounds */
+       now = get_time();
+       ROUNDS(estimated);
+       then = get_time();
+
+       timed = (unsigned int)(then - now);
+
+       /* approximation of the wanted load time by comparing with the
+        * initial calculation time */
+       for (i = 0; i < 4; i++) {
+               rounds = (unsigned int)(load * estimated / timed);
+               dprintf("calibrating with %u rounds\n", rounds);
+               now = get_time();
+               ROUNDS(rounds);
+               then = get_time();
+
+               timed = (unsigned int)(then - now);
+               estimated = rounds;
+       }
+       if (config->verbose)
+               printf("calibration done\n");
+
+       return estimated;
+}
+
+/**
+ * benchmark
+ * generates a specific sleep an load time with the performance
+ * governor and compares the used time for same calculations done
+ * with the configured powersave governor
+ *
+ * @param config config values for the benchmark
+ *
+ **/
+
+void start_benchmark(struct config *config)
+{
+       unsigned int _round, cycle;
+       long long now, then;
+       long sleep_time = 0, load_time = 0;
+       long performance_time = 0, powersave_time = 0;
+       unsigned int calculations;
+       unsigned long total_time = 0, progress_time = 0;
+
+       sleep_time = config->sleep;
+       load_time = config->load;
+
+       /* For the progress bar */
+       for (_round = 1; _round <= config->rounds; _round++)
+               total_time += _round * (config->sleep + config->load);
+       total_time *= 2; /* powersave and performance cycles */
+
+       for (_round = 0; _round < config->rounds; _round++) {
+               performance_time = 0LL;
+               powersave_time = 0LL;
+
+               show_progress(total_time, progress_time);
+
+               /* set the cpufreq governor to "performance" which disables
+                * P-State switching. */
+               if (set_cpufreq_governor("performance", config->cpu) != 0)
+                       return;
+
+               /* calibrate the calculation time. the resulting calculation
+                * _rounds should produce a load which matches the configured
+                * load time */
+               calculations = calculate_timespace(load_time, config);
+
+               if (config->verbose)
+                       printf("_round %i: doing %u cycles with %u calculations"
+                              " for %lius\n", _round + 1, config->cycles,
+                              calculations, load_time);
+
+               fprintf(config->output, "%u %li %li ",
+                       _round, load_time, sleep_time);
+
+               if (config->verbose)
+                       printf("avarage: %lius, rps:%li\n",
+                               load_time / calculations,
+                               1000000 * calculations / load_time);
+
+               /* do some sleep/load cycles with the performance governor */
+               for (cycle = 0; cycle < config->cycles; cycle++) {
+                       now = get_time();
+                       usleep(sleep_time);
+                       ROUNDS(calculations);
+                       then = get_time();
+                       performance_time += then - now - sleep_time;
+                       if (config->verbose)
+                               printf("performance cycle took %lius, "
+                                       "sleep: %lius, "
+                                       "load: %lius, rounds: %u\n",
+                                       (long)(then - now), sleep_time,
+                                       load_time, calculations);
+               }
+               fprintf(config->output, "%li ",
+                       performance_time / config->cycles);
+
+               progress_time += sleep_time + load_time;
+               show_progress(total_time, progress_time);
+
+               /* set the powersave governor which activates P-State switching
+                * again */
+               if (set_cpufreq_governor(config->governor, config->cpu) != 0)
+                       return;
+
+               /* again, do some sleep/load cycles with the
+                * powersave governor */
+               for (cycle = 0; cycle < config->cycles; cycle++) {
+                       now = get_time();
+                       usleep(sleep_time);
+                       ROUNDS(calculations);
+                       then = get_time();
+                       powersave_time += then - now - sleep_time;
+                       if (config->verbose)
+                               printf("powersave cycle took %lius, "
+                                       "sleep: %lius, "
+                                       "load: %lius, rounds: %u\n",
+                                       (long)(then - now), sleep_time,
+                                       load_time, calculations);
+               }
+
+               progress_time += sleep_time + load_time;
+
+               /* compare the avarage sleep/load cycles  */
+               fprintf(config->output, "%li ",
+                       powersave_time / config->cycles);
+               fprintf(config->output, "%.3f\n",
+                       performance_time * 100.0 / powersave_time);
+               fflush(config->output);
+
+               if (config->verbose)
+                       printf("performance is at %.2f%%\n",
+                               performance_time * 100.0 / powersave_time);
+
+               sleep_time += config->sleep_step;
+               load_time += config->load_step;
+       }
+}
diff --git a/tools/power/cpupower/bench/benchmark.h b/tools/power/cpupower/bench/benchmark.h
new file mode 100644 (file)
index 0000000..51d7f50
--- /dev/null
@@ -0,0 +1,29 @@
+/*  cpufreq-bench CPUFreq microbenchmark
+ *
+ *  Copyright (C) 2008 Christian Kornacker <ckornacker@suse.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* load loop, this schould take about 1 to 2ms to complete */
+#define ROUNDS(x) {unsigned int rcnt;                         \
+               for (rcnt = 0; rcnt < x*1000; rcnt++) { \
+                       (void)(((int)(pow(rcnt, rcnt) * \
+                                     sqrt(rcnt*7230970)) ^ 7230716) ^ \
+                                     (int)atan2(rcnt, rcnt));         \
+               } }                                                     \
+
+
+void start_benchmark(struct config *config);
diff --git a/tools/power/cpupower/bench/config.h b/tools/power/cpupower/bench/config.h
new file mode 100644 (file)
index 0000000..ee6f258
--- /dev/null
@@ -0,0 +1,36 @@
+/*  cpufreq-bench CPUFreq microbenchmark
+ *
+ *  Copyright (C) 2008 Christian Kornacker <ckornacker@suse.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* initial loop count for the load calibration */
+#define GAUGECOUNT     1500
+
+/* default scheduling policy SCHED_OTHER */
+#define SCHEDULER      SCHED_OTHER
+
+#define PRIORITY_DEFAULT 0
+#define PRIORITY_HIGH   sched_get_priority_max(SCHEDULER)
+#define PRIORITY_LOW    sched_get_priority_min(SCHEDULER)
+
+/* enable further debug messages */
+#ifdef DEBUG
+#define dprintf printf
+#else
+#define dprintf(...) do { } while (0)
+#endif
+
diff --git a/tools/power/cpupower/bench/cpufreq-bench_plot.sh b/tools/power/cpupower/bench/cpufreq-bench_plot.sh
new file mode 100644 (file)
index 0000000..410021a
--- /dev/null
@@ -0,0 +1,104 @@
+#!/bin/bash
+
+# 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, 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.
+
+# Author/Copyright(c): 2009, Thomas Renninger <trenn@suse.de>, Novell Inc.
+
+# Helper script to easily create nice plots of your cpufreq-bench results
+
+dir=`mktemp -d`
+output_file="cpufreq-bench.png"
+global_title="cpufreq-bench plot"
+picture_type="jpeg"
+file[0]=""
+
+function usage()
+{
+    echo "cpufreq-bench_plot.sh [OPTIONS] logfile [measure_title] [logfile [measure_title]] ...]"
+    echo
+    echo "Options"
+    echo "   -o output_file"
+    echo "   -t global_title"
+    echo "   -p picture_type [jpeg|gif|png|postscript|...]"
+    exit 1
+}
+
+if [ $# -eq 0 ];then
+       echo "No benchmark results file provided"
+       echo
+       usage
+fi
+
+while getopts o:t:p: name ; do
+    case $name in
+       o)
+           output_file="$OPTARG".$picture_type
+           ;;
+       t)
+           global_title="$OPTARG"
+           ;;
+       p)
+           picture_type="$OPTARG"
+           ;;
+        ?)
+           usage
+           ;;
+    esac
+done
+shift $(($OPTIND -1))
+
+plots=0
+while [ "$1" ];do
+    if [ ! -f "$1" ];then
+       echo "File $1 does not exist"
+       usage
+    fi
+    file[$plots]="$1"
+    title[$plots]="$2"
+    # echo "File: ${file[$plots]} - ${title[plots]}"
+    shift;shift
+    plots=$((plots + 1))
+done
+
+echo "set terminal $picture_type"      >> $dir/plot_script.gpl
+echo "set output \"$output_file\""     >> $dir/plot_script.gpl
+echo "set title \"$global_title\""     >> $dir/plot_script.gpl
+echo "set xlabel \"sleep/load time\""  >> $dir/plot_script.gpl
+echo "set ylabel \"Performance (%)\""  >> $dir/plot_script.gpl
+
+for((plot=0;plot<$plots;plot++));do
+
+    # Sanity check
+    ###### I am to dump to get this redirected to stderr/stdout in one awk call... #####
+    cat ${file[$plot]} |grep -v "^#" |awk '{if ($2 != $3) printf("Error in measure %d:Load time %s does not equal sleep time %s, plot will not be correct\n", $1, $2, $3); ERR=1}'
+    ###### I am to dump to get this redirected in one awk call... #####
+
+    # Parse out load time (which must be equal to sleep time for a plot), divide it by 1000
+    # to get ms and parse out the performance in percentage and write it to a temp file for plotting
+    cat ${file[$plot]} |grep -v "^#" |awk '{printf "%lu %.1f\n",$2/1000, $6}' >$dir/data_$plot
+
+    if [ $plot -eq 0 ];then
+       echo -n "plot " >> $dir/plot_script.gpl
+    fi
+    echo -n "\"$dir/data_$plot\" title \"${title[$plot]}\" with lines" >> $dir/plot_script.gpl
+    if [ $(($plot + 1)) -ne $plots ];then
+       echo -n ", " >> $dir/plot_script.gpl
+    fi
+done
+echo >> $dir/plot_script.gpl
+
+gnuplot $dir/plot_script.gpl
+rm -r $dir
\ No newline at end of file
diff --git a/tools/power/cpupower/bench/cpufreq-bench_script.sh b/tools/power/cpupower/bench/cpufreq-bench_script.sh
new file mode 100644 (file)
index 0000000..de20d2a
--- /dev/null
@@ -0,0 +1,101 @@
+#!/bin/bash
+
+# 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, 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.
+
+# Author/Copyright(c): 2009, Thomas Renninger <trenn@suse.de>, Novell Inc.
+
+# Ondemand up_threshold and sampling rate test script for cpufreq-bench
+# mircobenchmark.
+# Modify the general variables at the top or extend or copy out parts
+# if you want to test other things
+#
+
+# Default with latest kernels is 95, before micro account patches
+# it was 80, cmp. with git commit 808009131046b62ac434dbc796
+UP_THRESHOLD="60 80 95"
+# Depending on the kernel and the HW sampling rate could be restricted
+# and cannot be set that low...
+# E.g. before git commit cef9615a853ebc4972084f7 one could only set
+# min sampling rate of 80000 if CONFIG_HZ=250
+SAMPLING_RATE="20000 80000"
+
+function measure()
+{
+    local -i up_threshold_set
+    local -i sampling_rate_set
+
+    for up_threshold in $UP_THRESHOLD;do
+       for sampling_rate in $SAMPLING_RATE;do
+           # Set values in sysfs
+           echo $up_threshold >/sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold
+           echo $sampling_rate >/sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate
+           up_threshold_set=$(cat /sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold)
+           sampling_rate_set=$(cat /sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate)
+
+           # Verify set values in sysfs
+           if [ ${up_threshold_set} -eq ${up_threshold} ];then
+               echo "up_threshold: $up_threshold, set in sysfs: ${up_threshold_set}"
+           else
+               echo "WARNING: Tried to set up_threshold: $up_threshold, set in sysfs: ${up_threshold_set}"
+           fi
+           if [ ${sampling_rate_set} -eq ${sampling_rate} ];then
+               echo "sampling_rate: $sampling_rate, set in sysfs: ${sampling_rate_set}"
+           else
+               echo "WARNING: Tried to set sampling_rate: $sampling_rate, set in sysfs: ${sampling_rate_set}"
+           fi
+
+           # Benchmark
+           cpufreq-bench -o /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}
+       done
+    done
+}
+
+function create_plots()
+{
+    local command
+
+    for up_threshold in $UP_THRESHOLD;do
+       command="cpufreq-bench_plot.sh -o \"sampling_rate_${SAMPLING_RATE}_up_threshold_${up_threshold}\" -t \"Ondemand sampling_rate: ${SAMPLING_RATE} comparison - Up_threshold: $up_threshold %\""
+       for sampling_rate in $SAMPLING_RATE;do
+           command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"sampling_rate = $sampling_rate\""
+       done
+       echo $command
+       eval "$command"
+       echo
+    done
+
+    for sampling_rate in $SAMPLING_RATE;do
+       command="cpufreq-bench_plot.sh -o \"up_threshold_${UP_THRESHOLD}_sampling_rate_${sampling_rate}\" -t \"Ondemand up_threshold: ${UP_THRESHOLD} % comparison - sampling_rate: $sampling_rate\""
+       for up_threshold in $UP_THRESHOLD;do
+           command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"up_threshold = $up_threshold\""
+       done
+       echo $command
+       eval "$command"
+       echo
+    done
+
+    command="cpufreq-bench_plot.sh -o \"up_threshold_${UP_THRESHOLD}_sampling_rate_${SAMPLING_RATE}\" -t \"Ondemand up_threshold: ${UP_THRESHOLD} and sampling_rate ${SAMPLING_RATE} comparison\""
+    for sampling_rate in $SAMPLING_RATE;do
+       for up_threshold in $UP_THRESHOLD;do
+           command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"up_threshold = $up_threshold - sampling_rate = $sampling_rate\""
+       done
+    done
+    echo "$command"
+    eval "$command"
+}
+
+measure
+create_plots
\ No newline at end of file
diff --git a/tools/power/cpupower/bench/example.cfg b/tools/power/cpupower/bench/example.cfg
new file mode 100644 (file)
index 0000000..f91f643
--- /dev/null
@@ -0,0 +1,11 @@
+sleep = 50000
+load = 50000
+cpu = 0
+priority = LOW
+output = /var/log/cpufreq-bench
+sleep_step = 50000
+load_step = 50000
+cycles = 20
+rounds = 40
+verbose = 0
+governor = ondemand
diff --git a/tools/power/cpupower/bench/main.c b/tools/power/cpupower/bench/main.c
new file mode 100644 (file)
index 0000000..2491031
--- /dev/null
@@ -0,0 +1,202 @@
+/*  cpufreq-bench CPUFreq microbenchmark
+ *
+ *  Copyright (C) 2008 Christian Kornacker <ckornacker@suse.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include "config.h"
+#include "system.h"
+#include "benchmark.h"
+
+static struct option long_options[] = {
+       {"output",      1,      0,      'o'},
+       {"sleep",       1,      0,      's'},
+       {"load",        1,      0,      'l'},
+       {"verbose",     0,      0,      'v'},
+       {"cpu",         1,      0,      'c'},
+       {"governor",    1,      0,      'g'},
+       {"prio",        1,      0,      'p'},
+       {"file",        1,      0,      'f'},
+       {"cycles",      1,      0,      'n'},
+       {"rounds",      1,      0,      'r'},
+       {"load-step",   1,      0,      'x'},
+       {"sleep-step",  1,      0,      'y'},
+       {"help",        0,      0,      'h'},
+       {0, 0, 0, 0}
+};
+
+/*******************************************************************
+ usage
+*******************************************************************/
+
+void usage()
+{
+       printf("usage: ./bench\n");
+       printf("Options:\n");
+       printf(" -l, --load=<long int>\t\tinitial load time in us\n");
+       printf(" -s, --sleep=<long int>\t\tinitial sleep time in us\n");
+       printf(" -x, --load-step=<long int>\ttime to be added to load time, in us\n");
+       printf(" -y, --sleep-step=<long int>\ttime to be added to sleep time, in us\n");
+       printf(" -c, --cpu=<cpu #>\t\t\tCPU Nr. to use, starting at 0\n");
+       printf(" -p, --prio=<priority>\t\t\tscheduler priority, HIGH, LOW or DEFAULT\n");
+       printf(" -g, --governor=<governor>\t\tcpufreq governor to test\n");
+       printf(" -n, --cycles=<int>\t\t\tload/sleep cycles\n");
+       printf(" -r, --rounds<int>\t\t\tload/sleep rounds\n");
+       printf(" -f, --file=<configfile>\t\tconfig file to use\n");
+       printf(" -o, --output=<dir>\t\t\toutput path. Filename will be OUTPUTPATH/benchmark_TIMESTAMP.log\n");
+       printf(" -v, --verbose\t\t\t\tverbose output on/off\n");
+       printf(" -h, --help\t\t\t\tPrint this help screen\n");
+       exit(1);
+}
+
+/*******************************************************************
+ main
+*******************************************************************/
+
+int main(int argc, char **argv)
+{
+       int c;
+       int option_index = 0;
+       struct config *config = NULL;
+
+       config = prepare_default_config();
+
+       if (config == NULL)
+               return EXIT_FAILURE;
+
+       while (1) {
+               c = getopt_long (argc, argv, "hg:o:s:l:vc:p:f:n:r:x:y:",
+                               long_options, &option_index);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+               case 'o':
+                       if (config->output != NULL)
+                               fclose(config->output);
+
+                       config->output = prepare_output(optarg);
+
+                       if (config->output == NULL)
+                               return EXIT_FAILURE;
+
+                       dprintf("user output path -> %s\n", optarg);
+                       break;
+               case 's':
+                       sscanf(optarg, "%li", &config->sleep);
+                       dprintf("user sleep time -> %s\n", optarg);
+                       break;
+               case 'l':
+                       sscanf(optarg, "%li", &config->load);
+                       dprintf("user load time -> %s\n", optarg);
+                       break;
+               case 'c':
+                       sscanf(optarg, "%u", &config->cpu);
+                       dprintf("user cpu -> %s\n", optarg);
+                       break;
+               case 'g':
+                       strncpy(config->governor, optarg, 14);
+                       dprintf("user governor -> %s\n", optarg);
+                       break;
+               case 'p':
+                       if (string_to_prio(optarg) != SCHED_ERR) {
+                               config->prio = string_to_prio(optarg);
+                               dprintf("user prio -> %s\n", optarg);
+                       } else {
+                               if (config != NULL) {
+                                       if (config->output != NULL)
+                                               fclose(config->output);
+                                       free(config);
+                               }
+                               usage();
+                       }
+                       break;
+               case 'n':
+                       sscanf(optarg, "%u", &config->cycles);
+                       dprintf("user cycles -> %s\n", optarg);
+                       break;
+               case 'r':
+                       sscanf(optarg, "%u", &config->rounds);
+                       dprintf("user rounds -> %s\n", optarg);
+                       break;
+               case 'x':
+                       sscanf(optarg, "%li", &config->load_step);
+                       dprintf("user load_step -> %s\n", optarg);
+                       break;
+               case 'y':
+                       sscanf(optarg, "%li", &config->sleep_step);
+                       dprintf("user sleep_step -> %s\n", optarg);
+                       break;
+               case 'f':
+                       if (prepare_config(optarg, config))
+                               return EXIT_FAILURE;
+                       break;
+               case 'v':
+                       config->verbose = 1;
+                       dprintf("verbose output enabled\n");
+                       break;
+               case 'h':
+               case '?':
+               default:
+                       if (config != NULL) {
+                               if (config->output != NULL)
+                                       fclose(config->output);
+                               free(config);
+                       }
+                       usage();
+               }
+       }
+
+       if (config->verbose) {
+               printf("starting benchmark with parameters:\n");
+               printf("config:\n\t"
+                      "sleep=%li\n\t"
+                      "load=%li\n\t"
+                      "sleep_step=%li\n\t"
+                      "load_step=%li\n\t"
+                      "cpu=%u\n\t"
+                      "cycles=%u\n\t"
+                      "rounds=%u\n\t"
+                      "governor=%s\n\n",
+                      config->sleep,
+                      config->load,
+                      config->sleep_step,
+                      config->load_step,
+                      config->cpu,
+                      config->cycles,
+                      config->rounds,
+                      config->governor);
+       }
+
+       prepare_user(config);
+       prepare_system(config);
+       start_benchmark(config);
+
+       if (config->output != stdout)
+               fclose(config->output);
+
+       free(config);
+
+       return EXIT_SUCCESS;
+}
+
diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c
new file mode 100644 (file)
index 0000000..543bba1
--- /dev/null
@@ -0,0 +1,225 @@
+/*  cpufreq-bench CPUFreq microbenchmark
+ *
+ *  Copyright (C) 2008 Christian Kornacker <ckornacker@suse.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#include <dirent.h>
+
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "parse.h"
+#include "config.h"
+
+/**
+ * converts priority string to priority
+ *
+ * @param str string that represents a scheduler priority
+ *
+ * @retval priority
+ * @retval SCHED_ERR when the priority doesn't exit
+ **/
+
+enum sched_prio string_to_prio(const char *str)
+{
+       if (strncasecmp("high", str, strlen(str)) == 0)
+               return  SCHED_HIGH;
+       else if (strncasecmp("default", str, strlen(str)) == 0)
+               return SCHED_DEFAULT;
+       else if (strncasecmp("low", str, strlen(str)) == 0)
+               return SCHED_LOW;
+       else
+               return SCHED_ERR;
+}
+
+/**
+ * create and open logfile
+ *
+ * @param dir directory in which the logfile should be created
+ *
+ * @retval logfile on success
+ * @retval NULL when the file can't be created
+ **/
+
+FILE *prepare_output(const char *dirname)
+{
+       FILE *output = NULL;
+       int len;
+       char *filename;
+       struct utsname sysdata;
+       DIR *dir;
+
+       dir = opendir(dirname);
+       if (dir == NULL) {
+               if (mkdir(dirname, 0755)) {
+                       perror("mkdir");
+                       fprintf(stderr, "error: Cannot create dir %s\n",
+                               dirname);
+                       return NULL;
+               }
+       }
+
+       len = strlen(dirname) + 30;
+       filename = malloc(sizeof(char) * len);
+
+       if (uname(&sysdata) == 0) {
+               len += strlen(sysdata.nodename) + strlen(sysdata.release);
+               filename = realloc(filename, sizeof(char) * len);
+
+               if (filename == NULL) {
+                       perror("realloc");
+                       return NULL;
+               }
+
+               snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log",
+                       dirname, sysdata.nodename, sysdata.release, time(NULL));
+       } else {
+               snprintf(filename, len - 1, "%s/benchmark_%li.log",
+                       dirname, time(NULL));
+       }
+
+       dprintf("logilename: %s\n", filename);
+
+       output = fopen(filename, "w+");
+       if (output == NULL) {
+               perror("fopen");
+               fprintf(stderr, "error: unable to open logfile\n");
+       }
+
+       fprintf(stdout, "Logfile: %s\n", filename);
+
+       free(filename);
+       fprintf(output, "#round load sleep performance powersave percentage\n");
+       return output;
+}
+
+/**
+ * returns the default config
+ *
+ * @retval default config on success
+ * @retval NULL when the output file can't be created
+ **/
+
+struct config *prepare_default_config()
+{
+       struct config *config = malloc(sizeof(struct config));
+
+       dprintf("loading defaults\n");
+
+       config->sleep = 500000;
+       config->load = 500000;
+       config->sleep_step = 500000;
+       config->load_step = 500000;
+       config->cycles = 5;
+       config->rounds = 50;
+       config->cpu = 0;
+       config->prio = SCHED_HIGH;
+       config->verbose = 0;
+       strncpy(config->governor, "ondemand", 8);
+
+       config->output = stdout;
+
+#ifdef DEFAULT_CONFIG_FILE
+       if (prepare_config(DEFAULT_CONFIG_FILE, config))
+               return NULL;
+#endif
+       return config;
+}
+
+/**
+ * parses config file and returns the config to the caller
+ *
+ * @param path config file name
+ *
+ * @retval 1 on error
+ * @retval 0 on success
+ **/
+
+int prepare_config(const char *path, struct config *config)
+{
+       size_t len = 0;
+       char *opt, *val, *line = NULL;
+       FILE *configfile = fopen(path, "r");
+
+       if (config == NULL) {
+               fprintf(stderr, "error: config is NULL\n");
+               return 1;
+       }
+
+       if (configfile == NULL) {
+               perror("fopen");
+               fprintf(stderr, "error: unable to read configfile\n");
+               free(config);
+               return 1;
+       }
+
+       while (getline(&line, &len, configfile) != -1) {
+               if (line[0] == '#' || line[0] == ' ')
+                       continue;
+
+               sscanf(line, "%as = %as", &opt, &val);
+
+               dprintf("parsing: %s -> %s\n", opt, val);
+
+               if (strncmp("sleep", opt, strlen(opt)) == 0)
+                       sscanf(val, "%li", &config->sleep);
+
+               else if (strncmp("load", opt, strlen(opt)) == 0)
+                       sscanf(val, "%li", &config->load);
+
+               else if (strncmp("load_step", opt, strlen(opt)) == 0)
+                       sscanf(val, "%li", &config->load_step);
+
+               else if (strncmp("sleep_step", opt, strlen(opt)) == 0)
+                       sscanf(val, "%li", &config->sleep_step);
+
+               else if (strncmp("cycles", opt, strlen(opt)) == 0)
+                       sscanf(val, "%u", &config->cycles);
+
+               else if (strncmp("rounds", opt, strlen(opt)) == 0)
+                       sscanf(val, "%u", &config->rounds);
+
+               else if (strncmp("verbose", opt, strlen(opt)) == 0)
+                       sscanf(val, "%u", &config->verbose);
+
+               else if (strncmp("output", opt, strlen(opt)) == 0)
+                       config->output = prepare_output(val); 
+
+               else if (strncmp("cpu", opt, strlen(opt)) == 0)
+                       sscanf(val, "%u", &config->cpu);
+
+               else if (strncmp("governor", opt, 14) == 0)
+                       strncpy(config->governor, val, 14);
+
+               else if (strncmp("priority", opt, strlen(opt)) == 0) {
+                       if (string_to_prio(val) != SCHED_ERR)
+                               config->prio = string_to_prio(val);
+               }
+       }
+
+       free(line);
+       free(opt);
+       free(val);
+
+       return 0;
+}
diff --git a/tools/power/cpupower/bench/parse.h b/tools/power/cpupower/bench/parse.h
new file mode 100644 (file)
index 0000000..a8dc632
--- /dev/null
@@ -0,0 +1,53 @@
+/*  cpufreq-bench CPUFreq microbenchmark
+ *
+ *  Copyright (C) 2008 Christian Kornacker <ckornacker@suse.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* struct that holds the required config parameters */
+struct config
+{
+       long sleep;             /* sleep time in µs */
+       long load;              /* load time in µs */
+       long sleep_step;        /* time value which changes the
+                                * sleep time after every round in µs */
+       long load_step;         /* time value which changes the
+                                * load time after every round in µs */
+       unsigned int cycles;    /* calculation cycles with the same sleep/load time */
+       unsigned int rounds;    /* calculation rounds with iterated sleep/load time */
+       unsigned int cpu;       /* cpu for which the affinity is set */
+       char governor[15];      /* cpufreq governor */
+       enum sched_prio         /* possible scheduler priorities */
+       {
+               SCHED_ERR = -1,
+               SCHED_HIGH,
+               SCHED_DEFAULT,
+               SCHED_LOW
+       } prio;
+
+       unsigned int verbose;   /* verbose output */
+       FILE *output;           /* logfile */
+       char *output_filename;  /* logfile name, must be freed at the end
+                                  if output != NULL and output != stdout*/
+};
+
+enum sched_prio string_to_prio(const char *str);
+
+FILE *prepare_output(const char *dir);
+
+int prepare_config(const char *path, struct config *config);
+struct config *prepare_default_config();
+
diff --git a/tools/power/cpupower/bench/system.c b/tools/power/cpupower/bench/system.c
new file mode 100644 (file)
index 0000000..f01e3f4
--- /dev/null
@@ -0,0 +1,191 @@
+/*  cpufreq-bench CPUFreq microbenchmark
+ *
+ *  Copyright (C) 2008 Christian Kornacker <ckornacker@suse.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <sched.h>
+
+#include <cpufreq.h>
+
+#include "config.h"
+#include "system.h"
+
+/**
+ * returns time since epoch in µs
+ *
+ * @retval time
+ **/
+
+long long int get_time()
+{
+       struct timeval now;
+
+       gettimeofday(&now, NULL);
+
+       return (long long int)(now.tv_sec * 1000000LL + now.tv_usec);
+}
+
+/**
+ * sets the cpufreq governor
+ *
+ * @param governor cpufreq governor name
+ * @param cpu cpu for which the governor should be set
+ *
+ * @retval 0 on success
+ * @retval -1 when failed
+ **/
+
+int set_cpufreq_governor(char *governor, unsigned int cpu)
+{
+
+       dprintf("set %s as cpufreq governor\n", governor);
+
+       if (cpufreq_cpu_exists(cpu) != 0) {
+               perror("cpufreq_cpu_exists");
+               fprintf(stderr, "error: cpu %u does not exist\n", cpu);
+               return -1;
+       }
+
+       if (cpufreq_modify_policy_governor(cpu, governor) != 0) {
+               perror("cpufreq_modify_policy_governor");
+               fprintf(stderr, "error: unable to set %s governor\n", governor);
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * sets cpu affinity for the process
+ *
+ * @param cpu cpu# to which the affinity should be set
+ *
+ * @retval 0 on success
+ * @retval -1 when setting the affinity failed
+ **/
+
+int set_cpu_affinity(unsigned int cpu)
+{
+       cpu_set_t cpuset;
+
+       CPU_ZERO(&cpuset);
+       CPU_SET(cpu, &cpuset);
+
+       dprintf("set affinity to cpu #%u\n", cpu);
+
+       if (sched_setaffinity(getpid(), sizeof(cpu_set_t), &cpuset) < 0) {
+               perror("sched_setaffinity");
+               fprintf(stderr, "warning: unable to set cpu affinity\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * sets the process priority parameter
+ *
+ * @param priority priority value
+ *
+ * @retval 0 on success
+ * @retval -1 when setting the priority failed
+ **/
+
+int set_process_priority(int priority)
+{
+       struct sched_param param;
+
+       dprintf("set scheduler priority to %i\n", priority);
+
+       param.sched_priority = priority;
+
+       if (sched_setscheduler(0, SCHEDULER, &param) < 0) {
+               perror("sched_setscheduler");
+               fprintf(stderr, "warning: unable to set scheduler priority\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * notifies the user that the benchmark may run some time
+ *
+ * @param config benchmark config values
+ *
+ **/
+
+void prepare_user(const struct config *config)
+{
+       unsigned long sleep_time = 0;
+       unsigned long load_time = 0;
+       unsigned int round;
+
+       for (round = 0; round < config->rounds; round++) {
+               sleep_time +=  2 * config->cycles *
+                       (config->sleep + config->sleep_step * round);
+               load_time += 2 * config->cycles *
+                       (config->load + config->load_step * round) +
+                       (config->load + config->load_step * round * 4);
+       }
+
+       if (config->verbose || config->output != stdout)
+               printf("approx. test duration: %im\n",
+                      (int)((sleep_time + load_time) / 60000000));
+}
+
+/**
+ * sets up the cpu affinity and scheduler priority
+ *
+ * @param config benchmark config values
+ *
+ **/
+
+void prepare_system(const struct config *config)
+{
+       if (config->verbose)
+               printf("set cpu affinity to cpu #%u\n", config->cpu);
+
+       set_cpu_affinity(config->cpu);
+
+       switch (config->prio) {
+       case SCHED_HIGH:
+               if (config->verbose)
+                       printf("high priority condition requested\n");
+
+               set_process_priority(PRIORITY_HIGH);
+               break;
+       case SCHED_LOW:
+               if (config->verbose)
+                       printf("low priority condition requested\n");
+
+               set_process_priority(PRIORITY_LOW);
+               break;
+       default:
+               if (config->verbose)
+                       printf("default priority condition requested\n");
+
+               set_process_priority(PRIORITY_DEFAULT);
+       }
+}
+
diff --git a/tools/power/cpupower/bench/system.h b/tools/power/cpupower/bench/system.h
new file mode 100644 (file)
index 0000000..3a8c858
--- /dev/null
@@ -0,0 +1,29 @@
+/*  cpufreq-bench CPUFreq microbenchmark
+ *
+ *  Copyright (C) 2008 Christian Kornacker <ckornacker@suse.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "parse.h"
+
+long long get_time();
+
+int set_cpufreq_governor(char *governor, unsigned int cpu);
+int set_cpu_affinity(unsigned int cpu);
+int set_process_priority(int priority);
+
+void prepare_user(const struct config *config);
+void prepare_system(const struct config *config);
diff --git a/tools/power/cpupower/debug/i386/Makefile b/tools/power/cpupower/debug/i386/Makefile
new file mode 100644 (file)
index 0000000..d08cc1e
--- /dev/null
@@ -0,0 +1,20 @@
+default: all
+
+centrino-decode: centrino-decode.c
+       $(CC) $(CFLAGS) -o centrino-decode centrino-decode.c
+
+dump_psb: dump_psb.c
+       $(CC) $(CFLAGS) -o dump_psb dump_psb.c
+
+intel_gsic: intel_gsic.c
+       $(CC) $(CFLAGS) -o intel_gsic -llrmi intel_gsic.c
+
+powernow-k8-decode: powernow-k8-decode.c
+       $(CC) $(CFLAGS) -o powernow-k8-decode powernow-k8-decode.c
+
+all: centrino-decode dump_psb intel_gsic powernow-k8-decode
+
+clean:
+       rm -rf centrino-decode dump_psb intel_gsic powernow-k8-decode
+
+.PHONY: all default clean
diff --git a/tools/power/cpupower/debug/i386/centrino-decode.c b/tools/power/cpupower/debug/i386/centrino-decode.c
new file mode 100644 (file)
index 0000000..7ef24cc
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  (C) 2003 - 2004  Dominik Brodowski <linux@dominikbrodowski.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ * Based on code found in
+ * linux/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+ * and originally developed by Jeremy Fitzhardinge.
+ *
+ * USAGE: simply run it to decode the current settings on CPU 0,
+ *       or pass the CPU number as argument, or pass the MSR content
+ *       as argument.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define MCPU   32
+
+#define MSR_IA32_PERF_STATUS   0x198
+
+static int rdmsr(unsigned int cpu, unsigned int msr,
+                unsigned int *lo, unsigned int *hi)
+{
+       int fd;
+       char file[20];
+       unsigned long long val;
+       int retval = -1;
+
+       *lo = *hi = 0;
+
+       if (cpu > MCPU)
+               goto err1;
+
+       sprintf(file, "/dev/cpu/%d/msr", cpu);
+       fd = open(file, O_RDONLY);
+
+       if (fd < 0)
+               goto err1;
+
+       if (lseek(fd, msr, SEEK_CUR) == -1)
+               goto err2;
+
+       if (read(fd, &val, 8) != 8)
+               goto err2;
+
+       *lo = (uint32_t )(val & 0xffffffffull);
+       *hi = (uint32_t )(val>>32 & 0xffffffffull);
+
+       retval = 0;
+err2:
+       close(fd);
+err1:
+       return retval;
+}
+
+static void decode (unsigned int msr)
+{
+       unsigned int multiplier;
+       unsigned int mv;
+
+       multiplier = ((msr >> 8) & 0xFF);
+
+       mv = (((msr & 0xFF) * 16) + 700);
+
+       printf("0x%x means multiplier %d @ %d mV\n", msr, multiplier, mv);
+}
+
+static int decode_live(unsigned int cpu)
+{
+       unsigned int lo, hi;
+       int err;
+
+       err = rdmsr(cpu, MSR_IA32_PERF_STATUS, &lo, &hi);
+
+       if (err) {
+               printf("can't get MSR_IA32_PERF_STATUS for cpu %d\n", cpu);
+               printf("Possible trouble: you don't run an Enhanced SpeedStep capable cpu\n");
+               printf("or you are not root, or the msr driver is not present\n");
+               return 1;
+       }
+
+       decode(lo);
+
+       return 0;
+}
+
+int main (int argc, char **argv)
+{
+       unsigned int cpu, mode = 0;
+
+       if (argc < 2)
+               cpu = 0;
+       else {
+               cpu = strtoul(argv[1], NULL, 0);
+               if (cpu >= MCPU)
+                       mode = 1;
+       }
+
+       if (mode)
+               decode(cpu);
+       else
+               decode_live(cpu);
+
+       return 0;
+}
diff --git a/tools/power/cpupower/debug/i386/dump_psb.c b/tools/power/cpupower/debug/i386/dump_psb.c
new file mode 100644 (file)
index 0000000..8d6a475
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * dump_psb. (c) 2004, Dave Jones, Red Hat Inc.
+ * Licensed under the GPL v2.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <sys/mman.h>
+
+#define LEN (0x100000 - 0xc0000)
+#define OFFSET (0xc0000)
+
+#ifndef __packed
+#define __packed __attribute((packed))
+#endif
+
+static long relevant;
+
+static const int fid_to_mult[32] = {
+       110, 115, 120, 125, 50, 55, 60, 65,
+       70, 75, 80, 85, 90, 95, 100, 105,
+       30, 190, 40, 200, 130, 135, 140, 210,
+       150, 225, 160, 165, 170, 180, -1, -1,
+};
+
+static const int vid_to_voltage[32] = {
+       2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
+       1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
+       1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
+       1075, 1050, 1024, 1000, 975, 950, 925, 0,
+};
+
+struct psb_header {
+       char signature[10];
+       u_char version;
+       u_char flags;
+       u_short settlingtime;
+       u_char res1;
+       u_char numpst;
+} __packed;
+
+struct pst_header {
+       u_int32_t cpuid;
+       u_char fsb;
+       u_char maxfid;
+       u_char startvid;
+       u_char numpstates;
+} __packed;
+
+static u_int fsb;
+static u_int sgtc;
+
+static int
+decode_pst(char *p, int npstates)
+{
+       int i;
+       int freq, fid, vid;
+
+       for (i = 0; i < npstates; ++i) {
+               fid = *p++;
+               vid = *p++;
+               freq = 100 * fid_to_mult[fid] * fsb;
+
+               printf("   %2d %8dkHz  FID %02x (%2d.%01d)  VID %02x (%4dmV)\n",
+                      i,
+                      freq,
+                      fid, fid_to_mult[fid]/10, fid_to_mult[fid]%10,
+                      vid, vid_to_voltage[vid]);
+       }
+
+       return 0;
+}
+
+static
+void decode_psb(char *p, int numpst)
+{
+       int i;
+       struct psb_header *psb;
+       struct pst_header *pst;
+
+       psb = (struct psb_header*) p;
+
+       if (psb->version != 0x12)
+               return;
+
+       printf("PSB version: %hhx flags: %hhx settling time %hhuus res1 %hhx num pst %hhu\n",
+                       psb->version,
+                       psb->flags,
+                       psb->settlingtime,
+                       psb->res1,
+                       psb->numpst);
+       sgtc = psb->settlingtime * 100;
+
+       if (sgtc < 10000)
+               sgtc = 10000;
+
+       p = ((char *) psb) + sizeof(struct psb_header);
+
+       if (numpst < 0)
+               numpst = psb->numpst;
+       else
+               printf("Overriding number of pst :%d\n", numpst);
+
+       for (i = 0; i < numpst; i++) {
+               pst = (struct pst_header*) p;
+
+               if (relevant != 0) {
+                       if (relevant!= pst->cpuid)
+                               goto next_one;
+               }
+
+               printf("  PST %d  cpuid %.3x fsb %hhu mfid %hhx svid %hhx numberstates %hhu\n",
+                               i+1,
+                               pst->cpuid,
+                               pst->fsb,
+                               pst->maxfid,
+                               pst->startvid,
+                               pst->numpstates);
+
+               fsb = pst->fsb;
+               decode_pst(p + sizeof(struct pst_header), pst->numpstates);
+
+next_one:
+               p += sizeof(struct pst_header) + 2*pst->numpstates;
+       }
+
+}
+
+static struct option info_opts[] = {
+       {.name = "numpst",      .has_arg=no_argument,   .flag=NULL, .val='n'},
+};
+
+void print_help(void)
+{
+       printf ("Usage: dump_psb [options]\n");
+       printf ("Options:\n");
+       printf ("  -n, --numpst     Set number of PST tables to scan\n");
+       printf ("  -r, --relevant   Only display PSTs relevant to cpuid N\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+       int fd;
+       int numpst=-1;
+       int ret=0, cont=1;
+       char *mem = NULL;
+       char *p;
+
+       do {
+               ret = getopt_long(argc, argv, "hr:n:", info_opts, NULL);
+               switch (ret){
+               case '?':
+               case 'h':
+                       print_help();
+                       cont = 0;
+                       break;
+               case 'r':
+                       relevant = strtol(optarg, NULL, 16);
+                       break;
+               case 'n':
+                       numpst = strtol(optarg, NULL, 10);
+                       break;
+               case -1:
+                       cont = 0;
+                       break;
+               }
+
+       } while(cont);
+
+       fd = open("/dev/mem", O_RDONLY);
+       if (fd < 0) {
+               printf ("Couldn't open /dev/mem. Are you root?\n");
+               exit(1);
+       }
+
+       mem = mmap(mem, 0x100000 - 0xc0000, PROT_READ, MAP_SHARED, fd, 0xc0000);
+       close(fd);
+
+       for (p = mem; p - mem < LEN; p+=16) {
+               if (memcmp(p, "AMDK7PNOW!", 10) == 0) {
+                       decode_psb(p, numpst);
+                       break;
+               }
+       }
+
+       munmap(mem, LEN);
+       return 0;
+}
diff --git a/tools/power/cpupower/debug/i386/intel_gsic.c b/tools/power/cpupower/debug/i386/intel_gsic.c
new file mode 100644 (file)
index 0000000..53f5293
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *  (C) 2003  Bruno Ducrot
+ *  (C) 2004  Dominik Brodowski <linux@dominikbrodowski.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ * Based on code found in
+ * linux/include/asm-i386/ist.h and linux/arch/i386/kernel/setup.c
+ * and originally developed by Andy Grover <andrew.grover@intel.com>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <lrmi.h>
+
+int main (void)
+{
+       struct LRMI_regs        r;
+       int                     retval;
+
+       if (!LRMI_init())
+               return 0;
+
+       memset(&r, 0, sizeof(r));
+
+       r.eax = 0x0000E980;
+       r.edx = 0x47534943;
+
+       retval = LRMI_int(0x15, &r);
+
+       if (!retval) {
+               printf("Failed!\n");
+               return 0;
+       }
+       if (r.eax == 0x47534943) {
+               printf("BIOS supports GSIC call:\n");
+               printf("\tsignature: %c%c%c%c\n",
+                      (r.eax >> 24) & 0xff,
+                      (r.eax >> 16) & 0xff,
+                      (r.eax >> 8) & 0xff,
+                      (r.eax) & 0xff);
+               printf("\tcommand port = 0x%.4x\n",
+                      r.ebx & 0xffff);
+               printf("\tcommand =      0x%.4x\n",
+                      (r.ebx >> 16) & 0xffff);
+               printf("\tevent port =   0x%.8x\n", r.ecx);
+               printf("\tflags =        0x%.8x\n", r.edx);
+               if (((r.ebx >> 16) & 0xffff) != 0x82) {
+                       printf("non-default command value. If speedstep-smi "
+                              "doesn't work out of the box,\nyou may want to "
+                              "try out the default value by passing "
+                              "smi_cmd=0x82 to the module\n ON YOUR OWN "
+                              "RISK.\n");
+               }
+               if ((r.ebx & 0xffff) != 0xb2) {
+                       printf("non-default command port. If speedstep-smi "
+                              "doesn't work out of the box,\nyou may want to "
+                              "try out the default value by passing "
+                              "smi_port=0x82 to the module\n ON YOUR OWN "
+                              "RISK.\n");
+               }
+       } else {
+               printf("BIOS DOES NOT support GSIC call.  Dumping registers anyway:\n");
+               printf("eax = 0x%.8x\n", r.eax);
+               printf("ebx = 0x%.8x\n", r.ebx);
+               printf("ecx = 0x%.8x\n", r.ecx);
+               printf("edx = 0x%.8x\n", r.edx);
+               printf("Note also that some BIOS do not support the initial "
+                      "GSIC call, but the newer\nspeeedstep-smi driver may "
+                      "work.\nFor this, you need to pass some arguments to "
+                      "the speedstep-smi driver:\n");
+               printf("\tsmi_cmd=0x?? smi_port=0x?? smi_sig=1\n");
+               printf("\nUnfortunately, you have to know what exactly are "
+                      "smi_cmd and smi_port, and this\nis system "
+                      "dependant.\n");
+       }
+       return 1;
+}
diff --git a/tools/power/cpupower/debug/i386/powernow-k8-decode.c b/tools/power/cpupower/debug/i386/powernow-k8-decode.c
new file mode 100644 (file)
index 0000000..638a6b3
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *  (C) 2004 Bruno Ducrot <ducrot@poupinou.org>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ * Based on code found in
+ * linux/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+ * and originally developed by Paul Devriendt
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define MCPU 32
+
+#define MSR_FIDVID_STATUS      0xc0010042
+
+#define MSR_S_HI_CURRENT_VID   0x0000001f
+#define MSR_S_LO_CURRENT_FID   0x0000003f
+
+static int get_fidvid(uint32_t cpu, uint32_t *fid, uint32_t *vid)
+{
+       int err = 1;
+       uint64_t msr = 0;
+       int fd;
+       char file[20];
+
+       if (cpu > MCPU)
+               goto out;
+
+       sprintf(file, "/dev/cpu/%d/msr", cpu);
+
+       fd = open(file, O_RDONLY);
+       if (fd < 0)
+               goto out;
+       lseek(fd, MSR_FIDVID_STATUS, SEEK_CUR);
+       if (read(fd, &msr, 8) != 8)
+               goto err1;
+
+       *fid = ((uint32_t )(msr & 0xffffffffull)) & MSR_S_LO_CURRENT_FID;
+       *vid = ((uint32_t )(msr>>32 & 0xffffffffull)) & MSR_S_HI_CURRENT_VID;
+       err = 0;
+err1:
+       close(fd);
+out:
+       return err;
+}
+
+
+/* Return a frequency in MHz, given an input fid */
+static uint32_t find_freq_from_fid(uint32_t fid)
+{
+       return 800 + (fid * 100);
+}
+
+/* Return a voltage in miliVolts, given an input vid */
+static uint32_t find_millivolts_from_vid(uint32_t vid)
+{
+       return 1550-vid*25;
+}
+
+int main (int argc, char *argv[])
+{
+       int err;
+       int cpu;
+       uint32_t fid, vid;
+
+       if (argc < 2)
+               cpu = 0;
+       else
+               cpu = strtoul(argv[1], NULL, 0);
+
+       err = get_fidvid(cpu, &fid, &vid);
+
+       if (err) {
+               printf("can't get fid, vid from MSR\n");
+               printf("Possible trouble: you don't run a powernow-k8 capable cpu\n");
+               printf("or you are not root, or the msr driver is not present\n");
+               exit(1);
+       }
+
+       
+       printf("cpu %d currently at %d MHz and %d mV\n",
+                       cpu,
+                       find_freq_from_fid(fid),
+                       find_millivolts_from_vid(vid));
+       
+       return 0;
+}
diff --git a/tools/power/cpupower/debug/kernel/Makefile b/tools/power/cpupower/debug/kernel/Makefile
new file mode 100644 (file)
index 0000000..96b146f
--- /dev/null
@@ -0,0 +1,23 @@
+obj-m  :=
+
+KDIR   := /lib/modules/$(shell uname -r)/build
+PWD            := $(shell pwd)
+KMISC   := /lib/modules/$(shell uname -r)/cpufrequtils/
+
+ifeq ("$(CONFIG_X86_TSC)", "y")
+  obj-m         += cpufreq-test_tsc.o
+endif
+
+default:
+       $(MAKE) -C $(KDIR) M=$(PWD)
+
+clean:
+       - rm -rf *.o *.ko .tmp-versions .*.cmd .*.mod.* *.mod.c
+       - rm -rf .tmp_versions* Module.symvers modules.order
+
+install: default
+       install -d $(KMISC)
+       install -m 644 -c *.ko $(KMISC)
+       /sbin/depmod -a
+
+all:   default
diff --git a/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c
new file mode 100644 (file)
index 0000000..66cace6
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * test module to check whether the TSC-based delay routine continues
+ * to work properly after cpufreq transitions. Needs ACPI to work
+ * properly.
+ *
+ * Based partly on the Power Management Timer (PMTMR) code to be found
+ * in arch/i386/kernel/timers/timer_pm.c on recent 2.6. kernels, especially
+ * code written by John Stultz. The read_pmtmr function was copied verbatim
+ * from that file.
+ *
+ * (C) 2004 Dominik Brodowski
+ *
+ * To use:
+ * 1.) pass clock=tsc to the kernel on your bootloader
+ * 2.) modprobe this module (it'll fail)
+ * 3.) change CPU frequency
+ * 4.) modprobe this module again
+ * 5.) if the third value, "diff_pmtmr", changes between 2. and 4., the
+ *     TSC-based delay routine on the Linux kernel does not correctly
+ *     handle the cpufreq transition. Please report this to
+ *     cpufreq@vger.kernel.org
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+static int pm_tmr_ioport = 0;
+
+/*helper function to safely read acpi pm timesource*/
+static u32 read_pmtmr(void)
+{
+       u32 v1=0,v2=0,v3=0;
+       /* It has been reported that because of various broken
+        * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time
+        * source is not latched, so you must read it multiple
+        * times to insure a safe value is read.
+        */
+       do {
+               v1 = inl(pm_tmr_ioport);
+               v2 = inl(pm_tmr_ioport);
+               v3 = inl(pm_tmr_ioport);
+       } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
+                || (v3 > v1 && v3 < v2));
+
+       /* mask the output to 24 bits */
+       return (v2 & 0xFFFFFF);
+}
+
+static int __init cpufreq_test_tsc(void)
+{
+       u32 now, then, diff;
+       u64 now_tsc, then_tsc, diff_tsc;
+       int i;
+
+       /* the following code snipped is copied from arch/x86/kernel/acpi/boot.c
+          of Linux v2.6.25. */
+
+       /* detect the location of the ACPI PM Timer */
+       if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) {
+               /* FADT rev. 2 */
+               if (acpi_gbl_FADT.xpm_timer_block.space_id !=
+                   ACPI_ADR_SPACE_SYSTEM_IO)
+                       return 0;
+
+               pm_tmr_ioport = acpi_gbl_FADT.xpm_timer_block.address;
+               /*
+                * "X" fields are optional extensions to the original V1.0
+                * fields, so we must selectively expand V1.0 fields if the
+                * corresponding X field is zero.
+                */
+               if (!pm_tmr_ioport)
+                       pm_tmr_ioport = acpi_gbl_FADT.pm_timer_block;
+       } else {
+               /* FADT rev. 1 */
+               pm_tmr_ioport = acpi_gbl_FADT.pm_timer_block;
+       }
+
+       printk(KERN_DEBUG "start--> \n");
+       then = read_pmtmr();
+        rdtscll(then_tsc);
+       for (i=0;i<20;i++) {
+               mdelay(100);
+               now = read_pmtmr();
+               rdtscll(now_tsc);
+               diff = (now - then) & 0xFFFFFF;
+               diff_tsc = now_tsc - then_tsc;
+               printk(KERN_DEBUG "t1: %08u t2: %08u diff_pmtmr: %08u diff_tsc: %016llu\n", then, now, diff, diff_tsc);
+               then = now;
+               then_tsc = now_tsc;
+       }
+       printk(KERN_DEBUG "<-- end \n");
+       return -ENODEV;
+}
+
+static void __exit cpufreq_none(void)
+{
+       return;
+}
+
+module_init(cpufreq_test_tsc)
+module_exit(cpufreq_none)
+
+
+MODULE_AUTHOR("Dominik Brodowski");
+MODULE_DESCRIPTION("Verify the TSC cpufreq notifier working correctly -- needs ACPI-enabled system");
+MODULE_LICENSE ("GPL");
diff --git a/tools/power/cpupower/debug/x86_64/Makefile b/tools/power/cpupower/debug/x86_64/Makefile
new file mode 100644 (file)
index 0000000..dbf1399
--- /dev/null
@@ -0,0 +1,14 @@
+default: all
+
+centrino-decode: centrino-decode.c
+       $(CC) $(CFLAGS) -o centrino-decode centrino-decode.c
+
+powernow-k8-decode: powernow-k8-decode.c
+       $(CC) $(CFLAGS) -o powernow-k8-decode powernow-k8-decode.c
+
+all: centrino-decode powernow-k8-decode
+
+clean:
+       rm -rf centrino-decode powernow-k8-decode
+
+.PHONY: all default clean
diff --git a/tools/power/cpupower/debug/x86_64/centrino-decode.c b/tools/power/cpupower/debug/x86_64/centrino-decode.c
new file mode 120000 (symlink)
index 0000000..26fb3f1
--- /dev/null
@@ -0,0 +1 @@
+../i386/centrino-decode.c
\ No newline at end of file
diff --git a/tools/power/cpupower/debug/x86_64/powernow-k8-decode.c b/tools/power/cpupower/debug/x86_64/powernow-k8-decode.c
new file mode 120000 (symlink)
index 0000000..eb30c79
--- /dev/null
@@ -0,0 +1 @@
+../i386/powernow-k8-decode.c
\ No newline at end of file
diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
new file mode 100644 (file)
index 0000000..d961101
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cpufreq.h"
+#include "sysfs.h"
+
+int cpufreq_cpu_exists(unsigned int cpu)
+{
+       return sysfs_cpu_exists(cpu);
+}
+
+unsigned long cpufreq_get_freq_kernel(unsigned int cpu)
+{
+       return sysfs_get_freq_kernel(cpu);
+}
+
+unsigned long cpufreq_get_freq_hardware(unsigned int cpu)
+{
+       return sysfs_get_freq_hardware(cpu);
+}
+
+unsigned long cpufreq_get_transition_latency(unsigned int cpu)
+{
+       return sysfs_get_freq_transition_latency(cpu);
+}
+
+int cpufreq_get_hardware_limits(unsigned int cpu,
+                               unsigned long *min,
+                               unsigned long *max)
+{
+       if ((!min) || (!max))
+               return -EINVAL;
+       return sysfs_get_freq_hardware_limits(cpu, min, max);
+}
+
+char *cpufreq_get_driver(unsigned int cpu)
+{
+       return sysfs_get_freq_driver(cpu);
+}
+
+void cpufreq_put_driver(char *ptr)
+{
+       if (!ptr)
+               return;
+       free(ptr);
+}
+
+struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu)
+{
+       return sysfs_get_freq_policy(cpu);
+}
+
+void cpufreq_put_policy(struct cpufreq_policy *policy)
+{
+       if ((!policy) || (!policy->governor))
+               return;
+
+       free(policy->governor);
+       policy->governor = NULL;
+       free(policy);
+}
+
+struct cpufreq_available_governors *cpufreq_get_available_governors(unsigned
+                                                               int cpu)
+{
+       return sysfs_get_freq_available_governors(cpu);
+}
+
+void cpufreq_put_available_governors(struct cpufreq_available_governors *any)
+{
+       struct cpufreq_available_governors *tmp, *next;
+
+       if (!any)
+               return;
+
+       tmp = any->first;
+       while (tmp) {
+               next = tmp->next;
+               if (tmp->governor)
+                       free(tmp->governor);
+               free(tmp);
+               tmp = next;
+       }
+}
+
+
+struct cpufreq_available_frequencies
+*cpufreq_get_available_frequencies(unsigned int cpu)
+{
+       return sysfs_get_available_frequencies(cpu);
+}
+
+void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies
+                               *any) {
+       struct cpufreq_available_frequencies *tmp, *next;
+
+       if (!any)
+               return;
+
+       tmp = any->first;
+       while (tmp) {
+               next = tmp->next;
+               free(tmp);
+               tmp = next;
+       }
+}
+
+
+struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned int cpu)
+{
+       return sysfs_get_freq_affected_cpus(cpu);
+}
+
+void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any)
+{
+       struct cpufreq_affected_cpus *tmp, *next;
+
+       if (!any)
+               return;
+
+       tmp = any->first;
+       while (tmp) {
+               next = tmp->next;
+               free(tmp);
+               tmp = next;
+       }
+}
+
+
+struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned int cpu)
+{
+       return sysfs_get_freq_related_cpus(cpu);
+}
+
+void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any)
+{
+       cpufreq_put_affected_cpus(any);
+}
+
+
+int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy)
+{
+       if (!policy || !(policy->governor))
+               return -EINVAL;
+
+       return sysfs_set_freq_policy(cpu, policy);
+}
+
+
+int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq)
+{
+       return sysfs_modify_freq_policy_min(cpu, min_freq);
+}
+
+
+int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq)
+{
+       return sysfs_modify_freq_policy_max(cpu, max_freq);
+}
+
+
+int cpufreq_modify_policy_governor(unsigned int cpu, char *governor)
+{
+       if ((!governor) || (strlen(governor) > 19))
+               return -EINVAL;
+
+       return sysfs_modify_freq_policy_governor(cpu, governor);
+}
+
+int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency)
+{
+       return sysfs_set_frequency(cpu, target_frequency);
+}
+
+struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
+                                       unsigned long long *total_time)
+{
+       return sysfs_get_freq_stats(cpu, total_time);
+}
+
+void cpufreq_put_stats(struct cpufreq_stats *any)
+{
+       struct cpufreq_stats *tmp, *next;
+
+       if (!any)
+               return;
+
+       tmp = any->first;
+       while (tmp) {
+               next = tmp->next;
+               free(tmp);
+               tmp = next;
+       }
+}
+
+unsigned long cpufreq_get_transitions(unsigned int cpu)
+{
+       return sysfs_get_freq_transitions(cpu);
+}
diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h
new file mode 100644 (file)
index 0000000..3aae8e7
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ *  cpufreq.h - definitions for libcpufreq
+ *
+ *  Copyright (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.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, version 2 of the License.
+ *
+ *  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 _CPUFREQ_H
+#define _CPUFREQ_H 1
+
+struct cpufreq_policy {
+       unsigned long min;
+       unsigned long max;
+       char *governor;
+};
+
+struct cpufreq_available_governors {
+       char *governor;
+       struct cpufreq_available_governors *next;
+       struct cpufreq_available_governors *first;
+};
+
+struct cpufreq_available_frequencies {
+       unsigned long frequency;
+       struct cpufreq_available_frequencies *next;
+       struct cpufreq_available_frequencies *first;
+};
+
+
+struct cpufreq_affected_cpus {
+       unsigned int cpu;
+       struct cpufreq_affected_cpus *next;
+       struct cpufreq_affected_cpus *first;
+};
+
+struct cpufreq_stats {
+       unsigned long frequency;
+       unsigned long long time_in_state;
+       struct cpufreq_stats *next;
+       struct cpufreq_stats *first;
+};
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * returns 0 if the specified CPU is present (it doesn't say
+ * whether it is online!), and an error value if not.
+ */
+
+extern int cpufreq_cpu_exists(unsigned int cpu);
+
+/* determine current CPU frequency
+ * - _kernel variant means kernel's opinion of CPU frequency
+ * - _hardware variant means actual hardware CPU frequency,
+ *    which is only available to root.
+ *
+ * returns 0 on failure, else frequency in kHz.
+ */
+
+extern unsigned long cpufreq_get_freq_kernel(unsigned int cpu);
+
+extern unsigned long cpufreq_get_freq_hardware(unsigned int cpu);
+
+#define cpufreq_get(cpu) cpufreq_get_freq_kernel(cpu);
+
+
+/* determine CPU transition latency
+ *
+ * returns 0 on failure, else transition latency in 10^(-9) s = nanoseconds
+ */
+extern unsigned long cpufreq_get_transition_latency(unsigned int cpu);
+
+
+/* determine hardware CPU frequency limits
+ *
+ * These may be limited further by thermal, energy or other
+ * considerations by cpufreq policy notifiers in the kernel.
+ */
+
+extern int cpufreq_get_hardware_limits(unsigned int cpu,
+                               unsigned long *min,
+                               unsigned long *max);
+
+
+/* determine CPUfreq driver used
+ *
+ * Remember to call cpufreq_put_driver when no longer needed
+ * to avoid memory leakage, please.
+ */
+
+extern char *cpufreq_get_driver(unsigned int cpu);
+
+extern void cpufreq_put_driver(char *ptr);
+
+
+/* determine CPUfreq policy currently used
+ *
+ * Remember to call cpufreq_put_policy when no longer needed
+ * to avoid memory leakage, please.
+ */
+
+
+extern struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu);
+
+extern void cpufreq_put_policy(struct cpufreq_policy *policy);
+
+
+/* determine CPUfreq governors currently available
+ *
+ * may be modified by modprobe'ing or rmmod'ing other governors. Please
+ * free allocated memory by calling cpufreq_put_available_governors
+ * after use.
+ */
+
+
+extern struct cpufreq_available_governors
+*cpufreq_get_available_governors(unsigned int cpu);
+
+extern void cpufreq_put_available_governors(
+       struct cpufreq_available_governors *first);
+
+
+/* determine CPU frequency states available
+ *
+ * Only present on _some_ ->target() cpufreq drivers. For information purposes
+ * only. Please free allocated memory by calling
+ * cpufreq_put_available_frequencies after use.
+ */
+
+extern struct cpufreq_available_frequencies
+*cpufreq_get_available_frequencies(unsigned int cpu);
+
+extern void cpufreq_put_available_frequencies(
+               struct cpufreq_available_frequencies *first);
+
+
+/* determine affected CPUs
+ *
+ * Remember to call cpufreq_put_affected_cpus when no longer needed
+ * to avoid memory leakage, please.
+ */
+
+extern struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned
+                                                       int cpu);
+
+extern void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first);
+
+
+/* determine related CPUs
+ *
+ * Remember to call cpufreq_put_related_cpus when no longer needed
+ * to avoid memory leakage, please.
+ */
+
+extern struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned
+                                                       int cpu);
+
+extern void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first);
+
+
+/* determine stats for cpufreq subsystem
+ *
+ * This is not available in all kernel versions or configurations.
+ */
+
+extern struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
+                                       unsigned long long *total_time);
+
+extern void cpufreq_put_stats(struct cpufreq_stats *stats);
+
+extern unsigned long cpufreq_get_transitions(unsigned int cpu);
+
+
+/* set new cpufreq policy
+ *
+ * Tries to set the passed policy as new policy as close as possible,
+ * but results may differ depending e.g. on governors being available.
+ */
+
+extern int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy);
+
+
+/* modify a policy by only changing min/max freq or governor
+ *
+ * Does not check whether result is what was intended.
+ */
+
+extern int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq);
+extern int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq);
+extern int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
+
+
+/* set a specific frequency
+ *
+ * Does only work if userspace governor can be used and no external
+ * interference (other calls to this function or to set/modify_policy)
+ * occurs. Also does not work on ->range() cpufreq drivers.
+ */
+
+extern int cpufreq_set_frequency(unsigned int cpu,
+                               unsigned long target_frequency);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CPUFREQ_H */
diff --git a/tools/power/cpupower/lib/sysfs.c b/tools/power/cpupower/lib/sysfs.c
new file mode 100644 (file)
index 0000000..870713a
--- /dev/null
@@ -0,0 +1,672 @@
+/*
+ *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "cpufreq.h"
+
+#define PATH_TO_CPU "/sys/devices/system/cpu/"
+#define MAX_LINE_LEN 4096
+#define SYSFS_PATH_MAX 255
+
+
+static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
+{
+       int fd;
+       ssize_t numread;
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1)
+               return 0;
+
+       numread = read(fd, buf, buflen - 1);
+       if (numread < 1) {
+               close(fd);
+               return 0;
+       }
+
+       buf[numread] = '\0';
+       close(fd);
+
+       return (unsigned int) numread;
+}
+
+
+/* CPUFREQ sysfs access **************************************************/
+
+/* helper function to read file from /sys into given buffer */
+/* fname is a relative path under "cpuX/cpufreq" dir */
+static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
+                                           char *buf, size_t buflen)
+{
+       char path[SYSFS_PATH_MAX];
+
+       snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
+                        cpu, fname);
+       return sysfs_read_file(path, buf, buflen);
+}
+
+/* helper function to write a new value to a /sys file */
+/* fname is a relative path under "cpuX/cpufreq" dir */
+static unsigned int sysfs_cpufreq_write_file(unsigned int cpu,
+                                            const char *fname,
+                                            const char *value, size_t len)
+{
+       char path[SYSFS_PATH_MAX];
+       int fd;
+       ssize_t numwrite;
+
+       snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
+                        cpu, fname);
+
+       fd = open(path, O_WRONLY);
+       if (fd == -1)
+               return 0;
+
+       numwrite = write(fd, value, len);
+       if (numwrite < 1) {
+               close(fd);
+               return 0;
+       }
+
+       close(fd);
+
+       return (unsigned int) numwrite;
+}
+
+/* read access to files which contain one numeric value */
+
+enum cpufreq_value {
+       CPUINFO_CUR_FREQ,
+       CPUINFO_MIN_FREQ,
+       CPUINFO_MAX_FREQ,
+       CPUINFO_LATENCY,
+       SCALING_CUR_FREQ,
+       SCALING_MIN_FREQ,
+       SCALING_MAX_FREQ,
+       STATS_NUM_TRANSITIONS,
+       MAX_CPUFREQ_VALUE_READ_FILES
+};
+
+static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
+       [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
+       [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
+       [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
+       [CPUINFO_LATENCY]  = "cpuinfo_transition_latency",
+       [SCALING_CUR_FREQ] = "scaling_cur_freq",
+       [SCALING_MIN_FREQ] = "scaling_min_freq",
+       [SCALING_MAX_FREQ] = "scaling_max_freq",
+       [STATS_NUM_TRANSITIONS] = "stats/total_trans"
+};
+
+
+static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
+                                                enum cpufreq_value which)
+{
+       unsigned long value;
+       unsigned int len;
+       char linebuf[MAX_LINE_LEN];
+       char *endp;
+
+       if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
+               return 0;
+
+       len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
+                               linebuf, sizeof(linebuf));
+
+       if (len == 0)
+               return 0;
+
+       value = strtoul(linebuf, &endp, 0);
+
+       if (endp == linebuf || errno == ERANGE)
+               return 0;
+
+       return value;
+}
+
+/* read access to files which contain one string */
+
+enum cpufreq_string {
+       SCALING_DRIVER,
+       SCALING_GOVERNOR,
+       MAX_CPUFREQ_STRING_FILES
+};
+
+static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
+       [SCALING_DRIVER] = "scaling_driver",
+       [SCALING_GOVERNOR] = "scaling_governor",
+};
+
+
+static char *sysfs_cpufreq_get_one_string(unsigned int cpu,
+                                          enum cpufreq_string which)
+{
+       char linebuf[MAX_LINE_LEN];
+       char *result;
+       unsigned int len;
+
+       if (which >= MAX_CPUFREQ_STRING_FILES)
+               return NULL;
+
+       len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which],
+                               linebuf, sizeof(linebuf));
+       if (len == 0)
+               return NULL;
+
+       result = strdup(linebuf);
+       if (result == NULL)
+               return NULL;
+
+       if (result[strlen(result) - 1] == '\n')
+               result[strlen(result) - 1] = '\0';
+
+       return result;
+}
+
+/* write access */
+
+enum cpufreq_write {
+       WRITE_SCALING_MIN_FREQ,
+       WRITE_SCALING_MAX_FREQ,
+       WRITE_SCALING_GOVERNOR,
+       WRITE_SCALING_SET_SPEED,
+       MAX_CPUFREQ_WRITE_FILES
+};
+
+static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = {
+       [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
+       [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
+       [WRITE_SCALING_GOVERNOR] = "scaling_governor",
+       [WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
+};
+
+static int sysfs_cpufreq_write_one_value(unsigned int cpu,
+                                        enum cpufreq_write which,
+                                        const char *new_value, size_t len)
+{
+       if (which >= MAX_CPUFREQ_WRITE_FILES)
+               return 0;
+
+       if (sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which],
+                                       new_value, len) != len)
+               return -ENODEV;
+
+       return 0;
+};
+
+unsigned long sysfs_get_freq_kernel(unsigned int cpu)
+{
+       return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ);
+}
+
+unsigned long sysfs_get_freq_hardware(unsigned int cpu)
+{
+       return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ);
+}
+
+unsigned long sysfs_get_freq_transition_latency(unsigned int cpu)
+{
+       return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
+}
+
+int sysfs_get_freq_hardware_limits(unsigned int cpu,
+                             unsigned long *min,
+                             unsigned long *max)
+{
+       if ((!min) || (!max))
+               return -EINVAL;
+
+       *min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ);
+       if (!*min)
+               return -ENODEV;
+
+       *max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
+       if (!*max)
+               return -ENODEV;
+
+       return 0;
+}
+
+char *sysfs_get_freq_driver(unsigned int cpu)
+{
+       return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER);
+}
+
+struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu)
+{
+       struct cpufreq_policy *policy;
+
+       policy = malloc(sizeof(struct cpufreq_policy));
+       if (!policy)
+               return NULL;
+
+       policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR);
+       if (!policy->governor) {
+               free(policy);
+               return NULL;
+       }
+       policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
+       policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ);
+       if ((!policy->min) || (!policy->max)) {
+               free(policy->governor);
+               free(policy);
+               return NULL;
+       }
+
+       return policy;
+}
+
+struct cpufreq_available_governors *
+sysfs_get_freq_available_governors(unsigned int cpu) {
+       struct cpufreq_available_governors *first = NULL;
+       struct cpufreq_available_governors *current = NULL;
+       char linebuf[MAX_LINE_LEN];
+       unsigned int pos, i;
+       unsigned int len;
+
+       len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors",
+                               linebuf, sizeof(linebuf));
+       if (len == 0)
+               return NULL;
+
+       pos = 0;
+       for (i = 0; i < len; i++) {
+               if (linebuf[i] == ' ' || linebuf[i] == '\n') {
+                       if (i - pos < 2)
+                               continue;
+                       if (current) {
+                               current->next = malloc(sizeof(*current));
+                               if (!current->next)
+                                       goto error_out;
+                               current = current->next;
+                       } else {
+                               first = malloc(sizeof(*first));
+                               if (!first)
+                                       goto error_out;
+                               current = first;
+                       }
+                       current->first = first;
+                       current->next = NULL;
+
+                       current->governor = malloc(i - pos + 1);
+                       if (!current->governor)
+                               goto error_out;
+
+                       memcpy(current->governor, linebuf + pos, i - pos);
+                       current->governor[i - pos] = '\0';
+                       pos = i + 1;
+               }
+       }
+
+       return first;
+
+ error_out:
+       while (first) {
+               current = first->next;
+               if (first->governor)
+                       free(first->governor);
+               free(first);
+               first = current;
+       }
+       return NULL;
+}
+
+
+struct cpufreq_available_frequencies *
+sysfs_get_available_frequencies(unsigned int cpu) {
+       struct cpufreq_available_frequencies *first = NULL;
+       struct cpufreq_available_frequencies *current = NULL;
+       char one_value[SYSFS_PATH_MAX];
+       char linebuf[MAX_LINE_LEN];
+       unsigned int pos, i;
+       unsigned int len;
+
+       len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies",
+                               linebuf, sizeof(linebuf));
+       if (len == 0)
+               return NULL;
+
+       pos = 0;
+       for (i = 0; i < len; i++) {
+               if (linebuf[i] == ' ' || linebuf[i] == '\n') {
+                       if (i - pos < 2)
+                               continue;
+                       if (i - pos >= SYSFS_PATH_MAX)
+                               goto error_out;
+                       if (current) {
+                               current->next = malloc(sizeof(*current));
+                               if (!current->next)
+                                       goto error_out;
+                               current = current->next;
+                       } else {
+                               first = malloc(sizeof(*first));
+                               if (!first)
+                                       goto error_out;
+                               current = first;
+                       }
+                       current->first = first;
+                       current->next = NULL;
+
+                       memcpy(one_value, linebuf + pos, i - pos);
+                       one_value[i - pos] = '\0';
+                       if (sscanf(one_value, "%lu", &current->frequency) != 1)
+                               goto error_out;
+
+                       pos = i + 1;
+               }
+       }
+
+       return first;
+
+ error_out:
+       while (first) {
+               current = first->next;
+               free(first);
+               first = current;
+       }
+       return NULL;
+}
+
+static struct cpufreq_affected_cpus *sysfs_get_cpu_list(unsigned int cpu,
+                                                       const char *file)
+{
+       struct cpufreq_affected_cpus *first = NULL;
+       struct cpufreq_affected_cpus *current = NULL;
+       char one_value[SYSFS_PATH_MAX];
+       char linebuf[MAX_LINE_LEN];
+       unsigned int pos, i;
+       unsigned int len;
+
+       len = sysfs_cpufreq_read_file(cpu, file, linebuf, sizeof(linebuf));
+       if (len == 0)
+               return NULL;
+
+       pos = 0;
+       for (i = 0; i < len; i++) {
+               if (i == len || linebuf[i] == ' ' || linebuf[i] == '\n') {
+                       if (i - pos  < 1)
+                               continue;
+                       if (i - pos >= SYSFS_PATH_MAX)
+                               goto error_out;
+                       if (current) {
+                               current->next = malloc(sizeof(*current));
+                               if (!current->next)
+                                       goto error_out;
+                               current = current->next;
+                       } else {
+                               first = malloc(sizeof(*first));
+                               if (!first)
+                                       goto error_out;
+                               current = first;
+                       }
+                       current->first = first;
+                       current->next = NULL;
+
+                       memcpy(one_value, linebuf + pos, i - pos);
+                       one_value[i - pos] = '\0';
+
+                       if (sscanf(one_value, "%u", &current->cpu) != 1)
+                               goto error_out;
+
+                       pos = i + 1;
+               }
+       }
+
+       return first;
+
+ error_out:
+       while (first) {
+               current = first->next;
+               free(first);
+               first = current;
+       }
+       return NULL;
+}
+
+struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(unsigned int cpu)
+{
+       return sysfs_get_cpu_list(cpu, "affected_cpus");
+}
+
+struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(unsigned int cpu)
+{
+       return sysfs_get_cpu_list(cpu, "related_cpus");
+}
+
+struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
+                                       unsigned long long *total_time) {
+       struct cpufreq_stats *first = NULL;
+       struct cpufreq_stats *current = NULL;
+       char one_value[SYSFS_PATH_MAX];
+       char linebuf[MAX_LINE_LEN];
+       unsigned int pos, i;
+       unsigned int len;
+
+       len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state",
+                               linebuf, sizeof(linebuf));
+       if (len == 0)
+               return NULL;
+
+       *total_time = 0;
+       pos = 0;
+       for (i = 0; i < len; i++) {
+               if (i == strlen(linebuf) || linebuf[i] == '\n') {
+                       if (i - pos < 2)
+                               continue;
+                       if ((i - pos) >= SYSFS_PATH_MAX)
+                               goto error_out;
+                       if (current) {
+                               current->next = malloc(sizeof(*current));
+                               if (!current->next)
+                                       goto error_out;
+                               current = current->next;
+                       } else {
+                               first = malloc(sizeof(*first));
+                               if (!first)
+                                       goto error_out;
+                               current = first;
+                       }
+                       current->first = first;
+                       current->next = NULL;
+
+                       memcpy(one_value, linebuf + pos, i - pos);
+                       one_value[i - pos] = '\0';
+                       if (sscanf(one_value, "%lu %llu",
+                                       &current->frequency,
+                                       &current->time_in_state) != 2)
+                               goto error_out;
+
+                       *total_time = *total_time + current->time_in_state;
+                       pos = i + 1;
+               }
+       }
+
+       return first;
+
+ error_out:
+       while (first) {
+               current = first->next;
+               free(first);
+               first = current;
+       }
+       return NULL;
+}
+
+unsigned long sysfs_get_freq_transitions(unsigned int cpu)
+{
+       return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
+}
+
+static int verify_gov(char *new_gov, char *passed_gov)
+{
+       unsigned int i, j = 0;
+
+       if (!passed_gov || (strlen(passed_gov) > 19))
+               return -EINVAL;
+
+       strncpy(new_gov, passed_gov, 20);
+       for (i = 0; i < 20; i++) {
+               if (j) {
+                       new_gov[i] = '\0';
+                       continue;
+               }
+               if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z'))
+                       continue;
+
+               if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z'))
+                       continue;
+
+               if (new_gov[i] == '-')
+                       continue;
+
+               if (new_gov[i] == '_')
+                       continue;
+
+               if (new_gov[i] == '\0') {
+                       j = 1;
+                       continue;
+               }
+               return -EINVAL;
+       }
+       new_gov[19] = '\0';
+       return 0;
+}
+
+int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor)
+{
+       char new_gov[SYSFS_PATH_MAX];
+
+       if (!governor)
+               return -EINVAL;
+
+       if (verify_gov(new_gov, governor))
+               return -EINVAL;
+
+       return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
+                                            new_gov, strlen(new_gov));
+};
+
+int sysfs_modify_freq_policy_max(unsigned int cpu, unsigned long max_freq)
+{
+       char value[SYSFS_PATH_MAX];
+
+       snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
+
+       return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
+                                            value, strlen(value));
+};
+
+
+int sysfs_modify_freq_policy_min(unsigned int cpu, unsigned long min_freq)
+{
+       char value[SYSFS_PATH_MAX];
+
+       snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
+
+       return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ,
+                                            value, strlen(value));
+};
+
+
+int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy)
+{
+       char min[SYSFS_PATH_MAX];
+       char max[SYSFS_PATH_MAX];
+       char gov[SYSFS_PATH_MAX];
+       int ret;
+       unsigned long old_min;
+       int write_max_first;
+
+       if (!policy || !(policy->governor))
+               return -EINVAL;
+
+       if (policy->max < policy->min)
+               return -EINVAL;
+
+       if (verify_gov(gov, policy->governor))
+               return -EINVAL;
+
+       snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
+       snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
+
+       old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
+       write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
+
+       if (write_max_first) {
+               ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
+                                                   max, strlen(max));
+               if (ret)
+                       return ret;
+       }
+
+       ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min,
+                                           strlen(min));
+       if (ret)
+               return ret;
+
+       if (!write_max_first) {
+               ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
+                                                   max, strlen(max));
+               if (ret)
+                       return ret;
+       }
+
+       return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
+                                            gov, strlen(gov));
+}
+
+int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency)
+{
+       struct cpufreq_policy *pol = sysfs_get_freq_policy(cpu);
+       char userspace_gov[] = "userspace";
+       char freq[SYSFS_PATH_MAX];
+       int ret;
+
+       if (!pol)
+               return -ENODEV;
+
+       if (strncmp(pol->governor, userspace_gov, 9) != 0) {
+               ret = sysfs_modify_freq_policy_governor(cpu, userspace_gov);
+               if (ret) {
+                       cpufreq_put_policy(pol);
+                       return ret;
+               }
+       }
+
+       cpufreq_put_policy(pol);
+
+       snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
+
+       return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED,
+                                            freq, strlen(freq));
+}
+
+/* CPUFREQ sysfs access **************************************************/
+
+/* General sysfs access **************************************************/
+int sysfs_cpu_exists(unsigned int cpu)
+{
+       char file[SYSFS_PATH_MAX];
+       struct stat statbuf;
+
+       snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/", cpu);
+
+       if (stat(file, &statbuf) != 0)
+               return -ENOSYS;
+
+       return S_ISDIR(statbuf.st_mode) ? 0 : -ENOSYS;
+}
+
+/* General sysfs access **************************************************/
diff --git a/tools/power/cpupower/lib/sysfs.h b/tools/power/cpupower/lib/sysfs.h
new file mode 100644 (file)
index 0000000..c76a5e0
--- /dev/null
@@ -0,0 +1,31 @@
+/* General */
+extern unsigned int sysfs_cpu_exists(unsigned int cpu);
+
+/* CPUfreq */
+extern unsigned long sysfs_get_freq_kernel(unsigned int cpu);
+extern unsigned long sysfs_get_freq_hardware(unsigned int cpu);
+extern unsigned long sysfs_get_freq_transition_latency(unsigned int cpu);
+extern int sysfs_get_freq_hardware_limits(unsigned int cpu,
+                                       unsigned long *min, unsigned long *max);
+extern char *sysfs_get_freq_driver(unsigned int cpu);
+extern struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu);
+extern struct cpufreq_available_governors *sysfs_get_freq_available_governors(
+       unsigned int cpu);
+extern struct cpufreq_available_frequencies *sysfs_get_available_frequencies(
+       unsigned int cpu);
+extern struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(
+       unsigned int cpu);
+extern struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(
+       unsigned int cpu);
+extern struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
+                                               unsigned long long *total_time);
+extern unsigned long sysfs_get_freq_transitions(unsigned int cpu);
+extern int sysfs_set_freq_policy(unsigned int cpu,
+                               struct cpufreq_policy *policy);
+extern int sysfs_modify_freq_policy_min(unsigned int cpu,
+                                       unsigned long min_freq);
+extern int sysfs_modify_freq_policy_max(unsigned int cpu,
+                                       unsigned long max_freq);
+extern int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor);
+extern int sysfs_set_frequency(unsigned int cpu,
+                       unsigned long target_frequency);
diff --git a/tools/power/cpupower/man/cpupower-frequency-info.1 b/tools/power/cpupower/man/cpupower-frequency-info.1
new file mode 100644 (file)
index 0000000..3194811
--- /dev/null
@@ -0,0 +1,76 @@
+.TH "cpufreq-info" "1" "0.1" "Mattia Dongili" ""
+.SH "NAME"
+.LP 
+cpufreq\-info \- Utility to retrieve cpufreq kernel information
+.SH "SYNTAX"
+.LP 
+cpufreq\-info [\fIoptions\fP]
+.SH "DESCRIPTION"
+.LP 
+A small tool which prints out cpufreq information helpful to developers and interested users.
+.SH "OPTIONS"
+.LP 
+.TP  
+\fB\-e\fR \fB\-\-debug\fR
+Prints out debug information.
+.TP  
+\fB\-f\fR \fB\-\-freq\fR
+Get frequency the CPU currently runs at, according to the cpufreq core.
+.TP  
+\fB\-w\fR \fB\-\-hwfreq\fR
+Get frequency the CPU currently runs at, by reading it from hardware (only available to root).
+.TP  
+\fB\-l\fR \fB\-\-hwlimits\fR
+Determine the minimum and maximum CPU frequency allowed.
+.TP  
+\fB\-d\fR \fB\-\-driver\fR
+Determines the used cpufreq kernel driver.
+.TP  
+\fB\-p\fR \fB\-\-policy\fR
+Gets the currently used cpufreq policy.
+.TP  
+\fB\-g\fR \fB\-\-governors\fR
+Determines available cpufreq governors.
+.TP  
+\fB\-a\fR \fB\-\-related\-cpus\fR
+Determines which CPUs run at the same hardware frequency.
+.TP  
+\fB\-a\fR \fB\-\-affected\-cpus\fR
+Determines which CPUs need to have their frequency coordinated by software.
+.TP  
+\fB\-s\fR \fB\-\-stats\fR
+Shows cpufreq statistics if available.
+.TP  
+\fB\-y\fR \fB\-\-latency\fR
+Determines the maximum latency on CPU frequency changes.
+.TP  
+\fB\-o\fR \fB\-\-proc\fR
+Prints out information like provided by the /proc/cpufreq interface in 2.4. and early 2.6. kernels.
+.TP  
+\fB\-m\fR \fB\-\-human\fR
+human\-readable output for the \-f, \-w, \-s and \-y parameters.
+.TP  
+\fB\-h\fR \fB\-\-help\fR
+Prints out the help screen.
+.SH "REMARKS"
+.LP 
+By default only values of core zero are displayed. How to display settings of
+other cores is described in the cpupower(1) manpage in the \-\-cpu option section.
+.LP 
+You can't specify more than one of the output specific options \-o \-e \-a \-g \-p \-d \-l \-w \-f \-y.
+.LP 
+You also can't specify the \-o option combined with the \-c option.
+.SH "FILES"
+.nf 
+\fI/sys/devices/system/cpu/cpu*/cpufreq/\fP  
+\fI/proc/cpufreq\fP (deprecated) 
+\fI/proc/sys/cpu/\fP (deprecated)
+.fi 
+.SH "AUTHORS"
+.nf
+Dominik Brodowski <linux@brodo.de> \- author 
+Mattia Dongili<malattia@gmail.com> \- first autolibtoolization
+.fi
+.SH "SEE ALSO"
+.LP 
+cpupower\-frequency\-set(1), cpupower(1)
diff --git a/tools/power/cpupower/man/cpupower-frequency-set.1 b/tools/power/cpupower/man/cpupower-frequency-set.1
new file mode 100644 (file)
index 0000000..26e3e13
--- /dev/null
@@ -0,0 +1,54 @@
+.TH "cpufreq-set" "1" "0.1" "Mattia Dongili" ""
+.SH "NAME"
+.LP 
+cpufreq\-set \- A small tool which allows to modify cpufreq settings.
+.SH "SYNTAX"
+.LP 
+cpufreq\-set [\fIoptions\fP]
+.SH "DESCRIPTION"
+.LP 
+cpufreq\-set allows you to modify cpufreq settings without having to type e.g. "/sys/devices/system/cpu/cpu0/cpufreq/scaling_set_speed" all the time.
+.SH "OPTIONS"
+.LP 
+.TP 
+\fB\-d\fR \fB\-\-min\fR <FREQ>
+new minimum CPU frequency the governor may select.
+.TP 
+\fB\-u\fR \fB\-\-max\fR <FREQ>
+new maximum CPU frequency the governor may select.
+.TP 
+\fB\-g\fR \fB\-\-governor\fR <GOV>
+new cpufreq governor.
+.TP 
+\fB\-f\fR \fB\-\-freq\fR <FREQ>
+specific frequency to be set. Requires userspace governor to be available and loaded.
+.TP 
+\fB\-r\fR \fB\-\-related\fR
+modify all hardware-related CPUs at the same time
+.TP 
+\fB\-h\fR \fB\-\-help\fR
+Prints out the help screen.
+.SH "REMARKS"
+.LP 
+By default values are applied on all cores. How to modify single core
+configurations is described in the cpupower(1) manpage in the \-\-cpu option section.
+.LP 
+The \-f FREQ, \-\-freq FREQ parameter cannot be combined with any other parameter.
+.LP 
+FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz by postfixing the value with the wanted unit name, without any space (frequency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).
+.LP 
+On Linux kernels up to 2.6.29, the \-r or \-\-related parameter is ignored.
+.SH "FILES" 
+.nf
+\fI/sys/devices/system/cpu/cpu*/cpufreq/\fP  
+\fI/proc/cpufreq\fP (deprecated) 
+\fI/proc/sys/cpu/\fP (deprecated)
+.fi 
+.SH "AUTHORS"
+.nf 
+Dominik Brodowski <linux@brodo.de> \- author 
+Mattia Dongili<malattia@gmail.com> \- first autolibtoolization
+.fi
+.SH "SEE ALSO"
+.LP 
+cpupower\-frequency\-info(1), cpupower(1)
diff --git a/tools/power/cpupower/man/cpupower-info.1 b/tools/power/cpupower/man/cpupower-info.1
new file mode 100644 (file)
index 0000000..58e2119
--- /dev/null
@@ -0,0 +1,19 @@
+.TH CPUPOWER\-INFO "1" "22/02/2011" "" "cpupower Manual"
+.SH NAME
+cpupower\-info \- Shows processor power related kernel or hardware configurations
+.SH SYNOPSIS
+.ft B
+.B cpupower info [ \-b ] [ \-s ] [ \-m ]
+
+.SH DESCRIPTION
+\fBcpupower info \fP shows kernel configurations or processor hardware
+registers affecting processor power saving policies.
+
+Some options are platform wide, some affect single cores. By default values
+of core zero are displayed only. cpupower --cpu all cpuinfo will show the
+settings of all cores, see cpupower(1) how to choose specific cores.
+
+.SH "SEE ALSO"
+Options are described in detail in:
+
+cpupower(1), cpupower-set(1)
diff --git a/tools/power/cpupower/man/cpupower-monitor.1 b/tools/power/cpupower/man/cpupower-monitor.1
new file mode 100644 (file)
index 0000000..d5cfa26
--- /dev/null
@@ -0,0 +1,179 @@
+.TH CPUPOWER\-MONITOR "1" "22/02/2011" "" "cpupower Manual"
+.SH NAME
+cpupower\-monitor \- Report processor frequency and idle statistics
+.SH SYNOPSIS
+.ft B
+.B cpupower monitor
+.RB "\-l"
+
+.B cpupower monitor
+.RB [ "\-m <mon1>," [ "<mon2>,..." ] ]
+.RB [ "\-i seconds" ]
+.br
+.B cpupower monitor
+.RB [ "\-m <mon1>," [ "<mon2>,..." ] ]
+.RB command
+.br
+.SH DESCRIPTION
+\fBcpupower-monitor \fP reports processor topology, frequency and idle power
+state statistics. Either \fBcommand\fP is forked and
+statistics are printed upon its completion, or statistics are printed periodically.
+
+\fBcpupower-monitor \fP implements independent processor sleep state and
+frequency counters. Some are retrieved from kernel statistics, some are
+directly reading out hardware registers. Use \-l to get an overview which are
+supported on your system.
+
+.SH Options
+.PP
+\-l
+.RS 4
+List available monitors on your system. Additional details about each monitor
+are shown:
+.RS 2
+.IP \(bu
+The name in quotation marks which can be passed to the \-m parameter.
+.IP \(bu
+The number of different counters the monitor supports in brackets.
+.IP \(bu
+The amount of time in seconds the counters might overflow, due to
+implementation constraints.
+.IP \(bu
+The name and a description of each counter and its processor hierarchy level
+coverage in square brackets:
+.RS 4
+.IP \(bu
+[T] \-> Thread
+.IP \(bu
+[C] \-> Core
+.IP \(bu
+[P] \-> Processor Package (Socket)
+.IP \(bu
+[M] \-> Machine/Platform wide counter
+.RE
+.RE
+.RE
+.PP
+\-m <mon1>,<mon2>,...
+.RS 4
+Only display specific monitors. Use the monitor string(s) provided by \-l option.
+.RE
+.PP
+\-i seconds
+.RS 4
+Measure intervall.
+.RE
+.PP
+command
+.RS 4
+Measure idle and frequency characteristics of an arbitrary command/workload.
+The executable \fBcommand\fP is forked and upon its exit, statistics gathered since it was
+forked are displayed.
+.RE
+.PP
+\-v
+.RS 4
+Increase verbosity if the binary was compiled with the DEBUG option set.
+.RE
+
+.SH MONITOR DESCRIPTIONS
+.SS "Idle_Stats"
+Shows statistics of the cpuidle kernel subsystem. Values are retrieved from
+/sys/devices/system/cpu/cpu*/cpuidle/state*/.
+The kernel updates these values every time an idle state is entered or
+left. Therefore there can be some inaccuracy when cores are in an idle
+state for some time when the measure starts or ends. In worst case it can happen
+that one core stayed in an idle state for the whole measure time and the idle
+state usage time as exported by the kernel did not get updated. In this case
+a state residency of 0 percent is shown while it was 100.
+
+.SS "Mperf"
+The name comes from the aperf/mperf (average and maximum) MSR registers used
+which are available on recent X86 processors. It shows the average frequency
+(including boost frequencies).
+The fact that on all recent hardware the mperf timer stops ticking in any idle
+state it is also used to show C0 (processor is active) and Cx (processor is in
+any sleep state) times. These counters do not have the inaccuracy restrictions
+the "Idle_Stats" counters may show.
+May work poorly on Linux-2.6.20 through 2.6.29, as the \fBacpi-cpufreq \fP
+kernel frequency driver periodically cleared aperf/mperf registers in those
+kernels.
+
+.SS "Nehalem" "SandyBridge"
+Intel Core and Package sleep state counters.
+Threads (hyperthreaded cores) may not be able to enter deeper core states if
+its sibling is utilized.
+Deepest package sleep states may in reality show up as machine/platform wide
+sleep states and can only be entered if all cores are idle. Look up Intel
+manuals (some are provided in the References section) for further details.
+
+.SS "Ontario" "Liano"
+AMD laptop and desktop processor (family 12h and 14h) sleep state counters.
+The registers are accessed via PCI and therefore can still be read out while
+cores have been offlined.
+
+There is one special counter: NBP1 (North Bridge P1).
+This one always returns 0 or 1, depending on whether the North Bridge P1
+power state got entered at least once during measure time.
+Being able to enter NBP1 state also depends on graphics power management.
+Therefore this counter can be used to verify whether the graphics' driver
+power management is working as expected.
+
+.SH EXAMPLES
+
+cpupower monitor -l" may show:
+.RS 4
+Monitor "Mperf" (3 states) \- Might overflow after 922000000 s
+
+   ...
+
+Monitor "Idle_Stats" (3 states) \- Might overflow after 4294967295 s
+
+   ...
+
+.RE
+cpupower monitor \-m "Idle_Stats,Mperf" scp /tmp/test /nfs/tmp
+
+Monitor the scp command, show both Mperf and Idle_Stats states counter
+statistics, but in exchanged order.
+
+
+
+.RE
+Be careful that the typical command to fully utilize one CPU by doing:
+
+cpupower monitor cat /dev/zero >/dev/null
+
+Does not work as expected, because the measured output is redirected to
+/dev/null. This could get workarounded by putting the line into an own, tiny
+shell script. Hit CTRL\-c to terminate the command and get the measure output
+displayed.
+
+.SH REFERENCES
+"BIOS and Kernel Developer’s Guide (BKDG) for AMD Family 14h Processors"
+http://support.amd.com/us/Processor_TechDocs/43170.pdf
+
+"Intel® Turbo Boost Technology
+in Intel® Core™ Microarchitecture (Nehalem) Based Processors"
+http://download.intel.com/design/processor/applnots/320354.pdf
+
+"Intel® 64 and IA-32 Architectures Software Developer's Manual
+Volume 3B: System Programming Guide"
+http://www.intel.com/products/processor/manuals
+
+.SH FILES
+.ta
+.nf
+/dev/cpu/*/msr
+/sys/devices/system/cpu/cpu*/cpuidle/state*/.
+.fi
+
+.SH "SEE ALSO"
+powertop(8), msr(4), vmstat(8)
+.PP
+.SH AUTHORS
+.nf
+Written by Thomas Renninger <trenn@suse.de>
+
+Nehalem, SandyBridge monitors and command passing
+based on turbostat.8 from Len Brown <len.brown@intel.com>
diff --git a/tools/power/cpupower/man/cpupower-set.1 b/tools/power/cpupower/man/cpupower-set.1
new file mode 100644 (file)
index 0000000..c4954a9
--- /dev/null
@@ -0,0 +1,103 @@
+.TH CPUPOWER\-SET "1" "22/02/2011" "" "cpupower Manual"
+.SH NAME
+cpupower\-set \- Set processor power related kernel or hardware configurations
+.SH SYNOPSIS
+.ft B
+.B cpupower set [ \-b VAL ] [ \-s VAL ] [ \-m VAL ]
+
+
+.SH DESCRIPTION
+\fBcpupower set \fP sets kernel configurations or directly accesses hardware
+registers affecting processor power saving policies.
+
+Some options are platform wide, some affect single cores. By default values
+are applied on all cores. How to modify single core configurations is
+described in the cpupower(1) manpage in the \-\-cpu option section. Whether an
+option affects the whole system or can be applied to individual cores is
+described in the Options sections.
+
+Use \fBcpupower info \fP to read out current settings and whether they are
+supported on the system at all.
+
+.SH Options
+.PP
+\-\-perf-bias, \-b
+.RS 4
+Sets a register on supported Intel processore which allows software to convey
+its policy for the relative importance of performance versus energy savings to
+the  processor.
+
+The range of valid numbers is 0-15, where 0 is maximum
+performance and 15 is maximum energy efficiency.
+
+The processor uses this information in model-specific ways
+when it must select trade-offs between performance and
+energy efficiency.
+
+This policy hint does not supersede Processor Performance states
+(P-states) or CPU Idle power states (C-states), but allows
+software to have influence where it would otherwise be unable
+to express a preference.
+
+For example, this setting may tell the hardware how
+aggressively or conservatively to control frequency
+in the "turbo range" above the explicitly OS-controlled
+P-state frequency range.  It may also tell the hardware
+how aggressively it should enter the OS requested C-states.
+
+This option can be applied to individual cores only via the \-\-cpu option,
+cpupower(1).
+
+Setting the performance bias value on one CPU can modify the setting on
+related CPUs as well (for example all CPUs on one socket), because of
+hardware restrictions.
+Use \fBcpupower -c all info -b\fP to verify.
+
+This options needs the msr kernel driver (CONFIG_X86_MSR) loaded.
+.RE
+.PP
+\-\-sched\-mc,  \-m [ VAL ]
+.RE
+\-\-sched\-smt, \-s [ VAL ]
+.RS 4
+\-\-sched\-mc utilizes cores in one processor package/socket first before
+processes are scheduled to other processor packages/sockets.
+
+\-\-sched\-smt utilizes thread siblings of one processor core first before
+processes are scheduled to other cores.
+
+The impact on power consumption and performance (positiv or negativ) heavily
+depends on processor support for deep sleep states, frequency scaling and
+frequency boost modes and their dependencies between other thread siblings
+and processor cores.
+
+Taken over from kernel documentation:
+
+Adjust the kernel's multi-core scheduler support.
+
+Possible values are:
+.RS 2
+0 - No power saving load balance (default value)
+
+1 - Fill one thread/core/package first for long running threads
+
+2 - Also bias task wakeups to semi-idle cpu package for power
+savings
+.RE
+
+sched_mc_power_savings is dependent upon SCHED_MC, which is
+itself architecture dependent.
+
+sched_smt_power_savings is dependent upon SCHED_SMT, which
+is itself architecture dependent.
+
+The two files are independent of each other. It is possible
+that one file may be present without the other.
+
+.SH "SEE ALSO"
+cpupower-info(1), cpupower-monitor(1), powertop(1)
+.PP
+.SH AUTHORS
+.nf
+\-\-perf\-bias parts written by Len Brown <len.brown@intel.com>
+Thomas Renninger <trenn@suse.de>
diff --git a/tools/power/cpupower/man/cpupower.1 b/tools/power/cpupower/man/cpupower.1
new file mode 100644 (file)
index 0000000..78c20fe
--- /dev/null
@@ -0,0 +1,72 @@
+.TH CPUPOWER "1" "07/03/2011" "" "cpupower Manual"
+.SH NAME
+cpupower \- Shows and sets processor power related values
+.SH SYNOPSIS
+.ft B
+.B cpupower [ \-c cpulist ] subcommand [ARGS]
+
+.B cpupower \-v|\-\-version
+
+.B cpupower \-h|\-\-help
+
+.SH DESCRIPTION
+\fBcpupower \fP is a collection of tools to examine and tune power saving
+related features of your processor.
+
+The manpages of the subcommands (cpupower\-<subcommand>(1)) provide detailed
+descriptions of supported features. Run \fBcpupower help\fP to get an overview
+of supported subcommands.
+
+.SH Options
+.PP
+\-\-help, \-h
+.RS 4
+Shows supported subcommands and general usage.
+.RE
+.PP
+\-\-cpu cpulist,  \-c cpulist
+.RS 4
+Only show or set values for specific cores.
+This option is not supported by all subcommands, details can be found in the
+manpages of the subcommands.
+
+Some subcommands access all cores (typically the *\-set commands), some only
+the first core (typically the *\-info commands) by default.
+
+The syntax for <cpulist> is based on how the kernel exports CPU bitmasks via
+sysfs files. Some examples:
+.RS 4
+.TP 16
+Input
+Equivalent to
+.TP
+all
+all cores
+.TP
+0\-3
+0,1,2,3
+.TP
+0\-7:2
+0,2,4,6
+.TP
+1,3,5-7
+1,3,5,6,7
+.TP
+0\-3:2,8\-15:4
+0,2,8,12       
+.RE
+.RE
+.PP
+\-\-version,  \-v
+.RS 4
+Print the package name and version number.
+
+.SH "SEE ALSO"
+cpupower-set(1), cpupower-info(1), cpupower-idle(1),
+cpupower-frequency-set(1), cpupower-frequency-info(1), cpupower-monitor(1),
+powertop(1)
+.PP
+.SH AUTHORS
+.nf
+\-\-perf\-bias parts written by Len Brown <len.brown@intel.com>
+Thomas Renninger <trenn@suse.de>
diff --git a/tools/power/cpupower/po/cs.po b/tools/power/cpupower/po/cs.po
new file mode 100644 (file)
index 0000000..cb22c45
--- /dev/null
@@ -0,0 +1,944 @@
+# translation of cs.po to Czech
+# Czech translation for cpufrequtils package
+# Czech messages for cpufrequtils.
+# Copyright (C) 2007 kavol
+# This file is distributed under the same license as the cpufrequtils package.
+#
+# Karel Volný <kavol@seznam.cz>, 2007, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: cs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-03-08 17:03+0100\n"
+"PO-Revision-Date: 2008-06-11 16:26+0200\n"
+"Last-Translator: Karel Volný <kavol@seznam.cz>\n"
+"Language-Team: Czech <diskuze@lists.l10n.cz>\n"
+"Language: cs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms:  nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: utils/idle_monitor/nhm_idle.c:36
+msgid "Processor Core C3"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:43
+msgid "Processor Core C6"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:51
+msgid "Processor Package C3"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
+msgid "Processor Package C6"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:33
+msgid "Processor Core C7"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:40
+msgid "Processor Package C2"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:47
+msgid "Processor Package C7"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:56
+msgid "Package in sleep state (PC1 or deeper)"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:63
+msgid "Processor Package C1"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:77
+msgid "North Bridge P1 boolean counter (returns 0 or 1)"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:35
+msgid "Processor Core not idle"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:42
+msgid "Processor Core in an idle state"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:50
+msgid "Average Frequency (including boost) in MHz"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:66
+#, c-format
+msgid ""
+"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
+"interval_sec | -c command ...]\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:69
+#, c-format
+msgid ""
+"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
+"interval_sec | -c command ...]\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:71
+#, c-format
+msgid "\t -v: be more verbose\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:73
+#, c-format
+msgid "\t -h: print this help\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:74
+#, c-format
+msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:75
+#, c-format
+msgid "\t -t: show CPU topology/hierarchy\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:76
+#, c-format
+msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:77
+#, c-format
+msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:79
+#, c-format
+msgid ""
+"only one of: -t, -l, -m are allowed\n"
+"If none of them is passed,"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:80
+#, c-format
+msgid " all supported monitors are shown\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:197
+#, c-format
+msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:207
+#, c-format
+msgid " *is offline\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:236
+#, c-format
+msgid "%s: max monitor name length (%d) exceeded\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:250
+#, c-format
+msgid "No matching monitor found in %s, try -l option\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:266
+#, c-format
+msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:319
+#, c-format
+msgid "%s took %.5f seconds and exited with status %d\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:406
+#, c-format
+msgid "Cannot read number of available processors\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:417
+#, c-format
+msgid "Available monitor %s needs root access\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:428
+#, c-format
+msgid "No HW Cstate monitors found\n"
+msgstr ""
+
+#: utils/cpupower.c:78
+#, c-format
+msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
+msgstr ""
+
+#: utils/cpupower.c:79
+#, c-format
+msgid "cpupower --version\n"
+msgstr ""
+
+#: utils/cpupower.c:80
+#, c-format
+msgid "Supported subcommands are:\n"
+msgstr ""
+
+#: utils/cpupower.c:83
+#, c-format
+msgid ""
+"\n"
+"Some subcommands can make use of the -c cpulist option.\n"
+msgstr ""
+
+#: utils/cpupower.c:84
+#, c-format
+msgid "Look at the general cpupower manpage how to use it\n"
+msgstr ""
+
+#: utils/cpupower.c:85
+#, c-format
+msgid "and read up the subcommand's manpage whether it is supported.\n"
+msgstr ""
+
+#: utils/cpupower.c:86
+#, c-format
+msgid ""
+"\n"
+"Use cpupower help subcommand for getting help for above subcommands.\n"
+msgstr ""
+
+#: utils/cpupower.c:91
+#, c-format
+msgid "Report errors and bugs to %s, please.\n"
+msgstr ""
+"Chyby v programu prosím hlaste na %s (anglicky).\n"
+"Chyby v překladu prosím hlaste na kavol@seznam.cz (česky ;-)\n"
+
+#: utils/cpupower.c:114
+#, c-format
+msgid "Error parsing cpu list\n"
+msgstr ""
+
+#: utils/cpupower.c:172
+#, c-format
+msgid "Subcommand %s needs root privileges\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:31
+#, c-format
+msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
+msgstr "Nelze zjistit počet CPU (%s: %s), předpokládá se 1.\n"
+
+#: utils/cpufreq-info.c:63
+#, c-format
+msgid ""
+"          minimum CPU frequency  -  maximum CPU frequency  -  governor\n"
+msgstr ""
+"         minimální frekvence CPU - maximální frekvence CPU -  regulátor\n"
+
+#: utils/cpufreq-info.c:151
+#, c-format
+msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
+msgstr ""
+
+#. P state changes via MSR are identified via cpuid 80000007
+#. on Intel and AMD, but we assume boost capable machines can do that
+#. if (cpuid_eax(0x80000000) >= 0x80000007
+#. && (cpuid_edx(0x80000007) & (1 << 7)))
+#.
+#: utils/cpufreq-info.c:161
+#, c-format
+msgid "  boost state support: \n"
+msgstr ""
+
+#: utils/cpufreq-info.c:163
+#, c-format
+msgid "    Supported: %s\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
+msgid "yes"
+msgstr ""
+
+#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
+msgid "no"
+msgstr ""
+
+#: utils/cpufreq-info.c:164
+#, fuzzy, c-format
+msgid "    Active: %s\n"
+msgstr "  ovladač: %s\n"
+
+#: utils/cpufreq-info.c:177
+#, c-format
+msgid "    Boost States: %d\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:178
+#, c-format
+msgid "    Total States: %d\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:181
+#, c-format
+msgid "    Pstate-Pb%d: %luMHz (boost state)\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:184
+#, c-format
+msgid "    Pstate-P%d:  %luMHz\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:211
+#, c-format
+msgid "  no or unknown cpufreq driver is active on this CPU\n"
+msgstr "  pro tento CPU není aktivní žádný známý ovladač cpufreq\n"
+
+#: utils/cpufreq-info.c:213
+#, c-format
+msgid "  driver: %s\n"
+msgstr "  ovladač: %s\n"
+
+#: utils/cpufreq-info.c:219
+#, fuzzy, c-format
+msgid "  CPUs which run at the same hardware frequency: "
+msgstr "  CPU, které musí měnit frekvenci zároveň: "
+
+#: utils/cpufreq-info.c:230
+#, fuzzy, c-format
+msgid "  CPUs which need to have their frequency coordinated by software: "
+msgstr "  CPU, které musí měnit frekvenci zároveň: "
+
+#: utils/cpufreq-info.c:241
+#, c-format
+msgid "  maximum transition latency: "
+msgstr ""
+
+#: utils/cpufreq-info.c:247
+#, c-format
+msgid "  hardware limits: "
+msgstr "  hardwarové meze: "
+
+#: utils/cpufreq-info.c:256
+#, c-format
+msgid "  available frequency steps: "
+msgstr "  dostupné frekvence: "
+
+#: utils/cpufreq-info.c:269
+#, c-format
+msgid "  available cpufreq governors: "
+msgstr "  dostupné regulátory: "
+
+#: utils/cpufreq-info.c:280
+#, c-format
+msgid "  current policy: frequency should be within "
+msgstr "  současná taktika: frekvence by měla být mezi "
+
+#: utils/cpufreq-info.c:282
+#, c-format
+msgid " and "
+msgstr " a "
+
+#: utils/cpufreq-info.c:286
+#, c-format
+msgid ""
+"The governor \"%s\" may decide which speed to use\n"
+"                  within this range.\n"
+msgstr ""
+"  Regulátor \"%s\" může rozhodnout jakou frekvenci použít\n"
+"                    v těchto mezích.\n"
+
+#: utils/cpufreq-info.c:293
+#, c-format
+msgid "  current CPU frequency is "
+msgstr "  současná frekvence CPU je "
+
+#: utils/cpufreq-info.c:296
+#, c-format
+msgid " (asserted by call to hardware)"
+msgstr "  (zjištěno hardwarovým voláním)"
+
+#: utils/cpufreq-info.c:304
+#, c-format
+msgid "  cpufreq stats: "
+msgstr "  statistika cpufreq: "
+
+#: utils/cpufreq-info.c:472
+#, fuzzy, c-format
+msgid "Usage: cpupower freqinfo [options]\n"
+msgstr "Užití: cpufreq-info [přepínače]\n"
+
+#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
+#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
+#, c-format
+msgid "Options:\n"
+msgstr "Přepínače:\n"
+
+#: utils/cpufreq-info.c:474
+#, fuzzy, c-format
+msgid "  -e, --debug          Prints out debug information [default]\n"
+msgstr "  -e, --debug          Vypíše ladicí informace\n"
+
+#: utils/cpufreq-info.c:475
+#, c-format
+msgid ""
+"  -f, --freq           Get frequency the CPU currently runs at, according\n"
+"                       to the cpufreq core *\n"
+msgstr ""
+"  -f, --freq           Zjistí aktuální frekvenci, na které CPU běží\n"
+"                       podle cpufreq *\n"
+
+#: utils/cpufreq-info.c:477
+#, c-format
+msgid ""
+"  -w, --hwfreq         Get frequency the CPU currently runs at, by reading\n"
+"                       it from hardware (only available to root) *\n"
+msgstr ""
+"  -w, --hwfreq         Zjistí aktuální frekvenci, na které CPU běží\n"
+"                       z hardware (dostupné jen uživateli root) *\n"
+
+#: utils/cpufreq-info.c:479
+#, c-format
+msgid ""
+"  -l, --hwlimits       Determine the minimum and maximum CPU frequency "
+"allowed *\n"
+msgstr ""
+"  -l, --hwlimits       Zjistí minimální a maximální dostupnou frekvenci CPU "
+"*\n"
+
+#: utils/cpufreq-info.c:480
+#, c-format
+msgid "  -d, --driver         Determines the used cpufreq kernel driver *\n"
+msgstr "  -d, --driver         Zjistí aktivní ovladač cpufreq *\n"
+
+#: utils/cpufreq-info.c:481
+#, c-format
+msgid "  -p, --policy         Gets the currently used cpufreq policy *\n"
+msgstr "  -p, --policy         Zjistí aktuální taktiku cpufreq *\n"
+
+#: utils/cpufreq-info.c:482
+#, c-format
+msgid "  -g, --governors      Determines available cpufreq governors *\n"
+msgstr "  -g, --governors      Zjistí dostupné regulátory cpufreq *\n"
+
+#: utils/cpufreq-info.c:483
+#, fuzzy, c-format
+msgid ""
+"  -r, --related-cpus   Determines which CPUs run at the same hardware "
+"frequency *\n"
+msgstr ""
+"  -a, --affected-cpus  Zjistí, které CPU musí měnit frekvenci zároveň *\n"
+
+#: utils/cpufreq-info.c:484
+#, fuzzy, c-format
+msgid ""
+"  -a, --affected-cpus  Determines which CPUs need to have their frequency\n"
+"                       coordinated by software *\n"
+msgstr ""
+"  -a, --affected-cpus  Zjistí, které CPU musí měnit frekvenci zároveň *\n"
+
+#: utils/cpufreq-info.c:486
+#, c-format
+msgid "  -s, --stats          Shows cpufreq statistics if available\n"
+msgstr "  -s, --stats          Zobrazí statistiku cpufreq, je-li dostupná\n"
+
+#: utils/cpufreq-info.c:487
+#, fuzzy, c-format
+msgid ""
+"  -y, --latency        Determines the maximum latency on CPU frequency "
+"changes *\n"
+msgstr ""
+"  -l, --hwlimits       Zjistí minimální a maximální dostupnou frekvenci CPU "
+"*\n"
+
+#: utils/cpufreq-info.c:488
+#, c-format
+msgid "  -b, --boost          Checks for turbo or boost modes  *\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:489
+#, c-format
+msgid ""
+"  -o, --proc           Prints out information like provided by the /proc/"
+"cpufreq\n"
+"                       interface in 2.4. and early 2.6. kernels\n"
+msgstr ""
+"  -o, --proc           Vypíše informace ve formátu, jaký používalo rozhraní\n"
+"                       /proc/cpufreq v kernelech řady 2.4 a časné 2.6\n"
+
+#: utils/cpufreq-info.c:491
+#, fuzzy, c-format
+msgid ""
+"  -m, --human          human-readable output for the -f, -w, -s and -y "
+"parameters\n"
+msgstr ""
+"  -m, --human          Výstup parametrů -f, -w a -s v „lidmi čitelném“ "
+"formátu\n"
+
+#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
+#, c-format
+msgid "  -h, --help           Prints out this screen\n"
+msgstr "  -h, --help           Vypíše tuto nápovědu\n"
+
+#: utils/cpufreq-info.c:495
+#, c-format
+msgid ""
+"If no argument or only the -c, --cpu parameter is given, debug output about\n"
+"cpufreq is printed which is useful e.g. for reporting bugs.\n"
+msgstr ""
+"Není-li zadán žádný parametr nebo je-li zadán pouze přepínač -c, --cpu, "
+"jsou\n"
+"vypsány ladicí informace, což může být užitečné například při hlášení chyb.\n"
+
+#: utils/cpufreq-info.c:497
+#, c-format
+msgid ""
+"For the arguments marked with *, omitting the -c or --cpu argument is\n"
+"equivalent to setting it to zero\n"
+msgstr ""
+"Není-li při použití přepínačů označených * zadán parametr -c nebo --cpu,\n"
+"předpokládá se jeho hodnota 0.\n"
+
+#: utils/cpufreq-info.c:580
+#, c-format
+msgid ""
+"The argument passed to this tool can't be combined with passing a --cpu "
+"argument\n"
+msgstr "Zadaný parametr nemůže být použit zároveň s přepínačem -c nebo --cpu\n"
+
+#: utils/cpufreq-info.c:596
+#, c-format
+msgid ""
+"You can't specify more than one --cpu parameter and/or\n"
+"more than one output-specific argument\n"
+msgstr ""
+"Nelze zadat více než jeden parametr -c nebo --cpu\n"
+"anebo více než jeden parametr určující výstup\n"
+
+#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
+#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
+#, c-format
+msgid "invalid or unknown argument\n"
+msgstr "neplatný nebo neznámý parametr\n"
+
+#: utils/cpufreq-info.c:617
+#, c-format
+msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
+msgstr "nelze analyzovat CPU %d, vypadá to, že není přítomen\n"
+
+#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
+#, c-format
+msgid "analyzing CPU %d:\n"
+msgstr "analyzuji CPU %d:\n"
+
+#: utils/cpufreq-set.c:25
+#, fuzzy, c-format
+msgid "Usage: cpupower frequency-set [options]\n"
+msgstr "Užití: cpufreq-set [přepínače]\n"
+
+#: utils/cpufreq-set.c:27
+#, c-format
+msgid ""
+"  -d FREQ, --min FREQ      new minimum CPU frequency the governor may "
+"select\n"
+msgstr ""
+"  -d FREQ, --min FREQ      Nová nejnižší frekvence, kterou může regulátor "
+"vybrat\n"
+
+#: utils/cpufreq-set.c:28
+#, c-format
+msgid ""
+"  -u FREQ, --max FREQ      new maximum CPU frequency the governor may "
+"select\n"
+msgstr ""
+"  -u FREQ, --max FREQ      Nová nejvyšší frekvence, kterou může regulátor "
+"zvolit\n"
+
+#: utils/cpufreq-set.c:29
+#, c-format
+msgid "  -g GOV, --governor GOV   new cpufreq governor\n"
+msgstr "  -g GOV, --governors GOV  Nový regulátor cpufreq\n"
+
+#: utils/cpufreq-set.c:30
+#, c-format
+msgid ""
+"  -f FREQ, --freq FREQ     specific frequency to be set. Requires userspace\n"
+"                           governor to be available and loaded\n"
+msgstr ""
+"  -f FREQ, --freq FREQ     Frekvence, která má být nastavena. Vyžaduje, aby "
+"byl\n"
+"                           v jádře nahrán regulátor ‚userspace‘.\n"
+
+#: utils/cpufreq-set.c:32
+#, c-format
+msgid "  -r, --related            Switches all hardware-related CPUs\n"
+msgstr ""
+
+#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
+#, fuzzy, c-format
+msgid "  -h, --help               Prints out this screen\n"
+msgstr "  -h, --help           Vypíše tuto nápovědu\n"
+
+#: utils/cpufreq-set.c:35
+#, fuzzy, c-format
+msgid ""
+"Notes:\n"
+"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
+msgstr ""
+"Není-li při použití přepínačů označených * zadán parametr -c nebo --cpu,\n"
+"předpokládá se jeho hodnota 0.\n"
+
+#: utils/cpufreq-set.c:37
+#, fuzzy, c-format
+msgid ""
+"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
+"parameter\n"
+"   except the -c CPU, --cpu CPU parameter\n"
+"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
+"   by postfixing the value with the wanted unit name, without any space\n"
+"   (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
+msgstr ""
+"Poznámky:\n"
+"1. Vynechání parametru -c nebo --cpu je ekvivalentní jeho nastavení na 0\n"
+"2. Přepínač -f nebo --freq nemůže být použit zároveň s žádným jiným vyjma -"
+"c\n"
+"   nebo --cpu\n"
+"3. Frekvence (FREQ) mohou být zadány v Hz, kHz (výchozí), MHz, GHz nebo THz\n"
+"   připojením názvu jednotky bez mezery mezi číslem a jednotkou\n"
+"   (FREQ v kHz =^ Hz * 0,001 = ^ MHz * 1000 =^ GHz * 1000000)\n"
+
+#: utils/cpufreq-set.c:57
+#, c-format
+msgid ""
+"Error setting new values. Common errors:\n"
+"- Do you have proper administration rights? (super-user?)\n"
+"- Is the governor you requested available and modprobed?\n"
+"- Trying to set an invalid policy?\n"
+"- Trying to set a specific frequency, but userspace governor is not "
+"available,\n"
+"   for example because of hardware which cannot be set to a specific "
+"frequency\n"
+"   or because the userspace governor isn't loaded?\n"
+msgstr ""
+"Chyba při nastavování nových hodnot. Obvyklé problémy:\n"
+"- Máte patřičná administrátorská práva? (root?)\n"
+"- Je požadovaný regulátor dostupný v jádře? (modprobe?)\n"
+"- Snažíte se nastavit neplatnou taktiku?\n"
+"- Snažíte se nastavit určitou frekvenci, ale není dostupný\n"
+"  regulátor ‚userspace‘, například protože není nahrán v jádře,\n"
+"  nebo nelze na tomto hardware nastavit určitou frekvenci?\n"
+
+#: utils/cpufreq-set.c:170
+#, c-format
+msgid "wrong, unknown or unhandled CPU?\n"
+msgstr "neznámý nebo nepodporovaný CPU?\n"
+
+#: utils/cpufreq-set.c:302
+#, c-format
+msgid ""
+"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
+"-g/--governor parameters\n"
+msgstr ""
+"přepínač -f/--freq nemůže být použit zároveň\n"
+"s přepínačem -d/--min, -u/--max nebo -g/--governor\n"
+
+#: utils/cpufreq-set.c:308
+#, c-format
+msgid ""
+"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
+"-g/--governor must be passed\n"
+msgstr ""
+"Musí být zadán alespoň jeden přepínač\n"
+"-f/--freq, -d/--min, -u/--max nebo -g/--governor\n"
+
+#: utils/cpufreq-set.c:347
+#, c-format
+msgid "Setting cpu: %d\n"
+msgstr ""
+
+#: utils/cpupower-set.c:22
+#, c-format
+msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:24
+#, c-format
+msgid ""
+"  -b, --perf-bias [VAL]    Sets CPU's power vs performance policy on some\n"
+"                           Intel models [0-15], see manpage for details\n"
+msgstr ""
+
+#: utils/cpupower-set.c:26
+#, c-format
+msgid ""
+"  -m, --sched-mc  [VAL]    Sets the kernel's multi core scheduler policy.\n"
+msgstr ""
+
+#: utils/cpupower-set.c:27
+#, c-format
+msgid ""
+"  -s, --sched-smt [VAL]    Sets the kernel's thread sibling scheduler "
+"policy.\n"
+msgstr ""
+
+#: utils/cpupower-set.c:80
+#, c-format
+msgid "--perf-bias param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:91
+#, c-format
+msgid "--sched-mc param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:102
+#, c-format
+msgid "--sched-smt param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:121
+#, c-format
+msgid "Error setting sched-mc %s\n"
+msgstr ""
+
+#: utils/cpupower-set.c:127
+#, c-format
+msgid "Error setting sched-smt %s\n"
+msgstr ""
+
+#: utils/cpupower-set.c:146
+#, c-format
+msgid "Error setting perf-bias value on CPU %d\n"
+msgstr ""
+
+#: utils/cpupower-info.c:21
+#, c-format
+msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
+msgstr ""
+
+#: utils/cpupower-info.c:23
+#, c-format
+msgid ""
+"  -b, --perf-bias    Gets CPU's power vs performance policy on some\n"
+"                           Intel models [0-15], see manpage for details\n"
+msgstr ""
+
+#: utils/cpupower-info.c:25
+#, fuzzy, c-format
+msgid "  -m, --sched-mc     Gets the kernel's multi core scheduler policy.\n"
+msgstr "  -p, --policy         Zjistí aktuální taktiku cpufreq *\n"
+
+#: utils/cpupower-info.c:26
+#, c-format
+msgid ""
+"  -s, --sched-smt    Gets the kernel's thread sibling scheduler policy.\n"
+msgstr ""
+
+#: utils/cpupower-info.c:28
+#, c-format
+msgid ""
+"\n"
+"Passing no option will show all info, by default only on core 0\n"
+msgstr ""
+
+#: utils/cpupower-info.c:102
+#, c-format
+msgid "System's multi core scheduler setting: "
+msgstr ""
+
+#. if sysfs file is missing it's: errno == ENOENT
+#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
+#, c-format
+msgid "not supported\n"
+msgstr ""
+
+#: utils/cpupower-info.c:111
+#, c-format
+msgid "System's thread sibling scheduler setting: "
+msgstr ""
+
+#: utils/cpupower-info.c:126
+#, c-format
+msgid "Intel's performance bias setting needs root privileges\n"
+msgstr ""
+
+#: utils/cpupower-info.c:128
+#, c-format
+msgid "System does not support Intel's performance bias setting\n"
+msgstr ""
+
+#: utils/cpupower-info.c:147
+#, c-format
+msgid "Could not read perf-bias value\n"
+msgstr ""
+
+#: utils/cpupower-info.c:150
+#, c-format
+msgid "perf-bias: %d\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:28
+#, fuzzy, c-format
+msgid "Analyzing CPU %d:\n"
+msgstr "analyzuji CPU %d:\n"
+
+#: utils/cpuidle-info.c:32
+#, c-format
+msgid "CPU %u: No idle states\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:36
+#, c-format
+msgid "CPU %u: Can't read idle state info\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:41
+#, c-format
+msgid "Could not determine max idle state %u\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:46
+#, c-format
+msgid "Number of idle states: %d\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:48
+#, fuzzy, c-format
+msgid "Available idle states:"
+msgstr "  dostupné frekvence: "
+
+#: utils/cpuidle-info.c:71
+#, c-format
+msgid "Flags/Description: %s\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:74
+#, c-format
+msgid "Latency: %lu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:76
+#, c-format
+msgid "Usage: %lu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:78
+#, c-format
+msgid "Duration: %llu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:90
+#, c-format
+msgid "Could not determine cpuidle driver\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:94
+#, fuzzy, c-format
+msgid "CPUidle driver: %s\n"
+msgstr "  ovladač: %s\n"
+
+#: utils/cpuidle-info.c:99
+#, c-format
+msgid "Could not determine cpuidle governor\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:103
+#, c-format
+msgid "CPUidle governor: %s\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:122
+#, c-format
+msgid "CPU %u: Can't read C-state info\n"
+msgstr ""
+
+#. printf("Cstates: %d\n", cstates);
+#: utils/cpuidle-info.c:127
+#, c-format
+msgid "active state:            C0\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:128
+#, c-format
+msgid "max_cstate:              C%u\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:129
+#, c-format
+msgid "maximum allowed latency: %lu usec\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:130
+#, c-format
+msgid "states:\t\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:132
+#, c-format
+msgid "    C%d:                  type[C%d] "
+msgstr ""
+
+#: utils/cpuidle-info.c:134
+#, c-format
+msgid "promotion[--] demotion[--] "
+msgstr ""
+
+#: utils/cpuidle-info.c:135
+#, c-format
+msgid "latency[%03lu] "
+msgstr ""
+
+#: utils/cpuidle-info.c:137
+#, c-format
+msgid "usage[%08lu] "
+msgstr ""
+
+#: utils/cpuidle-info.c:139
+#, c-format
+msgid "duration[%020Lu] \n"
+msgstr ""
+
+#: utils/cpuidle-info.c:147
+#, fuzzy, c-format
+msgid "Usage: cpupower idleinfo [options]\n"
+msgstr "Užití: cpufreq-info [přepínače]\n"
+
+#: utils/cpuidle-info.c:149
+#, fuzzy, c-format
+msgid "  -s, --silent         Only show general C-state information\n"
+msgstr "  -e, --debug          Vypíše ladicí informace\n"
+
+#: utils/cpuidle-info.c:150
+#, fuzzy, c-format
+msgid ""
+"  -o, --proc           Prints out information like provided by the /proc/"
+"acpi/processor/*/power\n"
+"                       interface in older kernels\n"
+msgstr ""
+"  -o, --proc           Vypíše informace ve formátu, jaký používalo rozhraní\n"
+"                       /proc/cpufreq v kernelech řady 2.4 a časné 2.6\n"
+
+#: utils/cpuidle-info.c:209
+#, fuzzy, c-format
+msgid "You can't specify more than one output-specific argument\n"
+msgstr ""
+"Nelze zadat více než jeden parametr -c nebo --cpu\n"
+"anebo více než jeden parametr určující výstup\n"
+
+#~ msgid ""
+#~ "  -c CPU, --cpu CPU    CPU number which information shall be determined "
+#~ "about\n"
+#~ msgstr ""
+#~ "  -c CPU, --cpu CPU    Číslo CPU, o kterém se mají zjistit informace\n"
+
+#~ msgid ""
+#~ "  -c CPU, --cpu CPU        number of CPU where cpufreq settings shall be "
+#~ "modified\n"
+#~ msgstr ""
+#~ "  -c CPU, --cpu CPU        Číslo CPU pro který se má provést nastavení "
+#~ "cpufreq\n"
diff --git a/tools/power/cpupower/po/de.po b/tools/power/cpupower/po/de.po
new file mode 100644 (file)
index 0000000..78c09e5
--- /dev/null
@@ -0,0 +1,961 @@
+# German translations for cpufrequtils package
+# German messages for cpufrequtils.
+# Copyright (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.net>
+# This file is distributed under the same license as the cpufrequtils package.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cpufrequtils 006\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-03-08 17:03+0100\n"
+"PO-Revision-Date: 2009-08-08 17:18+0100\n"
+"Last-Translator:  <linux@dominikbrodowski.net>\n"
+"Language-Team: NONE\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: utils/idle_monitor/nhm_idle.c:36
+msgid "Processor Core C3"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:43
+msgid "Processor Core C6"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:51
+msgid "Processor Package C3"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
+msgid "Processor Package C6"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:33
+msgid "Processor Core C7"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:40
+msgid "Processor Package C2"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:47
+msgid "Processor Package C7"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:56
+msgid "Package in sleep state (PC1 or deeper)"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:63
+msgid "Processor Package C1"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:77
+msgid "North Bridge P1 boolean counter (returns 0 or 1)"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:35
+msgid "Processor Core not idle"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:42
+msgid "Processor Core in an idle state"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:50
+msgid "Average Frequency (including boost) in MHz"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:66
+#, c-format
+msgid ""
+"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
+"interval_sec | -c command ...]\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:69
+#, c-format
+msgid ""
+"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
+"interval_sec | -c command ...]\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:71
+#, c-format
+msgid "\t -v: be more verbose\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:73
+#, c-format
+msgid "\t -h: print this help\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:74
+#, c-format
+msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:75
+#, c-format
+msgid "\t -t: show CPU topology/hierarchy\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:76
+#, c-format
+msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:77
+#, c-format
+msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:79
+#, c-format
+msgid ""
+"only one of: -t, -l, -m are allowed\n"
+"If none of them is passed,"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:80
+#, c-format
+msgid " all supported monitors are shown\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:197
+#, c-format
+msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:207
+#, c-format
+msgid " *is offline\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:236
+#, c-format
+msgid "%s: max monitor name length (%d) exceeded\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:250
+#, c-format
+msgid "No matching monitor found in %s, try -l option\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:266
+#, c-format
+msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:319
+#, c-format
+msgid "%s took %.5f seconds and exited with status %d\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:406
+#, c-format
+msgid "Cannot read number of available processors\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:417
+#, c-format
+msgid "Available monitor %s needs root access\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:428
+#, c-format
+msgid "No HW Cstate monitors found\n"
+msgstr ""
+
+#: utils/cpupower.c:78
+#, c-format
+msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
+msgstr ""
+
+#: utils/cpupower.c:79
+#, c-format
+msgid "cpupower --version\n"
+msgstr ""
+
+#: utils/cpupower.c:80
+#, c-format
+msgid "Supported subcommands are:\n"
+msgstr ""
+
+#: utils/cpupower.c:83
+#, c-format
+msgid ""
+"\n"
+"Some subcommands can make use of the -c cpulist option.\n"
+msgstr ""
+
+#: utils/cpupower.c:84
+#, c-format
+msgid "Look at the general cpupower manpage how to use it\n"
+msgstr ""
+
+#: utils/cpupower.c:85
+#, c-format
+msgid "and read up the subcommand's manpage whether it is supported.\n"
+msgstr ""
+
+#: utils/cpupower.c:86
+#, c-format
+msgid ""
+"\n"
+"Use cpupower help subcommand for getting help for above subcommands.\n"
+msgstr ""
+
+#: utils/cpupower.c:91
+#, c-format
+msgid "Report errors and bugs to %s, please.\n"
+msgstr "Bitte melden Sie Fehler an %s.\n"
+
+#: utils/cpupower.c:114
+#, c-format
+msgid "Error parsing cpu list\n"
+msgstr ""
+
+#: utils/cpupower.c:172
+#, c-format
+msgid "Subcommand %s needs root privileges\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:31
+#, c-format
+msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
+msgstr ""
+"Konnte nicht die Anzahl der CPUs herausfinden (%s : %s), nehme daher 1 an.\n"
+
+#: utils/cpufreq-info.c:63
+#, c-format
+msgid ""
+"          minimum CPU frequency  -  maximum CPU frequency  -  governor\n"
+msgstr ""
+"          minimale CPU-Taktfreq. -  maximale CPU-Taktfreq. -  Regler  \n"
+
+#: utils/cpufreq-info.c:151
+#, c-format
+msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
+msgstr ""
+
+#. P state changes via MSR are identified via cpuid 80000007
+#. on Intel and AMD, but we assume boost capable machines can do that
+#. if (cpuid_eax(0x80000000) >= 0x80000007
+#. && (cpuid_edx(0x80000007) & (1 << 7)))
+#.
+#: utils/cpufreq-info.c:161
+#, c-format
+msgid "  boost state support: \n"
+msgstr ""
+
+#: utils/cpufreq-info.c:163
+#, c-format
+msgid "    Supported: %s\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
+msgid "yes"
+msgstr ""
+
+#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
+msgid "no"
+msgstr ""
+
+#: utils/cpufreq-info.c:164
+#, fuzzy, c-format
+msgid "    Active: %s\n"
+msgstr "  Treiber: %s\n"
+
+#: utils/cpufreq-info.c:177
+#, c-format
+msgid "    Boost States: %d\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:178
+#, c-format
+msgid "    Total States: %d\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:181
+#, c-format
+msgid "    Pstate-Pb%d: %luMHz (boost state)\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:184
+#, c-format
+msgid "    Pstate-P%d:  %luMHz\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:211
+#, c-format
+msgid "  no or unknown cpufreq driver is active on this CPU\n"
+msgstr "  kein oder nicht bestimmbarer cpufreq-Treiber aktiv\n"
+
+#: utils/cpufreq-info.c:213
+#, c-format
+msgid "  driver: %s\n"
+msgstr "  Treiber: %s\n"
+
+#: utils/cpufreq-info.c:219
+#, c-format
+msgid "  CPUs which run at the same hardware frequency: "
+msgstr "  Folgende CPUs laufen mit der gleichen Hardware-Taktfrequenz: "
+
+#: utils/cpufreq-info.c:230
+#, c-format
+msgid "  CPUs which need to have their frequency coordinated by software: "
+msgstr "  Die Taktfrequenz folgender CPUs werden per Software koordiniert: "
+
+#: utils/cpufreq-info.c:241
+#, c-format
+msgid "  maximum transition latency: "
+msgstr "  Maximale Dauer eines Taktfrequenzwechsels: "
+
+#: utils/cpufreq-info.c:247
+#, c-format
+msgid "  hardware limits: "
+msgstr "  Hardwarebedingte Grenzen der Taktfrequenz: "
+
+#: utils/cpufreq-info.c:256
+#, c-format
+msgid "  available frequency steps: "
+msgstr "  mögliche Taktfrequenzen: "
+
+#: utils/cpufreq-info.c:269
+#, c-format
+msgid "  available cpufreq governors: "
+msgstr "  mögliche Regler: "
+
+#: utils/cpufreq-info.c:280
+#, c-format
+msgid "  current policy: frequency should be within "
+msgstr "  momentane Taktik: die Frequenz soll innerhalb "
+
+#: utils/cpufreq-info.c:282
+#, c-format
+msgid " and "
+msgstr " und "
+
+#: utils/cpufreq-info.c:286
+#, c-format
+msgid ""
+"The governor \"%s\" may decide which speed to use\n"
+"                  within this range.\n"
+msgstr ""
+"  liegen. Der Regler \"%s\" kann frei entscheiden,\n"
+"                    welche Taktfrequenz innerhalb dieser Grenze verwendet "
+"wird.\n"
+
+#: utils/cpufreq-info.c:293
+#, c-format
+msgid "  current CPU frequency is "
+msgstr "  momentane Taktfrequenz ist "
+
+#: utils/cpufreq-info.c:296
+#, c-format
+msgid " (asserted by call to hardware)"
+msgstr "  (verifiziert durch Nachfrage bei der Hardware)"
+
+#: utils/cpufreq-info.c:304
+#, c-format
+msgid "  cpufreq stats: "
+msgstr "  Statistik:"
+
+#: utils/cpufreq-info.c:472
+#, fuzzy, c-format
+msgid "Usage: cpupower freqinfo [options]\n"
+msgstr "Aufruf: cpufreq-info [Optionen]\n"
+
+#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
+#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
+#, c-format
+msgid "Options:\n"
+msgstr "Optionen:\n"
+
+#: utils/cpufreq-info.c:474
+#, fuzzy, c-format
+msgid "  -e, --debug          Prints out debug information [default]\n"
+msgstr ""
+"  -e, --debug          Erzeugt detaillierte Informationen, hilfreich\n"
+"                       zum Aufspüren von Fehlern\n"
+
+#: utils/cpufreq-info.c:475
+#, c-format
+msgid ""
+"  -f, --freq           Get frequency the CPU currently runs at, according\n"
+"                       to the cpufreq core *\n"
+msgstr ""
+"  -f, --freq           Findet die momentane CPU-Taktfrquenz heraus (nach\n"
+"                       Meinung des Betriebssystems) *\n"
+
+#: utils/cpufreq-info.c:477
+#, c-format
+msgid ""
+"  -w, --hwfreq         Get frequency the CPU currently runs at, by reading\n"
+"                       it from hardware (only available to root) *\n"
+msgstr ""
+"  -w, --hwfreq         Findet die momentane CPU-Taktfrequenz heraus\n"
+"                       (verifiziert durch Nachfrage bei der Hardware)\n"
+"                       [nur der Administrator kann dies tun] *\n"
+
+#: utils/cpufreq-info.c:479
+#, c-format
+msgid ""
+"  -l, --hwlimits       Determine the minimum and maximum CPU frequency "
+"allowed *\n"
+msgstr ""
+"  -l, --hwlimits       Findet die minimale und maximale Taktfrequenz heraus "
+"*\n"
+
+#: utils/cpufreq-info.c:480
+#, c-format
+msgid "  -d, --driver         Determines the used cpufreq kernel driver *\n"
+msgstr "  -d, --driver         Findet den momentanen Treiber heraus *\n"
+
+#: utils/cpufreq-info.c:481
+#, c-format
+msgid "  -p, --policy         Gets the currently used cpufreq policy *\n"
+msgstr "  -p, --policy         Findet die momentane Taktik heraus *\n"
+
+#: utils/cpufreq-info.c:482
+#, c-format
+msgid "  -g, --governors      Determines available cpufreq governors *\n"
+msgstr "  -g, --governors      Erzeugt eine Liste mit verfügbaren Reglern *\n"
+
+#: utils/cpufreq-info.c:483
+#, c-format
+msgid ""
+"  -r, --related-cpus   Determines which CPUs run at the same hardware "
+"frequency *\n"
+msgstr ""
+"  -r, --related-cpus   Findet heraus, welche CPUs mit derselben "
+"physikalischen\n"
+"                       Taktfrequenz laufen *\n"
+
+#: utils/cpufreq-info.c:484
+#, c-format
+msgid ""
+"  -a, --affected-cpus  Determines which CPUs need to have their frequency\n"
+"                       coordinated by software *\n"
+msgstr ""
+"  -a, --affected-cpus  Findet heraus, von welchen CPUs die Taktfrequenz "
+"durch\n"
+"                       Software koordiniert werden muss *\n"
+
+#: utils/cpufreq-info.c:486
+#, c-format
+msgid "  -s, --stats          Shows cpufreq statistics if available\n"
+msgstr ""
+"  -s, --stats          Zeigt, sofern möglich, Statistiken über cpufreq an.\n"
+
+#: utils/cpufreq-info.c:487
+#, c-format
+msgid ""
+"  -y, --latency        Determines the maximum latency on CPU frequency "
+"changes *\n"
+msgstr ""
+"  -y, --latency        Findet die maximale Dauer eines Taktfrequenzwechsels "
+"heraus *\n"
+
+#: utils/cpufreq-info.c:488
+#, c-format
+msgid "  -b, --boost          Checks for turbo or boost modes  *\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:489
+#, c-format
+msgid ""
+"  -o, --proc           Prints out information like provided by the /proc/"
+"cpufreq\n"
+"                       interface in 2.4. and early 2.6. kernels\n"
+msgstr ""
+"  -o, --proc           Erzeugt Informationen in einem ähnlichem Format zu "
+"dem\n"
+"                       der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n"
+"                       Kernel-Versionen\n"
+
+#: utils/cpufreq-info.c:491
+#, c-format
+msgid ""
+"  -m, --human          human-readable output for the -f, -w, -s and -y "
+"parameters\n"
+msgstr ""
+"  -m, --human          Formatiert Taktfrequenz- und Zeitdauerangaben in "
+"besser\n"
+"                       lesbarer Form (MHz, GHz; us, ms)\n"
+
+#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
+#, c-format
+msgid "  -h, --help           Prints out this screen\n"
+msgstr "  -h, --help           Gibt diese Kurzübersicht aus\n"
+
+#: utils/cpufreq-info.c:495
+#, c-format
+msgid ""
+"If no argument or only the -c, --cpu parameter is given, debug output about\n"
+"cpufreq is printed which is useful e.g. for reporting bugs.\n"
+msgstr ""
+"Sofern kein anderer Parameter als '-c, --cpu' angegeben wird, liefert "
+"dieses\n"
+"Programm Informationen, die z.B. zum Berichten von Fehlern nützlich sind.\n"
+
+#: utils/cpufreq-info.c:497
+#, c-format
+msgid ""
+"For the arguments marked with *, omitting the -c or --cpu argument is\n"
+"equivalent to setting it to zero\n"
+msgstr ""
+"Bei den mit * markierten Parametern wird '--cpu 0' angenommen, soweit nicht\n"
+"mittels -c oder --cpu etwas anderes angegeben wird\n"
+
+#: utils/cpufreq-info.c:580
+#, c-format
+msgid ""
+"The argument passed to this tool can't be combined with passing a --cpu "
+"argument\n"
+msgstr "Diese Option kann nicht mit der --cpu-Option kombiniert werden\n"
+
+#: utils/cpufreq-info.c:596
+#, c-format
+msgid ""
+"You can't specify more than one --cpu parameter and/or\n"
+"more than one output-specific argument\n"
+msgstr ""
+"Man kann nicht mehr als einen --cpu-Parameter und/oder mehr als einen\n"
+"informationsspezifischen Parameter gleichzeitig angeben\n"
+
+#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
+#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
+#, c-format
+msgid "invalid or unknown argument\n"
+msgstr "unbekannter oder falscher Parameter\n"
+
+#: utils/cpufreq-info.c:617
+#, c-format
+msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
+msgstr ""
+"Konnte nicht die CPU %d analysieren, da sie (scheinbar?) nicht existiert.\n"
+
+#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
+#, c-format
+msgid "analyzing CPU %d:\n"
+msgstr "analysiere CPU %d:\n"
+
+#: utils/cpufreq-set.c:25
+#, fuzzy, c-format
+msgid "Usage: cpupower frequency-set [options]\n"
+msgstr "Aufruf: cpufreq-set [Optionen]\n"
+
+#: utils/cpufreq-set.c:27
+#, c-format
+msgid ""
+"  -d FREQ, --min FREQ      new minimum CPU frequency the governor may "
+"select\n"
+msgstr ""
+"  -d FREQ, --min FREQ      neue minimale Taktfrequenz, die der Regler\n"
+"                           auswählen darf\n"
+
+#: utils/cpufreq-set.c:28
+#, c-format
+msgid ""
+"  -u FREQ, --max FREQ      new maximum CPU frequency the governor may "
+"select\n"
+msgstr ""
+"  -u FREQ, --max FREQ      neue maximale Taktfrequenz, die der Regler\n"
+"                           auswählen darf\n"
+
+#: utils/cpufreq-set.c:29
+#, c-format
+msgid "  -g GOV, --governor GOV   new cpufreq governor\n"
+msgstr "  -g GOV, --governors GOV  wechsle zu Regler GOV\n"
+
+#: utils/cpufreq-set.c:30
+#, c-format
+msgid ""
+"  -f FREQ, --freq FREQ     specific frequency to be set. Requires userspace\n"
+"                           governor to be available and loaded\n"
+msgstr ""
+"  -f FREQ, --freq FREQ     setze exakte Taktfrequenz. Benötigt den Regler\n"
+"                           'userspace'.\n"
+
+#: utils/cpufreq-set.c:32
+#, c-format
+msgid "  -r, --related            Switches all hardware-related CPUs\n"
+msgstr ""
+"  -r, --related            Setze Werte für alle CPUs, deren Taktfrequenz\n"
+"                           hardwarebedingt identisch ist.\n"
+
+#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
+#, c-format
+msgid "  -h, --help               Prints out this screen\n"
+msgstr "  -h, --help               Gibt diese Kurzübersicht aus\n"
+
+#: utils/cpufreq-set.c:35
+#, fuzzy, c-format
+msgid ""
+"Notes:\n"
+"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
+msgstr ""
+"Bei den mit * markierten Parametern wird '--cpu 0' angenommen, soweit nicht\n"
+"mittels -c oder --cpu etwas anderes angegeben wird\n"
+
+#: utils/cpufreq-set.c:37
+#, fuzzy, c-format
+msgid ""
+"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
+"parameter\n"
+"   except the -c CPU, --cpu CPU parameter\n"
+"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
+"   by postfixing the value with the wanted unit name, without any space\n"
+"   (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
+msgstr ""
+"Hinweise:\n"
+"1. Sofern kein -c oder --cpu-Parameter angegeben ist, wird '--cpu 0'\n"
+"   angenommen\n"
+"2. Der Parameter -f bzw. --freq kann mit keinem anderen als dem Parameter\n"
+"   -c bzw. --cpu kombiniert werden\n"
+"3. FREQuenzen können in Hz, kHz (Standard), MHz, GHz oder THz eingegeben\n"
+"   werden, indem der Wert und unmittelbar anschließend (ohne Leerzeichen!)\n"
+"   die Einheit angegeben werden. (Bsp: 1GHz )\n"
+"   (FREQuenz in kHz =^ MHz * 1000 =^ GHz * 1000000).\n"
+
+#: utils/cpufreq-set.c:57
+#, c-format
+msgid ""
+"Error setting new values. Common errors:\n"
+"- Do you have proper administration rights? (super-user?)\n"
+"- Is the governor you requested available and modprobed?\n"
+"- Trying to set an invalid policy?\n"
+"- Trying to set a specific frequency, but userspace governor is not "
+"available,\n"
+"   for example because of hardware which cannot be set to a specific "
+"frequency\n"
+"   or because the userspace governor isn't loaded?\n"
+msgstr ""
+"Beim Einstellen ist ein Fehler aufgetreten. Typische Fehlerquellen sind:\n"
+"- nicht ausreichende Rechte (Administrator)\n"
+"- der Regler ist nicht verfügbar bzw. nicht geladen\n"
+"- die angegebene Taktik ist inkorrekt\n"
+"- eine spezifische Frequenz wurde angegeben, aber der Regler 'userspace'\n"
+"  kann entweder hardwarebedingt nicht genutzt werden oder ist nicht geladen\n"
+
+#: utils/cpufreq-set.c:170
+#, c-format
+msgid "wrong, unknown or unhandled CPU?\n"
+msgstr "unbekannte oder nicht regelbare CPU\n"
+
+#: utils/cpufreq-set.c:302
+#, c-format
+msgid ""
+"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
+"-g/--governor parameters\n"
+msgstr ""
+"Der -f bzw. --freq-Parameter kann nicht mit den Parametern -d/--min, -u/--"
+"max\n"
+"oder -g/--governor kombiniert werden\n"
+
+#: utils/cpufreq-set.c:308
+#, c-format
+msgid ""
+"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
+"-g/--governor must be passed\n"
+msgstr ""
+"Es muss mindestens ein Parameter aus -f/--freq, -d/--min, -u/--max oder\n"
+"-g/--governor angegeben werden.\n"
+
+#: utils/cpufreq-set.c:347
+#, c-format
+msgid "Setting cpu: %d\n"
+msgstr ""
+
+#: utils/cpupower-set.c:22
+#, c-format
+msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:24
+#, c-format
+msgid ""
+"  -b, --perf-bias [VAL]    Sets CPU's power vs performance policy on some\n"
+"                           Intel models [0-15], see manpage for details\n"
+msgstr ""
+
+#: utils/cpupower-set.c:26
+#, c-format
+msgid ""
+"  -m, --sched-mc  [VAL]    Sets the kernel's multi core scheduler policy.\n"
+msgstr ""
+
+#: utils/cpupower-set.c:27
+#, c-format
+msgid ""
+"  -s, --sched-smt [VAL]    Sets the kernel's thread sibling scheduler "
+"policy.\n"
+msgstr ""
+
+#: utils/cpupower-set.c:80
+#, c-format
+msgid "--perf-bias param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:91
+#, c-format
+msgid "--sched-mc param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:102
+#, c-format
+msgid "--sched-smt param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:121
+#, c-format
+msgid "Error setting sched-mc %s\n"
+msgstr ""
+
+#: utils/cpupower-set.c:127
+#, c-format
+msgid "Error setting sched-smt %s\n"
+msgstr ""
+
+#: utils/cpupower-set.c:146
+#, c-format
+msgid "Error setting perf-bias value on CPU %d\n"
+msgstr ""
+
+#: utils/cpupower-info.c:21
+#, c-format
+msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
+msgstr ""
+
+#: utils/cpupower-info.c:23
+#, c-format
+msgid ""
+"  -b, --perf-bias    Gets CPU's power vs performance policy on some\n"
+"                           Intel models [0-15], see manpage for details\n"
+msgstr ""
+
+#: utils/cpupower-info.c:25
+#, fuzzy, c-format
+msgid "  -m, --sched-mc     Gets the kernel's multi core scheduler policy.\n"
+msgstr "  -p, --policy         Findet die momentane Taktik heraus *\n"
+
+#: utils/cpupower-info.c:26
+#, c-format
+msgid ""
+"  -s, --sched-smt    Gets the kernel's thread sibling scheduler policy.\n"
+msgstr ""
+
+#: utils/cpupower-info.c:28
+#, c-format
+msgid ""
+"\n"
+"Passing no option will show all info, by default only on core 0\n"
+msgstr ""
+
+#: utils/cpupower-info.c:102
+#, c-format
+msgid "System's multi core scheduler setting: "
+msgstr ""
+
+#. if sysfs file is missing it's: errno == ENOENT
+#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
+#, c-format
+msgid "not supported\n"
+msgstr ""
+
+#: utils/cpupower-info.c:111
+#, c-format
+msgid "System's thread sibling scheduler setting: "
+msgstr ""
+
+#: utils/cpupower-info.c:126
+#, c-format
+msgid "Intel's performance bias setting needs root privileges\n"
+msgstr ""
+
+#: utils/cpupower-info.c:128
+#, c-format
+msgid "System does not support Intel's performance bias setting\n"
+msgstr ""
+
+#: utils/cpupower-info.c:147
+#, c-format
+msgid "Could not read perf-bias value\n"
+msgstr ""
+
+#: utils/cpupower-info.c:150
+#, c-format
+msgid "perf-bias: %d\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:28
+#, fuzzy, c-format
+msgid "Analyzing CPU %d:\n"
+msgstr "analysiere CPU %d:\n"
+
+#: utils/cpuidle-info.c:32
+#, c-format
+msgid "CPU %u: No idle states\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:36
+#, c-format
+msgid "CPU %u: Can't read idle state info\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:41
+#, c-format
+msgid "Could not determine max idle state %u\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:46
+#, c-format
+msgid "Number of idle states: %d\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:48
+#, fuzzy, c-format
+msgid "Available idle states:"
+msgstr "  mögliche Taktfrequenzen: "
+
+#: utils/cpuidle-info.c:71
+#, c-format
+msgid "Flags/Description: %s\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:74
+#, c-format
+msgid "Latency: %lu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:76
+#, c-format
+msgid "Usage: %lu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:78
+#, c-format
+msgid "Duration: %llu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:90
+#, c-format
+msgid "Could not determine cpuidle driver\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:94
+#, fuzzy, c-format
+msgid "CPUidle driver: %s\n"
+msgstr "  Treiber: %s\n"
+
+#: utils/cpuidle-info.c:99
+#, c-format
+msgid "Could not determine cpuidle governor\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:103
+#, c-format
+msgid "CPUidle governor: %s\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:122
+#, c-format
+msgid "CPU %u: Can't read C-state info\n"
+msgstr ""
+
+#. printf("Cstates: %d\n", cstates);
+#: utils/cpuidle-info.c:127
+#, c-format
+msgid "active state:            C0\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:128
+#, c-format
+msgid "max_cstate:              C%u\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:129
+#, fuzzy, c-format
+msgid "maximum allowed latency: %lu usec\n"
+msgstr "  Maximale Dauer eines Taktfrequenzwechsels: "
+
+#: utils/cpuidle-info.c:130
+#, c-format
+msgid "states:\t\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:132
+#, c-format
+msgid "    C%d:                  type[C%d] "
+msgstr ""
+
+#: utils/cpuidle-info.c:134
+#, c-format
+msgid "promotion[--] demotion[--] "
+msgstr ""
+
+#: utils/cpuidle-info.c:135
+#, c-format
+msgid "latency[%03lu] "
+msgstr ""
+
+#: utils/cpuidle-info.c:137
+#, c-format
+msgid "usage[%08lu] "
+msgstr ""
+
+#: utils/cpuidle-info.c:139
+#, c-format
+msgid "duration[%020Lu] \n"
+msgstr ""
+
+#: utils/cpuidle-info.c:147
+#, fuzzy, c-format
+msgid "Usage: cpupower idleinfo [options]\n"
+msgstr "Aufruf: cpufreq-info [Optionen]\n"
+
+#: utils/cpuidle-info.c:149
+#, fuzzy, c-format
+msgid "  -s, --silent         Only show general C-state information\n"
+msgstr ""
+"  -e, --debug          Erzeugt detaillierte Informationen, hilfreich\n"
+"                       zum Aufspüren von Fehlern\n"
+
+#: utils/cpuidle-info.c:150
+#, fuzzy, c-format
+msgid ""
+"  -o, --proc           Prints out information like provided by the /proc/"
+"acpi/processor/*/power\n"
+"                       interface in older kernels\n"
+msgstr ""
+"  -o, --proc           Erzeugt Informationen in einem ähnlichem Format zu "
+"dem\n"
+"                       der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n"
+"                       Kernel-Versionen\n"
+
+#: utils/cpuidle-info.c:209
+#, fuzzy, c-format
+msgid "You can't specify more than one output-specific argument\n"
+msgstr ""
+"Man kann nicht mehr als einen --cpu-Parameter und/oder mehr als einen\n"
+"informationsspezifischen Parameter gleichzeitig angeben\n"
+
+#~ msgid ""
+#~ "  -c CPU, --cpu CPU    CPU number which information shall be determined "
+#~ "about\n"
+#~ msgstr ""
+#~ "  -c CPU, --cpu CPU    Nummer der CPU, über die Informationen "
+#~ "herausgefunden werden sollen\n"
+
+#~ msgid ""
+#~ "  -c CPU, --cpu CPU        number of CPU where cpufreq settings shall be "
+#~ "modified\n"
+#~ msgstr ""
+#~ "  -c CPU, --cpu CPU        Nummer der CPU, deren Taktfrequenz-"
+#~ "Einstellung\n"
+#~ "                           werden soll\n"
diff --git a/tools/power/cpupower/po/fr.po b/tools/power/cpupower/po/fr.po
new file mode 100644 (file)
index 0000000..245ad20
--- /dev/null
@@ -0,0 +1,947 @@
+# French translations for cpufrequtils package
+# Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the cpufrequtils package.
+# Ducrot Bruno <ducrot@poupinou.org>, 2004.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: cpufrequtils 0.1-pre2\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-03-08 17:03+0100\n"
+"PO-Revision-Date: 2004-11-17 15:53+1000\n"
+"Last-Translator: Bruno Ducrot <ducrot@poupinou.org>\n"
+"Language-Team: NONE\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: utils/idle_monitor/nhm_idle.c:36
+msgid "Processor Core C3"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:43
+msgid "Processor Core C6"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:51
+msgid "Processor Package C3"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
+msgid "Processor Package C6"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:33
+msgid "Processor Core C7"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:40
+msgid "Processor Package C2"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:47
+msgid "Processor Package C7"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:56
+msgid "Package in sleep state (PC1 or deeper)"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:63
+msgid "Processor Package C1"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:77
+msgid "North Bridge P1 boolean counter (returns 0 or 1)"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:35
+msgid "Processor Core not idle"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:42
+msgid "Processor Core in an idle state"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:50
+msgid "Average Frequency (including boost) in MHz"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:66
+#, c-format
+msgid ""
+"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
+"interval_sec | -c command ...]\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:69
+#, c-format
+msgid ""
+"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
+"interval_sec | -c command ...]\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:71
+#, c-format
+msgid "\t -v: be more verbose\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:73
+#, c-format
+msgid "\t -h: print this help\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:74
+#, c-format
+msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:75
+#, c-format
+msgid "\t -t: show CPU topology/hierarchy\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:76
+#, c-format
+msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:77
+#, c-format
+msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:79
+#, c-format
+msgid ""
+"only one of: -t, -l, -m are allowed\n"
+"If none of them is passed,"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:80
+#, c-format
+msgid " all supported monitors are shown\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:197
+#, c-format
+msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:207
+#, c-format
+msgid " *is offline\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:236
+#, c-format
+msgid "%s: max monitor name length (%d) exceeded\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:250
+#, c-format
+msgid "No matching monitor found in %s, try -l option\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:266
+#, c-format
+msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:319
+#, c-format
+msgid "%s took %.5f seconds and exited with status %d\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:406
+#, c-format
+msgid "Cannot read number of available processors\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:417
+#, c-format
+msgid "Available monitor %s needs root access\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:428
+#, c-format
+msgid "No HW Cstate monitors found\n"
+msgstr ""
+
+#: utils/cpupower.c:78
+#, c-format
+msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
+msgstr ""
+
+#: utils/cpupower.c:79
+#, c-format
+msgid "cpupower --version\n"
+msgstr ""
+
+#: utils/cpupower.c:80
+#, c-format
+msgid "Supported subcommands are:\n"
+msgstr ""
+
+#: utils/cpupower.c:83
+#, c-format
+msgid ""
+"\n"
+"Some subcommands can make use of the -c cpulist option.\n"
+msgstr ""
+
+#: utils/cpupower.c:84
+#, c-format
+msgid "Look at the general cpupower manpage how to use it\n"
+msgstr ""
+
+#: utils/cpupower.c:85
+#, c-format
+msgid "and read up the subcommand's manpage whether it is supported.\n"
+msgstr ""
+
+#: utils/cpupower.c:86
+#, c-format
+msgid ""
+"\n"
+"Use cpupower help subcommand for getting help for above subcommands.\n"
+msgstr ""
+
+#: utils/cpupower.c:91
+#, c-format
+msgid "Report errors and bugs to %s, please.\n"
+msgstr "Veuillez rapportez les erreurs et les bogues à %s, s'il vous plait.\n"
+
+#: utils/cpupower.c:114
+#, c-format
+msgid "Error parsing cpu list\n"
+msgstr ""
+
+#: utils/cpupower.c:172
+#, c-format
+msgid "Subcommand %s needs root privileges\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:31
+#, c-format
+msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
+msgstr "Détermination du nombre de CPUs (%s : %s) impossible.  Assume 1\n"
+
+#: utils/cpufreq-info.c:63
+#, c-format
+msgid ""
+"          minimum CPU frequency  -  maximum CPU frequency  -  governor\n"
+msgstr ""
+"         Fréquence CPU minimale - Fréquence CPU maximale  - régulateur\n"
+
+#: utils/cpufreq-info.c:151
+#, c-format
+msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
+msgstr ""
+
+#. P state changes via MSR are identified via cpuid 80000007
+#. on Intel and AMD, but we assume boost capable machines can do that
+#. if (cpuid_eax(0x80000000) >= 0x80000007
+#. && (cpuid_edx(0x80000007) & (1 << 7)))
+#.
+#: utils/cpufreq-info.c:161
+#, c-format
+msgid "  boost state support: \n"
+msgstr ""
+
+#: utils/cpufreq-info.c:163
+#, c-format
+msgid "    Supported: %s\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
+msgid "yes"
+msgstr ""
+
+#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
+msgid "no"
+msgstr ""
+
+#: utils/cpufreq-info.c:164
+#, fuzzy, c-format
+msgid "    Active: %s\n"
+msgstr "  pilote : %s\n"
+
+#: utils/cpufreq-info.c:177
+#, c-format
+msgid "    Boost States: %d\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:178
+#, c-format
+msgid "    Total States: %d\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:181
+#, c-format
+msgid "    Pstate-Pb%d: %luMHz (boost state)\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:184
+#, c-format
+msgid "    Pstate-P%d:  %luMHz\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:211
+#, c-format
+msgid "  no or unknown cpufreq driver is active on this CPU\n"
+msgstr "  pas de pilotes cpufreq reconnu pour ce CPU\n"
+
+#: utils/cpufreq-info.c:213
+#, c-format
+msgid "  driver: %s\n"
+msgstr "  pilote : %s\n"
+
+#: utils/cpufreq-info.c:219
+#, fuzzy, c-format
+msgid "  CPUs which run at the same hardware frequency: "
+msgstr "  CPUs qui doivent changer de fréquences en même temps : "
+
+#: utils/cpufreq-info.c:230
+#, fuzzy, c-format
+msgid "  CPUs which need to have their frequency coordinated by software: "
+msgstr "  CPUs qui doivent changer de fréquences en même temps : "
+
+#: utils/cpufreq-info.c:241
+#, c-format
+msgid "  maximum transition latency: "
+msgstr ""
+
+#: utils/cpufreq-info.c:247
+#, c-format
+msgid "  hardware limits: "
+msgstr "  limitation matérielle : "
+
+#: utils/cpufreq-info.c:256
+#, c-format
+msgid "  available frequency steps: "
+msgstr "  plage de fréquence : "
+
+#: utils/cpufreq-info.c:269
+#, c-format
+msgid "  available cpufreq governors: "
+msgstr "  régulateurs disponibles : "
+
+#: utils/cpufreq-info.c:280
+#, c-format
+msgid "  current policy: frequency should be within "
+msgstr "  tactique actuelle : la fréquence doit être comprise entre "
+
+#: utils/cpufreq-info.c:282
+#, c-format
+msgid " and "
+msgstr " et "
+
+#: utils/cpufreq-info.c:286
+#, c-format
+msgid ""
+"The governor \"%s\" may decide which speed to use\n"
+"                  within this range.\n"
+msgstr ""
+"Le régulateur \"%s\" est libre de choisir la vitesse\n"
+"                  dans cette plage de fréquences.\n"
+
+#: utils/cpufreq-info.c:293
+#, c-format
+msgid "  current CPU frequency is "
+msgstr "  la fréquence actuelle de ce CPU est "
+
+#: utils/cpufreq-info.c:296
+#, c-format
+msgid " (asserted by call to hardware)"
+msgstr " (vérifié par un appel direct du matériel)"
+
+#: utils/cpufreq-info.c:304
+#, c-format
+msgid "  cpufreq stats: "
+msgstr "  des statistique concernant cpufreq:"
+
+#: utils/cpufreq-info.c:472
+#, fuzzy, c-format
+msgid "Usage: cpupower freqinfo [options]\n"
+msgstr "Usage : cpufreq-info [options]\n"
+
+#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
+#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
+#, c-format
+msgid "Options:\n"
+msgstr "Options :\n"
+
+#: utils/cpufreq-info.c:474
+#, fuzzy, c-format
+msgid "  -e, --debug          Prints out debug information [default]\n"
+msgstr "  -e, --debug          Afficher les informations de déboguage\n"
+
+#: utils/cpufreq-info.c:475
+#, c-format
+msgid ""
+"  -f, --freq           Get frequency the CPU currently runs at, according\n"
+"                       to the cpufreq core *\n"
+msgstr ""
+"  -f, --freq           Obtenir la fréquence actuelle du CPU selon le point\n"
+"                       de vue du coeur du système de cpufreq *\n"
+
+#: utils/cpufreq-info.c:477
+#, c-format
+msgid ""
+"  -w, --hwfreq         Get frequency the CPU currently runs at, by reading\n"
+"                       it from hardware (only available to root) *\n"
+msgstr ""
+"  -w, --hwfreq         Obtenir la fréquence actuelle du CPU directement par\n"
+"                       le matériel (doit être root) *\n"
+
+#: utils/cpufreq-info.c:479
+#, c-format
+msgid ""
+"  -l, --hwlimits       Determine the minimum and maximum CPU frequency "
+"allowed *\n"
+msgstr ""
+"  -l, --hwlimits       Affiche les fréquences minimales et maximales du CPU "
+"*\n"
+
+#: utils/cpufreq-info.c:480
+#, c-format
+msgid "  -d, --driver         Determines the used cpufreq kernel driver *\n"
+msgstr "  -d, --driver         Affiche le pilote cpufreq utilisé *\n"
+
+#: utils/cpufreq-info.c:481
+#, c-format
+msgid "  -p, --policy         Gets the currently used cpufreq policy *\n"
+msgstr "  -p, --policy         Affiche la tactique actuelle de cpufreq *\n"
+
+#: utils/cpufreq-info.c:482
+#, c-format
+msgid "  -g, --governors      Determines available cpufreq governors *\n"
+msgstr ""
+"  -g, --governors      Affiche les régulateurs disponibles de cpufreq *\n"
+
+#: utils/cpufreq-info.c:483
+#, fuzzy, c-format
+msgid ""
+"  -r, --related-cpus   Determines which CPUs run at the same hardware "
+"frequency *\n"
+msgstr ""
+"  -a, --affected-cpus   Affiche quels sont les CPUs qui doivent changer de\n"
+"                        fréquences en même temps *\n"
+
+#: utils/cpufreq-info.c:484
+#, fuzzy, c-format
+msgid ""
+"  -a, --affected-cpus  Determines which CPUs need to have their frequency\n"
+"                       coordinated by software *\n"
+msgstr ""
+"  -a, --affected-cpus   Affiche quels sont les CPUs qui doivent changer de\n"
+"                        fréquences en même temps *\n"
+
+#: utils/cpufreq-info.c:486
+#, c-format
+msgid "  -s, --stats          Shows cpufreq statistics if available\n"
+msgstr ""
+"  -s, --stats          Indique des statistiques concernant cpufreq, si\n"
+"                       disponibles\n"
+
+#: utils/cpufreq-info.c:487
+#, fuzzy, c-format
+msgid ""
+"  -y, --latency        Determines the maximum latency on CPU frequency "
+"changes *\n"
+msgstr ""
+"  -l, --hwlimits       Affiche les fréquences minimales et maximales du CPU "
+"*\n"
+
+#: utils/cpufreq-info.c:488
+#, c-format
+msgid "  -b, --boost          Checks for turbo or boost modes  *\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:489
+#, c-format
+msgid ""
+"  -o, --proc           Prints out information like provided by the /proc/"
+"cpufreq\n"
+"                       interface in 2.4. and early 2.6. kernels\n"
+msgstr ""
+"  -o, --proc           Affiche les informations en utilisant l'interface\n"
+"                       fournie par /proc/cpufreq, présente dans les "
+"versions\n"
+"                       2.4 et les anciennes versions 2.6 du noyau\n"
+
+#: utils/cpufreq-info.c:491
+#, fuzzy, c-format
+msgid ""
+"  -m, --human          human-readable output for the -f, -w, -s and -y "
+"parameters\n"
+msgstr ""
+"  -m, --human           affiche dans un format lisible pour un humain\n"
+"                        pour les options -f, -w et -s (MHz, GHz)\n"
+
+#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
+#, c-format
+msgid "  -h, --help           Prints out this screen\n"
+msgstr "  -h, --help           affiche l'aide-mémoire\n"
+
+#: utils/cpufreq-info.c:495
+#, c-format
+msgid ""
+"If no argument or only the -c, --cpu parameter is given, debug output about\n"
+"cpufreq is printed which is useful e.g. for reporting bugs.\n"
+msgstr ""
+"Par défaut, les informations de déboguage seront affichées si aucun\n"
+"argument, ou bien si seulement l'argument -c (--cpu) est donné, afin de\n"
+"faciliter les rapports de bogues par exemple\n"
+
+#: utils/cpufreq-info.c:497
+#, c-format
+msgid ""
+"For the arguments marked with *, omitting the -c or --cpu argument is\n"
+"equivalent to setting it to zero\n"
+msgstr "Les arguments avec un * utiliseront le CPU 0 si -c (--cpu) est omis\n"
+
+#: utils/cpufreq-info.c:580
+#, c-format
+msgid ""
+"The argument passed to this tool can't be combined with passing a --cpu "
+"argument\n"
+msgstr "Cette option est incompatible avec --cpu\n"
+
+#: utils/cpufreq-info.c:596
+#, c-format
+msgid ""
+"You can't specify more than one --cpu parameter and/or\n"
+"more than one output-specific argument\n"
+msgstr ""
+"On ne peut indiquer plus d'un paramètre --cpu, tout comme l'on ne peut\n"
+"spécifier plus d'un argument de formatage\n"
+
+#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
+#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
+#, c-format
+msgid "invalid or unknown argument\n"
+msgstr "option invalide\n"
+
+#: utils/cpufreq-info.c:617
+#, c-format
+msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
+msgstr "analyse du CPU %d impossible puisqu'il ne semble pas être présent\n"
+
+#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
+#, c-format
+msgid "analyzing CPU %d:\n"
+msgstr "analyse du CPU %d :\n"
+
+#: utils/cpufreq-set.c:25
+#, fuzzy, c-format
+msgid "Usage: cpupower frequency-set [options]\n"
+msgstr "Usage : cpufreq-set [options]\n"
+
+#: utils/cpufreq-set.c:27
+#, c-format
+msgid ""
+"  -d FREQ, --min FREQ      new minimum CPU frequency the governor may "
+"select\n"
+msgstr ""
+"  -d FREQ, --min FREQ       nouvelle fréquence minimale du CPU à utiliser\n"
+"                            par le régulateur\n"
+
+#: utils/cpufreq-set.c:28
+#, c-format
+msgid ""
+"  -u FREQ, --max FREQ      new maximum CPU frequency the governor may "
+"select\n"
+msgstr ""
+"  -u FREQ, --max FREQ       nouvelle fréquence maximale du CPU à utiliser\n"
+"                            par le régulateur\n"
+
+#: utils/cpufreq-set.c:29
+#, c-format
+msgid "  -g GOV, --governor GOV   new cpufreq governor\n"
+msgstr "  -g GOV, --governor GOV   active le régulateur GOV\n"
+
+#: utils/cpufreq-set.c:30
+#, c-format
+msgid ""
+"  -f FREQ, --freq FREQ     specific frequency to be set. Requires userspace\n"
+"                           governor to be available and loaded\n"
+msgstr ""
+"  -f FREQ, --freq FREQ     fixe la fréquence du processeur à FREQ. Il faut\n"
+"                           que le régulateur « userspace » soit disponible \n"
+"                           et activé.\n"
+
+#: utils/cpufreq-set.c:32
+#, c-format
+msgid "  -r, --related            Switches all hardware-related CPUs\n"
+msgstr ""
+
+#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
+#, fuzzy, c-format
+msgid "  -h, --help               Prints out this screen\n"
+msgstr "  -h, --help           affiche l'aide-mémoire\n"
+
+#: utils/cpufreq-set.c:35
+#, fuzzy, c-format
+msgid ""
+"Notes:\n"
+"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
+msgstr "Les arguments avec un * utiliseront le CPU 0 si -c (--cpu) est omis\n"
+
+#: utils/cpufreq-set.c:37
+#, fuzzy, c-format
+msgid ""
+"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
+"parameter\n"
+"   except the -c CPU, --cpu CPU parameter\n"
+"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
+"   by postfixing the value with the wanted unit name, without any space\n"
+"   (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
+msgstr ""
+"Remarque :\n"
+"1. Le CPU numéro 0 sera utilisé par défaut si -c (ou --cpu) est omis ;\n"
+"2. l'argument -f FREQ (ou --freq FREQ) ne peut être utilisé qu'avec --cpu ;\n"
+"3. on pourra préciser l'unité des fréquences en postfixant sans aucune "
+"espace\n"
+"   les valeurs par hz, kHz (par défaut), MHz, GHz ou THz\n"
+"   (kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
+
+#: utils/cpufreq-set.c:57
+#, c-format
+msgid ""
+"Error setting new values. Common errors:\n"
+"- Do you have proper administration rights? (super-user?)\n"
+"- Is the governor you requested available and modprobed?\n"
+"- Trying to set an invalid policy?\n"
+"- Trying to set a specific frequency, but userspace governor is not "
+"available,\n"
+"   for example because of hardware which cannot be set to a specific "
+"frequency\n"
+"   or because the userspace governor isn't loaded?\n"
+msgstr ""
+"En ajustant les nouveaux paramètres, une erreur est apparue. Les sources\n"
+"d'erreur typique sont :\n"
+"- droit d'administration insuffisant (êtes-vous root ?) ;\n"
+"- le régulateur choisi n'est pas disponible, ou bien n'est pas disponible "
+"en\n"
+"  tant que module noyau ;\n"
+"- la tactique n'est pas disponible ;\n"
+"- vous voulez utiliser l'option -f/--freq, mais le régulateur « userspace »\n"
+"  n'est pas disponible, par exemple parce que le matériel ne le supporte\n"
+"  pas, ou bien n'est tout simplement pas chargé.\n"
+
+#: utils/cpufreq-set.c:170
+#, c-format
+msgid "wrong, unknown or unhandled CPU?\n"
+msgstr "CPU inconnu ou non supporté ?\n"
+
+#: utils/cpufreq-set.c:302
+#, c-format
+msgid ""
+"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
+"-g/--governor parameters\n"
+msgstr ""
+"l'option -f/--freq est incompatible avec les options -d/--min, -u/--max et\n"
+"-g/--governor\n"
+
+#: utils/cpufreq-set.c:308
+#, c-format
+msgid ""
+"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
+"-g/--governor must be passed\n"
+msgstr ""
+"L'un de ces paramètres est obligatoire : -f/--freq, -d/--min, -u/--max et\n"
+"-g/--governor\n"
+
+#: utils/cpufreq-set.c:347
+#, c-format
+msgid "Setting cpu: %d\n"
+msgstr ""
+
+#: utils/cpupower-set.c:22
+#, c-format
+msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:24
+#, c-format
+msgid ""
+"  -b, --perf-bias [VAL]    Sets CPU's power vs performance policy on some\n"
+"                           Intel models [0-15], see manpage for details\n"
+msgstr ""
+
+#: utils/cpupower-set.c:26
+#, c-format
+msgid ""
+"  -m, --sched-mc  [VAL]    Sets the kernel's multi core scheduler policy.\n"
+msgstr ""
+
+#: utils/cpupower-set.c:27
+#, c-format
+msgid ""
+"  -s, --sched-smt [VAL]    Sets the kernel's thread sibling scheduler "
+"policy.\n"
+msgstr ""
+
+#: utils/cpupower-set.c:80
+#, c-format
+msgid "--perf-bias param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:91
+#, c-format
+msgid "--sched-mc param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:102
+#, c-format
+msgid "--sched-smt param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:121
+#, c-format
+msgid "Error setting sched-mc %s\n"
+msgstr ""
+
+#: utils/cpupower-set.c:127
+#, c-format
+msgid "Error setting sched-smt %s\n"
+msgstr ""
+
+#: utils/cpupower-set.c:146
+#, c-format
+msgid "Error setting perf-bias value on CPU %d\n"
+msgstr ""
+
+#: utils/cpupower-info.c:21
+#, c-format
+msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
+msgstr ""
+
+#: utils/cpupower-info.c:23
+#, c-format
+msgid ""
+"  -b, --perf-bias    Gets CPU's power vs performance policy on some\n"
+"                           Intel models [0-15], see manpage for details\n"
+msgstr ""
+
+#: utils/cpupower-info.c:25
+#, fuzzy, c-format
+msgid "  -m, --sched-mc     Gets the kernel's multi core scheduler policy.\n"
+msgstr "  -p, --policy         Affiche la tactique actuelle de cpufreq *\n"
+
+#: utils/cpupower-info.c:26
+#, c-format
+msgid ""
+"  -s, --sched-smt    Gets the kernel's thread sibling scheduler policy.\n"
+msgstr ""
+
+#: utils/cpupower-info.c:28
+#, c-format
+msgid ""
+"\n"
+"Passing no option will show all info, by default only on core 0\n"
+msgstr ""
+
+#: utils/cpupower-info.c:102
+#, c-format
+msgid "System's multi core scheduler setting: "
+msgstr ""
+
+#. if sysfs file is missing it's: errno == ENOENT
+#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
+#, c-format
+msgid "not supported\n"
+msgstr ""
+
+#: utils/cpupower-info.c:111
+#, c-format
+msgid "System's thread sibling scheduler setting: "
+msgstr ""
+
+#: utils/cpupower-info.c:126
+#, c-format
+msgid "Intel's performance bias setting needs root privileges\n"
+msgstr ""
+
+#: utils/cpupower-info.c:128
+#, c-format
+msgid "System does not support Intel's performance bias setting\n"
+msgstr ""
+
+#: utils/cpupower-info.c:147
+#, c-format
+msgid "Could not read perf-bias value\n"
+msgstr ""
+
+#: utils/cpupower-info.c:150
+#, c-format
+msgid "perf-bias: %d\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:28
+#, fuzzy, c-format
+msgid "Analyzing CPU %d:\n"
+msgstr "analyse du CPU %d :\n"
+
+#: utils/cpuidle-info.c:32
+#, c-format
+msgid "CPU %u: No idle states\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:36
+#, c-format
+msgid "CPU %u: Can't read idle state info\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:41
+#, c-format
+msgid "Could not determine max idle state %u\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:46
+#, c-format
+msgid "Number of idle states: %d\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:48
+#, fuzzy, c-format
+msgid "Available idle states:"
+msgstr "  plage de fréquence : "
+
+#: utils/cpuidle-info.c:71
+#, c-format
+msgid "Flags/Description: %s\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:74
+#, c-format
+msgid "Latency: %lu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:76
+#, c-format
+msgid "Usage: %lu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:78
+#, c-format
+msgid "Duration: %llu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:90
+#, c-format
+msgid "Could not determine cpuidle driver\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:94
+#, fuzzy, c-format
+msgid "CPUidle driver: %s\n"
+msgstr "  pilote : %s\n"
+
+#: utils/cpuidle-info.c:99
+#, c-format
+msgid "Could not determine cpuidle governor\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:103
+#, c-format
+msgid "CPUidle governor: %s\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:122
+#, c-format
+msgid "CPU %u: Can't read C-state info\n"
+msgstr ""
+
+#. printf("Cstates: %d\n", cstates);
+#: utils/cpuidle-info.c:127
+#, c-format
+msgid "active state:            C0\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:128
+#, c-format
+msgid "max_cstate:              C%u\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:129
+#, c-format
+msgid "maximum allowed latency: %lu usec\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:130
+#, c-format
+msgid "states:\t\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:132
+#, c-format
+msgid "    C%d:                  type[C%d] "
+msgstr ""
+
+#: utils/cpuidle-info.c:134
+#, c-format
+msgid "promotion[--] demotion[--] "
+msgstr ""
+
+#: utils/cpuidle-info.c:135
+#, c-format
+msgid "latency[%03lu] "
+msgstr ""
+
+#: utils/cpuidle-info.c:137
+#, c-format
+msgid "usage[%08lu] "
+msgstr ""
+
+#: utils/cpuidle-info.c:139
+#, c-format
+msgid "duration[%020Lu] \n"
+msgstr ""
+
+#: utils/cpuidle-info.c:147
+#, fuzzy, c-format
+msgid "Usage: cpupower idleinfo [options]\n"
+msgstr "Usage : cpufreq-info [options]\n"
+
+#: utils/cpuidle-info.c:149
+#, fuzzy, c-format
+msgid "  -s, --silent         Only show general C-state information\n"
+msgstr "  -e, --debug          Afficher les informations de déboguage\n"
+
+#: utils/cpuidle-info.c:150
+#, fuzzy, c-format
+msgid ""
+"  -o, --proc           Prints out information like provided by the /proc/"
+"acpi/processor/*/power\n"
+"                       interface in older kernels\n"
+msgstr ""
+"  -o, --proc           Affiche les informations en utilisant l'interface\n"
+"                       fournie par /proc/cpufreq, présente dans les "
+"versions\n"
+"                       2.4 et les anciennes versions 2.6 du noyau\n"
+
+#: utils/cpuidle-info.c:209
+#, fuzzy, c-format
+msgid "You can't specify more than one output-specific argument\n"
+msgstr ""
+"On ne peut indiquer plus d'un paramètre --cpu, tout comme l'on ne peut\n"
+"spécifier plus d'un argument de formatage\n"
+
+#~ msgid ""
+#~ "  -c CPU, --cpu CPU    CPU number which information shall be determined "
+#~ "about\n"
+#~ msgstr ""
+#~ "  -c CPU, --cpu CPU    Numéro du CPU pour lequel l'information sera "
+#~ "affichée\n"
+
+#~ msgid ""
+#~ "  -c CPU, --cpu CPU        number of CPU where cpufreq settings shall be "
+#~ "modified\n"
+#~ msgstr ""
+#~ "  -c CPU, --cpu CPU        numéro du CPU à prendre en compte pour les\n"
+#~ "                           changements\n"
diff --git a/tools/power/cpupower/po/it.po b/tools/power/cpupower/po/it.po
new file mode 100644 (file)
index 0000000..f80c4dd
--- /dev/null
@@ -0,0 +1,961 @@
+# Italian translations for cpufrequtils package
+# Copyright (C) 2004-2009
+# This file is distributed under the same license as the cpufrequtils package.
+# Mattia Dongili <malattia@gmail.com>.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cpufrequtils 0.3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-03-08 17:03+0100\n"
+"PO-Revision-Date: 2009-08-15 12:00+0900\n"
+"Last-Translator: Mattia Dongili <malattia@gmail.com>\n"
+"Language-Team: NONE\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: utils/idle_monitor/nhm_idle.c:36
+msgid "Processor Core C3"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:43
+msgid "Processor Core C6"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:51
+msgid "Processor Package C3"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
+msgid "Processor Package C6"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:33
+msgid "Processor Core C7"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:40
+msgid "Processor Package C2"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:47
+msgid "Processor Package C7"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:56
+msgid "Package in sleep state (PC1 or deeper)"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:63
+msgid "Processor Package C1"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:77
+msgid "North Bridge P1 boolean counter (returns 0 or 1)"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:35
+msgid "Processor Core not idle"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:42
+msgid "Processor Core in an idle state"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:50
+msgid "Average Frequency (including boost) in MHz"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:66
+#, c-format
+msgid ""
+"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
+"interval_sec | -c command ...]\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:69
+#, c-format
+msgid ""
+"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
+"interval_sec | -c command ...]\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:71
+#, c-format
+msgid "\t -v: be more verbose\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:73
+#, c-format
+msgid "\t -h: print this help\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:74
+#, c-format
+msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:75
+#, c-format
+msgid "\t -t: show CPU topology/hierarchy\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:76
+#, c-format
+msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:77
+#, c-format
+msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:79
+#, c-format
+msgid ""
+"only one of: -t, -l, -m are allowed\n"
+"If none of them is passed,"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:80
+#, c-format
+msgid " all supported monitors are shown\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:197
+#, c-format
+msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:207
+#, c-format
+msgid " *is offline\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:236
+#, c-format
+msgid "%s: max monitor name length (%d) exceeded\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:250
+#, c-format
+msgid "No matching monitor found in %s, try -l option\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:266
+#, c-format
+msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:319
+#, c-format
+msgid "%s took %.5f seconds and exited with status %d\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:406
+#, c-format
+msgid "Cannot read number of available processors\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:417
+#, c-format
+msgid "Available monitor %s needs root access\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:428
+#, c-format
+msgid "No HW Cstate monitors found\n"
+msgstr ""
+
+#: utils/cpupower.c:78
+#, c-format
+msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
+msgstr ""
+
+#: utils/cpupower.c:79
+#, c-format
+msgid "cpupower --version\n"
+msgstr ""
+
+#: utils/cpupower.c:80
+#, c-format
+msgid "Supported subcommands are:\n"
+msgstr ""
+
+#: utils/cpupower.c:83
+#, c-format
+msgid ""
+"\n"
+"Some subcommands can make use of the -c cpulist option.\n"
+msgstr ""
+
+#: utils/cpupower.c:84
+#, c-format
+msgid "Look at the general cpupower manpage how to use it\n"
+msgstr ""
+
+#: utils/cpupower.c:85
+#, c-format
+msgid "and read up the subcommand's manpage whether it is supported.\n"
+msgstr ""
+
+#: utils/cpupower.c:86
+#, c-format
+msgid ""
+"\n"
+"Use cpupower help subcommand for getting help for above subcommands.\n"
+msgstr ""
+
+#: utils/cpupower.c:91
+#, c-format
+msgid "Report errors and bugs to %s, please.\n"
+msgstr "Per favore, comunicare errori e malfunzionamenti a %s.\n"
+
+#: utils/cpupower.c:114
+#, c-format
+msgid "Error parsing cpu list\n"
+msgstr ""
+
+#: utils/cpupower.c:172
+#, c-format
+msgid "Subcommand %s needs root privileges\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:31
+#, c-format
+msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
+msgstr "Impossibile determinare il numero di CPU (%s: %s), assumo sia 1\n"
+
+#: utils/cpufreq-info.c:63
+#, c-format
+msgid ""
+"          minimum CPU frequency  -  maximum CPU frequency  -  governor\n"
+msgstr ""
+"          frequenza minima CPU   -  frequenza massima CPU  -  gestore\n"
+
+#: utils/cpufreq-info.c:151
+#, c-format
+msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
+msgstr ""
+
+#. P state changes via MSR are identified via cpuid 80000007
+#. on Intel and AMD, but we assume boost capable machines can do that
+#. if (cpuid_eax(0x80000000) >= 0x80000007
+#. && (cpuid_edx(0x80000007) & (1 << 7)))
+#.
+#: utils/cpufreq-info.c:161
+#, c-format
+msgid "  boost state support: \n"
+msgstr ""
+
+#: utils/cpufreq-info.c:163
+#, c-format
+msgid "    Supported: %s\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
+msgid "yes"
+msgstr ""
+
+#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
+msgid "no"
+msgstr ""
+
+#: utils/cpufreq-info.c:164
+#, fuzzy, c-format
+msgid "    Active: %s\n"
+msgstr "  modulo %s\n"
+
+#: utils/cpufreq-info.c:177
+#, c-format
+msgid "    Boost States: %d\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:178
+#, c-format
+msgid "    Total States: %d\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:181
+#, c-format
+msgid "    Pstate-Pb%d: %luMHz (boost state)\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:184
+#, c-format
+msgid "    Pstate-P%d:  %luMHz\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:211
+#, c-format
+msgid "  no or unknown cpufreq driver is active on this CPU\n"
+msgstr "  nessun modulo o modulo cpufreq sconosciuto per questa CPU\n"
+
+#: utils/cpufreq-info.c:213
+#, c-format
+msgid "  driver: %s\n"
+msgstr "  modulo %s\n"
+
+#: utils/cpufreq-info.c:219
+#, c-format
+msgid "  CPUs which run at the same hardware frequency: "
+msgstr "  CPU che operano alla stessa frequenza hardware: "
+
+#: utils/cpufreq-info.c:230
+#, c-format
+msgid "  CPUs which need to have their frequency coordinated by software: "
+msgstr "  CPU che è necessario siano coordinate dal software: "
+
+#: utils/cpufreq-info.c:241
+#, c-format
+msgid "  maximum transition latency: "
+msgstr "  latenza massima durante la transizione: "
+
+#: utils/cpufreq-info.c:247
+#, c-format
+msgid "  hardware limits: "
+msgstr "  limiti hardware: "
+
+#: utils/cpufreq-info.c:256
+#, c-format
+msgid "  available frequency steps: "
+msgstr "  frequenze disponibili: "
+
+#: utils/cpufreq-info.c:269
+#, c-format
+msgid "  available cpufreq governors: "
+msgstr "  gestori disponibili: "
+
+#: utils/cpufreq-info.c:280
+#, c-format
+msgid "  current policy: frequency should be within "
+msgstr "  gestore attuale: la frequenza deve mantenersi tra "
+
+#: utils/cpufreq-info.c:282
+#, c-format
+msgid " and "
+msgstr " e "
+
+#: utils/cpufreq-info.c:286
+#, c-format
+msgid ""
+"The governor \"%s\" may decide which speed to use\n"
+"                  within this range.\n"
+msgstr ""
+" Il gestore \"%s\" può decidere quale velocità usare\n"
+"                  in questo intervallo.\n"
+
+#: utils/cpufreq-info.c:293
+#, c-format
+msgid "  current CPU frequency is "
+msgstr "  la frequenza attuale della CPU è "
+
+#: utils/cpufreq-info.c:296
+#, c-format
+msgid " (asserted by call to hardware)"
+msgstr " (ottenuta da una chiamata diretta all'hardware)"
+
+#: utils/cpufreq-info.c:304
+#, c-format
+msgid "  cpufreq stats: "
+msgstr " statistiche cpufreq:"
+
+#: utils/cpufreq-info.c:472
+#, fuzzy, c-format
+msgid "Usage: cpupower freqinfo [options]\n"
+msgstr "Uso: cpufreq-info [opzioni]\n"
+
+#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
+#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
+#, c-format
+msgid "Options:\n"
+msgstr "Opzioni:\n"
+
+#: utils/cpufreq-info.c:474
+#, fuzzy, c-format
+msgid "  -e, --debug          Prints out debug information [default]\n"
+msgstr "  -e, --debug          Mostra informazioni di debug\n"
+
+#: utils/cpufreq-info.c:475
+#, c-format
+msgid ""
+"  -f, --freq           Get frequency the CPU currently runs at, according\n"
+"                       to the cpufreq core *\n"
+msgstr ""
+"  -f, --freq           Mostra la frequenza attuale della CPU secondo\n"
+"                       il modulo cpufreq *\n"
+
+#: utils/cpufreq-info.c:477
+#, c-format
+msgid ""
+"  -w, --hwfreq         Get frequency the CPU currently runs at, by reading\n"
+"                       it from hardware (only available to root) *\n"
+msgstr ""
+"  -w, --hwfreq         Mostra la frequenza attuale della CPU leggendola\n"
+"                       dall'hardware (disponibile solo per l'utente root) *\n"
+
+#: utils/cpufreq-info.c:479
+#, c-format
+msgid ""
+"  -l, --hwlimits       Determine the minimum and maximum CPU frequency "
+"allowed *\n"
+msgstr ""
+"  -l, --hwlimits       Determina le frequenze minima e massima possibili per "
+"la CPU *\n"
+
+#: utils/cpufreq-info.c:480
+#, c-format
+msgid "  -d, --driver         Determines the used cpufreq kernel driver *\n"
+msgstr ""
+"  -d, --driver         Determina il modulo cpufreq del kernel in uso *\n"
+
+#: utils/cpufreq-info.c:481
+#, c-format
+msgid "  -p, --policy         Gets the currently used cpufreq policy *\n"
+msgstr ""
+"  -p, --policy         Mostra il gestore cpufreq attualmente in uso *\n"
+
+#: utils/cpufreq-info.c:482
+#, c-format
+msgid "  -g, --governors      Determines available cpufreq governors *\n"
+msgstr "  -g, --governors      Determina i gestori cpufreq disponibili *\n"
+
+#: utils/cpufreq-info.c:483
+#, c-format
+msgid ""
+"  -r, --related-cpus   Determines which CPUs run at the same hardware "
+"frequency *\n"
+msgstr ""
+"  -r, --related-cpus   Determina quali CPU operano alla stessa frequenza *\n"
+
+#: utils/cpufreq-info.c:484
+#, c-format
+msgid ""
+"  -a, --affected-cpus  Determines which CPUs need to have their frequency\n"
+"                       coordinated by software *\n"
+msgstr ""
+"  -a, --affected-cpus  Determina quali CPU devono avere la frequenza\n"
+"                       coordinata dal software *\n"
+
+#: utils/cpufreq-info.c:486
+#, c-format
+msgid "  -s, --stats          Shows cpufreq statistics if available\n"
+msgstr "  -s, --stats          Mostra le statistiche se disponibili\n"
+
+#: utils/cpufreq-info.c:487
+#, c-format
+msgid ""
+"  -y, --latency        Determines the maximum latency on CPU frequency "
+"changes *\n"
+msgstr ""
+"  -y, --latency        Determina la latenza massima durante i cambi di "
+"frequenza *\n"
+
+#: utils/cpufreq-info.c:488
+#, c-format
+msgid "  -b, --boost          Checks for turbo or boost modes  *\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:489
+#, c-format
+msgid ""
+"  -o, --proc           Prints out information like provided by the /proc/"
+"cpufreq\n"
+"                       interface in 2.4. and early 2.6. kernels\n"
+msgstr ""
+"  -o, --proc           Stampa le informazioni come se provenissero dalla\n"
+"                       interfaccia cpufreq /proc/ presente nei kernel\n"
+"                       2.4 ed i primi 2.6\n"
+
+#: utils/cpufreq-info.c:491
+#, c-format
+msgid ""
+"  -m, --human          human-readable output for the -f, -w, -s and -y "
+"parameters\n"
+msgstr ""
+"  -m, --human          formatta l'output delle opzioni -f, -w, -s e -y in "
+"maniera\n"
+"                       leggibile da un essere umano\n"
+
+#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
+#, c-format
+msgid "  -h, --help           Prints out this screen\n"
+msgstr "  -h, --help           Stampa questa schermata\n"
+
+#: utils/cpufreq-info.c:495
+#, c-format
+msgid ""
+"If no argument or only the -c, --cpu parameter is given, debug output about\n"
+"cpufreq is printed which is useful e.g. for reporting bugs.\n"
+msgstr ""
+"Se non viene specificata nessuna opzione o viene specificata solo l'opzione -"
+"c, --cpu,\n"
+"le informazioni di debug per cpufreq saranno utili ad esempio a riportare i "
+"bug.\n"
+
+#: utils/cpufreq-info.c:497
+#, c-format
+msgid ""
+"For the arguments marked with *, omitting the -c or --cpu argument is\n"
+"equivalent to setting it to zero\n"
+msgstr ""
+"Per le opzioni segnalate con *, omettere l'opzione -c o --cpu è come "
+"specificarla\n"
+"con il valore 0\n"
+
+#: utils/cpufreq-info.c:580
+#, c-format
+msgid ""
+"The argument passed to this tool can't be combined with passing a --cpu "
+"argument\n"
+msgstr ""
+"L'opzione specificata a questo programma non può essere combinata con --cpu\n"
+
+#: utils/cpufreq-info.c:596
+#, c-format
+msgid ""
+"You can't specify more than one --cpu parameter and/or\n"
+"more than one output-specific argument\n"
+msgstr ""
+"Non è possibile specificare più di una volta l'opzione --cpu e/o\n"
+"specificare più di un parametro di output specifico\n"
+
+#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
+#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
+#, c-format
+msgid "invalid or unknown argument\n"
+msgstr "opzione sconosciuta o non valida\n"
+
+#: utils/cpufreq-info.c:617
+#, c-format
+msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
+msgstr "impossibile analizzare la CPU %d poiché non sembra essere presente\n"
+
+#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
+#, c-format
+msgid "analyzing CPU %d:\n"
+msgstr "analisi della CPU %d:\n"
+
+#: utils/cpufreq-set.c:25
+#, fuzzy, c-format
+msgid "Usage: cpupower frequency-set [options]\n"
+msgstr "Uso: cpufreq-set [opzioni]\n"
+
+#: utils/cpufreq-set.c:27
+#, c-format
+msgid ""
+"  -d FREQ, --min FREQ      new minimum CPU frequency the governor may "
+"select\n"
+msgstr ""
+"  -d FREQ, --min FREQ      la nuova frequenza minima che il gestore cpufreq "
+"può scegliere\n"
+
+#: utils/cpufreq-set.c:28
+#, c-format
+msgid ""
+"  -u FREQ, --max FREQ      new maximum CPU frequency the governor may "
+"select\n"
+msgstr ""
+"  -u FREQ, --max FREQ      la nuova frequenza massima che il gestore cpufreq "
+"può scegliere\n"
+
+#: utils/cpufreq-set.c:29
+#, c-format
+msgid "  -g GOV, --governor GOV   new cpufreq governor\n"
+msgstr "  -g GOV, --governor GOV   nuovo gestore cpufreq\n"
+
+#: utils/cpufreq-set.c:30
+#, c-format
+msgid ""
+"  -f FREQ, --freq FREQ     specific frequency to be set. Requires userspace\n"
+"                           governor to be available and loaded\n"
+msgstr ""
+"  -f FREQ, --freq FREQ     specifica la frequenza a cui impostare la CPU.\n"
+"                           È necessario che il gestore userspace sia "
+"disponibile e caricato\n"
+
+#: utils/cpufreq-set.c:32
+#, c-format
+msgid "  -r, --related            Switches all hardware-related CPUs\n"
+msgstr ""
+"  -r, --related            Modifica tutte le CPU coordinate dall'hardware\n"
+
+#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
+#, c-format
+msgid "  -h, --help               Prints out this screen\n"
+msgstr "  -h, --help               Stampa questa schermata\n"
+
+#: utils/cpufreq-set.c:35
+#, fuzzy, c-format
+msgid ""
+"Notes:\n"
+"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
+msgstr ""
+"Per le opzioni segnalate con *, omettere l'opzione -c o --cpu è come "
+"specificarla\n"
+"con il valore 0\n"
+
+#: utils/cpufreq-set.c:37
+#, fuzzy, c-format
+msgid ""
+"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
+"parameter\n"
+"   except the -c CPU, --cpu CPU parameter\n"
+"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
+"   by postfixing the value with the wanted unit name, without any space\n"
+"   (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
+msgstr ""
+"Note:\n"
+"1. Omettere l'opzione -c o --cpu è equivalente a impostarlo a 0\n"
+"2. l'opzione -f FREQ, --freq FREQ non può essere specificata con altre "
+"opzioni\n"
+"   ad eccezione dell'opzione -c CPU o --cpu CPU\n"
+"3. le FREQuenze possono essere specuficate in  Hz, kHz (default), MHz, GHz, "
+"or THz\n"
+"   postponendo l'unità di misura al valore senza nessuno spazio fra loro\n"
+"   (FREQuenza in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
+
+#: utils/cpufreq-set.c:57
+#, c-format
+msgid ""
+"Error setting new values. Common errors:\n"
+"- Do you have proper administration rights? (super-user?)\n"
+"- Is the governor you requested available and modprobed?\n"
+"- Trying to set an invalid policy?\n"
+"- Trying to set a specific frequency, but userspace governor is not "
+"available,\n"
+"   for example because of hardware which cannot be set to a specific "
+"frequency\n"
+"   or because the userspace governor isn't loaded?\n"
+msgstr ""
+"Si sono verificati degli errori impostando i nuovi valori.\n"
+"Alcuni errori comuni possono essere:\n"
+"- Hai i necessari diritti di amministrazione? (super-user?)\n"
+"- Il gestore che hai richiesto è disponibile e caricato?\n"
+"- Stai provando ad impostare una politica di gestione non valida?\n"
+"- Stai provando a impostare una specifica frequenza ma il gestore\n"
+"  userspace non è disponibile, per esempio a causa dell'hardware\n"
+"  che non supporta frequenze fisse o a causa del fatto che\n"
+"  il gestore userspace non è caricato?\n"
+
+#: utils/cpufreq-set.c:170
+#, c-format
+msgid "wrong, unknown or unhandled CPU?\n"
+msgstr "CPU errata, sconosciuta o non gestita?\n"
+
+#: utils/cpufreq-set.c:302
+#, c-format
+msgid ""
+"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
+"-g/--governor parameters\n"
+msgstr ""
+"l'opzione -f/--freq non può venire combinata con i parametri\n"
+" -d/--min, -u/--max o -g/--governor\n"
+
+#: utils/cpufreq-set.c:308
+#, c-format
+msgid ""
+"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
+"-g/--governor must be passed\n"
+msgstr ""
+"Almeno una delle opzioni -f/--freq, -d/--min, -u/--max, e -g/--governor\n"
+"deve essere specificata\n"
+
+#: utils/cpufreq-set.c:347
+#, c-format
+msgid "Setting cpu: %d\n"
+msgstr ""
+
+#: utils/cpupower-set.c:22
+#, c-format
+msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:24
+#, c-format
+msgid ""
+"  -b, --perf-bias [VAL]    Sets CPU's power vs performance policy on some\n"
+"                           Intel models [0-15], see manpage for details\n"
+msgstr ""
+
+#: utils/cpupower-set.c:26
+#, c-format
+msgid ""
+"  -m, --sched-mc  [VAL]    Sets the kernel's multi core scheduler policy.\n"
+msgstr ""
+
+#: utils/cpupower-set.c:27
+#, c-format
+msgid ""
+"  -s, --sched-smt [VAL]    Sets the kernel's thread sibling scheduler "
+"policy.\n"
+msgstr ""
+
+#: utils/cpupower-set.c:80
+#, c-format
+msgid "--perf-bias param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:91
+#, c-format
+msgid "--sched-mc param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:102
+#, c-format
+msgid "--sched-smt param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:121
+#, c-format
+msgid "Error setting sched-mc %s\n"
+msgstr ""
+
+#: utils/cpupower-set.c:127
+#, c-format
+msgid "Error setting sched-smt %s\n"
+msgstr ""
+
+#: utils/cpupower-set.c:146
+#, c-format
+msgid "Error setting perf-bias value on CPU %d\n"
+msgstr ""
+
+#: utils/cpupower-info.c:21
+#, c-format
+msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
+msgstr ""
+
+#: utils/cpupower-info.c:23
+#, c-format
+msgid ""
+"  -b, --perf-bias    Gets CPU's power vs performance policy on some\n"
+"                           Intel models [0-15], see manpage for details\n"
+msgstr ""
+
+#: utils/cpupower-info.c:25
+#, fuzzy, c-format
+msgid "  -m, --sched-mc     Gets the kernel's multi core scheduler policy.\n"
+msgstr ""
+"  -p, --policy         Mostra il gestore cpufreq attualmente in uso *\n"
+
+#: utils/cpupower-info.c:26
+#, c-format
+msgid ""
+"  -s, --sched-smt    Gets the kernel's thread sibling scheduler policy.\n"
+msgstr ""
+
+#: utils/cpupower-info.c:28
+#, c-format
+msgid ""
+"\n"
+"Passing no option will show all info, by default only on core 0\n"
+msgstr ""
+
+#: utils/cpupower-info.c:102
+#, c-format
+msgid "System's multi core scheduler setting: "
+msgstr ""
+
+#. if sysfs file is missing it's: errno == ENOENT
+#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
+#, c-format
+msgid "not supported\n"
+msgstr ""
+
+#: utils/cpupower-info.c:111
+#, c-format
+msgid "System's thread sibling scheduler setting: "
+msgstr ""
+
+#: utils/cpupower-info.c:126
+#, c-format
+msgid "Intel's performance bias setting needs root privileges\n"
+msgstr ""
+
+#: utils/cpupower-info.c:128
+#, c-format
+msgid "System does not support Intel's performance bias setting\n"
+msgstr ""
+
+#: utils/cpupower-info.c:147
+#, c-format
+msgid "Could not read perf-bias value\n"
+msgstr ""
+
+#: utils/cpupower-info.c:150
+#, c-format
+msgid "perf-bias: %d\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:28
+#, fuzzy, c-format
+msgid "Analyzing CPU %d:\n"
+msgstr "analisi della CPU %d:\n"
+
+#: utils/cpuidle-info.c:32
+#, c-format
+msgid "CPU %u: No idle states\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:36
+#, c-format
+msgid "CPU %u: Can't read idle state info\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:41
+#, c-format
+msgid "Could not determine max idle state %u\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:46
+#, c-format
+msgid "Number of idle states: %d\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:48
+#, fuzzy, c-format
+msgid "Available idle states:"
+msgstr "  frequenze disponibili: "
+
+#: utils/cpuidle-info.c:71
+#, c-format
+msgid "Flags/Description: %s\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:74
+#, c-format
+msgid "Latency: %lu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:76
+#, c-format
+msgid "Usage: %lu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:78
+#, c-format
+msgid "Duration: %llu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:90
+#, c-format
+msgid "Could not determine cpuidle driver\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:94
+#, fuzzy, c-format
+msgid "CPUidle driver: %s\n"
+msgstr "  modulo %s\n"
+
+#: utils/cpuidle-info.c:99
+#, c-format
+msgid "Could not determine cpuidle governor\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:103
+#, c-format
+msgid "CPUidle governor: %s\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:122
+#, c-format
+msgid "CPU %u: Can't read C-state info\n"
+msgstr ""
+
+#. printf("Cstates: %d\n", cstates);
+#: utils/cpuidle-info.c:127
+#, c-format
+msgid "active state:            C0\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:128
+#, c-format
+msgid "max_cstate:              C%u\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:129
+#, fuzzy, c-format
+msgid "maximum allowed latency: %lu usec\n"
+msgstr "  latenza massima durante la transizione: "
+
+#: utils/cpuidle-info.c:130
+#, c-format
+msgid "states:\t\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:132
+#, c-format
+msgid "    C%d:                  type[C%d] "
+msgstr ""
+
+#: utils/cpuidle-info.c:134
+#, c-format
+msgid "promotion[--] demotion[--] "
+msgstr ""
+
+#: utils/cpuidle-info.c:135
+#, c-format
+msgid "latency[%03lu] "
+msgstr ""
+
+#: utils/cpuidle-info.c:137
+#, c-format
+msgid "usage[%08lu] "
+msgstr ""
+
+#: utils/cpuidle-info.c:139
+#, c-format
+msgid "duration[%020Lu] \n"
+msgstr ""
+
+#: utils/cpuidle-info.c:147
+#, fuzzy, c-format
+msgid "Usage: cpupower idleinfo [options]\n"
+msgstr "Uso: cpufreq-info [opzioni]\n"
+
+#: utils/cpuidle-info.c:149
+#, fuzzy, c-format
+msgid "  -s, --silent         Only show general C-state information\n"
+msgstr "  -e, --debug          Mostra informazioni di debug\n"
+
+#: utils/cpuidle-info.c:150
+#, fuzzy, c-format
+msgid ""
+"  -o, --proc           Prints out information like provided by the /proc/"
+"acpi/processor/*/power\n"
+"                       interface in older kernels\n"
+msgstr ""
+"  -o, --proc           Stampa le informazioni come se provenissero dalla\n"
+"                       interfaccia cpufreq /proc/ presente nei kernel\n"
+"                       2.4 ed i primi 2.6\n"
+
+#: utils/cpuidle-info.c:209
+#, fuzzy, c-format
+msgid "You can't specify more than one output-specific argument\n"
+msgstr ""
+"Non è possibile specificare più di una volta l'opzione --cpu e/o\n"
+"specificare più di un parametro di output specifico\n"
+
+#~ msgid ""
+#~ "  -c CPU, --cpu CPU    CPU number which information shall be determined "
+#~ "about\n"
+#~ msgstr ""
+#~ "  -c CPU, --cpu CPU    Numero di CPU per la quale ottenere le "
+#~ "informazioni\n"
+
+#~ msgid ""
+#~ "  -c CPU, --cpu CPU        number of CPU where cpufreq settings shall be "
+#~ "modified\n"
+#~ msgstr ""
+#~ "  -c CPU, --cpu CPU        numero di CPU per la quale modificare le "
+#~ "impostazioni\n"
+
+#, fuzzy
+#~ msgid "  CPUs which coordinate software frequency requirements: "
+#~ msgstr ""
+#~ "  CPU per le quali e` necessario cambiare la frequenza "
+#~ "contemporaneamente: "
diff --git a/tools/power/cpupower/po/pt.po b/tools/power/cpupower/po/pt.po
new file mode 100644 (file)
index 0000000..990f526
--- /dev/null
@@ -0,0 +1,957 @@
+# Brazilian Portuguese translations for cpufrequtils package
+# Copyright (C) 2008 THE cpufrequtils'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the cpufrequtils package.
+# Claudio Eduardo <claudioeddy@gmail.com>, 2009.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cpufrequtils 004\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-03-08 17:03+0100\n"
+"PO-Revision-Date: 2008-06-14 22:16-0400\n"
+"Last-Translator: Claudio Eduardo <claudioeddy@gmail.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: utils/idle_monitor/nhm_idle.c:36
+msgid "Processor Core C3"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:43
+msgid "Processor Core C6"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:51
+msgid "Processor Package C3"
+msgstr ""
+
+#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
+msgid "Processor Package C6"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:33
+msgid "Processor Core C7"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:40
+msgid "Processor Package C2"
+msgstr ""
+
+#: utils/idle_monitor/snb_idle.c:47
+msgid "Processor Package C7"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:56
+msgid "Package in sleep state (PC1 or deeper)"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:63
+msgid "Processor Package C1"
+msgstr ""
+
+#: utils/idle_monitor/amd_fam14h_idle.c:77
+msgid "North Bridge P1 boolean counter (returns 0 or 1)"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:35
+msgid "Processor Core not idle"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:42
+msgid "Processor Core in an idle state"
+msgstr ""
+
+#: utils/idle_monitor/mperf_monitor.c:50
+msgid "Average Frequency (including boost) in MHz"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:66
+#, c-format
+msgid ""
+"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
+"interval_sec | -c command ...]\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:69
+#, c-format
+msgid ""
+"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
+"interval_sec | -c command ...]\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:71
+#, c-format
+msgid "\t -v: be more verbose\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:73
+#, c-format
+msgid "\t -h: print this help\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:74
+#, c-format
+msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:75
+#, c-format
+msgid "\t -t: show CPU topology/hierarchy\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:76
+#, c-format
+msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:77
+#, c-format
+msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:79
+#, c-format
+msgid ""
+"only one of: -t, -l, -m are allowed\n"
+"If none of them is passed,"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:80
+#, c-format
+msgid " all supported monitors are shown\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:197
+#, c-format
+msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:207
+#, c-format
+msgid " *is offline\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:236
+#, c-format
+msgid "%s: max monitor name length (%d) exceeded\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:250
+#, c-format
+msgid "No matching monitor found in %s, try -l option\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:266
+#, c-format
+msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:319
+#, c-format
+msgid "%s took %.5f seconds and exited with status %d\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:406
+#, c-format
+msgid "Cannot read number of available processors\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:417
+#, c-format
+msgid "Available monitor %s needs root access\n"
+msgstr ""
+
+#: utils/idle_monitor/cpupower-monitor.c:428
+#, c-format
+msgid "No HW Cstate monitors found\n"
+msgstr ""
+
+#: utils/cpupower.c:78
+#, c-format
+msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
+msgstr ""
+
+#: utils/cpupower.c:79
+#, c-format
+msgid "cpupower --version\n"
+msgstr ""
+
+#: utils/cpupower.c:80
+#, c-format
+msgid "Supported subcommands are:\n"
+msgstr ""
+
+#: utils/cpupower.c:83
+#, c-format
+msgid ""
+"\n"
+"Some subcommands can make use of the -c cpulist option.\n"
+msgstr ""
+
+#: utils/cpupower.c:84
+#, c-format
+msgid "Look at the general cpupower manpage how to use it\n"
+msgstr ""
+
+#: utils/cpupower.c:85
+#, c-format
+msgid "and read up the subcommand's manpage whether it is supported.\n"
+msgstr ""
+
+#: utils/cpupower.c:86
+#, c-format
+msgid ""
+"\n"
+"Use cpupower help subcommand for getting help for above subcommands.\n"
+msgstr ""
+
+#: utils/cpupower.c:91
+#, c-format
+msgid "Report errors and bugs to %s, please.\n"
+msgstr "Reporte erros e bugs para %s, por favor.\n"
+
+#: utils/cpupower.c:114
+#, c-format
+msgid "Error parsing cpu list\n"
+msgstr ""
+
+#: utils/cpupower.c:172
+#, c-format
+msgid "Subcommand %s needs root privileges\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:31
+#, c-format
+msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
+msgstr "Não foi possível contar o número de CPUs (%s: %s), assumindo 1\n"
+
+#: utils/cpufreq-info.c:63
+#, c-format
+msgid ""
+"          minimum CPU frequency  -  maximum CPU frequency  -  governor\n"
+msgstr ""
+"          frequência mínina do CPU  -  frequência máxima do CPU  -  "
+"regulador\n"
+
+#: utils/cpufreq-info.c:151
+#, c-format
+msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
+msgstr ""
+
+#. P state changes via MSR are identified via cpuid 80000007
+#. on Intel and AMD, but we assume boost capable machines can do that
+#. if (cpuid_eax(0x80000000) >= 0x80000007
+#. && (cpuid_edx(0x80000007) & (1 << 7)))
+#.
+#: utils/cpufreq-info.c:161
+#, c-format
+msgid "  boost state support: \n"
+msgstr ""
+
+#: utils/cpufreq-info.c:163
+#, c-format
+msgid "    Supported: %s\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
+msgid "yes"
+msgstr ""
+
+#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
+msgid "no"
+msgstr ""
+
+#: utils/cpufreq-info.c:164
+#, fuzzy, c-format
+msgid "    Active: %s\n"
+msgstr "  driver: %s\n"
+
+#: utils/cpufreq-info.c:177
+#, c-format
+msgid "    Boost States: %d\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:178
+#, c-format
+msgid "    Total States: %d\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:181
+#, c-format
+msgid "    Pstate-Pb%d: %luMHz (boost state)\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:184
+#, c-format
+msgid "    Pstate-P%d:  %luMHz\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:211
+#, c-format
+msgid "  no or unknown cpufreq driver is active on this CPU\n"
+msgstr "  nenhum ou driver do cpufreq deconhecido está ativo nesse CPU\n"
+
+#: utils/cpufreq-info.c:213
+#, c-format
+msgid "  driver: %s\n"
+msgstr "  driver: %s\n"
+
+#: utils/cpufreq-info.c:219
+#, c-format
+msgid "  CPUs which run at the same hardware frequency: "
+msgstr "  CPUs que rodam na mesma frequência de hardware: "
+
+#: utils/cpufreq-info.c:230
+#, c-format
+msgid "  CPUs which need to have their frequency coordinated by software: "
+msgstr "  CPUs que precisam ter suas frequências coordenadas por software: "
+
+#: utils/cpufreq-info.c:241
+#, c-format
+msgid "  maximum transition latency: "
+msgstr "  maior latência de transição: "
+
+#: utils/cpufreq-info.c:247
+#, c-format
+msgid "  hardware limits: "
+msgstr "  limites do hardware: "
+
+#: utils/cpufreq-info.c:256
+#, c-format
+msgid "  available frequency steps: "
+msgstr "  níveis de frequência disponíveis: "
+
+#: utils/cpufreq-info.c:269
+#, c-format
+msgid "  available cpufreq governors: "
+msgstr "  reguladores do cpufreq disponíveis: "
+
+#: utils/cpufreq-info.c:280
+#, c-format
+msgid "  current policy: frequency should be within "
+msgstr "  política de frequência atual deve estar entre "
+
+#: utils/cpufreq-info.c:282
+#, c-format
+msgid " and "
+msgstr " e "
+
+#: utils/cpufreq-info.c:286
+#, c-format
+msgid ""
+"The governor \"%s\" may decide which speed to use\n"
+"                  within this range.\n"
+msgstr ""
+"O regulador \"%s\" deve decidir qual velocidade usar\n"
+"                  dentro desse limite.\n"
+
+#: utils/cpufreq-info.c:293
+#, c-format
+msgid "  current CPU frequency is "
+msgstr "  frequência atual do CPU é "
+
+#: utils/cpufreq-info.c:296
+#, c-format
+msgid " (asserted by call to hardware)"
+msgstr " (declarado por chamada ao hardware)"
+
+#: utils/cpufreq-info.c:304
+#, c-format
+msgid "  cpufreq stats: "
+msgstr "  status do cpufreq: "
+
+#: utils/cpufreq-info.c:472
+#, fuzzy, c-format
+msgid "Usage: cpupower freqinfo [options]\n"
+msgstr "Uso: cpufreq-info [opções]\n"
+
+#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
+#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
+#, c-format
+msgid "Options:\n"
+msgstr "Opções:\n"
+
+#: utils/cpufreq-info.c:474
+#, fuzzy, c-format
+msgid "  -e, --debug          Prints out debug information [default]\n"
+msgstr "  -e, --debug          Mostra informação de debug\n"
+
+#: utils/cpufreq-info.c:475
+#, c-format
+msgid ""
+"  -f, --freq           Get frequency the CPU currently runs at, according\n"
+"                       to the cpufreq core *\n"
+msgstr ""
+"  -f, --freq           Obtem a frequência na qual o CPU roda no momento, de "
+"acordo\n"
+"                       com o núcleo do cpufreq *\n"
+
+#: utils/cpufreq-info.c:477
+#, c-format
+msgid ""
+"  -w, --hwfreq         Get frequency the CPU currently runs at, by reading\n"
+"                       it from hardware (only available to root) *\n"
+msgstr ""
+"  -w, --hwfreq         Obtem a frequência na qual o CPU está operando no "
+"momento,\n"
+"                       através de leitura no hardware (disponível somente "
+"para root) *\n"
+
+#: utils/cpufreq-info.c:479
+#, c-format
+msgid ""
+"  -l, --hwlimits       Determine the minimum and maximum CPU frequency "
+"allowed *\n"
+msgstr ""
+"  -l, --hwlimits       Determina a frequência mínima e máxima do CPU "
+"permitida *\n"
+
+#: utils/cpufreq-info.c:480
+#, c-format
+msgid "  -d, --driver         Determines the used cpufreq kernel driver *\n"
+msgstr ""
+"  -d,  --driver         Determina o driver do kernel do cpufreq usado *\n"
+
+#: utils/cpufreq-info.c:481
+#, c-format
+msgid "  -p, --policy         Gets the currently used cpufreq policy *\n"
+msgstr ""
+"--p, --policy         Obtem a política do cpufreq em uso no momento *\n"
+
+#: utils/cpufreq-info.c:482
+#, c-format
+msgid "  -g, --governors      Determines available cpufreq governors *\n"
+msgstr ""
+"  -g, --governors      Determina reguladores do cpufreq disponíveis *\n"
+
+#: utils/cpufreq-info.c:483
+#, c-format
+msgid ""
+"  -r, --related-cpus   Determines which CPUs run at the same hardware "
+"frequency *\n"
+msgstr ""
+"  -r, --related-cpus   Determina quais CPUs rodam na mesma frequência de "
+"hardware *\n"
+
+#: utils/cpufreq-info.c:484
+#, c-format
+msgid ""
+"  -a, --affected-cpus  Determines which CPUs need to have their frequency\n"
+"                       coordinated by software *\n"
+msgstr ""
+"  -a, --affected-cpus  Determina quais CPUs precisam ter suas frequências\n"
+"                       coordenadas por software *\n"
+
+#: utils/cpufreq-info.c:486
+#, c-format
+msgid "  -s, --stats          Shows cpufreq statistics if available\n"
+msgstr "  -s, --stats          Mostra estatísticas do cpufreq se disponíveis\n"
+
+#: utils/cpufreq-info.c:487
+#, c-format
+msgid ""
+"  -y, --latency        Determines the maximum latency on CPU frequency "
+"changes *\n"
+msgstr ""
+"  -y, --latency        Determina a latência máxima nas trocas de frequência "
+"do CPU *\n"
+
+#: utils/cpufreq-info.c:488
+#, c-format
+msgid "  -b, --boost          Checks for turbo or boost modes  *\n"
+msgstr ""
+
+#: utils/cpufreq-info.c:489
+#, c-format
+msgid ""
+"  -o, --proc           Prints out information like provided by the /proc/"
+"cpufreq\n"
+"                       interface in 2.4. and early 2.6. kernels\n"
+msgstr ""
+"  -o, --proc           Mostra informação do tipo provida pela interface /"
+"proc/cpufreq\n"
+"                       em kernels 2.4. e mais recentes 2.6\n"
+
+#: utils/cpufreq-info.c:491
+#, c-format
+msgid ""
+"  -m, --human          human-readable output for the -f, -w, -s and -y "
+"parameters\n"
+msgstr ""
+"  -m, --human          saída legível para humanos para os parâmetros -f, -w, "
+"-s e -y\n"
+
+#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
+#, c-format
+msgid "  -h, --help           Prints out this screen\n"
+msgstr " -h, --help           Imprime essa tela\n"
+
+#: utils/cpufreq-info.c:495
+#, c-format
+msgid ""
+"If no argument or only the -c, --cpu parameter is given, debug output about\n"
+"cpufreq is printed which is useful e.g. for reporting bugs.\n"
+msgstr ""
+"Se nenhum argumento ou somente o parâmetro -c, --cpu é dado, informação de "
+"debug sobre\n"
+"o cpufreq é mostrada, o que é útil por exemplo para reportar bugs.\n"
+
+#: utils/cpufreq-info.c:497
+#, c-format
+msgid ""
+"For the arguments marked with *, omitting the -c or --cpu argument is\n"
+"equivalent to setting it to zero\n"
+msgstr ""
+"Para os argumentos marcados com *, omitir o argumento -c ou --cpu é\n"
+"equivalente a setá-lo como zero\n"
+
+#: utils/cpufreq-info.c:580
+#, c-format
+msgid ""
+"The argument passed to this tool can't be combined with passing a --cpu "
+"argument\n"
+msgstr ""
+"O argumento usado pra essa ferramenta não pode ser combinado com um "
+"argumento --cpu\n"
+
+#: utils/cpufreq-info.c:596
+#, c-format
+msgid ""
+"You can't specify more than one --cpu parameter and/or\n"
+"more than one output-specific argument\n"
+msgstr ""
+"Você não pode especificar mais do que um parâmetro --cpu e/ou\n"
+"mais do que um argumento de saída específico\n"
+
+#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
+#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
+#, c-format
+msgid "invalid or unknown argument\n"
+msgstr "argumento inválido ou desconhecido\n"
+
+#: utils/cpufreq-info.c:617
+#, c-format
+msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
+msgstr ""
+"não foi possível analisar o CPU % já que o mesmo parece não estar presente\n"
+
+#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
+#, c-format
+msgid "analyzing CPU %d:\n"
+msgstr "analisando o CPU %d:\n"
+
+#: utils/cpufreq-set.c:25
+#, fuzzy, c-format
+msgid "Usage: cpupower frequency-set [options]\n"
+msgstr "Uso: cpufreq-set [opções]\n"
+
+#: utils/cpufreq-set.c:27
+#, c-format
+msgid ""
+"  -d FREQ, --min FREQ      new minimum CPU frequency the governor may "
+"select\n"
+msgstr ""
+"  -d FREQ, --min FREQ      nova frequência mínima do CPU que o regulador "
+"deve selecionar\n"
+
+#: utils/cpufreq-set.c:28
+#, c-format
+msgid ""
+"  -u FREQ, --max FREQ      new maximum CPU frequency the governor may "
+"select\n"
+msgstr ""
+"  -u FREQ, --max FREQ      nova frequência máxima do CPU que o regulador "
+"deve escolher\n"
+
+#: utils/cpufreq-set.c:29
+#, c-format
+msgid "  -g GOV, --governor GOV   new cpufreq governor\n"
+msgstr "  -g GOV, --governor GOV   novo regulador do cpufreq\n"
+
+#: utils/cpufreq-set.c:30
+#, c-format
+msgid ""
+"  -f FREQ, --freq FREQ     specific frequency to be set. Requires userspace\n"
+"                           governor to be available and loaded\n"
+msgstr ""
+"  -f FREQ, --freq FREQ     frequência específica para ser setada. Necessita "
+"que o regulador em\n"
+"                           nível de usuário esteja disponível e carregado\n"
+
+#: utils/cpufreq-set.c:32
+#, c-format
+msgid "  -r, --related            Switches all hardware-related CPUs\n"
+msgstr ""
+"  -r, --related            Modifica todos os CPUs relacionados ao hardware\n"
+
+#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
+#, c-format
+msgid "  -h, --help               Prints out this screen\n"
+msgstr " -h, --help           Mostra essa tela\n"
+
+#: utils/cpufreq-set.c:35
+#, fuzzy, c-format
+msgid ""
+"Notes:\n"
+"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
+msgstr ""
+"Para os argumentos marcados com *, omitir o argumento -c ou --cpu é\n"
+"equivalente a setá-lo como zero\n"
+
+#: utils/cpufreq-set.c:37
+#, fuzzy, c-format
+msgid ""
+"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
+"parameter\n"
+"   except the -c CPU, --cpu CPU parameter\n"
+"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
+"   by postfixing the value with the wanted unit name, without any space\n"
+"   (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
+msgstr ""
+"Notas:\n"
+"1. Omitir o argumento -c or --cpu é equivalente a setá-lo como zero\n"
+"2. O parâmetro -f FREQ, --freq FREQ não pode ser combinado com qualquer "
+"outro parâmetro\n"
+"   exceto com o parâmetro -c CPU, --cpu CPU\n"
+"3. FREQuências podem ser usadas em Hz, kHz (padrão), MHz, GHz, o THz\n"
+"   colocando o nome desejado da unidade após o valor, sem qualquer espaço\n"
+"   (FREQuência em kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
+
+#: utils/cpufreq-set.c:57
+#, c-format
+msgid ""
+"Error setting new values. Common errors:\n"
+"- Do you have proper administration rights? (super-user?)\n"
+"- Is the governor you requested available and modprobed?\n"
+"- Trying to set an invalid policy?\n"
+"- Trying to set a specific frequency, but userspace governor is not "
+"available,\n"
+"   for example because of hardware which cannot be set to a specific "
+"frequency\n"
+"   or because the userspace governor isn't loaded?\n"
+msgstr ""
+"Erro ao setar novos valores. Erros comuns:\n"
+"- Você tem direitos administrativos necessários? (super-usuário?)\n"
+"- O regulador que você requesitou está disponível e foi \"modprobed\"?\n"
+"- Tentando setar uma política inválida?\n"
+"- Tentando setar uma frequência específica, mas o regulador em nível de "
+"usuário não está disponível,\n"
+"   por exemplo devido ao hardware que não pode ser setado pra uma frequência "
+"específica\n"
+"   ou porque o regulador em nível de usuário não foi carregado?\n"
+
+#: utils/cpufreq-set.c:170
+#, c-format
+msgid "wrong, unknown or unhandled CPU?\n"
+msgstr "CPU errado, desconhecido ou inesperado?\n"
+
+#: utils/cpufreq-set.c:302
+#, c-format
+msgid ""
+"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
+"-g/--governor parameters\n"
+msgstr ""
+"o parâmetro -f/--freq não pode ser combinado com os parâmetros -d/--min, -"
+"u/--max ou\n"
+"-g/--governor\n"
+
+#: utils/cpufreq-set.c:308
+#, c-format
+msgid ""
+"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
+"-g/--governor must be passed\n"
+msgstr ""
+"Pelo menos um parâmetro entre -f/--freq, -d/--min, -u/--max, e\n"
+"-g/--governor deve ser usado\n"
+
+#: utils/cpufreq-set.c:347
+#, c-format
+msgid "Setting cpu: %d\n"
+msgstr ""
+
+#: utils/cpupower-set.c:22
+#, c-format
+msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:24
+#, c-format
+msgid ""
+"  -b, --perf-bias [VAL]    Sets CPU's power vs performance policy on some\n"
+"                           Intel models [0-15], see manpage for details\n"
+msgstr ""
+
+#: utils/cpupower-set.c:26
+#, c-format
+msgid ""
+"  -m, --sched-mc  [VAL]    Sets the kernel's multi core scheduler policy.\n"
+msgstr ""
+
+#: utils/cpupower-set.c:27
+#, c-format
+msgid ""
+"  -s, --sched-smt [VAL]    Sets the kernel's thread sibling scheduler "
+"policy.\n"
+msgstr ""
+
+#: utils/cpupower-set.c:80
+#, c-format
+msgid "--perf-bias param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:91
+#, c-format
+msgid "--sched-mc param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:102
+#, c-format
+msgid "--sched-smt param out of range [0-%d]\n"
+msgstr ""
+
+#: utils/cpupower-set.c:121
+#, c-format
+msgid "Error setting sched-mc %s\n"
+msgstr ""
+
+#: utils/cpupower-set.c:127
+#, c-format
+msgid "Error setting sched-smt %s\n"
+msgstr ""
+
+#: utils/cpupower-set.c:146
+#, c-format
+msgid "Error setting perf-bias value on CPU %d\n"
+msgstr ""
+
+#: utils/cpupower-info.c:21
+#, c-format
+msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
+msgstr ""
+
+#: utils/cpupower-info.c:23
+#, c-format
+msgid ""
+"  -b, --perf-bias    Gets CPU's power vs performance policy on some\n"
+"                           Intel models [0-15], see manpage for details\n"
+msgstr ""
+
+#: utils/cpupower-info.c:25
+#, fuzzy, c-format
+msgid "  -m, --sched-mc     Gets the kernel's multi core scheduler policy.\n"
+msgstr ""
+"--p, --policy         Obtem a política do cpufreq em uso no momento *\n"
+
+#: utils/cpupower-info.c:26
+#, c-format
+msgid ""
+"  -s, --sched-smt    Gets the kernel's thread sibling scheduler policy.\n"
+msgstr ""
+
+#: utils/cpupower-info.c:28
+#, c-format
+msgid ""
+"\n"
+"Passing no option will show all info, by default only on core 0\n"
+msgstr ""
+
+#: utils/cpupower-info.c:102
+#, c-format
+msgid "System's multi core scheduler setting: "
+msgstr ""
+
+#. if sysfs file is missing it's: errno == ENOENT
+#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
+#, c-format
+msgid "not supported\n"
+msgstr ""
+
+#: utils/cpupower-info.c:111
+#, c-format
+msgid "System's thread sibling scheduler setting: "
+msgstr ""
+
+#: utils/cpupower-info.c:126
+#, c-format
+msgid "Intel's performance bias setting needs root privileges\n"
+msgstr ""
+
+#: utils/cpupower-info.c:128
+#, c-format
+msgid "System does not support Intel's performance bias setting\n"
+msgstr ""
+
+#: utils/cpupower-info.c:147
+#, c-format
+msgid "Could not read perf-bias value\n"
+msgstr ""
+
+#: utils/cpupower-info.c:150
+#, c-format
+msgid "perf-bias: %d\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:28
+#, fuzzy, c-format
+msgid "Analyzing CPU %d:\n"
+msgstr "analisando o CPU %d:\n"
+
+#: utils/cpuidle-info.c:32
+#, c-format
+msgid "CPU %u: No idle states\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:36
+#, c-format
+msgid "CPU %u: Can't read idle state info\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:41
+#, c-format
+msgid "Could not determine max idle state %u\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:46
+#, c-format
+msgid "Number of idle states: %d\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:48
+#, fuzzy, c-format
+msgid "Available idle states:"
+msgstr "  níveis de frequência disponíveis: "
+
+#: utils/cpuidle-info.c:71
+#, c-format
+msgid "Flags/Description: %s\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:74
+#, c-format
+msgid "Latency: %lu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:76
+#, c-format
+msgid "Usage: %lu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:78
+#, c-format
+msgid "Duration: %llu\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:90
+#, c-format
+msgid "Could not determine cpuidle driver\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:94
+#, fuzzy, c-format
+msgid "CPUidle driver: %s\n"
+msgstr "  driver: %s\n"
+
+#: utils/cpuidle-info.c:99
+#, c-format
+msgid "Could not determine cpuidle governor\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:103
+#, c-format
+msgid "CPUidle governor: %s\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:122
+#, c-format
+msgid "CPU %u: Can't read C-state info\n"
+msgstr ""
+
+#. printf("Cstates: %d\n", cstates);
+#: utils/cpuidle-info.c:127
+#, c-format
+msgid "active state:            C0\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:128
+#, c-format
+msgid "max_cstate:              C%u\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:129
+#, fuzzy, c-format
+msgid "maximum allowed latency: %lu usec\n"
+msgstr "  maior latência de transição: "
+
+#: utils/cpuidle-info.c:130
+#, c-format
+msgid "states:\t\n"
+msgstr ""
+
+#: utils/cpuidle-info.c:132
+#, c-format
+msgid "    C%d:                  type[C%d] "
+msgstr ""
+
+#: utils/cpuidle-info.c:134
+#, c-format
+msgid "promotion[--] demotion[--] "
+msgstr ""
+
+#: utils/cpuidle-info.c:135
+#, c-format
+msgid "latency[%03lu] "
+msgstr ""
+
+#: utils/cpuidle-info.c:137
+#, c-format
+msgid "usage[%08lu] "
+msgstr ""
+
+#: utils/cpuidle-info.c:139
+#, c-format
+msgid "duration[%020Lu] \n"
+msgstr ""
+
+#: utils/cpuidle-info.c:147
+#, fuzzy, c-format
+msgid "Usage: cpupower idleinfo [options]\n"
+msgstr "Uso: cpufreq-info [opções]\n"
+
+#: utils/cpuidle-info.c:149
+#, fuzzy, c-format
+msgid "  -s, --silent         Only show general C-state information\n"
+msgstr "  -e, --debug          Mostra informação de debug\n"
+
+#: utils/cpuidle-info.c:150
+#, fuzzy, c-format
+msgid ""
+"  -o, --proc           Prints out information like provided by the /proc/"
+"acpi/processor/*/power\n"
+"                       interface in older kernels\n"
+msgstr ""
+"  -o, --proc           Mostra informação do tipo provida pela interface /"
+"proc/cpufreq\n"
+"                       em kernels 2.4. e mais recentes 2.6\n"
+
+#: utils/cpuidle-info.c:209
+#, fuzzy, c-format
+msgid "You can't specify more than one output-specific argument\n"
+msgstr ""
+"Você não pode especificar mais do que um parâmetro --cpu e/ou\n"
+"mais do que um argumento de saída específico\n"
+
+#~ msgid ""
+#~ "  -c CPU, --cpu CPU    CPU number which information shall be determined "
+#~ "about\n"
+#~ msgstr ""
+#~ "  -c CPU, --cpu CPU    número do CPU sobre o qual as inforções devem ser "
+#~ "determinadas\n"
+
+#~ msgid ""
+#~ "  -c CPU, --cpu CPU        number of CPU where cpufreq settings shall be "
+#~ "modified\n"
+#~ msgstr ""
+#~ "  -c CPU, --cpu CPU        número do CPU onde as configurações do cpufreq "
+#~ "vão ser modificadas\n"
diff --git a/tools/power/cpupower/utils/builtin.h b/tools/power/cpupower/utils/builtin.h
new file mode 100644 (file)
index 0000000..c870ffb
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef BUILTIN_H
+#define BUILTIN_H
+
+extern int cmd_set(int argc, const char **argv);
+extern int cmd_info(int argc, const char **argv);
+extern int cmd_freq_set(int argc, const char **argv);
+extern int cmd_freq_info(int argc, const char **argv);
+extern int cmd_idle_info(int argc, const char **argv);
+extern int cmd_monitor(int argc, const char **argv);
+
+extern void set_help(void);
+extern void info_help(void);
+extern void freq_set_help(void);
+extern void freq_info_help(void);
+extern void idle_info_help(void);
+extern void monitor_help(void);
+
+#endif
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
new file mode 100644 (file)
index 0000000..5a1d25f
--- /dev/null
@@ -0,0 +1,708 @@
+/*
+ *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <getopt.h>
+
+#include "cpufreq.h"
+#include "helpers/helpers.h"
+#include "helpers/bitmask.h"
+
+#define LINE_LEN 10
+
+static unsigned int count_cpus(void)
+{
+       FILE *fp;
+       char value[LINE_LEN];
+       unsigned int ret = 0;
+       unsigned int cpunr = 0;
+
+       fp = fopen("/proc/stat", "r");
+       if (!fp) {
+               printf(_("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno));
+               return 1;
+       }
+
+       while (!feof(fp)) {
+               if (!fgets(value, LINE_LEN, fp))
+                       continue;
+               value[LINE_LEN - 1] = '\0';
+               if (strlen(value) < (LINE_LEN - 2))
+                       continue;
+               if (strstr(value, "cpu "))
+                       continue;
+               if (sscanf(value, "cpu%d ", &cpunr) != 1)
+                       continue;
+               if (cpunr > ret)
+                       ret = cpunr;
+       }
+       fclose(fp);
+
+       /* cpu count starts from 0, on error return 1 (UP) */
+       return ret + 1;
+}
+
+
+static void proc_cpufreq_output(void)
+{
+       unsigned int cpu, nr_cpus;
+       struct cpufreq_policy *policy;
+       unsigned int min_pctg = 0;
+       unsigned int max_pctg = 0;
+       unsigned long min, max;
+
+       printf(_("          minimum CPU frequency  -  maximum CPU frequency  -  governor\n"));
+
+       nr_cpus = count_cpus();
+       for (cpu = 0; cpu < nr_cpus; cpu++) {
+               policy = cpufreq_get_policy(cpu);
+               if (!policy)
+                       continue;
+
+               if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
+                       max = 0;
+               } else {
+                       min_pctg = (policy->min * 100) / max;
+                       max_pctg = (policy->max * 100) / max;
+               }
+               printf("CPU%3d    %9lu kHz (%3d %%)  -  %9lu kHz (%3d %%)  -  %s\n",
+                       cpu , policy->min, max ? min_pctg : 0, policy->max,
+                       max ? max_pctg : 0, policy->governor);
+
+               cpufreq_put_policy(policy);
+       }
+}
+
+static void print_speed(unsigned long speed)
+{
+       unsigned long tmp;
+
+       if (speed > 1000000) {
+               tmp = speed % 10000;
+               if (tmp >= 5000)
+                       speed += 10000;
+               printf("%u.%02u GHz", ((unsigned int) speed/1000000),
+                       ((unsigned int) (speed%1000000)/10000));
+       } else if (speed > 100000) {
+               tmp = speed % 1000;
+               if (tmp >= 500)
+                       speed += 1000;
+               printf("%u MHz", ((unsigned int) speed / 1000));
+       } else if (speed > 1000) {
+               tmp = speed % 100;
+               if (tmp >= 50)
+                       speed += 100;
+               printf("%u.%01u MHz", ((unsigned int) speed/1000),
+                       ((unsigned int) (speed%1000)/100));
+       } else
+               printf("%lu kHz", speed);
+
+       return;
+}
+
+static void print_duration(unsigned long duration)
+{
+       unsigned long tmp;
+
+       if (duration > 1000000) {
+               tmp = duration % 10000;
+               if (tmp >= 5000)
+                       duration += 10000;
+               printf("%u.%02u ms", ((unsigned int) duration/1000000),
+                       ((unsigned int) (duration%1000000)/10000));
+       } else if (duration > 100000) {
+               tmp = duration % 1000;
+               if (tmp >= 500)
+                       duration += 1000;
+               printf("%u us", ((unsigned int) duration / 1000));
+       } else if (duration > 1000) {
+               tmp = duration % 100;
+               if (tmp >= 50)
+                       duration += 100;
+               printf("%u.%01u us", ((unsigned int) duration/1000),
+                       ((unsigned int) (duration%1000)/100));
+       } else
+               printf("%lu ns", duration);
+
+       return;
+}
+
+/* --boost / -b */
+
+static int get_boost_mode(unsigned int cpu)
+{
+       int support, active, b_states = 0, ret, pstate_no, i;
+       /* ToDo: Make this more global */
+       unsigned long pstates[MAX_HW_PSTATES] = {0,};
+
+       if (cpupower_cpu_info.vendor != X86_VENDOR_AMD &&
+           cpupower_cpu_info.vendor != X86_VENDOR_INTEL)
+               return 0;
+
+       ret = cpufreq_has_boost_support(cpu, &support, &active, &b_states);
+       if (ret) {
+               printf(_("Error while evaluating Boost Capabilities"
+                               " on CPU %d -- are you root?\n"), cpu);
+               return ret;
+       }
+       /* P state changes via MSR are identified via cpuid 80000007
+          on Intel and AMD, but we assume boost capable machines can do that
+          if (cpuid_eax(0x80000000) >= 0x80000007
+          && (cpuid_edx(0x80000007) & (1 << 7)))
+       */
+
+       printf(_("  boost state support:\n"));
+
+       printf(_("    Supported: %s\n"), support ? _("yes") : _("no"));
+       printf(_("    Active: %s\n"), active ? _("yes") : _("no"));
+
+       if (cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
+           cpupower_cpu_info.family >= 0x10) {
+               ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states,
+                                    pstates, &pstate_no);
+               if (ret)
+                       return ret;
+
+               printf(_("    Boost States: %d\n"), b_states);
+               printf(_("    Total States: %d\n"), pstate_no);
+               for (i = 0; i < pstate_no; i++) {
+                       if (i < b_states)
+                               printf(_("    Pstate-Pb%d: %luMHz (boost state)"
+                                        "\n"), i, pstates[i]);
+                       else
+                               printf(_("    Pstate-P%d:  %luMHz\n"),
+                                      i - b_states, pstates[i]);
+               }
+       } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO) {
+               double bclk;
+               unsigned long long intel_turbo_ratio = 0;
+               unsigned int ratio;
+
+               /* Any way to autodetect this ? */
+               if (cpupower_cpu_info.caps & CPUPOWER_CAP_IS_SNB)
+                       bclk = 100.00;
+               else
+                       bclk = 133.33;
+               intel_turbo_ratio = msr_intel_get_turbo_ratio(cpu);
+               dprint ("    Ratio: 0x%llx - bclk: %f\n",
+                       intel_turbo_ratio, bclk);
+
+               ratio = (intel_turbo_ratio >> 24) & 0xFF;
+               if (ratio)
+                       printf(_("    %.0f MHz max turbo 4 active cores\n"),
+                              ratio * bclk);
+
+               ratio = (intel_turbo_ratio >> 16) & 0xFF;
+               if (ratio)
+                       printf(_("    %.0f MHz max turbo 3 active cores\n"),
+                              ratio * bclk);
+
+               ratio = (intel_turbo_ratio >> 8) & 0xFF;
+               if (ratio)
+                       printf(_("    %.0f MHz max turbo 2 active cores\n"),
+                              ratio * bclk);
+
+               ratio = (intel_turbo_ratio >> 0) & 0xFF;
+               if (ratio)
+                       printf(_("    %.0f MHz max turbo 1 active cores\n"),
+                              ratio * bclk);
+       }
+       return 0;
+}
+
+static void debug_output_one(unsigned int cpu)
+{
+       char *driver;
+       struct cpufreq_affected_cpus *cpus;
+       struct cpufreq_available_frequencies *freqs;
+       unsigned long min, max, freq_kernel, freq_hardware;
+       unsigned long total_trans, latency;
+       unsigned long long total_time;
+       struct cpufreq_policy *policy;
+       struct cpufreq_available_governors *governors;
+       struct cpufreq_stats *stats;
+
+       if (cpufreq_cpu_exists(cpu))
+               return;
+
+       freq_kernel = cpufreq_get_freq_kernel(cpu);
+       freq_hardware = cpufreq_get_freq_hardware(cpu);
+
+       driver = cpufreq_get_driver(cpu);
+       if (!driver) {
+               printf(_("  no or unknown cpufreq driver is active on this CPU\n"));
+       } else {
+               printf(_("  driver: %s\n"), driver);
+               cpufreq_put_driver(driver);
+       }
+
+       cpus = cpufreq_get_related_cpus(cpu);
+       if (cpus) {
+               printf(_("  CPUs which run at the same hardware frequency: "));
+               while (cpus->next) {
+                       printf("%d ", cpus->cpu);
+                       cpus = cpus->next;
+               }
+               printf("%d\n", cpus->cpu);
+               cpufreq_put_related_cpus(cpus);
+       }
+
+       cpus = cpufreq_get_affected_cpus(cpu);
+       if (cpus) {
+               printf(_("  CPUs which need to have their frequency coordinated by software: "));
+               while (cpus->next) {
+                       printf("%d ", cpus->cpu);
+                       cpus = cpus->next;
+               }
+               printf("%d\n", cpus->cpu);
+               cpufreq_put_affected_cpus(cpus);
+       }
+
+       latency = cpufreq_get_transition_latency(cpu);
+       if (latency) {
+               printf(_("  maximum transition latency: "));
+               print_duration(latency);
+               printf(".\n");
+       }
+
+       if (!(cpufreq_get_hardware_limits(cpu, &min, &max))) {
+               printf(_("  hardware limits: "));
+               print_speed(min);
+               printf(" - ");
+               print_speed(max);
+               printf("\n");
+       }
+
+       freqs = cpufreq_get_available_frequencies(cpu);
+       if (freqs) {
+               printf(_("  available frequency steps: "));
+               while (freqs->next) {
+                       print_speed(freqs->frequency);
+                       printf(", ");
+                       freqs = freqs->next;
+               }
+               print_speed(freqs->frequency);
+               printf("\n");
+               cpufreq_put_available_frequencies(freqs);
+       }
+
+       governors = cpufreq_get_available_governors(cpu);
+       if (governors) {
+               printf(_("  available cpufreq governors: "));
+               while (governors->next) {
+                       printf("%s, ", governors->governor);
+                       governors = governors->next;
+               }
+               printf("%s\n", governors->governor);
+               cpufreq_put_available_governors(governors);
+       }
+
+       policy = cpufreq_get_policy(cpu);
+       if (policy) {
+               printf(_("  current policy: frequency should be within "));
+               print_speed(policy->min);
+               printf(_(" and "));
+               print_speed(policy->max);
+
+               printf(".\n                  ");
+               printf(_("The governor \"%s\" may"
+                      " decide which speed to use\n                  within this range.\n"),
+                      policy->governor);
+               cpufreq_put_policy(policy);
+       }
+
+       if (freq_kernel || freq_hardware) {
+               printf(_("  current CPU frequency is "));
+               if (freq_hardware) {
+                       print_speed(freq_hardware);
+                       printf(_(" (asserted by call to hardware)"));
+               } else
+                       print_speed(freq_kernel);
+               printf(".\n");
+       }
+       stats = cpufreq_get_stats(cpu, &total_time);
+       if (stats) {
+               printf(_("  cpufreq stats: "));
+               while (stats) {
+                       print_speed(stats->frequency);
+                       printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time);
+                       stats = stats->next;
+                       if (stats)
+                               printf(", ");
+               }
+               cpufreq_put_stats(stats);
+               total_trans = cpufreq_get_transitions(cpu);
+               if (total_trans)
+                       printf("  (%lu)\n", total_trans);
+               else
+                       printf("\n");
+       }
+       get_boost_mode(cpu);
+
+}
+
+/* --freq / -f */
+
+static int get_freq_kernel(unsigned int cpu, unsigned int human)
+{
+       unsigned long freq = cpufreq_get_freq_kernel(cpu);
+       if (!freq)
+               return -EINVAL;
+       if (human) {
+               print_speed(freq);
+               printf("\n");
+       } else
+               printf("%lu\n", freq);
+       return 0;
+}
+
+
+/* --hwfreq / -w */
+
+static int get_freq_hardware(unsigned int cpu, unsigned int human)
+{
+       unsigned long freq = cpufreq_get_freq_hardware(cpu);
+       if (!freq)
+               return -EINVAL;
+       if (human) {
+               print_speed(freq);
+               printf("\n");
+       } else
+               printf("%lu\n", freq);
+       return 0;
+}
+
+/* --hwlimits / -l */
+
+static int get_hardware_limits(unsigned int cpu)
+{
+       unsigned long min, max;
+       if (cpufreq_get_hardware_limits(cpu, &min, &max))
+               return -EINVAL;
+       printf("%lu %lu\n", min, max);
+       return 0;
+}
+
+/* --driver / -d */
+
+static int get_driver(unsigned int cpu)
+{
+       char *driver = cpufreq_get_driver(cpu);
+       if (!driver)
+               return -EINVAL;
+       printf("%s\n", driver);
+       cpufreq_put_driver(driver);
+       return 0;
+}
+
+/* --policy / -p */
+
+static int get_policy(unsigned int cpu)
+{
+       struct cpufreq_policy *policy = cpufreq_get_policy(cpu);
+       if (!policy)
+               return -EINVAL;
+       printf("%lu %lu %s\n", policy->min, policy->max, policy->governor);
+       cpufreq_put_policy(policy);
+       return 0;
+}
+
+/* --governors / -g */
+
+static int get_available_governors(unsigned int cpu)
+{
+       struct cpufreq_available_governors *governors =
+               cpufreq_get_available_governors(cpu);
+       if (!governors)
+               return -EINVAL;
+
+       while (governors->next) {
+               printf("%s ", governors->governor);
+               governors = governors->next;
+       }
+       printf("%s\n", governors->governor);
+       cpufreq_put_available_governors(governors);
+       return 0;
+}
+
+
+/* --affected-cpus  / -a */
+
+static int get_affected_cpus(unsigned int cpu)
+{
+       struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu);
+       if (!cpus)
+               return -EINVAL;
+
+       while (cpus->next) {
+               printf("%d ", cpus->cpu);
+               cpus = cpus->next;
+       }
+       printf("%d\n", cpus->cpu);
+       cpufreq_put_affected_cpus(cpus);
+       return 0;
+}
+
+/* --related-cpus  / -r */
+
+static int get_related_cpus(unsigned int cpu)
+{
+       struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu);
+       if (!cpus)
+               return -EINVAL;
+
+       while (cpus->next) {
+               printf("%d ", cpus->cpu);
+               cpus = cpus->next;
+       }
+       printf("%d\n", cpus->cpu);
+       cpufreq_put_related_cpus(cpus);
+       return 0;
+}
+
+/* --stats / -s */
+
+static int get_freq_stats(unsigned int cpu, unsigned int human)
+{
+       unsigned long total_trans = cpufreq_get_transitions(cpu);
+       unsigned long long total_time;
+       struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time);
+       while (stats) {
+               if (human) {
+                       print_speed(stats->frequency);
+                       printf(":%.2f%%",
+                               (100.0 * stats->time_in_state) / total_time);
+               } else
+                       printf("%lu:%llu",
+                               stats->frequency, stats->time_in_state);
+               stats = stats->next;
+               if (stats)
+                       printf(", ");
+       }
+       cpufreq_put_stats(stats);
+       if (total_trans)
+               printf("  (%lu)\n", total_trans);
+       return 0;
+}
+
+/* --latency / -y */
+
+static int get_latency(unsigned int cpu, unsigned int human)
+{
+       unsigned long latency = cpufreq_get_transition_latency(cpu);
+       if (!latency)
+               return -EINVAL;
+
+       if (human) {
+               print_duration(latency);
+               printf("\n");
+       } else
+               printf("%lu\n", latency);
+       return 0;
+}
+
+void freq_info_help(void)
+{
+       printf(_("Usage: cpupower freqinfo [options]\n"));
+       printf(_("Options:\n"));
+       printf(_("  -e, --debug          Prints out debug information [default]\n"));
+       printf(_("  -f, --freq           Get frequency the CPU currently runs at, according\n"
+              "                       to the cpufreq core *\n"));
+       printf(_("  -w, --hwfreq         Get frequency the CPU currently runs at, by reading\n"
+              "                       it from hardware (only available to root) *\n"));
+       printf(_("  -l, --hwlimits       Determine the minimum and maximum CPU frequency allowed *\n"));
+       printf(_("  -d, --driver         Determines the used cpufreq kernel driver *\n"));
+       printf(_("  -p, --policy         Gets the currently used cpufreq policy *\n"));
+       printf(_("  -g, --governors      Determines available cpufreq governors *\n"));
+       printf(_("  -r, --related-cpus   Determines which CPUs run at the same hardware frequency *\n"));
+       printf(_("  -a, --affected-cpus  Determines which CPUs need to have their frequency\n"
+                       "                       coordinated by software *\n"));
+       printf(_("  -s, --stats          Shows cpufreq statistics if available\n"));
+       printf(_("  -y, --latency        Determines the maximum latency on CPU frequency changes *\n"));
+       printf(_("  -b, --boost          Checks for turbo or boost modes  *\n"));
+       printf(_("  -o, --proc           Prints out information like provided by the /proc/cpufreq\n"
+              "                       interface in 2.4. and early 2.6. kernels\n"));
+       printf(_("  -m, --human          human-readable output for the -f, -w, -s and -y parameters\n"));
+       printf(_("  -h, --help           Prints out this screen\n"));
+
+       printf("\n");
+       printf(_("If no argument is given, full output about\n"
+              "cpufreq is printed which is useful e.g. for reporting bugs.\n\n"));
+       printf(_("By default info of CPU 0 is shown which can be overridden\n"
+                "with the cpupower --cpu main command option.\n"));
+}
+
+static struct option info_opts[] = {
+       { .name = "debug",      .has_arg = no_argument,         .flag = NULL,   .val = 'e'},
+       { .name = "boost",      .has_arg = no_argument,         .flag = NULL,   .val = 'b'},
+       { .name = "freq",       .has_arg = no_argument,         .flag = NULL,   .val = 'f'},
+       { .name = "hwfreq",     .has_arg = no_argument,         .flag = NULL,   .val = 'w'},
+       { .name = "hwlimits",   .has_arg = no_argument,         .flag = NULL,   .val = 'l'},
+       { .name = "driver",     .has_arg = no_argument,         .flag = NULL,   .val = 'd'},
+       { .name = "policy",     .has_arg = no_argument,         .flag = NULL,   .val = 'p'},
+       { .name = "governors",  .has_arg = no_argument,         .flag = NULL,   .val = 'g'},
+       { .name = "related-cpus", .has_arg = no_argument,       .flag = NULL,   .val = 'r'},
+       { .name = "affected-cpus",.has_arg = no_argument,       .flag = NULL,   .val = 'a'},
+       { .name = "stats",      .has_arg = no_argument,         .flag = NULL,   .val = 's'},
+       { .name = "latency",    .has_arg = no_argument,         .flag = NULL,   .val = 'y'},
+       { .name = "proc",       .has_arg = no_argument,         .flag = NULL,   .val = 'o'},
+       { .name = "human",      .has_arg = no_argument,         .flag = NULL,   .val = 'm'},
+       { .name = "help",       .has_arg = no_argument,         .flag = NULL,   .val = 'h'},
+       { },
+};
+
+int cmd_freq_info(int argc, char **argv)
+{
+       extern char *optarg;
+       extern int optind, opterr, optopt;
+       int ret = 0, cont = 1;
+       unsigned int cpu = 0;
+       unsigned int human = 0;
+       int output_param = 0;
+
+       do {
+               ret = getopt_long(argc, argv, "hoefwldpgrasmyb", info_opts, NULL);
+               switch (ret) {
+               case '?':
+                       output_param = '?';
+                       cont = 0;
+                       break;
+               case 'h':
+                       output_param = 'h';
+                       cont = 0;
+                       break;
+               case -1:
+                       cont = 0;
+                       break;
+               case 'b':
+               case 'o':
+               case 'a':
+               case 'r':
+               case 'g':
+               case 'p':
+               case 'd':
+               case 'l':
+               case 'w':
+               case 'f':
+               case 'e':
+               case 's':
+               case 'y':
+                       if (output_param) {
+                               output_param = -1;
+                               cont = 0;
+                               break;
+                       }
+                       output_param = ret;
+                       break;
+               case 'm':
+                       if (human) {
+                               output_param = -1;
+                               cont = 0;
+                               break;
+                       }
+                       human = 1;
+                       break;
+               default:
+                       fprintf(stderr, "invalid or unknown argument\n");
+                       return EXIT_FAILURE;
+               }
+       } while (cont);
+
+       switch (output_param) {
+       case 'o':
+               if (!bitmask_isallclear(cpus_chosen)) {
+                       printf(_("The argument passed to this tool can't be "
+                                "combined with passing a --cpu argument\n"));
+                       return -EINVAL;
+               }
+               break;
+       case 0:
+               output_param = 'e';
+       }
+
+       ret = 0;
+
+       /* Default is: show output of CPU 0 only */
+       if (bitmask_isallclear(cpus_chosen))
+               bitmask_setbit(cpus_chosen, 0);
+
+       switch (output_param) {
+       case -1:
+               printf(_("You can't specify more than one --cpu parameter and/or\n"
+                      "more than one output-specific argument\n"));
+               return -EINVAL;
+       case '?':
+               printf(_("invalid or unknown argument\n"));
+               freq_info_help();
+               return -EINVAL;
+       case 'h':
+               freq_info_help();
+               return EXIT_SUCCESS;
+       case 'o':
+               proc_cpufreq_output();
+               return EXIT_SUCCESS;
+       }
+
+       for (cpu = bitmask_first(cpus_chosen);
+            cpu <= bitmask_last(cpus_chosen); cpu++) {
+
+               if (!bitmask_isbitset(cpus_chosen, cpu))
+                       continue;
+               if (cpufreq_cpu_exists(cpu)) {
+                       printf(_("couldn't analyze CPU %d as it doesn't seem to be present\n"), cpu);
+                       continue;
+               }
+               printf(_("analyzing CPU %d:\n"), cpu);
+
+               switch (output_param) {
+               case 'b':
+                       get_boost_mode(cpu);
+                       break;
+               case 'e':
+                       debug_output_one(cpu);
+                       break;
+               case 'a':
+                       ret = get_affected_cpus(cpu);
+                       break;
+               case 'r':
+                       ret = get_related_cpus(cpu);
+                       break;
+               case 'g':
+                       ret = get_available_governors(cpu);
+                       break;
+               case 'p':
+                       ret = get_policy(cpu);
+                       break;
+               case 'd':
+                       ret = get_driver(cpu);
+                       break;
+               case 'l':
+                       ret = get_hardware_limits(cpu);
+                       break;
+               case 'w':
+                       ret = get_freq_hardware(cpu, human);
+                       break;
+               case 'f':
+                       ret = get_freq_kernel(cpu, human);
+                       break;
+               case 's':
+                       ret = get_freq_stats(cpu, human);
+                       break;
+               case 'y':
+                       ret = get_latency(cpu, human);
+                       break;
+               }
+               if (ret)
+                       return ret;
+       }
+       return ret;
+}
diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c
new file mode 100644 (file)
index 0000000..5f78362
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <getopt.h>
+
+#include "cpufreq.h"
+#include "helpers/helpers.h"
+
+#define NORM_FREQ_LEN 32
+
+void freq_set_help(void)
+{
+       printf(_("Usage: cpupower frequency-set [options]\n"));
+       printf(_("Options:\n"));
+       printf(_("  -d FREQ, --min FREQ      new minimum CPU frequency the governor may select\n"));
+       printf(_("  -u FREQ, --max FREQ      new maximum CPU frequency the governor may select\n"));
+       printf(_("  -g GOV, --governor GOV   new cpufreq governor\n"));
+       printf(_("  -f FREQ, --freq FREQ     specific frequency to be set. Requires userspace\n"
+              "                           governor to be available and loaded\n"));
+       printf(_("  -r, --related            Switches all hardware-related CPUs\n"));
+       printf(_("  -h, --help               Prints out this screen\n"));
+       printf("\n");
+       printf(_("Notes:\n"
+              "1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"));
+       printf(_("2. The -f FREQ, --freq FREQ parameter cannot be combined with any other parameter\n"
+              "   except the -c CPU, --cpu CPU parameter\n"
+              "3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
+              "   by postfixing the value with the wanted unit name, without any space\n"
+              "   (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"));
+
+}
+
+static struct option set_opts[] = {
+       { .name = "min",        .has_arg = required_argument,   .flag = NULL,   .val = 'd'},
+       { .name = "max",        .has_arg = required_argument,   .flag = NULL,   .val = 'u'},
+       { .name = "governor",   .has_arg = required_argument,   .flag = NULL,   .val = 'g'},
+       { .name = "freq",       .has_arg = required_argument,   .flag = NULL,   .val = 'f'},
+       { .name = "help",       .has_arg = no_argument,         .flag = NULL,   .val = 'h'},
+       { .name = "related",    .has_arg = no_argument,         .flag = NULL,   .val='r'},
+       { },
+};
+
+static void print_error(void)
+{
+       printf(_("Error setting new values. Common errors:\n"
+                       "- Do you have proper administration rights? (super-user?)\n"
+                       "- Is the governor you requested available and modprobed?\n"
+                       "- Trying to set an invalid policy?\n"
+                       "- Trying to set a specific frequency, but userspace governor is not available,\n"
+                       "   for example because of hardware which cannot be set to a specific frequency\n"
+                       "   or because the userspace governor isn't loaded?\n"));
+};
+
+struct freq_units {
+       char            *str_unit;
+       int             power_of_ten;
+};
+
+const struct freq_units def_units[] = {
+       {"hz", -3},
+       {"khz", 0}, /* default */
+       {"mhz", 3},
+       {"ghz", 6},
+       {"thz", 9},
+       {NULL, 0}
+};
+
+static void print_unknown_arg(void)
+{
+       printf(_("invalid or unknown argument\n"));
+       freq_set_help();
+}
+
+static unsigned long string_to_frequency(const char *str)
+{
+       char normalized[NORM_FREQ_LEN];
+       const struct freq_units *unit;
+       const char *scan;
+       char *end;
+       unsigned long freq;
+       int power = 0, match_count = 0, i, cp, pad;
+
+       while (*str == '0')
+               str++;
+
+       for (scan = str; isdigit(*scan) || *scan == '.'; scan++) {
+               if (*scan == '.' && match_count == 0)
+                       match_count = 1;
+               else if (*scan == '.' && match_count == 1)
+                       return 0;
+       }
+
+       if (*scan) {
+               match_count = 0;
+               for (unit = def_units; unit->str_unit; unit++) {
+                       for (i = 0;
+                            scan[i] && tolower(scan[i]) == unit->str_unit[i];
+                            ++i)
+                               continue;
+                       if (scan[i])
+                               continue;
+                       match_count++;
+                       power = unit->power_of_ten;
+               }
+               if (match_count != 1)
+                       return 0;
+       }
+
+       /* count the number of digits to be copied */
+       for (cp = 0; isdigit(str[cp]); cp++)
+               continue;
+
+       if (str[cp] == '.') {
+               while (power > -1 && isdigit(str[cp+1]))
+                       cp++, power--;
+       }
+       if (power >= -1)        /* not enough => pad */
+               pad = power + 1;
+       else                    /* to much => strip */
+               pad = 0, cp += power + 1;
+       /* check bounds */
+       if (cp <= 0 || cp + pad > NORM_FREQ_LEN - 1)
+               return 0;
+
+       /* copy digits */
+       for (i = 0; i < cp; i++, str++) {
+               if (*str == '.')
+                       str++;
+               normalized[i] = *str;
+       }
+       /* and pad */
+       for (; i < cp + pad; i++)
+               normalized[i] = '0';
+
+       /* round up, down ? */
+       match_count = (normalized[i-1] >= '5');
+       /* and drop the decimal part */
+       normalized[i-1] = 0; /* cp > 0 && pad >= 0 ==> i > 0 */
+
+       /* final conversion (and applying rounding) */
+       errno = 0;
+       freq = strtoul(normalized, &end, 10);
+       if (errno)
+               return 0;
+       else {
+               if (match_count && freq != ULONG_MAX)
+                       freq++;
+               return freq;
+       }
+}
+
+static int do_new_policy(unsigned int cpu, struct cpufreq_policy *new_pol)
+{
+       struct cpufreq_policy *cur_pol = cpufreq_get_policy(cpu);
+       int ret;
+
+       if (!cur_pol) {
+               printf(_("wrong, unknown or unhandled CPU?\n"));
+               return -EINVAL;
+       }
+
+       if (!new_pol->min)
+               new_pol->min = cur_pol->min;
+
+       if (!new_pol->max)
+               new_pol->max = cur_pol->max;
+
+       if (!new_pol->governor)
+               new_pol->governor = cur_pol->governor;
+
+       ret = cpufreq_set_policy(cpu, new_pol);
+
+       cpufreq_put_policy(cur_pol);
+
+       return ret;
+}
+
+
+static int do_one_cpu(unsigned int cpu, struct cpufreq_policy *new_pol,
+               unsigned long freq, unsigned int pc)
+{
+       switch (pc) {
+       case 0:
+               return cpufreq_set_frequency(cpu, freq);
+
+       case 1:
+               /* if only one value of a policy is to be changed, we can
+                * use a "fast path".
+                */
+               if (new_pol->min)
+                       return cpufreq_modify_policy_min(cpu, new_pol->min);
+               else if (new_pol->max)
+                       return cpufreq_modify_policy_max(cpu, new_pol->max);
+               else if (new_pol->governor)
+                       return cpufreq_modify_policy_governor(cpu,
+                                                       new_pol->governor);
+
+       default:
+               /* slow path */
+               return do_new_policy(cpu, new_pol);
+       }
+}
+
+int cmd_freq_set(int argc, char **argv)
+{
+       extern char *optarg;
+       extern int optind, opterr, optopt;
+       int ret = 0, cont = 1;
+       int double_parm = 0, related = 0, policychange = 0;
+       unsigned long freq = 0;
+       char gov[20];
+       unsigned int cpu;
+
+       struct cpufreq_policy new_pol = {
+               .min = 0,
+               .max = 0,
+               .governor = NULL,
+       };
+
+       /* parameter parsing */
+       do {
+               ret = getopt_long(argc, argv, "d:u:g:f:hr", set_opts, NULL);
+               switch (ret) {
+               case '?':
+                       print_unknown_arg();
+                       return -EINVAL;
+               case 'h':
+                       freq_set_help();
+                       return 0;
+               case -1:
+                       cont = 0;
+                       break;
+               case 'r':
+                       if (related)
+                               double_parm++;
+                       related++;
+                       break;
+               case 'd':
+                       if (new_pol.min)
+                               double_parm++;
+                       policychange++;
+                       new_pol.min = string_to_frequency(optarg);
+                       if (new_pol.min == 0) {
+                               print_unknown_arg();
+                               return -EINVAL;
+                       }
+                       break;
+               case 'u':
+                       if (new_pol.max)
+                               double_parm++;
+                       policychange++;
+                       new_pol.max = string_to_frequency(optarg);
+                       if (new_pol.max == 0) {
+                               print_unknown_arg();
+                               return -EINVAL;
+                       }
+                       break;
+               case 'f':
+                       if (freq)
+                               double_parm++;
+                       freq = string_to_frequency(optarg);
+                       if (freq == 0) {
+                               print_unknown_arg();
+                               return -EINVAL;
+                       }
+                       break;
+               case 'g':
+                       if (new_pol.governor)
+                               double_parm++;
+                       policychange++;
+                       if ((strlen(optarg) < 3) || (strlen(optarg) > 18)) {
+                               print_unknown_arg();
+                               return -EINVAL;
+                       }
+                       if ((sscanf(optarg, "%s", gov)) != 1) {
+                               print_unknown_arg();
+                               return -EINVAL;
+                       }
+                       new_pol.governor = gov;
+                       break;
+               }
+       } while (cont);
+
+       /* parameter checking */
+       if (double_parm) {
+               printf("the same parameter was passed more than once\n");
+               return -EINVAL;
+       }
+
+       if (freq && policychange) {
+               printf(_("the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
+                               "-g/--governor parameters\n"));
+               return -EINVAL;
+       }
+
+       if (!freq && !policychange) {
+               printf(_("At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
+                               "-g/--governor must be passed\n"));
+               return -EINVAL;
+       }
+
+       /* Default is: set all CPUs */
+       if (bitmask_isallclear(cpus_chosen))
+               bitmask_setall(cpus_chosen);
+
+       /* Also set frequency settings for related CPUs if -r is passed */
+       if (related) {
+               for (cpu = bitmask_first(cpus_chosen);
+                    cpu <= bitmask_last(cpus_chosen); cpu++) {
+                       struct cpufreq_affected_cpus *cpus;
+
+                       if (!bitmask_isbitset(cpus_chosen, cpu) ||
+                           cpufreq_cpu_exists(cpu))
+                               continue;
+
+                       cpus = cpufreq_get_related_cpus(cpu);
+                       if (!cpus)
+                               break;
+                       while (cpus->next) {
+                               bitmask_setbit(cpus_chosen, cpus->cpu);
+                               cpus = cpus->next;
+                       }
+                       cpufreq_put_related_cpus(cpus);
+               }
+       }
+
+
+       /* loop over CPUs */
+       for (cpu = bitmask_first(cpus_chosen);
+            cpu <= bitmask_last(cpus_chosen); cpu++) {
+
+               if (!bitmask_isbitset(cpus_chosen, cpu) ||
+                   cpufreq_cpu_exists(cpu))
+                       continue;
+
+               printf(_("Setting cpu: %d\n"), cpu);
+               ret = do_one_cpu(cpu, &new_pol, freq, policychange);
+               if (ret)
+                       break;
+       }
+
+       if (ret)
+               print_error();
+
+       return ret;
+}
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c
new file mode 100644 (file)
index 0000000..70da357
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
+ *  (C) 2010       Thomas Renninger <trenn@suse.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <cpufreq.h>
+
+#include "helpers/helpers.h"
+#include "helpers/sysfs.h"
+#include "helpers/bitmask.h"
+
+#define LINE_LEN 10
+
+static void cpuidle_cpu_output(unsigned int cpu, int verbose)
+{
+       int idlestates, idlestate;
+       char *tmp;
+
+       printf(_ ("Analyzing CPU %d:\n"), cpu);
+
+       idlestates = sysfs_get_idlestate_count(cpu);
+       if (idlestates == 0) {
+               printf(_("CPU %u: No idle states\n"), cpu);
+               return;
+       } else if (idlestates <= 0) {
+               printf(_("CPU %u: Can't read idle state info\n"), cpu);
+               return;
+       }
+       tmp = sysfs_get_idlestate_name(cpu, idlestates - 1);
+       if (!tmp) {
+               printf(_("Could not determine max idle state %u\n"),
+                      idlestates - 1);
+               return;
+       }
+
+       printf(_("Number of idle states: %d\n"), idlestates);
+
+       printf(_("Available idle states:"));
+       for (idlestate = 1; idlestate < idlestates; idlestate++) {
+               tmp = sysfs_get_idlestate_name(cpu, idlestate);
+               if (!tmp)
+                       continue;
+               printf(" %s", tmp);
+               free(tmp);
+       }
+       printf("\n");
+
+       if (!verbose)
+               return;
+
+       for (idlestate = 1; idlestate < idlestates; idlestate++) {
+               tmp = sysfs_get_idlestate_name(cpu, idlestate);
+               if (!tmp)
+                       continue;
+               printf("%s:\n", tmp);
+               free(tmp);
+
+               tmp = sysfs_get_idlestate_desc(cpu, idlestate);
+               if (!tmp)
+                       continue;
+               printf(_("Flags/Description: %s\n"), tmp);
+               free(tmp);
+
+               printf(_("Latency: %lu\n"),
+                      sysfs_get_idlestate_latency(cpu, idlestate));
+               printf(_("Usage: %lu\n"),
+                      sysfs_get_idlestate_usage(cpu, idlestate));
+               printf(_("Duration: %llu\n"),
+                      sysfs_get_idlestate_time(cpu, idlestate));
+       }
+       printf("\n");
+}
+
+static void cpuidle_general_output(void)
+{
+       char *tmp;
+
+       tmp = sysfs_get_cpuidle_driver();
+       if (!tmp) {
+               printf(_("Could not determine cpuidle driver\n"));
+               return;
+       }
+
+       printf(_("CPUidle driver: %s\n"), tmp);
+       free(tmp);
+
+       tmp = sysfs_get_cpuidle_governor();
+       if (!tmp) {
+               printf(_("Could not determine cpuidle governor\n"));
+               return;
+       }
+
+       printf(_("CPUidle governor: %s\n"), tmp);
+       free(tmp);
+}
+
+static void proc_cpuidle_cpu_output(unsigned int cpu)
+{
+       long max_allowed_cstate = 2000000000;
+       int cstates, cstate;
+
+       cstates = sysfs_get_idlestate_count(cpu);
+       if (cstates == 0) {
+               /*
+                * Go on and print same useless info as you'd see with
+                * cat /proc/acpi/processor/../power
+                *      printf(_("CPU %u: No C-states available\n"), cpu);
+                *      return;
+                */
+       } else if (cstates <= 0) {
+               printf(_("CPU %u: Can't read C-state info\n"), cpu);
+               return;
+       }
+       /* printf("Cstates: %d\n", cstates); */
+
+       printf(_("active state:            C0\n"));
+       printf(_("max_cstate:              C%u\n"), cstates-1);
+       printf(_("maximum allowed latency: %lu usec\n"), max_allowed_cstate);
+       printf(_("states:\t\n"));
+       for (cstate = 1; cstate < cstates; cstate++) {
+               printf(_("    C%d:                  "
+                        "type[C%d] "), cstate, cstate);
+               printf(_("promotion[--] demotion[--] "));
+               printf(_("latency[%03lu] "),
+                      sysfs_get_idlestate_latency(cpu, cstate));
+               printf(_("usage[%08lu] "),
+                      sysfs_get_idlestate_usage(cpu, cstate));
+               printf(_("duration[%020Lu] \n"),
+                      sysfs_get_idlestate_time(cpu, cstate));
+       }
+}
+
+/* --freq / -f */
+
+void idle_info_help(void)
+{
+       printf(_ ("Usage: cpupower idleinfo [options]\n"));
+       printf(_ ("Options:\n"));
+       printf(_ ("  -s, --silent         Only show general C-state information\n"));
+       printf(_ ("  -o, --proc           Prints out information like provided by the /proc/acpi/processor/*/power\n"
+              "                       interface in older kernels\n"));
+       printf(_ ("  -h, --help           Prints out this screen\n"));
+
+       printf("\n");
+}
+
+static struct option info_opts[] = {
+       { .name = "silent",     .has_arg = no_argument, .flag = NULL,   .val = 's'},
+       { .name = "proc",       .has_arg = no_argument, .flag = NULL,   .val = 'o'},
+       { .name = "help",       .has_arg = no_argument, .flag = NULL,   .val = 'h'},
+       { },
+};
+
+static inline void cpuidle_exit(int fail)
+{
+       idle_info_help();
+       exit(EXIT_FAILURE);
+}
+
+int cmd_idle_info(int argc, char **argv)
+{
+       extern char *optarg;
+       extern int optind, opterr, optopt;
+       int ret = 0, cont = 1, output_param = 0, verbose = 1;
+       unsigned int cpu = 0;
+
+       do {
+               ret = getopt_long(argc, argv, "hos", info_opts, NULL);
+               if (ret == -1)
+                       break;
+               switch (ret) {
+               case '?':
+                       output_param = '?';
+                       cont = 0;
+                       break;
+               case 'h':
+                       output_param = 'h';
+                       cont = 0;
+                       break;
+               case 's':
+                       verbose = 0;
+                       break;
+               case -1:
+                       cont = 0;
+                       break;
+               case 'o':
+                       if (output_param) {
+                               output_param = -1;
+                               cont = 0;
+                               break;
+                       }
+                       output_param = ret;
+                       break;
+               }
+       } while (cont);
+
+       switch (output_param) {
+       case -1:
+               printf(_("You can't specify more than one "
+                        "output-specific argument\n"));
+               cpuidle_exit(EXIT_FAILURE);
+       case '?':
+               printf(_("invalid or unknown argument\n"));
+               cpuidle_exit(EXIT_FAILURE);
+       case 'h':
+               cpuidle_exit(EXIT_SUCCESS);
+       }
+
+       /* Default is: show output of CPU 0 only */
+       if (bitmask_isallclear(cpus_chosen))
+               bitmask_setbit(cpus_chosen, 0);
+
+       if (output_param == 0)
+               cpuidle_general_output();
+
+       for (cpu = bitmask_first(cpus_chosen);
+            cpu <= bitmask_last(cpus_chosen); cpu++) {
+
+               if (!bitmask_isbitset(cpus_chosen, cpu) ||
+                   cpufreq_cpu_exists(cpu))
+                       continue;
+
+               switch (output_param) {
+
+               case 'o':
+                       proc_cpuidle_cpu_output(cpu);
+                       break;
+               case 0:
+                       printf("\n");
+                       cpuidle_cpu_output(cpu, verbose);
+                       break;
+               }
+       }
+       return EXIT_SUCCESS;
+}
diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c
new file mode 100644 (file)
index 0000000..85253cb
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <cpufreq.h>
+#include "helpers/helpers.h"
+#include "helpers/sysfs.h"
+
+void info_help(void)
+{
+       printf(_("Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"));
+       printf(_("Options:\n"));
+       printf(_("  -b, --perf-bias    Gets CPU's power vs performance policy on some\n"
+              "                           Intel models [0-15], see manpage for details\n"));
+       printf(_("  -m, --sched-mc     Gets the kernel's multi core scheduler policy.\n"));
+       printf(_("  -s, --sched-smt    Gets the kernel's thread sibling scheduler policy.\n"));
+       printf(_("  -h, --help               Prints out this screen\n"));
+       printf(_("\nPassing no option will show all info, by default only on core 0\n"));
+       printf("\n");
+}
+
+static struct option set_opts[] = {
+       { .name = "perf-bias",  .has_arg = optional_argument,   .flag = NULL,   .val = 'b'},
+       { .name = "sched-mc",   .has_arg = optional_argument,   .flag = NULL,   .val = 'm'},
+       { .name = "sched-smt",  .has_arg = optional_argument,   .flag = NULL,   .val = 's'},
+       { .name = "help",       .has_arg = no_argument,         .flag = NULL,   .val = 'h'},
+       { },
+};
+
+static void print_wrong_arg_exit(void)
+{
+       printf(_("invalid or unknown argument\n"));
+       info_help();
+       exit(EXIT_FAILURE);
+}
+
+int cmd_info(int argc, char **argv)
+{
+       extern char *optarg;
+       extern int optind, opterr, optopt;
+       unsigned int cpu;
+
+       union {
+               struct {
+                       int sched_mc:1;
+                       int sched_smt:1;
+                       int perf_bias:1;
+               };
+               int params;
+       } params = {};
+       int ret = 0;
+
+       setlocale(LC_ALL, "");
+       textdomain(PACKAGE);
+
+       /* parameter parsing */
+       while ((ret = getopt_long(argc, argv, "msbh", set_opts, NULL)) != -1) {
+               switch (ret) {
+               case 'h':
+                       info_help();
+                       return 0;
+               case 'b':
+                       if (params.perf_bias)
+                               print_wrong_arg_exit();
+                       params.perf_bias = 1;
+                       break;
+               case 'm':
+                       if (params.sched_mc)
+                               print_wrong_arg_exit();
+                       params.sched_mc = 1;
+                       break;
+               case 's':
+                       if (params.sched_smt)
+                               print_wrong_arg_exit();
+                       params.sched_smt = 1;
+                       break;
+               default:
+                       print_wrong_arg_exit();
+               }
+       };
+
+       if (!params.params)
+               params.params = 0x7;
+
+       /* Default is: show output of CPU 0 only */
+       if (bitmask_isallclear(cpus_chosen))
+               bitmask_setbit(cpus_chosen, 0);
+
+       if (params.sched_mc) {
+               ret = sysfs_get_sched("mc");
+               printf(_("System's multi core scheduler setting: "));
+               if (ret < 0)
+                       /* if sysfs file is missing it's: errno == ENOENT */
+                       printf(_("not supported\n"));
+               else
+                       printf("%d\n", ret);
+       }
+       if (params.sched_smt) {
+               ret = sysfs_get_sched("smt");
+               printf(_("System's thread sibling scheduler setting: "));
+               if (ret < 0)
+                       /* if sysfs file is missing it's: errno == ENOENT */
+                       printf(_("not supported\n"));
+               else
+                       printf("%d\n", ret);
+       }
+
+       /* Add more per cpu options here */
+       if (!params.perf_bias)
+               return ret;
+
+       if (params.perf_bias) {
+               if (!run_as_root) {
+                       params.perf_bias = 0;
+                       printf(_("Intel's performance bias setting needs root privileges\n"));
+               } else if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) {
+                       printf(_("System does not support Intel's performance"
+                                " bias setting\n"));
+                       params.perf_bias = 0;
+               }
+       }
+
+       /* loop over CPUs */
+       for (cpu = bitmask_first(cpus_chosen);
+            cpu <= bitmask_last(cpus_chosen); cpu++) {
+
+               if (!bitmask_isbitset(cpus_chosen, cpu) ||
+                   cpufreq_cpu_exists(cpu))
+                       continue;
+
+               printf(_("analyzing CPU %d:\n"), cpu);
+
+               if (params.perf_bias) {
+                       ret = msr_intel_get_perf_bias(cpu);
+                       if (ret < 0) {
+                               printf(_("Could not read perf-bias value\n"));
+                               break;
+                       } else
+                               printf(_("perf-bias: %d\n"), ret);
+               }
+       }
+       return ret;
+}
diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c
new file mode 100644 (file)
index 0000000..bc1b391
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <cpufreq.h>
+#include "helpers/helpers.h"
+#include "helpers/sysfs.h"
+#include "helpers/bitmask.h"
+
+void set_help(void)
+{
+       printf(_("Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"));
+       printf(_("Options:\n"));
+       printf(_("  -b, --perf-bias [VAL]    Sets CPU's power vs performance policy on some\n"
+              "                           Intel models [0-15], see manpage for details\n"));
+       printf(_("  -m, --sched-mc  [VAL]    Sets the kernel's multi core scheduler policy.\n"));
+       printf(_("  -s, --sched-smt [VAL]    Sets the kernel's thread sibling scheduler policy.\n"));
+       printf(_("  -h, --help               Prints out this screen\n"));
+       printf("\n");
+}
+
+static struct option set_opts[] = {
+       { .name = "perf-bias",  .has_arg = optional_argument,   .flag = NULL,   .val = 'b'},
+       { .name = "sched-mc",   .has_arg = optional_argument,   .flag = NULL,   .val = 'm'},
+       { .name = "sched-smt",  .has_arg = optional_argument,   .flag = NULL,   .val = 's'},
+       { .name = "help",       .has_arg = no_argument,         .flag = NULL,   .val = 'h'},
+       { },
+};
+
+static void print_wrong_arg_exit(void)
+{
+       printf(_("invalid or unknown argument\n"));
+       set_help();
+       exit(EXIT_FAILURE);
+}
+
+int cmd_set(int argc, char **argv)
+{
+       extern char *optarg;
+       extern int optind, opterr, optopt;
+       unsigned int cpu;
+
+       union {
+               struct {
+                       int sched_mc:1;
+                       int sched_smt:1;
+                       int perf_bias:1;
+               };
+               int params;
+       } params;
+       int sched_mc = 0, sched_smt = 0, perf_bias = 0;
+       int ret = 0;
+
+       setlocale(LC_ALL, "");
+       textdomain(PACKAGE);
+
+       params.params = 0;
+       /* parameter parsing */
+       while ((ret = getopt_long(argc, argv, "m:s:b:h",
+                                               set_opts, NULL)) != -1) {
+               switch (ret) {
+               case 'h':
+                       set_help();
+                       return 0;
+               case 'b':
+                       if (params.perf_bias)
+                               print_wrong_arg_exit();
+                       perf_bias = atoi(optarg);
+                       if (perf_bias < 0 || perf_bias > 15) {
+                               printf(_("--perf-bias param out "
+                                        "of range [0-%d]\n"), 15);
+                               print_wrong_arg_exit();
+                       }
+                       params.perf_bias = 1;
+                       break;
+               case 'm':
+                       if (params.sched_mc)
+                               print_wrong_arg_exit();
+                       sched_mc = atoi(optarg);
+                       if (sched_mc < 0 || sched_mc > 2) {
+                               printf(_("--sched-mc param out "
+                                        "of range [0-%d]\n"), 2);
+                               print_wrong_arg_exit();
+                       }
+                       params.sched_mc = 1;
+                       break;
+               case 's':
+                       if (params.sched_smt)
+                               print_wrong_arg_exit();
+                       sched_smt = atoi(optarg);
+                       if (sched_smt < 0 || sched_smt > 2) {
+                               printf(_("--sched-smt param out "
+                                        "of range [0-%d]\n"), 2);
+                               print_wrong_arg_exit();
+                       }
+                       params.sched_smt = 1;
+                       break;
+               default:
+                       print_wrong_arg_exit();
+               }
+       };
+
+       if (!params.params) {
+               set_help();
+               return -EINVAL;
+       }
+
+       if (params.sched_mc) {
+               ret = sysfs_set_sched("mc", sched_mc);
+               if (ret)
+                       fprintf(stderr, _("Error setting sched-mc %s\n"),
+                               (ret == -ENODEV) ? "not supported" : "");
+       }
+       if (params.sched_smt) {
+               ret = sysfs_set_sched("smt", sched_smt);
+               if (ret)
+                       fprintf(stderr, _("Error setting sched-smt %s\n"),
+                               (ret == -ENODEV) ? "not supported" : "");
+       }
+
+       /* Default is: set all CPUs */
+       if (bitmask_isallclear(cpus_chosen))
+               bitmask_setall(cpus_chosen);
+
+       /* loop over CPUs */
+       for (cpu = bitmask_first(cpus_chosen);
+            cpu <= bitmask_last(cpus_chosen); cpu++) {
+
+               if (!bitmask_isbitset(cpus_chosen, cpu) ||
+                   cpufreq_cpu_exists(cpu))
+                       continue;
+
+               if (params.perf_bias) {
+                       ret = msr_intel_set_perf_bias(cpu, perf_bias);
+                       if (ret) {
+                               fprintf(stderr, _("Error setting perf-bias "
+                                                 "value on CPU %d\n"), cpu);
+                               break;
+                       }
+               }
+       }
+       return ret;
+}
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c
new file mode 100644 (file)
index 0000000..5844ae0
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ *  Ideas taken over from the perf userspace tool (included in the Linus
+ *  kernel git repo): subcommand builtins and param parsing.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "builtin.h"
+#include "helpers/helpers.h"
+#include "helpers/bitmask.h"
+
+struct cmd_struct {
+       const char *cmd;
+       int (*main)(int, const char **);
+       void (*usage)(void);
+       int needs_root;
+};
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+int cmd_help(int argc, const char **argv);
+
+/* Global cpu_info object available for all binaries
+ * Info only retrieved from CPU 0
+ *
+ * Values will be zero/unknown on non X86 archs
+ */
+struct cpupower_cpu_info cpupower_cpu_info;
+int run_as_root;
+/* Affected cpus chosen by -c/--cpu param */
+struct bitmask *cpus_chosen;
+
+#ifdef DEBUG
+int be_verbose;
+#endif
+
+static void print_help(void);
+
+static struct cmd_struct commands[] = {
+       { "frequency-info",     cmd_freq_info,  freq_info_help, 0       },
+       { "frequency-set",      cmd_freq_set,   freq_set_help,  1       },
+       { "idle-info",          cmd_idle_info,  idle_info_help, 0       },
+       { "set",                cmd_set,        set_help,       1       },
+       { "info",               cmd_info,       info_help,      0       },
+       { "monitor",            cmd_monitor,    monitor_help,   0       },
+       { "help",               cmd_help,       print_help,     0       },
+       /*      { "bench",      cmd_bench,      NULL,           1       }, */
+};
+
+int cmd_help(int argc, const char **argv)
+{
+       unsigned int i;
+
+       if (argc > 1) {
+               for (i = 0; i < ARRAY_SIZE(commands); i++) {
+                       struct cmd_struct *p = commands + i;
+                       if (strcmp(p->cmd, argv[1]))
+                               continue;
+                       if (p->usage) {
+                               p->usage();
+                               return EXIT_SUCCESS;
+                       }
+               }
+       }
+       print_help();
+       if (argc == 1)
+               return EXIT_SUCCESS; /* cpupower help */
+       return EXIT_FAILURE;
+}
+
+static void print_help(void)
+{
+       unsigned int i;
+
+#ifdef DEBUG
+       printf(_("cpupower [ -d ][ -c cpulist ] subcommand [ARGS]\n"));
+       printf(_("  -d, --debug      May increase output (stderr) on some subcommands\n"));
+#else
+       printf(_("cpupower [ -c cpulist ] subcommand [ARGS]\n"));
+#endif
+       printf(_("cpupower --version\n"));
+       printf(_("Supported subcommands are:\n"));
+       for (i = 0; i < ARRAY_SIZE(commands); i++)
+               printf("\t%s\n", commands[i].cmd);
+       printf(_("\nSome subcommands can make use of the -c cpulist option.\n"));
+       printf(_("Look at the general cpupower manpage how to use it\n"));
+       printf(_("and read up the subcommand's manpage whether it is supported.\n"));
+       printf(_("\nUse cpupower help subcommand for getting help for above subcommands.\n"));
+}
+
+static void print_version(void)
+{
+       printf(PACKAGE " " VERSION "\n");
+       printf(_("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
+}
+
+static void handle_options(int *argc, const char ***argv)
+{
+       int ret, x, new_argc = 0;
+
+       if (*argc < 1)
+               return;
+
+       for (x = 0;  x < *argc && ((*argv)[x])[0] == '-'; x++) {
+               const char *param = (*argv)[x];
+               if (!strcmp(param, "-h") || !strcmp(param, "--help")) {
+                       print_help();
+                       exit(EXIT_SUCCESS);
+               } else if (!strcmp(param, "-c") || !strcmp(param, "--cpu")) {
+                       if (*argc < 2) {
+                               print_help();
+                               exit(EXIT_FAILURE);
+                       }
+                       if (!strcmp((*argv)[x+1], "all"))
+                               bitmask_setall(cpus_chosen);
+                       else {
+                               ret = bitmask_parselist(
+                                               (*argv)[x+1], cpus_chosen);
+                               if (ret < 0) {
+                                       fprintf(stderr, _("Error parsing cpu "
+                                                         "list\n"));
+                                       exit(EXIT_FAILURE);
+                               }
+                       }
+                       x += 1;
+                       /* Cut out param: cpupower -c 1 info -> cpupower info */
+                       new_argc += 2;
+                       continue;
+               } else if (!strcmp(param, "-v") ||
+                       !strcmp(param, "--version")) {
+                       print_version();
+                       exit(EXIT_SUCCESS);
+#ifdef DEBUG
+               } else if (!strcmp(param, "-d") || !strcmp(param, "--debug")) {
+                       be_verbose = 1;
+                       new_argc++;
+                       continue;
+#endif
+               } else {
+                       fprintf(stderr, "Unknown option: %s\n", param);
+                       print_help();
+                       exit(EXIT_FAILURE);
+               }
+       }
+       *argc -= new_argc;
+       *argv += new_argc;
+}
+
+int main(int argc, const char *argv[])
+{
+       const char *cmd;
+       unsigned int i, ret;
+
+       cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
+
+       argc--;
+       argv += 1;
+
+       handle_options(&argc, &argv);
+
+       cmd = argv[0];
+
+       if (argc < 1) {
+               print_help();
+               return EXIT_FAILURE;
+       }
+
+       setlocale(LC_ALL, "");
+       textdomain(PACKAGE);
+
+       /* Turn "perf cmd --help" into "perf help cmd" */
+       if (argc > 1 && !strcmp(argv[1], "--help")) {
+               argv[1] = argv[0];
+               argv[0] = cmd = "help";
+       }
+
+       get_cpu_info(0, &cpupower_cpu_info);
+       run_as_root = !getuid();
+
+       for (i = 0; i < ARRAY_SIZE(commands); i++) {
+               struct cmd_struct *p = commands + i;
+               if (strcmp(p->cmd, cmd))
+                       continue;
+               if (!run_as_root && p->needs_root) {
+                       fprintf(stderr, _("Subcommand %s needs root "
+                                         "privileges\n"), cmd);
+                       return EXIT_FAILURE;
+               }
+               ret = p->main(argc, argv);
+               if (cpus_chosen)
+                       bitmask_free(cpus_chosen);
+               return ret;
+       }
+       print_help();
+       return EXIT_FAILURE;
+}
diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c
new file mode 100644 (file)
index 0000000..87d5605
--- /dev/null
@@ -0,0 +1,137 @@
+#if defined(__i386__) || defined(__x86_64__)
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include <pci/pci.h>
+
+#include "helpers/helpers.h"
+
+#define MSR_AMD_PSTATE_STATUS  0xc0010063
+#define MSR_AMD_PSTATE         0xc0010064
+#define MSR_AMD_PSTATE_LIMIT   0xc0010061
+
+union msr_pstate {
+       struct {
+               unsigned fid:6;
+               unsigned did:3;
+               unsigned vid:7;
+               unsigned res1:6;
+               unsigned nbdid:1;
+               unsigned res2:2;
+               unsigned nbvid:7;
+               unsigned iddval:8;
+               unsigned idddiv:2;
+               unsigned res3:21;
+               unsigned en:1;
+       } bits;
+       unsigned long long val;
+};
+
+static int get_did(int family, union msr_pstate pstate)
+{
+       int t;
+
+       if (family == 0x12)
+               t = pstate.val & 0xf;
+       else
+               t = pstate.bits.did;
+
+       return t;
+}
+
+static int get_cof(int family, union msr_pstate pstate)
+{
+       int t;
+       int fid, did;
+
+       did = get_did(family, pstate);
+
+       t = 0x10;
+       fid = pstate.bits.fid;
+       if (family == 0x11)
+               t = 0x8;
+
+       return (100 * (fid + t)) >> did;
+}
+
+/* Needs:
+ * cpu          -> the cpu that gets evaluated
+ * cpu_family   -> The cpu's family (0x10, 0x12,...)
+ * boots_states -> how much boost states the machines support
+ *
+ * Fills up:
+ * pstates -> a pointer to an array of size MAX_HW_PSTATES
+ *            must be initialized with zeros.
+ *            All available  HW pstates (including boost states)
+ * no      -> amount of pstates above array got filled up with
+ *
+ * returns zero on success, -1 on failure
+ */
+int decode_pstates(unsigned int cpu, unsigned int cpu_family,
+                  int boost_states, unsigned long *pstates, int *no)
+{
+       int i, psmax, pscur;
+       union msr_pstate pstate;
+       unsigned long long val;
+
+       /* Only read out frequencies from HW when CPU might be boostable
+          to keep the code as short and clean as possible.
+          Otherwise frequencies are exported via ACPI tables.
+       */
+       if (cpu_family < 0x10 || cpu_family == 0x14)
+               return -1;
+
+       if (read_msr(cpu, MSR_AMD_PSTATE_LIMIT, &val))
+               return -1;
+
+       psmax = (val >> 4) & 0x7;
+
+       if (read_msr(cpu, MSR_AMD_PSTATE_STATUS, &val))
+               return -1;
+
+       pscur = val & 0x7;
+
+       pscur += boost_states;
+       psmax += boost_states;
+       for (i = 0; i <= psmax; i++) {
+               if (i >= MAX_HW_PSTATES) {
+                       fprintf(stderr, "HW pstates [%d] exceeding max [%d]\n",
+                               psmax, MAX_HW_PSTATES);
+                       return -1;
+               }
+               if (read_msr(cpu, MSR_AMD_PSTATE + i, &pstate.val))
+                       return -1;
+               pstates[i] = get_cof(cpu_family, pstate);
+       }
+       *no = i;
+       return 0;
+}
+
+int amd_pci_get_num_boost_states(int *active, int *states)
+{
+       struct pci_access *pci_acc;
+       int vendor_id = 0x1022;
+       int boost_dev_ids[4] = {0x1204, 0x1604, 0x1704, 0};
+       struct pci_dev *device;
+       uint8_t val = 0;
+
+       *active = *states = 0;
+
+       device = pci_acc_init(&pci_acc, vendor_id, boost_dev_ids);
+
+       if (device == NULL)
+               return -ENODEV;
+
+       val = pci_read_byte(device, 0x15c);
+       if (val & 3)
+               *active = 1;
+       else
+               *active = 0;
+       *states = (val >> 2) & 7;
+
+       pci_cleanup(pci_acc);
+       return 0;
+}
+#endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/helpers/bitmask.c b/tools/power/cpupower/utils/helpers/bitmask.c
new file mode 100644 (file)
index 0000000..5c074c6
--- /dev/null
@@ -0,0 +1,292 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <helpers/bitmask.h>
+
+/* How many bits in an unsigned long */
+#define bitsperlong (8 * sizeof(unsigned long))
+
+/* howmany(a,b) : how many elements of size b needed to hold all of a */
+#define howmany(x, y) (((x)+((y)-1))/(y))
+
+/* How many longs in mask of n bits */
+#define longsperbits(n) howmany(n, bitsperlong)
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+/*
+ * Allocate and free `struct bitmask *`
+ */
+
+/* Allocate a new `struct bitmask` with a size of n bits */
+struct bitmask *bitmask_alloc(unsigned int n)
+{
+       struct bitmask *bmp;
+
+       bmp = malloc(sizeof(*bmp));
+       if (bmp == 0)
+               return 0;
+       bmp->size = n;
+       bmp->maskp = calloc(longsperbits(n), sizeof(unsigned long));
+       if (bmp->maskp == 0) {
+               free(bmp);
+               return 0;
+       }
+       return bmp;
+}
+
+/* Free `struct bitmask` */
+void bitmask_free(struct bitmask *bmp)
+{
+       if (bmp == 0)
+               return;
+       free(bmp->maskp);
+       bmp->maskp = (unsigned long *)0xdeadcdef;  /* double free tripwire */
+       free(bmp);
+}
+
+/*
+ * The routines _getbit() and _setbit() are the only
+ * routines that actually understand the layout of bmp->maskp[].
+ *
+ * On little endian architectures, this could simply be an array of
+ * bytes.  But the kernel layout of bitmasks _is_ visible to userspace
+ * via the sched_(set/get)affinity calls in Linux 2.6, and on big
+ * endian architectures, it is painfully obvious that this is an
+ * array of unsigned longs.
+ */
+
+/* Return the value (0 or 1) of bit n in bitmask bmp */
+static unsigned int _getbit(const struct bitmask *bmp, unsigned int n)
+{
+       if (n < bmp->size)
+               return (bmp->maskp[n/bitsperlong] >> (n % bitsperlong)) & 1;
+       else
+               return 0;
+}
+
+/* Set bit n in bitmask bmp to value v (0 or 1) */
+static void _setbit(struct bitmask *bmp, unsigned int n, unsigned int v)
+{
+       if (n < bmp->size) {
+               if (v)
+                       bmp->maskp[n/bitsperlong] |= 1UL << (n % bitsperlong);
+               else
+                       bmp->maskp[n/bitsperlong] &=
+                               ~(1UL << (n % bitsperlong));
+       }
+}
+
+/*
+ * When parsing bitmask lists, only allow numbers, separated by one
+ * of the allowed next characters.
+ *
+ * The parameter 'sret' is the return from a sscanf "%u%c".  It is
+ * -1 if the sscanf input string was empty.  It is 0 if the first
+ * character in the sscanf input string was not a decimal number.
+ * It is 1 if the unsigned number matching the "%u" was the end of the
+ * input string.  It is 2 if one or more additional characters followed
+ * the matched unsigned number.  If it is 2, then 'nextc' is the first
+ * character following the number.  The parameter 'ok_next_chars'
+ * is the nul-terminated list of allowed next characters.
+ *
+ * The mask term just scanned was ok if and only if either the numbers
+ * matching the %u were all of the input or if the next character in
+ * the input past the numbers was one of the allowed next characters.
+ */
+static int scan_was_ok(int sret, char nextc, const char *ok_next_chars)
+{
+       return sret == 1 ||
+               (sret == 2 && strchr(ok_next_chars, nextc) != NULL);
+}
+
+static const char *nexttoken(const char *q,  int sep)
+{
+       if (q)
+               q = strchr(q, sep);
+       if (q)
+               q++;
+       return q;
+}
+
+/* Set a single bit i in bitmask */
+struct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i)
+{
+       _setbit(bmp, i, 1);
+       return bmp;
+}
+
+/* Set all bits in bitmask: bmp = ~0 */
+struct bitmask *bitmask_setall(struct bitmask *bmp)
+{
+       unsigned int i;
+       for (i = 0; i < bmp->size; i++)
+               _setbit(bmp, i, 1);
+       return bmp;
+}
+
+/* Clear all bits in bitmask: bmp = 0 */
+struct bitmask *bitmask_clearall(struct bitmask *bmp)
+{
+       unsigned int i;
+       for (i = 0; i < bmp->size; i++)
+               _setbit(bmp, i, 0);
+       return bmp;
+}
+
+/* True if all bits are clear */
+int bitmask_isallclear(const struct bitmask *bmp)
+{
+       unsigned int i;
+       for (i = 0; i < bmp->size; i++)
+               if (_getbit(bmp, i))
+                       return 0;
+       return 1;
+}
+
+/* True if specified bit i is set */
+int bitmask_isbitset(const struct bitmask *bmp, unsigned int i)
+{
+       return _getbit(bmp, i);
+}
+
+/* Number of lowest set bit (min) */
+unsigned int bitmask_first(const struct bitmask *bmp)
+{
+       return bitmask_next(bmp, 0);
+}
+
+/* Number of highest set bit (max) */
+unsigned int bitmask_last(const struct bitmask *bmp)
+{
+       unsigned int i;
+       unsigned int m = bmp->size;
+       for (i = 0; i < bmp->size; i++)
+               if (_getbit(bmp, i))
+                       m = i;
+       return m;
+}
+
+/* Number of next set bit at or above given bit i */
+unsigned int bitmask_next(const struct bitmask *bmp, unsigned int i)
+{
+       unsigned int n;
+       for (n = i; n < bmp->size; n++)
+               if (_getbit(bmp, n))
+                       break;
+       return n;
+}
+
+/*
+ * Parses a comma-separated list of numbers and ranges of numbers,
+ * with optional ':%u' strides modifying ranges, into provided bitmask.
+ * Some examples of input lists and their equivalent simple list:
+ *     Input           Equivalent to
+ *     0-3             0,1,2,3
+ *     0-7:2           0,2,4,6
+ *     1,3,5-7         1,3,5,6,7
+ *     0-3:2,8-15:4    0,2,8,12
+ */
+int bitmask_parselist(const char *buf, struct bitmask *bmp)
+{
+       const char *p, *q;
+
+       bitmask_clearall(bmp);
+
+       q = buf;
+       while (p = q, q = nexttoken(q, ','), p) {
+               unsigned int a;         /* begin of range */
+               unsigned int b;         /* end of range */
+               unsigned int s;         /* stride */
+               const char *c1, *c2;    /* next tokens after '-' or ',' */
+               char nextc;             /* char after sscanf %u match */
+               int sret;               /* sscanf return (number of matches) */
+
+               sret = sscanf(p, "%u%c", &a, &nextc);
+               if (!scan_was_ok(sret, nextc, ",-"))
+                       goto err;
+               b = a;
+               s = 1;
+               c1 = nexttoken(p, '-');
+               c2 = nexttoken(p, ',');
+               if (c1 != NULL && (c2 == NULL || c1 < c2)) {
+                       sret = sscanf(c1, "%u%c", &b, &nextc);
+                       if (!scan_was_ok(sret, nextc, ",:"))
+                               goto err;
+                       c1 = nexttoken(c1, ':');
+                       if (c1 != NULL && (c2 == NULL || c1 < c2)) {
+                               sret = sscanf(c1, "%u%c", &s, &nextc);
+                               if (!scan_was_ok(sret, nextc, ","))
+                                       goto err;
+                       }
+               }
+               if (!(a <= b))
+                       goto err;
+               if (b >= bmp->size)
+                       goto err;
+               while (a <= b) {
+                       _setbit(bmp, a, 1);
+                       a += s;
+               }
+       }
+       return 0;
+err:
+       bitmask_clearall(bmp);
+       return -1;
+}
+
+/*
+ * emit(buf, buflen, rbot, rtop, len)
+ *
+ * Helper routine for bitmask_displaylist().  Write decimal number
+ * or range to buf+len, suppressing output past buf+buflen, with optional
+ * comma-prefix.  Return len of what would be written to buf, if it
+ * all fit.
+ */
+
+static inline int emit(char *buf, int buflen, int rbot, int rtop, int len)
+{
+       if (len > 0)
+               len += snprintf(buf + len, max(buflen - len, 0), ",");
+       if (rbot == rtop)
+               len += snprintf(buf + len, max(buflen - len, 0), "%d", rbot);
+       else
+               len += snprintf(buf + len, max(buflen - len, 0), "%d-%d",
+                               rbot, rtop);
+       return len;
+}
+
+/*
+ * Write decimal list representation of bmp to buf.
+ *
+ * Output format is a comma-separated list of decimal numbers and
+ * ranges.  Consecutively set bits are shown as two hyphen-separated
+ * decimal numbers, the smallest and largest bit numbers set in
+ * the range.  Output format is compatible with the format
+ * accepted as input by bitmap_parselist().
+ *
+ * The return value is the number of characters which would be
+ * generated for the given input, excluding the trailing '\0', as
+ * per ISO C99.
+ */
+
+int bitmask_displaylist(char *buf, int buflen, const struct bitmask *bmp)
+{
+       int len = 0;
+       /* current bit is 'cur', most recently seen range is [rbot, rtop] */
+       unsigned int cur, rbot, rtop;
+
+       if (buflen > 0)
+               *buf = 0;
+       rbot = cur = bitmask_first(bmp);
+       while (cur < bmp->size) {
+               rtop = cur;
+               cur = bitmask_next(bmp, cur+1);
+               if (cur >= bmp->size || cur > rtop + 1) {
+                       len = emit(buf, buflen, rbot, rtop, len);
+                       rbot = cur;
+               }
+       }
+       return len;
+}
diff --git a/tools/power/cpupower/utils/helpers/bitmask.h b/tools/power/cpupower/utils/helpers/bitmask.h
new file mode 100644 (file)
index 0000000..eb289df
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __CPUPOWER_BITMASK__
+#define __CPUPOWER_BITMASK__
+
+/* Taken over from libbitmask, a project initiated from sgi:
+ * Url:            http://oss.sgi.com/projects/cpusets/
+ * Unfortunately it's not very widespread, therefore relevant parts are
+ * pasted here.
+ */
+
+struct bitmask {
+       unsigned int size;
+       unsigned long *maskp;
+};
+
+struct bitmask *bitmask_alloc(unsigned int n);
+void bitmask_free(struct bitmask *bmp);
+
+struct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i);
+struct bitmask *bitmask_setall(struct bitmask *bmp);
+struct bitmask *bitmask_clearall(struct bitmask *bmp);
+
+unsigned int bitmask_first(const struct bitmask *bmp);
+unsigned int bitmask_next(const struct bitmask *bmp, unsigned int i);
+unsigned int bitmask_last(const struct bitmask *bmp);
+int bitmask_isallclear(const struct bitmask *bmp);
+int bitmask_isbitset(const struct bitmask *bmp, unsigned int i);
+
+int bitmask_parselist(const char *buf, struct bitmask *bmp);
+int bitmask_displaylist(char *buf, int len, const struct bitmask *bmp);
+
+
+
+#endif /*__CPUPOWER_BITMASK__ */
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
new file mode 100644 (file)
index 0000000..906895d
--- /dev/null
@@ -0,0 +1,176 @@
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "helpers/helpers.h"
+
+static const char *cpu_vendor_table[X86_VENDOR_MAX] = {
+       "Unknown", "GenuineIntel", "AuthenticAMD",
+};
+
+#if defined(__i386__) || defined(__x86_64__)
+
+/* from gcc */
+#include <cpuid.h>
+
+/*
+ * CPUID functions returning a single datum
+ *
+ * Define unsigned int cpuid_e[abcd]x(unsigned int op)
+ */
+#define cpuid_func(reg)                                        \
+       unsigned int cpuid_##reg(unsigned int op)       \
+       {                                               \
+       unsigned int eax, ebx, ecx, edx;                \
+       __cpuid(op, eax, ebx, ecx, edx);                \
+       return reg;                                     \
+       }
+cpuid_func(eax);
+cpuid_func(ebx);
+cpuid_func(ecx);
+cpuid_func(edx);
+
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
+/* get_cpu_info
+ *
+ * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo
+ *
+ * Returns 0 on success or a negativ error code
+ *
+ * TBD: Should there be a cpuid alternative for this if /proc is not mounted?
+ */
+int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info)
+{
+       FILE *fp;
+       char value[64];
+       unsigned int proc, x;
+       unsigned int unknown = 0xffffff;
+       unsigned int cpuid_level, ext_cpuid_level;
+
+       int ret = -EINVAL;
+
+       cpu_info->vendor                = X86_VENDOR_UNKNOWN;
+       cpu_info->family                = unknown;
+       cpu_info->model                 = unknown;
+       cpu_info->stepping              = unknown;
+       cpu_info->caps                  = 0;
+
+       fp = fopen("/proc/cpuinfo", "r");
+       if (!fp)
+               return -EIO;
+
+       while (!feof(fp)) {
+               if (!fgets(value, 64, fp))
+                       continue;
+               value[63 - 1] = '\0';
+
+               if (!strncmp(value, "processor\t: ", 12))
+                       sscanf(value, "processor\t: %u", &proc);
+
+               if (proc != cpu)
+                       continue;
+
+               /* Get CPU vendor */
+               if (!strncmp(value, "vendor_id", 9)) {
+                       for (x = 1; x < X86_VENDOR_MAX; x++) {
+                               if (strstr(value, cpu_vendor_table[x]))
+                                       cpu_info->vendor = x;
+                       }
+               /* Get CPU family, etc. */
+               } else if (!strncmp(value, "cpu family\t: ", 13)) {
+                       sscanf(value, "cpu family\t: %u",
+                              &cpu_info->family);
+               } else if (!strncmp(value, "model\t\t: ", 9)) {
+                       sscanf(value, "model\t\t: %u",
+                              &cpu_info->model);
+               } else if (!strncmp(value, "stepping\t: ", 10)) {
+                       sscanf(value, "stepping\t: %u",
+                              &cpu_info->stepping);
+
+                       /* Exit -> all values must have been set */
+                       if (cpu_info->vendor == X86_VENDOR_UNKNOWN ||
+                           cpu_info->family == unknown ||
+                           cpu_info->model == unknown ||
+                           cpu_info->stepping == unknown) {
+                               ret = -EINVAL;
+                               goto out;
+                       }
+
+                       ret = 0;
+                       goto out;
+               }
+       }
+       ret = -ENODEV;
+out:
+       fclose(fp);
+       /* Get some useful CPU capabilities from cpuid */
+       if (cpu_info->vendor != X86_VENDOR_AMD &&
+           cpu_info->vendor != X86_VENDOR_INTEL)
+               return ret;
+
+       cpuid_level     = cpuid_eax(0);
+       ext_cpuid_level = cpuid_eax(0x80000000);
+
+       /* Invariant TSC */
+       if (ext_cpuid_level >= 0x80000007 &&
+           (cpuid_edx(0x80000007) & (1 << 8)))
+               cpu_info->caps |= CPUPOWER_CAP_INV_TSC;
+
+       /* Aperf/Mperf registers support */
+       if (cpuid_level >= 6 && (cpuid_ecx(6) & 0x1))
+               cpu_info->caps |= CPUPOWER_CAP_APERF;
+
+       /* AMD Boost state enable/disable register */
+       if (cpu_info->vendor == X86_VENDOR_AMD) {
+               if (ext_cpuid_level >= 0x80000007 &&
+                   (cpuid_edx(0x80000007) & (1 << 9)))
+                       cpu_info->caps |= CPUPOWER_CAP_AMD_CBP;
+       }
+
+       if (cpu_info->vendor == X86_VENDOR_INTEL) {
+               if (cpuid_level >= 6 &&
+                   (cpuid_eax(6) & (1 << 1)))
+                       cpu_info->caps |= CPUPOWER_CAP_INTEL_IDA;
+       }
+
+       if (cpu_info->vendor == X86_VENDOR_INTEL) {
+               /* Intel's perf-bias MSR support */
+               if (cpuid_level >= 6 && (cpuid_ecx(6) & (1 << 3)))
+                       cpu_info->caps |= CPUPOWER_CAP_PERF_BIAS;
+
+               /* Intel's Turbo Ratio Limit support */
+               if (cpu_info->family == 6) {
+                       switch (cpu_info->model) {
+                       case 0x1A:      /* Core i7, Xeon 5500 series
+                                        * Bloomfield, Gainstown NHM-EP
+                                        */
+                       case 0x1E:      /* Core i7 and i5 Processor
+                                        * Clarksfield, Lynnfield, Jasper Forest
+                                        */
+                       case 0x1F:      /* Core i7 and i5 Processor - Nehalem */
+                       case 0x25:      /* Westmere Client
+                                        * Clarkdale, Arrandale
+                                        */
+                       case 0x2C:      /* Westmere EP - Gulftown */
+                               cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
+                       case 0x2A:      /* SNB */
+                       case 0x2D:      /* SNB Xeon */
+                               cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
+                               cpu_info->caps |= CPUPOWER_CAP_IS_SNB;
+                               break;
+                       case 0x2E:      /* Nehalem-EX Xeon - Beckton */
+                       case 0x2F:      /* Westmere-EX Xeon - Eagleton */
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       /*      printf("ID: %u - Extid: 0x%x - Caps: 0x%llx\n",
+               cpuid_level, ext_cpuid_level, cpu_info->caps);
+       */
+       return ret;
+}
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
new file mode 100644 (file)
index 0000000..592ee36
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ * Miscellaneous helpers which do not fit or are worth
+ * to put into separate headers
+ */
+
+#ifndef __CPUPOWERUTILS_HELPERS__
+#define __CPUPOWERUTILS_HELPERS__
+
+#include <libintl.h>
+#include <locale.h>
+
+#include "helpers/bitmask.h"
+
+/* Internationalization ****************************/
+#define _(String) gettext(String)
+#ifndef gettext_noop
+#define gettext_noop(String) String
+#endif
+#define N_(String) gettext_noop(String)
+/* Internationalization ****************************/
+
+extern int run_as_root;
+extern struct bitmask *cpus_chosen;
+
+/* Global verbose (-d) stuff *********************************/
+/*
+ * define DEBUG via global Makefile variable
+ * Debug output is sent to stderr, do:
+ * cpupower monitor 2>/tmp/debug
+ * to split debug output away from normal output
+*/
+#ifdef DEBUG
+extern int be_verbose;
+
+#define dprint(fmt, ...) {                                     \
+               if (be_verbose) {                               \
+                       fprintf(stderr, "%s: " fmt,             \
+                               __func__, ##__VA_ARGS__);       \
+               }                                               \
+       }
+#else
+static inline void dprint(const char *fmt, ...) { }
+#endif
+extern int be_verbose;
+/* Global verbose (-v) stuff *********************************/
+
+/* cpuid and cpuinfo helpers  **************************/
+enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
+                         X86_VENDOR_AMD, X86_VENDOR_MAX};
+
+#define CPUPOWER_CAP_INV_TSC           0x00000001
+#define CPUPOWER_CAP_APERF             0x00000002
+#define CPUPOWER_CAP_AMD_CBP           0x00000004
+#define CPUPOWER_CAP_PERF_BIAS         0x00000008
+#define CPUPOWER_CAP_HAS_TURBO_RATIO   0x00000010
+#define CPUPOWER_CAP_IS_SNB            0x00000011
+#define CPUPOWER_CAP_INTEL_IDA         0x00000012
+
+#define MAX_HW_PSTATES 10
+
+struct cpupower_cpu_info {
+       enum cpupower_cpu_vendor vendor;
+       unsigned int family;
+       unsigned int model;
+       unsigned int stepping;
+       /* CPU capabilities read out from cpuid */
+       unsigned long long caps;
+};
+
+/* get_cpu_info
+ *
+ * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo
+ *
+ * Returns 0 on success or a negativ error code
+ * Only used on x86, below global's struct values are zero/unknown on
+ * other archs
+ */
+extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info);
+extern struct cpupower_cpu_info cpupower_cpu_info;
+/* cpuid and cpuinfo helpers  **************************/
+
+
+/* CPU topology/hierarchy parsing ******************/
+struct cpupower_topology {
+       /* Amount of CPU cores, packages and threads per core in the system */
+       unsigned int cores;
+       unsigned int pkgs;
+       unsigned int threads; /* per core */
+
+       /* Array gets mallocated with cores entries, holding per core info */
+       struct {
+               int pkg;
+               int core;
+               int cpu;
+       } *core_info;
+};
+
+extern int get_cpu_topology(struct cpupower_topology *cpu_top);
+extern void cpu_topology_release(struct cpupower_topology cpu_top);
+/* CPU topology/hierarchy parsing ******************/
+
+/* X86 ONLY ****************************************/
+#if defined(__i386__) || defined(__x86_64__)
+
+#include <pci/pci.h>
+
+/* Read/Write msr ****************************/
+extern int read_msr(int cpu, unsigned int idx, unsigned long long *val);
+extern int write_msr(int cpu, unsigned int idx, unsigned long long val);
+
+extern int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val);
+extern int msr_intel_get_perf_bias(unsigned int cpu);
+extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu);
+
+/* Read/Write msr ****************************/
+
+/* PCI stuff ****************************/
+extern int amd_pci_get_num_boost_states(int *active, int *states);
+extern struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
+                                   int *dev_ids);
+
+/* PCI stuff ****************************/
+
+/* AMD HW pstate decoding **************************/
+
+extern int decode_pstates(unsigned int cpu, unsigned int cpu_family,
+                         int boost_states, unsigned long *pstates, int *no);
+
+/* AMD HW pstate decoding **************************/
+
+extern int cpufreq_has_boost_support(unsigned int cpu, int *support,
+                                    int *active, int * states);
+/*
+ * CPUID functions returning a single datum
+ */
+unsigned int cpuid_eax(unsigned int op);
+unsigned int cpuid_ebx(unsigned int op);
+unsigned int cpuid_ecx(unsigned int op);
+unsigned int cpuid_edx(unsigned int op);
+
+/* cpuid and cpuinfo helpers  **************************/
+/* X86 ONLY ********************************************/
+#else
+static inline int decode_pstates(unsigned int cpu, unsigned int cpu_family,
+                                int boost_states, unsigned long *pstates,
+                                int *no)
+{ return -1; };
+
+static inline int read_msr(int cpu, unsigned int idx, unsigned long long *val)
+{ return -1; };
+static inline int write_msr(int cpu, unsigned int idx, unsigned long long val)
+{ return -1; };
+static inline int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val)
+{ return -1; };
+static inline int msr_intel_get_perf_bias(unsigned int cpu)
+{ return -1; };
+static inline unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu)
+{ return 0; };
+
+/* Read/Write msr ****************************/
+
+static inline int cpufreq_has_boost_support(unsigned int cpu, int *support,
+                                           int *active, int * states)
+{ return -1; }
+
+/* cpuid and cpuinfo helpers  **************************/
+
+static inline unsigned int cpuid_eax(unsigned int op) { return 0; };
+static inline unsigned int cpuid_ebx(unsigned int op) { return 0; };
+static inline unsigned int cpuid_ecx(unsigned int op) { return 0; };
+static inline unsigned int cpuid_edx(unsigned int op) { return 0; };
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
+#endif /* __CPUPOWERUTILS_HELPERS__ */
diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
new file mode 100644 (file)
index 0000000..1609243
--- /dev/null
@@ -0,0 +1,27 @@
+#if defined(__i386__) || defined(__x86_64__)
+
+#include "helpers/helpers.h"
+
+int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
+                       int *states)
+{
+       struct cpupower_cpu_info cpu_info;
+       int ret;
+
+       *support = *active = *states = 0;
+
+       ret = get_cpu_info(0, &cpu_info);
+       if (ret)
+               return ret;
+
+       if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CBP) {
+               *support = 1;
+               amd_pci_get_num_boost_states(active, states);
+               if (ret <= 0)
+                       return ret;
+               *support = 1;
+       } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA)
+               *support = *active = 1;
+       return 0;
+}
+#endif /* #if defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/helpers/msr.c b/tools/power/cpupower/utils/helpers/msr.c
new file mode 100644 (file)
index 0000000..31a4b24
--- /dev/null
@@ -0,0 +1,115 @@
+#if defined(__i386__) || defined(__x86_64__)
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include "helpers/helpers.h"
+
+/* Intel specific MSRs */
+#define MSR_IA32_PERF_STATUS           0x198
+#define MSR_IA32_MISC_ENABLES          0x1a0
+#define MSR_IA32_ENERGY_PERF_BIAS      0x1b0
+#define MSR_NEHALEM_TURBO_RATIO_LIMIT  0x1ad
+
+/*
+ * read_msr
+ *
+ * Will return 0 on success and -1 on failure.
+ * Possible errno values could be:
+ * EFAULT -If the read/write did not fully complete
+ * EIO    -If the CPU does not support MSRs
+ * ENXIO  -If the CPU does not exist
+ */
+
+int read_msr(int cpu, unsigned int idx, unsigned long long *val)
+{
+       int fd;
+       char msr_file_name[64];
+
+       sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
+       fd = open(msr_file_name, O_RDONLY);
+       if (fd < 0)
+               return -1;
+       if (lseek(fd, idx, SEEK_CUR) == -1)
+               goto err;
+       if (read(fd, val, sizeof *val) != sizeof *val)
+               goto err;
+       close(fd);
+       return 0;
+ err:
+       close(fd);
+       return -1;
+}
+
+/*
+ * write_msr
+ *
+ * Will return 0 on success and -1 on failure.
+ * Possible errno values could be:
+ * EFAULT -If the read/write did not fully complete
+ * EIO    -If the CPU does not support MSRs
+ * ENXIO  -If the CPU does not exist
+ */
+int write_msr(int cpu, unsigned int idx, unsigned long long val)
+{
+       int fd;
+       char msr_file_name[64];
+
+       sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
+       fd = open(msr_file_name, O_WRONLY);
+       if (fd < 0)
+               return -1;
+       if (lseek(fd, idx, SEEK_CUR) == -1)
+               goto err;
+       if (write(fd, &val, sizeof val) != sizeof val)
+               goto err;
+       close(fd);
+       return 0;
+ err:
+       close(fd);
+       return -1;
+}
+
+int msr_intel_get_perf_bias(unsigned int cpu)
+{
+       unsigned long long val;
+       int ret;
+
+       if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS))
+               return -1;
+
+       ret = read_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &val);
+       if (ret)
+               return ret;
+       return val;
+}
+
+int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val)
+{
+       int ret;
+
+       if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS))
+               return -1;
+
+       ret = write_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, val);
+       if (ret)
+               return ret;
+       return 0;
+}
+
+unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu)
+{
+       unsigned long long val;
+       int ret;
+
+       if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO))
+               return -1;
+
+       ret = read_msr(cpu, MSR_NEHALEM_TURBO_RATIO_LIMIT, &val);
+       if (ret)
+               return ret;
+       return val;
+}
+#endif
diff --git a/tools/power/cpupower/utils/helpers/pci.c b/tools/power/cpupower/utils/helpers/pci.c
new file mode 100644 (file)
index 0000000..cd2eb6f
--- /dev/null
@@ -0,0 +1,44 @@
+#if defined(__i386__) || defined(__x86_64__)
+
+#include <helpers/helpers.h>
+
+/*
+ * pci_acc_init
+ *
+ * PCI access helper function depending on libpci
+ *
+ * **pacc : if a valid pci_dev is returned
+ *         *pacc must be passed to pci_acc_cleanup to free it
+ *
+ * vendor_id : the pci vendor id matching the pci device to access
+ * dev_ids :   device ids matching the pci device to access
+ *
+ * Returns :
+ * struct pci_dev which can be used with pci_{read,write}_* functions
+ *                to access the PCI config space of matching pci devices
+ */
+struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
+                                   int *dev_ids)
+{
+       struct pci_filter filter_nb_link = { -1, -1, -1, -1, vendor_id, 0};
+       struct pci_dev *device;
+       unsigned int i;
+
+       *pacc = pci_alloc();
+       if (*pacc == NULL)
+               return NULL;
+
+       pci_init(*pacc);
+       pci_scan_bus(*pacc);
+
+       for (i = 0; dev_ids[i] != 0; i++) {
+               filter_nb_link.device = dev_ids[i];
+               for (device = (*pacc)->devices; device; device = device->next) {
+                       if (pci_filter_match(&filter_nb_link, device))
+                               return device;
+               }
+       }
+       pci_cleanup(*pacc);
+       return NULL;
+}
+#endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c
new file mode 100644 (file)
index 0000000..55e2466
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
+ *  (C) 2011       Thomas Renninger <trenn@novell.com> Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "helpers/sysfs.h"
+
+unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
+{
+       int fd;
+       ssize_t numread;
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1)
+               return 0;
+
+       numread = read(fd, buf, buflen - 1);
+       if (numread < 1) {
+               close(fd);
+               return 0;
+       }
+
+       buf[numread] = '\0';
+       close(fd);
+
+       return (unsigned int) numread;
+}
+
+static unsigned int sysfs_write_file(const char *path,
+                                    const char *value, size_t len)
+{
+       int fd;
+       ssize_t numwrite;
+
+       fd = open(path, O_WRONLY);
+       if (fd == -1)
+               return 0;
+
+       numwrite = write(fd, value, len);
+       if (numwrite < 1) {
+               close(fd);
+               return 0;
+       }
+       close(fd);
+       return (unsigned int) numwrite;
+}
+
+/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
+
+/*
+ * helper function to read file from /sys into given buffer
+ * fname is a relative path under "cpuX/cpuidle/stateX/" dir
+ * cstates starting with 0, C0 is not counted as cstate.
+ * This means if you want C1 info, pass 0 as idlestate param
+ */
+unsigned int sysfs_idlestate_read_file(unsigned int cpu, unsigned int idlestate,
+                            const char *fname, char *buf, size_t buflen)
+{
+       char path[SYSFS_PATH_MAX];
+       int fd;
+       ssize_t numread;
+
+       snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
+                cpu, idlestate, fname);
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1)
+               return 0;
+
+       numread = read(fd, buf, buflen - 1);
+       if (numread < 1) {
+               close(fd);
+               return 0;
+       }
+
+       buf[numread] = '\0';
+       close(fd);
+
+       return (unsigned int) numread;
+}
+
+/* read access to files which contain one numeric value */
+
+enum idlestate_value {
+       IDLESTATE_USAGE,
+       IDLESTATE_POWER,
+       IDLESTATE_LATENCY,
+       IDLESTATE_TIME,
+       MAX_IDLESTATE_VALUE_FILES
+};
+
+static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = {
+       [IDLESTATE_USAGE] = "usage",
+       [IDLESTATE_POWER] = "power",
+       [IDLESTATE_LATENCY] = "latency",
+       [IDLESTATE_TIME]  = "time",
+};
+
+static unsigned long long sysfs_idlestate_get_one_value(unsigned int cpu,
+                                                    unsigned int idlestate,
+                                                    enum idlestate_value which)
+{
+       unsigned long long value;
+       unsigned int len;
+       char linebuf[MAX_LINE_LEN];
+       char *endp;
+
+       if (which >= MAX_IDLESTATE_VALUE_FILES)
+               return 0;
+
+       len = sysfs_idlestate_read_file(cpu, idlestate,
+                                       idlestate_value_files[which],
+                                       linebuf, sizeof(linebuf));
+       if (len == 0)
+               return 0;
+
+       value = strtoull(linebuf, &endp, 0);
+
+       if (endp == linebuf || errno == ERANGE)
+               return 0;
+
+       return value;
+}
+
+/* read access to files which contain one string */
+
+enum idlestate_string {
+       IDLESTATE_DESC,
+       IDLESTATE_NAME,
+       MAX_IDLESTATE_STRING_FILES
+};
+
+static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = {
+       [IDLESTATE_DESC] = "desc",
+       [IDLESTATE_NAME] = "name",
+};
+
+
+static char *sysfs_idlestate_get_one_string(unsigned int cpu,
+                                       unsigned int idlestate,
+                                       enum idlestate_string which)
+{
+       char linebuf[MAX_LINE_LEN];
+       char *result;
+       unsigned int len;
+
+       if (which >= MAX_IDLESTATE_STRING_FILES)
+               return NULL;
+
+       len = sysfs_idlestate_read_file(cpu, idlestate,
+                                       idlestate_string_files[which],
+                                       linebuf, sizeof(linebuf));
+       if (len == 0)
+               return NULL;
+
+       result = strdup(linebuf);
+       if (result == NULL)
+               return NULL;
+
+       if (result[strlen(result) - 1] == '\n')
+               result[strlen(result) - 1] = '\0';
+
+       return result;
+}
+
+unsigned long sysfs_get_idlestate_latency(unsigned int cpu,
+                                       unsigned int idlestate)
+{
+       return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_LATENCY);
+}
+
+unsigned long sysfs_get_idlestate_usage(unsigned int cpu,
+                                       unsigned int idlestate)
+{
+       return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_USAGE);
+}
+
+unsigned long long sysfs_get_idlestate_time(unsigned int cpu,
+                                       unsigned int idlestate)
+{
+       return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_TIME);
+}
+
+char *sysfs_get_idlestate_name(unsigned int cpu, unsigned int idlestate)
+{
+       return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_NAME);
+}
+
+char *sysfs_get_idlestate_desc(unsigned int cpu, unsigned int idlestate)
+{
+       return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_DESC);
+}
+
+/*
+ * Returns number of supported C-states of CPU core cpu
+ * Negativ in error case
+ * Zero if cpuidle does not export any C-states
+ */
+int sysfs_get_idlestate_count(unsigned int cpu)
+{
+       char file[SYSFS_PATH_MAX];
+       struct stat statbuf;
+       int idlestates = 1;
+
+
+       snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle");
+       if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
+               return -ENODEV;
+
+       snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu);
+       if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
+               return 0;
+
+       while (stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
+               snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU
+                        "cpu%u/cpuidle/state%d", cpu, idlestates);
+               idlestates++;
+       }
+       idlestates--;
+       return idlestates;
+}
+
+/* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/
+
+/*
+ * helper function to read file from /sys into given buffer
+ * fname is a relative path under "cpu/cpuidle/" dir
+ */
+static unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf,
+                                           size_t buflen)
+{
+       char path[SYSFS_PATH_MAX];
+
+       snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname);
+
+       return sysfs_read_file(path, buf, buflen);
+}
+
+
+
+/* read access to files which contain one string */
+
+enum cpuidle_string {
+       CPUIDLE_GOVERNOR,
+       CPUIDLE_GOVERNOR_RO,
+       CPUIDLE_DRIVER,
+       MAX_CPUIDLE_STRING_FILES
+};
+
+static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = {
+       [CPUIDLE_GOVERNOR]      = "current_governor",
+       [CPUIDLE_GOVERNOR_RO]   = "current_governor_ro",
+       [CPUIDLE_DRIVER]        = "current_driver",
+};
+
+
+static char *sysfs_cpuidle_get_one_string(enum cpuidle_string which)
+{
+       char linebuf[MAX_LINE_LEN];
+       char *result;
+       unsigned int len;
+
+       if (which >= MAX_CPUIDLE_STRING_FILES)
+               return NULL;
+
+       len = sysfs_cpuidle_read_file(cpuidle_string_files[which],
+                               linebuf, sizeof(linebuf));
+       if (len == 0)
+               return NULL;
+
+       result = strdup(linebuf);
+       if (result == NULL)
+               return NULL;
+
+       if (result[strlen(result) - 1] == '\n')
+               result[strlen(result) - 1] = '\0';
+
+       return result;
+}
+
+char *sysfs_get_cpuidle_governor(void)
+{
+       char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO);
+       if (!tmp)
+               return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR);
+       else
+               return tmp;
+}
+
+char *sysfs_get_cpuidle_driver(void)
+{
+       return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER);
+}
+/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
+
+/*
+ * Get sched_mc or sched_smt settings
+ * Pass "mc" or "smt" as argument
+ *
+ * Returns negative value on failure
+ */
+int sysfs_get_sched(const char *smt_mc)
+{
+       unsigned long value;
+       char linebuf[MAX_LINE_LEN];
+       char *endp;
+       char path[SYSFS_PATH_MAX];
+
+       if (strcmp("mc", smt_mc) && strcmp("smt", smt_mc))
+               return -EINVAL;
+
+       snprintf(path, sizeof(path),
+               PATH_TO_CPU "sched_%s_power_savings", smt_mc);
+       if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
+               return -1;
+       value = strtoul(linebuf, &endp, 0);
+       if (endp == linebuf || errno == ERANGE)
+               return -1;
+       return value;
+}
+
+/*
+ * Get sched_mc or sched_smt settings
+ * Pass "mc" or "smt" as argument
+ *
+ * Returns negative value on failure
+ */
+int sysfs_set_sched(const char *smt_mc, int val)
+{
+       char linebuf[MAX_LINE_LEN];
+       char path[SYSFS_PATH_MAX];
+       struct stat statbuf;
+
+       if (strcmp("mc", smt_mc) && strcmp("smt", smt_mc))
+               return -EINVAL;
+
+       snprintf(path, sizeof(path),
+               PATH_TO_CPU "sched_%s_power_savings", smt_mc);
+       sprintf(linebuf, "%d", val);
+
+       if (stat(path, &statbuf) != 0)
+               return -ENODEV;
+
+       if (sysfs_write_file(path, linebuf, MAX_LINE_LEN) == 0)
+               return -1;
+       return 0;
+}
diff --git a/tools/power/cpupower/utils/helpers/sysfs.h b/tools/power/cpupower/utils/helpers/sysfs.h
new file mode 100644 (file)
index 0000000..f9373e0
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __CPUPOWER_HELPERS_SYSFS_H__
+#define __CPUPOWER_HELPERS_SYSFS_H__
+
+#define PATH_TO_CPU "/sys/devices/system/cpu/"
+#define MAX_LINE_LEN 255
+#define SYSFS_PATH_MAX 255
+
+extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen);
+
+extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu,
+                                               unsigned int idlestate);
+extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu,
+                                       unsigned int idlestate);
+extern unsigned long long sysfs_get_idlestate_time(unsigned int cpu,
+                                               unsigned int idlestate);
+extern char *sysfs_get_idlestate_name(unsigned int cpu,
+                               unsigned int idlestate);
+extern char *sysfs_get_idlestate_desc(unsigned int cpu,
+                               unsigned int idlestate);
+extern int sysfs_get_idlestate_count(unsigned int cpu);
+
+extern char *sysfs_get_cpuidle_governor(void);
+extern char *sysfs_get_cpuidle_driver(void);
+
+extern int sysfs_get_sched(const char *smt_mc);
+extern int sysfs_set_sched(const char *smt_mc, int val);
+
+#endif /* __CPUPOWER_HELPERS_SYSFS_H__ */
diff --git a/tools/power/cpupower/utils/helpers/topology.c b/tools/power/cpupower/utils/helpers/topology.c
new file mode 100644 (file)
index 0000000..385ee5c
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ * ToDo: Needs to be done more properly for AMD/Intel specifics
+ */
+
+/* Helper struct for qsort, must be in sync with cpupower_topology.cpu_info */
+/* Be careful: Need to pass unsigned to the sort, so that offlined cores are
+   in the end, but double check for -1 for offlined cpus at other places */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <helpers/helpers.h>
+#include <helpers/sysfs.h>
+
+/* returns -1 on failure, 0 on success */
+int sysfs_topology_read_file(unsigned int cpu, const char *fname)
+{
+       unsigned long value;
+       char linebuf[MAX_LINE_LEN];
+       char *endp;
+       char path[SYSFS_PATH_MAX];
+
+       snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s",
+                        cpu, fname);
+       if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
+               return -1;
+       value = strtoul(linebuf, &endp, 0);
+       if (endp == linebuf || errno == ERANGE)
+               return -1;
+       return value;
+}
+
+struct cpuid_core_info {
+       unsigned int pkg;
+       unsigned int thread;
+       unsigned int cpu;
+};
+
+static int __compare(const void *t1, const void *t2)
+{
+       struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
+       struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2;
+       if (top1->pkg < top2->pkg)
+               return -1;
+       else if (top1->pkg > top2->pkg)
+               return 1;
+       else if (top1->thread < top2->thread)
+               return -1;
+       else if (top1->thread > top2->thread)
+               return 1;
+       else if (top1->cpu < top2->cpu)
+               return -1;
+       else if (top1->cpu > top2->cpu)
+               return 1;
+       else
+               return 0;
+}
+
+/*
+ * Returns amount of cpus, negative on error, cpu_top must be
+ * passed to cpu_topology_release to free resources
+ *
+ * Array is sorted after ->pkg, ->core, then ->cpu
+ */
+int get_cpu_topology(struct cpupower_topology *cpu_top)
+{
+       int cpu, cpus = sysconf(_SC_NPROCESSORS_CONF);
+
+       cpu_top->core_info = malloc(sizeof(struct cpupower_topology) * cpus);
+       if (cpu_top->core_info == NULL)
+               return -ENOMEM;
+       cpu_top->pkgs = cpu_top->cores = 0;
+       for (cpu = 0; cpu < cpus; cpu++) {
+               cpu_top->core_info[cpu].pkg =
+                       sysfs_topology_read_file(cpu, "physical_package_id");
+               if ((int)cpu_top->core_info[cpu].pkg != -1 &&
+                   cpu_top->core_info[cpu].pkg > cpu_top->pkgs)
+                       cpu_top->pkgs = cpu_top->core_info[cpu].pkg;
+               cpu_top->core_info[cpu].core =
+                       sysfs_topology_read_file(cpu, "core_id");
+               cpu_top->core_info[cpu].cpu = cpu;
+       }
+       cpu_top->pkgs++;
+
+       qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
+             __compare);
+
+       /* Intel's cores count is not consecutively numbered, there may
+        * be a core_id of 3, but none of 2. Assume there always is 0
+        * Get amount of cores by counting duplicates in a package
+       for (cpu = 0; cpu_top->core_info[cpu].pkg = 0 && cpu < cpus; cpu++) {
+               if (cpu_top->core_info[cpu].core == 0)
+       cpu_top->cores++;
+       */
+       return cpus;
+}
+
+void cpu_topology_release(struct cpupower_topology cpu_top)
+{
+       free(cpu_top.core_info);
+}
diff --git a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
new file mode 100644 (file)
index 0000000..202e555
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ *  (C) 2010,2011      Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ *  PCI initialization based on example code from:
+ *  Andreas Herrmann <andreas.herrmann3@amd.com>
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <time.h>
+#include <string.h>
+
+#include <pci/pci.h>
+
+#include "idle_monitor/cpupower-monitor.h"
+#include "helpers/helpers.h"
+
+/******** PCI parts could go into own file and get shared ***************/
+
+#define PCI_NON_PC0_OFFSET     0xb0
+#define PCI_PC1_OFFSET         0xb4
+#define PCI_PC6_OFFSET         0xb8
+
+#define PCI_MONITOR_ENABLE_REG  0xe0
+
+#define PCI_NON_PC0_ENABLE_BIT 0
+#define PCI_PC1_ENABLE_BIT     1
+#define PCI_PC6_ENABLE_BIT     2
+
+#define PCI_NBP1_STAT_OFFSET   0x98
+#define PCI_NBP1_ACTIVE_BIT    2
+#define PCI_NBP1_ENTERED_BIT   1
+
+#define PCI_NBP1_CAP_OFFSET    0x90
+#define PCI_NBP1_CAPABLE_BIT    31
+
+#define OVERFLOW_MS            343597 /* 32 bit register filled at 12500 HZ
+                                         (1 tick per 80ns) */
+
+enum amd_fam14h_states {NON_PC0 = 0, PC1, PC6, NBP1,
+                       AMD_FAM14H_STATE_NUM};
+
+static int fam14h_get_count_percent(unsigned int self_id, double *percent,
+                                   unsigned int cpu);
+static int fam14h_nbp1_count(unsigned int id, unsigned long long *count,
+                            unsigned int cpu);
+
+static cstate_t amd_fam14h_cstates[AMD_FAM14H_STATE_NUM] = {
+       {
+               .name                   = "!PC0",
+               .desc                   = N_("Package in sleep state (PC1 or deeper)"),
+               .id                     = NON_PC0,
+               .range                  = RANGE_PACKAGE,
+               .get_count_percent      = fam14h_get_count_percent,
+       },
+       {
+               .name                   = "PC1",
+               .desc                   = N_("Processor Package C1"),
+               .id                     = PC1,
+               .range                  = RANGE_PACKAGE,
+               .get_count_percent      = fam14h_get_count_percent,
+       },
+       {
+               .name                   = "PC6",
+               .desc                   = N_("Processor Package C6"),
+               .id                     = PC6,
+               .range                  = RANGE_PACKAGE,
+               .get_count_percent      = fam14h_get_count_percent,
+       },
+       {
+               .name                   = "NBP1",
+               .desc                   = N_("North Bridge P1 boolean counter (returns 0 or 1)"),
+               .id                     = NBP1,
+               .range                  = RANGE_PACKAGE,
+               .get_count              = fam14h_nbp1_count,
+       },
+};
+
+static struct pci_access *pci_acc;
+static int pci_vendor_id = 0x1022;
+static int pci_dev_ids[2] = {0x1716, 0};
+static struct pci_dev *amd_fam14h_pci_dev;
+
+static int nbp1_entered;
+
+struct timespec start_time;
+static unsigned long long timediff;
+
+#ifdef DEBUG
+struct timespec dbg_time;
+long dbg_timediff;
+#endif
+
+static unsigned long long *previous_count[AMD_FAM14H_STATE_NUM];
+static unsigned long long *current_count[AMD_FAM14H_STATE_NUM];
+
+static int amd_fam14h_get_pci_info(struct cstate *state,
+                                  unsigned int *pci_offset,
+                                  unsigned int *enable_bit,
+                                  unsigned int cpu)
+{
+       switch (state->id) {
+       case NON_PC0:
+               *enable_bit = PCI_NON_PC0_ENABLE_BIT;
+               *pci_offset = PCI_NON_PC0_OFFSET;
+               break;
+       case PC1:
+               *enable_bit = PCI_PC1_ENABLE_BIT;
+               *pci_offset = PCI_PC1_OFFSET;
+               break;
+       case PC6:
+               *enable_bit = PCI_PC6_ENABLE_BIT;
+               *pci_offset = PCI_PC6_OFFSET;
+               break;
+       case NBP1:
+               *enable_bit = PCI_NBP1_ENTERED_BIT;
+               *pci_offset = PCI_NBP1_STAT_OFFSET;
+               break;
+       default:
+               return -1;
+       };
+       return 0;
+}
+
+static int amd_fam14h_init(cstate_t *state, unsigned int cpu)
+{
+       int enable_bit, pci_offset, ret;
+       uint32_t val;
+
+       ret = amd_fam14h_get_pci_info(state, &pci_offset, &enable_bit, cpu);
+       if (ret)
+               return ret;
+
+       /* NBP1 needs extra treating -> write 1 to D18F6x98 bit 1 for init */
+       if (state->id == NBP1) {
+               val = pci_read_long(amd_fam14h_pci_dev, pci_offset);
+               val |= 1 << enable_bit;
+               val = pci_write_long(amd_fam14h_pci_dev, pci_offset, val);
+               return ret;
+       }
+
+       /* Enable monitor */
+       val = pci_read_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG);
+       dprint("Init %s: read at offset: 0x%x val: %u\n", state->name,
+              PCI_MONITOR_ENABLE_REG, (unsigned int) val);
+       val |= 1 << enable_bit;
+       pci_write_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG, val);
+
+       dprint("Init %s: offset: 0x%x enable_bit: %d - val: %u (%u)\n",
+              state->name, PCI_MONITOR_ENABLE_REG, enable_bit,
+              (unsigned int) val, cpu);
+
+       /* Set counter to zero */
+       pci_write_long(amd_fam14h_pci_dev, pci_offset, 0);
+       previous_count[state->id][cpu] = 0;
+
+       return 0;
+}
+
+static int amd_fam14h_disable(cstate_t *state, unsigned int cpu)
+{
+       int enable_bit, pci_offset, ret;
+       uint32_t val;
+
+       ret = amd_fam14h_get_pci_info(state, &pci_offset, &enable_bit, cpu);
+       if (ret)
+               return ret;
+
+       val = pci_read_long(amd_fam14h_pci_dev, pci_offset);
+       dprint("%s: offset: 0x%x %u\n", state->name, pci_offset, val);
+       if (state->id == NBP1) {
+               /* was the bit whether NBP1 got entered set? */
+               nbp1_entered = (val & (1 << PCI_NBP1_ACTIVE_BIT)) |
+                       (val & (1 << PCI_NBP1_ENTERED_BIT));
+
+               dprint("NBP1 was %sentered - 0x%x - enable_bit: "
+                      "%d - pci_offset: 0x%x\n",
+                      nbp1_entered ? "" : "not ",
+                      val, enable_bit, pci_offset);
+               return ret;
+       }
+       current_count[state->id][cpu] = val;
+
+       dprint("%s: Current -  %llu (%u)\n", state->name,
+              current_count[state->id][cpu], cpu);
+       dprint("%s: Previous - %llu (%u)\n", state->name,
+              previous_count[state->id][cpu], cpu);
+
+       val = pci_read_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG);
+       val &= ~(1 << enable_bit);
+       pci_write_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG, val);
+
+       return 0;
+}
+
+static int fam14h_nbp1_count(unsigned int id, unsigned long long *count,
+                            unsigned int cpu)
+{
+       if (id == NBP1) {
+               if (nbp1_entered)
+                       *count = 1;
+               else
+                       *count = 0;
+               return 0;
+       }
+       return -1;
+}
+static int fam14h_get_count_percent(unsigned int id, double *percent,
+                                   unsigned int cpu)
+{
+       unsigned long diff;
+
+       if (id >= AMD_FAM14H_STATE_NUM)
+               return -1;
+       /* residency count in 80ns -> divide through 12.5 to get us residency */
+       diff = current_count[id][cpu] - previous_count[id][cpu];
+
+       if (timediff == 0)
+               *percent = 0.0;
+       else
+               *percent = 100.0 * diff / timediff / 12.5;
+
+       dprint("Timediff: %llu - res~: %lu us - percent: %.2f %%\n",
+              timediff, diff * 10 / 125, *percent);
+
+       return 0;
+}
+
+static int amd_fam14h_start(void)
+{
+       int num, cpu;
+       clock_gettime(CLOCK_REALTIME, &start_time);
+       for (num = 0; num < AMD_FAM14H_STATE_NUM; num++) {
+               for (cpu = 0; cpu < cpu_count; cpu++)
+                       amd_fam14h_init(&amd_fam14h_cstates[num], cpu);
+       }
+#ifdef DEBUG
+       clock_gettime(CLOCK_REALTIME, &dbg_time);
+       dbg_timediff = timespec_diff_us(start_time, dbg_time);
+       dprint("Enabling counters took: %lu us\n",
+              dbg_timediff);
+#endif
+       return 0;
+}
+
+static int amd_fam14h_stop(void)
+{
+       int num, cpu;
+       struct timespec end_time;
+
+       clock_gettime(CLOCK_REALTIME, &end_time);
+
+       for (num = 0; num < AMD_FAM14H_STATE_NUM; num++) {
+               for (cpu = 0; cpu < cpu_count; cpu++)
+                       amd_fam14h_disable(&amd_fam14h_cstates[num], cpu);
+       }
+#ifdef DEBUG
+       clock_gettime(CLOCK_REALTIME, &dbg_time);
+       dbg_timediff = timespec_diff_us(end_time, dbg_time);
+       dprint("Disabling counters took: %lu ns\n", dbg_timediff);
+#endif
+       timediff = timespec_diff_us(start_time, end_time);
+       if (timediff / 1000 > OVERFLOW_MS)
+               print_overflow_err((unsigned int)timediff / 1000000,
+                                  OVERFLOW_MS / 1000);
+
+       return 0;
+}
+
+static int is_nbp1_capable(void)
+{
+       uint32_t val;
+       val = pci_read_long(amd_fam14h_pci_dev, PCI_NBP1_CAP_OFFSET);
+       return val & (1 << 31);
+}
+
+struct cpuidle_monitor *amd_fam14h_register(void)
+{
+       int num;
+
+       if (cpupower_cpu_info.vendor != X86_VENDOR_AMD)
+               return NULL;
+
+       if (cpupower_cpu_info.family == 0x14) {
+               if (cpu_count <= 0 || cpu_count > 2) {
+                       fprintf(stderr, "AMD fam14h: Invalid cpu count: %d\n",
+                               cpu_count);
+                       return NULL;
+               }
+       } else
+               return NULL;
+
+       /* We do not alloc for nbp1 machine wide counter */
+       for (num = 0; num < AMD_FAM14H_STATE_NUM - 1; num++) {
+               previous_count[num] = calloc(cpu_count,
+                                             sizeof(unsigned long long));
+               current_count[num]  = calloc(cpu_count,
+                                             sizeof(unsigned long long));
+       }
+
+       amd_fam14h_pci_dev = pci_acc_init(&pci_acc, pci_vendor_id, pci_dev_ids);
+       if (amd_fam14h_pci_dev == NULL || pci_acc == NULL)
+               return NULL;
+
+       if (!is_nbp1_capable())
+               amd_fam14h_monitor.hw_states_num = AMD_FAM14H_STATE_NUM - 1;
+
+       amd_fam14h_monitor.name_len = strlen(amd_fam14h_monitor.name);
+       return &amd_fam14h_monitor;
+}
+
+static void amd_fam14h_unregister(void)
+{
+       int num;
+       for (num = 0; num < AMD_FAM14H_STATE_NUM - 1; num++) {
+               free(previous_count[num]);
+               free(current_count[num]);
+       }
+       pci_cleanup(pci_acc);
+}
+
+struct cpuidle_monitor amd_fam14h_monitor = {
+       .name                   = "Ontario",
+       .hw_states              = amd_fam14h_cstates,
+       .hw_states_num          = AMD_FAM14H_STATE_NUM,
+       .start                  = amd_fam14h_start,
+       .stop                   = amd_fam14h_stop,
+       .do_register            = amd_fam14h_register,
+       .unregister             = amd_fam14h_unregister,
+       .needs_root             = 1,
+       .overflow_s             = OVERFLOW_MS / 1000,
+};
+#endif /* #if defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
new file mode 100644 (file)
index 0000000..d048b96
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+
+#include "helpers/sysfs.h"
+#include "helpers/helpers.h"
+#include "idle_monitor/cpupower-monitor.h"
+
+#define CPUIDLE_STATES_MAX 10
+static cstate_t cpuidle_cstates[CPUIDLE_STATES_MAX];
+struct cpuidle_monitor cpuidle_sysfs_monitor;
+
+static unsigned long long **previous_count;
+static unsigned long long **current_count;
+struct timespec start_time;
+static unsigned long long timediff;
+
+static int cpuidle_get_count_percent(unsigned int id, double *percent,
+                                    unsigned int cpu)
+{
+       unsigned long long statediff = current_count[cpu][id]
+               - previous_count[cpu][id];
+       dprint("%s: - diff: %llu - percent: %f (%u)\n",
+              cpuidle_cstates[id].name, timediff, *percent, cpu);
+
+       if (timediff == 0)
+               *percent = 0.0;
+       else
+               *percent = ((100.0 * statediff) / timediff);
+
+       dprint("%s: - timediff: %llu - statediff: %llu - percent: %f (%u)\n",
+              cpuidle_cstates[id].name, timediff, statediff, *percent, cpu);
+
+       return 0;
+}
+
+static int cpuidle_start(void)
+{
+       int cpu, state;
+       clock_gettime(CLOCK_REALTIME, &start_time);
+       for (cpu = 0; cpu < cpu_count; cpu++) {
+               for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
+                    state++) {
+                       previous_count[cpu][state] =
+                               sysfs_get_idlestate_time(cpu, state);
+                       dprint("CPU %d - State: %d - Val: %llu\n",
+                              cpu, state, previous_count[cpu][state]);
+               }
+       };
+       return 0;
+}
+
+static int cpuidle_stop(void)
+{
+       int cpu, state;
+       struct timespec end_time;
+       clock_gettime(CLOCK_REALTIME, &end_time);
+       timediff = timespec_diff_us(start_time, end_time);
+
+       for (cpu = 0; cpu < cpu_count; cpu++) {
+               for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
+                    state++) {
+                       current_count[cpu][state] =
+                               sysfs_get_idlestate_time(cpu, state);
+                       dprint("CPU %d - State: %d - Val: %llu\n",
+                              cpu, state, previous_count[cpu][state]);
+               }
+       };
+       return 0;
+}
+
+void fix_up_intel_idle_driver_name(char *tmp, int num)
+{
+       /* fix up cpuidle name for intel idle driver */
+       if (!strncmp(tmp, "NHM-", 4)) {
+               switch (num) {
+               case 1:
+                       strcpy(tmp, "C1");
+                       break;
+               case 2:
+                       strcpy(tmp, "C3");
+                       break;
+               case 3:
+                       strcpy(tmp, "C6");
+                       break;
+               }
+       } else if (!strncmp(tmp, "SNB-", 4)) {
+               switch (num) {
+               case 1:
+                       strcpy(tmp, "C1");
+                       break;
+               case 2:
+                       strcpy(tmp, "C3");
+                       break;
+               case 3:
+                       strcpy(tmp, "C6");
+                       break;
+               case 4:
+                       strcpy(tmp, "C7");
+                       break;
+               }
+       } else if (!strncmp(tmp, "ATM-", 4)) {
+               switch (num) {
+               case 1:
+                       strcpy(tmp, "C1");
+                       break;
+               case 2:
+                       strcpy(tmp, "C2");
+                       break;
+               case 3:
+                       strcpy(tmp, "C4");
+                       break;
+               case 4:
+                       strcpy(tmp, "C6");
+                       break;
+               }
+       }
+}
+
+static struct cpuidle_monitor *cpuidle_register(void)
+{
+       int num;
+       char *tmp;
+
+       /* Assume idle state count is the same for all CPUs */
+       cpuidle_sysfs_monitor.hw_states_num = sysfs_get_idlestate_count(0);
+
+       if (cpuidle_sysfs_monitor.hw_states_num == 0)
+               return NULL;
+
+       for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {
+               tmp = sysfs_get_idlestate_name(0, num);
+               if (tmp == NULL)
+                       continue;
+
+               fix_up_intel_idle_driver_name(tmp, num);
+               strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);
+               free(tmp);
+
+               tmp = sysfs_get_idlestate_desc(0, num);
+               if (tmp == NULL)
+                       continue;
+               strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1);
+               free(tmp);
+
+               cpuidle_cstates[num].range = RANGE_THREAD;
+               cpuidle_cstates[num].id = num;
+               cpuidle_cstates[num].get_count_percent =
+                       cpuidle_get_count_percent;
+       };
+
+       /* Free this at program termination */
+       previous_count = malloc(sizeof(long long *) * cpu_count);
+       current_count = malloc(sizeof(long long *) * cpu_count);
+       for (num = 0; num < cpu_count; num++) {
+               previous_count[num] = malloc(sizeof(long long) *
+                                       cpuidle_sysfs_monitor.hw_states_num);
+               current_count[num] = malloc(sizeof(long long) *
+                                       cpuidle_sysfs_monitor.hw_states_num);
+       }
+
+       cpuidle_sysfs_monitor.name_len = strlen(cpuidle_sysfs_monitor.name);
+       return &cpuidle_sysfs_monitor;
+}
+
+void cpuidle_unregister(void)
+{
+       int num;
+
+       for (num = 0; num < cpu_count; num++) {
+               free(previous_count[num]);
+               free(current_count[num]);
+       }
+       free(previous_count);
+       free(current_count);
+}
+
+struct cpuidle_monitor cpuidle_sysfs_monitor = {
+       .name                   = "Idle_Stats",
+       .hw_states              = cpuidle_cstates,
+       .start                  = cpuidle_start,
+       .stop                   = cpuidle_stop,
+       .do_register            = cpuidle_register,
+       .unregister             = cpuidle_unregister,
+       .needs_root             = 0,
+       .overflow_s             = UINT_MAX,
+};
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
new file mode 100644 (file)
index 0000000..ba4bf06
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ *  Output format inspired by Len Brown's <lenb@kernel.org> turbostat tool.
+ *
+ */
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <libgen.h>
+
+#include "idle_monitor/cpupower-monitor.h"
+#include "idle_monitor/idle_monitors.h"
+#include "helpers/helpers.h"
+
+/* Define pointers to all monitors.  */
+#define DEF(x) & x ## _monitor ,
+struct cpuidle_monitor *all_monitors[] = {
+#include "idle_monitors.def"
+0
+};
+
+static struct cpuidle_monitor *monitors[MONITORS_MAX];
+static unsigned int avail_monitors;
+
+static char *progname;
+
+enum operation_mode_e { list = 1, show, show_all };
+static int mode;
+static int interval = 1;
+static char *show_monitors_param;
+static struct cpupower_topology cpu_top;
+
+/* ToDo: Document this in the manpage */
+static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', };
+
+long long timespec_diff_us(struct timespec start, struct timespec end)
+{
+       struct timespec temp;
+       if ((end.tv_nsec - start.tv_nsec) < 0) {
+               temp.tv_sec = end.tv_sec - start.tv_sec - 1;
+               temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
+       } else {
+               temp.tv_sec = end.tv_sec - start.tv_sec;
+               temp.tv_nsec = end.tv_nsec - start.tv_nsec;
+       }
+       return (temp.tv_sec * 1000000) + (temp.tv_nsec / 1000);
+}
+
+void monitor_help(void)
+{
+       printf(_("cpupower monitor: [-m <mon1>,[<mon2>],.. ] command\n"));
+       printf(_("cpupower monitor: [-m <mon1>,[<mon2>],.. ] [ -i interval_sec ]\n"));
+       printf(_("cpupower monitor: -l\n"));
+       printf(_("\t command: pass an arbitrary command to measure specific workload\n"));
+       printf(_("\t -i: time intervall to measure for in seconds (default 1)\n"));
+       printf(_("\t -l: list available CPU sleep monitors (for use with -m)\n"));
+       printf(_("\t -m: show specific CPU sleep monitors only (in same order)\n"));
+       printf(_("\t -h: print this help\n"));
+       printf("\n");
+       printf(_("only one of: -l, -m are allowed\nIf none of them is passed,"));
+       printf(_(" all supported monitors are shown\n"));
+}
+
+void print_n_spaces(int n)
+{
+       int x;
+       for (x = 0; x < n; x++)
+               printf(" ");
+}
+
+/* size of s must be at least n + 1 */
+int fill_string_with_spaces(char *s, int n)
+{
+       int len = strlen(s);
+       if (len > n)
+               return -1;
+       for (; len < n; len++)
+               s[len] = ' ';
+       s[len] = '\0';
+       return 0;
+}
+
+void print_header(int topology_depth)
+{
+       int unsigned mon;
+       int state, need_len, pr_mon_len;
+       cstate_t s;
+       char buf[128] = "";
+       int percent_width = 4;
+
+       fill_string_with_spaces(buf, topology_depth * 5 - 1);
+       printf("%s|", buf);
+
+       for (mon = 0; mon < avail_monitors; mon++) {
+               pr_mon_len = 0;
+               need_len = monitors[mon]->hw_states_num * (percent_width + 3)
+                       - 1;
+               if (mon != 0) {
+                       printf("|| ");
+                       need_len--;
+               }
+               sprintf(buf, "%s", monitors[mon]->name);
+               fill_string_with_spaces(buf, need_len);
+               printf("%s", buf);
+       }
+       printf("\n");
+
+       if (topology_depth > 2)
+               printf("PKG |");
+       if (topology_depth > 1)
+               printf("CORE|");
+       if (topology_depth > 0)
+               printf("CPU |");
+
+       for (mon = 0; mon < avail_monitors; mon++) {
+               if (mon != 0)
+                       printf("|| ");
+               else
+                       printf(" ");
+               for (state = 0; state < monitors[mon]->hw_states_num; state++) {
+                       if (state != 0)
+                               printf(" | ");
+                       s = monitors[mon]->hw_states[state];
+                       sprintf(buf, "%s", s.name);
+                       fill_string_with_spaces(buf, percent_width);
+                       printf("%s", buf);
+               }
+               printf(" ");
+       }
+       printf("\n");
+}
+
+
+void print_results(int topology_depth, int cpu)
+{
+       unsigned int mon;
+       int state, ret;
+       double percent;
+       unsigned long long result;
+       cstate_t s;
+
+       if (topology_depth > 2)
+               printf("%4d|", cpu_top.core_info[cpu].pkg);
+       if (topology_depth > 1)
+               printf("%4d|", cpu_top.core_info[cpu].core);
+       if (topology_depth > 0)
+               printf("%4d|", cpu_top.core_info[cpu].cpu);
+
+       for (mon = 0; mon < avail_monitors; mon++) {
+               if (mon != 0)
+                       printf("||");
+
+               for (state = 0; state < monitors[mon]->hw_states_num; state++) {
+                       if (state != 0)
+                               printf("|");
+
+                       s = monitors[mon]->hw_states[state];
+
+                       if (s.get_count_percent) {
+                               ret = s.get_count_percent(s.id, &percent,
+                                                 cpu_top.core_info[cpu].cpu);
+                               if (ret)
+                                       printf("******");
+                               else if (percent >= 100.0)
+                                       printf("%6.1f", percent);
+                               else
+                                       printf("%6.2f", percent);
+                       } else if (s.get_count) {
+                               ret = s.get_count(s.id, &result,
+                                                 cpu_top.core_info[cpu].cpu);
+                               if (ret)
+                                       printf("******");
+                               else
+                                       printf("%6llu", result);
+                       } else {
+                               printf(_("Monitor %s, Counter %s has no count "
+                                        "function. Implementation error\n"),
+                                      monitors[mon]->name, s.name);
+                               exit(EXIT_FAILURE);
+                       }
+               }
+       }
+       /* cpu offline */
+       if (cpu_top.core_info[cpu].pkg == -1 ||
+           cpu_top.core_info[cpu].core == -1) {
+               printf(_(" *is offline\n"));
+               return;
+       } else
+               printf("\n");
+}
+
+
+/* param: string passed by -m param (The list of monitors to show)
+ *
+ * Monitors must have been registered already, matching monitors
+ * are picked out and available monitors array is overridden
+ * with matching ones
+ *
+ * Monitors get sorted in the same order the user passes them
+*/
+
+static void parse_monitor_param(char *param)
+{
+       unsigned int num;
+       int mon, hits = 0;
+       char *tmp = param, *token;
+       struct cpuidle_monitor *tmp_mons[MONITORS_MAX];
+
+
+       for (mon = 0; mon < MONITORS_MAX; mon++, tmp = NULL) {
+               token = strtok(tmp, ",");
+               if (token == NULL)
+                       break;
+               if (strlen(token) >= MONITOR_NAME_LEN) {
+                       printf(_("%s: max monitor name length"
+                                " (%d) exceeded\n"), token, MONITOR_NAME_LEN);
+                       continue;
+               }
+
+               for (num = 0; num < avail_monitors; num++) {
+                       if (!strcmp(monitors[num]->name, token)) {
+                               dprint("Found requested monitor: %s\n", token);
+                               tmp_mons[hits] = monitors[num];
+                               hits++;
+                       }
+               }
+       }
+       if (hits == 0) {
+               printf(_("No matching monitor found in %s, "
+                        "try -l option\n"), param);
+               monitor_help();
+               exit(EXIT_FAILURE);
+       }
+       /* Override detected/registerd monitors array with requested one */
+       memcpy(monitors, tmp_mons,
+               sizeof(struct cpuidle_monitor *) * MONITORS_MAX);
+       avail_monitors = hits;
+}
+
+void list_monitors(void)
+{
+       unsigned int mon;
+       int state;
+       cstate_t s;
+
+       for (mon = 0; mon < avail_monitors; mon++) {
+               printf(_("Monitor \"%s\" (%d states) - Might overflow after %u "
+                        "s\n"),
+                       monitors[mon]->name, monitors[mon]->hw_states_num,
+                       monitors[mon]->overflow_s);
+
+               for (state = 0; state < monitors[mon]->hw_states_num; state++) {
+                       s = monitors[mon]->hw_states[state];
+                       /*
+                        * ToDo show more state capabilities:
+                        * percent, time (granlarity)
+                        */
+                       printf("%s\t[%c] -> %s\n", s.name, range_abbr[s.range],
+                              gettext(s.desc));
+               }
+       }
+}
+
+int fork_it(char **argv)
+{
+       int status;
+       unsigned int num;
+       unsigned long long timediff;
+       pid_t child_pid;
+       struct timespec start, end;
+
+       child_pid = fork();
+       clock_gettime(CLOCK_REALTIME, &start);
+
+       for (num = 0; num < avail_monitors; num++)
+               monitors[num]->start();
+
+       if (!child_pid) {
+               /* child */
+               execvp(argv[0], argv);
+       } else {
+               /* parent */
+               if (child_pid == -1) {
+                       perror("fork");
+                       exit(1);
+               }
+
+               signal(SIGINT, SIG_IGN);
+               signal(SIGQUIT, SIG_IGN);
+               if (waitpid(child_pid, &status, 0) == -1) {
+                       perror("wait");
+                       exit(1);
+               }
+       }
+       clock_gettime(CLOCK_REALTIME, &end);
+       for (num = 0; num < avail_monitors; num++)
+               monitors[num]->stop();
+
+       timediff = timespec_diff_us(start, end);
+       if (WIFEXITED(status))
+               printf(_("%s took %.5f seconds and exited with status %d\n"),
+                       argv[0], timediff / (1000.0 * 1000),
+                       WEXITSTATUS(status));
+       return 0;
+}
+
+int do_interval_measure(int i)
+{
+       unsigned int num;
+
+       for (num = 0; num < avail_monitors; num++) {
+               dprint("HW C-state residency monitor: %s - States: %d\n",
+                      monitors[num]->name, monitors[num]->hw_states_num);
+               monitors[num]->start();
+       }
+       sleep(i);
+       for (num = 0; num < avail_monitors; num++)
+               monitors[num]->stop();
+
+       return 0;
+}
+
+static void cmdline(int argc, char *argv[])
+{
+       int opt;
+       progname = basename(argv[0]);
+
+       while ((opt = getopt(argc, argv, "+hli:m:")) != -1) {
+               switch (opt) {
+               case 'h':
+                       monitor_help();
+                       exit(EXIT_SUCCESS);
+               case 'l':
+                       if (mode) {
+                               monitor_help();
+                               exit(EXIT_FAILURE);
+                       }
+                       mode = list;
+                       break;
+               case 'i':
+                       /* only allow -i with -m or no option */
+                       if (mode && mode != show) {
+                               monitor_help();
+                               exit(EXIT_FAILURE);
+                       }
+                       interval = atoi(optarg);
+                       break;
+               case 'm':
+                       if (mode) {
+                               monitor_help();
+                               exit(EXIT_FAILURE);
+                       }
+                       mode = show;
+                       show_monitors_param = optarg;
+                       break;
+               default:
+                       monitor_help();
+                       exit(EXIT_FAILURE);
+               }
+       }
+       if (!mode)
+               mode = show_all;
+}
+
+int cmd_monitor(int argc, char **argv)
+{
+       unsigned int num;
+       struct cpuidle_monitor *test_mon;
+       int cpu;
+
+       cmdline(argc, argv);
+       cpu_count = get_cpu_topology(&cpu_top);
+       if (cpu_count < 0) {
+               printf(_("Cannot read number of available processors\n"));
+               return EXIT_FAILURE;
+       }
+
+       dprint("System has up to %d CPU cores\n", cpu_count);
+
+       for (num = 0; all_monitors[num]; num++) {
+               dprint("Try to register: %s\n", all_monitors[num]->name);
+               test_mon = all_monitors[num]->do_register();
+               if (test_mon) {
+                       if (test_mon->needs_root && !run_as_root) {
+                               fprintf(stderr, _("Available monitor %s needs "
+                                         "root access\n"), test_mon->name);
+                               continue;
+                       }
+                       monitors[avail_monitors] = test_mon;
+                       dprint("%s registered\n", all_monitors[num]->name);
+                       avail_monitors++;
+               }
+       }
+
+       if (avail_monitors == 0) {
+               printf(_("No HW Cstate monitors found\n"));
+               return 1;
+       }
+
+       if (mode == list) {
+               list_monitors();
+               exit(EXIT_SUCCESS);
+       }
+
+       if (mode == show)
+               parse_monitor_param(show_monitors_param);
+
+       dprint("Packages: %d - Cores: %d - CPUs: %d\n",
+              cpu_top.pkgs, cpu_top.cores, cpu_count);
+
+       /*
+        * if any params left, it must be a command to fork
+        */
+       if (argc - optind)
+               fork_it(argv + optind);
+       else
+               do_interval_measure(interval);
+
+       /* ToDo: Topology parsing needs fixing first to do
+          this more generically */
+       if (cpu_top.pkgs > 1)
+               print_header(3);
+       else
+               print_header(1);
+
+       for (cpu = 0; cpu < cpu_count; cpu++) {
+               if (cpu_top.pkgs > 1)
+                       print_results(3, cpu);
+               else
+                       print_results(1, cpu);
+       }
+
+       for (num = 0; num < avail_monitors; num++)
+               monitors[num]->unregister();
+
+       cpu_topology_release(cpu_top);
+       return 0;
+}
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
new file mode 100644 (file)
index 0000000..9312ee1
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ */
+
+#ifndef __CPUIDLE_INFO_HW__
+#define __CPUIDLE_INFO_HW__
+
+#include <stdarg.h>
+#include <time.h>
+
+#include "idle_monitor/idle_monitors.h"
+
+#define MONITORS_MAX 20
+#define MONITOR_NAME_LEN 20
+#define CSTATE_NAME_LEN 5
+#define CSTATE_DESC_LEN 60
+
+int cpu_count;
+
+/* Hard to define the right names ...: */
+enum power_range_e {
+       RANGE_THREAD,   /* Lowest in topology hierarcy, AMD: core, Intel: thread
+                          kernel sysfs: cpu */
+       RANGE_CORE,     /* AMD: unit, Intel: core, kernel_sysfs: core_id */
+       RANGE_PACKAGE,  /* Package, processor socket */
+       RANGE_MACHINE,  /* Machine, platform wide */
+       RANGE_MAX };
+
+typedef struct cstate {
+       int  id;
+       enum power_range_e range;
+       char name[CSTATE_NAME_LEN];
+       char desc[CSTATE_DESC_LEN];
+
+       /* either provide a percentage or a general count */
+       int (*get_count_percent)(unsigned int self_id, double *percent,
+                                unsigned int cpu);
+       int (*get_count)(unsigned int self_id, unsigned long long *count,
+                        unsigned int cpu);
+} cstate_t;
+
+struct cpuidle_monitor {
+       /* Name must not contain whitespaces */
+       char name[MONITOR_NAME_LEN];
+       int name_len;
+       int hw_states_num;
+       cstate_t *hw_states;
+       int (*start) (void);
+       int (*stop) (void);
+       struct cpuidle_monitor* (*do_register) (void);
+       void (*unregister)(void);
+       unsigned int overflow_s;
+       int needs_root;
+};
+
+extern long long timespec_diff_us(struct timespec start, struct timespec end);
+
+#define print_overflow_err(mes, ov)                                            \
+{                                                                              \
+       fprintf(stderr, gettext("Measure took %u seconds, but registers could " \
+                               "overflow at %u seconds, results "              \
+                               "could be inaccurate\n"), mes, ov);             \
+}
+
+#endif /* __CPUIDLE_INFO_HW__ */
diff --git a/tools/power/cpupower/utils/idle_monitor/idle_monitors.def b/tools/power/cpupower/utils/idle_monitor/idle_monitors.def
new file mode 100644 (file)
index 0000000..e3f8d9b
--- /dev/null
@@ -0,0 +1,7 @@
+#if defined(__i386__) || defined(__x86_64__)
+DEF(amd_fam14h)
+DEF(intel_nhm)
+DEF(intel_snb)
+DEF(mperf)
+#endif
+DEF(cpuidle_sysfs)
diff --git a/tools/power/cpupower/utils/idle_monitor/idle_monitors.h b/tools/power/cpupower/utils/idle_monitor/idle_monitors.h
new file mode 100644 (file)
index 0000000..4fcdeb1
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ *  Based on the idea from Michael Matz <matz@suse.de>
+ *
+ */
+
+#ifndef _CPUIDLE_IDLE_MONITORS_H_
+#define _CPUIDLE_IDLE_MONITORS_H_
+
+#define DEF(x) extern struct cpuidle_monitor x ##_monitor;
+#include "idle_monitors.def"
+#undef DEF
+extern struct cpuidle_monitor *all_monitors[];
+
+#endif /* _CPUIDLE_IDLE_MONITORS_H_ */
diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
new file mode 100644 (file)
index 0000000..63ca87a
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include <cpufreq.h>
+
+#include "helpers/helpers.h"
+#include "idle_monitor/cpupower-monitor.h"
+
+#define MSR_APERF      0xE8
+#define MSR_MPERF      0xE7
+
+#define MSR_TSC        0x10
+
+enum mperf_id { C0 = 0, Cx, AVG_FREQ, MPERF_CSTATE_COUNT };
+
+static int mperf_get_count_percent(unsigned int self_id, double *percent,
+                                  unsigned int cpu);
+static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
+                               unsigned int cpu);
+
+static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = {
+       {
+               .name                   = "C0",
+               .desc                   = N_("Processor Core not idle"),
+               .id                     = C0,
+               .range                  = RANGE_THREAD,
+               .get_count_percent      = mperf_get_count_percent,
+       },
+       {
+               .name                   = "Cx",
+               .desc                   = N_("Processor Core in an idle state"),
+               .id                     = Cx,
+               .range                  = RANGE_THREAD,
+               .get_count_percent      = mperf_get_count_percent,
+       },
+
+       {
+               .name                   = "Freq",
+               .desc                   = N_("Average Frequency (including boost) in MHz"),
+               .id                     = AVG_FREQ,
+               .range                  = RANGE_THREAD,
+               .get_count              = mperf_get_count_freq,
+       },
+};
+
+static unsigned long long tsc_at_measure_start;
+static unsigned long long tsc_at_measure_end;
+static unsigned long max_frequency;
+static unsigned long long *mperf_previous_count;
+static unsigned long long *aperf_previous_count;
+static unsigned long long *mperf_current_count;
+static unsigned long long *aperf_current_count;
+/* valid flag for all CPUs. If a MSR read failed it will be zero */
+static int *is_valid;
+
+static int mperf_get_tsc(unsigned long long *tsc)
+{
+       return read_msr(0, MSR_TSC, tsc);
+}
+
+static int mperf_init_stats(unsigned int cpu)
+{
+       unsigned long long val;
+       int ret;
+
+       ret = read_msr(cpu, MSR_APERF, &val);
+       aperf_previous_count[cpu] = val;
+       ret |= read_msr(cpu, MSR_MPERF, &val);
+       mperf_previous_count[cpu] = val;
+       is_valid[cpu] = !ret;
+
+       return 0;
+}
+
+static int mperf_measure_stats(unsigned int cpu)
+{
+       unsigned long long val;
+       int ret;
+
+       ret = read_msr(cpu, MSR_APERF, &val);
+       aperf_current_count[cpu] = val;
+       ret |= read_msr(cpu, MSR_MPERF, &val);
+       mperf_current_count[cpu] = val;
+       is_valid[cpu] = !ret;
+
+       return 0;
+}
+
+/*
+ * get_average_perf()
+ *
+ * Returns the average performance (also considers boosted frequencies)
+ *
+ * Input:
+ *   aperf_diff: Difference of the aperf register over a time period
+ *   mperf_diff: Difference of the mperf register over the same time period
+ *   max_freq:   Maximum frequency (P0)
+ *
+ * Returns:
+ *   Average performance over the time period
+ */
+static unsigned long get_average_perf(unsigned long long aperf_diff,
+                                     unsigned long long mperf_diff)
+{
+       unsigned int perf_percent = 0;
+       if (((unsigned long)(-1) / 100) < aperf_diff) {
+               int shift_count = 7;
+               aperf_diff >>= shift_count;
+               mperf_diff >>= shift_count;
+       }
+       perf_percent = (aperf_diff * 100) / mperf_diff;
+       return (max_frequency * perf_percent) / 100;
+}
+
+static int mperf_get_count_percent(unsigned int id, double *percent,
+                                  unsigned int cpu)
+{
+       unsigned long long aperf_diff, mperf_diff, tsc_diff;
+
+       if (!is_valid[cpu])
+               return -1;
+
+       if (id != C0 && id != Cx)
+               return -1;
+
+       mperf_diff = mperf_current_count[cpu] - mperf_previous_count[cpu];
+       aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];
+       tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
+
+       *percent = 100.0 * mperf_diff / tsc_diff;
+       dprint("%s: mperf_diff: %llu, tsc_diff: %llu\n",
+              mperf_cstates[id].name, mperf_diff, tsc_diff);
+
+       if (id == Cx)
+               *percent = 100.0 - *percent;
+
+       dprint("%s: previous: %llu - current: %llu - (%u)\n",
+               mperf_cstates[id].name, mperf_diff, aperf_diff, cpu);
+       dprint("%s: %f\n", mperf_cstates[id].name, *percent);
+       return 0;
+}
+
+static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
+                               unsigned int cpu)
+{
+       unsigned long long aperf_diff, mperf_diff;
+
+       if (id != AVG_FREQ)
+               return 1;
+
+       if (!is_valid[cpu])
+               return -1;
+
+       mperf_diff = mperf_current_count[cpu] - mperf_previous_count[cpu];
+       aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];
+
+       /* Return MHz for now, might want to return KHz if column width is more
+          generic */
+       *count = get_average_perf(aperf_diff, mperf_diff) / 1000;
+       dprint("%s: %llu\n", mperf_cstates[id].name, *count);
+
+       return 0;
+}
+
+static int mperf_start(void)
+{
+       int cpu;
+       unsigned long long dbg;
+
+       mperf_get_tsc(&tsc_at_measure_start);
+
+       for (cpu = 0; cpu < cpu_count; cpu++)
+               mperf_init_stats(cpu);
+
+       mperf_get_tsc(&dbg);
+       dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start);
+       return 0;
+}
+
+static int mperf_stop(void)
+{
+       unsigned long long dbg;
+       int cpu;
+
+       mperf_get_tsc(&tsc_at_measure_end);
+
+       for (cpu = 0; cpu < cpu_count; cpu++)
+               mperf_measure_stats(cpu);
+
+       mperf_get_tsc(&dbg);
+       dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);
+
+       return 0;
+}
+
+struct cpuidle_monitor mperf_monitor;
+
+struct cpuidle_monitor *mperf_register(void)
+{
+       unsigned long min;
+
+       if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_APERF))
+               return NULL;
+
+       /* Assume min/max all the same on all cores */
+       if (cpufreq_get_hardware_limits(0, &min, &max_frequency)) {
+               dprint("Cannot retrieve max freq from cpufreq kernel "
+                      "subsystem\n");
+               return NULL;
+       }
+
+       /* Free this at program termination */
+       is_valid = calloc(cpu_count, sizeof(int));
+       mperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
+       aperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
+       mperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
+       aperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
+
+       mperf_monitor.name_len = strlen(mperf_monitor.name);
+       return &mperf_monitor;
+}
+
+void mperf_unregister(void)
+{
+       free(mperf_previous_count);
+       free(aperf_previous_count);
+       free(mperf_current_count);
+       free(aperf_current_count);
+       free(is_valid);
+}
+
+struct cpuidle_monitor mperf_monitor = {
+       .name                   = "Mperf",
+       .hw_states_num          = MPERF_CSTATE_COUNT,
+       .hw_states              = mperf_cstates,
+       .start                  = mperf_start,
+       .stop                   = mperf_stop,
+       .do_register            = mperf_register,
+       .unregister             = mperf_unregister,
+       .needs_root             = 1,
+       .overflow_s             = 922000000 /* 922337203 seconds TSC overflow
+                                              at 20GHz */
+};
+#endif /* #if defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/idle_monitor/nhm_idle.c b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
new file mode 100644 (file)
index 0000000..d2a91dd
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ *  Based on Len Brown's <lenb@kernel.org> turbostat tool.
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "helpers/helpers.h"
+#include "idle_monitor/cpupower-monitor.h"
+
+#define MSR_PKG_C3_RESIDENCY   0x3F8
+#define MSR_PKG_C6_RESIDENCY   0x3F9
+#define MSR_CORE_C3_RESIDENCY  0x3FC
+#define MSR_CORE_C6_RESIDENCY  0x3FD
+
+#define MSR_TSC        0x10
+
+#define NHM_CSTATE_COUNT 4
+
+enum intel_nhm_id { C3 = 0, C6, PC3, PC6, TSC = 0xFFFF };
+
+static int nhm_get_count_percent(unsigned int self_id, double *percent,
+                                unsigned int cpu);
+
+static cstate_t nhm_cstates[NHM_CSTATE_COUNT] = {
+       {
+               .name                   = "C3",
+               .desc                   = N_("Processor Core C3"),
+               .id                     = C3,
+               .range                  = RANGE_CORE,
+               .get_count_percent      = nhm_get_count_percent,
+       },
+       {
+               .name                   = "C6",
+               .desc                   = N_("Processor Core C6"),
+               .id                     = C6,
+               .range                  = RANGE_CORE,
+               .get_count_percent      = nhm_get_count_percent,
+       },
+
+       {
+               .name                   = "PC3",
+               .desc                   = N_("Processor Package C3"),
+               .id                     = PC3,
+               .range                  = RANGE_PACKAGE,
+               .get_count_percent      = nhm_get_count_percent,
+       },
+       {
+               .name                   = "PC6",
+               .desc                   = N_("Processor Package C6"),
+               .id                     = PC6,
+               .range                  = RANGE_PACKAGE,
+               .get_count_percent      = nhm_get_count_percent,
+       },
+};
+
+static unsigned long long tsc_at_measure_start;
+static unsigned long long tsc_at_measure_end;
+static unsigned long long *previous_count[NHM_CSTATE_COUNT];
+static unsigned long long *current_count[NHM_CSTATE_COUNT];
+/* valid flag for all CPUs. If a MSR read failed it will be zero */
+static int *is_valid;
+
+static int nhm_get_count(enum intel_nhm_id id, unsigned long long *val,
+                       unsigned int cpu)
+{
+       int msr;
+
+       switch (id) {
+       case C3:
+               msr = MSR_CORE_C3_RESIDENCY;
+               break;
+       case C6:
+               msr = MSR_CORE_C6_RESIDENCY;
+               break;
+       case PC3:
+               msr = MSR_PKG_C3_RESIDENCY;
+               break;
+       case PC6:
+               msr = MSR_PKG_C6_RESIDENCY;
+               break;
+       case TSC:
+               msr = MSR_TSC;
+               break;
+       default:
+               return -1;
+       };
+       if (read_msr(cpu, msr, val))
+               return -1;
+
+       return 0;
+}
+
+static int nhm_get_count_percent(unsigned int id, double *percent,
+                                unsigned int cpu)
+{
+       *percent = 0.0;
+
+       if (!is_valid[cpu])
+               return -1;
+
+       *percent = (100.0 *
+               (current_count[id][cpu] - previous_count[id][cpu])) /
+               (tsc_at_measure_end - tsc_at_measure_start);
+
+       dprint("%s: previous: %llu - current: %llu - (%u)\n",
+               nhm_cstates[id].name, previous_count[id][cpu],
+               current_count[id][cpu], cpu);
+
+       dprint("%s: tsc_diff: %llu - count_diff: %llu - percent: %2.f (%u)\n",
+              nhm_cstates[id].name,
+              (unsigned long long) tsc_at_measure_end - tsc_at_measure_start,
+              current_count[id][cpu] - previous_count[id][cpu],
+              *percent, cpu);
+
+       return 0;
+}
+
+static int nhm_start(void)
+{
+       int num, cpu;
+       unsigned long long dbg, val;
+
+       nhm_get_count(TSC, &tsc_at_measure_start, 0);
+
+       for (num = 0; num < NHM_CSTATE_COUNT; num++) {
+               for (cpu = 0; cpu < cpu_count; cpu++) {
+                       is_valid[cpu] = !nhm_get_count(num, &val, cpu);
+                       previous_count[num][cpu] = val;
+               }
+       }
+       nhm_get_count(TSC, &dbg, 0);
+       dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start);
+       return 0;
+}
+
+static int nhm_stop(void)
+{
+       unsigned long long val;
+       unsigned long long dbg;
+       int num, cpu;
+
+       nhm_get_count(TSC, &tsc_at_measure_end, 0);
+
+       for (num = 0; num < NHM_CSTATE_COUNT; num++) {
+               for (cpu = 0; cpu < cpu_count; cpu++) {
+                       is_valid[cpu] = !nhm_get_count(num, &val, cpu);
+                       current_count[num][cpu] = val;
+               }
+       }
+       nhm_get_count(TSC, &dbg, 0);
+       dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);
+
+       return 0;
+}
+
+struct cpuidle_monitor intel_nhm_monitor;
+
+struct cpuidle_monitor *intel_nhm_register(void)
+{
+       int num;
+
+       if (cpupower_cpu_info.vendor != X86_VENDOR_INTEL)
+               return NULL;
+
+       if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_INV_TSC))
+               return NULL;
+
+       if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_APERF))
+               return NULL;
+
+       /* Free this at program termination */
+       is_valid = calloc(cpu_count, sizeof(int));
+       for (num = 0; num < NHM_CSTATE_COUNT; num++) {
+               previous_count[num] = calloc(cpu_count,
+                                       sizeof(unsigned long long));
+               current_count[num]  = calloc(cpu_count,
+                                       sizeof(unsigned long long));
+       }
+
+       intel_nhm_monitor.name_len = strlen(intel_nhm_monitor.name);
+       return &intel_nhm_monitor;
+}
+
+void intel_nhm_unregister(void)
+{
+       int num;
+
+       for (num = 0; num < NHM_CSTATE_COUNT; num++) {
+               free(previous_count[num]);
+               free(current_count[num]);
+       }
+       free(is_valid);
+}
+
+struct cpuidle_monitor intel_nhm_monitor = {
+       .name                   = "Nehalem",
+       .hw_states_num          = NHM_CSTATE_COUNT,
+       .hw_states              = nhm_cstates,
+       .start                  = nhm_start,
+       .stop                   = nhm_stop,
+       .do_register            = intel_nhm_register,
+       .unregister             = intel_nhm_unregister,
+       .needs_root             = 1,
+       .overflow_s             = 922000000 /* 922337203 seconds TSC overflow
+                                              at 20GHz */
+};
+#endif
diff --git a/tools/power/cpupower/utils/idle_monitor/snb_idle.c b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
new file mode 100644 (file)
index 0000000..a1bc07c
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ *  Based on Len Brown's <lenb@kernel.org> turbostat tool.
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "helpers/helpers.h"
+#include "idle_monitor/cpupower-monitor.h"
+
+#define MSR_PKG_C2_RESIDENCY   0x60D
+#define MSR_PKG_C7_RESIDENCY   0x3FA
+#define MSR_CORE_C7_RESIDENCY  0x3FE
+
+#define MSR_TSC        0x10
+
+enum intel_snb_id { C7 = 0, PC2, PC7, SNB_CSTATE_COUNT, TSC = 0xFFFF };
+
+static int snb_get_count_percent(unsigned int self_id, double *percent,
+                                unsigned int cpu);
+
+static cstate_t snb_cstates[SNB_CSTATE_COUNT] = {
+       {
+               .name                   = "C7",
+               .desc                   = N_("Processor Core C7"),
+               .id                     = C7,
+               .range                  = RANGE_CORE,
+               .get_count_percent      = snb_get_count_percent,
+       },
+       {
+               .name                   = "PC2",
+               .desc                   = N_("Processor Package C2"),
+               .id                     = PC2,
+               .range                  = RANGE_PACKAGE,
+               .get_count_percent      = snb_get_count_percent,
+       },
+       {
+               .name                   = "PC7",
+               .desc                   = N_("Processor Package C7"),
+               .id                     = PC7,
+               .range                  = RANGE_PACKAGE,
+               .get_count_percent      = snb_get_count_percent,
+       },
+};
+
+static unsigned long long tsc_at_measure_start;
+static unsigned long long tsc_at_measure_end;
+static unsigned long long *previous_count[SNB_CSTATE_COUNT];
+static unsigned long long *current_count[SNB_CSTATE_COUNT];
+/* valid flag for all CPUs. If a MSR read failed it will be zero */
+static int *is_valid;
+
+static int snb_get_count(enum intel_snb_id id, unsigned long long *val,
+                       unsigned int cpu)
+{
+       int msr;
+
+       switch (id) {
+       case C7:
+               msr = MSR_CORE_C7_RESIDENCY;
+               break;
+       case PC2:
+               msr = MSR_PKG_C2_RESIDENCY;
+               break;
+       case PC7:
+               msr = MSR_PKG_C7_RESIDENCY;
+               break;
+       case TSC:
+               msr = MSR_TSC;
+               break;
+       default:
+               return -1;
+       };
+       if (read_msr(cpu, msr, val))
+               return -1;
+       return 0;
+}
+
+static int snb_get_count_percent(unsigned int id, double *percent,
+                                unsigned int cpu)
+{
+       *percent = 0.0;
+
+       if (!is_valid[cpu])
+               return -1;
+
+       *percent = (100.0 *
+               (current_count[id][cpu] - previous_count[id][cpu])) /
+               (tsc_at_measure_end - tsc_at_measure_start);
+
+       dprint("%s: previous: %llu - current: %llu - (%u)\n",
+               snb_cstates[id].name, previous_count[id][cpu],
+               current_count[id][cpu], cpu);
+
+       dprint("%s: tsc_diff: %llu - count_diff: %llu - percent: %2.f (%u)\n",
+              snb_cstates[id].name,
+              (unsigned long long) tsc_at_measure_end - tsc_at_measure_start,
+              current_count[id][cpu] - previous_count[id][cpu],
+              *percent, cpu);
+
+       return 0;
+}
+
+static int snb_start(void)
+{
+       int num, cpu;
+       unsigned long long val;
+
+       for (num = 0; num < SNB_CSTATE_COUNT; num++) {
+               for (cpu = 0; cpu < cpu_count; cpu++) {
+                       snb_get_count(num, &val, cpu);
+                       previous_count[num][cpu] = val;
+               }
+       }
+       snb_get_count(TSC, &tsc_at_measure_start, 0);
+       return 0;
+}
+
+static int snb_stop(void)
+{
+       unsigned long long val;
+       int num, cpu;
+
+       snb_get_count(TSC, &tsc_at_measure_end, 0);
+
+       for (num = 0; num < SNB_CSTATE_COUNT; num++) {
+               for (cpu = 0; cpu < cpu_count; cpu++) {
+                       is_valid[cpu] = !snb_get_count(num, &val, cpu);
+                       current_count[num][cpu] = val;
+               }
+       }
+       return 0;
+}
+
+struct cpuidle_monitor intel_snb_monitor;
+
+static struct cpuidle_monitor *snb_register(void)
+{
+       int num;
+
+       if (cpupower_cpu_info.vendor != X86_VENDOR_INTEL
+           || cpupower_cpu_info.family != 6)
+               return NULL;
+
+       if (cpupower_cpu_info.model != 0x2A
+           && cpupower_cpu_info.model != 0x2D)
+               return NULL;
+
+       is_valid = calloc(cpu_count, sizeof(int));
+       for (num = 0; num < SNB_CSTATE_COUNT; num++) {
+               previous_count[num] = calloc(cpu_count,
+                                       sizeof(unsigned long long));
+               current_count[num]  = calloc(cpu_count,
+                                       sizeof(unsigned long long));
+       }
+       intel_snb_monitor.name_len = strlen(intel_snb_monitor.name);
+       return &intel_snb_monitor;
+}
+
+void snb_unregister(void)
+{
+       int num;
+       free(is_valid);
+       for (num = 0; num < SNB_CSTATE_COUNT; num++) {
+               free(previous_count[num]);
+               free(current_count[num]);
+       }
+}
+
+struct cpuidle_monitor intel_snb_monitor = {
+       .name                   = "SandyBridge",
+       .hw_states              = snb_cstates,
+       .hw_states_num          = SNB_CSTATE_COUNT,
+       .start                  = snb_start,
+       .stop                   = snb_stop,
+       .do_register            = snb_register,
+       .unregister             = snb_unregister,
+       .needs_root             = 1,
+       .overflow_s             = 922000000 /* 922337203 seconds TSC overflow
+                                              at 20GHz */
+};
+#endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/version-gen.sh b/tools/power/cpupower/utils/version-gen.sh
new file mode 100755 (executable)
index 0000000..5ec41c5
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# Script which prints out the version to use for building cpupowerutils.
+# Must be called from tools/power/cpupower/
+# 
+# Heavily based on tools/perf/util/PERF-VERSION-GEN .
+
+LF='
+'
+
+# First check if there is a .git to get the version from git describe
+# otherwise try to get the version from the kernel makefile
+if test -d ../../../.git -o -f ../../../.git &&
+       VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
+       case "$VN" in
+       *$LF*) (exit 1) ;;
+       v[0-9]*)
+               git update-index -q --refresh
+               test -z "$(git diff-index --name-only HEAD --)" ||
+               VN="$VN-dirty" ;;
+       esac
+then
+       VN=$(echo "$VN" | sed -e 's/-/./g');
+else
+       eval $(grep '^VERSION[[:space:]]*=' ../../../Makefile|tr -d ' ')
+       eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../../Makefile|tr -d ' ')
+       eval $(grep '^SUBLEVEL[[:space:]]*=' ../../../Makefile|tr -d ' ')
+       eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../../Makefile|tr -d ' ')
+
+       VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}"
+fi
+
+VN=$(expr "$VN" : v*'\(.*\)')
+
+echo $VN
index 6d8ef4a..8b2d37b 100644 (file)
@@ -128,34 +128,34 @@ unsigned long long get_msr(int cpu, off_t offset)
 void print_header(void)
 {
        if (show_pkg)
-               fprintf(stderr, "pk");
+               fprintf(stderr, "pk");
        if (show_core)
-               fprintf(stderr, "core");
+               fprintf(stderr, " cr");
        if (show_cpu)
                fprintf(stderr, " CPU");
        if (do_nhm_cstates)
-               fprintf(stderr, "   %%c0 ");
+               fprintf(stderr, "    %%c0 ");
        if (has_aperf)
-               fprintf(stderr, "  GHz");
+               fprintf(stderr, " GHz");
        fprintf(stderr, "  TSC");
        if (do_nhm_cstates)
-               fprintf(stderr, "   %%c1 ");
+               fprintf(stderr, "    %%c1");
        if (do_nhm_cstates)
-               fprintf(stderr, "   %%c3 ");
+               fprintf(stderr, "    %%c3");
        if (do_nhm_cstates)
-               fprintf(stderr, "   %%c6 ");
+               fprintf(stderr, "    %%c6");
        if (do_snb_cstates)
-               fprintf(stderr, "   %%c7 ");
+               fprintf(stderr, "    %%c7");
        if (do_snb_cstates)
-               fprintf(stderr, "  %%pc2 ");
+               fprintf(stderr, "  %%pc2");
        if (do_nhm_cstates)
-               fprintf(stderr, "  %%pc3 ");
+               fprintf(stderr, "  %%pc3");
        if (do_nhm_cstates)
-               fprintf(stderr, "  %%pc6 ");
+               fprintf(stderr, "  %%pc6");
        if (do_snb_cstates)
-               fprintf(stderr, "  %%pc7 ");
+               fprintf(stderr, "  %%pc7");
        if (extra_msr_offset)
-               fprintf(stderr, "       MSR 0x%x ", extra_msr_offset);
+               fprintf(stderr, "        MSR 0x%x ", extra_msr_offset);
 
        putc('\n', stderr);
 }
@@ -194,14 +194,14 @@ void print_cnt(struct counters *p)
        /* topology columns, print blanks on 1st (average) line */
        if (p == cnt_average) {
                if (show_pkg)
-                       fprintf(stderr, "    ");
+                       fprintf(stderr, " ");
                if (show_core)
                        fprintf(stderr, "    ");
                if (show_cpu)
                        fprintf(stderr, "    ");
        } else {
                if (show_pkg)
-                       fprintf(stderr, "%4d", p->pkg);
+                       fprintf(stderr, "%d", p->pkg);
                if (show_core)
                        fprintf(stderr, "%4d", p->core);
                if (show_cpu)
@@ -241,22 +241,22 @@ void print_cnt(struct counters *p)
                if (!skip_c1)
                        fprintf(stderr, "%7.2f", 100.0 * p->c1/p->tsc);
                else
-                       fprintf(stderr, "   ****");
+                       fprintf(stderr, "  ****");
        }
        if (do_nhm_cstates)
-               fprintf(stderr, "%7.2f", 100.0 * p->c3/p->tsc);
+               fprintf(stderr, " %6.2f", 100.0 * p->c3/p->tsc);
        if (do_nhm_cstates)
-               fprintf(stderr, "%7.2f", 100.0 * p->c6/p->tsc);
+               fprintf(stderr, " %6.2f", 100.0 * p->c6/p->tsc);
        if (do_snb_cstates)
-               fprintf(stderr, "%7.2f", 100.0 * p->c7/p->tsc);
+               fprintf(stderr, " %6.2f", 100.0 * p->c7/p->tsc);
        if (do_snb_cstates)
-               fprintf(stderr, "%7.2f", 100.0 * p->pc2/p->tsc);
+               fprintf(stderr, " %5.2f", 100.0 * p->pc2/p->tsc);
        if (do_nhm_cstates)
-               fprintf(stderr, "%7.2f", 100.0 * p->pc3/p->tsc);
+               fprintf(stderr, " %5.2f", 100.0 * p->pc3/p->tsc);
        if (do_nhm_cstates)
-               fprintf(stderr, "%7.2f", 100.0 * p->pc6/p->tsc);
+               fprintf(stderr, " %5.2f", 100.0 * p->pc6/p->tsc);
        if (do_snb_cstates)
-               fprintf(stderr, "%7.2f", 100.0 * p->pc7/p->tsc);
+               fprintf(stderr, " %5.2f", 100.0 * p->pc7/p->tsc);
        if (extra_msr_offset)
                fprintf(stderr, "  0x%016llx", p->extra_msr);
        putc('\n', stderr);
index 2618ef2..33c5c7e 100644 (file)
@@ -137,7 +137,6 @@ void cmdline(int argc, char **argv)
 void validate_cpuid(void)
 {
        unsigned int eax, ebx, ecx, edx, max_level;
-       char brand[16];
        unsigned int fms, family, model, stepping;
 
        eax = ebx = ecx = edx = 0;
@@ -160,8 +159,8 @@ void validate_cpuid(void)
                model += ((fms >> 16) & 0xf) << 4;
 
        if (verbose > 1)
-               printf("CPUID %s %d levels family:model:stepping "
-                       "0x%x:%x:%x (%d:%d:%d)\n", brand, max_level,
+               printf("CPUID %d levels family:model:stepping "
+                       "0x%x:%x:%x (%d:%d:%d)\n", max_level,
                        family, model, stepping, family, model, stepping);
 
        if (!(edx & (1 << 5))) {
index 516551c..868cc93 100644 (file)
@@ -2,8 +2,9 @@
  * Slabinfo: Tool to get reports about slabs
  *
  * (C) 2007 sgi, Christoph Lameter
+ * (C) 2011 Linux Foundation, Christoph Lameter
  *
- * Compile by:
+ * Compile with:
  *
  * gcc -o slabinfo slabinfo.c
  */
@@ -39,6 +40,8 @@ struct slabinfo {
        unsigned long cpuslab_flush, deactivate_full, deactivate_empty;
        unsigned long deactivate_to_head, deactivate_to_tail;
        unsigned long deactivate_remote_frees, order_fallback;
+       unsigned long cmpxchg_double_cpu_fail, cmpxchg_double_fail;
+       unsigned long alloc_node_mismatch, deactivate_bypass;
        int numa[MAX_NODES];
        int numa_partial[MAX_NODES];
 } slabinfo[MAX_SLABS];
@@ -99,7 +102,7 @@ static void fatal(const char *x, ...)
 
 static void usage(void)
 {
-       printf("slabinfo 5/7/2007. (c) 2007 sgi.\n\n"
+       printf("slabinfo 4/15/2011. (c) 2007 sgi/(c) 2011 Linux Foundation.\n\n"
                "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
                "-a|--aliases           Show aliases\n"
                "-A|--activity          Most active slabs first\n"
@@ -293,7 +296,7 @@ int line = 0;
 static void first_line(void)
 {
        if (show_activity)
-               printf("Name                   Objects      Alloc       Free   %%Fast Fallb O\n");
+               printf("Name                   Objects      Alloc       Free   %%Fast Fallb O CmpX   UL\n");
        else
                printf("Name                   Objects Objsize    Space "
                        "Slabs/Part/Cpu  O/S O %%Fr %%Ef Flg\n");
@@ -379,14 +382,14 @@ static void show_tracking(struct slabinfo *s)
        printf("\n%s: Kernel object allocation\n", s->name);
        printf("-----------------------------------------------------------------------\n");
        if (read_slab_obj(s, "alloc_calls"))
-               printf(buffer);
+               printf("%s", buffer);
        else
                printf("No Data\n");
 
        printf("\n%s: Kernel object freeing\n", s->name);
        printf("------------------------------------------------------------------------\n");
        if (read_slab_obj(s, "free_calls"))
-               printf(buffer);
+               printf("%s", buffer);
        else
                printf("No Data\n");
 
@@ -400,7 +403,7 @@ static void ops(struct slabinfo *s)
        if (read_slab_obj(s, "ops")) {
                printf("\n%s: kmem_cache operations\n", s->name);
                printf("--------------------------------------------\n");
-               printf(buffer);
+               printf("%s", buffer);
        } else
                printf("\n%s has no kmem_cache operations\n", s->name);
 }
@@ -462,19 +465,32 @@ static void slab_stats(struct slabinfo *s)
        if (s->cpuslab_flush)
                printf("Flushes %8lu\n", s->cpuslab_flush);
 
-       if (s->alloc_refill)
-               printf("Refill %8lu\n", s->alloc_refill);
-
        total = s->deactivate_full + s->deactivate_empty +
-                       s->deactivate_to_head + s->deactivate_to_tail;
-
-       if (total)
-               printf("Deactivate Full=%lu(%lu%%) Empty=%lu(%lu%%) "
-                       "ToHead=%lu(%lu%%) ToTail=%lu(%lu%%)\n",
-                       s->deactivate_full, (s->deactivate_full * 100) / total,
-                       s->deactivate_empty, (s->deactivate_empty * 100) / total,
-                       s->deactivate_to_head, (s->deactivate_to_head * 100) / total,
+                       s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass;
+
+       if (total) {
+               printf("\nSlab Deactivation             Ocurrences  %%\n");
+               printf("-------------------------------------------------\n");
+               printf("Slab full                     %7lu  %3lu%%\n",
+                       s->deactivate_full, (s->deactivate_full * 100) / total);
+               printf("Slab empty                    %7lu  %3lu%%\n",
+                       s->deactivate_empty, (s->deactivate_empty * 100) / total);
+               printf("Moved to head of partial list %7lu  %3lu%%\n",
+                       s->deactivate_to_head, (s->deactivate_to_head * 100) / total);
+               printf("Moved to tail of partial list %7lu  %3lu%%\n",
                        s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total);
+               printf("Deactivation bypass           %7lu  %3lu%%\n",
+                       s->deactivate_bypass, (s->deactivate_bypass * 100) / total);
+               printf("Refilled from foreign frees   %7lu  %3lu%%\n",
+                       s->alloc_refill, (s->alloc_refill * 100) / total);
+               printf("Node mismatch                 %7lu  %3lu%%\n",
+                       s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total);
+       }
+
+       if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail)
+               printf("\nCmpxchg_double Looping\n------------------------\n");
+               printf("Locked Cmpxchg Double redos   %lu\nUnlocked Cmpxchg Double redos %lu\n",
+                       s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail);
 }
 
 static void report(struct slabinfo *s)
@@ -573,12 +589,13 @@ static void slabcache(struct slabinfo *s)
                total_alloc = s->alloc_fastpath + s->alloc_slowpath;
                total_free = s->free_fastpath + s->free_slowpath;
 
-               printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d\n",
+               printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d %4ld %4ld\n",
                        s->name, s->objects,
                        total_alloc, total_free,
                        total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0,
                        total_free ? (s->free_fastpath * 100 / total_free) : 0,
-                       s->order_fallback, s->order);
+                       s->order_fallback, s->order, s->cmpxchg_double_fail,
+                       s->cmpxchg_double_cpu_fail);
        }
        else
                printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",
@@ -1190,6 +1207,10 @@ static void read_slab_dir(void)
                        slab->deactivate_to_tail = get_obj("deactivate_to_tail");
                        slab->deactivate_remote_frees = get_obj("deactivate_remote_frees");
                        slab->order_fallback = get_obj("order_fallback");
+                       slab->cmpxchg_double_cpu_fail = get_obj("cmpxchg_double_cpu_fail");
+                       slab->cmpxchg_double_fail = get_obj("cmpxchg_double_fail");
+                       slab->alloc_node_mismatch = get_obj("alloc_node_mismatch");
+                       slab->deactivate_bypass = get_obj("deactivate_bypass");
                        chdir("..");
                        if (slab->name[0] == ':')
                                alias_targets++;